class RulesContainerPlugin

Base class for ContainerPlugins like Rules, Logical Operations or Loops.

Hierarchy

Expanded class hierarchy of RulesContainerPlugin

File

includes/rules.core.inc, line 2209

View source
abstract class RulesContainerPlugin extends RulesPlugin implements IteratorAggregate {
    protected $children = array();
    public function __construct($variables = array()) {
        $this->setUp();
        if (!empty($variables) && $this->isRoot()) {
            $this->info['variables'] = $variables;
        }
    }
    
    /**
     * Returns the specified variables, in case the plugin is used as component.
     */
    public function &componentVariables() {
        if ($this->isRoot()) {
            $this->info += array(
                'variables' => array(),
            );
            return $this->info['variables'];
        }
        // We have to return a reference in any case.
        $return = NULL;
        return $return;
    }
    
    /**
     * Allows access to the children through the iterator.
     *
     * @return RulesRecursiveElementIterator
     */
    public function getIterator() {
        return new RulesRecursiveElementIterator($this->children);
    }
    
    /**
     * @return RulesContainerPlugin
     */
    public function integrityCheck() {
        if (!empty($this->info['variables']) && !$this->isRoot()) {
            throw new RulesIntegrityException(t('%plugin: Specifying state variables is not possible for child elements.', array(
                '%plugin' => $this->getPluginName(),
            )), $this);
        }
        parent::integrityCheck();
        foreach ($this->children as $child) {
            $child->integrityCheck();
        }
        return $this;
    }
    public function dependencies() {
        $modules = array_flip(parent::dependencies());
        foreach ($this->children as $child) {
            $modules += array_flip($child->dependencies());
        }
        return array_keys($modules);
    }
    public function parameterInfo($optional = FALSE) {
        $params = parent::parameterInfo($optional);
        if (isset($this->info['variables'])) {
            foreach ($this->info['variables'] as $name => $var_info) {
                if (empty($var_info['handler']) && (!isset($var_info['parameter']) || $var_info['parameter'])) {
                    $params[$name] = $var_info;
                    // For lists allow empty variables by default.
                    if (entity_property_list_extract_type($var_info['type'])) {
                        $params[$name] += array(
                            'allow null' => TRUE,
                        );
                    }
                }
            }
        }
        return $params;
    }
    public function availableVariables() {
        if (!isset($this->availableVariables)) {
            if ($this->isRoot()) {
                $this->availableVariables = RulesState::defaultVariables();
                if (isset($this->info['variables'])) {
                    $this->availableVariables += $this->info['variables'];
                }
            }
            else {
                $this->availableVariables = $this->parent
                    ->stateVariables($this);
            }
        }
        return $this->availableVariables;
    }
    
    /**
     * Returns available state variables for an element.
     *
     * Returns info about variables available in the evaluation state for any
     * children elements or if given for a special child element.
     *
     * @param $element
     *   The element for which the available state variables should be returned.
     *   If NULL is given, the variables available before any children are invoked
     *   are returned. If set to TRUE, the variables available after evaluating
     *   all children will be returned.
     */
    protected function stateVariables($element = NULL) {
        $vars = $this->availableVariables();
        if (isset($element)) {
            // Add in variables provided by siblings executed before the element.
            foreach ($this->children as $child) {
                if ($child === $element) {
                    break;
                }
                $vars += $child->providesVariables();
                // Take variable info assertions into account.
                if ($assertions = $child->variableInfoAssertions()) {
                    $vars = RulesData::addMetadataAssertions($vars, $assertions);
                }
            }
        }
        return $vars;
    }
    protected function variableInfoAssertions() {
        $assertions = array();
        foreach ($this->children as $child) {
            if ($add = $child->variableInfoAssertions()) {
                $assertions = rules_update_array($assertions, $add);
            }
        }
        return $assertions;
    }
    protected function setUpVariables() {
        return isset($this->info['variables']) ? parent::parameterInfo(TRUE) + $this->info['variables'] : $this->parameterInfo(TRUE);
    }
    
