You are here

include.module in Include 7

Same filename and directory in other branches
  1. 8 include.module
  2. 6 include.module

The Include module manages files on the include_files path.

File

include.module
View source
<?php

/**
 * @file
 * The Include module manages files on the include_files path.
 */

/**
 * Implements hook_init().
 *
 * Add the include files repository to the include_files path, if needed.
 * @see include_set_root(), include_clear_root()
 */
function include_init() {
  if (variable_get('include_set_root', FALSE)) {
    include_set_root();
  }
}

/**
 * Returns the absolute path of the include files repository.
 *
 * This defaults to conf_path() . '/files/include' but may be customized
 * by setting the 'include_root' variable and/or the default file scheme.
 */
function include_get_root() {
  return variable_get('include_root', drupal_realpath(file_build_uri('')) . '/include');
}

/**
 * Appends the include files repository to the include_path.
 *
 * This function should only be called when a file in the repository is
 * needed, and cannot be found in the regular include_path.  This sets the
 * 'include_set_root' variable to TRUE, which ensures that this function runs
 * again on every non-cached page request.
 * @see include_init()
 */
function include_set_root() {
  static $done = FALSE;
  if ($done || cache_get('include_error', 'cache_menu')) {
    return;
  }
  if (!variable_get('include_set_root', FALSE)) {
    watchdog('include', 'Adding directory: %path to include path.', array(
      '%path' => include_get_root(),
    ), WATCHDOG_NOTICE);

    // Setting the include_set_root variable ensures that the include_path gets
    // set in the include_init() function.
    variable_set('include_set_root', $done = TRUE);
  }
  set_include_path(implode(PATH_SEPARATOR, array_unique(array_merge(explode(PATH_SEPARATOR, get_include_path()), array(
    include_get_root(),
  )))));
}

/**
 * Clear the include files repository from the include_path.
 *
 * This function is called when an unrecoverable error occurs.  It sets the
 * include_error flag to true, which prevents any further changes to the
 * filesystem or include_path.
 */
function include_clear_root() {
  static $done = FALSE;
  if ($done || cache_get('include_error', 'cache_menu')) {
    return;
  }
  set_include_path(implode(PATH_SEPARATOR, array_diff(explode(PATH_SEPARATOR, get_include_path()), array(
    include_get_root(),
  ))));

  // Clearing the include_set_root variable prevents future attempts to set the
  // include_path in include_init().
  variable_del('include_set_root');

  // Don't try this again unless something changes.
  cache_set('include_error', TRUE, 'cache_menu');
}

/**
 * Verifies that a file exists on the include path.
 *
 * @param $filename
 *   The filename to verify, relative to the include path.
 *
 * @param $cache
 *   (optional) FALSE to ignore previously-cached results.  Defaults to TRUE.
 *
 * @return
 *   TRUE if the file exists; otherwise FALSE.
 */
function include_verify($filename, $cache = TRUE) {
  $files =& drupal_static(__FUNCTION__, array());
  if ($cache && isset($files[$filename])) {
    return $files[$filename];
  }
  if ($fd = @fopen($filename, 'r', TRUE)) {
    fclose($fd);
    return $files[$filename] = TRUE;
  }
  return $files[$filename] = FALSE;
}

/**
 * Verifies or installs a file or directory into the include repository.
 *
 * @param $path
 *   The target path to install, relative to the include file root.  If $path
 *   is empty or ends in a trailing slash, it is interpreted as a directory
 *   name, and both $source and $type are ignored.
 * @param $source
 *   (optional) The file data, or a uri where it may be found.  If unset or
 *   empty, then $path is a directory name, and $type is ignored.
 * @param $type
 *   (optional) A string which determines how $source is to be interpreted.
 *   Must be one of the following:
 *   - dir: $path is a directory name, and $source is ignored.
 *   - file: (Default) drupal_realpath($source) is a local file.
 *   - url: url($source) is a downloadable url.
 *   - string: $source is a string containing the file data.
 *
 * @return
 *   TRUE if the file was successfully installed; otherwise FALSE.
 */
