first commit
[step2_drupal.git] / views / plugins / views_plugin_style.inc
blobea9b902ac667841744813f9eaf712cafd8b2339d
1 <?php
2 // $Id: views_plugin_style.inc,v 1.5 2009/03/24 22:22:11 merlinofchaos Exp $
3 /**
4  * Base class to define a style plugin handler.
5  */
6 class views_plugin_style extends views_plugin {
7   /**
8    * Initialize a style plugin.
9    *
10    * @param $view
11    * @param $display
12    * @param $options
13    *   The style options might come externally as the style can be sourced
14    *   from at least two locations. If it's not included, look on the display.
15    */
16   function init(&$view, &$display, $options = NULL) {
17     $this->view = &$view;
18     $this->display = &$display;
20     // Overlay incoming options on top of defaults
21     $this->unpack_options($this->options, isset($options) ? $options : $display->handler->get_option('style_options'));
23     if ($this->uses_row_plugin() && $display->handler->get_option('row_plugin')) {
24       $this->row_plugin = $display->handler->get_plugin('row');
25     }
27     $this->options += array(
28       'grouping' => '',
29     );
31     $this->definition += array(
32       'uses grouping' => TRUE,
33     );
34   }
36   function destroy() {
37     parent::destroy();
39     if (isset($this->row_plugin)) {
40       $this->row_plugin->destroy();
41     }
42   }
44   /**
45    * Return TRUE if this style also uses a row plugin.
46    */
47   function uses_row_plugin() {
48     return !empty($this->definition['uses row plugin']);
49   }
51   /**
52    * Return TRUE if this style also uses fields.
53    */
54   function uses_fields() {
55     // If we use a row plugin, ask the row plugin. Chances are, we don't
56     // care, it does.
57     if ($this->uses_row_plugin() && !empty($this->row_plugin)) {
58       return $this->row_plugin->uses_fields();
59     }
60     // Otherwise, maybe we do.
61     return !empty($this->definition['uses fields']);
62   }
64   function option_definition() {
65     $options = parent::option_definition();
66     $options['grouping'] = array('default' => '');
67     return $options;
68   }
70   function options_form(&$form, &$form_state) {
71     // Only fields-based views can handle grouping.  Style plugins can also exclude
72     // themselves from being groupable by setting their "use grouping" definiton
73     // key to FALSE.
74     // @TODO: Document "uses grouping" in docs.php when docs.php is written.
75     if ($this->uses_fields() && $this->definition['uses grouping']) {
76       $options = array('' => t('<None>'));
77       foreach ($this->display->handler->get_handlers('field') as $field => $handler) {
79         if ($label = $handler->label()) {
80           $options[$field] = $label;
81         }
82         else {
83           $options[$field] = $handler->ui_name();
84         }
85       }
87       // If there are no fields, we can't group on them.
88       if (count($options) > 1) {
89         $form['grouping'] = array(
90           '#type' => 'select',
91           '#title' => t('Grouping field'),
92           '#options' => $options,
93           '#default_value' => $this->options['grouping'],
94           '#description' => t('You may optionally specify a field by which to group the records. Leave blank to not group.'),
95         );
96       }
97     }
98   }
100   /**
101    * Called by the view builder to see if this style handler wants to
102    * interfere with the sorts. If so it should build; if it returns
103    * any non-TRUE value, normal sorting will NOT be added to the query.
104    */
105   function build_sort() { return TRUE; }
107   /**
108    * Allow the style to do stuff before each row is rendered.
109    *
110    * @param $result
111    *   The full array of results from the query.
112    */
113   function pre_render($result) {
114     if (!empty($this->row_plugin)) {
115       $this->row_plugin->pre_render($result);
116     }
117   }
119   /**
120    * Render the display in this style.
121    */
122   function render() {
123     if ($this->uses_row_plugin() && empty($this->row_plugin)) {
124       vpr('views_plugin_style_default: Missing row plugin');
125       return;
126     }
128     // Group the rows according to the grouping field, if specified.
129     $sets = $this->render_grouping($this->view->result, $this->options['grouping']);
131     // Render each group separately and concatenate.  Plugins may override this
132     // method if they wish some other way of handling grouping.
133     $output = '';
134     foreach ($sets as $title => $records) {
135       if ($this->uses_row_plugin()) {
136         $rows = array();
137         foreach ($records as $label => $row) {
138           $rows[] = $this->row_plugin->render($row);
139         }
140       }
141       else {
142         $rows = $records;
143       }
145       $output .= theme($this->theme_functions(), $this->view, $this->options, $rows, $title);
146     }
147     return $output;
148   }
150   /**
151    * Group records as needed for rendering.
152    *
153    * @param $records
154    *   An array of records from the view to group.
155    * @param $grouping_field
156    *   The field id on which to group.  If empty, the result set will be given
157    *   a single group with an empty string as a label.
158    * @return
159    *   The grouped record set.
160    */
161   function render_grouping($records, $grouping_field = '') {
162     $sets = array();
163     if ($grouping_field) {
164       foreach ($records as $row) {
165         $grouping = '';
166         // Group on the rendered version of the field, not the raw.  That way,
167         // we can control any special formatting of the grouping field through
168         // the admin or theme layer or anywhere else we'd like.
169         if (isset($this->view->field[$grouping_field])) {
170           $grouping = $this->view->field[$grouping_field]->theme($row);
171           if ($this->view->field[$grouping_field]->options['label']) {
172             $grouping = $this->view->field[$grouping_field]->options['label'] . ': ' . $grouping;
173           }
174         }
175         $sets[$grouping][] = $row;
176       }
177     }
178     else {
179       // Create a single group with an empty grouping field.
180       $sets[''] = $records;
181     }
182     return $sets;
183   }
185   function validate() {
186     $errors = parent::validate();
188     if ($this->uses_row_plugin()) {
189       $plugin = $this->display->handler->get_plugin('row');
190       if (empty($plugin)) {
191         $errors[] = t('Style @style requires a row style but the row plugin is invalid.', array('@style' => $this->definition['title']));
192       }
193     }
194     return $errors;
195   }
197   function query() {
198     parent::query();
199     if (isset($this->row_plugin)) {
200       $this->row_plugin->query();
201     }
202   }