Newer
Older
/**
* @file
* Configuration system that lets administrators modify the workings of the site.
*/
use Drupal\Component\Utility\UrlHelper;
use Drupal\Core\Cache\Cache;
use Drupal\Core\Extension\Extension;
catch
committed
use Drupal\Core\Extension\ExtensionDiscovery;
Alex Pott
committed
use Drupal\Core\Form\FormState;
Dries Buytaert
committed
use Drupal\Core\Form\FormStateInterface;
Angie Byron
committed
use Drupal\Core\Routing\RouteMatchInterface;
use Drupal\Core\StringTranslation\TranslationWrapper;
use Drupal\Core\Language\LanguageInterface;
use Drupal\Core\Menu\MenuTreeParameters;
use Drupal\Core\Url;
use Drupal\Core\Block\BlockPluginInterface;
use Drupal\user\UserInterface;
use Symfony\Component\HttpFoundation\RedirectResponse;
use GuzzleHttp\Exception\RequestException;
Angie Byron
committed
/**
* New users will be set to the default time zone at registration.
*/
const DRUPAL_USER_TIMEZONE_DEFAULT = 0;
Angie Byron
committed
/**
* New users will get an empty time zone at registration.
*/
const DRUPAL_USER_TIMEZONE_EMPTY = 1;
Angie Byron
committed
/**
* New users will select their own timezone at registration.
*/
const DRUPAL_USER_TIMEZONE_SELECT = 2;
Angie Byron
committed
Dries Buytaert
committed
/**
Dries Buytaert
committed
* Disabled option on forms and settings
*/
const DRUPAL_DISABLED = 0;
Dries Buytaert
committed
/**
* Optional option on forms and settings
*/
const DRUPAL_OPTIONAL = 1;
Dries Buytaert
committed
/**
* Required option on forms and settings
*/
const DRUPAL_REQUIRED = 2;
Dries Buytaert
committed
Dries Buytaert
committed
/**
* Return only visible regions.
Dries Buytaert
committed
*
* @see system_region_list()
Dries Buytaert
committed
*/
const REGIONS_VISIBLE = 'visible';
Dries Buytaert
committed
/**
* Return all regions.
Dries Buytaert
committed
*
* @see system_region_list()
Dries Buytaert
committed
*/
const REGIONS_ALL = 'all';
Dries Buytaert
committed
Dries Buytaert
committed
* Implements hook_help().
Angie Byron
committed
function system_help($route_name, RouteMatchInterface $route_match) {
switch ($route_name) {
case 'help.page.system':
Dries Buytaert
committed
$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>';
Dries Buytaert
committed
$output .= '<h3>' . t('Uses') . '</h3>';
$output .= '<dl>';
$output .= '<dt>' . t('Managing modules') . '</dt>';
Angie Byron
committed
$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>';
Dries Buytaert
committed
$output .= '<dt>' . t('Managing themes') . '</dt>';
Angie Byron
committed
$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>';
Dries Buytaert
committed
$output .= '<dt>' . t('Managing caching') . '</dt>';
Angie Byron
committed
$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>';
Dries Buytaert
committed
$output .= '<dt>' . t('Performing system maintenance') . '</dt>';
Angie Byron
committed
$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>';
Dries Buytaert
committed
$output .= '<dt>' . t('Configuring basic site settings') . '</dt>';
Angie Byron
committed
$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>';
Jennifer Hodgdon
committed
$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>';
Dries Buytaert
committed
$output .= '</dl>';
Angie Byron
committed
$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>';
Dries Buytaert
committed
return $output;
case 'system.admin_index':
return '<p>' . t('This page shows you all available administration tasks for each module.') . '</p>';
case 'system.themes_page':
Angie Byron
committed
$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>';
return $output;
case 'system.theme_settings_theme':
Dries Buytaert
committed
$theme_list = list_themes();
Angie Byron
committed
$theme = $theme_list[$route_match->getParameter('theme')];
Dries Buytaert
committed
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>';
case 'system.theme_settings':
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>';
case 'system.modules_list':
$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')) {
Dries Buytaert
committed
if (update_manager_access()) {
Alex Pott
committed
$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>';
Dries Buytaert
committed
}
else {
Alex Pott
committed
$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>';
Dries Buytaert
committed
}
}
else {
Alex Pott
committed
$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>';
Dries Buytaert
committed
}
Dries Buytaert
committed
return $output;
case 'system.modules_uninstall':
Dries Buytaert
committed
return '<p>' . t('The uninstall process removes all data related to a module.') . '</p>';
case 'entity.block.edit_form':
Angie Byron
committed
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>';
Gábor Hojtsy
committed
}
Gábor Hojtsy
committed
break;
case 'block.admin_add':
Angie Byron
committed
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>';
Dries Buytaert
committed
}
Angie Byron
committed
break;
case 'system.status':
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
committed
}
/**
Dries Buytaert
committed
* Implements hook_theme().
*/
Dries Buytaert
committed
function system_theme() {
return array_merge(drupal_common_theme(), array(
Angie Byron
committed
// 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.
Angie Byron
committed
'block__system_branding_block' => array(
'render element' => 'elements',
Angie Byron
committed
'base hook' => 'block',
),
'block__system_menu_block' => array(
'render element' => 'elements',
'base hook' => 'block',
),
Dries Buytaert
committed
'system_themes_page' => array(
'variables' => array(
'theme_groups' => array(),
'theme_group_titles' => array(),
'file' => 'system.admin.inc',
Dries Buytaert
committed
),
'system_config_form' => array(
'render element' => 'form',
Dries Buytaert
committed
),
'confirm_form' => array(
'render element' => 'form',
Dries Buytaert
committed
),
'system_modules_details' => array(
'render element' => 'form',
'file' => 'system.admin.inc',
'function' => 'theme_system_modules_details',
Dries Buytaert
committed
),
'system_modules_uninstall' => array(
'render element' => 'form',
'file' => 'system.admin.inc',
'function' => 'theme_system_modules_uninstall',
Dries Buytaert
committed
),
'status_report' => array(
'variables' => array('requirements' => NULL),
'file' => 'system.admin.inc',
Dries Buytaert
committed
),
'admin_page' => array(
'variables' => array('blocks' => NULL),
'file' => 'system.admin.inc',
Dries Buytaert
committed
),
'admin_block' => array(
'variables' => array('block' => NULL),
'file' => 'system.admin.inc',
Dries Buytaert
committed
),
'admin_block_content' => array(
'variables' => array('content' => NULL),
'file' => 'system.admin.inc',
Dries Buytaert
committed
),
'system_admin_index' => array(
'variables' => array('menu_items' => NULL),
'file' => 'system.admin.inc',
Dries Buytaert
committed
),
'system_compact_link' => array(
'variables' => array(),
'function' => 'theme_system_compact_link',
Dries Buytaert
committed
),
Dries Buytaert
committed
));
}
Dries Buytaert
committed
* Implements hook_hook_info().
*/
function system_hook_info() {
$hooks['token_info'] = array(
'group' => 'tokens',
);
$hooks['token_info_alter'] = array(
'group' => 'tokens',
);
$hooks['tokens'] = array(
'group' => 'tokens',
);
Angie Byron
committed
$hooks['tokens_alter'] = array(
'group' => 'tokens',
);
return $hooks;
}
/**
* 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');
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
}
/**
* 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;
}
Dries Buytaert
committed
/**
* Implements hook_stream_wrappers_alter().
Dries Buytaert
committed
*/
function system_stream_wrappers_alter(&$wrappers) {
Angie Byron
committed
// 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']);
Angie Byron
committed
}
Dries Buytaert
committed
}
Gábor Hojtsy
committed
/**
catch
committed
* Menu item access callback - only installed themes can be accessed.
Gábor Hojtsy
committed
*/
function _system_themes_access($theme) {
return \Drupal::currentUser()->hasPermission('administer themes') && drupal_theme_access($theme);
Gábor Hojtsy
committed
}
/**
Angie Byron
committed
* @defgroup authorize Authorized operations
* @{
* Functions to run operations with elevated privileges via authorize.php.
*
Angie Byron
committed
* 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().
Angie Byron
committed
*
* 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
Alex Pott
committed
* @see \Drupal\Core\FileTransfer\FileTransfer
* @see hook_filetransfer_info()
Angie Byron
committed
*/
/**
* Setup a given callback to run via authorize.php with elevated privileges.
*
Jennifer Hodgdon
committed
* 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());
Jennifer Hodgdon
committed
* @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());
Jennifer Hodgdon
committed
* @endcode
*
* @param $callback
Jennifer Hodgdon
committed
* 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
Angie Byron
committed
* Nothing, this function just initializes variables in the user's session.
*/
Angie Byron
committed
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)) {
Angie Byron
committed
$_SESSION['authorize_page_title'] = $page_title;
}
Angie Byron
committed
}
Angie Byron
committed
/**
* Return the URL for the authorize.php script.
Angie Byron
committed
*
* @param array $options
* Optional array of options to pass to url().
* @return \Drupal\Core\Url
Angie Byron
committed
* The full URL to authorize.php, using HTTPS if available.
Jennifer Hodgdon
committed
*
* @see system_authorized_init()
Angie Byron
committed
*/
Angie Byron
committed
function system_authorized_get_url(array $options = array()) {
Angie Byron
committed
global $base_url;
Angie Byron
committed
// Force HTTPS if available, regardless of what the caller specifies.
Angie Byron
committed
$options['https'] = TRUE;
Dries Buytaert
committed
// 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;
}
Angie Byron
committed
/**
* 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().
*
* @return \Drupal\Core\Url
Angie Byron
committed
*/
function system_authorized_batch_processing_url(array $options = array()) {
$options['query'] = array('batch' => '1');
return system_authorized_get_url($options);
Angie Byron
committed
}
Angie Byron
committed
/**
* Setup and invoke an operation using authorize.php.
*
Dries Buytaert
committed
* @see system_authorized_init()
Angie Byron
committed
*/
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());
Angie Byron
committed
}
Angie Byron
committed
/**
* Use authorize.php to run batch_process().
*
* @see batch_process()
*/
function system_authorized_batch_process() {
$finish_url = system_authorized_get_url();
Angie Byron
committed
$process_url = system_authorized_batch_processing_url();
return batch_process($finish_url->toString(), $process_url->toString());
Angie Byron
committed
}
Angie Byron
committed
/**
* @} End of "defgroup authorize".
*/
/**
Dries Buytaert
committed
* Implements hook_updater_info().
*/
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',
'name' => t('Update themes'),
'weight' => 0,
),
);
}
Dries Buytaert
committed
/**
* Implements hook_filetransfer_info().
Dries Buytaert
committed
*/
function system_filetransfer_info() {
Dries Buytaert
committed
$backends = array();
Angie Byron
committed
// This is the default, will be available on most systems.
if (function_exists('ftp_connect')) {
Angie Byron
committed
$backends['ftp'] = array(
Dries Buytaert
committed
'title' => t('FTP'),
'class' => 'Drupal\Core\FileTransfer\FTP',
Dries Buytaert
committed
'weight' => 0,
Dries Buytaert
committed
);
}
Dries Buytaert
committed
// 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',
Dries Buytaert
committed
'weight' => 20,
Dries Buytaert
committed
);
}
return $backends;
}
/**
* 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(
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
'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 template_preprocess_links()
// @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
committed
}
Dries Buytaert
committed
* Implements hook_form_FORM_ID_alter().
Dries Buytaert
committed
function system_form_user_form_alter(&$form, FormStateInterface $form_state) {
if (\Drupal::config('system.date')->get('timezone.user.configurable')) {
catch
committed
system_user_timezone($form, $form_state);
Angie Byron
committed
}
}
/**
Dries Buytaert
committed
* Implements hook_form_FORM_ID_alter().
Angie Byron
committed
*/
Dries Buytaert
committed
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);
/**
* 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');
}
}
Angie Byron
committed
/**
Dries Buytaert
committed
* Implements hook_user_login().
Angie Byron
committed
*/
function system_user_login($account) {
$config = \Drupal::config('system.date');
Angie Byron
committed
// 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')))));
Angie Byron
committed
}
}
/**
* Add the time zone field to the user edit and register forms.
*/
Dries Buytaert
committed
function system_user_timezone(&$form, FormStateInterface $form_state) {
$user = \Drupal::currentUser();
Dries Buytaert
committed
$account = $form_state->getFormObject()->getEntity();
Angie Byron
committed
$form['timezone'] = array(
'#type' => 'details',
Angie Byron
committed
'#title' => t('Locale settings'),
Angie Byron
committed
'#open' => TRUE,
Angie Byron
committed
'#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'),
Dries Buytaert
committed
'#options' => system_time_zones($account->id() != $user->id()),
Angie Byron
committed
'#description' => t('Select the desired local time and time zone. Dates and times throughout this site will be displayed using this time zone.'),
);
Angie Byron
committed
$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.');
Angie Byron
committed
$form['timezone']['#attached']['library'][] = 'core/drupal.timezone';
$form['timezone']['timezone']['#attributes'] = array('class' => array('timezone-detect'));
Angie Byron
committed
}
}
Gábor Hojtsy
committed
/**
Angie Byron
committed
* Implements hook_preprocess_HOOK() for block templates.
Dries Buytaert
committed
*/
Dries Buytaert
committed
function system_preprocess_block(&$variables) {
switch ($variables['base_plugin_id']) {
Angie Byron
committed
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;
Dries Buytaert
committed
case 'system_powered_by_block':
Alex Pott
committed
$variables['attributes']['role'] = 'complementary';
Dries Buytaert
committed
break;
Angie Byron
committed
Dries Buytaert
committed
case 'system_help_block':
Alex Pott
committed
$variables['attributes']['role'] = 'complementary';
Dries Buytaert
committed
break;
Dries Buytaert
committed
}
Gábor Hojtsy
committed
}
Dries Buytaert
committed
/**
* 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).
Dries Buytaert
committed
*
* @param $form_element
* The form element containing the name of the directory to check.
Alex Pott
committed
* @param \Drupal\Core\Form\FormStateInterface $form_state
* The current state of the form.
Dries Buytaert
committed
*/
Alex Pott
committed
function system_check_directory($form_element, FormStateInterface $form_state) {
$directory = $form_element['#value'];
Angie Byron
committed
if (strlen($directory) == 0) {
return $form_element;
}
Angie Byron
committed
$logger = \Drupal::logger('file system');
if (!is_dir($directory) && !drupal_mkdir($directory, NULL, TRUE)) {
// If the directory does not exists and cannot be created.
Alex Pott
committed
$form_state->setErrorByName($form_element['#parents'][0], t('The directory %directory does not exist and could not be created.', array('%directory' => $directory)));
Angie Byron
committed
$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.
Alex Pott
committed
$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)));
Angie Byron
committed
$logger->error('The directory %directory exists but is not writable and could not be made writable.', array('%directory' => $directory));
}
Angie Byron
committed
elseif (is_dir($directory)) {
if ($form_element['#name'] == 'file_public_path') {
// Create public .htaccess file.
Dries Buytaert
committed
file_save_htaccess($directory, FALSE);
}
else {
// Create private .htaccess file.
Dries Buytaert
committed
file_save_htaccess($directory);
}
}
Dries Buytaert
committed
return $form_element;
}
Angie Byron
committed
/**
Dries Buytaert
committed
* Returns an array of information about enabled modules or themes.
Angie Byron
committed
*
Dries Buytaert
committed
* This function returns the contents of the .info.yml file for each installed
* module or theme.
Angie Byron
committed
*
* @param $type
* Either 'module' or 'theme'.
Dries Buytaert
committed
* @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.
Dries Buytaert
committed
*
Angie Byron
committed
* @return
Dries Buytaert
committed
* 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.
Angie Byron
committed
*
* @see system_rebuild_module_data()
* @see system_rebuild_theme_data()
*/
Dries Buytaert
committed
function system_get_info($type, $name = NULL) {
Angie Byron
committed
$info = array();
Dries Buytaert
committed
if ($type == 'module') {
$data = system_rebuild_module_data();
foreach (\Drupal::moduleHandler()->getModuleList() as $module => $filename) {
Angie Byron
committed
if (isset($data[$module])) {
$info[$module] = $data[$module]->info;
}
Dries Buytaert
committed
}
else {
$list = system_list($type);
foreach ($list as $shortname => $item) {
if (!empty($item->status)) {
$info[$shortname] = $item->info;
}
Dries Buytaert
committed
}
}
if (isset($name)) {
return isset($info[$name]) ? $info[$name] : array();
Angie Byron
committed
}
return $info;
}
* Helper function to scan and collect module .info.yml data.
*
catch
committed
* @return \Drupal\Core\Extension\Extension[]
Dries Buytaert
committed
* An associative array of module information.
Angie Byron
committed
function _system_rebuild_module_data() {
$listing = new ExtensionDiscovery(\Drupal::root());
Dries Buytaert
committed
// Find modules
catch
committed
$modules = $listing->scan('module');
Dries Buytaert
committed
// Find installation profiles.
catch
committed
$profiles = $listing->scan('profile');
Jennifer Hodgdon
committed
// Include the installation profile in modules that are loaded.
catch
committed
if ($profile = drupal_get_profile()) {
$modules[$profile] = $profiles[$profile];
// Installation profile hooks are always executed last.
$modules[$profile]->weight = 1000;
}
Angie Byron
committed
Dries Buytaert
committed
// Set defaults for module info.
$defaults = array(
'dependencies' => array(),
'description' => '',
Dries Buytaert
committed
'version' => NULL,
'php' => DRUPAL_MINIMUM_PHP,
);
Dries Buytaert
committed
// Read info files for each module.
foreach ($modules as $key => $module) {
// Look for the info file.
catch
committed
$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.
catch
committed
$module->info['mtime'] = $module->getMTime();
Dries Buytaert
committed
// Merge in defaults and save.
$modules[$key]->info = $module->info + $defaults;
Jennifer Hodgdon
committed
// Installation profiles are hidden by default, unless explicitly specified
// otherwise in the .info.yml file.
Angie Byron
committed
if ($key == $profile && !isset($modules[$key]->info['hidden'])) {
$modules[$key]->info['hidden'] = TRUE;
}
Dries Buytaert
committed
// Invoke hook_system_info_alter() to give installed modules a chance to
// modify the data in the .info.yml files if necessary.
catch
committed
// @todo Remove $type argument, obsolete with $module->getType().
$type = 'module';
\Drupal::moduleHandler()->alter('system_info', $modules[$key]->info, $modules[$key], $type);
}
Gábor Hojtsy
committed
// 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);
}
catch
committed
if ($profile && isset($modules[$profile])) {
Jennifer Hodgdon
committed
// The installation profile is required, if it's a valid module.
Dries Buytaert
committed
$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';
Dries Buytaert
committed
}
Dries Buytaert
committed
}
Angie Byron
committed
Dries Buytaert
committed
return $modules;
}
/**
* Ensures that dependencies of required modules are also required.
*
catch
committed
* @param \Drupal\Core\Extension\Extension $module
* The module info.
catch
committed
* @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);
}
}
}
}
Dries Buytaert
committed
/**
Angie Byron
committed
* Rebuild, save, and return data about all currently available modules.
Dries Buytaert
committed
*
catch
committed
* @return \Drupal\Core\Extension\Extension[]
Dries Buytaert
committed
* Array of all available modules and their data.
*/
Angie Byron
committed
function system_rebuild_module_data() {
Dries Buytaert
committed
$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();
$files = array();
Dries Buytaert
committed
ksort($modules);
catch
committed
// Add status, weight, and schema version.
$installed_modules = \Drupal::config('core.extension')->get('module') ?: array();
catch
committed
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);
Dries Buytaert
committed
$modules_cache = $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);
Dries Buytaert
committed
}
return $modules_cache;
Angie Byron
committed
}
Dries Buytaert
committed
/**
Angie Byron
committed
* Rebuild, save, and return data about all currently available themes.
Dries Buytaert
committed
*
catch
committed
* @return \Drupal\Core\Extension\Extension[]
Dries Buytaert
committed
* Array of all available themes and their data.
*
Jennifer Hodgdon
committed
* @deprecated in Drupal 8.x-dev, will be removed before Drupal 8.0.
* Use \Drupal::service('theme_handler')->rebuildThemeData().
Dries Buytaert
committed
*/
Angie Byron
committed
function system_rebuild_theme_data() {
return \Drupal::service('theme_handler')->rebuildThemeData();
Dries Buytaert
committed
}
/**
* 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.
Dries Buytaert
committed
* @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];