Coded something up in Couch in an interesting way? Have a snippet or shortcode to share? Post it here for the community to benefit.
4 posts Page 1 of 1
A common use of shortcodes (https://docs.couchcms.com/miscellaneous/shortcodes.html) is to inject arbitrary chunks of third-party code (e.g. PayPal buttons, Video embed-codes etc.) into richtext/textarea regions of a site.

Instead of creating a one-off shortcode for each such use-case, one may use @Tim's very useful 'All-purpose Embed shortcode' (viewtopic.php?f=8&t=7950) for this purpose. However, that solution becomes unwieldy when the amount of code to embed is large or contains some words that the shortcode does not accept.

Here is an alternative that I implemented recently on a client's site.
It consists of two separate components -

1. A single "universal shortcode" the PHP code of which needs to be placed within 'couch/addons/kfunctions.php' file (if this file is not present, rename 'kfunctions.example.php' to 'kfunctions.php') -
Code: Select all
// Universal Shortcode
// Usage:
// [code 'page name']
{
    class KShortcode{

        // Modify these values only if required
        const masterpage = 'code-snippets.php';
        const field_0 = 'code';
        const field_1 = 'execute_code';

        static function shortcode_handler( $params, $content=null ){
            global $FUNCS, $CTX;
       
            $page = trim( $params[0]['rhs'] );
            if( $page!=='' ){
                $pg = new KWebpage( self::masterpage, 0, $page );
                if( !$_pg->error ){
                    if( isset($pg->_fields[self::field_0]) ){
                        $code = $pg->_fields[self::field_0]->data;

                        // if code is executable..
                        if( isset($pg->_fields[self::field_1]) && $pg->_fields[self::field_1]->data=='yes'){
                            array_shift( $params );
                            $CTX->set_object( 'obj_sc_code_params', $params );
                            $CTX->set( 'k_content', $content );

                            // ..pass code on to Couch for execution using the 'embed' function
                            $code = $FUNCS->embed( $code, $is_code=1 );
                        }
                    }
                }
            }
       
            return $code;
        }

        static function tag_handler( $params, $node ){
            global $FUNCS, $CTX;

            $named_params = array();
            for( $x=0; $x<count($params); $x++ ){
                if( $params[$x]['op']=='=' && $params[$x]['lhs']){
                    $named_params[$params[$x]['lhs']] = $params[$x]['rhs'];
                }
            }
            if( count($named_params) ){
                $obj = &$CTX->get_object( 'obj_sc_code_params', 'do_shortcodes' );
                if( !is_null($obj) ){
                    $params = $obj;
                }
                $vars = $FUNCS->get_named_vars( $named_params, $params );
                $CTX->set_all( $vars );
            }
        }
    }
    $FUNCS->register_shortcode( 'code', array('KShortcode', 'shortcode_handler') );
    $FUNCS->register_tag( 'get_named_vars', array('KShortcode', 'tag_handler') );

}// end universal shortcode


2. A (regular) Couch template that is used to input the text/code/script to be injected.
universal-shortcode.png
universal-shortcode.png (23.7 KiB) Viewed 20781 times

Copy the following code into a file named 'code-snippets.php', place it within your site's root and visit it as super-admin to register it.
IMP: If you choose to name this template as something else, you'll need to specify the new name in the PHP code above for things to work correctly.
Code: Select all
<?php require_once("couch/cms.php"); ?>
<cms:template title='Code Snippets' clonable='1' executable='0' order='1000'>

    <cms:editable name='code' type='textarea' label='Code to embed' height='500' no_xss_check='1' />
    <cms:editable name='execute_code' type='checkbox' label='Executable Code?' opt_values='Yes=yes' />

    <cms:config_list_view exclude='default-page' />

</cms:template>

<cms:test>
    <cms:if execute_code>
        <cms:embed code=code />
    <cms:else />
        <cms:show code />
    </cms:if>
</cms:test>

<?php COUCH::invoke(); ?>

Coming back to the admin-panel, unpublish the default page created by Couch for the template and rename it as 'default-page' (you may set the 'Title' to 'Default Page' and leave the 'Name' empty to make Couch automatically name the template as 'default-page'). This will get rid of the default page for good.

USAGE:
As a test, create a new page from the template created above and copy the following code in the textarea within it
Code: Select all
<h1>Hello from universal shortcode!</h1>

Set the 'title' of the page as "Test" and save it. Note the 'name' of the saved page (it would be 'test').
You may now inject the content used in this page anywhere else in the site by using the following shortcode -
Code: Select all
[code test]

As you can see, it simply consists of specifying the source page-name with 'code' shortcode (our 'universal' shortcode).

Assuming you want to do this in a target template (or a page of it, if that template is clonable) and that template has a richtext editable region named 'my_richtext', insert [code test] in that region's text. On the front-end, make sure to wrap the output of that region in <cms:do_shortcodes> tags as follows (this is the standard way all shortcodes work) -
Code: Select all
<cms:do_shortcodes><cms:show my_richtext /></cms:do_shortcodes>

You should see the greeting appear embedded within the richtext's output.
Of course, in a real-world scenario you'd be embedding something less trivial than this :)

ADVANCED:
If the person creating the shortcode (i.e. entering content within the "Code to embed" textarea of the template used above) happens to be conversant with Couch tags (I'll assume this would be you, the developer, rather than the end-client), she can set the "Executable Code?" checkbox below the textarea to "Yes".

And now, the full gamut of Couch tags can be used freely in the content.

This will also allow your code to process any parameters passed by the client while using the shortcode.
For example the client could put the following somewhere in a textarea and send 'hello' and 'world' as two parameters to your 'test' shortcode -
Code: Select all
[code test hello world]

or
Code: Select all
[code test 'hello' 'world']

You can access and use the parameters in your shortcode as follows -
Code: Select all
<cms:get_named_vars greeting='' to='' />

<h1><cms:show greeting /> <cms:show to /> from universal shortcode!</h1>

As you can see, we need to use <cms:get_named_vars /> tag at the beginning and specify the parameters we are expecting.
We may also specify default values for the parameters to use in case the client does not pass a required parameter e.g.
Code: Select all
<cms:get_named_vars greeting='Hi' to='everybody' />

<h1><cms:show greeting /> <cms:show to /> from universal shortcode!</h1>

And now the client may use any of the following -
Code: Select all
[code test]
[code test hello]
[code test hello world]
[code test to=world greeting=hello]

Hope this helps.
Amazing solution!

And for code hoarders as well :lol:

Code: Select all
<cms:get_named_vars greeting='Hi' to='everybody' />

Its showcase reminds me of params passed via <cms:embed> and <cms:route_values>. On a personal level I am astounded to see an obvious PHP reference in the new tag's look and feel. Vote for a refab! We have <cms:get var into=''> that feels more 'Couch' :) I hope it does not go further than this cute addon :)
Glad you liked it, Anton :)

You are right - the <cms:get_named_vars /> tag is the exact counterpart of $FUNCS->get_named_vars() function already used by those who create shortcodes in PHP so the influence is apparent.
I am glad you are glad I liked it :)

Injection of any kind of code via admin panel is going to be fun.

If the person creating the shortcode (i.e. entering content within the "Code to embed" textarea of the template used above) happens to be conversant with Couch tags (I'll assume this would be you, the developer, rather than the end-client), she can set the "Executable Code?" checkbox below the textarea to "Yes".


I bet there must be a Validate button. :!:

P.S. And a set of white-listed tags, perhaps?
4 posts Page 1 of 1