5 * Function definitions for geotaxonomy module.
9 * Implementation of specific hook_form_alter().
10 * Adds option of geo storage to vocab edit page.
12 function geotaxonomy_form_taxonomy_form_vocabulary_alter(&$form, &$form_state) {
13 $vid = $form['vid']['#value'];
14 $form['settings']['geotaxonomy_status'] = array(
15 '#type' => 'checkbox',
16 '#title' => t('Store geo data for this vocabulary'),
17 '#default_value' => variable_get("geotaxonomy_$vid", 0),
18 '#description' => t('Allows latitude and longitude data to be stored with terms of this taxonomy.'),
20 $form['#submit'][] = 'geotaxonomy_form_vocabulary_submit';
24 * Additional submit handler for vocabulary form to accomodate geo setting.
26 function geotaxonomy_form_vocabulary_submit($form, &$form_state) {
27 $vid = $form_state['values']['vid'];
28 variable_set("geotaxonomy_$vid", $form_state['values']['geotaxonomy_status']);
32 * Implementation of specific hook_form_alter().
33 * Allows entry of geo data on term edit page.
35 function geotaxonomy_form_taxonomy_form_term_alter(&$form, &$form_state) {
36 $vid = $form['vid']['#value'];
37 if (!variable_get("geotaxonomy_".
$vid, 0)) {
40 $form['submit']['#weight'] = $form['submit']['#weight'] + 1;
41 $form['delete']['#weight'] = $form['delete']['#weight'] + 1;
43 $latlon = geotaxonomy_get_term($form['tid']['#value']);
44 $form['geotaxonomy'] = array(
45 '#type' => 'fieldset',
46 '#title' => t("Geotaxonomy data"),
49 $form['geotaxonomy']['lat'] = array (
50 '#type' => 'textfield',
51 '#title' => t('Latitude'),
52 '#default_value' => $latlon['lat'],
54 $form['geotaxonomy']['lon'] = array (
55 '#type' => 'textfield',
56 '#title' => t('Longitude'),
57 '#default_value' => $latlon['lon'],
60 $form['geotaxonomy']['bound_top'] = array (
61 '#type' => 'textfield',
62 '#title' => t('Bound Top'),
63 '#default_value' => $latlon['bound_top'],
65 $form['geotaxonomy']['bound_right'] = array (
66 '#type' => 'textfield',
67 '#title' => t('Bound Right'),
68 '#default_value' => $latlon['bound_right'],
71 $form['geotaxonomy']['bound_bottom'] = array (
72 '#type' => 'textfield',
73 '#title' => t('Bound Bottom'),
74 '#default_value' => $latlon['bound_bottom'],
76 $form['geotaxonomy']['bound_left'] = array (
77 '#type' => 'textfield',
78 '#title' => t('Bound Left'),
79 '#default_value' => $latlon['bound_left'],
82 // Helper map for lat/lon if OpenLayers UI is available.
83 // Not compatiable with current openlayers module.
84 if (module_exists('openlayers_ui')) {
85 drupal_add_js(drupal_get_path('module', 'geotaxonomy') .
'/js/geotaxonomy.admin.js', 'module');
87 $default_preset = openlayers_preset_load(variable_get('openlayers_default_preset', 'default'));
88 $defaults = $default_preset->data
;
90 $form['geotaxonomy']['helpmap'] = array(
91 '#value' => '<div class="form-item geotaxonomy-latlon-helpmap" style="display:block">'.
geotaxonomy_form_latlon_map($defaults) .
'</div>'
97 * Create LatLon Helper Map.
99 function geotaxonomy_form_latlon_map($defaults = array()) {
100 // Pass variables etc. to javascript
101 $pass_values = array(
102 'geotaxonomy' => array(),
104 drupal_add_js($pass_values, 'setting');
106 // Set up our map to help set lat and lon
107 // This map will always be projected as 4326 and use just the default map preset
108 $centermap_def = array(
109 'id' => 'geotaxonomy-latlon-helpmap',
110 'projection' => '4326',
111 'default_layer' => 'openlayers_default_wms',
115 'lat' => ($defaults['center']['lat']) ?
$defaults['center']['lat'] : 0,
116 'lon' => ($defaults['center']['lon']) ?
$defaults['center']['lon'] : 0,
117 'zoom' => ($defaults['center']['zoom']) ?
$defaults['center']['zoom'] : 2,
120 'openlayers_default_wms',
122 'behaviors' => array(
123 'openlayers_behavior_navigation' => array(),
126 'displayProjection' => '4326',
127 'maxResolution' => '1.40625',
128 'maxExtent' => array(
136 return openlayers_render_map($centermap_def);
141 * Implementation of hook_node_views().
143 function geotaxonomy_views_api() {
146 'path' => drupal_get_path('module', 'geotaxonomy') .
'/views',
151 * Little API helper function to retrieve geo data for a given term.
153 function geotaxonomy_get_term($tid) {
154 return db_fetch_array(db_query("SELECT lat, lon, bound_top, bound_right, bound_bottom, bound_left FROM term_geo WHERE tid = %d", $tid));
158 * Implementation of hook_taxonomy().
160 function geotaxonomy_taxonomy($op = NULL
, $type = NULL
, $term = NULL
){
161 if($type =='term' && $term && variable_get("geotaxonomy_".
$term['vid'], 0)) {
164 db_query("DELETE FROM {term_geo} WHERE tid = %d", $term['tid']);
167 db_query("DELETE FROM {term_geo} WHERE tid = %d", $term['tid']);
170 'tid' => $term['tid'],
171 'lat' => is_numeric($term['lat']) ?
$term['lat'] : NULL
,
172 'lon' => is_numeric($term['lon']) ?
$term['lon'] : NULL
,
173 'bound_top' => is_numeric($term['bound_top']) ?
$term['bound_top'] : NULL
,
174 'bound_right' => is_numeric($term['bound_right']) ?
$term['bound_right'] : NULL
,
175 'bound_bottom' => is_numeric($term['bound_bottom']) ?
$term['bound_bottom'] : NULL
,
176 'bound_left' => is_numeric($term['bound_left']) ?
$term['bound_left'] : NULL
,
178 drupal_write_record('term_geo', $term_geo);
185 * FEEDAPI INTEGRATION
186 * Allows flexible geo and other term importation.
190 * Implementation of hook_feedapi_settings_form().
191 * If a module provides parsers and processors it MUST evaluate the $type variable
192 * to return different forms for parsers and processors.
193 * There might be a better term for parsers and processors than $type.
195 function geotaxonomy_feedapi_settings_form($type) {
199 $vocabularies = taxonomy_get_vocabularies();
201 foreach ($vocabularies as
$vocabulary) {
202 $v_types[$vocabulary->vid
] = $vocabulary->name
;
204 $default_v = current(array_keys($v_types));
206 $form['vocabulary'] = array(
208 '#title' => t('Vocabulary of stored terms'),
209 '#default_value' => $default_v,
210 '#options' => $v_types,
211 '#description' => t('Choose the vocabulary for terms created by this feed. Feedapi term assumes complete freedom in this vocab, meaning it will delete all the vocabs terms when purging and will also update any terms with matching names.'),
219 * Implementation of hook_feedapi_item().
221 function geotaxonomy_feedapi_item($op) {
224 return array("XML feed");
232 if (function_exists('_geotaxonomy_'.
$op)) {
233 $args = array_slice(func_get_args(), 1);
234 return call_user_func_array('_geotaxonomy_'.
$op, $args);
240 * Check for expired items.
241 * Not currently supported, taxonomy doesn't store dates.
243 function _geotaxonomy_expire($feed, $settings) {
248 * Create a term from the feed item.
249 * Stores geo data as well so long as some of it is set.
251 function _geotaxonomy_save($feed_item, $feed_nid, $settings = array()) {
252 $feed_node = node_load($feed_nid);
253 if ($feed_item = feedapi_mapper_map($feed_node, 'geotaxonomy', $feed_item)) {
254 if (isset($feed_item['term_name'])) {
256 'name' => $feed_item['term_name'],
257 'vid' => $settings['vocabulary'],
258 'description' => $feed_item['term_description'],
259 'weight' => $feed_item['term_weight'],
261 if (drupal_write_record('term_data', $term)) {
262 _geotaxonomy_item_tid((!empty($feed_item['term_unique']) ?
$feed_item['term_unique'] : $feed_item['term_name'] .
crc32(serialize($feed_item))), $term['tid']);
263 if (is_numeric($feed_item['term_lat']) || is_numeric($feed_item['term_lon'])) {
265 'tid' => $term['tid'],
266 'lat' => is_numeric($feed_item['term_lat']) ?
$feed_item['term_lat'] : NULL
,
267 'lon' => is_numeric($feed_item['term_lon']) ?
$feed_item['term_lon'] : NULL
,
268 'bound_top' => is_numeric($feed_item['term_bound_top']) ?
$feed_item['term_bound_top'] : NULL
,
269 'bound_right' => is_numeric($feed_item['term_bound_right']) ?
$feed_item['term_bound_right'] : NULL
,
270 'bound_bottom' => is_numeric($feed_item['term_bound_bottom']) ?
$feed_item['term_bound_bottom'] : NULL
,
271 'bound_left' => is_numeric($feed_item['term_bound_left']) ?
$feed_item['term_bound_left'] : NULL
,
273 drupal_write_record('term_geo', $term_geo);
282 * Static cache function to temporarily resolve hierarchical imported information until everything is safely in the database.
284 function _geotaxonomy_item_tid($key, $tid = NULL
) {
285 static
$allkeys = array();
287 $allkeys[$key] = $tid;
289 return $allkeys[$key];
293 * Update a node which already assigned to a feed item
295 function _geotaxonomy_update($feed_item, $feed_nid, $settings, $id) {
301 * Delete a term which already assigned to a feed item
303 function _geotaxonomy_delete($feed_item, $feed_nid) {
304 $feed_node = node_load($feed_nid);
305 if ($feed_item = feedapi_mapper_map($feed_node, 'geotaxonomy', $feed_item)) {
306 if (isset($feed_item['term_name'])) {
307 $tid = db_result(db_query("SELECT tid FROM {term_data} WHERE vid = %d AND name = '%s'", $feed_node->feed
->settings
['processors']['geotaxonomy']['vocabulary'], $feed_item['term_name']));
309 taxonomy_del_term($tid);
316 * Delete all terms associated with a feed's vocabulary.
318 function _geotaxonomy_purge($feed) {
319 $feed_node = node_load($feed->nid
);
320 $result = db_query('SELECT tid FROM {term_data} WHERE vid = %d', $feed_node->feed
->settings
['processors']['geotaxonomy']['vocabulary']);
321 while ($term = db_fetch_object($result)) {
322 taxonomy_del_term($term->tid
);
326 drupal_set_message("Deleted all terms in the vocabulary.");
330 * Tell if the feed item was seen before or not at the feed
331 * Assumes every term in the vocabulary it uses is its own property.
338 * TRUE if the item is new, FALSE if the item is a duplicated one
340 function _geotaxonomy_unique($feed_item, $feed_nid, $settings) {
341 $feed_node = node_load($feed_nid);
342 if ($feed_item = feedapi_mapper_map($feed_node, 'geotaxonomy', $feed_item)) {
343 if (isset($feed_item['term_name'])) {
344 if (!empty($feed_item['term_parent_name'])) {
345 $tid = db_result(db_query("SELECT td.tid FROM {term_data} td LEFT JOIN {term_hierarchy} th ON td.tid = th.tid LEFT JOIN {term_data} td2 ON td2.tid = th.parent WHERE td.vid = %d AND td.name = '%s' AND td2.name = '%s'", $feed_node->feed
->settings
['processors']['geotaxonomy']['vocabulary'], $feed_item['term_name'], $feed_item['term_parent_name']));
347 $tid = db_result(db_query("SELECT td.tid FROM {term_data} td LEFT JOIN {term_hierarchy} th ON td.tid = th.tid WHERE td.vid = %d AND td.name = '%s' AND th.parent = 0", $feed_node->feed
->settings
['processors']['geotaxonomy']['vocabulary'], $feed_item['term_name']));
360 * Implementation of hook_feedapi_after_refresh().
362 function geotaxonomy_feedapi_after_refresh($feed) {
363 if (in_array('geotaxonomy', $feed->processors
)) {
364 $feed_node = node_load($feed->nid
);
366 // Refuse to continue if there are no items on the feed.
367 if (empty($feed->items
)) {
368 // feedapi will already alert the user, we just return.
372 foreach($feed->items as
$feed_item){
373 if ($feed_item = feedapi_mapper_map($feed_node, 'geotaxonomy', $feed_item)) {
374 if (isset($feed_item['term_name'])) {
375 $tid = _geotaxonomy_item_tid((!empty($feed_item['term_unique']) ?
$feed_item['term_unique'] : $feed_item['term_name'] .
crc32(serialize($feed_item))));
382 if (isset($feed_item['term_parent_unique'])) {
383 $ptid = _geotaxonomy_item_tid($feed_item['term_parent_unique']);
385 if (!$ptid && isset($feed_item['term_parent_name'])) {
386 // Just find parent by name.
387 $ptid = db_result(db_query("SELECT tid FROM {term_data} WHERE vid = %d AND name = '%s'", $feed_node->feed
->settings
['processors']['geotaxonomy']['vocabulary'], $feed_item['term_parent_name']));
389 $hierarchy['parent'] = $ptid ?
$ptid : 0;
390 drupal_write_record('term_hierarchy', $hierarchy);
399 * Implementation of hook_feedapi_mapper().
401 function geotaxonomy_feedapi_mapper($op, $feed_node, $processor, $target = NULL
, $feed_element = array(), $field_name = '', $sub_field = '') {
402 if ($processor != 'geotaxonomy') {
407 return t('Maps feed elements to taxonomy term, parent, and description fields as well as geotaxonomy information fields.');
411 'term_name' => 'Term name',
412 'term_description' => 'Term description',
413 'term_weight' => 'Term weight',
414 'term_parent_name' => 'Term parent name. Unreliable if names can be duplicated.',
415 'term_unique' => 'Unique field to identify this term if names can be repeated, for creating hierarchy.',
416 'term_parent_unique' => 'Unique field of the parent of this term. Requires the unique field to be mapped as well to be relevant.',
417 'term_lat' => 'Latitude',
418 'term_lon' => 'Longitude',
419 'term_bound_top' => 'Bound Top',
420 'term_bound_right' => 'Bound Right',
421 'term_bound_bottom' => 'Bound Bottom',
422 'term_bound_left' => 'Bound Left',
426 // Map $feed_element to the key specified by $field_name.
427 $target[$field_name] = $feed_element;