You are here

galleria.module in Galleria 7

Same filename and directory in other branches
  1. 6 galleria.module

A light-weight, customizable image gallery plugin for Drupal based on jQuery

File

galleria.module
View source
<?php

/**
 * @file
 * A light-weight, customizable image gallery plugin for Drupal based on jQuery
 */

/**
 * Implements hook_permission().
 */
function galleria_permission() {
  return array(
    'administer galleria' => array(
      'title' => t('Administer the Galleria module'),
    ),
  );
}

/**
 * Implements hook_menu().
 */
function galleria_menu() {
  $items = array();
  $items['admin/config/media/galleria'] = array(
    'title' => 'Galleria',
    'description' => 'Configure Galleria image galleries.',
    'page callback' => 'galleria_page_optionset_list',
    'access arguments' => array(
      'administer galleria',
    ),
    'file' => 'includes/galleria.admin.inc',
  );
  $items['admin/config/media/galleria/list'] = array(
    'title' => 'Option sets',
    'description' => 'List the current Galleria option sets.',
    'type' => MENU_DEFAULT_LOCAL_TASK,
    'weight' => 1,
  );
  $items['admin/config/media/galleria/add'] = array(
    'title' => 'Add option set',
    'description' => 'Add a new Galleria option set.',
    'page callback' => 'drupal_get_form',
    'page arguments' => array(
      'galleria_form_optionset_add',
    ),
    'access arguments' => array(
      'administer galleria',
    ),
    'type' => MENU_LOCAL_ACTION,
    'weight' => 1,
    'file' => 'includes/galleria.admin.inc',
  );
  $items['admin/config/media/galleria/edit/%galleria_optionset'] = array(
    'title' => 'Edit option set',
    'description' => 'Configure an option set.',
    'page callback' => 'drupal_get_form',
    'page arguments' => array(
      'galleria_form_optionset_edit',
      5,
    ),
    'access arguments' => array(
      'administer galleria',
    ),
    'file' => 'includes/galleria.admin.inc',
  );
  $items['admin/config/media/galleria/delete/%galleria_optionset'] = array(
    'title' => 'Delete option set',
    'description' => 'Delete an option set.',
    'page callback' => 'drupal_get_form',
    'page arguments' => array(
      'galleria_optionset_form_delete',
      5,
    ),
    'access arguments' => array(
      'administer galleria',
    ),
    'file' => 'includes/galleria.admin.inc',
  );
  $items['admin/config/media/galleria/advanced'] = array(
    'title' => 'Advanced settings',
    'description' => 'Configure the advanced Galleria module settings.',
    'page callback' => 'drupal_get_form',
    'page arguments' => array(
      'galleria_form_settings',
    ),
    'access arguments' => array(
      'administer galleria',
    ),
    'type' => MENU_LOCAL_TASK,
    'weight' => 2,
    'file' => 'includes/galleria.admin.inc',
  );
  $items['admin/config/media/galleria/import'] = array(
    'title' => 'Import',
    'description' => 'Import Galleria option sets',
    'page callback' => 'galleria_form_optionset_import',
    'access arguments' => array(
      'administer galleria',
    ),
    'type' => MENU_LOCAL_TASK,
    'weight' => 3,
    'file' => 'includes/galleria.admin.inc',
  );
  $items['admin/config/media/galleria/export'] = array(
    'title' => 'Export',
    'description' => 'Export Galleria option sets',
    'page callback' => 'galleria_form_optionset_export',
    'access arguments' => array(
      'administer galleria',
    ),
    'type' => MENU_LOCAL_TASK,
    'weight' => 4,
    'file' => 'includes/galleria.admin.inc',
  );
  return $items;
}

/**
 * Implements hook_help().
 */
function galleria_help($path, $arg) {
  switch ($path) {
    case 'admin/config/media/galleria/edit/%':
      return '<p>' . t('An <em>option set</em> defines exactly how a Galleria image gallery looks like on your site. ' . 'It is s a combination of <a href="@styles">image styles</a> for the various image sizes, Galleria theme and options.', array(
        '@styles' => url('admin/config/media/image-styles'),
      )) . '<br />' . t('For a full documentation of all options, refer to the official <a href="@docs">Galleria documentation</a>.', array(
        '@docs' => url('http://galleria.aino.se/docs/1.2/options/'),
      )) . '</p>';
    case 'admin/config/media/galleria/advanced':
      return '<p>' . t('This page lists some automatically detected files and folders. To improve performance, they are cached until the files get deleted.<br />' . 'If the module behaves strangely, try to clear the cached values below.') . '</p>';
  }
}

