rules.event.inc 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411
  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. */
  68. public function getDefaults();
  69. /**
  70. * Returns a user-facing summary of the settings.
  71. *
  72. * @return string
  73. * The summary in HTML, i.e. properly escaped or filtered.
  74. */
  75. public function summary();
  76. /**
  77. * Builds the event settings form.
  78. *
  79. * @param array $form_state
  80. * An associative array containing the current state of the form.
  81. *
  82. * @return array
  83. * The form structure.
  84. */
  85. public function buildForm(array &$form_state);
  86. /**
  87. * Validate the event settings independent from a form submission.
  88. *
  89. * @throws RulesIntegrityException
  90. * In case of validation errors, RulesIntegrityExceptions are thrown.
  91. */
  92. public function validate();
  93. /**
  94. * Extract the form values and update the event settings.
  95. *
  96. * @param array $form
  97. * An associative array containing the structure of the form.
  98. * @param array $form_state
  99. * An associative array containing the current state of the form.
  100. */
  101. public function extractFormValues(array &$form, array &$form_state);
  102. /**
  103. * Returns the suffix to be added to the base event named based upon settings.
  104. *
  105. * If event settings are used, the event name Rules uses for the configured
  106. * event is {EVENT_NAME}--{SUFFIX}.
  107. *
  108. * @return string
  109. * The suffix string. Return an empty string for not appending a suffix.
  110. */
  111. public function getEventNameSuffix();
  112. /**
  113. * Returns info about the variables provided by this event.
  114. *
  115. * @return array
  116. * An array of provided variables, keyed by variable names and with the
  117. * variable info array as value.
  118. */
  119. public function availableVariables();
  120. /**
  121. * Returns the base name of the event the event handler belongs to.
  122. *
  123. * @return string
  124. * The name of the event the event handler belongs to.
  125. */
  126. public function getEventName();
  127. /**
  128. * Returns the info array of the event the event handler belongs to.
  129. *
  130. * @return string
  131. * The info array of the event the event handler belongs to.
  132. */
  133. public function getEventInfo();
  134. }
  135. /**
  136. * Interface for event dispatchers.
  137. */
  138. interface RulesEventDispatcherInterface extends RulesEventHandlerInterface {
  139. /**
  140. * Starts the event watcher.
  141. */
  142. public function startWatching();
  143. /**
  144. * Stops the event watcher.
  145. */
  146. public function stopWatching();
  147. /**
  148. * Returns whether the event dispatcher is currently active.
  149. *
  150. * @return bool
  151. * TRUE if the event dispatcher is currently active, FALSE otherwise.
  152. */
  153. public function isWatching();
  154. }
  155. /**
  156. * Base class for event handler.
  157. */
  158. abstract class RulesEventHandlerBase implements RulesEventHandlerInterface {
  159. /**
  160. * The event name.
  161. *
  162. * @var string
  163. */
  164. protected $eventName;
  165. /**
  166. * The event info.
  167. *
  168. * @var array
  169. */
  170. protected $eventInfo;
  171. /**
  172. * The event settings.
  173. *
  174. * @var array
  175. */
  176. protected $settings = array();
  177. /**
  178. * Implements RulesEventHandlerInterface::__construct()
  179. */
  180. public function __construct($event_name, $info) {
  181. $this->eventName = $event_name;
  182. $this->eventInfo = $info;
  183. $this->settings = $this->getDefaults();
  184. }
  185. /**
  186. * Implements RulesEventHandlerInterface::getSettings()
  187. */
  188. public function getSettings() {
  189. return $this->settings;
  190. }
  191. /**
  192. * Implements RulesEventHandlerInterface::setSettings()
  193. */
  194. public function setSettings(array $settings) {
  195. $this->settings = $settings + $this->getDefaults();
  196. return $this;
  197. }
  198. /**
  199. * Implements RulesEventHandlerInterface::validate()
  200. */
  201. public function validate() {
  202. // Nothing to check by default.
  203. }
  204. /**
  205. * Implements RulesEventHandlerInterface::extractFormValues()
  206. */
  207. public function extractFormValues(array &$form, array &$form_state) {
  208. foreach ($this->getDefaults() as $key => $setting) {
  209. $this->settings[$key] = isset($form_state['values'][$key]) ? $form_state['values'][$key] : $setting;
  210. }
  211. }
  212. /**
  213. * Implements RulesEventHandlerInterface::availableVariables()
  214. */
  215. public function availableVariables() {
  216. return isset($this->eventInfo['variables']) ? $this->eventInfo['variables'] : array();
  217. }
  218. /**
  219. * Implements RulesEventHandlerInterface::getEventName()
  220. */
  221. public function getEventName() {
  222. return $this->eventName;
  223. }
  224. /**
  225. * Implements RulesEventHandlerInterface::getEventInfo()
  226. */
  227. public function getEventInfo() {
  228. return $this->eventInfo;
  229. }
  230. }
  231. /**
  232. * A handler for events having no settings. This is the default handler.
  233. */
  234. class RulesEventDefaultHandler extends RulesEventHandlerBase {
  235. /**
  236. * Implements RulesEventHandlerInterface::buildForm()
  237. */
  238. public function buildForm(array &$form_state) {
  239. return array();
  240. }
  241. /**
  242. * Implements RulesEventHandlerInterface::getConfiguredEventName()
  243. */
  244. public function getEventNameSuffix() {
  245. return '';
  246. }
  247. /**
  248. * Implements RulesEventHandlerInterface::summary()
  249. */
  250. public function summary() {
  251. return check_plain($this->eventInfo['label']);
  252. }
  253. /**
  254. * Implements RulesEventHandlerInterface::getDefaults()
  255. */
  256. public function getDefaults() {
  257. return array();
  258. }
  259. /**
  260. * Implements RulesEventHandlerInterface::getSettings()
  261. */
  262. public function getSettings() {
  263. return NULL;
  264. }
  265. }
  266. /**
  267. * Exposes the bundle of an entity as event setting.
  268. */
  269. class RulesEventHandlerEntityBundle extends RulesEventHandlerBase {
  270. protected $entityType, $entityInfo, $bundleKey;
  271. /**
  272. * Implements RulesEventHandlerInterface::__construct()
  273. */
  274. public function __construct($event_name, $info) {
  275. parent::__construct($event_name, $info);
  276. // Cut off the suffix, e.g. remove 'view' from node_view.
  277. $this->entityType = implode('_', explode('_', $event_name, -1));
  278. $this->entityInfo = entity_get_info($this->entityType);
  279. if (!$this->entityInfo) {
  280. throw new InvalidArgumentException('Unsupported event name passed.');
  281. }
  282. }
  283. /**
  284. * Implements RulesEventHandlerInterface::summary()
  285. */
  286. public function summary() {
  287. $bundle = &$this->settings['bundle'];
  288. $bundle_label = isset($this->entityInfo['bundles'][$bundle]['label']) ? $this->entityInfo['bundles'][$bundle]['label'] : $bundle;
  289. $suffix = isset($bundle) ? ' ' . t('of @bundle-key %name', array('@bundle-key' => $this->getBundlePropertyLabel(), '%name' => $bundle_label)) : '';
  290. return check_plain($this->eventInfo['label']) . $suffix;
  291. }
  292. /**
  293. * Implements RulesEventHandlerInterface::buildForm()
  294. */
  295. public function buildForm(array &$form_state) {
  296. $form['bundle'] = array(
  297. '#type' => 'select',
  298. '#title' => t('Restrict by @bundle', array('@bundle' => $this->getBundlePropertyLabel())),
  299. '#description' => t('If you need to filter for multiple values, either add multiple events or use the "Entity is of bundle" condition instead.'),
  300. '#default_value' => $this->settings['bundle'],
  301. '#empty_value' => '',
  302. );
  303. foreach ($this->entityInfo['bundles'] as $name => $bundle_info) {
  304. $form['bundle']['#options'][$name] = $bundle_info['label'];
  305. }
  306. return $form;
  307. }
  308. /**
  309. * Returns the label to use for the bundle property.
  310. *
  311. * @return string
  312. */
  313. protected function getBundlePropertyLabel() {
  314. return $this->entityInfo['entity keys']['bundle'];
  315. }
  316. /**
  317. * Implements RulesEventHandlerInterface::extractFormValues()
  318. */
  319. public function extractFormValues(array &$form, array &$form_state) {
  320. $this->settings['bundle'] = !empty($form_state['values']['bundle']) ? $form_state['values']['bundle'] : NULL;
  321. }
  322. /**
  323. * Implements RulesEventHandlerInterface::validate()
  324. */
  325. public function validate() {
  326. if ($this->settings['bundle'] && empty($this->entityInfo['bundles'][$this->settings['bundle']])) {
  327. throw new RulesIntegrityException(t('The @bundle %bundle of %entity_type is not known.',
  328. array(
  329. '%bundle' => $this->settings['bundle'],
  330. '%entity_type' => $this->entityInfo['label'],
  331. '@bundle' => $this->getBundlePropertyLabel(),
  332. )), array(NULL, 'bundle'));
  333. }
  334. }
  335. /**
  336. * Implements RulesEventHandlerInterface::getConfiguredEventName()
  337. */
  338. public function getEventNameSuffix() {
  339. return $this->settings['bundle'];
  340. }
  341. /**
  342. * Implements RulesEventHandlerInterface::getDefaults()
  343. */
  344. public function getDefaults() {
  345. return array(
  346. 'bundle' => NULL,
  347. );
  348. }
  349. /**
  350. * Implements RulesEventHandlerInterface::availableVariables()
  351. */
  352. public function availableVariables() {
  353. $variables = $this->eventInfo['variables'];
  354. if ($this->settings['bundle']) {
  355. // Add the bundle to all variables of the entity type.
  356. foreach ($variables as $name => $variable_info) {
  357. if ($variable_info['type'] == $this->entityType) {
  358. $variables[$name]['bundle'] = $this->settings['bundle'];
  359. }
  360. }
  361. }
  362. return $variables;
  363. }
  364. }