You are here

class ctools_context_required in Chaos Tool Suite (ctools) 7

Same name and namespace in other branches
  1. 6 includes/context.inc \ctools_context_required

Used to create a method of comparing if a list of contexts match a required context type.

Hierarchy

Expanded class hierarchy of ctools_context_required

1 string reference to 'ctools_context_required'
_views_content_get_context_from_display in views_content/views_content.module
Get the child plugin for a view context display.

File

includes/context.inc, line 207
Contains code related to the ctools system of 'context'.

View source
class ctools_context_required {

  /**
   * @var array
   *   Keyword strings associated with the context.
   */
  public $keywords;

  /**
   * If set, the title will be used in the selector to identify
   * the context. This is very useful when multiple contexts
   * are required to inform the user will be used for what.
   */
  public $title;

  /**
   * Test to see if this context is required.
   */
  public $required = TRUE;

  /**
   * If TRUE, skip the check in ctools_context_required::select()
   * for contexts whose names may have changed.
   */
  public $skip_name_check = FALSE;

  /**
   * The ctools_context_required constructor.
   *
   * Note: Constructor accepts a variable number of arguments, with optional
   * type-dependent args at the end of the list and one required argument,
   * the title. Note in particular that skip_name_check MUST be passed in as
   * a boolean (and not, for example, as an integer).
   *
   * @param string $title
   *   The title of the context for use in UI selectors when multiple contexts
   *   qualify.
   * @param string $keywords
   *   One or more keywords to use for matching which contexts are allowed.
   * @param array $restrictions
   *   Array of context restrictions.
   * @param bool $skip_name_check
   *   If True, skip the check in select() for contexts whose names may have
   *   changed.
   */
  public function __construct($title) {

    // If it was possible, using variadic syntax this should be:
    // __construct($title, string ...$keywords, array $restrictions = NULL, bool $skip = NULL)
    // but that form isn't allowed.
    $args = func_get_args();
    $this->title = array_shift($args);

    // If we have a boolean value at the end for $skip_name_check, store it.
    if (is_bool(end($args))) {
      $this->skip_name_check = array_pop($args);
    }

    // If we were given restrictions at the end, store them.
    if (count($args) > 1 && is_array(end($args))) {
      $this->restrictions = array_pop($args);
    }
    if (count($args) === 1) {
      $args = array_shift($args);
    }
    $this->keywords = $args;
  }

  /**
   * Filter the contexts to determine which apply in the current environment.
   *
   * A context passes the filter if:
   *  - the context matches 'type' of the required keywords (uses
   *    ctools_context::is_type(), so includes 'any' matches, etc).
   *  - AND if restrictions are present, there are some common elements between
   *    the requirement and the context.
   *
   * @param array $contexts
   *   An array of ctools_context objects (or something which will cast to an
   *   array of them). The contexts to apply the filter on.
   *
   * @return array
   *   An array of context objects, keyed with the same keys used for $contexts,
   *   which pass the filter.
   *
   * @see ctools_context::is_type()
   */
  public function filter($contexts) {
    $result = array();

    /**
     * See which of these contexts are valid.
     * @var ctools_context $context
     */
    foreach ((array) $contexts as $cid => $context) {
      if ($context
        ->is_type($this->keywords)) {

        // Compare to see if our contexts were met.
        if (!empty($this->restrictions) && !empty($context->restrictions)) {
          foreach ($this->restrictions as $key => $values) {

            // If we have a restriction, the context must either not have that
            // restriction listed, which means we simply don't know what it is,
            // or there must be an intersection of the restricted values on
            // both sides.
            if (!is_array($values)) {
              $values = array(
                $values,
              );
            }
            if (!empty($context->restrictions[$key]) && !array_intersect($values, $context->restrictions[$key])) {

              // Break out to check next context; this one fails the filter.
              continue 2;
            }
          }
        }

        // This context passes the filter.
        $result[$cid] = $context;
      }
    }
    return $result;
  }

  /**
   * Select one context from the list of contexts, accounting for changed IDs.
   *
   * Fundamentally, this returns $contexts[$context] or FALSE if that does not
   * exist. Additional logic accounts for changes in context names and dealing
   * with a $contexts parameter that is not an array.
   *
   * If we had requested a $context but that $context doesn't exist in our
   * context list, there is a good chance that what happened is the context
   * IDs changed. Look for another context that satisfies our requirements,
   * unless $skip_name_check is set.
   *
   * @param ctools_context|array $contexts
   *   A context, or an array of ctools_context.
   * @param string $context
   *   A context ID.
   *
   * @return bool|ctools_context
   *   The matching ctools_context, or False if no such context was found.
   */
  public function select($contexts, $context) {

    // Easier to deal with a standalone object as a 1-element array of objects.
    if (!is_array($contexts)) {
      if (is_object($contexts) && $contexts instanceof ctools_context) {
        $contexts = array(
          $contexts->id => $contexts,
        );
      }
      else {
        $contexts = array(
          $contexts,
        );
      }
    }

    // If we had requested a $context but that $context doesn't exist in our
    // context list, there is a good chance that what happened is the context
    // IDs changed. Check for another context that satisfies our requirements.
    if (!$this->skip_name_check && !empty($context) && !isset($contexts[$context])) {
      $choices = $this
        ->filter($contexts);

      // If we got a hit, take the first one that matches.
      if ($choices) {
        $keys = array_keys($choices);
        $context = reset($keys);
      }
    }
    if (empty($context) || empty($contexts[$context])) {
      return FALSE;
    }
    return $contexts[$context];
  }

}

Members

Namesort descending Modifiers Type Description Overrides
ctools_context_required::$keywords public property Keyword strings associated with the context.
ctools_context_required::$required public property Test to see if this context is required. 1
ctools_context_required::$skip_name_check public property If TRUE, skip the check in ctools_context_required::select() for contexts whose names may have changed.
ctools_context_required::$title public property If set, the title will be used in the selector to identify the context. This is very useful when multiple contexts are required to inform the user will be used for what.
ctools_context_required::filter public function Filter the contexts to determine which apply in the current environment. 1
ctools_context_required::select public function Select one context from the list of contexts, accounting for changed IDs. 1
ctools_context_required::__construct public function The ctools_context_required constructor.