Add values to MIGX TV via plugin OnResourceTVFormPrerender

Hi there,

I’m trying to put together a plugin that will dynamically add data to the MIGX form of a document when I open that document to edit it.

And then, what is “kept” by the admin user in the table will be saved.

So far, I’ve got a plugin with that fires on the OnResourceTVFormPrerender event.

I can pull the existing TV data quite easily with:

$page = $modx->getObject('modResource', $resource);
$facebookJSON = $page->getTVValue('my_migx_tv');

But what I am having trouble figuring out is how to take the modified data (once I’ve added to the JSON) and use that to populate the field values (colums and form tabs) of my TV.

Can anyone point me in the right direction ?

Cheers

to understand better, what you are trying: What is the code of your plugin now?

I think when you use the event “OnResourceTVFormPrerender”, you have to save the changes back to the database again (with $page->setTVValue()).


Maybe you could use the event “OnResourceTVFormRender” instead, but this event is quite hard to use (as you have to replace the value in the already generated HTML markup).

Here is an example of the event “OnResourceTVFormRender” in use:

https://modx.com/blog/2015/09/10/quick-tip-sorting-date-type-tv-values/

Here is the code, so far:

<?php
// Only for use in the MODX mgr
if ($modx->context->get('key') != 'mgr') {
        return;
}
 
$migx_tv = $modx->getOption('migx_tv', $scriptProperties, '');
$api_version = $modx->getOption('api_version', $scriptProperties, '');
$access_token = $modx->getOption('access_token', $scriptProperties, '');
 
function callFacebookAPI($method, $url, $data = false)
{
    global $modx;
    
    $curl = curl_init();
    $url = sprintf("%s?%s", $url, http_build_query($data));
    curl_setopt($curl, CURLOPT_URL, $url);
    curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
    $result = curl_exec($curl);
   
    if(curl_errno($curl)){
        $error = curl_error($curl);
        $modx->event->output('<pre style="padding: 15px; color:red;">'.$error .'</pre>');
    }
    // $info = print_r(curl_getinfo($curl), true);
    // $modx->event->output('<pre style="padding: 15px;">'.$info .'</pre>');
    
    curl_close($curl);
    return $result;
}


function maxAttributeInArray($array, $prop) {
    return max( array_map( function($o) use ($prop) {
                            return $o->$prop;
                         },
                         $array));
}


$eventName = $modx->event->name;
 

switch($eventName) {
    case 'OnResourceTVFormPrerender':

    // GET DATA CURENTLY SAVED IN MODX    
    $page = $modx->getObject('modResource', $resource);
    $facebookJSON = $page->getTVValue($migx_tv);
    $savedPosts = json_decode($facebookJSON);
    $highestMIGX_id = maxAttributeInArray($savedPosts, "MIGX_id");

    // GET NEW DATA WE MIGHT WANT TO SAVE
    $updatesJSON = callFacebookAPI('GET', "https://graph.facebook.com/$api_version/petrgatinaismontargois/feed", array(
        "access_token" =>$access_token,
        "fields"=>"permalink_url",
        ) );
    
    $posts = 0;
    if($updatesJSON){
      $posts = json_decode($updatesJSON);
    }
    
    
    // COMBINE IT WITH EXISTING DATA ALREADY SAVED IN DATABASE
    if($posts){
        $i = 1;
        $combinedData = $savedPosts;
        foreach($posts->data as $item){
            $item->MIGX_id = $highestMIGX_id + $i;
            array_push($combinedData, $item);
            $i++;
        }
    }
    
    
    // $modx->event->output('<pre style="padding: 15px; color:red;">'.print_r($combinedData,true) .'</pre>');
    
    // I WANT TO USE THIS DATA TO POPULATE THE MIGX TV FORM WHEN I EDIT MY RESOURCE
    $combinedJSON = json_encode($combinedData);
     

    break;
    
    case 'OnDocFormSave':
        // HERE I WILL SAVE ONLY THE ENTRIES THAT HAVE BEEN EDITED (assigned a hide or pin property)
    break;
}

Yes, I can see how to save it to the database first. But want to avoid that.

The whole point here is to pull data from an API, let the person editing the resource choose what data they are interested in saving.

And then save only the entries that have been edited in some way to the database.

Maybe you could create a custom action-button instead.
A click on the button would run a processor that loads the data from the API, and then you would add this data to the store of the grid.

Something similar to the “importCsvMigx” action button.

1 Like

Thank you for the suggestion. That could definitely work.

What is the best way to go about that, without hacking straight into MIGX files (and risk loosing my work on an update)?

I am sorry if this is noobie question, truth is I’ve never added an action button to an existing component before… can it be done with a plugin as well?

have your own core/components/… folder
then you can have your own /grid.config.inc.php like here

and have your processor under core/components/yourcomponent/processors/mgr/default/…

do your configuration (formtabs and columns) with the MIGX CMP
Under MIGXdb settings have package: yourpackage

and under actionbuttons select your new defined actionbutton

1 Like

Here is a simple example.

  • Create a folder in core/components/ with a unique name. For example “yourpackage”
  • Create a file core/components/yourpackage/migxconfigs/grid/grid.config.inc.php with content like this:
<?php
$gridactionbuttons['importfromfacebook']['text'] = "'Import from Facebook'";
$gridactionbuttons['importfromfacebook']['handler'] = 'this.importFromFacebook';
$gridactionbuttons['importfromfacebook']['scope'] = 'this';
$gridactionbuttons['importfromfacebook']['standalone'] = '1';

$gridfunctions['this.importFromFacebook'] = "
importFromFacebook: function() {
        MODx.Ajax.request({
            url: this.config.url
            ,params: {
                action: 'mgr/migxdb/process'
                ,processaction: 'importfromfacebook'
				,configs: this.config.configs
            }
            ,listeners: {
                success: {fn: function(r) {
                    console.log(r.message);
                }, scope:this},
                failure: {fn:function(r){console.log(r);},scope:this}
            }
        });
    }
";

A click on the button runs the handler function “importFromFacebook”. This function makes an AJAX request to a custom processor and logs the response.

  • Create the custom processor file → core/components/yourpackage/processors/mgr/default/importfromfacebook.php with content like this:
<?php
//Do something and return a value
return $modx->error->success('Value from processor');
  • In your MIGX configuration make the following changes: Tab “MIGXdb-Settings” → field “Package” = yourpackage | Tab “Actionbuttons” → select the checkbox “importfromfacebook” | Tab “Handlers” → select the checkbox “this.importFromFacebook”
1 Like

Thank you @halftrainedharry and @bruno17!
I was able to get this working thanks to your tips.

I still have some cleaning up to do in my code, but when done I can also share it if anyone else needs help on something like this.

Cheers

This topic was automatically closed 2 days after discussion ended and a solution was marked. New replies are no longer allowed. You can open a new topic by clicking the link icon below the original post or solution and selecting “+ New Topic”.