<?php

/**
 * @file
 * Makes TinyMCE Templates available as plugin for client-side editors integrated via
 * Wysiwyg API.
 */

 /**
 * Implementation of hook_menu().
 */
function wysiwyg_template_menu() {
  $items = array();

  // template overview settings page
  $items['admin/config/content/wysiwyg-templates'] = array(
    'title' => 'Wysiwyg templates',
    'description' => 'Create and modify Wysiwyg templates',
    'page callback' => 'drupal_get_form',
    'page arguments' => array('wysiwyg_template_overview'),
    'access arguments' => array('administer wysiwyg templates'),
    'file' => 'wysiwyg_template.admin.inc',
    'weight' => 10,
  );
  // add template
  $items['admin/config/content/wysiwyg-templates/add'] = array(
    'title' => 'Add Template',
    'page callback' => 'drupal_get_form',
    'page arguments' => array('wysiwyg_template_template_form'),
    'access arguments' => array('administer wysiwyg templates'),
    'type' => MENU_LOCAL_ACTION,
    'file' => 'wysiwyg_template.admin.inc',
  );
  // import template
  $items['admin/config/content/wysiwyg-templates/import'] = array(
    'title' => 'Import Template',
    'page callback' => 'drupal_get_form',
    'page arguments' => array('wysiwyg_template_import_form'),
    'access arguments' => array('import wysiwyg templates'),
    'type' => MENU_LOCAL_ACTION,
    'file' => 'wysiwyg_template.admin.inc',
  );

  // edit template
  $items['admin/config/content/wysiwyg-templates/%wysiwyg_template/edit'] = array(
    'title' => 'Edit Template',
    'page callback' => 'drupal_get_form',
    'page arguments' => array('wysiwyg_template_template_form', 4),
    'access arguments' => array('administer wysiwyg templates'),
    'type' => MENU_CALLBACK,
    'parent' => 'admin/config/content/wysiwyg-templates',
    'file' => 'wysiwyg_template.admin.inc',
  );
  $items['admin/config/content/wysiwyg-templates/%wysiwyg_template/export'] = array(
    'title' => 'Export Template',
    'page callback' => 'drupal_get_form',
    'page arguments' => array('wysiwyg_template_export_form', 4),
    'access arguments' => array('administer wysiwyg templates'),
    'type' => MENU_CALLBACK,
    'parent' => 'admin/config/content/wysiwyg-templates',
    'file' => 'wysiwyg_template.admin.inc',
  );
  //delete template
  $items['admin/config/content/wysiwyg-templates/%wysiwyg_template/delete'] = array(
    'title' => 'Delete Template',
    'page callback' => 'drupal_get_form',
    'page arguments' => array('wysiwyg_template_delete_confirm', 4),
    'access arguments' => array('administer wysiwyg templates'),
    'file' => 'wysiwyg_template.admin.inc',
    'type' => MENU_CALLBACK,
  );

  // javascript template list
  $items['wysiwyg-templates/%/%/list'] = array(
    'page callback' => 'wysiwyg_template_list_js',
    'page arguments' => array(1, 2),
    'access arguments' => array('access content'),
    'type' => MENU_CALLBACK,
  );
  // individual template html - referenced by javascript above
  $items['wysiwyg-templates/%/load/%wysiwyg_template_html'] = array(
    'page callback' => 'wysiwyg_template_html_print',
    'page arguments' => array(3, 1),
    'access arguments' => array('access content'),
    'type' => MENU_CALLBACK,
  );
  return $items;
}

/**
 * Implements hook_permission().
 */
function wysiwyg_template_permission() {
  $perms = array();
  $perms['administer wysiwyg templates'] = array(
    'title' => t('Administer WYSIWYG Templates'),
    'description' => t('Create, edit and delete WYSIWYG templates.'),
  );
  $perms['import wysiwyg templates'] = array(
    'title' => t('Import WYSIWYG Templates'),
    'description' => t('Import WYSIWYG templates from exported code.'),
    'restrict access' => TRUE,
  );
  return $perms;
}

/**
 * Implements hook_theme().
 */
function wysiwyg_template_theme() {
  return array(
    'wysiwyg_template_overview' => array(
      'render element' => 'form',
      'file' => 'wysiwyg_template.admin.inc',
    ),
  );
}

/**
 * Wysiwyg template Wildcard menu loader - prepare item for the create/modify admin form
 *
 * @param $name
 *   Template machine name.
 *
 * @return
 *   The loaded template from the db.
 */
