Search the Community

Showing results for tags 'hook'.

More search options

  • Search By Tags

    Type tags separated by commas.
  • Search By Author

Content Type


  • Welcome to ProcessWire
    • News & Announcements
    • Showcase
    • Wishlist & Roadmap
  • Community Support
    • Getting Started
    • Tutorials
    • FAQs
    • General Support
    • API & Templates
    • Modules/Plugins
    • Themes and Profiles
    • Multi-Language Support
    • Security
    • Jobs
  • Off Topic
    • Pub
    • Dev Talk


There are no results to display.

Found 55 results

  1. Hello, having trouble getting PW to save my user or field in cron hook. It seems to report the same field info each time unchanged. It should be counting down in seconds. public function init() { // set to every30Seconds in settings $this->defaultInterval = $this->cron_check; // add hooks to CRON $this->addHookAfter("LazyCron::{$this->defaultInterval}", $this, 'checkUserSubscription'); } public function ___checkUserSubscription(HookEvent $e){ // seconds since last lazycron $seconds = $e->arguments[0]; $log = wire('log'); $field = $this->exclusiveRole; // users with specific role and field $users = $this->users->find("roles=$field"); foreach ($users as $user) { // get stored time $currentTime = $user->get($this->fieldName); // if time not null if($currentTime){ // evalute stored time minus time past $resultTime = intval($currentTime) - intval($seconds); $log->message("result ".$resultTime); // save user page $user->set($this->fieldName, $resultTime); $this->users->save($user); } } }
  2. In a project I had to add the attribute 'disable' to some options of a select field (page reference) to show them but make them unselectable. Since I could not find an integrated solution, I wrote a tiny module and a hook. This could also be a POC to similar needs. Install module Add the Module to InputfieldPage in the module settings to make it selectable as Inputfield for page reference fields Create a hook in ready.php to manipulate attributes of the <option> tag for specified items Module <?php namespace ProcessWire; /** * POC Inputfield Select Hook Add Option -- Replacement for InputfieldSelect * * Selection of a single value from a select pulldown. Same like InputfieldSelect * except this version provides hookable addOption() function which allows to modify * attributes of the <option> tag (i. e. 'disabled' to show items but disallow to select them * * @author Christoph Thelen aka @kixe * */ class InputfieldSelectHookAddOption extends InputfieldSelect { /** * Return information about this module * */ public static function getModuleInfo() { return array( 'title' => __('Select Hookable Add Option', __FILE__), // Module Title 'summary' => __('Selection of a single value from a select pulldown. Same like InputfieldSelect. except this version provides hookable addOption() function which allows to modify attributes of the <option> tag (e.g. \'disabled\' to show items in dropdown but disallow to select', __FILE__), // Module Summary 'version' => 100, ); } /** * Hook in here to modify attributes */ public function ___addOptionAttributes($value, $label) { return array(); } /** * @see InputfieldSelect::addOption() * */ public function addOption($value, $label = null, array $attributes = null) { if (!is_array($attributes)) $attributes = array(); $attributes = array_merge($attributes, $this->addOptionAttributes($value, $label)); return parent::addOption($value, $label, $attributes); } } Hook /** * This example hook modifies the attributes of the selectable options of a Pagereference field named 'test'. * The selectable pages have the template 'test' assigned which includes a checkbox 'disallow'. * The attribute 'disabled' will be added to the selectable page if the user does not have the role 'user-extended' and 'disallow' is set. * */ $wire->addHookAfter('InputfieldSelectHookAddOption::addOptionAttributes', function($e) { // quick exit if ($e->object->name != 'test') return; if ($this->wire('user')->isSuperuser()|| $this->wire('user')->hasRole('user-extended')) return; // disable items (pages) in select $restrictedPageIDs = $this->wire('pages')->find('template=test,disallow=1')->each('id'); if (in_array($e->arguments[0], $restrictedPageIDs)) $e->return = array('disabled' => 'disabled'); });
  3. So I have a module that builds a dashboard (following the tutorial: It all works great now that I have gotten some kinks worked out. However, the page is saved under admin which is hidden from users that are not superusers. Is there a way to allow the user, with a certain role, to view this newly created page, and only this page?
  4. I was working on this: class PWCRM extends WireData implements Module { public static function getModuleInfo() { return array( 'title' => 'Client Relationship Management', 'version' => .001, 'singular' => true, 'autoload' => true ); } public function init() {} public function ready() { $this->pages->addHookBefore('render', $this, 'accessHook'); $this->pages->addHookAfter('render', $this, 'hookAfterPageRender'); } public function accessHook(HookEvent $event) { $page = $this->wire('page'); if (!strpos($page->template->tags, 'crm')) return; if (!$this->wire('user')->hasRole('crm')) $this->wire('session')->redirect($this->wire('config')->urls->login);//throw new Wire404Exception(); } public function hookAfterPageRender(HookEvent $event) { $page = $event->object; echo $page->template->tags; if (!strpos($page->template->tags, 'crm')) return; echo $this->wire('config')->urls->templates; include_once($this->wire('config')->urls->templates.''); $pagehtml = $event->return; $pagehtml = str_replace( '</head>', '<link id="css_crm" rel="stylesheet" href="'.$this->wire('config')->urls->templates.'css/crm.css"> </head>', $pagehtml ); $event->return = $pagehtml; //$event->replace = true; } } I have tried placing the hooks into the init() function, and more... Neither method is effective. The echoes now output, but no redirection (although I have the access settings for the top-level template for this set to render a 404 for underprivileged users, which it does, overriding this, but nonetheless this should work aside from that. Then I wrote this up quick: <?php namespace ProcessWire; class MaintenanceMode extends WireData implements Module { public static function getModuleInfo() { return array( 'title' => 'Maintenance Mode', 'version' => 1, 'summary' => 'Disables the website frontend for non-superusers.', 'singular' => true, 'autoload' => true, 'permanent' => false ); } public function init() { $this->addHookBefore('Page::render', $this, 'displayDecide'); } public function displayDecide($event) { $page = $event->object; if ($page->template == 'admin' || $this->wire('user')->hasRole('superuser')) return; // replace the method hooked $event->replace = true; $event->return = "Patience please while we undergo some brief maintenance work."; } } which likewise avails nothing. What the hell is my problem here?
  5. Hi all, Im trying to fill an options field in all the children of the parent page, after I save it. the options field is configured as multiple select checkboxes. here's the code i have so far: $this->addHookAfter('Pages::saved', function($event) { $page = $event->arguments[0]; //set the page if($page->template == 'sport-verenigingen-overzicht') { //get the subcategories from the parent textarea, split on newline $subcats = preg_split('/[\n\r]+/', $page->subcats); //(also tried without imploding and adding the array, also doesnt work) $subcats = implode("|",$subcats); //get the children $children = $page->children(); foreach ($children as $child) { //set the options(sport_categorie is the options field) $child->sport_categorie = $subcats; $child->save('sport_categorie'); } //if i use a normal textfield instead of an optionsfield, //all the children have the correct data e.g: test1|test2|test3 //how to get the values into the options field?? } }); Hope you guys can help! Keep up the good work, I'm loving what you're doing with PW!!
  6. Hi there, I'm trying to limit a specific user can only add pages as a child (under) a page created by themselves. The discussion in this thread gets close, it's a working solution on how to only allow editing on pages you created yourself. I'm using this and it works well. But I'm not sure how to modify this for my purposes. I'm suspecting I need to do to something like $this->addHookBefore("Page::added", $this, 'added'); then in "added" check if parent is created by the current user. But I'm a bit lost on how exactly to do this. thank you! /J
  7. I'm trying to add a new option to InputfieldTextarea. Depending on that option, I want to change how the input is rendered. I also want to change this option depending on different templates and repeaters, meaning it can have different values for different fieldgroups. I hooked into three methods: $this->addHookBefore('InputfieldTextarea::render', $this, 'hookInputRender'); $this->addHookAfter('InputfieldTextarea::getConfigInputfields', $this, 'hookInputSettings'); $this->addHookAfter('InputfieldTextarea::getConfigAllowContext', $this, 'hookInputContext'); In hookInputSettings, I build the additional option protected function hookInputSettings(HookEvent $e) { /** @var InputfieldTextarea $field */ $wrapper = $e->return; $field = $e->object; /** @var InputfieldSelect $font */ $font = $this->modules->get('InputfieldSelect'); $font->label = $this->_('Font'); $font->name = 'fontFamily'; $font->addOptions(self::fontOptions); $font->attr('value', $field->fontFamily); $wrapper->add($font); $e->return = $wrapper; } It shows up in field settings with no problem When I pick an option and save, it even shows up in the database. However, I cannot get the properties of that field in that fieldgroup context. Most other inputfields can get their inputfield settings because are inside a class that extends Inputfield, so $this->myOption works. If I hook into FieldtypeTextarea::getConfigInputfields, it works too, because getConfigInputfields method is called with $this as its argument, inside hooks it's possible to access fieldgroup specific settings. But for Inputfield, it's not given any arguments, so hooking Inputfield::getConfigInputfields, you won't be able to get any information about the context. // /wire/core/Field.php public function ___getConfigInputfields() { // ... if(!$fieldgroupContext || count($allowContext)) { // ... try { $fieldtypeInputfields = $this->type->getConfigInputfields($this); // ... } // ... } $inputfields = $this->wire(new InputfieldWrapper()); // ... if($inputfield) { if($fieldgroupContext) { $allowContext = array('visibility', 'collapsed', 'columnWidth', 'required', 'requiredIf', 'showIf'); $allowContext = array_merge($allowContext, $inputfield->getConfigAllowContext($this)); } // ... $inputfieldInputfields = $inputfield->getConfigInputfields(); // ... } // ... } So, as a solution I gave it $this as a parameter // $inputfieldInputfields = $inputfield->getConfigInputfields(); $inputfieldInputfields = $inputfield->getConfigInputfields($this); Now everything works without any hacks. It works in field settings, templates, repeaters just fine. protected function hookInputSettings(HookEvent $e) { // ... $field = $e->arguments(0); // ... $font->attr('value', $field->fontFamily); // WORKS! // ... } I wanted to write this post because it drove me mad last night. I guess the next step is to make a pull request.
  8. Hi PW fanatics In this post I share two of my addHookMethods for those interested. As you surely already know (if not, time to take a look at it) the Wire::addHookMethod() and the Wire::addHookProperty() API methods can be used to "breath some extra OOP" into your projects. Using addHookMethods and addHookProperty are alternatives to "Using custom page types in ProcessWire". The methods I want to share: basically the idea here is to get the URL pointing to images uploaded in the admin without writing much code in the template files. With methods like these below, it does not matter what Formatted value is set to the images, because some predefined defaults are used in all circumstances. #1 Example template file code: <?php $img_src = $latest_article->siteFeaturedImage(); ?> <img src="<?= $img_src ?>" alt="<?= $page->title ?>"> addHookMethod goes into /site/init.php <?php /* Returns URL of the original Pageimage of Article. * Image field's value can be either null (default missing image), Pageimage or Pageimages. * * @return string */ $wire->addHookMethod('Page::siteFeaturedImage', function($event) { $page = $event->object; if ($page->template != "article") { throw new WireException("Page::siteFeaturedImage() only works on 'Pages of article template', Page ID=$page is not such!"); } $article_featured = $page->getUnformatted('article_featured'); //always a Pageimages array if (count($article_featured)) { $img_url = $article_featured->first()->url; } else { $img_url = urls()->templates . "assets/img/missing-article_image.jpg"; //we show this when image is not available } $event->return = $img_url; }); ?> #2 Example template file code: <?php $img600_src = $page->siteProductImageMaxSize(600, 600, ['rotate' => 180]); ?> <img src="<?= $img600_src ?>" alt="<?= $page->title ?>"> addHookMethod goes into /site/init.php <?php /* Generates image variations for Product images. Returns URL of Pageimage. * Image field's value can be either null (default missing image), Pageimage or Pageimages. * * @param int arguments[0] Max allowed width * @param int arguments[1] Max allowed height * @param array arguments[2] See `Pageimage::size()` method for options * @return string */ $wire->addHookMethod('Page::siteProductImageMaxSize', function($event) { $page = $event->object; if ($page->template != "product") { throw new WireException("Page::siteProductImageMaxSize() only works on 'Pages of product template', Page ID=$page is not such!"); } $width = isset($event->arguments[0]) ? $event->arguments[0] : 48; //default width $height = isset($event->arguments[1]) ? $event->arguments[1] : 48; //default height $options = isset($event->arguments[2]) ? $event->arguments[2] : $options = array(); //default empty options $product_image = $page->getUnformatted('product_image'); //always a Pageimages array if (count($product_image)) { $img_url = $product_image->first()->maxSize($width, $height, $options)->url; } else { $img_url = urls()->templates . "assets/img/product-missing-image.jpg"; //we show this when image is not available } $event->return = $img_url; }); ?> BTW, you can find more examples here: How can I add a new method via a hook? Working with custom utility hooks Adding array_chunk support to WireArray addHookProperty() versus addHookMethod() Have a nice weekend!
  9. Hi community, i want to add a selector to every pages->find() method. I found this hook solution, and Ryan mentioned this somewhere in this forum. $this->addHookBefore('Pages::find', function(HookEvent $event) { // Get the object the event occurred on, if needed $pages = $event->object; // Get values of arguments sent to hook (and optionally modify them) $selector = $event->arguments(0); $options = $event->arguments(1); /* Your code here, perhaps modifying arguments */ // Populate back arguments (if you have modified them) $event->arguments(0, $selector); $event->arguments(1, $options); }); If i try to add something to the given $selector, the error occurs: Exception: Unknown Selector operator: '' -- was your selector value properly escaped? But the syntax is right, isn´t it? $this->addHookBefore('Pages::find', function(HookEvent $event) { // Get the object the event occurred on, if needed $pages = $event->object; // Get values of arguments sent to hook (and optionally modify them) $selector = $event->arguments(0); $options = $event->arguments(1); /* Your code here, perhaps modifying arguments */ $selector.= ", loremipsum_field!=1"; /* <----------------------- */ // Populate back arguments (if you have modified them) $event->arguments(0, $selector); $event->arguments(1, $options); }); What i am doing wrong? Thank you for your advice!
  10. Hello, I read about conditional hooks and wanted to utilize them. In the process of trying to implement them I found that they do not get called. So I reduced my hook to a minimum wire()->addHookAfter('Page::changed', function($event) { die('changed'); }); And nothing happens at all. Also with Page::changed(title) or Page(template=basic-page)::changed(title) no luck. In the code comment in Wire.php it says: "Hookable method that is called whenever a property has changed while change tracking is enabled" I see that change tracking is enabled as wire()->addHookAfter('Pages::saveReady', function($event) { if($event->arguments[0]->isChanged('title')) die('changed'); }); is working. The hookable method ___changed() in Wire.php is empty. I tried this on 2 different installs PW 3.0.61 and 3.0.62 Can anyone please confirm or let me know if I'm doing anything wrong here. Thank you.
  11. So I discovered in this topic ( ) that I can cancel all hooks after my own hook. Now I want something like that. I want my hook which is called on page render to cancel all other events, also the after page render and the before page render methods, is this possible? This only need to be done when some conditions are met. /** method replaces original page::render method and is called with hook priority one */ method onPageRender (HookEvent $event) { if (my condition is true) { $this->cancelHooks = true; // to cancel all hooks to page::render // how to cancel after Page::render events // how to cancel before Page::render events } } Is this possible at all?
  12. I've written a hook which replaces the page::render method. Based on a few conditions, I might want to output something different from what page::render would return. So when my conditions aren't met, I want to use the return value of the original page::render method. How can I do this? At the moment I've got something like this: function pageRenderHookMethod (HookEvent $event) { if ('my condition' == true) { $event->replace = true; $event->return = 'my custom return value'; } else { $event->return = 'original return value of page::render'; } } But I don't know how to get the original return value of page::render because the would trigger my hooked method instead of the original method.
  13. I have created a hook with priority one because I want it to run asap. Now I want this same hook to prevent all other hooks from running, is this possible, if so, how can I achieve that? For example, normally hooks would run like this: hook 1 -> hook 2 -> hook 3 -> hook 4 -> etc. Now I want it like this: hook 1 -> hook 2 -> hook 3 -> hook 4 -> etc.
  14. Hello, I am still learning ProcessWire. I am trying to hook a method in ListProConfig.php. After the processInput method is called I would like to know the user id of the person that called the method, the page name that was involved in changed lister settings, and then get the new settings. I am having problems getting my hook to work. In the init of my module I have the following code: wire()->addHook("ListerProConfig::processInput", function($event){ $this->wire('log')->save('stephen_ext',"Someone called processInput"); }); Even though I know that processInput is called I never get anything written to my log.
  15. Greetings to all processwire fans, I am new in processwire and I have used it since 3 weeks. Probably it's a really silly question but does someone now how I can execute a function in my own module, which is triggered when I save a pages, which contains a user-defined template. I tried to to this with an basic if/else condition to trigger the hook when the page has theTemplateName== "". Unfortunately it doesn't work. So I try this which might be the wrong Syntax. Perhaps someone can give me a hint THANKS a lot! public function init() { // add a hook after the $pages->save, to issue a notice every time a page is saved $this->page->template == "templateName"->addHookAfter('save', $this, 'example1'); }
  16. I think you can create a simple logout link with <a href="admin/login/logout">log out</a> But it redirects to the login form in the admin area. Can I hook into logout and change the redirect? Default redirect home would make sense. Or is the way to do this still to create a logout template + page with session->logout() and a redirect?
  17. I have a hook to change the template file on a certain page. This is not working at the moment for some reason. The usual location to place templates is under /site/template. Because the template should only be available in my module, I want my template file to be in /site/modules/mymodule/view/mytemplate.php When I place my file in the usual template location, it works fine. But when I place the file in my module folder, it doesn't work. When I var_dump the $page->template->filename variable, the location of the template file is correct and maps to my module folder. So everything seems to be correct, but somehow it's not working but I can't figure out the problem. Does anyone know how to solve this?
  18. How can I change the output of `Page::render`? I've created a hook before page::render, but when I set the $event->return to something else, my whole page is replaced with that value. For example: public function beforePageRender(HookEvent $event) { $event->return = 'blaat'; } This will cause my whole page to be nothing more than just 'blaat'. What I want, is that my menu, footer etc. are still visible but only the content of that page is replaced.
  19. Hi, I have a method (___renderImage) which renders an image tag (<img src) and has a single argument: Pageimage $image. Now I have a hook called "beforeRenderImage" in which I'd like to add a property to the argument of ___renderImage. So for example, I'd like to add a property "requiredDimension" to the argument before ___renderImage is called. Is this possible?
  20. I've added a hook after the '"ProcessPageEdit::buildFormContent" event. I've added a new config option to the language settings: public function beforeAdminProcessPageEditBuildFormContent (HookEvent $event) { $editPage = $this->getPage(wire('input')->get('id')); if ($editPage->template->name == 'language') { // only add field when editing language page $field = wire('modules')->get('InputfieldText'); $field->attr('name+id', 'locale'); $field->label = __('Locale'); $event->return->insertAfter($field, $event->return->getChildByName('title')); } } I've also created a field (Setup > Fields > Add new) which I've also named 'locale'. The field is displayed, but the value isn't saved when I click the save button. How do I make sure the input of the field is saved as well? And how can I access the stored value once it's saved?
  21. Hello, I am currently playing around to build my first module. It will be a simple module for the ImageOptim web service, but I am a little bit stuck on which right hook to use. Currently I use following hook: $this->pages->addHookAfter('saveFieldReady', $this, 'imageOptimSave'); I would like to pass images and its variations to the web service after adding them to the image field. But if I use the saveFieldReady hook only the original image will be optimized, not the API generated image variations, because they will be generated after viewing the page for the first time. Can anybody please help me how to hook into the image variations? I already tried to use my own method, but this one used in the template would be called on every page render. Regards, Andreas
  22. Hello, for quite a while I found it quite annoying that when you edit a page from a lister view and then save+exit you will end up at the page tree and not at the lister view where you came from. I haven't found a setting that lets you return to the lister view. I wrote a little hook that does just that for a project where I am using Lister Pro. The lister is called Events and has a fixed url. It lists only one type of pages with template event. Here's the working hook code that I placed in admin.php: // redirect to events list on save+exit wire()->addHookBefore('ProcessPageEdit::processSaveRedirect', function($event) { $id = (int) $this->input->post('id'); $page = wire('pages')->get($id); if($this->input->post('submit_save') == 'exit' && $page->template->name == 'event' && wire('user')->hasRole('member')) $this->session->redirect(wire('config')->urls->admin . 'events/'); }); Now I would like to make this more generic so that it works for any lister. How can I get the referring URL (other than from $_SERVER['HTTP_REFERER']) to use it instead of the hardcoded URL I have now in the redirect? And is there any way that I can access properties of the instance of ProcessPageEdit that called processSaveRedirect? The $event->object is the processSaveRedirect method and $this is ProcessWire. How can I access properties of ProcessPageEdit? E.g. $id or $page. ATM I am getting the page id from the $input->post. Obviously I am not a savvy PHP OOP dev and have no idea how to do such things in a proper way EDIT: I know I could open pages from the lister view in a modal to avoid having to redirect. But I don't want to use that option. $_SERVER['HTTP_REFERER'] gives me the URL of the page that I edited and not the URL of the lister.
  23. Hello, I'm trying to hide a specific field with a hook. This is what I tried so far. Changing the field label works but the hiding not. Changing addHookBefore to addHookAfter makes no difference. I searched the forum and found similar thread but could not translate the answer to this situation. Any help would be appreciated. class HideFields extends WireData implements Module { public static function getModuleInfo() { return array( 'title' => 'Hide Fields', 'version' => 100, 'summary' => 'Hide fields', 'singular' => true, 'autoload' => "template=admin" ); } public function init() { $this->addHookBefore('Inputfield::render', $this, 'setHide'); } public function setHide($event) { $inputfield = $event->object; if($inputfield->name != "Foo") return; $inputfield->label = "Bar"; // This works $inputfield->collapsed = Inputfield::collapsedHidden; // This doesn't work } }
  24. How would one pass a variable set in one module to another module via a Hook? e.g. module 1. public function ___saveUser($vars){ $userSaved = true } module 2 public function init() { $this->addHookAfter('module1::saveUser', $this, 'userSaved'); } public function userSaved($e){ $userSaved = $e->userSaved; return $userSaved; // true? }
  25. Hey, I made a hook that is triggered when a page with a certain template is saved. I meant to create the script only for the backend of the website. Now, whenever a page is saved on the front end (with the API) the module is being triggered. I was wondering if there is a method to have it only trigger whenever a page is saved on the backend (so not through the API). Jim