/**
 * Implements hook_theme().
 */
function galleria_theme() {
  return array(
    'galleria_container' => array(
      'variables' => array(
        'items' => array(),
        'settings' => array(),
      ),
      'template' => 'theme/galleria-container',
      'file' => 'theme/theme.inc',
    ),
    'galleria_form_table' => array(
      'render element' => 'form',
      'file' => 'includes/galleria.admin.inc',
    ),
  );
}

/**
 * Implements hook_image_default_styles().
 *
 * Provides default image style presets that can be overridden by site administrators.
 */
function galleria_image_default_styles() {
  $styles = array();

  // image preset for the big image
  $styles['galleria_zoom'] = array(
    'effects' => array(
      array(
        'name' => 'image_scale',
        'data' => array(
          'width' => 450,
          'height' => 300,
          'upscale' => 1,
        ),
        'weight' => 0,
      ),
    ),
  );

  // image preset for thumbnails
  $styles['galleria_thumb'] = array(
    'effects' => array(
      array(
        'name' => 'image_scale',
        'data' => array(
          'width' => 50,
          'height' => 40,
          'upscale' => 1,
        ),
        'weight' => 0,
      ),
    ),
  );
  return $styles;
}

/**
 * Implements hook_ctools_plugin_api().
 */
function galleria_ctools_plugin_api($owner, $api) {
  if ($owner == 'galleria' && $api == 'galleria_default_preset') {
    return array(
      'version' => 1,
    );
  }
}

/**
 * Implements hook_views_api().
 *
 * This tells drupal that there is Views integration file named
 * galleria.views.inc
 */
function galleria_views_api() {
  return array(
    'api' => 3,
  );
}

/**
 * Fetches all option sets from the database and returns them as an associative array.
 */
function galleria_optionsets_load_all() {
  ctools_include('export');
  return ctools_export_crud_load_all('galleria_optionset');
}

/**
 * Fetches the given option set and returns it as an object or NULL, if no set could be found.
 */
function galleria_optionset_load($optionset_name) {
  ctools_include('export');
  return ctools_export_crud_load('galleria_optionset', $optionset_name);
}

/**
 * Checks whether an option set with the given name already exists.
 */
function galleria_optionset_exists($optionset_name) {
  ctools_include('export');
  return ctools_export_crud_load('galleria_optionset', $optionset_name) !== NULL;
}

/*
 * Returns the JavaScript file of the Galleria core.
 * Uses a cached filename until this file gets deleted or the cache gets cleared.
 */
function galleria_get_library_file() {
  $cache = cache_get('galleria_lib_file');
  if ($cache !== FALSE && file_exists($cache->data)) {
    return $cache->data;
  }

  // Search for library file
  $libpath = libraries_get_path('galleria');

  // Seach for minimized files first.
  // Sort the found files to use the newest version if there's more than one.
  $js = glob($libpath . '/galleria-*.min.js');
  if ($js === FALSE || count($js) == 0) {
    $js = glob($libpath . '/galleria-*.js');
  }
  if (count($js) > 0) {
    rsort($js);
    cache_set('galleria_lib_file', $js[0]);
    return $js[0];
  }
  else {

    // Could not find JavaScript library
    return FALSE;
  }
}

/**
 * Searches for available themes inside the Galleria folder.
 * The list of themes is cached for performance reasons.
 */
function galleria_get_themes($nocache = FALSE) {
  if (!$nocache && ($themes = cache_get('galleria_themes')) !== FALSE) {
    return $themes->data;
  }
  $themes = array();

  // Search for theme folders
  $path = libraries_get_path('galleria') . '/themes/';
  if (is_dir($path) && ($path_handle = opendir($path)) !== FALSE) {
    while (($theme = readdir($path_handle)) !== FALSE) {
      if (!is_dir($path . $theme) || $theme[0] == '.') {
        continue;
      }

      // Search for the theme JavaScript file, minified version first
      $js = glob($path . $theme . '/*.min.js');
      if ($js === FALSE || count($js) == 0) {
        $js = glob($path . $theme . '/*.js');
      }

      // Sort by filename to (hopefully) get the newest version.
      if (count($js) > 0) {
        rsort($js);
        $themes[$theme] = $js[0];
      }
    }
    closedir($path_handle);
    cache_set('galleria_themes', $themes);
  }
  return $themes;
}

