- <?php
- * @file
- * Various functions that are required by the Installer browse pages.
- */
-
- * Checks if a project is enabled.
- *
- * @param string $type
- * The type of project. Could be 'theme', 'module', 'layout' or 'driver'.
- * @param string $name
- * The short name of the project.
- *
- * @return
- * TRUE if the project is enabled, FALSE otherwise.
- */
- function _installer_browser_is_project_enabled($type, $name) {
- switch ($type) {
- case 'module':
- return module_exists($name);
- break;
- case 'theme':
- $themes = list_themes();
- return isset($themes[$name]) && $themes[$name]->status;
- break;
- case 'layout':
- $excluded_templates = config_get('layout.settings', 'excluded_templates');
- return layout_get_layout_template_info($name) && !in_array($name, $excluded_templates);
- break;
- case 'driver':
- $drivers = silkscreen_driver_list();
- return in_array($name, array_keys($drivers));
- break;
- }
- return FALSE;
- }
-
- * Gets the currently listed projects from the session.
- */
- function installer_browser_get_listed_projects() {
- if (isset($_SESSION['installer_browser_listed_projects'])) {
- return $_SESSION['installer_browser_listed_projects'];
- }
-
- return array();
- }
-
- * Gets the currently queued projects from the session.
- */
- function installer_browser_get_queued_projects($type = NULL) {
- $projects = array();
-
- if (isset($_SESSION['installer_browser_install_list'])) {
- foreach ($_SESSION['installer_browser_install_list'] as $project) {
- if (is_array($project) && !empty($project)) {
- if (isset($type) && $type != $project['type']) {
- continue;
- }
- else {
- $projects[$project['name']] = $project;
- }
- }
- }
- }
-
- return $projects;
- }
-
- * Gets a release from a project and a release_name.
- */
- function installer_browser_get_release($release_name, $project) {
- $release_data = installer_browser_get_project_release_data($project);
-
- return isset($release_data['releases'][$release_name]) ? $release_data['releases'][$release_name] : FALSE;
- }
-
- * Gets the newly installed projects from the session.
- */
- function installer_browser_get_installed_projects() {
- $projects = array();
-
- if (isset($_SESSION['installer_browser_installed_projects'])) {
- foreach ($_SESSION['installer_browser_installed_projects'] as $project) {
- if (is_array($project) && !empty($project)) {
- $projects[$project['name']] = $project;
- }
- }
- }
-
- return $projects;
- }
-
- * Adds a project to the install queue.
- */
- function installer_browser_install_queue_add($project) {
- $_SESSION['installer_browser_install_list'][$project['name']] = $project;
- }
-
- * Removes a project from the install queue.
- */
- function installer_browser_install_queue_remove($project_name) {
- if (isset($_SESSION['installer_browser_install_list'][$project_name])) {
- unset($_SESSION['installer_browser_install_list'][$project_name]);
- }
- }
-
- * Removes a project from the list of recently installed projects.
- *
- * @param string[] $project_names
- * A list of projects to remove from the installed project list.
- *
- * @since 1.10.1
- */
- function installer_browser_installed_projects_remove($project_names) {
- foreach ($project_names as $project_name) {
- if (isset($_SESSION['installer_browser_installed_projects'][$project_name])) {
- unset($_SESSION['installer_browser_installed_projects'][$project_name]);
- }
- }
- }
-
- * Clears the install queue.
- *
- * Removes all projects from the $_SESSION variables.
- *
- * @param bool $include_installed
- * If TRUE, also clear the list of recently installed projects.
- */
- function installer_browser_install_queue_clear($include_installed = FALSE) {
- $_SESSION['installer_browser_install_list'] = array();
- if ($include_installed) {
- $_SESSION['installer_browser_installed_projects'] = array();
- }
- }
-
- * Gets the currently queued releases from the session.
- */
- function installer_browser_get_queued_releases() {
- $releases = array();
-
- if (isset($_SESSION['installer_browser_install_releases_list'])) {
- foreach ($_SESSION['installer_browser_install_releases_list'] as $release_name => $project) {
- if (is_array($project) && !empty($project)) {
- $releases[$release_name] = $project;
- }
- }
- }
-
- return $releases;
- }
-
- * Fetches results from the server based on the parameters passed in.
- *
- * $filters should be an associative array with the following keys:
- * - version: The Major Version of Backdrop that is running on the Client.
- * - text: The text that was entered as the search query, or '' if none.
- * - type: The type of project being searched.
- * - page: The zero-based page number.
- * - items_per_page: How many results are requested per page.
- *
- * For example:
- * @code
- * array(
- * 'version' => '1',
- * 'text' => 'views',
- * 'type' => 'module',
- * 'page' => 3,
- * 'items_per_page' => 12,
- * )
- * @endcode
- *
- * The installer_browser_fetch_results($filters) call returns an array with the
- * following keys:
- * - total: The total number of results found for the filters.
- * - projects: An array of projects returned for this page request keyed by
- * machine name. Each project array may contain the following key-value
- * pairs:
- * - type: The type of project this is. Can be 'module' or 'theme'.
- * - title: The title of the project.
- * - name: The machine name of the project.
- * - author: The author's name.
- * - description: The project description.
- * - image: Absolute url to the image, if any.
- * - usage: Number of reported active installs.
- * - project url: Absolute url to the project page, if any.
- * - project status url: The absolute url of the update checker.
- * - last updated: UNIX Timestamp of when the project was last updated.
- * - maintenance status: The project maintenance status.
- * - development status: The project development status.
- * - rating: A rating on a scale of 1 to 10 of the project, if available.
- * - dependencies: An array of the dependencies of this module.
- *
- * The following is an example of a valid return array:
- * @code
- * array(
- * 'total' = 5,
- * 'projects' => array(
- * 'views' => array(
- * 'type' => 'module',
- * 'title' => 'Views',
- * 'name' => 'views',
- * 'author' => 'merlinofchaos',
- * 'description' => 'Long project description',
- * 'image' => 'http://www.example.com/image.jpg',
- * 'usage' => '542312',
- * 'project url' => 'https://www.example.org/projects/views',
- * 'project status url' => 'https://updates.example.org/release-history/views/1.x',
- * 'last updated' => '12342523',
- * 'maintenance status' => 'Actively maintained',
- * 'development status' => 'Under active development',
- * 'rating' => '9.6',
- * 'dependencies' => array(
- * 'entity',
- * ),
- * ),
- * 'another_project => array(
- * 'type' => 'module',
- * ...
- * ),
- * ),
- * );
- * @endcode
- *
- * @param array $filters
- * An associative array of queries to use to filter results.
- *
- * @return
- * Returns an array of results.
- */
- function installer_browser_fetch_results($filters) {
- $servers = installer_browser_get_server_list();
-
- $cid = 'installer:results:' . md5(serialize(array_merge($filters, $servers)));
- if ($cache = cache_get($cid)) {
- return $cache->data;
- }
-
- $local_filters = $filters;
- $local_filters['method'] = 'query';
-
- $results = array('projects' => array());
- foreach ($servers as $repo_name => $server) {
- $count_results = _installer_browser_execute_query($server, $local_filters, 0);
- if ($count_results === NULL) {
- continue;
- }
- $package_results = _installer_browser_execute_query($server, $local_filters, $count_results['total']);
- if ($package_results === NULL) {
- continue;
- }
-
- foreach (array_keys($package_results['projects']) as $package) {
- $package_results['projects'][$package]['source'] = $repo_name;
- }
- $results['projects'] += $package_results['projects'];
- }
- $results['total'] = count($results['projects']);
-
-
- cache_set($cid, $results, 'cache', strtotime("+24 hours"));
-
- return $results;
- }
-
- * Helper function to execute queries for projects. Connects once to get
- * the total count of projects, and then a second time to get all the
- * projects in a repository.
- *
- * @param array $server
- * An array describing the server.
- * @param array $filters
- * An array of filters for the query.
- * @param int $ipp
- * The number of items to retrieve.
- * @return
- * An array of projects on the server or NULL on error.
- */
- function _installer_browser_execute_query($server, $filters, $ipp) {
- $filters = array_merge($filters, array('items_per_page' => $ipp));
- $query_url = $server['url'] . '/query/' . $filters['type'] . '/1?' . http_build_query($filters, FALSE, '&');
- $response = backdrop_http_request($query_url);
-
- if ($response->code == '200') {
- return backdrop_json_decode($response->data);
- }
- else {
- watchdog('installer', t("Encountered an error when trying to fetch results from @name. Error @code : @message",
- array('@name' => $server['name'], '@code' => $response->code, '@message' => $response->error)), WATCHDOG_WARNING);
- return NULL;
- }
- }
-
- * Gets the server to use for fetching results.
- *
- * The installer_browser_fetch_results($filters) call returns an array with the
- * following keys:
- * @return
- * Returns an array representing the active server with the following keys:
- * - url: The absolute url to the server without query parameters.
- * - name: A human-readable name for this server.
- * - site_name: The domain name for the "See on @site" link.
- * - logo: An image logo for the repository.
- * For example:
- * @code
- * array(
- * "url" => "https://projects.backdropcms.org",
- * "name" => "Backdrop",
- * "site_name" => "BackdropCMS.org",
- * "logo" => "core/modules/installer/images/backdrop.png",
- * )
- * @endcode
- *
- * @deprecated since 1.15
- */
- function installer_browser_get_server() {
- watchdog_deprecated_function('installer', __FUNCTION__);
-
- $server_list = installer_browser_get_server_list();
- $server = reset($server_list);
- backdrop_alter('installer_server', $server);
-
- return $server;
- }
-
- * Gets the list of servers to use for fetching results.
- *
- * The installer_browser_fetch_results($filters) call returns an array with the
- * following keys:
- * @return
- * Returns an array representing the active server with the following keys:
- * - url: The absolute url to the server without query parameters.
- * - name: A human-readable name for this server.
- * - site_name: The domain name for the "See on @site" link.
- * - logo: An image logo for the repository.
- * For example:
- * @code
- * array(
- * "url" => "https://projects.backdropcms.org",
- * "name" => "Backdrop",
- * "site_name" => "BackdropCMS.org",
- * "logo" => "core/modules/installer/images/backdrop.png",
- * )
- * @endcode
- */
- function installer_browser_get_server_list() {
- $server_list = config_get('installer.settings', 'installer_server');
- backdrop_alter('installer_server_list', $server_list);
-
-
- if (array_key_exists('url', $server_list)) {
- $server_list = array($server_list);
- }
-
- return $server_list;
- }
-
- * Uses the project status url to get the available releases for a project.
- *
- * @param array $project
- * Associative array of information about the project to fetch release data
- * for, as returned by the remote server.
- *
- * @return array|FALSE
- * An array of releases for this project or FALSE if the project is not found.
- */
- function installer_browser_get_project_release_data(array $project) {
- $project['project_type'] = $project['type'];
-
- module_load_include('inc', 'update', 'update.fetch');
- if (_update_process_fetch_task($project)) {
- $data = _update_cache_get('available_releases::' . $project['name']);
- if (isset($data->data) && isset($data->data['releases']) && is_array($data->data['releases'])) {
- return $data->data;
- }
- }
-
- return FALSE;
- }
-
- * Batch API callback: Installs a single release of a project during batch.
- *
- * @param $release_name
- * The short name of the selected release of the project being installed.
- * @param $project
- * Associative array of information about the project to be installed.
- */
- function _installer_browser_batch_install_release($release_name, $project, &$context) {
- $release = installer_browser_get_release($release_name, $project);
-
- module_load_include('inc', 'installer', 'installer.manager');
- $url = file_create_url($release['download_link']);
- $result = installer_manager_download_project($url, TRUE);
-
- if ($result['success']) {
- $context['results']['successes'][] = t('Successfully installed %project.', array('%project' => $project['title']));
- $context['message'] = t('Installed %project...', array('%project' => $project['title']));
-
-
-
- $_SESSION['installer_browser_installed_projects'][$project['name']] = $project;
- unset($_SESSION['installer_browser_install_list'][$project['name']]);
- }
- else {
- watchdog('installer', 'There was an error while installing %project.
- !message',
- array('%project' => $project['title'], '!message' => $result['message']), WATCHDOG_ERROR);
- $context['results']['failures'][] = t('Error installing %project. !message',
- array('%project' => $project['title'], '!message' => $result['message']));
- $context['message'] = t('Error installing %project. Errors have been logged.',
- array('%project' => $project['title']));
- }
- }
-
- * Batch API callback: shows a message and finishes up the batch.
- */
- function _installer_browser_batch_install_releases_finished($success, $results, $operations) {
-
-
-
- backdrop_get_messages();
-
-
- if (isset($_SESSION['maintenance_mode'])) {
- state_set('maintenance_mode', $_SESSION['maintenance_mode']);
- unset($_SESSION['maintenance_mode']);
- }
-
- unset($_SESSION['installer_browser_install_releases_list']);
- if ($success) {
- if (!empty($results)) {
- if (!empty($results['failures'])) {
- backdrop_set_message(format_plural(count($results['failures']), 'Failed to install one project.', 'Failed to install @count projects.'), 'error');
- foreach($results['failures'] as $message){
- backdrop_set_message($message, 'error');
- }
- }
- }
- }
- else {
- backdrop_set_message(t('Error installing projects.'), 'error');
- backdrop_goto('admin/installer/install/select_versions');
- }
-
- $projects = installer_browser_get_installed_projects();
- $missing = installer_browser_get_missing_dependencies($projects);
-
- if (count($missing) > 0) {
- backdrop_goto('admin/installer/install/install_dependencies');
- }
- else {
- installer_browser_get_destination_after_install();
- }
- }
-
- * Determines the types of installed projects.
- */
- function installer_browser_get_installed_types() {
- $types = array();
- $projects = installer_browser_get_installed_projects();
- foreach ($projects as $project) {
- $types[$project['type']] = $project['type'];
- }
-
- return $types;
- }
-
-
-
- * Determines the form destination after installed projects.
- */
- function installer_browser_get_destination_after_install() {
- $types = installer_browser_get_installed_types();
-
- $layout = in_array('layout', $types);
- $theme = in_array('theme', $types);
- $module = in_array('module', $types);
- $driver = in_array('driver', $types);
-
- $layout_message = t('Installation finished successfully. All newly-added layout templates have been enabled and are available for use in your layouts. You can manage layout templates on the layouts !link page.', array('!link' => l(t('Templates'), 'admin/structure/layouts/settings')));
-
- if ($layout) {
-
-
- if ($theme || $module) {
- if (!$theme) {
- backdrop_set_message($layout_message);
- backdrop_goto('admin/installer/install/enable');
- }
- else {
- backdrop_set_message($layout_message);
- backdrop_goto('admin/installer/install/theme');
- }
- }
-
- else {
- backdrop_set_message($layout_message);
- backdrop_goto('admin/structure/layouts');
- }
- }
-
- elseif ($theme && $module) {
- backdrop_goto('admin/installer/install/theme');
- }
-
- elseif ($theme && !$module) {
- backdrop_set_message(t('One or more themes were installed. You may enable them now.'));
- backdrop_goto('admin/appearance');
- }
-
- else {
- backdrop_goto('admin/installer/install/enable');
- }
- }
-
- * Gets the dependencies for installed projects.
- */
- function installer_browser_get_missing_dependencies($projects) {
- $modules = system_rebuild_module_data();
-
- $missing = array();
-
- foreach ($projects as $project) {
- if ($project['type'] == 'module') {
- $dependencies = array();
- if (isset($modules[$project['name']])) {
- foreach ($modules[$project['name']]->requires as $requires) {
- $dependency = $requires['name'];
- if (!isset($modules[$dependency])) {
- $dependencies[] = $dependency;
- }
- }
- if (count($dependencies) > 0) {
- $missing[$project['name']] = $dependencies;
- }
- }
- else {
- backdrop_set_message(t('There was an error getting information for @module',
- array('@module' => $project['name'])), 'error');
- }
- }
- }
-
- return $missing;
- }
-
- * Builds the add/remove project to install queue link.
- */
- function installer_browser_add_remove_queue_link($project_name, $title = NULL, $id_prefix = 'add-to-queue-link') {
- $queued_projects = installer_browser_get_queued_projects();
- if (!$title) {
- $title = isset($queued_projects[$project_name]) ? t('Remove from Installation queue') : t('Add to Installation queue');
- }
- $op = isset($queued_projects[$project_name]) ? 'remove' : 'add';
-
- if (backdrop_is_dialog()) {
- $form = backdrop_get_form('installer_browser_add_remove_queue_dialog_link', $project_name, $op, $title);
- return backdrop_render($form);
- }
- else {
- $build['ajax_link'] = array(
- '#type' => 'link',
- '#title' => $title,
- '#href' => 'admin/installer/queue/nojs/' . $op . '/'. $project_name,
- '#options' => array(
- 'query' => backdrop_get_destination(),
- ),
- '#id' => $id_prefix . '-' . $project_name,
- '#ajax' => array(
- 'effect' => 'fade',
- 'speed' => 1000,
- 'progress' => array(
- 'type' => 'throbber',
- ),
- ),
- );
-
- }
-
- return backdrop_render($build);
- }
-
- * Builds an "add-to-queue-link" button for project detail dialog.
- */
- function installer_browser_add_remove_queue_dialog_link($form, &$form_state, $project_name, $op, $title) {
- form_load_include($form_state, 'inc', 'installer', 'installer.browser');
- $form['#attached']['js'][] = backdrop_get_path('module', 'layout') . '/js/layout.admin.js';
- $form['#attached']['css'][] = backdrop_get_path('module', 'layout') . '/css/layout.admin.css';
-
- if (empty($form_state['project_name'])) {
- $form_state['project_name'] = $project_name;
- $form_state['op'] = $op;
- $form_state['title'] = $title;
- }
-
- $form['ajax_link'] = array(
- '#type' => 'submit',
- '#value' => $form_state['title'],
- '#attributes' => array('class' => array('layout-link-button')),
- '#ajax' => array(
- 'callback' => 'installer_browser_add_remove_queue_dialog_link_ajax',
- ),
- '#submit' => array(
- 'installer_browser_add_remove_queue_dialog_link_submit',
- ),
- );
-
- return $form;
- }
-
- * AJAX submit handler for installer_browser_add_remove_queue_dialog_link().
- */
- function installer_browser_add_remove_queue_dialog_link_ajax($form, &$form_state) {
- $commands = array();
-
- $commands[] = ajax_command_replace('.installer-browser-install-queue', installer_browser_get_install_list());
-
- $commands[] = ajax_command_replace('#add-to-queue-link-' . $form_state['project_name'], installer_browser_add_remove_queue_link($form_state['project_name']));
-
- $form_html = backdrop_render($form);
- $commands[] = ajax_command_replace('.installer-browser-add-remove-queue-dialog-link', $form_html);
- return array('#type' => 'ajax', '#commands' => $commands);
- }
-
- * Submit handler for installer_browser_add_remove_queue_dialog_link().
- */
- function installer_browser_add_remove_queue_dialog_link_submit($form, &$form_state) {
-
- $form_state['redirect'] = installer_browser_install_queue_callback('form', $form_state['op'], $form_state['project_name']);
-
-
- if ($form_state['op'] == 'add') {
- $form_state['op'] = 'remove';
- $form_state['title'] = t('Remove from Installation queue');
- }
- else {
- $form_state['op'] = 'add';
- $form_state['title'] = t('Add to Installation queue');
- }
- $form_state['rebuild'] = TRUE;
- }
-
- *
- * Checks if PHP zip extension loaded on webserver.
- */
- function installer_browser_check_zip_loaded() {
- $zip_loaded = array_key_exists('zip', archiver_get_info());
- if (!$zip_loaded) {
- backdrop_set_message(t('Sorry, it seems that the PHP .zip extension is not loaded on your server. You will not be able to download any projects using Project Installer until this is fixed. Please contact your website administrator.'), 'warning', FALSE);
- }
- return $zip_loaded;
- }