<?php

/**
 * @file
 * A module gives to Google information about images on your site.
 */

define('GOOGLE_IMAGE_SITEMAP_ADMIN_PATH', 'admin/config/search/google_image_sitemap');

/**
 * Implements hook_permission().
 */
function google_image_sitemap_permission() {
  $permissions['administer google image sitemap'] = array(
    'title' => t('Administer settings for Google Image Sitemap.'),
  );
  return $permissions;
}

/**
 * Implements hook_menu().
 *
 * Provides a page for configuring sitemap settings.
 */
function google_image_sitemap_menu() {
  $items[GOOGLE_IMAGE_SITEMAP_ADMIN_PATH] = array(
    'title' => 'Google Image Sitemap',
    'description' => 'Create and configure google image sitemap.',
    'page callback' => '_google_image_sitemap_list',
    'access arguments' => array('administer google image sitemap'),
  );
  $items[GOOGLE_IMAGE_SITEMAP_ADMIN_PATH . '/list'] = array(
    'title' => 'List',
    'type' => MENU_DEFAULT_LOCAL_TASK,
    'weight' => -5,
  );
  $items[GOOGLE_IMAGE_SITEMAP_ADMIN_PATH . '/add'] = array(
    'title' => 'Add new Google Image sitemap',
    'page callback' => 'drupal_get_form',
    'page arguments' => array('_google_image_sitemap_create_form'),
    'access arguments' => array('administer google image sitemap'),
    'type' => MENU_LOCAL_ACTION,
  );
  $items[GOOGLE_IMAGE_SITEMAP_ADMIN_PATH . '/edit/%'] = array(
    'title' => 'Edit google image sitemap',
    'page callback' => 'drupal_get_form',
    'page arguments' => array('_google_image_sitemap_create_form', 5),
    'access arguments' => array('administer google image sitemap'),
    'modal' => TRUE,
  );
  $items[GOOGLE_IMAGE_SITEMAP_ADMIN_PATH . '/delete/%'] = array(
    'title' => 'Delete google image sitemap',
    'page callback' => '_google_image_sitemap_delete_form',
    'page arguments' => array(5),
    'access arguments' => array('administer google image sitemap'),
  );
  $items[GOOGLE_IMAGE_SITEMAP_ADMIN_PATH . '/build/%'] = array(
    'title' => 'Build google image sitemap',
    'description' => 'Build google image sitemap.',
    'page callback' => '_google_image_sitemap_build',
    'page arguments' => array(5),
    'access arguments' => array('administer google image sitemap'),
  );
  return $items;
}

/**
 * Menu callback: Displays a list of available sitemaps.
 *
 * @return string
 *   Theme table data.
 */
function _google_image_sitemap_list() {
  $output = '';
  $header = array(
    t('S.NO.'),
    t('SITEMAP URL'),
    t('RANGE'),
    t('CONTENT TYPE'),
    t('LAST UPDATED'),
    t('ACTIONS'),
  );

  $query = db_select('google_image_sitemap', 'g');
  $query->fields('g');
  $result = $query->execute();

  $counter = 0;
  $rows = array();
  while ($gis_obj = $result->fetchObject()) {
    $url = 'google_image_sitemap/sitemap_' . $gis_obj->created . '.xml';
    //$url = file_create_url(file_build_uri($url));
    $url = variable_get('file_public_path', 'sites/default/files') . '/' . $url;
    // Build links.
    $link_attributs = array('attributes' => array('title' => $gis_obj->range_start . " to " . $gis_obj->range_end));
    if (empty($gis_obj->last_updated)) {
      $rebuild_link = '';
      $build_link = l(t('Generate Sitemap'), (GOOGLE_IMAGE_SITEMAP_ADMIN_PATH . '/build/' . $gis_obj->sid), $link_attributs);
    }
    else {
      $rebuild_link = l(t('RE-GENERATE'), GOOGLE_IMAGE_SITEMAP_ADMIN_PATH . '/build/' . $gis_obj->sid) . " | ";
      $build_link = l($url, $url, $link_attributs);
    }
    // Rows of table.
    $rows[] = array(
      ++$counter,
      $build_link,
      $gis_obj->range_start . " - " . $gis_obj->range_end,
      $gis_obj->node_type,
      empty($gis_obj->last_updated) ? '-' : date('d-M-Y ', $gis_obj->last_updated),
      $rebuild_link .
      l(t('EDIT'), GOOGLE_IMAGE_SITEMAP_ADMIN_PATH . '/edit/' . $gis_obj->sid) . " | " .
      l(t('DELETE'), GOOGLE_IMAGE_SITEMAP_ADMIN_PATH . '/delete/' . $gis_obj->sid),
    );
  }
  $theme_args = array(
    'header' => $header,
    'rows' => $rows,
    'empty' => t('No sitemaps available.') . ' ' . l(t('Add a new sitemap'), GOOGLE_IMAGE_SITEMAP_ADMIN_PATH . '/add'),
  );

  $output = theme('table', $theme_args);
  return $output;
}

