Newer
Older
The Great Git Migration
committed
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
<?php
/**
* @file view.inc
* Provides the view object type and associated methods.
*/
/**
* @defgroup views_objects Objects that represent a View or part of a view.
* @{
* These objects are the core of Views do the bulk of the direction and
* storing of data. All database activity is in these objects.
*/
/**
* An object to contain all of the data to generate a view, plus the member
* functions to build the view query, execute the query and render the output.
*/
class view extends views_db_object {
var $db_table = 'views_view';
var $base_table = 'node';
// State variables
var $built = FALSE;
var $executed = FALSE;
var $args = array();
var $build_info = array();
var $use_ajax = FALSE;
// Where the results of a query will go.
var $result = array();
// pager variables
var $pager = array(
'use_pager' => FALSE,
'items_per_page' => 10,
'element' => 0,
'offset' => 0,
'current_page' => 0,
);
// Places to put attached renderings:
var $attachment_before = '';
var $attachment_after = '';
// Exposed widget input
var $exposed_data = array();
var $exposed_input = array();
// Used to store views that were previously running if we recurse.
var $old_view = array();
/**
* Constructor
*/
function view() {
parent::init();
// Make sure all of our sub objects are arrays.
foreach ($this->db_objects() as $object) {
$this->$object = array();
}
$this->query = new stdClass();
}
/**
* Returns a list of the sub-object types used by this view. These types are
* stored on the display, and are used in the build process.
*/
function display_objects() {
return array('argument', 'field', 'sort', 'filter', 'relationship');
}
/**
* Returns the complete list of dependent objects in a view, for the purpose
* of initialization and loading/saving to/from the database.
*
* Note: In PHP5 this should be static, but PHP4 doesn't support static
* methods.
*/
function db_objects() {
return array('display');
}
/**
* Set the arguments that come to this view. Usually from the URL
* but possibly from elsewhere.
*/
function set_arguments($args) {
$this->args = $args;
}
/**
* Set the page size for ranged or pager queries
*/
function set_items_per_page($items_per_page) {
$this->pager['items_per_page'] = $items_per_page;
if (empty($items_per_page)) {
$this->pager['use_pager'] = FALSE;
}
}
/**
* Change/Set the current page for the pager.
*/
function set_current_page($page) {
$this->pager['current_page'] = $page;
}
/**
* Whether or not the pager should be used.
*/
function set_use_pager($use_pager) {
$this->pager['use_pager'] = $use_pager;
}
/**
* The pager element id to use if use_apger is on
*/
function set_pager_element($pager_element) {
$this->pager['element'] = $pager_element;
}
/**
* How many records to skip. This does not function if use_pager is
* set.
*/
function set_offset($offset) {
$this->pager['offset'] = $offset;
}
/**
* Whether or not AJAX should be used. If AJAX is used, paging,
* tablesorting and exposed filters will be fetched via an AJAX call
* rather than a page refresh.
*/
function set_use_ajax($use_ajax) {
$this->use_ajax = $use_ajax;
}
/**
* Set the exposed filters input to an array. If unset they will be taken
* from $_GET when the time comes.
*/
function set_exposed_input($filters) {
$this->exposed_input = $filters;
}
/**
* Figure out what the exposed input for this view is.
*/
function get_exposed_input() {
// Fill our input either from $_GET or from something previously set on the
// view.
if (empty($this->exposed_input)) {
$this->exposed_input = $_GET;
// unset items that are definitely not our input:
foreach (array('page', 'q') as $key) {
if (isset($this->exposed_input[$key])) {
unset($this->exposed_input[$key]);
}
}
// If we have no input at all, check for remembered input via session.
// If filters are not overridden, store the 'remember' settings on the
// default display. If they are, store them on this display. This way,
// multiple displays in the same view can share the same filters and
// remember settings.
$display_id = ($this->display_handler->is_defaulted('filters')) ? 'default' : $this->current_display;
if (empty($this->exposed_input) && !empty($_SESSION['views'][$this->name][$display_id])) {
$this->exposed_input = $_SESSION['views'][$this->name][$display_id];
}
}
return $this->exposed_input;
}
/**
* Set the display for this view and initialize the display handler.
*/
function init_display($reset = FALSE) {
// The default display is always the first one in the list.
if (isset($this->current_display)) {
return TRUE;
}
// Instantiate all displays
foreach (array_keys($this->display) as $id) {
// Correct for shallow cloning
// Often we'll have a cloned view so we don't mess up each other's
// displays, but the clone is pretty shallow and doesn't necessarily
// clone the displays. We can tell this by looking to see if a handler
// has already been set; if it has, but $this->current_display is not
// set, then something is dreadfully wrong.
if (!empty($this->display[$id]->handler)) {
$this->display[$id] = drupal_clone($this->display[$id]);
unset($this->display[$id]->handler);
}
$this->display[$id]->handler = views_get_plugin('display', $this->display[$id]->display_plugin);
if (!empty($this->display[$id]->handler)) {
// Initialize the new display handler with data.
$this->display[$id]->handler->init($this, $this->display[$id]);
// If this is NOT the default display handler, let it know which is
// since it may well utilize some data from the default.
// This assumes that the 'default' handler is always first. It always
// is. Make sure of it.
if ($id != 'default') {
$this->display[$id]->handler->default_display = &$this->display['default']->handler;
}
}
}
$this->current_display = 'default';
$this->display_handler = &$this->display['default']->handler;
return TRUE;
}
/**
* Get the first display that is accessible to the user.
*
* @param $displays
* Either a single display id or an array of display ids.
*/
function choose_display($displays) {
if (!is_array($displays)) {
return $displays;
}
$this->init_display();
foreach ($displays as $display_id) {
if ($this->display[$display_id]->handler->access()) {
return $display_id;
}
}
return 'default';
}
/**
* Set the display as current.
*
* @param $display_id
* The id of the display to mark as current.
*/
function set_display($display_id = NULL) {
// If we have not already initialized the display, do so. But be careful.
if (empty($this->current_display)) {
$this->init_display();
// If handlers were not initialized, and no argument was sent, set up
// to the default display.
if (empty($display_id)) {
$display_id = 'default';
}
}
$display_id = $this->choose_display($display_id);
// If no display id sent in and one wasn't chosen above, we're finished.
if (empty($display_id)) {
Earl Miles
committed
return FALSE;
The Great Git Migration
committed
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
}
// Ensure the requested display exists.
if (empty($this->display[$display_id])) {
$display_id = 'default';
if (empty($this->display[$display_id])) {
vpr(t('set_display() called with invalid display id @display.', array('@display' => $display_id)));
return FALSE;
}
}
// Set the current display.
$this->current_display = $display_id;
// Ensure requested display has a working handler.
if (empty($this->display[$display_id]->handler)) {
return FALSE;
}
// Set a shortcut
$this->display_handler = &$this->display[$display_id]->handler;
return TRUE;
}
/**
* Find and initialize the style plugin.
*
* Note that arguments may have changed which style plugin we use, so
* check the view object first, then ask the display handler.
*/
function init_style() {
if (isset($this->style_plugin)) {
return is_object($this->style_plugin);
}
if (!isset($this->plugin_name)) {
$this->plugin_name = $this->display_handler->get_option('style_plugin');
$this->style_options = $this->display_handler->get_option('style_options');
}
$this->style_plugin = views_get_plugin('style', $this->plugin_name);
if (empty($this->style_plugin)) {
return FALSE;
}
// init the new style handler with data.
The Great Git Migration
committed
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
$this->style_plugin->init($this, $this->display[$this->current_display], $this->style_options);
return TRUE;
}
/**
* Acquire and attach all of the handlers.
*/
function init_handlers() {
if (empty($this->inited)) {
foreach (views_object_types() as $key => $info) {
$this->_init_handler($key, $info);
}
$this->inited = TRUE;
}
}
/**
* Create a list of base tables eligible for this view. Used primarily
* for the UI. Display must be already initialized.
*/
function get_base_tables() {
$base_tables = array(
$this->base_table => TRUE,
'#global' => TRUE,
);
foreach ($this->display_handler->get_handlers('relationship') as $handler) {
$base_tables[$handler->definition['base']] = TRUE;
}
return $base_tables;
}
/**
* Run the pre_query() on all active handlers.
*/
function _pre_query() {
foreach (views_object_types() as $key => $info) {
$handlers = &$this->$key;
$position = 0;
foreach ($handlers as $id => $handler) {
$handlers[$id]->position = $position;
$handlers[$id]->pre_query();
$position++;
}
}
}
/**
* Attach all of the handlers for each type.
*
* @param $key
* One of 'argument', 'field', 'sort', 'filter', 'relationship'
* @param $info
* The $info from views_object_types for this object.
*/
function _init_handler($key, $info) {
// Load the requested items from the display onto the object.
$this->$key = $this->display_handler->get_handlers($key);
// This reference deals with difficult PHP indirection.
$handlers = &$this->$key;
// Run through and test for accessibility.
foreach ($handlers as $id => $handler) {
if (!$handler->access()) {
unset($handlers[$id]);
}
}
}
/**
* Render the exposed filter form.
*
* This actually does more than that; because it's using FAPI, the form will
* also assign data to the appropriate handlers for use in building the
* query.
*/
function render_exposed_form($block = FALSE) {
// Deal with any exposed filters we may have, before building.
$form_state = array(
'view' => &$this,
'display' => &$this->display_handler->display,
'method' => 'get',
'rerender' => TRUE,
'no_redirect' => TRUE,
);
// Some types of displays (eg. attachments) may wish to use the exposed
// filters of their parent displays instead of showing an additional
// exposed filter form for the attachment as well as that for the parent.
if (!$this->display_handler->displays_exposed() || (!$block && $this->display_handler->get_option('exposed_block'))) {
unset($form_state['rerender']);
}
if (!empty($this->ajax)) {
$form_state['ajax'] = TRUE;
}
$output = drupal_build_form('views_exposed_form', $form_state);
if (!empty($form_state['js settings'])) {
$this->js_settings = $form_state['js settings'];
}
Earl Miles
committed
// Don't render exposed filter form when there's form errors.
// Applies when filters are in a block ("exposed_block" option).
if (form_get_errors() && empty($form_state['rerender'])) {
return NULL;
}
The Great Git Migration
committed
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
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
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
return $output;
}
/**
* Build all the arguments.
*/
function _build_arguments() {
// Initially, we want to build sorts and fields. This can change, though,
// if we get a summary view.
if (empty($this->argument)) {
return TRUE;
}
// build arguments.
$position = -1;
// Create a title for use in the breadcrumb trail.
$title = $this->display_handler->get_option('title');
$this->build_info['breadcrumb'] = array();
$breadcrumb_args = array();
$substitutions = array();
$status = TRUE;
// Iterate through each argument and process.
foreach ($this->argument as $id => $arg) {
$position++;
$argument = &$this->argument[$id];
if ($argument->broken()) {
continue;
}
$argument->set_relationship();
$arg = isset($this->args[$position]) ? $this->args[$position] : NULL;
$argument->position = $position;
if (isset($arg) || $argument->has_default_argument()) {
if (!isset($arg)) {
$arg = $argument->get_default_argument();
// make sure default args get put back.
if (isset($arg)) {
$this->args[$position] = $arg;
}
}
// Set the argument, which will also validate that the argument can be set.
if (!$argument->set_argument($arg)) {
$status = $argument->validate_fail($arg);
break;
}
if ($argument->is_wildcard()) {
$arg_title = $argument->wildcard_title();
}
else {
$arg_title = $argument->get_title();
$argument->query();
}
// Add this argument's substitution
$substitutions['%' . ($position + 1)] = $arg_title;
// Since we're really generating the breadcrumb for the item above us,
// check the default action of this argument.
if ($this->display_handler->uses_breadcrumb() && $argument->uses_breadcrumb()) {
$path = $this->get_url($breadcrumb_args);
if (strpos($path, '%') === FALSE) {
$breadcrumb = !empty($argument->options['breadcrumb'])? $argument->options['breadcrumb'] : $title;
$this->build_info['breadcrumb'][$path] = str_replace(array_keys($substitutions), $substitutions, $breadcrumb);
}
}
// Allow the argument to muck with this breadcrumb.
$argument->set_breadcrumb($this->build_info['breadcrumb']);
// Test to see if we should use this argument's title
if (!empty($argument->options['title'])) {
$title = $argument->options['title'];
}
$breadcrumb_args[] = $arg;
}
else {
// determine default condition and handle.
$status = $argument->default_action();
break;
}
// Be safe with references and loops:
unset($argument);
}
// set the title in the build info.
if (!empty($title)) {
$this->build_info['title'] = str_replace(array_keys($substitutions), $substitutions, $title);
}
// Store the arguments for later use.
$this->build_info['substitutions'] = $substitutions;
return $status;
}
/**
* Do some common building initialization.
*/
function init_query() {
// Create and initialize the query object.
$views_data = views_fetch_data($this->base_table);
$this->base_field = $views_data['table']['base']['field'];
if (!empty($views_data['table']['base']['database'])) {
$this->base_database = $views_data['table']['base']['database'];
}
views_include('query');
$this->query = new views_query($this->base_table, $this->base_field);
}
/**
* Build the query for the view.
*/
function build($display_id = NULL) {
if (!empty($this->built)) {
return;
}
if (empty($this->current_display) || $display_id) {
if (!$this->set_display($display_id)) {
return FALSE;
}
}
Earl Miles
committed
// Let modules modify the view just prior to building it.
The Great Git Migration
committed
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
foreach (module_implements('views_pre_build') as $module) {
$function = $module . '_views_pre_build';
$function($this);
}
// Attempt to load from cache.
// @todo Load a build_info from cache.
$start = views_microtime();
// If that fails, let's build!
$this->build_info = array(
'query' => '',
'count_query' => '',
'query_args' => array(),
);
$this->init_query();
// Call a module hook and see if it wants to present us with a
// pre-built query or instruct us not to build the query for
// some reason.
// @todo: Implement this. Use the same mechanism Panels uses.
// Run through our handlers and ensure they have necessary information.
$this->init_handlers();
// Let the handlers interact with each other if they really want.
$this->_pre_query();
if ($this->display_handler->uses_exposed()) {
$this->exposed_widgets = $this->render_exposed_form();
if (form_set_error() || !empty($this->build_info['abort'])) {
$this->built = TRUE;
// Don't execute the query, but rendering will still be executed to display the empty text.
$this->executed = TRUE;
The Great Git Migration
committed
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
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
return empty($this->build_info['fail']);
}
}
// Build all the relationships first thing.
$this->_build('relationship');
// Build all the filters.
$this->_build('filter');
$this->build_sort = TRUE;
// Arguments can, in fact, cause this whole thing to abort.
if (!$this->_build_arguments()) {
$this->build_time = views_microtime() - $start;
$this->attach_displays();
return $this->built;
}
// Initialize the style; arguments may have changed which style we use,
// so waiting as long as possible is important. But we need to know
// about the style when we go to build fields.
if (!$this->init_style()) {
$this->build_info['fail'] = TRUE;
return FALSE;
}
if ($this->style_plugin->uses_fields()) {
$this->_build('field');
}
// Build our sort criteria if we were instructed to do so.
if (!empty($this->build_sort)) {
// Allow the style handler to deal with sorting.
if ($this->style_plugin->build_sort()) {
$this->_build('sort');
}
// allow the plugin to build second sorts as well.
$this->style_plugin->build_sort_post();
}
// Allow display handler to affect the query:
$this->display_handler->query();
// Allow style handler to affect the query:
$this->style_plugin->query();
if (variable_get('views_sql_signature', FALSE)) {
$this->query->add_field(NULL, "'" . $this->name . ':' . $this->current_display . "'", 'view_name');
}
// Let modules modify the query just prior to finalizing it.
foreach (module_implements('views_query_alter') as $module) {
$function = $module . '_views_query_alter';
$function($this, $this->query);
}
$this->build_info['query'] = $this->query->query();
$this->build_info['count_query'] = $this->query->query(TRUE);
$this->build_info['query_args'] = $this->query->get_where_args();
$this->built = TRUE;
$this->build_time = views_microtime() - $start;
// Attach displays
$this->attach_displays();
Earl Miles
committed
// Let modules modify the view just after building it.
foreach (module_implements('views_post_build') as $module) {
$function = $module . '_views_post_build';
$function($this);
}
The Great Git Migration
committed
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
return TRUE;
}
/**
* Internal method to build an individual set of handlers.
*/
function _build($key) {
$handlers = &$this->$key;
foreach ($handlers as $id => $data) {
if (!empty($handlers[$id]) && is_object($handlers[$id])) {
// Give this handler access to the exposed filter input.
if (!empty($this->exposed_data)) {
$rc = $handlers[$id]->accept_exposed_input($this->exposed_data);
$handlers[$id]->store_exposed_input($this->exposed_data, $rc);
if (!$rc) {
continue;
}
}
$handlers[$id]->set_relationship();
$handlers[$id]->query();
}
}
}
/**
* Execute the view's query.
*/
function execute($display_id = NULL) {
if (empty($this->built)) {
if (!$this->build($display_id)) {
return FALSE;
}
}
if (!empty($this->executed)) {
return TRUE;
}
// Let modules modify the view just prior to executing it.
foreach (module_implements('views_pre_execute') as $module) {
$function = $module . '_views_pre_execute';
$function($this);
}
$query = db_rewrite_sql($this->build_info['query'], $this->base_table, $this->base_field, array('view' => &$this));
$count_query = db_rewrite_sql($this->build_info['count_query'], $this->base_table, $this->base_field, array('view' => &$this));
$args = $this->build_info['query_args'];
vpr($query);
// Check for already-cached results.
if (!empty($this->live_preview)) {
$cache = FALSE;
}
else {
$cache = $this->display_handler->get_cache_plugin();
}
if ($cache && $cache->cache_get('results')) {
vpr('Used cached results');
}
else {
$items = array();
if ($query) {
$replacements = module_invoke_all('views_query_substitutions', $this);
$query = str_replace(array_keys($replacements), $replacements, $query);
$count_query = 'SELECT COUNT(*) FROM (' . str_replace(array_keys($replacements), $replacements, $count_query) . ') count_alias';
if (is_array($args)) {
foreach ($args as $id => $arg) {
$args[$id] = str_replace(array_keys($replacements), $replacements, $arg);
}
}
// Allow for a view to query an external database.
if (isset($this->base_database)) {
db_set_active($this->base_database);
$external = TRUE;
}
$start = views_microtime();
if (!empty($this->pager['items_per_page'])) {
// We no longer use pager_query() here because pager_query() does not
// support an offset. This is fine as we don't actually need pager
// query; we've already been doing most of what it does, and we
// just need to do a little more playing with globals.
if (!empty($this->pager['use_pager']) || !empty($this->get_total_rows)) {
$this->total_rows = db_result(db_query($count_query, $args)) - $this->pager['offset'];
}
if (!empty($this->pager['use_pager'])) {
// dump information about what we already know into the globals
global $pager_page_array, $pager_total, $pager_total_items;
// total rows in query
$pager_total_items[$this->pager['element']] = $this->total_rows;
// total pages
$pager_total[$this->pager['element']] = ceil($pager_total_items[$this->pager['element']] / $this->pager['items_per_page']);
// What page was requested:
$pager_page_array = isset($_GET['page']) ? explode(',', $_GET['page']) : array();
// If the requested page was within range. $this->pager['current_page']
// defaults to 0 so we don't need to set it in an out-of-range condition.
if (!empty($pager_page_array[$this->pager['element']])) {
$page = intval($pager_page_array[$this->pager['element']]);
if ($page > 0 && $page < $pager_total[$this->pager['element']]) {
$this->pager['current_page'] = $page;
}
}
$pager_page_array[$this->pager['element']] = $this->pager['current_page'];
}
$offset = $this->pager['current_page'] * $this->pager['items_per_page'] + $this->pager['offset'];
$result = db_query_range($query, $args, $offset, $this->pager['items_per_page']);
}
else {
$result = db_query($query, $args);
}
$this->result = array();
while ($item = db_fetch_object($result)) {
$this->result[] = $item;
}
// If we already know how many items we have even if we did not run the
// count query, go ahead and set that value:
if (empty($this->pager['items_per_page'])) {
$this->total_rows = count($this->result);
}
The Great Git Migration
committed
if (!empty($external)) {
db_set_active();
}
$this->execute_time = views_microtime() - $start;
}
if ($cache) {
$cache->cache_set('results');
}
}
Earl Miles
committed
// Let modules modify the view just after executing it.
foreach (module_implements('views_post_execute') as $module) {
$function = $module . '_views_post_execute';
$function($this);
}
The Great Git Migration
committed
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
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
$this->executed = TRUE;
}
/**
* Render this view for display.
*/
function render($display_id = NULL) {
$this->execute($display_id);
// Check to see if the build failed.
if (!empty($this->build_info['fail'])) {
return;
}
init_theme();
$start = views_microtime();
if (!empty($this->live_preview) && variable_get('views_show_additional_queries', FALSE)) {
$this->start_query_capture();
}
// Check for already-cached output.
if (!empty($this->live_preview)) {
$cache = FALSE;
}
else {
$cache = $this->display_handler->get_cache_plugin();
}
if ($cache && $cache->cache_get('output')) {
vpr('Used cached output');
}
else {
if ($cache) {
$cache->cache_start();
}
// Initialize the style plugin.
$this->init_style();
$this->style_plugin->pre_render($this->result);
Earl Miles
committed
// Let modules modify the view just prior to rendering it.
The Great Git Migration
committed
855
856
857
858
859
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
938
939
940
941
942
943
944
945
946
947
948
949
foreach (module_implements('views_pre_render') as $module) {
$function = $module . '_views_pre_render';
$function($this);
}
// Let the theme play too, because pre render is a very themey thing.
$function = $GLOBALS['theme'] . '_views_pre_render';
if (function_exists($function)) {
$function($this, $this->display_handler->output, $cache);
}
// Give field handlers the opportunity to perform additional queries
// using the entire resultset prior to rendering.
if ($this->style_plugin->uses_fields()) {
foreach ($this->field as $id => $handler) {
if (!empty($this->field[$id])) {
$this->field[$id]->pre_render($this->result);
}
}
}
$this->display_handler->output = $this->display_handler->render();
if ($cache) {
$cache->cache_set('output');
}
}
if ($cache) {
$cache->post_render($this->display_handler->output);
}
// Let modules modify the view output after it is rendered.
foreach (module_implements('views_post_render') as $module) {
$function = $module . '_views_post_render';
$function($this, $this->display_handler->output, $cache);
}
// Let the theme play too, because post render is a very themey thing.
$function = $GLOBALS['theme'] . '_views_post_render';
if (function_exists($function)) {
$function($this, $this->display_handler->output, $cache);
}
if (!empty($this->live_preview) && variable_get('views_show_additional_queries', FALSE)) {
$this->end_query_capture();
}
$this->render_time = views_microtime() - $start;
return $this->display_handler->output;
}
/**
* Render a specific field via the field ID and the row #.
*/
function render_field($field, $row) {
if (isset($this->field[$field]) && isset($this->result[$row])) {
return $this->field[$field]->advanced_render($this->result[$row]);
}
}
/**
* Execute the given display, with the given arguments.
* To be called externally by whatever mechanism invokes the view,
* such as a page callback, hook_block, etc.
*
* This function should NOT be used by anything external as this
* returns data in the format specified by the display. It can also
* have other side effects that are only intended for the 'proper'
* use of the display, such as setting page titles and breadcrumbs.
*
* If you simply want to view the display, use view::preview() instead.
*/
function execute_display($display_id = NULL, $args = array()) {
if (empty($this->current_display) || $this->current_display != $this->choose_display($display_id)) {
if (!$this->set_display($display_id)) {
return FALSE;
}
}
$this->pre_execute($args);
// Execute the view
$output = $this->display_handler->execute();
$this->post_execute();
return $output;
}
/**
* Preview the given display, with the given arguments.
*
* To be called externally, probably by an AJAX handler of some flavor.
* Can also be called when views are embedded, as this guarantees
* normalized output.
*/
function preview($display_id = NULL, $args = array()) {
Daniel Wehner
committed
if (empty($this->current_display) || ((!empty($display_id)) && $this->current_display != $display_id)) {
The Great Git Migration
committed
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
if (!$this->set_display($display_id)) {
return FALSE;
}
}
$this->preview = TRUE;
$this->pre_execute($args);
// Preview the view.
$output = $this->display_handler->preview();
$this->post_execute();
return $output;
}
/**
* Run attachments and let the display do what it needs to do prior
* to running.
*/
function pre_execute($args = array()) {
$this->old_view[] = views_get_current_view();
views_set_current_view($this);
$display_id = $this->current_display;
// Let modules modify the view just prior to executing it.
foreach (module_implements('views_pre_view') as $module) {
$function = $module . '_views_pre_view';
$function($this, $display_id, $args);
}
// Prepare the view with the information we have, but only if we were
// passed arguments, as they may have been set previously.
if ($args) {
$this->set_arguments($args);
}
// $this->attach_displays();
// Allow the display handler to set up for execution
$this->display_handler->pre_execute();
}
/**
* Unset the current view, mostly.
*/
function post_execute() {
// unset current view so we can be properly destructed later on.
// Return the previous value in case we're an attachment.
if ($this->old_view) {
$old_view = array_pop($this->old_view);