/[drupal]/contributions/modules/carto/carto.module
ViewVC logotype

Contents of /contributions/modules/carto/carto.module

Parent Directory Parent Directory | Revision Log Revision Log | View Revision Graph Revision Graph


Revision 1.22 - (show annotations) (download) (as text)
Wed Nov 1 19:39:01 2006 UTC (3 years ago) by openwereld
Branch: MAIN
CVS Tags: HEAD
Changes since 1.21: +16 -9 lines
File MIME type: text/x-php
default googlemap key
1 <?php
2 // $Id: carto.module,v 1.21 2006/10/15 22:37:26 openwereld Exp $
3
4 define( 'DEFAULT_WMS_SEARCH_FIELDS', 'name,title,keywords,abstract' );
5 define( 'DEFAULT_CARTO_WMS_TEASER_MAP', 1 );
6 define( "DEFAULT_GOOGLEMAP_KEY", "ABQIAAAAaypyu9OS8HKVoRqCx3wW2BT2yXp_ZAY8_ufC3CFXhHIE1NvwkxQWOIyCzqRypc-sQQZGpc-Mp-Jf7g" );
7
8 /**
9 * Implementation of hook_help().
10 *
11 * @param $section
12 * A string containing the path info.
13 * @return
14 * The output string which may contain html tags.
15 */
16 function carto_help( $section )
17 {
18 $output = '';
19 //print 'carto_help:' . $section . '<br />';
20 switch( $section )
21 {
22 case 'carto':
23 $output = '<p>... help for carto menu item ...</p>';
24 break;
25 case 'carto/maps':
26 $output = '<p>Nodes that contain mapping objects.</p>';
27 break;
28 case 'carto/wms':
29 $output = '<p>Web mapping services.</p>';
30 break;
31
32 // following texts are shown in /admin/help/carto (in 2 parts)
33 //case 'admin/help/carto': // 1st part
34 // break;
35 case 'admin/help#carto': // 2nd part
36 // return something to prevent message "No help is available for module carto."
37 $output .= '<p>' . t('The Carto module uses mappingwidgets for web mapping functionality.') . '</p>';
38 $output .= '<p>' . t('For more help on mappingwidgets see <a href="http://mappingtools.org/manual/">http://mappingtools.org/manual/</a>.') . '</p>';
39 break;
40
41 case 'admin/modules#description':
42 // description of this module in administer/modules
43 $output = t( "Cartography module; web mapping according to <a href=\"http://www.opengis.org\">OpenGIS</a> standards using the <a href=\"http://mappingwidgets.sourceforge.net\" target=\"_blank\">mappingwidgets</a> package." );
44 break;
45
46 case 'admin/settings/carto':
47 // visible for administer/settings/carto
48 $output = t("Settings for the carto module and for the external packages it requires.");
49 break;
50 /* commented out
51 case 'node/add#carto':
52 // for carto item in 'create content'
53 $output = t( "TODO: something about creating content in the carto module" );
54 break;
55 */
56 case 'admin/block/configure/carto/1':
57 // no help for the configuration of the overview block
58 break;
59 case 'admin/block/configure/carto/2':
60 // no help for the configuration of the legend block
61 break;
62
63 case 'node/add#cartowms':
64 //print 'carto_help:' . $section . '<br />';
65 $output = t('Add a Opengis web mapping service.');
66 break;
67
68 case 'node/add#carto-wfs':
69 $output = t('Add a Opengis web feature service.');
70 break;
71 }
72
73 if (arg(0) == 'node' && is_numeric(arg(1)) && arg(2) == 'layers') {
74 return t('Select the layers to be visible in the wms node. At leas one layer is required, and the selected layers must have a SRS in common.');
75 }
76
77 return $output;
78 }
79
80 /**
81 * Module initialization
82 *
83 * Initialize carto system.
84 */
85 function carto_init( )
86 {
87 // If not in bootstrap, include hooks
88 if( ! _carto_is_bootstrap( ) )
89 {
90 include drupal_get_path('module','carto') . '/carto.inc';
91 }
92 }
93
94 /**
95 * Implementation of hook_exit()
96 */
97 function carto_exit( $destination = NULL )
98 {
99 // cleanup tasks
100 }
101
102 /**
103 * Check whether we are in bootstrap mode
104 */
105 function _carto_is_bootstrap( )
106 {
107 return ! function_exists('drupal_get_headers');
108 }
109
110 function carto_wms_access( $op, $node )
111 {
112 global $user;
113
114 drupal_set_message( 'carto_wms_access: ' . $op );
115 switch( $op )
116 {
117 case 'view':
118 return user_access( 'view wms nodes' );
119 case 'create':
120 return user_access( 'create wms nodes' ) && $user->uid;
121 case 'delete': // own nodes only!
122 return user_access( 'create wms nodes' ) && $user->uid == $node->uid;
123 }
124
125 drupal_set_message( 'carto_wms_access: ' . var_export(func_get_args(),true) );
126 }
127
128 /**
129 * Implementation of hook_perm().
130 */
131 function carto_perm( )
132 {
133 // user permissions
134 return array(
135 'administer carto'
136 , 'create wms nodes' // create or edit wms nodes
137 , 'view wms nodes' // view wms nodes
138 , 'query wms nodes' // query wms nodes
139 , 'select wms layers' // select wms layers (select layers)
140 // , 'create wfs nodes'
141 // , 'access wfs nodes'
142 );
143 }
144
145 /**
146 * Implementation of hook_menu().
147 */
148 function carto_menu( $may_cache )
149 {
150 global $user;
151 $items = array();
152
153 if( $may_cache )
154 {
155 $items[] = array( 'path' => 'node/add/cartowms'
156 , 'title' => t('wms node')
157 , 'access' => user_access('create wms nodes')
158 );
159
160 $items[] = array( 'path' => 'carto'
161 , 'title' => t('carto')
162 , 'access' => user_access('access content')
163 , 'callback' => 'carto_all'
164 , 'type' => MENU_NORMAL_ITEM
165 );
166
167 // nodes with carto-filters
168 $items[] = array( 'path' => 'carto/maps'
169 , 'title' => t('maps')
170 , 'callback' => 'carto_page'
171 , 'access' => user_access('access content')
172 , 'type' => MENU_NORMAL_ITEM
173 );
174 $items[] = array( 'path' => 'carto/maps/' . $user->uid
175 , 'title' => t('my maps')
176 , 'access' => $user->uid > 0 && user_access('access content')
177 , 'type' => MENU_NORMAL_ITEM
178 );
179
180 // nodes of web mapping servers
181 $items[] = array( 'path' => 'carto/wms'
182 , 'title' => t('wms')
183 , 'callback' => 'carto_wms_all'
184 , 'access' => user_access('view wms nodes')
185 , 'type' => MENU_NORMAL_ITEM
186 );
187
188 $items[] = array( 'path' => 'carto/wms/node'
189 //, 'callback' => 'carto_wms_query'
190 , 'access' => user_access('query wms nodes')
191 , 'type' => MENU_CALLBACK
192 );
193
194 $items[] = array( 'path' => 'carto/wms/user/' . $user->uid
195 , 'title' => t('my wms')
196 , 'access' => $user->uid > 0 && user_access('view wms nodes')
197 , 'type' => MENU_NORMAL_ITEM
198 );
199
200 $items[] = array( 'path' => 'carto/feed'
201 , 'title' => t('RSS feed')
202 , 'callback' => 'carto_feed'
203 , 'access' => user_access('access content')
204 , 'type' => MENU_CALLBACK
205 );
206 $items[] = array( 'path' => 'carto/wms/feed'
207 , 'title' => t('RSS feed')
208 , 'callback' => 'carto_feed_wms'
209 , 'access' => user_access('access content')
210 , 'type' => MENU_CALLBACK
211 );
212
213 // settings
214 $items[] = array( 'path' => 'admin/settings/carto'
215 , 'title' => t('carto')
216 , 'callback' => 'drupal_get_form'
217 , 'callback arguments' => 'carto_admin_settings'
218 , 'access' => user_access('administer site configuration')
219 , 'type' => MENU_NORMAL_ITEM
220 );
221
222 // used for ajax functionality?
223 $items[] = array( 'path' => 'carto/action/simple'
224 , 'callback' => 'carto_action_simple'
225 , 'type' => MENU_CALLBACK
226 , 'access' => user_access('access content')
227 );
228 $items[] = array( 'path' => 'carto/action/gpx'
229 , 'callback' => 'carto_action_gpx'
230 , 'type' => MENU_CALLBACK
231 , 'access' => user_access('access content')
232 );
233 }
234 else
235 {
236 if( arg(0) == 'node' && is_numeric(arg(1)) && user_access('select wms layers'))
237 {
238 // Only add the 'select layers'-tab for cartowms pages:
239 $result = db_query(db_rewrite_sql("SELECT n.nid FROM {node} n WHERE n.nid = %d AND n.type = 'cartowms'"), arg(1));
240 if (db_num_rows($result) > 0)
241 {
242 $items[] = array( 'path' => 'node/' . arg(1) . '/layers'
243 , 'title' => t('select layers')
244 , 'callback' => 'drupal_get_form'
245 , 'callback arguments' => array('carto_wms_select_layers', intval(arg(1)))
246 , 'access' => user_access('select wms layers')
247 , 'type' => MENU_LOCAL_TASK
248 );
249 }
250 }
251 //drupal_add_css(drupal_get_path('module', 'system') .'/system.css', 'core');
252 }
253 return $items;
254 }
255
256
257 /**
258 * Implementation of hook_settings().
259 *
260 * After a submit, this function is called by the system module after the
261 * variables have been saved.
262 */
263 function carto_admin_settings( )
264 {
265 $sql = "select count(*) as count from {carto_filter_blocks}";
266 $result = db_query( $sql );
267 $item = db_fetch_object( $result );
268
269 // carto group
270 $form['carto'] = array(
271 '#type' => 'fieldset'
272 , '#title' => t('Carto')
273 , '#collapsible' => TRUE
274 , '#tree' => TRUE
275 );
276 // checkbox to empty cached carto-filters
277 $form['carto']['carto_empty_cache'] = array(
278 '#type' => 'checkbox'
279 , '#title' => t('Empty cached carto-filters (' . $item->count . ').')
280 , '#default_value' => variable_get('carto_empty_cache','0') != '0'
281 , '#description' => t("Check this box to empty the '%table' table"
282 , array('%table' => 'carto_filter_blocks'))
283 );
284 $form['carto']['carto_wms_teaser_map'] = array(
285 '#type' => 'checkbox'
286 , '#title' => t('Show map in teaser of web mapping service')
287 , '#default_value' => variable_get('carto_wms_teaser_map',DEFAULT_CARTO_WMS_TEASER_MAP) != 0
288 , '#description' => t('Check to show map in teaser of web mapping service')
289 );
290
291 // mappingwidgets group
292 $form['mappingwidgets'] = array(
293 '#type' => 'fieldset'
294 , '#title' => t('Mappingwidgets')
295 , '#tree' => TRUE
296 , '#collapsible' => TRUE
297 );
298 $value = variable_get('carto_mappingwidgets_dir',MAPPINGWIDGETS_DIR);
299 $form['mappingwidgets']['carto_mappingwidgets_dir'] = array(
300 '#type' => 'textfield'
301 , '#title' => t('Installation folder')
302 , '#default_value' => $value
303 , '#size' => 80
304 , '#maxlength' => 255
305 , '#description' => t('Location of MappingWidgets package.')
306 );
307 $value = variable_get('carto_mappingwidgets_base_uri','modules/carto/lib/mappingwidgets/htdocs/');
308 $form['mappingwidgets']['carto_mappingwidgets_base_uri'] = array(
309 '#type' => 'textfield'
310 , '#title' => t('Base URI')
311 , '#default_value' => $value
312 , '#size' => 80
313 , '#maxlength' => 255
314 , '#description' => t('URI to base of MappingWidgets package (relative to %host).', array('%host' => $_SERVER['HTTP_HOST']) )
315 );
316
317 // show googlmap api key here only if gmap is not enabled
318 if( ! module_exists('gmap') )
319 {
320 $value = variable_get( 'googlemap_api_key', DEFAULT_GOOGLEMAP_KEY );
321 $form['mappingwidgets']['googlemap_api_key'] = array(
322 '#type' => 'textfield'
323 , '#title' => t('Google map API key')
324 , '#default_value' => $value
325 , '#size' => 108
326 , '#maxlength' => 255
327 );
328 }
329
330 $form['mappingwidgets']['info'] = array(
331 '#type' => 'markup'
332 , '#value' =>
333 'Current values for constant settings in MappingWidgets'
334 . '<br /><strong>MAPPINGWIDGETS_BASE_URI</strong> = ' . MAPPINGWIDGETS_BASE_URI
335 . '<br /><strong>MAPPINGWIDGETS_WIDGETS_URI</strong> = ' . MAPPINGWIDGETS_WIDGETS_URI
336 . '<br /><strong>MAPPINGWIDGETS_TMP_DIR</strong> = ' . MAPPINGWIDGETS_TMP_DIR
337 // . '<br />MAPPINGWIDGETS_ = ' . MAPPINGWIDGETS_
338 );
339
340 // smarty group
341 $value = variable_get('carto_smarty_dir',SMARTY_DIR);
342 $form['smarty'] = array(
343 '#type' => 'fieldset'
344 , '#title' => t('Smarty')
345 , '#tree' => TRUE
346 , '#collapsible' => TRUE
347 );
348 $form['smarty']['carto_smarty_dir'] = array(
349 '#type' => 'textfield'
350 , '#title' => t('Installation folder')
351 , '#default_value' => $value
352 , '#size' => 80
353 , '#maxlength' => 255
354 , '#description' => t('Directory that contains the Smarty.class.php file.')
355 );
356 $form['smarty']['carto_enable_smarty_caching'] = array(
357 '#type' => 'checkbox'
358 , '#title' => t('Enable Smarty caching.')
359 , '#default_value' => variable_get('carto_enable_smarty_caching','1') == '1'
360 , '#description' => t('Check this box to enable Smarty caching.')
361 );
362 $form['smarty']['carto_smarty_force_compile'] = array(
363 '#type' => 'checkbox'
364 , '#title' => t('Force Smarty to compile templates.')
365 , '#default_value' => variable_get('carto_smarty_force_compile','0') == '1'
366 , '#description' => t('Check this box to force Smarty to compile the templates each time.')
367 );
368 $form['smarty']['carto_empty_smarty_cache'] = array(
369 '#type' => 'checkbox'
370 , '#title' => t('Empty Smarty cache.')
371 , '#default_value' => variable_get('carto_empty_smarty_cache','0') != '0'
372 , '#description' => t('Check this box to empty the Smarty cache.')
373 );
374
375 $contribs = array( 'mapscript', 'postgis' );
376 foreach( $contribs as $contrib )
377 {
378 $func = "carto_{$contrib}_get_settings_form";
379 if( function_exists($func) )
380 {
381 $form = array_merge( $form, call_user_func($func) );
382 }
383 }
384 return system_settings_form($form);
385 }
386
387 /**
388 * (drupal 4.7.x)
389 * Validate function for 'carto_settings_form'.
390 */
391 function carto_admin_settings_validate( $form_id, &$form )
392 {
393 if( ! file_exists( $form['mappingwidgets']['carto_mappingwidgets_dir'] . 'MappingWidgets.php' ) )
394 {
395 form_set_error( 'mappingwidgets][carto_mappingwidgets_dir', t('Wrong installation folder. The folder must end with a / and must contain MappingWidgets.php.') );
396 }
397
398 // check relative to $base_url defined in drupal's settings.php
399 global $base_url;
400 $path = $base_url . '/' . $form['mappingwidgets']['carto_mappingwidgets_base_uri'] . 'scripts/MappingWidgets.js';
401 $result = drupal_http_request( $path );
402 if( $result->code != 200 )
403 {
404 global $conf;
405 // form_set_error( '', var_export($conf,true) );
406 drupal_set_message( t("The URI is not correct. A check for '%path' did not return OK.", array('%path' => $path)));
407 // form_set_error( 'mappingwidgets][carto_mappingwidgets_base_uri', t("The URI is not correct. A check for '%path' did not return OK.", array('%path' => $path)) );
408 }
409
410 if( ! file_exists( $form['smarty']['carto_smarty_dir'] . 'Smarty.class.php' ) )
411 {
412 form_set_error( 'smarty][carto_smarty_dir', t('Wrong installation folder. The folder must end with a / and must contain Smarty.class.php.') );
413 }
414 //drupal_set_message( t("carto_settings_form_validate $form_id: " . var_export($form,true)) );
415 }
416
417 /**
418 * (drupal 4.7.x)
419 * Submit function for 'carto_settings_form'.
420 */
421 function carto_admin_settings_submit( $form_id, $values )
422 {
423 if( $values['op'] == t('Reset to defaults') )
424 {
425 variable_del( 'carto_wms_teaser_map' );
426 }
427 else if( $values['op'] == t('Save configuration') )
428 {
429 variable_set( 'carto_wms_teaser_map', $values['carto']['carto_wms_teaser_map'] );
430 }
431
432 if( $values['carto']['carto_empty_cache'] == 1 )
433 {
434 // empty carto_filter_blocks table
435 $sql = "delete from {carto_filter_blocks}";
436 $result = db_query( $sql );
437
438 // set carto_empty_cache to 0 (off)
439 drupal_set_message( t('The carto_filter_blocks table is emptied.') );
440 }
441
442 if( $values['smarty']['carto_empty_smarty_cache'] == 1 )
443 {
444 if( function_exists('get_carto_mapper') )
445 {
446 $cartoSmarty = get_carto_mapper( );
447
448 // clear all cache files
449 $cartoSmarty->clear_all_cache();
450 drupal_set_message( t("The Smarty cache at '%dir' is cleared.", array( '%dir' => $cartoSmarty->cache_dir)) );
451
452 variable_set( 'carto_empty_smarty_cache', '0' );
453 }
454 }
455
456 // keep googlemap_api_key
457 if( $values['mappingwidgets']['googlemap_api_key'] != '' )
458 {
459 variable_set( 'googlemap_api_key', $values['mappingwidgets']['googlemap_api_key'] );
460 }
461
462 variable_set( 'carto_mappingwidgets_dir', $values['mappingwidgets']['carto_mappingwidgets_dir'] );
463 variable_set( 'carto_mappingwidgets_base_uri', $values['mappingwidgets']['carto_mappingwidgets_base_uri'] );
464 variable_set( 'carto_smarty_dir', $values['smarty']['carto_smarty_dir'] );
465 variable_set( 'carto_enable_smarty_caching', $values['smarty']['carto_enable_smarty_caching'] );
466 variable_set( 'carto_smarty_force_compile', $values['smarty']['carto_smarty_force_compile'] );
467
468 // drupal_set_message( 'carto_settings_form_submit( ' . $form_id . '): ' . var_export($values,true) );
469 }
470
471 /**
472 *
473 */
474 function carto_all( )
475 {
476 $output = 'Statistics on maps/wms for user/general. Not implemented yet';
477
478 print theme('page', $output);
479 }
480
481 /**
482 * Menu callback; displays a Drupal page containing recent carto entries.
483 */
484 function carto_page( $uid = 0 )
485 {
486 if( $uid )
487 {
488 carto_page_user($uid);
489 }
490 else
491 {
492 carto_page_last();
493 }
494 }
495
496 /**
497 * Displays a Drupal page containing recent nodes with carto-filter entries of a
498 * given user.
499 */
500 function carto_page_user( $uid )
501 {
502 $user = user_load( array((is_numeric($uid) ? 'uid' : 'name') => $uid, 'status' => 1) );
503
504 if( $user->uid )
505 {
506 drupal_set_title($title = t("%name's maps", array('%name' => $user->name)));
507
508 $output = '';
509
510 $result = pager_query(db_rewrite_sql(
511 "SELECT n.nid, n.sticky, n.created FROM {node} n "
512 . "INNER JOIN {carto_filter_nodes} c ON n.nid = c.nid "
513 . "WHERE n.uid = %d AND n.status = 1 ORDER BY n.sticky DESC, n.created DESC")
514 , variable_get('default_nodes_main', 10), 0, NULL
515 , $user->uid
516 );
517 while( $node = db_fetch_object($result) )
518 {
519 $output .= node_view( node_load( array('nid' => $node->nid)), 1);
520 }
521 $output .= theme('pager', NULL, variable_get('default_nodes_main', 10));
522 $output .= theme('xml_icon', url("carto/feed/$user->uid"));
523
524 drupal_set_html_head('<link rel="alternate" type="application/rss+xml" title="RSS - '. $title .'" href="'. url("carto/feed/$user->uid") .'" />');
525 print theme('page', $output, $title);
526 }
527 else
528 {
529 drupal_not_found();
530 }
531 }
532
533 /**
534 * Displays a Drupal page containing recent carto entries of all users.
535 */
536 function carto_page_last()
537 {
538 global $user;
539
540 $output = '';
541
542 // SELECT n.nid, n.sticky, n.created FROM node n INNER JOIN carto_filter_nodes c ON n.nid = c.nid WHERE n.status = 1 ORDER BY n.sticky DESC, n.created DESC
543 $result = pager_query(db_rewrite_sql(
544 "SELECT n.nid, n.sticky, n.created FROM {node} n "
545 . "INNER JOIN {carto_filter_nodes} c ON n.nid = c.nid "
546 . "WHERE n.status = 1 ORDER BY n.sticky DESC, n.created DESC")
547 , variable_get('default_nodes_main', 10), 0, NULL
548 );
549 while( $node = db_fetch_object($result) )
550 {
551 // $output .= node_view(node_load(array('nid' => $node->nid)), 1);
552 $output .= node_view(node_load($node->nid), 1);
553 }
554 $output .= theme('pager', NULL, variable_get('default_nodes_main', 10));
555 $output .= theme('xml_icon', url('carto/feed'));
556
557 drupal_set_html_head('<link rel="alternate" type="application/rss+xml" title="RSS - maps" href="'. url('carto/feed') .'" />');
558 print theme('page', $output);
559 }
560
561
562 /**
563 * Menu callback; displays an RSS feed containing recent carto entries.
564 */
565 function carto_feed( $uid = 0 )
566 {
567 if( $uid )
568 {
569 carto_feed_user( $uid );
570 }
571 else
572 {
573 carto_feed_last( );
574 }
575 }
576
577 /**
578 * Displays an RSS feed containing recent carto entries of a given user.
579 */
580 function carto_feed_user( $uid = 0 )
581 {
582 global $user;
583
584 if ($uid) {
585 $account = user_load( array('uid' => $uid, 'status' => 1) );
586 }
587 else {
588 $account = $user;
589 }
590
591 $result = db_query_range(db_rewrite_sql(
592 "SELECT n.nid, n.title, n.teaser, n.created, u.name, u.uid FROM {node} n"
593 . " INNER JOIN {carto_filter_nodes} c ON n.nid = c.nid"
594 . " INNER JOIN {users} u ON n.uid = u.uid"
595 . " WHERE n.uid = %d AND n.status = 1"
596 . " ORDER BY n.created DESC")
597 , $uid, 0, 15
598 );
599 $channel['title'] = $account->name ."'s maps";
600 $channel['link'] = url("carto/maps/$uid", NULL, NULL, TRUE);
601 $channel['description'] = $term->description;
602 node_feed( $result, $channel );
603 }
604
605 /**
606 * Displays an RSS feed containing recent carto entries of all users.
607 */
608 function carto_feed_last( )
609 {
610 $result = db_query_range(db_rewrite_sql(
611 "SELECT n.nid, n.title, n.teaser, n.created, u.name, u.uid FROM {node} n"
612 . " INNER JOIN {carto_filter_nodes} c ON n.nid = c.nid"
613 . " INNER JOIN {users} u ON n.uid = u.uid"
614 . " WHERE n.status = 1 ORDER BY n.created DESC")
615 , 0, 15);
616 $channel['title'] = variable_get('site_name', 'drupal') .' maps';
617 $channel['link'] = url('carto/maps', NULL, NULL, TRUE);
618 $channel['description'] = $term->description;
619 node_feed($result, $channel);
620 }
621
622 /**
623 * Implementation of hook_block().
624 *
625 * Displays the most recent 10 carto titles.
626 */
627 function carto_block( $op = 'list', $delta = 0 )
628 {
629 global $user;
630
631 if( $op == 'list' )
632 {
633 $block[0]['info'] = t('Carto - Recent maps');
634 $block[1]['info'] = t('Carto - Overview');
635 $block[2]['info'] = t('Carto - Legend');
636 $block[3]['info'] = t('Carto - Recent WMS');
637 return $block;
638 }
639 else if( $op == 'configure' )
640 {
641 // drupal >= 4.7
642 $form = array();
643 switch( $delta )
644 {
645 case 0:
646 $form['carto_recent_maps'] = array(
647 '#type' => 'textfield'
648 , '#title' => t('Number of maps')
649 , '#default_value' => variable_get('carto_recent_maps',10)
650 , '#size' => 5
651 , '#maxlength' => 5
652 , '#description' => t('Maximum number of recent maps to show.')
653 );
654 break;
655 case 1:
656 $form['carto_overview_width'] = array(
657 '#type' => 'textfield'
658 , '#title' => t('Width')
659 , '#default_value' => variable_get('carto_overview_width',160)
660 , '#size' => 5
661 , '#maxlength' => 5
662 , '#description' => t('Width of the overview block.')
663 );
664 $form['carto_overview_height'] = array(
665 '#type' => 'textfield'
666 , '#title' => t('Height')
667 , '#default_value' => variable_get('carto_overview_height',80)
668 , '#size' => 5
669 , '#maxlength' => 5
670 , '#description' => t('Height of the overview block.')
671 );
672 break;
673 case 2:
674 break;
675 }
676 return $form;
677 }
678 else if( $op == 'save' )
679 {
680 $edit = func_get_arg( 2 );
681 if( $edit )
682 {
683 if( $delta == 0 )
684 {
685 variable_set( 'carto_recent_maps', $edit['carto_recent_maps'] );
686 }
687 else if( $delta == 1 )
688 {
689 variable_set( 'carto_overview_width', $edit['carto_overview_width'] );
690 variable_set( 'carto_overview_height', $edit['carto_overview_height'] );
691 }
692 else if( $delta == 2 )
693 {
694 variable_set( 'carto_legend_width', $edit['carto_legend_width'] );
695 variable_set( 'carto_legend_height', $edit['carto_legend_height'] );
696 }
697 }
698 }
699 else
700 {
701 //print 'op/delta = ' . $op . '/' . $delta . '<br />';
702 if( user_access('access content') )
703 {
704 switch( $delta )
705 {
706 case 0:
707 $block['subject'] = t('Recent maps');
708 $block['content'] = node_title_list(db_query_range(db_rewrite_sql(
709 "SELECT n.nid, n.title, n.created FROM {node} n"
710 . " INNER JOIN {carto_filter_nodes} c ON n.nid = c.nid"
711 . " WHERE n.status = 1 ORDER BY n.created DESC"), 0, variable_get('carto_recent_maps',10)));
712 $block['content'] .= '<div class="more-link">'. l(t('more'), 'carto/maps', array('title' => t('Look at the latest maps.'))) .'</div>';
713 break;
714
715 case 1:
716 // id of this block will be block-carto-1
717 $block['subject'] = t('Overview');
718 $block['content'] = fetch_overview( );
719 break;
720
721 case 2:
722 // id of this block will be block-carto-2
723 $block['subject'] = t('Legend');
724 $block['content'] = fetch_legend( );
725 break;
726
727 case 3:
728 $block['subject'] = t('Recent WMS');
729 $block['content'] = node_title_list(db_query_range(db_rewrite_sql(
730 "SELECT n.nid, n.title, n.created FROM {node} n"
731 . " INNER JOIN {carto_wms_node} c ON n.nid = c.nid"
732 . " WHERE n.status = 1 ORDER BY n.created DESC"), 0, variable_get('carto_recent_maps',10)));
733 $block['content'] .= '<div class="more-link">'. l(t('more'), 'carto/wms', array('title' => t('Look at the latest wms.'))) .'</div>';
734 break;
735 }
736 }
737 return $block;
738 }
739 }
740
741 /**
742 * Implementation of hook_onload().
743 */
744 function carto_onload( )
745 {
746 // return array met string waarin javascript functie aanroepen staan
747 // zoals 'my_javascript_function()'
748 return array( );//"carto_init()" );
749 }
750
751 /**
752 * Implementation of filter
753 * @todo: bedenken hoe een carto node inline gespecificeerd kan worden?
754 * waarschijnlijk: kaart widget met attributen, en standaard knoppenbalk erbij?
755 * Blok wordt aangegeven door: <div ...class="carto-section">???</div>
756 * @todo: change settings in bracket_type ({} or <> or []), tag (default: carto-filter)
757 */
758 function carto_filter( $op, $delta = 0, $format = -1, $text = '' )
759 {
760 if( $op == 'list' )
761 {
762 return array(
763 0 => t('Expand mappingwidgets inside carto filter blocks')
764 );
765 }
766
767 if( $delta == 0 )
768 {
769 switch( $op )
770 {
771 case 'settings':
772 $form['carto_filter'] = array(
773 '#type' => 'fieldset'
774 , '#title' => t('Carto filter')
775 );
776 $form['carto_filter']['carto_filter_expr'] = array(
777 '#type' => 'textfield'
778 , '#title' => t('Filter block expression')
779 , '#default_value' => variable_get('carto_filter_expr', "/\{carto-filter\}(.*)\{\/carto-filter\}/Us" )
780 , '#size' => 60
781 , '#maxlength' => 255
782 , '#description' => t('Enter the regular expression for the carto filter blocks.')
783 );
784 return $form;
785
786 case 'description':
787 return t('Mappingwidgets within carto-filter blocks are expanded to dynamic maps.');
788
789 case 'no cache':
790 // Return true if caching should be disabled for this filter.
791 return TRUE;
792
793 case 'prepare':
794 // unescape here?
795 return $text;
796
797 case 'process':
798 if( ! function_exists('get_carto_mapper') )
799 {
800 trigger_error( t('Carto module is not configured correctly. Check your \'config.inc\' file.'), E_USER_ERROR );
801 return "";
802 }
803 $cartoSmarty = get_carto_mapper( );
804
805 $output = "";
806 $output .= preg_replace_callback( variable_get('carto_filter_expr',"/\{carto-filter\}(.*)\{\/carto-filter\}/Us"), "fetch_widgets", $text );
807
808 return $output;
809 }
810 }
811 }
812
813
814 /**
815 *
816 */
817 function carto_filter_tips( $delta, $format, $long = false )
818 {
819 if( $long )
820 {
821 return t('<p>Between a starting {carto-filter} tag and an ending {/carto-filter} tag,
822 {mappingwidgets ..} can be defined. For more examples see
823 <a href="http://mappingwidgets.sourceforge.net" target="_blank">mappingwidgets</a>.
824 </p>
825 ');
826 }
827 else
828 {
829 return t("You can define {mappingwidget}'s in between {carto-filter} and {/carto-filter} tags.");
830 }
831 }
832
833
834 /**
835 * Insert html/javascript code just before the closing body tag.
836 */
837 function carto_footer( )
838 {
839 global $base_url;
840
841 if( ! function_exists('get_carto_mapper') ) return NULL;
842 $cartoSmarty = get_carto_mapper( );
843
844 $output = "\n<!-- carto_footer output -->\n";
845 // define drupal base_url and 'base href' in javascript
846 $output .= "<script type=\"text/javascript\">
847 //<!--
848 var drupal_base_url = '{$base_url}';
849 var drupal_base_href = '{$base_url}/';
850 //-->
851 </script>
852 ";
853
854 if( $cartoSmarty->get_widget_count('BaseMap') - $cartoSmarty->get_widget_count('OverviewMap') > 0 )
855 {
856 // target map present
857 if( $cartoSmarty->get_widget_count("OverviewMap") > 0 )
858 {
859 // get overviewmap widget(s)
860 $ow = $cartoSmarty->get_widgets( "OverviewMap" );
861 if( ! is_array( $ow ) )
862 $ows = array( $ow );
863 else
864 $ows = $ow;
865
866 foreach( $ows as $ow )
867 {
868 /* */
869 // adapt overviewmap widget definition for target map
870 $mapwidget = $cartoSmarty->find_map_widget( );
871 if( $mapwidget )
872 {
873 if( isset($ow->extent) )
874 $extent = $ow->extent;
875 else if( isset($mapwidget->fullextent) )
876 $extent = $mapwidget->fullextent;
877 else
878 $extent = $mapwidget->extent;
879
880 $output .= $cartoSmarty->fetch( "text:" . "{mappingwidget type=\"OverviewMap\""
881 . " id=\"{$ow->id}\""
882 . " extent=\"" . $extent . "\""
883 . " image=\"" . $mapwidget->overview . "\""
884 . " nohtml=\"true\"}" );
885 }
886 else // defaults
887 {
888 if( isset($ow->extent) )
889 $extent = $ow->extent;
890 else
891 $extent = "-180,-90,180,90";
892
893 $output .= $cartoSmarty->fetch( "text:" . "{mappingwidget type=\"OverviewMap\""
894 . " id=\"{$ow->id}\""
895 . " extent=\"$extent\""
896 . " image=\"images/world.png\""
897 . " nohtml=\"true\"}" );
898 }
899 // @todo: use wms request for maxextent (for overviewlayers)??
900 /* */
901 }
902 }
903
904 // get the final code (3 ways)
905 // $output .= $cartoSmarty->get_final_code( );
906 $output .= get_carto_filter_html( 'final_code', "{\$mappingWidgetManager->get_final_code()}" );
907 // $output .= get_carto_filter_html( 'final_code', "{mappingwidgets_javascript_includes}{mappingwidgets_javascript_objects}" );
908 }
909 else
910 {
911 if( $cartoSmarty->caching )
912 {
913 // When using the cache, the widget count equals 0!! Check if the
914
915 // check if resource is available in carto_filter_blocks table?
916 // $cfid = drupal_get_path_alias($_GET['q']) . ":" . $cartoSmarty->language->_currentLocale . ':final_code';
917 $cfid = drupal_get_normal_path($_GET['q']) . ":" . $cartoSmarty->language->_currentLocale . ':final_code';
918
919 $sql = "select 'x' from {carto_filter_blocks} where cfid = '%s'";
920 $result = db_query( $sql, $cfid );
921 if( db_num_rows( $result ) > 0 )
922 {
923 $output .= $cartoSmarty->fetch( 'carto:' . $cfid );
924 }
925 }
926
927 // no target maps present -> don't show overview/legend blocks
928 if( $cartoSmarty->get_widget_count("OverviewMap") + $cartoSmarty->get_widget_count('SimpleLegend') != 0 )
929 {
930 // if only overview/legend block(s) -> hide it
931 $output .= <<<EOT
932 <script type="text/javascript">
933 //<!--
934 function trimString (str) {
935 str = this != window ? this : str;
936 return str.replace(/^\s+/g, '').replace(/\s+\$/g, '');
937 }
938 String.prototype.trim = trimString;
939
940 for( i = 1; i <= 2; i++ )
941 {
942 var blk = document.getElementById( 'block-carto-' + i );
943 if( blk && blk.parentNode )
944 {
945 var par = blk.parentNode;
946 // remove block
947 blk.parentNode.removeChild( blk );
948 if( par.id == 'sidebar-left' || par.id == 'sidebar-right' )
949 {
950 /* if no content is left in sidebar, remove it */
951 if( trimString(par.innerHTML) == '' )
952 {
953 par.parentNode.removeChild( par );
954 }
955 }
956 }
957 }
958 //-->
959 </script>
960 EOT;
961 }
962 }
963 return $output;
964 }
965
966
967 /**
968 * fetch_widgets gets the html for the current carto filter block
969 */
970 function fetch_widgets( $matches )
971 {
972 static $count = 0;
973
974 $output = get_carto_filter_html( "carto-filter-{$count}", $matches[1] );
975
976 $count += 1;
977 return $output;
978 }
979
980
981 /**
982 * Get html for the standard overview block.
983 */
984 function fetch_overview( )
985 {
986 return get_carto_filter_html( "overview"
987 , "{mappingwidget type=\"OverviewMap\""
988 . " id=\"carto_overview\""
989 . " width=\"" . variable_get('carto_overview_width',160)
990 . "\" height=\"" . variable_get('carto_overview_height',80)
991 . "\" target=\"default\"}"
992 );
993 }
994
995
996 /**
997 * Get html for the standard legend block.
998 */
999 function fetch_legend( )
1000 {
1001 return get_carto_filter_html( "legend"
1002 , "{mappingwidget type=\"SimpleLegend\""
1003 . " id=\"carto_legend\""
1004 . " width=\"" . variable_get('carto_legend_width',160)
1005 . "\" height=\"" . variable_get('carto_legend_height',240)
1006 . "\" target=\"default\"}"
1007 );
1008 }
1009
1010
1011 function get_carto_filter_html( $id, $text )
1012 {
1013 static $calls = 0;
1014
1015 if( ! function_exists('get_carto_mapper') ) return NULL;
1016 $cartoSmarty = get_carto_mapper( );
1017
1018 $output = "";
1019 if( $calls++ == 0 )
1020 {
1021 $first = false;
1022
1023 // drupal < 4.7
1024 // $output = $cartoSmarty->get_first_code();
1025
1026 // add javascript files to head (drupal >= 4.7)
1027 $js_files = $cartoSmarty->get_javascript_includes();
1028 foreach( $js_files as $file )
1029 {
1030 // remove base_path from file path because drupal_add_js function
1031 // will preprend it again
1032 if( strpos( $file, base_path() ) === 0 )
1033 $file = substr( $file, strlen(base_path()) );
1034 drupal_add_js( $file );
1035 }
1036 }
1037 /* *
1038 if( drupal_get_path_alias($_GET['q']) != $_REQUEST['q'] )
1039 {
1040 // @todo: not clear why this needed to prevent multiple entries in table
1041 // e.g. for path 'node/1' an extra 'node'/'' would have been made??!
1042 return;
1043 }
1044 /* */
1045
1046 // $cfid = $_REQUEST['q'] . ':' . $id;
1047
1048 // determine carto filter id (cfid) from (normal) path, locale, and filter id
1049 $cfid = drupal_get_normal_path($_GET['q']) . ':'
1050 . $cartoSmarty->language->_currentLocale . ':' . $id;
1051
1052 // Replace html characters placed e.g. by htmlarea module
1053 // See htmlEncode function in htmlarea.js: &amp; &lt; &gt; &nbsp; &quot;
1054 $text = str_replace( '&quot;', '"', $text );
1055 $text = str_replace( '&nbsp;', ' ', $text );
1056 $text = str_replace( '&amp;', '&', $text );
1057 $crc = crc32( $text );
1058
1059 $sql = "select crc, content from {carto_filter_blocks} where cfid = '%s'";
1060 $result = db_query( $sql, $cfid );
1061 if( db_num_rows( $result ) == 0 )
1062 {
1063 /* if cfid is not found -> insert new record */
1064 $sql = "insert into {carto_filter_blocks}( cfid, crc, time, content ) values( '%s', %d, %d, '%s' )";
1065 db_query( $sql, $cfid, $crc, time(), $text );
1066 }
1067 else
1068 {
1069 $item = db_fetch_object( $result );
1070 if( $crc != $item->crc )
1071 {
1072 // update crc/content
1073 $sql = "update {carto_filter_blocks} set crc = %d, time = %d, content = '%s' where cfid = '%s'";
1074 db_query( $sql, $crc, time(), $text, $cfid );
1075 }
1076 }
1077 $content = $cartoSmarty->fetch( "carto:" . $cfid );
1078
1079 if( $id == 'final_code' )
1080 $output .= $content;
1081 else
1082 $output .= "<div id=\"{$id}\" class=\"block-carto-filter\">\n" . $content . "</div>\n";
1083
1084 return $output;
1085 }
1086
1087 /**
1088 * Implementation of hook_nodeapi().
1089 *
1090 * Allows modules to react to actions affecting all kinds of nodes.
1091 */
1092 function carto_nodeapi( &$node, $op, $teaser, $page )
1093 {
1094 switch( $op )
1095 {
1096 case 'load':
1097 // additional data to load?
1098 break;
1099
1100 case 'insert':
1101 // insert record into carto_filter_nodes
1102 $count = preg_match_all( variable_get('carto_filter_expr',"/\{carto-filter\}(.*)\{\/carto-filter\}/Us"), $node->body, $matches );
1103 if( $count > 0 )
1104 {
1105 db_query( "INSERT INTO {carto_filter_nodes} (nid,numblocks) VALUES (%d,%d)", $node->nid, $count );
1106 }
1107 break;
1108
1109 case 'update':
1110 // check if in db (NULL when not found)
1111 $previous = db_fetch_object(db_query('SELECT numblocks FROM {carto_filter_nodes} WHERE nid = %d', $node->nid));
1112 // determine if node contains carto-filter blocks
1113
1114 // @todo: AND that the carto filter is active!! ($node->format)
1115 $hasFilter = db_fetch_object(db_query("SELECT format FROM filters WHERE format = %d AND module = 'carto'", $node->format ));
1116 if( ! $hasFilter )
1117 {
1118 // no carto filter -> remove from carto_filter_nodes
1119 if( $previous )
1120 {
1121 db_query( 'DELETE FROM {carto_filter_nodes} WHERE nid = %d', $node->nid );
1122 }
1123 }
1124 else
1125 {
1126 $count = preg_match_all( variable_get('carto_filter_expr',"/\{carto-filter\}(.*)\{\/carto-filter\}/Us"), $node->body, $matches );
1127 if( $count > 0 )
1128 {
1129 if( ! $previous )
1130 db_query( "INSERT INTO {carto_filter_nodes} (nid,numblocks) VALUES (%d,%d)", $node->nid, $count );
1131 else if( $previous->numblocks != $count )
1132 db_query( "UPDATE {carto_filter_nodes} set numblocks = %d where nid = %d", $count, $node->nid );
1133 }
1134 else if( $previous )
1135 {
1136 db_query( 'DELETE FROM {carto_filter_nodes} WHERE nid = %d', $node->nid );
1137 }
1138 }
1139 break;
1140
1141 case 'delete':
1142 // check for $node->format?!
1143 $previous = db_fetch_object(db_query('SELECT numblocks FROM {carto_filter_nodes} WHERE nid = %d', $node->nid));
1144 if( $previous )
1145 {
1146 // remove record from carto_filter_nodes
1147 db_query( 'DELETE FROM {carto_filter_nodes} WHERE nid = %d', $node->nid );
1148 }
1149 break;
1150
1151 case 'view':
1152 // @todo: actions to take when viewing nodes with carto filters?
1153 // executed on view and preview of a node (but at new preview not yet
1154 // present in database!)
1155 $previous = db_fetch_object(db_query('SELECT numblocks FROM {carto_filter_nodes} WHERE nid = %d', $node->nid));
1156 if( $previous )
1157 {
1158 // if node has latitude and longitude properties, do something with it
1159 // print 'this node contains carto filter blocks: ' . var_export($previous,true);
1160 }
1161 else
1162 {
1163 // print 'this node contains NO carto filter blocks: ' . var_export($previous,true);
1164 }
1165 break;
1166 }
1167 }
1168
1169 /**
1170 * Implementation of hook_node_info (drupal 4.7).
1171 * This function replaces hook_node_name() and hook_node_types() from 4.6.
1172 */
1173 function carto_node_info()
1174 {
1175 return array(
1176 'cartowms' => array( 'name' => t('web mapping service')
1177 , 'module' => 'carto_wms'
1178 , 'description' => t('A web mapping service is a page that displays selected layers of an OpenGIS web mapping service. The node can also be used as a proxy to make e.g. map requests to that service.')
1179 //, 'has_body' => TRUE
1180 //, 'body_label' => t('Capabilities')
1181 )
1182 );
1183 }
1184
1185 function carto_wms_form( &$node )
1186 {
1187 // print 'carto_wms_form: ' . var_export(array('POST'=>$_POST,'capabilities.len'=>strlen($_SESSION['capabilities'])),true) . '<hr>';
1188 $type = node_get_types('type', $node);
1189
1190 $form['title'] = array( '#type' => 'textfield'
1191 , '#title' => check_plain($type->title_label)//t('Title')
1192 , '#required' =>