Data Grid Store (DGS)
One of the most commonly used components in the system is DGS
. It is used to describe display lists and editing forms for various data.
- Table
- Fields
- Field Grouping
- Actions
- Filters and Search
- Events
- Aggregators
- API Mode
- Dynamic Changes in DGS
- DGS with Multiple Tables
- DGS Class Approach
DGS Options
When creating a DGS
, many options are used, which are passed as an array in the third parameter:
$options = array(
...
);
$store = new Store($connection, $ident, $options);
Option model
- Store::OPTION_MODEL
The data model in the context of DGS
is similar to the schema declaration of a store and is used to describe what the structure of our store will be.
Currently, you can declare DGS
in the following ways: XML
, Array
, or by writing a custom class. To create a custom class, you need to inherit from the StoreModel
class.
By default, the XML
model is used.
To use an array
for the model, you must pass the array in the format described in the section Table.
For a custom model, you can specify either the class name or pass its instance.
Option store_view
- Store::OPTION_VIEW_MODEL
The display model for DGS
describes how to render the UI. You can pass an instance of the StoreView
class.
Option theme_template_path
- Store::OPTION_THEME_TEMPLATE_PATH
The path to the templates for the theme depends on the type of display model. By default, the path from Core
(Core::OPTION_THEME_TEMPLATE_PATH
) is taken.
Declaration of the Store in XML Format
To display a list or editing forms for data, you can use several options for data description: XML, Database, or Array. This section describes the XML format; all others are compatible with it.
Example of description:
<?xml version="1.0" encoding="UTF-8" ?>
<table charset="UTF-8"
name="products"
primaryKey="id"
defaultOrderField="id"
defaultOrderDirection="ASC"
rowsForPage="20"
grideditor="true">
<relations>
<link type="child"
field="id"
foreignTable="prices"
foreignField="id_company"
treeCaption="caption" />
<link type="child"
field="id"
foreignTable="categories"
foreignField="id_company"
treeCaption="caption" />
</relations>
<fields>
<field type="readonly"
caption="ID"
sorting="true"
name="id"
trim="60"
width="10%"
filter="text" />
<field type="text"
clicable="true"
name="caption"
caption="<?php echo __('Caption')?>"
width="30%"
filter="text"
sorting="yes"
required="true" />
<field type="select"
caption="<?php echo __('Status')?>"
sorting="true"
name="status"
filter="select"
width="10%"
required="true">
<option id="active"><?php echo __('Active')?></option>
<option id="deleted"><?php echo __('Deleted')?></option>
</field>
<field type="file"
name="logo"
hide="true"
caption="<?php echo __('Logo')?>"
fileName="__ID__.__EXT__"
thumb="120x80"
isnull="true"
uploadDirPath="<?php echo Core::getInstance()->config['paths']['logo']; ?>"
httpPath="<?php echo Core::getInstance()->config['http_paths']['logo']; ?>" />
<field type="text"
name="phone"
caption="<?php echo __('Phone')?>"
width="20%"
required="true"
disclaimer="<?php echo __('Format: (555) 787-4567');?>"
regexp="#^\([0-9]{3}\)\s[0-9]{3}-[0-9]{4}$#" />
<field type="text"
name="state"
caption="<?php echo __('State')?>"
width="10%"
filter="text"
required="true" />
<field type="text"
name="website"
caption="<?php echo __('Website');?>"
width="15%"
filter="text"
regexp="#^[a-z\.]+$#" />
<field type="checkbox"
name="is_paying"
caption="<?php echo __('Is Paying')?>"
isnull="true"
filter="yes"
width="5%" />
<field type="many2many"
caption="<?php echo __('Managers')?>"
linkTable="managers2products"
linkField="id_company"
linkForeignField="id_manager"
foreignTable="users"
foreignKeyField="id"
foreignValueField="name"
hide="true" />
</fields>
<filters>
<filter field="id_user"><?php echo Core::getInstance()->user->getID(); ?></filter>
</filters>
<externalValues>
<value field="mdate"><?php echo date('Y-m-d'); ?></value>
</externalValues>
<actions>
<action type="prices"
caption="<?php echo __('Prices')?>"
relation="prices"
relationType="child"
mode="new" />
<action type="categories"
caption="<?php echo __('Categories')?>"
relation="categories"
relationType="child"
mode="new" />
<action type="insert"
mode="new"
caption="<?php echo __('Add')?>"
title="<?php echo __('Add New'); ?>" />
<action type="list"
caption="<?php echo __('Products')?>" />
<action type="edit"
mode="new"
caption="<?php echo __('Edit')?>"
title="<?php echo __('Edit: %caption%'); ?>" />
<action type="remove"
caption="<?php echo __('Remove')?>" />
</actions>
</table>
Displaying the Store
- The simplest option to display the store is to use the system URL:
/festi/[XML_NAME]/[PLUGIN_NAME]/
/festi/products/
PLUGIN_NAME
must be specified if the XML is in a plugin; in the example, this is the plugin Products.
-
Call the display from the plugin method:
class ProductsPlugin extends DisplayPlugin { public function onDisplayList(Response &$response) { $store = $this->createStoreInstance("products"); $store->onRequest($response); return true; } }
The XML file should be located at: plugins/Products/tblDefs/products.xml
.
-
If you are using multiple databases and want to display data from another database:
$store = $this->createStoreInstanceByConnection($db, "products");
The XML file should be located at: plugins/Products/tblDefs/products.xml
.
-
Through the core:
$store = Core::getInstance()->createStoreInstanceByConnection(...); $store = Core::getInstance()->createStoreInstance(...);
Note that through the core, XML will be searched not in the plugin but in the root of the project in the tblDefs
folder.
If you need to search for XML in the plugin, pass the plugin name in the parameter array with the key plugin
:
```php
$params = array(
'plugin' => 'Products'
);
$store = Core::getInstance()->createStoreInstance("products", $params);
```
Displaying the Editing Form
Sometimes you need to display only specific forms in the stores; here’s an example of how to select and process only the edit form:
$store = $this->createStoreInstance("invoices");
$action = $store->createActionInstance(Store::ACTION_EDIT);
$search = array(
'id' => $data['id']
);
$action->loadRow($search);
$action->onStart($response);
echo $response->getContent();
If you only need to display the form without processing the update request, use fetchForm
instead of onStart
:
echo $action->fetchForm();
Tag relations
Often, it is necessary to establish a connection between different XML files and merge them based on a composite key.
This is done using the relations
and action
tags.
Let's consider an example: suppose we have a list of companies (companies.xml
), and each company has sub-sections of email templates (company_email_templates.xml
).
It is necessary to make a transition from companies
to company_email_templates
:
companies.xml
:
<?xml version="1.0" encoding="UTF-8" ?>
<table charset="UTF-8"
name="companies"
primaryKey="id"
defaultOrderField="id"
defaultOrderDirection="ASC"
rowsForPage="20"
grideditor="true">
<relations>
<link type="child"
field="id"
foreignTable="company_email_templates"
foreignField="id_company"
treeCaption="caption" />
</relations>
<fields>
<field type="readonly"
caption="<?php echo __('ID'); ?>"
sorting="true"
name="id"
trim="60"
width="10%"
filter="text" />
<field type="text"
name="caption"
caption="<?php echo __('Name'); ?>"
width="30%"
filter="text"
sorting="yes"
required="true" />
</fields>
<actions>
<action type="email_templates"
caption="<?php echo __('Email Templates'); ?>"
relation="company_email_templates"
relationType="child"
mode="new" />
<action type="insert"
mode="new"
caption="<?php echo __('Add')?>"
title="<?php echo __('Add New Company'); ?>" />
<action type="list"
caption="<?php echo __('Companies'); ?>" />
<action type="edit"
mode="new"
caption="<?php echo __('Edit')?>"
title="<?php echo __('Edit: %caption%'); ?>" />
<action type="remove"
caption="<?php echo __('Remove')?>" />
</actions>
</table>
We have described a child
dependency in relations
and added an action
of any random type, but it is important not to use reserved types such as insert, list, etc.,
and specified relation
attributes that must match with relations
foreignTable
:
relation="company_email_templates"
relationType="child"
Now, for it to work correctly, it is necessary to specify the parent
relation in company_email_templates.xml
:
<?xml version="1.0" encoding="UTF-8" ?>
<table charset="UTF-8"
name="company_email_templates"
primaryKey="id"
defaultOrderField="id"
defaultOrderDirection="ASC"
rowsForPage="50">
<relations>
<link type="parent"
field="id_company"
foreignTable="companies"
foreignField="id"
treeCaption="caption" />
</relations>
<fields>
<field type="text"
name="caption"
caption="<?php echo __('Caption')?>"
width="30%"
filter="text"
required="true"
sorting="false" />
<field type="text"
name="subject"
caption="<?php echo __('Subject')?>"
filter="text"
width="30%"
required="true"
sorting="false" />
<field type="textarea"
name="body"
caption="<?php echo __('Body')?>"
width="10%"
required="true"
hide="true" />
</fields>
<actions>
<action type="insert"
caption="<?php echo __('Add')?>"
title="<?php echo __('Email Template'); ?>"
mode="new" />
<action type="parent"
caption="<?php echo __('Companies')?>"
relation="companies"
relationType="parent" />
<action type="list"
caption="<?php echo __('Email Templates')?>" />
<action type="edit"
caption="<?php echo __('Edit')?>" />
<action type="remove"
caption="<?php echo __('Remove')?>" />
</actions>
</table>
It is important that in action
you must specify the type as parent
.
If non-system URLs are used (
/festi/
), then you need to specify theurl
attribute in the relation:<link type="child" field="ident" foreignTable="module_options" foreignField="module" url="<?php echo Core::getInstance()->getUrl('/manage/modules/options/');?>" treeCaption="caption" /> <link type="parent" field="module" foreignTable="modules" url="<?php echo Core::getInstance()->getUrl('/manage/modules/');?>" foreignField="ident" treeCaption="caption" />
Tag externalValues
Through externalValues
, you can add values for columns in the store that are known in advance and should not be entered by the user.
<externalValues>
<value field="mdate"><?php echo date('Y-m-d'); ?></value>
</externalValues>
Tag routers
To describe the relationship between tables, you need to use the routers
tag.
<field type="text"
caption="<?php echo __('Owner Email')?>"
sorting="true"
name="id_user"
store="users"
expression="email"
filter="text"
width="25%"
readonly="true" />
<routers>
<route store="advertisements"
joinStore="users"
type="INNER"
on="advertisements.id_user = users.id" />
</routers>
Tag route
Describes the rule for joining tables.
joinStoreName
- the real name of the table; if this attribute is specified, thenjoinStore
will be used as an alias.
Tag highlights
It is often necessary to highlight or change something in the rows of the data list.
For this, you can use highlights
, which adds the specified CSS
class to a row that matches the values specified in the rule
tag.
It is important to note that for foreignKey
fields, if you want to set conditions on values rather than names, you need to add the _foreign_
prefix.
<highlights>
<rule cssClass="m-row-green">
<field name="_foreign_action">replay</field>
</rule>
<rule cssClass="m-row-yellow">
<field name="action">Sent to Customer</field>
</rule>
<rule cssClass="CUSTOM_CSS_CLASS_NAME">
<field name="action">Sent to Customer</field>
<field name="status">active</field>
</rule>
</highlights>
If you need to specify a rule for the value of a column that is not displayed, in the action Store::ACTION_INSERT
, you need to set the attribute isLoadAllColumns="true"
.
Annotations
/**
* @store festi_plugins
* @event Store::EVENT_PREPARE_ACTION_REQUEST
*/
public function onUploadPlugin(FestiEvent &$event)
{
...
}
/**
* @store festi_plugins | OTHERE_STORE
* @event Store::EVENT_BEFORE_INSERT | Store::EVENT_BEFORE_UPDATE
*/
public function onInstallPlugin(FestiEvent &$event)
{
...
}
Examples
Removing an Action from the Store
public function onDisplayList(Response &$response)
{
$store = $this->createStoreInstance("invoices");
$store->getModel()->removeAction(Store::ACTION_EDIT);
$store->onRequest($response);
return true;
}
Retrieving Data from One Table by Multiple Fields
This task often occurs with a user table; for example, in the system, there are two types of users, buyers and managers.
We need to store both the buyer and the manager in one table and display both in the list.
For this, we need to join the user table twice.
In the routers
, the joinStoreName
attribute should specify the actual name of the table, while the joinStore
should be your chosen alias.
<?xml version="1.0" encoding="UTF-8" ?>
<table charset="UTF-8"
name="deals"
primaryKey="id"
defaultOrderField="mdate"
defaultOrderDirection="DESC"
rowsForPage="50"
plugin="Deals">
<search>
<filter field="deals.status">new</filter>
</search>
<routers>
<route store="deals"
joinStore="advertisements"
type="INNER"
on="advertisements.id = deals.id_ad" />
<route store="deals"
joinStore="users"
type="INNER"
on="users.id = deals.id_user" />
<route store="deals"
joinStore="company_users"
joinStoreName="users"
type="LEFT"
on="company_users.id = deals.id_company_user" />
</routers>
<fields>
<field type="text"
caption="<?php echo __('Deal ID'); ?>"
name="id"
width="7%"
required="true"
filter="text"
clicable="true"
sorting="true" />
<field type="composite"
caption="<?php echo __('Customer')?>"
name="customer"
width="10%">
<option store="users">name</option>
<option store="users">lastname</option>
</field>
<field type="composite"
caption="<?php echo __('Contact Info')?>"
name="customer_info"
separator="<br/>"
width="10%">
<option store="users">email</option>
<option store="users">phone</option>
</field>
<field type="datetime"
caption="<?php echo __('Last Updated'); ?>"
name="mdate"
width="10%"
sorting="true" />
<field type="datetime"
caption="<?php echo __('Expiration'); ?>"
name="expire_date"
width="10%"
sorting="true" />
<field type="foreignKey"
name="action"
caption="<?php echo __('Status'); ?>"
width="15%"
foreignTable="deal_actions"
foreignKeyField="ident"
foreignValueField="caption"
filter="select"
isnull="true" />
<field type="composite"
caption="<?php echo __('Manager')?>"
name="company_user"
width="10%">
<option store="company_users">name</option>
<option store="company_users">lastname</option>
</field>
</fields>
<actions>
<action type="list"
caption="<?php echo __('Deals'); ?>" />
</actions>
</table>
Retrieving Parent ID in Tables with Nested Inheritance
<?xml version="1.0" encoding="UTF-8" ?>
<table name="site_contents"
charset="UTF-8"
primaryKey="id"
defaultOrderField="id"
defaultOrderDirection="ASC"
rowsForPage="200">
<relations>
<link type="parent"
field="id_parent"
foreignTable="site_contents"
url="<?php echo '/site/'.$idSite.'/manager/'; ?>"
foreignField="id" />
<link type="child"
field="id"
url="<?php echo '/site/'.$idSite.'/manager/'; ?>"
foreignTable="site_contents"
foreignField="id_parent"
cascade="true"
treeCaption="name" />
</relations>
<filters>
<filter field="status"><?php echo ContentValuesObject::STATUS_ACTIVE; ?></filter>
</filters>
<externalValues>
<value field="id_site"><?php echo $idSite; ?></value>
</externalValues>
<fields>
<field type="readonly"
caption="<?php echo __l('ID'); ?>"
name="id"
width="5%"
required="true"
sorting="true"/>
<field type="text"
clicable="true"
caption="<?php echo __l('Page Title'); ?>"
name="title"
width="30%" />
<field type="text"
clicable="true"
caption="<?php echo __l('Name'); ?>"
name="name"
width="30%"
required="true" />
<field type="select"
caption="<?php echo __('Type');?>"
sorting="true"
name="type"
filter="select"
readonly="true"
width="10%"
required="true">
<option id="file"><?php echo __('File'); ?></option>
<option id="directory"><?php echo __('Directory'); ?></option>
<option id="image"><?php echo __('Image'); ?></option>
<option id="page"><?php echo __('Page'); ?></option>
<option id="module"><?php echo __('Module'); ?></option>
</field>
<field type="text"
caption="<?php echo __l('Path'); ?>"
name="path"
hide="true"
readonly="true"
required="true" />
<field type="checkbox"
clicable="true"
caption="<?php echo __l('Is Menu Item?'); ?>"
name="is_menu_item"
width="20%"
filter="select"
isnull="true"
sorting="true" />
<field type="text"
caption="<?php echo __l('Meta Title'); ?>"
name="meta_title"
hide="true"
isnull="true" />
<field type="text"
caption="<?php echo __l('Meta Keywords'); ?>"
name="meta_keywords"
hide="true"
isnull="true" />
<field type="textarea"
caption="<?php echo __l('Meta Description'); ?>"
name="meta_description"
hide="true"
maxChars="180"
isnull="true" />
</fields>
<filters>
<filter field="id_site"><?php echo $idSite; ?></filter>
</filters>
<listeners>
<listener event="<?php echo Store::EVENT_BEFORE_INSERT; ?>"
plugin="Sites"
method="onCreateNewCategory" />
<listener event="<?php echo Store::EVENT_BEFORE_UPDATE; ?>"
plugin="Sites"
method="onUpdateContent" />
<listener event="<?php echo Store::EVENT_REMOVE; ?>"
plugin="Sites"
method="onDeleteContent" />
<listener event="<?php echo Store::EVENT_ON_LIST_ACTIONS; ?>"
plugin="Sites"
method="onPrepareContentActions" />
</listeners>
<actions>
<action type="parent"
caption="<?php echo __l('Parent'); ?>"
relation="site_contents"
relationType="parent" />
<action type="child"
caption="<?php echo __l('Child Contents'); ?>"
relation="site_contents"
relationType="child" />
<action type="upload"
mode="new"
caption="<?php echo __l('Upload'); ?>"
view="top"
link="<?php
$idParent = $this->store->getParentValue();
if ($idParent) {
echo Core::getInstance()->getUrl('/site/%s/manager/%s/upload/', $idSite, $idParent);
} else {
echo Core::getInstance()->getUrl('/site/%s/manager/upload/', $idSite);
}
?>" />
<action type="insert"
caption="<?php echo __l('Create Directory'); ?>" />
<action type="list"
caption="<?php echo __l('Contents'); ?>" />
<action type="edit"
caption="<?php echo __l('Edit Item'); ?>" />
<action type="remove"
caption="<?php echo __l('Remove Item'); ?>" />
</actions>
</table>
Manually Overriding the Error When Adding a New Record
<?xml version="1.0" encoding="UTF-8" ?>
<table charset="UTF-8"
name="invoices"
primaryKey="id"
defaultOrderField="invoices.id"
defaultOrderDirection="DESC"
rowsForPage="50">
<fields>
<field type="readonly"
name="id_rand_invoice"
caption="<?php echo __('Invoice No')?>"
width="20%"
sorting="yes"
readonly="true"
link="<?php echo Core::getInstance()->getUrl('/invoice/%id%/'); ?>"
isnull="true"
filter="text" />
<field type="readonly"
name="rand_account_number"
caption="<?php echo __('Account No')?>"
width="20%"
sorting="yes"
regexp="#^[A-Za-z0-9]+$#Umis"
filter="text"
readonly="true"
link="<?php echo Core::getInstance()->getUrl('/invoice/%id%/'); ?>"/>
<field type="text"
name="id_tobaccostock_order"
caption="<?php echo __('Order No')?>"
width="20%"
sorting="yes"
regexp="#^[A-Za-z0-9]+$#Umis"
filter="text"
required="true"
link="<?php echo Core::getInstance()->getUrl('/invoice/%id%/'); ?>"/>
<field type="select"
caption="<?php echo __('Status')?>"
sorting="true"
name="status"
onlyList="true"
width="20%">
<option id="new"><?php echo __('New')?></option>
<option id="created"><?php echo __('Created')?></option>
</field>
<field type="foreignKey"
name="id_user"
caption="<?php echo __('Creator'); ?>"
width="20%"
foreignTable="users"
foreignKeyField="id"
foreignValueField="login"
onlyList="true" />
</fields>
<externalValues>
<value field="id_user"><?php echo Core::getInstance()->user->getID(); ?></value>
<value field="status">new</value>
</externalValues>
<listeners>
<listener event="<?php echo Store::EVENT_BEFORE_INSERT; ?>"
plugin="Invoice"
method="onBeforeCreateInvoice" />
</listeners>
<actions>
<action type="list"
caption="<?php echo __('Invoices')?>" />
<action type="edit"
caption="<?php echo __('Edit')?>"
button="<?php echo __('Preview'); ?>"
title="<?php echo __('Invoice Options'); ?>"
cancelCaption="<?php echo __('Create Invoice'); ?>"
cancelUrl="javascript:void(0)"
mode="new" />
<action type="remove"
caption="<?php echo __('Remove'); ?>" />
<action type="create"
caption="<?php echo __('Create'); ?>"
view="top"
link="<?php echo Core::getInstance()->getUrl('/invoices/create/'); ?>"
mode="new" />
</actions>
</table>
/**
* @event Store::EVENT_BEFORE_INSERT
*/
public function onBeforeCreateInvoice(FestiEvent &$event)
{
$idOrder = $event->target['values']['id_tobaccostock_order'];
$search = array(
'id_tobaccostock_order' => $idOrder
);
$invoiceValues = $this->object->get($search);
if ($invoiceValues) {
$event->target['isUpdated'] = true;
$event->target['lastErrorMessage'] = __(
'Invoice for Order No %s already exists.',
$idOrder
);
return false;
}
return true;
} // end onBeforeCreateInvoice
How to Change the Link in Table Cells with Links?
<?xml version="1.0" encoding="UTF-8" ?>
<table name="site_contents"
charset="UTF-8"
primaryKey="id"
defaultOrderField="id"
defaultOrderDirection="ASC"
rowsForPage="200">
<relations>
<link type="parent"
field="id_parent"
foreignTable="site_contents"
url="<?php echo '/site/'.$idSite.'/manager/'; ?>"
foreignField="id" />
<link type="child"
field="id"
url="<?php echo '/site/'.$idSite.'/manager/'; ?>"
foreignTable="site_contents"
foreignField="id_parent"
cascade="true"
treeCaption="name" />
</relations>
<filters>
<filter field="status"><?php echo ContentValuesObject::STATUS_ACTIVE; ?></filter>
</filters>
<externalValues>
<value field="id_site"><?php echo $idSite; ?></value>
</externalValues>
<fields>
<field type="readonly"
caption="<?php echo __l('ID'); ?>"
name="id"
width="5%"
required="true"
sorting="true"/>
<field type="text"
clicable="true"
caption="<?php echo __l('Page Title'); ?>"
name="title"
width="30%" />
<field type="text"
clicable="true"
caption="<?php echo __l('Name'); ?>"
name="name"
width="30%"
required="true" />
</fields>
<filters>
<filter field="id_site"><?php echo $idSite; ?></filter>
</filters>
<listeners>
<listener event="<?php echo Store::EVENT_ON_FETCH_LIST_CELL_VALUE_WITH_LINK; ?>"
plugin="Sites"
method="onPrepareListCellValueLink" />
</listeners>
<actions>
<action type="parent"
caption="<?php echo __l('Parent'); ?>"
relation="site_contents"
relationType="parent" />
<action type="child"
caption="<?php echo __l('Child Contents'); ?>"
relation="site_contents"
relationType="child" />
</actions>
</table>
public function onPrepareListCellValueLink(FestiEvent &$event)
{
$values = &$event->getTargetValueByKey('row');
$allowedTypes = array(
ContentValuesObject::TYPE_IMAGE,
ContentValuesObject::TYPE_PAGE
);
if (!in_array($values['type'], $allowedTypes)) {
return false;
}
$site = System::getCurrentSiteInfo();
$search = array(
'site_contents.id' => $values['id'],
'id_site' => $site['id']
);
$contentValuesObject = $this->plugin->siteContents->loadRow($search);
$url = &$event->getTargetValueByKey('url');
$url = $contentValuesObject->getFullUrl();
$target = &$event->getTargetValueByKey('target');
$target = '_blank';
return true;
} // end onPrepareListCellValueLink
Example of Using DGS
to Create a Form and Manually Process Data
/**
* @urlRule ~^/companies/new/$~
* @area admin
*/
public function onAjaxCreateForm(Response &$response)
{
$store = $this->createStoreInstance("company_create");
$method = array(&$this, 'onCreateNewCompany');
$store->addEventListener(Store::EVENT_BEFORE_INSERT, $method);
$action = $store->createActionInstance(Store::ACTION_INSERT);
if (!$response->isFlush()) {
$response->setAction(Response::ACTION_CONTENT);
}
$action->onStart($response);
return true;
} // end onAjaxCreateForm
public function onCreateNewCompany(StoreActionEvent &$event)
{
$event->setUpdated();
$store = &$event->getActionInstance()->getStore();
$actionName = $store->getAction();
$action = &$store->getModel()->getActionByRef($actionName);
$action['redirectUrl'] = $this->getUrl('/companies/');
} // end onCreateNewCompany
Example of a List Where Columns Obtained Not from the Database, but Filled from a Plugin Need to be Added
<?xml version="1.0" encoding="UTF-8" ?>
<table charset="UTF-8"
name="cloud_services"
primaryKey="id"
defaultOrderField="id"
defaultOrderDirection="ASC"
rowsForPage="20"
emptyMessage="<?php echo __('Not found Services...')?>">
<fields>
<field type="text"
name="caption"
caption="<?php echo __('Service'); ?>"
width="30%" />
<field type="text"
caption="<?php echo __('Host'); ?>"
name="host"
width="30%"
isCustom="true" />
<field type="text"
caption="<?php echo __('Status'); ?>"
name="status"
width="30%"
isCustom="true" />
</fields>
<listeners>
<listener event="<?php echo Store::EVENT_ON_LOAD_LIST_DATA; ?>"
plugin="FestiCloudServicesManager"
method="onLoadListData" />
</listeners>
<actions>
<action type="list"
caption="<?php echo __('Services'); ?>" />
<action type="toggle"
caption="<?php echo __l('Enable'); ?>"
confirmDialog="true"
dialogTitle="<?php echo __('Confirmation'); ?>"
dialogMessage="<?php echo __('Are you sure?'); ?>"
link="<?php echo Core::getInstance()->getUrl('/app/%s/services/%%id%%/toggle/', App::getID()); ?>" />
</actions>
</table>
public function onLoadListData(FestiEvent &$event)
{
$tableData = &$event->getTargetValueByKey('data');
$info = &$event->getTargetValueByKey('info');
$indexes = &$info['indexes'];
$idApp = App::getID();
$statusIndex = $indexes['status'];
$hostIndex = $indexes['host'];
$services = $this->_loadServicesByAppID($idApp);
foreach ($tableData as &$row) {
$this->_prepareServiceRow(
$row,
$services,
$statusIndex,
$hostIndex
);
}
} // end onLoadListData
private function _prepareServiceRow(
&$row, $services, $statusIndex, $hostIndex
)
{
$idService = $row['id'];
$status = &$row['data'][$statusIndex]['value'];
$host = &$row['data'][$hostIndex]['value'];
if (empty($services[$idService])) {
$status = '—';
$host = '—';
} else {
$service = $services[$idService];
$status = $service['status'];
$host = $service['host'].":".$service['port'];
}
return true;
} // end _prepareServiceRow
Changing Standard Notifications When Adding (Deleting) a Record
After successfully adding (deleting) a record, we see the standard message STATUS_SUCCESS
. To change it, you can use the following code:
public function onDisplayInvites(Response &$response)
{
$store = $this->createStoreInstance("user_invites");
$msg = __('Your invitation has been sent successfully');
if ($this->isRemoveRequest()) {
$msg = __('Your invitation has been deleted successfully');
}
$store->setOption(Store::OPTION_MESSAGE_SUCCESS, $msg);
$store->onRequest($response);
} // end onDisplayInvites
To disable messages, you should set the option Store::OPTION_MESSAGE_SUCCESS
to null
.
$store->setOption(Store::OPTION_MESSAGE_SUCCESS, null);