In our tutorial "Using Classes as Code Wrappers for WordPress Plugins" we took a plugin that used a global function for its filter hook and converted it to using a PHP class as a code wrapper. Unfortunately the approach we showed didn't allow other plugins and/or themes to remove or chain the actions and/or filters if needed.

Let's explore the hook removal problem. We'll start with the example from the prior tutorial:

  1. <?php
  2. /*
  3.  * Plugin Name: Thanks for Reading
  4.  */
  5. class Thanks_For_Reading_Plugin {
  6.   function __construct() {
  7.     add_filter( 'the_content', array( $this, 'the_content' ) );
  8.   }
  9.   function the_content( $content ) {
  10.     return $content . '<p>Thanks for Reading!</p>';
  11.   }
  12. }
  13. new Thanks_For_Reading_Plugin();
<?php
/*
 * Plugin Name: Thanks for Reading
 */
class Thanks_For_Reading_Plugin {
  function __construct() {
    add_filter( 'the_content', array( $this, 'the_content' ) );
  }
  function the_content( $content ) {
    return $content . '<p>Thanks for Reading!</p>';
  }
}
new Thanks_For_Reading_Plugin();

Use a Global Variable for the Instance?

We could assign a global variable when we create the plugin's instance, and that is what a lot of plugins do:

  1. $thanks_for_reading = new Thanks_For_Reading_Plugin();
$thanks_for_reading = new Thanks_For_Reading_Plugin();

Others could then use this approach to remove our filter:

  1. global $thanks_for_reading;
  2. remove_filter( 'the_content', array( $thanks_for_reading, 'the_content' ) );
global $thanks_for_reading;
remove_filter( 'the_content', array( $thanks_for_reading, 'the_content' ) );

Unfortunately this adds yet another global variable that may conflict with other plugins or themes. It also adds to the list of global variables making for more to scan in IDE debuggers like PhpStorm. For these and other reasons we don't recommend using global variables for plugins like this.

Use a Private Static Property Instead

Rather than use global we'll declare a private static variable we'll call $_this.

  1. class Thanks_For_Reading_Plugin {
  2.   private static $_this;
  3.   ...
  4. }
class Thanks_For_Reading_Plugin {
  private static $_this;
  ...
}

The Static Declaration

The static declaration in PHP means that all instances of the class share the same single value. But as we only want one instance of this class we use static to allow us to access the instance using the class name, as you'll see below.

The Private Qualifier

In PHP the private variable qualifier "hides" the variable to any code outside of the class. In our case we want to ensure other code doesn't change its value accidentally, again as you'll see below.

Capture the Plugin's Instance

Inside the constructor we'll assign the object's instance from the $this variable to the static variable self::$_this:

  1. class Thanks_For_Reading_Plugin {
  2.   private static $_this;
  3.   function __construct() {
  4.     self::$_this = $this;
  5.     ...
  6.   }
  7.   ...
  8. }
class Thanks_For_Reading_Plugin {
  private static $_this;
  function __construct() {
    self::$_this = $this;
    ...
  }
  ...
}

Add a Read-Only Access Function

Next add a static function to the class which we'll name this() and have it return the value of self::$_this. This function will be public[^public-methods] by default providing read-only access to the single instance used by the plugin's class:

  1. class Thanks_For_Reading_Plugin {
  2.   private static $_this;
  3.   function __construct() {
  4.     self::$_this = $this;
  5.     ...
  6.   }
  7.   static function this() {
  8.     return self::$_this;
  9.   }
  10.   ...
  11. }
class Thanks_For_Reading_Plugin {
  private static $_this;
  function __construct() {
    self::$_this = $this;
    ...
  }
  static function this() {
    return self::$_this;
  }
  ...
}

To access the plugin's instance from outside the class simply call this() using the syntax for calling static methods:

  1. $instance = Thanks_For_Reading_Plugin::this();
$instance = Thanks_For_Reading_Plugin::this();

Removing the Filter

We've now enabled other plugins and themes to remove or chain any of our plugin's filters they may need to. Here's code they can use to remove the 'the_content' filter from our example plugin:

  1. $instance = Thanks_For_Reading_Plugin::this();
  2. remove_filter( 'the_content', array( $instance, 'the_content' ) );
