Jump to content

Replace a core method


muzzer
 Share

Recommended Posts

A little out of my comfort zone here; Is it possible to replace a core method in PW:

class ExtendedWireArray extends WireArray {

   public function findRandomTimed($num, $seed = 'Ymd') {
      // new code
   }
}

Reason: I have Suhosin apache security extension installed which means the findRandomTimed() method does not work correctly as php seeding is overwritten by Suhosin. I need to alter the function to use my own seeded random generator, but hacking the core is obviously not a good idea. Is a module the way this is normally done or can I simply extend the WireArray class somehow?

Link to comment
Share on other sites

Sure, you can do whatever you want with PW! Put something like this in your template file, or change it to extend the WireArray class if you'd like

// Adding the method "suhosinRandomTimed to the WireArray class
$wire->addHook('WireArray::suhosinRandomTimed',null,'suhosinRandomTimed'); 

// Define the method, I added $num and $seed to make this easy to demonstrate
function suhosinRandomTimed($event, $num = 2, $seed = 'Ymd') { 
	$pages = $event->object; // This is the WireArray object, more than likely will be pages

	if(is_string($seed)) $seed = crc32(date($seed)); 
	srand($seed);
	$keys = $pages->getKeys(); // changed all instances of $this to $pages since I'm not defining within class
	$items = $pages->makeNew(); 

	while(count($keys) > 0 && count($items) < $num) {
		$index = rand(0, count($keys)-1);
		$key = $keys[$index];
		$items->add($pages->get($key));
		array_splice($keys, $index, 1);
	}

	$event->return = $items; // return the pages
}

$p = $pages->find("template=someTemplate")->suhosinRandomTimed(); // Call the method on the results of $pages->find
echo $p->render(); 

Just change the function's body to do whatever you need it to be and you should be good.

  • Like 7
Link to comment
Share on other sites

Thanks all, Teppos article is pretty sharp, don't know how I missed the existence of all this, perhaps because I've been avoiding getting into module creation which is where it seems hooks are mostly used

@MindFull; It seems I can't access the functions arguments $num and $seed inside the function, eg debug( $seed ); returns 2 even if I pass a different value to the function, but I can do debug( $event->arguments[0) and that retuens the passed value;

Is this normal or am I on another planet?

Link to comment
Share on other sites

@muzzer:

It seems I can't access the functions arguments $num and $seed inside the function, eg debug( $seed ); returns 2 even if I pass a different value to the function, but I can do debug( $event->arguments[0) and that retuens the passed value;

You need to retrieve all arguments from the HookEvent-object. ProcessWire will never add any other arguments to the hooked method call.

In your case, you can get the passed seed-argument with $event->arguments("seed") or like you noticed, with $event->arguments(0). 

To implement optional arguments, you can do something like

$seed = ($event->arguments("seed") !== NULL) ? $event->arguments("seed") : "Ymd";

If you have any other arguments than $event in the definition of your hooked function, I would remove them for clarity and use the method defined above. Or if you think it's nice to see the default values in the function definition, you need to check if the arguments are set in $event and then overwrite them.

  • Like 2
Link to comment
Share on other sites

@muzzer - Show me some code, I'm not sure I'm following you on this

function suhosinRandomTimed($event, $num = 2, $seed = 'Ymd') {
	$pages = $event->object; // This is the WireArray object, more than likely will be pages
	$num = 3; // Is this what you're doing?
	// Rest of code here

If so, I can set a breakpoint right at $num=3, step into it and get the correct value. I'm using Xdebug with PHPStorm and the Google Chrome extension.

I think he means that when he does $pages->find($selector)->suhosinRandomTimed(3, "c"), $num will still be "2" and $seed will be "Ymd".

Like I explained earlier, this happens because in the given example suhosinRandomTimed() -function, the arguments are not read from the $event-object.

Here's an example of a hooked method that would work with arguments as expected 

function suhosinRandomTimed($event) {
  $pages = $event->object;
  $num = $event->arguments("num");
  $seed = $event->arguments("seed");

  if(!$num) $num = 2;
  if(!$seed) $seed = "Ymd";

  // ... rest of the code here
}
  • 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...