You are here

colorized_gmap.module in Colorized google maps block 7

Same filename and directory in other branches
  1. 8 colorized_gmap.module

Colorized gmap module.

File

colorized_gmap.module
View source
<?php

/**
 * @file
 * Colorized gmap module.
 */

/**
 * Implements hook_help().
 */
function colorized_gmap_help($path, $arg) {
  switch ($path) {
    case 'admin/help#colorized_gmap':

      // Return a line-break version of the module README.txt
      return check_markup(file_get_contents(dirname(__FILE__) . "/README.txt"));
  }
}

/**
 * Implements hook_menu().
 */
function colorized_gmap_menu() {
  $items = array();
  $items['admin/structure/block/colorized_gmap_block'] = array(
    'title' => 'Add colorized gmap block',
    'description' => 'Add a new colorized gmap block.',
    'page callback' => 'drupal_get_form',
    'page arguments' => array(
      'colorized_gmap_page_form',
    ),
    'access arguments' => array(
      'administer blocks',
    ),
    'type' => MENU_LOCAL_ACTION,
    'file' => 'colorized_gmap.admin.inc',
  );
  $items['admin/structure/block/delete-colorized-gmap/%'] = array(
    'title' => 'Delete colorized gmap block',
    'page callback' => 'drupal_get_form',
    'page arguments' => array(
      'colorized_gmap_block_delete',
      4,
    ),
    'access arguments' => array(
      'administer blocks',
    ),
    'type' => MENU_CALLBACK,
    'file' => 'colorized_gmap.admin.inc',
  );
  $items['admin/config/content/colorized_gmap'] = array(
    'title' => 'Colorized gmap',
    'description' => 'Colorized gmap module settings settings page',
    'page callback' => 'drupal_get_form',
    'page arguments' => array(
      'colorized_gmap_settings_form',
    ),
    'access arguments' => array(
      'administer site configuration',
    ),
    'file' => 'colorized_gmap.admin.inc',
  );
  return $items;
}

/**
 * Implements hook_block_info().
 */
function colorized_gmap_block_info() {
  $blocks = array();
  $theme_default = variable_get('theme_default', 'bartik');
  $map_entities = entity_load('colorized_gmap');
  if (!empty($map_entities)) {
    foreach ($map_entities as $key => $item) {
      $blocks[$key] = array(
        'info' => "Colorized gmap block ({$item->name})",
        'cache' => DRUPAL_NO_CACHE,
        'visibility' => $item->block_settings['visibility'],
        'custom' => $item->block_settings['custom'],
        'pages' => $item->block_settings['pages'],
        'region' => isset($item->block_settings['region'][$theme_default]) ? $item->block_settings['region'][$theme_default] : -1,
        'status' => !isset($item->block_settings['region'][$theme_default]) || $item->block_settings['region'][$theme_default] == -1 ? 0 : 1,
      );
    }
  }
  return $blocks;
}

/**
 * Implements hook_block_info_alter().
 */
function colorized_gmap_block_info_alter(&$blocks, $theme, $code_blocks) {

  // @todo: Just use then blocks imported via features.
  // There is a strange behavior with _block_rehash().
  // After enabling feature, _block_rehash() is called and
  // set the same region for each enabled themes.
  // Below code just set true region values (from block entity).
  // Cannot figure out how to fix it correctly.
  if (module_exists('features') && isset($blocks['colorized_gmap'])) {
    $ids = array_keys($blocks['colorized_gmap']);
    $entities = entity_load('colorized_gmap', $ids);
    foreach ($entities as $key => $item) {
      if (isset($item->block_settings['region'][$theme])) {
        $blocks['colorized_gmap'][$key]['region'] = $item->block_settings['region'][$theme];
      }
      else {
        $blocks['colorized_gmap'][$key]['region'] = -1;
      }
    }
  }
}

/**
 * Implements hook_block_view().
 */
