MIGX

Make MIGX TV Searchable

gourmet fare

Search MIGX TV Values

MIGX takes TVs to a whole new level. But how can you use a search function like SimpleSearch for them?

Menno Pietersen asked...

How can I search MIGX TV's?

The Solution:

Bruno17 says...

for easier searching, its possible to store the text of all MIGX-items into another 'search-TV' with a plugin, that runs at OnDocFormSave.

It is running on all resources with given migxtv_templates (3 and 7).
It stores all configured Text-fields of configured MIGX-TVs into a target_tv.
The target_tv could be at the same resource (if the template matches the given template) or into a child-resource, which matches the given template.
This was for a special setup, where some of the MIGX-TVs was not listed at the same resource, but at a child-resource. Normally this option isn't needed.

It reads also nested MIGX - TVs, example here, the field 'downloads' with type 'migx' in the migxtv3.

<?php
$migxtv_templates = '3,7';
$config = '[
{"tvname":"migxtv","template":"3","target_tv":"searchMigxData","fields":[
    {"field":"headline"},
    {"field":"text"}
]},
{"tvname":"migxtv","template":"7","target_tv":"searchMigxData","fields":[
    {"field":"headline"},
    {"field":"text"}
]},
{"tvname":"othermigxtv","template":"4","target_tv":"searchMigxData","fields":[
    {"field":"headline"},
    {"field":"text"}
]},
{"tvname":"migxtv3","template":"5","target_tv":"searchMigxData","fields":[
    {"field":"headline"},
    {"field":"text"},
    {"field":"headline_bundle"},
    {"field":"downloads","type":"migx","fields":[
        {"field":"title1"},
        {"field":"title2"},
        {"field":"text"}
    ]}
]}
]';
 
function jsonFieldsToArray($items, $fields) {
    global $modx;
     
    $output = array();
    if (!is_array($items)) {
        $items = $modx->fromJson($items);
    }
    if (is_array($items)) {
        foreach ($items as $item) {
            foreach ($fields as $field) {
                $fieldname = $modx->getOption('field', $field, '');
                $type = $modx->getOption('type', $field, '');
                if (isset($item[$fieldname])) {
                    if ($type == 'migx') {
                        $subitems = $item[$fieldname];
                        $subfields = $modx->getOption('fields', $field, '');
                        $suboutput = jsonFieldsToArray($subitems,$subfields);
                        $output = array_merge($output,$suboutput);  
                    } else {
                        $output[] = $item[$fieldname];
                    }
                }
            }
        }
    }
    return $output;
}

$migxtv_templates = explode(',', $migxtv_templates);
 
$resource_template = $resource->get('template');
if (in_array($resource_template, $migxtv_templates)) {
 
    $config = $modx->fromJson($config);
    foreach ($config as $cfg) {
        $tvname = $modx->getOption('tvname', $cfg, '');
        $template = $modx->getOption('template', $cfg, '');
        $fields = $modx->getOption('fields', $cfg, '');
        $target_tv = $modx->getOption('target_tv', $cfg, '');
        $items = $resource->getTVValue($tvname);
        $values = jsonFieldsToArray($items, $fields);
        if ($template == $resource_template){
            //has the template itself - we save to that resource
            $resource->setTVValue($target_tv,implode("\n\n",$values));
             
        }elseif ($target_resource = $modx->getObject('modResource',array('template'=>$template,'parent'=>$resource->get('id')))){
            //otherwise search child-resource with that template
            $target_resource->setTVValue($target_tv,implode("\n\n",$values)); 
        }
    }
     
}

What's the Story?

A MIGX TV stores all of its data in one big JSON string. It's very difficult, if possible at all, to search for anything specific within this string. So the easiest solution is to save the TV value to another TV in a form that is easier to search.