Leaderboard
Popular Content
Showing content with the highest reputation on 04/16/2022 in all areas
-
I think a better way is to skip the Add Page step and then make sure the title is always automatically derived from your two fields when they are populated. There are a few steps involved, illustrated here with case that is different to yours but you can see the similarity. In this example the template of the parent page that new pages are added under is named "creatures", and the child template (where the title is being set automatically) is named "creature". 1. For the "creatures" template, make sure that it allows a single template for children: the "creature" template. 2. For the "creatures" template, in the "Name format for children" setting enter "Y/m/d H:i:s". This will allow the "Add Page" step to be skipped and will automatically set the page name to the current date and time. We will later change the name in a hook. 3. Optional but recommended: for the "creature" template, choose the "creatures" template as "Allowed template(s) for parent". This lets you quickly add child pages via Pages > Add New and also ensures that new pages can't be added in the wrong place. 4. For the "creature" template, edit the Title field in the template context and set the visibility to "Open when populated + Closed when blank + Locked (not editable)". The title is going to be set automatically so editors should not be able to change it manually. 5. Add hooks like the ones below to /site/ready.php. // Pages::added $pages->addHookAfter('added', function(HookEvent $event) { /** @var Page $page */ $page = $event->arguments(0); // Creature if($page->template == 'creature') { // This is a newly added page so the fields that make up the title won't be populated yet $page->setAndSave('title', 'New creature'); } }); // Pages::saveReady $pages->addHookAfter('saveReady', function(HookEvent $event) { /** @var Page $page */ $page = $event->arguments(0); /** @var Pages $pages */ $pages = $event->object; // Creature if($page->template == 'creature') { // Return early if the page is in the trash (thanks @taotoo) if($page->isTrash) return; // If the fields that make up the title are populated if($page->colour->id && $page->animal->id) { // Set the title $page->title = "{$page->colour->title} {$page->animal->title}"; // Sanitize the title as a page name $name = $event->wire()->sanitizer->pageName($page->title, true); // Set the page name while making sure it auto-increments if there is a sibling page with the same title $page->name = $pages->names()->uniquePageName($name, $page); } } }); Result:3 points
-
Hey, @Aleksey Popov! First of all you need to create a field to store page views data, and collect the actual data with a script. And then just use sorting in selector. Look at this topic or at this module.2 points
-
I'm trying to understand the basics of module development in PW. I'm quite confused with the structure of it. what I put figured out so far… the object class "Process" is going to be applied as a "process" to the admin page and attach to the top menu of the admin panel. The function __execute is what puts content on this page. Here's my first question: How can I add input fields for content to be added to the database? then you have the module itself that will appear in the modules tab (and page tree under admin but hidden). There I can add input fields via the class ModuleConfig and the function __construct am I right? but also, you can navigate to the modules section, overview of all site and core modules (and uninstalled ones and new ones) where you can see another "settings" button which doesn't appear on the module's detail page. (a bit weird, isn't it?) anyways, long story short, I'm quite confused about the different classes and which one I should actually use when building a module and how to know. I might add that I'm not a php expert, though I have built a bunch of websites with some rather complex templates in PW already, I still haven't touched any of this stuff. Maybe it's still some of my lack of understanding of php (also need to learn about the difference of implements and extends for example) but I feel that these PW classes are somewhat arbitrary. So is there a way to get more clarity on that?1 point
-
ProcessWire 3.0.198 contains a mixture of new features and issue resolutions. Below are details on a few of the new features: Support was added for runtime page cache groups. This enables pages to be cached as a group—and just as importantly—uncached as a group. While it can be used by anybody, it was added primarily to add efficiency to $pages->findMany(), so that it can cache supporting pages (like parents and page references). Previously, it would have to load a fresh copy of each supporting page used by findMany() results (for every returned page) since findMany() used no in-memory caching. If it did cache in memory, then you could potentially run out of memory on large result sets, so that strategy was avoided. Consider the case of iterating over all pages returned by findMany() and outputting their URLs... that triggers load of all parent pages for each page in the result set. And without a memory cache, it meant it would have to do it for each page in the results. Following this week's updates, now it can cache these supporting pages for each chunk of 250 pages, offering potentially significant performance improvement in many cases, without creating excess memory usage or memory leaks. When the chunk of 250 result pages is released from memory (to make room for the next chunk), all the supporting pages (parents, page references, etc.) are also released from memory, but not before. Now findMany() can offer both memory efficiency and great performance. For as long as I can remember, ProcessWire has had an apparently undocumented feature for dependent select fields that enables you to have two page reference fields using selects (single, multiple or AsmSelect) where the selected value in one select changes the selectable options in the other select (Ajax powered). Think of "categories" and "subcategories" selects, for example, where your selection for "categories" changes what options are selectable in "subcategories". Part of the reason it's undocumented is that it is one of those features that is a little bit fragile, and didn't work in some instances, such as within Repeater items. That changed this week, as the feature has been updated so that it can also work in Repeater items too. The $pages->findRaw() method was updated with a new "nulls" option (per Adrian's request in #1553). If you enable this new "nulls" option, it will add placeholders in the return value with null values for any fields you requested that were not present on each matching page. This reflects how PW's database works, in that if a field has no value, PW removes it from the database entirely. Without the nulls option (the existing behavior), it retains the more compact return values, which omit non present values completely. For example, consider the following: $items = $pages->findRaw("template=user, fields=email|first_name|last_name"); If a row in the result set had no "first_name" or "last_name" populated, then it would not appear in the that row of the return value at all... [ "email": "ryan@processwire.com" ] By specifying the "nulls" option, it will still include placeholders for field values not present in the database, and these will have a value of null: $items = $pages->findRaw("template=user, nulls=1, fields=email|first_name|last_name"); [ "email": "ryan@processwire.com", "first_name": null, "last_name": null ] By the way, if you don't specify which fields you want to get (which is the same as saying "get all") then adding the nulls option makes it provide placeholders for all fields used by the page's template. As you might expect, without the nulls option, it includes only populated fields. Also included in 3.0.198 are 7 issue fixes, most of which are visible in the dev branch commits log. That's all for this week. Thanks for reading this update and have a great weekend!1 point
-
Some of your questions will be answered by reading through the articles listed at https://processwire.com/docs/modules/, particularly the first three. Also really helpful are the Hello World example modules described in the blog post https://processwire.com/blog/posts/pw-3.0.181-hello/. And another excellent post is https://processwire.com/blog/posts/building-custom-admin-pages-with-process-modules/. These will probably give you enough to start building useful modules. And I'd suggest that building a module or two (especially by following examples) would be the best way to get started, working things out as needed.1 point
-
There is no built-in functionality. The simplest way is to create addtional fields like 'page_views' and 'page_popularity', then populate these fields inthe desirerable way and use them in your selectors like pages('template=post, sort=-page_views');1 point
-
Why just not create a text field like 'externa_id' and then check it while import like foreach ($import_records as $import_record) { $exists = $this->wire()->pages->has("template=some-template, external_id=" . $import_record['unique_id']); if($exists) { // update } else { // create a new page } }1 point
-
Hi @swissdoode . Take a look at Inputfields.js file, there are many methods that you could find helpfull https://github.com/processwire/processwire/blob/dev/wire/templates-admin/scripts/inputfields.js#L371 point
-
1 point
-
1 point
-
Same for Outlook, Yandex, Zoho and everything that needs either an "App password" or 2FA (2 Factor Auth). Another thing: sometimes it's necessary to use different ports (for whatever reason) so it's either 465, 587, or even 2525. Just double-check here.1 point
-
I don't think that will work because the page will also be saved immediately after it is created and so the hook would just delete it before it can be edited. I suggest you just clean up abandoned pages on a regular shedule using LazyCron. First install the module at Modules > Install > LazyCron. Then add a hook like this to /site/ready.php: // Once per day $wire->addHook('LazyCron::everyDay', function(HookEvent $event) { // Find pages that appear to be abandoned because they still have the default title 24 hours after creation $time = strtotime('-24 hours'); $abandoned_pages = $event->wire()->pages->find("template=your_template, title='New Owner', created>$time, include=all"); // Trash the abandoned pages foreach($abandoned_pages as $abandoned_page) { $abandoned_page->trash(); } }); You could delete the pages if you like but maybe safer to trash them and then just empty the trash once in a while.1 point
-
ProcessWire LazyCron Module This core module provides hooks that are automatically executed at various intervals. It is called 'lazy' because it's triggered by a pageview, so the interval is guaranteed to be at least the time requested (and maybe more) rather than exactly the time requested. The more pageviews your site gets, the closer it is. This is fine for most cases, but if you need it to be fully accurate I'll describe how you can make it not-lazy a little further down. How to download and install This was built as a core module for ProcessWire 2.1 (development version), so you need to grab the latest commit of the development version and you will have the module. This module is not compatible with PW 2.0 (stable version). ProcessWire 2.1 is at: https://github.com/ryancramerdesign/P21 If you already have the latest commit of ProcessWire 2.1, go to your modules menu, click "check for new modules" at the bottom, and then click the "install" button for the LazyCron module. LazyCron is now installed and ready to be used by other modules or via the API. Hookable time intervals These are the function names you can hook from LazyCron. The function names describe the time intervals they provide. If you think I'm missing any important time intervals, please let me know and I can add more. every30Seconds everyMinute every2Minutes every3Minutes every4Minutes every5Minutes every10Minutes every15Minutes every30Minutes every45Minutes everyHour every2Hours every4Hours every6Hours every12Hours everyDay every2Days every4Days everyWeek every2Weeks every4Weeks How to use it This module is mainly of use inside the API and to other modules. You hook one of the named intervals mentioned in the list above, and the function you provide will be executed at approximately that time interval. Here's how you do it, both from a class (module) and outside of one: Usage in a class/module <?php // initialize the hook in your AutoLoad module public function init() { $this->addHook('LazyCron::every30Minutes', $this, 'myFunc'); } // the function you want executed every 30 minutes public function myFunc(HookEvent $e) { echo "30 Minutes have passed!"; } Procedural usage (like in a template or elsewhere in the API): <?php // create your hook function function myHook(HookEvent $e) { echo "30 Minutes have passed!"; } // add a hook to your function: wire()->addHook('LazyCron::every30Minutes', null, 'myFunc'); Arguments provided to the hooks If desired, you can retrieve the number of seconds that have actually elapsed since your hooked function was last called: <?php function myHook(HookEvent $e) { $seconds = $e->arguments[0]; echo "30 Minutes have passed! (actual seconds were: $seconds)"; } Note that in production usage, you probably wouldn't want to echo anything from these hooks because they are executed after the pageview was already delivered. So while you can directly echo output from these, it's probably not that useful (other than for demonstration purposes, like this). How it works When installed, LazyCron hooks into ProcessWire's ProcessPageView::finished() method. This ensures that the scheduled tasks are executed after the pageview has already been delivered rather than before or during it. This hopefully avoids any perceived slowdown if the scheduled tasks take time. LazyCron provides a bunch of hooks that anything else can hook into. These functions are outlined in the section above titled "Hookable time intervals." These functions are called at the interval specified in their name. LazyCron simply uses ProcessWire's existing hook system. So when you hook into any one of these functions, your hook will also be executed at that same time interval. LazyCron hooks are only executed during pageviews that are delivered by ProcessWire. They are not executed when using ProcessWire's API from other scripts. How to make it not-lazy In most cases, the way that LazyCron works out of the box is just fine. But if your need requires assurance that the module will always execute at exactly the interval you need (rather than possibly later), you need to setup a real cron job to trigger a pageview in your site. So if you needed accuracy to 1 minute, you'd setup a cron job to execute every one minute, and pull a page from the site. There are any number of ways you could pull a page from your site, but here is one using wget: wget --quiet --no-cache -O - http://www.your-site.com > /dev/null That command basically says to pull a page from the site, don't tell us anything, don't cache the request, and discard any output.1 point
-
Since I recognized a remarkable overflow of my trash bin I made a small module which auto delete pages sustainably from the trash after a period which can be set in module settings. PW modules: http://modules.processwire.com/modules/cronjob-empty-trash/ Github: https://github.com/kixe/CronjobEmptyTrash1 point