123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569 |
- <?php
- /**
- * @file
- * Rules Link - module file.
- */
- /**
- * Implements hook_entity_info().
- */
- function rules_link_entity_info() {
- return array(
- 'rules_link' => array(
- 'label' => t('Rules Link'),
- 'entity class' => 'RulesLink',
- 'controller class' => 'EntityAPIControllerExportable',
- 'base table' => 'rules_link',
- 'fieldable' => TRUE,
- 'entity keys' => array(
- 'id' => 'id',
- 'name' => 'name',
- 'label' => 'label',
- ),
- 'exportable' => TRUE,
- 'module' => 'rules_link',
- 'access callback' => 'rules_link_access',
- // Enable the entity API's admin UI.
- 'admin ui' => array(
- 'path' => 'admin/config/workflow/rules_links',
- 'file' => 'rules_link.admin.inc',
- 'controller class' => 'RulesLinkUIController',
- ),
- ),
- );
- }
- /**
- * Access callback for the entity API.
- */
- function rules_link_access($op, $type = NULL, $account = NULL) {
- return user_access('administer rules links', $account);
- }
- /**
- * Menu argument loader; Load a rules link by string.
- *
- * @param $name
- * The machine-readable name of a rules link to load.
- * @return
- * A rules link array or FALSE if $name does not exist.
- */
- function rules_link_load($name) {
- return rules_link_get_links($name);
- }
- /**
- * Implements hook_permission().
- */
- function rules_link_permission() {
- $permissions = array(
- 'administer rules links' => array(
- 'title' => t('Administer rules links'),
- 'description' => t('Create and delete rules links and set their permissions.'),
- ),
- );
- foreach (rules_link_get_links() as $link) {
- $name = check_plain($link->name);
- $permissions += array(
- "access rules link $name" => array(
- 'title' => t('%link_label: Execute rules link', array('%link_label' => $link->label)),
- ),
- );
- }
- return $permissions;
- }
- /**
- * Gets an array of all rules links, keyed by the type name.
- *
- * @param $link_names
- * If set, the function will return the link with the given name.
- * @return RuleLinks[]
- * Depending on isset $link_names, a name single or an array of rules links.
- */
- function rules_link_get_links($link_names = NULL) {
- $links = entity_load_multiple_by_name('rules_link', isset($link_names) ? array($link_names) : FALSE);
- return isset($link_names) ? reset($links) : $links;
- }
- /**
- * Returns the name condition set to a rules link.
- */
- function rules_link_get_condition_set_name($rules_link) {
- return 'rules_link_condition_' . $rules_link->name;
- }
- /**
- * Returns the name condition set to a rules link.
- */
- function rules_link_get_rules_set_name($rules_link) {
- return 'rules_link_set_' . $rules_link->name;
- }
- /**
- * Loads and returns the condition to a link. If it
- * doesn't exist, a new one will be created.
- *
- * @param $rules_link
- * The rules link to which the condition should be loaded.
- */
- function rules_link_load_condition_set($rules_link) {
- $condition_set = rules_config_load(rules_link_get_condition_set_name($rules_link));
- if ($condition_set != FALSE) {
- return $condition_set;
- }
- else {
- $conditions = rules_and(array(
- $rules_link->entity_type => array('type' => $rules_link->entity_type, 'label' => $rules_link->entity_type),
- ));
- $conditions->label = 'Rules link: ' . $rules_link->label . ' condition';
- $conditions->save(rules_link_get_condition_set_name($rules_link), 'rules_link');
- return $conditions;
- }
- }
- /**
- * Loads and returns the rules set to a link. If it
- * doesn't exist, a new one will be created.
- *
- * @param $rules_link
- * The rules link to which the condition or rules set should be loaded.
- */
- function rules_link_load_rules_set($rules_link) {
- $rule_set = rules_config_load(rules_link_get_rules_set_name($rules_link));
- if ($rule_set != FALSE) {
- return $rule_set;
- }
- else {
- $rule_set = rules_rule_set(array(
- $rules_link->entity_type => array('type' => $rules_link->entity_type, 'label' => $rules_link->entity_type),
- ));
- $rule_set->label = 'Rules link: ' . $rules_link->label . ' rules set';
- $rule_set->save(rules_link_get_rules_set_name($rules_link), 'rules_link');
- return $rule_set;
- }
- }
- /**
- * Renders a link using the name of the rules_link and the entity id.
- *
- * @param $rules_link_name
- * The name the link which should be rendered.
- * @param $entity_id
- * The entity id of entity on which the rule should be triggered.
- * @param $destination
- * The destination to which the Rules Module should redirect the user after
- * triggering the link.
- * @param $parameters
- * Additional parameters for the Rules components of the link.
- *
- * @return
- * A renderable array.
- */
- function rules_link_render($rules_link_name, $entity_id, $destination = NULL, $parameters = array()) {
- $rules_link = rules_link_load($rules_link_name);
- return rules_link_render_link($rules_link, $entity_id, $destination, $parameters);
- }
- /**
- * Renders a link.
- *
- * @param $rules_link
- * The link which should be rendered.
- * @param $entity_id
- * The entity id of entity on which the rule should be triggered.
- * @param $destination
- * The destination to which the Rules Module should redirect the user after
- * triggering the link.
- * @param $parameters
- * Additional parameters for the Rules components of the link.
- *
- * @return
- * A renderable array.
- */
- function rules_link_render_link($rules_link, $entity_id, $destination = NULL, $parameters = array()) {
- if (rules_link_check_visibility($rules_link, array_merge(array($entity_id), $parameters))) {
- $path = $rules_link->path . '/' . $entity_id;
- if (count($parameters) > 0) {
- $path .= '/' . implode('/', $parameters);
- }
- $path .= $rules_link->settings['link_type'] == 'confirm' ? '' : '/' . rules_link_get_token($entity_id);
- $link = array(
- '#title' => $rules_link->getSettingTranslation('text'),
- '#href' => $path,
- '#attr' => array('class' => array('rules-link'), 'rel' => 'nofollow'),
- '#rules_link' => $rules_link,
- '#theme' => 'rules_link',
- );
- if ($rules_link->settings['link_type'] == 'javascript') {
- $link['#attr']['class'][] = 'rules-link-js';
- drupal_add_js(drupal_get_path('module', 'rules_link') . '/rules_link.js', 'file');
- drupal_add_css(drupal_get_path('module', 'rules_link') . '/rules_link.css', 'file');
- }
- else {
- $link['#options'] = array('query' => $destination);
- }
- return $link;
- }
- return array();
- }
- /**
- * Trims a whitespaces from a parameter.
- */
- function rules_link_trim_parameters(&$value) {
- $value = trim($value);
- }
- /**
- * Custom Entity class.
- */
- class RulesLink extends Entity {
- public $settings = array();
- public function __construct($values = array()) {
- parent::__construct($values, 'rules_link');
- }
- /**
- * Gets the i18n translation of a setting.
- *
- * @param $name
- * The setting name.
- * @param $langcode
- * The optional language code. Defaults to the current display language.
- *
- * @see Entity::getTranslation()
- */
- public function getSettingTranslation($name, $langcode = NULL) {
- $value = isset($this->settings[$name]) ? $this->settings[$name] : NULL;
- $i18n_name = 'rules_link:rules_link:' . $this->identifier() . ':' . $name;
- return entity_i18n_string($i18n_name, $value, $langcode);
- }
- }
- /**
- * Implements hook_rules_link_insert().
- */
- function rules_link_rules_link_insert($link) {
- // Do not directly issue menu rebuilds here to avoid potentially multiple
- // rebuilds. Instead, let menu_get_item() issue the rebuild on the next page.
- variable_set('menu_rebuild_needed', TRUE);
- }
- /**
- * Implements hook_rules_link_update().
- */
- function rules_link_rules_link_update($link) {
- // Make sure to only issue menu rebuilds if necessary.
- // @see rules_link_rules_link_insert()
- if (!empty($link->original) && ($link->path != $link->original->path || $link->settings['link_type'] != $link->original->settings['link_type'])) {
- variable_set('menu_rebuild_needed', TRUE);
- }
- }
- /**
- * Implements hook_rules_link_delete().
- */
- function rules_link_rules_link_delete($link) {
- // @see rules_link_rules_link_insert()
- variable_set('menu_rebuild_needed', TRUE);
- // Delete associate rule configs.
- rules_link_load_condition_set($link)->delete();
- rules_link_load_rules_set($link)->delete();
- }
- /**
- * Generates a token used to protect links from spoofing.
- */
- function rules_link_get_token($content_id) {
- // Anonymous users get a less secure token, since it must be the same for all
- // anonymous users on the entire site to work with page caching.
- return ($GLOBALS['user']->uid) ? drupal_get_token($content_id) : drupal_hmac_base64($content_id, drupal_get_private_key() . drupal_get_hash_salt());
- }
- /**
- * Checks if the given token is correct.
- */
- function rules_link_check_token($token, $content_id) {
- return rules_link_get_token($content_id) === $token;
- }
- function rules_link_get_paramters($rules_link) {
- $args = arg();
- // Remove the first arguments, that represent the url of the link.
- $path_args = explode('/', $rules_link->path);
- $args = array_slice($args, count($path_args));
- return $args;
- }
- function rules_link_invoke_component($name, $args) {
- if ($component = rules_get_cache('comp_' . $name)) {
- return $component->executeByArgs($args);
- }
- }
- function rules_link_check_visibility($rules_link, $args) {
- $rule_set = rules_link_load_rules_set($rules_link);
- $paramInfo = $rule_set->parameterInfo();
- return count($args) >= count($paramInfo) && user_access("access rules link " . $rules_link->name) && rules_link_invoke_component(rules_link_get_condition_set_name($rules_link), $args);
- }
- /**
- * Triggers a rule set from a rules link.
- */
- function rules_link_trigger($rules_link, $entity_id) {
- rules_link_invoke_component(rules_link_get_rules_set_name($rules_link), rules_link_get_paramters($rules_link));
- }
- /**
- * Menu callback for javascript links.
- */
- function rules_link_trigger_js($rules_link, $entity_id) {
- rules_link_trigger($rules_link, $entity_id);
- $json = array(
- 'message' => drupal_get_messages(),
- );
- drupal_json_output($json);
- }
- /**
- * Menu callback for token links.
- */
- function rules_link_trigger_token($rules_link, $entity_id) {
- rules_link_trigger($rules_link, $entity_id);
- drupal_goto();
- }
- /**
- * Form generator for the menu callback for the confirm form links.
- */
- function rules_link_trigger_form($form, &$form_state, $rules_link, $entity_id) {
- $form['link'] = array(
- '#type' => 'hidden',
- '#value' => $rules_link->name,
- );
- $form['entity_id'] = array(
- '#type' => 'hidden',
- '#value' => $entity_id,
- );
- return confirm_form($form, filter_xss_admin($rules_link->getSettingTranslation('confirm_question')), '', filter_xss_admin($rules_link->getSettingTranslation('confirm_description')));
- }
- /**
- * Submit function for the confirm form links.
- */
- function rules_link_trigger_form_submit($form, &$form_state) {
- $rules_link = rules_link_load($form_state['values']['link']);
- rules_link_trigger($rules_link, $form_state['values']['entity_id']);
- }
- /**
- * Access callback function for confirm type links.
- */
- function rules_link_access_link_confirm($rules_link, $entity_id) {
- if (rules_link_check_visibility($rules_link, rules_link_get_paramters($rules_link))) {
- return TRUE;
- }
- return FALSE;
- }
- /**
- * Access callback function for the token and javascript links.
- */
- function rules_link_access_link($rules_link, $entity_id) {
- // The token is always the last element of the argument array.
- $params = rules_link_get_paramters($rules_link);
- $token = array_pop($params);
- return rules_link_check_token($token, $entity_id) && rules_link_access_link_confirm($rules_link, $entity_id);
- }
- /**
- * Implements hook_menu().
- */
- function rules_link_menu() {
- $item = array();
- foreach (rules_link_get_links() as $name => $link) {
- $first_arg = (count(explode('/', $link->path)));
- switch ($link->settings['link_type']) {
- case 'javascript':
- $item[$link->path . '/%/%'] = array(
- 'page callback' => 'rules_link_trigger_js',
- 'page arguments' => array($link, $first_arg),
- 'access arguments' => array($link, $first_arg, $first_arg + 1),
- 'access callback' => 'rules_link_access_link',
- 'type' => MENU_CALLBACK,
- );
- break;
- case 'token':
- $item[$link->path . '/%/%'] = array(
- 'page callback' => 'rules_link_trigger_token',
- 'page arguments' => array($link, $first_arg),
- 'access arguments' => array($link, $first_arg, $first_arg + 1),
- 'access callback' => 'rules_link_access_link',
- 'type' => MENU_CALLBACK,
- );
- break;
- case 'confirm':
- $item[$link->path . '/%'] = array(
- 'page callback' => 'drupal_get_form',
- 'page arguments' => array('rules_link_trigger_form', $link, $first_arg),
- 'access arguments' => array($link, $first_arg),
- 'access callback' => 'rules_link_access_link_confirm',
- 'type' => MENU_CALLBACK,
- );
- break;
- }
- }
- return $item;
- }
- /**
- * Implements hook_theme().
- */
- function rules_link_theme() {
- return array(
- 'rules_link' => array(
- 'template' => 'rules-link',
- 'variables' => array('title' => NULL, 'href' => NULL, 'attr' => NULL, 'options' => NULL, 'rules_link' => NULL),
- 'pattern' => 'rules-link__',
- ),
- );
- }
- /**
- * Implements hook_theme_registry_alter().
- */
- function rules_link_theme_registry_alter(&$theme_registry) {
- // Override the base hook so that we do not overlay with the default entity
- // theme hook defined in entity_theme().
- // Directly changing this setting in rules_link_theme() did not work.
- $theme_registry['rules_link']['base hook'] = 'rules_link';
- }
- /**
- * Implements hook_views_api().
- */
- function rules_link_views_api() {
- return array(
- 'api' => '3.0',
- );
- }
- function template_preprocess_rules_link(&$variables) {
- if (!isset($variables['options'])) {
- $variables['options'] = array();
- }
- $variables['options'] += array('html' => FALSE);
- $variables['title'] = ($variables['options']['html'] ? $variables['title'] : check_plain($variables['title']));
- if (isset($options['attr']['title']) && strpos($options['attr']['title'], '<') !== FALSE) {
- $variables['attr']['title'] = strip_tags($options['attr']['title']);
- } else if (!isset($options['attr']['title'])) {
- $variables['attr']['title'] = $variables['title'];
- }
- $variables['href'] = check_plain(url($variables['href'], $variables['options']));
- $variables['attr'] = drupal_attributes($variables['attr']);
- }
- /**
- * Implement hook_entity_view().
- */
- function rules_link_entity_view($entity, $type, $view_mode, $langcode) {
- $links = array();
- $rules_links = rules_link_get_links();
- foreach ($rules_links as $name => $rules_link) {
- if ($rules_link->entity_type == $type && $rules_link->settings['entity_link']) {
- list($id, $rev, $bundle) = entity_extract_ids($type, $entity);
- // If the link is restricted to some bundles, verify the bundle.
- if ($id && (empty($rules_link->settings['bundles']) || in_array($bundle, $rules_link->settings['bundles']))) {
- $renderd_link = rules_link_render_link($rules_link, $id, drupal_get_destination());
- if (!empty($renderd_link)) {
- $links[$name] = drupal_render($renderd_link);
- }
- }
- }
- }
- foreach ($links as $name => $link) {
- $entity->content['rules_links_' . $name] = array(
- '#markup' => $link,
- );
- }
- }
- /**
- * Implements hook_features_pipe_component_alter() for fields.
- */
- function rules_link_features_pipe_rules_link_alter(&$pipe, $data, $export) {
- foreach ($data as $id) {
- $rules_link = entity_load_single('rules_link', $id);
- $pipe['rules_config'][] = rules_link_get_condition_set_name($rules_link);
- $pipe['rules_config'][] = rules_link_get_rules_set_name($rules_link);
- }
- }
- /**
- * Alter the breadcrumb trail of the rules components.
- */
- function rules_link_menu_breadcrumb_alter(&$active_trail, $item) {
- if (substr($item['href'], 22, 34) == 'rules/components/manage/rules_link') {
- // Parse the name out of the link.
- if (substr($item['href'], 57, 3) == 'set') {
- $start = 61;
- }
- elseif (substr($item['href'], 57, 3) == 'con') {
- $start = 67;
- }
- $link_name = substr($item['href'], $start, strlen($item['href']));
- $pos = strpos($link_name, '/') ;
- if ($pos !== FALSE) {
- $link_name = substr($link_name, 0, $pos);
- }
- $rules_link = rules_link_load($link_name);
- if ($rules_link) {
- // Replace the link to Rules with a link to Rules Link.
- $active_trail[4]['title'] = 'Rules Links';
- $active_trail[4]['href'] = 'admin/config/workflow/rules_links';
- $active_trail[4]['options']['attributes']['title'] = 'Manage links that triggers rules.';
- $active_trail[4]['localized_options'] = array();
- // Replace component link with link to the current rules link.
- $active_trail[5]['title'] = $rules_link->label;
- $active_trail[5]['href'] = "admin/config/workflow/rules_links/manage/$link_name/components";
- $active_trail[5]['options']['attributes']['title'] = 'Edit the current link.';
- $active_trail[5]['localized_options'] = array();
- }
- }
- }
- /**
- * Implements hook_field_extra_fields().
- */
- function rules_link_field_extra_fields() {
- $return = array();
- $rules_links = rules_link_get_links();
- foreach ($rules_links as $rules_link) {
- if ($rules_link->settings['entity_link']) {
- $entity_info = entity_get_info($rules_link->entity_type);
- $bundles = empty($rules_link->settings['bundles']) ? array_keys($entity_info['bundles']) : $rules_link->settings['bundles'];
- foreach ($bundles as $bundle) {
- $return[$rules_link->entity_type][$bundle]['display']['rules_links_' . $rules_link->name]['label'] = $rules_link->label;
- $return[$rules_link->entity_type][$bundle]['display']['rules_links_' . $rules_link->name]['description'] = '';
- $return[$rules_link->entity_type][$bundle]['display']['rules_links_' . $rules_link->name]['weight'] = 0;
- }
- }
- }
- return $return;
- }
|