Skip to content
gallery_base.inc 21.7 KiB
Newer Older
<?php
// $Id$

/**
 * gallery.module : gallery_base.inc
 * Base functions
 */

define(GALLERY_ERROR_WATCHDOG,  1);
define(GALLERY_ERROR_BROWSER,   2);
define(GALLERY_ERROR_VERBOSE,   3);

define(GALLERY_SEVERITY_SUCCESS,       1);
define(GALLERY_SEVERITY_ERROR,        -1);
define(GALLERY_SEVERITY_WARNING,      -2);
define(GALLERY_SEVERITY_ADVISE,       -3);
define(GALLERY_SEVERITY_UNKNOWN,      -4);

define(GALLERY_PLUGIN_ENABLED,         1);
define(GALLERY_PLUGIN_DISABLED,        0);
define(GALLERY_PLUGIN_STATUS_UNKNOWN, -1);
define(GALLERY_PLUGIN_NOT_ACTIVE,     -2);
define(GALLERY_PLUGIN_NOT_INSTALLED,  -3);
define(GALLERY_PLUGIN_MISSING,        -4);

define(GALLERY_DEBUGTRACE, TRUE);

/**
 * Function gallery_login().
 * (login user into embedded gallery)
function gallery_login() {
  _gallery_init();
}

/**
 * Function gallery_logout().
 * (end user session)
 */
function gallery_logout() {
  if (variable_get('gallery_valid', FALSE)) {
    require_once(variable_get('gallery_dir', './gallery2/') .'embed.php');
    GalleryEmbed::logout();
  }
}

 * Function _gallery_init().
 * (initialize embedded gallery)
