Jump to content

Hook not working


SteveB
 Share

Recommended Posts

I'm not sure what else there is to check in order to find out why a hook I'm setting has no effect.

The intent is to modify the form that is step 1 of adding a new page

Just for test I made the function the hook should call die() but execution gets right to where the buildForm is run, continues after, and the form appears. It's clear my function isn't called.

I've uninstalled (deleted the compiled file too just in case) and reinstalled the module.

What else can I check?

Code snippets:

class HookPageAdd extends WireData implements Module, ConfigurableModule {

	public static function getModuleInfo() {

		return array(
			'title' => 'HookPageAdd', 
			'version' => 1, 
			'summary' => 'Hook to intervene during adding of new pages.',
			'singular' => true,
			'autoload' => true
			);
	}
.....
	public function init() {
		// init() is called when the module is loaded. 
		$this->addHookAfter('ProcessPageAdd::buildForm', $this, 'intervene');
		$this->enabledPaths = $this->data['enabledPaths'];
	 }
.....
	public function intervene($event) {
		die(__FILE__.'@'.__LINE__.' '.__FUNCTION__);
	 }
.....
//Added messages before and after where ProcessPageAdd uses the function I'm hooking
 
		$this->wire('log')->message(__FILE__.'@'.__LINE__.' '.__FUNCTION__);	//SB////////////////////////////////////////
		$this->form = $this->buildForm();
		$this->wire('log')->message(__FILE__.'@'.__LINE__.' '.__FUNCTION__);	//SB////////////////////////////////////////

Using 3.0.10

Link to comment
Share on other sites

If that test works, it could be that you are trying to add a child to a page who's template only allows children with a fixed template and for which a child naming policy is defined. If that is the case, the initial add form you are hooking is not even called (and, therefore, your hook won't get called) as PW will do a 'quick add' and use the only permitted template for the child and the defined naming policy. (PW source code)

Hope that helps!

Edited to add: From your OP it sounds like the build form is being shown, so this is probably not the case. 

  • Like 2
Link to comment
Share on other sites

When you hook after, your event->return is your form I guess :-).

$this->addHookAfter('ProcessPageAdd::buildForm', $this, 'intervene');

public function intervene(HookEvent $event) {
    $form = $event->return;
    $name = $form->getChildByName('_pw_page_name');
    $name->set('value', 'tralala-my-ding-ding-dong');
}

Edited by Martijn Geerts
added spoiler
  • Like 3
Link to comment
Share on other sites

Netcarver, Good idea to put die() in init. Made no difference. So now the question is why did my module not get loaded?

But you're off track in the other comment. The buildForm() method is called. Aside from messages in the log from ProcessPageAdd before and after calling it (see last of the code snippets), the next thing I see on the screen is the form.

  • Like 1
Link to comment
Share on other sites

Hmm, not sure why the module might not be loading. Did Martijn's suggestion help?

If not, does it start working if you manually force your module to be loaded by adding a site/init.php file to your site and putting something like this in it...

<?php

$my_module = wire('modules')->get('HookPageAdd');

..?

  • Like 1
Link to comment
Share on other sites

Having just read this...

/site/init.php
This file is included during ProcessWire's boot initialization, immediately after autoload modules have been loaded and had their init() methods called. Anything you do in here will behave the same as an init() method on a module. When this file is called, the current $page has not yet been determined. This is an excellent place to attach hooks that don't need to know anything about the current page.

...(source.) It seems that you could run your hook directly from the init.php file and be done with your module (if needed.) You could, at least, use init.php to test your intercept routine.

Link to comment
Share on other sites

Hey thanks for the support.

Yes I've refreshed many times. Loading the module from init.php I can call $my_module->intervene() and get a reaction. Calling the module's  init() from there does not get the function hooked though.

It's not my first choice but I can get the functionality I want by modifying ProcessPageAdd.module this way:

		$this->form = $this->buildForm();

		$my_module = wire('modules')->get('HookPageAdd');	//module that wont hook
		$my_module->init();
		$this->form = $my_module->intervene(null, $this->form);

The last three lines being my addition to replace the broken hook. The call to init() readies some configuration data.

Then in the module I just added a second optional argument to pass the form through instead faking an event object.

Calling it this way, everything works.

I should be able to run this modified one as a site module. I've done that before. Nice feature of PW..

Still hoping to revert this back to normal do-it-with-a-hook usage someday. It's a mystery to me why it won't hook.

The module will help manage what can be added where without having to and maintain otherwise identical templates just for the sake of having different allowed children. It has an alternative configurable way to determine allowable templates for adding pages based on the path of the parent page specified in the add request. You can even do a regex match to the original parent path and assign a substitute path. It auto generates a page name and rebuilds the step-1 page editing form with name and template in hidden fields showing only the Title field. Another module, HookAfterSave, finalizes things, sometimes giving the page a different name and parent such as an A to Z folder as parent and normal name string both based on title from the user.

Link to comment
Share on other sites

As a followup, here's the README.md file. Please comment on the Implementation Issue. It's working but could probably be packaged better.

## HookAfterPageAdd

## IMPLEMENTATION ISSUE
Original plan was to accomplish this with hooks. For reasons unknown the hooks were not being setup. As a temporary workaround, a modified copy of ProcessPageAdd was created with code added to init the module and use its methods. In the end doing it this way is not so bad and simplifies certain tasks since we can jump in anywhere rather just at hookable function calls. Four changes to ProcessPageAdd are required. What should this module be called?

## Introduction
Ordinarily one step page add requires specifying only one valid child template on the template settings of parent page's template. That leads to many near-duplicate templates which leads to extra work keeping their other settings matched.

## Purpose
This module provides a way to specify everything we need to add the page in one step.
* The template is determined from config info and parent's path.
* Permission to add the new page to the parent is granted accoding to config info and template name.
* If no name format is set this module sets one.

## Path Configuration
Comma separated, starting with template name. See examples. Okay to have more than one per template. First matching line is used.

### Example 1
``````
artist, /data/artists/
``````
* Specify name of template to use for the new page: artist
* Specify path to new page's parent: /data/artists/

### Example 2
``````
publication, /data/bibliography/a/, /data/bibliography/[a-z]/
``````
Like above but with optional 3rd part using regular expression syntax. Consider this case...
* We have 26 folders named 'A' though 'Z' under /data/bibliography/
* We want to allow any of them to accept an Add request to add a new publication
* We setup another module, hooked after Pages::saveReady, to reassign the page to the correct folder. That's in case the user goofs or the page gets renamed.

The third part is used in a regular expression pattern (PHP preg_match). It will match the path of any of the 26 folders. Easier than adding 26 rules. In this example, the user can start an add request at any of the A-Z folders and the new unpublished page opened in the editor will always be in the A folder.

## Role Configuration

Again it's comma separated, starting with template name. After that add as many role names as you like.
Do not put in more than one line for the same template.

* Example 1
``````
artist, editor, manager

Thanks.

Link to comment
Share on other sites

  • 1 year later...

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
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...