function colorized_gmap_block_view($delta = '') {
  $block = array();
  $map_entity = entity_load_single('colorized_gmap', $delta);
  if (!empty($map_entity)) {
    if ($map_entity->id == $delta) {
      $api_key = variable_get('colorized_gmap_api_key', '');
      $api_url = colorized_gmap_build_api_url();
      if (empty($api_key)) {
        $missing_api_key_message = t('Google maps are no longer working without !info. Please visit !get-key page to get API key and follow further instructions. After that, please enter your api key on !settings-page.', array(
          '!info' => l("api key", "http://googlegeodevelopers.blogspot.ru/2016/06/building-for-scale-updates-to-google.html", array(
            'external' => TRUE,
            'attributes' => array(
              'target' => '_blank',
            ),
          )),
          '!get-key' => l('this', 'https://developers.google.com/maps/documentation/javascript/get-api-key', array(
            'external' => TRUE,
            'attributes' => array(
              'target' => '_blank',
            ),
          )),
          '!settings-page' => l('module settings page', '/admin/config/content/colorized_gmap'),
        ));
        drupal_set_message($missing_api_key_message, 'warning');
      }
      $block = array(
        'subject' => $map_entity->block_settings['title'],
        'content' => array(
          '#markup' => theme('colorized_gmap', array(
            'delta' => $delta,
          )),
          '#attached' => array(
            'js' => array(
              drupal_get_path('module', 'colorized_gmap') . '/js/colorized_gmap.js',
              array(
                'data' => url($api_url, array(
                  'type' => 'external',
                  'scope' => 'footer',
                )),
                'type' => 'external',
              ),
              array(
                'data' => array(
                  'colorized_gmap' => _colorized_gmap_get_map_js_settings($delta, $map_entity),
                ),
                'type' => 'setting',
              ),
            ),
            'css' => array(
              drupal_get_path('module', 'colorized_gmap') . '/css/colorized_gmap.css',
            ),
          ),
        ),
      );
    }
  }
  return $block;
}

/**
 * Implements hook_block_configure().
 */
function colorized_gmap_block_configure($delta = '') {
  $api_key = variable_get('colorized_gmap_api_key', '');
  if (empty($api_key)) {
    $missing_api_key_message = t('Google maps are no longer working without !info. Please visit !get-key page to get API key and follow further instructions. After that, please enter your api key on !settings-page.', array(
      '!info' => l("api key", "http://googlegeodevelopers.blogspot.ru/2016/06/building-for-scale-updates-to-google.html", array(
        'external' => TRUE,
        'attributes' => array(
          'target' => '_blank',
        ),
      )),
      '!get-key' => l('this', 'https://developers.google.com/maps/documentation/javascript/get-api-key', array(
        'external' => TRUE,
        'attributes' => array(
          'target' => '_blank',
        ),
      )),
      '!settings-page' => l('module settings page', '/admin/config/content/colorized_gmap'),
    ));
    drupal_set_message($missing_api_key_message, 'warning');
  }
  $form = array();
  $form['#attached']['libraries_load'][] = array(
    'colorpicker',
  );
  $form['#attached']['css'] = array(
    drupal_get_path('module', 'colorized_gmap') . '/css/colorized_gmap.css',
  );
  $api_url = colorized_gmap_build_api_url();
  $form['#attached']['js'] = array(
    drupal_get_path('module', 'colorized_gmap') . '/js/colorized_gmap_admin.js',
    "{$api_url}" => array(
      'type' => 'external',
      'scope' => 'footer',
    ),
  );
  return $form;
}

/**
 * Implements hook_block_save().
 */
