Entities Plugin

With this plugin, you describe the data of a system as entities in the database, not in XML files. An entity is a table with fields. Each entity can have an unlimited number of storages (forms) for data management. A storage is a DGS (Store) that the plugin builds from database records at run time.

What the plugin does

  • It keeps the entity definitions in festi_entities and the entity fields in festi_entity_fields.
  • It keeps the storages in festi_entity_forms. Each storage has fields, actions, conditions, sections and routers.
  • loadStorage() reads these records and returns a Store instance.
  • The backend pages let an administrator edit entities, fields and storages.
  • If an entity has the Alter Table flag (is_use_alterstore), the plugin changes the database table of the entity. It creates, renames and removes the table and its columns when you change the entity or its fields.

Requirements

  • A Festi project with the Jimbo system plugin.
  • A MySQL database. The install files and the Alter Table function use MySQL statements only.
  • The HUI bundle of the framework (bundle/ui/Hui.php). The plugin class loads this file.

Installation

Use the Festi CLI to add the plugin to the project. Run the command from the project root:

./vendor/bin/festi-plugin --mode install --path ./src/dashboard/ --dump ./dumps/ \
    --plugin Entities --repository [email protected]:FestiPlugins/PHP_Festi_Plugin_Entities.git

This example was not run for this page.

The command adds the repository to the plugins directory as a git submodule. It also adds the plugin to festi_plugins through a new project migration.

The command does not create the plugin tables. It reads install/install.<database type>.sql, and this repository has install/install.sql and install/update1.sql. Thus, add the tables with a project migration:

  1. Make an empty migration:
./vendor/bin/festi-make-migration --path ./src/dashboard/ --dump ./dumps/
  1. Copy the statements from install/install.sql into the new migration.
  2. Add the statements from install/update1.sql that the database does not have.
  3. Apply the migration:
./vendor/bin/festi-migrate --path ./src/dashboard/ --dump ./dumps/

Obey these precautions when you make the migration:

  • install/install.sql contains DROP TABLE IF EXISTS statements. Do not apply them to a database that has data in these tables.
  • The two files overlap. Both add festi_entities.is_use_alterstore and festi_entity_form_fields.attributes.
  • The two files disagree about the column type of festi_entity_default_actions. Use the definition from install/install.sql.
  • The source needs these objects from install/update1.sql: the column festi_entity_forms.attributes and the tables festi_entity_form_routers, festi_entity_form_action_user_types_permission and festi_entity_form_field_user_types_permission.

The install files do not add URL rules. The plugin class declares these rules for the area backend:

URL rule Method Function
~^/festi/make_form/([^/]+)/$~ onDisplayMakeFormByEntity Makes a storage with all fields of the entity.
~^/forms/([^/]+)/$~ onDisplayForm Shows the storage with the given ident.

Configuration

The plugin has no options in the project configuration. You do the configuration on the backend pages:

Page URL Function
Definition /festi/festi_entities/Entities/ Add entities and their fields.
Storages /festi/festi_entity_forms/Entities/ Add storages and their fields, actions, conditions and sections.

The plugin menu (__getMenu()) also contains the item Wizard with the URL /store/wizard/. This repository does not contain a method for that URL.

To make a storage:

  1. Open the page Definition and add an entity. The field Table Name is the ident of the entity.
  2. Add the fields of the entity with the action Fields.
  3. Use the action Make Form. The plugin adds a storage with the same ident as the entity.
  4. Open the page Storages to change the fields, actions, conditions and sections of the storage.
  5. Use the action Preview to open the storage at /forms/<ident>/.

Usage

Get the plugin from another plugin with $this->plugin->entities. The examples in this section were not run for this page.

Load a row of an entity

loadInfoByIdent() takes the ident of an entity. loadDatabaseData() returns one row.

$info = $this->plugin->entities->loadInfoByIdent('new_store');

$search = array(
    'id' => $id
);

$data = $this->plugin->entities->loadDatabaseData($info, $search);

Load a storage and use event listeners

loadStorage() takes the ident of a storage and an array of options. It returns a Store instance. loadFormStore() does the same, but it is deprecated.

$options = array(
    'title' => __('Test Store'),
    'search' => array(
        'id_parent' => $idParent
    ),
    'externalValues' => array(
        'cdate' => date('Y-m-d')
    ),
    'actions' => array(
        'insert' => array(
            'type'    => 'insert',
            'caption' => __('New Record')
        )
    ),
    'url' => '/stores/test/'
);

$store = $this->plugin->entities->loadStorage('new_store', $options);

$store->addEventListener(
    Store::EVENT_INSERT,
    array($this, 'onInsert')
);

$store->addEventListener(
    Store::EVENT_PREPARE_VALUES,
    array($this, 'onPreparedValues')
);

$store->onRequest($response);

loadStorage() reads these options:

Option Type Function
title string Replaces the title of the storage.
search array Conditions that the plugin adds to the conditions of the storage.
actions array Actions that the plugin adds to the actions of the storage.
routers array Table relations that the plugin adds to the relations of the storage.
filters array Filters of the Store model.
externalValues array External values of the Store model.
externalFields array Fields that the plugin adds to the fields of the storage.
plugin string or object The plugin that owns the handler. With a string, the plugin reads the handler from <plugins_path><plugin>/tblHandlers/.
customHandler string The class name of the Store handler.
handler_options array Options for the handler.
url string The URL of the storage. The default is the current URL.
defaultAction string The default action of the Store model.
groupBy string The groupBy value of the Store model.
storeName string The name of the Store and of its table. The defaults are the ident of the storage and the ident of the entity.
store_view object The view object of the Store.
theme_template_path string The template path of the theme for the Store.
message_success string The message that the Store shows after a successful action.
connection object The database connection. The default is the connection of the project.

Get the insert form and insert values into a storage

Show the insert form:

$action = $store->createActionInstance(Store::ACTION_INSERT);
$action->onStart($response);

Insert the values from the request:

$action = $store->createActionInstance(Store::ACTION_INSERT);

$store->addEventListener(
    Store::EVENT_PREPARE_VALUES,
    array($this, 'onPreparedProcessingValues')
);

$store->begin();

$info = $action->apply($_REQUEST, $errors);
if (!$info) {
    $store->rollback();
    return false;
}

Load a formatted row with a custom handler

loadFormattedRowByForm() returns the caption and the formatted value of each field of one row. loadRowByForm() returns the row without the format. loadFormattedByForm() returns all rows that match the search.

require_once dirname(__FILE__).'/tblHandlers/NegotiatorHandler.php';

$options = array(
    'plugin' => 'Negotiator',
    'customHandler' => 'NegotiatorHandler',
);

$values = $this->plugin->entities->loadFormattedRowByForm(
    'negotiator_email',
    $data['id'],
    $options
);