Jump to content

gebeer

Members
  • Posts

    1,394
  • Joined

  • Last visited

  • Days Won

    39

Everything posted by gebeer

  1. can confirm same behaviour. Disabling TracyDebugger helps. Fatal error: Exception: Unable to obtain lock for session (retry in 30s) (in xxx/wire/modules/Session/SessionHandlerDB/SessionHandlerDB.module line 96) #0 [internal function]: ProcessWire\SessionHandlerDB->read('836ab08de536179...') #1 xxx/wire/core/Session.php(327): session_start(Array) #2 xxx/wire/core/Wire.php(413): ProcessWire\Session->___init() #3 xxx/wire/core/WireHooks.php(952): ProcessWire\Wire->_callMethod('___init', Array) #4 xxx/wire/core/Wire.php(484): ProcessWire\WireHooks->runHooks(Object(ProcessWire\Session), 'init', Array) #5 xxx/wire/core/Session.php(205): ProcessWire\Wire->__call('init', Array) #6 xxx/wire/core/ProcessWire.php(581): ProcessWire\Session->__construct(Object(ProcessWire\ProcessWire)) #7 xxx/wire/core/ProcessWire.php(315): ProcessWire\ProcessWire->load(Object(ProcessWire\Config)) #8 xxx/index.php(52): ProcessWire\ProcessWire->__construct(Object(ProcessWire\Config)) #9 {main} in xxx/index.php on line 64
  2. @flydev wow, that is really impressive. I am far below your knowledge level atm. Thanks very much for sharing those links. Will certainly help me to brush up my knowledge. That idea about the forum chatbot is great. But that would be quite a lot of info to ingest. for large data sets like these, would you use pinecone or weaviate or other solutions?
  3. That prompt is pretty amazing. I gave it the task: It did a quite good job without me having to iterate manually over the results (not tested): <?php class ErrorInterceptor extends WireData implements Module { public static function getModuleInfo() { return array( 'title' => 'Error Interceptor', 'version' => 1, 'summary' => 'Intercepts all warnings, errors, exceptions, and fatal errors, adds a backtrace, unifies the message, and logs it using the ProcessWire log API.', 'autoload' => true, 'singular' => true, ); } public function init() { set_error_handler(array($this, 'errorHandler')); set_exception_handler(array($this, 'exceptionHandler')); register_shutdown_function(array($this, 'shutdownFunction')); } public function errorHandler($errno, $errstr, $errfile, $errline) { $backtrace = debug_backtrace(); $unifiedMessage = $this->unifyMessage('Error', $errno, $errstr, $errfile, $errline, $backtrace); $this->logError($unifiedMessage); } public function exceptionHandler($exception) { $errno = $exception->getCode(); $errstr = $exception->getMessage(); $errfile = $exception->getFile(); $errline = $exception->getLine(); $backtrace = $exception->getTrace(); $unifiedMessage = $this->unifyMessage('Exception', $errno, $errstr, $errfile, $errline, $backtrace); $this->logError($unifiedMessage); } public function shutdownFunction() { $error = error_get_last(); if ($error !== null) { $errno = $error['type']; $errstr = $error['message']; $errfile = $error['file']; $errline = $error['line']; $backtrace = debug_backtrace(); $unifiedMessage = $this->unifyMessage('Fatal Error', $errno, $errstr, $errfile, $errline, $backtrace); $this->logError($unifiedMessage); } } private function unifyMessage($errorType, $errno, $errstr, $errfile, $errline, $backtrace) { $unifiedMessage = array( 'type' => $errorType, 'code' => $errno, 'message' => $errstr, 'file' => $errfile, 'line' => $errline, 'backtrace' => $backtrace ); return json_encode($unifiedMessage, JSON_PRETTY_PRINT); } private function logError($unifiedMessage) { $log = $this->wire('log'); $log->save('ErrorInterceptor', $unifiedMessage); } } Instead of using it on flowgpt.com, I put it in my locally hosted chatbot-ui. I installed it from https://github.com/jorge-menjivar/chatbot-ui which is a fork of the original https://github.com/mckaywrigley/chatbot-ui with some more features and bugfixes. I run it as a docker container locally. This ui is great because it lets you save and manage your prompts (and system prompts). It offers prompt variables, so I took that long prompt, added a variable where you are supposed to put in your project details and now I can use this prompt very conveniently. It also letz you export/import conversations, search the web etc. More info and some demos of the tool: twitter.com/chatbotui Interesting. Do you finetune existing models or use tools like langchain to create bots with custom context? I am experimenting with the latter and got some pretty good results so far. This is in the early stages but looks promising. I am building a vector db (chromadb) with embeddings for the complete core codebase of PW and then query that db to give context to a chatbot so it can answer coding questions on PW more specifically. ATM I only gave it the contents of the wire/core folder which is already 250MB in the vector db. The answers I'm getting out of it so far are quite good. The challenge here lies in optimizing the text splitter and creating the embeddings in a way targeting the LLM you are going to use for the chat. Ultimate goal is to have this running locally without proprietary LLMs like chatGPT. https://github.com/imartinez/privateGPT is a great project that can help with that. Open source models are getting better and better. So I hope in the not so distant future we can have our local coding assistants.
  4. with this code you are setting the template of the page to 'myTemplate'. You need to use == or === as a comparison operator if(($page->template == "myTemplate") EDIT: don't worry, we've all been there πŸ™‚
  5. Have you been able to solve this? I had the very same issue some time ago. In my case it was related to the machine I was working on. It only happened on my notebook. On the desktop everything was fine. I never went to investigate this deeper because at that time I happened to do an OS reinstall (Linux) on my notebook. I suspect though that it might had something to do with the local time on my notebook OS not being correct or something along those lines. What I used as a temp workaround is to force login with my superuser account in _main.php or home.php (can't remember exactly) so I was able to work on the site locally. $session->forceLogin('superusername');
  6. Hi all, I read through https://www.php.net/manual/en/language.namespaces.basics.php, https://www.php.net/manual/en/language.namespaces.rules.php and @MoritzLostvery nice writup here: Been using PW classloader and namespacing for quite a while. Now for the first time I run into problems. On the local and remote dev environments everything is working as expected. Now moving the site to staging for the first time, I get an E\error Trait not found (see below for exact error in context). Here's my setup all environments on PHP 8.1 with PW 3.0.208: site/modules/Site/Site.module.php public function __construct() { parent::__construct(); $this->wire->classLoader->addNamespace("Diff", __DIR__ . "/classes"); } site/modules/Site/classes/ResponsiveImages.php <?php namespace Diff; use ProcessWire\Pageimage; use ProcessWire\WireException; use function ProcessWire\wireInstanceOf; trait ResponsiveImages { /** * renders responsive picture tag for specific breakpoints/sizes * used for product description image, ... * @param PageImage $pageImage * @param bool $full optional, default false, if true, sizes attribute will be '100vw' * @return string picture markup */ public function renderImageFormat1($pageImage, $full = false) { ... site/classes/DefaultPage.php <?php namespace ProcessWire; use Diff\ResponsiveImages; #use RockMigrations\MagicPage; /** * Custom page class that provides properties/methods for all pages * * */ class DefaultPage extends Page { use ResponsiveImages; #use MagicPage; On the staging server this throws the error: Fatal Error: Trait "Diff\ResponsiveImages" not found if I change the first use statement to `use \Diff\ResponsiveImages;` the error is gone. In my understanding this doesn't make sense, because with the $wire->classloader the namespace 'Diff' is loaded inside the 'ProcessWire' namespace and not as a direct descendant of the root namespace '\'. Or am I wrong in my assumption? And if it is added to the root namespace as \Diff then it should throw errors in all environments? EDIT: I see from the ResponsiveImages.php that indeed my namspace Diff seems to live off root namespace. Otherwise my IDE wouldn't have added that namespace import statements for \ProcessWire\Pageimage etc I see in Moritz's example that he is defining his namespace explicitely under ProcessWire like 'ProcessWire\\TrelloWire' inside the classloader function. (I think the double backslash is not needed anymore, looking at https://github.com/processwire/processwire/blob/6ff498f503db118d5b6c190b35bd937b38b80a77/wire/core/WireClassLoader.php#L239 ff) What could be the reason for that server behaving in that way? Like I said, in other environments (and on other projects) that has never been an issue. And I see other modules setup in a similar fashion (like @bernhard's for example). That makes me think that there might be some server setting for that or some PHP module missing on that specific server?
  7. A little update. @teppowas spot on. Having my logic inside a hook to PageView::execute was not a good idea. I refactored it, put simple URL segment logic in home.php while keeping the processing of the segments inside a module. This makes life much easier because I can throw 404s and therefore have URL hooks working as they should. Thanks again everyone for your input on this. Very much appreciated.
  8. Very enlightening info. Thank you! I'm not going to be able to handle that in home.php. But given your info, I'll try to hook into ProcessPageView::pageNotFound instead and see how it goes.
  9. Thanks to everyone for your valuable input. Here are my findings after having tested this on a fairly virgin multilang install with root URL in default language redirected to /en/ through LanguageSupportPageNames setting and URL segements enabled on the home template. After putting in anything in the URL segment whiltelist, the URL hook works. And of course, like @bernhard suggested the regex option makes total sense. Great idea if you control behaviour from within the template file. And this also proofs that URL hooks are kicking in right befor showing the 404 page. I enabled all segments by leaving the whitelist empty. Then in my PageView::execute hook, that handles display of pages by URL segment, I am throwing a 404 with `throw new Wire404Exception();` This throws an Exception and doesn't show 404 or execute my URL hook. Seems like we can use wire404() or throw new Wire404Exception only in template files? My hook is triggered inside init() of an autoload module. My conclusion: if you have URL segments enabled on the home page and want a URL hook to execute, you need to have a whitelist for URL segments defined. Thanks again to everyone. Now if you can tell me how I can throw a 404 without getting an Exception in my autoload module, that would be awesome πŸ™‚
  10. Thank you. Actually I had already tried that but didn't mention it in my post. Unfortunately it didn't work in my scenario. I'll try to replicate it on a fairly blank multilang install and see how it goes. EDIT: what I also didn't mention is that in my multilang scenarion the homepage of the default language is redirected to /en/ through the setting in LanguageSupportPageNames.
  11. Hi, I've been using the URL hooks feature quite extensively since it has been introduced and generally this is working fine. Now I have a case where URL segments are activated for the home page because I need to rewrite some URLs for pages that live under a certain parent to make them live under home. Those pages have custom page paths modified through Page::path hooks. This is all working fine. But now I wanted to introduce a new route for outputting files through a URL hook $wire->addHook('/files/{filename}). And this hook never fires. Accessing URLs like /files/my-file.pdf leads to a 404. The reason seems to be that home template has URL segments enabled. As soon as I disable them, my URL hook is working. I can't find any mention of this in the URL hook or URL segments documentation. I tried higher hook priority on my URL hook so that it kicks in before my ProcessPageView::execute hook which handles the URL segments for the home page. Didn't work. I am assuming that before a 404 is thrown when none of the URL segments is handled, my URL hook would kick in. But obviously this is not the case. I know that I could add the logic for handling the files output inside my ProcessPageView::execute hook. But that one is quite complex already and for separation of concerns I'd rather prefer to have that logic in a separate hook. Anyways, I wanted to ask if someone has come across a similar situation or if any of you know that the observed behaviour (URL hooks not working when URL segments are active on home template) is to be expected.
  12. https://warp-design.co.uk/blog/why-we-love-processwire/ https://dotnetic.de/blog/processwire-the-best-cms
  13. @kongondo on multilang installs, when the title field is set to TextLanguage, MM pages that are creted for each image under Admin->Media Manager->Media Manager: image are published in the default language only. Other languages are disabled. This poses a problem with $pages->find operations, e.g. $this->wire->pages->findIDs("template=media-manager-image, image_gallery=1, products.id={$this->id}"); this return 0 pages for non-default languages. I had to change the selector to $this->wire->pages->findIDs("template=media-manager-image, image_gallery=1, products.id={$this->id}, include=all, status!=" . Page::statusUnpublished . ', status<' . Page::statusTrash); in order to get results. It might be good to have these pages published in all languages by default.
  14. In PW you would typically use https://processwire.com/docs/front-end/how-to-use-url-segments/ The docs should help you get started. If not, feel free to ask.
  15. Thanks for the suggestion. This is throwing all kinds of errors. If I want to bd($vars), I get: User Error Exception: Method RockMigrations::getModuleInfo does not exist or is not callable in this context (in /var/www/html/wire/core/Wire.php line 563) #0 /var/www/html/wire/core/Wire.php(419): ProcessWire\Wire->___callUnknown('getModuleInfo', Array) #1 /var/www/html/wire/core/WireHooks.php(952): ProcessWire\Wire->_callMethod('___callUnknown', Array) #2 /var/www/html/wire/core/Wire.php(484): ProcessWire\WireHooks->runHooks(Object(ProcessWire\RockMigrations), 'callUnknown', Array) #3 /var/www/html/wire/core/Wire.php(487): ProcessWire\Wire->__call('callUnknown', Array) #4 /var/www/html/site/modules/RockMigrations/RockMigrations.module.php(4560): ProcessWire\Wire->__call('getModuleInfo', Array) #5 /var/www/html/site/modules/TracyDebugger/tracy-2.9.x/src/Tracy/Dumper/Describer.php(295): ProcessWire\RockMigrations->__debugInfo() With print_r($vars) I get: Fatal Error __debuginfo() must return an array Related to RockMigrations::__debugInfo(). Seems like this method is interfering with print_r(). After uninstalling Tracy I finally got to outputting var_dump($vars). Still throwing a Warning about RockMigrations::__debugInfo(). $vars contains all defined vars including fuel which contains wire and so on. So this is not feasable for the simple purpose of passing on some vars. What I finally did, is putting all vars that I need to pass on into an array $arr, then passing $arr to the render file. In the render file I can retrieve it with $arr and pass it on. Sometimes solutions are so simple. But the other day it was getting late already. Braindead just around the corner πŸ™‚
  16. Thanks. I'm aware of that. But I'm looking for a way to get the $vars variable like it was sent to the render method so I can pass it on easily. Imagine you pass a $vars array with 10 items to render(). Then from the render file that you passed them to you want to take $vars and pass it on to another partial with the render() method. ATM you have to write each one out again in the new render() call. That is tedious and it would be much easier if we could just grab $vars and pass it on.
  17. I just tried this and $vars is still null inside the render file, even when sending $options. Also $options is null. I am using this to render files (views) inside a module. So the render files sit inside /site/modules/myModule/views. I am rendering those with $this->files->render('/full/path/to/viewFile', [...], []); Can't find anything in the docs on how to retrieve $vars here. I need to pass them on to another render file. With ReflectionMethod, we can get all the parameter names passed to $files->render(). But not the values passed to that instance of the method. $f = new ReflectionMethod(wire('files'), 'render'); bd($f->getParameters()); If anybody knows how to get $vars inside the render files, would be much appreciated πŸ™‚
  18. For all that are interested in testing, I have created a PHP7.4 compatible version at https://github.com/gebeer/RockMigrations/tree/repeatermatrix-php74 It just so happens that I needed it urgently on a live project where I couldn't change the PHP version in time πŸ™‚
  19. Sure. I'd like some other people test this before I make the PR.
  20. Hi, my current state of RepeaterMatrix (RM) integration is here: https://github.com/gebeer/RockMigrations/tree/repeatermatrix It is based off @bernhard's dev branch. I just merged the latest changes from dev into my repeatermatrix branch. I have basically done what Bernhard suggested and ported over the original RM methods from RockMigrations v1 and did some minor adjustments. You can create RM fields inside the $rm->migrate(['fields]) array like this: self::content_blocks => [ 'label' => 'Content Blocks', 'type' => 'FieldtypeRepeaterMatrix', 'repeaterTitle' => '#n: {title}', 'familyFriendly' => 1, 'repeaterDepth' => 0, 'tags' => 'repeatermatrix', 'repeaterAddLabel' => 'Add New Block', 'columnWidth' => 100, ], Note that I'm using class constants in my Site module for field names. You can of course use ordinary strings here. Alternatively you can create the field like this: $rmfContent = $rm->createField('content_blocks', 'FieldtypeRepeaterMatrix', ['label' => 'Content Blocks', 'tags' => 'content']); And then after the $rm->migrate() method you can define your RM types like this: $rm->setMatrixItems(self::content_blocks, [ 'test_rte' => [ 'label' => 'Test Repeater', 'fields' => [ self::title => [ 'label' => 'Title', 'required' => 0, ], self::images => [ 'label' => 'My Images', ], self::rte => [ 'label' => 'My Text', ], 'my_repeater' => [ 'label' => 'Test RTE in RepeaterMatrix', ], ] ], ]); As you can see, you can also have regular repeater fields inside RM types. Besides setMatrixItems() there are following RM related methods: setMatrixItem(), setMatrixItemData(), addMatrixItem(), removeMatrixItem() There is no way atm to have the full field definition inside the $rm->migrate() method as array definition. That is something that would need some extra work mainly because the getCode() method as is doesn't play nicely with RM fields. But other that that it seems to work pretty well. Actually I'm using it in a bigger project which is still in development and makes heavy use of RM fields with nested repeaters. I would be happy if you and others could test this. @gornycreative wanted to have a play with it some weeks ago. Don't know if he already had the time to look at it. Eagerly looking forward πŸ™‚ It is totally different from RepeaterMatrix but really great what I saw so far.
  21. Great Talk! And thanks for the mention πŸ™‚ Very well structured introduction to PW. I like the clean aesthetics. This surely will get some people interested in PW. Please everyone go and like/comment this on YT.
  22. I would use a Pages::published hook for that. Assuming that the "help request" is a single item (I'll call it job in my example) on your "job board" and that both users and jobs have a page reference field "interests" that links to the area of interests, you can attach that published hook and everytime a job is published, those emails will get send. Dummy code: wire()->addHookAfter('Pages::published', function(HookEvent $event) { $page = $event->arguments(0); if($page->template !== 'job') return; // build selector value for interests, e.g. 1234|3456|5678 $interests = implode('|', $page->interests->explode('id')); // get users who are interested in this job, assuming the template for users is 'applicant' $interestedUsers = wire('pages')->find("template=applicant, interests={$interests}"); // either send emails directly foreach ($interestedUsers as $u) { // logic for sending emails } // display send result status message wire()->message('Notifications sent', 'success'); // or create a page for job-notifications and redirect there }); Sending emails directly from this hook will take some time until the admin user gets a message displayed. So this might not be optimal. As an alternative you could create a job-notification page and redirect the admin there. On that page you can list the interests and intersted users and a sent status as well as a send/resend button and handle the sending there. With these separate notification pages available in the system you could build a custom Lister for an overview which makes it more convenient to interact with the notification system, see sent statuses etc.
  23. Great you solve it. Jut for explanation: if you hook after Pages::save and save the page again within that hook, this will cause an infinite loop as you already have observed. To avoid this you can either use a before hook like you did or take advantage of the the $page->save([options]) by using `$page->save(['noHooks' => true])`
  24. At the time of import of new pages you should use the same sanitizer that you use later for the exist check and assign the page name manually when creating. That should give you consistency.
Γ—
Γ—
  • Create New...