/**
 * Form builder: Generate a form to add/edit sitemaps.
 */
function _google_image_sitemap_create_form($form, &$form_state, $sitemap_id = NULL) {
  $form = array();
  // Get all node types.
  $node_types = node_type_get_names();
  // Count the all records from every content types.
  foreach ($node_types as $node_type_key => $node_type_val) {
    $query = db_select('node');
    $query->addExpression('count(*)', 'cnt');
    $query->condition('type', $node_type_key);
    $node_types[$node_type_key] = $node_type_val . " ( " . $query->execute()->fetchObject()->cnt . " )";
  }
  $form['node_type'] = array(
    '#type' => 'select',
    '#title' => t('Select Content Type'),
    '#description' => t('Select the content type for which you want to generate image sitemap.'),
    '#options' => $node_types,
    '#required' => TRUE,
  );
  $form['range_start'] = array(
    '#type' => 'textfield',
    '#title' => t('Range Start'),
    '#description' => t('Starting Node ID.'),
    '#default_value' => '',
    '#required' => TRUE,
  );
  $form['range_end'] = array(
    '#type' => 'textfield',
    '#title' => t('Range End'),
    '#description' => t('Ending Node ID.'),
    '#default_value' => '',
    '#required' => TRUE,
  );
  $form['license'] = array(
    '#type' => 'textfield',
    '#title' => t('License url'),
    '#description' => t('An absolute url to the license agreement of the image.'),
  );
  $form['buttons']['save'] = array(
    '#type' => 'submit',
    '#value' => t('Save'),
  );
  $form['buttons']['cancel'] = array(
    '#type' => 'link',
    '#href' => isset($_GET['destination']) ? $_GET['destination'] : GOOGLE_IMAGE_SITEMAP_ADMIN_PATH,
    '#title' => t('Cancel'),
  );
  if (!empty($sitemap_id) && ($sitemap_obj = _google_image_sitemap_valid_sitemap_id($sitemap_id))) {
    $form_state['storage']['sitemap_id'] = $sitemap_id;
    // Set default value of form elements.
    $form['node_type']['#default_value'] = $sitemap_obj->node_type;
    $form['license']['#default_value'] = $sitemap_obj->license;
    $form['range_end']['#default_value'] = $sitemap_obj->range_end;
    $form['range_start']['#default_value'] = $sitemap_obj->range_start;
  }
  return $form;
}

/**
 * Form validation handler for _google_image_sitemap_create_form().
 */
function _google_image_sitemap_create_form_validate($form, &$form_state) {
  // Check for valid url.
  if (!empty($form_state['values']['license']) && !valid_url($form_state['values']['license'], TRUE)) {
    form_set_error('license', t('Lincese should be a valid url.'));
  }
  // Validate range start for integer.
  if (empty($form_state['values']['range_start'])) {
    form_set_error('range_start', t('Range start should be an integer and greater than 0 value.'));
  }
  // Validate range start for integer.
  if (!(preg_match("/^([0-9]+)$/", $form_state['values']['range_start']))) {
    form_set_error('range_start', t('Range start should be an integer.'));
  }
  // Validate range end for integer.
  if (!(preg_match("/^([0-9]+)$/", $form_state['values']['range_end']))) {
    form_set_error('range_end', t('Range end should be an integer value.'));
  }
  // Validate range start and end.
  if ($form_state['values']['range_start'] > $form_state['values']['range_end']) {
    form_set_error('range_start', t('Range start should be less than to Range end.'));
  }
  // Validate range end with datbase.
  $query = db_select('node', 'n');
  $query->condition('n.type', $form_state['values']['node_type'], '=');
  $query->condition('n.status', NODE_PUBLISHED);
  $query->addExpression('COUNT(n.nid)', 'max_nid');
  // Validate range start and end.
  if ($form_state['values']['range_start'] > $query->execute()->fetchField()) {
    form_set_error('range_start', t('Range Start should not be greater than @max_nid (Node ID).', array('@max_nid' => $query->execute()->fetchField())));
  }
  if ($form_state['values']['range_end'] > $query->execute()->fetchField()) {
    form_set_error('range_end', t('Range End should not be greater than @max_nid (Node ID).', array('@max_nid' => $query->execute()->fetchField())));
  }
}

/**
 * Form submission handler for _google_image_sitemap_create_form().
 */
function _google_image_sitemap_create_form_submit($form, &$form_state) {
  $sitemap_obj = (object) $form_state['values'];
  // Check for sitemap_id sign.
  if (isset($form_state['storage']['sitemap_id']) && is_numeric($form_state['storage']['sitemap_id'])) {
    // Update if set.
    $sitemap_obj->sid = $form_state['storage']['sitemap_id'];
    drupal_write_record('google_image_sitemap', $sitemap_obj, 'sid');
  }
  else {
    // Insert if not set.
    $sitemap_obj->created = REQUEST_TIME;
    drupal_write_record('google_image_sitemap', $sitemap_obj);
  }
  // Redirect to main page of sitemap.
  $form_state['redirect'] = isset($_GET['destination']) ? $_GET['destination'] : GOOGLE_IMAGE_SITEMAP_ADMIN_PATH;
}

