31

I have a Plugin installed on my WordPress site.

I'd like to override a function within the Plugin. Do I override this in my theme's functions.php and if so, how do I do this?

Here's the original function in my plugin:

    /**
     * sensei_start_course_form function.
     *
     * @access public
     * @param mixed $course_id
     * @return void
     */
    function sensei_start_course_form( $course_id ) {

        $prerequisite_complete = sensei_check_prerequisite_course( $course_id );

        if ( $prerequisite_complete ) {
        ?><form method="POST" action="<?php echo esc_url( get_permalink() ); ?>">

                <input type="hidden" name="<?php echo esc_attr( 'woothemes_sensei_start_course_noonce' ); ?>" id="<?php echo esc_attr( 'woothemes_sensei_start_course_noonce' ); ?>" value="<?php echo esc_attr( wp_create_nonce( 'woothemes_sensei_start_course_noonce' ) ); ?>" />

                <span><input name="course_start" type="submit" class="course-start" value="<?php echo apply_filters( 'sensei_start_course_text', __( 'Start taking this Course', 'woothemes-sensei' ) ); ?>"/></span>

            </form><?php
        } // End If Statement
    } // End sensei_start_course_form()
michaelmcgurk
  • 6,367
  • 23
  • 94
  • 190

5 Answers5

17

You can't really "override" a function. If a function is defined, you can't redefine or change it. Your best option is to create a copy of the plugin and change the function directly. Of course you will have to repeat this everytime the plugin is updated.

Give the plugin a different name to distinguish them in the plugin listing. Disable the original, enable your copy.

Gerald Schneider
  • 17,416
  • 9
  • 60
  • 78
  • 1
    it might be worth mentioning that duplicating a plugin hence obviously also disables any potential important (e.g. security-related) updates – m1ck Feb 05 '23 at 02:43
  • just my 2 cents. I have a few projects where big plug-ins are being altered on some places. To maintain the right version control in this editing flow i'm using GitHub for reviewing an update and merging the custom changes that were previously made. This does help with updating such plug-ins manually + it keeps a nice version control of it all. You could in some cases also use .gitignore in your advantage so that the plug-in update doesn't override your self made changes. – Deathstorm Mar 28 '23 at 21:15
14

I know this is late but in the event that someone else finds this post. A simpler solution is to make a copy of the function if you can to your themes functions file and rename it so that it doesn't conflict with the original function. Then use your new function in place of the original. That way you can update the plugin files without affecting your changes.

Braeden Black
  • 443
  • 4
  • 6
12

You can do it by using add_filter() function.
See wordpress stackexchange: Override plugin with functions.php

Just add the below code in theme's functions.php file.

add_filter('sensei_start_course_form','MyCustomfilter',$priority = 10, $args = 1);

function MyCustomfilter($course_id) { 
// Do your logics here
}
Community
  • 1
  • 1
Noman
  • 4,088
  • 1
  • 21
  • 36
  • 14
    `add_filter()` only works for existing hooks. You can't override funtions with it. – Gerald Schneider Oct 15 '15 at 12:11
  • 1
    @michaelmcgurk change priority (`change this $priority = 10 to this $priority = 9999 ` ) to call your custom filter , try adding `die('callingmy function');` in `MyCustomfilter` function – Noman Oct 15 '15 at 12:13
  • @GeraldSchneider Can you tell me an alternative approach to achieve this? I'd rather not edit the plugin directly if I can help it. – michaelmcgurk Oct 15 '15 at 12:25
  • 1
    There is no other way. – Gerald Schneider Oct 15 '15 at 12:26
  • @GeraldSchneider Really? Gulp :( – michaelmcgurk Oct 15 '15 at 12:27
  • 13
    This works, but only if the original plugin author has been forward-thinking enough to add a `add_filter()` to the original function. If not, then the hook isn't available. This answer solved my issue, but only because the function I wanted to latch on to was open to overrides. – Rillus Jun 30 '18 at 06:44
  • There is NO filter for sensei_start_course_form. God knows how you got 12 upvotes! – Michelle Jul 15 '23 at 09:07
8

A bit late on this (november 2021) but I still found this answer today, so I'll add a solution I didn't see around:

For some historical reasons, WP still has the ability to add "must use" plugins that runs before all other plugins. So this give us the opportunity to add the function you want to override, so it already exists when the original plugin run.

In your case

  1. add a .php file in the folder wp-content/mu-plugins let say
wp-content/mu-plugins/custom-override.php
  1. add your function in custom-override.php :
if ( ! function_exists( 'sensei_start_course_form' ) ) {
         function sensei_start_course_form( $course_id ) {
             //your magic here
             //...
         }
    }

  1. be sure that the original plugin also has this conditional "if function doesn't already exists..."
if ( ! function_exists( 'sensei_start_course_form' ) ) { ... 

This did the trick for me ;-)

PD: I'm not an expert, please give me some feedback if this is wrong somehow. Thanks

REF: https://wordpress.org/support/article/must-use-plugins/

jenciso
  • 145
  • 3
  • 7
0

I also needed to change some code in a WordPress plugin. So I created a function that can be placed in functions.php in your child-theme. Please test before use! It is probably poor written since I'm no PHP expert. But the concept works for me. I tested it first outside WordPress so some variables like $root should/could be modified.

Situation was that I had to change some values in two different files in the plugin Email posts to subscribers.

I needed to change $home_url = home_url('/'); to $home_url = 'custom-redirect-url'; and 'content="10; to 'content="1; in the files optin.php and unsubscribe.php.

Every time the plugin gets updated it runs a function after the update. This is the code I use:

// Function that replaces the code
function replace_text_plugin_email_posts_to_subscribers($pluginTargetFile, $replaceURL) {

    $root = $_SERVER['DOCUMENT_ROOT']; 

    $replaceThis = array("\$home_url = home_url('/');", "content=\"10;");
    $withThis   = array($replaceURL, "content=\"1;");

    $fname = $root . $pluginTargetFile;
    $fhandle = fopen($fname,"r");
    $content = fread($fhandle,filesize($fname));
    $content = str_replace($replaceThis, $withThis, $content);

    $fhandle = fopen($fname,"w");
    fwrite($fhandle,$content);
    fclose($fhandle);
}


//Function that runs every time that email-posts-to-subscribers is updated

function my_upgrade_function( $upgrader_object, $options ) {

    $current_plugin_path_name = 'email-posts-to-subscribers/email-posts-to-subscribers.php';

    if ($options['action'] == 'update' && $options['type'] == 'plugin' ) {
        foreach($options['plugins'] as $each_plugin) {
            
            if ($each_plugin==$current_plugin_path_name) {
       
                replace_text_plugin_email_posts_to_subscribers("/wp-content/plugins/email-posts-to-subscribers/job/optin.php","\$home_url = 'https://example.com/redirect-optin';");
                replace_text_plugin_email_posts_to_subscribers("/wp-content/plugins/email-posts-to-subscribers/job/unsubscribe.php","\$home_url = 'https://example.com/redirect-unsubscribe';");

            }
        }
    }
}

add_action( 'upgrader_process_complete', 'my_upgrade_function',10, 2);

I guess this wil only be of use when you have to adjust some minor things. Rewriting complete code is maybe not working with this code, but I didn't test this.

WillCom
  • 1
  • 1