abstract class RulesAbstractPlugin in Rules 7.2
Defines a common base class for so-called "Abstract Plugins" like actions.
Modules have to provide the concrete plugin implementation.
Hierarchy
- class \RulesExtendable extends \FacesExtendable
- class \RulesPlugin
- class \RulesAbstractPlugin
- class \RulesPlugin
Expanded class hierarchy of RulesAbstractPlugin
1 string reference to 'RulesAbstractPlugin'
- rules_ui_add_element in ui/
ui.forms.inc - Add a new element a rules configuration.
File
- includes/
rules.core.inc, line 1500 - Rules base classes and interfaces needed for any rule evaluation.
View source
abstract class RulesAbstractPlugin extends RulesPlugin {
protected $elementName;
protected $info = array(
'parameter' => array(),
'provides' => array(),
);
protected $infoLoaded = FALSE;
/**
* @param string $name
* The plugin implementation's name.
* @param $settings
* (optional) Further information provided about the plugin.
* @throws RulesException
* If validation of the passed settings fails RulesExceptions are thrown.
*/
public function __construct($name = NULL, $settings = array()) {
$this->elementName = $name;
$this->settings = (array) $settings + array(
'#_needs_processing' => TRUE,
);
$this
->setUp();
}
protected function setUp() {
parent::setUp();
if (isset($this->cache[$this->itemName . '_info'][$this->elementName])) {
$this->info = $this->cache[$this->itemName . '_info'][$this->elementName];
// Remember that the info has been correctly setup.
// @see self::forceSetup()
$this->infoLoaded = TRUE;
// Register the defined class, if any.
if (isset($this->info['class'])) {
$this->faces['RulesPluginImplInterface'] = 'RulesPluginImplInterface';
$face_methods = get_class_methods('RulesPluginImplInterface');
$class_info = array(
1 => $this->info['class'],
);
foreach ($face_methods as $method) {
$this->facesMethods[$method] = $class_info;
}
}
// Add in per-plugin implementation callbacks if any.
if (!empty($this->info['faces_cache'])) {
foreach ($this->info['faces_cache'] as $face => $data) {
list($methods, $file_names) = $data;
foreach ($methods as $method => $callback) {
$this->facesMethods[$method] = $callback;
}
foreach ((array) $file_names as $method => $name) {
$this->facesIncludes[$method] = array(
'module' => $this->info['module'],
'name' => $name,
);
}
}
// Invoke the info_alter callback, but only if it has been implemented.
if ($this->facesMethods['info_alter'] != $this->itemInfo['faces_cache'][0]['info_alter']) {
$this
->__call('info_alter', array(
&$this->info,
));
}
}
}
elseif (!empty($this->itemInfo['faces_cache']) && function_exists($this->elementName)) {
// We don't have any info, so just add the name as execution callback.
$this
->override(array(
'execute' => $this->elementName,
));
}
}
public function forceSetUp() {
if (!isset($this->cache) || !empty($this->itemInfo['faces_cache']) && !$this->faces) {
$this
->setUp();
}
elseif (!$this->infoLoaded && isset($this->cache[$this->itemName . '_info'][$this->elementName])) {
$this
->setUp();
}
}
/**
* Returns the label of the element.
*/
public function label() {
$info = $this
->info();
return isset($info['label']) ? $info['label'] : t('@plugin "@name"', array(
'@name' => $this->elementName,
'@plugin' => $this
->plugin(),
));
}
public function access() {
$info = $this
->info();
$this
->loadBasicInclude();
if (!empty($info['access callback']) && !call_user_func($info['access callback'], $this->itemName, $this
->getElementName())) {
return FALSE;
}
return parent::access() && $this
->__call('access');
}
public function integrityCheck() {
// Do the usual integrity check first so the implementation's validation
// handler can rely on that already.
parent::integrityCheck();
// Make sure the element is known.
$this
->forceSetUp();
if (!isset($this->cache[$this->itemName . '_info'][$this->elementName])) {
throw new RulesIntegrityException(t('Unknown @plugin %name.', array(
'@plugin' => $this
->plugin(),
'%name' => $this->elementName,
)));
}
$this
->validate();
return $this;
}
public function processSettings($force = FALSE) {
// Process if not done yet.
if ($force || !empty($this->settings['#_needs_processing'])) {
$this
->resetInternalCache();
// In case the element implements the info alteration callback, (re-)run
// the alteration so that any settings depending info alterations are
// applied.
if ($this->facesMethods && $this->facesMethods['info_alter'] != $this->itemInfo['faces_cache'][0]['info_alter']) {
$this
->__call('info_alter', array(
&$this->info,
));
}
// First let the plugin implementation do processing, so data types of the
// parameters are fixed when we process the settings.
$this
->process();
parent::processSettings($force);
}
}
public function pluginParameterInfo() {
// Ensure the info alter callback has been executed.
$this
->forceSetup();
return parent::pluginParameterInfo();
}
public function pluginProvidesVariables() {
// Ensure the info alter callback has been executed.
$this
->forceSetup();
return parent::pluginProvidesVariables();
}
public function info() {
// Ensure the info alter callback has been executed.
$this
->forceSetup();
return $this->info;
}
protected function variableInfoAssertions() {
// Get the implementation's assertions and map them to the variable names.
if ($assertions = $this
->__call('assertions')) {
foreach ($assertions as $param_name => $data) {
$name = isset($this->settings[$param_name . ':select']) ? $this->settings[$param_name . ':select'] : $param_name;
$return[$name] = $data;
}
return $return;
}
}
public function import(array $export) {
// The key is the element name and the value the actual export.
$this->elementName = rules_array_key($export);
$export = reset($export);
// After setting the element name, setup the element again so the right
// element info is loaded.
$this
->setUp();
if (!isset($export['USING']) && !isset($export['PROVIDES']) && !empty($export)) {
// The export has been abbreviated to skip "USING".
$export = array(
'USING' => $export,
);
}
$this
->importSettings($export);
}
protected function exportToArray() {
$export = $this
->exportSettings();
if (!$this
->providesVariables()) {
// Abbreviate the export making "USING" implicit.
$export = isset($export['USING']) ? $export['USING'] : array();
}
return array(
$this->elementName => $export,
);
}
public function dependencies() {
$modules = array_flip(parent::dependencies());
$modules += array_flip((array) $this
->__call('dependencies'));
return array_keys($modules + (!empty($this->info['module']) ? array(
$this->info['module'] => 1,
) : array()));
}
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();
// If there is no element info, just pass through the passed arguments.
// That way we support executing actions without any info at all.
if ($this
->info()) {
$state = $this
->setUpState($args);
module_invoke_all('rules_config_execute', $this);
$result = $this
->evaluate($state);
$return = $this
->returnVariables($state, $result);
}
else {
rules_log('Unable to execute @plugin %label.', $replacements, RulesLog::ERROR, $this);
}
$state
->cleanUp();
rules_log('Finished executing of @plugin %label.', $replacements, RulesLog::INFO, $this, FALSE);
return $return;
}
/**
* Execute the configured execution callback and log that.
*/
protected abstract function executeCallback(array $args, RulesState $state = NULL);
public function evaluate(RulesState $state) {
$this
->processSettings();
try {
// Get vars as needed for execute and call it.
return $this
->executeCallback($this
->getExecutionArguments($state), $state);
} catch (RulesEvaluationException $e) {
rules_log($e->msg, $e->args, $e->severity);
rules_log('Unable to evaluate %name.', array(
'%name' => $this
->getPluginName(),
), RulesLog::WARN, $this);
} catch (EntityMetadataWrapperException $e) {
rules_log('Unable to get a data value. Error: !error', array(
'!error' => $e
->getMessage(),
), RulesLog::WARN);
rules_log('Unable to evaluate %name.', array(
'%name' => $this
->getPluginName(),
), RulesLog::WARN, $this);
}
}
public function __sleep() {
return parent::__sleep() + array(
'elementName' => 'elementName',
);
}
public function getPluginName() {
return $this->itemName . " " . $this->elementName;
}
/**
* Gets the name of the configured action or condition.
*/
public function getElementName() {
return $this->elementName;
}
/**
* Add in the data provided by the info hooks to the cache.
*/
public function rebuildCache(&$itemInfo, &$cache) {
parent::rebuildCache($itemInfo, $cache);
// Include all declared files so we can find all implementations.
self::includeFiles();
// Get the plugin's own info data.
$cache[$this->itemName . '_info'] = rules_fetch_data($this->itemName . '_info');
foreach ($cache[$this->itemName . '_info'] as $name => &$info) {
$info += array(
'parameter' => isset($info['arguments']) ? $info['arguments'] : array(),
'provides' => isset($info['new variables']) ? $info['new variables'] : array(),
'base' => $name,
'callbacks' => array(),
);
unset($info['arguments'], $info['new variables']);
if (function_exists($info['base'])) {
$info['callbacks'] += array(
'execute' => $info['base'],
);
}
// We do not need to build a faces cache for RulesPluginHandlerInterface,
// which gets added in automatically as its a parent of
// RulesPluginImplInterface.
unset($this->faces['RulesPluginHandlerInterface']);
// Build up the per-plugin implementation faces cache.
foreach ($this->faces as $interface) {
$methods = $file_names = array();
$includes = self::getIncludeFiles($info['module']);
foreach (get_class_methods($interface) as $method) {
if (isset($info['callbacks'][$method]) && ($function = $info['callbacks'][$method])) {
$methods[$method][0] = $function;
$file_names[$method] = $this
->getFileName($function, $includes);
}
elseif (isset($info['class']) && is_subclass_of($info['class'], $interface)) {
$methods[$method][1] = $info['class'];
}
elseif (function_exists($function = $info['base'] . '_' . $method)) {
$methods[$method][0] = $function;
$file_names[$method] = $this
->getFileName($function, $includes);
}
}
// Cache only the plugin implementation specific callbacks.
$info['faces_cache'][$interface] = array(
$methods,
array_filter($file_names),
);
}
// Filter out interfaces with no overridden methods.
$info['faces_cache'] = rules_filter_array($info['faces_cache'], 0, TRUE);
// We don't need that any more.
unset($info['callbacks'], $info['base']);
}
}
/**
* Loads this module's .rules.inc file.
*
* Makes sure the providing modules' .rules.inc file is included, as diverse
* callbacks may reside in that file.
*/
protected function loadBasicInclude() {
static $included = array();
if (isset($this->info['module']) && !isset($included[$this->info['module']])) {
$module = $this->info['module'];
module_load_include('inc', $module, $module . '.rules');
$included[$module] = TRUE;
}
}
/**
* Makes sure all supported destinations are included.
*/
public static function includeFiles() {
static $included;
if (!isset($included)) {
foreach (module_implements('rules_file_info') as $module) {
// rules.inc are already included thanks to the rules_hook_info() group.
foreach (self::getIncludeFiles($module, FALSE) as $name) {
module_load_include('inc', $module, $name);
}
}
$dirs = array();
foreach (module_implements('rules_directory') as $module) {
// Include all files once, so the discovery can find them.
$result = module_invoke($module, 'rules_directory');
if (!is_array($result)) {
$result = array(
$module => $result,
);
}
$dirs += $result;
}
foreach ($dirs as $module => $directory) {
$module_path = drupal_get_path('module', $module);
foreach (array(
'inc',
'php',
) as $extension) {
foreach (glob("{$module_path}/{$directory}/*.{$extension}") as $filename) {
include_once $filename;
}
}
}
$included = TRUE;
}
}
/**
* Returns all include files for a module.
*
* @param string $module
* The module name.
* @param bool $all
* If FALSE, the $module.rules.inc file isn't added.
*
* @return string[]
* An array containing the names of all the include files for a module.
*/
protected static function getIncludeFiles($module, $all = TRUE) {
$files = (array) module_invoke($module, 'rules_file_info');
// Automatically add "$module.rules_forms.inc" and "$module.rules.inc".
$files[] = $module . '.rules_forms';
if ($all) {
$files[] = $module . '.rules';
}
return $files;
}
protected function getFileName($function, $includes) {
static $filenames;
if (!isset($filenames) || !array_key_exists($function, $filenames)) {
$filenames[$function] = NULL;
$reflector = new ReflectionFunction($function);
// On windows the path contains backslashes instead of slashes, fix that.
$file = str_replace('\\', '/', $reflector
->getFileName());
foreach ($includes as $include) {
$pos = strpos($file, $include . '.inc');
// Test whether the file ends with the given filename.inc.
if ($pos !== FALSE && strlen($file) - $pos == strlen($include) + 4) {
$filenames[$function] = $include;
return $include;
}
}
}
return $filenames[$function];
}
}
Members
Name![]() |
Modifiers | Type | Description | Overrides |
---|---|---|---|---|
RulesAbstractPlugin:: |
protected | property | ||
RulesAbstractPlugin:: |
protected | property |
Info about this element. Usage depends on the plugin. Overrides RulesPlugin:: |
|
RulesAbstractPlugin:: |
protected | property | ||
RulesAbstractPlugin:: |
public | function |
Whether the currently logged in user has access to all configured elements. Overrides RulesPlugin:: |
|
RulesAbstractPlugin:: |
public | function |
Calculates an array of required modules. Overrides RulesPlugin:: |
|
RulesAbstractPlugin:: |
public | function |
Evaluate the element on a given rules evaluation state. Overrides RulesPlugin:: |
|
RulesAbstractPlugin:: |
public | function |
Execute the configuration by passing arguments in a single array. Overrides RulesPlugin:: |
|
RulesAbstractPlugin:: |
abstract protected | function | Execute the configured execution callback and log that. | 2 |
RulesAbstractPlugin:: |
protected | function |
Overrides RulesPlugin:: |
1 |
RulesAbstractPlugin:: |
public | function |
Forces the object to be setUp, this executes setUp() if not done yet. Overrides RulesExtendable:: |
|
RulesAbstractPlugin:: |
public | function | Gets the name of the configured action or condition. | |
RulesAbstractPlugin:: |
protected | function | ||
RulesAbstractPlugin:: |
protected static | function | Returns all include files for a module. | |
RulesAbstractPlugin:: |
public | function |
Gets the name of this plugin instance. Overrides RulesPlugin:: |
|
RulesAbstractPlugin:: |
public | function |
Applies the given export. Overrides RulesPlugin:: |
1 |
RulesAbstractPlugin:: |
public static | function | Makes sure all supported destinations are included. | |
RulesAbstractPlugin:: |
public | function |
Returns the info of the plugin. Overrides RulesPlugin:: |
|
RulesAbstractPlugin:: |
public | function |
Makes sure the plugin is configured right. Overrides RulesPlugin:: |
|
RulesAbstractPlugin:: |
public | function |
Returns the label of the element. Overrides RulesPlugin:: |
1 |
RulesAbstractPlugin:: |
protected | function | Loads this module's .rules.inc file. | |
RulesAbstractPlugin:: |
public | function |
Returns info about parameters needed by the plugin. Overrides RulesPlugin:: |
|
RulesAbstractPlugin:: |
public | function |
Returns info about variables 'provided' by the plugin. Overrides RulesPlugin:: |
|
RulesAbstractPlugin:: |
public | function |
Processes the settings e.g. to prepare input evaluators. Overrides RulesPlugin:: |
|
RulesAbstractPlugin:: |
public | function |
Add in the data provided by the info hooks to the cache. Overrides RulesExtendable:: |
|
RulesAbstractPlugin:: |
protected | function |
Overrides RulesExtendable:: |
|
RulesAbstractPlugin:: |
protected | function |
Returns asserted additions to the available variable info. Overrides RulesPlugin:: |
|
RulesAbstractPlugin:: |
public | function |
Overrides RulesExtendable:: |
|
RulesAbstractPlugin:: |
public | function |
Overrides RulesPlugin:: |
1 |
RulesExtendable:: |
protected | property | ||
RulesExtendable:: |
protected | property | The name of the item this class represents in the info hook. | 9 |
RulesExtendable:: |
public | function | ||
RulesExtendable:: |
public static | function | Returns whether the a RuleExtendable supports the given interface. | |
RulesExtendable:: |
public | function | Magic method: Invoke the dynamically implemented methods. | |
RulesPlugin:: |
protected | property | Static cache for availableVariables(). | 1 |
RulesPlugin:: |
protected | property |
Overrides RulesExtendable:: |
|
RulesPlugin:: |
protected | property | Identifies an element inside a configuration. | |
RulesPlugin:: |
protected | property |
Overrides RulesExtendable:: |
|
RulesPlugin:: |
public | property | If this is a configuration saved to the db, the id of it. | |
RulesPlugin:: |
public | property | ||
RulesPlugin:: |
protected | property | The parent element, if any. | |
RulesPlugin:: |
public | property | An array of settings for this element. | |
RulesPlugin:: |
public | property | ||
RulesPlugin:: |
public | function | Applies the given data selector. | |
RulesPlugin:: |
public | function | Returns info about variables available to be used as arguments for this element. | 1 |
RulesPlugin:: |
protected | function | Checks whether parameters are correctly configured. | |
RulesPlugin:: |
protected | function | ||
RulesPlugin:: |
protected static | function | ||
RulesPlugin:: |
public | function | Deletes configuration from database. | 1 |
RulesPlugin:: |
public | function | Returns the depth of this element in the configuration. | |
RulesPlugin:: |
public | function | Removes circular object references so PHP garbage collector can work. | 1 |
RulesPlugin:: |
public | function | Returns the element id, which identifies the element inside the config. | |
RulesPlugin:: |
public | function | Gets the element map helper object, which helps mapping elements to ids. | |
RulesPlugin:: |
public | function | Iterate over all elements nested below the current element. | |
RulesPlugin:: |
protected | function | Ensure the configuration has a name. If not, generate one. | |
RulesPlugin:: |
public | function | ||
RulesPlugin:: |
public | function | ||
RulesPlugin:: |
public | function | Execute the configuration. | |
RulesPlugin:: |
public | function | Exports a rule configuration. | |
RulesPlugin:: |
protected | function | ||
RulesPlugin:: |
protected | function | 1 | |
RulesPlugin:: |
public | function | Seamlessly invokes the method implemented via faces. | |
RulesPlugin:: |
public | function | ||
RulesPlugin:: |
public | function | ||
RulesPlugin:: |
protected | function | Returns the argument for the parameter $name described with $info. | |
RulesPlugin:: |
public | function | Returns info about the configured argument. | |
RulesPlugin:: |
protected | function | Gets the right arguments for executing the element. | |
RulesPlugin:: |
public | function | Checks if the configuration has a certain exportable status. | |
RulesPlugin:: |
public | function | Returns the config name. | |
RulesPlugin:: |
protected | function | ||
RulesPlugin:: |
protected | function | 1 | |
RulesPlugin:: |
public | function | ||
RulesPlugin:: |
public | function | Returns whether the element is the root of the configuration. | |
RulesPlugin:: |
public | function | Optimizes a rule configuration in order to speed up evaluation. | 1 |
RulesPlugin:: |
public | function | Returns info about parameters needed for executing the configured plugin. | 1 |
RulesPlugin:: |
public | function | Returns the element's parent. | |
RulesPlugin:: |
public | function | Returns the name of the element's plugin. | |
RulesPlugin:: |
public | function | Returns info about the element's plugin. | |
RulesPlugin:: |
public | function | Returns info about all variables provided for later evaluated elements. | 2 |
RulesPlugin:: |
public | function | Resets any internal static caches. | 1 |
RulesPlugin:: |
protected | function | Finalizes the configuration export. | |
RulesPlugin:: |
protected | function | Gets variables to return once the configuration has been executed. | 2 |
RulesPlugin:: |
public | function | Gets the root element of the configuration. | |
RulesPlugin:: |
public | function | Saves the configuration to the database. | 1 |
RulesPlugin:: |
public | function | Sets a new parent element. | |
RulesPlugin:: |
public | function | Sets up the execution state for the given arguments. | |
RulesPlugin:: |
protected | function | Returns info about all variables that have to be setup in the state. | 1 |
RulesPlugin:: |
public | function | Do a deep clone. | 1 |
RulesPlugin:: |
public | function | When converted to a string, just use the export format. |