business_rules.module in Business Rules 2.x
Same filename and directory in other branches
Business Rules module.
File
business_rules.moduleView source
<?php
/**
* @file
* Business Rules module.
*/
use Drupal\business_rules\Entity\Schedule;
use Drupal\business_rules\Events\BusinessRulesEvent;
use Drupal\Core\Entity\Display\EntityFormDisplayInterface;
use Drupal\Core\Entity\Display\EntityViewDisplayInterface;
use Drupal\Core\Entity\EntityFormInterface;
use Drupal\Core\Entity\EntityInterface;
use Drupal\Core\Field\Plugin\Field\FieldWidget\EntityReferenceAutocompleteWidget;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Link;
use Drupal\Core\Routing\RouteMatchInterface;
use Drupal\Core\Url;
use Drupal\quickedit\Form\QuickEditFieldForm;
use Drupal\user\Entity\User;
use Drupal\Core\Field\EntityReferenceFieldItemListInterface;
/**
* Implements hook_help().
*/
function business_rules_help($route_name, RouteMatchInterface $route_match) {
switch ($route_name) {
// Main module help for the business_rules module.
case 'help.page.business_rules':
$output = '';
$output .= '<h3>' . t('About') . '</h3>';
$output .= '<p>' . t('Business Rules') . '</p>';
$output .= '<p>' . Link::fromTextAndUrl(t('Click here to access the online Business Rules documentation.'), Url::fromUri('https://www.drupal.org/docs/8/modules/business-rules'))
->toString() . '</p>';
return $output;
default:
}
}
/**
* Implements hook_entity_presave().
*/
function business_rules_entity_presave(EntityInterface $entity) {
// Only handle content entities and ignore config entities.
if (\Drupal::service('business_rules.processor')
->ruleExists('entity_presave', $entity)) {
$reacts_on_definition = \Drupal::getContainer()
->get('plugin.manager.business_rules.reacts_on')
->getDefinition('entity_presave');
$entity_type_id = $entity
->getEntityTypeId();
$event = new BusinessRulesEvent($entity, [
'entity_type_id' => $entity_type_id,
'bundle' => $entity
->bundle(),
'entity' => $entity,
'entity_unchanged' => $entity->original,
'reacts_on' => $reacts_on_definition,
'loop_control' => $entity
->getEntityTypeId() . $entity
->id(),
]);
/** @var \Symfony\Component\EventDispatcher\EventDispatcherInterface $event_dispatcher */
$event_dispatcher = \Drupal::service('event_dispatcher');
$event_dispatcher
->dispatch($reacts_on_definition['eventName'], $event);
}
}
/**
* Implements hook_entity_update().
*/
function business_rules_entity_update(EntityInterface $entity) {
// Only handle content entities and ignore config entities.
if (\Drupal::service('business_rules.processor')
->ruleExists('entity_update', $entity)) {
$reacts_on_definition = \Drupal::getContainer()
->get('plugin.manager.business_rules.reacts_on')
->getDefinition('entity_update');
$entity_type_id = $entity
->getEntityTypeId();
$event = new BusinessRulesEvent($entity, [
'entity_type_id' => $entity_type_id,
'bundle' => $entity
->bundle(),
'entity' => $entity,
'entity_unchanged' => $entity->original,
'reacts_on' => $reacts_on_definition,
'loop_control' => $entity
->getEntityTypeId() . $entity
->id(),
]);
/** @var \Symfony\Component\EventDispatcher\EventDispatcherInterface $event_dispatcher */
$event_dispatcher = \Drupal::service('event_dispatcher');
$event_dispatcher
->dispatch($reacts_on_definition['eventName'], $event);
}
}
/**
* Implements hook_entity_insert().
*/
function business_rules_entity_insert(EntityInterface $entity) {
// Only handle content entities and ignore config entities.
if (\Drupal::service('business_rules.processor')
->ruleExists('entity_insert', $entity)) {
$reacts_on_definition = \Drupal::getContainer()
->get('plugin.manager.business_rules.reacts_on')
->getDefinition('entity_insert');
$entity_type_id = $entity
->getEntityTypeId();
$event = new BusinessRulesEvent($entity, [
'entity_type_id' => $entity_type_id,
'bundle' => $entity
->bundle(),
'entity' => $entity,
'entity_unchanged' => $entity->original,
'reacts_on' => $reacts_on_definition,
'loop_control' => $entity
->getEntityTypeId() . $entity
->id(),
]);
/** @var \Symfony\Component\EventDispatcher\EventDispatcherInterface $event_dispatcher */
$event_dispatcher = \Drupal::service('event_dispatcher');
$event_dispatcher
->dispatch($reacts_on_definition['eventName'], $event);
}
}
/**
* Implements hook_entity_delete().
*/
function business_rules_entity_delete(EntityInterface $entity) {
// Only handle content entities and ignore config entities.
if (\Drupal::service('business_rules.processor')
->ruleExists('entity_delete', $entity)) {
$reacts_on_definition = \Drupal::getContainer()
->get('plugin.manager.business_rules.reacts_on')
->getDefinition('entity_delete');
$entity_type_id = $entity
->getEntityTypeId();
$event = new BusinessRulesEvent($entity, [
'entity_type_id' => $entity_type_id,
'bundle' => $entity
->bundle(),
'entity' => $entity,
'entity_unchanged' => $entity->original,
'reacts_on' => $reacts_on_definition,
'loop_control' => $entity
->getEntityTypeId() . $entity
->id(),
]);
/** @var \Symfony\Component\EventDispatcher\EventDispatcherInterface $event_dispatcher */
$event_dispatcher = \Drupal::service('event_dispatcher');
$event_dispatcher
->dispatch($reacts_on_definition['eventName'], $event);
}
}
/**
* Implements hook_form_alter().
*/
function business_rules_form_alter(&$form, FormStateInterface $form_state, $form_id) {
$request_object = \Drupal::request();
if (method_exists($form_state
->getFormObject(), 'getEntity') && !$form_state
->isCached() && (!$request_object->query
->has('ajax_form') || $request_object->query
->get('ajax_form') != 1) && (!$request_object->query
->has('_wrapper_format') || $request_object->query
->get('_wrapper_format') != 'drupal_ajax')) {
$entity = $form_state
->getFormObject()
->getEntity();
if (\Drupal::service('business_rules.processor')
->ruleExists('form_validation', $entity)) {
// Prepare the event for formValidation.
$form_validation_reacts_on_definition = \Drupal::getContainer()
->get('plugin.manager.business_rules.reacts_on')
->getDefinition('form_validation');
$form_validation_event = new BusinessRulesEvent($entity, [
'form_id' => $form_id,
'form_state' => $form_state,
'form' => $form,
'entity_type_id' => $entity
->getEntityTypeId(),
'bundle' => $entity
->bundle(),
'entity' => $entity,
'entity_unchanged' => $entity->original,
'reacts_on' => $form_validation_reacts_on_definition,
'loop_control' => $entity
->getEntityTypeId() . $entity
->id(),
]);
$form_state
->set('business_rules_event', $form_validation_event);
// We can't dispatch this event here, otherwise it would be processed
// before the form validation. In this case, the FormValidator will take
// care of the event process and we are just adding this validation.
$form['#validate'][] = 'Drupal\\business_rules\\Plugin\\BusinessRulesReactsOn\\FormValidation::validateForm';
}
}
}
/**
* Implements hook_field_widget_form_alter().
*/
function business_rules_field_widget_form_alter(&$element, FormStateInterface $form_state, $context) {
// @todo check patch inline_entity_form_2973571_1.patch.
$form_object = $form_state
->getFormObject();
// Establish whether we're in a normal EntityForm context or an inline
// QuickeditFieldForm context and retrieve the entity from the respectively
// appropriate place.
if (isset($context['items']) && $context['items'] instanceof EntityReferenceFieldItemListInterface) {
/**
* @var \Drupal\Core\Field\EntityReferenceFieldItemListInterface $items
*/
$items = $context['items'];
$entity = $items
->getEntity();
}
elseif ($form_object instanceof EntityFormInterface) {
$entity = $form_object
->getEntity();
}
else {
if ($form_object instanceof QuickEditFieldForm) {
$entity = $form_state
->getBuildInfo()['args'][0];
}
else {
$entity = new stdClass();
}
}
if ($entity instanceof EntityInterface) {
// Check if the field is a dependent field.
/** @var \Drupal\Core\Field\FieldItemList $items */
$items = $context['items'];
$current_field = $items
->getFieldDefinition()
->getName();
// Check if field is configured as parent of one dependent field.
if (method_exists($entity, 'getFieldDefinitions')) {
$fields_definitions = $entity
->getFieldDefinitions();
$parent_field = NULL;
// Check if current field has children.
$child_fields = [];
foreach ($fields_definitions as $field_name => $field_definition) {
$handler = $field_definition
->getSetting('handler');
if ($handler == 'business_rules_views') {
$handle_settings = $field_definition
->getSetting('handler_settings');
$parent_field = $handle_settings['business_rules_view']['parent_field'];
$has_children = $parent_field == $current_field;
if ($has_children) {
$child_fields[] = $field_name;
}
}
}
// Add ajax to parent field.
if (count($child_fields)) {
$children = isset($element['#ajax']['br_children']) ? $element['#ajax']['br_children'] : [];
$children += $child_fields;
$ajax_definition = [
'callback' => '\\Drupal\\business_rules\\Plugin\\EntityReferenceSelection\\BusinessRulesViewsSelection::updateDependentField',
'event' => 'change',
'progress' => [
'type' => 'throbber',
],
'br_children' => $children,
];
if (!empty($context['widget']) && $context['widget'] instanceof EntityReferenceAutocompleteWidget && !empty($element['target_id'])) {
$ajax_definition['event'] = 'autocompleteclose';
$element['target_id']['#ajax'] = $ajax_definition;
}
else {
$element['#ajax'] = $ajax_definition;
}
$element['#attached']['library'][] = 'business_rules/dependentField';
}
}
// Prepare the event to FormFieldAlter.
$reacts_on_definition = \Drupal::getContainer()
->get('plugin.manager.business_rules.reacts_on')
->getDefinition('form_field_alter');
// Business rules processor needs to process this event every time it's
// called by Drupal. There is no necessity of loop control here. In this
// case we are creating an uuid because there is no risk of infinite loop.
$loop_control = \Drupal::getContainer()
->get('uuid')
->generate();
$event = new BusinessRulesEvent($element, [
'form_state' => $form_state,
'element' => $element,
'context' => $context,
'entity_type_id' => $entity
->getEntityTypeId(),
'bundle' => $entity
->bundle(),
'entity' => $entity,
'entity_unchanged' => property_exists($entity, 'original') ? $entity->original : $entity,
'reacts_on' => $reacts_on_definition,
'loop_control' => $loop_control,
]);
/** @var \Symfony\Component\EventDispatcher\EventDispatcherInterface $event_dispatcher */
$event_dispatcher = \Drupal::service('event_dispatcher');
$event_dispatcher
->dispatch($reacts_on_definition['eventName'], $event);
// Now we need to replace the current element by the changed one.
$element = $event
->getArgument('element');
}
}
/**
* Implements hook_entity_view().
*/
function business_rules_entity_view(array &$build, EntityInterface $entity, EntityViewDisplayInterface $display, $view_mode) {
// Only handle content entities and ignore config entities.
if (\Drupal::service('business_rules.processor')
->ruleExists('entity_is_viewed', $entity)) {
$reacts_on_definition = \Drupal::getContainer()
->get('plugin.manager.business_rules.reacts_on')
->getDefinition('entity_is_viewed');
$entity_type_id = $entity
->getEntityTypeId();
$event = new BusinessRulesEvent($entity, [
'entity_type_id' => $entity_type_id,
'bundle' => $entity
->bundle(),
'entity' => $entity,
'entity_unchanged' => $entity->original,
'build' => &$build,
'reacts_on' => $reacts_on_definition,
'loop_control' => $entity
->getEntityTypeId() . $entity
->id(),
]);
/** @var \Symfony\Component\EventDispatcher\EventDispatcherInterface $event_dispatcher */
$event_dispatcher = \Drupal::service('event_dispatcher');
$event_dispatcher
->dispatch($reacts_on_definition['eventName'], $event);
}
}
/**
* Implements hook_entity_load().
*/
function business_rules_entity_load(array $entities, $entity_type_id) {
foreach ($entities as $entity) {
if (\Drupal::service('business_rules.processor')
->ruleExists('entity_is_loaded', $entity)) {
$reacts_on_definition = \Drupal::getContainer()
->get('plugin.manager.business_rules.reacts_on')
->getDefinition('entity_is_loaded');
$entity_type_id = $entity
->getEntityTypeId();
$event = new BusinessRulesEvent($entity, [
'entity_type_id' => $entity_type_id,
'bundle' => $entity
->bundle(),
'entity' => $entity,
'entity_unchanged' => $entity->original,
'reacts_on' => $reacts_on_definition,
'loop_control' => $entity
->getEntityTypeId() . $entity
->id(),
]);
/** @var \Symfony\Component\EventDispatcher\EventDispatcherInterface $event_dispatcher */
$event_dispatcher = \Drupal::service('event_dispatcher');
$event_dispatcher
->dispatch($reacts_on_definition['eventName'], $event);
}
}
}
/**
* Implements hook_user_login().
*/
function business_rules_user_login($account) {
$entity = $account;
if (\Drupal::service('business_rules.processor')
->ruleExists('user_login', $entity)) {
$reacts_on_definition = \Drupal::getContainer()
->get('plugin.manager.business_rules.reacts_on')
->getDefinition('user_login');
$entity_type_id = $account
->getEntityTypeId();
$event = new BusinessRulesEvent($entity, [
'entity_type_id' => $entity_type_id,
'bundle' => $entity
->bundle(),
'entity' => $entity,
'entity_unchanged' => NULL,
'reacts_on' => $reacts_on_definition,
'loop_control' => $entity
->getEntityTypeId() . $entity
->id(),
]);
/** @var \Symfony\Component\EventDispatcher\EventDispatcherInterface $event_dispatcher */
$event_dispatcher = \Drupal::service('event_dispatcher');
$event_dispatcher
->dispatch($reacts_on_definition['eventName'], $event);
}
}
/**
* Implements hook_user_logout().
*/
function business_rules_user_logout($account) {
$entity = User::load($account
->id());
if (\Drupal::service('business_rules.processor')
->ruleExists('user_logout', $entity)) {
$reacts_on_definition = \Drupal::getContainer()
->get('plugin.manager.business_rules.reacts_on')
->getDefinition('user_logout');
if (method_exists($account, 'getAccount')) {
$account = $account
->getAccount();
}
$entity_type_id = $entity
->getEntityTypeId();
$event = new BusinessRulesEvent($entity, [
'entity_type_id' => $entity_type_id,
'bundle' => $entity
->bundle(),
'entity' => $entity,
'entity_unchanged' => NULL,
'reacts_on' => $reacts_on_definition,
'loop_control' => $entity
->getEntityTypeId() . $entity
->id(),
]);
/** @var \Symfony\Component\EventDispatcher\EventDispatcherInterface $event_dispatcher */
$event_dispatcher = \Drupal::service('event_dispatcher');
$event_dispatcher
->dispatch($reacts_on_definition['eventName'], $event);
}
}
/**
* Implements hook_cache_flush().
*/
function business_rules_cache_flush() {
$key_value = \Drupal::keyValueExpirable('business_rules.debug');
$key_value
->deleteAll();
$key_value = \Drupal::keyValueExpirable('business_rules.token_tree');
$key_value
->deleteAll();
}
/**
* Implements hook_mail().
*/
function business_rules_mail($key, &$message, $params) {
if ($key === 'business_rules_mail') {
$message['headers'] = array_merge($message['headers'], $params['headers']);
$message['subject'] = $params['subject'];
$message['body'][] = $params['message'];
}
}
/**
* Page load event dispatcher.
*/
function business_rules_page_load_event() {
if (Drupal::hasContainer()) {
$reacts_on_definition = \Drupal::getContainer()
->get('plugin.manager.business_rules.reacts_on')
->getDefinition('page_load');
$path = $_SERVER['REQUEST_URI'];
$event = new BusinessRulesEvent($path, [
'entity_type_id' => '',
'bundle' => NULL,
'entity' => NULL,
'entity_unchanged' => NULL,
'reacts_on' => $reacts_on_definition,
'loop_control' => $path,
]);
$event_dispatcher = \Drupal::service('event_dispatcher');
$event_dispatcher
->dispatch($reacts_on_definition['eventName'], $event);
}
}
/**
* Implements hook_page_top().
*/
function business_rules_page_top(array &$page_top) {
business_rules_page_load_event();
}
/**
* Implements hook_cron().
*/
function business_rules_cron() {
if (Drupal::hasContainer()) {
// Dispatch the cron runs business rules items.
$reacts_on_definition = \Drupal::getContainer()
->get('plugin.manager.business_rules.reacts_on')
->getDefinition('cron_runs');
$loop_control = time();
$dummy = new stdClass();
$event = new BusinessRulesEvent($dummy, [
'entity_type_id' => '',
'bundle' => NULL,
'entity' => NULL,
'entity_unchanged' => NULL,
'reacts_on' => $reacts_on_definition,
'loop_control' => $loop_control,
]);
$event_dispatcher = \Drupal::service('event_dispatcher');
$event_dispatcher
->dispatch($reacts_on_definition['eventName'], $event);
// Dispatch the scheduled items.
Schedule::executeSchedule($event);
}
}
/**
* Implements hook_entity_type_alter().
*/
function business_rules_entity_type_alter(array &$entity_types) {
$form_modes = \Drupal::service('entity_display.repository')
->getAllFormModes();
$skip_names = [
'register',
'add_to_cart',
];
foreach ($form_modes as $entity_type => $display_modes) {
$type = $entity_types[$entity_type];
foreach ($display_modes as $machine_name => $form_display) {
if (!in_array($machine_name, $skip_names) && isset($type
->getHandlerClasses()['form']['default'])) {
$default_handler_class = $type
->getHandlerClasses()['form']['default'];
$type
->setFormClass($machine_name, $default_handler_class);
}
}
}
}
/**
* Implements hook_entity_form_display_alter().
*
* The trick here is to pass the $form_display as a reference.
*/
function business_rules_entity_form_display_alter(EntityFormDisplayInterface &$form_display, array $context) {
$reacts_on_definition = \Drupal::getContainer()
->get('plugin.manager.business_rules.reacts_on')
->getDefinition('form_display_mode_alter');
$loop_control = $form_display
->id();
$event = new BusinessRulesEvent($form_display, [
'entity_type_id' => $context['entity_type'],
'bundle' => $context['bundle'],
'reacts_on' => $reacts_on_definition,
'loop_control' => $loop_control,
'form_display' => NULL,
]);
/** @var \Symfony\Component\EventDispatcher\EventDispatcherInterface $event_dispatcher */
$event_dispatcher = \Drupal::service('event_dispatcher');
$event_dispatcher
->dispatch($reacts_on_definition['eventName'], $event);
$new_form_display = $event
->getArgument('form_display');
if ($new_form_display instanceof EntityFormDisplayInterface) {
$form_display = $new_form_display;
}
}