Fork me on GitHub

tutorial : functions overriding  Bottom

  • Problem:

    for a given module, you need to add a special function specific to your code. For instance, you have added a little Ajax part to your template, and you want to add on Ajax function on the server side. You can add it directly in "modules/[modname]/pnajax.php" . BUT it's not easily "maintainable", you will have to edit the pnajax file each time there is an update of the module

    Solution:

    Zikula implements a really interesting systeme, which allow you to add (or override) function to your module without touching it. Indeed, you store your functions in a separate file , and zikula will automatically look in this file to execute the given function.

    How to

    It simple if you ve got a "[modname]_[type]_[func]", create a file with the following syntaxe

    Code

    config/functions/<modname>/pn<type>/<func>.php


    And then copy your function in it

    For instance, if you've got a News_ajax_edit() function, go to

    Code

    config/functions/News/pnajax/edit.php

    and put your function in it.

    then when you will upgrade your module your function won't be affected (this has to be used with template overriding :) )

    Thanks to Mateo and Guite for their help
    http://code.zikula.org/core/ticket/651

    Notes:i m not sure it's possible to override function if you ve got modules/modname/pnuser.php, which could be interesting for function like "encode()" or "decodeurl()" for rewriting urls

    Notes bis: if you can put your function in "themes/[mytheme]/functions/[modname]/[type]/[func].php" too




    edited by: mumuri, Dec 10, 2008 - 03:51 AM
  • Luke, now you know the power of the core-force icon_wink

    A function already defined in pnuser.php will be used instead search for your custom one. include it will result in a PHP Fatal error: function redeclared.
    We can separate the userapi functions of the ValueAddons modules (and in general that would be a nice practice for the third party modules, i've already saw it in some) to put the encodeurl and decode URL into /modules/ModName/pnuserapi/encodeurl.php and decodeurl.php, then we'll be able to override it from config/functions/ModName/pnuserapi/**codeurl.php, and that's very very good icon_wink

    We already can do that on MediaAttach and others icon_cool

    Note: config is recommended instead themes unless you need theme-specific functions. With Ajax, the theme-layer is not loaded and custom functions in themes will not work.

    --
    - Mateo T. -
    Mis principios... son mis fines
  • Hey,

    I came across this thread just as I was about to take the butcher's knife to Pagesetter...

    I have followed the instructions yet I still get the dreaded message:

    Code

    We're sorry. The page you requested, /~julian/ica/index.php?module=Page&type=results&func=uploadresults, doesn't exist on "Illinois Cycling Association".


    I have created config/functions/pagesetter/pnresults/uploadresults.php with my function but it doesn't work. Here's the function (just for testing...)

    Code

    function pagesetter_results_uploadresults() {
       
        echo "hello world!;
    }


    Is there something fishy because this is a local testing site on my mac or is something else wrong? Even when I add the function to the core pageseter files I get nothing...!!

    --
    Burnham Racing
    Illinois Cycling Association
  • Nevermind... I'm an idiot. I have it working now...

    --
    Burnham Racing
    Illinois Cycling Association
  • Hi

    I dont know what Im dooing wrong with overriding:

    I have changed function pagemaster_user_executecommand ()
    I have created folder config/functions/pagemaster/pnuser/
    I have placed function in file named executecommand.php in above path
    Overrided function stay oryginal

    Code

    <?php
    /**
     * Executes a Workflow command over a direct URL Request
     *
     * @param $args['tid']
     * @param $args['id']
     * @param $args['goto'] redirect to after execution
     * @param $args['schema'] optional workflow shema
     * @param $args['commandName'] commandName
     * @author kundi
     */


    Loader::includeOnce('modules/pagemaster/common.php');

    function pagemaster_user_executecommand()
    {
        $tid         = FormUtil::getPassedValue('tid');
        $id          = FormUtil::getPassedValue('id');
        $commandName = FormUtil::getPassedValue('commandName');
        $schema      = FormUtil::getPassedValue('schema');
        $goto        = unserialize(base64_decode(FormUtil::getPassedValue('goto')));

     ................
     
      }
    }


    but it is not working as it sopoused to it is not overriding
    If Im making changes in modules/pagemaster/pnuser.php > pagemaster_user_executecommand()
    everything is ok

    What Im dooing wrong?

    --
    rgfdgafgaf
  • Assuming that in order to execute an override, the functions must be separated into individual files, then it extremely would be helpful, if *all* third-party module developers and Zikula core developers would adhere to separating all functions into individual files, instead of grouping everything in one file such as "pnuser.php", "pnadmin.php", etc.

    This will make it very helpful when needing to do function overrides, and much easier to manage, since specific function hacks can be contained in individual instances, instead of buried in the grouped file such as "pnuser.php"

    Doing this for the "News" module, and other assumed highly-used modules, would be a great place to start.
  • What, if any, performance issues are there with doing that as a matter of practice? I mean it's gonna make a bear of a messy looking file system, but.

    --
    Home Page | Find on Facebook | Follow on Twitter
  • I think grouping functions in pnuser etc files its good and its clear, dont have idea how it is affecting performance.

    At the moment im struggling with this overriding... actually I was... I have found what was wrong I'm using Zikula 1.1.2 on one website and 1.2 on another and both zikulas act in same way.

    I had to delete/rename original function to get function from config/functions/pagemaster/pnuser/
    Then I have done some test and it is not working from themes/mytheme/config/functions/pagemaster/pnuser/ I think it is down to error in this $file = 'themes/'.$theme['directory']."/functions/$modname/pn{$type}{$ftype}/$func.php"

    Don't understand what you mean by "overriding" when actually overriding part in pnMod.php look like this and it is not overriding at all... shouldn't it look first for function in theme then in config then in module ?

    Code

    function pnModFuncExec ($modname, $type='user', $func='main', $args=array(), $api=false)
    {
        // define input, all numbers and booleans to strings
        $modname  = isset($modname) ? ((string)$modname) : '';
        $ftype    = ($api ? 'api' : '');
        $loadfunc = ($api ? 'pnModAPILoad' : 'pnModLoad');

        // validate
        if (!pnVarValidate($modname, 'mod')) {
            return null;
        }

        $modinfo = pnModGetInfo(pnModGetIDFromName($modname));
        $path = ($modinfo['type'] == '3' ? 'system' : 'modules');

        // get the theme
        if ($GLOBALS['loadstages'] & PN_CORE_THEME) {
            $theme = ThemeUtil::getInfo(ThemeUtil::getIDFromName(pnUserGetTheme()));
        }
        // Build function name and call function
        $modfunc = "{$modname}_{$type}{$ftype}_{$func}";
        if ($loadfunc($modname, $type)) {
            if (function_exists($modfunc)) {
                return $modfunc($args);
            } else {
                if (($GLOBALS['loadstages'] & PN_CORE_THEME) && file_exists($file = 'themes/'.$theme['directory']."/functions/$modname/pn{$type}{$ftype}/$func.php")) {
                    Loader::loadFile($file);
                    if (function_exists($modfunc)) {
                        return $modfunc($args);
                    }
                } elseif (file_exists($file = "config/functions/$modname/pn{$type}{$ftype}/$func.php")) {
                    Loader::loadFile($file);
                    if (function_exists($modfunc)) {
                        return $modfunc($args);
                    }
                } elseif (file_exists($file = "$path/$modname/pn{$type}{$ftype}/$func.php")) {
                    Loader::loadFile($file);
                    if (function_exists($modfunc)) {
                        return $modfunc($args);
                    }
                }
            }
        }




    edited by: Kaik, datetimebrief

    --
    rgfdgafgaf
  • Ok im smoking too much of bad things...

    There is a way to add function and override it I just follow mumuri's post thinking that it is a way to override.

    So adding func

    Code

    config/functions/<modname>/pn<type>/<func>.php


    overriding

    Code

    config/functions/<modname>/pn<type>.php with changed func.


    It is working :)



    edited by: Kaik, datetimebrief

    --
    rgfdgafgaf

This list is based on users active over the last 60 minutes.