We launched new forums in March 2019—join us there. In a hurry for help with your website? Get Help Now!
    • 28000 ☆ A M B ☆
    • 397 Posts
    I have found an interesting problem that I need help with that may depend on how MODX parses nested snippets.

    For my project I need to pass json to a snippet that really does nothing more than accepts 1) a string as chunk name and 2) a json array.

    The snippet checks if the chunk name exists, if not, it takes the default name that does exist. It runs getChunk, passing the correct chunk name and the properties array. The snippet is being used with Content Blocks to parse Content Blocks settings. The issues starts when I use a repeater within a repeater. For each templating instance in Content Blocks I am using my snippet to check the chunk name and convert the json to a php array. At some point in the nesting process MODX stops parsing the snippet and my end result is null.

    Here is the snippet:

    <?php
    $props =  $modx->getOption('props',$scriptProperties,'');
    $tpl =  $modx->getOption('chunk',$scriptProperties,'');
    $ctx = $modx->context->key;
    $output = array();
    
    $tpl_ctx = $tpl.'-'.$ctx;
    $tpl_default = $tpl.'-default';
    
    // convert json to array
    $propsarr = $modx->fromJSON($props);
    
    // check if chunk exists
    $chunk_exists = isset($tpl) ? $modx->getChunk($tpl_ctx): '';
    
    if ($chunk_exists == ''){
        //chunk does not exist
        $output[] = $modx->getChunk($tpl_default, $propsarr);
    }else{
        // chunk does exist
        $output[] = $modx->getChunk($tpl_ctx, $propsarr);
    }
    
    return implode("\n", $output);


    It works in all Content Block fields, except in the one where I have a repeater inside of a repeater, whereby the inner repeater is rendering HTML (a list item).

    So we have in this construct a Repeater field, that is calling another Repeater Field as a group setting.

    If the outer Repeater only has one element, than it parses correctly. Even the inner Repeater works fine. What Content Blocks writes to the content field of the resource is this:

    [[lpParseChunk?
        &chunk=`lp-tpl-products`
        &props=`{
            "rows": [[jsonencode? &input=`<!-- beginn outer row -->
                [[lpParseChunk?
                    &chunk=`lp-tpl-products-item`
                    &props=`{
                        "prod_title": [[jsonencode? &input=`Das neue Album`]],
                        "prod_name": [[jsonencode? &input=`Das neue Album`]],
                        "prod_link": [[jsonencode? &input=`http://www.google.com`]],
                        "prod_date": [[jsonencode? &input=`Ab jetzt`]],
                        "cover_art": [[jsonencode? &input=`/assets/uploads/landingpages/covers/56b08683481fd-cover-single.jpg`]],
                        "buy_links": [[jsonencode? &input=`<!-- beginn inner repeater -->
                                <!-- inside start -->
                                [[lpParseChunk?
                                    &chunk=`lp-tpl-buylinks-item`
                                    &props=`{
                                        "link" : [[jsonencode? &input=`http://www.amazon.com`]],
                                        "link_title" : [[jsonencode? &input=`Amazon Box`]]
                                    }`
                                ]]
                                <!-- inside end -->
    
                                <!-- inside start -->
                                [[lpParseChunk?
                                    &chunk=`lp-tpl-buylinks-item`
                                    &props=`{
                                        "link" : [[jsonencode? &input=`http://www.amazon.com`]],
                                        "link_title" : [[jsonencode? &input=`Amazon CD`]]
                                    }`
                                ]]
                                <!-- inside end -->
    
                                <!-- inside start -->
                                [[lpParseChunk?
                                    &chunk=`lp-tpl-buylinks-item`
                                    &props=`{
                                        "link" : [[jsonencode? &input=`http://www.amazon.com`]],
                                        "link_title" : [[jsonencode? &input=`Amazon LP`]]
                                    }`
                                ]]
                                <!-- inside end -->
                <!-- end inner repeater -->`]]
                    }`
                ]]
            <!-- end outer row -->`]]
        }`
    ]]


    As I stated, this code parses! Where I get into trouble is when the outer "rows" property gets more than one input. So where in the commenting you see "begin outer row and end outer row". If you have more than one of these outer rows, I get a value of NULL.

    The other snippet that is being used "jsonencode" looks like this:

    <?php
    return json_encode($input);


    Maybe some can give me a hint here? How far nested can MODX go before it fails to output something?

    I am running MODX Version 2.4.2-pl and PHP 5.6

    This question has been answered by sonicpunk. See the first response.

      Benjamin Davis: American web designer living in Munich, Germany and a MODX Ambassador. I am also co-founder of SEDA.digital, a MODX Agency.
      • 18373 ☆ A M B ☆
      • 3,141 Posts
      For the love of whatever you consider to be holy: simplify. Are you really going to know exactly how any of that works/worked in two years from now when the client calls you that something broke? That's not exactly maintainable code there.

      Why do you need to encode every single value as JSON like that? Those values aren't even arrays, so that's probably not doing anything. Why not just pass your properties directly to the lpParseChunk snippet, like:

      [[lpParseChunk?
                      &chunk=`lp-tpl-products-item`
                      &prod_title=`Das neue Album`


      Inside lpParseChunk you can then just use the $scriptProperties array. That means you can forget about at least half of those JSON value and jsonencode snippet calls.

      Where I get into trouble is when the outer "rows" property gets more than one input.
      Sounds like somewhere in your JSON, it is not accepting an array of rows. Perhaps your JSON is broken because it's missing a comma between elements.


      If you need context specific chunks, can't you just use something like this:
      [[$lp-tpl-products-item-[[*context_key]]? &prod_title=`Das neue Album`]]

      and call it a day?

      For your fall back defaults, you could use a plugin that fires OnElementNotFound to create them on the fly, but you would _really_ simplify your output.
        Mark Hamstra • Developer spending his days working on Premium Extras and a MODX Site Dashboard with the ability to remotely upgrade MODX and extras to make the MODX world a little better.

        Tweet me @mark_hamstra, check my infrequent blog at markhamstra.com, my slightly more frequent ramblings at MODX.today or see code at Github.
        • 28000 ☆ A M B ☆
        • 397 Posts
        Thanks for the tips, Mark.

        Yeah, the lpParseChunk snippet is being used on a wide variety of Content Block fields, not just this one, so it needs to be pretty generic. I will think about it again.
          Benjamin Davis: American web designer living in Munich, Germany and a MODX Ambassador. I am also co-founder of SEDA.digital, a MODX Agency.
          • 3749
          • 24,544 Posts
          I'm with Mark. As long as you're writing a snippet, put all the business logic in a single snippet (or a class), put any control settings in the snippet properties, and get rid of all the output modifiers.

          It will not only be easier to maintain and more reliable, it will be *much* faster. MODX is spending time and resources parsing every one of the output modifiers before running them, for no good reason. So do the various snippet calls which require parsing,the creation of a separate $scriptProperties array, and a separate function call.
            Did I help you? Buy me a beer
            Get my Book: MODX:The Official Guide
            MODX info for everyone: http://bobsguides.com/modx.html
            My MODX Extras
            Bob's Guides is now hosted at A2 MODX Hosting
            • 28000 ☆ A M B ☆
            • 397 Posts
            How would I pass the scriptProperties array from the chunk call to the newly written chunk within the OnElementNotFound system event?

            And how can I affect the ordering of the output? Sometimes there are nested Chunk calls.

              Benjamin Davis: American web designer living in Munich, Germany and a MODX Ambassador. I am also co-founder of SEDA.digital, a MODX Agency.
              • 3749
              • 24,544 Posts
              Something like this:

              $result = $modx->getChunk('MyChunk', $scriptProperties);


              I don't understand the question about ordering the output.
                Did I help you? Buy me a beer
                Get my Book: MODX:The Official Guide
                MODX info for everyone: http://bobsguides.com/modx.html
                My MODX Extras
                Bob's Guides is now hosted at A2 MODX Hosting
              • discuss.answer
                • 28000 ☆ A M B ☆
                • 397 Posts
                Hi Mark and Bob,

                So, I was able to write the plugin and create the structure in my Content Block fields, as Mark suggested. Now the whole json delivery is no longer needed. The Problem is still there however. It seems that there is an issue with the MODX Parser. Christian Seel has posted it as an issue here:
                https://github.com/modxcms/revolution/issues/13043

                My question above is no longer valid.
                  Benjamin Davis: American web designer living in Munich, Germany and a MODX Ambassador. I am also co-founder of SEDA.digital, a MODX Agency.