-
Posts
5,008 -
Joined
-
Days Won
333
Everything posted by Robin S
-
Nice site! One thing: to avoid blurry text in Chrome you could change instances of... transform: translate3d(-50%,-50%,0); ...to... transform: translate(-50%,-50%); ...if you're not actually using 3D space. Before: After:
-
Matching 2 pages based on title and "combining" data
Robin S replied to louisstephens's topic in API & Templates
You'd need to put more of the markup inside the conditional, otherwise it will be output for each iteration of the foreach. But for more nested markup like this it will be easier to make sense of if you first loop over all the service pages and build an associative array to group the services by person, then loop over the array. <?php $services = $pages->find("template=service-a|service-b, sort=parent.name, sort=sort"); // Group the services by person $people = []; foreach($services as $service) { $people[$service->parent->title][] = $service; } // Take a look at $people using Tracy Debugger just to understand what is going on bd($people, 'people'); ?> <?php foreach($people as $name => $services): ?> <div class="user"> <h3><?= $name ?></h3> <ul> <?php foreach($services as $service): ?> <li><?= $service->title ?></li> <?php endforeach; ?> </ul> </div> <?php endforeach; ?> -
Could be done, but I think there are probably better solutions already available such as AvbImage and PageImage Manipulator.
-
Acces multilang field values inside processInput Hook
Robin S replied to Andreas Augustin's topic in General Support
I don't normally deal with multi-language so I'm not sure if this is the best way, but it seems to work... public function validateShortlinks($event) { $field = $event->object; // Get specific language value $french = $this->languages->get('french'); $french_value = $field->get('value' . $french->id); // Or loop over all languages foreach($this->languages as $language) { $value = $field->get('value' . $language->id); //... } } -
Programmatic manual sorting of page reference pages
Robin S replied to Martin Muzatko's topic in General Support
It is neither built-in nor is it a field - it is just a custom property that you are setting to a page object while it is in memory. You can name the property anything you like - it doesn't need to be named "custom_sort". The "custom_sort" is not saved to the database for any page - it only exists while the page is in memory, and it's purpose is simply to provide some property to use the sort() method on. Then once the PageArray is sorted on that property and saved to the Page Reference field the sort is retained as part of the Page Reference field value. If you just give it a go it will probably start to make more sense. -
Great, thanks. Enjoy your holiday!
-
I had a quick look and validating the form is straightforward. After the form input is processed... if(count($form->getErrors())) { // There were some form errors so do not proceed with action } But at this point we are already in executeExecute() because the action of the form is the execute URL segment, and the page headings are different in this method. Maybe it would be better if the action of the options form was options URL segment, and then if successful redirect to execute segment? Not sure, there are probably several different ways to handle it and I'm sure you'll know the best approach.
-
Hi @adrian, I have a request for an enhancement to this module. I think it would be useful if the options form for an action was validated before executeAction() fires. So the required/requiredIf conditions are evaluated and executeAction() only fires if the form submission is successful. At the moment executeAction() fires even when the required/requiredIf conditions are not met, which means you have to do extra validation inside executeAction() and that can get quite tricky with some requiredIf setups. What do you think?
-
Programmatic manual sorting of page reference pages
Robin S replied to Martin Muzatko's topic in General Support
What is causing you to draw this conclusion? The value of a (multiple) Page Reference field is a PageArray. The sort order of pages in the field will be the sort order of the pages in the PageArray at the time the field (or the whole page containing the field) is saved. So setting the sort order of the field consists of putting the pages in the PageArray into the order you want and then saving the field (or the whole page containing the field). So if I have a Page Reference field "colours" which is currently empty on page $p and I add some pages to the field then the order is the order in which I add them (to the PageArray)... $p->of(false); $yellow = $pages->get('name=yellow'); $p->colours->add($yellow); $red = $pages->get('name=red'); $p->colours->add($red); $blue = $pages->get('name=blue'); $p->colours->add($blue); $p->save('colours'); // Alternatively you could save the whole page // Sort order of $p->colours is yellow, red, blue Suppose I now want to change this sort order to some other custom order. Let's say I want to sort them by the length of the page name. $p->of(false); foreach($p->colours as $colour) { $colour->custom_sort = strlen($colour->name); } $p->colours->sort('custom_sort'); $p->save('colours'); // Alternatively you could save the whole page // Sort order of $p->colours is red, blue, yellow -
Matching 2 pages based on title and "combining" data
Robin S replied to louisstephens's topic in API & Templates
As a general observation, I think using the page title or page name as a way to connect different pages to a single person is not very robust. It would be better to have a separate section in your page tree for "Persons", with John Doe, Jane Doe, etc, stored under there. Those pages don't necessarily have to appear on the front-end or have a template file. Then other pages are connected to a person by a Page Reference field. But on to your question... If it is acceptable to sort the persons listing by the name of the person then you could do this... $services = $pages->find("template=service-a|service-b, sort=parent.name"); $name = ''; foreach($services as $service) { if($service->parent->name !== $name) { // This service is from a different person, so output a heading echo "<h3>{$service->parent->title}</h3>"; $name = $service->parent->name; } echo "<p>$service->title</p>"; } Note that if you were using a Page Reference field to link services to a person then you would have more sorting options available to you - i.e. you could sort by any field that exists in the person template. -
Wow, that truncate function will truncate my search for the ultimate truncate function! ? I wonder if the default for the "visible" option should be true rather than false. If my string included entities and markup tags I think in nearly all cases I wouldn't want those invisible items affecting the visible string length.
-
It's just like @kongondo said - you have to save a new page before you can add files or images to it. The directory needed to hold the files/images gets created on the first save - then you can add files/images. So in submit(), do $p->save() before setDummyData()... public function submit() { $input = $this->wire('input'); $page = $this->wire('page'); $session = $this->wire('session'); if ($input->post->submit && $this->canEdit()) { if (($p = $this->savePageBasic()) !== false) { $p->addStatus(Page::statusHidden); $p->save(); $this->setDummyData($p); } $session->redirect($page->path); } } P.S. This... $parent = $this->wire('pages')->get($page->path); $p->parent = $parent; ...could be better optimised as... $p->parent = $page;
-
Exclude "page copying" from addHookAfter("saved")
Robin S replied to chumneypwire's topic in API & Templates
A couple of different ways... $pages->addHookAfter('saved', function(HookEvent $event) { $page = $event->arguments(0); if($page->hasStatus('unpublished') || $page->hasStatus('trash')) return; // Your code... }); $pages->addHookAfter('saved', function(HookEvent $event) { $page = $event->arguments(0); if($page->isUnpublished() || $page->isTrash()) return; // Your code... });- 3 replies
-
- copying
- addhookafter
-
(and 2 more)
Tagged with:
-
@PWaddict, I agree with @kongondo. If page A has a single page reference field with page B selected in it then page B must not have a single page reference field with page A selected in it. This only applies to two single page reference fields - if one or both are multiple page reference fields then there is no problem. This isn't an issue with this module specifically, just a limitation of PW. Related GitHub issues: https://github.com/processwire/processwire-issues/issues/152 https://github.com/processwire/processwire-issues/issues/572
-
If you are able to log in you may be able to resolve the errors by rebuilding the modules cache at Modules > Refresh. Related topic:
-
Exclude "page copying" from addHookAfter("saved")
Robin S replied to chumneypwire's topic in API & Templates
I think ProcessPageClone should give the user an opportunity to specify a title and name for the page before the clone is done, as is the case for cloning pages with children. I opened a request for this. But in the meantime you could check to see if a sibling page exists with the same name as the cloned page excluding the "-1" suffix. $base_name = rtrim($page->name, '-1'); if($page->siblings("name=$base_name", false)->count()) return; Edit: or maybe a better approach is not to write to your CSV for unpublished pages, as cloned pages are unpublished at first.- 3 replies
-
- 2
-
-
- copying
- addhookafter
-
(and 2 more)
Tagged with:
-
@adrian, maybe the module needs a try/catch to show the login throttle message rather than the 500 error?
-
FYI, Ryan has pushed a fix for this issue to the dev branch.
-
You don't want to chain methods together like that if there is a chance that one of them will return something unexpected. What I mean is if $page->find('name=foo|bar') finds zero pages, then there will be no first() page, and you can't get the children() of nothing. So you want to break it up a bit more, e.g. $mypages = $page->find('name=foo|bar'); if($mypages->count) { $mychildren = $mypages->first()->children(); if($mychildren->count) { // do something with $mychildren } } Or seeing as you only want the children of a single page (the first) then you can shorten it a bit by using child() instead of find()... $mychildren = $page->child('name=foo|bar')->children(); if($mychildren->count) { // do something with $mychildren } (Actually, $page->find() is different than $page->child() or $page->children() in that it will find pages at any depth under $page, but in your case I think you want to get only a direct child of $page).
-
If I'm going to type that out I might as well create the GitHub issue: https://github.com/processwire/processwire-issues/issues/583
-
Programmatic manual sorting of page reference pages
Robin S replied to Martin Muzatko's topic in General Support
Not totally sure what you are asking, but you can do a sort of some pages (either as part of a selector, or using the sort() method of WireArray) or you can set the sort value of some page(s) (either by setting $page->sort to some integer value, or by using the $pages->sort() method). The sort value of pages under a given parent determines their order in the page tree if no automatic sort of children is defined on the parent template/page. And if you do "sort=sort" or $some_pagearray->sort("sort") you are sorting by the sort value. Makes sense?? If you are saying you want to go through some pages and put them in a manual order that is different than their manual order in the page tree then one approach is to set a custom property of each page to an integer and then sort by that custom property. foreach($some_pagearray as $p) { // Some code to work out $sort_int for $p so that it will go where you want // ... $p->custom_sort = $sort_int; } $some_pagearray->sort('custom_sort'); -
[SOLVED] Required only if with required field action issue
Robin S replied to PWaddict's topic in General Support
I see the issue now. It's not related to PageTable fields as such, and it affects both the "Restore the previous value" and "Unpublish the page" options. I'll add a comment in the GitHub issue. -
[SOLVED] Required only if with required field action issue
Robin S replied to PWaddict's topic in General Support
What rule did you enter in the "Required only if" input? I tested it with a checkbox field and couldn't reproduce the issue. -
Thanks, fixed now.
- 17 replies
-
- module
- form builder
-
(and 1 more)
Tagged with:
-
@celfred, I don't think I'll be able to get my head around all the facets of your PW-based game, so will just answer in general terms. First thing is that, broadly speaking, there's no reason to avoid using plain PHP arrays, functions, etc in your development if that is easier or clearer for whatever you're wanting to achieve. Behind the scenes PW will be using these native PHP types and functions anyway. So it comes down to choosing whatever you find easiest or most transparent. So by all means use WireArrays/PageArrays where you find that easiest - in most circumstances that will be the way to go. But in your code I saw some places where you are creating new Page objects that are not actually going to be saved in the page tree anywhere. As if you are just creating these pages as a way to temporarily store some data. That doesn't make much sense to me and leads me to think there is probably some better way to do it. And it also pays to think about creating some structure to your data so that if you need to debug it or come back to the code in six months time you can dump things and understand what is going on from the dump. So that's why I suggested using a PHP array where the key names and array structure reveal the purpose of what you're doing. But if you need to take the 'players' element and do other things with it in the PW API then you're right that it would be easier if it were a PageArray rather than a plain PHP array of Page objects. So you could make that element a PageArray and then add pages to it... //... foreach($allPlayers as $player) { // Define the $groupId // Use an underscore (or other non-integer) in the $groupId to force it to be a string, not an integer // That way when array_multisort() is used later the keys will be preserved $groupId = $player->team->id . '_' . $player->group->id; // Optional: add $groupId to $player as a custom property in case you need it later $player->groupId = $groupId; // Add player to a PageArray in $uniqueGroups using $groupId as key if(!isset($uniqueGroups[$groupId]['players'])) $uniqueGroups[$groupId]['players'] = new PageArray(); $uniqueGroups[$groupId]['players']->add($player); } //... Then when you later need to work with the 'players' element it is a PageArray that you can use methods like sort() on. And while looking into the issue I discovered something new: although you cannot create a nested PageArray, you can create a WireArray of PageArrays. So you could think about taking this approach if you are more comfortable sticking with PW API methods rather than doing sorting etc in plain PHP. An example of what I mean about a WireArray of PageArrays... // Create a new WireArray to hold the PageArrays $my_wirearray = new WireArray(); // PageArray number 1 $pa1 = $pages->find("template=foo"); // PageArray number 2 $pa2 = $pages->find("template=bar"); // PageArray number 3 $pa3 = $pages->find("template=baz"); // Attach some custom data to the PageArrays $pa1->data('karma', 25); $pa2->data('karma', 13); $pa3->data('karma', 37); // Add the PageArrays to the WireArray $my_wirearray->add($pa1); $my_wirearray->add($pa2); $my_wirearray->add($pa3); // If you need to sort the WireArray by the custom data $my_wirearray->sort('-karma'); // Or maybe you want to explode on that custom data $karma_values = $my_wirearray->explode('karma', ['getMethod' => 'data']);