Skip to content
system.module 50.9 KiB
Newer Older
Dries Buytaert's avatar
Dries Buytaert committed
<?php

Dries Buytaert's avatar
 
Dries Buytaert committed
/**
 * @file
 * Configuration system that lets administrators modify the workings of the site.
 */

use Drupal\Component\Utility\UrlHelper;
use Drupal\Core\Extension\Extension;
use Drupal\Core\Extension\ExtensionDiscovery;
use Drupal\Core\StringTranslation\TranslationWrapper;
use Drupal\Core\Language\LanguageInterface;
use Drupal\Core\Menu\MenuTreeParameters;
use Drupal\Core\Block\BlockPluginInterface;
use Drupal\user\UserInterface;
use Symfony\Component\HttpFoundation\RedirectResponse;
use GuzzleHttp\Exception\RequestException;
/**
 * New users will be set to the default time zone at registration.
 */
const DRUPAL_USER_TIMEZONE_DEFAULT = 0;

/**
 * New users will get an empty time zone at registration.
 */
const DRUPAL_USER_TIMEZONE_EMPTY = 1;

/**
 * New users will select their own timezone at registration.
 */
const DRUPAL_USER_TIMEZONE_SELECT = 2;
 * Disabled option on forms and settings
 */
const REGIONS_VISIBLE = 'visible';
Dries Buytaert's avatar
 
Dries Buytaert committed
/**
Dries Buytaert's avatar
 
Dries Buytaert committed
 */