/**
 * This will delete a sitemap of user.
 */
function _google_image_sitemap_delete_form($sitemap_id) {
  // Validate sitemap_id string.
  if (!empty($sitemap_id) && ($sitemap_obj = _google_image_sitemap_valid_sitemap_id($sitemap_id))) {
    //$uri = file_build_uri('google_image_sitemap/sitemap_' . $sitemap_obj->created . '.xml');
    $uri = variable_get('file_public_path', 'sites/default/files') . '/google_image_sitemap/sitemap_' . $sitemap_obj->created . '.xml';
    if (file_unmanaged_delete($uri)) {
      db_delete('google_image_sitemap')
        ->condition('sid', $sitemap_id)
        ->execute();
      drupal_set_message(t("Sitemap deleted successfully!"));
    }
  }
  drupal_goto(isset($_GET['destination']) ? $_GET['destination'] : GOOGLE_IMAGE_SITEMAP_ADMIN_PATH);
}

/**
 * Menu callback for sitemap generate.
 */
function _google_image_sitemap_build($sitemap_id) {
  if (!empty($sitemap_id) && ($sitemap_obj = _google_image_sitemap_valid_sitemap_id($sitemap_id))) {
    // Get records.
    $query = db_select('node', 'n');
    $query->fields('n', array('nid', 'created', 'title'));
    $query->innerJoin('file_usage', 'fu', "n.nid = fu.id");
    $query->innerJoin('file_managed', 'f', "fu.fid = f.fid");
    $query->fields('f', array('uri'));
    // Use a 'node_access' tag with a query to find out how many this user has
    // access to. This will be the standard way to make lists while respecting
    // node access restrictions.
    $query->addTag('node_access');
    $query->condition('n.type', $sitemap_obj->node_type);
    $query->condition('n.status', NODE_PUBLISHED);
    $query->condition('f.filemime', array('image/png', 'image/jpg', 'image/gif', 'image/jpeg'), 'IN');
    $query->orderBy('n.created', 'DESC');
    $query->orderBy('f.timestamp', 'DESC');
    $query->range(($sitemap_obj->range_start - 1), ($sitemap_obj->range_end));
    $nodes = $query->execute()->fetchAll();
    // Create only if images are found.
    if (count($nodes) > 0) {
      $output = '<?xml version="1.0" encoding="UTF-8"?>';
      $output .= '<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9"
                  xmlns:image="http://www.google.com/schemas/sitemap-image/1.1">';
      foreach ($nodes as $node) {
        $output .= '<url><loc>' . url('node/' . $node->nid, array('absolute' => TRUE)) . '</loc>
                    <image:image>
                      <image:loc>' . file_create_url($node->uri) . '</image:loc>
                      <image:title>' . check_plain($node->title) . '</image:title>
                      <image:caption>' . check_plain($node->title) . '</image:caption>
                      <image:license>' . check_url($sitemap_obj->license) . '</image:license>
                    </image:image></url>';
      }
      $output .= '</urlset>';
      // File build path.
      // $path = file_build_uri('google_image_sitemap');
      $path = variable_get('file_public_path', 'sites/default/files') . '/google_image_sitemap';
      if (!is_dir($path)) {
        drupal_mkdir($path);
      }
      $filename = 'sitemap_' . $sitemap_obj->created . '.xml';
      if ($file = file_unmanaged_save_data($output, $path . '/' . $filename, FILE_EXISTS_REPLACE)) {
        db_update('google_image_sitemap')
          ->fields(array('last_updated' => REQUEST_TIME))
          ->condition('sid', $sitemap_obj->sid, '=')
          ->execute();
        drupal_set_message(t("Sitemap created successfully!"));
      }
    }
    else {
      drupal_set_message(t("No Images found!"));
    }
  }
  drupal_goto(isset($_GET['destination']) ? $_GET['destination'] : GOOGLE_IMAGE_SITEMAP_ADMIN_PATH);
}

/**
 * This will check a valid sitemap_id with database table.
 */
function _google_image_sitemap_valid_sitemap_id($sitemap_id) {
  $result = db_query("SELECT * FROM {google_image_sitemap} WHERE sid = :sid", array(':sid' => $sitemap_id));
  if ($row = $result->fetchObject()) {
    return $row;
  }
  else {
    return FALSE;
  }
}

/**
 * Implements hook_node_type_update().
 */
function google_image_sitemap_node_type_update($info) {
  if (!empty($info->old_type) && $info->old_type != $info->type) {
    db_update('google_image_sitemap')
      ->fields(array('node_type' => $info->type))
      ->condition('node_type', $info->old_type, '=')
      ->execute();
  }
}

/**
 * Implements hook_node_type_delete().
 */
function google_image_sitemap_node_type_delete($info) {
  // Node type is being deleted, delete its preferences.
  db_delete('google_image_sitemap')
    ->condition('node_type', $info->type);
}
