[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