function colorized_gmap_block_save($delta = '', $edit = array()) {

  // Array of block settings such as region, visibility, etc.
  $block_settings = array(
    'region' => $edit['regions'],
    'custom' => $edit['custom'],
    'visibility' => $edit['visibility'],
    'pages' => $edit['pages'],
    'title' => $edit['title'],
  );
  if (!empty($delta)) {
    $entity = entity_load_single('colorized_gmap', $delta);
    if ($entity) {

      // If marker was uploaded - update its info.
      $marker = $edit['colorized_map_addtional_settings']['marker_settings']['marker'];
      if (!is_array($marker) && !empty($marker)) {
        $marker = _colorized_gmap_marker_info($marker, $delta);
        $edit['colorized_map_addtional_settings']['marker_settings']['marker'] = $marker;
      }
      $entity->latitude = $edit['latitude'];
      $entity->longitude = $edit['longitude'];
      $entity->additional_settings = $edit['colorized_map_addtional_settings'];
      $entity->style = $edit['settings'];
      $entity->block_settings = $block_settings;
      $entity
        ->save();
    }
  }
  else {
    $options = array(
      'name' => $edit['machine-name'],
      'module' => 'colorized_gmap',
      'latitude' => $edit['latitude'],
      'longitude' => $edit['longitude'],
      'additional_settings' => $edit['colorized_map_addtional_settings'],
      'style' => $edit['settings'],
      'block_settings' => $block_settings,
    );
    $entity = entity_create('colorized_gmap', $options);
    $entity
      ->save();
  }
}

/**
 * Prepare map style values to pass to js.
 *
 * @param int $delta
 *   Block delta.
 * @param object $entity
 *   Map entity.
 *
 * @return array
 *   Array of map settings to be passed to js.
 */
function _colorized_gmap_get_map_js_settings($delta, $entity) {
  module_load_include('inc', 'colorized_gmap', 'colorized_gmap.admin');
  $styles = array();
  $fid = $entity->additional_settings['marker_settings']['marker'];
  if (!is_array($fid) && !empty($fid)) {
    $marker = _colorized_gmap_marker_info($fid, $delta);
    $entity->additional_settings['marker_settings']['marker'] = $marker;
  }

  // @todo: Fix this. Used to make array indexes start with 0.
  foreach ($entity->style as $item) {
    $styles[] = $item;
  }
  $settings = array(
    'blocks' => array(
      $delta => array(
        'latitude' => $entity->latitude,
        'longitude' => $entity->longitude,
        'style' => $styles,
        'additional_settings' => $entity->additional_settings,
        'delta' => $delta,
      ),
    ),
  );
  return $settings;
}

/**
 * Implements hook_theme().
 */
function colorized_gmap_theme() {
  return array(
    'colorized_gmap_table_form' => array(
      'render element' => 'form',
      'file' => 'colorized_gmap.theme.inc',
    ),
    'colorized_gmap_image_marker' => array(
      'render element' => 'element',
      'file' => 'colorized_gmap.theme.inc',
    ),
    'colorized_gmap' => array(
      'template' => 'colorized-gmap-block',
      'arguments' => array(
        'delta' => NULL,
      ),
    ),
  );
}

/**
 * Implements hook_entity_info().
 */
function colorized_gmap_entity_info() {
  return array(
    'colorized_gmap' => array(
      'label' => t('Colorized gmap'),
      'entity class' => 'Entity',
      'controller class' => 'ColorizedGmapEntityController',
      'fieldable' => FALSE,
      'exportable' => TRUE,
      'base table' => 'colorized_gmap_units',
      'label callback' => 'colorized_gmap_entity_info_label',
      'entity keys' => array(
        'id' => 'id',
        'name' => 'name',
      ),
      'metadata controller class' => 'ColorizedGmapEntityMetadataController',
      'access arguments' => array(
        'administer blocks',
      ),
      'module' => 'colorized_gmap',
    ),
  );
}

/**
 * Entity label callback.
 */
function colorized_gmap_entity_info_label($entity, $entity_type) {
  return "Colorized gmap ({$entity->name})";
}

/**
 * Implements hook_form_alter().
 */