/**
 * Returns the JavaScript file of the given theme, or FALSE if it could not be found.
 */
function galleria_get_theme_file($theme) {
  $themes = galleria_get_themes();
  return isset($themes[$theme]) ? $themes[$theme] : FALSE;
}

/**
 * Searches for available plugins inside the Galleria folder.
 * The list of plugins is cached for performance reasons.
 */
function galleria_get_plugins($nocache = FALSE) {
  if (!$nocache && ($plugins = cache_get('galleria_plugins')) !== FALSE) {
    return $plugins->data;
  }
  $plugins = array();

  // Search for theme folders
  $path = libraries_get_path('galleria') . '/plugins/';
  if (is_dir($path) && ($path_handle = opendir($path)) !== FALSE) {
    while (($plugin = readdir($path_handle)) !== FALSE) {
      if (!is_dir($path . $plugin) || $plugin[0] == '.') {
        continue;
      }

      // Search for the theme JavaScript file, minified version first
      $js = glob($path . $plugin . '/*.min.js');
      if ($js === FALSE || count($js) == 0) {
        $js = glob($path . $plugin . '/*.js');
      }

      // Sort by filename to (hopefully) get the newest version.
      if (count($js) > 0) {
        rsort($js);
        $plugins[$plugin] = $js[0];
      }
    }
    closedir($path_handle);
    cache_set('galleria_plugins', $plugins);
  }
  return $plugins;
}

/**
 * Returns the JavaScript file of the given plugin, or FALSE if it could not be found.
 */
function galleria_get_plugin_file($plugin) {
  $plugins = galleria_get_plugins();
  return isset($plugins[$plugin]) ? $plugins[$plugin] : FALSE;
}

/**
 * Implements hook_field_formatter_info().
 *
 * Adds the Galleria format option within the manage display form of
 * of an image field.
 */
function galleria_field_formatter_info() {
  return array(
    'galleria' => array(
      'label' => t('Galleria'),
      'field types' => array(
        'image',
        'media',
        'node_reference',
        'file',
      ),
      'settings' => array(
        'optionset' => 'default',
        'title_field' => '',
        'alt_field' => '',
        'referenced_fields' => array(),
      ),
    ),
  );
}

/**
 * Implements hook_field_formatter_settings_form().
 *
 * Provides display settings form within the manage display page of
 * an image field with formatter galleria.
 */
