Jump to content

Robin S

  • Posts

  • Joined

  • Days Won


Robin S last won the day on June 13

Robin S had the most liked content!

Profile Information

  • Gender
  • Location
    New Zealand

Recent Profile Visitors

The recent visitors block is disabled and is not being shown to other users.

Robin S's Achievements

Hero Member

Hero Member (6/6)




Community Answers

  1. I didn't study your post in detail, but maybe this gives you an idea: $wire->addHookBefore('InputfieldText::render', function(HookEvent $event) { /** @var InputfieldText $inputfield */ $inputfield = $event->object; // The Field object associated with the inputfield, so the name isn't affected by any repeater suffix $field = $inputfield->hasField; // The Page that the inputfield is in so you can check its template // to see if it belongs to the relevant repeater field $page = $inputfield->hasPage; if(!$field || !$page) return; if($field->name === 'text_1' && $page->template == 'repeater_test_repeater') { $inputfield->appendMarkup('hello'); } });
  2. For the title field you can enable access control in template context to limit editability by role. For deletion you can revoke the delete permission per template per role. For the settings tab there is a $template->noSettings property: https://github.com/processwire/processwire/blob/38a5320f612a4b38a7353265343219f224f20e6d/wire/core/Template.php#L100 You can conditionally set this with a hook for non-superusers: $wire->addHookBefore('ProcessPageEdit::execute', function(HookEvent $event) { /** @var ProcessPageEdit $ppe */ $ppe = $event->object; /** @var Page $page */ $page = $ppe->getPage(); if($page->template == 'my_template' && !$event->wire()->user->isSuperuser()) { $page->template->noSettings = 1; } });
  3. Check the files in the folder at: /wire/modules/Inputfield/InputfieldDatetime/types/ It sounds like might you have a file named "._InputfieldDatetimeText.php" in there. That file should not exist. There should only be the three files shown here:
  4. You could try the latest dev (3.0.239) to see if it's an issue that has been fixed since 3.0.229 was released. If it's still present in the latest dev then please open a GitHub issue so Ryan can investigate.
  5. System templates have the Template::flagSystem flag. So the "proper" way: $non_system_templates = new TemplatesArray(); foreach($templates as $template) { // Skip templates with the system flag if($template->flags & Template::flagSystem) continue; $non_system_templates->add($template); } The lazy way that is likely to work 99.9% of the time: $non_system_templates = $templates->find("flags=0"); For some reason templates that are used for the custom fields for files/images feature don't have the system flag, so you will have to exclude those separately if you have any. The name of such templates starts with "field-".
  6. I don't know for sure but it looks like a problem with your Imagick configuration or file permissions. The module won't be able to solve that but if you update to the newly released v0.2.2 there is an option in the module config where you can choose to use GD for the conversion instead.
  7. I do it essentially the same as what @TomPich said, but on the first move from local to remote I find it's a lot faster and more reliable to compress all the website files to a ZIP archive, upload that to the remote server, then extract it on the server. If you're using cPanel then the included File Manager is a convenient way to upload and extract. And when using a host that doesn't include a file manager I like to use TinyFileManager, although you need to take due care with security - as extra protection I rename the containing folder to include a dot prefix to prevent access when I'm not actively using it.
  8. @mel47, currently the PW core does not support showIf or requiredIf in custom fields for files/images. See this issue: https://github.com/processwire/processwire-issues/issues/1889 And even if that issue is resolved, the way the core is handling showIf/requiredIf at the moment means that it will only evaluate the showIf/requiredIf based on values of other custom fields for the image/file item, not fields in the page that is open in Page Edit. But I've just updated the CustomInputfieldDependencies module so that it should handle your case. Please update the module to v0.3.0 and test it again.
  9. When $config->debug and $config->advanced are true there is an "Autoload disabled" checkbox available in the module info for any autoload module. Checking this box disables the module in the same way as Tracy's Module Disabler panel, but might be useful on a site that doesn't have Tracy installed.
  10. For a case like this you can use the hookable method to return any markup you like, including an image. It won't work for a UIkit tooltip though because that only supports text. Example: $wire->addHookAfter('PageFieldInfo::getPageInfo', function(HookEvent $event) { $page = $event->arguments(0); // The page $inputfield = $event->arguments(1); // InputfieldPage $field = $event->arguments(2); // The Page Reference field // Return custom markup if($field->name === 'colour') { $image = $page->get('image[0]'); if($image) $event->return = "<img src='$image->url' alt='$image->description' style='max-width:200px; max-height:200px; margin-top:10px;'>"; } });
  11. Ryan said in the previous announcement that you can use a hook to set which pages become editable. So you could use this to make the grandchildren editable, or the children and the grandchildren if you wanted the child pages to serve as a kind of visual divider between the categories of options. Edit: example... // Define custom "children" for PageEditChildren $wire->addHookAfter('PageEditChildren::getChildren', function(HookEvent $event) { /** @var Page $page */ $page = $event->arguments(0); if($page->template == 'blank') { $items = new PageArray(); foreach($page->children as $child) { $items->add($child); foreach($child->children as $grandchild) { $items->add($grandchild); } } $event->return = $items; } }); // Hook rendering of PageEditChildren "child" fieldsets // to apply a data attribute for identifying the template // It would be cool if PageEditChildren did this by default $wire->addHookBefore('InputfieldFieldset::render', function(HookEvent $event) { /* @var $fieldset InputfieldFieldset */ $fieldset = $event->object; $wrap_class = $fieldset->wrapClass(); if($wrap_class !== 'PageEditChild') return; $attr = $fieldset->wrapAttr(); if(!isset($attr['data-page'])) return; $p = $event->wire()->pages->get($attr['data-page']); if(!$p->id) return; $fieldset->wrapAttr('data-template', $p->template->name); }); Custom admin SCSS: li.PageEditChild[data-template="references"] { > .InputfieldHeader { background-color:#f0f3f7 !important; } }
  12. Since ProcessWire v3.0.152 we have been able to use custom Page classes: https://processwire.com/blog/posts/pw-3.0.152/#new-ability-to-specify-custom-page-classes Some PW users have said that they would like to have all their hooks relating to a particular Page class contained within their custom Page class file (in /site/classes/), to keep things tidy and organised. But custom Page classes do not have methods that fire on states like "init" or "ready", and it also wouldn't be ideal to attach hooks within a Page class because the class can be instantiated multiple times and therefore such hooks would be attached multiple times. I understand @bernhard has a feature that addresses this need built into his RockMigrations module, so check that out. And here's another approach, where hooks are attached in the places where you would normally attach them (e.g. in /site/ready.php or /site/init.php, or in the init() or ready() methods of some custom module) but the method that executes in the hook exists within your custom Page classes. Step 1 In /site/classes/DefaultPage.php, add the method shown below: class DefaultPage extends Page { // Call any Page methods with names that match the HookEvent object and method public function callHookMethods(HookEvent $event) { $objectName = $event->object->className; $methodName = $objectName . '_' . $event->method; if(!method_exists($this, $methodName)) return; $this->$methodName($event); } } This method looks for other Page method names that match the HookEvent object and method and if any exist it calls them. Hooks are attached using the format "Class::method" and this format wouldn't be valid for a method name, so an underscore is used instead of the two colons. E.g. "ProcessPageEdit::buildFormContent" would become "ProcessPageEdit_buildFormContent". Step 2 In any of your custom Page class files, add methods named to match the hookable methods you want to target. These custom Page classes should extend DefaultPage. In the example below I'm targeting hookable methods Pages::saveReady and ProcessPageEdit::buildFormContent in the BasicPagePage class. class BasicPagePage extends DefaultPage { public function Pages_saveReady(HookEvent $event) { // Show a message in the PW admin $this->wire()->message("About to save page named: $this->name"); } public function ProcessPageEdit_buildFormContent(HookEvent $event) { /** @var InputfieldWrapper $wrapper */ $wrapper = $event->return; // Add a custom markup field to Page Edit /** @var InputfieldMarkup $f */ $f = $this->wire()->modules->get('InputfieldMarkup'); $f->label = 'My custom markup'; $f->value = 'Hello!'; $wrapper->insertAfter($f, 'title'); } } Step 3 Attach hooks in the places where you normally would. You need to attach a hook for each hookable method you are targeting in your custom Page classes, but the hook code itself is minimal and where multiple Page classes target the same hookable method you only need it attach it once. In the example below I'm attaching hooks in /site/ready.php. $pages->addHookAfter('saveReady', function(HookEvent $event) { /** @var DefaultPage $page */ $page = $event->arguments(0); if($page instanceof DefaultPage) $page->callHookMethods($event); }); $wire->addHookAfter('ProcessPageEdit::buildFormContent', function(HookEvent $event) { /** @var ProcessPageEdit $ppe */ $ppe = $event->object; /** @var DefaultPage $page */ $page = $ppe->getPage(); if($page instanceof DefaultPage) $page->callHookMethods($event); }); Each hook only need to establish a $page object (often this is available as an argument to the hookable method) and if it's an instance of DefaultPage then it simply calls $page->callHookMethods($event), and any relevant hook-targeting methods for that particular Page class will fire. Here's the result of my two hook-targeting methods in BasicPagePage.php when I save a page of this class in Page Edit:
  13. @ryan, that sounds great, thanks!
  • Create New...