function wysiwyg_template_load($name) {
  $template = wysiwyg_template_load_template($name);
  return $template;
}

/**
 * Callback to determine the correct URL which allows the editor to receive
 * the list of templates.
 *
 * @param $editorName
 */
function _wysiwyg_template_get_list_url($editorName) {
  return url('wysiwyg-templates/' . $editorName . '/' . _wysiwyg_template_set_node_type() . '/list');
}

/**
 * Implementation of hook_wysiwyg_plugin().
 */
function wysiwyg_template_wysiwyg_plugin($editorName, $version) {
  switch ($editorName) {
    case 'tinymce':
      return array(
        'template' => array(
          'buttons' => array('template' => t('Insert templates')),
          'url' => 'http://drupal.org/project/wysiwyg_template',
          'internal' => TRUE,
          'options' => array(
            'template_external_list_url' => _wysiwyg_template_get_list_url($editorName),
            //load the javascript template list
            //'template_selected_content_classes' => variable_get('wysiwyg_template_selected_content_classes', ''),
            //'template_replace_values' => array('caption' => 'Replace with this content')
          ),
          'extended_valid_elements' => array( //tinymce specific - allows additional elements to be used
            'img[id|class|src|border=0|alt|title|width|height|align|name|style]',
          ),
          'load' => TRUE,
        ),
      );
      break;
    case 'ckeditor':
      return array(
        'templates' => array(
          'buttons' => array('Templates' => t('Insert templates')),
          'url' => 'http://drupal.org/project/wysiwyg_template',
          'internal' => TRUE,
          'options' => array(
            'templates_files' => array(_wysiwyg_template_get_list_url($editorName)),
            //load the javascript template list
            'templates_replaceContent' => false,
          ),
          'load' => FALSE,
        ),
      );
      break;
    case 'fckeditor':
      return array(
        'templates' => array(
          'buttons' => array('Templates' => t('Insert templates')),
          'url' => 'http://drupal.org/project/wysiwyg_template',
          'internal' => TRUE,
          'options' => array(
            'TemplatesXmlPath' => array(_wysiwyg_template_get_list_url($editorName)),
            //load the javascript template list
          ),
          'load' => FALSE,
        ),
      );
      break;
  }
}

function wysiwyg_template_ckeditor_settings_alter(&$settings) {
  $settings['templates_files'] = array(_wysiwyg_template_get_list_url('ckeditor'));
}

/**
 * Implements hook_features_api().
 */
function wysiwyg_template_features_api() {
  return array(
    'wysiwyg_template' => array(
      'name' => t('WYSIWYG Template'),
      'default_hook' => 'wysiwyg_template_default_templates',
      'default_file' => FEATURES_DEFAULTS_INCLUDED,
      'feature_source' => TRUE,
      'file' => drupal_get_path('module', 'wysiwyg_template') . '/wysiwyg_template.features.inc',
    ),
  );
}

/**
 * Generate javascript for template loading
 */
function wysiwyg_template_list_js($editorName, $contentType) {
  global $base_url;
  //don't cache templates
  drupal_add_http_header('CacheControl', 'no-cache');
  drupal_add_http_header('Expires', '-1');
  drupal_add_http_header('Content-Type', 'text/javascript; charset=UTF-8');
  $templates = wysiwyg_template_load_all($contentType);
  switch ($editorName) {
    case 'tinymce':
      print 'var tinyMCETemplateList = ';
      $outArray = array();
      foreach ($templates as $template) {
        $outArray[] = array(
          $template['title'],
          url('wysiwyg-templates/' . $editorName . '/load/') . $template['name'],
          $template['description'],
        );
      }
      print json_encode($outArray) . ";";
      break;
    case 'ckeditor':
      print "CKEDITOR.addTemplates( 'default', { imagesPath:'" . $base_url . "', templates: ";
      // load the templates into the json array structure
      foreach ($templates as &$template) {
        $template['html'] = $template['body'];
        unset($template['body']);
        unset($template['tid']);
      }
      print json_encode($templates);
      print "});";
      break;
    case 'fckeditor':
      print '<?xml version="1.0" encoding="utf-8" ?>';
      print '<Templates imagesBasePath="">';
      foreach ($templates as $template) {
        print '<Template title="' . check_plain($template['title']) . '" image="">';
        print '<Description>' . check_plain($template['description']) . '</Description>';
        print '<Html><![CDATA[';
        print $template['body'];
        print ']]></Html></Template>';
      }
      print '</Templates>';
      break;
    case '':
      break;
  }
}

