Jump to content

Robin S

Members
  • Posts

    4,791
  • Joined

  • Days Won

    303

Everything posted by Robin S

  1. The *= operator isn't the right one to use because it doesn't match partial strings at the start. If you use the %= operator I think it will work.
  2. Why is that? Why not create a copy of the template (Setup > Templates > Add New > Copy fields from another template) that has access control enabled and then edit the pages to use that template? And the template file can just consist of: include './your_other_template_file.php';
  3. You can set the base URL for MarkupPagerNav that is used for the Lister pagination. public function ___executeBrowser() { // Before MarkupPagerNav is rendered $this->addHookBefore('MarkupPagerNav::render', function(HookEvent $event) { $pager = $event->object; // Set base URL to the current page + URL segment $pager->setBaseUrl($this->wire()->page->url . 'browser/'); }); $browser = $this->modules->get('ProcessPageLister'); return $browser->execute(); }
  4. Something that would be worth a try... Use a saveReady hook to put all the tags as space-separated values into a (hidden) textarea field. Then use the **= operator with the tags string of the current project. From the docs:
  5. Thanks. It looks like the legacy Default and Reno themes don't call AdminThemeFramework::getPrimaryNavArray() so the hooks added by this module don't have any effect. Therefore AdminThemeUikit is a requirement - I've updated the module install requirements and readme to reflect this.
  6. I think a couple of ways are possible. One is similar to what @horst suggested, but you can use the special created timestamp of 10 to more exactly identify temporary images: $page->getUnformatted('images')->find('created!=10') There are also the public Pagefile::isTemp() and Pagefiles::isTemp() methods that can be used to check if a particular Pagefile/Pageimage is temporary or not. Another way would be to set the outputFormat property of the images field to array before you get the field value so that the value is standardised for single and multiple image fields. $page->getField('image')->outputFormat = FieldtypeFile::outputFormatArray; // Now use $page->image
  7. It's not different between frontend and admin - I just used that in my screenshot to show the as-yet-unsaved image. So you do have to watch out for it in template code too. Suppose you have a busy site and you're using getUnformatted() in your template code. If a website editor accidentally uploads the wrong image (you can imagine some worst-case scenarios here!) but then notices before they save the page, that temporary image might have already been displayed and viewed on the frontend via getUnformatted().
  8. True, but just want to point out there can be occasional "gotchas" when doing this because PW sometimes returns things that may be unexpected in the unformatted value. For example, the unformatted value of a Page Reference field will include unpublished pages and the unformatted value of a Repeater field can include "ready" items that are not populated in Page Edit. And in the case being discussed here the unformatted value of an images field can include "temporary" images that have been uploaded in Page Edit but the page has not yet been saved. So in the example below the frog image is saved but the fish image has just been uploaded but not yet saved, and might yet be abandoned before saving because of being a mistake or unwanted. Yet it appears in the unformatted value:
  9. This is great, thanks @MoritzLost for taking the time to write this up and share it with us. Although I don't agree with all the points (e.g. I think the PW emphasis on tree/hierarchy is a pro rather than a con) it's really interesting and useful to get an insight into how other CMSs solve problems and bring value to their users. I'm not sure if Ryan feels the same, but speaking as a person who enjoys developing modules and tools: eventually the limiting factor becomes ideas. That is, the will is there to keep creating useful things but the challenge is knowing what will consititute a useful thing to the audience. So getting user requests and descriptions of pain points is what's needed to keep the wheels turning. Regarding the Craft/PW comparison... You did state this clearly at the outset but I want to really emphasise this because it's such a major factor: the difference in cost between Craft CMS and ProcessWire is massive. I did a conservative estimate of the net income I would have lost as a solo developer over the last 5 years if I had have built all of my projects with Craft/plugins rather than PW/modules. It's approximately USD $43,000. For someone in my position that is just huge. Maybe I could have successfully added those Craft costs into the quotes but then maybe I would have lost many bids if I had done that. In general, if you think about the difference between something that's free and something that costs upwards of $299 it should be no surprise if there are some advantages to the thing that costs you $299. In fact it would be outrageous if you paid $299 for a thing and it was worse or no better than a free alternative. Suppose I would like a drink and I'm choosing between the free option (a bottle of tap water) and the $299 option (a bottle of Dom Pérignon champagne). The champagne should be a better experience than the tap water. That's why it costs $299. But when we bring this analogy back to PW/Craft, it's like ordering a bottle of tap water and then having the pleasant surprise that it's a very nice méthode traditionnelle. Maybe not quite as good as the Dom Pérignon, but at $0 that's extraodinary value and a lot of people would say it's the better choice for them. For the types of projects I use PW for, I have the occassional niggle but it's very minor stuff. Although I'd love to see PW match all the features of all its commercial competitors I also think it's reasonable to take the position that a free product is not going to be all things to all people. I actually wish there was more clarity about the kind of developer and kind of projects PW is targetted towards. In my opinion, narrowing the focus of PW and clearly communicating this at processwire.com would be a step in the right direction. Even if this was somehow expressed in negative terms, e.g. Don't know what a foreach loop is? Other tools will suit you better than PW. Looking for themes? Other tools will suit you better than PW. Looking for "a plugin for everything"? Other tools will suit you better than PW. Part of a large development team? Other tools will suit you better than PW. Building "enterprise" applications? Other tools will suit you better than PW. Working on projects with budgets in the mid-five-figures and higher? Don't be such a cheapskate, get out your chequebook because other tools will suit you better than PW. The way I see it, the person who will get most value and satisfaction from PW is a solo developer with at least intermediate experience (or a willingness to get there), working on projects that have demands that go beyond the basic but where the budget is somewhat limited. The main benefit that I get from PW is that I can build surprisingly powerful sites and build them fast so the hours/costs are kept down. This is the PW sweetspot and I think we should lean into it.
  10. @rick messaged me asking for advice about how to use dependent selects in a module config. That is, where the options of one select change depending on what is selected in a another select. I thought others might also find this info useful so I've put together a demonstration module: https://github.com/Toutouwai/DemoDependentSelects The general idea is that the dependent (target) select needs to include all the possible options, and then the options are hidden or shown by JavaScript depending on what is selected in the source select. See the source code for comments.
  11. As far as I can see it's working as per the documentation for the method - wireRenderFile() just calls $files->render(): https://processwire.com/api/ref/wire-file-tools/render/ If you do set an additional allowed path (which in your case you don't need to do because files within /site/modules/ are allowed by default) then the allowedPaths option needs to be an array of extra allowed paths.
  12. @MarkE, the SelectizeAll module itself doesn't get involved with the change event. The problem is likely to be an incompatibility between the Selectize and htmx libraries. I can't do much about that, but in the newly released SelectizeAll v0.1.2 you can disable the module for an inputfield by giving it a "no-selectize" class. So when you create a select or AsmSelect inputfield in your module you would add a line like this... $inputfield->addClass('no-selectize'); ...and then if the two modules are used together your selects/AsmSelects won't be "selectized".
  13. As a side note, if the new site is an enhancement of the old site (rather than a totally new site built from scratch) and you have PagePathHistory installed (a must-have on every site) then you should be able to move the existing news articles to any new path and PW will automatically redirect visitors from the old location to the new location. But if it's a new site from scratch where the IDs of historical news articles are now different to the old site, then I suggest doing the redirects using the PW API rather than manually entering a long list of redirects in htaccess. There are different ways you could do it. You could hook ProcessPageView::pageNotFound or use URL segments on the template for the /news/ page. Both would be fine, but I think the latter is a bit easier. Enable URL segments on the template for the /news/ page, and at the top of the template file: // If there is a URL segment (i.e. no real page exists at the requested URL) if($input->urlSegment1) { // Check for a published news article with that name $article = $pages->findOne("template=your_news_article_template, name=$input->urlSegment1"); if($article->id) { // If match found then redirect $session->redirect($article->url); } else { // Otherwise throw 404 throw new Wire404Exception(); } } // Only one segment is allowed if($input->urlSegment2) throw new Wire404Exception();
  14. Does the field have the "Required" checkbox checked?
  15. Open the page tree to Admin > Access > Roles and open the Roles page for editing. Temporarily uncheck the "Locked" status on the Settings tab and save. On the Children tab, in Sort Settings, choose "name" in the "Children are sorted by" dropdown. Save. Now re-check the "Locked" status and save.
  16. 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.
  17. I'm surprised you have so many template variables to declare. You might like to take a look at Markup Regions because that should greatly reduce the number of variables you need to hold markup. Does the below work? (P.S. parentheses are redundant for include, include_once, etc because they are expressions rather than functions) include_once './_func.php'; include './_header.php'; include './_sidebar.php'; include './_footer.php'; include './_buttons.php';
  18. I use generic words and numbers for field names, e.g. text_1, textarea_1. I really wish I didn't have to do this and could use descriptive names for fields, but the problem is that I almost always want to reuse fields for different purposes on different templates. So while a name like "city" is more meaningful than "text_1", I think it's much more confusing to call $page->city in some template when that field is actually holding a person's job title or something totally unrelated to "city". What I'd like is for PW to support field aliases, so that in the context of the "store" template I can give text_1 the alias of "city" and in the "employee" template I can give text_1 the alias of "job_title". Field aliases would need to be unique and in practice you could refer to a field by any of its aliases in any place in your code. I have an open request for this: https://github.com/processwire/processwire-requests/issues/154 Ryan seemed supportive at the time but it hasn't progressed anywhere since 2018. If anyone else would like this feature please "vote" for it with a thumbs-up at GitHub. I've also created a module that would allow aliases to be used but it can't be released due to issues with FileCompiler: https://github.com/processwire/processwire-issues/issues/882
  19. 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:
  20. It's explained in this post: Try separating functions from declared variables. See how it is done in the core site-default profile: https://github.com/processwire/processwire/blob/d78276e2c265f6b70384a13eb4febd4811a1db77/site-default/templates/_init.php Put all your functions in a file that is pulled in with include_once. Declare your variables in _init.php.
  21. @MarkE, thanks for the report. Please try the updated v0.3.4.
  22. It might work as a selector string: template=my_Template, field_in_my_Template=page.parent.title Or if field_in_my_Template is a Page Reference field: template=my_Template, field_in_my_Template=page.parent
  23. The "Multiple page selection" version of Page Auto Complete doesn't support the "Custom PHP code" option (i.e. the InputfieldPage::getSelectablePages hook). In earlier versions of PW it used to be more explicit about that. Now it just removes the "Custom PHP code" option depending on what you have selected in "Input field type". Page List Select and Page List Select Multiple also do not support the "Custom PHP code" option. If you really are returning something like that from you hook then you could change to the "Selector string" option, which will work with autocomplete.
  24. I am, but only on a single site and it's for a feature that's only activated once a year for a short period (an annual vote). I think I might have a use case for the module in some updates to a site that will be happening in the coming months. When that happens I'll spend some more time getting familiar with the module and can submit any ideas that come out of that. Thanks.
  25. @monollonom, you could do this with a hook in /site/ready.php: $wire->addHookAfter('InputfieldRepeater::renderReadyHook', function(HookEvent $event) { /** @var InputfieldRepeater $inputfield */ $inputfield = $event->object; // Disable RepeaterEasySort on all Repeater fields apart from those named "foo" if($inputfield->hasField && $inputfield->hasField->name !== 'foo') { $inputfield->removeClass('RepeaterEasySort', 'wrapClass'); } }, [ 'priority' => 101 ]);
×
×
  • Create New...