    /**
     * Executes container with the given arguments.
     *
     * Condition containers just return a boolean while action containers return
     * the configured provided variables as an array of variables.
     */
    public function executeByArgs($args = array()) {
        $replacements = array(
            '%label' => $this->label(),
            '@plugin' => $this->itemName,
        );
        rules_log('Executing @plugin %label.', $replacements, RulesLog::INFO, $this, TRUE);
        $this->processSettings();
        $state = $this->setUpState($args);
        // Handle recursion prevention.
        if ($state->isBlocked($this)) {
            return rules_log('Not evaluating @plugin %label to prevent recursion.', array(
                '%label' => $this->label(),
                '@plugin' => $this->plugin(),
            ), RulesLog::INFO);
        }
        // Block the config to prevent any future recursion.
        $state->block($this);
        module_invoke_all('rules_config_execute', $this);
        $result = $this->evaluate($state);
        $return = $this->returnVariables($state, $result);
        $state->unblock($this);
        $state->cleanUp();
        rules_log('Finished executing of @plugin %label.', $replacements, RulesLog::INFO, $this, FALSE);
        return $return;
    }
    public function access() {
        foreach ($this->children as $key => $child) {
            if (!$child->access()) {
                return FALSE;
            }
        }
        return TRUE;
    }
    public function destroy() {
        foreach ($this->children as $key => $child) {
            $child->destroy();
        }
        parent::destroy();
    }
    
    /**
     * By default we do a deep clone.
     */
    public function __clone() {
        parent::__clone();
        foreach ($this->children as $key => $child) {
            $this->children[$key] = clone $child;
            $this->children[$key]->parent = $this;
        }
    }
    
    /**
     * Overrides delete to keep the children alive, if possible.
     */
    public function delete($keep_children = TRUE) {
        if (isset($this->parent) && $keep_children) {
            foreach ($this->children as $child) {
                $child->setParent($this->parent);
            }
        }
        parent::delete();
    }
    public function __sleep() {
        return parent::__sleep() + array(
            'children' => 'children',
            'info' => 'info',
        );
    }
    
    /**
     * Sorts all child elements by their weight.
     *
     * @param bool $deep
     *   If enabled a deep sort is performed, thus the whole element tree below
     *   this element is sorted.
     */
    public function sortChildren($deep = FALSE) {
        // Make sure the array order is kept in case two children have the same
        // weight by ensuring later children would have higher weights.
        foreach (array_values($this->children) as $i => $child) {
            $child->weight += $i / 1000;
        }
        usort($this->children, array(
            'RulesPlugin',
            'compare',
        ));
        // Fix up the weights afterwards to be unique integers.
        foreach (array_values($this->children) as $i => $child) {
            $child->weight = $i;
        }
        if ($deep) {
            foreach (new ParentIterator($this->getIterator()) as $child) {
                $child->sortChildren(TRUE);
            }
        }
        $this->resetInternalCache();
    }
    protected function exportChildren($key = NULL) {
        $key = isset($key) ? $key : strtoupper($this->plugin());
        $export[$key] = array();
        foreach ($this->children as $child) {
            $export[$key][] = $child->export();
        }
        return $export;
    }
    
    /**
     * Determines whether the element should be exported in flat style.
     *
     * Flat style means that the export keys are written directly into the export
     * array, whereas else the export is written into a sub-array.
     */
    protected function exportFlat() {
        // By default we always use flat style for plugins without any parameters
        // or provided variables, as then only children have to be exported. E.g.
        // this applies to the OR and AND plugins.
        return $this->isRoot() || !$this->pluginParameterInfo() && !$this->providesVariables();
    }
    protected function exportToArray() {
        $export = array();
        if (!empty($this->info['variables'])) {
            $export['USES VARIABLES'] = $this->info['variables'];
        }
        if ($this->exportFlat()) {
            $export += $this->exportSettings() + $this->exportChildren();
        }
        else {
            $export[strtoupper($this->plugin())] = $this->exportSettings() + $this->exportChildren();
        }
        return $export;
    }
    public function import(array $export) {
        if (!empty($export['USES VARIABLES'])) {
            $this->info['variables'] = $export['USES VARIABLES'];
        }
        // Care for exports having the export array nested in a sub-array.
        if (!$this->exportFlat()) {
            $export = reset($export);
        }
        $this->importSettings($export);
        $this->importChildren($export);
    }
    protected function importChildren($export, $key = NULL) {
        $key = isset($key) ? $key : strtoupper($this->plugin());
        foreach ($export[$key] as $child_export) {
            $plugin = _rules_import_get_plugin(rules_array_key($child_export), $this instanceof RulesActionInterface ? 'action' : 'condition');
            $child = rules_plugin_factory($plugin);
            $child->setParent($this);
            $child->import($child_export);
        }
    }
    public function resetInternalCache() {
        $this->availableVariables = NULL;
        foreach ($this->children as $child) {
            $child->resetInternalCache();
        }
    }
    
