Jump to content

Search the Community

Showing results for tags 'hooks'.

  • Search By Tags

    Type tags separated by commas.
  • Search By Author

Content Type


Forums

  • 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

Product Groups

  • Form Builder
  • ProFields
  • ProCache
  • ProMailer
  • Login Register Pro
  • ProDrafts
  • ListerPro
  • ProDevTools
  • Likes
  • Custom Development

Find results in...

Find results that contain...


Date Created

  • Start

    End


Last Updated

  • Start

    End


Filter by number of...

Joined

  • Start

    End


Group


AIM


MSN


Website URL


ICQ


Yahoo


Jabber


Skype


Location


Interests

  1. Hi, I was wondering if it is possible to hook some logic into the output of a certain field. System wide, front- and backend. I'm thinking TextFormatters. What I want for example is to: echo $page->some_fancy_field; And in the background it is making some very individual calculations and other fancy stuff with other fields of that same $page. The field itself holds no actual value. Possible?
  2. Hello, The Hook API documentation is great in explaining how hooks work. I wanted to know if it's possible to add a method or property to a Page, but pages only of a specific template type. The reasoning behind this would be certain methods or properties would only apply to specific template types. Possible? Thank you.
  3. Hi, I've created a simple module that does the following: Checks if a checkbox is ticked ('media_wall_quote_hero') on a page using the template 'media_wall_quote'. If that checkbox is ticked, it adds that page to a PageTable field ('quotes_hero') located on the 'home' template. If it's not checked and the page is in the PageTable field it is removed. It all works correctly when checking/unchecking the box on pages using the 'media_wall_quote' template in admin. However, if I edit the pages in the PageTable field itself on the homepage in admin, when I save the modal, the PageTable field is not updated. Strangely if I uncheck it (ie. when it should be removed) the PageTable field says 'item added'. Is there a way I can hook into the PageTable field when the modal is saved and update it so if I check/uncheck the box it does the correct action? public function init() { $this->pages->addHookAfter('save', $this, 'AddRemoveHeroQuotes'); } public function AddRemoveHeroQuotes($event) { $page = $event->arguments(0); if($page->template == 'media_wall_quote') { $home = wire('pages')->get(1); $home->of(false); $work_page = wire('pages')->get("template=work, media_wall_work=$page"); // If this quote is a (published) hero quote add it to the pagetable field if($page->media_wall_quote_hero == 1 && !$page->is(Page::statusUnpublished)) { if(!$home->quotes_hero->has($page)) { $home->quotes_hero->add($page); } } // If this quote is a not a hero quote or is unpublished remove if from the pagetable field elseif($page->template == 'media_wall_quote' && $page->media_wall_quote_hero == 0 || $page->template == 'media_wall_quote' && $page->is(Page::statusUnpublished)) { if($home->quotes_hero->has($page)) { $home->quotes_hero->remove($page); $this->message('removed'); } } $home->save('quotes_hero'); } }
  4. For some reason when I unpublish an already-published page, even of a template other than the specified 'importer', all its fields are cleared on page render. How do I understand and remedy this? Peace & thanks public function init() { $this->addHookAfter('Page::render', $this, 'renderEditor'); } protected function renderEditor(HookEvent $event) { $here = $event->object; $page = $this->pages->get($this->input->get->id); //$this->log->message($page->template.$here->process); return; if ($here->process != 'ProcessPageEdit' && $page->template != 'importer') return; $css = $this->config->urls->ProcessImportAll . 'ass/ProcessPageEdit_importer.css'; $event->return = str_replace("</head>", "<link rel='stylesheet' type='text/css' href='{$css}'/>\n</head>", $event->return); $field = wire('fields')->get('name=pi_template'); if (count($field->templateTypes)>0) { $templates = $field->templateTypes; } else { $templates = []; foreach (wire('templates') as $tpl) $templates[] = $tpl->id; } sort($templates); //$tplTypes = json_encode($templates); $templatesFields = $this->getTemplatesFields($templates); $templatesFields = json_encode($templatesFields); $js = <<<EOT <script> $(document).ready(function(){ if (!document.getElementById('Inputfield_status_2048').checked) { $('#ProcessPageEditContent *').prop('disabled',true); } else { var all = $templatesFields; var sel = '#Inputfield_pi_template option[selected="selected"]'; var tpl = getTpl(); var arr = all[tpl]; var def = '<option value=""></option>'; $('#Inputfield_pi_match').prepend(def); filterFields(tpl); $('#wrap_Inputfield_pi_template .asmListItem .asmListItemRemove').click(clearFieldOptions); $('#Inputfield_pi_template').change(function() { var on = $(this).find('option[selected="selected"]')[0]; if (on !== undefined) { tpl = on.value; //console.log('clicked ' + tpl); filterFields(tpl); } else { tpl = null; clearFieldOptions(); } }); function filterFields(t) { if (t != null) { $('#Inputfield_pi_match').prop('disabled',false); arr = all[t]; //console.log(arr); $('#Inputfield_pi_match option').each(templateFieldOptions); $('#wrap_Inputfield_pi_fieldmap select option').each(templateFieldOptions); $('#_Inputfield_pi_maptab').click(function() { //$('#wrap_Inputfield_iu_fieldmap select option').each(templateFieldOptions); }); } else { clearFieldOptions(); } } function getTpl() { if ($(sel).length>0 && $(sel)[0].value) { var tpl = $(sel)[0].value; } else { var tpl = null; } return tpl; } function templateFieldOptions() { var val = parseInt(this.value); if (!arr.includes(val) && val>0) { //console.log(val + ' ' + arr); $(this).prop('selected',false); $(this).prop('disabled',true); } else { if (arr.includes(val) && val>0) { //console.log(tpl); $(this).prop('disabled',false); } } } function clearFieldOptions() { $('#Inputfield_pi_match').find('option[value=""]').first().prop('selected',true); $('#Inputfield_pi_match').find('option[value!=""]').each(function() { $(this).prop('disabled',true); }); $('#Inputfield_pi_match').prop('disabled',true); $('#wrap_Inputfield_pi_fieldmap select').find('option[value=""]').first().prop('selected',true); $('#wrap_Inputfield_pi_fieldmap select').find('option[value!=""]').each(function() { $(this).prop('disabled',true); }); $('#wrap_Inputfield_pi_fieldmap select').prop('disabled',true); } } }); </script> EOT; $event->return = str_replace("</body>", "$js</body>", $event->return); //$this->filterFieldFields($event); }
  5. I have a module with 'autoload' => 'template=admin'. I need to hook into ProcessPageEdit for editing template=importupdate, and within my hook function add CSS and JS files. I have: public function init() { $this->addHookAfter('ProcessPageEdit::execute', $this, 'addlStyles'); } private function addlStyles(HookEvent $event) { //$page = $event->arguments(0); if($page->template != 'importupdate') return; $css = wire('config')->urls->modules . 'ImportUpdateUltimate/editImportUpdate.css'; $this->config->styles->add($css); } which does nothing.
  6. Hi, I'm about to implement a multisite project with PW3 (which is great btw!!!). Because of "reasons" I need to implement my own routing. To do this I implemented a little module the hooks ProcessPageView::execute(). I reviewed its code and found out, that the actual logic to look-up the requested page from the request is placed in a protected method ProcessPageView::getPage(). And because this method is currently not hookable, I needed to do a dirty hack (overriding the GET.it parameter that is inspected by ProcessPageView::getPage()). I suggest making ProcessPageView::getPage() hookable and pass the arguments for the page look-up via method arguments instead of inspecting the GET scope within the method.
  7. Hi fellows I have a problem with one of my hooks in processwire 3. It's a hook which manipulates the processpagelist to only show the pages which are not editable and not addable. This works fine in 2.7.3 but in pw 3 it doesn't work 100%. When the first time the ProcessPageList is rendered the hook works. Now when I open a branch and reload then it shows all pages. but when i close the branch before reload it works again and only shows the pages which are editable or addable. How it should look like: How it looks when i let the branch open and reload: PHP-Code $this->addHookAfter('ProcessPageList::execute', $this, 'hidePages'); public function hidePages(HookEvent $event){ $excludePages = new PageArray(); $the_pages = wire('pages')->find("template=newsletter-clinic|sender_2016|sender_2016_collab|inside-news-folder|event-clinic"); foreach ($the_pages as $the_page) { if(!$the_page->editable() && !$the_page->addable()) { $excludePages->add($the_page); } } $hidden = explode('|', $excludePages); if($this->config->ajax){ // manipulate the json returned and remove any pages found from array $json = json_decode($event->return, true); foreach($json['children'] as $key => $child){ if(in_array($child['id'],$hidden)) unset($json['children'][$key]); } $json['children'] = array_values($json['children']); $event->return = json_encode($json); } } Do you perhaps know what causes this and how to fix this?
  8. Hi, I'm trying to add a hook to lazycron in my module that finds all pages with a checkbox and then sets less the seconds passed to another field, but as yet have seen anything happen. public function init() { $this->checkboxName = "pdp_pub_later_check"; $this->fieldName = "pdp_pub_later"; $this->addHook("LazyCron::everyMinute", $this, 'publishDefferedPages'); } public function ___publishDefferedPages(HookEvent $e){ // seconds since last lazycron $seconds = $e->arguments[0]; // find all pages with deffered field $defferedPages = $this->pages->find("{$this->checkboxName}=true"); // for each page decrease time for deffered field foreach ($defferedPages as $page) { // get current page time $timeTillPublish = $page->get($this->fieldName); // set time to time minus time past $timeLeft = $timeTillPublish - $seconds; // if time passed 0 or less then publish page $page->of(false); if($timeLeft <= 0){ // remove flags and save $this->publish(); $page->set($this->fieldName, 0); }else{ $page->set($this->fieldName, $timeLeft); } $page->Save(); $page->of(true); } }
  9. I'm creating a simple module for hooks, but have run into a small problem. The hook is basically to keep two fields in sync. I have two templates "template1" and "template2" each with a Page Field that references the other. So a page using "template1" has a Page Field that contains multiple pages using "template2", and a page using "template2" has a Page Field that contains multiple pages using "template1". I'm hooking Pages::saveReady to detect any pages added/removed from the Page Field on either of these templates, and then adding/removing the relevant pages from the other's Page Field. However as each hook saves other pages before it saves itself, I assume this will create some kind of loop? The actual code is more complex, but I've tried to give some example code below: public function init() { $this->addHookBefore('Pages::saveReady', $this, 'save'); } public function save($event) { $page = $event->arguments[0]; if ($page->template->name == "template1" || $page->template->name == "template2") { $clone = clone($page); $this->pages->uncache($clone); $prev = $this->pages->get($clone->id); $prev_related = $prev->related_pages; $page_related = $page->related_pages; $deleted_ids = array_diff($prev_related->explode('id'), $page_related->explode('id')); $added_ids = array_diff($page_related->explode('id'), $prev_related->explode('id')); $pagesToSave = new PageArray(); foreach($added_ids as $added_id) { $added = $this->pages->get($added_id); if (!$added->relatedPageField->has($page)) { $added->relatedPageField->add($page); $pagesToSave->add($added); } } foreach ($deleted_ids as $deleted_id) { $removed = $this->pages->get($deleted_id); if ($removed->relatedPageField->has($page)) { $removed->relatedPageField->remove($page); $pagesToSave->add($removed); } } $this->message("saving ".count($pagesToSave)." pages."); foreach ($pagesToSave as $pageToSave) { $pageToSave->save(); } } }
  10. Hi Guys I have a question about the ProcessList.module in /wire/modules/. When I add a summary field to the admin template, the module takes the value of the summary field and outputs it, when it doesn't find a summary field it takes the summary value of the getModuleInfo(). How can I alter the behavior of ProcessList::render with Hooks so that I can also use another field than summary?
  11. Hello for all. This is not a topic about multilanguage websites, but mostly about one-language web sites and translation methods. In one-language none-english projects I don't install "Language Support" modules, but still use static English phrases in files ("Read more"...), and later translate that phrases using some of many options (eg. method + arrays). To simplifie this topic: if you build website in one none-english language (eg. Germany, Russian etc.) and, as example, want to use wonderfull "Pollino" Soma module, than you have to install "Language Support" module, or you will have "Vote" button at the form. And that's ok. But how to translate that module phrases without using "Language Support" modules? <- was my first idea. Also, all this is in connection with my custom development where I want to standardise some things, like translation of static phrases. Target: Leave, and respect native PW call for all phrases in English (__("Some text")) and use that standard principle in all projects (one language, or multilanguage). Idea: use hooks inside __() call and at the beginning, stop all next calls and procedures, and do some compare and replace job Problem: there is no hookable method for that job ("wire/core/LanguageFunctions.php") Currently working solution (example): // _func.php // prepend // Call Language Support module // You can comment next line if you have installed module // , or this will do the same job $module = wire('modules')->get('LanguageSupport'); // Here we rewrite response from module function translation( HookEvent $event ){ $event->return = translate( $event->arguments(1) ); } // These is the example where we do "find and replace" job // You can use different variant, like include dict. file function translate( $phrase ){ $dictionary = array( 'Read more' => 'Opširnije', 'Total votings:' => 'Ukupno glasova: ', 'Vote' => 'Glasaj', 'Name' => 'Ime i prezime', 'Message'=> 'Poruka', 'Subscribe' => 'Pošalji', 'Missing required value' => 'Ovo polje je obavezno', 'Next' => '>>', 'Prev' => '<<' ); return isset($dictionary[$phrase]) ? $dictionary[$phrase] : $phrase; } // This is the main part where we hook wire()->addHookAfter('LanguageTranslator::getTranslation', null, 'translation'); I didn't avoid "Language Support" installation, but with this I can translate all website phrases in one place (good if you need to translate 20 - 30 views with repeatable phrases, eg. "Read more"). Also with this no need to use custom translation methods (use default PW call (__("Some text")). p.s. also there is idea to hook append same 'textdomain' for all files/views Regards, Sasa
  12. I tried the new bookmark system in the dev branch (2.6.17). It's great for quick access, but I have too many parents with the same name "Products" under different parents like "office/products" "home/products" etc. So I needed to change the labels for add new button on Tree view. After a little bit poking I found a solution, so I'm sharing for anyone who might need. public function init() { //hooking the event for editing list of bookmarked pages from my SiteHelper module $this->addHookAfter("ProcessPageAdd::executeNavJSON", $this, 'bookmarksEvent'); } public function bookmarksEvent(HookEvent $event) { $eventReturn = $event->return; foreach($eventReturn['list'] as $key => $item) { //if its a parent url for adding if( strpos($item['url'],'parent_id') > 0 ) { $url = str_replace('?','',$item['url']); parse_str( $url ); //get page in the bookmark $page = wire('pages')->get($parent_id); //my scheme is for a label format: parentTitle - title $newLabel = "{$page->parent->title} - $page->title"; $item['label'] = $newLabel; $eventReturn['list'][$key] = $item; } } $event->return = $eventReturn; }
  13. Hi all, I've been working on this for ages, but I cannot seem to find a generic way to exclude pages (subtree's) from the admin interface depending on a known rootParent id. My case: I have a site-tree like: HOME - Client A - Client B - Client C My subdomain determines which client we are. I have a hookAfter in a custom module that attaches to: ProcessPageList::execute This filters the tree so that when the user logs in at: clientA.domain.com the pagetree in the admin interface only shows: HOME - Client A Thus filtering by rootParent But, I'm trying to hook into for example the Pages::find to make a more generic way of filtering, so that also the Search (ajax or lister) are working correctly. They now also return pages from the other subtrees like Client B etc. Is there a workable 'generic' hook to filter results within processwire? Background on setup: My setup is done this way to have a shared /site/modules, /site/assets, /site/logs etc. but to have a client specific /site-clienta/templates My core code in this application (it's not a public site, it's actually a narrowcasting system) is centrally managed within /site/ And templates are maintained within a clients' /site-client It is all running in the same database (so that I don't have to maintain multiple instances/code/settings etc) I made some changes in /index.php so that I have a $siteCore and a different $siteDir, this way, only templates are in the clients site directory. The siteCore also has templates, which are in code included in the clients templates if needed... This setup works great and is remarkably easy to maintain (shared templates, custom templates (overrides), central modules, shared users, etc.) The only thing missing is filtering all pagetree results (everywhere, but now mainly search/ajax results) by client rootParent. I looked into using permissions/roles, but the hassle to maintain it is not worth it... I already know by the domainname what to do, so I don't want to implement a different layer... The current setup allows me to very quickly add a new client by simply create a rootParent with a pageName like: site-clientD and a directory /site-clientD and /site-clientD/templates and I'm ready to customize it where needed, letting the core handle defaults etc.
  14. Hello, My Goal: To create a custom module that will take an array of images and generate a sprite sheet, as well as, the CSS to access each sprite. (This part I have completed ). To have it be a custom InputType, so that every image field does not create a sprite sheet. (Still needs to be completed). To create an admin page for the module to allow you to customize the output, size, etc. (Still needs to be completed). My Problems: Currently, it is looking at a specific folder that is hardcoded in the module, and creating a sprite sheet from those images. I suspect that creating a custom InputType would allow me to have the folder dynamically set based on the page that is using the module. I am struggling on finding the proper documentation that would allow me to do that. I also, have created a "Create Sprite Sheet" button and have it hooked after the page save button... on every page, even if there isn't an image upload on that page .I would like the create sprite sheet functionality to be hooked to the actual page save button only on the pages that have the custom InputType that needs to be created - mentioned above. I'd appreciate any help/direction provided, to help me achieve my goals. Also, if anyone has any recommended features that they think would be helpful as a part of this module, please feel free to make suggestions. Thanks in advance.
  15. I found 'ProcessTemplate::executeRename' but that is called before the rename confirm. 'Pages::saveReady' seems a bit too generic for a template rename. Is there something more like a 'templateRenamed'?
  16. Hi everyone, I want to use the core module PagePathHistory in a Processwire instance with multi-language URLs/page names activated through the core module LanguageSupportPageNames. From looking at that old Post by Ryan I was pretty sure that it should work without any problems and was surprised that actually it doesn't. PagePathHistory only saves entries to it's DB table when the page name in the main language changes, not when any of the other language names change. Looking at the code this is no suprise as PagePathHistory only hooks Pages::moved(), Pages::renamed() and Pages::deleted(), none of which would be triggered by a change in a language page name. Starry-eyed I started to implement the missing language-awareness in the module, how hard can it be, eh? ...pretty quickly it turned out that this isn't that simple, so I decided to first ask for some help and guidance. Does anyone maybe already work out a solution for this particular problem or something similiar? The problem with the implementation is that after saving a page with changes to language names, there still has to be a means of accessing the old names. For the default language name this is pretty simple because it's saved as $page->namePrevious. For language names the module would have to deposit the original names for later to build the PagePathHistory-URLs. I've been looking through all hookable functions in core classes/modules but haven't found the best place to hook into to implement this functionality. Does anyone have an idea where this would be done best? Any help is appreciated. Thanks a lot in advance Marc
  17. Hello fellow wirecionados, looking at the roadmap to 3.0 always gives me the good feeling of being on the sunny, futureproof side when using Processwire. Everything we already have together with the features planned is all I ever needed from a CMS. At least this is what I thought until that next idea came to my mind. Actually, there's one thing about Processwire that I have been struggling with from the start and until now: the hook system. I know, the hook system is deeply enrooted in Processwire (as can be seen from the fact that it's implemented in the Wire class that virtually every other class extends) and therefore is one of the key aspects for its success in the first place. It allows for the relatively loose coupling of components, with a lot of the core functionalities being implemented as modules. This makes for the great extensibility that Processwire is famous for. There aren't many parts of Processwire that can't be tweaked and modified to anyones needs by developing a module that alters some core functionality. I'm really glad about that and probably wouldn't have started to use Processwire in the first place, if the hook system didn't exist. That all being said, I also see some more or less problematic downside to the current implementation. It's sometimes pretty hard to find out, where functions are actually implemented. How long did it take you to find out that the actual logic for Page::render() is implenented in PageRender::renderPage()? While this kind of flexibility is just great, the implementation is not very verbose. This makes things harder than they have to be – especially for beginners. Just to make the argument above worse, there are several different ways to define a hook: addHook(), addHookAfter() & addHookBefore(), and all can be called either with a Class name or on an object. This makes it even harder to find modules, that hook into a particular function. I know, we have Soma's fabulous Captain Hook, and I use it all the time, but it still feels more like a workaround than like a solution. Speaking of Captain Hook, there's still a „Crocodile Hooked“ missing, a central repository that keeps track of all methods that are hooked to another method, including (private) site modules – and if possibly available at run time. Hooks for classes are saved in a static variable of Wire, but local hooks can only be fetched from that particular instance of an object. The convention with the three underscores in front of a function name makes functions harder to find. It is a nightmare to debug. If you ever tried to follow a request through the system with Xdebug, maybe involving some hooks placed by modules, you probably know what I mean. You have to go through Wire::runHooks() and __call() again and again to get where you want. It also prevents some of the convenient features of your favourite IDE™ (e.g. code completion, parameter hints when using a function, go to the definition of a function by clicking on it, etc.) from working in some cases. While one could definitely argue, that this is the fault of the IDE used, it's still slowing down work and not likely to be changed anywhere soon. Please excuse me if this was too ranty and even more correct me if anything I mentioned is an error on my side. I have to emphasize that none of these downsides prevents anyone from getting something done, it just makes it a tad less obvious and comfortable. Thinking through the things that I don't like about the current implementation of the hooks system, it came to my mind, that what we currently have here is kind of a non-verbose version of a „traditional“ event system and maybe what's missing could be more verbosity, so maybe such an event system (that implements the mediator pattern) could be of help? What I have in my mind here is the Symfony EventDispatcher or the Drupal8 EventDispatcher component, which is similiar to the CakePHP Events System and the handling of Events in Laravel. Let's look at how a solution to the problems mentioned might work by way of example using the Symfony EventDispatcher. In this particular example, the difference would be that Page::render() would actually be implemented in the Page class but just dispatches an Event.render event. Functionally no real difference, but much more verbose and therefore it is much more clear, that you will find the implementation anywhere a listener for Event.render is added. A new implementation could use just one method to add listeners (e.g. EventDispatcher::addListener()). Execution before or after an event will have to be handled by multiple events where this makes sense. Because the event dispatcher is the application-wide sole instance where event listeners are stored, it's easy to get all registered event listeners at runtime (using EventDispatcher::getListeners()). No more underscore's, just calls to dispatch events and calls to listeners. Debugging get's as smooth as it get's with loose component coupling. No more running through __call() all the time, always be able to check the defined event listeners. Having separated before and after events prevents you from some running through runHooks(). The added verbosity also helps to grasp the existing architecture quickly. Most of the IDE comfort functionality that doesn't work now should work with the Event System in place, because functions are always really where they are expected and with the exact same name. As an added benefit this system is very well known to a lot of developers already. But there are also some downsides for sure: Added verbosity is, well, verbose. More keys will have to be hit to get something done. Method and property would have to be implemented differently. This can be done by sending events on missing methods/properties, but it certainly looses some of the appeal it has now. The key argument would for sure be, that it breaks compatibility with a lot of core and user contributed modules. This is definitely true, so there shouldn't be an easy decision on this one. I thought I'll use the time before 3.0 to bring this one up, because as I understand it, the next major will break some stuff either way. Also I think that it should be possible to do the switch by in the beginning only deprecating the old hook system while keeping it functional, by translating calls to the old functions to adding and calling event listeners. This will have a performance impact, but would make a gentle transition possible. Now I'm really interested on your opinions on this topic. Do you already like the current implementation and wouldn't want to loose it? Do you have other problems with hooks? What kind of solution could you imagine? Is such a deep change realistic (and worth it) at all? Thanks a lot for your feedback Marc
  18. In my ProcessBlog project, I have multiple authors and would like to send notifications on a couple different kinds of events. Situation 1: First, for blog_comments (a FieldtypeComments field) on the blog posts, I'd like to email the page's creator when there is a comment posted. Since the field's settings ask for a constant value for emails to send notifications to, I'm wondering if I should hook onto this field somehow, or if there's a syntax by which I can specify the superuser(s) and the person whose post it is (their email address is stored in their user page). I looked in the FieldtypeComments module for this and didn't see an obvious place where I could tack in code to append $createduser->email Situation 2 (& 2b): Second, I created a system of posts, sort of like a ticket system, by which users can communicate with each other (without having to know personal contact info). A user would issue one of these messages (by creating a page) and select the user from a Page field of qualified users. When they publish this page, I'd like to send an email to the user that was selected ($targeteduser->email). This page also has a comments field, and I'd like one user to get an email when the other user comments (similar to the first situation, except slightly more aware of who is posting and who is referenced in the page). Since both situations deal with page saves (saves generated by FieldtypeComments in situations 1 and 2b, and general page saves with publish in situation 2), I don't want to hook this to the page save or there might be excess emails going out. Not really familiar enough with hooks to know what else to consider, and nothing jumped out at me when I browsed the Captain Hook list. I imagine I'd create a new module, possibly 2, that looks at the page template and draws information from the fields in it, but I am a little stuck beyond that and would appreciate help with as much detail as anyone is willing to go into. Thanks in advance!
  19. I just wanted to vote for making Template class’ filenameExists method hookable. Would become handy as soon as you don’t want to work with native template files the usual way without all pages being marked as not viewable. BTW: As the hook method viewable provided by PagePermissions is the main problem here, it would be good to know if it were possible to override existing hooks of other modules somehow. Just a thought.
  20. I really wanted to create this post with some sample code to show that I at least tried to figure it out on my own first, but I'm really struggling with how hooks are even written. I know it's a very simple context for anyone who's already using them (and hopefully it will be for me, soon), but this is my first time. What I'm trying to achieve in this attempt is to verify/change the name and title fields of a page, of one specific template with one specific field, whenever the page is saved. Initially, I am using the Family / Name Format for Children to skip the name/title/confirm save page when an author creates a new page in my site using kongondo's ProcessBlog module. In English, I want to: Detect when a page of template blog_page is saved with the blog_categories field value of Swatch, and replace the title and name string with a concatenated version of the following fields (from the same page): blog_date, createdUser, blog_brand and blog_name. From what I've read so far, I should build this hook into site/templates/admin.php, and I should use the saveReady() and maybe saveField() hooks. Other than knowing I need to define a custom hook, I really haven't got any idea of where to go from here. Here's my mangled first attempt at coding my hook. Hopefully you'll be able to tell how I might be misunderstanding this from the following: $pages->addHookAfter('saveReady', $this, 'myPageRename); public function myPageRename($event) { } I'm afraid that's really as far as I've gotten because I have no idea what I'm doing. I try to follow examples but they feel really far removed from context for me. Thanks for any light that can be shed on this!
  21. Hi, I want to write up a module that upon installation generates my site fields, templates, and roles... What hook do I use? This is a better approach than simply exporting a Site Profile, no? Thanks...
  22. public function init() { // add a hook after each page is saved $this->pages->addHookAfter('saved', $this, 'populateDefaults'); } /** * Populates model defaults after save for corresponding blank fields. * */ public function populateDefaults($event) { $page = $event->arguments('page'); if($page->template != 'vessel') return; //$this->message("hi {$page->model->hulls}"); if($page->model && !$page->hulls && $page->model->hulls) { $page->set("hulls", $page->model->hulls); $this->message("hi $page->hulls {$page->model->hulls}"); } } This sort of works; the message echoed is "hi 1082 1082". When I set the hulls to null in the above code, it then goes back to "hi 1082". However, it doesn't update the select input in the edit screen, and the "Missing required value" error for that field remains... Also the message shouldn't even be showing if $page->hulls is set... How can I get it to update the field value and the input?
  23. I found something I'd consider a bug. Let's say we have this very useless hook: $pages->addHookProperty("Page::foo", null, function($event) { $page = $event->object; if ($page->title === "About") { $event->return = "About foo"; } }); When I search for pages with a non empty foo property: $pages->find("foo!=''"); I get an exception: Error: Exception: Field does not exist: foo (in /wire/core/PageFinder.php line 494) Which I consider very IN YOUR FACE to begin with, even if the hooked property foo would not exist. If none of the pages have a field called foo, then just get me ZERO pages. BUT since this property is created via hook, PW should not tell me the field does not exist. However, If I use the same search with a filter it works as expected, I get a PageArray with one result (bc there is one page with the title About): $pages->find("*")->filter("foo!=''"); Please don't tell me this is expected behavior
  24. I'm trying to create a simple module that on pages of a certain template, when they are saved, redirect to the front-end. The thinking here is that I have created simple front end buttons on a blog to add either a "gallery post" or a "blog post" (different template same parent). I don't really want to handle the uploading of images part in the front-end and so would like to use the admin for the post creation but I would like the user to return instantly to the front end when they have added their new post. When they click the relevant front-end button, the relevant page gets created with the required template. They get sent to the newly created admin page where they can add their content. Front end bit: <?php if ($user->isSuperuser() && $input->get->type == "blog") { $new_post = new Page(); $new_post->of(false); $new_post->parent = $page; $new_post->template = "blog_post"; $new_post->title = "New Blog Post"; $new_post->save(); $session->redirect($config->urls->admin . "page/edit/?id=" . $new_post->id . "&new=1"); } if ($user->isSuperuser() && $input->get->type == "gallery") { $new_post = new Page(); $new_post->of(false); $new_post->parent = $page; $new_post->template = "gallery_post"; $new_post->title = "New Gallery Post"; $new_post->save(); $session->redirect($config->urls->admin . "page/edit/?id=" . $new_post->id . "&new=1"); } ?> <?php if ($page->template == "journal" && $user->isLoggedin()) { ?> <a href="<?php echo $page->url . '?type=blog'; ?>">Add Blog Post</a> <a href="<?php echo $page->url . '?type=gallery'; ?>">Add Gallery Post</a> <?php } ?> This works fine, creates the page with the right template and redirects to the correct admin form page. Now when they have added their content, I would like them to be redirected to the front-end to see the immediate effects of their new post. I've created the module but I'm having trouble finding the right combination of hook and before/after. So far I can either seem to manage the redirect without the changes or save the changes but the redirect doesn't take effect. This is the basic module I have so far but obviously the hooks/processes are incorrect. Does anyone have any experience of getting this working? Thanks <?php class BlogRedirect extends WireData implements Module { public static function getModuleInfo() { return array( 'title' => 'Redirects back to front end journal', 'version' => 101, 'summary' => 'Redirects back to front end journal page.', 'singular' => true, 'autoload' => true, ); } public function init() { $this->pages->addHookBefore('save', $this, 'redirectToBlog'); } public function redirectToBlog($event) { $page = $event->arguments[0]; $session = wire("session"); // make sure that the initial create page doesn't redirect if ($page->parent->template == "journal" && $page->id) { $session->redirect("http://localhost/route66_pw/journal"); } } }
  25. I added some input fields to the Textarea input tab with a hook: $this->addHookAfter('InputfieldTextarea::getConfigInputfields', function(HookEvent $event) { // field generation here }); The fields are rendered perfectly, all fine here: When I hit "save" the new config values are saved to the database. This is what I see in the field's config in the fields table, all fine, great: {"textformatters":["TextformatterParsedownExtra"],"inputfieldClass":"InputfieldTextarea","collapsed":2,"rows":16,"contentType":0,"trackChangesInterval":777,"cssTheme":"theme-solarized-dark"} But when I want to access the new saved data from anywhere, I can't, it's not there. Only the standard values from textarea are there but not the custom ones. What else do I have to do to make them accessible from the respective fields instance? The are there but do not seem to be added/set to the instances. PS: PW's docs need some serious work =( Thanks!
×
×
  • Create New...