function galleria_field_formatter_settings_form($field, $instance, $view_mode, $form, &$form_state) {
  $display = $instance['display'][$view_mode];
  $settings = $display['settings'];
  $form = array(
    '#tree' => TRUE,
  );

  // Show select box for the option set
  $optionsets = array();
  foreach (galleria_optionsets_load_all() as $name => $optionset) {
    $optionsets[$name] = check_plain($optionset->title);
  }
  $form['optionset'] = array(
    '#title' => t('Option set'),
    '#type' => 'select',
    '#options' => $optionsets,
    '#default_value' => $settings['optionset'],
  );
  if ($field['type'] == 'file') {

    // Provide alternate settings to allow selection of caption and alt tags.
    $bundles = field_info_instances('file');

    // Determine if there are additional fields on the image instance.
    if (isset($bundles['image']) && !empty($bundles['image'])) {
      $options = array(
        '' => t('None'),
      );
      foreach ($bundles['image'] as $field_name => $field_details) {
        $options[$field_name] = $field_details['label'];
      }
      $form['alt_field'] = array(
        '#title' => t('Alt field'),
        '#description' => t('Select an optional field to draw alt tags from.'),
        '#type' => 'select',
        '#options' => $options,
        '#default_value' => isset($settings['alt_field']) ? $settings['alt_field'] : '',
      );
      $form['title_field'] = array(
        '#description' => t('Select an optional field to draw images titles from.'),
        '#title' => t('Title field'),
        '#type' => 'select',
        '#options' => $options,
        '#default_value' => isset($settings['title_field']) ? $settings['title_field'] : '',
      );
    }
  }

  // Show select box for image fields if we're formatting a node_reference field
  if ($field['type'] == 'node_reference') {

    // Find all image fields
    $referenceable_types = array_filter($field['settings']['referenceable_types']);
    foreach ($referenceable_types as $referenceable_type) {
      $image_fields = array();
      foreach (field_info_instances('node', $referenceable_type) as $field_name => $field_instance) {
        $field = field_info_field($field_name);
        if ($field['type'] == 'image' || $field['type'] == 'media') {
          $image_fields[$field_name] = $field_instance['label'];
        }
      }
      if (!empty($image_fields)) {
        $form['referenced_fields'][$referenceable_type] = array(
          '#type' => 'checkboxes',
          '#title' => node_type_get_name($referenceable_type),
          '#options' => $image_fields,
          '#default_value' => isset($settings['referenced_fields'][$referenceable_type]) ? $settings['referenced_fields'][$referenceable_type] : array(),
        );
      }
    }
    if (count($form['referenced_fields']) == 0) {
      drupal_set_message(t('The referenced node type(s) does not contain any valid image fields.'), 'error');
    }
    else {
      $form['referenced_fields'] += array(
        '#type' => 'fieldset',
        '#title' => t('Image source fields'),
        '#description' => t('Select the image fields of the referenced content types to use as the source for Galleria.'),
      );
    }
  }
  return $form;
}

/**
 * Implements hook_field_formatter_settings_summary().
 *
 * Displays the summary of the set options of a Galleria formatted image field
 */
function galleria_field_formatter_settings_summary($field, $instance, $view_mode) {
  $display = $instance['display'][$view_mode];
  $settings = $display['settings'];
  $summary = array();

  // Optionset
  $optionset = t('Default settings');
  if (!empty($settings['optionset'])) {
    $o = galleria_optionset_load($settings['optionset']);
    if ($o !== NULL) {
      $optionset = $o->title;
    }
  }
  $summary[] = t('Option set: %optionset', array(
    '%optionset' => $optionset,
  ));

  // Summary for file fields.
  if ($field['type'] == 'file') {

    // Prepare options list.
    if (!empty($settings['alt_field']) || !empty($settings['title_field'])) {
      $bundles = field_info_instances('file');

      // Determine if there are additional fields on the image instance.
      if (isset($bundles['image']) && !empty($bundles['image'])) {
        $options = array(
          '' => t('None'),
        );
        foreach ($bundles['image'] as $field_name => $field_details) {
          $options[$field_name] = $field_details['label'];
        }
      }
    }
    if (!empty($settings['alt_field'])) {
      $summary[] = t('Alt field: @title', array(
        '@title' => $options[$settings['alt_field']],
      ));
    }
    if (!empty($settings['title_field'])) {
      $summary[] = t('Title field: @title', array(
        '@title' => $options[$settings['title_field']],
      ));
    }
  }

  // For node_reference fields: Referenced image fields
  if ($field['type'] == 'node_reference') {
    $referenced_fields = array();
    foreach ($settings['referenced_fields'] as $node_type => $fields) {
      $fields = array_keys(array_filter($fields));
      if (!empty($fields)) {
        foreach ($fields as &$field) {
          $field_info = field_info_instance('node', $field, $node_type);
          $field = $field_info['label'];
        }
        $referenced_fields[] = node_type_get_name($node_type) . ': ' . implode(', ', $fields);
      }
    }
    $referenced_fields = empty($referenced_fields) ? t('All') : implode('; ', $referenced_fields);
    $summary[] = t('Referenced image fields: %fields', array(
      '%fields' => $referenced_fields,
    ));
  }
  return '<p>' . implode("</p>\n<p>", $summary) . '</p>';
}

/**
 * Implements hook_field_formatter_prepare_view().
 * 
 * Loads the attached nodes for node_reference fields so we can later access the image fields.
 */
