Welcome to Geeklog, Anonymous Thursday, April 18 2024 @ 07:52 pm EDT

Geeklog Forums

Overriding/Inheriting COM_*** function


Phize

Anonymous
Hello, all.

You know we can replace 'COM_siteHeader'/'COM_siteFooter' function with 'Theme_siteHeader'/'Theme_siteFooter' in functions.php, but cannot replace other 'COM_***' function in this way.
This is the the hack emulates Overriding/Inheriting 'COM_***' function in '/public_html/lib-common.php'.

I really wish Geeklog would merge this hack by the default because It enables us to extend the functions and expand the use of Geeklog, though I think it should be discussed.
If all would feel it's good, I should be happy Big Grin

The advantage of this hack:
1.Emulating Overriding/Inheriting 'COM_***' function.
2.Enabling us to extend Geeklog's functions without hacking the core-script, with minimum hack.
3.Protecting 'COM/Theme_***' function from infinite loops.
etc.

How to hack:
1. Modify/Insert some code in the head of each 'COM_***' function in '/public_html/lib-common.php' like an example.

This is an example of 'COM_getBlockTemplate' function.
Text Formatted Code
 function COM_getBlockTemplate( $blockname, $which )
{
    global $_BLOCK_TEMPLATE, $_COM_VERBOSE;

   // *** The hack begins ***
   // If the theme implemented this for us then call their version instead.
    global $_CONF;    
    $function = $_CONF['theme'] . '_getBlockTemplate';  // 'getBlockTemplate' should be replaced with function's name.
    $bt = debug_backtrace();

    if(( strtolower(@$bt[0]['function']) !== strtolower($function)) && ( strtolower(@$bt[1]['function']) !== strtolower($function)) && function_exists( $function ) ) {
        return $function( $blockname, $which );  // '$blockname, $which' should be replaced with function's parameters.
    }
   // *** The hack ends ***
 


Usage(an example):
After this hack, we can replace 'COM_getBlockTemplate' with 'Theme_getBlockTemplate' in functions.php like present 'COM_siteHeader/Footer' function.
In addition, we can call 'COM_getBlockTemplate' function from 'Theme_getBlockTemplate' function.

An example by kino who is a member of Geeklog Japanese.
Text Formatted Code
function Theme_getBlockTemplate( $blockname, $which ){
        global $_TABLES,$_BLOCK_TEMPLATE;
       
        $result = DB_query ("SELECT onleft,name FROM {$_TABLES['blocks']} WHERE is_enabled = 1");
        $nrows = DB_numRows ($result);
        for ($i = 0; $i < $nrows; $i++) {
            $A = DB_fetchArray ($result);
                if ($A['onleft'] == 1) {
                    $_BLOCK_TEMPLATE[$A['name']] = 'blockheader-left.thtml,blockfooter-left.thtml';
                } else {
                    $_BLOCK_TEMPLATE[$A['name']] = 'blockheader-right.thtml,blockfooter-right.thtml';
            }
        }

    $retval = COM_getBlockTemplate( $blockname, $which );  // call 'COM_getBlockTemplate' from 'Theme_getBlockTemplate' !!
    return $retval;    
}


Thank you for reading.

-----------
Phize
 Quote

Status: offline

jmucchiello

Forum User
Full Member
Registered: 08/29/05
Posts: 985
Isn't the array that COM_getBlockTemplate uses to find the template files is already in the theme's functions.php file? The example from kino could just be outside a function in the functions.php file. There's no reason to update the BLOCK_TEMPLATE structure every time there a call to COM_getBlockTemplate. In fact doing so slows your system down since the SQL will return the same data. On my test system I added:

echo "Call to COM_getBlockTemplate(blockname=$blockname, which=$which)<br>";

to COM_getBlockTemplate and it seems it was called 12 times. That's twelve times you would be hitting the blocks table per website hit and of course that's silly since the details in the blocks table will not change during a single website hit.

If you really need this kind of functionality, you ask them to do the function correctly.
Text Formatted Code
function COM_getBlockTemplate( $blockname, $which )
{
    global $_BLOCK_TEMPLATE, $_COM_VERBOSE;

    if ($_COM_VERBOSE) {
        COM_errorLog( "_BLOCK_TEMPLATE[$blockname] = " . $_BLOCK_TEMPLATE[$blockname], 1 );
    }

    $function = $_CONF['theme'] . '_getBlockTemplate';
    if (function_exists($function)) {
        $template = $function($blockname, $which);
        if (!empty($template)) {
             return $template;
        }
    }
// rest of code
The kino's example should be:
Text Formatted Code

$_BLOCK_TEMPLATE = Array();

function Theme_getBlockTemplate( $blockname, $which ){
    global $_TABLES,$_BLOCK_TEMPLATE;

    if (empty($_BLOCK_TEMPLATE)) {
        $result = DB_query ("SELECT onleft,name FROM {$_TABLES['blocks']} WHERE is_enabled = 1 " . COM_getPermSQL('AND'));
        $nrows = DB_numRows ($result);
        for ($i = 0; $i < $nrows; $i++) {
            $A = DB_fetchArray ($result);
            if ($A['onleft'] == 1) {
                $_BLOCK_TEMPLATE[$A['name']] = 'blockheader-left.thtml,blockfooter-left.thtml';
            } else {
                $_BLOCK_TEMPLATE[$A['name']] = 'blockheader-right.thtml,blockfooter-right.thtml';
            }
        }
    }
    return ''; // empty return falls through for normal processing
}

And of course, as I said, this could also be:
Text Formatted Code
//inside functions.php of the theme:

$_BLOCK_TEMPLATE = Array();
$result = DB_query ("SELECT onleft,name FROM {$_TABLES['blocks']} WHERE is_enabled = 1 " . COM_getPermSQL('AND'));
$nrows = DB_numRows ($result);
for ($i = 0; $i < $nrows; $i++) {
    $A = DB_fetchArray ($result);
    if ($A['onleft'] == 1) {
        $_BLOCK_TEMPLATE[$A['name']] = 'blockheader-left.thtml,blockfooter-left.thtml';
    } else {
        $_BLOCK_TEMPLATE[$A['name']] = 'blockheader-right.thtml,blockfooter-right.thtml';
    }
}

But I digress. Using debug tracing to allow functions to call out to other functions and back is much more safely done using controlled return codes. An empty return from THEME_getBlockTemplate is also much easier to understand for new readers of the code.
 Quote

Status: offline

kino

Forum User
Newbie
Registered: 06/14/06
Posts: 14
Location:Japan
hello.
I'm kino.

It is because a theme wasn't applied when making a plug-in effective with the management screen that we needed this code.

I attempted to change as follows because there was wasteful access as the pointing-out.

Text Formatted Code

function Theme_getBlockTemplate( $blockname, $which ){
        global $_TABLES,$_BLOCK_TEMPLATE;
       
        $result = DB_query ("SELECT onleft,name FROM {$_TABLES['blocks']} WHERE is_enabled = 1 AND name='{$blockname}';" );
        echo DB_numRows ($result);
        if(DB_numRows ($result)>0){
            $A = DB_fetchArray ($result);
                if ($A['onleft'] == 1) {
                    $_BLOCK_TEMPLATE[$A['name']] = 'blockheader-left.thtml,blockfooter-left.thtml';
                } else {
                    $_BLOCK_TEMPLATE[$A['name']] = 'blockheader-right.thtml,blockfooter-right.thtml';
            }
        }
               
        $retval = COM_getBlockTemplate( $blockname, $which );  // call 'COM_getBlockTemplate' from 'Theme_getBlockTemplate' !!
    return $retval;
}
 

 Quote

Status: offline

jmucchiello

Forum User
Full Member
Registered: 08/29/05
Posts: 985
I still don't understand. The loading of BLOCK_TEMPLATE happens in functions.php of the professional theme outside of any functions. Once it is loaded, why load it again? You don't need to put it into a function. Just load it in the theme's functions.php like professional does.

Unless you are coding specific blocks versus specific users there's no need to override COM_getBlockTemplate. And as I posted above, the proper way to modify COM_getBlockTemplate is to look for THEME_getBlockTemplate and call it. If it returns a string return it, otherwise perform the rest of the code in COM_getBlockTemplate. No need to jump through hoops with debug_backtrace.

In other words, this design style is more in keeping with Geeklog
1) Call a standard call
2) If an override function exists
2a) Call it if it return NULL or FALSE go to step 3
2b) Otherwise pass return to caller. Stop.
3) Continue with standard processing
4) Return result to caller.

If the override function is called it:
1) Checks to see if it should override
1a) If it should not override, return FALSE or NULL to the original function. Stop.
1b) Process the inputs
2) Return valid result to main function.

There's no reason for the override function to call the original function.
 Quote

All times are EDT. The time is now 07:52 pm.

  • Normal Topic
  • Sticky Topic
  • Locked Topic
  • New Post
  • Sticky Topic W/ New Post
  • Locked Topic W/ New Post
  •  View Anonymous Posts
  •  Able to post
  •  Filtered HTML Allowed
  •  Censored Content