OK
Here is a working setup
This is my schema:
<?xml version="1.0" encoding="utf-8"?>
<model package="pscupresets" baseClass="xPDOObject" platform="mysql" defaultEngine="MyISAM" version="1.1">
<object class="pscuDashboardRole" table="pscu_roles" extends="xPDOSimpleObject">
<field key="name" dbtype="text" phptype="string" null="true" />
<composite alias="applications" class="pscuPresetApplication" local="id" foreign="roleId" cardinality="many" owner="local" />
</object>
<object class="pscuPresetApplication" table="pscu_rolesPresets" extends="xPDOSimpleObject">
<field key="roleId" dbtype="int" precision="11" phptype="integer" null="true" />
<field key="applicationId" dbtype="int" precision="11" phptype="integer" null="true" />
<aggregate alias="roleOwner" class="pscuDashboardRole" local="roleId" foreign="id" cardinality="one" owner="foreign" />
<aggregate alias="Application" class="modResource" local="applicationId" foreign="id" cardinality="one" owner="foreign" />
</object>
</model>
This is the setup for the CMP:
{
"formtabs":[
{
"MIGX_id":121,
"caption":"Role",
"print_before_tabs":"0",
"fields":[
{
"MIGX_id":476,
"field":"name",
"caption":"Role name",
"description":"",
"description_is_code":"0",
"inputTV":"",
"inputTVtype":"",
"validation":"",
"configs":"",
"restrictive_condition":"",
"display":"",
"sourceFrom":"config",
"sources":"",
"inputOptionValues":"",
"default":"",
"useDefaultIfEmpty":"0",
"pos":1
},
{
"MIGX_id":477,
"field":"applications",
"caption":"Applications",
"description":"",
"description_is_code":"0",
"inputTV":"",
"inputTVtype":"migxdb",
"validation":"",
"configs":"pscu_roleapplications",
"restrictive_condition":"[[migxIsNewObject]]",
"display":"",
"sourceFrom":"config",
"sources":"",
"inputOptionValues":"",
"default":"",
"useDefaultIfEmpty":"0",
"pos":2
}
],
"pos":1
}
],
"contextmenus":"update||duplicate||remove||movetotop_migx||movetotop_bottom",
"actionbuttons":"addItem",
"columnbuttons":"",
"filters":"",
"extended":{
"migx_add":"Add dashboard role",
"disable_add_item":"",
"add_items_directly":"",
"formcaption":"",
"update_win_title":"",
"win_id":"pscupresets",
"maxRecords":"",
"addNewItemAt":"bottom",
"multiple_formtabs":"",
"multiple_formtabs_label":"",
"multiple_formtabs_field":"",
"multiple_formtabs_optionstext":"",
"multiple_formtabs_optionsvalue":"",
"actionbuttonsperrow":4,
"winbuttonslist":"",
"extrahandlers":"",
"filtersperrow":4,
"packageName":"pscupresets",
"classname":"pscuDashboardRole",
"task":"pscupresets",
"getlistsort":"",
"getlistsortdir":"",
"sortconfig":"",
"gridpagesize":"",
"use_custom_prefix":"0",
"prefix":"",
"grid":"",
"gridload_mode":1,
"check_resid":1,
"check_resid_TV":"",
"join_alias":"applications",
"has_jointable":"yes",
"getlistwhere":"",
"joins":"",
"hooksnippets":"",
"cmpmaincaption":"Manage Dashboards",
"cmptabcaption":"Dashboard Roles",
"cmptabdescription":"Add\/edit dashboard role",
"cmptabcontroller":"",
"winbuttons":"",
"onsubmitsuccess":"",
"submitparams":""
},
"columns":[
{
"MIGX_id":1,
"header":"Id",
"dataIndex":"id",
"width":"",
"sortable":"false",
"show_in_grid":"0",
"renderer":"",
"clickaction":"",
"selectorconfig":"",
"renderchunktpl":"",
"renderoptions":"",
"editor":""
},
{
"MIGX_id":2,
"header":"Role Name",
"dataIndex":"name",
"width":"",
"sortable":true,
"show_in_grid":1,
"renderer":"",
"clickaction":"",
"selectorconfig":"",
"renderchunktpl":"",
"renderoptions":"",
"editor":""
},
{
"MIGX_id":3,
"header":"Applications",
"dataIndex":"applications",
"width":"",
"sortable":"false",
"show_in_grid":1,
"renderer":"this.renderChunk",
"clickaction":"",
"selectorconfig":"",
"renderchunktpl":"[[migxLoopCollection?\n&packageName=`pscupresets`\n&classname=`pscuPresetApplication`\n&joins=`[{\"alias\":\"Application\"}]`\n&where=`{\"roleId\":\"[[+id]]\"}`\n&tpl=`@CODE:[[+Application_pagetitle]]`\n&outputSeparator=`,`\n]]",
"renderoptions":"",
"editor":""
}
]
}
important parts:
the grid-field, uses the config pscu_roleapplications and is not shown on new objects with the snippet in restrictive_condition
"inputTVtype":"migxdb",
"configs":"pscu_roleapplications",
"restrictive_condition":"[[migxIsNewObject]]",
the snippet 'migxIsNewObject':
if (isset($_REQUEST['object_id']) && $_REQUEST['object_id']=='new'){
return 1;
}
the applications - column
"renderer":"this.renderChunk",
"renderchunktpl":"[[migxLoopCollection?\n&packageName=`pscupresets`\n&classname=`pscuPresetApplication`\n&joins=`[{\"alias\":\"Application\"}]`\n&where=`{\"roleId\":\"[[+id]]\"}`\n&tpl=`@CODE:[[+Application_pagetitle]]`\n&outputSeparator=`,`\n]]",
uses the renderChunk - renderer with a snippet to get the commaseperated applications:
[[migxLoopCollection?
&packageName=`pscupresets`
&classname=`pscuPresetApplication`
&joins=`[{"alias":"Application"}]`
&where=`{"roleId":"[[+id]]"}`
&tpl=`@CODE:[[+Application_pagetitle]]`
&outputSeparator=`,`
]]
the setup for the applications-grid with checkboxes with name 'pscu_roleapplications'
{
"formtabs":"",
"contextmenus":"",
"actionbuttons":"",
"columnbuttons":"",
"filters":"",
"extended":{
"migx_add":"",
"disable_add_item":"",
"add_items_directly":"",
"formcaption":"",
"update_win_title":"",
"win_id":"pscu_roleapplications",
"maxRecords":"",
"addNewItemAt":"bottom",
"multiple_formtabs":"",
"multiple_formtabs_label":"",
"multiple_formtabs_field":"",
"multiple_formtabs_optionstext":"",
"multiple_formtabs_optionsvalue":"",
"actionbuttonsperrow":4,
"winbuttonslist":"",
"extrahandlers":"this.handleColumnSwitch",
"filtersperrow":4,
"packageName":"pscupresets",
"classname":"modResource",
"task":"roleapplications",
"getlistsort":"",
"getlistsortdir":"",
"sortconfig":"",
"gridpagesize":"",
"use_custom_prefix":"0",
"prefix":"",
"grid":"",
"gridload_mode":2,
"check_resid":"0",
"check_resid_TV":"",
"join_alias":"",
"has_jointable":"no",
"getlistwhere":{
"parent":239
},
"joins":"",
"hooksnippets":"",
"cmpmaincaption":"",
"cmptabcaption":"",
"cmptabdescription":"",
"cmptabcontroller":"",
"winbuttons":"",
"onsubmitsuccess":"",
"submitparams":""
},
"columns":[
{
"MIGX_id":1,
"header":"ID",
"dataIndex":"id",
"width":10,
"sortable":"false",
"show_in_grid":1,
"renderer":"",
"clickaction":"",
"selectorconfig":"",
"renderchunktpl":"",
"renderoptions":"",
"editor":""
},
{
"MIGX_id":2,
"header":"Pagetitle",
"dataIndex":"pagetitle",
"width":40,
"sortable":"false",
"show_in_grid":1,
"renderer":"",
"clickaction":"",
"selectorconfig":"",
"renderchunktpl":"",
"renderoptions":"",
"editor":""
},
{
"MIGX_id":3,
"header":"Joined",
"dataIndex":"joined",
"width":10,
"sortable":"false",
"show_in_grid":1,
"renderer":"this.renderSwitchStatusOptions",
"clickaction":"switchOption",
"selectorconfig":"",
"renderchunktpl":"",
"renderoptions":[
{
"MIGX_id":1,
"name":"joined",
"use_as_fallback":"",
"value":1,
"clickaction":"",
"handler":"",
"image":"assets\/components\/migx\/style\/images\/cb_ticked.png"
},
{
"MIGX_id":2,
"name":"unjoined",
"use_as_fallback":1,
"value":"0",
"clickaction":"",
"handler":"",
"image":"assets\/components\/migx\/style\/images\/cb_empty.png"
}
],
"editor":""
}
]
}
Important parts:
the column with the renderSwitchStatusOptions - renderer and two renderoptions for the states 'joined/unjoined/'
which calls the custom processor 'handlecolumnswitch.php' when you click that column
{
"MIGX_id":3,
"header":"Joined",
"dataIndex":"joined",
"width":10,
"sortable":"false",
"show_in_grid":1,
"renderer":"this.renderSwitchStatusOptions",
"clickaction":"switchOption",
"selectorconfig":"",
"renderchunktpl":"",
"renderoptions":[
{
"MIGX_id":1,
"name":"joined",
"use_as_fallback":"",
"value":1,
"clickaction":"",
"handler":"",
"image":"assets\/components\/migx\/style\/images\/cb_ticked.png"
},
{
"MIGX_id":2,
"name":"unjoined",
"use_as_fallback":1,
"value":"0",
"clickaction":"",
"handler":"",
"image":"assets\/components\/migx\/style\/images\/cb_empty.png"
}
],
"editor":""
}
don't forget to check the extrahandler this.handleColumnSwitch - checkbox:
"extrahandlers":"this.handleColumnSwitch",
the processor core/components/pscupresets/processors/mgr/roleapplications/handlecolumnswitch.php
<?php
$config = $modx->migx->customconfigs;
$prefix = $modx->getOption('prefix', $config, null);
$packageName = $config['packageName'];
$packagepath = $modx->getOption('core_path') . 'components/' . $packageName . '/';
$modelpath = $packagepath . 'model/';
$modx->addPackage($packageName, $modelpath, $prefix);
$classname = $config['classname'];
$configs = $modx->getOption('configs', $scriptProperties, 0);
$resource_id = $modx->getOption('resource_id', $scriptProperties, 0);
$co_id = $modx->getOption('co_id', $scriptProperties, 0);
$object_id = $modx->getOption('object_id', $scriptProperties, 0);
if (!empty($object_id) && !empty($co_id)) {
$joinclass = 'pscuPresetApplication';
$fields = array();
$fields['roleId'] = $co_id;
$fields['applicationId'] = $object_id;
switch ($scriptProperties['idx']) {
case '1':
if ($joinobject = $modx->getObject($joinclass, $fields)) {
} else {
$joinobject = $modx->newObject($joinclass);
//$joinobject->set('pos', $pos);
$joinobject->fromArray($fields);
}
$joinobject->save();
break;
case '0':
if ($joinobject = $modx->getObject($joinclass, $fields)) {
$joinobject->remove();
}
break;
default:
break;
}
//clear cache for all contexts
$collection = $modx->getCollection('modContext');
foreach ($collection as $context) {
$contexts[] = $context->get('key');
}
$modx->cacheManager->refresh(array(
'db' => array(),
'auto_publish' => array('contexts' => $contexts),
'context_settings' => array('contexts' => $contexts),
'resource' => array('contexts' => $contexts),
));
}
return $modx->error->success();
the processor core/components/pscupresets/processors/mgr/roleapplications/getlist.php
<?php
//if (!$modx->hasPermission('quip.thread_list')) return $modx->error->failure($modx->lexicon('access_denied'));
$config = $modx->migx->customconfigs;
$prefix = isset($config['prefix']) && !empty($config['prefix']) ? $config['prefix'] : null;
if (isset($config['use_custom_prefix']) && !empty($config['use_custom_prefix'])) {
$prefix = isset($config['prefix']) ? $config['prefix'] : '';
}
if (!empty($config['packageName'])) {
$packageNames = explode(',', $config['packageName']);
if (count($packageNames) == '1') {
//for now connecting also to foreign databases, only with one package by default possible
$xpdo = $modx->migx->getXpdoInstanceAndAddPackage($config);
} else {
//all packages must have the same prefix for now!
foreach ($packageNames as $packageName) {
$packagepath = $modx->getOption('core_path') . 'components/' . $packageName . '/';
$modelpath = $packagepath . 'model/';
if (is_dir($modelpath)) {
$modx->addPackage($packageName, $modelpath, $prefix);
}
}
$xpdo = &$modx;
}
} else {
$xpdo = &$modx;
}
$classname = $config['classname'];
$checkdeleted = isset($config['gridactionbuttons']['toggletrash']['active']) && !empty($config['gridactionbuttons']['toggletrash']['active']) ? true : false;
$joins = isset($config['joins']) && !empty($config['joins']) ? $modx->fromJson($config['joins']) : false;
$joinalias = isset($config['join_alias']) ? $config['join_alias'] : '';
if (!empty($joinalias)) {
if ($fkMeta = $xpdo->getFKDefinition($classname, $joinalias)) {
$joinclass = $fkMeta['class'];
$joinfield = $fkMeta[$fkMeta['owner']];
} else {
$joinalias = '';
}
}
if ($modx->lexicon) {
$modx->lexicon->load($packageName . ':default');
}
/* setup default properties */
$isLimit = !empty($scriptProperties['limit']);
$isCombo = !empty($scriptProperties['combo']);
$start = $modx->getOption('start', $scriptProperties, 0);
$limit = $modx->getOption('limit', $scriptProperties, 20);
$sort = !empty($config['getlistsort']) ? $config['getlistsort'] : 'id';
$sort = $modx->getOption('sort', $scriptProperties, $sort);
$dir = !empty($config['getlistsortdir']) ? $config['getlistsortdir'] : 'ASC';
$dir = $modx->getOption('dir', $scriptProperties, $dir);
$showtrash = $modx->getOption('showtrash', $scriptProperties, '');
$object_id = $modx->getOption('object_id', $scriptProperties, '');
$resource_id = $modx->getOption('resource_id', $scriptProperties, '');
//$resource_id = $modx->getOption('resource_id', $scriptProperties, is_object($modx->resource) ? $modx->resource->get('id') : false);
//$resource_id = !empty($object_id) ? $object_id : $resource_id;
$sortConfig = $modx->getOption('sortconfig', $config, '');
if (!empty($sortConfig)) {
$sort = '';
if (!is_array($sortConfig)) {
$sortConfig = $modx->fromJson($sortConfig);
}
}
$where = !empty($config['getlistwhere']) ? $config['getlistwhere'] : '';
$where = $modx->getOption('where', $scriptProperties, $where);
$c = $xpdo->newQuery($classname);
$c->select($xpdo->getSelectColumns($classname, $classname));
if (!empty($joinalias)) {
/*
if ($joinFkMeta = $modx->getFKDefinition($joinclass, 'Resource')){
$localkey = $joinFkMeta['local'];
}
*/
$c->leftjoin($joinclass, $joinalias);
$c->select($xpdo->getSelectColumns($joinclass, $joinalias, 'Joined_'));
}
if ($joins) {
$modx->migx->prepareJoins($classname, $joins, $c);
}
/*
$c->leftjoin('poProduktFormat','ProduktFormat', 'format_id = poFormat.id AND product_id ='.$scriptProperties['object_id']);
//$c->select($classname.'.*');
$c->select('ProduktFormat.format_id,ProduktFormat.calctype,ProduktFormat.price,ProduktFormat.published AS pof_published');
*/
//print_r($config['gridfilters']);
if (isset($config['gridfilters']) && count($config['gridfilters']) > 0) {
foreach ($config['gridfilters'] as $filter) {
if (!empty($filter['getlistwhere'])) {
$requestvalue = $modx->getOption($filter['name'], $scriptProperties, 'all');
if (isset($scriptProperties[$filter['name']]) && $requestvalue != 'all') {
$chunk = $modx->newObject('modChunk');
$chunk->setCacheable(false);
$chunk->setContent($filter['getlistwhere']);
$fwhere = $chunk->process($scriptProperties);
$fwhere = strpos($fwhere, '{') === 0 ? $modx->fromJson($fwhere) : $fwhere;
$c->where($fwhere);
}
}
}
}
if ($modx->migx->checkForConnectedResource($object_id, $config)) {
if (!empty($joinalias)) {
$c->where(array($joinalias . '.' . $joinfield => $object_id));
} else {
$c->where(array($classname . '.resource_id' => $object_id));
}
}
if ($checkdeleted) {
if (!empty($showtrash)) {
$c->where(array($classname . '.deleted' => '1'));
} else {
$c->where(array($classname . '.deleted' => '0'));
}
}
if (!empty($where)) {
$c->where($modx->fromJson($where));
}
$count = $xpdo->getCount($classname, $c);
if (empty($sort)) {
if (is_array($sortConfig)) {
foreach ($sortConfig as $sort) {
$sortby = $sort['sortby'];
$sortdir = isset($sort['sortdir']) ? $sort['sortdir'] : 'ASC';
$c->sortby($sortby, $sortdir);
}
}
} else {
$c->sortby($sort, $dir);
}
if ($isCombo || $isLimit) {
$c->limit($limit, $start);
}
$configs = $modx->getOption('configs', $scriptProperties, 0);
$joinclass = 'pscuPresetApplication';
$fields = array();
$fields['roleId'] = $object_id;
$target_field = 'applicationId';
//get joined Resources
$resCategories = array();
$positions = array();
$c2 = $modx->newQuery($joinclass);
$c2->where($fields);
if ($resCategoryCollection = $modx->getCollection($joinclass, $c2)) {
foreach ($resCategoryCollection as $resCategoryObject) {
$resCategories[] = $resCategoryObject->get($target_field);
//$positions[$resCategoryObject->get($target_field)] = $resCategoryObject->get('pos');
}
}
//print_r($resCategories);
//$c->sortby($sort,$dir);
//$c->prepare();echo $c->toSql();
$rows = array();
if ($collection = $xpdo->getCollection($classname, $c)) {
$pk = $xpdo->getPK($classname);
foreach ($collection as $object) {
$row = $object->toArray();
$row['id'] = !isset($row['id']) ? $row[$pk] : $row['id'];
$row['joined'] = in_array($row['id'], $resCategories) ? '1' : '0';
//$row['pos'] = $positions[$row['id']];
$rows[] = $row;
}
}
$rows = $modx->migx->checkRenderOptions($rows);
I was lazy and copied the default getlist.php - processor from MIGX and just added this lines:
$joinclass = 'pscuPresetApplication';
$fields = array();
$fields['roleId'] = $object_id;
$target_field = 'applicationId';
//get joined Resources
$resCategories = array();
$positions = array();
$c2 = $modx->newQuery($joinclass);
$c2->where($fields);
if ($resCategoryCollection = $modx->getCollection($joinclass, $c2)) {
foreach ($resCategoryCollection as $resCategoryObject) {
$resCategories[] = $resCategoryObject->get($target_field);
//$positions[$resCategoryObject->get($target_field)] = $resCategoryObject->get('pos');
}
}
//print_r($resCategories);
//$c->sortby($sort,$dir);
//$c->prepare();echo $c->toSql();
$rows = array();
if ($collection = $xpdo->getCollection($classname, $c)) {
$pk = $xpdo->getPK($classname);
foreach ($collection as $object) {
$row = $object->toArray();
$row['id'] = !isset($row['id']) ? $row[$pk] : $row['id'];
$row['joined'] = in_array($row['id'], $resCategories) ? '1' : '0';
//$row['pos'] = $positions[$row['id']];
$rows[] = $row;
}
}
I think, that was it.
Some similiar setups are here:
https://github.com/Bruno17/migxNestedNodes
https://github.com/Bruno17/migxResourceCategories
[ed. note: Bruno17 last edited this post 9 years, 6 months ago.]