Removing translation directories
[project/ctools.git] / views_content / plugins / content_types / views_panes.inc
CommitLineData
ee19aeef 1<?php
ee19aeef
EM
2
3/**
4 * @file
5 * Content type plugin to allow Views to be exposed as a display type,
6 * leaving most of the configuration on the view.
7 */
8
9/**
0da7776f 10 * Implements hook_ctools_content_types()
ee19aeef
EM
11 */
12function views_content_views_panes_ctools_content_types() {
13 return array(
14 'title' => t('View panes'),
1888fb9a 15 'admin settings' => 'views_content_admin_form',
f6cadac0 16 'js' => array(drupal_get_path('module', 'ctools') . '/js/dependent.js'),
ee19aeef
EM
17 );
18}
19
20/**
21 * Return all content types available.
22 */
23function views_content_views_panes_content_type_content_types($plugin) {
24 $types = array();
25 // It can be fairly intensive to calculate this, so let's cache this in the
26 // cache_views table. The nice thing there is that if views ever change, that
27 // table will always be cleared. Except for the occasional default view, so
28 // we must use the Views caching functions in order to respect Views caching
29 // settings.
30 views_include('cache');
31 $data = views_cache_get('views_content_panes', TRUE);
32 if (!empty($data->data)) {
33 $types = $data->data;
34 }
35
36 if (empty($types)) {
37 $types = array();
38
39 $views = views_get_all_views();
40
41 foreach ($views as $view) {
36ecb4d1
EM
42 if (!empty($view->disabled)) {
43 continue;
44 }
45
ee19aeef
EM
46 $view->init_display();
47
48 foreach ($view->display as $id => $display) {
49 if (empty($display->handler->panel_pane_display)) {
50 continue;
51 }
aeed3fef
SB
52 $info = _views_content_panes_content_type($view, $display);
53 if ($info) {
54 $types[$view->name . '-' . $id] = $info;
55 }
ee19aeef
EM
56 }
57
58 $view->destroy();
59 }
60 views_cache_set('views_content_panes', $types, TRUE);
61 }
62
63 return $types;
64}
65
66/**
67 * Return a single content type.
68 */
69function views_content_views_panes_content_type_content_type($subtype, $plugin) {
70 list($name, $display) = explode('-', $subtype);
71 $view = views_get_view($name);
72 if (empty($view)) {
73 return;
74 }
75
76 $view->set_display($display);
77 $retval = _views_content_panes_content_type($view, $view->display[$display]);
78
79 $view->destroy();
80 return $retval;
81}
82
83function _views_content_panes_content_type($view, $display) {
aeed3fef
SB
84 // Ensure the handler is the right type, as Views will fall back to
85 // the default display if something is broken:
86 if (get_class($display->handler) != 'views_content_plugin_display_panel_pane') {
87 return;
88 }
89
ee19aeef
EM
90 $title = $display->handler->get_option('pane_title');
91 if (!$title) {
a8d2a9ea 92 $title = t('@view: @display', array('@view' => $view->name, '@display' => $display->display_title));
ee19aeef
EM
93 }
94
95 $description = $display->handler->get_option('pane_description');
96 if (!$description) {
97 $description = $view->description;
98 }
99
100 $category = $display->handler->get_option('pane_category');
101 if (!$category['name']) {
102 $category['name'] = t('View panes');
103 }
104
105 $icon = 'icon_views_page.png';
106
107 $contexts = array();
108
109 $arguments = $display->handler->get_argument_input();
110 foreach ($arguments as $argument) {
111 if ($argument['type'] == 'context') {
112 if (strpos($argument['context'], '.')) {
113 list($context, $converter) = explode('.', $argument['context'], 2);
114 }
115 else {
4054c37f
EM
116 // Backwards-compat for before we had a system for delimiting the data
117 // we retrieve out of context objects.
ee19aeef
EM
118 $context = $argument['context'];
119 }
4054c37f
EM
120 $class = 'ctools_context_' . (empty($argument['context_optional']) ? 'required' : 'optional');
121 $contexts[] = new $class($argument['label'], $context);
ee19aeef
EM
122 }
123 }
124
125 $allow = $display->handler->get_option('allow');
126 return array(
127 'title' => $title,
128 'icon' => $icon,
129 'description' => filter_xss_admin($description),
130 'required context' => $contexts,
131 'category' => array($category['name'], $category['weight']),
132 'no title override' => empty($allow['title_override']),
133 );
134}
135
136/**
137 * Output function for the 'views' content type.
138 *
139 * Outputs a view based on the module and delta supplied in the configuration.
140 */
141function views_content_views_panes_content_type_render($subtype, $conf, $panel_args, $contexts) {
142 if (!is_array($contexts)) {
143 $contexts = array($contexts);
144 }
145
146 list($name, $display) = explode('-', $subtype);
147 $view = views_get_view($name);
148 if (empty($view)) {
149 return;
150 }
151
152 $view->set_display($display);
a268f3e4 153 if (!$view->display_handler->access($GLOBALS['user']) || !$view->display_handler->panel_pane_display) {
ee19aeef
EM
154 return;
155 }
156
aeed3fef 157 $view->display_handler->set_pane_conf($conf);
a268f3e4 158
ee19aeef
EM
159 $args = array();
160 $arguments = $view->display_handler->get_option('arguments');
161
a268f3e4 162
ee19aeef
EM
163 $context_keys = array_keys($contexts);
164 foreach ($view->display_handler->get_argument_input() as $id => $argument) {
165 switch ($argument['type']) {
166 case 'context':
167 $key = array_shift($context_keys);
13781140 168 if (isset($contexts [$key])) {
ee19aeef
EM
169 if (strpos($argument['context'], '.')) {
170 list($context, $converter) = explode('.', $argument['context'], 2);
171 $args[] = ctools_context_convert_context($contexts[$key], $converter);
172 }
173 else {
174 $args[] = $contexts[$key]->argument;
175 }
176 }
177 break;
178
179 case 'fixed':
180 $args[] = $argument['fixed'];
181 break;
182
183 case 'panel':
184 $args[] = $panel_args[$argument['panel']];
185 break;
186
187 case 'user':
aeed3fef 188 $args[] = (isset($conf['arguments'][$id]) && $conf['arguments'][$id] !== '') ? $conf['arguments'][$id] : NULL;
ee19aeef
EM
189 break;
190
191 case 'wildcard':
192 // Put in the wildcard.
193 $args[] = isset($arguments[$id]['wildcard']) ? $arguments[$id]['wildcard'] : '*';
194 break;
195
196 case 'none':
197 default:
198 // Put in NULL.
199 // views.module knows what to do with NULL (or missing) arguments
200 $args[] = NULL;
201 break;
202 }
203 }
204
205 // remove any trailing NULL arguments as these are non-args:
206 while (count($args) && end($args) === NULL) {
207 array_pop($args);
208 }
209 $view->set_arguments($args);
210
211 $allow = $view->display_handler->get_option('allow');
212
bf66e96f
SB
213 if (!empty($conf['path'])) {
214 $conf['path'] = ctools_context_keyword_substitute($conf['path'], array(), $contexts);
215 }
ee19aeef 216 if ($allow['path_override'] && !empty($conf['path'])) {
d5070f2d 217 $view->override_path = $conf['path'];
ee19aeef 218 }
91b4d975
EM
219 else if ($path = $view->display_handler->get_option('inherit_panels_path')) {
220 $view->override_path = $_GET['q'];
221 }
ee19aeef
EM
222
223 $block = new stdClass();
224 $block->module = 'views';
225 $block->delta = $view->name . $display;
ee19aeef
EM
226
227 if (($allow['link_to_view'] && !empty($conf['link_to_view'])) ||
228 (!$allow['link_to_view'] && $view->display_handler->get_option('link_to_view'))) {
229 $block->title_link = $view->get_url();
230 }
231
232 // more link
aeed3fef
SB
233 if ($allow['more_link']) {
234 if (empty($conf['more_link'])) {
235 $view->display_handler->set_option('use_more', FALSE);
236 }
237 else {
238 $view->display_handler->set_option('use_more', TRUE);
239 // make sure the view runs the count query so we know whether or not the
240 // more link applies.
241 $view->get_total_rows = TRUE;
242 }
243 }
244
245 if ($allow['items_per_page'] && isset($conf['items_per_page'])) {
246 $view->display_handler->set_option('items_per_page', $conf['items_per_page']);
247 // And here too, which works in Views 3 where the above does not.
248 $view->set_items_per_page($conf['items_per_page']);
249 }
250
251 if ($allow['offset']) {
252 $view->display_handler->set_option('offset', $conf['offset']);
253 $view->set_offset($conf['offset']);
ee19aeef
EM
254 }
255
256 if ($allow['use_pager']) {
fcd9b875
EM
257 // Only set use_pager if they differ, this way we can avoid overwriting the
258 // pager type that Views uses.
aeed3fef
SB
259 // Views 3 version
260 if (method_exists($view, 'init_pager')) {
261 $pager = $view->display_handler->get_option('pager');
262 if ($conf['use_pager'] && ($pager['type'] == 'none' || $pager['type'] == 'some')) {
263 $pager['type'] = 'full';
264 }
265 elseif (!$conf['use_pager'] && $pager['type'] != 'none' && $pager['type'] != 'some') {
266 $pager['type'] = $view->get_items_per_page() || !empty($pager['options']['items_per_page']) ? 'some' : 'none';
267 }
268
269 if ($conf['use_pager']) {
270 if (!isset($pager['options']['id']) || $pager['options']['id'] != $conf['pager_id']) {
271 $pager['options']['id'] = $conf['pager_id'];
272 }
273 }
274
275 $view->display_handler->set_option('pager', $pager);
276 }
277 else {
278 if (!$view->display_handler->get_option('use_pager') || empty($conf['use_pager'])) {
279 $view->display_handler->set_option('use_pager', $conf['use_pager']);
280 }
281
282 $view->display_handler->set_option('pager_element', $conf['pager_id']);
fcd9b875 283 }
ee19aeef 284 }
aeed3fef
SB
285
286 if ($allow['fields_override']) {
287 if ($conf['fields_override']) {
288 $fields = $view->get_items('field');
289 foreach ($conf['fields_override'] as $field => $display) {
290 $fields[$field]['exclude'] = empty($conf['fields_override'][$field]);
291 }
292 $view->display_handler->set_option('fields', $fields);
293
294 }
ee19aeef 295 }
aeed3fef
SB
296
297 if ($allow['exposed_form'] && !empty($conf['exposed'])) {
298 $view->set_exposed_input($conf['exposed']);
ee19aeef
EM
299 }
300
301 $stored_feeds = drupal_add_feed();
302
303 $block->content = $view->preview();
e881ee2f
EM
304 if (empty($view->result) && !$view->display_handler->get_option('empty') && empty($view->style_plugin->definition['even empty'])) {
305 return;
306 }
307
308 $block->title = $view->get_title();
ee19aeef
EM
309
310 if (empty($view->total_rows) || $view->total_rows <= $view->display_handler->get_option('items_per_page')) {
311 unset($block->more);
312 }
313
314 if ((!empty($allow['feed_icons']) && !empty($conf['feed_icons'])) ||
315 (empty($allow['feed_icons']) && $view->display_handler->get_option('feed_icons'))) {
316 $new_feeds = drupal_add_feed();
317 if ($diff = array_diff(array_keys($new_feeds), array_keys($stored_feeds))) {
318 foreach ($diff as $url) {
319 $block->feeds[$url] = $new_feeds[$url];
320 }
321 }
322 }
323
324 return $block;
325}
326
327/**
328 * Returns an edit form for a block.
329 */
a40482ac 330function views_content_views_panes_content_type_edit_form($form, &$form_state) {
ee19aeef 331 $conf = $form_state['conf'];
bf66e96f 332 $contexts = $form_state['contexts'];
ee19aeef
EM
333 // This allows older content to continue to work, where we used to embed
334 // the display directly.
335 list($name, $display_id) = explode('-', $form_state['subtype_name']);
336 $view = views_get_view($name);
337
338 if (empty($view)) {
339 $form['markup'] = array('#value' => t('Broken/missing/deleted view.'));
340 return;
341 }
342
343 $view->set_display($display_id);
344
345 $allow = $view->display_handler->get_option('allow');
346
347 // Provide defaults for everything in order to prevent warnings.
348 if (empty($conf)) {
349 $conf['link_to_view'] = $view->display_handler->get_option('link_to_view');
350 $conf['more_link'] = $view->display_handler->get_option('more_link');
351 $conf['feed_icons'] = FALSE;
352 $conf['use_pager'] = $view->display_handler->get_option('use_pager');
353 $conf['pager_id'] = $view->display_handler->get_option('element_id');
354 $conf['items_per_page'] = $view->display_handler->get_option('items_per_page');
355 $conf['offset'] = $view->display_handler->get_option('offset');
356 $conf['path_override'] = FALSE;
357 $conf['path'] = $view->get_path();
aeed3fef 358 $conf['fields_override'] = $view->display_handler->get_option('fields_override');
ee19aeef
EM
359 }
360
7c959842
EM
361 $form['arguments']['#tree'] = TRUE;
362
ee19aeef
EM
363 foreach ($view->display_handler->get_argument_input() as $id => $argument) {
364 if ($argument['type'] == 'user') {
365 $form['arguments'][$id] = array(
366 '#type' => 'textfield',
367 '#default_value' => isset($conf['arguments'][$id]) ? $conf['arguments'][$id] : '',
368 '#title' => $argument['label'],
369 );
370 }
371 }
aeed3fef
SB
372 if ($allow['link_to_view'] ) {
373 $form['link_to_view'] = array(
374 '#type' => 'checkbox',
375 '#default_value' => isset($conf['link_to_view']) ? $conf['link_to_view'] : $view->display_handler->get_option('link_to_view'),
376 '#title' => t('Link title to page'),
377 );
378 }
379 if ($allow['more_link']) {
380 $form['more_link'] = array(
381 '#type' => 'checkbox',
382 '#default_value' => isset($conf['more_link']) ? $conf['more_link'] : $view->display_handler->get_option('use_more'),
383 '#description' => t('The text of this link will be "@more". This setting can only be modified on the View configuration.', array('@more' => $view->display_handler->use_more_text())),
384 '#title' => t('Provide a "more" link.'),
385 );
386 }
ee19aeef
EM
387
388 if (!empty($allow['feed_icons'])) {
389 $form['feed_icons'] = array(
390 '#type' => 'checkbox',
f6cadac0 391 '#default_value' => !empty($conf['feed_icons']),
ee19aeef
EM
392 '#title' => t('Display feed icons'),
393 );
394 }
395
aeed3fef
SB
396 $view->init_style();
397 if ($allow['fields_override'] && $view->style_plugin->uses_fields()) {
398 $form['fields_override'] = array(
399 '#type' => 'fieldset',
400 '#title' => 'Fields to display',
401 '#collapsible' => TRUE,
402 '#tree' => TRUE,
403 );
404 foreach ($view->display_handler->get_handlers('field') as $field => $handler) {
405 $title = $handler->ui_name();
406 if ($handler->options['label']) {
407 $title .= ' ('. $handler->options['label'] .')';
408 }
409
410 $form['fields_override'][$field] = array(
411 '#type' => 'checkbox',
412 '#title' => $title,
413 '#default_value' => isset($conf['fields_override'][$field]) ? $conf['fields_override'][$field] : TRUE,
414 );
415 }
416 }
417
f6cadac0 418 ctools_include('dependent');
ee19aeef 419 if ($allow['use_pager']) {
ee19aeef
EM
420 $form['use_pager'] = array(
421 '#type' => 'checkbox',
422 '#title' => t('Use pager'),
f6cadac0 423 '#default_value' => isset($conf['use_pager']) ? $conf['use_pager'] : $view->display_handler->get_option('use_pager'),
ee19aeef 424 '#id' => 'use-pager-checkbox',
99f0d601 425 '#prefix' => '<div class="container-inline">',
ee19aeef
EM
426 );
427 $form['pager_id'] = array(
428 '#type' => 'textfield',
f6cadac0 429 '#default_value' => isset($conf['pager_id']) ? $conf['pager_id'] : $view->display_handler->get_option('element_id'),
ee19aeef
EM
430 '#title' => t('Pager ID'),
431 '#size' => 4,
432 '#id' => 'use-pager-textfield',
f6cadac0
EM
433 '#process' => array('ctools_dependent_process'),
434 '#dependency' => array('use-pager-checkbox' => array(1)),
99f0d601 435 '#suffix' => '</div>',
ee19aeef
EM
436 );
437 }
438 if ($allow['items_per_page']) {
439 $form['items_per_page'] = array(
440 '#type' => 'textfield',
f6cadac0 441 '#default_value' => isset($conf['items_per_page']) ? $conf['items_per_page'] : $view->display_handler->get_option('items_per_page'),
ee19aeef
EM
442 '#title' => t('Num items'),
443 '#size' => 4,
444 '#description' => t('Select the number of items to display, or 0 to display all results.'),
445 );
446 }
447 if ($allow['offset']) {
448 $form['offset'] = array(
449 '#type' => 'textfield',
f6cadac0 450 '#default_value' => isset($conf['offset']) ? $conf['offset'] : $view->display_handler->get_option('offset'),
ee19aeef
EM
451 '#title' => t('Offset'),
452 '#size' => 4,
453 '#description' => t('Enter the number of items to skip; enter 0 to skip no items.'),
454 );
455 }
456 if ($allow['path_override']) {
ee19aeef
EM
457 $form['path'] = array(
458 '#type' => 'textfield',
f6cadac0 459 '#default_value' => isset($conf['path']) ? $conf['path'] : $view->get_path(),
ee19aeef
EM
460 '#title' => t('Override path'),
461 '#size' => 30,
462 '#description' => t('If this is set, override the View URL path; this can sometimes be useful to set to the panel URL.'),
463 );
bf66e96f
SB
464 if (!empty($contexts)) {
465 $form['path']['#description'] .= ' ' . t('You may use substitutions in this path.');
466
aeed3fef
SB
467 // Add js for collapsible fieldsets manually
468 drupal_add_js('misc/collapse.js');
469
bf66e96f
SB
470 // We have to create a manual fieldset because fieldsets do not support IDs.
471 // Use 'hidden' instead of 'markup' so that the process will run.
472 $form['contexts_prefix'] = array(
473 '#type' => 'hidden',
474 '#id' => 'edit-path-substitutions',
475 '#prefix' => '<div><fieldset id="edit-path-substitutions" class="collapsed collapsible"><legend>' . t('Substitutions') . '</legend>',
476 );
477
478 $rows = array();
479 foreach ($contexts as $context) {
480 foreach (ctools_context_get_converters('%' . check_plain($context->keyword) . ':', $context) as $keyword => $title) {
481 $rows[] = array(
482 check_plain($keyword),
483 t('@identifier: @title', array('@title' => $title, '@identifier' => $context->identifier)),
484 );
485 }
486 }
487
488 $header = array(t('Keyword'), t('Value'));
489 $form['contexts']['context'] = array('#value' => theme('table', $header, $rows));
490 $form['contexts_suffix'] = array(
491 '#value' => '</fieldset></div>',
492 );
493 }
ee19aeef 494 }
aeed3fef
SB
495
496 if (empty($conf['exposed'])) {
497 $conf['exposed'] = array();
498 }
499
500 if ($allow['exposed_form']) {
501 // If the exposed form is part of pane configuration, get the exposed
502 // form re-tool it for our use.
503 $exposed_form_state = array(
504 'view' => &$view,
505 'display' => &$view->display[$display_id],
506 );
507
508 $view->set_exposed_input($conf['exposed']);
509
510 if (version_compare(views_api_version(), '3', '>=')) {
511 $exposed_form_state['exposed_form_plugin'] = $view->display_handler->get_plugin('exposed_form');
512 }
513 $view->init_handlers();
514 $exposed_form = views_exposed_form($exposed_form_state);
515
516 $form['exposed'] = array(
517 '#tree' => TRUE,
518 );
519
520 foreach ($exposed_form['#info'] as $id => $info) {
521 $form['exposed'][$id] = array(
522 '#type' => 'item',
523 '#id' => 'views-exposed-pane',
524 );
525
526 if (!empty($info['label'])) {
527 $form['exposed'][$id]['#title'] = $info['label'];
528 }
529
530 if (!empty($info['operator']) && !empty($exposed_form[$info['operator']])) {
531 $form['exposed'][$id][$info['operator']] = $exposed_form[$info['operator']];
532 $form['exposed'][$id][$info['operator']]['#parents'] = array('exposed', $info['operator']);
533 $form['exposed'][$id][$info['operator']]['#default_value'] = isset($conf['exposed'][$info['operator']]) ? $conf['exposed'][$info['operator']] : '';
534 }
535 $form['exposed'][$id][$info['value']] = $exposed_form[$info['value']];
536 $form['exposed'][$id][$info['value']]['#parents'] = array('exposed', $info['value']);
537 $form['exposed'][$id][$info['value']]['#default_value'] = isset($conf['exposed'][$info['value']]) ? $conf['exposed'][$info['value']] : '';
538 }
539 }
a40482ac
SB
540
541 return $form;
ee19aeef
EM
542}
543
544/**
545 * Store form values in $conf.
546 */
547function views_content_views_panes_content_type_edit_form_submit(&$form, &$form_state) {
548 // Copy everything from our defaults.
549 $keys = array('link_to_view', 'more_link', 'feed_icons', 'use_pager',
aeed3fef 550 'pager_id', 'items_per_page', 'offset', 'path_override', 'path', 'arguments', 'fields_override', 'exposed');
ee19aeef
EM
551
552 foreach ($keys as $key) {
f6cadac0
EM
553 if (isset($form_state['values'][$key])) {
554 $form_state['conf'][$key] = $form_state['values'][$key];
555 }
ee19aeef
EM
556 }
557}
558
559
560/**
561 * Returns the administrative title for a type.
562 */
563function views_content_views_panes_content_type_admin_title($subtype, $conf, $contexts) {
564 list($name, $display) = explode('-', $subtype);
565 $view = views_get_view($name);
93e4a660 566 if (empty($view) || empty($view->display[$display])) {
ee19aeef
EM
567 return t('Deleted/missing view @view', array('@view' => $name));
568 }
569
570 $view->set_display($display);
571 $title = $view->display_handler->get_option('pane_title');
572 return check_plain($title ? $title : $view->name);
573}
574
575/**
576 * Returns the administrative title for a type.
577 */
578function views_content_views_panes_content_type_admin_info($subtype, $conf, $contexts) {
3162df33
EM
579 $info = array();
580
581 list($view_name, $display_name) = explode('-', $subtype);
582 $view = views_get_view($view_name);
93e4a660
EM
583
584 if (empty($view) || empty($view->display[$display_name])) {
585 return;
586 }
587
3162df33
EM
588 $view->set_display($display_name);
589
590 // Add arguments first
dfd5d58a 591 if (!empty($conf['arguments'])) {
3162df33
EM
592 $keys = array_keys($conf['arguments']);
593 $values = array_values($conf['arguments']);
594 $argument_input = $view->display_handler->get_option('argument_input');
595
93e4a660 596 foreach ($conf['arguments'] as $key => $value) {
3162df33
EM
597 $label = $argument_input[$key]['label'];
598 $info[] = $label .': '. $value;
599 }
600 }
601
602 $block = new stdClass;
93e4a660 603 if ($info) {
3162df33
EM
604 $block->title = array_shift($info);
605
606 $info[] = $view->display_handler->get_option('pane_description');
607 $block->content = theme('item_list', $info);
608 }
93e4a660 609 else {
3162df33 610 $block->title = $view->display_handler->get_option('pane_description');
dfd5d58a 611 $block->content = '';
3162df33
EM
612 }
613 return $block;
ee19aeef 614}