function colorized_gmap_form_alter(&$form, &$form_state, $form_id) {
  if ($form_id == 'colorized_gmap_page_form' || $form_id == 'block_admin_configure' && $form['module']['#value'] == 'colorized_gmap') {
    module_load_include('inc', 'colorized_gmap', 'colorized_gmap.admin');
    $map_entity = NULL;
    if (!empty($form['delta']['#value'])) {
      $map_entity = entity_load_single('colorized_gmap', $form['delta']['#value']);
      $form['settings']['title']['#default_value'] = $map_entity->block_settings['title'];
    }

    // Machine name.
    $form['settings']['machine-name'] = array(
      '#type' => 'machine_name',
      '#title' => t("Machine Name"),
      '#required' => TRUE,
      '#description' => t("Machine-friendly name."),
      '#size' => 15,
      // @todo: I set default value here to not to break ajax.
      '#default_value' => isset($map_entity) ? $map_entity->name : 'colorized_gmap_' . time(),
      '#disabled' => isset($map_entity->name) ? TRUE : FALSE,
      '#machine_name' => array(
        'exists' => '_colorized_gmap_block_name_exists',
      ),
    );

    // Options for map controls positions (comes from GMAP api v3 reference).
    $position = array(
      '1' => 'Top Left',
      '2' => 'Top Center',
      '3' => 'Top Right',
      '4' => 'Left Center',
      '5' => 'Left Top',
      '6' => 'Left Bottom',
      '7' => 'Right Top',
      '8' => 'Right Center',
      '9' => 'Right Bottom',
      '10' => 'Bottom Left',
      '11' => 'Bottom Center',
      '12' => 'Bottom Right',
    );

    // Some helper function to create form elements.
    // Just to make code more user friendly.
    _colorized_gmap_form_map_stylers($form, $form_state, $map_entity);
    _colorized_gmap_form_map_coordinates($form, $form_state, $map_entity);
    _colorized_gmap_form_map_controls($form, $form_state, $map_entity);
    _colorized_gmap_form_map_controls_position($form, $form_state, $position, $map_entity);
    _colorized_gmap_form_map_marker($form, $form_state, $map_entity);
    _colorized_gmap_form_zoom_settings($form, $form_state, $position, $map_entity);

    // Update map styles js setting on AJAX.
    if ($form_state['rebuild'] && isset($form_state['values']['settings'])) {
      foreach ($form_state['styles_removed'] as $item) {
        $form_state['values']['settings'][$item] = array();
      }
      if ($form_state['values']['delta']) {
        $marker = _colorized_gmap_marker_info($form_state['values']['colorized_map_addtional_settings']['marker_settings']['marker'], $form_state['values']['delta']);
        $form_state['values']['colorized_map_addtional_settings']['marker_settings']['marker'] = $marker;
      }
      colorized_gmap_admin_js_settings_export($form_state['values']);
    }

    // Pre-populate default map style values.
    if ($map_entity && !$form_state['rebuild']) {

      // If marker was uploaded - update its info.
      $marker = $map_entity->additional_settings['marker_settings']['marker'];
      if (!is_array($marker) && !empty($marker)) {
        $marker = _colorized_gmap_marker_info($marker, $map_entity->id);
        $map_entity->additional_settings['marker_settings']['marker'] = $marker;
      }
      $settings = array(
        'settings' => $map_entity->style,
        'colorized_map_addtional_settings' => $map_entity->additional_settings,
        'latitude' => $map_entity->latitude,
        'longitude' => $map_entity->longitude,
      );
      colorized_gmap_admin_js_settings_export($settings);
    }
    $form['#validate'][] = 'colorized_gmap_page_form_validate';
  }
}

/**
 * Validate callback.
 */
function colorized_gmap_page_form_validate($form, &$form_state) {
  if (!is_numeric($form_state['values']['latitude'])) {
    form_set_error('latitude', t('Latitude must be a numeric amount'));
  }
  if (!is_numeric($form_state['values']['longitude'])) {
    form_set_error('longitude', t('Longitude must be a numeric amount'));
  }
  if (!is_numeric($form_state['values']['colorized_map_addtional_settings']['controls']['min_drag_width'])) {
    form_set_error('colorized_map_addtional_settings][controls][min_drag_width', t('Min drag width must be a numeric amount'));
  }
  if (!is_numeric($form_state['values']['colorized_map_addtional_settings']['zoom_control_settings']['zoom'])) {
    form_set_error('colorized_map_addtional_settings][zoom_control_settings][zoom', t('Zoom must be a numeric amount'));
  }
}

