updated core to 8.6.3
@@ -1639,16 +1639,16 @@
|
||||
},
|
||||
{
|
||||
"name": "drupal/core",
|
||||
"version": "8.6.2",
|
||||
"version": "8.6.3",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/drupal/core.git",
|
||||
"reference": "356292934802bb1aecc478e88a3cba77442d7c62"
|
||||
"reference": "9e9a1dd9e280ebaf10622217e54448b529167965"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/drupal/core/zipball/356292934802bb1aecc478e88a3cba77442d7c62",
|
||||
"reference": "356292934802bb1aecc478e88a3cba77442d7c62",
|
||||
"url": "https://api.github.com/repos/drupal/core/zipball/9e9a1dd9e280ebaf10622217e54448b529167965",
|
||||
"reference": "9e9a1dd9e280ebaf10622217e54448b529167965",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -1814,7 +1814,7 @@
|
||||
"jcalderonzumba/gastonjs": "^1.0.2",
|
||||
"jcalderonzumba/mink-phantomjs-driver": "^0.3.1",
|
||||
"mikey179/vfsstream": "^1.2",
|
||||
"phpspec/prophecy": "^1.4",
|
||||
"phpspec/prophecy": "^1.7",
|
||||
"phpunit/phpunit": "^4.8.35 || ^6.5",
|
||||
"symfony/css-selector": "^3.4.0",
|
||||
"symfony/debug": "^3.4.0",
|
||||
@@ -1873,7 +1873,7 @@
|
||||
"GPL-2.0-or-later"
|
||||
],
|
||||
"description": "Drupal is an open source content management platform powering millions of websites and applications.",
|
||||
"time": "2018-10-17T22:19:50+00:00"
|
||||
"time": "2018-11-07T14:45:40+00:00"
|
||||
},
|
||||
{
|
||||
"name": "drush/drush",
|
||||
|
||||
@@ -11,7 +11,10 @@
|
||||
"no-duplicate-selectors": null,
|
||||
"no-unknown-animations": true,
|
||||
"media-feature-name-no-unknown": [true, {
|
||||
"ignoreMediaFeatureNames": ["prefers-reduced-motion"]
|
||||
"ignoreMediaFeatureNames": [
|
||||
"prefers-reduced-motion",
|
||||
"min--moz-device-pixel-ratio"
|
||||
]
|
||||
}],
|
||||
"number-leading-zero": "always",
|
||||
"plugin/no-browser-hacks": [true, {
|
||||
|
||||
@@ -113,7 +113,6 @@ CKEditor
|
||||
|
||||
Classy
|
||||
- David Hernandez 'davidhernandez' https://www.drupal.org/u/davidhernandez
|
||||
- Morten Birch Heide-Jørgensen 'mortendk' https://www.drupal.org/u/mortendk
|
||||
|
||||
Color
|
||||
- ?
|
||||
@@ -475,6 +474,7 @@ their responsibilities. The initiative coordinators for Drupal 8 are:
|
||||
API-first Initiative
|
||||
- Wim Leers 'Wim Leers' https://www.drupal.org/u/wim-leers
|
||||
- Mateu Aguiló Bosch 'e0ipso' https://www.drupal.org/u/e0ipso
|
||||
- Gabe Sullice 'gabesullice' https://www.drupal.org/u/gabesullice
|
||||
|
||||
Admin UI & JavaScript Modernisation Initiative
|
||||
- Angela Byron 'webchick' https://www.drupal.org/u/webchick
|
||||
|
||||
@@ -64,15 +64,51 @@ following the instructions in the INTRODUCTION section at the top of this file:
|
||||
Enable the "Put site into maintenance mode" checkbox and save the
|
||||
configuration.
|
||||
|
||||
3. Remove the 'core' and 'vendor' directories. Also remove all of the files
|
||||
in the top-level directory, except any that you added manually.
|
||||
3. Determine if your project is managed by Composer.
|
||||
|
||||
If you made modifications to files like .htaccess, composer.json, or
|
||||
robots.txt you will need to re-apply them from your backup, after the new
|
||||
files are in place.
|
||||
On a typical Unix/Linux command line, this can be determined by running the
|
||||
following command (replace /PATH/TO/composer with the appropriate location
|
||||
for your system):
|
||||
|
||||
Sometimes an update includes changes to default.settings.php (this will be
|
||||
noted in the release notes). If that's the case, follow these steps:
|
||||
/PATH/TO/composer info drupal/core
|
||||
|
||||
If this is successful, your project is managed by Composer.
|
||||
|
||||
If you don't have Composer installed or access to the command line, you can
|
||||
check the contents of composer.json. If "drupal/core" is present in the
|
||||
"require" section of your composer.json file, then the project is managed by
|
||||
Composer.
|
||||
|
||||
If the project is not managed by Composer, follow the steps under "UPDATING
|
||||
CODE WITHOUT COMPOSER", otherwise go to "UPDATING CODE WITH COMPOSER".
|
||||
|
||||
UPDATING CODE WITH COMPOSER
|
||||
---------------------------
|
||||
1. On a typical Unix/Linux command line, run the following command from the root
|
||||
directory (replace /PATH/TO/composer with the appropriate location for your
|
||||
system):
|
||||
|
||||
/PATH/TO/composer update
|
||||
|
||||
Note, if Composer is not installed you will need to install it in order to
|
||||
update Drupal.
|
||||
|
||||
Note, if you want to only update drupal/core the following command will
|
||||
probably work:
|
||||
|
||||
/PATH/TO/composer update drupal/core symfony/* --with-all-dependencies
|
||||
|
||||
2. Check the release notes for the updated version of Drupal to find out if
|
||||
there is a change to default.settings.php.
|
||||
|
||||
You can find the release notes for your version at
|
||||
https://www.drupal.org/project/drupal. At bottom of the project page under
|
||||
"Downloads" use the link for your version of Drupal to view the release
|
||||
notes. If your version is not listed, use the 'View all releases' link. From
|
||||
this page you can scroll down or use the filter to find your version and its
|
||||
release notes.
|
||||
|
||||
If there is a change to default.settings.php, follow these steps:
|
||||
|
||||
- Locate your settings.php file in the /sites/* directory. (Typically
|
||||
sites/default.)
|
||||
@@ -87,16 +123,32 @@ following the instructions in the INTRODUCTION section at the top of this file:
|
||||
database information, and you will also want to copy in any other
|
||||
customizations you have added.
|
||||
|
||||
You can find the release notes for your version at
|
||||
https://www.drupal.org/project/drupal. At bottom of the project page under
|
||||
"Downloads" use the link for your version of Drupal to view the release
|
||||
notes. If your version is not listed, use the 'View all releases' link. From
|
||||
this page you can scroll down or use the filter to find your version and its
|
||||
release notes.
|
||||
3. Determine if there are any modifications to files such as .htaccess or
|
||||
robots.txt and re-apply them. The Drupal Scaffold composer plugin
|
||||
(https://github.com/drupal-composer/drupal-scaffold) can help you with
|
||||
excluding files you'd like to always preserve when updating Drupal.
|
||||
|
||||
4. Download the latest Drupal 8.x.x release from https://www.drupal.org to a
|
||||
directory outside of your web root. Extract the archive and copy the files
|
||||
into your Drupal directory.
|
||||
4. Go to the "UPLOADING THE CODE" section
|
||||
|
||||
UPDATING CODE WITHOUT COMPOSER
|
||||
------------------------------
|
||||
1. Remove the 'core' and 'vendor' directories. Also remove all of the files
|
||||
in the top-level directory, except any that you added manually.
|
||||
|
||||
If you made modifications to files like .htaccess, composer.json, or
|
||||
robots.txt you will need to re-apply them from your backup, after the new
|
||||
files are in place.
|
||||
|
||||
This should leave you with the modules, profiles, sites, and themes
|
||||
directories. These directories should only contain code that you've used to
|
||||
extend Drupal.
|
||||
|
||||
2. Download the latest Drupal 8.x.x release from https://www.drupal.org/download
|
||||
to a directory outside of your web root. Extract the archive and copy the
|
||||
files into your Drupal directory.
|
||||
|
||||
Copy all the files, but do not accidentally overwrite your modules, profiles,
|
||||
sites, or themes directories.
|
||||
|
||||
On a typical Unix/Linux command line, use the following commands to download
|
||||
and extract:
|
||||
@@ -110,13 +162,60 @@ following the instructions in the INTRODUCTION section at the top of this file:
|
||||
cp -R drupal-x.y.z/* drupal-x.y.z/.htaccess /path/to/your/installation
|
||||
|
||||
If you do not have command line access to your server, download the archive
|
||||
from https://www.drupal.org using your web browser, extract it, and then use
|
||||
an FTP client to upload the files to your web root.
|
||||
from https://www.drupal.org using your web browser and extract it locally.
|
||||
|
||||
5. Re-apply any modifications to files such as .htaccess, composer.json, or
|
||||
robots.txt.
|
||||
3. Check the release notes for the updated version of Drupal to find out if
|
||||
there is a change to default.settings.php.
|
||||
|
||||
6. Run update.php by visiting http://www.example.com/update.php (replace
|
||||
You can find the release notes for your updated version at
|
||||
https://www.drupal.org/project/drupal. At bottom of the project page under
|
||||
"Downloads" use the link for your updated version of Drupal to view the
|
||||
release notes. If your updated version is not listed, use the 'View all
|
||||
releases' link. From this page you can scroll down or use the filter to find
|
||||
your updated version and its release notes.
|
||||
|
||||
If there is a change to default.settings.php, follow these steps:
|
||||
|
||||
- Locate your settings.php file in the /sites/* directory. (Typically
|
||||
sites/default.)
|
||||
|
||||
- Make a backup copy of your settings.php file, with a different file name.
|
||||
|
||||
- Make a copy of the new default.settings.php file, and name the copy
|
||||
settings.php (overwriting your previous settings.php file).
|
||||
|
||||
- Copy the custom and site-specific entries from the backup you made into the
|
||||
new settings.php file. You will definitely need the lines giving the
|
||||
database information, and you will also want to copy in any other
|
||||
customizations you have added.
|
||||
|
||||
4. Re-apply any modifications to files such as .htaccess or robots.txt.
|
||||
|
||||
If you have added requirements in composer.json, it is recommended that you
|
||||
re-add the requirements using Composer instead of applying the changes by
|
||||
hand. For example, on a typical Unix/Linux command line, to reinstall the
|
||||
Address module and its dependencies run (replace /PATH/TO/composer with the
|
||||
appropriate location for your system):
|
||||
|
||||
/PATH/TO/composer require drupal/address
|
||||
|
||||
If you do not have command line access to your server, you will need to run
|
||||
the Composer commands locally before uploading the file system to your
|
||||
server.
|
||||
|
||||
5. Go to the "UPLOADING THE CODE" section
|
||||
|
||||
UPLOADING THE CODE
|
||||
------------------
|
||||
1. If you updated the code in a different environment from where it is running
|
||||
you need to upload the files to your web root including the vendor/
|
||||
directory.
|
||||
|
||||
2. Go to the "UPDATING THE DATABASE" section
|
||||
|
||||
UPDATING THE DATABASE
|
||||
---------------------
|
||||
1. Run update.php by visiting http://www.example.com/update.php (replace
|
||||
www.example.com with your domain name). This will update the core database
|
||||
tables.
|
||||
|
||||
@@ -133,12 +232,11 @@ following the instructions in the INTRODUCTION section at the top of this file:
|
||||
- Once the update is done, $settings['update_free_access'] must be reverted
|
||||
to FALSE.
|
||||
|
||||
7. Go to Administration > Reports > Status report. Verify that everything is
|
||||
2. Go to Administration > Reports > Status report. Verify that everything is
|
||||
working as expected.
|
||||
|
||||
8. Ensure that $settings['update_free_access'] is FALSE in settings.php.
|
||||
3. Ensure that $settings['update_free_access'] is FALSE in settings.php.
|
||||
|
||||
9. Go to Administration > Configuration > Development > Maintenance mode.
|
||||
4. Go to Administration > Configuration > Development > Maintenance mode.
|
||||
Disable the "Put site into maintenance mode" checkbox and save the
|
||||
configuration.
|
||||
|
||||
|
||||
|
Before Width: | Height: | Size: 3.1 KiB After Width: | Height: | Size: 4.2 KiB |
|
Before Width: | Height: | Size: 11 KiB After Width: | Height: | Size: 14 KiB |
@@ -3,13 +3,13 @@
|
||||
For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
|
||||
*/
|
||||
CKEDITOR.dialog.add("image2",function(f){function C(){var a=this.getValue().match(D);(a=!(!a||0===parseInt(a[1],10)))||alert(c.invalidLength.replace("%1",c[this.id]).replace("%2","px"));return a}function N(){function a(a,c){q.push(b.once(a,function(a){for(var b;b=q.pop();)b.removeListener();c(a)}))}var b=r.createElement("img"),q=[];return function(q,c,e){a("load",function(){var a=E(b);c.call(e,b,a.width,a.height)});a("error",function(){c(null)});a("abort",function(){c(null)});b.setAttribute("src",
|
||||
(w.baseHref||"")+q+"?"+Math.random().toString(16).substring(2))}}function F(){var a=this.getValue();t(!1);a!==x.data.src?(G(a,function(a,b,c){t(!0);if(!a)return k(!1);g.setValue(!1===f.config.image2_prefillDimensions?0:b);h.setValue(!1===f.config.image2_prefillDimensions?0:c);u=b;v=c;k(H.checkHasNaturalRatio(a))}),l=!0):l?(t(!0),g.setValue(m),h.setValue(n),l=!1):t(!0)}function I(){if(e){var a=this.getValue();if(a&&(a.match(D)||k(!1),"0"!==a)){var b="width"==this.id,c=m||u,d=n||v,a=b?Math.round(a/
|
||||
c*d):Math.round(a/d*c);isNaN(a)||(b?h:g).setValue(a)}}}function k(a){if(d){if("boolean"==typeof a){if(y)return;e=a}else a=g.getValue(),y=!0,(e=!e)&&a&&(a*=n/m,isNaN(a)||h.setValue(Math.round(a)));d[e?"removeClass":"addClass"]("cke_btn_unlocked");d.setAttribute("aria-checked",e);CKEDITOR.env.hc&&d.getChild(0).setHtml(e?CKEDITOR.env.ie?"■":"▣":CKEDITOR.env.ie?"□":"▢")}}function t(a){a=a?"enable":"disable";g[a]();h[a]()}var D=/(^\s*(\d+)(px)?\s*$)|^$/i,J=CKEDITOR.tools.getNextId(),K=CKEDITOR.tools.getNextId(),
|
||||
(w.baseHref||"")+q+"?"+Math.random().toString(16).substring(2))}}function F(){var a=this.getValue();t(!1);a!==x.data.src?(G(a,function(a,b,c){t(!0);if(!a)return m(!1);g.setValue(!1===f.config.image2_prefillDimensions?0:b);h.setValue(!1===f.config.image2_prefillDimensions?0:c);u=k=b;v=l=c;m(H.checkHasNaturalRatio(a))}),n=!0):n?(t(!0),g.setValue(k),h.setValue(l),n=!1):t(!0)}function I(){if(e){var a=this.getValue();if(a&&(a.match(D)||m(!1),"0"!==a)){var b="width"==this.id,c=k||u,d=l||v,a=b?Math.round(a/
|
||||
c*d):Math.round(a/d*c);isNaN(a)||(b?h:g).setValue(a)}}}function m(a){if(d){if("boolean"==typeof a){if(y)return;e=a}else a=g.getValue(),y=!0,(e=!e)&&a&&(a*=l/k,isNaN(a)||h.setValue(Math.round(a)));d[e?"removeClass":"addClass"]("cke_btn_unlocked");d.setAttribute("aria-checked",e);CKEDITOR.env.hc&&d.getChild(0).setHtml(e?CKEDITOR.env.ie?"■":"▣":CKEDITOR.env.ie?"□":"▢")}}function t(a){a=a?"enable":"disable";g[a]();h[a]()}var D=/(^\s*(\d+)(px)?\s*$)|^$/i,J=CKEDITOR.tools.getNextId(),K=CKEDITOR.tools.getNextId(),
|
||||
b=f.lang.image2,c=f.lang.common,O=(new CKEDITOR.template('\x3cdiv\x3e\x3ca href\x3d"javascript:void(0)" tabindex\x3d"-1" title\x3d"'+b.lockRatio+'" class\x3d"cke_btn_locked" id\x3d"{lockButtonId}" role\x3d"checkbox"\x3e\x3cspan class\x3d"cke_icon"\x3e\x3c/span\x3e\x3cspan class\x3d"cke_label"\x3e'+b.lockRatio+'\x3c/span\x3e\x3c/a\x3e\x3ca href\x3d"javascript:void(0)" tabindex\x3d"-1" title\x3d"'+b.resetSize+'" class\x3d"cke_btn_reset" id\x3d"{resetButtonId}" role\x3d"button"\x3e\x3cspan class\x3d"cke_label"\x3e'+
|
||||
b.resetSize+"\x3c/span\x3e\x3c/a\x3e\x3c/div\x3e")).output({lockButtonId:J,resetButtonId:K}),H=CKEDITOR.plugins.image2,w=f.config,z=!(!w.filebrowserImageBrowseUrl&&!w.filebrowserBrowseUrl),A=f.widgets.registered.image.features,E=H.getNatural,r,x,L,G,m,n,u,v,l,e,y,d,p,g,h,B,M=[{id:"src",type:"text",label:c.url,onKeyup:F,onChange:F,setup:function(a){this.setValue(a.data.src)},commit:function(a){a.setData("src",this.getValue())},validate:CKEDITOR.dialog.validate.notEmpty(b.urlMissing)}];z&&M.push({type:"button",
|
||||
id:"browse",style:"display:inline-block;margin-top:14px;",align:"center",label:f.lang.common.browseServer,hidden:!0,filebrowser:"info:src"});return{title:b.title,minWidth:250,minHeight:100,onLoad:function(){r=this._.element.getDocument();G=N()},onShow:function(){x=this.widget;L=x.parts.image;l=y=e=!1;B=E(L);u=m=B.width;v=n=B.height},contents:[{id:"info",label:b.infoTab,elements:[{type:"vbox",padding:0,children:[{type:"hbox",widths:["100%"],className:"cke_dialog_image_url",children:M}]},{id:"alt",
|
||||
b.resetSize+"\x3c/span\x3e\x3c/a\x3e\x3c/div\x3e")).output({lockButtonId:J,resetButtonId:K}),H=CKEDITOR.plugins.image2,w=f.config,z=!(!w.filebrowserImageBrowseUrl&&!w.filebrowserBrowseUrl),A=f.widgets.registered.image.features,E=H.getNatural,r,x,L,G,k,l,u,v,n,e,y,d,p,g,h,B,M=[{id:"src",type:"text",label:c.url,onKeyup:F,onChange:F,setup:function(a){this.setValue(a.data.src)},commit:function(a){a.setData("src",this.getValue())},validate:CKEDITOR.dialog.validate.notEmpty(b.urlMissing)}];z&&M.push({type:"button",
|
||||
id:"browse",style:"display:inline-block;margin-top:14px;",align:"center",label:f.lang.common.browseServer,hidden:!0,filebrowser:"info:src"});return{title:b.title,minWidth:250,minHeight:100,onLoad:function(){r=this._.element.getDocument();G=N()},onShow:function(){x=this.widget;L=x.parts.image;n=y=e=!1;B=E(L);u=k=B.width;v=l=B.height},contents:[{id:"info",label:b.infoTab,elements:[{type:"vbox",padding:0,children:[{type:"hbox",widths:["100%"],className:"cke_dialog_image_url",children:M}]},{id:"alt",
|
||||
type:"text",label:b.alt,setup:function(a){this.setValue(a.data.alt)},commit:function(a){a.setData("alt",this.getValue())},validate:!0===f.config.image2_altRequired?CKEDITOR.dialog.validate.notEmpty(b.altMissing):null},{type:"hbox",widths:["25%","25%","50%"],requiredContent:A.dimension.requiredContent,children:[{type:"text",width:"45px",id:"width",label:c.width,validate:C,onKeyUp:I,onLoad:function(){g=this},setup:function(a){this.setValue(a.data.width)},commit:function(a){a.setData("width",this.getValue())}},
|
||||
{type:"text",id:"height",width:"45px",label:c.height,validate:C,onKeyUp:I,onLoad:function(){h=this},setup:function(a){this.setValue(a.data.height)},commit:function(a){a.setData("height",this.getValue())}},{id:"lock",type:"html",style:"margin-top:18px;width:40px;height:20px;",onLoad:function(){function a(a){a.on("mouseover",function(){this.addClass("cke_btn_over")},a);a.on("mouseout",function(){this.removeClass("cke_btn_over")},a)}var b=this.getDialog();d=r.getById(J);p=r.getById(K);d&&(b.addFocusable(d,
|
||||
4+z),d.on("click",function(a){k();a.data&&a.data.preventDefault()},this.getDialog()),a(d));p&&(b.addFocusable(p,5+z),p.on("click",function(a){l?(g.setValue(u),h.setValue(v)):(g.setValue(m),h.setValue(n));a.data&&a.data.preventDefault()},this),a(p))},setup:function(a){k(a.data.lock)},commit:function(a){a.setData("lock",e)},html:O}]},{type:"hbox",id:"alignment",requiredContent:A.align.requiredContent,children:[{id:"align",type:"radio",items:[[c.alignNone,"none"],[c.left,"left"],[c.center,"center"],
|
||||
4+z),d.on("click",function(a){m();a.data&&a.data.preventDefault()},this.getDialog()),a(d));p&&(b.addFocusable(p,5+z),p.on("click",function(a){n?(g.setValue(u),h.setValue(v)):(g.setValue(k),h.setValue(l));a.data&&a.data.preventDefault()},this),a(p))},setup:function(a){m(a.data.lock)},commit:function(a){a.setData("lock",e)},html:O}]},{type:"hbox",id:"alignment",requiredContent:A.align.requiredContent,children:[{id:"align",type:"radio",items:[[c.alignNone,"none"],[c.left,"left"],[c.center,"center"],
|
||||
[c.right,"right"]],label:c.align,setup:function(a){this.setValue(a.data.align)},commit:function(a){a.setData("align",this.getValue())}}]},{id:"hasCaption",type:"checkbox",label:b.captioned,requiredContent:A.caption.requiredContent,setup:function(a){this.setValue(a.data.hasCaption)},commit:function(a){a.setData("hasCaption",this.getValue())}}]},{id:"Upload",hidden:!0,filebrowser:"uploadButton",label:b.uploadTab,elements:[{type:"file",id:"upload",label:b.btnUpload,style:"height:40px"},{type:"fileButton",
|
||||
id:"uploadButton",filebrowser:"info:src",label:b.btnUpload,"for":["Upload","upload"]}]}]}});
|
||||
|
Before Width: | Height: | Size: 3.1 KiB After Width: | Height: | Size: 4.2 KiB |
|
Before Width: | Height: | Size: 11 KiB After Width: | Height: | Size: 14 KiB |
@@ -125,7 +125,7 @@ if ($is_allowed) {
|
||||
$links = $results['tasks'];
|
||||
}
|
||||
else {
|
||||
// Since this is being called outsite of the primary front controller,
|
||||
// Since this is being called outside of the primary front controller,
|
||||
// the base_url needs to be set explicitly to ensure that links are
|
||||
// relative to the site root.
|
||||
// @todo Simplify with https://www.drupal.org/node/2548095
|
||||
|
||||
@@ -59,7 +59,7 @@
|
||||
"jcalderonzumba/mink-phantomjs-driver": "^0.3.1",
|
||||
"mikey179/vfsStream": "^1.2",
|
||||
"phpunit/phpunit": "^4.8.35 || ^6.5",
|
||||
"phpspec/prophecy": "^1.4",
|
||||
"phpspec/prophecy": "^1.7",
|
||||
"symfony/css-selector": "^3.4.0",
|
||||
"symfony/phpunit-bridge": "^3.4.3",
|
||||
"symfony/debug": "^3.4.0"
|
||||
|
||||
@@ -24,10 +24,10 @@ classList:
|
||||
|
||||
ckeditor:
|
||||
remote: https://github.com/ckeditor/ckeditor-dev
|
||||
version: "4.10.0"
|
||||
version: "4.10.1"
|
||||
license:
|
||||
name: GNU-GPL-2.0-or-later
|
||||
url: https://github.com/ckeditor/ckeditor-dev/blob/4.10.0/LICENSE.md
|
||||
url: https://github.com/ckeditor/ckeditor-dev/blob/4.10.1/LICENSE.md
|
||||
gpl-compatible: true
|
||||
js:
|
||||
assets/vendor/ckeditor/ckeditor.js: { preprocess: false, minified: true }
|
||||
|
||||
@@ -431,9 +431,7 @@ services:
|
||||
factory: Drupal\Core\Site\Settings::getInstance
|
||||
state:
|
||||
class: Drupal\Core\State\State
|
||||
arguments: ['@keyvalue', '@cache.bootstrap', '@lock']
|
||||
tags:
|
||||
- { name: needs_destruction }
|
||||
arguments: ['@keyvalue']
|
||||
queue:
|
||||
class: Drupal\Core\Queue\QueueFactory
|
||||
arguments: ['@settings']
|
||||
|
||||
@@ -572,14 +572,14 @@ function drupal_get_user_timezone() {
|
||||
* @param $message
|
||||
* The error message.
|
||||
* @param $filename
|
||||
* The filename that the error was raised in.
|
||||
* (optional) The filename that the error was raised in.
|
||||
* @param $line
|
||||
* The line number the error was raised at.
|
||||
* (optional) The line number the error was raised at.
|
||||
* @param $context
|
||||
* An array that points to the active symbol table at the point the error
|
||||
* occurred.
|
||||
* (optional) An array that points to the active symbol table at the point the
|
||||
* error occurred.
|
||||
*/
|
||||
function _drupal_error_handler($error_level, $message, $filename, $line, $context) {
|
||||
function _drupal_error_handler($error_level, $message, $filename = NULL, $line = NULL, $context = NULL) {
|
||||
require_once __DIR__ . '/errors.inc';
|
||||
_drupal_error_handler_real($error_level, $message, $filename, $line, $context);
|
||||
}
|
||||
@@ -1033,8 +1033,12 @@ function _drupal_shutdown_function() {
|
||||
chdir(DRUPAL_ROOT);
|
||||
|
||||
try {
|
||||
foreach ($callbacks as &$callback) {
|
||||
reset($callbacks);
|
||||
// Do not use foreach() here because it is possible that the callback will
|
||||
// add to the $callbacks array via drupal_register_shutdown_function().
|
||||
while ($callback = current($callbacks)) {
|
||||
call_user_func_array($callback['callback'], $callback['arguments']);
|
||||
next($callbacks);
|
||||
}
|
||||
}
|
||||
// PHP 7 introduces Throwable, which covers both Error and
|
||||
|
||||
@@ -1270,12 +1270,19 @@ function install_select_profile(&$install_state) {
|
||||
/**
|
||||
* Determines the installation profile to use in the installer.
|
||||
*
|
||||
* A profile will be selected in the following order of conditions:
|
||||
* Depending on the context from which it's being called, this method
|
||||
* may be used to:
|
||||
* - Automatically select a profile under certain conditions.
|
||||
* - Indicate which profile has already been selected.
|
||||
* - Indicate that a profile still needs to be selected.
|
||||
*
|
||||
* A profile will be selected automatically if one of the following conditions
|
||||
* is met. They are checked in the given order:
|
||||
* - Only one profile is available.
|
||||
* - A specific profile name is requested in installation parameters:
|
||||
* - For interactive installations via request query parameters.
|
||||
* - For non-interactive installations via install_drupal() settings.
|
||||
* - A discovered profile that is a distribution. If multiple profiles are
|
||||
* - One of the available profiles is a distribution. If multiple profiles are
|
||||
* distributions, then the first discovered profile will be selected.
|
||||
* - Only one visible profile is available.
|
||||
*
|
||||
@@ -1283,35 +1290,37 @@ function install_select_profile(&$install_state) {
|
||||
* The current installer state, containing a 'profiles' key, which is an
|
||||
* associative array of profiles with the machine-readable names as keys.
|
||||
*
|
||||
* @return
|
||||
* @return string|null
|
||||
* The machine-readable name of the selected profile or NULL if no profile was
|
||||
* selected.
|
||||
*
|
||||
* @see install_select_profile()
|
||||
*/
|
||||
function _install_select_profile(&$install_state) {
|
||||
// Don't need to choose profile if only one available.
|
||||
// If there is only one profile available it will always be the one selected.
|
||||
if (count($install_state['profiles']) == 1) {
|
||||
return key($install_state['profiles']);
|
||||
}
|
||||
// If a valid profile has already been selected, return the selection.
|
||||
if (!empty($install_state['parameters']['profile'])) {
|
||||
$profile = $install_state['parameters']['profile'];
|
||||
if (isset($install_state['profiles'][$profile])) {
|
||||
return $profile;
|
||||
}
|
||||
}
|
||||
// Check for a distribution profile.
|
||||
// If any of the profiles are distribution profiles, return the first one.
|
||||
foreach ($install_state['profiles'] as $profile) {
|
||||
$profile_info = install_profile_info($profile->getName());
|
||||
if (!empty($profile_info['distribution'])) {
|
||||
return $profile->getName();
|
||||
}
|
||||
}
|
||||
|
||||
// Get all visible (not hidden) profiles.
|
||||
$visible_profiles = array_filter($install_state['profiles'], function ($profile) {
|
||||
$profile_info = install_profile_info($profile->getName());
|
||||
return !isset($profile_info['hidden']) || !$profile_info['hidden'];
|
||||
});
|
||||
|
||||
// If there is only one visible profile, return it.
|
||||
if (count($visible_profiles) == 1) {
|
||||
return (key($visible_profiles));
|
||||
}
|
||||
|
||||
@@ -11,6 +11,7 @@ use Drupal\Component\Utility\Crypt;
|
||||
use Drupal\Component\Utility\OpCodeCache;
|
||||
use Drupal\Component\Utility\UrlHelper;
|
||||
use Drupal\Core\Extension\ExtensionDiscovery;
|
||||
use Drupal\Core\Extension\ModuleHandler;
|
||||
use Drupal\Core\Site\Settings;
|
||||
|
||||
/**
|
||||
@@ -990,6 +991,12 @@ function drupal_check_profile($profile) {
|
||||
}
|
||||
}
|
||||
|
||||
// Add the profile requirements.
|
||||
$function = $profile . '_requirements';
|
||||
if (function_exists($function)) {
|
||||
$requirements = array_merge($requirements, $function('install'));
|
||||
}
|
||||
|
||||
return $requirements;
|
||||
}
|
||||
|
||||
@@ -1113,6 +1120,16 @@ function install_profile_info($profile, $langcode = 'en') {
|
||||
$info = \Drupal::service('info_parser')->parse("$profile_path/$profile.info.yml");
|
||||
$info += $defaults;
|
||||
|
||||
// Convert dependencies in [project:module] format.
|
||||
$info['dependencies'] = array_map(function ($dependency) {
|
||||
return ModuleHandler::parseDependency($dependency)['name'];
|
||||
}, $info['dependencies']);
|
||||
|
||||
// Convert install key in [project:module] format.
|
||||
$info['install'] = array_map(function ($dependency) {
|
||||
return ModuleHandler::parseDependency($dependency)['name'];
|
||||
}, $info['install']);
|
||||
|
||||
// drupal_required_modules() includes the current profile as a dependency.
|
||||
// Remove that dependency, since a module cannot depend on itself.
|
||||
$required = array_diff(drupal_required_modules(), [$profile]);
|
||||
|
||||
@@ -82,7 +82,7 @@ class Drupal {
|
||||
/**
|
||||
* The current system version.
|
||||
*/
|
||||
const VERSION = '8.6.2';
|
||||
const VERSION = '8.6.3';
|
||||
|
||||
/**
|
||||
* Core API compatibility.
|
||||
@@ -229,7 +229,7 @@ class Drupal {
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrives the request stack.
|
||||
* Retrieves the request stack.
|
||||
*
|
||||
* @return \Symfony\Component\HttpFoundation\RequestStack
|
||||
* The request stack
|
||||
|
||||
@@ -200,7 +200,7 @@ class PhpArrayContainer extends Container {
|
||||
// The PhpArrayDumper just uses the hash of the private service
|
||||
// definition to generate a unique ID.
|
||||
//
|
||||
// @see \Drupal\Component\DependecyInjection\Dumper\OptimizedPhpArrayDumper::getPrivateServiceCall
|
||||
// @see \Drupal\Component\DependencyInjection\Dumper\OptimizedPhpArrayDumper::getPrivateServiceCall
|
||||
if ($type == 'private_service') {
|
||||
$id = $argument->id;
|
||||
|
||||
|
||||
@@ -394,7 +394,7 @@ class PoStreamReader implements PoStreamInterface, PoReaderInterface {
|
||||
($this->context != 'MSGCTXT') &&
|
||||
($this->context != 'MSGID_PLURAL') &&
|
||||
($this->context != 'MSGSTR_ARR')) {
|
||||
// Plural message strings must come after msgid, msgxtxt,
|
||||
// Plural message strings must come after msgid, msgctxt,
|
||||
// msgid_plural, or other msgstr[] entries.
|
||||
$this->errors[] = new FormattableMarkup('The translation stream %uri contains an error: "msgstr[]" is unexpected on line %line.', $log_vars);
|
||||
return FALSE;
|
||||
|
||||
@@ -36,7 +36,7 @@ abstract class SecuredRedirectResponse extends RedirectResponse {
|
||||
* Copies over the values from the given response.
|
||||
*
|
||||
* @param \Symfony\Component\HttpFoundation\RedirectResponse $response
|
||||
* The redirect reponse object.
|
||||
* The redirect response object.
|
||||
*/
|
||||
protected function fromResponse(RedirectResponse $response) {
|
||||
$this->setProtocolVersion($response->getProtocolVersion());
|
||||
|
||||
@@ -29,7 +29,7 @@ abstract class PluginManagerBase implements PluginManagerInterface {
|
||||
/**
|
||||
* The object that returns the preconfigured plugin instance appropriate for a particular runtime condition.
|
||||
*
|
||||
* @var \Drupal\Component\Plugin\Mapper\MapperInterface
|
||||
* @var \Drupal\Component\Plugin\Mapper\MapperInterface|null
|
||||
*/
|
||||
protected $mapper;
|
||||
|
||||
@@ -104,6 +104,9 @@ abstract class PluginManagerBase implements PluginManagerInterface {
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getInstance(array $options) {
|
||||
if (!$this->mapper) {
|
||||
throw new \BadMethodCallException(sprintf('%s does not support this method unless %s::$mapper is set.', static::class, static::class));
|
||||
}
|
||||
return $this->mapper->getInstance($options);
|
||||
}
|
||||
|
||||
|
||||
@@ -49,7 +49,7 @@
|
||||
* The following changes have been done:
|
||||
* Added namespace Drupal\Core\Archiver.
|
||||
* Removed require_once 'PEAR.php'.
|
||||
* Added defintion of OS_WINDOWS taken from PEAR.php.
|
||||
* Added definition of OS_WINDOWS taken from PEAR.php.
|
||||
* Renamed class to ArchiveTar.
|
||||
* Removed extends PEAR from class.
|
||||
* Removed call parent:: __construct().
|
||||
@@ -181,7 +181,7 @@ class ArchiveTar
|
||||
if ($data == "\37\213") {
|
||||
$this->_compress = true;
|
||||
$this->_compress_type = 'gz';
|
||||
// No sure it's enought for a magic code ....
|
||||
// Not sure it's enough for a magic code ....
|
||||
} elseif ($data == "BZ") {
|
||||
$this->_compress = true;
|
||||
$this->_compress_type = 'bz2';
|
||||
@@ -2385,7 +2385,7 @@ class ArchiveTar
|
||||
|
||||
/**
|
||||
* Compress path by changing for example "/dir/foo/../bar" to "/dir/bar",
|
||||
* rand emove double slashes.
|
||||
* and remove double slashes.
|
||||
*
|
||||
* @param string $p_dir path to reduce
|
||||
*
|
||||
|
||||
@@ -9,7 +9,7 @@ namespace Drupal\Core\Cache;
|
||||
* Drupal\Core\Cache\DatabaseBackend provides the default implementation, which
|
||||
* can be consulted as an example.
|
||||
*
|
||||
* The cache indentifiers are case sensitive.
|
||||
* The cache identifiers are case sensitive.
|
||||
*
|
||||
* @ingroup cache
|
||||
*/
|
||||
|
||||
@@ -157,9 +157,7 @@ class MemoryBackend implements CacheBackendInterface, CacheTagsInvalidatorInterf
|
||||
*/
|
||||
public function invalidateMultiple(array $cids) {
|
||||
foreach ($cids as $cid) {
|
||||
if (isset($this->cache[$cid])) {
|
||||
$this->cache[$cid]->expire = $this->getRequestTime() - 1;
|
||||
}
|
||||
$this->cache[$cid]->expire = $this->getRequestTime() - 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -160,7 +160,10 @@ class ConfigInstaller implements ConfigInstallerInterface {
|
||||
*/
|
||||
public function installOptionalConfig(StorageInterface $storage = NULL, $dependency = []) {
|
||||
$profile = $this->drupalGetProfile();
|
||||
$optional_profile_config = [];
|
||||
$enabled_extensions = $this->getEnabledExtensions();
|
||||
$existing_config = $this->getActiveStorages()->listAll();
|
||||
|
||||
// Create the storages to read configuration from.
|
||||
if (!$storage) {
|
||||
// Search the install profile's optional configuration too.
|
||||
$storage = new ExtensionInstallStorage($this->getActiveStorages(StorageInterface::DEFAULT_COLLECTION), InstallStorage::CONFIG_OPTIONAL_DIRECTORY, StorageInterface::DEFAULT_COLLECTION, TRUE, $this->installProfile);
|
||||
@@ -171,7 +174,6 @@ class ConfigInstaller implements ConfigInstallerInterface {
|
||||
// Creates a profile storage to search for overrides.
|
||||
$profile_install_path = $this->drupalGetPath('module', $profile) . '/' . InstallStorage::CONFIG_OPTIONAL_DIRECTORY;
|
||||
$profile_storage = new FileStorage($profile_install_path, StorageInterface::DEFAULT_COLLECTION);
|
||||
$optional_profile_config = $profile_storage->listAll();
|
||||
}
|
||||
else {
|
||||
// Profile has not been set yet. For example during the first steps of the
|
||||
@@ -179,10 +181,17 @@ class ConfigInstaller implements ConfigInstallerInterface {
|
||||
$profile_storage = NULL;
|
||||
}
|
||||
|
||||
$enabled_extensions = $this->getEnabledExtensions();
|
||||
$existing_config = $this->getActiveStorages()->listAll();
|
||||
// Build the list of possible configuration to create.
|
||||
$list = $storage->listAll();
|
||||
if ($profile_storage && !empty($dependency)) {
|
||||
// Only add the optional profile configuration into the list if we are
|
||||
// have a dependency to check. This ensures that optional profile
|
||||
// configuration is not unexpectedly re-created after being deleted.
|
||||
$list = array_unique(array_merge($list, $profile_storage->listAll()));
|
||||
}
|
||||
|
||||
$list = array_unique(array_merge($storage->listAll(), $optional_profile_config));
|
||||
// Filter the list of configuration to only include configuration that
|
||||
// should be created.
|
||||
$list = array_filter($list, function ($config_name) use ($existing_config) {
|
||||
// Only list configuration that:
|
||||
// - does not already exist
|
||||
@@ -226,6 +235,8 @@ class ConfigInstaller implements ConfigInstallerInterface {
|
||||
unset($all_config[$config_name]);
|
||||
}
|
||||
}
|
||||
|
||||
// Create the optional configuration if there is any left after filtering.
|
||||
if (!empty($config_to_create)) {
|
||||
$this->createConfiguration(StorageInterface::DEFAULT_COLLECTION, $config_to_create, TRUE);
|
||||
}
|
||||
|
||||
@@ -43,7 +43,8 @@ interface ConfigInstallerInterface {
|
||||
* @param \Drupal\Core\Config\StorageInterface $storage
|
||||
* (optional) The configuration storage to search for optional
|
||||
* configuration. If not provided, all enabled extension's optional
|
||||
* configuration directories will be searched.
|
||||
* configuration directories including the install profile's will be
|
||||
* searched.
|
||||
* @param array $dependency
|
||||
* (optional) If set, ensures that the configuration being installed has
|
||||
* this dependency. The format is dependency type as the key ('module',
|
||||
|
||||
@@ -189,7 +189,7 @@ interface ConfigEntityInterface extends EntityInterface, ThirdPartySettingsInter
|
||||
* For example, a default view might not be installable if the base table
|
||||
* doesn't exist.
|
||||
*
|
||||
* @retun bool
|
||||
* @return bool
|
||||
* TRUE if the entity is installable, FALSE otherwise.
|
||||
*/
|
||||
public function isInstallable();
|
||||
|
||||
@@ -46,7 +46,7 @@ class FileStorage implements StorageInterface {
|
||||
$this->collection = $collection;
|
||||
|
||||
// Use a NULL File Cache backend by default. This will ensure only the
|
||||
// internal statc caching of FileCache is used and thus avoids blowing up
|
||||
// internal static caching of FileCache is used and thus avoids blowing up
|
||||
// the APCu cache.
|
||||
$this->fileCache = FileCacheFactory::get('config', ['cache_backend_class' => NULL]);
|
||||
}
|
||||
@@ -279,6 +279,9 @@ class FileStorage implements StorageInterface {
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getAllCollectionNames() {
|
||||
if (!is_dir($this->directory)) {
|
||||
return [];
|
||||
}
|
||||
$collections = $this->getAllCollectionNamesHelper($this->directory);
|
||||
sort($collections);
|
||||
return $collections;
|
||||
@@ -305,7 +308,8 @@ class FileStorage implements StorageInterface {
|
||||
* @param string $directory
|
||||
* The directory to check for sub directories. This allows this
|
||||
* function to be used recursively to discover all the collections in the
|
||||
* storage.
|
||||
* storage. It is the responsibility of the caller to ensure the directory
|
||||
* exists.
|
||||
*
|
||||
* @return array
|
||||
* A list of collection names contained within the provided directory.
|
||||
|
||||
@@ -65,7 +65,7 @@ class Tasks extends InstallTasks {
|
||||
Database::getConnection();
|
||||
}
|
||||
catch (\Exception $e) {
|
||||
// Detect utf8mb4 incompability.
|
||||
// Detect utf8mb4 incompatibility.
|
||||
if ($e->getCode() == Connection::UNSUPPORTED_CHARSET || ($e->getCode() == Connection::SQLSTATE_SYNTAX_ERROR && $e->errorInfo[1] == Connection::UNKNOWN_CHARSET)) {
|
||||
$this->fail(t('Your MySQL server and PHP MySQL driver must support utf8mb4 character encoding. Make sure to use a database system that supports this (such as MySQL/MariaDB/Percona 5.5.3 and up), and that the utf8mb4 character set is compiled in. See the <a href=":documentation" target="_blank">MySQL documentation</a> for more information.', [':documentation' => 'https://dev.mysql.com/doc/refman/5.0/en/cannot-initialize-character-set.html']));
|
||||
$info = Database::getConnectionInfo();
|
||||
|
||||
@@ -38,7 +38,7 @@ class Connection extends DatabaseConnection {
|
||||
/**
|
||||
* A map of condition operators to PostgreSQL operators.
|
||||
*
|
||||
* In PostgreSQL, 'LIKE' is case-sensitive. ILKE should be used for
|
||||
* In PostgreSQL, 'LIKE' is case-sensitive. ILIKE should be used for
|
||||
* case-insensitive statements.
|
||||
*/
|
||||
protected static $postgresqlConditionOperatorMap = [
|
||||
|
||||
@@ -914,6 +914,8 @@ class Select extends Query implements SelectInterface {
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function __clone() {
|
||||
parent::__clone();
|
||||
|
||||
// On cloning, also clone the dependent objects. However, we do not
|
||||
// want to clone the database connection object as that would duplicate the
|
||||
// connection itself.
|
||||
@@ -923,6 +925,11 @@ class Select extends Query implements SelectInterface {
|
||||
foreach ($this->union as $key => $aggregate) {
|
||||
$this->union[$key]['query'] = clone($aggregate['query']);
|
||||
}
|
||||
foreach ($this->tables as $alias => $table) {
|
||||
if ($table['table'] instanceof SelectInterface) {
|
||||
$this->tables[$alias]['table'] = clone $table['table'];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -20,7 +20,7 @@ class StatementPrefetch implements \Iterator, StatementInterface {
|
||||
/**
|
||||
* Driver-specific options. Can be used by child classes.
|
||||
*
|
||||
* @var Array
|
||||
* @var array
|
||||
*/
|
||||
protected $driverOptions;
|
||||
|
||||
@@ -41,14 +41,14 @@ class StatementPrefetch implements \Iterator, StatementInterface {
|
||||
/**
|
||||
* Main data store.
|
||||
*
|
||||
* @var Array
|
||||
* @var array
|
||||
*/
|
||||
protected $data = [];
|
||||
|
||||
/**
|
||||
* The current row, retrieved in \PDO::FETCH_ASSOC format.
|
||||
*
|
||||
* @var Array
|
||||
* @var array
|
||||
*/
|
||||
protected $currentRow = NULL;
|
||||
|
||||
@@ -62,7 +62,7 @@ class StatementPrefetch implements \Iterator, StatementInterface {
|
||||
/**
|
||||
* The list of column names in this result set.
|
||||
*
|
||||
* @var Array
|
||||
* @var array
|
||||
*/
|
||||
protected $columnNames = NULL;
|
||||
|
||||
@@ -91,7 +91,7 @@ class StatementPrefetch implements \Iterator, StatementInterface {
|
||||
/**
|
||||
* Holds supplementary current fetch options (which will be used by the next fetch).
|
||||
*
|
||||
* @var Array
|
||||
* @var array
|
||||
*/
|
||||
protected $fetchOptions = [
|
||||
'class' => 'stdClass',
|
||||
@@ -110,7 +110,7 @@ class StatementPrefetch implements \Iterator, StatementInterface {
|
||||
/**
|
||||
* Holds supplementary default fetch options.
|
||||
*
|
||||
* @var Array
|
||||
* @var array
|
||||
*/
|
||||
protected $defaultFetchOptions = [
|
||||
'class' => 'stdClass',
|
||||
|
||||
@@ -22,7 +22,7 @@ class CorsCompilerPass implements CompilerPassInterface {
|
||||
$enabled = !empty($cors_config['enabled']);
|
||||
}
|
||||
|
||||
// Remove the CORS middleware completly in case it was not enabled.
|
||||
// Remove the CORS middleware completely in case it was not enabled.
|
||||
if (!$enabled) {
|
||||
$container->removeDefinition('http_middleware.cors');
|
||||
}
|
||||
|
||||
@@ -298,12 +298,16 @@ class DrupalKernel implements DrupalKernelInterface, TerminableInterface {
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine the application root directory based on assumptions.
|
||||
* Determine the application root directory based on this file's location.
|
||||
*
|
||||
* @return string
|
||||
* The application root.
|
||||
*/
|
||||
protected static function guessApplicationRoot() {
|
||||
// Determine the application root by:
|
||||
// - Removing the namespace directories from the path.
|
||||
// - Getting the path to the directory two levels up from the path
|
||||
// determined in the previous step.
|
||||
return dirname(dirname(substr(__DIR__, 0, -strlen(__NAMESPACE__))));
|
||||
}
|
||||
|
||||
@@ -1091,7 +1095,7 @@ class DrupalKernel implements DrupalKernelInterface, TerminableInterface {
|
||||
// misses.
|
||||
$old_loader = $this->classLoader;
|
||||
$this->classLoader = $loader;
|
||||
// Our class loaders are preprended to ensure they come first like the
|
||||
// Our class loaders are prepended to ensure they come first like the
|
||||
// class loader they are replacing.
|
||||
$old_loader->register(TRUE);
|
||||
$loader->register(TRUE);
|
||||
|
||||
@@ -60,6 +60,7 @@ class ContentEntityDeleteForm extends ContentEntityConfirmFormBase {
|
||||
public function submitForm(array &$form, FormStateInterface $form_state) {
|
||||
/** @var \Drupal\Core\Entity\ContentEntityInterface $entity */
|
||||
$entity = $this->getEntity();
|
||||
$message = $this->getDeletionMessage();
|
||||
|
||||
// Make sure that deleting a translation does not delete the whole entity.
|
||||
if (!$entity->isDefaultTranslation()) {
|
||||
@@ -73,7 +74,7 @@ class ContentEntityDeleteForm extends ContentEntityConfirmFormBase {
|
||||
$form_state->setRedirectUrl($this->getRedirectUrl());
|
||||
}
|
||||
|
||||
$this->messenger()->addStatus($this->getDeletionMessage());
|
||||
$this->messenger()->addStatus($message);
|
||||
$this->logDeletionMessage();
|
||||
}
|
||||
|
||||
|
||||
@@ -251,8 +251,8 @@ class EntityAutocomplete extends Textfield {
|
||||
/**
|
||||
* Finds an entity from an autocomplete input without an explicit ID.
|
||||
*
|
||||
* The method will return an entity ID if one single entity unambuguously
|
||||
* matches the incoming input, and sill assign form errors otherwise.
|
||||
* The method will return an entity ID if one single entity unambiguously
|
||||
* matches the incoming input, and assign form errors otherwise.
|
||||
*
|
||||
* @param \Drupal\Core\Entity\EntityReferenceSelection\SelectionInterface $handler
|
||||
* Entity reference selection plugin.
|
||||
|
||||
@@ -68,6 +68,7 @@ class EntityBundleListener implements EntityBundleListenerInterface {
|
||||
}
|
||||
// Invoke hook_entity_bundle_create() hook.
|
||||
$this->moduleHandler->invokeAll('entity_bundle_create', [$entity_type_id, $bundle]);
|
||||
$this->entityFieldManager->clearCachedFieldDefinitions();
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -497,7 +497,7 @@ class EntityFieldManager implements EntityFieldManagerInterface {
|
||||
}
|
||||
}
|
||||
|
||||
$this->cacheSet($cid, $this->fieldMap, Cache::PERMANENT, ['entity_types']);
|
||||
$this->cacheSet($cid, $this->fieldMap, Cache::PERMANENT, ['entity_types', 'entity_field_info']);
|
||||
}
|
||||
}
|
||||
return $this->fieldMap;
|
||||
|
||||
@@ -194,7 +194,7 @@ abstract class EntityStorageBase extends EntityHandlerBase implements EntityStor
|
||||
* Invokes a hook on behalf of the entity.
|
||||
*
|
||||
* @param string $hook
|
||||
* One of 'presave', 'insert', 'update', 'predelete', 'delete', or
|
||||
* One of 'create', 'presave', 'insert', 'update', 'predelete', 'delete', or
|
||||
* 'revision_delete'.
|
||||
* @param \Drupal\Core\Entity\EntityInterface $entity
|
||||
* The entity object.
|
||||
|
||||
@@ -16,7 +16,7 @@ use Drupal\Core\TypedData\DataReferenceBase;
|
||||
* or the entity ID may be passed.
|
||||
*
|
||||
* Note that the definition of the referenced entity's type is required, whereas
|
||||
* defining referencable entity bundle(s) is optional. A reference defining the
|
||||
* defining referenceable entity bundle(s) is optional. A reference defining the
|
||||
* type and bundle of the referenced entity can be created as following:
|
||||
* @code
|
||||
* $definition = \Drupal\Core\Entity\EntityDefinition::create($entity_type)
|
||||
|
||||
@@ -518,7 +518,7 @@ class SqlContentEntityStorage extends ContentEntityStorageBase implements SqlEnt
|
||||
// Some fields can have more then one columns in the data table so
|
||||
// column names are needed.
|
||||
foreach ($data_fields as $data_field) {
|
||||
// \Drupal\Core\Entity\Sql\TableMappingInterface:: getColumNames()
|
||||
// \Drupal\Core\Entity\Sql\TableMappingInterface::getColumnNames()
|
||||
// returns an array keyed by property names so remove the keys
|
||||
// before array_merge() to avoid losing data with fields having the
|
||||
// same columns i.e. value.
|
||||
|
||||
@@ -1174,12 +1174,12 @@ class SqlContentEntityStorageSchema implements DynamicallyFieldableEntityStorage
|
||||
* The entity type.
|
||||
* @param array $schema
|
||||
* The table schema, passed by reference.
|
||||
*
|
||||
* @return array
|
||||
* A partial schema array for the base table.
|
||||
*/
|
||||
protected function processBaseTable(ContentEntityTypeInterface $entity_type, array &$schema) {
|
||||
$this->processIdentifierSchema($schema, $entity_type->getKey('id'));
|
||||
// Process the schema for the 'id' entity key only if it exists.
|
||||
if ($entity_type->hasKey('id')) {
|
||||
$this->processIdentifierSchema($schema, $entity_type->getKey('id'));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1189,12 +1189,12 @@ class SqlContentEntityStorageSchema implements DynamicallyFieldableEntityStorage
|
||||
* The entity type.
|
||||
* @param array $schema
|
||||
* The table schema, passed by reference.
|
||||
*
|
||||
* @return array
|
||||
* A partial schema array for the base table.
|
||||
*/
|
||||
protected function processRevisionTable(ContentEntityTypeInterface $entity_type, array &$schema) {
|
||||
$this->processIdentifierSchema($schema, $entity_type->getKey('revision'));
|
||||
// Process the schema for the 'revision' entity key only if it exists.
|
||||
if ($entity_type->hasKey('revision')) {
|
||||
$this->processIdentifierSchema($schema, $entity_type->getKey('revision'));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1333,11 +1333,23 @@ class SqlContentEntityStorageSchema implements DynamicallyFieldableEntityStorage
|
||||
// Create field columns.
|
||||
$schema[$table_name] = $this->getSharedTableFieldSchema($storage_definition, $table_name, $column_names);
|
||||
if (!$only_save) {
|
||||
// The entity schema needs to be checked because the field schema is
|
||||
// potentially incomplete.
|
||||
// @todo Fix this in https://www.drupal.org/node/2929120.
|
||||
$entity_schema = $this->getEntitySchema($this->entityType);
|
||||
foreach ($schema[$table_name]['fields'] as $name => $specifier) {
|
||||
// Check if the field is part of the primary keys and pass along
|
||||
// this information when adding the field.
|
||||
// @see \Drupal\Core\Database\Schema::addField()
|
||||
$new_keys = [];
|
||||
if (isset($entity_schema[$table_name]['primary key']) && array_intersect($column_names, $entity_schema[$table_name]['primary key'])) {
|
||||
$new_keys = ['primary key' => $entity_schema[$table_name]['primary key']];
|
||||
}
|
||||
|
||||
// Check if the field exists because it might already have been
|
||||
// created as part of the earlier entity type update event.
|
||||
if (!$schema_handler->fieldExists($table_name, $name)) {
|
||||
$schema_handler->addField($table_name, $name, $specifier);
|
||||
$schema_handler->addField($table_name, $name, $specifier, $new_keys);
|
||||
}
|
||||
}
|
||||
if (!empty($schema[$table_name]['indexes'])) {
|
||||
|
||||
@@ -60,10 +60,7 @@ class KernelDestructionSubscriber implements EventSubscriberInterface, Container
|
||||
* An array of event listener definitions.
|
||||
*/
|
||||
public static function getSubscribedEvents() {
|
||||
// Run this subscriber after others as those might use services that need
|
||||
// to be terminated as well or run code that needs to run before
|
||||
// termination.
|
||||
$events[KernelEvents::TERMINATE][] = ['onKernelTerminate', -100];
|
||||
$events[KernelEvents::TERMINATE][] = ['onKernelTerminate', 100];
|
||||
return $events;
|
||||
}
|
||||
|
||||
|
||||
@@ -5,6 +5,7 @@ namespace Drupal\Core\Field\Plugin\Field\FieldFormatter;
|
||||
use Drupal\Component\Render\FormattableMarkup;
|
||||
use Drupal\Core\Cache\CacheableMetadata;
|
||||
use Drupal\Core\Datetime\DateFormatterInterface;
|
||||
use Drupal\Core\Datetime\DrupalDateTime;
|
||||
use Drupal\Core\Field\FieldDefinitionInterface;
|
||||
use Drupal\Core\Field\FieldItemListInterface;
|
||||
use Drupal\Core\Field\FormatterBase;
|
||||
@@ -104,7 +105,7 @@ class TimestampAgoFormatter extends FormatterBase implements ContainerFactoryPlu
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function settingsForm(array $form, FormStateInterface $form_state) {
|
||||
$elements = parent::settingsForm($form, $form_state);
|
||||
$form = parent::settingsForm($form, $form_state);
|
||||
|
||||
$form['future_format'] = [
|
||||
'#type' => 'textfield',
|
||||
@@ -120,7 +121,7 @@ class TimestampAgoFormatter extends FormatterBase implements ContainerFactoryPlu
|
||||
'#description' => $this->t('Use <em>@interval</em> where you want the formatted interval text to appear.'),
|
||||
];
|
||||
|
||||
$elements['granularity'] = [
|
||||
$form['granularity'] = [
|
||||
'#type' => 'number',
|
||||
'#title' => $this->t('Granularity'),
|
||||
'#description' => $this->t('How many time interval units should be shown in the formatted output.'),
|
||||
@@ -129,7 +130,7 @@ class TimestampAgoFormatter extends FormatterBase implements ContainerFactoryPlu
|
||||
'#max' => 6,
|
||||
];
|
||||
|
||||
return $elements;
|
||||
return $form;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -138,10 +139,19 @@ class TimestampAgoFormatter extends FormatterBase implements ContainerFactoryPlu
|
||||
public function settingsSummary() {
|
||||
$summary = parent::settingsSummary();
|
||||
|
||||
$future_date = strtotime('1 year 1 month 1 week 1 day 1 hour 1 minute');
|
||||
$past_date = strtotime('-1 year -1 month -1 week -1 day -1 hour -1 minute');
|
||||
$summary[] = $this->t('Future date: %display', ['%display' => $this->formatTimestamp($future_date)]);
|
||||
$summary[] = $this->t('Past date: %display', ['%display' => $this->formatTimestamp($past_date)]);
|
||||
$future_date = new DrupalDateTime('1 year 1 month 1 week 1 day 1 hour 1 minute');
|
||||
$past_date = new DrupalDateTime('-1 year -1 month -1 week -1 day -1 hour -1 minute');
|
||||
$granularity = $this->getSetting('granularity');
|
||||
$options = [
|
||||
'granularity' => $granularity,
|
||||
'return_as_object' => FALSE,
|
||||
];
|
||||
|
||||
$future_date_interval = new FormattableMarkup($this->getSetting('future_format'), ['@interval' => $this->dateFormatter->formatTimeDiffUntil($future_date->getTimestamp(), $options)]);
|
||||
$past_date_interval = new FormattableMarkup($this->getSetting('past_format'), ['@interval' => $this->dateFormatter->formatTimeDiffSince($past_date->getTimestamp(), $options)]);
|
||||
|
||||
$summary[] = $this->t('Future date: %display', ['%display' => $future_date_interval]);
|
||||
$summary[] = $this->t('Past date: %display', ['%display' => $past_date_interval]);
|
||||
|
||||
return $summary;
|
||||
}
|
||||
|
||||
@@ -10,7 +10,7 @@ interface ConfirmFormInterface extends FormInterface {
|
||||
/**
|
||||
* Returns the question to ask the user.
|
||||
*
|
||||
* @return string
|
||||
* @return \Drupal\Core\StringTranslation\TranslatableMarkup
|
||||
* The form question. The page title will be set to this value.
|
||||
*/
|
||||
public function getQuestion();
|
||||
@@ -26,7 +26,7 @@ interface ConfirmFormInterface extends FormInterface {
|
||||
/**
|
||||
* Returns additional text to display as a description.
|
||||
*
|
||||
* @return string
|
||||
* @return \Drupal\Core\StringTranslation\TranslatableMarkup
|
||||
* The form description.
|
||||
*/
|
||||
public function getDescription();
|
||||
@@ -34,7 +34,7 @@ interface ConfirmFormInterface extends FormInterface {
|
||||
/**
|
||||
* Returns a caption for the button that confirms the action.
|
||||
*
|
||||
* @return string
|
||||
* @return \Drupal\Core\StringTranslation\TranslatableMarkup
|
||||
* The form confirmation text.
|
||||
*/
|
||||
public function getConfirmText();
|
||||
@@ -42,7 +42,7 @@ interface ConfirmFormInterface extends FormInterface {
|
||||
/**
|
||||
* Returns a caption for the link which cancels the action.
|
||||
*
|
||||
* @return string
|
||||
* @return \Drupal\Core\StringTranslation\TranslatableMarkup
|
||||
* The form cancellation text.
|
||||
*/
|
||||
public function getCancelText();
|
||||
|
||||
@@ -687,7 +687,7 @@ class FormBuilder implements FormBuilderInterface, FormValidatorInterface, FormS
|
||||
// will be replaced at the very last moment. This ensures forms with
|
||||
// dynamically generated action URLs don't have poor cacheability.
|
||||
// Use the proper API to generate the placeholder, when we have one. See
|
||||
// https://www.drupal.org/node/2562341. The placholder uses a fixed string
|
||||
// https://www.drupal.org/node/2562341. The placeholder uses a fixed string
|
||||
// that is Crypt::hashBase64('Drupal\Core\Form\FormBuilder::prepareForm');
|
||||
$placeholder = 'form_action_p_pvdeGsVG5zNF_XLGPTvYSKCf43t8qZYSwcfZl2uzM';
|
||||
|
||||
|
||||
@@ -87,8 +87,8 @@ class FormState implements FormStateInterface {
|
||||
* copy of the form is immediately built and sent to the browser, instead of a
|
||||
* redirect. This is used for multi-step forms, such as wizards and
|
||||
* confirmation forms. Normally, self::$rebuild is set by a submit handler,
|
||||
* since its is usually logic within a submit handler that determines whether
|
||||
* a form is done or requires another step. However, a validation handler may
|
||||
* since it is usually logic within a submit handler that determines whether a
|
||||
* form is done or requires another step. However, a validation handler may
|
||||
* already set self::$rebuild to cause the form processing to bypass submit
|
||||
* handlers and rebuild the form instead, even if there are no validation
|
||||
* errors.
|
||||
|
||||
@@ -43,7 +43,7 @@ class HandlerStackConfigurator {
|
||||
protected $container;
|
||||
|
||||
/**
|
||||
* Contructs a new HandlerStackConfigurator object.
|
||||
* Constructs a new HandlerStackConfigurator object.
|
||||
*
|
||||
* @param \Symfony\Component\DependencyInjection\ContainerInterface $container
|
||||
* The service container.
|
||||
|
||||
@@ -44,7 +44,7 @@ class TrustedHostsRequestFactory {
|
||||
* @param array $request
|
||||
* (optional) An array of request variables.
|
||||
* @param array $attributes
|
||||
* (optioanl) An array of attributes.
|
||||
* (optional) An array of attributes.
|
||||
* @param array $cookies
|
||||
* (optional) The request cookies ($_COOKIE).
|
||||
* @param array $files
|
||||
|
||||
@@ -19,7 +19,7 @@ class InstallProfileMismatchException extends InstallerException {
|
||||
* @param string $settings_profile
|
||||
* The profile in settings.php.
|
||||
* @param string $settings_file
|
||||
* The path to settigns.php.
|
||||
* The path to settings.php.
|
||||
* @param \Drupal\Core\StringTranslation\TranslationInterface $string_translation
|
||||
* The string translation manager.
|
||||
*
|
||||
|
||||
@@ -2,7 +2,9 @@
|
||||
|
||||
namespace Drupal\Core\Mail;
|
||||
|
||||
use Drupal\Component\Render\MarkupInterface;
|
||||
use Drupal\Component\Render\PlainTextOutput;
|
||||
use Drupal\Component\Utility\Html;
|
||||
use Drupal\Component\Utility\Unicode;
|
||||
use Drupal\Core\Logger\LoggerChannelFactoryInterface;
|
||||
use Drupal\Core\Messenger\MessengerTrait;
|
||||
@@ -10,6 +12,7 @@ use Drupal\Core\Plugin\DefaultPluginManager;
|
||||
use Drupal\Core\Cache\CacheBackendInterface;
|
||||
use Drupal\Core\Extension\ModuleHandlerInterface;
|
||||
use Drupal\Core\Config\ConfigFactoryInterface;
|
||||
use Drupal\Core\Render\Markup;
|
||||
use Drupal\Core\Render\RenderContext;
|
||||
use Drupal\Core\Render\RendererInterface;
|
||||
use Drupal\Core\StringTranslation\StringTranslationTrait;
|
||||
@@ -277,6 +280,13 @@ class MailManager extends DefaultPluginManager implements MailManagerInterface {
|
||||
// Retrieve the responsible implementation for this message.
|
||||
$system = $this->getInstance(['module' => $module, 'key' => $key]);
|
||||
|
||||
// Attempt to convert relative URLs to absolute.
|
||||
foreach ($message['body'] as &$body_part) {
|
||||
if ($body_part instanceof MarkupInterface) {
|
||||
$body_part = Markup::create(Html::transformRootRelativeUrlsToAbsolute((string) $body_part, \Drupal::request()->getSchemeAndHttpHost()));
|
||||
}
|
||||
}
|
||||
|
||||
// Format the message body.
|
||||
$message = $system->format($message);
|
||||
|
||||
|
||||
@@ -83,33 +83,36 @@ class LocalActionDefault extends PluginBase implements LocalActionInterface, Con
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getRouteParameters(RouteMatchInterface $route_match) {
|
||||
$parameters = isset($this->pluginDefinition['route_parameters']) ? $this->pluginDefinition['route_parameters'] : [];
|
||||
$route_parameters = isset($this->pluginDefinition['route_parameters']) ? $this->pluginDefinition['route_parameters'] : [];
|
||||
$route = $this->routeProvider->getRouteByName($this->getRouteName());
|
||||
$variables = $route->compile()->getVariables();
|
||||
|
||||
// Normally the \Drupal\Core\ParamConverter\ParamConverterManager has
|
||||
// processed the Request attributes, and in that case the _raw_variables
|
||||
// attribute holds the original path strings keyed to the corresponding
|
||||
// slugs in the path patterns. For example, if the route's path pattern is
|
||||
// run, and the route parameters have been upcast. The original values can
|
||||
// be retrieved from the raw parameters. For example, if the route's path is
|
||||
// /filter/tips/{filter_format} and the path is /filter/tips/plain_text then
|
||||
// $raw_variables->get('filter_format') == 'plain_text'.
|
||||
$raw_variables = $route_match->getRawParameters();
|
||||
// $raw_parameters->get('filter_format') == 'plain_text'. Parameters that
|
||||
// are not represented in the route path as slugs might be added by a route
|
||||
// enhancer and will not be present in the raw parameters.
|
||||
$raw_parameters = $route_match->getRawParameters();
|
||||
$parameters = $route_match->getParameters();
|
||||
|
||||
foreach ($variables as $name) {
|
||||
if (isset($parameters[$name])) {
|
||||
if (isset($route_parameters[$name])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($raw_variables && $raw_variables->has($name)) {
|
||||
$parameters[$name] = $raw_variables->get($name);
|
||||
if ($raw_parameters->has($name)) {
|
||||
$route_parameters[$name] = $raw_parameters->get($name);
|
||||
}
|
||||
elseif ($value = $route_match->getRawParameter($name)) {
|
||||
$parameters[$name] = $value;
|
||||
elseif ($parameters->has($name)) {
|
||||
$route_parameters[$name] = $parameters->get($name);
|
||||
}
|
||||
}
|
||||
|
||||
// The UrlGenerator will throw an exception if expected parameters are
|
||||
// missing. This method should be overridden if that is possible.
|
||||
return $parameters;
|
||||
return $route_parameters;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -196,9 +196,10 @@ class LocalActionManager extends DefaultPluginManager implements LocalActionMana
|
||||
}
|
||||
}
|
||||
$links = [];
|
||||
$cacheability = new CacheableMetadata();
|
||||
$cacheability->addCacheContexts(['route']);
|
||||
/** @var $plugin \Drupal\Core\Menu\LocalActionInterface */
|
||||
foreach ($this->instances[$route_appears] as $plugin_id => $plugin) {
|
||||
$cacheability = new CacheableMetadata();
|
||||
$route_name = $plugin->getRouteName();
|
||||
$route_parameters = $plugin->getRouteParameters($this->routeMatch);
|
||||
$access = $this->accessManager->checkNamedRoute($route_name, $route_parameters, $this->account, TRUE);
|
||||
@@ -213,9 +214,8 @@ class LocalActionManager extends DefaultPluginManager implements LocalActionMana
|
||||
'#weight' => $plugin->getWeight(),
|
||||
];
|
||||
$cacheability->addCacheableDependency($access)->addCacheableDependency($plugin);
|
||||
$cacheability->applyTo($links[$plugin_id]);
|
||||
}
|
||||
$links['#cache']['contexts'][] = 'route';
|
||||
$cacheability->applyTo($links);
|
||||
|
||||
return $links;
|
||||
}
|
||||
|
||||
@@ -41,34 +41,36 @@ class LocalTaskDefault extends PluginBase implements LocalTaskInterface, Cacheab
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getRouteParameters(RouteMatchInterface $route_match) {
|
||||
$parameters = isset($this->pluginDefinition['route_parameters']) ? $this->pluginDefinition['route_parameters'] : [];
|
||||
$route_parameters = isset($this->pluginDefinition['route_parameters']) ? $this->pluginDefinition['route_parameters'] : [];
|
||||
$route = $this->routeProvider()->getRouteByName($this->getRouteName());
|
||||
$variables = $route->compile()->getVariables();
|
||||
|
||||
// Normally the \Drupal\Core\ParamConverter\ParamConverterManager has
|
||||
// processed the Request attributes, and in that case the _raw_variables
|
||||
// attribute holds the original path strings keyed to the corresponding
|
||||
// slugs in the path patterns. For example, if the route's path pattern is
|
||||
// run, and the route parameters have been upcast. The original values can
|
||||
// be retrieved from the raw parameters. For example, if the route's path is
|
||||
// /filter/tips/{filter_format} and the path is /filter/tips/plain_text then
|
||||
// $raw_variables->get('filter_format') == 'plain_text'.
|
||||
|
||||
$raw_variables = $route_match->getRawParameters();
|
||||
// $raw_parameters->get('filter_format') == 'plain_text'. Parameters that
|
||||
// are not represented in the route path as slugs might be added by a route
|
||||
// enhancer and will not be present in the raw parameters.
|
||||
$raw_parameters = $route_match->getRawParameters();
|
||||
$parameters = $route_match->getParameters();
|
||||
|
||||
foreach ($variables as $name) {
|
||||
if (isset($parameters[$name])) {
|
||||
if (isset($route_parameters[$name])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($raw_variables && $raw_variables->has($name)) {
|
||||
$parameters[$name] = $raw_variables->get($name);
|
||||
if ($raw_parameters->has($name)) {
|
||||
$route_parameters[$name] = $raw_parameters->get($name);
|
||||
}
|
||||
elseif ($value = $route_match->getRawParameter($name)) {
|
||||
$parameters[$name] = $value;
|
||||
elseif ($parameters->has($name)) {
|
||||
$route_parameters[$name] = $parameters->get($name);
|
||||
}
|
||||
}
|
||||
|
||||
// The UrlGenerator will throw an exception if expected parameters are
|
||||
// missing. This method should be overridden if that is possible.
|
||||
return $parameters;
|
||||
return $route_parameters;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -30,7 +30,7 @@ interface MenuLinkTreeInterface {
|
||||
*
|
||||
* Builds menu link tree parameters that:
|
||||
* - Expand all links in the active trail based on route being viewed.
|
||||
* - Expand the descendents of the links in the active trail whose
|
||||
* - Expand the descendants of the links in the active trail whose
|
||||
* 'expanded' flag is enabled.
|
||||
*
|
||||
* This only sets the (relatively complex) parameters to achieve the two above
|
||||
|
||||
@@ -11,7 +11,7 @@ use Symfony\Component\HttpFoundation\Request;
|
||||
*
|
||||
* Do not serve cached pages to authenticated users, or to anonymous users when
|
||||
* $_SESSION is non-empty. $_SESSION may contain status messages from a form
|
||||
* submission, the contents of a shopping cart, or other userspecific content
|
||||
* submission, the contents of a shopping cart, or other user-specific content
|
||||
* that should not be cached and displayed to other users.
|
||||
*/
|
||||
class NoSessionOpen implements RequestPolicyInterface {
|
||||
|
||||
@@ -12,10 +12,17 @@ interface InboundPathProcessorInterface {
|
||||
/**
|
||||
* Processes the inbound path.
|
||||
*
|
||||
* Implementations may make changes to the request object passed in but should
|
||||
* avoid all other side effects. This method can be called to process requests
|
||||
* other than the current request.
|
||||
*
|
||||
* @param string $path
|
||||
* The path to process, with a leading slash.
|
||||
* @param \Symfony\Component\HttpFoundation\Request $request
|
||||
* The HttpRequest object representing the current request.
|
||||
* The HttpRequest object representing the request to process. Note, if this
|
||||
* method is being called via the path_processor_manager service and is not
|
||||
* part of routing, the current request object must be cloned before being
|
||||
* passed in.
|
||||
*
|
||||
* @return string
|
||||
* The processed path.
|
||||
|
||||
@@ -6,6 +6,7 @@ use Drupal\Component\Plugin\Context\Context as ComponentContext;
|
||||
use Drupal\Component\Plugin\Exception\ContextException;
|
||||
use Drupal\Core\Cache\CacheableDependencyInterface;
|
||||
use Drupal\Core\Cache\CacheableMetadata;
|
||||
use Drupal\Core\DependencyInjection\DependencySerializationTrait;
|
||||
use Drupal\Core\TypedData\TypedDataInterface;
|
||||
use Drupal\Core\TypedData\TypedDataTrait;
|
||||
|
||||
@@ -15,6 +16,7 @@ use Drupal\Core\TypedData\TypedDataTrait;
|
||||
class Context extends ComponentContext implements ContextInterface {
|
||||
|
||||
use TypedDataTrait;
|
||||
use DependencySerializationTrait;
|
||||
|
||||
/**
|
||||
* The data associated with the context.
|
||||
|
||||
@@ -5,7 +5,7 @@ namespace Drupal\Core\ProxyBuilder;
|
||||
use Drupal\Component\ProxyBuilder\ProxyBuilder as BaseProxyBuilder;
|
||||
|
||||
/**
|
||||
* Extend the component proxy builder by using the DependencySerialziationTrait.
|
||||
* Extend the component proxy builder by using the DependencySerializationTrait.
|
||||
*/
|
||||
class ProxyBuilder extends BaseProxyBuilder {
|
||||
|
||||
|
||||
@@ -11,12 +11,14 @@ use Drupal\Core\Render\Element;
|
||||
* Properties:
|
||||
* - #default_value: An RFC-compliant email address.
|
||||
* - #size: The size of the input element in characters.
|
||||
* - #pattern: A string for the native HTML5 pattern attribute.
|
||||
*
|
||||
* Example usage:
|
||||
* @code
|
||||
* $form['email'] = array(
|
||||
* '#type' => 'email',
|
||||
* '#title' => $this->t('Email'),
|
||||
* '#pattern' => '*@example.com',
|
||||
* );
|
||||
* @end
|
||||
*
|
||||
|
||||
@@ -10,6 +10,7 @@ use Drupal\Core\Render\Element;
|
||||
*
|
||||
* Properties:
|
||||
* - #size: The size of the input element in characters.
|
||||
* - #pattern: A string for the native HTML5 pattern attribute.
|
||||
*
|
||||
* Usage example:
|
||||
* @code
|
||||
@@ -17,6 +18,7 @@ use Drupal\Core\Render\Element;
|
||||
* '#type' => 'password',
|
||||
* '#title' => $this->t('Password'),
|
||||
* '#size' => 25,
|
||||
* '#pattern' => '[01]+',
|
||||
* );
|
||||
* @endcode
|
||||
*
|
||||
|
||||
@@ -32,7 +32,7 @@ use Drupal\Core\Url;
|
||||
* strings, if they are literals provided by your module, should be
|
||||
* internationalized and translated; see the
|
||||
* @link i18n Internationalization topic @endlink for more information. Note
|
||||
* that although in the properies list that follows, they are designated to be
|
||||
* that although in the properties list that follows, they are designated to be
|
||||
* of type string, they would generally end up being
|
||||
* \Drupal\Core\StringTranslation\TranslatableMarkup objects instead.
|
||||
*
|
||||
|
||||
@@ -12,12 +12,14 @@ use Drupal\Core\Render\Element;
|
||||
*
|
||||
* Properties:
|
||||
* - #size: The size of the input element in characters.
|
||||
* - #pattern: A string for the native HTML5 pattern attribute.
|
||||
*
|
||||
* Usage example:
|
||||
* @code
|
||||
* $form['phone'] = array(
|
||||
* '#type' => 'tel',
|
||||
* '#title' => $this->t('Phone'),
|
||||
* '#pattern' => '[^\d]*',
|
||||
* );
|
||||
* @endcode
|
||||
*
|
||||
|
||||
@@ -15,6 +15,7 @@ use Drupal\Core\Render\Element;
|
||||
* autocomplete JavaScript library.
|
||||
* - #autocomplete_route_parameters: An array of parameters to be used in
|
||||
* conjunction with the route name.
|
||||
* - #pattern: A string for the native HTML5 pattern attribute.
|
||||
*
|
||||
* Usage example:
|
||||
* @code
|
||||
@@ -24,7 +25,8 @@ use Drupal\Core\Render\Element;
|
||||
* '#default_value' => $node->title,
|
||||
* '#size' => 60,
|
||||
* '#maxlength' => 128,
|
||||
* '#required' => TRUE,
|
||||
* '#pattern' => 'some-prefix-[a-z]+',
|
||||
* '#required' => TRUE,
|
||||
* );
|
||||
* @endcode
|
||||
*
|
||||
|
||||
@@ -12,6 +12,7 @@ use Drupal\Core\Render\Element;
|
||||
* Properties:
|
||||
* - #default_value: A valid URL string.
|
||||
* - #size: The size of the input element in characters.
|
||||
* - #pattern: A string for the native HTML5 pattern attribute.
|
||||
*
|
||||
* Usage example:
|
||||
* @code
|
||||
@@ -19,6 +20,7 @@ use Drupal\Core\Render\Element;
|
||||
* '#type' => 'url',
|
||||
* '#title' => $this->t('Home Page'),
|
||||
* '#size' => 30,
|
||||
* '#pattern' => '*.example.com',
|
||||
* ...
|
||||
* );
|
||||
* @endcode
|
||||
|
||||
@@ -106,7 +106,7 @@ class SessionConfiguration implements SessionConfigurationInterface {
|
||||
* Return the session cookie domain.
|
||||
*
|
||||
* The Set-Cookie response header and its domain attribute are defined in RFC
|
||||
* 2109, RFC 2965 and RFC 6265 each one superseeding the previous version.
|
||||
* 2109, RFC 2965 and RFC 6265 each one superseding the previous version.
|
||||
*
|
||||
* @see http://tools.ietf.org/html/rfc2109
|
||||
* @see http://tools.ietf.org/html/rfc2965
|
||||
|
||||
@@ -14,8 +14,7 @@ interface WriteSafeSessionHandlerInterface {
|
||||
* only capable of forcibly disabling that session data is written to storage.
|
||||
*
|
||||
* @param bool $flag
|
||||
* TRUE if the session the session is allowed to be written, FALSE
|
||||
* otherwise.
|
||||
* TRUE if the session is allowed to be written, FALSE otherwise.
|
||||
*/
|
||||
public function setSessionWritable($flag);
|
||||
|
||||
@@ -23,8 +22,7 @@ interface WriteSafeSessionHandlerInterface {
|
||||
* Returns whether or not a session may be written to storage.
|
||||
*
|
||||
* @return bool
|
||||
* TRUE if the session the session is allowed to be written, FALSE
|
||||
* otherwise.
|
||||
* TRUE if the session is allowed to be written, FALSE otherwise.
|
||||
*/
|
||||
public function isSessionWritable();
|
||||
|
||||
|
||||
@@ -2,15 +2,12 @@
|
||||
|
||||
namespace Drupal\Core\State;
|
||||
|
||||
use Drupal\Core\Cache\CacheBackendInterface;
|
||||
use Drupal\Core\Cache\CacheCollector;
|
||||
use Drupal\Core\KeyValueStore\KeyValueFactoryInterface;
|
||||
use Drupal\Core\Lock\LockBackendInterface;
|
||||
|
||||
/**
|
||||
* Provides the state system using a key value store.
|
||||
*/
|
||||
class State extends CacheCollector implements StateInterface {
|
||||
class State implements StateInterface {
|
||||
|
||||
/**
|
||||
* The key value store to use.
|
||||
@@ -19,18 +16,20 @@ class State extends CacheCollector implements StateInterface {
|
||||
*/
|
||||
protected $keyValueStore;
|
||||
|
||||
/**
|
||||
* Static state cache.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $cache = [];
|
||||
|
||||
/**
|
||||
* Constructs a State object.
|
||||
*
|
||||
* @param \Drupal\Core\KeyValueStore\KeyValueFactoryInterface $key_value_factory
|
||||
* The key value store to use.
|
||||
* @param \Drupal\Core\Cache\CacheBackendInterface $cache
|
||||
* The cache backend.
|
||||
* @param \Drupal\Core\Lock\LockBackendInterface $lock
|
||||
* The lock backend.
|
||||
*/
|
||||
public function __construct(KeyValueFactoryInterface $key_value_factory, CacheBackendInterface $cache, LockBackendInterface $lock) {
|
||||
parent::__construct('state', $cache, $lock);
|
||||
public function __construct(KeyValueFactoryInterface $key_value_factory) {
|
||||
$this->keyValueStore = $key_value_factory->get('state');
|
||||
}
|
||||
|
||||
@@ -38,18 +37,8 @@ class State extends CacheCollector implements StateInterface {
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function get($key, $default = NULL) {
|
||||
$value = parent::get($key);
|
||||
return $value !== NULL ? $value : $default;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function resolveCacheMiss($key) {
|
||||
$value = $this->keyValueStore->get($key);
|
||||
$this->storage[$key] = $value;
|
||||
$this->persist($key);
|
||||
return $value;
|
||||
$values = $this->getMultiple([$key]);
|
||||
return isset($values[$key]) ? $values[$key] : $default;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -57,9 +46,33 @@ class State extends CacheCollector implements StateInterface {
|
||||
*/
|
||||
public function getMultiple(array $keys) {
|
||||
$values = [];
|
||||
$load = [];
|
||||
foreach ($keys as $key) {
|
||||
$values[$key] = $this->get($key);
|
||||
// Check if we have a value in the cache.
|
||||
if (isset($this->cache[$key])) {
|
||||
$values[$key] = $this->cache[$key];
|
||||
}
|
||||
// Load the value if we don't have an explicit NULL value.
|
||||
elseif (!array_key_exists($key, $this->cache)) {
|
||||
$load[] = $key;
|
||||
}
|
||||
}
|
||||
|
||||
if ($load) {
|
||||
$loaded_values = $this->keyValueStore->getMultiple($load);
|
||||
foreach ($load as $key) {
|
||||
// If we find a value, even one that is NULL, add it to the cache and
|
||||
// return it.
|
||||
if (isset($loaded_values[$key]) || array_key_exists($key, $loaded_values)) {
|
||||
$values[$key] = $loaded_values[$key];
|
||||
$this->cache[$key] = $loaded_values[$key];
|
||||
}
|
||||
else {
|
||||
$this->cache[$key] = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $values;
|
||||
}
|
||||
|
||||
@@ -67,7 +80,7 @@ class State extends CacheCollector implements StateInterface {
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function set($key, $value) {
|
||||
parent::set($key, $value);
|
||||
$this->cache[$key] = $value;
|
||||
$this->keyValueStore->set($key, $value);
|
||||
}
|
||||
|
||||
@@ -76,7 +89,7 @@ class State extends CacheCollector implements StateInterface {
|
||||
*/
|
||||
public function setMultiple(array $data) {
|
||||
foreach ($data as $key => $value) {
|
||||
parent::set($key, $value);
|
||||
$this->cache[$key] = $value;
|
||||
}
|
||||
$this->keyValueStore->setMultiple($data);
|
||||
}
|
||||
@@ -85,8 +98,7 @@ class State extends CacheCollector implements StateInterface {
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function delete($key) {
|
||||
parent::delete($key);
|
||||
$this->keyValueStore->delete($key);
|
||||
$this->deleteMultiple([$key]);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -94,7 +106,7 @@ class State extends CacheCollector implements StateInterface {
|
||||
*/
|
||||
public function deleteMultiple(array $keys) {
|
||||
foreach ($keys as $key) {
|
||||
parent::delete($key);
|
||||
unset($this->cache[$key]);
|
||||
}
|
||||
$this->keyValueStore->deleteMultiple($keys);
|
||||
}
|
||||
@@ -103,7 +115,7 @@ class State extends CacheCollector implements StateInterface {
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function resetCache() {
|
||||
$this->clear();
|
||||
$this->cache = [];
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -82,7 +82,7 @@ interface StreamWrapperInterface extends PhpStreamWrapperInterface {
|
||||
const READ_VISIBLE = 0x0014;
|
||||
|
||||
/**
|
||||
* This is the default 'type' falg. This does not include
|
||||
* This is the default 'type' flag. This does not include
|
||||
* StreamWrapperInterface::LOCAL, because PHP grants a greater trust level to
|
||||
* local files (for example, they can be used in an "include" statement,
|
||||
* regardless of the "allow_url_include" setting), so stream wrappers need to
|
||||
|
||||
@@ -123,6 +123,7 @@ class PrivateTempStore {
|
||||
if ($this->currentUser->isAnonymous()) {
|
||||
// @todo when https://www.drupal.org/node/2865991 is resolved, use force
|
||||
// start session API rather than setting an arbitrary value directly.
|
||||
$this->startSession();
|
||||
$this->requestStack
|
||||
->getCurrentRequest()
|
||||
->getSession()
|
||||
@@ -219,7 +220,34 @@ class PrivateTempStore {
|
||||
* The owner.
|
||||
*/
|
||||
protected function getOwner() {
|
||||
return $this->currentUser->id() ?: $this->requestStack->getCurrentRequest()->getSession()->getId();
|
||||
$owner = $this->currentUser->id();
|
||||
if ($this->currentUser->isAnonymous()) {
|
||||
$this->startSession();
|
||||
$owner = $this->requestStack->getCurrentRequest()->getSession()->getId();
|
||||
}
|
||||
return $owner;
|
||||
}
|
||||
|
||||
/**
|
||||
* Start session because it is required for a private temp store.
|
||||
*
|
||||
* Ensures that an anonymous user has a session created for them, as
|
||||
* otherwise subsequent page loads will not be able to retrieve their
|
||||
* tempstore data.
|
||||
*
|
||||
* @todo when https://www.drupal.org/node/2865991 is resolved, use force
|
||||
* start session API.
|
||||
*/
|
||||
protected function startSession() {
|
||||
$has_session = $this->requestStack
|
||||
->getCurrentRequest()
|
||||
->hasSession();
|
||||
if (!$has_session) {
|
||||
/** @var \Symfony\Component\HttpFoundation\Session\SessionInterface $session */
|
||||
$session = \Drupal::service('session');
|
||||
$this->requestStack->getCurrentRequest()->setSession($session);
|
||||
$session->start();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -188,7 +188,7 @@ class TypedDataManager extends DefaultPluginManager implements TypedDataManagerI
|
||||
throw new \InvalidArgumentException("Property $property_name is unknown.");
|
||||
}
|
||||
// Create the prototype without any value, but with initial parenting
|
||||
// so that constructors can set up the objects correclty.
|
||||
// so that constructors can set up the objects correctly.
|
||||
$this->prototypes[$key] = $this->create($definition, NULL, $property_name, $object);
|
||||
}
|
||||
|
||||
|
||||
@@ -197,7 +197,7 @@ class UpdateRegistry {
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers that update fucntions got executed.
|
||||
* Registers that update functions were executed.
|
||||
*
|
||||
* @param string[] $function_names
|
||||
* The executed update functions.
|
||||
|
||||
@@ -105,7 +105,7 @@ class Module extends Updater implements UpdaterInterface {
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function postInstallTasks() {
|
||||
// Since this is being called outsite of the primary front controller,
|
||||
// Since this is being called outside of the primary front controller,
|
||||
// the base_url needs to be set explicitly to ensure that links are
|
||||
// relative to the site root.
|
||||
// @todo Simplify with https://www.drupal.org/node/2548095
|
||||
|
||||
@@ -87,7 +87,7 @@ class Theme extends Updater implements UpdaterInterface {
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function postInstallTasks() {
|
||||
// Since this is being called outsite of the primary front controller,
|
||||
// Since this is being called outside of the primary front controller,
|
||||
// the base_url needs to be set explicitly to ensure that links are
|
||||
// relative to the site root.
|
||||
// @todo Simplify with https://www.drupal.org/node/2548095
|
||||
|
||||
@@ -78,7 +78,6 @@ class UnroutedUrlAssembler implements UnroutedUrlAssemblerInterface {
|
||||
$options += ['query' => []];
|
||||
|
||||
$options['query'] = NestedArray::mergeDeep($parsed['query'], $options['query']);
|
||||
ksort($options['query']);
|
||||
|
||||
if ($parsed['fragment'] && !$options['fragment']) {
|
||||
$options['fragment'] = '#' . $parsed['fragment'];
|
||||
|
||||
@@ -28,7 +28,7 @@
|
||||
* @type {Drupal~behavior}
|
||||
*
|
||||
* @prop {Drupal~behaviorAttach} attach
|
||||
* Attaches the behavior for drupalAnnouce.
|
||||
* Attaches the behavior for drupalAnnounce.
|
||||
*/
|
||||
Drupal.behaviors.drupalAnnounce = {
|
||||
attach(context) {
|
||||
|
||||
@@ -218,7 +218,7 @@
|
||||
.find('input.form-autocomplete')
|
||||
.once('autocomplete');
|
||||
if ($autocomplete.length) {
|
||||
// Allow options to be overriden per instance.
|
||||
// Allow options to be overridden per instance.
|
||||
const blacklist = $autocomplete.attr(
|
||||
'data-autocomplete-first-character-blacklist',
|
||||
);
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
/**
|
||||
* Fix problem with details/summary lines missing the drop arrows.
|
||||
*/
|
||||
@-moz-document url-prefix() {
|
||||
@media (min--moz-device-pixel-ratio: 0) {
|
||||
summary {
|
||||
display: list-item;
|
||||
}
|
||||
|
||||
@@ -59,6 +59,30 @@
|
||||
return typeof a === 'undefined' || typeof b === 'undefined';
|
||||
}
|
||||
|
||||
/**
|
||||
* Bitwise AND with a third undefined state.
|
||||
*
|
||||
* @function Drupal.states~ternary
|
||||
*
|
||||
* @param {*} a
|
||||
* Value a.
|
||||
* @param {*} b
|
||||
* Value b
|
||||
*
|
||||
* @return {bool}
|
||||
* The result.
|
||||
*/
|
||||
function ternary(a, b) {
|
||||
if (typeof a === 'undefined') {
|
||||
return b;
|
||||
}
|
||||
if (typeof b === 'undefined') {
|
||||
return a;
|
||||
}
|
||||
|
||||
return a && b;
|
||||
}
|
||||
|
||||
/**
|
||||
* Attaches the states.
|
||||
*
|
||||
@@ -305,18 +329,20 @@
|
||||
// bogus, we don't want to end up with an infinite loop.
|
||||
else if ($.isPlainObject(constraints)) {
|
||||
// This constraint is an object (AND).
|
||||
result = Object.keys(constraints).every(constraint => {
|
||||
const check = this.checkConstraints(
|
||||
constraints[constraint],
|
||||
selector,
|
||||
constraint,
|
||||
);
|
||||
/**
|
||||
* The checkConstraints() function's return value can be undefined. If
|
||||
* this so, consider it to have returned true.
|
||||
*/
|
||||
return typeof check === 'undefined' ? true : check;
|
||||
});
|
||||
// eslint-disable-next-line no-restricted-syntax
|
||||
for (const n in constraints) {
|
||||
if (constraints.hasOwnProperty(n)) {
|
||||
result = ternary(
|
||||
result,
|
||||
this.checkConstraints(constraints[n], selector, n),
|
||||
);
|
||||
// False and anything else will evaluate to false, so return when
|
||||
// any false condition is found.
|
||||
if (result === false) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
},
|
||||
|
||||
@@ -24,6 +24,17 @@
|
||||
return typeof a === 'undefined' || typeof b === 'undefined';
|
||||
}
|
||||
|
||||
function ternary(a, b) {
|
||||
if (typeof a === 'undefined') {
|
||||
return b;
|
||||
}
|
||||
if (typeof b === 'undefined') {
|
||||
return a;
|
||||
}
|
||||
|
||||
return a && b;
|
||||
}
|
||||
|
||||
Drupal.behaviors.states = {
|
||||
attach: function attach(context, settings) {
|
||||
var $states = $(context).find('[data-drupal-states]');
|
||||
@@ -127,8 +138,6 @@
|
||||
}
|
||||
},
|
||||
verifyConstraints: function verifyConstraints(constraints, selector) {
|
||||
var _this3 = this;
|
||||
|
||||
var result = void 0;
|
||||
if ($.isArray(constraints)) {
|
||||
var hasXor = $.inArray('xor', constraints) === -1;
|
||||
@@ -144,11 +153,15 @@
|
||||
}
|
||||
}
|
||||
} else if ($.isPlainObject(constraints)) {
|
||||
result = Object.keys(constraints).every(function (constraint) {
|
||||
var check = _this3.checkConstraints(constraints[constraint], selector, constraint);
|
||||
for (var n in constraints) {
|
||||
if (constraints.hasOwnProperty(n)) {
|
||||
result = ternary(result, this.checkConstraints(constraints[n], selector, n));
|
||||
|
||||
return typeof check === 'undefined' ? true : check;
|
||||
});
|
||||
if (result === false) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
},
|
||||
@@ -197,7 +210,7 @@
|
||||
|
||||
states.Trigger.prototype = {
|
||||
initialize: function initialize() {
|
||||
var _this4 = this;
|
||||
var _this3 = this;
|
||||
|
||||
var trigger = states.Trigger.states[this.state];
|
||||
|
||||
@@ -205,7 +218,7 @@
|
||||
trigger.call(window, this.element);
|
||||
} else {
|
||||
Object.keys(trigger || {}).forEach(function (event) {
|
||||
_this4.defaultTrigger(event, trigger[event]);
|
||||
_this3.defaultTrigger(event, trigger[event]);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -40,7 +40,7 @@ class GotoAction extends ConfigurableActionBase implements ContainerFactoryPlugi
|
||||
protected $unroutedUrlAssembler;
|
||||
|
||||
/**
|
||||
* Constructs a new DeleteNode object.
|
||||
* Constructs a GotoAction object.
|
||||
*
|
||||
* @param array $configuration
|
||||
* A configuration array containing information about the plugin instance.
|
||||
|
||||
@@ -94,7 +94,7 @@ class ItemsImporter implements ItemsImporterInterface {
|
||||
watchdog_exception('aggregator', $e);
|
||||
}
|
||||
|
||||
// Store instances in an array so we dont have to instantiate new objects.
|
||||
// Store instances in an array so we don't have to instantiate new objects.
|
||||
$processor_instances = [];
|
||||
foreach ($this->config->get('processors') as $processor) {
|
||||
try {
|
||||
|
||||
@@ -33,7 +33,7 @@ class BlockedIP extends DestinationBase implements ContainerFactoryPluginInterfa
|
||||
* @param string $plugin_id
|
||||
* The plugin ID.
|
||||
* @param mixed $plugin_definition
|
||||
* The plugin definiiton.
|
||||
* The plugin definition.
|
||||
* @param \Drupal\migrate\Plugin\MigrationInterface $migration
|
||||
* The current migration.
|
||||
* @param \Drupal\ban\BanIpManagerInterface $ban_manager
|
||||
|
||||
@@ -2,8 +2,7 @@
|
||||
|
||||
namespace Drupal\block_content\Plugin\migrate\source\d6;
|
||||
|
||||
use Drupal\migrate\Row;
|
||||
use Drupal\migrate_drupal\Plugin\migrate\source\DrupalSqlBase;
|
||||
use Drupal\block_content\Plugin\migrate\source\d7\BlockCustomTranslation as D7BlockCustomTranslation;
|
||||
|
||||
/**
|
||||
* Gets Drupal 6 i18n custom block translations from database.
|
||||
@@ -13,97 +12,12 @@ use Drupal\migrate_drupal\Plugin\migrate\source\DrupalSqlBase;
|
||||
* source_module = "i18nblocks"
|
||||
* )
|
||||
*/
|
||||
class BoxTranslation extends DrupalSqlBase {
|
||||
class BoxTranslation extends D7BlockCustomTranslation {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
* Drupal 6 table names.
|
||||
*/
|
||||
public function query() {
|
||||
// Build a query based on i18n_strings table where each row has the
|
||||
// translation for only one property, either title or description. The
|
||||
// method prepareRow() is then used to obtain the translation for the
|
||||
// other property.
|
||||
$query = $this->select('boxes', 'b')
|
||||
->fields('b', ['bid', 'format', 'body'])
|
||||
->fields('i18n', ['property'])
|
||||
->fields('lt', ['lid', 'translation', 'language'])
|
||||
->orderBy('b.bid')
|
||||
->isNotNull('lt.lid');
|
||||
|
||||
// Use 'title' for the info field to match the property name in the
|
||||
// i18n_strings table.
|
||||
$query->addField('b', 'info', 'title');
|
||||
|
||||
// Add in the property, which is either title or body. Cast the bid to text
|
||||
// so PostgreSQL can make the join.
|
||||
$query->leftJoin('i18n_strings', 'i18n', 'i18n.objectid = CAST(b.bid as CHAR(255))');
|
||||
$query->condition('i18n.type', 'block');
|
||||
|
||||
// Add in the translation for the property.
|
||||
$query->leftJoin('locales_target', 'lt', 'lt.lid = i18n.lid');
|
||||
return $query;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function prepareRow(Row $row) {
|
||||
$language = $row->getSourceProperty('language');
|
||||
$bid = $row->getSourceProperty('bid');
|
||||
|
||||
// If this row has been migrated it is a duplicate then skip it.
|
||||
if ($this->idMap->lookupDestinationIds(['bid' => $bid, 'language' => $language])) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
// Save the translation for this property.
|
||||
$property = $row->getSourceProperty('property');
|
||||
$row->setSourceProperty($property . '_translated', $row->getSourceProperty('translation'));
|
||||
|
||||
// Get the translation for the property not already in the row.
|
||||
$translation = ($property === 'title') ? 'body' : 'title';
|
||||
$query = $this->select('i18n_strings', 'i18n')
|
||||
->fields('i18n', ['lid'])
|
||||
->condition('i18n.property', $translation)
|
||||
->condition('i18n.objectid', $bid);
|
||||
$query->leftJoin('locales_target', 'lt', 'i18n.lid = lt.lid');
|
||||
$query->condition('lt.language', $language)
|
||||
->addField('lt', 'translation');
|
||||
$results = $query->execute()->fetchAssoc();
|
||||
if (!$results) {
|
||||
$row->setSourceProperty($translation . '_translated', NULL);
|
||||
}
|
||||
else {
|
||||
$row->setSourceProperty($translation . '_translated', $results['translation']);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function fields() {
|
||||
return [
|
||||
'bid' => $this->t('The block numeric identifier.'),
|
||||
'format' => $this->t('Input format of the custom block/box content.'),
|
||||
'lid' => $this->t('i18n_string table id'),
|
||||
'language' => $this->t('Language for this field.'),
|
||||
'property' => $this->t('Block property'),
|
||||
'translation' => $this->t('The translation of the value of "property".'),
|
||||
'title' => $this->t('Block title.'),
|
||||
'title_translated' => $this->t('Block title translation.'),
|
||||
'body' => $this->t('Block body.'),
|
||||
'body_translated' => $this->t('Block body translation.'),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getIds() {
|
||||
$ids['bid']['type'] = 'integer';
|
||||
$ids['bid']['alias'] = 'b';
|
||||
$ids['language']['type'] = 'string';
|
||||
return $ids;
|
||||
}
|
||||
const CUSTOM_BLOCK_TABLE = 'boxes';
|
||||
const I18N_STRING_TABLE = 'i18n_strings';
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,99 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\block_content\Plugin\migrate\source\d7;
|
||||
|
||||
use Drupal\migrate\Row;
|
||||
use Drupal\migrate_drupal\Plugin\migrate\source\DrupalSqlBase;
|
||||
use Drupal\content_translation\Plugin\migrate\source\I18nQueryTrait;
|
||||
|
||||
/**
|
||||
* Gets Drupal 7 custom block translation from database.
|
||||
*
|
||||
* @MigrateSource(
|
||||
* id = "d7_block_custom_translation",
|
||||
* source_module = "block"
|
||||
* )
|
||||
*/
|
||||
class BlockCustomTranslation extends DrupalSqlBase {
|
||||
|
||||
use I18nQueryTrait;
|
||||
|
||||
/**
|
||||
* Drupal 7 table names.
|
||||
*/
|
||||
const CUSTOM_BLOCK_TABLE = 'block_custom';
|
||||
const I18N_STRING_TABLE = 'i18n_string';
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function query() {
|
||||
// Build a query based on blockCustomTable table where each row has the
|
||||
// translation for only one property, either title or description. The
|
||||
// method prepareRow() is then used to obtain the translation for the
|
||||
// other property.
|
||||
$query = $this->select(static::CUSTOM_BLOCK_TABLE, 'b')
|
||||
->fields('b', ['bid', 'format', 'body'])
|
||||
->fields('i18n', ['property'])
|
||||
->fields('lt', ['lid', 'translation', 'language'])
|
||||
->orderBy('b.bid')
|
||||
->isNotNull('lt.lid');
|
||||
|
||||
// Use 'title' for the info field to match the property name in
|
||||
// i18nStringTable.
|
||||
$query->addField('b', 'info', 'title');
|
||||
|
||||
// Add in the property, which is either title or body. Cast the bid to text
|
||||
// so PostgreSQL can make the join.
|
||||
$query->leftJoin(static::I18N_STRING_TABLE, 'i18n', 'i18n.objectid = CAST(b.bid as CHAR(255))');
|
||||
$query->condition('i18n.type', 'block');
|
||||
|
||||
// Add in the translation for the property.
|
||||
$query->leftJoin('locales_target', 'lt', 'lt.lid = i18n.lid');
|
||||
return $query;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function prepareRow(Row $row) {
|
||||
parent::prepareRow($row);
|
||||
// Set the i18n string table for use in I18nQueryTrait.
|
||||
$this->i18nStringTable = static::I18N_STRING_TABLE;
|
||||
// Save the translation for this property.
|
||||
$property_in_row = $row->getSourceProperty('property');
|
||||
// Get the translation for the property not already in the row and save it
|
||||
// in the row.
|
||||
$property_not_in_row = ($property_in_row === 'title') ? 'body' : 'title';
|
||||
return $this->getPropertyNotInRowTranslation($row, $property_not_in_row, 'bid', $this->idMap);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function fields() {
|
||||
return [
|
||||
'bid' => $this->t('The block numeric identifier.'),
|
||||
'format' => $this->t('Input format of the custom block/box content.'),
|
||||
'lid' => $this->t('i18n_string table id'),
|
||||
'language' => $this->t('Language for this field.'),
|
||||
'property' => $this->t('Block property'),
|
||||
'translation' => $this->t('The translation of the value of "property".'),
|
||||
'title' => $this->t('Block title.'),
|
||||
'title_translated' => $this->t('Block title translation.'),
|
||||
'body' => $this->t('Block body.'),
|
||||
'body_translated' => $this->t('Block body translation.'),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getIds() {
|
||||
$ids['bid']['type'] = 'integer';
|
||||
$ids['bid']['alias'] = 'b';
|
||||
$ids['language']['type'] = 'string';
|
||||
return $ids;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\Tests\block_content\Kernel\Migrate\d7;
|
||||
|
||||
use Drupal\block_content\Entity\BlockContent;
|
||||
use Drupal\Tests\migrate_drupal\Kernel\d7\MigrateDrupal7TestBase;
|
||||
|
||||
/**
|
||||
* Tests migration of i18n custom block strings.
|
||||
*
|
||||
* @group migrate_drupal_7
|
||||
*/
|
||||
class MigrateCustomBlockContentTranslationTest extends MigrateDrupal7TestBase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static $modules = [
|
||||
'block_content',
|
||||
'content_translation',
|
||||
'filter',
|
||||
'language',
|
||||
'text',
|
||||
// Required for translation migrations.
|
||||
'migrate_drupal_multilingual',
|
||||
];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setUp() {
|
||||
parent::setUp();
|
||||
$this->installConfig(['block_content']);
|
||||
$this->installEntitySchema('block_content');
|
||||
$this->executeMigrations([
|
||||
'language',
|
||||
'd7_filter_format',
|
||||
'block_content_type',
|
||||
'block_content_body_field',
|
||||
'd7_custom_block',
|
||||
'd7_custom_block_translation',
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the Drupal 7 i18n custom block strings to Drupal 8 migration.
|
||||
*/
|
||||
public function testCustomBlockContentTranslation() {
|
||||
/** @var \Drupal\block_content\Entity\BlockContent $block */
|
||||
$block = BlockContent::load(1)->getTranslation('fr');
|
||||
$this->assertSame('fr - Mildly amusing limerick of the day', $block->label());
|
||||
$this->assertGreaterThanOrEqual($block->getChangedTime(), \Drupal::time()->getRequestTime());
|
||||
$this->assertLessThanOrEqual(time(), $block->getChangedTime());
|
||||
$this->assertSame('fr', $block->language()->getId());
|
||||
$translation = "fr - A fellow jumped off a high wall\r\nAnd had a most terrible fall\r\nHe went back to bed\r\nWith a bump on his head\r\nThat's why you don't jump off a wall";
|
||||
$this->assertSame($translation, $block->body->value);
|
||||
$this->assertSame('filtered_html', $block->body->format);
|
||||
|
||||
$block = $block->getTranslation('is');
|
||||
$this->assertSame('is - Mildly amusing limerick of the day', $block->label());
|
||||
$this->assertGreaterThanOrEqual($block->getChangedTime(), \Drupal::time()->getRequestTime());
|
||||
$this->assertLessThanOrEqual(time(), $block->getChangedTime());
|
||||
$this->assertSame('is', $block->language()->getId());
|
||||
$text = "A fellow jumped off a high wall\r\nAnd had a most terrible fall\r\nHe went back to bed\r\nWith a bump on his head\r\nThat's why you don't jump off a wall";
|
||||
$this->assertSame($text, $block->body->value);
|
||||
$this->assertSame('filtered_html', $block->body->format);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,148 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\Tests\block_content\Kernel\Plugin\migrate\source\d7;
|
||||
|
||||
use Drupal\Tests\migrate\Kernel\MigrateSqlSourceTestBase;
|
||||
|
||||
/**
|
||||
* Tests i18n custom block translations source plugin.
|
||||
*
|
||||
* @covers \Drupal\block_content\Plugin\migrate\source\d7\BlockCustomTranslation
|
||||
*
|
||||
* @group content_translation
|
||||
*/
|
||||
class BlockCustomTranslationTest extends MigrateSqlSourceTestBase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static $modules = ['block_content', 'migrate_drupal'];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function providerSource() {
|
||||
$tests = [];
|
||||
|
||||
// The source data.
|
||||
$tests[0]['database']['block_custom'] = [
|
||||
[
|
||||
'bid' => 1,
|
||||
'body' => 'box 1 body',
|
||||
'info' => 'box 1 title',
|
||||
'format' => '2',
|
||||
],
|
||||
[
|
||||
'bid' => 2,
|
||||
'body' => 'box 2 body',
|
||||
'info' => 'box 2 title',
|
||||
'format' => '2',
|
||||
],
|
||||
];
|
||||
|
||||
$tests[0]['database']['i18n_string'] = [
|
||||
[
|
||||
'lid' => 1,
|
||||
'objectid' => 1,
|
||||
'type' => 'block',
|
||||
'property' => 'title',
|
||||
'objectindex' => 1,
|
||||
'format' => 0,
|
||||
],
|
||||
[
|
||||
'lid' => 2,
|
||||
'objectid' => 1,
|
||||
'type' => 'block',
|
||||
'property' => 'body',
|
||||
'objectindex' => 1,
|
||||
'format' => 0,
|
||||
],
|
||||
[
|
||||
'lid' => 3,
|
||||
'objectid' => 2,
|
||||
'type' => 'block',
|
||||
'property' => 'body',
|
||||
'objectindex' => 2,
|
||||
'format' => 2,
|
||||
],
|
||||
];
|
||||
|
||||
$tests[0]['database']['locales_target'] = [
|
||||
[
|
||||
'lid' => 1,
|
||||
'language' => 'fr',
|
||||
'translation' => 'fr - title translation',
|
||||
'plid' => 0,
|
||||
'plural' => 0,
|
||||
'i18n_status' => 0,
|
||||
],
|
||||
[
|
||||
'lid' => 2,
|
||||
'language' => 'fr',
|
||||
'translation' => 'fr - body translation',
|
||||
'plid' => 0,
|
||||
'plural' => 0,
|
||||
'i18n_status' => 0,
|
||||
],
|
||||
[
|
||||
'lid' => 3,
|
||||
'language' => 'zu',
|
||||
'translation' => 'zu - body translation',
|
||||
'plid' => 0,
|
||||
'plural' => 0,
|
||||
'i18n_status' => 0,
|
||||
],
|
||||
];
|
||||
|
||||
$tests[0]['database']['system'] = [
|
||||
[
|
||||
'type' => 'module',
|
||||
'name' => 'system',
|
||||
'schema_version' => '7001',
|
||||
'status' => '1',
|
||||
],
|
||||
];
|
||||
|
||||
$tests[0]['expected_results'] = [
|
||||
[
|
||||
'lid' => '1',
|
||||
'property' => 'title',
|
||||
'language' => 'fr',
|
||||
'translation' => 'fr - title translation',
|
||||
'bid' => '1',
|
||||
'format' => '2',
|
||||
'title_translated' => 'fr - title translation',
|
||||
'body_translated' => 'fr - body translation',
|
||||
'title' => 'box 1 title',
|
||||
'body' => 'box 1 body',
|
||||
],
|
||||
[
|
||||
'lid' => '2',
|
||||
'property' => 'body',
|
||||
'language' => 'fr',
|
||||
'translation' => 'fr - body translation',
|
||||
'bid' => '1',
|
||||
'format' => '2',
|
||||
'title_translated' => 'fr - title translation',
|
||||
'body_translated' => 'fr - body translation',
|
||||
'title' => 'box 1 title',
|
||||
'body' => 'box 1 body',
|
||||
],
|
||||
[
|
||||
'lid' => '3',
|
||||
'property' => 'body',
|
||||
'language' => 'zu',
|
||||
'translation' => 'zu - body translation',
|
||||
'bid' => '2',
|
||||
'format' => '2',
|
||||
'title_translated' => NULL,
|
||||
'body_translated' => 'zu - body translation',
|
||||
'title' => 'box 2 title',
|
||||
'body' => 'box 2 body',
|
||||
],
|
||||
];
|
||||
|
||||
return $tests;
|
||||
}
|
||||
|
||||
}
|
||||