Newer
Older
<?php
// $Id$
/**
* @file plugins.inc
*
* Contains helper code for plugins and contexts.
*/
/**
* Forms the basis for describing and storing a context that a display
* might be running in.
*/
class panels_context {
var $type = NULL;
var $data = NULL;
// The title of this object.
var $title = '';
// The title of the page if this object exists
var $page_title = '';
// The identifier (in the UI) of this object
var $identifier = '';
var $argument = NULL;
var $keyword = '';
function panels_context($type = 'none', $data = NULL) {
$this->type = $type;
$this->data = $data;
$this->title = t('Unknown context');
}
function is_type($type) {
if ($type == 'any' || $this->type == 'any') {
return TRUE;
}
$a = is_array($type) ? $type : array($type);
$b = is_array($this->type) ? $this->type : array($this->type);
return (bool) array_intersect($a, $b);
}
function get_argument() {
return $this->argument;
}
function get_keyword() {
return $this->keyword;
}
function get_identifier() {
return $this->identifier;
}
function get_title() {
return $this->title;
}
function get_page_title() {
return $this->page_title;
}
}
/**
* This is used to explain to Panels what context is required.
*/
class panels_required_context {
var $keywords = '';
function panels_required_context() {
$args = func_get_args();
$this->title = array_shift($args);
if (count($args) == 1) {
$args = array_shift($args);
}
$this->keywords = $args;
}
function filter($contexts) {
$result = array();
// See which of these contexts are valid
foreach ($contexts as $cid => $context) {
if ($context->is_type($this->keywords)) {
$result[$cid] = $context;
}
}
return $result;
}
function select($contexts, $context) {
if (empty($context) || empty($contexts[$context])) {
}
return $contexts[$context];
}
}
class panels_optional_context extends panels_required_context {
function panels_optional_context() {
$args = func_get_args();
call_user_func_array(array($this, 'panels_required_context'), $args);
}
/**
* Add the 'empty' context which is possible for optional
*/
function add_empty(&$contexts) {
$context = new panels_context('any');
$context->title = t('No context');
$context->identifier = t('No context');
$contexts = array_merge(array('empty' => $context), $contexts);
}
function filter($contexts) {
$this->add_empty($contexts);
return parent::filter($contexts);
}
function select($contexts, $context) {
$this->add_empty($contexts);
if (empty($context)) {
return $contexts['empty'];
}
// Don't flip out if it can't find the context; this is optional, put
// in an empty.
if ($result == FALSE) {
$result = $contexts['empty'];
}
}
/**
* Master pane access function; combines all the relevant parameters that
* natively used by the Panels API to determine a pane's access. Called from
* panels_render_panes().
* @param $pane
* The pane object to test for access.
* @param $display
* The display object containing the pane object to be tested.
function panels_pane_access($pane, $display) {
global $user;
// Administrator privileges
if (user_access('view all pane', $user)) {
return TRUE;
}
$role_access = _panels_pane_access_role($pane, $user);
$type = panels_get_content_type($pane->type);
if (!$visibility_check = panels_plugin_get_function('content_types', $type, 'visibility check')) {
return $role_access;
// Call the content type's custom-defined visibility rendering check.
// Pass as much possibly relevant data as possible.
$visibility_access = $visibility_check($pane, $display, $user);
// Content type marked both access modes to be ANDed together.
if (!empty($type['roles and visibility'])) {
return ($visibility_access === TRUE && $role_access === TRUE) ? TRUE : FALSE;
}
// Err on the safe side: if EVERYTHING else has failed, then don't render the pane.
return isset($visibility_access) ? $visibility_access : FALSE;
}
/**
* Determine role-based access to a panel pane for the current user
*
* @param object $pane
* The pane object to test.
* @param object $account
* The current $user object.
*
* @return bool $role_access
* The boolean result of the roles-based segment of the Panels access system.
*/
function _panels_pane_access_role($pane, $account) {
// All views with an empty access setting are available to all roles.
if (!$pane->access || !is_array($pane->access)) {
return TRUE;
}
// Otherwise, check roles
static $roles = array();
if (!isset($roles[$account->uid])) {
$roles[$account->uid] = array_keys($account->roles);
$roles[$account->uid][] = $account->uid ? DRUPAL_AUTHENTICATED_RID : DRUPAL_ANONYMOUS_RID;
}
return array_intersect($pane->access, $roles[$account->uid]) ? TRUE : FALSE;
}
/**
* Get the content from a given content type.
*
* @param $type
* The content type. May be the name or an already loaded content type object.
* @param $conf
* The configuration for the content type.
* @param $args
* The arguments to the content type.
* @param $context
* The panels_context object.
* @Param $incoming_content
* Any incoming content, if this display is a wrapper.
*/
function panels_ct_get_content($type, $conf, $args, $context, $incoming_content) {
if ($function = panels_plugin_get_function('content_types', $type, 'render callback')) {
Earl Miles
committed
$content = $function($conf, $args, $context, $incoming_content);
if (empty($content->title) && !empty($content->subject)) {
$content->title = $content->subject;
}
if (!empty($content->title) && empty($content->subject)) {
$content->subject = $content->title;
}
return $content;
}
}
/**
* Get the title from a given content type.
*
* @param $type
* The content type. May be the name or an already loaded content type object.
* @param $conf
* The configuration for the content type.
* @param $context
* The panels_context object.
* @param $incoming_content
* Any incoming content, if this display is a wrapper.
*/
function panels_ct_get_title($type, $conf, $context = NULL, $incoming_content = NULL) {
if ($function = panels_plugin_get_function('content_types', $type, 'title callback')) {
return $function($conf, $context, $incoming_content);
}
return t('Deleted/missing content type @type', array('@type' => $type));
}
/**
Sam Boyer
committed
* Add the default FAPI elements to the content type configuration form
Sam Boyer
committed
function panels_ct_conf_form($ct_data, $contexts, $conf) {
list($subtype, $content_type) = array($ct_data['subtype'], $ct_data['type']);
Sam Boyer
committed
if (!empty($subtype['required context']) && is_array($contexts)) {
$form['context'] = panels_context_selector($contexts, $subtype['required context'], isset($conf['context']) ? $conf['context'] : array());
}
$style_options = array('default' => t('Default'));
foreach (panels_get_styles() as $name => $properties) {
if (empty($properties['hidden']) && (!empty($properties['render pane']))) {
$style_options[$name] = $properties['title'];
}
}
asort($style_options);
if (empty($conf['style'])) {
$conf['style'] = 'default';
}
if ($style_options) {
$form['style'] = array(
'#type' => 'select',
'#title' => t('Pane style'),
'#default_value' => $conf['style'],
'#options' => $style_options,
);
}
// Unless we're not allowed to overide the title on this content type, add this
// gadget to all panes.
if (empty($content_type['no title override'])) {
$form['aligner_start'] = array(
'#value' => '<div class="option-text-aligner">',
);
$form['override_title'] = array(
'#type' => 'checkbox',
Sam Boyer
committed
'#default_value' => isset($conf['override_title']) ? $conf['override_title'] : '',
'#title' => t('Override title'),
'#id' => 'override-title-checkbox',
);
$form['override_title_text'] = array(
'#type' => 'textfield',
Sam Boyer
committed
'#default_value' => isset($conf['override_title_text']) ? $conf['override_title_text'] : '',
'#size' => 35,
'#id' => 'override-title-textfield',
);
$form['aligner_stop'] = array(
'#value' => '</div><div style="clear: both; padding: 0; margin: 0"></div>',
);
$form['override_title_markup'] = array(
'#prefix' => '<div class="description">',
'#suffix' => '</div>',
'#value' => t('You may use %keywords from contexts, as well as %title to contain the original title.'),
);
}
// Add CSS class and ID gadgets to all panes if advanced pane settings is set.
if (user_access('administer advanced pane settings')) {
$form['css_id'] = array(
'#type' => 'textfield',
Sam Boyer
committed
'#default_value' => isset($conf['css_id']) ? $conf['css_id'] : '',
'#title' => t('CSS ID'),
'#description' => t('CSS ID to apply to this content. This may be blank.'),
'#weight' => 2,
'#size' => 15,
);
$form['css_class'] = array(
'#type' => 'textfield',
Sam Boyer
committed
'#default_value' => isset($conf['css_class']) ? $conf['css_class'] : '',
'#title' => t('CSS class'),
'#description' => t('CSS class to apply to this content. This may be blank.'),
'#weight' => 2,
'#size' => 15,
);
}
return $form;
}
/**
Sam Boyer
committed
* Call any content type-defined add/edit callbacks so that additions
* to $form['configuration'] can be made.
Sam Boyer
committed
* @see panels_content_config_form()
Sam Boyer
committed
* @param object $pane
* The $pane object currently being edited.
* @param $contexts
* A list of possible contexts.
* @param $parents
* The #parents to be used on the form, because some form gadgets need to
* know where they live.
Sam Boyer
committed
* @param string $op
* Either 'add' or 'edit' depending on the operation being performed.
* @param mixed $content_type
* This variable should only be passed if the calling function already has access to the
* relevant content_type data and wants to save a little on performance. If so, then the
* fully-loaded content type plugin declaration array should be passed.
Sam Boyer
committed
function panels_ct_pane_config_form($pane, $contexts, $parents, $op, $content_type = 'content_types') {
if ($function = panels_plugin_get_function($content_type, $pane->type, "$op callback")) {
return $function($pane->subtype, $parents, $pane->configuration);
}
}
/**
Sam Boyer
committed
* Call any add/edit validators defined by the content type.
Sam Boyer
committed
* @see panels_content_config_form_validate()
* @param $type
* The content type. May be the name or an already loaded content type object.
* @param $form
* The actual Forms API form that is being validated.
* @param $form_values
* The actual Forms API values being validated.
Sam Boyer
committed
* @param string $op
* Either 'add' or 'edit' depending on the operation being performed.
Sam Boyer
committed
function panels_ct_pane_validate_form($content_type, $form, $form_values, $op) {
if ($function = panels_plugin_get_function('content_types', $content_type, "$op validate callback")) {
return $function($form, $form_values);
}
}
/**
Sam Boyer
committed
* Call any add/edit submit handlers defined by the content type.
*
* @param string $content_type
* A string value containing the name of the content type.
* @param $form_values
Sam Boyer
committed
* The $form_values['configuration'] sub-array generated by FAPI for the
* overall ct add/edit submit handler.
* @param string $op
* Either 'add' or 'edit' depending on the operation being performed.
Sam Boyer
committed
function panels_ct_pane_submit_form($content_type, $form_values, $op) {
if ($function = panels_plugin_get_function('content_types', $content_type, "$op submit callback")) {
return $function($form_values);
}
}
/**
* Get all of the individual types provided by a given content types. This
* would be all of the blocks for the block type, or all of the views for
* the view type.
*
* @param $type
* The content type to load.
*/
function panels_ct_get_types($type) {
if (is_array($type)) {
$content_type = $type;
}
else {
$content_type = panels_get_content_type($type);
}
$function = $content_type['content_types'];
if (is_array($function)) {
}
if (function_exists($function)) {
return (array) $function();
}
/**
* Get a list of panels available in the layout.
*/
function panels_get_panels($layout, $display) {
if (!empty($layout['panels function']) && function_exists($layout['panels function'])) {
return $layout['panels function']($display, $display->layout_settings);
}
if (!empty($layout['panels'])) {
return $layout['panels'];
}
return array();
}
/**
* Get an array of all available content types that can be fed into the
* display editor for the add content list.
*
* @param $context
* If a context is provided, content that requires that context can apepar.
* @param $has_content
* Whether or not the display will have incoming content
* @param $allowed_types
* An array of allowed content types (pane types) keyed by content_type . '-' . sub_type
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
* @param $default_types
* A default allowed/denied status for content that isn't known about
*/
function panels_get_available_content_types($contexts = NULL, $has_content = FALSE, $allowed_types = NULL, $default_types = NULL) {
$content_types = panels_get_content_types();
$available = array();
foreach ($content_types as $id => $type) {
foreach (panels_ct_get_types($type) as $cid => $cinfo) {
// exclude items that require content if we're saying we don't
// provide it.
if (!empty($cinfo['requires content']) && !$has_content) {
continue;
}
// Check to see if the content type can be used in this context.
if (!empty($cinfo['required context'])) {
if (!panels_context_filter($contexts, $cinfo['required context'])) {
continue;
}
}
// Check to see if the passed-in allowed types allows this content.
if ($allowed_types) {
$key = $id . '-' . $cid;
if (!isset($allowed_types[$key])) {
$allowed_types[$key] = isset($default_types[$id]) ? $default_types[$id] : $default_types['other'];
}
if (!$allowed_types[$key]) {
continue;
}
}
// If we made it through all the tests, then we can use this content.
$available[$id][$cid] = $cinfo;
}
}
return $available;
}
/**
* Get an array of all content types that can be fed into the
* display editor for the add content list, regardless of
* availability.
*
*/
function panels_get_all_content_types() {
$content_types = panels_get_content_types();
$available = array();
foreach ($content_types as $id => $type) {
foreach (panels_ct_get_types($type) as $cid => $cinfo) {
// If we made it through all the tests, then we can use this content.
$available[$id][$cid] = $cinfo;
}
}
return $available;
}
// ------------------------------------------------------------------
// Functions to provide information about a panel or part of a panel.
/**
* Get the content from a given pane.
*
* @param $pane
* The pane to retrieve content from.
* @param $args
* The arguments sent to the display.
* @param $context
* The panels context.
* @param $incoming_content
* Any incoming content if this display is a wrapper.
*/
Earl Miles
committed
function panels_get_pane_content($display, $pane, $args = array(), $context = NULL, $incoming_content = '') {
if (!$context) {
$context = new panels_context;
}
// FIXME misplaced bang?
if (!$incoming_content === '') {
$incoming_content = t('Incoming content will be displayed here.');
}
Earl Miles
committed
$content = FALSE;
$caching = !empty($pane->cache['method']) ? TRUE : FALSE;
if ($caching && ($cache = panels_get_cached_content($display, $args, $context, $pane))) {
$content = $cache->content;
}
else {
Earl Miles
committed
$content = panels_ct_get_content($pane->type, $pane->configuration, $args, $context, $incoming_content);
foreach (module_implements('panels_pane_content_alter') as $module) {
// TODO This makes the third hook invocation on the render path. How badly is this hindering performance?
$function = $module . '_panels_pane_content_alter';
$function($content, $pane, $args, $context);
}
if ($caching) {
Earl Miles
committed
$cache = new panels_cache_object();
$cache->set_content($content);
Earl Miles
committed
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
panels_set_cached_content($cache, $display, $args, $context, $pane);
}
}
return $content;
}
/**
* Get cached content for a given display and possibly pane.
*
* @return
* The cached content, or FALSE to indicate no cached content exists.
*/
function panels_get_cached_content($display, $args, $context, $pane = NULL) {
$method = $pane ? $pane->cache['method'] : $display->cache['method'];
$function = panels_plugin_get_function('cache', $method, 'cache get');
if (!$function) {
return FALSE;
}
$conf = $pane ? $pane->cache['settings'] : $display->cache['settings'];
$cache = $function($conf, $display, $args, $context, $pane);
if (empty($cache)) {
return FALSE;
}
// restore it.
$cache->restore();
return $cache;
}
/**
* Store cached content for a given display and possibly pane.
*/
function panels_set_cached_content($cache, $display, $args, $context, $pane = NULL) {
$method = $pane ? $pane->cache['method'] : $display->cache['method'];
$function = panels_plugin_get_function('cache', $method, 'cache set');
if (!$function) {
return FALSE;
}
$conf = $pane ? $pane->cache['settings'] : $display->cache['settings'];
// snapshot it.
$cache->cache();
return $function($conf, $cache, $display, $args, $context, $pane);
}
/**
* Clear all cached content for a display.
*/
function panels_clear_cached_content($display) {
// Figure out every method we might be using to cache content in this display:
$methods = array();
if (!empty($display->cache['method'])) {
$methods[$display->cache['method']] = TRUE;
}
foreach ($display->content as $pane) {
if (!empty($pane->cache['method'])) {
$methods[$pane->cache['method']] = TRUE;
}
}
foreach (array_keys($methods) as $method) {
$function = panels_plugin_get_function('cache', $method, 'cache clear');
if ($function) {
$function($display);
}
}
}
/**
* An object to hold caching information while it is happening.
*/
class panels_cache_object {
var $content = '';
var $head = NULL;
var $css = NULL;
var $js = NULL;
var $ready = FALSE;
/**
* When constructed, take a snapshot of our existing out of band data.
*/
function panels_cache_object() {
$this->head = drupal_set_html_head();
$this->css = drupal_add_css();
foreach (array('header', 'footer') as $scope) {
Earl Miles
committed
$this->js[$scope] = drupal_add_js(NULL, NULL, $scope);
}
}
/**
* Add content to the cache. This assumes a pure stream;
* use set_content() if it's something else.
*/
function add_content($content) {
$this->content .= $content;
}
function set_content($content) {
$this->content = $content;
}
/**
* Set the object for storing. This overwrites.
*/
function cache() {
Earl Miles
committed
return;
}
Earl Miles
committed
// Simple replacement for head
$this->head = str_replace($this->head, '', drupal_set_html_head());
// Slightly less simple for CSS:
$css = drupal_add_css();
$start = $this->css;
$this->css = array();
foreach ($css as $media => $medias) {
foreach ($medias as $type => $types) {
foreach ($types as $path => $preprocess) {
if (!isset($start[$media][$type][$path])) {
$this->css[] = array($path, $type, $media, $preprocess);
}
}
}
}
Earl Miles
committed
// A little less simple for js
foreach (array('header', 'footer') as $scope) {
Earl Miles
committed
$js[$scope] = drupal_add_js(NULL, NULL, $scope);
Earl Miles
committed
$start = $this->js;
$this->js = array();
foreach ($js as $scope => $scopes) {
foreach ($scopes as $type => $types) {
foreach ($types as $id => $info) {
if (!isset($start[$scope][$type][$id])) {
Earl Miles
committed
switch ($type) {
case 'setting':
$this->js[] = array($info, $type, $scope);
break;
Earl Miles
committed
case 'inline':
$this->js[] = array($info['code'], $type, $scope, $info['defer']);
break;
Earl Miles
committed
default:
$this->js[] = array($id, $type, $scope, $info['defer'], $info['cache']);
}
}
}
}
}
}
Earl Miles
committed
/**
* Restore out of band data saved to cache.
*/
function restore() {
if (!empty($this->head)) {
drupal_set_html_head($this->head);
}
if (!empty($this->css)) {
foreach ($this->css as $args) {
call_user_func_array('drupal_add_css', $args);
}
}
if (!empty($this->js)) {
foreach ($this->js as $args) {
call_user_func_array('drupal_add_js', $args);
}
}
}
}
/**
* Get the title of a pane.
*
* @param $pane
* The $pane object.
*/
function panels_get_pane_title(&$pane, $context = array(), $incoming_content = NULL) {
if (empty($pane->context)) {
$pane->context = panels_pane_select_context($pane, $context);
if ($pane->context === FALSE) {
return t('Does not meet context requirements');
}
}
return panels_ct_get_title($pane->type, $pane->configuration, $pane->context, $incoming_content);
}
// ---------------------------------------------------------------------------
// panels argument helpers
/**
* Get a context from an argument
*/
function panels_argument_get_context($argument, $arg, $empty = FALSE) {
if ($function = panels_plugin_get_function('arguments', $argument['name'], 'context')) {
$context = $function($arg, $argument['argument_settings'], $empty);
Earl Miles
committed
if ($context) {
$context->identifier = $argument['identifier'];
$context->page_title = $argument['title'];
$context->keyword = $argument['keyword'];
return $context;
}
}
}
/**
* Pick which display an argument wants to use
*/
function panels_argument_choose_display($type, $conf, $context) {
if ($function = panels_plugin_get_function('arguments', $type, 'choose display')) {
return $function($conf, $context);
}
}
/**
* Determine a unique context ID for an argument
*/
function panels_argument_context_id($argument) {
return "argument_$argument[name]_$argument[id]";
}
/**
* Retrieve a list of empty contexts for all arguments
*/
function panels_argument_get_contexts($arguments) {
$contexts = array();
foreach ($arguments as $argument) {
$context = panels_argument_get_context($argument, NULL, true);
if ($context) {
$contexts[panels_argument_context_id($argument)] = $context;
}
}
return $contexts;
}
Earl Miles
committed
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
/**
* Load the contexts for a given panel.
*
* @param $arguments
* The array of argument definitions
* @param &$contexts
* The array of existing contexts.
* @param $args
* The arguments to load
*
* @return
* FALSE if an argument wants to 404.
*/
function panels_argument_load_contexts($arguments, &$contexts, $args) {
foreach ($arguments as $argument) {
// pull the argument off the list.
$arg = array_shift($args);
$id = panels_argument_context_id($argument);
// For % arguments embedded in the URL, our context is already loaded.
// There is no need to go and load it again.
if (empty($contexts[$id])) {
if ($context = panels_argument_get_context($argument, $arg)) {
$contexts[$id] = $context;
}
}
else {
$context = $contexts[$id];
}
if ((empty($context) || empty($context->data)) && $argument['default'] == '404') {
return FALSE;
}
}
return TRUE;
}
/**
* Choose a display based upon arguments and loaded contexts.
*
* @param $arguments
* The array of argument definitions
* @param $contexts
Earl Miles
committed
* The array of existing contexts.
*
* @return
* The identification of the display to use
*/
function panels_argument_get_display($arguments, $contexts) {
$display_candidate = NULL;
Earl Miles
committed
foreach ($arguments as $i => $argument) {
Earl Miles
committed
$id = panels_argument_context_id($argument);
if (!empty($contexts[$id]) && !empty($contexts[$id]->data)) {
$context = $contexts[$id];
$d = panels_argument_choose_display($argument['name'], $argument['argument_settings'], $context);
if ($d) {
$display_candidate = "argument_$i" . '-' . $d;
}
}
}
return $display_candidate;
}
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
// ---------------------------------------------------------------------------
// panels relationship helpers
/**
* Fetch all relevant relationships
*
* @param $contexts
* An array of contexts used to figure out which relationships are relevant.
*
* @return
* An array of relationship keys that are relevant for the given set of
* arguments.
*/
function panels_get_relevant_relationships($contexts) {
$relevant = array();
$relationships = panels_get_relationships();
// Go through each relationship
foreach ($relationships as $rid => $relationship) {
// For each relationship, see if there is a context that satisfies it.
if (panels_context_filter($contexts, $relationship['required context'])) {
$relevant[$rid] = $relationship['title'];
}
}
return $relevant;
}
/**
* Fetch all active relationships
*
* @param $relationships
* An keyed array of relationship data including:
* - name: name of relationship
* - context: context id relationship belongs to.
*
* @param $contexts
* A keyed array of contexts used to figure out which relationships
* are relevant. New contexts will be added to this.
*
*/
function panels_relationship_get_contexts($relationships, &$contexts) {
$return = array();
foreach ($relationships as $rdata) {
if (empty($contexts[$rdata['context']])) {
continue;
}
$relationship = panels_get_relationship($rdata['name']);
// If the relationship can't be found or its context can't be found,
// ignore.
if (!$relationship) {
continue;
}
$cid = panels_relationship_context_id($rdata);
if ($context = panels_relationship_get_context($rdata, $contexts[$rdata['context']])) {
$contexts[$cid] = $context;
}
}
}
/**
* Determine a unique context ID for an argument
*/
function panels_relationship_context_id($relationship) {
return "relationship_$relationship[name]_$relationship[id]";
}
/**
* Fetch a context from a relationship, given the context input.
*/
function panels_relationship_get_context($relationship, $arg) {
if ($function = panels_plugin_get_function('relationships', $relationship['name'], 'context')) {
$context = $function($arg, $relationship['relationship_settings']);
if ($context) {
$context->identifier = $relationship['identifier'];
$context->page_title = $relationship['title'];
$context->keyword = $relationship['keyword'];
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
return $context;
}
}
}
// ---------------------------------------------------------------------------
// panels context helpers
/**
* Return a keyed array of context that match the given 'required context'
* filters.
*
* @param $contexts
* A keyed array of all available contexts.
* @param $required
* The required context string or array.
*
* @return
* A keyed array of contexts.
*/
function panels_context_filter($contexts, $required) {
if (is_array($required)) {
$result = array();
foreach ($required as $r) {
$result = array_merge($result, _panels_context_filter($contexts, $r));
}
return $result;
}
return _panels_context_filter($contexts, $required);
}
function _panels_context_filter($contexts, $required) {
// TODO: Multiples
$result = array();
if (is_object($required)) {
$result = $required->filter($contexts);
}
return $result;
}
/**
* Create a select box to choose possible contexts. This only creates a
* selector if there is actually a choice.
*
* @param $contexts
* A keyed array of all available contexts.
* @param $required
* The required context string or array.
*
* @return
* A form element, or NULL if there are no contexts that satisfy the
* requirements.
*/
function panels_context_selector($contexts, $required, $default) {
if (is_array($required)) {
$result = array();
$count = 1;
foreach ($required as $id => $r) {
$result[] = _panels_context_selector($contexts, $r, $default[$id], $count++);