function _gallery_init($full = FALSE, $vars = NULL, $report_error = TRUE) {
  static $ready = array('half' => FALSE, 'full' => FALSE);
  
  // Initialize only once
  if ($ready[$full ? 'full' : 'half']) {
    return TRUE;
  }
    $embed_path = variable_get('gallery_dir', './gallery2/') .'embed.php';
    $g2_uri =  variable_get('gallery_uri', '/gallery2/');
    $embed_uri = variable_get('gallery_embed_uri', '?q=gallery');
    $gallery_valid = variable_get('gallery_valid', 0);
    $uid = ($user->uid > 0) ? $user->uid : '';
  } 
  else {
    $embed_path = $vars['gallery_dir'] .'embed.php';
    $g2_uri = $vars['gallery_uri'];
    $embed_uri = $vars['gallery_embed_uri'];
    $gallery_valid = $vars['gallery_valid'];
    $uid = '';
  }
  
  $init_err_msg = t('Unable to initialize embedded Gallery. You need to <a href="@link"> configure your embedded Gallery</a>.',
                      array('@link' => url('admin/settings/gallery/install')));
  
  if ((!$gallery_valid) || (!is_readable($embed_path))) {
    if ($report_error) {
      gallery_error($init_err_msg);
    }
    return FALSE;
  }

  include_once($embed_path);
  
  // i18n url rewrite
  $language = gallery_get_language($user);
  if (module_exists('i18n')) {
    $embed_uri = preg_replace('/index.php\?q=/', i18n_path('index.php?q=', $language), $embed_uri);
  }
  
  $params = array('embedUri' => $embed_uri,
                  'g2Uri' => $g2_uri,
                  'loginRedirect' => url('user/login', drupal_get_destination(), NULL, TRUE),
                  'activeUserId' => $uid,
                  'activeLanguage' => $language,
                  'fullInit' => $full,
                  'apiVersion' => array(1, 2));

  $ret = GalleryEmbed::init($params);
  if ($ret) {
    if ($ret->getErrorCode() & ERROR_PLUGIN_VERSION_MISMATCH) {
      if ($report_error) {
        gallery_error($vars ? t('Embedding API version is incompatible.') : $init_err_msg, $ret, TRUE);
      return FALSE;
    else {
      if ($report_error) {
        gallery_error($init_err_msg, $ret, TRUE);
      return FALSE;
  
  if (!class_exists('GalleryEmbed') || !class_exists('GalleryCoreApi')) {
    if ($report_error) {
      gallery_error(t('Classes \'GalleryEmbed\' and/or \'GalleryCoreApi\' are not available,
                       although initialization seemed successful.'));
    }
    return FALSE;
  }
  
  $ready['half'] = $full ? ($ready['full'] = TRUE) : TRUE;
  
  return TRUE;
 * Function gallery_handle_request().
 * (handleRequest extension with error handling)
function gallery_handle_request() {
  // Remove the language-prefix for G2
  if (!empty($_GET['g2_path']) && module_exists('i18n')) {
    i18n_get_lang_prefix($_GET['g2_path'], TRUE);
  }
  
  ob_start();
  $result = GalleryEmbed::handleRequest();
  $output = ob_get_contents();
  ob_end_clean();
  
  if ($output) {
    if (!preg_match('%<h2>\sError\s</h2>%', $output)) {
      // If $output does not contain '<h2>Error</h2>', this is an AJAX/Image callback
      print $output;
      exit();
    }
    else {
      // Otherwise (on regular pages) $output means that an error occured
      if (variable_get('gallery_error_redirect', 0) && user_access('search content')) {
        drupal_set_message('The requested Gallery URL does not exist. The item may have been
                            moved or deleted. You can search for it below.', 'notice');
        drupal_goto('search/gallery');
      }
      preg_match('%<div id="giStackTrace" [^>]*>(.*?)</div>%is', $output, $matches);
      gallery_error(t('Error handling request (invalid request)<br />or the requested Gallery URL does not exist.'), $matches[1], TRUE);
      return NULL;
    }
 * Function gallery_get_language().
 * (get the language for $user)
kiz_0987's avatar
kiz_0987 committed
function gallery_get_language($user) {
  // Default is the user-specific language
  $language = $user->uid ? $user->language : '';
  // If i18n is enabled, use that language instead
  if (module_exists('i18n')) {
    $language = i18n_get_lang();
  }
  // If there is still no language available, try to get the default one
  if (empty($language)) {
    $language = 'en';
    if (module_exists('locale')) {
      $result = db_query('SELECT locale FROM {locales_meta} WHERE isdefault = 1');
      $language = db_result($result);
    }
  }
  // Convert certain lang codes, e.g. 'esl/spa es' => 'es' or 'fr-ca' => 'fr'
  return preg_replace(array('/([\w\/]+) ([a-z]{2,3})/i', '/([a-z]{2,3})-(\w+)/i'), array('${2}', '${1}'), $language);
kiz_0987's avatar
kiz_0987 committed
/**
 * Function gallery_get_themes().
 * (retrieve all (active) themes from Gallery2)
 */
function gallery_get_themes() {
  if (!_gallery_init()) {
    return array();
  }
  // List of themes
  list($ret, $g2_themes) = GalleryCoreApi::fetchPluginStatus('theme', TRUE);
  if ($ret) {
    gallery_error(t('Error retrieving theme list'), $ret);
    return array();
  }

  $themes = array();
  foreach (array_keys($g2_themes) as $themeid) {
    // Only active themes
    if (!empty($g2_themes[$themeid]['active'])) {
      // Get theme details
      list($ret, $theme) = GalleryCoreApi::loadPlugin('theme', $themeid, TRUE);
      if ($ret) {
        gallery_error(t('Error getting theme (:themeid) details',
          array(':themeid' => $themeid)), $ret);
        return array();
      }
      $themes[$themeid] = $theme->getName();
    }
  }

  return $themes;
}

/**
 * Function gallery_get_image_frames().
 * (retrieve all image frames from Gallery2)
 */
function gallery_get_image_frames() {
  if (!_gallery_init()) {
    return array('none' => t('None'));
  }
  // List of available image frames
  list($ret, $imageframe) = GalleryCoreApi::newFactoryInstance('ImageFrameInterface_1_1');
  if ($ret || !isset($imageframe)) {
      return array('none' => t('None'));
  }
  list($ret, $list) = $imageframe->getImageFrameList();
  if ($ret) {
      return array('none' => t('None'));
  }
  
  return $list;
}

/**
 * Function gallery_generate_url().
 */
function gallery_generate_url($params, $html = TRUE, $full = TRUE) {
  if (!_gallery_init(TRUE)) {
    return '';
  }
  // Get URL generator and generate the url
  $url_generator =& $GLOBALS['gallery']->getUrlGenerator();
  if (!$url_generator) {
    gallery_error(t('Error: UrlGenerator not available'));
    return '';
  }
  
  $options = array();
  $options['forceFullUrl'] = $full;
  $options['htmlEntities'] = $html;
  
  if (!isset($params['view'])) {
    $params['view'] = 'core.ShowItem';
  }
  
  return $url_generator->generateUrl($params, $options);
}

/**
 * Function gallery_album_tree().
 */
function gallery_album_tree($root = NULL, $depth = NULL, $uid = NULL) {
  if (!_gallery_init(TRUE)) {
    return array();
  }
  // If this is called for the Drupal guest user, pass in G2
  // anonymous user id (otherwise fetchAlbumTree() returns nothing)
  global $user;
  if (!$uid && !$user->uid) {
    list($ret, $uid) = GalleryCoreApi::getPluginParameter('module', 'core', 'id.anonymousUser');
    if ($ret) {
      return array();
    }
  }
  // Fetch G2 album tree
  list($ret, $tree) = GalleryCoreApi::fetchAlbumTree($root, $depth, $uid);
  if ($ret) {
    gallery_error(t('Error fetching album tree'), $ret);
    return array();
  }

  return $tree;
}

/**
 * Function gallery_item_details().
 */
function gallery_item_details($id, $verbose = FALSE) {
  $details = array();
  if (!_gallery_init(TRUE)) {
    return $details;
  }
  // Load entity
  list($ret, $entity) = GalleryCoreApi::loadEntitiesById($id);
  if ($ret) {
    gallery_error(t('Error fetching item details (entityId: :id)',
      array(':id' => $id)), $ret);
    return $details;
  }
  // Extract details
  $details['g2type'] = $entity->entityType;
  $details['g2owner'] = $entity->ownerId;
  $details['g2parent'] = $entity->parentId;
  // Drupal node properties (no g2 prefix)
  $details['title'] = _gallery_htmlcharsdecode($entity->title);
  $details['created'] = $entity->creationTimestamp;

  if ($verbose) {
    $details['g2description'] = _gallery_htmlcharsdecode($entity->description);
    $details['g2summary'] = _gallery_htmlcharsdecode($entity->summary);
    $details['g2keywords'] = $entity->keywords;
    $details['g2theme'] = isset($entity->theme) ? $entity->theme : NULL;
  }

  return $details;
}

/**
 * Function gallery_db_query().
 */
function gallery_db_query($query, $data = NULL) {
  if (!_gallery_init(TRUE)) {
    return FALSE;
  }
  // Perform query
  list ($ret, $search) = $GLOBALS['gallery']->search($query, $data);
	if ($ret) {
    return FALSE;
	}
	$results = array();
	while ($result = $search->nextResult()) {
    $results += $result;
  }

  return $results;
}

/**
 * Function gallery_flush_entity_cache().
 */
function gallery_flush_entity_cache() {
  if (!_gallery_init()) {
    return FALSE;
  }
  // Flush entity cache
  $platform =& $GLOBALS['gallery']->getPlatform();
  $cache_basedir = $GLOBALS['gallery']->getConfig('data.gallery.cache');
  $cache_dir = $cache_basedir .'entity';

  if ($platform->file_exists($cache_dir)) {
    if (!$platform->recursiveRmDir($cache_dir)) {
      return FALSE;
    }
  }

  return TRUE;
}

/**
 * Function gallery_set_head().
 */
function gallery_set_head($html, $settitle = FALSE) {
  if (!empty($html)) {
    list($title, $css, $javascript) = GalleryEmbed::parseHead($html);
    if ($settitle) {
      drupal_set_title($title);
    }
    gallery_set_css($css);
    gallery_set_javascript($javascript);
  }
}

/**
 * Function gallery_set_css().
 */
function gallery_set_css($css) {
  global $base_url;
  static $css_memory = array();
  
  if (count($css)) {
    $css = preg_replace('/<link(.*?)href="([^"]*)"(.*?)\/>/i', '${2}', $css);
    foreach ($css as $include) {
      if (!in_array(($md5 = md5($include)), $css_memory)) {
        $css_memory[] = $md5;
        if (variable_get('gallery_outside', 0)) {
          // drupal_add_css() does not support external paths
          drupal_set_html_head('<link type="text/css" rel="stylesheet" media="all" href="'. $include .'" />');
        }
        else {
          $include = preg_replace(array('#^'. $base_url .'#', '#^'. base_path() .'#', '#^/#'), '', $include);
          // Workaround for urls containing '&amp;' with @import directive (#157978)
          $include = str_replace('&amp;g2_frames', '&g2_frames', $include);
          if (substr($include, 0, 6) == '<style') {
            // drupal_add_css() does not support inline styles
            drupal_set_html_head($include);
          }
          elseif (substr($include, 0, 4) == 'http') {
            // drupal_add_css() does not support external paths
            drupal_set_html_head('<style type="text/css" media="all">@import "'. $include .'";</style>');
          }
          else {
            // Gallery's css must always be added first to allow overriding from the module(s)
            drupal_add_css($include, 'module', 'all', FALSE);
          }
        }
      }
    }
  }
}

/**
 * Function gallery_set_javascript().
 * (druapl_add_js() ensures proper cascading of included G2 javascript)  
 */
function gallery_set_javascript($javascript) {
  global $base_url;
  static $js_memory = array();
  
  if (!empty($javascript)) {
    $files = preg_grep('/<script(.*?)src=/i', $javascript);
    // Inline Javascript
    $inline = array_diff($javascript, $files);
    $inline = preg_replace('/<script([^>]*)>(.*?)<\/script>/is', '\2', $inline);
    drupal_add_js(implode("\n", $inline), 'inline');
    // Javascript files
    $files = preg_replace('/<script(.*?)src="([^"]*)"([^>]*)>(.*?)<\/script>/i', '${2}', $files);
    foreach ($files as $include) {
      if (!in_array(($md5 = md5($include)), $js_memory)) {
        $js_memory[] = $md5;
        if (variable_get('gallery_outside', 0)) {
          // drupal_add_js() does not support external paths
          drupal_set_html_head('<script type="text/javascript" src="'. $include .'"></script>');
        }
        else {
          $include = preg_replace(array('#^'. $base_url .'#', '#^'. base_path() .'#', '#^/#'), '', $include);
          if (substr($include, 0, 4) == 'http') {
            // drupal_add_js() does not support external paths
            drupal_set_html_head('<script type="text/javascript" src="'. $include .'"></script>');
          }
          else {
            drupal_add_js($include);
          }
        }
      }
    }
  }
}

/**
 * Function gallery_get_block().
 *
 * This function allows developers to fetch an image or grid block with certain
 * parameters from Gallery2.
 *
 * @param $params
 *   An array of parameters to be passed to getImageBlock().
 *   (http://gallery.menalto.com/apidoc/GalleryCore/Classes/GalleryEmbed.html#methodgetImageBlock)
 *   If 'itemId' is set to 'user' (or 'user:uid') items are be taken from the
 *   current (or specified) user's useralbum.
 * @param $block
 *   Reserved (for future use)
 *   For compatibility with future versions of gallery module you should set this to 'ImageBlock'
 *   although the parameter is not used at the moment.
 * @param $extra
 *   $extra['class']:
 *     Optional class to apply to the block (if customized css styles are required).
 *   $extra['num_colums']:
 *     If given a grid block with 'num_cols' columns is generated.
 *     Otherwise (default) a 'normal' image block is returned.
 */
function gallery_get_block($params, $block = 'ImageBlock', $extra = array()) {
  if (!_gallery_init(TRUE)) {
    return array('content' => '');
  }
  // Include gallery_block.inc and call the private implementation
  require_once(drupal_get_path('module', 'gallery') .'/gallery_block.inc');
  return _gallery_block_get_block($params, $extra);
}

/**
 * Function _gallery_split_imageblock().
 * (split an image block result into individual images)
kiz_0987's avatar
kiz_0987 committed
 */
function _gallery_split_imageblock($html) {
  // From http://uk.php.net/manual/en/function.preg-split.php
  // Split the html from image block into <...> parts
kiz_0987's avatar
kiz_0987 committed
  $pattern = '/(<(?:[^<>]+(?:"[^"]*"|\'[^\']*\')?)+>)/';
  $html_array = preg_split($pattern, trim($html), -1, PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_NO_EMPTY);
kiz_0987's avatar
kiz_0987 committed
  
  $ndx = 0;
  $images = array();
  $image_html = '';
  // Iterate through this array and combine again, but on a per-image basis
kiz_0987's avatar
kiz_0987 committed
  foreach ($html_array as $value) {
    $value = trim($value);
    $image_html .= $value; 
    if (!strcmp($value, '<div class="one-image">')) {
      // Found the opening <div> for the image
      $open_divs = 0;
    }
    elseif (!strncmp($value, '<div', 4)) {
kiz_0987's avatar
kiz_0987 committed
      // Found a <div> but not the main image one (eg a frame)
      $open_divs++;
    }
    elseif (!strcmp($value, '</div>')) {
kiz_0987's avatar
kiz_0987 committed
      // Found a </div> but check if it's for the main image or a subcomponent (eg frame)
      if ($open_divs > 0) {
kiz_0987's avatar
kiz_0987 committed
        $open_divs--;
kiz_0987's avatar
kiz_0987 committed
        // This must be the closing div for "one-image" so move to next image
        $images[] = $image_html;
        $image_html = '';
      }
    }
  }
kiz_0987's avatar
kiz_0987 committed
  return $images;  
}

/**
 * Function _gallery_htmlcharsdecode().
 * (recover special character's HTML entities, see htmlspecialchars_decode() for php5)
 */
function _gallery_htmlcharsdecode($string) {
  return strtr($string, array_flip(get_html_translation_table(HTML_SPECIALCHARS)));
}
/* 
 * --------------------------------------------------------------------------
 * Error, Debug and Status Functions
 * --------------------------------------------------------------------------
 */

/**
 * Function gallery_error().
 */
function gallery_error($msg, $ret = NULL, $serious = FALSE) {
  $error_mode = variable_get('gallery_error_mode', array(GALLERY_ERROR_WATCHDOG));
  $admin = user_access('administer site configuration');
  $report = $admin && variable_get('gallery_report', 1);
  // Verbose error messages
  $debug_info = array();
  if (in_array(GALLERY_ERROR_VERBOSE, $error_mode) || variable_get('gallery_debug', 0) || $admin) {
    $msg = $ret ? (is_object($ret) ? ($msg .'<br />'. $ret->getAsHtml()) : $ret) : $msg;
    if (GALLERY_DEBUGTRACE && function_exists('debug_backtrace')) {
      $trace = debug_backtrace();
      $source = t('Error in function \':func()\' (:file::line):<br />',
        array(':func' => $trace[1]['function'], ':file' => basename($trace[0]['file']), ':line' => $trace[0]['line']));
      $message  = $source .'<ul><li>'. $msg .'</li></ul>';
      $debug_info = array('Debug Trace' => $trace);
    }
  }
  $message = !empty($message) ? $message : $msg;
  // Debug output (skip watchdog)
  if (variable_get('gallery_debug', 0) && $admin) {
    if ($report) {
      _gallery_report_error($debug_info);
    }
    drupal_set_message($message, 'error');
    return;
  }
  // Error output to browser
  if (in_array(GALLERY_ERROR_BROWSER, $error_mode)) {
    if ($report) {
      _gallery_report_error($debug_info);
    }
    drupal_set_message($message, 'error');
  }
  elseif ($serious) {
    if ($report) {
      _gallery_report_error($debug_info);
    }
    drupal_set_message($admin ? $message : t('Embedded Gallery2 is not available or requested Gallery URL does not exist.'), 'error');
  }
  // Error output to watchdog
  if (in_array(GALLERY_ERROR_WATCHDOG, $error_mode)) {
    watchdog('gallery', $message, WATCHDOG_ERROR);
  }
}

/**
 * Function _gallery_report_error().
 */
function _gallery_report_error($report = array()) {
  require_once(drupal_get_path('module', 'gallery') .'/gallery_help.inc');
  require_once(drupal_get_path('module', 'gallery') .'/gallery_report.inc');

  drupal_set_message(_gallery_report_help(), 'error');
  _gallery_report(FALSE, $report, TRUE);
}

/**
 * Function gallery_debug().
 */
function gallery_debug($array, $label = 'Gallery Debug') {
  if (variable_get('gallery_debug', 0) && user_access('administer site configuration')) {
    drupal_set_message('<strong>'. $label .':</strong><br />'. nl2br(htmlspecialchars(print_r($array, TRUE))), 'error');
  }
}

/**
 * Function gallery_plugin_status().
 */
function gallery_plugin_status($plugin_names) {
  static $all_plugins_status = array();

  $plugins_status = array();
  if (!_gallery_init()) {
    foreach ($plugin_names as $plugin) {
      $plugins_status[$plugin] = GALLERY_PLUGIN_STATUS_UNKNOWN;
    }
    
    return $plugins_status;
  }
  // Fetch status of G2 modules
  if (empty($plugins_status_cache)) {
    list($ret, $plugins_status_cache) = GalleryCoreApi::fetchPluginStatus('module');
    if ($ret) {
      gallery_error(t('Unable to get Gallery2 module status.'), $ret);
      foreach ($plugin_names as $plugin) {
        $plugins_status[$plugin] = GALLERY_PLUGIN_STATUS_UNKNOWN;
      }
      
      return $plugins_status;
    }
  }
  // Generate array containing module status
  foreach ($plugin_names as $plugin) {
    if (isset($plugins_status_cache[$plugin])) {
      if ($plugins_status_cache[$plugin]['active'] && $plugins_status_cache[$plugin]['available']) {
        $plugins_status[$plugin] = GALLERY_PLUGIN_ENABLED;
      }
      elseif (!isset($plugins_status_cache[$plugin]['active']) && $plugins_status_cache[$plugin]['available']) {
        $plugins_status[$plugin] = GALLERY_PLUGIN_NOT_INSTALLED;
      }
      elseif (($plugins_status_cache[$plugin]['active'] == 0) && $plugins_status_cache[$plugin]['available']) {
        $plugins_status[$plugin] = GALLERY_PLUGIN_NOT_ACTIVE;
      }
      else {
        $plugins_status[$plugin] = GALLERY_PLUGIN_DISABLED;
      }
    }
    else {
      $plugins_status[$plugin] = GALLERY_PLUGIN_MISSING;
    }
  
  return $plugins_status;
}

/**
 * Function gallery_single_plugin_status().
 */
function gallery_single_plugin_status($plugin_name) {
  $status = gallery_plugin_status(array($plugin_name));
  return $status[$plugin_name];
}
/**
 * Function gallery_set_status().
 */
function gallery_set_status($status = array(), $reset = FALSE) {
  $status_array = $status;
  if (!$reset) {
    $status_array = unserialize(variable_get('gallery_status', serialize(array())));
    foreach ($status as $key => $value) {
      if (!empty($value)) {
        $status_array[$key] = $value;
      }
      elseif (isset($status_array[$key])) {
        unset($status_array[$key]);
      }
    }
  
  variable_set('gallery_status', serialize($status_array));
}
/**
 * Function gallery_get_status().
 */
function gallery_get_status() {
  return unserialize(variable_get('gallery_status', serialize(array())));
}

/**
 * Function gallery_version().
 */
function gallery_version() {
  if (!_gallery_init()) {
    return array();
  // Get API version
  list($core_major, $core_minor) = GalleryCoreApi::getApiVersion();
  list($embed_major, $embed_minor) = GalleryEmbed::getApiVersion();
  $version = array(
    'core' => array('major' => $core_major, 'minor' => $core_minor),
    'embed' => array('major' => $embed_major, 'minor' => $embed_minor)
  );

  // Update version in status messages
  $status = array('version' => array(
    'title' => t('Gallery2 API version'),
    'info' => "$core_major.$core_minor / $embed_major.$embed_minor")
  );
  gallery_set_status($status);
      
  return $version;