Jump to content

Hook pages::find caused error


Qualtext
 Share

Recommended Posts

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.
https://processwire.com/api/ref/pages/find/

$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!

 

Link to comment
Share on other sites

That's a bit dangerous, since not every template may have the field you're adding a search for.

Also, the value passed in $selector may be a regular selector string, a page id, an array of page ids or even an instance of the Selectors class. For most of those, simple concatenation isn't an option, and I'm suspecting that the error is caused by that. Perhaps peeking at $selector with Tracy Debugger can give you a quick insight into what exactly $selector contains when the error occurs.

  • Like 1
Link to comment
Share on other sites

Hi BitPoet,

first of all: it´s only a test environment. I debugged a lot. I was focusing on this lines to let the question short as possible :) 
I know, it´s not a good idea. But i think, i found a bug, and i want to point this out.

Nethertheless, i think there is an programming "mistake" in the Selectors.module. I followed the lines, and the splitting of the parts of selector doesn´t work right, (only!) IF, the field exists in the PW Installation, but isn´t appended to this template where the request starts, and its directly in the pages::find before hook. The output message is wrong: the selector operator is valid.

The idea behind the hook is: i want that processwire jumps over declared pages (if you have a lot of pages (> 20000) and template (> 100)) to do some tests, batch processing, or to leave a bunch of pages unawares in whole system. Because the hook can do so mutch with one line of code, that all mehtodes like :find, :get, :children, :parent will be effected, i want to work with that, for fun, testing in a playground environment. 

My current solution is to hook in after an filter the $event->return. But filtering 20000 pages feels like wrong. I dont want that PW notice the 20000 pages. With HookAfter :( :

$this->addHookAfter('Pages::find', function(HookEvent $event) {
  // Get the object the event occurred on, if needed
  $pages = $event->object;

  // An 'after' hook can retrieve and/or modify the return value
  $return = $event->return;

  // Get values of arguments sent to hook (if needed)
  $selector = $event->arguments(0);
  $options = $event->arguments(1);

  /* Your code here, perhaps modifying the return value */
  $return->filter("loremipsum_field!=1|3|");

  // Populate back return value, if you have modified it
  $event->return = $return;
});

Again, i know, is not the best idea, but i wanto to try it. Ryan said that in some post too, i can´t find it anymore.

Link to comment
Share on other sites

From PW's point of view, the error message is correct. It shows if you add the hook very early (like in site/init.php). PW, under the hood, calls find() with a numeric id, and that is when the error is triggered. With the numeric id, your selector becomes something like "32, loremipsum_field!=1". This has a comma and thus is a compount selector, so PW parses it into multiple expressions that need to match the form FIELD OPERATOR MATCH. The first expression, by these parsing rules, has an empty (missing) operator.

Still, you should be able make the hook work for most cases with a little type checking and conditional logic.

<?php

wire()->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);
  
  $customfilter = ", loremipsum_field!=1";
  
  /* Your code here, perhaps modifying arguments */
  if(is_numeric($selector)) {
	// The selector is a numeric page id
  	$selector = "id=" . $selector . $customfilter;
  } else if(is_string($selector)) {
	// Regular selector, FIELD OP MATCH
  	$selector .= $customfilter;
  } else if(is_array($selector)) {
	// Array of page ids
  	$selector = "id=" . implode('|', $selector) . $customfilter;
  } else if($selector instanceof Selectors) {
	// Already parsed Selectors object
  	$selector->add(new SelectorNotEqual("loremipsum_field", "1"));
  } else {
	// Unknown selector argument format!
  }
  
  // Populate back arguments (if you have modified them)
  $event->arguments(0, $selector);
  $event->arguments(1, $options);
});

 

  • Like 2
Link to comment
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
 Share

×
×
  • Create New...