function include_check_path($path, $source = NULL, $type = 'file') {
  if (empty($source) || substr($path, -1) === '/') {
    $type = 'dir';
  }
  $path = trim($path, '/');
  if (empty($path)) {
    $type = 'dir';
  }
  elseif ($path == '.') {
    $type = 'dir';
    $path = '';
  }
  elseif ($path == '..') {
    return TRUE;
  }
  elseif ($type != 'dir' && include_verify($path)) {
    return TRUE;
  }
  elseif (cache_get('include_error', 'cache_menu')) {

    // Something went wrong with previous installs; abort.
    return FALSE;
  }
  elseif ($type != 'dir' && !include_check_path(dirname($path))) {
    return FALSE;
  }
  $target = include_get_root() . '/' . $path;
  $args = array(
    '%function' => __FUNCTION__,
    '%source' => $source,
    '%path' => $path,
    '%target' => $target,
  );
  switch ($type) {
    case 'dir':
      if (!file_prepare_directory($target, FILE_CREATE_DIRECTORY | FILE_MODIFY_PERMISSIONS)) {
        drupal_set_message(t('Could not create directory: %target. Check permissions.', $args), 'error');
        watchdog('include', 'Could not create directory: %target.', $args, WATCHDOG_ERROR);
        return FALSE;
      }
      break;
    case 'file':
      if (!($source_path = drupal_realpath($source))) {
        drupal_set_message(t('File not found: %source', $args), 'error');
        watchdog('include', 'File not found: %source', $args, WATCHDOG_ERROR);
        return FALSE;
      }
      elseif (!copy($source_path, $target)) {
        drupal_set_message(t('Could not copy file from (%source) to (%target). Check permissions.', $args), 'error');
        watchdog('include', 'Could not copy file from (%source) to (%target)', $args, WATCHDOG_ERROR);
        return FALSE;
      }
      break;
    case 'url':
      if (!($args['%source'] = url($source))) {
        drupal_set_message(t('Could not resolve (%source) to a download url.', $args), 'error');
        watchdog('include', 'Could not resolve (%source) to a download url.', $args, WATCHDOG_ERROR);
        return FALSE;
      }
      elseif (!($response = drupal_http_request($args['%source']))) {
        drupal_set_message(t('Could not open url (%source).', $args), 'error');
        watchdog('include', 'Could not open url (%source).', $args, WATCHDOG_ERROR);
        return FALSE;
      }
      elseif (!empty($response->error)) {
        $args['@error'] = $response->error;
        drupal_set_message(t('Error downloading (%source): @error', $args), 'error');
        watchdog('include', 'Error downloading (%source): @error', $args, WATCHDOG_ERROR);
        return FALSE;
      }
      $source = $response->data;

    // Fall-through and share code with case 'string'.
    case 'string':
      if (!($args['%count'] = strlen($source))) {
        drupal_set_message(t('Source file at (%source) is empty.', $args), 'error');
        watchdog('include', 'Source file at (%source) is empty.', $args, WATCHDOG_ERROR);
        return FALSE;
      }
      elseif ($args['%count'] != file_put_contents($target, $source)) {
        drupal_set_message(t('Could not write (%count) bytes to file: (%target).  Disk full?', $args), 'error');
        watchdog('include', 'Could not write (%count) bytes to file: (%target).', $args, WATCHDOG_ERROR);
        return FALSE;
      }
      break;
    default:

      // Modules may implement hook_include_install_HOOK().
      $modules = module_implements("include_install_{$type}");
      if (empty($modules)) {
        drupal_set_message(t('No installer found for include type (%type).  Check your dependencies.', $args), 'error');
        watchdog('include', 'No installer found for include type (%type).', $args, WATCHDOG_CRITICAL);
        return FALSE;
      }
      foreach ($modules as $module) {
        $function = $module . '_include_install_' . $type;
        if (!$function($path, $source)) {

          // The hook function is responsible for its own error reporting.
          return FALSE;
        }
      }

      // Each hook function is responsible for calling
      // include_set_root() and include_verify() if necessary.
      return TRUE;
  }
  if (empty($error) && $type != 'dir') {

    // A file was installed; add the include file repository to the PHP
    // include_path and verify that the newly-installed file can be found.
    watchdog('include', 'Added file: %path to include path.', array(
      '%path' => $path,
    ));
    include_set_root();
    if (!include_verify($path, FALSE)) {
      include_clear_root();
      $args['%dir'] = include_get_root();
      $args['!include_path'] = url('http://php.net/manual/ini.core.php#ini.include-path');
      $args['!set_include_path'] = url('http://php.net/set_include_path');
      $args['!include'] = url('admin/modules', array(
        'fragment' => 'edit-modules-other-include-enable',
      ));
      drupal_set_message(t('The file at %path (realpath %target) could not be found, even after adding %dir to the PHP <a href="!include_path">include_path</a>. Your hosting provider may have disabled the <a href="!set_include_path">set_include_path</a> function. An error flag has been set, and no further attempts will be made, until the <a href="!include">Include</a> module is disabled and then re-enabled.', $args), 'error');
      watchdog('include', 'Error including a downloaded file.  Auto-downloading has been disabled.', WATCHDOG_CRITICAL);
      return FALSE;
    }
    else {
      drupal_set_message(t('Created include %path.', $args));
    }
  }
  if (empty($error)) {
    return TRUE;
  }
  watchdog('include', "Error in %function function: {$error}", $args, $error_level);
  return FALSE;
}

Functions

Namesort descending Description
include_check_path Verifies or installs a file or directory into the include repository.
include_clear_root Clear the include files repository from the include_path.
include_get_root Returns the absolute path of the include files repository.
include_init Implements hook_init().
include_set_root Appends the include files repository to the include_path.
include_verify Verifies that a file exists on the include path.