Move into nested docroot
This commit is contained in:
parent
83a0d3a149
commit
c8b70abde9
13405 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:
|
3
web/core/modules/system/config/install/system.cron.yml
Normal file
3
web/core/modules/system/config/install/system.cron.yml
Normal file
|
@ -0,0 +1,3 @@
|
|||
threshold:
|
||||
requirements_warning: 172800
|
||||
requirements_error: 1209600
|
9
web/core/modules/system/config/install/system.date.yml
Normal file
9
web/core/modules/system/config/install/system.date.yml
Normal file
|
@ -0,0 +1,9 @@
|
|||
country:
|
||||
default: ''
|
||||
first_day: 0
|
||||
timezone:
|
||||
default: ''
|
||||
user:
|
||||
configurable: true
|
||||
warn: false
|
||||
default: 0
|
3
web/core/modules/system/config/install/system.diff.yml
Normal file
3
web/core/modules/system/config/install/system.diff.yml
Normal file
|
@ -0,0 +1,3 @@
|
|||
context:
|
||||
lines_leading: 2
|
||||
lines_trailing: 2
|
5
web/core/modules/system/config/install/system.file.yml
Normal file
5
web/core/modules/system/config/install/system.file.yml
Normal file
|
@ -0,0 +1,5 @@
|
|||
allow_insecure_uploads: false
|
||||
default_scheme: 'public'
|
||||
path:
|
||||
temporary: ''
|
||||
temporary_maximum_age: 21600
|
|
@ -0,0 +1 @@
|
|||
jpeg_quality: 75
|
1
web/core/modules/system/config/install/system.image.yml
Normal file
1
web/core/modules/system/config/install/system.image.yml
Normal file
|
@ -0,0 +1 @@
|
|||
toolkit: gd
|
|
@ -0,0 +1 @@
|
|||
error_level: hide
|
2
web/core/modules/system/config/install/system.mail.yml
Normal file
2
web/core/modules/system/config/install/system.mail.yml
Normal file
|
@ -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
|
6
web/core/modules/system/config/install/system.rss.yml
Normal file
6
web/core/modules/system/config/install/system.rss.yml
Normal file
|
@ -0,0 +1,6 @@
|
|||
channel:
|
||||
description: ''
|
||||
items:
|
||||
limit: 10
|
||||
view_mode: rss
|
||||
langcode: en
|
12
web/core/modules/system/config/install/system.site.yml
Normal file
12
web/core/modules/system/config/install/system.site.yml
Normal file
|
@ -0,0 +1,12 @@
|
|||
uuid: ''
|
||||
name: 'Drupal'
|
||||
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
|
2
web/core/modules/system/config/install/system.theme.yml
Normal file
2
web/core/modules/system/config/install/system.theme.yml
Normal file
|
@ -0,0 +1,2 @@
|
|||
admin: ''
|
||||
default: stark
|
357
web/core/modules/system/config/schema/system.schema.yml
Normal file
357
web/core/modules/system/config/schema/system.schema.yml
Normal file
|
@ -0,0 +1,357 @@
|
|||
# Schema for the configuration files of the System module.
|
||||
|
||||
system.site:
|
||||
type: config_object
|
||||
label: 'Site information'
|
||||
mapping:
|
||||
uuid:
|
||||
type: string
|
||||
label: 'Site UUID'
|
||||
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'
|
||||
|
||||
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.'
|
||||
response:
|
||||
type: mapping
|
||||
label: 'Response performance settings'
|
||||
mapping:
|
||||
gzip:
|
||||
type: boolean
|
||||
label: 'Compress cached pages'
|
||||
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 0px 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
web/core/modules/system/css/components/align.module.css
Normal file
32
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;
|
||||
}
|
15
web/core/modules/system/css/components/clearfix.module.css
Normal file
15
web/core/modules/system/css/components/clearfix.module.css
Normal file
|
@ -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;
|
||||
}
|
10
web/core/modules/system/css/components/details.module.css
Normal file
10
web/core/modules/system/css/components/details.module.css
Normal file
|
@ -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;
|
||||
}
|
53
web/core/modules/system/css/components/hidden.module.css
Normal file
53
web/core/modules/system/css/components/hidden.module.css
Normal file
|
@ -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;
|
||||
}
|
19
web/core/modules/system/css/components/item-list.module.css
Normal file
19
web/core/modules/system/css/components/item-list.module.css
Normal file
|
@ -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
web/core/modules/system/css/components/js.module.css
Normal file
22
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;
|
||||
}
|
8
web/core/modules/system/css/components/nowrap.module.css
Normal file
8
web/core/modules/system/css/components/nowrap.module.css
Normal file
|
@ -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;
|
||||
}
|
51
web/core/modules/system/css/components/progress.module.css
Normal file
51
web/core/modules/system/css/components/progress.module.css
Normal file
|
@ -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: .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;
|
||||
}
|
21
web/core/modules/system/css/components/resize.module.css
Normal file
21
web/core/modules/system/css/components/resize.module.css
Normal file
|
@ -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;
|
||||
}
|
88
web/core/modules/system/css/components/tabledrag.module.css
Normal file
88
web/core/modules/system/css/components/tabledrag.module.css
Normal file
|
@ -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;
|
||||
}
|
19
web/core/modules/system/css/components/tablesort.module.css
Normal file
19
web/core/modules/system/css/components/tablesort.module.css
Normal file
|
@ -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);
|
||||
}
|
18
web/core/modules/system/css/components/tree-child.module.css
Normal file
18
web/core/modules/system/css/components/tree-child.module.css
Normal file
|
@ -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;
|
||||
}
|
389
web/core/modules/system/css/system.admin.css
Normal file
389
web/core/modules/system/css/system.admin.css
Normal file
|
@ -0,0 +1,389 @@
|
|||
/**
|
||||
* @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: 0px;
|
||||
}
|
||||
.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: 25%;
|
||||
padding: 10px 6px 10px 40px; /* LTR */
|
||||
box-sizing: border-box;
|
||||
font-weight: normal;
|
||||
}
|
||||
[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);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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;
|
||||
}
|
42
web/core/modules/system/css/system.diff.css
Normal file
42
web/core/modules/system/css/system.diff.css
Normal file
|
@ -0,0 +1,42 @@
|
|||
/**
|
||||
* Traditional split diff theming
|
||||
*/
|
||||
table.diff {
|
||||
border-spacing: 4px;
|
||||
margin-bottom: 20px;
|
||||
table-layout: fixed;
|
||||
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
web/core/modules/system/css/system.maintenance.css
Normal file
56
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
web/core/modules/system/images/no_screenshot.png
Normal file
BIN
web/core/modules/system/images/no_screenshot.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.5 KiB |
57
web/core/modules/system/js/system.date.js
Normal file
57
web/core/modules/system/js/system.date.js
Normal file
|
@ -0,0 +1,57 @@
|
|||
/**
|
||||
* @file
|
||||
* Provides date format preview feature.
|
||||
*/
|
||||
|
||||
(function ($, Drupal, drupalSettings) {
|
||||
|
||||
'use strict';
|
||||
|
||||
var 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: function (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');
|
||||
|
||||
// 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) {
|
||||
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);
|
||||
}
|
||||
|
||||
/**
|
||||
* On given event triggers the date character replacement.
|
||||
*/
|
||||
$source.on('keyup.dateFormat change.dateFormat input.dateFormat', dateFormatHandler)
|
||||
// Initialize preview.
|
||||
.trigger('keyup');
|
||||
}
|
||||
};
|
||||
|
||||
})(jQuery, Drupal, drupalSettings);
|
81
web/core/modules/system/js/system.js
Normal file
81
web/core/modules/system/js/system.js
Normal file
|
@ -0,0 +1,81 @@
|
|||
/**
|
||||
* @file
|
||||
* System behaviors.
|
||||
*/
|
||||
|
||||
(function ($, Drupal, drupalSettings) {
|
||||
|
||||
'use strict';
|
||||
|
||||
// Cache IDs in an array for ease of use.
|
||||
var 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: function (context) {
|
||||
// List of fields IDs on which to bind the event listener.
|
||||
// Create an array of IDs to use with jQuery.
|
||||
for (var sourceId in drupalSettings.copyFieldValue) {
|
||||
if (drupalSettings.copyFieldValue.hasOwnProperty(sourceId)) {
|
||||
ids.push(sourceId);
|
||||
}
|
||||
}
|
||||
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: function (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: function (e, value) {
|
||||
var $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: function (e) {
|
||||
var value = $(e.target).val();
|
||||
var targetIds = drupalSettings.copyFieldValue[e.target.id];
|
||||
$('#' + targetIds.join(', #')).trigger('value:copy', value);
|
||||
}
|
||||
};
|
||||
|
||||
})(jQuery, Drupal, drupalSettings);
|
103
web/core/modules/system/js/system.modules.js
Normal file
103
web/core/modules/system/js/system.modules.js
Normal file
|
@ -0,0 +1,103 @@
|
|||
/**
|
||||
* @file
|
||||
* Module page behaviors.
|
||||
*/
|
||||
|
||||
(function ($, Drupal, debounce) {
|
||||
|
||||
'use strict';
|
||||
|
||||
/**
|
||||
* 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: function (context, settings) {
|
||||
var $input = $('input.table-filter-text').once('table-filter-text');
|
||||
var $table = $($input.attr('data-table'));
|
||||
var $rowsAndDetails;
|
||||
var $rows;
|
||||
var $details;
|
||||
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();
|
||||
// Case insensitive expression to find query at the beginning of a word.
|
||||
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);
|
||||
}
|
||||
// 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));
|
|
@ -0,0 +1,21 @@
|
|||
id: d6_date_formats
|
||||
label: Date format configuration
|
||||
migration_tags:
|
||||
- Drupal 6
|
||||
source:
|
||||
plugin: variable_multirow
|
||||
variables:
|
||||
- date_format_long
|
||||
- date_format_medium
|
||||
- date_format_short
|
||||
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
|
13
web/core/modules/system/migration_templates/d6_menu.yml
Normal file
13
web/core/modules/system/migration_templates/d6_menu.yml
Normal file
|
@ -0,0 +1,13 @@
|
|||
# The menu_settings migration is in the menu_ui module.
|
||||
id: d6_menu
|
||||
label: Menus
|
||||
migration_tags:
|
||||
- Drupal 6
|
||||
source:
|
||||
plugin: menu
|
||||
process:
|
||||
id: menu_name
|
||||
label: title
|
||||
description: description
|
||||
destination:
|
||||
plugin: entity:menu
|
|
@ -0,0 +1,16 @@
|
|||
id: d6_system_cron
|
||||
label: Cron settings
|
||||
migration_tags:
|
||||
- Drupal 6
|
||||
source:
|
||||
plugin: variable
|
||||
variables:
|
||||
- cron_threshold_warning
|
||||
- cron_threshold_error
|
||||
- cron_last
|
||||
process:
|
||||
'threshold/requirements_warning': cron_threshold_warning
|
||||
'threshold/requirements_error': cron_threshold_error
|
||||
destination:
|
||||
plugin: config
|
||||
config_name: system.cron
|
|
@ -0,0 +1,19 @@
|
|||
id: d6_system_date
|
||||
label: System date configuration
|
||||
migration_tags:
|
||||
- Drupal 6
|
||||
source:
|
||||
plugin: variable
|
||||
variables:
|
||||
- configurable_timezones
|
||||
- date_first_day
|
||||
- date_default_timezone
|
||||
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
|
|
@ -0,0 +1,20 @@
|
|||
id: d6_system_file
|
||||
label: File system configuration
|
||||
migration_tags:
|
||||
- Drupal 6
|
||||
source:
|
||||
plugin: variable
|
||||
variables:
|
||||
- file_directory_temp
|
||||
- allow_insecure_uploads
|
||||
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,20 @@
|
|||
id: d6_system_performance
|
||||
label: Performance configuration
|
||||
migration_tags:
|
||||
- Drupal 6
|
||||
source:
|
||||
plugin: variable
|
||||
variables:
|
||||
- preprocess_css
|
||||
- preprocess_js
|
||||
- cache_lifetime
|
||||
- cache
|
||||
- page_compression
|
||||
process:
|
||||
'css/preprocess': preprocess_css
|
||||
'js/preprocess': preprocess_js
|
||||
'cache/page/max_age': cache_lifetime
|
||||
'response/gzip': page_compression
|
||||
destination:
|
||||
plugin: config
|
||||
config_name: system.performance
|
|
@ -0,0 +1,29 @@
|
|||
id: d7_global_theme_settings
|
||||
label: D7 global theme settings
|
||||
migration_tags:
|
||||
- Drupal 7
|
||||
source:
|
||||
plugin: variable
|
||||
variables:
|
||||
- theme_settings
|
||||
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
|
20
web/core/modules/system/migration_templates/d7_menu.yml
Normal file
20
web/core/modules/system/migration_templates/d7_menu.yml
Normal file
|
@ -0,0 +1,20 @@
|
|||
id: d7_menu
|
||||
label: Menus
|
||||
migration_tags:
|
||||
- Drupal 7
|
||||
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,12 @@
|
|||
id: d7_system_authorize
|
||||
migration_tags:
|
||||
- Drupal 7
|
||||
source:
|
||||
plugin: variable
|
||||
variables:
|
||||
- authorize_filetransfer_default
|
||||
process:
|
||||
filetransfer_default: authorize_filetransfer_default
|
||||
destination:
|
||||
plugin: config
|
||||
config_name: system.authorize
|
|
@ -0,0 +1,15 @@
|
|||
id: d7_system_cron
|
||||
label: Drupal 7 cron settings
|
||||
migration_tags:
|
||||
- Drupal 7
|
||||
source:
|
||||
plugin: variable
|
||||
variables:
|
||||
- cron_threshold_warning
|
||||
- cron_threshold_error
|
||||
process:
|
||||
'threshold/requirements_warning': cron_threshold_warning
|
||||
'threshold/requirements_error': cron_threshold_error
|
||||
destination:
|
||||
plugin: config
|
||||
config_name: system.cron
|
|
@ -0,0 +1,22 @@
|
|||
id: d7_system_date
|
||||
migration_tags:
|
||||
- Drupal 7
|
||||
source:
|
||||
plugin: variable
|
||||
variables:
|
||||
- site_default_country
|
||||
- date_first_day
|
||||
- date_default_timezone
|
||||
- configurable_timezones
|
||||
- empty_timezone_message
|
||||
- user_default_timezone
|
||||
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
|
|
@ -0,0 +1,20 @@
|
|||
id: d7_system_file
|
||||
label: Drupal 7 file system configuration
|
||||
migration_tags:
|
||||
- Drupal 7
|
||||
source:
|
||||
plugin: variable
|
||||
variables:
|
||||
- allow_insecure_uploads
|
||||
- file_temporary_path
|
||||
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
|
|
@ -0,0 +1,17 @@
|
|||
id: d7_system_mail
|
||||
migration_tags:
|
||||
- Drupal 7
|
||||
source:
|
||||
plugin: variable
|
||||
variables:
|
||||
- mail_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,19 @@
|
|||
id: d7_system_performance
|
||||
label: Drupal 7 performance configuration
|
||||
migration_tags:
|
||||
- Drupal 7
|
||||
source:
|
||||
plugin: variable
|
||||
variables:
|
||||
- preprocess_css
|
||||
- preprocess_js
|
||||
- cache_lifetime
|
||||
- page_compression
|
||||
process:
|
||||
'css/preprocess': preprocess_css
|
||||
'js/preprocess': preprocess_js
|
||||
'cache/page/max_age': cache_lifetime
|
||||
'response/gzip': page_compression
|
||||
destination:
|
||||
plugin: config
|
||||
config_name: system.performance
|
14
web/core/modules/system/migration_templates/system_image.yml
Normal file
14
web/core/modules/system/migration_templates/system_image.yml
Normal file
|
@ -0,0 +1,14 @@
|
|||
id: system_image
|
||||
label: Image toolkit configuration
|
||||
migration_tags:
|
||||
- Drupal 6
|
||||
- Drupal 7
|
||||
source:
|
||||
plugin: variable
|
||||
variables:
|
||||
- image_toolkit
|
||||
process:
|
||||
toolkit: image_toolkit
|
||||
destination:
|
||||
plugin: config
|
||||
config_name: system.image
|
|
@ -0,0 +1,14 @@
|
|||
id: system_image_gd
|
||||
label: Image quality configuration
|
||||
migration_tags:
|
||||
- Drupal 6
|
||||
- Drupal 7
|
||||
source:
|
||||
plugin: variable
|
||||
variables:
|
||||
- image_jpeg_quality
|
||||
process:
|
||||
jpeg_quality: image_jpeg_quality
|
||||
destination:
|
||||
plugin: config
|
||||
config_name: system.image.gd
|
|
@ -0,0 +1,22 @@
|
|||
id: system_logging
|
||||
label: System logging
|
||||
migration_tags:
|
||||
- Drupal 6
|
||||
- Drupal 7
|
||||
source:
|
||||
plugin: variable
|
||||
variables:
|
||||
- error_level
|
||||
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,14 @@
|
|||
id: system_maintenance
|
||||
label: Maintenance page configuration
|
||||
migration_tags:
|
||||
- Drupal 6
|
||||
- Drupal 7
|
||||
source:
|
||||
plugin: variable
|
||||
variables:
|
||||
- site_offline_message
|
||||
process:
|
||||
message: site_offline_message
|
||||
destination:
|
||||
plugin: config
|
||||
config_name: system.maintenance
|
16
web/core/modules/system/migration_templates/system_rss.yml
Normal file
16
web/core/modules/system/migration_templates/system_rss.yml
Normal file
|
@ -0,0 +1,16 @@
|
|||
id: system_rss
|
||||
label: RSS configuration
|
||||
migration_tags:
|
||||
- Drupal 6
|
||||
- Drupal 7
|
||||
source:
|
||||
plugin: variable
|
||||
variables:
|
||||
- feed_default_items
|
||||
- feed_item_length
|
||||
process:
|
||||
'items/limit': feed_default_items
|
||||
'items/view_mode': feed_item_length
|
||||
destination:
|
||||
plugin: config
|
||||
config_name: system.rss
|
42
web/core/modules/system/migration_templates/system_site.yml
Normal file
42
web/core/modules/system/migration_templates/system_site.yml
Normal file
|
@ -0,0 +1,42 @@
|
|||
id: system_site
|
||||
label: Site configuration
|
||||
migration_tags:
|
||||
- Drupal 6
|
||||
- Drupal 7
|
||||
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
|
||||
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
web/core/modules/system/src/Access/CronAccessCheck.php
Normal file
34
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);
|
||||
}
|
||||
|
||||
}
|
38
web/core/modules/system/src/Access/DbUpdateAccessCheck.php
Normal file
38
web/core/modules/system/src/Access/DbUpdateAccessCheck.php
Normal file
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
33
web/core/modules/system/src/ActionConfigEntityInterface.php
Normal file
33
web/core/modules/system/src/ActionConfigEntityInterface.php
Normal file
|
@ -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();
|
||||
|
||||
}
|
53
web/core/modules/system/src/Controller/AdminController.php
Normal file
53
web/core/modules/system/src/Controller/AdminController.php
Normal file
|
@ -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 = array();
|
||||
|
||||
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, array('\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']] = array($info->info['description'], $admin_tasks);
|
||||
}
|
||||
}
|
||||
|
||||
$output = array(
|
||||
'#theme' => 'system_admin_index',
|
||||
'#menu_items' => $menu_items,
|
||||
);
|
||||
|
||||
return $output;
|
||||
}
|
||||
|
||||
}
|
84
web/core/modules/system/src/Controller/BatchController.php
Normal file
84
web/core/modules/system/src/Controller/BatchController.php
Normal file
|
@ -0,0 +1,84 @@
|
|||
<?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)) {
|
||||
$page = [
|
||||
'#type' => 'page',
|
||||
'#show_messages' => FALSE,
|
||||
'content' => $output,
|
||||
];
|
||||
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']);
|
||||
}
|
||||
|
||||
}
|
705
web/core/modules/system/src/Controller/DbUpdateController.php
Normal file
705
web/core/modules/system/src/Controller/DbUpdateController.php
Normal file
|
@ -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 = array();
|
||||
$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'] = array(
|
||||
'#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>.', array(
|
||||
':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'] = array(
|
||||
'#theme' => 'item_list',
|
||||
'#list_type' => 'ol',
|
||||
'#items' => $info,
|
||||
);
|
||||
$build['info_footer'] = array(
|
||||
'#markup' => '<p>' . $this->t('When you have performed the steps above, you may proceed.') . '</p>',
|
||||
);
|
||||
|
||||
$build['link'] = array(
|
||||
'#type' => 'link',
|
||||
'#title' => $this->t('Continue'),
|
||||
'#attributes' => array('class' => array('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'] = array(
|
||||
'#tree' => TRUE,
|
||||
'#type' => 'details',
|
||||
);
|
||||
|
||||
// Ensure system.module's updates appear first.
|
||||
$build['start']['system'] = array();
|
||||
|
||||
$starting_updates = array();
|
||||
$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] = array(
|
||||
'#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] = array(
|
||||
'#type' => 'hidden',
|
||||
'#value' => $update['start'],
|
||||
);
|
||||
// Store the previous items in order to merge normal updates and
|
||||
// post_update functions together.
|
||||
$build['start'][$module] = array(
|
||||
'#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'] = array($module_update_key => $build['start'][$module_update_key]) + $build['start'];
|
||||
}
|
||||
}
|
||||
|
||||
// Warn the user if any updates were incompatible.
|
||||
if ($incompatible_updates_exist) {
|
||||
drupal_set_message($this->t('Some of the pending updates cannot be applied because their dependencies were not met.'), 'warning');
|
||||
}
|
||||
|
||||
if (empty($count)) {
|
||||
drupal_set_message($this->t('No pending updates.'));
|
||||
unset($build);
|
||||
$build['links'] = array(
|
||||
'#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'] = array(
|
||||
'#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)',
|
||||
array('@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', array('op' => 'run')))->setOption('base_url', $base_url);
|
||||
$build['link'] = array(
|
||||
'#type' => 'link',
|
||||
'#title' => $this->t('Apply pending updates'),
|
||||
'#attributes' => array('class' => array('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>.', array(
|
||||
':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.', array(':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>.', array(
|
||||
'@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'] = array(
|
||||
'#markup' => $message,
|
||||
);
|
||||
$build['links'] = array(
|
||||
'#theme' => 'links',
|
||||
'#links' => $this->helpfulLinks($request),
|
||||
);
|
||||
|
||||
// Output a list of info messages.
|
||||
if (!empty($_SESSION['update_results'])) {
|
||||
$all_messages = array();
|
||||
foreach ($_SESSION['update_results'] as $module => $updates) {
|
||||
if ($module != '#abort') {
|
||||
$module_has_message = FALSE;
|
||||
$info_messages = array();
|
||||
foreach ($updates as $name => $queries) {
|
||||
$messages = array();
|
||||
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[] = array(
|
||||
'#wrapper_attributes' => array('class' => array('success')),
|
||||
'#markup' => $query['query'],
|
||||
);
|
||||
}
|
||||
else {
|
||||
$messages[] = array(
|
||||
'#wrapper_attributes' => array('class' => array('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[] = array(
|
||||
'#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[] = array(
|
||||
'#type' => 'container',
|
||||
'#prefix' => '<h3>' . $this->t('@module module', array('@module' => $module)) . '</h3>',
|
||||
'#children' => $info_messages,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
if ($all_messages) {
|
||||
$build['query_messages'] = array(
|
||||
'#type' => 'container',
|
||||
'#children' => $all_messages,
|
||||
'#attributes' => array('class' => array('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 ? array('continue' => 1) : array();
|
||||
// @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'] = array(
|
||||
'#theme' => 'status_report',
|
||||
'#requirements' => $requirements,
|
||||
'#suffix' => $this->t('Check the messages and <a href=":url">try again</a>.', array(':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 = array(
|
||||
'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 = array(
|
||||
'#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 = array();
|
||||
|
||||
// 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 = array();
|
||||
foreach ($updates as $function => $update) {
|
||||
$dependency_map[$function] = !empty($update['reverse_paths']) ? array_keys($update['reverse_paths']) : array();
|
||||
}
|
||||
|
||||
// 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[] = array('update_do_one', array($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 += array(
|
||||
'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' => array('\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'] = array(
|
||||
'title' => $this->t('Front page'),
|
||||
'url' => Url::fromRoute('<front>')->setOption('base_url', $base_url),
|
||||
);
|
||||
if ($this->account->hasPermission('access administration pages')) {
|
||||
$links['admin-pages'] = array(
|
||||
'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 = array();
|
||||
$updates = update_get_update_list();
|
||||
foreach ($updates as $module => $update) {
|
||||
$return[$module] = $update['start'];
|
||||
}
|
||||
|
||||
return $return;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,109 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\system\Controller;
|
||||
|
||||
use Drupal\Component\Utility\Crypt;
|
||||
use Drupal\Component\Utility\Tags;
|
||||
use Drupal\Component\Utility\Unicode;
|
||||
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 = array();
|
||||
// Get the typed string from the URL, if it exists.
|
||||
if ($input = $request->query->get('q')) {
|
||||
$typed_string = Tags::explode($input);
|
||||
$typed_string = Unicode::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);
|
||||
}
|
||||
|
||||
}
|
48
web/core/modules/system/src/Controller/Http4xxController.php
Normal file
48
web/core/modules/system/src/Controller/Http4xxController.php
Normal file
|
@ -0,0 +1,48 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\system\Controller;
|
||||
|
||||
use Drupal\Core\Controller\ControllerBase;
|
||||
|
||||
/**
|
||||
* Controller for default HTTP 4xx responses.
|
||||
*/
|
||||
class Http4xxController extends ControllerBase {
|
||||
|
||||
/**
|
||||
* 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 404 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.'),
|
||||
];
|
||||
}
|
||||
|
||||
}
|
339
web/core/modules/system/src/Controller/SystemController.php
Normal file
339
web/core/modules/system/src/Controller/SystemController.php
Normal file
|
@ -0,0 +1,339 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\system\Controller;
|
||||
|
||||
use Drupal\Core\Cache\CacheableMetadata;
|
||||
use Drupal\Core\Controller\ControllerBase;
|
||||
use Drupal\Core\Entity\Query\QueryFactory;
|
||||
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 {
|
||||
|
||||
/**
|
||||
* The entity query factory object.
|
||||
*
|
||||
* @var \Drupal\Core\Entity\Query\QueryFactory
|
||||
*/
|
||||
protected $queryFactory;
|
||||
|
||||
/**
|
||||
* 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\Entity\Query\QueryFactory $queryFactory
|
||||
* The entity query object.
|
||||
* @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, QueryFactory $queryFactory, ThemeAccessCheck $theme_access, FormBuilderInterface $form_builder, ThemeHandlerInterface $theme_handler, MenuLinkTreeInterface $menu_link_tree) {
|
||||
$this->systemManager = $systemManager;
|
||||
$this->queryFactory = $queryFactory;
|
||||
$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('entity.query'),
|
||||
$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')) {
|
||||
drupal_set_message($this->t('One or more problems were detected with your Drupal installation. Check the <a href=":status">status report</a> for more information.', array(':status' => $this->url('system.status'))), 'error');
|
||||
}
|
||||
// Load all menu links below it.
|
||||
$parameters = new MenuTreeParameters();
|
||||
$parameters->setRoot($link_id)->excludeRoot()->setTopLevelOnly()->onlyEnabledLinks();
|
||||
$tree = $this->menuLinkTree->load(NULL, $parameters);
|
||||
$manipulators = array(
|
||||
array('callable' => 'menu.default_tree_manipulators:checkAccess'),
|
||||
array('callable' => 'menu.default_tree_manipulators:generateIndexAndSort'),
|
||||
);
|
||||
$tree = $this->menuLinkTree->transform($tree, $manipulators);
|
||||
$tree_access_cacheability = new CacheableMetadata();
|
||||
$blocks = array();
|
||||
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'] = array(
|
||||
'#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(array('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 = array('installed' => array(), 'uninstalled' => array());
|
||||
$admin_theme = $config->get('admin');
|
||||
$admin_theme_options = array();
|
||||
|
||||
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 = array($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 = array(
|
||||
'uri' => $themes[$theme_key]->info['screenshot'],
|
||||
'alt' => $this->t('Screenshot for @theme theme', array('@theme' => $theme->info['name'])),
|
||||
'title' => $this->t('Screenshot for @theme theme', array('@theme' => $theme->info['name'])),
|
||||
'attributes' => array('class' => array('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 = array();
|
||||
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[] = array(
|
||||
'title' => $this->t('Settings'),
|
||||
'url' => Url::fromRoute('system.theme_settings_theme', ['theme' => $theme->getName()]),
|
||||
'attributes' => array('title' => $this->t('Settings for @theme theme', array('@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[] = array(
|
||||
'title' => $this->t('Uninstall'),
|
||||
'url' => Url::fromRoute('system.theme_uninstall'),
|
||||
'query' => $query,
|
||||
'attributes' => array('title' => $this->t('Uninstall @theme theme', array('@theme' => $theme->info['name']))),
|
||||
);
|
||||
}
|
||||
$theme->operations[] = array(
|
||||
'title' => $this->t('Set as default'),
|
||||
'url' => Url::fromRoute('system.theme_set_default'),
|
||||
'query' => $query,
|
||||
'attributes' => array('title' => $this->t('Set @theme as default theme', array('@theme' => $theme->info['name']))),
|
||||
);
|
||||
}
|
||||
$admin_theme_options[$theme->getName()] = $theme->info['name'];
|
||||
}
|
||||
else {
|
||||
$theme->operations[] = array(
|
||||
'title' => $this->t('Install'),
|
||||
'url' => Url::fromRoute('system.theme_install'),
|
||||
'query' => $query,
|
||||
'attributes' => array('title' => $this->t('Install @theme theme', array('@theme' => $theme->info['name']))),
|
||||
);
|
||||
$theme->operations[] = array(
|
||||
'title' => $this->t('Install and set as default'),
|
||||
'url' => Url::fromRoute('system.theme_set_default'),
|
||||
'query' => $query,
|
||||
'attributes' => array('title' => $this->t('Install @theme as default theme', array('@theme' => $theme->info['name']))),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// Add notes to default and administration theme.
|
||||
$theme->notes = array();
|
||||
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 = array(
|
||||
'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 = array();
|
||||
$build[] = array(
|
||||
'#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 array('#theme' => 'status_report', '#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.', array(':phpinfo' => 'https://www.drupal.org/node/243993'));
|
||||
}
|
||||
return new Response($output);
|
||||
}
|
||||
|
||||
}
|
193
web/core/modules/system/src/Controller/ThemeController.php
Normal file
193
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')) {
|
||||
drupal_set_message($this->t('%theme is the default theme and cannot be uninstalled.', array('%theme' => $themes[$theme]->info['name'])), 'error');
|
||||
}
|
||||
else {
|
||||
$this->themeHandler->uninstall(array($theme));
|
||||
drupal_set_message($this->t('The %theme theme has been uninstalled.', array('%theme' => $themes[$theme]->info['name'])));
|
||||
}
|
||||
}
|
||||
else {
|
||||
drupal_set_message($this->t('The %theme theme was not found.', array('%theme' => $theme)), 'error');
|
||||
}
|
||||
|
||||
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(array($theme))) {
|
||||
$themes = $this->themeHandler->listInfo();
|
||||
drupal_set_message($this->t('The %theme theme has been installed.', array('%theme' => $themes[$theme]->info['name'])));
|
||||
}
|
||||
else {
|
||||
drupal_set_message($this->t('The %theme theme was not found.', array('%theme' => $theme)), 'error');
|
||||
}
|
||||
}
|
||||
catch (PreExistingConfigException $e) {
|
||||
$config_objects = $e->flattenConfigObjects($e->getConfigObjects());
|
||||
drupal_set_message(
|
||||
$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.',
|
||||
array(
|
||||
'%config_names' => implode(', ', $config_objects),
|
||||
'@extension' => $theme,
|
||||
)),
|
||||
'error'
|
||||
);
|
||||
}
|
||||
catch (UnmetDependenciesException $e) {
|
||||
drupal_set_message($e->getTranslatedMessage($this->getStringTranslation(), $theme), 'error');
|
||||
}
|
||||
|
||||
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(array($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) {
|
||||
drupal_set_message($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.', array(
|
||||
'%admin_theme' => $themes[$admin_theme]->info['name'],
|
||||
'%selected_theme' => $themes[$theme]->info['name'],
|
||||
)));
|
||||
}
|
||||
else {
|
||||
drupal_set_message($this->t('%theme is now the default theme.', array('%theme' => $themes[$theme]->info['name'])));
|
||||
}
|
||||
}
|
||||
else {
|
||||
drupal_set_message($this->t('The %theme theme was not found.', array('%theme' => $theme)), 'error');
|
||||
}
|
||||
|
||||
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 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);
|
||||
}
|
||||
|
||||
}
|
70
web/core/modules/system/src/CronController.php
Normal file
70
web/core/modules/system/src/CronController.php
Normal file
|
@ -0,0 +1,70 @@
|
|||
<?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()) {
|
||||
drupal_set_message($this->t('Cron ran successfully.'));
|
||||
}
|
||||
else {
|
||||
drupal_set_message($this->t('Cron run failed.'), 'error');
|
||||
}
|
||||
|
||||
return $this->redirect('system.status');
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,38 @@
|
|||
<?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 function checkAccess(EntityInterface $entity, $operation, AccountInterface $account) {
|
||||
// There are no restrictions on viewing a date format.
|
||||
if ($operation == 'view') {
|
||||
return AccessResult::allowed();
|
||||
}
|
||||
// Locked date formats cannot be updated or deleted.
|
||||
elseif (in_array($operation, array('update', 'delete'))) {
|
||||
if ($entity->isLocked()) {
|
||||
return AccessResult::forbidden()->addCacheableDependency($entity);
|
||||
}
|
||||
else {
|
||||
return parent::checkAccess($entity, $operation, $account)->addCacheableDependency($entity);
|
||||
}
|
||||
}
|
||||
|
||||
return parent::checkAccess($entity, $operation, $account);
|
||||
}
|
||||
|
||||
}
|
71
web/core/modules/system/src/DateFormatListBuilder.php
Normal file
71
web/core/modules/system/src/DateFormatListBuilder.php
Normal file
|
@ -0,0 +1,71 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\system;
|
||||
|
||||
use Drupal\Core\Config\Entity\ConfigEntityListBuilder;
|
||||
use Drupal\Core\Datetime\DateFormatterInterface;
|
||||
use Drupal\Core\Entity\EntityInterface;
|
||||
use Drupal\Core\Entity\EntityStorageInterface;
|
||||
use Drupal\Core\Entity\EntityTypeInterface;
|
||||
use Symfony\Component\DependencyInjection\ContainerInterface;
|
||||
|
||||
/**
|
||||
* Defines a class to build a listing of date format entities.
|
||||
*
|
||||
* @see \Drupal\system\Entity\DateFormat
|
||||
*/
|
||||
class DateFormatListBuilder extends ConfigEntityListBuilder {
|
||||
|
||||
/**
|
||||
* The date formatter service.
|
||||
*
|
||||
* @var \Drupal\Core\Datetime\DateFormatterInterface
|
||||
*/
|
||||
protected $dateFormatter;
|
||||
|
||||
/**
|
||||
* Constructs a new DateFormatListBuilder object.
|
||||
*
|
||||
* @param \Drupal\Core\Entity\EntityTypeInterface $entity_type
|
||||
* The entity type definition.
|
||||
* @param \Drupal\Core\Entity\EntityStorageInterface $storage
|
||||
* The entity storage class.
|
||||
* @param \Drupal\Core\Datetime\DateFormatterInterface $date_formatter
|
||||
* The date formatter service.
|
||||
*/
|
||||
public function __construct(EntityTypeInterface $entity_type, EntityStorageInterface $storage, DateFormatterInterface $date_formatter) {
|
||||
parent::__construct($entity_type, $storage);
|
||||
|
||||
$this->dateFormatter = $date_formatter;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static function createInstance(ContainerInterface $container, EntityTypeInterface $entity_type) {
|
||||
return new static(
|
||||
$entity_type,
|
||||
$container->get('entity.manager')->getStorage($entity_type->id()),
|
||||
$container->get('date.formatter')
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function buildHeader() {
|
||||
$header['label'] = t('Name');
|
||||
$header['pattern'] = t('Pattern');
|
||||
return $header + parent::buildHeader();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function buildRow(EntityInterface $entity) {
|
||||
$row['label'] = $entity->label();
|
||||
$row['pattern'] = $this->dateFormatter->format(REQUEST_TIME, $entity->id());
|
||||
return $row + parent::buildRow($entity);
|
||||
}
|
||||
|
||||
}
|
153
web/core/modules/system/src/Entity/Action.php
Normal file
153
web/core/modules/system/src/Entity/Action.php
Normal file
|
@ -0,0 +1,153 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\system\Entity;
|
||||
|
||||
use Drupal\Core\Config\Entity\ConfigEntityBase;
|
||||
use Drupal\Core\Config\Entity\ConfigEntityInterface;
|
||||
use Drupal\Core\Entity\EntityWithPluginCollectionInterface;
|
||||
use Drupal\system\ActionConfigEntityInterface;
|
||||
use Drupal\Core\Action\ActionPluginCollection;
|
||||
use Drupal\Component\Plugin\ConfigurablePluginInterface;
|
||||
|
||||
/**
|
||||
* Defines the configured action entity.
|
||||
*
|
||||
* @ConfigEntityType(
|
||||
* id = "action",
|
||||
* label = @Translation("Action"),
|
||||
* admin_permission = "administer actions",
|
||||
* entity_keys = {
|
||||
* "id" = "id",
|
||||
* "label" = "label"
|
||||
* },
|
||||
* config_export = {
|
||||
* "id",
|
||||
* "label",
|
||||
* "type",
|
||||
* "plugin",
|
||||
* "configuration",
|
||||
* }
|
||||
* )
|
||||
*/
|
||||
class Action extends ConfigEntityBase implements ActionConfigEntityInterface, EntityWithPluginCollectionInterface {
|
||||
|
||||
/**
|
||||
* The name (plugin ID) of the action.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $id;
|
||||
|
||||
/**
|
||||
* The label of the action.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $label;
|
||||
|
||||
/**
|
||||
* The action type.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $type;
|
||||
|
||||
/**
|
||||
* The configuration of the action.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $configuration = array();
|
||||
|
||||
/**
|
||||
* The plugin ID of the action.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $plugin;
|
||||
|
||||
/**
|
||||
* The plugin collection that stores action plugins.
|
||||
*
|
||||
* @var \Drupal\Core\Action\ActionPluginCollection
|
||||
*/
|
||||
protected $pluginCollection;
|
||||
|
||||
/**
|
||||
* Encapsulates the creation of the action's LazyPluginCollection.
|
||||
*
|
||||
* @return \Drupal\Component\Plugin\LazyPluginCollection
|
||||
* The action's plugin collection.
|
||||
*/
|
||||
protected function getPluginCollection() {
|
||||
if (!$this->pluginCollection) {
|
||||
$this->pluginCollection = new ActionPluginCollection(\Drupal::service('plugin.manager.action'), $this->plugin, $this->configuration);
|
||||
}
|
||||
return $this->pluginCollection;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getPluginCollections() {
|
||||
return array('configuration' => $this->getPluginCollection());
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getPlugin() {
|
||||
return $this->getPluginCollection()->get($this->plugin);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function setPlugin($plugin_id) {
|
||||
$this->plugin = $plugin_id;
|
||||
$this->getPluginCollection()->addInstanceId($plugin_id);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getPluginDefinition() {
|
||||
return $this->getPlugin()->getPluginDefinition();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function execute(array $entities) {
|
||||
return $this->getPlugin()->executeMultiple($entities);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function isConfigurable() {
|
||||
return $this->getPlugin() instanceof ConfigurablePluginInterface;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getType() {
|
||||
return $this->type;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static function sort(ConfigEntityInterface $a, ConfigEntityInterface $b) {
|
||||
/** @var \Drupal\system\ActionConfigEntityInterface $a */
|
||||
/** @var \Drupal\system\ActionConfigEntityInterface $b */
|
||||
$a_type = $a->getType();
|
||||
$b_type = $b->getType();
|
||||
if ($a_type != $b_type) {
|
||||
return strnatcasecmp($a_type, $b_type);
|
||||
}
|
||||
return parent::sort($a, $b);
|
||||
}
|
||||
|
||||
}
|
74
web/core/modules/system/src/Entity/Menu.php
Normal file
74
web/core/modules/system/src/Entity/Menu.php
Normal file
|
@ -0,0 +1,74 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\system\Entity;
|
||||
|
||||
use Drupal\Core\Config\Entity\ConfigEntityBase;
|
||||
use Drupal\system\MenuInterface;
|
||||
|
||||
/**
|
||||
* Defines the Menu configuration entity class.
|
||||
*
|
||||
* @ConfigEntityType(
|
||||
* id = "menu",
|
||||
* label = @Translation("Menu"),
|
||||
* handlers = {
|
||||
* "access" = "Drupal\system\MenuAccessControlHandler"
|
||||
* },
|
||||
* admin_permission = "administer menu",
|
||||
* entity_keys = {
|
||||
* "id" = "id",
|
||||
* "label" = "label"
|
||||
* },
|
||||
* config_export = {
|
||||
* "id",
|
||||
* "label",
|
||||
* "description",
|
||||
* "locked",
|
||||
* }
|
||||
* )
|
||||
*/
|
||||
class Menu extends ConfigEntityBase implements MenuInterface {
|
||||
|
||||
/**
|
||||
* The menu machine name.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $id;
|
||||
|
||||
/**
|
||||
* The human-readable name of the menu entity.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $label;
|
||||
|
||||
/**
|
||||
* The menu description.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $description;
|
||||
|
||||
/**
|
||||
* The locked status of this menu.
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
protected $locked = FALSE;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getDescription() {
|
||||
return $this->description;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function isLocked() {
|
||||
return (bool) $this->locked;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,39 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\system\EventSubscriber;
|
||||
|
||||
use Drupal\Core\Routing\RouteSubscriberBase;
|
||||
use Drupal\Core\Routing\RoutingEvents;
|
||||
use Symfony\Component\Routing\RouteCollection;
|
||||
|
||||
/**
|
||||
* Adds the _admin_route option to each admin route.
|
||||
*/
|
||||
class AdminRouteSubscriber extends RouteSubscriberBase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function alterRoutes(RouteCollection $collection) {
|
||||
foreach ($collection->all() as $route) {
|
||||
if (strpos($route->getPath(), '/admin') === 0 && !$route->hasOption('_admin_route')) {
|
||||
$route->setOption('_admin_route', TRUE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static function getSubscribedEvents() {
|
||||
$events = parent::getSubscribedEvents();
|
||||
|
||||
// Use a lower priority than \Drupal\field_ui\Routing\RouteSubscriber or
|
||||
// \Drupal\views\EventSubscriber\RouteSubscriber to ensure we add the option
|
||||
// to their routes.
|
||||
$events[RoutingEvents::ALTER] = array('onAlterRoutes', -200);
|
||||
|
||||
return $events;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,80 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\system\EventSubscriber;
|
||||
|
||||
use Drupal\Core\Cache\CacheTagsInvalidatorInterface;
|
||||
use Drupal\Core\Config\ConfigCrudEvent;
|
||||
use Drupal\Core\Config\ConfigEvents;
|
||||
use Drupal\Core\Extension\ThemeHandlerInterface;
|
||||
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
|
||||
|
||||
/**
|
||||
* A subscriber invalidating cache tags when system config objects are saved.
|
||||
*/
|
||||
class ConfigCacheTag implements EventSubscriberInterface {
|
||||
|
||||
/**
|
||||
* The theme handler.
|
||||
*
|
||||
* @var \Drupal\Core\Extension\ThemeHandlerInterface
|
||||
*/
|
||||
protected $themeHandler;
|
||||
|
||||
/**
|
||||
* The cache tags invalidator.
|
||||
*
|
||||
* @var \Drupal\Core\Cache\CacheTagsInvalidatorInterface
|
||||
*/
|
||||
protected $cacheTagsInvalidator;
|
||||
|
||||
/**
|
||||
* Constructs a ConfigCacheTag object.
|
||||
*
|
||||
* @param \Drupal\Core\Extension\ThemeHandlerInterface $theme_handler
|
||||
* The theme handler.
|
||||
* @param \Drupal\Core\Cache\CacheTagsInvalidatorInterface $cache_tags_invalidator
|
||||
* The cache tags invalidator.
|
||||
*/
|
||||
public function __construct(ThemeHandlerInterface $theme_handler, CacheTagsInvalidatorInterface $cache_tags_invalidator) {
|
||||
$this->themeHandler = $theme_handler;
|
||||
$this->cacheTagsInvalidator = $cache_tags_invalidator;
|
||||
}
|
||||
|
||||
/**
|
||||
* Invalidate cache tags when particular system config objects are saved.
|
||||
*
|
||||
* @param \Drupal\Core\Config\ConfigCrudEvent $event
|
||||
* The Event to process.
|
||||
*/
|
||||
public function onSave(ConfigCrudEvent $event) {
|
||||
// Changing the site settings may mean a different route is selected for the
|
||||
// front page. Additionally a change to the site name or similar must
|
||||
// invalidate the render cache since this could be used anywhere.
|
||||
if ($event->getConfig()->getName() === 'system.site') {
|
||||
$this->cacheTagsInvalidator->invalidateTags(['route_match', 'rendered']);
|
||||
}
|
||||
|
||||
// Theme configuration and global theme settings.
|
||||
if (in_array($event->getConfig()->getName(), ['system.theme', 'system.theme.global'], TRUE)) {
|
||||
$this->cacheTagsInvalidator->invalidateTags(['rendered']);
|
||||
}
|
||||
|
||||
// Theme-specific settings, check if this matches a theme settings
|
||||
// configuration object, in that case, clear the rendered cache tag.
|
||||
foreach (array_keys($this->themeHandler->listInfo()) as $theme_name) {
|
||||
if ($theme_name == $event->getConfig()->getName()) {
|
||||
$this->cacheTagsInvalidator->invalidateTags(['rendered']);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static function getSubscribedEvents() {
|
||||
$events[ConfigEvents::SAVE][] = ['onSave'];
|
||||
return $events;
|
||||
}
|
||||
|
||||
}
|
70
web/core/modules/system/src/FileDownloadController.php
Normal file
70
web/core/modules/system/src/FileDownloadController.php
Normal file
|
@ -0,0 +1,70 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\system;
|
||||
|
||||
use Drupal\Core\Controller\ControllerBase;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException;
|
||||
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
|
||||
use Symfony\Component\HttpFoundation\BinaryFileResponse;
|
||||
|
||||
/**
|
||||
* System file controller.
|
||||
*/
|
||||
class FileDownloadController extends ControllerBase {
|
||||
|
||||
/**
|
||||
* Handles private file transfers.
|
||||
*
|
||||
* Call modules that implement hook_file_download() to find out if a file is
|
||||
* accessible and what headers it should be transferred with. If one or more
|
||||
* modules returned headers the download will start with the returned headers.
|
||||
* If a module returns -1 an AccessDeniedHttpException will be thrown. If the
|
||||
* file exists but no modules responded an AccessDeniedHttpException will be
|
||||
* thrown. If the file does not exist a NotFoundHttpException will be thrown.
|
||||
*
|
||||
* @see hook_file_download()
|
||||
*
|
||||
* @param \Symfony\Component\HttpFoundation\Request $request
|
||||
* The request object.
|
||||
* @param string $scheme
|
||||
* The file scheme, defaults to 'private'.
|
||||
*
|
||||
* @return \Symfony\Component\HttpFoundation\BinaryFileResponse
|
||||
* The transferred file as response.
|
||||
*
|
||||
* @throws \Symfony\Component\HttpKernel\Exception\NotFoundHttpException
|
||||
* Thrown when the requested file does not exist.
|
||||
* @throws \Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException
|
||||
* Thrown when the user does not have access to the file.
|
||||
*/
|
||||
public function download(Request $request, $scheme = 'private') {
|
||||
$target = $request->query->get('file');
|
||||
// Merge remaining path arguments into relative file path.
|
||||
$uri = $scheme . '://' . $target;
|
||||
|
||||
if (file_stream_wrapper_valid_scheme($scheme) && file_exists($uri)) {
|
||||
// Let other modules provide headers and controls access to the file.
|
||||
$headers = $this->moduleHandler()->invokeAll('file_download', array($uri));
|
||||
|
||||
foreach ($headers as $result) {
|
||||
if ($result == -1) {
|
||||
throw new AccessDeniedHttpException();
|
||||
}
|
||||
}
|
||||
|
||||
if (count($headers)) {
|
||||
// \Drupal\Core\EventSubscriber\FinishResponseSubscriber::onRespond()
|
||||
// sets response as not cacheable if the Cache-Control header is not
|
||||
// already modified. We pass in FALSE for non-private schemes for the
|
||||
// $public parameter to make sure we don't change the headers.
|
||||
return new BinaryFileResponse($uri, 200, $headers, $scheme !== 'private');
|
||||
}
|
||||
|
||||
throw new AccessDeniedHttpException();
|
||||
}
|
||||
|
||||
throw new NotFoundHttpException();
|
||||
}
|
||||
|
||||
}
|
132
web/core/modules/system/src/Form/CronForm.php
Normal file
132
web/core/modules/system/src/Form/CronForm.php
Normal file
|
@ -0,0 +1,132 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\system\Form;
|
||||
|
||||
use Drupal\Core\Config\ConfigFactoryInterface;
|
||||
use Drupal\Core\CronInterface;
|
||||
use Drupal\Core\Datetime\DateFormatterInterface;
|
||||
use Drupal\Core\Extension\ModuleHandlerInterface;
|
||||
use Drupal\Core\Form\FormBase;
|
||||
use Drupal\Core\Form\FormStateInterface;
|
||||
use Drupal\Core\State\StateInterface;
|
||||
use Symfony\Component\DependencyInjection\ContainerInterface;
|
||||
|
||||
/**
|
||||
* Configure cron settings for this site.
|
||||
*/
|
||||
class CronForm extends FormBase {
|
||||
|
||||
/**
|
||||
* Stores the state storage service.
|
||||
*
|
||||
* @var \Drupal\Core\State\StateInterface
|
||||
*/
|
||||
protected $state;
|
||||
|
||||
/**
|
||||
* The cron service.
|
||||
*
|
||||
* @var \Drupal\Core\CronInterface
|
||||
*/
|
||||
protected $cron;
|
||||
|
||||
/**
|
||||
* The date formatter service.
|
||||
*
|
||||
* @var \Drupal\Core\Datetime\DateFormatterInterface
|
||||
*/
|
||||
protected $dateFormatter;
|
||||
|
||||
/**
|
||||
* The module handler service.
|
||||
*
|
||||
* @var \Drupal\Core\Extension\ModuleHandlerInterface $moduleHandler
|
||||
*/
|
||||
protected $moduleHandler;
|
||||
|
||||
/**
|
||||
* Constructs a CronForm object.
|
||||
*
|
||||
* @param \Drupal\Core\Config\ConfigFactoryInterface $config_factory
|
||||
* The factory for configuration objects.
|
||||
* @param \Drupal\Core\State\StateInterface $state
|
||||
* The state key value store.
|
||||
* @param \Drupal\Core\CronInterface $cron
|
||||
* The cron service.
|
||||
* @param \Drupal\Core\Datetime\DateFormatterInterface $date_formatter
|
||||
* The date formatter service.
|
||||
* @param \Drupal\Core\Extension\ModuleHandlerInterface $module_handler
|
||||
* The module handler service.
|
||||
*/
|
||||
public function __construct(ConfigFactoryInterface $config_factory, StateInterface $state, CronInterface $cron, DateFormatterInterface $date_formatter, ModuleHandlerInterface $module_handler) {
|
||||
$this->state = $state;
|
||||
$this->cron = $cron;
|
||||
$this->dateFormatter = $date_formatter;
|
||||
$this->moduleHandler = $module_handler;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static function create(ContainerInterface $container) {
|
||||
return new static(
|
||||
$container->get('config.factory'),
|
||||
$container->get('state'),
|
||||
$container->get('cron'),
|
||||
$container->get('date.formatter'),
|
||||
$container->get('module_handler')
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getFormId() {
|
||||
return 'system_cron_settings';
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function buildForm(array $form, FormStateInterface $form_state) {
|
||||
$form['description'] = array(
|
||||
'#markup' => '<p>' . t('Cron takes care of running periodic tasks like checking for updates and indexing content for search.') . '</p>',
|
||||
);
|
||||
$form['run'] = array(
|
||||
'#type' => 'submit',
|
||||
'#value' => t('Run cron'),
|
||||
);
|
||||
$status = '<p>' . $this->t('Last run: %time ago.', array('%time' => $this->dateFormatter->formatTimeDiffSince($this->state->get('system.cron_last')))) . '</p>';
|
||||
$form['status'] = array(
|
||||
'#markup' => $status,
|
||||
);
|
||||
|
||||
$cron_url = $this->url('system.cron', array('key' => $this->state->get('system.cron_key')), array('absolute' => TRUE));
|
||||
$form['cron_url'] = array(
|
||||
'#markup' => '<p>' . t('To run cron from outside the site, go to <a href=":cron">@cron</a>', array(':cron' => $cron_url, '@cron' => $cron_url)) . '</p>',
|
||||
);
|
||||
|
||||
if (!$this->moduleHandler->moduleExists('automated_cron')) {
|
||||
$form['cron'] = array(
|
||||
'#markup' => $this->t('Enable the <em>Automated Cron</em> module to allow cron execution at the end of a server response.'),
|
||||
);
|
||||
}
|
||||
|
||||
return $form;
|
||||
}
|
||||
|
||||
/**
|
||||
* Runs cron and reloads the page.
|
||||
*/
|
||||
public function submitForm(array &$form, FormStateInterface $form_state) {
|
||||
// Run cron manually from Cron form.
|
||||
if ($this->cron->run()) {
|
||||
drupal_set_message(t('Cron ran successfully.'));
|
||||
}
|
||||
else {
|
||||
drupal_set_message(t('Cron run failed.'), 'error');
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show more
Reference in a new issue