yj-t
2/16/2016 - 5:31 PM

Turns JSON into TV input options in MODX.

Turns JSON into TV input options in MODX.

<?php
/*
 * getTVInputsFromJson
 * @author @sepiariver <yj@modx.com>
 * 
 * Example usage:
 * 1. Create a Chunk with this Snippet call: [[getTVInputsFromJson? &jsonFile=`http://schema.org/docs/tree.jsonld`]]
 * 2. Create a Single-Select TV with @CHUNK binding for "Input Options": @CHUNK my_schema_tv_chunk
 * 3. Resources with the TV enabled will get a list of schema.org itemtype property values, like this screenshot: http://sepiariver.co/1KUr4LJ
 *
 */

// Options 
$json = $modx->getOption('json', $scriptProperties, ''); // json string
$jsonFile = $modx->getOption('jsonFile', $scriptProperties, ''); // json file pointer [url]
$default = $modx->getOption('default', $scriptProperties, ''); // default output
$parentElement = array_filter(array_map('trim', explode('.', $modx->getOption('parentElement', $scriptProperties, 'children')))); // JS dot notation property accessor "child.grandchild.key"
$childProperty = $modx->getOption('childProperty', $scriptProperties, 'name'); // the property with the value we want
$childrenKey = $modx->getOption('childrenKey', $scriptProperties, 'children'); // the property key with child elements
$filterMinLength = (int) $modx->getOption('filterMinLength', $scriptProperties, 2); // remove strings smaller than this
$operator = $modx->getOption('operator', $scriptProperties, '=='); // customizable for contentblocks
$delim = $modx->getOption('delim', $scriptProperties, '||'); // customizable for contentblocks

// Attempt to fetch JSON
if (empty($json) && !empty($jsonFile)) {
    $json = file_get_contents($jsonFile);
}
if (!$json) return $default;

// Setup PHP array
$workingArray = $modx->fromJSON($json);
if (!$workingArray || !is_array($workingArray)) return $default;

// Set the root element per runtime config
if (!empty($parentElement) && is_array($parentElement)) {
    foreach ($parentElement as $parent) {
        $workingArray = $workingArray[$parent];
    }
}

// Iterate
$output = array();
$iterator  = new RecursiveArrayIterator($workingArray);
$recursive = new RecursiveIteratorIterator($iterator, RecursiveIteratorIterator::SELF_FIRST);
foreach ($recursive as $key => $value) {
    
    // Add the value to the working array
    if (isset($value[$childProperty]) && is_string($value[$childProperty])) {
        // Overwrite duplicates
        $output[$value[$childProperty]] = $value[$childProperty] . $operator . $value[$childProperty];
    }
    // Check for children
    if (isset($value[$childrenKey]) && is_array($value[$childrenKey])) {
        // Loop through children
        foreach ($value[$childrenKey] as $child) {
            if (isset($child[$childProperty]) && is_string($child[$childProperty])) {
                $output[$child[$childProperty]] = $child[$childProperty] . $operator . $child[$childProperty];
            }
        }
    }
    
}
// Optionally remove junk
if ($filterMinLength) {
    foreach ($output as $key => $value) {
        if (strlen($key) < $filterMinLength) unset($output[$key]);
    }
}
// Return with delim
return implode($delim, $output);