1 installer.manager.inc installer_manager_download_project($url, $is_installer = FALSE)

Downloads a project given a project url.

Either downloads the file specified in the URL to a temporary cache, or uploads the file attached to the form, then attempts to extract the archive into a temporary location and verify it. Instantiate the appropriate Updater class for this project and make sure it is not already installed in the live webroot. If everything is successful, setup an operation to run via authorize.php which will copy the extracted files from the temporary location into the live site.

Parameters

string $is_installer: Whether the project is being installed via the Project Installer UI.

Return value

array: An associative array with keys:

  • 'success': whether the update was successful
  • 'message': an error or success message.

See also

installer_manager_install_form_validate()

installer_authorize_run_install()

system_authorized_init()

system_authorized_get_url()

Related topics

File

core/modules/installer/installer.manager.inc, line 799
Administrative screens and processing functions of the Installer module.

Code

function installer_manager_download_project($url, $is_installer = FALSE) {
  if ($url) {
    $local_cache = installer_manager_file_get($url);
    if (!$local_cache) {
      return array(
        'success' => FALSE,
        'message' => t('Unable to retrieve Backdrop project from %url.', array('%url' => $url)),
      );
    }
  }
  elseif ($_FILES['files']['name']['project_upload']) {
    $validators = array('file_validate_extensions' => array(archiver_get_extensions()));
    $field = 'project_upload';
    if (!($file_info = file_save_upload($field, $validators, NULL, FILE_EXISTS_REPLACE))) {
      // Failed to upload the file. file_save_upload() calls form_set_error() on
      // failure.
      return array(
        'success' => FALSE,
        'message' => t('Unable to save downloaded project into the temporary directory.'),
      );
    }
    $local_cache = $file_info->uri;
  }
  else {
    $local_cache = NULL;
  }

  // Try to extract it.
  $directory = _installer_manager_extract_directory();
  try {
    $archive = installer_manager_archive_extract($local_cache, $directory);
  }
  catch (Exception $e) {
    return array(
      'success' => FALSE,
      'message' => $e->getMessage(),
    );
  }
  $files = $archive->listContents();
  if (!$files) {
    return array(
      'success' => FALSE,
      'message' => t('Provided archive contains no files.'),
    );
  }


  // Unfortunately, we can only use the directory name to determine the project
  // name. Some archivers list the first file as the directory (i.e., MODULE/)
  // and others list an actual file (i.e., MODULE/README.MD).
  $project = strtok($files[0], '/\\');

  $archive_errors = installer_manager_archive_verify($project, $local_cache, $directory);
  if (!empty($archive_errors)) {
    return array(
      'success' => FALSE,
      'message' => array_shift($archive_errors),
    );
  }

  // Make sure the Updater registry is loaded.
  backdrop_get_updaters();

  $project_location = $directory . '/' . $project;
  try {
    $updater = Updater::factory($project_location);
  }
  catch (Exception $e) {
    return array(
      'success' => FALSE,
      'message' => $e->getMessage(),
    );
  }

  try {
    $project_title = Updater::getProjectTitle($project_location);
  }
  catch (Exception $e) {
    return array(
      'success' => FALSE,
      'message' => $e->getMessage(),
    );
  }

  if (!$project_title) {
    return array(
      'success' => FALSE,
      'message' => t('Unable to determine %project name.', array('%project' => $project)),
    );
  }

  if ($updater->isInstalled()) {
    return array(
      'success' => FALSE,
      'message' => t('%project is already installed.', array('%project' => $project_title)),
    );
  }

  $project_realpath = backdrop_realpath($project_location);
  $updater_name = get_class($updater);

  // If the permissions of the downloaded file match those of the settings.php
  // directory, go ahead and install the module directly.
  if (fileowner($project_realpath) == fileowner(conf_path()) || filegroup($project_realpath) == filegroup(conf_path())) {
    module_load_include('inc', 'installer', 'installer.authorize');
    $filetransfer = new FileTransferLocal(BACKDROP_ROOT);

    if ($is_installer) {
      // Initialize some variables in the Batch API $context array.
      /* @var Updater $updater */
      $updater = new $updater_name($project_realpath);

      try {
        if ($updater->isInstalled()) {
          // This is an update.
          $updater->update($filetransfer);
        }
        else {
          $updater->install($filetransfer);
        }
      }
      catch (UpdaterException $e) {
        return array(
          'success' => FALSE,
          'message' => t('Error installing / updating. Error: @error', array('@error' => $e->getMessage())),
        );
      }
    }
    else {
      // Start the batch process to install the module but suppress redirecting
      // to authorize.php, return the redirect instead.
      $redirect_callback = backdrop_is_ajax() ? FALSE : 'backdrop_goto';
      installer_authorize_run_install($filetransfer, $project, $updater_name, $project_realpath, $redirect_callback);

      // Assemble the authorize.php path and go to it to complete the batch.
      $batch = &batch_get();
      return array(
        'success' => TRUE,
        'redirect' => array($batch['url'], array('query' => array('op' => 'start', 'id' => $batch['id']))),
      );
    }
  }
  // If permissions differ, redirect to authorize.php to copy the file as a
  // different system user.
  else {
    if ($is_installer) {
      return array(
        'success' => FALSE,
        'message' => t('Permissions are not set up properly.'),
      );
    }
    else {
      $path = backdrop_get_path('module', 'installer') . '/installer.authorize.inc';
      system_authorized_init('installer_authorize_run_install', $path, array($project, $updater_name, $project_realpath), t('Update manager'));
      return array(
        'success' => TRUE,
        'redirect' => system_authorized_get_url(),
      );
    }
  }

  return array(
    'success' => TRUE,
  );
}