[wp-trac] [WordPress Trac] #32470: Abstracting the Widget Classes
WordPress Trac
noreply at wordpress.org
Tue Jun 2 03:41:25 UTC 2015
#32470: Abstracting the Widget Classes
------------------------------------+------------------------------
Reporter: welcher | Owner:
Type: enhancement | Status: new
Priority: normal | Milestone: Awaiting Review
Component: Widgets | Version:
Severity: normal | Resolution:
Keywords: dev-feedback has-patch | Focuses:
------------------------------------+------------------------------
Comment (by jacobsantos):
I made a video further explaining the motivations and reasons behind the
changes. Not sure if you would sit through an hour video but here you go.
https://www.youtube.com/watch?v=ot4LTj04KoE
I think the point that matters the most is the last 3 to 5 minutes. I
think that is really what I want to show.
{{{
#!php
interface WP_DisplayInterface {
public function render();
}
interface WP_Display_BeforeInterface {
public function before_render();
}
interface WP_Display_AfterInterface {
public function after_render();
}
interface WP_Display_VerifyInterface {
public function should_render();
}
abstract class WP_Abstract_Display
implements WP_DisplayInterface, WP_Display_VerifyInterface {
public function render() {
if ( ! $this->should_render() ) {
return;
}
if ($this instanceof WP_Display_BeforeInterface) {
$this->before_render();
}
$this->display();
if ($this instanceof WP_Display_AfterInterface) {
$this->after_render();
}
}
abstract public function should_render();
abstract function display();
}
}}}
The ultimate point is to go towards this code and not the current code.
The purpose I'm going to go into is how to develop with reusability in
mind. The idea of creating generic interfaces and classes that can then be
further reused in any place.
What exactly is a Widget? An object that displays arbitrary content at a
given location. Okay. Fine. Why does it need to have a specialized
contract, when a generic one would satisfy? I think the problem is that
the developers didn't think generally but specifically towards solving the
problem. Well, then again, the code needed to support PHP4, which didn't
support interfaces, so that is part of the problem.
There is another problem that the code would be better off using
namespaces to better segment and name the code. The solution should be
solved with as minimal amount of code as possible. That is also ultimately
what I'm attempting to show.
The above solves your problem without adding any new methods.
{{{
#!php
class WP_Widget_Control extends WP_Widget {
protected $display_instance = null;
public function __construct(WP_DisplayInterface $display) {
// Call parent::__construct();
$this->display_instance = $display;
}
public function widget( $args, $instance ) {
$this->display_instance->render();
}
}
}}}
The below code also implements a solution to your problem, again without
adding any more methods to the existing class. Furthermore, the new
interfaces could be used within WP_Widget with an test as to whether the
interface is implemented and then called.
{{{
#!php
final class WP_Widget_Display_Adapter implements WP_DisplayInterface {
private $_storage = array(
'display' => null,
'before' => null,
'after' => null,
'verify' => null,
);
public function register($instance) {
switch (true) {
case $instance instanceof WP_DisplayInterface:
$this->_storage['display'] = $instance;
break;
case $instance instanceof
WP_Display_BeforeInterface:
$this->_storage['before'] = $instance;
break;
case $instance instanceof
WP_Display_AfterInterface:
$this->_storage['after'] = $instance;
break;
case $instance instanceof
WP_Display_VerifyInterface:
$this->_storage['verify'] = $instance;
break;
}
return $this;
}
public static function factory() {
if ( func_num_args() < 1 ) {
return new static;
}
$instance = new static;
$args = func_get_args();
foreach ($args as $obj) {
$instance->register($obj);
}
return $instance;
}
public function render() {
if ( is_object( $this->_storage['verify'] ) && !
$this->_storage['verify']->should_render() )
return;
}
if ( is_object( $this->_storage['before'] ) ) {
$this->_storage['before']->before_render();
}
if ( is_object( $this->_storage['display'] ) ) {
$this->_storage['display']->render();
}
if ( is_object( $this->_storage['after']) ) {
$this->_storage['after']->after_render();
}
}
}
}}}
I'm not sure how to explain what I mean any better. Which part do you not
understand? I think the problem with the patch is that I tried to show how
the code could be refactored and I think I'm going away from that goal and
towards what I should have attempted to explain previously. This is my end
goal. This is where I want the code to go towards. I would have done it in
a roundabout way, but at least you get to see where the finish line is
located.
True, it doesn't exactly fit in with the goals you are attempting to
design. However, in all honestly, your patch and design should not be
allowed as it only compounds the existing problem. The original
implementation should not have been allowed, if but for compat with PHP4.
--
Ticket URL: <https://core.trac.wordpress.org/ticket/32470#comment:23>
WordPress Trac <https://core.trac.wordpress.org/>
WordPress publishing platform
More information about the wp-trac
mailing list