plugins.inc 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485
  1. <?php
  2. /**
  3. * @file
  4. *
  5. * Contains helper code for plugins and contexts.
  6. */
  7. /**
  8. * Determine if a pane is visible.
  9. *
  10. * @param $pane
  11. * The pane object to test for access.
  12. * @param $display
  13. * The display object containing the pane object to be tested.
  14. */
  15. function panels_pane_access($pane, $display) {
  16. ctools_include('context');
  17. return ctools_access($pane->access, $display->context);
  18. }
  19. /**
  20. * Get a list of panels available in the layout.
  21. */
  22. function panels_get_regions($layout, $display) {
  23. if ($function = ctools_plugin_get_function($layout, 'regions function')) {
  24. return $function($display, $display->layout_settings, $layout);
  25. }
  26. if (!empty($layout['regions'])) {
  27. return $layout['regions'];
  28. }
  29. return array();
  30. }
  31. /**
  32. * Get cached content for a given display and possibly pane.
  33. *
  34. * @return
  35. * The cached content, or FALSE to indicate no cached content exists.
  36. */
  37. function panels_get_cached_content($display, $args, $context, $pane = NULL) {
  38. // Never use cache on a POST
  39. if (!empty($_POST)) {
  40. return FALSE;
  41. }
  42. $method = $pane ? $pane->cache['method'] : $display->cache['method'];
  43. $function = panels_plugin_get_function('cache', $method, 'cache get');
  44. if (!$function) {
  45. return FALSE;
  46. }
  47. $conf = $pane ? $pane->cache['settings'] : $display->cache['settings'];
  48. $cache = $function($conf, $display, $args, $context, $pane);
  49. if (empty($cache)) {
  50. return FALSE;
  51. }
  52. // restore it.
  53. $cache->restore();
  54. return $cache;
  55. }
  56. /**
  57. * Store cached content for a given display and possibly pane.
  58. */
  59. function panels_set_cached_content($cache, $display, $args, $context, $pane = NULL) {
  60. // Never use cache on a POST
  61. if (!empty($_POST)) {
  62. return FALSE;
  63. }
  64. $method = $pane ? $pane->cache['method'] : $display->cache['method'];
  65. $function = panels_plugin_get_function('cache', $method, 'cache set');
  66. if (!$function) {
  67. return FALSE;
  68. }
  69. $conf = $pane ? $pane->cache['settings'] : $display->cache['settings'];
  70. // snapshot it.
  71. $cache->cache();
  72. return $function($conf, $cache, $display, $args, $context, $pane);
  73. }
  74. /**
  75. * Clear all cached content for a display.
  76. */
  77. function panels_clear_cached_content($display) {
  78. // Figure out every method we might be using to cache content in this display:
  79. $methods = array();
  80. if (!empty($display->cache['method'])) {
  81. $methods[$display->cache['method']] = TRUE;
  82. }
  83. foreach ($display->content as $pane) {
  84. if (!empty($pane->cache['method'])) {
  85. $methods[$pane->cache['method']] = TRUE;
  86. }
  87. }
  88. foreach (array_keys($methods) as $method) {
  89. $function = panels_plugin_get_function('cache', $method, 'cache clear');
  90. if ($function) {
  91. $function($display);
  92. }
  93. }
  94. }
  95. /**
  96. * An object to hold caching information while it is happening.
  97. */
  98. class panels_cache_object {
  99. var $content = '';
  100. var $head = NULL;
  101. var $css = NULL;
  102. var $js = NULL;
  103. var $tokens = NULL;
  104. var $ready = FALSE;
  105. /**
  106. * When constructed, take a snapshot of our existing out of band data.
  107. */
  108. function panels_cache_object() {
  109. $this->head = drupal_add_html_head();
  110. $this->css = drupal_add_css();
  111. $this->tokens = ctools_set_page_token();
  112. $this->js = drupal_add_js();
  113. }
  114. /**
  115. * Add content to the cache. This assumes a pure stream;
  116. * use set_content() if it's something else.
  117. */
  118. function add_content($content) {
  119. $this->content .= $content;
  120. }
  121. function set_content($content) {
  122. $this->content = $content;
  123. }
  124. /**
  125. * Set the object for storing. This overwrites.
  126. */
  127. function cache() {
  128. if ($this->ready) {
  129. return;
  130. }
  131. $this->ready = TRUE;
  132. // Simple replacement for head
  133. $this->head = str_replace($this->head, '', drupal_add_html_head());
  134. // Slightly less simple for CSS:
  135. $css = drupal_add_css();
  136. $start = $this->css;
  137. $this->css = array();
  138. foreach ($css as $name => $data) {
  139. if (!isset($start[$name])) {
  140. $this->css[$name] = $data;
  141. }
  142. }
  143. $js = drupal_add_js();
  144. $start = $this->js;
  145. $this->js = array();
  146. // If there are any differences between the old and the new javascript then
  147. // store them to be added later.
  148. if ($diff = array_diff_assoc($js, $start)) {
  149. $this->js = $diff;
  150. }
  151. // Special case the settings key and get the difference of the data.
  152. if ($settings_diff = array_diff_assoc($js['settings']['data'], $start['settings']['data'])) {
  153. $this->js['settings'] = $settings_diff;
  154. }
  155. // And for tokens:
  156. $tokens = ctools_set_page_token();
  157. foreach ($this->tokens as $token => $argument) {
  158. if (isset($tokens[$token])) {
  159. unset($tokens[$token]);
  160. }
  161. }
  162. $this->tokens = $tokens;
  163. }
  164. /**
  165. * Restore out of band data saved to cache.
  166. */
  167. function restore() {
  168. if (!empty($this->head)) {
  169. drupal_add_html_head($this->head);
  170. }
  171. if (!empty($this->css)) {
  172. foreach ($this->css as $args) {
  173. drupal_add_css($args['data'], $args);
  174. }
  175. }
  176. if (!empty($this->js)) {
  177. foreach ($this->js as $key => $args) {
  178. if ($key !== 'settings') {
  179. drupal_add_js($args['data'], $args);
  180. }
  181. else {
  182. foreach ($args as $setting) {
  183. drupal_add_js($setting, 'setting');
  184. }
  185. }
  186. }
  187. }
  188. if (!empty($this->tokens)) {
  189. foreach ($this->tokens as $token => $key) {
  190. list($type, $argument) = $key;
  191. ctools_set_page_token($token, $type, $argument);
  192. }
  193. }
  194. }
  195. }
  196. /**
  197. * Get the title of a pane.
  198. *
  199. * @deprecated @todo this function should be removed.
  200. *
  201. * @param $pane
  202. * The $pane object.
  203. */
  204. function panels_get_pane_title(&$pane, $context = array(), $incoming_content = NULL) {
  205. ctools_include('content');
  206. return ctools_content_admin_title($pane->type, $pane->subtype, $pane->configuration, $context);
  207. }
  208. /**
  209. * Fetch metadata on a specific layout plugin.
  210. *
  211. * @param $layout
  212. * Name of a panel layout. If the layout name contains a ':' this
  213. * indicates that we need to separate the sublayout out and
  214. * load it individually.
  215. *
  216. * @return
  217. * An array with information about the requested panel layout.
  218. */
  219. function panels_get_layout($layout) {
  220. ctools_include('plugins');
  221. return ctools_get_plugins('panels', 'layouts', $layout);
  222. }
  223. /**
  224. * Fetch metadata for all layout plugins.
  225. *
  226. * @return
  227. * An array of arrays with information about all available panel layouts.
  228. */
  229. function panels_get_layouts() {
  230. ctools_include('plugins');
  231. return ctools_get_plugins('panels', 'layouts');
  232. }
  233. /**
  234. * Fetch metadata for all layout plugins that provide builders.
  235. *
  236. * The layout builders allow reusable layouts be stored in the database and
  237. * exported. Since there are different methods, we are not limiting this
  238. * to just one plugin.
  239. *
  240. * @return
  241. * An array of arrays with information about panel layouts with builders.
  242. */
  243. function panels_get_layout_builders() {
  244. ctools_include('plugins');
  245. $plugins = ctools_get_plugins('panels', 'layouts');
  246. $builders = array();
  247. foreach ($plugins as $name => $plugin) {
  248. if (!empty($plugin['builder'])) {
  249. $builders[$name] = $plugin;
  250. }
  251. }
  252. return $builders;
  253. }
  254. /**
  255. * Fetch metadata on a specific style plugin.
  256. *
  257. * @param $style
  258. * Name of a panel style.
  259. *
  260. * @return
  261. * An array with information about the requested panel style.
  262. */
  263. function panels_get_style($style) {
  264. ctools_include('plugins');
  265. return ctools_get_plugins('panels', 'styles', $style);
  266. }
  267. /**
  268. * Fetch metadata for all style plugins.
  269. *
  270. * @return
  271. * An array of arrays with information about all available panel styles.
  272. */
  273. function panels_get_styles() {
  274. ctools_include('plugins');
  275. return ctools_get_plugins('panels', 'styles');
  276. }
  277. /**
  278. * Fetch metadata on a specific caching plugin.
  279. *
  280. * @param $cache
  281. * Name of a panel cache.
  282. *
  283. * @return
  284. * An array with information about the requested panel cache.
  285. */
  286. function panels_get_cache($cache) {
  287. ctools_include('plugins');
  288. return ctools_get_plugins('panels', 'cache', $cache);
  289. }
  290. /**
  291. * Fetch metadata for all context plugins.
  292. *
  293. * @return
  294. * An array of arrays with information about all available panel caches.
  295. */
  296. function panels_get_caches() {
  297. ctools_include('plugins');
  298. return ctools_get_plugins('panels', 'cache');
  299. }
  300. /**
  301. * Fetch metadata on a specific display renderer plugin.
  302. *
  303. * @return
  304. * An array of arrays with information about the requested panels display
  305. * renderer.
  306. */
  307. function panels_get_display_renderer($renderer) {
  308. ctools_include('plugins');
  309. return ctools_get_plugins('panels', 'display_renderers', $renderer);
  310. }
  311. /**
  312. * Fetch metadata for all display renderer plugins.
  313. *
  314. * @return
  315. * An array of arrays with information about all available panels display
  316. * renderer.
  317. */
  318. function panels_get_display_renderers() {
  319. ctools_include('plugins');
  320. return ctools_get_plugins('panels', 'display_renderers');
  321. }
  322. /**
  323. * Get and initialize the class to handle rendering a display.
  324. *
  325. * @return
  326. * Either the instantiated renderer or FALSE if one could not be found.
  327. */
  328. function panels_get_renderer_handler($plugin, &$display) {
  329. if (is_string($plugin)) {
  330. $plugin = panels_get_display_renderer($plugin);
  331. }
  332. $class = ctools_plugin_get_class($plugin, 'renderer');
  333. if ($class) {
  334. $renderer = new $class();
  335. $renderer->init($plugin, $display);
  336. return $renderer;
  337. }
  338. return FALSE;
  339. }
  340. /**
  341. * Choose a renderer for a display based on a render pipeline setting.
  342. */
  343. function panels_get_renderer($pipeline_name, &$display) {
  344. // Load the pipeline
  345. ctools_include('export');
  346. $pipeline = ctools_export_crud_load('panels_renderer_pipeline', $pipeline_name);
  347. // If we can't, or it has no renderers, default.
  348. if (!$pipeline || empty($pipeline->settings['renderers'])) {
  349. return panels_get_renderer_handler('standard', $display);
  350. }
  351. // Get contexts set on the pipeline:
  352. $contexts = array();
  353. if (!empty($pipeline->settings['contexts'])) {
  354. $contexts = ctools_context_load_contexts($pipeline->settings['context']);
  355. }
  356. // Cycle through our renderers and see.
  357. foreach ($pipeline->settings['renderers'] as $candidate) {
  358. // See if this passes selection criteria.
  359. if (!ctools_access($candidate['access'], $contexts)) {
  360. continue;
  361. }
  362. $renderer = panels_get_renderer_handler($candidate['renderer'], $display);
  363. if (!empty($candidate['options'])) {
  364. $renderer->set_options($candidate['options']);
  365. }
  366. return $renderer;
  367. }
  368. // Fall through. If no renderer is selected, use the standard renderer
  369. return panels_get_renderer_handler('standard', $display);
  370. }
  371. /**
  372. * Sort callback for sorting renderer pipelines.
  373. *
  374. * Sort first by weight, then by title.
  375. */
  376. function _panels_renderer_pipeline_sort($a, $b) {
  377. if ($a->weight == $b->weight) {
  378. if ($a->admin_title == $b->admin_title) {
  379. return 0;
  380. }
  381. return ($a->admin_title < $b->admin_title) ? -1 : 1;
  382. }
  383. return ($a->weight < $b->weight) ? -1 : 1;
  384. }
  385. /**
  386. * Get a list of available renderer pipelines.
  387. *
  388. * This can be used to form a select or radios widget by enabling
  389. * sorting. Descriptions are left in.
  390. */
  391. function panels_get_renderer_pipelines($sort = TRUE) {
  392. ctools_include('export');
  393. $pipelines = ctools_export_crud_load_all('panels_renderer_pipeline');
  394. if ($sort) {
  395. uasort($pipelines, '_panels_renderer_pipeline_sort');
  396. }
  397. return $pipelines;
  398. }
  399. /**
  400. * Get a function from a plugin, if it exists.
  401. *
  402. * @param $plugin
  403. * The type of plugin
  404. * @param $which
  405. * Either the loaded plugin object (or the same data in array form)
  406. * or a string with the name of the desired the specific plugin.
  407. * @param $function_name
  408. * The identifier of the function. For example, 'settings form'.
  409. *
  410. * @return
  411. * The actual name of the function to call, or NULL if the function
  412. * does not exist.
  413. *
  414. * @deprecated All calls to this function should be removed.
  415. */
  416. function panels_plugin_get_function($plugin, $which, $function_name) {
  417. ctools_include('plugins');
  418. if (is_object($which) || is_array($which)) {
  419. return ctools_plugin_get_function($which, $function_name);
  420. }
  421. else {
  422. return ctools_plugin_load_function('panels', $plugin, $which, $function_name);
  423. }
  424. }