You are here

class context_redirect_reaction in Context Redirect 7

Same name and namespace in other branches
  1. 6 context_redirect_reaction.inc \context_redirect_reaction

@file Context redirect reaction plugin for Context API.

Hierarchy

Expanded class hierarchy of context_redirect_reaction

2 string references to 'context_redirect_reaction'
context_redirect_context_plugins in ./context_redirect.module
Implements hook_context_plugins().
context_redirect_context_registry in ./context_redirect.module
Implements hook_context_registry().

File

./context_redirect_reaction.inc, line 7
Context redirect reaction plugin for Context API.

View source
class context_redirect_reaction extends context_reaction {

  /**
   * Implements options_form().
   */
  public function options_form($context) {
    $values = $this
      ->fetch_from_context($context);
    $form['#tree'] = TRUE;
    $form['redirect_path'] = array(
      '#title' => t('Redirect URL or path'),
      '#type' => 'textfield',
      '#default_value' => isset($values['redirect_path']) ? $values['redirect_path'] : '',
      '#description' => t('Provide a valid internal URL (ie. node/1) or path (ie. company/about-us) or an external URL (ie. http://drupal.org). You may also use @front to redirect to the front page.', array(
        '@front' => '<front>',
      )),
    );
    $form['enable_message'] = array(
      '#title' => t('Display redirect message'),
      '#type' => 'checkbox',
      '#default_value' => isset($values['enable_message']) ? $values['enable_message'] : 0,
      '#description' => t('When enabled, this will display a message to the user saying they were redirected.'),
    );
    $form['redirect_message'] = array(
      '#title' => t('Redirect message'),
      '#type' => 'textfield',
      '#default_value' => isset($values['redirect_message']) ? $values['redirect_message'] : '',
      '#description' => t('The message displayed to the user after they are redirected.'),
      '#states' => array(
        'visible' => array(
          ':input[name="reactions[plugins][context_redirect][enable_message]"]' => array(
            'checked' => TRUE,
          ),
        ),
      ),
    );
    $form['qsa'] = array(
      '#title' => t('Attach query string'),
      '#type' => 'checkbox',
      '#default_value' => isset($values['qsa']) ? $values['qsa'] : 0,
      '#description' => t('When enabled, append the original query string (GET values) to redirected URL.'),
    );
    $form['redirect_type'] = array(
      '#title' => t('Redirect type'),
      '#type' => 'select',
      '#default_value' => isset($values['redirect_type']) ? $values['redirect_type'] : 302,
      '#description' => t('The type of redirect to issue. You can !link.', array(
        '!link' => l('review HTTP redirect codes here', 'http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.3'),
      )),
      '#options' => array(
        301 => '301: Moved Permanently',
        302 => '302: Found',
        303 => '303: See Other',
        307 => '307: Temporary Redirect',
      ),
    );
    $form['admin_key'] = array(
      '#title' => t('Admin Key'),
      '#type' => 'textfield',
      '#default_value' => isset($values['admin_key']) ? $values['admin_key'] : '',
      '#field_prefix' => url('', array(
        'query' => array(
          'admin_key' => '',
        ),
        'absolute' => TRUE,
      )),
      '#description' => t('You can optionally provide an "admin key" which you can enter as a get variable in the page url to prevent the redirect triggering (eg. ?admin_key=no-redirect-please your admin key would be "no-redirect-please"). Leave blank to disable this.'),
    );
    return $form;
  }

