Coded something up in Couch in an interesting way? Have a snippet or shortcode to share? Post it here for the community to benefit.
14 posts Page 1 of 2
Sometimes it is required to write data into text files e.g. some time back I had to create a very large XML file using data from Couch (for exporting into an accounting package).

To help with that, I created a simple tag - <cms:write>. I am sharing it here as it could come in handy to others tackling similar use-cases.

Please add the following code in your 'couch/addons/kfunctions.php' file (if this file is not found, rename the 'kfunctions.example.php' to this name) -
Code: Select all
// Tag <cms:write />
// writes the enclosed contents into file
$FUNCS->register_tag( 'write', 'my_write_handler' );
function my_write_handler( $params, $node ){
    global $FUNCS;

    extract( $FUNCS->get_named_vars(
                array(
                      'file'=>'',       /* file name if provided needs to be relative to the site directory */
                      'truncate'=>'0',  /* will begin afresh */
                      'add_newline'=>'0',   /* appends newline character to the content */
                    ),
                $params)
           );

    // sanitize params
    $file = trim( $file );
    if( !$file ){
        $file = 'my_log.txt';
    }
    $file = K_SITE_DIR . $file;
    $truncate = ( $truncate==1 ) ? 1 : 0;
    $add_newline = ( $add_newline==1 ) ? 1 : 0;

    $content='';
    foreach( $node->children as $child ){
        $content .= $child->get_HTML();
    }
    if( $add_newline ){
        $content .= "\r\n";
    }

    $fp = @fopen( $file,'a' );
    if( $fp ){
        @flock( $fp, LOCK_EX );
        if( $truncate ){
            ftruncate( $fp, 0 );
            rewind( $fp );
        }
        @fwrite( $fp, $content );
        @flock( $fp, LOCK_UN );
        @fclose( $fp );
    }

    return;
}

Usage:

The usage of this tag is simple. All content enclosed within this tag will be written into the file specified as its first parameter (always considered relative to the site's root) e.g.
Code: Select all
<cms:write 'my.txt' >Hello world!</cms:write>

The code above will write "Hello world!" into a file named 'my.txt' present in the site's root (i.e. the parent folder of 'couch').
If the file is not present, the tag will create it. The created file should now contain the following -

Hello world!

Now suppose we used the same statement twice e.g. as follows -
Code: Select all
<cms:write 'my.txt' >Hello world!</cms:write>
<cms:write 'my.txt' >Hello world!</cms:write>

Assuming the 'my.txt' file does not exist to begin with, when the first statement executes it creates the file and writes "Hello world!" into it. When the second statement executes, the 'my.txt' file is already present so it uses the same file and writes "Hello world!" into it appending it to the "Hello world!" written by the first statement. The 'my.txt' file will now contain the following data -

Hello world!Hello world!

Please notice above that there are no 'newlines' between the two writes because the data we specified each time did not contain any newlines. That is to say, the <cms:write> tag, by default, writes into the file verbatim whatever data is given to it.

If newlines were required between the two writes, you can either -
1. Add the newline as part of the data e.g. as follows
Code: Select all
<cms:write 'my.txt' >
Hello world!
</cms:write>

2. Or, set 'add_newline' parameter to '1' e.g.as follows
Code: Select all
<cms:write 'my.txt' add_newline='1'>Hello world!</cms:write>

One last point -
As mentioned above, if the specified file already exists, this tag by default appends data to that file's existing contents.
If you wish the tag to discard any existing file and create a new file, set its 'truncate' parameter to '1'.
For example, the following will result in the target file always containing only one "Hello world!" because each statement discards the existing file and starts a new file before writing its content into it -
Code: Select all
<cms:write 'my.txt' add_newline='1' truncate='1'>Hello world!</cms:write>
<cms:write 'my.txt' add_newline='1' truncate='1'>Hello world!</cms:write>

In practice you'll normally want to use 'truncate' only once somewhere at the beginning of your script so that it starts with a blank slate. Rest of the write statements then append their data into this new file.

Addendum:
For a real-life example using this tag, please see the CSV exporter example discussed here -
viewtopic.php?f=8&t=11378


Hope this helps.
Thank you, @KK - this is an awesome tag.

Here it is posted as a separate addon file —

Tweakus-Dilectus Tags » write

- - -

Following listing is a simple server benchmark.

Code will keep running itself, writing with cms:write consecutive numbers to log.txt before php script dies (browser tab stops loading) from timeout. Final written number is a relative score, which may represent cpu speed and CouchCMS performance with a certain version of PHP.


Code: Select all
<cms:set cnt = '1' />
<cms:set code = '<cms:embed code="<cms:show code /><cms:write file=\'log.txt\' add_newline=\'1\' ><cms:show cnt /></cms:write><cms:incr cnt />" />' />
<cms:embed code=code />


It is a derivative of my successful experiment to write an indefinite unlimited loop with couch code.

Code: Select all
<cms:set code = '<cms:embed code=code />' />
<cms:embed code=code />


Regards
... and something very important
Use this tag to speed up your every site - see the discussion https://www.couchcms.com/forum/viewtopic.php?f=3&t=11833&p=34208
KK,

Thank you for the <cms:write> tag and explanation on how to use it:

Code: Select all
<cms:write 'log_file.txt' truncate='0' add_newline='1' >Hello world!</cms:write>


Could you provide a how to use this tag in <cms:php> like we do with setting variables?

Code: Select all
<cms:php>
    global $CTX;
    $CTX->set('my_set_variable', 'Hello World!', 'global');
</cms:php>


Example of what I would like to achieve, I assume this would use $FUNCS:

Code: Select all
<cms:php>
    global $FUNCS;
    $FUNCS->write("log_file.txt", '0', '1', 'Hello World!'); // in order of params file, truncate, add_newline
</cms:php>


Ty
@Blutbaden,

You can adapt the tag's code to create a PHP function for yourself e.g. -
Code: Select all
function my_write( $content, $file='', $add_newline=0, $truncate=0 ){
    $file = trim( $file );
    if( !$file ){
        $file = 'my_log.txt';
    }
    $truncate = ( $truncate==1 ) ? 1 : 0;
    $add_newline = ( $add_newline==1 ) ? 1 : 0;
    if( $add_newline ){
        $content .= "\r\n";
    }

    $file = K_SITE_DIR . $file;
    $fp = @fopen( $file,'a' );
    if( $fp ){
        @flock( $fp, LOCK_EX );
        if( $truncate ){
            ftruncate( $fp, 0 );
            rewind( $fp );
        }
        @fwrite( $fp, $content );
        @flock( $fp, LOCK_UN );
        @fclose( $fp );
    }
}

Place the code above in your addons/kfunctions.php file and now you can use it as follows -
Code: Select all
<cms:php>
    my_write( 'Hello World!', 'log_file.txt', 1, 0 ); // order of params: content, file, add_newline, truncate
</cms:php>

or simply
Code: Select all
<cms:php>
    my_write( 'Hello World!' );
</cms:php>

Please notice that the sequence of params is slightly different from that of the tag.

Hope this helps.
KK, This helped immensely, thanks!
You are welcome :)
Could this tag be used to write into an Excel file at specific sheets/cells assuming that the file will pe uploaded ?
@aleksandru
Could this tag be used to write into an Excel file at specific sheets/cells assuming that the file will pe uploaded ?

XLS is a binary format which, I don't think, can be handled by writing plain text (as by this addon), I am afraid.
@KK, no worries than, thank you very much, I will figure out a way to achieve this and if I can wrap it into a addon of some sorts, i will make sure to come back and post it.
14 posts Page 1 of 2