You are here

abstract class RulesContainerPlugin in Rules 7.2

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

Hierarchy

Expanded class hierarchy of RulesContainerPlugin

File

includes/rules.core.inc, line 2190
Rules base classes and interfaces needed for any rule evaluation.

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

Namesort descending Modifiers Type Description 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.