  /**
   * Implements execute().
   */
  public function execute() {
    $contexts = $this
      ->get_contexts();

    // Check if we need to react to current Contexts.
    foreach ($contexts as $context) {
      if (!empty($context->reactions[$this->plugin])) {
        if ($url = $context->reactions[$this->plugin]['redirect_path']) {

          // Do nothing if this reaction is an invalid redirection.
          if ($this
            ->context_redirect_validate_redirect($url, $context)) {

            // Display a message if required.
            if ($context->reactions[$this->plugin]['enable_message'] && !(url_is_external($url) && !context_redirect_external_url_is_local($url))) {
              drupal_set_message(t('@message', array(
                '@message' => check_plain($context->reactions[$this->plugin]['redirect_message']),
              )));
            }

            // Start building an $options array for drupal_goto().
            $options = array();

            // Preserve the current query parameters if required.
            if ($context->reactions[$this->plugin]['qsa']) {
              $options['query'] = drupal_get_query_parameters();
            }

            // Log a watchdog notice.
            watchdog('context_redirect', 'User was redirected with the @context context, from @from to @destination.', array(
              '@context' => $context->name,
              '@from' => current_path(),
              '@destination' => $url,
            ), WATCHDOG_NOTICE, l("Configure {$context->name} context", "admin/structure/context/list/{$context->name}"));

            // If the url is "external" according to url_is_external()
            // && the url is a domain defined by the Domain Access module
            // && the current url is not a registered path on this domain
            // then the 'destination' is set to the current internal path,
            // leading to an infinite redirect from drupal_goto().
            // @see http://drupal.org/node/1883796
            if (url_is_external($url) && isset($_GET['destination'])) {
              unset($_GET['destination']);
            }

            // Perform the redirection.
            $http_response_code = isset($context->reactions[$this->plugin]['redirect_type']) ? $context->reactions[$this->plugin]['redirect_type'] : 302;
            drupal_goto($url, $options, $http_response_code);
          }
        }
      }
    }
  }

  /**
   * Validate the redirection.
   *
   * Depending on the current page, the destination url and the context's
   * configuration we may not want to allow this redirection.
   *
   * @param string $url
   *   The candidate destination url to be validated.
   * @param object $context
   *   The context object provided by Context API.
   *
   * @return boolean
   *   TRUE if the redirect should be allowed, FALSE otherwise.
   */
  public function context_redirect_validate_redirect($url, $context) {
    $valid_redirect = TRUE;
    $current_path = request_path();

    // If the url is not a valid path do nothing.
    if (!drupal_valid_path($url, FALSE)) {
      $valid_redirect = FALSE;
    }

    // Resolve aliases and/or relative paths to absolute system urls if possible
    // and attempt to detect obvious redirect loops.
    $normalized_url = url_is_external($url) ? rtrim($url, '/') . '/' : url(drupal_get_normal_path($url), array(
      'absolute' => TRUE,
    ));
    $normalized_current_path = url(drupal_get_normal_path($current_path), array(
      'absolute' => TRUE,
    ));
    if ($normalized_url == $normalized_current_path) {
      $valid_redirect = FALSE;
    }

    // Don't perform redirections on the context configuration screens.
    if (strpos($current_path, 'admin/structure/context') === 0) {
      $valid_redirect = FALSE;
    }

    // Admin key override.
    if ($admin_key = $context->reactions['context_redirect']['admin_key']) {
      if (isset($_GET['admin_key']) && $_GET['admin_key'] == $admin_key) {
        $valid_redirect = FALSE;
      }
    }

    // Allow other modules to invalidate the redirect.
    drupal_alter('context_redirect_validate_redirect', $valid_redirect, $context);
    return $valid_redirect;
  }

}

Members

Namesort descending Modifiers Type Description Overrides
context_reaction::$description property
context_reaction::$plugin property
context_reaction::$title property
context_reaction::fetch_from_context function Retrieve options from the context provided. 1
context_reaction::get_contexts function Retrieve active contexts that have values for this reaction.
context_reaction::options_form_submit function Options form submit handler. 3
context_reaction::settings_form function Settings form. Provide variable settings for your reaction. 2
context_reaction::__clone function Clone our references when we're being cloned.
context_reaction::__construct function Constructor. Do not override.
context_redirect_reaction::context_redirect_validate_redirect public function Validate the redirection.
context_redirect_reaction::execute public function Implements execute().
context_redirect_reaction::options_form public function Implements options_form(). Overrides context_reaction::options_form