function galleria_field_formatter_prepare_view($entity_type, $entities, $field, $instances, $langcode, &$items, $displays) {
  if ($field['type'] == 'node_reference') {

    // Collect ids to load.
    $ids = array();
    foreach ($displays as $id => $display) {
      foreach ($items[$id] as $item) {
        if ($item['access']) {
          $ids[$item['nid']] = $item['nid'];
        }
      }
    }

    // Load the nodes.
    $nodes = node_load_multiple($ids);
    field_attach_prepare_view('node', $nodes, 'default', $langcode);
    entity_prepare_view('node', $nodes, $langcode);

    // Add the loaded nodes to the items.
    foreach ($displays as $id => $display) {
      foreach ($items[$id] as &$item) {
        if ($item['access']) {
          $item['node'] = $nodes[$item['nid']];
        }
      }
    }
  }
}

/**
 * Implements hook_field_formatter_view().
 *
 * Prepares a renderable array of images and adds the neccessary JS and CSS
 */
function galleria_field_formatter_view($entity_type, $entity, $field, $instance, $langcode, $items, $display) {
  if ($field['type'] == 'media') {
    $items = galleria_prepare_media_images($items);
  }
  elseif ($field['type'] == 'file') {
    $items = galleria_prepare_file_images($items, $display['settings'], $langcode);
  }
  elseif ($field['type'] == 'node_reference') {

    // Cleanup referenced_fields array
    $referenced_fields =& $display['settings']['referenced_fields'];
    foreach ($referenced_fields as &$field) {
      $field = array_filter($field);
    }
    $referenced_fields = array_filter($referenced_fields);

    // Collect items
    $images = array();
    foreach ($items as $item) {
      $node = $item['node'];
      foreach (field_info_instances('node', $node->type) as $field_name => $field_instance) {
        $field_info = field_info_field($field_name);
        if ($field_info['type'] == 'image' || $field_info['type'] == 'media') {
          if (empty($referenced_fields) || !empty($referenced_fields[$node->type][$field_name])) {
            $lang = field_language('node', $node, $field_name, $langcode);
            $node_items = $node->{$field_name}[$lang];
            if ($field_info['type'] == 'media') {
              $node_items = galleria_prepare_media_images($node_items);
            }
            $images = array_merge($images, $node_items);
          }
        }
      }
    }
    $items = $images;
  }
  $element = array();
  if (count($items) > 0) {
    $element[] = array(
      '#theme' => 'galleria_container',
      '#items' => $items,
      '#settings' => $display['settings'],
    );
  }
  return $element;
}

/**
 * Util function to parse media $items and return images in format expected by
 * galleria formatter.
 *
 * @param array $items
 *   Array of field items.
 */
function galleria_prepare_media_images($items) {
  $image_items = array();
  foreach ($items as $item) {
    if ($item['file']->type == 'image') {
      $file = (array) $item['file'];
      $file += array(
        'alt' => '',
        'title' => '',
      );
      $image_items[] = $file;
    }
  }
  return $image_items;
}

/**
 * Util function to parse file $items and return images in format expected by
 * galleria formatter.
 *
 * @param array $items
 *   Array of field items.
 * @param array $settings
 *   Array of settings
 * @param string $langcode
 *   Language code of the field
 */
function galleria_prepare_file_images($items, $settings, $langcode) {
  $image_fids = array();
  $alt_field = empty($settings['alt_field']) ? FALSE : $settings['alt_field'];
  $title_field = empty($settings['title_field']) ? FALSE : $settings['title_field'];

  // First pass, fetch the fids. We pass twice so we can minimize calls to
  // entity_load which is expensive to call multiple times.
  foreach ($items as $delta => $item) {
    if ($item['type'] == 'image') {
      $image_fids[] = $item['fid'];

      // Set a sensible default.
      $items[$delta]['alt'] = $items[$delta]['title'] = '';
    }
    else {

      // Galleria only handles images.
      unset($items['key']);
    }
  }
  $file_entities = entity_load('file', $image_fids);

  // Second pass, set the alt/title tag.
  foreach ($items as $delta => $item) {
    if ($item['type'] == 'image') {
      $file_entity = $file_entities[$item['fid']];
      if ($alt_field) {
        $alt_field_items = field_get_items('file', $file_entity, $alt_field, $langcode);
        if (!empty($alt_field_items[0]['safe_value'])) {
          $items[$delta]['alt'] = $alt_field_items[0]['safe_value'];
        }
      }
      if ($title_field) {
        $title_field_items = field_get_items('file', $file_entity, $title_field, $langcode);
        if (!empty($title_field_items[0]['safe_value'])) {
          $items[$delta]['title'] = $title_field_items[0]['safe_value'];
        }
      }
    }
  }
  return $items;
}

