muzzer Posted October 21, 2014 Share Posted October 21, 2014 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 More sharing options...
MindFull Posted October 21, 2014 Share Posted October 21, 2014 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. 7 Link to comment Share on other sites More sharing options...
netcarver Posted October 21, 2014 Share Posted October 21, 2014 @MindFull Nice example of how to use PW hooks to extend a class, thanks! Link to comment Share on other sites More sharing options...
muzzer Posted October 21, 2014 Author Share Posted October 21, 2014 holysh*t, never knew you could do that! Absolutely solves my problem, thx @MindFull for the explanation. BTW, what is the 3rd to last line for? $example - new $PageArray(); , is this relevant? Link to comment Share on other sites More sharing options...
MindFull Posted October 21, 2014 Share Posted October 21, 2014 @Muzzer - Nope, that line was a stray, lol. I was eating Capt'n Crunch, thinking, and typing all at once. Glad the rest of it was of use though! 1 Link to comment Share on other sites More sharing options...
MindFull Posted October 21, 2014 Share Posted October 21, 2014 Fixed it so it won't confuse others Link to comment Share on other sites More sharing options...
netcarver Posted October 21, 2014 Share Posted October 21, 2014 @muzzer Check out Teppo's ProcessWire hooking article on this sort of thing and also look at the last two hooks added in the HelloWord example module. You'll see that Ryan's added the ability not only to externally inject new methods to Wire-derived classes but to inject new properties too. 3 Link to comment Share on other sites More sharing options...
muzzer Posted October 21, 2014 Author Share Posted October 21, 2014 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 More sharing options...
sforsman Posted October 22, 2014 Share Posted October 22, 2014 @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. 2 Link to comment Share on other sites More sharing options...
MindFull Posted October 22, 2014 Share Posted October 22, 2014 Edited - sforsman beat me to it Link to comment Share on other sites More sharing options...
sforsman Posted October 22, 2014 Share Posted October 22, 2014 @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 } 2 Link to comment Share on other sites More sharing options...
Soma Posted October 22, 2014 Share Posted October 22, 2014 There's a nice tuto by Ryan https://processwire.com/talk/topic/4834-simple-hooks-tutorial-turn-a-pagearray-into-a-list-of-links/ 1 Link to comment Share on other sites More sharing options...
Recommended Posts
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 accountSign in
Already have an account? Sign in here.
Sign In Now