Best Practices for Modifying Core Plugins

At first glance, it appears that the only way to really get in and make dramatic changes to a core plugin is the get in and actually modify the plugin (especially if there is a need for additions to the start.php or index.php file for that plugin).

This seems as though it will cause upgrade problems/difficulties for us in the future if we do this.  Does anyone have any suggestions for the best way to add functionality to core plugins and not cause too many issues when it comes time to upgrade my site?

  • Here is what we do:

    1. If significant functionalty is being changed or added, we fork and don't use the core plugin anymore.
    2. There is a lot you can do by just creating another plugin that changes functionality: every vew can be overridden, page handlers can be replaced, actions can be replaced, other stuff can unregistered, language strings can be overridden.
    3. If the changes *require* editing files/functions, try to feed the changes back by using if they are general. If not, we maintain the changes in our version control system. When new versions of the core plugins come out, we do diffs and try to patch. We also comment out functions and redefine them in our plugin that adds new functionality to the core plugin - try to keep the changes atomic.
  • Thanks Cash.

    This really just confirms what I was thinking.  This was pretty much what we have been doing (modifying the code in our own repo).  We haven't had to go through the merge/patch process yet (no new releases since we started coding).  Most of the changes have been pretty custom and not too beneficial yet for public consumption.

    Once example is a custom relationship we have created.  We wanted to add a tab to the riverdashboard so you can filter and view activity for that custom relationship.  Since it appears that most of the tab logic is done in the index.php file (and I am still not sure if I can override/extend a plugin's index.php file) we have forked our own version of the riverdashboard plugin.  It seemed a little much to me that I would need to fork the entire plugin just to add a few lines of code to the index.php.  This is why I decided to ask.  it wouldn't be the first time I did it the hard way first only to learn later on that the framework had already provided a nice solution to my problem. 

    Thanks again.

  • Typically index.php is included by a page handler.  That seems to be the case with riverdashboard, so you could replace the handler with your own.  (Hopefully the index.php script is not invoked explicitly in some URLs.)  Depending on how your tab is done, you might even be able to just include the original index.php so that you don't need to duplicate code.  That is naively,

    function tabbed_riverdashboard_page_handler($page) {
        echo '<div class="riverdashboard_tab">';
        if filter tab selected then
            do custom stuff;
            riverdashboard_page_handler();  // include original index.php
        echo '/<div>';
        return true;

    When touching stock Elgg code cannot be avoided, I prefer to just strategically add a few calls to elgg_view() (or even to custom functions), for better separation of real custom code and for easier upgrade time.

  • @Plai Thanks for the suggestions.  I will try this.  The more I learn about ELGG the more I learn I can pretty much override anything.  It is just a matter of finding the "how" (which has been the most difficult part of ELGG).  

    If I could just find that link to the "Definitive Guide to learning PHP using the ELGG Framework".  (By the way I would buy that book is someone wrote it).  Thanks again.

  • Daniel,

    A technique I've been using lately is client side modification of Elgg created pages.  For instance, if you just want to replace one small item's text, rather than overriding the entire view, you can use jQuery to make the change for you on the client side.

    For example, the Invite new users functionality has a button that says "Save", when it really should say "Send".  What a pain to copy the view and override that one word.

    So instead, you can extend the offending view (rather than overwriting it), and include some jQuery to change the text, something like:

    <script type="text/javascript">
        $(document).ready(function() {
            $('input .... (whatever you need').text("Send");

    I've acutally wrapped the above into its own view, which I call using a function:

        function jqueryTextReplace($selector, $newText)
            set_input('textReplaceSelector', $selector);
            set_input('textReplaceNewText', $newText);   

    I wouldn't do this sort of thing all the time, but for small changes it's not too bad. 

    But you could also make bigger changes using the same technique.  Like adding a new tab to the group listing - extend the core view, adding some monster div, then use jQuery to move your div into the right place in the DOM structure.

    Oh, and one other thing I just instituted today - formal commenting guidelines to identify what I'm modifying/extending in other people's code.