rules.event.inc 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421
  1. <?php
  2. /**
  3. * @file
  4. * Contains event handler interface and base classes.
  5. */
  6. /**
  7. * Interface for handling rules events.
  8. *
  9. * Configurable events (i.e. events making use of settings) have a custom
  10. * event suffix, which gets appended to the base event name. The configured
  11. * event name of, e.g. the event for viewing an article node, would be
  12. * node_view--article, whereas "node_view" is the base event name and "article"
  13. * the event suffix as returned from
  14. * RulesEventHandlerInterface::getEventNameSuffix(). The event suffix is
  15. * generated based upon the event settings and must map to this settings, i.e.
  16. * each set of event settings must always generate the same suffix.
  17. * For a configurable event to be invoked, rules_invoke_event() has to be called
  18. * with the configured event name, e.g.
  19. * @code
  20. * rules_invoke_event('node_view--' . $node->type, $node, $view_mode);
  21. * @endcode
  22. * If the event settings are optional, both events have to be invoked whereas
  23. * usually the more general event is invoked last. E.g.:
  24. * @code
  25. * rules_invoke_event('node_view--' . $node->type, $node, $view_mode);
  26. * rules_invoke_event('node_view', $node, $view_mode);
  27. * @endcode
  28. *
  29. * Rules event handlers have to be declared using the 'class' key in
  30. * hook_rules_event_info(), or may be discovered automatically, see
  31. * rules_discover_plugins() for details.
  32. *
  33. * @see RulesEventHandlerBase
  34. * @see RulesEventDefaultHandler
  35. */
  36. interface RulesEventHandlerInterface {
  37. /**
  38. * Constructs the event handler.
  39. *
  40. * @param string $event_name
  41. * The base event string.
  42. * @param array $info
  43. * The event info of the given event.
  44. */
  45. public function __construct($event_name, $info);
  46. /**
  47. * Sets the event settings.
  48. *
  49. * @param array $settings
  50. * An array of settings to set.
  51. *
  52. * @return RulesEventHandlerInterface
  53. * The handler itself for chaining.
  54. */
  55. public function setSettings(array $settings);
  56. /**
  57. * Gets the event settings.
  58. *
  59. * @return array
  60. * The array of settings.
  61. */
  62. public function getSettings();
  63. /**
  64. * Returns an array of default settings.
  65. *
  66. * @return array
  67. * The array of default settings.
  68. */
  69. public function getDefaults();
  70. /**
  71. * Returns a user-facing summary of the settings.
  72. *
  73. * @return string
  74. * The summary in HTML, i.e. properly escaped or filtered.
  75. */
  76. public function summary();
  77. /**
  78. * Builds the event settings form.
  79. *
  80. * @param array $form_state
  81. * An associative array containing the current state of the form.
  82. *
  83. * @return array
  84. * The form structure.
  85. */
  86. public function buildForm(array &$form_state);
  87. /**
  88. * Validate the event settings independent from a form submission.
  89. *
  90. * @throws RulesIntegrityException
  91. * In case of validation errors, RulesIntegrityExceptions are thrown.
  92. */
  93. public function validate();
  94. /**
  95. * Extract the form values and update the event settings.
  96. *
  97. * @param array $form
  98. * An associative array containing the structure of the form.
  99. * @param array $form_state
  100. * An associative array containing the current state of the form.
  101. */
  102. public function extractFormValues(array &$form, array &$form_state);
  103. /**
  104. * Returns the suffix to be added to the base event named based upon settings.
  105. *
  106. * If event settings are used, the event name Rules uses for the configured
  107. * event is {EVENT_NAME}--{SUFFIX}.
  108. *
  109. * @return string
  110. * The suffix string. Return an empty string for not appending a suffix.
  111. */
  112. public function getEventNameSuffix();
  113. /**
  114. * Returns info about the variables provided by this event.
  115. *
  116. * @return array
  117. * An array of provided variables, keyed by variable names and with the
  118. * variable info array as value.
  119. */
  120. public function availableVariables();
  121. /**
  122. * Returns the base name of the event the event handler belongs to.
  123. *
  124. * @return string
  125. * The name of the event the event handler belongs to.
  126. */
  127. public function getEventName();
  128. /**
  129. * Returns the info array of the event the event handler belongs to.
  130. *
  131. * @return string
  132. * The info array of the event the event handler belongs to.
  133. */
  134. public function getEventInfo();
  135. }
  136. /**
  137. * Interface for event dispatchers.
  138. */
  139. interface RulesEventDispatcherInterface extends RulesEventHandlerInterface {
  140. /**
  141. * Starts the event watcher.
  142. */
  143. public function startWatching();
  144. /**
  145. * Stops the event watcher.
  146. */
  147. public function stopWatching();
  148. /**
  149. * Returns whether the event dispatcher is currently active.
  150. *
  151. * @return bool
  152. * TRUE if the event dispatcher is currently active, FALSE otherwise.
  153. */
  154. public function isWatching();
  155. }
  156. /**
  157. * Base class for event handler.
  158. */
  159. abstract class RulesEventHandlerBase implements RulesEventHandlerInterface {
  160. /**
  161. * The event name.
  162. *
  163. * @var string
  164. */
  165. protected $eventName;
  166. /**
  167. * The event info.
  168. *
  169. * @var array
  170. */
  171. protected $eventInfo;
  172. /**
  173. * The event settings.
  174. *
  175. * @var array
  176. */
  177. protected $settings = array();
  178. /**
  179. * Implements RulesEventHandlerInterface::__construct().
  180. */
  181. public function __construct($event_name, $info) {
  182. $this->eventName = $event_name;
  183. $this->eventInfo = $info;
  184. $this->settings = $this->getDefaults();
  185. }
  186. /**
  187. * Implements RulesEventHandlerInterface::getSettings().
  188. */
  189. public function getSettings() {
  190. return $this->settings;
  191. }
  192. /**
  193. * Implements RulesEventHandlerInterface::setSettings().
  194. */
  195. public function setSettings(array $settings) {
  196. $this->settings = $settings + $this->getDefaults();
  197. return $this;
  198. }
  199. /**
  200. * Implements RulesEventHandlerInterface::validate().
  201. */
  202. public function validate() {
  203. // Nothing to check by default.
  204. }
  205. /**
  206. * Implements RulesEventHandlerInterface::extractFormValues().
  207. */
  208. public function extractFormValues(array &$form, array &$form_state) {
  209. foreach ($this->getDefaults() as $key => $setting) {
  210. $this->settings[$key] = isset($form_state['values'][$key]) ? $form_state['values'][$key] : $setting;
  211. }
  212. }
  213. /**
  214. * Implements RulesEventHandlerInterface::availableVariables().
  215. */
  216. public function availableVariables() {
  217. return isset($this->eventInfo['variables']) ? $this->eventInfo['variables'] : array();
  218. }
  219. /**
  220. * Implements RulesEventHandlerInterface::getEventName().
  221. */
  222. public function getEventName() {
  223. return $this->eventName;
  224. }
  225. /**
  226. * Implements RulesEventHandlerInterface::getEventInfo().
  227. */
  228. public function getEventInfo() {
  229. return $this->eventInfo;
  230. }
  231. }
  232. /**
  233. * A handler for events having no settings. This is the default handler.
  234. */
  235. class RulesEventDefaultHandler extends RulesEventHandlerBase {
  236. /**
  237. * Implements RulesEventHandlerInterface::buildForm().
  238. */
  239. public function buildForm(array &$form_state) {
  240. return array();
  241. }
  242. /**
  243. * Implements RulesEventHandlerInterface::getConfiguredEventName().
  244. */
  245. public function getEventNameSuffix() {
  246. return '';
  247. }
  248. /**
  249. * Implements RulesEventHandlerInterface::summary().
  250. */
  251. public function summary() {
  252. return check_plain($this->eventInfo['label']);
  253. }
  254. /**
  255. * Implements RulesEventHandlerInterface::getDefaults().
  256. */
  257. public function getDefaults() {
  258. return array();
  259. }
  260. /**
  261. * Implements RulesEventHandlerInterface::getSettings().
  262. */
  263. public function getSettings() {
  264. return NULL;
  265. }
  266. }
  267. /**
  268. * Exposes the bundle of an entity as event setting.
  269. */
  270. class RulesEventHandlerEntityBundle extends RulesEventHandlerBase {
  271. protected $entityType;
  272. protected $entityInfo;
  273. protected $bundleKey;
  274. /**
  275. * Implements RulesEventHandlerInterface::__construct().
  276. */
  277. public function __construct($event_name, $info) {
  278. parent::__construct($event_name, $info);
  279. // Cut off the suffix, e.g. remove 'view' from node_view.
  280. $this->entityType = implode('_', explode('_', $event_name, -1));
  281. $this->entityInfo = entity_get_info($this->entityType);
  282. if (!$this->entityInfo) {
  283. throw new InvalidArgumentException('Unsupported event name passed.');
  284. }
  285. }
  286. /**
  287. * Implements RulesEventHandlerInterface::summary().
  288. */
  289. public function summary() {
  290. $bundle = &$this->settings['bundle'];
  291. $bundle_label = isset($this->entityInfo['bundles'][$bundle]['label']) ? $this->entityInfo['bundles'][$bundle]['label'] : $bundle;
  292. $suffix = isset($bundle) ? ' ' . t('of @bundle-key %name', array('@bundle-key' => $this->getBundlePropertyLabel(), '%name' => $bundle_label)) : '';
  293. return check_plain($this->eventInfo['label']) . $suffix;
  294. }
  295. /**
  296. * Implements RulesEventHandlerInterface::buildForm().
  297. */
  298. public function buildForm(array &$form_state) {
  299. $form['bundle'] = array(
  300. '#type' => 'select',
  301. '#title' => t('Restrict by @bundle', array('@bundle' => $this->getBundlePropertyLabel())),
  302. '#description' => t('If you need to filter for multiple values, either add multiple events or use the "Entity is of bundle" condition instead.'),
  303. '#default_value' => $this->settings['bundle'],
  304. '#empty_value' => '',
  305. '#options' => array(),
  306. );
  307. foreach ($this->entityInfo['bundles'] as $name => $bundle_info) {
  308. $form['bundle']['#options'][$name] = $bundle_info['label'];
  309. }
  310. return $form;
  311. }
  312. /**
  313. * Returns the label to use for the bundle property.
  314. *
  315. * @return string
  316. * The label to use for the bundle property.
  317. */
  318. protected function getBundlePropertyLabel() {
  319. return $this->entityInfo['entity keys']['bundle'];
  320. }
  321. /**
  322. * Implements RulesEventHandlerInterface::extractFormValues().
  323. */
  324. public function extractFormValues(array &$form, array &$form_state) {
  325. $this->settings['bundle'] = !empty($form_state['values']['bundle']) ? $form_state['values']['bundle'] : NULL;
  326. }
  327. /**
  328. * Implements RulesEventHandlerInterface::validate().
  329. */
  330. public function validate() {
  331. if ($this->settings['bundle'] && empty($this->entityInfo['bundles'][$this->settings['bundle']])) {
  332. throw new RulesIntegrityException(t('The @bundle %bundle of %entity_type is not known.',
  333. array(
  334. '%bundle' => $this->settings['bundle'],
  335. '%entity_type' => $this->entityInfo['label'],
  336. '@bundle' => $this->getBundlePropertyLabel(),
  337. )), array(NULL, 'bundle'));
  338. }
  339. }
  340. /**
  341. * Implements RulesEventHandlerInterface::getConfiguredEventName().
  342. */
  343. public function getEventNameSuffix() {
  344. return $this->settings['bundle'];
  345. }
  346. /**
  347. * Implements RulesEventHandlerInterface::getDefaults().
  348. */
  349. public function getDefaults() {
  350. return array(
  351. 'bundle' => NULL,
  352. );
  353. }
  354. /**
  355. * Implements RulesEventHandlerInterface::availableVariables().
  356. */
  357. public function availableVariables() {
  358. $variables = $this->eventInfo['variables'];
  359. if ($this->settings['bundle']) {
  360. // Add the bundle to all variables of the entity type.
  361. foreach ($variables as $name => $variable_info) {
  362. if ($variable_info['type'] == $this->entityType) {
  363. $variables[$name]['bundle'] = $this->settings['bundle'];
  364. }
  365. }
  366. }
  367. return $variables;
  368. }
  369. }