    /**
     * Overrides optimize().
     */
    public function optimize() {
        parent::optimize();
        // Now let the children optimize itself.
        foreach ($this as $element) {
            $element->optimize();
        }
    }

}

Members

Title Sort descending Modifiers Object type Summary Overriden Title Overrides
RulesContainerPlugin::$children protected property
RulesContainerPlugin::access public function Whether the currently logged in user has access to all configured elements. Overrides RulesPlugin::access 1
RulesContainerPlugin::availableVariables public function Returns info about variables available to be used as arguments for this element. Overrides RulesPlugin::availableVariables
RulesContainerPlugin::componentVariables public function Returns the specified variables, in case the plugin is used as component.
RulesContainerPlugin::delete public function Overrides delete to keep the children alive, if possible. Overrides RulesPlugin::delete 1
RulesContainerPlugin::dependencies public function Calculates an array of required modules. Overrides RulesPlugin::dependencies 1
RulesContainerPlugin::destroy public function Removes circular object references so PHP garbage collector can work. Overrides RulesPlugin::destroy 1
RulesContainerPlugin::executeByArgs public function Executes container with the given arguments. Overrides RulesPlugin::executeByArgs 1
RulesContainerPlugin::exportChildren protected function 4
RulesContainerPlugin::exportFlat protected function Determines whether the element should be exported in flat style. 1
RulesContainerPlugin::exportToArray protected function Overrides RulesPlugin::exportToArray 1
RulesContainerPlugin::getIterator public function Allows access to the children through the iterator. 1
RulesContainerPlugin::import public function Applies the given export. Overrides RulesPlugin::import 1
RulesContainerPlugin::importChildren protected function 4
RulesContainerPlugin::integrityCheck public function Overrides RulesPlugin::integrityCheck 2
RulesContainerPlugin::optimize public function Overrides optimize(). Overrides RulesPlugin::optimize
RulesContainerPlugin::parameterInfo public function Returns info about parameters needed for executing the configured plugin. Overrides RulesPlugin::parameterInfo
RulesContainerPlugin::resetInternalCache public function Resets any internal static caches. Overrides RulesPlugin::resetInternalCache 1
RulesContainerPlugin::setUpVariables protected function Returns info about all variables that have to be setup in the state. Overrides RulesPlugin::setUpVariables
RulesContainerPlugin::sortChildren public function Sorts all child elements by their weight. 1
RulesContainerPlugin::stateVariables protected function Returns available state variables for an element. 4
RulesContainerPlugin::variableInfoAssertions protected function Returns asserted additions to the available variable info. Overrides RulesPlugin::variableInfoAssertions 1
RulesContainerPlugin::__clone public function By default we do a deep clone. Overrides RulesPlugin::__clone 1
RulesContainerPlugin::__construct public function Overrides RulesExtendable::__construct 1
RulesContainerPlugin::__sleep public function Overrides RulesPlugin::__sleep 2
RulesExtendable::$itemInfo protected property
RulesExtendable::$itemName protected property The name of the item this class represents in the info hook. 9
RulesExtendable::facesAs public function
RulesExtendable::forceSetUp public function Forces the object to be setUp, this executes setUp() if not done yet. 1
RulesExtendable::itemFacesAs public static function Returns whether the a RuleExtendable supports the given interface.
RulesExtendable::rebuildCache public function Allows items to add something to the rules cache. 1
RulesExtendable::setUp protected function 1
RulesExtendable::__call public function Magic method: Invoke the dynamically implemented methods.
RulesPlugin::$availableVariables protected property Static cache for availableVariables(). 1
RulesPlugin::$cache protected property Overrides RulesExtendable::$cache
RulesPlugin::$elementId protected property Identifies an element inside a configuration.
RulesPlugin::$hook protected property Overrides RulesExtendable::$hook
RulesPlugin::$id public property If this is a configuration saved to the db, the id of it.
RulesPlugin::$info protected property Info about this element. Usage depends on the plugin. 2
RulesPlugin::$name public property
RulesPlugin::$parent protected property The parent element, if any.
RulesPlugin::$settings public property An array of settings for this element.
RulesPlugin::$weight public property
RulesPlugin::applyDataSelector public function Applies the given data selector.
RulesPlugin::checkParameterSettings protected function Checks whether parameters are correctly configured.
RulesPlugin::checkVarName protected function
RulesPlugin::compare protected static function
RulesPlugin::depth public function Returns the depth of this element in the configuration.
RulesPlugin::elementId public function Returns the element id, which identifies the element inside the config.
RulesPlugin::elementMap public function Gets the element map helper object, which helps mapping elements to ids.
RulesPlugin::elements public function Iterate over all elements nested below the current element.
RulesPlugin::ensureNameExists protected function Ensure the configuration has a name. If not, generate one.
RulesPlugin::entityInfo public function
RulesPlugin::entityType public function
RulesPlugin::evaluate abstract public function Evaluate the element on a given rules evaluation state. 5
RulesPlugin::execute public function Execute the configuration.
RulesPlugin::export public function Exports a rule configuration.
RulesPlugin::exportParameterSetting protected function
RulesPlugin::exportSettings protected function 1
RulesPlugin::form public function Seamlessly invokes the method implemented via faces.
RulesPlugin::form_submit public function
RulesPlugin::form_validate public function
RulesPlugin::getArgument protected function Returns the argument for the parameter $name described with $info.
RulesPlugin::getArgumentInfo public function Returns info about the configured argument.
RulesPlugin::getExecutionArguments protected function Gets the right arguments for executing the element.
RulesPlugin::getPluginName public function Gets the name of this plugin instance. 1
RulesPlugin::hasStatus public function Checks if the configuration has a certain exportable status.
RulesPlugin::identifier public function Returns the config name.
RulesPlugin::importParameterSetting protected function
RulesPlugin::importSettings protected function 1
RulesPlugin::info public function Returns the info of the plugin. 2
RulesPlugin::internalIdentifier public function
RulesPlugin::isRoot public function Returns whether the element is the root of the configuration.
RulesPlugin::label public function Returns the label of the element. 4
RulesPlugin::parentElement public function Returns the element's parent.
RulesPlugin::plugin public function Returns the name of the element's plugin.
RulesPlugin::pluginInfo public function Returns info about the element's plugin.
RulesPlugin::pluginParameterInfo public function Returns info about parameters needed by the plugin. 2
RulesPlugin::pluginProvidesVariables public function Returns info about variables 'provided' by the plugin. 2
RulesPlugin::processSettings public function Processes the settings e.g. to prepare input evaluators. 1
RulesPlugin::providesVariables public function Returns info about all variables provided for later evaluated elements. 2
RulesPlugin::returnExport protected function Finalizes the configuration export.
RulesPlugin::returnVariables protected function Gets variables to return once the configuration has been executed. 2
RulesPlugin::root public function Gets the root element of the configuration.
RulesPlugin::save public function Saves the configuration to the database. 1
RulesPlugin::setParent public function Sets a new parent element.
RulesPlugin::setUpState public function Sets up the execution state for the given arguments.
RulesPlugin::__toString public function When converted to a string, just use the export format.