class RulesEntityController in Rules 7.2
Make sure loaded rule configs are instantiated right.
Hierarchy
- class \DrupalDefaultEntityController implements DrupalEntityControllerInterface
- class \EntityAPIController implements EntityAPIControllerRevisionableInterface
- class \EntityAPIControllerExportable
- class \RulesEntityController
- class \EntityAPIControllerExportable
- class \EntityAPIController implements EntityAPIControllerRevisionableInterface
Expanded class hierarchy of RulesEntityController
1 string reference to 'RulesEntityController'
- rules_entity_info in ./
rules.module - Implements hook_entity_info().
File
- includes/
rules.core.inc, line 16 - Rules base classes and interfaces needed for any rule evaluation.
View source
class RulesEntityController extends EntityAPIControllerExportable {
/**
* Overridden.
*
* @see EntityAPIController::create()
*/
public function create(array $values = array()) {
// Default to rules as owning module.
$values += array(
'owner' => 'rules',
);
return parent::create($values);
}
/**
* Overridden.
*
* @see DrupalDefaultEntityController::attachLoad()
*/
protected function attachLoad(&$queried_entities, $revision_id = FALSE) {
// Retrieve stdClass records and store them as rules objects in 'data'.
$ids = array_keys($queried_entities);
$result = db_select('rules_tags')
->fields('rules_tags', array(
'id',
'tag',
))
->condition('id', $ids, 'IN')
->execute();
foreach ($result as $row) {
$tags[$row->id][] = $row->tag;
}
$result = db_select('rules_dependencies')
->fields('rules_dependencies', array(
'id',
'module',
))
->condition('id', $ids, 'IN')
->execute();
foreach ($result as $row) {
$modules[$row->id][] = $row->module;
}
$entities = array();
foreach ($queried_entities as $record) {
$entity = $record->data;
// Set the values of the other columns.
foreach ($this->entityInfo['schema_fields_sql']['base table'] as $field) {
$entity->{$field} = $record->{$field};
}
unset($entity->data, $entity->plugin);
// Add any tags or dependencies.
$entity->dependencies = isset($modules[$entity->id]) ? $modules[$entity->id] : array();
$entity->tags = isset($tags[$entity->id]) ? $tags[$entity->id] : array();
$entities[$entity->id] = $entity;
}
$queried_entities = $entities;
parent::attachLoad($queried_entities, $revision_id);
}
/**
* Override to support having events and tags as conditions.
*
* @see EntityAPIController::applyConditions()
* @see rules_query_rules_config_load_multiple_alter()
*/
protected function applyConditions($entities, $conditions = array()) {
if (isset($conditions['event']) || isset($conditions['plugin'])) {
foreach ($entities as $key => $entity) {
if (isset($conditions['event']) && (!$entity instanceof RulesTriggerableInterface || !in_array($conditions['event'], $entity
->events()))) {
unset($entities[$key]);
}
if (isset($conditions['plugin']) && !is_array($conditions['plugin'])) {
$conditions['plugin'] = array(
$conditions['plugin'],
);
}
if (isset($conditions['plugin']) && !in_array($entity
->plugin(), $conditions['plugin'])) {
unset($entities[$key]);
}
}
unset($conditions['event'], $conditions['plugin']);
}
if (!empty($conditions['tags'])) {
foreach ($entities as $key => $entity) {
foreach ($conditions['tags'] as $tag) {
if (in_array($tag, $entity->tags)) {
continue 2;
}
}
unset($entities[$key]);
}
unset($conditions['tags']);
}
return parent::applyConditions($entities, $conditions);
}
/**
* Overridden to work with Rules' custom export format.
*
* @param string $export
* A serialized string in JSON format as produced by the
* RulesPlugin::export() method, or the PHP export as usual PHP array.
* @param string $error_msg
* The error message.
*/
public function import($export, &$error_msg = '') {
$export = is_array($export) ? $export : drupal_json_decode($export);
if (!is_array($export)) {
$error_msg = t('Unable to parse the pasted export.');
return FALSE;
}
// The key is the configuration name and the value the actual export.
$name = key($export);
$export = current($export);
if (!isset($export['PLUGIN'])) {
$error_msg = t('Export misses plugin information.');
return FALSE;
}
// Create an empty configuration, re-set basic keys and import.
$config = rules_plugin_factory($export['PLUGIN']);
$config->name = $name;
foreach (array(
'label',
'active',
'weight',
'tags',
'access_exposed',
'owner',
) as $key) {
if (isset($export[strtoupper($key)])) {
$config->{$key} = $export[strtoupper($key)];
}
}
if (!empty($export['REQUIRES'])) {
foreach ($export['REQUIRES'] as $module) {
if (!module_exists($module)) {
$error_msg = t('Missing the required module %module.', array(
'%module' => $module,
));
return FALSE;
}
}
$config->dependencies = $export['REQUIRES'];
}
$config
->import($export);
return $config;
}
public function save($rules_config, DatabaseTransaction $transaction = NULL) {
$transaction = isset($transaction) ? $transaction : db_transaction();
// Load the stored entity, if any.
if (!isset($rules_config->original) && $rules_config->{$this->idKey}) {
$rules_config->original = entity_load_unchanged($this->entityType, $rules_config->{$this->idKey});
}
$original = isset($rules_config->original) ? $rules_config->original : NULL;
$return = parent::save($rules_config, $transaction);
$this
->storeTags($rules_config);
if ($rules_config instanceof RulesTriggerableInterface) {
$this
->storeEvents($rules_config);
}
$this
->storeDependencies($rules_config);
// See if there are any events that have been removed.
if ($original && $rules_config->plugin == 'reaction rule') {
foreach (array_diff($original
->events(), $rules_config
->events()) as $event_name) {
// Check if the event handler implements the event dispatcher interface.
$handler = rules_get_event_handler($event_name, $rules_config
->getEventSettings($event_name));
if (!$handler instanceof RulesEventDispatcherInterface) {
continue;
}
// Only stop an event dispatcher if there are no rules for it left.
if (!rules_config_load_multiple(FALSE, array(
'event' => $event_name,
'plugin' => 'reaction rule',
'active' => TRUE,
)) && $handler
->isWatching()) {
$handler
->stopWatching();
}
}
}
return $return;
}
/**
* Save tagging information to the rules_tags table.
*/
protected function storeTags($rules_config) {
db_delete('rules_tags')
->condition('id', $rules_config->id)
->execute();
if (!empty($rules_config->tags)) {
foreach ($rules_config->tags as $tag) {
db_insert('rules_tags')
->fields(array(
'id',
'tag',
), array(
$rules_config->id,
$tag,
))
->execute();
}
}
}
/**
* Save event information to the rules_trigger table.
*/
protected function storeEvents(RulesTriggerableInterface $rules_config) {
db_delete('rules_trigger')
->condition('id', $rules_config->id)
->execute();
foreach ($rules_config
->events() as $event) {
db_insert('rules_trigger')
->fields(array(
'id' => $rules_config->id,
'event' => $event,
))
->execute();
}
}
protected function storeDependencies($rules_config) {
db_delete('rules_dependencies')
->condition('id', $rules_config->id)
->execute();
if (!empty($rules_config->dependencies)) {
foreach ($rules_config->dependencies as $dependency) {
db_insert('rules_dependencies')
->fields(array(
'id' => $rules_config->id,
'module' => $dependency,
))
->execute();
}
}
}
/**
* Overridden to support tags and events in $conditions.
*
* @see EntityAPIControllerExportable::buildQuery()
*/
protected function buildQuery($ids, $conditions = array(), $revision_id = FALSE) {
$query = parent::buildQuery($ids, $conditions, $revision_id);
$query_conditions =& $query
->conditions();
foreach ($query_conditions as &$condition) {
// One entry in $query_conditions is a string with key '#conjunction'.
// @see QueryConditionInterface::conditions()
if (is_array($condition)) {
// Support using 'tags' => array('tag1', 'tag2') as condition.
if ($condition['field'] == 'base.tags') {
$query
->join('rules_tags', 'rt', 'base.id = rt.id');
$condition['field'] = 'rt.tag';
}
// Support using 'event' => $name as condition.
if ($condition['field'] == 'base.event') {
$query
->join('rules_trigger', 'tr', "base.id = tr.id");
$condition['field'] = 'tr.event';
// Use like operator to support % wildcards also.
$condition['operator'] = 'LIKE';
}
}
}
return $query;
}
/**
* Overridden to also delete tags and events.
*
* @see EntityAPIControllerExportable::delete()
*/
public function delete($ids, DatabaseTransaction $transaction = NULL) {
$transaction = isset($transaction) ? $transaction : db_transaction();
// Use entity-load as ids may be the names as well as the ids.
$configs = $ids ? entity_load('rules_config', $ids) : array();
if ($configs) {
foreach ($configs as $config) {
db_delete('rules_trigger')
->condition('id', $config->id)
->execute();
db_delete('rules_tags')
->condition('id', $config->id)
->execute();
db_delete('rules_dependencies')
->condition('id', $config->id)
->execute();
}
}
$return = parent::delete($ids, $transaction);
// Stop event dispatchers when deleting the last rule of an event set.
$processed = array();
foreach ($configs as $config) {
if ($config
->getPluginName() != 'reaction rule') {
continue;
}
foreach ($config
->events() as $event_name) {
// Only process each event once.
if (!empty($processed[$event_name])) {
continue;
}
$processed[$event_name] = TRUE;
// Check if the event handler implements the event dispatcher interface.
$handler = rules_get_event_handler($event_name, $config
->getEventSettings($event_name));
if (!$handler instanceof RulesEventDispatcherInterface) {
continue;
}
// Only stop an event dispatcher if there are no rules for it left.
if ($handler
->isWatching() && !rules_config_load_multiple(FALSE, array(
'event' => $event_name,
'plugin' => 'reaction rule',
'active' => TRUE,
))) {
$handler
->stopWatching();
}
}
}
return $return;
}
}
Members
Name | Modifiers | Type | Description | Overrides |
---|---|---|---|---|
DrupalDefaultEntityController:: |
protected | property | Whether this entity type should use the static cache. | |
DrupalDefaultEntityController:: |
protected | property | Static cache of entities, keyed by entity ID. | |
DrupalDefaultEntityController:: |
protected | property | Array of information about the entity. | |
DrupalDefaultEntityController:: |
protected | property | Entity type for this controller instance. | |
DrupalDefaultEntityController:: |
protected | property | Additional arguments to pass to hook_TYPE_load(). | |
DrupalDefaultEntityController:: |
protected | property | Name of the entity's ID field in the entity database table. | |
DrupalDefaultEntityController:: |
protected | property | Name of entity's revision database table field, if it supports revisions. | |
DrupalDefaultEntityController:: |
protected | property | The table that stores revisions, if the entity supports revisions. | |
DrupalDefaultEntityController:: |
protected | function | Ensures integer entity IDs are valid. | |
DrupalDefaultEntityController:: |
protected | function | Callback for array_filter that removes non-integer IDs. | |
EntityAPIController:: |
protected | property | ||
EntityAPIController:: |
protected | property | ||
EntityAPIController:: |
protected | property | ||
EntityAPIController:: |
public | function |
Implements EntityAPIControllerInterface. Overrides EntityAPIControllerInterface:: |
|
EntityAPIController:: |
public | function |
Implements EntityAPIControllerRevisionableInterface::deleteRevision(). Overrides EntityAPIControllerRevisionableInterface:: |
|
EntityAPIController:: |
public | function | Builds and executes the query for loading. | |
EntityAPIController:: |
protected | function | Renders a single entity property. | |
EntityAPIController:: |
protected | function | Saves an entity revision. | |
EntityAPIControllerExportable:: |
protected | property | ||
EntityAPIControllerExportable:: |
protected | property | ||
EntityAPIControllerExportable:: |
protected | function |
Overridden. Overrides DrupalDefaultEntityController:: |
|
EntityAPIControllerExportable:: |
protected | function | Like cacheGet() but keyed by name. | |
EntityAPIControllerExportable:: |
protected | function |
Overridden. Overrides DrupalDefaultEntityController:: |
|
EntityAPIControllerExportable:: |
public | function |
Overridden. Overrides EntityAPIController:: |
|
EntityAPIControllerExportable:: |
public | function |
Overridden to care about reverted bundle entities and to skip Rules. Overrides EntityAPIController:: |
|
EntityAPIControllerExportable:: |
public | function |
Overridden to support passing numeric ids as well as names as $ids. Overrides EntityAPIController:: |
|
EntityAPIControllerExportable:: |
public | function |
Overrides DrupalDefaultEntityController::resetCache(). Overrides EntityAPIController:: |
|
EntityAPIControllerExportable:: |
public | function |
Implements EntityAPIControllerInterface. Overrides EntityAPIController:: |
|
EntityAPIControllerExportable:: |
public | function |
Overridden. Overrides EntityAPIController:: |
|
RulesEntityController:: |
protected | function |
Override to support having events and tags as conditions. Overrides EntityAPIControllerExportable:: |
|
RulesEntityController:: |
protected | function |
Overridden. Overrides EntityAPIControllerExportable:: |
|
RulesEntityController:: |
protected | function |
Overridden to support tags and events in $conditions. Overrides EntityAPIControllerExportable:: |
|
RulesEntityController:: |
public | function |
Overridden. Overrides EntityAPIController:: |
|
RulesEntityController:: |
public | function |
Overridden to also delete tags and events. Overrides EntityAPIControllerExportable:: |
|
RulesEntityController:: |
public | function |
Overridden to work with Rules' custom export format. Overrides EntityAPIController:: |
|
RulesEntityController:: |
public | function |
Overridden to care exportables that are overridden. Overrides EntityAPIControllerExportable:: |
|
RulesEntityController:: |
protected | function | ||
RulesEntityController:: |
protected | function | Save event information to the rules_trigger table. | |
RulesEntityController:: |
protected | function | Save tagging information to the rules_tags table. |