-
Posts
5,044 -
Joined
-
Days Won
340
Everything posted by Robin S
-
Excluding a past event from a PageReference field after it's been chosen
Robin S replied to a-ok's topic in General Support
I misunderstood - I thought you wanted to sort by the most distant upcoming date, not the soonest upcoming date. So you'll need a different approach I think, where you loop over your result pages add them to a new array using the next upcoming date as the key, then you sort the array by key. Edit: after thinking some more, this is not an ideal solution because your upcoming date timestamps may not be unique, so they don't make good candidates to use as array keys. A better idea is to add the next upcoming date timestamp as a custom property of each result. So the general principles... 1. Keep the "events_detail_dates_sort_date" field in your template, but instead of populating it with the soonest upcoming date you populate with the most distant upcoming date in the saveReady hook. This field will not be used to sort the pages (so you could consider renaming it if you like) but rather to exclude pages that have no upcoming date in your $pages->find() selector, so that you are not having to process more pages than necessary. 2. Loop over the raw unsorted results of your $pages->find() query, adding the timestamp of the next upcoming date as a custom property. Then sort on that property: // For each of your $pages->find() results... foreach($results as $result) { // Test for the template of the result here // ... // Get the repeater page with the next upcoming date $next_upcoming = $result->events_detail_dates->get("events_detail_dates_start_date>=$today, sort=events_detail_dates_start_date"); // Add the timestamp of the next upcoming date to the result as a custom property $result->next_upcoming = $next_upcoming->getUnformatted('events_detail_dates_start_date'); } // Sort the results by the custom property $results->sort('next_upcoming'); // Now loop over $results to output the markup You'll need to expand on this to deal with the other template ("Our pick") you are including in your results. So you would first test for the template of the result page and use the above if it is "events-detail" and come up with some other numerical value for the "our pick" results to use as "next_upcoming" so they appear where you want them when sorted by the custom property. -
The UIkit theme is looking lovely, but does anyone else think it goes a little too far in terms of padding? On my 27" monitor this interface looks quite large. On something like a 13" laptop you would not get much interface on the screen it would require a lot of scrolling. I love clean whitespace as much as the next person, but there is more than just aesthetics to consider. The admin interface is something that as developers we are going to spend a significant amount of time using. The extra scrolling and mouse movement that a widely-spaced interface requires is something to consider. Definitely not wanting a cramped, crowded interface but I think there is scope to be more efficient here, particularly in the vertical padding. In designing a utilitarian interface like this I would be inclined to follow a process of starting with no padding and then adding padding to elements by eye until it feels right.
-
Excluding a past event from a PageReference field after it's been chosen
Robin S replied to a-ok's topic in General Support
Oh right, that's because you can't use spaces around field/operator/value in selector strings. I was just composing that in the browser. If you change to... if($article->template->name == 'events-detail') { if(count($article->events_detail_dates->find("events_detail_dates_start_date>=$today"))) include './inc/events-item.inc'; } //... ...it should work. Not sure why it would need to auto update apart from when the page is saved. It only needs to update if you are making a change to the page by adding or removing a date. In terms of old dates you exclude those in the $pages->find() selector that gets your results: events_detail_dates_sort_date>=$today -
If you are using Page Reference fields there is some limited support for this. See this post:
-
If you want to add a CSS file so that it is linked at the bottom of the list of admin styles and scripts you can use a hook like this: $wire->addHookAfter('AdminTheme::getExtraMarkup', function(HookEvent $event) { $parts = $event->return; $parts['head'] .= '<link rel="stylesheet" href="/path/to/custom.css">'; $event->return = $parts; });
-
Excluding a past event from a PageReference field after it's been chosen
Robin S replied to a-ok's topic in General Support
Of course it depends on what you are iterating over, but in general foreach is very efficient. For instance, I've read that when working with a plain PHP array it is often more efficient to use foreach in place of dedicated PHP functions such as array_map and array_reduce (although for most situations that would be micro-optimisation and you would just use whichever is most convenient). I don't think that kind of sort would be possible in a selector, where you want to look through all repeater items and sort their containing pages by the most distant date. I think when you sort by a value contained within a multiple-page field (repeater, page reference, etc) the sort happens on whatever is the first page in that multiple-page field. So therefore you would need to apply some automatic sort to the repeater items so that the most distant date is always first, and that isn't so easy to do. If you have Profields Table then that has an option to automatically sort by a column. Or you might have to create a hidden field in the event template and populate it with a saveReady hook so it contains the most distant date, then sort by that field. To shorten your code you could do away with the nested foreach and do something like: if($article->template->name == 'events-detail') { if(count($article->events_detail_dates->find("events_detail_dates_start_date >= $today"))) include './inc/events-item.inc'; } //... BTW, where you are not mixing HTML and PHP you don't need PHP open/close tags on every line - you can just put the whole block of PHP code between a single pair of open/close tags. It doesn't do any harm the way you are doing it, but perhaps a little harder to read. -
each user allowed to add only one page under a parent template
Robin S replied to ziu's topic in General Support
Another approach is to not allow users to create pages at all, but rather automatically create a single unpublished page for each user in a hook at the time the user is created. Then each user can populate and publish their page if they wish. -
Using markup regions causes template to render twice?
Robin S replied to jtborger's topic in API & Templates
Check out Tracy Debugger and you'll be glad you did. Then rather than using var_dump and echo you can use the bd() function in your files to get a lovely expandable dump output and the "double output" thing won't be an issue with Markup Regions. -
@taoguang, I think you might be mixing up two different approaches to tagging. This looks like you have a text field with comma separated tags. But you don't need this if you are using pages for your tags - you can use a Page Reference field to add the tag pages directly. So like you quoted in your post:
-
@Tom., there does seem to be something funny going on in this case when hooking before Pages::save. Will do some more testing, but to allow you to move forward with your project the quick solution is just to hook after Pages::save. So in the test case: $wire->addHookAfter("Pages::save", function(HookEvent $event) { $page = $event->arguments('page'); if($page->template == 'bug' && !$page->skip_me) { for($i = 0; $i < 3; $i++) { $p = $page->repeater_2->getNew(); $p->text = 'Bug'; $p->save(); $page->repeater_2->add($p); $page->skip_me = true; // prevent recursion $page->save(); } } }); Edit: did some more testing using a Page Reference field and managed to trace it back to the "uncacheAll" option in PagesEditor::save(). Posted a comment on the other GitHub issue, which is definitely related to your issue. Hopefully Ryan can fix it soon.
-
I know, and I can't reproduce any problem, so more of a step by step guide to reproducing the issue on a clean PW installation would be helpful.
-
Is it possible to change the Notes of a field with a Hook?
Robin S replied to PWaddict's topic in General Support
$wire->addHookBefore('Inputfield::render', function(HookEvent $event) { $field = $event->object; if($this->process != 'ProcessPageEdit') return; $page = $this->process->getPage(); //... BTW, it would be better to hook a more specific inputfield render rather than just Inputfield::render. So something like InputfieldPageTable::render or whatever inputfield type you are targeting. -
@Tom., members of the PW community might be able to help with your issue if you can isolate the conditions that cause it and list steps for reproducing the issue. In the GitHub issue under "Steps to reproduce the issue" you just say... ...which really does not make for a useful bug report.
-
Excluding a past event from a PageReference field after it's been chosen
Robin S replied to a-ok's topic in General Support
It is a public method of the FieldtypePage class. See the description of the arguments in the DocBlock. Not sure. It works for me. But if you're not going to be changing the conditions for selectable pages often then you can just check the template and date in the foreach instead. There is no performance reason to not use a foreach. It's not like a $pages->find() selector where the database is involved. When you do anything with the value of a Page Reference field the entire PageArray (aka WireArray) is loaded (more about that here) and methods like find() or filter() are just foreaching the WireArray internally anyway. -
Excluding a past event from a PageReference field after it's been chosen
Robin S replied to a-ok's topic in General Support
As a general issue... It's a tricky one, how pages that are already selected in a Page Reference field should be handled if they no longer meet the requirements for selectable pages for that field. When getting the value of the Page Reference field via the API, I think the value should be validated through the isValidPage() method when it is "woken up" from the database. Currently the field value is validated on sleep but not on wakeup. Validating on wakeup would solve the situation where the value of the field when accessed from the API is different to the apparent value when viewing the field in Page Edit. But wouldn't solve the fact that the database value still includes an invalid page and so could give unwanted matches in $pages->find() for example. Or if that is not desirable for some reason then I think there should be some improvement to how invalid items are handled in the inputfield. Currently they are hidden in the inputfield, but that means that if you just view the page in Page Edit but do not save then you get a false impression of what the value of the field is. Maybe if invalid items were shown in the inputfield but highlighted in a warning colour, and then those items removed when the page is saved. Would be good to hear what others think about how invalid selected pages should be handled. For your specific issue... If you are foreaching the pages in your template, you could check the template and date of each item to determine if it should be output or not. Edit: you could actually use FieldtypePage::isValidPage() to validate each page in the Page Reference field value in your template, e.g. /* @var FieldtypePage $field */ $field = $fields->home_whatson; foreach($page->home_whatson as $item) { if($modules->FieldtypePage->isValidPage($item, $field, $page)) { // output $item } } -
Thanks for the updates! Seeing as the profile editor is getting some improvements, could you look at adding FieldsetTab support? Related topics: https://processwire.com/talk/topic/16125-tabs-on-profile-edit-page/ https://processwire.com/talk/topic/16253-user-profile-tabs-markup-regions-the-lack-of-tuts/
-
how pages that logged user has created in admin panel
Robin S replied to ziu's topic in General Support
To hide pages from ProcessPageList for non-superusers (doesn't apply for superusers) you can hook Page::listable(). $page->listable() bool Returns true if the page is listable by the current user, false if not. Can also be used as property: $page->listable So to hide pages that the user cannot edit you can add this to /site/ready.php: $wire->addHookAfter('Page::listable', function(HookEvent $event) { $page = $event->object; if(!$page->editable) $event->return = false; }); -
[SOLVED] 403 Forbidden when loading images from folder
Robin S replied to jploch's topic in Getting Started
If you can control the naming of the images then that is an easy solution. Otherwise you need to do natural sorting of the files array. Something like: $files_array = $item->sequenz_files->getArray(); natsort($files_array); // Now foreach $files_array // And if you need the files as a Pagefiles object for some reason $pagefiles = new Pagefiles($item); $pagefiles->import($files_array); // Now foreach $pagefiles -
Is it possible to change the Notes of a field with a Hook?
Robin S replied to PWaddict's topic in General Support
Easiest way that works for inputfields both inside and outside of repeaters is to match the name of the field associated with the inputfield: $wire->addHookBefore('Inputfield::render', function(HookEvent $event) { $inputfield = $event->object; if($inputfield->hasField == 'YOUR_FIELD_NAME') { //... -
Does anyone know if it's possible to do something to "tell" PhpStorm how PW uses a template file and what variables are in scope there? For the purposes of code completion and to avoid erroneous undeclared variable warnings. Currently I manually list all API variables and variables declared in the auto-prepended _init.php inside a DocBlock at the top of every template file. This works but gets pretty tiresome, especially when you need to make a change globally. What would be cool is if PhpStorm could "know" that all API variables are available in every template file and that _init.php is prepended and so all the variables declared there are in scope. Anyone know a way to achieve this? BTW, for API variables the Functions API is a no-go for me because I dislike all the string concatenation that goes with it.
- 15 replies
-
- 2
-
-
- ide
- code editor
-
(and 1 more)
Tagged with:
-
Okay, I've narrowed down the problem. It occurs whenever an image or file is uploaded and then the page is immediately saved via the hotkey. It seems to be related to the "Choose File" button having focus after a image/file is uploaded - like the first click() just shifts the focus but does not trigger a submit. What fixed it for me was, at the end of aos_triggerSave() where the button click is triggered, first focus the button: aos_saveButton.focus().click();
-
Or use a "saving" indicator that does not cover/lock the screen but just overlays a small part of it.
-
Hi @tpr, I've been having intermittent problems when using the save hotkey. I get the overlay but the form is not submitted. It's been happening on remote sites and on localhost, but I'm not sure exactly what version of AOS I first noticed the issue with. There are no errors in the browser console when the issue occurs. Browser is Chrome on Windows. Tricky one to debug because it only happens intermittently - just thought I'd mention it in case others have been experiencing it too. I'm wondering if the behaviour of the save hotkey could be a little less restricting so if an issue like this does occur the interface is not locked and the save button is still accessible. Currently I have to use my browser dev tools to remove the height and width from the added pseudo-element and allow pointer events.
-
Page Reference Input fieldtype: Checkboxes - more advanced options
Robin S replied to cst989's topic in Wishlist & Roadmap
The inputfield could be approached a similar way to Profields Table, which does support large amounts of data through limiting and pagination. It was the introduction of pagination within Table that prompted my GitHub request. But although an inputfield solution is important it is the API side that is of greater importance. Currently you cannot do anything with the value of a Page Reference field without loading all the pages into memory. So if you have a Page Reference field with 2000 items and you do... $item = $page->my_page_reference->first(); ...or... $item = $page->my_page_reference->findOne("name=foo"); ...then boom, you have 2000 pages loaded to memory. It's not like $pages->find() or $page->children() where you can be selective or limit what is loaded. Compare with $page->children(): parent-child is one kind of basic relationship between pages. Page Reference is the other kind of basic relationship between pages. Both of these relationships should be able to scale up, but currently only parent-child does. This discussion probably warrants it's own topic. -
Matching by tempate name in a PageReference field is working for me: $items = $pages->find("test_page_reference.template.name=basic-page"); Could it be that you have no template named "events-detail" or no pages using that template selected? Incidentally, how did you dump the selector to get the selector string that PW converts to? Looks like a useful debugging trick.