Jump to content

Robin S

  • Content Count

  • Joined

  • Last visited

  • Days Won


Everything posted by Robin S

  1. Welcome to the forums @skoskie 🙂 The Comments fieldtype already includes a star rating option: https://processwire.com/blog/posts/processwire-2.6.21-upgrades-comments-more-on-pw-3.x/#new-star-ratings-for-comments-fields
  2. @msavard, in this module HTML tags are not supported inside attributes. But you could use Markdown for the same result, for example: In your attribute: Claims filed between **February 16 - December 10** will receive a [partial exemption](https://www.google.com) for that year. In your Hanna Tag code: <div class="message-box"><?= $sanitizer->entitiesMarkdown($text) ?></div>
  3. Maybe: check_access=0 https://processwire.com/docs/selectors/#access_control
  4. I'm sure you're right, but I'm not 100% clear on what you mean here. It seems like both include and exclude settings would use OR conditions: exclude (role1 OR role2 OR role3) include only (role1 OR role2 OR role3) Or maybe you mean AND/OR in terms of combining the two settings? "exclude (roles) AND include (roles)" versus "exclude (roles) OR include (roles)" I imagined using one setting or the other but not both, but maybe there are some situations where a user would want to combine them.
  5. Hi @adrian, I have a little problem with the User Switcher panel: there's a config option for limiting the list of users that appear in the panel, which is great because often there can be a lot of front-end-only users. But the problem for me is that the option gets defined in terms of roles that are excluded rather than included: I'm not sure how common this is for others, but I often give back-end users (who I want to be able to switch to via the User Switcher) front-end roles because they can also be "members" as well as "administrators". So these kinds of users have multiple roles. What do you think about adding an "include only these roles" option for User Switcher as well as a "exclude these roles" option? Or maybe you have another idea of how this might be accommodated?
  6. v0.1.10 released. Now that new core ways of setting field widths in template context have been introduced it seems that users are sometimes setting a field width using a core input and then saving the Edit Template form. Although it's not necessary to save the Edit Template form after adjusting a field width using a core input (those settings are AJAX-saved), it's not unlikely that users will do this and in these circumstances the old width stored in the Template Field Widths inputfield was overwriting the new width. So from v0.1.10 onward the widths entered into the Template Field Widths inputfield are only saved if Edit Template is saved with the Template Field Widths inputfield in a open state. And it's recommended to use the default "Collapsed" config option for Template Field Widths if you think you might also use core inputs for setting field widths.
  7. All good if another way is added to open files in PhpStorm, but I use the editor:// protocol with PhpStorm and never had any problem with it. It's been a long time since I set it up but I expect I followed the PhpStorm docs and I don't remember it being difficult.
  8. Yes, there are core permissions built in for this purpose. https://processwire.com/docs/user-access/permissions/#user-admin-permissions https://processwire.com/blog/posts/new-user-admin-permissions-automatic-version-change-detection-and-more-2.6.10/#new-user-admin-permissions
  9. It all depends on how your original image was created. Was it saved at maximum quality? Was it passed through some sort of optimisation process/service (TinyJPG, CompressOrDie, etc) that compressed the image and reduced the filesize? Your PW resizer settings are asking for maximum quality, minimum compression, and therefore you can expect relatively large filesizes. And the PW resizer is not going to produce filesizes as small a specialised optimisation service, particularly one that you customise the settings of per image.
  10. @Orkun, do you know about $page->listable()? It determines whether a page may appear in Page List (and also PageListSelect inputfields, which is probably something you want too). So you could do: $wire->addHookAfter('Page::listable', function(HookEvent $event) { /* @var Page $page */ $page = $event->object; if(!$page->editable() && !$page->addable()) $event->return = false; }); You can hook ProcessPageListRender::getNumChildren to customise the child count. But in some cases depending on what is determining a page's listable status you might decide it's not worth the trouble. Here's one way you might do it (in /site/ready.php): // Work out which templates are editable or addable for the user and store them on the $user object // Doing this here to avoid doing it repeatedly in the getNumChildren hook if(!$user->isSuperuser() && $page->template == 'admin') { $user_roles_ids = $user->roles->explode('id'); $allowed_templates = []; foreach($templates as $template) { $edit_add_roles = array_merge($template->editRoles, $template->addRoles); if(count(array_intersect($user_roles_ids, $edit_add_roles))) $allowed_templates[] = $template->name; } $user->allowed_templates = $allowed_templates; } // Set a selector to correct the children count $wire->addHookBefore('ProcessPageListRender::getNumChildren', function(HookEvent $event) { $user = $event->wire('user'); if($user->isSuperuser()) return; $selector = 'template=' . implode('|', $user->allowed_templates); $event->arguments(1, $selector); }); Be aware that there are some other areas you probably want to consider if you are hiding pages in Page List. Here are some pointers to get you started: Pages that can be found in the admin search - look at manipulating the selector by hooking ProcessPageSearch::findReady Pages that can be found in Lister - look at manipulating the selector by hooking ProcessPageLister::getSelector
  11. Try hooking after ProcessPageEdit::buildForm. ProcessPageEdit::buildFormContent only contains the page template fields and not the fields from the Children, Settings, etc tabs. Another hurdle is that the value of InputfieldPageAutocomplete is always an array, and ProcessPageEdit expects the value of the parent_id field to be an integer. This seems to be working: $wire->addHookAfter('ProcessPageEdit::buildForm', function(HookEvent $event) { /* @var InputfieldWrapper $form */ $form = $event->return; $orig_pi_field = $form->getChildByName('parent_id'); $attrs = [ 'collapsed', 'required', 'label', 'icon', 'id', 'name', 'value', ]; $new_pi_field = $event->wire('modules')->get('InputfieldPageAutocomplete'); $form->insertAfter($new_pi_field, $orig_pi_field); $form->remove($orig_pi_field); foreach($attrs as $attr) { $new_pi_field->$attr = $orig_pi_field->$attr; } $new_pi_field->maxSelectedItems = 1; }); $wire->addHookAfter('ProcessPageEdit::processInput', function(HookEvent $event) { /* @var InputfieldWrapper $form */ $form = $event->arguments(0); if($form->id !== 'ProcessPageEditSettings') return; $pi_field = $form->getChildByName('parent_id'); if(!$pi_field || !$pi_field->isChanged()) return; $parent_id = $pi_field->value; $parent_id = (int) reset($parent_id); /* @var Page $page */ $page = $event->object->getPage(); $page->parent_id = $parent_id; });
  12. I also have this question. Which is the recommended branch to use? @Soma
  13. The method that sets the filename is here: https://github.com/processwire/processwire/blob/655c4cdd245fa4990d010c06ccfcfd37a04c0fde/wire/core/Pagefiles.php#L554-L599
  14. As an alternative to step 2 and adding the matched images to cloned fields, in step 6 you could copy the matched files to the page's folder in /site/assets/files/. That's probably the easier approach. Edit: here's some API code you could execute in the Tracy console... // Find all image fields $image_fields = $fields->find("type=FieldtypeImage"); // Find all templates that contain those image fields $tpls = new TemplatesArray(); foreach($image_fields as $image_field) { /* @var Field $image_field */ $tpls->add($image_field->getTemplates()); } // The page that contains the unorganised images - update ID to suit $unorganised = $pages(1287); // Find all pages with missing images $pages_with_missing_images = $pages->find("template=$tpls, id!=$unorganised"); // Loop over those pages foreach($pages_with_missing_images as $p) { // Get the directory for the page $page_dir = $p->filesManager()->path; // Loop over the image fields foreach($image_fields as $image_field) { // Continue if the page doesn't contain the image field if(!$p->fields->has($image_field)) continue; // Get images as Pageimages object regardless of formatted value foreach($p->getUnformatted($image_field->name) as $image) { // Look for a matching image among the unorganised images $match = $unorganised->images->get("name={$image->basename}"); if($match) { // Copy to the page directory if a match is found $files->copy($match->filename, $page_dir); } else { // Display (or log) a message about unmatched images d("No match found for image '{$image->basename}' in field '{$image_field->name}' on page '{$p->title}'"); } } } }
  15. First thing would be check with your host to see if they have a backup of the file system. If they can't help you then I suggest... 1. Copy the site to your local machine. Everything else that follows you do locally - don't do anything else on the live site because you only risk losing more data. 2. Create clones of all your image fields (Add New Field > Type > Clone existing field...). Add them to the same templates that your original fields are on. This is so that when you add the new images you keep them separate from the existing field values. 3. Create another new image field that will hold all the unorganised images. Create a new template and add the image field to the template. Create a new page using the template - we'll title this "Unorganised Images". 4. Add all the unorganised images to the new page. Personally I would do this using the API together with glob or DirectoryIterator but you might be able to do it via the admin if you allow a lot of memory and a set a long max execution time. This step will sanitize the image filenames. 5. Create a DB backup now in case you make some errors in the next step and need to recover to this state. 6. Use an API script (using Admin Actions, in the Tracy console, or just in a template file) to loop over all pages that have image fields (apart from your page with the unorganised images), and loop over all the images in those image fields. For each image in any of your original image fields, look for an image of the same name in your Unorganised Images page. If you find a match then add the image to the clone of that image field. You might want to log the page title / image field name / image filename for any images that can't be matched. 7. Check the results. When you've done the best you can then you can delete the original image fields, rename the cloned image fields according to the original field names, delete the page/template/field used in Unorganised Images, and redeploy to the live site.
  16. There is a noTrim setting for InputfieldText and inputfields that extend it. Hooking InputfieldText::render is too late to set this, but you could hook Field::getInputfield if you want leading/trailing whitespace not to be trimmed for all text fields. // Include leading/trailing whitespace in inputfields for all text fields $wire->addHookAfter('Field::getInputfield', function(HookEvent $event) { /* @var Inputfield $inputfield */ $inputfield = $event->return; if(!$inputfield instanceof InputfieldText) return; $inputfield->noTrim = true; }); Before: After:
  17. I like it! Not only is it easier but it makes it less likely that the setting of the $wire variable will be accidentally left behind after debugging is finished.
  18. Hi all, Just wanted to share a tip that can be useful if you want to debug a core file before Tracy has been loaded. Suppose you were debugging ProcessWire::getHttpHost() and for some reason wanted to dump the $host variable just before it is returned. If you add the line... bd($host, 'host'); ...then you'll get a fatal error when the code runs because Tracy has not yet been loaded and so the bd() function is undefined. When debugging core files you'll find a number of places like this where the Tracy dump functions are not available. A workaround for this is to set the variable that you want to dump as a custom property on the Wire object. You want to be careful not to use a property name that clashes with any existing Wire properties or API variables - adding a prefix like "td_" is a safe bet. $this->wire()->set('td_host', $host); Now in /site/ready.php you can dump the variable that you stored on the Wire object: bd($wire->td_host, 'host'); ...or shorter (thanks @adrian)... bd($td_host, 'host');
  19. $page->parents() can take a selector: foreach($page->parents('template!=myTemplate') as $item) { // ...
  20. Your site visitors would have to download two copies of every image if you do this server-side. These days a CSS filter is the way to go: .bw-image:hover { filter:grayscale(100%); } And who cares about IE (or use a polyfill). But if you're sure you want to do this in PW and set a destination filename... $is = new ImageSizer('/path/to/filename.ext'); $is->getEngine()->convertToGreyscale('/path/to/filename_new.ext');
  21. @bernhard's post gives you the clue - it's to do with PW's built-in caching. $page->children() is a method that queries the database. You want to minimise the number of requests to the database because going to the DB is a lot slower than working with objects in memory. In your code you call $page->children() five times, so the expectation is that this would mean five trips to the DB... except that PW tries to help you out and caches the results to avoid unnecessary DB queries. But the exact workings of this caching are undocumented (as far as I know) and so I'd say it's best practice not to rely on it. It would be better to consciously minimise the DB requests in your code - it would make things clearer (i.e. avoid the confusion you're getting from the behind-the-scenes caching) and it's a good habit to get into for when you're working with other PHP projects that might not cache DB query results like PW does. You could rewrite your code like this: $layout->setTemplate('sidebar'); $selector = [ 'template' => 'product', 'sort' => 'title', 'categories' => page('id'), 'limit' => 9 ]; // Just get the children from the DB once // I assume you need all the children at some point later in the code because you dump page()->children() in your example. // If you don't need all the children then just get the categories directly with page()->children('template=category') $children = page()->children(); // Get the categories from the children PageArray (happens in memory) $categories = $children->find('template=category'); // If there are any categories then modify $selector if($categories->count) { $categories->add(page()); $selector['categories'] = $categories; } bd($children); bd($categories); And this might be getting into the zone of micro-optimisation but you could consider if you actually need full Page objects in a PageArray or if you only need the IDs (reduces the memory footprint): $category_ids = page()->children('template=category', ['findIDs' => 1]);; if(count($category_ids)) { $category_ids[] = page()->id; $selector['categories'] = $category_ids; }
  22. Possible reasons... 1. Your /site/ready.php is missing this code: https://github.com/ryancramerdesign/regular/blob/master/site-regular/ready.php 2. The child pages you are looping over do not (all) use a template named "category". The hook code linked to above attaches a numPosts() method only to pages using the template "category".
  23. This doesn't make much sense to me because the guest role should always be the most restricted role in the site. Making a role more restricted than the guest role isn't effective because the user could just log out and then access the protected content.
  • Create New...