/**
 * This function loads the required JavaScripts and settings for a Galleria instance.
 */
function galleria_add_js($id, $optionset) {

  // Static array to remember which scripts are already attached.
  $cache =& drupal_static(__FUNCTION__, array());

  // Library JavaScript
  //   Cache this filename to prevent multiple file_exists() calls.
  if (!isset($cache['lib'])) {
    $lib = galleria_get_library_file();
    if ($lib === FALSE) {
      drupal_set_message(t('The Galleria JavaScript file was not found in its path. Please refer to README.txt for installation instructions.'), 'error');
      return;
    }
    $cache['lib'] = $lib;
  }
  drupal_add_js($cache['lib'], array(
    'group' => JS_LIBRARY,
  ));

  // Theme
  //   As it's only possible to use one theme per page, use the first one we get for everything.
  if (empty($cache['theme'])) {
    $theme = !empty($optionset->theme) ? $optionset->theme : 'classic';
    $theme_file = galleria_get_theme_file($theme);
    if ($theme_file === FALSE && $theme !== 'classic') {

      // Try to fall back to classic theme, the other one might have been deleted.
      $theme_file = galleria_get_theme_file('classic');
    }
    $cache['theme'] = $theme_file;
  }

  // Plugins
  $plugins = empty($optionset->plugins) ? array() : $optionset->plugins;
  foreach ($plugins as $plugin) {
    if (empty($cache['plugins'][$plugin])) {
      $plugin_file = galleria_get_plugin_file($plugin);
      if ($plugin_file !== FALSE) {
        $cache['plugins'][$plugin] = $plugin_file;
        drupal_add_js($plugin_file);
      }
    }
  }

  // JavaScript settings
  $js_settings = array(
    'themepath' => file_create_url($cache['theme']),
    'optionsets' => array(
      $optionset->name => $optionset->options,
    ),
    'instances' => array(
      'galleria-' . $id => $optionset->name,
    ),
  );
  drupal_add_js(array(
    'galleria' => $js_settings,
  ), 'setting');

  // Loader JavaScript
  drupal_add_js(drupal_get_path('module', 'galleria') . '/js/galleria.load.js');
}

Functions

Namesort descending Description
galleria_add_js This function loads the required JavaScripts and settings for a Galleria instance.
galleria_ctools_plugin_api Implements hook_ctools_plugin_api().
galleria_field_formatter_info Implements hook_field_formatter_info().
galleria_field_formatter_prepare_view Implements hook_field_formatter_prepare_view().
galleria_field_formatter_settings_form Implements hook_field_formatter_settings_form().
galleria_field_formatter_settings_summary Implements hook_field_formatter_settings_summary().
galleria_field_formatter_view Implements hook_field_formatter_view().
galleria_get_library_file
galleria_get_plugins Searches for available plugins inside the Galleria folder. The list of plugins is cached for performance reasons.
galleria_get_plugin_file Returns the JavaScript file of the given plugin, or FALSE if it could not be found.
galleria_get_themes Searches for available themes inside the Galleria folder. The list of themes is cached for performance reasons.
galleria_get_theme_file Returns the JavaScript file of the given theme, or FALSE if it could not be found.
galleria_help Implements hook_help().
galleria_image_default_styles Implements hook_image_default_styles().
galleria_menu Implements hook_menu().
galleria_optionsets_load_all Fetches all option sets from the database and returns them as an associative array.
galleria_optionset_exists Checks whether an option set with the given name already exists.
galleria_optionset_load Fetches the given option set and returns it as an object or NULL, if no set could be found.
galleria_permission Implements hook_permission().
galleria_prepare_file_images Util function to parse file $items and return images in format expected by galleria formatter.
galleria_prepare_media_images Util function to parse media $items and return images in format expected by galleria formatter.
galleria_theme Implements hook_theme().
galleria_views_api Implements hook_views_api().