$instance = Thanks_For_Reading_Plugin::this();
remove_filter( 'the_content', array( $instance, 'the_content' ) );

The Complete Example

Here is the entire example for viewing this post's code in context:

  1. <?php
  2. /*
  3.  * Plugin Name: Thanks for Reading
  4.  */
  5. class Thanks_For_Reading_Plugin {
  6.   private static $_this;
  7.   function __construct() {
  8.     self::$_this = $this;
  9.     add_filter( 'the_content', array( $this, 'the_content' ) );
  10.   }
  11.   static function this() {
  12.     return self::$_this;
  13.   }
  14.   function the_content( $content ) {
  15.     return $content . '<p>Thanks for Reading!</p>';
  16.   }
  17. }
  18. new Thanks_For_Reading_Plugin();
<?php
/*
 * Plugin Name: Thanks for Reading
 */
class Thanks_For_Reading_Plugin {
  private static $_this;
  function __construct() {
    self::$_this = $this;
    add_filter( 'the_content', array( $this, 'the_content' ) );
  }
  static function this() {
    return self::$_this;
  }
  function the_content( $content ) {
    return $content . '<p>Thanks for Reading!</p>';
  }
}
new Thanks_For_Reading_Plugin();

Summary

If you use classes as code wrappers for your WordPress plugins, which we recommend, you should take the tiny bit of extra effort to enable your users the flexibility they might need to remove or chain your filters. Fortunately the code required is almost completely copy-and-paste so it doesn't require in-depth understanding to get started; just grab the code template below and get started with your plugin:

Related Links

There are other posts on the web related to this topic:

We're haven't read each of these in-depth so can't vouch for them all, we're just telling you they exist. Caveat emptor.

Follow up Posts

If you'd like to learn more about writing class-based WordPress plugins you might be interested in this post too:

[footnotes]
[^public-methods]: Methods[^methods] in a class have public visibility by default unless explicitly declared private or protected.
[^methods]: For those whom the term "method" confuses, methods are simply functions declared within a class using the PHP function keyword. Methods act on instances of the class, i.e. $object->get_name() means that $object is calling it's get_name() method which would likely return a different value for each of the different instances of the class on which it was called.
[/footnotes]

