Jump to content

Recommended Posts

Hello,

 

Here's what I'm trying to achieve : I have a textarea field that is frontend editable on any page I want to. If a user with a specific role updates it, I want to tick a checkbox field on the parent page where the textarea resides. So I tried to hook as follows in my ready.php file :

	  $this->addHookBefore('Fieldtype::savePageField', function(HookEvent $event) {
      $page = $event->argument[0];
      $field = $event->argument[1];
      if($this->user->hasRole('teacher')) {
	     $page->alertBox = 1;
	      }
	// DEBUG HERE (bd($page),  l($field)... ????
  });
	

Of course (!) it doesn't work (yet !) but the thing is I have no idea how to debug this since my bd() never triggers. I've tried the 'Event interceptor' of Tracy debugger which helped me setting up my hook. I guess my $page and $field are correct... but how could I go any further ?

The road is long to become a dev (when you're not one 🙂 )...

For further information in case someone wonders : I'd like to set up a textarea that is modified by a user (having a 'player' role, ie 'student'). When front-end modified, I wish it would automatically alert me (the teacher) by ticking a box. So when I log in with my teacher role, I get a list of all textareas I have to read over. When I read/correct/update them (front-end), I would like my hook to automatically untick the box to remove it from my list. In other words, the 'textarea' status should go back and forth according to who modified it last. For the time being, I have managed to make it work with a checkbox that the user has to manually tick/untick, but I've noticed many kids forget to tick the box so they edit their text and I don't get a notice 😞

Thanks if anyone takes time to try and help me on that one !

Share this post


Link to post
Share on other sites

Still digging...

I have tried this taken from the docs :

	$wire->addHookAfter('Pages::saved', function(HookEvent $event) {
  $page = $event->arguments(0);
  $event->message("You saved page $page->path");
});
	

But I see nothing... My logs > messages do not show anything, my Tracy bar doesn't show anything...

Does a front-end edition and a hit on the 'Save' button does not trigger the hook ?

I have a feeling I was confusing things in my previous post, so all in all, let's sum up my question : how do you debug hooks ? Is a simple bd('ok') suppose to work if the hook is working ?

 

Share this post


Link to post
Share on other sites

Thanks a lot @Zeka for your reply. I do use TracyDebugger in my usual debugging 'flow', but my problem here is that it never triggers anything, and that is exactly what I don't understand.

After trying some more things, I can understand thath Tracy works in hooks by testing this :

	  $this->addHookBefore('Page::render', function(HookEvent $event) {
    bd('ok');
  });
	

which does give me a result on page load.

Eventually, my concern is there : in my initial question, I want to debug in a hook that doesn't completely reload my page. I guess that's why I can't see anything. When I double-click my textarea to front-end edit it and then hit 'Save', the page doesn't reload so my dump bar stays silent. Is there a way to dynamically see what's going on ?

Share this post


Link to post
Share on other sites

Still desperately trying things...

I have this in my ready.php :

	$this->addHookBefore('Fieldtype::savePageField', function (HookEvent $event) {
	bd('ok'); // Also tried fl(), d()...
});

I have nothing anywhere (after front-editing my textarea and clicking 'save' in my CKEditor) aven after reloading the page, whereas if I use the event interceptor, I get the whole list of fields being saved (after reloading the page) and I can see that one of them is the field I have just edited.

So I'm stuck 😞

Share this post


Link to post
Share on other sites

Hi @celfred I can confirm that your hook does only fired when the page is saved on the backend. Frontend-Editing does not trigger this hook. The Event Interceptor does also show the event log for me... That's a bit strange. Maybe @adrian knows why?

 

Share this post


Link to post
Share on other sites

Thanks @bernhard for your reply. This helps me feeling more confident about my tests since I often don't know if I'm going in the right direction. I must admit I am not mastering anything there (you can tell !). I was glad to learn about the 'Event interceptor' but it seems like it lead me on a false interpretation 😉

So hooks don't fire when front-end editing ? I don't really understand why since the field is actually saved, isn't it ?

So I guess I won't be able to avoid my 'Manually check this box to alert your teacher' way of doing 🙂

Share this post


Link to post
Share on other sites
2 minutes ago, celfred said:

So hooks don't fire when front-end editing ? I don't really understand why since the field is actually saved, isn't it ?

I don't know if that is the case and I don't have time to investigate. You did lots of things right (like placing the most basic hook you can think of, then check if it works and only then doing the next step). If you encounter any problems on that road you either have to look for a different solution (like changing from frontend to backend editing) or you have to investigate and find the reason why things don't work as expected.

In the current case it could either be a bug or that saving of the field just works a little differently when fired from the frontend. That's by the way one of the reasons why I'm not using frontend editing any more. It bring's too much troubles for too little benefits imho. Doing those investigations can be frustrating sometimes, but you'll learn a lot about ProcessWire which will help you on all following challenges 🙂 

  • Like 1

Share this post


Link to post
Share on other sites
5 minutes ago, bernhard said:

Doing those investigations can be frustrating sometimes, but you'll learn a lot about ProcessWire which will help you on all following challenges

That's what I keep telling myself but I often end up having a greater and more difficult challenge 🙂

On my side, front-end editing seemed a good solution because I may have up to 50 textareas to edit and if I have to click on each in back-end, save and go to another, having a rather slow connection, can be troublesome... Here, I can load all the 'alerted' textareas on 1 page and edit them 'right away'. It was then just (!) a matter of automatically detecting who was the last user to modify the text. But nevermind for now, as you said, I still have learned a lot trying to do that !

Thanks a lot for your encouraging message and your help !

Share this post


Link to post
Share on other sites

Well... I'm also not convinced 100% myself to ban frontend editing completely 🙂 The interface is great and it's so much more user friendly to get exactly the same visual representation as you type. And it sounds reasonable to only load/save parts of a page and not everything. It always depends on the usecase, just wanted to note that one has to be careful with those fancy tools and also think of the drawbacks 🙂 

  • Like 1

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

  • Recently Browsing   0 members

    No registered users viewing this page.

  • Similar Content

    • By Andi
      Continuing my journey into PW hooks, I'm trying to find a way to retrieve all images from a page that explicitly *do not* have a certain tag (or tags) attached to them.
      Found this post from 2015
      But I'm wondering if there's a more elegant way to go about this.
      Let's say I have a multi-image field called "images_header" and instead of
      $page->images_header->findTag('mytag'); I would like to do this:
      $page->images_header->excludeTag('mytag'); So I'd be able to do
      // find images that don't have the tag "mytag" $images = $page->images_header->excludeTag('mytag'); // check if there's any images if (count($images)>0) { // do something.. } Would this be possible by hooking into Pagefiles somehow?
      There's this bit in /wire/core/Pagefiles.php Line 626 that I'd basically just need to reverse (or at least in my mind 😄 )
      public function findTag($tag) { $items = $this->makeNew(); foreach($this as $pagefile) { if($pagefile->hasTag($tag)) $items->add($pagefile); } return $items; } Any ideas on how this could be done in a graceful manner?
      Thanks in advance!
    • By Andi
      Getting a little deeper into the ProcessWire state-of-mind here. I seriously think I wouldn't have come back to webdev if it wasn't for this wonderful little gem of a CMS.
      I have an "Options" field added to all users on a site. If the user has anything other then "default" selected, I would like to show a permanent message in the admin like the one in the screenshot, only so that the user can't close it. As a friendly reminder that he changed that option from default to something crazy 🙂
      I've read up on how to send messages to users, but where would I hook into to make this show up all the time in the backend?
      https://processwire.com/api/ref/wire/message/
      Thanks in advance!

    • By celfred
      Hello,
      I'm struggling with hooks to try and do this : adding user page to a page field when visiting a particular page on my website. In fact, I want to have a list of connected users on a particular page (called meeting-hall).
      I've tried all kinds of things (which I don't really understand, sorry) but the latest is this :

        $wire->addHookBefore('Page::render', function($e) {     $page = $e->arguments(0);     if ($page->is("name=meeting-hall")) {       $page->connected->add($user); // connected is a Page field       $page->save();     } else {       $meeting = wire("pages")->get("name=meeting-hall");       $meeting->connected->remove($user);       $meeting->save();     }   }); I put this in my _init.php file but nothing works...
      The best I managed was updating my 'connected' field when the user loads the 'meeting hall' page by having this on the page template :

          if ($user->isLoggedin()) {       $page->connected->add($user);       $page->of(false);       $page->save();       $page->of(true);     } But I wanted to remove the user when he or she leaves the page... hence my thought about using hooks...
      If you can give me a hint, I'd greatly appreciate !
    • By Gadgetto
      Hi there,
      I'd like to prevent duplicate values in a specific page field (FieldtypeText) across all pages. The hook should also prevent saving of the page if a duplicate value is detected. Therefore I created two hook methods but I can't get it to work properly.
      Here are both hooks placed in init() method of an autoloader module:
      The first hook is to initially preset the field with the page id. The field value can be customized by the admin before saving.
      The second hook should check if the value is unique.
      If I create a new page and try to save, the WireException is already triggered in first step of page creation, where you enter the page title: SKU [] is already in use
      If I check the value of $sku (with Tracy) it's always empty!
      Any idea what could be wrong?
      EDIT: if I remove the second hook, the field value is correctly preset with the page id!
      $this->addHookAfter('Pages::added', $this, 'presetProductFields', ['priority' => 99]); $this->addHookAfter('Pages::saveReady', $this, 'checkSKUUnique', ['priority' => 101]); And this are the hook methods:
      public function presetProductFields(HookEvent $event) { $snipwire = $this->wire('snipwire'); if (!$snipwire) return; $page = $event->arguments(0); if ($snipwire->isProductTemplate($page->template)) { if ($page->hasfield('snipcart_item_id')) $page->setAndSave('snipcart_item_id', $page->id); } } /** * Check if the SKU value is unique across all product pages. * (Method triggered after Pages saveReady -> just before page is saved) * * @throws WireException * */ public function checkSKUUnique(HookEvent $event) { $snipwire = $this->wire('snipwire'); if (!$snipwire) return; $page = $event->arguments(0); if ($snipwire->isProductTemplate($page->template)) { $field = $page->getField('snipcart_item_id'); $sku = $page->snipcart_item_id; // SKU field value bd($sku); if ($page->isChanged('snipcart_item_id')) { $exists = $this->wire('pages')->get("snipcart_item_id=$sku"); if ($exists->id) { // value is not unique! $error = $this->_('SKU must be unique'); $exception = sprintf( $this->_('SKU [%s] is already in use'), $sku ); $inputfield = $page->getInputfield($field); $inputfield->error($error); throw new WireException($exception); // Prevent saving of non-unique value! } } } }  
    • By t0b1
      Hello there, and thanks for ProcessWire!
      I'm getting to know ProcessWire while doing my first project using it and I really like it so far.
      The challenge I'm facing right now is the following:
      I have a One-Pager using fullpage.js, realized as a single PW-Page containing a Repeater Field where each Repeater Item is one Section.
      Some Sections are supposed to have a little menu at the Top which references/links to different Sections of the Website, so I wanted to use a Checkbox Field "Top Menu" to decide if a Section gets a Menu and a Page Reference Field to choose the different Sections (Repeater Items) it should contain.
      I've already accomplished this by pasting the following code into /site/ready.php:
       
      $wire->addHookAfter('InputfieldPage::getSelectablePages', function($event) { if($event->object->hasField == 'top_menu_entries') { $page = $event->arguments('page'); if($page instanceof RepeaterPage) $page = $page->getForPage(); $event->return = $page->; } });  
      The only problem that still remains is that when I select the Entry of the Repeater Item itself it doesnt save the selection, meaning after I saved it's unselected again.
      On some Sections I do want a Menu-Entry for the Section itself though (which would be styled differently and not link anywhere) for Continuity-Reasons, any ideas on how to achieve that?
×
×
  • Create New...