| Commit | Line | Data |
|---|---|---|
| 647d2d1b BB |
1 | <?php |
| 2 | // $Id$ | |
| 3 | ||
| 4 | /** | |
| 5 | * @file | |
| 6 | * GMap style plugin. | |
| 7 | */ | |
| 8 | ||
| 9 | /** | |
| 10 | * Style plugin to render a map. | |
| 11 | * | |
| 12 | * @ingroup views_style_plugins | |
| 13 | */ | |
| 14 | class gmap_plugin_style_gmap extends views_plugin_style { | |
| 15 | /** | |
| 16 | * Set default options | |
| 17 | */ | |
| 18 | function option_definition() { | |
| 19 | $options = parent::option_definition(); | |
| 20 | ||
| 21 | $options['macro'] = array( | |
| 22 | 'default' => '[gmap ]', | |
| 23 | ); | |
| 24 | ||
| 25 | $options['datasource'] = array( | |
| 26 | 'default' => 'location', | |
| 27 | ); | |
| 28 | ||
| 29 | $options['markers'] = array('default' => 'static'); | |
| 63ea4fe4 | 30 | $options['markertype'] = array('default' => 'drupal'); |
| 647d2d1b | 31 | |
| 134619f6 BB |
32 | $options['latfield'] = array('default' => ''); |
| 33 | $options['lonfield'] = array('default' => ''); | |
| 34 | $options['markerfield'] = array('default' => ''); | |
| 35 | ||
| 21147c2c RT |
36 | $options['center_on_nodearg'] = array('default' => 0); |
| 37 | $options['center_on_nodearg_arg'] = array('default' => ''); | |
| 38 | ||
| 39 | $options['highlight_nodearg'] = array('default' => 0); | |
| 40 | $options['highlight_nodearg_arg'] = array('default' => ''); | |
| 41 | $options['highlight_nodearg_color'] = array('default' => '#FF0000'); | |
| 42 | ||
| 43 | $options['tooltipenabled'] = array('default' => 0); | |
| 44 | $options['tooltipfield'] = array('default' => ''); | |
| 45 | ||
| 647d2d1b BB |
46 | return $options; |
| 47 | } | |
| 48 | ||
| 49 | function query() { | |
| 5395ece9 BB |
50 | parent::query(); |
| 51 | ||
| 647d2d1b | 52 | if ($this->options['datasource'] == 'location') { |
| fd5ab78b BB |
53 | $table = $this->view->query->ensure_table('location'); |
| 54 | $this->view->query->add_field($table, 'latitude', 'gmap_lat'); | |
| 55 | $this->view->query->add_field($table, 'longitude', 'gmap_lon'); | |
| 647d2d1b BB |
56 | } |
| 57 | ||
| 58 | if ($this->options['markers'] == 'nodetype') { | |
| 59 | $this->view->query->add_field('node', 'type', 'gmap_node_type'); | |
| 60 | } | |
| 13aaa0f3 BB |
61 | else if ($this->options['markers'] == 'taxonomy') { |
| 62 | $this->view->query->add_field('gmap_taxonomy_node', 'marker', 'gmap_node_marker'); | |
| 63 | } | |
| fcafbc28 BB |
64 | else if ($this->options['markers'] == 'userrole') { |
| 65 | $this->view->query->add_field('users_roles', 'rid', 'gmap_role_marker'); | |
| 66 | } | |
| 5395ece9 BB |
67 | |
| 68 | if (isset($this->row_plugin)) { | |
| 69 | $this->row_plugin->query(); | |
| 70 | } | |
| 647d2d1b BB |
71 | } |
| 72 | ||
| 5395ece9 BB |
73 | /** |
| 74 | * Render the display in this style. | |
| 75 | */ | |
| 647d2d1b | 76 | function render() { |
| 5395ece9 | 77 | |
| 6fc6d362 BB |
78 | if (isset($this->view->live_preview) && $this->view->live_preview) { |
| 79 | return t('GMap views are not compatible with live preview.'); | |
| 80 | } | |
| 81 | ||
| 647d2d1b BB |
82 | if (empty($this->row_plugin)) { |
| 83 | vpr('gmap_plugin_style_gmap: Missing row plugin'); | |
| 84 | return; | |
| 85 | } | |
| 86 | ||
| 2d6c0053 | 87 | $defaults = gmap_defaults(); |
| 134619f6 BB |
88 | $lat_field = 'gmap_lat'; |
| 89 | $lon_field = 'gmap_lon'; | |
| 90 | ||
| 91 | // Determine fieldname for latitude and longitude fields. | |
| 92 | if ($this->options['datasource'] == 'fields') { | |
| ee581070 BB |
93 | $lat_fied_obj = $this->view->display_handler->get_handler('field', $this->options['latfield']); |
| 94 | $lon_field_obj = $this->view->display_handler->get_handler('field', $this->options['lonfield']); | |
| ee581070 BB |
95 | $lat_field = $lat_fied_obj->field_alias; |
| 96 | $lon_field = $lon_field_obj->field_alias; | |
| 134619f6 BB |
97 | } |
| 98 | ||
| 21147c2c RT |
99 | $tooltip_field = ''; |
| 100 | if ($this->options['tooltipenabled']) { | |
| 101 | $tooltip_field_obj = $this->view->display_handler->get_handler('field', $this->options['tooltipfield']); | |
| 102 | $tooltip_field = $tooltip_field_obj->field_alias; | |
| 103 | } | |
| 104 | ||
| 134619f6 BB |
105 | // Determine fieldname for marker field. |
| 106 | if ($this->options['markers'] == 'field') { | |
| ee581070 BB |
107 | $marker_field_obj = $this->view->display_handler->get_handler('field', $this->options['markerfield']); |
| 108 | $marker_field = $marker_field_obj->field_alias; | |
| 134619f6 BB |
109 | } |
| 110 | ||
| 63ea4fe4 | 111 | $markername = isset($this->options['markertype']) ? $this->options['markertype'] : 'drupal'; |
| 647d2d1b BB |
112 | |
| 113 | $markertypes = variable_get('gmap_node_markers', array()); | |
| 114 | if ($this->options['markers'] == 'nodetype') { | |
| 115 | $markertypes = variable_get('gmap_node_markers', array()); | |
| 116 | } | |
| fcafbc28 BB |
117 | else if ($this->options['markers'] == 'userrole') { |
| 118 | $markertypes = variable_get('gmap_role_markers', array(DRUPAL_AUTHENTICATED_RID => 'drupal')); | |
| 119 | } | |
| 647d2d1b BB |
120 | |
| 121 | // Group the rows according to the grouping field, if specified. | |
| 122 | $sets = $this->render_grouping($this->view->result, $this->options['grouping']); | |
| 123 | ||
| 124 | // Render each group separately and concatenate. Plugins may override this | |
| 125 | // method if they wish some other way of handling grouping. | |
| 126 | $output = ''; | |
| 127 | foreach ($sets as $title => $records) { | |
| 128 | $markers = array(); | |
| 129 | $offsets = array(); | |
| 21147c2c RT |
130 | $center_lat = null; |
| 131 | $center_lon = null; | |
| 132 | $center_nid = null; | |
| 133 | $highlight_nid = null; | |
| 134 | ||
| 135 | // We search nid argument used to center map | |
| 136 | if ($this->options['center_on_nodearg'] && $nodehandler = $this->view->display_handler->get_handler('argument', $this->options['center_on_nodearg_arg'])) { | |
| 137 | $center_nid = $nodehandler->get_value(); | |
| 138 | } | |
| 139 | if ($this->options['highlight_nodearg'] && $nodehandler = $this->view->display_handler->get_handler('argument', $this->options['highlight_nodearg_arg'])) { | |
| 140 | $highlight_nid = $nodehandler->get_value(); | |
| 141 | } | |
| 142 | ||
| 5395ece9 BB |
143 | foreach ($records as $row_index => $row) { |
| 144 | $this->view->row_index = $row_index; | |
| 134619f6 BB |
145 | $lat = (float)$row->{$lat_field}; |
| 146 | $lon = (float)$row->{$lon_field}; | |
| 21147c2c | 147 | |
| a5e068aa RT |
148 | // $row->nid is present in node views, views without node as the base table must include the nid field, |
| 149 | // which will be in $row->node_nid if present. | |
| 150 | // If nid for a row is required use $row_nid. | |
| 151 | $row_nid = isset($row->nid) ? $row->nid : (isset($row->node_nid) ? $row->node_nid : NULL); | |
| 152 | ||
| 21147c2c RT |
153 | // If this row will be used as center map then we keep its lon/lat |
| 154 | // If there are multiple points on a single node take the first match | |
| a5e068aa | 155 | if (!empty($center_nid) && !empty($row_nid) && $center_nid == $row_nid && ($center_lon === NULL || $center_lat === NULL)) { |
| 21147c2c RT |
156 | $center_lon = $lon; |
| 157 | $center_lat = $lat; | |
| 158 | } | |
| 159 | ||
| 647d2d1b BB |
160 | if (!empty($lat) && !empty($lon)) { |
| 161 | if ($this->options['markers'] == 'nodetype') { | |
| 63ea4fe4 BB |
162 | if (isset($markertypes[$row->gmap_node_type])) { |
| 163 | $markername = $markertypes[$row->gmap_node_type]; | |
| 164 | } | |
| 647d2d1b | 165 | } |
| 13aaa0f3 | 166 | else if ($this->options['markers'] == 'taxonomy') { |
| 63ea4fe4 BB |
167 | if (!empty($row->gmap_node_marker)) { |
| 168 | $markername = $row->gmap_node_marker; | |
| 169 | } | |
| 13aaa0f3 | 170 | } |
| fcafbc28 BB |
171 | else if ($this->options['markers'] == 'userrole') { |
| 172 | if (!empty($row->gmap_role_marker)) { | |
| 173 | $markername = $markertypes[DRUPAL_AUTHENTICATED_RID]; | |
| 174 | if (isset($markertypes[$row->gmap_role_marker])) { | |
| 175 | $markername = $markertypes[$row->gmap_role_marker]; | |
| 176 | } | |
| 177 | } | |
| 178 | } | |
| 134619f6 BB |
179 | else if ($this->options['markers'] == 'field') { |
| 180 | if (!empty($row->{$marker_field})) { | |
| 181 | $markername = $row->{$marker_field}; | |
| 182 | } | |
| 183 | } | |
| 647d2d1b BB |
184 | if (!isset($offsets[$markername])) { |
| 185 | $offsets[$markername] = 0; | |
| 186 | } | |
| 21147c2c RT |
187 | |
| 188 | $tooltip = ""; | |
| 189 | if ($this->options['tooltipenabled'] && $row->$tooltip_field) { | |
| 190 | $tooltip = $row->$tooltip_field; | |
| 191 | } | |
| 192 | ||
| 2d6c0053 | 193 | $marker = array( |
| 647d2d1b BB |
194 | 'latitude' => $lat, |
| 195 | 'longitude' => $lon, | |
| 196 | 'markername' => $markername, | |
| 197 | 'offset' => $offsets[$markername], | |
| 21147c2c RT |
198 | 'opts' => array( |
| 199 | 'title' => $tooltip, | |
| a5e068aa | 200 | 'highlight' => (!empty($highlight_nid) && !empty($row_nid) && $highlight_nid == $row_nid) ? 1 : 0, |
| 21147c2c RT |
201 | 'highlightcolor' => $this->options['highlight_nodearg_color'], |
| 202 | ), | |
| 647d2d1b | 203 | ); |
| 2d6c0053 RT |
204 | // Marker mode: popup. |
| 205 | if ($defaults['markermode'] == 1) { | |
| 206 | $marker['text'] = $this->row_plugin->render($row); | |
| 207 | } | |
| 208 | // Marker mode: link. | |
| 209 | else if ($defaults['markermode'] == 2) { | |
| 210 | $marker['link'] = url('node/' . $row_nid); | |
| 211 | } | |
| 212 | $markers[] = $marker; | |
| 21147c2c | 213 | |
| 647d2d1b BB |
214 | $offsets[$markername]++; |
| 215 | } | |
| 216 | } | |
| 217 | if (!empty($markers)) { // Don't draw empty maps. | |
| 218 | $map = gmap_parse_macro($this->options['macro']); | |
| 21147c2c RT |
219 | |
| 220 | // If center lon/lat are not empty they are used to center map | |
| 221 | if (!empty($center_lon) && !empty($center_lat)) { | |
| 222 | $map['longitude'] = $center_lon; | |
| 223 | $map['latitude'] = $center_lat; | |
| 224 | } | |
| 225 | ||
| 647d2d1b | 226 | $map['markers'] = $markers; |
| 647d2d1b BB |
227 | $output .= theme($this->theme_functions(), $this->view, $this->options, $map, $title); |
| 228 | } | |
| 229 | } | |
| 21147c2c | 230 | |
| 5395ece9 | 231 | unset($this->view->row_index); |
| 647d2d1b BB |
232 | return $output; |
| 233 | } | |
| 234 | ||
| 235 | /** | |
| 236 | * Render the given style. | |
| 237 | */ | |
| 238 | function options_form(&$form, &$form_state) { | |
| 239 | parent::options_form($form, $form_state); | |
| 21147c2c RT |
240 | |
| 241 | $field_options = array(); | |
| 242 | $fields = $this->display->handler->get_handlers('field'); | |
| 243 | foreach ($fields as $id => $handler) { | |
| 244 | $field_options[$id] = $handler->ui_name(FALSE); | |
| 245 | } | |
| 246 | ||
| 247 | $argument_options = array(); | |
| 248 | $arguments = $this->display->handler->get_handlers('argument'); | |
| 249 | foreach ($arguments as $id => $handler) { | |
| 250 | $argument_options[$id] = $handler->ui_name(FALSE); | |
| 251 | } | |
| 252 | ||
| 647d2d1b | 253 | $form['macro'] = array( |
| ebdb1d8c | 254 | '#type' => 'textarea', |
| 647d2d1b | 255 | '#title' => t('Macro'), |
| ebdb1d8c | 256 | '#rows' => 3, |
| 647d2d1b BB |
257 | '#default_value' => $this->options['macro'], |
| 258 | ); | |
| 259 | ||
| 260 | $form['datasource'] = array( | |
| 134619f6 | 261 | '#type' => 'select', |
| 647d2d1b BB |
262 | '#title' => t('Data Source'), |
| 263 | '#options' => array( | |
| 264 | 'location' => t('Location.module'), | |
| 134619f6 | 265 | 'fields' => t('Choose latitude and longitude fields'), |
| 647d2d1b BB |
266 | //'geocode' => t('Just-in-time geocoding on field named "address"'), |
| 267 | ), | |
| 268 | '#default_value' => $this->options['datasource'], | |
| 269 | '#multiple' => FALSE, | |
| 270 | ); | |
| 271 | ||
| 134619f6 BB |
272 | $form['latfield'] = array( |
| 273 | '#title' => t('Latitude field'), | |
| 274 | '#description' => t('Format must be degrees decimal.'), | |
| 275 | '#type' => 'select', | |
| 21147c2c | 276 | '#options' => $field_options, |
| 134619f6 BB |
277 | '#default_value' => $this->options['latfield'], |
| 278 | '#process' => array('views_process_dependency'), | |
| 279 | '#dependency' => array('edit-style-options-datasource' => array('fields')), | |
| 280 | ); | |
| be03b55e | 281 | |
| 134619f6 BB |
282 | $form['lonfield'] = array( |
| 283 | '#title' => t('Longitude field'), | |
| 284 | '#description' => t('Format must be degrees decimal.'), | |
| 285 | '#type' => 'select', | |
| 21147c2c | 286 | '#options' => $field_options, |
| 134619f6 BB |
287 | '#default_value' => $this->options['lonfield'], |
| 288 | '#process' => array('views_process_dependency'), | |
| 289 | '#dependency' => array('edit-style-options-datasource' => array('fields')), | |
| 290 | ); | |
| 291 | ||
| 647d2d1b | 292 | $form['markers'] = array( |
| 134619f6 | 293 | '#type' => 'select', |
| 647d2d1b BB |
294 | '#title' => t('Marker handling'), |
| 295 | // @@@ Detect view type automatically? | |
| 296 | '#options' => array( | |
| 297 | 'nodetype' => t('By content type (for node views)'), | |
| 13aaa0f3 | 298 | 'taxonomy' => t('By term (for node views)'), |
| fcafbc28 | 299 | 'userrole' => t('By user role (for user views)'), |
| 134619f6 | 300 | 'field' => t('Use marker field'), |
| 647d2d1b BB |
301 | 'static' => t('Use single marker type'), |
| 302 | ), | |
| 303 | '#default_value' => $this->options['markers'], | |
| 304 | ); | |
| 305 | ||
| 134619f6 BB |
306 | $form['markerfield'] = array( |
| 307 | '#type' => 'select', | |
| 308 | '#title' => t('Marker field'), | |
| 309 | '#description' => t('You can use a views field to set the <em>markername</em> property of the markers.'), | |
| 21147c2c | 310 | '#options' => $field_options, |
| 134619f6 BB |
311 | '#default_value' => $this->options['markerfield'], |
| 312 | '#process' => array('views_process_dependency'), | |
| 313 | '#dependency' => array('edit-style-options-markers' => array('field')), | |
| 314 | ); | |
| 315 | ||
| 13aaa0f3 BB |
316 | // Hide the taxonomy handling if gmap_taxonomy.module isn't installed. |
| 317 | if (!module_exists('gmap_taxonomy')) { | |
| 318 | unset($form['markers']['#options']['taxonomy']); | |
| 319 | } | |
| 320 | ||
| 63ea4fe4 BB |
321 | $form['markertype'] = array( |
| 322 | '#type' => 'gmap_markerchooser', | |
| 323 | '#title' => t('Marker / fallback marker to use'), | |
| 324 | '#default_value' => $this->options['markertype'], | |
| 325 | ); | |
| 21147c2c | 326 | |
| be03b55e BB |
327 | $form['center_on_nodearg'] = array( |
| 328 | '#type' => 'checkbox', | |
| 329 | '#title' => t('Center on node argument'), | |
| 330 | '#default_value' => $this->options['center_on_nodearg'], | |
| 331 | '#description' => ($this->view->base_table == 'node') ? t('Note: The view must contain an argument whose value is a node ID.') : t('Note: The view must contain an argument whose value is a node ID.') . '<br />' . t("The view must contain 'Node: nid' as one of its fields because the view type is not 'Node'."), | |
| 332 | ); | |
| 333 | $form['center_on_nodearg_arg'] = array( | |
| 334 | '#title' => t('Argument'), | |
| 335 | '#description' => empty($argument_options) ? t("The value of the selected argument must be a number that matches a node ID. Use the 'Global: Null' argument if you don't want to also restrict results to that node ID. You must have added arguments to the view to use this option.") : t("The selected argument must be a number that matches a node ID. Use the 'Global: Null' argument if you don't want to also restrict results to that node ID."), | |
| 336 | '#type' => 'select', | |
| 337 | '#options' => $argument_options, | |
| 338 | '#default_value' => $this->options['center_on_nodearg_arg'], | |
| 339 | '#process' => array('views_process_dependency'), | |
| 340 | '#dependency' => array('edit-style-options-center-on-nodearg' => array(TRUE)), | |
| 341 | ); | |
| 342 | ||
| 21147c2c RT |
343 | $form['highlight_nodearg'] = array( |
| 344 | '#type' => 'checkbox', | |
| 345 | '#title' => t('Highlight marker for node argument'), | |
| 346 | '#default_value' => $this->options['highlight_nodearg'], | |
| a5e068aa | 347 | '#description' => ($this->view->base_table == 'node') ? t('Note: The view must contain an argument whose value is a node ID.') : t('Note: The view must contain an argument whose value is a node ID.') . '<br />' . t("The view must contain 'Node: nid' as one of its fields because the view type is not 'Node'."), |
| 21147c2c RT |
348 | ); |
| 349 | $form['highlight_nodearg_arg'] = array( | |
| 350 | '#title' => t('Argument'), | |
| 351 | '#description' => empty($argument_options) ? t("The value of the selected argument must be a number that matches a node ID. Use the 'Global: Null' argument if you don't want to also restrict results to that node ID. You must have added arguments to the view to use this option.") : t("The value of the selected argument must be a number that matches a node ID. Use the 'Global: Null' argument if you don't want to also restrict results to that node ID."), | |
| 352 | '#type' => 'select', | |
| 353 | '#options' => $argument_options, | |
| 354 | '#default_value' => $this->options['highlight_nodearg_arg'], | |
| 355 | '#process' => array('views_process_dependency'), | |
| 356 | '#dependency' => array('edit-style-options-highlight-nodearg' => array(TRUE)), | |
| 357 | ); | |
| 358 | $form['highlight_nodearg_color'] = array( | |
| 359 | '#title' => t('Highlight color'), | |
| 360 | '#description' => t("A 6 digit hex color value to use for the highlight. Include preceding hash. Example #FF0000"), | |
| 361 | '#type' => 'textfield', | |
| 362 | '#size' => 7, | |
| 363 | '#maxlength' => 7, | |
| 364 | '#default_value' => $this->options['highlight_nodearg_color'], | |
| 365 | '#process' => array('views_process_dependency'), | |
| 366 | '#dependency' => array('edit-style-options-highlight-nodearg' => array(TRUE)), | |
| 367 | ); | |
| 368 | ||
| 369 | $form['tooltipenabled'] = array( | |
| 370 | '#type' => 'checkbox', | |
| 371 | '#title' => t('Display a tooltip when hovering over markers'), | |
| 372 | '#default_value' => $this->options['tooltipenabled'], | |
| 373 | ); | |
| 374 | $form['tooltipfield'] = array( | |
| 375 | '#title' => t('Tooltip field'), | |
| 376 | '#description' => empty($field_options) ? t("The field's format must be text. You must be using the fields row style and have added fields to the view to use this option.") : t("The field's format must be text."), | |
| 377 | '#type' => 'select', | |
| 378 | '#options' => $field_options, | |
| 379 | '#default_value' => $this->options['tooltipfield'], | |
| 380 | '#process' => array('views_process_dependency'), | |
| 381 | '#dependency' => array('edit-style-options-tooltipenabled' => array(TRUE)), | |
| 382 | ); | |
| 383 | } | |
| 384 | ||
| 385 | /** | |
| 386 | * Validate the options form. | |
| 387 | */ | |
| 388 | function options_validate(&$form, &$form_state) { | |
| 389 | // Check if highlight color is a valid hex color | |
| 390 | if (!preg_match('/^#[a-f0-9]{6}$/i', $form_state['values']['style_options']['highlight_nodearg_color'])) { | |
| 391 | form_error($form['highlight_nodearg_color'], t('Highlight colour must be a valid hex code in the form #FF0000.')); | |
| 392 | } | |
| 647d2d1b BB |
393 | } |
| 394 | } |