/**
 * Menu callback to display the loaded template
 */
function wysiwyg_template_html_print($body, $editorName) {
  //don't cache templates
  drupal_add_http_header('CacheControl', 'no-cache');
  drupal_add_http_header('Expires', '-1');
  drupal_add_http_header('Content-Type', 'text/javascript; charset=UTF-8');
  switch ($editorName) {
    case 'tinymce':
      print $body;
      break;
  }
}

/**
 * Load a specific template for viewing, as called through the menu wildcard
 */
function wysiwyg_template_html_load($name) {
  $template = wysiwyg_template_load_template($name);
  return module_exists('token') ? token_replace($template['body']) : $template['body'];
}

/**
 * Wysiwyg template database load function
 */
function wysiwyg_template_load_template($name) {
  $templateResults = db_query("SELECT * FROM {wysiwyg_templates} WHERE name = :name", array(':name' => $name));
  $template = $templateResults->fetchObject();
  $tItem = null;
  if ($template != null) {
    $tItem = array(
      'title' => $template->title,
      'description' => $template->description,
      'weight' => $template->weight,
      'fid' => $template->fid,
      'body' => $template->body,
      'name' => $name,
      'content_types' => wysiwyg_template_load_template_content_types($name),
    );
  }

  return $tItem;
}

/**
 * Provide a list of content types for which the template $name is limited to.
 */
function wysiwyg_template_load_template_content_types($name) {
  $query = db_select('wysiwyg_templates_content_types', 'wc');
  $query->join('node_type', 'nt', 'wc.type = nt.type');
  return $query
    ->fields('wc', array('type'))
    ->fields('nt', array('name'))
    ->condition('wc.name', $name)
    ->execute()
    ->fetchAllKeyed();
}

/**
 * Implements hook_node_type_delete().
 */
function wysiwyg_template_node_type_delete($info) {
  db_query("DELETE FROM {wysiwyg_templates_content_types} WHERE type = :type", array(':type' => $info->type));
  db_query("DELETE FROM {wysiwyg_templates_default} WHERE type = :type", array(':type' => $info->type));
}

/**
 * Wysiwyg load all templates from the database
 */
function wysiwyg_template_load_all($contentType = '_', $forSelect = FALSE, $includeNone = FALSE) {
  global $base_url;
  $templateResults = db_query("SELECT * FROM {wysiwyg_templates} order by weight");
  $templates = array();
  foreach ($templateResults as $dbTemplate) {
    // Check, if the template is limited to a content type.
    if ($contentType != '_') {
      $types = db_select('wysiwyg_templates_content_types', 'wc')
        ->fields('wc', array('type'))
        ->condition('wc.name', $dbTemplate->name)
        ->execute()
        ->fetchCol();
      if (!empty($types)) {
        // The template is limited and we now check it.
        if (!in_array($contentType, $types)) {
          // Do not include this template.
          continue;
        }
      }
    }

    //get the image
    $image = file_load($dbTemplate->fid);
    if ($image) {
      $image_uri = str_replace($base_url, "", image_style_url('wysiwyg_template_thumbnail', $image->uri));
    }
    else {
      $image_uri = "";
    }
    $template = array(
      'title' => $dbTemplate->title,
      'description' => $dbTemplate->description,
      'weight' => $dbTemplate->weight,
      'image' => $image_uri,
      'body' => token_replace($dbTemplate->body),
      'name' => $dbTemplate->name,
    );
    $templates[] = $template;
  }
  // provide a hook to prepare the templates
  drupal_alter('wysiwyg_templates_load', $templates);
  if (!$forSelect) {
    return $templates;
  }

  $template_select = $includeNone ? array('' => '-' . t('none') . '-') : array();
  foreach ($templates as $template) {
    $template_select[$template['name']] = $template['title'];
  }
  return $template_select;
}

/**
 * Wysiwyg template database save function.
 */
