[ Index ]

PHP Cross Reference of Drupal 6 (yi-drupal)

title

Body

[close]

/sites/all/modules/ctools/includes/ -> context.inc (source)

   1  <?php
   2  // $Id: context.inc,v 1.33.2.17 2010/09/10 17:07:52 merlinofchaos Exp $
   3  
   4  /**
   5   * @file
   6   *
   7   * Contains code related to the ctools system of 'context'.
   8   *
   9   * Context, originally from Panels, is a method of packaging objects into
  10   * a more generic bundle and providing a plugin system so that a UI can
  11   * take advantage of them. The idea is that the context objects
  12   * represent 'the context' that a given operation (usually a page view)
  13   * is operating in or on.
  14   *
  15   * For example, when viewing a page, the 'context' is a node object. When
  16   * viewing a user, the 'context' is a user object. Contexs can also
  17   * have related contexts. For example, when viewing a 'node' you may need
  18   * to know something about the node author. Therefore, the node author
  19   * is a related context.
  20   */
  21  
  22  /**
  23   * The context object is largely a wrapper around some other object, with
  24   * an interface to finding out what is contained and getting to both
  25   * the object and information about the object.
  26   *
  27   * Each context object has its own information, but some things are very
  28   * common, such as titles, data, keywords, etc. In particulare, the 'type'
  29   * of the context is important.
  30   */
  31  class ctools_context {
  32    var $type = NULL;
  33    var $data = NULL;
  34    // The title of this object.
  35    var $title = '';
  36    // The title of the page if this object exists
  37    var $page_title = '';
  38    // The identifier (in the UI) of this object
  39    var $identifier = '';
  40    var $argument = NULL;
  41    var $keyword = '';
  42    var $original_argument = NULL;
  43    var $restrictions = array();
  44    var $empty = FALSE;
  45  
  46    function ctools_context($type = 'none', $data = NULL) {
  47      $this->type  = $type;
  48      $this->data  = $data;
  49      $this->title = t('Unknown context');
  50    }
  51  
  52    function is_type($type) {
  53      if ($type == 'any' || $this->type == 'any') {
  54        return TRUE;
  55      }
  56  
  57      $a = is_array($type) ? $type : array($type);
  58      $b = is_array($this->type) ? $this->type : array($this->type);
  59      return (bool) array_intersect($a, $b);
  60    }
  61  
  62    function get_argument() {
  63      return $this->argument;
  64    }
  65  
  66    function get_original_argument() {
  67      if (!is_null($this->original_argument)) {
  68        return $this->original_argument;
  69      }
  70      return $this->argument;
  71    }
  72  
  73    function get_keyword() {
  74      return $this->keyword;
  75    }
  76  
  77    function get_identifier() {
  78      return $this->identifier;
  79    }
  80  
  81    function get_title() {
  82      return $this->title;
  83    }
  84  
  85    function get_page_title() {
  86      return $this->page_title;
  87    }
  88  }
  89  
  90  /**
  91   * Used to create a method of comparing if a list of contexts
  92   * match a required context type.
  93   */
  94  class ctools_context_required {
  95    var $keywords = '';
  96  
  97    /**
  98     * If set, the title will be used in the selector to identify
  99     * the context. This is very useful when multiple contexts
 100     * are required to inform the user will be used for what.
 101     */
 102    var $title = NULL;
 103  
 104    /**
 105     * Test to see if this context is required.
 106     */
 107    var $required = TRUE;
 108  
 109    /**
 110     *
 111     * @param $title
 112     *   The first parameter should be the 'title' of the context for use
 113     *   in UYI selectors when multiple contexts qualify.
 114     * @param ...
 115     *   One or more keywords to use for matching which contexts are allowed.
 116     */
 117    function ctools_context_required($title) {
 118      $args = func_get_args();
 119      $this->title = array_shift($args);
 120  
 121      // If we were given restrictions at the end, store them.
 122      if (count($args) > 1 && is_array(end($args))) {
 123        $this->restrictions = array_pop($args);
 124      }
 125  
 126      if (count($args) == 1) {
 127        $args = array_shift($args);
 128      }
 129      $this->keywords = $args;
 130    }
 131  
 132    function filter($contexts) {
 133      $result = array();
 134  
 135      // See which of these contexts are valid
 136      foreach ((array) $contexts as $cid => $context) {
 137        if ($context->is_type($this->keywords)) {
 138          // Compare to see if our contexts were met.
 139          if (!empty($this->restrictions) && !empty($context->restrictions)) {
 140            foreach ($this->restrictions as $key => $values) {
 141              // If we have a restriction, the context must either not have that
 142              // restriction listed, which means we simply don't know what it is,
 143              // or there must be an intersection of the restricted values on
 144              // both sides.
 145              if (!is_array($values)) {
 146                $values = array($values);
 147              }
 148              if (!empty($context->restrictions[$key]) && !array_intersect($values, $context->restrictions[$key])) {
 149                continue 2;
 150              }
 151            }
 152          }
 153          $result[$cid] = $context;
 154        }
 155      }
 156  
 157      return $result;
 158    }
 159  
 160    function select($contexts, $context) {
 161      if (!is_array($contexts)) {
 162        $contexts = array($contexts);
 163      }
 164  
 165      // Due to a bug, some contexts got recorded with an id of 0. This will
 166      // convert them to the correct ID allowing for some earlier panels
 167      // to continue to work.
 168      if (!empty($context) && $context[strlen($context) - 1] === '0') {
 169        $context[strlen($context) - 1] = 1;
 170      }
 171  
 172      if (empty($context) || empty($contexts[$context])) {
 173        return FALSE;
 174      }
 175      return $contexts[$context];
 176    }
 177  }
 178  
 179  /**
 180   * Used to compare to see if a list of contexts match an optional context. This
 181   * can produce empty contexts to use as placeholders.
 182   */
 183  class ctools_context_optional extends ctools_context_required {
 184    var $required = FALSE;
 185    function ctools_context_optional() {
 186      $args = func_get_args();
 187      call_user_func_array(array($this, 'ctools_context_required'), $args);
 188    }
 189  
 190    /**
 191     * Add the 'empty' context which is possible for optional
 192     */
 193    function add_empty(&$contexts) {
 194      $context = new ctools_context('any');
 195      $context->title      = t('No context');
 196      $context->identifier = t('No context');
 197      $contexts = array_merge(array('empty' => $context), $contexts);
 198    }
 199  
 200    function filter($contexts) {
 201      $this->add_empty($contexts);
 202      return parent::filter($contexts);
 203    }
 204  
 205    function select($contexts, $context) {
 206      $this->add_empty($contexts);
 207      if (empty($context)) {
 208        return $contexts['empty'];
 209      }
 210  
 211      $result = parent::select($contexts, $context);
 212  
 213      // Don't flip out if it can't find the context; this is optional, put
 214      // in an empty.
 215      if ($result == FALSE) {
 216        $result = $contexts['empty'];
 217      }
 218      return $result;
 219    }
 220  }
 221  
 222  /**
 223   * Return a keyed array of context that match the given 'required context'
 224   * filters.
 225   *
 226   * Functions or systems that require contexts of a particular type provide a
 227   * ctools_context_required or ctools_context_optional object. This function
 228   * examines that object and an array of contexts to determine which contexts
 229   * match the filter.
 230   *
 231   * Since multiple contexts can be required, this function will accept either
 232   * an array of all required contexts, or just a single required context object.
 233   *
 234   * @param $contexts
 235   *   A keyed array of all available contexts.
 236   * @param $required
 237   *   A ctools_context_required or ctools_context_optional object, or an array
 238   *   of such objects.
 239   *
 240   * @return
 241   *   A keyed array of contexts that match the filter.
 242   */
 243  function ctools_context_filter($contexts, $required) {
 244    if (is_array($required)) {
 245      $result = array();
 246      foreach ($required as $r) {
 247        $result = array_merge($result, _ctools_context_filter($contexts, $r));
 248      }
 249      return $result;
 250    }
 251  
 252    return _ctools_context_filter($contexts, $required);
 253  }
 254  
 255  function _ctools_context_filter($contexts, $required) {
 256    $result = array();
 257  
 258    if (is_object($required)) {
 259      $result = $required->filter($contexts);
 260    }
 261  
 262    return $result;
 263  }
 264  
 265  /**
 266   * Create a select box to choose possible contexts.
 267   *
 268   * This only creates a selector if there is actually a choice; if there
 269   * is only one possible context, that one is silently assigned.
 270   *
 271   * If an array of required contexts is provided, one selector will be
 272   * provided for each context.
 273   *
 274   * @param $contexts
 275   *   A keyed array of all available contexts.
 276   * @param $required
 277   *   The required context object or array of objects.
 278   *
 279   * @return
 280   *   A form element, or NULL if there are no contexts that satisfy the
 281   *   requirements.
 282   */
 283  function ctools_context_selector($contexts, $required, $default) {
 284    if (is_array($required)) {
 285      $result = array('#tree' => TRUE);
 286      $count = 1;
 287      foreach ($required as $id => $r) {
 288        $result[] = _ctools_context_selector($contexts, $r, isset($default[$id]) ? $default[$id] : '', $count++);
 289      }
 290      return $result;
 291    }
 292  
 293    return _ctools_context_selector($contexts, $required, $default);
 294  }
 295  
 296  function _ctools_context_selector($contexts, $required, $default, $num = 0) {
 297    $filtered = ctools_context_filter($contexts, $required);
 298    $count = count($filtered);
 299  
 300    $form = array();
 301  
 302    if ($count >= 1) {
 303      // If there's more than one to choose from, create a select widget.
 304      foreach ($filtered as $cid => $context) {
 305        $options[$cid] = $context->get_identifier();
 306      }
 307      if (!empty($required->title)) {
 308        $title = $required->title;
 309      }
 310      else {
 311        $title = $num ? t('Context %count', array('%count' => $num)) : t('Context');
 312      }
 313  
 314      return array(
 315        '#type' => 'select',
 316        '#options' => $options,
 317        '#title' => $title,
 318        '#default_value' => $default,
 319      );
 320    }
 321  }
 322  
 323  /**
 324   * Are there enough contexts for a plugin?
 325   *
 326   * Some plugins can have a 'required contexts' item which can either
 327   * be a context requirement object or an array of them. When contexts
 328   * are required, items that do not have enough contexts should not
 329   * appear. This tests an item to see if it has enough contexts
 330   * to actually appear.
 331   *
 332   * @param $contexts
 333   *   A keyed array of all available contexts.
 334   * @param $required
 335   *   The required context object or array of objects.
 336   *
 337   * @return
 338   *   TRUE if there are enough contexts, FALSE if there are not.
 339   */
 340  function ctools_context_match_requirements($contexts, $required) {
 341    if (!is_array($required)) {
 342      $required = array($required);
 343    }
 344  
 345    // Get the keys to avoid bugs in PHP 5.0.8 with keys and loops.
 346    // And use it to remove optional contexts.
 347    $keys = array_keys($required);
 348    foreach ($keys as $key) {
 349      if (empty($required[$key]->required)) {
 350        unset($required[$key]);
 351      }
 352    }
 353  
 354    $count = count($required);
 355    return (count(ctools_context_filter($contexts, $required)) >= $count);
 356  }
 357  
 358  /**
 359   * Create a select box to choose possible contexts.
 360   *
 361   * This only creates a selector if there is actually a choice; if there
 362   * is only one possible context, that one is silently assigned.
 363   *
 364   * If an array of required contexts is provided, one selector will be
 365   * provided for each context.
 366   *
 367   * @param $contexts
 368   *   A keyed array of all available contexts.
 369   * @param $required
 370   *   The required context object or array of objects.
 371   *
 372   * @return
 373   *   A form element, or NULL if there are no contexts that satisfy the
 374   *   requirements.
 375   */
 376  function ctools_context_converter_selector($contexts, $required, $default) {
 377    if (is_array($required)) {
 378      $result = array('#tree' => TRUE);
 379      $count = 1;
 380      foreach ($required as $id => $r) {
 381        $result[] = _ctools_context_converter_selector($contexts, $r, isset($default[$id]) ? $default[$id] : '', $count++);
 382      }
 383      return $result;
 384    }
 385  
 386    return _ctools_context_converter_selector($contexts, $required, $default);
 387  }
 388  
 389  function _ctools_context_converter_selector($contexts, $required, $default, $num = 0) {
 390    $filtered = ctools_context_filter($contexts, $required);
 391    $count = count($filtered);
 392  
 393    $form = array();
 394  
 395    if ($count > 1) {
 396      // If there's more than one to choose from, create a select widget.
 397      $options = array();
 398      foreach ($filtered as $cid => $context) {
 399        if ($context->type == 'any') {
 400          $options[''] = t('No context');
 401          continue;
 402        }
 403        $key = $context->get_identifier();
 404        if ($converters = ctools_context_get_converters($cid . '.', $context)) {
 405          $options[$key] = $converters;
 406        }
 407      }
 408      if (empty($options)) {
 409        return array(
 410          '#type' => 'value',
 411          '#value' => 'any',
 412        );
 413      }
 414      if (!empty($required->title)) {
 415        $title = $required->title;
 416      }
 417      else {
 418        $title = $num ? t('Context %count', array('%count' => $num)) : t('Context');
 419      }
 420  
 421      return array(
 422        '#type' => 'select',
 423        '#options' => $options,
 424        '#title' => $title,
 425        '#description' => t('Please choose which context and how you would like it converted.'),
 426        '#default_value' => $default,
 427      );
 428    }
 429  }
 430  
 431  /**
 432   * Get a list of converters available for a given context.
 433   */
 434  function ctools_context_get_converters($cid, $context) {
 435    if (empty($context->plugin)) {
 436      return array();
 437    }
 438  
 439    return _ctools_context_get_converters($cid, $context->plugin);
 440  }
 441  
 442  /**
 443   * Get a list of converters available for a given context.
 444   */
 445  function _ctools_context_get_converters($id, $plugin_name) {
 446    $plugin = ctools_get_context($plugin_name);
 447    if (empty($plugin['convert list'])) {
 448      return array();
 449    }
 450  
 451    $converters = array();
 452    if (is_array($plugin['convert list'])) {
 453      $converters = $plugin['convert list'];
 454    }
 455    else if ($function = ctools_plugin_get_function($plugin, 'convert list')) {
 456      $converters = (array) $function();
 457    }
 458  
 459    // DEPRECATED, but left in: This alter was misnamed.
 460    foreach (module_implements('ctools_context_convert_list') as $module) {
 461      $function = $module . '_ctools_context_convert_list';
 462      $function($plugin, $converters);
 463    }
 464  
 465    foreach (module_implements('ctools_context_convert_list_alter') as $module) {
 466      $function = $module . '_ctools_context_convert_list_alter';
 467      $function($plugin, $converters);
 468    }
 469  
 470    // Now, change them all to include the plugin:
 471    $return = array();
 472    foreach ($converters as $key => $title) {
 473      $return[$id . $key] = $title;
 474    }
 475  
 476    natcasesort($return);
 477    return $return;
 478  }
 479  
 480  /**
 481   * Get a list of all contexts + converters available.
 482   */
 483  function ctools_context_get_all_converters() {
 484    $contexts = ctools_get_contexts();
 485    $converters = array();
 486    foreach ($contexts as $name => $context) {
 487      $context_converters = _ctools_context_get_converters($name . '.', $name);
 488      if ($context_converters) {
 489        $converters[$context['title']] = $context_converters;
 490      }
 491    }
 492  
 493    return $converters;
 494  }
 495  
 496  /**
 497   * Let the context convert an argument based upon the converter that was given.
 498   */
 499  function ctools_context_convert_context($context, $converter) {
 500    $value = $context->argument;
 501    if ($function = ctools_plugin_load_function('ctools', 'contexts', $context->plugin, 'convert')) {
 502      $value = $function($context, $converter);
 503    }
 504  
 505    foreach (module_implements('ctools_context_converter_alter') as $module) {
 506      $function = $module . '_ctools_context_converter_alter';
 507      $function($context, $converter, $value);
 508    }
 509  
 510    return $value;
 511  }
 512  
 513  /**
 514   * Choose a context or contexts based upon the selection made via
 515   * ctools_context_filter.
 516   *
 517   * @param $contexts
 518   *   A keyed array of all available contexts
 519   * @param $required
 520   *   The required context object provided by the plugin
 521   * @param $context
 522   *   The selection made using ctools_context_selector
 523   */
 524  function ctools_context_select($contexts, $required, $context) {
 525    if (is_array($required)) {
 526      $result = array();
 527      foreach ($required as $id => $r) {
 528        if (($result[] = _ctools_context_select($contexts, $r, $context[$id])) === FALSE) {
 529          return FALSE;
 530        }
 531      }
 532      return $result;
 533    }
 534  
 535    return _ctools_context_select($contexts, $required, $context);
 536  }
 537  
 538  function _ctools_context_select($contexts, $required, $context) {
 539    if (!is_object($required)) {
 540      return FALSE;
 541    }
 542  
 543    return $required->select($contexts, $context);
 544  }
 545  
 546  /**
 547   * Create a new context object.
 548   *
 549   * @param $type
 550   *   The type of context to create; this loads a plugin.
 551   * @param $data
 552   *   The data to put into the context.
 553   * @param $empty
 554   *   Whether or not this context is specifically empty.
 555   * @param $conf
 556   *   A configuration structure if this context was created via UI.
 557   *
 558   * @return
 559   *   A $context or NULL if one could not be created.
 560   */
 561  function ctools_context_create($type, $data = NULL, $conf = FALSE) {
 562    ctools_include('plugins');
 563    if ($function = ctools_plugin_load_function('ctools', 'contexts', $type, 'context')) {
 564      return $function(FALSE, $data, $conf);
 565    }
 566  }
 567  
 568  /**
 569   * Create an empty context object.
 570   *
 571   * Empty context objects are primarily used as placeholders in the UI where
 572   * the actual contents of a context object may not be known. It may have
 573   * additional text embedded to give the user clues as to how the context
 574   * is used.
 575   *
 576   * @param $type
 577   *   The type of context to create; this loads a plugin.
 578   *
 579   * @return
 580   *   A $context or NULL if one could not be created.
 581   */
 582  function ctools_context_create_empty($type) {
 583    if ($function = ctools_plugin_load_function('ctools', 'contexts', $type, 'context')) {
 584      $context = $function(TRUE);
 585      if (is_object($context)) {
 586        $context->empty = TRUE;
 587      }
 588  
 589      return $context;
 590    }
 591  }
 592  
 593  /**
 594   * Perform keyword and context substitutions.
 595   */
 596  function ctools_context_keyword_substitute($string, $keywords, $contexts) {
 597    // Ensure a default keyword exists:
 598    $keywords['%%'] = '%';
 599  
 600    // Match contexts to the base keywords:
 601    $context_keywords = array();
 602    foreach ($contexts as $context) {
 603      if (isset($context->keyword)) {
 604        $context_keywords[$context->keyword] = $context;
 605      }
 606    }
 607  
 608    // Look for context matches we we only have to convert known matches.
 609    $matches = array();
 610    if (preg_match_all('/%([a-zA-Z0-9%:_-]+)/us', $string, $matches)) {
 611      foreach ($matches[1] as $keyword) {
 612        // Ignore anything it finds with %%.
 613        if ($keyword[0] == '%') {
 614          continue;
 615        }
 616  
 617        // If the keyword is already set by something passed in, don't try to
 618        // overwrite it.
 619        if (!empty($keywords['%' . $keyword])) {
 620          continue;
 621        }
 622  
 623        // Figure out our keyword and converter, if specified.
 624        if (strpos($keyword, ':')) {
 625          list($context, $converter) = explode(':', $keyword);
 626        }
 627        else {
 628          $context = $keyword;
 629          if (isset($context_keywords[$keyword])) {
 630            $plugin = ctools_get_context($context_keywords[$context]->plugin);
 631  
 632            // Fall back to a default converter, if specified.
 633            if ($plugin && !empty($plugin['convert default'])) {
 634              $converter = $plugin['convert default'];
 635            }
 636          }
 637        }
 638  
 639        if (empty($context_keywords[$context]) || !empty($context_keywords[$context]->empty)) {
 640          $keywords['%' . $keyword] = '';
 641        }
 642        else if (!empty($converter)) {
 643          $keywords['%' . $keyword] = ctools_context_convert_context($context_keywords[$context], $converter);
 644        }
 645        else {
 646          $keywords['%' . $keyword] = $context_keywords[$keyword]->title;
 647        }
 648      }
 649    }
 650    return strtr($string, $keywords);
 651  }
 652  
 653  /**
 654   * Determine a unique context ID for a context
 655   *
 656   * Often contexts of many different types will be placed into a list. This
 657   * ensures that even though contexts of multiple types may share IDs, they
 658   * are unique in the final list.
 659   */
 660  function ctools_context_id($context, $type = 'context') {
 661    if (!$context['id']) {
 662      $context['id'] = 1;
 663    }
 664  
 665    return $type . '_' . $context['name'] . '_' . $context['id'];
 666  }
 667  
 668  /**
 669   * Get the next id available given a list of already existing objects.
 670   *
 671   * This finds the next id available for the named object.
 672   *
 673   * @param $objects
 674   *   A list of context descriptor objects, i.e, arguments, relationships, contexts, etc.
 675   * @param $name
 676   *   The name being used.
 677   */
 678  function ctools_context_next_id($objects, $name) {
 679    $id = 0;
 680    // Figure out which instance of this argument we're creating
 681    if (!$objects) {
 682      return $id + 1;
 683    }
 684  
 685    foreach ($objects as $object) {
 686      if (isset($object['name']) && $object['name'] == $name) {
 687        if ($object['id'] > $id) {
 688          $id = $object['id'];
 689        }
 690      }
 691    }
 692  
 693    return $id + 1;
 694  }
 695  
 696  
 697  // ---------------------------------------------------------------------------
 698  // Functions related to contexts from arguments.
 699  
 700  /**
 701   * Fetch metadata on a specific argument plugin.
 702   *
 703   * @param $argument
 704   *   Name of an argument plugin.
 705   *
 706   * @return
 707   *   An array with information about the requested argument plugin.
 708   */
 709  function ctools_get_argument($argument) {
 710    ctools_include('plugins');
 711    return ctools_get_plugins('ctools', 'arguments', $argument);
 712  }
 713  
 714  /**
 715   * Fetch metadata for all argument plugins.
 716   *
 717   * @return
 718   *   An array of arrays with information about all available argument plugins.
 719   */
 720  function ctools_get_arguments() {
 721    ctools_include('plugins');
 722    return ctools_get_plugins('ctools', 'arguments');
 723  }
 724  
 725  /**
 726   * Get a context from an argument.
 727   *
 728   * @param $argument
 729   *   The configuration of an argument. It must contain the following data:
 730   *   - name: The name of the argument plugin being used.
 731   *   - argument_settings: The configuration based upon the plugin forms.
 732   *   - identifier: The human readable identifier for this argument, usually
 733   *     defined by the UI.
 734   *   - keyword: The keyword used for this argument for substitutions.
 735   *
 736   * @param $arg
 737   *   The actual argument received. This is expected to be a string from a URL but
 738   *   this does not have to be the only source of arguments.
 739   * @param $empty
 740   *   If true, the $arg will not be used to load the context. Instead, an empty
 741   *   placeholder context will be loaded.
 742   *
 743   * @return
 744   *   A context object if one can be loaded.
 745   */
 746  function ctools_context_get_context_from_argument($argument, $arg, $empty = FALSE) {
 747    ctools_include('plugins');
 748    if (empty($argument['name'])) {
 749      return;
 750    }
 751  
 752    if ($function = ctools_plugin_load_function('ctools', 'arguments', $argument['name'], 'context')) {
 753      if (!isset($argument['settings'])) {
 754        $argument['settings'] = array();
 755      }
 756  
 757      $context = $function($arg, $argument['settings'], $empty);
 758  
 759      if (is_object($context)) {
 760        $context->identifier = $argument['identifier'];
 761        $context->page_title = isset($argument['title']) ? $argument['title'] : '';
 762        $context->keyword    = $argument['keyword'];
 763        $context->id         = ctools_context_id($argument, 'argument');
 764        $context->original_argument = $arg;
 765  
 766        if (!empty($context->empty)) {
 767          $context->placeholder = array(
 768            'type' => 'argument',
 769            'conf' => $argument,
 770          );
 771        }
 772      }
 773      return $context;
 774    }
 775  }
 776  
 777  /**
 778   * Retrieve a list of empty contexts for all arguments.
 779   */
 780  function ctools_context_get_placeholders_from_argument($arguments) {
 781    $contexts = array();
 782    foreach ($arguments as $argument) {
 783      $context = ctools_context_get_context_from_argument($argument, NULL, TRUE);
 784      if ($context) {
 785        $contexts[ctools_context_id($argument, 'argument')] = $context;
 786      }
 787    }
 788    return $contexts;
 789  }
 790  
 791  /**
 792   * Load the contexts for a given list of arguments.
 793   *
 794   * @param $arguments
 795   *   The array of argument definitions.
 796   * @param &$contexts
 797   *   The array of existing contexts. New contexts will be added to this array.
 798   * @param $args
 799   *   The arguments to load.
 800   *
 801   * @return
 802   *   FALSE if an argument wants to 404.
 803   */
 804  function ctools_context_get_context_from_arguments($arguments, &$contexts, $args) {
 805    foreach ($arguments as $argument) {
 806      // pull the argument off the list.
 807      $arg = array_shift($args);
 808      $id = ctools_context_id($argument, 'argument');
 809  
 810      // For % arguments embedded in the URL, our context is already loaded.
 811      // There is no need to go and load it again.
 812      if (empty($contexts[$id])) {
 813        if ($context = ctools_context_get_context_from_argument($argument, $arg)) {
 814          $contexts[$id] = $context;
 815        }
 816      }
 817      else {
 818        $context = $contexts[$id];
 819      }
 820  
 821      if ((empty($context) || empty($context->data)) && !empty($argument['default']) && $argument['default'] == '404') {
 822        return FALSE;
 823      }
 824    }
 825    return TRUE;
 826  }
 827  
 828  // ---------------------------------------------------------------------------
 829  // Functions related to contexts from relationships.
 830  
 831  /**
 832   * Fetch metadata on a specific relationship plugin.
 833   *
 834   * @param $content type
 835   *   Name of a panel content type.
 836   *
 837   * @return
 838   *   An array with information about the requested relationship.
 839   */
 840  function ctools_get_relationship($relationship) {
 841    ctools_include('plugins');
 842    return ctools_get_plugins('ctools', 'relationships', $relationship);
 843  }
 844  
 845  /**
 846   * Fetch metadata for all relationship plugins.
 847   *
 848   * @return
 849   *   An array of arrays with information about all available relationships.
 850   */
 851  function ctools_get_relationships() {
 852    ctools_include('plugins');
 853    return ctools_get_plugins('ctools', 'relationships');
 854  }
 855  
 856  /**
 857   *
 858   * @param $relationship
 859   *   The configuration of a relationship. It must contain the following data:
 860   *   - name: The name of the relationship plugin being used.
 861   *   - relationship_settings: The configuration based upon the plugin forms.
 862   *   - identifier: The human readable identifier for this relationship, usually
 863   *     defined by the UI.
 864   *   - keyword: The keyword used for this relationship for substitutions.
 865   *
 866   * @param $source_context
 867   *   The context this relationship is based upon.
 868   *
 869   * @param $placeholders
 870   *   If TRUE, placeholders are acceptable.
 871   *
 872   * @return
 873   *   A context object if one can be loaded.
 874   */
 875  function ctools_context_get_context_from_relationship($relationship, $source_context, $placeholders = FALSE) {
 876    ctools_include('plugins');
 877    if ($function = ctools_plugin_load_function('ctools', 'relationships', $relationship['name'], 'context')) {
 878      if (!isset($relationship['relationship_settings'])) {
 879        $relationship['relationship_settings'] = array();
 880      }
 881  
 882      $context = $function($source_context, $relationship['relationship_settings'], $placeholders);
 883      if ($context) {
 884        $context->identifier = $relationship['identifier'];
 885        $context->page_title = isset($relationship['title']) ? $relationship['title'] : '';
 886        $context->keyword    = $relationship['keyword'];
 887        if (!empty($context->empty)) {
 888          $context->placeholder = array(
 889            'type' => 'relationship',
 890            'conf' => $relationship,
 891          );
 892        }
 893        return $context;
 894      }
 895    }
 896  }
 897  
 898  /**
 899   * Fetch all relevant relationships.
 900   *
 901   * Relevant relationships are any relationship that can be created based upon
 902   * the list of existing contexts. For example, the 'node author' relationship
 903   * is relevant if there is a 'node' context, but makes no sense if there is
 904   * not one.
 905   *
 906   * @param $contexts
 907   *   An array of contexts used to figure out which relationships are relevant.
 908   *
 909   * @return
 910   *   An array of relationship keys that are relevant for the given set of
 911   *   contexts.
 912   */
 913  function ctools_context_get_relevant_relationships($contexts) {
 914    $relevant = array();
 915    $relationships = ctools_get_relationships();
 916  
 917    // Go through each relationship
 918    foreach ($relationships as $rid => $relationship) {
 919      // For each relationship, see if there is a context that satisfies it.
 920      if (ctools_context_filter($contexts, $relationship['required context'])) {
 921        $relevant[$rid] = $relationship['title'];
 922      }
 923    }
 924  
 925    return $relevant;
 926  }
 927  
 928  /**
 929   * Fetch all active relationships
 930   *
 931   * @param $relationships
 932   *   An keyed array of relationship data including:
 933   *   - name: name of relationship
 934   *   - context: context id relationship belongs to. This will be used to
 935   *     identify which context in the $contexts array to use to create the
 936   *     relationship context.
 937   *
 938   * @param $contexts
 939   *   A keyed array of contexts used to figure out which relationships
 940   *   are relevant. New contexts will be added to this.
 941   *
 942   * @param $placeholders
 943   *   If TRUE, placeholders are acceptable.
 944   */
 945  function ctools_context_get_context_from_relationships($relationships, &$contexts, $placeholders = FALSE) {
 946    $return = array();
 947  
 948    foreach ($relationships as $rdata) {
 949      if (!isset($rdata['context'])) {
 950        continue;
 951      }
 952  
 953      if (is_array($rdata['context'])) {
 954        $rcontexts = array();
 955        foreach ($rdata['context'] as $cid) {
 956          if (empty($contexts[$cid])) {
 957            continue 2;
 958          }
 959          $rcontexts[] = $contexts[$cid];
 960        }
 961      }
 962      else {
 963        if (empty($contexts[$rdata['context']])) {
 964          continue;
 965        }
 966        $rcontexts = $contexts[$rdata['context']];
 967      }
 968  
 969      $cid = ctools_context_id($rdata, 'relationship');
 970      if ($context = ctools_context_get_context_from_relationship($rdata, $rcontexts)) {
 971        $contexts[$cid] = $context;
 972      }
 973    }
 974  }
 975  
 976  // ---------------------------------------------------------------------------
 977  // Functions related to loading contexts from simple context definitions.
 978  
 979  /**
 980   * Fetch metadata on a specific context plugin.
 981   *
 982   * @param $context
 983   *   Name of a context.
 984   *
 985   * @return
 986   *   An array with information about the requested panel context.
 987   */
 988  function ctools_get_context($context) {
 989    ctools_include('plugins');
 990    return ctools_get_plugins('ctools', 'contexts', $context);
 991  }
 992  
 993  /**
 994   * Fetch metadata for all context plugins.
 995   *
 996   * @return
 997   *   An array of arrays with information about all available panel contexts.
 998   */
 999  function ctools_get_contexts() {
1000    ctools_include('plugins');
1001    return ctools_get_plugins('ctools', 'contexts');
1002  }
1003  
1004  /**
1005   *
1006   * @param $context
1007   *   The configuration of a context. It must contain the following data:
1008   *   - name: The name of the context plugin being used.
1009   *   - context_settings: The configuration based upon the plugin forms.
1010   *   - identifier: The human readable identifier for this context, usually
1011   *     defined by the UI.
1012   *   - keyword: The keyword used for this context for substitutions.
1013   * @param $type
1014   *   This is either 'context' which indicates the context will be loaded
1015   *   from data in the settings, or 'required_context' which means the
1016   *   context must be acquired from an external source. This is the method
1017   *   used to pass pure contexts from one system to another.
1018   *
1019   * @return
1020   *   A context object if one can be loaded.
1021   */
1022  function ctools_context_get_context_from_context($context, $type = 'context', $argument = NULL) {
1023    ctools_include('plugins');
1024    $plugin = ctools_get_context($context['name']);
1025    if ($function = ctools_plugin_get_function($plugin, 'context')) {
1026      if (!isset($context['context_settings'])) {
1027        $context['context_settings'] = array();
1028      }
1029  
1030      if (isset($argument) && isset($plugin['placeholder name'])) {
1031        $context['context_settings'][$plugin['placeholder name']] = $argument;
1032      }
1033  
1034      $return = $function($type == 'requiredcontext', $context['context_settings'], TRUE);
1035      if ($return) {
1036        $return->identifier = $context['identifier'];
1037        $return->page_title = isset($context['title']) ? $context['title'] : '';
1038        $return->keyword    = $context['keyword'];
1039  
1040        if (!empty($context->empty)) {
1041          $context->placeholder = array(
1042            'type' => 'context',
1043            'conf' => $context,
1044          );
1045        }
1046  
1047        return $return;
1048      }
1049    }
1050  }
1051  
1052  /**
1053   * Retrieve a list of base contexts based upon a simple 'contexts' definition.
1054   *
1055   * For required contexts this will always retrieve placeholders.
1056   *
1057   * @param $contexts
1058   *   The list of contexts defined in the UI.
1059   * @param $type
1060   *   Either 'context' or 'requiredcontext', which indicates whether the contexts
1061   *   are loaded from internal data or copied from an external source.
1062   * @param $placeholders
1063   *   If true, placeholders are acceptable.
1064   */
1065  function ctools_context_get_context_from_contexts($contexts, $type = 'context', $placeholders = FALSE) {
1066    $return = array();
1067    foreach ($contexts as $context) {
1068      $ctext = ctools_context_get_context_from_context($context, $type);
1069      if ($ctext) {
1070        if ($placeholders) {
1071          $ctext->placeholder = TRUE;
1072        }
1073        $return[ctools_context_id($context, $type)] = $ctext;
1074      }
1075    }
1076    return $return;
1077  }
1078  
1079  /**
1080   * Match up external contexts to our required contexts.
1081   *
1082   * This function is used to create a list of contexts with proper
1083   * IDs based upon a list of required contexts.
1084   *
1085   * These contexts passed in should match the numeric positions of the
1086   * required contexts. The caller must ensure this has already happened
1087   * correctly as this function will not detect errors here.
1088   *
1089   * @param $required
1090   *   A list of required contexts as defined by the UI.
1091   * @param $contexts
1092   *   A list of matching contexts as passed in from the calling system.
1093   */
1094  function ctools_context_match_required_contexts($required, $contexts) {
1095    $return = array();
1096    if (!is_array($required)) {
1097      return $return;
1098    }
1099  
1100    foreach ($required as $r) {
1101      $context = drupal_clone(array_shift($contexts));
1102      $context->identifier = $r['identifier'];
1103      $context->page_title = isset($r['title']) ? $r['title'] : '';
1104      $context->keyword    = $r['keyword'];
1105      $return[ctools_context_id($r, 'requiredcontext')] = $context;
1106    }
1107  
1108    return $return;
1109  }
1110  
1111  /**
1112   * Load a full array of contexts for an object.
1113   *
1114   * Not all of the types need to be supported by this object.
1115   *
1116   * This function is not used to load contexts from external data, but may
1117   * be used to load internal contexts and relationships. Otherwise it can also
1118   * be used to generate a full set of placeholders for UI purposes.
1119   *
1120   * @param $object
1121   *   An object that contains some or all of the following variables:
1122   *
1123   * - requiredcontexts: A list of UI configured contexts that are required
1124   *   from an external source. Since these require external data, they will
1125   *   only be added if $placeholders is set to TRUE, and empty contexts will
1126   *   be created.
1127   * - arguments: A list of UI configured arguments that will create contexts.
1128   *   Since these require external data, they will only be added if $placeholders
1129   *   is set to TRUE.
1130   * - contexts: A list of UI configured contexts that have no external source,
1131   *   and are essentially hardcoded. For example, these might configure a
1132   *   particular node or a particular taxonomy term.
1133   * - relationships: A list of UI configured contexts to be derived from other
1134   *   contexts that already exist from other sources. For example, these might
1135   *   be used to get a user object from a node via the node author relationship.
1136   * @param $placeholders
1137   *   If TRUE, this will generate placeholder objects for types this function
1138   *   cannot load.
1139   * @param $contexts
1140   *   An array of pre-existing contexts that will be part of the return value.
1141   */
1142  function ctools_context_load_contexts($object, $placeholders = TRUE, $contexts = array()) {
1143    if (!empty($object->base_contexts)) {
1144      $contexts += $object->base_contexts;
1145    }
1146  
1147    if ($placeholders) {
1148      // This will load empty contexts as placeholders for arguments that come
1149      // from external sources. If this isn't set, it's assumed these context
1150      // will already have been matched up and loaded.
1151      if (!empty($object->requiredcontexts) && is_array($object->requiredcontexts)) {
1152        $contexts += ctools_context_get_context_from_contexts($object->requiredcontexts, 'requiredcontext', $placeholders);
1153      }
1154  
1155      if (!empty($object->arguments) && is_array($object->arguments)) {
1156        $contexts += ctools_context_get_placeholders_from_argument($object->arguments);
1157      }
1158    }
1159  
1160    if (!empty($object->contexts) && is_array($object->contexts)) {
1161      $contexts += ctools_context_get_context_from_contexts($object->contexts, 'context', $placeholders);
1162    }
1163  
1164    // add contexts from relationships
1165    if (!empty($object->relationships) && is_array($object->relationships)) {
1166      ctools_context_get_context_from_relationships($object->relationships, $contexts, $placeholders);
1167    }
1168  
1169    return $contexts;
1170  }
1171  
1172  /**
1173   * Return the first context with a form id from a list of contexts.
1174   *
1175   * This function is used to figure out which contexts represents 'the form'
1176   * from a list of contexts. Only one contexts can actually be 'the form' for
1177   * a given page, since the @code{<form>} tag can not be embedded within
1178   * itself.
1179   */
1180  function ctools_context_get_form($contexts) {
1181    if (!empty($contexts)) {
1182      foreach ($contexts as $id => $context) {
1183        // if a form shows its id as being a 'required context' that means the
1184        // the context is external to this display and does not count.
1185        if (!empty($context->form_id) && substr($id, 0, 15) != 'requiredcontext') {
1186          return $context;
1187        }
1188      }
1189    }
1190  }
1191  
1192  /**
1193   * Replace placeholders with real contexts using data extracted from a form
1194   * for the purposes of previews.
1195   *
1196   * @param $contexts
1197   *   All of the contexts, including the placeholders.
1198   * @param $arguments
1199   *   The arguments. These will be acquired from $form_state['values'] and the
1200   *   keys must match the context IDs.
1201   *
1202   * @return
1203   *   A new $contexts array containing the replaced contexts. Not all contexts
1204   *   may be replaced if, for example, an argument was unable to be converted
1205   *   into a context.
1206   */
1207  function ctools_context_replace_placeholders($contexts, $arguments) {
1208    foreach ($contexts as $cid => $context) {
1209      if (empty($context->empty)) {
1210        continue;
1211      }
1212  
1213      $new_context = NULL;
1214      switch ($context->placeholder['type']) {
1215        case 'relationship':
1216          $relationship = $context->placeholder['conf'];
1217          if (isset($contexts[$relationship['context']])) {
1218            $new_context = ctools_context_get_context_from_relationship($relationship, $contexts[$relationship['context']]);
1219          }
1220          break;
1221        case 'argument':
1222          if (isset($arguments[$cid]) && $arguments[$cid] !== '') {
1223            $argument = $context->placeholder['conf'];
1224            $new_context = ctools_context_get_context_from_argument($argument, $arguments[$cid]);
1225          }
1226          break;
1227        case 'context':
1228          if (!empty($arguments[$cid])) {
1229            $context_info = $context->placeholder['conf'];
1230            $new_context = ctools_context_get_context_from_context($context_info, 'requiredcontext', $arguments[$cid]);
1231          }
1232          break;
1233      }
1234  
1235      if ($new_context && empty($new_context->empty)) {
1236        $contexts[$cid] = $new_context;
1237      }
1238    }
1239  
1240    return $contexts;
1241  }
1242  
1243  /**
1244   * Provide a form array for getting data to replace placeholder contexts
1245   * with real data.
1246   */
1247  function ctools_context_replace_form(&$form, $contexts) {
1248    foreach ($contexts as $cid => $context) {
1249      if (empty($context->empty)) {
1250        continue;
1251      }
1252  
1253      // Get plugin info from the context which should have been set when the
1254      // empty context was created.
1255      $info = NULL;
1256      $plugin = NULL;
1257      $settings = NULL;
1258      switch ($context->placeholder['type']) {
1259        case 'argument':
1260          $info = $context->placeholder['conf'];
1261          $plugin = ctools_get_argument($info['name']);
1262          $settings = $info['settings'];
1263          break;
1264  
1265        case 'context':
1266          $info = $context->placeholder['conf'];
1267          $plugin = ctools_get_context($info['name']);
1268          $settings = $info['context_settings'];
1269          break;
1270      }
1271  
1272      // Ask the plugin where the form is.
1273      if ($plugin && isset($plugin['placeholder form'])) {
1274        if (is_array($plugin['placeholder form'])) {
1275          $form[$cid] = $plugin['placeholder form'];
1276        }
1277        else if (function_exists($plugin['placeholder form'])) {
1278          $widget = $plugin['placeholder form']($info['settings']);
1279          if ($widget) {
1280            $form[$cid] = $widget;
1281          }
1282        }
1283  
1284        if (!empty($form[$cid])) {
1285          $form[$cid]['#title'] = t('@identifier (@keyword)', array('@keyword' => '%' . $context->keyword, '@identifier' => $context->identifier));
1286        }
1287      }
1288    }
1289  }
1290  
1291  // ---------------------------------------------------------------------------
1292  // Functions related to loading access control plugins
1293  
1294  /**
1295   * Fetch metadata on a specific access control plugin.
1296   *
1297   * @param $name
1298   *   Name of a plugin.
1299   *
1300   * @return
1301   *   An array with information about the requested access control plugin.
1302   */
1303  function ctools_get_access_plugin($name) {
1304    ctools_include('plugins');
1305    return ctools_get_plugins('ctools', 'access', $name);
1306  }
1307  
1308  /**
1309   * Fetch metadata for all access control plugins.
1310   *
1311   * @return
1312   *   An array of arrays with information about all available access control plugins.
1313   */
1314  function ctools_get_access_plugins() {
1315    ctools_include('plugins');
1316    return ctools_get_plugins('ctools', 'access');
1317  }
1318  
1319  /**
1320   * Fetch a list of access plugins that are available for a given list of
1321   * contexts.
1322   *
1323   * if 'logged-in-user' is not in the list of contexts, it will be added as
1324   * this is required.
1325   */
1326  function ctools_get_relevant_access_plugins($contexts) {
1327    if (!isset($contexts['logged-in-user'])) {
1328      $contexts['logged-in-user'] = ctools_access_get_loggedin_context();
1329    }
1330  
1331    $all_plugins = ctools_get_access_plugins();
1332    $plugins = array();
1333    foreach ($all_plugins as $id => $plugin) {
1334      if (!empty($plugin['required context']) && !ctools_context_match_requirements($contexts, $plugin['required context'])) {
1335        continue;
1336      }
1337      $plugins[$id] = $plugin;
1338    }
1339  
1340    return $plugins;
1341  }
1342  
1343  /**
1344   * Create a context for the logged in user.
1345   */
1346  function ctools_access_get_loggedin_context() {
1347    global $user;
1348    $context = ctools_context_create('user', $user);
1349    $context->identifier = t('Logged in user');
1350    $context->keyword    = 'viewer';
1351    $context->id         = 0;
1352  
1353    return $context;
1354  }
1355  
1356  /**
1357   * Get a summary of an access plugin's settings.
1358   */
1359  function ctools_access_summary($plugin, $contexts, $test) {
1360    if (!isset($contexts['logged-in-user'])) {
1361      $contexts['logged-in-user'] = ctools_access_get_loggedin_context();
1362    }
1363  
1364    $description = '';
1365    if ($function = ctools_plugin_get_function($plugin, 'summary')) {
1366      $required_context = isset($plugin['required context']) ? $plugin['required context'] : array();
1367      $context          = isset($test['context']) ? $test['context'] : array();
1368      $description      = $function($test['settings'], ctools_context_select($contexts, $required_context, $context), $plugin);
1369    }
1370  
1371    if (!empty($test['not'])) {
1372      $description = "NOT ($description)";
1373    }
1374  
1375    return $description;
1376  }
1377  
1378  /**
1379   * Get a summary of a group of access plugin's settings.
1380   */
1381  function ctools_access_group_summary($access, $contexts) {
1382    if (empty($access['plugins'])) {
1383      return;
1384    }
1385  
1386    $descriptions = array();
1387    foreach ($access['plugins'] as $id => $test) {
1388      $plugin = ctools_get_access_plugin($test['name']);
1389      $descriptions[] = ctools_access_summary($plugin, $contexts, $test);
1390    }
1391  
1392    $separator = $access['logic'] == 'and' ? t(', and ') : t(', or ');
1393    return implode($separator, $descriptions);
1394  }
1395  
1396  /**
1397   * Determine if the current user has access via  plugin.
1398   *
1399   * @param $settings
1400   *   An array of settings theoretically set by the user.
1401   * @param $contexts
1402   *   An array of zero or more contexts that may be used to determine if
1403   *   the user has access.
1404   *
1405   * @return
1406   *   TRUE if access is granted, false if otherwise.
1407   */
1408  function ctools_access($settings, $contexts = array()) {
1409    if (empty($settings['plugins'])) {
1410      return TRUE;
1411    }
1412  
1413    if (!isset($settings['logic'])) {
1414      $settings['logic'] = 'and';
1415    }
1416  
1417    if (!isset($contexts['logged-in-user'])) {
1418      $contexts['logged-in-user'] = ctools_access_get_loggedin_context();
1419    }
1420  
1421    foreach ($settings['plugins'] as $test) {
1422      $pass = FALSE;
1423      $plugin = ctools_get_access_plugin($test['name']);
1424      if ($plugin && $function = ctools_plugin_get_function($plugin, 'callback')) {
1425        // Do we need just some contexts or all of them?
1426        if (!empty($plugin['all contexts'])) {
1427          $test_contexts = $contexts;
1428        }
1429        else {
1430          $required_context = isset($plugin['required context']) ? $plugin['required context'] : array();
1431          $context = isset($test['context']) ? $test['context'] : array();
1432          $test_contexts = ctools_context_select($contexts, $required_context, $context);
1433        }
1434  
1435        $pass = $function($test['settings'], $test_contexts, $plugin);
1436        if (!empty($test['not'])) {
1437          $pass = !$pass;
1438        }
1439      }
1440  
1441      if ($pass && $settings['logic'] == 'or') {
1442        // Pass if 'or' and this rule passed.
1443        return TRUE;
1444      }
1445      else if (!$pass && $settings['logic'] == 'and') {
1446        // Fail if 'and' and htis rule failed.
1447        return FALSE;
1448      }
1449    }
1450  
1451    // Return TRUE if logic was and, meaning all rules passed.
1452    // Return FALSE if logic was or, meaning no rule passed.
1453    return $settings['logic'] == 'and';
1454  }
1455  
1456  /**
1457   * Create default settings for a new access plugin.
1458   *
1459   * @param $plugin
1460   *   The access plugin being used.
1461   *
1462   * @return
1463   *   A default configured test that should be placed in $access['plugins'];
1464   */
1465  function ctools_access_new_test($plugin) {
1466    $test = array(
1467      'name' => $plugin['name'],
1468      'settings' => array(),
1469    );
1470  
1471    // Set up required context defaults.
1472    if (isset($plugin['required context'])) {
1473      if (is_object($plugin['required context'])) {
1474        $test['context'] = '';
1475      }
1476      else {
1477        $test['context'] = array();
1478        foreach ($plugin['required context'] as $required) {
1479          $test['context'][] = '';
1480        }
1481      }
1482    }
1483  
1484  
1485    $default = NULL;
1486    if (isset($plugin['default'])) {
1487      $default = $plugin['default'];
1488    }
1489    elseif (isset($plugin['defaults'])) {
1490      $default = $plugin['defaults'];
1491    }
1492  
1493    // Setup plugin defaults.
1494    if (isset($default)) {
1495      if (is_array($default)) {
1496        $test['settings'] = $default;
1497      }
1498      else if (function_exists($default)) {
1499        $test['settings'] = $default();
1500      }
1501      else {
1502        $test['settings'] = array();
1503      }
1504    }
1505  
1506    return $test;
1507  }
1508  
1509  /**
1510   * Apply restrictions to contexts based upon the access control configured.
1511   *
1512   * These restrictions allow the UI to not show content that may not
1513   * be relevant to all types of a particular context.
1514   */
1515  function ctools_access_add_restrictions($settings, $contexts) {
1516    if (empty($settings['plugins'])) {
1517      return;
1518    }
1519  
1520    if (!isset($settings['logic'])) {
1521      $settings['logic'] = 'and';
1522    }
1523  
1524    // We're not going to try to figure out restrictions on the or.
1525    if ($settings['logic'] == 'or' && count($settings['plugins']) > 1) {
1526      return;
1527    }
1528  
1529    foreach ($settings['plugins'] as $test) {
1530      $plugin = ctools_get_access_plugin($test['name']);
1531      if ($plugin && $function = ctools_plugin_get_function($plugin, 'restrictions')) {
1532        $required_context = isset($plugin['required context']) ? $plugin['required context'] : array();
1533        $context = isset($test['context']) ? $test['context'] : array();
1534        $contexts = ctools_context_select($contexts, $required_context, $context);
1535        $function($test['settings'], $contexts);
1536      }
1537    }
1538  }


Generated: Mon Jul 9 18:01:44 2012 Cross-referenced by PHPXref 0.7