For background, WordPress, which I love, but bless its heart, for some reason still supports PHP 5.2, which hasn't had security support forever. I'm pretty passionate that if WordPress wants to be the serious application platform we all want to claim its become because REST API, than dropping support for PHP5 in core, is an important signal to the developer community that developer experience is going to be prioritized.
Also, I pride myself on really tweaky bug reports and patches. My favorite is the patch I wrote to reduce the loops that run when metadata is saved from 4 to 2. That or some inline documentation updates in
Also, I'm experimenting with acceptance testing using Ghost Inspector, which is a really cool name for a SaaS. They give you a really simple looking way to record and run acceptance tests and I think using this tool will be easier to set up and maintain then learning/deploying/using Selenium, which I'm sure they are using.
But, this isn't about acceptance testing with Ghost Inspector. I'll report back on that once I figure that out, either here or on Torque. Anyway, this post is about how I registered a widget, inside an an anonymous function, using an anonymous class extending
\WP_Widget class included in WordPress core. #ApexClosure
If you're not familiar with older versions of PHP, PHP 5.4 was probably the first version where object-oriented programming made sense, because you could actually use $this in object-context inside of a closure, and also late static bindings -- closures being new to PHP in 5.3 is the key point here.
You can see a simplified version of what I did here: https://gist.github.com/Shelob9/fbc12169c965d77ed37b43256cac7071#file-wp-af-closure-php
And if you're wondering, who does that, I do, I want to have a way to record current Caldera Forms version and WordPress version in the video, so I made a quick widget:
Yah, that's my Hello Dolly right now. I know anyone reading this from inside the WordPress bubble might be screaming right now that I'm using the wp-admin code editor. While I don't want to encourage this behavior in the spirit of WordPress 4.9, which is making this easier to do, let me just make it clear, I do this shit all the time.
Anyway, off topic - Widget should work, but in the admin area we're getting a warning from this widget:
Warning: preg_match(): Null byte in regex in /srv/bindings/84ff30a58b1643d3bd9d52e40799fee1/code/wp-admin/includes/widgets.php on line 147
So, problem one with using an anonymous class for a WordPress widget is it creates that warning.
Diamond in a question mark is browser for "I can't decode this shit." This led me to belive -- I later confirmed it by reading source -- that WordPress must be identifying widgets in the DOM by the name of the class that calls them, and then using this identifier as part of the ID attribute of the UI element for adding a new instance of this widget to a sidebar.
So, problem two with using an anonymous class for a WordPress widget is that the unique identifier used will no longer be safe to use as an HTML attribute, which it is. BTW Someone should check the escaping there.
Finally, problem three with using an anonymous class for a WordPress widget is it doesn't work.
So, what's next? Obviously code review first, make sure I'm not totally full of shit here. If this still feels valid tomorrow, I'll open a new trac ticket. Yes, WordPress uses trac, not Github issues...
And BTW, if you're thinking, hey that's supposed to be a string you're passing to
register_widget -- the function that registers widgets, at first glance you'd think you have a strong case. The docs clearly indicate that function argument should be
The name of a class that extends WP_Widget IE a string.
But that function probably -- but who knows because that's assuming the value of a global variable, which is how 26% of the internet works -- is a wrapper for
\WP_Widget_Factory::register() which has totally different inline docs that make it clear that, and I quote
Either the name of a WP_Widget subclass or an instance of a WP_Widget subclass.
Therefore, unless I'm missing something, I think this is a clear bug as the documentation and the way the program is actually written should allow for any instance of any
\WP_Widget subclass, including an anonymous class extending
\WP_Widget should work. But the
hash_object method of that class is probably broken in this context.
But first, figuring out why my acceptance tests are passing but when I do the clicks myself, I can reproduce the bug in my own software, which actually will get fixed if I can figure this one thing out, which requires me modifying my Hello Dolly plugin to just use a named class #sigh.
I hope someone enjoys my story.