Move all files to 2017/
This commit is contained in:
parent
ac7370f67f
commit
2875863330
15717 changed files with 0 additions and 0 deletions
|
@ -0,0 +1,7 @@
|
|||
langcode: en
|
||||
status: true
|
||||
dependencies: { }
|
||||
id: fallback
|
||||
label: 'Fallback date format'
|
||||
locked: true
|
||||
pattern: 'D, m/d/Y - H:i'
|
|
@ -0,0 +1,7 @@
|
|||
langcode: en
|
||||
status: true
|
||||
dependencies: { }
|
||||
id: html_date
|
||||
label: 'HTML Date'
|
||||
locked: true
|
||||
pattern: Y-m-d
|
|
@ -0,0 +1,7 @@
|
|||
langcode: en
|
||||
status: true
|
||||
dependencies: { }
|
||||
id: html_datetime
|
||||
label: 'HTML Datetime'
|
||||
locked: true
|
||||
pattern: 'Y-m-d\TH:i:sO'
|
|
@ -0,0 +1,7 @@
|
|||
langcode: en
|
||||
status: true
|
||||
dependencies: { }
|
||||
id: html_month
|
||||
label: 'HTML Month'
|
||||
locked: true
|
||||
pattern: Y-m
|
|
@ -0,0 +1,7 @@
|
|||
langcode: en
|
||||
status: true
|
||||
dependencies: { }
|
||||
id: html_time
|
||||
label: 'HTML Time'
|
||||
locked: true
|
||||
pattern: 'H:i:s'
|
|
@ -0,0 +1,7 @@
|
|||
langcode: en
|
||||
status: true
|
||||
dependencies: { }
|
||||
id: html_week
|
||||
label: 'HTML Week'
|
||||
locked: true
|
||||
pattern: Y-\WW
|
|
@ -0,0 +1,7 @@
|
|||
langcode: en
|
||||
status: true
|
||||
dependencies: { }
|
||||
id: html_year
|
||||
label: 'HTML Year'
|
||||
locked: true
|
||||
pattern: 'Y'
|
|
@ -0,0 +1,7 @@
|
|||
langcode: en
|
||||
status: true
|
||||
dependencies: { }
|
||||
id: html_yearless_date
|
||||
label: 'HTML Yearless date'
|
||||
locked: true
|
||||
pattern: m-d
|
|
@ -0,0 +1,7 @@
|
|||
langcode: en
|
||||
status: true
|
||||
dependencies: { }
|
||||
id: long
|
||||
label: 'Default long date'
|
||||
locked: false
|
||||
pattern: 'l, F j, Y - H:i'
|
|
@ -0,0 +1,7 @@
|
|||
langcode: en
|
||||
status: true
|
||||
dependencies: { }
|
||||
id: medium
|
||||
label: 'Default medium date'
|
||||
locked: false
|
||||
pattern: 'D, m/d/Y - H:i'
|
|
@ -0,0 +1,7 @@
|
|||
langcode: en
|
||||
status: true
|
||||
dependencies: { }
|
||||
id: short
|
||||
label: 'Default short date'
|
||||
locked: false
|
||||
pattern: 'm/d/Y - H:i'
|
|
@ -0,0 +1 @@
|
|||
filetransfer_default:
|
|
@ -0,0 +1,4 @@
|
|||
threshold:
|
||||
requirements_warning: 172800
|
||||
requirements_error: 1209600
|
||||
logging: 1
|
|
@ -0,0 +1,9 @@
|
|||
country:
|
||||
default: ''
|
||||
first_day: 0
|
||||
timezone:
|
||||
default: ''
|
||||
user:
|
||||
configurable: true
|
||||
warn: false
|
||||
default: 0
|
|
@ -0,0 +1,3 @@
|
|||
context:
|
||||
lines_leading: 2
|
||||
lines_trailing: 2
|
|
@ -0,0 +1,5 @@
|
|||
allow_insecure_uploads: false
|
||||
default_scheme: 'public'
|
||||
path:
|
||||
temporary: ''
|
||||
temporary_maximum_age: 21600
|
|
@ -0,0 +1 @@
|
|||
jpeg_quality: 75
|
|
@ -0,0 +1 @@
|
|||
toolkit: gd
|
|
@ -0,0 +1 @@
|
|||
error_level: hide
|
|
@ -0,0 +1,2 @@
|
|||
interface:
|
||||
default: 'php_mail'
|
|
@ -0,0 +1,2 @@
|
|||
message: '@site is currently under maintenance. We should be back shortly. Thank you for your patience.'
|
||||
langcode: en
|
|
@ -0,0 +1,7 @@
|
|||
langcode: en
|
||||
status: true
|
||||
dependencies: { }
|
||||
id: account
|
||||
label: 'User account menu'
|
||||
description: 'Links related to the active user account'
|
||||
locked: true
|
|
@ -0,0 +1,7 @@
|
|||
langcode: en
|
||||
status: true
|
||||
dependencies: { }
|
||||
id: admin
|
||||
label: Administration
|
||||
description: 'Administrative task links'
|
||||
locked: true
|
|
@ -0,0 +1,7 @@
|
|||
langcode: en
|
||||
status: true
|
||||
dependencies: { }
|
||||
id: footer
|
||||
label: Footer
|
||||
description: 'Site information links'
|
||||
locked: true
|
|
@ -0,0 +1,7 @@
|
|||
langcode: en
|
||||
status: true
|
||||
dependencies: { }
|
||||
id: main
|
||||
label: 'Main navigation'
|
||||
description: 'Site section links'
|
||||
locked: true
|
|
@ -0,0 +1,7 @@
|
|||
langcode: en
|
||||
status: true
|
||||
dependencies: { }
|
||||
id: tools
|
||||
label: Tools
|
||||
description: 'User tool links, often added by modules'
|
||||
locked: true
|
|
@ -0,0 +1,15 @@
|
|||
cache:
|
||||
page:
|
||||
max_age: 0
|
||||
css:
|
||||
preprocess: true
|
||||
gzip: true
|
||||
fast_404:
|
||||
enabled: true
|
||||
paths: '/\.(?:txt|png|gif|jpe?g|css|js|ico|swf|flv|cgi|bat|pl|dll|exe|asp)$/i'
|
||||
exclude_paths: '/\/(?:styles|imagecache)\//'
|
||||
html: '<!DOCTYPE html><html><head><title>404 Not Found</title></head><body><h1>Not Found</h1><p>The requested URL "@path" was not found on this server.</p></body></html>'
|
||||
js:
|
||||
preprocess: true
|
||||
gzip: true
|
||||
stale_file_threshold: 2592000
|
|
@ -0,0 +1,6 @@
|
|||
channel:
|
||||
description: ''
|
||||
items:
|
||||
limit: 10
|
||||
view_mode: rss
|
||||
langcode: en
|
12
2017/web/core/modules/system/config/install/system.site.yml
Normal file
12
2017/web/core/modules/system/config/install/system.site.yml
Normal file
|
@ -0,0 +1,12 @@
|
|||
uuid: ''
|
||||
name: ''
|
||||
mail: ''
|
||||
slogan: ''
|
||||
page:
|
||||
403: ''
|
||||
404: ''
|
||||
front: /user/login
|
||||
admin_compact_mode: false
|
||||
weight_select_max: 100
|
||||
langcode: en
|
||||
default_langcode: en
|
|
@ -0,0 +1,14 @@
|
|||
favicon:
|
||||
mimetype: image/vnd.microsoft.icon
|
||||
path: ''
|
||||
url: ''
|
||||
use_default: true
|
||||
features:
|
||||
comment_user_picture: true
|
||||
comment_user_verification: true
|
||||
favicon: true
|
||||
node_user_picture: true
|
||||
logo:
|
||||
path: ''
|
||||
url: ''
|
||||
use_default: true
|
|
@ -0,0 +1,2 @@
|
|||
admin: ''
|
||||
default: stark
|
356
2017/web/core/modules/system/config/schema/system.schema.yml
Normal file
356
2017/web/core/modules/system/config/schema/system.schema.yml
Normal file
|
@ -0,0 +1,356 @@
|
|||
# Schema for the configuration files of the System module.
|
||||
|
||||
system.site:
|
||||
type: config_object
|
||||
label: 'Site information'
|
||||
mapping:
|
||||
uuid:
|
||||
type: uuid
|
||||
label: 'Site UUID'
|
||||
constraints:
|
||||
Uuid: []
|
||||
NotNull: []
|
||||
name:
|
||||
type: label
|
||||
label: 'Site name'
|
||||
mail:
|
||||
type: email
|
||||
label: 'Email address'
|
||||
slogan:
|
||||
type: label
|
||||
label: 'Slogan'
|
||||
page:
|
||||
type: mapping
|
||||
label: 'Pages'
|
||||
mapping:
|
||||
403:
|
||||
type: path
|
||||
label: 'Default 403 (access denied) page'
|
||||
404:
|
||||
type: path
|
||||
label: 'Default 404 (not found) page'
|
||||
front:
|
||||
type: path
|
||||
label: 'Default front page'
|
||||
admin_compact_mode:
|
||||
type: boolean
|
||||
label: 'Compact mode'
|
||||
weight_select_max:
|
||||
type: integer
|
||||
label: 'Weight element maximum value'
|
||||
default_langcode:
|
||||
type: string
|
||||
label: 'Site default language code'
|
||||
mail_notification:
|
||||
type: string
|
||||
label: 'Notification email address'
|
||||
|
||||
system.maintenance:
|
||||
type: config_object
|
||||
label: 'Maintenance mode'
|
||||
mapping:
|
||||
message:
|
||||
type: text
|
||||
label: 'Message to display when in maintenance mode'
|
||||
|
||||
system.authorize:
|
||||
type: config_object
|
||||
label: 'Authorize settings'
|
||||
mapping:
|
||||
filetransfer_default:
|
||||
type: string
|
||||
label: 'Default file transfer protocol'
|
||||
|
||||
system.cron:
|
||||
type: config_object
|
||||
label: 'Cron settings'
|
||||
mapping:
|
||||
threshold:
|
||||
type: mapping
|
||||
label: 'Thresholds'
|
||||
mapping:
|
||||
requirements_warning:
|
||||
type: integer
|
||||
label: 'Requirements warning period'
|
||||
requirements_error:
|
||||
type: integer
|
||||
label: 'Requirements error period'
|
||||
logging:
|
||||
type: integer
|
||||
label: 'Detailed cron logging'
|
||||
|
||||
system.date:
|
||||
type: config_object
|
||||
label: 'Date settings'
|
||||
mapping:
|
||||
first_day:
|
||||
type: integer
|
||||
label: 'First day of week'
|
||||
country:
|
||||
type: mapping
|
||||
label: 'Country'
|
||||
mapping:
|
||||
default:
|
||||
type: string
|
||||
label: 'Default country'
|
||||
timezone:
|
||||
type: mapping
|
||||
label: 'Time zone settings'
|
||||
mapping:
|
||||
default:
|
||||
type: string
|
||||
label: 'Default time zone'
|
||||
user:
|
||||
type: mapping
|
||||
label: 'User'
|
||||
mapping:
|
||||
configurable:
|
||||
type: boolean
|
||||
label: 'Users may set their own time zone'
|
||||
default:
|
||||
type: integer
|
||||
label: 'Time zone for new users'
|
||||
warn:
|
||||
type: boolean
|
||||
label: 'Remind users at login if their time zone is not set'
|
||||
|
||||
system.diff:
|
||||
type: config_object
|
||||
label: 'Diff settings'
|
||||
mapping:
|
||||
context:
|
||||
type: mapping
|
||||
label: 'Context'
|
||||
mapping:
|
||||
lines_leading:
|
||||
type: integer
|
||||
label: 'Number of leading lines in a diff'
|
||||
lines_trailing:
|
||||
type: integer
|
||||
label: 'Number of trailing lines in a diff'
|
||||
|
||||
system.logging:
|
||||
type: config_object
|
||||
label: 'Logging settings'
|
||||
mapping:
|
||||
error_level:
|
||||
type: string
|
||||
label: 'Error messages to display'
|
||||
|
||||
system.performance:
|
||||
type: config_object
|
||||
label: 'Performance settings'
|
||||
mapping:
|
||||
cache:
|
||||
type: mapping
|
||||
label: 'Caching'
|
||||
mapping:
|
||||
page:
|
||||
type: mapping
|
||||
label: 'Page caching'
|
||||
mapping:
|
||||
max_age:
|
||||
type: integer
|
||||
label: 'Max age'
|
||||
css:
|
||||
type: mapping
|
||||
label: 'CSS performance settings'
|
||||
mapping:
|
||||
preprocess:
|
||||
type: boolean
|
||||
label: 'Aggregate CSS files'
|
||||
gzip:
|
||||
type: boolean
|
||||
label: 'Compress CSS files'
|
||||
fast_404:
|
||||
type: mapping
|
||||
label: 'Fast 404 settings'
|
||||
mapping:
|
||||
enabled:
|
||||
type: boolean
|
||||
label: 'Fast 404 enabled'
|
||||
paths:
|
||||
type: string
|
||||
label: 'Regular expression to match'
|
||||
exclude_paths:
|
||||
type: string
|
||||
label: 'Regular expression to not match'
|
||||
html:
|
||||
type: string
|
||||
label: 'Fast 404 page html'
|
||||
js:
|
||||
type: mapping
|
||||
label: 'JavaScript performance settings'
|
||||
mapping:
|
||||
preprocess:
|
||||
type: boolean
|
||||
label: 'JavaScript preprocess'
|
||||
gzip:
|
||||
type: boolean
|
||||
label: 'Compress JavaScript files.'
|
||||
stale_file_threshold:
|
||||
type: integer
|
||||
label: 'Stale file threshold'
|
||||
|
||||
system.rss:
|
||||
type: config_object
|
||||
label: 'Feed settings'
|
||||
mapping:
|
||||
channel:
|
||||
type: mapping
|
||||
label: 'Feed channel'
|
||||
mapping:
|
||||
description:
|
||||
type: text
|
||||
label: 'Feed description'
|
||||
items:
|
||||
type: mapping
|
||||
label: 'Feed items'
|
||||
mapping:
|
||||
limit:
|
||||
type: integer
|
||||
label: 'Feed item limit'
|
||||
view_mode:
|
||||
type: string
|
||||
label: 'Feed content'
|
||||
|
||||
system.theme:
|
||||
type: config_object
|
||||
label: 'Theme settings'
|
||||
mapping:
|
||||
admin:
|
||||
type: string
|
||||
label: 'Administration theme'
|
||||
default:
|
||||
type: string
|
||||
label: 'Default theme'
|
||||
|
||||
system.menu.*:
|
||||
type: config_entity
|
||||
label: 'Menu'
|
||||
mapping:
|
||||
id:
|
||||
type: string
|
||||
label: 'ID'
|
||||
label:
|
||||
type: label
|
||||
label: 'Label'
|
||||
description:
|
||||
type: label
|
||||
label: 'Menu description'
|
||||
locked:
|
||||
type: boolean
|
||||
label: ''
|
||||
|
||||
system.action.*:
|
||||
type: config_entity
|
||||
label: 'System action'
|
||||
mapping:
|
||||
id:
|
||||
type: string
|
||||
label: 'ID'
|
||||
label:
|
||||
type: label
|
||||
label: 'Label'
|
||||
type:
|
||||
type: string
|
||||
label: 'Type'
|
||||
plugin:
|
||||
type: string
|
||||
label: 'Plugin'
|
||||
configuration:
|
||||
type: action.configuration.[%parent.plugin]
|
||||
|
||||
system.file:
|
||||
type: config_object
|
||||
label: 'File system'
|
||||
mapping:
|
||||
allow_insecure_uploads:
|
||||
type: boolean
|
||||
label: 'Allow insecure uploads'
|
||||
default_scheme:
|
||||
type: string
|
||||
label: 'Default download method'
|
||||
path:
|
||||
type: mapping
|
||||
label: 'Path settings'
|
||||
mapping:
|
||||
temporary:
|
||||
type: string
|
||||
label: 'Temporary directory'
|
||||
temporary_maximum_age:
|
||||
type: integer
|
||||
label: 'Maximum age for temporary files'
|
||||
|
||||
system.image:
|
||||
type: config_object
|
||||
label: 'Image settings'
|
||||
mapping:
|
||||
toolkit:
|
||||
type: string
|
||||
label: 'Toolkit'
|
||||
|
||||
system.image.gd:
|
||||
type: config_object
|
||||
label: 'Image settings'
|
||||
mapping:
|
||||
jpeg_quality:
|
||||
type: integer
|
||||
label: 'JPEG quality'
|
||||
|
||||
system.mail:
|
||||
type: config_object
|
||||
label: 'Mail system'
|
||||
mapping:
|
||||
interface:
|
||||
type: sequence
|
||||
label: 'Interfaces'
|
||||
sequence:
|
||||
type: string
|
||||
label: 'Interface'
|
||||
|
||||
system.theme.global:
|
||||
type: theme_settings
|
||||
label: 'Theme global settings'
|
||||
|
||||
block.settings.system_branding_block:
|
||||
type: block_settings
|
||||
label: 'Branding block'
|
||||
mapping:
|
||||
use_site_logo:
|
||||
type: boolean
|
||||
label: 'Use site logo'
|
||||
use_site_name:
|
||||
type: boolean
|
||||
label: 'Use site name'
|
||||
use_site_slogan:
|
||||
type: boolean
|
||||
label: 'Use site slogan'
|
||||
|
||||
block.settings.system_menu_block:*:
|
||||
type: block_settings
|
||||
label: 'Menu block'
|
||||
mapping:
|
||||
level:
|
||||
type: integer
|
||||
label: 'Starting level'
|
||||
depth:
|
||||
type: integer
|
||||
label: 'Maximum number of levels'
|
||||
|
||||
block.settings.local_tasks_block:
|
||||
type: block_settings
|
||||
label: 'Tabs block'
|
||||
mapping:
|
||||
primary:
|
||||
type: boolean
|
||||
label: 'Whether primary tabs are shown'
|
||||
secondary:
|
||||
type: boolean
|
||||
label: 'Whether secondary tabs are shown'
|
||||
|
||||
condition.plugin.request_path:
|
||||
type: condition.plugin
|
||||
mapping:
|
||||
pages:
|
||||
type: string
|
|
@ -0,0 +1,49 @@
|
|||
/**
|
||||
* @file
|
||||
* Throbber.
|
||||
*/
|
||||
|
||||
.ajax-progress {
|
||||
display: inline-block;
|
||||
padding: 1px 5px 2px 5px;
|
||||
}
|
||||
[dir="rtl"] .ajax-progress {
|
||||
float: right;
|
||||
}
|
||||
.ajax-progress-throbber .throbber {
|
||||
background: transparent url(../../../../misc/throbber-active.gif) no-repeat 0 center;
|
||||
display: inline;
|
||||
padding: 1px 5px 2px;
|
||||
}
|
||||
.ajax-progress-throbber .message {
|
||||
display: inline;
|
||||
padding: 1px 5px 2px;
|
||||
}
|
||||
tr .ajax-progress-throbber .throbber {
|
||||
margin: 0 2px;
|
||||
}
|
||||
.ajax-progress-bar {
|
||||
width: 16em;
|
||||
}
|
||||
|
||||
/* Full screen throbber */
|
||||
.ajax-progress-fullscreen {
|
||||
/* Can't do center:50% middle: 50%, so approximate it for a typical window size. */
|
||||
left: 49%; /* LTR */
|
||||
position: fixed;
|
||||
top: 48.5%;
|
||||
z-index: 1000;
|
||||
background-color: #232323;
|
||||
background-image: url(../../../../misc/loading-small.gif);
|
||||
background-position: center center;
|
||||
background-repeat: no-repeat;
|
||||
border-radius: 7px;
|
||||
height: 24px;
|
||||
opacity: 0.9;
|
||||
padding: 4px;
|
||||
width: 24px;
|
||||
}
|
||||
[dir="rtl"] .ajax-progress-fullscreen {
|
||||
left: auto;
|
||||
right: 49%;
|
||||
}
|
32
2017/web/core/modules/system/css/components/align.module.css
Normal file
32
2017/web/core/modules/system/css/components/align.module.css
Normal file
|
@ -0,0 +1,32 @@
|
|||
/**
|
||||
* @file
|
||||
* Alignment classes for text and block level elements.
|
||||
*/
|
||||
|
||||
.text-align-left {
|
||||
text-align: left;
|
||||
}
|
||||
.text-align-right {
|
||||
text-align: right;
|
||||
}
|
||||
.text-align-center {
|
||||
text-align: center;
|
||||
}
|
||||
.text-align-justify {
|
||||
text-align: justify;
|
||||
}
|
||||
|
||||
/**
|
||||
* Alignment classes for block level elements (images, videos, blockquotes, etc.)
|
||||
*/
|
||||
.align-left {
|
||||
float: left;
|
||||
}
|
||||
.align-right {
|
||||
float: right;
|
||||
}
|
||||
.align-center {
|
||||
display: block;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
}
|
|
@ -0,0 +1,22 @@
|
|||
/**
|
||||
* @file
|
||||
* Visual styles for animated throbber.
|
||||
*
|
||||
* @see autocomplete.js
|
||||
*/
|
||||
|
||||
.js input.form-autocomplete {
|
||||
background-image: url(../../../../misc/throbber-inactive.png);
|
||||
background-position: 100% center; /* LTR */
|
||||
background-repeat: no-repeat;
|
||||
}
|
||||
.js[dir="rtl"] input.form-autocomplete {
|
||||
background-position: 0% center;
|
||||
}
|
||||
.js input.form-autocomplete.ui-autocomplete-loading {
|
||||
background-image: url(../../../../misc/throbber-active.gif);
|
||||
background-position: 100% center; /* LTR */
|
||||
}
|
||||
.js[dir="rtl"] input.form-autocomplete.ui-autocomplete-loading {
|
||||
background-position: 0% center;
|
||||
}
|
|
@ -0,0 +1,15 @@
|
|||
/**
|
||||
* @file
|
||||
* Float clearing.
|
||||
*
|
||||
* Based on the micro clearfix hack by Nicolas Gallagher, with the :before
|
||||
* pseudo selector removed to allow normal top margin collapse.
|
||||
*
|
||||
* @see http://nicolasgallagher.com/micro-clearfix-hack
|
||||
*/
|
||||
|
||||
.clearfix:after {
|
||||
content: "";
|
||||
display: table;
|
||||
clear: both;
|
||||
}
|
|
@ -0,0 +1,13 @@
|
|||
/**
|
||||
* @file
|
||||
* Inline items.
|
||||
*/
|
||||
|
||||
.container-inline div,
|
||||
.container-inline label {
|
||||
display: inline-block;
|
||||
}
|
||||
/* Details contents always need to be rendered as block. */
|
||||
.container-inline .details-wrapper {
|
||||
display: block;
|
||||
}
|
|
@ -0,0 +1,10 @@
|
|||
/**
|
||||
* @file
|
||||
* Collapsible details.
|
||||
*
|
||||
* @see collapse.js
|
||||
*/
|
||||
|
||||
.js details:not([open]) .details-wrapper {
|
||||
display: none;
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
/**
|
||||
* @file
|
||||
* Fieldgroup border reset.
|
||||
*/
|
||||
|
||||
.fieldgroup {
|
||||
border-width: 0;
|
||||
padding: 0;
|
||||
}
|
|
@ -0,0 +1,53 @@
|
|||
/**
|
||||
* @file
|
||||
* Utility classes to hide elements in different ways.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Hide elements from all users.
|
||||
*
|
||||
* Used for elements which should not be immediately displayed to any user. An
|
||||
* example would be collapsible details that will be expanded with a click
|
||||
* from a user. The effect of this class can be toggled with the jQuery show()
|
||||
* and hide() functions.
|
||||
*/
|
||||
.hidden {
|
||||
display: none;
|
||||
}
|
||||
|
||||
/**
|
||||
* Hide elements visually, but keep them available for screen readers.
|
||||
*
|
||||
* Used for information required for screen reader users to understand and use
|
||||
* the site where visual display is undesirable. Information provided in this
|
||||
* manner should be kept concise, to avoid unnecessary burden on the user.
|
||||
* "!important" is used to prevent unintentional overrides.
|
||||
*/
|
||||
.visually-hidden {
|
||||
position: absolute !important;
|
||||
clip: rect(1px, 1px, 1px, 1px);
|
||||
overflow: hidden;
|
||||
height: 1px;
|
||||
width: 1px;
|
||||
word-wrap: normal;
|
||||
}
|
||||
|
||||
/**
|
||||
* The .focusable class extends the .visually-hidden class to allow
|
||||
* the element to be focusable when navigated to via the keyboard.
|
||||
*/
|
||||
.visually-hidden.focusable:active,
|
||||
.visually-hidden.focusable:focus {
|
||||
position: static !important;
|
||||
clip: auto;
|
||||
overflow: visible;
|
||||
height: auto;
|
||||
width: auto;
|
||||
}
|
||||
|
||||
/**
|
||||
* Hide visually and from screen readers, but maintain layout.
|
||||
*/
|
||||
.invisible {
|
||||
visibility: hidden;
|
||||
}
|
|
@ -0,0 +1,19 @@
|
|||
/**
|
||||
* @file
|
||||
* Styles for item list.
|
||||
*/
|
||||
|
||||
.item-list__comma-list,
|
||||
.item-list__comma-list li {
|
||||
display: inline;
|
||||
}
|
||||
.item-list__comma-list {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
.item-list__comma-list li:after {
|
||||
content: ", ";
|
||||
}
|
||||
.item-list__comma-list li:last-child:after {
|
||||
content: "";
|
||||
}
|
22
2017/web/core/modules/system/css/components/js.module.css
Normal file
22
2017/web/core/modules/system/css/components/js.module.css
Normal file
|
@ -0,0 +1,22 @@
|
|||
/**
|
||||
* @file
|
||||
* Utility classes to assist with Javascript functionality.
|
||||
*/
|
||||
|
||||
/**
|
||||
* For anything you want to hide on page load when JS is enabled, so
|
||||
* that you can use the JS to control visibility and avoid flicker.
|
||||
*/
|
||||
.js .js-hide {
|
||||
display: none;
|
||||
}
|
||||
|
||||
/**
|
||||
* For anything you want to show on page load only when JS is enabled.
|
||||
*/
|
||||
.js-show {
|
||||
display: none;
|
||||
}
|
||||
.js .js-show {
|
||||
display: block;
|
||||
}
|
|
@ -0,0 +1,8 @@
|
|||
/**
|
||||
* @file
|
||||
* Utility class to prevent text wrapping.
|
||||
*/
|
||||
|
||||
.nowrap {
|
||||
white-space: nowrap;
|
||||
}
|
|
@ -0,0 +1,8 @@
|
|||
/*
|
||||
* @file
|
||||
* Contain positioned elements.
|
||||
*/
|
||||
|
||||
.position-container {
|
||||
position: relative;
|
||||
}
|
|
@ -0,0 +1,51 @@
|
|||
/**
|
||||
* @file
|
||||
* Progress behavior.
|
||||
*
|
||||
* @see progress.js
|
||||
*/
|
||||
|
||||
.progress {
|
||||
position: relative;
|
||||
}
|
||||
.progress__track {
|
||||
background-color: #fff;
|
||||
border: 1px solid;
|
||||
margin-top: 5px;
|
||||
max-width: 100%;
|
||||
min-width: 100px;
|
||||
height: 16px;
|
||||
}
|
||||
.progress__bar {
|
||||
background-color: #000;
|
||||
height: 16px;
|
||||
width: 3%;
|
||||
min-width: 3%;
|
||||
max-width: 100%;
|
||||
}
|
||||
.progress__description,
|
||||
.progress__percentage {
|
||||
color: #555;
|
||||
overflow: hidden;
|
||||
font-size: 0.875em;
|
||||
margin-top: 0.2em;
|
||||
}
|
||||
.progress__description {
|
||||
float: left; /* LTR */
|
||||
}
|
||||
[dir="rtl"] .progress__description {
|
||||
float: right;
|
||||
}
|
||||
.progress__percentage {
|
||||
float: right; /* LTR */
|
||||
}
|
||||
[dir="rtl"] .progress__percentage {
|
||||
float: left;
|
||||
}
|
||||
.progress--small .progress__track {
|
||||
height: 7px;
|
||||
}
|
||||
.progress--small .progress__bar {
|
||||
height: 7px;
|
||||
background-size: 20px 20px;
|
||||
}
|
|
@ -0,0 +1,15 @@
|
|||
/*
|
||||
* @file
|
||||
* Utility class to remove browser styles, especially for button.
|
||||
*/
|
||||
|
||||
.reset-appearance {
|
||||
-webkit-appearance: none;
|
||||
-moz-appearance: none;
|
||||
appearance: none;
|
||||
border: 0 none;
|
||||
background: transparent;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
line-height: inherit;
|
||||
}
|
|
@ -0,0 +1,21 @@
|
|||
/**
|
||||
* @file
|
||||
* Resizable textareas.
|
||||
*/
|
||||
|
||||
.resize-none {
|
||||
resize: none;
|
||||
}
|
||||
.resize-vertical {
|
||||
resize: vertical;
|
||||
min-height: 2em;
|
||||
}
|
||||
.resize-horizontal {
|
||||
resize: horizontal;
|
||||
max-width: 100%;
|
||||
}
|
||||
.resize-both {
|
||||
resize: both;
|
||||
max-width: 100%;
|
||||
min-height: 2em;
|
||||
}
|
|
@ -0,0 +1,13 @@
|
|||
/**
|
||||
* @file
|
||||
* Table header behavior.
|
||||
*
|
||||
* @see tableheader.js
|
||||
*/
|
||||
|
||||
table.sticky-header {
|
||||
background-color: #fff;
|
||||
margin-top: 0;
|
||||
z-index: 500;
|
||||
top: 0;
|
||||
}
|
|
@ -0,0 +1,30 @@
|
|||
/**
|
||||
* @file
|
||||
* Styles for the system status counter component.
|
||||
*/
|
||||
|
||||
.system-status-counter__status-icon {
|
||||
display: inline-block;
|
||||
height: 25px;
|
||||
width: 25px;
|
||||
vertical-align: middle;
|
||||
}
|
||||
.system-status-counter__status-icon:before {
|
||||
content: "";
|
||||
background-size: 16px;
|
||||
background-position: center 2px;
|
||||
background-repeat: no-repeat;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.system-status-counter__status-icon--error:before {
|
||||
background-image: url(../../../../misc/icons/e32700/error.svg);
|
||||
}
|
||||
.system-status-counter__status-icon--warning:before {
|
||||
background-image: url(../../../../misc/icons/e29700/warning.svg);
|
||||
}
|
||||
.system-status-counter__status-icon--checked:before {
|
||||
background-image: url(../../../../misc/icons/73b355/check.svg);
|
||||
}
|
|
@ -0,0 +1,27 @@
|
|||
/**
|
||||
* @file
|
||||
* Styles for the system status report counters.
|
||||
*/
|
||||
|
||||
.system-status-report-counters__item {
|
||||
width: 100%;
|
||||
padding: 0.5em 0;
|
||||
text-align: center;
|
||||
white-space: nowrap;
|
||||
background-color: rgba(0, 0, 0, 0.063);
|
||||
margin-bottom: 0.5em;
|
||||
}
|
||||
|
||||
@media screen and (min-width: 60em) {
|
||||
.system-status-report-counters {
|
||||
flex-wrap: wrap;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
}
|
||||
.system-status-report-counters__item--half-width {
|
||||
width: 49%;
|
||||
}
|
||||
.system-status-report-counters__item--third-width {
|
||||
width: 33%;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,14 @@
|
|||
/**
|
||||
* @file
|
||||
* Default styles for the System Status general info.
|
||||
*/
|
||||
|
||||
.system-status-general-info__item {
|
||||
border: 1px solid #ccc;
|
||||
margin-top: 1em;
|
||||
padding: 0 1em 1em;
|
||||
}
|
||||
|
||||
.system-status-general-info__item-title {
|
||||
border-bottom: 1px solid #ccc;
|
||||
}
|
|
@ -0,0 +1,88 @@
|
|||
/**
|
||||
* @file
|
||||
* Table drag behavior.
|
||||
*
|
||||
* @see tabledrag.js
|
||||
*/
|
||||
|
||||
body.drag {
|
||||
cursor: move;
|
||||
}
|
||||
tr.region-title {
|
||||
font-weight: bold;
|
||||
}
|
||||
tr.region-message {
|
||||
color: #999;
|
||||
}
|
||||
tr.region-populated {
|
||||
display: none;
|
||||
}
|
||||
tr.add-new .tabledrag-changed {
|
||||
display: none;
|
||||
}
|
||||
.draggable a.tabledrag-handle {
|
||||
cursor: move;
|
||||
float: left; /* LTR */
|
||||
height: 1.7em;
|
||||
margin-left: -1em; /* LTR */
|
||||
overflow: hidden;
|
||||
text-decoration: none;
|
||||
}
|
||||
[dir="rtl"] .draggable a.tabledrag-handle {
|
||||
float: right;
|
||||
margin-right: -1em;
|
||||
margin-left: 0;
|
||||
}
|
||||
a.tabledrag-handle:hover {
|
||||
text-decoration: none;
|
||||
}
|
||||
a.tabledrag-handle .handle {
|
||||
background: url(../../../../misc/icons/787878/move.svg) no-repeat 6px 7px;
|
||||
height: 14px;
|
||||
margin: -0.4em 0.5em 0;
|
||||
padding: 0.42em 0.5em;
|
||||
width: 14px;
|
||||
}
|
||||
a.tabledrag-handle:hover .handle,
|
||||
a.tabledrag-handle:focus .handle {
|
||||
background-image: url(../../../../misc/icons/000000/move.svg);
|
||||
}
|
||||
.touchevents .draggable td {
|
||||
padding: 0 10px;
|
||||
}
|
||||
.touchevents .draggable .menu-item__link {
|
||||
display: inline-block;
|
||||
padding: 10px 0;
|
||||
}
|
||||
.touchevents a.tabledrag-handle {
|
||||
height: 44px;
|
||||
width: 40px;
|
||||
}
|
||||
.touchevents a.tabledrag-handle .handle {
|
||||
background-position: 40% 19px; /* LTR */
|
||||
height: 21px;
|
||||
}
|
||||
[dir="rtl"] .touch a.tabledrag-handle .handle {
|
||||
background-position: right 40% top 19px;
|
||||
}
|
||||
.touchevents .draggable.drag a.tabledrag-handle .handle {
|
||||
background-position: 50% -32px;
|
||||
}
|
||||
.tabledrag-toggle-weight-wrapper {
|
||||
text-align: right; /* LTR */
|
||||
}
|
||||
[dir="rtl"] .tabledrag-toggle-weight-wrapper {
|
||||
text-align: left;
|
||||
}
|
||||
.indentation {
|
||||
float: left; /* LTR */
|
||||
height: 1.7em;
|
||||
margin: -0.4em 0.2em -0.4em -0.4em; /* LTR */
|
||||
padding: 0.42em 0 0.42em 0.6em; /* LTR */
|
||||
width: 20px;
|
||||
}
|
||||
[dir="rtl"] .indentation {
|
||||
float: right;
|
||||
margin: -0.4em -0.4em -0.4em 0.2em;
|
||||
padding: 0.42em 0.6em 0.42em 0;
|
||||
}
|
|
@ -0,0 +1,19 @@
|
|||
/**
|
||||
* @file
|
||||
* Table sort indicator.
|
||||
*
|
||||
* @see tablesort-indicator.html.twig
|
||||
*/
|
||||
|
||||
.tablesort {
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
display: inline-block;
|
||||
background-size: 100%;
|
||||
}
|
||||
.tablesort--asc {
|
||||
background-image: url(../../../../misc/icons/787878/twistie-down.svg);
|
||||
}
|
||||
.tablesort--desc {
|
||||
background-image: url(../../../../misc/icons/787878/twistie-up.svg);
|
||||
}
|
|
@ -0,0 +1,18 @@
|
|||
/**
|
||||
* @file
|
||||
* Visual styles for a nested tree child.
|
||||
*/
|
||||
|
||||
div.tree-child {
|
||||
background: url(../../../../misc/tree.png) no-repeat 11px center; /* LTR */
|
||||
}
|
||||
div.tree-child-last {
|
||||
background: url(../../../../misc/tree-bottom.png) no-repeat 11px center; /* LTR */
|
||||
}
|
||||
[dir="rtl"] div.tree-child,
|
||||
[dir="rtl"] div.tree-child-last {
|
||||
background-position: -65px center;
|
||||
}
|
||||
div.tree-child-horizontal {
|
||||
background: url(../../../../misc/tree.png) no-repeat -11px center;
|
||||
}
|
401
2017/web/core/modules/system/css/system.admin.css
Normal file
401
2017/web/core/modules/system/css/system.admin.css
Normal file
|
@ -0,0 +1,401 @@
|
|||
/**
|
||||
* @file
|
||||
* Styles for administration pages.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Reusable layout styles.
|
||||
*/
|
||||
.layout-container {
|
||||
margin: 0 1.5em;
|
||||
}
|
||||
.layout-container:after {
|
||||
content: "";
|
||||
display: table;
|
||||
clear: both;
|
||||
}
|
||||
|
||||
@media screen and (min-width: 38em) {
|
||||
.layout-container {
|
||||
margin: 0 2.5em;
|
||||
}
|
||||
.layout-column {
|
||||
float: left; /* LTR */
|
||||
box-sizing: border-box;
|
||||
}
|
||||
[dir="rtl"] .layout-column {
|
||||
float: right;
|
||||
}
|
||||
.layout-column + .layout-column {
|
||||
padding-left: 10px; /* LTR */
|
||||
}
|
||||
[dir="rtl"] .layout-column + .layout-column {
|
||||
padding-right: 10px;
|
||||
padding-left: 0;
|
||||
}
|
||||
.layout-column--half {
|
||||
width: 50%;
|
||||
}
|
||||
.layout-column--quarter {
|
||||
width: 25%;
|
||||
}
|
||||
.layout-column--three-quarter {
|
||||
width: 75%;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Panel.
|
||||
* Used to visually group items together.
|
||||
*/
|
||||
.panel {
|
||||
padding: 5px 5px 15px;
|
||||
}
|
||||
.panel__description {
|
||||
margin: 0 0 3px;
|
||||
padding: 2px 0 3px 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* System compact link: to toggle the display of description text.
|
||||
*/
|
||||
.compact-link {
|
||||
margin: 0 0 0.5em 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Quick inline admin links.
|
||||
*/
|
||||
small .admin-link:before {
|
||||
content: ' [';
|
||||
}
|
||||
small .admin-link:after {
|
||||
content: ']';
|
||||
}
|
||||
|
||||
/**
|
||||
* Modules page.
|
||||
*/
|
||||
.system-modules thead > tr {
|
||||
border: 0;
|
||||
}
|
||||
.system-modules div.incompatible {
|
||||
font-weight: bold;
|
||||
}
|
||||
.system-modules td.checkbox {
|
||||
min-width: 25px;
|
||||
width: 4%;
|
||||
}
|
||||
.system-modules td.module {
|
||||
width: 25%;
|
||||
}
|
||||
.system-modules td {
|
||||
vertical-align: top;
|
||||
}
|
||||
.system-modules label,
|
||||
.system-modules-uninstall label {
|
||||
color: #1d1d1d;
|
||||
font-size: 1.15em;
|
||||
}
|
||||
.system-modules details {
|
||||
color: #5c5c5b;
|
||||
line-height: 20px;
|
||||
overflow: hidden; /* truncates descriptions if too long */
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
.system-modules details[open] {
|
||||
height: auto;
|
||||
overflow: visible;
|
||||
white-space: normal;
|
||||
}
|
||||
.system-modules details[open] summary .text {
|
||||
-webkit-hyphens: auto;
|
||||
-moz-hyphens: auto;
|
||||
-ms-hyphens: auto;
|
||||
hyphens: auto;
|
||||
text-transform: none;
|
||||
}
|
||||
.system-modules td details a {
|
||||
color: #5c5c5b;
|
||||
border: 0;
|
||||
}
|
||||
.system-modules td details {
|
||||
border: 0;
|
||||
margin: 0;
|
||||
height: 20px;
|
||||
}
|
||||
.system-modules td details summary {
|
||||
padding: 0;
|
||||
text-transform: none;
|
||||
font-weight: normal;
|
||||
cursor: default;
|
||||
}
|
||||
.system-modules td {
|
||||
padding-left: 0; /* LTR */
|
||||
}
|
||||
[dir="rtl"] .system-modules td {
|
||||
padding-left: 12px;
|
||||
padding-right: 0;
|
||||
}
|
||||
|
||||
@media screen and (max-width: 40em) {
|
||||
.system-modules td.name {
|
||||
width: 20%;
|
||||
}
|
||||
.system-modules td.description {
|
||||
width: 40%;
|
||||
}
|
||||
}
|
||||
.system-modules .requirements {
|
||||
padding: 5px 0;
|
||||
max-width: 490px;
|
||||
}
|
||||
.system-modules .links {
|
||||
overflow: hidden; /* prevents collapse */
|
||||
}
|
||||
.system-modules .checkbox {
|
||||
margin: 0 5px;
|
||||
}
|
||||
.system-modules .checkbox .form-item {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
.admin-requirements,
|
||||
.admin-required {
|
||||
font-size: 0.9em;
|
||||
color: #666;
|
||||
}
|
||||
.admin-enabled {
|
||||
color: #080;
|
||||
}
|
||||
.admin-missing {
|
||||
color: #f00;
|
||||
}
|
||||
.module-link {
|
||||
display: block;
|
||||
padding: 2px 20px;
|
||||
white-space: nowrap;
|
||||
margin-top: 2px;
|
||||
float: left; /* LTR */
|
||||
}
|
||||
[dir="rtl"] .module-link {
|
||||
float: right;
|
||||
}
|
||||
.module-link-help {
|
||||
background: url(../../../misc/icons/787878/questionmark-disc.svg) 0 50% no-repeat; /* LTR */
|
||||
}
|
||||
[dir="rtl"] .module-link-help {
|
||||
background-position: top 50% right 0;
|
||||
}
|
||||
.module-link-permissions {
|
||||
background: url(../../../misc/icons/787878/key.svg) 0 50% no-repeat; /* LTR */
|
||||
}
|
||||
[dir="rtl"] .module-link-permissions {
|
||||
background-position: top 50% right 0;
|
||||
}
|
||||
.module-link-configure {
|
||||
background: url(../../../misc/icons/787878/cog.svg) 0 50% no-repeat; /* LTR */
|
||||
}
|
||||
[dir="rtl"] .module-link-configure {
|
||||
background-position: top 50% right 0;
|
||||
}
|
||||
|
||||
/* Status report. */
|
||||
.system-status-report__status-title {
|
||||
position: relative;
|
||||
vertical-align: top;
|
||||
width: 100%;
|
||||
padding: 10px 6px 10px 40px; /* LTR */
|
||||
box-sizing: border-box;
|
||||
font-weight: normal;
|
||||
background-color: transparent;
|
||||
}
|
||||
[dir="rtl"] .system-status-report__status-title {
|
||||
padding: 10px 40px 10px 6px;
|
||||
}
|
||||
.system-status-report__status-icon:before {
|
||||
content: "";
|
||||
background-repeat: no-repeat;
|
||||
height: 16px;
|
||||
width: 16px;
|
||||
display: block;
|
||||
position: absolute;
|
||||
left: 12px; /* LTR */
|
||||
top: 12px;
|
||||
}
|
||||
[dir="rtl"] .system-status-report__status-icon:before {
|
||||
left: auto;
|
||||
right: 12px;
|
||||
}
|
||||
.system-status-report__status-icon--error:before {
|
||||
background-image: url(../../../misc/icons/e32700/error.svg);
|
||||
}
|
||||
.system-status-report__status-icon--warning:before {
|
||||
background-image: url(../../../misc/icons/e29700/warning.svg);
|
||||
}
|
||||
.system-status-report__entry__value {
|
||||
padding: 1em 0.5em;
|
||||
}
|
||||
|
||||
/**
|
||||
* Appearance page.
|
||||
*/
|
||||
.theme-info__header {
|
||||
margin-bottom: 0;
|
||||
font-weight: normal;
|
||||
}
|
||||
.theme-default .theme-info__header {
|
||||
font-weight: bold;
|
||||
}
|
||||
.theme-info__description {
|
||||
margin-top: 0;
|
||||
}
|
||||
.system-themes-list {
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
.system-themes-list-uninstalled {
|
||||
border-top: 1px solid #cdcdcd;
|
||||
padding-top: 20px;
|
||||
}
|
||||
.system-themes-list__header {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.theme-selector {
|
||||
padding-top: 20px;
|
||||
}
|
||||
.theme-selector .screenshot,
|
||||
.theme-selector .no-screenshot {
|
||||
border: 1px solid #e0e0d8;
|
||||
padding: 2px;
|
||||
vertical-align: bottom;
|
||||
max-width: 100%;
|
||||
height: auto;
|
||||
text-align: center;
|
||||
}
|
||||
.theme-default .screenshot {
|
||||
border: 1px solid #aaa;
|
||||
}
|
||||
.system-themes-list-uninstalled .screenshot,
|
||||
.system-themes-list-uninstalled .no-screenshot {
|
||||
max-width: 194px;
|
||||
height: auto;
|
||||
}
|
||||
|
||||
/**
|
||||
* Theme display without vertical toolbar.
|
||||
*/
|
||||
@media screen and (min-width: 45em) {
|
||||
body:not(.toolbar-vertical) .system-themes-list-installed .screenshot,
|
||||
body:not(.toolbar-vertical) .system-themes-list-installed .no-screenshot {
|
||||
float: left; /* LTR */
|
||||
margin: 0 20px 0 0; /* LTR */
|
||||
width: 294px;
|
||||
}
|
||||
[dir="rtl"] body:not(.toolbar-vertical) .system-themes-list-installed .screenshot,
|
||||
[dir="rtl"] body:not(.toolbar-vertical) .system-themes-list-installed .no-screenshot {
|
||||
float: right;
|
||||
margin: 0 0 0 20px;
|
||||
}
|
||||
body:not(.toolbar-vertical) .system-themes-list-installed .system-themes-list__header {
|
||||
margin-top: 0;
|
||||
}
|
||||
body:not(.toolbar-vertical) .system-themes-list-uninstalled .theme-selector {
|
||||
box-sizing: border-box;
|
||||
width: 31.25%;
|
||||
float: left; /* LTR */
|
||||
padding: 20px 20px 20px 0; /* LTR */
|
||||
}
|
||||
[dir="rtl"] body:not(.toolbar-vertical) .system-themes-list-uninstalled .theme-selector {
|
||||
float: right;
|
||||
padding: 20px 0 20px 20px;
|
||||
}
|
||||
body:not(.toolbar-vertical) .system-themes-list-uninstalled .theme-info {
|
||||
min-height: 170px;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Theme display with vertical toolbar.
|
||||
*/
|
||||
@media screen and (min-width: 60em) {
|
||||
.toolbar-vertical .system-themes-list-installed .screenshot,
|
||||
.toolbar-vertical .system-themes-list-installed .no-screenshot {
|
||||
float: left; /* LTR */
|
||||
margin: 0 20px 0 0; /* LTR */
|
||||
width: 294px;
|
||||
}
|
||||
[dir="rtl"] .toolbar-vertical .system-themes-list-installed .screenshot,
|
||||
[dir="rtl"] .toolbar-vertical .system-themes-list-installed .no-screenshot {
|
||||
float: right;
|
||||
margin: 0 0 0 20px;
|
||||
}
|
||||
.toolbar-vertical .system-themes-list-installed .theme-info__header {
|
||||
margin-top: 0;
|
||||
}
|
||||
.toolbar-vertical .system-themes-list-uninstalled .theme-selector {
|
||||
box-sizing: border-box;
|
||||
width: 31.25%;
|
||||
float: left; /* LTR */
|
||||
padding: 20px 20px 20px 0; /* LTR */
|
||||
}
|
||||
[dir="rtl"] .toolbar-vertical .system-themes-list-uninstalled .theme-selector {
|
||||
float: right;
|
||||
padding: 20px 0 20px 20px;
|
||||
}
|
||||
.toolbar-vertical .system-themes-list-uninstalled .theme-info {
|
||||
min-height: 170px;
|
||||
}
|
||||
}
|
||||
.system-themes-list-installed .theme-info {
|
||||
max-width: 940px;
|
||||
}
|
||||
|
||||
.theme-selector .incompatible {
|
||||
margin-top: 10px;
|
||||
font-weight: bold;
|
||||
}
|
||||
.theme-selector .operations {
|
||||
margin: 10px 0 0 0;
|
||||
padding: 0;
|
||||
}
|
||||
.theme-selector .operations li {
|
||||
float: left; /* LTR */
|
||||
margin: 0;
|
||||
padding: 0 0.7em;
|
||||
list-style-type: none;
|
||||
border-right: 1px solid #cdcdcd; /* LTR */
|
||||
}
|
||||
[dir="rtl"] .theme-selector .operations li {
|
||||
float: right;
|
||||
border-left: 1px solid #cdcdcd;
|
||||
border-right: none;
|
||||
}
|
||||
.theme-selector .operations li:last-child {
|
||||
padding: 0 0 0 0.7em; /* LTR */
|
||||
border-right: none; /* LTR */
|
||||
}
|
||||
[dir="rtl"] .theme-selector .operations li:last-child {
|
||||
padding: 0 0.7em 0 0;
|
||||
border-left: none;
|
||||
}
|
||||
.theme-selector .operations li:first-child {
|
||||
padding: 0 0.7em 0 0; /* LTR */
|
||||
}
|
||||
[dir="rtl"] .theme-selector .operations li:first-child {
|
||||
padding: 0 0 0 0.7em;
|
||||
}
|
||||
.system-themes-admin-form {
|
||||
clear: left; /* LTR */
|
||||
}
|
||||
[dir="rtl"] .system-themes-admin-form {
|
||||
clear: right;
|
||||
}
|
||||
.cron-description__run-cron {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.system-cron-settings__link {
|
||||
overflow-wrap: break-word;
|
||||
word-wrap: break-word;
|
||||
}
|
41
2017/web/core/modules/system/css/system.diff.css
Normal file
41
2017/web/core/modules/system/css/system.diff.css
Normal file
|
@ -0,0 +1,41 @@
|
|||
/**
|
||||
* Traditional split diff theming
|
||||
*/
|
||||
table.diff {
|
||||
border-spacing: 4px;
|
||||
margin-bottom: 20px;
|
||||
width: 100%;
|
||||
}
|
||||
table.diff .diff-context {
|
||||
background-color: #fafafa;
|
||||
}
|
||||
table.diff .diff-deletedline {
|
||||
background-color: #ffa;
|
||||
width: 50%;
|
||||
}
|
||||
table.diff .diff-addedline {
|
||||
background-color: #afa;
|
||||
width: 50%;
|
||||
}
|
||||
table.diff .diffchange {
|
||||
color: #f00;
|
||||
font-weight: bold;
|
||||
}
|
||||
table.diff .diff-marker {
|
||||
width: 1.4em;
|
||||
}
|
||||
table.diff th {
|
||||
padding-right: inherit; /* LTR */
|
||||
}
|
||||
[dir="rtl"] table.diff th {
|
||||
padding-right: 0;
|
||||
padding-left: inherit;
|
||||
}
|
||||
table.diff td div {
|
||||
overflow: auto;
|
||||
padding: 0.1ex 0.5em;
|
||||
word-wrap: break-word;
|
||||
}
|
||||
table.diff td {
|
||||
padding: 0.1ex 0.4em;
|
||||
}
|
56
2017/web/core/modules/system/css/system.maintenance.css
Normal file
56
2017/web/core/modules/system/css/system.maintenance.css
Normal file
|
@ -0,0 +1,56 @@
|
|||
/**
|
||||
* Update styles
|
||||
*/
|
||||
.update-results {
|
||||
margin-top: 3em;
|
||||
padding: 0.25em;
|
||||
border: 1px solid #ccc;
|
||||
background: #eee;
|
||||
font-size: smaller;
|
||||
}
|
||||
.update-results h2 {
|
||||
margin-top: 0.25em;
|
||||
}
|
||||
.update-results h4 {
|
||||
margin-bottom: 0.25em;
|
||||
}
|
||||
.update-results .none {
|
||||
color: #888;
|
||||
font-style: italic;
|
||||
}
|
||||
.update-results .failure strong {
|
||||
color: #b63300;
|
||||
}
|
||||
|
||||
/**
|
||||
* Authorize.php styles
|
||||
*/
|
||||
#edit-submit-connection {
|
||||
clear: both;
|
||||
}
|
||||
#edit-submit-process,
|
||||
.filetransfer {
|
||||
display: none;
|
||||
clear: both;
|
||||
}
|
||||
.js #edit-submit-connection {
|
||||
display: none;
|
||||
}
|
||||
.js #edit-submit-process {
|
||||
display: block;
|
||||
}
|
||||
|
||||
#edit-connection-settings-change-connection-type {
|
||||
margin: 2.6em 0.5em 0 1em; /* LTR */
|
||||
}
|
||||
[dir="rtl"] #edit-connection-settings-change-connection-type {
|
||||
margin-left: 0.5em;
|
||||
margin-right: 1em;
|
||||
}
|
||||
|
||||
/**
|
||||
* Theme maintenance styles
|
||||
*/
|
||||
.authorize-results__failure {
|
||||
font-weight: bold;
|
||||
}
|
BIN
2017/web/core/modules/system/images/no_screenshot.png
Normal file
BIN
2017/web/core/modules/system/images/no_screenshot.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.5 KiB |
62
2017/web/core/modules/system/js/system.date.es6.js
Normal file
62
2017/web/core/modules/system/js/system.date.es6.js
Normal file
|
@ -0,0 +1,62 @@
|
|||
/**
|
||||
* @file
|
||||
* Provides date format preview feature.
|
||||
*/
|
||||
|
||||
(function($, Drupal, drupalSettings) {
|
||||
const dateFormats = drupalSettings.dateFormats;
|
||||
|
||||
/**
|
||||
* Display the preview for date format entered.
|
||||
*
|
||||
* @type {Drupal~behavior}
|
||||
*
|
||||
* @prop {Drupal~behaviorAttach} attach
|
||||
* Attach behavior for previewing date formats on input elements.
|
||||
*/
|
||||
Drupal.behaviors.dateFormat = {
|
||||
attach(context) {
|
||||
const $context = $(context);
|
||||
const $source = $context
|
||||
.find('[data-drupal-date-formatter="source"]')
|
||||
.once('dateFormat');
|
||||
const $target = $context
|
||||
.find('[data-drupal-date-formatter="preview"]')
|
||||
.once('dateFormat');
|
||||
const $preview = $target.find('em');
|
||||
|
||||
// All elements have to exist.
|
||||
if (!$source.length || !$target.length) {
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Event handler that replaces date characters with value.
|
||||
*
|
||||
* @param {jQuery.Event} e
|
||||
* The jQuery event triggered.
|
||||
*/
|
||||
function dateFormatHandler(e) {
|
||||
const baseValue = $(e.target).val() || '';
|
||||
const dateString = baseValue.replace(
|
||||
/\\?(.?)/gi,
|
||||
(key, value) => (dateFormats[key] ? dateFormats[key] : value),
|
||||
);
|
||||
|
||||
$preview.html(dateString);
|
||||
$target.toggleClass('js-hide', !dateString.length);
|
||||
}
|
||||
|
||||
/**
|
||||
* On given event triggers the date character replacement.
|
||||
*/
|
||||
$source
|
||||
.on(
|
||||
'keyup.dateFormat change.dateFormat input.dateFormat',
|
||||
dateFormatHandler,
|
||||
)
|
||||
// Initialize preview.
|
||||
.trigger('keyup');
|
||||
},
|
||||
};
|
||||
})(jQuery, Drupal, drupalSettings);
|
35
2017/web/core/modules/system/js/system.date.js
Normal file
35
2017/web/core/modules/system/js/system.date.js
Normal file
|
@ -0,0 +1,35 @@
|
|||
/**
|
||||
* DO NOT EDIT THIS FILE.
|
||||
* See the following change record for more information,
|
||||
* https://www.drupal.org/node/2815083
|
||||
* @preserve
|
||||
**/
|
||||
|
||||
(function ($, Drupal, drupalSettings) {
|
||||
var dateFormats = drupalSettings.dateFormats;
|
||||
|
||||
Drupal.behaviors.dateFormat = {
|
||||
attach: function attach(context) {
|
||||
var $context = $(context);
|
||||
var $source = $context.find('[data-drupal-date-formatter="source"]').once('dateFormat');
|
||||
var $target = $context.find('[data-drupal-date-formatter="preview"]').once('dateFormat');
|
||||
var $preview = $target.find('em');
|
||||
|
||||
if (!$source.length || !$target.length) {
|
||||
return;
|
||||
}
|
||||
|
||||
function dateFormatHandler(e) {
|
||||
var baseValue = $(e.target).val() || '';
|
||||
var dateString = baseValue.replace(/\\?(.?)/gi, function (key, value) {
|
||||
return dateFormats[key] ? dateFormats[key] : value;
|
||||
});
|
||||
|
||||
$preview.html(dateString);
|
||||
$target.toggleClass('js-hide', !dateString.length);
|
||||
}
|
||||
|
||||
$source.on('keyup.dateFormat change.dateFormat input.dateFormat', dateFormatHandler).trigger('keyup');
|
||||
}
|
||||
};
|
||||
})(jQuery, Drupal, drupalSettings);
|
84
2017/web/core/modules/system/js/system.es6.js
Normal file
84
2017/web/core/modules/system/js/system.es6.js
Normal file
|
@ -0,0 +1,84 @@
|
|||
/**
|
||||
* @file
|
||||
* System behaviors.
|
||||
*/
|
||||
|
||||
(function($, Drupal, drupalSettings) {
|
||||
// Cache IDs in an array for ease of use.
|
||||
const ids = [];
|
||||
|
||||
/**
|
||||
* Attaches field copy behavior from input fields to other input fields.
|
||||
*
|
||||
* When a field is filled out, apply its value to other fields that will
|
||||
* likely use the same value. In the installer this is used to populate the
|
||||
* administrator email address with the same value as the site email address.
|
||||
*
|
||||
* @type {Drupal~behavior}
|
||||
*
|
||||
* @prop {Drupal~behaviorAttach} attach
|
||||
* Attaches the field copy behavior to an input field.
|
||||
*/
|
||||
Drupal.behaviors.copyFieldValue = {
|
||||
attach(context) {
|
||||
// List of fields IDs on which to bind the event listener.
|
||||
// Create an array of IDs to use with jQuery.
|
||||
Object.keys(drupalSettings.copyFieldValue || {}).forEach(element => {
|
||||
ids.push(element);
|
||||
});
|
||||
|
||||
if (ids.length) {
|
||||
// Listen to value:copy events on all dependent fields.
|
||||
// We have to use body and not document because of the way jQuery events
|
||||
// bubble up the DOM tree.
|
||||
$('body')
|
||||
.once('copy-field-values')
|
||||
.on('value:copy', this.valueTargetCopyHandler);
|
||||
// Listen on all source elements.
|
||||
$(`#${ids.join(', #')}`)
|
||||
.once('copy-field-values')
|
||||
.on('blur', this.valueSourceBlurHandler);
|
||||
}
|
||||
},
|
||||
detach(context, settings, trigger) {
|
||||
if (trigger === 'unload' && ids.length) {
|
||||
$('body')
|
||||
.removeOnce('copy-field-values')
|
||||
.off('value:copy');
|
||||
$(`#${ids.join(', #')}`)
|
||||
.removeOnce('copy-field-values')
|
||||
.off('blur');
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Event handler that fill the target element with the specified value.
|
||||
*
|
||||
* @param {jQuery.Event} e
|
||||
* Event object.
|
||||
* @param {string} value
|
||||
* Custom value from jQuery trigger.
|
||||
*/
|
||||
valueTargetCopyHandler(e, value) {
|
||||
const $target = $(e.target);
|
||||
if ($target.val() === '') {
|
||||
$target.val(value);
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Handler for a Blur event on a source field.
|
||||
*
|
||||
* This event handler will trigger a 'value:copy' event on all dependent
|
||||
* fields.
|
||||
*
|
||||
* @param {jQuery.Event} e
|
||||
* The event triggered.
|
||||
*/
|
||||
valueSourceBlurHandler(e) {
|
||||
const value = $(e.target).val();
|
||||
const targetIds = drupalSettings.copyFieldValue[e.target.id];
|
||||
$(`#${targetIds.join(', #')}`).trigger('value:copy', value);
|
||||
},
|
||||
};
|
||||
})(jQuery, Drupal, drupalSettings);
|
41
2017/web/core/modules/system/js/system.js
Normal file
41
2017/web/core/modules/system/js/system.js
Normal file
|
@ -0,0 +1,41 @@
|
|||
/**
|
||||
* DO NOT EDIT THIS FILE.
|
||||
* See the following change record for more information,
|
||||
* https://www.drupal.org/node/2815083
|
||||
* @preserve
|
||||
**/
|
||||
|
||||
(function ($, Drupal, drupalSettings) {
|
||||
var ids = [];
|
||||
|
||||
Drupal.behaviors.copyFieldValue = {
|
||||
attach: function attach(context) {
|
||||
Object.keys(drupalSettings.copyFieldValue || {}).forEach(function (element) {
|
||||
ids.push(element);
|
||||
});
|
||||
|
||||
if (ids.length) {
|
||||
$('body').once('copy-field-values').on('value:copy', this.valueTargetCopyHandler);
|
||||
|
||||
$('#' + ids.join(', #')).once('copy-field-values').on('blur', this.valueSourceBlurHandler);
|
||||
}
|
||||
},
|
||||
detach: function detach(context, settings, trigger) {
|
||||
if (trigger === 'unload' && ids.length) {
|
||||
$('body').removeOnce('copy-field-values').off('value:copy');
|
||||
$('#' + ids.join(', #')).removeOnce('copy-field-values').off('blur');
|
||||
}
|
||||
},
|
||||
valueTargetCopyHandler: function valueTargetCopyHandler(e, value) {
|
||||
var $target = $(e.target);
|
||||
if ($target.val() === '') {
|
||||
$target.val(value);
|
||||
}
|
||||
},
|
||||
valueSourceBlurHandler: function valueSourceBlurHandler(e) {
|
||||
var value = $(e.target).val();
|
||||
var targetIds = drupalSettings.copyFieldValue[e.target.id];
|
||||
$('#' + targetIds.join(', #')).trigger('value:copy', value);
|
||||
}
|
||||
};
|
||||
})(jQuery, Drupal, drupalSettings);
|
102
2017/web/core/modules/system/js/system.modules.es6.js
Normal file
102
2017/web/core/modules/system/js/system.modules.es6.js
Normal file
|
@ -0,0 +1,102 @@
|
|||
/**
|
||||
* @file
|
||||
* Module page behaviors.
|
||||
*/
|
||||
|
||||
(function($, Drupal, debounce) {
|
||||
/**
|
||||
* Filters the module list table by a text input search string.
|
||||
*
|
||||
* Additionally accounts for multiple tables being wrapped in "package" details
|
||||
* elements.
|
||||
*
|
||||
* Text search input: input.table-filter-text
|
||||
* Target table: input.table-filter-text[data-table]
|
||||
* Source text: .table-filter-text-source, .module-name, .module-description
|
||||
*
|
||||
* @type {Drupal~behavior}
|
||||
*/
|
||||
Drupal.behaviors.tableFilterByText = {
|
||||
attach(context, settings) {
|
||||
const $input = $('input.table-filter-text').once('table-filter-text');
|
||||
const $table = $($input.attr('data-table'));
|
||||
let $rowsAndDetails;
|
||||
let $rows;
|
||||
let $details;
|
||||
let searching = false;
|
||||
|
||||
function hidePackageDetails(index, element) {
|
||||
const $packDetails = $(element);
|
||||
const $visibleRows = $packDetails.find('tbody tr:visible');
|
||||
$packDetails.toggle($visibleRows.length > 0);
|
||||
}
|
||||
|
||||
function filterModuleList(e) {
|
||||
const query = $(e.target).val();
|
||||
// Case insensitive expression to find query at the beginning of a word.
|
||||
const re = new RegExp(`\\b${query}`, 'i');
|
||||
|
||||
function showModuleRow(index, row) {
|
||||
const $row = $(row);
|
||||
const $sources = $row.find(
|
||||
'.table-filter-text-source, .module-name, .module-description',
|
||||
);
|
||||
const textMatch = $sources.text().search(re) !== -1;
|
||||
$row.closest('tr').toggle(textMatch);
|
||||
}
|
||||
// Search over all rows and packages.
|
||||
$rowsAndDetails.show();
|
||||
|
||||
// Filter if the length of the query is at least 2 characters.
|
||||
if (query.length >= 2) {
|
||||
searching = true;
|
||||
$rows.each(showModuleRow);
|
||||
|
||||
// Note that we first open all <details> to be able to use ':visible'.
|
||||
// Mark the <details> elements that were closed before filtering, so
|
||||
// they can be reclosed when filtering is removed.
|
||||
$details
|
||||
.not('[open]')
|
||||
.attr('data-drupal-system-state', 'forced-open');
|
||||
|
||||
// Hide the package <details> if they don't have any visible rows.
|
||||
// Note that we first show() all <details> to be able to use ':visible'.
|
||||
$details.attr('open', true).each(hidePackageDetails);
|
||||
|
||||
Drupal.announce(
|
||||
Drupal.t('!modules modules are available in the modified list.', {
|
||||
'!modules': $rowsAndDetails.find('tbody tr:visible').length,
|
||||
}),
|
||||
);
|
||||
} else if (searching) {
|
||||
searching = false;
|
||||
$rowsAndDetails.show();
|
||||
// Return <details> elements that had been closed before filtering
|
||||
// to a closed state.
|
||||
$details
|
||||
.filter('[data-drupal-system-state="forced-open"]')
|
||||
.removeAttr('data-drupal-system-state')
|
||||
.attr('open', false);
|
||||
}
|
||||
}
|
||||
|
||||
function preventEnterKey(event) {
|
||||
if (event.which === 13) {
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
}
|
||||
}
|
||||
|
||||
if ($table.length) {
|
||||
$rowsAndDetails = $table.find('tr, details');
|
||||
$rows = $table.find('tbody tr');
|
||||
$details = $rowsAndDetails.filter('.package-listing');
|
||||
|
||||
$input.on({
|
||||
keyup: debounce(filterModuleList, 200),
|
||||
keydown: preventEnterKey,
|
||||
});
|
||||
}
|
||||
},
|
||||
};
|
||||
})(jQuery, Drupal, Drupal.debounce);
|
76
2017/web/core/modules/system/js/system.modules.js
Normal file
76
2017/web/core/modules/system/js/system.modules.js
Normal file
|
@ -0,0 +1,76 @@
|
|||
/**
|
||||
* DO NOT EDIT THIS FILE.
|
||||
* See the following change record for more information,
|
||||
* https://www.drupal.org/node/2815083
|
||||
* @preserve
|
||||
**/
|
||||
|
||||
(function ($, Drupal, debounce) {
|
||||
Drupal.behaviors.tableFilterByText = {
|
||||
attach: function attach(context, settings) {
|
||||
var $input = $('input.table-filter-text').once('table-filter-text');
|
||||
var $table = $($input.attr('data-table'));
|
||||
var $rowsAndDetails = void 0;
|
||||
var $rows = void 0;
|
||||
var $details = void 0;
|
||||
var searching = false;
|
||||
|
||||
function hidePackageDetails(index, element) {
|
||||
var $packDetails = $(element);
|
||||
var $visibleRows = $packDetails.find('tbody tr:visible');
|
||||
$packDetails.toggle($visibleRows.length > 0);
|
||||
}
|
||||
|
||||
function filterModuleList(e) {
|
||||
var query = $(e.target).val();
|
||||
|
||||
var re = new RegExp('\\b' + query, 'i');
|
||||
|
||||
function showModuleRow(index, row) {
|
||||
var $row = $(row);
|
||||
var $sources = $row.find('.table-filter-text-source, .module-name, .module-description');
|
||||
var textMatch = $sources.text().search(re) !== -1;
|
||||
$row.closest('tr').toggle(textMatch);
|
||||
}
|
||||
|
||||
$rowsAndDetails.show();
|
||||
|
||||
if (query.length >= 2) {
|
||||
searching = true;
|
||||
$rows.each(showModuleRow);
|
||||
|
||||
$details.not('[open]').attr('data-drupal-system-state', 'forced-open');
|
||||
|
||||
$details.attr('open', true).each(hidePackageDetails);
|
||||
|
||||
Drupal.announce(Drupal.t('!modules modules are available in the modified list.', {
|
||||
'!modules': $rowsAndDetails.find('tbody tr:visible').length
|
||||
}));
|
||||
} else if (searching) {
|
||||
searching = false;
|
||||
$rowsAndDetails.show();
|
||||
|
||||
$details.filter('[data-drupal-system-state="forced-open"]').removeAttr('data-drupal-system-state').attr('open', false);
|
||||
}
|
||||
}
|
||||
|
||||
function preventEnterKey(event) {
|
||||
if (event.which === 13) {
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
}
|
||||
}
|
||||
|
||||
if ($table.length) {
|
||||
$rowsAndDetails = $table.find('tr, details');
|
||||
$rows = $table.find('tbody tr');
|
||||
$details = $rowsAndDetails.filter('.package-listing');
|
||||
|
||||
$input.on({
|
||||
keyup: debounce(filterModuleList, 200),
|
||||
keydown: preventEnterKey
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
})(jQuery, Drupal, Drupal.debounce);
|
23
2017/web/core/modules/system/migrations/d6_date_formats.yml
Normal file
23
2017/web/core/modules/system/migrations/d6_date_formats.yml
Normal file
|
@ -0,0 +1,23 @@
|
|||
id: d6_date_formats
|
||||
label: Date format configuration
|
||||
migration_tags:
|
||||
- Drupal 6
|
||||
- Configuration
|
||||
source:
|
||||
plugin: variable_multirow
|
||||
variables:
|
||||
- date_format_long
|
||||
- date_format_medium
|
||||
- date_format_short
|
||||
source_module: system
|
||||
process:
|
||||
id:
|
||||
plugin: static_map
|
||||
source: name
|
||||
map:
|
||||
date_format_long: long
|
||||
date_format_short: short
|
||||
date_format_medium: medium
|
||||
pattern: value
|
||||
destination:
|
||||
plugin: entity:date_format
|
14
2017/web/core/modules/system/migrations/d6_menu.yml
Normal file
14
2017/web/core/modules/system/migrations/d6_menu.yml
Normal file
|
@ -0,0 +1,14 @@
|
|||
# The menu_settings migration is in the menu_ui module.
|
||||
id: d6_menu
|
||||
label: Menus
|
||||
migration_tags:
|
||||
- Drupal 6
|
||||
- Configuration
|
||||
source:
|
||||
plugin: menu
|
||||
process:
|
||||
id: menu_name
|
||||
label: title
|
||||
description: description
|
||||
destination:
|
||||
plugin: entity:menu
|
18
2017/web/core/modules/system/migrations/d6_system_cron.yml
Normal file
18
2017/web/core/modules/system/migrations/d6_system_cron.yml
Normal file
|
@ -0,0 +1,18 @@
|
|||
id: d6_system_cron
|
||||
label: Cron settings
|
||||
migration_tags:
|
||||
- Drupal 6
|
||||
- Configuration
|
||||
source:
|
||||
plugin: variable
|
||||
variables:
|
||||
- cron_threshold_warning
|
||||
- cron_threshold_error
|
||||
- cron_last
|
||||
source_module: system
|
||||
process:
|
||||
'threshold/requirements_warning': cron_threshold_warning
|
||||
'threshold/requirements_error': cron_threshold_error
|
||||
destination:
|
||||
plugin: config
|
||||
config_name: system.cron
|
21
2017/web/core/modules/system/migrations/d6_system_date.yml
Normal file
21
2017/web/core/modules/system/migrations/d6_system_date.yml
Normal file
|
@ -0,0 +1,21 @@
|
|||
id: d6_system_date
|
||||
label: System date configuration
|
||||
migration_tags:
|
||||
- Drupal 6
|
||||
- Configuration
|
||||
source:
|
||||
plugin: variable
|
||||
variables:
|
||||
- configurable_timezones
|
||||
- date_first_day
|
||||
- date_default_timezone
|
||||
source_module: system
|
||||
process:
|
||||
'timezone/user/configurable': configurable_timezones
|
||||
first_day: date_first_day
|
||||
'timezone/default':
|
||||
plugin: timezone
|
||||
source: date_default_timezone
|
||||
destination:
|
||||
plugin: config
|
||||
config_name: system.date
|
22
2017/web/core/modules/system/migrations/d6_system_file.yml
Normal file
22
2017/web/core/modules/system/migrations/d6_system_file.yml
Normal file
|
@ -0,0 +1,22 @@
|
|||
id: d6_system_file
|
||||
label: File system configuration
|
||||
migration_tags:
|
||||
- Drupal 6
|
||||
- Configuration
|
||||
source:
|
||||
plugin: variable
|
||||
variables:
|
||||
- file_directory_temp
|
||||
- allow_insecure_uploads
|
||||
source_module: system
|
||||
process:
|
||||
'path/temporary': file_directory_temp
|
||||
allow_insecure_uploads:
|
||||
plugin: static_map
|
||||
source: allow_insecure_uploads
|
||||
map:
|
||||
0: FALSE
|
||||
1: TRUE
|
||||
destination:
|
||||
plugin: config
|
||||
config_name: system.file
|
|
@ -0,0 +1,21 @@
|
|||
id: d6_system_performance
|
||||
label: Performance configuration
|
||||
migration_tags:
|
||||
- Drupal 6
|
||||
- Configuration
|
||||
source:
|
||||
plugin: variable
|
||||
variables:
|
||||
- preprocess_css
|
||||
- preprocess_js
|
||||
- cache_lifetime
|
||||
- cache
|
||||
- page_compression
|
||||
source_module: system
|
||||
process:
|
||||
'css/preprocess': preprocess_css
|
||||
'js/preprocess': preprocess_js
|
||||
'cache/page/max_age': cache_lifetime
|
||||
destination:
|
||||
plugin: config
|
||||
config_name: system.performance
|
|
@ -0,0 +1,31 @@
|
|||
id: d7_global_theme_settings
|
||||
label: D7 global theme settings
|
||||
migration_tags:
|
||||
- Drupal 7
|
||||
- Configuration
|
||||
source:
|
||||
plugin: variable
|
||||
variables:
|
||||
- theme_settings
|
||||
source_module: system
|
||||
process:
|
||||
'features/logo': theme_settings/toggle_logo
|
||||
'features/name': theme_settings/toggle_name
|
||||
'features/slogan': theme_settings/toggle_slogan
|
||||
'features/node_user_picture': theme_settings/toggle_node_user_picture
|
||||
'features/comment_user_picture': theme_settings/toggle_comment_user_picture
|
||||
'features/comment_user_verification': theme_settings/toggle_comment_user_verification
|
||||
'features/favicon': theme_settings/toggle_favicon
|
||||
'logo/use_default': theme_settings/default_logo
|
||||
'logo/path': theme_settings/logo_path
|
||||
'favicon/use_default': theme_settings/default_favicon
|
||||
'favicon/path': theme_settings/favicon_path
|
||||
'favicon/mimetype': theme_settings/favicon_mimetype
|
||||
# Ignore settings not present in Drupal 8
|
||||
# theme_settings/logo_upload
|
||||
# theme_settings/favicon_upload
|
||||
# theme_settings/toggle_main_menu
|
||||
# theme_settings/toggle_secondary_menu
|
||||
destination:
|
||||
plugin: config
|
||||
config_name: system.theme.global
|
21
2017/web/core/modules/system/migrations/d7_menu.yml
Normal file
21
2017/web/core/modules/system/migrations/d7_menu.yml
Normal file
|
@ -0,0 +1,21 @@
|
|||
id: d7_menu
|
||||
label: Menus
|
||||
migration_tags:
|
||||
- Drupal 7
|
||||
- Configuration
|
||||
source:
|
||||
plugin: menu
|
||||
process:
|
||||
id:
|
||||
plugin: static_map
|
||||
bypass: true
|
||||
source: menu_name
|
||||
map:
|
||||
main-menu: main
|
||||
management: admin
|
||||
navigation: tools
|
||||
user-menu: account
|
||||
label: title
|
||||
description: description
|
||||
destination:
|
||||
plugin: entity:menu
|
|
@ -0,0 +1,15 @@
|
|||
id: d7_system_authorize
|
||||
label: Drupal 7 file transfer authorize configuration
|
||||
migration_tags:
|
||||
- Drupal 7
|
||||
- Configuration
|
||||
source:
|
||||
plugin: variable
|
||||
variables:
|
||||
- authorize_filetransfer_default
|
||||
source_module: system
|
||||
process:
|
||||
filetransfer_default: authorize_filetransfer_default
|
||||
destination:
|
||||
plugin: config
|
||||
config_name: system.authorize
|
17
2017/web/core/modules/system/migrations/d7_system_cron.yml
Normal file
17
2017/web/core/modules/system/migrations/d7_system_cron.yml
Normal file
|
@ -0,0 +1,17 @@
|
|||
id: d7_system_cron
|
||||
label: Drupal 7 cron settings
|
||||
migration_tags:
|
||||
- Drupal 7
|
||||
- Configuration
|
||||
source:
|
||||
plugin: variable
|
||||
variables:
|
||||
- cron_threshold_warning
|
||||
- cron_threshold_error
|
||||
source_module: system
|
||||
process:
|
||||
'threshold/requirements_warning': cron_threshold_warning
|
||||
'threshold/requirements_error': cron_threshold_error
|
||||
destination:
|
||||
plugin: config
|
||||
config_name: system.cron
|
25
2017/web/core/modules/system/migrations/d7_system_date.yml
Normal file
25
2017/web/core/modules/system/migrations/d7_system_date.yml
Normal file
|
@ -0,0 +1,25 @@
|
|||
id: d7_system_date
|
||||
label: Drupal 7 system date configuration
|
||||
migration_tags:
|
||||
- Drupal 7
|
||||
- Configuration
|
||||
source:
|
||||
plugin: variable
|
||||
variables:
|
||||
- site_default_country
|
||||
- date_first_day
|
||||
- date_default_timezone
|
||||
- configurable_timezones
|
||||
- empty_timezone_message
|
||||
- user_default_timezone
|
||||
source_module: system
|
||||
process:
|
||||
'country/default': site_default_country
|
||||
first_day: date_first_day
|
||||
'timezone/default': date_default_timezone
|
||||
'timezone/user/configurable': configurable_timezones
|
||||
'timezone/user/warn': empty_timezone_message
|
||||
'timezone/user/default': user_default_timezone
|
||||
destination:
|
||||
plugin: config
|
||||
config_name: system.date
|
22
2017/web/core/modules/system/migrations/d7_system_file.yml
Normal file
22
2017/web/core/modules/system/migrations/d7_system_file.yml
Normal file
|
@ -0,0 +1,22 @@
|
|||
id: d7_system_file
|
||||
label: Drupal 7 file system configuration
|
||||
migration_tags:
|
||||
- Drupal 7
|
||||
- Configuration
|
||||
source:
|
||||
plugin: variable
|
||||
variables:
|
||||
- allow_insecure_uploads
|
||||
- file_temporary_path
|
||||
source_module: system
|
||||
process:
|
||||
allow_insecure_uploads:
|
||||
plugin: static_map
|
||||
source: allow_insecure_uploads
|
||||
map:
|
||||
0: FALSE
|
||||
1: TRUE
|
||||
'path/temporary': file_temporary_path
|
||||
destination:
|
||||
plugin: config
|
||||
config_name: system.file
|
20
2017/web/core/modules/system/migrations/d7_system_mail.yml
Normal file
20
2017/web/core/modules/system/migrations/d7_system_mail.yml
Normal file
|
@ -0,0 +1,20 @@
|
|||
id: d7_system_mail
|
||||
label: Drupal 7 system mail configuration
|
||||
migration_tags:
|
||||
- Drupal 7
|
||||
- Configuration
|
||||
source:
|
||||
plugin: variable
|
||||
variables:
|
||||
- mail_system
|
||||
source_module: system
|
||||
process:
|
||||
'interface/default':
|
||||
plugin: static_map
|
||||
source: 'mail_system/default-system'
|
||||
map:
|
||||
DefaultMailSystem: php_mail
|
||||
MailTestCase: test_mail_collector
|
||||
destination:
|
||||
plugin: config
|
||||
config_name: system.mail
|
|
@ -0,0 +1,20 @@
|
|||
id: d7_system_performance
|
||||
label: Drupal 7 performance configuration
|
||||
migration_tags:
|
||||
- Drupal 7
|
||||
- Configuration
|
||||
source:
|
||||
plugin: variable
|
||||
variables:
|
||||
- preprocess_css
|
||||
- preprocess_js
|
||||
- cache_lifetime
|
||||
- page_compression
|
||||
source_module: system
|
||||
process:
|
||||
'css/preprocess': preprocess_css
|
||||
'js/preprocess': preprocess_js
|
||||
'cache/page/max_age': cache_lifetime
|
||||
destination:
|
||||
plugin: config
|
||||
config_name: system.performance
|
|
@ -0,0 +1,45 @@
|
|||
id: d7_theme_settings
|
||||
label: D7 theme settings
|
||||
migration_tags:
|
||||
- Drupal 7
|
||||
- Configuration
|
||||
source:
|
||||
plugin: d7_theme_settings
|
||||
constants:
|
||||
config_suffix: '.settings'
|
||||
process:
|
||||
# Build the configuration name from the variable name, i.e.
|
||||
# theme_bartik_settings becomes bartik.settings.
|
||||
theme_name:
|
||||
-
|
||||
plugin: explode
|
||||
source: name
|
||||
delimiter: _
|
||||
-
|
||||
plugin: extract
|
||||
index:
|
||||
- 1
|
||||
configuration_name:
|
||||
plugin: concat
|
||||
source:
|
||||
- '@theme_name'
|
||||
- constants/config_suffix
|
||||
toggle_logo: theme_settings/toggle_logo
|
||||
toggle_name: value/toggle_name
|
||||
toggle_slogan: value/toggle_slogan
|
||||
toggle_node_user_picture: value/toggle_node_user_picture
|
||||
toggle_comment_user_picture: value/toggle_comment_user_picture
|
||||
toggle_comment_user_verification: value/toggle_comment_user_verification
|
||||
toggle_favicon: value/toggle_favicon
|
||||
default_logo: value/default_logo
|
||||
logo_path: value/logo_path
|
||||
logo_upload: value/logo_upload
|
||||
default_favicon: value/default_favicon
|
||||
favicon_path: value/favicon_path
|
||||
favicon_mimetype: value/favicon_mimetype
|
||||
# Ignore settings not present in Drupal 8.
|
||||
# value/favicon_upload
|
||||
# value/toggle_main_menu
|
||||
# value/toggle_secondary_menu
|
||||
destination:
|
||||
plugin: d7_theme_settings
|
16
2017/web/core/modules/system/migrations/system_image.yml
Normal file
16
2017/web/core/modules/system/migrations/system_image.yml
Normal file
|
@ -0,0 +1,16 @@
|
|||
id: system_image
|
||||
label: Image toolkit configuration
|
||||
migration_tags:
|
||||
- Drupal 6
|
||||
- Drupal 7
|
||||
- Configuration
|
||||
source:
|
||||
plugin: variable
|
||||
variables:
|
||||
- image_toolkit
|
||||
source_module: system
|
||||
process:
|
||||
toolkit: image_toolkit
|
||||
destination:
|
||||
plugin: config
|
||||
config_name: system.image
|
16
2017/web/core/modules/system/migrations/system_image_gd.yml
Normal file
16
2017/web/core/modules/system/migrations/system_image_gd.yml
Normal file
|
@ -0,0 +1,16 @@
|
|||
id: system_image_gd
|
||||
label: Image quality configuration
|
||||
migration_tags:
|
||||
- Drupal 6
|
||||
- Drupal 7
|
||||
- Configuration
|
||||
source:
|
||||
plugin: variable
|
||||
variables:
|
||||
- image_jpeg_quality
|
||||
source_module: system
|
||||
process:
|
||||
jpeg_quality: image_jpeg_quality
|
||||
destination:
|
||||
plugin: config
|
||||
config_name: system.image.gd
|
24
2017/web/core/modules/system/migrations/system_logging.yml
Normal file
24
2017/web/core/modules/system/migrations/system_logging.yml
Normal file
|
@ -0,0 +1,24 @@
|
|||
id: system_logging
|
||||
label: System logging
|
||||
migration_tags:
|
||||
- Drupal 6
|
||||
- Drupal 7
|
||||
- Configuration
|
||||
source:
|
||||
plugin: variable
|
||||
variables:
|
||||
- error_level
|
||||
source_module: system
|
||||
process:
|
||||
error_level:
|
||||
plugin: static_map
|
||||
source: error_level
|
||||
default_value: all
|
||||
map:
|
||||
0: hide
|
||||
1: some
|
||||
2: all
|
||||
3: verbose
|
||||
destination:
|
||||
plugin: config
|
||||
config_name: system.logging
|
|
@ -0,0 +1,16 @@
|
|||
id: system_maintenance
|
||||
label: Maintenance page configuration
|
||||
migration_tags:
|
||||
- Drupal 6
|
||||
- Drupal 7
|
||||
- Configuration
|
||||
source:
|
||||
plugin: variable
|
||||
variables:
|
||||
- site_offline_message
|
||||
source_module: system
|
||||
process:
|
||||
message: site_offline_message
|
||||
destination:
|
||||
plugin: config
|
||||
config_name: system.maintenance
|
18
2017/web/core/modules/system/migrations/system_rss.yml
Normal file
18
2017/web/core/modules/system/migrations/system_rss.yml
Normal file
|
@ -0,0 +1,18 @@
|
|||
id: system_rss
|
||||
label: RSS configuration
|
||||
migration_tags:
|
||||
- Drupal 6
|
||||
- Drupal 7
|
||||
- Configuration
|
||||
source:
|
||||
plugin: variable
|
||||
variables:
|
||||
- feed_default_items
|
||||
- feed_item_length
|
||||
source_module: system
|
||||
process:
|
||||
'items/limit': feed_default_items
|
||||
'items/view_mode': feed_item_length
|
||||
destination:
|
||||
plugin: config
|
||||
config_name: system.rss
|
44
2017/web/core/modules/system/migrations/system_site.yml
Normal file
44
2017/web/core/modules/system/migrations/system_site.yml
Normal file
|
@ -0,0 +1,44 @@
|
|||
id: system_site
|
||||
label: Site configuration
|
||||
migration_tags:
|
||||
- Drupal 6
|
||||
- Drupal 7
|
||||
- Configuration
|
||||
source:
|
||||
plugin: variable
|
||||
constants:
|
||||
slash: '/'
|
||||
variables:
|
||||
- site_name
|
||||
- site_mail
|
||||
- site_slogan
|
||||
- site_frontpage
|
||||
- site_403
|
||||
- site_404
|
||||
- drupal_weight_select_max
|
||||
- admin_compact_mode
|
||||
source_module: system
|
||||
process:
|
||||
name: site_name
|
||||
mail: site_mail
|
||||
slogan: site_slogan
|
||||
'page/front':
|
||||
plugin: concat
|
||||
source:
|
||||
- constants/slash
|
||||
- site_frontpage
|
||||
'page/403':
|
||||
plugin: concat
|
||||
source:
|
||||
- constants/slash
|
||||
- site_403
|
||||
'page/404':
|
||||
plugin: concat
|
||||
source:
|
||||
- constants/slash
|
||||
- site_404
|
||||
weight_select_max: drupal_weight_select_max
|
||||
admin_compact_mode: admin_compact_mode
|
||||
destination:
|
||||
plugin: config
|
||||
config_name: system.site
|
34
2017/web/core/modules/system/src/Access/CronAccessCheck.php
Normal file
34
2017/web/core/modules/system/src/Access/CronAccessCheck.php
Normal file
|
@ -0,0 +1,34 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\system\Access;
|
||||
|
||||
use Drupal\Core\Access\AccessResult;
|
||||
use Drupal\Core\Routing\Access\AccessInterface;
|
||||
|
||||
/**
|
||||
* Access check for cron routes.
|
||||
*/
|
||||
class CronAccessCheck implements AccessInterface {
|
||||
|
||||
/**
|
||||
* Checks access.
|
||||
*
|
||||
* @param string $key
|
||||
* The cron key.
|
||||
*
|
||||
* @return \Drupal\Core\Access\AccessResultInterface
|
||||
* The access result.
|
||||
*/
|
||||
public function access($key) {
|
||||
if ($key != \Drupal::state()->get('system.cron_key')) {
|
||||
\Drupal::logger('cron')->notice('Cron could not run because an invalid key was used.');
|
||||
return AccessResult::forbidden()->setCacheMaxAge(0);
|
||||
}
|
||||
elseif (\Drupal::state()->get('system.maintenance_mode')) {
|
||||
\Drupal::logger('cron')->notice('Cron could not run because the site is in maintenance mode.');
|
||||
return AccessResult::forbidden()->setCacheMaxAge(0);
|
||||
}
|
||||
return AccessResult::allowed()->setCacheMaxAge(0);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,38 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\system\Access;
|
||||
|
||||
use Drupal\Core\Routing\Access\AccessInterface;
|
||||
use Drupal\Core\Access\AccessResult;
|
||||
use Drupal\Core\Session\AccountInterface;
|
||||
use Drupal\Core\Site\Settings;
|
||||
|
||||
/**
|
||||
* Access check for database update routes.
|
||||
*/
|
||||
class DbUpdateAccessCheck implements AccessInterface {
|
||||
|
||||
/**
|
||||
* Checks access for update routes.
|
||||
*
|
||||
* @param \Drupal\Core\Session\AccountInterface $account
|
||||
* The currently logged in account.
|
||||
*
|
||||
* @return string
|
||||
* A \Drupal\Core\Access\AccessInterface constant value.
|
||||
*/
|
||||
public function access(AccountInterface $account) {
|
||||
// Allow the global variable in settings.php to override the access check.
|
||||
if (Settings::get('update_free_access')) {
|
||||
return AccessResult::allowed()->setCacheMaxAge(0);
|
||||
}
|
||||
|
||||
if ($account->hasPermission('administer software updates')) {
|
||||
return AccessResult::allowed()->cachePerPermissions();
|
||||
}
|
||||
else {
|
||||
return AccessResult::forbidden()->cachePerPermissions();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,33 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\system;
|
||||
|
||||
use Drupal\Core\Config\Entity\ConfigEntityInterface;
|
||||
|
||||
/**
|
||||
* Provides an interface defining a action entity.
|
||||
*/
|
||||
interface ActionConfigEntityInterface extends ConfigEntityInterface {
|
||||
|
||||
/**
|
||||
* Returns whether or not this action is configurable.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function isConfigurable();
|
||||
|
||||
/**
|
||||
* Returns the operation type.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getType();
|
||||
|
||||
/**
|
||||
* Returns the operation plugin.
|
||||
*
|
||||
* @return \Drupal\Core\Action\ActionInterface
|
||||
*/
|
||||
public function getPlugin();
|
||||
|
||||
}
|
|
@ -0,0 +1,53 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\system\Controller;
|
||||
|
||||
use Drupal\Core\Controller\ControllerBase;
|
||||
|
||||
/**
|
||||
* Controller for admin section.
|
||||
*/
|
||||
class AdminController extends ControllerBase {
|
||||
|
||||
/**
|
||||
* Prints a listing of admin tasks, organized by module.
|
||||
*
|
||||
* @return array
|
||||
* A render array containing the listing.
|
||||
*/
|
||||
public function index() {
|
||||
$module_info = system_get_info('module');
|
||||
foreach ($module_info as $module => $info) {
|
||||
$module_info[$module] = new \stdClass();
|
||||
$module_info[$module]->info = $info;
|
||||
}
|
||||
|
||||
uasort($module_info, 'system_sort_modules_by_info_name');
|
||||
$menu_items = [];
|
||||
|
||||
foreach ($module_info as $module => $info) {
|
||||
// Only display a section if there are any available tasks.
|
||||
if ($admin_tasks = system_get_module_admin_tasks($module, $info->info)) {
|
||||
// Sort links by title.
|
||||
uasort($admin_tasks, ['\Drupal\Component\Utility\SortArray', 'sortByTitleElement']);
|
||||
// Move 'Configure permissions' links to the bottom of each section.
|
||||
$permission_key = "user.admin_permissions.$module";
|
||||
if (isset($admin_tasks[$permission_key])) {
|
||||
$permission_task = $admin_tasks[$permission_key];
|
||||
unset($admin_tasks[$permission_key]);
|
||||
$admin_tasks[$permission_key] = $permission_task;
|
||||
}
|
||||
|
||||
$menu_items[$info->info['name']] = [$info->info['description'], $admin_tasks];
|
||||
}
|
||||
}
|
||||
|
||||
$output = [
|
||||
'#theme' => 'system_admin_index',
|
||||
'#menu_items' => $menu_items,
|
||||
];
|
||||
|
||||
return $output;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,95 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\system\Controller;
|
||||
|
||||
use Drupal\Core\DependencyInjection\ContainerInjectionInterface;
|
||||
use Symfony\Component\DependencyInjection\ContainerInterface;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException;
|
||||
|
||||
/**
|
||||
* Controller routines for batch routes.
|
||||
*/
|
||||
class BatchController implements ContainerInjectionInterface {
|
||||
|
||||
/**
|
||||
* The app root.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $root;
|
||||
|
||||
/**
|
||||
* Constructs a new BatchController.
|
||||
*
|
||||
* @param string $root
|
||||
* The app root.
|
||||
*/
|
||||
public function __construct($root) {
|
||||
$this->root = $root;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static function create(ContainerInterface $container) {
|
||||
return new static(
|
||||
$container->get('app.root')
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a system batch page.
|
||||
*
|
||||
* @param \Symfony\Component\HttpFoundation\Request $request
|
||||
* The current request object.
|
||||
*
|
||||
* @return \Symfony\Component\HttpFoundation\Response|array
|
||||
* A \Symfony\Component\HttpFoundation\Response object or render array.
|
||||
*
|
||||
* @throws \Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException
|
||||
*/
|
||||
public function batchPage(Request $request) {
|
||||
require_once $this->root . '/core/includes/batch.inc';
|
||||
$output = _batch_page($request);
|
||||
|
||||
if ($output === FALSE) {
|
||||
throw new AccessDeniedHttpException();
|
||||
}
|
||||
elseif ($output instanceof Response) {
|
||||
return $output;
|
||||
}
|
||||
elseif (isset($output)) {
|
||||
$title = isset($output['#title']) ? $output['#title'] : NULL;
|
||||
$page = [
|
||||
'#type' => 'page',
|
||||
'#title' => $title,
|
||||
'#show_messages' => FALSE,
|
||||
'content' => $output,
|
||||
];
|
||||
|
||||
// Also inject title as a page header (if available).
|
||||
if ($title) {
|
||||
$page['header'] = [
|
||||
'#type' => 'page_title',
|
||||
'#title' => $title,
|
||||
];
|
||||
}
|
||||
|
||||
return $page;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The _title_callback for the system.batch_page.normal route.
|
||||
*
|
||||
* @return string
|
||||
* The page title.
|
||||
*/
|
||||
public function batchPageTitle() {
|
||||
$current_set = _batch_current_set();
|
||||
return !empty($current_set['title']) ? $current_set['title'] : '';
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,52 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\system\Controller;
|
||||
|
||||
use Drupal\Core\Access\CsrfRequestHeaderAccessCheck;
|
||||
use Drupal\Core\Access\CsrfTokenGenerator;
|
||||
use Drupal\Core\DependencyInjection\ContainerInjectionInterface;
|
||||
use Symfony\Component\DependencyInjection\ContainerInterface;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
|
||||
/**
|
||||
* Returns responses for CSRF token routes.
|
||||
*/
|
||||
class CsrfTokenController implements ContainerInjectionInterface {
|
||||
|
||||
/**
|
||||
* The CSRF token generator.
|
||||
*
|
||||
* @var \Drupal\Core\Access\CsrfTokenGenerator
|
||||
*/
|
||||
protected $tokenGenerator;
|
||||
|
||||
/**
|
||||
* Constructs a new CsrfTokenController object.
|
||||
*
|
||||
* @param \Drupal\Core\Access\CsrfTokenGenerator $token_generator
|
||||
* The CSRF token generator.
|
||||
*/
|
||||
public function __construct(CsrfTokenGenerator $token_generator) {
|
||||
$this->tokenGenerator = $token_generator;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static function create(ContainerInterface $container) {
|
||||
return new static(
|
||||
$container->get('csrf_token')
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a CSRF protecting session token.
|
||||
*
|
||||
* @return \Symfony\Component\HttpFoundation\Response
|
||||
* The response object.
|
||||
*/
|
||||
public function csrfToken() {
|
||||
return new Response($this->tokenGenerator->get(CsrfRequestHeaderAccessCheck::TOKEN_KEY), 200, ['Content-Type' => 'text/plain']);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,705 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\system\Controller;
|
||||
|
||||
use Drupal\Core\Cache\CacheBackendInterface;
|
||||
use Drupal\Core\Controller\ControllerBase;
|
||||
use Drupal\Core\Extension\ModuleHandlerInterface;
|
||||
use Drupal\Core\KeyValueStore\KeyValueExpirableFactoryInterface;
|
||||
use Drupal\Core\Render\BareHtmlPageRendererInterface;
|
||||
use Drupal\Core\Session\AccountInterface;
|
||||
use Drupal\Core\Site\Settings;
|
||||
use Drupal\Core\State\StateInterface;
|
||||
use Drupal\Core\Update\UpdateRegistry;
|
||||
use Drupal\Core\Url;
|
||||
use Symfony\Component\DependencyInjection\ContainerInterface;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
|
||||
/**
|
||||
* Controller routines for database update routes.
|
||||
*/
|
||||
class DbUpdateController extends ControllerBase {
|
||||
|
||||
/**
|
||||
* The keyvalue expirable factory.
|
||||
*
|
||||
* @var \Drupal\Core\KeyValueStore\KeyValueExpirableFactoryInterface
|
||||
*/
|
||||
protected $keyValueExpirableFactory;
|
||||
|
||||
/**
|
||||
* A cache backend interface.
|
||||
*
|
||||
* @var \Drupal\Core\Cache\CacheBackendInterface
|
||||
*/
|
||||
protected $cache;
|
||||
|
||||
/**
|
||||
* The state service.
|
||||
*
|
||||
* @var \Drupal\Core\State\StateInterface
|
||||
*/
|
||||
protected $state;
|
||||
|
||||
/**
|
||||
* The module handler.
|
||||
*
|
||||
* @var \Drupal\Core\Extension\ModuleHandlerInterface
|
||||
*/
|
||||
protected $moduleHandler;
|
||||
|
||||
/**
|
||||
* The current user.
|
||||
*
|
||||
* @var \Drupal\Core\Session\AccountInterface
|
||||
*/
|
||||
protected $account;
|
||||
|
||||
/**
|
||||
* The bare HTML page renderer.
|
||||
*
|
||||
* @var \Drupal\Core\Render\BareHtmlPageRendererInterface
|
||||
*/
|
||||
protected $bareHtmlPageRenderer;
|
||||
|
||||
/**
|
||||
* The app root.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $root;
|
||||
|
||||
/**
|
||||
* The post update registry.
|
||||
*
|
||||
* @var \Drupal\Core\Update\UpdateRegistry
|
||||
*/
|
||||
protected $postUpdateRegistry;
|
||||
|
||||
/**
|
||||
* Constructs a new UpdateController.
|
||||
*
|
||||
* @param string $root
|
||||
* The app root.
|
||||
* @param \Drupal\Core\KeyValueStore\KeyValueExpirableFactoryInterface $key_value_expirable_factory
|
||||
* The keyvalue expirable factory.
|
||||
* @param \Drupal\Core\Cache\CacheBackendInterface $cache
|
||||
* A cache backend interface.
|
||||
* @param \Drupal\Core\State\StateInterface $state
|
||||
* The state service.
|
||||
* @param \Drupal\Core\Extension\ModuleHandlerInterface $module_handler
|
||||
* The module handler.
|
||||
* @param \Drupal\Core\Session\AccountInterface $account
|
||||
* The current user.
|
||||
* @param \Drupal\Core\Render\BareHtmlPageRendererInterface $bare_html_page_renderer
|
||||
* The bare HTML page renderer.
|
||||
* @param \Drupal\Core\Update\UpdateRegistry $post_update_registry
|
||||
* The post update registry.
|
||||
*/
|
||||
public function __construct($root, KeyValueExpirableFactoryInterface $key_value_expirable_factory, CacheBackendInterface $cache, StateInterface $state, ModuleHandlerInterface $module_handler, AccountInterface $account, BareHtmlPageRendererInterface $bare_html_page_renderer, UpdateRegistry $post_update_registry) {
|
||||
$this->root = $root;
|
||||
$this->keyValueExpirableFactory = $key_value_expirable_factory;
|
||||
$this->cache = $cache;
|
||||
$this->state = $state;
|
||||
$this->moduleHandler = $module_handler;
|
||||
$this->account = $account;
|
||||
$this->bareHtmlPageRenderer = $bare_html_page_renderer;
|
||||
$this->postUpdateRegistry = $post_update_registry;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static function create(ContainerInterface $container) {
|
||||
return new static(
|
||||
$container->get('app.root'),
|
||||
$container->get('keyvalue.expirable'),
|
||||
$container->get('cache.default'),
|
||||
$container->get('state'),
|
||||
$container->get('module_handler'),
|
||||
$container->get('current_user'),
|
||||
$container->get('bare_html_page_renderer'),
|
||||
$container->get('update.post_update_registry')
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a database update page.
|
||||
*
|
||||
* @param string $op
|
||||
* The update operation to perform. Can be any of the below:
|
||||
* - info
|
||||
* - selection
|
||||
* - run
|
||||
* - results
|
||||
* @param \Symfony\Component\HttpFoundation\Request $request
|
||||
* The current request object.
|
||||
*
|
||||
* @return \Symfony\Component\HttpFoundation\Response
|
||||
* A response object object.
|
||||
*/
|
||||
public function handle($op, Request $request) {
|
||||
require_once $this->root . '/core/includes/install.inc';
|
||||
require_once $this->root . '/core/includes/update.inc';
|
||||
|
||||
drupal_load_updates();
|
||||
update_fix_compatibility();
|
||||
|
||||
if ($request->query->get('continue')) {
|
||||
$_SESSION['update_ignore_warnings'] = TRUE;
|
||||
}
|
||||
|
||||
$regions = [];
|
||||
$requirements = update_check_requirements();
|
||||
$severity = drupal_requirements_severity($requirements);
|
||||
if ($severity == REQUIREMENT_ERROR || ($severity == REQUIREMENT_WARNING && empty($_SESSION['update_ignore_warnings']))) {
|
||||
$regions['sidebar_first'] = $this->updateTasksList('requirements');
|
||||
$output = $this->requirements($severity, $requirements, $request);
|
||||
}
|
||||
else {
|
||||
switch ($op) {
|
||||
case 'selection':
|
||||
$regions['sidebar_first'] = $this->updateTasksList('selection');
|
||||
$output = $this->selection($request);
|
||||
break;
|
||||
|
||||
case 'run':
|
||||
$regions['sidebar_first'] = $this->updateTasksList('run');
|
||||
$output = $this->triggerBatch($request);
|
||||
break;
|
||||
|
||||
case 'info':
|
||||
$regions['sidebar_first'] = $this->updateTasksList('info');
|
||||
$output = $this->info($request);
|
||||
break;
|
||||
|
||||
case 'results':
|
||||
$regions['sidebar_first'] = $this->updateTasksList('results');
|
||||
$output = $this->results($request);
|
||||
break;
|
||||
|
||||
// Regular batch ops : defer to batch processing API.
|
||||
default:
|
||||
require_once $this->root . '/core/includes/batch.inc';
|
||||
$regions['sidebar_first'] = $this->updateTasksList('run');
|
||||
$output = _batch_page($request);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ($output instanceof Response) {
|
||||
return $output;
|
||||
}
|
||||
$title = isset($output['#title']) ? $output['#title'] : $this->t('Drupal database update');
|
||||
|
||||
return $this->bareHtmlPageRenderer->renderBarePage($output, $title, 'maintenance_page', $regions);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the info database update page.
|
||||
*
|
||||
* @param \Symfony\Component\HttpFoundation\Request $request
|
||||
* The current request.
|
||||
*
|
||||
* @return array
|
||||
* A render array.
|
||||
*/
|
||||
protected function info(Request $request) {
|
||||
// Change query-strings on css/js files to enforce reload for all users.
|
||||
_drupal_flush_css_js();
|
||||
// Flush the cache of all data for the update status module.
|
||||
$this->keyValueExpirableFactory->get('update')->deleteAll();
|
||||
$this->keyValueExpirableFactory->get('update_available_release')->deleteAll();
|
||||
|
||||
$build['info_header'] = [
|
||||
'#markup' => '<p>' . $this->t('Use this utility to update your database whenever a new release of Drupal or a module is installed.') . '</p><p>' . $this->t('For more detailed information, see the <a href="https://www.drupal.org/upgrade">upgrading handbook</a>. If you are unsure what these terms mean you should probably contact your hosting provider.') . '</p>',
|
||||
];
|
||||
|
||||
$info[] = $this->t("<strong>Back up your code</strong>. Hint: when backing up module code, do not leave that backup in the 'modules' or 'sites/*/modules' directories as this may confuse Drupal's auto-discovery mechanism.");
|
||||
$info[] = $this->t('Put your site into <a href=":url">maintenance mode</a>.', [
|
||||
':url' => Url::fromRoute('system.site_maintenance_mode')->toString(TRUE)->getGeneratedUrl(),
|
||||
]);
|
||||
$info[] = $this->t('<strong>Back up your database</strong>. This process will change your database values and in case of emergency you may need to revert to a backup.');
|
||||
$info[] = $this->t('Install your new files in the appropriate location, as described in the handbook.');
|
||||
$build['info'] = [
|
||||
'#theme' => 'item_list',
|
||||
'#list_type' => 'ol',
|
||||
'#items' => $info,
|
||||
];
|
||||
$build['info_footer'] = [
|
||||
'#markup' => '<p>' . $this->t('When you have performed the steps above, you may proceed.') . '</p>',
|
||||
];
|
||||
|
||||
$build['link'] = [
|
||||
'#type' => 'link',
|
||||
'#title' => $this->t('Continue'),
|
||||
'#attributes' => ['class' => ['button', 'button--primary']],
|
||||
// @todo Revisit once https://www.drupal.org/node/2548095 is in.
|
||||
'#url' => Url::fromUri('base://selection'),
|
||||
];
|
||||
return $build;
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders a list of available database updates.
|
||||
*
|
||||
* @param \Symfony\Component\HttpFoundation\Request $request
|
||||
* The current request.
|
||||
*
|
||||
* @return array
|
||||
* A render array.
|
||||
*/
|
||||
protected function selection(Request $request) {
|
||||
// Make sure there is no stale theme registry.
|
||||
$this->cache->deleteAll();
|
||||
|
||||
$count = 0;
|
||||
$incompatible_count = 0;
|
||||
$build['start'] = [
|
||||
'#tree' => TRUE,
|
||||
'#type' => 'details',
|
||||
];
|
||||
|
||||
// Ensure system.module's updates appear first.
|
||||
$build['start']['system'] = [];
|
||||
|
||||
$starting_updates = [];
|
||||
$incompatible_updates_exist = FALSE;
|
||||
$updates_per_module = [];
|
||||
foreach (['update', 'post_update'] as $update_type) {
|
||||
switch ($update_type) {
|
||||
case 'update':
|
||||
$updates = update_get_update_list();
|
||||
break;
|
||||
case 'post_update':
|
||||
$updates = $this->postUpdateRegistry->getPendingUpdateInformation();
|
||||
break;
|
||||
}
|
||||
foreach ($updates as $module => $update) {
|
||||
if (!isset($update['start'])) {
|
||||
$build['start'][$module] = [
|
||||
'#type' => 'item',
|
||||
'#title' => $module . ' module',
|
||||
'#markup' => $update['warning'],
|
||||
'#prefix' => '<div class="messages messages--warning">',
|
||||
'#suffix' => '</div>',
|
||||
];
|
||||
$incompatible_updates_exist = TRUE;
|
||||
continue;
|
||||
}
|
||||
if (!empty($update['pending'])) {
|
||||
$updates_per_module += [$module => []];
|
||||
$updates_per_module[$module] = array_merge($updates_per_module[$module], $update['pending']);
|
||||
$build['start'][$module] = [
|
||||
'#type' => 'hidden',
|
||||
'#value' => $update['start'],
|
||||
];
|
||||
// Store the previous items in order to merge normal updates and
|
||||
// post_update functions together.
|
||||
$build['start'][$module] = [
|
||||
'#theme' => 'item_list',
|
||||
'#items' => $updates_per_module[$module],
|
||||
'#title' => $module . ' module',
|
||||
];
|
||||
|
||||
if ($update_type === 'update') {
|
||||
$starting_updates[$module] = $update['start'];
|
||||
}
|
||||
}
|
||||
if (isset($update['pending'])) {
|
||||
$count = $count + count($update['pending']);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Find and label any incompatible updates.
|
||||
foreach (update_resolve_dependencies($starting_updates) as $data) {
|
||||
if (!$data['allowed']) {
|
||||
$incompatible_updates_exist = TRUE;
|
||||
$incompatible_count++;
|
||||
$module_update_key = $data['module'] . '_updates';
|
||||
if (isset($build['start'][$module_update_key]['#items'][$data['number']])) {
|
||||
if ($data['missing_dependencies']) {
|
||||
$text = $this->t('This update will been skipped due to the following missing dependencies:') . '<em>' . implode(', ', $data['missing_dependencies']) . '</em>';
|
||||
}
|
||||
else {
|
||||
$text = $this->t("This update will be skipped due to an error in the module's code.");
|
||||
}
|
||||
$build['start'][$module_update_key]['#items'][$data['number']] .= '<div class="warning">' . $text . '</div>';
|
||||
}
|
||||
// Move the module containing this update to the top of the list.
|
||||
$build['start'] = [$module_update_key => $build['start'][$module_update_key]] + $build['start'];
|
||||
}
|
||||
}
|
||||
|
||||
// Warn the user if any updates were incompatible.
|
||||
if ($incompatible_updates_exist) {
|
||||
$this->messenger()->addWarning($this->t('Some of the pending updates cannot be applied because their dependencies were not met.'));
|
||||
}
|
||||
|
||||
if (empty($count)) {
|
||||
$this->messenger()->addStatus($this->t('No pending updates.'));
|
||||
unset($build);
|
||||
$build['links'] = [
|
||||
'#theme' => 'links',
|
||||
'#links' => $this->helpfulLinks($request),
|
||||
];
|
||||
|
||||
// No updates to run, so caches won't get flushed later. Clear them now.
|
||||
drupal_flush_all_caches();
|
||||
}
|
||||
else {
|
||||
$build['help'] = [
|
||||
'#markup' => '<p>' . $this->t('The version of Drupal you are updating from has been automatically detected.') . '</p>',
|
||||
'#weight' => -5,
|
||||
];
|
||||
if ($incompatible_count) {
|
||||
$build['start']['#title'] = $this->formatPlural(
|
||||
$count,
|
||||
'1 pending update (@number_applied to be applied, @number_incompatible skipped)',
|
||||
'@count pending updates (@number_applied to be applied, @number_incompatible skipped)',
|
||||
['@number_applied' => $count - $incompatible_count, '@number_incompatible' => $incompatible_count]
|
||||
);
|
||||
}
|
||||
else {
|
||||
$build['start']['#title'] = $this->formatPlural($count, '1 pending update', '@count pending updates');
|
||||
}
|
||||
// @todo Simplify with https://www.drupal.org/node/2548095
|
||||
$base_url = str_replace('/update.php', '', $request->getBaseUrl());
|
||||
$url = (new Url('system.db_update', ['op' => 'run']))->setOption('base_url', $base_url);
|
||||
$build['link'] = [
|
||||
'#type' => 'link',
|
||||
'#title' => $this->t('Apply pending updates'),
|
||||
'#attributes' => ['class' => ['button', 'button--primary']],
|
||||
'#weight' => 5,
|
||||
'#url' => $url,
|
||||
'#access' => $url->access($this->currentUser()),
|
||||
];
|
||||
}
|
||||
|
||||
return $build;
|
||||
}
|
||||
|
||||
/**
|
||||
* Displays results of the update script with any accompanying errors.
|
||||
*
|
||||
* @param \Symfony\Component\HttpFoundation\Request $request
|
||||
* The current request.
|
||||
*
|
||||
* @return array
|
||||
* A render array.
|
||||
*/
|
||||
protected function results(Request $request) {
|
||||
// @todo Simplify with https://www.drupal.org/node/2548095
|
||||
$base_url = str_replace('/update.php', '', $request->getBaseUrl());
|
||||
|
||||
// Report end result.
|
||||
$dblog_exists = $this->moduleHandler->moduleExists('dblog');
|
||||
if ($dblog_exists && $this->account->hasPermission('access site reports')) {
|
||||
$log_message = $this->t('All errors have been <a href=":url">logged</a>.', [
|
||||
':url' => Url::fromRoute('dblog.overview')->setOption('base_url', $base_url)->toString(TRUE)->getGeneratedUrl(),
|
||||
]);
|
||||
}
|
||||
else {
|
||||
$log_message = $this->t('All errors have been logged.');
|
||||
}
|
||||
|
||||
if (!empty($_SESSION['update_success'])) {
|
||||
$message = '<p>' . $this->t('Updates were attempted. If you see no failures below, you may proceed happily back to your <a href=":url">site</a>. Otherwise, you may need to update your database manually.', [':url' => Url::fromRoute('<front>')->setOption('base_url', $base_url)->toString(TRUE)->getGeneratedUrl()]) . ' ' . $log_message . '</p>';
|
||||
}
|
||||
else {
|
||||
$last = reset($_SESSION['updates_remaining']);
|
||||
list($module, $version) = array_pop($last);
|
||||
$message = '<p class="error">' . $this->t('The update process was aborted prematurely while running <strong>update #@version in @module.module</strong>.', [
|
||||
'@version' => $version,
|
||||
'@module' => $module,
|
||||
]) . ' ' . $log_message;
|
||||
if ($dblog_exists) {
|
||||
$message .= ' ' . $this->t('You may need to check the <code>watchdog</code> database table manually.');
|
||||
}
|
||||
$message .= '</p>';
|
||||
}
|
||||
|
||||
if (Settings::get('update_free_access')) {
|
||||
$message .= '<p>' . $this->t("<strong>Reminder: don't forget to set the <code>\$settings['update_free_access']</code> value in your <code>settings.php</code> file back to <code>FALSE</code>.</strong>") . '</p>';
|
||||
}
|
||||
|
||||
$build['message'] = [
|
||||
'#markup' => $message,
|
||||
];
|
||||
$build['links'] = [
|
||||
'#theme' => 'links',
|
||||
'#links' => $this->helpfulLinks($request),
|
||||
];
|
||||
|
||||
// Output a list of info messages.
|
||||
if (!empty($_SESSION['update_results'])) {
|
||||
$all_messages = [];
|
||||
foreach ($_SESSION['update_results'] as $module => $updates) {
|
||||
if ($module != '#abort') {
|
||||
$module_has_message = FALSE;
|
||||
$info_messages = [];
|
||||
foreach ($updates as $name => $queries) {
|
||||
$messages = [];
|
||||
foreach ($queries as $query) {
|
||||
// If there is no message for this update, don't show anything.
|
||||
if (empty($query['query'])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($query['success']) {
|
||||
$messages[] = [
|
||||
'#wrapper_attributes' => ['class' => ['success']],
|
||||
'#markup' => $query['query'],
|
||||
];
|
||||
}
|
||||
else {
|
||||
$messages[] = [
|
||||
'#wrapper_attributes' => ['class' => ['failure']],
|
||||
'#markup' => '<strong>' . $this->t('Failed:') . '</strong> ' . $query['query'],
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
if ($messages) {
|
||||
$module_has_message = TRUE;
|
||||
if (is_numeric($name)) {
|
||||
$title = $this->t('Update #@count', ['@count' => $name]);
|
||||
}
|
||||
else {
|
||||
$title = $this->t('Update @name', ['@name' => trim($name, '_')]);
|
||||
}
|
||||
$info_messages[] = [
|
||||
'#theme' => 'item_list',
|
||||
'#items' => $messages,
|
||||
'#title' => $title,
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
// If there were any messages then prefix them with the module name
|
||||
// and add it to the global message list.
|
||||
if ($module_has_message) {
|
||||
$all_messages[] = [
|
||||
'#type' => 'container',
|
||||
'#prefix' => '<h3>' . $this->t('@module module', ['@module' => $module]) . '</h3>',
|
||||
'#children' => $info_messages,
|
||||
];
|
||||
}
|
||||
}
|
||||
}
|
||||
if ($all_messages) {
|
||||
$build['query_messages'] = [
|
||||
'#type' => 'container',
|
||||
'#children' => $all_messages,
|
||||
'#attributes' => ['class' => ['update-results']],
|
||||
'#prefix' => '<h2>' . $this->t('The following updates returned messages:') . '</h2>',
|
||||
];
|
||||
}
|
||||
}
|
||||
unset($_SESSION['update_results']);
|
||||
unset($_SESSION['update_success']);
|
||||
unset($_SESSION['update_ignore_warnings']);
|
||||
|
||||
return $build;
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders a list of requirement errors or warnings.
|
||||
*
|
||||
* @param \Symfony\Component\HttpFoundation\Request $request
|
||||
* The current request.
|
||||
*
|
||||
* @return array
|
||||
* A render array.
|
||||
*/
|
||||
public function requirements($severity, array $requirements, Request $request) {
|
||||
$options = $severity == REQUIREMENT_WARNING ? ['continue' => 1] : [];
|
||||
// @todo Revisit once https://www.drupal.org/node/2548095 is in. Something
|
||||
// like Url::fromRoute('system.db_update')->setOptions() should then be
|
||||
// possible.
|
||||
$try_again_url = Url::fromUri($request->getUriForPath(''))->setOptions(['query' => $options])->toString(TRUE)->getGeneratedUrl();
|
||||
|
||||
$build['status_report'] = [
|
||||
'#type' => 'status_report',
|
||||
'#requirements' => $requirements,
|
||||
'#suffix' => $this->t('Check the messages and <a href=":url">try again</a>.', [':url' => $try_again_url]),
|
||||
];
|
||||
|
||||
$build['#title'] = $this->t('Requirements problem');
|
||||
return $build;
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides the update task list render array.
|
||||
*
|
||||
* @param string $active
|
||||
* The active task.
|
||||
* Can be one of 'requirements', 'info', 'selection', 'run', 'results'.
|
||||
*
|
||||
* @return array
|
||||
* A render array.
|
||||
*/
|
||||
protected function updateTasksList($active = NULL) {
|
||||
// Default list of tasks.
|
||||
$tasks = [
|
||||
'requirements' => $this->t('Verify requirements'),
|
||||
'info' => $this->t('Overview'),
|
||||
'selection' => $this->t('Review updates'),
|
||||
'run' => $this->t('Run updates'),
|
||||
'results' => $this->t('Review log'),
|
||||
];
|
||||
|
||||
$task_list = [
|
||||
'#theme' => 'maintenance_task_list',
|
||||
'#items' => $tasks,
|
||||
'#active' => $active,
|
||||
];
|
||||
return $task_list;
|
||||
}
|
||||
|
||||
/**
|
||||
* Starts the database update batch process.
|
||||
*
|
||||
* @param \Symfony\Component\HttpFoundation\Request $request
|
||||
* The current request object.
|
||||
*/
|
||||
protected function triggerBatch(Request $request) {
|
||||
$maintenance_mode = $this->state->get('system.maintenance_mode', FALSE);
|
||||
// Store the current maintenance mode status in the session so that it can
|
||||
// be restored at the end of the batch.
|
||||
$_SESSION['maintenance_mode'] = $maintenance_mode;
|
||||
// During the update, always put the site into maintenance mode so that
|
||||
// in-progress schema changes do not affect visiting users.
|
||||
if (empty($maintenance_mode)) {
|
||||
$this->state->set('system.maintenance_mode', TRUE);
|
||||
}
|
||||
|
||||
$operations = [];
|
||||
|
||||
// Resolve any update dependencies to determine the actual updates that will
|
||||
// be run and the order they will be run in.
|
||||
$start = $this->getModuleUpdates();
|
||||
$updates = update_resolve_dependencies($start);
|
||||
|
||||
// Store the dependencies for each update function in an array which the
|
||||
// batch API can pass in to the batch operation each time it is called. (We
|
||||
// do not store the entire update dependency array here because it is
|
||||
// potentially very large.)
|
||||
$dependency_map = [];
|
||||
foreach ($updates as $function => $update) {
|
||||
$dependency_map[$function] = !empty($update['reverse_paths']) ? array_keys($update['reverse_paths']) : [];
|
||||
}
|
||||
|
||||
// Determine updates to be performed.
|
||||
foreach ($updates as $function => $update) {
|
||||
if ($update['allowed']) {
|
||||
// Set the installed version of each module so updates will start at the
|
||||
// correct place. (The updates are already sorted, so we can simply base
|
||||
// this on the first one we come across in the above foreach loop.)
|
||||
if (isset($start[$update['module']])) {
|
||||
drupal_set_installed_schema_version($update['module'], $update['number'] - 1);
|
||||
unset($start[$update['module']]);
|
||||
}
|
||||
$operations[] = ['update_do_one', [$update['module'], $update['number'], $dependency_map[$function]]];
|
||||
}
|
||||
}
|
||||
|
||||
$post_updates = $this->postUpdateRegistry->getPendingUpdateFunctions();
|
||||
|
||||
if ($post_updates) {
|
||||
// Now we rebuild all caches and after that execute the hook_post_update()
|
||||
// functions.
|
||||
$operations[] = ['drupal_flush_all_caches', []];
|
||||
foreach ($post_updates as $function) {
|
||||
$operations[] = ['update_invoke_post_update', [$function]];
|
||||
}
|
||||
}
|
||||
|
||||
$batch['operations'] = $operations;
|
||||
$batch += [
|
||||
'title' => $this->t('Updating'),
|
||||
'init_message' => $this->t('Starting updates'),
|
||||
'error_message' => $this->t('An unrecoverable error has occurred. You can find the error message below. It is advised to copy it to the clipboard for reference.'),
|
||||
'finished' => ['\Drupal\system\Controller\DbUpdateController', 'batchFinished'],
|
||||
];
|
||||
batch_set($batch);
|
||||
|
||||
// @todo Revisit once https://www.drupal.org/node/2548095 is in.
|
||||
return batch_process(Url::fromUri('base://results'), Url::fromUri('base://start'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Finishes the update process and stores the results for eventual display.
|
||||
*
|
||||
* After the updates run, all caches are flushed. The update results are
|
||||
* stored into the session (for example, to be displayed on the update results
|
||||
* page in update.php). Additionally, if the site was off-line, now that the
|
||||
* update process is completed, the site is set back online.
|
||||
*
|
||||
* @param $success
|
||||
* Indicate that the batch API tasks were all completed successfully.
|
||||
* @param array $results
|
||||
* An array of all the results that were updated in update_do_one().
|
||||
* @param array $operations
|
||||
* A list of all the operations that had not been completed by the batch API.
|
||||
*/
|
||||
public static function batchFinished($success, $results, $operations) {
|
||||
// No updates to run, so caches won't get flushed later. Clear them now.
|
||||
drupal_flush_all_caches();
|
||||
|
||||
$_SESSION['update_results'] = $results;
|
||||
$_SESSION['update_success'] = $success;
|
||||
$_SESSION['updates_remaining'] = $operations;
|
||||
|
||||
// Now that the update is done, we can put the site back online if it was
|
||||
// previously not in maintenance mode.
|
||||
if (empty($_SESSION['maintenance_mode'])) {
|
||||
\Drupal::state()->set('system.maintenance_mode', FALSE);
|
||||
}
|
||||
unset($_SESSION['maintenance_mode']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides links to the homepage and administration pages.
|
||||
*
|
||||
* @param \Symfony\Component\HttpFoundation\Request $request
|
||||
* The current request.
|
||||
*
|
||||
* @return array
|
||||
* An array of links.
|
||||
*/
|
||||
protected function helpfulLinks(Request $request) {
|
||||
// @todo Simplify with https://www.drupal.org/node/2548095
|
||||
$base_url = str_replace('/update.php', '', $request->getBaseUrl());
|
||||
$links['front'] = [
|
||||
'title' => $this->t('Front page'),
|
||||
'url' => Url::fromRoute('<front>')->setOption('base_url', $base_url),
|
||||
];
|
||||
if ($this->account->hasPermission('access administration pages')) {
|
||||
$links['admin-pages'] = [
|
||||
'title' => $this->t('Administration pages'),
|
||||
'url' => Url::fromRoute('system.admin')->setOption('base_url', $base_url),
|
||||
];
|
||||
}
|
||||
return $links;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves module updates.
|
||||
*
|
||||
* @return array
|
||||
* The module updates that can be performed.
|
||||
*/
|
||||
protected function getModuleUpdates() {
|
||||
$return = [];
|
||||
$updates = update_get_update_list();
|
||||
foreach ($updates as $module => $update) {
|
||||
$return[$module] = $update['start'];
|
||||
}
|
||||
|
||||
return $return;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,108 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\system\Controller;
|
||||
|
||||
use Drupal\Component\Utility\Crypt;
|
||||
use Drupal\Component\Utility\Tags;
|
||||
use Drupal\Core\Controller\ControllerBase;
|
||||
use Drupal\Core\Entity\EntityAutocompleteMatcher;
|
||||
use Drupal\Core\KeyValueStore\KeyValueStoreInterface;
|
||||
use Drupal\Core\Site\Settings;
|
||||
use Symfony\Component\DependencyInjection\ContainerInterface;
|
||||
use Symfony\Component\HttpFoundation\JsonResponse;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException;
|
||||
|
||||
/**
|
||||
* Defines a route controller for entity autocomplete form elements.
|
||||
*/
|
||||
class EntityAutocompleteController extends ControllerBase {
|
||||
|
||||
/**
|
||||
* The autocomplete matcher for entity references.
|
||||
*
|
||||
* @var \Drupal\Core\Entity\EntityAutocompleteMatcher
|
||||
*/
|
||||
protected $matcher;
|
||||
|
||||
/**
|
||||
* The key value store.
|
||||
*
|
||||
* @var \Drupal\Core\KeyValueStore\KeyValueStoreInterface
|
||||
*/
|
||||
protected $keyValue;
|
||||
|
||||
/**
|
||||
* Constructs a EntityAutocompleteController object.
|
||||
*
|
||||
* @param \Drupal\Core\Entity\EntityAutocompleteMatcher $matcher
|
||||
* The autocomplete matcher for entity references.
|
||||
* @param \Drupal\Core\KeyValueStore\KeyValueStoreInterface $key_value
|
||||
* The key value factory.
|
||||
*/
|
||||
public function __construct(EntityAutocompleteMatcher $matcher, KeyValueStoreInterface $key_value) {
|
||||
$this->matcher = $matcher;
|
||||
$this->keyValue = $key_value;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static function create(ContainerInterface $container) {
|
||||
return new static(
|
||||
$container->get('entity.autocomplete_matcher'),
|
||||
$container->get('keyvalue')->get('entity_autocomplete')
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Autocomplete the label of an entity.
|
||||
*
|
||||
* @param \Symfony\Component\HttpFoundation\Request $request
|
||||
* The request object that contains the typed tags.
|
||||
* @param string $target_type
|
||||
* The ID of the target entity type.
|
||||
* @param string $selection_handler
|
||||
* The plugin ID of the entity reference selection handler.
|
||||
* @param string $selection_settings_key
|
||||
* The hashed key of the key/value entry that holds the selection handler
|
||||
* settings.
|
||||
*
|
||||
* @return \Symfony\Component\HttpFoundation\JsonResponse
|
||||
* The matched entity labels as a JSON response.
|
||||
*
|
||||
* @throws \Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException
|
||||
* Thrown if the selection settings key is not found in the key/value store
|
||||
* or if it does not match the stored data.
|
||||
*/
|
||||
public function handleAutocomplete(Request $request, $target_type, $selection_handler, $selection_settings_key) {
|
||||
$matches = [];
|
||||
// Get the typed string from the URL, if it exists.
|
||||
if ($input = $request->query->get('q')) {
|
||||
$typed_string = Tags::explode($input);
|
||||
$typed_string = mb_strtolower(array_pop($typed_string));
|
||||
|
||||
// Selection settings are passed in as a hashed key of a serialized array
|
||||
// stored in the key/value store.
|
||||
$selection_settings = $this->keyValue->get($selection_settings_key, FALSE);
|
||||
if ($selection_settings !== FALSE) {
|
||||
$selection_settings_hash = Crypt::hmacBase64(serialize($selection_settings) . $target_type . $selection_handler, Settings::getHashSalt());
|
||||
if ($selection_settings_hash !== $selection_settings_key) {
|
||||
// Disallow access when the selection settings hash does not match the
|
||||
// passed-in key.
|
||||
throw new AccessDeniedHttpException('Invalid selection settings key.');
|
||||
}
|
||||
}
|
||||
else {
|
||||
// Disallow access when the selection settings key is not found in the
|
||||
// key/value store.
|
||||
throw new AccessDeniedHttpException();
|
||||
}
|
||||
|
||||
$matches = $this->matcher->getMatches($target_type, $selection_handler, $selection_settings, $typed_string);
|
||||
}
|
||||
|
||||
return new JsonResponse($matches);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,60 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\system\Controller;
|
||||
|
||||
use Drupal\Core\Controller\ControllerBase;
|
||||
|
||||
/**
|
||||
* Controller for default HTTP 4xx responses.
|
||||
*/
|
||||
class Http4xxController extends ControllerBase {
|
||||
|
||||
/**
|
||||
* The default 4xx error content.
|
||||
*
|
||||
* @return array
|
||||
* A render array containing the message to display for 4xx errors.
|
||||
*/
|
||||
public function on4xx() {
|
||||
return [
|
||||
'#markup' => $this->t('A client error happened'),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* The default 401 content.
|
||||
*
|
||||
* @return array
|
||||
* A render array containing the message to display for 401 pages.
|
||||
*/
|
||||
public function on401() {
|
||||
return [
|
||||
'#markup' => $this->t('Please log in to access this page.'),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* The default 403 content.
|
||||
*
|
||||
* @return array
|
||||
* A render array containing the message to display for 403 pages.
|
||||
*/
|
||||
public function on403() {
|
||||
return [
|
||||
'#markup' => $this->t('You are not authorized to access this page.'),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* The default 404 content.
|
||||
*
|
||||
* @return array
|
||||
* A render array containing the message to display for 404 pages.
|
||||
*/
|
||||
public function on404() {
|
||||
return [
|
||||
'#markup' => $this->t('The requested page could not be found.'),
|
||||
];
|
||||
}
|
||||
|
||||
}
|
327
2017/web/core/modules/system/src/Controller/SystemController.php
Normal file
327
2017/web/core/modules/system/src/Controller/SystemController.php
Normal file
|
@ -0,0 +1,327 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\system\Controller;
|
||||
|
||||
use Drupal\Core\Cache\CacheableMetadata;
|
||||
use Drupal\Core\Controller\ControllerBase;
|
||||
use Drupal\Core\Extension\ThemeHandlerInterface;
|
||||
use Drupal\Core\Form\FormBuilderInterface;
|
||||
use Drupal\Core\Menu\MenuLinkTreeInterface;
|
||||
use Drupal\Core\Menu\MenuTreeParameters;
|
||||
use Drupal\Core\Theme\ThemeAccessCheck;
|
||||
use Drupal\Core\Url;
|
||||
use Drupal\system\SystemManager;
|
||||
use Symfony\Component\DependencyInjection\ContainerInterface;
|
||||
|
||||
/**
|
||||
* Returns responses for System routes.
|
||||
*/
|
||||
class SystemController extends ControllerBase {
|
||||
|
||||
/**
|
||||
* System Manager Service.
|
||||
*
|
||||
* @var \Drupal\system\SystemManager
|
||||
*/
|
||||
protected $systemManager;
|
||||
|
||||
/**
|
||||
* The theme access checker service.
|
||||
*
|
||||
* @var \Drupal\Core\Theme\ThemeAccessCheck
|
||||
*/
|
||||
protected $themeAccess;
|
||||
|
||||
/**
|
||||
* The form builder service.
|
||||
*
|
||||
* @var \Drupal\Core\Form\FormBuilderInterface
|
||||
*/
|
||||
protected $formBuilder;
|
||||
|
||||
/**
|
||||
* The theme handler service.
|
||||
*
|
||||
* @var \Drupal\Core\Extension\ThemeHandlerInterface
|
||||
*/
|
||||
protected $themeHandler;
|
||||
|
||||
/**
|
||||
* The menu link tree service.
|
||||
*
|
||||
* @var \Drupal\Core\Menu\MenuLinkTreeInterface
|
||||
*/
|
||||
protected $menuLinkTree;
|
||||
|
||||
/**
|
||||
* Constructs a new SystemController.
|
||||
*
|
||||
* @param \Drupal\system\SystemManager $systemManager
|
||||
* System manager service.
|
||||
* @param \Drupal\Core\Theme\ThemeAccessCheck $theme_access
|
||||
* The theme access checker service.
|
||||
* @param \Drupal\Core\Form\FormBuilderInterface $form_builder
|
||||
* The form builder.
|
||||
* @param \Drupal\Core\Extension\ThemeHandlerInterface $theme_handler
|
||||
* The theme handler.
|
||||
* @param \Drupal\Core\Menu\MenuLinkTreeInterface $menu_link_tree
|
||||
* The menu link tree service.
|
||||
*/
|
||||
public function __construct(SystemManager $systemManager, ThemeAccessCheck $theme_access, FormBuilderInterface $form_builder, ThemeHandlerInterface $theme_handler, MenuLinkTreeInterface $menu_link_tree) {
|
||||
$this->systemManager = $systemManager;
|
||||
$this->themeAccess = $theme_access;
|
||||
$this->formBuilder = $form_builder;
|
||||
$this->themeHandler = $theme_handler;
|
||||
$this->menuLinkTree = $menu_link_tree;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static function create(ContainerInterface $container) {
|
||||
return new static(
|
||||
$container->get('system.manager'),
|
||||
$container->get('access_check.theme'),
|
||||
$container->get('form_builder'),
|
||||
$container->get('theme_handler'),
|
||||
$container->get('menu.link_tree')
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Provide the administration overview page.
|
||||
*
|
||||
* @param string $link_id
|
||||
* The ID of the administrative path link for which to display child links.
|
||||
*
|
||||
* @return array
|
||||
* A renderable array of the administration overview page.
|
||||
*/
|
||||
public function overview($link_id) {
|
||||
// Check for status report errors.
|
||||
if ($this->systemManager->checkRequirements() && $this->currentUser()->hasPermission('administer site configuration')) {
|
||||
$this->messenger()->addError($this->t('One or more problems were detected with your Drupal installation. Check the <a href=":status">status report</a> for more information.', [':status' => $this->url('system.status')]));
|
||||
}
|
||||
// Load all menu links below it.
|
||||
$parameters = new MenuTreeParameters();
|
||||
$parameters->setRoot($link_id)->excludeRoot()->setTopLevelOnly()->onlyEnabledLinks();
|
||||
$tree = $this->menuLinkTree->load(NULL, $parameters);
|
||||
$manipulators = [
|
||||
['callable' => 'menu.default_tree_manipulators:checkAccess'],
|
||||
['callable' => 'menu.default_tree_manipulators:generateIndexAndSort'],
|
||||
];
|
||||
$tree = $this->menuLinkTree->transform($tree, $manipulators);
|
||||
$tree_access_cacheability = new CacheableMetadata();
|
||||
$blocks = [];
|
||||
foreach ($tree as $key => $element) {
|
||||
$tree_access_cacheability = $tree_access_cacheability->merge(CacheableMetadata::createFromObject($element->access));
|
||||
|
||||
// Only render accessible links.
|
||||
if (!$element->access->isAllowed()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$link = $element->link;
|
||||
$block['title'] = $link->getTitle();
|
||||
$block['description'] = $link->getDescription();
|
||||
$block['content'] = [
|
||||
'#theme' => 'admin_block_content',
|
||||
'#content' => $this->systemManager->getAdminBlock($link),
|
||||
];
|
||||
|
||||
if (!empty($block['content']['#content'])) {
|
||||
$blocks[$key] = $block;
|
||||
}
|
||||
}
|
||||
|
||||
if ($blocks) {
|
||||
ksort($blocks);
|
||||
$build = [
|
||||
'#theme' => 'admin_page',
|
||||
'#blocks' => $blocks,
|
||||
];
|
||||
$tree_access_cacheability->applyTo($build);
|
||||
return $build;
|
||||
}
|
||||
else {
|
||||
$build = [
|
||||
'#markup' => $this->t('You do not have any administrative items.'),
|
||||
];
|
||||
$tree_access_cacheability->applyTo($build);
|
||||
return $build;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets whether the admin menu is in compact mode or not.
|
||||
*
|
||||
* @param string $mode
|
||||
* Valid values are 'on' and 'off'.
|
||||
*
|
||||
* @return \Symfony\Component\HttpFoundation\RedirectResponse
|
||||
*/
|
||||
public function compactPage($mode) {
|
||||
user_cookie_save(['admin_compact_mode' => ($mode == 'on')]);
|
||||
return $this->redirect('<front>');
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides a single block from the administration menu as a page.
|
||||
*/
|
||||
public function systemAdminMenuBlockPage() {
|
||||
return $this->systemManager->getBlockContents();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a theme listing.
|
||||
*
|
||||
* @return string
|
||||
* An HTML string of the theme listing page.
|
||||
*
|
||||
* @todo Move into ThemeController.
|
||||
*/
|
||||
public function themesPage() {
|
||||
$config = $this->config('system.theme');
|
||||
// Get all available themes.
|
||||
$themes = $this->themeHandler->rebuildThemeData();
|
||||
uasort($themes, 'system_sort_modules_by_info_name');
|
||||
|
||||
$theme_default = $config->get('default');
|
||||
$theme_groups = ['installed' => [], 'uninstalled' => []];
|
||||
$admin_theme = $config->get('admin');
|
||||
$admin_theme_options = [];
|
||||
|
||||
foreach ($themes as &$theme) {
|
||||
if (!empty($theme->info['hidden'])) {
|
||||
continue;
|
||||
}
|
||||
$theme->is_default = ($theme->getName() == $theme_default);
|
||||
$theme->is_admin = ($theme->getName() == $admin_theme || ($theme->is_default && $admin_theme == '0'));
|
||||
|
||||
// Identify theme screenshot.
|
||||
$theme->screenshot = NULL;
|
||||
// Create a list which includes the current theme and all its base themes.
|
||||
if (isset($themes[$theme->getName()]->base_themes)) {
|
||||
$theme_keys = array_keys($themes[$theme->getName()]->base_themes);
|
||||
$theme_keys[] = $theme->getName();
|
||||
}
|
||||
else {
|
||||
$theme_keys = [$theme->getName()];
|
||||
}
|
||||
// Look for a screenshot in the current theme or in its closest ancestor.
|
||||
foreach (array_reverse($theme_keys) as $theme_key) {
|
||||
if (isset($themes[$theme_key]) && file_exists($themes[$theme_key]->info['screenshot'])) {
|
||||
$theme->screenshot = [
|
||||
'uri' => $themes[$theme_key]->info['screenshot'],
|
||||
'alt' => $this->t('Screenshot for @theme theme', ['@theme' => $theme->info['name']]),
|
||||
'title' => $this->t('Screenshot for @theme theme', ['@theme' => $theme->info['name']]),
|
||||
'attributes' => ['class' => ['screenshot']],
|
||||
];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (empty($theme->status)) {
|
||||
// Ensure this theme is compatible with this version of core.
|
||||
$theme->incompatible_core = !isset($theme->info['core']) || ($theme->info['core'] != \DRUPAL::CORE_COMPATIBILITY);
|
||||
// Require the 'content' region to make sure the main page
|
||||
// content has a common place in all themes.
|
||||
$theme->incompatible_region = !isset($theme->info['regions']['content']);
|
||||
$theme->incompatible_php = version_compare(phpversion(), $theme->info['php']) < 0;
|
||||
// Confirm that all base themes are available.
|
||||
$theme->incompatible_base = (isset($theme->info['base theme']) && !($theme->base_themes === array_filter($theme->base_themes)));
|
||||
// Confirm that the theme engine is available.
|
||||
$theme->incompatible_engine = isset($theme->info['engine']) && !isset($theme->owner);
|
||||
}
|
||||
$theme->operations = [];
|
||||
if (!empty($theme->status) || !$theme->incompatible_core && !$theme->incompatible_php && !$theme->incompatible_base && !$theme->incompatible_engine) {
|
||||
// Create the operations links.
|
||||
$query['theme'] = $theme->getName();
|
||||
if ($this->themeAccess->checkAccess($theme->getName())) {
|
||||
$theme->operations[] = [
|
||||
'title' => $this->t('Settings'),
|
||||
'url' => Url::fromRoute('system.theme_settings_theme', ['theme' => $theme->getName()]),
|
||||
'attributes' => ['title' => $this->t('Settings for @theme theme', ['@theme' => $theme->info['name']])],
|
||||
];
|
||||
}
|
||||
if (!empty($theme->status)) {
|
||||
if (!$theme->is_default) {
|
||||
$theme_uninstallable = TRUE;
|
||||
if ($theme->getName() == $admin_theme) {
|
||||
$theme_uninstallable = FALSE;
|
||||
}
|
||||
// Check it isn't the base of theme of an installed theme.
|
||||
foreach ($theme->required_by as $themename => $dependency) {
|
||||
if (!empty($themes[$themename]->status)) {
|
||||
$theme_uninstallable = FALSE;
|
||||
}
|
||||
}
|
||||
if ($theme_uninstallable) {
|
||||
$theme->operations[] = [
|
||||
'title' => $this->t('Uninstall'),
|
||||
'url' => Url::fromRoute('system.theme_uninstall'),
|
||||
'query' => $query,
|
||||
'attributes' => ['title' => $this->t('Uninstall @theme theme', ['@theme' => $theme->info['name']])],
|
||||
];
|
||||
}
|
||||
$theme->operations[] = [
|
||||
'title' => $this->t('Set as default'),
|
||||
'url' => Url::fromRoute('system.theme_set_default'),
|
||||
'query' => $query,
|
||||
'attributes' => ['title' => $this->t('Set @theme as default theme', ['@theme' => $theme->info['name']])],
|
||||
];
|
||||
}
|
||||
$admin_theme_options[$theme->getName()] = $theme->info['name'];
|
||||
}
|
||||
else {
|
||||
$theme->operations[] = [
|
||||
'title' => $this->t('Install'),
|
||||
'url' => Url::fromRoute('system.theme_install'),
|
||||
'query' => $query,
|
||||
'attributes' => ['title' => $this->t('Install @theme theme', ['@theme' => $theme->info['name']])],
|
||||
];
|
||||
$theme->operations[] = [
|
||||
'title' => $this->t('Install and set as default'),
|
||||
'url' => Url::fromRoute('system.theme_set_default'),
|
||||
'query' => $query,
|
||||
'attributes' => ['title' => $this->t('Install @theme as default theme', ['@theme' => $theme->info['name']])],
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
// Add notes to default and administration theme.
|
||||
$theme->notes = [];
|
||||
if ($theme->is_default) {
|
||||
$theme->notes[] = $this->t('default theme');
|
||||
}
|
||||
if ($theme->is_admin) {
|
||||
$theme->notes[] = $this->t('administration theme');
|
||||
}
|
||||
|
||||
// Sort installed and uninstalled themes into their own groups.
|
||||
$theme_groups[$theme->status ? 'installed' : 'uninstalled'][] = $theme;
|
||||
}
|
||||
|
||||
// There are two possible theme groups.
|
||||
$theme_group_titles = [
|
||||
'installed' => $this->formatPlural(count($theme_groups['installed']), 'Installed theme', 'Installed themes'),
|
||||
];
|
||||
if (!empty($theme_groups['uninstalled'])) {
|
||||
$theme_group_titles['uninstalled'] = $this->formatPlural(count($theme_groups['uninstalled']), 'Uninstalled theme', 'Uninstalled themes');
|
||||
}
|
||||
|
||||
uasort($theme_groups['installed'], 'system_sort_themes');
|
||||
$this->moduleHandler()->alter('system_themes_page', $theme_groups);
|
||||
|
||||
$build = [];
|
||||
$build[] = [
|
||||
'#theme' => 'system_themes_page',
|
||||
'#theme_groups' => $theme_groups,
|
||||
'#theme_group_titles' => $theme_group_titles,
|
||||
];
|
||||
$build[] = $this->formBuilder->getForm('Drupal\system\Form\ThemeAdminForm', $admin_theme_options);
|
||||
|
||||
return $build;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,71 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\system\Controller;
|
||||
|
||||
use Symfony\Component\DependencyInjection\ContainerInterface;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Drupal\Core\DependencyInjection\ContainerInjectionInterface;
|
||||
use Drupal\system\SystemManager;
|
||||
|
||||
/**
|
||||
* Returns responses for System Info routes.
|
||||
*/
|
||||
class SystemInfoController implements ContainerInjectionInterface {
|
||||
|
||||
/**
|
||||
* System Manager Service.
|
||||
*
|
||||
* @var \Drupal\system\SystemManager
|
||||
*/
|
||||
protected $systemManager;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static function create(ContainerInterface $container) {
|
||||
return new static(
|
||||
$container->get('system.manager')
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a SystemInfoController object.
|
||||
*
|
||||
* @param \Drupal\system\SystemManager $systemManager
|
||||
* System manager service.
|
||||
*/
|
||||
public function __construct(SystemManager $systemManager) {
|
||||
$this->systemManager = $systemManager;
|
||||
}
|
||||
|
||||
/**
|
||||
* Displays the site status report.
|
||||
*
|
||||
* @return array
|
||||
* A render array containing a list of system requirements for the Drupal
|
||||
* installation and whether this installation meets the requirements.
|
||||
*/
|
||||
public function status() {
|
||||
$requirements = $this->systemManager->listRequirements();
|
||||
return ['#type' => 'status_report_page', '#requirements' => $requirements];
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the contents of phpinfo().
|
||||
*
|
||||
* @return \Symfony\Component\HttpFoundation\Response
|
||||
* A response object to be sent to the client.
|
||||
*/
|
||||
public function php() {
|
||||
if (function_exists('phpinfo')) {
|
||||
ob_start();
|
||||
phpinfo();
|
||||
$output = ob_get_clean();
|
||||
}
|
||||
else {
|
||||
$output = t('The phpinfo() function has been disabled for security reasons. For more information, visit <a href=":phpinfo">Enabling and disabling phpinfo()</a> handbook page.', [':phpinfo' => 'https://www.drupal.org/node/243993']);
|
||||
}
|
||||
return new Response($output);
|
||||
}
|
||||
|
||||
}
|
193
2017/web/core/modules/system/src/Controller/ThemeController.php
Normal file
193
2017/web/core/modules/system/src/Controller/ThemeController.php
Normal file
|
@ -0,0 +1,193 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\system\Controller;
|
||||
|
||||
use Drupal\Core\Config\ConfigFactoryInterface;
|
||||
use Drupal\Core\Config\PreExistingConfigException;
|
||||
use Drupal\Core\Config\UnmetDependenciesException;
|
||||
use Drupal\Core\Controller\ControllerBase;
|
||||
use Drupal\Core\Extension\ThemeHandlerInterface;
|
||||
use Symfony\Component\DependencyInjection\ContainerInterface;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException;
|
||||
|
||||
/**
|
||||
* Controller for theme handling.
|
||||
*/
|
||||
class ThemeController extends ControllerBase {
|
||||
|
||||
/**
|
||||
* The theme handler service.
|
||||
*
|
||||
* @var \Drupal\Core\Extension\ThemeHandlerInterface
|
||||
*/
|
||||
protected $themeHandler;
|
||||
|
||||
/**
|
||||
* Constructs a new ThemeController.
|
||||
*
|
||||
* @param \Drupal\Core\Extension\ThemeHandlerInterface $theme_handler
|
||||
* The theme handler.
|
||||
* @param \Drupal\Core\Config\ConfigFactoryInterface $config_factory
|
||||
* The config factory.
|
||||
*/
|
||||
public function __construct(ThemeHandlerInterface $theme_handler, ConfigFactoryInterface $config_factory) {
|
||||
$this->themeHandler = $theme_handler;
|
||||
$this->configFactory = $config_factory;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static function create(ContainerInterface $container) {
|
||||
return new static(
|
||||
$container->get('theme_handler'),
|
||||
$container->get('config.factory')
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Uninstalls a theme.
|
||||
*
|
||||
* @param \Symfony\Component\HttpFoundation\Request $request
|
||||
* A request object containing a theme name and a valid token.
|
||||
*
|
||||
* @return \Symfony\Component\HttpFoundation\RedirectResponse
|
||||
* Redirects back to the appearance admin page.
|
||||
*
|
||||
* @throws \Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException
|
||||
* Throws access denied when no theme or token is set in the request or when
|
||||
* the token is invalid.
|
||||
*/
|
||||
public function uninstall(Request $request) {
|
||||
$theme = $request->query->get('theme');
|
||||
$config = $this->config('system.theme');
|
||||
|
||||
if (isset($theme)) {
|
||||
// Get current list of themes.
|
||||
$themes = $this->themeHandler->listInfo();
|
||||
|
||||
// Check if the specified theme is one recognized by the system.
|
||||
if (!empty($themes[$theme])) {
|
||||
// Do not uninstall the default or admin theme.
|
||||
if ($theme === $config->get('default') || $theme === $config->get('admin')) {
|
||||
$this->messenger()->addError($this->t('%theme is the default theme and cannot be uninstalled.', ['%theme' => $themes[$theme]->info['name']]));
|
||||
}
|
||||
else {
|
||||
$this->themeHandler->uninstall([$theme]);
|
||||
$this->messenger()->addStatus($this->t('The %theme theme has been uninstalled.', ['%theme' => $themes[$theme]->info['name']]));
|
||||
}
|
||||
}
|
||||
else {
|
||||
$this->messenger()->addError($this->t('The %theme theme was not found.', ['%theme' => $theme]));
|
||||
}
|
||||
|
||||
return $this->redirect('system.themes_page');
|
||||
}
|
||||
|
||||
throw new AccessDeniedHttpException();
|
||||
}
|
||||
|
||||
/**
|
||||
* Installs a theme.
|
||||
*
|
||||
* @param \Symfony\Component\HttpFoundation\Request $request
|
||||
* A request object containing a theme name and a valid token.
|
||||
*
|
||||
* @return \Symfony\Component\HttpFoundation\RedirectResponse
|
||||
* Redirects back to the appearance admin page.
|
||||
*
|
||||
* @throws \Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException
|
||||
* Throws access denied when no theme or token is set in the request or when
|
||||
* the token is invalid.
|
||||
*/
|
||||
public function install(Request $request) {
|
||||
$theme = $request->query->get('theme');
|
||||
|
||||
if (isset($theme)) {
|
||||
try {
|
||||
if ($this->themeHandler->install([$theme])) {
|
||||
$themes = $this->themeHandler->listInfo();
|
||||
$this->messenger()->addStatus($this->t('The %theme theme has been installed.', ['%theme' => $themes[$theme]->info['name']]));
|
||||
}
|
||||
else {
|
||||
$this->messenger()->addError($this->t('The %theme theme was not found.', ['%theme' => $theme]));
|
||||
}
|
||||
}
|
||||
catch (PreExistingConfigException $e) {
|
||||
$config_objects = $e->flattenConfigObjects($e->getConfigObjects());
|
||||
$this->messenger()->addError(
|
||||
$this->formatPlural(
|
||||
count($config_objects),
|
||||
'Unable to install @extension, %config_names already exists in active configuration.',
|
||||
'Unable to install @extension, %config_names already exist in active configuration.',
|
||||
[
|
||||
'%config_names' => implode(', ', $config_objects),
|
||||
'@extension' => $theme,
|
||||
])
|
||||
);
|
||||
}
|
||||
catch (UnmetDependenciesException $e) {
|
||||
$this->messenger()->addError($e->getTranslatedMessage($this->getStringTranslation(), $theme));
|
||||
}
|
||||
|
||||
return $this->redirect('system.themes_page');
|
||||
}
|
||||
|
||||
throw new AccessDeniedHttpException();
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the default theme.
|
||||
*
|
||||
* @param \Symfony\Component\HttpFoundation\Request $request
|
||||
* A request object containing a theme name.
|
||||
*
|
||||
* @return \Symfony\Component\HttpFoundation\RedirectResponse
|
||||
* Redirects back to the appearance admin page.
|
||||
*
|
||||
* @throws \Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException
|
||||
* Throws access denied when no theme is set in the request.
|
||||
*/
|
||||
public function setDefaultTheme(Request $request) {
|
||||
$config = $this->configFactory->getEditable('system.theme');
|
||||
$theme = $request->query->get('theme');
|
||||
|
||||
if (isset($theme)) {
|
||||
// Get current list of themes.
|
||||
$themes = $this->themeHandler->listInfo();
|
||||
|
||||
// Check if the specified theme is one recognized by the system.
|
||||
// Or try to install the theme.
|
||||
if (isset($themes[$theme]) || $this->themeHandler->install([$theme])) {
|
||||
$themes = $this->themeHandler->listInfo();
|
||||
|
||||
// Set the default theme.
|
||||
$config->set('default', $theme)->save();
|
||||
|
||||
// The status message depends on whether an admin theme is currently in
|
||||
// use: a value of 0 means the admin theme is set to be the default
|
||||
// theme.
|
||||
$admin_theme = $config->get('admin');
|
||||
if ($admin_theme != 0 && $admin_theme != $theme) {
|
||||
$this->messenger()
|
||||
->addStatus($this->t('Please note that the administration theme is still set to the %admin_theme theme; consequently, the theme on this page remains unchanged. All non-administrative sections of the site, however, will show the selected %selected_theme theme by default.', [
|
||||
'%admin_theme' => $themes[$admin_theme]->info['name'],
|
||||
'%selected_theme' => $themes[$theme]->info['name'],
|
||||
]));
|
||||
}
|
||||
else {
|
||||
$this->messenger()->addStatus($this->t('%theme is now the default theme.', ['%theme' => $themes[$theme]->info['name']]));
|
||||
}
|
||||
}
|
||||
else {
|
||||
$this->messenger()->addError($this->t('The %theme theme was not found.', ['%theme' => $theme]));
|
||||
}
|
||||
|
||||
return $this->redirect('system.themes_page');
|
||||
|
||||
}
|
||||
throw new AccessDeniedHttpException();
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,38 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\system\Controller;
|
||||
|
||||
use Symfony\Component\HttpFoundation\JsonResponse;
|
||||
|
||||
/**
|
||||
* Provides a callback for finding out a timezone name.
|
||||
*/
|
||||
class TimezoneController {
|
||||
|
||||
/**
|
||||
* Retrieve a JSON object containing a time zone name given a timezone
|
||||
* abbreviation.
|
||||
*
|
||||
* @param string $abbreviation
|
||||
* Time zone abbreviation.
|
||||
* @param int $offset
|
||||
* Offset from GMT in seconds. Defaults to -1 which means that first found
|
||||
* time zone corresponding to abbr is returned. Otherwise exact offset is
|
||||
* searched and only if not found then the first time zone with any offset
|
||||
* is returned.
|
||||
* @param null|bool $is_daylight_saving_time
|
||||
* Daylight saving time indicator. If abbr does not exist then the time
|
||||
* zone is searched solely by offset and isdst.
|
||||
*
|
||||
* @return \Symfony\Component\HttpFoundation\JsonResponse
|
||||
* The timezone name in JsonResponse object.
|
||||
*/
|
||||
public function getTimezone($abbreviation = '', $offset = -1, $is_daylight_saving_time = NULL) {
|
||||
// An abbreviation of "0" passed in the callback arguments should be
|
||||
// interpreted as the empty string.
|
||||
$abbreviation = $abbreviation ? $abbreviation : '';
|
||||
$timezone = timezone_name_from_abbr($abbreviation, intval($offset), $is_daylight_saving_time);
|
||||
return new JsonResponse($timezone);
|
||||
}
|
||||
|
||||
}
|
69
2017/web/core/modules/system/src/CronController.php
Normal file
69
2017/web/core/modules/system/src/CronController.php
Normal file
|
@ -0,0 +1,69 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\system;
|
||||
|
||||
use Drupal\Core\Controller\ControllerBase;
|
||||
use Drupal\Core\CronInterface;
|
||||
use Symfony\Component\DependencyInjection\ContainerInterface;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
|
||||
/**
|
||||
* Controller for Cron handling.
|
||||
*/
|
||||
class CronController extends ControllerBase {
|
||||
|
||||
/**
|
||||
* The cron service.
|
||||
*
|
||||
* @var \Drupal\Core\CronInterface
|
||||
*/
|
||||
protected $cron;
|
||||
|
||||
/**
|
||||
* Constructs a CronController object.
|
||||
*
|
||||
* @param \Drupal\Core\CronInterface $cron
|
||||
* The cron service.
|
||||
*/
|
||||
public function __construct(CronInterface $cron) {
|
||||
$this->cron = $cron;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static function create(ContainerInterface $container) {
|
||||
return new static($container->get('cron'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Run Cron once.
|
||||
*
|
||||
* @return \Symfony\Component\HttpFoundation\Response
|
||||
* A Symfony response object.
|
||||
*/
|
||||
public function run() {
|
||||
$this->cron->run();
|
||||
|
||||
// HTTP 204 is "No content", meaning "I did what you asked and we're done."
|
||||
return new Response('', 204);
|
||||
}
|
||||
|
||||
/**
|
||||
* Run cron manually.
|
||||
*
|
||||
* @return \Symfony\Component\HttpFoundation\RedirectResponse
|
||||
* A Symfony direct response object.
|
||||
*/
|
||||
public function runManually() {
|
||||
if ($this->cron->run()) {
|
||||
$this->messenger()->addStatus($this->t('Cron ran successfully.'));
|
||||
}
|
||||
else {
|
||||
$this->messenger()->addError($this->t('Cron run failed.'));
|
||||
}
|
||||
|
||||
return $this->redirect('system.status');
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,43 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\system;
|
||||
|
||||
use Drupal\Core\Access\AccessResult;
|
||||
use Drupal\Core\Entity\EntityAccessControlHandler;
|
||||
use Drupal\Core\Entity\EntityInterface;
|
||||
use Drupal\Core\Session\AccountInterface;
|
||||
|
||||
/**
|
||||
* Defines the access control handler for the date format entity type.
|
||||
*
|
||||
* @see \Drupal\system\Entity\DateFormat
|
||||
*/
|
||||
class DateFormatAccessControlHandler extends EntityAccessControlHandler {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected $viewLabelOperation = TRUE;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function checkAccess(EntityInterface $entity, $operation, AccountInterface $account) {
|
||||
// There are no restrictions on viewing the label of a date format.
|
||||
if ($operation === 'view label') {
|
||||
return AccessResult::allowed();
|
||||
}
|
||||
// Locked date formats cannot be updated or deleted.
|
||||
elseif (in_array($operation, ['update', 'delete'])) {
|
||||
if ($entity->isLocked()) {
|
||||
return AccessResult::forbidden('The DateFormat config entity is locked.')->addCacheableDependency($entity);
|
||||
}
|
||||
else {
|
||||
return parent::checkAccess($entity, $operation, $account)->addCacheableDependency($entity);
|
||||
}
|
||||
}
|
||||
|
||||
return parent::checkAccess($entity, $operation, $account);
|
||||
}
|
||||
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show more
Reference in a new issue