/**
 * AJAX callback for "Add More" button.
 */
function colorized_gmap_form_add_row($form, &$form_state) {
  $form_state['styles_count']++;
  $form_state['rebuild'] = TRUE;
}

/**
 * AJAX callback for "Remove Row" button.
 */
function colorized_gmap_form_remove_row($form, &$form_state) {
  foreach ($form_state['values']['settings'] as $key => $item) {
    if (is_numeric($key)) {
      if ($item['remove']) {
        $form_state['styles_removed'][] = $key;
      }
    }
  }
  $form_state['rebuild'] = TRUE;
}

/**
 * Implements hook_form_FORM_ID_alter().
 */
function colorized_gmap_form_block_admin_display_form_alter(&$form, $form_state) {

  // @todo: Figure out why entity_load() don't work here.
  $query = new EntityFieldQuery();
  $query
    ->entityCondition('entity_type', 'colorized_gmap');
  $result = $query
    ->execute();
  if (!empty($result)) {
    foreach (array_keys($result['colorized_gmap']) as $item) {
      $form['blocks']['colorized_gmap_' . $item]['delete'] = array(
        '#type' => 'link',
        '#title' => t('delete'),
        '#href' => 'admin/structure/block/delete-colorized-gmap/' . $item,
      );
    }
  }
}

/**
 * Implements hook_libraries_info().
 */
function colorized_gmap_libraries_info() {
  $libraries['colorpicker'] = array(
    'name' => 'Colorpicker',
    'vendor url' => 'http://www.eyecon.ro/colorpicker',
    'download url' => 'http://www.eyecon.ro/colorpicker/colorpicker.zip',
    // @todo: There is no info about version in the library files.
    'version callback' => '_colorized_gmap_return_colorpicker_lib_version',
    'version arguments' => array(
      '1',
    ),
    'files' => array(
      'js' => array(
        'js/colorpicker.js',
      ),
      'css' => array(
        'css/colorpicker.css',
      ),
    ),
  );
  return $libraries;
}

/**
 * Version callback for colorpicker library.
 */
function _colorized_gmap_return_colorpicker_lib_version($library, $version) {
  return $version;
}

/**
 * Load file info.
 *
 * @param int $fid
 *   File id.
 * @param int $delta
 *   Block delta.
 *
 * @return array
 *   Array contains file url and fid.
 */
function _colorized_gmap_marker_info($fid, $delta) {
  $file = file_load($fid);
  $marker = array();
  if ($file != FALSE) {
    $file->status = FILE_STATUS_PERMANENT;
    $marker = array(
      'fid' => $file->fid,
      'url' => file_create_url($file->uri),
    );
    file_save($file);
    file_usage_add($file, 'colorized_gmap', 'colorized_gmap', $delta);
  }
  return $marker;
}

/**
 * Builds the javascript maps api url based on authentication method.
 */
function colorized_gmap_build_api_url() {

  // Google api url.
  $api_url = '//maps.googleapis.com/maps/api/js';

  // Array to hold query parameters for the google maps url.
  // Including version number as it's required for Premium plans.
  // https://developers.google.com/maps/documentation/javascript/versions
  $query = array(
    'v' => '3',
  );
  switch (variable_get('colorized_gmap_auth_method')) {
    case 1:
      $key = variable_get('colorized_gmap_api_key', '');
      if (!empty($key)) {
        $query['key'] = $key;
      }
      break;
    case 2:
      $client_id = variable_get('colorized_gmap_client_id', '');
      $private_key = variable_get('colorized_gmap_private_key', '');
      if (!empty($client_id)) {
        $query['client'] = $client_id;
        if (!empty($private_key)) {
          $query['signature'] = $private_key;
        }
      }
      break;
  }

  // Add query params to API url.
  if (!empty($query)) {
    $api_url .= '?' . drupal_http_build_query($query);
  }
  return $api_url;
}