function system_help($route_name, RouteMatchInterface $route_match) {
  switch ($route_name) {
    case 'help.page.system':
      $output = '';
      $output .= '<h3>' . t('About') . '</h3>';
      $output .= '<p>' . t('The System module is integral to the site, and provides basic but extensible functionality for use by other modules and themes. Some integral elements of Drupal are contained in and managed by the System module, including caching, enabling and disabling modules and themes, preparing and displaying the administrative page, and configuring fundamental site settings. A number of key system maintenance operations are also part of the System module. For more information, see the online handbook entry for <a href="@system">System module</a>.', array('@system' => 'http://drupal.org/documentation/modules/system')) . '</p>';
      $output .= '<h3>' . t('Uses') . '</h3>';
      $output .= '<dl>';
      $output .= '<dt>' . t('Managing modules') . '</dt>';
      $output .= '<dd>' . t('The System module allows users with the appropriate permissions to enable and disable modules on the <a href="@modules">Modules administration page</a>. Drupal comes with a number of core modules, and each module provides a discrete set of features and may be enabled or disabled depending on the needs of the site. Many additional modules contributed by members of the Drupal community are available for download at the <a href="@drupal-modules">Drupal.org module page</a>.', array('@modules' => \Drupal::url('system.modules_list'), '@drupal-modules' => 'http://drupal.org/project/modules')) . '</dd>';
      $output .= '<dt>' . t('Managing themes') . '</dt>';
      $output .= '<dd>' . t('The System module allows users with the appropriate permissions to install and uninstall themes on the <a href="@themes">Appearance administration page</a>. Themes determine the design and presentation of your site. Drupal comes packaged with several core themes, and additional contributed themes are available at the <a href="@drupal-themes">Drupal.org theme page</a>.', array('@themes' => \Drupal::url('system.themes_page'), '@drupal-themes' => 'http://drupal.org/project/themes')) . '</dd>';
      $output .= '<dt>' . t('Managing caching') . '</dt>';
      $output .= '<dd>' . t("The System module allows users with the appropriate permissions to manage caching on the <a href='@cache-settings'>Performance settings page</a>. Drupal has a robust caching system that allows the efficient re-use of previously-constructed web pages and web page components. Pages requested by anonymous users are stored in a compressed format; depending on your site configuration and the amount of your web traffic tied to anonymous visitors, the caching system may significantly increase the speed of your site.", array('@cache-settings' => \Drupal::url('system.performance_settings'))) . '</dd>';
      $output .= '<dt>' . t('Performing system maintenance') . '</dt>';
      $output .= '<dd>' . t('In order for the site and its modules to continue to operate well, a set of routine administrative operations must run on a regular basis. The System module manages this task by making use of a system cron job. You can verify the status of cron tasks by visiting the <a href="@status">Status report page</a>. For more information, see the online handbook entry for <a href="@handbook">configuring cron jobs</a>. You can set up cron job by visiting <a href="@cron">Cron configuration</a> page', array('@status' => \Drupal::url('system.status'), '@handbook' => 'http://drupal.org/cron', '@cron' => \Drupal::url('system.cron_settings'))) . '</dd>';
      $output .= '<dt>' . t('Configuring basic site settings') . '</dt>';
      $output .= '<dd>' . t('The System module also handles basic configuration options for your site, including <a href="@date-time-settings">Date and time settings</a>, <a href="@file-system">File system settings</a>, <a href="@site-info">Site name and other information</a>, and a <a href="@maintenance-mode">Maintenance mode</a> for taking your site temporarily offline.', array('@date-time-settings' => \Drupal::url('system.date_format_list'), '@file-system' => \Drupal::url('system.file_system_settings'), '@site-info' => \Drupal::url('system.site_information_settings'), '@maintenance-mode' => \Drupal::url('system.site_maintenance_mode'))) . '</dd>';
      $output .= '<dt>' . t('Providing administrative help') . '</dt>';
      $output .= '<dd>' . t('Page-specific administrative help text that is provided by the System module and other modules is displayed in the System Help block. This block can be placed and configured on the <a href="!blocks">Block layout page</a>.', array('!blocks' => (\Drupal::moduleHandler()->moduleExists('block')) ? \Drupal::url('block.admin_display') : '#')) . '</dd>';
      $output .= '<dt>' . t('Disabling drag-and-drop functionality') . '</dt>';
      $output .= '<dd>' . t('The default drag-and-drop user interface for ordering tables in Drupal presents a challenge for some users, including users of screen readers and other assistive technology. The drag-and-drop interface can be disabled in a table by clicking a link labeled "Show row weights" above the table. The replacement interface allows users to order the table by choosing numerical weights instead of dragging table rows.') . '</dd>';
      return '<p>' . t('This page shows you all available administration tasks for each module.') . '</p>';
      $output = '<p>' . t('Set and configure the default theme for your website.  Alternative <a href="@themes">themes</a> are available.', array('@themes' => 'http://drupal.org/project/themes')) . '</p>';
      $theme = $theme_list[$route_match->getParameter('theme')];
      return '<p>' . t('These options control the display settings for the %name theme. When your site is displayed using this theme, these settings will be used.', array('%name' => $theme->info['name'])) . '</p>';
      return '<p>' . t('These options control the default display settings for your entire site, across all themes. Unless they have been overridden by a specific theme, these settings will be used.') . '</p>';
      $output = '<p>' . t('Download additional <a href="@modules">contributed modules</a> to extend Drupal\'s functionality.', array('@modules' => 'http://drupal.org/project/modules')) . '</p>';
      if (\Drupal::moduleHandler()->moduleExists('update')) {
          $output .= '<p>' . t('Regularly review and install <a href="@updates">available updates</a> to maintain a secure and current site. Always run the <a href="@update-php">update script</a> each time a module is updated.', array('@update-php' => \Drupal::url('system.db_update'), '@updates' => \Drupal::url('update.status'))) . '</p>';
          $output .= '<p>' . t('Regularly review <a href="@updates">available updates</a> to maintain a secure and current site. Always run the <a href="@update-php">update script</a> each time a module is updated.', array('@update-php' => \Drupal::url('system.db_update'), '@updates' => \Drupal::url('update.status'))) . '</p>';
        $output .= '<p>' . t('Regularly review available updates to maintain a secure and current site. Always run the <a href="@update-php">update script</a> each time a module is updated. Enable the Update Manager module to update and install modules and themes.', array('@update-php' => \Drupal::url('system.db_update'))) . '</p>';
      return '<p>' . t('The uninstall process removes all data related to a module.') . '</p>';
    case 'entity.block.edit_form':
      if (($block = $route_match->getParameter('block')) && $block->get('plugin') == 'system_powered_by_block') {
        return '<p>' . t('The <em>Powered by Drupal</em> block is an optional link to the home page of the Drupal project. While there is absolutely no requirement that sites feature this link, it may be used to show support for Drupal.') . '</p>';
      if ($route_match->getParameter('plugin_id') == 'system_powered_by_block') {
        return '<p>' . t('The <em>Powered by Drupal</em> block is an optional link to the home page of the Drupal project. While there is absolutely no requirement that sites feature this link, it may be used to show support for Drupal.') . '</p>';
      }
      break;

    case 'system.site_maintenance_mode':
      if (\Drupal::currentUser()->id() == 1) {
        return '<p>' . t('Use maintenance mode when making major updates, particularly if the updates could disrupt visitors or the update process. Examples include upgrading, importing or exporting content, modifying a theme, modifying content types, and making backups.') . '</p>';
      return '<p>' . t("Here you can find a short overview of your site's parameters as well as any problems detected with your installation. It may be useful to copy and paste this information into support requests filed on drupal.org's support forums and project issue queues. Before filing a support request, ensure that your web server meets the <a href=\"@system-requirements\">system requirements.</a>", array('@system-requirements' => 'http://drupal.org/requirements')) . '</p>';
Dries Buytaert's avatar
 
Dries Buytaert committed
}

  return array_merge(drupal_common_theme(), array(
    // Normally theme suggestion templates are only picked up when they are in
    // themes. We explicitly define theme suggestions here so that the block
    // templates in core/modules/system/templates are picked up.
    'block__system_branding_block' => array(
    'block__system_menu_block' => array(
      'render element' => 'elements',
      'base hook' => 'block',
    ),
        'theme_groups' => array(),
        'theme_group_titles' => array(),
    'system_config_form' => array(
      'function' => 'theme_system_modules_details',
      'function' => 'theme_system_modules_uninstall',
      'variables' => array('requirements' => NULL),
      'variables' => array('blocks' => NULL),
      'variables' => array('block' => NULL),
      'variables' => array('content' => NULL),
      'variables' => array('menu_items' => NULL),
    'system_compact_link' => array(
      'variables' => array(),
      'function' => 'theme_system_compact_link',
 */
function system_hook_info() {
  $hooks['token_info'] = array(
    'group' => 'tokens',
  );
  $hooks['token_info_alter'] = array(
    'group' => 'tokens',
  );
  $hooks['tokens'] = array(
    'group' => 'tokens',
  );
/**
 * Implements hook_theme_suggestions_HOOK().
 */
function system_theme_suggestions_html(array $variables) {
  $path_args = explode('/', current_path());
  return theme_get_suggestions($path_args, 'html');
}

/**
 * Implements hook_theme_suggestions_HOOK().
 */
function system_theme_suggestions_page(array $variables) {
  $path_args = explode('/', current_path());
  return theme_get_suggestions($path_args, 'page');
}

/**
 * Implements hook_theme_suggestions_HOOK().
 */
function system_theme_suggestions_maintenance_page(array $variables) {
  $suggestions = array();

  // Dead databases will show error messages so supplying this template will
  // allow themers to override the page and the content completely.
  $offline = defined('MAINTENANCE_MODE');
  try {
    drupal_is_front_page();
  }
  catch (Exception $e) {
    // The database is not yet available.
    $offline = TRUE;
  }
  if ($offline) {
    $suggestions[] = 'maintenance_page__offline';
  }

  return $suggestions;
}

/**
 * Implements hook_theme_suggestions_HOOK().
 */
function system_theme_suggestions_region(array $variables) {
  $suggestions = array();
  if (!empty($variables['elements']['#region'])) {
    $suggestions[] = 'region__' . $variables['elements']['#region'];
  }
  return $suggestions;
}

/**
 * Implements hook_theme_suggestions_HOOK().
 */
function system_theme_suggestions_field(array $variables) {
  $suggestions = array();
  $element = $variables['element'];

  $suggestions[] = 'field__' . $element['#field_type'];
  $suggestions[] = 'field__' . $element['#field_name'];
  $suggestions[] = 'field__' . $element['#entity_type'] . '__' . $element['#bundle'];
  $suggestions[] = 'field__' . $element['#entity_type'] . '__' . $element['#field_name'];
  $suggestions[] = 'field__' . $element['#entity_type'] . '__' . $element['#field_name'] . '__' . $element['#bundle'];

  return $suggestions;
}

 * Implements hook_stream_wrappers_alter().
function system_stream_wrappers_alter(&$wrappers) {
  // Only register the private file stream wrapper if a file path has been set.
  if (!\Drupal::config('system.file')->get('path.private')) {
    unset($wrappers['private']);
 * Menu item access callback - only installed themes can be accessed.
  return \Drupal::currentUser()->hasPermission('administer themes') && drupal_theme_access($theme);
 * @defgroup authorize Authorized operations
 * @{
 * Functions to run operations with elevated privileges via authorize.php.
 * Because of the Update manager functionality included in Drupal core, there
 * is a mechanism for running operations with elevated file system privileges,
 * the top-level authorize.php script. This script runs at a reduced Drupal
 * bootstrap level so that it is not reliant on the entire site being
 * functional. The operations use a FileTransfer class to manipulate code
 * installed on the system as the user that owns the files, not the user that
 * the httpd is running as.
 *
 * The first setup is to define a callback function that should be authorized
 * to run with the elevated privileges. This callback should take a
 * FileTransfer as its first argument, although you can define an array of
 * other arguments it should be invoked with. The callback should be placed in
 * a separate .inc file that will be included by authorize.php.
 *
 * To run the operation, certain data must be saved into the SESSION, and then
 * the flow of control should be redirected to the authorize.php script. There
 * are two ways to do this, either to call system_authorized_run() directly,
 * or to call system_authorized_init() and then redirect to authorize.php,
 * using the URL from system_authorized_get_url(). Redirecting yourself is
 * necessary when your authorized operation is being triggered by a form
 * submit handler, since calling redirecting in a submit handler is a bad
 * idea, and you should instead use $form_state->setRedirect().
 *
 * Once the SESSION is setup for the operation and the user is redirected to
 * authorize.php, they will be prompted for their connection credentials (core
 * provides FTP and SSH by default, although other connection classes can be
 * added via contributed modules). With valid credentials, authorize.php will
 * instantiate the appropriate FileTransfer object, and then invoke the
 * desired operation passing in that object. The authorize.php script can act
 * as a Batch API processing page, if the operation requires a batch.
 *
 * @see authorize.php
 * @see \Drupal\Core\FileTransfer\FileTransfer
 */

/**
 * Setup a given callback to run via authorize.php with elevated privileges.
 *
 * To use authorize.php, certain variables must be stashed into $_SESSION. This
 * function sets up all the necessary $_SESSION variables. The calling function
 * should then redirect to authorize.php, using the full path returned by
 * system_authorized_get_url(). That initiates the workflow that will eventually
 * lead to the callback being invoked. The callback will be invoked at a low
 * bootstrap level, without all modules being invoked, so it needs to be careful
 * not to assume any code exists. Example (system_authorized_run()):
 * @code
 *   system_authorized_init($callback, $file, $arguments, $page_title);
 *   return new RedirectResponse(system_authorized_get_url()->toString());
 * @endcode
 * Example (update_manager_install_form_submit()):
 * @code
 *  system_authorized_init('update_authorize_run_install',
 *    drupal_get_path('module', 'update') . '/update.authorize.inc',
 *    $arguments, t('Update manager'));
 *  $form_state->setRedirectUrl(system_authorized_get_url());
 *   The name of the function to invoke once the user authorizes the operation.
 * @param $file
 *   The full path to the file where the callback function is implemented.
 * @param $arguments
 *   Optional array of arguments to pass into the callback when it is invoked.
 *   Note that the first argument to the callback is always the FileTransfer
 *   object created by authorize.php when the user authorizes the operation.
 * @param $page_title
 *   Optional string to use as the page title once redirected to authorize.php.
 * @return
 *   Nothing, this function just initializes variables in the user's session.
function system_authorized_init($callback, $file, $arguments = array(), $page_title = NULL) {
  // First, figure out what file transfer backends the site supports, and put
  // all of those in the SESSION so that authorize.php has access to all of
  // them via the class autoloader, even without a full bootstrap.
  $_SESSION['authorize_filetransfer_info'] = drupal_get_filetransfer_info();

  // Now, define the callback to invoke.
  $_SESSION['authorize_operation'] = array(
    'callback' => $callback,
    'file' => $file,
    'arguments' => $arguments,
  );

  if (isset($page_title)) {
    $_SESSION['authorize_page_title'] = $page_title;
/**
 * Return the URL for the authorize.php script.
 *
 * @param array $options
 *   Optional array of options to pass to url().
 *   The full URL to authorize.php, using HTTPS if available.
function system_authorized_get_url(array $options = array()) {
  // Force HTTPS if available, regardless of what the caller specifies.
  // Prefix with $base_url so url() treats it as an external link.
  $url = Url::fromUri('base://core/authorize.php');
  $url_options = $url->getOptions();
  $url->setOptions($options + $url_options);
  return $url;
/**
 * Returns the URL for the authorize.php script when it is processing a batch.
 *
 * @param array $options
 *   Optional array of options to pass to url().
function system_authorized_batch_processing_url(array $options = array()) {
  $options['query'] = array('batch' => '1');
  return system_authorized_get_url($options);
/**
 * Setup and invoke an operation using authorize.php.
 *
 */
function system_authorized_run($callback, $file, $arguments = array(), $page_title = NULL) {
  system_authorized_init($callback, $file, $arguments, $page_title);
  return new RedirectResponse(system_authorized_get_url()->toString());
/**
 * Use authorize.php to run batch_process().
 *
 * @see batch_process()
 */
function system_authorized_batch_process() {
  $finish_url = system_authorized_get_url();
  $process_url = system_authorized_batch_processing_url();
  return batch_process($finish_url->toString(), $process_url->toString());
 */
function system_updater_info() {
  return array(
    'module' => array(
      'class' => 'Drupal\Core\Updater\Module',
      'name' => t('Update modules'),
      'weight' => 0,
    ),
    'theme' => array(
      'class' => 'Drupal\Core\Updater\Theme',
 * Implements hook_filetransfer_info().
function system_filetransfer_info() {
  // This is the default, will be available on most systems.
  if (function_exists('ftp_connect')) {
      'class' => 'Drupal\Core\FileTransfer\FTP',
  // SSH2 lib connection is only available if the proper PHP extension is
  // installed.
  if (function_exists('ssh2_connect')) {
    $backends['ssh'] = array(
      'title' => t('SSH'),
      'class' => 'Drupal\Core\FileTransfer\SSH',
 * Implements hook_page_attachments().
 *
 * @see template_preprocess_maintenance_page()
 * @see \Drupal\system\Controller\SystemController::setLinkActiveClass()
function system_page_attachments(array &$page) {
  // Ensure the same CSS is loaded in template_preprocess_maintenance_page().
  $page['#attached']['library'][] = 'core/normalize';
  $page['#attached']['library'][] = 'system/base';
  if (\Drupal::service('router.admin_context')->isAdminRoute()) {
    $page['#attached']['library'][] = 'system/admin';
  // Attach libraries and CSS used by this theme.
  $active_theme = \Drupal::theme()->getActiveTheme();
  foreach ($active_theme->getLibraries() as $library) {
    $page['#attached']['library'][] = $library;
  }
  foreach ($active_theme->getStyleSheets() as $media => $stylesheets) {
    foreach ($stylesheets as $stylesheet) {
      $page['#attached']['css'][$stylesheet] = array(
        'group' => CSS_AGGREGATE_THEME,
        'every_page' => TRUE,
        'media' => $media
      );
    }
  }

  // Attach favicon.
  if (theme_get_setting('features.favicon')) {
    $favicon = theme_get_setting('favicon.url');
    $type = theme_get_setting('favicon.mimetype');
    $page['#attached']['html_head_link'][][] = array(
      'rel' => 'shortcut icon',
      'href' => UrlHelper::stripDangerousProtocols($favicon),
      'type' => $type,
    );
  }

  // Get the major Drupal version.
  list($version, ) = explode('.', \Drupal::VERSION);

  // Attach default meta tags.
  $meta_default = array(
    // Make sure the Content-Type comes first because the IE browser may be
    // vulnerable to XSS via encoding attacks from any content that comes
    // before this META tag, such as a TITLE tag.
    'system_meta_content_type' => array(
      '#tag' => 'meta',
      '#attributes' => array(
        'name' => 'charset',
        'charset' => 'utf-8',
      ),
      // Security: This always has to be output first.
      '#weight' => -1000,
    ),
    // Show Drupal and the major version number in the META GENERATOR tag.
    'system_meta_generator' => array(
      '#type' => 'html_tag',
      '#tag' => 'meta',
      '#attributes' => array(
        'name' => 'Generator',
        'content' => 'Drupal ' . $version . ' (http://drupal.org)',
      ),
    ),
    // Attach default mobile meta tags for responsive design.
    'MobileOptimized' => array(
      '#tag' => 'meta',
      '#attributes' => array(
        'name' => 'MobileOptimized',
        'content' => 'width',
      ),
    ),
    'HandheldFriendly' => array(
      '#tag' => 'meta',
      '#attributes' => array(
        'name' => 'HandheldFriendly',
        'content' => 'true',
      ),
    ),
    'viewport' => array(
      '#tag' => 'meta',
      '#attributes' => array(
        'name' => 'viewport',
        'content' => 'width=device-width, initial-scale=1.0',
      ),
    ),
  );
  foreach ($meta_default as $key => $value) {
    $page['#attached']['html_head'][] = [$value, $key];
  }

  // Handle setting the "active" class on links by:
  // - loading the active-link library if the current user is authenticated;
  // - applying a post-render cache callback if the current user is anonymous.
  // @see l()
  // @see \Drupal\Core\Utility\LinkGenerator::generate()
  // @see \Drupal\system\Controller\SystemController::setLinkActiveClass
  if (\Drupal::currentUser()->isAuthenticated()) {
    $page['#attached']['library'][] = 'core/drupal.active-link';
  }
  else {
    $page['#post_render_cache']['\Drupal\system\Controller\SystemController::setLinkActiveClass'] = array(
      // Collect the current state that determines whether a link is active.
      array(
        'path' => current_path(),
        'front' => drupal_is_front_page(),
        'language' => \Drupal::languageManager()->getCurrentLanguage(LanguageInterface::TYPE_URL)->getId(),
        'query' => \Drupal::request()->query->all(),
Dries Buytaert's avatar
 
Dries Buytaert committed
/**
Dries Buytaert's avatar
 
Dries Buytaert committed
 */
function system_form_user_form_alter(&$form, FormStateInterface $form_state) {
  if (\Drupal::config('system.date')->get('timezone.user.configurable')) {
function system_form_user_register_form_alter(&$form, FormStateInterface $form_state) {
  $config = \Drupal::config('system.date');
  if ($config->get('timezone.user.configurable') && $config->get('timezone.user.default') == DRUPAL_USER_TIMEZONE_SELECT) {
    system_user_timezone($form, $form_state);
Dries Buytaert's avatar
 
Dries Buytaert committed
  }
Dries Buytaert's avatar
 
Dries Buytaert committed
}

 * Implements hook_ENTITY_TYPE_presave() for user entities.
function system_user_presave(UserInterface $account) {
  $config = \Drupal::config('system.date');
  if ($config->get('timezone.user.configurable') && !$account->getTimeZone() && !$config->get('timezone.user.default')) {
    $account->timezone = $config->get('timezone.default');
function system_user_login($account) {
  $config = \Drupal::config('system.date');
  // If the user has a NULL time zone, notify them to set a time zone.
  if (!$account->getTimezone() && $config->get('timezone.user.configurable') && $config->get('timezone.user.warn')) {
    drupal_set_message(t('Configure your <a href="@user-edit">account time zone setting</a>.', array('@user-edit' => _url("user/$account->id()/edit", array('query' => drupal_get_destination(), 'fragment' => 'edit-timezone')))));
  }
}

/**
 * Add the time zone field to the user edit and register forms.
 */
function system_user_timezone(&$form, FormStateInterface $form_state) {
  $user = \Drupal::currentUser();
  $account = $form_state->getFormObject()->getEntity();
    '#weight' => 6,
  );
  $form['timezone']['timezone'] = array(
    '#type' => 'select',
    '#title' => t('Time zone'),
    '#default_value' => $account->getTimezone() ? $account->getTimezone() : \Drupal::config('system.date')->get('timezone.default'),
    '#options' => system_time_zones($account->id() != $user->id()),
    '#description' => t('Select the desired local time and time zone. Dates and times throughout this site will be displayed using this time zone.'),
  );
  $user_input = $form_state->getUserInput();
  if (!$account->getTimezone() && $account->id() == $user->id() && empty($user_input['timezone'])) {
    $form['timezone']['#description'] = t('Your time zone setting will be automatically detected if possible. Confirm the selection and click save.');
    $form['timezone']['#attached']['library'][] = 'core/drupal.timezone';
    $form['timezone']['timezone']['#attributes'] = array('class' => array('timezone-detect'));
 * Implements hook_preprocess_HOOK() for block templates.
function system_preprocess_block(&$variables) {
  switch ($variables['base_plugin_id']) {
    case 'system_branding_block':
      $variables['site_logo'] = '';
      if ($variables['content']['site_logo']['#access'] && $variables['content']['site_logo']['#uri']) {
        $variables['site_logo'] = $variables['content']['site_logo']['#uri'];
      }
      $variables['site_name'] = '';
      if ($variables['content']['site_name']['#access'] && $variables['content']['site_name']['#markup']) {
        $variables['site_name'] = $variables['content']['site_name']['#markup'];
      }
      $variables['site_slogan'] = '';
      if ($variables['content']['site_slogan']['#access'] && $variables['content']['site_slogan']['#markup']) {
        $variables['site_slogan'] = $variables['content']['site_slogan']['#markup'];
      }
      break;

      $variables['attributes']['role'] = 'complementary';
      $variables['attributes']['role'] = 'complementary';
 * Checks the existence of the directory specified in $form_element.
 *
 * This function is called from the system_settings form to check all core
 * file directories (file_public_path, file_private_path, file_temporary_path).
 *
 * @param $form_element
 *   The form element containing the name of the directory to check.
 * @param \Drupal\Core\Form\FormStateInterface $form_state
 *   The current state of the form.
function system_check_directory($form_element, FormStateInterface $form_state) {
  $directory = $form_element['#value'];
  if (strlen($directory) == 0) {
    return $form_element;
  }
  $logger = \Drupal::logger('file system');
  if (!is_dir($directory) && !drupal_mkdir($directory, NULL, TRUE)) {
    // If the directory does not exists and cannot be created.
    $form_state->setErrorByName($form_element['#parents'][0], t('The directory %directory does not exist and could not be created.', array('%directory' => $directory)));
    $logger->error('The directory %directory does not exist and could not be created.', array('%directory' => $directory));
  }

  if (is_dir($directory) && !is_writable($directory) && !drupal_chmod($directory)) {
    // If the directory is not writable and cannot be made so.
    $form_state->setErrorByName($form_element['#parents'][0], t('The directory %directory exists but is not writable and could not be made writable.', array('%directory' => $directory)));
    $logger->error('The directory %directory exists but is not writable and could not be made writable.', array('%directory' => $directory));
    if ($form_element['#name'] == 'file_public_path') {
      // Create public .htaccess file.
      file_save_htaccess($directory, FALSE);
 * Returns an array of information about enabled modules or themes.
 * This function returns the contents of the .info.yml file for each installed
 * @param $name
 *   (optional) The name of a module or theme whose information shall be
 *   returned. If omitted, all records for the provided $type will be returned.
 *   If $name does not exist in the provided $type or is not enabled, an empty
 *   array will be returned.
 *   An associative array of module or theme information keyed by name, or only
 *   information for $name, if given. If no records are available, an empty
 *   array is returned.
 *
 * @see system_rebuild_module_data()
 * @see system_rebuild_theme_data()
 */
function system_get_info($type, $name = NULL) {
    $data = system_rebuild_module_data();
    foreach (\Drupal::moduleHandler()->getModuleList() as $module => $filename) {
      if (isset($data[$module])) {
        $info[$module] = $data[$module]->info;
      }
  else {
    $list = system_list($type);
    foreach ($list as $shortname => $item) {
      if (!empty($item->status)) {
        $info[$shortname] = $item->info;
      }
    }
  }
  if (isset($name)) {
    return isset($info[$name]) ? $info[$name] : array();
Dries Buytaert's avatar
 
Dries Buytaert committed
/**
 * Helper function to scan and collect module .info.yml data.
 * @return \Drupal\Core\Extension\Extension[]
Dries Buytaert's avatar
 
Dries Buytaert committed
 */
function _system_rebuild_module_data() {
  $listing = new ExtensionDiscovery(\Drupal::root());
  // Include the installation profile in modules that are loaded.
  if ($profile = drupal_get_profile()) {
    $modules[$profile] = $profiles[$profile];
    // Installation profile hooks are always executed last.
    $modules[$profile]->weight = 1000;
  }
  // Set defaults for module info.
  $defaults = array(
    'dependencies' => array(),
    'description' => '',
    'package' => 'Other',
Dries Buytaert's avatar
 
Dries Buytaert committed

  // Read info files for each module.
  foreach ($modules as $key => $module) {
    // Look for the info file.
    $module->info = \Drupal::service('info_parser')->parse($module->getPathname());
    // Add the info file modification time, so it becomes available for
    // contributed modules to use for ordering module lists.
    $module->info['mtime'] = $module->getMTime();
    // Merge in defaults and save.
    $modules[$key]->info = $module->info + $defaults;

    // Installation profiles are hidden by default, unless explicitly specified
    // otherwise in the .info.yml file.
    if ($key == $profile && !isset($modules[$key]->info['hidden'])) {
      $modules[$key]->info['hidden'] = TRUE;
    }

    // Invoke hook_system_info_alter() to give installed modules a chance to
    // modify the data in the .info.yml files if necessary.
    // @todo Remove $type argument, obsolete with $module->getType().
    \Drupal::moduleHandler()->alter('system_info', $modules[$key]->info, $modules[$key], $type);
  // It is possible that a module was marked as required by
  // hook_system_info_alter() and modules that it depends on are not required.
  foreach ($modules as $module) {
    _system_rebuild_module_data_ensure_required($module, $modules);
  }


  if ($profile && isset($modules[$profile])) {
    // The installation profile is required, if it's a valid module.
    $modules[$profile]->info['required'] = TRUE;
    // Add a default distribution name if the profile did not provide one.
    // @see install_profile_info()
    // @see drupal_install_profile_distribution_name()
    if (!isset($modules[$profile]->info['distribution']['name'])) {
      $modules[$profile]->info['distribution']['name'] = 'Drupal';
/**
 * Ensures that dependencies of required modules are also required.
 *
 * @param \Drupal\Core\Extension\Extension $module
 * @param \Drupal\Core\Extension\Extension[] $modules
 *   The array of all module info.
 */
function _system_rebuild_module_data_ensure_required($module, &$modules) {
  if (!empty($module->info['required'])) {
    foreach ($module->info['dependencies'] as $dependant) {
      if (!isset($modules[$dependant]->info['required'])) {
        $modules[$dependant]->info['required'] = TRUE;
        $modules[$dependant]->info['explanation'] = t('Dependency of required module @module', array('@module' => $module->info['name']));
        // Ensure any dependencies it has are required.
        _system_rebuild_module_data_ensure_required($modules[$dependant], $modules);
      }
    }
  }
}

 * Rebuild, save, and return data about all currently available modules.
 * @return \Drupal\Core\Extension\Extension[]
function system_rebuild_module_data() {
  $modules_cache = &drupal_static(__FUNCTION__);
  // Only rebuild once per request. $modules and $modules_cache cannot be
  // combined into one variable, because the $modules_cache variable is reset by
  // reference from system_list_reset() during the rebuild.
  if (!isset($modules_cache)) {
    $modules = _system_rebuild_module_data();
    // Add status, weight, and schema version.
    $installed_modules = \Drupal::config('core.extension')->get('module') ?: array();
    foreach ($modules as $name => $module) {
      $module->weight = isset($installed_modules[$name]) ? $installed_modules[$name] : 0;
      $module->status = (int) isset($installed_modules[$name]);
      $module->schema_version = SCHEMA_UNINSTALLED;
      $files[$name] = $module->getPathname();
    $modules = \Drupal::moduleHandler()->buildModuleDependencies($modules);

    // Store filenames to allow system_list() and drupal_get_filename() to
    // retrieve them without having to rebuild or scan the filesystem.
    \Drupal::state()->set('system.module.files', $files);
 * Rebuild, save, and return data about all currently available themes.
 * @return \Drupal\Core\Extension\Extension[]
 * @deprecated in Drupal 8.x-dev, will be removed before Drupal 8.0.
 *   Use \Drupal::service('theme_handler')->rebuildThemeData().
  return \Drupal::service('theme_handler')->rebuildThemeData();
/**
 * Returns an array of default theme features.
 */
function _system_default_theme_features() {
  return array(
    'logo',
    'favicon',
    'name',
    'slogan',
    'node_user_picture',
    'comment_user_picture',
    'comment_user_verification',
  );
}

/**
 * Get a list of available regions from a specified theme.
 *
 * @param \Drupal\Core\Extension\Extension|string $theme
 *   A theme extension object, or the name of a theme.
 * @param $show
 *   Possible values: REGIONS_ALL or REGIONS_VISIBLE. Visible excludes hidden
 *   regions.
 * @return
 *   An array of regions in the form $region['name'] = 'description'.
 */
function system_region_list($theme, $show = REGIONS_ALL) {
  if (!$theme instanceof Extension) {
    $themes = \Drupal::service('theme_handler')->listInfo();
    if (!isset($themes[$theme])) {
      return array();
    }
    $theme = $themes[$theme];