function wysiwyg_template_save_template($template) {
  $new_template = array(
    'name' => $template['name'],
    'title' => $template['title'],
    'description' => $template['description'],
    'weight' => $template['weight'],
    'fid' => $template['fid'],
    'body' => (isset($template['body']['value']) && strlen($template['body']['value']) > 1) ? $template['body']['value'] : $template['body'],
  );

  $existing = wysiwyg_template_name_exists($template['name']);

  // Save to database.
  if (drupal_write_record('wysiwyg_templates', $new_template, ($existing ? 'name' : array()))) {
    db_query("DELETE FROM {wysiwyg_templates_content_types} WHERE name = :name", array(':name' => $template['name']));
    foreach ($template['content_types'] as $type) {
      if (!empty($type)) {
        $values = array(
          'name' => $template['name'],
          'type' => $type,
        );
        drupal_write_record('wysiwyg_templates_content_types', $values);
      }
    }
    return TRUE;
  }
  return FALSE;
}

/**
 * Wysiwyg template database delete function
 */
function wysiwyg_template_delete_template($name) {
  db_query("DELETE FROM {wysiwyg_templates_content_types} WHERE name = :name", array(':name' => $name));
  db_query("DELETE FROM {wysiwyg_templates_default} WHERE name = :name", array(':name' => $name));
  db_query("DELETE FROM {wysiwyg_templates} WHERE name = :name", array(':name' => $name));
}

function wysiwyg_template_name_exists($name) {
  return (bool) db_query('SELECT 1 FROM {wysiwyg_templates} WHERE name = :name', array(':name' => $name))->fetchField();
}

/**
 * Implements hook_image_default_styles().
 */
function wysiwyg_template_image_default_styles() {
  $styles = array();
  // supply the default image thumbnail style
  $styles['wysiwyg_template_thumbnail'] = array(
    'effects' => array(
      array(
        'name' => 'image_resize',
        'data' => array(
          'width' => 100,
          'height' => 70,
        ),
        'weight' => 0,
      ),
    ),
  );
  return $styles;
}

/**
 * Implements hook_form_FORM_ID_alter().
 */
function wysiwyg_template_form_node_type_form_alter(&$form, &$form_state, $form_id) {
  $type = $form['#node_type']->type;
  $form['wysiwyg_template'] = array(
    '#type' => 'fieldset',
    '#title' => t('Wysiwyg Template'),
    '#collapsible' => TRUE,
    '#collapsed' => TRUE,
    '#group' => 'additional_settings',
  );
  $form['wysiwyg_template']['wysiwyg_template_default'] = array(
    '#type' => 'select',
    '#title' => t('Default template for this content type'),
    '#options' => wysiwyg_template_load_all($type, TRUE, TRUE),
    '#default_value' => wysiwyg_template_load_default($type),
  );
  $form['#submit'][] = 'wysiwyg_template_form_node_type_form_submit';
}

function wysiwyg_template_form_node_type_form_submit($form, $form_state) {
  $name = $form_state['values']['wysiwyg_template_default'];
  $type = $form_state['values']['type'];
  if (!empty($name)) {
    db_merge('wysiwyg_templates_default')
      ->key(array('type' => $type))
      ->fields(array(
        'name' => $name,
        'type' => $type,
      ))
      ->execute();
  }
  else {
    db_delete('wysiwyg_templates_default')
      ->condition('type', $type)
      ->execute();
  }
}

function wysiwyg_template_load_default($type) {
  $name = db_select('wysiwyg_templates_default', 'w')
    ->fields('w', array('name'))
    ->condition('w.type', $type)
    ->execute()
    ->fetchField();
  return empty($name) ? '' : $name;
}

/**
 * Implements hook_form_FORM_ID_alter().
 */
function wysiwyg_template_form_node_form_alter(&$form, &$form_state, $form_id) {
  _wysiwyg_template_set_node_type($form['type']['#value']);
  if (!empty($form['nid']['#value'])) {
    // This is an existing node and we do *not* apply a template.
    return;
  }

  $type = $form['type']['#value'];
  $name = wysiwyg_template_load_default($type);
  if (empty($name)) {
    // There is no default defined and we have nothing to do.
    return;
  }

  $body = wysiwyg_template_html_load($name);
  if (empty($body)) {
    // Nothing to do.
    return;
  }

  $form['body'][LANGUAGE_NONE][0]['#default_value'] = $body;
}

/**
 * Callback to set/get the content type of the current node, defaults to '_'.
 */
function _wysiwyg_template_set_node_type($type = NULL) {
  static $content_type;
  if (isset($type)) {
    $content_type = $type;
  }

  return isset($content_type) ? $content_type : '_';
}
