View source
<?php
define('OPENLAYERS_CCK_WIDGET_MAP_ID_PREFIX', 'openlayers-cck-widget-map');
define('OPENLAYERS_CCK_FORMATTER_MAP_ID_PREFIX', 'openlayers-cck-formatter-map');
module_load_include('inc', 'openlayers_cck', 'includes/openlayers_cck.feeds');
function openlayers_cck_help($path, $arg) {
$output = '';
switch ($path) {
case 'admin/help#openlayers_cck':
$output = '<p>' . t('The openlayers_cck module provides fields and widgets that interface with OpenLayers.') . '</p>';
return $output;
}
}
function openlayers_cck_theme() {
$themes = array(
'openlayers_wkt_widget' => array(
'arguments' => array(
'element' => NULL,
),
),
'openlayers_cck_map' => array(
'arguments' => array(
'field' => NULL,
'map' => NULL,
),
),
'openlayers_cck_formatter_default' => array(
'arguments' => array(
'element' => NULL,
),
'gis input' => 'wkt',
),
);
foreach (openlayers_get_presets() as $name => $title) {
$themes['openlayers_cck_formatter_openlayers_map_' . $name] = array(
'arguments' => array(
'element' => NULL,
),
'function' => 'theme_openlayers_cck_formatter_map',
'gis input' => 'wkt',
);
}
return $themes;
}
function openlayers_cck_field_info() {
return array(
'openlayers_wkt' => array(
'label' => t('OpenLayers WKT'),
'description' => t('Input WKT data via an OpenLayers map.'),
'callbacks' => array(
'tables' => CONTENT_CALLBACK_DEFAULT,
'arguments' => CONTENT_CALLBACK_DEFAULT,
),
),
);
}
function openlayers_cck_field_settings($op, $field) {
switch ($op) {
case 'form':
$form = array();
$features = array(
'point' => t('Point'),
'path' => t('Path'),
'polygon' => t('Polygon'),
);
$form['openlayers_cck_feature_types'] = array(
'#type' => 'checkboxes',
'#title' => t('Feature Types'),
'#description' => t('Choose the features that are allowed to be inputed on the map.'),
'#options' => $features,
'#required' => TRUE,
'#default_value' => is_array($field['openlayers_cck_feature_types']) ? $field['openlayers_cck_feature_types'] : array(
'point',
'path',
'polygon',
),
);
return $form;
case 'validate':
break;
case 'save':
return array(
'openlayers_cck_feature_types',
);
case 'database columns':
$columns = array(
'openlayers_wkt' => array(
'type' => 'text',
'size' => 'big',
'not null' => FALSE,
'sortable' => TRUE,
'views' => TRUE,
),
);
return $columns;
case 'views data':
$data = content_views_field_views_data($field);
$db_info = content_database_info($field);
$table_alias = content_views_tablename($field);
return $data;
}
}
function openlayers_cck_field($op, &$node, $field, &$items, $teaser, $page) {
switch ($op) {
case 'validate':
foreach ($items as $delta => $value) {
}
break;
}
}
function openlayers_cck_content_is_empty($item, $field) {
if (empty($item['openlayers_wkt'])) {
return TRUE;
}
return FALSE;
}
function openlayers_cck_content_generate(&$node, $field) {
$node_field = array();
$types = array();
$value = NULL;
$multiple_count = $field['multiple'];
foreach ($field['openlayers_cck_feature_types'] as $type => $available) {
if ($available) {
$types[] = $type;
}
}
if ($field['multiple'] == 0) {
$multiple_count = 1;
}
elseif ($field['multiple'] == 1) {
$multiple_count = rand(3, 11);
}
for ($i = 0; $i < $multiple_count; $i++) {
$type = $types[array_rand($types)];
switch ($type) {
case 'point':
$value = 'POINT(' . _openlayers_cck_generate_pair() . ')';
break;
case 'path':
$line_array = array();
for ($j = 1; $j <= rand(1, 12); $j++) {
$line_array[] = _openlayers_cck_generate_pair();
}
$value = 'LINESTRING(' . implode(',', $line_array) . ')';
break;
case 'polygon':
$poly_array = array();
for ($j = 1; $j <= rand(1, 12); $j++) {
$poly_array[] = _openlayers_cck_generate_pair();
}
$value = 'POLYGON((' . implode(',', $poly_array) . '))';
break;
}
$node_field[$i] = array(
'openlayers_wkt' => $value,
);
}
if (count($node_field) > 0) {
return $node_field;
}
}
function openlayers_cck_widget_info() {
return array(
'openlayers_wkt_widget' => array(
'label' => t('OpenLayers Map'),
'field types' => array(
'openlayers_wkt',
'geo',
),
'multiple values' => CONTENT_HANDLE_MODULE,
'callbacks' => array(
'default value' => CONTENT_CALLBACK_DEFAULT,
),
),
);
}
function openlayers_cck_widget_settings($op, $widget) {
switch ($op) {
case 'form':
$presets = openlayers_get_presets();
$default_preset = variable_get('openlayers_default_preset', 'default');
$form['openlayers_cck_preset_map'] = array(
'#type' => 'select',
'#title' => t('Input Map Preset'),
'#description' => t('Choose the OpenLayers Preset Map that will be used to input the data.'),
'#options' => $presets,
'#default_value' => isset($widget['openlayers_cck_preset_map']) ? $widget['openlayers_cck_preset_map'] : $default_preset,
);
$form['openlayers_cck_zoom_to_layer'] = array(
'#type' => 'checkbox',
'#title' => t('Zoom to Layer'),
'#description' => t('This option will affect how the map will display on the node view. The zoom to layer behavior means that the map will automatically be centered and zoomed onto the features that are created.'),
'#default_value' => isset($widget['openlayers_cck_zoom_to_layer']) ? $widget['openlayers_cck_zoom_to_layer'] : FALSE,
);
$zoom_levels = array();
for ($i = 0; $i <= 20; $i++) {
$zoom_levels[$i] = $i;
}
$form['openlayers_cck_zoom_to_layer_level'] = array(
'#type' => 'select',
'#title' => t('Zoom Level'),
'#description' => t('Choose the zoom level that the Zoom to Layer behavior will have. This will only apply for single feature maps, meaning if you have one point on the map, this level will be given. These levels are arbitrary and the levels will depend on your map and layers. The lower the number the more zoomed in the map will be.'),
'#options' => $zoom_levels,
'#default_value' => isset($widget['openlayers_cck_zoom_to_layer_level']) ? $widget['openlayers_cck_zoom_to_layer_level'] : 10,
);
$form['openlayers_cck_show_empty_map'] = array(
'#type' => 'checkbox',
'#title' => t('Show Empty Map'),
'#description' => t('If the formatter for this field is a map, by default a map will not display if there are no features/data. Check this if you want to ensure that the map does show if there is no data in the field. Please note that this setting actually affects the formatter and will be true in any of the displays that map formatters are used.'),
'#default_value' => isset($widget['openlayers_cck_show_empty_map']) ? $widget['openlayers_cck_show_empty_map'] : FALSE,
);
return $form;
case 'save':
return array(
'openlayers_cck_preset_map',
'openlayers_cck_show_empty_map',
'openlayers_cck_zoom_to_layer',
'openlayers_cck_zoom_to_layer_level',
);
}
}
function openlayers_cck_widget(&$form, &$form_state, $field, $items, $delta = 0) {
$element = array();
if ($field['type'] == 'geo') {
$info = module_invoke_all('gis_input_info');
$info = $info[$field['widget']['type']];
foreach ($items as $key => $item) {
if ($info['gis input']) {
$data = geo_wkb_get_data($item['wkb'], $info['gis input']);
$items[$key] = $data['value'];
}
}
$element['geo'] = array_merge($info['element'], array(
'#default_value' => isset($items[$delta]) ? $items[$delta] : '',
'#gis_type' => $field['geo_type'],
'#gis_input' => $info['gis input'],
'#gis_output' => 'wkt',
'#delta' => $delta,
'#title' => $field['widget']['label'],
'#required' => $field['required'],
'#description' => $field['widget']['description'],
));
if (!isset($element['geo']['#after_build'])) {
$element['geo']['#after_build'] = array();
}
}
switch ($field['widget']['type']) {
case 'openlayers_wkt_widget':
$element['#type'] = 'openlayers_wkt_widget';
$element['#default_value'] = $items;
break;
}
return $element;
}
function openlayers_cck_elements() {
return array(
'openlayers_wkt_widget' => array(
'#input' => TRUE,
'#columns' => array(
'openlayers_wkt',
),
'#delta' => 0,
'#process' => array(
'openlayers_cck_wkt_element_process',
),
),
);
}
function openlayers_cck_wkt_element_process($element, $edit, &$form_state, &$form) {
$field = $form['#field_info'][$element['#parents'][0]];
$delta = $element['#delta'];
$field_name = $field['field_name'];
$widget = $field['widget'];
$field_label = $widget['label'];
$field_key = $element['#columns'][0];
$rendered_map = _openlayers_cck_render_element_map($field_name, $field_label, $element['#value'], $field);
$element['map'] = array(
'#value' => theme('openlayers_cck_map', $field, $rendered_map),
);
$element['openlayers_wkt'] = array(
'#type' => 'textarea',
'#rows' => 2,
'#attributes' => array(
'rel' => $rendered_map['id'],
),
'#title' => $element['#title'],
'#description' => $element['#description'],
'#required' => $element['#required'],
'#field_name' => $element['#field_name'],
'#type_name' => $element['#type_name'],
'#delta' => $element['#delta'],
'#columns' => $element['#columns'],
);
$default_value = '';
if (is_array($element['#value']) && count($element['#value']) > 0) {
$values = array();
foreach ($element['#value'] as $id => $data) {
if (is_array($data)) {
$values[$id] = $data['openlayers_wkt'];
}
elseif (is_string($data)) {
$values[$id] = $data;
}
}
if (is_array($values) && count($values) > 0) {
$default_value = implode('||', $values);
}
}
$element['openlayers_wkt_hidden'] = array(
'#type' => 'hidden',
'#default_value' => $default_value,
);
if (empty($element['#element_validate'])) {
$element['#element_validate'] = array();
}
array_unshift($element['#element_validate'], 'openlayers_cck_validate');
$form_state['#field_info'][$field['field_name']] = $field;
return $element;
}
function openlayers_cck_validate($element, &$form_state) {
$field = $form_state['#field_info'][$element['#field_name']];
$items = _openlayers_cck_convert_form_data($element, $field);
form_set_value($element, $items, $form_state);
if ($field['multiple'] >= 2) {
if (count($items) > $field['multiple']) {
$field_key = $element['#columns'][0];
form_error($element[$field_key], t('%name: this field cannot hold more than @count values.', array(
'%name' => $field['widget']['label'],
'@count' => $field['multiple'],
)));
}
}
}
function _openlayers_cck_convert_form_data($element, $field) {
$field_key = $element['#columns'][0];
$items = explode('||', $element['#value']['openlayers_wkt_hidden']);
$result = array();
if (empty($items)) {
$items[] = NULL;
}
$result = content_transpose_array_rows_cols(array(
$field_key => $items,
));
return $result;
}
function openlayers_cck_field_formatter_info() {
$formatters = array();
$formatters['default'] = array(
'label' => t('WKT Value'),
'field types' => array(
'openlayers_wkt',
),
'multiple values' => CONTENT_HANDLE_MODULE,
'gis types' => array(
'point',
'linestring',
'polygon',
),
'gis input' => 'wkt',
);
foreach (openlayers_get_presets() as $name => $title) {
$formatters['openlayers_map_' . $name] = array(
'label' => t('OpenLayers Map: @preset', array(
'@preset' => check_plain($title),
)),
'field types' => array(
'geo',
'geo_data',
'openlayers_wkt',
),
'multiple values' => CONTENT_HANDLE_MODULE,
'gis types' => array(
'point',
'linestring',
'polygon',
),
'gis input' => 'wkt',
);
}
return $formatters;
}
function theme_openlayers_wkt_widget($element) {
return $element['#children'];
}
function theme_openlayers_cck_formatter_default($element) {
$features = array();
$output = '';
foreach (element_children($element) as $delta) {
$features[$delta] = $element[$delta]['#item']['wkt'] ? $element[$delta]['#item']['wkt'] : $element[$delta]['#item']['openlayers_wkt'];
}
$features = array_filter($features);
if (count($features) > 0) {
if (count($features) > 1) {
$samefeaturetype = TRUE;
foreach ($features as $feature) {
foreach ($features as $checkfeature) {
if (drupal_substr($feature, 0, 5) != drupal_substr($checkfeature, 0, 5)) {
$samefeaturetype = FALSE;
break 2;
}
}
}
if ($samefeaturetype) {
if (drupal_substr($features[0], 0, 5) == 'POINT') {
$output = 'MULTIPOINT(' . str_replace('POINT', '', implode(',', $features)) . ')';
}
if (drupal_substr($features[0], 0, 10) == 'LINESTRING') {
$output = 'MULTILINESTRING(' . str_replace('LINESTRING', '', implode(',', $features)) . ')';
}
if (drupal_substr($features[0], 0, 7) == 'POLYGON') {
$output = 'MULTIPOLYGON(' . str_replace('POLYGON', '', implode(',', $features)) . ')';
}
}
else {
$output = 'GEOMETRYCOLLECTION(' . implode(',', $features) . ')';
}
}
else {
$output = $features[0];
}
}
return $output;
}
function theme_openlayers_cck_formatter_map($element) {
$features = array();
$field = content_fields($element['#field_name'], $element['#type_name']);
$widget = $field['widget'];
foreach (element_children($element) as $delta) {
$features['openlayers_cck_vector_feature_' . $delta] = array(
'wkt' => $element[$delta]['#item']['wkt'] ? $element[$delta]['#item']['wkt'] : $element[$delta]['#item']['openlayers_wkt'],
'projection' => $element[$delta]['#item']['srid'] ? $element[$delta]['#item']['srid'] : '4326',
);
}
if ((count($features) == 0 || empty($features['openlayers_cck_vector_feature_0']['wkt'])) && $widget['openlayers_cck_show_empty_map'] == FALSE) {
return '';
}
if (drupal_substr($element['#formatter'], 25) == 'openlayers_cck_formatter_') {
$preset_name = drupal_substr($element['#formatter'], 25);
}
if (drupal_substr($element['#formatter'], 0, 15) == 'openlayers_map_') {
$preset_name = drupal_substr($element['#formatter'], 15);
}
$map = openlayers_get_map($preset_name);
static $formatter_count = array();
if (isset($formatter_count[$field['field_name']])) {
$formatter_count[$field['field_name']]++;
}
else {
$formatter_count[$field['field_name']] = 0;
}
$map['id'] = OPENLAYERS_CCK_FORMATTER_MAP_ID_PREFIX . '-' . str_replace('_', '-', $field['field_name']) . '-' . $formatter_count[$field['field_name']];
$formatter_count++;
if (count($features) > 0) {
$map['layers']['openlayers_cck_vector'] = array(
'id' => 'openlayers_cck_vector',
'name' => $field['widget']['label'],
'type' => 'Vector',
'options' => array(),
'features' => $features,
);
$map['options']['displayProjection'] = $field['srid'] != 0 ? $field['srid'] : '4326';
if ($widget['openlayers_cck_zoom_to_layer']) {
$map['behaviors']['cck_zoom_to_layer'] = array(
'id' => 'cck_zoom_to_layer',
'type' => 'openlayers_behaviors_zoom_to_layer',
'layer' => 'openlayers_cck_vector',
'pointzoom' => $widget['openlayers_cck_zoom_to_layer_level'],
);
}
}
$rendered = openlayers_render_map($map);
if (!$map['errors'] && !empty($map['width'])) {
return $rendered['themed'];
}
else {
return '';
}
}
function theme_openlayers_cck_map($field = array(), $map = array()) {
$title = check_plain($field['widget']['label']);
$description = content_filter_xss($field['widget']['description']);
$output = '';
if (!empty($map['errors'])) {
return $output;
}
$output = '
<div id="openlayers-cck-map-container-' . $map['id'] . '" class="form-item openlayers-cck-map-container">
<label for="openlayers-cck-map-' . $map['id'] . '">' . $title . ':</label>
' . $map['themed'] . '
<div class="description openlayers-cck-map-instructions">
' . t('Click the tools in the upper right-hand corner of the map to switch between draw mode and zoom/pan mode. Draw your shape, double-clicking to finish. You may edit your shape using the control points. To delete a shape, select it and press the delete key. To delete a vertex hover over it and press the d key.') . '
</div>
<div class="description openlayers-cck-map-description">
' . $description . '
</div>
<div class="openlayers-cck-actions">
<a href="#" id="' . $map['id'] . '-wkt-switcher" rel="' . $map['id'] . '">' . t('Show/Hide WKT Fields') . '</a>
</div>
</div>
';
return $output;
}
function openlayers_cck_gis_input_info($gis_type = NULL) {
$inputs = array(
'openlayers_wkt_widget' => array(
'label' => t('OpenLayers Map'),
'gis input' => 'wkt',
'safe reverse' => TRUE,
'gis types' => array(
'point',
'linestring',
'polygon',
),
'element' => array(
'#type' => 'openlayers_wkt',
),
),
);
return $inputs;
}
function _openlayers_cck_render_element_map($field_name = '', $field_label = '', $values = array(), $field = array()) {
$field_name_html = str_replace('_', '-', $field_name);
$map_id = OPENLAYERS_CCK_WIDGET_MAP_ID_PREFIX . '-' . $field_name;
$field_type = $field['type'];
$widget = $field['widget'];
$field_container = 'edit-' . $field_name_html . '-openlayers-wkt-wrapper';
$field_id = 'edit-' . $field_name_html . '-openlayers-wkt';
$hidden_field_id = 'edit-' . $field_name_html . '-openlayers-wkt-hidden';
if (isset($widget['openlayers_cck_preset_map'])) {
$map = openlayers_get_map($widget['openlayers_cck_preset_map']);
}
else {
$map = openlayers_get_default_map();
}
$map['id'] = $map_id;
$map['events']['beforeBehaviors'] = array(
'CCKProcess',
);
$map['options']['displayProjection'] = $field['srid'] != 0 ? $field['srid'] : '4326';
$map['layers']['openlayers_cck_vector'] = array(
'id' => 'openlayers_cck_vector',
'type' => 'Vector',
'name' => $field_label,
'options' => array(),
'events' => array(
'featureselected' => array(
'CCKFeaturesSelected',
),
'featureunselected' => array(
'CCKFeaturesUnselected',
),
),
);
$behavior_base = array(
'type' => 'openlayers_behaviors_draw_features',
'layer' => 'openlayers_cck_vector',
'featureadded_handler' => array(
'OL.CCK.featureAdded',
),
'featuremodified_handler' => array(
'OL.CCK.featureModified',
),
'featureremoved_handler' => array(
'OL.CCK.featureRemoved',
),
);
if ($field_type == 'geo' && isset($field['geo_type'])) {
$type = $field['geo_type'] == 'linestring' ? 'path' : $field['geo_type'];
$map['behaviors']['openlayers_cck_edit_' . $type] = $behavior_base + array(
'id' => 'openlayers_cck_edit_' . $type,
'feature_type' => $type,
);
}
else {
if ($field['openlayers_cck_feature_types']) {
foreach ($field['openlayers_cck_feature_types'] as $type) {
if (!empty($type)) {
$map['behaviors']['openlayers_cck_edit_' . $type] = $behavior_base + array(
'id' => 'openlayers_cck_edit_' . $type,
'feature_type' => $type,
);
}
}
}
else {
return FALSE;
}
}
$rendered_map = openlayers_render_map($map);
if (!$rendered_map['errors']) {
drupal_add_js(drupal_get_path('module', 'openlayers_cck') . '/js/openlayers_cck.js');
drupal_add_css(drupal_get_path('module', 'openlayers_cck') . '/openlayers_cck.css', 'module');
$openlayers_cck = array(
'openlayers_cck' => array(
'maps' => array(
$map_id => array(
'field_name' => $field_name,
'field_data' => $field,
'field_name_js' => $field_name_html,
'field_container' => $field_container,
'field_items' => $items,
'field_id' => $field_id,
'hidden_field_id' => $hidden_field_id,
'map_container' => 'openlayers-cck-map-container-' . $map_id,
),
),
),
);
drupal_add_js($openlayers_cck, 'setting');
}
return $rendered_map;
}
function _openlayers_cck_generate_pair() {
$lat = (double) ((mt_rand(0, 120000) - 60000) / 1000);
$lon = (double) ((mt_rand(0, 360000) - 180000) / 1000);
return (string) $lon . ' ' . (string) $lat;
}