33 thoughts on “Enabling Action and Filter Hook Removal from Class-based WordPress Plugins

  1. This is a neat solution to a problem I’ve come across several times. One thing, shouldn’t the function this() be static this() in the “The Complete Example” and “Summary” code blocks?

    Reply
    • Hey @Drew,

      Thanks for stopping by and dropping a comment. And yes, you caught my typo! Fixed now, thanks.

      Reply
  2. It’s such a pita to remove actions & filters hooks called from classes. Makes me hate the overzealous use of classes especially in cases when there are no major benefits to use a class to start with. At least it’s one step forward if authors make it a bit easier to access those hooks for removal, but it’s still a nightmare for people who are not coders.

    Reply
    • Hi @Peter,

      I really appreciate your comment, thanks!

      I believe that I tend to push the limits of what’s possible with WordPress given how often other plugin developers tell me they don’t understand why I need the improvements to WordPress core that I ask for, but to push the limits you need a solid code architecture or you’ll end up with an unmaintainable mess. But I’m also highly sensitive to the needs of people who are not yet “hardcore” or who do not actually want to be but instead just want to get stuff done.

      I once switched from Windows/IIS/SQL Server/ASP+VBScript after 12 years to Windows/Apache/MySQL/PHP and then to Mac OSX/Apache/MySQL/PHP so I’m very aware of how frustrating it can be to need to get something done but feel overwhelmed by the understanding required to do it. I also ran a web entrepreneur meetup for 3+ years and organized a lot of trainings for members including at least one training for WordPress so I’ve seen firsthand the frustration that others feels when they want to use WordPress but it’s just a bit more technical than they can grasp on their own.

      So I’d really love to explore the issues you have and how we coders who publish plugins could make it better for you. tried to address the hook removal use-case abive and posted the code showing how to do it: remove_filter( 'the_content', array( Thanks_For_Reading_Plugin::this(), 'the_content' ) ); which compares to:
      remove_filter( 'the_content', 'thanks_for_reading_the_content' ); Please help me understand your concerns about the former; it is just too complicated to understand for a non-coder, or it it something else? If the plugin’s README.TXT file had instructions for hook removal, would that be sufficient? Or would this be better? Thanks_For_Reading_Plugin::remove_filter( 'the_content' ); It seems like it’s mostly a documentation issue on the part of the plugin developer, but maybe I misunderstand?

      Again, I’d really love to understand how we plugin developers could improve our plugins so theme developers and site builders can be more comfortable using and extending our plugins. Thanks in advance.

      Reply
      • Well your solution is a hell of a lot better than hunting through the wp_filters global cowboy style. If this were the standard for all plugin developers that would be a step forward. Obviously, it doesn’t get any easier than remove_filter( 'the_content', 'thanks_for_reading_the_content' );. My view is that developers should do a cost-benefit analysis from a user point of view and not just stick commonly used hooks inside classes if it can be done without.

        The problem also lies in the discoverability. If it’s documented, at least a user could potentially find it. The truth is most plugins aren’t going to have a ton of documentation and would a non-savvy user know what to look for? It would require more explanation.

        Some plugins just are the kinds of plugins where you are going to spend a lot of time trawling through documentation (S2Member springs to mind), in those situations I like this solution a lot if the plugin is heavily into object oriented code.

        If it’s about pushing core changes, I would rather see them make remove_action & remove_filter smarter so that you don’t have to reference the class instance in the first place. That would retroactively make all relevant plugins easier to customize without requiring plugin authors to implement workarounds (even pretty elegant ones like yours). Are there any critical objections to that that you could think of?

        As a self taught dev who’s learning was based mostly around WP projects, I am happy that most code I encountered wasn’t object oriented in the early days. I’ve found OO much hard to grasp initially. Now that I’ve got some years under my belt, I’m comfortable with it (just wrote a class yesterday because it made the most sense) but I still wish to see less of it in plugins because I find it gets in the way a lot of the time. I imagine lots of new users might feel similar. I do think the offical WP docs contribute to that as well (not a ton of examples with classes etc).

        I have to say reading your story about switching between windows/iis/apache/mac environments, I realize I’m very much married to my current setup. The thought of having to change makes me feel quite inflexible. I guess it’s all about having a really compelling reason to change is key. Reminds me of a recent Ohz post about learning git (when he was quite comfy with svn). I love learning like nothing else, but having to relearn how to do simple things in a different way isn’t always fun (especially when you get the same result as the ‘old’ way).

        Reply
        • Hi @Peter,

          I really appreciate the detailed follow up.

          Okay so my takeaway is that part of the problem is 1.) developers who don’t expose a method to remove or chain hooks, 2.) (lack of) documentation and 3.) that anything besides remove_filter( 'bar', 'foo_bar' ); is non-standard and thus will require discovery and/or more learning.

          So if I got it right, I hear you. (Almost?) everyone on our current team is very concerned about making tools the majority of WordPress site builders will find easy to use. Frankly we’re a lot more interested in discussing how we can better address needs like yours than to debate the more pedantic points about alternate PHP code architectures.

          If our goals are to build significant and reusable open-source libraries — they are — and the goal of this blog is to teach people how to use them and then advocate for their use and standardization then we’ve got to use object-orientation. From our experience not using object-orientation in many cases leads to a level of complexity that we can’t easily manage; I know, I’ve actually tried.

          But so far none of our posts on this blog have even gotten close to the level of complexity I’m talking about. Still we have to start with a foundation to build on.

          If it’s about pushing core changes, I would rather see them make remove_action & remove_filter smarter so that you don’t have to reference the class instance in the first place.

          If you are referring to global scope I don’t see how that would be possible unless you mean to reference class name instead of instance. This approach could become standard if WordPress were to adopt a base class for WordPress plugins which would make this possible: A_Plug_Class::remove_filter( 'hook_name' ); Is that what you are suggesting?

          …without requiring plugin authors to implement workarounds (even pretty elegant ones like yours).

          You wouldn’t know this from reading the blog as we’ve not yet been explicit but we plan future posts to build up to recommending the use of a defacto-standard base class for WordPress plugins and then it won’t be a workaround as it will be built into the base class. And if a lot of plugin developers follow our lead (or if the core WordPress team were to adopt what a similar approach) then it would become a (defacto) standard approach, and that’s our goal.

          As a self taught dev who’s learning was based mostly around WP projects, I am happy that most code I encountered wasn’t object oriented in the early days. I’ve found OO much hard to grasp initially. Now that I’ve got some years under my belt, I’m comfortable with it (just wrote a class yesterday because it made the most sense) but I still wish to see less of it in plugins because I find it gets in the way a lot of the time. I imagine lots of new users might feel similar. I do think the offical WP docs contribute to that as well (not a ton of examples with classes etc).

          As I’ve mentioned in several other comments the techniques described above are not object-oriented. Unfortunately numerous WordPress-related bloggers have called the use of classes to encapsulate function names used for hooks as “object oriented” but that’s a misnomer. All we are doing here is using the class syntax to create defacto namespaces (since PHP doesn’t support namespaces in PHP 5.2.4) and then we also use a few syntactic techniques to ensure we get the visibility we require such as what we need to enabling filter removal. Yes, the syntax is a little more complex, I’ll give you that. But it’s not object-oriented.

          That said, object-orientation is critical for being able to build plugins with advanced functionality. OTOH, there’s no reason real object-orientation needs to be exposed to most site builders if the plugin developers care about meeting the needs of site builders vs. just end users (I know we do.)

          Honestly what would be great is if the core WordPress team would be open to adding more hooks for things like this. For example, if remove_filter() had a filter of it’s own that would allow a plugin developer to filter the $function_to_remove parameter then our plugin could support the following approach for removing a filter: remove_filter( 'the_content', 'Thanks_For_Reading_Plugin::the_content' ); would this approach be better?

          Alas, I’ve found the core team less than amenable to adding filters and actions; more than once they told me there’s not a need which I think makes it really hard for plugin developers to make things easier for site builders in cases like this.

          I have to say reading your story about switching between windows/iis/apache/mac environments, I realize I’m very much married to my current setup. The thought of having to change makes me feel quite inflexible.

          Here’s what my own journey of self-discovery taught me; I really enjoy learning new things but I really don’t enjoy going from highly productive to almost completely unproductive. If I have to learn how to do 5-10 new things before I can get a single new unit of work done that’s when I get annoyed. So it’s evolutionary learning which I embrace and revolutionary learning I abhor.

          I guess it’s all about having a really compelling reason to change is key.

          The reason I switched from IIS/Sql Server/ASP+VBScript to Apache/MySQL/PHP was because I became very disenchanted with the Microsoft and their web stack and the fact that most developer components were commercial meant developers could not build on other developers’s work without having a commerical licensing arrangement in place. So I left the company I founded where we got all the .NET-related add-ons from vendors for free since we were a reseller and started doing web development where I had to pay for all the software I used. All of that made me switch to PHP and I even blogged about it at the start of the process of switching.

          The reason I switched to Mac was I knew lots of the people in Atlanta who were interested in building web startups and almost all of them used Mac. So when I started using Twitter and I would tweet a question asking how to do something on Windows and I would get a shitstorm of replies telling me to get a Mac and if so all my problems would be solved. Rather than fight I finally switched in hopes to be able to get help from the people I knew on Twitter and in person (seriously, that’s really why I switched.) In hindsight they were wrong, the Mac is not a panacea. But while I don’t love the Mac I do see a lot of benefits to it over Windows now that I’m proficient with it.

          Reminds me of a recent Ohz post about learning git (when he was quite comfy with svn).

          Oh I struggle with Git too because it’s so obtuse. OTOH I have always hated SVN. What I really like and still do is Mercurial; how I wish that GitHub supported Hg (as if there were any chance of that!) One of my pet planned projects is to implement a wrapper around Git to make it more Mercurial-like and call it Rational Git.”

          I love learning like nothing else, but having to relearn how to do simple things in a different way isn’t always fun (especially when you get the same result as the ‘old’ way).

          Agreed. And I would say not only not fun but also damn frustrating.

          Anywho, I really do appreciate your comments and hope you’ll feel motivated to leave similar comments on future posts because addressing the issues that people with your perspective have is one of the main reasons we launched this blog. And when we advocate for adding hooks to WordPress it would be helpful if we readers could validate that we do in fact need what we’re asking for.

          Reply
          • I agree with all your points,

            Honestly what would be great is if the core WordPress team would be open to adding more hooks for things like this. For example, if remove_filter() had a filter of it’s own that would allow a plugin developer to filter the $function_to_remove parameter then our plugin could support the following approach for removing a filter: remove_filter( 'the_content', 'Thanks_For_Reading_Plugin::the_content' ); would this approach be better?

            I think definitely it would be better yes.

            Thanks for your thoughts, have your site in my RSS (thanks to Ryan Hellyer)

  3. Pingback: Dependency injection in WordPress | Nothing But Words

  4. I’m trying to remove an action from a function within a Class like this:

    function unhook_appthemes_notices() {
      $instance = CP_User_Dashboard::get_id();
      remove_action( 'appthemes_notices', array( $instance, 'show_notice'));
    }
    add_action ('appthemes_init','unhook_appthemes_notices');

    The class is below …

    class CP_User_Dashboard extends APP_View_Page {
    
      function __construct() {
        parent::__construct( 'tpl-dashboard.php', __( 'Dashboard', APP_TD ) );
      }
    
      static function get_id() {
        return parent::_get_id( __CLASS__ );
      }
    
      function template_redirect() {
        appthemes_auth_redirect_login(); // if not logged in, redirect to login page
        nocache_headers();
    
        // process actions if needed
        self::process_actions();
    
        add_action( 'appthemes_notices', array( $this, 'show_notice' ) );
      }
    
      function process_actions() {
        /* 
         * Do things unrelated to the question…
         */
      }
    
      function show_notice() {
        if ( isset( $_GET['paused'] ) ) {
          appthemes_display_notice( 'success', __( 'Ad has been paused.', APP_TD ) );
        } elseif ( /* ... */ ) {
          /* 
           * And more like this…
           */
        }
      }
      
    }

    For some reason, this doesn’t work. This is driving me crazy.

    Reply
    • Hi @Ovidiu,

      Thanks so much for asking. I love these kind of comments, it’s fun to try to deduce coding problems.

      I cannot tell for sure because you didn’t provide the source code for APP_View_Page::get_id(); I don’t know if it is returning the actual instance or another value. If it is not providing the instance there’s one of your problems; you’ll need to get the actual instance used.

      Assuming you have the correct instance then the problem is almost certainly that the 'appthemes_init' hook you are using is fired before WordPress’ 'template_redirect' hook. Instead of using 'appthemes_init' find the priority AppThemes are using to call CP_User_Dashboard::template_redirect() and use the 'template_redirect' hook with a priority at least 1 higher than they are using which will result in your code being called by WordPress to remove the hook shortly after their code that added the hook is called.

      If AppThemes are using the default priority of 10 (and if $instance does indeed have the actual Singleton instance) then using priorty 11 should probably work:

      function unhook_appthemes_notices() { 
        $instance = CP_User_Dashboard::get_id();
        remove_action( 'appthemes_notices', array( $instance, 'show_notice') ); 
      } 
      add_action( 'template_redirect', 'unhook_appthemes_notices', 11 );

      Hope this helps; please leave a reply comment to let me know either way. If not I’d be happy to figure it out for you if you can get me a full copy of the code to debug. If yes send me an email via my about.me page.

      P.S. I edited you comment for formatting and shorten it to show just the relevant code.

      Reply
    • Hi @Ovidiu,

      Thanks for emailing me your code. I was able to figure out the problem and the problem is that AppThemes does not provide any method to access the Singleton instance of the class they use for their apps. In other words, they don’t follow the best practices I presented in this post! 🙁

      However, never fear; with WordPress there is almost always a way. The solution is to use the excellent function remove_anonymous_object_filter() by Thomas Scholz found in his answer to the question How to remove a filter that is an anonymous object?

      Below is the code I believe should work for you; it removes the 'show_notice' hook from the CP_Add_New class. If you want to remove that hook for all classes you’ll unfortunately need to call the function for each AppThemes class you want it removed from and/or write a custom version of the remove_anonymous_object_filter() function that can remove the hook from a list of classes.

      Here’s the code:

      add_action( 'template_redirect', 'unhook_appthemes_notices' );
      
      function unhook_appthemes_notices() {
        $class_needing_removal = 'CP_Add_New';
        remove_anonymous_object_filter( 'appthemes_notices', $class_needing_removal, 'show_notice' );
      }
      
      if ( ! function_exists( 'remove_anonymous_object_filter' ) ) {
        /**
         * Remove an anonymous object filter.
         *
         * @param  string $tag    Hook name.
         * @param  string $class  Class name
         * @param  string $method Method name
         *
         * @return void
         */
         function remove_anonymous_object_filter( $tag, $class, $method ) {
           $filters = false;
       
           if ( isset( $GLOBALS['wp_filter'][$tag] ) )
             $filters = $GLOBALS['wp_filter'][$tag];
       
           if ( $filters )
             foreach ( $filters as $priority => $filter ) {
               foreach ( $filter as $identifier => $function ) {
                 if ( ! is_array( $function ) )
                   continue;
                 if ( ! $function['function'][0] instanceof $class )
                   continue;
                 if ( $method == $function['function'][1] ) {
                   remove_filter(
                     $tag,
                     array( $function['function'][0], $method ),
                     $priority
                   );
                 }
               }
             }
         }
      }

      Please do let me know in the comments if this meets your needs.

      P.S. Ironically as I added this I got an email from AppThemes announcing ClassiPress 3.3 beta; maybe they’ve added a way to access the Singleton instance in this beta?

      Reply
      • @Mike, @Thomas, you are my heroes, this totally works. Funny enough, I found that function while I was searching for a solution but couldn’t get it to work as I was hooking into the wrong place.
        As for the new ClassiPress Beta 3.3, that class alone, has not been updated but since its a major release… I have a lot of code to review.
        Thanks again for your help.

        Reply
  5. Thanks for the article. I’m still trying to grasp the whole concept. I am struggling with replacing a function that is defined in a class for a installed plug-in.

    the function is:

    public function picker() {
      global $woocommerce;
      ?>
      <table class="variations-table" cellspacing="0">
        <tbody>
          <?php
          $loop = 0;
          foreach ($this->attributes as $name => $options) : $loop++;
            ?>
            <tr>
              <td>
                <label for="<?php echo sanitize_title($name); ?>">
                  <?php echo $woocommerce->attribute_label($name); ?>
                </label>
              </td>
              <td>
                <?php
                if (isset($this->swatch_type_options[sanitize_title($name)])) {
                  $picker_type = $this->swatch_type_options[sanitize_title($name)]['type'];
                  if ($picker_type == 'default') {
                    $this->render_default(sanitize_title($name), $options);
                  } else {
                    $this->render_picker(sanitize_title($name), $options);
                  }
                } else {
                  $this->render_default(sanitize_title($name), $options);
                }
                ?>
              </td>
            </tr>
          <?php endforeach; ?>
        </tbody>
      </table>
      <?php
    }
    

    and the class that it resides in is

    class WC_Swatch_Picker

    So can I just remove that function and replace it with my own based on what you show above, or do I need to re-create the entire class? If I need to show more of the class met me know.

    Reply
    • Hi @Ken,

      Thanks for the comment, and sorry for the late reply.

      I’d love to answer your question but it looks like your code got eaten by the comment system and I’m not 100% sure what you are asking. If you’ll post your code into a Gist and reply with a link to it I’ll update your original comment and then do my best to answer.

      -Mike

      Reply
      • Hey Mike,

        Here is the Gist: https://gist.github.com/anonymous/6504983 it is only a portion of the full php file, but I am hoping that its enough.

        So again this is a function inside of a class. I want to take the function and replace the code with divs. but was not clear how to do this in my functions.php file. if at all possible.

        Thanks

        Ken

        Reply
        • Hi @Ken,

          Thanks for the Gist; I updated the code in your original comment.

          On the other hand, I really want to help but I’m still confused by your description. You say you want to replace the function with divs but the former is a PHP language structure and the latter is a markup element in HTML so I’m still not sure what you mean. Do you mean that you want to replace the function’s output of <table>, <tr> and <td> elements with <div> elements? If not, can you explain in a different way?

          Also, is this part of the WooCommerce open-source code and available for download so I can look at it, or is it a paid 3rd party extension? If the above is correct then the answer you want is likely to be to subclass the current class and override the method, but that will only work if you can override the code that instantiates the class and replace it with your extension of said class. So I need to see more of the code to be able to give better guidance.

          -Mike

          Reply
          • You are correct, I want to change the output of the <table> elements and use a <div> with some of my own classes.

            Unfortunately it is a 3rd party extension sold on woo’s website it is for the variable swatches plug-in. That is why I only posted a snippet of that entire class. Maybe there is some other way I can share more of the class or get you the details you need?

          • Hi Ken,

            Okay, thanks for sending me the plugin via email. I think I’ve got my head wrapped around what you need.

            First, the class WC_Swatch_Picker is only called from the file in the plugin directories /templates/single-product/variable.php which appears to be a template that is used if you don’t provide your own, correct?

            Assuming that you provide your own template in place of variable.php then the way to achieve your goal is to subclass WC_Swatch_Picker and call it instead in your own template that overrides variable.php. Here’s what that subclass code would look like, and you can put in your functions.php file if you like:

            
            class Kens_Swatch_Picker extends WC_Swatch_Picker {
              public function picker() {
                // Copy WC_Swatch_Picker picker()'s code and modify for your needs.
              }
            }
            

            While there are many ways to override and extend code in WordPress, sometimes there only a few ways that are viable, and in this case that is one of the few viable ways to achieve your end goal because Lucas Stark did not implement a official way via hooks or some other approach to achieve what you need.

            Hope this helps?

            -Mike

  6. I am converting a plugin that does not follow modern WP plugin architecture. It’s a plugin that uses the ImageMagick image library for creating images instead of WP’s default.

    The original plugin is just a bunch of functions and at the bottom of the code the add_filter('image_make_intermediate_size','imagick_sharpen_resized_files',900); filter and it works fine, both when uploading new images or with the use of the “Regenerate Thumbnails” plugin

    Now I am trying to convert the plugin, wrapping in a class with the add_filter() added in the __construct() but I get:

    Warning: call_user_func_array() expects parameter 1 to be a valid callback,
                      function \'magic_sharpen_watermark\' not found or invalid function
                      name in /Applications/MAMP/htdocs/claireobscuur/wp-includes/plugin.php
                      on line 213

    I tried placing the filter in various positions in the class, even outside but still get the error.
    I also tried your singleton method from this page but still get the error.
    I am a NON coder and just want to get things done, why do they make it so diffucult for us a create a simple plugin following best practices?

    Here is my code:

    < ?php 
    
    class MySettingsPage {
    
    	private static $_this;
    	private $options; 
    
    	public function __construct() {
    		self::$_this = $this;
    		add_filter( 'image_make_intermediate_size', array( $this, 'magic_sharpen_watermark'), 900 );
    		
    		add_action( 'admin_menu', array( $this, 'add_plugin_page' ) );
    		add_action( 'admin_init', array( $this, 'page_init' ) );
    	}
    	
    	static function this() {
    		return self::$_this;
    	}
    	
    	public function add_plugin_page() {
    		add_options_page( 'Settings Admin', 'Magic Sharpen Watermark', 'manage_options', 'msw_setting_admin', array( $this, 'create_admin_page' ) );
    	}
    	
    	public function page_init() {        
    		register_setting( 'msw_option_group', 'co_msw_options', array( $this, 'sanitize' ) );
    		/* ... add_settings_section(), add_settings_field() etc. ... */
    	}
    	
    	public function create_admin_page() {
    		$this->options = get_option( 'co_msw_options' );
    		/* ... 
    ... */ } public function magic_sharpen_watermark($resized_file) { $image = new Imagick($resized_file); /* ... */ $image->writeImage($resized_file); return $resized_file; } } if ( is_admin() ) { $my_settings_page = new MySettingsPage(); // add_filter( 'image_make_intermediate_size', array( 'MySettingsPage', 'magic_sharpen_watermark'), 900 ); // did not work }
    Reply
  7. Hi @Anton,

    Thanks for the comment. Sorry it’s hard for a non-coder; coding is unfortunately something that can take a long while to learn.

    I reviewed your code, and even tested it, and it works fine, ignoring the parts INSIDE magic_sharpen_watermark(). I could not get it to trigger the same error.

    Maybe you do not have Imagick on your system? Or maybe you have a really old version of PHP on your server (although I’m just guessing at that?)

    -Mike

    Reply
  8. Hi Mike, I need help in removing an action of wordpress within a public function of class. I want to remove OLD function and want to define a new function against it. I tried but failed to do.

    Code looks like below:

    function hook_link($c){ return  apply_filters( 'hook_link', $c);  }
    
    class blue_themes {
       public function blue_themes(){
          add_action( 'hook_link', array($this, 'OLD') );
       }
       function OLD($val){ //want to remove this action
          return $val;
       }       
    }
    
    Reply
    • Hi @Sunil,

      Thanks for the comment.

      To remove that action you will need to get the same instance of the class that blue_themes is using when it added the action. Does the class file end with an instantiation of the blue_themes class, with code that looks something like this?

      $blue_them = new blue_theme();
      Reply
          • @mikechinkel I am Waiting for that post because I tried some method but they are not working. May be I tried wrong syntex. Googled so many pages but still failed.

          • @Sunil – Which plugin is it you are trying to do this with? Can i download it from somewhere to see the full source code?

          • Its a premium theme. I can provide full theme source code. Please contact me via email to provide source code.

    • Hi @Sunil –

      I know you are anxious for the answer and I doubt I will have time to write a new post in the near term so here’s the answer below.

      You told me via email that the theme was the Premium Press Auction theme and that you wanted to remove the hook that calls the PRICE() method that was added with this code:

      add_action( 'hook_price', array($this, 'PRICE') );
      

      Further you told me that the theme’s _config.php file contained the following line:

      $CORE = new white_label_themes;  
      

      With that information I was able to provide you with a solution. Since $CORE is a global variable then the following line should remove the hook for you:

      remove_action( 'hook_price', array( $GLOBALS['CORE'], 'PRICE') );
      

      Here’s a full plugin that should do the job:

      <?php
      /**
       * Plugin name: Remove Premium Press Auction Theme Price Hook
       */
      class Remove_Premium_Press_Auction_Theme_Price_Hook {
      	static function on_load() {
      		add_action( 'after_setup_theme', 
      			 array( __CLASS__, '_after_setup_theme' ) );
      	}
      	static function _after_setup_theme() {
      		remove_action( 'hook_price', array( $GLOBALS['CORE'], 'PRICE') );
      	}
      }
      Remove_Premium_Press_Auction_Theme_Price_Hook::on_load();
      

      Let me know if this solves your issue.

      -Mike

      P.S. BTW, in some ways the theme appears to be well-coded but in other ways, such as naming a global variable $CORE the theme is awful! A theme vendor should never create a generically named global variable, and ideally the theme vendor should create no global variables at all and instead create classes with a rather unique name, such as Premium_Press_Auction, for example.

      And the entire theme is filled with generically named functions, which means there’s a great chance of conflict with a plugin that is also architected in a similarly poor manner. Caveat Emptor!

      Reply
  9. Hi @Anastasia,

    Thanks for your comment.

    I downloaded WordPress SEO and think this is what you need; you can add to your theme's functions.php file:

    add_action( 'template_redirect', 'Anastasia_Remove_WP_SEO_OpenGraph_Hook', 1000 );
    function Anastasia_Remove_WP_SEO_OpenGraph_Hook() {
        if ( ! isset( $GLOBALS['wpseo_og'] ) {
            return;
        }
        if ( ! is_a( $GLOBALS['wpseo_og'], 'WPSEO_OpenGraph' ) ) {
            return;
        }
        remove_filter( 'language_attributes', array( 
            $GLOBALS['wpseo_og'], 
            'add_opengraph_namespace' 
        ));
    
    }
    

    First we used a priority of 1000 which is +1 the value of 999 that WordPress SEO used to set the hook here.

    Next you'll notice we access the global object $GLOBALS['wpseo_og']. That object was assigned on this line in wpseo_frontend_head_init().

    The $GLOBALS['wpseo_og'] object is an instance of the WPSEO_OpenGraph class that contains a __construct() that sets the hook you want to remove.

    Finally we call removed_filter() to remove the filter. This all gets called at priority 1000 on the template_redirect hook right after the wpseo_frontend_head_init() function is called at priority 999.

    How this helps?

    -Mike

    Reply

Leave a reply

<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code lang=""> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong> <pre lang="" extra=""> 

required