-
Posts
5,008 -
Joined
-
Days Won
333
Everything posted by Robin S
-
You cannot use a Repeater field in a Process module. I think a similar restriction might apply to PageTable fields. It sound like your Process module is getting fields from another page, so maybe it would be better to simply edit that page in Page Edit? If you want a menu item to appear in the Setup menu you could create a Process module that redirects to Page Edit for a particular page, as @PWaddict shows in the post below:
-
Breadcrumbs in backend doesn't link to parent page
Robin S replied to dragan's topic in General Support
There is discussion on this topic here: https://github.com/processwire/processwire-issues/issues/22 -
Strange output when setting Name format for children
Robin S replied to Tyssen's topic in General Support
From the documentation for "Name format for children": So if you want date format "U" you would enter that along with at least one non-alphanumeric character - e.g. "/U" or "U/". Do not enter "date()" anywhere in the format. ProcessSetupPageName is not the same as the core "Name format for children" feature and it has different format requirements. -
Very nice, thanks for the module! I have to say though, the fact that the fields get automatically added to all templates doesn't sit quite right with me. People probably only need to use time limits for specific templates and for the other templates the fields become a kind of clutter. Better I think to let people add the fields to only the templates they need to be on. I haven't looked closely but perhaps you could reduce the number of needed fields to two - just the Datetime fields. Instead of the checkboxes you can have the Datetime fields set to collapse when empty. Don't have the fields default to "today" but just let people populate them when they want them to be active and leave them empty if they want them deactivated. Another possibility if you want to make it easy for people to add/remove the fields from templates would be to have an AsmSelect field in the module config for choosing templates. Then you could hook Modules::saveConfig to get the selected templates and programmatically add/remove the fields from those templates. Clauses could be added to the selector to check... 1. Either releasetime_start is unpopulated or releasetime_start is less than "now" ...and... 2. Either releasetime_end is unpopulated or releasetime_end is greater than "now"... $pages->find("or1=(releasetime_start=''), or1=(releasetime_start<now), or2=(releasetime_end=''), or2=(releasetime_end>now)"); But rather than try and do this automatically in a hook to Pages::find (which would almost certainly be problematic) I suggest just explaining this in the documentation and letting people add it to their selectors as needed.
-
I'd be keen to have an option to enable the Console for non-superusers on localhost. If it's limited to localhost then there's not really a security risk I think. It would be handy for checking things like $page->addable(), $page->publishable(), etc from the perspective of a non-superuser role. When testing I typically keep an incognito window open with an editor role logged in rather than work with the User Switcher.
-
I'm talking about the array keys, not the values. If you use a string as an array key the string has to be in quotes or else it is interpreted as a constant. In the FieldtypeText example you show the keys are correctly within quotes. I recommend installing Tracy Debugger - it is good at picking up errors that can otherwise be missed.
- 14 replies
-
Thanks for the updates! I spotted a few little issues in InputfieldTagify... There are quotes missing around version, autoload and singular in getModuleInfo(): https://github.com/Sebi2020/InputfieldTagify/blob/354acf86ac88baa8c257523cd093ec202c573fe0/InputfieldTagify.module#L18-L20 PHP gives a warning that InputfieldTagify::renderReady() and InputfieldTagify::___processInput() should be compatible with the methods of the Inputfield class that the module extends. So for renderReady() I think you want: public function renderReady(Inputfield $parent = null, $renderValueMode = false) { $this->addClass("tagify-input"); return parent::renderReady($parent, $renderValueMode); } And for ___processInput(): public function ___processInput(WireInputData $input) { //...
- 14 replies
-
- 1
-
-
Ha ha, you might have spoken too soon. ? I knew that as soon as I posted this a much simpler solution would present itself. You don't need to exclude anything to make an exact match - you just need to match all the pages and the count of the pages. So no helper method is needed really. $matches = $pages->find("template=traveller, countries=Albania, countries=Andorra, countries.count=2"); Or for a more complex match where the count isn't immediately obvious: $value = $pages->find('template=country, title=Albania|Andorra'); // imagine a more complex value than this $selector = $value->each('countries={id}, '); $selector .= "countries.count=$value->count, template=traveller"; $matches = $pages->find($selector);
-
I took a stab at a helper method and posted it here: This makes it easier if you have a more complex definition for selectable pages than simply children, or if you later change the definition for selectable pages and don't want to have to remember to update your code, or if you have a lot of selectable pages (for the selector it only includes pages that have actually been selected somewhere).
-
Update: you don't need this method. See my next post below. ? ----- Suppose you have a Page Reference field "countries" in template "traveller" that contains any countries the traveller has visited. It's easy to find travellers who have visited Albania and Andorra... $matches = $pages->find("template=traveller, countries=Albania, countries=Andorra"); But what if you want to find travellers who have only visited Albania and Andorra and not visited any other countries? Then it's not so easy. There's no simple syntax for selectors that allows you to match an exact Page Reference field value, as @adrian highlighted recently. Within your selector you have to include all the countries that you don't want to be in the field value. That's a hassle to do manually, and in some circumstances where new pages are being added all the time you may not know in advance all the pages you need to exclude. So to make it an easier job to create an exact match selector for Page Reference fields, here is a helper method you can add in /site/ready.php: // Returns a selector string for matching pages that have the exact supplied value in the Page Reference field $wire->addHookMethod('Field(type=FieldtypePage)::getExactSelector', function(HookEvent $event) { $field = $event->object; $value = $event->arguments(0); if($value instanceof PageArray) $value = $value->explode('id'); if(!is_array($value)) throw new WireException('The $value argument supplied to getExactSelector() must be a PageArray or an array of page IDs.'); $table = $field->getTable(); $query = $this->database->query("SELECT data FROM $table GROUP BY data"); $field_values = $query->fetchAll(\PDO::FETCH_COLUMN); $exclude_ids = array_diff($field_values, $value); $selector = ''; foreach($value as $id) $selector .= "$field->name=$id, "; if(count($exclude_ids)) $selector .= $field->name . '!=' . implode('|', $exclude_ids); $event->return = rtrim($selector, ', '); }); And you use the method like this: // Get the Page Reference field you want to use in the selector $field = $fields->get('countries'); // Get the value you want to match (PageArray) $value = $pages->find('template=country, title=Albania|Andorra'); // Alternatively $value can be an array of page IDs // $value = [1105, 1107]; // Use the method to get a selector string $selector = $field->getExactSelector($value); // Optional: add anything else to the selector that you want $selector .= ', template=traveller'; // Find the matching pages $matches = $pages->find($selector);
-
That's a really good point, and a situation I haven't considered before. But I don't think there is any syntax that does what you want. And if you look at how the values of multiple page reference fields are stored in the database (with each selected page being a separate row in the database) I can't see a way to find exact matches, either with an API selector or an SQL query, without explicitly stating all the values that you don't want to match. So I'm thinking that one approach to make it easier to do these kinds of searches would be to create a function that: 1. Takes the field name and pages you want to match as arguments 2. Gets all the pages that have been selected in the field 3. Subtracts the pages to match from the pool of selected pages 4. Returns a selector string component for the pages not to match Then you include that exclusion string in your selector. I might have a play around with this later if you don't beat me to it or you come up with a smarter solution. ?
-
For anyone interested, I solved this by setting the "User navigation label format" in the AdminThemeUikit module config to an empty string... ...and changed the icon and link href with the following custom JS: // Modify tools menu var $tools_link = $('#tools-toggle'); $tools_link.find('.fa-user-circle').removeClass('fa-user-circle').addClass('fa-wrench'); $tools_link.attr('href', ProcessWire.config.urls.root).attr('target', '_blank');
-
The "hookable" icon in the API methods listing is almost invisible - I think it's missing a width rule: Besides the size glitch, I think it would be helpful to make the meaning of this icon a bit more obvious - the single note at the top about it's meaning probably is not enough. Some ideas: Add a label for the column in the table header Add a title tooltip that explains the meaning of the icon on hover Use a different icon than the thunderbolt - didn't the old site have a "hook" icon in this place?
-
The view permission controls viewing on the front-end, it doesn't relate to pages being listed in Page List. For more advanced control over page permissions try hooking after the following Page methods, returning true/false as needed. $page->listable() is the one related to which pages appear in Page List. $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 $page->moveable() bool Returns true if the current user can move this page. Optionally specify the new parent to check if the page is moveable to that parent. Can also be used as property: $page->moveable $page->publishable() bool Returns true if the page is publishable by the current user, false if not. Can also be used as property: $page->publishable $page->restorable() bool Returns true if page is in the trash and is capable of being restored to its original location. @since 3.0.107 $page->sortable() bool Returns true if the current user can change the sort order of the current page (within the same parent). Can also be used as property: $page->sortable $page->trashable() bool Returns true if the page is trashable by the current user, false if not. Can also be used as property: $page->trashable $page->viewable() bool Returns true if the page (and optionally field) is viewable by the current user, false if not. Can also be used as property: $page->viewable An example of a Page::listable hook - note that such hooks do not restrict the superuser role: $wire->addHookAfter('Page::listable', function(HookEvent $event) { $page = $event->object; if($this->wire()->user->hasRole('editor') && $page->template == 'basic_page') $event->return = false; });
-
Enable debug mode to get more informative error messages. Open file /site/config.php via FTP or hosting file manager and edit the line below to set debug mode true, or add the line if none exists. $config->debug = true; It's possible if the original superuser was deleted, but that's not a common scenario. You could try adding a new superuser account by adding and loading the following "add_user.php" file in the site root. <?php require './index.php'; $u = new User(); $u->name = 'new_user'; $u->pass = '123456'; $u->addRole('superuser'); $u->save(); Edit: by the way, you can also find the names and ids of the existing users by looking in the pages table of the database. In phpMyAdmin or similar, sort the table by the templates_id column, and look at the names and ids of rows where templates_id is 3 (3 is the id of the user template).
-
Alternatively you can hook after ProcessPageSearch::findReady to make it a bit more specific to autocomplete:
-
Try... 1. Create file "reset.php" containing the following (beware of non-printable characters creeping in - to be sure you could type it out rather than copy/pasting): <?php require './index.php'; // Bootstrap ProcessWire $admin = $users->get(41); // Get the default superuser by ID $admin->of(false); // Set output formatting off $admin->name = 'yourNewUserName'; // Set the name $admin->pass = 'yo123456'; // Set the password $admin->save(); // Save the user 2. Upload reset.php to the site root (where the ProcessWire index.php file is). 3. Load the file in your browser: https://guidetodrawing.com/reset.php 4. Login with the user details at: https://guidetodrawing.com/admin/ 5. Delete reset.php
-
Yeah, I think you're right that this would be better.
-
That does make some sense to me, because httpRoot is not a setting that is defined anywhere but more like "given the way you are accessing this website right now, this is the root URL". Imagine a site that had several domains that are valid to access the site at, or a site where both HTTP and HTTPS protocols are allowed without redirect (lets disregard the SEO implications of all of this). The httpRoot would be expected to change depending on the domain/protocol you are accessing the site at. If you are using the CLI then PW doesn't have a protocol or domain to refer to so it just gives you the first allowed httpHost (rather than giving you nothing which would arguably be worse). This is how I imagine the thinking goes - I haven't looked at the code.
-
Love this module, but how come the edit icon that is added to the inputfield is fa-search? I reckon fa-pencil-square-o would be more suitable for an edit icon.
-
I don't think this behaviour is related to the pattern that is used. When a field is set to "required" or with some validation rule then PW gives feedback to the user when the field is not submitted in the correct state but it saves the form regardless. Client-side validation prevents form submission but this is a browser feature not a PW feature. The PW behaviour is deliberate and @ryan has explained the rationale behind it somewhere - I can't find it at the moment but maybe someone else will chime in with a link. Perhaps Ryan would be open to having an option to restore the previous value in case of failed validation, seeing as that option exists at the template level for required fields. You could make a request at GitHub. Also see Soma's hook solution:
-
Clean syntax for rendering pages with specific template?
Robin S replied to Anders's topic in Getting Started
Perhaps you have auto-prepended and/or auto-appended template files in your /site/config.php, in which case you would want to use the $options array to override those when rendering the page, e.g. foreach ($pages->find("template=article") as $article) { $content .= $article->render('teaser.php', ['appendFile' => null]); } -
Hi @ryan, could you please add some more detailed documentation for the $page->render() method to the API docs? Currently the details are quite minimal (the method doesn't have it's own page but just a short entry on the $page documentation) and doesn't cover all the options that you describe in this post: I guess the docs for $page->render() need to somehow pull in the PhpDoc comments from PageRender::renderPage().
-
Clean syntax for rendering pages with specific template?
Robin S replied to Anders's topic in Getting Started
Welcome to the PW forums @Anders! There are many different ways you could do this and at the end of the day it comes down to personal preference. Myself, if this was a one-off listing of teasers that wasn't to be used on other templates I would tend to build the markup directly in the template file and not render any other files. And if it was a listing that was to be used in several template files I would tend to render a file that looped over multiple pages and I would pass those pages to the rendered file. I prefer to output markup directly and make use of the Markup Regions feature, but to keep with your case of populating a $content variable it would be something like this: $content .= $files->render('teasers', ['items' => $pages->find("template=article")]); BTW, the wireRenderFile() function is sort of obsolete as far as I can see because it is just an alias for $files->render(). But if you wanted to render a page with something similar to your example... ...then you could look at the (largely undocumented) $page->render() method. The best resource that I know of for this method is Ryan's post here: Also you can read the comments for PageRender::renderPage() in /wire/modules/PageRender.module (which is what $page->render() calls behind the scenes). So you could do something like: foreach ($pages->find("template=article") as $article) { $content .= $article->render('teaser.php'); } -
Warning message when defining a field in repeater as required
Robin S replied to dragan's topic in General Support
I did some testing to see what is needed to get required-if conditions working within repeaters and opened a request here: https://github.com/processwire/processwire-requests/issues/262