Forum for discussing general topics related to Couch.
4 posts Page 1 of 1
Hi Kamran,

After being away for a long time from my code of CustomParams class, I have decided to give it another look. I know you are always interested in what I am coding and you have already reviewed that Class, so I think it is a good idea to share the news with you. I think discussing it in forum is okay, if you don't mind.

In retrospective, I wanted to add any custom parameter to any stock or custom tag. I have noted that some parameters are best handled before tag executes -
Code: Select all
<cms:pages ignore='1'>
    .. some very long code that is hard to wrap in <cms:ignore></cms:ignore>.
</cms:pages>


While other parameters are needed to work with tag's value (or generated HTML) after tag executed -
Code: Select all
<cms:set test = "<cms:gpc 'myvar' />" debug='1'/>

Example output:
----------- Debug of tag 'set': -----------
Value:
Params:
[
    {
        "lhs": "test",
        "op": "=",
        "rhs": ""
    }
]
----------- /set -----------


I have merged both Classes into a single one (which is your great suggestion). It suddenly (by a miraculous coincidence) appeared to me that certain tags rely on all provided parameters, consider my modded tag <cms:add> -
Code: Select all
Example of my modded tag which sums all parameters - 
<cms:add '10' '11' '12' debug='1' />

Since parameter debug is handled after tag executed, then the value automatically is wrong (34), because '1' was taken into sum. I did not find initially a good way of handling such things, simply because custom params are not fixed. Then I have decided to rewrite some methods in Class and fixed it by the following routine -
Code: Select all
a. First register all nodes that contain a custom parameter
$FUNCS->add_event_listener( "alter_tag_{$tag_name}_execute", array($this, 'register_tag_node'), 1000 ); //default priority of '0', so '1000' called first
b. Function register_tag_node  saves found tags -  $this->known_nodes[] = $node->ID;
c. Next, remove all custom parameter(s) from &$params and allow the tag process regular parameters.
d. If current tag is found among known_nodes, then call our user defined function.


I have also switched from call_user_func to call_user_func_array, which follows the way you have set the parser - resulting in tag_handler becomes very effective and allows to control the flow of execution. Parameters such as 'ignore' prevent any further bubbling.
Code: Select all
function tag_handler($tag_name, $params, $node, &$html ){
   if( !in_array($node->ID, $this->known_nodes) ) return false;

   $skip = call_user_func_array( $this->processor, array($tag_name, $params, $node, &$html, $debug ));
   return $skip; // false : pass onto the next event (best), !false : stop propagation of events (prevent other handlers in event bubble).
}


I now think with the precursory work done, I can try to devise a method to handle help parameter (similar to debug). It seems handy to have different files for different styles of output. Of course, it doesn't seem to be an easy task.

For example, this is how ignore, the simplest parameter handler, looks -

Code: Select all
<?php

    /**
    *   Handles parameter 'ignore' in tags.
    *
    *   @category Tag Mods
    *   @link
    *   @author Anton Smirnov aka Trendoman <tony.smirnov@gmail.com>
    *   @date   6/11/2019
    */

    $p = new MyCustomParams( $call_func='ignore_param_handler', $if_tag_has_param='ignore, skip', $in_tags='' /*all*/, $excl_tags='' /*none*/, $always_first=true, $debug=false );

    function ignore_param_handler( $tag_name, $params, $node, &$html, $debug=0 ){
        if($debug) error_log("Tag '{$tag_name}' is processed by");
        if($debug) error_log("..function '". __FUNCTION__ ."' in");
        if($debug) error_log("..".__FILE__.".");

        //$html = "Tag '{$tag_name}' skipped.."; // Can set custom output
        return true; // false : pass onto the next event (best), true : stop propagation of events (prevent other handlers in event bubble).
    }

    // Important:
    // Some parameters should prevent Tag's execution AND be processed first - so,
    //      take good care of the combination of "$always_first" and "return true;".

Hi Anton,

I can image it wouldn't have been an easy solution.
I am glad you are making progress. Do keep us posted.
KK wrote: Hi Anton,

I can image it wouldn't have been an easy solution.
I am glad you are making progress. Do keep us posted.


Thank you for encouragement.

I found my foundation is pretty simple to extend further and add more params. For example, it is now possible to see how much time elapsed for any individual tag with param get_time -
Code: Select all
<cms:pages ids_only='1' get_time='1' />
<cms:add '10' '12' get_time='1' />

Output is -
..list of ids..
Tag pages finished in 0.212 sec.
22
Tag add finished in 0.000 sec.


As I said earlier, to prevent custom params from tampering with tag's data I am removing any traces of custom params before tag executes. Param get_time created a situation where I needed to run my function before tag executed AND after it as well. However a new object of the same Class wouldn't have helped simply because after the first object created, there would be no trace of custom parameter in tag's params. It became a simple task and the solution is to hook on the final event when the first event dispatches.
Impressive :)
4 posts Page 1 of 1
cron