diff --git a/web/core/.stylelintrc.json b/web/core/.stylelintrc.json index d9d0ede9f52fbae052dbdbb5d16919297a402d2b..87d15295345632c5b09285e6e346cb3d5fbc9e71 100644 --- a/web/core/.stylelintrc.json +++ b/web/core/.stylelintrc.json @@ -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, { diff --git a/web/core/MAINTAINERS.txt b/web/core/MAINTAINERS.txt index e4120cc3d82a66dee60c191ec1a3d4052f47dcaf..a505c631ab135c77e8c297f6d825624ec9929480 100644 --- a/web/core/MAINTAINERS.txt +++ b/web/core/MAINTAINERS.txt @@ -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 - ? @@ -285,9 +284,9 @@ Menu UI Migrate - Adam Globus-Hoenich 'phenaproxima' https://www.drupal.org/u/phenaproxima - Lucas Hedding 'heddn' https://www.drupal.org/u/heddn +- Michael Lutz 'mikelutz' https://www.drupal.org/u/mikelutz - Markus Sipilä 'masipila' https://www.drupal.org/u/masipila - Vicki Spagnolo 'quietone' https://www.drupal.org/u/quietone -- Maxime Turcotte 'maxocub' https://www.drupal.org/u/maxocub Node - Tim Millwood 'timmillwood' https://www.drupal.org/u/timmillwood @@ -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 diff --git a/web/core/UPDATE.txt b/web/core/UPDATE.txt index ebc4e827eb7fff7f552c81b85f8ee881d3e88096..efcb5e9dd8248c99cac72e9049a77a4bc3f87e36 100644 --- a/web/core/UPDATE.txt +++ b/web/core/UPDATE.txt @@ -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): + + /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. - 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: + 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. 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. -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. + 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. + +3. 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 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. -5. Re-apply any modifications to files such as .htaccess, composer.json, or - robots.txt. + - 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. -6. Run update.php by visiting http://www.example.com/update.php (replace + 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. - diff --git a/web/core/assets/vendor/ckeditor/CHANGES.md b/web/core/assets/vendor/ckeditor/CHANGES.md index 1205b92adfad727e98ec1707ed3e0ff2bab71891..95af6ed814376ce58b0f798ffacc048fb5a5140f 100644 --- a/web/core/assets/vendor/ckeditor/CHANGES.md +++ b/web/core/assets/vendor/ckeditor/CHANGES.md @@ -1,6 +1,36 @@ CKEditor 4 Changelog ==================== +## CKEditor 4.10.1 + +Fixed Issues: + +* [#2114](https://github.com/ckeditor/ckeditor-dev/issues/2114): Fixed: [Autocomplete](https://ckeditor.com/cke4/addon/autocomplete) cannot be initialized before [`instanceReady`](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_editor.html#event-instanceReady). +* [#2107](https://github.com/ckeditor/ckeditor-dev/issues/2107): Fixed: Holding and releasing the mouse button is not inserting an [autocomplete](https://ckeditor.com/cke4/addon/autocomplete) suggestion. +* [#2167](https://github.com/ckeditor/ckeditor-dev/issues/2167): Fixed: Matching in [Emoji](https://ckeditor.com/cke4/addon/emoji) plugin is not case insensitive. +* [#2195](https://github.com/ckeditor/ckeditor-dev/issues/2195): Fixed: [Emoji](https://ckeditor.com/cke4/addon/emoji) shows the suggestion box when the colon is preceded with other characters than white space. +* [#2169](https://github.com/ckeditor/ckeditor-dev/issues/2169): [Edge] Fixed: Error thrown when pasting into the editor. +* [#1084](https://github.com/ckeditor/ckeditor-dev/issues/1084) Fixed: Using the "Automatic" option with [Color Button](https://ckeditor.com/cke4/addon/colorbutton) on a text with the color already defined sets an invalid color value. +* [#2271](https://github.com/ckeditor/ckeditor-dev/issues/2271): Fixed: Custom color name not used as a label in the [Color Button](https://ckeditor.com/cke4/addon/image2) plugin. Thanks to [Eric Geloen](https://github.com/egeloen)! +* [#2296](https://github.com/ckeditor/ckeditor-dev/issues/2296): Fixed: [Color Button](https://ckeditor.com/cke4/addon/colorbutton) throws an error when activated on a content containing HTML comments. +* [#966](https://github.com/ckeditor/ckeditor-dev/issues/966): Fixed: Executing [`editor.destroy()`](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_editor.html#method-destroy) during the [file upload](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_fileTools_uploadWidgetDefinition.html#property-onUploading) throws an error. Thanks to [Maksim Makarevich](https://github.com/MaksimMakarevich)! +* [#1719](https://github.com/ckeditor/ckeditor-dev/issues/1719): Fixed: <kbd>Ctrl</kbd>/<kbd>Cmd</kbd> + <kbd>A</kbd> inadvertently focuses inline editor if it is starting and ending with a list. Thanks to [theNailz](https://github.com/theNailz)! +* [#1046](https://github.com/ckeditor/ckeditor-dev/issues/1046): Fixed: Subsequent new links do not include the `id` attribute. Thanks to [Nathan Samson](https://github.com/nathansamson)! +* [#1348](https://github.com/ckeditor/ckeditor-dev/issues/1348): Fixed: [Enhanced Image](https://ckeditor.com/cke4/addon/image2) plugin aspect ratio locking uses an old width and height on image URL change. +* [#1791](https://github.com/ckeditor/ckeditor-dev/issues/1791): Fixed: [Image](https://ckeditor.com/cke4/addon/image) and [Enhanced Image](https://ckeditor.com/cke4/addon/image2) plugins can be enabled when [Easy Image](https://ckeditor.com/cke4/addon/easyimage) is present. +* [#2254](https://github.com/ckeditor/ckeditor-dev/issues/2254): Fixed: [Image](https://ckeditor.com/cke4/addon/image) ratio locking is too precise for resized images. Thanks to [Jonathan Gilbert](https://github.com/logiclrd)! +* [#1184](https://github.com/ckeditor/ckeditor-dev/issues/1184): [IE8-11] Fixed: Copying and pasting data in [read-only mode](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_editor.html#property-readOnly) throws an error. +* [#1916](https://github.com/ckeditor/ckeditor-dev/issues/1916): [IE9-11] Fixed: Pressing the <kbd>Delete</kbd> key in [read-only mode](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_editor.html#property-readOnly) throws an error. +* [#2003](https://github.com/ckeditor/ckeditor-dev/issues/2003): [Firefox] Fixed: Right-clicking multiple selected table cells containing empty paragraphs removes the selection. +* [#1816](https://github.com/ckeditor/ckeditor-dev/issues/1816): Fixed: Table breaks when <kbd>Enter</kbd> is pressed over the [Table Selection](https://ckeditor.com/cke4/addon/tableselection) plugin. +* [#1115](https://github.com/ckeditor/ckeditor-dev/issues/1115): Fixed: The `<font>` tag is not preserved when proper configuration is provided and a style is applied by the [Font](https://ckeditor.com/cke4/addon/font) plugin. +* [#727](https://github.com/ckeditor/ckeditor-dev/issues/727): Fixed: Custom styles may be invisible in the [Styles Combo](https://ckeditor.com/cke4/addon/stylescombo) plugin. +* [#988](https://github.com/ckeditor/ckeditor-dev/issues/988): Fixed: ACF-enabled custom elements prefixed with `object`, `embed`, `param` are removed from the editor content. + +API Changes: + +* [#2249](https://github.com/ckeditor/ckeditor-dev/issues/1791): Added the [`editor.plugins.detectConflict()`](https://ckeditor.com/docs/ckeditor4/latest/CKEDITOR_editor_plugins.html#method-detectConflict) method finding conflicts between provided plugins. + ## CKEditor 4.10 New Features: @@ -8,7 +38,7 @@ New Features: * [#1751](https://github.com/ckeditor/ckeditor-dev/issues/1751): Introduced the **Autocomplete** feature that consists of the following plugins: * [Autocomplete](https://ckeditor.com/cke4/addon/autocomplete) – Provides contextual completion feature for custom text matches based on user input. * [Text Watcher](https://ckeditor.com/cke4/addon/textWatcher) – Checks whether an editor's text change matches the chosen criteria. - * [Text Match](https://ckeditor.com/cke4/addon/textMatch) – Allows to search [`CKEDITOR.dom.range`](https://docs.ckeditor.com/ckeditor4/latest/api/CKEDITOR_dom_range.html) for matching text. + * [Text Match](https://ckeditor.com/cke4/addon/textMatch) – Allows to search [`CKEDITOR.dom.range`](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_dom_range.html) for matching text. * [#1703](https://github.com/ckeditor/ckeditor-dev/issues/1703): Introduced the [Mentions](https://ckeditor.com/cke4/addon/mentions) plugin providing smart completion feature for custom text matches based on user input starting with a chosen marker character. * [#1746](https://github.com/ckeditor/ckeditor-dev/issues/1703): Introduced the [Emoji](https://ckeditor.com/cke4/addon/emoji) plugin providing completion feature for emoji ideograms. * [#1761](https://github.com/ckeditor/ckeditor-dev/issues/1761): The [Auto Link](https://ckeditor.com/cke4/addon/autolink) plugin now supports email links. @@ -17,22 +47,22 @@ Fixed Issues: * [#1458](https://github.com/ckeditor/ckeditor-dev/issues/1458): [Edge] Fixed: After blurring the editor it takes 2 clicks to focus a widget. * [#1034](https://github.com/ckeditor/ckeditor-dev/issues/1034): Fixed: JAWS leaves forms mode after pressing the <kbd>Enter</kbd> key in an inline editor instance. -* [#1748](https://github.com/ckeditor/ckeditor-dev/pull/1748): Fixed: Missing [`CKEDITOR.dialog.definition.onHide`](https://docs.ckeditor.com/ckeditor4/latest/api/CKEDITOR_dialog_definition.html#property-onHide) API documentation. Thanks to [sunnyone](https://github.com/sunnyone)! -* [#1321](https://github.com/ckeditor/ckeditor-dev/issues/1321): Ideographic space character (`\u3000`) is lost when pasting text. -* [#1776](https://github.com/ckeditor/ckeditor-dev/issues/1776): Empty caption placeholder of the [Image Base](https://ckeditor.com/cke4/addon/imagebase) plugin is not hidden when blurred. -* [#1592](https://github.com/ckeditor/ckeditor-dev/issues/1592): The [Image Base](https://ckeditor.com/cke4/addon/imagebase) plugin caption is not visible after paste. -* [#620](https://github.com/ckeditor/ckeditor-dev/issues/620): Fixed: The [`config.forcePasteAsPlainText`](https://docs.ckeditor.com/ckeditor4/latest/api/CKEDITOR_config.html#cfg-forcePasteAsPlainText) option is not respected in internal and cross-editor pasting. +* [#1748](https://github.com/ckeditor/ckeditor-dev/pull/1748): Fixed: Missing [`CKEDITOR.dialog.definition.onHide`](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_dialog_definition.html#property-onHide) API documentation. Thanks to [sunnyone](https://github.com/sunnyone)! +* [#1321](https://github.com/ckeditor/ckeditor-dev/issues/1321): Fixed: Ideographic space character (`\u3000`) is lost when pasting text. +* [#1776](https://github.com/ckeditor/ckeditor-dev/issues/1776): Fixed: Empty caption placeholder of the [Image Base](https://ckeditor.com/cke4/addon/imagebase) plugin is not hidden when blurred. +* [#1592](https://github.com/ckeditor/ckeditor-dev/issues/1592): Fixed: The [Image Base](https://ckeditor.com/cke4/addon/imagebase) plugin caption is not visible after paste. +* [#620](https://github.com/ckeditor/ckeditor-dev/issues/620): Fixed: The [`config.forcePasteAsPlainText`](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_config.html#cfg-forcePasteAsPlainText) option is not respected in internal and cross-editor pasting. * [#1467](https://github.com/ckeditor/ckeditor-dev/issues/1467): Fixed: The resizing cursor of the [Table Resize](https://ckeditor.com/cke4/addon/tableresize) plugin appearing in the middle of a merged cell. API Changes: * [#850](https://github.com/ckeditor/ckeditor-dev/issues/850): Backward incompatibility: Replaced the `replace` dialog from the [Find / Replace](https://ckeditor.com/cke4/addon/find) plugin with a `tabId` option in the `find` command. -* [#1582](https://github.com/ckeditor/ckeditor-dev/issues/1582): The [`CKEDITOR.editor.addCommand()`](https://docs.ckeditor.com/ckeditor4/latest/api/CKEDITOR_editor.html#method-addCommand) method can now accept a [`CKEDITOR.command`](https://docs.ckeditor.com/ckeditor4/latest/api/CKEDITOR_command.html) instance as a parameter. -* [#1712](https://github.com/ckeditor/ckeditor-dev/issues/1712): The [`extraPlugins`](https://docs.ckeditor.com/ckeditor4/latest/api/CKEDITOR_config.html#cfg-extraPlugins), [`removePlugins`](https://docs.ckeditor.com/ckeditor4/latest/api/CKEDITOR_config.html#cfg-removePlugins) and [`plugins`](https://docs.ckeditor.com/ckeditor4/latest/api/CKEDITOR_config.html#cfg-plugins) configuration options allow whitespace. -* [#1802](https://github.com/ckeditor/ckeditor-dev/issues/1802): The [`extraPlugins`](https://docs.ckeditor.com/ckeditor4/latest/api/CKEDITOR_config.html#cfg-extraPlugins), [`removePlugins`](https://docs.ckeditor.com/ckeditor4/latest/api/CKEDITOR_config.html#cfg-removePlugins) and [`plugins`](https://docs.ckeditor.com/ckeditor4/latest/api/CKEDITOR_config.html#cfg-plugins) configuration options allow passing plugin names as an array. -* [#1724](https://github.com/ckeditor/ckeditor-dev/issues/1724): Added an option to the [`getClientRect()`](https://docs.ckeditor.com/ckeditor4/latest/api/CKEDITOR_dom_element.html#method-getClientRect) function allowing to retrieve an absolute bounding rectangle of the element, i.e. a position relative to the upper-left corner of the topmost viewport. -* [#1498](https://github.com/ckeditor/ckeditor-dev/issues/1498) : Added a new [`getClientRects()`](https://docs.ckeditor.com/ckeditor4/latest/api/CKEDITOR_dom_range.html#method-getClientRects) method to `CKEDITOR.dom.range`. It returns a list of rectangles for each selected element. -* [#1993](https://github.com/ckeditor/ckeditor-dev/issues/1993): Added the [`CKEDITOR.tools.throttle()`](http://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR_tools.html#method-throttle) function. +* [#1582](https://github.com/ckeditor/ckeditor-dev/issues/1582): The [`CKEDITOR.editor.addCommand()`](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_editor.html#method-addCommand) method can now accept a [`CKEDITOR.command`](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_command.html) instance as a parameter. +* [#1712](https://github.com/ckeditor/ckeditor-dev/issues/1712): The [`extraPlugins`](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_config.html#cfg-extraPlugins), [`removePlugins`](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_config.html#cfg-removePlugins) and [`plugins`](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_config.html#cfg-plugins) configuration options allow whitespace. +* [#1802](https://github.com/ckeditor/ckeditor-dev/issues/1802): The [`extraPlugins`](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_config.html#cfg-extraPlugins), [`removePlugins`](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_config.html#cfg-removePlugins) and [`plugins`](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_config.html#cfg-plugins) configuration options allow passing plugin names as an array. +* [#1724](https://github.com/ckeditor/ckeditor-dev/issues/1724): Added an option to the [`getClientRect()`](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_dom_element.html#method-getClientRect) function allowing to retrieve an absolute bounding rectangle of the element, i.e. a position relative to the upper-left corner of the topmost viewport. +* [#1498](https://github.com/ckeditor/ckeditor-dev/issues/1498) : Added a new [`getClientRects()`](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_dom_range.html#method-getClientRects) method to `CKEDITOR.dom.range`. It returns a list of rectangles for each selected element. +* [#1993](https://github.com/ckeditor/ckeditor-dev/issues/1993): Added the [`CKEDITOR.tools.throttle()`](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_tools.html#method-throttle) function. Other Changes: @@ -79,9 +109,9 @@ New Features: * [Cloud Services](https://ckeditor.com/cke4/addon/cloudservices) * [Image Base](https://ckeditor.com/cke4/addon/imagebase) * [#1338](https://github.com/ckeditor/ckeditor-dev/issues/1338): Keystroke labels are displayed for function keys (like F7, F8). -* [#643](https://github.com/ckeditor/ckeditor-dev/issues/643): The [File Browser](https://ckeditor.com/cke4/addon/filebrowser) plugin can now upload files using XHR requests. This allows for setting custom HTTP headers using the [`config.fileTools_requestHeaders`](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR.config-cfg-fileTools_requestHeaders) configuration option. +* [#643](https://github.com/ckeditor/ckeditor-dev/issues/643): The [File Browser](https://ckeditor.com/cke4/addon/filebrowser) plugin can now upload files using XHR requests. This allows for setting custom HTTP headers using the [`config.fileTools_requestHeaders`](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_config.html#cfg-fileTools_requestHeaders) configuration option. * [#1365](https://github.com/ckeditor/ckeditor-dev/issues/1365): The [File Browser](https://ckeditor.com/cke4/addon/filebrowser) plugin uses XHR requests by default. -* [#1399](https://github.com/ckeditor/ckeditor-dev/issues/1399): Added the possibility to set [`CKEDITOR.config.startupFocus`](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR.config-cfg-startupFocus) as `start` or `end` to specify where the editor focus should be after the initialization. +* [#1399](https://github.com/ckeditor/ckeditor-dev/issues/1399): Added the possibility to set [`CKEDITOR.config.startupFocus`](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_config.html#cfg-startupFocus) as `start` or `end` to specify where the editor focus should be after the initialization. * [#1441](https://github.com/ckeditor/ckeditor-dev/issues/1441): The [Magic Line](https://ckeditor.com/cke4/addon/magicline) plugin line element can now be identified by the `data-cke-magic-line="1"` attribute. Fixed Issues: @@ -89,16 +119,16 @@ Fixed Issues: * [#595](https://github.com/ckeditor/ckeditor-dev/issues/595): Fixed: Pasting does not work on mobile devices. * [#869](https://github.com/ckeditor/ckeditor-dev/issues/869): Fixed: Empty selection clears cached clipboard data in the editor. * [#1419](https://github.com/ckeditor/ckeditor-dev/issues/1419): Fixed: The [Widget Selection](https://ckeditor.com/cke4/addon/widgetselection) plugin selects the editor content with the <kbd>Alt+A</kbd> key combination on Windows. -* [#1274](https://github.com/ckeditor/ckeditor-dev/issues/1274): Fixed: [Balloon Toolbar](https://ckeditor.com/cke4/addon/balloontoolbar) does not match a single selected image using the [`contextDefinition.cssSelector`](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR.plugins.balloontoolbar.contextDefinition-property-cssSelector) matcher. +* [#1274](https://github.com/ckeditor/ckeditor-dev/issues/1274): Fixed: [Balloon Toolbar](https://ckeditor.com/cke4/addon/balloontoolbar) does not match a single selected image using the [`contextDefinition.cssSelector`](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_plugins_balloontoolbar_contextDefinition.html#property-cssSelector) matcher. * [#1232](https://github.com/ckeditor/ckeditor-dev/issues/1232): Fixed: [Balloon Toolbar](https://ckeditor.com/cke4/addon/balloontoolbar) buttons should be registered as focusable elements. -* [#1342](https://github.com/ckeditor/ckeditor-dev/issues/1342): Fixed: [Balloon Toolbar](https://ckeditor.com/cke4/addon/balloontoolbar) should be re-positioned after the [`change`](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR.editor-event-change) event. +* [#1342](https://github.com/ckeditor/ckeditor-dev/issues/1342): Fixed: [Balloon Toolbar](https://ckeditor.com/cke4/addon/balloontoolbar) should be re-positioned after the [`change`](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_editor.html#event-change) event. * [#1426](https://github.com/ckeditor/ckeditor-dev/issues/1426): [IE8-9] Fixed: Missing [Balloon Toolbar](https://ckeditor.com/cke4/addon/balloontoolbar) background in the [Kama](https://ckeditor.com/cke4/addon/kama) skin. Thanks to [Christian Elmer](https://github.com/keinkurt)! * [#1470](https://github.com/ckeditor/ckeditor-dev/issues/1470): Fixed: [Balloon Toolbar](https://ckeditor.com/cke4/addon/balloontoolbar) is not visible after drag and drop of a widget it is attached to. * [#1048](https://github.com/ckeditor/ckeditor-dev/issues/1048): Fixed: [Balloon Panel](https://ckeditor.com/cke4/addon/balloonpanel) is not positioned properly when a margin is added to its non-static parent. * [#889](https://github.com/ckeditor/ckeditor-dev/issues/889): Fixed: Unclear error message for width and height fields in the [Image](https://ckeditor.com/cke4/addon/image) and [Enhanced Image](https://ckeditor.com/cke4/addon/image2) plugins. * [#859](https://github.com/ckeditor/ckeditor-dev/issues/859): Fixed: Cannot edit a link after a double-click on the text in the link. -* [#1013](https://github.com/ckeditor/ckeditor-dev/issues/1013): Fixed: [Paste from Word](https://ckeditor.com/cke4/addon/pastefromword) does not work correctly with the [`config.forcePasteAsPlainText`](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR.config-cfg-forcePasteAsPlainText) option. -* [#1356](https://github.com/ckeditor/ckeditor-dev/issues/1356): Fixed: [Border parse function](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR.tools.style.parse-method-border) does not allow spaces in the color value. +* [#1013](https://github.com/ckeditor/ckeditor-dev/issues/1013): Fixed: [Paste from Word](https://ckeditor.com/cke4/addon/pastefromword) does not work correctly with the [`config.forcePasteAsPlainText`](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_config.html#cfg-forcePasteAsPlainText) option. +* [#1356](https://github.com/ckeditor/ckeditor-dev/issues/1356): Fixed: [Border parse function](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_tools_style_parse.html#method-border) does not allow spaces in the color value. * [#1010](https://github.com/ckeditor/ckeditor-dev/issues/1010): Fixed: The CSS `border` shorthand property was incorrectly expanded ignoring the `border-color` style. * [#1535](https://github.com/ckeditor/ckeditor-dev/issues/1535): Fixed: [Widget](https://ckeditor.com/cke4/addon/widget) mouseover border contrast is insufficient. * [#1516](https://github.com/ckeditor/ckeditor-dev/issues/1516): Fixed: Fake selection allows removing content in read-only mode using the <kbd>Backspace</kbd> and <kbd>Delete</kbd> keys. @@ -107,13 +137,13 @@ Fixed Issues: API Changes: -* [#1346](https://github.com/ckeditor/ckeditor-dev/issues/1346): [Balloon Toolbar](https://ckeditor.com/cke4/addon/balloontoolbar) [context manager API](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR.plugins.balloontoolbar.contextManager) is now available in the [`pluginDefinition.init()`](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR.pluginDefinition-method-init) method of the [requiring](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR.pluginDefinition-property-requires) plugin. -* [#1530](https://github.com/ckeditor/ckeditor-dev/issues/1530): Added the possibility to use custom icons for [buttons](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR_ui_button.html). +* [#1346](https://github.com/ckeditor/ckeditor-dev/issues/1346): [Balloon Toolbar](https://ckeditor.com/cke4/addon/balloontoolbar) [context manager API](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR.plugins.balloontoolbar.contextManager.html) is now available in the [`pluginDefinition.init()`](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_pluginDefinition.html#method-init) method of the [requiring](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_pluginDefinition.html#property-requires) plugin. +* [#1530](https://github.com/ckeditor/ckeditor-dev/issues/1530): Added the possibility to use custom icons for [buttons](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_ui_button.html.html). Other Changes: * Updated [SCAYT](https://ckeditor.com/cke4/addon/scayt) (Spell Check As You Type) and [WebSpellChecker](https://ckeditor.com/cke4/addon/wsc) (WSC) plugins: - * SCAYT [`scayt_minWordLength`](https://docs.ckeditor.com/ckeditor4/latest/api/CKEDITOR_config.html#scayt_minWordLength) configuration option now defaults to 3 instead of 4. + * SCAYT [`scayt_minWordLength`](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_config.html#scayt_minWordLength) configuration option now defaults to 3 instead of 4. * SCAYT default number of suggested words in the context menu changed to 3. * [#90](https://github.com/WebSpellChecker/ckeditor-plugin-scayt/issues/90): Fixed: Selection is lost on link creation if SCAYT highlights the word. * Fixed: SCAYT crashes when the browser `localStorage` is disabled. @@ -129,7 +159,7 @@ Other Changes: **Important Notes:** -* [#1249](https://github.com/ckeditor/ckeditor-dev/issues/1249): Enabled the [Upload Image](https://ckeditor.com/cke4/addon/uploadimage) plugin by default in standard and full presets. Also, it will no longer log an error in case of missing [`config.imageUploadUrl`](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR.config-cfg-imageUploadUrl) property. +* [#1249](https://github.com/ckeditor/ckeditor-dev/issues/1249): Enabled the [Upload Image](https://ckeditor.com/cke4/addon/uploadimage) plugin by default in standard and full presets. Also, it will no longer log an error in case of missing [`config.imageUploadUrl`](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_config.html#cfg-imageUploadUrl) property. New Features: @@ -138,9 +168,9 @@ New Features: * [#468](https://github.com/ckeditor/ckeditor-dev/issues/468): [Edge] Introduced support for the Clipboard API. * [#607](https://github.com/ckeditor/ckeditor-dev/issues/607): Manually inserted Hex color is prefixed with a hash character (`#`) if needed. It ensures a valid Hex color value is used when setting the table cell border or background color with the [Color Dialog](https://ckeditor.com/cke4/addon/colordialog) window. * [#584](https://github.com/ckeditor/ckeditor-dev/issues/584): [Font size and Family](https://ckeditor.com/cke4/addon/font) and [Format](https://ckeditor.com/cke4/addon/format) drop-downs are not toggleable anymore. Default option to reset styles added. -* [#856](https://github.com/ckeditor/ckeditor-dev/issues/856): Introduced the [`CKEDITOR.tools.keystrokeToArray()`](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR.tools-method-keystrokeToArray) method. It converts a keystroke into its string representation, returning every key name as a separate array element. -* [#1053](https://github.com/ckeditor/ckeditor-dev/issues/1053): Introduced the [`CKEDITOR.tools.object.merge()`](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR.tools.object-method-merge) method. It allows to merge two objects, returning the new object with all properties from both objects deeply cloned. -* [#1073](https://github.com/ckeditor/ckeditor-dev/issues/1073): Introduced the [`CKEDITOR.tools.array.every()`](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR.tools.array-method-every) method. It invokes a given test function on every array element and returns `true` if all elements pass the test. +* [#856](https://github.com/ckeditor/ckeditor-dev/issues/856): Introduced the [`CKEDITOR.tools.keystrokeToArray()`](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_tools.html#method-keystrokeToArray) method. It converts a keystroke into its string representation, returning every key name as a separate array element. +* [#1053](https://github.com/ckeditor/ckeditor-dev/issues/1053): Introduced the [`CKEDITOR.tools.object.merge()`](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_tools_object.html#method-merge) method. It allows to merge two objects, returning the new object with all properties from both objects deeply cloned. +* [#1073](https://github.com/ckeditor/ckeditor-dev/issues/1073): Introduced the [`CKEDITOR.tools.array.every()`](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_tools_array.html#method-every) method. It invokes a given test function on every array element and returns `true` if all elements pass the test. Fixed Issues: @@ -152,18 +182,18 @@ Fixed Issues: * [#842](https://github.com/ckeditor/ckeditor-dev/issues/842): Fixed: List style not restored when toggling list indent level in the [Indent List](https://ckeditor.com/cke4/addon/indentlist) plugin. * [#711](https://github.com/ckeditor/ckeditor-dev/issues/711): Fixed: Dragging widgets should only work with the left mouse button. * [#862](https://github.com/ckeditor/ckeditor-dev/issues/862): Fixed: The "Object Styles" group in the [Styles Combo](https://ckeditor.com/cke4/addon/stylescombo) plugin is visible only if the whole element is selected. -* [#994](https://github.com/ckeditor/ckeditor-dev/pull/994): Fixed: Typo in the [`CKEDITOR.focusManager.focus()`](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR.focusManager-method-focus) API documentation. Thanks to [benjy](https://github.com/benjy)! -* [#1014](https://github.com/ckeditor/ckeditor-dev/issues/1014): Fixed: The [Table Tools](https://ckeditor.com/cke4/addon/tabletools) Cell Properties dialog is now [Advanced Content Filter](https://docs.ckeditor.com/ckeditor4/docs/#!/guide/dev_acf) aware — it is not possible to change the cell width or height if corresponding styles are disabled. +* [#994](https://github.com/ckeditor/ckeditor-dev/pull/994): Fixed: Typo in the [`CKEDITOR.focusManager.focus()`](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_focusManager.html#method-focus) API documentation. Thanks to [benjy](https://github.com/benjy)! +* [#1014](https://github.com/ckeditor/ckeditor-dev/issues/1014): Fixed: The [Table Tools](https://ckeditor.com/cke4/addon/tabletools) Cell Properties dialog is now [Advanced Content Filter](https://ckeditor.com/docs/ckeditor4/latest/guide/dev_acf.html) aware — it is not possible to change the cell width or height if corresponding styles are disabled. * [#877](https://github.com/ckeditor/ckeditor-dev/issues/877): Fixed: A list with custom bullets with exotic characters crashes the editor when [pasted from Word](https://ckeditor.com/cke4/addon/pastefromword). * [#605](https://github.com/ckeditor/ckeditor-dev/issues/605): Fixed: Inline widgets do not preserve trailing spaces. -* [#1008](https://github.com/ckeditor/ckeditor-dev/issues/1008): Fixed: Shorthand Hex colors from the [`config.colorButton_colors`](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR.config-cfg-colorButton_colors) option are not correctly highlighted in the [Color Button](https://ckeditor.com/cke4/addon/colorbutton) Text Color or Background Color panel. -* [#1094](https://github.com/ckeditor/ckeditor-dev/issues/1094): Fixed: Widget definition [`upcast`](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR.plugins.widget.definition-property-upcasts) methods are called for every element. +* [#1008](https://github.com/ckeditor/ckeditor-dev/issues/1008): Fixed: Shorthand Hex colors from the [`config.colorButton_colors`](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_config.html#cfg-colorButton_colors) option are not correctly highlighted in the [Color Button](https://ckeditor.com/cke4/addon/colorbutton) Text Color or Background Color panel. +* [#1094](https://github.com/ckeditor/ckeditor-dev/issues/1094): Fixed: Widget definition [`upcast`](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_plugins_widget_definition.html#property-upcasts) methods are called for every element. * [#1057](https://github.com/ckeditor/ckeditor-dev/issues/1057): Fixed: The [Notification](https://ckeditor.com/addon/notification) plugin overwrites Web Notifications API due to leakage to the global scope. -* [#1068](https://github.com/ckeditor/ckeditor-dev/issues/1068): Fixed: Upload widget paste listener ignores changes to the [`uploadWidgetDefinition`](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR.fileTools.uploadWidgetDefinition). +* [#1068](https://github.com/ckeditor/ckeditor-dev/issues/1068): Fixed: Upload widget paste listener ignores changes to the [`uploadWidgetDefinition`](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR.fileTools.uploadWidgetDefinition.html). * [#921](https://github.com/ckeditor/ckeditor-dev/issues/921): Fixed: [Edge] CKEditor erroneously perceives internal copy and paste as type "external". * [#1213](https://github.com/ckeditor/ckeditor-dev/issues/1213): Fixed: Multiple images uploaded using [Upload Image](https://ckeditor.com/cke4/addon/uploadimage) plugin are randomly duplicated or mangled. * [#532](https://github.com/ckeditor/ckeditor-dev/issues/532): Fixed: Removed an outdated user guide link from the [About](https://ckeditor.com/cke4/addon/about) dialog. -* [#1221](https://github.com/ckeditor/ckeditor-dev/issues/1221): Fixed: Invalid CSS loaded by [Balloon Panel](https://ckeditor.com/cke4/addon/balloonpanel) plugin when [`config.skin`](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR.config-cfg-skin) is loaded using a custom path. +* [#1221](https://github.com/ckeditor/ckeditor-dev/issues/1221): Fixed: Invalid CSS loaded by [Balloon Panel](https://ckeditor.com/cke4/addon/balloonpanel) plugin when [`config.skin`](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_config.html#cfg-skin) is loaded using a custom path. * [#522](https://github.com/ckeditor/ckeditor-dev/issues/522): Fixed: Widget selection is not removed when widget is inside table cell with [Table Selection](https://ckeditor.com/cke4/addon/tableselection) plugin enabled. * [#1027](https://github.com/ckeditor/ckeditor-dev/issues/1027): Fixed: Cannot add multiple images to the table with [Table Selection](https://ckeditor.com/cke4/addon/tableselection) plugin in certain situations. * [#1069](https://github.com/ckeditor/ckeditor-dev/issues/1069): Fixed: Wrong shape processing by [Paste from Word](https://ckeditor.com/cke4/addon/pastefromword) plugin. @@ -172,9 +202,9 @@ Fixed Issues: API Changes: -* [#1097](https://github.com/ckeditor/ckeditor-dev/issues/1097): Widget [`upcast`](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR.plugins.widget.definition-property-upcast) methods are now called in the [widget definition's](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR.plugins.widget-property-definition) context. -* [#1118](https://github.com/ckeditor/ckeditor-dev/issues/1118): Added the `show` option in the [`balloonPanel.attach()`](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR.ui.balloonPanel-method-attach) method, allowing to attach a hidden [Balloon Panel](https://ckeditor.com/cke4/addon/balloonpanel) instance. -* [#1145](https://github.com/ckeditor/ckeditor-dev/issues/1145): Added the [`skipNotifications`](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR.fileTools.uploadWidgetDefinition-property-skipNotifications) option to the [`CKEDITOR.fileTools.uploadWidgetDefinition`](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR.fileTools.uploadWidgetDefinition), allowing to switch off default notifications displayed by upload widgets. +* [#1097](https://github.com/ckeditor/ckeditor-dev/issues/1097): Widget [`upcast`](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_plugins_widget_definition.html#property-upcast) methods are now called in the [widget definition's](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_plugins_widget.html#property-definition) context. +* [#1118](https://github.com/ckeditor/ckeditor-dev/issues/1118): Added the `show` option in the [`balloonPanel.attach()`](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_ui_balloonPanel.html#method-attach) method, allowing to attach a hidden [Balloon Panel](https://ckeditor.com/cke4/addon/balloonpanel) instance. +* [#1145](https://github.com/ckeditor/ckeditor-dev/issues/1145): Added the [`skipNotifications`](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_fileTools_uploadWidgetDefinition.html#property-skipNotifications) option to the [`CKEDITOR.fileTools.uploadWidgetDefinition`](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR.fileTools.uploadWidgetDefinition.html), allowing to switch off default notifications displayed by upload widgets. Other Changes: @@ -185,15 +215,15 @@ Other Changes: New Features: -* [#568](https://github.com/ckeditor/ckeditor-dev/issues/568): Added possibility to adjust nested editables' filters using the [`CKEDITOR.filter.disallowedContent`](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR.filter-property-disallowedContent) property. +* [#568](https://github.com/ckeditor/ckeditor-dev/issues/568): Added possibility to adjust nested editables' filters using the [`CKEDITOR.filter.disallowedContent`](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_filter.html#property-disallowedContent) property. Fixed Issues: -* [#554](https://github.com/ckeditor/ckeditor-dev/issues/554): Fixed: [`change`](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR.editor-event-change) event not fired when typing the first character after pasting into the editor. Thanks to [Daniel Miller](https://github.com/millerdev)! +* [#554](https://github.com/ckeditor/ckeditor-dev/issues/554): Fixed: [`change`](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_editor.html#event-change) event not fired when typing the first character after pasting into the editor. Thanks to [Daniel Miller](https://github.com/millerdev)! * [#566](https://github.com/ckeditor/ckeditor-dev/issues/566): Fixed: The CSS `border` shorthand property with zero width (`border: 0px solid #000;`) causes the table to have the border attribute set to 1. * [#779](https://github.com/ckeditor/ckeditor-dev/issues/779): Fixed: The [Remove Format](https://ckeditor.com/cke4/addon/removeformat) plugin removes elements with language definition inserted by the [Language](https://ckeditor.com/cke4/addon/language) plugin. -* [#423](https://github.com/ckeditor/ckeditor-dev/issues/423): Fixed: The [Paste from Word](https://ckeditor.com/cke4/addon/pastefromword) plugin pastes paragraphs into the editor even if [`CKEDITOR.config.enterMode`](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR.config-cfg-enterMode) is set to `CKEDITOR.ENTER_BR`. -* [#719](https://github.com/ckeditor/ckeditor-dev/issues/719): Fixed: Image inserted using the [Enhanced Image](https://ckeditor.com/cke4/addon/image2) plugin can be resized when the editor is in [read-only mode](https://docs.ckeditor.com/ckeditor4/docs/#!/guide/dev_readonly). +* [#423](https://github.com/ckeditor/ckeditor-dev/issues/423): Fixed: The [Paste from Word](https://ckeditor.com/cke4/addon/pastefromword) plugin pastes paragraphs into the editor even if [`CKEDITOR.config.enterMode`](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_config.html#cfg-enterMode) is set to `CKEDITOR.ENTER_BR`. +* [#719](https://github.com/ckeditor/ckeditor-dev/issues/719): Fixed: Image inserted using the [Enhanced Image](https://ckeditor.com/cke4/addon/image2) plugin can be resized when the editor is in [read-only mode](https://ckeditor.com/docs/ckeditor4/latest/guide/dev_readonly.html). * [#577](https://github.com/ckeditor/ckeditor-dev/issues/577): Fixed: The "Delete Columns" command provided by the [Table Tools](https://ckeditor.com/cke4/addon/tabletools) plugin throws an error when trying to delete columns. * [#867](https://github.com/ckeditor/ckeditor-dev/issues/867): Fixed: Typing into a selected table throws an error. * [#817](https://github.com/ckeditor/ckeditor-dev/issues/817): Fixed: The [Save](https://ckeditor.com/cke4/addon/save) plugin does not work in [Source Mode](https://ckeditor.com/cke4/addon/sourcearea). @@ -202,14 +232,14 @@ Other Changes: * Updated the [WebSpellChecker](https://ckeditor.com/cke4/addon/wsc) plugin: * [#40](https://github.com/WebSpellChecker/ckeditor-plugin-wsc/issues/40): Fixed: IE10 throws an error when spell checking is started. -* [#800](https://github.com/ckeditor/ckeditor-dev/issues/800): Added the [`CKEDITOR.dom.selection.isCollapsed()`](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR.dom.selection-method-isCollapsed) method which is a simpler way to check if the selection is collapsed. -* [#830](https://github.com/ckeditor/ckeditor-dev/issues/830): Added an option to define which dialog tab should be shown by default when creating [`CKEDITOR.dialogCommand`](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR.dialogCommand). +* [#800](https://github.com/ckeditor/ckeditor-dev/issues/800): Added the [`CKEDITOR.dom.selection.isCollapsed()`](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_dom_selection.html#method-isCollapsed) method which is a simpler way to check if the selection is collapsed. +* [#830](https://github.com/ckeditor/ckeditor-dev/issues/830): Added an option to define which dialog tab should be shown by default when creating [`CKEDITOR.dialogCommand`](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR.dialogCommand.html). ## CKEditor 4.7.2 New Features: -* [#455](https://github.com/ckeditor/ckeditor-dev/issues/455): Added [Advanced Content Filter](https://docs.ckeditor.com/ckeditor4/docs/#!/guide/dev_acf) integration with the [Justify](https://ckeditor.com/cke4/addon/justify) plugin. +* [#455](https://github.com/ckeditor/ckeditor-dev/issues/455): Added [Advanced Content Filter](https://ckeditor.com/docs/ckeditor4/latest/guide/dev_acf.html) integration with the [Justify](https://ckeditor.com/cke4/addon/justify) plugin. Fixed Issues: @@ -223,17 +253,17 @@ Fixed Issues: * [#491](https://github.com/ckeditor/ckeditor-dev/issues/491): Fixed: Unnecessary dependency on the [Editor Toolbar](https://ckeditor.com/cke4/addon/toolbar) plugin inside the [Notification](https://ckeditor.com/cke4/addon/notification) plugin. * [#646](https://github.com/ckeditor/ckeditor-dev/issues/646): Fixed: Error thrown into the browser console after opening the [Styles Combo](https://ckeditor.com/cke4/addon/stylescombo) plugin menu in the editor without any selection. * [#501](https://github.com/ckeditor/ckeditor-dev/issues/501): Fixed: Double click does not open the dialog for modifying anchors inserted via the [Link](https://ckeditor.com/cke4/addon/link) plugin. -* [#9780](https://dev.ckeditor.com/ticket/9780): [IE8-9] Fixed: Clicking inside an empty [read-only](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR.editor-property-readOnly) editor throws an error. +* [#9780](https://dev.ckeditor.com/ticket/9780): [IE8-9] Fixed: Clicking inside an empty [read-only](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_editor.html#property-readOnly) editor throws an error. * [#16820](https://dev.ckeditor.com/ticket/16820): [IE10] Fixed: Clicking below a single horizontal rule throws an error. -* [#426](https://github.com/ckeditor/ckeditor-dev/issues/426): Fixed: The [`range.cloneContents()`](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR.dom.range-method-cloneContents) method selects the whole element when the selection starts at the beginning of that element. -* [#644](https://github.com/ckeditor/ckeditor-dev/issues/644): Fixed: The [`range.extractContents()`](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR.dom.range-method-extractContents) method returns an incorrect result when multiple nodes are selected. -* [#684](https://github.com/ckeditor/ckeditor-dev/issues/684): Fixed: The [`elementPath.contains()`](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR.dom.elementPath-method-contains) method incorrectly excludes the last element instead of root when the `fromTop` parameter is set to `true`. +* [#426](https://github.com/ckeditor/ckeditor-dev/issues/426): Fixed: The [`range.cloneContents()`](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_dom_range.html#method-cloneContents) method selects the whole element when the selection starts at the beginning of that element. +* [#644](https://github.com/ckeditor/ckeditor-dev/issues/644): Fixed: The [`range.extractContents()`](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_dom_range.html#method-extractContents) method returns an incorrect result when multiple nodes are selected. +* [#684](https://github.com/ckeditor/ckeditor-dev/issues/684): Fixed: The [`elementPath.contains()`](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_dom_elementPath.html#method-contains) method incorrectly excludes the last element instead of root when the `fromTop` parameter is set to `true`. Other Changes: * Updated the [SCAYT](https://ckeditor.com/cke4/addon/scayt) (Spell Check As You Type) plugin: * [#148](https://github.com/WebSpellChecker/ckeditor-plugin-scayt/issues/148): Fixed: SCAYT leaves underlined word after the CKEditor Replace dialog corrects it. -* [#751](https://github.com/ckeditor/ckeditor-dev/issues/751): Added the [`CKEDITOR.dom.nodeList.toArray()`](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR.dom.nodeList-method-toArray) method which returns an array representation of a [node list](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR.dom.nodeList). +* [#751](https://github.com/ckeditor/ckeditor-dev/issues/751): Added the [`CKEDITOR.dom.nodeList.toArray()`](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_dom_nodeList.html#method-toArray) method which returns an array representation of a [node list](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR.dom.nodeList.html). ## CKEditor 4.7.1 @@ -252,28 +282,28 @@ Fixed Issues: * [#424](https://github.com/ckeditor/ckeditor-dev/issues/424): Fixed: Error thrown by [Tab Key Handling](https://ckeditor.com/cke4/addon/tab) and [Indent List](https://ckeditor.com/cke4/addon/indentlist) plugins when pressing <kbd>Tab</kbd> with no selection in inline editor. * [#476](https://github.com/ckeditor/ckeditor-dev/issues/476): Fixed: Anchors inserted with the [Link](https://ckeditor.com/cke4/addon/link) plugin on collapsed selection cannot be edited. * [#417](https://github.com/ckeditor/ckeditor-dev/issues/417): Fixed: The [Table Resize](https://ckeditor.com/cke4/addon/tableresize) plugin throws an error when used with a table with only header or footer rows. -* [#523](https://github.com/ckeditor/ckeditor-dev/issues/523): Fixed: The [`editor.getCommandKeystroke()`](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR.editor-method-getCommandKeystroke) method does not obtain the correct keystroke. +* [#523](https://github.com/ckeditor/ckeditor-dev/issues/523): Fixed: The [`editor.getCommandKeystroke()`](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_editor.html#method-getCommandKeystroke) method does not obtain the correct keystroke. * [#534](https://github.com/ckeditor/ckeditor-dev/issues/534): [IE] Fixed: [Paste from Word](https://ckeditor.com/cke4/addon/pastefromword) does not work in Quirks Mode. -* [#450](https://github.com/ckeditor/ckeditor-dev/issues/450): Fixed: [`CKEDITOR.filter`](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR.filter) incorrectly transforms the `margin` CSS property. +* [#450](https://github.com/ckeditor/ckeditor-dev/issues/450): Fixed: [`CKEDITOR.filter`](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR.filter.html) incorrectly transforms the `margin` CSS property. ## CKEditor 4.7 **Important Notes:** -* [#13793](https://dev.ckeditor.com/ticket/13793): The [`embed_provider`](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR.config-cfg-embed_provider) configuration option for the [Media Embed](https://ckeditor.com/cke4/addon/embed) and [Semantic Media Embed](https://ckeditor.com/cke4/addon/embedsemantic) plugins is no longer preset by default. +* [#13793](https://dev.ckeditor.com/ticket/13793): The [`embed_provider`](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_config.html#cfg-embed_provider) configuration option for the [Media Embed](https://ckeditor.com/cke4/addon/embed) and [Semantic Media Embed](https://ckeditor.com/cke4/addon/embedsemantic) plugins is no longer preset by default. * The [UI Color](https://ckeditor.com/cke4/addon/uicolor) plugin now uses a custom color picker instead of the `YUI 2.7.0` library which has some known vulnerabilities (it's a security precaution, there was no security issue in CKEditor due to the way it was used). New Features: * [#16755](https://dev.ckeditor.com/ticket/16755): Added the [Table Selection](https://ckeditor.com/cke4/addon/tableselection) plugin that lets you select and manipulate an arbitrary rectangular table fragment (a few cells, a row or a column). * [#16961](https://dev.ckeditor.com/ticket/16961): Added support for pasting from Microsoft Excel. -* [#13381](https://dev.ckeditor.com/ticket/13381): Dynamic code evaluation call in [`CKEDITOR.template`](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR.template) removed. CKEditor can now be used without the `unsafe-eval` Content Security Policy. Thanks to [Caridy Patiño](http://caridy.name)! +* [#13381](https://dev.ckeditor.com/ticket/13381): Dynamic code evaluation call in [`CKEDITOR.template`](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR.template.html) removed. CKEditor can now be used without the `unsafe-eval` Content Security Policy. Thanks to [Caridy Patiño](http://caridy.name)! * [#16971](https://dev.ckeditor.com/ticket/16971): Added support for color in the `background` property containing also other styles for table cells in the [Table Tools](https://ckeditor.com/cke4/addon/tabletools) plugin. * [#16847](https://dev.ckeditor.com/ticket/16847): Added support for parsing and inlining any formatting created using the Microsoft Word style system to the [Paste from Word](https://ckeditor.com/cke4/addon/pastefromword) plugin. * [#16818](https://dev.ckeditor.com/ticket/16818): Added table cell height parsing in the [Paste from Word](https://ckeditor.com/cke4/addon/pastefromword) plugin. -* [#16850](https://dev.ckeditor.com/ticket/16850): Added a new [`config.enableContextMenu`](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR.config-cfg-enableContextMenu) configuration option for enabling and disabling the [context menu](https://ckeditor.com/cke4/addon/contextmenu). -* [#16937](https://dev.ckeditor.com/ticket/16937): The `command` parameter in [`CKEDITOR.editor.getCommandKeystroke()`](http://docs.ckeditor.dev/#!/api/CKEDITOR.editor-method-getCommandKeystroke) now also accepts a command name as an argument. -* [#17010](https://dev.ckeditor.com/ticket/17010): The [`CKEDITOR.dom.range.shrink()`](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR.dom.range-method-shrink) method now allows for skipping bogus `<br>` elements. +* [#16850](https://dev.ckeditor.com/ticket/16850): Added a new [`config.enableContextMenu`](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_config.html#cfg-enableContextMenu) configuration option for enabling and disabling the [context menu](https://ckeditor.com/cke4/addon/contextmenu). +* [#16937](https://dev.ckeditor.com/ticket/16937): The `command` parameter in [`CKEDITOR.editor.getCommandKeystroke()`](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_editor.html#method-getCommandKeystroke) now also accepts a command name as an argument. +* [#17010](https://dev.ckeditor.com/ticket/17010): The [`CKEDITOR.dom.range.shrink()`](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_dom_range.html#method-shrink) method now allows for skipping bogus `<br>` elements. Fixed Issues: @@ -307,9 +337,9 @@ Fixed Issues: * [#14407](https://dev.ckeditor.com/ticket/14407): [IE] Fixed: Non-editable widgets can be edited. * [#16927](https://dev.ckeditor.com/ticket/16927): Fixed: An error thrown if a bundle containing the [Color Button](https://ckeditor.com/cke4/addon/colorbutton) plugin is run in ES5 strict mode. Thanks to [Igor Rubinovich](https://github.com/IgorRubinovich)! * [#16920](https://dev.ckeditor.com/ticket/16920): Fixed: Several plugins not using the [Dialog](https://ckeditor.com/cke4/addon/dialog) plugin as a direct dependency. -* [PR#336](https://github.com/ckeditor/ckeditor-dev/pull/336): Fixed: Typo in [`CKEDITOR.getCss()`](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR-method-getCss) API documentation. Thanks to [knusperpixel](https://github.com/knusperpixel)! +* [PR#336](https://github.com/ckeditor/ckeditor-dev/pull/336): Fixed: Typo in [`CKEDITOR.getCss()`](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR.html#method-getCss) API documentation. Thanks to [knusperpixel](https://github.com/knusperpixel)! * [#17027](https://dev.ckeditor.com/ticket/17027): Fixed: Command event data should be initialized as an empty object. -* Fixed the behavior of HTML parser when parsing `src`/`srcdoc` attributes of the `<iframe>` element in a CKEditor setup with ACF turned off and without the [Iframe Dialog](https://ckeditor.com/cke4/addon/iframe) plugin. The issue was originally reported as a security issue by [Sriramk21](https://twitter.com/sriramk21) from Pegasystems and was later downgraded by the security team into a normal issue due to the requirement of having ACF turned off. Disabling [Advanced Content Filter](https://docs.ckeditor.com/ckeditor4/docs/#!/guide/dev_advanced_content_filter) is against [security best practices](https://docs.ckeditor.com/ckeditor4/docs/#!/guide/dev_best_practices-section-security), so the problem described above has not been considered a security issue as such. +* Fixed the behavior of HTML parser when parsing `src`/`srcdoc` attributes of the `<iframe>` element in a CKEditor setup with ACF turned off and without the [Iframe Dialog](https://ckeditor.com/cke4/addon/iframe) plugin. The issue was originally reported as a security issue by [Sriramk21](https://twitter.com/sriramk21) from Pegasystems and was later downgraded by the security team into a normal issue due to the requirement of having ACF turned off. Disabling [Advanced Content Filter](https://ckeditor.com/docs/ckeditor4/latest/guide/dev_advanced_content_filter.html) is against [security best practices](https://ckeditor.com/docs/ckeditor4/latest/guide/dev_best_practices.html#security), so the problem described above has not been considered a security issue as such. Other Changes: @@ -324,21 +354,21 @@ Other Changes: New Features: -* [#16733](https://dev.ckeditor.com/ticket/16733): Added a new pastel color palette for the [Color Button](https://ckeditor.com/cke4/addon/colorbutton) plugin and a new [`config.colorButton_colorsPerRow`](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR.config-cfg-colorButton_colorsPerRow) configuration option for setting the number of rows in the color selector. +* [#16733](https://dev.ckeditor.com/ticket/16733): Added a new pastel color palette for the [Color Button](https://ckeditor.com/cke4/addon/colorbutton) plugin and a new [`config.colorButton_colorsPerRow`](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_config.html#cfg-colorButton_colorsPerRow) configuration option for setting the number of rows in the color selector. * [#16752](https://dev.ckeditor.com/ticket/16752): Added a new Azerbaijani localization. Thanks to the [Azerbaijani language team](https://www.transifex.com/ckeditor/teams/11143/az/)! -* [#13818](https://dev.ckeditor.com/ticket/13818): It is now possible to group [Widget](https://ckeditor.com/cke4/addon/widget) [style definitions](https://docs.ckeditor.com/ckeditor4/docs/#!/guide/dev_styles-section-widget-styles), so applying one style disables the other. +* [#13818](https://dev.ckeditor.com/ticket/13818): It is now possible to group [Widget](https://ckeditor.com/cke4/addon/widget) [style definitions](https://ckeditor.com/docs/ckeditor4/latest/guide/dev_styles.html#widget-styles), so applying one style disables the other. Fixed Issues: * [#13446](https://dev.ckeditor.com/ticket/13446): [Chrome] Fixed: It is possible to type in an unfocused inline editor. * [#14856](https://dev.ckeditor.com/ticket/14856): Fixed: [Font size and font family](https://ckeditor.com/cke4/addon/font) reset each other when modified at certain positions. * [#16745](https://dev.ckeditor.com/ticket/16745): [Edge] Fixed: List items are lost when [pasted from Word](https://ckeditor.com/cke4/addon/pastefromword). -* [#16682](https://dev.ckeditor.com/ticket/16682): [Edge] Fixed: A list gets [pasted from Word](https://ckeditor.com/cke4/addon/pastefromword) as a set of paragraphs. Added the [`config.pasteFromWord_heuristicsEdgeList`](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR.config-cfg-pasteFromWord_heuristicsEdgeList) configuration option. +* [#16682](https://dev.ckeditor.com/ticket/16682): [Edge] Fixed: A list gets [pasted from Word](https://ckeditor.com/cke4/addon/pastefromword) as a set of paragraphs. Added the [`config.pasteFromWord_heuristicsEdgeList`](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_config.html#cfg-pasteFromWord_heuristicsEdgeList) configuration option. * [#10373](https://dev.ckeditor.com/ticket/10373): Fixed: Context menu items can be dragged into the editor. * [#16728](https://dev.ckeditor.com/ticket/16728): [IE] Fixed: [Copy Formatting](https://ckeditor.com/cke4/addon/copyformatting) breaks the editor in Quirks Mode. * [#16795](https://dev.ckeditor.com/ticket/16795): [IE] Fixed: [Copy Formatting](https://ckeditor.com/cke4/addon/copyformatting) breaks the editor in Compatibility Mode. * [#16675](https://dev.ckeditor.com/ticket/16675): Fixed: Styles applied with [Copy Formatting](https://ckeditor.com/cke4/addon/copyformatting) to a single table cell are applied to the whole table. -* [#16753](https://dev.ckeditor.com/ticket/16753): Fixed: [`element.setSize()`](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR.dom.element-method-setSize) sets incorrect editor dimensions if the border width is represented as a fraction of pixels. +* [#16753](https://dev.ckeditor.com/ticket/16753): Fixed: [`element.setSize()`](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_dom_element.html#method-setSize) sets incorrect editor dimensions if the border width is represented as a fraction of pixels. * [#16705](https://dev.ckeditor.com/ticket/16705): [Firefox] Fixed: Unable to paste images as Base64 strings when using [Clipboard](https://ckeditor.com/cke4/addon/clipboard). * [#14869](https://dev.ckeditor.com/ticket/14869): Fixed: JavaScript error is thrown when trying to use [Find](https://ckeditor.com/cke4/addon/find) in a [`<div>`-based editor](https://ckeditor.com/cke4/addon/divarea). @@ -346,7 +376,7 @@ Fixed Issues: New Features: -* [#16639](https://dev.ckeditor.com/ticket/16639): The `callback` parameter in the [`CKEDITOR.ajax.post()`](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR.ajax-method-post) method became optional. +* [#16639](https://dev.ckeditor.com/ticket/16639): The `callback` parameter in the [`CKEDITOR.ajax.post()`](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_ajax.html#method-post) method became optional. Fixed Issues: @@ -359,11 +389,11 @@ Fixed Issues: New Features: -* [#14569](https://dev.ckeditor.com/ticket/14569): Added a new, flat, default CKEditor skin called [Moono-Lisa](https://ckeditor.com/cke4/addon/moono-lisa). Refreshed default colors available in the [Color Button](https://ckeditor.com/cke4/addon/colorbutton) plugin ([Text Color and Background Color](https://docs.ckeditor.com/ckeditor4/docs/#!/guide/dev_colorbutton) feature). +* [#14569](https://dev.ckeditor.com/ticket/14569): Added a new, flat, default CKEditor skin called [Moono-Lisa](https://ckeditor.com/cke4/addon/moono-lisa). Refreshed default colors available in the [Color Button](https://ckeditor.com/cke4/addon/colorbutton) plugin ([Text Color and Background Color](https://ckeditor.com/docs/ckeditor4/latest/guide/dev_colorbutton.html) feature). * [#14707](https://dev.ckeditor.com/ticket/14707): Added a new [Copy Formatting](https://ckeditor.com/cke4/addon/copyformatting) feature to enable easy copying of styles between your document parts. * Introduced the completely rewritten [Paste from Word](https://ckeditor.com/cke4/addon/pastefromword) plugin: - * Backward incompatibility: The [`config.pasteFromWordRemoveFontStyles`](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR.config-cfg-pasteFromWordRemoveFontStyles) option now defaults to `false`. This option will be deprecated in the future. Use [Advanced Content Filter](https://docs.ckeditor.com/ckeditor4/docs/#!/guide/dev_acf) to replicate the effect of setting it to `true`. - * Backward incompatibility: The [`config.pasteFromWordNumberedHeadingToList`](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR.config-cfg-pasteFromWordNumberedHeadingToList) and [`config.pasteFromWordRemoveStyles`](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR.config-cfg-pasteFromWordRemoveStyles) options were dropped and no longer have any effect on pasted content. + * Backward incompatibility: The [`config.pasteFromWordRemoveFontStyles`](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_config.html#cfg-pasteFromWordRemoveFontStyles) option now defaults to `false`. This option will be deprecated in the future. Use [Advanced Content Filter](https://ckeditor.com/docs/ckeditor4/latest/guide/dev_acf.html) to replicate the effect of setting it to `true`. + * Backward incompatibility: The [`config.pasteFromWordNumberedHeadingToList`](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_config.html#cfg-pasteFromWordNumberedHeadingToList) and [`config.pasteFromWordRemoveStyles`](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_config.html#cfg-pasteFromWordRemoveStyles) options were dropped and no longer have any effect on pasted content. * Major improvements in preservation of list numbering, styling and indentation (nested lists with multiple levels). * Major improvements in document structure parsing that fix plenty of issues with distorted or missing content after paste. * Added new translation: Occitan. Thanks to [Cédric Valmary](https://totenoc.eu/)! @@ -372,8 +402,8 @@ New Features: * [#12541](https://dev.ckeditor.com/ticket/12541): Added the [Upload File](https://ckeditor.com/cke4/addon/uploadfile) plugin that lets you upload a file by drag&dropping it into the editor content. * [#14449](https://dev.ckeditor.com/ticket/14449): Introduced the [Balloon Panel](https://ckeditor.com/cke4/addon/balloonpanel) plugin that lets you create stylish floating UI elements for the editor. * [#12077](https://dev.ckeditor.com/ticket/12077): Added support for the HTML5 `download` attribute in link (`<a>`) elements. Selecting the "Force Download" checkbox in the [Link](https://ckeditor.com/cke4/addon/link) dialog will cause the linked file to be downloaded automatically. Thanks to [sbusse](https://github.com/sbusse)! -* [#13518](https://dev.ckeditor.com/ticket/13518): Introduced the [`additionalRequestParameters`](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR.fileTools.uploadWidgetDefinition-property-additionalRequestParameters) property for file uploads to make it possible to send additional information about the uploaded file to the server. -* [#14889](https://dev.ckeditor.com/ticket/14889): Added the [`config.image2_altRequired`](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR.config-cfg-image2_altRequired) option for the [Enhanced Image](https://ckeditor.com/cke4/addon/image2) plugin to allow making alternative text a mandatory field. Thanks to [Andrey Fedoseev](https://github.com/andreyfedoseev)! +* [#13518](https://dev.ckeditor.com/ticket/13518): Introduced the [`additionalRequestParameters`](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_fileTools_uploadWidgetDefinition.html#property-additionalRequestParameters) property for file uploads to make it possible to send additional information about the uploaded file to the server. +* [#14889](https://dev.ckeditor.com/ticket/14889): Added the [`config.image2_altRequired`](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_config.html#cfg-image2_altRequired) option for the [Enhanced Image](https://ckeditor.com/cke4/addon/image2) plugin to allow making alternative text a mandatory field. Thanks to [Andrey Fedoseev](https://github.com/andreyfedoseev)! Fixed Issues: @@ -387,7 +417,7 @@ Fixed Issues: * [#2507](https://dev.ckeditor.com/ticket/2507): Fixed: [Paste from Word](https://ckeditor.com/cke4/addon/pastefromword) does not detect pasting a part of a paragraph. * [#3336](https://dev.ckeditor.com/ticket/3336): Fixed: Extra blank row added on top of the content [pasted from Word](https://ckeditor.com/cke4/addon/pastefromword). * [#6115](https://dev.ckeditor.com/ticket/6115): Fixed: When Right-to-Left text direction is applied to a table [pasted from Word](https://ckeditor.com/cke4/addon/pastefromword), borders are missing on one side. -* [#6342](https://dev.ckeditor.com/ticket/6342): Fixed: [Paste from Word](https://ckeditor.com/cke4/addon/pastefromword) filters out a basic text style when it is [configured to use attributes](https://docs.ckeditor.com/ckeditor4/docs/#!/guide/dev_basicstyles-section-custom-basic-text-style-definition). +* [#6342](https://dev.ckeditor.com/ticket/6342): Fixed: [Paste from Word](https://ckeditor.com/cke4/addon/pastefromword) filters out a basic text style when it is [configured to use attributes](https://ckeditor.com/docs/ckeditor4/latest/guide/dev_basicstyles.html#custom-basic-text-style-definition). * [#6457](https://dev.ckeditor.com/ticket/6457): [IE] Fixed: [Pasting from Word](https://ckeditor.com/cke4/addon/pastefromword) is extremely slow. * [#6789](https://dev.ckeditor.com/ticket/6789): Fixed: The `mso-list: ignore` style is not handled properly when [pasting from Word](https://ckeditor.com/cke4/addon/pastefromword). * [#7262](https://dev.ckeditor.com/ticket/7262): Fixed: Lists in preformatted body disappear when [pasting from Word](https://ckeditor.com/cke4/addon/pastefromword). @@ -399,10 +429,10 @@ Fixed Issues: * [#8266](https://dev.ckeditor.com/ticket/8266): Fixed: [Paste from Word](https://ckeditor.com/cke4/addon/pastefromword) inserts a blank line at the top. * [#8341](https://dev.ckeditor.com/ticket/8341), [#7646](https://dev.ckeditor.com/ticket/7646): Fixed: Faulty removal of empty `<span>` elements in [Paste from Word](https://ckeditor.com/cke4/addon/pastefromword) content cleanup breaking content formatting. * [#8754](https://dev.ckeditor.com/ticket/8754): [Firefox] Fixed: Incorrect pasting of multiple nested lists in [Paste from Word](https://ckeditor.com/cke4/addon/pastefromword). -* [#8983](https://dev.ckeditor.com/ticket/8983): Fixed: Alignment lost when [pasting from Word](https://ckeditor.com/cke4/addon/pastefromword) with [`config.enterMode`](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR.config-cfg-enterMode) set to [`CKEDITOR.ENTER_BR`](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR-property-ENTER_BR). +* [#8983](https://dev.ckeditor.com/ticket/8983): Fixed: Alignment lost when [pasting from Word](https://ckeditor.com/cke4/addon/pastefromword) with [`config.enterMode`](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_config.html#cfg-enterMode) set to [`CKEDITOR.ENTER_BR`](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR.html#property-ENTER_BR). * [#9331](https://dev.ckeditor.com/ticket/9331): [IE] Fixed: [Pasting text from Word](https://ckeditor.com/cke4/addon/pastefromword) creates a simple Caesar cipher. * [#9422](https://dev.ckeditor.com/ticket/9422): Fixed: [Paste from Word](https://ckeditor.com/cke4/addon/pastefromword) leaves an unwanted `color:windowtext` style. -* [#10011](https://dev.ckeditor.com/ticket/10011): [IE9-10] Fixed: [`config.pasteFromWordRemoveFontStyles`](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR.config-cfg-pasteFromWordRemoveFontStyles) is ignored under certain conditions. +* [#10011](https://dev.ckeditor.com/ticket/10011): [IE9-10] Fixed: [`config.pasteFromWordRemoveFontStyles`](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_config.html#cfg-pasteFromWordRemoveFontStyles) is ignored under certain conditions. * [#10643](https://dev.ckeditor.com/ticket/10643): Fixed: Differences between using <kbd>Ctrl+V</kbd> and pasting from the [Paste from Word](https://ckeditor.com/cke4/addon/pastefromword) dialog. * [#10784](https://dev.ckeditor.com/ticket/10784): Fixed: Lines missing when [pasting from Word](https://ckeditor.com/cke4/addon/pastefromword). * [#11294](https://dev.ckeditor.com/ticket/11294): [IE10] Fixed: Font size is not preserved when [pasting from Word](https://ckeditor.com/cke4/addon/pastefromword). @@ -451,7 +481,7 @@ Fixed Issues: Fixed Issues: * [#10750](https://dev.ckeditor.com/ticket/10750): Fixed: The editor does not escape the `font-style` family property correctly, removing quotes and whitespace from font names. -* [#14413](https://dev.ckeditor.com/ticket/14413): Fixed: The [Auto Grow](https://ckeditor.com/cke4/addon/autogrow) plugin with the [`config.autoGrow_onStartup`](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR.config-cfg-autoGrow_onStartup) option set to `true` does not work properly for an editor that is not visible. +* [#14413](https://dev.ckeditor.com/ticket/14413): Fixed: The [Auto Grow](https://ckeditor.com/cke4/addon/autogrow) plugin with the [`config.autoGrow_onStartup`](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_config.html#cfg-autoGrow_onStartup) option set to `true` does not work properly for an editor that is not visible. * [#14451](https://dev.ckeditor.com/ticket/14451): Fixed: Numeric element ID not escaped properly. Thanks to [Jakub Chalupa](https://github.com/chaluja7)! * [#14590](https://dev.ckeditor.com/ticket/14590): Fixed: Additional line break appearing after inline elements when switching modes. Thanks to [dpidcock](https://github.com/dpidcock)! * [#14539](https://dev.ckeditor.com/ticket/14539): Fixed: JAWS reads "selected Blank" instead of "selected <widget name>" when selecting a widget. @@ -468,17 +498,17 @@ Fixed Issues: * [#14573](https://dev.ckeditor.com/ticket/14573): Fixed: Missing [Widget](https://ckeditor.com/cke4/addon/widget) drag handler CSS when there are multiple editor instances. * [#14620](https://dev.ckeditor.com/ticket/14620): Fixed: Setting both the `min-height` style for the `<body>` element and the `height` style for the `<html>` element breaks the [Auto Grow](https://ckeditor.com/cke4/addon/autogrow) plugin. * [#14538](https://dev.ckeditor.com/ticket/14538): Fixed: Keyboard focus goes into an embedded `<iframe>` element. -* [#14602](https://dev.ckeditor.com/ticket/14602): Fixed: The [`dom.element.removeAttribute()`](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR.dom.element-method-removeAttribute) method does not remove all attributes if no parameter is given. +* [#14602](https://dev.ckeditor.com/ticket/14602): Fixed: The [`dom.element.removeAttribute()`](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_dom_element.html#method-removeAttribute) method does not remove all attributes if no parameter is given. * [#8679](https://dev.ckeditor.com/ticket/8679): Fixed: Better focus indication and ability to style the selected color in the [color picker dialog](https://ckeditor.com/cke4/addon/colordialog). * [#11697](https://dev.ckeditor.com/ticket/11697): Fixed: Content is replaced ignoring the letter case setting in the [Find and Replace](https://ckeditor.com/cke4/addon/find) dialog window. -* [#13886](https://dev.ckeditor.com/ticket/13886): Fixed: Invalid handling of the [`CKEDITOR.style`](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR.style) instance with the `styles` property by [`CKEDITOR.filter`](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR.filter). +* [#13886](https://dev.ckeditor.com/ticket/13886): Fixed: Invalid handling of the [`CKEDITOR.style`](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR.style.html) instance with the `styles` property by [`CKEDITOR.filter`](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR.filter.html). * [#14535](https://dev.ckeditor.com/ticket/14535): Fixed: CSS syntax corrections. Thanks to [mdjdenormandie](https://github.com/mdjdenormandie)! ## CKEditor 4.5.8 New Features: -* [#12440](https://dev.ckeditor.com/ticket/12440): Added the [`config.colorButton_enableAutomatic`](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR.config-cfg-colorButton_enableAutomatic) option to allow hiding the "Automatic" option in the [color picker](https://ckeditor.com/cke4/addon/colorbutton). +* [#12440](https://dev.ckeditor.com/ticket/12440): Added the [`config.colorButton_enableAutomatic`](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_config.html#cfg-colorButton_enableAutomatic) option to allow hiding the "Automatic" option in the [color picker](https://ckeditor.com/cke4/addon/colorbutton). Fixed Issues: @@ -497,8 +527,8 @@ Fixed Issues: * [#13816](https://dev.ckeditor.com/ticket/13816): Introduced a new strategy for Filling Character handling to avoid changes in DOM. This fixes the following issues: * [#12727](https://dev.ckeditor.com/ticket/12727): [Blink] `IndexSizeError` when using the [Div Editing Area](https://ckeditor.com/cke4/addon/divarea) and [Content Templates](https://ckeditor.com/cke4/addon/templates) plugins. * [#13377](https://dev.ckeditor.com/ticket/13377): [Widget](https://ckeditor.com/cke4/addon/widget) plugin issue when typing in Korean. - * [#13389](https://dev.ckeditor.com/ticket/13389): [Blink] [`editor.getData()`](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR.editor-method-getData) fails when the cursor is next to an `<hr>` tag. - * [#13513](https://dev.ckeditor.com/ticket/13513): [Blink, WebKit] [Div Editing Area](https://ckeditor.com/cke4/addon/divarea) and [`editor.getData()`](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR.editor-method-getData) throw an error when an image is the only data in the editor. + * [#13389](https://dev.ckeditor.com/ticket/13389): [Blink] [`editor.getData()`](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_editor.html#method-getData) fails when the cursor is next to an `<hr>` tag. + * [#13513](https://dev.ckeditor.com/ticket/13513): [Blink, WebKit] [Div Editing Area](https://ckeditor.com/cke4/addon/divarea) and [`editor.getData()`](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_editor.html#method-getData) throw an error when an image is the only data in the editor. * [#13884](https://dev.ckeditor.com/ticket/13884): [Firefox] Fixed: Copying and pasting a table results in just the first cell being pasted. * [#14234](https://dev.ckeditor.com/ticket/14234): Fixed: URL input field is not marked as required in the [Media Embed](https://ckeditor.com/cke4/addon/embed) dialog. @@ -506,8 +536,8 @@ Fixed Issues: New Features: -* Introduced the [`CKEDITOR.tools.getCookie()`](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR.tools-method-getCookie) and [`CKEDITOR.tools.setCookie()`](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR.tools-method-setCookie) methods for accessing cookies. -* Introduced the [`CKEDITOR.tools.getCsrfToken()`](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR.tools-method-getCsrfToken) method. The CSRF token is now automatically sent by the [File Browser](https://ckeditor.com/cke4/addon/filebrowser) and [File Tools](https://ckeditor.com/cke4/addon/filetools) plugins during file uploads. The server-side upload handlers may check it and use it to additionally secure the communication. +* Introduced the [`CKEDITOR.tools.getCookie()`](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_tools.html#method-getCookie) and [`CKEDITOR.tools.setCookie()`](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_tools.html#method-setCookie) methods for accessing cookies. +* Introduced the [`CKEDITOR.tools.getCsrfToken()`](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_tools.html#method-getCsrfToken) method. The CSRF token is now automatically sent by the [File Browser](https://ckeditor.com/cke4/addon/filebrowser) and [File Tools](https://ckeditor.com/cke4/addon/filetools) plugins during file uploads. The server-side upload handlers may check it and use it to additionally secure the communication. Other Changes: @@ -516,7 +546,7 @@ Other Changes: - CKEditor [Language](https://ckeditor.com/cke4/addon/language) plugin support. - CKEditor [Placeholder](https://ckeditor.com/cke4/addon/placeholder) plugin support. - [Drag&Drop](https://sdk.ckeditor.com/samples/fileupload.html) support. - - **Experimental** [GRAYT](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR.config-cfg-grayt_autoStartup) (Grammar As You Type) functionality. + - **Experimental** [GRAYT](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_config.html#cfg-grayt_autoStartup) (Grammar As You Type) functionality. - Fixed issues: * [#98](https://github.com/WebSpellChecker/ckeditor-plugin-scayt/issues/98): SCAYT affects dialog double-click. Fixed in SCAYT core. * [#102](https://github.com/WebSpellChecker/ckeditor-plugin-scayt/issues/102): SCAYT core performance enhancements. @@ -534,15 +564,15 @@ Fixed Issues: * [#13887](https://dev.ckeditor.com/ticket/13887): Fixed: [Link](https://ckeditor.com/cke4/addon/link) plugin alters the `target` attribute value. Thanks to [SamZiemer](https://github.com/SamZiemer)! * [#12189](https://dev.ckeditor.com/ticket/12189): Fixed: The [Link](https://ckeditor.com/cke4/addon/link) plugin dialog does not display the subject of email links if the subject parameter is not lowercase. -* [#9192](https://dev.ckeditor.com/ticket/9192): Fixed: An `undefined` string is appended to an email address added with the [Link](https://ckeditor.com/cke4/addon/link) plugin if subject and email body are empty and [`config.emailProtection`](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR.config-cfg-emailProtection) is set to `encode`. +* [#9192](https://dev.ckeditor.com/ticket/9192): Fixed: An `undefined` string is appended to an email address added with the [Link](https://ckeditor.com/cke4/addon/link) plugin if subject and email body are empty and [`config.emailProtection`](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_config.html#cfg-emailProtection) is set to `encode`. * [#13790](https://dev.ckeditor.com/ticket/13790): Fixed: It is not possible to destroy the editor `<iframe>` after the editor was detached from DOM. Thanks to [Stefan Rijnhart](https://github.com/StefanRijnhart)! * [#13803](https://dev.ckeditor.com/ticket/13803): Fixed: The editor cannot be destroyed before being fully initialized. Thanks to [Cyril Fluck](https://github.com/cyril-sf)! * [#13867](https://dev.ckeditor.com/ticket/13867): Fixed: CKEditor does not work when the `classList` polyfill is used. * [#13885](https://dev.ckeditor.com/ticket/13885): Fixed: [Enhanced Image](https://ckeditor.com/cke4/addon/image2) requires the [Link](https://ckeditor.com/cke4/addon/link) plugin to link an image. * [#13883](https://dev.ckeditor.com/ticket/13883): Fixed: Copying a table using the context menu strips off styles. -* [#13872](https://dev.ckeditor.com/ticket/13872): Fixed: Cutting is possible in the [read-only](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR.editor-property-readOnly) mode. -* [#12848](https://dev.ckeditor.com/ticket/12848): [Blink] Fixed: Opening the [Find and Replace](https://ckeditor.com/cke4/addon/find) dialog window in the [read-only](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR.editor-property-readOnly) mode throws an exception. -* [#13879](https://dev.ckeditor.com/ticket/13879): Fixed: It is not possible to prevent the [`editor.drop`](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR.editor-event-drop) event. +* [#13872](https://dev.ckeditor.com/ticket/13872): Fixed: Cutting is possible in the [read-only](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_editor.html#property-readOnly) mode. +* [#12848](https://dev.ckeditor.com/ticket/12848): [Blink] Fixed: Opening the [Find and Replace](https://ckeditor.com/cke4/addon/find) dialog window in the [read-only](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_editor.html#property-readOnly) mode throws an exception. +* [#13879](https://dev.ckeditor.com/ticket/13879): Fixed: It is not possible to prevent the [`editor.drop`](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_editor.html#event-drop) event. * [#13361](https://dev.ckeditor.com/ticket/13361): Fixed: Skin images fail when the site path includes parentheses because the `background-image` path needs single quotes around the URL value. * [#13771](https://dev.ckeditor.com/ticket/13771): Fixed: The `contents.css` style is not used if the [IFrame Editing Area](https://ckeditor.com/cke4/addon/wysiwygarea) plugin is missing. * [#13782](https://dev.ckeditor.com/ticket/13782): Fixed: Unclear log messages. @@ -576,14 +606,14 @@ Fixed Issues: Other Changes: -* [#11725](https://dev.ckeditor.com/ticket/11725): Marked [`CKEDITOR.env.mobile`](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR.env-property-mobile) as deprecated. The reason is that it is no longer clear what "mobile" means. +* [#11725](https://dev.ckeditor.com/ticket/11725): Marked [`CKEDITOR.env.mobile`](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_env.html#property-mobile) as deprecated. The reason is that it is no longer clear what "mobile" means. * [#13737](https://dev.ckeditor.com/ticket/13737): Upgraded [Bender.js](https://github.com/benderjs/benderjs) to 0.4.1. ## CKEditor 4.5.3 New Features: -* [#13501](https://dev.ckeditor.com/ticket/13501): Added the [`config.fileTools_defaultFileName`](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR.config-cfg-fileTools_defaultFileName) option to allow setting a default file name for paste uploads. +* [#13501](https://dev.ckeditor.com/ticket/13501): Added the [`config.fileTools_defaultFileName`](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_config.html#cfg-fileTools_defaultFileName) option to allow setting a default file name for paste uploads. * [#13603](https://dev.ckeditor.com/ticket/13603): Added support for uploading dropped BMP images. Fixed Issues: @@ -593,7 +623,7 @@ Fixed Issues: * [#8780](https://dev.ckeditor.com/ticket/8780), * [#12762](https://dev.ckeditor.com/ticket/12762). * [#13386](https://dev.ckeditor.com/ticket/13386): [Edge] Fixed: Issues with selecting and editing images. -* [#13568](https://dev.ckeditor.com/ticket/13568): Fixed: The [`editor.getSelectedHtml()`](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR.editor-method-getSelectedHtml) method returns invalid results for entire content selection. +* [#13568](https://dev.ckeditor.com/ticket/13568): Fixed: The [`editor.getSelectedHtml()`](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_editor.html#method-getSelectedHtml) method returns invalid results for entire content selection. * [#13453](https://dev.ckeditor.com/ticket/13453): Fixed: Drag&drop of entire editor content throws an error. * [#13465](https://dev.ckeditor.com/ticket/13465): Fixed: Error is thrown and the widget is lost on drag&drop if it is the only content of the editor. * [#13414](https://dev.ckeditor.com/ticket/13414): Fixed: Content auto paragraphing in a nested editable despite editor configuration. @@ -615,16 +645,16 @@ Fixed Issues: * [#13494](https://dev.ckeditor.com/ticket/13494): Fixed: Error thrown in the toolbar configurator if plugin requirements are not met. * [#13409](https://dev.ckeditor.com/ticket/13409): Fixed: List elements incorrectly merged when pressing *Backspace* or *Delete*. * [#13434](https://dev.ckeditor.com/ticket/13434): Fixed: Dialog state indicator broken in Right–To–Left environments. -* [#13460](https://dev.ckeditor.com/ticket/13460): [IE8] Fixed: Copying inline widgets is broken when [Advanced Content Filter](https://docs.ckeditor.com/ckeditor4/docs/#!/guide/dev_acf) is disabled. +* [#13460](https://dev.ckeditor.com/ticket/13460): [IE8] Fixed: Copying inline widgets is broken when [Advanced Content Filter](https://ckeditor.com/docs/ckeditor4/latest/guide/dev_acf.html) is disabled. * [#13495](https://dev.ckeditor.com/ticket/13495): [Firefox, IE] Fixed: Text is not word-wrapped in the Paste dialog window. * [#13528](https://dev.ckeditor.com/ticket/13528): [Firefox@Windows] Fixed: Content copied from Microsoft Word and other external applications is pasted as a plain text. Removed the `CKEDITOR.plugins.clipboard.isHtmlInExternalDataTransfer` property as the check must be dynamic. -* [#13583](https://dev.ckeditor.com/ticket/13583): Fixed: [`DataTransfer.getData()`](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR.plugins.clipboard.dataTransfer-method-getData) should work consistently in all browsers and should not strip valuable content. Fixed pasting tables from Microsoft Excel on Chrome. +* [#13583](https://dev.ckeditor.com/ticket/13583): Fixed: [`DataTransfer.getData()`](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_plugins_clipboard_dataTransfer.html#method-getData) should work consistently in all browsers and should not strip valuable content. Fixed pasting tables from Microsoft Excel on Chrome. * [#13468](https://dev.ckeditor.com/ticket/13468): [IE] Fixed: Binding drag&drop `dataTransfer` does not work if `text` data was set in the meantime. * [#13451](https://dev.ckeditor.com/ticket/13451): [IE8-9] Fixed: One drag&drop operation may affect following ones. * [#13184](https://dev.ckeditor.com/ticket/13184): Fixed: Web page reloaded after a drop on editor UI. * [#13129](https://dev.ckeditor.com/ticket/13129) Fixed: Block widget blurred after a drop followed by an undo. * [#13397](https://dev.ckeditor.com/ticket/13397): Fixed: Drag&drop of a widget inside its nested widget crashes the editor. -* [#13385](https://dev.ckeditor.com/ticket/13385): Fixed: [`editor.getSnapshot()`](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR.editor-method-getSnapshot) may return a non-string value. +* [#13385](https://dev.ckeditor.com/ticket/13385): Fixed: [`editor.getSnapshot()`](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_editor.html#method-getSnapshot) may return a non-string value. * [#13419](https://dev.ckeditor.com/ticket/13419): Fixed: The [Auto Link](https://ckeditor.com/cke4/addon/autolink) plugin does not encode double quotes in URLs. * [#13420](https://dev.ckeditor.com/ticket/13420): Fixed: The [Auto Embed](https://ckeditor.com/cke4/addon/autoembed) plugin ignores encoded characters in URL parameters. * [#13410](https://dev.ckeditor.com/ticket/13410): Fixed: Error thrown in the [Auto Embed](https://ckeditor.com/cke4/addon/autoembed) plugin when undoing right after pasting a link. @@ -652,16 +682,16 @@ Fixed Issues: New Features: -* [#13304](https://dev.ckeditor.com/ticket/13304): Added support for passing DOM elements to [`config.sharedSpaces`](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR.config-cfg-sharedSpaces). Thanks to [Undergrounder](https://github.com/Undergrounder)! +* [#13304](https://dev.ckeditor.com/ticket/13304): Added support for passing DOM elements to [`config.sharedSpaces`](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_config.html#cfg-sharedSpaces). Thanks to [Undergrounder](https://github.com/Undergrounder)! * [#13215](https://dev.ckeditor.com/ticket/13215): Added ability to cancel fetching a resource by the Embed plugins. -* [#13213](https://dev.ckeditor.com/ticket/13213): Added the [`dialog#setState()`](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR.dialog-method-setState) method and used it in the [Embed](https://ckeditor.com/cke4/addon/embed) dialog to indicate that a resource is being loaded. -* [#13337](https://dev.ckeditor.com/ticket/13337): Added the [`repository.onWidget()`](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR.plugins.widget.repository-method-onWidget) method — a convenient way to listen to [widget](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR.plugins.widget) events through the [repository](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR.plugins.widget.repository). +* [#13213](https://dev.ckeditor.com/ticket/13213): Added the [`dialog#setState()`](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_dialog.html#method-setState) method and used it in the [Embed](https://ckeditor.com/cke4/addon/embed) dialog to indicate that a resource is being loaded. +* [#13337](https://dev.ckeditor.com/ticket/13337): Added the [`repository.onWidget()`](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_plugins_widget_repository.html#method-onWidget) method — a convenient way to listen to [widget](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR.plugins.widget.html) events through the [repository](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR.plugins.widget.repository.html). * [#13214](https://dev.ckeditor.com/ticket/13214): Added support for pasting links that convert into embeddable resources on the fly. Fixed Issues: * [#13334](https://dev.ckeditor.com/ticket/13334): Fixed: Error after nesting widgets and playing with undo/redo. -* [#13118](https://dev.ckeditor.com/ticket/13118): Fixed: The [`editor.getSelectedHtml()`](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR.editor-method-getSelectedHtml) method throws an error when called in the source mode. +* [#13118](https://dev.ckeditor.com/ticket/13118): Fixed: The [`editor.getSelectedHtml()`](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_editor.html#method-getSelectedHtml) method throws an error when called in the source mode. * [#13158](https://dev.ckeditor.com/ticket/13158): Fixed: Error after canceling a dialog when creating a widget. * [#13197](https://dev.ckeditor.com/ticket/13197): Fixed: Linked inline [Enhanced Image](https://ckeditor.com/cke4/addon/image2) alignment class is not transferred to the widget wrapper. * [#13199](https://dev.ckeditor.com/ticket/13199): Fixed: [Semantic Embed](https://ckeditor.com/cke4/addon/embedsemantic) does not support widget classes. @@ -670,24 +700,24 @@ Fixed Issues: * [#13300](https://dev.ckeditor.com/ticket/13300): Fixed: The `internalCommit` argument in the [Image](https://ckeditor.com/cke4/addon/image) dialog seems to be never used. * [#13036](https://dev.ckeditor.com/ticket/13036): Fixed: Notifications are moved 10px to the right. * [#13280](https://dev.ckeditor.com/ticket/13280): [IE8] Fixed: Undo after inline widget drag&drop throws an error. -* [#13186](https://dev.ckeditor.com/ticket/13186): Fixed: Content dropped into a nested editable is not filtered by [Advanced Content Filter](https://docs.ckeditor.com/ckeditor4/docs/#!/guide/dev_acf). +* [#13186](https://dev.ckeditor.com/ticket/13186): Fixed: Content dropped into a nested editable is not filtered by [Advanced Content Filter](https://ckeditor.com/docs/ckeditor4/latest/guide/dev_acf.html). * [#13140](https://dev.ckeditor.com/ticket/13140): Fixed: Error thrown when dropping a block widget right after itself. * [#13176](https://dev.ckeditor.com/ticket/13176): [IE8] Fixed: Errors on drag&drop of embed widgets. * [#13015](https://dev.ckeditor.com/ticket/13015): Fixed: Dropping an image file on [Enhanced Image](https://ckeditor.com/cke4/addon/image2) causes a page reload. * [#13080](https://dev.ckeditor.com/ticket/13080): Fixed: Ugly notification shown when the response contains HTML content. * [#13011](https://dev.ckeditor.com/ticket/13011): [IE8] Fixed: Anchors are duplicated on drag&drop in specific locations. -* [#13105](https://dev.ckeditor.com/ticket/13105): Fixed: Various issues related to [`CKEDITOR.tools.htmlEncode()`](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR.tools-method-htmlEncode) and [`CKEDITOR.tools.htmlDecode()`](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR.tools-method-htmlDecode) methods. +* [#13105](https://dev.ckeditor.com/ticket/13105): Fixed: Various issues related to [`CKEDITOR.tools.htmlEncode()`](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_tools.html#method-htmlEncode) and [`CKEDITOR.tools.htmlDecode()`](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_tools.html#method-htmlDecode) methods. * [#11976](https://dev.ckeditor.com/ticket/11976): [Chrome] Fixed: Copy&paste and drag&drop lists from Microsoft Word. * [#13128](https://dev.ckeditor.com/ticket/13128): Fixed: Various issues with cloning element IDs: - * Fixed the default behavior of [`range.cloneContents()`](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR.dom.range-method-cloneContents) and [`range.extractContents()`](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR.dom.range-method-extractContents) methods which now clone IDs similarly to their native counterparts. - * Added `cloneId` arguments to the above methods, [`range.splitBlock()`](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR.dom.range-method-splitBlock) and [`element.breakParent()`](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR.dom.element-method-breakParent). Mind the default values and special behavior in the `extractContents()` method! + * Fixed the default behavior of [`range.cloneContents()`](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_dom_range.html#method-cloneContents) and [`range.extractContents()`](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_dom_range.html#method-extractContents) methods which now clone IDs similarly to their native counterparts. + * Added `cloneId` arguments to the above methods, [`range.splitBlock()`](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_dom_range.html#method-splitBlock) and [`element.breakParent()`](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_dom_element.html#method-breakParent). Mind the default values and special behavior in the `extractContents()` method! * Fixed issues where IDs were lost on copy&paste and drag&drop. * Toolbar configurators: * [#13185](https://dev.ckeditor.com/ticket/13185): Fixed: Wrong position of the suggestion box if there is not enough space below the caret. * [#13138](https://dev.ckeditor.com/ticket/13138): Fixed: The "Toggle empty elements" button label is unclear. * [#13136](https://dev.ckeditor.com/ticket/13136): Fixed: Autocompleter is far too intrusive. * [#13133](https://dev.ckeditor.com/ticket/13133): Fixed: Tab leaves the editor. - * [#13173](https://dev.ckeditor.com/ticket/13173): Fixed: [`config.removeButtons`](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR.config-cfg-removeButtons) is ignored by the advanced toolbar configurator. + * [#13173](https://dev.ckeditor.com/ticket/13173): Fixed: [`config.removeButtons`](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_config.html#cfg-removeButtons) is ignored by the advanced toolbar configurator. Other Changes: @@ -695,8 +725,8 @@ Other Changes: * Toolbar configurators: * [#13147](https://dev.ckeditor.com/ticket/13147): Added buttons to the sticky toolbar. * [#13207](https://dev.ckeditor.com/ticket/13207): Used modal window to display toolbar configurator help. -* [#13316](https://dev.ckeditor.com/ticket/13316): Made [`CKEDITOR.env.isCompatible`](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR.env-property-isCompatible) a blacklist rather than a whitelist. More about the change in the [Browser Compatibility](https://docs.ckeditor.com/ckeditor4/docs/#!/guide/dev_browsers) guide. -* [#13398](https://dev.ckeditor.com/ticket/13398): Renamed `CKEDITOR.fileTools.UploadsRepository` to [`CKEDITOR.fileTools.UploadRepository`](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR.fileTools.uploadRepository) and changed all related properties. +* [#13316](https://dev.ckeditor.com/ticket/13316): Made [`CKEDITOR.env.isCompatible`](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_env.html#property-isCompatible) a blacklist rather than a whitelist. More about the change in the [Browser Compatibility](https://ckeditor.com/docs/ckeditor4/latest/guide/dev_browsers.html) guide. +* [#13398](https://dev.ckeditor.com/ticket/13398): Renamed `CKEDITOR.fileTools.UploadsRepository` to [`CKEDITOR.fileTools.UploadRepository`](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR.fileTools.uploadRepository.html) and changed all related properties. * [#13279](https://dev.ckeditor.com/ticket/13279): Reviewed CSS vendor prefixes. * [#13454](https://dev.ckeditor.com/ticket/13454): Removed unused `lang.image.alertUrl` token from the [Image](https://ckeditor.com/cke4/addon/image) plugin. @@ -708,18 +738,18 @@ New Features: * Major features: * Support for dropping and pasting files into the editor was introduced. Through a set of new facades for native APIs it is now possible to easily intercept and process inserted files. - * [File upload tools](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR.fileTools) were introduced in order to simplify controlling the loading, uploading and handling server response, properly handle [new upload configuration](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR.config-cfg-uploadUrl) options, etc. - * [Upload Image](https://ckeditor.com/cke4/addon/uploadimage) widget was introduced to upload dropped images. A base class for the [upload widget](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR.fileTools.uploadWidgetDefinition) was exposed, too, to make it simple to create new types of upload widgets which can handle any type of dropped file, show the upload progress and update the content when the process is done. It also handles editing and undo/redo operations when a file is being uploaded and integrates with the [notification aggregator](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR.plugins.notificationAggregator) to show progress and success or error. - * All drag and drop operations were integrated with the editor. All dropped content is passed through the [`editor#paste`](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR.editor-event-paste) event and a set of new editor events was introduced — [`dragstart`](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR.editor-event-dragstart), [`drop`](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR.editor-event-drop), [`dragend`](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR.editor-event-dragend). - * The [Data Transfer](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR.plugins.clipboard.dataTransfer) facade was introduced to unify access to data in various types and files. [Data Transfer](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR.plugins.clipboard.dataTransfer) is now always available in the [`editor#paste`](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR.editor-event-paste) event. + * [File upload tools](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR.fileTools.html) were introduced in order to simplify controlling the loading, uploading and handling server response, properly handle [new upload configuration](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_config.html#cfg-uploadUrl) options, etc. + * [Upload Image](https://ckeditor.com/cke4/addon/uploadimage) widget was introduced to upload dropped images. A base class for the [upload widget](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR.fileTools.uploadWidgetDefinition.html) was exposed, too, to make it simple to create new types of upload widgets which can handle any type of dropped file, show the upload progress and update the content when the process is done. It also handles editing and undo/redo operations when a file is being uploaded and integrates with the [notification aggregator](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR.plugins.notificationAggregator.html) to show progress and success or error. + * All drag and drop operations were integrated with the editor. All dropped content is passed through the [`editor#paste`](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_editor.html#event-paste) event and a set of new editor events was introduced — [`dragstart`](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_editor.html#event-dragstart), [`drop`](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_editor.html#event-drop), [`dragend`](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_editor.html#event-dragend). + * The [Data Transfer](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR.plugins.clipboard.dataTransfer.html) facade was introduced to unify access to data in various types and files. [Data Transfer](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR.plugins.clipboard.dataTransfer.html) is now always available in the [`editor#paste`](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_editor.html#event-paste) event. * Switched from the pastebin to using the native clipboard access whenever possible. This solved many issues related to pastebin such as unnecessary scrolling or data loss. Additionally, on copy and cut from the editor the clipboard data is set. Therefore, on paste the editor has access to clean data, undisturbed by the browsers. * Drag and drop of inline and block widgets was integrated with the standard clipboard APIs. By listening to drag events you will thus be notified about widgets, too. This opens a possibility to filter pasted and dropped widgets. - * The [`editor#paste`](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR.editor-event-paste) event can have the `range` parameter so it is possible to change the paste position in the listener or paste in the not selectable position. Also the [`editor.insertHtml()`](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR.editor-method-insertHtml) method now accepts `range` as an additional parameter. - * [#11621](https://dev.ckeditor.com/ticket/11621): A configurable [paste filter](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR.config-cfg-pasteFilter) was introduced. The filter is by default turned to `'semantic-content'` on Webkit and Blink for all pasted content coming from external sources because of the low quality of HTML that these engines put into the clipboard. Internal and cross-editor paste is safe due to the change explained in the previous point. + * The [`editor#paste`](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_editor.html#event-paste) event can have the `range` parameter so it is possible to change the paste position in the listener or paste in the not selectable position. Also the [`editor.insertHtml()`](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_editor.html#method-insertHtml) method now accepts `range` as an additional parameter. + * [#11621](https://dev.ckeditor.com/ticket/11621): A configurable [paste filter](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_config.html#cfg-pasteFilter) was introduced. The filter is by default turned to `'semantic-content'` on Webkit and Blink for all pasted content coming from external sources because of the low quality of HTML that these engines put into the clipboard. Internal and cross-editor paste is safe due to the change explained in the previous point. * Other changes and related fixes: - * [#12095](https://dev.ckeditor.com/ticket/12095): On drag and copy of widgets [the same method](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR.editor-method-getSelectedHtml) is used to get selected HTML as in the normal case. Thanks to that styles applied to inline widgets are not lost. - * [#11219](https://dev.ckeditor.com/ticket/11219): Fixed: Dragging a [captioned image](https://ckeditor.com/cke4/addon/image2) does not fire the [`editor#paste`](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR.editor-event-paste) event. + * [#12095](https://dev.ckeditor.com/ticket/12095): On drag and copy of widgets [the same method](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_editor.html#method-getSelectedHtml) is used to get selected HTML as in the normal case. Thanks to that styles applied to inline widgets are not lost. + * [#11219](https://dev.ckeditor.com/ticket/11219): Fixed: Dragging a [captioned image](https://ckeditor.com/cke4/addon/image2) does not fire the [`editor#paste`](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_editor.html#event-paste) event. * [#9554](https://dev.ckeditor.com/ticket/9554): [Webkit Mac] Fixed: Editor scrolls on paste. * [#9898](https://dev.ckeditor.com/ticket/9898): [Webkit&Divarea] Fixed: Pasting causes undesirable scrolling. * [#11993](https://dev.ckeditor.com/ticket/11993): [Chrome] Fixed: Pasting content scrolls the document. @@ -734,48 +764,48 @@ New Features: * Direct access to clipboard could only be implemented in Chrome, Safari on Mac OS, Opera and Firefox. In other browsers the pastebin must still be used. * [#12875](https://dev.ckeditor.com/ticket/12875): Samples and toolbar configuration tools. - * The old set of samples shipped with every CKEditor package was replaced with a shiny new single-page sample. This change concluded a long term plan which started from introducing the [CKEditor SDK](https://sdk.ckeditor.com/) and [CKEditor Functionality Overview](https://docs.ckeditor.com/ckeditor4/docs/#!/guide/dev_features) section in the documentation which essentially redefined the old samples. + * The old set of samples shipped with every CKEditor package was replaced with a shiny new single-page sample. This change concluded a long term plan which started from introducing the [CKEditor SDK](https://sdk.ckeditor.com/) and [CKEditor Functionality Overview](https://ckeditor.com/docs/ckeditor4/latest/guide/dev_features.html) section in the documentation which essentially redefined the old samples. * Toolbar configurators with live previews were introduced. They will be shipped with every CKEditor package and are meant to help in configuring toolbar layouts. -* [#10925](https://dev.ckeditor.com/ticket/10925): The [Media Embed](https://ckeditor.com/cke4/addon/embed) and [Semantic Media Embed](https://ckeditor.com/cke4/addon/embedsemantic) plugins were introduced. Read more about the new features in the [Embedding Content](https://docs.ckeditor.com/ckeditor4/docs/#!/guide/dev_media_embed) article. -* [#10931](https://dev.ckeditor.com/ticket/10931): Added support for nesting widgets. It is now possible to insert one widget into another widget's nested editable. Note that unless nested editable's [allowed content](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR.plugins.widget.nestedEditable.definition-property-allowedContent) is defined precisely, starting from CKEditor 4.5 some widget buttons may become enabled. This feature is not supported in IE8. Included issues: +* [#10925](https://dev.ckeditor.com/ticket/10925): The [Media Embed](https://ckeditor.com/cke4/addon/embed) and [Semantic Media Embed](https://ckeditor.com/cke4/addon/embedsemantic) plugins were introduced. Read more about the new features in the [Embedding Content](https://ckeditor.com/docs/ckeditor4/latest/guide/dev_media_embed.html) article. +* [#10931](https://dev.ckeditor.com/ticket/10931): Added support for nesting widgets. It is now possible to insert one widget into another widget's nested editable. Note that unless nested editable's [allowed content](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_plugins_widget_nestedEditable_definition.html#property-allowedContent) is defined precisely, starting from CKEditor 4.5 some widget buttons may become enabled. This feature is not supported in IE8. Included issues: * [#12018](https://dev.ckeditor.com/ticket/12018): Fixed and reviewed: Nested widgets garbage collection. * [#12024](https://dev.ckeditor.com/ticket/12024): [Firefox] Fixed: Outline is extended to the left by unpositioned drag handlers. * [#12006](https://dev.ckeditor.com/ticket/12006): Fixed: Drag and drop of nested block widgets. - * [#12008](https://dev.ckeditor.com/ticket/12008): Fixed various cases of inserting a single non-editable element using the [`editor.insertHtml()`](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR.editor-method-insertHtml) method. Fixes pasting a widget with a nested editable inside another widget's nested editable. + * [#12008](https://dev.ckeditor.com/ticket/12008): Fixed various cases of inserting a single non-editable element using the [`editor.insertHtml()`](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_editor.html#method-insertHtml) method. Fixes pasting a widget with a nested editable inside another widget's nested editable. * Notification system: - * [#11580](https://dev.ckeditor.com/ticket/11580): Introduced the [notification system](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR.plugins.notification). - * [#12810](https://dev.ckeditor.com/ticket/12810): Introduced a [notification aggregator](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR.plugins.notificationAggregator) for the [notification system](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR.plugins.notification) which simplifies displaying progress of many concurrent tasks. -* [#11636](https://dev.ckeditor.com/ticket/11636): Introduced new, UX-focused, methods for getting selected HTML and deleting it — [`editor.getSelectedHtml()`](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR.editor-method-getSelectedHtml) and [`editor.extractSelectedHtml()`](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR.editor-method-extractSelectedHtml). -* [#12416](https://dev.ckeditor.com/ticket/12416): Added the [`widget.definition.upcastPriority`](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR.plugins.widget.definition-property-upcastPriority) property which gives more control over widget upcasting order to the widget author. -* [#12036](https://dev.ckeditor.com/ticket/12036): Initialize the editor in [read-only](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR.editor-property-readOnly) mode when the `<textarea>` element has a `readonly` attribute. -* [#11905](https://dev.ckeditor.com/ticket/11905): The [`resize` event](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR.editor-event-resize) passes the current dimensions in its data. -* [#12126](https://dev.ckeditor.com/ticket/12126): Introduced [`config.image_prefillDimensions`](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR.config-cfg-image_prefillDimensions) and [`config.image2_prefillDimensions`](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR.config-cfg-image2_prefillDimensions) to make pre-filling `width` and `height` configurable for the [Enhanced Image](https://ckeditor.com/cke4/addon/image2). + * [#11580](https://dev.ckeditor.com/ticket/11580): Introduced the [notification system](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR.plugins.notification.html). + * [#12810](https://dev.ckeditor.com/ticket/12810): Introduced a [notification aggregator](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR.plugins.notificationAggregator.html) for the [notification system](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR.plugins.notification.html) which simplifies displaying progress of many concurrent tasks. +* [#11636](https://dev.ckeditor.com/ticket/11636): Introduced new, UX-focused, methods for getting selected HTML and deleting it — [`editor.getSelectedHtml()`](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_editor.html#method-getSelectedHtml) and [`editor.extractSelectedHtml()`](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_editor.html#method-extractSelectedHtml). +* [#12416](https://dev.ckeditor.com/ticket/12416): Added the [`widget.definition.upcastPriority`](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_plugins_widget_definition.html#property-upcastPriority) property which gives more control over widget upcasting order to the widget author. +* [#12036](https://dev.ckeditor.com/ticket/12036): Initialize the editor in [read-only](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_editor.html#property-readOnly) mode when the `<textarea>` element has a `readonly` attribute. +* [#11905](https://dev.ckeditor.com/ticket/11905): The [`resize` event](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_editor.html#event-resize) passes the current dimensions in its data. +* [#12126](https://dev.ckeditor.com/ticket/12126): Introduced [`config.image_prefillDimensions`](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_config.html#cfg-image_prefillDimensions) and [`config.image2_prefillDimensions`](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_config.html#cfg-image2_prefillDimensions) to make pre-filling `width` and `height` configurable for the [Enhanced Image](https://ckeditor.com/cke4/addon/image2). * [#12746](https://dev.ckeditor.com/ticket/12746): Added a new configuration option to hide the [Enhanced Image](https://ckeditor.com/cke4/addon/image2) resizer. -* [#12150](https://dev.ckeditor.com/ticket/12150): Exposed the [`getNestedEditable()`](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR.plugins.widget-static-method-getNestedEditable) and `is*` [widget helper](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR.plugins.widget) functions (see the static methods). -* [#12448](https://dev.ckeditor.com/ticket/12448): Introduced the [`editable.insertHtmlIntoRange`](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR.editable-method-insertHtmlIntoRange) method. -* [#12143](https://dev.ckeditor.com/ticket/12143): Added the [`config.floatSpacePreferRight`](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR.config-cfg-floatSpacePreferRight) configuration option that switches the alignment of the floating toolbar. Thanks to [InvisibleBacon](http://github.com/InvisibleBacon)! -* [#10986](https://dev.ckeditor.com/ticket/10986): Added support for changing dialog input and textarea text directions by using the *Shift+Alt+Home/End* keystrokes. The direction is stored in the value of the input by prepending the [`\u202A`](http://unicode.org/cldr/utility/character.jsp?a=202A) or [`\u202B`](http://unicode.org/cldr/utility/character.jsp?a=202B) marker to it. Read more in the [documentation](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR.dialog.definition.textInput-property-bidi). Thanks to [edithkk](https://github.com/edithkk)! -* [#12770](https://dev.ckeditor.com/ticket/12770): Added support for passing [widget](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR.plugins.widget)'s startup data as a widget command's argument. Thanks to [Rebrov Boris](https://github.com/zipp3r) and [Tieme van Veen](https://github.com/tiemevanveen)! +* [#12150](https://dev.ckeditor.com/ticket/12150): Exposed the [`getNestedEditable()`](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_plugins_widget.html#static-method-getNestedEditable) and `is*` [widget helper](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR.plugins.widget.html) functions (see the static methods). +* [#12448](https://dev.ckeditor.com/ticket/12448): Introduced the [`editable.insertHtmlIntoRange`](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_editable.html#method-insertHtmlIntoRange) method. +* [#12143](https://dev.ckeditor.com/ticket/12143): Added the [`config.floatSpacePreferRight`](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_config.html#cfg-floatSpacePreferRight) configuration option that switches the alignment of the floating toolbar. Thanks to [InvisibleBacon](http://github.com/InvisibleBacon)! +* [#10986](https://dev.ckeditor.com/ticket/10986): Added support for changing dialog input and textarea text directions by using the *Shift+Alt+Home/End* keystrokes. The direction is stored in the value of the input by prepending the [`\u202A`](http://unicode.org/cldr/utility/character.jsp?a=202A) or [`\u202B`](http://unicode.org/cldr/utility/character.jsp?a=202B) marker to it. Read more in the [documentation](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_dialog_definition_textInput.html#property-bidi). Thanks to [edithkk](https://github.com/edithkk)! +* [#12770](https://dev.ckeditor.com/ticket/12770): Added support for passing [widget](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR.plugins.widget.html)'s startup data as a widget command's argument. Thanks to [Rebrov Boris](https://github.com/zipp3r) and [Tieme van Veen](https://github.com/tiemevanveen)! * [#11583](https://dev.ckeditor.com/ticket/11583): Added support for the HTML5 `required` attribute in various form elements. Thanks to [Steven Busse](https://github.com/sbusse)! Changes: * [#12858](https://dev.ckeditor.com/ticket/12858): Basic [Spartan](http://blogs.windows.com/bloggingwindows/2015/03/30/introducing-project-spartan-the-new-browser-built-for-windows-10/) browser compatibility. Full compatibility will be introduced later, because at the moment Spartan is still too unstable to be used for tests and we see many changes from version to version. -* [#12948](https://dev.ckeditor.com/ticket/12948): The [`config.mathJaxLibrary`](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR.config-cfg-mathJaxLib) option does not default to the MathJax CDN any more. It needs to be configured to enable the [Mathematical Formulas](https://ckeditor.com/cke4/addon/mathjax) plugin now. -* [#13069](https://dev.ckeditor.com/ticket/13069): Fixed inconsistencies between [`editable.insertHtml()`](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR.editable-method-insertElement) and [`editable.insertElement()`](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR.editable-method-insertElement) when the `range` parameter is used. Now, the `editor.insertElement()` method works on a higher level, which means that it saves undo snapshots and sets the selection after insertion. Use the [`editable.insertElementIntoRange()`](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR.editable-method-insertElementIntoRange) method directly for the pre 4.5 behavior of `editable.insertElement()`. -* [#12870](https://dev.ckeditor.com/ticket/12870): Use [`editor.showNotification()`](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR.editor-method-showNotification) instead of `alert()` directly whenever possible. When the [Notification plugin](https://ckeditor.com/cke4/addon/notification) is loaded, the notification system is used automatically. Otherwise, the native `alert()` is displayed. +* [#12948](https://dev.ckeditor.com/ticket/12948): The [`config.mathJaxLibrary`](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_config.html#cfg-mathJaxLib) option does not default to the MathJax CDN any more. It needs to be configured to enable the [Mathematical Formulas](https://ckeditor.com/cke4/addon/mathjax) plugin now. +* [#13069](https://dev.ckeditor.com/ticket/13069): Fixed inconsistencies between [`editable.insertHtml()`](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_editable.html#method-insertElement) and [`editable.insertElement()`](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_editable.html#method-insertElement) when the `range` parameter is used. Now, the `editor.insertElement()` method works on a higher level, which means that it saves undo snapshots and sets the selection after insertion. Use the [`editable.insertElementIntoRange()`](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_editable.html#method-insertElementIntoRange) method directly for the pre 4.5 behavior of `editable.insertElement()`. +* [#12870](https://dev.ckeditor.com/ticket/12870): Use [`editor.showNotification()`](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_editor.html#method-showNotification) instead of `alert()` directly whenever possible. When the [Notification plugin](https://ckeditor.com/cke4/addon/notification) is loaded, the notification system is used automatically. Otherwise, the native `alert()` is displayed. * [#8024](https://dev.ckeditor.com/ticket/8024): Swapped behavior of the Split Cell Vertically and Horizontally features of the [Table Tools](https://ckeditor.com/cke4/addon/tabletools) plugin to be more intuitive. Thanks to [kevinisagit](https://github.com/kevinisagit)! -* [#10903](https://dev.ckeditor.com/ticket/10903): Performance improvements for the [`dom.element.addClass()`](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR.dom.element-method-addClass), [`dom.element.removeClass()`](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR.dom.element-method-removeClass) and [`dom.element.hasClass()`](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR.dom.element-method-hasClass) methods. Note: The previous implementation allowed passing multiple classes to `addClass()` although it was only a side effect of that implementation. The new implementation does not allow this. +* [#10903](https://dev.ckeditor.com/ticket/10903): Performance improvements for the [`dom.element.addClass()`](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_dom_element.html#method-addClass), [`dom.element.removeClass()`](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_dom_element.html#method-removeClass) and [`dom.element.hasClass()`](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_dom_element.html#method-hasClass) methods. Note: The previous implementation allowed passing multiple classes to `addClass()` although it was only a side effect of that implementation. The new implementation does not allow this. * [#11856](https://dev.ckeditor.com/ticket/11856): The jQuery adapter throws a meaningful error if CKEditor or jQuery are not loaded. Fixed issues: -* [#11586](https://dev.ckeditor.com/ticket/11586): Fixed: [`range.cloneContents()`](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR.dom.range-method-cloneContents) should not change the DOM in order not to affect selection. -* [#12148](https://dev.ckeditor.com/ticket/12148): Fixed: [`dom.element.getChild()`](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR.dom.element-method-getChild) should not modify a passed array. +* [#11586](https://dev.ckeditor.com/ticket/11586): Fixed: [`range.cloneContents()`](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_dom_range.html#method-cloneContents) should not change the DOM in order not to affect selection. +* [#12148](https://dev.ckeditor.com/ticket/12148): Fixed: [`dom.element.getChild()`](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_dom_element.html#method-getChild) should not modify a passed array. * [#12503](https://dev.ckeditor.com/ticket/12503): [Blink/Webkit] Fixed: Incorrect result of Select All and *Backspace* or *Delete*. -* [#13001](https://dev.ckeditor.com/ticket/13001): [Firefox] Fixed: The `<br />` filler is placed in the wrong position by the [`range.fixBlock()`](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR.dom.range-method-fixBlock) method due to quirky Firefox behavior. +* [#13001](https://dev.ckeditor.com/ticket/13001): [Firefox] Fixed: The `<br />` filler is placed in the wrong position by the [`range.fixBlock()`](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_dom_range.html#method-fixBlock) method due to quirky Firefox behavior. * [#13101](https://dev.ckeditor.com/ticket/13101): [IE8] Fixed: Colons are prepended to HTML5 element names when cloning them. ## CKEditor 4.4.8 @@ -792,14 +822,14 @@ Fixed Issues: * [#12899](https://dev.ckeditor.com/ticket/12899): Fixed: Corrected wrong tag ending for horizontal box definition in the [Dialog User Interface](https://ckeditor.com/cke4/addon/dialogui) plugin. Thanks to [mizafish](https://github.com/mizafish)! * [#13254](https://dev.ckeditor.com/ticket/13254): Fixed: Cannot outdent block after indent when using the [Div Editing Area](https://ckeditor.com/cke4/addon/divarea) plugin. Thanks to [Jonathan Cottrill](https://github.com/jcttrll)! -* [#13268](https://dev.ckeditor.com/ticket/13268): Fixed: Documentation for [`CKEDITOR.dom.text`](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR.dom.text) is incorrect. Thanks to [Ben Kiefer](https://github.com/benkiefer)! +* [#13268](https://dev.ckeditor.com/ticket/13268): Fixed: Documentation for [`CKEDITOR.dom.text`](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR.dom.text.html) is incorrect. Thanks to [Ben Kiefer](https://github.com/benkiefer)! * [#12739](https://dev.ckeditor.com/ticket/12739): Fixed: Link loses inline styles when edited without the [Advanced Tab for Dialogs](https://ckeditor.com/cke4/addon/dialogadvtab) plugin. Thanks to [Віталій Крутько](https://github.com/asmforce)! * [#13292](https://dev.ckeditor.com/ticket/13292): Fixed: Protection pattern does not work in attribute in self-closing elements with no space before `/>`. Thanks to [Віталій Крутько](https://github.com/asmforce)! -* [PR#192](https://github.com/ckeditor/ckeditor-dev/pull/192): Fixed: Variable name typo in the [Dialog User Interface](https://ckeditor.com/cke4/addon/dialogui) plugin which caused [`CKEDITOR.ui.dialog.radio`](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR.ui.dialog.radio) validation to not work. Thanks to [Florian Ludwig](https://github.com/FlorianLudwig)! -* [#13232](https://dev.ckeditor.com/ticket/13232): [Safari] Fixed: The [`element.appendText()`](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR.dom.element-method-appendText) method does not work properly for empty elements. -* [#13233](https://dev.ckeditor.com/ticket/13233): Fixed: [HTMLDataProcessor](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR.htmlDataProcessor) can process `foo:href` attributes. +* [PR#192](https://github.com/ckeditor/ckeditor-dev/pull/192): Fixed: Variable name typo in the [Dialog User Interface](https://ckeditor.com/cke4/addon/dialogui) plugin which caused [`CKEDITOR.ui.dialog.radio`](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR.ui.dialog.radio.html) validation to not work. Thanks to [Florian Ludwig](https://github.com/FlorianLudwig)! +* [#13232](https://dev.ckeditor.com/ticket/13232): [Safari] Fixed: The [`element.appendText()`](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_dom_element.html#method-appendText) method does not work properly for empty elements. +* [#13233](https://dev.ckeditor.com/ticket/13233): Fixed: [HTMLDataProcessor](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR.htmlDataProcessor.html) can process `foo:href` attributes. * [#12796](https://dev.ckeditor.com/ticket/12796): Fixed: The [Indent List](https://ckeditor.com/cke4/addon/indentlist) plugin unwraps parent `<li>` elements. Thanks to [Andrew Stucki](https://github.com/andrewstucki)! -* [#12885](https://dev.ckeditor.com/ticket/12885): Added missing [`editor.getData()`](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR.editor-method-getData) parameter documentation. +* [#12885](https://dev.ckeditor.com/ticket/12885): Added missing [`editor.getData()`](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_editor.html#method-getData) parameter documentation. * [#11982](https://dev.ckeditor.com/ticket/11982): Fixed: Bullet added in a wrong position after the *Enter* key is pressed in a nested list. * [#13027](https://dev.ckeditor.com/ticket/13027): Fixed: Keyboard navigation in dialog windows with multiple tabs not following IBM CI 162 instructions or [ARIA Authoring Practices](http://www.w3.org/TR/2013/WD-wai-aria-practices-20130307/#tabpanel). * [#12256](https://dev.ckeditor.com/ticket/12256): Fixed: Basic styles classes are lost when pasting from Microsoft Word if [basic styles](https://ckeditor.com/cke4/addon/basicstyles) were configured to use classes. @@ -810,11 +840,11 @@ Fixed Issues: * [#13164](https://dev.ckeditor.com/ticket/13164): Fixed: Error when inserting a hidden field. * [#13155](https://dev.ckeditor.com/ticket/13155): Fixed: Incorrect [Line Utilities](https://ckeditor.com/cke4/addon/lineutils) positioning when `<body>` has a margin. * [#13351](https://dev.ckeditor.com/ticket/13351): Fixed: Link lost when editing a linked image with the Link tab disabled. This also fixed a bug when inserting an image into a fully selected link would throw an error ([#12847](https://dev.ckeditor.com/ticket/12847)). -* [#13344](https://dev.ckeditor.com/ticket/13344): [WebKit/Blink] Fixed: It is possible to remove or change editor content in [read-only mode](https://docs.ckeditor.com/ckeditor4/docs/#!/guide/dev_readonly). +* [#13344](https://dev.ckeditor.com/ticket/13344): [WebKit/Blink] Fixed: It is possible to remove or change editor content in [read-only mode](https://ckeditor.com/docs/ckeditor4/latest/guide/dev_readonly.html). Other Changes: -* [#12844](https://dev.ckeditor.com/ticket/12844) and [#13103](https://dev.ckeditor.com/ticket/13103): Upgraded the [testing environment](https://docs.ckeditor.com/ckeditor4/docs/#!/guide/dev_tests) to [Bender.js](https://github.com/benderjs/benderjs) `0.2.3`. +* [#12844](https://dev.ckeditor.com/ticket/12844) and [#13103](https://dev.ckeditor.com/ticket/13103): Upgraded the [testing environment](https://ckeditor.com/docs/ckeditor4/latest/guide/dev_tests.html) to [Bender.js](https://github.com/benderjs/benderjs) `0.2.3`. * [#12930](https://dev.ckeditor.com/ticket/12930): Because of licensing issues, `truncated-mathjax/` is now removed from the `tests/` directory. Now `bender.config.mathJaxLibPath` must be configured manually in order to run [Mathematical Formulas](https://ckeditor.com/cke4/addon/mathjax) plugin tests. * [#13266](https://dev.ckeditor.com/ticket/13266): Added more shades of gray in the [Color Dialog](https://ckeditor.com/cke4/addon/colordialog) window. Thanks to [mizafish](https://github.com/mizafish)! @@ -824,13 +854,13 @@ Other Changes: Fixed Issues: * [#12825](https://dev.ckeditor.com/ticket/12825): Fixed: Preventing the [Table Resize](https://ckeditor.com/cke4/addon/tableresize) plugin from operating on elements outside the editor. Thanks to [Paul Martin](https://github.com/Paul-Martin)! -* [#12157](https://dev.ckeditor.com/ticket/12157): Fixed: Lost text formatting on pressing *Tab* when the [`config.tabSpaces`](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR.config-cfg-tabSpaces) configuration option value was greater than zero. +* [#12157](https://dev.ckeditor.com/ticket/12157): Fixed: Lost text formatting on pressing *Tab* when the [`config.tabSpaces`](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_config.html#cfg-tabSpaces) configuration option value was greater than zero. * [#12777](https://dev.ckeditor.com/ticket/12777): Fixed: The `table-layout` CSS property should be reset by skins. Thanks to [vita10gy](https://github.com/vita10gy)! * [#12812](https://dev.ckeditor.com/ticket/12812): Fixed: An uncaught security exception is thrown when [Line Utilities](https://ckeditor.com/cke4/addon/lineutils) are used in an inline editor loaded in a cross-domain `iframe`. Thanks to [Vitaliy Zurian](https://github.com/thecatontheflat)! -* [#12735](https://dev.ckeditor.com/ticket/12735): Fixed: [`config.fillEmptyBlocks`](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR.config-cfg-fillEmptyBlocks) should only apply when outputting data. +* [#12735](https://dev.ckeditor.com/ticket/12735): Fixed: [`config.fillEmptyBlocks`](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_config.html#cfg-fillEmptyBlocks) should only apply when outputting data. * [#10032](https://dev.ckeditor.com/ticket/10032): Fixed: [Paste from Word](https://ckeditor.com/cke4/addon/pastefromword) filter is executed for every paste after using the button. * [#12597](https://dev.ckeditor.com/ticket/12597): [Blink/WebKit] Fixed: Multi-byte Japanese characters entry not working properly after *Shift+Enter*. -* [#12387](https://dev.ckeditor.com/ticket/12387): Fixed: An error is thrown if a skin does not have the [`chameleon`](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR.skin-method-chameleon) property defined and [`config.uiColor`](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR.config-cfg-uiColor) is defined. +* [#12387](https://dev.ckeditor.com/ticket/12387): Fixed: An error is thrown if a skin does not have the [`chameleon`](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_skin.html#method-chameleon) property defined and [`config.uiColor`](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_config.html#cfg-uiColor) is defined. * [#12747](https://dev.ckeditor.com/ticket/12747): [IE8-10] Fixed: Opening a drop-down for a specific selection when the editor is maximized results in incorrect drop-down panel position. * [#12850](https://dev.ckeditor.com/ticket/12850): [IEQM] Fixed: An error is thrown after focusing the editor. @@ -846,33 +876,33 @@ Fixed Issues: New Features: -* [#12501](https://dev.ckeditor.com/ticket/12501): Allowed dashes in element names in the [string format of allowed content rules](https://docs.ckeditor.com/ckeditor4/docs/#!/guide/dev_allowed_content_rules-section-string-format). -* [#12550](https://dev.ckeditor.com/ticket/12550): Added the `<main>` element to the [`CKEDITOR.dtd`](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR.dtd). +* [#12501](https://dev.ckeditor.com/ticket/12501): Allowed dashes in element names in the [string format of allowed content rules](https://ckeditor.com/docs/ckeditor4/latest/guide/dev_allowed_content_rules.html#string-format). +* [#12550](https://dev.ckeditor.com/ticket/12550): Added the `<main>` element to the [`CKEDITOR.dtd`](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR.dtd.html). Fixed Issues: * [#12506](https://dev.ckeditor.com/ticket/12506): [Safari] Fixed: Cannot paste into inline editor if the page has `user-select: none` style. Thanks to [shaohua](https://github.com/shaohua)! -* [#12683](https://dev.ckeditor.com/ticket/12683): Fixed: [Filter](https://docs.ckeditor.com/ckeditor4/docs/#!/guide/dev_acf) fails to remove custom tags. Thanks to [timselier](https://github.com/timselier)! +* [#12683](https://dev.ckeditor.com/ticket/12683): Fixed: [Filter](https://ckeditor.com/docs/ckeditor4/latest/guide/dev_acf.html) fails to remove custom tags. Thanks to [timselier](https://github.com/timselier)! * [#12489](https://dev.ckeditor.com/ticket/12489) and [#12491](https://dev.ckeditor.com/ticket/12491): Fixed: Various issues related to restoring the selection after performing operations on filler character. See the [fixed cases](https://dev.ckeditor.com/ticket/12491#comment:4). * [#12621](https://dev.ckeditor.com/ticket/12621): Fixed: Cannot remove inline styles (bold, italic, etc.) in empty lines. * [#12630](https://dev.ckeditor.com/ticket/12630): [Chrome] Fixed: Selection is placed outside the paragraph when the [New Page](https://ckeditor.com/cke4/addon/newpage) button is clicked. This patch significantly simplified the way how the initial selection (a selection after the content of the editable is overwritten) is being fixed. That might have fixed many related scenarios in all browsers. -* [#11647](https://dev.ckeditor.com/ticket/11647): Fixed: The [`editor.blur`](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR.editor-event-blur) event is not fired on first blur after initializing the inline editor on an already focused element. +* [#11647](https://dev.ckeditor.com/ticket/11647): Fixed: The [`editor.blur`](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_editor.html#event-blur) event is not fired on first blur after initializing the inline editor on an already focused element. * [#12601](https://dev.ckeditor.com/ticket/12601): Fixed: [Strikethrough](https://ckeditor.com/cke4/addon/basicstyles) button tooltip spelling. * [#12546](https://dev.ckeditor.com/ticket/12546): Fixed: The Preview tab in the [Document Properties](https://ckeditor.com/cke4/addon/docprops) dialog window is always disabled. -* [#12300](https://dev.ckeditor.com/ticket/12300): Fixed: The [`editor.change`](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR.editor-event-change) event fired on first navigation key press after typing. +* [#12300](https://dev.ckeditor.com/ticket/12300): Fixed: The [`editor.change`](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_editor.html#event-change) event fired on first navigation key press after typing. * [#12141](https://dev.ckeditor.com/ticket/12141): Fixed: List items are lost when indenting a list item with content wrapped with a block element. * [#12515](https://dev.ckeditor.com/ticket/12515): Fixed: Cursor is in the wrong position when undoing after adding an image and typing some text. * [#12484](https://dev.ckeditor.com/ticket/12484): [Blink/WebKit] Fixed: DOM is changed outside the editor area in a certain case. -* [#12688](https://dev.ckeditor.com/ticket/12688): Improved the tests of the [styles system](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR.style) and fixed two minor issues. +* [#12688](https://dev.ckeditor.com/ticket/12688): Improved the tests of the [styles system](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR.style.html) and fixed two minor issues. * [#12403](https://dev.ckeditor.com/ticket/12403): Fixed: Changing the [font](https://ckeditor.com/cke4/addon/font) style should not lead to nesting it in the previous style element. -* [#12609](https://dev.ckeditor.com/ticket/12609): Fixed: Incorrect `config.magicline_putEverywhere` name used for a [Magic Line](https://ckeditor.com/cke4/addon/magicline) all-encompassing [`config.magicline_everywhere`](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR.config-cfg-magicline_everywhere) configuration option. +* [#12609](https://dev.ckeditor.com/ticket/12609): Fixed: Incorrect `config.magicline_putEverywhere` name used for a [Magic Line](https://ckeditor.com/cke4/addon/magicline) all-encompassing [`config.magicline_everywhere`](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_config.html#cfg-magicline_everywhere) configuration option. ## CKEditor 4.4.5 New Features: -* [#12279](https://dev.ckeditor.com/ticket/12279): Added a possibility to pass a custom evaluator to [`node.getAscendant()`](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR.dom.node-method-getAscendant). +* [#12279](https://dev.ckeditor.com/ticket/12279): Added a possibility to pass a custom evaluator to [`node.getAscendant()`](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_dom_node.html#method-getAscendant). Fixed Issues: @@ -882,11 +912,11 @@ Fixed Issues: * [#9137](https://dev.ckeditor.com/ticket/9137): Fixed: The `<base>` tag is not created when `<head>` has an attribute. Thanks to [naoki.fujikawa](https://github.com/naoki-fujikawa)! * [#12377](https://dev.ckeditor.com/ticket/12377): Fixed: Errors thrown in the [Image](https://ckeditor.com/cke4/addon/image) plugin when removing preview from the dialog window definition. Thanks to [Axinet](https://github.com/Axinet)! * [#12162](https://dev.ckeditor.com/ticket/12162): Fixed: Auto paragraphing and *Enter* key in nested editables. -* [#12315](https://dev.ckeditor.com/ticket/12315): Fixed: Marked [`config.autoParagraph`](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR.config-cfg-autoParagraph) as deprecated. +* [#12315](https://dev.ckeditor.com/ticket/12315): Fixed: Marked [`config.autoParagraph`](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_config.html#cfg-autoParagraph) as deprecated. * [#12113](https://dev.ckeditor.com/ticket/12113): Fixed: A [code snippet](https://ckeditor.com/cke4/addon/codesnippet) should be presented in the [elements path](https://ckeditor.com/cke4/addon/elementspath) as "code snippet" (translatable). * [#12311](https://dev.ckeditor.com/ticket/12311): Fixed: [Remove Format](https://ckeditor.com/cke4/addon/removeformat) should also remove `<cite>` elements. -* [#12261](https://dev.ckeditor.com/ticket/12261): Fixed: Filter has to be destroyed and removed from [`CKEDITOR.filter.instances`](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR.filter-static-property-instances) on editor destroy. -* [#12398](https://dev.ckeditor.com/ticket/12398): Fixed: [Maximize](https://ckeditor.com/cke4/addon/maximize) does not work on an instance without a [title](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR.config-cfg-title). +* [#12261](https://dev.ckeditor.com/ticket/12261): Fixed: Filter has to be destroyed and removed from [`CKEDITOR.filter.instances`](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_filter.html#static-property-instances) on editor destroy. +* [#12398](https://dev.ckeditor.com/ticket/12398): Fixed: [Maximize](https://ckeditor.com/cke4/addon/maximize) does not work on an instance without a [title](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_config.html#cfg-title). * [#12097](https://dev.ckeditor.com/ticket/12097): Fixed: JAWS not reading the number of options correctly in the [Text Color and Background Color](https://ckeditor.com/cke4/addon/colorbutton) button menu. * [#12411](https://dev.ckeditor.com/ticket/12411): Fixed: [Page Break](https://ckeditor.com/cke4/addon/pagebreak) used directly in the editable breaks the editor. * [#12354](https://dev.ckeditor.com/ticket/12354): Fixed: Various issues in undo manager when holding keys. @@ -904,9 +934,9 @@ Fixed Issues: * [#12263](https://dev.ckeditor.com/ticket/12263): Fixed: [Paste from Word](https://ckeditor.com/cke4/addon/pastefromword) filter does not properly normalize semicolons style text. Thanks to [Alin Purcaru](https://github.com/mesmerizero)! * [#12243](https://dev.ckeditor.com/ticket/12243): Fixed: Text formatting lost when pasting from Word. Thanks to [Alin Purcaru](https://github.com/mesmerizero)! * [#111739](https://dev.ckeditor.com/ticket/11739): Fixed: `keypress` listeners should not be used in the undo manager. A complete rewrite of keyboard handling in the undo manager was made. Numerous smaller issues were fixed, among others: - * [#10926](https://dev.ckeditor.com/ticket/10926): [Chrome@Android] Fixed: Typing does not record snapshots and does not fire the [`editor.change`](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR.editor-event-change) event. - * [#11611](https://dev.ckeditor.com/ticket/11611): [Firefox] Fixed: The [`editor.change`](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR.editor-event-change) event is fired when pressing Arrow keys. - * [#12219](https://dev.ckeditor.com/ticket/12219): [Safari] Fixed: Some modifications of the [`UndoManager.locked`](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR.plugins.undo.UndoManager-property-locked) property violate strict mode in the [Undo](https://ckeditor.com/cke4/addon/undo) plugin. + * [#10926](https://dev.ckeditor.com/ticket/10926): [Chrome@Android] Fixed: Typing does not record snapshots and does not fire the [`editor.change`](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_editor.html#event-change) event. + * [#11611](https://dev.ckeditor.com/ticket/11611): [Firefox] Fixed: The [`editor.change`](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_editor.html#event-change) event is fired when pressing Arrow keys. + * [#12219](https://dev.ckeditor.com/ticket/12219): [Safari] Fixed: Some modifications of the [`UndoManager.locked`](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_plugins_undo_UndoManager.html#property-locked) property violate strict mode in the [Undo](https://ckeditor.com/cke4/addon/undo) plugin. * [#10916](https://dev.ckeditor.com/ticket/10916): Fixed: [Magic Line](https://ckeditor.com/cke4/addon/magicline) icon in Right-To-Left environments. * [#11970](https://dev.ckeditor.com/ticket/11970): [IE] Fixed: CKEditor `paste` event is not fired when pasting with *Shift+Ins*. * [#12111](https://dev.ckeditor.com/ticket/12111): Fixed: Linked image attributes are not read when opening the image dialog window by doubleclicking. @@ -918,7 +948,7 @@ Fixed Issues: * [#12215](https://dev.ckeditor.com/ticket/12215): Fixed: Basepath resolution does not recognize semicolon as a query separator. * [#12135](https://dev.ckeditor.com/ticket/12135): Fixed: [Remove Format](https://ckeditor.com/cke4/addon/removeformat) does not work on widgets. * [#12298](https://dev.ckeditor.com/ticket/12298): [IE11] Fixed: Clicking below `<body>` in Compatibility Mode will no longer reset selection to the first line. -* [#12204](https://dev.ckeditor.com/ticket/12204): Fixed: Editor's voice label is not affected by [`config.title`](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR.config-cfg-title). +* [#12204](https://dev.ckeditor.com/ticket/12204): Fixed: Editor's voice label is not affected by [`config.title`](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_config.html#cfg-title). * [#11915](https://dev.ckeditor.com/ticket/11915): Fixed: With [SCAYT](https://ckeditor.com/cke4/addon/scayt) enabled, cursor moves to the beginning of the first highlighted, misspelled word after typing or pasting into the editor. * [SCAYT](https://github.com/WebSpellChecker/ckeditor-plugin-scayt/issues/69): Fixed: Error thrown in the console after enabling [SCAYT](https://ckeditor.com/cke4/addon/scayt) and trying to add a new image. @@ -945,30 +975,30 @@ Fixed Issues: * [#11897](https://dev.ckeditor.com/ticket/11897): Fixed: *Enter* key used in an empty list item creates a new line instead of breaking the list. Thanks to [noam-si](https://github.com/noam-si)! * [#12140](https://dev.ckeditor.com/ticket/12140): Fixed: Double-clicking linked widgets opens two dialog windows. * [#12132](https://dev.ckeditor.com/ticket/12132): Fixed: Image is inserted with `width` and `height` styles even when they are not allowed. -* [#9317](https://dev.ckeditor.com/ticket/9317): [IE] Fixed: [`config.disableObjectResizing`](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR.config-cfg-disableObjectResizing) does not work on IE. **Note**: We were not able to fix this issue on IE11+ because necessary events stopped working. See a [last resort workaround](https://dev.ckeditor.com/ticket/9317#comment:16) and make sure to [support our complaint to Microsoft](https://connect.microsoft.com/IE/feedback/details/742593/please-respect-execcommand-enableobjectresizing-in-contenteditable-elements). +* [#9317](https://dev.ckeditor.com/ticket/9317): [IE] Fixed: [`config.disableObjectResizing`](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_config.html#cfg-disableObjectResizing) does not work on IE. **Note**: We were not able to fix this issue on IE11+ because necessary events stopped working. See a [last resort workaround](https://dev.ckeditor.com/ticket/9317#comment:16) and make sure to [support our complaint to Microsoft](https://connect.microsoft.com/IE/feedback/details/742593/please-respect-execcommand-enableobjectresizing-in-contenteditable-elements). * [#9638](https://dev.ckeditor.com/ticket/9638): Fixed: There should be no information about accessibility help available under the *Alt+0* keyboard shortcut if the [Accessibility Help](https://ckeditor.com/cke4/addon/a11yhelp) plugin is not available. * [#8117](https://dev.ckeditor.com/ticket/8117) and [#9186](https://dev.ckeditor.com/ticket/9186): Fixed: In HTML5 `<meta>` tags should be allowed everywhere, including inside the `<body>` element. -* [#10422](https://dev.ckeditor.com/ticket/10422): Fixed: [`config.fillEmptyBlocks`](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR.config-cfg-fillEmptyBlocks) not working properly if a function is specified. +* [#10422](https://dev.ckeditor.com/ticket/10422): Fixed: [`config.fillEmptyBlocks`](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_config.html#cfg-fillEmptyBlocks) not working properly if a function is specified. ## CKEditor 4.4.2 Important Notes: -* The CKEditor testing environment is now publicly available. Read more about how to set up the environment and execute tests in the [CKEditor Testing Environment](https://docs.ckeditor.com/ckeditor4/docs/#!/guide/dev_tests) guide. +* The CKEditor testing environment is now publicly available. Read more about how to set up the environment and execute tests in the [CKEditor Testing Environment](https://ckeditor.com/docs/ckeditor4/latest/guide/dev_tests.html) guide. Please note that the [`tests/`](https://github.com/ckeditor/ckeditor-dev/tree/master/tests) directory which contains editor tests is not available in release packages. It can only be found in the development version of CKEditor on [GitHub](https://github.com/ckeditor/ckeditor-dev/). New Features: -* [#11909](https://dev.ckeditor.com/ticket/11909): Introduced a parameter to prevent the [`editor.setData()`](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR.editor-method-setData) method from recording undo snapshots. +* [#11909](https://dev.ckeditor.com/ticket/11909): Introduced a parameter to prevent the [`editor.setData()`](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_editor.html#method-setData) method from recording undo snapshots. Fixed Issues: * [#11757](https://dev.ckeditor.com/ticket/11757): Fixed: Imperfections in the [Moono](https://ckeditor.com/cke4/addon/moono) skin. Thanks to [danyaPostfactum](https://github.com/danyaPostfactum)! * [#10091](https://dev.ckeditor.com/ticket/10091): Blockquote should be treated like an object by the styles system. Thanks to [dan-james-deeson](https://github.com/dan-james-deeson)! -* [#11478](https://dev.ckeditor.com/ticket/11478): Fixed: Issue with passing jQuery objects to [adapter](https://docs.ckeditor.com/ckeditor4/docs/#!/guide/dev_jquery) configuration. +* [#11478](https://dev.ckeditor.com/ticket/11478): Fixed: Issue with passing jQuery objects to [adapter](https://ckeditor.com/docs/ckeditor4/latest/guide/dev_jquery.html) configuration. * [#10867](https://dev.ckeditor.com/ticket/10867): Fixed: Issue with setting encoded URI as image link. -* [#11983](https://dev.ckeditor.com/ticket/11983): Fixed: Clicking a nested widget does not focus it. Additionally, performance of the [`widget.repository.getByElement()`](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR.plugins.widget.repository-method-getByElement) method was improved. -* [#12000](https://dev.ckeditor.com/ticket/12000): Fixed: Nested widgets should be initialized on [`editor.setData()`](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR.editor-method-setData) and [`nestedEditable.setData()`](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR.plugins.widget.nestedEditable-method-setData). +* [#11983](https://dev.ckeditor.com/ticket/11983): Fixed: Clicking a nested widget does not focus it. Additionally, performance of the [`widget.repository.getByElement()`](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_plugins_widget_repository.html#method-getByElement) method was improved. +* [#12000](https://dev.ckeditor.com/ticket/12000): Fixed: Nested widgets should be initialized on [`editor.setData()`](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_editor.html#method-setData) and [`nestedEditable.setData()`](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_plugins_widget_nestedEditable.html#method-setData). * [#12022](https://dev.ckeditor.com/ticket/12022): Fixed: Outer widget's drag handler is not created at all if it has any nested widgets inside. * [#11960](https://dev.ckeditor.com/ticket/11960): [Blink/WebKit] Fixed: The caret should be scrolled into view on *Backspace* and *Delete* (covers only the merging blocks case). * [#11306](https://dev.ckeditor.com/ticket/11306): [OSX][Blink/WebKit] Fixed: No widget entries in the context menu on widget right-click. @@ -978,10 +1008,10 @@ Fixed Issues: * [#11387](https://dev.ckeditor.com/ticket/11387): Fixed: `role="radiogroup"` should be applied only to radio inputs' container. * [#7975](https://dev.ckeditor.com/ticket/7975): [IE8] Fixed: Errors when trying to select an empty table cell. * [#11947](https://dev.ckeditor.com/ticket/11947): [Firefox+IE11] Fixed: *Shift+Enter* in lists produces two line breaks. -* [#11972](https://dev.ckeditor.com/ticket/11972): Fixed: Feature detection in the [`element.setText()`](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR.dom.element-method-setText) method should not trigger the layout engine. +* [#11972](https://dev.ckeditor.com/ticket/11972): Fixed: Feature detection in the [`element.setText()`](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_dom_element.html#method-setText) method should not trigger the layout engine. * [#7634](https://dev.ckeditor.com/ticket/7634): Fixed: The [Flash Dialog](https://ckeditor.com/cke4/addon/flash) plugin omits the `allowFullScreen` parameter in the editor data if set to `true`. -* [#11910](https://dev.ckeditor.com/ticket/11910): Fixed: [Enhanced Image](https://ckeditor.com/cke4/addon/image2) does not take [`config.baseHref`](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR.config-cfg-baseHref) into account when updating image dimensions. -* [#11753](https://dev.ckeditor.com/ticket/11753): Fixed: Wrong [`checkDirty()`](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR.editor-method-checkDirty) method value after focusing or blurring a widget. +* [#11910](https://dev.ckeditor.com/ticket/11910): Fixed: [Enhanced Image](https://ckeditor.com/cke4/addon/image2) does not take [`config.baseHref`](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_config.html#cfg-baseHref) into account when updating image dimensions. +* [#11753](https://dev.ckeditor.com/ticket/11753): Fixed: Wrong [`checkDirty()`](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_editor.html#method-checkDirty) method value after focusing or blurring a widget. * [#11830](https://dev.ckeditor.com/ticket/11830): Fixed: Impossible to pass some arguments to [CKBuilder](https://github.com/ckeditor/ckbuilder) when using the `/dev/builder/build.sh` script. * [#11945](https://dev.ckeditor.com/ticket/11945): Fixed: [Form Elements](https://ckeditor.com/cke4/addon/forms) plugin should not change a core method. * [#11384](https://dev.ckeditor.com/ticket/11384): [IE9+] Fixed: `IndexSizeError` thrown when pasting into a non-empty selection anchored in one text node. @@ -990,28 +1020,28 @@ Fixed Issues: New Features: -* [#9661](https://dev.ckeditor.com/ticket/9661): Added the option to [configure](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR.config-cfg-linkJavaScriptLinksAllowed) anchor tags with JavaScript code in the `href` attribute. +* [#9661](https://dev.ckeditor.com/ticket/9661): Added the option to [configure](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_config.html#cfg-linkJavaScriptLinksAllowed) anchor tags with JavaScript code in the `href` attribute. Fixed Issues: * [#11861](https://dev.ckeditor.com/ticket/11861): [WebKit/Blink] Fixed: Span elements created while joining adjacent elements. **Note:** This patch only covers cases when *Backspace* or *Delete* is pressed on a collapsed (empty) selection. The remaining case, with a non-empty selection, will be fixed in the next release. * [#10714](https://dev.ckeditor.com/ticket/10714): [iOS] Fixed: Selection and drop-downs are broken if a touch event listener is used due to a [WebKit bug](https://bugs.webkit.org/show_bug.cgi?id=128924). Thanks to [Arty Gus](https://github.com/artygus)! -* [#11911](https://dev.ckeditor.com/ticket/11911): Fixed setting the `dir` attribute for a preloaded language in [CKEDITOR.lang](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR.lang). Thanks to [Akash Mohapatra](https://github.com/akashmohapatra)! +* [#11911](https://dev.ckeditor.com/ticket/11911): Fixed setting the `dir` attribute for a preloaded language in [CKEDITOR.lang](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR.lang.html). Thanks to [Akash Mohapatra](https://github.com/akashmohapatra)! * [#11926](https://dev.ckeditor.com/ticket/11926): Fixed: [Code Snippet](https://ckeditor.com/cke4/addon/codesnippet) does not decode HTML entities when loading code from the `<code>` element. -* [#11223](https://dev.ckeditor.com/ticket/11223): Fixed: Issue when [Protected Source](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR.config-cfg-protectedSource) was not working in the `<title>` element. +* [#11223](https://dev.ckeditor.com/ticket/11223): Fixed: Issue when [Protected Source](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_config.html#cfg-protectedSource) was not working in the `<title>` element. * [#11859](https://dev.ckeditor.com/ticket/11859): Fixed: Removed the [Source Dialog](https://ckeditor.com/cke4/addon/sourcedialog) plugin dependency from the [Code Snippet](https://ckeditor.com/cke4/addon/codesnippet) sample. * [#11754](https://dev.ckeditor.com/ticket/11754): [Chrome] Fixed: Infinite loop when content includes not closed attributes. -* [#11848](https://dev.ckeditor.com/ticket/11848): [IE] Fixed: [`editor.insertElement()`](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR.editor-method-insertElement) throwing an exception when there was no selection in the editor. +* [#11848](https://dev.ckeditor.com/ticket/11848): [IE] Fixed: [`editor.insertElement()`](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_editor.html#method-insertElement) throwing an exception when there was no selection in the editor. * [#11801](https://dev.ckeditor.com/ticket/11801): Fixed: Editor anchors unavailable when linking the [Enhanced Image](https://ckeditor.com/cke4/addon/image2) widget. * [#11626](https://dev.ckeditor.com/ticket/11626): Fixed: [Table Resize](https://ckeditor.com/cke4/addon/tableresize) sets invalid column width. -* [#11872](https://dev.ckeditor.com/ticket/11872): Made [`element.addClass()`](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR.dom.element-method-addClass) chainable symmetrically to [`element.removeClass()`](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR.dom.element-method-removeClass). +* [#11872](https://dev.ckeditor.com/ticket/11872): Made [`element.addClass()`](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_dom_element.html#method-addClass) chainable symmetrically to [`element.removeClass()`](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_dom_element.html#method-removeClass). * [#11813](https://dev.ckeditor.com/ticket/11813): Fixed: Link lost while pasting a captioned image and restoring an undo snapshot ([Enhanced Image](https://ckeditor.com/cke4/addon/image2)). * [#11814](https://dev.ckeditor.com/ticket/11814): Fixed: _Link_ and _Unlink_ entries persistently displayed in the [Enhanced Image](https://ckeditor.com/cke4/addon/image2) context menu. * [#11839](https://dev.ckeditor.com/ticket/11839): [IE9] Fixed: The caret jumps out of the editable area when resizing the editor in the source mode. * [#11822](https://dev.ckeditor.com/ticket/11822): [WebKit] Fixed: Editing anchors by double-click is broken in some cases. * [#11823](https://dev.ckeditor.com/ticket/11823): [IE8] Fixed: [Table Resize](https://ckeditor.com/cke4/addon/tableresize) throws an error over scrollbar. * [#11788](https://dev.ckeditor.com/ticket/11788): Fixed: It is not possible to change the language back to _Not set_ in the [Code Snippet](https://ckeditor.com/cke4/addon/codesnippet) dialog window. -* [#11788](https://dev.ckeditor.com/ticket/11788): Fixed: [Filter](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR.htmlParser.filter) rules are not applied inside elements with the `contenteditable` attribute set to `true`. +* [#11788](https://dev.ckeditor.com/ticket/11788): Fixed: [Filter](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR.htmlParser.filter.html) rules are not applied inside elements with the `contenteditable` attribute set to `true`. * [#11798](https://dev.ckeditor.com/ticket/11798): Fixed: Inserting a non-editable element inside a table cell breaks the table. * [#11793](https://dev.ckeditor.com/ticket/11793): Fixed: Drop-down is not "on" when clicking it while the editor is blurred. * [#11850](https://dev.ckeditor.com/ticket/11850): Fixed: Fake objects with the `contenteditable` attribute set to `false` are not downcasted properly. @@ -1029,46 +1059,46 @@ Other Changes: **Important Notes:** -* Marked the [`editor.beforePaste`](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR.editor-event-beforePaste) event as deprecated. -* The default class of captioned images has changed to `image` (was: `caption`). Please note that once edited in CKEditor 4.4+, all existing images of the `caption` class (`<figure class="caption">`) will be [filtered out](https://docs.ckeditor.com/ckeditor4/docs/#!/guide/dev_advanced_content_filter) unless the [`config.image2_captionedClass`](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR.config-cfg-image2_captionedClass) option is set to `caption`. For backward compatibility (i.e. when upgrading), it is highly recommended to use this setting, which also helps prevent CSS conflicts, etc. This does not apply to new CKEditor integrations. -* Widgets without defined buttons are no longer registered automatically to the [Advanced Content Filter](https://docs.ckeditor.com/ckeditor4/docs/#!/guide/dev_advanced_content_filter). Before CKEditor 4.4 widgets were registered to the ACF which was an incorrect behavior ([#11567](https://dev.ckeditor.com/ticket/11567)). This change should not have any impact on standard scenarios, but if your button does not execute the widget command, you need to set [`allowedContent`](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR.feature-property-allowedContent) and [`requiredContent`](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR.feature-property-requiredContent) properties for it manually, because the editor will not be able to find them. +* Marked the [`editor.beforePaste`](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_editor.html#event-beforePaste) event as deprecated. +* The default class of captioned images has changed to `image` (was: `caption`). Please note that once edited in CKEditor 4.4+, all existing images of the `caption` class (`<figure class="caption">`) will be [filtered out](https://ckeditor.com/docs/ckeditor4/latest/guide/dev_advanced_content_filter.html) unless the [`config.image2_captionedClass`](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_config.html#cfg-image2_captionedClass) option is set to `caption`. For backward compatibility (i.e. when upgrading), it is highly recommended to use this setting, which also helps prevent CSS conflicts, etc. This does not apply to new CKEditor integrations. +* Widgets without defined buttons are no longer registered automatically to the [Advanced Content Filter](https://ckeditor.com/docs/ckeditor4/latest/guide/dev_advanced_content_filter.html). Before CKEditor 4.4 widgets were registered to the ACF which was an incorrect behavior ([#11567](https://dev.ckeditor.com/ticket/11567)). This change should not have any impact on standard scenarios, but if your button does not execute the widget command, you need to set [`allowedContent`](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_feature.html#property-allowedContent) and [`requiredContent`](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_feature.html#property-requiredContent) properties for it manually, because the editor will not be able to find them. * The [Show Borders](https://ckeditor.com/cke4/addon/showborders) plugin was added to the Standard installation package in order to ensure that unstyled tables are still visible for the user ([#11665](https://dev.ckeditor.com/ticket/11665)). -* Since CKEditor 4.4 the editor instance should be passed to [`CKEDITOR.style`](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR.style) methods to ensure full compatibility with other features (e.g. applying styles to widgets requires that). We ensured backward compatibility though, so the [`CKEDITOR.style`](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR.style) will work even when the editor instance is not provided. +* Since CKEditor 4.4 the editor instance should be passed to [`CKEDITOR.style`](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR.style.html) methods to ensure full compatibility with other features (e.g. applying styles to widgets requires that). We ensured backward compatibility though, so the [`CKEDITOR.style`](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR.style.html) will work even when the editor instance is not provided. New Features: -* [#11297](https://dev.ckeditor.com/ticket/11297): Styles can now be applied to widgets. The definition of a style which can be applied to a specific widget must contain two additional properties — `type` and `widget`. Read more in the [Widget Styles](https://docs.ckeditor.com/ckeditor4/docs/#!/guide/dev_styles-section-widget-styles) section of the "Syles Drop-down" guide. Note that by default, widgets support only classes and no other attributes or styles. Related changes and features: - * Introduced the [`CKEDITOR.style.addCustomHandler()`](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR.style-static-method-addCustomHandler) method for registering custom style handlers. - * The [`CKEDITOR.style.apply()`](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR.style-method-apply) and [`CKEDITOR.style.remove()`](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR.style-method-remove) methods are now called with an editor instance instead of the document so they can be reused by the [`CKEDITOR.editor.applyStyle()`](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR.editor-method-applyStyle) and [`CKEDITOR.editor.removeStyle()`](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR.editor-method-removeStyle) methods. Backward compatibility was preserved, but from CKEditor 4.4 it is highly recommended to pass an editor instead of a document to these methods. - * Many new methods and properties were introduced in the [Widget API](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR.plugins.widget) to make the handling of styles by widgets fully customizable. See: [`widget.definition.styleableElements`](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR.plugins.widget.definition-property-styleableElements), [`widget.definition.styleToAllowedContentRule`](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR.plugins.widget.definition-property-styleToAllowedContentRules), [`widget.addClass()`](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR.plugins.widget-method-addClass), [`widget.removeClass()`](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR.plugins.widget-method-removeClass), [`widget.getClasses()`](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR.plugins.widget-method-getClasses), [`widget.hasClass()`](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR.plugins.widget-method-hasClass), [`widget.applyStyle()`](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR.plugins.widget-method-applyStyle), [`widget.removeStyle()`](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR.plugins.widget-method-removeStyle), [`widget.checkStyleActive()`](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR.plugins.widget-method-checkStyleActive). - * Integration with the [Allowed Content Filter](https://docs.ckeditor.com/ckeditor4/docs/#!/guide/dev_advanced_content_filter) required an introduction of the [`CKEDITOR.style.toAllowedContent()`](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR.style-method-toAllowedContentRules) method which can be implemented by the custom style handler and if exists, it is used by the [`CKEDITOR.filter`](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR.filter) to translate a style to [allowed content rules](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR.filter.allowedContentRules). +* [#11297](https://dev.ckeditor.com/ticket/11297): Styles can now be applied to widgets. The definition of a style which can be applied to a specific widget must contain two additional properties — `type` and `widget`. Read more in the [Widget Styles](https://ckeditor.com/docs/ckeditor4/latest/guide/dev_styles.html#widget-styles) section of the "Syles Drop-down" guide. Note that by default, widgets support only classes and no other attributes or styles. Related changes and features: + * Introduced the [`CKEDITOR.style.addCustomHandler()`](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_style.html#static-method-addCustomHandler) method for registering custom style handlers. + * The [`CKEDITOR.style.apply()`](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_style.html#method-apply) and [`CKEDITOR.style.remove()`](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_style.html#method-remove) methods are now called with an editor instance instead of the document so they can be reused by the [`CKEDITOR.editor.applyStyle()`](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_editor.html#method-applyStyle) and [`CKEDITOR.editor.removeStyle()`](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_editor.html#method-removeStyle) methods. Backward compatibility was preserved, but from CKEditor 4.4 it is highly recommended to pass an editor instead of a document to these methods. + * Many new methods and properties were introduced in the [Widget API](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR.plugins.widget.html) to make the handling of styles by widgets fully customizable. See: [`widget.definition.styleableElements`](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_plugins_widget_definition.html#property-styleableElements), [`widget.definition.styleToAllowedContentRule`](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_plugins_widget_definition.html#property-styleToAllowedContentRules), [`widget.addClass()`](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_plugins_widget.html#method-addClass), [`widget.removeClass()`](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_plugins_widget.html#method-removeClass), [`widget.getClasses()`](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_plugins_widget.html#method-getClasses), [`widget.hasClass()`](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_plugins_widget.html#method-hasClass), [`widget.applyStyle()`](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_plugins_widget.html#method-applyStyle), [`widget.removeStyle()`](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_plugins_widget.html#method-removeStyle), [`widget.checkStyleActive()`](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_plugins_widget.html#method-checkStyleActive). + * Integration with the [Allowed Content Filter](https://ckeditor.com/docs/ckeditor4/latest/guide/dev_advanced_content_filter.html) required an introduction of the [`CKEDITOR.style.toAllowedContent()`](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_style.html#method-toAllowedContentRules) method which can be implemented by the custom style handler and if exists, it is used by the [`CKEDITOR.filter`](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR.filter.html) to translate a style to [allowed content rules](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR.filter.allowedContentRules.html). * [#11300](https://dev.ckeditor.com/ticket/11300): Various changes in the [Enhanced Image](https://ckeditor.com/cke4/addon/image2) plugin: - * Introduced the [`config.image2_captionedClass`](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR.config-cfg-image2_captionedClass) option to configure the class of captioned images. - * Introduced the [`config.image2_alignClasses`](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR.config-cfg-image2_alignClasses) option to configure the way images are aligned with CSS classes. + * Introduced the [`config.image2_captionedClass`](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_config.html#cfg-image2_captionedClass) option to configure the class of captioned images. + * Introduced the [`config.image2_alignClasses`](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_config.html#cfg-image2_alignClasses) option to configure the way images are aligned with CSS classes. If this setting is defined, the editor produces classes instead of inline styles for aligned images. * Default image caption can be translated (customized) with the `editor.lang.image2.captionPlaceholder` string. * [#11341](https://dev.ckeditor.com/ticket/11341): [Enhanced Image](https://ckeditor.com/cke4/addon/image2) plugin: It is now possible to add a link to any image type. -* [#10202](https://dev.ckeditor.com/ticket/10202): Introduced wildcard support in the [Allowed Content Rules](https://docs.ckeditor.com/ckeditor4/docs/#!/guide/dev_allowed_content_rules) format. -* [#10276](https://dev.ckeditor.com/ticket/10276): Introduced blacklisting in the [Allowed Content Filter](https://docs.ckeditor.com/ckeditor4/docs/#!/guide/dev_advanced_content_filter). +* [#10202](https://dev.ckeditor.com/ticket/10202): Introduced wildcard support in the [Allowed Content Rules](https://ckeditor.com/docs/ckeditor4/latest/guide/dev_allowed_content_rules.html) format. +* [#10276](https://dev.ckeditor.com/ticket/10276): Introduced blacklisting in the [Allowed Content Filter](https://ckeditor.com/docs/ckeditor4/latest/guide/dev_advanced_content_filter.html). * [#10480](https://dev.ckeditor.com/ticket/10480): Introduced code snippets with code highlighting. There are two versions available so far — the default [Code Snippet](https://ckeditor.com/cke4/addon/codesnippet) which uses the [highlight.js](http://highlightjs.org) library and the [Code Snippet GeSHi](https://ckeditor.com/cke4/addon/codesnippetgeshi) which uses the [GeSHi](http://qbnz.com/highlighter/) library. -* [#11737](https://dev.ckeditor.com/ticket/11737): Introduced an option to prevent [filtering](https://docs.ckeditor.com/ckeditor4/docs/#!/guide/dev_advanced_content_filter) of an element that matches custom criteria (see [`filter.addElementCallback()`](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR.filter-method-addElementCallback)). -* [#11532](https://dev.ckeditor.com/ticket/11532): Introduced the [`editor.addContentsCss()`](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR.editor-method-addContentsCss) method that can be used for [adding custom CSS files](https://docs.ckeditor.com/ckeditor4/docs/#!/guide/plugin_sdk_styles). -* [#11536](https://dev.ckeditor.com/ticket/11536): Added the [`CKEDITOR.tools.htmlDecode()`](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR.tools-method-htmlDecode) method for decoding HTML entities. -* [#11225](https://dev.ckeditor.com/ticket/11225): Introduced the [`CKEDITOR.tools.transparentImageData`](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR.tools-property-transparentImageData) property which contains transparent image data to be used in CSS or as image source. +* [#11737](https://dev.ckeditor.com/ticket/11737): Introduced an option to prevent [filtering](https://ckeditor.com/docs/ckeditor4/latest/guide/dev_advanced_content_filter.html) of an element that matches custom criteria (see [`filter.addElementCallback()`](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_filter.html#method-addElementCallback)). +* [#11532](https://dev.ckeditor.com/ticket/11532): Introduced the [`editor.addContentsCss()`](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_editor.html#method-addContentsCss) method that can be used for [adding custom CSS files](https://ckeditor.com/docs/ckeditor4/latest/guide/plugin_sdk_styles.html). +* [#11536](https://dev.ckeditor.com/ticket/11536): Added the [`CKEDITOR.tools.htmlDecode()`](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_tools.html#method-htmlDecode) method for decoding HTML entities. +* [#11225](https://dev.ckeditor.com/ticket/11225): Introduced the [`CKEDITOR.tools.transparentImageData`](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_tools.html#property-transparentImageData) property which contains transparent image data to be used in CSS or as image source. Other Changes: * [#11377](https://dev.ckeditor.com/ticket/11377): Unified internal representation of empty anchors using the [fake objects](https://ckeditor.com/cke4/addon/fakeobjects). * [#11422](https://dev.ckeditor.com/ticket/11422): Removed Firefox 3.x, Internet Explorer 6 and Opera 12.x leftovers in code. * [#5217](https://dev.ckeditor.com/ticket/5217): Setting data (including switching between modes) creates a new undo snapshot. Besides that: - * Introduced the [`editable.status`](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR.editable-property-status) property. - * Introduced a new `forceUpdate` option for the [`editor.lockSnapshot`](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR.editor-event-lockSnapshot) event. + * Introduced the [`editable.status`](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_editable.html#property-status) property. + * Introduced a new `forceUpdate` option for the [`editor.lockSnapshot`](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_editor.html#event-lockSnapshot) event. * Fixed: Selection not being unlocked in inline editor after setting data ([#11500](https://dev.ckeditor.com/ticket/11500)). * The [WebSpellChecker](https://ckeditor.com/cke4/addon/wsc) plugin was updated to the latest version. Fixed Issues: -* [#10190](https://dev.ckeditor.com/ticket/10190): Fixed: Removing block style with [`editor.removeStyle()`](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR.editor-method-removeStyle) should result in a paragraph and not a div. +* [#10190](https://dev.ckeditor.com/ticket/10190): Fixed: Removing block style with [`editor.removeStyle()`](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_editor.html#method-removeStyle) should result in a paragraph and not a div. * [#11727](https://dev.ckeditor.com/ticket/11727): Fixed: The editor tries to select a non-editable image which was clicked. ## CKEditor 4.3.5 @@ -1088,7 +1118,7 @@ Fixed Issues: * [#11597](https://dev.ckeditor.com/ticket/11597): [IE11] Fixed: Error thrown when trying to open the [preview](https://ckeditor.com/cke4/addon/preview) using the keyboard. * [#11544](https://dev.ckeditor.com/ticket/11544): [Placeholders](https://ckeditor.com/cke4/addon/placeholder) will no longer be upcasted in parents not accepting `<span>` elements. -* [#8663](https://dev.ckeditor.com/ticket/8663): Fixed [`element.renameNode()`](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR.dom.element-method-renameNode) not clearing the [`element.getName()`](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR.dom.element-method-getName) cache. +* [#8663](https://dev.ckeditor.com/ticket/8663): Fixed [`element.renameNode()`](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_dom_element.html#method-renameNode) not clearing the [`element.getName()`](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_dom_element.html#method-getName) cache. * [#11574](https://dev.ckeditor.com/ticket/11574): Fixed: *Backspace* destroying the DOM structure if an inline editable is placed in a list item. * [#11603](https://dev.ckeditor.com/ticket/11603): Fixed: [Table Resize](https://ckeditor.com/cke4/addon/tableresize) attaches to tables outside the editable. * [#9205](https://dev.ckeditor.com/ticket/9205), [#7805](https://dev.ckeditor.com/ticket/7805), [#8216](https://dev.ckeditor.com/ticket/8216): Fixed: `{cke_protected_1}` appearing in data in various cases where HTML comments are placed next to `"` or `'`. @@ -1101,26 +1131,26 @@ Fixed Issues: Fixed Issues: -* [#11500](https://dev.ckeditor.com/ticket/11500): [WebKit/Blink] Fixed: Selection lost when setting data in another inline editor. Additionally, [`selection.removeAllRanges()`](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR.dom.selection-method-removeAllRanges) is now scoped to selection's [root](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR.dom.selection-property-root). +* [#11500](https://dev.ckeditor.com/ticket/11500): [WebKit/Blink] Fixed: Selection lost when setting data in another inline editor. Additionally, [`selection.removeAllRanges()`](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_dom_selection.html#method-removeAllRanges) is now scoped to selection's [root](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_dom_selection.html#property-root). * [#11104](https://dev.ckeditor.com/ticket/11104): [IE] Fixed: Various issues with scrolling and selection when focusing widgets. -* [#11487](https://dev.ckeditor.com/ticket/11487): Moving mouse over the [Enhanced Image](https://ckeditor.com/cke4/addon/image2) widget will no longer change the value returned by the [`editor.checkDirty()`](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR.editor-method-checkDirty) method. +* [#11487](https://dev.ckeditor.com/ticket/11487): Moving mouse over the [Enhanced Image](https://ckeditor.com/cke4/addon/image2) widget will no longer change the value returned by the [`editor.checkDirty()`](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_editor.html#method-checkDirty) method. * [#8673](https://dev.ckeditor.com/ticket/8673): [WebKit] Fixed: Cannot select and remove the [Page Break](https://ckeditor.com/cke4/addon/pagebreak). -* [#11413](https://dev.ckeditor.com/ticket/11413): Fixed: Incorrect [`editor.execCommand()`](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR.editor-method-execCommand) behavior. +* [#11413](https://dev.ckeditor.com/ticket/11413): Fixed: Incorrect [`editor.execCommand()`](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_editor.html#method-execCommand) behavior. * [#11438](https://dev.ckeditor.com/ticket/11438): Splitting table cells vertically is no longer changing table structure. * [#8899](https://dev.ckeditor.com/ticket/8899): Fixed: Links in the [About CKEditor](https://ckeditor.com/cke4/addon/about) dialog window now open in a new browser window or tab. * [#11490](https://dev.ckeditor.com/ticket/11490): Fixed: [Menu button](https://ckeditor.com/cke4/addon/menubutton) panel not showing in the source mode. -* [#11417](https://dev.ckeditor.com/ticket/11417): The [`widget.doubleclick`](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR.plugins.widget-event-doubleclick) event is not canceled anymore after editing was triggered. +* [#11417](https://dev.ckeditor.com/ticket/11417): The [`widget.doubleclick`](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_plugins_widget.html#event-doubleclick) event is not canceled anymore after editing was triggered. * [#11253](https://dev.ckeditor.com/ticket/11253): [IE] Fixed: Clipped upload button in the [Enhanced Image](https://ckeditor.com/cke4/addon/image2) dialog window. * [#11359](https://dev.ckeditor.com/ticket/11359): Standardized the way anchors are discovered by the [Link](https://ckeditor.com/cke4/addon/link) plugin. * [#11058](https://dev.ckeditor.com/ticket/11058): [IE8] Fixed: Error when deleting a table row. -* [#11508](https://dev.ckeditor.com/ticket/11508): Fixed: [`htmlDataProcessor`](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR.htmlDataProcessor) discovering protected attributes within other attributes' values. +* [#11508](https://dev.ckeditor.com/ticket/11508): Fixed: [`htmlDataProcessor`](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR.htmlDataProcessor.html) discovering protected attributes within other attributes' values. * [#11533](https://dev.ckeditor.com/ticket/11533): Widgets: Avoid recurring upcasts if the DOM structure was modified during an upcast. -* [#11400](https://dev.ckeditor.com/ticket/11400): Fixed: The [`domObject.removeAllListeners()`](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR.dom.domObject-method-removeAllListeners) method does not remove custom listeners completely. -* [#11493](https://dev.ckeditor.com/ticket/11493): Fixed: The [`selection.getRanges()`](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR.dom.selection-method-getRanges) method does not override cached ranges when used with the `onlyEditables` argument. -* [#11390](https://dev.ckeditor.com/ticket/11390): [IE] All [XML](https://ckeditor.com/cke4/addon/xml) plugin [methods](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR.xml) now work in IE10+. +* [#11400](https://dev.ckeditor.com/ticket/11400): Fixed: The [`domObject.removeAllListeners()`](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_dom_domObject.html#method-removeAllListeners) method does not remove custom listeners completely. +* [#11493](https://dev.ckeditor.com/ticket/11493): Fixed: The [`selection.getRanges()`](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_dom_selection.html#method-getRanges) method does not override cached ranges when used with the `onlyEditables` argument. +* [#11390](https://dev.ckeditor.com/ticket/11390): [IE] All [XML](https://ckeditor.com/cke4/addon/xml) plugin [methods](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR.xml.html) now work in IE10+. * [#11542](https://dev.ckeditor.com/ticket/11542): [IE11] Fixed: Blurry toolbar icons when Right-to-Left UI language is set. -* [#11504](https://dev.ckeditor.com/ticket/11504): Fixed: When [`config.fullPage`](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR.config-cfg-fullPage) is set to `true`, entities are not encoded in editor output. -* [#11004](https://dev.ckeditor.com/ticket/11004): Integrated [Enhanced Image](https://ckeditor.com/cke4/addon/image2) dialog window with [Advanced Content Filter](https://docs.ckeditor.com/ckeditor4/docs/#!/guide/dev_advanced_content_filter). +* [#11504](https://dev.ckeditor.com/ticket/11504): Fixed: When [`config.fullPage`](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_config.html#cfg-fullPage) is set to `true`, entities are not encoded in editor output. +* [#11004](https://dev.ckeditor.com/ticket/11004): Integrated [Enhanced Image](https://ckeditor.com/cke4/addon/image2) dialog window with [Advanced Content Filter](https://ckeditor.com/docs/ckeditor4/latest/guide/dev_advanced_content_filter.html). * [#11439](https://dev.ckeditor.com/ticket/11439): Fixed: Properties get cloned in the Cell Properties dialog window if multiple cells are selected. ## CKEditor 4.3.2 @@ -1138,7 +1168,7 @@ Fixed Issues: * [#11102](https://dev.ckeditor.com/ticket/11102): Added newline character support. * [#11216](https://dev.ckeditor.com/ticket/11216): Added "\\'" substring support. * [#11121](https://dev.ckeditor.com/ticket/11121): [Firefox] Fixed: High Contrast mode is enabled when the editor is loaded in a hidden iframe. -* [#11350](https://dev.ckeditor.com/ticket/11350): The default value of [`config.contentsCss`](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR.config-cfg-contentsCss) is affected by [`CKEDITOR.getUrl()`](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR-method-getUrl). +* [#11350](https://dev.ckeditor.com/ticket/11350): The default value of [`config.contentsCss`](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_config.html#cfg-contentsCss) is affected by [`CKEDITOR.getUrl()`](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR.html#method-getUrl). * [#11097](https://dev.ckeditor.com/ticket/11097): Improved the [Autogrow](https://ckeditor.com/cke4/addon/autogrow) plugin performance when dealing with very big tables. * [#11290](https://dev.ckeditor.com/ticket/11290): Removed redundant code in the [Source Dialog](https://ckeditor.com/cke4/addon/sourcedialog) plugin. * [#11133](https://dev.ckeditor.com/ticket/11133): [Page Break](https://ckeditor.com/cke4/addon/pagebreak) becomes editable if pasted. @@ -1148,7 +1178,7 @@ Fixed Issues: * [#10778](https://dev.ckeditor.com/ticket/10778): Fixed a bug with range enlargement. The range no longer expands to visible whitespace. * [#11146](https://dev.ckeditor.com/ticket/11146): [IE] Fixed: Preview window switches Internet Explorer to Quirks Mode. * [#10762](https://dev.ckeditor.com/ticket/10762): [IE] Fixed: JavaScript code displayed in preview window's URL bar. -* [#11186](https://dev.ckeditor.com/ticket/11186): Introduced the [`widgets.repository.addUpcastCallback()`](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR.plugins.widget.repository-method-addUpcastCallback) method that allows to block upcasting given element to a widget. +* [#11186](https://dev.ckeditor.com/ticket/11186): Introduced the [`widgets.repository.addUpcastCallback()`](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_plugins_widget_repository.html#method-addUpcastCallback) method that allows to block upcasting given element to a widget. * [#11307](https://dev.ckeditor.com/ticket/11307): Fixed: Paste as Plain Text conflict with the [MooTools](http://mootools.net) library. * [#11140](https://dev.ckeditor.com/ticket/11140): [IE11] Fixed: Anchors are not draggable. * [#11379](https://dev.ckeditor.com/ticket/11379): Changed default contents `line-height` to unitless values to avoid huge text overlapping (like in [#9696](https://dev.ckeditor.com/ticket/9696)). @@ -1170,8 +1200,8 @@ Fixed Issues: Fixed Issues: -* [#11244](https://dev.ckeditor.com/ticket/11244): Changed: The [`widget.repository.checkWidgets()`](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR.plugins.widget.repository-method-checkWidgets) method now fires the [`widget.repository.checkWidgets`](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR.plugins.widget.repository-event-checkWidgets) event, so from CKEditor 4.3.1 it is preferred to use the method rather than fire the event. -* [#11171](https://dev.ckeditor.com/ticket/11171): Fixed: [`editor.insertElement()`](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR.editor-method-insertElement) and [`editor.insertText()`](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR.editor-method-insertText) methods do not call the [`widget.repository.checkWidgets()`](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR.plugins.widget.repository-method-checkWidgets) method. +* [#11244](https://dev.ckeditor.com/ticket/11244): Changed: The [`widget.repository.checkWidgets()`](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_plugins_widget_repository.html#method-checkWidgets) method now fires the [`widget.repository.checkWidgets`](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_plugins_widget_repository.html#event-checkWidgets) event, so from CKEditor 4.3.1 it is preferred to use the method rather than fire the event. +* [#11171](https://dev.ckeditor.com/ticket/11171): Fixed: [`editor.insertElement()`](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_editor.html#method-insertElement) and [`editor.insertText()`](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_editor.html#method-insertText) methods do not call the [`widget.repository.checkWidgets()`](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_plugins_widget_repository.html#method-checkWidgets) method. * [#11085](https://dev.ckeditor.com/ticket/11085): [IE8] Replaced preview generated by the [Mathematical Formulas](https://ckeditor.com/cke4/addon/mathjax) widget with a placeholder. * [#11044](https://dev.ckeditor.com/ticket/11044): Enhanced WAI-ARIA support for the [Language](https://ckeditor.com/cke4/addon/language) plugin drop-down menu. * [#11075](https://dev.ckeditor.com/ticket/11075): With drop-down menu button focused, pressing the *Down Arrow* key will now open the menu and focus its first option. @@ -1182,16 +1212,16 @@ Fixed Issues: * [#10853](https://dev.ckeditor.com/ticket/10853): [Enhanced Image](https://ckeditor.com/cke4/addon/image2): Widget has paragraph wrapper when de-captioning unaligned image. * [#11198](https://dev.ckeditor.com/ticket/11198): Widgets: Drag handler is not fully visible when an inline widget is in a heading. * [#11132](https://dev.ckeditor.com/ticket/11132): [Firefox] Fixed: Caret is lost after drag and drop of an inline widget. -* [#11182](https://dev.ckeditor.com/ticket/11182): [IE10-11] Fixed: Editor crashes (IE11) or works with minor issues (IE10) if a page is loaded in Quirks Mode. See [`env.quirks`](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR.env-property-quirks) for more details. +* [#11182](https://dev.ckeditor.com/ticket/11182): [IE10-11] Fixed: Editor crashes (IE11) or works with minor issues (IE10) if a page is loaded in Quirks Mode. See [`env.quirks`](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_env.html#property-quirks) for more details. * [#11204](https://dev.ckeditor.com/ticket/11204): Added `figure` and `figcaption` styles to the `contents.css` file so [Enhanced Image](https://ckeditor.com/cke4/addon/image2) looks nicer. * [#11202](https://dev.ckeditor.com/ticket/11202): Fixed: No newline in [BBCode](https://ckeditor.com/cke4/addon/bbcode) mode. * [#10890](https://dev.ckeditor.com/ticket/10890): Fixed: Error thrown when pressing the *Delete* key in a list item. * [#10055](https://dev.ckeditor.com/ticket/10055): [IE8-10] Fixed: *Delete* pressed on a selected image causes the browser to go back. -* [#11183](https://dev.ckeditor.com/ticket/11183): Fixed: Inserting a horizontal rule or a table in multiple row selection causes a browser crash. Additionally, the [`editor.insertElement()`](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR.editor-method-insertElement) method does not insert the element into every range of a selection any more. +* [#11183](https://dev.ckeditor.com/ticket/11183): Fixed: Inserting a horizontal rule or a table in multiple row selection causes a browser crash. Additionally, the [`editor.insertElement()`](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_editor.html#method-insertElement) method does not insert the element into every range of a selection any more. * [#11042](https://dev.ckeditor.com/ticket/11042): Fixed: Selection made on an element containing a non-editable element was not auto faked. * [#11125](https://dev.ckeditor.com/ticket/11125): Fixed: Keyboard navigation through menu and drop-down items will now cycle. -* [#11011](https://dev.ckeditor.com/ticket/11011): Fixed: The [`editor.applyStyle()`](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR.editor-method-applyStyle) method removes attributes from nested elements. -* [#11179](https://dev.ckeditor.com/ticket/11179): Fixed: [`editor.destroy()`](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR.editor-method-destroy) does not cleanup content generated by the [Table Resize](https://ckeditor.com/cke4/addon/tableresize) plugin for inline editors. +* [#11011](https://dev.ckeditor.com/ticket/11011): Fixed: The [`editor.applyStyle()`](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_editor.html#method-applyStyle) method removes attributes from nested elements. +* [#11179](https://dev.ckeditor.com/ticket/11179): Fixed: [`editor.destroy()`](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_editor.html#method-destroy) does not cleanup content generated by the [Table Resize](https://ckeditor.com/cke4/addon/tableresize) plugin for inline editors. * [#11237](https://dev.ckeditor.com/ticket/11237): Fixed: Table border attribute value is deleted when pasting content from Microsoft Word. * [#11250](https://dev.ckeditor.com/ticket/11250): Fixed: HTML entities inside the `<textarea>` element are not encoded. * [#11260](https://dev.ckeditor.com/ticket/11260): Fixed: Initially disabled buttons are not read by JAWS as disabled. @@ -1207,7 +1237,7 @@ New Features: * [#10933](https://dev.ckeditor.com/ticket/10933): Widgets: Introduced drag and drop of block widgets with the [Line Utilities](https://ckeditor.com/cke4/addon/lineutils) plugin. * [#10936](https://dev.ckeditor.com/ticket/10936): Widget System changes for easier integration with other dialog systems. * [#10895](https://dev.ckeditor.com/ticket/10895): [Enhanced Image](https://ckeditor.com/cke4/addon/image2): Added file browser integration. -* [#11002](https://dev.ckeditor.com/ticket/11002): Added the [`draggable`](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR.plugins.widget.definition-property-draggable) option to disable drag and drop support for widgets. +* [#11002](https://dev.ckeditor.com/ticket/11002): Added the [`draggable`](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_plugins_widget_definition.html#property-draggable) option to disable drag and drop support for widgets. * [#10937](https://dev.ckeditor.com/ticket/10937): [Mathematical Formulas](https://ckeditor.com/cke4/addon/mathjax) widget improvements: * loading indicator ([#10948](https://dev.ckeditor.com/ticket/10948)), * applying paragraph changes (like font color change) to iframe ([#10841](https://dev.ckeditor.com/ticket/10841)), @@ -1218,8 +1248,8 @@ New Features: * [#10862](https://dev.ckeditor.com/ticket/10862): [Placeholder](https://ckeditor.com/cke4/addon/placeholder) plugin was rewritten as a widget. * [#10822](https://dev.ckeditor.com/ticket/10822): Added styles system integration with non-editable elements (for example widgets) and their nested editables. Styles cannot change non-editable content and are applied in nested editable only if allowed by its type and content filter. * [#10856](https://dev.ckeditor.com/ticket/10856): Menu buttons will now toggle the visibility of their panels when clicked multiple times. [Language](https://ckeditor.com/cke4/addon/language) plugin fixes: Added active language highlighting, added an option to remove the language. -* [#10028](https://dev.ckeditor.com/ticket/10028): New [`config.dialog_noConfirmCancel`](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR.config-cfg-dialog_noConfirmCancel) configuration option that eliminates the need to confirm closing of a dialog window when the user changed any of its fields. -* [#10848](https://dev.ckeditor.com/ticket/10848): Integrate remaining plugins ([Styles](https://ckeditor.com/cke4/addon/stylescombo), [Format](https://ckeditor.com/cke4/addon/format), [Font](https://ckeditor.com/cke4/addon/font), [Color Button](https://ckeditor.com/cke4/addon/colorbutton), [Language](https://ckeditor.com/cke4/addon/language) and [Indent](https://ckeditor.com/cke4/addon/indent)) with [active filter](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR.editor-property-activeFilter). +* [#10028](https://dev.ckeditor.com/ticket/10028): New [`config.dialog_noConfirmCancel`](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_config.html#cfg-dialog_noConfirmCancel) configuration option that eliminates the need to confirm closing of a dialog window when the user changed any of its fields. +* [#10848](https://dev.ckeditor.com/ticket/10848): Integrate remaining plugins ([Styles](https://ckeditor.com/cke4/addon/stylescombo), [Format](https://ckeditor.com/cke4/addon/format), [Font](https://ckeditor.com/cke4/addon/font), [Color Button](https://ckeditor.com/cke4/addon/colorbutton), [Language](https://ckeditor.com/cke4/addon/language) and [Indent](https://ckeditor.com/cke4/addon/indent)) with [active filter](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_editor.html#property-activeFilter). * [#10855](https://dev.ckeditor.com/ticket/10855): Change the extension of emoticons in the [BBCode](https://ckeditor.com/cke4/addon/bbcode) sample from GIF to PNG. Fixed Issues: @@ -1241,7 +1271,7 @@ Fixed Issues: * [#10828](https://dev.ckeditor.com/ticket/10828): [Magic Line](https://ckeditor.com/cke4/addon/magicline) integration with the Widget System. * [#10865](https://dev.ckeditor.com/ticket/10865): Improved hiding copybin, so copying widgets works smoothly. * [#11066](https://dev.ckeditor.com/ticket/11066): Widget's private parts use CSS reset. -* [#11027](https://dev.ckeditor.com/ticket/11027): Fixed: Block commands break on widgets; added the [`contentDomInvalidated`](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR.editor-event-contentDomInvalidated) event. +* [#11027](https://dev.ckeditor.com/ticket/11027): Fixed: Block commands break on widgets; added the [`contentDomInvalidated`](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_editor.html#event-contentDomInvalidated) event. * [#10430](https://dev.ckeditor.com/ticket/10430): Resolve dependence of the [Image](https://ckeditor.com/cke4/addon/image) plugin on the [Form Elements](https://ckeditor.com/cke4/addon/forms) plugin. * [#10911](https://dev.ckeditor.com/ticket/10911): Fixed: Browser *Alt* hotkeys will no longer be blocked while a widget is focused. * [#11082](https://dev.ckeditor.com/ticket/11082): Fixed: Selected widget is not copied or cut when using toolbar buttons or context menu. @@ -1259,19 +1289,19 @@ Fixed Issues: New Features: * [#9764](https://dev.ckeditor.com/ticket/9764): Widget System. - * [Widget plugin](https://ckeditor.com/cke4/addon/widget) introducing the [Widget API](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR.plugins.widget). - * New [`editor.enterMode`](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR.editor-property-enterMode) and [`editor.shiftEnterMode`](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR.editor-property-shiftEnterMode) properties – normalized versions of [`config.enterMode`](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR.config-cfg-enterMode) and [`config.shiftEnterMode`](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR.config-cfg-shiftEnterMode). - * Dynamic editor settings. Starting from CKEditor 4.3 Beta, *Enter* mode values and [content filter](https://docs.ckeditor.com/ckeditor4/docs/#!/guide/dev_advanced_content_filter) instances may be changed dynamically (for example when the caret was placed in an element in which editor features should be adjusted). When you are implementing a new editor feature, you should base its behavior on [dynamic](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR.editor-property-activeEnterMode) or [static](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR.editor-property-enterMode) *Enter* mode values depending on whether this feature works in selection context or globally on editor content. - * Dynamic *Enter* mode values – [`editor.setActiveEnterMode()`](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR.editor-method-setActiveEnterMode) method, [`editor.activeEnterModeChange`](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR.editor-event-activeEnterModeChange) event, and two properties: [`editor.activeEnterMode`](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR.editor-property-activeEnterMode) and [`editor.activeShiftEnterMode`](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR.editor-property-activeShiftEnterMode). - * Dynamic content filter instances – [`editor.setActiveFilter()`](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR.editor-method-setActiveFilter) method, [`editor.activeFilterChange`](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR.editor-event-activeFilterChange) event, and [`editor.activeFilter`](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR.editor-property-activeFilter) property. - * "Fake" selection was introduced. It makes it possible to virtually select any element when the real selection remains hidden. See the [`selection.fake()`](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR.dom.selection-method-fake) method. - * Default [`htmlParser.filter`](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR.htmlParser.filter) rules are not applied to non-editable elements (elements with `contenteditable` attribute set to `false` and their descendants) anymore. To add a rule which will be applied to all elements you need to pass an additional argument to the [`filter.addRules()`](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR.htmlParser.filter-method-addRules) method. + * [Widget plugin](https://ckeditor.com/cke4/addon/widget) introducing the [Widget API](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR.plugins.widget.html). + * New [`editor.enterMode`](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_editor.html#property-enterMode) and [`editor.shiftEnterMode`](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_editor.html#property-shiftEnterMode) properties – normalized versions of [`config.enterMode`](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_config.html#cfg-enterMode) and [`config.shiftEnterMode`](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_config.html#cfg-shiftEnterMode). + * Dynamic editor settings. Starting from CKEditor 4.3 Beta, *Enter* mode values and [content filter](https://ckeditor.com/docs/ckeditor4/latest/guide/dev_advanced_content_filter.html) instances may be changed dynamically (for example when the caret was placed in an element in which editor features should be adjusted). When you are implementing a new editor feature, you should base its behavior on [dynamic](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_editor.html#property-activeEnterMode) or [static](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_editor.html#property-enterMode) *Enter* mode values depending on whether this feature works in selection context or globally on editor content. + * Dynamic *Enter* mode values – [`editor.setActiveEnterMode()`](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_editor.html#method-setActiveEnterMode) method, [`editor.activeEnterModeChange`](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_editor.html#event-activeEnterModeChange) event, and two properties: [`editor.activeEnterMode`](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_editor.html#property-activeEnterMode) and [`editor.activeShiftEnterMode`](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_editor.html#property-activeShiftEnterMode). + * Dynamic content filter instances – [`editor.setActiveFilter()`](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_editor.html#method-setActiveFilter) method, [`editor.activeFilterChange`](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_editor.html#event-activeFilterChange) event, and [`editor.activeFilter`](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_editor.html#property-activeFilter) property. + * "Fake" selection was introduced. It makes it possible to virtually select any element when the real selection remains hidden. See the [`selection.fake()`](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_dom_selection.html#method-fake) method. + * Default [`htmlParser.filter`](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR.htmlParser.filter.html) rules are not applied to non-editable elements (elements with `contenteditable` attribute set to `false` and their descendants) anymore. To add a rule which will be applied to all elements you need to pass an additional argument to the [`filter.addRules()`](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_htmlParser_filter.html#method-addRules) method. * Dozens of new methods were introduced – most interesting ones: - * [`document.find()`](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR.dom.document-method-find), - * [`document.findOne()`](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR.dom.document-method-findOne), - * [`editable.insertElementIntoRange()`](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR.editable-method-insertElementIntoRange), - * [`range.moveToClosestEditablePosition()`](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR.dom.range-method-moveToClosestEditablePosition), - * New methods for [`htmlParser.node`](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR.htmlParser.node) and [`htmlParser.element`](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR.htmlParser.element). + * [`document.find()`](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_dom_document.html#method-find), + * [`document.findOne()`](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_dom_document.html#method-findOne), + * [`editable.insertElementIntoRange()`](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_editable.html#method-insertElementIntoRange), + * [`range.moveToClosestEditablePosition()`](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_dom_range.html#method-moveToClosestEditablePosition), + * New methods for [`htmlParser.node`](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR.htmlParser.node.html) and [`htmlParser.element`](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR.htmlParser.element.html). * [#10659](https://dev.ckeditor.com/ticket/10659): New [Enhanced Image](https://ckeditor.com/cke4/addon/image2) plugin that introduces a widget with integrated image captions, an option to center images, and dynamic "click and drag" resizing. * [#10664](https://dev.ckeditor.com/ticket/10664): New [Mathematical Formulas](https://ckeditor.com/cke4/addon/mathjax) plugin that introduces the MathJax widget. * [#7987](https://dev.ckeditor.com/ticket/7987): New [Language](https://ckeditor.com/cke4/addon/language) plugin that implements Language toolbar button to support [WCAG 3.1.2 Language of Parts](http://www.w3.org/TR/UNDERSTANDING-WCAG20/meaning-other-lang-id.html). @@ -1281,7 +1311,7 @@ New Features: Fixed Issues: -* [#10994](https://dev.ckeditor.com/ticket/10994): Fixed: Loading external jQuery library when opening the [jQuery Adapter](https://docs.ckeditor.com/ckeditor4/docs/#!/guide/dev_jquery) sample directly from file. +* [#10994](https://dev.ckeditor.com/ticket/10994): Fixed: Loading external jQuery library when opening the [jQuery Adapter](https://ckeditor.com/docs/ckeditor4/latest/guide/dev_jquery.html) sample directly from file. * [#10975](https://dev.ckeditor.com/ticket/10975): [IE] Fixed: Error thrown while opening the color palette. * [#9929](https://dev.ckeditor.com/ticket/9929): [Blink/WebKit] Fixed: A non-breaking space is created once a character is deleted and a regular space is typed. * [#10963](https://dev.ckeditor.com/ticket/10963): Fixed: JAWS issue with the keyboard shortcut for [Magic Line](https://ckeditor.com/cke4/addon/magicline). @@ -1295,13 +1325,13 @@ Fixed Issues: * [#10308](https://dev.ckeditor.com/ticket/10308): [IE10] Fixed: Unspecified error when deleting a row. * [#10945](https://dev.ckeditor.com/ticket/10945): [Chrome] Fixed: Clicking with a mouse inside the editor does not show the caret. * [#10912](https://dev.ckeditor.com/ticket/10912): Prevent default action when content of a non-editable link is clicked. -* [#10913](https://dev.ckeditor.com/ticket/10913): Fixed [`CKEDITOR.plugins.addExternal()`](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR.resourceManager-method-addExternal) not handling paths including file name specified. -* [#10666](https://dev.ckeditor.com/ticket/10666): Fixed [`CKEDITOR.tools.isArray()`](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR.tools-method-isArray) not working cross frame. +* [#10913](https://dev.ckeditor.com/ticket/10913): Fixed [`CKEDITOR.plugins.addExternal()`](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_resourceManager.html#method-addExternal) not handling paths including file name specified. +* [#10666](https://dev.ckeditor.com/ticket/10666): Fixed [`CKEDITOR.tools.isArray()`](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_tools.html#method-isArray) not working cross frame. * [#10910](https://dev.ckeditor.com/ticket/10910): [IE9] Fixed JavaScript error thrown in Compatibility Mode when clicking and/or typing in the editing area. * [#10868](https://dev.ckeditor.com/ticket/10868): [IE8] Prevent the browser from crashing when applying the Inline Quotation style. * [#10915](https://dev.ckeditor.com/ticket/10915): Fixed: Invalid CSS filter in the Kama skin. * [#10914](https://dev.ckeditor.com/ticket/10914): Plugins [Indent List](https://ckeditor.com/cke4/addon/indentlist) and [Indent Block](https://ckeditor.com/cke4/addon/indentblock) are now included in the build configuration. -* [#10812](https://dev.ckeditor.com/ticket/10812): Fixed [`range.createBookmark2()`](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR.dom.range-method-createBookmark2) incorrectly normalizing offsets. This bug was causing many issues: [#10850](https://dev.ckeditor.com/ticket/10850), [#10842](https://dev.ckeditor.com/ticket/10842). +* [#10812](https://dev.ckeditor.com/ticket/10812): Fixed [`range.createBookmark2()`](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_dom_range.html#method-createBookmark2) incorrectly normalizing offsets. This bug was causing many issues: [#10850](https://dev.ckeditor.com/ticket/10850), [#10842](https://dev.ckeditor.com/ticket/10842). * [#10951](https://dev.ckeditor.com/ticket/10951): Reviewed and optimized focus handling on panels (combo, menu buttons, color buttons, and context menu) to enhance accessibility. Fixed [#10705](https://dev.ckeditor.com/ticket/10705), [#10706](https://dev.ckeditor.com/ticket/10706) and [#10707](https://dev.ckeditor.com/ticket/10707). * [#10704](https://dev.ckeditor.com/ticket/10704): Fixed a JAWS issue with the Select Color dialog window title not being announced. * [#10753](https://dev.ckeditor.com/ticket/10753): The floating toolbar in inline instances now has a dedicated accessibility label. @@ -1331,24 +1361,24 @@ Fixed Issues: * Dropped compatibility support for Internet Explorer 7 and Firefox 3.6. -* Both the Basic and the Standard distribution packages will not contain the new [Indent Block](https://ckeditor.com/cke4/addon/indentblock) plugin. Because of this the [Advanced Content Filter](https://docs.ckeditor.com/ckeditor4/docs/#!/guide/dev_advanced_content_filter) might remove block indentations from existing contents. If you want to prevent this, either [add an appropriate ACF rule to your filter](https://docs.ckeditor.com/ckeditor4/docs/#!/guide/dev_allowed_content_rules) or create a custom build based on the Basic/Standard package and add the Indent Block plugin in [CKBuilder](https://ckeditor.com/cke4/builder). +* Both the Basic and the Standard distribution packages will not contain the new [Indent Block](https://ckeditor.com/cke4/addon/indentblock) plugin. Because of this the [Advanced Content Filter](https://ckeditor.com/docs/ckeditor4/latest/guide/dev_advanced_content_filter.html) might remove block indentations from existing contents. If you want to prevent this, either [add an appropriate ACF rule to your filter](https://ckeditor.com/docs/ckeditor4/latest/guide/dev_allowed_content_rules.html) or create a custom build based on the Basic/Standard package and add the Indent Block plugin in [CKBuilder](https://ckeditor.com/cke4/builder). New Features: * [#10027](https://dev.ckeditor.com/ticket/10027): Separated list and block indentation into two plugins: [Indent List](https://ckeditor.com/cke4/addon/indentlist) and [Indent Block](https://ckeditor.com/cke4/addon/indentblock). * [#8244](https://dev.ckeditor.com/ticket/8244): Use *(Shift+)Tab* to indent and outdent lists. -* [#10281](https://dev.ckeditor.com/ticket/10281): The [jQuery Adapter](https://docs.ckeditor.com/ckeditor4/docs/#!/guide/dev_jquery) is now available. Several jQuery-related issues fixed: [#8261](https://dev.ckeditor.com/ticket/8261), [#9077](https://dev.ckeditor.com/ticket/9077), [#8710](https://dev.ckeditor.com/ticket/8710), [#8530](https://dev.ckeditor.com/ticket/8530), [#9019](https://dev.ckeditor.com/ticket/9019), [#6181](https://dev.ckeditor.com/ticket/6181), [#7876](https://dev.ckeditor.com/ticket/7876), [#6906](https://dev.ckeditor.com/ticket/6906). -* [#10042](https://dev.ckeditor.com/ticket/10042): Introduced [`config.title`](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR.config-cfg-title) setting to change the human-readable title of the editor. -* [#9794](https://dev.ckeditor.com/ticket/9794): Added [`editor.change`](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR.editor-event-change) event. +* [#10281](https://dev.ckeditor.com/ticket/10281): The [jQuery Adapter](https://ckeditor.com/docs/ckeditor4/latest/guide/dev_jquery.html) is now available. Several jQuery-related issues fixed: [#8261](https://dev.ckeditor.com/ticket/8261), [#9077](https://dev.ckeditor.com/ticket/9077), [#8710](https://dev.ckeditor.com/ticket/8710), [#8530](https://dev.ckeditor.com/ticket/8530), [#9019](https://dev.ckeditor.com/ticket/9019), [#6181](https://dev.ckeditor.com/ticket/6181), [#7876](https://dev.ckeditor.com/ticket/7876), [#6906](https://dev.ckeditor.com/ticket/6906). +* [#10042](https://dev.ckeditor.com/ticket/10042): Introduced [`config.title`](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_config.html#cfg-title) setting to change the human-readable title of the editor. +* [#9794](https://dev.ckeditor.com/ticket/9794): Added [`editor.change`](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_editor.html#event-change) event. * [#9923](https://dev.ckeditor.com/ticket/9923): HiDPI support in the editor UI. HiDPI icons for [Moono skin](https://ckeditor.com/cke4/addon/moono) added. -* [#8031](https://dev.ckeditor.com/ticket/8031): Handle `required` attributes on `<textarea>` elements — introduced [`editor.required`](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR.editor-event-required) event. +* [#8031](https://dev.ckeditor.com/ticket/8031): Handle `required` attributes on `<textarea>` elements — introduced [`editor.required`](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_editor.html#event-required) event. * [#10280](https://dev.ckeditor.com/ticket/10280): Ability to replace `<textarea>` elements with the inline editor. Fixed Issues: * [#10599](https://dev.ckeditor.com/ticket/10599): [Indent](https://ckeditor.com/cke4/addon/indent) plugin is no longer required by the [List](https://ckeditor.com/cke4/addon/list) plugin. * [#10370](https://dev.ckeditor.com/ticket/10370): Inconsistency in data events between framed and inline editors. -* [#10438](https://dev.ckeditor.com/ticket/10438): [FF, IE] No selection is done on an editable element on executing [`editor.setData()`](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR.editor-method-setData). +* [#10438](https://dev.ckeditor.com/ticket/10438): [FF, IE] No selection is done on an editable element on executing [`editor.setData()`](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_editor.html#method-setData). ## CKEditor 4.1.3 @@ -1361,8 +1391,8 @@ Fixed Issues: * [#10644](https://dev.ckeditor.com/ticket/10644): Fixed a critical bug when pasting plain text in Blink-based browsers. * [#5189](https://dev.ckeditor.com/ticket/5189): [Find/Replace](https://ckeditor.com/cke4/addon/find) dialog window: rename "Cancel" button to "Close". * [#10562](https://dev.ckeditor.com/ticket/10562): [Housekeeping] Unified CSS gradient filter formats in the [Moono](https://ckeditor.com/cke4/addon/moono) skin. -* [#10537](https://dev.ckeditor.com/ticket/10537): Advanced Content Filter should register a default rule for [`config.shiftEnterMode`](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR.config-cfg-shiftEnterMode). -* [#10610](https://dev.ckeditor.com/ticket/10610): [`CKEDITOR.dialog.addIframe()`](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR.dialog-static-method-addIframe) incorrectly sets the iframe size in dialog windows. +* [#10537](https://dev.ckeditor.com/ticket/10537): Advanced Content Filter should register a default rule for [`config.shiftEnterMode`](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_config.html#cfg-shiftEnterMode). +* [#10610](https://dev.ckeditor.com/ticket/10610): [`CKEDITOR.dialog.addIframe()`](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_dialog.html#static-method-addIframe) incorrectly sets the iframe size in dialog windows. ## CKEditor 4.1.2 @@ -1374,11 +1404,11 @@ Fixed Issues: * [#10339](https://dev.ckeditor.com/ticket/10339): Fixed: Error thrown when inserted data was totally stripped out after filtering and processing. * [#10298](https://dev.ckeditor.com/ticket/10298): Fixed: Data processor breaks attributes containing protected parts. -* [#10367](https://dev.ckeditor.com/ticket/10367): Fixed: [`editable.insertText()`](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR.editable-method-insertText) loses characters when `RegExp` replace controls are being inserted. +* [#10367](https://dev.ckeditor.com/ticket/10367): Fixed: [`editable.insertText()`](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_editable.html#method-insertText) loses characters when `RegExp` replace controls are being inserted. * [#10165](https://dev.ckeditor.com/ticket/10165): [IE] Access denied error when `document.domain` has been altered. -* [#9761](https://dev.ckeditor.com/ticket/9761): Update the *Backspace* key state in [`keystrokeHandler.blockedKeystrokes`](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR.keystrokeHandler-property-blockedKeystrokes) when calling [`editor.setReadOnly()`](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR.editor-method-setReadOnly). -* [#6504](https://dev.ckeditor.com/ticket/6504): Fixed: Race condition while loading several [`config.customConfig`](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR.config-cfg-customConfig) files. -* [#10146](https://dev.ckeditor.com/ticket/10146): [Firefox] Empty lines are being removed while [`config.enterMode`](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR.config-cfg-enterMode) is [`CKEDITOR.ENTER_BR`](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR-property-ENTER_BR). +* [#9761](https://dev.ckeditor.com/ticket/9761): Update the *Backspace* key state in [`keystrokeHandler.blockedKeystrokes`](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_keystrokeHandler.html#property-blockedKeystrokes) when calling [`editor.setReadOnly()`](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_editor.html#method-setReadOnly). +* [#6504](https://dev.ckeditor.com/ticket/6504): Fixed: Race condition while loading several [`config.customConfig`](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_config.html#cfg-customConfig) files. +* [#10146](https://dev.ckeditor.com/ticket/10146): [Firefox] Empty lines are being removed while [`config.enterMode`](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_config.html#cfg-enterMode) is [`CKEDITOR.ENTER_BR`](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR.html#property-ENTER_BR). * [#10360](https://dev.ckeditor.com/ticket/10360): Fixed: ARIA `role="application"` should not be used for dialog windows. * [#10361](https://dev.ckeditor.com/ticket/10361): Fixed: ARIA `role="application"` should not be used for floating panels. * [#10510](https://dev.ckeditor.com/ticket/10510): Introduced unique voice labels to differentiate between different editor instances. @@ -1399,27 +1429,27 @@ Fixed Issues: * [#10265](https://dev.ckeditor.com/ticket/10265): Wrong loop type in the [File Browser](https://ckeditor.com/cke4/addon/filebrowser) plugin. * [#10249](https://dev.ckeditor.com/ticket/10249): Wrong undo/redo states at start. * [#10268](https://dev.ckeditor.com/ticket/10268): [Show Blocks](https://ckeditor.com/cke4/addon/showblocks) does not recover after switching to Source view. -* [#9995](https://dev.ckeditor.com/ticket/9995): HTML code in the `<textarea>` should not be modified by the [`htmlDataProcessor`](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR.htmlDataProcessor). -* [#10320](https://dev.ckeditor.com/ticket/10320): [Justify](https://ckeditor.com/cke4/addon/justify) plugin should add elements to Advanced Content Filter based on current [Enter mode](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR.config-cfg-enterMode). -* [#10260](https://dev.ckeditor.com/ticket/10260): Fixed: Advanced Content Filter blocks [`tabSpaces`](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR.config-cfg-tabSpaces). Unified `data-cke-*` attributes filtering. -* [#10315](https://dev.ckeditor.com/ticket/10315): [WebKit] [Undo manager](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR.plugins.undo.UndoManager) should not record snapshots after a filling character was added/removed. +* [#9995](https://dev.ckeditor.com/ticket/9995): HTML code in the `<textarea>` should not be modified by the [`htmlDataProcessor`](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR.htmlDataProcessor.html). +* [#10320](https://dev.ckeditor.com/ticket/10320): [Justify](https://ckeditor.com/cke4/addon/justify) plugin should add elements to Advanced Content Filter based on current [Enter mode](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_config.html#cfg-enterMode). +* [#10260](https://dev.ckeditor.com/ticket/10260): Fixed: Advanced Content Filter blocks [`tabSpaces`](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_config.html#cfg-tabSpaces). Unified `data-cke-*` attributes filtering. +* [#10315](https://dev.ckeditor.com/ticket/10315): [WebKit] [Undo manager](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR.plugins.undo.UndoManager.html) should not record snapshots after a filling character was added/removed. * [#10291](https://dev.ckeditor.com/ticket/10291): [WebKit] Space after a filling character should be secured. * [#10330](https://dev.ckeditor.com/ticket/10330): [WebKit] The filling character is not removed on `keydown` in specific cases. * [#10285](https://dev.ckeditor.com/ticket/10285): Fixed: Styled text pasted from MS Word causes an infinite loop. -* [#10131](https://dev.ckeditor.com/ticket/10131): Fixed: [`undoManager.update()`](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR.plugins.undo.UndoManager-method-update) does not refresh the command state. +* [#10131](https://dev.ckeditor.com/ticket/10131): Fixed: [`undoManager.update()`](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_plugins_undo_UndoManager.html#method-update) does not refresh the command state. * [#10337](https://dev.ckeditor.com/ticket/10337): Fixed: Unable to remove `<s>` using [Remove Format](https://ckeditor.com/cke4/addon/removeformat). ## CKEditor 4.1 Fixed Issues: -* [#10192](https://dev.ckeditor.com/ticket/10192): Closing lists with the *Enter* key does not work with [Advanced Content Filter](https://docs.ckeditor.com/ckeditor4/docs/#!/guide/dev_advanced_content_filter) in several cases. -* [#10191](https://dev.ckeditor.com/ticket/10191): Fixed allowed content rules unification, so the [`filter.allowedContent`](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR.filter-property-allowedContent) property always contains rules in the same format. +* [#10192](https://dev.ckeditor.com/ticket/10192): Closing lists with the *Enter* key does not work with [Advanced Content Filter](https://ckeditor.com/docs/ckeditor4/latest/guide/dev_advanced_content_filter.html) in several cases. +* [#10191](https://dev.ckeditor.com/ticket/10191): Fixed allowed content rules unification, so the [`filter.allowedContent`](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_filter.html#property-allowedContent) property always contains rules in the same format. * [#10224](https://dev.ckeditor.com/ticket/10224): Advanced Content Filter does not remove non-empty `<a>` elements anymore. * Minor issues in plugin integration with Advanced Content Filter: * [#10166](https://dev.ckeditor.com/ticket/10166): Added transformation from the `align` attribute to `float` style to preserve backward compatibility after the introduction of Advanced Content Filter. * [#10195](https://dev.ckeditor.com/ticket/10195): [Image](https://ckeditor.com/cke4/addon/image) plugin no longer registers rules for links to Advanced Content Filter. - * [#10213](https://dev.ckeditor.com/ticket/10213): [Justify](https://ckeditor.com/cke4/addon/justify) plugin is now correctly registering rules to Advanced Content Filter when [`config.justifyClasses`](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR.config-cfg-justifyClasses) is defined. + * [#10213](https://dev.ckeditor.com/ticket/10213): [Justify](https://ckeditor.com/cke4/addon/justify) plugin is now correctly registering rules to Advanced Content Filter when [`config.justifyClasses`](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_config.html#cfg-justifyClasses) is defined. ## CKEditor 4.1 RC @@ -1431,18 +1461,18 @@ New Features: * Based on loaded features (toolbar items, plugins) - the data will be filtered according to what the editor in its current configuration can handle. - * Based on [`config.allowedContent`](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR.config-cfg-allowedContent) rules - the data + * Based on [`config.allowedContent`](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_config.html#cfg-allowedContent) rules - the data will be filtered and the editor features (toolbar items, commands, keystrokes) will be enabled if they are allowed. - See the `datafiltering.html` sample, [guides](https://docs.ckeditor.com/ckeditor4/docs/#!/guide/dev_advanced_content_filter) and [`CKEDITOR.filter` API documentation](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR.filter). + See the `datafiltering.html` sample, [guides](https://ckeditor.com/docs/ckeditor4/latest/guide/dev_advanced_content_filter.html) and [`CKEDITOR.filter` API documentation](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR.filter.html). * [#9387](https://dev.ckeditor.com/ticket/9387): Reintroduced [Shared Spaces](https://ckeditor.com/cke4/addon/sharedspace) - the ability to display toolbar and bottom editor space in selected locations and to share them by different editor instances. -* [#9907](https://dev.ckeditor.com/ticket/9907): Added the [`contentPreview`](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR-event-contentPreview) event for preview data manipulation. +* [#9907](https://dev.ckeditor.com/ticket/9907): Added the [`contentPreview`](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR.html#event-contentPreview) event for preview data manipulation. * [#9713](https://dev.ckeditor.com/ticket/9713): Introduced the [Source Dialog](https://ckeditor.com/cke4/addon/sourcedialog) plugin that brings raw HTML editing for inline editor instances. -* Included in [#9829](https://dev.ckeditor.com/ticket/9829): Introduced new events, [`toHtml`](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR.editor-event-toHtml) and [`toDataFormat`](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR.editor-event-toDataFormat), allowing for better integration with data processing. -* [#9981](https://dev.ckeditor.com/ticket/9981): Added ability to filter [`htmlParser.fragment`](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR.htmlParser.fragment), [`htmlParser.element`](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR.htmlParser.element) etc. by many [`htmlParser.filter`](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR.htmlParser.filter)s before writing structure to an HTML string. +* Included in [#9829](https://dev.ckeditor.com/ticket/9829): Introduced new events, [`toHtml`](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_editor.html#event-toHtml) and [`toDataFormat`](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_editor.html#event-toDataFormat), allowing for better integration with data processing. +* [#9981](https://dev.ckeditor.com/ticket/9981): Added ability to filter [`htmlParser.fragment`](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR.htmlParser.fragment.html), [`htmlParser.element`](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR.htmlParser.element.html) etc. by many [`htmlParser.filter`](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR.htmlParser.filter.html)s before writing structure to an HTML string. * Included in [#10103](https://dev.ckeditor.com/ticket/10103): - * Introduced the [`editor.status`](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR.editor-property-status) property to make it easier to check the current status of the editor. - * Default [`command`](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR.command) state is now [`CKEDITOR.TRISTATE_DISABLE`](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR-property-TRISTATE_DISABLED). It will be activated on [`editor.instanceReady`](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR-event-instanceReady) or immediately after being added if the editor is already initialized. + * Introduced the [`editor.status`](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_editor.html#property-status) property to make it easier to check the current status of the editor. + * Default [`command`](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR.command.html) state is now [`CKEDITOR.TRISTATE_DISABLE`](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR.html#property-TRISTATE_DISABLED). It will be activated on [`editor.instanceReady`](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR.html#event-instanceReady) or immediately after being added if the editor is already initialized. * [#9796](https://dev.ckeditor.com/ticket/9796): Introduced `<s>` as a default tag for strikethrough, which replaces obsolete `<strike>` in HTML5. ## CKEditor 4.0.3 @@ -1451,21 +1481,21 @@ Fixed Issues: * [#10196](https://dev.ckeditor.com/ticket/10196): Fixed context menus not opening with keyboard shortcuts when [Autogrow](https://ckeditor.com/cke4/addon/autogrow) is enabled. * [#10212](https://dev.ckeditor.com/ticket/10212): [IE7-10] Undo command throws errors after multiple switches between Source and WYSIWYG view. -* [#10219](https://dev.ckeditor.com/ticket/10219): [Inline editor] Error thrown after calling [`editor.destroy()`](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR.editor-method-destroy). +* [#10219](https://dev.ckeditor.com/ticket/10219): [Inline editor] Error thrown after calling [`editor.destroy()`](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_editor.html#method-destroy). ## CKEditor 4.0.2 Fixed Issues: -* [#9779](https://dev.ckeditor.com/ticket/9779): Fixed overriding [`CKEDITOR.getUrl()`](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR-method-getUrl) with `CKEDITOR_GETURL`. +* [#9779](https://dev.ckeditor.com/ticket/9779): Fixed overriding [`CKEDITOR.getUrl()`](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR.html#method-getUrl) with `CKEDITOR_GETURL`. * [#9772](https://dev.ckeditor.com/ticket/9772): Custom buttons in the dialog window footer have different look and size ([Moono](https://ckeditor.com/cke4/addon/moono), [Kama](https://ckeditor.com/cke4/addon/kama) skins). -* [#9029](https://dev.ckeditor.com/ticket/9029): Custom styles added with the [`stylesSet.add()`](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR.stylesSet-method-add) are displayed in the wrong order. -* [#9887](https://dev.ckeditor.com/ticket/9887): Disable [Magic Line](https://ckeditor.com/cke4/addon/magicline) when [`editor.readOnly`](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR.editor-property-readOnly) is set. -* [#9882](https://dev.ckeditor.com/ticket/9882): Fixed empty document title on [`editor.getData()`](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR.editor-method-getData) if set via the Document Properties dialog window. +* [#9029](https://dev.ckeditor.com/ticket/9029): Custom styles added with the [`stylesSet.add()`](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_stylesSet.html#method-add) are displayed in the wrong order. +* [#9887](https://dev.ckeditor.com/ticket/9887): Disable [Magic Line](https://ckeditor.com/cke4/addon/magicline) when [`editor.readOnly`](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_editor.html#property-readOnly) is set. +* [#9882](https://dev.ckeditor.com/ticket/9882): Fixed empty document title on [`editor.getData()`](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_editor.html#method-getData) if set via the Document Properties dialog window. * [#9773](https://dev.ckeditor.com/ticket/9773): Fixed rendering problems with selection fields in the Kama skin. -* [#9851](https://dev.ckeditor.com/ticket/9851): The [`selectionChange`](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR.editor-event-selectionChange) event is not fired when mouse selection ended outside editable. +* [#9851](https://dev.ckeditor.com/ticket/9851): The [`selectionChange`](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_editor.html#event-selectionChange) event is not fired when mouse selection ended outside editable. * [#9903](https://dev.ckeditor.com/ticket/9903): [Inline editor] Bad positioning of floating space with page horizontal scroll. -* [#9872](https://dev.ckeditor.com/ticket/9872): [`editor.checkDirty()`](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR.editor-method-checkDirty) returns `true` when called onload. Removed the obsolete `editor.mayBeDirty` flag. +* [#9872](https://dev.ckeditor.com/ticket/9872): [`editor.checkDirty()`](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_editor.html#method-checkDirty) returns `true` when called onload. Removed the obsolete `editor.mayBeDirty` flag. * [#9893](https://dev.ckeditor.com/ticket/9893): [IE] Fixed broken toolbar when editing mixed direction content in Quirks mode. * [#9845](https://dev.ckeditor.com/ticket/9845): Fixed TAB navigation in the [Link](https://ckeditor.com/cke4/addon/link) dialog window when the Anchor option is used and no anchors are available. * [#9883](https://dev.ckeditor.com/ticket/9883): Maximizing was making the entire page editable with [divarea](https://ckeditor.com/cke4/addon/divarea)-based editors. @@ -1522,8 +1552,8 @@ Fixed Issues: * [#9787](https://dev.ckeditor.com/ticket/9787): [IE9] `onChange` is not fired for checkboxes in dialogs. * [#9842](https://dev.ckeditor.com/ticket/9842): [Firefox 17] When opening a toolbar menu for the first time and pressing the *Down Arrow* key, focus goes to the next toolbar button instead of the menu options. * [#9847](https://dev.ckeditor.com/ticket/9847): [Elements Path](https://ckeditor.com/cke4/addon/elementspath) should not be initialized in the inline editor. -* [#9853](https://dev.ckeditor.com/ticket/9853): [`editor.addRemoveFormatFilter()`](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR.editor-method-addRemoveFormatFilter) is exposed before it really works. -* [#8893](https://dev.ckeditor.com/ticket/8893): Value of the [`pasteFromWordCleanupFile`](https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR.config-cfg-pasteFromWordCleanupFile) configuration option is now taken from the instance configuration. +* [#9853](https://dev.ckeditor.com/ticket/9853): [`editor.addRemoveFormatFilter()`](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_editor.html#method-addRemoveFormatFilter) is exposed before it really works. +* [#8893](https://dev.ckeditor.com/ticket/8893): Value of the [`pasteFromWordCleanupFile`](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_config.html#cfg-pasteFromWordCleanupFile) configuration option is now taken from the instance configuration. * [#9693](https://dev.ckeditor.com/ticket/9693): Removed "Live Preview" checkbox from UI color picker. @@ -1535,4 +1565,4 @@ The CKEditor JavaScript API has been kept compatible with CKEditor 4, whenever possible. The list of relevant changes can be found in the [API Changes page of the CKEditor 4 documentation][1]. -[1]: https://docs.ckeditor.com/ckeditor4/docs/#!/guide/dev_api_changes "API Changes" +[1]: https://ckeditor.com/docs/ckeditor4/latest/guide/dev_api_changes.html "API Changes" diff --git a/web/core/assets/vendor/ckeditor/ckeditor.js b/web/core/assets/vendor/ckeditor/ckeditor.js index 894c7efe49d0bb088c36f659ba0dcad2ff2fe338..fd05da6cf70d192bbb8bae10b4466f80603272eb 100644 --- a/web/core/assets/vendor/ckeditor/ckeditor.js +++ b/web/core/assets/vendor/ckeditor/ckeditor.js @@ -2,13 +2,13 @@ Copyright (c) 2003-2018, CKSource - Frederico Knabben. All rights reserved. For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license */ -(function(){window.CKEDITOR&&window.CKEDITOR.dom||(window.CKEDITOR||(window.CKEDITOR=function(){var f=/(^|.*[\\\/])ckeditor\.js(?:\?.*|;.*)?$/i,h={timestamp:"I648",version:"4.10.0",revision:"de1371d",rnd:Math.floor(900*Math.random())+100,_:{pending:[],basePathSrcPattern:f},status:"unloaded",basePath:function(){var d=window.CKEDITOR_BASEPATH||"";if(!d)for(var k=document.getElementsByTagName("script"),e=0;e<k.length;e++){var b=k[e].src.match(f);if(b){d=b[1];break}}-1==d.indexOf(":/")&&"//"!=d.slice(0, +(function(){window.CKEDITOR&&window.CKEDITOR.dom||(window.CKEDITOR||(window.CKEDITOR=function(){var f=/(^|.*[\\\/])ckeditor\.js(?:\?.*|;.*)?$/i,h={timestamp:"I8E8",version:"4.10.1",revision:"59246e973",rnd:Math.floor(900*Math.random())+100,_:{pending:[],basePathSrcPattern:f},status:"unloaded",basePath:function(){var d=window.CKEDITOR_BASEPATH||"";if(!d)for(var k=document.getElementsByTagName("script"),e=0;e<k.length;e++){var b=k[e].src.match(f);if(b){d=b[1];break}}-1==d.indexOf(":/")&&"//"!=d.slice(0, 2)&&(d=0===d.indexOf("/")?location.href.match(/^.*?:\/\/[^\/]*/)[0]+d:location.href.match(/^[^\?]*\/(?:)/)[0]+d);if(!d)throw'The CKEditor installation path could not be automatically detected. Please set the global variable "CKEDITOR_BASEPATH" before creating editor instances.';return d}(),getUrl:function(d){-1==d.indexOf(":/")&&0!==d.indexOf("/")&&(d=this.basePath+d);this.timestamp&&"/"!=d.charAt(d.length-1)&&!/[&?]t=/.test(d)&&(d+=(0<=d.indexOf("?")?"\x26":"?")+"t\x3d"+this.timestamp);return d}, domReady:function(){function d(){try{document.addEventListener?(document.removeEventListener("DOMContentLoaded",d,!1),k()):document.attachEvent&&"complete"===document.readyState&&(document.detachEvent("onreadystatechange",d),k())}catch(b){}}function k(){for(var b;b=e.shift();)b()}var e=[];return function(b){function g(){try{document.documentElement.doScroll("left")}catch(a){setTimeout(g,1);return}d()}e.push(b);"complete"===document.readyState&&setTimeout(d,1);if(1==e.length)if(document.addEventListener)document.addEventListener("DOMContentLoaded", d,!1),window.addEventListener("load",d,!1);else if(document.attachEvent){document.attachEvent("onreadystatechange",d);window.attachEvent("onload",d);b=!1;try{b=!window.frameElement}catch(c){}document.documentElement.doScroll&&b&&g()}}}()},e=window.CKEDITOR_GETURL;if(e){var k=h.getUrl;h.getUrl=function(d){return e.call(h,d)||k.call(h,d)}}return h}()),CKEDITOR.event||(CKEDITOR.event=function(){},CKEDITOR.event.implementOn=function(f){var h=CKEDITOR.event.prototype,e;for(e in h)null==f[e]&&(f[e]=h[e])}, CKEDITOR.event.prototype=function(){function f(k){var d=h(this);return d[k]||(d[k]=new e(k))}var h=function(k){k=k.getPrivate&&k.getPrivate()||k._||(k._={});return k.events||(k.events={})},e=function(k){this.name=k;this.listeners=[]};e.prototype={getListenerIndex:function(k){for(var d=0,e=this.listeners;d<e.length;d++)if(e[d].fn==k)return d;return-1}};return{define:function(k,d){var e=f.call(this,k);CKEDITOR.tools.extend(e,d,!0)},on:function(k,d,e,h,b){function g(a,n,b,g){a={name:k,sender:this,editor:a, data:n,listenerData:h,stop:b,cancel:g,removeListener:c};return!1===d.call(e,a)?!1:a.data}function c(){n.removeListener(k,d)}var a=f.call(this,k);if(0>a.getListenerIndex(d)){a=a.listeners;e||(e=this);isNaN(b)&&(b=10);var n=this;g.fn=d;g.priority=b;for(var w=a.length-1;0<=w;w--)if(a[w].priority<=b)return a.splice(w+1,0,g),{removeListener:c};a.unshift(g)}return{removeListener:c}},once:function(){var k=Array.prototype.slice.call(arguments),d=k[1];k[1]=function(k){k.removeListener();return d.apply(this, -arguments)};return this.on.apply(this,k)},capture:function(){CKEDITOR.event.useCapture=1;var k=this.on.apply(this,arguments);CKEDITOR.event.useCapture=0;return k},fire:function(){var k=0,d=function(){k=1},e=0,f=function(){e=1};return function(b,g,c){var a=h(this)[b];b=k;var n=e;k=e=0;if(a){var w=a.listeners;if(w.length)for(var w=w.slice(0),v,p=0;p<w.length;p++){if(a.errorProof)try{v=w[p].call(this,c,g,d,f)}catch(r){}else v=w[p].call(this,c,g,d,f);!1===v?e=1:"undefined"!=typeof v&&(g=v);if(k||e)break}}g= +arguments)};return this.on.apply(this,k)},capture:function(){CKEDITOR.event.useCapture=1;var k=this.on.apply(this,arguments);CKEDITOR.event.useCapture=0;return k},fire:function(){var k=0,d=function(){k=1},e=0,f=function(){e=1};return function(b,g,c){var a=h(this)[b];b=k;var n=e;k=e=0;if(a){var w=a.listeners;if(w.length)for(var w=w.slice(0),v,t=0;t<w.length;t++){if(a.errorProof)try{v=w[t].call(this,c,g,d,f)}catch(p){}else v=w[t].call(this,c,g,d,f);!1===v?e=1:"undefined"!=typeof v&&(g=v);if(k||e)break}}g= e?!1:"undefined"==typeof g?!0:g;k=b;e=n;return g}}(),fireOnce:function(k,d,e){d=this.fire(k,d,e);delete h(this)[k];return d},removeListener:function(k,d){var e=h(this)[k];if(e){var f=e.getListenerIndex(d);0<=f&&e.listeners.splice(f,1)}},removeAllListeners:function(){var e=h(this),d;for(d in e)delete e[d]},hasListeners:function(e){return(e=h(this)[e])&&0<e.listeners.length}}}()),CKEDITOR.editor||(CKEDITOR.editor=function(){CKEDITOR._.pending.push([this,arguments]);CKEDITOR.event.call(this)},CKEDITOR.editor.prototype.fire= function(f,h){f in{instanceReady:1,loaded:1}&&(this[f]=!0);return CKEDITOR.event.prototype.fire.call(this,f,h,this)},CKEDITOR.editor.prototype.fireOnce=function(f,h){f in{instanceReady:1,loaded:1}&&(this[f]=!0);return CKEDITOR.event.prototype.fireOnce.call(this,f,h,this)},CKEDITOR.event.implementOn(CKEDITOR.editor.prototype)),CKEDITOR.env||(CKEDITOR.env=function(){var f=navigator.userAgent.toLowerCase(),h=f.match(/edge[ \/](\d+.?\d*)/),e=-1<f.indexOf("trident/"),e=!(!h&&!e),e={ie:e,edge:!!h,webkit:!e&& -1<f.indexOf(" applewebkit/"),air:-1<f.indexOf(" adobeair/"),mac:-1<f.indexOf("macintosh"),quirks:"BackCompat"==document.compatMode&&(!document.documentMode||10>document.documentMode),mobile:-1<f.indexOf("mobile"),iOS:/(ipad|iphone|ipod)/.test(f),isCustomDomain:function(){if(!this.ie)return!1;var d=document.domain,e=window.location.hostname;return d!=e&&d!="["+e+"]"},secure:"https:"==location.protocol};e.gecko="Gecko"==navigator.product&&!e.webkit&&!e.ie;e.webkit&&(-1<f.indexOf("chrome")?e.chrome= @@ -16,7 +16,7 @@ function(f,h){f in{instanceReady:1,loaded:1}&&(this[f]=!0);return CKEDITOR.event 534>k);e.hidpi=2<=window.devicePixelRatio;e.needsBrFiller=e.gecko||e.webkit||e.ie&&10<k;e.needsNbspFiller=e.ie&&11>k;e.cssClass="cke_browser_"+(e.ie?"ie":e.gecko?"gecko":e.webkit?"webkit":"unknown");e.quirks&&(e.cssClass+=" cke_browser_quirks");e.ie&&(e.cssClass+=" cke_browser_ie"+(e.quirks?"6 cke_browser_iequirks":e.version));e.air&&(e.cssClass+=" cke_browser_air");e.iOS&&(e.cssClass+=" cke_browser_ios");e.hidpi&&(e.cssClass+=" cke_hidpi");return e}()),"unloaded"==CKEDITOR.status&&function(){CKEDITOR.event.implementOn(CKEDITOR); CKEDITOR.loadFullCore=function(){if("basic_ready"!=CKEDITOR.status)CKEDITOR.loadFullCore._load=1;else{delete CKEDITOR.loadFullCore;var f=document.createElement("script");f.type="text/javascript";f.src=CKEDITOR.basePath+"ckeditor.js";document.getElementsByTagName("head")[0].appendChild(f)}};CKEDITOR.loadFullCoreTimeout=0;CKEDITOR.add=function(f){(this._.pending||(this._.pending=[])).push(f)};(function(){CKEDITOR.domReady(function(){var f=CKEDITOR.loadFullCore,h=CKEDITOR.loadFullCoreTimeout;f&&(CKEDITOR.status= "basic_ready",f&&f._load?f():h&&setTimeout(function(){CKEDITOR.loadFullCore&&CKEDITOR.loadFullCore()},1E3*h))})})();CKEDITOR.status="basic_loaded"}(),"use strict",CKEDITOR.VERBOSITY_WARN=1,CKEDITOR.VERBOSITY_ERROR=2,CKEDITOR.verbosity=CKEDITOR.VERBOSITY_WARN|CKEDITOR.VERBOSITY_ERROR,CKEDITOR.warn=function(f,h){CKEDITOR.verbosity&CKEDITOR.VERBOSITY_WARN&&CKEDITOR.fire("log",{type:"warn",errorCode:f,additionalData:h})},CKEDITOR.error=function(f,h){CKEDITOR.verbosity&CKEDITOR.VERBOSITY_ERROR&&CKEDITOR.fire("log", -{type:"error",errorCode:f,additionalData:h})},CKEDITOR.on("log",function(f){if(window.console&&window.console.log){var h=console[f.data.type]?f.data.type:"log",e=f.data.errorCode;if(f=f.data.additionalData)console[h]("[CKEDITOR] Error code: "+e+".",f);else console[h]("[CKEDITOR] Error code: "+e+".");console[h]("[CKEDITOR] For more information about this error go to https://docs.ckeditor.com/ckeditor4/docs/#!/guide/dev_errors-section-"+e)}},null,null,999),CKEDITOR.dom={},function(){var f=[],h=CKEDITOR.env.gecko? +{type:"error",errorCode:f,additionalData:h})},CKEDITOR.on("log",function(f){if(window.console&&window.console.log){var h=console[f.data.type]?f.data.type:"log",e=f.data.errorCode;if(f=f.data.additionalData)console[h]("[CKEDITOR] Error code: "+e+".",f);else console[h]("[CKEDITOR] Error code: "+e+".");console[h]("[CKEDITOR] For more information about this error go to https://ckeditor.com/docs/ckeditor4/latest/guide/dev_errors.html#"+e)}},null,null,999),CKEDITOR.dom={},function(){var f=[],h=CKEDITOR.env.gecko? "-moz-":CKEDITOR.env.webkit?"-webkit-":CKEDITOR.env.ie?"-ms-":"",e=/&/g,k=/>/g,d=/</g,l=/"/g,m=/&(lt|gt|amp|quot|nbsp|shy|#\d{1,5});/g,b={lt:"\x3c",gt:"\x3e",amp:"\x26",quot:'"',nbsp:" ",shy:""},g=function(c,a){return"#"==a[0]?String.fromCharCode(parseInt(a.slice(1),10)):b[a]};CKEDITOR.on("reset",function(){f=[]});CKEDITOR.tools={arrayCompare:function(c,a){if(!c&&!a)return!0;if(!c||!a||c.length!=a.length)return!1;for(var n=0;n<c.length;n++)if(c[n]!=a[n])return!1;return!0},getIndex:function(c,a){for(var n= 0;n<c.length;++n)if(a(c[n]))return n;return-1},clone:function(c){var a;if(c&&c instanceof Array){a=[];for(var n=0;n<c.length;n++)a[n]=CKEDITOR.tools.clone(c[n]);return a}if(null===c||"object"!=typeof c||c instanceof String||c instanceof Number||c instanceof Boolean||c instanceof Date||c instanceof RegExp||c.nodeType||c.window===c)return c;a=new c.constructor;for(n in c)a[n]=CKEDITOR.tools.clone(c[n]);return a},capitalize:function(c,a){return c.charAt(0).toUpperCase()+(a?c.slice(1):c.slice(1).toLowerCase())}, extend:function(c){var a=arguments.length,n,b;"boolean"==typeof(n=arguments[a-1])?a--:"boolean"==typeof(n=arguments[a-2])&&(b=arguments[a-1],a-=2);for(var g=1;g<a;g++){var d=arguments[g],e;for(e in d)if(!0===n||null==c[e])if(!b||e in b)c[e]=d[e]}return c},prototypedCopy:function(c){var a=function(){};a.prototype=c;return new a},copy:function(c){var a={},n;for(n in c)a[n]=c[n];return a},isArray:function(c){return"[object Array]"==Object.prototype.toString.call(c)},isEmpty:function(c){for(var a in c)if(c.hasOwnProperty(a))return!1; @@ -114,208 +114,209 @@ f=a.$.documentElement,h=f.clientTop||d.$.clientTop||0,q=f.clientLeft||d.$.client h.$.scrollTop;h.equals(this)||(g+=h.$.clientLeft||0,c+=h.$.clientTop||0);for(;q&&!q.equals(h);)g-=q.$.scrollLeft,c-=q.$.scrollTop,q=q.getParent();q=h;h=(k=h.$.offsetParent)?new CKEDITOR.dom.element(k):null}b&&(k=this.getWindow(),h=b.getWindow(),!k.equals(h)&&k.$.frameElement&&(b=(new CKEDITOR.dom.element(k.$.frameElement)).getDocumentPosition(b),g+=b.x,c+=b.y));document.documentElement.getBoundingClientRect||!CKEDITOR.env.gecko||e||(g+=this.$.clientLeft?1:0,c+=this.$.clientTop?1:0);return{x:g,y:c}}, scrollIntoView:function(b){var g=this.getParent();if(g){do if((g.$.clientWidth&&g.$.clientWidth<g.$.scrollWidth||g.$.clientHeight&&g.$.clientHeight<g.$.scrollHeight)&&!g.is("body")&&this.scrollIntoParent(g,b,1),g.is("html")){var c=g.getWindow();try{var a=c.$.frameElement;a&&(g=new CKEDITOR.dom.element(a))}catch(d){}}while(g=g.getParent())}},scrollIntoParent:function(b,g,c){var a,d,e,k;function f(a,c){/body|html/.test(b.getName())?b.getWindow().$.scrollBy(a,c):(b.$.scrollLeft+=a,b.$.scrollTop+=c)} function h(a,c){var b={x:0,y:0};if(!a.is(m?"body":"html")){var g=a.$.getBoundingClientRect();b.x=g.left;b.y=g.top}g=a.getWindow();g.equals(c)||(g=h(CKEDITOR.dom.element.get(g.$.frameElement),c),b.x+=g.x,b.y+=g.y);return b}function q(a,c){return parseInt(a.getComputedStyle("margin-"+c)||0,10)||0}!b&&(b=this.getWindow());e=b.getDocument();var m="BackCompat"==e.$.compatMode;b instanceof CKEDITOR.dom.window&&(b=m?e.getBody():e.getDocumentElement());CKEDITOR.env.webkit&&(e=this.getEditor(!1))&&(e._.previousScrollTop= -null);e=b.getWindow();d=h(this,e);var l=h(b,e),A=this.$.offsetHeight;a=this.$.offsetWidth;var D=b.$.clientHeight,t=b.$.clientWidth;e=d.x-q(this,"left")-l.x||0;k=d.y-q(this,"top")-l.y||0;a=d.x+a+q(this,"right")-(l.x+t)||0;d=d.y+A+q(this,"bottom")-(l.y+D)||0;(0>k||0<d)&&f(0,!0===g?k:!1===g?d:0>k?k:d);c&&(0>e||0<a)&&f(0>e?e:a,0)},setState:function(b,g,c){g=g||"cke";switch(b){case CKEDITOR.TRISTATE_ON:this.addClass(g+"_on");this.removeClass(g+"_off");this.removeClass(g+"_disabled");c&&this.setAttribute("aria-pressed", +null);e=b.getWindow();d=h(this,e);var l=h(b,e),C=this.$.offsetHeight;a=this.$.offsetWidth;var B=b.$.clientHeight,u=b.$.clientWidth;e=d.x-q(this,"left")-l.x||0;k=d.y-q(this,"top")-l.y||0;a=d.x+a+q(this,"right")-(l.x+u)||0;d=d.y+C+q(this,"bottom")-(l.y+B)||0;(0>k||0<d)&&f(0,!0===g?k:!1===g?d:0>k?k:d);c&&(0>e||0<a)&&f(0>e?e:a,0)},setState:function(b,g,c){g=g||"cke";switch(b){case CKEDITOR.TRISTATE_ON:this.addClass(g+"_on");this.removeClass(g+"_off");this.removeClass(g+"_disabled");c&&this.setAttribute("aria-pressed", !0);c&&this.removeAttribute("aria-disabled");break;case CKEDITOR.TRISTATE_DISABLED:this.addClass(g+"_disabled");this.removeClass(g+"_off");this.removeClass(g+"_on");c&&this.setAttribute("aria-disabled",!0);c&&this.removeAttribute("aria-pressed");break;default:this.addClass(g+"_off"),this.removeClass(g+"_on"),this.removeClass(g+"_disabled"),c&&this.removeAttribute("aria-pressed"),c&&this.removeAttribute("aria-disabled")}},getFrameDocument:function(){var b=this.$;try{b.contentWindow.document}catch(g){b.src= b.src}return b&&new CKEDITOR.dom.document(b.contentWindow.document)},copyAttributes:function(b,g){var c=this.$.attributes;g=g||{};for(var a=0;a<c.length;a++){var d=c[a],e=d.nodeName.toLowerCase(),k;if(!(e in g))if("checked"==e&&(k=this.getAttribute(e)))b.setAttribute(e,k);else if(!CKEDITOR.env.ie||this.hasAttribute(e))k=this.getAttribute(e),null===k&&(k=d.nodeValue),b.setAttribute(e,k)}""!==this.$.style.cssText&&(b.$.style.cssText=this.$.style.cssText)},renameNode:function(b){if(this.getName()!=b){var g= this.getDocument();b=new CKEDITOR.dom.element(b,g);this.copyAttributes(b);this.moveChildren(b);this.getParent(!0)&&this.$.parentNode.replaceChild(b.$,this.$);b.$["data-cke-expando"]=this.$["data-cke-expando"];this.$=b.$;delete this.getName}},getChild:function(){function b(b,c){var a=b.childNodes;if(0<=c&&c<a.length)return a[c]}return function(g){var c=this.$;if(g.slice)for(g=g.slice();0<g.length&&c;)c=b(c,g.shift());else c=b(c,g);return c?new CKEDITOR.dom.node(c):null}}(),getChildCount:function(){return this.$.childNodes.length}, disableContextMenu:function(){function b(b){return b.type==CKEDITOR.NODE_ELEMENT&&b.hasClass("cke_enable_context_menu")}this.on("contextmenu",function(g){g.data.getTarget().getAscendant(b,!0)||g.data.preventDefault()})},getDirection:function(b){return b?this.getComputedStyle("direction")||this.getDirection()||this.getParent()&&this.getParent().getDirection(1)||this.getDocument().$.dir||"ltr":this.getStyle("direction")||this.getAttribute("dir")},data:function(b,g){b="data-"+b;if(void 0===g)return this.getAttribute(b); !1===g?this.removeAttribute(b):this.setAttribute(b,g);return null},getEditor:function(b){var g=CKEDITOR.instances,c,a,d;b=b||void 0===b;for(c in g)if(a=g[c],a.element.equals(this)&&a.elementMode!=CKEDITOR.ELEMENT_MODE_APPENDTO||!b&&(d=a.editable())&&(d.equals(this)||d.contains(this)))return a;return null},find:function(b){var g=h(this);b=new CKEDITOR.dom.nodeList(this.$.querySelectorAll(e(this,b)));g();return b},findOne:function(b){var g=h(this);b=this.$.querySelector(e(this,b));g();return b?new CKEDITOR.dom.element(b): -null},forEach:function(b,g,c){if(!(c||g&&this.type!=g))var a=b(this);if(!1!==a){c=this.getChildren();for(var d=0;d<c.count();d++)a=c.getItem(d),a.type==CKEDITOR.NODE_ELEMENT?a.forEach(b,g):g&&a.type!=g||b(a)}}});var m={width:["border-left-width","border-right-width","padding-left","padding-right"],height:["border-top-width","border-bottom-width","padding-top","padding-bottom"]};CKEDITOR.dom.element.prototype.setSize=function(b,g,c){"number"==typeof g&&(!c||CKEDITOR.env.ie&&CKEDITOR.env.quirks||(g-= -k.call(this,b)),this.setStyle(b,g+"px"))};CKEDITOR.dom.element.prototype.getSize=function(b,g){var c=Math.max(this.$["offset"+CKEDITOR.tools.capitalize(b)],this.$["client"+CKEDITOR.tools.capitalize(b)])||0;g&&(c-=k.call(this,b));return c}}(),CKEDITOR.dom.documentFragment=function(f){f=f||CKEDITOR.document;this.$=f.type==CKEDITOR.NODE_DOCUMENT?f.$.createDocumentFragment():f},CKEDITOR.tools.extend(CKEDITOR.dom.documentFragment.prototype,CKEDITOR.dom.element.prototype,{type:CKEDITOR.NODE_DOCUMENT_FRAGMENT, +null},forEach:function(b,g,c){if(!(c||g&&this.type!=g))var a=b(this);if(!1!==a){c=this.getChildren();for(var d=0;d<c.count();d++)a=c.getItem(d),a.type==CKEDITOR.NODE_ELEMENT?a.forEach(b,g):g&&a.type!=g||b(a)}}});var m={width:["border-left-width","border-right-width","padding-left","padding-right"],height:["border-top-width","border-bottom-width","padding-top","padding-bottom"]};CKEDITOR.dom.element.prototype.setSize=function(b,d,c){"number"==typeof d&&(!c||CKEDITOR.env.ie&&CKEDITOR.env.quirks||(d-= +k.call(this,b)),this.setStyle(b,d+"px"))};CKEDITOR.dom.element.prototype.getSize=function(b,d){var c=Math.max(this.$["offset"+CKEDITOR.tools.capitalize(b)],this.$["client"+CKEDITOR.tools.capitalize(b)])||0;d&&(c-=k.call(this,b));return c}}(),CKEDITOR.dom.documentFragment=function(f){f=f||CKEDITOR.document;this.$=f.type==CKEDITOR.NODE_DOCUMENT?f.$.createDocumentFragment():f},CKEDITOR.tools.extend(CKEDITOR.dom.documentFragment.prototype,CKEDITOR.dom.element.prototype,{type:CKEDITOR.NODE_DOCUMENT_FRAGMENT, insertAfterNode:function(f){f=f.$;f.parentNode.insertBefore(this.$,f.nextSibling)},getHtml:function(){var f=new CKEDITOR.dom.element("div");this.clone(1,1).appendTo(f);return f.getHtml().replace(/\s*data-cke-expando=".*?"/g,"")}},!0,{append:1,appendBogus:1,clone:1,getFirst:1,getHtml:1,getLast:1,getParent:1,getNext:1,getPrevious:1,appendTo:1,moveChildren:1,insertBefore:1,insertAfterNode:1,replace:1,trim:1,type:1,ltrim:1,rtrim:1,getDocument:1,getChildCount:1,getChild:1,getChildren:1}),function(){function f(a, -c){var b=this.range;if(this._.end)return null;if(!this._.start){this._.start=1;if(b.collapsed)return this.end(),null;b.optimize()}var g,d=b.startContainer;g=b.endContainer;var e=b.startOffset,k=b.endOffset,f,n=this.guard,h=this.type,m=a?"getPreviousSourceNode":"getNextSourceNode";if(!a&&!this._.guardLTR){var l=g.type==CKEDITOR.NODE_ELEMENT?g:g.getParent(),z=g.type==CKEDITOR.NODE_ELEMENT?g.getChild(k):g.getNext();this._.guardLTR=function(a,c){return(!c||!l.equals(a))&&(!z||!a.equals(z))&&(a.type!= -CKEDITOR.NODE_ELEMENT||!c||!a.equals(b.root))}}if(a&&!this._.guardRTL){var I=d.type==CKEDITOR.NODE_ELEMENT?d:d.getParent(),E=d.type==CKEDITOR.NODE_ELEMENT?e?d.getChild(e-1):null:d.getPrevious();this._.guardRTL=function(a,c){return(!c||!I.equals(a))&&(!E||!a.equals(E))&&(a.type!=CKEDITOR.NODE_ELEMENT||!c||!a.equals(b.root))}}var F=a?this._.guardRTL:this._.guardLTR;f=n?function(a,c){return!1===F(a,c)?!1:n(a,c)}:F;this.current?g=this.current[m](!1,h,f):(a?g.type==CKEDITOR.NODE_ELEMENT&&(g=0<k?g.getChild(k- -1):!1===f(g,!0)?null:g.getPreviousSourceNode(!0,h,f)):(g=d,g.type==CKEDITOR.NODE_ELEMENT&&((g=g.getChild(e))||(g=!1===f(d,!0)?null:d.getNextSourceNode(!0,h,f)))),g&&!1===f(g)&&(g=null));for(;g&&!this._.end;){this.current=g;if(!this.evaluator||!1!==this.evaluator(g)){if(!c)return g}else if(c&&this.evaluator)return!1;g=g[m](!1,h,f)}this.end();return this.current=null}function h(a){for(var c,b=null;c=f.call(this,a);)b=c;return b}CKEDITOR.dom.walker=CKEDITOR.tools.createClass({$:function(a){this.range= +c){var b=this.range;if(this._.end)return null;if(!this._.start){this._.start=1;if(b.collapsed)return this.end(),null;b.optimize()}var d,g=b.startContainer;d=b.endContainer;var e=b.startOffset,k=b.endOffset,f,n=this.guard,h=this.type,m=a?"getPreviousSourceNode":"getNextSourceNode";if(!a&&!this._.guardLTR){var l=d.type==CKEDITOR.NODE_ELEMENT?d:d.getParent(),z=d.type==CKEDITOR.NODE_ELEMENT?d.getChild(k):d.getNext();this._.guardLTR=function(a,c){return(!c||!l.equals(a))&&(!z||!a.equals(z))&&(a.type!= +CKEDITOR.NODE_ELEMENT||!c||!a.equals(b.root))}}if(a&&!this._.guardRTL){var I=g.type==CKEDITOR.NODE_ELEMENT?g:g.getParent(),F=g.type==CKEDITOR.NODE_ELEMENT?e?g.getChild(e-1):null:g.getPrevious();this._.guardRTL=function(a,c){return(!c||!I.equals(a))&&(!F||!a.equals(F))&&(a.type!=CKEDITOR.NODE_ELEMENT||!c||!a.equals(b.root))}}var E=a?this._.guardRTL:this._.guardLTR;f=n?function(a,c){return!1===E(a,c)?!1:n(a,c)}:E;this.current?d=this.current[m](!1,h,f):(a?d.type==CKEDITOR.NODE_ELEMENT&&(d=0<k?d.getChild(k- +1):!1===f(d,!0)?null:d.getPreviousSourceNode(!0,h,f)):(d=g,d.type==CKEDITOR.NODE_ELEMENT&&((d=d.getChild(e))||(d=!1===f(g,!0)?null:g.getNextSourceNode(!0,h,f)))),d&&!1===f(d)&&(d=null));for(;d&&!this._.end;){this.current=d;if(!this.evaluator||!1!==this.evaluator(d)){if(!c)return d}else if(c&&this.evaluator)return!1;d=d[m](!1,h,f)}this.end();return this.current=null}function h(a){for(var c,b=null;c=f.call(this,a);)b=c;return b}CKEDITOR.dom.walker=CKEDITOR.tools.createClass({$:function(a){this.range= a;this._={}},proto:{end:function(){this._.end=1},next:function(){return f.call(this)},previous:function(){return f.call(this,1)},checkForward:function(){return!1!==f.call(this,0,1)},checkBackward:function(){return!1!==f.call(this,1,1)},lastForward:function(){return h.call(this)},lastBackward:function(){return h.call(this,1)},reset:function(){delete this.current;this._={}}}});var e={block:1,"list-item":1,table:1,"table-row-group":1,"table-header-group":1,"table-footer-group":1,"table-row":1,"table-column-group":1, "table-column":1,"table-cell":1,"table-caption":1},k={absolute:1,fixed:1};CKEDITOR.dom.element.prototype.isBlockBoundary=function(a){return"none"!=this.getComputedStyle("float")||this.getComputedStyle("position")in k||!e[this.getComputedStyle("display")]?!!(this.is(CKEDITOR.dtd.$block)||a&&this.is(a)):!0};CKEDITOR.dom.walker.blockBoundary=function(a){return function(c){return!(c.type==CKEDITOR.NODE_ELEMENT&&c.isBlockBoundary(a))}};CKEDITOR.dom.walker.listItemBoundary=function(){return this.blockBoundary({br:1})}; -CKEDITOR.dom.walker.bookmark=function(a,c){function b(a){return a&&a.getName&&"span"==a.getName()&&a.data("cke-bookmark")}return function(g){var d,e;d=g&&g.type!=CKEDITOR.NODE_ELEMENT&&(e=g.getParent())&&b(e);d=a?d:d||b(g);return!!(c^d)}};CKEDITOR.dom.walker.whitespaces=function(a){return function(c){var b;c&&c.type==CKEDITOR.NODE_TEXT&&(b=!CKEDITOR.tools.trim(c.getText())||CKEDITOR.env.webkit&&c.getText()==CKEDITOR.dom.selection.FILLING_CHAR_SEQUENCE);return!!(a^b)}};CKEDITOR.dom.walker.invisible= -function(a){var c=CKEDITOR.dom.walker.whitespaces(),b=CKEDITOR.env.webkit?1:0;return function(g){c(g)?g=1:(g.type==CKEDITOR.NODE_TEXT&&(g=g.getParent()),g=g.$.offsetWidth<=b);return!!(a^g)}};CKEDITOR.dom.walker.nodeType=function(a,c){return function(b){return!!(c^b.type==a)}};CKEDITOR.dom.walker.bogus=function(a){function c(a){return!l(a)&&!m(a)}return function(b){var g=CKEDITOR.env.needsBrFiller?b.is&&b.is("br"):b.getText&&d.test(b.getText());g&&(g=b.getParent(),b=b.getNext(c),g=g.isBlockBoundary()&& +CKEDITOR.dom.walker.bookmark=function(a,c){function b(a){return a&&a.getName&&"span"==a.getName()&&a.data("cke-bookmark")}return function(d){var g,e;g=d&&d.type!=CKEDITOR.NODE_ELEMENT&&(e=d.getParent())&&b(e);g=a?g:g||b(d);return!!(c^g)}};CKEDITOR.dom.walker.whitespaces=function(a){return function(c){var b;c&&c.type==CKEDITOR.NODE_TEXT&&(b=!CKEDITOR.tools.trim(c.getText())||CKEDITOR.env.webkit&&c.getText()==CKEDITOR.dom.selection.FILLING_CHAR_SEQUENCE);return!!(a^b)}};CKEDITOR.dom.walker.invisible= +function(a){var c=CKEDITOR.dom.walker.whitespaces(),b=CKEDITOR.env.webkit?1:0;return function(d){c(d)?d=1:(d.type==CKEDITOR.NODE_TEXT&&(d=d.getParent()),d=d.$.offsetWidth<=b);return!!(a^d)}};CKEDITOR.dom.walker.nodeType=function(a,c){return function(b){return!!(c^b.type==a)}};CKEDITOR.dom.walker.bogus=function(a){function c(a){return!l(a)&&!m(a)}return function(b){var g=CKEDITOR.env.needsBrFiller?b.is&&b.is("br"):b.getText&&d.test(b.getText());g&&(g=b.getParent(),b=b.getNext(c),g=g.isBlockBoundary()&& (!b||b.type==CKEDITOR.NODE_ELEMENT&&b.isBlockBoundary()));return!!(a^g)}};CKEDITOR.dom.walker.temp=function(a){return function(c){c.type!=CKEDITOR.NODE_ELEMENT&&(c=c.getParent());c=c&&c.hasAttribute("data-cke-temp");return!!(a^c)}};var d=/^[\t\r\n ]*(?: |\xa0)$/,l=CKEDITOR.dom.walker.whitespaces(),m=CKEDITOR.dom.walker.bookmark(),b=CKEDITOR.dom.walker.temp(),g=function(a){return m(a)||l(a)||a.type==CKEDITOR.NODE_ELEMENT&&a.is(CKEDITOR.dtd.$inline)&&!a.is(CKEDITOR.dtd.$empty)};CKEDITOR.dom.walker.ignored= -function(a){return function(c){c=l(c)||m(c)||b(c);return!!(a^c)}};var c=CKEDITOR.dom.walker.ignored();CKEDITOR.dom.walker.empty=function(a){return function(b){for(var g=0,d=b.getChildCount();g<d;++g)if(!c(b.getChild(g)))return!!a;return!a}};var a=CKEDITOR.dom.walker.empty(),n=CKEDITOR.dom.walker.validEmptyBlockContainers=CKEDITOR.tools.extend(function(a){var c={},b;for(b in a)CKEDITOR.dtd[b]["#"]&&(c[b]=1);return c}(CKEDITOR.dtd.$block),{caption:1,td:1,th:1});CKEDITOR.dom.walker.editable=function(b){return function(g){g= -c(g)?!1:g.type==CKEDITOR.NODE_TEXT||g.type==CKEDITOR.NODE_ELEMENT&&(g.is(CKEDITOR.dtd.$inline)||g.is("hr")||"false"==g.getAttribute("contenteditable")||!CKEDITOR.env.needsBrFiller&&g.is(n)&&a(g))?!0:!1;return!!(b^g)}};CKEDITOR.dom.element.prototype.getBogus=function(){var a=this;do a=a.getPreviousSourceNode();while(g(a));return a&&(CKEDITOR.env.needsBrFiller?a.is&&a.is("br"):a.getText&&d.test(a.getText()))?a:!1}}(),CKEDITOR.dom.range=function(f){this.endOffset=this.endContainer=this.startOffset=this.startContainer= -null;this.collapsed=!0;var h=f instanceof CKEDITOR.dom.document;this.document=h?f:f.getDocument();this.root=h?f.getBody():f},function(){function f(a){a.collapsed=a.startContainer&&a.endContainer&&a.startContainer.equals(a.endContainer)&&a.startOffset==a.endOffset}function h(a,c,b,g,d){function e(a,c,b,g){var k=b?a.getPrevious():a.getNext();if(g&&h)return k;l||g?c.append(a.clone(!0,d),b):(a.remove(),m&&c.append(a,b));return k}function k(){var a,c,b,g=Math.min(O.length,C.length);for(a=0;a<g;a++)if(c= -O[a],b=C[a],!c.equals(b))return a;return a-1}function f(){var c=S-1,b=F&&H&&!t.equals(B);c<J-1||c<R-1||b?(b?a.moveToPosition(B,CKEDITOR.POSITION_BEFORE_START):R==c+1&&E?a.moveToPosition(C[c],CKEDITOR.POSITION_BEFORE_END):a.moveToPosition(C[c+1],CKEDITOR.POSITION_BEFORE_START),g&&(c=O[c+1])&&c.type==CKEDITOR.NODE_ELEMENT&&(b=CKEDITOR.dom.element.createFromHtml('\x3cspan data-cke-bookmark\x3d"1" style\x3d"display:none"\x3e\x26nbsp;\x3c/span\x3e',a.document),b.insertAfter(c),c.mergeSiblings(!1),a.moveToBookmark({startNode:b}))): -a.collapse(!0)}a.optimizeBookmark();var h=0===c,m=1==c,l=2==c;c=l||m;var t=a.startContainer,B=a.endContainer,y=a.startOffset,z=a.endOffset,I,E,F,H,G,L;if(l&&B.type==CKEDITOR.NODE_TEXT&&(t.equals(B)||t.type===CKEDITOR.NODE_ELEMENT&&t.getFirst().equals(B)))b.append(a.document.createText(B.substring(y,z)));else{B.type==CKEDITOR.NODE_TEXT?l?L=!0:B=B.split(z):0<B.getChildCount()?z>=B.getChildCount()?(B=B.getChild(z-1),E=!0):B=B.getChild(z):H=E=!0;t.type==CKEDITOR.NODE_TEXT?l?G=!0:t.split(y):0<t.getChildCount()? -0===y?(t=t.getChild(y),I=!0):t=t.getChild(y-1):F=I=!0;for(var O=t.getParents(),C=B.getParents(),S=k(),J=O.length-1,R=C.length-1,K=b,U,Y,Z,aa=-1,M=S;M<=J;M++){Y=O[M];Z=Y.getNext();for(M!=J||Y.equals(C[M])&&J<R?c&&(U=K.append(Y.clone(0,d))):I?e(Y,K,!1,F):G&&K.append(a.document.createText(Y.substring(y)));Z;){if(Z.equals(C[M])){aa=M;break}Z=e(Z,K)}K=U}K=b;for(M=S;M<=R;M++)if(b=C[M],Z=b.getPrevious(),b.equals(O[M]))c&&(K=K.getChild(0));else{M!=R||b.equals(O[M])&&R<J?c&&(U=K.append(b.clone(0,d))):E?e(b, -K,!1,H):L&&K.append(a.document.createText(b.substring(0,z)));if(M>aa)for(;Z;)Z=e(Z,K,!0);K=U}l||f()}}function e(){var a=!1,c=CKEDITOR.dom.walker.whitespaces(),b=CKEDITOR.dom.walker.bookmark(!0),g=CKEDITOR.dom.walker.bogus();return function(d){return b(d)||c(d)?!0:g(d)&&!a?a=!0:d.type==CKEDITOR.NODE_TEXT&&(d.hasAscendant("pre")||CKEDITOR.tools.trim(d.getText()).length)||d.type==CKEDITOR.NODE_ELEMENT&&!d.is(l)?!1:!0}}function k(a){var c=CKEDITOR.dom.walker.whitespaces(),b=CKEDITOR.dom.walker.bookmark(1); -return function(g){return b(g)||c(g)?!0:!a&&m(g)||g.type==CKEDITOR.NODE_ELEMENT&&g.is(CKEDITOR.dtd.$removeEmpty)}}function d(a){return function(){var b;return this[a?"getPreviousNode":"getNextNode"](function(a){!b&&c(a)&&(b=a);return g(a)&&!(m(a)&&a.equals(b))})}}var l={abbr:1,acronym:1,b:1,bdo:1,big:1,cite:1,code:1,del:1,dfn:1,em:1,font:1,i:1,ins:1,label:1,kbd:1,q:1,samp:1,small:1,span:1,strike:1,strong:1,sub:1,sup:1,tt:1,u:1,"var":1},m=CKEDITOR.dom.walker.bogus(),b=/^[\t\r\n ]*(?: |\xa0)$/, +function(a){return function(c){c=l(c)||m(c)||b(c);return!!(a^c)}};var c=CKEDITOR.dom.walker.ignored();CKEDITOR.dom.walker.empty=function(a){return function(b){for(var d=0,g=b.getChildCount();d<g;++d)if(!c(b.getChild(d)))return!!a;return!a}};var a=CKEDITOR.dom.walker.empty(),n=CKEDITOR.dom.walker.validEmptyBlockContainers=CKEDITOR.tools.extend(function(a){var c={},b;for(b in a)CKEDITOR.dtd[b]["#"]&&(c[b]=1);return c}(CKEDITOR.dtd.$block),{caption:1,td:1,th:1});CKEDITOR.dom.walker.editable=function(b){return function(d){d= +c(d)?!1:d.type==CKEDITOR.NODE_TEXT||d.type==CKEDITOR.NODE_ELEMENT&&(d.is(CKEDITOR.dtd.$inline)||d.is("hr")||"false"==d.getAttribute("contenteditable")||!CKEDITOR.env.needsBrFiller&&d.is(n)&&a(d))?!0:!1;return!!(b^d)}};CKEDITOR.dom.element.prototype.getBogus=function(){var a=this;do a=a.getPreviousSourceNode();while(g(a));return a&&(CKEDITOR.env.needsBrFiller?a.is&&a.is("br"):a.getText&&d.test(a.getText()))?a:!1}}(),CKEDITOR.dom.range=function(f){this.endOffset=this.endContainer=this.startOffset=this.startContainer= +null;this.collapsed=!0;var h=f instanceof CKEDITOR.dom.document;this.document=h?f:f.getDocument();this.root=h?f.getBody():f},function(){function f(a){a.collapsed=a.startContainer&&a.endContainer&&a.startContainer.equals(a.endContainer)&&a.startOffset==a.endOffset}function h(a,c,b,d,g){function e(a,c,b,d){var k=b?a.getPrevious():a.getNext();if(d&&h)return k;l||d?c.append(a.clone(!0,g),b):(a.remove(),m&&c.append(a,b));return k}function k(){var a,c,b,d=Math.min(O.length,D.length);for(a=0;a<d;a++)if(c= +O[a],b=D[a],!c.equals(b))return a;return a-1}function f(){var c=S-1,b=E&&H&&!u.equals(y);c<J-1||c<R-1||b?(b?a.moveToPosition(y,CKEDITOR.POSITION_BEFORE_START):R==c+1&&F?a.moveToPosition(D[c],CKEDITOR.POSITION_BEFORE_END):a.moveToPosition(D[c+1],CKEDITOR.POSITION_BEFORE_START),d&&(c=O[c+1])&&c.type==CKEDITOR.NODE_ELEMENT&&(b=CKEDITOR.dom.element.createFromHtml('\x3cspan data-cke-bookmark\x3d"1" style\x3d"display:none"\x3e\x26nbsp;\x3c/span\x3e',a.document),b.insertAfter(c),c.mergeSiblings(!1),a.moveToBookmark({startNode:b}))): +a.collapse(!0)}a.optimizeBookmark();var h=0===c,m=1==c,l=2==c;c=l||m;var u=a.startContainer,y=a.endContainer,x=a.startOffset,z=a.endOffset,I,F,E,H,G,L;if(l&&y.type==CKEDITOR.NODE_TEXT&&(u.equals(y)||u.type===CKEDITOR.NODE_ELEMENT&&u.getFirst().equals(y)))b.append(a.document.createText(y.substring(x,z)));else{y.type==CKEDITOR.NODE_TEXT?l?L=!0:y=y.split(z):0<y.getChildCount()?z>=y.getChildCount()?(y=y.getChild(z-1),F=!0):y=y.getChild(z):H=F=!0;u.type==CKEDITOR.NODE_TEXT?l?G=!0:u.split(x):0<u.getChildCount()? +0===x?(u=u.getChild(x),I=!0):u=u.getChild(x-1):E=I=!0;for(var O=u.getParents(),D=y.getParents(),S=k(),J=O.length-1,R=D.length-1,K=b,U,X,Y,Z=-1,M=S;M<=J;M++){X=O[M];Y=X.getNext();for(M!=J||X.equals(D[M])&&J<R?c&&(U=K.append(X.clone(0,g))):I?e(X,K,!1,E):G&&K.append(a.document.createText(X.substring(x)));Y;){if(Y.equals(D[M])){Z=M;break}Y=e(Y,K)}K=U}K=b;for(M=S;M<=R;M++)if(b=D[M],Y=b.getPrevious(),b.equals(O[M]))c&&(K=K.getChild(0));else{M!=R||b.equals(O[M])&&R<J?c&&(U=K.append(b.clone(0,g))):F?e(b, +K,!1,H):L&&K.append(a.document.createText(b.substring(0,z)));if(M>Z)for(;Y;)Y=e(Y,K,!0);K=U}l||f()}}function e(){var a=!1,c=CKEDITOR.dom.walker.whitespaces(),b=CKEDITOR.dom.walker.bookmark(!0),d=CKEDITOR.dom.walker.bogus();return function(g){return b(g)||c(g)?!0:d(g)&&!a?a=!0:g.type==CKEDITOR.NODE_TEXT&&(g.hasAscendant("pre")||CKEDITOR.tools.trim(g.getText()).length)||g.type==CKEDITOR.NODE_ELEMENT&&!g.is(l)?!1:!0}}function k(a){var c=CKEDITOR.dom.walker.whitespaces(),b=CKEDITOR.dom.walker.bookmark(1); +return function(d){return b(d)||c(d)?!0:!a&&m(d)||d.type==CKEDITOR.NODE_ELEMENT&&d.is(CKEDITOR.dtd.$removeEmpty)}}function d(a){return function(){var b;return this[a?"getPreviousNode":"getNextNode"](function(a){!b&&c(a)&&(b=a);return g(a)&&!(m(a)&&a.equals(b))})}}var l={abbr:1,acronym:1,b:1,bdo:1,big:1,cite:1,code:1,del:1,dfn:1,em:1,font:1,i:1,ins:1,label:1,kbd:1,q:1,samp:1,small:1,span:1,strike:1,strong:1,sub:1,sup:1,tt:1,u:1,"var":1},m=CKEDITOR.dom.walker.bogus(),b=/^[\t\r\n ]*(?: |\xa0)$/, g=CKEDITOR.dom.walker.editable(),c=CKEDITOR.dom.walker.ignored(!0);CKEDITOR.dom.range.prototype={clone:function(){var a=new CKEDITOR.dom.range(this.root);a._setStartContainer(this.startContainer);a.startOffset=this.startOffset;a._setEndContainer(this.endContainer);a.endOffset=this.endOffset;a.collapsed=this.collapsed;return a},collapse:function(a){a?(this._setEndContainer(this.startContainer),this.endOffset=this.startOffset):(this._setStartContainer(this.endContainer),this.startOffset=this.endOffset); -this.collapsed=!0},cloneContents:function(a){var c=new CKEDITOR.dom.documentFragment(this.document);this.collapsed||h(this,2,c,!1,"undefined"==typeof a?!0:a);return c},deleteContents:function(a){this.collapsed||h(this,0,null,a)},extractContents:function(a,c){var b=new CKEDITOR.dom.documentFragment(this.document);this.collapsed||h(this,1,b,a,"undefined"==typeof c?!0:c);return b},createBookmark:function(a){var c,b,g,d,e=this.collapsed;c=this.document.createElement("span");c.data("cke-bookmark",1);c.setStyle("display", -"none");c.setHtml("\x26nbsp;");a&&(g="cke_bm_"+CKEDITOR.tools.getNextNumber(),c.setAttribute("id",g+(e?"C":"S")));e||(b=c.clone(),b.setHtml("\x26nbsp;"),a&&b.setAttribute("id",g+"E"),d=this.clone(),d.collapse(),d.insertNode(b));d=this.clone();d.collapse(!0);d.insertNode(c);b?(this.setStartAfter(c),this.setEndBefore(b)):this.moveToPosition(c,CKEDITOR.POSITION_AFTER_END);return{startNode:a?g+(e?"C":"S"):c,endNode:a?g+"E":b,serializable:a,collapsed:e}},createBookmark2:function(){function a(a){var c= -a.container,g=a.offset,d;d=c;var e=g;d=d.type!=CKEDITOR.NODE_ELEMENT||0===e||e==d.getChildCount()?0:d.getChild(e-1).type==CKEDITOR.NODE_TEXT&&d.getChild(e).type==CKEDITOR.NODE_TEXT;d&&(c=c.getChild(g-1),g=c.getLength());if(c.type==CKEDITOR.NODE_ELEMENT&&0<g){a:{for(d=c;g--;)if(e=d.getChild(g).getIndex(!0),0<=e){g=e;break a}g=-1}g+=1}if(c.type==CKEDITOR.NODE_TEXT){d=c;for(e=0;(d=d.getPrevious())&&d.type==CKEDITOR.NODE_TEXT;)e+=d.getText().replace(CKEDITOR.dom.selection.FILLING_CHAR_SEQUENCE,"").length; -d=e;c.getText()?g+=d:(e=c.getPrevious(b),d?(g=d,c=e?e.getNext():c.getParent().getFirst()):(c=c.getParent(),g=e?e.getIndex(!0)+1:0))}a.container=c;a.offset=g}function c(a,b){var g=b.getCustomData("cke-fillingChar");if(g){var d=a.container;g.equals(d)&&(a.offset-=CKEDITOR.dom.selection.FILLING_CHAR_SEQUENCE.length,0>=a.offset&&(a.offset=d.getIndex(),a.container=d.getParent()))}}var b=CKEDITOR.dom.walker.nodeType(CKEDITOR.NODE_TEXT,!0);return function(b){var g=this.collapsed,d={container:this.startContainer, -offset:this.startOffset},e={container:this.endContainer,offset:this.endOffset};b&&(a(d),c(d,this.root),g||(a(e),c(e,this.root)));return{start:d.container.getAddress(b),end:g?null:e.container.getAddress(b),startOffset:d.offset,endOffset:e.offset,normalized:b,collapsed:g,is2:!0}}}(),moveToBookmark:function(a){if(a.is2){var c=this.document.getByAddress(a.start,a.normalized),b=a.startOffset,g=a.end&&this.document.getByAddress(a.end,a.normalized);a=a.endOffset;this.setStart(c,b);g?this.setEnd(g,a):this.collapse(!0)}else c= -(b=a.serializable)?this.document.getById(a.startNode):a.startNode,a=b?this.document.getById(a.endNode):a.endNode,this.setStartBefore(c),c.remove(),a?(this.setEndBefore(a),a.remove()):this.collapse(!0)},getBoundaryNodes:function(){var a=this.startContainer,c=this.endContainer,b=this.startOffset,g=this.endOffset,d;if(a.type==CKEDITOR.NODE_ELEMENT)if(d=a.getChildCount(),d>b)a=a.getChild(b);else if(1>d)a=a.getPreviousSourceNode();else{for(a=a.$;a.lastChild;)a=a.lastChild;a=new CKEDITOR.dom.node(a);a= -a.getNextSourceNode()||a}if(c.type==CKEDITOR.NODE_ELEMENT)if(d=c.getChildCount(),d>g)c=c.getChild(g).getPreviousSourceNode(!0);else if(1>d)c=c.getPreviousSourceNode();else{for(c=c.$;c.lastChild;)c=c.lastChild;c=new CKEDITOR.dom.node(c)}a.getPosition(c)&CKEDITOR.POSITION_FOLLOWING&&(a=c);return{startNode:a,endNode:c}},getCommonAncestor:function(a,c){var b=this.startContainer,g=this.endContainer,b=b.equals(g)?a&&b.type==CKEDITOR.NODE_ELEMENT&&this.startOffset==this.endOffset-1?b.getChild(this.startOffset): -b:b.getCommonAncestor(g);return c&&!b.is?b.getParent():b},optimize:function(){var a=this.startContainer,c=this.startOffset;a.type!=CKEDITOR.NODE_ELEMENT&&(c?c>=a.getLength()&&this.setStartAfter(a):this.setStartBefore(a));a=this.endContainer;c=this.endOffset;a.type!=CKEDITOR.NODE_ELEMENT&&(c?c>=a.getLength()&&this.setEndAfter(a):this.setEndBefore(a))},optimizeBookmark:function(){var a=this.startContainer,c=this.endContainer;a.is&&a.is("span")&&a.data("cke-bookmark")&&this.setStartAt(a,CKEDITOR.POSITION_BEFORE_START); -c&&c.is&&c.is("span")&&c.data("cke-bookmark")&&this.setEndAt(c,CKEDITOR.POSITION_AFTER_END)},trim:function(a,c){var b=this.startContainer,g=this.startOffset,d=this.collapsed;if((!a||d)&&b&&b.type==CKEDITOR.NODE_TEXT){if(g)if(g>=b.getLength())g=b.getIndex()+1,b=b.getParent();else{var e=b.split(g),g=b.getIndex()+1,b=b.getParent();this.startContainer.equals(this.endContainer)?this.setEnd(e,this.endOffset-this.startOffset):b.equals(this.endContainer)&&(this.endOffset+=1)}else g=b.getIndex(),b=b.getParent(); -this.setStart(b,g);if(d){this.collapse(!0);return}}b=this.endContainer;g=this.endOffset;c||d||!b||b.type!=CKEDITOR.NODE_TEXT||(g?(g>=b.getLength()||b.split(g),g=b.getIndex()+1):g=b.getIndex(),b=b.getParent(),this.setEnd(b,g))},enlarge:function(a,c){function b(a){return a&&a.type==CKEDITOR.NODE_ELEMENT&&a.hasAttribute("contenteditable")?null:a}var g=new RegExp(/[^\s\ufeff]/);switch(a){case CKEDITOR.ENLARGE_INLINE:var d=1;case CKEDITOR.ENLARGE_ELEMENT:var e=function(a,c){var b=new CKEDITOR.dom.range(f); -b.setStart(a,c);b.setEndAt(f,CKEDITOR.POSITION_BEFORE_END);var b=new CKEDITOR.dom.walker(b),d;for(b.guard=function(a){return!(a.type==CKEDITOR.NODE_ELEMENT&&a.isBlockBoundary())};d=b.next();){if(d.type!=CKEDITOR.NODE_TEXT)return!1;I=d!=a?d.getText():d.substring(c);if(g.test(I))return!1}return!0};if(this.collapsed)break;var k=this.getCommonAncestor(),f=this.root,h,m,l,t,B,y=!1,z,I;z=this.startContainer;var E=this.startOffset;z.type==CKEDITOR.NODE_TEXT?(E&&(z=!CKEDITOR.tools.trim(z.substring(0,E)).length&& -z,y=!!z),z&&((t=z.getPrevious())||(l=z.getParent()))):(E&&(t=z.getChild(E-1)||z.getLast()),t||(l=z));for(l=b(l);l||t;){if(l&&!t){!B&&l.equals(k)&&(B=!0);if(d?l.isBlockBoundary():!f.contains(l))break;y&&"inline"==l.getComputedStyle("display")||(y=!1,B?h=l:this.setStartBefore(l));t=l.getPrevious()}for(;t;)if(z=!1,t.type==CKEDITOR.NODE_COMMENT)t=t.getPrevious();else{if(t.type==CKEDITOR.NODE_TEXT)I=t.getText(),g.test(I)&&(t=null),z=/[\s\ufeff]$/.test(I);else if((t.$.offsetWidth>(CKEDITOR.env.webkit?1: -0)||c&&t.is("br"))&&!t.data("cke-bookmark"))if(y&&CKEDITOR.dtd.$removeEmpty[t.getName()]){I=t.getText();if(g.test(I))t=null;else for(var E=t.$.getElementsByTagName("*"),F=0,H;H=E[F++];)if(!CKEDITOR.dtd.$removeEmpty[H.nodeName.toLowerCase()]){t=null;break}t&&(z=!!I.length)}else t=null;z&&(y?B?h=l:l&&this.setStartBefore(l):y=!0);if(t){z=t.getPrevious();if(!l&&!z){l=t;t=null;break}t=z}else l=null}l&&(l=b(l.getParent()))}z=this.endContainer;E=this.endOffset;l=t=null;B=y=!1;z.type==CKEDITOR.NODE_TEXT? -CKEDITOR.tools.trim(z.substring(E)).length?y=!0:(y=!z.getLength(),E==z.getLength()?(t=z.getNext())||(l=z.getParent()):e(z,E)&&(l=z.getParent())):(t=z.getChild(E))||(l=z);for(;l||t;){if(l&&!t){!B&&l.equals(k)&&(B=!0);if(d?l.isBlockBoundary():!f.contains(l))break;y&&"inline"==l.getComputedStyle("display")||(y=!1,B?m=l:l&&this.setEndAfter(l));t=l.getNext()}for(;t;){z=!1;if(t.type==CKEDITOR.NODE_TEXT)I=t.getText(),e(t,0)||(t=null),z=/^[\s\ufeff]/.test(I);else if(t.type==CKEDITOR.NODE_ELEMENT){if((0<t.$.offsetWidth|| -c&&t.is("br"))&&!t.data("cke-bookmark"))if(y&&CKEDITOR.dtd.$removeEmpty[t.getName()]){I=t.getText();if(g.test(I))t=null;else for(E=t.$.getElementsByTagName("*"),F=0;H=E[F++];)if(!CKEDITOR.dtd.$removeEmpty[H.nodeName.toLowerCase()]){t=null;break}t&&(z=!!I.length)}else t=null}else z=1;z&&y&&(B?m=l:this.setEndAfter(l));if(t){z=t.getNext();if(!l&&!z){l=t;t=null;break}t=z}else l=null}l&&(l=b(l.getParent()))}h&&m&&(k=h.contains(m)?m:h,this.setStartBefore(k),this.setEndAfter(k));break;case CKEDITOR.ENLARGE_BLOCK_CONTENTS:case CKEDITOR.ENLARGE_LIST_ITEM_CONTENTS:l= -new CKEDITOR.dom.range(this.root);f=this.root;l.setStartAt(f,CKEDITOR.POSITION_AFTER_START);l.setEnd(this.startContainer,this.startOffset);l=new CKEDITOR.dom.walker(l);var G,L,O=CKEDITOR.dom.walker.blockBoundary(a==CKEDITOR.ENLARGE_LIST_ITEM_CONTENTS?{br:1}:null),C=null,S=function(a){if(a.type==CKEDITOR.NODE_ELEMENT&&"false"==a.getAttribute("contenteditable"))if(C){if(C.equals(a)){C=null;return}}else C=a;else if(C)return;var c=O(a);c||(G=a);return c},d=function(a){var c=S(a);!c&&a.is&&a.is("br")&& +this.collapsed=!0},cloneContents:function(a){var c=new CKEDITOR.dom.documentFragment(this.document);this.collapsed||h(this,2,c,!1,"undefined"==typeof a?!0:a);return c},deleteContents:function(a){this.collapsed||h(this,0,null,a)},extractContents:function(a,c){var b=new CKEDITOR.dom.documentFragment(this.document);this.collapsed||h(this,1,b,a,"undefined"==typeof c?!0:c);return b},createBookmark:function(a){var c,b,d,g,e=this.collapsed;c=this.document.createElement("span");c.data("cke-bookmark",1);c.setStyle("display", +"none");c.setHtml("\x26nbsp;");a&&(d="cke_bm_"+CKEDITOR.tools.getNextNumber(),c.setAttribute("id",d+(e?"C":"S")));e||(b=c.clone(),b.setHtml("\x26nbsp;"),a&&b.setAttribute("id",d+"E"),g=this.clone(),g.collapse(),g.insertNode(b));g=this.clone();g.collapse(!0);g.insertNode(c);b?(this.setStartAfter(c),this.setEndBefore(b)):this.moveToPosition(c,CKEDITOR.POSITION_AFTER_END);return{startNode:a?d+(e?"C":"S"):c,endNode:a?d+"E":b,serializable:a,collapsed:e}},createBookmark2:function(){function a(a){var c= +a.container,d=a.offset,g;g=c;var e=d;g=g.type!=CKEDITOR.NODE_ELEMENT||0===e||e==g.getChildCount()?0:g.getChild(e-1).type==CKEDITOR.NODE_TEXT&&g.getChild(e).type==CKEDITOR.NODE_TEXT;g&&(c=c.getChild(d-1),d=c.getLength());if(c.type==CKEDITOR.NODE_ELEMENT&&0<d){a:{for(g=c;d--;)if(e=g.getChild(d).getIndex(!0),0<=e){d=e;break a}d=-1}d+=1}if(c.type==CKEDITOR.NODE_TEXT){g=c;for(e=0;(g=g.getPrevious())&&g.type==CKEDITOR.NODE_TEXT;)e+=g.getText().replace(CKEDITOR.dom.selection.FILLING_CHAR_SEQUENCE,"").length; +g=e;c.getText()?d+=g:(e=c.getPrevious(b),g?(d=g,c=e?e.getNext():c.getParent().getFirst()):(c=c.getParent(),d=e?e.getIndex(!0)+1:0))}a.container=c;a.offset=d}function c(a,b){var d=b.getCustomData("cke-fillingChar");if(d){var g=a.container;d.equals(g)&&(a.offset-=CKEDITOR.dom.selection.FILLING_CHAR_SEQUENCE.length,0>=a.offset&&(a.offset=g.getIndex(),a.container=g.getParent()))}}var b=CKEDITOR.dom.walker.nodeType(CKEDITOR.NODE_TEXT,!0);return function(b){var d=this.collapsed,g={container:this.startContainer, +offset:this.startOffset},e={container:this.endContainer,offset:this.endOffset};b&&(a(g),c(g,this.root),d||(a(e),c(e,this.root)));return{start:g.container.getAddress(b),end:d?null:e.container.getAddress(b),startOffset:g.offset,endOffset:e.offset,normalized:b,collapsed:d,is2:!0}}}(),moveToBookmark:function(a){if(a.is2){var c=this.document.getByAddress(a.start,a.normalized),b=a.startOffset,d=a.end&&this.document.getByAddress(a.end,a.normalized);a=a.endOffset;this.setStart(c,b);d?this.setEnd(d,a):this.collapse(!0)}else c= +(b=a.serializable)?this.document.getById(a.startNode):a.startNode,a=b?this.document.getById(a.endNode):a.endNode,this.setStartBefore(c),c.remove(),a?(this.setEndBefore(a),a.remove()):this.collapse(!0)},getBoundaryNodes:function(){var a=this.startContainer,c=this.endContainer,b=this.startOffset,d=this.endOffset,g;if(a.type==CKEDITOR.NODE_ELEMENT)if(g=a.getChildCount(),g>b)a=a.getChild(b);else if(1>g)a=a.getPreviousSourceNode();else{for(a=a.$;a.lastChild;)a=a.lastChild;a=new CKEDITOR.dom.node(a);a= +a.getNextSourceNode()||a}if(c.type==CKEDITOR.NODE_ELEMENT)if(g=c.getChildCount(),g>d)c=c.getChild(d).getPreviousSourceNode(!0);else if(1>g)c=c.getPreviousSourceNode();else{for(c=c.$;c.lastChild;)c=c.lastChild;c=new CKEDITOR.dom.node(c)}a.getPosition(c)&CKEDITOR.POSITION_FOLLOWING&&(a=c);return{startNode:a,endNode:c}},getCommonAncestor:function(a,c){var b=this.startContainer,d=this.endContainer,b=b.equals(d)?a&&b.type==CKEDITOR.NODE_ELEMENT&&this.startOffset==this.endOffset-1?b.getChild(this.startOffset): +b:b.getCommonAncestor(d);return c&&!b.is?b.getParent():b},optimize:function(){var a=this.startContainer,c=this.startOffset;a.type!=CKEDITOR.NODE_ELEMENT&&(c?c>=a.getLength()&&this.setStartAfter(a):this.setStartBefore(a));a=this.endContainer;c=this.endOffset;a.type!=CKEDITOR.NODE_ELEMENT&&(c?c>=a.getLength()&&this.setEndAfter(a):this.setEndBefore(a))},optimizeBookmark:function(){var a=this.startContainer,c=this.endContainer;a.is&&a.is("span")&&a.data("cke-bookmark")&&this.setStartAt(a,CKEDITOR.POSITION_BEFORE_START); +c&&c.is&&c.is("span")&&c.data("cke-bookmark")&&this.setEndAt(c,CKEDITOR.POSITION_AFTER_END)},trim:function(a,c){var b=this.startContainer,d=this.startOffset,g=this.collapsed;if((!a||g)&&b&&b.type==CKEDITOR.NODE_TEXT){if(d)if(d>=b.getLength())d=b.getIndex()+1,b=b.getParent();else{var e=b.split(d),d=b.getIndex()+1,b=b.getParent();this.startContainer.equals(this.endContainer)?this.setEnd(e,this.endOffset-this.startOffset):b.equals(this.endContainer)&&(this.endOffset+=1)}else d=b.getIndex(),b=b.getParent(); +this.setStart(b,d);if(g){this.collapse(!0);return}}b=this.endContainer;d=this.endOffset;c||g||!b||b.type!=CKEDITOR.NODE_TEXT||(d?(d>=b.getLength()||b.split(d),d=b.getIndex()+1):d=b.getIndex(),b=b.getParent(),this.setEnd(b,d))},enlarge:function(a,c){function b(a){return a&&a.type==CKEDITOR.NODE_ELEMENT&&a.hasAttribute("contenteditable")?null:a}var d=new RegExp(/[^\s\ufeff]/);switch(a){case CKEDITOR.ENLARGE_INLINE:var g=1;case CKEDITOR.ENLARGE_ELEMENT:var e=function(a,c){var b=new CKEDITOR.dom.range(f); +b.setStart(a,c);b.setEndAt(f,CKEDITOR.POSITION_BEFORE_END);var b=new CKEDITOR.dom.walker(b),g;for(b.guard=function(a){return!(a.type==CKEDITOR.NODE_ELEMENT&&a.isBlockBoundary())};g=b.next();){if(g.type!=CKEDITOR.NODE_TEXT)return!1;I=g!=a?g.getText():g.substring(c);if(d.test(I))return!1}return!0};if(this.collapsed)break;var k=this.getCommonAncestor(),f=this.root,h,m,l,u,y,x=!1,z,I;z=this.startContainer;var F=this.startOffset;z.type==CKEDITOR.NODE_TEXT?(F&&(z=!CKEDITOR.tools.trim(z.substring(0,F)).length&& +z,x=!!z),z&&((u=z.getPrevious())||(l=z.getParent()))):(F&&(u=z.getChild(F-1)||z.getLast()),u||(l=z));for(l=b(l);l||u;){if(l&&!u){!y&&l.equals(k)&&(y=!0);if(g?l.isBlockBoundary():!f.contains(l))break;x&&"inline"==l.getComputedStyle("display")||(x=!1,y?h=l:this.setStartBefore(l));u=l.getPrevious()}for(;u;)if(z=!1,u.type==CKEDITOR.NODE_COMMENT)u=u.getPrevious();else{if(u.type==CKEDITOR.NODE_TEXT)I=u.getText(),d.test(I)&&(u=null),z=/[\s\ufeff]$/.test(I);else if((u.$.offsetWidth>(CKEDITOR.env.webkit?1: +0)||c&&u.is("br"))&&!u.data("cke-bookmark"))if(x&&CKEDITOR.dtd.$removeEmpty[u.getName()]){I=u.getText();if(d.test(I))u=null;else for(var F=u.$.getElementsByTagName("*"),E=0,H;H=F[E++];)if(!CKEDITOR.dtd.$removeEmpty[H.nodeName.toLowerCase()]){u=null;break}u&&(z=!!I.length)}else u=null;z&&(x?y?h=l:l&&this.setStartBefore(l):x=!0);if(u){z=u.getPrevious();if(!l&&!z){l=u;u=null;break}u=z}else l=null}l&&(l=b(l.getParent()))}z=this.endContainer;F=this.endOffset;l=u=null;y=x=!1;z.type==CKEDITOR.NODE_TEXT? +CKEDITOR.tools.trim(z.substring(F)).length?x=!0:(x=!z.getLength(),F==z.getLength()?(u=z.getNext())||(l=z.getParent()):e(z,F)&&(l=z.getParent())):(u=z.getChild(F))||(l=z);for(;l||u;){if(l&&!u){!y&&l.equals(k)&&(y=!0);if(g?l.isBlockBoundary():!f.contains(l))break;x&&"inline"==l.getComputedStyle("display")||(x=!1,y?m=l:l&&this.setEndAfter(l));u=l.getNext()}for(;u;){z=!1;if(u.type==CKEDITOR.NODE_TEXT)I=u.getText(),e(u,0)||(u=null),z=/^[\s\ufeff]/.test(I);else if(u.type==CKEDITOR.NODE_ELEMENT){if((0<u.$.offsetWidth|| +c&&u.is("br"))&&!u.data("cke-bookmark"))if(x&&CKEDITOR.dtd.$removeEmpty[u.getName()]){I=u.getText();if(d.test(I))u=null;else for(F=u.$.getElementsByTagName("*"),E=0;H=F[E++];)if(!CKEDITOR.dtd.$removeEmpty[H.nodeName.toLowerCase()]){u=null;break}u&&(z=!!I.length)}else u=null}else z=1;z&&x&&(y?m=l:this.setEndAfter(l));if(u){z=u.getNext();if(!l&&!z){l=u;u=null;break}u=z}else l=null}l&&(l=b(l.getParent()))}h&&m&&(k=h.contains(m)?m:h,this.setStartBefore(k),this.setEndAfter(k));break;case CKEDITOR.ENLARGE_BLOCK_CONTENTS:case CKEDITOR.ENLARGE_LIST_ITEM_CONTENTS:l= +new CKEDITOR.dom.range(this.root);f=this.root;l.setStartAt(f,CKEDITOR.POSITION_AFTER_START);l.setEnd(this.startContainer,this.startOffset);l=new CKEDITOR.dom.walker(l);var G,L,O=CKEDITOR.dom.walker.blockBoundary(a==CKEDITOR.ENLARGE_LIST_ITEM_CONTENTS?{br:1}:null),D=null,S=function(a){if(a.type==CKEDITOR.NODE_ELEMENT&&"false"==a.getAttribute("contenteditable"))if(D){if(D.equals(a)){D=null;return}}else D=a;else if(D)return;var c=O(a);c||(G=a);return c},g=function(a){var c=S(a);!c&&a.is&&a.is("br")&& (L=a);return c};l.guard=S;l=l.lastBackward();G=G||f;this.setStartAt(G,!G.is("br")&&(!l&&this.checkStartOfBlock()||l&&G.contains(l))?CKEDITOR.POSITION_AFTER_START:CKEDITOR.POSITION_AFTER_END);if(a==CKEDITOR.ENLARGE_LIST_ITEM_CONTENTS){l=this.clone();l=new CKEDITOR.dom.walker(l);var J=CKEDITOR.dom.walker.whitespaces(),R=CKEDITOR.dom.walker.bookmark();l.evaluator=function(a){return!J(a)&&!R(a)};if((l=l.previous())&&l.type==CKEDITOR.NODE_ELEMENT&&l.is("br"))break}l=this.clone();l.collapse();l.setEndAt(f, -CKEDITOR.POSITION_BEFORE_END);l=new CKEDITOR.dom.walker(l);l.guard=a==CKEDITOR.ENLARGE_LIST_ITEM_CONTENTS?d:S;G=C=L=null;l=l.lastForward();G=G||f;this.setEndAt(G,!l&&this.checkEndOfBlock()||l&&G.contains(l)?CKEDITOR.POSITION_BEFORE_END:CKEDITOR.POSITION_BEFORE_START);L&&this.setEndAfter(L)}},shrink:function(a,c,b){var g="boolean"===typeof b?b:b&&"boolean"===typeof b.shrinkOnBlockBoundary?b.shrinkOnBlockBoundary:!0,d=b&&b.skipBogus;if(!this.collapsed){a=a||CKEDITOR.SHRINK_TEXT;var e=this.clone(),k= -this.startContainer,f=this.endContainer,h=this.startOffset,l=this.endOffset,m=b=1;k&&k.type==CKEDITOR.NODE_TEXT&&(h?h>=k.getLength()?e.setStartAfter(k):(e.setStartBefore(k),b=0):e.setStartBefore(k));f&&f.type==CKEDITOR.NODE_TEXT&&(l?l>=f.getLength()?e.setEndAfter(f):(e.setEndAfter(f),m=0):e.setEndBefore(f));var e=new CKEDITOR.dom.walker(e),t=CKEDITOR.dom.walker.bookmark(),B=CKEDITOR.dom.walker.bogus();e.evaluator=function(c){return c.type==(a==CKEDITOR.SHRINK_ELEMENT?CKEDITOR.NODE_ELEMENT:CKEDITOR.NODE_TEXT)}; -var y;e.guard=function(c,b){if(d&&B(c)||t(c))return!0;if(a==CKEDITOR.SHRINK_ELEMENT&&c.type==CKEDITOR.NODE_TEXT||b&&c.equals(y)||!1===g&&c.type==CKEDITOR.NODE_ELEMENT&&c.isBlockBoundary()||c.type==CKEDITOR.NODE_ELEMENT&&c.hasAttribute("contenteditable"))return!1;b||c.type!=CKEDITOR.NODE_ELEMENT||(y=c);return!0};b&&(k=e[a==CKEDITOR.SHRINK_ELEMENT?"lastForward":"next"]())&&this.setStartAt(k,c?CKEDITOR.POSITION_AFTER_START:CKEDITOR.POSITION_BEFORE_START);m&&(e.reset(),(e=e[a==CKEDITOR.SHRINK_ELEMENT? +CKEDITOR.POSITION_BEFORE_END);l=new CKEDITOR.dom.walker(l);l.guard=a==CKEDITOR.ENLARGE_LIST_ITEM_CONTENTS?g:S;G=D=L=null;l=l.lastForward();G=G||f;this.setEndAt(G,!l&&this.checkEndOfBlock()||l&&G.contains(l)?CKEDITOR.POSITION_BEFORE_END:CKEDITOR.POSITION_BEFORE_START);L&&this.setEndAfter(L)}},shrink:function(a,c,b){var d="boolean"===typeof b?b:b&&"boolean"===typeof b.shrinkOnBlockBoundary?b.shrinkOnBlockBoundary:!0,g=b&&b.skipBogus;if(!this.collapsed){a=a||CKEDITOR.SHRINK_TEXT;var e=this.clone(),k= +this.startContainer,f=this.endContainer,h=this.startOffset,l=this.endOffset,m=b=1;k&&k.type==CKEDITOR.NODE_TEXT&&(h?h>=k.getLength()?e.setStartAfter(k):(e.setStartBefore(k),b=0):e.setStartBefore(k));f&&f.type==CKEDITOR.NODE_TEXT&&(l?l>=f.getLength()?e.setEndAfter(f):(e.setEndAfter(f),m=0):e.setEndBefore(f));var e=new CKEDITOR.dom.walker(e),u=CKEDITOR.dom.walker.bookmark(),y=CKEDITOR.dom.walker.bogus();e.evaluator=function(c){return c.type==(a==CKEDITOR.SHRINK_ELEMENT?CKEDITOR.NODE_ELEMENT:CKEDITOR.NODE_TEXT)}; +var x;e.guard=function(c,b){if(g&&y(c)||u(c))return!0;if(a==CKEDITOR.SHRINK_ELEMENT&&c.type==CKEDITOR.NODE_TEXT||b&&c.equals(x)||!1===d&&c.type==CKEDITOR.NODE_ELEMENT&&c.isBlockBoundary()||c.type==CKEDITOR.NODE_ELEMENT&&c.hasAttribute("contenteditable"))return!1;b||c.type!=CKEDITOR.NODE_ELEMENT||(x=c);return!0};b&&(k=e[a==CKEDITOR.SHRINK_ELEMENT?"lastForward":"next"]())&&this.setStartAt(k,c?CKEDITOR.POSITION_AFTER_START:CKEDITOR.POSITION_BEFORE_START);m&&(e.reset(),(e=e[a==CKEDITOR.SHRINK_ELEMENT? "lastBackward":"previous"]())&&this.setEndAt(e,c?CKEDITOR.POSITION_BEFORE_END:CKEDITOR.POSITION_AFTER_END));return!(!b&&!m)}},insertNode:function(a){this.optimizeBookmark();this.trim(!1,!0);var c=this.startContainer,b=c.getChild(this.startOffset);b?a.insertBefore(b):c.append(a);a.getParent()&&a.getParent().equals(this.endContainer)&&this.endOffset++;this.setStartBefore(a)},moveToPosition:function(a,c){this.setStartAt(a,c);this.collapse(!0)},moveToRange:function(a){this.setStart(a.startContainer,a.startOffset); this.setEnd(a.endContainer,a.endOffset)},selectNodeContents:function(a){this.setStart(a,0);this.setEnd(a,a.type==CKEDITOR.NODE_TEXT?a.getLength():a.getChildCount())},setStart:function(a,c){a.type==CKEDITOR.NODE_ELEMENT&&CKEDITOR.dtd.$empty[a.getName()]&&(c=a.getIndex(),a=a.getParent());this._setStartContainer(a);this.startOffset=c;this.endContainer||(this._setEndContainer(a),this.endOffset=c);f(this)},setEnd:function(a,c){a.type==CKEDITOR.NODE_ELEMENT&&CKEDITOR.dtd.$empty[a.getName()]&&(c=a.getIndex()+ 1,a=a.getParent());this._setEndContainer(a);this.endOffset=c;this.startContainer||(this._setStartContainer(a),this.startOffset=c);f(this)},setStartAfter:function(a){this.setStart(a.getParent(),a.getIndex()+1)},setStartBefore:function(a){this.setStart(a.getParent(),a.getIndex())},setEndAfter:function(a){this.setEnd(a.getParent(),a.getIndex()+1)},setEndBefore:function(a){this.setEnd(a.getParent(),a.getIndex())},setStartAt:function(a,c){switch(c){case CKEDITOR.POSITION_AFTER_START:this.setStart(a,0); break;case CKEDITOR.POSITION_BEFORE_END:a.type==CKEDITOR.NODE_TEXT?this.setStart(a,a.getLength()):this.setStart(a,a.getChildCount());break;case CKEDITOR.POSITION_BEFORE_START:this.setStartBefore(a);break;case CKEDITOR.POSITION_AFTER_END:this.setStartAfter(a)}f(this)},setEndAt:function(a,c){switch(c){case CKEDITOR.POSITION_AFTER_START:this.setEnd(a,0);break;case CKEDITOR.POSITION_BEFORE_END:a.type==CKEDITOR.NODE_TEXT?this.setEnd(a,a.getLength()):this.setEnd(a,a.getChildCount());break;case CKEDITOR.POSITION_BEFORE_START:this.setEndBefore(a); -break;case CKEDITOR.POSITION_AFTER_END:this.setEndAfter(a)}f(this)},fixBlock:function(a,c){var b=this.createBookmark(),g=this.document.createElement(c);this.collapse(a);this.enlarge(CKEDITOR.ENLARGE_BLOCK_CONTENTS);this.extractContents().appendTo(g);g.trim();this.insertNode(g);var d=g.getBogus();d&&d.remove();g.appendBogus();this.moveToBookmark(b);return g},splitBlock:function(a,c){var b=new CKEDITOR.dom.elementPath(this.startContainer,this.root),g=new CKEDITOR.dom.elementPath(this.endContainer,this.root), -d=b.block,e=g.block,k=null;if(!b.blockLimit.equals(g.blockLimit))return null;"br"!=a&&(d||(d=this.fixBlock(!0,a),e=(new CKEDITOR.dom.elementPath(this.endContainer,this.root)).block),e||(e=this.fixBlock(!1,a)));b=d&&this.checkStartOfBlock();g=e&&this.checkEndOfBlock();this.deleteContents();d&&d.equals(e)&&(g?(k=new CKEDITOR.dom.elementPath(this.startContainer,this.root),this.moveToPosition(e,CKEDITOR.POSITION_AFTER_END),e=null):b?(k=new CKEDITOR.dom.elementPath(this.startContainer,this.root),this.moveToPosition(d, -CKEDITOR.POSITION_BEFORE_START),d=null):(e=this.splitElement(d,c||!1),d.is("ul","ol")||d.appendBogus()));return{previousBlock:d,nextBlock:e,wasStartOfBlock:b,wasEndOfBlock:g,elementPath:k}},splitElement:function(a,c){if(!this.collapsed)return null;this.setEndAt(a,CKEDITOR.POSITION_BEFORE_END);var b=this.extractContents(!1,c||!1),g=a.clone(!1,c||!1);b.appendTo(g);g.insertAfter(a);this.moveToPosition(a,CKEDITOR.POSITION_AFTER_END);return g},removeEmptyBlocksAtEnd:function(){function a(a){return function(g){return c(g)|| -b(g)||g.type==CKEDITOR.NODE_ELEMENT&&g.isEmptyInlineRemoveable()||a.is("table")&&g.is("caption")?!1:!0}}var c=CKEDITOR.dom.walker.whitespaces(),b=CKEDITOR.dom.walker.bookmark(!1);return function(c){for(var b=this.createBookmark(),g=this[c?"endPath":"startPath"](),d=g.block||g.blockLimit,e;d&&!d.equals(g.root)&&!d.getFirst(a(d));)e=d.getParent(),this[c?"setEndAt":"setStartAt"](d,CKEDITOR.POSITION_AFTER_END),d.remove(1),d=e;this.moveToBookmark(b)}}(),startPath:function(){return new CKEDITOR.dom.elementPath(this.startContainer, -this.root)},endPath:function(){return new CKEDITOR.dom.elementPath(this.endContainer,this.root)},checkBoundaryOfElement:function(a,c){var b=c==CKEDITOR.START,g=this.clone();g.collapse(b);g[b?"setStartAt":"setEndAt"](a,b?CKEDITOR.POSITION_AFTER_START:CKEDITOR.POSITION_BEFORE_END);g=new CKEDITOR.dom.walker(g);g.evaluator=k(b);return g[b?"checkBackward":"checkForward"]()},checkStartOfBlock:function(){var a=this.startContainer,c=this.startOffset;CKEDITOR.env.ie&&c&&a.type==CKEDITOR.NODE_TEXT&&(a=CKEDITOR.tools.ltrim(a.substring(0, +break;case CKEDITOR.POSITION_AFTER_END:this.setEndAfter(a)}f(this)},fixBlock:function(a,c){var b=this.createBookmark(),d=this.document.createElement(c);this.collapse(a);this.enlarge(CKEDITOR.ENLARGE_BLOCK_CONTENTS);this.extractContents().appendTo(d);d.trim();this.insertNode(d);var g=d.getBogus();g&&g.remove();d.appendBogus();this.moveToBookmark(b);return d},splitBlock:function(a,c){var b=new CKEDITOR.dom.elementPath(this.startContainer,this.root),d=new CKEDITOR.dom.elementPath(this.endContainer,this.root), +g=b.block,e=d.block,k=null;if(!b.blockLimit.equals(d.blockLimit))return null;"br"!=a&&(g||(g=this.fixBlock(!0,a),e=(new CKEDITOR.dom.elementPath(this.endContainer,this.root)).block),e||(e=this.fixBlock(!1,a)));b=g&&this.checkStartOfBlock();d=e&&this.checkEndOfBlock();this.deleteContents();g&&g.equals(e)&&(d?(k=new CKEDITOR.dom.elementPath(this.startContainer,this.root),this.moveToPosition(e,CKEDITOR.POSITION_AFTER_END),e=null):b?(k=new CKEDITOR.dom.elementPath(this.startContainer,this.root),this.moveToPosition(g, +CKEDITOR.POSITION_BEFORE_START),g=null):(e=this.splitElement(g,c||!1),g.is("ul","ol")||g.appendBogus()));return{previousBlock:g,nextBlock:e,wasStartOfBlock:b,wasEndOfBlock:d,elementPath:k}},splitElement:function(a,c){if(!this.collapsed)return null;this.setEndAt(a,CKEDITOR.POSITION_BEFORE_END);var b=this.extractContents(!1,c||!1),d=a.clone(!1,c||!1);b.appendTo(d);d.insertAfter(a);this.moveToPosition(a,CKEDITOR.POSITION_AFTER_END);return d},removeEmptyBlocksAtEnd:function(){function a(a){return function(d){return c(d)|| +b(d)||d.type==CKEDITOR.NODE_ELEMENT&&d.isEmptyInlineRemoveable()||a.is("table")&&d.is("caption")?!1:!0}}var c=CKEDITOR.dom.walker.whitespaces(),b=CKEDITOR.dom.walker.bookmark(!1);return function(c){for(var b=this.createBookmark(),d=this[c?"endPath":"startPath"](),g=d.block||d.blockLimit,e;g&&!g.equals(d.root)&&!g.getFirst(a(g));)e=g.getParent(),this[c?"setEndAt":"setStartAt"](g,CKEDITOR.POSITION_AFTER_END),g.remove(1),g=e;this.moveToBookmark(b)}}(),startPath:function(){return new CKEDITOR.dom.elementPath(this.startContainer, +this.root)},endPath:function(){return new CKEDITOR.dom.elementPath(this.endContainer,this.root)},checkBoundaryOfElement:function(a,c){var b=c==CKEDITOR.START,d=this.clone();d.collapse(b);d[b?"setStartAt":"setEndAt"](a,b?CKEDITOR.POSITION_AFTER_START:CKEDITOR.POSITION_BEFORE_END);d=new CKEDITOR.dom.walker(d);d.evaluator=k(b);return d[b?"checkBackward":"checkForward"]()},checkStartOfBlock:function(){var a=this.startContainer,c=this.startOffset;CKEDITOR.env.ie&&c&&a.type==CKEDITOR.NODE_TEXT&&(a=CKEDITOR.tools.ltrim(a.substring(0, c)),b.test(a)&&this.trim(0,1));this.trim();a=new CKEDITOR.dom.elementPath(this.startContainer,this.root);c=this.clone();c.collapse(!0);c.setStartAt(a.block||a.blockLimit,CKEDITOR.POSITION_AFTER_START);a=new CKEDITOR.dom.walker(c);a.evaluator=e();return a.checkBackward()},checkEndOfBlock:function(){var a=this.endContainer,c=this.endOffset;CKEDITOR.env.ie&&a.type==CKEDITOR.NODE_TEXT&&(a=CKEDITOR.tools.rtrim(a.substring(c)),b.test(a)&&this.trim(1,0));this.trim();a=new CKEDITOR.dom.elementPath(this.endContainer, -this.root);c=this.clone();c.collapse(!1);c.setEndAt(a.block||a.blockLimit,CKEDITOR.POSITION_BEFORE_END);a=new CKEDITOR.dom.walker(c);a.evaluator=e();return a.checkForward()},getPreviousNode:function(a,c,b){var g=this.clone();g.collapse(1);g.setStartAt(b||this.root,CKEDITOR.POSITION_AFTER_START);b=new CKEDITOR.dom.walker(g);b.evaluator=a;b.guard=c;return b.previous()},getNextNode:function(a,c,b){var g=this.clone();g.collapse();g.setEndAt(b||this.root,CKEDITOR.POSITION_BEFORE_END);b=new CKEDITOR.dom.walker(g); -b.evaluator=a;b.guard=c;return b.next()},checkReadOnly:function(){function a(a,c){for(;a;){if(a.type==CKEDITOR.NODE_ELEMENT){if("false"==a.getAttribute("contentEditable")&&!a.data("cke-editable"))return 0;if(a.is("html")||"true"==a.getAttribute("contentEditable")&&(a.contains(c)||a.equals(c)))break}a=a.getParent()}return 1}return function(){var c=this.startContainer,b=this.endContainer;return!(a(c,b)&&a(b,c))}}(),moveToElementEditablePosition:function(a,g){if(a.type==CKEDITOR.NODE_ELEMENT&&!a.isEditable(!1))return this.moveToPosition(a, -g?CKEDITOR.POSITION_AFTER_END:CKEDITOR.POSITION_BEFORE_START),!0;for(var d=0;a;){if(a.type==CKEDITOR.NODE_TEXT){g&&this.endContainer&&this.checkEndOfBlock()&&b.test(a.getText())?this.moveToPosition(a,CKEDITOR.POSITION_BEFORE_START):this.moveToPosition(a,g?CKEDITOR.POSITION_AFTER_END:CKEDITOR.POSITION_BEFORE_START);d=1;break}if(a.type==CKEDITOR.NODE_ELEMENT)if(a.isEditable())this.moveToPosition(a,g?CKEDITOR.POSITION_BEFORE_END:CKEDITOR.POSITION_AFTER_START),d=1;else if(g&&a.is("br")&&this.endContainer&& -this.checkEndOfBlock())this.moveToPosition(a,CKEDITOR.POSITION_BEFORE_START);else if("false"==a.getAttribute("contenteditable")&&a.is(CKEDITOR.dtd.$block))return this.setStartBefore(a),this.setEndAfter(a),!0;var e=a,k=d,f=void 0;e.type==CKEDITOR.NODE_ELEMENT&&e.isEditable(!1)&&(f=e[g?"getLast":"getFirst"](c));k||f||(f=e[g?"getPrevious":"getNext"](c));a=f}return!!d},moveToClosestEditablePosition:function(a,c){var b,g=0,d,e,k=[CKEDITOR.POSITION_AFTER_END,CKEDITOR.POSITION_BEFORE_START];a?(b=new CKEDITOR.dom.range(this.root), -b.moveToPosition(a,k[c?0:1])):b=this.clone();if(a&&!a.is(CKEDITOR.dtd.$block))g=1;else if(d=b[c?"getNextEditableNode":"getPreviousEditableNode"]())g=1,(e=d.type==CKEDITOR.NODE_ELEMENT)&&d.is(CKEDITOR.dtd.$block)&&"false"==d.getAttribute("contenteditable")?(b.setStartAt(d,CKEDITOR.POSITION_BEFORE_START),b.setEndAt(d,CKEDITOR.POSITION_AFTER_END)):!CKEDITOR.env.needsBrFiller&&e&&d.is(CKEDITOR.dom.walker.validEmptyBlockContainers)?(b.setEnd(d,0),b.collapse()):b.moveToPosition(d,k[c?1:0]);g&&this.moveToRange(b); -return!!g},moveToElementEditStart:function(a){return this.moveToElementEditablePosition(a)},moveToElementEditEnd:function(a){return this.moveToElementEditablePosition(a,!0)},getEnclosedNode:function(){var a=this.clone();a.optimize();if(a.startContainer.type!=CKEDITOR.NODE_ELEMENT||a.endContainer.type!=CKEDITOR.NODE_ELEMENT)return null;var a=new CKEDITOR.dom.walker(a),c=CKEDITOR.dom.walker.bookmark(!1,!0),b=CKEDITOR.dom.walker.whitespaces(!0);a.evaluator=function(a){return b(a)&&c(a)};var g=a.next(); -a.reset();return g&&g.equals(a.previous())?g:null},getTouchedStartNode:function(){var a=this.startContainer;return this.collapsed||a.type!=CKEDITOR.NODE_ELEMENT?a:a.getChild(this.startOffset)||a},getTouchedEndNode:function(){var a=this.endContainer;return this.collapsed||a.type!=CKEDITOR.NODE_ELEMENT?a:a.getChild(this.endOffset-1)||a},getNextEditableNode:d(),getPreviousEditableNode:d(1),_getTableElement:function(a){a=a||{td:1,th:1,tr:1,tbody:1,thead:1,tfoot:1,table:1};var c=this.startContainer,b= -this.endContainer,g=c.getAscendant("table",!0),d=b.getAscendant("table",!0);return CKEDITOR.env.safari&&g&&b.equals(this.root)?c.getAscendant(a,!0):this.getEnclosedNode()?this.getEnclosedNode().getAscendant(a,!0):g&&d&&(g.equals(d)||g.contains(d)||d.contains(g))?c.getAscendant(a,!0):null},scrollIntoView:function(){var a=new CKEDITOR.dom.element.createFromHtml("\x3cspan\x3e\x26nbsp;\x3c/span\x3e",this.document),c,b,g,d=this.clone();d.optimize();(g=d.startContainer.type==CKEDITOR.NODE_TEXT)?(b=d.startContainer.getText(), -c=d.startContainer.split(d.startOffset),a.insertAfter(d.startContainer)):d.insertNode(a);a.scrollIntoView();g&&(d.startContainer.setText(b),c.remove());a.remove()},getClientRects:function(){function a(a,c){var b=CKEDITOR.tools.array.map(a,function(a){return a}),g=new CKEDITOR.dom.range(c.root),d,e,k;c.startContainer instanceof CKEDITOR.dom.element&&(e=0===c.startOffset&&c.startContainer.hasAttribute("data-widget"));c.endContainer instanceof CKEDITOR.dom.element&&(k=(k=c.endOffset===(c.endContainer.getChildCount? -c.endContainer.getChildCount():c.endContainer.length))&&c.endContainer.hasAttribute("data-widget"));e&&g.setStart(c.startContainer.getParent(),c.startContainer.getIndex());k&&g.setEnd(c.endContainer.getParent(),c.endContainer.getIndex()+1);if(e||k)c=g;g=c.cloneContents();g=CKEDITOR.dom.document.prototype.find.call(g,"[data-cke-widget-id]").toArray();if(g=CKEDITOR.tools.array.map(g,function(a){var b=c.root.editor;a=a.getAttribute("data-cke-widget-id");return b.widgets.instances[a].element}))return g= -CKEDITOR.tools.array.map(g,function(a){var c;c=a.getParent().hasClass("cke_widget_wrapper")?a.getParent():a;d=this.root.getDocument().$.createRange();d.setStart(c.getParent().$,c.getIndex());d.setEnd(c.getParent().$,c.getIndex()+1);c=d.getClientRects();c.widgetRect=a.getClientRect();return c},c),CKEDITOR.tools.array.forEach(g,function(a){function c(d){CKEDITOR.tools.array.forEach(b,function(c,e){var k=CKEDITOR.tools.objectCompare(a[d],c);k||(k=CKEDITOR.tools.objectCompare(a.widgetRect,c));k&&(Array.prototype.splice.call(b, -e,a.length-d,a.widgetRect),g=!0)});g||(d<b.length-1?c(d+1):b.push(a.widgetRect))}var g;c(0)}),b}function c(a,b,d){var e;b.collapsed?d.startContainer instanceof CKEDITOR.dom.element?(a=d.checkStartOfBlock(),e=new CKEDITOR.dom.text(""),a?d.startContainer.append(e,!0):0===d.startOffset?e.insertBefore(d.startContainer.getFirst()):(d=d.startContainer.getChildren().getItem(d.startOffset-1),e.insertAfter(d)),b.setStart(e.$,0),b.setEnd(e.$,0),a=b.getClientRects(),e.remove()):d.startContainer instanceof CKEDITOR.dom.text&& -(""===d.startContainer.getText()?(d.startContainer.setText(""),a=b.getClientRects(),d.startContainer.setText("")):a=[g(d.createBookmark())]):a=[g(d.createBookmark())];return a}function b(a,c,g){a=CKEDITOR.tools.extend({},a);c&&(a=CKEDITOR.tools.getAbsoluteRectPosition(g.document.getWindow(),a));!a.width&&(a.width=a.right-a.left);!a.height&&(a.height=a.bottom-a.top);return a}function g(a){var c=a.startNode;a=a.endNode;var b;c.setText("");c.removeStyle("display");a?(a.setText(""),a.removeStyle("display"), -b=[c.getClientRect(),a.getClientRect()],a.remove()):b=[c.getClientRect(),c.getClientRect()];c.remove();return{right:Math.max(b[0].right,b[1].right),bottom:Math.max(b[0].bottom,b[1].bottom),left:Math.min(b[0].left,b[1].left),top:Math.min(b[0].top,b[1].top),width:Math.abs(b[0].left-b[1].left),height:Math.max(b[0].bottom,b[1].bottom)-Math.min(b[0].top,b[1].top)}}return void 0!==this.document.getSelection?function(g){var d=this.root.getDocument().$.createRange(),e;d.setStart(this.startContainer.$,this.startOffset); -d.setEnd(this.endContainer.$,this.endOffset);e=d.getClientRects();e=a(e,this);e.length||(e=c(e,d,this));return CKEDITOR.tools.array.map(e,function(a){return b(a,g,this)},this)}:function(a){return[b(g(this.createBookmark()),a,this)]}}(),_setStartContainer:function(a){this.startContainer=a},_setEndContainer:function(a){this.endContainer=a},_find:function(a,c){var b=this.getCommonAncestor(),g=this.getBoundaryNodes(),d=[],e,k,f,h;if(b&&b.find)for(k=b.find(a),e=0;e<k.count();e++)if(b=k.getItem(e),c||!b.isReadOnly())f= -b.getPosition(g.startNode)&CKEDITOR.POSITION_FOLLOWING||g.startNode.equals(b),h=b.getPosition(g.endNode)&CKEDITOR.POSITION_PRECEDING+CKEDITOR.POSITION_IS_CONTAINED||g.endNode.equals(b),f&&h&&d.push(b);return d}};CKEDITOR.dom.range.mergeRanges=function(a){return CKEDITOR.tools.array.reduce(a,function(a,c){var b=a[a.length-1],g=!1;c=c.clone();c.enlarge(CKEDITOR.ENLARGE_ELEMENT);if(b){var d=new CKEDITOR.dom.range(c.root),g=new CKEDITOR.dom.walker(d),e=CKEDITOR.dom.walker.whitespaces();d.setStart(b.endContainer, -b.endOffset);d.setEnd(c.startContainer,c.startOffset);for(d=g.next();e(d)||c.endContainer.equals(d);)d=g.next();g=!d}g?b.setEnd(c.endContainer,c.endOffset):a.push(c);return a},[])}}(),CKEDITOR.POSITION_AFTER_START=1,CKEDITOR.POSITION_BEFORE_END=2,CKEDITOR.POSITION_BEFORE_START=3,CKEDITOR.POSITION_AFTER_END=4,CKEDITOR.ENLARGE_ELEMENT=1,CKEDITOR.ENLARGE_BLOCK_CONTENTS=2,CKEDITOR.ENLARGE_LIST_ITEM_CONTENTS=3,CKEDITOR.ENLARGE_INLINE=4,CKEDITOR.START=1,CKEDITOR.END=2,CKEDITOR.SHRINK_ELEMENT=1,CKEDITOR.SHRINK_TEXT= -2,"use strict",function(){function f(c){1>arguments.length||(this.range=c,this.forceBrBreak=0,this.enlargeBr=1,this.enforceRealBlocks=0,this._||(this._={}))}function h(c){var a=[];c.forEach(function(c){if("true"==c.getAttribute("contenteditable"))return a.push(c),!1},CKEDITOR.NODE_ELEMENT,!0);return a}function e(c,a,b,g){a:{null==g&&(g=h(b));for(var d;d=g.shift();)if(d.getDtd().p){g={element:d,remaining:g};break a}g=null}if(!g)return 0;if((d=CKEDITOR.filter.instances[g.element.data("cke-filter")])&& -!d.check(a))return e(c,a,b,g.remaining);a=new CKEDITOR.dom.range(g.element);a.selectNodeContents(g.element);a=a.createIterator();a.enlargeBr=c.enlargeBr;a.enforceRealBlocks=c.enforceRealBlocks;a.activeFilter=a.filter=d;c._.nestedEditable={element:g.element,container:b,remaining:g.remaining,iterator:a};return 1}function k(c,a,b){if(!a)return!1;c=c.clone();c.collapse(!b);return c.checkBoundaryOfElement(a,b?CKEDITOR.START:CKEDITOR.END)}var d=/^[\r\n\t ]+$/,l=CKEDITOR.dom.walker.bookmark(!1,!0),m=CKEDITOR.dom.walker.whitespaces(!0), -b=function(c){return l(c)&&m(c)},g={dd:1,dt:1,li:1};f.prototype={getNextParagraph:function(c){var a,f,h,m,p;c=c||"p";if(this._.nestedEditable){if(a=this._.nestedEditable.iterator.getNextParagraph(c))return this.activeFilter=this._.nestedEditable.iterator.activeFilter,a;this.activeFilter=this.filter;if(e(this,c,this._.nestedEditable.container,this._.nestedEditable.remaining))return this.activeFilter=this._.nestedEditable.iterator.activeFilter,this._.nestedEditable.iterator.getNextParagraph(c);this._.nestedEditable= -null}if(!this.range.root.getDtd()[c])return null;if(!this._.started){var r=this.range.clone();f=r.startPath();var q=r.endPath(),u=!r.collapsed&&k(r,f.block),x=!r.collapsed&&k(r,q.block,1);r.shrink(CKEDITOR.SHRINK_ELEMENT,!0);u&&r.setStartAt(f.block,CKEDITOR.POSITION_BEFORE_END);x&&r.setEndAt(q.block,CKEDITOR.POSITION_AFTER_START);f=r.endContainer.hasAscendant("pre",!0)||r.startContainer.hasAscendant("pre",!0);r.enlarge(this.forceBrBreak&&!f||!this.enlargeBr?CKEDITOR.ENLARGE_LIST_ITEM_CONTENTS:CKEDITOR.ENLARGE_BLOCK_CONTENTS); -r.collapsed||(f=new CKEDITOR.dom.walker(r.clone()),q=CKEDITOR.dom.walker.bookmark(!0,!0),f.evaluator=q,this._.nextNode=f.next(),f=new CKEDITOR.dom.walker(r.clone()),f.evaluator=q,f=f.previous(),this._.lastNode=f.getNextSourceNode(!0,null,r.root),this._.lastNode&&this._.lastNode.type==CKEDITOR.NODE_TEXT&&!CKEDITOR.tools.trim(this._.lastNode.getText())&&this._.lastNode.getParent().isBlockBoundary()&&(q=this.range.clone(),q.moveToPosition(this._.lastNode,CKEDITOR.POSITION_AFTER_END),q.checkEndOfBlock()&& -(q=new CKEDITOR.dom.elementPath(q.endContainer,q.root),this._.lastNode=(q.block||q.blockLimit).getNextSourceNode(!0))),this._.lastNode&&r.root.contains(this._.lastNode)||(this._.lastNode=this._.docEndMarker=r.document.createText(""),this._.lastNode.insertAfter(f)),r=null);this._.started=1;f=r}q=this._.nextNode;r=this._.lastNode;for(this._.nextNode=null;q;){var u=0,x=q.hasAscendant("pre"),A=q.type!=CKEDITOR.NODE_ELEMENT,D=0;if(A)q.type==CKEDITOR.NODE_TEXT&&d.test(q.getText())&&(A=0);else{var t=q.getName(); -if(CKEDITOR.dtd.$block[t]&&"false"==q.getAttribute("contenteditable")){a=q;e(this,c,a);break}else if(q.isBlockBoundary(this.forceBrBreak&&!x&&{br:1})){if("br"==t)A=1;else if(!f&&!q.getChildCount()&&"hr"!=t){a=q;h=q.equals(r);break}f&&(f.setEndAt(q,CKEDITOR.POSITION_BEFORE_START),"br"!=t&&(this._.nextNode=q));u=1}else{if(q.getFirst()){f||(f=this.range.clone(),f.setStartAt(q,CKEDITOR.POSITION_BEFORE_START));q=q.getFirst();continue}A=1}}A&&!f&&(f=this.range.clone(),f.setStartAt(q,CKEDITOR.POSITION_BEFORE_START)); -h=(!u||A)&&q.equals(r);if(f&&!u)for(;!q.getNext(b)&&!h;){t=q.getParent();if(t.isBlockBoundary(this.forceBrBreak&&!x&&{br:1})){u=1;A=0;h||t.equals(r);f.setEndAt(t,CKEDITOR.POSITION_BEFORE_END);break}q=t;A=1;h=q.equals(r);D=1}A&&f.setEndAt(q,CKEDITOR.POSITION_AFTER_END);q=this._getNextSourceNode(q,D,r);if((h=!q)||u&&f)break}if(!a){if(!f)return this._.docEndMarker&&this._.docEndMarker.remove(),this._.nextNode=null;a=new CKEDITOR.dom.elementPath(f.startContainer,f.root);q=a.blockLimit;u={div:1,th:1,td:1}; -a=a.block;!a&&q&&!this.enforceRealBlocks&&u[q.getName()]&&f.checkStartOfBlock()&&f.checkEndOfBlock()&&!q.equals(f.root)?a=q:!a||this.enforceRealBlocks&&a.is(g)?(a=this.range.document.createElement(c),f.extractContents().appendTo(a),a.trim(),f.insertNode(a),m=p=!0):"li"!=a.getName()?f.checkStartOfBlock()&&f.checkEndOfBlock()||(a=a.clone(!1),f.extractContents().appendTo(a),a.trim(),p=f.splitBlock(),m=!p.wasStartOfBlock,p=!p.wasEndOfBlock,f.insertNode(a)):h||(this._.nextNode=a.equals(r)?null:this._getNextSourceNode(f.getBoundaryNodes().endNode, -1,r))}m&&(m=a.getPrevious())&&m.type==CKEDITOR.NODE_ELEMENT&&("br"==m.getName()?m.remove():m.getLast()&&"br"==m.getLast().$.nodeName.toLowerCase()&&m.getLast().remove());p&&(m=a.getLast())&&m.type==CKEDITOR.NODE_ELEMENT&&"br"==m.getName()&&(!CKEDITOR.env.needsBrFiller||m.getPrevious(l)||m.getNext(l))&&m.remove();this._.nextNode||(this._.nextNode=h||a.equals(r)||!r?null:this._getNextSourceNode(a,1,r));return a},_getNextSourceNode:function(c,a,b){function g(a){return!(a.equals(b)||a.equals(d))}var d= -this.range.root;for(c=c.getNextSourceNode(a,null,g);!l(c);)c=c.getNextSourceNode(a,null,g);return c}};CKEDITOR.dom.range.prototype.createIterator=function(){return new f(this)}}(),CKEDITOR.command=function(f,h){this.uiItems=[];this.exec=function(e){if(this.state==CKEDITOR.TRISTATE_DISABLED||!this.checkAllowed())return!1;this.editorFocus&&f.focus();return!1===this.fire("exec")?!0:!1!==h.exec.call(this,f,e)};this.refresh=function(e,d){if(!this.readOnly&&e.readOnly)return!0;if(this.context&&!d.isContextFor(this.context)|| +this.root);c=this.clone();c.collapse(!1);c.setEndAt(a.block||a.blockLimit,CKEDITOR.POSITION_BEFORE_END);a=new CKEDITOR.dom.walker(c);a.evaluator=e();return a.checkForward()},getPreviousNode:function(a,c,b){var d=this.clone();d.collapse(1);d.setStartAt(b||this.root,CKEDITOR.POSITION_AFTER_START);b=new CKEDITOR.dom.walker(d);b.evaluator=a;b.guard=c;return b.previous()},getNextNode:function(a,c,b){var d=this.clone();d.collapse();d.setEndAt(b||this.root,CKEDITOR.POSITION_BEFORE_END);b=new CKEDITOR.dom.walker(d); +b.evaluator=a;b.guard=c;return b.next()},checkReadOnly:function(){function a(a,c){for(;a;){if(a.type==CKEDITOR.NODE_ELEMENT){if("false"==a.getAttribute("contentEditable")&&!a.data("cke-editable"))return 0;if(a.is("html")||"true"==a.getAttribute("contentEditable")&&(a.contains(c)||a.equals(c)))break}a=a.getParent()}return 1}return function(){var c=this.startContainer,b=this.endContainer;return!(a(c,b)&&a(b,c))}}(),moveToElementEditablePosition:function(a,d){if(a.type==CKEDITOR.NODE_ELEMENT&&!a.isEditable(!1))return this.moveToPosition(a, +d?CKEDITOR.POSITION_AFTER_END:CKEDITOR.POSITION_BEFORE_START),!0;for(var g=0;a;){if(a.type==CKEDITOR.NODE_TEXT){d&&this.endContainer&&this.checkEndOfBlock()&&b.test(a.getText())?this.moveToPosition(a,CKEDITOR.POSITION_BEFORE_START):this.moveToPosition(a,d?CKEDITOR.POSITION_AFTER_END:CKEDITOR.POSITION_BEFORE_START);g=1;break}if(a.type==CKEDITOR.NODE_ELEMENT)if(a.isEditable())this.moveToPosition(a,d?CKEDITOR.POSITION_BEFORE_END:CKEDITOR.POSITION_AFTER_START),g=1;else if(d&&a.is("br")&&this.endContainer&& +this.checkEndOfBlock())this.moveToPosition(a,CKEDITOR.POSITION_BEFORE_START);else if("false"==a.getAttribute("contenteditable")&&a.is(CKEDITOR.dtd.$block))return this.setStartBefore(a),this.setEndAfter(a),!0;var e=a,k=g,f=void 0;e.type==CKEDITOR.NODE_ELEMENT&&e.isEditable(!1)&&(f=e[d?"getLast":"getFirst"](c));k||f||(f=e[d?"getPrevious":"getNext"](c));a=f}return!!g},moveToClosestEditablePosition:function(a,c){var b,d=0,g,e,k=[CKEDITOR.POSITION_AFTER_END,CKEDITOR.POSITION_BEFORE_START];a?(b=new CKEDITOR.dom.range(this.root), +b.moveToPosition(a,k[c?0:1])):b=this.clone();if(a&&!a.is(CKEDITOR.dtd.$block))d=1;else if(g=b[c?"getNextEditableNode":"getPreviousEditableNode"]())d=1,(e=g.type==CKEDITOR.NODE_ELEMENT)&&g.is(CKEDITOR.dtd.$block)&&"false"==g.getAttribute("contenteditable")?(b.setStartAt(g,CKEDITOR.POSITION_BEFORE_START),b.setEndAt(g,CKEDITOR.POSITION_AFTER_END)):!CKEDITOR.env.needsBrFiller&&e&&g.is(CKEDITOR.dom.walker.validEmptyBlockContainers)?(b.setEnd(g,0),b.collapse()):b.moveToPosition(g,k[c?1:0]);d&&this.moveToRange(b); +return!!d},moveToElementEditStart:function(a){return this.moveToElementEditablePosition(a)},moveToElementEditEnd:function(a){return this.moveToElementEditablePosition(a,!0)},getEnclosedNode:function(){var a=this.clone();a.optimize();if(a.startContainer.type!=CKEDITOR.NODE_ELEMENT||a.endContainer.type!=CKEDITOR.NODE_ELEMENT)return null;var a=new CKEDITOR.dom.walker(a),c=CKEDITOR.dom.walker.bookmark(!1,!0),b=CKEDITOR.dom.walker.whitespaces(!0);a.evaluator=function(a){return b(a)&&c(a)};var d=a.next(); +a.reset();return d&&d.equals(a.previous())?d:null},getTouchedStartNode:function(){var a=this.startContainer;return this.collapsed||a.type!=CKEDITOR.NODE_ELEMENT?a:a.getChild(this.startOffset)||a},getTouchedEndNode:function(){var a=this.endContainer;return this.collapsed||a.type!=CKEDITOR.NODE_ELEMENT?a:a.getChild(this.endOffset-1)||a},getNextEditableNode:d(),getPreviousEditableNode:d(1),_getTableElement:function(a){a=a||{td:1,th:1,tr:1,tbody:1,thead:1,tfoot:1,table:1};var c=this.startContainer,b= +this.endContainer,d=c.getAscendant("table",!0),g=b.getAscendant("table",!0);return CKEDITOR.env.safari&&d&&b.equals(this.root)?c.getAscendant(a,!0):this.getEnclosedNode()?this.getEnclosedNode().getAscendant(a,!0):d&&g&&(d.equals(g)||d.contains(g)||g.contains(d))?c.getAscendant(a,!0):null},scrollIntoView:function(){var a=new CKEDITOR.dom.element.createFromHtml("\x3cspan\x3e\x26nbsp;\x3c/span\x3e",this.document),c,b,d,g=this.clone();g.optimize();(d=g.startContainer.type==CKEDITOR.NODE_TEXT)?(b=g.startContainer.getText(), +c=g.startContainer.split(g.startOffset),a.insertAfter(g.startContainer)):g.insertNode(a);a.scrollIntoView();d&&(g.startContainer.setText(b),c.remove());a.remove()},getClientRects:function(){function a(a,c){var b=CKEDITOR.tools.array.map(a,function(a){return a}),d=new CKEDITOR.dom.range(c.root),g,e,k;c.startContainer instanceof CKEDITOR.dom.element&&(e=0===c.startOffset&&c.startContainer.hasAttribute("data-widget"));c.endContainer instanceof CKEDITOR.dom.element&&(k=(k=c.endOffset===(c.endContainer.getChildCount? +c.endContainer.getChildCount():c.endContainer.length))&&c.endContainer.hasAttribute("data-widget"));e&&d.setStart(c.startContainer.getParent(),c.startContainer.getIndex());k&&d.setEnd(c.endContainer.getParent(),c.endContainer.getIndex()+1);if(e||k)c=d;d=c.cloneContents();d=CKEDITOR.dom.document.prototype.find.call(d,"[data-cke-widget-id]").toArray();if(d=CKEDITOR.tools.array.map(d,function(a){var b=c.root.editor;a=a.getAttribute("data-cke-widget-id");return b.widgets.instances[a].element}))return d= +CKEDITOR.tools.array.map(d,function(a){var c;c=a.getParent().hasClass("cke_widget_wrapper")?a.getParent():a;g=this.root.getDocument().$.createRange();g.setStart(c.getParent().$,c.getIndex());g.setEnd(c.getParent().$,c.getIndex()+1);c=g.getClientRects();c.widgetRect=a.getClientRect();return c},c),CKEDITOR.tools.array.forEach(d,function(a){function c(g){CKEDITOR.tools.array.forEach(b,function(c,e){var k=CKEDITOR.tools.objectCompare(a[g],c);k||(k=CKEDITOR.tools.objectCompare(a.widgetRect,c));k&&(Array.prototype.splice.call(b, +e,a.length-g,a.widgetRect),d=!0)});d||(g<b.length-1?c(g+1):b.push(a.widgetRect))}var d;c(0)}),b}function c(a,b,g){var e;b.collapsed?g.startContainer instanceof CKEDITOR.dom.element?(a=g.checkStartOfBlock(),e=new CKEDITOR.dom.text(""),a?g.startContainer.append(e,!0):0===g.startOffset?e.insertBefore(g.startContainer.getFirst()):(g=g.startContainer.getChildren().getItem(g.startOffset-1),e.insertAfter(g)),b.setStart(e.$,0),b.setEnd(e.$,0),a=b.getClientRects(),e.remove()):g.startContainer instanceof CKEDITOR.dom.text&& +(""===g.startContainer.getText()?(g.startContainer.setText(""),a=b.getClientRects(),g.startContainer.setText("")):a=[d(g.createBookmark())]):a=[d(g.createBookmark())];return a}function b(a,c,d){a=CKEDITOR.tools.extend({},a);c&&(a=CKEDITOR.tools.getAbsoluteRectPosition(d.document.getWindow(),a));!a.width&&(a.width=a.right-a.left);!a.height&&(a.height=a.bottom-a.top);return a}function d(a){var c=a.startNode;a=a.endNode;var b;c.setText("");c.removeStyle("display");a?(a.setText(""),a.removeStyle("display"), +b=[c.getClientRect(),a.getClientRect()],a.remove()):b=[c.getClientRect(),c.getClientRect()];c.remove();return{right:Math.max(b[0].right,b[1].right),bottom:Math.max(b[0].bottom,b[1].bottom),left:Math.min(b[0].left,b[1].left),top:Math.min(b[0].top,b[1].top),width:Math.abs(b[0].left-b[1].left),height:Math.max(b[0].bottom,b[1].bottom)-Math.min(b[0].top,b[1].top)}}return void 0!==this.document.getSelection?function(d){var g=this.root.getDocument().$.createRange(),e;g.setStart(this.startContainer.$,this.startOffset); +g.setEnd(this.endContainer.$,this.endOffset);e=g.getClientRects();e=a(e,this);e.length||(e=c(e,g,this));return CKEDITOR.tools.array.map(e,function(a){return b(a,d,this)},this)}:function(a){return[b(d(this.createBookmark()),a,this)]}}(),_setStartContainer:function(a){this.startContainer=a},_setEndContainer:function(a){this.endContainer=a},_find:function(a,c){var b=this.getCommonAncestor(),d=this.getBoundaryNodes(),g=[],e,k,f,h;if(b&&b.find)for(k=b.find(a),e=0;e<k.count();e++)if(b=k.getItem(e),c||!b.isReadOnly())f= +b.getPosition(d.startNode)&CKEDITOR.POSITION_FOLLOWING||d.startNode.equals(b),h=b.getPosition(d.endNode)&CKEDITOR.POSITION_PRECEDING+CKEDITOR.POSITION_IS_CONTAINED||d.endNode.equals(b),f&&h&&g.push(b);return g}};CKEDITOR.dom.range.mergeRanges=function(a){return CKEDITOR.tools.array.reduce(a,function(a,c){var b=a[a.length-1],d=!1;c=c.clone();c.enlarge(CKEDITOR.ENLARGE_ELEMENT);if(b){var g=new CKEDITOR.dom.range(c.root),d=new CKEDITOR.dom.walker(g),e=CKEDITOR.dom.walker.whitespaces();g.setStart(b.endContainer, +b.endOffset);g.setEnd(c.startContainer,c.startOffset);for(g=d.next();e(g)||c.endContainer.equals(g);)g=d.next();d=!g}d?b.setEnd(c.endContainer,c.endOffset):a.push(c);return a},[])}}(),CKEDITOR.POSITION_AFTER_START=1,CKEDITOR.POSITION_BEFORE_END=2,CKEDITOR.POSITION_BEFORE_START=3,CKEDITOR.POSITION_AFTER_END=4,CKEDITOR.ENLARGE_ELEMENT=1,CKEDITOR.ENLARGE_BLOCK_CONTENTS=2,CKEDITOR.ENLARGE_LIST_ITEM_CONTENTS=3,CKEDITOR.ENLARGE_INLINE=4,CKEDITOR.START=1,CKEDITOR.END=2,CKEDITOR.SHRINK_ELEMENT=1,CKEDITOR.SHRINK_TEXT= +2,"use strict",function(){function f(c){1>arguments.length||(this.range=c,this.forceBrBreak=0,this.enlargeBr=1,this.enforceRealBlocks=0,this._||(this._={}))}function h(c){var a=[];c.forEach(function(c){if("true"==c.getAttribute("contenteditable"))return a.push(c),!1},CKEDITOR.NODE_ELEMENT,!0);return a}function e(c,a,b,d){a:{null==d&&(d=h(b));for(var g;g=d.shift();)if(g.getDtd().p){d={element:g,remaining:d};break a}d=null}if(!d)return 0;if((g=CKEDITOR.filter.instances[d.element.data("cke-filter")])&& +!g.check(a))return e(c,a,b,d.remaining);a=new CKEDITOR.dom.range(d.element);a.selectNodeContents(d.element);a=a.createIterator();a.enlargeBr=c.enlargeBr;a.enforceRealBlocks=c.enforceRealBlocks;a.activeFilter=a.filter=g;c._.nestedEditable={element:d.element,container:b,remaining:d.remaining,iterator:a};return 1}function k(c,a,b){if(!a)return!1;c=c.clone();c.collapse(!b);return c.checkBoundaryOfElement(a,b?CKEDITOR.START:CKEDITOR.END)}var d=/^[\r\n\t ]+$/,l=CKEDITOR.dom.walker.bookmark(!1,!0),m=CKEDITOR.dom.walker.whitespaces(!0), +b=function(c){return l(c)&&m(c)},g={dd:1,dt:1,li:1};f.prototype={getNextParagraph:function(c){var a,f,h,m,t;c=c||"p";if(this._.nestedEditable){if(a=this._.nestedEditable.iterator.getNextParagraph(c))return this.activeFilter=this._.nestedEditable.iterator.activeFilter,a;this.activeFilter=this.filter;if(e(this,c,this._.nestedEditable.container,this._.nestedEditable.remaining))return this.activeFilter=this._.nestedEditable.iterator.activeFilter,this._.nestedEditable.iterator.getNextParagraph(c);this._.nestedEditable= +null}if(!this.range.root.getDtd()[c])return null;if(!this._.started){var p=this.range.clone();f=p.startPath();var q=p.endPath(),A=!p.collapsed&&k(p,f.block),r=!p.collapsed&&k(p,q.block,1);p.shrink(CKEDITOR.SHRINK_ELEMENT,!0);A&&p.setStartAt(f.block,CKEDITOR.POSITION_BEFORE_END);r&&p.setEndAt(q.block,CKEDITOR.POSITION_AFTER_START);f=p.endContainer.hasAscendant("pre",!0)||p.startContainer.hasAscendant("pre",!0);p.enlarge(this.forceBrBreak&&!f||!this.enlargeBr?CKEDITOR.ENLARGE_LIST_ITEM_CONTENTS:CKEDITOR.ENLARGE_BLOCK_CONTENTS); +p.collapsed||(f=new CKEDITOR.dom.walker(p.clone()),q=CKEDITOR.dom.walker.bookmark(!0,!0),f.evaluator=q,this._.nextNode=f.next(),f=new CKEDITOR.dom.walker(p.clone()),f.evaluator=q,f=f.previous(),this._.lastNode=f.getNextSourceNode(!0,null,p.root),this._.lastNode&&this._.lastNode.type==CKEDITOR.NODE_TEXT&&!CKEDITOR.tools.trim(this._.lastNode.getText())&&this._.lastNode.getParent().isBlockBoundary()&&(q=this.range.clone(),q.moveToPosition(this._.lastNode,CKEDITOR.POSITION_AFTER_END),q.checkEndOfBlock()&& +(q=new CKEDITOR.dom.elementPath(q.endContainer,q.root),this._.lastNode=(q.block||q.blockLimit).getNextSourceNode(!0))),this._.lastNode&&p.root.contains(this._.lastNode)||(this._.lastNode=this._.docEndMarker=p.document.createText(""),this._.lastNode.insertAfter(f)),p=null);this._.started=1;f=p}q=this._.nextNode;p=this._.lastNode;for(this._.nextNode=null;q;){var A=0,r=q.hasAscendant("pre"),C=q.type!=CKEDITOR.NODE_ELEMENT,B=0;if(C)q.type==CKEDITOR.NODE_TEXT&&d.test(q.getText())&&(C=0);else{var u=q.getName(); +if(CKEDITOR.dtd.$block[u]&&"false"==q.getAttribute("contenteditable")){a=q;e(this,c,a);break}else if(q.isBlockBoundary(this.forceBrBreak&&!r&&{br:1})){if("br"==u)C=1;else if(!f&&!q.getChildCount()&&"hr"!=u){a=q;h=q.equals(p);break}f&&(f.setEndAt(q,CKEDITOR.POSITION_BEFORE_START),"br"!=u&&(this._.nextNode=q));A=1}else{if(q.getFirst()){f||(f=this.range.clone(),f.setStartAt(q,CKEDITOR.POSITION_BEFORE_START));q=q.getFirst();continue}C=1}}C&&!f&&(f=this.range.clone(),f.setStartAt(q,CKEDITOR.POSITION_BEFORE_START)); +h=(!A||C)&&q.equals(p);if(f&&!A)for(;!q.getNext(b)&&!h;){u=q.getParent();if(u.isBlockBoundary(this.forceBrBreak&&!r&&{br:1})){A=1;C=0;h||u.equals(p);f.setEndAt(u,CKEDITOR.POSITION_BEFORE_END);break}q=u;C=1;h=q.equals(p);B=1}C&&f.setEndAt(q,CKEDITOR.POSITION_AFTER_END);q=this._getNextSourceNode(q,B,p);if((h=!q)||A&&f)break}if(!a){if(!f)return this._.docEndMarker&&this._.docEndMarker.remove(),this._.nextNode=null;a=new CKEDITOR.dom.elementPath(f.startContainer,f.root);q=a.blockLimit;A={div:1,th:1,td:1}; +a=a.block;!a&&q&&!this.enforceRealBlocks&&A[q.getName()]&&f.checkStartOfBlock()&&f.checkEndOfBlock()&&!q.equals(f.root)?a=q:!a||this.enforceRealBlocks&&a.is(g)?(a=this.range.document.createElement(c),f.extractContents().appendTo(a),a.trim(),f.insertNode(a),m=t=!0):"li"!=a.getName()?f.checkStartOfBlock()&&f.checkEndOfBlock()||(a=a.clone(!1),f.extractContents().appendTo(a),a.trim(),t=f.splitBlock(),m=!t.wasStartOfBlock,t=!t.wasEndOfBlock,f.insertNode(a)):h||(this._.nextNode=a.equals(p)?null:this._getNextSourceNode(f.getBoundaryNodes().endNode, +1,p))}m&&(m=a.getPrevious())&&m.type==CKEDITOR.NODE_ELEMENT&&("br"==m.getName()?m.remove():m.getLast()&&"br"==m.getLast().$.nodeName.toLowerCase()&&m.getLast().remove());t&&(m=a.getLast())&&m.type==CKEDITOR.NODE_ELEMENT&&"br"==m.getName()&&(!CKEDITOR.env.needsBrFiller||m.getPrevious(l)||m.getNext(l))&&m.remove();this._.nextNode||(this._.nextNode=h||a.equals(p)||!p?null:this._getNextSourceNode(a,1,p));return a},_getNextSourceNode:function(c,a,b){function d(a){return!(a.equals(b)||a.equals(g))}var g= +this.range.root;for(c=c.getNextSourceNode(a,null,d);!l(c);)c=c.getNextSourceNode(a,null,d);return c}};CKEDITOR.dom.range.prototype.createIterator=function(){return new f(this)}}(),CKEDITOR.command=function(f,h){this.uiItems=[];this.exec=function(e){if(this.state==CKEDITOR.TRISTATE_DISABLED||!this.checkAllowed())return!1;this.editorFocus&&f.focus();return!1===this.fire("exec")?!0:!1!==h.exec.call(this,f,e)};this.refresh=function(e,d){if(!this.readOnly&&e.readOnly)return!0;if(this.context&&!d.isContextFor(this.context)|| !this.checkAllowed(!0))return this.disable(),!0;this.startDisabled||this.enable();this.modes&&!this.modes[e.mode]&&this.disable();return!1===this.fire("refresh",{editor:e,path:d})?!0:h.refresh&&!1!==h.refresh.apply(this,arguments)};var e;this.checkAllowed=function(k){return k||"boolean"!=typeof e?e=f.activeFilter.checkFeature(this):e};CKEDITOR.tools.extend(this,h,{modes:{wysiwyg:1},editorFocus:1,contextSensitive:!!h.context,state:CKEDITOR.TRISTATE_DISABLED});CKEDITOR.event.call(this)},CKEDITOR.command.prototype= {enable:function(){this.state==CKEDITOR.TRISTATE_DISABLED&&this.checkAllowed()&&this.setState(this.preserveState&&"undefined"!=typeof this.previousState?this.previousState:CKEDITOR.TRISTATE_OFF)},disable:function(){this.setState(CKEDITOR.TRISTATE_DISABLED)},setState:function(f){if(this.state==f||f!=CKEDITOR.TRISTATE_DISABLED&&!this.checkAllowed())return!1;this.previousState=this.state;this.state=f;this.fire("state");return!0},toggleState:function(){this.state==CKEDITOR.TRISTATE_OFF?this.setState(CKEDITOR.TRISTATE_ON): this.state==CKEDITOR.TRISTATE_ON&&this.setState(CKEDITOR.TRISTATE_OFF)}},CKEDITOR.event.implementOn(CKEDITOR.command.prototype),CKEDITOR.ENTER_P=1,CKEDITOR.ENTER_BR=2,CKEDITOR.ENTER_DIV=3,CKEDITOR.config={customConfig:"config.js",autoUpdateElement:!0,language:"",defaultLanguage:"en",contentsLangDirection:"",enterMode:CKEDITOR.ENTER_P,forceEnterMode:!1,shiftEnterMode:CKEDITOR.ENTER_BR,docType:"\x3c!DOCTYPE html\x3e",bodyId:"",bodyClass:"",fullPage:!1,height:200,contentsCss:CKEDITOR.getUrl("contents.css"), -extraPlugins:"",removePlugins:"",protectedSource:[],tabIndex:0,width:"",baseFloatZIndex:1E4,blockedKeystrokes:[CKEDITOR.CTRL+66,CKEDITOR.CTRL+73,CKEDITOR.CTRL+85]},function(){function f(a,c,b,g,d){var e,f;a=[];for(e in c){f=c[e];f="boolean"==typeof f?{}:"function"==typeof f?{match:f}:F(f);"$"!=e.charAt(0)&&(f.elements=e);b&&(f.featureName=b.toLowerCase());var k=f;k.elements=m(k.elements,/\s+/)||null;k.propertiesOnly=k.propertiesOnly||!0===k.elements;var h=/\s*,\s*/,n=void 0;for(n in L){k[n]=m(k[n], -h)||null;var l=k,q=O[n],t=m(k[O[n]],h),C=k[n],D=[],J=!0,r=void 0;t?J=!1:t={};for(r in C)"!"==r.charAt(0)&&(r=r.slice(1),D.push(r),t[r]=!0,J=!1);for(;r=D.pop();)C[r]=C["!"+r],delete C["!"+r];l[q]=(J?!1:t)||null}k.match=k.match||null;g.push(f);a.push(f)}c=d.elements;d=d.generic;var w;b=0;for(g=a.length;b<g;++b){e=F(a[b]);f=!0===e.classes||!0===e.styles||!0===e.attributes;k=e;n=q=h=void 0;for(h in L)k[h]=u(k[h]);l=!0;for(n in O){h=O[n];q=k[h];t=[];C=void 0;for(C in q)-1<C.indexOf("*")?t.push(new RegExp("^"+ -C.replace(/\*/g,".*")+"$")):t.push(C);q=t;q.length&&(k[h]=q,l=!1)}k.nothingRequired=l;k.noProperties=!(k.attributes||k.classes||k.styles);if(!0===e.elements||null===e.elements)d[f?"unshift":"push"](e);else for(w in k=e.elements,delete e.elements,k)if(c[w])c[w][f?"unshift":"push"](e);else c[w]=[e]}}function h(a,c,g,d){if(!a.match||a.match(c))if(d||b(a,c))if(a.propertiesOnly||(g.valid=!0),g.allAttributes||(g.allAttributes=e(a.attributes,c.attributes,g.validAttributes)),g.allStyles||(g.allStyles=e(a.styles, -c.styles,g.validStyles)),!g.allClasses){a=a.classes;c=c.classes;d=g.validClasses;if(a)if(!0===a)a=!0;else{for(var f=0,k=c.length,h;f<k;++f)h=c[f],d[h]||(d[h]=a(h));a=!1}else a=!1;g.allClasses=a}}function e(a,c,b){if(!a)return!1;if(!0===a)return!0;for(var g in c)b[g]||(b[g]=a(g));return!1}function k(a,c,b){if(!a.match||a.match(c)){if(a.noProperties)return!1;b.hadInvalidAttribute=d(a.attributes,c.attributes)||b.hadInvalidAttribute;b.hadInvalidStyle=d(a.styles,c.styles)||b.hadInvalidStyle;a=a.classes; -c=c.classes;if(a){for(var g=!1,e=!0===a,f=c.length;f--;)if(e||a(c[f]))c.splice(f,1),g=!0;a=g}else a=!1;b.hadInvalidClass=a||b.hadInvalidClass}}function d(a,c){if(!a)return!1;var b=!1,g=!0===a,d;for(d in c)if(g||a(d))delete c[d],b=!0;return b}function l(a,c,b){if(a.disabled||a.customConfig&&!b||!c)return!1;a._.cachedChecks={};return!0}function m(a,c){if(!a)return!1;if(!0===a)return a;if("string"==typeof a)return a=H(a),"*"==a?!0:CKEDITOR.tools.convertArrayToObject(a.split(c));if(CKEDITOR.tools.isArray(a))return a.length? -CKEDITOR.tools.convertArrayToObject(a):!1;var b={},g=0,d;for(d in a)b[d]=a[d],g++;return g?b:!1}function b(a,c){if(a.nothingRequired)return!0;var b,d,e,f;if(e=a.requiredClasses)for(f=c.classes,b=0;b<e.length;++b)if(d=e[b],"string"==typeof d){if(-1==CKEDITOR.tools.indexOf(f,d))return!1}else if(!CKEDITOR.tools.checkIfAnyArrayItemMatches(f,d))return!1;return g(c.styles,a.requiredStyles)&&g(c.attributes,a.requiredAttributes)}function g(a,c){if(!c)return!0;for(var b=0,g;b<c.length;++b)if(g=c[b],"string"== -typeof g){if(!(g in a))return!1}else if(!CKEDITOR.tools.checkIfAnyObjectPropertyMatches(a,g))return!1;return!0}function c(a){if(!a)return{};a=a.split(/\s*,\s*/).sort();for(var c={};a.length;)c[a.shift()]="cke-test";return c}function a(a){var c,b,g,d,e={},f=1;for(a=H(a);c=a.match(C);)(b=c[2])?(g=n(b,"styles"),d=n(b,"attrs"),b=n(b,"classes")):g=d=b=null,e["$"+f++]={elements:c[1],classes:b,styles:g,attributes:d},a=a.slice(c[0].length);return e}function n(a,c){var b=a.match(S[c]);return b?H(b[1]):null} -function w(a){var c=a.styleBackup=a.attributes.style,b=a.classBackup=a.attributes["class"];a.styles||(a.styles=CKEDITOR.tools.parseCssText(c||"",1));a.classes||(a.classes=b?b.split(/\s+/):[])}function v(a,c,b,g){var d=0,e;g.toHtml&&(c.name=c.name.replace(J,"$1"));if(g.doCallbacks&&a.elementCallbacks){a:{e=a.elementCallbacks;for(var f=0,n=e.length,l;f<n;++f)if(l=e[f](c)){e=l;break a}e=void 0}if(e)return e}if(g.doTransform&&(e=a._.transformations[c.name])){w(c);for(f=0;f<e.length;++f)t(a,c,e[f]);r(c)}if(g.doFilter){a:{f= -c.name;n=a._;a=n.allowedRules.elements[f];e=n.allowedRules.generic;f=n.disallowedRules.elements[f];n=n.disallowedRules.generic;l=g.skipRequired;var m={valid:!1,validAttributes:{},validClasses:{},validStyles:{},allAttributes:!1,allClasses:!1,allStyles:!1,hadInvalidAttribute:!1,hadInvalidClass:!1,hadInvalidStyle:!1},C,D;if(a||e){w(c);if(f)for(C=0,D=f.length;C<D;++C)if(!1===k(f[C],c,m)){a=null;break a}if(n)for(C=0,D=n.length;C<D;++C)k(n[C],c,m);if(a)for(C=0,D=a.length;C<D;++C)h(a[C],c,m,l);if(e)for(C= -0,D=e.length;C<D;++C)h(e[C],c,m,l);a=m}else a=null}if(!a||!a.valid)return b.push(c),1;D=a.validAttributes;var O=a.validStyles;e=a.validClasses;var f=c.attributes,u=c.styles,n=c.classes;l=c.classBackup;var B=c.styleBackup,x,p,E=[],m=[],y=/^data-cke-/;C=!1;delete f.style;delete f["class"];delete c.classBackup;delete c.styleBackup;if(!a.allAttributes)for(x in f)D[x]||(y.test(x)?x==(p=x.replace(/^data-cke-saved-/,""))||D[p]||(delete f[x],C=!0):(delete f[x],C=!0));if(!a.allStyles||a.hadInvalidStyle){for(x in u)a.allStyles|| -O[x]?E.push(x+":"+u[x]):C=!0;E.length&&(f.style=E.sort().join("; "))}else B&&(f.style=B);if(!a.allClasses||a.hadInvalidClass){for(x=0;x<n.length;++x)(a.allClasses||e[n[x]])&&m.push(n[x]);m.length&&(f["class"]=m.sort().join(" "));l&&m.length<l.split(/\s+/).length&&(C=!0)}else l&&(f["class"]=l);C&&(d=1);if(!g.skipFinalValidation&&!q(c))return b.push(c),1}g.toHtml&&(c.name=c.name.replace(R,"cke:$1"));return d}function p(a){var c=[],b;for(b in a)-1<b.indexOf("*")&&c.push(b.replace(/\*/g,".*"));return c.length? -new RegExp("^(?:"+c.join("|")+")$"):null}function r(a){var c=a.attributes,b;delete c.style;delete c["class"];if(b=CKEDITOR.tools.writeCssText(a.styles,!0))c.style=b;a.classes.length&&(c["class"]=a.classes.sort().join(" "))}function q(a){switch(a.name){case "a":if(!(a.children.length||a.attributes.name||a.attributes.id))return!1;break;case "img":if(!a.attributes.src)return!1}return!0}function u(a){if(!a)return!1;if(!0===a)return!0;var c=p(a);return function(b){return b in a||c&&b.match(c)}}function x(){return new CKEDITOR.htmlParser.element("br")} -function A(a){return a.type==CKEDITOR.NODE_ELEMENT&&("br"==a.name||E.$block[a.name])}function D(a,c,b){var g=a.name;if(E.$empty[g]||!a.children.length)"hr"==g&&"br"==c?a.replaceWith(x()):(a.parent&&b.push({check:"it",el:a.parent}),a.remove());else if(E.$block[g]||"tr"==g)if("br"==c)a.previous&&!A(a.previous)&&(c=x(),c.insertBefore(a)),a.next&&!A(a.next)&&(c=x(),c.insertAfter(a)),a.replaceWithChildren();else{var g=a.children,d;b:{d=E[c];for(var e=0,f=g.length,k;e<f;++e)if(k=g[e],k.type==CKEDITOR.NODE_ELEMENT&& -!d[k.name]){d=!1;break b}d=!0}if(d)a.name=c,a.attributes={},b.push({check:"parent-down",el:a});else{d=a.parent;for(var e=d.type==CKEDITOR.NODE_DOCUMENT_FRAGMENT||"body"==d.name,h,n,f=g.length;0<f;)k=g[--f],e&&(k.type==CKEDITOR.NODE_TEXT||k.type==CKEDITOR.NODE_ELEMENT&&E.$inline[k.name])?(h||(h=new CKEDITOR.htmlParser.element(c),h.insertAfter(a),b.push({check:"parent-down",el:h})),h.add(k,0)):(h=null,n=E[d.name]||E.span,k.insertAfter(a),d.type==CKEDITOR.NODE_DOCUMENT_FRAGMENT||k.type!=CKEDITOR.NODE_ELEMENT|| -n[k.name]||b.push({check:"el-up",el:k}));a.remove()}}else g in{style:1,script:1}?a.remove():(a.parent&&b.push({check:"it",el:a.parent}),a.replaceWithChildren())}function t(a,c,b){var g,d;for(g=0;g<b.length;++g)if(d=b[g],!(d.check&&!a.check(d.check,!1)||d.left&&!d.left(c))){d.right(c,K);break}}function B(a,c){var b=c.getDefinition(),g=b.attributes,d=b.styles,e,f,k,h;if(a.name!=b.element)return!1;for(e in g)if("class"==e)for(b=g[e].split(/\s+/),k=a.classes.join("|");h=b.pop();){if(-1==k.indexOf(h))return!1}else if(a.attributes[e]!= -g[e])return!1;for(f in d)if(a.styles[f]!=d[f])return!1;return!0}function y(a,c){var b,g;"string"==typeof a?b=a:a instanceof CKEDITOR.style?g=a:(b=a[0],g=a[1]);return[{element:b,left:g,right:function(a,b){b.transform(a,c)}}]}function z(a){return function(c){return B(c,a)}}function I(a){return function(c,b){b[a](c)}}var E=CKEDITOR.dtd,F=CKEDITOR.tools.copy,H=CKEDITOR.tools.trim,G=["","p","br","div"];CKEDITOR.FILTER_SKIP_TREE=2;CKEDITOR.filter=function(a){this.allowedContent=[];this.disallowedContent= +extraPlugins:"",removePlugins:"",protectedSource:[],tabIndex:0,width:"",baseFloatZIndex:1E4,blockedKeystrokes:[CKEDITOR.CTRL+66,CKEDITOR.CTRL+73,CKEDITOR.CTRL+85]},function(){function f(a,c,b,d,g){var e,f;a=[];for(e in c){f=c[e];f="boolean"==typeof f?{}:"function"==typeof f?{match:f}:E(f);"$"!=e.charAt(0)&&(f.elements=e);b&&(f.featureName=b.toLowerCase());var k=f;k.elements=m(k.elements,/\s+/)||null;k.propertiesOnly=k.propertiesOnly||!0===k.elements;var h=/\s*,\s*/,n=void 0;for(n in L){k[n]=m(k[n], +h)||null;var l=k,q=O[n],u=m(k[O[n]],h),D=k[n],B=[],J=!0,p=void 0;u?J=!1:u={};for(p in D)"!"==p.charAt(0)&&(p=p.slice(1),B.push(p),u[p]=!0,J=!1);for(;p=B.pop();)D[p]=D["!"+p],delete D["!"+p];l[q]=(J?!1:u)||null}k.match=k.match||null;d.push(f);a.push(f)}c=g.elements;g=g.generic;var w;b=0;for(d=a.length;b<d;++b){e=E(a[b]);f=!0===e.classes||!0===e.styles||!0===e.attributes;k=e;n=q=h=void 0;for(h in L)k[h]=A(k[h]);l=!0;for(n in O){h=O[n];q=k[h];u=[];D=void 0;for(D in q)-1<D.indexOf("*")?u.push(new RegExp("^"+ +D.replace(/\*/g,".*")+"$")):u.push(D);q=u;q.length&&(k[h]=q,l=!1)}k.nothingRequired=l;k.noProperties=!(k.attributes||k.classes||k.styles);if(!0===e.elements||null===e.elements)g[f?"unshift":"push"](e);else for(w in k=e.elements,delete e.elements,k)if(c[w])c[w][f?"unshift":"push"](e);else c[w]=[e]}}function h(a,c,d,g){if(!a.match||a.match(c))if(g||b(a,c))if(a.propertiesOnly||(d.valid=!0),d.allAttributes||(d.allAttributes=e(a.attributes,c.attributes,d.validAttributes)),d.allStyles||(d.allStyles=e(a.styles, +c.styles,d.validStyles)),!d.allClasses){a=a.classes;c=c.classes;g=d.validClasses;if(a)if(!0===a)a=!0;else{for(var f=0,k=c.length,h;f<k;++f)h=c[f],g[h]||(g[h]=a(h));a=!1}else a=!1;d.allClasses=a}}function e(a,c,b){if(!a)return!1;if(!0===a)return!0;for(var d in c)b[d]||(b[d]=a(d));return!1}function k(a,c,b){if(!a.match||a.match(c)){if(a.noProperties)return!1;b.hadInvalidAttribute=d(a.attributes,c.attributes)||b.hadInvalidAttribute;b.hadInvalidStyle=d(a.styles,c.styles)||b.hadInvalidStyle;a=a.classes; +c=c.classes;if(a){for(var g=!1,e=!0===a,f=c.length;f--;)if(e||a(c[f]))c.splice(f,1),g=!0;a=g}else a=!1;b.hadInvalidClass=a||b.hadInvalidClass}}function d(a,c){if(!a)return!1;var b=!1,d=!0===a,g;for(g in c)if(d||a(g))delete c[g],b=!0;return b}function l(a,c,b){if(a.disabled||a.customConfig&&!b||!c)return!1;a._.cachedChecks={};return!0}function m(a,c){if(!a)return!1;if(!0===a)return a;if("string"==typeof a)return a=H(a),"*"==a?!0:CKEDITOR.tools.convertArrayToObject(a.split(c));if(CKEDITOR.tools.isArray(a))return a.length? +CKEDITOR.tools.convertArrayToObject(a):!1;var b={},d=0,g;for(g in a)b[g]=a[g],d++;return d?b:!1}function b(a,c){if(a.nothingRequired)return!0;var b,d,e,f;if(e=a.requiredClasses)for(f=c.classes,b=0;b<e.length;++b)if(d=e[b],"string"==typeof d){if(-1==CKEDITOR.tools.indexOf(f,d))return!1}else if(!CKEDITOR.tools.checkIfAnyArrayItemMatches(f,d))return!1;return g(c.styles,a.requiredStyles)&&g(c.attributes,a.requiredAttributes)}function g(a,c){if(!c)return!0;for(var b=0,d;b<c.length;++b)if(d=c[b],"string"== +typeof d){if(!(d in a))return!1}else if(!CKEDITOR.tools.checkIfAnyObjectPropertyMatches(a,d))return!1;return!0}function c(a){if(!a)return{};a=a.split(/\s*,\s*/).sort();for(var c={};a.length;)c[a.shift()]="cke-test";return c}function a(a){var c,b,d,g,e={},f=1;for(a=H(a);c=a.match(D);)(b=c[2])?(d=n(b,"styles"),g=n(b,"attrs"),b=n(b,"classes")):d=g=b=null,e["$"+f++]={elements:c[1],classes:b,styles:d,attributes:g},a=a.slice(c[0].length);return e}function n(a,c){var b=a.match(S[c]);return b?H(b[1]):null} +function w(a){var c=a.styleBackup=a.attributes.style,b=a.classBackup=a.attributes["class"];a.styles||(a.styles=CKEDITOR.tools.parseCssText(c||"",1));a.classes||(a.classes=b?b.split(/\s+/):[])}function v(a,c,b,d){var g=0,e;d.toHtml&&(c.name=c.name.replace(J,"$1"));if(d.doCallbacks&&a.elementCallbacks){a:{e=a.elementCallbacks;for(var f=0,n=e.length,l;f<n;++f)if(l=e[f](c)){e=l;break a}e=void 0}if(e)return e}if(d.doTransform&&(e=a._.transformations[c.name])){w(c);for(f=0;f<e.length;++f)u(a,c,e[f]);p(c)}if(d.doFilter){a:{f= +c.name;n=a._;a=n.allowedRules.elements[f];e=n.allowedRules.generic;f=n.disallowedRules.elements[f];n=n.disallowedRules.generic;l=d.skipRequired;var m={valid:!1,validAttributes:{},validClasses:{},validStyles:{},allAttributes:!1,allClasses:!1,allStyles:!1,hadInvalidAttribute:!1,hadInvalidClass:!1,hadInvalidStyle:!1},D,B;if(a||e){w(c);if(f)for(D=0,B=f.length;D<B;++D)if(!1===k(f[D],c,m)){a=null;break a}if(n)for(D=0,B=n.length;D<B;++D)k(n[D],c,m);if(a)for(D=0,B=a.length;D<B;++D)h(a[D],c,m,l);if(e)for(D= +0,B=e.length;D<B;++D)h(e[D],c,m,l);a=m}else a=null}if(!a||!a.valid)return b.push(c),1;B=a.validAttributes;var O=a.validStyles;e=a.validClasses;var f=c.attributes,r=c.styles,n=c.classes;l=c.classBackup;var A=c.styleBackup,y,t,F=[],m=[],x=/^data-cke-/;D=!1;delete f.style;delete f["class"];delete c.classBackup;delete c.styleBackup;if(!a.allAttributes)for(y in f)B[y]||(x.test(y)?y==(t=y.replace(/^data-cke-saved-/,""))||B[t]||(delete f[y],D=!0):(delete f[y],D=!0));if(!a.allStyles||a.hadInvalidStyle){for(y in r)a.allStyles|| +O[y]?F.push(y+":"+r[y]):D=!0;F.length&&(f.style=F.sort().join("; "))}else A&&(f.style=A);if(!a.allClasses||a.hadInvalidClass){for(y=0;y<n.length;++y)(a.allClasses||e[n[y]])&&m.push(n[y]);m.length&&(f["class"]=m.sort().join(" "));l&&m.length<l.split(/\s+/).length&&(D=!0)}else l&&(f["class"]=l);D&&(g=1);if(!d.skipFinalValidation&&!q(c))return b.push(c),1}d.toHtml&&(c.name=c.name.replace(R,"cke:$1"));return g}function t(a){var c=[],b;for(b in a)-1<b.indexOf("*")&&c.push(b.replace(/\*/g,".*"));return c.length? +new RegExp("^(?:"+c.join("|")+")$"):null}function p(a){var c=a.attributes,b;delete c.style;delete c["class"];if(b=CKEDITOR.tools.writeCssText(a.styles,!0))c.style=b;a.classes.length&&(c["class"]=a.classes.sort().join(" "))}function q(a){switch(a.name){case "a":if(!(a.children.length||a.attributes.name||a.attributes.id))return!1;break;case "img":if(!a.attributes.src)return!1}return!0}function A(a){if(!a)return!1;if(!0===a)return!0;var c=t(a);return function(b){return b in a||c&&b.match(c)}}function r(){return new CKEDITOR.htmlParser.element("br")} +function C(a){return a.type==CKEDITOR.NODE_ELEMENT&&("br"==a.name||F.$block[a.name])}function B(a,c,b){var d=a.name;if(F.$empty[d]||!a.children.length)"hr"==d&&"br"==c?a.replaceWith(r()):(a.parent&&b.push({check:"it",el:a.parent}),a.remove());else if(F.$block[d]||"tr"==d)if("br"==c)a.previous&&!C(a.previous)&&(c=r(),c.insertBefore(a)),a.next&&!C(a.next)&&(c=r(),c.insertAfter(a)),a.replaceWithChildren();else{var d=a.children,g;b:{g=F[c];for(var e=0,f=d.length,k;e<f;++e)if(k=d[e],k.type==CKEDITOR.NODE_ELEMENT&& +!g[k.name]){g=!1;break b}g=!0}if(g)a.name=c,a.attributes={},b.push({check:"parent-down",el:a});else{g=a.parent;for(var e=g.type==CKEDITOR.NODE_DOCUMENT_FRAGMENT||"body"==g.name,h,n,f=d.length;0<f;)k=d[--f],e&&(k.type==CKEDITOR.NODE_TEXT||k.type==CKEDITOR.NODE_ELEMENT&&F.$inline[k.name])?(h||(h=new CKEDITOR.htmlParser.element(c),h.insertAfter(a),b.push({check:"parent-down",el:h})),h.add(k,0)):(h=null,n=F[g.name]||F.span,k.insertAfter(a),g.type==CKEDITOR.NODE_DOCUMENT_FRAGMENT||k.type!=CKEDITOR.NODE_ELEMENT|| +n[k.name]||b.push({check:"el-up",el:k}));a.remove()}}else d in{style:1,script:1}?a.remove():(a.parent&&b.push({check:"it",el:a.parent}),a.replaceWithChildren())}function u(a,c,b){var d,g;for(d=0;d<b.length;++d)if(g=b[d],!(g.check&&!a.check(g.check,!1)||g.left&&!g.left(c))){g.right(c,K);break}}function y(a,c){var b=c.getDefinition(),d=b.attributes,g=b.styles,e,f,k,h;if(a.name!=b.element)return!1;for(e in d)if("class"==e)for(b=d[e].split(/\s+/),k=a.classes.join("|");h=b.pop();){if(-1==k.indexOf(h))return!1}else if(a.attributes[e]!= +d[e])return!1;for(f in g)if(a.styles[f]!=g[f])return!1;return!0}function x(a,c){var b,d;"string"==typeof a?b=a:a instanceof CKEDITOR.style?d=a:(b=a[0],d=a[1]);return[{element:b,left:d,right:function(a,b){b.transform(a,c)}}]}function z(a){return function(c){return y(c,a)}}function I(a){return function(c,b){b[a](c)}}var F=CKEDITOR.dtd,E=CKEDITOR.tools.copy,H=CKEDITOR.tools.trim,G=["","p","br","div"];CKEDITOR.FILTER_SKIP_TREE=2;CKEDITOR.filter=function(a){this.allowedContent=[];this.disallowedContent= [];this.elementCallbacks=null;this.disabled=!1;this.editor=null;this.id=CKEDITOR.tools.getNextNumber();this._={allowedRules:{elements:{},generic:[]},disallowedRules:{elements:{},generic:[]},transformations:{},cachedTests:{},cachedChecks:{}};CKEDITOR.filter.instances[this.id]=this;if(a instanceof CKEDITOR.editor){a=this.editor=a;this.customConfig=!0;var c=a.config.allowedContent;!0===c?this.disabled=!0:(c||(this.customConfig=!1),this.allow(c,"config",1),this.allow(a.config.extraAllowedContent,"extra", -1),this.allow(G[a.enterMode]+" "+G[a.shiftEnterMode],"default",1),this.disallow(a.config.disallowedContent))}else this.customConfig=!1,this.allow(a,"default",1)};CKEDITOR.filter.instances={};CKEDITOR.filter.prototype={allow:function(c,b,g){if(!l(this,c,g))return!1;var d,e;if("string"==typeof c)c=a(c);else if(c instanceof CKEDITOR.style){if(c.toAllowedContentRules)return this.allow(c.toAllowedContentRules(this.editor),b,g);d=c.getDefinition();c={};g=d.attributes;c[d.element]=d={styles:d.styles,requiredStyles:d.styles&& -CKEDITOR.tools.objectKeys(d.styles)};g&&(g=F(g),d.classes=g["class"]?g["class"].split(/\s+/):null,d.requiredClasses=d.classes,delete g["class"],d.attributes=g,d.requiredAttributes=g&&CKEDITOR.tools.objectKeys(g))}else if(CKEDITOR.tools.isArray(c)){for(d=0;d<c.length;++d)e=this.allow(c[d],b,g);return e}f(this,c,b,this.allowedContent,this._.allowedRules);return!0},applyTo:function(a,c,b,g){if(this.disabled)return!1;var d=this,e=[],f=this.editor&&this.editor.config.protectedSource,k,h=!1,n={doFilter:!b, -doTransform:!0,doCallbacks:!0,toHtml:c};a.forEach(function(a){if(a.type==CKEDITOR.NODE_ELEMENT){if("off"==a.attributes["data-cke-filter"])return!1;if(!c||"span"!=a.name||!~CKEDITOR.tools.objectKeys(a.attributes).join("|").indexOf("data-cke-"))if(k=v(d,a,e,n),k&1)h=!0;else if(k&2)return!1}else if(a.type==CKEDITOR.NODE_COMMENT&&a.value.match(/^\{cke_protected\}(?!\{C\})/)){var b;a:{var g=decodeURIComponent(a.value.replace(/^\{cke_protected\}/,""));b=[];var l,m,q;if(f)for(m=0;m<f.length;++m)if((q=g.match(f[m]))&& -q[0].length==g.length){b=!0;break a}g=CKEDITOR.htmlParser.fragment.fromHtml(g);1==g.children.length&&(l=g.children[0]).type==CKEDITOR.NODE_ELEMENT&&v(d,l,b,n);b=!b.length}b||e.push(a)}},null,!0);e.length&&(h=!0);var l;a=[];g=G[g||(this.editor?this.editor.enterMode:CKEDITOR.ENTER_P)];for(var m;b=e.pop();)b.type==CKEDITOR.NODE_ELEMENT?D(b,g,a):b.remove();for(;l=a.pop();)if(b=l.el,b.parent)switch(m=E[b.parent.name]||E.span,l.check){case "it":E.$removeEmpty[b.name]&&!b.children.length?D(b,g,a):q(b)|| -D(b,g,a);break;case "el-up":b.parent.type==CKEDITOR.NODE_DOCUMENT_FRAGMENT||m[b.name]||D(b,g,a);break;case "parent-down":b.parent.type==CKEDITOR.NODE_DOCUMENT_FRAGMENT||m[b.name]||D(b.parent,g,a)}return h},checkFeature:function(a){if(this.disabled||!a)return!0;a.toFeature&&(a=a.toFeature(this.editor));return!a.requiredContent||this.check(a.requiredContent)},disable:function(){this.disabled=!0},disallow:function(c){if(!l(this,c,!0))return!1;"string"==typeof c&&(c=a(c));f(this,c,null,this.disallowedContent, -this._.disallowedRules);return!0},addContentForms:function(a){if(!this.disabled&&a){var c,b,g=[],d;for(c=0;c<a.length&&!d;++c)b=a[c],("string"==typeof b||b instanceof CKEDITOR.style)&&this.check(b)&&(d=b);if(d){for(c=0;c<a.length;++c)g.push(y(a[c],d));this.addTransformations(g)}}},addElementCallback:function(a){this.elementCallbacks||(this.elementCallbacks=[]);this.elementCallbacks.push(a)},addFeature:function(a){if(this.disabled||!a)return!0;a.toFeature&&(a=a.toFeature(this.editor));this.allow(a.allowedContent, -a.name);this.addTransformations(a.contentTransformations);this.addContentForms(a.contentForms);return a.requiredContent&&(this.customConfig||this.disallowedContent.length)?this.check(a.requiredContent):!0},addTransformations:function(a){var c,b;if(!this.disabled&&a){var g=this._.transformations,d;for(d=0;d<a.length;++d){c=a[d];var e=void 0,f=void 0,k=void 0,h=void 0,n=void 0,l=void 0;b=[];for(f=0;f<c.length;++f)k=c[f],"string"==typeof k?(k=k.split(/\s*:\s*/),h=k[0],n=null,l=k[1]):(h=k.check,n=k.left, -l=k.right),e||(e=k,e=e.element?e.element:h?h.match(/^([a-z0-9]+)/i)[0]:e.left.getDefinition().element),n instanceof CKEDITOR.style&&(n=z(n)),b.push({check:h==e?null:h,left:n,right:"string"==typeof l?I(l):l});c=e;g[c]||(g[c]=[]);g[c].push(b)}}},check:function(b,g,d){if(this.disabled)return!0;if(CKEDITOR.tools.isArray(b)){for(var e=b.length;e--;)if(this.check(b[e],g,d))return!0;return!1}var f,k;if("string"==typeof b){k=b+"\x3c"+(!1===g?"0":"1")+(d?"1":"0")+"\x3e";if(k in this._.cachedChecks)return this._.cachedChecks[k]; -e=a(b).$1;f=e.styles;var h=e.classes;e.name=e.elements;e.classes=h=h?h.split(/\s*,\s*/):[];e.styles=c(f);e.attributes=c(e.attributes);e.children=[];h.length&&(e.attributes["class"]=h.join(" "));f&&(e.attributes.style=CKEDITOR.tools.writeCssText(e.styles));f=e}else e=b.getDefinition(),f=e.styles,h=e.attributes||{},f&&!CKEDITOR.tools.isEmpty(f)?(f=F(f),h.style=CKEDITOR.tools.writeCssText(f,!0)):f={},f={name:e.element,attributes:h,classes:h["class"]?h["class"].split(/\s+/):[],styles:f,children:[]};var h= -CKEDITOR.tools.clone(f),n=[],l;if(!1!==g&&(l=this._.transformations[f.name])){for(e=0;e<l.length;++e)t(this,f,l[e]);r(f)}v(this,h,n,{doFilter:!0,doTransform:!1!==g,skipRequired:!d,skipFinalValidation:!d});g=0<n.length?!1:CKEDITOR.tools.objectCompare(f.attributes,h.attributes,!0)?!0:!1;"string"==typeof b&&(this._.cachedChecks[k]=g);return g},getAllowedEnterMode:function(){var a=["p","div","br"],c={p:CKEDITOR.ENTER_P,div:CKEDITOR.ENTER_DIV,br:CKEDITOR.ENTER_BR};return function(b,g){var d=a.slice(), -e;if(this.check(G[b]))return b;for(g||(d=d.reverse());e=d.pop();)if(this.check(e))return c[e];return CKEDITOR.ENTER_BR}}(),clone:function(){var a=new CKEDITOR.filter,c=CKEDITOR.tools.clone;a.allowedContent=c(this.allowedContent);a._.allowedRules=c(this._.allowedRules);a.disallowedContent=c(this.disallowedContent);a._.disallowedRules=c(this._.disallowedRules);a._.transformations=c(this._.transformations);a.disabled=this.disabled;a.editor=this.editor;return a},destroy:function(){delete CKEDITOR.filter.instances[this.id]; -delete this._;delete this.allowedContent;delete this.disallowedContent}};var L={styles:1,attributes:1,classes:1},O={styles:"requiredStyles",attributes:"requiredAttributes",classes:"requiredClasses"},C=/^([a-z0-9\-*\s]+)((?:\s*\{[!\w\-,\s\*]+\}\s*|\s*\[[!\w\-,\s\*]+\]\s*|\s*\([!\w\-,\s\*]+\)\s*){0,3})(?:;\s*|$)/i,S={styles:/{([^}]+)}/,attrs:/\[([^\]]+)\]/,classes:/\(([^\)]+)\)/},J=/^cke:(object|embed|param)$/,R=/^(object|embed|param)$/,K;K=CKEDITOR.filter.transformationsTools={sizeToStyle:function(a){this.lengthToStyle(a, -"width");this.lengthToStyle(a,"height")},sizeToAttribute:function(a){this.lengthToAttribute(a,"width");this.lengthToAttribute(a,"height")},lengthToStyle:function(a,c,b){b=b||c;if(!(b in a.styles)){var g=a.attributes[c];g&&(/^\d+$/.test(g)&&(g+="px"),a.styles[b]=g)}delete a.attributes[c]},lengthToAttribute:function(a,c,b){b=b||c;if(!(b in a.attributes)){var g=a.styles[c],d=g&&g.match(/^(\d+)(?:\.\d*)?px$/);d?a.attributes[b]=d[1]:"cke-test"==g&&(a.attributes[b]="cke-test")}delete a.styles[c]},alignmentToStyle:function(a){if(!("float"in -a.styles)){var c=a.attributes.align;if("left"==c||"right"==c)a.styles["float"]=c}delete a.attributes.align},alignmentToAttribute:function(a){if(!("align"in a.attributes)){var c=a.styles["float"];if("left"==c||"right"==c)a.attributes.align=c}delete a.styles["float"]},splitBorderShorthand:function(a){if(a.styles.border){var c=CKEDITOR.tools.style.parse.border(a.styles.border);c.color&&(a.styles["border-color"]=c.color);c.style&&(a.styles["border-style"]=c.style);c.width&&(a.styles["border-width"]=c.width); -delete a.styles.border}},listTypeToStyle:function(a){if(a.attributes.type)switch(a.attributes.type){case "a":a.styles["list-style-type"]="lower-alpha";break;case "A":a.styles["list-style-type"]="upper-alpha";break;case "i":a.styles["list-style-type"]="lower-roman";break;case "I":a.styles["list-style-type"]="upper-roman";break;case "1":a.styles["list-style-type"]="decimal";break;default:a.styles["list-style-type"]=a.attributes.type}},splitMarginShorthand:function(a){function c(g){a.styles["margin-top"]= -b[g[0]];a.styles["margin-right"]=b[g[1]];a.styles["margin-bottom"]=b[g[2]];a.styles["margin-left"]=b[g[3]]}if(a.styles.margin){var b=a.styles.margin.match(/(\-?[\.\d]+\w+)/g)||["0px"];switch(b.length){case 1:c([0,0,0,0]);break;case 2:c([0,1,0,1]);break;case 3:c([0,1,2,1]);break;case 4:c([0,1,2,3])}delete a.styles.margin}},matchesStyle:B,transform:function(a,c){if("string"==typeof c)a.name=c;else{var b=c.getDefinition(),g=b.styles,d=b.attributes,e,f,k,h;a.name=b.element;for(e in d)if("class"==e)for(b= -a.classes.join("|"),k=d[e].split(/\s+/);h=k.pop();)-1==b.indexOf(h)&&a.classes.push(h);else a.attributes[e]=d[e];for(f in g)a.styles[f]=g[f]}}}}(),function(){CKEDITOR.focusManager=function(f){if(f.focusManager)return f.focusManager;this.hasFocus=!1;this.currentActive=null;this._={editor:f};return this};CKEDITOR.focusManager._={blurDelay:200};CKEDITOR.focusManager.prototype={focus:function(f){this._.timer&&clearTimeout(this._.timer);f&&(this.currentActive=f);this.hasFocus||this._.locked||((f=CKEDITOR.currentInstance)&& -f.focusManager.blur(1),this.hasFocus=!0,(f=this._.editor.container)&&f.addClass("cke_focus"),this._.editor.fire("focus"))},lock:function(){this._.locked=1},unlock:function(){delete this._.locked},blur:function(f){function h(){if(this.hasFocus){this.hasFocus=!1;var e=this._.editor.container;e&&e.removeClass("cke_focus");this._.editor.fire("blur")}}if(!this._.locked){this._.timer&&clearTimeout(this._.timer);var e=CKEDITOR.focusManager._.blurDelay;f||!e?h.call(this):this._.timer=CKEDITOR.tools.setTimeout(function(){delete this._.timer; -h.call(this)},e,this)}},add:function(f,h){var e=f.getCustomData("focusmanager");if(!e||e!=this){e&&e.remove(f);var e="focus",k="blur";h&&(CKEDITOR.env.ie?(e="focusin",k="focusout"):CKEDITOR.event.useCapture=1);var d={blur:function(){f.equals(this.currentActive)&&this.blur()},focus:function(){this.focus(f)}};f.on(e,d.focus,this);f.on(k,d.blur,this);h&&(CKEDITOR.event.useCapture=0);f.setCustomData("focusmanager",this);f.setCustomData("focusmanager_handlers",d)}},remove:function(f){f.removeCustomData("focusmanager"); -var h=f.removeCustomData("focusmanager_handlers");f.removeListener("blur",h.blur);f.removeListener("focus",h.focus)}}}(),CKEDITOR.keystrokeHandler=function(f){if(f.keystrokeHandler)return f.keystrokeHandler;this.keystrokes={};this.blockedKeystrokes={};this._={editor:f};return this},function(){var f,h=function(e){e=e.data;var d=e.getKeystroke(),h=this.keystrokes[d],m=this._.editor;f=!1===m.fire("key",{keyCode:d,domEvent:e});f||(h&&(f=!1!==m.execCommand(h,{from:"keystrokeHandler"})),f||(f=!!this.blockedKeystrokes[d])); -f&&e.preventDefault(!0);return!f},e=function(e){f&&(f=!1,e.data.preventDefault(!0))};CKEDITOR.keystrokeHandler.prototype={attach:function(f){f.on("keydown",h,this);if(CKEDITOR.env.gecko&&CKEDITOR.env.mac)f.on("keypress",e,this)}}}(),function(){CKEDITOR.lang={languages:{af:1,ar:1,az:1,bg:1,bn:1,bs:1,ca:1,cs:1,cy:1,da:1,de:1,"de-ch":1,el:1,"en-au":1,"en-ca":1,"en-gb":1,en:1,eo:1,es:1,"es-mx":1,et:1,eu:1,fa:1,fi:1,fo:1,"fr-ca":1,fr:1,gl:1,gu:1,he:1,hi:1,hr:1,hu:1,id:1,is:1,it:1,ja:1,ka:1,km:1,ko:1,ku:1, -lt:1,lv:1,mk:1,mn:1,ms:1,nb:1,nl:1,no:1,oc:1,pl:1,"pt-br":1,pt:1,ro:1,ru:1,si:1,sk:1,sl:1,sq:1,"sr-latn":1,sr:1,sv:1,th:1,tr:1,tt:1,ug:1,uk:1,vi:1,"zh-cn":1,zh:1},rtl:{ar:1,fa:1,he:1,ku:1,ug:1},load:function(f,h,e){f&&CKEDITOR.lang.languages[f]||(f=this.detect(h,f));var k=this;h=function(){k[f].dir=k.rtl[f]?"rtl":"ltr";e(f,k[f])};this[f]?h():CKEDITOR.scriptLoader.load(CKEDITOR.getUrl("lang/"+f+".js"),h,this)},detect:function(f,h){var e=this.languages;h=h||navigator.userLanguage||navigator.language|| -f;var k=h.toLowerCase().match(/([a-z]+)(?:-([a-z]+))?/),d=k[1],k=k[2];e[d+"-"+k]?d=d+"-"+k:e[d]||(d=null);CKEDITOR.lang.detect=d?function(){return d}:function(d){return d};return d||f}}}(),CKEDITOR.scriptLoader=function(){var f={},h={};return{load:function(e,k,d,l){var m="string"==typeof e;m&&(e=[e]);d||(d=CKEDITOR);var b=e.length,g=[],c=[],a=function(a){k&&(m?k.call(d,a):k.call(d,g,c))};if(0===b)a(!0);else{var n=function(d,e){(e?g:c).push(d);0>=--b&&(l&&CKEDITOR.document.getDocumentElement().removeStyle("cursor"), -a(e))},w=function(a,c){f[a]=1;var b=h[a];delete h[a];for(var g=0;g<b.length;g++)b[g](a,c)},v=function(a){if(f[a])n(a,!0);else{var c=h[a]||(h[a]=[]);c.push(n);if(!(1<c.length)){var b=new CKEDITOR.dom.element("script");b.setAttributes({type:"text/javascript",src:a});k&&(CKEDITOR.env.ie&&(8>=CKEDITOR.env.version||CKEDITOR.env.ie9Compat)?b.$.onreadystatechange=function(){if("loaded"==b.$.readyState||"complete"==b.$.readyState)b.$.onreadystatechange=null,w(a,!0)}:(b.$.onload=function(){setTimeout(function(){w(a, -!0)},0)},b.$.onerror=function(){w(a,!1)}));b.appendTo(CKEDITOR.document.getHead())}}};l&&CKEDITOR.document.getDocumentElement().setStyle("cursor","wait");for(var p=0;p<b;p++)v(e[p])}},queue:function(){function e(){var d;(d=f[0])&&this.load(d.scriptUrl,d.callback,CKEDITOR,0)}var f=[];return function(d,h){var m=this;f.push({scriptUrl:d,callback:function(){h&&h.apply(this,arguments);f.shift();e.call(m)}});1==f.length&&e.call(this)}}()}}(),CKEDITOR.resourceManager=function(f,h){this.basePath=f;this.fileName= -h;this.registered={};this.loaded={};this.externals={};this._={waitingList:{}}},CKEDITOR.resourceManager.prototype={add:function(f,h){if(this.registered[f])throw Error('[CKEDITOR.resourceManager.add] The resource name "'+f+'" is already registered.');var e=this.registered[f]=h||{};e.name=f;e.path=this.getPath(f);CKEDITOR.fire(f+CKEDITOR.tools.capitalize(this.fileName)+"Ready",e);return this.get(f)},get:function(f){return this.registered[f]||null},getPath:function(f){var h=this.externals[f];return CKEDITOR.getUrl(h&& -h.dir||this.basePath+f+"/")},getFilePath:function(f){var h=this.externals[f];return CKEDITOR.getUrl(this.getPath(f)+(h?h.file:this.fileName+".js"))},addExternal:function(f,h,e){f=f.split(",");for(var k=0;k<f.length;k++){var d=f[k];e||(h=h.replace(/[^\/]+$/,function(d){e=d;return""}));this.externals[d]={dir:h,file:e||this.fileName+".js"}}},load:function(f,h,e){CKEDITOR.tools.isArray(f)||(f=f?[f]:[]);for(var k=this.loaded,d=this.registered,l=[],m={},b={},g=0;g<f.length;g++){var c=f[g];if(c)if(k[c]|| -d[c])b[c]=this.get(c);else{var a=this.getFilePath(c);l.push(a);a in m||(m[a]=[]);m[a].push(c)}}CKEDITOR.scriptLoader.load(l,function(a,c){if(c.length)throw Error('[CKEDITOR.resourceManager.load] Resource name "'+m[c[0]].join(",")+'" was not found at "'+c[0]+'".');for(var g=0;g<a.length;g++)for(var d=m[a[g]],f=0;f<d.length;f++){var l=d[f];b[l]=this.get(l);k[l]=1}h.call(e,b)},this)}},CKEDITOR.plugins=new CKEDITOR.resourceManager("plugins/","plugin"),CKEDITOR.plugins.load=CKEDITOR.tools.override(CKEDITOR.plugins.load, -function(f){var h={};return function(e,k,d){var l={},m=function(b){f.call(this,b,function(b){CKEDITOR.tools.extend(l,b);var c=[],a;for(a in b){var e=b[a],f=e&&e.requires;if(!h[a]){if(e.icons)for(var v=e.icons.split(","),p=v.length;p--;)CKEDITOR.skin.addIcon(v[p],e.path+"icons/"+(CKEDITOR.env.hidpi&&e.hidpi?"hidpi/":"")+v[p]+".png");h[a]=1}if(f)for(f.split&&(f=f.split(",")),e=0;e<f.length;e++)l[f[e]]||c.push(f[e])}if(c.length)m.call(this,c);else{for(a in l)e=l[a],e.onLoad&&!e.onLoad._called&&(!1=== -e.onLoad()&&delete l[a],e.onLoad._called=1);k&&k.call(d||window,l)}},this)};m.call(this,e)}}),CKEDITOR.plugins.setLang=function(f,h,e){var k=this.get(f);f=k.langEntries||(k.langEntries={});k=k.lang||(k.lang=[]);k.split&&(k=k.split(","));-1==CKEDITOR.tools.indexOf(k,h)&&k.push(h);f[h]=e},CKEDITOR.ui=function(f){if(f.ui)return f.ui;this.items={};this.instances={};this.editor=f;this._={handlers:{}};return this},CKEDITOR.ui.prototype={add:function(f,h,e){e.name=f.toLowerCase();var k=this.items[f]={type:h, -command:e.command||null,args:Array.prototype.slice.call(arguments,2)};CKEDITOR.tools.extend(k,e)},get:function(f){return this.instances[f]},create:function(f){var h=this.items[f],e=h&&this._.handlers[h.type],k=h&&h.command&&this.editor.getCommand(h.command),e=e&&e.create.apply(this,h.args);this.instances[f]=e;k&&k.uiItems.push(e);e&&!e.type&&(e.type=h.type);return e},addHandler:function(f,h){this._.handlers[f]=h},space:function(f){return CKEDITOR.document.getById(this.spaceId(f))},spaceId:function(f){return this.editor.id+ -"_"+f}},CKEDITOR.event.implementOn(CKEDITOR.ui),function(){function f(a,c,g){CKEDITOR.event.call(this);a=a&&CKEDITOR.tools.clone(a);if(void 0!==c){if(!(c instanceof CKEDITOR.dom.element))throw Error("Expect element of type CKEDITOR.dom.element.");if(!g)throw Error("One of the element modes must be specified.");if(CKEDITOR.env.ie&&CKEDITOR.env.quirks&&g==CKEDITOR.ELEMENT_MODE_INLINE)throw Error("Inline element mode is not supported on IE quirks.");if(!e(c,g))throw Error('The specified element mode is not supported on element: "'+ -c.getName()+'".');this.element=c;this.elementMode=g;this.name=this.elementMode!=CKEDITOR.ELEMENT_MODE_APPENDTO&&(c.getId()||c.getNameAtt())}else this.elementMode=CKEDITOR.ELEMENT_MODE_NONE;this._={};this.commands={};this.templates={};this.name=this.name||h();this.id=CKEDITOR.tools.getNextId();this.status="unloaded";this.config=CKEDITOR.tools.prototypedCopy(CKEDITOR.config);this.ui=new CKEDITOR.ui(this);this.focusManager=new CKEDITOR.focusManager(this);this.keystrokeHandler=new CKEDITOR.keystrokeHandler(this); -this.on("readOnly",k);this.on("selectionChange",function(a){l(this,a.data.path)});this.on("activeFilterChange",function(){l(this,this.elementPath(),!0)});this.on("mode",k);this.on("instanceReady",function(){if(this.config.startupFocus){if("end"===this.config.startupFocus){var a=this.createRange();a.selectNodeContents(this.editable());a.shrink(CKEDITOR.SHRINK_ELEMENT,!0);a.collapse();this.getSelection().selectRanges([a])}this.focus()}});CKEDITOR.fire("instanceCreated",null,this);CKEDITOR.add(this); -CKEDITOR.tools.setTimeout(function(){"destroyed"!==this.status?b(this,a):CKEDITOR.warn("editor-incorrect-destroy")},0,this)}function h(){do var a="editor"+ ++p;while(CKEDITOR.instances[a]);return a}function e(a,c){return c==CKEDITOR.ELEMENT_MODE_INLINE?a.is(CKEDITOR.dtd.$editable)||a.is("textarea"):c==CKEDITOR.ELEMENT_MODE_REPLACE?!a.is(CKEDITOR.dtd.$nonBodyContent):1}function k(){var a=this.commands,c;for(c in a)d(this,a[c])}function d(a,c){c[c.startDisabled?"disable":a.readOnly&&!c.readOnly?"disable": -c.modes[a.mode]?"enable":"disable"]()}function l(a,c,b){if(c){var g,d,e=a.commands;for(d in e)g=e[d],(b||g.contextSensitive)&&g.refresh(a,c)}}function m(a){var c=a.config.customConfig;if(!c)return!1;var c=CKEDITOR.getUrl(c),b=r[c]||(r[c]={});b.fn?(b.fn.call(a,a.config),CKEDITOR.getUrl(a.config.customConfig)!=c&&m(a)||a.fireOnce("customConfigLoaded")):CKEDITOR.scriptLoader.queue(c,function(){b.fn=CKEDITOR.editorConfig?CKEDITOR.editorConfig:function(){};m(a)});return!0}function b(a,c){a.on("customConfigLoaded", -function(){if(c){if(c.on)for(var b in c.on)a.on(b,c.on[b]);CKEDITOR.tools.extend(a.config,c,!0);delete a.config.on}b=a.config;a.readOnly=b.readOnly?!0:a.elementMode==CKEDITOR.ELEMENT_MODE_INLINE?a.element.is("textarea")?a.element.hasAttribute("disabled")||a.element.hasAttribute("readonly"):a.element.isReadOnly():a.elementMode==CKEDITOR.ELEMENT_MODE_REPLACE?a.element.hasAttribute("disabled")||a.element.hasAttribute("readonly"):!1;a.blockless=a.elementMode==CKEDITOR.ELEMENT_MODE_INLINE?!(a.element.is("textarea")|| -CKEDITOR.dtd[a.element.getName()].p):!1;a.tabIndex=b.tabIndex||a.element&&a.element.getAttribute("tabindex")||0;a.activeEnterMode=a.enterMode=a.blockless?CKEDITOR.ENTER_BR:b.enterMode;a.activeShiftEnterMode=a.shiftEnterMode=a.blockless?CKEDITOR.ENTER_BR:b.shiftEnterMode;b.skin&&(CKEDITOR.skinName=b.skin);a.fireOnce("configLoaded");a.dataProcessor=new CKEDITOR.htmlDataProcessor(a);a.filter=a.activeFilter=new CKEDITOR.filter(a);g(a)});c&&null!=c.customConfig&&(a.config.customConfig=c.customConfig); -m(a)||a.fireOnce("customConfigLoaded")}function g(a){CKEDITOR.skin.loadPart("editor",function(){c(a)})}function c(c){CKEDITOR.lang.load(c.config.language,c.config.defaultLanguage,function(b,g){var d=c.config.title;c.langCode=b;c.lang=CKEDITOR.tools.prototypedCopy(g);c.title="string"==typeof d||!1===d?d:[c.lang.editor,c.name].join(", ");c.config.contentsLangDirection||(c.config.contentsLangDirection=c.elementMode==CKEDITOR.ELEMENT_MODE_INLINE?c.element.getDirection(1):c.lang.dir);c.fire("langLoaded"); -a(c)})}function a(a){a.getStylesSet(function(c){a.once("loaded",function(){a.fire("stylesSet",{styles:c})},null,null,1);n(a)})}function n(a){function c(a){if(!a)return"";CKEDITOR.tools.isArray(a)&&(a=a.join(","));return a.replace(/\s/g,"")}var b=a.config,g=c(b.plugins),d=c(b.extraPlugins),e=c(b.removePlugins);if(d)var f=new RegExp("(?:^|,)(?:"+d.replace(/,/g,"|")+")(?\x3d,|$)","g"),g=g.replace(f,""),g=g+(","+d);if(e)var k=new RegExp("(?:^|,)(?:"+e.replace(/,/g,"|")+")(?\x3d,|$)","g"),g=g.replace(k, -"");CKEDITOR.env.air&&(g+=",adobeair");CKEDITOR.plugins.load(g.split(","),function(c){var g=[],d=[],e=[];a.plugins=c;for(var f in c){var h=c[f],n=h.lang,l=null,m=h.requires,t;CKEDITOR.tools.isArray(m)&&(m=m.join(","));if(m&&(t=m.match(k)))for(;m=t.pop();)CKEDITOR.error("editor-plugin-required",{plugin:m.replace(",",""),requiredBy:f});n&&!a.lang[f]&&(n.split&&(n=n.split(",")),0<=CKEDITOR.tools.indexOf(n,a.langCode)?l=a.langCode:(l=a.langCode.replace(/-.*/,""),l=l!=a.langCode&&0<=CKEDITOR.tools.indexOf(n, -l)?l:0<=CKEDITOR.tools.indexOf(n,"en")?"en":n[0]),h.langEntries&&h.langEntries[l]?(a.lang[f]=h.langEntries[l],l=null):e.push(CKEDITOR.getUrl(h.path+"lang/"+l+".js")));d.push(l);g.push(h)}CKEDITOR.scriptLoader.load(e,function(){for(var c=["beforeInit","init","afterInit"],e=0;e<c.length;e++)for(var f=0;f<g.length;f++){var k=g[f];0===e&&d[f]&&k.lang&&k.langEntries&&(a.lang[k.name]=k.langEntries[d[f]]);if(k[c[e]])k[c[e]](a)}a.fireOnce("pluginsLoaded");b.keystrokes&&a.setKeystroke(a.config.keystrokes); -for(f=0;f<a.config.blockedKeystrokes.length;f++)a.keystrokeHandler.blockedKeystrokes[a.config.blockedKeystrokes[f]]=1;a.status="loaded";a.fireOnce("loaded");CKEDITOR.fire("instanceLoaded",null,a)})})}function w(){var a=this.element;if(a&&this.elementMode!=CKEDITOR.ELEMENT_MODE_APPENDTO){var c=this.getData();this.config.htmlEncodeOutput&&(c=CKEDITOR.tools.htmlEncode(c));a.is("textarea")?a.setValue(c):a.setHtml(c);return!0}return!1}function v(a,c){function b(a){var c=a.startContainer,g=a.endContainer; -return c.is&&(c.is("tr")||c.is("td")&&c.equals(g)&&a.endOffset===c.getChildCount())?!0:!1}function g(a){var c=a.startContainer;return c.is("tr")?a.cloneContents():c.clone(!0)}for(var d=new CKEDITOR.dom.documentFragment,e,f,k,h=0;h<a.length;h++){var n=a[h],l=n.startContainer.getAscendant("tr",!0);b(n)?(e||(e=l.getAscendant("table").clone(),e.append(l.getAscendant({thead:1,tbody:1,tfoot:1}).clone()),d.append(e),e=e.findOne("thead, tbody, tfoot")),f&&f.equals(l)||(f=l,k=l.clone(),e.append(k)),k.append(g(n))): -d.append(n.cloneContents())}return e?d:c.getHtmlFromRange(a[0])}f.prototype=CKEDITOR.editor.prototype;CKEDITOR.editor=f;var p=0,r={};CKEDITOR.tools.extend(CKEDITOR.editor.prototype,{addCommand:function(a,c){c.name=a.toLowerCase();var b=c instanceof CKEDITOR.command?c:new CKEDITOR.command(this,c);this.mode&&d(this,b);return this.commands[a]=b},_attachToForm:function(){function a(c){b.updateElement();b._.required&&!g.getValue()&&!1===b.fire("required")&&c.data.preventDefault()}function c(a){return!!(a&& -a.call&&a.apply)}var b=this,g=b.element,d=new CKEDITOR.dom.element(g.$.form);g.is("textarea")&&d&&(d.on("submit",a),c(d.$.submit)&&(d.$.submit=CKEDITOR.tools.override(d.$.submit,function(c){return function(){a();c.apply?c.apply(this):c()}})),b.on("destroy",function(){d.removeListener("submit",a)}))},destroy:function(a){this.fire("beforeDestroy");!a&&w.call(this);this.editable(null);this.filter&&(this.filter.destroy(),delete this.filter);delete this.activeFilter;this.status="destroyed";this.fire("destroy"); -this.removeAllListeners();CKEDITOR.remove(this);CKEDITOR.fire("instanceDestroyed",null,this)},elementPath:function(a){if(!a){a=this.getSelection();if(!a)return null;a=a.getStartElement()}return a?new CKEDITOR.dom.elementPath(a,this.editable()):null},createRange:function(){var a=this.editable();return a?new CKEDITOR.dom.range(a):null},execCommand:function(a,c){var b=this.getCommand(a),g={name:a,commandData:c||{},command:b};return b&&b.state!=CKEDITOR.TRISTATE_DISABLED&&!1!==this.fire("beforeCommandExec", -g)&&(g.returnValue=b.exec(g.commandData),!b.async&&!1!==this.fire("afterCommandExec",g))?g.returnValue:!1},getCommand:function(a){return this.commands[a]},getData:function(a){!a&&this.fire("beforeGetData");var c=this._.data;"string"!=typeof c&&(c=(c=this.element)&&this.elementMode==CKEDITOR.ELEMENT_MODE_REPLACE?c.is("textarea")?c.getValue():c.getHtml():"");c={dataValue:c};!a&&this.fire("getData",c);return c.dataValue},getSnapshot:function(){var a=this.fire("getSnapshot");"string"!=typeof a&&(a=(a= -this.element)&&this.elementMode==CKEDITOR.ELEMENT_MODE_REPLACE?a.is("textarea")?a.getValue():a.getHtml():"");return a},loadSnapshot:function(a){this.fire("loadSnapshot",a)},setData:function(a,c,b){var g=!0,d=c;c&&"object"==typeof c&&(b=c.internal,d=c.callback,g=!c.noSnapshot);!b&&g&&this.fire("saveSnapshot");if(d||!b)this.once("dataReady",function(a){!b&&g&&this.fire("saveSnapshot");d&&d.call(a.editor)});a={dataValue:a};!b&&this.fire("setData",a);this._.data=a.dataValue;!b&&this.fire("afterSetData", -a)},setReadOnly:function(a){a=null==a||a;this.readOnly!=a&&(this.readOnly=a,this.keystrokeHandler.blockedKeystrokes[8]=+a,this.editable().setReadOnly(a),this.fire("readOnly"))},insertHtml:function(a,c,b){this.fire("insertHtml",{dataValue:a,mode:c,range:b})},insertText:function(a){this.fire("insertText",a)},insertElement:function(a){this.fire("insertElement",a)},getSelectedHtml:function(a){var c=this.editable(),b=this.getSelection(),b=b&&b.getRanges();if(!c||!b||0===b.length)return null;c=v(b,c);return a? -c.getHtml():c},extractSelectedHtml:function(a,c){var b=this.editable(),g=this.getSelection().getRanges(),d=new CKEDITOR.dom.documentFragment,e;if(!b||0===g.length)return null;for(e=0;e<g.length;e++)d.append(b.extractHtmlFromRange(g[e],c));c||this.getSelection().selectRanges([g[0]]);return a?d.getHtml():d},focus:function(){this.fire("beforeFocus")},checkDirty:function(){return"ready"==this.status&&this._.previousValue!==this.getSnapshot()},resetDirty:function(){this._.previousValue=this.getSnapshot()}, -updateElement:function(){return w.call(this)},setKeystroke:function(){for(var a=this.keystrokeHandler.keystrokes,c=CKEDITOR.tools.isArray(arguments[0])?arguments[0]:[[].slice.call(arguments,0)],b,g,d=c.length;d--;)b=c[d],g=0,CKEDITOR.tools.isArray(b)&&(g=b[1],b=b[0]),g?a[b]=g:delete a[b]},getCommandKeystroke:function(a){if(a="string"===typeof a?this.getCommand(a):a){var c=CKEDITOR.tools.object.findKey(this.commands,a),b=this.keystrokeHandler.keystrokes,g;if(a.fakeKeystroke)return a.fakeKeystroke; -for(g in b)if(b.hasOwnProperty(g)&&b[g]==c)return g}return null},addFeature:function(a){return this.filter.addFeature(a)},setActiveFilter:function(a){a||(a=this.filter);this.activeFilter!==a&&(this.activeFilter=a,this.fire("activeFilterChange"),a===this.filter?this.setActiveEnterMode(null,null):this.setActiveEnterMode(a.getAllowedEnterMode(this.enterMode),a.getAllowedEnterMode(this.shiftEnterMode,!0)))},setActiveEnterMode:function(a,c){a=a?this.blockless?CKEDITOR.ENTER_BR:a:this.enterMode;c=c?this.blockless? -CKEDITOR.ENTER_BR:c:this.shiftEnterMode;if(this.activeEnterMode!=a||this.activeShiftEnterMode!=c)this.activeEnterMode=a,this.activeShiftEnterMode=c,this.fire("activeEnterModeChange")},showNotification:function(a){alert(a)}})}(),CKEDITOR.ELEMENT_MODE_NONE=0,CKEDITOR.ELEMENT_MODE_REPLACE=1,CKEDITOR.ELEMENT_MODE_APPENDTO=2,CKEDITOR.ELEMENT_MODE_INLINE=3,CKEDITOR.htmlParser=function(){this._={htmlPartsRegex:/<(?:(?:\/([^>]+)>)|(?:!--([\S|\s]*?)--\x3e)|(?:([^\/\s>]+)((?:\s+[\w\-:.]+(?:\s*=\s*?(?:(?:"[^"]*")|(?:'[^']*')|[^\s"'\/>]+))?)*)[\S\s]*?(\/?)>))/g}}, -function(){var f=/([\w\-:.]+)(?:(?:\s*=\s*(?:(?:"([^"]*)")|(?:'([^']*)')|([^\s>]+)))|(?=\s|$))/g,h={checked:1,compact:1,declare:1,defer:1,disabled:1,ismap:1,multiple:1,nohref:1,noresize:1,noshade:1,nowrap:1,readonly:1,selected:1};CKEDITOR.htmlParser.prototype={onTagOpen:function(){},onTagClose:function(){},onText:function(){},onCDATA:function(){},onComment:function(){},parse:function(e){for(var k,d,l=0,m;k=this._.htmlPartsRegex.exec(e);){d=k.index;if(d>l)if(l=e.substring(l,d),m)m.push(l);else this.onText(l); -l=this._.htmlPartsRegex.lastIndex;if(d=k[1])if(d=d.toLowerCase(),m&&CKEDITOR.dtd.$cdata[d]&&(this.onCDATA(m.join("")),m=null),!m){this.onTagClose(d);continue}if(m)m.push(k[0]);else if(d=k[3]){if(d=d.toLowerCase(),!/="/.test(d)){var b={},g,c=k[4];k=!!k[5];if(c)for(;g=f.exec(c);){var a=g[1].toLowerCase();g=g[2]||g[3]||g[4]||"";b[a]=!g&&h[a]?a:CKEDITOR.tools.htmlDecodeAttr(g)}this.onTagOpen(d,b,k);!m&&CKEDITOR.dtd.$cdata[d]&&(m=[])}}else if(d=k[2])this.onComment(d)}if(e.length>l)this.onText(e.substring(l, -e.length))}}}(),CKEDITOR.htmlParser.basicWriter=CKEDITOR.tools.createClass({$:function(){this._={output:[]}},proto:{openTag:function(f){this._.output.push("\x3c",f)},openTagClose:function(f,h){h?this._.output.push(" /\x3e"):this._.output.push("\x3e")},attribute:function(f,h){"string"==typeof h&&(h=CKEDITOR.tools.htmlEncodeAttr(h));this._.output.push(" ",f,'\x3d"',h,'"')},closeTag:function(f){this._.output.push("\x3c/",f,"\x3e")},text:function(f){this._.output.push(f)},comment:function(f){this._.output.push("\x3c!--", -f,"--\x3e")},write:function(f){this._.output.push(f)},reset:function(){this._.output=[];this._.indent=!1},getHtml:function(f){var h=this._.output.join("");f&&this.reset();return h}}}),"use strict",function(){CKEDITOR.htmlParser.node=function(){};CKEDITOR.htmlParser.node.prototype={remove:function(){var f=this.parent.children,h=CKEDITOR.tools.indexOf(f,this),e=this.previous,k=this.next;e&&(e.next=k);k&&(k.previous=e);f.splice(h,1);this.parent=null},replaceWith:function(f){var h=this.parent.children, -e=CKEDITOR.tools.indexOf(h,this),k=f.previous=this.previous,d=f.next=this.next;k&&(k.next=f);d&&(d.previous=f);h[e]=f;f.parent=this.parent;this.parent=null},insertAfter:function(f){var h=f.parent.children,e=CKEDITOR.tools.indexOf(h,f),k=f.next;h.splice(e+1,0,this);this.next=f.next;this.previous=f;f.next=this;k&&(k.previous=this);this.parent=f.parent},insertBefore:function(f){var h=f.parent.children,e=CKEDITOR.tools.indexOf(h,f);h.splice(e,0,this);this.next=f;(this.previous=f.previous)&&(f.previous.next= -this);f.previous=this;this.parent=f.parent},getAscendant:function(f){var h="function"==typeof f?f:"string"==typeof f?function(e){return e.name==f}:function(e){return e.name in f},e=this.parent;for(;e&&e.type==CKEDITOR.NODE_ELEMENT;){if(h(e))return e;e=e.parent}return null},wrapWith:function(f){this.replaceWith(f);f.add(this);return f},getIndex:function(){return CKEDITOR.tools.indexOf(this.parent.children,this)},getFilterContext:function(f){return f||{}}}}(),"use strict",CKEDITOR.htmlParser.comment= -function(f){this.value=f;this._={isBlockLike:!1}},CKEDITOR.htmlParser.comment.prototype=CKEDITOR.tools.extend(new CKEDITOR.htmlParser.node,{type:CKEDITOR.NODE_COMMENT,filter:function(f,h){var e=this.value;if(!(e=f.onComment(h,e,this)))return this.remove(),!1;if("string"!=typeof e)return this.replaceWith(e),!1;this.value=e;return!0},writeHtml:function(f,h){h&&this.filter(h);f.comment(this.value)}}),"use strict",function(){CKEDITOR.htmlParser.text=function(f){this.value=f;this._={isBlockLike:!1}};CKEDITOR.htmlParser.text.prototype= -CKEDITOR.tools.extend(new CKEDITOR.htmlParser.node,{type:CKEDITOR.NODE_TEXT,filter:function(f,h){if(!(this.value=f.onText(h,this.value,this)))return this.remove(),!1},writeHtml:function(f,h){h&&this.filter(h);f.text(this.value)}})}(),"use strict",function(){CKEDITOR.htmlParser.cdata=function(f){this.value=f};CKEDITOR.htmlParser.cdata.prototype=CKEDITOR.tools.extend(new CKEDITOR.htmlParser.node,{type:CKEDITOR.NODE_TEXT,filter:function(){},writeHtml:function(f){f.write(this.value)}})}(),"use strict", -CKEDITOR.htmlParser.fragment=function(){this.children=[];this.parent=null;this._={isBlockLike:!0,hasInlineStarted:!1}},function(){function f(d){return d.attributes["data-cke-survive"]?!1:"a"==d.name&&d.attributes.href||CKEDITOR.dtd.$removeEmpty[d.name]}var h=CKEDITOR.tools.extend({table:1,ul:1,ol:1,dl:1},CKEDITOR.dtd.table,CKEDITOR.dtd.ul,CKEDITOR.dtd.ol,CKEDITOR.dtd.dl),e={ol:1,ul:1},k=CKEDITOR.tools.extend({},{html:1},CKEDITOR.dtd.html,CKEDITOR.dtd.body,CKEDITOR.dtd.head,{style:1,script:1}),d={ul:"li", -ol:"li",dl:"dd",table:"tbody",tbody:"tr",thead:"tr",tfoot:"tr",tr:"td"};CKEDITOR.htmlParser.fragment.fromHtml=function(l,m,b){function g(a){var b;if(0<q.length)for(var g=0;g<q.length;g++){var d=q[g],e=d.name,f=CKEDITOR.dtd[e],k=x.name&&CKEDITOR.dtd[x.name];k&&!k[e]||a&&f&&!f[a]&&CKEDITOR.dtd[a]?e==x.name&&(n(x,x.parent,1),g--):(b||(c(),b=1),d=d.clone(),d.parent=x,x=d,q.splice(g,1),g--)}}function c(){for(;u.length;)n(u.shift(),x)}function a(a){if(a._.isBlockLike&&"pre"!=a.name&&"textarea"!=a.name){var c= -a.children.length,b=a.children[c-1],g;b&&b.type==CKEDITOR.NODE_TEXT&&((g=CKEDITOR.tools.rtrim(b.value))?b.value=g:a.children.length=c-1)}}function n(c,g,d){g=g||x||r;var e=x;void 0===c.previous&&(w(g,c)&&(x=g,p.onTagOpen(b,{}),c.returnPoint=g=x),a(c),f(c)&&!c.children.length||g.add(c),"pre"==c.name&&(D=!1),"textarea"==c.name&&(A=!1));c.returnPoint?(x=c.returnPoint,delete c.returnPoint):x=d?g:e}function w(a,c){if((a==r||"body"==a.name)&&b&&(!a.name||CKEDITOR.dtd[a.name][b])){var g,d;return(g=c.attributes&& -(d=c.attributes["data-cke-real-element-type"])?d:c.name)&&g in CKEDITOR.dtd.$inline&&!(g in CKEDITOR.dtd.head)&&!c.isOrphan||c.type==CKEDITOR.NODE_TEXT}}function v(a,c){return a in CKEDITOR.dtd.$listItem||a in CKEDITOR.dtd.$tableContent?a==c||"dt"==a&&"dd"==c||"dd"==a&&"dt"==c:!1}var p=new CKEDITOR.htmlParser,r=m instanceof CKEDITOR.htmlParser.element?m:"string"==typeof m?new CKEDITOR.htmlParser.element(m):new CKEDITOR.htmlParser.fragment,q=[],u=[],x=r,A="textarea"==r.name,D="pre"==r.name;p.onTagOpen= -function(a,b,d,l){b=new CKEDITOR.htmlParser.element(a,b);b.isUnknown&&d&&(b.isEmpty=!0);b.isOptionalClose=l;if(f(b))q.push(b);else{if("pre"==a)D=!0;else{if("br"==a&&D){x.add(new CKEDITOR.htmlParser.text("\n"));return}"textarea"==a&&(A=!0)}if("br"==a)u.push(b);else{for(;!(l=(d=x.name)?CKEDITOR.dtd[d]||(x._.isBlockLike?CKEDITOR.dtd.div:CKEDITOR.dtd.span):k,b.isUnknown||x.isUnknown||l[a]);)if(x.isOptionalClose)p.onTagClose(d);else if(a in e&&d in e)d=x.children,(d=d[d.length-1])&&"li"==d.name||n(d=new CKEDITOR.htmlParser.element("li"), -x),!b.returnPoint&&(b.returnPoint=x),x=d;else if(a in CKEDITOR.dtd.$listItem&&!v(a,d))p.onTagOpen("li"==a?"ul":"dl",{},0,1);else if(d in h&&!v(a,d))!b.returnPoint&&(b.returnPoint=x),x=x.parent;else if(d in CKEDITOR.dtd.$inline&&q.unshift(x),x.parent)n(x,x.parent,1);else{b.isOrphan=1;break}g(a);c();b.parent=x;b.isEmpty?n(b):x=b}}};p.onTagClose=function(a){for(var g=q.length-1;0<=g;g--)if(a==q[g].name){q.splice(g,1);return}for(var d=[],e=[],f=x;f!=r&&f.name!=a;)f._.isBlockLike||e.unshift(f),d.push(f), -f=f.returnPoint||f.parent;if(f!=r){for(g=0;g<d.length;g++){var k=d[g];n(k,k.parent)}x=f;f._.isBlockLike&&c();n(f,f.parent);f==x&&(x=x.parent);q=q.concat(e)}"body"==a&&(b=!1)};p.onText=function(a){if(!(x._.hasInlineStarted&&!u.length||D||A)&&(a=CKEDITOR.tools.ltrim(a),0===a.length))return;var e=x.name,f=e?CKEDITOR.dtd[e]||(x._.isBlockLike?CKEDITOR.dtd.div:CKEDITOR.dtd.span):k;if(!A&&!f["#"]&&e in h)p.onTagOpen(d[e]||""),p.onText(a);else{c();g();D||A||(a=a.replace(/[\t\r\n ]{2,}|[\t\r\n]/g," "));a= -new CKEDITOR.htmlParser.text(a);if(w(x,a))this.onTagOpen(b,{},0,1);x.add(a)}};p.onCDATA=function(a){x.add(new CKEDITOR.htmlParser.cdata(a))};p.onComment=function(a){c();g();x.add(new CKEDITOR.htmlParser.comment(a))};p.parse(l);for(c();x!=r;)n(x,x.parent,1);a(r);return r};CKEDITOR.htmlParser.fragment.prototype={type:CKEDITOR.NODE_DOCUMENT_FRAGMENT,add:function(d,e){isNaN(e)&&(e=this.children.length);var b=0<e?this.children[e-1]:null;if(b){if(d._.isBlockLike&&b.type==CKEDITOR.NODE_TEXT&&(b.value=CKEDITOR.tools.rtrim(b.value), -0===b.value.length)){this.children.pop();this.add(d);return}b.next=d}d.previous=b;d.parent=this;this.children.splice(e,0,d);this._.hasInlineStarted||(this._.hasInlineStarted=d.type==CKEDITOR.NODE_TEXT||d.type==CKEDITOR.NODE_ELEMENT&&!d._.isBlockLike)},filter:function(d,e){e=this.getFilterContext(e);d.onRoot(e,this);this.filterChildren(d,!1,e)},filterChildren:function(d,e,b){if(this.childrenFilteredBy!=d.id){b=this.getFilterContext(b);if(e&&!this.parent)d.onRoot(b,this);this.childrenFilteredBy=d.id; -for(e=0;e<this.children.length;e++)!1===this.children[e].filter(d,b)&&e--}},writeHtml:function(d,e){e&&this.filter(e);this.writeChildrenHtml(d)},writeChildrenHtml:function(d,e,b){var g=this.getFilterContext();if(b&&!this.parent&&e)e.onRoot(g,this);e&&this.filterChildren(e,!1,g);e=0;b=this.children;for(g=b.length;e<g;e++)b[e].writeHtml(d)},forEach:function(d,e,b){if(!(b||e&&this.type!=e))var g=d(this);if(!1!==g){b=this.children;for(var c=0;c<b.length;c++)g=b[c],g.type==CKEDITOR.NODE_ELEMENT?g.forEach(d, +1),this.allow(G[a.enterMode]+" "+G[a.shiftEnterMode],"default",1),this.disallow(a.config.disallowedContent))}else this.customConfig=!1,this.allow(a,"default",1)};CKEDITOR.filter.instances={};CKEDITOR.filter.prototype={allow:function(c,b,d){if(!l(this,c,d))return!1;var g,e;if("string"==typeof c)c=a(c);else if(c instanceof CKEDITOR.style){if(c.toAllowedContentRules)return this.allow(c.toAllowedContentRules(this.editor),b,d);g=c.getDefinition();c={};d=g.attributes;c[g.element]=g={styles:g.styles,requiredStyles:g.styles&& +CKEDITOR.tools.objectKeys(g.styles)};d&&(d=E(d),g.classes=d["class"]?d["class"].split(/\s+/):null,g.requiredClasses=g.classes,delete d["class"],g.attributes=d,g.requiredAttributes=d&&CKEDITOR.tools.objectKeys(d))}else if(CKEDITOR.tools.isArray(c)){for(g=0;g<c.length;++g)e=this.allow(c[g],b,d);return e}f(this,c,b,this.allowedContent,this._.allowedRules);return!0},applyTo:function(a,c,b,d){if(this.disabled)return!1;var g=this,e=[],f=this.editor&&this.editor.config.protectedSource,k,h=!1,n={doFilter:!b, +doTransform:!0,doCallbacks:!0,toHtml:c};a.forEach(function(a){if(a.type==CKEDITOR.NODE_ELEMENT){if("off"==a.attributes["data-cke-filter"])return!1;if(!c||"span"!=a.name||!~CKEDITOR.tools.objectKeys(a.attributes).join("|").indexOf("data-cke-"))if(k=v(g,a,e,n),k&1)h=!0;else if(k&2)return!1}else if(a.type==CKEDITOR.NODE_COMMENT&&a.value.match(/^\{cke_protected\}(?!\{C\})/)){var b;a:{var d=decodeURIComponent(a.value.replace(/^\{cke_protected\}/,""));b=[];var l,q,m;if(f)for(q=0;q<f.length;++q)if((m=d.match(f[q]))&& +m[0].length==d.length){b=!0;break a}d=CKEDITOR.htmlParser.fragment.fromHtml(d);1==d.children.length&&(l=d.children[0]).type==CKEDITOR.NODE_ELEMENT&&v(g,l,b,n);b=!b.length}b||e.push(a)}},null,!0);e.length&&(h=!0);var l;a=[];d=G[d||(this.editor?this.editor.enterMode:CKEDITOR.ENTER_P)];for(var m;b=e.pop();)b.type==CKEDITOR.NODE_ELEMENT?B(b,d,a):b.remove();for(;l=a.pop();)if(b=l.el,b.parent)switch(m=F[b.parent.name]||F.span,l.check){case "it":F.$removeEmpty[b.name]&&!b.children.length?B(b,d,a):q(b)|| +B(b,d,a);break;case "el-up":b.parent.type==CKEDITOR.NODE_DOCUMENT_FRAGMENT||m[b.name]||B(b,d,a);break;case "parent-down":b.parent.type==CKEDITOR.NODE_DOCUMENT_FRAGMENT||m[b.name]||B(b.parent,d,a)}return h},checkFeature:function(a){if(this.disabled||!a)return!0;a.toFeature&&(a=a.toFeature(this.editor));return!a.requiredContent||this.check(a.requiredContent)},disable:function(){this.disabled=!0},disallow:function(c){if(!l(this,c,!0))return!1;"string"==typeof c&&(c=a(c));f(this,c,null,this.disallowedContent, +this._.disallowedRules);return!0},addContentForms:function(a){if(!this.disabled&&a){var c,b,d=[],g;for(c=0;c<a.length&&!g;++c)b=a[c],("string"==typeof b||b instanceof CKEDITOR.style)&&this.check(b)&&(g=b);if(g){for(c=0;c<a.length;++c)d.push(x(a[c],g));this.addTransformations(d)}}},addElementCallback:function(a){this.elementCallbacks||(this.elementCallbacks=[]);this.elementCallbacks.push(a)},addFeature:function(a){if(this.disabled||!a)return!0;a.toFeature&&(a=a.toFeature(this.editor));this.allow(a.allowedContent, +a.name);this.addTransformations(a.contentTransformations);this.addContentForms(a.contentForms);return a.requiredContent&&(this.customConfig||this.disallowedContent.length)?this.check(a.requiredContent):!0},addTransformations:function(a){var c,b;if(!this.disabled&&a){var d=this._.transformations,g;for(g=0;g<a.length;++g){c=a[g];var e=void 0,f=void 0,k=void 0,h=void 0,n=void 0,l=void 0;b=[];for(f=0;f<c.length;++f)k=c[f],"string"==typeof k?(k=k.split(/\s*:\s*/),h=k[0],n=null,l=k[1]):(h=k.check,n=k.left, +l=k.right),e||(e=k,e=e.element?e.element:h?h.match(/^([a-z0-9]+)/i)[0]:e.left.getDefinition().element),n instanceof CKEDITOR.style&&(n=z(n)),b.push({check:h==e?null:h,left:n,right:"string"==typeof l?I(l):l});c=e;d[c]||(d[c]=[]);d[c].push(b)}}},check:function(b,d,g){if(this.disabled)return!0;if(CKEDITOR.tools.isArray(b)){for(var e=b.length;e--;)if(this.check(b[e],d,g))return!0;return!1}var f,k;if("string"==typeof b){k=b+"\x3c"+(!1===d?"0":"1")+(g?"1":"0")+"\x3e";if(k in this._.cachedChecks)return this._.cachedChecks[k]; +f=a(b).$1;var h=f.styles,e=f.classes;f.name=f.elements;f.classes=e=e?e.split(/\s*,\s*/):[];f.styles=c(h);f.attributes=c(f.attributes);f.children=[];e.length&&(f.attributes["class"]=e.join(" "));h&&(f.attributes.style=CKEDITOR.tools.writeCssText(f.styles))}else f=b.getDefinition(),h=f.styles,e=f.attributes||{},h&&!CKEDITOR.tools.isEmpty(h)?(h=E(h),e.style=CKEDITOR.tools.writeCssText(h,!0)):h={},f={name:f.element,attributes:e,classes:e["class"]?e["class"].split(/\s+/):[],styles:h,children:[]};var h= +CKEDITOR.tools.clone(f),n=[],l;if(!1!==d&&(l=this._.transformations[f.name])){for(e=0;e<l.length;++e)u(this,f,l[e]);p(f)}v(this,h,n,{doFilter:!0,doTransform:!1!==d,skipRequired:!g,skipFinalValidation:!g});0<n.length?g=!1:((d=f.attributes["class"])&&(f.attributes["class"]=f.attributes["class"].split(" ").sort().join(" ")),g=CKEDITOR.tools.objectCompare(f.attributes,h.attributes,!0),d&&(f.attributes["class"]=d));"string"==typeof b&&(this._.cachedChecks[k]=g);return g},getAllowedEnterMode:function(){var a= +["p","div","br"],c={p:CKEDITOR.ENTER_P,div:CKEDITOR.ENTER_DIV,br:CKEDITOR.ENTER_BR};return function(b,d){var g=a.slice(),e;if(this.check(G[b]))return b;for(d||(g=g.reverse());e=g.pop();)if(this.check(e))return c[e];return CKEDITOR.ENTER_BR}}(),clone:function(){var a=new CKEDITOR.filter,c=CKEDITOR.tools.clone;a.allowedContent=c(this.allowedContent);a._.allowedRules=c(this._.allowedRules);a.disallowedContent=c(this.disallowedContent);a._.disallowedRules=c(this._.disallowedRules);a._.transformations= +c(this._.transformations);a.disabled=this.disabled;a.editor=this.editor;return a},destroy:function(){delete CKEDITOR.filter.instances[this.id];delete this._;delete this.allowedContent;delete this.disallowedContent}};var L={styles:1,attributes:1,classes:1},O={styles:"requiredStyles",attributes:"requiredAttributes",classes:"requiredClasses"},D=/^([a-z0-9\-*\s]+)((?:\s*\{[!\w\-,\s\*]+\}\s*|\s*\[[!\w\-,\s\*]+\]\s*|\s*\([!\w\-,\s\*]+\)\s*){0,3})(?:;\s*|$)/i,S={styles:/{([^}]+)}/,attrs:/\[([^\]]+)\]/,classes:/\(([^\)]+)\)/}, +J=/^cke:(object|embed|param)$/,R=/^(object|embed|param)$/,K;K=CKEDITOR.filter.transformationsTools={sizeToStyle:function(a){this.lengthToStyle(a,"width");this.lengthToStyle(a,"height")},sizeToAttribute:function(a){this.lengthToAttribute(a,"width");this.lengthToAttribute(a,"height")},lengthToStyle:function(a,c,b){b=b||c;if(!(b in a.styles)){var d=a.attributes[c];d&&(/^\d+$/.test(d)&&(d+="px"),a.styles[b]=d)}delete a.attributes[c]},lengthToAttribute:function(a,c,b){b=b||c;if(!(b in a.attributes)){var d= +a.styles[c],g=d&&d.match(/^(\d+)(?:\.\d*)?px$/);g?a.attributes[b]=g[1]:"cke-test"==d&&(a.attributes[b]="cke-test")}delete a.styles[c]},alignmentToStyle:function(a){if(!("float"in a.styles)){var c=a.attributes.align;if("left"==c||"right"==c)a.styles["float"]=c}delete a.attributes.align},alignmentToAttribute:function(a){if(!("align"in a.attributes)){var c=a.styles["float"];if("left"==c||"right"==c)a.attributes.align=c}delete a.styles["float"]},splitBorderShorthand:function(a){if(a.styles.border){var c= +CKEDITOR.tools.style.parse.border(a.styles.border);c.color&&(a.styles["border-color"]=c.color);c.style&&(a.styles["border-style"]=c.style);c.width&&(a.styles["border-width"]=c.width);delete a.styles.border}},listTypeToStyle:function(a){if(a.attributes.type)switch(a.attributes.type){case "a":a.styles["list-style-type"]="lower-alpha";break;case "A":a.styles["list-style-type"]="upper-alpha";break;case "i":a.styles["list-style-type"]="lower-roman";break;case "I":a.styles["list-style-type"]="upper-roman"; +break;case "1":a.styles["list-style-type"]="decimal";break;default:a.styles["list-style-type"]=a.attributes.type}},splitMarginShorthand:function(a){function c(d){a.styles["margin-top"]=b[d[0]];a.styles["margin-right"]=b[d[1]];a.styles["margin-bottom"]=b[d[2]];a.styles["margin-left"]=b[d[3]]}if(a.styles.margin){var b=a.styles.margin.match(/(\-?[\.\d]+\w+)/g)||["0px"];switch(b.length){case 1:c([0,0,0,0]);break;case 2:c([0,1,0,1]);break;case 3:c([0,1,2,1]);break;case 4:c([0,1,2,3])}delete a.styles.margin}}, +matchesStyle:y,transform:function(a,c){if("string"==typeof c)a.name=c;else{var b=c.getDefinition(),d=b.styles,g=b.attributes,e,f,k,h;a.name=b.element;for(e in g)if("class"==e)for(b=a.classes.join("|"),k=g[e].split(/\s+/);h=k.pop();)-1==b.indexOf(h)&&a.classes.push(h);else a.attributes[e]=g[e];for(f in d)a.styles[f]=d[f]}}}}(),function(){CKEDITOR.focusManager=function(f){if(f.focusManager)return f.focusManager;this.hasFocus=!1;this.currentActive=null;this._={editor:f};return this};CKEDITOR.focusManager._= +{blurDelay:200};CKEDITOR.focusManager.prototype={focus:function(f){this._.timer&&clearTimeout(this._.timer);f&&(this.currentActive=f);this.hasFocus||this._.locked||((f=CKEDITOR.currentInstance)&&f.focusManager.blur(1),this.hasFocus=!0,(f=this._.editor.container)&&f.addClass("cke_focus"),this._.editor.fire("focus"))},lock:function(){this._.locked=1},unlock:function(){delete this._.locked},blur:function(f){function h(){if(this.hasFocus){this.hasFocus=!1;var e=this._.editor.container;e&&e.removeClass("cke_focus"); +this._.editor.fire("blur")}}if(!this._.locked){this._.timer&&clearTimeout(this._.timer);var e=CKEDITOR.focusManager._.blurDelay;f||!e?h.call(this):this._.timer=CKEDITOR.tools.setTimeout(function(){delete this._.timer;h.call(this)},e,this)}},add:function(f,h){var e=f.getCustomData("focusmanager");if(!e||e!=this){e&&e.remove(f);var e="focus",k="blur";h&&(CKEDITOR.env.ie?(e="focusin",k="focusout"):CKEDITOR.event.useCapture=1);var d={blur:function(){f.equals(this.currentActive)&&this.blur()},focus:function(){this.focus(f)}}; +f.on(e,d.focus,this);f.on(k,d.blur,this);h&&(CKEDITOR.event.useCapture=0);f.setCustomData("focusmanager",this);f.setCustomData("focusmanager_handlers",d)}},remove:function(f){f.removeCustomData("focusmanager");var h=f.removeCustomData("focusmanager_handlers");f.removeListener("blur",h.blur);f.removeListener("focus",h.focus)}}}(),CKEDITOR.keystrokeHandler=function(f){if(f.keystrokeHandler)return f.keystrokeHandler;this.keystrokes={};this.blockedKeystrokes={};this._={editor:f};return this},function(){var f, +h=function(e){e=e.data;var d=e.getKeystroke(),h=this.keystrokes[d],m=this._.editor;f=!1===m.fire("key",{keyCode:d,domEvent:e});f||(h&&(f=!1!==m.execCommand(h,{from:"keystrokeHandler"})),f||(f=!!this.blockedKeystrokes[d]));f&&e.preventDefault(!0);return!f},e=function(e){f&&(f=!1,e.data.preventDefault(!0))};CKEDITOR.keystrokeHandler.prototype={attach:function(f){f.on("keydown",h,this);if(CKEDITOR.env.gecko&&CKEDITOR.env.mac)f.on("keypress",e,this)}}}(),function(){CKEDITOR.lang={languages:{af:1,ar:1, +az:1,bg:1,bn:1,bs:1,ca:1,cs:1,cy:1,da:1,de:1,"de-ch":1,el:1,"en-au":1,"en-ca":1,"en-gb":1,en:1,eo:1,es:1,"es-mx":1,et:1,eu:1,fa:1,fi:1,fo:1,"fr-ca":1,fr:1,gl:1,gu:1,he:1,hi:1,hr:1,hu:1,id:1,is:1,it:1,ja:1,ka:1,km:1,ko:1,ku:1,lt:1,lv:1,mk:1,mn:1,ms:1,nb:1,nl:1,no:1,oc:1,pl:1,"pt-br":1,pt:1,ro:1,ru:1,si:1,sk:1,sl:1,sq:1,"sr-latn":1,sr:1,sv:1,th:1,tr:1,tt:1,ug:1,uk:1,vi:1,"zh-cn":1,zh:1},rtl:{ar:1,fa:1,he:1,ku:1,ug:1},load:function(f,h,e){f&&CKEDITOR.lang.languages[f]||(f=this.detect(h,f));var k=this; +h=function(){k[f].dir=k.rtl[f]?"rtl":"ltr";e(f,k[f])};this[f]?h():CKEDITOR.scriptLoader.load(CKEDITOR.getUrl("lang/"+f+".js"),h,this)},detect:function(f,h){var e=this.languages;h=h||navigator.userLanguage||navigator.language||f;var k=h.toLowerCase().match(/([a-z]+)(?:-([a-z]+))?/),d=k[1],k=k[2];e[d+"-"+k]?d=d+"-"+k:e[d]||(d=null);CKEDITOR.lang.detect=d?function(){return d}:function(d){return d};return d||f}}}(),CKEDITOR.scriptLoader=function(){var f={},h={};return{load:function(e,k,d,l){var m="string"== +typeof e;m&&(e=[e]);d||(d=CKEDITOR);var b=e.length,g=[],c=[],a=function(a){k&&(m?k.call(d,a):k.call(d,g,c))};if(0===b)a(!0);else{var n=function(d,e){(e?g:c).push(d);0>=--b&&(l&&CKEDITOR.document.getDocumentElement().removeStyle("cursor"),a(e))},w=function(a,c){f[a]=1;var b=h[a];delete h[a];for(var d=0;d<b.length;d++)b[d](a,c)},v=function(a){if(f[a])n(a,!0);else{var c=h[a]||(h[a]=[]);c.push(n);if(!(1<c.length)){var b=new CKEDITOR.dom.element("script");b.setAttributes({type:"text/javascript",src:a}); +k&&(CKEDITOR.env.ie&&(8>=CKEDITOR.env.version||CKEDITOR.env.ie9Compat)?b.$.onreadystatechange=function(){if("loaded"==b.$.readyState||"complete"==b.$.readyState)b.$.onreadystatechange=null,w(a,!0)}:(b.$.onload=function(){setTimeout(function(){w(a,!0)},0)},b.$.onerror=function(){w(a,!1)}));b.appendTo(CKEDITOR.document.getHead())}}};l&&CKEDITOR.document.getDocumentElement().setStyle("cursor","wait");for(var t=0;t<b;t++)v(e[t])}},queue:function(){function e(){var d;(d=f[0])&&this.load(d.scriptUrl,d.callback, +CKEDITOR,0)}var f=[];return function(d,h){var m=this;f.push({scriptUrl:d,callback:function(){h&&h.apply(this,arguments);f.shift();e.call(m)}});1==f.length&&e.call(this)}}()}}(),CKEDITOR.resourceManager=function(f,h){this.basePath=f;this.fileName=h;this.registered={};this.loaded={};this.externals={};this._={waitingList:{}}},CKEDITOR.resourceManager.prototype={add:function(f,h){if(this.registered[f])throw Error('[CKEDITOR.resourceManager.add] The resource name "'+f+'" is already registered.');var e= +this.registered[f]=h||{};e.name=f;e.path=this.getPath(f);CKEDITOR.fire(f+CKEDITOR.tools.capitalize(this.fileName)+"Ready",e);return this.get(f)},get:function(f){return this.registered[f]||null},getPath:function(f){var h=this.externals[f];return CKEDITOR.getUrl(h&&h.dir||this.basePath+f+"/")},getFilePath:function(f){var h=this.externals[f];return CKEDITOR.getUrl(this.getPath(f)+(h?h.file:this.fileName+".js"))},addExternal:function(f,h,e){f=f.split(",");for(var k=0;k<f.length;k++){var d=f[k];e||(h= +h.replace(/[^\/]+$/,function(d){e=d;return""}));this.externals[d]={dir:h,file:e||this.fileName+".js"}}},load:function(f,h,e){CKEDITOR.tools.isArray(f)||(f=f?[f]:[]);for(var k=this.loaded,d=this.registered,l=[],m={},b={},g=0;g<f.length;g++){var c=f[g];if(c)if(k[c]||d[c])b[c]=this.get(c);else{var a=this.getFilePath(c);l.push(a);a in m||(m[a]=[]);m[a].push(c)}}CKEDITOR.scriptLoader.load(l,function(a,c){if(c.length)throw Error('[CKEDITOR.resourceManager.load] Resource name "'+m[c[0]].join(",")+'" was not found at "'+ +c[0]+'".');for(var d=0;d<a.length;d++)for(var g=m[a[d]],f=0;f<g.length;f++){var l=g[f];b[l]=this.get(l);k[l]=1}h.call(e,b)},this)}},CKEDITOR.plugins=new CKEDITOR.resourceManager("plugins/","plugin"),CKEDITOR.plugins.load=CKEDITOR.tools.override(CKEDITOR.plugins.load,function(f){var h={};return function(e,k,d){var l={},m=function(b){f.call(this,b,function(b){CKEDITOR.tools.extend(l,b);var c=[],a;for(a in b){var e=b[a],f=e&&e.requires;if(!h[a]){if(e.icons)for(var v=e.icons.split(","),t=v.length;t--;)CKEDITOR.skin.addIcon(v[t], +e.path+"icons/"+(CKEDITOR.env.hidpi&&e.hidpi?"hidpi/":"")+v[t]+".png");h[a]=1}if(f)for(f.split&&(f=f.split(",")),e=0;e<f.length;e++)l[f[e]]||c.push(f[e])}if(c.length)m.call(this,c);else{for(a in l)e=l[a],e.onLoad&&!e.onLoad._called&&(!1===e.onLoad()&&delete l[a],e.onLoad._called=1);k&&k.call(d||window,l)}},this)};m.call(this,e)}}),CKEDITOR.plugins.setLang=function(f,h,e){var k=this.get(f);f=k.langEntries||(k.langEntries={});k=k.lang||(k.lang=[]);k.split&&(k=k.split(","));-1==CKEDITOR.tools.indexOf(k, +h)&&k.push(h);f[h]=e},CKEDITOR.ui=function(f){if(f.ui)return f.ui;this.items={};this.instances={};this.editor=f;this._={handlers:{}};return this},CKEDITOR.ui.prototype={add:function(f,h,e){e.name=f.toLowerCase();var k=this.items[f]={type:h,command:e.command||null,args:Array.prototype.slice.call(arguments,2)};CKEDITOR.tools.extend(k,e)},get:function(f){return this.instances[f]},create:function(f){var h=this.items[f],e=h&&this._.handlers[h.type],k=h&&h.command&&this.editor.getCommand(h.command),e=e&& +e.create.apply(this,h.args);this.instances[f]=e;k&&k.uiItems.push(e);e&&!e.type&&(e.type=h.type);return e},addHandler:function(f,h){this._.handlers[f]=h},space:function(f){return CKEDITOR.document.getById(this.spaceId(f))},spaceId:function(f){return this.editor.id+"_"+f}},CKEDITOR.event.implementOn(CKEDITOR.ui),function(){function f(a,c,d){CKEDITOR.event.call(this);a=a&&CKEDITOR.tools.clone(a);if(void 0!==c){if(!(c instanceof CKEDITOR.dom.element))throw Error("Expect element of type CKEDITOR.dom.element."); +if(!d)throw Error("One of the element modes must be specified.");if(CKEDITOR.env.ie&&CKEDITOR.env.quirks&&d==CKEDITOR.ELEMENT_MODE_INLINE)throw Error("Inline element mode is not supported on IE quirks.");if(!e(c,d))throw Error('The specified element mode is not supported on element: "'+c.getName()+'".');this.element=c;this.elementMode=d;this.name=this.elementMode!=CKEDITOR.ELEMENT_MODE_APPENDTO&&(c.getId()||c.getNameAtt())}else this.elementMode=CKEDITOR.ELEMENT_MODE_NONE;this._={};this.commands={}; +this.templates={};this.name=this.name||h();this.id=CKEDITOR.tools.getNextId();this.status="unloaded";this.config=CKEDITOR.tools.prototypedCopy(CKEDITOR.config);this.ui=new CKEDITOR.ui(this);this.focusManager=new CKEDITOR.focusManager(this);this.keystrokeHandler=new CKEDITOR.keystrokeHandler(this);this.on("readOnly",k);this.on("selectionChange",function(a){l(this,a.data.path)});this.on("activeFilterChange",function(){l(this,this.elementPath(),!0)});this.on("mode",k);this.on("instanceReady",function(){if(this.config.startupFocus){if("end"=== +this.config.startupFocus){var a=this.createRange();a.selectNodeContents(this.editable());a.shrink(CKEDITOR.SHRINK_ELEMENT,!0);a.collapse();this.getSelection().selectRanges([a])}this.focus()}});CKEDITOR.fire("instanceCreated",null,this);CKEDITOR.add(this);CKEDITOR.tools.setTimeout(function(){"destroyed"!==this.status?b(this,a):CKEDITOR.warn("editor-incorrect-destroy")},0,this)}function h(){do var a="editor"+ ++t;while(CKEDITOR.instances[a]);return a}function e(a,c){return c==CKEDITOR.ELEMENT_MODE_INLINE? +a.is(CKEDITOR.dtd.$editable)||a.is("textarea"):c==CKEDITOR.ELEMENT_MODE_REPLACE?!a.is(CKEDITOR.dtd.$nonBodyContent):1}function k(){var a=this.commands,c;for(c in a)d(this,a[c])}function d(a,c){c[c.startDisabled?"disable":a.readOnly&&!c.readOnly?"disable":c.modes[a.mode]?"enable":"disable"]()}function l(a,c,b){if(c){var d,g,e=a.commands;for(g in e)d=e[g],(b||d.contextSensitive)&&d.refresh(a,c)}}function m(a){var c=a.config.customConfig;if(!c)return!1;var c=CKEDITOR.getUrl(c),b=p[c]||(p[c]={});b.fn? +(b.fn.call(a,a.config),CKEDITOR.getUrl(a.config.customConfig)!=c&&m(a)||a.fireOnce("customConfigLoaded")):CKEDITOR.scriptLoader.queue(c,function(){b.fn=CKEDITOR.editorConfig?CKEDITOR.editorConfig:function(){};m(a)});return!0}function b(a,c){a.on("customConfigLoaded",function(){if(c){if(c.on)for(var b in c.on)a.on(b,c.on[b]);CKEDITOR.tools.extend(a.config,c,!0);delete a.config.on}b=a.config;a.readOnly=b.readOnly?!0:a.elementMode==CKEDITOR.ELEMENT_MODE_INLINE?a.element.is("textarea")?a.element.hasAttribute("disabled")|| +a.element.hasAttribute("readonly"):a.element.isReadOnly():a.elementMode==CKEDITOR.ELEMENT_MODE_REPLACE?a.element.hasAttribute("disabled")||a.element.hasAttribute("readonly"):!1;a.blockless=a.elementMode==CKEDITOR.ELEMENT_MODE_INLINE?!(a.element.is("textarea")||CKEDITOR.dtd[a.element.getName()].p):!1;a.tabIndex=b.tabIndex||a.element&&a.element.getAttribute("tabindex")||0;a.activeEnterMode=a.enterMode=a.blockless?CKEDITOR.ENTER_BR:b.enterMode;a.activeShiftEnterMode=a.shiftEnterMode=a.blockless?CKEDITOR.ENTER_BR: +b.shiftEnterMode;b.skin&&(CKEDITOR.skinName=b.skin);a.fireOnce("configLoaded");a.dataProcessor=new CKEDITOR.htmlDataProcessor(a);a.filter=a.activeFilter=new CKEDITOR.filter(a);g(a)});c&&null!=c.customConfig&&(a.config.customConfig=c.customConfig);m(a)||a.fireOnce("customConfigLoaded")}function g(a){CKEDITOR.skin.loadPart("editor",function(){c(a)})}function c(c){CKEDITOR.lang.load(c.config.language,c.config.defaultLanguage,function(b,d){var g=c.config.title;c.langCode=b;c.lang=CKEDITOR.tools.prototypedCopy(d); +c.title="string"==typeof g||!1===g?g:[c.lang.editor,c.name].join(", ");c.config.contentsLangDirection||(c.config.contentsLangDirection=c.elementMode==CKEDITOR.ELEMENT_MODE_INLINE?c.element.getDirection(1):c.lang.dir);c.fire("langLoaded");a(c)})}function a(a){a.getStylesSet(function(c){a.once("loaded",function(){a.fire("stylesSet",{styles:c})},null,null,1);n(a)})}function n(a){function c(a){if(!a)return"";CKEDITOR.tools.isArray(a)&&(a=a.join(","));return a.replace(/\s/g,"")}var b=a.config,d=c(b.plugins), +g=c(b.extraPlugins),e=c(b.removePlugins);if(g)var f=new RegExp("(?:^|,)(?:"+g.replace(/,/g,"|")+")(?\x3d,|$)","g"),d=d.replace(f,""),d=d+(","+g);if(e)var k=new RegExp("(?:^|,)(?:"+e.replace(/,/g,"|")+")(?\x3d,|$)","g"),d=d.replace(k,"");CKEDITOR.env.air&&(d+=",adobeair");CKEDITOR.plugins.load(d.split(","),function(c){var d=[],g=[],e=[];a.plugins=CKEDITOR.tools.extend({},a.plugins,c);for(var f in c){var h=c[f],n=h.lang,l=null,m=h.requires,u;CKEDITOR.tools.isArray(m)&&(m=m.join(","));if(m&&(u=m.match(k)))for(;m= +u.pop();)CKEDITOR.error("editor-plugin-required",{plugin:m.replace(",",""),requiredBy:f});n&&!a.lang[f]&&(n.split&&(n=n.split(",")),0<=CKEDITOR.tools.indexOf(n,a.langCode)?l=a.langCode:(l=a.langCode.replace(/-.*/,""),l=l!=a.langCode&&0<=CKEDITOR.tools.indexOf(n,l)?l:0<=CKEDITOR.tools.indexOf(n,"en")?"en":n[0]),h.langEntries&&h.langEntries[l]?(a.lang[f]=h.langEntries[l],l=null):e.push(CKEDITOR.getUrl(h.path+"lang/"+l+".js")));g.push(l);d.push(h)}CKEDITOR.scriptLoader.load(e,function(){for(var c=["beforeInit", +"init","afterInit"],e=0;e<c.length;e++)for(var f=0;f<d.length;f++){var k=d[f];0===e&&g[f]&&k.lang&&k.langEntries&&(a.lang[k.name]=k.langEntries[g[f]]);if(k[c[e]])k[c[e]](a)}a.fireOnce("pluginsLoaded");b.keystrokes&&a.setKeystroke(a.config.keystrokes);for(f=0;f<a.config.blockedKeystrokes.length;f++)a.keystrokeHandler.blockedKeystrokes[a.config.blockedKeystrokes[f]]=1;a.status="loaded";a.fireOnce("loaded");CKEDITOR.fire("instanceLoaded",null,a)})})}function w(){var a=this.element;if(a&&this.elementMode!= +CKEDITOR.ELEMENT_MODE_APPENDTO){var c=this.getData();this.config.htmlEncodeOutput&&(c=CKEDITOR.tools.htmlEncode(c));a.is("textarea")?a.setValue(c):a.setHtml(c);return!0}return!1}function v(a,c){function b(a){var c=a.startContainer,d=a.endContainer;return c.is&&(c.is("tr")||c.is("td")&&c.equals(d)&&a.endOffset===c.getChildCount())?!0:!1}function d(a){var c=a.startContainer;return c.is("tr")?a.cloneContents():c.clone(!0)}for(var g=new CKEDITOR.dom.documentFragment,e,f,k,h=0;h<a.length;h++){var n=a[h], +l=n.startContainer.getAscendant("tr",!0);b(n)?(e||(e=l.getAscendant("table").clone(),e.append(l.getAscendant({thead:1,tbody:1,tfoot:1}).clone()),g.append(e),e=e.findOne("thead, tbody, tfoot")),f&&f.equals(l)||(f=l,k=l.clone(),e.append(k)),k.append(d(n))):g.append(n.cloneContents())}return e?g:c.getHtmlFromRange(a[0])}f.prototype=CKEDITOR.editor.prototype;CKEDITOR.editor=f;var t=0,p={};CKEDITOR.tools.extend(CKEDITOR.editor.prototype,{plugins:{detectConflict:function(a,c){for(var b=0;b<c.length;b++){var d= +c[b];if(this[d])return CKEDITOR.warn("editor-plugin-conflict",{plugin:a,replacedWith:d}),!0}return!1}},addCommand:function(a,c){c.name=a.toLowerCase();var b=c instanceof CKEDITOR.command?c:new CKEDITOR.command(this,c);this.mode&&d(this,b);return this.commands[a]=b},_attachToForm:function(){function a(c){b.updateElement();b._.required&&!d.getValue()&&!1===b.fire("required")&&c.data.preventDefault()}function c(a){return!!(a&&a.call&&a.apply)}var b=this,d=b.element,g=new CKEDITOR.dom.element(d.$.form); +d.is("textarea")&&g&&(g.on("submit",a),c(g.$.submit)&&(g.$.submit=CKEDITOR.tools.override(g.$.submit,function(c){return function(){a();c.apply?c.apply(this):c()}})),b.on("destroy",function(){g.removeListener("submit",a)}))},destroy:function(a){this.fire("beforeDestroy");!a&&w.call(this);this.editable(null);this.filter&&(this.filter.destroy(),delete this.filter);delete this.activeFilter;this.status="destroyed";this.fire("destroy");this.removeAllListeners();CKEDITOR.remove(this);CKEDITOR.fire("instanceDestroyed", +null,this)},elementPath:function(a){if(!a){a=this.getSelection();if(!a)return null;a=a.getStartElement()}return a?new CKEDITOR.dom.elementPath(a,this.editable()):null},createRange:function(){var a=this.editable();return a?new CKEDITOR.dom.range(a):null},execCommand:function(a,c){var b=this.getCommand(a),d={name:a,commandData:c||{},command:b};return b&&b.state!=CKEDITOR.TRISTATE_DISABLED&&!1!==this.fire("beforeCommandExec",d)&&(d.returnValue=b.exec(d.commandData),!b.async&&!1!==this.fire("afterCommandExec", +d))?d.returnValue:!1},getCommand:function(a){return this.commands[a]},getData:function(a){!a&&this.fire("beforeGetData");var c=this._.data;"string"!=typeof c&&(c=(c=this.element)&&this.elementMode==CKEDITOR.ELEMENT_MODE_REPLACE?c.is("textarea")?c.getValue():c.getHtml():"");c={dataValue:c};!a&&this.fire("getData",c);return c.dataValue},getSnapshot:function(){var a=this.fire("getSnapshot");"string"!=typeof a&&(a=(a=this.element)&&this.elementMode==CKEDITOR.ELEMENT_MODE_REPLACE?a.is("textarea")?a.getValue(): +a.getHtml():"");return a},loadSnapshot:function(a){this.fire("loadSnapshot",a)},setData:function(a,c,b){var d=!0,g=c;c&&"object"==typeof c&&(b=c.internal,g=c.callback,d=!c.noSnapshot);!b&&d&&this.fire("saveSnapshot");if(g||!b)this.once("dataReady",function(a){!b&&d&&this.fire("saveSnapshot");g&&g.call(a.editor)});a={dataValue:a};!b&&this.fire("setData",a);this._.data=a.dataValue;!b&&this.fire("afterSetData",a)},setReadOnly:function(a){a=null==a||a;this.readOnly!=a&&(this.readOnly=a,this.keystrokeHandler.blockedKeystrokes[8]= ++a,this.editable().setReadOnly(a),this.fire("readOnly"))},insertHtml:function(a,c,b){this.fire("insertHtml",{dataValue:a,mode:c,range:b})},insertText:function(a){this.fire("insertText",a)},insertElement:function(a){this.fire("insertElement",a)},getSelectedHtml:function(a){var c=this.editable(),b=this.getSelection(),b=b&&b.getRanges();if(!c||!b||0===b.length)return null;c=v(b,c);return a?c.getHtml():c},extractSelectedHtml:function(a,c){var b=this.editable(),d=this.getSelection().getRanges(),g=new CKEDITOR.dom.documentFragment, +e;if(!b||0===d.length)return null;for(e=0;e<d.length;e++)g.append(b.extractHtmlFromRange(d[e],c));c||this.getSelection().selectRanges([d[0]]);return a?g.getHtml():g},focus:function(){this.fire("beforeFocus")},checkDirty:function(){return"ready"==this.status&&this._.previousValue!==this.getSnapshot()},resetDirty:function(){this._.previousValue=this.getSnapshot()},updateElement:function(){return w.call(this)},setKeystroke:function(){for(var a=this.keystrokeHandler.keystrokes,c=CKEDITOR.tools.isArray(arguments[0])? +arguments[0]:[[].slice.call(arguments,0)],b,d,g=c.length;g--;)b=c[g],d=0,CKEDITOR.tools.isArray(b)&&(d=b[1],b=b[0]),d?a[b]=d:delete a[b]},getCommandKeystroke:function(a){if(a="string"===typeof a?this.getCommand(a):a){var c=CKEDITOR.tools.object.findKey(this.commands,a),b=this.keystrokeHandler.keystrokes,d;if(a.fakeKeystroke)return a.fakeKeystroke;for(d in b)if(b.hasOwnProperty(d)&&b[d]==c)return d}return null},addFeature:function(a){return this.filter.addFeature(a)},setActiveFilter:function(a){a|| +(a=this.filter);this.activeFilter!==a&&(this.activeFilter=a,this.fire("activeFilterChange"),a===this.filter?this.setActiveEnterMode(null,null):this.setActiveEnterMode(a.getAllowedEnterMode(this.enterMode),a.getAllowedEnterMode(this.shiftEnterMode,!0)))},setActiveEnterMode:function(a,c){a=a?this.blockless?CKEDITOR.ENTER_BR:a:this.enterMode;c=c?this.blockless?CKEDITOR.ENTER_BR:c:this.shiftEnterMode;if(this.activeEnterMode!=a||this.activeShiftEnterMode!=c)this.activeEnterMode=a,this.activeShiftEnterMode= +c,this.fire("activeEnterModeChange")},showNotification:function(a){alert(a)}})}(),CKEDITOR.ELEMENT_MODE_NONE=0,CKEDITOR.ELEMENT_MODE_REPLACE=1,CKEDITOR.ELEMENT_MODE_APPENDTO=2,CKEDITOR.ELEMENT_MODE_INLINE=3,CKEDITOR.htmlParser=function(){this._={htmlPartsRegex:/<(?:(?:\/([^>]+)>)|(?:!--([\S|\s]*?)--\x3e)|(?:([^\/\s>]+)((?:\s+[\w\-:.]+(?:\s*=\s*?(?:(?:"[^"]*")|(?:'[^']*')|[^\s"'\/>]+))?)*)[\S\s]*?(\/?)>))/g}},function(){var f=/([\w\-:.]+)(?:(?:\s*=\s*(?:(?:"([^"]*)")|(?:'([^']*)')|([^\s>]+)))|(?=\s|$))/g, +h={checked:1,compact:1,declare:1,defer:1,disabled:1,ismap:1,multiple:1,nohref:1,noresize:1,noshade:1,nowrap:1,readonly:1,selected:1};CKEDITOR.htmlParser.prototype={onTagOpen:function(){},onTagClose:function(){},onText:function(){},onCDATA:function(){},onComment:function(){},parse:function(e){for(var k,d,l=0,m;k=this._.htmlPartsRegex.exec(e);){d=k.index;if(d>l)if(l=e.substring(l,d),m)m.push(l);else this.onText(l);l=this._.htmlPartsRegex.lastIndex;if(d=k[1])if(d=d.toLowerCase(),m&&CKEDITOR.dtd.$cdata[d]&& +(this.onCDATA(m.join("")),m=null),!m){this.onTagClose(d);continue}if(m)m.push(k[0]);else if(d=k[3]){if(d=d.toLowerCase(),!/="/.test(d)){var b={},g,c=k[4];k=!!k[5];if(c)for(;g=f.exec(c);){var a=g[1].toLowerCase();g=g[2]||g[3]||g[4]||"";b[a]=!g&&h[a]?a:CKEDITOR.tools.htmlDecodeAttr(g)}this.onTagOpen(d,b,k);!m&&CKEDITOR.dtd.$cdata[d]&&(m=[])}}else if(d=k[2])this.onComment(d)}if(e.length>l)this.onText(e.substring(l,e.length))}}}(),CKEDITOR.htmlParser.basicWriter=CKEDITOR.tools.createClass({$:function(){this._= +{output:[]}},proto:{openTag:function(f){this._.output.push("\x3c",f)},openTagClose:function(f,h){h?this._.output.push(" /\x3e"):this._.output.push("\x3e")},attribute:function(f,h){"string"==typeof h&&(h=CKEDITOR.tools.htmlEncodeAttr(h));this._.output.push(" ",f,'\x3d"',h,'"')},closeTag:function(f){this._.output.push("\x3c/",f,"\x3e")},text:function(f){this._.output.push(f)},comment:function(f){this._.output.push("\x3c!--",f,"--\x3e")},write:function(f){this._.output.push(f)},reset:function(){this._.output= +[];this._.indent=!1},getHtml:function(f){var h=this._.output.join("");f&&this.reset();return h}}}),"use strict",function(){CKEDITOR.htmlParser.node=function(){};CKEDITOR.htmlParser.node.prototype={remove:function(){var f=this.parent.children,h=CKEDITOR.tools.indexOf(f,this),e=this.previous,k=this.next;e&&(e.next=k);k&&(k.previous=e);f.splice(h,1);this.parent=null},replaceWith:function(f){var h=this.parent.children,e=CKEDITOR.tools.indexOf(h,this),k=f.previous=this.previous,d=f.next=this.next;k&&(k.next= +f);d&&(d.previous=f);h[e]=f;f.parent=this.parent;this.parent=null},insertAfter:function(f){var h=f.parent.children,e=CKEDITOR.tools.indexOf(h,f),k=f.next;h.splice(e+1,0,this);this.next=f.next;this.previous=f;f.next=this;k&&(k.previous=this);this.parent=f.parent},insertBefore:function(f){var h=f.parent.children,e=CKEDITOR.tools.indexOf(h,f);h.splice(e,0,this);this.next=f;(this.previous=f.previous)&&(f.previous.next=this);f.previous=this;this.parent=f.parent},getAscendant:function(f){var h="function"== +typeof f?f:"string"==typeof f?function(e){return e.name==f}:function(e){return e.name in f},e=this.parent;for(;e&&e.type==CKEDITOR.NODE_ELEMENT;){if(h(e))return e;e=e.parent}return null},wrapWith:function(f){this.replaceWith(f);f.add(this);return f},getIndex:function(){return CKEDITOR.tools.indexOf(this.parent.children,this)},getFilterContext:function(f){return f||{}}}}(),"use strict",CKEDITOR.htmlParser.comment=function(f){this.value=f;this._={isBlockLike:!1}},CKEDITOR.htmlParser.comment.prototype= +CKEDITOR.tools.extend(new CKEDITOR.htmlParser.node,{type:CKEDITOR.NODE_COMMENT,filter:function(f,h){var e=this.value;if(!(e=f.onComment(h,e,this)))return this.remove(),!1;if("string"!=typeof e)return this.replaceWith(e),!1;this.value=e;return!0},writeHtml:function(f,h){h&&this.filter(h);f.comment(this.value)}}),"use strict",function(){CKEDITOR.htmlParser.text=function(f){this.value=f;this._={isBlockLike:!1}};CKEDITOR.htmlParser.text.prototype=CKEDITOR.tools.extend(new CKEDITOR.htmlParser.node,{type:CKEDITOR.NODE_TEXT, +filter:function(f,h){if(!(this.value=f.onText(h,this.value,this)))return this.remove(),!1},writeHtml:function(f,h){h&&this.filter(h);f.text(this.value)}})}(),"use strict",function(){CKEDITOR.htmlParser.cdata=function(f){this.value=f};CKEDITOR.htmlParser.cdata.prototype=CKEDITOR.tools.extend(new CKEDITOR.htmlParser.node,{type:CKEDITOR.NODE_TEXT,filter:function(){},writeHtml:function(f){f.write(this.value)}})}(),"use strict",CKEDITOR.htmlParser.fragment=function(){this.children=[];this.parent=null; +this._={isBlockLike:!0,hasInlineStarted:!1}},function(){function f(d){return d.attributes["data-cke-survive"]?!1:"a"==d.name&&d.attributes.href||CKEDITOR.dtd.$removeEmpty[d.name]}var h=CKEDITOR.tools.extend({table:1,ul:1,ol:1,dl:1},CKEDITOR.dtd.table,CKEDITOR.dtd.ul,CKEDITOR.dtd.ol,CKEDITOR.dtd.dl),e={ol:1,ul:1},k=CKEDITOR.tools.extend({},{html:1},CKEDITOR.dtd.html,CKEDITOR.dtd.body,CKEDITOR.dtd.head,{style:1,script:1}),d={ul:"li",ol:"li",dl:"dd",table:"tbody",tbody:"tr",thead:"tr",tfoot:"tr",tr:"td"}; +CKEDITOR.htmlParser.fragment.fromHtml=function(l,m,b){function g(a){var b;if(0<q.length)for(var d=0;d<q.length;d++){var g=q[d],e=g.name,f=CKEDITOR.dtd[e],k=r.name&&CKEDITOR.dtd[r.name];k&&!k[e]||a&&f&&!f[a]&&CKEDITOR.dtd[a]?e==r.name&&(n(r,r.parent,1),d--):(b||(c(),b=1),g=g.clone(),g.parent=r,r=g,q.splice(d,1),d--)}}function c(){for(;A.length;)n(A.shift(),r)}function a(a){if(a._.isBlockLike&&"pre"!=a.name&&"textarea"!=a.name){var c=a.children.length,b=a.children[c-1],d;b&&b.type==CKEDITOR.NODE_TEXT&& +((d=CKEDITOR.tools.rtrim(b.value))?b.value=d:a.children.length=c-1)}}function n(c,d,g){d=d||r||p;var e=r;void 0===c.previous&&(w(d,c)&&(r=d,t.onTagOpen(b,{}),c.returnPoint=d=r),a(c),f(c)&&!c.children.length||d.add(c),"pre"==c.name&&(B=!1),"textarea"==c.name&&(C=!1));c.returnPoint?(r=c.returnPoint,delete c.returnPoint):r=g?d:e}function w(a,c){if((a==p||"body"==a.name)&&b&&(!a.name||CKEDITOR.dtd[a.name][b])){var d,g;return(d=c.attributes&&(g=c.attributes["data-cke-real-element-type"])?g:c.name)&&d in +CKEDITOR.dtd.$inline&&!(d in CKEDITOR.dtd.head)&&!c.isOrphan||c.type==CKEDITOR.NODE_TEXT}}function v(a,c){return a in CKEDITOR.dtd.$listItem||a in CKEDITOR.dtd.$tableContent?a==c||"dt"==a&&"dd"==c||"dd"==a&&"dt"==c:!1}var t=new CKEDITOR.htmlParser,p=m instanceof CKEDITOR.htmlParser.element?m:"string"==typeof m?new CKEDITOR.htmlParser.element(m):new CKEDITOR.htmlParser.fragment,q=[],A=[],r=p,C="textarea"==p.name,B="pre"==p.name;t.onTagOpen=function(a,b,d,l){b=new CKEDITOR.htmlParser.element(a,b);b.isUnknown&& +d&&(b.isEmpty=!0);b.isOptionalClose=l;if(f(b))q.push(b);else{if("pre"==a)B=!0;else{if("br"==a&&B){r.add(new CKEDITOR.htmlParser.text("\n"));return}"textarea"==a&&(C=!0)}if("br"==a)A.push(b);else{for(;!(l=(d=r.name)?CKEDITOR.dtd[d]||(r._.isBlockLike?CKEDITOR.dtd.div:CKEDITOR.dtd.span):k,b.isUnknown||r.isUnknown||l[a]);)if(r.isOptionalClose)t.onTagClose(d);else if(a in e&&d in e)d=r.children,(d=d[d.length-1])&&"li"==d.name||n(d=new CKEDITOR.htmlParser.element("li"),r),!b.returnPoint&&(b.returnPoint= +r),r=d;else if(a in CKEDITOR.dtd.$listItem&&!v(a,d))t.onTagOpen("li"==a?"ul":"dl",{},0,1);else if(d in h&&!v(a,d))!b.returnPoint&&(b.returnPoint=r),r=r.parent;else if(d in CKEDITOR.dtd.$inline&&q.unshift(r),r.parent)n(r,r.parent,1);else{b.isOrphan=1;break}g(a);c();b.parent=r;b.isEmpty?n(b):r=b}}};t.onTagClose=function(a){for(var d=q.length-1;0<=d;d--)if(a==q[d].name){q.splice(d,1);return}for(var g=[],e=[],f=r;f!=p&&f.name!=a;)f._.isBlockLike||e.unshift(f),g.push(f),f=f.returnPoint||f.parent;if(f!= +p){for(d=0;d<g.length;d++){var k=g[d];n(k,k.parent)}r=f;f._.isBlockLike&&c();n(f,f.parent);f==r&&(r=r.parent);q=q.concat(e)}"body"==a&&(b=!1)};t.onText=function(a){if(!(r._.hasInlineStarted&&!A.length||B||C)&&(a=CKEDITOR.tools.ltrim(a),0===a.length))return;var e=r.name,f=e?CKEDITOR.dtd[e]||(r._.isBlockLike?CKEDITOR.dtd.div:CKEDITOR.dtd.span):k;if(!C&&!f["#"]&&e in h)t.onTagOpen(d[e]||""),t.onText(a);else{c();g();B||C||(a=a.replace(/[\t\r\n ]{2,}|[\t\r\n]/g," "));a=new CKEDITOR.htmlParser.text(a); +if(w(r,a))this.onTagOpen(b,{},0,1);r.add(a)}};t.onCDATA=function(a){r.add(new CKEDITOR.htmlParser.cdata(a))};t.onComment=function(a){c();g();r.add(new CKEDITOR.htmlParser.comment(a))};t.parse(l);for(c();r!=p;)n(r,r.parent,1);a(p);return p};CKEDITOR.htmlParser.fragment.prototype={type:CKEDITOR.NODE_DOCUMENT_FRAGMENT,add:function(d,e){isNaN(e)&&(e=this.children.length);var b=0<e?this.children[e-1]:null;if(b){if(d._.isBlockLike&&b.type==CKEDITOR.NODE_TEXT&&(b.value=CKEDITOR.tools.rtrim(b.value),0=== +b.value.length)){this.children.pop();this.add(d);return}b.next=d}d.previous=b;d.parent=this;this.children.splice(e,0,d);this._.hasInlineStarted||(this._.hasInlineStarted=d.type==CKEDITOR.NODE_TEXT||d.type==CKEDITOR.NODE_ELEMENT&&!d._.isBlockLike)},filter:function(d,e){e=this.getFilterContext(e);d.onRoot(e,this);this.filterChildren(d,!1,e)},filterChildren:function(d,e,b){if(this.childrenFilteredBy!=d.id){b=this.getFilterContext(b);if(e&&!this.parent)d.onRoot(b,this);this.childrenFilteredBy=d.id;for(e= +0;e<this.children.length;e++)!1===this.children[e].filter(d,b)&&e--}},writeHtml:function(d,e){e&&this.filter(e);this.writeChildrenHtml(d)},writeChildrenHtml:function(d,e,b){var g=this.getFilterContext();if(b&&!this.parent&&e)e.onRoot(g,this);e&&this.filterChildren(e,!1,g);e=0;b=this.children;for(g=b.length;e<g;e++)b[e].writeHtml(d)},forEach:function(d,e,b){if(!(b||e&&this.type!=e))var g=d(this);if(!1!==g){b=this.children;for(var c=0;c<b.length;c++)g=b[c],g.type==CKEDITOR.NODE_ELEMENT?g.forEach(d, e):e&&g.type!=e||d(g)}},getFilterContext:function(d){return d||{}}}}(),"use strict",function(){function f(){this.rules=[]}function h(e,k,d,h){var m,b;for(m in k)(b=e[m])||(b=e[m]=new f),b.add(k[m],d,h)}CKEDITOR.htmlParser.filter=CKEDITOR.tools.createClass({$:function(e){this.id=CKEDITOR.tools.getNextNumber();this.elementNameRules=new f;this.attributeNameRules=new f;this.elementsRules={};this.attributesRules={};this.textRules=new f;this.commentRules=new f;this.rootRules=new f;e&&this.addRules(e,10)}, proto:{addRules:function(e,f){var d;"number"==typeof f?d=f:f&&"priority"in f&&(d=f.priority);"number"!=typeof d&&(d=10);"object"!=typeof f&&(f={});e.elementNames&&this.elementNameRules.addMany(e.elementNames,d,f);e.attributeNames&&this.attributeNameRules.addMany(e.attributeNames,d,f);e.elements&&h(this.elementsRules,e.elements,d,f);e.attributes&&h(this.attributesRules,e.attributes,d,f);e.text&&this.textRules.add(e.text,d,f);e.comment&&this.commentRules.add(e.comment,d,f);e.root&&this.rootRules.add(e.root, d,f)},applyTo:function(e){e.filter(this)},onElementName:function(e,f){return this.elementNameRules.execOnName(e,f)},onAttributeName:function(e,f){return this.attributeNameRules.execOnName(e,f)},onText:function(e,f,d){return this.textRules.exec(e,f,d)},onComment:function(e,f,d){return this.commentRules.exec(e,f,d)},onRoot:function(e,f){return this.rootRules.exec(e,f)},onElement:function(e,f){for(var d=[this.elementsRules["^"],this.elementsRules[f.name],this.elementsRules.$],h,m=0;3>m;m++)if(h=d[m]){h= h.exec(e,f,this);if(!1===h)return null;if(h&&h!=f)return this.onNode(e,h);if(f.parent&&!f.name)break}return f},onNode:function(e,f){var d=f.type;return d==CKEDITOR.NODE_ELEMENT?this.onElement(e,f):d==CKEDITOR.NODE_TEXT?new CKEDITOR.htmlParser.text(this.onText(e,f.value)):d==CKEDITOR.NODE_COMMENT?new CKEDITOR.htmlParser.comment(this.onComment(e,f.value)):null},onAttribute:function(e,f,d,h){return(d=this.attributesRules[d])?d.exec(e,h,f,this):h}}});CKEDITOR.htmlParser.filterRulesGroup=f;f.prototype= {add:function(e,f,d){this.rules.splice(this.findIndex(f),0,{value:e,priority:f,options:d})},addMany:function(e,f,d){for(var h=[this.findIndex(f),0],m=0,b=e.length;m<b;m++)h.push({value:e[m],priority:f,options:d});this.rules.splice.apply(this.rules,h)},findIndex:function(e){for(var f=this.rules,d=f.length-1;0<=d&&e<f[d].priority;)d--;return d+1},exec:function(e,f){var d=f instanceof CKEDITOR.htmlParser.node||f instanceof CKEDITOR.htmlParser.fragment,h=Array.prototype.slice.call(arguments,1),m=this.rules, b=m.length,g,c,a,n;for(n=0;n<b;n++)if(d&&(g=f.type,c=f.name),a=m[n],!(e.nonEditable&&!a.options.applyToAll||e.nestedEditable&&a.options.excludeNestedEditable)){a=a.value.apply(null,h);if(!1===a||d&&a&&(a.name!=c||a.type!=g))return a;null!=a&&(h[0]=f=a)}return f},execOnName:function(e,f){for(var d=0,h=this.rules,m=h.length,b;f&&d<m;d++)b=h[d],e.nonEditable&&!b.options.applyToAll||e.nestedEditable&&b.options.excludeNestedEditable||(f=f.replace(b.value[0],b.value[1]));return f}}}(),function(){function f(a, -c){function b(a){return a||CKEDITOR.env.needsNbspFiller?new CKEDITOR.htmlParser.text(" "):new CKEDITOR.htmlParser.element("br",{"data-cke-bogus":1})}function g(a,c){return function(g){if(g.type!=CKEDITOR.NODE_DOCUMENT_FRAGMENT){var d=[],h=e(g),m,C;if(h)for(f(h,1)&&d.push(h);h;)l(h)&&(m=k(h))&&f(m)&&((C=k(m))&&!l(C)?d.push(m):(b(n).insertAfter(m),m.remove())),h=h.previous;for(h=0;h<d.length;h++)d[h].remove();if(d=!a||!1!==("function"==typeof c?c(g):c))n||CKEDITOR.env.needsBrFiller||g.type!=CKEDITOR.NODE_DOCUMENT_FRAGMENT? -n||CKEDITOR.env.needsBrFiller||!(7<document.documentMode||g.name in CKEDITOR.dtd.tr||g.name in CKEDITOR.dtd.$listItem)?(d=e(g),d=!d||"form"==g.name&&"input"==d.name):d=!1:d=!1;d&&g.add(b(a))}}}function f(a,c){if((!n||CKEDITOR.env.needsBrFiller)&&a.type==CKEDITOR.NODE_ELEMENT&&"br"==a.name&&!a.attributes["data-cke-eol"])return!0;var b;return a.type==CKEDITOR.NODE_TEXT&&(b=a.value.match(q))&&(b.index&&((new CKEDITOR.htmlParser.text(a.value.substring(0,b.index))).insertBefore(a),a.value=b[0]),!CKEDITOR.env.needsBrFiller&& -n&&(!c||a.parent.name in C)||!n&&((b=a.previous)&&"br"==b.name||!b||l(b)))?!0:!1}var h={elements:{}},n="html"==c,C=CKEDITOR.tools.extend({},D),t;for(t in C)"#"in x[t]||delete C[t];for(t in C)h.elements[t]=g(n,a.config.fillEmptyBlocks);h.root=g(n,!1);h.elements.br=function(a){return function(c){if(c.parent.type!=CKEDITOR.NODE_DOCUMENT_FRAGMENT){var g=c.attributes;if("data-cke-bogus"in g||"data-cke-eol"in g)delete g["data-cke-bogus"];else{for(g=c.next;g&&d(g);)g=g.next;var e=k(c);!g&&l(c.parent)?m(c.parent, +c){function b(a){return a||CKEDITOR.env.needsNbspFiller?new CKEDITOR.htmlParser.text(" "):new CKEDITOR.htmlParser.element("br",{"data-cke-bogus":1})}function g(a,c){return function(d){if(d.type!=CKEDITOR.NODE_DOCUMENT_FRAGMENT){var g=[],h=e(d),m,D;if(h)for(f(h,1)&&g.push(h);h;)l(h)&&(m=k(h))&&f(m)&&((D=k(m))&&!l(D)?g.push(m):(b(n).insertAfter(m),m.remove())),h=h.previous;for(h=0;h<g.length;h++)g[h].remove();if(g=!a||!1!==("function"==typeof c?c(d):c))n||CKEDITOR.env.needsBrFiller||d.type!=CKEDITOR.NODE_DOCUMENT_FRAGMENT? +n||CKEDITOR.env.needsBrFiller||!(7<document.documentMode||d.name in CKEDITOR.dtd.tr||d.name in CKEDITOR.dtd.$listItem)?(g=e(d),g=!g||"form"==d.name&&"input"==g.name):g=!1:g=!1;g&&d.add(b(a))}}}function f(a,c){if((!n||CKEDITOR.env.needsBrFiller)&&a.type==CKEDITOR.NODE_ELEMENT&&"br"==a.name&&!a.attributes["data-cke-eol"])return!0;var b;return a.type==CKEDITOR.NODE_TEXT&&(b=a.value.match(q))&&(b.index&&((new CKEDITOR.htmlParser.text(a.value.substring(0,b.index))).insertBefore(a),a.value=b[0]),!CKEDITOR.env.needsBrFiller&& +n&&(!c||a.parent.name in D)||!n&&((b=a.previous)&&"br"==b.name||!b||l(b)))?!0:!1}var h={elements:{}},n="html"==c,D=CKEDITOR.tools.extend({},B),u;for(u in D)"#"in r[u]||delete D[u];for(u in D)h.elements[u]=g(n,a.config.fillEmptyBlocks);h.root=g(n,!1);h.elements.br=function(a){return function(c){if(c.parent.type!=CKEDITOR.NODE_DOCUMENT_FRAGMENT){var g=c.attributes;if("data-cke-bogus"in g||"data-cke-eol"in g)delete g["data-cke-bogus"];else{for(g=c.next;g&&d(g);)g=g.next;var e=k(c);!g&&l(c.parent)?m(c.parent, b(a)):l(g)&&e&&!l(e)&&b(a).insertBefore(g)}}}}(n);return h}function h(a,c){return a!=CKEDITOR.ENTER_BR&&!1!==c?a==CKEDITOR.ENTER_DIV?"div":"p":!1}function e(a){for(a=a.children[a.children.length-1];a&&d(a);)a=a.previous;return a}function k(a){for(a=a.previous;a&&d(a);)a=a.previous;return a}function d(a){return a.type==CKEDITOR.NODE_TEXT&&!CKEDITOR.tools.trim(a.value)||a.type==CKEDITOR.NODE_ELEMENT&&a.attributes["data-cke-bookmark"]}function l(a){return a&&(a.type==CKEDITOR.NODE_ELEMENT&&a.name in -D||a.type==CKEDITOR.NODE_DOCUMENT_FRAGMENT)}function m(a,c){var b=a.children[a.children.length-1];a.children.push(c);c.parent=a;b&&(b.next=c,c.previous=b)}function b(a){a=a.attributes;"false"!=a.contenteditable&&(a["data-cke-editable"]=a.contenteditable?"true":1);a.contenteditable="false"}function g(a){a=a.attributes;switch(a["data-cke-editable"]){case "true":a.contenteditable="true";break;case "1":delete a.contenteditable}}function c(a){return a.replace(I,function(a,c,b){return"\x3c"+c+b.replace(E, -function(a,c){return F.test(c)&&-1==b.indexOf("data-cke-saved-"+c)?" data-cke-saved-"+a+" data-cke-"+CKEDITOR.rnd+"-"+a:a})+"\x3e"})}function a(a,c){return a.replace(c,function(a,c,b){0===a.indexOf("\x3ctextarea")&&(a=c+v(b).replace(/</g,"\x26lt;").replace(/>/g,"\x26gt;")+"\x3c/textarea\x3e");return"\x3ccke:encoded\x3e"+encodeURIComponent(a)+"\x3c/cke:encoded\x3e"})}function n(a){return a.replace(L,function(a,c){return decodeURIComponent(c)})}function w(a){return a.replace(/\x3c!--(?!{cke_protected})[\s\S]+?--\x3e/g, -function(a){return"\x3c!--"+u+"{C}"+encodeURIComponent(a).replace(/--/g,"%2D%2D")+"--\x3e"})}function v(a){return a.replace(/\x3c!--\{cke_protected\}\{C\}([\s\S]+?)--\x3e/g,function(a,c){return decodeURIComponent(c)})}function p(a,c){var b=c._.dataStore;return a.replace(/\x3c!--\{cke_protected\}([\s\S]+?)--\x3e/g,function(a,c){return decodeURIComponent(c)}).replace(/\{cke_protected_(\d+)\}/g,function(a,c){return b&&b[c]||""})}function r(a,c){var b=[],g=c.config.protectedSource,d=c._.dataStore||(c._.dataStore= -{id:1}),e=/<\!--\{cke_temp(comment)?\}(\d*?)--\x3e/g,g=[/<script[\s\S]*?(<\/script>|$)/gi,/<noscript[\s\S]*?<\/noscript>/gi,/<meta[\s\S]*?\/?>/gi].concat(g);a=a.replace(/\x3c!--[\s\S]*?--\x3e/g,function(a){return"\x3c!--{cke_tempcomment}"+(b.push(a)-1)+"--\x3e"});for(var f=0;f<g.length;f++)a=a.replace(g[f],function(a){a=a.replace(e,function(a,c,g){return b[g]});return/cke_temp(comment)?/.test(a)?a:"\x3c!--{cke_temp}"+(b.push(a)-1)+"--\x3e"});a=a.replace(e,function(a,c,g){return"\x3c!--"+u+(c?"{C}": -"")+encodeURIComponent(b[g]).replace(/--/g,"%2D%2D")+"--\x3e"});a=a.replace(/<\w+(?:\s+(?:(?:[^\s=>]+\s*=\s*(?:[^'"\s>]+|'[^']*'|"[^"]*"))|[^\s=\/>]+))+\s*\/?>/g,function(a){return a.replace(/\x3c!--\{cke_protected\}([^>]*)--\x3e/g,function(a,c){d[d.id]=decodeURIComponent(c);return"{cke_protected_"+d.id++ +"}"})});return a=a.replace(/<(title|iframe|textarea)([^>]*)>([\s\S]*?)<\/\1>/g,function(a,b,g,d){return"\x3c"+b+g+"\x3e"+p(v(d),c)+"\x3c/"+b+"\x3e"})}CKEDITOR.htmlDataProcessor=function(b){var g, -d,e=this;this.editor=b;this.dataFilter=g=new CKEDITOR.htmlParser.filter;this.htmlFilter=d=new CKEDITOR.htmlParser.filter;this.writer=new CKEDITOR.htmlParser.basicWriter;g.addRules(t);g.addRules(B,{applyToAll:!0});g.addRules(f(b,"data"),{applyToAll:!0});d.addRules(y);d.addRules(z,{applyToAll:!0});d.addRules(f(b,"html"),{applyToAll:!0});b.on("toHtml",function(g){g=g.data;var d=g.dataValue,e,d=r(d,b),d=a(d,G),d=c(d),d=a(d,H),d=d.replace(O,"$1cke:$2"),d=d.replace(S,"\x3ccke:$1$2\x3e\x3c/cke:$1\x3e"), -d=d.replace(/(<pre\b[^>]*>)(\r\n|\n)/g,"$1$2$2"),d=d.replace(/([^a-z0-9<\-])(on\w{3,})(?!>)/gi,"$1data-cke-"+CKEDITOR.rnd+"-$2");e=g.context||b.editable().getName();var f;CKEDITOR.env.ie&&9>CKEDITOR.env.version&&"pre"==e&&(e="div",d="\x3cpre\x3e"+d+"\x3c/pre\x3e",f=1);e=b.document.createElement(e);e.setHtml("a"+d);d=e.getHtml().substr(1);d=d.replace(new RegExp("data-cke-"+CKEDITOR.rnd+"-","ig"),"");f&&(d=d.replace(/^<pre>|<\/pre>$/gi,""));d=d.replace(C,"$1$2");d=n(d);d=v(d);e=!1===g.fixForBody?!1: -h(g.enterMode,b.config.autoParagraph);d=CKEDITOR.htmlParser.fragment.fromHtml(d,g.context,e);e&&(f=d,!f.children.length&&CKEDITOR.dtd[f.name][e]&&(e=new CKEDITOR.htmlParser.element(e),f.add(e)));g.dataValue=d},null,null,5);b.on("toHtml",function(a){a.data.filter.applyTo(a.data.dataValue,!0,a.data.dontFilter,a.data.enterMode)&&b.fire("dataFiltered")},null,null,6);b.on("toHtml",function(a){a.data.dataValue.filterChildren(e.dataFilter,!0)},null,null,10);b.on("toHtml",function(a){a=a.data;var c=a.dataValue, +B||a.type==CKEDITOR.NODE_DOCUMENT_FRAGMENT)}function m(a,c){var b=a.children[a.children.length-1];a.children.push(c);c.parent=a;b&&(b.next=c,c.previous=b)}function b(a){a=a.attributes;"false"!=a.contenteditable&&(a["data-cke-editable"]=a.contenteditable?"true":1);a.contenteditable="false"}function g(a){a=a.attributes;switch(a["data-cke-editable"]){case "true":a.contenteditable="true";break;case "1":delete a.contenteditable}}function c(a){return a.replace(I,function(a,c,b){return"\x3c"+c+b.replace(F, +function(a,c){return E.test(c)&&-1==b.indexOf("data-cke-saved-"+c)?" data-cke-saved-"+a+" data-cke-"+CKEDITOR.rnd+"-"+a:a})+"\x3e"})}function a(a,c){return a.replace(c,function(a,c,b){0===a.indexOf("\x3ctextarea")&&(a=c+v(b).replace(/</g,"\x26lt;").replace(/>/g,"\x26gt;")+"\x3c/textarea\x3e");return"\x3ccke:encoded\x3e"+encodeURIComponent(a)+"\x3c/cke:encoded\x3e"})}function n(a){return a.replace(L,function(a,c){return decodeURIComponent(c)})}function w(a){return a.replace(/\x3c!--(?!{cke_protected})[\s\S]+?--\x3e/g, +function(a){return"\x3c!--"+A+"{C}"+encodeURIComponent(a).replace(/--/g,"%2D%2D")+"--\x3e"})}function v(a){return a.replace(/\x3c!--\{cke_protected\}\{C\}([\s\S]+?)--\x3e/g,function(a,c){return decodeURIComponent(c)})}function t(a,c){var b=c._.dataStore;return a.replace(/\x3c!--\{cke_protected\}([\s\S]+?)--\x3e/g,function(a,c){return decodeURIComponent(c)}).replace(/\{cke_protected_(\d+)\}/g,function(a,c){return b&&b[c]||""})}function p(a,c){var b=[],d=c.config.protectedSource,g=c._.dataStore||(c._.dataStore= +{id:1}),e=/<\!--\{cke_temp(comment)?\}(\d*?)--\x3e/g,d=[/<script[\s\S]*?(<\/script>|$)/gi,/<noscript[\s\S]*?<\/noscript>/gi,/<meta[\s\S]*?\/?>/gi].concat(d);a=a.replace(/\x3c!--[\s\S]*?--\x3e/g,function(a){return"\x3c!--{cke_tempcomment}"+(b.push(a)-1)+"--\x3e"});for(var f=0;f<d.length;f++)a=a.replace(d[f],function(a){a=a.replace(e,function(a,c,d){return b[d]});return/cke_temp(comment)?/.test(a)?a:"\x3c!--{cke_temp}"+(b.push(a)-1)+"--\x3e"});a=a.replace(e,function(a,c,d){return"\x3c!--"+A+(c?"{C}": +"")+encodeURIComponent(b[d]).replace(/--/g,"%2D%2D")+"--\x3e"});a=a.replace(/<\w+(?:\s+(?:(?:[^\s=>]+\s*=\s*(?:[^'"\s>]+|'[^']*'|"[^"]*"))|[^\s=\/>]+))+\s*\/?>/g,function(a){return a.replace(/\x3c!--\{cke_protected\}([^>]*)--\x3e/g,function(a,c){g[g.id]=decodeURIComponent(c);return"{cke_protected_"+g.id++ +"}"})});return a=a.replace(/<(title|iframe|textarea)([^>]*)>([\s\S]*?)<\/\1>/g,function(a,b,d,g){return"\x3c"+b+d+"\x3e"+t(v(g),c)+"\x3c/"+b+"\x3e"})}CKEDITOR.htmlDataProcessor=function(b){var d, +g,e=this;this.editor=b;this.dataFilter=d=new CKEDITOR.htmlParser.filter;this.htmlFilter=g=new CKEDITOR.htmlParser.filter;this.writer=new CKEDITOR.htmlParser.basicWriter;d.addRules(u);d.addRules(y,{applyToAll:!0});d.addRules(f(b,"data"),{applyToAll:!0});g.addRules(x);g.addRules(z,{applyToAll:!0});g.addRules(f(b,"html"),{applyToAll:!0});b.on("toHtml",function(d){d=d.data;var g=d.dataValue,e,g=p(g,b),g=a(g,G),g=c(g),g=a(g,H),g=g.replace(O,"$1cke:$2"),g=g.replace(S,"\x3ccke:$1$2\x3e\x3c/cke:$1\x3e"), +g=g.replace(/(<pre\b[^>]*>)(\r\n|\n)/g,"$1$2$2"),g=g.replace(/([^a-z0-9<\-])(on\w{3,})(?!>)/gi,"$1data-cke-"+CKEDITOR.rnd+"-$2");e=d.context||b.editable().getName();var f;CKEDITOR.env.ie&&9>CKEDITOR.env.version&&"pre"==e&&(e="div",g="\x3cpre\x3e"+g+"\x3c/pre\x3e",f=1);e=b.document.createElement(e);e.setHtml("a"+g);g=e.getHtml().substr(1);g=g.replace(new RegExp("data-cke-"+CKEDITOR.rnd+"-","ig"),"");f&&(g=g.replace(/^<pre>|<\/pre>$/gi,""));g=g.replace(D,"$1$2");g=n(g);g=v(g);e=!1===d.fixForBody?!1: +h(d.enterMode,b.config.autoParagraph);g=CKEDITOR.htmlParser.fragment.fromHtml(g,d.context,e);e&&(f=g,!f.children.length&&CKEDITOR.dtd[f.name][e]&&(e=new CKEDITOR.htmlParser.element(e),f.add(e)));d.dataValue=g},null,null,5);b.on("toHtml",function(a){a.data.filter.applyTo(a.data.dataValue,!0,a.data.dontFilter,a.data.enterMode)&&b.fire("dataFiltered")},null,null,6);b.on("toHtml",function(a){a.data.dataValue.filterChildren(e.dataFilter,!0)},null,null,10);b.on("toHtml",function(a){a=a.data;var c=a.dataValue, b=new CKEDITOR.htmlParser.basicWriter;c.writeChildrenHtml(b);c=b.getHtml(!0);a.dataValue=w(c)},null,null,15);b.on("toDataFormat",function(a){var c=a.data.dataValue;a.data.enterMode!=CKEDITOR.ENTER_BR&&(c=c.replace(/^<br *\/?>/i,""));a.data.dataValue=CKEDITOR.htmlParser.fragment.fromHtml(c,a.data.context,h(a.data.enterMode,b.config.autoParagraph))},null,null,5);b.on("toDataFormat",function(a){a.data.dataValue.filterChildren(e.htmlFilter,!0)},null,null,10);b.on("toDataFormat",function(a){a.data.filter.applyTo(a.data.dataValue, -!1,!0)},null,null,11);b.on("toDataFormat",function(a){var c=a.data.dataValue,g=e.writer;g.reset();c.writeChildrenHtml(g);c=g.getHtml(!0);c=v(c);c=p(c,b);a.data.dataValue=c},null,null,15)};CKEDITOR.htmlDataProcessor.prototype={toHtml:function(a,c,b,g){var d=this.editor,e,f,k,h;c&&"object"==typeof c?(e=c.context,b=c.fixForBody,g=c.dontFilter,f=c.filter,k=c.enterMode,h=c.protectedWhitespaces):e=c;e||null===e||(e=d.editable().getName());return d.fire("toHtml",{dataValue:a,context:e,fixForBody:b,dontFilter:g, -filter:f||d.filter,enterMode:k||d.enterMode,protectedWhitespaces:h}).dataValue},toDataFormat:function(a,c){var b,g,d;c&&(b=c.context,g=c.filter,d=c.enterMode);b||null===b||(b=this.editor.editable().getName());return this.editor.fire("toDataFormat",{dataValue:a,filter:g||this.editor.filter,context:b,enterMode:d||this.editor.enterMode}).dataValue}};var q=/(?: |\xa0)$/,u="{cke_protected}",x=CKEDITOR.dtd,A="caption colgroup col thead tfoot tbody".split(" "),D=CKEDITOR.tools.extend({},x.$blockLimit, -x.$block),t={elements:{input:b,textarea:b}},B={attributeNames:[[/^on/,"data-cke-pa-on"],[/^srcdoc/,"data-cke-pa-srcdoc"],[/^data-cke-expando$/,""]],elements:{iframe:function(a){if(a.attributes&&a.attributes.src){var c=a.attributes.src.toLowerCase().replace(/[^a-z]/gi,"");if(0===c.indexOf("javascript")||0===c.indexOf("data"))a.attributes["data-cke-pa-src"]=a.attributes.src,delete a.attributes.src}}}},y={elements:{embed:function(a){var c=a.parent;if(c&&"object"==c.name){var b=c.attributes.width,c=c.attributes.height; -b&&(a.attributes.width=b);c&&(a.attributes.height=c)}},a:function(a){var c=a.attributes;if(!(a.children.length||c.name||c.id||a.attributes["data-cke-saved-name"]))return!1}}},z={elementNames:[[/^cke:/,""],[/^\?xml:namespace$/,""]],attributeNames:[[/^data-cke-(saved|pa)-/,""],[/^data-cke-.*/,""],["hidefocus",""]],elements:{$:function(a){var c=a.attributes;if(c){if(c["data-cke-temp"])return!1;for(var b=["name","href","src"],g,d=0;d<b.length;d++)g="data-cke-saved-"+b[d],g in c&&delete c[b[d]]}return a}, -table:function(a){a.children.slice(0).sort(function(a,c){var b,g;a.type==CKEDITOR.NODE_ELEMENT&&c.type==a.type&&(b=CKEDITOR.tools.indexOf(A,a.name),g=CKEDITOR.tools.indexOf(A,c.name));-1<b&&-1<g&&b!=g||(b=a.parent?a.getIndex():-1,g=c.parent?c.getIndex():-1);return b>g?1:-1})},param:function(a){a.children=[];a.isEmpty=!0;return a},span:function(a){"Apple-style-span"==a.attributes["class"]&&delete a.name},html:function(a){delete a.attributes.contenteditable;delete a.attributes["class"]},body:function(a){delete a.attributes.spellcheck; +!1,!0)},null,null,11);b.on("toDataFormat",function(a){var c=a.data.dataValue,d=e.writer;d.reset();c.writeChildrenHtml(d);c=d.getHtml(!0);c=v(c);c=t(c,b);a.data.dataValue=c},null,null,15)};CKEDITOR.htmlDataProcessor.prototype={toHtml:function(a,c,b,d){var g=this.editor,e,f,k,h;c&&"object"==typeof c?(e=c.context,b=c.fixForBody,d=c.dontFilter,f=c.filter,k=c.enterMode,h=c.protectedWhitespaces):e=c;e||null===e||(e=g.editable().getName());return g.fire("toHtml",{dataValue:a,context:e,fixForBody:b,dontFilter:d, +filter:f||g.filter,enterMode:k||g.enterMode,protectedWhitespaces:h}).dataValue},toDataFormat:function(a,c){var b,d,g;c&&(b=c.context,d=c.filter,g=c.enterMode);b||null===b||(b=this.editor.editable().getName());return this.editor.fire("toDataFormat",{dataValue:a,filter:d||this.editor.filter,context:b,enterMode:g||this.editor.enterMode}).dataValue}};var q=/(?: |\xa0)$/,A="{cke_protected}",r=CKEDITOR.dtd,C="caption colgroup col thead tfoot tbody".split(" "),B=CKEDITOR.tools.extend({},r.$blockLimit, +r.$block),u={elements:{input:b,textarea:b}},y={attributeNames:[[/^on/,"data-cke-pa-on"],[/^srcdoc/,"data-cke-pa-srcdoc"],[/^data-cke-expando$/,""]],elements:{iframe:function(a){if(a.attributes&&a.attributes.src){var c=a.attributes.src.toLowerCase().replace(/[^a-z]/gi,"");if(0===c.indexOf("javascript")||0===c.indexOf("data"))a.attributes["data-cke-pa-src"]=a.attributes.src,delete a.attributes.src}}}},x={elements:{embed:function(a){var c=a.parent;if(c&&"object"==c.name){var b=c.attributes.width,c=c.attributes.height; +b&&(a.attributes.width=b);c&&(a.attributes.height=c)}},a:function(a){var c=a.attributes;if(!(a.children.length||c.name||c.id||a.attributes["data-cke-saved-name"]))return!1}}},z={elementNames:[[/^cke:/,""],[/^\?xml:namespace$/,""]],attributeNames:[[/^data-cke-(saved|pa)-/,""],[/^data-cke-.*/,""],["hidefocus",""]],elements:{$:function(a){var c=a.attributes;if(c){if(c["data-cke-temp"])return!1;for(var b=["name","href","src"],d,g=0;g<b.length;g++)d="data-cke-saved-"+b[g],d in c&&delete c[b[g]]}return a}, +table:function(a){a.children.slice(0).sort(function(a,c){var b,d;a.type==CKEDITOR.NODE_ELEMENT&&c.type==a.type&&(b=CKEDITOR.tools.indexOf(C,a.name),d=CKEDITOR.tools.indexOf(C,c.name));-1<b&&-1<d&&b!=d||(b=a.parent?a.getIndex():-1,d=c.parent?c.getIndex():-1);return b>d?1:-1})},param:function(a){a.children=[];a.isEmpty=!0;return a},span:function(a){"Apple-style-span"==a.attributes["class"]&&delete a.name},html:function(a){delete a.attributes.contenteditable;delete a.attributes["class"]},body:function(a){delete a.attributes.spellcheck; delete a.attributes.contenteditable},style:function(a){var c=a.children[0];c&&c.value&&(c.value=CKEDITOR.tools.trim(c.value));a.attributes.type||(a.attributes.type="text/css")},title:function(a){var c=a.children[0];!c&&m(a,c=new CKEDITOR.htmlParser.text);c.value=a.attributes["data-cke-title"]||""},input:g,textarea:g},attributes:{"class":function(a){return CKEDITOR.tools.ltrim(a.replace(/(?:^|\s+)cke_[^\s]*/g,""))||!1}}};CKEDITOR.env.ie&&(z.attributes.style=function(a){return a.replace(/(^|;)([^\:]+)/g, -function(a){return a.toLowerCase()})});var I=/<(a|area|img|input|source)\b([^>]*)>/gi,E=/([\w-:]+)\s*=\s*(?:(?:"[^"]*")|(?:'[^']*')|(?:[^ "'>]+))/gi,F=/^(href|src|name)$/i,H=/(?:<style(?=[ >])[^>]*>[\s\S]*?<\/style>)|(?:<(:?link|meta|base)[^>]*>)/gi,G=/(<textarea(?=[ >])[^>]*>)([\s\S]*?)(?:<\/textarea>)/gi,L=/<cke:encoded>([^<]*)<\/cke:encoded>/gi,O=/(<\/?)((?:object|embed|param|html|body|head|title)[^>]*>)/gi,C=/(<\/?)cke:((?:html|body|head|title)[^>]*>)/gi,S=/<cke:(param|embed)([^>]*?)\/?>(?!\s*<\/cke:\1)/gi}(), +function(a){return a.toLowerCase()})});var I=/<(a|area|img|input|source)\b([^>]*)>/gi,F=/([\w-:]+)\s*=\s*(?:(?:"[^"]*")|(?:'[^']*')|(?:[^ "'>]+))/gi,E=/^(href|src|name)$/i,H=/(?:<style(?=[ >])[^>]*>[\s\S]*?<\/style>)|(?:<(:?link|meta|base)[^>]*>)/gi,G=/(<textarea(?=[ >])[^>]*>)([\s\S]*?)(?:<\/textarea>)/gi,L=/<cke:encoded>([^<]*)<\/cke:encoded>/gi,O=/(<\/?)((?:object|embed|param|html|body|head|title)([\s][^>]*)?>)/gi,D=/(<\/?)cke:((?:html|body|head|title)[^>]*>)/gi,S=/<cke:(param|embed)([^>]*?)\/?>(?!\s*<\/cke:\1)/gi}(), "use strict",CKEDITOR.htmlParser.element=function(f,h){this.name=f;this.attributes=h||{};this.children=[];var e=f||"",k=e.match(/^cke:(.*)/);k&&(e=k[1]);e=!!(CKEDITOR.dtd.$nonBodyContent[e]||CKEDITOR.dtd.$block[e]||CKEDITOR.dtd.$listItem[e]||CKEDITOR.dtd.$tableContent[e]||CKEDITOR.dtd.$nonEditable[e]||"br"==e);this.isEmpty=!!CKEDITOR.dtd.$empty[f];this.isUnknown=!CKEDITOR.dtd[f];this._={isBlockLike:e,hasInlineStarted:this.isEmpty||!e}},CKEDITOR.htmlParser.cssStyle=function(f){var h={};((f instanceof CKEDITOR.htmlParser.element?f.attributes.style:f)||"").replace(/"/g,'"').replace(/\s*([^ :;]+)\s*:\s*([^;]+)\s*(?=;|$)/g,function(e,f,d){"font-family"==f&&(d=d.replace(/["']/g,""));h[f.toLowerCase()]=d});return{rules:h,populate:function(e){var f=this.toString();f&&(e instanceof CKEDITOR.dom.element?e.setAttribute("style",f):e instanceof CKEDITOR.htmlParser.element?e.attributes.style=f:e.style=f)},toString:function(){var e=[],f;for(f in h)h[f]&&e.push(f,":",h[f],";");return e.join("")}}},function(){function f(e){return function(d){return d.type== CKEDITOR.NODE_ELEMENT&&("string"==typeof e?d.name==e:d.name in e)}}var h=function(e,d){e=e[0];d=d[0];return e<d?-1:e>d?1:0},e=CKEDITOR.htmlParser.fragment.prototype;CKEDITOR.htmlParser.element.prototype=CKEDITOR.tools.extend(new CKEDITOR.htmlParser.node,{type:CKEDITOR.NODE_ELEMENT,add:e.add,clone:function(){return new CKEDITOR.htmlParser.element(this.name,this.attributes)},filter:function(e,d){var f=this,h,b;d=f.getFilterContext(d);if(d.off)return!0;if(!f.parent)e.onRoot(d,f);for(;;){h=f.name;if(!(b= @@ -338,169 +339,169 @@ d=CKEDITOR.dom.element.createFromHtml(c.output({id:e.id,name:d,langDir:e.lang.di CKEDITOR.appendTo=function(e,d,h){return f(e,d,h,CKEDITOR.ELEMENT_MODE_APPENDTO)};CKEDITOR.replaceAll=function(){for(var e=document.getElementsByTagName("textarea"),d=0;d<e.length;d++){var f=null,h=e[d];if(h.name||h.id){if("string"==typeof arguments[0]){if(!(new RegExp("(?:^|\\s)"+arguments[0]+"(?:$|\\s)")).test(h.className))continue}else if("function"==typeof arguments[0]&&(f={},!1===arguments[0](h,f)))continue;this.replace(h,f)}}};CKEDITOR.editor.prototype.addMode=function(e,d){(this._.modes||(this._.modes= {}))[e]=d};CKEDITOR.editor.prototype.setMode=function(e,d){var f=this,h=this._.modes;if(e!=f.mode&&h&&h[e]){f.fire("beforeSetMode",e);if(f.mode){var b=f.checkDirty(),h=f._.previousModeData,g,c=0;f.fire("beforeModeUnload");f.editable(0);f._.previousMode=f.mode;f._.previousModeData=g=f.getData(1);"source"==f.mode&&h==g&&(f.fire("lockSnapshot",{forceUpdate:!0}),c=1);f.ui.space("contents").setHtml("");f.mode=""}else f._.previousModeData=f.getData(1);this._.modes[e](function(){f.mode=e;void 0!==b&&!b&& f.resetDirty();c?f.fire("unlockSnapshot"):"wysiwyg"==e&&f.fire("saveSnapshot");setTimeout(function(){f.fire("mode");d&&d.call(f)},0)})}};CKEDITOR.editor.prototype.resize=function(e,d,f,h){var b=this.container,g=this.ui.space("contents"),c=CKEDITOR.env.webkit&&this.document&&this.document.getWindow().$.frameElement;h=h?this.container.getFirst(function(a){return a.type==CKEDITOR.NODE_ELEMENT&&a.hasClass("cke_inner")}):b;h.setSize("width",e,!0);c&&(c.style.width="1%");var a=(h.$.offsetHeight||0)-(g.$.clientHeight|| -0),b=Math.max(d-(f?0:a),0);d=f?d+a:d;g.setStyle("height",b+"px");c&&(c.style.width="100%");this.fire("resize",{outerHeight:d,contentsHeight:b,outerWidth:e||h.getSize("width")})};CKEDITOR.editor.prototype.getResizable=function(e){return e?this.ui.space("contents"):this.container};CKEDITOR.domReady(function(){CKEDITOR.replaceClass&&CKEDITOR.replaceAll(CKEDITOR.replaceClass)})}(),CKEDITOR.config.startupMode="wysiwyg",function(){function f(a){var c=a.editor,b=a.data.path,g=b.blockLimit,d=a.data.selection, -e=d.getRanges()[0],f;if(CKEDITOR.env.gecko||CKEDITOR.env.ie&&CKEDITOR.env.needsBrFiller)if(d=h(d,b))d.appendBogus(),f=CKEDITOR.env.ie;m(c,b.block,g)&&e.collapsed&&!e.getCommonAncestor().isReadOnly()&&(b=e.clone(),b.enlarge(CKEDITOR.ENLARGE_BLOCK_CONTENTS),g=new CKEDITOR.dom.walker(b),g.guard=function(a){return!k(a)||a.type==CKEDITOR.NODE_COMMENT||a.isReadOnly()},!g.checkForward()||b.checkStartOfBlock()&&b.checkEndOfBlock())&&(c=e.fixBlock(!0,c.activeEnterMode==CKEDITOR.ENTER_DIV?"div":"p"),CKEDITOR.env.needsBrFiller|| -(c=c.getFirst(k))&&c.type==CKEDITOR.NODE_TEXT&&CKEDITOR.tools.trim(c.getText()).match(/^(?: |\xa0)$/)&&c.remove(),f=1,a.cancel());f&&e.select()}function h(a,c){if(a.isFake)return 0;var b=c.block||c.blockLimit,g=b&&b.getLast(k);if(!(!b||!b.isBlockBoundary()||g&&g.type==CKEDITOR.NODE_ELEMENT&&g.isBlockBoundary()||b.is("pre")||b.getBogus()))return b}function e(a){var c=a.data.getTarget();c.is("input")&&(c=c.getAttribute("type"),"submit"!=c&&"reset"!=c||a.data.preventDefault())}function k(c){return a(c)&& -n(c)}function d(a,c){return function(b){var g=b.data.$.toElement||b.data.$.fromElement||b.data.$.relatedTarget;(g=g&&g.nodeType==CKEDITOR.NODE_ELEMENT?new CKEDITOR.dom.element(g):null)&&(c.equals(g)||c.contains(g))||a.call(this,b)}}function l(a){function c(a){return function(c,g){g&&c.type==CKEDITOR.NODE_ELEMENT&&c.is(d)&&(b=c);if(!(g||!k(c)||a&&v(c)))return!1}}var b,g=a.getRanges()[0];a=a.root;var d={table:1,ul:1,ol:1,dl:1};if(g.startPath().contains(d)){var e=g.clone();e.collapse(1);e.setStartAt(a, -CKEDITOR.POSITION_AFTER_START);a=new CKEDITOR.dom.walker(e);a.guard=c();a.checkBackward();if(b)return e=g.clone(),e.collapse(),e.setEndAt(b,CKEDITOR.POSITION_AFTER_END),a=new CKEDITOR.dom.walker(e),a.guard=c(!0),b=!1,a.checkForward(),b}return null}function m(a,c,b){return!1!==a.config.autoParagraph&&a.activeEnterMode!=CKEDITOR.ENTER_BR&&(a.editable().equals(b)&&!c||c&&"true"==c.getAttribute("contenteditable"))}function b(a){return a.activeEnterMode!=CKEDITOR.ENTER_BR&&!1!==a.config.autoParagraph? -a.activeEnterMode==CKEDITOR.ENTER_DIV?"div":"p":!1}function g(a){var c=a.editor;c.getSelection().scrollIntoView();setTimeout(function(){c.fire("saveSnapshot")},0)}function c(a,c,b){var g=a.getCommonAncestor(c);for(c=a=b?c:a;(a=a.getParent())&&!g.equals(a)&&1==a.getChildCount();)c=a;c.remove()}var a,n,w,v,p,r,q,u,x,A;CKEDITOR.editable=CKEDITOR.tools.createClass({base:CKEDITOR.dom.element,$:function(a,c){this.base(c.$||c);this.editor=a;this.status="unloaded";this.hasFocus=!1;this.setup()},proto:{focus:function(){var a; +0),b=Math.max(d-(f?0:a),0);d=f?d+a:d;g.setStyle("height",b+"px");c&&(c.style.width="100%");this.fire("resize",{outerHeight:d,contentsHeight:b,outerWidth:e||h.getSize("width")})};CKEDITOR.editor.prototype.getResizable=function(e){return e?this.ui.space("contents"):this.container};CKEDITOR.domReady(function(){CKEDITOR.replaceClass&&CKEDITOR.replaceAll(CKEDITOR.replaceClass)})}(),CKEDITOR.config.startupMode="wysiwyg",function(){function f(a){var c=a.editor,b=a.data.path,d=b.blockLimit,g=a.data.selection, +e=g.getRanges()[0],f;if(CKEDITOR.env.gecko||CKEDITOR.env.ie&&CKEDITOR.env.needsBrFiller)if(g=h(g,b))g.appendBogus(),f=CKEDITOR.env.ie;m(c,b.block,d)&&e.collapsed&&!e.getCommonAncestor().isReadOnly()&&(b=e.clone(),b.enlarge(CKEDITOR.ENLARGE_BLOCK_CONTENTS),d=new CKEDITOR.dom.walker(b),d.guard=function(a){return!k(a)||a.type==CKEDITOR.NODE_COMMENT||a.isReadOnly()},!d.checkForward()||b.checkStartOfBlock()&&b.checkEndOfBlock())&&(c=e.fixBlock(!0,c.activeEnterMode==CKEDITOR.ENTER_DIV?"div":"p"),CKEDITOR.env.needsBrFiller|| +(c=c.getFirst(k))&&c.type==CKEDITOR.NODE_TEXT&&CKEDITOR.tools.trim(c.getText()).match(/^(?: |\xa0)$/)&&c.remove(),f=1,a.cancel());f&&e.select()}function h(a,c){if(a.isFake)return 0;var b=c.block||c.blockLimit,d=b&&b.getLast(k);if(!(!b||!b.isBlockBoundary()||d&&d.type==CKEDITOR.NODE_ELEMENT&&d.isBlockBoundary()||b.is("pre")||b.getBogus()))return b}function e(a){var c=a.data.getTarget();c.is("input")&&(c=c.getAttribute("type"),"submit"!=c&&"reset"!=c||a.data.preventDefault())}function k(c){return a(c)&& +n(c)}function d(a,c){return function(b){var d=b.data.$.toElement||b.data.$.fromElement||b.data.$.relatedTarget;(d=d&&d.nodeType==CKEDITOR.NODE_ELEMENT?new CKEDITOR.dom.element(d):null)&&(c.equals(d)||c.contains(d))||a.call(this,b)}}function l(a){function c(a){return function(c,d){d&&c.type==CKEDITOR.NODE_ELEMENT&&c.is(g)&&(b=c);if(!(d||!k(c)||a&&v(c)))return!1}}var b,d=a.getRanges()[0];a=a.root;var g={table:1,ul:1,ol:1,dl:1};if(d.startPath().contains(g)){var e=d.clone();e.collapse(1);e.setStartAt(a, +CKEDITOR.POSITION_AFTER_START);a=new CKEDITOR.dom.walker(e);a.guard=c();a.checkBackward();if(b)return e=d.clone(),e.collapse(),e.setEndAt(b,CKEDITOR.POSITION_AFTER_END),a=new CKEDITOR.dom.walker(e),a.guard=c(!0),b=!1,a.checkForward(),b}return null}function m(a,c,b){return!1!==a.config.autoParagraph&&a.activeEnterMode!=CKEDITOR.ENTER_BR&&(a.editable().equals(b)&&!c||c&&"true"==c.getAttribute("contenteditable"))}function b(a){return a.activeEnterMode!=CKEDITOR.ENTER_BR&&!1!==a.config.autoParagraph? +a.activeEnterMode==CKEDITOR.ENTER_DIV?"div":"p":!1}function g(a){var c=a.editor;c.getSelection().scrollIntoView();setTimeout(function(){c.fire("saveSnapshot")},0)}function c(a,c,b){var d=a.getCommonAncestor(c);for(c=a=b?c:a;(a=a.getParent())&&!d.equals(a)&&1==a.getChildCount();)c=a;c.remove()}var a,n,w,v,t,p,q,A,r,C;CKEDITOR.editable=CKEDITOR.tools.createClass({base:CKEDITOR.dom.element,$:function(a,c){this.base(c.$||c);this.editor=a;this.status="unloaded";this.hasFocus=!1;this.setup()},proto:{focus:function(){var a; if(CKEDITOR.env.webkit&&!this.hasFocus&&(a=this.editor._.previousActive||this.getDocument().getActive(),this.contains(a))){a.focus();return}CKEDITOR.env.edge&&14<CKEDITOR.env.version&&!this.hasFocus&&this.getDocument().equals(CKEDITOR.document)&&(this.editor._.previousScrollTop=this.$.scrollTop);try{if(!CKEDITOR.env.ie||CKEDITOR.env.edge&&14<CKEDITOR.env.version||!this.getDocument().equals(CKEDITOR.document))if(CKEDITOR.env.chrome){var c=this.$.scrollTop;this.$.focus();this.$.scrollTop=c}else this.$.focus(); else this.$.setActive()}catch(b){if(!CKEDITOR.env.ie)throw b;}CKEDITOR.env.safari&&!this.isInline()&&(a=CKEDITOR.document.getActive(),a.equals(this.getWindow().getFrame())||this.getWindow().focus())},on:function(a,c){var b=Array.prototype.slice.call(arguments,0);CKEDITOR.env.ie&&/^focus|blur$/.exec(a)&&(a="focus"==a?"focusin":"focusout",c=d(c,this),b[0]=a,b[1]=c);return CKEDITOR.dom.element.prototype.on.apply(this,b)},attachListener:function(a){!this._.listeners&&(this._.listeners=[]);var c=Array.prototype.slice.call(arguments, 1),c=a.on.apply(a,c);this._.listeners.push(c);return c},clearListeners:function(){var a=this._.listeners;try{for(;a.length;)a.pop().removeListener()}catch(c){}},restoreAttrs:function(){var a=this._.attrChanges,c,b;for(b in a)a.hasOwnProperty(b)&&(c=a[b],null!==c?this.setAttribute(b,c):this.removeAttribute(b))},attachClass:function(a){var c=this.getCustomData("classes");this.hasClass(a)||(!c&&(c=[]),c.push(a),this.setCustomData("classes",c),this.addClass(a))},changeAttr:function(a,c){var b=this.getAttribute(a); c!==b&&(!this._.attrChanges&&(this._.attrChanges={}),a in this._.attrChanges||(this._.attrChanges[a]=b),this.setAttribute(a,c))},insertText:function(a){this.editor.focus();this.insertHtml(this.transformPlainTextToHtml(a),"text")},transformPlainTextToHtml:function(a){var c=this.editor.getSelection().getStartElement().hasAscendant("pre",!0)?CKEDITOR.ENTER_BR:this.editor.activeEnterMode;return CKEDITOR.tools.transformPlainTextToHtml(a,c)},insertHtml:function(a,c,b){var d=this.editor;d.focus();d.fire("saveSnapshot"); -b||(b=d.getSelection().getRanges()[0]);r(this,c||"html",a,b);b.select();g(this);this.editor.fire("afterInsertHtml",{})},insertHtmlIntoRange:function(a,c,b){r(this,b||"html",a,c);this.editor.fire("afterInsertHtml",{intoRange:c})},insertElement:function(a,c){var b=this.editor;b.focus();b.fire("saveSnapshot");var d=b.activeEnterMode,b=b.getSelection(),e=a.getName(),e=CKEDITOR.dtd.$block[e];c||(c=b.getRanges()[0]);this.insertElementIntoRange(a,c)&&(c.moveToPosition(a,CKEDITOR.POSITION_AFTER_END),e&&((e= -a.getNext(function(a){return k(a)&&!v(a)}))&&e.type==CKEDITOR.NODE_ELEMENT&&e.is(CKEDITOR.dtd.$block)?e.getDtd()["#"]?c.moveToElementEditStart(e):c.moveToElementEditEnd(a):e||d==CKEDITOR.ENTER_BR||(e=c.fixBlock(!0,d==CKEDITOR.ENTER_DIV?"div":"p"),c.moveToElementEditStart(e))));b.selectRanges([c]);g(this)},insertElementIntoSelection:function(a){this.insertElement(a)},insertElementIntoRange:function(a,c){var b=this.editor,g=b.config.enterMode,d=a.getName(),e=CKEDITOR.dtd.$block[d];if(c.checkReadOnly())return!1; -c.deleteContents(1);c.startContainer.type==CKEDITOR.NODE_ELEMENT&&(c.startContainer.is({tr:1,table:1,tbody:1,thead:1,tfoot:1})?q(c):c.startContainer.is(CKEDITOR.dtd.$list)&&u(c));var f,h;if(e)for(;(f=c.getCommonAncestor(0,1))&&(h=CKEDITOR.dtd[f.getName()])&&(!h||!h[d]);)f.getName()in CKEDITOR.dtd.span?c.splitElement(f):c.checkStartOfBlock()&&c.checkEndOfBlock()?(c.setStartBefore(f),c.collapse(!0),f.remove()):c.splitBlock(g==CKEDITOR.ENTER_DIV?"div":"p",b.editable());c.insertNode(a);return!0},setData:function(a, +b||(b=d.getSelection().getRanges()[0]);p(this,c||"html",a,b);b.select();g(this);this.editor.fire("afterInsertHtml",{})},insertHtmlIntoRange:function(a,c,b){p(this,b||"html",a,c);this.editor.fire("afterInsertHtml",{intoRange:c})},insertElement:function(a,c){var b=this.editor;b.focus();b.fire("saveSnapshot");var d=b.activeEnterMode,b=b.getSelection(),e=a.getName(),e=CKEDITOR.dtd.$block[e];c||(c=b.getRanges()[0]);this.insertElementIntoRange(a,c)&&(c.moveToPosition(a,CKEDITOR.POSITION_AFTER_END),e&&((e= +a.getNext(function(a){return k(a)&&!v(a)}))&&e.type==CKEDITOR.NODE_ELEMENT&&e.is(CKEDITOR.dtd.$block)?e.getDtd()["#"]?c.moveToElementEditStart(e):c.moveToElementEditEnd(a):e||d==CKEDITOR.ENTER_BR||(e=c.fixBlock(!0,d==CKEDITOR.ENTER_DIV?"div":"p"),c.moveToElementEditStart(e))));b.selectRanges([c]);g(this)},insertElementIntoSelection:function(a){this.insertElement(a)},insertElementIntoRange:function(a,c){var b=this.editor,d=b.config.enterMode,g=a.getName(),e=CKEDITOR.dtd.$block[g];if(c.checkReadOnly())return!1; +c.deleteContents(1);c.startContainer.type==CKEDITOR.NODE_ELEMENT&&(c.startContainer.is({tr:1,table:1,tbody:1,thead:1,tfoot:1})?q(c):c.startContainer.is(CKEDITOR.dtd.$list)&&A(c));var f,h;if(e)for(;(f=c.getCommonAncestor(0,1))&&(h=CKEDITOR.dtd[f.getName()])&&(!h||!h[g]);)f.getName()in CKEDITOR.dtd.span?c.splitElement(f):c.checkStartOfBlock()&&c.checkEndOfBlock()?(c.setStartBefore(f),c.collapse(!0),f.remove()):c.splitBlock(d==CKEDITOR.ENTER_DIV?"div":"p",b.editable());c.insertNode(a);return!0},setData:function(a, c){c||(a=this.editor.dataProcessor.toHtml(a));this.setHtml(a);this.fixInitialSelection();"unloaded"==this.status&&(this.status="ready");this.editor.fire("dataReady")},getData:function(a){var c=this.getHtml();a||(c=this.editor.dataProcessor.toDataFormat(c));return c},setReadOnly:function(a){this.setAttribute("contenteditable",!a)},detach:function(){this.removeClass("cke_editable");this.status="detached";var a=this.editor;this._.detach();delete a.document;delete a.window},isInline:function(){return this.getDocument().equals(CKEDITOR.document)}, -fixInitialSelection:function(){function a(){var c=b.getDocument().$,g=c.getSelection(),d;a:if(g.anchorNode&&g.anchorNode==b.$)d=!0;else{if(CKEDITOR.env.webkit&&(d=b.getDocument().getActive())&&d.equals(b)&&!g.anchorNode){d=!0;break a}d=void 0}d&&(d=new CKEDITOR.dom.range(b),d.moveToElementEditStart(b),c=c.createRange(),c.setStart(d.startContainer.$,d.startOffset),c.collapse(!0),g.removeAllRanges(),g.addRange(c))}function c(){var a=b.getDocument().$,g=a.selection,d=b.getDocument().getActive();"None"== -g.type&&d.equals(b)&&(g=new CKEDITOR.dom.range(b),a=a.body.createTextRange(),g.moveToElementEditStart(b),g=g.startContainer,g.type!=CKEDITOR.NODE_ELEMENT&&(g=g.getParent()),a.moveToElementText(g.$),a.collapse(!0),a.select())}var b=this;if(CKEDITOR.env.ie&&(9>CKEDITOR.env.version||CKEDITOR.env.quirks))this.hasFocus&&(this.focus(),c());else if(this.hasFocus)this.focus(),a();else this.once("focus",function(){a()},null,null,-999)},getHtmlFromRange:function(a){if(a.collapsed)return new CKEDITOR.dom.documentFragment(a.document); -a={doc:this.getDocument(),range:a.clone()};x.eol.detect(a,this);x.bogus.exclude(a);x.cell.shrink(a);a.fragment=a.range.cloneContents();x.tree.rebuild(a,this);x.eol.fix(a,this);return new CKEDITOR.dom.documentFragment(a.fragment.$)},extractHtmlFromRange:function(a,c){var b=A,g={range:a,doc:a.document},d=this.getHtmlFromRange(a);if(a.collapsed)return a.optimize(),d;a.enlarge(CKEDITOR.ENLARGE_INLINE,1);b.table.detectPurge(g);g.bookmark=a.createBookmark();delete g.range;var e=this.editor.createRange(); -e.moveToPosition(g.bookmark.startNode,CKEDITOR.POSITION_BEFORE_START);g.targetBookmark=e.createBookmark();b.list.detectMerge(g,this);b.table.detectRanges(g,this);b.block.detectMerge(g,this);g.tableContentsRanges?(b.table.deleteRanges(g),a.moveToBookmark(g.bookmark),g.range=a):(a.moveToBookmark(g.bookmark),g.range=a,a.extractContents(b.detectExtractMerge(g)));a.moveToBookmark(g.targetBookmark);a.optimize();b.fixUneditableRangePosition(a);b.list.merge(g,this);b.table.purge(g,this);b.block.merge(g,this); -if(c){b=a.startPath();if(g=a.checkStartOfBlock()&&a.checkEndOfBlock()&&b.block&&!a.root.equals(b.block)){a:{var g=b.block.getElementsByTag("span"),e=0,f;if(g)for(;f=g.getItem(e++);)if(!n(f)){g=!0;break a}g=!1}g=!g}g&&(a.moveToPosition(b.block,CKEDITOR.POSITION_BEFORE_START),b.block.remove())}else b.autoParagraph(this.editor,a),w(a.startContainer)&&a.startContainer.appendBogus();a.startContainer.mergeSiblings();return d},setup:function(){var b=this.editor;this.attachListener(b,"beforeGetData",function(){var a= -this.getData();this.is("textarea")||!1!==b.config.ignoreEmptyParagraph&&(a=a.replace(p,function(a,c){return c}));b.setData(a,null,1)},this);this.attachListener(b,"getSnapshot",function(a){a.data=this.getData(1)},this);this.attachListener(b,"afterSetData",function(){this.setData(b.getData(1))},this);this.attachListener(b,"loadSnapshot",function(a){this.setData(a.data,1)},this);this.attachListener(b,"beforeFocus",function(){var a=b.getSelection();(a=a&&a.getNative())&&"Control"==a.type||this.focus()}, +fixInitialSelection:function(){function a(){var c=b.getDocument().$,d=c.getSelection(),g;a:if(d.anchorNode&&d.anchorNode==b.$)g=!0;else{if(CKEDITOR.env.webkit&&(g=b.getDocument().getActive())&&g.equals(b)&&!d.anchorNode){g=!0;break a}g=void 0}g&&(g=new CKEDITOR.dom.range(b),g.moveToElementEditStart(b),c=c.createRange(),c.setStart(g.startContainer.$,g.startOffset),c.collapse(!0),d.removeAllRanges(),d.addRange(c))}function c(){var a=b.getDocument().$,d=a.selection,g=b.getDocument().getActive();"None"== +d.type&&g.equals(b)&&(d=new CKEDITOR.dom.range(b),a=a.body.createTextRange(),d.moveToElementEditStart(b),d=d.startContainer,d.type!=CKEDITOR.NODE_ELEMENT&&(d=d.getParent()),a.moveToElementText(d.$),a.collapse(!0),a.select())}var b=this;if(CKEDITOR.env.ie&&(9>CKEDITOR.env.version||CKEDITOR.env.quirks))this.hasFocus&&(this.focus(),c());else if(this.hasFocus)this.focus(),a();else this.once("focus",function(){a()},null,null,-999)},getHtmlFromRange:function(a){if(a.collapsed)return new CKEDITOR.dom.documentFragment(a.document); +a={doc:this.getDocument(),range:a.clone()};r.eol.detect(a,this);r.bogus.exclude(a);r.cell.shrink(a);a.fragment=a.range.cloneContents();r.tree.rebuild(a,this);r.eol.fix(a,this);return new CKEDITOR.dom.documentFragment(a.fragment.$)},extractHtmlFromRange:function(a,c){var b=C,d={range:a,doc:a.document},g=this.getHtmlFromRange(a);if(a.collapsed)return a.optimize(),g;a.enlarge(CKEDITOR.ENLARGE_INLINE,1);b.table.detectPurge(d);d.bookmark=a.createBookmark();delete d.range;var e=this.editor.createRange(); +e.moveToPosition(d.bookmark.startNode,CKEDITOR.POSITION_BEFORE_START);d.targetBookmark=e.createBookmark();b.list.detectMerge(d,this);b.table.detectRanges(d,this);b.block.detectMerge(d,this);d.tableContentsRanges?(b.table.deleteRanges(d),a.moveToBookmark(d.bookmark),d.range=a):(a.moveToBookmark(d.bookmark),d.range=a,a.extractContents(b.detectExtractMerge(d)));a.moveToBookmark(d.targetBookmark);a.optimize();b.fixUneditableRangePosition(a);b.list.merge(d,this);b.table.purge(d,this);b.block.merge(d,this); +if(c){b=a.startPath();if(d=a.checkStartOfBlock()&&a.checkEndOfBlock()&&b.block&&!a.root.equals(b.block)){a:{var d=b.block.getElementsByTag("span"),e=0,f;if(d)for(;f=d.getItem(e++);)if(!n(f)){d=!0;break a}d=!1}d=!d}d&&(a.moveToPosition(b.block,CKEDITOR.POSITION_BEFORE_START),b.block.remove())}else b.autoParagraph(this.editor,a),w(a.startContainer)&&a.startContainer.appendBogus();a.startContainer.mergeSiblings();return g},setup:function(){var b=this.editor;this.attachListener(b,"beforeGetData",function(){var a= +this.getData();this.is("textarea")||!1!==b.config.ignoreEmptyParagraph&&(a=a.replace(t,function(a,c){return c}));b.setData(a,null,1)},this);this.attachListener(b,"getSnapshot",function(a){a.data=this.getData(1)},this);this.attachListener(b,"afterSetData",function(){this.setData(b.getData(1))},this);this.attachListener(b,"loadSnapshot",function(a){this.setData(a.data,1)},this);this.attachListener(b,"beforeFocus",function(){var a=b.getSelection();(a=a&&a.getNative())&&"Control"==a.type||this.focus()}, this);this.attachListener(b,"insertHtml",function(a){this.insertHtml(a.data.dataValue,a.data.mode,a.data.range)},this);this.attachListener(b,"insertElement",function(a){this.insertElement(a.data)},this);this.attachListener(b,"insertText",function(a){this.insertText(a.data)},this);this.setReadOnly(b.readOnly);this.attachClass("cke_editable");b.elementMode==CKEDITOR.ELEMENT_MODE_INLINE?this.attachClass("cke_editable_inline"):b.elementMode!=CKEDITOR.ELEMENT_MODE_REPLACE&&b.elementMode!=CKEDITOR.ELEMENT_MODE_APPENDTO|| -this.attachClass("cke_editable_themed");this.attachClass("cke_contents_"+b.config.contentsLangDirection);b.keystrokeHandler.blockedKeystrokes[8]=+b.readOnly;b.keystrokeHandler.attach(this);this.on("blur",function(){this.hasFocus=!1},null,null,-1);this.on("focus",function(){this.hasFocus=!0},null,null,-1);if(CKEDITOR.env.webkit)this.on("scroll",function(){b._.previousScrollTop=b.editable().$.scrollTop},null,null,-1);if(CKEDITOR.env.edge&&14<CKEDITOR.env.version){var g=function(){var a=b.editable(); -null!=b._.previousScrollTop&&a.getDocument().equals(CKEDITOR.document)&&(a.$.scrollTop=b._.previousScrollTop,b._.previousScrollTop=null,this.removeListener("scroll",g))};this.on("scroll",g)}b.focusManager.add(this);this.equals(CKEDITOR.document.getActive())&&(this.hasFocus=!0,b.once("contentDom",function(){b.focusManager.focus(this)},this));this.isInline()&&this.changeAttr("tabindex",b.tabIndex);if(!this.is("textarea")){b.document=this.getDocument();b.window=this.getWindow();var d=b.document;this.changeAttr("spellcheck", -!b.config.disableNativeSpellChecker);var f=b.config.contentsLangDirection;this.getDirection(1)!=f&&this.changeAttr("dir",f);var h=CKEDITOR.getCss();if(h){var f=d.getHead(),n=f.getCustomData("stylesheet");n?h!=n.getText()&&(CKEDITOR.env.ie&&9>CKEDITOR.env.version?n.$.styleSheet.cssText=h:n.setText(h)):(h=d.appendStyleText(h),h=new CKEDITOR.dom.element(h.ownerNode||h.owningElement),f.setCustomData("stylesheet",h),h.data("cke-temp",1))}f=d.getCustomData("stylesheet_ref")||0;d.setCustomData("stylesheet_ref", -f+1);this.setCustomData("cke_includeReadonly",!b.config.disableReadonlyStyling);this.attachListener(this,"click",function(a){a=a.data;var c=(new CKEDITOR.dom.elementPath(a.getTarget(),this)).contains("a");c&&2!=a.$.button&&c.isReadOnly()&&a.preventDefault()});var m={8:1,46:1};this.attachListener(b,"key",function(c){if(b.readOnly)return!0;var g=c.data.domEvent.getKey(),d;c=b.getSelection();if(0!==c.getRanges().length){if(g in m){var e,f=c.getRanges()[0],h=f.startPath(),k,n,q,g=8==g;CKEDITOR.env.ie&& -11>CKEDITOR.env.version&&(e=c.getSelectedElement())||(e=l(c))?(b.fire("saveSnapshot"),f.moveToPosition(e,CKEDITOR.POSITION_BEFORE_START),e.remove(),f.select(),b.fire("saveSnapshot"),d=1):f.collapsed&&((k=h.block)&&(q=k[g?"getPrevious":"getNext"](a))&&q.type==CKEDITOR.NODE_ELEMENT&&q.is("table")&&f[g?"checkStartOfBlock":"checkEndOfBlock"]()?(b.fire("saveSnapshot"),f[g?"checkEndOfBlock":"checkStartOfBlock"]()&&k.remove(),f["moveToElementEdit"+(g?"End":"Start")](q),f.select(),b.fire("saveSnapshot"), -d=1):h.blockLimit&&h.blockLimit.is("td")&&(n=h.blockLimit.getAscendant("table"))&&f.checkBoundaryOfElement(n,g?CKEDITOR.START:CKEDITOR.END)&&(q=n[g?"getPrevious":"getNext"](a))?(b.fire("saveSnapshot"),f["moveToElementEdit"+(g?"End":"Start")](q),f.checkStartOfBlock()&&f.checkEndOfBlock()?q.remove():f.select(),b.fire("saveSnapshot"),d=1):(n=h.contains(["td","th","caption"]))&&f.checkBoundaryOfElement(n,g?CKEDITOR.START:CKEDITOR.END)&&(d=1))}return!d}});b.blockless&&CKEDITOR.env.ie&&CKEDITOR.env.needsBrFiller&& +this.attachClass("cke_editable_themed");this.attachClass("cke_contents_"+b.config.contentsLangDirection);b.keystrokeHandler.blockedKeystrokes[8]=+b.readOnly;b.keystrokeHandler.attach(this);this.on("blur",function(){this.hasFocus=!1},null,null,-1);this.on("focus",function(){this.hasFocus=!0},null,null,-1);if(CKEDITOR.env.webkit)this.on("scroll",function(){b._.previousScrollTop=b.editable().$.scrollTop},null,null,-1);if(CKEDITOR.env.edge&&14<CKEDITOR.env.version){var d=function(){var a=b.editable(); +null!=b._.previousScrollTop&&a.getDocument().equals(CKEDITOR.document)&&(a.$.scrollTop=b._.previousScrollTop,b._.previousScrollTop=null,this.removeListener("scroll",d))};this.on("scroll",d)}b.focusManager.add(this);this.equals(CKEDITOR.document.getActive())&&(this.hasFocus=!0,b.once("contentDom",function(){b.focusManager.focus(this)},this));this.isInline()&&this.changeAttr("tabindex",b.tabIndex);if(!this.is("textarea")){b.document=this.getDocument();b.window=this.getWindow();var g=b.document;this.changeAttr("spellcheck", +!b.config.disableNativeSpellChecker);var f=b.config.contentsLangDirection;this.getDirection(1)!=f&&this.changeAttr("dir",f);var h=CKEDITOR.getCss();if(h){var f=g.getHead(),n=f.getCustomData("stylesheet");n?h!=n.getText()&&(CKEDITOR.env.ie&&9>CKEDITOR.env.version?n.$.styleSheet.cssText=h:n.setText(h)):(h=g.appendStyleText(h),h=new CKEDITOR.dom.element(h.ownerNode||h.owningElement),f.setCustomData("stylesheet",h),h.data("cke-temp",1))}f=g.getCustomData("stylesheet_ref")||0;g.setCustomData("stylesheet_ref", +f+1);this.setCustomData("cke_includeReadonly",!b.config.disableReadonlyStyling);this.attachListener(this,"click",function(a){a=a.data;var c=(new CKEDITOR.dom.elementPath(a.getTarget(),this)).contains("a");c&&2!=a.$.button&&c.isReadOnly()&&a.preventDefault()});var m={8:1,46:1};this.attachListener(b,"key",function(c){if(b.readOnly)return!0;var d=c.data.domEvent.getKey(),g;c=b.getSelection();if(0!==c.getRanges().length){if(d in m){var e,f=c.getRanges()[0],h=f.startPath(),k,n,q,d=8==d;CKEDITOR.env.ie&& +11>CKEDITOR.env.version&&(e=c.getSelectedElement())||(e=l(c))?(b.fire("saveSnapshot"),f.moveToPosition(e,CKEDITOR.POSITION_BEFORE_START),e.remove(),f.select(),b.fire("saveSnapshot"),g=1):f.collapsed&&((k=h.block)&&(q=k[d?"getPrevious":"getNext"](a))&&q.type==CKEDITOR.NODE_ELEMENT&&q.is("table")&&f[d?"checkStartOfBlock":"checkEndOfBlock"]()?(b.fire("saveSnapshot"),f[d?"checkEndOfBlock":"checkStartOfBlock"]()&&k.remove(),f["moveToElementEdit"+(d?"End":"Start")](q),f.select(),b.fire("saveSnapshot"), +g=1):h.blockLimit&&h.blockLimit.is("td")&&(n=h.blockLimit.getAscendant("table"))&&f.checkBoundaryOfElement(n,d?CKEDITOR.START:CKEDITOR.END)&&(q=n[d?"getPrevious":"getNext"](a))?(b.fire("saveSnapshot"),f["moveToElementEdit"+(d?"End":"Start")](q),f.checkStartOfBlock()&&f.checkEndOfBlock()?q.remove():f.select(),b.fire("saveSnapshot"),g=1):(n=h.contains(["td","th","caption"]))&&f.checkBoundaryOfElement(n,d?CKEDITOR.START:CKEDITOR.END)&&(g=1))}return!g}});b.blockless&&CKEDITOR.env.ie&&CKEDITOR.env.needsBrFiller&& this.attachListener(this,"keyup",function(a){a.data.getKeystroke()in m&&!this.getFirst(k)&&(this.appendBogus(),a=b.createRange(),a.moveToPosition(this,CKEDITOR.POSITION_AFTER_START),a.select())});this.attachListener(this,"dblclick",function(a){if(b.readOnly)return!1;a={element:a.data.getTarget()};b.fire("doubleclick",a)});CKEDITOR.env.ie&&this.attachListener(this,"click",e);CKEDITOR.env.ie&&!CKEDITOR.env.edge||this.attachListener(this,"mousedown",function(a){var c=a.data.getTarget();c.is("img","hr", -"input","textarea","select")&&!c.isReadOnly()&&(b.getSelection().selectElement(c),c.is("input","textarea","select")&&a.data.preventDefault())});CKEDITOR.env.edge&&this.attachListener(this,"mouseup",function(a){(a=a.data.getTarget())&&a.is("img")&&!a.isReadOnly()&&b.getSelection().selectElement(a)});CKEDITOR.env.gecko&&this.attachListener(this,"mouseup",function(a){if(2==a.data.$.button&&(a=a.data.getTarget(),!a.getOuterHtml().replace(p,""))){var c=b.createRange();c.moveToElementEditStart(a);c.select(!0)}}); -CKEDITOR.env.webkit&&(this.attachListener(this,"click",function(a){a.data.getTarget().is("input","select")&&a.data.preventDefault()}),this.attachListener(this,"mouseup",function(a){a.data.getTarget().is("input","textarea")&&a.data.preventDefault()}));CKEDITOR.env.webkit&&this.attachListener(b,"key",function(a){if(b.readOnly)return!0;var g=a.data.domEvent.getKey();if(g in m&&(a=b.getSelection(),0!==a.getRanges().length)){var g=8==g,d=a.getRanges()[0];a=d.startPath();if(d.collapsed)a:{var e=a.block; -if(e&&d[g?"checkStartOfBlock":"checkEndOfBlock"]()&&d.moveToClosestEditablePosition(e,!g)&&d.collapsed){if(d.startContainer.type==CKEDITOR.NODE_ELEMENT){var f=d.startContainer.getChild(d.startOffset-(g?1:0));if(f&&f.type==CKEDITOR.NODE_ELEMENT&&f.is("hr")){b.fire("saveSnapshot");f.remove();a=!0;break a}}d=d.startPath().block;if(!d||d&&d.contains(e))a=void 0;else{b.fire("saveSnapshot");var h;(h=(g?d:e).getBogus())&&h.remove();h=b.getSelection();f=h.createBookmarks();(g?e:d).moveChildren(g?d:e,!1); -a.lastElement.mergeSiblings();c(e,d,!g);h.selectBookmarks(f);a=!0}}else a=!1}else g=d,h=a.block,d=g.endPath().block,h&&d&&!h.equals(d)?(b.fire("saveSnapshot"),(e=h.getBogus())&&e.remove(),g.enlarge(CKEDITOR.ENLARGE_INLINE),g.deleteContents(),d.getParent()&&(d.moveChildren(h,!1),a.lastElement.mergeSiblings(),c(h,d,!0)),g=b.getSelection().getRanges()[0],g.collapse(1),g.optimize(),""===g.startContainer.getHtml()&&g.startContainer.appendBogus(),g.select(),a=!0):a=!1;if(!a)return;b.getSelection().scrollIntoView(); +"input","textarea","select")&&!c.isReadOnly()&&(b.getSelection().selectElement(c),c.is("input","textarea","select")&&a.data.preventDefault())});CKEDITOR.env.edge&&this.attachListener(this,"mouseup",function(a){(a=a.data.getTarget())&&a.is("img")&&!a.isReadOnly()&&b.getSelection().selectElement(a)});CKEDITOR.env.gecko&&this.attachListener(this,"mouseup",function(a){if(2==a.data.$.button&&(a=a.data.getTarget(),!a.getAscendant("table")&&!a.getOuterHtml().replace(t,""))){var c=b.createRange();c.moveToElementEditStart(a); +c.select(!0)}});CKEDITOR.env.webkit&&(this.attachListener(this,"click",function(a){a.data.getTarget().is("input","select")&&a.data.preventDefault()}),this.attachListener(this,"mouseup",function(a){a.data.getTarget().is("input","textarea")&&a.data.preventDefault()}));CKEDITOR.env.webkit&&this.attachListener(b,"key",function(a){if(b.readOnly)return!0;var d=a.data.domEvent.getKey();if(d in m&&(a=b.getSelection(),0!==a.getRanges().length)){var d=8==d,g=a.getRanges()[0];a=g.startPath();if(g.collapsed)a:{var e= +a.block;if(e&&g[d?"checkStartOfBlock":"checkEndOfBlock"]()&&g.moveToClosestEditablePosition(e,!d)&&g.collapsed){if(g.startContainer.type==CKEDITOR.NODE_ELEMENT){var f=g.startContainer.getChild(g.startOffset-(d?1:0));if(f&&f.type==CKEDITOR.NODE_ELEMENT&&f.is("hr")){b.fire("saveSnapshot");f.remove();a=!0;break a}}g=g.startPath().block;if(!g||g&&g.contains(e))a=void 0;else{b.fire("saveSnapshot");var h;(h=(d?g:e).getBogus())&&h.remove();h=b.getSelection();f=h.createBookmarks();(d?e:g).moveChildren(d? +g:e,!1);a.lastElement.mergeSiblings();c(e,g,!d);h.selectBookmarks(f);a=!0}}else a=!1}else d=g,h=a.block,g=d.endPath().block,h&&g&&!h.equals(g)?(b.fire("saveSnapshot"),(e=h.getBogus())&&e.remove(),d.enlarge(CKEDITOR.ENLARGE_INLINE),d.deleteContents(),g.getParent()&&(g.moveChildren(h,!1),a.lastElement.mergeSiblings(),c(h,g,!0)),d=b.getSelection().getRanges()[0],d.collapse(1),d.optimize(),""===d.startContainer.getHtml()&&d.startContainer.appendBogus(),d.select(),a=!0):a=!1;if(!a)return;b.getSelection().scrollIntoView(); b.fire("saveSnapshot");return!1}},this,null,100)}}},_:{detach:function(){this.editor.setData(this.editor.getData(),0,1);this.clearListeners();this.restoreAttrs();var a;if(a=this.removeCustomData("classes"))for(;a.length;)this.removeClass(a.pop());if(!this.is("textarea")){a=this.getDocument();var c=a.getHead();if(c.getCustomData("stylesheet")){var b=a.getCustomData("stylesheet_ref");--b?a.setCustomData("stylesheet_ref",b):(a.removeCustomData("stylesheet_ref"),c.removeCustomData("stylesheet").remove())}}this.editor.fire("contentDomUnload"); delete this.editor}}});CKEDITOR.editor.prototype.editable=function(a){var c=this._.editable;if(c&&a)return 0;arguments.length&&(c=this._.editable=a?a instanceof CKEDITOR.editable?a:new CKEDITOR.editable(this,a):(c&&c.detach(),null));return c};CKEDITOR.on("instanceLoaded",function(a){var c=a.editor;c.on("insertElement",function(a){a=a.data;a.type==CKEDITOR.NODE_ELEMENT&&(a.is("input")||a.is("textarea"))&&("false"!=a.getAttribute("contentEditable")&&a.data("cke-editable",a.hasAttribute("contenteditable")? -"true":"1"),a.setAttribute("contentEditable",!1))});c.on("selectionChange",function(a){if(!c.readOnly){var b=c.getSelection();b&&!b.isLocked&&(b=c.checkDirty(),c.fire("lockSnapshot"),f(a),c.fire("unlockSnapshot"),!b&&c.resetDirty())}})});CKEDITOR.on("instanceCreated",function(a){var c=a.editor;c.on("mode",function(){var a=c.editable();if(a&&a.isInline()){var b=c.title;a.changeAttr("role","textbox");a.changeAttr("aria-multiline","true");a.changeAttr("aria-label",b);b&&a.changeAttr("title",b);var g= -c.fire("ariaEditorHelpLabel",{}).label;if(g&&(b=this.ui.space(this.elementMode==CKEDITOR.ELEMENT_MODE_INLINE?"top":"contents"))){var d=CKEDITOR.tools.getNextId(),g=CKEDITOR.dom.element.createFromHtml('\x3cspan id\x3d"'+d+'" class\x3d"cke_voice_label"\x3e'+g+"\x3c/span\x3e");b.append(g);a.changeAttr("aria-describedby",d)}}})});CKEDITOR.addCss(".cke_editable{cursor:text}.cke_editable img,.cke_editable input,.cke_editable textarea{cursor:default}");a=CKEDITOR.dom.walker.whitespaces(!0);n=CKEDITOR.dom.walker.bookmark(!1, -!0);w=CKEDITOR.dom.walker.empty();v=CKEDITOR.dom.walker.bogus();p=/(^|<body\b[^>]*>)\s*<(p|div|address|h\d|center|pre)[^>]*>\s*(?:<br[^>]*>| |\u00A0| )?\s*(:?<\/\2>)?\s*(?=$|<\/body>)/gi;r=function(){function a(c){return c.type==CKEDITOR.NODE_ELEMENT}function c(b,g){var d,e,f,h,k=[],m=g.range.startContainer;d=g.range.startPath();for(var m=n[m.getName()],l=0,q=b.getChildren(),r=q.count(),w=-1,p=-1,u=0,E=d.contains(n.$list);l<r;++l)d=q.getItem(l),a(d)?(f=d.getName(),E&&f in CKEDITOR.dtd.$list? -k=k.concat(c(d,g)):(h=!!m[f],"br"!=f||!d.data("cke-eol")||l&&l!=r-1||(u=(e=l?k[l-1].node:q.getItem(l+1))&&(!a(e)||!e.is("br")),e=e&&a(e)&&n.$block[e.getName()]),-1!=w||h||(w=l),h||(p=l),k.push({isElement:1,isLineBreak:u,isBlock:d.isBlockBoundary(),hasBlockSibling:e,node:d,name:f,allowed:h}),e=u=0)):k.push({isElement:0,node:d,allowed:1});-1<w&&(k[w].firstNotAllowed=1);-1<p&&(k[p].lastNotAllowed=1);return k}function g(c,b){var d=[],e=c.getChildren(),f=e.count(),h,k=0,m=n[b],l=!c.is(n.$inline)||c.is("br"); -for(l&&d.push(" ");k<f;k++)h=e.getItem(k),a(h)&&!h.is(m)?d=d.concat(g(h,b)):d.push(h);l&&d.push(" ");return d}function d(c){return a(c.startContainer)&&c.startContainer.getChild(c.startOffset-1)}function e(c){return c&&a(c)&&(c.is(n.$removeEmpty)||c.is("a")&&!c.isBlockBoundary())}function f(c,b,g,d){var e=c.clone(),h,k;e.setEndAt(b,CKEDITOR.POSITION_BEFORE_END);(h=(new CKEDITOR.dom.walker(e)).next())&&a(h)&&l[h.getName()]&&(k=h.getPrevious())&&a(k)&&!k.getParent().equals(c.startContainer)&&g.contains(k)&& -d.contains(h)&&h.isIdentical(k)&&(h.moveChildren(k),h.remove(),f(c,b,g,d))}function h(c,b){function g(c,b){if(b.isBlock&&b.isElement&&!b.node.is("br")&&a(c)&&c.is("br"))return c.remove(),1}var d=b.endContainer.getChild(b.endOffset),e=b.endContainer.getChild(b.endOffset-1);d&&g(d,c[c.length-1]);e&&g(e,c[0])&&(b.setEnd(b.endContainer,b.endOffset-1),b.collapse())}var n=CKEDITOR.dtd,l={p:1,div:1,h1:1,h2:1,h3:1,h4:1,h5:1,h6:1,ul:1,ol:1,li:1,pre:1,dl:1,blockquote:1},q={p:1,div:1,h1:1,h2:1,h3:1,h4:1,h5:1, -h6:1},r=CKEDITOR.tools.extend({},n.$inline);delete r.br;return function(l,C,w,p){var u=l.editor,x=!1;"unfiltered_html"==C&&(C="html",x=!0);if(!p.checkReadOnly()){var v=(new CKEDITOR.dom.elementPath(p.startContainer,p.root)).blockLimit||p.root;l={type:C,dontFilter:x,editable:l,editor:u,range:p,blockLimit:v,mergeCandidates:[],zombies:[]};C=l.range;p=l.mergeCandidates;var H,A;"text"==l.type&&C.shrink(CKEDITOR.SHRINK_ELEMENT,!0,!1)&&(H=CKEDITOR.dom.element.createFromHtml("\x3cspan\x3e\x26nbsp;\x3c/span\x3e", -C.document),C.insertNode(H),C.setStartAfter(H));x=new CKEDITOR.dom.elementPath(C.startContainer);l.endPath=v=new CKEDITOR.dom.elementPath(C.endContainer);if(!C.collapsed){var u=v.block||v.blockLimit,aa=C.getCommonAncestor();u&&!u.equals(aa)&&!u.contains(aa)&&C.checkEndOfBlock()&&l.zombies.push(u);C.deleteContents()}for(;(A=d(C))&&a(A)&&A.isBlockBoundary()&&x.contains(A);)C.moveToPosition(A,CKEDITOR.POSITION_BEFORE_END);f(C,l.blockLimit,x,v);H&&(C.setEndBefore(H),C.collapse(),H.remove());H=C.startPath(); -if(u=H.contains(e,!1,1))C.splitElement(u),l.inlineStylesRoot=u,l.inlineStylesPeak=H.lastElement;H=C.createBookmark();(u=H.startNode.getPrevious(k))&&a(u)&&e(u)&&p.push(u);(u=H.startNode.getNext(k))&&a(u)&&e(u)&&p.push(u);for(u=H.startNode;(u=u.getParent())&&e(u);)p.push(u);C.moveToBookmark(H);if(H=w){H=l.range;if("text"==l.type&&l.inlineStylesRoot){A=l.inlineStylesPeak;C=A.getDocument().createText("{cke-peak}");for(p=l.inlineStylesRoot.getParent();!A.equals(p);)C=C.appendTo(A.clone()),A=A.getParent(); -w=C.getOuterHtml().split("{cke-peak}").join(w)}A=l.blockLimit.getName();if(/^\s+|\s+$/.test(w)&&"span"in CKEDITOR.dtd[A]){var M='\x3cspan data-cke-marker\x3d"1"\x3e\x26nbsp;\x3c/span\x3e';w=M+w+M}w=l.editor.dataProcessor.toHtml(w,{context:null,fixForBody:!1,protectedWhitespaces:!!M,dontFilter:l.dontFilter,filter:l.editor.activeFilter,enterMode:l.editor.activeEnterMode});A=H.document.createElement("body");A.setHtml(w);M&&(A.getFirst().remove(),A.getLast().remove());if((M=H.startPath().block)&&(1!= -M.getChildCount()||!M.getBogus()))a:{var Q;if(1==A.getChildCount()&&a(Q=A.getFirst())&&Q.is(q)&&!Q.hasAttribute("contenteditable")){M=Q.getElementsByTag("*");H=0;for(p=M.count();H<p;H++)if(C=M.getItem(H),!C.is(r))break a;Q.moveChildren(Q.getParent(1));Q.remove()}}l.dataWrapper=A;H=w}if(H){Q=l.range;H=Q.document;var N;A=l.blockLimit;p=0;var V,M=[],T,P;w=u=0;var X,ca;C=Q.startContainer;var x=l.endPath.elements[0],W,v=x.getPosition(C),aa=!!x.getCommonAncestor(C)&&v!=CKEDITOR.POSITION_IDENTICAL&&!(v& -CKEDITOR.POSITION_CONTAINS+CKEDITOR.POSITION_IS_CONTAINED);C=c(l.dataWrapper,l);for(h(C,Q);p<C.length;p++){v=C[p];if(N=v.isLineBreak){N=Q;X=A;var ba=void 0,da=void 0;v.hasBlockSibling?N=1:(ba=N.startContainer.getAscendant(n.$block,1))&&ba.is({div:1,p:1})?(da=ba.getPosition(X),da==CKEDITOR.POSITION_IDENTICAL||da==CKEDITOR.POSITION_CONTAINS?N=0:(X=N.splitElement(ba),N.moveToPosition(X,CKEDITOR.POSITION_AFTER_START),N=1)):N=0}if(N)w=0<p;else{N=Q.startPath();!v.isBlock&&m(l.editor,N.block,N.blockLimit)&& -(P=b(l.editor))&&(P=H.createElement(P),P.appendBogus(),Q.insertNode(P),CKEDITOR.env.needsBrFiller&&(V=P.getBogus())&&V.remove(),Q.moveToPosition(P,CKEDITOR.POSITION_BEFORE_END));if((N=Q.startPath().block)&&!N.equals(T)){if(V=N.getBogus())V.remove(),M.push(N);T=N}v.firstNotAllowed&&(u=1);if(u&&v.isElement){N=Q.startContainer;for(X=null;N&&!n[N.getName()][v.name];){if(N.equals(A)){N=null;break}X=N;N=N.getParent()}if(N)X&&(ca=Q.splitElement(X),l.zombies.push(ca),l.zombies.push(X));else{X=A.getName(); -W=!p;N=p==C.length-1;X=g(v.node,X);for(var ba=[],da=X.length,ea=0,ga=void 0,ha=0,ia=-1;ea<da;ea++)ga=X[ea]," "==ga?(ha||W&&!ea||(ba.push(new CKEDITOR.dom.text(" ")),ia=ba.length),ha=1):(ba.push(ga),ha=0);N&&ia==ba.length&&ba.pop();W=ba}}if(W){for(;N=W.pop();)Q.insertNode(N);W=0}else Q.insertNode(v.node);v.lastNotAllowed&&p<C.length-1&&((ca=aa?x:ca)&&Q.setEndAt(ca,CKEDITOR.POSITION_AFTER_START),u=0);Q.collapse()}}1!=C.length?V=!1:(V=C[0],V=V.isElement&&"false"==V.node.getAttribute("contenteditable")); -V&&(w=!0,N=C[0].node,Q.setStartAt(N,CKEDITOR.POSITION_BEFORE_START),Q.setEndAt(N,CKEDITOR.POSITION_AFTER_END));l.dontMoveCaret=w;l.bogusNeededBlocks=M}V=l.range;var fa;ca=l.bogusNeededBlocks;for(W=V.createBookmark();T=l.zombies.pop();)T.getParent()&&(P=V.clone(),P.moveToElementEditStart(T),P.removeEmptyBlocksAtEnd());if(ca)for(;T=ca.pop();)CKEDITOR.env.needsBrFiller?T.appendBogus():T.append(V.document.createText(" "));for(;T=l.mergeCandidates.pop();)T.mergeSiblings();V.moveToBookmark(W);if(!l.dontMoveCaret){for(T= -d(V);T&&a(T)&&!T.is(n.$empty);){if(T.isBlockBoundary())V.moveToPosition(T,CKEDITOR.POSITION_BEFORE_END);else{if(e(T)&&T.getHtml().match(/(\s| )$/g)){fa=null;break}fa=V.clone();fa.moveToPosition(T,CKEDITOR.POSITION_BEFORE_END)}T=T.getLast(k)}fa&&V.moveToRange(fa)}}}}();q=function(){function a(c){c=new CKEDITOR.dom.walker(c);c.guard=function(a,c){if(c)return!1;if(a.type==CKEDITOR.NODE_ELEMENT)return a.is(CKEDITOR.dtd.$tableContent)};c.evaluator=function(a){return a.type==CKEDITOR.NODE_ELEMENT}; -return c}function c(a,b,g){b=a.getDocument().createElement(b);a.append(b,g);return b}function b(a){var c=a.count(),g;for(c;0<c--;)g=a.getItem(c),CKEDITOR.tools.trim(g.getHtml())||(g.appendBogus(),CKEDITOR.env.ie&&9>CKEDITOR.env.version&&g.getChildCount()&&g.getFirst().remove())}return function(g){var d=g.startContainer,e=d.getAscendant("table",1),f=!1;b(e.getElementsByTag("td"));b(e.getElementsByTag("th"));e=g.clone();e.setStart(d,0);e=a(e).lastBackward();e||(e=g.clone(),e.setEndAt(d,CKEDITOR.POSITION_BEFORE_END), -e=a(e).lastForward(),f=!0);e||(e=d);e.is("table")?(g.setStartAt(e,CKEDITOR.POSITION_BEFORE_START),g.collapse(!0),e.remove()):(e.is({tbody:1,thead:1,tfoot:1})&&(e=c(e,"tr",f)),e.is("tr")&&(e=c(e,e.getParent().is("thead")?"th":"td",f)),(d=e.getBogus())&&d.remove(),g.moveToPosition(e,f?CKEDITOR.POSITION_AFTER_START:CKEDITOR.POSITION_BEFORE_END))}}();u=function(){function a(c){c=new CKEDITOR.dom.walker(c);c.guard=function(a,c){if(c)return!1;if(a.type==CKEDITOR.NODE_ELEMENT)return a.is(CKEDITOR.dtd.$list)|| -a.is(CKEDITOR.dtd.$listItem)};c.evaluator=function(a){return a.type==CKEDITOR.NODE_ELEMENT&&a.is(CKEDITOR.dtd.$listItem)};return c}return function(c){var b=c.startContainer,g=!1,d;d=c.clone();d.setStart(b,0);d=a(d).lastBackward();d||(d=c.clone(),d.setEndAt(b,CKEDITOR.POSITION_BEFORE_END),d=a(d).lastForward(),g=!0);d||(d=b);d.is(CKEDITOR.dtd.$list)?(c.setStartAt(d,CKEDITOR.POSITION_BEFORE_START),c.collapse(!0),d.remove()):((b=d.getBogus())&&b.remove(),c.moveToPosition(d,g?CKEDITOR.POSITION_AFTER_START: -CKEDITOR.POSITION_BEFORE_END),c.select())}}();x={eol:{detect:function(a,c){var b=a.range,g=b.clone(),d=b.clone(),e=new CKEDITOR.dom.elementPath(b.startContainer,c),f=new CKEDITOR.dom.elementPath(b.endContainer,c);g.collapse(1);d.collapse();e.block&&g.checkBoundaryOfElement(e.block,CKEDITOR.END)&&(b.setStartAfter(e.block),a.prependEolBr=1);f.block&&d.checkBoundaryOfElement(f.block,CKEDITOR.START)&&(b.setEndBefore(f.block),a.appendEolBr=1)},fix:function(a,c){var b=c.getDocument(),g;a.appendEolBr&&(g= -this.createEolBr(b),a.fragment.append(g));!a.prependEolBr||g&&!g.getPrevious()||a.fragment.append(this.createEolBr(b),1)},createEolBr:function(a){return a.createElement("br",{attributes:{"data-cke-eol":1}})}},bogus:{exclude:function(a){var c=a.range.getBoundaryNodes(),b=c.startNode,c=c.endNode;!c||!v(c)||b&&b.equals(c)||a.range.setEndBefore(c)}},tree:{rebuild:function(a,c){var b=a.range,g=b.getCommonAncestor(),d=new CKEDITOR.dom.elementPath(g,c),e=new CKEDITOR.dom.elementPath(b.startContainer,c), -b=new CKEDITOR.dom.elementPath(b.endContainer,c),f;g.type==CKEDITOR.NODE_TEXT&&(g=g.getParent());if(d.blockLimit.is({tr:1,table:1})){var h=d.contains("table").getParent();f=function(a){return!a.equals(h)}}else if(d.block&&d.block.is(CKEDITOR.dtd.$listItem)&&(e=e.contains(CKEDITOR.dtd.$list),b=b.contains(CKEDITOR.dtd.$list),!e.equals(b))){var k=d.contains(CKEDITOR.dtd.$list).getParent();f=function(a){return!a.equals(k)}}f||(f=function(a){return!a.equals(d.block)&&!a.equals(d.blockLimit)});this.rebuildFragment(a, -c,g,f)},rebuildFragment:function(a,c,b,g){for(var d;b&&!b.equals(c)&&g(b);)d=b.clone(0,1),a.fragment.appendTo(d),a.fragment=d,b=b.getParent()}},cell:{shrink:function(a){a=a.range;var c=a.startContainer,b=a.endContainer,g=a.startOffset,d=a.endOffset;c.type==CKEDITOR.NODE_ELEMENT&&c.equals(b)&&c.is("tr")&&++g==d&&a.shrink(CKEDITOR.SHRINK_TEXT)}}};A=function(){function a(c,b){var g=c.getParent();if(g.is(CKEDITOR.dtd.$inline))c[b?"insertBefore":"insertAfter"](g)}function c(b,g,d){a(g);a(d,1);for(var e;e= -d.getNext();)e.insertAfter(g),g=e;w(b)&&b.remove()}function g(a,c){var b=new CKEDITOR.dom.range(a);b.setStartAfter(c.startNode);b.setEndBefore(c.endNode);return b}return{list:{detectMerge:function(a,c){var b=g(c,a.bookmark),d=b.startPath(),e=b.endPath(),f=d.contains(CKEDITOR.dtd.$list),h=e.contains(CKEDITOR.dtd.$list);a.mergeList=f&&h&&f.getParent().equals(h.getParent())&&!f.equals(h);a.mergeListItems=d.block&&e.block&&d.block.is(CKEDITOR.dtd.$listItem)&&e.block.is(CKEDITOR.dtd.$listItem);if(a.mergeList|| -a.mergeListItems)b=b.clone(),b.setStartBefore(a.bookmark.startNode),b.setEndAfter(a.bookmark.endNode),a.mergeListBookmark=b.createBookmark()},merge:function(a,b){if(a.mergeListBookmark){var g=a.mergeListBookmark.startNode,d=a.mergeListBookmark.endNode,e=new CKEDITOR.dom.elementPath(g,b),f=new CKEDITOR.dom.elementPath(d,b);if(a.mergeList){var h=e.contains(CKEDITOR.dtd.$list),k=f.contains(CKEDITOR.dtd.$list);h.equals(k)||(k.moveChildren(h),k.remove())}a.mergeListItems&&(e=e.contains(CKEDITOR.dtd.$listItem), -f=f.contains(CKEDITOR.dtd.$listItem),e.equals(f)||c(f,g,d));g.remove();d.remove()}}},block:{detectMerge:function(a,c){if(!a.tableContentsRanges&&!a.mergeListBookmark){var b=new CKEDITOR.dom.range(c);b.setStartBefore(a.bookmark.startNode);b.setEndAfter(a.bookmark.endNode);a.mergeBlockBookmark=b.createBookmark()}},merge:function(a,b){if(a.mergeBlockBookmark&&!a.purgeTableBookmark){var g=a.mergeBlockBookmark.startNode,d=a.mergeBlockBookmark.endNode,e=new CKEDITOR.dom.elementPath(g,b),f=new CKEDITOR.dom.elementPath(d, -b),e=e.block,f=f.block;e&&f&&!e.equals(f)&&c(f,g,d);g.remove();d.remove()}}},table:function(){function a(g){var d=[],e,f=new CKEDITOR.dom.walker(g),h=g.startPath().contains(b),k=g.endPath().contains(b),n={};f.guard=function(a,f){if(a.type==CKEDITOR.NODE_ELEMENT){var l="visited_"+(f?"out":"in");if(a.getCustomData(l))return;CKEDITOR.dom.element.setMarker(n,a,l,1)}if(f&&h&&a.equals(h))e=g.clone(),e.setEndAt(h,CKEDITOR.POSITION_BEFORE_END),d.push(e);else if(!f&&k&&a.equals(k))e=g.clone(),e.setStartAt(k, -CKEDITOR.POSITION_AFTER_START),d.push(e);else{if(l=!f)l=a.type==CKEDITOR.NODE_ELEMENT&&a.is(b)&&(!h||c(a,h))&&(!k||c(a,k));if(!l&&(l=f))if(a.is(b))var l=h&&h.getAscendant("table",!0),m=k&&k.getAscendant("table",!0),q=a.getAscendant("table",!0),l=l&&l.contains(q)||m&&m.contains(q);else l=void 0;l&&(e=g.clone(),e.selectNodeContents(a),d.push(e))}};f.lastForward();CKEDITOR.dom.element.clearAllMarkers(n);return d}function c(a,b){var g=CKEDITOR.POSITION_CONTAINS+CKEDITOR.POSITION_IS_CONTAINED,d=a.getPosition(b); -return d===CKEDITOR.POSITION_IDENTICAL?!1:0===(d&g)}var b={td:1,th:1,caption:1};return{detectPurge:function(a){var c=a.range,g=c.clone();g.enlarge(CKEDITOR.ENLARGE_ELEMENT);var g=new CKEDITOR.dom.walker(g),d=0;g.evaluator=function(a){a.type==CKEDITOR.NODE_ELEMENT&&a.is(b)&&++d};g.checkForward();if(1<d){var g=c.startPath().contains("table"),e=c.endPath().contains("table");g&&e&&c.checkBoundaryOfElement(g,CKEDITOR.START)&&c.checkBoundaryOfElement(e,CKEDITOR.END)&&(c=a.range.clone(),c.setStartBefore(g), -c.setEndAfter(e),a.purgeTableBookmark=c.createBookmark())}},detectRanges:function(d,e){var f=g(e,d.bookmark),h=f.clone(),k,n,l=f.getCommonAncestor();l.is(CKEDITOR.dtd.$tableContent)&&!l.is(b)&&(l=l.getAscendant("table",!0));n=l;l=new CKEDITOR.dom.elementPath(f.startContainer,n);n=new CKEDITOR.dom.elementPath(f.endContainer,n);l=l.contains("table");n=n.contains("table");if(l||n)l&&n&&c(l,n)?(d.tableSurroundingRange=h,h.setStartAt(l,CKEDITOR.POSITION_AFTER_END),h.setEndAt(n,CKEDITOR.POSITION_BEFORE_START), -h=f.clone(),h.setEndAt(l,CKEDITOR.POSITION_AFTER_END),k=f.clone(),k.setStartAt(n,CKEDITOR.POSITION_BEFORE_START),k=a(h).concat(a(k))):l?n||(d.tableSurroundingRange=h,h.setStartAt(l,CKEDITOR.POSITION_AFTER_END),f.setEndAt(l,CKEDITOR.POSITION_AFTER_END)):(d.tableSurroundingRange=h,h.setEndAt(n,CKEDITOR.POSITION_BEFORE_START),f.setStartAt(n,CKEDITOR.POSITION_AFTER_START)),d.tableContentsRanges=k?k:a(f)},deleteRanges:function(a){for(var c;c=a.tableContentsRanges.pop();)c.extractContents(),w(c.startContainer)&& +"true":"1"),a.setAttribute("contentEditable",!1))});c.on("selectionChange",function(a){if(!c.readOnly){var b=c.getSelection();b&&!b.isLocked&&(b=c.checkDirty(),c.fire("lockSnapshot"),f(a),c.fire("unlockSnapshot"),!b&&c.resetDirty())}})});CKEDITOR.on("instanceCreated",function(a){var c=a.editor;c.on("mode",function(){var a=c.editable();if(a&&a.isInline()){var b=c.title;a.changeAttr("role","textbox");a.changeAttr("aria-multiline","true");a.changeAttr("aria-label",b);b&&a.changeAttr("title",b);var d= +c.fire("ariaEditorHelpLabel",{}).label;if(d&&(b=this.ui.space(this.elementMode==CKEDITOR.ELEMENT_MODE_INLINE?"top":"contents"))){var g=CKEDITOR.tools.getNextId(),d=CKEDITOR.dom.element.createFromHtml('\x3cspan id\x3d"'+g+'" class\x3d"cke_voice_label"\x3e'+d+"\x3c/span\x3e");b.append(d);a.changeAttr("aria-describedby",g)}}})});CKEDITOR.addCss(".cke_editable{cursor:text}.cke_editable img,.cke_editable input,.cke_editable textarea{cursor:default}");a=CKEDITOR.dom.walker.whitespaces(!0);n=CKEDITOR.dom.walker.bookmark(!1, +!0);w=CKEDITOR.dom.walker.empty();v=CKEDITOR.dom.walker.bogus();t=/(^|<body\b[^>]*>)\s*<(p|div|address|h\d|center|pre)[^>]*>\s*(?:<br[^>]*>| |\u00A0| )?\s*(:?<\/\2>)?\s*(?=$|<\/body>)/gi;p=function(){function a(c){return c.type==CKEDITOR.NODE_ELEMENT}function c(b,d){var g,e,f,h,k=[],l=d.range.startContainer;g=d.range.startPath();for(var l=n[l.getName()],m=0,q=b.getChildren(),p=q.count(),w=-1,t=-1,r=0,F=g.contains(n.$list);m<p;++m)g=q.getItem(m),a(g)?(f=g.getName(),F&&f in CKEDITOR.dtd.$list? +k=k.concat(c(g,d)):(h=!!l[f],"br"!=f||!g.data("cke-eol")||m&&m!=p-1||(r=(e=m?k[m-1].node:q.getItem(m+1))&&(!a(e)||!e.is("br")),e=e&&a(e)&&n.$block[e.getName()]),-1!=w||h||(w=m),h||(t=m),k.push({isElement:1,isLineBreak:r,isBlock:g.isBlockBoundary(),hasBlockSibling:e,node:g,name:f,allowed:h}),e=r=0)):k.push({isElement:0,node:g,allowed:1});-1<w&&(k[w].firstNotAllowed=1);-1<t&&(k[t].lastNotAllowed=1);return k}function d(c,b){var g=[],e=c.getChildren(),f=e.count(),h,k=0,m=n[b],l=!c.is(n.$inline)||c.is("br"); +for(l&&g.push(" ");k<f;k++)h=e.getItem(k),a(h)&&!h.is(m)?g=g.concat(d(h,b)):g.push(h);l&&g.push(" ");return g}function g(c){return a(c.startContainer)&&c.startContainer.getChild(c.startOffset-1)}function e(c){return c&&a(c)&&(c.is(n.$removeEmpty)||c.is("a")&&!c.isBlockBoundary())}function f(c,b,d,g){var e=c.clone(),h,k;e.setEndAt(b,CKEDITOR.POSITION_BEFORE_END);(h=(new CKEDITOR.dom.walker(e)).next())&&a(h)&&l[h.getName()]&&(k=h.getPrevious())&&a(k)&&!k.getParent().equals(c.startContainer)&&d.contains(k)&& +g.contains(h)&&h.isIdentical(k)&&(h.moveChildren(k),h.remove(),f(c,b,d,g))}function h(c,b){function d(c,b){if(b.isBlock&&b.isElement&&!b.node.is("br")&&a(c)&&c.is("br"))return c.remove(),1}var g=b.endContainer.getChild(b.endOffset),e=b.endContainer.getChild(b.endOffset-1);g&&d(g,c[c.length-1]);e&&d(e,c[0])&&(b.setEnd(b.endContainer,b.endOffset-1),b.collapse())}var n=CKEDITOR.dtd,l={p:1,div:1,h1:1,h2:1,h3:1,h4:1,h5:1,h6:1,ul:1,ol:1,li:1,pre:1,dl:1,blockquote:1},q={p:1,div:1,h1:1,h2:1,h3:1,h4:1,h5:1, +h6:1},p=CKEDITOR.tools.extend({},n.$inline);delete p.br;return function(l,D,w,t){var r=l.editor,A=!1;"unfiltered_html"==D&&(D="html",A=!0);if(!t.checkReadOnly()){var H=(new CKEDITOR.dom.elementPath(t.startContainer,t.root)).blockLimit||t.root;l={type:D,dontFilter:A,editable:l,editor:r,range:t,blockLimit:H,mergeCandidates:[],zombies:[]};D=l.range;t=l.mergeCandidates;var v,C;"text"==l.type&&D.shrink(CKEDITOR.SHRINK_ELEMENT,!0,!1)&&(v=CKEDITOR.dom.element.createFromHtml("\x3cspan\x3e\x26nbsp;\x3c/span\x3e", +D.document),D.insertNode(v),D.setStartAfter(v));A=new CKEDITOR.dom.elementPath(D.startContainer);l.endPath=H=new CKEDITOR.dom.elementPath(D.endContainer);if(!D.collapsed){var r=H.block||H.blockLimit,Z=D.getCommonAncestor();r&&!r.equals(Z)&&!r.contains(Z)&&D.checkEndOfBlock()&&l.zombies.push(r);D.deleteContents()}for(;(C=g(D))&&a(C)&&C.isBlockBoundary()&&A.contains(C);)D.moveToPosition(C,CKEDITOR.POSITION_BEFORE_END);f(D,l.blockLimit,A,H);v&&(D.setEndBefore(v),D.collapse(),v.remove());v=D.startPath(); +if(r=v.contains(e,!1,1))D.splitElement(r),l.inlineStylesRoot=r,l.inlineStylesPeak=v.lastElement;v=D.createBookmark();(r=v.startNode.getPrevious(k))&&a(r)&&e(r)&&t.push(r);(r=v.startNode.getNext(k))&&a(r)&&e(r)&&t.push(r);for(r=v.startNode;(r=r.getParent())&&e(r);)t.push(r);D.moveToBookmark(v);if(v=w){v=l.range;if("text"==l.type&&l.inlineStylesRoot){C=l.inlineStylesPeak;D=C.getDocument().createText("{cke-peak}");for(t=l.inlineStylesRoot.getParent();!C.equals(t);)D=D.appendTo(C.clone()),C=C.getParent(); +w=D.getOuterHtml().split("{cke-peak}").join(w)}C=l.blockLimit.getName();if(/^\s+|\s+$/.test(w)&&"span"in CKEDITOR.dtd[C]){var M='\x3cspan data-cke-marker\x3d"1"\x3e\x26nbsp;\x3c/span\x3e';w=M+w+M}w=l.editor.dataProcessor.toHtml(w,{context:null,fixForBody:!1,protectedWhitespaces:!!M,dontFilter:l.dontFilter,filter:l.editor.activeFilter,enterMode:l.editor.activeEnterMode});C=v.document.createElement("body");C.setHtml(w);M&&(C.getFirst().remove(),C.getLast().remove());if((M=v.startPath().block)&&(1!= +M.getChildCount()||!M.getBogus()))a:{var Q;if(1==C.getChildCount()&&a(Q=C.getFirst())&&Q.is(q)&&!Q.hasAttribute("contenteditable")){M=Q.getElementsByTag("*");v=0;for(t=M.count();v<t;v++)if(D=M.getItem(v),!D.is(p))break a;Q.moveChildren(Q.getParent(1));Q.remove()}}l.dataWrapper=C;v=w}if(v){Q=l.range;v=Q.document;var N;C=l.blockLimit;t=0;var V,M=[],T,P;w=r=0;var W,ba;D=Q.startContainer;var A=l.endPath.elements[0],ca,H=A.getPosition(D),Z=!!A.getCommonAncestor(D)&&H!=CKEDITOR.POSITION_IDENTICAL&&!(H& +CKEDITOR.POSITION_CONTAINS+CKEDITOR.POSITION_IS_CONTAINED);D=c(l.dataWrapper,l);for(h(D,Q);t<D.length;t++){H=D[t];if(N=H.isLineBreak){N=Q;W=C;var aa=void 0,da=void 0;H.hasBlockSibling?N=1:(aa=N.startContainer.getAscendant(n.$block,1))&&aa.is({div:1,p:1})?(da=aa.getPosition(W),da==CKEDITOR.POSITION_IDENTICAL||da==CKEDITOR.POSITION_CONTAINS?N=0:(W=N.splitElement(aa),N.moveToPosition(W,CKEDITOR.POSITION_AFTER_START),N=1)):N=0}if(N)w=0<t;else{N=Q.startPath();!H.isBlock&&m(l.editor,N.block,N.blockLimit)&& +(P=b(l.editor))&&(P=v.createElement(P),P.appendBogus(),Q.insertNode(P),CKEDITOR.env.needsBrFiller&&(V=P.getBogus())&&V.remove(),Q.moveToPosition(P,CKEDITOR.POSITION_BEFORE_END));if((N=Q.startPath().block)&&!N.equals(T)){if(V=N.getBogus())V.remove(),M.push(N);T=N}H.firstNotAllowed&&(r=1);if(r&&H.isElement){N=Q.startContainer;for(W=null;N&&!n[N.getName()][H.name];){if(N.equals(C)){N=null;break}W=N;N=N.getParent()}if(N)W&&(ba=Q.splitElement(W),l.zombies.push(ba),l.zombies.push(W));else{W=C.getName(); +ca=!t;N=t==D.length-1;W=d(H.node,W);for(var aa=[],da=W.length,ea=0,ha=void 0,ia=0,fa=-1;ea<da;ea++)ha=W[ea]," "==ha?(ia||ca&&!ea||(aa.push(new CKEDITOR.dom.text(" ")),fa=aa.length),ia=1):(aa.push(ha),ia=0);N&&fa==aa.length&&aa.pop();ca=aa}}if(ca){for(;N=ca.pop();)Q.insertNode(N);ca=0}else Q.insertNode(H.node);H.lastNotAllowed&&t<D.length-1&&((ba=Z?A:ba)&&Q.setEndAt(ba,CKEDITOR.POSITION_AFTER_START),r=0);Q.collapse()}}1!=D.length?V=!1:(V=D[0],V=V.isElement&&"false"==V.node.getAttribute("contenteditable")); +V&&(w=!0,N=D[0].node,Q.setStartAt(N,CKEDITOR.POSITION_BEFORE_START),Q.setEndAt(N,CKEDITOR.POSITION_AFTER_END));l.dontMoveCaret=w;l.bogusNeededBlocks=M}V=l.range;var ga;ba=l.bogusNeededBlocks;for(ca=V.createBookmark();T=l.zombies.pop();)T.getParent()&&(P=V.clone(),P.moveToElementEditStart(T),P.removeEmptyBlocksAtEnd());if(ba)for(;T=ba.pop();)CKEDITOR.env.needsBrFiller?T.appendBogus():T.append(V.document.createText(" "));for(;T=l.mergeCandidates.pop();)T.mergeSiblings();V.moveToBookmark(ca);if(!l.dontMoveCaret){for(T= +g(V);T&&a(T)&&!T.is(n.$empty);){if(T.isBlockBoundary())V.moveToPosition(T,CKEDITOR.POSITION_BEFORE_END);else{if(e(T)&&T.getHtml().match(/(\s| )$/g)){ga=null;break}ga=V.clone();ga.moveToPosition(T,CKEDITOR.POSITION_BEFORE_END)}T=T.getLast(k)}ga&&V.moveToRange(ga)}}}}();q=function(){function a(c){c=new CKEDITOR.dom.walker(c);c.guard=function(a,c){if(c)return!1;if(a.type==CKEDITOR.NODE_ELEMENT)return a.is(CKEDITOR.dtd.$tableContent)};c.evaluator=function(a){return a.type==CKEDITOR.NODE_ELEMENT}; +return c}function c(a,b,d){b=a.getDocument().createElement(b);a.append(b,d);return b}function b(a){var c=a.count(),d;for(c;0<c--;)d=a.getItem(c),CKEDITOR.tools.trim(d.getHtml())||(d.appendBogus(),CKEDITOR.env.ie&&9>CKEDITOR.env.version&&d.getChildCount()&&d.getFirst().remove())}return function(d){var g=d.startContainer,e=g.getAscendant("table",1),f=!1;b(e.getElementsByTag("td"));b(e.getElementsByTag("th"));e=d.clone();e.setStart(g,0);e=a(e).lastBackward();e||(e=d.clone(),e.setEndAt(g,CKEDITOR.POSITION_BEFORE_END), +e=a(e).lastForward(),f=!0);e||(e=g);e.is("table")?(d.setStartAt(e,CKEDITOR.POSITION_BEFORE_START),d.collapse(!0),e.remove()):(e.is({tbody:1,thead:1,tfoot:1})&&(e=c(e,"tr",f)),e.is("tr")&&(e=c(e,e.getParent().is("thead")?"th":"td",f)),(g=e.getBogus())&&g.remove(),d.moveToPosition(e,f?CKEDITOR.POSITION_AFTER_START:CKEDITOR.POSITION_BEFORE_END))}}();A=function(){function a(c){c=new CKEDITOR.dom.walker(c);c.guard=function(a,c){if(c)return!1;if(a.type==CKEDITOR.NODE_ELEMENT)return a.is(CKEDITOR.dtd.$list)|| +a.is(CKEDITOR.dtd.$listItem)};c.evaluator=function(a){return a.type==CKEDITOR.NODE_ELEMENT&&a.is(CKEDITOR.dtd.$listItem)};return c}return function(c){var b=c.startContainer,d=!1,g;g=c.clone();g.setStart(b,0);g=a(g).lastBackward();g||(g=c.clone(),g.setEndAt(b,CKEDITOR.POSITION_BEFORE_END),g=a(g).lastForward(),d=!0);g||(g=b);g.is(CKEDITOR.dtd.$list)?(c.setStartAt(g,CKEDITOR.POSITION_BEFORE_START),c.collapse(!0),g.remove()):((b=g.getBogus())&&b.remove(),c.moveToPosition(g,d?CKEDITOR.POSITION_AFTER_START: +CKEDITOR.POSITION_BEFORE_END),c.select())}}();r={eol:{detect:function(a,c){var b=a.range,d=b.clone(),g=b.clone(),e=new CKEDITOR.dom.elementPath(b.startContainer,c),f=new CKEDITOR.dom.elementPath(b.endContainer,c);d.collapse(1);g.collapse();e.block&&d.checkBoundaryOfElement(e.block,CKEDITOR.END)&&(b.setStartAfter(e.block),a.prependEolBr=1);f.block&&g.checkBoundaryOfElement(f.block,CKEDITOR.START)&&(b.setEndBefore(f.block),a.appendEolBr=1)},fix:function(a,c){var b=c.getDocument(),d;a.appendEolBr&&(d= +this.createEolBr(b),a.fragment.append(d));!a.prependEolBr||d&&!d.getPrevious()||a.fragment.append(this.createEolBr(b),1)},createEolBr:function(a){return a.createElement("br",{attributes:{"data-cke-eol":1}})}},bogus:{exclude:function(a){var c=a.range.getBoundaryNodes(),b=c.startNode,c=c.endNode;!c||!v(c)||b&&b.equals(c)||a.range.setEndBefore(c)}},tree:{rebuild:function(a,c){var b=a.range,d=b.getCommonAncestor(),g=new CKEDITOR.dom.elementPath(d,c),e=new CKEDITOR.dom.elementPath(b.startContainer,c), +b=new CKEDITOR.dom.elementPath(b.endContainer,c),f;d.type==CKEDITOR.NODE_TEXT&&(d=d.getParent());if(g.blockLimit.is({tr:1,table:1})){var h=g.contains("table").getParent();f=function(a){return!a.equals(h)}}else if(g.block&&g.block.is(CKEDITOR.dtd.$listItem)&&(e=e.contains(CKEDITOR.dtd.$list),b=b.contains(CKEDITOR.dtd.$list),!e.equals(b))){var k=g.contains(CKEDITOR.dtd.$list).getParent();f=function(a){return!a.equals(k)}}f||(f=function(a){return!a.equals(g.block)&&!a.equals(g.blockLimit)});this.rebuildFragment(a, +c,d,f)},rebuildFragment:function(a,c,b,d){for(var g;b&&!b.equals(c)&&d(b);)g=b.clone(0,1),a.fragment.appendTo(g),a.fragment=g,b=b.getParent()}},cell:{shrink:function(a){a=a.range;var c=a.startContainer,b=a.endContainer,d=a.startOffset,g=a.endOffset;c.type==CKEDITOR.NODE_ELEMENT&&c.equals(b)&&c.is("tr")&&++d==g&&a.shrink(CKEDITOR.SHRINK_TEXT)}}};C=function(){function a(c,b){var d=c.getParent();if(d.is(CKEDITOR.dtd.$inline))c[b?"insertBefore":"insertAfter"](d)}function c(b,d,g){a(d);a(g,1);for(var e;e= +g.getNext();)e.insertAfter(d),d=e;w(b)&&b.remove()}function d(a,c){var b=new CKEDITOR.dom.range(a);b.setStartAfter(c.startNode);b.setEndBefore(c.endNode);return b}return{list:{detectMerge:function(a,c){var b=d(c,a.bookmark),g=b.startPath(),e=b.endPath(),f=g.contains(CKEDITOR.dtd.$list),h=e.contains(CKEDITOR.dtd.$list);a.mergeList=f&&h&&f.getParent().equals(h.getParent())&&!f.equals(h);a.mergeListItems=g.block&&e.block&&g.block.is(CKEDITOR.dtd.$listItem)&&e.block.is(CKEDITOR.dtd.$listItem);if(a.mergeList|| +a.mergeListItems)b=b.clone(),b.setStartBefore(a.bookmark.startNode),b.setEndAfter(a.bookmark.endNode),a.mergeListBookmark=b.createBookmark()},merge:function(a,b){if(a.mergeListBookmark){var d=a.mergeListBookmark.startNode,g=a.mergeListBookmark.endNode,e=new CKEDITOR.dom.elementPath(d,b),f=new CKEDITOR.dom.elementPath(g,b);if(a.mergeList){var h=e.contains(CKEDITOR.dtd.$list),k=f.contains(CKEDITOR.dtd.$list);h.equals(k)||(k.moveChildren(h),k.remove())}a.mergeListItems&&(e=e.contains(CKEDITOR.dtd.$listItem), +f=f.contains(CKEDITOR.dtd.$listItem),e.equals(f)||c(f,d,g));d.remove();g.remove()}}},block:{detectMerge:function(a,c){if(!a.tableContentsRanges&&!a.mergeListBookmark){var b=new CKEDITOR.dom.range(c);b.setStartBefore(a.bookmark.startNode);b.setEndAfter(a.bookmark.endNode);a.mergeBlockBookmark=b.createBookmark()}},merge:function(a,b){if(a.mergeBlockBookmark&&!a.purgeTableBookmark){var d=a.mergeBlockBookmark.startNode,g=a.mergeBlockBookmark.endNode,e=new CKEDITOR.dom.elementPath(d,b),f=new CKEDITOR.dom.elementPath(g, +b),e=e.block,f=f.block;e&&f&&!e.equals(f)&&c(f,d,g);d.remove();g.remove()}}},table:function(){function a(d){var g=[],e,f=new CKEDITOR.dom.walker(d),h=d.startPath().contains(b),k=d.endPath().contains(b),n={};f.guard=function(a,f){if(a.type==CKEDITOR.NODE_ELEMENT){var l="visited_"+(f?"out":"in");if(a.getCustomData(l))return;CKEDITOR.dom.element.setMarker(n,a,l,1)}if(f&&h&&a.equals(h))e=d.clone(),e.setEndAt(h,CKEDITOR.POSITION_BEFORE_END),g.push(e);else if(!f&&k&&a.equals(k))e=d.clone(),e.setStartAt(k, +CKEDITOR.POSITION_AFTER_START),g.push(e);else{if(l=!f)l=a.type==CKEDITOR.NODE_ELEMENT&&a.is(b)&&(!h||c(a,h))&&(!k||c(a,k));if(!l&&(l=f))if(a.is(b))var l=h&&h.getAscendant("table",!0),m=k&&k.getAscendant("table",!0),q=a.getAscendant("table",!0),l=l&&l.contains(q)||m&&m.contains(q);else l=void 0;l&&(e=d.clone(),e.selectNodeContents(a),g.push(e))}};f.lastForward();CKEDITOR.dom.element.clearAllMarkers(n);return g}function c(a,b){var d=CKEDITOR.POSITION_CONTAINS+CKEDITOR.POSITION_IS_CONTAINED,g=a.getPosition(b); +return g===CKEDITOR.POSITION_IDENTICAL?!1:0===(g&d)}var b={td:1,th:1,caption:1};return{detectPurge:function(a){var c=a.range,d=c.clone();d.enlarge(CKEDITOR.ENLARGE_ELEMENT);var d=new CKEDITOR.dom.walker(d),g=0;d.evaluator=function(a){a.type==CKEDITOR.NODE_ELEMENT&&a.is(b)&&++g};d.checkForward();if(1<g){var d=c.startPath().contains("table"),e=c.endPath().contains("table");d&&e&&c.checkBoundaryOfElement(d,CKEDITOR.START)&&c.checkBoundaryOfElement(e,CKEDITOR.END)&&(c=a.range.clone(),c.setStartBefore(d), +c.setEndAfter(e),a.purgeTableBookmark=c.createBookmark())}},detectRanges:function(g,e){var f=d(e,g.bookmark),h=f.clone(),k,n,l=f.getCommonAncestor();l.is(CKEDITOR.dtd.$tableContent)&&!l.is(b)&&(l=l.getAscendant("table",!0));n=l;l=new CKEDITOR.dom.elementPath(f.startContainer,n);n=new CKEDITOR.dom.elementPath(f.endContainer,n);l=l.contains("table");n=n.contains("table");if(l||n)l&&n&&c(l,n)?(g.tableSurroundingRange=h,h.setStartAt(l,CKEDITOR.POSITION_AFTER_END),h.setEndAt(n,CKEDITOR.POSITION_BEFORE_START), +h=f.clone(),h.setEndAt(l,CKEDITOR.POSITION_AFTER_END),k=f.clone(),k.setStartAt(n,CKEDITOR.POSITION_BEFORE_START),k=a(h).concat(a(k))):l?n||(g.tableSurroundingRange=h,h.setStartAt(l,CKEDITOR.POSITION_AFTER_END),f.setEndAt(l,CKEDITOR.POSITION_AFTER_END)):(g.tableSurroundingRange=h,h.setEndAt(n,CKEDITOR.POSITION_BEFORE_START),f.setStartAt(n,CKEDITOR.POSITION_AFTER_START)),g.tableContentsRanges=k?k:a(f)},deleteRanges:function(a){for(var c;c=a.tableContentsRanges.pop();)c.extractContents(),w(c.startContainer)&& c.startContainer.appendBogus();a.tableSurroundingRange&&a.tableSurroundingRange.extractContents()},purge:function(a){if(a.purgeTableBookmark){var c=a.doc,b=a.range.clone(),c=c.createElement("p");c.insertBefore(a.purgeTableBookmark.startNode);b.moveToBookmark(a.purgeTableBookmark);b.deleteContents();a.range.moveToPosition(c,CKEDITOR.POSITION_AFTER_START)}}}}(),detectExtractMerge:function(a){return!(a.range.startPath().contains(CKEDITOR.dtd.$listItem)&&a.range.endPath().contains(CKEDITOR.dtd.$listItem))}, -fixUneditableRangePosition:function(a){a.startContainer.getDtd()["#"]||a.moveToClosestEditablePosition(null,!0)},autoParagraph:function(a,c){var g=c.startPath(),d;m(a,g.block,g.blockLimit)&&(d=b(a))&&(d=c.document.createElement(d),d.appendBogus(),c.insertNode(d),c.moveToPosition(d,CKEDITOR.POSITION_AFTER_START))}}}()}(),function(){function f(a){return CKEDITOR.plugins.widget&&CKEDITOR.plugins.widget.isDomWidget(a)}function h(a,c){if(0===a.length||f(a[0].getEnclosedNode()))return!1;var b,g;if((b=!c&& -1===a.length)&&!(b=a[0].collapsed)){var d=a[0];b=d.startContainer.getAscendant({td:1,th:1},!0);var e=d.endContainer.getAscendant({td:1,th:1},!0);g=CKEDITOR.tools.trim;b&&b.equals(e)&&!b.findOne("td, th, tr, tbody, table")?(d=d.cloneContents(),b=d.getFirst()?g(d.getFirst().getText())!==g(b.getText()):!0):b=!1}if(b)return!1;for(g=0;g<a.length;g++)if(b=a[g]._getTableElement(),!b)return!1;return!0}function e(a){function c(a){a=a.find("td, th");var b=[],g;for(g=0;g<a.count();g++)b.push(a.getItem(g));return b} -var b=[],g,d;for(d=0;d<a.length;d++)g=a[d]._getTableElement(),g.is&&g.is({td:1,th:1})?b.push(g):b=b.concat(c(g));return b}function k(a){a=e(a);var c="",b=[],g,d;for(d=0;d<a.length;d++)g&&!g.equals(a[d].getAscendant("tr"))?(c+=b.join("\t")+"\n",g=a[d].getAscendant("tr"),b=[]):0===d&&(g=a[d].getAscendant("tr")),b.push(a[d].getText());return c+=b.join("\t")}function d(a){var c=this.root.editor,b=c.getSelection(1);this.reset();D=!0;b.root.once("selectionchange",function(a){a.cancel()},null,null,0);b.selectRanges([a[0]]); -b=this._.cache;b.ranges=new CKEDITOR.dom.rangeList(a);b.type=CKEDITOR.SELECTION_TEXT;b.selectedElement=a[0]._getTableElement();b.selectedText=k(a);b.nativeSel=null;this.isFake=1;this.rev=u++;c._.fakeSelection=this;D=!1;this.root.fire("selectionchange")}function l(){var a=this._.fakeSelection,c;if(a){c=this.getSelection(1);var b;if(!(b=!c)&&(b=!c.isHidden())){b=a;var g=c.getRanges(),d=b.getRanges(),e=g.length&&g[0]._getTableElement()&&g[0]._getTableElement().getAscendant("table",!0),k=d.length&&d[0]._getTableElement()&& -d[0]._getTableElement().getAscendant("table",!0),n=1===g.length&&g[0]._getTableElement()&&g[0]._getTableElement().is("table"),l=1===d.length&&d[0]._getTableElement()&&d[0]._getTableElement().is("table");if(f(b.getSelectedElement()))b=!1;else{var m=1===g.length&&g[0].collapsed,d=h(g,!!CKEDITOR.env.webkit)&&h(d);e=e&&k?e.equals(k)||k.contains(e):!1;e&&(m||d)?(n&&!l&&b.selectRanges(g),b=!0):b=!1}b=!b}b&&(a.reset(),a=0)}if(!a&&(a=c||this.getSelection(1),!a||a.getType()==CKEDITOR.SELECTION_NONE))return; -this.fire("selectionCheck",a);c=this.elementPath();c.compare(this._.selectionPreviousPath)||(b=this._.selectionPreviousPath&&this._.selectionPreviousPath.blockLimit.equals(c.blockLimit),CKEDITOR.env.webkit&&!b&&(this._.previousActive=this.document.getActive()),this._.selectionPreviousPath=c,this.fire("selectionChange",{selection:a,path:c}))}function m(){B=!0;t||(b.call(this),t=CKEDITOR.tools.setTimeout(b,200,this))}function b(){t=null;B&&(CKEDITOR.tools.setTimeout(l,0,this),B=!1)}function g(a){return y(a)|| -a.type==CKEDITOR.NODE_ELEMENT&&!a.is(CKEDITOR.dtd.$empty)?!0:!1}function c(a){function c(b,g){return b&&b.type!=CKEDITOR.NODE_TEXT?a.clone()["moveToElementEdit"+(g?"End":"Start")](b):!1}if(!(a.root instanceof CKEDITOR.editable))return!1;var b=a.startContainer,d=a.getPreviousNode(g,null,b),e=a.getNextNode(g,null,b);return c(d)||c(e,1)||!(d||e||b.type==CKEDITOR.NODE_ELEMENT&&b.isBlockBoundary()&&b.getBogus())?!0:!1}function a(a){n(a,!1);var c=a.getDocument().createText(x);a.setCustomData("cke-fillingChar", -c);return c}function n(a,c){var b=a&&a.removeCustomData("cke-fillingChar");if(b){if(!1!==c){var g=a.getDocument().getSelection().getNative(),d=g&&"None"!=g.type&&g.getRangeAt(0),e=x.length;if(b.getLength()>e&&d&&d.intersectsNode(b.$)){var f=[{node:g.anchorNode,offset:g.anchorOffset},{node:g.focusNode,offset:g.focusOffset}];g.anchorNode==b.$&&g.anchorOffset>e&&(f[0].offset-=e);g.focusNode==b.$&&g.focusOffset>e&&(f[1].offset-=e)}}b.setText(w(b.getText(),1));f&&(b=a.getDocument().$,g=b.getSelection(), -b=b.createRange(),b.setStart(f[0].node,f[0].offset),b.collapse(!0),g.removeAllRanges(),g.addRange(b),g.extend(f[1].node,f[1].offset))}}function w(a,c){return c?a.replace(A,function(a,c){return c?" ":""}):a.replace(x,"")}function v(a,c){var b=c&&CKEDITOR.tools.htmlEncode(c)||"\x26nbsp;",b=CKEDITOR.dom.element.createFromHtml('\x3cdiv data-cke-hidden-sel\x3d"1" data-cke-temp\x3d"1" style\x3d"'+(CKEDITOR.env.ie&&14>CKEDITOR.env.version?"display:none":"position:fixed;top:0;left:-1000px")+'"\x3e'+b+"\x3c/div\x3e", -a.document);a.fire("lockSnapshot");a.editable().append(b);var g=a.getSelection(1),d=a.createRange(),e=g.root.on("selectionchange",function(a){a.cancel()},null,null,0);d.setStartAt(b,CKEDITOR.POSITION_AFTER_START);d.setEndAt(b,CKEDITOR.POSITION_BEFORE_END);g.selectRanges([d]);e.removeListener();a.fire("unlockSnapshot");a._.hiddenSelectionContainer=b}function p(a){var c={37:1,39:1,8:1,46:1};return function(b){var g=b.data.getKeystroke();if(c[g]){var d=a.getSelection().getRanges(),e=d[0];1==d.length&& -e.collapsed&&(g=e[38>g?"getPreviousEditableNode":"getNextEditableNode"]())&&g.type==CKEDITOR.NODE_ELEMENT&&"false"==g.getAttribute("contenteditable")&&(a.getSelection().fake(g),b.data.preventDefault(),b.cancel())}}}function r(a){for(var c=0;c<a.length;c++){var b=a[c];b.getCommonAncestor().isReadOnly()&&a.splice(c,1);if(!b.collapsed){if(b.startContainer.isReadOnly())for(var g=b.startContainer,d;g&&!((d=g.type==CKEDITOR.NODE_ELEMENT)&&g.is("body")||!g.isReadOnly());)d&&"false"==g.getAttribute("contentEditable")&& -b.setStartAfter(g),g=g.getParent();g=b.startContainer;d=b.endContainer;var e=b.startOffset,f=b.endOffset,h=b.clone();g&&g.type==CKEDITOR.NODE_TEXT&&(e>=g.getLength()?h.setStartAfter(g):h.setStartBefore(g));d&&d.type==CKEDITOR.NODE_TEXT&&(f?h.setEndAfter(d):h.setEndBefore(d));g=new CKEDITOR.dom.walker(h);g.evaluator=function(g){if(g.type==CKEDITOR.NODE_ELEMENT&&g.isReadOnly()){var d=b.clone();b.setEndBefore(g);b.collapsed&&a.splice(c--,1);g.getPosition(h.endContainer)&CKEDITOR.POSITION_CONTAINS||(d.setStartAfter(g), -d.collapsed||a.splice(c+1,0,d));return!0}return!1};g.next()}}return a}var q="function"!=typeof window.getSelection,u=1,x=CKEDITOR.tools.repeat("",7),A=new RegExp(x+"( )?","g"),D,t,B,y=CKEDITOR.dom.walker.invisible(1),z=function(){function a(c){return function(a){var b=a.editor.createRange();b.moveToClosestEditablePosition(a.selected,c)&&a.editor.getSelection().selectRanges([b]);return!1}}function c(a){return function(c){var b=c.editor,g=b.createRange(),d;if(!b.readOnly)return(d=g.moveToClosestEditablePosition(c.selected, -a))||(d=g.moveToClosestEditablePosition(c.selected,!a)),d&&b.getSelection().selectRanges([g]),b.fire("saveSnapshot"),c.selected.remove(),d||(g.moveToElementEditablePosition(b.editable()),b.getSelection().selectRanges([g])),b.fire("saveSnapshot"),!1}}var b=a(),g=a(1);return{37:b,38:b,39:g,40:g,8:c(),46:c(1)}}();CKEDITOR.on("instanceCreated",function(a){function c(){var a=b.getSelection();a&&a.removeAllRanges()}var b=a.editor;b.on("contentDom",function(){function a(){u=new CKEDITOR.dom.selection(b.getSelection()); -u.lock()}function c(){e.removeListener("mouseup",c);k.removeListener("mouseup",c);var a=CKEDITOR.document.$.selection,b=a.createRange();"None"!=a.type&&b.parentElement()&&b.parentElement().ownerDocument==d.$&&b.select()}function g(a){if(CKEDITOR.env.ie){var c=(a=a.getRanges()[0])?a.startContainer.getAscendant(function(a){return a.type==CKEDITOR.NODE_ELEMENT&&("false"==a.getAttribute("contenteditable")||"true"==a.getAttribute("contenteditable"))},!0):null;return a&&"false"==c.getAttribute("contenteditable")&& -c}}var d=b.document,e=CKEDITOR.document,f=b.editable(),h=d.getBody(),k=d.getDocumentElement(),w=f.isInline(),r,u;CKEDITOR.env.gecko&&f.attachListener(f,"focus",function(a){a.removeListener();0!==r&&(a=b.getSelection().getNative())&&a.isCollapsed&&a.anchorNode==f.$&&(a=b.createRange(),a.moveToElementEditStart(f),a.select())},null,null,-2);f.attachListener(f,CKEDITOR.env.webkit?"DOMFocusIn":"focus",function(){r&&CKEDITOR.env.webkit&&(r=b._.previousActive&&b._.previousActive.equals(d.getActive()))&& -null!=b._.previousScrollTop&&b._.previousScrollTop!=f.$.scrollTop&&(f.$.scrollTop=b._.previousScrollTop);b.unlockSelection(r);r=0},null,null,-1);f.attachListener(f,"mousedown",function(){r=0});if(CKEDITOR.env.ie||w)q?f.attachListener(f,"beforedeactivate",a,null,null,-1):f.attachListener(b,"selectionCheck",a,null,null,-1),f.attachListener(f,CKEDITOR.env.webkit?"DOMFocusOut":"blur",function(){b.lockSelection(u);r=1},null,null,-1),f.attachListener(f,"mousedown",function(){r=0});if(CKEDITOR.env.ie&&!w){var t; -f.attachListener(f,"mousedown",function(a){2==a.data.$.button&&((a=b.document.getSelection())&&a.getType()!=CKEDITOR.SELECTION_NONE||(t=b.window.getScrollPosition()))});f.attachListener(f,"mouseup",function(a){2==a.data.$.button&&t&&(b.document.$.documentElement.scrollLeft=t.x,b.document.$.documentElement.scrollTop=t.y);t=null});if("BackCompat"!=d.$.compatMode){if(CKEDITOR.env.ie7Compat||CKEDITOR.env.ie6Compat){var x,v;k.on("mousedown",function(a){function c(a){a=a.data.$;if(x){var b=h.$.createTextRange(); -try{b.moveToPoint(a.clientX,a.clientY)}catch(g){}x.setEndPoint(0>v.compareEndPoints("StartToStart",b)?"EndToEnd":"StartToStart",b);x.select()}}function b(){k.removeListener("mousemove",c);e.removeListener("mouseup",b);k.removeListener("mouseup",b);x.select()}a=a.data;if(a.getTarget().is("html")&&a.$.y<k.$.clientHeight&&a.$.x<k.$.clientWidth){x=h.$.createTextRange();try{x.moveToPoint(a.$.clientX,a.$.clientY)}catch(g){}v=x.duplicate();k.on("mousemove",c);e.on("mouseup",b);k.on("mouseup",b)}})}if(7< -CKEDITOR.env.version&&11>CKEDITOR.env.version)k.on("mousedown",function(a){a.data.getTarget().is("html")&&(e.on("mouseup",c),k.on("mouseup",c))})}}f.attachListener(f,"selectionchange",l,b);f.attachListener(f,"keyup",m,b);f.attachListener(f,"keydown",function(a){var c=this.getSelection(1);g(c)&&(c.selectElement(g(c)),a.data.preventDefault())},b);f.attachListener(f,CKEDITOR.env.webkit?"DOMFocusIn":"focus",function(){b.forceNextSelectionCheck();b.selectionChange(1)});if(w&&(CKEDITOR.env.webkit||CKEDITOR.env.gecko)){var A; -f.attachListener(f,"mousedown",function(){A=1});f.attachListener(d.getDocumentElement(),"mouseup",function(){A&&m.call(b);A=0})}else f.attachListener(CKEDITOR.env.ie?f:d.getDocumentElement(),"mouseup",m,b);CKEDITOR.env.webkit&&f.attachListener(d,"keydown",function(a){switch(a.data.getKey()){case 13:case 33:case 34:case 35:case 36:case 37:case 39:case 8:case 45:case 46:f.hasFocus&&n(f)}},null,null,-1);f.attachListener(f,"keydown",p(b),null,null,-1)});b.on("setData",function(){b.unlockSelection();CKEDITOR.env.webkit&& -c()});b.on("contentDomUnload",function(){b.unlockSelection()});if(CKEDITOR.env.ie9Compat)b.on("beforeDestroy",c,null,null,9);b.on("dataReady",function(){delete b._.fakeSelection;delete b._.hiddenSelectionContainer;b.selectionChange(1)});b.on("loadSnapshot",function(){var a=CKEDITOR.dom.walker.nodeType(CKEDITOR.NODE_ELEMENT),c=b.editable().getLast(a);c&&c.hasAttribute("data-cke-hidden-sel")&&(c.remove(),CKEDITOR.env.gecko&&(a=b.editable().getFirst(a))&&a.is("br")&&a.getAttribute("_moz_editor_bogus_node")&& -a.remove())},null,null,100);b.on("key",function(a){if("wysiwyg"==b.mode){var c=b.getSelection();if(c.isFake){var g=z[a.data.keyCode];if(g)return g({editor:b,selected:c.getSelectedElement(),selection:c,keyEvent:a})}}})});if(CKEDITOR.env.webkit)CKEDITOR.on("instanceReady",function(a){var c=a.editor;c.on("selectionChange",function(){var a=c.editable(),b=a.getCustomData("cke-fillingChar");b&&(b.getCustomData("ready")?(n(a),a.editor.fire("selectionCheck")):b.setCustomData("ready",1))},null,null,-1);c.on("beforeSetMode", -function(){n(c.editable())},null,null,-1);c.on("getSnapshot",function(a){a.data&&(a.data=w(a.data))},c,null,20);c.on("toDataFormat",function(a){a.data.dataValue=w(a.data.dataValue)},null,null,0)});CKEDITOR.editor.prototype.selectionChange=function(a){(a?l:m).call(this)};CKEDITOR.editor.prototype.getSelection=function(a){return!this._.savedSelection&&!this._.fakeSelection||a?(a=this.editable())&&"wysiwyg"==this.mode?new CKEDITOR.dom.selection(a):null:this._.savedSelection||this._.fakeSelection};CKEDITOR.editor.prototype.lockSelection= -function(a){a=a||this.getSelection(1);return a.getType()!=CKEDITOR.SELECTION_NONE?(!a.isLocked&&a.lock(),this._.savedSelection=a,!0):!1};CKEDITOR.editor.prototype.unlockSelection=function(a){var c=this._.savedSelection;return c?(c.unlock(a),delete this._.savedSelection,!0):!1};CKEDITOR.editor.prototype.forceNextSelectionCheck=function(){delete this._.selectionPreviousPath};CKEDITOR.dom.document.prototype.getSelection=function(){return new CKEDITOR.dom.selection(this)};CKEDITOR.dom.range.prototype.select= -function(){var a=this.root instanceof CKEDITOR.editable?this.root.editor.getSelection():new CKEDITOR.dom.selection(this.root);a.selectRanges([this]);return a};CKEDITOR.SELECTION_NONE=1;CKEDITOR.SELECTION_TEXT=2;CKEDITOR.SELECTION_ELEMENT=3;CKEDITOR.dom.selection=function(a){if(a instanceof CKEDITOR.dom.selection){var c=a;a=a.root}var b=a instanceof CKEDITOR.dom.element;this.rev=c?c.rev:u++;this.document=a instanceof CKEDITOR.dom.document?a:a.getDocument();this.root=b?a:this.document.getBody();this.isLocked= -0;this._={cache:{}};if(c)return CKEDITOR.tools.extend(this._.cache,c._.cache),this.isFake=c.isFake,this.isLocked=c.isLocked,this;a=this.getNative();var g,d;if(a)if(a.getRangeAt)g=(d=a.rangeCount&&a.getRangeAt(0))&&new CKEDITOR.dom.node(d.commonAncestorContainer);else{try{d=a.createRange()}catch(e){}g=d&&CKEDITOR.dom.element.get(d.item&&d.item(0)||d.parentElement())}if(!g||g.type!=CKEDITOR.NODE_ELEMENT&&g.type!=CKEDITOR.NODE_TEXT||!this.root.equals(g)&&!this.root.contains(g))this._.cache.type=CKEDITOR.SELECTION_NONE, -this._.cache.startElement=null,this._.cache.selectedElement=null,this._.cache.selectedText="",this._.cache.ranges=new CKEDITOR.dom.rangeList;return this};var I={img:1,hr:1,li:1,table:1,tr:1,td:1,th:1,embed:1,object:1,ol:1,ul:1,a:1,input:1,form:1,select:1,textarea:1,button:1,fieldset:1,thead:1,tfoot:1};CKEDITOR.tools.extend(CKEDITOR.dom.selection,{_removeFillingCharSequenceString:w,_createFillingCharSequenceNode:a,FILLING_CHAR_SEQUENCE:x});CKEDITOR.dom.selection.prototype={getNative:function(){return void 0!== -this._.cache.nativeSel?this._.cache.nativeSel:this._.cache.nativeSel=q?this.document.$.selection:this.document.getWindow().$.getSelection()},getType:q?function(){var a=this._.cache;if(a.type)return a.type;var c=CKEDITOR.SELECTION_NONE;try{var b=this.getNative(),g=b.type;"Text"==g&&(c=CKEDITOR.SELECTION_TEXT);"Control"==g&&(c=CKEDITOR.SELECTION_ELEMENT);b.createRange().parentElement()&&(c=CKEDITOR.SELECTION_TEXT)}catch(d){}return a.type=c}:function(){var a=this._.cache;if(a.type)return a.type;var c= -CKEDITOR.SELECTION_TEXT,b=this.getNative();if(!b||!b.rangeCount)c=CKEDITOR.SELECTION_NONE;else if(1==b.rangeCount){var b=b.getRangeAt(0),g=b.startContainer;g==b.endContainer&&1==g.nodeType&&1==b.endOffset-b.startOffset&&I[g.childNodes[b.startOffset].nodeName.toLowerCase()]&&(c=CKEDITOR.SELECTION_ELEMENT)}return a.type=c},getRanges:function(){var a=q?function(){function a(c){return(new CKEDITOR.dom.node(c)).getIndex()}var c=function(c,b){c=c.duplicate();c.collapse(b);var g=c.parentElement();if(!g.hasChildNodes())return{container:g, -offset:0};for(var d=g.children,e,f,h=c.duplicate(),k=0,n=d.length-1,l=-1,m,q;k<=n;)if(l=Math.floor((k+n)/2),e=d[l],h.moveToElementText(e),m=h.compareEndPoints("StartToStart",c),0<m)n=l-1;else if(0>m)k=l+1;else return{container:g,offset:a(e)};if(-1==l||l==d.length-1&&0>m){h.moveToElementText(g);h.setEndPoint("StartToStart",c);h=h.text.replace(/(\r\n|\r)/g,"\n").length;d=g.childNodes;if(!h)return e=d[d.length-1],e.nodeType!=CKEDITOR.NODE_TEXT?{container:g,offset:d.length}:{container:e,offset:e.nodeValue.length}; -for(g=d.length;0<h&&0<g;)f=d[--g],f.nodeType==CKEDITOR.NODE_TEXT&&(q=f,h-=f.nodeValue.length);return{container:q,offset:-h}}h.collapse(0<m?!0:!1);h.setEndPoint(0<m?"StartToStart":"EndToStart",c);h=h.text.replace(/(\r\n|\r)/g,"\n").length;if(!h)return{container:g,offset:a(e)+(0<m?0:1)};for(;0<h;)try{f=e[0<m?"previousSibling":"nextSibling"],f.nodeType==CKEDITOR.NODE_TEXT&&(h-=f.nodeValue.length,q=f),e=f}catch(w){return{container:g,offset:a(e)}}return{container:q,offset:0<m?-h:q.nodeValue.length+h}}; -return function(){var a=this.getNative(),b=a&&a.createRange(),g=this.getType();if(!a)return[];if(g==CKEDITOR.SELECTION_TEXT)return a=new CKEDITOR.dom.range(this.root),g=c(b,!0),a.setStart(new CKEDITOR.dom.node(g.container),g.offset),g=c(b),a.setEnd(new CKEDITOR.dom.node(g.container),g.offset),a.endContainer.getPosition(a.startContainer)&CKEDITOR.POSITION_PRECEDING&&a.endOffset<=a.startContainer.getIndex()&&a.collapse(),[a];if(g==CKEDITOR.SELECTION_ELEMENT){for(var g=[],d=0;d<b.length;d++){for(var e= -b.item(d),f=e.parentNode,h=0,a=new CKEDITOR.dom.range(this.root);h<f.childNodes.length&&f.childNodes[h]!=e;h++);a.setStart(new CKEDITOR.dom.node(f),h);a.setEnd(new CKEDITOR.dom.node(f),h+1);g.push(a)}return g}return[]}}():function(){var a=[],c,b=this.getNative();if(!b)return a;for(var g=0;g<b.rangeCount;g++){var d=b.getRangeAt(g);c=new CKEDITOR.dom.range(this.root);c.setStart(new CKEDITOR.dom.node(d.startContainer),d.startOffset);c.setEnd(new CKEDITOR.dom.node(d.endContainer),d.endOffset);a.push(c)}return a}; -return function(c){var b=this._.cache,g=b.ranges;g||(b.ranges=g=new CKEDITOR.dom.rangeList(a.call(this)));return c?r(new CKEDITOR.dom.rangeList(g.slice())):g}}(),getStartElement:function(){var a=this._.cache;if(void 0!==a.startElement)return a.startElement;var c;switch(this.getType()){case CKEDITOR.SELECTION_ELEMENT:return this.getSelectedElement();case CKEDITOR.SELECTION_TEXT:var b=this.getRanges()[0];if(b){if(b.collapsed)c=b.startContainer,c.type!=CKEDITOR.NODE_ELEMENT&&(c=c.getParent());else{for(b.optimize();c= -b.startContainer,b.startOffset==(c.getChildCount?c.getChildCount():c.getLength())&&!c.isBlockBoundary();)b.setStartAfter(c);c=b.startContainer;if(c.type!=CKEDITOR.NODE_ELEMENT)return c.getParent();if((c=c.getChild(b.startOffset))&&c.type==CKEDITOR.NODE_ELEMENT)for(b=c.getFirst();b&&b.type==CKEDITOR.NODE_ELEMENT;)c=b,b=b.getFirst();else c=b.startContainer}c=c.$}}return a.startElement=c?new CKEDITOR.dom.element(c):null},getSelectedElement:function(){var a=this._.cache;if(void 0!==a.selectedElement)return a.selectedElement; -var c=this,b=CKEDITOR.tools.tryThese(function(){return c.getNative().createRange().item(0)},function(){for(var a=c.getRanges()[0].clone(),b,g,d=2;d&&!((b=a.getEnclosedNode())&&b.type==CKEDITOR.NODE_ELEMENT&&I[b.getName()]&&(g=b));d--)a.shrink(CKEDITOR.SHRINK_ELEMENT);return g&&g.$});return a.selectedElement=b?new CKEDITOR.dom.element(b):null},getSelectedText:function(){var a=this._.cache;if(void 0!==a.selectedText)return a.selectedText;var c=this.getNative(),c=q?"Control"==c.type?"":c.createRange().text: -c.toString();return a.selectedText=c},lock:function(){this.getRanges();this.getStartElement();this.getSelectedElement();this.getSelectedText();this._.cache.nativeSel=null;this.isLocked=1},unlock:function(a){if(this.isLocked){if(a)var c=this.getSelectedElement(),b=this.getRanges(),g=this.isFake;this.isLocked=0;this.reset();a&&(a=c||b[0]&&b[0].getCommonAncestor())&&a.getAscendant("body",1)&&(h(b)?d.call(this,b):g?this.fake(c):c?this.selectElement(c):this.selectRanges(b))}},reset:function(){this._.cache= -{};this.isFake=0;var a=this.root.editor;if(a&&a._.fakeSelection)if(this.rev==a._.fakeSelection.rev){delete a._.fakeSelection;var c=a._.hiddenSelectionContainer;if(c){var b=a.checkDirty();a.fire("lockSnapshot");c.remove();a.fire("unlockSnapshot");!b&&a.resetDirty()}delete a._.hiddenSelectionContainer}else CKEDITOR.warn("selection-fake-reset");this.rev=u++},selectElement:function(a){var c=new CKEDITOR.dom.range(this.root);c.setStartBefore(a);c.setEndAfter(a);this.selectRanges([c])},selectRanges:function(b){var g= -this.root.editor,e=g&&g._.hiddenSelectionContainer;this.reset();if(e)for(var e=this.root,f,k=0;k<b.length;++k)f=b[k],f.endContainer.equals(e)&&(f.endOffset=Math.min(f.endOffset,e.getChildCount()));if(b.length)if(this.isLocked){var l=CKEDITOR.document.getActive();this.unlock();this.selectRanges(b);this.lock();l&&!l.equals(this.root)&&l.focus()}else{var m;a:{var w,r;if(1==b.length&&!(r=b[0]).collapsed&&(m=r.getEnclosedNode())&&m.type==CKEDITOR.NODE_ELEMENT&&(r=r.clone(),r.shrink(CKEDITOR.SHRINK_ELEMENT, -!0),(w=r.getEnclosedNode())&&w.type==CKEDITOR.NODE_ELEMENT&&(m=w),"false"==m.getAttribute("contenteditable")))break a;m=void 0}if(m)this.fake(m);else if(g&&g.plugins.tableselection&&CKEDITOR.plugins.tableselection.isSupportedEnvironment&&h(b)&&!D)d.call(this,b);else{if(q){w=CKEDITOR.dom.walker.whitespaces(!0);m=/\ufeff|\u00a0/;r={table:1,tbody:1,tr:1};1<b.length&&(g=b[b.length-1],b[0].setEnd(g.endContainer,g.endOffset));g=b[0];b=g.collapsed;var p,u,t;if((e=g.getEnclosedNode())&&e.type==CKEDITOR.NODE_ELEMENT&& -e.getName()in I&&(!e.is("a")||!e.getText()))try{t=e.$.createControlRange();t.addElement(e.$);t.select();return}catch(x){}if(g.startContainer.type==CKEDITOR.NODE_ELEMENT&&g.startContainer.getName()in r||g.endContainer.type==CKEDITOR.NODE_ELEMENT&&g.endContainer.getName()in r)g.shrink(CKEDITOR.NODE_ELEMENT,!0),b=g.collapsed;t=g.createBookmark();r=t.startNode;b||(l=t.endNode);t=g.document.$.body.createTextRange();t.moveToElementText(r.$);t.moveStart("character",1);l?(m=g.document.$.body.createTextRange(), -m.moveToElementText(l.$),t.setEndPoint("EndToEnd",m),t.moveEnd("character",-1)):(p=r.getNext(w),u=r.hasAscendant("pre"),p=!(p&&p.getText&&p.getText().match(m))&&(u||!r.hasPrevious()||r.getPrevious().is&&r.getPrevious().is("br")),u=g.document.createElement("span"),u.setHtml("\x26#65279;"),u.insertBefore(r),p&&g.document.createText("").insertBefore(r));g.setStartBefore(r);r.remove();b?(p?(t.moveStart("character",-1),t.select(),g.document.$.selection.clear()):t.select(),g.moveToPosition(u,CKEDITOR.POSITION_BEFORE_START), -u.remove()):(g.setEndBefore(l),l.remove(),t.select())}else{l=this.getNative();if(!l)return;this.removeAllRanges();for(t=0;t<b.length;t++){if(t<b.length-1&&(p=b[t],u=b[t+1],m=p.clone(),m.setStart(p.endContainer,p.endOffset),m.setEnd(u.startContainer,u.startOffset),!m.collapsed&&(m.shrink(CKEDITOR.NODE_ELEMENT,!0),g=m.getCommonAncestor(),m=m.getEnclosedNode(),g.isReadOnly()||m&&m.isReadOnly()))){u.setStart(p.startContainer,p.startOffset);b.splice(t--,1);continue}g=b[t];u=this.document.$.createRange(); -g.collapsed&&CKEDITOR.env.webkit&&c(g)&&(m=a(this.root),g.insertNode(m),(p=m.getNext())&&!m.getPrevious()&&p.type==CKEDITOR.NODE_ELEMENT&&"br"==p.getName()?(n(this.root),g.moveToPosition(p,CKEDITOR.POSITION_BEFORE_START)):g.moveToPosition(m,CKEDITOR.POSITION_AFTER_END));u.setStart(g.startContainer.$,g.startOffset);try{u.setEnd(g.endContainer.$,g.endOffset)}catch(v){if(0<=v.toString().indexOf("NS_ERROR_ILLEGAL_VALUE"))g.collapse(1),u.setEnd(g.endContainer.$,g.endOffset);else throw v;}l.addRange(u)}}this.reset(); -this.root.fire("selectionchange")}}},fake:function(a,c){var b=this.root.editor;void 0===c&&a.hasAttribute("aria-label")&&(c=a.getAttribute("aria-label"));this.reset();v(b,c);var g=this._.cache,d=new CKEDITOR.dom.range(this.root);d.setStartBefore(a);d.setEndAfter(a);g.ranges=new CKEDITOR.dom.rangeList(d);g.selectedElement=g.startElement=a;g.type=CKEDITOR.SELECTION_ELEMENT;g.selectedText=g.nativeSel=null;this.isFake=1;this.rev=u++;b._.fakeSelection=this;this.root.fire("selectionchange")},isHidden:function(){var a= -this.getCommonAncestor();a&&a.type==CKEDITOR.NODE_TEXT&&(a=a.getParent());return!(!a||!a.data("cke-hidden-sel"))},isInTable:function(a){return h(this.getRanges(),a)},isCollapsed:function(){var a=this.getRanges();return 1===a.length&&a[0].collapsed},createBookmarks:function(a){a=this.getRanges().createBookmarks(a);this.isFake&&(a.isFake=1);return a},createBookmarks2:function(a){a=this.getRanges().createBookmarks2(a);this.isFake&&(a.isFake=1);return a},selectBookmarks:function(a){for(var c=[],b,g=0;g< -a.length;g++){var d=new CKEDITOR.dom.range(this.root);d.moveToBookmark(a[g]);c.push(d)}a.isFake&&(b=h(c)?c[0]._getTableElement():c[0].getEnclosedNode(),b&&b.type==CKEDITOR.NODE_ELEMENT||(CKEDITOR.warn("selection-not-fake"),a.isFake=0));a.isFake&&!h(c)?this.fake(b):this.selectRanges(c);return this},getCommonAncestor:function(){var a=this.getRanges();return a.length?a[0].startContainer.getCommonAncestor(a[a.length-1].endContainer):null},scrollIntoView:function(){this.type!=CKEDITOR.SELECTION_NONE&& -this.getRanges()[0].scrollIntoView()},removeAllRanges:function(){if(this.getType()!=CKEDITOR.SELECTION_NONE){var a=this.getNative();try{a&&a[q?"empty":"removeAllRanges"]()}catch(c){}this.reset()}}}}(),"use strict",CKEDITOR.STYLE_BLOCK=1,CKEDITOR.STYLE_INLINE=2,CKEDITOR.STYLE_OBJECT=3,function(){function f(a,c){for(var b,g;(a=a.getParent())&&!a.equals(c);)if(a.getAttribute("data-nostyle"))b=a;else if(!g){var d=a.getAttribute("contentEditable");"false"==d?b=a:"true"==d&&(g=1)}return b}function h(a, -c,b,g){return(a.getPosition(c)|g)==g&&(!b.childRule||b.childRule(a))}function e(a){var c=a.document;if(a.collapsed)c=u(this,c),a.insertNode(c),a.moveToPosition(c,CKEDITOR.POSITION_BEFORE_END);else{var b=this.element,g=this._.definition,k,n=g.ignoreReadonly,l=n||g.includeReadonly;null==l&&(l=a.root.getCustomData("cke_includeReadonly"));var m=CKEDITOR.dtd[b];m||(k=!0,m=CKEDITOR.dtd.span);a.enlarge(CKEDITOR.ENLARGE_INLINE,1);a.trim();var q=a.createBookmark(),r=q.startNode,w=q.endNode,t=r,x;if(!n){var v= -a.getCommonAncestor(),n=f(r,v),v=f(w,v);n&&(t=n.getNextSourceNode(!0));v&&(w=v)}for(t.getPosition(w)==CKEDITOR.POSITION_FOLLOWING&&(t=0);t;){n=!1;if(t.equals(w))t=null,n=!0;else{var P=t.type==CKEDITOR.NODE_ELEMENT?t.getName():null,v=P&&"false"==t.getAttribute("contentEditable"),A=P&&t.getAttribute("data-nostyle");if(P&&t.data("cke-bookmark")){t=t.getNextSourceNode(!0);continue}if(v&&l&&CKEDITOR.dtd.$block[P])for(var D=t,W=d(D),B=void 0,z=W.length,ea=0,D=z&&new CKEDITOR.dom.range(D.getDocument());ea< -z;++ea){var B=W[ea],y=CKEDITOR.filter.instances[B.data("cke-filter")];if(y?y.check(this):1)D.selectNodeContents(B),e.call(this,D)}W=P?!m[P]||A?0:v&&!l?0:h(t,w,g,L):1;if(W)if(B=t.getParent(),W=g,z=b,ea=k,!B||!(B.getDtd()||CKEDITOR.dtd.span)[z]&&!ea||W.parentRule&&!W.parentRule(B))n=!0;else{if(x||P&&CKEDITOR.dtd.$removeEmpty[P]&&(t.getPosition(w)|L)!=L||(x=a.clone(),x.setStartBefore(t)),P=t.type,P==CKEDITOR.NODE_TEXT||v||P==CKEDITOR.NODE_ELEMENT&&!t.getChildCount()){for(var P=t,I;(n=!P.getNext(H))&& -(I=P.getParent(),m[I.getName()])&&h(I,r,g,O);)P=I;x.setEndAfter(P)}}else n=!0;t=t.getNextSourceNode(A||v)}if(n&&x&&!x.collapsed){for(var n=u(this,c),v=n.hasAttributes(),A=x.getCommonAncestor(),P={},W={},B={},z={},E,G,F;n&&A;){if(A.getName()==b){for(E in g.attributes)!z[E]&&(F=A.getAttribute(G))&&(n.getAttribute(E)==F?W[E]=1:z[E]=1);for(G in g.styles)!B[G]&&(F=A.getStyle(G))&&(n.getStyle(G)==F?P[G]=1:B[G]=1)}A=A.getParent()}for(E in W)n.removeAttribute(E);for(G in P)n.removeStyle(G);v&&!n.hasAttributes()&& -(n=null);n?(x.extractContents().appendTo(n),x.insertNode(n),p.call(this,n),n.mergeSiblings(),CKEDITOR.env.ie||n.$.normalize()):(n=new CKEDITOR.dom.element("span"),x.extractContents().appendTo(n),x.insertNode(n),p.call(this,n),n.remove(!0));x=null}}a.moveToBookmark(q);a.shrink(CKEDITOR.SHRINK_TEXT);a.shrink(CKEDITOR.NODE_ELEMENT,!0)}}function k(a){function c(){for(var a=new CKEDITOR.dom.elementPath(g.getParent()),b=new CKEDITOR.dom.elementPath(l.getParent()),d=null,e=null,f=0;f<a.elements.length;f++){var h= -a.elements[f];if(h==a.block||h==a.blockLimit)break;m.checkElementRemovable(h,!0)&&(d=h)}for(f=0;f<b.elements.length;f++){h=b.elements[f];if(h==b.block||h==b.blockLimit)break;m.checkElementRemovable(h,!0)&&(e=h)}e&&l.breakParent(e);d&&g.breakParent(d)}a.enlarge(CKEDITOR.ENLARGE_INLINE,1);var b=a.createBookmark(),g=b.startNode,d=this._.definition.alwaysRemoveElement;if(a.collapsed){for(var e=new CKEDITOR.dom.elementPath(g.getParent(),a.root),f,h=0,k;h<e.elements.length&&(k=e.elements[h])&&k!=e.block&& -k!=e.blockLimit;h++)if(this.checkElementRemovable(k)){var n;!d&&a.collapsed&&(a.checkBoundaryOfElement(k,CKEDITOR.END)||(n=a.checkBoundaryOfElement(k,CKEDITOR.START)))?(f=k,f.match=n?"start":"end"):(k.mergeSiblings(),k.is(this.element)?v.call(this,k):r(k,D(this)[k.getName()]))}if(f){d=g;for(h=0;;h++){k=e.elements[h];if(k.equals(f))break;else if(k.match)continue;else k=k.clone();k.append(d);d=k}d["start"==f.match?"insertBefore":"insertAfter"](f)}}else{var l=b.endNode,m=this;c();for(e=g;!e.equals(l);)f= -e.getNextSourceNode(),e.type==CKEDITOR.NODE_ELEMENT&&this.checkElementRemovable(e)&&(e.getName()==this.element?v.call(this,e):r(e,D(this)[e.getName()]),f.type==CKEDITOR.NODE_ELEMENT&&f.contains(g)&&(c(),f=g.getNext())),e=f}a.moveToBookmark(b);a.shrink(CKEDITOR.NODE_ELEMENT,!0)}function d(a){var c=[];a.forEach(function(a){if("true"==a.getAttribute("contenteditable"))return c.push(a),!1},CKEDITOR.NODE_ELEMENT,!0);return c}function l(a){var c=a.getEnclosedNode()||a.getCommonAncestor(!1,!0);(a=(new CKEDITOR.dom.elementPath(c, -a.root)).contains(this.element,1))&&!a.isReadOnly()&&x(a,this)}function m(a){var c=a.getCommonAncestor(!0,!0);if(a=(new CKEDITOR.dom.elementPath(c,a.root)).contains(this.element,1)){var c=this._.definition,b=c.attributes;if(b)for(var g in b)a.removeAttribute(g,b[g]);if(c.styles)for(var d in c.styles)c.styles.hasOwnProperty(d)&&a.removeStyle(d)}}function b(a){var b=a.createBookmark(!0),g=a.createIterator();g.enforceRealBlocks=!0;this._.enterMode&&(g.enlargeBr=this._.enterMode!=CKEDITOR.ENTER_BR);for(var d, -e=a.document,f;d=g.getNextParagraph();)!d.isReadOnly()&&(g.activeFilter?g.activeFilter.check(this):1)&&(f=u(this,e,d),c(d,f));a.moveToBookmark(b)}function g(a){var b=a.createBookmark(1),g=a.createIterator();g.enforceRealBlocks=!0;g.enlargeBr=this._.enterMode!=CKEDITOR.ENTER_BR;for(var d,e;d=g.getNextParagraph();)this.checkElementRemovable(d)&&(d.is("pre")?((e=this._.enterMode==CKEDITOR.ENTER_BR?null:a.document.createElement(this._.enterMode==CKEDITOR.ENTER_P?"p":"div"))&&d.copyAttributes(e),c(d,e)): -v.call(this,d));a.moveToBookmark(b)}function c(c,b){var g=!b;g&&(b=c.getDocument().createElement("div"),c.copyAttributes(b));var d=b&&b.is("pre"),e=c.is("pre"),f=!d&&e;if(d&&!e){e=b;(f=c.getBogus())&&f.remove();f=c.getHtml();f=n(f,/(?:^[ \t\n\r]+)|(?:[ \t\n\r]+$)/g,"");f=f.replace(/[ \t\r\n]*(<br[^>]*>)[ \t\r\n]*/gi,"$1");f=f.replace(/([ \t\n\r]+| )/g," ");f=f.replace(/<br\b[^>]*>/gi,"\n");if(CKEDITOR.env.ie){var h=c.getDocument().createElement("div");h.append(e);e.$.outerHTML="\x3cpre\x3e"+ -f+"\x3c/pre\x3e";e.copyAttributes(h.getFirst());e=h.getFirst().remove()}else e.setHtml(f);b=e}else f?b=w(g?[c.getHtml()]:a(c),b):c.moveChildren(b);b.replace(c);if(d){var g=b,k;(k=g.getPrevious(G))&&k.type==CKEDITOR.NODE_ELEMENT&&k.is("pre")&&(d=n(k.getHtml(),/\n$/,"")+"\n\n"+n(g.getHtml(),/^\n/,""),CKEDITOR.env.ie?g.$.outerHTML="\x3cpre\x3e"+d+"\x3c/pre\x3e":g.setHtml(d),k.remove())}else g&&q(b)}function a(a){var c=[];n(a.getOuterHtml(),/(\S\s*)\n(?:\s|(<span[^>]+data-cke-bookmark.*?\/span>))*\n(?!$)/gi, -function(a,c,b){return c+"\x3c/pre\x3e"+b+"\x3cpre\x3e"}).replace(/<pre\b.*?>([\s\S]*?)<\/pre>/gi,function(a,b){c.push(b)});return c}function n(a,c,b){var g="",d="";a=a.replace(/(^<span[^>]+data-cke-bookmark.*?\/span>)|(<span[^>]+data-cke-bookmark.*?\/span>$)/gi,function(a,c,b){c&&(g=c);b&&(d=b);return""});return g+a.replace(c,b)+d}function w(a,c){var b;1<a.length&&(b=new CKEDITOR.dom.documentFragment(c.getDocument()));for(var g=0;g<a.length;g++){var d=a[g],d=d.replace(/(\r\n|\r)/g,"\n"),d=n(d,/^[ \t]*\n/, -""),d=n(d,/\n$/,""),d=n(d,/^[ \t]+|[ \t]+$/g,function(a,c){return 1==a.length?"\x26nbsp;":c?" "+CKEDITOR.tools.repeat("\x26nbsp;",a.length-1):CKEDITOR.tools.repeat("\x26nbsp;",a.length-1)+" "}),d=d.replace(/\n/g,"\x3cbr\x3e"),d=d.replace(/[ \t]{2,}/g,function(a){return CKEDITOR.tools.repeat("\x26nbsp;",a.length-1)+" "});if(b){var e=c.clone();e.setHtml(d);b.append(e)}else c.setHtml(d)}return b||c}function v(a,c){var b=this._.definition,g=b.attributes,b=b.styles,d=D(this)[a.getName()],e=CKEDITOR.tools.isEmpty(g)&& -CKEDITOR.tools.isEmpty(b),f;for(f in g)if("class"!=f&&!this._.definition.fullMatch||a.getAttribute(f)==t(f,g[f]))c&&"data-"==f.slice(0,5)||(e=a.hasAttribute(f),a.removeAttribute(f));for(var h in b)this._.definition.fullMatch&&a.getStyle(h)!=t(h,b[h],!0)||(e=e||!!a.getStyle(h),a.removeStyle(h));r(a,d,z[a.getName()]);e&&(this._.definition.alwaysRemoveElement?q(a,1):!CKEDITOR.dtd.$block[a.getName()]||this._.enterMode==CKEDITOR.ENTER_BR&&!a.hasAttributes()?q(a):a.renameNode(this._.enterMode==CKEDITOR.ENTER_P? -"p":"div"))}function p(a){for(var c=D(this),b=a.getElementsByTag(this.element),g,d=b.count();0<=--d;)g=b.getItem(d),g.isReadOnly()||v.call(this,g,!0);for(var e in c)if(e!=this.element)for(b=a.getElementsByTag(e),d=b.count()-1;0<=d;d--)g=b.getItem(d),g.isReadOnly()||r(g,c[e])}function r(a,c,b){if(c=c&&c.attributes)for(var g=0;g<c.length;g++){var d=c[g][0],e;if(e=a.getAttribute(d)){var f=c[g][1];(null===f||f.test&&f.test(e)||"string"==typeof f&&e==f)&&a.removeAttribute(d)}}b||q(a)}function q(a,c){if(!a.hasAttributes()|| -c)if(CKEDITOR.dtd.$block[a.getName()]){var b=a.getPrevious(G),g=a.getNext(G);!b||b.type!=CKEDITOR.NODE_TEXT&&b.isBlockBoundary({br:1})||a.append("br",1);!g||g.type!=CKEDITOR.NODE_TEXT&&g.isBlockBoundary({br:1})||a.append("br");a.remove(!0)}else b=a.getFirst(),g=a.getLast(),a.remove(!0),b&&(b.type==CKEDITOR.NODE_ELEMENT&&b.mergeSiblings(),g&&!b.equals(g)&&g.type==CKEDITOR.NODE_ELEMENT&&g.mergeSiblings())}function u(a,c,b){var g;g=a.element;"*"==g&&(g="span");g=new CKEDITOR.dom.element(g,c);b&&b.copyAttributes(g); -g=x(g,a);c.getCustomData("doc_processing_style")&&g.hasAttribute("id")?g.removeAttribute("id"):c.setCustomData("doc_processing_style",1);return g}function x(a,c){var b=c._.definition,g=b.attributes,b=CKEDITOR.style.getStyleText(b);if(g)for(var d in g)a.setAttribute(d,g[d]);b&&a.setAttribute("style",b);return a}function A(a,c){for(var b in a)a[b]=a[b].replace(F,function(a,b){return c[b]})}function D(a){if(a._.overrides)return a._.overrides;var c=a._.overrides={},b=a._.definition.overrides;if(b){CKEDITOR.tools.isArray(b)|| -(b=[b]);for(var g=0;g<b.length;g++){var d=b[g],e,f;"string"==typeof d?e=d.toLowerCase():(e=d.element?d.element.toLowerCase():a.element,f=d.attributes);d=c[e]||(c[e]={});if(f){var d=d.attributes=d.attributes||[],h;for(h in f)d.push([h.toLowerCase(),f[h]])}}}return c}function t(a,c,b){var g=new CKEDITOR.dom.element("span");g[b?"setStyle":"setAttribute"](a,c);return g[b?"getStyle":"getAttribute"](a)}function B(a,c){function b(a,c){return"font-family"==c.toLowerCase()?a.replace(/["']/g,""):a}"string"== -typeof a&&(a=CKEDITOR.tools.parseCssText(a));"string"==typeof c&&(c=CKEDITOR.tools.parseCssText(c,!0));for(var g in a)if(!(g in c)||b(c[g],g)!=b(a[g],g)&&"inherit"!=a[g]&&"inherit"!=c[g])return!1;return!0}function y(a,c,b){var g=a.document,d=a.getRanges();c=c?this.removeFromRange:this.applyToRange;var e,f;if(a.isFake&&a.isInTable())for(e=[],f=0;f<d.length;f++)e.push(d[f].clone());for(var h=d.createIterator();f=h.getNextRange();)c.call(this,f,b);a.selectRanges(e||d);g.removeCustomData("doc_processing_style")} -var z={address:1,div:1,h1:1,h2:1,h3:1,h4:1,h5:1,h6:1,p:1,pre:1,section:1,header:1,footer:1,nav:1,article:1,aside:1,figure:1,dialog:1,hgroup:1,time:1,meter:1,menu:1,command:1,keygen:1,output:1,progress:1,details:1,datagrid:1,datalist:1},I={a:1,blockquote:1,embed:1,hr:1,img:1,li:1,object:1,ol:1,table:1,td:1,tr:1,th:1,ul:1,dl:1,dt:1,dd:1,form:1,audio:1,video:1},E=/\s*(?:;\s*|$)/,F=/#\((.+?)\)/g,H=CKEDITOR.dom.walker.bookmark(0,1),G=CKEDITOR.dom.walker.whitespaces(1);CKEDITOR.style=function(a,c){if("string"== -typeof a.type)return new CKEDITOR.style.customHandlers[a.type](a);var b=a.attributes;b&&b.style&&(a.styles=CKEDITOR.tools.extend({},a.styles,CKEDITOR.tools.parseCssText(b.style)),delete b.style);c&&(a=CKEDITOR.tools.clone(a),A(a.attributes,c),A(a.styles,c));b=this.element=a.element?"string"==typeof a.element?a.element.toLowerCase():a.element:"*";this.type=a.type||(z[b]?CKEDITOR.STYLE_BLOCK:I[b]?CKEDITOR.STYLE_OBJECT:CKEDITOR.STYLE_INLINE);"object"==typeof this.element&&(this.type=CKEDITOR.STYLE_OBJECT); -this._={definition:a}};CKEDITOR.style.prototype={apply:function(a){if(a instanceof CKEDITOR.dom.document)return y.call(this,a.getSelection());if(this.checkApplicable(a.elementPath(),a)){var c=this._.enterMode;c||(this._.enterMode=a.activeEnterMode);y.call(this,a.getSelection(),0,a);this._.enterMode=c}},remove:function(a){if(a instanceof CKEDITOR.dom.document)return y.call(this,a.getSelection(),1);if(this.checkApplicable(a.elementPath(),a)){var c=this._.enterMode;c||(this._.enterMode=a.activeEnterMode); -y.call(this,a.getSelection(),1,a);this._.enterMode=c}},applyToRange:function(a){this.applyToRange=this.type==CKEDITOR.STYLE_INLINE?e:this.type==CKEDITOR.STYLE_BLOCK?b:this.type==CKEDITOR.STYLE_OBJECT?l:null;return this.applyToRange(a)},removeFromRange:function(a){this.removeFromRange=this.type==CKEDITOR.STYLE_INLINE?k:this.type==CKEDITOR.STYLE_BLOCK?g:this.type==CKEDITOR.STYLE_OBJECT?m:null;return this.removeFromRange(a)},applyToObject:function(a){x(a,this)},checkActive:function(a,c){switch(this.type){case CKEDITOR.STYLE_BLOCK:return this.checkElementRemovable(a.block|| -a.blockLimit,!0,c);case CKEDITOR.STYLE_OBJECT:case CKEDITOR.STYLE_INLINE:for(var b=a.elements,g=0,d;g<b.length;g++)if(d=b[g],this.type!=CKEDITOR.STYLE_INLINE||d!=a.block&&d!=a.blockLimit){if(this.type==CKEDITOR.STYLE_OBJECT){var e=d.getName();if(!("string"==typeof this.element?e==this.element:e in this.element))continue}if(this.checkElementRemovable(d,!0,c))return!0}}return!1},checkApplicable:function(a,c,b){c&&c instanceof CKEDITOR.filter&&(b=c);if(b&&!b.check(this))return!1;switch(this.type){case CKEDITOR.STYLE_OBJECT:return!!a.contains(this.element); -case CKEDITOR.STYLE_BLOCK:return!!a.blockLimit.getDtd()[this.element]}return!0},checkElementMatch:function(a,c){var b=this._.definition;if(!a||!b.ignoreReadonly&&a.isReadOnly())return!1;var g=a.getName();if("string"==typeof this.element?g==this.element:g in this.element){if(!c&&!a.hasAttributes())return!0;if(g=b._AC)b=g;else{var g={},d=0,e=b.attributes;if(e)for(var f in e)d++,g[f]=e[f];if(f=CKEDITOR.style.getStyleText(b))g.style||d++,g.style=f;g._length=d;b=b._AC=g}if(b._length){for(var h in b)if("_length"!= -h)if(g=a.getAttribute(h)||"","style"==h?B(b[h],g):b[h]==g){if(!c)return!0}else if(c)return!1;if(c)return!0}else return!0}return!1},checkElementRemovable:function(a,c,b){if(this.checkElementMatch(a,c,b))return!0;if(c=D(this)[a.getName()]){var g;if(!(c=c.attributes))return!0;for(b=0;b<c.length;b++)if(g=c[b][0],g=a.getAttribute(g)){var d=c[b][1];if(null===d)return!0;if("string"==typeof d){if(g==d)return!0}else if(d.test(g))return!0}}return!1},buildPreview:function(a){var c=this._.definition,b=[],g=c.element; -"bdo"==g&&(g="span");var b=["\x3c",g],d=c.attributes;if(d)for(var e in d)b.push(" ",e,'\x3d"',d[e],'"');(d=CKEDITOR.style.getStyleText(c))&&b.push(' style\x3d"',d,'"');b.push("\x3e",a||c.name,"\x3c/",g,"\x3e");return b.join("")},getDefinition:function(){return this._.definition}};CKEDITOR.style.getStyleText=function(a){var c=a._ST;if(c)return c;var c=a.styles,b=a.attributes&&a.attributes.style||"",g="";b.length&&(b=b.replace(E,";"));for(var d in c){var e=c[d],f=(d+":"+e).replace(E,";");"inherit"== -e?g+=f:b+=f}b.length&&(b=CKEDITOR.tools.normalizeCssText(b,!0));return a._ST=b+g};CKEDITOR.style.customHandlers={};CKEDITOR.style.addCustomHandler=function(a){var c=function(a){this._={definition:a};this.setup&&this.setup(a)};c.prototype=CKEDITOR.tools.extend(CKEDITOR.tools.prototypedCopy(CKEDITOR.style.prototype),{assignedTo:CKEDITOR.STYLE_OBJECT},a,!0);return this.customHandlers[a.type]=c};var L=CKEDITOR.POSITION_PRECEDING|CKEDITOR.POSITION_IDENTICAL|CKEDITOR.POSITION_IS_CONTAINED,O=CKEDITOR.POSITION_FOLLOWING| -CKEDITOR.POSITION_IDENTICAL|CKEDITOR.POSITION_IS_CONTAINED}(),CKEDITOR.styleCommand=function(f,h){this.requiredContent=this.allowedContent=this.style=f;CKEDITOR.tools.extend(this,h,!0)},CKEDITOR.styleCommand.prototype.exec=function(f){f.focus();this.state==CKEDITOR.TRISTATE_OFF?f.applyStyle(this.style):this.state==CKEDITOR.TRISTATE_ON&&f.removeStyle(this.style)},CKEDITOR.stylesSet=new CKEDITOR.resourceManager("","stylesSet"),CKEDITOR.addStylesSet=CKEDITOR.tools.bind(CKEDITOR.stylesSet.add,CKEDITOR.stylesSet), -CKEDITOR.loadStylesSet=function(f,h,e){CKEDITOR.stylesSet.addExternal(f,h,"");CKEDITOR.stylesSet.load(f,e)},CKEDITOR.tools.extend(CKEDITOR.editor.prototype,{attachStyleStateChange:function(f,h){var e=this._.styleStateChangeCallbacks;e||(e=this._.styleStateChangeCallbacks=[],this.on("selectionChange",function(f){for(var d=0;d<e.length;d++){var h=e[d],m=h.style.checkActive(f.data.path,this)?CKEDITOR.TRISTATE_ON:CKEDITOR.TRISTATE_OFF;h.fn.call(this,m)}}));e.push({style:f,fn:h})},applyStyle:function(f){f.apply(this)}, -removeStyle:function(f){f.remove(this)},getStylesSet:function(f){if(this._.stylesDefinitions)f(this._.stylesDefinitions);else{var h=this,e=h.config.stylesCombo_stylesSet||h.config.stylesSet;if(!1===e)f(null);else if(e instanceof Array)h._.stylesDefinitions=e,f(e);else{e||(e="default");var e=e.split(":"),k=e[0];CKEDITOR.stylesSet.addExternal(k,e[1]?e.slice(1).join(":"):CKEDITOR.getUrl("styles.js"),"");CKEDITOR.stylesSet.load(k,function(d){h._.stylesDefinitions=d[k];f(h._.stylesDefinitions)})}}}}), -CKEDITOR.dom.comment=function(f,h){"string"==typeof f&&(f=(h?h.$:document).createComment(f));CKEDITOR.dom.domObject.call(this,f)},CKEDITOR.dom.comment.prototype=new CKEDITOR.dom.node,CKEDITOR.tools.extend(CKEDITOR.dom.comment.prototype,{type:CKEDITOR.NODE_COMMENT,getOuterHtml:function(){return"\x3c!--"+this.$.nodeValue+"--\x3e"}}),"use strict",function(){var f={},h={},e;for(e in CKEDITOR.dtd.$blockLimit)e in CKEDITOR.dtd.$list||(f[e]=1);for(e in CKEDITOR.dtd.$block)e in CKEDITOR.dtd.$blockLimit|| -e in CKEDITOR.dtd.$empty||(h[e]=1);CKEDITOR.dom.elementPath=function(e,d){var l=null,m=null,b=[],g=e,c;d=d||e.getDocument().getBody();g||(g=d);do if(g.type==CKEDITOR.NODE_ELEMENT){b.push(g);if(!this.lastElement&&(this.lastElement=g,g.is(CKEDITOR.dtd.$object)||"false"==g.getAttribute("contenteditable")))continue;if(g.equals(d))break;if(!m&&(c=g.getName(),"true"==g.getAttribute("contenteditable")?m=g:!l&&h[c]&&(l=g),f[c])){if(c=!l&&"div"==c){a:{c=g.getChildren();for(var a=0,n=c.count();a<n;a++){var w= -c.getItem(a);if(w.type==CKEDITOR.NODE_ELEMENT&&CKEDITOR.dtd.$block[w.getName()]){c=!0;break a}}c=!1}c=!c}c?l=g:m=g}}while(g=g.getParent());m||(m=d);this.block=l;this.blockLimit=m;this.root=d;this.elements=b}}(),CKEDITOR.dom.elementPath.prototype={compare:function(f){var h=this.elements;f=f&&f.elements;if(!f||h.length!=f.length)return!1;for(var e=0;e<h.length;e++)if(!h[e].equals(f[e]))return!1;return!0},contains:function(f,h,e){var k=0,d;"string"==typeof f&&(d=function(b){return b.getName()==f});f instanceof -CKEDITOR.dom.element?d=function(b){return b.equals(f)}:CKEDITOR.tools.isArray(f)?d=function(b){return-1<CKEDITOR.tools.indexOf(f,b.getName())}:"function"==typeof f?d=f:"object"==typeof f&&(d=function(b){return b.getName()in f});var l=this.elements,m=l.length;h&&(e?k+=1:--m);e&&(l=Array.prototype.slice.call(l,0),l.reverse());for(;k<m;k++)if(d(l[k]))return l[k];return null},isContextFor:function(f){var h;return f in CKEDITOR.dtd.$block?(h=this.contains(CKEDITOR.dtd.$intermediate)||this.root.equals(this.block)&& -this.block||this.blockLimit,!!h.getDtd()[f]):!0},direction:function(){return(this.block||this.blockLimit||this.root).getDirection(1)}},CKEDITOR.dom.text=function(f,h){"string"==typeof f&&(f=(h?h.$:document).createTextNode(f));this.$=f},CKEDITOR.dom.text.prototype=new CKEDITOR.dom.node,CKEDITOR.tools.extend(CKEDITOR.dom.text.prototype,{type:CKEDITOR.NODE_TEXT,getLength:function(){return this.$.nodeValue.length},getText:function(){return this.$.nodeValue},setText:function(f){this.$.nodeValue=f},split:function(f){var h= -this.$.parentNode,e=h.childNodes.length,k=this.getLength(),d=this.getDocument(),l=new CKEDITOR.dom.text(this.$.splitText(f),d);h.childNodes.length==e&&(f>=k?(l=d.createText(""),l.insertAfter(this)):(f=d.createText(""),f.insertAfter(l),f.remove()));return l},substring:function(f,h){return"number"!=typeof h?this.$.nodeValue.substr(f):this.$.nodeValue.substring(f,h)}}),function(){function f(e,f,d){var h=e.serializable,m=f[d?"endContainer":"startContainer"],b=d?"endOffset":"startOffset",g=h?f.document.getById(e.startNode): -e.startNode;e=h?f.document.getById(e.endNode):e.endNode;m.equals(g.getPrevious())?(f.startOffset=f.startOffset-m.getLength()-e.getPrevious().getLength(),m=e.getNext()):m.equals(e.getPrevious())&&(f.startOffset-=m.getLength(),m=e.getNext());m.equals(g.getParent())&&f[b]++;m.equals(e.getParent())&&f[b]++;f[d?"endContainer":"startContainer"]=m;return f}CKEDITOR.dom.rangeList=function(e){if(e instanceof CKEDITOR.dom.rangeList)return e;e?e instanceof CKEDITOR.dom.range&&(e=[e]):e=[];return CKEDITOR.tools.extend(e, -h)};var h={createIterator:function(){var e=this,f=CKEDITOR.dom.walker.bookmark(),d=[],h;return{getNextRange:function(m){h=void 0===h?0:h+1;var b=e[h];if(b&&1<e.length){if(!h)for(var g=e.length-1;0<=g;g--)d.unshift(e[g].createBookmark(!0));if(m)for(var c=0;e[h+c+1];){var a=b.document;m=0;g=a.getById(d[c].endNode);for(a=a.getById(d[c+1].startNode);;){g=g.getNextSourceNode(!1);if(a.equals(g))m=1;else if(f(g)||g.type==CKEDITOR.NODE_ELEMENT&&g.isBlockBoundary())continue;break}if(!m)break;c++}for(b.moveToBookmark(d.shift());c--;)g= -e[++h],g.moveToBookmark(d.shift()),b.setEnd(g.endContainer,g.endOffset)}return b}}},createBookmarks:function(e){for(var h=[],d,l=0;l<this.length;l++){h.push(d=this[l].createBookmark(e,!0));for(var m=l+1;m<this.length;m++)this[m]=f(d,this[m]),this[m]=f(d,this[m],!0)}return h},createBookmarks2:function(e){for(var f=[],d=0;d<this.length;d++)f.push(this[d].createBookmark2(e));return f},moveToBookmarks:function(e){for(var f=0;f<this.length;f++)this[f].moveToBookmark(e[f])}}}(),function(){function f(){return CKEDITOR.getUrl(CKEDITOR.skinName.split(",")[1]|| -"skins/"+CKEDITOR.skinName.split(",")[0]+"/")}function h(c){var a=CKEDITOR.skin["ua_"+c],b=CKEDITOR.env;if(a)for(var a=a.split(",").sort(function(a,c){return a>c?-1:1}),g=0,d;g<a.length;g++)if(d=a[g],b.ie&&(d.replace(/^ie/,"")==b.version||b.quirks&&"iequirks"==d)&&(d="ie"),b[d]){c+="_"+a[g];break}return CKEDITOR.getUrl(f()+c+".css")}function e(c,a){l[c]||(CKEDITOR.document.appendStyleSheet(h(c)),l[c]=1);a&&a()}function k(c){var a=c.getById(m);a||(a=c.getHead().append("style"),a.setAttribute("id", -m),a.setAttribute("type","text/css"));return a}function d(c,a,b){var g,d,e;if(CKEDITOR.env.webkit)for(a=a.split("}").slice(0,-1),d=0;d<a.length;d++)a[d]=a[d].split("{");for(var f=0;f<c.length;f++)if(CKEDITOR.env.webkit)for(d=0;d<a.length;d++){e=a[d][1];for(g=0;g<b.length;g++)e=e.replace(b[g][0],b[g][1]);c[f].$.sheet.addRule(a[d][0],e)}else{e=a;for(g=0;g<b.length;g++)e=e.replace(b[g][0],b[g][1]);CKEDITOR.env.ie&&11>CKEDITOR.env.version?c[f].$.styleSheet.cssText+=e:c[f].$.innerHTML+=e}}var l={};CKEDITOR.skin= -{path:f,loadPart:function(c,a){CKEDITOR.skin.name!=CKEDITOR.skinName.split(",")[0]?CKEDITOR.scriptLoader.load(CKEDITOR.getUrl(f()+"skin.js"),function(){e(c,a)}):e(c,a)},getPath:function(c){return CKEDITOR.getUrl(h(c))},icons:{},addIcon:function(c,a,b,g){c=c.toLowerCase();this.icons[c]||(this.icons[c]={path:a,offset:b||0,bgsize:g||"16px"})},getIconStyle:function(c,a,b,g,d){var e;c&&(c=c.toLowerCase(),a&&(e=this.icons[c+"-rtl"]),e||(e=this.icons[c]));c=b||e&&e.path||"";g=g||e&&e.offset;d=d||e&&e.bgsize|| -"16px";c&&(c=c.replace(/'/g,"\\'"));return c&&"background-image:url('"+CKEDITOR.getUrl(c)+"');background-position:0 "+g+"px;background-size:"+d+";"}};CKEDITOR.tools.extend(CKEDITOR.editor.prototype,{getUiColor:function(){return this.uiColor},setUiColor:function(c){var a=k(CKEDITOR.document);return(this.setUiColor=function(c){this.uiColor=c;var e=CKEDITOR.skin.chameleon,f="",h="";"function"==typeof e&&(f=e(this,"editor"),h=e(this,"panel"));c=[[g,c]];d([a],f,c);d(b,h,c)}).call(this,c)}});var m="cke_ui_color", -b=[],g=/\$color/g;CKEDITOR.on("instanceLoaded",function(c){if(!CKEDITOR.env.ie||!CKEDITOR.env.quirks){var a=c.editor;c=function(c){c=(c.data[0]||c.data).element.getElementsByTag("iframe").getItem(0).getFrameDocument();if(!c.getById("cke_ui_color")){c=k(c);b.push(c);var e=a.getUiColor();e&&d([c],CKEDITOR.skin.chameleon(a,"panel"),[[g,e]])}};a.on("panelShow",c);a.on("menuShow",c);a.config.uiColor&&a.setUiColor(a.config.uiColor)}})}(),function(){if(CKEDITOR.env.webkit)CKEDITOR.env.hc=!1;else{var f=CKEDITOR.dom.element.createFromHtml('\x3cdiv style\x3d"width:0;height:0;position:absolute;left:-10000px;border:1px solid;border-color:red blue"\x3e\x3c/div\x3e', -CKEDITOR.document);f.appendTo(CKEDITOR.document.getHead());try{var h=f.getComputedStyle("border-top-color"),e=f.getComputedStyle("border-right-color");CKEDITOR.env.hc=!(!h||h!=e)}catch(k){CKEDITOR.env.hc=!1}f.remove()}CKEDITOR.env.hc&&(CKEDITOR.env.cssClass+=" cke_hc");CKEDITOR.document.appendStyleText(".cke{visibility:hidden;}");CKEDITOR.status="loaded";CKEDITOR.fireOnce("loaded");if(f=CKEDITOR._.pending)for(delete CKEDITOR._.pending,h=0;h<f.length;h++)CKEDITOR.editor.prototype.constructor.apply(f[h][0], -f[h][1]),CKEDITOR.add(f[h][0])}(),CKEDITOR.skin.name="moono-lisa",CKEDITOR.skin.ua_editor="ie,iequirks,ie8,gecko",CKEDITOR.skin.ua_dialog="ie,iequirks,ie8",CKEDITOR.skin.chameleon=function(){var f=function(){return function(e,f){for(var d=e.match(/[^#]./g),h=0;3>h;h++){var m=h,b;b=parseInt(d[h],16);b=("0"+(0>f?0|b*(1+f):0|b+(255-b)*f).toString(16)).slice(-2);d[m]=b}return"#"+d.join("")}}(),h={editor:new CKEDITOR.template("{id}.cke_chrome [border-color:{defaultBorder};] {id} .cke_top [ background-color:{defaultBackground};border-bottom-color:{defaultBorder};] {id} .cke_bottom [background-color:{defaultBackground};border-top-color:{defaultBorder};] {id} .cke_resizer [border-right-color:{ckeResizer}] {id} .cke_dialog_title [background-color:{defaultBackground};border-bottom-color:{defaultBorder};] {id} .cke_dialog_footer [background-color:{defaultBackground};outline-color:{defaultBorder};] {id} .cke_dialog_tab [background-color:{dialogTab};border-color:{defaultBorder};] {id} .cke_dialog_tab:hover [background-color:{lightBackground};] {id} .cke_dialog_contents [border-top-color:{defaultBorder};] {id} .cke_dialog_tab_selected, {id} .cke_dialog_tab_selected:hover [background:{dialogTabSelected};border-bottom-color:{dialogTabSelectedBorder};] {id} .cke_dialog_body [background:{dialogBody};border-color:{defaultBorder};] {id} a.cke_button_off:hover,{id} a.cke_button_off:focus,{id} a.cke_button_off:active [background-color:{darkBackground};border-color:{toolbarElementsBorder};] {id} .cke_button_on [background-color:{ckeButtonOn};border-color:{toolbarElementsBorder};] {id} .cke_toolbar_separator,{id} .cke_toolgroup a.cke_button:last-child:after,{id} .cke_toolgroup a.cke_button.cke_button_disabled:hover:last-child:after [background-color: {toolbarElementsBorder};border-color: {toolbarElementsBorder};] {id} a.cke_combo_button:hover,{id} a.cke_combo_button:focus,{id} .cke_combo_on a.cke_combo_button [border-color:{toolbarElementsBorder};background-color:{darkBackground};] {id} .cke_combo:after [border-color:{toolbarElementsBorder};] {id} .cke_path_item [color:{elementsPathColor};] {id} a.cke_path_item:hover,{id} a.cke_path_item:focus,{id} a.cke_path_item:active [background-color:{darkBackground};] {id}.cke_panel [border-color:{defaultBorder};] "), +fixUneditableRangePosition:function(a){a.startContainer.getDtd()["#"]||a.moveToClosestEditablePosition(null,!0)},autoParagraph:function(a,c){var d=c.startPath(),g;m(a,d.block,d.blockLimit)&&(g=b(a))&&(g=c.document.createElement(g),g.appendBogus(),c.insertNode(g),c.moveToPosition(g,CKEDITOR.POSITION_AFTER_START))}}}()}(),function(){function f(a){return CKEDITOR.plugins.widget&&CKEDITOR.plugins.widget.isDomWidget(a)}function h(a,c){if(0===a.length||f(a[0].getEnclosedNode()))return!1;var b,d;if((b=!c&& +1===a.length)&&!(b=a[0].collapsed)){var g=a[0];b=g.startContainer.getAscendant({td:1,th:1},!0);var e=g.endContainer.getAscendant({td:1,th:1},!0);d=CKEDITOR.tools.trim;b&&b.equals(e)&&!b.findOne("td, th, tr, tbody, table")?(g=g.cloneContents(),b=g.getFirst()?d(g.getFirst().getText())!==d(b.getText()):!0):b=!1}if(b)return!1;for(d=0;d<a.length;d++)if(b=a[d]._getTableElement(),!b)return!1;return!0}function e(a){function c(a){a=a.find("td, th");var b=[],d;for(d=0;d<a.count();d++)b.push(a.getItem(d));return b} +var b=[],d,g;for(g=0;g<a.length;g++)d=a[g]._getTableElement(),d.is&&d.is({td:1,th:1})?b.push(d):b=b.concat(c(d));return b}function k(a){a=e(a);var c="",b=[],d,g;for(g=0;g<a.length;g++)d&&!d.equals(a[g].getAscendant("tr"))?(c+=b.join("\t")+"\n",d=a[g].getAscendant("tr"),b=[]):0===g&&(d=a[g].getAscendant("tr")),b.push(a[g].getText());return c+=b.join("\t")}function d(a){var c=this.root.editor,b=c.getSelection(1);this.reset();B=!0;b.root.once("selectionchange",function(a){a.cancel()},null,null,0);b.selectRanges([a[0]]); +b=this._.cache;b.ranges=new CKEDITOR.dom.rangeList(a);b.type=CKEDITOR.SELECTION_TEXT;b.selectedElement=a[0]._getTableElement();b.selectedText=k(a);b.nativeSel=null;this.isFake=1;this.rev=A++;c._.fakeSelection=this;B=!1;this.root.fire("selectionchange")}function l(){var a=this._.fakeSelection,c;if(a){c=this.getSelection(1);var b;if(!(b=!c)&&(b=!c.isHidden())){b=a;var d=c.getRanges(),g=b.getRanges(),e=d.length&&d[0]._getTableElement()&&d[0]._getTableElement().getAscendant("table",!0),k=g.length&&g[0]._getTableElement()&& +g[0]._getTableElement().getAscendant("table",!0),n=1===d.length&&d[0]._getTableElement()&&d[0]._getTableElement().is("table"),l=1===g.length&&g[0]._getTableElement()&&g[0]._getTableElement().is("table");if(f(b.getSelectedElement()))b=!1;else{var m=1===d.length&&d[0].collapsed,g=h(d,!!CKEDITOR.env.webkit)&&h(g);e=e&&k?e.equals(k)||k.contains(e):!1;e&&(m||g)?(n&&!l&&b.selectRanges(d),b=!0):b=!1}b=!b}b&&(a.reset(),a=0)}if(!a&&(a=c||this.getSelection(1),!a||a.getType()==CKEDITOR.SELECTION_NONE))return; +this.fire("selectionCheck",a);c=this.elementPath();c.compare(this._.selectionPreviousPath)||(b=this._.selectionPreviousPath&&this._.selectionPreviousPath.blockLimit.equals(c.blockLimit),CKEDITOR.env.webkit&&!b&&(this._.previousActive=this.document.getActive()),this._.selectionPreviousPath=c,this.fire("selectionChange",{selection:a,path:c}))}function m(){y=!0;u||(b.call(this),u=CKEDITOR.tools.setTimeout(b,200,this))}function b(){u=null;y&&(CKEDITOR.tools.setTimeout(l,0,this),y=!1)}function g(a){return x(a)|| +a.type==CKEDITOR.NODE_ELEMENT&&!a.is(CKEDITOR.dtd.$empty)?!0:!1}function c(a){function c(b,d){return b&&b.type!=CKEDITOR.NODE_TEXT?a.clone()["moveToElementEdit"+(d?"End":"Start")](b):!1}if(!(a.root instanceof CKEDITOR.editable))return!1;var b=a.startContainer,d=a.getPreviousNode(g,null,b),e=a.getNextNode(g,null,b);return c(d)||c(e,1)||!(d||e||b.type==CKEDITOR.NODE_ELEMENT&&b.isBlockBoundary()&&b.getBogus())?!0:!1}function a(a){n(a,!1);var c=a.getDocument().createText(r);a.setCustomData("cke-fillingChar", +c);return c}function n(a,c){var b=a&&a.removeCustomData("cke-fillingChar");if(b){if(!1!==c){var d=a.getDocument().getSelection().getNative(),g=d&&"None"!=d.type&&d.getRangeAt(0),e=r.length;if(b.getLength()>e&&g&&g.intersectsNode(b.$)){var f=[{node:d.anchorNode,offset:d.anchorOffset},{node:d.focusNode,offset:d.focusOffset}];d.anchorNode==b.$&&d.anchorOffset>e&&(f[0].offset-=e);d.focusNode==b.$&&d.focusOffset>e&&(f[1].offset-=e)}}b.setText(w(b.getText(),1));f&&(b=a.getDocument().$,d=b.getSelection(), +b=b.createRange(),b.setStart(f[0].node,f[0].offset),b.collapse(!0),d.removeAllRanges(),d.addRange(b),d.extend(f[1].node,f[1].offset))}}function w(a,c){return c?a.replace(C,function(a,c){return c?" ":""}):a.replace(r,"")}function v(a,c){var b=c&&CKEDITOR.tools.htmlEncode(c)||"\x26nbsp;",b=CKEDITOR.dom.element.createFromHtml('\x3cdiv data-cke-hidden-sel\x3d"1" data-cke-temp\x3d"1" style\x3d"'+(CKEDITOR.env.ie&&14>CKEDITOR.env.version?"display:none":"position:fixed;top:0;left:-1000px")+'"\x3e'+b+"\x3c/div\x3e", +a.document);a.fire("lockSnapshot");a.editable().append(b);var d=a.getSelection(1),g=a.createRange(),e=d.root.on("selectionchange",function(a){a.cancel()},null,null,0);g.setStartAt(b,CKEDITOR.POSITION_AFTER_START);g.setEndAt(b,CKEDITOR.POSITION_BEFORE_END);d.selectRanges([g]);e.removeListener();a.fire("unlockSnapshot");a._.hiddenSelectionContainer=b}function t(a){var c={37:1,39:1,8:1,46:1};return function(b){var d=b.data.getKeystroke();if(c[d]){var g=a.getSelection().getRanges(),e=g[0];1==g.length&& +e.collapsed&&(d=e[38>d?"getPreviousEditableNode":"getNextEditableNode"]())&&d.type==CKEDITOR.NODE_ELEMENT&&"false"==d.getAttribute("contenteditable")&&(a.getSelection().fake(d),b.data.preventDefault(),b.cancel())}}}function p(a){for(var c=0;c<a.length;c++){var b=a[c];b.getCommonAncestor().isReadOnly()&&a.splice(c,1);if(!b.collapsed){if(b.startContainer.isReadOnly())for(var d=b.startContainer,g;d&&!((g=d.type==CKEDITOR.NODE_ELEMENT)&&d.is("body")||!d.isReadOnly());)g&&"false"==d.getAttribute("contentEditable")&& +b.setStartAfter(d),d=d.getParent();d=b.startContainer;g=b.endContainer;var e=b.startOffset,f=b.endOffset,h=b.clone();d&&d.type==CKEDITOR.NODE_TEXT&&(e>=d.getLength()?h.setStartAfter(d):h.setStartBefore(d));g&&g.type==CKEDITOR.NODE_TEXT&&(f?h.setEndAfter(g):h.setEndBefore(g));d=new CKEDITOR.dom.walker(h);d.evaluator=function(d){if(d.type==CKEDITOR.NODE_ELEMENT&&d.isReadOnly()){var g=b.clone();b.setEndBefore(d);b.collapsed&&a.splice(c--,1);d.getPosition(h.endContainer)&CKEDITOR.POSITION_CONTAINS||(g.setStartAfter(d), +g.collapsed||a.splice(c+1,0,g));return!0}return!1};d.next()}}return a}var q="function"!=typeof window.getSelection,A=1,r=CKEDITOR.tools.repeat("",7),C=new RegExp(r+"( )?","g"),B,u,y,x=CKEDITOR.dom.walker.invisible(1),z=function(){function a(c){return function(a){var b=a.editor.createRange();b.moveToClosestEditablePosition(a.selected,c)&&a.editor.getSelection().selectRanges([b]);return!1}}function c(a){return function(c){var b=c.editor,d=b.createRange(),g;if(!b.readOnly)return(g=d.moveToClosestEditablePosition(c.selected, +a))||(g=d.moveToClosestEditablePosition(c.selected,!a)),g&&b.getSelection().selectRanges([d]),b.fire("saveSnapshot"),c.selected.remove(),g||(d.moveToElementEditablePosition(b.editable()),b.getSelection().selectRanges([d])),b.fire("saveSnapshot"),!1}}var b=a(),d=a(1);return{37:b,38:b,39:d,40:d,8:c(),46:c(1)}}();CKEDITOR.on("instanceCreated",function(a){function c(){var a=b.getSelection();a&&a.removeAllRanges()}var b=a.editor;b.on("contentDom",function(){function a(){r=new CKEDITOR.dom.selection(b.getSelection()); +r.lock()}function c(){e.removeListener("mouseup",c);k.removeListener("mouseup",c);var a=CKEDITOR.document.$.selection,b=a.createRange();"None"!=a.type&&b.parentElement()&&b.parentElement().ownerDocument==g.$&&b.select()}function d(a){a=a.getRanges()[0];return a?(a=a.startContainer.getAscendant(function(a){return a.type==CKEDITOR.NODE_ELEMENT&&a.hasAttribute("contenteditable")},!0))&&"false"===a.getAttribute("contenteditable")?a:null:null}var g=b.document,e=CKEDITOR.document,f=b.editable(),h=g.getBody(), +k=g.getDocumentElement(),w=f.isInline(),p,r;CKEDITOR.env.gecko&&f.attachListener(f,"focus",function(a){a.removeListener();0!==p&&(a=b.getSelection().getNative())&&a.isCollapsed&&a.anchorNode==f.$&&(a=b.createRange(),a.moveToElementEditStart(f),a.select())},null,null,-2);f.attachListener(f,CKEDITOR.env.webkit?"DOMFocusIn":"focus",function(){p&&CKEDITOR.env.webkit&&(p=b._.previousActive&&b._.previousActive.equals(g.getActive()))&&null!=b._.previousScrollTop&&b._.previousScrollTop!=f.$.scrollTop&&(f.$.scrollTop= +b._.previousScrollTop);b.unlockSelection(p);p=0},null,null,-1);f.attachListener(f,"mousedown",function(){p=0});if(CKEDITOR.env.ie||w)q?f.attachListener(f,"beforedeactivate",a,null,null,-1):f.attachListener(b,"selectionCheck",a,null,null,-1),f.attachListener(f,CKEDITOR.env.webkit?"DOMFocusOut":"blur",function(){b.lockSelection(r);p=1},null,null,-1),f.attachListener(f,"mousedown",function(){p=0});if(CKEDITOR.env.ie&&!w){var u;f.attachListener(f,"mousedown",function(a){2==a.data.$.button&&((a=b.document.getSelection())&& +a.getType()!=CKEDITOR.SELECTION_NONE||(u=b.window.getScrollPosition()))});f.attachListener(f,"mouseup",function(a){2==a.data.$.button&&u&&(b.document.$.documentElement.scrollLeft=u.x,b.document.$.documentElement.scrollTop=u.y);u=null});if("BackCompat"!=g.$.compatMode){if(CKEDITOR.env.ie7Compat||CKEDITOR.env.ie6Compat){var A,v;k.on("mousedown",function(a){function c(a){a=a.data.$;if(A){var b=h.$.createTextRange();try{b.moveToPoint(a.clientX,a.clientY)}catch(d){}A.setEndPoint(0>v.compareEndPoints("StartToStart", +b)?"EndToEnd":"StartToStart",b);A.select()}}function b(){k.removeListener("mousemove",c);e.removeListener("mouseup",b);k.removeListener("mouseup",b);A.select()}a=a.data;if(a.getTarget().is("html")&&a.$.y<k.$.clientHeight&&a.$.x<k.$.clientWidth){A=h.$.createTextRange();try{A.moveToPoint(a.$.clientX,a.$.clientY)}catch(d){}v=A.duplicate();k.on("mousemove",c);e.on("mouseup",b);k.on("mouseup",b)}})}if(7<CKEDITOR.env.version&&11>CKEDITOR.env.version)k.on("mousedown",function(a){a.data.getTarget().is("html")&& +(e.on("mouseup",c),k.on("mouseup",c))})}}f.attachListener(f,"selectionchange",l,b);f.attachListener(f,"keyup",m,b);CKEDITOR.env.ie&&f.attachListener(f,"keydown",function(a){var c=this.getSelection(1),b=d(c);b&&!b.equals(f)&&(c.selectElement(b),a.data.preventDefault())},b);f.attachListener(f,CKEDITOR.env.webkit?"DOMFocusIn":"focus",function(){b.forceNextSelectionCheck();b.selectionChange(1)});if(w&&(CKEDITOR.env.webkit||CKEDITOR.env.gecko)){var B;f.attachListener(f,"mousedown",function(){B=1});f.attachListener(g.getDocumentElement(), +"mouseup",function(){B&&m.call(b);B=0})}else f.attachListener(CKEDITOR.env.ie?f:g.getDocumentElement(),"mouseup",m,b);CKEDITOR.env.webkit&&f.attachListener(g,"keydown",function(a){switch(a.data.getKey()){case 13:case 33:case 34:case 35:case 36:case 37:case 39:case 8:case 45:case 46:f.hasFocus&&n(f)}},null,null,-1);f.attachListener(f,"keydown",t(b),null,null,-1)});b.on("setData",function(){b.unlockSelection();CKEDITOR.env.webkit&&c()});b.on("contentDomUnload",function(){b.unlockSelection()});if(CKEDITOR.env.ie9Compat)b.on("beforeDestroy", +c,null,null,9);b.on("dataReady",function(){delete b._.fakeSelection;delete b._.hiddenSelectionContainer;b.selectionChange(1)});b.on("loadSnapshot",function(){var a=CKEDITOR.dom.walker.nodeType(CKEDITOR.NODE_ELEMENT),c=b.editable().getLast(a);c&&c.hasAttribute("data-cke-hidden-sel")&&(c.remove(),CKEDITOR.env.gecko&&(a=b.editable().getFirst(a))&&a.is("br")&&a.getAttribute("_moz_editor_bogus_node")&&a.remove())},null,null,100);b.on("key",function(a){if("wysiwyg"==b.mode){var c=b.getSelection();if(c.isFake){var d= +z[a.data.keyCode];if(d)return d({editor:b,selected:c.getSelectedElement(),selection:c,keyEvent:a})}}})});if(CKEDITOR.env.webkit)CKEDITOR.on("instanceReady",function(a){var c=a.editor;c.on("selectionChange",function(){var a=c.editable(),b=a.getCustomData("cke-fillingChar");b&&(b.getCustomData("ready")?(n(a),a.editor.fire("selectionCheck")):b.setCustomData("ready",1))},null,null,-1);c.on("beforeSetMode",function(){n(c.editable())},null,null,-1);c.on("getSnapshot",function(a){a.data&&(a.data=w(a.data))}, +c,null,20);c.on("toDataFormat",function(a){a.data.dataValue=w(a.data.dataValue)},null,null,0)});CKEDITOR.editor.prototype.selectionChange=function(a){(a?l:m).call(this)};CKEDITOR.editor.prototype.getSelection=function(a){return!this._.savedSelection&&!this._.fakeSelection||a?(a=this.editable())&&"wysiwyg"==this.mode?new CKEDITOR.dom.selection(a):null:this._.savedSelection||this._.fakeSelection};CKEDITOR.editor.prototype.lockSelection=function(a){a=a||this.getSelection(1);return a.getType()!=CKEDITOR.SELECTION_NONE? +(!a.isLocked&&a.lock(),this._.savedSelection=a,!0):!1};CKEDITOR.editor.prototype.unlockSelection=function(a){var c=this._.savedSelection;return c?(c.unlock(a),delete this._.savedSelection,!0):!1};CKEDITOR.editor.prototype.forceNextSelectionCheck=function(){delete this._.selectionPreviousPath};CKEDITOR.dom.document.prototype.getSelection=function(){return new CKEDITOR.dom.selection(this)};CKEDITOR.dom.range.prototype.select=function(){var a=this.root instanceof CKEDITOR.editable?this.root.editor.getSelection(): +new CKEDITOR.dom.selection(this.root);a.selectRanges([this]);return a};CKEDITOR.SELECTION_NONE=1;CKEDITOR.SELECTION_TEXT=2;CKEDITOR.SELECTION_ELEMENT=3;CKEDITOR.dom.selection=function(a){if(a instanceof CKEDITOR.dom.selection){var c=a;a=a.root}var b=a instanceof CKEDITOR.dom.element;this.rev=c?c.rev:A++;this.document=a instanceof CKEDITOR.dom.document?a:a.getDocument();this.root=b?a:this.document.getBody();this.isLocked=0;this._={cache:{}};if(c)return CKEDITOR.tools.extend(this._.cache,c._.cache), +this.isFake=c.isFake,this.isLocked=c.isLocked,this;a=this.getNative();var d,g;if(a)if(a.getRangeAt)d=(g=a.rangeCount&&a.getRangeAt(0))&&new CKEDITOR.dom.node(g.commonAncestorContainer);else{try{g=a.createRange()}catch(e){}d=g&&CKEDITOR.dom.element.get(g.item&&g.item(0)||g.parentElement())}if(!d||d.type!=CKEDITOR.NODE_ELEMENT&&d.type!=CKEDITOR.NODE_TEXT||!this.root.equals(d)&&!this.root.contains(d))this._.cache.type=CKEDITOR.SELECTION_NONE,this._.cache.startElement=null,this._.cache.selectedElement= +null,this._.cache.selectedText="",this._.cache.ranges=new CKEDITOR.dom.rangeList;return this};var I={img:1,hr:1,li:1,table:1,tr:1,td:1,th:1,embed:1,object:1,ol:1,ul:1,a:1,input:1,form:1,select:1,textarea:1,button:1,fieldset:1,thead:1,tfoot:1};CKEDITOR.tools.extend(CKEDITOR.dom.selection,{_removeFillingCharSequenceString:w,_createFillingCharSequenceNode:a,FILLING_CHAR_SEQUENCE:r});CKEDITOR.dom.selection.prototype={getNative:function(){return void 0!==this._.cache.nativeSel?this._.cache.nativeSel:this._.cache.nativeSel= +q?this.document.$.selection:this.document.getWindow().$.getSelection()},getType:q?function(){var a=this._.cache;if(a.type)return a.type;var c=CKEDITOR.SELECTION_NONE;try{var b=this.getNative(),d=b.type;"Text"==d&&(c=CKEDITOR.SELECTION_TEXT);"Control"==d&&(c=CKEDITOR.SELECTION_ELEMENT);b.createRange().parentElement()&&(c=CKEDITOR.SELECTION_TEXT)}catch(g){}return a.type=c}:function(){var a=this._.cache;if(a.type)return a.type;var c=CKEDITOR.SELECTION_TEXT,b=this.getNative();if(!b||!b.rangeCount)c=CKEDITOR.SELECTION_NONE; +else if(1==b.rangeCount){var b=b.getRangeAt(0),d=b.startContainer;d==b.endContainer&&1==d.nodeType&&1==b.endOffset-b.startOffset&&I[d.childNodes[b.startOffset].nodeName.toLowerCase()]&&(c=CKEDITOR.SELECTION_ELEMENT)}return a.type=c},getRanges:function(){var a=q?function(){function a(c){return(new CKEDITOR.dom.node(c)).getIndex()}var c=function(c,b){c=c.duplicate();c.collapse(b);var d=c.parentElement();if(!d.hasChildNodes())return{container:d,offset:0};for(var g=d.children,e,f,h=c.duplicate(),k=0, +n=g.length-1,l=-1,m,q;k<=n;)if(l=Math.floor((k+n)/2),e=g[l],h.moveToElementText(e),m=h.compareEndPoints("StartToStart",c),0<m)n=l-1;else if(0>m)k=l+1;else return{container:d,offset:a(e)};if(-1==l||l==g.length-1&&0>m){h.moveToElementText(d);h.setEndPoint("StartToStart",c);h=h.text.replace(/(\r\n|\r)/g,"\n").length;g=d.childNodes;if(!h)return e=g[g.length-1],e.nodeType!=CKEDITOR.NODE_TEXT?{container:d,offset:g.length}:{container:e,offset:e.nodeValue.length};for(d=g.length;0<h&&0<d;)f=g[--d],f.nodeType== +CKEDITOR.NODE_TEXT&&(q=f,h-=f.nodeValue.length);return{container:q,offset:-h}}h.collapse(0<m?!0:!1);h.setEndPoint(0<m?"StartToStart":"EndToStart",c);h=h.text.replace(/(\r\n|\r)/g,"\n").length;if(!h)return{container:d,offset:a(e)+(0<m?0:1)};for(;0<h;)try{f=e[0<m?"previousSibling":"nextSibling"],f.nodeType==CKEDITOR.NODE_TEXT&&(h-=f.nodeValue.length,q=f),e=f}catch(w){return{container:d,offset:a(e)}}return{container:q,offset:0<m?-h:q.nodeValue.length+h}};return function(){var a=this.getNative(),b=a&& +a.createRange(),d=this.getType();if(!a)return[];if(d==CKEDITOR.SELECTION_TEXT)return a=new CKEDITOR.dom.range(this.root),d=c(b,!0),a.setStart(new CKEDITOR.dom.node(d.container),d.offset),d=c(b),a.setEnd(new CKEDITOR.dom.node(d.container),d.offset),a.endContainer.getPosition(a.startContainer)&CKEDITOR.POSITION_PRECEDING&&a.endOffset<=a.startContainer.getIndex()&&a.collapse(),[a];if(d==CKEDITOR.SELECTION_ELEMENT){for(var d=[],g=0;g<b.length;g++){for(var e=b.item(g),f=e.parentNode,h=0,a=new CKEDITOR.dom.range(this.root);h< +f.childNodes.length&&f.childNodes[h]!=e;h++);a.setStart(new CKEDITOR.dom.node(f),h);a.setEnd(new CKEDITOR.dom.node(f),h+1);d.push(a)}return d}return[]}}():function(){var a=[],c,b=this.getNative();if(!b)return a;for(var d=0;d<b.rangeCount;d++){var g=b.getRangeAt(d);c=new CKEDITOR.dom.range(this.root);c.setStart(new CKEDITOR.dom.node(g.startContainer),g.startOffset);c.setEnd(new CKEDITOR.dom.node(g.endContainer),g.endOffset);a.push(c)}return a};return function(c){var b=this._.cache,d=b.ranges;d||(b.ranges= +d=new CKEDITOR.dom.rangeList(a.call(this)));return c?p(new CKEDITOR.dom.rangeList(d.slice())):d}}(),getStartElement:function(){var a=this._.cache;if(void 0!==a.startElement)return a.startElement;var c;switch(this.getType()){case CKEDITOR.SELECTION_ELEMENT:return this.getSelectedElement();case CKEDITOR.SELECTION_TEXT:var b=this.getRanges()[0];if(b){if(b.collapsed)c=b.startContainer,c.type!=CKEDITOR.NODE_ELEMENT&&(c=c.getParent());else{for(b.optimize();c=b.startContainer,b.startOffset==(c.getChildCount? +c.getChildCount():c.getLength())&&!c.isBlockBoundary();)b.setStartAfter(c);c=b.startContainer;if(c.type!=CKEDITOR.NODE_ELEMENT)return c.getParent();if((c=c.getChild(b.startOffset))&&c.type==CKEDITOR.NODE_ELEMENT)for(b=c.getFirst();b&&b.type==CKEDITOR.NODE_ELEMENT;)c=b,b=b.getFirst();else c=b.startContainer}c=c.$}}return a.startElement=c?new CKEDITOR.dom.element(c):null},getSelectedElement:function(){var a=this._.cache;if(void 0!==a.selectedElement)return a.selectedElement;var c=this,b=CKEDITOR.tools.tryThese(function(){return c.getNative().createRange().item(0)}, +function(){for(var a=c.getRanges()[0].clone(),b,d,g=2;g&&!((b=a.getEnclosedNode())&&b.type==CKEDITOR.NODE_ELEMENT&&I[b.getName()]&&(d=b));g--)a.shrink(CKEDITOR.SHRINK_ELEMENT);return d&&d.$});return a.selectedElement=b?new CKEDITOR.dom.element(b):null},getSelectedText:function(){var a=this._.cache;if(void 0!==a.selectedText)return a.selectedText;var c=this.getNative(),c=q?"Control"==c.type?"":c.createRange().text:c.toString();return a.selectedText=c},lock:function(){this.getRanges();this.getStartElement(); +this.getSelectedElement();this.getSelectedText();this._.cache.nativeSel=null;this.isLocked=1},unlock:function(a){if(this.isLocked){if(a)var c=this.getSelectedElement(),b=this.getRanges(),g=this.isFake;this.isLocked=0;this.reset();a&&(a=c||b[0]&&b[0].getCommonAncestor())&&a.getAscendant("body",1)&&(h(b)?d.call(this,b):g?this.fake(c):c?this.selectElement(c):this.selectRanges(b))}},reset:function(){this._.cache={};this.isFake=0;var a=this.root.editor;if(a&&a._.fakeSelection)if(this.rev==a._.fakeSelection.rev){delete a._.fakeSelection; +var c=a._.hiddenSelectionContainer;if(c){var b=a.checkDirty();a.fire("lockSnapshot");c.remove();a.fire("unlockSnapshot");!b&&a.resetDirty()}delete a._.hiddenSelectionContainer}else CKEDITOR.warn("selection-fake-reset");this.rev=A++},selectElement:function(a){var c=new CKEDITOR.dom.range(this.root);c.setStartBefore(a);c.setEndAfter(a);this.selectRanges([c])},selectRanges:function(b){var g=this.root.editor,e=g&&g._.hiddenSelectionContainer;this.reset();if(e)for(var e=this.root,f,k=0;k<b.length;++k)f= +b[k],f.endContainer.equals(e)&&(f.endOffset=Math.min(f.endOffset,e.getChildCount()));if(b.length)if(this.isLocked){var l=CKEDITOR.document.getActive();this.unlock();this.selectRanges(b);this.lock();l&&!l.equals(this.root)&&l.focus()}else{var m;a:{var w,p;if(1==b.length&&!(p=b[0]).collapsed&&(m=p.getEnclosedNode())&&m.type==CKEDITOR.NODE_ELEMENT&&(p=p.clone(),p.shrink(CKEDITOR.SHRINK_ELEMENT,!0),(w=p.getEnclosedNode())&&w.type==CKEDITOR.NODE_ELEMENT&&(m=w),"false"==m.getAttribute("contenteditable")))break a; +m=void 0}if(m)this.fake(m);else if(g&&g.plugins.tableselection&&CKEDITOR.plugins.tableselection.isSupportedEnvironment&&h(b)&&!B)d.call(this,b);else{if(q){w=CKEDITOR.dom.walker.whitespaces(!0);m=/\ufeff|\u00a0/;p={table:1,tbody:1,tr:1};1<b.length&&(g=b[b.length-1],b[0].setEnd(g.endContainer,g.endOffset));g=b[0];b=g.collapsed;var t,r,u;if((e=g.getEnclosedNode())&&e.type==CKEDITOR.NODE_ELEMENT&&e.getName()in I&&(!e.is("a")||!e.getText()))try{u=e.$.createControlRange();u.addElement(e.$);u.select();return}catch(A){}if(g.startContainer.type== +CKEDITOR.NODE_ELEMENT&&g.startContainer.getName()in p||g.endContainer.type==CKEDITOR.NODE_ELEMENT&&g.endContainer.getName()in p)g.shrink(CKEDITOR.NODE_ELEMENT,!0),b=g.collapsed;u=g.createBookmark();p=u.startNode;b||(l=u.endNode);u=g.document.$.body.createTextRange();u.moveToElementText(p.$);u.moveStart("character",1);l?(m=g.document.$.body.createTextRange(),m.moveToElementText(l.$),u.setEndPoint("EndToEnd",m),u.moveEnd("character",-1)):(t=p.getNext(w),r=p.hasAscendant("pre"),t=!(t&&t.getText&&t.getText().match(m))&& +(r||!p.hasPrevious()||p.getPrevious().is&&p.getPrevious().is("br")),r=g.document.createElement("span"),r.setHtml("\x26#65279;"),r.insertBefore(p),t&&g.document.createText("").insertBefore(p));g.setStartBefore(p);p.remove();b?(t?(u.moveStart("character",-1),u.select(),g.document.$.selection.clear()):u.select(),g.moveToPosition(r,CKEDITOR.POSITION_BEFORE_START),r.remove()):(g.setEndBefore(l),l.remove(),u.select())}else{l=this.getNative();if(!l)return;this.removeAllRanges();for(u=0;u<b.length;u++){if(u< +b.length-1&&(t=b[u],r=b[u+1],m=t.clone(),m.setStart(t.endContainer,t.endOffset),m.setEnd(r.startContainer,r.startOffset),!m.collapsed&&(m.shrink(CKEDITOR.NODE_ELEMENT,!0),g=m.getCommonAncestor(),m=m.getEnclosedNode(),g.isReadOnly()||m&&m.isReadOnly()))){r.setStart(t.startContainer,t.startOffset);b.splice(u--,1);continue}g=b[u];r=this.document.$.createRange();g.collapsed&&CKEDITOR.env.webkit&&c(g)&&(m=a(this.root),g.insertNode(m),(t=m.getNext())&&!m.getPrevious()&&t.type==CKEDITOR.NODE_ELEMENT&&"br"== +t.getName()?(n(this.root),g.moveToPosition(t,CKEDITOR.POSITION_BEFORE_START)):g.moveToPosition(m,CKEDITOR.POSITION_AFTER_END));r.setStart(g.startContainer.$,g.startOffset);try{r.setEnd(g.endContainer.$,g.endOffset)}catch(v){if(0<=v.toString().indexOf("NS_ERROR_ILLEGAL_VALUE"))g.collapse(1),r.setEnd(g.endContainer.$,g.endOffset);else throw v;}l.addRange(r)}}this.reset();this.root.fire("selectionchange")}}},fake:function(a,c){var b=this.root.editor;void 0===c&&a.hasAttribute("aria-label")&&(c=a.getAttribute("aria-label")); +this.reset();v(b,c);var d=this._.cache,g=new CKEDITOR.dom.range(this.root);g.setStartBefore(a);g.setEndAfter(a);d.ranges=new CKEDITOR.dom.rangeList(g);d.selectedElement=d.startElement=a;d.type=CKEDITOR.SELECTION_ELEMENT;d.selectedText=d.nativeSel=null;this.isFake=1;this.rev=A++;b._.fakeSelection=this;this.root.fire("selectionchange")},isHidden:function(){var a=this.getCommonAncestor();a&&a.type==CKEDITOR.NODE_TEXT&&(a=a.getParent());return!(!a||!a.data("cke-hidden-sel"))},isInTable:function(a){return h(this.getRanges(), +a)},isCollapsed:function(){var a=this.getRanges();return 1===a.length&&a[0].collapsed},createBookmarks:function(a){a=this.getRanges().createBookmarks(a);this.isFake&&(a.isFake=1);return a},createBookmarks2:function(a){a=this.getRanges().createBookmarks2(a);this.isFake&&(a.isFake=1);return a},selectBookmarks:function(a){for(var c=[],b,d=0;d<a.length;d++){var g=new CKEDITOR.dom.range(this.root);g.moveToBookmark(a[d]);c.push(g)}a.isFake&&(b=h(c)?c[0]._getTableElement():c[0].getEnclosedNode(),b&&b.type== +CKEDITOR.NODE_ELEMENT||(CKEDITOR.warn("selection-not-fake"),a.isFake=0));a.isFake&&!h(c)?this.fake(b):this.selectRanges(c);return this},getCommonAncestor:function(){var a=this.getRanges();return a.length?a[0].startContainer.getCommonAncestor(a[a.length-1].endContainer):null},scrollIntoView:function(){this.type!=CKEDITOR.SELECTION_NONE&&this.getRanges()[0].scrollIntoView()},removeAllRanges:function(){if(this.getType()!=CKEDITOR.SELECTION_NONE){var a=this.getNative();try{a&&a[q?"empty":"removeAllRanges"]()}catch(c){}this.reset()}}}}(), +"use strict",CKEDITOR.STYLE_BLOCK=1,CKEDITOR.STYLE_INLINE=2,CKEDITOR.STYLE_OBJECT=3,function(){function f(a,c){for(var b,d;(a=a.getParent())&&!a.equals(c);)if(a.getAttribute("data-nostyle"))b=a;else if(!d){var g=a.getAttribute("contentEditable");"false"==g?b=a:"true"==g&&(d=1)}return b}function h(a,c,b,d){return(a.getPosition(c)|d)==d&&(!b.childRule||b.childRule(a))}function e(a){var c=a.document;if(a.collapsed)c=A(this,c),a.insertNode(c),a.moveToPosition(c,CKEDITOR.POSITION_BEFORE_END);else{var b= +this.element,g=this._.definition,k,n=g.ignoreReadonly,l=n||g.includeReadonly;null==l&&(l=a.root.getCustomData("cke_includeReadonly"));var m=CKEDITOR.dtd[b];m||(k=!0,m=CKEDITOR.dtd.span);a.enlarge(CKEDITOR.ENLARGE_INLINE,1);a.trim();var q=a.createBookmark(),p=q.startNode,w=q.endNode,r=p,u;if(!n){var v=a.getCommonAncestor(),n=f(p,v),v=f(w,v);n&&(r=n.getNextSourceNode(!0));v&&(w=v)}for(r.getPosition(w)==CKEDITOR.POSITION_FOLLOWING&&(r=0);r;){n=!1;if(r.equals(w))r=null,n=!0;else{var P=r.type==CKEDITOR.NODE_ELEMENT? +r.getName():null,v=P&&"false"==r.getAttribute("contentEditable"),B=P&&r.getAttribute("data-nostyle");if(P&&r.data("cke-bookmark")){r=r.getNextSourceNode(!0);continue}if(v&&l&&CKEDITOR.dtd.$block[P])for(var C=r,y=d(C),z=void 0,x=y.length,ea=0,C=x&&new CKEDITOR.dom.range(C.getDocument());ea<x;++ea){var z=y[ea],I=CKEDITOR.filter.instances[z.data("cke-filter")];if(I?I.check(this):1)C.selectNodeContents(z),e.call(this,C)}y=P?!m[P]||B?0:v&&!l?0:h(r,w,g,L):1;if(y)if(z=r.getParent(),y=g,x=b,ea=k,!z||!(z.getDtd()|| +CKEDITOR.dtd.span)[x]&&!ea||y.parentRule&&!y.parentRule(z))n=!0;else{if(u||P&&CKEDITOR.dtd.$removeEmpty[P]&&(r.getPosition(w)|L)!=L||(u=a.clone(),u.setStartBefore(r)),P=r.type,P==CKEDITOR.NODE_TEXT||v||P==CKEDITOR.NODE_ELEMENT&&!r.getChildCount()){for(var P=r,F;(n=!P.getNext(H))&&(F=P.getParent(),m[F.getName()])&&h(F,p,g,O);)P=F;u.setEndAfter(P)}}else n=!0;r=r.getNextSourceNode(B||v)}if(n&&u&&!u.collapsed){for(var n=A(this,c),v=n.hasAttributes(),B=u.getCommonAncestor(),P={},y={},z={},x={},fa,G,E;n&& +B;){if(B.getName()==b){for(fa in g.attributes)!x[fa]&&(E=B.getAttribute(G))&&(n.getAttribute(fa)==E?y[fa]=1:x[fa]=1);for(G in g.styles)!z[G]&&(E=B.getStyle(G))&&(n.getStyle(G)==E?P[G]=1:z[G]=1)}B=B.getParent()}for(fa in y)n.removeAttribute(fa);for(G in P)n.removeStyle(G);v&&!n.hasAttributes()&&(n=null);n?(u.extractContents().appendTo(n),u.insertNode(n),t.call(this,n),n.mergeSiblings(),CKEDITOR.env.ie||n.$.normalize()):(n=new CKEDITOR.dom.element("span"),u.extractContents().appendTo(n),u.insertNode(n), +t.call(this,n),n.remove(!0));u=null}}a.moveToBookmark(q);a.shrink(CKEDITOR.SHRINK_TEXT);a.shrink(CKEDITOR.NODE_ELEMENT,!0)}}function k(a){function c(){for(var a=new CKEDITOR.dom.elementPath(d.getParent()),b=new CKEDITOR.dom.elementPath(l.getParent()),g=null,e=null,f=0;f<a.elements.length;f++){var h=a.elements[f];if(h==a.block||h==a.blockLimit)break;m.checkElementRemovable(h,!0)&&(g=h)}for(f=0;f<b.elements.length;f++){h=b.elements[f];if(h==b.block||h==b.blockLimit)break;m.checkElementRemovable(h,!0)&& +(e=h)}e&&l.breakParent(e);g&&d.breakParent(g)}a.enlarge(CKEDITOR.ENLARGE_INLINE,1);var b=a.createBookmark(),d=b.startNode,g=this._.definition.alwaysRemoveElement;if(a.collapsed){for(var e=new CKEDITOR.dom.elementPath(d.getParent(),a.root),f,h=0,k;h<e.elements.length&&(k=e.elements[h])&&k!=e.block&&k!=e.blockLimit;h++)if(this.checkElementRemovable(k)){var n;!g&&a.collapsed&&(a.checkBoundaryOfElement(k,CKEDITOR.END)||(n=a.checkBoundaryOfElement(k,CKEDITOR.START)))?(f=k,f.match=n?"start":"end"):(k.mergeSiblings(), +k.is(this.element)?v.call(this,k):p(k,B(this)[k.getName()]))}if(f){g=d;for(h=0;;h++){k=e.elements[h];if(k.equals(f))break;else if(k.match)continue;else k=k.clone();k.append(g);g=k}g["start"==f.match?"insertBefore":"insertAfter"](f)}}else{var l=b.endNode,m=this;c();for(e=d;!e.equals(l);)f=e.getNextSourceNode(),e.type==CKEDITOR.NODE_ELEMENT&&this.checkElementRemovable(e)&&(e.getName()==this.element?v.call(this,e):p(e,B(this)[e.getName()]),f.type==CKEDITOR.NODE_ELEMENT&&f.contains(d)&&(c(),f=d.getNext())), +e=f}a.moveToBookmark(b);a.shrink(CKEDITOR.NODE_ELEMENT,!0)}function d(a){var c=[];a.forEach(function(a){if("true"==a.getAttribute("contenteditable"))return c.push(a),!1},CKEDITOR.NODE_ELEMENT,!0);return c}function l(a){var c=a.getEnclosedNode()||a.getCommonAncestor(!1,!0);(a=(new CKEDITOR.dom.elementPath(c,a.root)).contains(this.element,1))&&!a.isReadOnly()&&r(a,this)}function m(a){var c=a.getCommonAncestor(!0,!0);if(a=(new CKEDITOR.dom.elementPath(c,a.root)).contains(this.element,1)){var c=this._.definition, +b=c.attributes;if(b)for(var d in b)a.removeAttribute(d,b[d]);if(c.styles)for(var g in c.styles)c.styles.hasOwnProperty(g)&&a.removeStyle(g)}}function b(a){var b=a.createBookmark(!0),d=a.createIterator();d.enforceRealBlocks=!0;this._.enterMode&&(d.enlargeBr=this._.enterMode!=CKEDITOR.ENTER_BR);for(var g,e=a.document,f;g=d.getNextParagraph();)!g.isReadOnly()&&(d.activeFilter?d.activeFilter.check(this):1)&&(f=A(this,e,g),c(g,f));a.moveToBookmark(b)}function g(a){var b=a.createBookmark(1),d=a.createIterator(); +d.enforceRealBlocks=!0;d.enlargeBr=this._.enterMode!=CKEDITOR.ENTER_BR;for(var g,e;g=d.getNextParagraph();)this.checkElementRemovable(g)&&(g.is("pre")?((e=this._.enterMode==CKEDITOR.ENTER_BR?null:a.document.createElement(this._.enterMode==CKEDITOR.ENTER_P?"p":"div"))&&g.copyAttributes(e),c(g,e)):v.call(this,g));a.moveToBookmark(b)}function c(c,b){var d=!b;d&&(b=c.getDocument().createElement("div"),c.copyAttributes(b));var g=b&&b.is("pre"),e=c.is("pre"),f=!g&&e;if(g&&!e){e=b;(f=c.getBogus())&&f.remove(); +f=c.getHtml();f=n(f,/(?:^[ \t\n\r]+)|(?:[ \t\n\r]+$)/g,"");f=f.replace(/[ \t\r\n]*(<br[^>]*>)[ \t\r\n]*/gi,"$1");f=f.replace(/([ \t\n\r]+| )/g," ");f=f.replace(/<br\b[^>]*>/gi,"\n");if(CKEDITOR.env.ie){var h=c.getDocument().createElement("div");h.append(e);e.$.outerHTML="\x3cpre\x3e"+f+"\x3c/pre\x3e";e.copyAttributes(h.getFirst());e=h.getFirst().remove()}else e.setHtml(f);b=e}else f?b=w(d?[c.getHtml()]:a(c),b):c.moveChildren(b);b.replace(c);if(g){var d=b,k;(k=d.getPrevious(G))&&k.type==CKEDITOR.NODE_ELEMENT&& +k.is("pre")&&(g=n(k.getHtml(),/\n$/,"")+"\n\n"+n(d.getHtml(),/^\n/,""),CKEDITOR.env.ie?d.$.outerHTML="\x3cpre\x3e"+g+"\x3c/pre\x3e":d.setHtml(g),k.remove())}else d&&q(b)}function a(a){var c=[];n(a.getOuterHtml(),/(\S\s*)\n(?:\s|(<span[^>]+data-cke-bookmark.*?\/span>))*\n(?!$)/gi,function(a,c,b){return c+"\x3c/pre\x3e"+b+"\x3cpre\x3e"}).replace(/<pre\b.*?>([\s\S]*?)<\/pre>/gi,function(a,b){c.push(b)});return c}function n(a,c,b){var d="",g="";a=a.replace(/(^<span[^>]+data-cke-bookmark.*?\/span>)|(<span[^>]+data-cke-bookmark.*?\/span>$)/gi, +function(a,c,b){c&&(d=c);b&&(g=b);return""});return d+a.replace(c,b)+g}function w(a,c){var b;1<a.length&&(b=new CKEDITOR.dom.documentFragment(c.getDocument()));for(var d=0;d<a.length;d++){var g=a[d],g=g.replace(/(\r\n|\r)/g,"\n"),g=n(g,/^[ \t]*\n/,""),g=n(g,/\n$/,""),g=n(g,/^[ \t]+|[ \t]+$/g,function(a,c){return 1==a.length?"\x26nbsp;":c?" "+CKEDITOR.tools.repeat("\x26nbsp;",a.length-1):CKEDITOR.tools.repeat("\x26nbsp;",a.length-1)+" "}),g=g.replace(/\n/g,"\x3cbr\x3e"),g=g.replace(/[ \t]{2,}/g,function(a){return CKEDITOR.tools.repeat("\x26nbsp;", +a.length-1)+" "});if(b){var e=c.clone();e.setHtml(g);b.append(e)}else c.setHtml(g)}return b||c}function v(a,c){var b=this._.definition,d=b.attributes,b=b.styles,g=B(this)[a.getName()],e=CKEDITOR.tools.isEmpty(d)&&CKEDITOR.tools.isEmpty(b),f;for(f in d)if("class"!=f&&!this._.definition.fullMatch||a.getAttribute(f)==u(f,d[f]))c&&"data-"==f.slice(0,5)||(e=a.hasAttribute(f),a.removeAttribute(f));for(var h in b)this._.definition.fullMatch&&a.getStyle(h)!=u(h,b[h],!0)||(e=e||!!a.getStyle(h),a.removeStyle(h)); +p(a,g,z[a.getName()]);e&&(this._.definition.alwaysRemoveElement?q(a,1):!CKEDITOR.dtd.$block[a.getName()]||this._.enterMode==CKEDITOR.ENTER_BR&&!a.hasAttributes()?q(a):a.renameNode(this._.enterMode==CKEDITOR.ENTER_P?"p":"div"))}function t(a){for(var c=B(this),b=a.getElementsByTag(this.element),d,g=b.count();0<=--g;)d=b.getItem(g),d.isReadOnly()||v.call(this,d,!0);for(var e in c)if(e!=this.element)for(b=a.getElementsByTag(e),g=b.count()-1;0<=g;g--)d=b.getItem(g),d.isReadOnly()||p(d,c[e])}function p(a, +c,b){if(c=c&&c.attributes)for(var d=0;d<c.length;d++){var g=c[d][0],e;if(e=a.getAttribute(g)){var f=c[d][1];(null===f||f.test&&f.test(e)||"string"==typeof f&&e==f)&&a.removeAttribute(g)}}b||q(a)}function q(a,c){if(!a.hasAttributes()||c)if(CKEDITOR.dtd.$block[a.getName()]){var b=a.getPrevious(G),d=a.getNext(G);!b||b.type!=CKEDITOR.NODE_TEXT&&b.isBlockBoundary({br:1})||a.append("br",1);!d||d.type!=CKEDITOR.NODE_TEXT&&d.isBlockBoundary({br:1})||a.append("br");a.remove(!0)}else b=a.getFirst(),d=a.getLast(), +a.remove(!0),b&&(b.type==CKEDITOR.NODE_ELEMENT&&b.mergeSiblings(),d&&!b.equals(d)&&d.type==CKEDITOR.NODE_ELEMENT&&d.mergeSiblings())}function A(a,c,b){var d;d=a.element;"*"==d&&(d="span");d=new CKEDITOR.dom.element(d,c);b&&b.copyAttributes(d);d=r(d,a);c.getCustomData("doc_processing_style")&&d.hasAttribute("id")?d.removeAttribute("id"):c.setCustomData("doc_processing_style",1);return d}function r(a,c){var b=c._.definition,d=b.attributes,b=CKEDITOR.style.getStyleText(b);if(d)for(var g in d)a.setAttribute(g, +d[g]);b&&a.setAttribute("style",b);a.getDocument().removeCustomData("doc_processing_style");return a}function C(a,c){for(var b in a)a[b]=a[b].replace(E,function(a,b){return c[b]})}function B(a){if(a._.overrides)return a._.overrides;var c=a._.overrides={},b=a._.definition.overrides;if(b){CKEDITOR.tools.isArray(b)||(b=[b]);for(var d=0;d<b.length;d++){var g=b[d],e,f;"string"==typeof g?e=g.toLowerCase():(e=g.element?g.element.toLowerCase():a.element,f=g.attributes);g=c[e]||(c[e]={});if(f){var g=g.attributes= +g.attributes||[],h;for(h in f)g.push([h.toLowerCase(),f[h]])}}}return c}function u(a,c,b){var d=new CKEDITOR.dom.element("span");d[b?"setStyle":"setAttribute"](a,c);return d[b?"getStyle":"getAttribute"](a)}function y(a,c){function b(a,c){return"font-family"==c.toLowerCase()?a.replace(/["']/g,""):a}"string"==typeof a&&(a=CKEDITOR.tools.parseCssText(a));"string"==typeof c&&(c=CKEDITOR.tools.parseCssText(c,!0));for(var d in a)if(!(d in c)||b(c[d],d)!=b(a[d],d)&&"inherit"!=a[d]&&"inherit"!=c[d])return!1; +return!0}function x(a,c,b){var d=a.getRanges();c=c?this.removeFromRange:this.applyToRange;var g,e;if(a.isFake&&a.isInTable())for(g=[],e=0;e<d.length;e++)g.push(d[e].clone());for(var f=d.createIterator();e=f.getNextRange();)c.call(this,e,b);a.selectRanges(g||d)}var z={address:1,div:1,h1:1,h2:1,h3:1,h4:1,h5:1,h6:1,p:1,pre:1,section:1,header:1,footer:1,nav:1,article:1,aside:1,figure:1,dialog:1,hgroup:1,time:1,meter:1,menu:1,command:1,keygen:1,output:1,progress:1,details:1,datagrid:1,datalist:1},I={a:1, +blockquote:1,embed:1,hr:1,img:1,li:1,object:1,ol:1,table:1,td:1,tr:1,th:1,ul:1,dl:1,dt:1,dd:1,form:1,audio:1,video:1},F=/\s*(?:;\s*|$)/,E=/#\((.+?)\)/g,H=CKEDITOR.dom.walker.bookmark(0,1),G=CKEDITOR.dom.walker.whitespaces(1);CKEDITOR.style=function(a,c){if("string"==typeof a.type)return new CKEDITOR.style.customHandlers[a.type](a);var b=a.attributes;b&&b.style&&(a.styles=CKEDITOR.tools.extend({},a.styles,CKEDITOR.tools.parseCssText(b.style)),delete b.style);c&&(a=CKEDITOR.tools.clone(a),C(a.attributes, +c),C(a.styles,c));b=this.element=a.element?"string"==typeof a.element?a.element.toLowerCase():a.element:"*";this.type=a.type||(z[b]?CKEDITOR.STYLE_BLOCK:I[b]?CKEDITOR.STYLE_OBJECT:CKEDITOR.STYLE_INLINE);"object"==typeof this.element&&(this.type=CKEDITOR.STYLE_OBJECT);this._={definition:a}};CKEDITOR.style.prototype={apply:function(a){if(a instanceof CKEDITOR.dom.document)return x.call(this,a.getSelection());if(this.checkApplicable(a.elementPath(),a)){var c=this._.enterMode;c||(this._.enterMode=a.activeEnterMode); +x.call(this,a.getSelection(),0,a);this._.enterMode=c}},remove:function(a){if(a instanceof CKEDITOR.dom.document)return x.call(this,a.getSelection(),1);if(this.checkApplicable(a.elementPath(),a)){var c=this._.enterMode;c||(this._.enterMode=a.activeEnterMode);x.call(this,a.getSelection(),1,a);this._.enterMode=c}},applyToRange:function(a){this.applyToRange=this.type==CKEDITOR.STYLE_INLINE?e:this.type==CKEDITOR.STYLE_BLOCK?b:this.type==CKEDITOR.STYLE_OBJECT?l:null;return this.applyToRange(a)},removeFromRange:function(a){this.removeFromRange= +this.type==CKEDITOR.STYLE_INLINE?k:this.type==CKEDITOR.STYLE_BLOCK?g:this.type==CKEDITOR.STYLE_OBJECT?m:null;return this.removeFromRange(a)},applyToObject:function(a){r(a,this)},checkActive:function(a,c){switch(this.type){case CKEDITOR.STYLE_BLOCK:return this.checkElementRemovable(a.block||a.blockLimit,!0,c);case CKEDITOR.STYLE_OBJECT:case CKEDITOR.STYLE_INLINE:for(var b=a.elements,d=0,g;d<b.length;d++)if(g=b[d],this.type!=CKEDITOR.STYLE_INLINE||g!=a.block&&g!=a.blockLimit){if(this.type==CKEDITOR.STYLE_OBJECT){var e= +g.getName();if(!("string"==typeof this.element?e==this.element:e in this.element))continue}if(this.checkElementRemovable(g,!0,c))return!0}}return!1},checkApplicable:function(a,c,b){c&&c instanceof CKEDITOR.filter&&(b=c);if(b&&!b.check(this))return!1;switch(this.type){case CKEDITOR.STYLE_OBJECT:return!!a.contains(this.element);case CKEDITOR.STYLE_BLOCK:return!!a.blockLimit.getDtd()[this.element]}return!0},checkElementMatch:function(a,c){var b=this._.definition;if(!a||!b.ignoreReadonly&&a.isReadOnly())return!1; +var d=a.getName();if("string"==typeof this.element?d==this.element:d in this.element){if(!c&&!a.hasAttributes())return!0;if(d=b._AC)b=d;else{var d={},g=0,e=b.attributes;if(e)for(var f in e)g++,d[f]=e[f];if(f=CKEDITOR.style.getStyleText(b))d.style||g++,d.style=f;d._length=g;b=b._AC=d}if(b._length){for(var h in b)if("_length"!=h)if(d=a.getAttribute(h)||"","style"==h?y(b[h],d):b[h]==d){if(!c)return!0}else if(c)return!1;if(c)return!0}else return!0}return!1},checkElementRemovable:function(a,c,b){if(this.checkElementMatch(a, +c,b))return!0;if(c=B(this)[a.getName()]){var d;if(!(c=c.attributes))return!0;for(b=0;b<c.length;b++)if(d=c[b][0],d=a.getAttribute(d)){var g=c[b][1];if(null===g)return!0;if("string"==typeof g){if(d==g)return!0}else if(g.test(d))return!0}}return!1},buildPreview:function(a){var c=this._.definition,b=[],d=c.element;"bdo"==d&&(d="span");var b=["\x3c",d],g=c.attributes;if(g)for(var e in g)b.push(" ",e,'\x3d"',g[e],'"');(g=CKEDITOR.style.getStyleText(c))&&b.push(' style\x3d"',g,'"');b.push("\x3e",a||c.name, +"\x3c/",d,"\x3e");return b.join("")},getDefinition:function(){return this._.definition}};CKEDITOR.style.getStyleText=function(a){var c=a._ST;if(c)return c;var c=a.styles,b=a.attributes&&a.attributes.style||"",d="";b.length&&(b=b.replace(F,";"));for(var g in c){var e=c[g],f=(g+":"+e).replace(F,";");"inherit"==e?d+=f:b+=f}b.length&&(b=CKEDITOR.tools.normalizeCssText(b,!0));return a._ST=b+d};CKEDITOR.style.customHandlers={};CKEDITOR.style.addCustomHandler=function(a){var c=function(a){this._={definition:a}; +this.setup&&this.setup(a)};c.prototype=CKEDITOR.tools.extend(CKEDITOR.tools.prototypedCopy(CKEDITOR.style.prototype),{assignedTo:CKEDITOR.STYLE_OBJECT},a,!0);return this.customHandlers[a.type]=c};var L=CKEDITOR.POSITION_PRECEDING|CKEDITOR.POSITION_IDENTICAL|CKEDITOR.POSITION_IS_CONTAINED,O=CKEDITOR.POSITION_FOLLOWING|CKEDITOR.POSITION_IDENTICAL|CKEDITOR.POSITION_IS_CONTAINED}(),CKEDITOR.styleCommand=function(f,h){this.requiredContent=this.allowedContent=this.style=f;CKEDITOR.tools.extend(this,h,!0)}, +CKEDITOR.styleCommand.prototype.exec=function(f){f.focus();this.state==CKEDITOR.TRISTATE_OFF?f.applyStyle(this.style):this.state==CKEDITOR.TRISTATE_ON&&f.removeStyle(this.style)},CKEDITOR.stylesSet=new CKEDITOR.resourceManager("","stylesSet"),CKEDITOR.addStylesSet=CKEDITOR.tools.bind(CKEDITOR.stylesSet.add,CKEDITOR.stylesSet),CKEDITOR.loadStylesSet=function(f,h,e){CKEDITOR.stylesSet.addExternal(f,h,"");CKEDITOR.stylesSet.load(f,e)},CKEDITOR.tools.extend(CKEDITOR.editor.prototype,{attachStyleStateChange:function(f, +h){var e=this._.styleStateChangeCallbacks;e||(e=this._.styleStateChangeCallbacks=[],this.on("selectionChange",function(f){for(var d=0;d<e.length;d++){var h=e[d],m=h.style.checkActive(f.data.path,this)?CKEDITOR.TRISTATE_ON:CKEDITOR.TRISTATE_OFF;h.fn.call(this,m)}}));e.push({style:f,fn:h})},applyStyle:function(f){f.apply(this)},removeStyle:function(f){f.remove(this)},getStylesSet:function(f){if(this._.stylesDefinitions)f(this._.stylesDefinitions);else{var h=this,e=h.config.stylesCombo_stylesSet||h.config.stylesSet; +if(!1===e)f(null);else if(e instanceof Array)h._.stylesDefinitions=e,f(e);else{e||(e="default");var e=e.split(":"),k=e[0];CKEDITOR.stylesSet.addExternal(k,e[1]?e.slice(1).join(":"):CKEDITOR.getUrl("styles.js"),"");CKEDITOR.stylesSet.load(k,function(d){h._.stylesDefinitions=d[k];f(h._.stylesDefinitions)})}}}}),CKEDITOR.dom.comment=function(f,h){"string"==typeof f&&(f=(h?h.$:document).createComment(f));CKEDITOR.dom.domObject.call(this,f)},CKEDITOR.dom.comment.prototype=new CKEDITOR.dom.node,CKEDITOR.tools.extend(CKEDITOR.dom.comment.prototype, +{type:CKEDITOR.NODE_COMMENT,getOuterHtml:function(){return"\x3c!--"+this.$.nodeValue+"--\x3e"}}),"use strict",function(){var f={},h={},e;for(e in CKEDITOR.dtd.$blockLimit)e in CKEDITOR.dtd.$list||(f[e]=1);for(e in CKEDITOR.dtd.$block)e in CKEDITOR.dtd.$blockLimit||e in CKEDITOR.dtd.$empty||(h[e]=1);CKEDITOR.dom.elementPath=function(e,d){var l=null,m=null,b=[],g=e,c;d=d||e.getDocument().getBody();g||(g=d);do if(g.type==CKEDITOR.NODE_ELEMENT){b.push(g);if(!this.lastElement&&(this.lastElement=g,g.is(CKEDITOR.dtd.$object)|| +"false"==g.getAttribute("contenteditable")))continue;if(g.equals(d))break;if(!m&&(c=g.getName(),"true"==g.getAttribute("contenteditable")?m=g:!l&&h[c]&&(l=g),f[c])){if(c=!l&&"div"==c){a:{c=g.getChildren();for(var a=0,n=c.count();a<n;a++){var w=c.getItem(a);if(w.type==CKEDITOR.NODE_ELEMENT&&CKEDITOR.dtd.$block[w.getName()]){c=!0;break a}}c=!1}c=!c}c?l=g:m=g}}while(g=g.getParent());m||(m=d);this.block=l;this.blockLimit=m;this.root=d;this.elements=b}}(),CKEDITOR.dom.elementPath.prototype={compare:function(f){var h= +this.elements;f=f&&f.elements;if(!f||h.length!=f.length)return!1;for(var e=0;e<h.length;e++)if(!h[e].equals(f[e]))return!1;return!0},contains:function(f,h,e){var k=0,d;"string"==typeof f&&(d=function(b){return b.getName()==f});f instanceof CKEDITOR.dom.element?d=function(b){return b.equals(f)}:CKEDITOR.tools.isArray(f)?d=function(b){return-1<CKEDITOR.tools.indexOf(f,b.getName())}:"function"==typeof f?d=f:"object"==typeof f&&(d=function(b){return b.getName()in f});var l=this.elements,m=l.length;h&& +(e?k+=1:--m);e&&(l=Array.prototype.slice.call(l,0),l.reverse());for(;k<m;k++)if(d(l[k]))return l[k];return null},isContextFor:function(f){var h;return f in CKEDITOR.dtd.$block?(h=this.contains(CKEDITOR.dtd.$intermediate)||this.root.equals(this.block)&&this.block||this.blockLimit,!!h.getDtd()[f]):!0},direction:function(){return(this.block||this.blockLimit||this.root).getDirection(1)}},CKEDITOR.dom.text=function(f,h){"string"==typeof f&&(f=(h?h.$:document).createTextNode(f));this.$=f},CKEDITOR.dom.text.prototype= +new CKEDITOR.dom.node,CKEDITOR.tools.extend(CKEDITOR.dom.text.prototype,{type:CKEDITOR.NODE_TEXT,getLength:function(){return this.$.nodeValue.length},getText:function(){return this.$.nodeValue},setText:function(f){this.$.nodeValue=f},split:function(f){var h=this.$.parentNode,e=h.childNodes.length,k=this.getLength(),d=this.getDocument(),l=new CKEDITOR.dom.text(this.$.splitText(f),d);h.childNodes.length==e&&(f>=k?(l=d.createText(""),l.insertAfter(this)):(f=d.createText(""),f.insertAfter(l),f.remove())); +return l},substring:function(f,h){return"number"!=typeof h?this.$.nodeValue.substr(f):this.$.nodeValue.substring(f,h)}}),function(){function f(e,f,d){var h=e.serializable,m=f[d?"endContainer":"startContainer"],b=d?"endOffset":"startOffset",g=h?f.document.getById(e.startNode):e.startNode;e=h?f.document.getById(e.endNode):e.endNode;m.equals(g.getPrevious())?(f.startOffset=f.startOffset-m.getLength()-e.getPrevious().getLength(),m=e.getNext()):m.equals(e.getPrevious())&&(f.startOffset-=m.getLength(), +m=e.getNext());m.equals(g.getParent())&&f[b]++;m.equals(e.getParent())&&f[b]++;f[d?"endContainer":"startContainer"]=m;return f}CKEDITOR.dom.rangeList=function(e){if(e instanceof CKEDITOR.dom.rangeList)return e;e?e instanceof CKEDITOR.dom.range&&(e=[e]):e=[];return CKEDITOR.tools.extend(e,h)};var h={createIterator:function(){var e=this,f=CKEDITOR.dom.walker.bookmark(),d=[],h;return{getNextRange:function(m){h=void 0===h?0:h+1;var b=e[h];if(b&&1<e.length){if(!h)for(var g=e.length-1;0<=g;g--)d.unshift(e[g].createBookmark(!0)); +if(m)for(var c=0;e[h+c+1];){var a=b.document;m=0;g=a.getById(d[c].endNode);for(a=a.getById(d[c+1].startNode);;){g=g.getNextSourceNode(!1);if(a.equals(g))m=1;else if(f(g)||g.type==CKEDITOR.NODE_ELEMENT&&g.isBlockBoundary())continue;break}if(!m)break;c++}for(b.moveToBookmark(d.shift());c--;)g=e[++h],g.moveToBookmark(d.shift()),b.setEnd(g.endContainer,g.endOffset)}return b}}},createBookmarks:function(e){for(var h=[],d,l=0;l<this.length;l++){h.push(d=this[l].createBookmark(e,!0));for(var m=l+1;m<this.length;m++)this[m]= +f(d,this[m]),this[m]=f(d,this[m],!0)}return h},createBookmarks2:function(e){for(var f=[],d=0;d<this.length;d++)f.push(this[d].createBookmark2(e));return f},moveToBookmarks:function(e){for(var f=0;f<this.length;f++)this[f].moveToBookmark(e[f])}}}(),function(){function f(){return CKEDITOR.getUrl(CKEDITOR.skinName.split(",")[1]||"skins/"+CKEDITOR.skinName.split(",")[0]+"/")}function h(c){var a=CKEDITOR.skin["ua_"+c],b=CKEDITOR.env;if(a)for(var a=a.split(",").sort(function(a,c){return a>c?-1:1}),d=0, +g;d<a.length;d++)if(g=a[d],b.ie&&(g.replace(/^ie/,"")==b.version||b.quirks&&"iequirks"==g)&&(g="ie"),b[g]){c+="_"+a[d];break}return CKEDITOR.getUrl(f()+c+".css")}function e(c,a){l[c]||(CKEDITOR.document.appendStyleSheet(h(c)),l[c]=1);a&&a()}function k(c){var a=c.getById(m);a||(a=c.getHead().append("style"),a.setAttribute("id",m),a.setAttribute("type","text/css"));return a}function d(c,a,b){var d,g,e;if(CKEDITOR.env.webkit)for(a=a.split("}").slice(0,-1),g=0;g<a.length;g++)a[g]=a[g].split("{");for(var f= +0;f<c.length;f++)if(CKEDITOR.env.webkit)for(g=0;g<a.length;g++){e=a[g][1];for(d=0;d<b.length;d++)e=e.replace(b[d][0],b[d][1]);c[f].$.sheet.addRule(a[g][0],e)}else{e=a;for(d=0;d<b.length;d++)e=e.replace(b[d][0],b[d][1]);CKEDITOR.env.ie&&11>CKEDITOR.env.version?c[f].$.styleSheet.cssText+=e:c[f].$.innerHTML+=e}}var l={};CKEDITOR.skin={path:f,loadPart:function(c,a){CKEDITOR.skin.name!=CKEDITOR.skinName.split(",")[0]?CKEDITOR.scriptLoader.load(CKEDITOR.getUrl(f()+"skin.js"),function(){e(c,a)}):e(c,a)}, +getPath:function(c){return CKEDITOR.getUrl(h(c))},icons:{},addIcon:function(c,a,b,d){c=c.toLowerCase();this.icons[c]||(this.icons[c]={path:a,offset:b||0,bgsize:d||"16px"})},getIconStyle:function(c,a,b,d,g){var e;c&&(c=c.toLowerCase(),a&&(e=this.icons[c+"-rtl"]),e||(e=this.icons[c]));c=b||e&&e.path||"";d=d||e&&e.offset;g=g||e&&e.bgsize||"16px";c&&(c=c.replace(/'/g,"\\'"));return c&&"background-image:url('"+CKEDITOR.getUrl(c)+"');background-position:0 "+d+"px;background-size:"+g+";"}};CKEDITOR.tools.extend(CKEDITOR.editor.prototype, +{getUiColor:function(){return this.uiColor},setUiColor:function(c){var a=k(CKEDITOR.document);return(this.setUiColor=function(c){this.uiColor=c;var e=CKEDITOR.skin.chameleon,f="",h="";"function"==typeof e&&(f=e(this,"editor"),h=e(this,"panel"));c=[[g,c]];d([a],f,c);d(b,h,c)}).call(this,c)}});var m="cke_ui_color",b=[],g=/\$color/g;CKEDITOR.on("instanceLoaded",function(c){if(!CKEDITOR.env.ie||!CKEDITOR.env.quirks){var a=c.editor;c=function(c){c=(c.data[0]||c.data).element.getElementsByTag("iframe").getItem(0).getFrameDocument(); +if(!c.getById("cke_ui_color")){c=k(c);b.push(c);var e=a.getUiColor();e&&d([c],CKEDITOR.skin.chameleon(a,"panel"),[[g,e]])}};a.on("panelShow",c);a.on("menuShow",c);a.config.uiColor&&a.setUiColor(a.config.uiColor)}})}(),function(){if(CKEDITOR.env.webkit)CKEDITOR.env.hc=!1;else{var f=CKEDITOR.dom.element.createFromHtml('\x3cdiv style\x3d"width:0;height:0;position:absolute;left:-10000px;border:1px solid;border-color:red blue"\x3e\x3c/div\x3e',CKEDITOR.document);f.appendTo(CKEDITOR.document.getHead()); +try{var h=f.getComputedStyle("border-top-color"),e=f.getComputedStyle("border-right-color");CKEDITOR.env.hc=!(!h||h!=e)}catch(k){CKEDITOR.env.hc=!1}f.remove()}CKEDITOR.env.hc&&(CKEDITOR.env.cssClass+=" cke_hc");CKEDITOR.document.appendStyleText(".cke{visibility:hidden;}");CKEDITOR.status="loaded";CKEDITOR.fireOnce("loaded");if(f=CKEDITOR._.pending)for(delete CKEDITOR._.pending,h=0;h<f.length;h++)CKEDITOR.editor.prototype.constructor.apply(f[h][0],f[h][1]),CKEDITOR.add(f[h][0])}(),CKEDITOR.skin.name= +"moono-lisa",CKEDITOR.skin.ua_editor="ie,iequirks,ie8,gecko",CKEDITOR.skin.ua_dialog="ie,iequirks,ie8",CKEDITOR.skin.chameleon=function(){var f=function(){return function(e,f){for(var d=e.match(/[^#]./g),h=0;3>h;h++){var m=h,b;b=parseInt(d[h],16);b=("0"+(0>f?0|b*(1+f):0|b+(255-b)*f).toString(16)).slice(-2);d[m]=b}return"#"+d.join("")}}(),h={editor:new CKEDITOR.template("{id}.cke_chrome [border-color:{defaultBorder};] {id} .cke_top [ background-color:{defaultBackground};border-bottom-color:{defaultBorder};] {id} .cke_bottom [background-color:{defaultBackground};border-top-color:{defaultBorder};] {id} .cke_resizer [border-right-color:{ckeResizer}] {id} .cke_dialog_title [background-color:{defaultBackground};border-bottom-color:{defaultBorder};] {id} .cke_dialog_footer [background-color:{defaultBackground};outline-color:{defaultBorder};] {id} .cke_dialog_tab [background-color:{dialogTab};border-color:{defaultBorder};] {id} .cke_dialog_tab:hover [background-color:{lightBackground};] {id} .cke_dialog_contents [border-top-color:{defaultBorder};] {id} .cke_dialog_tab_selected, {id} .cke_dialog_tab_selected:hover [background:{dialogTabSelected};border-bottom-color:{dialogTabSelectedBorder};] {id} .cke_dialog_body [background:{dialogBody};border-color:{defaultBorder};] {id} a.cke_button_off:hover,{id} a.cke_button_off:focus,{id} a.cke_button_off:active [background-color:{darkBackground};border-color:{toolbarElementsBorder};] {id} .cke_button_on [background-color:{ckeButtonOn};border-color:{toolbarElementsBorder};] {id} .cke_toolbar_separator,{id} .cke_toolgroup a.cke_button:last-child:after,{id} .cke_toolgroup a.cke_button.cke_button_disabled:hover:last-child:after [background-color: {toolbarElementsBorder};border-color: {toolbarElementsBorder};] {id} a.cke_combo_button:hover,{id} a.cke_combo_button:focus,{id} .cke_combo_on a.cke_combo_button [border-color:{toolbarElementsBorder};background-color:{darkBackground};] {id} .cke_combo:after [border-color:{toolbarElementsBorder};] {id} .cke_path_item [color:{elementsPathColor};] {id} a.cke_path_item:hover,{id} a.cke_path_item:focus,{id} a.cke_path_item:active [background-color:{darkBackground};] {id}.cke_panel [border-color:{defaultBorder};] "), panel:new CKEDITOR.template(".cke_panel_grouptitle [background-color:{lightBackground};border-color:{defaultBorder};] .cke_menubutton_icon [background-color:{menubuttonIcon};] .cke_menubutton:hover,.cke_menubutton:focus,.cke_menubutton:active [background-color:{menubuttonHover};] .cke_menubutton:hover .cke_menubutton_icon, .cke_menubutton:focus .cke_menubutton_icon, .cke_menubutton:active .cke_menubutton_icon [background-color:{menubuttonIconHover};] .cke_menubutton_disabled:hover .cke_menubutton_icon,.cke_menubutton_disabled:focus .cke_menubutton_icon,.cke_menubutton_disabled:active .cke_menubutton_icon [background-color:{menubuttonIcon};] .cke_menuseparator [background-color:{menubuttonIcon};] a:hover.cke_colorbox, a:active.cke_colorbox [border-color:{defaultBorder};] a:hover.cke_colorauto, a:hover.cke_colormore, a:active.cke_colorauto, a:active.cke_colormore [background-color:{ckeColorauto};border-color:{defaultBorder};] ")}; return function(e,k){var d=f(e.uiColor,.4),d={id:"."+e.id,defaultBorder:f(d,-.2),toolbarElementsBorder:f(d,-.25),defaultBackground:d,lightBackground:f(d,.8),darkBackground:f(d,-.15),ckeButtonOn:f(d,.4),ckeResizer:f(d,-.4),ckeColorauto:f(d,.8),dialogBody:f(d,.7),dialogTab:f(d,.65),dialogTabSelected:"#FFF",dialogTabSelectedBorder:"#FFF",elementsPathColor:f(d,-.6),menubuttonHover:f(d,.1),menubuttonIcon:f(d,.5),menubuttonIconHover:f(d,.3)};return h[k].output(d).replace(/\[/g,"{").replace(/\]/g,"}")}}(), CKEDITOR.plugins.add("dialogui",{onLoad:function(){var f=function(b){this._||(this._={});this._["default"]=this._.initValue=b["default"]||"";this._.required=b.required||!1;for(var c=[this._],a=1;a<arguments.length;a++)c.push(arguments[a]);c.push(!0);CKEDITOR.tools.extend.apply(CKEDITOR.tools,c);return this._},h={build:function(b,c,a){return new CKEDITOR.ui.dialog.textInput(b,c,a)}},e={build:function(b,c,a){return new CKEDITOR.ui.dialog[c.type](b,c,a)}},k={isChanged:function(){return this.getValue()!= @@ -508,14 +509,14 @@ this.getInitValue()},reset:function(b){this.setValue(this.getInitValue(),b)},set this)},this),this._.domOnChangeRegistered=!0);this.on("change",c)}},!0),l=/^on([A-Z]\w+)/,m=function(b){for(var c in b)(l.test(c)||"title"==c||"type"==c)&&delete b[c];return b},b=function(b){b=b.data.getKeystroke();b==CKEDITOR.SHIFT+CKEDITOR.ALT+36?this.setDirectionMarker("ltr"):b==CKEDITOR.SHIFT+CKEDITOR.ALT+35&&this.setDirectionMarker("rtl")};CKEDITOR.tools.extend(CKEDITOR.ui.dialog,{labeledElement:function(b,c,a,d){if(!(4>arguments.length)){var e=f.call(this,c);e.labelId=CKEDITOR.tools.getNextId()+ "_label";this._.children=[];var h={role:c.role||"presentation"};c.includeLabel&&(h["aria-labelledby"]=e.labelId);CKEDITOR.ui.dialog.uiElement.call(this,b,c,a,"div",null,h,function(){var a=[],f=c.required?" cke_required":"";"horizontal"!=c.labelLayout?a.push('\x3clabel class\x3d"cke_dialog_ui_labeled_label'+f+'" ',' id\x3d"'+e.labelId+'"',e.inputId?' for\x3d"'+e.inputId+'"':"",(c.labelStyle?' style\x3d"'+c.labelStyle+'"':"")+"\x3e",c.label,"\x3c/label\x3e",'\x3cdiv class\x3d"cke_dialog_ui_labeled_content"', c.controlStyle?' style\x3d"'+c.controlStyle+'"':"",' role\x3d"presentation"\x3e',d.call(this,b,c),"\x3c/div\x3e"):(f={type:"hbox",widths:c.widths,padding:0,children:[{type:"html",html:'\x3clabel class\x3d"cke_dialog_ui_labeled_label'+f+'" id\x3d"'+e.labelId+'" for\x3d"'+e.inputId+'"'+(c.labelStyle?' style\x3d"'+c.labelStyle+'"':"")+"\x3e"+CKEDITOR.tools.htmlEncode(c.label)+"\x3c/label\x3e"},{type:"html",html:'\x3cspan class\x3d"cke_dialog_ui_labeled_content"'+(c.controlStyle?' style\x3d"'+c.controlStyle+ -'"':"")+"\x3e"+d.call(this,b,c)+"\x3c/span\x3e"}]},CKEDITOR.dialog._.uiElementBuilders.hbox.build(b,f,a));return a.join("")})}},textInput:function(g,c,a){if(!(3>arguments.length)){f.call(this,c);var d=this._.inputId=CKEDITOR.tools.getNextId()+"_textInput",e={"class":"cke_dialog_ui_input_"+c.type,id:d,type:c.type};c.validate&&(this.validate=c.validate);c.maxLength&&(e.maxlength=c.maxLength);c.size&&(e.size=c.size);c.inputStyle&&(e.style=c.inputStyle);var h=this,k=!1;g.on("load",function(){h.getInputElement().on("keydown", -function(a){13==a.data.getKeystroke()&&(k=!0)});h.getInputElement().on("keyup",function(a){13==a.data.getKeystroke()&&k&&(g.getButton("ok")&&setTimeout(function(){g.getButton("ok").click()},0),k=!1);h.bidi&&b.call(h,a)},null,null,1E3)});CKEDITOR.ui.dialog.labeledElement.call(this,g,c,a,function(){var a=['\x3cdiv class\x3d"cke_dialog_ui_input_',c.type,'" role\x3d"presentation"'];c.width&&a.push('style\x3d"width:'+c.width+'" ');a.push("\x3e\x3cinput ");e["aria-labelledby"]=this._.labelId;this._.required&& -(e["aria-required"]=this._.required);for(var b in e)a.push(b+'\x3d"'+e[b]+'" ');a.push(" /\x3e\x3c/div\x3e");return a.join("")})}},textarea:function(g,c,a){if(!(3>arguments.length)){f.call(this,c);var d=this,e=this._.inputId=CKEDITOR.tools.getNextId()+"_textarea",h={};c.validate&&(this.validate=c.validate);h.rows=c.rows||5;h.cols=c.cols||20;h["class"]="cke_dialog_ui_input_textarea "+(c["class"]||"");"undefined"!=typeof c.inputStyle&&(h.style=c.inputStyle);c.dir&&(h.dir=c.dir);if(d.bidi)g.on("load", -function(){d.getInputElement().on("keyup",b)},d);CKEDITOR.ui.dialog.labeledElement.call(this,g,c,a,function(){h["aria-labelledby"]=this._.labelId;this._.required&&(h["aria-required"]=this._.required);var a=['\x3cdiv class\x3d"cke_dialog_ui_input_textarea" role\x3d"presentation"\x3e\x3ctextarea id\x3d"',e,'" '],c;for(c in h)a.push(c+'\x3d"'+CKEDITOR.tools.htmlEncode(h[c])+'" ');a.push("\x3e",CKEDITOR.tools.htmlEncode(d._["default"]),"\x3c/textarea\x3e\x3c/div\x3e");return a.join("")})}},checkbox:function(b, +'"':"")+"\x3e"+d.call(this,b,c)+"\x3c/span\x3e"}]},CKEDITOR.dialog._.uiElementBuilders.hbox.build(b,f,a));return a.join("")})}},textInput:function(d,c,a){if(!(3>arguments.length)){f.call(this,c);var e=this._.inputId=CKEDITOR.tools.getNextId()+"_textInput",h={"class":"cke_dialog_ui_input_"+c.type,id:e,type:c.type};c.validate&&(this.validate=c.validate);c.maxLength&&(h.maxlength=c.maxLength);c.size&&(h.size=c.size);c.inputStyle&&(h.style=c.inputStyle);var k=this,l=!1;d.on("load",function(){k.getInputElement().on("keydown", +function(a){13==a.data.getKeystroke()&&(l=!0)});k.getInputElement().on("keyup",function(a){13==a.data.getKeystroke()&&l&&(d.getButton("ok")&&setTimeout(function(){d.getButton("ok").click()},0),l=!1);k.bidi&&b.call(k,a)},null,null,1E3)});CKEDITOR.ui.dialog.labeledElement.call(this,d,c,a,function(){var a=['\x3cdiv class\x3d"cke_dialog_ui_input_',c.type,'" role\x3d"presentation"'];c.width&&a.push('style\x3d"width:'+c.width+'" ');a.push("\x3e\x3cinput ");h["aria-labelledby"]=this._.labelId;this._.required&& +(h["aria-required"]=this._.required);for(var b in h)a.push(b+'\x3d"'+h[b]+'" ');a.push(" /\x3e\x3c/div\x3e");return a.join("")})}},textarea:function(d,c,a){if(!(3>arguments.length)){f.call(this,c);var e=this,h=this._.inputId=CKEDITOR.tools.getNextId()+"_textarea",k={};c.validate&&(this.validate=c.validate);k.rows=c.rows||5;k.cols=c.cols||20;k["class"]="cke_dialog_ui_input_textarea "+(c["class"]||"");"undefined"!=typeof c.inputStyle&&(k.style=c.inputStyle);c.dir&&(k.dir=c.dir);if(e.bidi)d.on("load", +function(){e.getInputElement().on("keyup",b)},e);CKEDITOR.ui.dialog.labeledElement.call(this,d,c,a,function(){k["aria-labelledby"]=this._.labelId;this._.required&&(k["aria-required"]=this._.required);var a=['\x3cdiv class\x3d"cke_dialog_ui_input_textarea" role\x3d"presentation"\x3e\x3ctextarea id\x3d"',h,'" '],c;for(c in k)a.push(c+'\x3d"'+CKEDITOR.tools.htmlEncode(k[c])+'" ');a.push("\x3e",CKEDITOR.tools.htmlEncode(e._["default"]),"\x3c/textarea\x3e\x3c/div\x3e");return a.join("")})}},checkbox:function(b, c,a){if(!(3>arguments.length)){var d=f.call(this,c,{"default":!!c["default"]});c.validate&&(this.validate=c.validate);CKEDITOR.ui.dialog.uiElement.call(this,b,c,a,"span",null,null,function(){var a=CKEDITOR.tools.extend({},c,{id:c.id?c.id+"_checkbox":CKEDITOR.tools.getNextId()+"_checkbox"},!0),e=[],f=CKEDITOR.tools.getNextId()+"_label",h={"class":"cke_dialog_ui_checkbox_input",type:"checkbox","aria-labelledby":f};m(a);c["default"]&&(h.checked="checked");"undefined"!=typeof a.inputStyle&&(a.style=a.inputStyle); d.checkbox=new CKEDITOR.ui.dialog.uiElement(b,a,e,"input",null,h);e.push(' \x3clabel id\x3d"',f,'" for\x3d"',h.id,'"'+(c.labelStyle?' style\x3d"'+c.labelStyle+'"':"")+"\x3e",CKEDITOR.tools.htmlEncode(c.label),"\x3c/label\x3e");return e.join("")})}},radio:function(b,c,a){if(!(3>arguments.length)){f.call(this,c);this._["default"]||(this._["default"]=this._.initValue=c.items[0][1]);c.validate&&(this.validate=c.validate);var d=[],e=this;c.role="radiogroup";c.includeLabel=!0;CKEDITOR.ui.dialog.labeledElement.call(this, -b,c,a,function(){for(var a=[],f=[],h=(c.id?c.id:CKEDITOR.tools.getNextId())+"_radio",k=0;k<c.items.length;k++){var l=c.items[k],x=void 0!==l[2]?l[2]:l[0],A=void 0!==l[1]?l[1]:l[0],D=CKEDITOR.tools.getNextId()+"_radio_input",t=D+"_label",D=CKEDITOR.tools.extend({},c,{id:D,title:null,type:null},!0),x=CKEDITOR.tools.extend({},D,{title:x},!0),B={type:"radio","class":"cke_dialog_ui_radio_input",name:h,value:A,"aria-labelledby":t},y=[];e._["default"]==A&&(B.checked="checked");m(D);m(x);"undefined"!=typeof D.inputStyle&& -(D.style=D.inputStyle);D.keyboardFocusable=!0;d.push(new CKEDITOR.ui.dialog.uiElement(b,D,y,"input",null,B));y.push(" ");new CKEDITOR.ui.dialog.uiElement(b,x,y,"label",null,{id:t,"for":B.id},l[0]);a.push(y.join(""))}new CKEDITOR.ui.dialog.hbox(b,d,a,f);return f.join("")});this._.children=d}},button:function(b,c,a){if(arguments.length){"function"==typeof c&&(c=c(b.getParentEditor()));f.call(this,c,{disabled:c.disabled||!1});CKEDITOR.event.implementOn(this);var d=this;b.on("load",function(){var a=this.getElement(); +b,c,a,function(){for(var a=[],f=[],h=(c.id?c.id:CKEDITOR.tools.getNextId())+"_radio",k=0;k<c.items.length;k++){var l=c.items[k],r=void 0!==l[2]?l[2]:l[0],C=void 0!==l[1]?l[1]:l[0],B=CKEDITOR.tools.getNextId()+"_radio_input",u=B+"_label",B=CKEDITOR.tools.extend({},c,{id:B,title:null,type:null},!0),r=CKEDITOR.tools.extend({},B,{title:r},!0),y={type:"radio","class":"cke_dialog_ui_radio_input",name:h,value:C,"aria-labelledby":u},x=[];e._["default"]==C&&(y.checked="checked");m(B);m(r);"undefined"!=typeof B.inputStyle&& +(B.style=B.inputStyle);B.keyboardFocusable=!0;d.push(new CKEDITOR.ui.dialog.uiElement(b,B,x,"input",null,y));x.push(" ");new CKEDITOR.ui.dialog.uiElement(b,r,x,"label",null,{id:u,"for":y.id},l[0]);a.push(x.join(""))}new CKEDITOR.ui.dialog.hbox(b,d,a,f);return f.join("")});this._.children=d}},button:function(b,c,a){if(arguments.length){"function"==typeof c&&(c=c(b.getParentEditor()));f.call(this,c,{disabled:c.disabled||!1});CKEDITOR.event.implementOn(this);var d=this;b.on("load",function(){var a=this.getElement(); (function(){a.on("click",function(a){d.click();a.data.preventDefault()});a.on("keydown",function(a){a.data.getKeystroke()in{32:1}&&(d.click(),a.data.preventDefault())})})();a.unselectable()},this);var e=CKEDITOR.tools.extend({},c);delete e.style;var h=CKEDITOR.tools.getNextId()+"_label";CKEDITOR.ui.dialog.uiElement.call(this,b,e,a,"a",null,{style:c.style,href:"javascript:void(0)",title:c.label,hidefocus:"true","class":c["class"],role:"button","aria-labelledby":h},'\x3cspan id\x3d"'+h+'" class\x3d"cke_dialog_ui_button"\x3e'+ CKEDITOR.tools.htmlEncode(c.label)+"\x3c/span\x3e")}},select:function(b,c,a){if(!(3>arguments.length)){var d=f.call(this,c);c.validate&&(this.validate=c.validate);d.inputId=CKEDITOR.tools.getNextId()+"_select";CKEDITOR.ui.dialog.labeledElement.call(this,b,c,a,function(){var a=CKEDITOR.tools.extend({},c,{id:c.id?c.id+"_select":CKEDITOR.tools.getNextId()+"_select"},!0),e=[],f=[],h={id:d.inputId,"class":"cke_dialog_ui_input_select","aria-labelledby":this._.labelId};e.push('\x3cdiv class\x3d"cke_dialog_ui_input_', c.type,'" role\x3d"presentation"');c.width&&e.push('style\x3d"width:'+c.width+'" ');e.push("\x3e");void 0!==c.size&&(h.size=c.size);void 0!==c.multiple&&(h.multiple=c.multiple);m(a);for(var k=0,l;k<c.items.length&&(l=c.items[k]);k++)f.push('\x3coption value\x3d"',CKEDITOR.tools.htmlEncode(void 0!==l[1]?l[1]:l[0]).replace(/"/g,"\x26quot;"),'" /\x3e ',CKEDITOR.tools.htmlEncode(l[0]));"undefined"!=typeof a.inputStyle&&(a.style=a.inputStyle);d.select=new CKEDITOR.ui.dialog.uiElement(b,a,e,"select",null, @@ -533,89 +534,89 @@ return this},clear:function(){for(var b=this.getInputElement().$;0<b.length;)b.r c){if(!CKEDITOR.env.ie||8<CKEDITOR.env.version)return d.onChange.apply(this,arguments);b.on("load",function(){var a=this._.checkbox.getElement();a.on("propertychange",function(b){b=b.data.$;"checked"==b.propertyName&&this.fire("change",{value:a.$.checked})},this)},this);this.on("change",c);return null}},keyboardFocusable:!0},k,!0);CKEDITOR.ui.dialog.radio.prototype=CKEDITOR.tools.extend(new CKEDITOR.ui.dialog.uiElement,{setValue:function(b,c){for(var a=this._.children,d,e=0;e<a.length&&(d=a[e]);e++)d.getElement().$.checked= d.getValue()==b;!c&&this.fire("change",{value:b})},getValue:function(){for(var b=this._.children,c=0;c<b.length;c++)if(b[c].getElement().$.checked)return b[c].getValue();return null},accessKeyUp:function(){var b=this._.children,c;for(c=0;c<b.length;c++)if(b[c].getElement().$.checked){b[c].getElement().focus();return}b[0].getElement().focus()},eventProcessors:{onChange:function(b,c){if(!CKEDITOR.env.ie||8<CKEDITOR.env.version)return d.onChange.apply(this,arguments);b.on("load",function(){for(var a= this._.children,b=this,c=0;c<a.length;c++)a[c].getElement().on("propertychange",function(a){a=a.data.$;"checked"==a.propertyName&&this.$.checked&&b.fire("change",{value:this.getAttribute("value")})})},this);this.on("change",c);return null}}},k,!0);CKEDITOR.ui.dialog.file.prototype=CKEDITOR.tools.extend(new CKEDITOR.ui.dialog.labeledElement,k,{getInputElement:function(){var b=CKEDITOR.document.getById(this._.frameId).getFrameDocument();return 0<b.$.forms.length?new CKEDITOR.dom.element(b.$.forms[0].elements[0]): -this.getElement()},submit:function(){this.getInputElement().getParent().$.submit();return this},getAction:function(){return this.getInputElement().getParent().$.action},registerEvents:function(b){var c=/^on([A-Z]\w+)/,a,d=function(a,b,c,g){a.on("formLoaded",function(){a.getInputElement().on(c,g,a)})},e;for(e in b)if(a=e.match(c))this.eventProcessors[e]?this.eventProcessors[e].call(this,this._.dialog,b[e]):d(this,this._.dialog,a[1].toLowerCase(),b[e]);return this},reset:function(){function b(){a.$.open(); +this.getElement()},submit:function(){this.getInputElement().getParent().$.submit();return this},getAction:function(){return this.getInputElement().getParent().$.action},registerEvents:function(b){var c=/^on([A-Z]\w+)/,a,d=function(a,b,c,d){a.on("formLoaded",function(){a.getInputElement().on(c,d,a)})},e;for(e in b)if(a=e.match(c))this.eventProcessors[e]?this.eventProcessors[e].call(this,this._.dialog,b[e]):d(this,this._.dialog,a[1].toLowerCase(),b[e]);return this},reset:function(){function b(){a.$.open(); var g="";d.size&&(g=d.size-(CKEDITOR.env.ie?7:0));var m=c.frameId+"_input";a.$.write(['\x3chtml dir\x3d"'+k+'" lang\x3d"'+l+'"\x3e\x3chead\x3e\x3ctitle\x3e\x3c/title\x3e\x3c/head\x3e\x3cbody style\x3d"margin: 0; overflow: hidden; background: transparent;"\x3e','\x3cform enctype\x3d"multipart/form-data" method\x3d"POST" dir\x3d"'+k+'" lang\x3d"'+l+'" action\x3d"',CKEDITOR.tools.htmlEncode(d.action),'"\x3e\x3clabel id\x3d"',c.labelId,'" for\x3d"',m,'" style\x3d"display:none"\x3e',CKEDITOR.tools.htmlEncode(d.label), '\x3c/label\x3e\x3cinput style\x3d"width:100%" id\x3d"',m,'" aria-labelledby\x3d"',c.labelId,'" type\x3d"file" name\x3d"',CKEDITOR.tools.htmlEncode(d.id||"cke_upload"),'" size\x3d"',CKEDITOR.tools.htmlEncode(0<g?g:""),'" /\x3e\x3c/form\x3e\x3c/body\x3e\x3c/html\x3e\x3cscript\x3e',CKEDITOR.env.ie?"("+CKEDITOR.tools.fixDomain+")();":"","window.parent.CKEDITOR.tools.callFunction("+f+");","window.onbeforeunload \x3d function() {window.parent.CKEDITOR.tools.callFunction("+h+")}","\x3c/script\x3e"].join("")); a.$.close();for(g=0;g<e.length;g++)e[g].enable()}var c=this._,a=CKEDITOR.document.getById(c.frameId).getFrameDocument(),d=c.definition,e=c.buttons,f=this.formLoadedNumber,h=this.formUnloadNumber,k=c.dialog._.editor.lang.dir,l=c.dialog._.editor.langCode;f||(f=this.formLoadedNumber=CKEDITOR.tools.addFunction(function(){this.fire("formLoaded")},this),h=this.formUnloadNumber=CKEDITOR.tools.addFunction(function(){this.getInputElement().clearCustomData()},this),this.getDialog()._.editor.on("destroy",function(){CKEDITOR.tools.removeFunction(f); CKEDITOR.tools.removeFunction(h)}));CKEDITOR.env.gecko?setTimeout(b,500):b()},getValue:function(){return this.getInputElement().$.value||""},setInitValue:function(){this._.initValue=""},eventProcessors:{onChange:function(b,c){this._.domOnChangeRegistered||(this.on("formLoaded",function(){this.getInputElement().on("change",function(){this.fire("change",{value:this.getValue()})},this)},this),this._.domOnChangeRegistered=!0);this.on("change",c)}},keyboardFocusable:!0},!0);CKEDITOR.ui.dialog.fileButton.prototype= new CKEDITOR.ui.dialog.button;CKEDITOR.ui.dialog.fieldset.prototype=CKEDITOR.tools.clone(CKEDITOR.ui.dialog.hbox.prototype);CKEDITOR.dialog.addUIElement("text",h);CKEDITOR.dialog.addUIElement("password",h);CKEDITOR.dialog.addUIElement("textarea",e);CKEDITOR.dialog.addUIElement("checkbox",e);CKEDITOR.dialog.addUIElement("radio",e);CKEDITOR.dialog.addUIElement("button",e);CKEDITOR.dialog.addUIElement("select",e);CKEDITOR.dialog.addUIElement("file",e);CKEDITOR.dialog.addUIElement("fileButton",e);CKEDITOR.dialog.addUIElement("html", e);CKEDITOR.dialog.addUIElement("fieldset",{build:function(b,c,a){for(var d=c.children,e,f=[],h=[],k=0;k<d.length&&(e=d[k]);k++){var l=[];f.push(l);h.push(CKEDITOR.dialog._.uiElementBuilders[e.type].build(b,e,l))}return new CKEDITOR.ui.dialog[c.type](b,h,f,a,c)}})}}),CKEDITOR.DIALOG_RESIZE_NONE=0,CKEDITOR.DIALOG_RESIZE_WIDTH=1,CKEDITOR.DIALOG_RESIZE_HEIGHT=2,CKEDITOR.DIALOG_RESIZE_BOTH=3,CKEDITOR.DIALOG_STATE_IDLE=1,CKEDITOR.DIALOG_STATE_BUSY=2,function(){function f(){for(var a=this._.tabIdList.length, -b=CKEDITOR.tools.indexOf(this._.tabIdList,this._.currentTabId)+a,c=b-1;c>b-a;c--)if(this._.tabs[this._.tabIdList[c%a]][0].$.offsetHeight)return this._.tabIdList[c%a];return null}function h(){for(var a=this._.tabIdList.length,b=CKEDITOR.tools.indexOf(this._.tabIdList,this._.currentTabId),c=b+1;c<b+a;c++)if(this._.tabs[this._.tabIdList[c%a]][0].$.offsetHeight)return this._.tabIdList[c%a];return null}function e(a,b){for(var c=a.$.getElementsByTagName("input"),g=0,d=c.length;g<d;g++){var e=new CKEDITOR.dom.element(c[g]); -"text"==e.getAttribute("type").toLowerCase()&&(b?(e.setAttribute("value",e.getCustomData("fake_value")||""),e.removeCustomData("fake_value")):(e.setCustomData("fake_value",e.getAttribute("value")),e.setAttribute("value","")))}}function k(a,b){var c=this.getInputElement();c&&(a?c.removeAttribute("aria-invalid"):c.setAttribute("aria-invalid",!0));a||(this.select?this.select():this.focus());b&&alert(b);this.fire("validated",{valid:a,msg:b})}function d(){var a=this.getInputElement();a&&a.removeAttribute("aria-invalid")} -function l(a){var b=CKEDITOR.dom.element.createFromHtml(CKEDITOR.addTemplate("dialog",r).output({id:CKEDITOR.tools.getNextNumber(),editorId:a.id,langDir:a.lang.dir,langCode:a.langCode,editorDialogClass:"cke_editor_"+a.name.replace(/\./g,"\\.")+"_dialog",closeTitle:a.lang.common.close,hidpi:CKEDITOR.env.hidpi?"cke_hidpi":""})),c=b.getChild([0,0,0,0,0]),g=c.getChild(0),d=c.getChild(1);a.plugins.clipboard&&CKEDITOR.plugins.clipboard.preventDefaultDropOnElement(c);!CKEDITOR.env.ie||CKEDITOR.env.quirks|| -CKEDITOR.env.edge||(a="javascript:void(function(){"+encodeURIComponent("document.open();("+CKEDITOR.tools.fixDomain+")();document.close();")+"}())",CKEDITOR.dom.element.createFromHtml('\x3ciframe frameBorder\x3d"0" class\x3d"cke_iframe_shim" src\x3d"'+a+'" tabIndex\x3d"-1"\x3e\x3c/iframe\x3e').appendTo(c.getParent()));g.unselectable();d.unselectable();return{element:b,parts:{dialog:b.getChild(0),title:g,close:d,tabs:c.getChild(2),contents:c.getChild([3,0,0,0]),footer:c.getChild([3,0,1,0])}}}function m(a, +b=CKEDITOR.tools.indexOf(this._.tabIdList,this._.currentTabId)+a,c=b-1;c>b-a;c--)if(this._.tabs[this._.tabIdList[c%a]][0].$.offsetHeight)return this._.tabIdList[c%a];return null}function h(){for(var a=this._.tabIdList.length,b=CKEDITOR.tools.indexOf(this._.tabIdList,this._.currentTabId),c=b+1;c<b+a;c++)if(this._.tabs[this._.tabIdList[c%a]][0].$.offsetHeight)return this._.tabIdList[c%a];return null}function e(a,b){for(var c=a.$.getElementsByTagName("input"),d=0,e=c.length;d<e;d++){var g=new CKEDITOR.dom.element(c[d]); +"text"==g.getAttribute("type").toLowerCase()&&(b?(g.setAttribute("value",g.getCustomData("fake_value")||""),g.removeCustomData("fake_value")):(g.setCustomData("fake_value",g.getAttribute("value")),g.setAttribute("value","")))}}function k(a,b){var c=this.getInputElement();c&&(a?c.removeAttribute("aria-invalid"):c.setAttribute("aria-invalid",!0));a||(this.select?this.select():this.focus());b&&alert(b);this.fire("validated",{valid:a,msg:b})}function d(){var a=this.getInputElement();a&&a.removeAttribute("aria-invalid")} +function l(a){var b=CKEDITOR.dom.element.createFromHtml(CKEDITOR.addTemplate("dialog",p).output({id:CKEDITOR.tools.getNextNumber(),editorId:a.id,langDir:a.lang.dir,langCode:a.langCode,editorDialogClass:"cke_editor_"+a.name.replace(/\./g,"\\.")+"_dialog",closeTitle:a.lang.common.close,hidpi:CKEDITOR.env.hidpi?"cke_hidpi":""})),c=b.getChild([0,0,0,0,0]),d=c.getChild(0),g=c.getChild(1);a.plugins.clipboard&&CKEDITOR.plugins.clipboard.preventDefaultDropOnElement(c);!CKEDITOR.env.ie||CKEDITOR.env.quirks|| +CKEDITOR.env.edge||(a="javascript:void(function(){"+encodeURIComponent("document.open();("+CKEDITOR.tools.fixDomain+")();document.close();")+"}())",CKEDITOR.dom.element.createFromHtml('\x3ciframe frameBorder\x3d"0" class\x3d"cke_iframe_shim" src\x3d"'+a+'" tabIndex\x3d"-1"\x3e\x3c/iframe\x3e').appendTo(c.getParent()));d.unselectable();g.unselectable();return{element:b,parts:{dialog:b.getChild(0),title:d,close:g,tabs:c.getChild(2),contents:c.getChild([3,0,0,0]),footer:c.getChild([3,0,1,0])}}}function m(a, b,c){this.element=b;this.focusIndex=c;this.tabIndex=0;this.isFocusable=function(){return!b.getAttribute("disabled")&&b.isVisible()};this.focus=function(){a._.currentFocusIndex=this.focusIndex;this.element.focus()};b.on("keydown",function(a){a.data.getKeystroke()in{32:1,13:1}&&this.fire("click")});b.on("focus",function(){this.fire("mouseover")});b.on("blur",function(){this.fire("mouseout")})}function b(a){function b(){a.layout()}var c=CKEDITOR.document.getWindow();c.on("resize",b);a.on("hide",function(){c.removeListener("resize", -b)})}function g(a,b){this._={dialog:a};CKEDITOR.tools.extend(this,b)}function c(a){function b(c){var k=a.getSize(),n=CKEDITOR.document.getWindow().getViewPaneSize(),l=c.data.$.screenX,m=c.data.$.screenY,q=l-g.x,t=m-g.y;g={x:l,y:m};d.x+=q;d.y+=t;a.move(d.x+h[3]<f?-h[3]:d.x-h[1]>n.width-k.width-f?n.width-k.width+("rtl"==e.lang.dir?0:h[1]):d.x,d.y+h[0]<f?-h[0]:d.y-h[2]>n.height-k.height-f?n.height-k.height+h[2]:d.y,1);c.data.preventDefault()}function c(){CKEDITOR.document.removeListener("mousemove", -b);CKEDITOR.document.removeListener("mouseup",c);if(CKEDITOR.env.ie6Compat){var a=y.getChild(0).getFrameDocument();a.removeListener("mousemove",b);a.removeListener("mouseup",c)}}var g=null,d=null,e=a.getParentEditor(),f=e.config.dialog_magnetDistance,h=CKEDITOR.skin.margins||[0,0,0,0];"undefined"==typeof f&&(f=20);a.parts.title.on("mousedown",function(e){g={x:e.data.$.screenX,y:e.data.$.screenY};CKEDITOR.document.on("mousemove",b);CKEDITOR.document.on("mouseup",c);d=a.getPosition();if(CKEDITOR.env.ie6Compat){var f= -y.getChild(0).getFrameDocument();f.on("mousemove",b);f.on("mouseup",c)}e.data.preventDefault()},a)}function a(a){function b(c){var m="rtl"==e.lang.dir,q=l.width,t=l.height,r=q+(c.data.$.screenX-n.x)*(m?-1:1)*(a._.moved?1:2),u=t+(c.data.$.screenY-n.y)*(a._.moved?1:2),w=a._.element.getFirst(),w=m&&w.getComputedStyle("right"),p=a.getPosition();p.y+u>k.height&&(u=k.height-p.y);(m?w:p.x)+r>k.width&&(r=k.width-(m?w:p.x));if(d==CKEDITOR.DIALOG_RESIZE_WIDTH||d==CKEDITOR.DIALOG_RESIZE_BOTH)q=Math.max(g.minWidth|| -0,r-f);if(d==CKEDITOR.DIALOG_RESIZE_HEIGHT||d==CKEDITOR.DIALOG_RESIZE_BOTH)t=Math.max(g.minHeight||0,u-h);a.resize(q,t);a._.moved||a.layout();c.data.preventDefault()}function c(){CKEDITOR.document.removeListener("mouseup",c);CKEDITOR.document.removeListener("mousemove",b);m&&(m.remove(),m=null);if(CKEDITOR.env.ie6Compat){var a=y.getChild(0).getFrameDocument();a.removeListener("mouseup",c);a.removeListener("mousemove",b)}}var g=a.definition,d=g.resizable;if(d!=CKEDITOR.DIALOG_RESIZE_NONE){var e=a.getParentEditor(), -f,h,k,n,l,m,q=CKEDITOR.tools.addFunction(function(g){l=a.getSize();var d=a.parts.contents;d.$.getElementsByTagName("iframe").length&&(m=CKEDITOR.dom.element.createFromHtml('\x3cdiv class\x3d"cke_dialog_resize_cover" style\x3d"height: 100%; position: absolute; width: 100%;"\x3e\x3c/div\x3e'),d.append(m));h=l.height-a.parts.contents.getSize("height",!(CKEDITOR.env.gecko||CKEDITOR.env.ie&&CKEDITOR.env.quirks));f=l.width-a.parts.contents.getSize("width",1);n={x:g.screenX,y:g.screenY};k=CKEDITOR.document.getWindow().getViewPaneSize(); -CKEDITOR.document.on("mousemove",b);CKEDITOR.document.on("mouseup",c);CKEDITOR.env.ie6Compat&&(d=y.getChild(0).getFrameDocument(),d.on("mousemove",b),d.on("mouseup",c));g.preventDefault&&g.preventDefault()});a.on("load",function(){var b="";d==CKEDITOR.DIALOG_RESIZE_WIDTH?b=" cke_resizer_horizontal":d==CKEDITOR.DIALOG_RESIZE_HEIGHT&&(b=" cke_resizer_vertical");b=CKEDITOR.dom.element.createFromHtml('\x3cdiv class\x3d"cke_resizer'+b+" cke_resizer_"+e.lang.dir+'" title\x3d"'+CKEDITOR.tools.htmlEncode(e.lang.common.resize)+ -'" onmousedown\x3d"CKEDITOR.tools.callFunction('+q+', event )"\x3e'+("ltr"==e.lang.dir?"◢":"◣")+"\x3c/div\x3e");a.parts.footer.append(b,1)});e.on("destroy",function(){CKEDITOR.tools.removeFunction(q)})}}function n(a){a.data.preventDefault(1)}function w(a){var b=CKEDITOR.document.getWindow(),c=a.config,g=CKEDITOR.skinName||a.config.skin,d=c.dialog_backgroundCoverColor||("moono-lisa"==g?"black":"white"),g=c.dialog_backgroundCoverOpacity,e=c.baseFloatZIndex,c=CKEDITOR.tools.genKey(d,g,e),f=B[c];f?f.show(): -(e=['\x3cdiv tabIndex\x3d"-1" style\x3d"position: ',CKEDITOR.env.ie6Compat?"absolute":"fixed","; z-index: ",e,"; top: 0px; left: 0px; ",CKEDITOR.env.ie6Compat?"":"background-color: "+d,'" class\x3d"cke_dialog_background_cover"\x3e'],CKEDITOR.env.ie6Compat&&(d="\x3chtml\x3e\x3cbody style\x3d\\'background-color:"+d+";\\'\x3e\x3c/body\x3e\x3c/html\x3e",e.push('\x3ciframe hidefocus\x3d"true" frameborder\x3d"0" id\x3d"cke_dialog_background_iframe" src\x3d"javascript:'),e.push("void((function(){"+encodeURIComponent("document.open();("+ -CKEDITOR.tools.fixDomain+")();document.write( '"+d+"' );document.close();")+"})())"),e.push('" style\x3d"position:absolute;left:0;top:0;width:100%;height: 100%;filter: progid:DXImageTransform.Microsoft.Alpha(opacity\x3d0)"\x3e\x3c/iframe\x3e')),e.push("\x3c/div\x3e"),f=CKEDITOR.dom.element.createFromHtml(e.join("")),f.setOpacity(void 0!==g?g:.5),f.on("keydown",n),f.on("keypress",n),f.on("keyup",n),f.appendTo(CKEDITOR.document.getBody()),B[c]=f);a.focusManager.add(f);y=f;a=function(){var a=b.getViewPaneSize(); -f.setStyles({width:a.width+"px",height:a.height+"px"})};var h=function(){var a=b.getScrollPosition(),c=CKEDITOR.dialog._.currentTop;f.setStyles({left:a.x+"px",top:a.y+"px"});if(c){do a=c.getPosition(),c.move(a.x,a.y);while(c=c._.parentDialog)}};t=a;b.on("resize",a);a();CKEDITOR.env.mac&&CKEDITOR.env.webkit||f.focus();if(CKEDITOR.env.ie6Compat){var k=function(){h();arguments.callee.prevScrollHandler.apply(this,arguments)};b.$.setTimeout(function(){k.prevScrollHandler=window.onscroll||function(){}; -window.onscroll=k},0);h()}}function v(a){y&&(a.focusManager.remove(y),a=CKEDITOR.document.getWindow(),y.hide(),a.removeListener("resize",t),CKEDITOR.env.ie6Compat&&a.$.setTimeout(function(){window.onscroll=window.onscroll&&window.onscroll.prevScrollHandler||null},0),t=null)}var p=CKEDITOR.tools.cssLength,r='\x3cdiv class\x3d"cke_reset_all {editorId} {editorDialogClass} {hidpi}" dir\x3d"{langDir}" lang\x3d"{langCode}" role\x3d"dialog" aria-labelledby\x3d"cke_dialog_title_{id}"\x3e\x3ctable class\x3d"cke_dialog '+ +b)})}function g(a,b){this._={dialog:a};CKEDITOR.tools.extend(this,b)}function c(a){function b(c){var k=a.getSize(),n=CKEDITOR.document.getWindow().getViewPaneSize(),l=c.data.$.screenX,m=c.data.$.screenY,q=l-d.x,r=m-d.y;d={x:l,y:m};g.x+=q;g.y+=r;a.move(g.x+h[3]<f?-h[3]:g.x-h[1]>n.width-k.width-f?n.width-k.width+("rtl"==e.lang.dir?0:h[1]):g.x,g.y+h[0]<f?-h[0]:g.y-h[2]>n.height-k.height-f?n.height-k.height+h[2]:g.y,1);c.data.preventDefault()}function c(){CKEDITOR.document.removeListener("mousemove", +b);CKEDITOR.document.removeListener("mouseup",c);if(CKEDITOR.env.ie6Compat){var a=x.getChild(0).getFrameDocument();a.removeListener("mousemove",b);a.removeListener("mouseup",c)}}var d=null,g=null,e=a.getParentEditor(),f=e.config.dialog_magnetDistance,h=CKEDITOR.skin.margins||[0,0,0,0];"undefined"==typeof f&&(f=20);a.parts.title.on("mousedown",function(e){d={x:e.data.$.screenX,y:e.data.$.screenY};CKEDITOR.document.on("mousemove",b);CKEDITOR.document.on("mouseup",c);g=a.getPosition();if(CKEDITOR.env.ie6Compat){var f= +x.getChild(0).getFrameDocument();f.on("mousemove",b);f.on("mouseup",c)}e.data.preventDefault()},a)}function a(a){function b(c){var m="rtl"==e.lang.dir,q=l.width,r=l.height,p=q+(c.data.$.screenX-n.x)*(m?-1:1)*(a._.moved?1:2),u=r+(c.data.$.screenY-n.y)*(a._.moved?1:2),w=a._.element.getFirst(),w=m&&w.getComputedStyle("right"),t=a.getPosition();t.y+u>k.height&&(u=k.height-t.y);(m?w:t.x)+p>k.width&&(p=k.width-(m?w:t.x));if(g==CKEDITOR.DIALOG_RESIZE_WIDTH||g==CKEDITOR.DIALOG_RESIZE_BOTH)q=Math.max(d.minWidth|| +0,p-f);if(g==CKEDITOR.DIALOG_RESIZE_HEIGHT||g==CKEDITOR.DIALOG_RESIZE_BOTH)r=Math.max(d.minHeight||0,u-h);a.resize(q,r);a._.moved||a.layout();c.data.preventDefault()}function c(){CKEDITOR.document.removeListener("mouseup",c);CKEDITOR.document.removeListener("mousemove",b);m&&(m.remove(),m=null);if(CKEDITOR.env.ie6Compat){var a=x.getChild(0).getFrameDocument();a.removeListener("mouseup",c);a.removeListener("mousemove",b)}}var d=a.definition,g=d.resizable;if(g!=CKEDITOR.DIALOG_RESIZE_NONE){var e=a.getParentEditor(), +f,h,k,n,l,m,q=CKEDITOR.tools.addFunction(function(d){l=a.getSize();var g=a.parts.contents;g.$.getElementsByTagName("iframe").length&&(m=CKEDITOR.dom.element.createFromHtml('\x3cdiv class\x3d"cke_dialog_resize_cover" style\x3d"height: 100%; position: absolute; width: 100%;"\x3e\x3c/div\x3e'),g.append(m));h=l.height-a.parts.contents.getSize("height",!(CKEDITOR.env.gecko||CKEDITOR.env.ie&&CKEDITOR.env.quirks));f=l.width-a.parts.contents.getSize("width",1);n={x:d.screenX,y:d.screenY};k=CKEDITOR.document.getWindow().getViewPaneSize(); +CKEDITOR.document.on("mousemove",b);CKEDITOR.document.on("mouseup",c);CKEDITOR.env.ie6Compat&&(g=x.getChild(0).getFrameDocument(),g.on("mousemove",b),g.on("mouseup",c));d.preventDefault&&d.preventDefault()});a.on("load",function(){var b="";g==CKEDITOR.DIALOG_RESIZE_WIDTH?b=" cke_resizer_horizontal":g==CKEDITOR.DIALOG_RESIZE_HEIGHT&&(b=" cke_resizer_vertical");b=CKEDITOR.dom.element.createFromHtml('\x3cdiv class\x3d"cke_resizer'+b+" cke_resizer_"+e.lang.dir+'" title\x3d"'+CKEDITOR.tools.htmlEncode(e.lang.common.resize)+ +'" onmousedown\x3d"CKEDITOR.tools.callFunction('+q+', event )"\x3e'+("ltr"==e.lang.dir?"◢":"◣")+"\x3c/div\x3e");a.parts.footer.append(b,1)});e.on("destroy",function(){CKEDITOR.tools.removeFunction(q)})}}function n(a){a.data.preventDefault(1)}function w(a){var b=CKEDITOR.document.getWindow(),c=a.config,d=CKEDITOR.skinName||a.config.skin,g=c.dialog_backgroundCoverColor||("moono-lisa"==d?"black":"white"),d=c.dialog_backgroundCoverOpacity,e=c.baseFloatZIndex,c=CKEDITOR.tools.genKey(g,d,e),f=y[c];f?f.show(): +(e=['\x3cdiv tabIndex\x3d"-1" style\x3d"position: ',CKEDITOR.env.ie6Compat?"absolute":"fixed","; z-index: ",e,"; top: 0px; left: 0px; ",CKEDITOR.env.ie6Compat?"":"background-color: "+g,'" class\x3d"cke_dialog_background_cover"\x3e'],CKEDITOR.env.ie6Compat&&(g="\x3chtml\x3e\x3cbody style\x3d\\'background-color:"+g+";\\'\x3e\x3c/body\x3e\x3c/html\x3e",e.push('\x3ciframe hidefocus\x3d"true" frameborder\x3d"0" id\x3d"cke_dialog_background_iframe" src\x3d"javascript:'),e.push("void((function(){"+encodeURIComponent("document.open();("+ +CKEDITOR.tools.fixDomain+")();document.write( '"+g+"' );document.close();")+"})())"),e.push('" style\x3d"position:absolute;left:0;top:0;width:100%;height: 100%;filter: progid:DXImageTransform.Microsoft.Alpha(opacity\x3d0)"\x3e\x3c/iframe\x3e')),e.push("\x3c/div\x3e"),f=CKEDITOR.dom.element.createFromHtml(e.join("")),f.setOpacity(void 0!==d?d:.5),f.on("keydown",n),f.on("keypress",n),f.on("keyup",n),f.appendTo(CKEDITOR.document.getBody()),y[c]=f);a.focusManager.add(f);x=f;a=function(){var a=b.getViewPaneSize(); +f.setStyles({width:a.width+"px",height:a.height+"px"})};var h=function(){var a=b.getScrollPosition(),c=CKEDITOR.dialog._.currentTop;f.setStyles({left:a.x+"px",top:a.y+"px"});if(c){do a=c.getPosition(),c.move(a.x,a.y);while(c=c._.parentDialog)}};u=a;b.on("resize",a);a();CKEDITOR.env.mac&&CKEDITOR.env.webkit||f.focus();if(CKEDITOR.env.ie6Compat){var k=function(){h();arguments.callee.prevScrollHandler.apply(this,arguments)};b.$.setTimeout(function(){k.prevScrollHandler=window.onscroll||function(){}; +window.onscroll=k},0);h()}}function v(a){x&&(a.focusManager.remove(x),a=CKEDITOR.document.getWindow(),x.hide(),a.removeListener("resize",u),CKEDITOR.env.ie6Compat&&a.$.setTimeout(function(){window.onscroll=window.onscroll&&window.onscroll.prevScrollHandler||null},0),u=null)}var t=CKEDITOR.tools.cssLength,p='\x3cdiv class\x3d"cke_reset_all {editorId} {editorDialogClass} {hidpi}" dir\x3d"{langDir}" lang\x3d"{langCode}" role\x3d"dialog" aria-labelledby\x3d"cke_dialog_title_{id}"\x3e\x3ctable class\x3d"cke_dialog '+ CKEDITOR.env.cssClass+' cke_{langDir}" style\x3d"position:absolute" role\x3d"presentation"\x3e\x3ctr\x3e\x3ctd role\x3d"presentation"\x3e\x3cdiv class\x3d"cke_dialog_body" role\x3d"presentation"\x3e\x3cdiv id\x3d"cke_dialog_title_{id}" class\x3d"cke_dialog_title" role\x3d"presentation"\x3e\x3c/div\x3e\x3ca id\x3d"cke_dialog_close_button_{id}" class\x3d"cke_dialog_close_button" href\x3d"javascript:void(0)" title\x3d"{closeTitle}" role\x3d"button"\x3e\x3cspan class\x3d"cke_label"\x3eX\x3c/span\x3e\x3c/a\x3e\x3cdiv id\x3d"cke_dialog_tabs_{id}" class\x3d"cke_dialog_tabs" role\x3d"tablist"\x3e\x3c/div\x3e\x3ctable class\x3d"cke_dialog_contents" role\x3d"presentation"\x3e\x3ctr\x3e\x3ctd id\x3d"cke_dialog_contents_{id}" class\x3d"cke_dialog_contents_body" role\x3d"presentation"\x3e\x3c/td\x3e\x3c/tr\x3e\x3ctr\x3e\x3ctd id\x3d"cke_dialog_footer_{id}" class\x3d"cke_dialog_footer" role\x3d"presentation"\x3e\x3c/td\x3e\x3c/tr\x3e\x3c/table\x3e\x3c/div\x3e\x3c/td\x3e\x3c/tr\x3e\x3c/table\x3e\x3c/div\x3e'; -CKEDITOR.dialog=function(b,g){function e(){var a=z._.focusList;a.sort(function(a,b){return a.tabIndex!=b.tabIndex?b.tabIndex-a.tabIndex:a.focusIndex-b.focusIndex});for(var b=a.length,c=0;c<b;c++)a[c].focusIndex=c}function n(a){var b=z._.focusList;a=a||0;if(!(1>b.length)){var c=z._.currentFocusIndex;z._.tabBarMode&&0>a&&(c=0);try{b[c].getInputElement().$.blur()}catch(g){}var d=c,e=1<z._.pageCount;do{d+=a;if(e&&!z._.tabBarMode&&(d==b.length||-1==d)){z._.tabBarMode=!0;z._.tabs[z._.currentTabId][0].focus(); -z._.currentFocusIndex=-1;return}d=(d+b.length)%b.length;if(d==c)break}while(a&&!b[d].isFocusable());b[d].focus();"text"==b[d].type&&b[d].select()}}function m(a){if(z==CKEDITOR.dialog._.currentTop){var c=a.data.getKeystroke(),g="rtl"==b.lang.dir,d=[37,38,39,40];A=v=0;if(9==c||c==CKEDITOR.SHIFT+9)n(c==CKEDITOR.SHIFT+9?-1:1),A=1;else if(c==CKEDITOR.ALT+121&&!z._.tabBarMode&&1<z.getPageCount())z._.tabBarMode=!0,z._.tabs[z._.currentTabId][0].focus(),z._.currentFocusIndex=-1,A=1;else if(-1!=CKEDITOR.tools.indexOf(d, -c)&&z._.tabBarMode)c=-1!=CKEDITOR.tools.indexOf([g?39:37,38],c)?f.call(z):h.call(z),z.selectPage(c),z._.tabs[c][0].focus(),A=1;else if(13!=c&&32!=c||!z._.tabBarMode)if(13==c)c=a.data.getTarget(),c.is("a","button","select","textarea")||c.is("input")&&"button"==c.$.type||((c=this.getButton("ok"))&&CKEDITOR.tools.setTimeout(c.click,0,c),A=1),v=1;else if(27==c)(c=this.getButton("cancel"))?CKEDITOR.tools.setTimeout(c.click,0,c):!1!==this.fire("cancel",{hide:!0}).hide&&this.hide(),v=1;else return;else this.selectPage(this._.currentTabId), -this._.tabBarMode=!1,this._.currentFocusIndex=-1,n(1),A=1;t(a)}}function t(a){A?a.data.preventDefault(1):v&&a.data.stopPropagation()}var r=CKEDITOR.dialog._.dialogDefinitions[g],w=CKEDITOR.tools.clone(q),u=b.config.dialog_buttonsOrder||"OS",p=b.lang.dir,x={},A,v;("OS"==u&&CKEDITOR.env.mac||"rtl"==u&&"ltr"==p||"ltr"==u&&"rtl"==p)&&w.buttons.reverse();r=CKEDITOR.tools.extend(r(b),w);r=CKEDITOR.tools.clone(r);r=new D(this,r);w=l(b);this._={editor:b,element:w.element,name:g,contentSize:{width:0,height:0}, -size:{width:0,height:0},contents:{},buttons:{},accessKeyMap:{},tabs:{},tabIdList:[],currentTabId:null,currentTabIndex:null,pageCount:0,lastTab:null,tabBarMode:!1,focusList:[],currentFocusIndex:0,hasFocus:!1};this.parts=w.parts;CKEDITOR.tools.setTimeout(function(){b.fire("ariaWidget",this.parts.contents)},0,this);w={position:CKEDITOR.env.ie6Compat?"absolute":"fixed",top:0,visibility:"hidden"};w["rtl"==p?"right":"left"]=0;this.parts.dialog.setStyles(w);CKEDITOR.event.call(this);this.definition=r=CKEDITOR.fire("dialogDefinition", -{name:g,definition:r},b).definition;if(!("removeDialogTabs"in b._)&&b.config.removeDialogTabs){w=b.config.removeDialogTabs.split(";");for(p=0;p<w.length;p++)if(u=w[p].split(":"),2==u.length){var B=u[0];x[B]||(x[B]=[]);x[B].push(u[1])}b._.removeDialogTabs=x}if(b._.removeDialogTabs&&(x=b._.removeDialogTabs[g]))for(p=0;p<x.length;p++)r.removeContents(x[p]);if(r.onLoad)this.on("load",r.onLoad);if(r.onShow)this.on("show",r.onShow);if(r.onHide)this.on("hide",r.onHide);if(r.onOk)this.on("ok",function(a){b.fire("saveSnapshot"); -setTimeout(function(){b.fire("saveSnapshot")},0);!1===r.onOk.call(this,a)&&(a.data.hide=!1)});this.state=CKEDITOR.DIALOG_STATE_IDLE;if(r.onCancel)this.on("cancel",function(a){!1===r.onCancel.call(this,a)&&(a.data.hide=!1)});var z=this,P=function(a){var b=z._.contents,c=!1,g;for(g in b)for(var d in b[g])if(c=a.call(this,b[g][d]))return};this.on("ok",function(a){P(function(b){if(b.validate){var c=b.validate(this),g="string"==typeof c||!1===c;g&&(a.data.hide=!1,a.stop());k.call(b,!g,"string"==typeof c? -c:void 0);return g}})},this,null,0);this.on("cancel",function(a){P(function(c){if(c.isChanged())return b.config.dialog_noConfirmCancel||confirm(b.lang.common.confirmCancel)||(a.data.hide=!1),!0})},this,null,0);this.parts.close.on("click",function(a){!1!==this.fire("cancel",{hide:!0}).hide&&this.hide();a.data.preventDefault()},this);this.changeFocus=n;var X=this._.element;b.focusManager.add(X,1);this.on("show",function(){X.on("keydown",m,this);if(CKEDITOR.env.gecko)X.on("keypress",t,this)});this.on("hide", -function(){X.removeListener("keydown",m);CKEDITOR.env.gecko&&X.removeListener("keypress",t);P(function(a){d.apply(a)})});this.on("iframeAdded",function(a){(new CKEDITOR.dom.document(a.data.iframe.$.contentWindow.document)).on("keydown",m,this,null,0)});this.on("show",function(){e();var a=1<z._.pageCount;b.config.dialog_startupFocusTab&&a?(z._.tabBarMode=!0,z._.tabs[z._.currentTabId][0].focus(),z._.currentFocusIndex=-1):this._.hasFocus||(this._.currentFocusIndex=a?-1:this._.focusList.length-1,r.onFocus? -(a=r.onFocus.call(this))&&a.focus():n(1))},this,null,4294967295);if(CKEDITOR.env.ie6Compat)this.on("load",function(){var a=this.getElement(),b=a.getFirst();b.remove();b.appendTo(a)},this);c(this);a(this);(new CKEDITOR.dom.text(r.title,CKEDITOR.document)).appendTo(this.parts.title);for(p=0;p<r.contents.length;p++)(x=r.contents[p])&&this.addPage(x);this.parts.tabs.on("click",function(a){var b=a.data.getTarget();b.hasClass("cke_dialog_tab")&&(b=b.$.id,this.selectPage(b.substring(4,b.lastIndexOf("_"))), -this._.tabBarMode&&(this._.tabBarMode=!1,this._.currentFocusIndex=-1,n(1)),a.data.preventDefault())},this);p=[];x=CKEDITOR.dialog._.uiElementBuilders.hbox.build(this,{type:"hbox",className:"cke_dialog_footer_buttons",widths:[],children:r.buttons},p).getChild();this.parts.footer.setHtml(p.join(""));for(p=0;p<x.length;p++)this._.buttons[x[p].id]=x[p]};CKEDITOR.dialog.prototype={destroy:function(){this.hide();this._.element.remove()},resize:function(){return function(a,b){this._.contentSize&&this._.contentSize.width== +CKEDITOR.dialog=function(b,g){function e(){var a=z._.focusList;a.sort(function(a,b){return a.tabIndex!=b.tabIndex?b.tabIndex-a.tabIndex:a.focusIndex-b.focusIndex});for(var b=a.length,c=0;c<b;c++)a[c].focusIndex=c}function n(a){var b=z._.focusList;a=a||0;if(!(1>b.length)){var c=z._.currentFocusIndex;z._.tabBarMode&&0>a&&(c=0);try{b[c].getInputElement().$.blur()}catch(d){}var g=c,e=1<z._.pageCount;do{g+=a;if(e&&!z._.tabBarMode&&(g==b.length||-1==g)){z._.tabBarMode=!0;z._.tabs[z._.currentTabId][0].focus(); +z._.currentFocusIndex=-1;return}g=(g+b.length)%b.length;if(g==c)break}while(a&&!b[g].isFocusable());b[g].focus();"text"==b[g].type&&b[g].select()}}function m(a){if(z==CKEDITOR.dialog._.currentTop){var c=a.data.getKeystroke(),d="rtl"==b.lang.dir,g=[37,38,39,40];C=v=0;if(9==c||c==CKEDITOR.SHIFT+9)n(c==CKEDITOR.SHIFT+9?-1:1),C=1;else if(c==CKEDITOR.ALT+121&&!z._.tabBarMode&&1<z.getPageCount())z._.tabBarMode=!0,z._.tabs[z._.currentTabId][0].focus(),z._.currentFocusIndex=-1,C=1;else if(-1!=CKEDITOR.tools.indexOf(g, +c)&&z._.tabBarMode)c=-1!=CKEDITOR.tools.indexOf([d?39:37,38],c)?f.call(z):h.call(z),z.selectPage(c),z._.tabs[c][0].focus(),C=1;else if(13!=c&&32!=c||!z._.tabBarMode)if(13==c)c=a.data.getTarget(),c.is("a","button","select","textarea")||c.is("input")&&"button"==c.$.type||((c=this.getButton("ok"))&&CKEDITOR.tools.setTimeout(c.click,0,c),C=1),v=1;else if(27==c)(c=this.getButton("cancel"))?CKEDITOR.tools.setTimeout(c.click,0,c):!1!==this.fire("cancel",{hide:!0}).hide&&this.hide(),v=1;else return;else this.selectPage(this._.currentTabId), +this._.tabBarMode=!1,this._.currentFocusIndex=-1,n(1),C=1;r(a)}}function r(a){C?a.data.preventDefault(1):v&&a.data.stopPropagation()}var p=CKEDITOR.dialog._.dialogDefinitions[g],u=CKEDITOR.tools.clone(q),w=b.config.dialog_buttonsOrder||"OS",t=b.lang.dir,A={},C,v;("OS"==w&&CKEDITOR.env.mac||"rtl"==w&&"ltr"==t||"ltr"==w&&"rtl"==t)&&u.buttons.reverse();p=CKEDITOR.tools.extend(p(b),u);p=CKEDITOR.tools.clone(p);p=new B(this,p);u=l(b);this._={editor:b,element:u.element,name:g,contentSize:{width:0,height:0}, +size:{width:0,height:0},contents:{},buttons:{},accessKeyMap:{},tabs:{},tabIdList:[],currentTabId:null,currentTabIndex:null,pageCount:0,lastTab:null,tabBarMode:!1,focusList:[],currentFocusIndex:0,hasFocus:!1};this.parts=u.parts;CKEDITOR.tools.setTimeout(function(){b.fire("ariaWidget",this.parts.contents)},0,this);u={position:CKEDITOR.env.ie6Compat?"absolute":"fixed",top:0,visibility:"hidden"};u["rtl"==t?"right":"left"]=0;this.parts.dialog.setStyles(u);CKEDITOR.event.call(this);this.definition=p=CKEDITOR.fire("dialogDefinition", +{name:g,definition:p},b).definition;if(!("removeDialogTabs"in b._)&&b.config.removeDialogTabs){u=b.config.removeDialogTabs.split(";");for(t=0;t<u.length;t++)if(w=u[t].split(":"),2==w.length){var y=w[0];A[y]||(A[y]=[]);A[y].push(w[1])}b._.removeDialogTabs=A}if(b._.removeDialogTabs&&(A=b._.removeDialogTabs[g]))for(t=0;t<A.length;t++)p.removeContents(A[t]);if(p.onLoad)this.on("load",p.onLoad);if(p.onShow)this.on("show",p.onShow);if(p.onHide)this.on("hide",p.onHide);if(p.onOk)this.on("ok",function(a){b.fire("saveSnapshot"); +setTimeout(function(){b.fire("saveSnapshot")},0);!1===p.onOk.call(this,a)&&(a.data.hide=!1)});this.state=CKEDITOR.DIALOG_STATE_IDLE;if(p.onCancel)this.on("cancel",function(a){!1===p.onCancel.call(this,a)&&(a.data.hide=!1)});var z=this,P=function(a){var b=z._.contents,c=!1,d;for(d in b)for(var g in b[d])if(c=a.call(this,b[d][g]))return};this.on("ok",function(a){P(function(b){if(b.validate){var c=b.validate(this),d="string"==typeof c||!1===c;d&&(a.data.hide=!1,a.stop());k.call(b,!d,"string"==typeof c? +c:void 0);return d}})},this,null,0);this.on("cancel",function(a){P(function(c){if(c.isChanged())return b.config.dialog_noConfirmCancel||confirm(b.lang.common.confirmCancel)||(a.data.hide=!1),!0})},this,null,0);this.parts.close.on("click",function(a){!1!==this.fire("cancel",{hide:!0}).hide&&this.hide();a.data.preventDefault()},this);this.changeFocus=n;var W=this._.element;b.focusManager.add(W,1);this.on("show",function(){W.on("keydown",m,this);if(CKEDITOR.env.gecko)W.on("keypress",r,this)});this.on("hide", +function(){W.removeListener("keydown",m);CKEDITOR.env.gecko&&W.removeListener("keypress",r);P(function(a){d.apply(a)})});this.on("iframeAdded",function(a){(new CKEDITOR.dom.document(a.data.iframe.$.contentWindow.document)).on("keydown",m,this,null,0)});this.on("show",function(){e();var a=1<z._.pageCount;b.config.dialog_startupFocusTab&&a?(z._.tabBarMode=!0,z._.tabs[z._.currentTabId][0].focus(),z._.currentFocusIndex=-1):this._.hasFocus||(this._.currentFocusIndex=a?-1:this._.focusList.length-1,p.onFocus? +(a=p.onFocus.call(this))&&a.focus():n(1))},this,null,4294967295);if(CKEDITOR.env.ie6Compat)this.on("load",function(){var a=this.getElement(),b=a.getFirst();b.remove();b.appendTo(a)},this);c(this);a(this);(new CKEDITOR.dom.text(p.title,CKEDITOR.document)).appendTo(this.parts.title);for(t=0;t<p.contents.length;t++)(A=p.contents[t])&&this.addPage(A);this.parts.tabs.on("click",function(a){var b=a.data.getTarget();b.hasClass("cke_dialog_tab")&&(b=b.$.id,this.selectPage(b.substring(4,b.lastIndexOf("_"))), +this._.tabBarMode&&(this._.tabBarMode=!1,this._.currentFocusIndex=-1,n(1)),a.data.preventDefault())},this);t=[];A=CKEDITOR.dialog._.uiElementBuilders.hbox.build(this,{type:"hbox",className:"cke_dialog_footer_buttons",widths:[],children:p.buttons},t).getChild();this.parts.footer.setHtml(t.join(""));for(t=0;t<A.length;t++)this._.buttons[A[t].id]=A[t]};CKEDITOR.dialog.prototype={destroy:function(){this.hide();this._.element.remove()},resize:function(){return function(a,b){this._.contentSize&&this._.contentSize.width== a&&this._.contentSize.height==b||(CKEDITOR.dialog.fire("resize",{dialog:this,width:a,height:b},this._.editor),this.fire("resize",{width:a,height:b},this._.editor),this.parts.contents.setStyles({width:a+"px",height:b+"px"}),"rtl"==this._.editor.lang.dir&&this._.position&&(this._.position.x=CKEDITOR.document.getWindow().getViewPaneSize().width-this._.contentSize.width-parseInt(this._.element.getFirst().getStyle("right"),10)),this._.contentSize={width:a,height:b})}}(),getSize:function(){var a=this._.element.getFirst(); -return{width:a.$.offsetWidth||0,height:a.$.offsetHeight||0}},move:function(a,b,c){var g=this._.element.getFirst(),d="rtl"==this._.editor.lang.dir,e="fixed"==g.getComputedStyle("position");CKEDITOR.env.ie&&g.setStyle("zoom","100%");e&&this._.position&&this._.position.x==a&&this._.position.y==b||(this._.position={x:a,y:b},e||(e=CKEDITOR.document.getWindow().getScrollPosition(),a+=e.x,b+=e.y),d&&(e=this.getSize(),a=CKEDITOR.document.getWindow().getViewPaneSize().width-e.width-a),b={top:(0<b?b:0)+"px"}, -b[d?"right":"left"]=(0<a?a:0)+"px",g.setStyles(b),c&&(this._.moved=1))},getPosition:function(){return CKEDITOR.tools.extend({},this._.position)},show:function(){var a=this._.element,c=this.definition;a.getParent()&&a.getParent().equals(CKEDITOR.document.getBody())?a.setStyle("display","block"):a.appendTo(CKEDITOR.document.getBody());this.resize(this._.contentSize&&this._.contentSize.width||c.width||c.minWidth,this._.contentSize&&this._.contentSize.height||c.height||c.minHeight);this.reset();null=== +return{width:a.$.offsetWidth||0,height:a.$.offsetHeight||0}},move:function(a,b,c){var d=this._.element.getFirst(),g="rtl"==this._.editor.lang.dir,e="fixed"==d.getComputedStyle("position");CKEDITOR.env.ie&&d.setStyle("zoom","100%");e&&this._.position&&this._.position.x==a&&this._.position.y==b||(this._.position={x:a,y:b},e||(e=CKEDITOR.document.getWindow().getScrollPosition(),a+=e.x,b+=e.y),g&&(e=this.getSize(),a=CKEDITOR.document.getWindow().getViewPaneSize().width-e.width-a),b={top:(0<b?b:0)+"px"}, +b[g?"right":"left"]=(0<a?a:0)+"px",d.setStyles(b),c&&(this._.moved=1))},getPosition:function(){return CKEDITOR.tools.extend({},this._.position)},show:function(){var a=this._.element,c=this.definition;a.getParent()&&a.getParent().equals(CKEDITOR.document.getBody())?a.setStyle("display","block"):a.appendTo(CKEDITOR.document.getBody());this.resize(this._.contentSize&&this._.contentSize.width||c.width||c.minWidth,this._.contentSize&&this._.contentSize.height||c.height||c.minHeight);this.reset();null=== this._.currentTabId&&this.selectPage(this.definition.contents[0].id);null===CKEDITOR.dialog._.currentZIndex&&(CKEDITOR.dialog._.currentZIndex=this._.editor.config.baseFloatZIndex);this._.element.getFirst().setStyle("z-index",CKEDITOR.dialog._.currentZIndex+=10);null===CKEDITOR.dialog._.currentTop?(CKEDITOR.dialog._.currentTop=this,this._.parentDialog=null,w(this._.editor)):(this._.parentDialog=CKEDITOR.dialog._.currentTop,this._.parentDialog.getElement().getFirst().$.style.zIndex-=Math.floor(this._.editor.config.baseFloatZIndex/ -2),CKEDITOR.dialog._.currentTop=this);a.on("keydown",I);a.on("keyup",E);this._.hasFocus=!1;for(var g in c.contents)if(c.contents[g]){var a=c.contents[g],d=this._.tabs[a.id],e=a.requiredContent,f=0;if(d){for(var h in this._.contents[a.id]){var k=this._.contents[a.id][h];"hbox"!=k.type&&"vbox"!=k.type&&k.getInputElement()&&(k.requiredContent&&!this._.editor.activeFilter.check(k.requiredContent)?k.disable():(k.enable(),f++))}!f||e&&!this._.editor.activeFilter.check(e)?d[0].addClass("cke_dialog_tab_disabled"): -d[0].removeClass("cke_dialog_tab_disabled")}}CKEDITOR.tools.setTimeout(function(){this.layout();b(this);this.parts.dialog.setStyle("visibility","");this.fireOnce("load",{});CKEDITOR.ui.fire("ready",this);this.fire("show",{});this._.editor.fire("dialogShow",this);this._.parentDialog||this._.editor.focusManager.lock();this.foreach(function(a){a.setInitValue&&a.setInitValue()})},100,this)},layout:function(){var a=this.parts.dialog,b=this.getSize(),c=CKEDITOR.document.getWindow().getViewPaneSize(),g= -(c.width-b.width)/2,d=(c.height-b.height)/2;CKEDITOR.env.ie6Compat||(b.height+(0<d?d:0)>c.height||b.width+(0<g?g:0)>c.width?a.setStyle("position","absolute"):a.setStyle("position","fixed"));this.move(this._.moved?this._.position.x:g,this._.moved?this._.position.y:d)},foreach:function(a){for(var b in this._.contents)for(var c in this._.contents[b])a.call(this,this._.contents[b][c]);return this},reset:function(){var a=function(a){a.reset&&a.reset(1)};return function(){this.foreach(a);return this}}(), +2),CKEDITOR.dialog._.currentTop=this);a.on("keydown",I);a.on("keyup",F);this._.hasFocus=!1;for(var d in c.contents)if(c.contents[d]){var a=c.contents[d],g=this._.tabs[a.id],e=a.requiredContent,f=0;if(g){for(var h in this._.contents[a.id]){var k=this._.contents[a.id][h];"hbox"!=k.type&&"vbox"!=k.type&&k.getInputElement()&&(k.requiredContent&&!this._.editor.activeFilter.check(k.requiredContent)?k.disable():(k.enable(),f++))}!f||e&&!this._.editor.activeFilter.check(e)?g[0].addClass("cke_dialog_tab_disabled"): +g[0].removeClass("cke_dialog_tab_disabled")}}CKEDITOR.tools.setTimeout(function(){this.layout();b(this);this.parts.dialog.setStyle("visibility","");this.fireOnce("load",{});CKEDITOR.ui.fire("ready",this);this.fire("show",{});this._.editor.fire("dialogShow",this);this._.parentDialog||this._.editor.focusManager.lock();this.foreach(function(a){a.setInitValue&&a.setInitValue()})},100,this)},layout:function(){var a=this.parts.dialog,b=this.getSize(),c=CKEDITOR.document.getWindow().getViewPaneSize(),d= +(c.width-b.width)/2,g=(c.height-b.height)/2;CKEDITOR.env.ie6Compat||(b.height+(0<g?g:0)>c.height||b.width+(0<d?d:0)>c.width?a.setStyle("position","absolute"):a.setStyle("position","fixed"));this.move(this._.moved?this._.position.x:d,this._.moved?this._.position.y:g)},foreach:function(a){for(var b in this._.contents)for(var c in this._.contents[b])a.call(this,this._.contents[b][c]);return this},reset:function(){var a=function(a){a.reset&&a.reset(1)};return function(){this.foreach(a);return this}}(), setupContent:function(){var a=arguments;this.foreach(function(b){b.setup&&b.setup.apply(b,a)})},commitContent:function(){var a=arguments;this.foreach(function(b){CKEDITOR.env.ie&&this._.currentFocusIndex==b.focusIndex&&b.getInputElement().$.blur();b.commit&&b.commit.apply(b,a)})},hide:function(){if(this.parts.dialog.isVisible()){this.fire("hide",{});this._.editor.fire("dialogHide",this);this.selectPage(this._.tabIdList[0]);var a=this._.element;a.setStyle("display","none");this.parts.dialog.setStyle("visibility", -"hidden");for(H(this);CKEDITOR.dialog._.currentTop!=this;)CKEDITOR.dialog._.currentTop.hide();if(this._.parentDialog){var b=this._.parentDialog.getElement().getFirst();b.setStyle("z-index",parseInt(b.$.style.zIndex,10)+Math.floor(this._.editor.config.baseFloatZIndex/2))}else v(this._.editor);if(CKEDITOR.dialog._.currentTop=this._.parentDialog)CKEDITOR.dialog._.currentZIndex-=10;else{CKEDITOR.dialog._.currentZIndex=null;a.removeListener("keydown",I);a.removeListener("keyup",E);var c=this._.editor; -c.focus();setTimeout(function(){c.focusManager.unlock();CKEDITOR.env.iOS&&c.window.focus()},0)}delete this._.parentDialog;this.foreach(function(a){a.resetInitValue&&a.resetInitValue()});this.setState(CKEDITOR.DIALOG_STATE_IDLE)}},addPage:function(a){if(!a.requiredContent||this._.editor.filter.check(a.requiredContent)){for(var b=[],c=a.label?' title\x3d"'+CKEDITOR.tools.htmlEncode(a.label)+'"':"",g=CKEDITOR.dialog._.uiElementBuilders.vbox.build(this,{type:"vbox",className:"cke_dialog_page_contents", -children:a.elements,expand:!!a.expand,padding:a.padding,style:a.style||"width: 100%;"},b),d=this._.contents[a.id]={},e=g.getChild(),f=0;g=e.shift();)g.notAllowed||"hbox"==g.type||"vbox"==g.type||f++,d[g.id]=g,"function"==typeof g.getChild&&e.push.apply(e,g.getChild());f||(a.hidden=!0);b=CKEDITOR.dom.element.createFromHtml(b.join(""));b.setAttribute("role","tabpanel");g=CKEDITOR.env;d="cke_"+a.id+"_"+CKEDITOR.tools.getNextNumber();c=CKEDITOR.dom.element.createFromHtml(['\x3ca class\x3d"cke_dialog_tab"', -0<this._.pageCount?" cke_last":"cke_first",c,a.hidden?' style\x3d"display:none"':"",' id\x3d"',d,'"',g.gecko&&!g.hc?"":' href\x3d"javascript:void(0)"',' tabIndex\x3d"-1" hidefocus\x3d"true" role\x3d"tab"\x3e',a.label,"\x3c/a\x3e"].join(""));b.setAttribute("aria-labelledby",d);this._.tabs[a.id]=[c,b];this._.tabIdList.push(a.id);!a.hidden&&this._.pageCount++;this._.lastTab=c;this.updateStyle();b.setAttribute("name",a.id);b.appendTo(this.parts.contents);c.unselectable();this.parts.tabs.append(c);a.accessKey&& -(F(this,this,"CTRL+"+a.accessKey,L,G),this._.accessKeyMap["CTRL+"+a.accessKey]=a.id)}},selectPage:function(a){if(this._.currentTabId!=a&&!this._.tabs[a][0].hasClass("cke_dialog_tab_disabled")&&!1!==this.fire("selectPage",{page:a,currentPage:this._.currentTabId})){for(var b in this._.tabs){var c=this._.tabs[b][0],g=this._.tabs[b][1];b!=a&&(c.removeClass("cke_dialog_tab_selected"),g.hide());g.setAttribute("aria-hidden",b!=a)}var d=this._.tabs[a];d[0].addClass("cke_dialog_tab_selected");CKEDITOR.env.ie6Compat|| -CKEDITOR.env.ie7Compat?(e(d[1]),d[1].show(),setTimeout(function(){e(d[1],1)},0)):d[1].show();this._.currentTabId=a;this._.currentTabIndex=CKEDITOR.tools.indexOf(this._.tabIdList,a)}},updateStyle:function(){this.parts.dialog[(1===this._.pageCount?"add":"remove")+"Class"]("cke_single_page")},hidePage:function(a){var b=this._.tabs[a]&&this._.tabs[a][0];b&&1!=this._.pageCount&&b.isVisible()&&(a==this._.currentTabId&&this.selectPage(f.call(this)),b.hide(),this._.pageCount--,this.updateStyle())},showPage:function(a){if(a= +"hidden");for(H(this);CKEDITOR.dialog._.currentTop!=this;)CKEDITOR.dialog._.currentTop.hide();if(this._.parentDialog){var b=this._.parentDialog.getElement().getFirst();b.setStyle("z-index",parseInt(b.$.style.zIndex,10)+Math.floor(this._.editor.config.baseFloatZIndex/2))}else v(this._.editor);if(CKEDITOR.dialog._.currentTop=this._.parentDialog)CKEDITOR.dialog._.currentZIndex-=10;else{CKEDITOR.dialog._.currentZIndex=null;a.removeListener("keydown",I);a.removeListener("keyup",F);var c=this._.editor; +c.focus();setTimeout(function(){c.focusManager.unlock();CKEDITOR.env.iOS&&c.window.focus()},0)}delete this._.parentDialog;this.foreach(function(a){a.resetInitValue&&a.resetInitValue()});this.setState(CKEDITOR.DIALOG_STATE_IDLE)}},addPage:function(a){if(!a.requiredContent||this._.editor.filter.check(a.requiredContent)){for(var b=[],c=a.label?' title\x3d"'+CKEDITOR.tools.htmlEncode(a.label)+'"':"",d=CKEDITOR.dialog._.uiElementBuilders.vbox.build(this,{type:"vbox",className:"cke_dialog_page_contents", +children:a.elements,expand:!!a.expand,padding:a.padding,style:a.style||"width: 100%;"},b),g=this._.contents[a.id]={},e=d.getChild(),f=0;d=e.shift();)d.notAllowed||"hbox"==d.type||"vbox"==d.type||f++,g[d.id]=d,"function"==typeof d.getChild&&e.push.apply(e,d.getChild());f||(a.hidden=!0);b=CKEDITOR.dom.element.createFromHtml(b.join(""));b.setAttribute("role","tabpanel");d=CKEDITOR.env;g="cke_"+a.id+"_"+CKEDITOR.tools.getNextNumber();c=CKEDITOR.dom.element.createFromHtml(['\x3ca class\x3d"cke_dialog_tab"', +0<this._.pageCount?" cke_last":"cke_first",c,a.hidden?' style\x3d"display:none"':"",' id\x3d"',g,'"',d.gecko&&!d.hc?"":' href\x3d"javascript:void(0)"',' tabIndex\x3d"-1" hidefocus\x3d"true" role\x3d"tab"\x3e',a.label,"\x3c/a\x3e"].join(""));b.setAttribute("aria-labelledby",g);this._.tabs[a.id]=[c,b];this._.tabIdList.push(a.id);!a.hidden&&this._.pageCount++;this._.lastTab=c;this.updateStyle();b.setAttribute("name",a.id);b.appendTo(this.parts.contents);c.unselectable();this.parts.tabs.append(c);a.accessKey&& +(E(this,this,"CTRL+"+a.accessKey,L,G),this._.accessKeyMap["CTRL+"+a.accessKey]=a.id)}},selectPage:function(a){if(this._.currentTabId!=a&&!this._.tabs[a][0].hasClass("cke_dialog_tab_disabled")&&!1!==this.fire("selectPage",{page:a,currentPage:this._.currentTabId})){for(var b in this._.tabs){var c=this._.tabs[b][0],d=this._.tabs[b][1];b!=a&&(c.removeClass("cke_dialog_tab_selected"),d.hide());d.setAttribute("aria-hidden",b!=a)}var g=this._.tabs[a];g[0].addClass("cke_dialog_tab_selected");CKEDITOR.env.ie6Compat|| +CKEDITOR.env.ie7Compat?(e(g[1]),g[1].show(),setTimeout(function(){e(g[1],1)},0)):g[1].show();this._.currentTabId=a;this._.currentTabIndex=CKEDITOR.tools.indexOf(this._.tabIdList,a)}},updateStyle:function(){this.parts.dialog[(1===this._.pageCount?"add":"remove")+"Class"]("cke_single_page")},hidePage:function(a){var b=this._.tabs[a]&&this._.tabs[a][0];b&&1!=this._.pageCount&&b.isVisible()&&(a==this._.currentTabId&&this.selectPage(f.call(this)),b.hide(),this._.pageCount--,this.updateStyle())},showPage:function(a){if(a= this._.tabs[a]&&this._.tabs[a][0])a.show(),this._.pageCount++,this.updateStyle()},getElement:function(){return this._.element},getName:function(){return this._.name},getContentElement:function(a,b){var c=this._.contents[a];return c&&c[b]},getValueOf:function(a,b){return this.getContentElement(a,b).getValue()},setValueOf:function(a,b,c){return this.getContentElement(a,b).setValue(c)},getButton:function(a){return this._.buttons[a]},click:function(a){return this._.buttons[a].click()},disableButton:function(a){return this._.buttons[a].disable()}, enableButton:function(a){return this._.buttons[a].enable()},getPageCount:function(){return this._.pageCount},getParentEditor:function(){return this._.editor},getSelectedElement:function(){return this.getParentEditor().getSelection().getSelectedElement()},addFocusable:function(a,b){if("undefined"==typeof b)b=this._.focusList.length,this._.focusList.push(new m(this,a,b));else{this._.focusList.splice(b,0,new m(this,a,b));for(var c=b+1;c<this._.focusList.length;c++)this._.focusList[c].focusIndex++}}, setState:function(a){if(this.state!=a){this.state=a;if(a==CKEDITOR.DIALOG_STATE_BUSY){if(!this.parts.spinner){var b=this.getParentEditor().lang.dir,c={attributes:{"class":"cke_dialog_spinner"},styles:{"float":"rtl"==b?"right":"left"}};c.styles["margin-"+("rtl"==b?"left":"right")]="8px";this.parts.spinner=CKEDITOR.document.createElement("div",c);this.parts.spinner.setHtml("\x26#8987;");this.parts.spinner.appendTo(this.parts.title,1)}this.parts.spinner.show();this.getButton("ok").disable()}else a== CKEDITOR.DIALOG_STATE_IDLE&&(this.parts.spinner&&this.parts.spinner.hide(),this.getButton("ok").enable());this.fire("state",a)}}};CKEDITOR.tools.extend(CKEDITOR.dialog,{add:function(a,b){this._.dialogDefinitions[a]&&"function"!=typeof b||(this._.dialogDefinitions[a]=b)},exists:function(a){return!!this._.dialogDefinitions[a]},getCurrent:function(){return CKEDITOR.dialog._.currentTop},isTabEnabled:function(a,b,c){a=a.config.removeDialogTabs;return!(a&&a.match(new RegExp("(?:^|;)"+b+":"+c+"(?:$|;)", "i")))},okButton:function(){var a=function(a,b){b=b||{};return CKEDITOR.tools.extend({id:"ok",type:"button",label:a.lang.common.ok,"class":"cke_dialog_ui_button_ok",onClick:function(a){a=a.data.dialog;!1!==a.fire("ok",{hide:!0}).hide&&a.hide()}},b,!0)};a.type="button";a.override=function(b){return CKEDITOR.tools.extend(function(c){return a(c,b)},{type:"button"},!0)};return a}(),cancelButton:function(){var a=function(a,b){b=b||{};return CKEDITOR.tools.extend({id:"cancel",type:"button",label:a.lang.common.cancel, "class":"cke_dialog_ui_button_cancel",onClick:function(a){a=a.data.dialog;!1!==a.fire("cancel",{hide:!0}).hide&&a.hide()}},b,!0)};a.type="button";a.override=function(b){return CKEDITOR.tools.extend(function(c){return a(c,b)},{type:"button"},!0)};return a}(),addUIElement:function(a,b){this._.uiElementBuilders[a]=b}});CKEDITOR.dialog._={uiElementBuilders:{},dialogDefinitions:{},currentTop:null,currentZIndex:null};CKEDITOR.event.implementOn(CKEDITOR.dialog);CKEDITOR.event.implementOn(CKEDITOR.dialog.prototype); -var q={resizable:CKEDITOR.DIALOG_RESIZE_BOTH,minWidth:600,minHeight:400,buttons:[CKEDITOR.dialog.okButton,CKEDITOR.dialog.cancelButton]},u=function(a,b,c){for(var g=0,d;d=a[g];g++)if(d.id==b||c&&d[c]&&(d=u(d[c],b,c)))return d;return null},x=function(a,b,c,g,d){if(c){for(var e=0,f;f=a[e];e++){if(f.id==c)return a.splice(e,0,b),b;if(g&&f[g]&&(f=x(f[g],b,c,g,!0)))return f}if(d)return null}a.push(b);return b},A=function(a,b,c){for(var g=0,d;d=a[g];g++){if(d.id==b)return a.splice(g,1);if(c&&d[c]&&(d=A(d[c], -b,c)))return d}return null},D=function(a,b){this.dialog=a;for(var c=b.contents,d=0,e;e=c[d];d++)c[d]=e&&new g(a,e);CKEDITOR.tools.extend(this,b)};D.prototype={getContents:function(a){return u(this.contents,a)},getButton:function(a){return u(this.buttons,a)},addContents:function(a,b){return x(this.contents,a,b)},addButton:function(a,b){return x(this.buttons,a,b)},removeContents:function(a){A(this.contents,a)},removeButton:function(a){A(this.buttons,a)}};g.prototype={get:function(a){return u(this.elements, -a,"children")},add:function(a,b){return x(this.elements,a,b,"children")},remove:function(a){A(this.elements,a,"children")}};var t,B={},y,z={},I=function(a){var b=a.data.$.ctrlKey||a.data.$.metaKey,c=a.data.$.altKey,g=a.data.$.shiftKey,d=String.fromCharCode(a.data.$.keyCode);(b=z[(b?"CTRL+":"")+(c?"ALT+":"")+(g?"SHIFT+":"")+d])&&b.length&&(b=b[b.length-1],b.keydown&&b.keydown.call(b.uiElement,b.dialog,b.key),a.data.preventDefault())},E=function(a){var b=a.data.$.ctrlKey||a.data.$.metaKey,c=a.data.$.altKey, -g=a.data.$.shiftKey,d=String.fromCharCode(a.data.$.keyCode);(b=z[(b?"CTRL+":"")+(c?"ALT+":"")+(g?"SHIFT+":"")+d])&&b.length&&(b=b[b.length-1],b.keyup&&(b.keyup.call(b.uiElement,b.dialog,b.key),a.data.preventDefault()))},F=function(a,b,c,g,d){(z[c]||(z[c]=[])).push({uiElement:a,dialog:b,key:c,keyup:d||a.accessKeyUp,keydown:g||a.accessKeyDown})},H=function(a){for(var b in z){for(var c=z[b],g=c.length-1;0<=g;g--)c[g].dialog!=a&&c[g].uiElement!=a||c.splice(g,1);0===c.length&&delete z[b]}},G=function(a, -b){a._.accessKeyMap[b]&&a.selectPage(a._.accessKeyMap[b])},L=function(){};(function(){CKEDITOR.ui.dialog={uiElement:function(a,b,c,g,d,e,f){if(!(4>arguments.length)){var h=(g.call?g(b):g)||"div",k=["\x3c",h," "],n=(d&&d.call?d(b):d)||{},l=(e&&e.call?e(b):e)||{},m=(f&&f.call?f.call(this,a,b):f)||"",q=this.domId=l.id||CKEDITOR.tools.getNextId()+"_uiElement";b.requiredContent&&!a.getParentEditor().filter.check(b.requiredContent)&&(n.display="none",this.notAllowed=!0);l.id=q;var r={};b.type&&(r["cke_dialog_ui_"+ -b.type]=1);b.className&&(r[b.className]=1);b.disabled&&(r.cke_disabled=1);for(var t=l["class"]&&l["class"].split?l["class"].split(" "):[],q=0;q<t.length;q++)t[q]&&(r[t[q]]=1);t=[];for(q in r)t.push(q);l["class"]=t.join(" ");b.title&&(l.title=b.title);r=(b.style||"").split(";");b.align&&(t=b.align,n["margin-left"]="left"==t?0:"auto",n["margin-right"]="right"==t?0:"auto");for(q in n)r.push(q+":"+n[q]);b.hidden&&r.push("display:none");for(q=r.length-1;0<=q;q--)""===r[q]&&r.splice(q,1);0<r.length&&(l.style= -(l.style?l.style+"; ":"")+r.join("; "));for(q in l)k.push(q+'\x3d"'+CKEDITOR.tools.htmlEncode(l[q])+'" ');k.push("\x3e",m,"\x3c/",h,"\x3e");c.push(k.join(""));(this._||(this._={})).dialog=a;"boolean"==typeof b.isChanged&&(this.isChanged=function(){return b.isChanged});"function"==typeof b.isChanged&&(this.isChanged=b.isChanged);"function"==typeof b.setValue&&(this.setValue=CKEDITOR.tools.override(this.setValue,function(a){return function(c){a.call(this,b.setValue.call(this,c))}}));"function"==typeof b.getValue&& -(this.getValue=CKEDITOR.tools.override(this.getValue,function(a){return function(){return b.getValue.call(this,a.call(this))}}));CKEDITOR.event.implementOn(this);this.registerEvents(b);this.accessKeyUp&&this.accessKeyDown&&b.accessKey&&F(this,a,"CTRL+"+b.accessKey);var p=this;a.on("load",function(){var b=p.getInputElement();if(b){var c=p.type in{checkbox:1,ratio:1}&&CKEDITOR.env.ie&&8>CKEDITOR.env.version?"cke_dialog_ui_focused":"";b.on("focus",function(){a._.tabBarMode=!1;a._.hasFocus=!0;p.fire("focus"); -c&&this.addClass(c)});b.on("blur",function(){p.fire("blur");c&&this.removeClass(c)})}});CKEDITOR.tools.extend(this,b);this.keyboardFocusable&&(this.tabIndex=b.tabIndex||0,this.focusIndex=a._.focusList.push(this)-1,this.on("focus",function(){a._.currentFocusIndex=p.focusIndex}))}},hbox:function(a,b,c,g,d){if(!(4>arguments.length)){this._||(this._={});var e=this._.children=b,f=d&&d.widths||null,h=d&&d.height||null,k,n={role:"presentation"};d&&d.align&&(n.align=d.align);CKEDITOR.ui.dialog.uiElement.call(this, -a,d||{type:"hbox"},g,"table",{},n,function(){var a=['\x3ctbody\x3e\x3ctr class\x3d"cke_dialog_ui_hbox"\x3e'];for(k=0;k<c.length;k++){var b="cke_dialog_ui_hbox_child",g=[];0===k&&(b="cke_dialog_ui_hbox_first");k==c.length-1&&(b="cke_dialog_ui_hbox_last");a.push('\x3ctd class\x3d"',b,'" role\x3d"presentation" ');f?f[k]&&g.push("width:"+p(f[k])):g.push("width:"+Math.floor(100/c.length)+"%");h&&g.push("height:"+p(h));d&&void 0!==d.padding&&g.push("padding:"+p(d.padding));CKEDITOR.env.ie&&CKEDITOR.env.quirks&& -e[k].align&&g.push("text-align:"+e[k].align);0<g.length&&a.push('style\x3d"'+g.join("; ")+'" ');a.push("\x3e",c[k],"\x3c/td\x3e")}a.push("\x3c/tr\x3e\x3c/tbody\x3e");return a.join("")})}},vbox:function(a,b,c,g,d){if(!(3>arguments.length)){this._||(this._={});var e=this._.children=b,f=d&&d.width||null,h=d&&d.heights||null;CKEDITOR.ui.dialog.uiElement.call(this,a,d||{type:"vbox"},g,"div",null,{role:"presentation"},function(){var b=['\x3ctable role\x3d"presentation" cellspacing\x3d"0" border\x3d"0" ']; -b.push('style\x3d"');d&&d.expand&&b.push("height:100%;");b.push("width:"+p(f||"100%"),";");CKEDITOR.env.webkit&&b.push("float:none;");b.push('"');b.push('align\x3d"',CKEDITOR.tools.htmlEncode(d&&d.align||("ltr"==a.getParentEditor().lang.dir?"left":"right")),'" ');b.push("\x3e\x3ctbody\x3e");for(var g=0;g<c.length;g++){var k=[];b.push('\x3ctr\x3e\x3ctd role\x3d"presentation" ');f&&k.push("width:"+p(f||"100%"));h?k.push("height:"+p(h[g])):d&&d.expand&&k.push("height:"+Math.floor(100/c.length)+"%"); -d&&void 0!==d.padding&&k.push("padding:"+p(d.padding));CKEDITOR.env.ie&&CKEDITOR.env.quirks&&e[g].align&&k.push("text-align:"+e[g].align);0<k.length&&b.push('style\x3d"',k.join("; "),'" ');b.push(' class\x3d"cke_dialog_ui_vbox_child"\x3e',c[g],"\x3c/td\x3e\x3c/tr\x3e")}b.push("\x3c/tbody\x3e\x3c/table\x3e");return b.join("")})}}}})();CKEDITOR.ui.dialog.uiElement.prototype={getElement:function(){return CKEDITOR.document.getById(this.domId)},getInputElement:function(){return this.getElement()},getDialog:function(){return this._.dialog}, +var q={resizable:CKEDITOR.DIALOG_RESIZE_BOTH,minWidth:600,minHeight:400,buttons:[CKEDITOR.dialog.okButton,CKEDITOR.dialog.cancelButton]},A=function(a,b,c){for(var d=0,g;g=a[d];d++)if(g.id==b||c&&g[c]&&(g=A(g[c],b,c)))return g;return null},r=function(a,b,c,d,g){if(c){for(var e=0,f;f=a[e];e++){if(f.id==c)return a.splice(e,0,b),b;if(d&&f[d]&&(f=r(f[d],b,c,d,!0)))return f}if(g)return null}a.push(b);return b},C=function(a,b,c){for(var d=0,g;g=a[d];d++){if(g.id==b)return a.splice(d,1);if(c&&g[c]&&(g=C(g[c], +b,c)))return g}return null},B=function(a,b){this.dialog=a;for(var c=b.contents,d=0,e;e=c[d];d++)c[d]=e&&new g(a,e);CKEDITOR.tools.extend(this,b)};B.prototype={getContents:function(a){return A(this.contents,a)},getButton:function(a){return A(this.buttons,a)},addContents:function(a,b){return r(this.contents,a,b)},addButton:function(a,b){return r(this.buttons,a,b)},removeContents:function(a){C(this.contents,a)},removeButton:function(a){C(this.buttons,a)}};g.prototype={get:function(a){return A(this.elements, +a,"children")},add:function(a,b){return r(this.elements,a,b,"children")},remove:function(a){C(this.elements,a,"children")}};var u,y={},x,z={},I=function(a){var b=a.data.$.ctrlKey||a.data.$.metaKey,c=a.data.$.altKey,d=a.data.$.shiftKey,g=String.fromCharCode(a.data.$.keyCode);(b=z[(b?"CTRL+":"")+(c?"ALT+":"")+(d?"SHIFT+":"")+g])&&b.length&&(b=b[b.length-1],b.keydown&&b.keydown.call(b.uiElement,b.dialog,b.key),a.data.preventDefault())},F=function(a){var b=a.data.$.ctrlKey||a.data.$.metaKey,c=a.data.$.altKey, +d=a.data.$.shiftKey,g=String.fromCharCode(a.data.$.keyCode);(b=z[(b?"CTRL+":"")+(c?"ALT+":"")+(d?"SHIFT+":"")+g])&&b.length&&(b=b[b.length-1],b.keyup&&(b.keyup.call(b.uiElement,b.dialog,b.key),a.data.preventDefault()))},E=function(a,b,c,d,g){(z[c]||(z[c]=[])).push({uiElement:a,dialog:b,key:c,keyup:g||a.accessKeyUp,keydown:d||a.accessKeyDown})},H=function(a){for(var b in z){for(var c=z[b],d=c.length-1;0<=d;d--)c[d].dialog!=a&&c[d].uiElement!=a||c.splice(d,1);0===c.length&&delete z[b]}},G=function(a, +b){a._.accessKeyMap[b]&&a.selectPage(a._.accessKeyMap[b])},L=function(){};(function(){CKEDITOR.ui.dialog={uiElement:function(a,b,c,d,g,e,f){if(!(4>arguments.length)){var h=(d.call?d(b):d)||"div",k=["\x3c",h," "],n=(g&&g.call?g(b):g)||{},l=(e&&e.call?e(b):e)||{},m=(f&&f.call?f.call(this,a,b):f)||"",q=this.domId=l.id||CKEDITOR.tools.getNextId()+"_uiElement";b.requiredContent&&!a.getParentEditor().filter.check(b.requiredContent)&&(n.display="none",this.notAllowed=!0);l.id=q;var p={};b.type&&(p["cke_dialog_ui_"+ +b.type]=1);b.className&&(p[b.className]=1);b.disabled&&(p.cke_disabled=1);for(var r=l["class"]&&l["class"].split?l["class"].split(" "):[],q=0;q<r.length;q++)r[q]&&(p[r[q]]=1);r=[];for(q in p)r.push(q);l["class"]=r.join(" ");b.title&&(l.title=b.title);p=(b.style||"").split(";");b.align&&(r=b.align,n["margin-left"]="left"==r?0:"auto",n["margin-right"]="right"==r?0:"auto");for(q in n)p.push(q+":"+n[q]);b.hidden&&p.push("display:none");for(q=p.length-1;0<=q;q--)""===p[q]&&p.splice(q,1);0<p.length&&(l.style= +(l.style?l.style+"; ":"")+p.join("; "));for(q in l)k.push(q+'\x3d"'+CKEDITOR.tools.htmlEncode(l[q])+'" ');k.push("\x3e",m,"\x3c/",h,"\x3e");c.push(k.join(""));(this._||(this._={})).dialog=a;"boolean"==typeof b.isChanged&&(this.isChanged=function(){return b.isChanged});"function"==typeof b.isChanged&&(this.isChanged=b.isChanged);"function"==typeof b.setValue&&(this.setValue=CKEDITOR.tools.override(this.setValue,function(a){return function(c){a.call(this,b.setValue.call(this,c))}}));"function"==typeof b.getValue&& +(this.getValue=CKEDITOR.tools.override(this.getValue,function(a){return function(){return b.getValue.call(this,a.call(this))}}));CKEDITOR.event.implementOn(this);this.registerEvents(b);this.accessKeyUp&&this.accessKeyDown&&b.accessKey&&E(this,a,"CTRL+"+b.accessKey);var u=this;a.on("load",function(){var b=u.getInputElement();if(b){var c=u.type in{checkbox:1,ratio:1}&&CKEDITOR.env.ie&&8>CKEDITOR.env.version?"cke_dialog_ui_focused":"";b.on("focus",function(){a._.tabBarMode=!1;a._.hasFocus=!0;u.fire("focus"); +c&&this.addClass(c)});b.on("blur",function(){u.fire("blur");c&&this.removeClass(c)})}});CKEDITOR.tools.extend(this,b);this.keyboardFocusable&&(this.tabIndex=b.tabIndex||0,this.focusIndex=a._.focusList.push(this)-1,this.on("focus",function(){a._.currentFocusIndex=u.focusIndex}))}},hbox:function(a,b,c,d,g){if(!(4>arguments.length)){this._||(this._={});var e=this._.children=b,f=g&&g.widths||null,h=g&&g.height||null,k,n={role:"presentation"};g&&g.align&&(n.align=g.align);CKEDITOR.ui.dialog.uiElement.call(this, +a,g||{type:"hbox"},d,"table",{},n,function(){var a=['\x3ctbody\x3e\x3ctr class\x3d"cke_dialog_ui_hbox"\x3e'];for(k=0;k<c.length;k++){var b="cke_dialog_ui_hbox_child",d=[];0===k&&(b="cke_dialog_ui_hbox_first");k==c.length-1&&(b="cke_dialog_ui_hbox_last");a.push('\x3ctd class\x3d"',b,'" role\x3d"presentation" ');f?f[k]&&d.push("width:"+t(f[k])):d.push("width:"+Math.floor(100/c.length)+"%");h&&d.push("height:"+t(h));g&&void 0!==g.padding&&d.push("padding:"+t(g.padding));CKEDITOR.env.ie&&CKEDITOR.env.quirks&& +e[k].align&&d.push("text-align:"+e[k].align);0<d.length&&a.push('style\x3d"'+d.join("; ")+'" ');a.push("\x3e",c[k],"\x3c/td\x3e")}a.push("\x3c/tr\x3e\x3c/tbody\x3e");return a.join("")})}},vbox:function(a,b,c,d,g){if(!(3>arguments.length)){this._||(this._={});var e=this._.children=b,f=g&&g.width||null,h=g&&g.heights||null;CKEDITOR.ui.dialog.uiElement.call(this,a,g||{type:"vbox"},d,"div",null,{role:"presentation"},function(){var b=['\x3ctable role\x3d"presentation" cellspacing\x3d"0" border\x3d"0" ']; +b.push('style\x3d"');g&&g.expand&&b.push("height:100%;");b.push("width:"+t(f||"100%"),";");CKEDITOR.env.webkit&&b.push("float:none;");b.push('"');b.push('align\x3d"',CKEDITOR.tools.htmlEncode(g&&g.align||("ltr"==a.getParentEditor().lang.dir?"left":"right")),'" ');b.push("\x3e\x3ctbody\x3e");for(var d=0;d<c.length;d++){var k=[];b.push('\x3ctr\x3e\x3ctd role\x3d"presentation" ');f&&k.push("width:"+t(f||"100%"));h?k.push("height:"+t(h[d])):g&&g.expand&&k.push("height:"+Math.floor(100/c.length)+"%"); +g&&void 0!==g.padding&&k.push("padding:"+t(g.padding));CKEDITOR.env.ie&&CKEDITOR.env.quirks&&e[d].align&&k.push("text-align:"+e[d].align);0<k.length&&b.push('style\x3d"',k.join("; "),'" ');b.push(' class\x3d"cke_dialog_ui_vbox_child"\x3e',c[d],"\x3c/td\x3e\x3c/tr\x3e")}b.push("\x3c/tbody\x3e\x3c/table\x3e");return b.join("")})}}}})();CKEDITOR.ui.dialog.uiElement.prototype={getElement:function(){return CKEDITOR.document.getById(this.domId)},getInputElement:function(){return this.getElement()},getDialog:function(){return this._.dialog}, setValue:function(a,b){this.getInputElement().setValue(a);!b&&this.fire("change",{value:a});return this},getValue:function(){return this.getInputElement().getValue()},isChanged:function(){return!1},selectParentTab:function(){for(var a=this.getInputElement();(a=a.getParent())&&-1==a.$.className.search("cke_dialog_page_contents"););if(!a)return this;a=a.getAttribute("name");this._.dialog._.currentTabId!=a&&this._.dialog.selectPage(a);return this},focus:function(){this.selectParentTab().getInputElement().focus(); -return this},registerEvents:function(a){var b=/^on([A-Z]\w+)/,c,g=function(a,b,c,g){b.on("load",function(){a.getInputElement().on(c,g,a)})},d;for(d in a)if(c=d.match(b))this.eventProcessors[d]?this.eventProcessors[d].call(this,this._.dialog,a[d]):g(this,this._.dialog,c[1].toLowerCase(),a[d]);return this},eventProcessors:{onLoad:function(a,b){a.on("load",b,this)},onShow:function(a,b){a.on("show",b,this)},onHide:function(a,b){a.on("hide",b,this)}},accessKeyDown:function(){this.focus()},accessKeyUp:function(){}, +return this},registerEvents:function(a){var b=/^on([A-Z]\w+)/,c,d=function(a,b,c,d){b.on("load",function(){a.getInputElement().on(c,d,a)})},g;for(g in a)if(c=g.match(b))this.eventProcessors[g]?this.eventProcessors[g].call(this,this._.dialog,a[g]):d(this,this._.dialog,c[1].toLowerCase(),a[g]);return this},eventProcessors:{onLoad:function(a,b){a.on("load",b,this)},onShow:function(a,b){a.on("show",b,this)},onHide:function(a,b){a.on("hide",b,this)}},accessKeyDown:function(){this.focus()},accessKeyUp:function(){}, disable:function(){var a=this.getElement();this.getInputElement().setAttribute("disabled","true");a.addClass("cke_disabled")},enable:function(){var a=this.getElement();this.getInputElement().removeAttribute("disabled");a.removeClass("cke_disabled")},isEnabled:function(){return!this.getElement().hasClass("cke_disabled")},isVisible:function(){return this.getInputElement().isVisible()},isFocusable:function(){return this.isEnabled()&&this.isVisible()?!0:!1}};CKEDITOR.ui.dialog.hbox.prototype=CKEDITOR.tools.extend(new CKEDITOR.ui.dialog.uiElement, -{getChild:function(a){if(1>arguments.length)return this._.children.concat();a.splice||(a=[a]);return 2>a.length?this._.children[a[0]]:this._.children[a[0]]&&this._.children[a[0]].getChild?this._.children[a[0]].getChild(a.slice(1,a.length)):null}},!0);CKEDITOR.ui.dialog.vbox.prototype=new CKEDITOR.ui.dialog.hbox;(function(){var a={build:function(a,b,c){for(var g=b.children,d,e=[],f=[],h=0;h<g.length&&(d=g[h]);h++){var k=[];e.push(k);f.push(CKEDITOR.dialog._.uiElementBuilders[d.type].build(a,d,k))}return new CKEDITOR.ui.dialog[b.type](a, -f,e,c,b)}};CKEDITOR.dialog.addUIElement("hbox",a);CKEDITOR.dialog.addUIElement("vbox",a)})();CKEDITOR.dialogCommand=function(a,b){this.dialogName=a;CKEDITOR.tools.extend(this,b,!0)};CKEDITOR.dialogCommand.prototype={exec:function(a){var b=this.tabId;a.openDialog(this.dialogName,function(a){b&&a.selectPage(b)})},canUndo:!1,editorFocus:1};(function(){var a=/^([a]|[^a])+$/,b=/^\d*$/,c=/^\d*(?:\.\d+)?$/,g=/^(((\d*(\.\d+))|(\d*))(px|\%)?)?$/,d=/^(((\d*(\.\d+))|(\d*))(px|em|ex|in|cm|mm|pt|pc|\%)?)?$/i, -e=/^(\s*[\w-]+\s*:\s*[^:;]+(?:;|$))*$/;CKEDITOR.VALIDATE_OR=1;CKEDITOR.VALIDATE_AND=2;CKEDITOR.dialog.validate={functions:function(){var a=arguments;return function(){var b=this&&this.getValue?this.getValue():a[0],c,g=CKEDITOR.VALIDATE_AND,d=[],e;for(e=0;e<a.length;e++)if("function"==typeof a[e])d.push(a[e]);else break;e<a.length&&"string"==typeof a[e]&&(c=a[e],e++);e<a.length&&"number"==typeof a[e]&&(g=a[e]);var f=g==CKEDITOR.VALIDATE_AND?!0:!1;for(e=0;e<d.length;e++)f=g==CKEDITOR.VALIDATE_AND?f&& -d[e](b):f||d[e](b);return f?!0:c}},regex:function(a,b){return function(c){c=this&&this.getValue?this.getValue():c;return a.test(c)?!0:b}},notEmpty:function(b){return this.regex(a,b)},integer:function(a){return this.regex(b,a)},number:function(a){return this.regex(c,a)},cssLength:function(a){return this.functions(function(a){return d.test(CKEDITOR.tools.trim(a))},a)},htmlLength:function(a){return this.functions(function(a){return g.test(CKEDITOR.tools.trim(a))},a)},inlineStyle:function(a){return this.functions(function(a){return e.test(CKEDITOR.tools.trim(a))}, -a)},equals:function(a,b){return this.functions(function(b){return b==a},b)},notEqual:function(a,b){return this.functions(function(b){return b!=a},b)}};CKEDITOR.on("instanceDestroyed",function(a){if(CKEDITOR.tools.isEmpty(CKEDITOR.instances)){for(var b;b=CKEDITOR.dialog._.currentTop;)b.hide();for(var c in B)B[c].remove();B={}}a=a.editor._.storedDialogs;for(var g in a)a[g].destroy()})})();CKEDITOR.tools.extend(CKEDITOR.editor.prototype,{openDialog:function(a,b){var c=null,g=CKEDITOR.dialog._.dialogDefinitions[a]; -null===CKEDITOR.dialog._.currentTop&&w(this);if("function"==typeof g)c=this._.storedDialogs||(this._.storedDialogs={}),c=c[a]||(c[a]=new CKEDITOR.dialog(this,a)),b&&b.call(c,c),c.show();else{if("failed"==g)throw v(this),Error('[CKEDITOR.dialog.openDialog] Dialog "'+a+'" failed when loading definition.');"string"==typeof g&&CKEDITOR.scriptLoader.load(CKEDITOR.getUrl(g),function(){"function"!=typeof CKEDITOR.dialog._.dialogDefinitions[a]&&(CKEDITOR.dialog._.dialogDefinitions[a]="failed");this.openDialog(a, +{getChild:function(a){if(1>arguments.length)return this._.children.concat();a.splice||(a=[a]);return 2>a.length?this._.children[a[0]]:this._.children[a[0]]&&this._.children[a[0]].getChild?this._.children[a[0]].getChild(a.slice(1,a.length)):null}},!0);CKEDITOR.ui.dialog.vbox.prototype=new CKEDITOR.ui.dialog.hbox;(function(){var a={build:function(a,b,c){for(var d=b.children,g,e=[],f=[],h=0;h<d.length&&(g=d[h]);h++){var k=[];e.push(k);f.push(CKEDITOR.dialog._.uiElementBuilders[g.type].build(a,g,k))}return new CKEDITOR.ui.dialog[b.type](a, +f,e,c,b)}};CKEDITOR.dialog.addUIElement("hbox",a);CKEDITOR.dialog.addUIElement("vbox",a)})();CKEDITOR.dialogCommand=function(a,b){this.dialogName=a;CKEDITOR.tools.extend(this,b,!0)};CKEDITOR.dialogCommand.prototype={exec:function(a){var b=this.tabId;a.openDialog(this.dialogName,function(a){b&&a.selectPage(b)})},canUndo:!1,editorFocus:1};(function(){var a=/^([a]|[^a])+$/,b=/^\d*$/,c=/^\d*(?:\.\d+)?$/,d=/^(((\d*(\.\d+))|(\d*))(px|\%)?)?$/,g=/^(((\d*(\.\d+))|(\d*))(px|em|ex|in|cm|mm|pt|pc|\%)?)?$/i, +e=/^(\s*[\w-]+\s*:\s*[^:;]+(?:;|$))*$/;CKEDITOR.VALIDATE_OR=1;CKEDITOR.VALIDATE_AND=2;CKEDITOR.dialog.validate={functions:function(){var a=arguments;return function(){var b=this&&this.getValue?this.getValue():a[0],c,d=CKEDITOR.VALIDATE_AND,g=[],e;for(e=0;e<a.length;e++)if("function"==typeof a[e])g.push(a[e]);else break;e<a.length&&"string"==typeof a[e]&&(c=a[e],e++);e<a.length&&"number"==typeof a[e]&&(d=a[e]);var f=d==CKEDITOR.VALIDATE_AND?!0:!1;for(e=0;e<g.length;e++)f=d==CKEDITOR.VALIDATE_AND?f&& +g[e](b):f||g[e](b);return f?!0:c}},regex:function(a,b){return function(c){c=this&&this.getValue?this.getValue():c;return a.test(c)?!0:b}},notEmpty:function(b){return this.regex(a,b)},integer:function(a){return this.regex(b,a)},number:function(a){return this.regex(c,a)},cssLength:function(a){return this.functions(function(a){return g.test(CKEDITOR.tools.trim(a))},a)},htmlLength:function(a){return this.functions(function(a){return d.test(CKEDITOR.tools.trim(a))},a)},inlineStyle:function(a){return this.functions(function(a){return e.test(CKEDITOR.tools.trim(a))}, +a)},equals:function(a,b){return this.functions(function(b){return b==a},b)},notEqual:function(a,b){return this.functions(function(b){return b!=a},b)}};CKEDITOR.on("instanceDestroyed",function(a){if(CKEDITOR.tools.isEmpty(CKEDITOR.instances)){for(var b;b=CKEDITOR.dialog._.currentTop;)b.hide();for(var c in y)y[c].remove();y={}}a=a.editor._.storedDialogs;for(var d in a)a[d].destroy()})})();CKEDITOR.tools.extend(CKEDITOR.editor.prototype,{openDialog:function(a,b){var c=null,d=CKEDITOR.dialog._.dialogDefinitions[a]; +null===CKEDITOR.dialog._.currentTop&&w(this);if("function"==typeof d)c=this._.storedDialogs||(this._.storedDialogs={}),c=c[a]||(c[a]=new CKEDITOR.dialog(this,a)),b&&b.call(c,c),c.show();else{if("failed"==d)throw v(this),Error('[CKEDITOR.dialog.openDialog] Dialog "'+a+'" failed when loading definition.');"string"==typeof d&&CKEDITOR.scriptLoader.load(CKEDITOR.getUrl(d),function(){"function"!=typeof CKEDITOR.dialog._.dialogDefinitions[a]&&(CKEDITOR.dialog._.dialogDefinitions[a]="failed");this.openDialog(a, b)},this,0,1)}CKEDITOR.skin.loadPart("dialog");return c}})}(),CKEDITOR.plugins.add("dialog",{requires:"dialogui",init:function(f){f.on("doubleclick",function(h){h.data.dialog&&f.openDialog(h.data.dialog)},null,null,999)}}),function(){CKEDITOR.plugins.add("a11yhelp",{requires:"dialog",availableLangs:{af:1,ar:1,az:1,bg:1,ca:1,cs:1,cy:1,da:1,de:1,"de-ch":1,el:1,en:1,"en-au":1,"en-gb":1,eo:1,es:1,"es-mx":1,et:1,eu:1,fa:1,fi:1,fo:1,fr:1,"fr-ca":1,gl:1,gu:1,he:1,hi:1,hr:1,hu:1,id:1,it:1,ja:1,km:1,ko:1, ku:1,lt:1,lv:1,mk:1,mn:1,nb:1,nl:1,no:1,oc:1,pl:1,pt:1,"pt-br":1,ro:1,ru:1,si:1,sk:1,sl:1,sq:1,sr:1,"sr-latn":1,sv:1,th:1,tr:1,tt:1,ug:1,uk:1,vi:1,zh:1,"zh-cn":1},init:function(f){var h=this;f.addCommand("a11yHelp",{exec:function(){var e=f.langCode,e=h.availableLangs[e]?e:h.availableLangs[e.replace(/-.*/,"")]?e.replace(/-.*/,""):"en";CKEDITOR.scriptLoader.load(CKEDITOR.getUrl(h.path+"dialogs/lang/"+e+".js"),function(){f.lang.a11yhelp=h.langEntries[e];f.openDialog("a11yHelp")})},modes:{wysiwyg:1,source:1}, readOnly:1,canUndo:!1});f.setKeystroke(CKEDITOR.ALT+48,"a11yHelp");CKEDITOR.dialog.add("a11yHelp",this.path+"dialogs/a11yhelp.js");f.on("ariaEditorHelpLabel",function(e){e.data.label=f.lang.common.editorHelp})}})}(),CKEDITOR.plugins.add("about",{requires:"dialog",init:function(f){var h=f.addCommand("about",new CKEDITOR.dialogCommand("about"));h.modes={wysiwyg:1,source:1};h.canUndo=!1;h.readOnly=1;f.ui.addButton&&f.ui.addButton("About",{label:f.lang.about.dlgTitle,command:"about",toolbar:"about"}); CKEDITOR.dialog.add("about",this.path+"dialogs/about.js")}}),"use strict",function(){function f(f){function e(){l=f.document;m=l[CKEDITOR.env.ie?"getBody":"getDocumentElement"]();b=CKEDITOR.env.quirks?l.getBody():l.getDocumentElement();var a=CKEDITOR.env.quirks?b:b.findOne("body");a&&(a.setStyle("height","auto"),a.setStyle("min-height",CKEDITOR.env.safari?"0%":"auto"));g=CKEDITOR.dom.element.createFromHtml('\x3cspan style\x3d"margin:0;padding:0;border:0;clear:both;width:1px;height:1px;display:block;"\x3e'+ (CKEDITOR.env.webkit?"\x26nbsp;":"")+"\x3c/span\x3e",l)}function k(){w&&b.setStyle("overflow-y","hidden");var e=f.window.getViewPaneSize().height,k;m.append(g);k=g.getDocumentPosition(l).y+g.$.offsetHeight;g.remove();k+=c;k=Math.max(k,a);k=Math.min(k,n);k!=e&&d!=k&&(k=f.fire("autoGrow",{currentHeight:e,newHeight:k}).newHeight,f.resize(f.container.getStyle("width"),k,!0),d=k);w||(k<n&&b.$.scrollHeight>b.$.clientHeight?b.setStyle("overflow-y","hidden"):b.removeStyle("overflow-y"))}var d,l,m,b,g,c=f.config.autoGrow_bottomSpace|| -0,a=void 0!==f.config.autoGrow_minHeight?f.config.autoGrow_minHeight:200,n=f.config.autoGrow_maxHeight||Infinity,w=!f.config.autoGrow_maxHeight;f.addCommand("autogrow",{exec:k,modes:{wysiwyg:1},readOnly:1,canUndo:!1,editorFocus:!1});var v={contentDom:1,key:1,selectionChange:1,insertElement:1,mode:1},p;for(p in v)f.on(p,function(a){"wysiwyg"==a.editor.mode&&setTimeout(function(){var a=f.getCommand("maximize");!f.window||a&&a.state==CKEDITOR.TRISTATE_ON?d=null:(k(),w||k())},100)});f.on("afterCommandExec", +0,a=void 0!==f.config.autoGrow_minHeight?f.config.autoGrow_minHeight:200,n=f.config.autoGrow_maxHeight||Infinity,w=!f.config.autoGrow_maxHeight;f.addCommand("autogrow",{exec:k,modes:{wysiwyg:1},readOnly:1,canUndo:!1,editorFocus:!1});var v={contentDom:1,key:1,selectionChange:1,insertElement:1,mode:1},t;for(t in v)f.on(t,function(a){"wysiwyg"==a.editor.mode&&setTimeout(function(){var a=f.getCommand("maximize");!f.window||a&&a.state==CKEDITOR.TRISTATE_ON?d=null:(k(),w||k())},100)});f.on("afterCommandExec", function(a){"maximize"==a.data.name&&"wysiwyg"==a.editor.mode&&(a.data.command.state==CKEDITOR.TRISTATE_ON?b.removeStyle("overflow-y"):k())});f.on("contentDom",e);e();f.config.autoGrow_onStartup&&f.editable().isVisible()&&f.execCommand("autogrow")}CKEDITOR.plugins.add("autogrow",{init:function(h){if(h.elementMode!=CKEDITOR.ELEMENT_MODE_INLINE)h.on("instanceReady",function(){h.editable().isInline()?h.ui.space("contents").setStyle("height","auto"):f(h)})}})}(),CKEDITOR.plugins.add("basicstyles",{init:function(f){var h= 0,e=function(d,b,g,c){if(c){c=new CKEDITOR.style(c);var a=k[g];a.unshift(c);f.attachStyleStateChange(c,function(a){!f.readOnly&&f.getCommand(g).setState(a)});f.addCommand(g,new CKEDITOR.styleCommand(c,{contentForms:a}));f.ui.addButton&&f.ui.addButton(d,{label:b,command:g,toolbar:"basicstyles,"+(h+=10)})}},k={bold:["strong","b",["span",function(d){d=d.styles["font-weight"];return"bold"==d||700<=+d}]],italic:["em","i",["span",function(d){return"italic"==d.styles["font-style"]}]],underline:["u",["span", function(d){return"underline"==d.styles["text-decoration"]}]],strike:["s","strike",["span",function(d){return"line-through"==d.styles["text-decoration"]}]],subscript:["sub"],superscript:["sup"]},d=f.config,l=f.lang.basicstyles;e("Bold",l.bold,"bold",d.coreStyles_bold);e("Italic",l.italic,"italic",d.coreStyles_italic);e("Underline",l.underline,"underline",d.coreStyles_underline);e("Strike",l.strike,"strike",d.coreStyles_strike);e("Subscript",l.subscript,"subscript",d.coreStyles_subscript);e("Superscript", @@ -636,90 +637,90 @@ f.append(d);d=CKEDITOR.dom.element.createFromHtml('\x3ca class\x3d"cke_notificat e.setStyle("width",this._getPercentageProgress());return e},_getPercentageProgress:function(){return Math.round(100*(this.progress||0))+"%"},_hideAfterTimeout:function(){var e=this,f;this._hideTimeoutId&&clearTimeout(this._hideTimeoutId);if("number"==typeof this.duration)f=this.duration;else if("info"==this.type||"success"==this.type)f="number"==typeof this.editor.config.notification_duration?this.editor.config.notification_duration:5E3;f&&(e._hideTimeoutId=setTimeout(function(){e.hide()},f))}};h.prototype= {add:function(e){this.notifications.push(e);this.element.append(e.element);1==this.element.getChildCount()&&(CKEDITOR.document.getBody().append(this.element),this._attachListeners());this._layout()},remove:function(e){var f=CKEDITOR.tools.indexOf(this.notifications,e);0>f||(this.notifications.splice(f,1),e.element.remove(),this.element.getChildCount()||(this._removeListeners(),this.element.remove()))},_createElement:function(){var e=this.editor,f=e.config,d=new CKEDITOR.dom.element("div");d.addClass("cke_notifications_area"); d.setAttribute("id","cke_notifications_area_"+e.name);d.setStyle("z-index",f.baseFloatZIndex-2);return d},_attachListeners:function(){var e=CKEDITOR.document.getWindow(),f=this.editor;e.on("scroll",this._uiBuffer.input);e.on("resize",this._uiBuffer.input);f.on("change",this._changeBuffer.input);f.on("floatingSpaceLayout",this._layout,this,null,20);f.on("blur",this._layout,this,null,20)},_removeListeners:function(){var e=CKEDITOR.document.getWindow(),f=this.editor;e.removeListener("scroll",this._uiBuffer.input); -e.removeListener("resize",this._uiBuffer.input);f.removeListener("change",this._changeBuffer.input);f.removeListener("floatingSpaceLayout",this._layout);f.removeListener("blur",this._layout)},_layout:function(){function e(){f.setStyle("left",u(x+h.width-n-w))}var f=this.element,d=this.editor,h=d.ui.contentsElement.getClientRect(),m=d.ui.contentsElement.getDocumentPosition(),b,g,c=f.getClientRect(),a,n=this._notificationWidth,w=this._notificationMargin;a=CKEDITOR.document.getWindow();var v=a.getScrollPosition(), -p=a.getViewPaneSize(),r=CKEDITOR.document.getBody(),q=r.getDocumentPosition(),u=CKEDITOR.tools.cssLength;n&&w||(a=this.element.getChild(0),n=this._notificationWidth=a.getClientRect().width,w=this._notificationMargin=parseInt(a.getComputedStyle("margin-left"),10)+parseInt(a.getComputedStyle("margin-right"),10));d.toolbar&&(b=d.ui.space("top"),g=b.getClientRect());b&&b.isVisible()&&g.bottom>h.top&&g.bottom<h.bottom-c.height?f.setStyles({position:"fixed",top:u(g.bottom)}):0<h.top?f.setStyles({position:"absolute", -top:u(m.y)}):m.y+h.height-c.height>v.y?f.setStyles({position:"fixed",top:0}):f.setStyles({position:"absolute",top:u(m.y+h.height-c.height)});var x="fixed"==f.getStyle("position")?h.left:"static"!=r.getComputedStyle("position")?m.x-q.x:m.x;h.width<n+w?m.x+n+w>v.x+p.width?e():f.setStyle("left",u(x)):m.x+n+w>v.x+p.width?f.setStyle("left",u(x)):m.x+h.width/2+n/2+w>v.x+p.width?f.setStyle("left",u(x-m.x+v.x+p.width-n-w)):0>h.left+h.width-n-w?e():0>h.left+h.width/2-n/2?f.setStyle("left",u(x-m.x+v.x)):f.setStyle("left", -u(x+h.width/2-n/2-w/2))}};CKEDITOR.plugins.notification=f}(),function(){var f='\x3ca id\x3d"{id}" class\x3d"cke_button cke_button__{name} cke_button_{state} {cls}"'+(CKEDITOR.env.gecko&&!CKEDITOR.env.hc?"":" href\x3d\"javascript:void('{titleJs}')\"")+' title\x3d"{title}" tabindex\x3d"-1" hidefocus\x3d"true" role\x3d"button" aria-labelledby\x3d"{id}_label" aria-describedby\x3d"{id}_description" aria-haspopup\x3d"{hasArrow}" aria-disabled\x3d"{ariaDisabled}"';CKEDITOR.env.gecko&&CKEDITOR.env.mac&&(f+= +e.removeListener("resize",this._uiBuffer.input);f.removeListener("change",this._changeBuffer.input);f.removeListener("floatingSpaceLayout",this._layout);f.removeListener("blur",this._layout)},_layout:function(){function e(){f.setStyle("left",A(r+h.width-n-w))}var f=this.element,d=this.editor,h=d.ui.contentsElement.getClientRect(),m=d.ui.contentsElement.getDocumentPosition(),b,g,c=f.getClientRect(),a,n=this._notificationWidth,w=this._notificationMargin;a=CKEDITOR.document.getWindow();var v=a.getScrollPosition(), +t=a.getViewPaneSize(),p=CKEDITOR.document.getBody(),q=p.getDocumentPosition(),A=CKEDITOR.tools.cssLength;n&&w||(a=this.element.getChild(0),n=this._notificationWidth=a.getClientRect().width,w=this._notificationMargin=parseInt(a.getComputedStyle("margin-left"),10)+parseInt(a.getComputedStyle("margin-right"),10));d.toolbar&&(b=d.ui.space("top"),g=b.getClientRect());b&&b.isVisible()&&g.bottom>h.top&&g.bottom<h.bottom-c.height?f.setStyles({position:"fixed",top:A(g.bottom)}):0<h.top?f.setStyles({position:"absolute", +top:A(m.y)}):m.y+h.height-c.height>v.y?f.setStyles({position:"fixed",top:0}):f.setStyles({position:"absolute",top:A(m.y+h.height-c.height)});var r="fixed"==f.getStyle("position")?h.left:"static"!=p.getComputedStyle("position")?m.x-q.x:m.x;h.width<n+w?m.x+n+w>v.x+t.width?e():f.setStyle("left",A(r)):m.x+n+w>v.x+t.width?f.setStyle("left",A(r)):m.x+h.width/2+n/2+w>v.x+t.width?f.setStyle("left",A(r-m.x+v.x+t.width-n-w)):0>h.left+h.width-n-w?e():0>h.left+h.width/2-n/2?f.setStyle("left",A(r-m.x+v.x)):f.setStyle("left", +A(r+h.width/2-n/2-w/2))}};CKEDITOR.plugins.notification=f}(),function(){var f='\x3ca id\x3d"{id}" class\x3d"cke_button cke_button__{name} cke_button_{state} {cls}"'+(CKEDITOR.env.gecko&&!CKEDITOR.env.hc?"":" href\x3d\"javascript:void('{titleJs}')\"")+' title\x3d"{title}" tabindex\x3d"-1" hidefocus\x3d"true" role\x3d"button" aria-labelledby\x3d"{id}_label" aria-describedby\x3d"{id}_description" aria-haspopup\x3d"{hasArrow}" aria-disabled\x3d"{ariaDisabled}"';CKEDITOR.env.gecko&&CKEDITOR.env.mac&&(f+= ' onkeypress\x3d"return false;"');CKEDITOR.env.gecko&&(f+=' onblur\x3d"this.style.cssText \x3d this.style.cssText;"');var f=f+(' onkeydown\x3d"return CKEDITOR.tools.callFunction({keydownFn},event);" onfocus\x3d"return CKEDITOR.tools.callFunction({focusFn},event);" '+(CKEDITOR.env.ie?'onclick\x3d"return false;" onmouseup':"onclick")+'\x3d"CKEDITOR.tools.callFunction({clickFn},this);return false;"\x3e\x3cspan class\x3d"cke_button_icon cke_button__{iconName}_icon" style\x3d"{style}"'),f=f+'\x3e\x26nbsp;\x3c/span\x3e\x3cspan id\x3d"{id}_label" class\x3d"cke_button_label cke_button__{name}_label" aria-hidden\x3d"false"\x3e{label}\x3c/span\x3e\x3cspan id\x3d"{id}_description" class\x3d"cke_button_label" aria-hidden\x3d"false"\x3e{ariaShortcut}\x3c/span\x3e{arrowHtml}\x3c/a\x3e', h=CKEDITOR.addTemplate("buttonArrow",'\x3cspan class\x3d"cke_button_arrow"\x3e'+(CKEDITOR.env.hc?"\x26#9660;":"")+"\x3c/span\x3e"),e=CKEDITOR.addTemplate("button",f);CKEDITOR.plugins.add("button",{beforeInit:function(e){e.ui.addHandler(CKEDITOR.UI_BUTTON,CKEDITOR.ui.button.handler)}});CKEDITOR.UI_BUTTON="button";CKEDITOR.ui.button=function(e){CKEDITOR.tools.extend(this,e,{title:e.label,click:e.click||function(d){d.execCommand(e.command)}});this._={}};CKEDITOR.ui.button.handler={create:function(e){return new CKEDITOR.ui.button(e)}}; -CKEDITOR.ui.button.prototype={render:function(f,d){function l(){var a=f.mode;a&&(a=this.modes[a]?void 0!==m[a]?m[a]:CKEDITOR.TRISTATE_OFF:CKEDITOR.TRISTATE_DISABLED,a=f.readOnly&&!this.readOnly?CKEDITOR.TRISTATE_DISABLED:a,this.setState(a),this.refresh&&this.refresh())}var m=null,b=CKEDITOR.env,g=this._.id=CKEDITOR.tools.getNextId(),c="",a=this.command,n,w,v;this._.editor=f;var p={id:g,button:this,editor:f,focus:function(){CKEDITOR.document.getById(g).focus()},execute:function(){this.button.click(f)}, -attach:function(a){this.button.attach(a)}},r=CKEDITOR.tools.addFunction(function(a){if(p.onkey)return a=new CKEDITOR.dom.event(a),!1!==p.onkey(p,a.getKeystroke())}),q=CKEDITOR.tools.addFunction(function(a){var b;p.onfocus&&(b=!1!==p.onfocus(p,new CKEDITOR.dom.event(a)));return b}),u=0;p.clickFn=n=CKEDITOR.tools.addFunction(function(){u&&(f.unlockSelection(1),u=0);p.execute();b.iOS&&f.focus()});this.modes?(m={},f.on("beforeModeUnload",function(){f.mode&&this._.state!=CKEDITOR.TRISTATE_DISABLED&&(m[f.mode]= -this._.state)},this),f.on("activeFilterChange",l,this),f.on("mode",l,this),!this.readOnly&&f.on("readOnly",l,this)):a&&(a=f.getCommand(a))&&(a.on("state",function(){this.setState(a.state)},this),c+=a.state==CKEDITOR.TRISTATE_ON?"on":a.state==CKEDITOR.TRISTATE_DISABLED?"disabled":"off");var x;if(this.directional)f.on("contentDirChanged",function(a){var b=CKEDITOR.document.getById(this._.id),c=b.getFirst();a=a.data;a!=f.lang.dir?b.addClass("cke_"+a):b.removeClass("cke_ltr").removeClass("cke_rtl");c.setAttribute("style", -CKEDITOR.skin.getIconStyle(x,"rtl"==a,this.icon,this.iconOffset))},this);a?(w=f.getCommandKeystroke(a))&&(v=CKEDITOR.tools.keystrokeToString(f.lang.common.keyboard,w)):c+="off";w=this.name||this.command;var A=null,D=this.icon;x=w;this.icon&&!/\./.test(this.icon)?(x=this.icon,D=null):(this.icon&&(A=this.icon),CKEDITOR.env.hidpi&&this.iconHiDpi&&(A=this.iconHiDpi));A?(CKEDITOR.skin.addIcon(A,A),D=null):A=x;c={id:g,name:w,iconName:x,label:this.label,cls:this.className||"",state:c,ariaDisabled:"disabled"== -c?"true":"false",title:this.title+(v?" ("+v.display+")":""),ariaShortcut:v?f.lang.common.keyboardShortcut+" "+v.aria:"",titleJs:b.gecko&&!b.hc?"":(this.title||"").replace("'",""),hasArrow:this.hasArrow?"true":"false",keydownFn:r,focusFn:q,clickFn:n,style:CKEDITOR.skin.getIconStyle(A,"rtl"==f.lang.dir,D,this.iconOffset),arrowHtml:this.hasArrow?h.output():""};e.output(c,d);if(this.onRender)this.onRender();return p},setState:function(e){if(this._.state==e)return!1;this._.state=e;var d=CKEDITOR.document.getById(this._.id); +CKEDITOR.ui.button.prototype={render:function(f,d){function l(){var a=f.mode;a&&(a=this.modes[a]?void 0!==m[a]?m[a]:CKEDITOR.TRISTATE_OFF:CKEDITOR.TRISTATE_DISABLED,a=f.readOnly&&!this.readOnly?CKEDITOR.TRISTATE_DISABLED:a,this.setState(a),this.refresh&&this.refresh())}var m=null,b=CKEDITOR.env,g=this._.id=CKEDITOR.tools.getNextId(),c="",a=this.command,n,w,v;this._.editor=f;var t={id:g,button:this,editor:f,focus:function(){CKEDITOR.document.getById(g).focus()},execute:function(){this.button.click(f)}, +attach:function(a){this.button.attach(a)}},p=CKEDITOR.tools.addFunction(function(a){if(t.onkey)return a=new CKEDITOR.dom.event(a),!1!==t.onkey(t,a.getKeystroke())}),q=CKEDITOR.tools.addFunction(function(a){var b;t.onfocus&&(b=!1!==t.onfocus(t,new CKEDITOR.dom.event(a)));return b}),A=0;t.clickFn=n=CKEDITOR.tools.addFunction(function(){A&&(f.unlockSelection(1),A=0);t.execute();b.iOS&&f.focus()});this.modes?(m={},f.on("beforeModeUnload",function(){f.mode&&this._.state!=CKEDITOR.TRISTATE_DISABLED&&(m[f.mode]= +this._.state)},this),f.on("activeFilterChange",l,this),f.on("mode",l,this),!this.readOnly&&f.on("readOnly",l,this)):a&&(a=f.getCommand(a))&&(a.on("state",function(){this.setState(a.state)},this),c+=a.state==CKEDITOR.TRISTATE_ON?"on":a.state==CKEDITOR.TRISTATE_DISABLED?"disabled":"off");var r;if(this.directional)f.on("contentDirChanged",function(a){var b=CKEDITOR.document.getById(this._.id),c=b.getFirst();a=a.data;a!=f.lang.dir?b.addClass("cke_"+a):b.removeClass("cke_ltr").removeClass("cke_rtl");c.setAttribute("style", +CKEDITOR.skin.getIconStyle(r,"rtl"==a,this.icon,this.iconOffset))},this);a?(w=f.getCommandKeystroke(a))&&(v=CKEDITOR.tools.keystrokeToString(f.lang.common.keyboard,w)):c+="off";w=this.name||this.command;var C=null,B=this.icon;r=w;this.icon&&!/\./.test(this.icon)?(r=this.icon,B=null):(this.icon&&(C=this.icon),CKEDITOR.env.hidpi&&this.iconHiDpi&&(C=this.iconHiDpi));C?(CKEDITOR.skin.addIcon(C,C),B=null):C=r;c={id:g,name:w,iconName:r,label:this.label,cls:this.className||"",state:c,ariaDisabled:"disabled"== +c?"true":"false",title:this.title+(v?" ("+v.display+")":""),ariaShortcut:v?f.lang.common.keyboardShortcut+" "+v.aria:"",titleJs:b.gecko&&!b.hc?"":(this.title||"").replace("'",""),hasArrow:this.hasArrow?"true":"false",keydownFn:p,focusFn:q,clickFn:n,style:CKEDITOR.skin.getIconStyle(C,"rtl"==f.lang.dir,B,this.iconOffset),arrowHtml:this.hasArrow?h.output():""};e.output(c,d);if(this.onRender)this.onRender();return t},setState:function(e){if(this._.state==e)return!1;this._.state=e;var d=CKEDITOR.document.getById(this._.id); return d?(d.setState(e,"cke_button"),e==CKEDITOR.TRISTATE_DISABLED?d.setAttribute("aria-disabled",!0):d.removeAttribute("aria-disabled"),this.hasArrow?(e=e==CKEDITOR.TRISTATE_ON?this._.editor.lang.button.selectedLabel.replace(/%1/g,this.label):this.label,CKEDITOR.document.getById(this._.id+"_label").setText(e)):e==CKEDITOR.TRISTATE_ON?d.setAttribute("aria-pressed",!0):d.removeAttribute("aria-pressed"),!0):!1},getState:function(){return this._.state},toFeature:function(e){if(this._.feature)return this._.feature; -var d=this;this.allowedContent||this.requiredContent||!this.command||(d=e.getCommand(this.command)||d);return this._.feature=d}};CKEDITOR.ui.prototype.addButton=function(e,d){this.add(e,CKEDITOR.UI_BUTTON,d)}}(),function(){function f(d){function e(){for(var a=f(),c=CKEDITOR.tools.clone(d.config.toolbarGroups)||h(d),g=0;g<c.length;g++){var k=c[g];if("/"!=k){"string"==typeof k&&(k=c[g]={name:k});var l,q=k.groups;if(q)for(var u=0;u<q.length;u++)l=q[u],(l=a[l])&&b(k,l);(l=a[k.name])&&b(k,l)}}return c} +var d=this;this.allowedContent||this.requiredContent||!this.command||(d=e.getCommand(this.command)||d);return this._.feature=d}};CKEDITOR.ui.prototype.addButton=function(e,d){this.add(e,CKEDITOR.UI_BUTTON,d)}}(),function(){function f(d){function e(){for(var a=f(),c=CKEDITOR.tools.clone(d.config.toolbarGroups)||h(d),g=0;g<c.length;g++){var k=c[g];if("/"!=k){"string"==typeof k&&(k=c[g]={name:k});var l,q=k.groups;if(q)for(var A=0;A<q.length;A++)l=q[A],(l=a[l])&&b(k,l);(l=a[k.name])&&b(k,l)}}return c} function f(){var a={},b,c,g;for(b in d.ui.items)c=d.ui.items[b],g=c.toolbar||"others",g=g.split(","),c=g[0],g=parseInt(g[1]||-1,10),a[c]||(a[c]=[]),a[c].push({name:b,order:g});for(c in a)a[c]=a[c].sort(function(a,b){return a.order==b.order?0:0>b.order?-1:0>a.order?1:a.order<b.order?-1:1});return a}function b(a,b){if(b.length){a.items?a.items.push(d.ui.create("-")):a.items=[];for(var g;g=b.shift();)g="string"==typeof g?g:g.name,c&&-1!=CKEDITOR.tools.indexOf(c,g)||(g=d.ui.create(g))&&d.addFeature(g)&& -a.items.push(g)}}function g(a){var c=[],g,d,e;for(g=0;g<a.length;++g)d=a[g],e={},"/"==d?c.push(d):CKEDITOR.tools.isArray(d)?(b(e,CKEDITOR.tools.clone(d)),c.push(e)):d.items&&(b(e,CKEDITOR.tools.clone(d.items)),e.name=d.name,c.push(e));return c}var c=d.config.removeButtons,c=c&&c.split(","),a=d.config.toolbar;"string"==typeof a&&(a=d.config["toolbar_"+a]);return d.toolbar=a?g(a):e()}function h(d){return d._.toolbarGroups||(d._.toolbarGroups=[{name:"document",groups:["mode","document","doctools"]}, +a.items.push(g)}}function g(a){var c=[],d,g,e;for(d=0;d<a.length;++d)g=a[d],e={},"/"==g?c.push(g):CKEDITOR.tools.isArray(g)?(b(e,CKEDITOR.tools.clone(g)),c.push(e)):g.items&&(b(e,CKEDITOR.tools.clone(g.items)),e.name=g.name,c.push(e));return c}var c=d.config.removeButtons,c=c&&c.split(","),a=d.config.toolbar;"string"==typeof a&&(a=d.config["toolbar_"+a]);return d.toolbar=a?g(a):e()}function h(d){return d._.toolbarGroups||(d._.toolbarGroups=[{name:"document",groups:["mode","document","doctools"]}, {name:"clipboard",groups:["clipboard","undo"]},{name:"editing",groups:["find","selection","spellchecker"]},{name:"forms"},"/",{name:"basicstyles",groups:["basicstyles","cleanup"]},{name:"paragraph",groups:["list","indent","blocks","align","bidi"]},{name:"links"},{name:"insert"},"/",{name:"styles"},{name:"colors"},{name:"tools"},{name:"others"},{name:"about"}])}var e=function(){this.toolbars=[];this.focusCommandExecuted=!1};e.prototype.focus=function(){for(var d=0,e;e=this.toolbars[d++];)for(var f= 0,b;b=e.items[f++];)if(b.focus){b.focus();return}};var k={modes:{wysiwyg:1,source:1},readOnly:1,exec:function(d){d.toolbox&&(d.toolbox.focusCommandExecuted=!0,CKEDITOR.env.ie||CKEDITOR.env.air?setTimeout(function(){d.toolbox.focus()},100):d.toolbox.focus())}};CKEDITOR.plugins.add("toolbar",{requires:"button",init:function(d){var h,m=function(b,g){var c,a="rtl"==d.lang.dir,e=d.config.toolbarGroupCycling,f=a?37:39,a=a?39:37,e=void 0===e||e;switch(g){case 9:case CKEDITOR.SHIFT+9:for(;!c||!c.items.length;)if(c= 9==g?(c?c.next:b.toolbar.next)||d.toolbox.toolbars[0]:(c?c.previous:b.toolbar.previous)||d.toolbox.toolbars[d.toolbox.toolbars.length-1],c.items.length)for(b=c.items[h?c.items.length-1:0];b&&!b.focus;)(b=h?b.previous:b.next)||(c=0);b&&b.focus();return!1;case f:c=b;do c=c.next,!c&&e&&(c=b.toolbar.items[0]);while(c&&!c.focus);c?c.focus():m(b,9);return!1;case 40:return b.button&&b.button.hasArrow?b.execute():m(b,40==g?f:a),!1;case a:case 38:c=b;do c=c.previous,!c&&e&&(c=b.toolbar.items[b.toolbar.items.length- 1]);while(c&&!c.focus);c?c.focus():(h=1,m(b,CKEDITOR.SHIFT+9),h=0);return!1;case 27:return d.focus(),!1;case 13:case 32:return b.execute(),!1}return!0};d.on("uiSpace",function(b){if(b.data.space==d.config.toolbarLocation){b.removeListener();d.toolbox=new e;var g=CKEDITOR.tools.getNextId(),c=['\x3cspan id\x3d"',g,'" class\x3d"cke_voice_label"\x3e',d.lang.toolbar.toolbars,"\x3c/span\x3e",'\x3cspan id\x3d"'+d.ui.spaceId("toolbox")+'" class\x3d"cke_toolbox" role\x3d"group" aria-labelledby\x3d"',g,'" onmousedown\x3d"return false;"\x3e'], -g=!1!==d.config.toolbarStartupExpanded,a,h;d.config.toolbarCanCollapse&&d.elementMode!=CKEDITOR.ELEMENT_MODE_INLINE&&c.push('\x3cspan class\x3d"cke_toolbox_main"'+(g?"\x3e":' style\x3d"display:none"\x3e'));for(var k=d.toolbox.toolbars,l=f(d),p=l.length,r=0;r<p;r++){var q,u=0,x,A=l[r],D="/"!==A&&("/"===l[r+1]||r==p-1),t;if(A)if(a&&(c.push("\x3c/span\x3e"),h=a=0),"/"===A)c.push('\x3cspan class\x3d"cke_toolbar_break"\x3e\x3c/span\x3e');else{t=A.items||A;for(var B=0;B<t.length;B++){var y=t[B],z;if(y){var I= -function(a){a=a.render(d,c);E=u.items.push(a)-1;0<E&&(a.previous=u.items[E-1],a.previous.next=a);a.toolbar=u;a.onkey=m;a.onfocus=function(){d.toolbox.focusCommandExecuted||d.focus()}};if(y.type==CKEDITOR.UI_SEPARATOR)h=a&&y;else{z=!1!==y.canGroup;if(!u){q=CKEDITOR.tools.getNextId();u={id:q,items:[]};x=A.name&&(d.lang.toolbar.toolbarGroups[A.name]||A.name);c.push('\x3cspan id\x3d"',q,'" class\x3d"cke_toolbar'+(D?' cke_toolbar_last"':'"'),x?' aria-labelledby\x3d"'+q+'_label"':"",' role\x3d"toolbar"\x3e'); -x&&c.push('\x3cspan id\x3d"',q,'_label" class\x3d"cke_voice_label"\x3e',x,"\x3c/span\x3e");c.push('\x3cspan class\x3d"cke_toolbar_start"\x3e\x3c/span\x3e');var E=k.push(u)-1;0<E&&(u.previous=k[E-1],u.previous.next=u)}z?a||(c.push('\x3cspan class\x3d"cke_toolgroup" role\x3d"presentation"\x3e'),a=1):a&&(c.push("\x3c/span\x3e"),a=0);h&&(I(h),h=0);I(y)}}}a&&(c.push("\x3c/span\x3e"),h=a=0);u&&c.push('\x3cspan class\x3d"cke_toolbar_end"\x3e\x3c/span\x3e\x3c/span\x3e')}}d.config.toolbarCanCollapse&&c.push("\x3c/span\x3e"); -if(d.config.toolbarCanCollapse&&d.elementMode!=CKEDITOR.ELEMENT_MODE_INLINE){var F=CKEDITOR.tools.addFunction(function(){d.execCommand("toolbarCollapse")});d.on("destroy",function(){CKEDITOR.tools.removeFunction(F)});d.addCommand("toolbarCollapse",{readOnly:1,exec:function(a){var b=a.ui.space("toolbar_collapser"),c=b.getPrevious(),g=a.ui.space("contents"),d=c.getParent(),e=parseInt(g.$.style.height,10),f=d.$.offsetHeight,h=b.hasClass("cke_toolbox_collapser_min");h?(c.show(),b.removeClass("cke_toolbox_collapser_min"), -b.setAttribute("title",a.lang.toolbar.toolbarCollapse)):(c.hide(),b.addClass("cke_toolbox_collapser_min"),b.setAttribute("title",a.lang.toolbar.toolbarExpand));b.getFirst().setText(h?"▲":"◀");g.setStyle("height",e-(d.$.offsetHeight-f)+"px");a.fire("resize",{outerHeight:a.container.$.offsetHeight,contentsHeight:g.$.offsetHeight,outerWidth:a.container.$.offsetWidth})},modes:{wysiwyg:1,source:1}});d.setKeystroke(CKEDITOR.ALT+(CKEDITOR.env.ie||CKEDITOR.env.webkit?189:109),"toolbarCollapse");c.push('\x3ca title\x3d"'+ -(g?d.lang.toolbar.toolbarCollapse:d.lang.toolbar.toolbarExpand)+'" id\x3d"'+d.ui.spaceId("toolbar_collapser")+'" tabIndex\x3d"-1" class\x3d"cke_toolbox_collapser');g||c.push(" cke_toolbox_collapser_min");c.push('" onclick\x3d"CKEDITOR.tools.callFunction('+F+')"\x3e','\x3cspan class\x3d"cke_arrow"\x3e\x26#9650;\x3c/span\x3e',"\x3c/a\x3e")}c.push("\x3c/span\x3e");b.data.html+=c.join("")}});d.on("destroy",function(){if(this.toolbox){var b,g=0,c,a,d;for(b=this.toolbox.toolbars;g<b.length;g++)for(a=b[g].items, -c=0;c<a.length;c++)d=a[c],d.clickFn&&CKEDITOR.tools.removeFunction(d.clickFn),d.keyDownFn&&CKEDITOR.tools.removeFunction(d.keyDownFn)}});d.on("uiReady",function(){var b=d.ui.space("toolbox");b&&d.focusManager.add(b,1)});d.addCommand("toolbarFocus",k);d.setKeystroke(CKEDITOR.ALT+121,"toolbarFocus");d.ui.add("-",CKEDITOR.UI_SEPARATOR,{});d.ui.addHandler(CKEDITOR.UI_SEPARATOR,{create:function(){return{render:function(b,g){g.push('\x3cspan class\x3d"cke_toolbar_separator" role\x3d"separator"\x3e\x3c/span\x3e'); +g=!1!==d.config.toolbarStartupExpanded,a,h;d.config.toolbarCanCollapse&&d.elementMode!=CKEDITOR.ELEMENT_MODE_INLINE&&c.push('\x3cspan class\x3d"cke_toolbox_main"'+(g?"\x3e":' style\x3d"display:none"\x3e'));for(var k=d.toolbox.toolbars,l=f(d),t=l.length,p=0;p<t;p++){var q,A=0,r,C=l[p],B="/"!==C&&("/"===l[p+1]||p==t-1),u;if(C)if(a&&(c.push("\x3c/span\x3e"),h=a=0),"/"===C)c.push('\x3cspan class\x3d"cke_toolbar_break"\x3e\x3c/span\x3e');else{u=C.items||C;for(var y=0;y<u.length;y++){var x=u[y],z;if(x){var I= +function(a){a=a.render(d,c);F=A.items.push(a)-1;0<F&&(a.previous=A.items[F-1],a.previous.next=a);a.toolbar=A;a.onkey=m;a.onfocus=function(){d.toolbox.focusCommandExecuted||d.focus()}};if(x.type==CKEDITOR.UI_SEPARATOR)h=a&&x;else{z=!1!==x.canGroup;if(!A){q=CKEDITOR.tools.getNextId();A={id:q,items:[]};r=C.name&&(d.lang.toolbar.toolbarGroups[C.name]||C.name);c.push('\x3cspan id\x3d"',q,'" class\x3d"cke_toolbar'+(B?' cke_toolbar_last"':'"'),r?' aria-labelledby\x3d"'+q+'_label"':"",' role\x3d"toolbar"\x3e'); +r&&c.push('\x3cspan id\x3d"',q,'_label" class\x3d"cke_voice_label"\x3e',r,"\x3c/span\x3e");c.push('\x3cspan class\x3d"cke_toolbar_start"\x3e\x3c/span\x3e');var F=k.push(A)-1;0<F&&(A.previous=k[F-1],A.previous.next=A)}z?a||(c.push('\x3cspan class\x3d"cke_toolgroup" role\x3d"presentation"\x3e'),a=1):a&&(c.push("\x3c/span\x3e"),a=0);h&&(I(h),h=0);I(x)}}}a&&(c.push("\x3c/span\x3e"),h=a=0);A&&c.push('\x3cspan class\x3d"cke_toolbar_end"\x3e\x3c/span\x3e\x3c/span\x3e')}}d.config.toolbarCanCollapse&&c.push("\x3c/span\x3e"); +if(d.config.toolbarCanCollapse&&d.elementMode!=CKEDITOR.ELEMENT_MODE_INLINE){var E=CKEDITOR.tools.addFunction(function(){d.execCommand("toolbarCollapse")});d.on("destroy",function(){CKEDITOR.tools.removeFunction(E)});d.addCommand("toolbarCollapse",{readOnly:1,exec:function(a){var b=a.ui.space("toolbar_collapser"),c=b.getPrevious(),d=a.ui.space("contents"),g=c.getParent(),e=parseInt(d.$.style.height,10),f=g.$.offsetHeight,h=b.hasClass("cke_toolbox_collapser_min");h?(c.show(),b.removeClass("cke_toolbox_collapser_min"), +b.setAttribute("title",a.lang.toolbar.toolbarCollapse)):(c.hide(),b.addClass("cke_toolbox_collapser_min"),b.setAttribute("title",a.lang.toolbar.toolbarExpand));b.getFirst().setText(h?"▲":"◀");d.setStyle("height",e-(g.$.offsetHeight-f)+"px");a.fire("resize",{outerHeight:a.container.$.offsetHeight,contentsHeight:d.$.offsetHeight,outerWidth:a.container.$.offsetWidth})},modes:{wysiwyg:1,source:1}});d.setKeystroke(CKEDITOR.ALT+(CKEDITOR.env.ie||CKEDITOR.env.webkit?189:109),"toolbarCollapse");c.push('\x3ca title\x3d"'+ +(g?d.lang.toolbar.toolbarCollapse:d.lang.toolbar.toolbarExpand)+'" id\x3d"'+d.ui.spaceId("toolbar_collapser")+'" tabIndex\x3d"-1" class\x3d"cke_toolbox_collapser');g||c.push(" cke_toolbox_collapser_min");c.push('" onclick\x3d"CKEDITOR.tools.callFunction('+E+')"\x3e','\x3cspan class\x3d"cke_arrow"\x3e\x26#9650;\x3c/span\x3e',"\x3c/a\x3e")}c.push("\x3c/span\x3e");b.data.html+=c.join("")}});d.on("destroy",function(){if(this.toolbox){var b,d=0,c,a,e;for(b=this.toolbox.toolbars;d<b.length;d++)for(a=b[d].items, +c=0;c<a.length;c++)e=a[c],e.clickFn&&CKEDITOR.tools.removeFunction(e.clickFn),e.keyDownFn&&CKEDITOR.tools.removeFunction(e.keyDownFn)}});d.on("uiReady",function(){var b=d.ui.space("toolbox");b&&d.focusManager.add(b,1)});d.addCommand("toolbarFocus",k);d.setKeystroke(CKEDITOR.ALT+121,"toolbarFocus");d.ui.add("-",CKEDITOR.UI_SEPARATOR,{});d.ui.addHandler(CKEDITOR.UI_SEPARATOR,{create:function(){return{render:function(b,d){d.push('\x3cspan class\x3d"cke_toolbar_separator" role\x3d"separator"\x3e\x3c/span\x3e'); return{}}}}})}});CKEDITOR.ui.prototype.addToolbarGroup=function(d,e,f){var b=h(this.editor),g=0===e,c={name:d};if(f){if(f=CKEDITOR.tools.search(b,function(a){return a.name==f})){!f.groups&&(f.groups=[]);if(e&&(e=CKEDITOR.tools.indexOf(f.groups,e),0<=e)){f.groups.splice(e+1,0,d);return}g?f.groups.splice(0,0,d):f.groups.push(d);return}e=null}e&&(e=CKEDITOR.tools.indexOf(b,function(a){return a.name==e}));g?b.splice(0,0,d):"number"==typeof e?b.splice(e+1,0,c):b.push(d)}}(),CKEDITOR.UI_SEPARATOR="separator", -CKEDITOR.config.toolbarLocation="top","use strict",function(){function f(a,b,c){b.type||(b.type="auto");if(c&&!1===a.fire("beforePaste",b)||!b.dataValue&&b.dataTransfer.isEmpty())return!1;b.dataValue||(b.dataValue="");if(CKEDITOR.env.gecko&&"drop"==b.method&&a.toolbox)a.once("afterPaste",function(){a.toolbox.focus()});return a.fire("paste",b)}function h(a){function b(){var c=a.editable();if(CKEDITOR.plugins.clipboard.isCustomCopyCutSupported){var g=function(b){a.getSelection().isCollapsed()||(a.readOnly&& -"cut"==b.name||z.initPasteDataTransfer(b,a),b.data.preventDefault())};c.on("copy",g);c.on("cut",g);c.on("cut",function(){a.readOnly||a.extractSelectedHtml()},null,null,999)}c.on(z.mainPasteEvent,function(a){"beforepaste"==z.mainPasteEvent&&I||t(a)});"beforepaste"==z.mainPasteEvent&&(c.on("paste",function(a){E||(d(),a.data.preventDefault(),t(a),h("paste"))}),c.on("contextmenu",e,null,null,0),c.on("beforepaste",function(a){!a.data||a.data.$.ctrlKey||a.data.$.shiftKey||e()},null,null,0));c.on("beforecut", -function(){!I&&k(a)});var f;c.attachListener(CKEDITOR.env.ie?c:a.document.getDocumentElement(),"mouseup",function(){f=setTimeout(function(){B()},0)});a.on("destroy",function(){clearTimeout(f)});c.on("keyup",B)}function c(b){return{type:b,canUndo:"cut"==b,startDisabled:!0,fakeKeystroke:"cut"==b?CKEDITOR.CTRL+88:CKEDITOR.CTRL+67,exec:function(){"cut"==this.type&&k();var b;var c=this.type;if(CKEDITOR.env.ie)b=h(c);else try{b=a.document.$.execCommand(c,!1,null)}catch(g){b=!1}b||a.showNotification(a.lang.clipboard[this.type+ -"Error"]);return b}}}function g(){return{canUndo:!1,async:!0,fakeKeystroke:CKEDITOR.CTRL+86,exec:function(a,b){function c(b,e){e="undefined"!==typeof e?e:!0;b?(b.method="paste",b.dataTransfer||(b.dataTransfer=z.initPasteDataTransfer()),f(a,b,e)):d&&!a._.forcePasteDialog&&a.showNotification(k,"info",a.config.clipboard_notificationDuration);a._.forcePasteDialog=!1;a.fire("afterCommandExec",{name:"paste",command:g,returnValue:!!b})}b="undefined"!==typeof b&&null!==b?b:{};var g=this,d="undefined"!==typeof b.notification? -b.notification:!0,e=b.type,h=CKEDITOR.tools.keystrokeToString(a.lang.common.keyboard,a.getCommandKeystroke(this)),k="string"===typeof d?d:a.lang.clipboard.pasteNotification.replace(/%1/,'\x3ckbd aria-label\x3d"'+h.aria+'"\x3e'+h.display+"\x3c/kbd\x3e"),h="string"===typeof b?b:b.dataValue;e&&!0!==a.config.forcePasteAsPlainText&&"allow-word"!==a.config.forcePasteAsPlainText?a._.nextPasteType=e:delete a._.nextPasteType;"string"===typeof h?c({dataValue:h}):a.getClipboardData(c)}}}function d(){E=1;setTimeout(function(){E= -0},100)}function e(){I=1;setTimeout(function(){I=0},10)}function h(b){var c=a.document,g=c.getBody(),d=!1,e=function(){d=!0};g.on(b,e);7<CKEDITOR.env.version?c.$.execCommand(b):c.$.selection.createRange().execCommand(b);g.removeListener(b,e);return d}function k(){if(CKEDITOR.env.ie&&!CKEDITOR.env.quirks){var b=a.getSelection(),c,g,d;b.getType()==CKEDITOR.SELECTION_ELEMENT&&(c=b.getSelectedElement())&&(g=b.getRanges()[0],d=a.document.createText(""),d.insertBefore(c),g.setStartBefore(d),g.setEndAfter(c), -b.selectRanges([g]),setTimeout(function(){c.getParent()&&(d.remove(),b.selectElement(c))},0))}}function l(b,c){var g=a.document,d=a.editable(),e=function(a){a.cancel()},f;if(!g.getById("cke_pastebin")){var h=a.getSelection(),k=h.createBookmarks();CKEDITOR.env.ie&&h.root.fire("selectionchange");var n=new CKEDITOR.dom.element(!CKEDITOR.env.webkit&&!d.is("body")||CKEDITOR.env.ie?"div":"body",g);n.setAttributes({id:"cke_pastebin","data-cke-temp":"1"});var m=0,g=g.getWindow();CKEDITOR.env.webkit?(d.append(n), -n.addClass("cke_editable"),d.is("body")||(m="static"!=d.getComputedStyle("position")?d:CKEDITOR.dom.element.get(d.$.offsetParent),m=m.getDocumentPosition().y)):d.getAscendant(CKEDITOR.env.ie?"body":"html",1).append(n);n.setStyles({position:"absolute",top:g.getScrollPosition().y-m+10+"px",width:"1px",height:Math.max(1,g.getViewPaneSize().height-20)+"px",overflow:"hidden",margin:0,padding:0});CKEDITOR.env.safari&&n.setStyles(CKEDITOR.tools.cssVendorPrefix("user-select","text"));(m=n.getParent().isReadOnly())? -(n.setOpacity(0),n.setAttribute("contenteditable",!0)):n.setStyle("ltr"==a.config.contentsLangDirection?"left":"right","-10000px");a.on("selectionChange",e,null,null,0);if(CKEDITOR.env.webkit||CKEDITOR.env.gecko)f=d.once("blur",e,null,null,-100);m&&n.focus();m=new CKEDITOR.dom.range(n);m.selectNodeContents(n);var q=m.select();CKEDITOR.env.ie&&(f=d.once("blur",function(){a.lockSelection(q)}));var r=CKEDITOR.document.getWindow().getScrollPosition().y;setTimeout(function(){CKEDITOR.env.webkit&&(CKEDITOR.document.getBody().$.scrollTop= -r);f&&f.removeListener();CKEDITOR.env.ie&&d.focus();h.selectBookmarks(k);n.remove();var b;CKEDITOR.env.webkit&&(b=n.getFirst())&&b.is&&b.hasClass("Apple-style-span")&&(n=b);a.removeListener("selectionChange",e);c(n.getHtml())},0)}}function m(){if("paste"==z.mainPasteEvent)return a.fire("beforePaste",{type:"auto",method:"paste"}),!1;a.focus();d();var b=a.focusManager;b.lock();if(a.editable().fire(z.mainPasteEvent)&&!h("paste"))return b.unlock(),!1;b.unlock();return!0}function D(b){if("wysiwyg"==a.mode)switch(b.data.keyCode){case CKEDITOR.CTRL+ -86:case CKEDITOR.SHIFT+45:b=a.editable();d();"paste"==z.mainPasteEvent&&b.fire("beforepaste");break;case CKEDITOR.CTRL+88:case CKEDITOR.SHIFT+46:a.fire("saveSnapshot"),setTimeout(function(){a.fire("saveSnapshot")},50)}}function t(b){var c={type:"auto",method:"paste",dataTransfer:z.initPasteDataTransfer(b)};c.dataTransfer.cacheData();var g=!1!==a.fire("beforePaste",c);g&&z.canClipboardApiBeTrusted(c.dataTransfer,a)?(b.data.preventDefault(),setTimeout(function(){f(a,c)},0)):l(b,function(b){c.dataValue= -b.replace(/<span[^>]+data-cke-bookmark[^<]*?<\/span>/ig,"");g&&f(a,c)})}function B(){if("wysiwyg"==a.mode){var b=y("paste");a.getCommand("cut").setState(y("cut"));a.getCommand("copy").setState(y("copy"));a.getCommand("paste").setState(b);a.fire("pasteState",b)}}function y(b){if(F&&b in{paste:1,cut:1})return CKEDITOR.TRISTATE_DISABLED;if("paste"==b)return CKEDITOR.TRISTATE_OFF;b=a.getSelection();var c=b.getRanges();return b.getType()==CKEDITOR.SELECTION_NONE||1==c.length&&c[0].collapsed?CKEDITOR.TRISTATE_DISABLED: -CKEDITOR.TRISTATE_OFF}var z=CKEDITOR.plugins.clipboard,I=0,E=0,F=0;(function(){a.on("key",D);a.on("contentDom",b);a.on("selectionChange",function(a){F=a.data.selection.getRanges()[0].checkReadOnly();B()});if(a.contextMenu){a.contextMenu.addListener(function(a,b){F=b.getRanges()[0].checkReadOnly();return{cut:y("cut"),copy:y("copy"),paste:y("paste")}});var c=null;a.on("menuShow",function(){c&&(c.removeListener(),c=null);var b=a.contextMenu.findItemByCommandName("paste");b&&b.element&&(c=b.element.on("touchend", -function(){a._.forcePasteDialog=!0}))})}if(a.ui.addButton)a.once("instanceReady",function(){a._.pasteButtons&&CKEDITOR.tools.array.forEach(a._.pasteButtons,function(b){if(b=a.ui.get(b))CKEDITOR.document.getById(b._.id).on("touchend",function(){a._.forcePasteDialog=!0})})})})();(function(){function b(c,g,d,e,f){var h=a.lang.clipboard[g];a.addCommand(g,d);a.ui.addButton&&a.ui.addButton(c,{label:h,command:g,toolbar:"clipboard,"+e});a.addMenuItems&&a.addMenuItem(g,{label:h,command:g,group:"clipboard", -order:f})}b("Cut","cut",c("cut"),10,1);b("Copy","copy",c("copy"),20,4);b("Paste","paste",g(),30,8);a._.pasteButtons||(a._.pasteButtons=[]);a._.pasteButtons.push("Paste")})();a.getClipboardData=function(b,c){function g(a){a.removeListener();a.cancel();c(a.data)}function d(a){a.removeListener();a.cancel();c({type:f,dataValue:a.data.dataValue,dataTransfer:a.data.dataTransfer,method:"paste"})}var e=!1,f="auto";c||(c=b,b=null);a.on("beforePaste",function(a){a.removeListener();e=!0;f=a.data.type},null, -null,1E3);a.on("paste",g,null,null,0);!1===m()&&(a.removeListener("paste",g),a._.forcePasteDialog&&e&&a.fire("pasteDialog")?(a.on("pasteDialogCommit",d),a.on("dialogHide",function(a){a.removeListener();a.data.removeListener("pasteDialogCommit",d);a.data._.committed||c(null)})):c(null))}}function e(a){if(CKEDITOR.env.webkit){if(!a.match(/^[^<]*$/g)&&!a.match(/^(<div><br( ?\/)?><\/div>|<div>[^<]*<\/div>)*$/gi))return"html"}else if(CKEDITOR.env.ie){if(!a.match(/^([^<]|<br( ?\/)?>)*$/gi)&&!a.match(/^(<p>([^<]|<br( ?\/)?>)*<\/p>|(\r\n))*$/gi))return"html"}else if(CKEDITOR.env.gecko){if(!a.match(/^([^<]|<br( ?\/)?>)*$/gi))return"html"}else return"html"; +CKEDITOR.config.toolbarLocation="top","use strict",function(){function f(a,b,c){b.type||(b.type="auto");if(c&&!1===a.fire("beforePaste",b)||!b.dataValue&&b.dataTransfer.isEmpty())return!1;b.dataValue||(b.dataValue="");if(CKEDITOR.env.gecko&&"drop"==b.method&&a.toolbox)a.once("afterPaste",function(){a.toolbox.focus()});return a.fire("paste",b)}function h(a){function b(){var c=a.editable();if(CKEDITOR.plugins.clipboard.isCustomCopyCutSupported){var d=function(b){a.getSelection().isCollapsed()||(a.readOnly&& +"cut"==b.name||z.initPasteDataTransfer(b,a),b.data.preventDefault())};c.on("copy",d);c.on("cut",d);c.on("cut",function(){a.readOnly||a.extractSelectedHtml()},null,null,999)}c.on(z.mainPasteEvent,function(a){"beforepaste"==z.mainPasteEvent&&I||u(a)});"beforepaste"==z.mainPasteEvent&&(c.on("paste",function(a){F||(g(),a.data.preventDefault(),u(a),h("paste"))}),c.on("contextmenu",e,null,null,0),c.on("beforepaste",function(a){!a.data||a.data.$.ctrlKey||a.data.$.shiftKey||e()},null,null,0));c.on("beforecut", +function(){!I&&k(a)});var f;c.attachListener(CKEDITOR.env.ie?c:a.document.getDocumentElement(),"mouseup",function(){f=setTimeout(function(){y()},0)});a.on("destroy",function(){clearTimeout(f)});c.on("keyup",y)}function c(b){return{type:b,canUndo:"cut"==b,startDisabled:!0,fakeKeystroke:"cut"==b?CKEDITOR.CTRL+88:CKEDITOR.CTRL+67,exec:function(){"cut"==this.type&&k();var b;var c=this.type;if(CKEDITOR.env.ie)b=h(c);else try{b=a.document.$.execCommand(c,!1,null)}catch(d){b=!1}b||a.showNotification(a.lang.clipboard[this.type+ +"Error"]);return b}}}function d(){return{canUndo:!1,async:!0,fakeKeystroke:CKEDITOR.CTRL+86,exec:function(a,b){function c(b,e){e="undefined"!==typeof e?e:!0;b?(b.method="paste",b.dataTransfer||(b.dataTransfer=z.initPasteDataTransfer()),f(a,b,e)):g&&!a._.forcePasteDialog&&a.showNotification(k,"info",a.config.clipboard_notificationDuration);a._.forcePasteDialog=!1;a.fire("afterCommandExec",{name:"paste",command:d,returnValue:!!b})}b="undefined"!==typeof b&&null!==b?b:{};var d=this,g="undefined"!==typeof b.notification? +b.notification:!0,e=b.type,h=CKEDITOR.tools.keystrokeToString(a.lang.common.keyboard,a.getCommandKeystroke(this)),k="string"===typeof g?g:a.lang.clipboard.pasteNotification.replace(/%1/,'\x3ckbd aria-label\x3d"'+h.aria+'"\x3e'+h.display+"\x3c/kbd\x3e"),h="string"===typeof b?b:b.dataValue;e&&!0!==a.config.forcePasteAsPlainText&&"allow-word"!==a.config.forcePasteAsPlainText?a._.nextPasteType=e:delete a._.nextPasteType;"string"===typeof h?c({dataValue:h}):a.getClipboardData(c)}}}function g(){F=1;setTimeout(function(){F= +0},100)}function e(){I=1;setTimeout(function(){I=0},10)}function h(b){var c=a.document,d=c.getBody(),g=!1,e=function(){g=!0};d.on(b,e);7<CKEDITOR.env.version?c.$.execCommand(b):c.$.selection.createRange().execCommand(b);d.removeListener(b,e);return g}function k(){if(CKEDITOR.env.ie&&!CKEDITOR.env.quirks){var b=a.getSelection(),c,d,g;b.getType()==CKEDITOR.SELECTION_ELEMENT&&(c=b.getSelectedElement())&&(d=b.getRanges()[0],g=a.document.createText(""),g.insertBefore(c),d.setStartBefore(g),d.setEndAfter(c), +b.selectRanges([d]),setTimeout(function(){c.getParent()&&(g.remove(),b.selectElement(c))},0))}}function l(b,c){var d=a.document,g=a.editable(),e=function(a){a.cancel()},f;if(!d.getById("cke_pastebin")){var h=a.getSelection(),k=h.createBookmarks();CKEDITOR.env.ie&&h.root.fire("selectionchange");var n=new CKEDITOR.dom.element(!CKEDITOR.env.webkit&&!g.is("body")||CKEDITOR.env.ie?"div":"body",d);n.setAttributes({id:"cke_pastebin","data-cke-temp":"1"});var m=0,d=d.getWindow();CKEDITOR.env.webkit?(g.append(n), +n.addClass("cke_editable"),g.is("body")||(m="static"!=g.getComputedStyle("position")?g:CKEDITOR.dom.element.get(g.$.offsetParent),m=m.getDocumentPosition().y)):g.getAscendant(CKEDITOR.env.ie?"body":"html",1).append(n);n.setStyles({position:"absolute",top:d.getScrollPosition().y-m+10+"px",width:"1px",height:Math.max(1,d.getViewPaneSize().height-20)+"px",overflow:"hidden",margin:0,padding:0});CKEDITOR.env.safari&&n.setStyles(CKEDITOR.tools.cssVendorPrefix("user-select","text"));(m=n.getParent().isReadOnly())? +(n.setOpacity(0),n.setAttribute("contenteditable",!0)):n.setStyle("ltr"==a.config.contentsLangDirection?"left":"right","-10000px");a.on("selectionChange",e,null,null,0);if(CKEDITOR.env.webkit||CKEDITOR.env.gecko)f=g.once("blur",e,null,null,-100);m&&n.focus();m=new CKEDITOR.dom.range(n);m.selectNodeContents(n);var q=m.select();CKEDITOR.env.ie&&(f=g.once("blur",function(){a.lockSelection(q)}));var r=CKEDITOR.document.getWindow().getScrollPosition().y;setTimeout(function(){CKEDITOR.env.webkit&&(CKEDITOR.document.getBody().$.scrollTop= +r);f&&f.removeListener();CKEDITOR.env.ie&&g.focus();h.selectBookmarks(k);n.remove();var b;CKEDITOR.env.webkit&&(b=n.getFirst())&&b.is&&b.hasClass("Apple-style-span")&&(n=b);a.removeListener("selectionChange",e);c(n.getHtml())},0)}}function m(){if("paste"==z.mainPasteEvent)return a.fire("beforePaste",{type:"auto",method:"paste"}),!1;a.focus();g();var b=a.focusManager;b.lock();if(a.editable().fire(z.mainPasteEvent)&&!h("paste"))return b.unlock(),!1;b.unlock();return!0}function B(b){if("wysiwyg"==a.mode)switch(b.data.keyCode){case CKEDITOR.CTRL+ +86:case CKEDITOR.SHIFT+45:b=a.editable();g();"paste"==z.mainPasteEvent&&b.fire("beforepaste");break;case CKEDITOR.CTRL+88:case CKEDITOR.SHIFT+46:a.fire("saveSnapshot"),setTimeout(function(){a.fire("saveSnapshot")},50)}}function u(b){var c={type:"auto",method:"paste",dataTransfer:z.initPasteDataTransfer(b)};c.dataTransfer.cacheData();var d=!1!==a.fire("beforePaste",c);d&&z.canClipboardApiBeTrusted(c.dataTransfer,a)?(b.data.preventDefault(),setTimeout(function(){f(a,c)},0)):l(b,function(b){c.dataValue= +b.replace(/<span[^>]+data-cke-bookmark[^<]*?<\/span>/ig,"");d&&f(a,c)})}function y(){if("wysiwyg"==a.mode){var b=x("paste");a.getCommand("cut").setState(x("cut"));a.getCommand("copy").setState(x("copy"));a.getCommand("paste").setState(b);a.fire("pasteState",b)}}function x(b){if(E&&b in{paste:1,cut:1})return CKEDITOR.TRISTATE_DISABLED;if("paste"==b)return CKEDITOR.TRISTATE_OFF;b=a.getSelection();var c=b.getRanges();return b.getType()==CKEDITOR.SELECTION_NONE||1==c.length&&c[0].collapsed?CKEDITOR.TRISTATE_DISABLED: +CKEDITOR.TRISTATE_OFF}var z=CKEDITOR.plugins.clipboard,I=0,F=0,E=0;(function(){a.on("key",B);a.on("contentDom",b);a.on("selectionChange",function(a){E=a.data.selection.getRanges()[0].checkReadOnly();y()});if(a.contextMenu){a.contextMenu.addListener(function(a,b){E=b.getRanges()[0].checkReadOnly();return{cut:x("cut"),copy:x("copy"),paste:x("paste")}});var c=null;a.on("menuShow",function(){c&&(c.removeListener(),c=null);var b=a.contextMenu.findItemByCommandName("paste");b&&b.element&&(c=b.element.on("touchend", +function(){a._.forcePasteDialog=!0}))})}if(a.ui.addButton)a.once("instanceReady",function(){a._.pasteButtons&&CKEDITOR.tools.array.forEach(a._.pasteButtons,function(b){if(b=a.ui.get(b))if(b=CKEDITOR.document.getById(b._.id))b.on("touchend",function(){a._.forcePasteDialog=!0})})})})();(function(){function b(c,d,g,e,f){var h=a.lang.clipboard[d];a.addCommand(d,g);a.ui.addButton&&a.ui.addButton(c,{label:h,command:d,toolbar:"clipboard,"+e});a.addMenuItems&&a.addMenuItem(d,{label:h,command:d,group:"clipboard", +order:f})}b("Cut","cut",c("cut"),10,1);b("Copy","copy",c("copy"),20,4);b("Paste","paste",d(),30,8);a._.pasteButtons||(a._.pasteButtons=[]);a._.pasteButtons.push("Paste")})();a.getClipboardData=function(b,c){function d(a){a.removeListener();a.cancel();c(a.data)}function g(a){a.removeListener();a.cancel();c({type:f,dataValue:a.data.dataValue,dataTransfer:a.data.dataTransfer,method:"paste"})}var e=!1,f="auto";c||(c=b,b=null);a.on("beforePaste",function(a){a.removeListener();e=!0;f=a.data.type},null, +null,1E3);a.on("paste",d,null,null,0);!1===m()&&(a.removeListener("paste",d),a._.forcePasteDialog&&e&&a.fire("pasteDialog")?(a.on("pasteDialogCommit",g),a.on("dialogHide",function(a){a.removeListener();a.data.removeListener("pasteDialogCommit",g);a.data._.committed||c(null)})):c(null))}}function e(a){if(CKEDITOR.env.webkit){if(!a.match(/^[^<]*$/g)&&!a.match(/^(<div><br( ?\/)?><\/div>|<div>[^<]*<\/div>)*$/gi))return"html"}else if(CKEDITOR.env.ie){if(!a.match(/^([^<]|<br( ?\/)?>)*$/gi)&&!a.match(/^(<p>([^<]|<br( ?\/)?>)*<\/p>|(\r\n))*$/gi))return"html"}else if(CKEDITOR.env.gecko){if(!a.match(/^([^<]|<br( ?\/)?>)*$/gi))return"html"}else return"html"; return"htmlifiedtext"}function k(a,b){function c(a){return CKEDITOR.tools.repeat("\x3c/p\x3e\x3cp\x3e",~~(a/2))+(1==a%2?"\x3cbr\x3e":"")}b=b.replace(/(?!\u3000)\s+/g," ").replace(/> +</g,"\x3e\x3c").replace(/<br ?\/>/gi,"\x3cbr\x3e");b=b.replace(/<\/?[A-Z]+>/g,function(a){return a.toLowerCase()});if(b.match(/^[^<]$/))return b;CKEDITOR.env.webkit&&-1<b.indexOf("\x3cdiv\x3e")&&(b=b.replace(/^(<div>(<br>|)<\/div>)(?!$|(<div>(<br>|)<\/div>))/g,"\x3cbr\x3e").replace(/^(<div>(<br>|)<\/div>){2}(?!$)/g,"\x3cdiv\x3e\x3c/div\x3e"), b.match(/<div>(<br>|)<\/div>/)&&(b="\x3cp\x3e"+b.replace(/(<div>(<br>|)<\/div>)+/g,function(a){return c(a.split("\x3c/div\x3e\x3cdiv\x3e").length+1)})+"\x3c/p\x3e"),b=b.replace(/<\/div><div>/g,"\x3cbr\x3e"),b=b.replace(/<\/?div>/g,""));CKEDITOR.env.gecko&&a.enterMode!=CKEDITOR.ENTER_BR&&(CKEDITOR.env.gecko&&(b=b.replace(/^<br><br>$/,"\x3cbr\x3e")),-1<b.indexOf("\x3cbr\x3e\x3cbr\x3e")&&(b="\x3cp\x3e"+b.replace(/(<br>){2,}/g,function(a){return c(a.length/4)})+"\x3c/p\x3e"));return m(a,b)}function d(){function a(){var a= -{},b;for(b in CKEDITOR.dtd)"$"!=b.charAt(0)&&"div"!=b&&"span"!=b&&(a[b]=1);return a}var b={};return{get:function(c){return"plain-text"==c?b.plainText||(b.plainText=new CKEDITOR.filter("br")):"semantic-content"==c?((c=b.semanticContent)||(c=new CKEDITOR.filter,c.allow({$1:{elements:a(),attributes:!0,styles:!1,classes:!1}}),c=b.semanticContent=c),c):c?new CKEDITOR.filter(c):null}}}function l(a,b,c){b=CKEDITOR.htmlParser.fragment.fromHtml(b);var g=new CKEDITOR.htmlParser.basicWriter;c.applyTo(b,!0,!1, -a.activeEnterMode);b.writeHtml(g);return g.getHtml()}function m(a,b){a.enterMode==CKEDITOR.ENTER_BR?b=b.replace(/(<\/p><p>)+/g,function(a){return CKEDITOR.tools.repeat("\x3cbr\x3e",a.length/7*2)}).replace(/<\/?p>/g,""):a.enterMode==CKEDITOR.ENTER_DIV&&(b=b.replace(/<(\/)?p>/g,"\x3c$1div\x3e"));return b}function b(a){a.data.preventDefault();a.data.$.dataTransfer.dropEffect="none"}function g(a){var b=CKEDITOR.plugins.clipboard;a.on("contentDom",function(){function c(b,g,d){g.select();f(a,{dataTransfer:d, -method:"drop"},1);d.sourceEditor.fire("saveSnapshot");d.sourceEditor.editable().extractHtmlFromRange(b);d.sourceEditor.getSelection().selectRanges([b]);d.sourceEditor.fire("saveSnapshot")}function g(c,d){c.select();f(a,{dataTransfer:d,method:"drop"},1);b.resetDragDataTransfer()}function d(b,c,g){var e={$:b.data.$,target:b.data.getTarget()};c&&(e.dragRange=c);g&&(e.dropRange=g);!1===a.fire(b.name,e)&&b.data.preventDefault()}function e(a){a.type!=CKEDITOR.NODE_ELEMENT&&(a=a.getParent());return a.getChildCount()} -var h=a.editable(),k=CKEDITOR.plugins.clipboard.getDropTarget(a),l=a.ui.space("top"),m=a.ui.space("bottom");b.preventDefaultDropOnElement(l);b.preventDefaultDropOnElement(m);h.attachListener(k,"dragstart",d);h.attachListener(a,"dragstart",b.resetDragDataTransfer,b,null,1);h.attachListener(a,"dragstart",function(c){b.initDragDataTransfer(c,a)},null,null,2);h.attachListener(a,"dragstart",function(){var c=b.dragRange=a.getSelection().getRanges()[0];CKEDITOR.env.ie&&10>CKEDITOR.env.version&&(b.dragStartContainerChildCount= -c?e(c.startContainer):null,b.dragEndContainerChildCount=c?e(c.endContainer):null)},null,null,100);h.attachListener(k,"dragend",d);h.attachListener(a,"dragend",b.initDragDataTransfer,b,null,1);h.attachListener(a,"dragend",b.resetDragDataTransfer,b,null,100);h.attachListener(k,"dragover",function(a){if(CKEDITOR.env.edge)a.data.preventDefault();else{var b=a.data.getTarget();b&&b.is&&b.is("html")?a.data.preventDefault():CKEDITOR.env.ie&&CKEDITOR.plugins.clipboard.isFileApiSupported&&a.data.$.dataTransfer.types.contains("Files")&& -a.data.preventDefault()}});h.attachListener(k,"drop",function(c){if(!c.data.$.defaultPrevented){c.data.preventDefault();var g=c.data.getTarget();if(!g.isReadOnly()||g.type==CKEDITOR.NODE_ELEMENT&&g.is("html")){var g=b.getRangeAtDropPosition(c,a),e=b.dragRange;g&&d(c,e,g)}}},null,null,9999);h.attachListener(a,"drop",b.initDragDataTransfer,b,null,1);h.attachListener(a,"drop",function(d){if(d=d.data){var e=d.dropRange,f=d.dragRange,h=d.dataTransfer;h.getTransferType(a)==CKEDITOR.DATA_TRANSFER_INTERNAL? -setTimeout(function(){b.internalDrop(f,e,h,a)},0):h.getTransferType(a)==CKEDITOR.DATA_TRANSFER_CROSS_EDITORS?c(f,e,h):g(e,h)}},null,null,9999)})}var c;CKEDITOR.plugins.add("clipboard",{requires:"dialog,notification,toolbar",init:function(a){var b,c=d();a.config.forcePasteAsPlainText?b="plain-text":a.config.pasteFilter?b=a.config.pasteFilter:!CKEDITOR.env.webkit||"pasteFilter"in a.config||(b="semantic-content");a.pasteFilter=c.get(b);h(a);g(a);CKEDITOR.dialog.add("paste",CKEDITOR.getUrl(this.path+ -"dialogs/paste.js"));if(CKEDITOR.env.gecko){var f=["image/png","image/jpeg","image/gif"],m;a.on("paste",function(b){var c=b.data,g=c.dataTransfer;if(!c.dataValue&&"paste"==c.method&&g&&1==g.getFilesCount()&&m!=g.id&&(g=g.getFile(0),-1!=CKEDITOR.tools.indexOf(f,g.type))){var d=new FileReader;d.addEventListener("load",function(){b.data.dataValue='\x3cimg src\x3d"'+d.result+'" /\x3e';a.fire("paste",b.data)},!1);d.addEventListener("abort",function(){a.fire("paste",b.data)},!1);d.addEventListener("error", -function(){a.fire("paste",b.data)},!1);d.readAsDataURL(g);m=c.dataTransfer.id;b.stop()}},null,null,1)}a.on("paste",function(b){b.data.dataTransfer||(b.data.dataTransfer=new CKEDITOR.plugins.clipboard.dataTransfer);if(!b.data.dataValue){var c=b.data.dataTransfer,g=c.getData("text/html");if(g)b.data.dataValue=g,b.data.type="html";else if(g=c.getData("text/plain"))b.data.dataValue=a.editable().transformPlainTextToHtml(g),b.data.type="text"}},null,null,1);a.on("paste",function(a){var b=a.data.dataValue, +{},b;for(b in CKEDITOR.dtd)"$"!=b.charAt(0)&&"div"!=b&&"span"!=b&&(a[b]=1);return a}var b={};return{get:function(c){return"plain-text"==c?b.plainText||(b.plainText=new CKEDITOR.filter("br")):"semantic-content"==c?((c=b.semanticContent)||(c=new CKEDITOR.filter,c.allow({$1:{elements:a(),attributes:!0,styles:!1,classes:!1}}),c=b.semanticContent=c),c):c?new CKEDITOR.filter(c):null}}}function l(a,b,c){b=CKEDITOR.htmlParser.fragment.fromHtml(b);var d=new CKEDITOR.htmlParser.basicWriter;c.applyTo(b,!0,!1, +a.activeEnterMode);b.writeHtml(d);return d.getHtml()}function m(a,b){a.enterMode==CKEDITOR.ENTER_BR?b=b.replace(/(<\/p><p>)+/g,function(a){return CKEDITOR.tools.repeat("\x3cbr\x3e",a.length/7*2)}).replace(/<\/?p>/g,""):a.enterMode==CKEDITOR.ENTER_DIV&&(b=b.replace(/<(\/)?p>/g,"\x3c$1div\x3e"));return b}function b(a){a.data.preventDefault();a.data.$.dataTransfer.dropEffect="none"}function g(a){var b=CKEDITOR.plugins.clipboard;a.on("contentDom",function(){function c(b,d,g){d.select();f(a,{dataTransfer:g, +method:"drop"},1);g.sourceEditor.fire("saveSnapshot");g.sourceEditor.editable().extractHtmlFromRange(b);g.sourceEditor.getSelection().selectRanges([b]);g.sourceEditor.fire("saveSnapshot")}function d(c,g){c.select();f(a,{dataTransfer:g,method:"drop"},1);b.resetDragDataTransfer()}function g(b,c,d){var e={$:b.data.$,target:b.data.getTarget()};c&&(e.dragRange=c);d&&(e.dropRange=d);!1===a.fire(b.name,e)&&b.data.preventDefault()}function e(a){a.type!=CKEDITOR.NODE_ELEMENT&&(a=a.getParent());return a.getChildCount()} +var h=a.editable(),k=CKEDITOR.plugins.clipboard.getDropTarget(a),l=a.ui.space("top"),m=a.ui.space("bottom");b.preventDefaultDropOnElement(l);b.preventDefaultDropOnElement(m);h.attachListener(k,"dragstart",g);h.attachListener(a,"dragstart",b.resetDragDataTransfer,b,null,1);h.attachListener(a,"dragstart",function(c){b.initDragDataTransfer(c,a)},null,null,2);h.attachListener(a,"dragstart",function(){var c=b.dragRange=a.getSelection().getRanges()[0];CKEDITOR.env.ie&&10>CKEDITOR.env.version&&(b.dragStartContainerChildCount= +c?e(c.startContainer):null,b.dragEndContainerChildCount=c?e(c.endContainer):null)},null,null,100);h.attachListener(k,"dragend",g);h.attachListener(a,"dragend",b.initDragDataTransfer,b,null,1);h.attachListener(a,"dragend",b.resetDragDataTransfer,b,null,100);h.attachListener(k,"dragover",function(a){if(CKEDITOR.env.edge)a.data.preventDefault();else{var b=a.data.getTarget();b&&b.is&&b.is("html")?a.data.preventDefault():CKEDITOR.env.ie&&CKEDITOR.plugins.clipboard.isFileApiSupported&&a.data.$.dataTransfer.types.contains("Files")&& +a.data.preventDefault()}});h.attachListener(k,"drop",function(c){if(!c.data.$.defaultPrevented){c.data.preventDefault();var d=c.data.getTarget();if(!d.isReadOnly()||d.type==CKEDITOR.NODE_ELEMENT&&d.is("html")){var d=b.getRangeAtDropPosition(c,a),e=b.dragRange;d&&g(c,e,d)}}},null,null,9999);h.attachListener(a,"drop",b.initDragDataTransfer,b,null,1);h.attachListener(a,"drop",function(g){if(g=g.data){var e=g.dropRange,f=g.dragRange,h=g.dataTransfer;h.getTransferType(a)==CKEDITOR.DATA_TRANSFER_INTERNAL? +setTimeout(function(){b.internalDrop(f,e,h,a)},0):h.getTransferType(a)==CKEDITOR.DATA_TRANSFER_CROSS_EDITORS?c(f,e,h):d(e,h)}},null,null,9999)})}var c;CKEDITOR.plugins.add("clipboard",{requires:"dialog,notification,toolbar",init:function(a){var b,c=d();a.config.forcePasteAsPlainText?b="plain-text":a.config.pasteFilter?b=a.config.pasteFilter:!CKEDITOR.env.webkit||"pasteFilter"in a.config||(b="semantic-content");a.pasteFilter=c.get(b);h(a);g(a);CKEDITOR.dialog.add("paste",CKEDITOR.getUrl(this.path+ +"dialogs/paste.js"));if(CKEDITOR.env.gecko){var f=["image/png","image/jpeg","image/gif"],m;a.on("paste",function(b){var c=b.data,d=c.dataTransfer;if(!c.dataValue&&"paste"==c.method&&d&&1==d.getFilesCount()&&m!=d.id&&(d=d.getFile(0),-1!=CKEDITOR.tools.indexOf(f,d.type))){var g=new FileReader;g.addEventListener("load",function(){b.data.dataValue='\x3cimg src\x3d"'+g.result+'" /\x3e';a.fire("paste",b.data)},!1);g.addEventListener("abort",function(){a.fire("paste",b.data)},!1);g.addEventListener("error", +function(){a.fire("paste",b.data)},!1);g.readAsDataURL(d);m=c.dataTransfer.id;b.stop()}},null,null,1)}a.on("paste",function(b){b.data.dataTransfer||(b.data.dataTransfer=new CKEDITOR.plugins.clipboard.dataTransfer);if(!b.data.dataValue){var c=b.data.dataTransfer,d=c.getData("text/html");if(d)b.data.dataValue=d,b.data.type="html";else if(d=c.getData("text/plain"))b.data.dataValue=a.editable().transformPlainTextToHtml(d),b.data.type="text"}},null,null,1);a.on("paste",function(a){var b=a.data.dataValue, c=CKEDITOR.dtd.$block;-1<b.indexOf("Apple-")&&(b=b.replace(/<span class="Apple-converted-space"> <\/span>/gi," "),"html"!=a.data.type&&(b=b.replace(/<span class="Apple-tab-span"[^>]*>([^<]*)<\/span>/gi,function(a,b){return b.replace(/\t/g,"\x26nbsp;\x26nbsp; \x26nbsp;")})),-1<b.indexOf('\x3cbr class\x3d"Apple-interchange-newline"\x3e')&&(a.data.startsWithEOL=1,a.data.preSniffing="html",b=b.replace(/<br class="Apple-interchange-newline">/,"")),b=b.replace(/(<[^>]+) class="Apple-[^"]*"/gi,"$1")); -if(b.match(/^<[^<]+cke_(editable|contents)/i)){var g,d,e=new CKEDITOR.dom.element("div");for(e.setHtml(b);1==e.getChildCount()&&(g=e.getFirst())&&g.type==CKEDITOR.NODE_ELEMENT&&(g.hasClass("cke_editable")||g.hasClass("cke_contents"));)e=d=g;d&&(b=d.getHtml().replace(/<br>$/i,""))}CKEDITOR.env.ie?b=b.replace(/^ (?: |\r\n)?<(\w+)/g,function(b,g){return g.toLowerCase()in c?(a.data.preSniffing="html","\x3c"+g):b}):CKEDITOR.env.webkit?b=b.replace(/<\/(\w+)><div><br><\/div>$/,function(b,g){return g in -c?(a.data.endsWithEOL=1,"\x3c/"+g+"\x3e"):b}):CKEDITOR.env.gecko&&(b=b.replace(/(\s)<br>$/,"$1"));a.data.dataValue=b},null,null,3);a.on("paste",function(b){b=b.data;var g=a._.nextPasteType||b.type,d=b.dataValue,f,h=a.config.clipboard_defaultContentType||"html",m=b.dataTransfer.getTransferType(a)==CKEDITOR.DATA_TRANSFER_EXTERNAL,n=!0===a.config.forcePasteAsPlainText;f="html"==g||"html"==b.preSniffing?"html":e(d);delete a._.nextPasteType;"htmlifiedtext"==f&&(d=k(a.config,d));if("text"==g&&"html"==f)d= -l(a,d,c.get("plain-text"));else if(m&&a.pasteFilter&&!b.dontFilter||n)d=l(a,d,a.pasteFilter);b.startsWithEOL&&(d='\x3cbr data-cke-eol\x3d"1"\x3e'+d);b.endsWithEOL&&(d+='\x3cbr data-cke-eol\x3d"1"\x3e');"auto"==g&&(g="html"==f||"html"==h?"html":"text");b.type=g;b.dataValue=d;delete b.preSniffing;delete b.startsWithEOL;delete b.endsWithEOL},null,null,6);a.on("paste",function(b){b=b.data;b.dataValue&&(a.insertHtml(b.dataValue,b.type,b.range),setTimeout(function(){a.fire("afterPaste")},0))},null,null, +if(b.match(/^<[^<]+cke_(editable|contents)/i)){var d,g,e=new CKEDITOR.dom.element("div");for(e.setHtml(b);1==e.getChildCount()&&(d=e.getFirst())&&d.type==CKEDITOR.NODE_ELEMENT&&(d.hasClass("cke_editable")||d.hasClass("cke_contents"));)e=g=d;g&&(b=g.getHtml().replace(/<br>$/i,""))}CKEDITOR.env.ie?b=b.replace(/^ (?: |\r\n)?<(\w+)/g,function(b,d){return d.toLowerCase()in c?(a.data.preSniffing="html","\x3c"+d):b}):CKEDITOR.env.webkit?b=b.replace(/<\/(\w+)><div><br><\/div>$/,function(b,d){return d in +c?(a.data.endsWithEOL=1,"\x3c/"+d+"\x3e"):b}):CKEDITOR.env.gecko&&(b=b.replace(/(\s)<br>$/,"$1"));a.data.dataValue=b},null,null,3);a.on("paste",function(b){b=b.data;var d=a._.nextPasteType||b.type,g=b.dataValue,f,h=a.config.clipboard_defaultContentType||"html",m=b.dataTransfer.getTransferType(a)==CKEDITOR.DATA_TRANSFER_EXTERNAL,n=!0===a.config.forcePasteAsPlainText;f="html"==d||"html"==b.preSniffing?"html":e(g);delete a._.nextPasteType;"htmlifiedtext"==f&&(g=k(a.config,g));if("text"==d&&"html"==f)g= +l(a,g,c.get("plain-text"));else if(m&&a.pasteFilter&&!b.dontFilter||n)g=l(a,g,a.pasteFilter);b.startsWithEOL&&(g='\x3cbr data-cke-eol\x3d"1"\x3e'+g);b.endsWithEOL&&(g+='\x3cbr data-cke-eol\x3d"1"\x3e');"auto"==d&&(d="html"==f||"html"==h?"html":"text");b.type=d;b.dataValue=g;delete b.preSniffing;delete b.startsWithEOL;delete b.endsWithEOL},null,null,6);a.on("paste",function(b){b=b.data;b.dataValue&&(a.insertHtml(b.dataValue,b.type,b.range),setTimeout(function(){a.fire("afterPaste")},0))},null,null, 1E3);a.on("pasteDialog",function(b){setTimeout(function(){a.openDialog("paste",b.data)},0)})}});CKEDITOR.plugins.clipboard={isCustomCopyCutSupported:(!CKEDITOR.env.ie||16<=CKEDITOR.env.version)&&!CKEDITOR.env.iOS,isCustomDataTypesSupported:!CKEDITOR.env.ie||16<=CKEDITOR.env.version,isFileApiSupported:!CKEDITOR.env.ie||9<CKEDITOR.env.version,mainPasteEvent:CKEDITOR.env.ie&&!CKEDITOR.env.edge?"beforepaste":"paste",addPasteButton:function(a,b,c){a.ui.addButton&&(a.ui.addButton(b,c),a._.pasteButtons|| (a._.pasteButtons=[]),a._.pasteButtons.push(b))},canClipboardApiBeTrusted:function(a,b){return a.getTransferType(b)!=CKEDITOR.DATA_TRANSFER_EXTERNAL||CKEDITOR.env.chrome&&!a.isEmpty()||CKEDITOR.env.gecko&&(a.getData("text/html")||a.getFilesCount())||CKEDITOR.env.safari&&603<=CKEDITOR.env.version&&!CKEDITOR.env.iOS||CKEDITOR.env.edge&&16<=CKEDITOR.env.version?!0:!1},getDropTarget:function(a){var b=a.editable();return CKEDITOR.env.ie&&9>CKEDITOR.env.version||b.isInline()?b:a.document},fixSplitNodesAfterDrop:function(a, -b,c,g){function d(a,c,g){var e=a;e.type==CKEDITOR.NODE_TEXT&&(e=a.getParent());if(e.equals(c)&&g!=c.getChildCount())return a=b.startContainer.getChild(b.startOffset-1),c=b.startContainer.getChild(b.startOffset),a&&a.type==CKEDITOR.NODE_TEXT&&c&&c.type==CKEDITOR.NODE_TEXT&&(g=a.getLength(),a.setText(a.getText()+c.getText()),c.remove(),b.setStart(a,g),b.collapse(!0)),!0}var e=b.startContainer;"number"==typeof g&&"number"==typeof c&&e.type==CKEDITOR.NODE_ELEMENT&&(d(a.startContainer,e,c)||d(a.endContainer, -e,g))},isDropRangeAffectedByDragRange:function(a,b){var c=b.startContainer,g=b.endOffset;return a.endContainer.equals(c)&&a.endOffset<=g||a.startContainer.getParent().equals(c)&&a.startContainer.getIndex()<g||a.endContainer.getParent().equals(c)&&a.endContainer.getIndex()<g?!0:!1},internalDrop:function(a,b,c,g){var d=CKEDITOR.plugins.clipboard,e=g.editable(),h,k;g.fire("saveSnapshot");g.fire("lockSnapshot",{dontUpdate:1});CKEDITOR.env.ie&&10>CKEDITOR.env.version&&this.fixSplitNodesAfterDrop(a,b,d.dragStartContainerChildCount, -d.dragEndContainerChildCount);(k=this.isDropRangeAffectedByDragRange(a,b))||(h=a.createBookmark(!1));d=b.clone().createBookmark(!1);k&&(h=a.createBookmark(!1));a=h.startNode;b=h.endNode;k=d.startNode;b&&a.getPosition(k)&CKEDITOR.POSITION_PRECEDING&&b.getPosition(k)&CKEDITOR.POSITION_FOLLOWING&&k.insertBefore(a);a=g.createRange();a.moveToBookmark(h);e.extractHtmlFromRange(a,1);b=g.createRange();b.moveToBookmark(d);f(g,{dataTransfer:c,method:"drop",range:b},1);g.fire("unlockSnapshot")},getRangeAtDropPosition:function(a, -b){var c=a.data.$,g=c.clientX,d=c.clientY,e=b.getSelection(!0).getRanges()[0],f=b.createRange();if(a.data.testRange)return a.data.testRange;if(document.caretRangeFromPoint&&b.document.$.caretRangeFromPoint(g,d))c=b.document.$.caretRangeFromPoint(g,d),f.setStart(CKEDITOR.dom.node(c.startContainer),c.startOffset),f.collapse(!0);else if(c.rangeParent)f.setStart(CKEDITOR.dom.node(c.rangeParent),c.rangeOffset),f.collapse(!0);else{if(CKEDITOR.env.ie&&8<CKEDITOR.env.version&&e&&b.editable().hasFocus)return e; -if(document.body.createTextRange){b.focus();c=b.document.getBody().$.createTextRange();try{for(var h=!1,k=0;20>k&&!h;k++){if(!h)try{c.moveToPoint(g,d-k),h=!0}catch(l){}if(!h)try{c.moveToPoint(g,d+k),h=!0}catch(m){}}if(h){var t="cke-temp-"+(new Date).getTime();c.pasteHTML('\x3cspan id\x3d"'+t+'"\x3e\x3c/span\x3e');var B=b.document.getById(t);f.moveToPosition(B,CKEDITOR.POSITION_BEFORE_START);B.remove()}else{var y=b.document.$.elementFromPoint(g,d),z=new CKEDITOR.dom.element(y),I;if(z.equals(b.editable())|| -"html"==z.getName())return e&&e.startContainer&&!e.startContainer.equals(b.editable())?e:null;I=z.getClientRect();g<I.left?f.setStartAt(z,CKEDITOR.POSITION_AFTER_START):f.setStartAt(z,CKEDITOR.POSITION_BEFORE_END);f.collapse(!0)}}catch(E){return null}}else return null}return f},initDragDataTransfer:function(a,b){var c=a.data.$?a.data.$.dataTransfer:null,g=new this.dataTransfer(c,b);"dragstart"===a.name&&g.storeId();c?this.dragData&&g.id==this.dragData.id?g=this.dragData:this.dragData=g:this.dragData? -g=this.dragData:this.dragData=g;a.data.dataTransfer=g},resetDragDataTransfer:function(){this.dragData=null},initPasteDataTransfer:function(a,b){if(this.isCustomCopyCutSupported){if(a&&a.data&&a.data.$){var c=a.data.$.clipboardData,g=new this.dataTransfer(c,b);"copy"!==a.name&&"cut"!==a.name||g.storeId();this.copyCutData&&g.id==this.copyCutData.id?(g=this.copyCutData,g.$=c):this.copyCutData=g;return g}return new this.dataTransfer(null,b)}return new this.dataTransfer(CKEDITOR.env.edge&&a&&a.data.$&& +b,c,d){function g(a,c,d){var e=a;e.type==CKEDITOR.NODE_TEXT&&(e=a.getParent());if(e.equals(c)&&d!=c.getChildCount())return a=b.startContainer.getChild(b.startOffset-1),c=b.startContainer.getChild(b.startOffset),a&&a.type==CKEDITOR.NODE_TEXT&&c&&c.type==CKEDITOR.NODE_TEXT&&(d=a.getLength(),a.setText(a.getText()+c.getText()),c.remove(),b.setStart(a,d),b.collapse(!0)),!0}var e=b.startContainer;"number"==typeof d&&"number"==typeof c&&e.type==CKEDITOR.NODE_ELEMENT&&(g(a.startContainer,e,c)||g(a.endContainer, +e,d))},isDropRangeAffectedByDragRange:function(a,b){var c=b.startContainer,d=b.endOffset;return a.endContainer.equals(c)&&a.endOffset<=d||a.startContainer.getParent().equals(c)&&a.startContainer.getIndex()<d||a.endContainer.getParent().equals(c)&&a.endContainer.getIndex()<d?!0:!1},internalDrop:function(a,b,c,d){var g=CKEDITOR.plugins.clipboard,e=d.editable(),h,k;d.fire("saveSnapshot");d.fire("lockSnapshot",{dontUpdate:1});CKEDITOR.env.ie&&10>CKEDITOR.env.version&&this.fixSplitNodesAfterDrop(a,b,g.dragStartContainerChildCount, +g.dragEndContainerChildCount);(k=this.isDropRangeAffectedByDragRange(a,b))||(h=a.createBookmark(!1));g=b.clone().createBookmark(!1);k&&(h=a.createBookmark(!1));a=h.startNode;b=h.endNode;k=g.startNode;b&&a.getPosition(k)&CKEDITOR.POSITION_PRECEDING&&b.getPosition(k)&CKEDITOR.POSITION_FOLLOWING&&k.insertBefore(a);a=d.createRange();a.moveToBookmark(h);e.extractHtmlFromRange(a,1);b=d.createRange();b.moveToBookmark(g);f(d,{dataTransfer:c,method:"drop",range:b},1);d.fire("unlockSnapshot")},getRangeAtDropPosition:function(a, +b){var c=a.data.$,d=c.clientX,g=c.clientY,e=b.getSelection(!0).getRanges()[0],f=b.createRange();if(a.data.testRange)return a.data.testRange;if(document.caretRangeFromPoint&&b.document.$.caretRangeFromPoint(d,g))c=b.document.$.caretRangeFromPoint(d,g),f.setStart(CKEDITOR.dom.node(c.startContainer),c.startOffset),f.collapse(!0);else if(c.rangeParent)f.setStart(CKEDITOR.dom.node(c.rangeParent),c.rangeOffset),f.collapse(!0);else{if(CKEDITOR.env.ie&&8<CKEDITOR.env.version&&e&&b.editable().hasFocus)return e; +if(document.body.createTextRange){b.focus();c=b.document.getBody().$.createTextRange();try{for(var h=!1,k=0;20>k&&!h;k++){if(!h)try{c.moveToPoint(d,g-k),h=!0}catch(l){}if(!h)try{c.moveToPoint(d,g+k),h=!0}catch(m){}}if(h){var u="cke-temp-"+(new Date).getTime();c.pasteHTML('\x3cspan id\x3d"'+u+'"\x3e\x3c/span\x3e');var y=b.document.getById(u);f.moveToPosition(y,CKEDITOR.POSITION_BEFORE_START);y.remove()}else{var x=b.document.$.elementFromPoint(d,g),z=new CKEDITOR.dom.element(x),I;if(z.equals(b.editable())|| +"html"==z.getName())return e&&e.startContainer&&!e.startContainer.equals(b.editable())?e:null;I=z.getClientRect();d<I.left?f.setStartAt(z,CKEDITOR.POSITION_AFTER_START):f.setStartAt(z,CKEDITOR.POSITION_BEFORE_END);f.collapse(!0)}}catch(F){return null}}else return null}return f},initDragDataTransfer:function(a,b){var c=a.data.$?a.data.$.dataTransfer:null,d=new this.dataTransfer(c,b);"dragstart"===a.name&&d.storeId();c?this.dragData&&d.id==this.dragData.id?d=this.dragData:this.dragData=d:this.dragData? +d=this.dragData:this.dragData=d;a.data.dataTransfer=d},resetDragDataTransfer:function(){this.dragData=null},initPasteDataTransfer:function(a,b){if(this.isCustomCopyCutSupported){if(a&&a.data&&a.data.$){var c=a.data.$.clipboardData,d=new this.dataTransfer(c,b);"copy"!==a.name&&"cut"!==a.name||d.storeId();this.copyCutData&&d.id==this.copyCutData.id?(d=this.copyCutData,d.$=c):this.copyCutData=d;return d}return new this.dataTransfer(null,b)}return new this.dataTransfer(CKEDITOR.env.edge&&a&&a.data.$&& a.data.$.clipboardData||null,b)},preventDefaultDropOnElement:function(a){a&&a.on("dragover",b)}};c=CKEDITOR.plugins.clipboard.isCustomDataTypesSupported?"cke/id":"Text";CKEDITOR.plugins.clipboard.dataTransfer=function(a,b){a&&(this.$=a);this._={metaRegExp:/^<meta.*?>/i,bodyRegExp:/<body(?:[\s\S]*?)>([\s\S]*)<\/body>/i,fragmentRegExp:/\x3c!--(?:Start|End)Fragment--\x3e/g,data:{},files:[],nativeHtmlCache:"",normalizeType:function(a){a=a.toLowerCase();return"text"==a||"text/plain"==a?"Text":"url"==a? "URL":a}};this._.fallbackDataTransfer=new CKEDITOR.plugins.clipboard.fallbackDataTransfer(this);this.id=this.getData(c);this.id||(this.id="Text"==c?"":"cke-"+CKEDITOR.tools.getUniqueId());b&&(this.sourceEditor=b,this.setData("text/html",b.getSelectedHtml(1)),"Text"==c||this.getData("text/plain")||this.setData("text/plain",b.getSelection().getSelectedText()))};CKEDITOR.DATA_TRANSFER_INTERNAL=1;CKEDITOR.DATA_TRANSFER_CROSS_EDITORS=2;CKEDITOR.DATA_TRANSFER_EXTERNAL=3;CKEDITOR.plugins.clipboard.dataTransfer.prototype= -{getData:function(a,b){a=this._.normalizeType(a);var c="text/html"==a&&b?this._.nativeHtmlCache:this._.data[a];if(void 0===c||null===c||""===c){if(this._.fallbackDataTransfer.isRequired())c=this._.fallbackDataTransfer.getData(a,b);else try{c=this.$.getData(a)||""}catch(g){c=""}"text/html"!=a||b||(c=this._stripHtml(c))}"Text"==a&&CKEDITOR.env.gecko&&this.getFilesCount()&&"file://"==c.substring(0,7)&&(c="");if("string"===typeof c)var d=c.indexOf("\x3c/html\x3e"),c=-1!==d?c.substring(0,d+7):c;return c}, -setData:function(a,b){a=this._.normalizeType(a);"text/html"==a?(this._.data[a]=this._stripHtml(b),this._.nativeHtmlCache=b):this._.data[a]=b;if(CKEDITOR.plugins.clipboard.isCustomDataTypesSupported||"URL"==a||"Text"==a)if("Text"==c&&"Text"==a&&(this.id=b),this._.fallbackDataTransfer.isRequired())this._.fallbackDataTransfer.setData(a,b);else try{this.$.setData(a,b)}catch(g){}},storeId:function(){"Text"!==c&&this.setData(c,this.id)},getTransferType:function(a){return this.sourceEditor?this.sourceEditor== -a?CKEDITOR.DATA_TRANSFER_INTERNAL:CKEDITOR.DATA_TRANSFER_CROSS_EDITORS:CKEDITOR.DATA_TRANSFER_EXTERNAL},cacheData:function(){function a(a){a=b._.normalizeType(a);var c=b.getData(a);"text/html"==a&&(b._.nativeHtmlCache=b.getData(a,!0),c=b._stripHtml(c));c&&(b._.data[a]=c)}if(this.$){var b=this,c,g;if(CKEDITOR.plugins.clipboard.isCustomDataTypesSupported){if(this.$.types)for(c=0;c<this.$.types.length;c++)a(this.$.types[c])}else a("Text"),a("URL");g=this._getImageFromClipboard();if(this.$&&this.$.files|| -g){this._.files=[];if(this.$.files&&this.$.files.length)for(c=0;c<this.$.files.length;c++)this._.files.push(this.$.files[c]);0===this._.files.length&&g&&this._.files.push(g)}}},getFilesCount:function(){return this._.files.length?this._.files.length:this.$&&this.$.files&&this.$.files.length?this.$.files.length:this._getImageFromClipboard()?1:0},getFile:function(a){return this._.files.length?this._.files[a]:this.$&&this.$.files&&this.$.files.length?this.$.files[a]:0===a?this._getImageFromClipboard(): -void 0},isEmpty:function(){var a={},b;if(this.getFilesCount())return!1;CKEDITOR.tools.array.forEach(CKEDITOR.tools.objectKeys(this._.data),function(b){a[b]=1});if(this.$)if(CKEDITOR.plugins.clipboard.isCustomDataTypesSupported){if(this.$.types)for(var g=0;g<this.$.types.length;g++)a[this.$.types[g]]=1}else a.Text=1,a.URL=1;"Text"!=c&&(a[c]=0);for(b in a)if(a[b]&&""!==this.getData(b))return!1;return!0},_getImageFromClipboard:function(){var a;if(this.$&&this.$.items&&this.$.items[0])try{if((a=this.$.items[0].getAsFile())&& +{getData:function(a,b){a=this._.normalizeType(a);var c="text/html"==a&&b?this._.nativeHtmlCache:this._.data[a];if(void 0===c||null===c||""===c){if(this._.fallbackDataTransfer.isRequired())c=this._.fallbackDataTransfer.getData(a,b);else try{c=this.$.getData(a)||""}catch(d){c=""}"text/html"!=a||b||(c=this._stripHtml(c))}"Text"==a&&CKEDITOR.env.gecko&&this.getFilesCount()&&"file://"==c.substring(0,7)&&(c="");if("string"===typeof c)var g=c.indexOf("\x3c/html\x3e"),c=-1!==g?c.substring(0,g+7):c;return c}, +setData:function(a,b){a=this._.normalizeType(a);"text/html"==a?(this._.data[a]=this._stripHtml(b),this._.nativeHtmlCache=b):this._.data[a]=b;if(CKEDITOR.plugins.clipboard.isCustomDataTypesSupported||"URL"==a||"Text"==a)if("Text"==c&&"Text"==a&&(this.id=b),this._.fallbackDataTransfer.isRequired())this._.fallbackDataTransfer.setData(a,b);else try{this.$.setData(a,b)}catch(d){}},storeId:function(){"Text"!==c&&this.setData(c,this.id)},getTransferType:function(a){return this.sourceEditor?this.sourceEditor== +a?CKEDITOR.DATA_TRANSFER_INTERNAL:CKEDITOR.DATA_TRANSFER_CROSS_EDITORS:CKEDITOR.DATA_TRANSFER_EXTERNAL},cacheData:function(){function a(a){a=b._.normalizeType(a);var c=b.getData(a);"text/html"==a&&(b._.nativeHtmlCache=b.getData(a,!0),c=b._stripHtml(c));c&&(b._.data[a]=c)}if(this.$){var b=this,c,d;if(CKEDITOR.plugins.clipboard.isCustomDataTypesSupported){if(this.$.types)for(c=0;c<this.$.types.length;c++)a(this.$.types[c])}else a("Text"),a("URL");d=this._getImageFromClipboard();if(this.$&&this.$.files|| +d){this._.files=[];if(this.$.files&&this.$.files.length)for(c=0;c<this.$.files.length;c++)this._.files.push(this.$.files[c]);0===this._.files.length&&d&&this._.files.push(d)}}},getFilesCount:function(){return this._.files.length?this._.files.length:this.$&&this.$.files&&this.$.files.length?this.$.files.length:this._getImageFromClipboard()?1:0},getFile:function(a){return this._.files.length?this._.files[a]:this.$&&this.$.files&&this.$.files.length?this.$.files[a]:0===a?this._getImageFromClipboard(): +void 0},isEmpty:function(){var a={},b;if(this.getFilesCount())return!1;CKEDITOR.tools.array.forEach(CKEDITOR.tools.objectKeys(this._.data),function(b){a[b]=1});if(this.$)if(CKEDITOR.plugins.clipboard.isCustomDataTypesSupported){if(this.$.types)for(var d=0;d<this.$.types.length;d++)a[this.$.types[d]]=1}else a.Text=1,a.URL=1;"Text"!=c&&(a[c]=0);for(b in a)if(a[b]&&""!==this.getData(b))return!1;return!0},_getImageFromClipboard:function(){var a;if(this.$&&this.$.items&&this.$.items[0])try{if((a=this.$.items[0].getAsFile())&& a.type)return a}catch(b){}},_stripHtml:function(a){if(a&&a.length){a=a.replace(this._.metaRegExp,"");var b=this._.bodyRegExp.exec(a);b&&b.length&&(a=b[1],a=a.replace(this._.fragmentRegExp,""))}return a}};CKEDITOR.plugins.clipboard.fallbackDataTransfer=function(a){this._dataTransfer=a;this._customDataFallbackType="text/html"};CKEDITOR.plugins.clipboard.fallbackDataTransfer._isCustomMimeTypeSupported=null;CKEDITOR.plugins.clipboard.fallbackDataTransfer._customTypes=[];CKEDITOR.plugins.clipboard.fallbackDataTransfer.prototype= -{isRequired:function(){var a=CKEDITOR.plugins.clipboard.fallbackDataTransfer,b=this._dataTransfer.$;if(null===a._isCustomMimeTypeSupported)if(b){a._isCustomMimeTypeSupported=!1;try{b.setData("cke/mimetypetest","cke test value"),a._isCustomMimeTypeSupported="cke test value"===b.getData("cke/mimetypetest"),b.clearData("cke/mimetypetest")}catch(c){}}else return!1;return!a._isCustomMimeTypeSupported},getData:function(a,b){var c=this._getData(this._customDataFallbackType,!0);if(b)return c;var c=this._extractDataComment(c), -g=null,g=a===this._customDataFallbackType?c.content:c.data&&c.data[a]?c.data[a]:this._getData(a,!0);return null!==g?g:""},setData:function(a,b){var c=a===this._customDataFallbackType;c&&(b=this._applyDataComment(b,this._getFallbackTypeData()));var g=b,d=this._dataTransfer.$;try{d.setData(a,g),c&&(this._dataTransfer._.nativeHtmlCache=g)}catch(e){if(this._isUnsupportedMimeTypeError(e)){c=CKEDITOR.plugins.clipboard.fallbackDataTransfer;-1===CKEDITOR.tools.indexOf(c._customTypes,a)&&c._customTypes.push(a); -var c=this._getFallbackTypeContent(),f=this._getFallbackTypeData();f[a]=g;try{g=this._applyDataComment(c,f),d.setData(this._customDataFallbackType,g),this._dataTransfer._.nativeHtmlCache=g}catch(h){g=""}}}return g},_getData:function(a,b){var c=this._dataTransfer._.data;if(!b&&c[a])return c[a];try{return this._dataTransfer.$.getData(a)}catch(g){return null}},_getFallbackTypeContent:function(){var a=this._dataTransfer._.data[this._customDataFallbackType];a||(a=this._extractDataComment(this._getData(this._customDataFallbackType, +{isRequired:function(){var a=CKEDITOR.plugins.clipboard.fallbackDataTransfer,b=this._dataTransfer.$;if(null===a._isCustomMimeTypeSupported)if(b){a._isCustomMimeTypeSupported=!1;if(CKEDITOR.env.edge&&17<=CKEDITOR.env.version)return!0;try{b.setData("cke/mimetypetest","cke test value"),a._isCustomMimeTypeSupported="cke test value"===b.getData("cke/mimetypetest"),b.clearData("cke/mimetypetest")}catch(c){}}else return!1;return!a._isCustomMimeTypeSupported},getData:function(a,b){var c=this._getData(this._customDataFallbackType, +!0);if(b)return c;var c=this._extractDataComment(c),d=null,d=a===this._customDataFallbackType?c.content:c.data&&c.data[a]?c.data[a]:this._getData(a,!0);return null!==d?d:""},setData:function(a,b){var c=a===this._customDataFallbackType;c&&(b=this._applyDataComment(b,this._getFallbackTypeData()));var d=b,g=this._dataTransfer.$;try{g.setData(a,d),c&&(this._dataTransfer._.nativeHtmlCache=d)}catch(e){if(this._isUnsupportedMimeTypeError(e)){c=CKEDITOR.plugins.clipboard.fallbackDataTransfer;-1===CKEDITOR.tools.indexOf(c._customTypes, +a)&&c._customTypes.push(a);var c=this._getFallbackTypeContent(),f=this._getFallbackTypeData();f[a]=d;try{d=this._applyDataComment(c,f),g.setData(this._customDataFallbackType,d),this._dataTransfer._.nativeHtmlCache=d}catch(h){d=""}}}return d},_getData:function(a,b){var c=this._dataTransfer._.data;if(!b&&c[a])return c[a];try{return this._dataTransfer.$.getData(a)}catch(d){return null}},_getFallbackTypeContent:function(){var a=this._dataTransfer._.data[this._customDataFallbackType];a||(a=this._extractDataComment(this._getData(this._customDataFallbackType, !0)).content);return a},_getFallbackTypeData:function(){var a=CKEDITOR.plugins.clipboard.fallbackDataTransfer._customTypes,b=this._extractDataComment(this._getData(this._customDataFallbackType,!0)).data||{},c=this._dataTransfer._.data;CKEDITOR.tools.array.forEach(a,function(a){void 0!==c[a]?b[a]=c[a]:void 0!==b[a]&&(b[a]=b[a])},this);return b},_isUnsupportedMimeTypeError:function(a){return a.message&&-1!==a.message.search(/element not found/gi)},_extractDataComment:function(a){var b={data:null,content:a|| ""};if(a&&16<a.length){var c;(c=/\x3c!--cke-data:(.*?)--\x3e/g.exec(a))&&c[1]&&(b.data=JSON.parse(decodeURIComponent(c[1])),b.content=a.replace(c[0],""))}return b},_applyDataComment:function(a,b){var c="";b&&CKEDITOR.tools.objectKeys(b).length&&(c="\x3c!--cke-data:"+encodeURIComponent(JSON.stringify(b))+"--\x3e");return c+(a&&a.length?a:"")}}}(),CKEDITOR.config.clipboard_notificationDuration=1E4,function(){CKEDITOR.plugins.add("panel",{beforeInit:function(e){e.ui.addHandler(CKEDITOR.UI_PANEL,CKEDITOR.ui.panel.handler)}}); CKEDITOR.UI_PANEL="panel";CKEDITOR.ui.panel=function(e,d){d&&CKEDITOR.tools.extend(this,d);CKEDITOR.tools.extend(this,{className:"",css:[]});this.id=CKEDITOR.tools.getNextId();this.document=e;this.isFramed=this.forceIFrame||this.css.length;this._={blocks:{}}};CKEDITOR.ui.panel.handler={create:function(e){return new CKEDITOR.ui.panel(e)}};var f=CKEDITOR.addTemplate("panel",'\x3cdiv lang\x3d"{langCode}" id\x3d"{id}" dir\x3d{dir} class\x3d"cke cke_reset_all {editorId} cke_panel cke_panel {cls} cke_{dir}" style\x3d"z-index:{z-index}" role\x3d"presentation"\x3e{frame}\x3c/div\x3e'), h=CKEDITOR.addTemplate("panel-frame",'\x3ciframe id\x3d"{id}" class\x3d"cke_panel_frame" role\x3d"presentation" frameborder\x3d"0" src\x3d"{src}"\x3e\x3c/iframe\x3e'),e=CKEDITOR.addTemplate("panel-frame-inner",'\x3c!DOCTYPE html\x3e\x3chtml class\x3d"cke_panel_container {env}" dir\x3d"{dir}" lang\x3d"{langCode}"\x3e\x3chead\x3e{css}\x3c/head\x3e\x3cbody class\x3d"cke_{dir}" style\x3d"margin:0;padding:0" onload\x3d"{onload}"\x3e\x3c/body\x3e\x3c/html\x3e');CKEDITOR.ui.panel.prototype={render:function(k, -d){this.getHolderElement=function(){var b=this._.holder;if(!b){if(this.isFramed){var b=this.document.getById(this.id+"_frame"),g=b.getParent(),b=b.getFrameDocument();CKEDITOR.env.iOS&&g.setStyles({overflow:"scroll","-webkit-overflow-scrolling":"touch"});g=CKEDITOR.tools.addFunction(CKEDITOR.tools.bind(function(){this.isLoaded=!0;if(this.onLoad)this.onLoad()},this));b.write(e.output(CKEDITOR.tools.extend({css:CKEDITOR.tools.buildStyleHtml(this.css),onload:"window.parent.CKEDITOR.tools.callFunction("+ -g+");"},l)));b.getWindow().$.CKEDITOR=CKEDITOR;b.on("keydown",function(b){var a=b.data.getKeystroke(),g=this.document.getById(this.id).getAttribute("dir");this._.onKeyDown&&!1===this._.onKeyDown(a)?b.data.preventDefault():(27==a||a==("rtl"==g?39:37))&&this.onEscape&&!1===this.onEscape(a)&&b.data.preventDefault()},this);b=b.getBody();b.unselectable();CKEDITOR.env.air&&CKEDITOR.tools.callFunction(g)}else b=this.document.getById(this.id);this._.holder=b}return b};var l={editorId:k.id,id:this.id,langCode:k.langCode, +d){this.getHolderElement=function(){var b=this._.holder;if(!b){if(this.isFramed){var b=this.document.getById(this.id+"_frame"),d=b.getParent(),b=b.getFrameDocument();CKEDITOR.env.iOS&&d.setStyles({overflow:"scroll","-webkit-overflow-scrolling":"touch"});d=CKEDITOR.tools.addFunction(CKEDITOR.tools.bind(function(){this.isLoaded=!0;if(this.onLoad)this.onLoad()},this));b.write(e.output(CKEDITOR.tools.extend({css:CKEDITOR.tools.buildStyleHtml(this.css),onload:"window.parent.CKEDITOR.tools.callFunction("+ +d+");"},l)));b.getWindow().$.CKEDITOR=CKEDITOR;b.on("keydown",function(b){var a=b.data.getKeystroke(),d=this.document.getById(this.id).getAttribute("dir");this._.onKeyDown&&!1===this._.onKeyDown(a)?b.data.preventDefault():(27==a||a==("rtl"==d?39:37))&&this.onEscape&&!1===this.onEscape(a)&&b.data.preventDefault()},this);b=b.getBody();b.unselectable();CKEDITOR.env.air&&CKEDITOR.tools.callFunction(d)}else b=this.document.getById(this.id);this._.holder=b}return b};var l={editorId:k.id,id:this.id,langCode:k.langCode, dir:k.lang.dir,cls:this.className,frame:"",env:CKEDITOR.env.cssClass,"z-index":k.config.baseFloatZIndex+1};if(this.isFramed){var m=CKEDITOR.env.air?"javascript:void(0)":CKEDITOR.env.ie?"javascript:void(function(){"+encodeURIComponent("document.open();("+CKEDITOR.tools.fixDomain+")();document.close();")+"}())":"";l.frame=h.output({id:this.id+"_frame",src:m})}m=f.output(l);d&&d.push(m);return m},addBlock:function(e,d){d=this._.blocks[e]=d instanceof CKEDITOR.ui.panel.block?d:new CKEDITOR.ui.panel.block(this.getHolderElement(), d);this._.currentBlock||this.showBlock(e);return d},getBlock:function(e){return this._.blocks[e]},showBlock:function(e){e=this._.blocks[e];var d=this._.currentBlock,f=!this.forceIFrame||CKEDITOR.env.ie?this._.holder:this.document.getById(this.id+"_frame");d&&d.hide();this._.currentBlock=e;CKEDITOR.fire("ariaWidget",f);e._.focusIndex=-1;this._.onKeyDown=e.onKeyDown&&CKEDITOR.tools.bind(e.onKeyDown,e);e.show();return e},destroy:function(){this.element&&this.element.remove()}};CKEDITOR.ui.panel.block= CKEDITOR.tools.createClass({$:function(e,d){this.element=e.append(e.getDocument().createElement("div",{attributes:{tabindex:-1,"class":"cke_panel_block"},styles:{display:"none"}}));d&&CKEDITOR.tools.extend(this,d);this.element.setAttributes({role:this.attributes.role||"presentation","aria-label":this.attributes["aria-label"],title:this.attributes.title||this.attributes["aria-label"]});this.keys={};this._.focusIndex=-1;this.element.disableContextMenu()},_:{markItem:function(e){-1!=e&&(e=this.element.getElementsByTag("a").getItem(this._.focusIndex= @@ -728,12 +729,12 @@ getItems:function(){return this.element.getElementsByTag("a")}},proto:{show:func 1));case "prev":h=this._.focusIndex;for(f=this.element.getElementsByTag("a");0<h&&(b=f.getItem(--h));){if(b.getAttribute("_cke_focus")&&b.$.offsetWidth){this._.focusIndex=h;b.focus();break}b=null}return b||d?!1:(this._.focusIndex=f.count(),this.onKeyDown(e,1));case "click":case "mouseup":return h=this._.focusIndex,(b=0<=h&&this.element.getElementsByTag("a").getItem(h))&&(b.$[f]?b.$[f]():b.$["on"+f]()),!1}return!0}}})}(),CKEDITOR.plugins.add("floatpanel",{requires:"panel"}),function(){function f(e, f,d,l,m){m=CKEDITOR.tools.genKey(f.getUniqueId(),d.getUniqueId(),e.lang.dir,e.uiColor||"",l.css||"",m||"");var b=h[m];b||(b=h[m]=new CKEDITOR.ui.panel(f,l),b.element=d.append(CKEDITOR.dom.element.createFromHtml(b.render(e),f)),b.element.setStyles({display:"none",position:"absolute"}));return b}var h={};CKEDITOR.ui.floatPanel=CKEDITOR.tools.createClass({$:function(e,h,d,l){function m(){a.hide()}d.forceIFrame=1;d.toolbarRelated&&e.elementMode==CKEDITOR.ELEMENT_MODE_INLINE&&(h=CKEDITOR.document.getById("cke_"+ e.name));var b=h.getDocument();l=f(e,b,h,d,l||0);var g=l.element,c=g.getFirst(),a=this;g.disableContextMenu();this.element=g;this._={editor:e,panel:l,parentElement:h,definition:d,document:b,iframe:c,children:[],dir:e.lang.dir,showBlockParams:null};e.on("mode",m);e.on("resize",m);b.getWindow().on("resize",function(){this.reposition()},this)},proto:{addBlock:function(e,f){return this._.panel.addBlock(e,f)},addListBlock:function(e,f){return this._.panel.addListBlock(e,f)},getBlock:function(e){return this._.panel.getBlock(e)}, -showBlock:function(e,f,d,h,m,b){var g=this._.panel,c=g.showBlock(e);this._.showBlockParams=[].slice.call(arguments);this.allowBlur(!1);var a=this._.editor.editable();this._.returnFocus=a.hasFocus?a:new CKEDITOR.dom.element(CKEDITOR.document.$.activeElement);this._.hideTimeout=0;var n=this.element,a=this._.iframe,a=CKEDITOR.env.ie&&!CKEDITOR.env.edge?a:new CKEDITOR.dom.window(a.$.contentWindow),w=n.getDocument(),v=this._.parentElement.getPositionedAncestor(),p=f.getDocumentPosition(w),w=v?v.getDocumentPosition(w): -{x:0,y:0},r="rtl"==this._.dir,q=p.x+(h||0)-w.x,u=p.y+(m||0)-w.y;!r||1!=d&&4!=d?r||2!=d&&3!=d||(q+=f.$.offsetWidth-1):q+=f.$.offsetWidth;if(3==d||4==d)u+=f.$.offsetHeight-1;this._.panel._.offsetParentId=f.getId();n.setStyles({top:u+"px",left:0,display:""});n.setOpacity(0);n.getFirst().removeStyle("width");this._.editor.focusManager.add(a);this._.blurSet||(CKEDITOR.event.useCapture=!0,a.on("blur",function(a){function b(){delete this._.returnFocus;this.hide()}this.allowBlur()&&a.data.getPhase()==CKEDITOR.EVENT_PHASE_AT_TARGET&& +showBlock:function(e,f,d,h,m,b){var g=this._.panel,c=g.showBlock(e);this._.showBlockParams=[].slice.call(arguments);this.allowBlur(!1);var a=this._.editor.editable();this._.returnFocus=a.hasFocus?a:new CKEDITOR.dom.element(CKEDITOR.document.$.activeElement);this._.hideTimeout=0;var n=this.element,a=this._.iframe,a=CKEDITOR.env.ie&&!CKEDITOR.env.edge?a:new CKEDITOR.dom.window(a.$.contentWindow),w=n.getDocument(),v=this._.parentElement.getPositionedAncestor(),t=f.getDocumentPosition(w),w=v?v.getDocumentPosition(w): +{x:0,y:0},p="rtl"==this._.dir,q=t.x+(h||0)-w.x,A=t.y+(m||0)-w.y;!p||1!=d&&4!=d?p||2!=d&&3!=d||(q+=f.$.offsetWidth-1):q+=f.$.offsetWidth;if(3==d||4==d)A+=f.$.offsetHeight-1;this._.panel._.offsetParentId=f.getId();n.setStyles({top:A+"px",left:0,display:""});n.setOpacity(0);n.getFirst().removeStyle("width");this._.editor.focusManager.add(a);this._.blurSet||(CKEDITOR.event.useCapture=!0,a.on("blur",function(a){function b(){delete this._.returnFocus;this.hide()}this.allowBlur()&&a.data.getPhase()==CKEDITOR.EVENT_PHASE_AT_TARGET&& this.visible&&!this._.activeChild&&(CKEDITOR.env.iOS?this._.hideTimeout||(this._.hideTimeout=CKEDITOR.tools.setTimeout(b,0,this)):b.call(this))},this),a.on("focus",function(){this._.focused=!0;this.hideChild();this.allowBlur(!0)},this),CKEDITOR.env.iOS&&(a.on("touchstart",function(){clearTimeout(this._.hideTimeout)},this),a.on("touchend",function(){this._.hideTimeout=0;this.focus()},this)),CKEDITOR.event.useCapture=!1,this._.blurSet=1);g.onEscape=CKEDITOR.tools.bind(function(a){if(this.onEscape&& !1===this.onEscape(a))return!1},this);CKEDITOR.tools.setTimeout(function(){var a=CKEDITOR.tools.bind(function(){var a=n;a.removeStyle("width");if(c.autoSize){var d=c.element.getDocument(),d=(CKEDITOR.env.webkit||CKEDITOR.env.edge?c.element:d.getBody()).$.scrollWidth;CKEDITOR.env.ie&&CKEDITOR.env.quirks&&0<d&&(d+=(a.$.offsetWidth||0)-(a.$.clientWidth||0)+3);a.setStyle("width",d+10+"px");d=c.element.$.scrollHeight;CKEDITOR.env.ie&&CKEDITOR.env.quirks&&0<d&&(d+=(a.$.offsetHeight||0)-(a.$.clientHeight|| -0)+3);a.setStyle("height",d+"px");g._.currentBlock.element.setStyle("display","none").removeStyle("display")}else a.removeStyle("height");r&&(q-=n.$.offsetWidth);n.setStyle("left",q+"px");var d=g.element.getWindow(),a=n.$.getBoundingClientRect(),d=d.getViewPaneSize(),e=a.width||a.right-a.left,f=a.height||a.bottom-a.top,h=r?a.right:d.width-a.left,k=r?d.width-a.right:a.left;r?h<e&&(q=k>e?q+e:d.width>e?q-a.left:q-a.right+d.width):h<e&&(q=k>e?q-e:d.width>e?q-a.right+d.width:q-a.left);e=a.top;d.height- -a.top<f&&(u=e>f?u-f:d.height>f?u-a.bottom+d.height:u-a.top);CKEDITOR.env.ie&&(d=a=new CKEDITOR.dom.element(n.$.offsetParent),"html"==d.getName()&&(d=d.getDocument().getBody()),"rtl"==d.getComputedStyle("direction")&&(q=CKEDITOR.env.ie8Compat?q-2*n.getDocument().getDocumentElement().$.scrollLeft:q-(a.$.scrollWidth-a.$.clientWidth)));var a=n.getFirst(),l;(l=a.getCustomData("activePanel"))&&l.onHide&&l.onHide.call(this,1);a.setCustomData("activePanel",this);n.setStyles({top:u+"px",left:q+"px"});n.setOpacity(1); +0)+3);a.setStyle("height",d+"px");g._.currentBlock.element.setStyle("display","none").removeStyle("display")}else a.removeStyle("height");p&&(q-=n.$.offsetWidth);n.setStyle("left",q+"px");var d=g.element.getWindow(),a=n.$.getBoundingClientRect(),d=d.getViewPaneSize(),e=a.width||a.right-a.left,f=a.height||a.bottom-a.top,h=p?a.right:d.width-a.left,k=p?d.width-a.right:a.left;p?h<e&&(q=k>e?q+e:d.width>e?q-a.left:q-a.right+d.width):h<e&&(q=k>e?q-e:d.width>e?q-a.right+d.width:q-a.left);e=a.top;d.height- +a.top<f&&(A=e>f?A-f:d.height>f?A-a.bottom+d.height:A-a.top);CKEDITOR.env.ie&&(d=a=new CKEDITOR.dom.element(n.$.offsetParent),"html"==d.getName()&&(d=d.getDocument().getBody()),"rtl"==d.getComputedStyle("direction")&&(q=CKEDITOR.env.ie8Compat?q-2*n.getDocument().getDocumentElement().$.scrollLeft:q-(a.$.scrollWidth-a.$.clientWidth)));var a=n.getFirst(),l;(l=a.getCustomData("activePanel"))&&l.onHide&&l.onHide.call(this,1);a.setCustomData("activePanel",this);n.setStyles({top:A+"px",left:q+"px"});n.setOpacity(1); b&&b()},this);g.isLoaded?a():g.onLoad=a;CKEDITOR.tools.setTimeout(function(){var a=CKEDITOR.env.webkit&&CKEDITOR.document.getWindow().getScrollPosition().y;this.focus();c.element.focus();CKEDITOR.env.webkit&&(CKEDITOR.document.getBody().$.scrollTop=a);this.allowBlur(!0);CKEDITOR.env.ie?CKEDITOR.tools.setTimeout(function(){c.markFirstDisplayed?c.markFirstDisplayed():c._.markFirstDisplayed()},0):c.markFirstDisplayed?c.markFirstDisplayed():c._.markFirstDisplayed();this._.editor.fire("panelShow",this)}, 0,this)},CKEDITOR.env.air?200:0,this);this.visible=1;this.onShow&&this.onShow.call(this)},reposition:function(){var e=this._.showBlockParams;this.visible&&this._.showBlockParams&&(this.hide(),this.showBlock.apply(this,e))},focus:function(){if(CKEDITOR.env.webkit){var e=CKEDITOR.document.getActive();e&&!e.equals(this._.iframe)&&e.$.blur()}(this._.lastFocused||this._.iframe.getFrameDocument().getWindow()).focus()},blur:function(){var e=this._.iframe.getFrameDocument().getActive();e&&e.is("a")&&(this._.lastFocused= e)},hide:function(e){if(this.visible&&(!this.onHide||!0!==this.onHide.call(this))){this.hideChild();CKEDITOR.env.gecko&&this._.iframe.getFrameDocument().$.activeElement.blur();this.element.setStyle("display","none");this.visible=0;this.element.getFirst().removeCustomData("activePanel");if(e=e&&this._.returnFocus)CKEDITOR.env.webkit&&e.type&&e.getWindow().$.focus(),e.focus();delete this._.lastFocused;this._.showBlockParams=null;this._.editor.fire("panelHide",this)}},allowBlur:function(e){var f=this._.panel; @@ -748,33 +749,33 @@ b},_:{onShow:function(){var d=this.editor.getSelection(),e=d&&d.getStartElement( String(d));setTimeout(function(){e.show(a,2)},0)}else this._.panel.hideChild(1)}},proto:{add:function(d){d.order||(d.order=this.items.length);this.items.push(d)},removeAll:function(){this.items=[]},show:function(d,e,b,g){if(!this.parent&&(this._.onShow(),!this.items.length))return;e=e||("rtl"==this.editor.lang.dir?2:1);var c=this.items,a=this.editor,h=this._.panel,k=this._.element;if(!h){h=this._.panel=new CKEDITOR.ui.floatPanel(this.editor,CKEDITOR.document.getBody(),this._.panelDefinition,this._.level); h.onEscape=CKEDITOR.tools.bind(function(a){if(!1===this._.onEscape(a))return!1},this);h.onShow=function(){h._.panel.getHolderElement().getParent().addClass("cke").addClass("cke_reset_all")};h.onHide=CKEDITOR.tools.bind(function(){this._.onHide&&this._.onHide()},this);k=h.addBlock(this.id,this._.panelDefinition.block);k.autoSize=!0;var v=k.keys;v[40]="next";v[9]="next";v[38]="prev";v[CKEDITOR.SHIFT+9]="prev";v["rtl"==a.lang.dir?37:39]=CKEDITOR.env.ie?"mouseup":"click";v[32]=CKEDITOR.env.ie?"mouseup": "click";CKEDITOR.env.ie&&(v[13]="mouseup");k=this._.element=k.element;v=k.getDocument();v.getBody().setStyle("overflow","hidden");v.getElementsByTag("html").getItem(0).setStyle("overflow","hidden");this._.itemOverFn=CKEDITOR.tools.addFunction(function(b){clearTimeout(this._.showSubTimeout);this._.showSubTimeout=CKEDITOR.tools.setTimeout(this._.showSubMenu,a.config.menu_subMenuDelay||400,this,[b])},this);this._.itemOutFn=CKEDITOR.tools.addFunction(function(){clearTimeout(this._.showSubTimeout)},this); -this._.itemClickFn=CKEDITOR.tools.addFunction(function(a){var b=this.items[a];if(b.state==CKEDITOR.TRISTATE_DISABLED)this.hide(1);else if(b.getItems)this._.showSubMenu(a);else this._.onClick(b)},this)}f(c);for(var v=a.elementPath(),v=['\x3cdiv class\x3d"cke_menu'+(v&&v.direction()!=a.lang.dir?" cke_mixed_dir_content":"")+'" role\x3d"presentation"\x3e'],p=c.length,r=p&&c[0].group,q=0;q<p;q++){var u=c[q];r!=u.group&&(v.push('\x3cdiv class\x3d"cke_menuseparator" role\x3d"separator"\x3e\x3c/div\x3e'), -r=u.group);u.render(this,q,v)}v.push("\x3c/div\x3e");k.setHtml(v.join(""));CKEDITOR.ui.fire("ready",this);this.parent?this.parent._.panel.showAsChild(h,this.id,d,e,b,g):h.showBlock(this.id,d,e,b,g);a.fire("menuShow",[h])},addListener:function(d){this._.listeners.push(d)},hide:function(d){this._.onHide&&this._.onHide();this._.panel&&this._.panel.hide(d)},findItemByCommandName:function(d){var e=CKEDITOR.tools.array.filter(this.items,function(b){return d===b.command});return e.length?(e=e[0],{item:e, -element:this._.element.findOne("."+e.className)}):null}}});CKEDITOR.menuItem=CKEDITOR.tools.createClass({$:function(d,e,b){CKEDITOR.tools.extend(this,b,{order:0,className:"cke_menubutton__"+e});this.group=d._.menuGroups[this.group];this.editor=d;this.name=e},proto:{render:function(f,h,b){var g=f.id+String(h),c="undefined"==typeof this.state?CKEDITOR.TRISTATE_OFF:this.state,a="",n=this.editor,w,v,p=c==CKEDITOR.TRISTATE_ON?"on":c==CKEDITOR.TRISTATE_DISABLED?"disabled":"off";this.role in{menuitemcheckbox:1, -menuitemradio:1}&&(a=' aria-checked\x3d"'+(c==CKEDITOR.TRISTATE_ON?"true":"false")+'"');var r=this.getItems,q="\x26#"+("rtl"==this.editor.lang.dir?"9668":"9658")+";",u=this.name;this.icon&&!/\./.test(this.icon)&&(u=this.icon);this.command&&(w=n.getCommand(this.command),(w=n.getCommandKeystroke(w))&&(v=CKEDITOR.tools.keystrokeToString(n.lang.common.keyboard,w)));f={id:g,name:this.name,iconName:u,label:this.label,cls:this.className||"",state:p,hasPopup:r?"true":"false",disabled:c==CKEDITOR.TRISTATE_DISABLED, -title:this.label+(v?" ("+v.display+")":""),ariaShortcut:v?n.lang.common.keyboardShortcut+" "+v.aria:"",href:"javascript:void('"+(this.label||"").replace("'")+"')",hoverFn:f._.itemOverFn,moveOutFn:f._.itemOutFn,clickFn:f._.itemClickFn,index:h,iconStyle:CKEDITOR.skin.getIconStyle(u,"rtl"==this.editor.lang.dir,u==this.icon?null:this.icon,this.iconOffset),shortcutHtml:v?d.output({shortcut:v.display}):"",arrowHtml:r?k.output({label:q}):"",role:this.role?this.role:"menuitem",ariaChecked:a};e.output(f,b)}}})}(), +this._.itemClickFn=CKEDITOR.tools.addFunction(function(a){var b=this.items[a];if(b.state==CKEDITOR.TRISTATE_DISABLED)this.hide(1);else if(b.getItems)this._.showSubMenu(a);else this._.onClick(b)},this)}f(c);for(var v=a.elementPath(),v=['\x3cdiv class\x3d"cke_menu'+(v&&v.direction()!=a.lang.dir?" cke_mixed_dir_content":"")+'" role\x3d"presentation"\x3e'],t=c.length,p=t&&c[0].group,q=0;q<t;q++){var A=c[q];p!=A.group&&(v.push('\x3cdiv class\x3d"cke_menuseparator" role\x3d"separator"\x3e\x3c/div\x3e'), +p=A.group);A.render(this,q,v)}v.push("\x3c/div\x3e");k.setHtml(v.join(""));CKEDITOR.ui.fire("ready",this);this.parent?this.parent._.panel.showAsChild(h,this.id,d,e,b,g):h.showBlock(this.id,d,e,b,g);a.fire("menuShow",[h])},addListener:function(d){this._.listeners.push(d)},hide:function(d){this._.onHide&&this._.onHide();this._.panel&&this._.panel.hide(d)},findItemByCommandName:function(d){var e=CKEDITOR.tools.array.filter(this.items,function(b){return d===b.command});return e.length?(e=e[0],{item:e, +element:this._.element.findOne("."+e.className)}):null}}});CKEDITOR.menuItem=CKEDITOR.tools.createClass({$:function(d,e,b){CKEDITOR.tools.extend(this,b,{order:0,className:"cke_menubutton__"+e});this.group=d._.menuGroups[this.group];this.editor=d;this.name=e},proto:{render:function(f,h,b){var g=f.id+String(h),c="undefined"==typeof this.state?CKEDITOR.TRISTATE_OFF:this.state,a="",n=this.editor,w,v,t=c==CKEDITOR.TRISTATE_ON?"on":c==CKEDITOR.TRISTATE_DISABLED?"disabled":"off";this.role in{menuitemcheckbox:1, +menuitemradio:1}&&(a=' aria-checked\x3d"'+(c==CKEDITOR.TRISTATE_ON?"true":"false")+'"');var p=this.getItems,q="\x26#"+("rtl"==this.editor.lang.dir?"9668":"9658")+";",A=this.name;this.icon&&!/\./.test(this.icon)&&(A=this.icon);this.command&&(w=n.getCommand(this.command),(w=n.getCommandKeystroke(w))&&(v=CKEDITOR.tools.keystrokeToString(n.lang.common.keyboard,w)));f={id:g,name:this.name,iconName:A,label:this.label,cls:this.className||"",state:t,hasPopup:p?"true":"false",disabled:c==CKEDITOR.TRISTATE_DISABLED, +title:this.label+(v?" ("+v.display+")":""),ariaShortcut:v?n.lang.common.keyboardShortcut+" "+v.aria:"",href:"javascript:void('"+(this.label||"").replace("'")+"')",hoverFn:f._.itemOverFn,moveOutFn:f._.itemOutFn,clickFn:f._.itemClickFn,index:h,iconStyle:CKEDITOR.skin.getIconStyle(A,"rtl"==this.editor.lang.dir,A==this.icon?null:this.icon,this.iconOffset),shortcutHtml:v?d.output({shortcut:v.display}):"",arrowHtml:p?k.output({label:q}):"",role:this.role?this.role:"menuitem",ariaChecked:a};e.output(f,b)}}})}(), CKEDITOR.config.menu_groups="clipboard,form,tablecell,tablecellproperties,tablerow,tablecolumn,table,anchor,link,image,flash,checkbox,radio,textfield,hiddenfield,imagebutton,button,select,textarea,div",CKEDITOR.plugins.add("contextmenu",{requires:"menu",onLoad:function(){CKEDITOR.plugins.contextMenu=CKEDITOR.tools.createClass({base:CKEDITOR.menu,$:function(f){this.base.call(this,f,{panel:{className:"cke_menu_panel",attributes:{"aria-label":f.lang.contextmenu.options}}})},proto:{addTarget:function(f, h){f.on("contextmenu",function(d){d=d.data;var f=CKEDITOR.env.webkit?e:CKEDITOR.env.mac?d.$.metaKey:d.$.ctrlKey;if(!h||!f){d.preventDefault();if(CKEDITOR.env.mac&&CKEDITOR.env.webkit){var f=this.editor,k=(new CKEDITOR.dom.elementPath(d.getTarget(),f.editable())).contains(function(a){return a.hasAttribute("contenteditable")},!0);k&&"false"==k.getAttribute("contenteditable")&&f.getSelection().fake(k)}var k=d.getTarget().getDocument(),b=d.getTarget().getDocument().getDocumentElement(),f=!k.equals(CKEDITOR.document), k=k.getWindow().getScrollPosition(),g=f?d.$.clientX:d.$.pageX||k.x+d.$.clientX,c=f?d.$.clientY:d.$.pageY||k.y+d.$.clientY;CKEDITOR.tools.setTimeout(function(){this.open(b,null,g,c)},CKEDITOR.env.ie?200:0,this)}},this);if(CKEDITOR.env.webkit){var e,k=function(){e=0};f.on("keydown",function(d){e=CKEDITOR.env.mac?d.data.$.metaKey:d.data.$.ctrlKey});f.on("keyup",k);f.on("contextmenu",k)}},open:function(f,h,e,k){!1!==this.editor.config.enableContextMenu&&(this.editor.focus(),f=f||CKEDITOR.document.getDocumentElement(), this.editor.selectionChange(1),this.show(f,h,e,k))}}})},beforeInit:function(f){var h=f.contextMenu=new CKEDITOR.plugins.contextMenu(f);f.on("contentDom",function(){h.addTarget(f.editable(),!1!==f.config.browserContextMenuOnCtrl)});f.addCommand("contextMenu",{exec:function(){f.contextMenu.open(f.document.getBody())}});f.setKeystroke(CKEDITOR.SHIFT+121,"contextMenu");f.setKeystroke(CKEDITOR.CTRL+CKEDITOR.SHIFT+121,"contextMenu")}}),function(){function f(d,e){function f(b){b=a.list[b];var c;b.equals(d.editable())|| "true"==b.getAttribute("contenteditable")?(c=d.createRange(),c.selectNodeContents(b),c=c.select()):(c=d.getSelection(),c.selectElement(b));CKEDITOR.env.ie&&d.fire("selectionChange",{selection:c,path:new CKEDITOR.dom.elementPath(b)});d.focus()}function b(){c&&c.setHtml('\x3cspan class\x3d"cke_path_empty"\x3e\x26nbsp;\x3c/span\x3e');delete a.list}var g=d.ui.spaceId("path"),c,a=d._.elementsPath,n=a.idBase;e.html+='\x3cspan id\x3d"'+g+'_label" class\x3d"cke_voice_label"\x3e'+d.lang.elementspath.eleLabel+ -'\x3c/span\x3e\x3cspan id\x3d"'+g+'" class\x3d"cke_path" role\x3d"group" aria-labelledby\x3d"'+g+'_label"\x3e\x3cspan class\x3d"cke_path_empty"\x3e\x26nbsp;\x3c/span\x3e\x3c/span\x3e';d.on("uiReady",function(){var a=d.ui.space("path");a&&d.focusManager.add(a,1)});a.onClick=f;var w=CKEDITOR.tools.addFunction(f),v=CKEDITOR.tools.addFunction(function(b,c){var g=a.idBase,e;c=new CKEDITOR.dom.event(c);e="rtl"==d.lang.dir;switch(c.getKeystroke()){case e?39:37:case 9:return(e=CKEDITOR.document.getById(g+ -(b+1)))||(e=CKEDITOR.document.getById(g+"0")),e.focus(),!1;case e?37:39:case CKEDITOR.SHIFT+9:return(e=CKEDITOR.document.getById(g+(b-1)))||(e=CKEDITOR.document.getById(g+(a.list.length-1))),e.focus(),!1;case 27:return d.focus(),!1;case 13:case 32:return f(b),!1}return!0});d.on("selectionChange",function(b){for(var e=[],f=a.list=[],h=[],l=a.filters,m=!0,D=b.data.path.elements,t=D.length;t--;){var B=D[t],y=0;b=B.data("cke-display-name")?B.data("cke-display-name"):B.data("cke-real-element-type")?B.data("cke-real-element-type"): -B.getName();(m=B.hasAttribute("contenteditable")?"true"==B.getAttribute("contenteditable"):m)||B.hasAttribute("contenteditable")||(y=1);for(var z=0;z<l.length;z++){var I=l[z](B,b);if(!1===I){y=1;break}b=I||b}y||(f.unshift(B),h.unshift(b))}f=f.length;for(l=0;l<f;l++)b=h[l],m=d.lang.elementspath.eleTitle.replace(/%1/,b),b=k.output({id:n+l,label:m,text:b,jsTitle:"javascript:void('"+b+"')",index:l,keyDownFn:v,clickFn:w}),e.unshift(b);c||(c=CKEDITOR.document.getById(g));h=c;h.setHtml(e.join("")+'\x3cspan class\x3d"cke_path_empty"\x3e\x26nbsp;\x3c/span\x3e'); +'\x3c/span\x3e\x3cspan id\x3d"'+g+'" class\x3d"cke_path" role\x3d"group" aria-labelledby\x3d"'+g+'_label"\x3e\x3cspan class\x3d"cke_path_empty"\x3e\x26nbsp;\x3c/span\x3e\x3c/span\x3e';d.on("uiReady",function(){var a=d.ui.space("path");a&&d.focusManager.add(a,1)});a.onClick=f;var w=CKEDITOR.tools.addFunction(f),v=CKEDITOR.tools.addFunction(function(b,c){var e=a.idBase,g;c=new CKEDITOR.dom.event(c);g="rtl"==d.lang.dir;switch(c.getKeystroke()){case g?39:37:case 9:return(g=CKEDITOR.document.getById(e+ +(b+1)))||(g=CKEDITOR.document.getById(e+"0")),g.focus(),!1;case g?37:39:case CKEDITOR.SHIFT+9:return(g=CKEDITOR.document.getById(e+(b-1)))||(g=CKEDITOR.document.getById(e+(a.list.length-1))),g.focus(),!1;case 27:return d.focus(),!1;case 13:case 32:return f(b),!1}return!0});d.on("selectionChange",function(b){for(var e=[],f=a.list=[],h=[],l=a.filters,m=!0,B=b.data.path.elements,u=B.length;u--;){var y=B[u],x=0;b=y.data("cke-display-name")?y.data("cke-display-name"):y.data("cke-real-element-type")?y.data("cke-real-element-type"): +y.getName();(m=y.hasAttribute("contenteditable")?"true"==y.getAttribute("contenteditable"):m)||y.hasAttribute("contenteditable")||(x=1);for(var z=0;z<l.length;z++){var I=l[z](y,b);if(!1===I){x=1;break}b=I||b}x||(f.unshift(y),h.unshift(b))}f=f.length;for(l=0;l<f;l++)b=h[l],m=d.lang.elementspath.eleTitle.replace(/%1/,b),b=k.output({id:n+l,label:m,text:b,jsTitle:"javascript:void('"+b+"')",index:l,keyDownFn:v,clickFn:w}),e.unshift(b);c||(c=CKEDITOR.document.getById(g));h=c;h.setHtml(e.join("")+'\x3cspan class\x3d"cke_path_empty"\x3e\x26nbsp;\x3c/span\x3e'); d.fire("elementsPathUpdate",{space:h})});d.on("readOnly",b);d.on("contentDomUnload",b);d.addCommand("elementsPathFocus",h.toolbarFocus);d.setKeystroke(CKEDITOR.ALT+122,"elementsPathFocus")}var h={toolbarFocus:{editorFocus:!1,readOnly:1,exec:function(d){(d=CKEDITOR.document.getById(d._.elementsPath.idBase+"0"))&&d.focus(CKEDITOR.env.ie||CKEDITOR.env.air)}}},e="";CKEDITOR.env.gecko&&CKEDITOR.env.mac&&(e+=' onkeypress\x3d"return false;"');CKEDITOR.env.gecko&&(e+=' onblur\x3d"this.style.cssText \x3d this.style.cssText;"'); var k=CKEDITOR.addTemplate("pathItem",'\x3ca id\x3d"{id}" href\x3d"{jsTitle}" tabindex\x3d"-1" class\x3d"cke_path_item" title\x3d"{label}"'+e+' hidefocus\x3d"true" onkeydown\x3d"return CKEDITOR.tools.callFunction({keyDownFn},{index}, event );" onclick\x3d"CKEDITOR.tools.callFunction({clickFn},{index}); return false;" role\x3d"button" aria-label\x3d"{label}"\x3e{text}\x3c/a\x3e');CKEDITOR.plugins.add("elementspath",{init:function(d){d._.elementsPath={idBase:"cke_elementspath_"+CKEDITOR.tools.getNextNumber()+ -"_",filters:[]};d.on("uiSpace",function(e){"bottom"==e.data.space&&f(d,e.data)})}})}(),function(){function f(c,a,g){g=c.config.forceEnterMode||g;if("wysiwyg"==c.mode){a||(a=c.activeEnterMode);var d=c.elementPath();d&&!d.isContextFor("p")&&(a=CKEDITOR.ENTER_BR,g=1);c.fire("saveSnapshot");a==CKEDITOR.ENTER_BR?m(c,a,null,g):b(c,a,null,g);c.fire("saveSnapshot")}}function h(b){b=b.getSelection().getRanges(!0);for(var a=b.length-1;0<a;a--)b[a].deleteContents();return b[0]}function e(b){var a=b.startContainer.getAscendant(function(a){return a.type== +"_",filters:[]};d.on("uiSpace",function(e){"bottom"==e.data.space&&f(d,e.data)})}})}(),function(){function f(c,a,d){d=c.config.forceEnterMode||d;if("wysiwyg"==c.mode){a||(a=c.activeEnterMode);var e=c.elementPath();e&&!e.isContextFor("p")&&(a=CKEDITOR.ENTER_BR,d=1);c.fire("saveSnapshot");a==CKEDITOR.ENTER_BR?m(c,a,null,d):b(c,a,null,d);c.fire("saveSnapshot")}}function h(b){b=b.getSelection().getRanges(!0);for(var a=b.length-1;0<a;a--)b[a].deleteContents();return b[0]}function e(b){var a=b.startContainer.getAscendant(function(a){return a.type== CKEDITOR.NODE_ELEMENT&&"true"==a.getAttribute("contenteditable")},!0);if(b.root.equals(a))return b;a=new CKEDITOR.dom.range(a);a.moveToRange(b);return a}CKEDITOR.plugins.add("enterkey",{init:function(b){b.addCommand("enter",{modes:{wysiwyg:1},editorFocus:!1,exec:function(a){f(a)}});b.addCommand("shiftEnter",{modes:{wysiwyg:1},editorFocus:!1,exec:function(a){f(a,a.activeShiftEnterMode,1)}});b.setKeystroke([[13,"enter"],[CKEDITOR.SHIFT+13,"shiftEnter"]])}});var k=CKEDITOR.dom.walker.whitespaces(),d= -CKEDITOR.dom.walker.bookmark();CKEDITOR.plugins.enterkey={enterBlock:function(b,a,f,l){if(f=f||h(b)){f=e(f);var v=f.document,p=f.checkStartOfBlock(),r=f.checkEndOfBlock(),q=b.elementPath(f.startContainer),u=q.block,x=a==CKEDITOR.ENTER_DIV?"div":"p",A;if(p&&r){if(u&&(u.is("li")||u.getParent().is("li"))){u.is("li")||(u=u.getParent());f=u.getParent();A=f.getParent();l=!u.hasPrevious();var D=!u.hasNext(),x=b.getSelection(),t=x.createBookmarks(),p=u.getDirection(1),r=u.getAttribute("class"),B=u.getAttribute("style"), -y=A.getDirection(1)!=p;b=b.enterMode!=CKEDITOR.ENTER_BR||y||B||r;if(A.is("li"))l||D?(l&&D&&f.remove(),u[D?"insertAfter":"insertBefore"](A)):u.breakParent(A);else{if(b)if(q.block.is("li")?(A=v.createElement(a==CKEDITOR.ENTER_P?"p":"div"),y&&A.setAttribute("dir",p),B&&A.setAttribute("style",B),r&&A.setAttribute("class",r),u.moveChildren(A)):A=q.block,l||D)A[l?"insertBefore":"insertAfter"](f);else u.breakParent(f),A.insertAfter(f);else if(u.appendBogus(!0),l||D)for(;v=u[l?"getFirst":"getLast"]();)v[l? -"insertBefore":"insertAfter"](f);else for(u.breakParent(f);v=u.getLast();)v.insertAfter(f);u.remove()}x.selectBookmarks(t);return}if(u&&u.getParent().is("blockquote")){u.breakParent(u.getParent());u.getPrevious().getFirst(CKEDITOR.dom.walker.invisible(1))||u.getPrevious().remove();u.getNext().getFirst(CKEDITOR.dom.walker.invisible(1))||u.getNext().remove();f.moveToElementEditStart(u);f.select();return}}else if(u&&u.is("pre")&&!r){m(b,a,f,l);return}if(p=f.splitBlock(x)){a=p.previousBlock;u=p.nextBlock; -q=p.wasStartOfBlock;b=p.wasEndOfBlock;u?(t=u.getParent(),t.is("li")&&(u.breakParent(t),u.move(u.getNext(),1))):a&&(t=a.getParent())&&t.is("li")&&(a.breakParent(t),t=a.getNext(),f.moveToElementEditStart(t),a.move(a.getPrevious()));if(q||b){if(a){if(a.is("li")||!g.test(a.getName())&&!a.is("pre"))A=a.clone()}else u&&(A=u.clone());A?l&&!A.is("li")&&A.renameNode(x):t&&t.is("li")?A=t:(A=v.createElement(x),a&&(D=a.getDirection())&&A.setAttribute("dir",D));if(v=p.elementPath)for(l=0,x=v.elements.length;l< -x;l++){t=v.elements[l];if(t.equals(v.block)||t.equals(v.blockLimit))break;CKEDITOR.dtd.$removeEmpty[t.getName()]&&(t=t.clone(),A.moveChildren(t),A.append(t))}A.appendBogus();A.getParent()||f.insertNode(A);A.is("li")&&A.removeAttribute("value");!CKEDITOR.env.ie||!q||b&&a.getChildCount()||(f.moveToElementEditStart(b?a:A),f.select());f.moveToElementEditStart(q&&!b?u:A)}else u.is("li")&&(A=f.clone(),A.selectNodeContents(u),A=new CKEDITOR.dom.walker(A),A.evaluator=function(a){return!(d(a)||k(a)||a.type== -CKEDITOR.NODE_ELEMENT&&a.getName()in CKEDITOR.dtd.$inline&&!(a.getName()in CKEDITOR.dtd.$empty))},(t=A.next())&&t.type==CKEDITOR.NODE_ELEMENT&&t.is("ul","ol")&&(CKEDITOR.env.needsBrFiller?v.createElement("br"):v.createText(" ")).insertBefore(t)),u&&f.moveToElementEditStart(u);f.select();f.scrollIntoView()}}},enterBr:function(c,a,d,e){if(d=d||h(c)){var f=d.document,k=d.checkEndOfBlock(),l=new CKEDITOR.dom.elementPath(c.getSelection().getStartElement()),m=l.block,u=m&&l.block.getName();e||"li"!=u?(!e&& -k&&g.test(u)?(k=m.getDirection())?(f=f.createElement("div"),f.setAttribute("dir",k),f.insertAfter(m),d.setStart(f,0)):(f.createElement("br").insertAfter(m),CKEDITOR.env.gecko&&f.createText("").insertAfter(m),d.setStartAt(m.getNext(),CKEDITOR.env.ie?CKEDITOR.POSITION_BEFORE_START:CKEDITOR.POSITION_AFTER_START)):(c="pre"==u&&CKEDITOR.env.ie&&8>CKEDITOR.env.version?f.createText("\r"):f.createElement("br"),d.deleteContents(),d.insertNode(c),CKEDITOR.env.needsBrFiller?(f.createText("").insertAfter(c), -k&&(m||l.blockLimit).appendBogus(),c.getNext().$.nodeValue="",d.setStartAt(c.getNext(),CKEDITOR.POSITION_AFTER_START)):d.setStartAt(c,CKEDITOR.POSITION_AFTER_END)),d.collapse(!0),d.select(),d.scrollIntoView()):b(c,a,d,e)}}};var l=CKEDITOR.plugins.enterkey,m=l.enterBr,b=l.enterBlock,g=/^h[1-6]$/}(),function(){function f(f,e){var k={},d=[],l={nbsp:" ",shy:"",gt:"\x3e",lt:"\x3c",amp:"\x26",apos:"'",quot:'"'};f=f.replace(/\b(nbsp|shy|gt|lt|amp|apos|quot)(?:,|$)/g,function(b,a){var g=e?"\x26"+a+";":l[a]; -k[g]=e?l[a]:"\x26"+a+";";d.push(g);return""});if(!e&&f){f=f.split(",");var m=document.createElement("div"),b;m.innerHTML="\x26"+f.join(";\x26")+";";b=m.innerHTML;m=null;for(m=0;m<b.length;m++){var g=b.charAt(m);k[g]="\x26"+f[m]+";";d.push(g)}}k.regex=d.join(e?"|":"");return k}CKEDITOR.plugins.add("entities",{afterInit:function(h){function e(a){return g[a]}function k(a){return"force"!=d.entities_processNumerical&&m[a]?m[a]:"\x26#"+a.charCodeAt(0)+";"}var d=h.config;if(h=(h=h.dataProcessor)&&h.htmlFilter){var l= -[];!1!==d.basicEntities&&l.push("nbsp,gt,lt,amp");d.entities&&(l.length&&l.push("quot,iexcl,cent,pound,curren,yen,brvbar,sect,uml,copy,ordf,laquo,not,shy,reg,macr,deg,plusmn,sup2,sup3,acute,micro,para,middot,cedil,sup1,ordm,raquo,frac14,frac12,frac34,iquest,times,divide,fnof,bull,hellip,prime,Prime,oline,frasl,weierp,image,real,trade,alefsym,larr,uarr,rarr,darr,harr,crarr,lArr,uArr,rArr,dArr,hArr,forall,part,exist,empty,nabla,isin,notin,ni,prod,sum,minus,lowast,radic,prop,infin,ang,and,or,cap,cup,int,there4,sim,cong,asymp,ne,equiv,le,ge,sub,sup,nsub,sube,supe,oplus,otimes,perp,sdot,lceil,rceil,lfloor,rfloor,lang,rang,loz,spades,clubs,hearts,diams,circ,tilde,ensp,emsp,thinsp,zwnj,zwj,lrm,rlm,ndash,mdash,lsquo,rsquo,sbquo,ldquo,rdquo,bdquo,dagger,Dagger,permil,lsaquo,rsaquo,euro"), +CKEDITOR.dom.walker.bookmark(),l,m,b,g;CKEDITOR.plugins.enterkey={enterBlock:function(b,a,f,l){function v(a){var b;if(a===CKEDITOR.ENTER_BR||-1===CKEDITOR.tools.indexOf(["td","th"],A.lastElement.getName())||1!==A.lastElement.getChildCount())return!1;a=A.lastElement.getChild(0).clone(!0);(b=a.getBogus())&&b.remove();return a.getText().length?!1:!0}if(f=f||h(b)){f=e(f);var t=f.document,p=f.checkStartOfBlock(),q=f.checkEndOfBlock(),A=b.elementPath(f.startContainer),r=A.block,C=a==CKEDITOR.ENTER_DIV? +"div":"p",B;if(p&&q){if(r&&(r.is("li")||r.getParent().is("li"))){r.is("li")||(r=r.getParent());f=r.getParent();B=f.getParent();l=!r.hasPrevious();var q=!r.hasNext(),C=b.getSelection(),p=C.createBookmarks(),u=r.getDirection(1),y=r.getAttribute("class"),x=r.getAttribute("style"),z=B.getDirection(1)!=u;b=b.enterMode!=CKEDITOR.ENTER_BR||z||x||y;if(B.is("li"))l||q?(l&&q&&f.remove(),r[q?"insertAfter":"insertBefore"](B)):r.breakParent(B);else{if(b)if(A.block.is("li")?(B=t.createElement(a==CKEDITOR.ENTER_P? +"p":"div"),z&&B.setAttribute("dir",u),x&&B.setAttribute("style",x),y&&B.setAttribute("class",y),r.moveChildren(B)):B=A.block,l||q)B[l?"insertBefore":"insertAfter"](f);else r.breakParent(f),B.insertAfter(f);else if(r.appendBogus(!0),l||q)for(;t=r[l?"getFirst":"getLast"]();)t[l?"insertBefore":"insertAfter"](f);else for(r.breakParent(f);t=r.getLast();)t.insertAfter(f);r.remove()}C.selectBookmarks(p);return}if(r&&r.getParent().is("blockquote")){r.breakParent(r.getParent());r.getPrevious().getFirst(CKEDITOR.dom.walker.invisible(1))|| +r.getPrevious().remove();r.getNext().getFirst(CKEDITOR.dom.walker.invisible(1))||r.getNext().remove();f.moveToElementEditStart(r);f.select();return}}else if(r&&r.is("pre")&&!q){m(b,a,f,l);return}if(x=f.splitBlock(C)){b=x.previousBlock;r=x.nextBlock;p=x.wasStartOfBlock;q=x.wasEndOfBlock;r?(u=r.getParent(),u.is("li")&&(r.breakParent(u),r.move(r.getNext(),1))):b&&(u=b.getParent())&&u.is("li")&&(b.breakParent(u),u=b.getNext(),f.moveToElementEditStart(u),b.move(b.getPrevious()));if(p||q)if(v(a))f.moveToElementEditStart(f.getTouchedStartNode()); +else{if(b){if(b.is("li")||!g.test(b.getName())&&!b.is("pre"))B=b.clone()}else r&&(B=r.clone());B?l&&!B.is("li")&&B.renameNode(C):u&&u.is("li")?B=u:(B=t.createElement(C),b&&(y=b.getDirection())&&B.setAttribute("dir",y));if(t=x.elementPath)for(a=0,l=t.elements.length;a<l;a++){C=t.elements[a];if(C.equals(t.block)||C.equals(t.blockLimit))break;CKEDITOR.dtd.$removeEmpty[C.getName()]&&(C=C.clone(),B.moveChildren(C),B.append(C))}B.appendBogus();B.getParent()||f.insertNode(B);B.is("li")&&B.removeAttribute("value"); +!CKEDITOR.env.ie||!p||q&&b.getChildCount()||(f.moveToElementEditStart(q?b:B),f.select());f.moveToElementEditStart(p&&!q?r:B)}else r.is("li")&&(B=f.clone(),B.selectNodeContents(r),B=new CKEDITOR.dom.walker(B),B.evaluator=function(a){return!(d(a)||k(a)||a.type==CKEDITOR.NODE_ELEMENT&&a.getName()in CKEDITOR.dtd.$inline&&!(a.getName()in CKEDITOR.dtd.$empty))},(u=B.next())&&u.type==CKEDITOR.NODE_ELEMENT&&u.is("ul","ol")&&(CKEDITOR.env.needsBrFiller?t.createElement("br"):t.createText(" ")).insertBefore(u)), +r&&f.moveToElementEditStart(r);f.select();f.scrollIntoView()}}},enterBr:function(c,a,d,e){if(d=d||h(c)){var f=d.document,k=d.checkEndOfBlock(),l=new CKEDITOR.dom.elementPath(c.getSelection().getStartElement()),m=l.block,A=m&&l.block.getName();e||"li"!=A?(!e&&k&&g.test(A)?(k=m.getDirection())?(f=f.createElement("div"),f.setAttribute("dir",k),f.insertAfter(m),d.setStart(f,0)):(f.createElement("br").insertAfter(m),CKEDITOR.env.gecko&&f.createText("").insertAfter(m),d.setStartAt(m.getNext(),CKEDITOR.env.ie? +CKEDITOR.POSITION_BEFORE_START:CKEDITOR.POSITION_AFTER_START)):(c="pre"==A&&CKEDITOR.env.ie&&8>CKEDITOR.env.version?f.createText("\r"):f.createElement("br"),d.deleteContents(),d.insertNode(c),CKEDITOR.env.needsBrFiller?(f.createText("").insertAfter(c),k&&(m||l.blockLimit).appendBogus(),c.getNext().$.nodeValue="",d.setStartAt(c.getNext(),CKEDITOR.POSITION_AFTER_START)):d.setStartAt(c,CKEDITOR.POSITION_AFTER_END)),d.collapse(!0),d.select(),d.scrollIntoView()):b(c,a,d,e)}}};l=CKEDITOR.plugins.enterkey; +m=l.enterBr;b=l.enterBlock;g=/^h[1-6]$/}(),function(){function f(f,e){var k={},d=[],l={nbsp:" ",shy:"",gt:"\x3e",lt:"\x3c",amp:"\x26",apos:"'",quot:'"'};f=f.replace(/\b(nbsp|shy|gt|lt|amp|apos|quot)(?:,|$)/g,function(b,a){var g=e?"\x26"+a+";":l[a];k[g]=e?l[a]:"\x26"+a+";";d.push(g);return""});if(!e&&f){f=f.split(",");var m=document.createElement("div"),b;m.innerHTML="\x26"+f.join(";\x26")+";";b=m.innerHTML;m=null;for(m=0;m<b.length;m++){var g=b.charAt(m);k[g]="\x26"+f[m]+";";d.push(g)}}k.regex=d.join(e? +"|":"");return k}CKEDITOR.plugins.add("entities",{afterInit:function(h){function e(a){return g[a]}function k(a){return"force"!=d.entities_processNumerical&&m[a]?m[a]:"\x26#"+a.charCodeAt(0)+";"}var d=h.config;if(h=(h=h.dataProcessor)&&h.htmlFilter){var l=[];!1!==d.basicEntities&&l.push("nbsp,gt,lt,amp");d.entities&&(l.length&&l.push("quot,iexcl,cent,pound,curren,yen,brvbar,sect,uml,copy,ordf,laquo,not,shy,reg,macr,deg,plusmn,sup2,sup3,acute,micro,para,middot,cedil,sup1,ordm,raquo,frac14,frac12,frac34,iquest,times,divide,fnof,bull,hellip,prime,Prime,oline,frasl,weierp,image,real,trade,alefsym,larr,uarr,rarr,darr,harr,crarr,lArr,uArr,rArr,dArr,hArr,forall,part,exist,empty,nabla,isin,notin,ni,prod,sum,minus,lowast,radic,prop,infin,ang,and,or,cap,cup,int,there4,sim,cong,asymp,ne,equiv,le,ge,sub,sup,nsub,sube,supe,oplus,otimes,perp,sdot,lceil,rceil,lfloor,rfloor,lang,rang,loz,spades,clubs,hearts,diams,circ,tilde,ensp,emsp,thinsp,zwnj,zwj,lrm,rlm,ndash,mdash,lsquo,rsquo,sbquo,ldquo,rdquo,bdquo,dagger,Dagger,permil,lsaquo,rsaquo,euro"), d.entities_latin&&l.push("Agrave,Aacute,Acirc,Atilde,Auml,Aring,AElig,Ccedil,Egrave,Eacute,Ecirc,Euml,Igrave,Iacute,Icirc,Iuml,ETH,Ntilde,Ograve,Oacute,Ocirc,Otilde,Ouml,Oslash,Ugrave,Uacute,Ucirc,Uuml,Yacute,THORN,szlig,agrave,aacute,acirc,atilde,auml,aring,aelig,ccedil,egrave,eacute,ecirc,euml,igrave,iacute,icirc,iuml,eth,ntilde,ograve,oacute,ocirc,otilde,ouml,oslash,ugrave,uacute,ucirc,uuml,yacute,thorn,yuml,OElig,oelig,Scaron,scaron,Yuml"),d.entities_greek&&l.push("Alpha,Beta,Gamma,Delta,Epsilon,Zeta,Eta,Theta,Iota,Kappa,Lambda,Mu,Nu,Xi,Omicron,Pi,Rho,Sigma,Tau,Upsilon,Phi,Chi,Psi,Omega,alpha,beta,gamma,delta,epsilon,zeta,eta,theta,iota,kappa,lambda,mu,nu,xi,omicron,pi,rho,sigmaf,sigma,tau,upsilon,phi,chi,psi,omega,thetasym,upsih,piv"), d.entities_additional&&l.push(d.entities_additional));var m=f(l.join(",")),b=m.regex?"["+m.regex+"]":"a^";delete m.regex;d.entities&&d.entities_processNumerical&&(b="[^ -~]|"+b);var b=new RegExp(b,"g"),g=f("nbsp,gt,lt,amp,shy",!0),c=new RegExp(g.regex,"g");h.addRules({text:function(a){return a.replace(c,e).replace(b,k)}},{applyToAll:!0,excludeNestedEditable:!0})}}})}(),CKEDITOR.config.basicEntities=!0,CKEDITOR.config.entities=!0,CKEDITOR.config.entities_latin=!0,CKEDITOR.config.entities_greek=!0, CKEDITOR.config.entities_additional="#39",CKEDITOR.plugins.add("popup"),CKEDITOR.tools.extend(CKEDITOR.editor.prototype,{popup:function(f,h,e,k){h=h||"80%";e=e||"70%";"string"==typeof h&&1<h.length&&"%"==h.substr(h.length-1,1)&&(h=parseInt(window.screen.width*parseInt(h,10)/100,10));"string"==typeof e&&1<e.length&&"%"==e.substr(e.length-1,1)&&(e=parseInt(window.screen.height*parseInt(e,10)/100,10));640>h&&(h=640);420>e&&(e=420);var d=parseInt((window.screen.height-e)/2,10),l=parseInt((window.screen.width- @@ -786,19 +787,19 @@ if(c.uploaded)for(var a in c)g[a]=c[a];else d.cancel()}catch(f){g.message=e.lang e){var f=this;this.once("loaded",function(b){b.cancel();f.once("update",function(b){b.cancel()},null,null,0);f.upload(d,e)},null,null,0);this.load()},load:function(){var d=this,e=this.reader=new FileReader;d.changeStatus("loading");this.abort=function(){d.reader.abort()};e.onabort=function(){d.changeStatus("abort")};e.onerror=function(){d.message=d.lang.filetools.loadError;d.changeStatus("error")};e.onprogress=function(e){d.loaded=e.loaded;d.update()};e.onload=function(){d.loaded=d.total;d.data=e.result; d.changeStatus("loaded")};e.readAsDataURL(this.file)},upload:function(d,e){var f=e||{};d?(this.uploadUrl=d,this.xhr=new XMLHttpRequest,this.attachRequestListeners(),this.editor.fire("fileUploadRequest",{fileLoader:this,requestData:f})&&this.changeStatus("uploading")):(this.message=this.lang.filetools.noUrlError,this.changeStatus("error"))},attachRequestListeners:function(){function d(){"error"!=f.status&&(f.message=f.lang.filetools.networkError,f.changeStatus("error"))}function e(){"abort"!=f.status&& f.changeStatus("abort")}var f=this,b=this.xhr;f.abort=function(){b.abort();e()};b.onerror=d;b.onabort=e;b.upload?(b.upload.onprogress=function(b){b.lengthComputable&&(f.uploadTotal||(f.uploadTotal=b.total),f.uploaded=b.loaded,f.update())},b.upload.onerror=d,b.upload.onabort=e):(f.uploadTotal=f.total,f.update());b.onload=function(){f.update();if("abort"!=f.status)if(f.uploaded=f.uploadTotal,200>b.status||299<b.status)f.message=f.lang.filetools["httpError"+b.status],f.message||(f.message=f.lang.filetools.httpError.replace("%1", -b.status)),f.changeStatus("error");else{for(var g={fileLoader:f},c=["message","fileName","url"],a=f.editor.fire("fileUploadResponse",g),d=0;d<c.length;d++){var e=c[d];"string"===typeof g[e]&&(f[e]=g[e])}f.responseData=g;delete f.responseData.fileLoader;!1===a?f.changeStatus("error"):f.changeStatus("uploaded")}}},changeStatus:function(d){this.status=d;if("error"==d||"abort"==d||"loaded"==d||"uploaded"==d)this.abort=function(){};this.fire(d);this.update()},update:function(){this.fire("update")},isFinished:function(){return!!this.status.match(/^(?:loaded|uploaded|error|abort)$/)}}; +b.status)),f.changeStatus("error");else{for(var d={fileLoader:f},c=["message","fileName","url"],a=f.editor.fire("fileUploadResponse",d),e=0;e<c.length;e++){var h=c[e];"string"===typeof d[h]&&(f[h]=d[h])}f.responseData=d;delete f.responseData.fileLoader;!1===a?f.changeStatus("error"):f.changeStatus("uploaded")}}},changeStatus:function(d){this.status=d;if("error"==d||"abort"==d||"loaded"==d||"uploaded"==d)this.abort=function(){};this.fire(d);this.update()},update:function(){this.fire("update")},isFinished:function(){return!!this.status.match(/^(?:loaded|uploaded|error|abort)$/)}}; CKEDITOR.event.implementOn(f.prototype);CKEDITOR.event.implementOn(h.prototype);var k=/^data:(\S*?);base64,/;CKEDITOR.fileTools||(CKEDITOR.fileTools={});CKEDITOR.tools.extend(CKEDITOR.fileTools,{uploadRepository:f,fileLoader:h,getUploadUrl:function(d,e){var f=CKEDITOR.tools.capitalize;return e&&d[e+"UploadUrl"]?d[e+"UploadUrl"]:d.uploadUrl?d.uploadUrl:e&&d["filebrowser"+f(e,1)+"UploadUrl"]?d["filebrowser"+f(e,1)+"UploadUrl"]+"\x26responseType\x3djson":d.filebrowserUploadUrl?d.filebrowserUploadUrl+ -"\x26responseType\x3djson":null},isTypeSupported:function(d,e){return!!d.type.match(e)},isFileUploadSupported:"function"===typeof FileReader&&"function"===typeof(new FileReader).readAsDataURL&&"function"===typeof FormData&&"function"===typeof(new FormData).append&&"function"===typeof XMLHttpRequest&&"function"===typeof Blob})}(),function(){function f(a,b){var c=[];if(b)for(var g in b)c.push(g+"\x3d"+encodeURIComponent(b[g]));else return a;return a+(-1!=a.indexOf("?")?"\x26":"?")+c.join("\x26")}function h(a){return!a.match(/command=QuickUpload/)|| -a.match(/(\?|&)responseType=json/)?a:f(a,{responseType:"json"})}function e(a){a+="";return a.charAt(0).toUpperCase()+a.substr(1)}function k(){var a=this.getDialog(),b=a.getParentEditor();b._.filebrowserSe=this;var c=b.config["filebrowser"+e(a.getName())+"WindowWidth"]||b.config.filebrowserWindowWidth||"80%",a=b.config["filebrowser"+e(a.getName())+"WindowHeight"]||b.config.filebrowserWindowHeight||"70%",g=this.filebrowser.params||{};g.CKEditor=b.name;g.CKEditorFuncNum=b._.filebrowserFn;g.langCode|| -(g.langCode=b.langCode);g=f(this.filebrowser.url,g);b.popup(g,c,a,b.config.filebrowserWindowFeatures||b.config.fileBrowserWindowFeatures)}function d(a){var b=new CKEDITOR.dom.element(a.$.form);b&&((a=b.$.elements.ckCsrfToken)?a=new CKEDITOR.dom.element(a):(a=new CKEDITOR.dom.element("input"),a.setAttributes({name:"ckCsrfToken",type:"hidden"}),b.append(a)),a.setAttribute("value",CKEDITOR.tools.getCsrfToken()))}function l(){var a=this.getDialog();a.getParentEditor()._.filebrowserSe=this;return a.getContentElement(this["for"][0], -this["for"][1]).getInputElement().$.value&&a.getContentElement(this["for"][0],this["for"][1]).getAction()?!0:!1}function m(a,b,c){var g=c.params||{};g.CKEditor=a.name;g.CKEditorFuncNum=a._.filebrowserFn;g.langCode||(g.langCode=a.langCode);b.action=f(c.url,g);b.filebrowser=c}function b(c,f,v,p){if(p&&p.length)for(var r,q=p.length;q--;)if(r=p[q],"hbox"!=r.type&&"vbox"!=r.type&&"fieldset"!=r.type||b(c,f,v,r.children),r.filebrowser)if("string"==typeof r.filebrowser&&(r.filebrowser={action:"fileButton"== -r.type?"QuickUpload":"Browse",target:r.filebrowser}),"Browse"==r.filebrowser.action){var u=r.filebrowser.url;void 0===u&&(u=c.config["filebrowser"+e(f)+"BrowseUrl"],void 0===u&&(u=c.config.filebrowserBrowseUrl));u&&(r.onClick=k,r.filebrowser.url=u,r.hidden=!1)}else if("QuickUpload"==r.filebrowser.action&&r["for"]&&(u=r.filebrowser.url,void 0===u&&(u=c.config["filebrowser"+e(f)+"UploadUrl"],void 0===u&&(u=c.config.filebrowserUploadUrl)),u)){var x=r.onClick;r.onClick=function(b){var e=b.sender,f=e.getDialog().getContentElement(this["for"][0], -this["for"][1]).getInputElement(),k=CKEDITOR.fileTools&&CKEDITOR.fileTools.isFileUploadSupported;if(x&&!1===x.call(e,b))return!1;if(l.call(e,b)){if("form"!==c.config.filebrowserUploadMethod&&k)return b=c.uploadRepository.create(f.$.files[0]),b.on("uploaded",function(b){var c=b.sender.responseData;a.call(b.sender.editor,c.url,c.message)}),b.on("error",g.bind(this)),b.on("abort",g.bind(this)),b.loadAndUpload(h(u)),"xhr";d(f);return!0}return!1};r.filebrowser.url=u;r.hidden=!1;m(c,v.getContents(r["for"][0]).get(r["for"][1]), -r.filebrowser)}}function g(a){var b={};try{b=JSON.parse(a.sender.xhr.response)||{}}catch(c){}this.enable();alert(b.error?b.error.message:a.sender.message)}function c(a,b,g){if(-1!==g.indexOf(";")){g=g.split(";");for(var d=0;d<g.length;d++)if(c(a,b,g[d]))return!0;return!1}return(a=a.getContents(b).get(g).filebrowser)&&a.url}function a(a,b){var c=this._.filebrowserSe.getDialog(),g=this._.filebrowserSe["for"],d=this._.filebrowserSe.filebrowser.onSelect;g&&c.getContentElement(g[0],g[1]).reset();if("function"!= -typeof b||!1!==b.call(this._.filebrowserSe))if(!d||!1!==d.call(this._.filebrowserSe,a,b))if("string"==typeof b&&b&&alert(b),a&&(g=this._.filebrowserSe,c=g.getDialog(),g=g.filebrowser.target||null))if(g=g.split(":"),d=c.getContentElement(g[0],g[1]))d.setValue(a),c.selectPage(g[0])}CKEDITOR.plugins.add("filebrowser",{requires:"popup,filetools",init:function(b){b._.filebrowserFn=CKEDITOR.tools.addFunction(a,b);b.on("destroy",function(){CKEDITOR.tools.removeFunction(this._.filebrowserFn)})}});CKEDITOR.on("dialogDefinition", -function(a){if(a.editor.plugins.filebrowser)for(var g=a.data.definition,d,e=0;e<g.contents.length;++e)if(d=g.contents[e])b(a.editor,a.data.name,g,d.elements),d.hidden&&d.filebrowser&&(d.hidden=!c(g,d.id,d.filebrowser))})}(),function(){function f(f){var d=f.config,l=f.fire("uiSpace",{space:"top",html:""}).html,m=function(){function a(b,c,d){g.setStyle(c,e(d));g.setStyle("position",b)}function b(g){var d=l.getDocumentPosition();switch(g){case "top":a("absolute","top",d.y-x-t);break;case "pin":a("fixed", -"top",y);break;case "bottom":a("absolute","top",d.y+(q.height||q.bottom-q.top)+t)}c=g}var c,l,r,q,u,x,A,D=d.floatSpaceDockedOffsetX||0,t=d.floatSpaceDockedOffsetY||0,B=d.floatSpacePinnedOffsetX||0,y=d.floatSpacePinnedOffsetY||0;return function(a){if(l=f.editable()){var n=a&&"focus"==a.name;n&&g.show();f.fire("floatingSpaceLayout",{show:n});g.removeStyle("left");g.removeStyle("right");r=g.getClientRect();q=l.getClientRect();u=h.getViewPaneSize();x=r.height;A="pageXOffset"in h.$?h.$.pageXOffset:CKEDITOR.document.$.documentElement.scrollLeft; -c?(x+t<=q.top?b("top"):x+t>u.height-q.bottom?b("pin"):b("bottom"),a=u.width/2,a=d.floatSpacePreferRight?"right":0<q.left&&q.right<u.width&&q.width>r.width?"rtl"==d.contentsLangDirection?"right":"left":a-q.left>q.right-a?"left":"right",r.width>u.width?(a="left",n=0):(n="left"==a?0<q.left?q.left:0:q.right<u.width?u.width-q.right:0,n+r.width>u.width&&(a="left"==a?"right":"left",n=0)),g.setStyle(a,e(("pin"==c?B:D)+n+("pin"==c?0:"left"==a?A:-A)))):(c="pin",b("pin"),m(a))}}}();if(l){var b=new CKEDITOR.template('\x3cdiv id\x3d"cke_{name}" class\x3d"cke {id} cke_reset_all cke_chrome cke_editor_{name} cke_float cke_{langDir} '+ +"\x26responseType\x3djson":null},isTypeSupported:function(d,e){return!!d.type.match(e)},isFileUploadSupported:"function"===typeof FileReader&&"function"===typeof(new FileReader).readAsDataURL&&"function"===typeof FormData&&"function"===typeof(new FormData).append&&"function"===typeof XMLHttpRequest&&"function"===typeof Blob})}(),function(){function f(a,b){var c=[];if(b)for(var d in b)c.push(d+"\x3d"+encodeURIComponent(b[d]));else return a;return a+(-1!=a.indexOf("?")?"\x26":"?")+c.join("\x26")}function h(a){return!a.match(/command=QuickUpload/)|| +a.match(/(\?|&)responseType=json/)?a:f(a,{responseType:"json"})}function e(a){a+="";return a.charAt(0).toUpperCase()+a.substr(1)}function k(){var a=this.getDialog(),b=a.getParentEditor();b._.filebrowserSe=this;var c=b.config["filebrowser"+e(a.getName())+"WindowWidth"]||b.config.filebrowserWindowWidth||"80%",a=b.config["filebrowser"+e(a.getName())+"WindowHeight"]||b.config.filebrowserWindowHeight||"70%",d=this.filebrowser.params||{};d.CKEditor=b.name;d.CKEditorFuncNum=b._.filebrowserFn;d.langCode|| +(d.langCode=b.langCode);d=f(this.filebrowser.url,d);b.popup(d,c,a,b.config.filebrowserWindowFeatures||b.config.fileBrowserWindowFeatures)}function d(a){var b=new CKEDITOR.dom.element(a.$.form);b&&((a=b.$.elements.ckCsrfToken)?a=new CKEDITOR.dom.element(a):(a=new CKEDITOR.dom.element("input"),a.setAttributes({name:"ckCsrfToken",type:"hidden"}),b.append(a)),a.setAttribute("value",CKEDITOR.tools.getCsrfToken()))}function l(){var a=this.getDialog();a.getParentEditor()._.filebrowserSe=this;return a.getContentElement(this["for"][0], +this["for"][1]).getInputElement().$.value&&a.getContentElement(this["for"][0],this["for"][1]).getAction()?!0:!1}function m(a,b,c){var d=c.params||{};d.CKEditor=a.name;d.CKEditorFuncNum=a._.filebrowserFn;d.langCode||(d.langCode=a.langCode);b.action=f(c.url,d);b.filebrowser=c}function b(c,f,v,t){if(t&&t.length)for(var p,q=t.length;q--;)if(p=t[q],"hbox"!=p.type&&"vbox"!=p.type&&"fieldset"!=p.type||b(c,f,v,p.children),p.filebrowser)if("string"==typeof p.filebrowser&&(p.filebrowser={action:"fileButton"== +p.type?"QuickUpload":"Browse",target:p.filebrowser}),"Browse"==p.filebrowser.action){var A=p.filebrowser.url;void 0===A&&(A=c.config["filebrowser"+e(f)+"BrowseUrl"],void 0===A&&(A=c.config.filebrowserBrowseUrl));A&&(p.onClick=k,p.filebrowser.url=A,p.hidden=!1)}else if("QuickUpload"==p.filebrowser.action&&p["for"]&&(A=p.filebrowser.url,void 0===A&&(A=c.config["filebrowser"+e(f)+"UploadUrl"],void 0===A&&(A=c.config.filebrowserUploadUrl)),A)){var r=p.onClick;p.onClick=function(b){var e=b.sender,f=e.getDialog().getContentElement(this["for"][0], +this["for"][1]).getInputElement(),k=CKEDITOR.fileTools&&CKEDITOR.fileTools.isFileUploadSupported;if(r&&!1===r.call(e,b))return!1;if(l.call(e,b)){if("form"!==c.config.filebrowserUploadMethod&&k)return b=c.uploadRepository.create(f.$.files[0]),b.on("uploaded",function(b){var c=b.sender.responseData;a.call(b.sender.editor,c.url,c.message)}),b.on("error",g.bind(this)),b.on("abort",g.bind(this)),b.loadAndUpload(h(A)),"xhr";d(f);return!0}return!1};p.filebrowser.url=A;p.hidden=!1;m(c,v.getContents(p["for"][0]).get(p["for"][1]), +p.filebrowser)}}function g(a){var b={};try{b=JSON.parse(a.sender.xhr.response)||{}}catch(c){}this.enable();alert(b.error?b.error.message:a.sender.message)}function c(a,b,d){if(-1!==d.indexOf(";")){d=d.split(";");for(var e=0;e<d.length;e++)if(c(a,b,d[e]))return!0;return!1}return(a=a.getContents(b).get(d).filebrowser)&&a.url}function a(a,b){var c=this._.filebrowserSe.getDialog(),d=this._.filebrowserSe["for"],e=this._.filebrowserSe.filebrowser.onSelect;d&&c.getContentElement(d[0],d[1]).reset();if("function"!= +typeof b||!1!==b.call(this._.filebrowserSe))if(!e||!1!==e.call(this._.filebrowserSe,a,b))if("string"==typeof b&&b&&alert(b),a&&(d=this._.filebrowserSe,c=d.getDialog(),d=d.filebrowser.target||null))if(d=d.split(":"),e=c.getContentElement(d[0],d[1]))e.setValue(a),c.selectPage(d[0])}CKEDITOR.plugins.add("filebrowser",{requires:"popup,filetools",init:function(b){b._.filebrowserFn=CKEDITOR.tools.addFunction(a,b);b.on("destroy",function(){CKEDITOR.tools.removeFunction(this._.filebrowserFn)})}});CKEDITOR.on("dialogDefinition", +function(a){if(a.editor.plugins.filebrowser)for(var d=a.data.definition,e,g=0;g<d.contents.length;++g)if(e=d.contents[g])b(a.editor,a.data.name,d,e.elements),e.hidden&&e.filebrowser&&(e.hidden=!c(d,e.id,e.filebrowser))})}(),function(){function f(f){var d=f.config,l=f.fire("uiSpace",{space:"top",html:""}).html,m=function(){function a(b,c,d){g.setStyle(c,e(d));g.setStyle("position",b)}function b(d){var e=l.getDocumentPosition();switch(d){case "top":a("absolute","top",e.y-r-u);break;case "pin":a("fixed", +"top",x);break;case "bottom":a("absolute","top",e.y+(q.height||q.bottom-q.top)+u)}c=d}var c,l,p,q,A,r,C,B=d.floatSpaceDockedOffsetX||0,u=d.floatSpaceDockedOffsetY||0,y=d.floatSpacePinnedOffsetX||0,x=d.floatSpacePinnedOffsetY||0;return function(a){if(l=f.editable()){var n=a&&"focus"==a.name;n&&g.show();f.fire("floatingSpaceLayout",{show:n});g.removeStyle("left");g.removeStyle("right");p=g.getClientRect();q=l.getClientRect();A=h.getViewPaneSize();r=p.height;C="pageXOffset"in h.$?h.$.pageXOffset:CKEDITOR.document.$.documentElement.scrollLeft; +c?(r+u<=q.top?b("top"):r+u>A.height-q.bottom?b("pin"):b("bottom"),a=A.width/2,a=d.floatSpacePreferRight?"right":0<q.left&&q.right<A.width&&q.width>p.width?"rtl"==d.contentsLangDirection?"right":"left":a-q.left>q.right-a?"left":"right",p.width>A.width?(a="left",n=0):(n="left"==a?0<q.left?q.left:0:q.right<A.width?A.width-q.right:0,n+p.width>A.width&&(a="left"==a?"right":"left",n=0)),g.setStyle(a,e(("pin"==c?y:B)+n+("pin"==c?0:"left"==a?C:-C)))):(c="pin",b("pin"),m(a))}}}();if(l){var b=new CKEDITOR.template('\x3cdiv id\x3d"cke_{name}" class\x3d"cke {id} cke_reset_all cke_chrome cke_editor_{name} cke_float cke_{langDir} '+ CKEDITOR.env.cssClass+'" dir\x3d"{langDir}" title\x3d"'+(CKEDITOR.env.gecko?" ":"")+'" lang\x3d"{langCode}" role\x3d"application" style\x3d"{style}"'+(f.title?' aria-labelledby\x3d"cke_{name}_arialbl"':" ")+"\x3e"+(f.title?'\x3cspan id\x3d"cke_{name}_arialbl" class\x3d"cke_voice_label"\x3e{voiceLabel}\x3c/span\x3e':" ")+'\x3cdiv class\x3d"cke_inner"\x3e\x3cdiv id\x3d"{topId}" class\x3d"cke_top" role\x3d"presentation"\x3e{content}\x3c/div\x3e\x3c/div\x3e\x3c/div\x3e'),g=CKEDITOR.document.getBody().append(CKEDITOR.dom.element.createFromHtml(b.output({content:l, id:f.id,langDir:f.lang.dir,langCode:f.langCode,name:f.name,style:"display:none;z-index:"+(d.baseFloatZIndex-1),topId:f.ui.spaceId("top"),voiceLabel:f.title}))),c=CKEDITOR.tools.eventsBuffer(500,m),a=CKEDITOR.tools.eventsBuffer(100,m);g.unselectable();g.on("mousedown",function(a){a=a.data;a.getTarget().hasAscendant("a",1)||a.preventDefault()});f.on("focus",function(b){m(b);f.on("change",c.input);h.on("scroll",a.input);h.on("resize",a.input)});f.on("blur",function(){g.hide();f.removeListener("change", c.input);h.removeListener("scroll",a.input);h.removeListener("resize",a.input)});f.on("destroy",function(){h.removeListener("scroll",a.input);h.removeListener("resize",a.input);g.clearCustomData();g.remove()});f.focusManager.hasFocus&&g.show();f.focusManager.add(g,1)}}var h=CKEDITOR.document.getWindow(),e=CKEDITOR.tools.cssLength;CKEDITOR.plugins.add("floatingspace",{init:function(e){e.on("loaded",function(){f(this)},null,null,20)}})}(),CKEDITOR.plugins.add("listblock",{requires:"panel",onLoad:function(){var f= @@ -815,7 +816,7 @@ CKEDITOR.ui.richCombo.handler)}}),function(){var f='\x3cspan id\x3d"{id}" class\ (CKEDITOR.env.hc?"\x26#9660;":CKEDITOR.env.air?"\x26nbsp;":"")+"\x3c/span\x3e\x3c/span\x3e\x3c/a\x3e\x3c/span\x3e"),h=CKEDITOR.addTemplate("combo",f);CKEDITOR.UI_RICHCOMBO="richcombo";CKEDITOR.ui.richCombo=CKEDITOR.tools.createClass({$:function(e){CKEDITOR.tools.extend(this,e,{canGroup:!1,title:e.label,modes:{wysiwyg:1},editorFocus:1});e=this.panel||{};delete this.panel;this.id=CKEDITOR.tools.getNextNumber();this.document=e.parent&&e.parent.getDocument()||CKEDITOR.document;e.className="cke_combopanel"; e.block={multiSelect:e.multiSelect,attributes:e.attributes};e.toolbarRelated=!0;this._={panelDefinition:e,items:{}}},proto:{renderHtml:function(e){var f=[];this.render(e,f);return f.join("")},render:function(e,f){function d(){if(this.getState()!=CKEDITOR.TRISTATE_ON){var a=this.modes[e.mode]?CKEDITOR.TRISTATE_OFF:CKEDITOR.TRISTATE_DISABLED;e.readOnly&&!this.readOnly&&(a=CKEDITOR.TRISTATE_DISABLED);this.setState(a);this.setValue("");a!=CKEDITOR.TRISTATE_DISABLED&&this.refresh&&this.refresh()}}var l= CKEDITOR.env,m="cke_"+this.id,b=CKEDITOR.tools.addFunction(function(a){w&&(e.unlockSelection(1),w=0);c.execute(a)},this),g=this,c={id:m,combo:this,focus:function(){CKEDITOR.document.getById(m).getChild(1).focus()},execute:function(a){var b=g._;if(b.state!=CKEDITOR.TRISTATE_DISABLED)if(g.createPanel(e),b.on)b.panel.hide();else{g.commit();var c=g.getValue();c?b.list.mark(c):b.list.unmarkAll();b.panel.showBlock(g.id,new CKEDITOR.dom.element(a),4)}},clickFn:b};e.on("activeFilterChange",d,this);e.on("mode", -d,this);e.on("selectionChange",d,this);!this.readOnly&&e.on("readOnly",d,this);var a=CKEDITOR.tools.addFunction(function(a,g){a=new CKEDITOR.dom.event(a);var d=a.getKeystroke();switch(d){case 13:case 32:case 40:CKEDITOR.tools.callFunction(b,g);break;default:c.onkey(c,d)}a.preventDefault()}),n=CKEDITOR.tools.addFunction(function(){c.onfocus&&c.onfocus()}),w=0;c.keyDownFn=a;l={id:m,name:this.name||this.command,label:this.label,title:this.title,cls:this.className||"",titleJs:l.gecko&&!l.hc?"":(this.title|| +d,this);e.on("selectionChange",d,this);!this.readOnly&&e.on("readOnly",d,this);var a=CKEDITOR.tools.addFunction(function(a,d){a=new CKEDITOR.dom.event(a);var e=a.getKeystroke();switch(e){case 13:case 32:case 40:CKEDITOR.tools.callFunction(b,d);break;default:c.onkey(c,e)}a.preventDefault()}),n=CKEDITOR.tools.addFunction(function(){c.onfocus&&c.onfocus()}),w=0;c.keyDownFn=a;l={id:m,name:this.name||this.command,label:this.label,title:this.title,cls:this.className||"",titleJs:l.gecko&&!l.hc?"":(this.title|| "").replace("'",""),keydownFn:a,focusFn:n,clickFn:b};h.output(l,f);if(this.onRender)this.onRender();return c},createPanel:function(e){if(!this._.panel){var f=this._.panelDefinition,d=this._.panelDefinition.block,h=f.parent||CKEDITOR.document.getBody(),m="cke_combopanel__"+this.name,b=new CKEDITOR.ui.floatPanel(e,h,f),f=b.addListBlock(this.id,d),g=this;b.onShow=function(){this.element.addClass(m);g.setState(CKEDITOR.TRISTATE_ON);g._.on=1;g.editorFocus&&!e.focusManager.hasFocus&&e.focus();if(g.onOpen)g.onOpen()}; b.onHide=function(b){this.element.removeClass(m);g.setState(g.modes&&g.modes[e.mode]?CKEDITOR.TRISTATE_OFF:CKEDITOR.TRISTATE_DISABLED);g._.on=0;if(!b&&g.onClose)g.onClose()};b.onEscape=function(){b.hide(1)};f.onClick=function(c,a){g.onClick&&g.onClick.call(g,c,a);b.hide()};this._.panel=b;this._.list=f;b.getBlock(this.id).onHide=function(){g._.on=0;g.setState(CKEDITOR.TRISTATE_OFF)};this.init&&this.init()}},setValue:function(e,f){this._.value=e;var d=this.document.getById("cke_"+this.id+"_text");d&& (e||f?d.removeClass("cke_combo_inlinelabel"):(f=this.label,d.addClass("cke_combo_inlinelabel")),d.setText("undefined"!=typeof f?f:e))},getValue:function(){return this._.value||""},unmarkAll:function(){this._.list.unmarkAll()},mark:function(e){this._.list.mark(e)},hideItem:function(e){this._.list.hideItem(e)},hideGroup:function(e){this._.list.hideGroup(e)},showAll:function(){this._.list.showAll()},add:function(e,f,d){this._.items[e]=d||e;this._.list.add(e,f,d)},startGroup:function(e){this._.list.startGroup(e)}, @@ -833,11 +834,11 @@ this._.output.push(f)},comment:function(f){this._.indent&&this.indentation();thi this._.rules[f];e?CKEDITOR.tools.extend(e,h,!0):this._.rules[f]=h}}}),"use strict",function(){function f(b,c){CKEDITOR.tools.extend(this,{editor:b,editable:b.editable(),doc:b.document,win:b.window},c,!0);this.inline=this.editable.isInline();this.inline||(this.frame=this.win.getFrame());this.target=this[this.inline?"editable":"doc"]}function h(b,c){CKEDITOR.tools.extend(this,c,{editor:b},!0)}function e(b,c){var a=b.editable();CKEDITOR.tools.extend(this,{editor:b,editable:a,inline:a.isInline(),doc:b.document, win:b.window,container:CKEDITOR.document.getBody(),winTop:CKEDITOR.document.getWindow()},c,!0);this.hidden={};this.visible={};this.inline||(this.frame=this.win.getFrame());this.queryViewport();var e=CKEDITOR.tools.bind(this.queryViewport,this),f=CKEDITOR.tools.bind(this.hideVisible,this),h=CKEDITOR.tools.bind(this.removeAll,this);a.attachListener(this.winTop,"resize",e);a.attachListener(this.winTop,"scroll",e);a.attachListener(this.winTop,"resize",f);a.attachListener(this.win,"scroll",f);a.attachListener(this.inline? a:this.frame,"mouseout",function(a){var b=a.data.$.clientX;a=a.data.$.clientY;this.queryViewport();(b<=this.rect.left||b>=this.rect.right||a<=this.rect.top||a>=this.rect.bottom)&&this.hideVisible();(0>=b||b>=this.winTopPane.width||0>=a||a>=this.winTopPane.height)&&this.hideVisible()},this);a.attachListener(b,"resize",e);a.attachListener(b,"mode",h);b.on("destroy",h);this.lineTpl=(new CKEDITOR.template('\x3cdiv data-cke-lineutils-line\x3d"1" class\x3d"cke_reset_all" style\x3d"{lineStyle}"\x3e\x3cspan style\x3d"{tipLeftStyle}"\x3e\x26nbsp;\x3c/span\x3e\x3cspan style\x3d"{tipRightStyle}"\x3e\x26nbsp;\x3c/span\x3e\x3c/div\x3e')).output({lineStyle:CKEDITOR.tools.writeCssText(CKEDITOR.tools.extend({}, -l,this.lineStyle,!0)),tipLeftStyle:CKEDITOR.tools.writeCssText(CKEDITOR.tools.extend({},d,{left:"0px","border-left-color":"red","border-width":"6px 0 6px 6px"},this.tipCss,this.tipLeftStyle,!0)),tipRightStyle:CKEDITOR.tools.writeCssText(CKEDITOR.tools.extend({},d,{right:"0px","border-right-color":"red","border-width":"6px 6px 6px 0"},this.tipCss,this.tipRightStyle,!0))})}function k(g){var c;if(c=g&&g.type==CKEDITOR.NODE_ELEMENT)c=!(m[g.getComputedStyle("float")]||m[g.getAttribute("align")]);return c&& -!b[g.getComputedStyle("position")]}CKEDITOR.plugins.add("lineutils");CKEDITOR.LINEUTILS_BEFORE=1;CKEDITOR.LINEUTILS_AFTER=2;CKEDITOR.LINEUTILS_INSIDE=4;f.prototype={start:function(b){var c=this,a=this.editor,d=this.doc,e,f,h,k,l=CKEDITOR.tools.eventsBuffer(50,function(){a.readOnly||"wysiwyg"!=a.mode||(c.relations={},(f=d.$.elementFromPoint(h,k))&&f.nodeType&&(e=new CKEDITOR.dom.element(f),c.traverseSearch(e),isNaN(h+k)||c.pixelSearch(e,h,k),b&&b(c.relations,h,k)))});this.listener=this.editable.attachListener(this.target, +l,this.lineStyle,!0)),tipLeftStyle:CKEDITOR.tools.writeCssText(CKEDITOR.tools.extend({},d,{left:"0px","border-left-color":"red","border-width":"6px 0 6px 6px"},this.tipCss,this.tipLeftStyle,!0)),tipRightStyle:CKEDITOR.tools.writeCssText(CKEDITOR.tools.extend({},d,{right:"0px","border-right-color":"red","border-width":"6px 6px 6px 0"},this.tipCss,this.tipRightStyle,!0))})}function k(d){var c;if(c=d&&d.type==CKEDITOR.NODE_ELEMENT)c=!(m[d.getComputedStyle("float")]||m[d.getAttribute("align")]);return c&& +!b[d.getComputedStyle("position")]}CKEDITOR.plugins.add("lineutils");CKEDITOR.LINEUTILS_BEFORE=1;CKEDITOR.LINEUTILS_AFTER=2;CKEDITOR.LINEUTILS_INSIDE=4;f.prototype={start:function(b){var c=this,a=this.editor,d=this.doc,e,f,h,k,l=CKEDITOR.tools.eventsBuffer(50,function(){a.readOnly||"wysiwyg"!=a.mode||(c.relations={},(f=d.$.elementFromPoint(h,k))&&f.nodeType&&(e=new CKEDITOR.dom.element(f),c.traverseSearch(e),isNaN(h+k)||c.pixelSearch(e,h,k),b&&b(c.relations,h,k)))});this.listener=this.editable.attachListener(this.target, "mousemove",function(a){h=a.data.$.clientX;k=a.data.$.clientY;l.input()});this.editable.attachListener(this.inline?this.editable:this.frame,"mouseout",function(){l.reset()})},stop:function(){this.listener&&this.listener.removeListener()},getRange:function(){var b={};b[CKEDITOR.LINEUTILS_BEFORE]=CKEDITOR.POSITION_BEFORE_START;b[CKEDITOR.LINEUTILS_AFTER]=CKEDITOR.POSITION_AFTER_END;b[CKEDITOR.LINEUTILS_INSIDE]=CKEDITOR.POSITION_AFTER_START;return function(c){var a=this.editor.createRange();a.moveToPosition(this.relations[c.uid].element, -b[c.type]);return a}}(),store:function(){function b(c,a,d){var g=c.getUniqueId();g in d?d[g].type|=a:d[g]={element:c,type:a}}return function(c,a){var d;a&CKEDITOR.LINEUTILS_AFTER&&k(d=c.getNext())&&d.isVisible()&&(b(d,CKEDITOR.LINEUTILS_BEFORE,this.relations),a^=CKEDITOR.LINEUTILS_AFTER);a&CKEDITOR.LINEUTILS_INSIDE&&k(d=c.getFirst())&&d.isVisible()&&(b(d,CKEDITOR.LINEUTILS_BEFORE,this.relations),a^=CKEDITOR.LINEUTILS_INSIDE);b(c,a,this.relations)}}(),traverseSearch:function(b){var c,a,d;do if(d=b.$["data-cke-expando"], -!(d&&d in this.relations)){if(b.equals(this.editable))break;if(k(b))for(c in this.lookups)(a=this.lookups[c](b))&&this.store(b,a)}while((!b||b.type!=CKEDITOR.NODE_ELEMENT||"true"!=b.getAttribute("contenteditable"))&&(b=b.getParent()))},pixelSearch:function(){function b(a,d,g,e,f){for(var h=0,l;f(g);){g+=e;if(25==++h)break;if(l=this.doc.$.elementFromPoint(d,g))if(l==a)h=0;else if(c(a,l)&&(h=0,k(l=new CKEDITOR.dom.element(l))))return l}}var c=CKEDITOR.env.ie||CKEDITOR.env.webkit?function(a,b){return a.contains(b)}: +b[c.type]);return a}}(),store:function(){function b(c,a,d){var e=c.getUniqueId();e in d?d[e].type|=a:d[e]={element:c,type:a}}return function(c,a){var d;a&CKEDITOR.LINEUTILS_AFTER&&k(d=c.getNext())&&d.isVisible()&&(b(d,CKEDITOR.LINEUTILS_BEFORE,this.relations),a^=CKEDITOR.LINEUTILS_AFTER);a&CKEDITOR.LINEUTILS_INSIDE&&k(d=c.getFirst())&&d.isVisible()&&(b(d,CKEDITOR.LINEUTILS_BEFORE,this.relations),a^=CKEDITOR.LINEUTILS_INSIDE);b(c,a,this.relations)}}(),traverseSearch:function(b){var c,a,d;do if(d=b.$["data-cke-expando"], +!(d&&d in this.relations)){if(b.equals(this.editable))break;if(k(b))for(c in this.lookups)(a=this.lookups[c](b))&&this.store(b,a)}while((!b||b.type!=CKEDITOR.NODE_ELEMENT||"true"!=b.getAttribute("contenteditable"))&&(b=b.getParent()))},pixelSearch:function(){function b(a,d,e,f,g){for(var h=0,l;g(e);){e+=f;if(25==++h)break;if(l=this.doc.$.elementFromPoint(d,e))if(l==a)h=0;else if(c(a,l)&&(h=0,k(l=new CKEDITOR.dom.element(l))))return l}}var c=CKEDITOR.env.ie||CKEDITOR.env.webkit?function(a,b){return a.contains(b)}: function(a,b){return!!(a.compareDocumentPosition(b)&16)};return function(a,c,d){var e=this.win.getViewPaneSize().height,f=b.call(this,a.$,c,d,-1,function(a){return 0<a});c=b.call(this,a.$,c,d,1,function(a){return a<e});if(f)for(this.traverseSearch(f);!f.getParent().equals(a);)f=f.getParent();if(c)for(this.traverseSearch(c);!c.getParent().equals(a);)c=c.getParent();for(;f||c;){f&&(f=f.getNext(k));if(!f||f.equals(c))break;this.traverseSearch(f);c&&(c=c.getPrevious(k));if(!c||c.equals(f))break;this.traverseSearch(c)}}}(), greedySearch:function(){this.relations={};for(var b=this.editable.getElementsByTag("*"),c=0,a,d,e;a=b.getItem(c++);)if(!a.equals(this.editable)&&a.type==CKEDITOR.NODE_ELEMENT&&(a.hasAttribute("contenteditable")||!a.isReadOnly())&&k(a)&&a.isVisible())for(e in this.lookups)(d=this.lookups[e](a))&&this.store(a,d);return this.relations}};h.prototype={locate:function(){function b(c,a){var d=c.element[a===CKEDITOR.LINEUTILS_BEFORE?"getPrevious":"getNext"]();return d&&k(d)?(c.siblingRect=d.getClientRect(), a==CKEDITOR.LINEUTILS_BEFORE?(c.siblingRect.bottom+c.elementRect.top)/2:(c.elementRect.bottom+c.siblingRect.top)/2):a==CKEDITOR.LINEUTILS_BEFORE?c.elementRect.top:c.elementRect.bottom}return function(c){var a;this.locations={};for(var d in c)a=c[d],a.elementRect=a.element.getClientRect(),a.type&CKEDITOR.LINEUTILS_BEFORE&&this.store(d,CKEDITOR.LINEUTILS_BEFORE,b(a,CKEDITOR.LINEUTILS_BEFORE)),a.type&CKEDITOR.LINEUTILS_AFTER&&this.store(d,CKEDITOR.LINEUTILS_AFTER,b(a,CKEDITOR.LINEUTILS_AFTER)),a.type& @@ -847,203 +848,202 @@ b.hide();this.hidden[c]=b;delete this.visible[c]},showLine:function(b){var c=b.g break}d||this.showLine(d=this.addLine());d.setCustomData("hash",this.hash);this.visible[d.getUniqueId()]=d;d.setStyles(a);c&&c(d)}},getStyle:function(b,c){var a=this.relations[b],d=this.locations[b][c],e={};e.width=a.siblingRect?Math.max(a.siblingRect.width,a.elementRect.width):a.elementRect.width;e.top=this.inline?d+this.winTopScroll.y-this.rect.relativeY:this.rect.top+this.winTopScroll.y+d;if(e.top-this.winTopScroll.y<this.rect.top||e.top-this.winTopScroll.y>this.rect.bottom)return!1;this.inline? e.left=a.elementRect.left-this.rect.relativeX:(0<a.elementRect.left?e.left=this.rect.left+a.elementRect.left:(e.width+=a.elementRect.left,e.left=this.rect.left),0<(a=e.left+e.width-(this.rect.left+this.winPane.width))&&(e.width-=a));e.left+=this.winTopScroll.x;for(var f in e)e[f]=CKEDITOR.tools.cssLength(e[f]);return e},addLine:function(){var b=CKEDITOR.dom.element.createFromHtml(this.lineTpl);b.appendTo(this.container);return b},prepare:function(b,c){this.relations=b;this.locations=c;this.hash=Math.random()}, cleanup:function(){var b,c;for(c in this.visible)b=this.visible[c],b.getCustomData("hash")!==this.hash&&this.hideLine(b)},queryViewport:function(){this.winPane=this.win.getViewPaneSize();this.winTopScroll=this.winTop.getScrollPosition();this.winTopPane=this.winTop.getViewPaneSize();this.rect=this.getClientRect(this.inline?this.editable:this.frame)},getClientRect:function(b){b=b.getClientRect();var c=this.container.getDocumentPosition(),a=this.container.getComputedStyle("position");b.relativeX=b.relativeY= -0;"static"!=a&&(b.relativeY=c.y,b.relativeX=c.x,b.top-=b.relativeY,b.bottom-=b.relativeY,b.left-=b.relativeX,b.right-=b.relativeX);return b}};var m={left:1,right:1,center:1},b={absolute:1,fixed:1};CKEDITOR.plugins.lineutils={finder:f,locator:h,liner:e}}(),function(){function f(f){return f.getName&&!f.hasAttribute("data-cke-temp")}CKEDITOR.plugins.add("widgetselection",{init:function(f){if(CKEDITOR.env.webkit){var e=CKEDITOR.plugins.widgetselection;f.on("contentDom",function(f){f=f.editor;var d=f.document, -h=f.editable();h.attachListener(d,"keydown",function(d){d.data.getKeystroke()==CKEDITOR.CTRL+65&&CKEDITOR.tools.setTimeout(function(){e.addFillers(h)||e.removeFillers(h)},0)},null,null,-1);f.on("selectionCheck",function(d){e.removeFillers(d.editor.editable())});f.on("paste",function(d){d.data.dataValue=e.cleanPasteData(d.data.dataValue)});"selectall"in f.plugins&&e.addSelectAllIntegration(f)})}}});CKEDITOR.plugins.widgetselection={startFiller:null,endFiller:null,fillerAttribute:"data-cke-filler-webkit", -fillerContent:"\x26nbsp;",fillerTagName:"div",addFillers:function(h){var e=h.editor;if(!this.isWholeContentSelected(h)&&0<h.getChildCount()){var k=h.getFirst(f),d=h.getLast(f);k&&k.type==CKEDITOR.NODE_ELEMENT&&!k.isEditable()&&(this.startFiller=this.createFiller(),h.append(this.startFiller,1));d&&d.type==CKEDITOR.NODE_ELEMENT&&!d.isEditable()&&(this.endFiller=this.createFiller(!0),h.append(this.endFiller,0));if(this.hasFiller(h))return e=e.createRange(),e.selectNodeContents(h),e.select(),!0}return!1}, -removeFillers:function(f){if(this.hasFiller(f)&&!this.isWholeContentSelected(f)){var e=f.findOne(this.fillerTagName+"["+this.fillerAttribute+"\x3dstart]"),k=f.findOne(this.fillerTagName+"["+this.fillerAttribute+"\x3dend]");this.startFiller&&e&&this.startFiller.equals(e)?this.removeFiller(this.startFiller,f):this.startFiller=e;this.endFiller&&k&&this.endFiller.equals(k)?this.removeFiller(this.endFiller,f):this.endFiller=k}},cleanPasteData:function(f){f&&f.length&&(f=f.replace(this.createFillerRegex(), -"").replace(this.createFillerRegex(!0),""));return f},isWholeContentSelected:function(f){var e=f.editor.getSelection().getRanges()[0];return!e||e&&e.collapsed?!1:(e=e.clone(),e.enlarge(CKEDITOR.ENLARGE_ELEMENT),!!(e&&f&&e.startContainer&&e.endContainer&&0===e.startOffset&&e.endOffset===f.getChildCount()&&e.startContainer.equals(f)&&e.endContainer.equals(f)))},hasFiller:function(f){return 0<f.find(this.fillerTagName+"["+this.fillerAttribute+"]").count()},createFiller:function(f){var e=new CKEDITOR.dom.element(this.fillerTagName); -e.setHtml(this.fillerContent);e.setAttribute(this.fillerAttribute,f?"end":"start");e.setAttribute("data-cke-temp",1);e.setStyles({display:"block",width:0,height:0,padding:0,border:0,margin:0,position:"absolute",top:0,left:"-9999px",opacity:0,overflow:"hidden"});return e},removeFiller:function(f,e){if(f){var k=e.editor,d=e.editor.getSelection().getRanges()[0].startPath(),l=k.createRange(),m,b;d.contains(f)&&(m=f.getHtml(),b=!0);d="start"==f.getAttribute(this.fillerAttribute);f.remove();m&&0<m.length&& -m!=this.fillerContent?(e.insertHtmlIntoRange(m,k.getSelection().getRanges()[0]),l.setStartAt(e.getChild(e.getChildCount()-1),CKEDITOR.POSITION_BEFORE_END),k.getSelection().selectRanges([l])):b&&(d?l.setStartAt(e.getFirst().getNext(),CKEDITOR.POSITION_AFTER_START):l.setEndAt(e.getLast().getPrevious(),CKEDITOR.POSITION_BEFORE_END),e.editor.getSelection().selectRanges([l]))}},createFillerRegex:function(f){var e=this.createFiller(f).getOuterHtml().replace(/style="[^"]*"/gi,'style\x3d"[^"]*"').replace(/>[^<]*</gi, -"\x3e[^\x3c]*\x3c");return new RegExp((f?"":"^")+e+(f?"$":""))},addSelectAllIntegration:function(f){var e=this;f.editable().attachListener(f,"beforeCommandExec",function(k){var d=f.editable();"selectAll"==k.data.name&&d&&e.addFillers(d)},null,null,9999)}}}(),"use strict",function(){function f(a){this.editor=a;this.registered={};this.instances={};this.selected=[];this.widgetHoldingFocusedEditable=this.focused=null;this._={nextId:0,upcasts:[],upcastCallbacks:[],filters:{}};I(this);z(this);this.on("checkWidgets", -m);this.editor.on("contentDomInvalidated",this.checkWidgets,this);y(this);D(this);t(this);A(this);B(this)}function h(a,b,c,d,g){var e=a.editor;CKEDITOR.tools.extend(this,d,{editor:e,id:b,inline:"span"==c.getParent().getName(),element:c,data:CKEDITOR.tools.extend({},"function"==typeof d.defaults?d.defaults():d.defaults),dataReady:!1,inited:!1,ready:!1,edit:h.prototype.edit,focusedEditable:null,definition:d,repository:a,draggable:!1!==d.draggable,_:{downcastFn:d.downcast&&"string"==typeof d.downcast? -d.downcasts[d.downcast]:d.downcast}},!0);a.fire("instanceCreated",this);aa(this,d);this.init&&this.init();this.inited=!0;(a=this.element.data("cke-widget-data"))&&this.setData(JSON.parse(decodeURIComponent(a)));g&&this.setData(g);this.data.classes||this.setData("classes",this.getClasses());this.dataReady=!0;Q(this);this.fire("data",this.data);this.isInited()&&e.editable().contains(this.wrapper)&&(this.ready=!0,this.fire("ready"))}function e(a,b,c){CKEDITOR.dom.element.call(this,b.$);this.editor=a; -this._={};b=this.filter=c.filter;CKEDITOR.dtd[this.getName()].p?(this.enterMode=b?b.getAllowedEnterMode(a.enterMode):a.enterMode,this.shiftEnterMode=b?b.getAllowedEnterMode(a.shiftEnterMode,!0):a.shiftEnterMode):this.enterMode=this.shiftEnterMode=CKEDITOR.ENTER_BR}function k(a,b){a.addCommand(b.name,{exec:function(a,c){function d(){a.widgets.finalizeCreation(h)}var g=a.widgets.focused;if(g&&g.name==b.name)g.edit();else if(b.insert)b.insert();else if(b.template){var g="function"==typeof b.defaults? -b.defaults():b.defaults,g=CKEDITOR.dom.element.createFromHtml(b.template.output(g)),e,f=a.widgets.wrapElement(g,b.name),h=new CKEDITOR.dom.documentFragment(f.getDocument());h.append(f);(e=a.widgets.initOn(g,b,c&&c.startupData))?(g=e.once("edit",function(b){if(b.data.dialog)e.once("dialog",function(b){b=b.data;var c,g;c=b.once("ok",d,null,null,20);g=b.once("cancel",function(b){b.data&&!1===b.data.hide||a.widgets.destroy(e,!0)});b.once("hide",function(){c.removeListener();g.removeListener()})});else d()}, -null,null,999),e.edit(),g.removeListener()):d()}},allowedContent:b.allowedContent,requiredContent:b.requiredContent,contentForms:b.contentForms,contentTransformations:b.contentTransformations})}function d(a,b){function c(a,d){var g=b.upcast.split(","),e,f;for(f=0;f<g.length;f++)if(e=g[f],e===a.name)return b.upcasts[e].call(this,a,d);return!1}function d(b,c,g){var e=CKEDITOR.tools.getIndex(a._.upcasts,function(a){return a[2]>g});0>e&&(e=a._.upcasts.length);a._.upcasts.splice(e,0,[CKEDITOR.tools.bind(b, -c),c.name,g])}var g=b.upcast,e=b.upcastPriority||10;g&&("string"==typeof g?d(c,b,e):d(g,b,e))}function l(a,b){a.focused=null;if(b.isInited()){var c=b.editor.checkDirty();a.fire("widgetBlurred",{widget:b});b.setFocused(!1);!c&&b.editor.resetDirty()}}function m(a){a=a.data;if("wysiwyg"==this.editor.mode){var b=this.editor.editable(),c=this.instances,d,g,e,f;if(b){for(d in c)c[d].isReady()&&!b.contains(c[d].wrapper)&&this.destroy(c[d],!0);if(a&&a.initOnlyNew)c=this.initOnAll();else{var k=b.find(".cke_widget_wrapper"), -c=[];d=0;for(g=k.count();d<g;d++){e=k.getItem(d);if(f=!this.getByElement(e,!0)){a:{f=r;for(var l=e;l=l.getParent();)if(f(l)){f=!0;break a}f=!1}f=!f}f&&b.contains(e)&&(e.addClass("cke_widget_new"),c.push(this.initOn(e.getFirst(h.isDomWidgetElement))))}}a&&a.focusInited&&1==c.length&&c[0].focus()}}}function b(a){if("undefined"!=typeof a.attributes&&a.attributes["data-widget"]){var b=g(a),d=c(a),e=!1;b&&b.value&&b.value.match(/^\s/g)&&(b.parent.attributes["data-cke-white-space-first"]=1,b.value=b.value.replace(/^\s/g, -"\x26nbsp;"),e=!0);d&&d.value&&d.value.match(/\s$/g)&&(d.parent.attributes["data-cke-white-space-last"]=1,d.value=d.value.replace(/\s$/g,"\x26nbsp;"),e=!0);e&&(a.attributes["data-cke-widget-white-space"]=1)}}function g(a){return a.find(function(a){return 3===a.type},!0).shift()}function c(a){return a.find(function(a){return 3===a.type},!0).pop()}function a(a,b,c){if(!c.allowedContent&&!c.disallowedContent)return null;var d=this._.filters[a];d||(this._.filters[a]=d={});a=d[b];a||(a=c.allowedContent? -new CKEDITOR.filter(c.allowedContent):this.editor.filter.clone(),d[b]=a,c.disallowedContent&&a.disallow(c.disallowedContent));return a}function n(a){var b=[],c=a._.upcasts,d=a._.upcastCallbacks;return{toBeWrapped:b,iterator:function(a){var g,e,f,k,l;if("data-cke-widget-wrapper"in a.attributes)return(a=a.getFirst(h.isParserWidgetElement))&&b.push([a]),!1;if("data-widget"in a.attributes)return b.push([a]),!1;if(l=c.length){if(a.attributes["data-cke-widget-upcasted"])return!1;k=0;for(g=d.length;k<g;++k)if(!1=== -d[k](a))return;for(k=0;k<l;++k)if(g=c[k],f={},e=g[0](a,f))return e instanceof CKEDITOR.htmlParser.element&&(a=e),a.attributes["data-cke-widget-data"]=encodeURIComponent(JSON.stringify(f)),a.attributes["data-cke-widget-upcasted"]=1,b.push([a,g[1]]),!1}}}}function w(a,b){return{tabindex:-1,contenteditable:"false","data-cke-widget-wrapper":1,"data-cke-filter":"off","class":"cke_widget_wrapper cke_widget_new cke_widget_"+(a?"inline":"block")+(b?" cke_widget_"+b:"")}}function v(a,b,c){if(a.type==CKEDITOR.NODE_ELEMENT){var d= -CKEDITOR.dtd[a.name];if(d&&!d[c.name]){var d=a.split(b),g=a.parent;b=d.getIndex();a.children.length||(--b,a.remove());d.children.length||d.remove();return v(g,b,c)}}a.add(c,b)}function p(a,b){return"boolean"==typeof a.inline?a.inline:!!CKEDITOR.dtd.$inline[b]}function r(a){return a.hasAttribute("data-cke-temp")}function q(a,b,c,d){var g=a.editor;g.fire("lockSnapshot");c?(d=c.data("cke-widget-editable"),d=b.editables[d],a.widgetHoldingFocusedEditable=b,b.focusedEditable=d,c.addClass("cke_widget_editable_focused"), -d.filter&&g.setActiveFilter(d.filter),g.setActiveEnterMode(d.enterMode,d.shiftEnterMode)):(d||b.focusedEditable.removeClass("cke_widget_editable_focused"),b.focusedEditable=null,a.widgetHoldingFocusedEditable=null,g.setActiveFilter(null),g.setActiveEnterMode(null,null));g.fire("unlockSnapshot")}function u(a){a.contextMenu&&a.contextMenu.addListener(function(b){if(b=a.widgets.getByElement(b,!0))return b.fire("contextMenu",{})})}function x(a,b){return CKEDITOR.tools.trim(b)}function A(a){var b=a.editor, -c=CKEDITOR.plugins.lineutils;b.on("dragstart",function(c){var d=c.data.target;h.isDomDragHandler(d)&&(d=a.getByElement(d),c.data.dataTransfer.setData("cke/widget-id",d.id),b.focus(),d.focus())});b.on("drop",function(c){var d=c.data.dataTransfer,g=d.getData("cke/widget-id"),e=d.getTransferType(b),d=b.createRange();""!==g&&e===CKEDITOR.DATA_TRANSFER_CROSS_EDITORS?c.cancel():""!==g&&e==CKEDITOR.DATA_TRANSFER_INTERNAL&&(g=a.instances[g])&&(d.setStartBefore(g.wrapper),d.setEndAfter(g.wrapper),c.data.dragRange= -d,delete CKEDITOR.plugins.clipboard.dragStartContainerChildCount,delete CKEDITOR.plugins.clipboard.dragEndContainerChildCount,c.data.dataTransfer.setData("text/html",b.editable().getHtmlFromRange(d).getHtml()),b.widgets.destroy(g,!0))});b.on("contentDom",function(){var d=b.editable();CKEDITOR.tools.extend(a,{finder:new c.finder(b,{lookups:{"default":function(b){if(!b.is(CKEDITOR.dtd.$listItem)&&b.is(CKEDITOR.dtd.$block)&&!h.isDomNestedEditable(b)&&!a._.draggedWidget.wrapper.contains(b)){var c=h.getNestedEditable(d, -b);if(c){b=a._.draggedWidget;if(a.getByElement(c)==b)return;c=CKEDITOR.filter.instances[c.data("cke-filter")];b=b.requiredContent;if(c&&b&&!c.check(b))return}return CKEDITOR.LINEUTILS_BEFORE|CKEDITOR.LINEUTILS_AFTER}}}}),locator:new c.locator(b),liner:new c.liner(b,{lineStyle:{cursor:"move !important","border-top-color":"#666"},tipLeftStyle:{"border-left-color":"#666"},tipRightStyle:{"border-right-color":"#666"}})},!0)})}function D(a){var b=a.editor;b.on("contentDom",function(){var c=b.editable(), -d=c.isInline()?c:b.document,g,e;c.attachListener(d,"mousedown",function(c){var d=c.data.getTarget();g=d instanceof CKEDITOR.dom.element?a.getByElement(d):null;e=0;g&&(g.inline&&d.type==CKEDITOR.NODE_ELEMENT&&d.hasAttribute("data-cke-widget-drag-handler")?(e=1,a.focused!=g&&b.getSelection().removeAllRanges()):h.getNestedEditable(g.wrapper,d)?g=null:(c.data.preventDefault(),CKEDITOR.env.ie||g.focus()))});c.attachListener(d,"mouseup",function(){e&&g&&g.wrapper&&(e=0,g.focus())});CKEDITOR.env.ie&&c.attachListener(d, -"mouseup",function(){setTimeout(function(){g&&g.wrapper&&c.contains(g.wrapper)&&(g.focus(),g=null)})})});b.on("doubleclick",function(b){var c=a.getByElement(b.data.element);if(c&&!h.getNestedEditable(c.wrapper,b.data.element))return c.fire("doubleclick",{element:b.data.element})},null,null,1)}function t(a){a.editor.on("key",function(b){var c=a.focused,d=a.widgetHoldingFocusedEditable,g;c?g=c.fire("key",{keyCode:b.data.keyCode}):d&&(c=b.data.keyCode,b=d.focusedEditable,c==CKEDITOR.CTRL+65?(c=b.getBogus(), -d=d.editor.createRange(),d.selectNodeContents(b),c&&d.setEndAt(c,CKEDITOR.POSITION_BEFORE_START),d.select(),g=!1):8==c||46==c?(g=d.editor.getSelection().getRanges(),d=g[0],g=!(1==g.length&&d.collapsed&&d.checkBoundaryOfElement(b,CKEDITOR[8==c?"START":"END"]))):g=void 0);return g},null,null,1)}function B(a){function b(c){a.focused&&G(a.focused,"cut"==c.name)}var c=a.editor;c.on("contentDom",function(){var a=c.editable();a.attachListener(a,"copy",b);a.attachListener(a,"cut",b)})}function y(a){var b= -a.editor;b.on("selectionCheck",function(){a.fire("checkSelection")});a.on("checkSelection",a.checkSelection,a);b.on("selectionChange",function(c){var d=(c=h.getNestedEditable(b.editable(),c.data.selection.getStartElement()))&&a.getByElement(c),g=a.widgetHoldingFocusedEditable;g?g===d&&g.focusedEditable.equals(c)||(q(a,g,null),d&&c&&q(a,d,c)):d&&c&&q(a,d,c)});b.on("dataReady",function(){E(a).commit()});b.on("blur",function(){var b;(b=a.focused)&&l(a,b);(b=a.widgetHoldingFocusedEditable)&&q(a,b,null)})} -function z(a){var b=a.editor,d={};b.on("toDataFormat",function(b){var e=CKEDITOR.tools.getNextNumber(),f=[];b.data.downcastingSessionId=e;d[e]=f;b.data.dataValue.forEach(function(b){var d=b.attributes,e;if("data-cke-widget-white-space"in d){e=g(b);var k=c(b);e.parent.attributes["data-cke-white-space-first"]&&(e.value=e.value.replace(/^ /g," "));k.parent.attributes["data-cke-white-space-last"]&&(k.value=k.value.replace(/ $/g," "))}if("data-cke-widget-id"in d){if(d=a.instances[d["data-cke-widget-id"]])e= -b.getFirst(h.isParserWidgetElement),f.push({wrapper:b,element:e,widget:d,editables:{}}),"1"!=e.attributes["data-cke-widget-keep-attr"]&&delete e.attributes["data-widget"]}else if("data-cke-widget-editable"in d)return f[f.length-1].editables[d["data-cke-widget-editable"]]=b,!1},CKEDITOR.NODE_ELEMENT,!0)},null,null,8);b.on("toDataFormat",function(a){if(a.data.downcastingSessionId){a=d[a.data.downcastingSessionId];for(var b,c,g,e,f,h;b=a.shift();){c=b.widget;g=b.element;e=c._.downcastFn&&c._.downcastFn.call(c, -g);for(h in b.editables)f=b.editables[h],delete f.attributes.contenteditable,f.setHtml(c.editables[h].getData());e||(e=g);b.wrapper.replaceWith(e)}}},null,null,13);b.on("contentDomUnload",function(){a.destroyAll(!0)})}function I(a){var b=a.editor,c,d;b.on("toHtml",function(b){var d=n(a),g;for(b.data.dataValue.forEach(d.iterator,CKEDITOR.NODE_ELEMENT,!0);g=d.toBeWrapped.pop();){var e=g[0],f=e.parent;f.type==CKEDITOR.NODE_ELEMENT&&f.attributes["data-cke-widget-wrapper"]&&f.replaceWith(e);a.wrapElement(g[0], -g[1])}c=b.data.protectedWhitespaces?3==b.data.dataValue.children.length&&h.isParserWidgetWrapper(b.data.dataValue.children[1]):1==b.data.dataValue.children.length&&h.isParserWidgetWrapper(b.data.dataValue.children[0])},null,null,8);b.on("dataReady",function(){if(d)for(var c=b.editable().find(".cke_widget_wrapper"),g,e,f=0,k=c.count();f<k;++f)g=c.getItem(f),e=g.getFirst(h.isDomWidgetElement),e.type==CKEDITOR.NODE_ELEMENT&&e.data("widget")?(e.replace(g),a.wrapElement(e)):g.remove();d=0;a.destroyAll(!0); -a.initOnAll()});b.on("loadSnapshot",function(b){/data-cke-widget/.test(b.data)&&(d=1);a.destroyAll(!0)},null,null,9);b.on("paste",function(a){a=a.data;a.dataValue=a.dataValue.replace(V,x);a.range&&(a=h.getNestedEditable(b.editable(),a.range.startContainer))&&(a=CKEDITOR.filter.instances[a.data("cke-filter")])&&b.setActiveFilter(a)});b.on("afterInsertHtml",function(d){d.data.intoRange?a.checkWidgets({initOnlyNew:!0}):(b.fire("lockSnapshot"),a.checkWidgets({initOnlyNew:!0,focusInited:c}),b.fire("unlockSnapshot"))})} -function E(a){var b=a.selected,c=[],d=b.slice(0),g=null;return{select:function(a){0>CKEDITOR.tools.indexOf(b,a)&&c.push(a);a=CKEDITOR.tools.indexOf(d,a);0<=a&&d.splice(a,1);return this},focus:function(a){g=a;return this},commit:function(){var e=a.focused!==g,f,h;a.editor.fire("lockSnapshot");for(e&&(f=a.focused)&&l(a,f);f=d.pop();)b.splice(CKEDITOR.tools.indexOf(b,f),1),f.isInited()&&(h=f.editor.checkDirty(),f.setSelected(!1),!h&&f.editor.resetDirty());e&&g&&(h=a.editor.checkDirty(),a.focused=g,a.fire("widgetFocused", -{widget:g}),g.setFocused(!0),!h&&a.editor.resetDirty());for(;f=c.pop();)b.push(f),f.setSelected(!0);a.editor.fire("unlockSnapshot")}}}function F(a,b,c){var d=0;b=L(b);var g=a.data.classes||{},e;if(b){for(g=CKEDITOR.tools.clone(g);e=b.pop();)c?g[e]||(d=g[e]=1):g[e]&&(delete g[e],d=1);d&&a.setData("classes",g)}}function H(a){a.cancel()}function G(a,b){var c=a.editor,d=c.document,g=CKEDITOR.env.edge&&16<=CKEDITOR.env.version;if(!d.getById("cke_copybin")){var e=!c.blockless&&!CKEDITOR.env.ie||g?"div": -"span",g=d.createElement(e),f=d.createElement(e),e=CKEDITOR.env.ie&&9>CKEDITOR.env.version;f.setAttributes({id:"cke_copybin","data-cke-temp":"1"});g.setStyles({position:"absolute",width:"1px",height:"1px",overflow:"hidden"});g.setStyle("ltr"==c.config.contentsLangDirection?"left":"right","-5000px");var h=c.createRange();h.setStartBefore(a.wrapper);h.setEndAfter(a.wrapper);g.setHtml('\x3cspan data-cke-copybin-start\x3d"1"\x3e\x3c/span\x3e'+c.editable().getHtmlFromRange(h).getHtml()+'\x3cspan data-cke-copybin-end\x3d"1"\x3e\x3c/span\x3e'); -c.fire("saveSnapshot");c.fire("lockSnapshot");f.append(g);c.editable().append(f);var k=c.on("selectionChange",H,null,null,0),l=a.repository.on("checkSelection",H,null,null,0);if(e)var m=d.getDocumentElement().$,q=m.scrollTop;h=c.createRange();h.selectNodeContents(g);h.select();e&&(m.scrollTop=q);setTimeout(function(){b||a.focus();f.remove();k.removeListener();l.removeListener();c.fire("unlockSnapshot");b&&!c.readOnly&&(a.repository.del(a),c.fire("saveSnapshot"))},100)}}function L(a){return(a=(a=a.getDefinition().attributes)&& -a["class"])?a.split(/\s+/):null}function O(){var a=CKEDITOR.document.getActive(),b=this.editor,c=b.editable();(c.isInline()?c:b.document.getWindow().getFrame()).equals(a)&&b.focusManager.focus(c)}function C(){CKEDITOR.env.gecko&&this.editor.unlockSelection();CKEDITOR.env.webkit||(this.editor.forceNextSelectionCheck(),this.editor.selectionChange(1))}function S(a){var b=null;a.on("data",function(){var a=this.data.classes,c;if(b!=a){for(c in b)a&&a[c]||this.removeClass(c);for(c in a)this.addClass(c); -b=a}})}function J(a){a.on("data",function(){if(a.wrapper){var b=this.getLabel?this.getLabel():this.editor.lang.widget.label.replace(/%1/,this.pathName||this.element.getName());a.wrapper.setAttribute("role","region");a.wrapper.setAttribute("aria-label",b)}},null,null,9999)}function R(a){if(a.draggable){var b=a.editor,c=a.wrapper.getLast(h.isDomDragHandlerContainer),d;c?d=c.findOne("img"):(c=new CKEDITOR.dom.element("span",b.document),c.setAttributes({"class":"cke_reset cke_widget_drag_handler_container", -style:"background:rgba(220,220,220,0.5);background-image:url("+b.plugins.widget.path+"images/handle.png)"}),d=new CKEDITOR.dom.element("img",b.document),d.setAttributes({"class":"cke_reset cke_widget_drag_handler","data-cke-widget-drag-handler":"1",src:CKEDITOR.tools.transparentImageData,width:15,title:b.lang.widget.move,height:15,role:"presentation"}),a.inline&&d.setAttribute("draggable","true"),c.append(d),a.wrapper.append(c));a.wrapper.on("dragover",function(a){a.data.preventDefault()});a.wrapper.on("mouseenter", -a.updateDragHandlerPosition,a);setTimeout(function(){a.on("data",a.updateDragHandlerPosition,a)},50);if(!a.inline&&(d.on("mousedown",K,a),CKEDITOR.env.ie&&9>CKEDITOR.env.version))d.on("dragstart",function(a){a.data.preventDefault(!0)});a.dragHandlerContainer=c}}function K(a){function b(){var c;for(n.reset();c=h.pop();)c.removeListener();var d=k;c=a.sender;var g=this.repository.finder,e=this.repository.liner,f=this.editor,l=this.editor.editable();CKEDITOR.tools.isEmpty(e.visible)||(d=g.getRange(d[0]), -this.focus(),f.fire("drop",{dropRange:d,target:d.startContainer}));l.removeClass("cke_widget_dragging");e.hideVisible();f.fire("dragend",{target:c})}if(CKEDITOR.tools.getMouseButton(a)===CKEDITOR.MOUSE_BUTTON_LEFT){var c=this.repository.finder,d=this.repository.locator,g=this.repository.liner,e=this.editor,f=e.editable(),h=[],k=[],l,m;this.repository._.draggedWidget=this;var q=c.greedySearch(),n=CKEDITOR.tools.eventsBuffer(50,function(){l=d.locate(q);k=d.sort(m,1);k.length&&(g.prepare(q,l),g.placeLine(k[0]), -g.cleanup())});f.addClass("cke_widget_dragging");h.push(f.on("mousemove",function(a){m=a.data.$.clientY;n.input()}));e.fire("dragstart",{target:a.sender});h.push(e.document.once("mouseup",b,this));f.isInline()||h.push(CKEDITOR.document.once("mouseup",b,this))}}function U(a){var b,c,d=a.editables;a.editables={};if(a.editables)for(b in d)c=d[b],a.initEditable(b,"string"==typeof c?{selector:c}:c)}function Y(a){if(a.mask){var b=a.wrapper.findOne(".cke_widget_mask");b||(b=new CKEDITOR.dom.element("img", -a.editor.document),b.setAttributes({src:CKEDITOR.tools.transparentImageData,"class":"cke_reset cke_widget_mask"}),a.wrapper.append(b));a.mask=b}}function Z(a){if(a.parts){var b={},c,d;for(d in a.parts)c=a.wrapper.findOne(a.parts[d]),b[d]=c;a.parts=b}}function aa(a,b){M(a);Z(a);U(a);Y(a);R(a);S(a);J(a);if(CKEDITOR.env.ie&&9>CKEDITOR.env.version)a.wrapper.on("dragstart",function(b){var c=b.data.getTarget();h.getNestedEditable(a,c)||a.inline&&h.isDomDragHandler(c)||b.data.preventDefault()});a.wrapper.removeClass("cke_widget_new"); -a.element.addClass("cke_widget_element");a.on("key",function(b){b=b.data.keyCode;if(13==b)a.edit();else{if(b==CKEDITOR.CTRL+67||b==CKEDITOR.CTRL+88){G(a,b==CKEDITOR.CTRL+88);return}if(b in T||CKEDITOR.CTRL&b||CKEDITOR.ALT&b)return}return!1},null,null,999);a.on("doubleclick",function(b){a.edit()&&b.cancel()});if(b.data)a.on("data",b.data);if(b.edit)a.on("edit",b.edit)}function M(a){(a.wrapper=a.element.getParent()).setAttribute("data-cke-widget-id",a.id)}function Q(a){a.element.data("cke-widget-data", -encodeURIComponent(JSON.stringify(a.data)))}function N(){function a(){}function b(a,c,d){return d&&this.checkElement(a)?(a=d.widgets.getByElement(a,!0))&&a.checkStyleActive(this):!1}var c={};CKEDITOR.style.addCustomHandler({type:"widget",setup:function(a){this.widget=a.widget;if(this.group="string"==typeof a.group?[a.group]:a.group){a=this.widget;var b;c[a]||(c[a]={});for(var d=0,g=this.group.length;d<g;d++)b=this.group[d],c[a][b]||(c[a][b]=[]),c[a][b].push(this)}},apply:function(a){var b;a instanceof -CKEDITOR.editor&&this.checkApplicable(a.elementPath(),a)&&(b=a.widgets.focused,this.group&&this.removeStylesFromSameGroup(a),b.applyStyle(this))},remove:function(a){a instanceof CKEDITOR.editor&&this.checkApplicable(a.elementPath(),a)&&a.widgets.focused.removeStyle(this)},removeStylesFromSameGroup:function(a){var b,d,g=!1;if(!(a instanceof CKEDITOR.editor))return!1;d=a.elementPath();if(this.checkApplicable(d,a))for(var e=0,f=this.group.length;e<f;e++){b=c[this.widget][this.group[e]];for(var h=0;h< -b.length;h++)b[h]!==this&&b[h].checkActive(d,a)&&(a.widgets.focused.removeStyle(b[h]),g=!0)}return g},checkActive:function(a,b){return this.checkElementMatch(a.lastElement,0,b)},checkApplicable:function(a,b){return b instanceof CKEDITOR.editor?this.checkElement(a.lastElement):!1},checkElementMatch:b,checkElementRemovable:b,checkElement:function(a){return h.isDomWidgetWrapper(a)?(a=a.getFirst(h.isDomWidgetElement))&&a.data("widget")==this.widget:!1},buildPreview:function(a){return a||this._.definition.name}, -toAllowedContentRules:function(a){if(!a)return null;a=a.widgets.registered[this.widget];var b,c={};if(!a)return null;if(a.styleableElements){b=this.getClassesArray();if(!b)return null;c[a.styleableElements]={classes:b,propertiesOnly:!0};return c}return a.styleToAllowedContentRules?a.styleToAllowedContentRules(this):null},getClassesArray:function(){var a=this._.definition.attributes&&this._.definition.attributes["class"];return a?CKEDITOR.tools.trim(a).split(/\s+/):null},applyToRange:a,removeFromRange:a, -applyToObject:a})}CKEDITOR.plugins.add("widget",{requires:"lineutils,clipboard,widgetselection",onLoad:function(){void 0!==CKEDITOR.document.$.querySelectorAll&&(CKEDITOR.addCss(".cke_widget_wrapper{position:relative;outline:none}.cke_widget_inline{display:inline-block}.cke_widget_wrapper:hover\x3e.cke_widget_element{outline:2px solid #ffd25c;cursor:default}.cke_widget_wrapper:hover .cke_widget_editable{outline:2px solid #ffd25c}.cke_widget_wrapper.cke_widget_focused\x3e.cke_widget_element,.cke_widget_wrapper .cke_widget_editable.cke_widget_editable_focused{outline:2px solid #47a4f5}.cke_widget_editable{cursor:text}.cke_widget_drag_handler_container{position:absolute;width:15px;height:0;display:none;opacity:0.75;transition:height 0s 0.2s;line-height:0}.cke_widget_wrapper:hover\x3e.cke_widget_drag_handler_container{height:15px;transition:none}.cke_widget_drag_handler_container:hover{opacity:1}img.cke_widget_drag_handler{cursor:move;width:15px;height:15px;display:inline-block}.cke_widget_mask{position:absolute;top:0;left:0;width:100%;height:100%;display:block}.cke_editable.cke_widget_dragging, .cke_editable.cke_widget_dragging *{cursor:move !important}"), -N())},beforeInit:function(a){void 0!==CKEDITOR.document.$.querySelectorAll&&(a.widgets=new f(a))},afterInit:function(a){if(void 0!==CKEDITOR.document.$.querySelectorAll){var b=a.widgets.registered,c,d,g;for(d in b)c=b[d],(g=c.button)&&a.ui.addButton&&a.ui.addButton(CKEDITOR.tools.capitalize(c.name,!0),{label:g,command:c.name,toolbar:"insert,10"});u(a)}}});f.prototype={MIN_SELECTION_CHECK_INTERVAL:500,add:function(a,b){b=CKEDITOR.tools.prototypedCopy(b);b.name=a;b._=b._||{};this.editor.fire("widgetDefinition", -b);b.template&&(b.template=new CKEDITOR.template(b.template));k(this.editor,b);d(this,b);return this.registered[a]=b},addUpcastCallback:function(a){this._.upcastCallbacks.push(a)},checkSelection:function(){var a=this.editor.getSelection(),b=a.getSelectedElement(),c=E(this),d;if(b&&(d=this.getByElement(b,!0)))return c.focus(d).select(d).commit();a=a.getRanges()[0];if(!a||a.collapsed)return c.commit();a=new CKEDITOR.dom.walker(a);for(a.evaluator=h.isDomWidgetWrapper;b=a.next();)c.select(this.getByElement(b)); +0;"static"!=a&&(b.relativeY=c.y,b.relativeX=c.x,b.top-=b.relativeY,b.bottom-=b.relativeY,b.left-=b.relativeX,b.right-=b.relativeX);return b}};var m={left:1,right:1,center:1},b={absolute:1,fixed:1};CKEDITOR.plugins.lineutils={finder:f,locator:h,liner:e}}(),function(){function f(f){return f.getName&&!f.hasAttribute("data-cke-temp")}CKEDITOR.plugins.add("widgetselection",{init:function(f){if(CKEDITOR.env.webkit){var e=CKEDITOR.plugins.widgetselection;f.on("contentDom",function(f){f=f.editor;var d=f.editable(); +d.attachListener(d,"keydown",function(f){f.data.getKeystroke()==CKEDITOR.CTRL+65&&CKEDITOR.tools.setTimeout(function(){e.addFillers(d)||e.removeFillers(d)},0)},null,null,-1);f.on("selectionCheck",function(d){e.removeFillers(d.editor.editable())});f.on("paste",function(d){d.data.dataValue=e.cleanPasteData(d.data.dataValue)});"selectall"in f.plugins&&e.addSelectAllIntegration(f)})}}});CKEDITOR.plugins.widgetselection={startFiller:null,endFiller:null,fillerAttribute:"data-cke-filler-webkit",fillerContent:"\x26nbsp;", +fillerTagName:"div",addFillers:function(h){var e=h.editor;if(!this.isWholeContentSelected(h)&&0<h.getChildCount()){var k=h.getFirst(f),d=h.getLast(f);k&&k.type==CKEDITOR.NODE_ELEMENT&&!k.isEditable()&&(this.startFiller=this.createFiller(),h.append(this.startFiller,1));d&&d.type==CKEDITOR.NODE_ELEMENT&&!d.isEditable()&&(this.endFiller=this.createFiller(!0),h.append(this.endFiller,0));if(this.hasFiller(h))return e=e.createRange(),e.selectNodeContents(h),e.select(),!0}return!1},removeFillers:function(f){if(this.hasFiller(f)&& +!this.isWholeContentSelected(f)){var e=f.findOne(this.fillerTagName+"["+this.fillerAttribute+"\x3dstart]"),k=f.findOne(this.fillerTagName+"["+this.fillerAttribute+"\x3dend]");this.startFiller&&e&&this.startFiller.equals(e)?this.removeFiller(this.startFiller,f):this.startFiller=e;this.endFiller&&k&&this.endFiller.equals(k)?this.removeFiller(this.endFiller,f):this.endFiller=k}},cleanPasteData:function(f){f&&f.length&&(f=f.replace(this.createFillerRegex(),"").replace(this.createFillerRegex(!0),"")); +return f},isWholeContentSelected:function(f){var e=f.editor.getSelection().getRanges()[0];return!e||e&&e.collapsed?!1:(e=e.clone(),e.enlarge(CKEDITOR.ENLARGE_ELEMENT),!!(e&&f&&e.startContainer&&e.endContainer&&0===e.startOffset&&e.endOffset===f.getChildCount()&&e.startContainer.equals(f)&&e.endContainer.equals(f)))},hasFiller:function(f){return 0<f.find(this.fillerTagName+"["+this.fillerAttribute+"]").count()},createFiller:function(f){var e=new CKEDITOR.dom.element(this.fillerTagName);e.setHtml(this.fillerContent); +e.setAttribute(this.fillerAttribute,f?"end":"start");e.setAttribute("data-cke-temp",1);e.setStyles({display:"block",width:0,height:0,padding:0,border:0,margin:0,position:"absolute",top:0,left:"-9999px",opacity:0,overflow:"hidden"});return e},removeFiller:function(f,e){if(f){var k=e.editor,d=e.editor.getSelection().getRanges()[0].startPath(),l=k.createRange(),m,b;d.contains(f)&&(m=f.getHtml(),b=!0);d="start"==f.getAttribute(this.fillerAttribute);f.remove();m&&0<m.length&&m!=this.fillerContent?(e.insertHtmlIntoRange(m, +k.getSelection().getRanges()[0]),l.setStartAt(e.getChild(e.getChildCount()-1),CKEDITOR.POSITION_BEFORE_END),k.getSelection().selectRanges([l])):b&&(d?l.setStartAt(e.getFirst().getNext(),CKEDITOR.POSITION_AFTER_START):l.setEndAt(e.getLast().getPrevious(),CKEDITOR.POSITION_BEFORE_END),e.editor.getSelection().selectRanges([l]))}},createFillerRegex:function(f){var e=this.createFiller(f).getOuterHtml().replace(/style="[^"]*"/gi,'style\x3d"[^"]*"').replace(/>[^<]*</gi,"\x3e[^\x3c]*\x3c");return new RegExp((f? +"":"^")+e+(f?"$":""))},addSelectAllIntegration:function(f){var e=this;f.editable().attachListener(f,"beforeCommandExec",function(k){var d=f.editable();"selectAll"==k.data.name&&d&&e.addFillers(d)},null,null,9999)}}}(),"use strict",function(){function f(a){this.editor=a;this.registered={};this.instances={};this.selected=[];this.widgetHoldingFocusedEditable=this.focused=null;this._={nextId:0,upcasts:[],upcastCallbacks:[],filters:{}};I(this);z(this);this.on("checkWidgets",m);this.editor.on("contentDomInvalidated", +this.checkWidgets,this);x(this);B(this);u(this);C(this);y(this)}function h(a,b,c,d,e){var f=a.editor;CKEDITOR.tools.extend(this,d,{editor:f,id:b,inline:"span"==c.getParent().getName(),element:c,data:CKEDITOR.tools.extend({},"function"==typeof d.defaults?d.defaults():d.defaults),dataReady:!1,inited:!1,ready:!1,edit:h.prototype.edit,focusedEditable:null,definition:d,repository:a,draggable:!1!==d.draggable,_:{downcastFn:d.downcast&&"string"==typeof d.downcast?d.downcasts[d.downcast]:d.downcast}},!0); +a.fire("instanceCreated",this);Z(this,d);this.init&&this.init();this.inited=!0;(a=this.element.data("cke-widget-data"))&&this.setData(JSON.parse(decodeURIComponent(a)));e&&this.setData(e);this.data.classes||this.setData("classes",this.getClasses());this.dataReady=!0;Q(this);this.fire("data",this.data);this.isInited()&&f.editable().contains(this.wrapper)&&(this.ready=!0,this.fire("ready"))}function e(a,b,c){CKEDITOR.dom.element.call(this,b.$);this.editor=a;this._={};b=this.filter=c.filter;CKEDITOR.dtd[this.getName()].p? +(this.enterMode=b?b.getAllowedEnterMode(a.enterMode):a.enterMode,this.shiftEnterMode=b?b.getAllowedEnterMode(a.shiftEnterMode,!0):a.shiftEnterMode):this.enterMode=this.shiftEnterMode=CKEDITOR.ENTER_BR}function k(a,b){a.addCommand(b.name,{exec:function(a,c){function d(){a.widgets.finalizeCreation(h)}var e=a.widgets.focused;if(e&&e.name==b.name)e.edit();else if(b.insert)b.insert();else if(b.template){var e="function"==typeof b.defaults?b.defaults():b.defaults,e=CKEDITOR.dom.element.createFromHtml(b.template.output(e)), +f,g=a.widgets.wrapElement(e,b.name),h=new CKEDITOR.dom.documentFragment(g.getDocument());h.append(g);(f=a.widgets.initOn(e,b,c&&c.startupData))?(e=f.once("edit",function(b){if(b.data.dialog)f.once("dialog",function(b){b=b.data;var c,e;c=b.once("ok",d,null,null,20);e=b.once("cancel",function(b){b.data&&!1===b.data.hide||a.widgets.destroy(f,!0)});b.once("hide",function(){c.removeListener();e.removeListener()})});else d()},null,null,999),f.edit(),e.removeListener()):d()}},allowedContent:b.allowedContent, +requiredContent:b.requiredContent,contentForms:b.contentForms,contentTransformations:b.contentTransformations})}function d(a,b){function c(a,d){var e=b.upcast.split(","),f,g;for(g=0;g<e.length;g++)if(f=e[g],f===a.name)return b.upcasts[f].call(this,a,d);return!1}function d(b,c,e){var f=CKEDITOR.tools.getIndex(a._.upcasts,function(a){return a[2]>e});0>f&&(f=a._.upcasts.length);a._.upcasts.splice(f,0,[CKEDITOR.tools.bind(b,c),c.name,e])}var e=b.upcast,f=b.upcastPriority||10;e&&("string"==typeof e?d(c, +b,f):d(e,b,f))}function l(a,b){a.focused=null;if(b.isInited()){var c=b.editor.checkDirty();a.fire("widgetBlurred",{widget:b});b.setFocused(!1);!c&&b.editor.resetDirty()}}function m(a){a=a.data;if("wysiwyg"==this.editor.mode){var b=this.editor.editable(),c=this.instances,d,e,f,g;if(b){for(d in c)c[d].isReady()&&!b.contains(c[d].wrapper)&&this.destroy(c[d],!0);if(a&&a.initOnlyNew)c=this.initOnAll();else{var k=b.find(".cke_widget_wrapper"),c=[];d=0;for(e=k.count();d<e;d++){f=k.getItem(d);if(g=!this.getByElement(f, +!0)){a:{g=p;for(var l=f;l=l.getParent();)if(g(l)){g=!0;break a}g=!1}g=!g}g&&b.contains(f)&&(f.addClass("cke_widget_new"),c.push(this.initOn(f.getFirst(h.isDomWidgetElement))))}}a&&a.focusInited&&1==c.length&&c[0].focus()}}}function b(a){if("undefined"!=typeof a.attributes&&a.attributes["data-widget"]){var b=g(a),d=c(a),e=!1;b&&b.value&&b.value.match(/^\s/g)&&(b.parent.attributes["data-cke-white-space-first"]=1,b.value=b.value.replace(/^\s/g,"\x26nbsp;"),e=!0);d&&d.value&&d.value.match(/\s$/g)&&(d.parent.attributes["data-cke-white-space-last"]= +1,d.value=d.value.replace(/\s$/g,"\x26nbsp;"),e=!0);e&&(a.attributes["data-cke-widget-white-space"]=1)}}function g(a){return a.find(function(a){return 3===a.type},!0).shift()}function c(a){return a.find(function(a){return 3===a.type},!0).pop()}function a(a,b,c){if(!c.allowedContent&&!c.disallowedContent)return null;var d=this._.filters[a];d||(this._.filters[a]=d={});a=d[b];a||(a=c.allowedContent?new CKEDITOR.filter(c.allowedContent):this.editor.filter.clone(),d[b]=a,c.disallowedContent&&a.disallow(c.disallowedContent)); +return a}function n(a){var b=[],c=a._.upcasts,d=a._.upcastCallbacks;return{toBeWrapped:b,iterator:function(a){var e,f,g,k,l;if("data-cke-widget-wrapper"in a.attributes)return(a=a.getFirst(h.isParserWidgetElement))&&b.push([a]),!1;if("data-widget"in a.attributes)return b.push([a]),!1;if(l=c.length){if(a.attributes["data-cke-widget-upcasted"])return!1;k=0;for(e=d.length;k<e;++k)if(!1===d[k](a))return;for(k=0;k<l;++k)if(e=c[k],g={},f=e[0](a,g))return f instanceof CKEDITOR.htmlParser.element&&(a=f),a.attributes["data-cke-widget-data"]= +encodeURIComponent(JSON.stringify(g)),a.attributes["data-cke-widget-upcasted"]=1,b.push([a,e[1]]),!1}}}}function w(a,b){return{tabindex:-1,contenteditable:"false","data-cke-widget-wrapper":1,"data-cke-filter":"off","class":"cke_widget_wrapper cke_widget_new cke_widget_"+(a?"inline":"block")+(b?" cke_widget_"+b:"")}}function v(a,b,c){if(a.type==CKEDITOR.NODE_ELEMENT){var d=CKEDITOR.dtd[a.name];if(d&&!d[c.name]){var d=a.split(b),e=a.parent;b=d.getIndex();a.children.length||(--b,a.remove());d.children.length|| +d.remove();return v(e,b,c)}}a.add(c,b)}function t(a,b){return"boolean"==typeof a.inline?a.inline:!!CKEDITOR.dtd.$inline[b]}function p(a){return a.hasAttribute("data-cke-temp")}function q(a,b,c,d){var e=a.editor;e.fire("lockSnapshot");c?(d=c.data("cke-widget-editable"),d=b.editables[d],a.widgetHoldingFocusedEditable=b,b.focusedEditable=d,c.addClass("cke_widget_editable_focused"),d.filter&&e.setActiveFilter(d.filter),e.setActiveEnterMode(d.enterMode,d.shiftEnterMode)):(d||b.focusedEditable.removeClass("cke_widget_editable_focused"), +b.focusedEditable=null,a.widgetHoldingFocusedEditable=null,e.setActiveFilter(null),e.setActiveEnterMode(null,null));e.fire("unlockSnapshot")}function A(a){a.contextMenu&&a.contextMenu.addListener(function(b){if(b=a.widgets.getByElement(b,!0))return b.fire("contextMenu",{})})}function r(a,b){return CKEDITOR.tools.trim(b)}function C(a){var b=a.editor,c=CKEDITOR.plugins.lineutils;b.on("dragstart",function(c){var d=c.data.target;h.isDomDragHandler(d)&&(d=a.getByElement(d),c.data.dataTransfer.setData("cke/widget-id", +d.id),b.focus(),d.focus())});b.on("drop",function(c){var d=c.data.dataTransfer,e=d.getData("cke/widget-id"),f=d.getTransferType(b),d=b.createRange();""!==e&&f===CKEDITOR.DATA_TRANSFER_CROSS_EDITORS?c.cancel():""!==e&&f==CKEDITOR.DATA_TRANSFER_INTERNAL&&(e=a.instances[e])&&(d.setStartBefore(e.wrapper),d.setEndAfter(e.wrapper),c.data.dragRange=d,delete CKEDITOR.plugins.clipboard.dragStartContainerChildCount,delete CKEDITOR.plugins.clipboard.dragEndContainerChildCount,c.data.dataTransfer.setData("text/html", +b.editable().getHtmlFromRange(d).getHtml()),b.widgets.destroy(e,!0))});b.on("contentDom",function(){var d=b.editable();CKEDITOR.tools.extend(a,{finder:new c.finder(b,{lookups:{"default":function(b){if(!b.is(CKEDITOR.dtd.$listItem)&&b.is(CKEDITOR.dtd.$block)&&!h.isDomNestedEditable(b)&&!a._.draggedWidget.wrapper.contains(b)){var c=h.getNestedEditable(d,b);if(c){b=a._.draggedWidget;if(a.getByElement(c)==b)return;c=CKEDITOR.filter.instances[c.data("cke-filter")];b=b.requiredContent;if(c&&b&&!c.check(b))return}return CKEDITOR.LINEUTILS_BEFORE| +CKEDITOR.LINEUTILS_AFTER}}}}),locator:new c.locator(b),liner:new c.liner(b,{lineStyle:{cursor:"move !important","border-top-color":"#666"},tipLeftStyle:{"border-left-color":"#666"},tipRightStyle:{"border-right-color":"#666"}})},!0)})}function B(a){var b=a.editor;b.on("contentDom",function(){var c=b.editable(),d=c.isInline()?c:b.document,e,f;c.attachListener(d,"mousedown",function(c){var d=c.data.getTarget();e=d instanceof CKEDITOR.dom.element?a.getByElement(d):null;f=0;e&&(e.inline&&d.type==CKEDITOR.NODE_ELEMENT&& +d.hasAttribute("data-cke-widget-drag-handler")?(f=1,a.focused!=e&&b.getSelection().removeAllRanges()):h.getNestedEditable(e.wrapper,d)?e=null:(c.data.preventDefault(),CKEDITOR.env.ie||e.focus()))});c.attachListener(d,"mouseup",function(){f&&e&&e.wrapper&&(f=0,e.focus())});CKEDITOR.env.ie&&c.attachListener(d,"mouseup",function(){setTimeout(function(){e&&e.wrapper&&c.contains(e.wrapper)&&(e.focus(),e=null)})})});b.on("doubleclick",function(b){var c=a.getByElement(b.data.element);if(c&&!h.getNestedEditable(c.wrapper, +b.data.element))return c.fire("doubleclick",{element:b.data.element})},null,null,1)}function u(a){a.editor.on("key",function(b){var c=a.focused,d=a.widgetHoldingFocusedEditable,e;c?e=c.fire("key",{keyCode:b.data.keyCode}):d&&(c=b.data.keyCode,b=d.focusedEditable,c==CKEDITOR.CTRL+65?(c=b.getBogus(),d=d.editor.createRange(),d.selectNodeContents(b),c&&d.setEndAt(c,CKEDITOR.POSITION_BEFORE_START),d.select(),e=!1):8==c||46==c?(e=d.editor.getSelection().getRanges(),d=e[0],e=!(1==e.length&&d.collapsed&& +d.checkBoundaryOfElement(b,CKEDITOR[8==c?"START":"END"]))):e=void 0);return e},null,null,1)}function y(a){function b(c){a.focused&&G(a.focused,"cut"==c.name)}var c=a.editor;c.on("contentDom",function(){var a=c.editable();a.attachListener(a,"copy",b);a.attachListener(a,"cut",b)})}function x(a){var b=a.editor;b.on("selectionCheck",function(){a.fire("checkSelection")});a.on("checkSelection",a.checkSelection,a);b.on("selectionChange",function(c){var d=(c=h.getNestedEditable(b.editable(),c.data.selection.getStartElement()))&& +a.getByElement(c),e=a.widgetHoldingFocusedEditable;e?e===d&&e.focusedEditable.equals(c)||(q(a,e,null),d&&c&&q(a,d,c)):d&&c&&q(a,d,c)});b.on("dataReady",function(){F(a).commit()});b.on("blur",function(){var b;(b=a.focused)&&l(a,b);(b=a.widgetHoldingFocusedEditable)&&q(a,b,null)})}function z(a){var b=a.editor,d={};b.on("toDataFormat",function(b){var e=CKEDITOR.tools.getNextNumber(),f=[];b.data.downcastingSessionId=e;d[e]=f;b.data.dataValue.forEach(function(b){var d=b.attributes,e;if("data-cke-widget-white-space"in +d){e=g(b);var k=c(b);e.parent.attributes["data-cke-white-space-first"]&&(e.value=e.value.replace(/^ /g," "));k.parent.attributes["data-cke-white-space-last"]&&(k.value=k.value.replace(/ $/g," "))}if("data-cke-widget-id"in d){if(d=a.instances[d["data-cke-widget-id"]])e=b.getFirst(h.isParserWidgetElement),f.push({wrapper:b,element:e,widget:d,editables:{}}),"1"!=e.attributes["data-cke-widget-keep-attr"]&&delete e.attributes["data-widget"]}else if("data-cke-widget-editable"in d)return f[f.length- +1].editables[d["data-cke-widget-editable"]]=b,!1},CKEDITOR.NODE_ELEMENT,!0)},null,null,8);b.on("toDataFormat",function(a){if(a.data.downcastingSessionId){a=d[a.data.downcastingSessionId];for(var b,c,e,f,g,h;b=a.shift();){c=b.widget;e=b.element;f=c._.downcastFn&&c._.downcastFn.call(c,e);for(h in b.editables)g=b.editables[h],delete g.attributes.contenteditable,g.setHtml(c.editables[h].getData());f||(f=e);b.wrapper.replaceWith(f)}}},null,null,13);b.on("contentDomUnload",function(){a.destroyAll(!0)})} +function I(a){var b=a.editor,c,d;b.on("toHtml",function(b){var d=n(a),e;for(b.data.dataValue.forEach(d.iterator,CKEDITOR.NODE_ELEMENT,!0);e=d.toBeWrapped.pop();){var f=e[0],g=f.parent;g.type==CKEDITOR.NODE_ELEMENT&&g.attributes["data-cke-widget-wrapper"]&&g.replaceWith(f);a.wrapElement(e[0],e[1])}c=b.data.protectedWhitespaces?3==b.data.dataValue.children.length&&h.isParserWidgetWrapper(b.data.dataValue.children[1]):1==b.data.dataValue.children.length&&h.isParserWidgetWrapper(b.data.dataValue.children[0])}, +null,null,8);b.on("dataReady",function(){if(d)for(var c=b.editable().find(".cke_widget_wrapper"),e,f,g=0,k=c.count();g<k;++g)e=c.getItem(g),f=e.getFirst(h.isDomWidgetElement),f.type==CKEDITOR.NODE_ELEMENT&&f.data("widget")?(f.replace(e),a.wrapElement(f)):e.remove();d=0;a.destroyAll(!0);a.initOnAll()});b.on("loadSnapshot",function(b){/data-cke-widget/.test(b.data)&&(d=1);a.destroyAll(!0)},null,null,9);b.on("paste",function(a){a=a.data;a.dataValue=a.dataValue.replace(V,r);a.range&&(a=h.getNestedEditable(b.editable(), +a.range.startContainer))&&(a=CKEDITOR.filter.instances[a.data("cke-filter")])&&b.setActiveFilter(a)});b.on("afterInsertHtml",function(d){d.data.intoRange?a.checkWidgets({initOnlyNew:!0}):(b.fire("lockSnapshot"),a.checkWidgets({initOnlyNew:!0,focusInited:c}),b.fire("unlockSnapshot"))})}function F(a){var b=a.selected,c=[],d=b.slice(0),e=null;return{select:function(a){0>CKEDITOR.tools.indexOf(b,a)&&c.push(a);a=CKEDITOR.tools.indexOf(d,a);0<=a&&d.splice(a,1);return this},focus:function(a){e=a;return this}, +commit:function(){var f=a.focused!==e,g,h;a.editor.fire("lockSnapshot");for(f&&(g=a.focused)&&l(a,g);g=d.pop();)b.splice(CKEDITOR.tools.indexOf(b,g),1),g.isInited()&&(h=g.editor.checkDirty(),g.setSelected(!1),!h&&g.editor.resetDirty());f&&e&&(h=a.editor.checkDirty(),a.focused=e,a.fire("widgetFocused",{widget:e}),e.setFocused(!0),!h&&a.editor.resetDirty());for(;g=c.pop();)b.push(g),g.setSelected(!0);a.editor.fire("unlockSnapshot")}}}function E(a,b,c){var d=0;b=L(b);var e=a.data.classes||{},f;if(b){for(e= +CKEDITOR.tools.clone(e);f=b.pop();)c?e[f]||(d=e[f]=1):e[f]&&(delete e[f],d=1);d&&a.setData("classes",e)}}function H(a){a.cancel()}function G(a,b){var c=a.editor,d=c.document,e=CKEDITOR.env.edge&&16<=CKEDITOR.env.version;if(!d.getById("cke_copybin")){var f=!c.blockless&&!CKEDITOR.env.ie||e?"div":"span",e=d.createElement(f),g=d.createElement(f),f=CKEDITOR.env.ie&&9>CKEDITOR.env.version;g.setAttributes({id:"cke_copybin","data-cke-temp":"1"});e.setStyles({position:"absolute",width:"1px",height:"1px", +overflow:"hidden"});e.setStyle("ltr"==c.config.contentsLangDirection?"left":"right","-5000px");var h=c.createRange();h.setStartBefore(a.wrapper);h.setEndAfter(a.wrapper);e.setHtml('\x3cspan data-cke-copybin-start\x3d"1"\x3e\x3c/span\x3e'+c.editable().getHtmlFromRange(h).getHtml()+'\x3cspan data-cke-copybin-end\x3d"1"\x3e\x3c/span\x3e');c.fire("saveSnapshot");c.fire("lockSnapshot");g.append(e);c.editable().append(g);var k=c.on("selectionChange",H,null,null,0),l=a.repository.on("checkSelection",H, +null,null,0);if(f)var m=d.getDocumentElement().$,q=m.scrollTop;h=c.createRange();h.selectNodeContents(e);h.select();f&&(m.scrollTop=q);setTimeout(function(){b||a.focus();g.remove();k.removeListener();l.removeListener();c.fire("unlockSnapshot");b&&!c.readOnly&&(a.repository.del(a),c.fire("saveSnapshot"))},100)}}function L(a){return(a=(a=a.getDefinition().attributes)&&a["class"])?a.split(/\s+/):null}function O(){var a=CKEDITOR.document.getActive(),b=this.editor,c=b.editable();(c.isInline()?c:b.document.getWindow().getFrame()).equals(a)&& +b.focusManager.focus(c)}function D(){CKEDITOR.env.gecko&&this.editor.unlockSelection();CKEDITOR.env.webkit||(this.editor.forceNextSelectionCheck(),this.editor.selectionChange(1))}function S(a){var b=null;a.on("data",function(){var a=this.data.classes,c;if(b!=a){for(c in b)a&&a[c]||this.removeClass(c);for(c in a)this.addClass(c);b=a}})}function J(a){a.on("data",function(){if(a.wrapper){var b=this.getLabel?this.getLabel():this.editor.lang.widget.label.replace(/%1/,this.pathName||this.element.getName()); +a.wrapper.setAttribute("role","region");a.wrapper.setAttribute("aria-label",b)}},null,null,9999)}function R(a){if(a.draggable){var b=a.editor,c=a.wrapper.getLast(h.isDomDragHandlerContainer),d;c?d=c.findOne("img"):(c=new CKEDITOR.dom.element("span",b.document),c.setAttributes({"class":"cke_reset cke_widget_drag_handler_container",style:"background:rgba(220,220,220,0.5);background-image:url("+b.plugins.widget.path+"images/handle.png)"}),d=new CKEDITOR.dom.element("img",b.document),d.setAttributes({"class":"cke_reset cke_widget_drag_handler", +"data-cke-widget-drag-handler":"1",src:CKEDITOR.tools.transparentImageData,width:15,title:b.lang.widget.move,height:15,role:"presentation"}),a.inline&&d.setAttribute("draggable","true"),c.append(d),a.wrapper.append(c));a.wrapper.on("dragover",function(a){a.data.preventDefault()});a.wrapper.on("mouseenter",a.updateDragHandlerPosition,a);setTimeout(function(){a.on("data",a.updateDragHandlerPosition,a)},50);if(!a.inline&&(d.on("mousedown",K,a),CKEDITOR.env.ie&&9>CKEDITOR.env.version))d.on("dragstart", +function(a){a.data.preventDefault(!0)});a.dragHandlerContainer=c}}function K(a){function b(){var c;for(r.reset();c=h.pop();)c.removeListener();var d=k;c=a.sender;var e=this.repository.finder,f=this.repository.liner,g=this.editor,l=this.editor.editable();CKEDITOR.tools.isEmpty(f.visible)||(d=e.getRange(d[0]),this.focus(),g.fire("drop",{dropRange:d,target:d.startContainer}));l.removeClass("cke_widget_dragging");f.hideVisible();g.fire("dragend",{target:c})}if(CKEDITOR.tools.getMouseButton(a)===CKEDITOR.MOUSE_BUTTON_LEFT){var c= +this.repository.finder,d=this.repository.locator,e=this.repository.liner,f=this.editor,g=f.editable(),h=[],k=[],l,m;this.repository._.draggedWidget=this;var q=c.greedySearch(),r=CKEDITOR.tools.eventsBuffer(50,function(){l=d.locate(q);k=d.sort(m,1);k.length&&(e.prepare(q,l),e.placeLine(k[0]),e.cleanup())});g.addClass("cke_widget_dragging");h.push(g.on("mousemove",function(a){m=a.data.$.clientY;r.input()}));f.fire("dragstart",{target:a.sender});h.push(f.document.once("mouseup",b,this));g.isInline()|| +h.push(CKEDITOR.document.once("mouseup",b,this))}}function U(a){var b,c,d=a.editables;a.editables={};if(a.editables)for(b in d)c=d[b],a.initEditable(b,"string"==typeof c?{selector:c}:c)}function X(a){if(a.mask){var b=a.wrapper.findOne(".cke_widget_mask");b||(b=new CKEDITOR.dom.element("img",a.editor.document),b.setAttributes({src:CKEDITOR.tools.transparentImageData,"class":"cke_reset cke_widget_mask"}),a.wrapper.append(b));a.mask=b}}function Y(a){if(a.parts){var b={},c,d;for(d in a.parts)c=a.wrapper.findOne(a.parts[d]), +b[d]=c;a.parts=b}}function Z(a,b){M(a);Y(a);U(a);X(a);R(a);S(a);J(a);if(CKEDITOR.env.ie&&9>CKEDITOR.env.version)a.wrapper.on("dragstart",function(b){var c=b.data.getTarget();h.getNestedEditable(a,c)||a.inline&&h.isDomDragHandler(c)||b.data.preventDefault()});a.wrapper.removeClass("cke_widget_new");a.element.addClass("cke_widget_element");a.on("key",function(b){b=b.data.keyCode;if(13==b)a.edit();else{if(b==CKEDITOR.CTRL+67||b==CKEDITOR.CTRL+88){G(a,b==CKEDITOR.CTRL+88);return}if(b in T||CKEDITOR.CTRL& +b||CKEDITOR.ALT&b)return}return!1},null,null,999);a.on("doubleclick",function(b){a.edit()&&b.cancel()});if(b.data)a.on("data",b.data);if(b.edit)a.on("edit",b.edit)}function M(a){(a.wrapper=a.element.getParent()).setAttribute("data-cke-widget-id",a.id)}function Q(a){a.element.data("cke-widget-data",encodeURIComponent(JSON.stringify(a.data)))}function N(){function a(){}function b(a,c,d){return d&&this.checkElement(a)?(a=d.widgets.getByElement(a,!0))&&a.checkStyleActive(this):!1}var c={};CKEDITOR.style.addCustomHandler({type:"widget", +setup:function(a){this.widget=a.widget;if(this.group="string"==typeof a.group?[a.group]:a.group){a=this.widget;var b;c[a]||(c[a]={});for(var d=0,e=this.group.length;d<e;d++)b=this.group[d],c[a][b]||(c[a][b]=[]),c[a][b].push(this)}},apply:function(a){var b;a instanceof CKEDITOR.editor&&this.checkApplicable(a.elementPath(),a)&&(b=a.widgets.focused,this.group&&this.removeStylesFromSameGroup(a),b.applyStyle(this))},remove:function(a){a instanceof CKEDITOR.editor&&this.checkApplicable(a.elementPath(), +a)&&a.widgets.focused.removeStyle(this)},removeStylesFromSameGroup:function(a){var b,d,e=!1;if(!(a instanceof CKEDITOR.editor))return!1;d=a.elementPath();if(this.checkApplicable(d,a))for(var f=0,g=this.group.length;f<g;f++){b=c[this.widget][this.group[f]];for(var h=0;h<b.length;h++)b[h]!==this&&b[h].checkActive(d,a)&&(a.widgets.focused.removeStyle(b[h]),e=!0)}return e},checkActive:function(a,b){return this.checkElementMatch(a.lastElement,0,b)},checkApplicable:function(a,b){return b instanceof CKEDITOR.editor? +this.checkElement(a.lastElement):!1},checkElementMatch:b,checkElementRemovable:b,checkElement:function(a){return h.isDomWidgetWrapper(a)?(a=a.getFirst(h.isDomWidgetElement))&&a.data("widget")==this.widget:!1},buildPreview:function(a){return a||this._.definition.name},toAllowedContentRules:function(a){if(!a)return null;a=a.widgets.registered[this.widget];var b,c={};if(!a)return null;if(a.styleableElements){b=this.getClassesArray();if(!b)return null;c[a.styleableElements]={classes:b,propertiesOnly:!0}; +return c}return a.styleToAllowedContentRules?a.styleToAllowedContentRules(this):null},getClassesArray:function(){var a=this._.definition.attributes&&this._.definition.attributes["class"];return a?CKEDITOR.tools.trim(a).split(/\s+/):null},applyToRange:a,removeFromRange:a,applyToObject:a})}CKEDITOR.plugins.add("widget",{requires:"lineutils,clipboard,widgetselection",onLoad:function(){void 0!==CKEDITOR.document.$.querySelectorAll&&(CKEDITOR.addCss(".cke_widget_wrapper{position:relative;outline:none}.cke_widget_inline{display:inline-block}.cke_widget_wrapper:hover\x3e.cke_widget_element{outline:2px solid #ffd25c;cursor:default}.cke_widget_wrapper:hover .cke_widget_editable{outline:2px solid #ffd25c}.cke_widget_wrapper.cke_widget_focused\x3e.cke_widget_element,.cke_widget_wrapper .cke_widget_editable.cke_widget_editable_focused{outline:2px solid #47a4f5}.cke_widget_editable{cursor:text}.cke_widget_drag_handler_container{position:absolute;width:15px;height:0;display:none;opacity:0.75;transition:height 0s 0.2s;line-height:0}.cke_widget_wrapper:hover\x3e.cke_widget_drag_handler_container{height:15px;transition:none}.cke_widget_drag_handler_container:hover{opacity:1}img.cke_widget_drag_handler{cursor:move;width:15px;height:15px;display:inline-block}.cke_widget_mask{position:absolute;top:0;left:0;width:100%;height:100%;display:block}.cke_editable.cke_widget_dragging, .cke_editable.cke_widget_dragging *{cursor:move !important}"), +N())},beforeInit:function(a){void 0!==CKEDITOR.document.$.querySelectorAll&&(a.widgets=new f(a))},afterInit:function(a){if(void 0!==CKEDITOR.document.$.querySelectorAll){var b=a.widgets.registered,c,d,e;for(d in b)c=b[d],(e=c.button)&&a.ui.addButton&&a.ui.addButton(CKEDITOR.tools.capitalize(c.name,!0),{label:e,command:c.name,toolbar:"insert,10"});A(a)}}});f.prototype={MIN_SELECTION_CHECK_INTERVAL:500,add:function(a,b){b=CKEDITOR.tools.prototypedCopy(b);b.name=a;b._=b._||{};this.editor.fire("widgetDefinition", +b);b.template&&(b.template=new CKEDITOR.template(b.template));k(this.editor,b);d(this,b);return this.registered[a]=b},addUpcastCallback:function(a){this._.upcastCallbacks.push(a)},checkSelection:function(){var a=this.editor.getSelection(),b=a.getSelectedElement(),c=F(this),d;if(b&&(d=this.getByElement(b,!0)))return c.focus(d).select(d).commit();a=a.getRanges()[0];if(!a||a.collapsed)return c.commit();a=new CKEDITOR.dom.walker(a);for(a.evaluator=h.isDomWidgetWrapper;b=a.next();)c.select(this.getByElement(b)); c.commit()},checkWidgets:function(a){this.fire("checkWidgets",CKEDITOR.tools.copy(a||{}))},del:function(a){if(this.focused===a){var b=a.editor,c=b.createRange(),d;(d=c.moveToClosestEditablePosition(a.wrapper,!0))||(d=c.moveToClosestEditablePosition(a.wrapper,!1));d&&b.getSelection().selectRanges([c])}a.wrapper.remove();this.destroy(a,!0)},destroy:function(a,b){this.widgetHoldingFocusedEditable===a&&q(this,a,null,b);a.destroy(b);delete this.instances[a.id];this.fire("instanceDestroyed",a)},destroyAll:function(a, -b){var c,d,g=this.instances;if(b&&!a){d=b.find(".cke_widget_wrapper");for(var g=d.count(),e=0;e<g;++e)(c=this.getByElement(d.getItem(e),!0))&&this.destroy(c)}else for(d in g)c=g[d],this.destroy(c,a)},finalizeCreation:function(a){(a=a.getFirst())&&h.isDomWidgetWrapper(a)&&(this.editor.insertElement(a),a=this.getByElement(a),a.ready=!0,a.fire("ready"),a.focus())},getByElement:function(){function a(c){return c.is(b)&&c.data("cke-widget-id")}var b={div:1,span:1};return function(b,c){if(!b)return null; -var d=a(b);if(!c&&!d){var g=this.editor.editable();do b=b.getParent();while(b&&!b.equals(g)&&!(d=a(b)))}return this.instances[d]||null}}(),initOn:function(a,b,c){b?"string"==typeof b&&(b=this.registered[b]):b=this.registered[a.data("widget")];if(!b)return null;var d=this.wrapElement(a,b.name);return d?d.hasClass("cke_widget_new")?(a=new h(this,this._.nextId++,a,b,c),a.isInited()?this.instances[a.id]=a:null):this.getByElement(a):null},initOnAll:function(a){a=(a||this.editor.editable()).find(".cke_widget_new"); +b){var c,d,e=this.instances;if(b&&!a){d=b.find(".cke_widget_wrapper");for(var e=d.count(),f=0;f<e;++f)(c=this.getByElement(d.getItem(f),!0))&&this.destroy(c)}else for(d in e)c=e[d],this.destroy(c,a)},finalizeCreation:function(a){(a=a.getFirst())&&h.isDomWidgetWrapper(a)&&(this.editor.insertElement(a),a=this.getByElement(a),a.ready=!0,a.fire("ready"),a.focus())},getByElement:function(){function a(c){return c.is(b)&&c.data("cke-widget-id")}var b={div:1,span:1};return function(b,c){if(!b)return null; +var d=a(b);if(!c&&!d){var e=this.editor.editable();do b=b.getParent();while(b&&!b.equals(e)&&!(d=a(b)))}return this.instances[d]||null}}(),initOn:function(a,b,c){b?"string"==typeof b&&(b=this.registered[b]):b=this.registered[a.data("widget")];if(!b)return null;var d=this.wrapElement(a,b.name);return d?d.hasClass("cke_widget_new")?(a=new h(this,this._.nextId++,a,b,c),a.isInited()?this.instances[a.id]=a:null):this.getByElement(a):null},initOnAll:function(a){a=(a||this.editor.editable()).find(".cke_widget_new"); for(var b=[],c,d=a.count();d--;)(c=this.initOn(a.getItem(d).getFirst(h.isDomWidgetElement)))&&b.push(c);return b},onWidget:function(a){var b=Array.prototype.slice.call(arguments);b.shift();for(var c in this.instances){var d=this.instances[c];d.name==a&&d.on.apply(d,b)}this.on("instanceCreated",function(c){c=c.data;c.name==a&&c.on.apply(c,b)})},parseElementClasses:function(a){if(!a)return null;a=CKEDITOR.tools.trim(a).split(/\s+/);for(var b,c={},d=0;b=a.pop();)-1==b.indexOf("cke_")&&(c[b]=d=1);return d? -c:null},wrapElement:function(a,c){var d=null,g,e;if(a instanceof CKEDITOR.dom.element){c=c||a.data("widget");g=this.registered[c];if(!g)return null;if((d=a.getParent())&&d.type==CKEDITOR.NODE_ELEMENT&&d.data("cke-widget-wrapper"))return d;a.hasAttribute("data-cke-widget-keep-attr")||a.data("cke-widget-keep-attr",a.data("widget")?1:0);a.data("widget",c);(e=p(g,a.getName()))&&b(a);d=new CKEDITOR.dom.element(e?"span":"div");d.setAttributes(w(e,c));d.data("cke-display-name",g.pathName?g.pathName:a.getName()); -a.getParent(!0)&&d.replace(a);a.appendTo(d)}else if(a instanceof CKEDITOR.htmlParser.element){c=c||a.attributes["data-widget"];g=this.registered[c];if(!g)return null;if((d=a.parent)&&d.type==CKEDITOR.NODE_ELEMENT&&d.attributes["data-cke-widget-wrapper"])return d;"data-cke-widget-keep-attr"in a.attributes||(a.attributes["data-cke-widget-keep-attr"]=a.attributes["data-widget"]?1:0);c&&(a.attributes["data-widget"]=c);(e=p(g,a.name))&&b(a);d=new CKEDITOR.htmlParser.element(e?"span":"div",w(e,c));d.attributes["data-cke-display-name"]= -g.pathName?g.pathName:a.name;g=a.parent;var f;g&&(f=a.getIndex(),a.remove());d.add(a);g&&v(g,f,d)}return d},_tests_createEditableFilter:a};CKEDITOR.event.implementOn(f.prototype);h.prototype={addClass:function(a){this.element.addClass(a);this.wrapper.addClass(h.WRAPPER_CLASS_PREFIX+a)},applyStyle:function(a){F(this,a,1)},checkStyleActive:function(a){a=L(a);var b;if(!a)return!1;for(;b=a.pop();)if(!this.hasClass(b))return!1;return!0},destroy:function(a){this.fire("destroy");if(this.editables)for(var b in this.editables)this.destroyEditable(b, -a);a||("0"==this.element.data("cke-widget-keep-attr")&&this.element.removeAttribute("data-widget"),this.element.removeAttributes(["data-cke-widget-data","data-cke-widget-keep-attr"]),this.element.removeClass("cke_widget_element"),this.element.replace(this.wrapper));this.wrapper=null},destroyEditable:function(a,b){var c=this.editables[a];c.removeListener("focus",C);c.removeListener("blur",O);this.editor.focusManager.remove(c);b||(this.repository.destroyAll(!1,c),c.removeClass("cke_widget_editable"), +c:null},wrapElement:function(a,c){var d=null,e,f;if(a instanceof CKEDITOR.dom.element){c=c||a.data("widget");e=this.registered[c];if(!e)return null;if((d=a.getParent())&&d.type==CKEDITOR.NODE_ELEMENT&&d.data("cke-widget-wrapper"))return d;a.hasAttribute("data-cke-widget-keep-attr")||a.data("cke-widget-keep-attr",a.data("widget")?1:0);a.data("widget",c);(f=t(e,a.getName()))&&b(a);d=new CKEDITOR.dom.element(f?"span":"div");d.setAttributes(w(f,c));d.data("cke-display-name",e.pathName?e.pathName:a.getName()); +a.getParent(!0)&&d.replace(a);a.appendTo(d)}else if(a instanceof CKEDITOR.htmlParser.element){c=c||a.attributes["data-widget"];e=this.registered[c];if(!e)return null;if((d=a.parent)&&d.type==CKEDITOR.NODE_ELEMENT&&d.attributes["data-cke-widget-wrapper"])return d;"data-cke-widget-keep-attr"in a.attributes||(a.attributes["data-cke-widget-keep-attr"]=a.attributes["data-widget"]?1:0);c&&(a.attributes["data-widget"]=c);(f=t(e,a.name))&&b(a);d=new CKEDITOR.htmlParser.element(f?"span":"div",w(f,c));d.attributes["data-cke-display-name"]= +e.pathName?e.pathName:a.name;e=a.parent;var g;e&&(g=a.getIndex(),a.remove());d.add(a);e&&v(e,g,d)}return d},_tests_createEditableFilter:a};CKEDITOR.event.implementOn(f.prototype);h.prototype={addClass:function(a){this.element.addClass(a);this.wrapper.addClass(h.WRAPPER_CLASS_PREFIX+a)},applyStyle:function(a){E(this,a,1)},checkStyleActive:function(a){a=L(a);var b;if(!a)return!1;for(;b=a.pop();)if(!this.hasClass(b))return!1;return!0},destroy:function(a){this.fire("destroy");if(this.editables)for(var b in this.editables)this.destroyEditable(b, +a);a||("0"==this.element.data("cke-widget-keep-attr")&&this.element.removeAttribute("data-widget"),this.element.removeAttributes(["data-cke-widget-data","data-cke-widget-keep-attr"]),this.element.removeClass("cke_widget_element"),this.element.replace(this.wrapper));this.wrapper=null},destroyEditable:function(a,b){var c=this.editables[a];c.removeListener("focus",D);c.removeListener("blur",O);this.editor.focusManager.remove(c);b||(this.repository.destroyAll(!1,c),c.removeClass("cke_widget_editable"), c.removeClass("cke_widget_editable_focused"),c.removeAttributes(["contenteditable","data-cke-widget-editable","data-cke-enter-mode"]));delete this.editables[a]},edit:function(){var a={dialog:this.dialog},b=this;if(!1===this.fire("edit",a)||!a.dialog)return!1;this.editor.openDialog(a.dialog,function(a){var c,d;!1!==b.fire("dialog",a)&&(c=a.on("show",function(){a.setupContent(b)}),d=a.on("ok",function(){var c,d=b.on("data",function(a){c=1;a.cancel()},null,null,0);b.editor.fire("saveSnapshot");a.commitContent(b); d.removeListener();c&&(b.fire("data",b.data),b.editor.fire("saveSnapshot"))}),a.once("hide",function(){c.removeListener();d.removeListener()}))});return!0},getClasses:function(){return this.repository.parseElementClasses(this.element.getAttribute("class"))},hasClass:function(a){return this.element.hasClass(a)},initEditable:function(b,c){var d=this._findOneNotNested(c.selector);return d&&d.is(CKEDITOR.dtd.$editable)?(d=new e(this.editor,d,{filter:a.call(this.repository,this.name,b,c)}),this.editables[b]= -d,d.setAttributes({contenteditable:"true","data-cke-widget-editable":b,"data-cke-enter-mode":d.enterMode}),d.filter&&d.data("cke-filter",d.filter.id),d.addClass("cke_widget_editable"),d.removeClass("cke_widget_editable_focused"),c.pathName&&d.data("cke-display-name",c.pathName),this.editor.focusManager.add(d),d.on("focus",C,this),CKEDITOR.env.ie&&d.on("blur",O,this),d._.initialSetData=!0,d.setData(d.getHtml()),!0):!1},_findOneNotNested:function(a){a=this.wrapper.find(a);for(var b,c,d=0;d<a.count();d++)if(b= -a.getItem(d),c=b.getAscendant(h.isDomWidgetWrapper),this.wrapper.equals(c))return b;return null},isInited:function(){return!(!this.wrapper||!this.inited)},isReady:function(){return this.isInited()&&this.ready},focus:function(){var a=this.editor.getSelection();if(a){var b=this.editor.checkDirty();a.fake(this.wrapper);!b&&this.editor.resetDirty()}this.editor.focus()},removeClass:function(a){this.element.removeClass(a);this.wrapper.removeClass(h.WRAPPER_CLASS_PREFIX+a)},removeStyle:function(a){F(this, -a,0)},setData:function(a,b){var c=this.data,d=0;if("string"==typeof a)c[a]!==b&&(c[a]=b,d=1);else{var g=a;for(a in g)c[a]!==g[a]&&(d=1,c[a]=g[a])}d&&this.dataReady&&(Q(this),this.fire("data",c));return this},setFocused:function(a){this.wrapper[a?"addClass":"removeClass"]("cke_widget_focused");this.fire(a?"focus":"blur");return this},setSelected:function(a){this.wrapper[a?"addClass":"removeClass"]("cke_widget_selected");this.fire(a?"select":"deselect");return this},updateDragHandlerPosition:function(){var a= +d,d.setAttributes({contenteditable:"true","data-cke-widget-editable":b,"data-cke-enter-mode":d.enterMode}),d.filter&&d.data("cke-filter",d.filter.id),d.addClass("cke_widget_editable"),d.removeClass("cke_widget_editable_focused"),c.pathName&&d.data("cke-display-name",c.pathName),this.editor.focusManager.add(d),d.on("focus",D,this),CKEDITOR.env.ie&&d.on("blur",O,this),d._.initialSetData=!0,d.setData(d.getHtml()),!0):!1},_findOneNotNested:function(a){a=this.wrapper.find(a);for(var b,c,d=0;d<a.count();d++)if(b= +a.getItem(d),c=b.getAscendant(h.isDomWidgetWrapper),this.wrapper.equals(c))return b;return null},isInited:function(){return!(!this.wrapper||!this.inited)},isReady:function(){return this.isInited()&&this.ready},focus:function(){var a=this.editor.getSelection();if(a){var b=this.editor.checkDirty();a.fake(this.wrapper);!b&&this.editor.resetDirty()}this.editor.focus()},removeClass:function(a){this.element.removeClass(a);this.wrapper.removeClass(h.WRAPPER_CLASS_PREFIX+a)},removeStyle:function(a){E(this, +a,0)},setData:function(a,b){var c=this.data,d=0;if("string"==typeof a)c[a]!==b&&(c[a]=b,d=1);else{var e=a;for(a in e)c[a]!==e[a]&&(d=1,c[a]=e[a])}d&&this.dataReady&&(Q(this),this.fire("data",c));return this},setFocused:function(a){this.wrapper[a?"addClass":"removeClass"]("cke_widget_focused");this.fire(a?"focus":"blur");return this},setSelected:function(a){this.wrapper[a?"addClass":"removeClass"]("cke_widget_selected");this.fire(a?"select":"deselect");return this},updateDragHandlerPosition:function(){var a= this.editor,b=this.element.$,c=this._.dragHandlerOffset,b={x:b.offsetLeft,y:b.offsetTop-15};c&&b.x==c.x&&b.y==c.y||(c=a.checkDirty(),a.fire("lockSnapshot"),this.dragHandlerContainer.setStyles({top:b.y+"px",left:b.x+"px",display:"block"}),a.fire("unlockSnapshot"),!c&&a.resetDirty(),this._.dragHandlerOffset=b)}};CKEDITOR.event.implementOn(h.prototype);h.getNestedEditable=function(a,b){return!b||b.equals(a)?null:h.isDomNestedEditable(b)?b:h.getNestedEditable(a,b.getParent())};h.isDomDragHandler=function(a){return a.type== CKEDITOR.NODE_ELEMENT&&a.hasAttribute("data-cke-widget-drag-handler")};h.isDomDragHandlerContainer=function(a){return a.type==CKEDITOR.NODE_ELEMENT&&a.hasClass("cke_widget_drag_handler_container")};h.isDomNestedEditable=function(a){return a.type==CKEDITOR.NODE_ELEMENT&&a.hasAttribute("data-cke-widget-editable")};h.isDomWidgetElement=function(a){return a.type==CKEDITOR.NODE_ELEMENT&&a.hasAttribute("data-widget")};h.isDomWidgetWrapper=function(a){return a.type==CKEDITOR.NODE_ELEMENT&&a.hasAttribute("data-cke-widget-wrapper")}; h.isDomWidget=function(a){return a?this.isDomWidgetWrapper(a)||this.isDomWidgetElement(a):!1};h.isParserWidgetElement=function(a){return a.type==CKEDITOR.NODE_ELEMENT&&!!a.attributes["data-widget"]};h.isParserWidgetWrapper=function(a){return a.type==CKEDITOR.NODE_ELEMENT&&!!a.attributes["data-cke-widget-wrapper"]};h.WRAPPER_CLASS_PREFIX="cke_widget_wrapper_";e.prototype=CKEDITOR.tools.extend(CKEDITOR.tools.prototypedCopy(CKEDITOR.dom.element.prototype),{setData:function(a){this._.initialSetData|| this.editor.widgets.destroyAll(!1,this);this._.initialSetData=!1;a=this.editor.dataProcessor.toHtml(a,{context:this.getName(),filter:this.filter,enterMode:this.enterMode});this.setHtml(a);this.editor.widgets.initOnAll(this)},getData:function(){return this.editor.dataProcessor.toDataFormat(this.getHtml(),{context:this.getName(),filter:this.filter,enterMode:this.enterMode})}});var V=/^(?:<(?:div|span)(?: data-cke-temp="1")?(?: id="cke_copybin")?(?: data-cke-temp="1")?>)?(?:<(?:div|span)(?: style="[^"]+")?>)?<span [^>]*data-cke-copybin-start="1"[^>]*>.?<\/span>([\s\S]+)<span [^>]*data-cke-copybin-end="1"[^>]*>.?<\/span>(?:<\/(?:div|span)>)?(?:<\/(?:div|span)>)?$/i, -T={37:1,38:1,39:1,40:1,8:1,46:1};CKEDITOR.plugins.widget=h;h.repository=f;h.nestedEditable=e}(),"use strict",function(){function f(b){function d(){this.deflated||(b.widgets.focused==this.widget&&(this.focused=!0),b.widgets.destroy(this.widget),this.deflated=!0)}function g(){var a=b.editable(),c=b.document;if(this.deflated)this.widget=b.widgets.initOn(this.element,"image",this.widget.data),this.widget.inline&&!(new CKEDITOR.dom.elementPath(this.widget.wrapper,a)).block&&(a=c.createElement(b.activeEnterMode== -CKEDITOR.ENTER_P?"p":"div"),a.replace(this.widget.wrapper),this.widget.wrapper.move(a)),this.focused&&(this.widget.focus(),delete this.focused),delete this.deflated;else{var d=this.widget,a=f,c=d.wrapper,e=d.data.align,d=d.data.hasCaption;if(a){for(var h=3;h--;)c.removeClass(a[h]);"center"==e?d&&c.addClass(a[1]):"none"!=e&&c.addClass(a[v[e]])}else"center"==e?(d?c.setStyle("text-align","center"):c.removeStyle("text-align"),c.removeStyle("float")):("none"==e?c.removeStyle("float"):c.setStyle("float", -e),c.removeStyle("text-align"))}}var f=b.config.image2_alignClasses,k=b.config.image2_captionedClass;return{allowedContent:c(b),requiredContent:"img[src,alt]",features:a(b),styleableElements:"img figure",contentTransformations:[["img[width]: sizeToAttribute"]],editables:{caption:{selector:"figcaption",allowedContent:"br em strong sub sup u s; a[!href,target]"}},parts:{image:"img",caption:"figcaption"},dialog:"image2",template:'\x3cimg alt\x3d"" src\x3d"" /\x3e',data:function(){var a=this.features; -this.data.hasCaption&&!b.filter.checkFeature(a.caption)&&(this.data.hasCaption=!1);"none"==this.data.align||b.filter.checkFeature(a.align)||(this.data.align="none");this.shiftState({widget:this,element:this.element,oldData:this.oldData,newData:this.data,deflate:d,inflate:g});this.data.link?this.parts.link||(this.parts.link=this.parts.image.getParent()):this.parts.link&&delete this.parts.link;this.parts.image.setAttributes({src:this.data.src,"data-cke-saved-src":this.data.src,alt:this.data.alt});if(this.oldData&& +T={37:1,38:1,39:1,40:1,8:1,46:1};CKEDITOR.plugins.widget=h;h.repository=f;h.nestedEditable=e}(),"use strict",function(){function f(b){function d(){this.deflated||(b.widgets.focused==this.widget&&(this.focused=!0),b.widgets.destroy(this.widget),this.deflated=!0)}function f(){var a=b.editable(),c=b.document;if(this.deflated)this.widget=b.widgets.initOn(this.element,"image",this.widget.data),this.widget.inline&&!(new CKEDITOR.dom.elementPath(this.widget.wrapper,a)).block&&(a=c.createElement(b.activeEnterMode== +CKEDITOR.ENTER_P?"p":"div"),a.replace(this.widget.wrapper),this.widget.wrapper.move(a)),this.focused&&(this.widget.focus(),delete this.focused),delete this.deflated;else{var d=this.widget,a=g,c=d.wrapper,e=d.data.align,d=d.data.hasCaption;if(a){for(var h=3;h--;)c.removeClass(a[h]);"center"==e?d&&c.addClass(a[1]):"none"!=e&&c.addClass(a[v[e]])}else"center"==e?(d?c.setStyle("text-align","center"):c.removeStyle("text-align"),c.removeStyle("float")):("none"==e?c.removeStyle("float"):c.setStyle("float", +e),c.removeStyle("text-align"))}}var g=b.config.image2_alignClasses,k=b.config.image2_captionedClass;return{allowedContent:c(b),requiredContent:"img[src,alt]",features:a(b),styleableElements:"img figure",contentTransformations:[["img[width]: sizeToAttribute"]],editables:{caption:{selector:"figcaption",allowedContent:"br em strong sub sup u s; a[!href,target]"}},parts:{image:"img",caption:"figcaption"},dialog:"image2",template:'\x3cimg alt\x3d"" src\x3d"" /\x3e',data:function(){var a=this.features; +this.data.hasCaption&&!b.filter.checkFeature(a.caption)&&(this.data.hasCaption=!1);"none"==this.data.align||b.filter.checkFeature(a.align)||(this.data.align="none");this.shiftState({widget:this,element:this.element,oldData:this.oldData,newData:this.data,deflate:d,inflate:f});this.data.link?this.parts.link||(this.parts.link=this.parts.image.getParent()):this.parts.link&&delete this.parts.link;this.parts.image.setAttributes({src:this.data.src,"data-cke-saved-src":this.data.src,alt:this.data.alt});if(this.oldData&& !this.oldData.hasCaption&&this.data.hasCaption)for(var c in this.data.classes)this.parts.image.removeClass(c);if(b.filter.checkFeature(a.dimension)){a=this.data;a={width:a.width,height:a.height};c=this.parts.image;for(var e in a)a[e]?c.setAttribute(e,a[e]):c.removeAttribute(e)}this.oldData=CKEDITOR.tools.extend({},this.data)},init:function(){var a=CKEDITOR.plugins.image2,c=this.parts.image,d={hasCaption:!!this.parts.caption,src:c.getAttribute("src"),alt:c.getAttribute("alt")||"",width:c.getAttribute("width")|| -"",height:c.getAttribute("height")||"",lock:this.ready?a.checkHasNaturalRatio(c):!0},g=c.getAscendant("a");g&&this.wrapper.contains(g)&&(this.parts.link=g);d.align||(c=d.hasCaption?this.element:c,f?(c.hasClass(f[0])?d.align="left":c.hasClass(f[2])&&(d.align="right"),d.align?c.removeClass(f[v[d.align]]):d.align="none"):(d.align=c.getStyle("float")||"none",c.removeStyle("float")));b.plugins.link&&this.parts.link&&(d.link=a.getLinkAttributesParser()(b,this.parts.link),(c=d.link.advanced)&&c.advCSSClasses&& +"",height:c.getAttribute("height")||"",lock:this.ready?a.checkHasNaturalRatio(c):!0},e=c.getAscendant("a");e&&this.wrapper.contains(e)&&(this.parts.link=e);d.align||(c=d.hasCaption?this.element:c,g?(c.hasClass(g[0])?d.align="left":c.hasClass(g[2])&&(d.align="right"),d.align?c.removeClass(g[v[d.align]]):d.align="none"):(d.align=c.getStyle("float")||"none",c.removeStyle("float")));b.plugins.link&&this.parts.link&&(d.link=a.getLinkAttributesParser()(b,this.parts.link),(c=d.link.advanced)&&c.advCSSClasses&& (c.advCSSClasses=CKEDITOR.tools.trim(c.advCSSClasses.replace(/cke_\S+/,""))));this.wrapper[(d.hasCaption?"remove":"add")+"Class"]("cke_image_nocaption");this.setData(d);b.filter.checkFeature(this.features.dimension)&&!0!==b.config.image2_disableResizer&&1!=b.readOnly&&l(this);this.shiftState=a.stateShifter(this.editor);this.on("contextMenu",function(a){a.data.image=CKEDITOR.TRISTATE_OFF;if(this.parts.link||this.wrapper.getAscendant("a"))a.data.link=a.data.unlink=CKEDITOR.TRISTATE_OFF});this.on("dialog", -function(a){a.data.widget=this},this)},addClass:function(a){n(this).addClass(a)},hasClass:function(a){return n(this).hasClass(a)},removeClass:function(a){n(this).removeClass(a)},getClasses:function(){var a=new RegExp("^("+[].concat(k,f).join("|")+")$");return function(){var b=this.repository.parseElementClasses(n(this).getAttribute("class")),c;for(c in b)a.test(c)&&delete b[c];return b}}(),upcast:h(b),downcast:e(b),getLabel:function(){return this.editor.lang.widget.label.replace(/%1/,(this.data.alt|| -"")+" "+this.pathName)}}}function h(a){var b=k(a),c=a.config.image2_captionedClass;return function(a,g){var e={width:1,height:1},f=a.name,h;if(!a.attributes["data-cke-realelement"]&&(b(a)?("div"==f&&(h=a.getFirst("figure"))&&(a.replaceWith(h),a=h),g.align="center",h=a.getFirst("img")||a.getFirst("a").getFirst("img")):"figure"==f&&a.hasClass(c)?h=a.getFirst("img")||a.getFirst("a").getFirst("img"):d(a)&&(h="a"==a.name?a.children[0]:a),h)){for(var k in e)(e=h.attributes[k])&&e.match(p)&&delete h.attributes[k]; -return a}}}function e(a){var b=a.config.image2_alignClasses;return function(a){var c="a"==a.name?a.getFirst():a,d=c.attributes,g=this.data.align;if(!this.inline){var e=a.getFirst("span");e&&e.replaceWith(e.getFirst({img:1,a:1}))}g&&"none"!=g&&(e=CKEDITOR.tools.parseCssText(d.style||""),"center"==g&&"figure"==a.name?a=a.wrapWith(new CKEDITOR.htmlParser.element("div",b?{"class":b[1]}:{style:"text-align:center"})):g in{left:1,right:1}&&(b?c.addClass(b[v[g]]):e["float"]=g),b||CKEDITOR.tools.isEmpty(e)|| -(d.style=CKEDITOR.tools.writeCssText(e)));return a}}function k(a){var b=a.config.image2_captionedClass,c=a.config.image2_alignClasses,g={figure:1,a:1,img:1};return function(e){if(!(e.name in{div:1,p:1}))return!1;var f=e.children;if(1!==f.length)return!1;f=f[0];if(!(f.name in g))return!1;if("p"==e.name){if(!d(f))return!1}else if("figure"==f.name){if(!f.hasClass(b))return!1}else if(a.enterMode==CKEDITOR.ENTER_P||!d(f))return!1;return(c?e.hasClass(c[1]):"center"==CKEDITOR.tools.parseCssText(e.attributes.style|| -"",!0)["text-align"])?!0:!1}}function d(a){return"img"==a.name?!0:"a"==a.name?1==a.children.length&&a.getFirst("img"):!1}function l(a){var b=a.editor,c=b.editable(),d=b.document,g=a.resizer=d.createElement("span");g.addClass("cke_image_resizer");g.setAttribute("title",b.lang.image2.resizer);g.append(new CKEDITOR.dom.text("",d));if(a.inline)a.wrapper.append(g);else{var e=a.parts.link||a.parts.image,f=e.getParent(),h=d.createElement("span");h.addClass("cke_image_resizer_wrapper");h.append(e);h.append(g); -a.element.append(h,!0);f.is("span")&&f.remove()}g.on("mousedown",function(e){function f(a,b,c){var g=CKEDITOR.document,e=[];d.equals(g)||e.push(g.on(a,b));e.push(d.on(a,b));if(c)for(a=e.length;a--;)c.push(e.pop())}function h(){U=p+m*aa;Y=Math.round(U/D)}function k(){Y=B-M;U=Math.round(Y*D)}var l=a.parts.image,m="right"==a.data.align?-1:1,n=e.data.$.screenX,t=e.data.$.screenY,p=l.$.clientWidth,B=l.$.clientHeight,D=p/B,w=[],v="cke_image_s"+(~m?"e":"w"),K,U,Y,Z,aa,M,Q;b.fire("saveSnapshot");f("mousemove", -function(a){K=a.data.$;aa=K.screenX-n;M=t-K.screenY;Q=Math.abs(aa/M);1==m?0>=aa?0>=M?h():Q>=D?h():k():0>=M?Q>=D?k():h():k():0>=aa?0>=M?Q>=D?k():h():k():0>=M?h():Q>=D?h():k();15<=U&&15<=Y?(l.setAttributes({width:U,height:Y}),Z=!0):Z=!1},w);f("mouseup",function(){for(var d;d=w.pop();)d.removeListener();c.removeClass(v);g.removeClass("cke_image_resizing");Z&&(a.setData({width:U,height:Y}),b.fire("saveSnapshot"));Z=!1},w);c.addClass(v);g.addClass("cke_image_resizing")});a.on("data",function(){g["right"== +function(a){a.data.widget=this},this)},addClass:function(a){n(this).addClass(a)},hasClass:function(a){return n(this).hasClass(a)},removeClass:function(a){n(this).removeClass(a)},getClasses:function(){var a=new RegExp("^("+[].concat(k,g).join("|")+")$");return function(){var b=this.repository.parseElementClasses(n(this).getAttribute("class")),c;for(c in b)a.test(c)&&delete b[c];return b}}(),upcast:h(b),downcast:e(b),getLabel:function(){return this.editor.lang.widget.label.replace(/%1/,(this.data.alt|| +"")+" "+this.pathName)}}}function h(a){var b=k(a),c=a.config.image2_captionedClass;return function(a,e){var f={width:1,height:1},g=a.name,h;if(!a.attributes["data-cke-realelement"]&&(b(a)?("div"==g&&(h=a.getFirst("figure"))&&(a.replaceWith(h),a=h),e.align="center",h=a.getFirst("img")||a.getFirst("a").getFirst("img")):"figure"==g&&a.hasClass(c)?h=a.getFirst("img")||a.getFirst("a").getFirst("img"):d(a)&&(h="a"==a.name?a.children[0]:a),h)){for(var k in f)(f=h.attributes[k])&&f.match(t)&&delete h.attributes[k]; +return a}}}function e(a){var b=a.config.image2_alignClasses;return function(a){var c="a"==a.name?a.getFirst():a,d=c.attributes,e=this.data.align;if(!this.inline){var f=a.getFirst("span");f&&f.replaceWith(f.getFirst({img:1,a:1}))}e&&"none"!=e&&(f=CKEDITOR.tools.parseCssText(d.style||""),"center"==e&&"figure"==a.name?a=a.wrapWith(new CKEDITOR.htmlParser.element("div",b?{"class":b[1]}:{style:"text-align:center"})):e in{left:1,right:1}&&(b?c.addClass(b[v[e]]):f["float"]=e),b||CKEDITOR.tools.isEmpty(f)|| +(d.style=CKEDITOR.tools.writeCssText(f)));return a}}function k(a){var b=a.config.image2_captionedClass,c=a.config.image2_alignClasses,e={figure:1,a:1,img:1};return function(f){if(!(f.name in{div:1,p:1}))return!1;var g=f.children;if(1!==g.length)return!1;g=g[0];if(!(g.name in e))return!1;if("p"==f.name){if(!d(g))return!1}else if("figure"==g.name){if(!g.hasClass(b))return!1}else if(a.enterMode==CKEDITOR.ENTER_P||!d(g))return!1;return(c?f.hasClass(c[1]):"center"==CKEDITOR.tools.parseCssText(f.attributes.style|| +"",!0)["text-align"])?!0:!1}}function d(a){return"img"==a.name?!0:"a"==a.name?1==a.children.length&&a.getFirst("img"):!1}function l(a){var b=a.editor,c=b.editable(),d=b.document,e=a.resizer=d.createElement("span");e.addClass("cke_image_resizer");e.setAttribute("title",b.lang.image2.resizer);e.append(new CKEDITOR.dom.text("",d));if(a.inline)a.wrapper.append(e);else{var f=a.parts.link||a.parts.image,g=f.getParent(),h=d.createElement("span");h.addClass("cke_image_resizer_wrapper");h.append(f);h.append(e); +a.element.append(h,!0);g.is("span")&&g.remove()}e.on("mousedown",function(f){function g(a,b,c){var e=CKEDITOR.document,f=[];d.equals(e)||f.push(e.on(a,b));f.push(d.on(a,b));if(c)for(a=f.length;a--;)c.push(f.pop())}function h(){U=t+m*Z;X=Math.round(U/y)}function k(){X=B-M;U=Math.round(X*y)}var l=a.parts.image,m="right"==a.data.align?-1:1,n=f.data.$.screenX,u=f.data.$.screenY,t=l.$.clientWidth,B=l.$.clientHeight,y=t/B,w=[],v="cke_image_s"+(~m?"e":"w"),K,U,X,Y,Z,M,Q;b.fire("saveSnapshot");g("mousemove", +function(a){K=a.data.$;Z=K.screenX-n;M=u-K.screenY;Q=Math.abs(Z/M);1==m?0>=Z?0>=M?h():Q>=y?h():k():0>=M?Q>=y?k():h():k():0>=Z?0>=M?Q>=y?k():h():k():0>=M?h():Q>=y?h():k();15<=U&&15<=X?(l.setAttributes({width:U,height:X}),Y=!0):Y=!1},w);g("mouseup",function(){for(var d;d=w.pop();)d.removeListener();c.removeClass(v);e.removeClass("cke_image_resizing");Y&&(a.setData({width:U,height:X}),b.fire("saveSnapshot"));Y=!1},w);c.addClass(v);e.addClass("cke_image_resizing")});a.on("data",function(){e["right"== a.data.align?"addClass":"removeClass"]("cke_image_resizer_left")})}function m(a){var b=[],c;return function(d){var e=a.getCommand("justify"+d);if(e){b.push(function(){e.refresh(a,a.elementPath())});if(d in{right:1,left:1,center:1})e.on("exec",function(c){var e=g(a);if(e){e.setData("align",d);for(e=b.length;e--;)b[e]();c.cancel()}});e.on("refresh",function(b){var e=g(a),f={right:1,left:1,center:1};e&&(void 0===c&&(c=a.filter.checkFeature(a.widgets.registered.image.features.align)),c?this.setState(e.data.align== d?CKEDITOR.TRISTATE_ON:d in f?CKEDITOR.TRISTATE_OFF:CKEDITOR.TRISTATE_DISABLED):this.setState(CKEDITOR.TRISTATE_DISABLED),b.cancel())})}}}function b(a){a.plugins.link&&(CKEDITOR.on("dialogDefinition",function(b){b=b.data;if("link"==b.name){b=b.definition;var c=b.onShow,d=b.onOk;b.onShow=function(){var b=g(a),d=this.getContentElement("info","linkDisplayText").getElement().getParent().getParent();b&&(b.inline?!b.wrapper.getAscendant("a"):1)?(this.setupContent(b.data.link||{}),d.hide()):(d.show(),c.apply(this, arguments))};b.onOk=function(){var b=g(a);if(b&&(b.inline?!b.wrapper.getAscendant("a"):1)){var c={};this.commitContent(c);b.setData("link",c)}else d.apply(this,arguments)}}}),a.getCommand("unlink").on("exec",function(b){var c=g(a);c&&c.parts.link&&(c.setData("link",null),this.refresh(a,a.elementPath()),b.cancel())}),a.getCommand("unlink").on("refresh",function(b){var c=g(a);c&&(this.setState(c.data.link||c.wrapper.getAscendant("a")?CKEDITOR.TRISTATE_OFF:CKEDITOR.TRISTATE_DISABLED),b.cancel())}))} function g(a){return(a=a.widgets.focused)&&"image"==a.name?a:null}function c(a){var b=a.config.image2_alignClasses;a={div:{match:k(a)},p:{match:k(a)},img:{attributes:"!src,alt,width,height"},figure:{classes:"!"+a.config.image2_captionedClass},figcaption:!0};b?(a.div.classes=b[1],a.p.classes=a.div.classes,a.img.classes=b[0]+","+b[2],a.figure.classes+=","+a.img.classes):(a.div.styles="text-align",a.p.styles="text-align",a.img.styles="float",a.figure.styles="float,display");return a}function a(a){a= -a.config.image2_alignClasses;return{dimension:{requiredContent:"img[width,height]"},align:{requiredContent:"img"+(a?"("+a[0]+")":"{float}")},caption:{requiredContent:"figcaption"}}}function n(a){return a.data.hasCaption?a.element:a.parts.image}var w=new CKEDITOR.template('\x3cfigure class\x3d"{captionedClass}"\x3e\x3cimg alt\x3d"" src\x3d"" /\x3e\x3cfigcaption\x3e{captionPlaceholder}\x3c/figcaption\x3e\x3c/figure\x3e'),v={left:0,center:1,right:2},p=/^\s*(\d+\%)\s*$/i;CKEDITOR.plugins.add("image2", +a.config.image2_alignClasses;return{dimension:{requiredContent:"img[width,height]"},align:{requiredContent:"img"+(a?"("+a[0]+")":"{float}")},caption:{requiredContent:"figcaption"}}}function n(a){return a.data.hasCaption?a.element:a.parts.image}var w=new CKEDITOR.template('\x3cfigure class\x3d"{captionedClass}"\x3e\x3cimg alt\x3d"" src\x3d"" /\x3e\x3cfigcaption\x3e{captionPlaceholder}\x3c/figcaption\x3e\x3c/figure\x3e'),v={left:0,center:1,right:2},t=/^\s*(\d+\%)\s*$/i;CKEDITOR.plugins.add("image2", {requires:"widget,dialog",icons:"image",hidpi:!0,onLoad:function(){CKEDITOR.addCss(".cke_image_nocaption{line-height:0}.cke_editable.cke_image_sw, .cke_editable.cke_image_sw *{cursor:sw-resize !important}.cke_editable.cke_image_se, .cke_editable.cke_image_se *{cursor:se-resize !important}.cke_image_resizer{display:none;position:absolute;width:10px;height:10px;bottom:-5px;right:-5px;background:#000;outline:1px solid #fff;line-height:0;cursor:se-resize;}.cke_image_resizer_wrapper{position:relative;display:inline-block;line-height:0;}.cke_image_resizer.cke_image_resizer_left{right:auto;left:-5px;cursor:sw-resize;}.cke_widget_wrapper:hover .cke_image_resizer,.cke_image_resizer.cke_image_resizing{display:block}.cke_widget_wrapper\x3ea{display:inline-block}")}, -init:function(a){var b=a.config,c=a.lang.image2,d=f(a);b.filebrowserImage2BrowseUrl=b.filebrowserImageBrowseUrl;b.filebrowserImage2UploadUrl=b.filebrowserImageUploadUrl;d.pathName=c.pathName;d.editables.caption.pathName=c.pathNameCaption;a.widgets.add("image",d);a.ui.addButton&&a.ui.addButton("Image",{label:a.lang.common.image,command:"image",toolbar:"insert,10"});a.contextMenu&&(a.addMenuGroup("image",10),a.addMenuItem("image",{label:c.menu,command:"image",group:"image"}));CKEDITOR.dialog.add("image2", -this.path+"dialogs/image2.js")},afterInit:function(a){var c={left:1,right:1,center:1,block:1},d=m(a),g;for(g in c)d(g);b(a)}});CKEDITOR.plugins.image2={stateShifter:function(a){function b(a,e){var f={};g?f.attributes={"class":g[1]}:f.styles={"text-align":"center"};f=d.createElement(a.activeEnterMode==CKEDITOR.ENTER_P?"p":"div",f);c(f,e);e.move(f);return f}function c(b,d){if(d.getParent()){var g=a.createRange();g.moveToPosition(d,CKEDITOR.POSITION_BEFORE_START);d.remove();f.insertElementIntoRange(b, -g)}else b.replace(d)}var d=a.document,g=a.config.image2_alignClasses,e=a.config.image2_captionedClass,f=a.editable(),h=["hasCaption","align","link"],k={align:function(c,d,e){var f=c.element;c.changed.align?c.newData.hasCaption||("center"==e&&(c.deflate(),c.element=b(a,f)),c.changed.hasCaption||"center"!=d||"center"==e||(c.deflate(),d=f.findOne("a,img"),d.replace(f),c.element=d)):"center"==e&&c.changed.hasCaption&&!c.newData.hasCaption&&(c.deflate(),c.element=b(a,f));!g&&f.is("figure")&&("center"== -e?f.setStyle("display","inline-block"):f.removeStyle("display"))},hasCaption:function(b,g,f){b.changed.hasCaption&&(g=b.element.is({img:1,a:1})?b.element:b.element.findOne("a,img"),b.deflate(),f?(f=CKEDITOR.dom.element.createFromHtml(w.output({captionedClass:e,captionPlaceholder:a.lang.image2.captionPlaceholder}),d),c(f,b.element),g.replace(f.findOne("img")),b.element=f):(g.replace(b.element),b.element=g))},link:function(b,c,g){if(b.changed.link){var e=b.element.is("img")?b.element:b.element.findOne("img"), -f=b.element.is("a")?b.element:b.element.findOne("a"),h=b.element.is("a")&&!g||b.element.is("img")&&g,k;h&&b.deflate();g?(c||(k=d.createElement("a",{attributes:{href:b.newData.link.url}}),k.replace(e),e.move(k)),g=CKEDITOR.plugins.image2.getLinkAttributesGetter()(a,g),CKEDITOR.tools.isEmpty(g.set)||(k||f).setAttributes(g.set),g.removed.length&&(k||f).removeAttributes(g.removed)):(g=f.findOne("img"),g.replace(f),k=g);h&&(b.element=k)}}};return function(a){var b,c;a.changed={};for(c=0;c<h.length;c++)b= -h[c],a.changed[b]=a.oldData?a.oldData[b]!==a.newData[b]:!1;for(c=0;c<h.length;c++)b=h[c],k[b](a,a.oldData?a.oldData[b]:null,a.newData[b]);a.inflate()}},checkHasNaturalRatio:function(a){var b=a.$;a=this.getNatural(a);return Math.round(b.clientWidth/a.width*a.height)==b.clientHeight||Math.round(b.clientHeight/a.height*a.width)==b.clientWidth},getNatural:function(a){if(a.$.naturalWidth)a={width:a.$.naturalWidth,height:a.$.naturalHeight};else{var b=new Image;b.src=a.getAttribute("src");a={width:b.width, -height:b.height}}return a},getLinkAttributesGetter:function(){return CKEDITOR.plugins.link.getLinkAttributes},getLinkAttributesParser:function(){return CKEDITOR.plugins.link.parseLinkAttributes}}}(),CKEDITOR.config.image2_captionedClass="image",function(){function f(f,d){var l,m;d.on("refresh",function(b){var d=[h],c;for(c in b.data.states)d.push(b.data.states[c]);this.setState(CKEDITOR.tools.search(d,e)?e:h)},d,null,100);d.on("exec",function(b){l=f.getSelection();m=l.createBookmarks(1);b.data||(b.data= -{});b.data.done=!1},d,null,0);d.on("exec",function(){f.forceNextSelectionCheck();l.selectBookmarks(m)},d,null,100)}var h=CKEDITOR.TRISTATE_DISABLED,e=CKEDITOR.TRISTATE_OFF;CKEDITOR.plugins.add("indent",{init:function(e){var d=CKEDITOR.plugins.indent.genericDefinition;f(e,e.addCommand("indent",new d(!0)));f(e,e.addCommand("outdent",new d));e.ui.addButton&&(e.ui.addButton("Indent",{label:e.lang.indent.indent,command:"indent",directional:!0,toolbar:"indent,20"}),e.ui.addButton("Outdent",{label:e.lang.indent.outdent, -command:"outdent",directional:!0,toolbar:"indent,10"}));e.on("dirChanged",function(d){var f=e.createRange(),b=d.data.node;f.setStartBefore(b);f.setEndAfter(b);for(var g=new CKEDITOR.dom.walker(f),c;c=g.next();)if(c.type==CKEDITOR.NODE_ELEMENT)if(!c.equals(b)&&c.getDirection())f.setStartAfter(c),g=new CKEDITOR.dom.walker(f);else{var a=e.config.indentClasses;if(a)for(var h="ltr"==d.data.dir?["_rtl",""]:["","_rtl"],w=0;w<a.length;w++)c.hasClass(a[w]+h[0])&&(c.removeClass(a[w]+h[0]),c.addClass(a[w]+h[1])); -a=c.getStyle("margin-right");h=c.getStyle("margin-left");a?c.setStyle("margin-left",a):c.removeStyle("margin-left");h?c.setStyle("margin-right",h):c.removeStyle("margin-right")}})}});CKEDITOR.plugins.indent={genericDefinition:function(e){this.isIndent=!!e;this.startDisabled=!this.isIndent},specificDefinition:function(e,d,f){this.name=d;this.editor=e;this.jobs={};this.enterBr=e.config.enterMode==CKEDITOR.ENTER_BR;this.isIndent=!!f;this.relatedGlobal=f?"indent":"outdent";this.indentKey=f?9:CKEDITOR.SHIFT+ -9;this.database={}},registerCommands:function(e,d){e.on("pluginsLoaded",function(){for(var e in d)(function(d,b){var g=d.getCommand(b.relatedGlobal),c;for(c in b.jobs)g.on("exec",function(a){a.data.done||(d.fire("lockSnapshot"),b.execJob(d,c)&&(a.data.done=!0),d.fire("unlockSnapshot"),CKEDITOR.dom.element.clearAllMarkers(b.database))},this,null,c),g.on("refresh",function(a){a.data.states||(a.data.states={});a.data.states[b.name+"@"+c]=b.refreshJob(d,c,a.data.path)},this,null,c);d.addFeature(b)})(this, -d[e])})}};CKEDITOR.plugins.indent.genericDefinition.prototype={context:"p",exec:function(){}};CKEDITOR.plugins.indent.specificDefinition.prototype={execJob:function(e,d){var f=this.jobs[d];if(f.state!=h)return f.exec.call(this,e)},refreshJob:function(e,d,f){d=this.jobs[d];e.activeFilter.checkFeature(this)?d.state=d.refresh.call(this,e,f):d.state=h;return d.state},getContext:function(e){return e.contains(this.context)}}}(),function(){function f(b){function d(g){for(var h=k.startContainer,l=k.endContainer;h&& -!h.getParent().equals(g);)h=h.getParent();for(;l&&!l.getParent().equals(g);)l=l.getParent();if(!h||!l)return!1;for(var m=[],p=!1;!p;)h.equals(l)&&(p=!0),m.push(h),h=h.getNext();if(1>m.length)return!1;h=g.getParents(!0);for(l=0;l<h.length;l++)if(h[l].getName&&f[h[l].getName()]){g=h[l];break}for(var h=c.isIndent?1:-1,l=m[0],m=m[m.length-1],p=CKEDITOR.plugins.list.listToArray(g,a),t=p[m.getCustomData("listarray_index")].indent,l=l.getCustomData("listarray_index");l<=m.getCustomData("listarray_index");l++)if(p[l].indent+= -h,0<h){for(var r=p[l].parent,y=l-1;0<=y;y--)if(p[y].indent===h){r=p[y].parent;break}p[l].parent=new CKEDITOR.dom.element(r.getName(),r.getDocument())}for(l=m.getCustomData("listarray_index")+1;l<p.length&&p[l].indent>t;l++)p[l].indent+=h;h=CKEDITOR.plugins.list.arrayToList(p,a,null,b.config.enterMode,g.getDirection());if(!c.isIndent){var z;if((z=g.getParent())&&z.is("li"))for(var m=h.listNode.getChildren(),v=[],E,l=m.count()-1;0<=l;l--)(E=m.getItem(l))&&E.is&&E.is("li")&&v.push(E)}h&&h.listNode.replace(g); -if(v&&v.length)for(l=0;l<v.length;l++){for(E=g=v[l];(E=E.getNext())&&E.is&&E.getName()in f;)CKEDITOR.env.needsNbspFiller&&!g.getFirst(e)&&g.append(k.document.createText(" ")),g.append(E);g.insertAfter(z)}h&&b.fire("contentDomInvalidated");return!0}for(var c=this,a=this.database,f=this.context,k,l=b.getSelection(),l=(l&&l.getRanges()).createIterator();k=l.getNextRange();){for(var m=k.getCommonAncestor();m&&(m.type!=CKEDITOR.NODE_ELEMENT||!f[m.getName()]);){if(b.editable().equals(m)){m=!1;break}m=m.getParent()}m|| -(m=k.startPath().contains(f))&&k.setEndAt(m,CKEDITOR.POSITION_BEFORE_END);if(!m){var r=k.getEnclosedNode();r&&r.type==CKEDITOR.NODE_ELEMENT&&r.getName()in f&&(k.setStartAt(r,CKEDITOR.POSITION_AFTER_START),k.setEndAt(r,CKEDITOR.POSITION_BEFORE_END),m=r)}m&&k.startContainer.type==CKEDITOR.NODE_ELEMENT&&k.startContainer.getName()in f&&(r=new CKEDITOR.dom.walker(k),r.evaluator=h,k.startContainer=r.next());m&&k.endContainer.type==CKEDITOR.NODE_ELEMENT&&k.endContainer.getName()in f&&(r=new CKEDITOR.dom.walker(k), -r.evaluator=h,k.endContainer=r.previous());if(m)return d(m)}return 0}function h(b){return b.type==CKEDITOR.NODE_ELEMENT&&b.is("li")}function e(b){return k(b)&&d(b)}var k=CKEDITOR.dom.walker.whitespaces(!0),d=CKEDITOR.dom.walker.bookmark(!1,!0),l=CKEDITOR.TRISTATE_DISABLED,m=CKEDITOR.TRISTATE_OFF;CKEDITOR.plugins.add("indentlist",{requires:"indent",init:function(b){function d(a){c.specificDefinition.apply(this,arguments);this.requiredContent=["ul","ol"];a.on("key",function(b){var c=a.elementPath(); -if("wysiwyg"==a.mode&&b.data.keyCode==this.indentKey&&c){var d=this.getContext(c);!d||this.isIndent&&CKEDITOR.plugins.indentList.firstItemInPath(this.context,c,d)||(a.execCommand(this.relatedGlobal),b.cancel())}},this);this.jobs[this.isIndent?10:30]={refresh:this.isIndent?function(a,b){var c=this.getContext(b),d=CKEDITOR.plugins.indentList.firstItemInPath(this.context,b,c);return c&&this.isIndent&&!d?m:l}:function(a,b){return!this.getContext(b)||this.isIndent?l:m},exec:CKEDITOR.tools.bind(f,this)}} -var c=CKEDITOR.plugins.indent;c.registerCommands(b,{indentlist:new d(b,"indentlist",!0),outdentlist:new d(b,"outdentlist")});CKEDITOR.tools.extend(d.prototype,c.specificDefinition.prototype,{context:{ol:1,ul:1}})}});CKEDITOR.plugins.indentList={};CKEDITOR.plugins.indentList.firstItemInPath=function(b,d,c){var a=d.contains(h);c||(c=d.contains(b));return c&&a&&a.equals(c.getFirst(h))}}(),function(){function f(e,d){d=void 0===d||d;var f;if(d)f=e.getComputedStyle("text-align");else{for(;!e.hasAttribute|| -!e.hasAttribute("align")&&!e.getStyle("text-align");){f=e.getParent();if(!f)break;e=f}f=e.getStyle("text-align")||e.getAttribute("align")||""}f&&(f=f.replace(/(?:-(?:moz|webkit)-)?(?:start|auto)/i,""));!f&&d&&(f="rtl"==e.getComputedStyle("direction")?"right":"left");return f}function h(e,d,f){this.editor=e;this.name=d;this.value=f;this.context="p";d=e.config.justifyClasses;var h=e.config.enterMode==CKEDITOR.ENTER_P?"p":"div";if(d){switch(f){case "left":this.cssClassName=d[0];break;case "center":this.cssClassName= -d[1];break;case "right":this.cssClassName=d[2];break;case "justify":this.cssClassName=d[3]}this.cssClassRegex=new RegExp("(?:^|\\s+)(?:"+d.join("|")+")(?\x3d$|\\s)");this.requiredContent=h+"("+this.cssClassName+")"}else this.requiredContent=h+"{text-align}";this.allowedContent={"caption div h1 h2 h3 h4 h5 h6 p pre td th li":{propertiesOnly:!0,styles:this.cssClassName?null:"text-align",classes:this.cssClassName||null}};e.config.enterMode==CKEDITOR.ENTER_BR&&(this.allowedContent.div=!0)}function e(e){var d= -e.editor,f=d.createRange();f.setStartBefore(e.data.node);f.setEndAfter(e.data.node);for(var h=new CKEDITOR.dom.walker(f),b;b=h.next();)if(b.type==CKEDITOR.NODE_ELEMENT)if(!b.equals(e.data.node)&&b.getDirection())f.setStartAfter(b),h=new CKEDITOR.dom.walker(f);else{var g=d.config.justifyClasses;g&&(b.hasClass(g[0])?(b.removeClass(g[0]),b.addClass(g[2])):b.hasClass(g[2])&&(b.removeClass(g[2]),b.addClass(g[0])));g=b.getStyle("text-align");"left"==g?b.setStyle("text-align","right"):"right"==g&&b.setStyle("text-align", -"left")}}h.prototype={exec:function(e){var d=e.getSelection(),h=e.config.enterMode;if(d){for(var m=d.createBookmarks(),b=d.getRanges(),g=this.cssClassName,c,a,n=e.config.useComputedState,n=void 0===n||n,w=b.length-1;0<=w;w--)for(c=b[w].createIterator(),c.enlargeBr=h!=CKEDITOR.ENTER_BR;a=c.getNextParagraph(h==CKEDITOR.ENTER_P?"p":"div");)if(!a.isReadOnly()){var v=a.getName(),p;p=e.activeFilter.check(v+"{text-align}");if((v=e.activeFilter.check(v+"("+g+")"))||p){a.removeAttribute("align");a.removeStyle("text-align"); -var r=g&&(a.$.className=CKEDITOR.tools.ltrim(a.$.className.replace(this.cssClassRegex,""))),q=this.state==CKEDITOR.TRISTATE_OFF&&(!n||f(a,!0)!=this.value);g&&v?q?a.addClass(g):r||a.removeAttribute("class"):q&&p&&a.setStyle("text-align",this.value)}}e.focus();e.forceNextSelectionCheck();d.selectBookmarks(m)}},refresh:function(e,d){var h=d.block||d.blockLimit,m=h.getName(),b=h.equals(e.editable()),m=this.cssClassName?e.activeFilter.check(m+"("+this.cssClassName+")"):e.activeFilter.check(m+"{text-align}"); -b&&1===d.elements.length?this.setState(CKEDITOR.TRISTATE_OFF):!b&&m?this.setState(f(h,this.editor.config.useComputedState)==this.value?CKEDITOR.TRISTATE_ON:CKEDITOR.TRISTATE_OFF):this.setState(CKEDITOR.TRISTATE_DISABLED)}};CKEDITOR.plugins.add("justify",{init:function(f){if(!f.blockless){var d=new h(f,"justifyleft","left"),l=new h(f,"justifycenter","center"),m=new h(f,"justifyright","right"),b=new h(f,"justifyblock","justify");f.addCommand("justifyleft",d);f.addCommand("justifycenter",l);f.addCommand("justifyright", -m);f.addCommand("justifyblock",b);f.ui.addButton&&(f.ui.addButton("JustifyLeft",{label:f.lang.common.alignLeft,command:"justifyleft",toolbar:"align,10"}),f.ui.addButton("JustifyCenter",{label:f.lang.common.center,command:"justifycenter",toolbar:"align,20"}),f.ui.addButton("JustifyRight",{label:f.lang.common.alignRight,command:"justifyright",toolbar:"align,30"}),f.ui.addButton("JustifyBlock",{label:f.lang.common.justify,command:"justifyblock",toolbar:"align,40"}));f.on("dirChanged",e)}}})}(),CKEDITOR.plugins.add("menubutton", -{requires:"button,menu",onLoad:function(){var f=function(f){var e=this._,k=e.menu;e.state!==CKEDITOR.TRISTATE_DISABLED&&(e.on&&k?k.hide():(e.previousState=e.state,k||(k=e.menu=new CKEDITOR.menu(f,{panel:{className:"cke_menu_panel",attributes:{"aria-label":f.lang.common.options}}}),k.onHide=CKEDITOR.tools.bind(function(){var d=this.command?f.getCommand(this.command).modes:this.modes;this.setState(!d||d[f.mode]?e.previousState:CKEDITOR.TRISTATE_DISABLED);e.on=0},this),this.onMenu&&k.addListener(this.onMenu)), -this.setState(CKEDITOR.TRISTATE_ON),e.on=1,setTimeout(function(){k.show(CKEDITOR.document.getById(e.id),4)},0)))};CKEDITOR.ui.menuButton=CKEDITOR.tools.createClass({base:CKEDITOR.ui.button,$:function(h){delete h.panel;this.base(h);this.hasArrow=!0;this.click=f},statics:{handler:{create:function(f){return new CKEDITOR.ui.menuButton(f)}}}})},beforeInit:function(f){f.ui.addHandler(CKEDITOR.UI_MENUBUTTON,CKEDITOR.ui.menuButton.handler)}}),CKEDITOR.UI_MENUBUTTON="menubutton","use strict",function(){CKEDITOR.plugins.add("language", -{requires:"menubutton",init:function(f){var h=f.config.language_list||["ar:Arabic:rtl","fr:French","es:Spanish"],e=this,k=f.lang.language,d={},l,m,b,g;f.addCommand("language",{allowedContent:"span[!lang,!dir]",requiredContent:"span[lang,dir]",contextSensitive:!0,exec:function(b,a){var g=d["language_"+a];if(g)b[g.style.checkActive(b.elementPath(),b)?"removeStyle":"applyStyle"](g.style)},refresh:function(b){this.setState(e.getCurrentLangElement(b)?CKEDITOR.TRISTATE_ON:CKEDITOR.TRISTATE_OFF)}});for(g= -0;g<h.length;g++)l=h[g].split(":"),m=l[0],b="language_"+m,d[b]={label:l[1],langId:m,group:"language",order:g,ltr:"rtl"!=(""+l[2]).toLowerCase(),onClick:function(){f.execCommand("language",this.langId)},role:"menuitemcheckbox"},d[b].style=new CKEDITOR.style({element:"span",attributes:{lang:m,dir:d[b].ltr?"ltr":"rtl"}});d.language_remove={label:k.remove,group:"language_remove",state:CKEDITOR.TRISTATE_DISABLED,order:d.length,onClick:function(){var b=e.getCurrentLangElement(f);b&&f.execCommand("language", -b.getAttribute("lang"))}};f.addMenuGroup("language",1);f.addMenuGroup("language_remove");f.addMenuItems(d);f.ui.add("Language",CKEDITOR.UI_MENUBUTTON,{label:k.button,allowedContent:"span[!lang,!dir]",requiredContent:"span[lang,dir]",toolbar:"bidi,30",command:"language",onMenu:function(){var b={},a=e.getCurrentLangElement(f),g;for(g in d)b[g]=CKEDITOR.TRISTATE_OFF;b.language_remove=a?CKEDITOR.TRISTATE_OFF:CKEDITOR.TRISTATE_DISABLED;a&&(b["language_"+a.getAttribute("lang")]=CKEDITOR.TRISTATE_ON);return b}}); -f.addRemoveFormatFilter&&f.addRemoveFormatFilter(function(b){return!(b.is("span")&&b.getAttribute("dir")&&b.getAttribute("lang"))})},getCurrentLangElement:function(f){var h=f.elementPath();f=h&&h.elements;var e;if(h)for(var k=0;k<f.length;k++)h=f[k],!e&&"span"==h.getName()&&h.hasAttribute("dir")&&h.hasAttribute("lang")&&(e=h);return e}})}(),function(){function f(a,b,c){function d(c){if(!(!(l=k[c?"getFirst":"getLast"]())||l.is&&l.isBlockBoundary()||!(m=b.root[c?"getPrevious":"getNext"](CKEDITOR.dom.walker.invisible(!0)))|| -m.is&&m.isBlockBoundary({br:1})))a.document.createElement("br")[c?"insertBefore":"insertAfter"](l)}for(var g=CKEDITOR.plugins.list.listToArray(b.root,c),e=[],f=0;f<b.contents.length;f++){var h=b.contents[f];(h=h.getAscendant("li",!0))&&!h.getCustomData("list_item_processed")&&(e.push(h),CKEDITOR.dom.element.setMarker(c,h,"list_item_processed",!0))}h=null;for(f=0;f<e.length;f++)h=e[f].getCustomData("listarray_index"),g[h].indent=-1;for(f=h+1;f<g.length;f++)if(g[f].indent>g[f-1].indent+1){e=g[f-1].indent+ -1-g[f].indent;for(h=g[f].indent;g[f]&&g[f].indent>=h;)g[f].indent+=e,f++;f--}var k=CKEDITOR.plugins.list.arrayToList(g,c,null,a.config.enterMode,b.root.getAttribute("dir")).listNode,l,m;d(!0);d();k.replace(b.root);a.fire("contentDomInvalidated")}function h(a,b){this.name=a;this.context=this.type=b;this.allowedContent=b+" li";this.requiredContent=b}function e(a,b,c,d){for(var g,e;g=a[d?"getLast":"getFirst"](v);)(e=g.getDirection(1))!==b.getDirection(1)&&g.setAttribute("dir",e),g.remove(),c?g[d?"insertBefore": -"insertAfter"](c):b.append(g,d)}function k(b){function c(d){var g=b[d?"getPrevious":"getNext"](a);g&&g.type==CKEDITOR.NODE_ELEMENT&&g.is(b.getName())&&(e(b,g,null,!d),b.remove(),b=g)}c();c(1)}function d(a){return a.type==CKEDITOR.NODE_ELEMENT&&(a.getName()in CKEDITOR.dtd.$block||a.getName()in CKEDITOR.dtd.$listItem)&&CKEDITOR.dtd[a.getName()]["#"]}function l(b,c,d){b.fire("saveSnapshot");d.enlarge(CKEDITOR.ENLARGE_LIST_ITEM_CONTENTS);var g=d.extractContents();c.trim(!1,!0);var f=c.createBookmark(), -h=new CKEDITOR.dom.elementPath(c.startContainer),l=h.block,h=h.lastElement.getAscendant("li",1)||l,t=new CKEDITOR.dom.elementPath(d.startContainer),B=t.contains(CKEDITOR.dtd.$listItem),t=t.contains(CKEDITOR.dtd.$list);l?(l=l.getBogus())&&l.remove():t&&(l=t.getPrevious(a))&&n(l)&&l.remove();(l=g.getLast())&&l.type==CKEDITOR.NODE_ELEMENT&&l.is("br")&&l.remove();(l=c.startContainer.getChild(c.startOffset))?g.insertBefore(l):c.startContainer.append(g);B&&(g=m(B))&&(h.contains(B)?(e(g,B.getParent(),B), -g.remove()):h.append(g));for(;d.checkStartOfBlock()&&d.checkEndOfBlock();){t=d.startPath();g=t.block;if(!g)break;g.is("li")&&(h=g.getParent(),g.equals(h.getLast(a))&&g.equals(h.getFirst(a))&&(g=h));d.moveToPosition(g,CKEDITOR.POSITION_BEFORE_START);g.remove()}d=d.clone();g=b.editable();d.setEndAt(g,CKEDITOR.POSITION_BEFORE_END);d=new CKEDITOR.dom.walker(d);d.evaluator=function(b){return a(b)&&!n(b)};(d=d.next())&&d.type==CKEDITOR.NODE_ELEMENT&&d.getName()in CKEDITOR.dtd.$list&&k(d);c.moveToBookmark(f); -c.select();b.fire("saveSnapshot")}function m(c){return(c=c.getLast(a))&&c.type==CKEDITOR.NODE_ELEMENT&&c.getName()in b?c:null}var b={ol:1,ul:1},g=CKEDITOR.dom.walker.whitespaces(),c=CKEDITOR.dom.walker.bookmark(),a=function(a){return!(g(a)||c(a))},n=CKEDITOR.dom.walker.bogus();CKEDITOR.plugins.list={listToArray:function(a,c,d,g,e){if(!b[a.getName()])return[];g||(g=0);d||(d=[]);for(var f=0,h=a.getChildCount();f<h;f++){var k=a.getChild(f);k.type==CKEDITOR.NODE_ELEMENT&&k.getName()in CKEDITOR.dtd.$list&& -CKEDITOR.plugins.list.listToArray(k,c,d,g+1);if("li"==k.$.nodeName.toLowerCase()){var l={parent:a,indent:g,element:k,contents:[]};e?l.grandparent=e:(l.grandparent=a.getParent(),l.grandparent&&"li"==l.grandparent.$.nodeName.toLowerCase()&&(l.grandparent=l.grandparent.getParent()));c&&CKEDITOR.dom.element.setMarker(c,k,"listarray_index",d.length);d.push(l);for(var m=0,n=k.getChildCount(),w;m<n;m++)w=k.getChild(m),w.type==CKEDITOR.NODE_ELEMENT&&b[w.getName()]?CKEDITOR.plugins.list.listToArray(w,c,d, -g+1,l.grandparent):l.contents.push(w)}}return d},arrayToList:function(d,g,e,f,h){e||(e=0);if(!d||d.length<e+1)return null;for(var k,l=d[e].parent.getDocument(),m=new CKEDITOR.dom.documentFragment(l),n=null,y=e,z=Math.max(d[e].indent,0),w=null,v,F,H=f==CKEDITOR.ENTER_P?"p":"div";;){var G=d[y];k=G.grandparent;v=G.element.getDirection(1);if(G.indent==z){n&&d[y].parent.getName()==n.getName()||(n=d[y].parent.clone(!1,1),h&&n.setAttribute("dir",h),m.append(n));w=n.append(G.element.clone(0,1));v!=n.getDirection(1)&& -w.setAttribute("dir",v);for(k=0;k<G.contents.length;k++)w.append(G.contents[k].clone(1,1));y++}else if(G.indent==Math.max(z,0)+1)G=d[y-1].element.getDirection(1),y=CKEDITOR.plugins.list.arrayToList(d,null,y,f,G!=v?v:null),!w.getChildCount()&&CKEDITOR.env.needsNbspFiller&&7>=l.$.documentMode&&w.append(l.createText(" ")),w.append(y.listNode),y=y.nextIndex;else if(-1==G.indent&&!e&&k){b[k.getName()]?(w=G.element.clone(!1,!0),v!=k.getDirection(1)&&w.setAttribute("dir",v)):w=new CKEDITOR.dom.documentFragment(l); -var n=k.getDirection(1)!=v,L=G.element,O=L.getAttribute("class"),C=L.getAttribute("style"),S=w.type==CKEDITOR.NODE_DOCUMENT_FRAGMENT&&(f!=CKEDITOR.ENTER_BR||n||C||O),J,R=G.contents.length,K;for(k=0;k<R;k++)if(J=G.contents[k],c(J)&&1<R)S?K=J.clone(1,1):w.append(J.clone(1,1));else if(J.type==CKEDITOR.NODE_ELEMENT&&J.isBlockBoundary()){n&&!J.getDirection()&&J.setAttribute("dir",v);F=J;var U=L.getAttribute("style");U&&F.setAttribute("style",U.replace(/([^;])$/,"$1;")+(F.getAttribute("style")||""));O&& -J.addClass(O);F=null;K&&(w.append(K),K=null);w.append(J.clone(1,1))}else S?(F||(F=l.createElement(H),w.append(F),n&&F.setAttribute("dir",v)),C&&F.setAttribute("style",C),O&&F.setAttribute("class",O),K&&(F.append(K),K=null),F.append(J.clone(1,1))):w.append(J.clone(1,1));K&&((F||w).append(K),K=null);w.type==CKEDITOR.NODE_DOCUMENT_FRAGMENT&&y!=d.length-1&&(CKEDITOR.env.needsBrFiller&&(v=w.getLast())&&v.type==CKEDITOR.NODE_ELEMENT&&v.is("br")&&v.remove(),(v=w.getLast(a))&&v.type==CKEDITOR.NODE_ELEMENT&& -v.is(CKEDITOR.dtd.$block)||w.append(l.createElement("br")));v=w.$.nodeName.toLowerCase();"div"!=v&&"p"!=v||w.appendBogus();m.append(w);n=null;y++}else return null;F=null;if(d.length<=y||Math.max(d[y].indent,0)<z)break}if(g)for(d=m.getFirst();d;){if(d.type==CKEDITOR.NODE_ELEMENT&&(CKEDITOR.dom.element.clearMarkers(g,d),d.getName()in CKEDITOR.dtd.$listItem&&(e=d,l=h=f=void 0,f=e.getDirection()))){for(h=e.getParent();h&&!(l=h.getDirection());)h=h.getParent();f==l&&e.removeAttribute("dir")}d=d.getNextSourceNode()}return{listNode:m, -nextIndex:y}}};var w=/^h[1-6]$/,v=CKEDITOR.dom.walker.nodeType(CKEDITOR.NODE_ELEMENT);h.prototype={exec:function(c){this.refresh(c,c.elementPath());var d=c.config,g=c.getSelection(),e=g&&g.getRanges();if(this.state==CKEDITOR.TRISTATE_OFF){var h=c.editable();if(h.getFirst(a)){var l=1==e.length&&e[0];(d=l&&l.getEnclosedNode())&&d.is&&this.type==d.getName()&&this.setState(CKEDITOR.TRISTATE_ON)}else d.enterMode==CKEDITOR.ENTER_BR?h.appendBogus():e[0].fixBlock(1,d.enterMode==CKEDITOR.ENTER_P?"p":"div"), -g.selectRanges(e)}for(var d=g.createBookmarks(!0),h=[],m={},e=e.createIterator(),n=0;(l=e.getNextRange())&&++n;){var B=l.getBoundaryNodes(),y=B.startNode,z=B.endNode;y.type==CKEDITOR.NODE_ELEMENT&&"td"==y.getName()&&l.setStartAt(B.startNode,CKEDITOR.POSITION_AFTER_START);z.type==CKEDITOR.NODE_ELEMENT&&"td"==z.getName()&&l.setEndAt(B.endNode,CKEDITOR.POSITION_BEFORE_END);l=l.createIterator();for(l.forceBrBreak=this.state==CKEDITOR.TRISTATE_OFF;B=l.getNextParagraph();)if(!B.getCustomData("list_block")){CKEDITOR.dom.element.setMarker(m, -B,"list_block",1);for(var v=c.elementPath(B),y=v.elements,z=0,v=v.blockLimit,E,F=y.length-1;0<=F&&(E=y[F]);F--)if(b[E.getName()]&&v.contains(E)){v.removeCustomData("list_group_object_"+n);(y=E.getCustomData("list_group_object"))?y.contents.push(B):(y={root:E,contents:[B]},h.push(y),CKEDITOR.dom.element.setMarker(m,E,"list_group_object",y));z=1;break}z||(z=v,z.getCustomData("list_group_object_"+n)?z.getCustomData("list_group_object_"+n).contents.push(B):(y={root:z,contents:[B]},CKEDITOR.dom.element.setMarker(m, -z,"list_group_object_"+n,y),h.push(y)))}}for(E=[];0<h.length;)if(y=h.shift(),this.state==CKEDITOR.TRISTATE_OFF)if(b[y.root.getName()]){e=c;n=y;y=m;l=E;z=CKEDITOR.plugins.list.listToArray(n.root,y);v=[];for(B=0;B<n.contents.length;B++)F=n.contents[B],(F=F.getAscendant("li",!0))&&!F.getCustomData("list_item_processed")&&(v.push(F),CKEDITOR.dom.element.setMarker(y,F,"list_item_processed",!0));for(var F=n.root.getDocument(),H=void 0,G=void 0,B=0;B<v.length;B++){var L=v[B].getCustomData("listarray_index"), -H=z[L].parent;H.is(this.type)||(G=F.createElement(this.type),H.copyAttributes(G,{start:1,type:1}),G.removeStyle("list-style-type"),z[L].parent=G)}y=CKEDITOR.plugins.list.arrayToList(z,y,null,e.config.enterMode);z=void 0;v=y.listNode.getChildCount();for(B=0;B<v&&(z=y.listNode.getChild(B));B++)z.getName()==this.type&&l.push(z);y.listNode.replace(n.root);e.fire("contentDomInvalidated")}else{z=c;l=y;B=E;v=l.contents;e=l.root.getDocument();n=[];1==v.length&&v[0].equals(l.root)&&(y=e.createElement("div"), -v[0].moveChildren&&v[0].moveChildren(y),v[0].append(y),v[0]=y);l=l.contents[0].getParent();for(F=0;F<v.length;F++)l=l.getCommonAncestor(v[F].getParent());H=z.config.useComputedState;z=y=void 0;H=void 0===H||H;for(F=0;F<v.length;F++)for(G=v[F];L=G.getParent();){if(L.equals(l)){n.push(G);!z&&G.getDirection()&&(z=1);G=G.getDirection(H);null!==y&&(y=y&&y!=G?null:G);break}G=L}if(!(1>n.length)){v=n[n.length-1].getNext();F=e.createElement(this.type);B.push(F);for(H=B=void 0;n.length;)B=n.shift(),H=e.createElement("li"), -G=B,G.is("pre")||w.test(G.getName())||"false"==G.getAttribute("contenteditable")?B.appendTo(H):(B.copyAttributes(H),y&&B.getDirection()&&(H.removeStyle("direction"),H.removeAttribute("dir")),B.moveChildren(H),B.remove()),H.appendTo(F);y&&z&&F.setAttribute("dir",y);v?F.insertBefore(v):F.appendTo(l)}}else this.state==CKEDITOR.TRISTATE_ON&&b[y.root.getName()]&&f.call(this,c,y,m);for(F=0;F<E.length;F++)k(E[F]);CKEDITOR.dom.element.clearAllMarkers(m);g.selectBookmarks(d);c.focus()},refresh:function(a, -c){var d=c.contains(b,1),g=c.blockLimit||c.root;d&&g.contains(d)?this.setState(d.is(this.type)?CKEDITOR.TRISTATE_ON:CKEDITOR.TRISTATE_OFF):this.setState(CKEDITOR.TRISTATE_OFF)}};CKEDITOR.plugins.add("list",{requires:"indentlist",init:function(c){c.blockless||(c.addCommand("numberedlist",new h("numberedlist","ol")),c.addCommand("bulletedlist",new h("bulletedlist","ul")),c.ui.addButton&&(c.ui.addButton("NumberedList",{label:c.lang.list.numberedlist,command:"numberedlist",directional:!0,toolbar:"list,10"}), -c.ui.addButton("BulletedList",{label:c.lang.list.bulletedlist,command:"bulletedlist",directional:!0,toolbar:"list,20"})),c.on("key",function(g){var e=g.data.domEvent.getKey(),f;if("wysiwyg"==c.mode&&e in{8:1,46:1}){var h=c.getSelection().getRanges()[0],k=h&&h.startPath();if(h&&h.collapsed){var w=8==e,t=c.editable(),v=new CKEDITOR.dom.walker(h.clone());v.evaluator=function(b){return a(b)&&!n(b)};v.guard=function(a,b){return!(b&&a.type==CKEDITOR.NODE_ELEMENT&&a.is("table"))};e=h.clone();if(w){var y; -(y=k.contains(b))&&h.checkBoundaryOfElement(y,CKEDITOR.START)&&(y=y.getParent())&&y.is("li")&&(y=m(y))?(f=y,y=y.getPrevious(a),e.moveToPosition(y&&n(y)?y:f,CKEDITOR.POSITION_BEFORE_START)):(v.range.setStartAt(t,CKEDITOR.POSITION_AFTER_START),v.range.setEnd(h.startContainer,h.startOffset),(y=v.previous())&&y.type==CKEDITOR.NODE_ELEMENT&&(y.getName()in b||y.is("li"))&&(y.is("li")||(v.range.selectNodeContents(y),v.reset(),v.evaluator=d,y=v.previous()),f=y,e.moveToElementEditEnd(f),e.moveToPosition(e.endPath().block, -CKEDITOR.POSITION_BEFORE_END)));if(f)l(c,e,h),g.cancel();else{var z=k.contains(b);z&&h.checkBoundaryOfElement(z,CKEDITOR.START)&&(f=z.getFirst(a),h.checkBoundaryOfElement(f,CKEDITOR.START)&&(y=z.getPrevious(a),m(f)?y&&(h.moveToElementEditEnd(y),h.select()):c.execCommand("outdent"),g.cancel()))}}else if(f=k.contains("li")){if(v.range.setEndAt(t,CKEDITOR.POSITION_BEFORE_END),w=(t=f.getLast(a))&&d(t)?t:f,k=0,(y=v.next())&&y.type==CKEDITOR.NODE_ELEMENT&&y.getName()in b&&y.equals(t)?(k=1,y=v.next()):h.checkBoundaryOfElement(w, -CKEDITOR.END)&&(k=2),k&&y){h=h.clone();h.moveToElementEditStart(y);if(1==k&&(e.optimize(),!e.startContainer.equals(f))){for(f=e.startContainer;f.is(CKEDITOR.dtd.$inline);)z=f,f=f.getParent();z&&e.moveToPosition(z,CKEDITOR.POSITION_AFTER_END)}2==k&&(e.moveToPosition(e.endPath().block,CKEDITOR.POSITION_BEFORE_END),h.endPath().block&&h.moveToPosition(h.endPath().block,CKEDITOR.POSITION_AFTER_START));l(c,e,h);g.cancel()}}else v.range.setEndAt(t,CKEDITOR.POSITION_BEFORE_END),(y=v.next())&&y.type==CKEDITOR.NODE_ELEMENT&& -y.is(b)&&(y=y.getFirst(a),k.block&&h.checkStartOfBlock()&&h.checkEndOfBlock()?(k.block.remove(),h.moveToElementEditStart(y),h.select()):m(y)?(h.moveToElementEditStart(y),h.select()):(h=h.clone(),h.moveToElementEditStart(y),l(c,e,h)),g.cancel());setTimeout(function(){c.selectionChange(1)})}}}))}})}(),"use strict",function(){function f(a,b,c){return n(b)&&n(c)&&c.equals(b.getNext(function(a){return!(ca(a)||W(a)||w(a))}))}function h(a){this.upper=a[0];this.lower=a[1];this.set.apply(this,a.slice(2))} -function e(a){var b=a.element;if(b&&n(b)&&(b=b.getAscendant(a.triggers,!0))&&a.editable.contains(b)){var c=m(b);if("true"==c.getAttribute("contenteditable"))return b;if(c.is(a.triggers))return c}return null}function k(a,b,c){D(a,b);D(a,c);a=b.size.bottom;c=c.size.top;return a&&c?0|(a+c)/2:a||c}function d(b,c,d){return c=c[d?"getPrevious":"getNext"](function(c){return c&&c.type==CKEDITOR.NODE_TEXT&&!ca(c)||n(c)&&!w(c)&&!a(b,c)})}function l(a,b,c){return a>b&&a<c}function m(a,b){if(a.data("cke-editable"))return null; -for(b||(a=a.getParent());a&&!a.data("cke-editable");){if(a.hasAttribute("contenteditable"))return a;a=a.getParent()}return null}function b(a){var b=a.doc,c=E('\x3cspan contenteditable\x3d"false" data-cke-magic-line\x3d"1" style\x3d"'+V+"position:absolute;border-top:1px dashed "+a.boxColor+'"\x3e\x3c/span\x3e',b),d=CKEDITOR.getUrl(this.path+"images/"+(F.hidpi?"hidpi/":"")+"icon"+(a.rtl?"-rtl":"")+".png");z(c,{attach:function(){this.wrap.getParent()||this.wrap.appendTo(a.editable,!0);return this},lineChildren:[z(E('\x3cspan title\x3d"'+ -a.editor.lang.magicline.title+'" contenteditable\x3d"false"\x3e\x26#8629;\x3c/span\x3e',b),{base:V+"height:17px;width:17px;"+(a.rtl?"left":"right")+":17px;background:url("+d+") center no-repeat "+a.boxColor+";cursor:pointer;"+(F.hc?"font-size: 15px;line-height:14px;border:1px solid #fff;text-align:center;":"")+(F.hidpi?"background-size: 9px 10px;":""),looks:["top:-8px; border-radius: 2px;","top:-17px; border-radius: 2px 2px 0px 0px;","top:-1px; border-radius: 0px 0px 2px 2px;"]}),z(E(P,b),{base:T+ -"left:0px;border-left-color:"+a.boxColor+";",looks:["border-width:8px 0 8px 8px;top:-8px","border-width:8px 0 0 8px;top:-8px","border-width:0 0 8px 8px;top:0px"]}),z(E(P,b),{base:T+"right:0px;border-right-color:"+a.boxColor+";",looks:["border-width:8px 8px 8px 0;top:-8px","border-width:8px 8px 0 0;top:-8px","border-width:0 8px 8px 0;top:0px"]})],detach:function(){this.wrap.getParent()&&this.wrap.remove();return this},mouseNear:function(){D(a,this);var b=a.holdDistance,c=this.size;return c&&l(a.mouse.y, -c.top-b,c.bottom+b)&&l(a.mouse.x,c.left-b,c.right+b)?!0:!1},place:function(){var b=a.view,c=a.editable,d=a.trigger,g=d.upper,e=d.lower,f=g||e,h=f.getParent(),k={};this.trigger=d;g&&D(a,g,!0);e&&D(a,e,!0);D(a,h,!0);a.inInlineMode&&t(a,!0);h.equals(c)?(k.left=b.scroll.x,k.right=-b.scroll.x,k.width=""):(k.left=f.size.left-f.size.margin.left+b.scroll.x-(a.inInlineMode?b.editable.left+b.editable.border.left:0),k.width=f.size.outerWidth+f.size.margin.left+f.size.margin.right+b.scroll.x,k.right="");g&&e? -k.top=g.size.margin.bottom===e.size.margin.top?0|g.size.bottom+g.size.margin.bottom/2:g.size.margin.bottom<e.size.margin.top?g.size.bottom+g.size.margin.bottom:g.size.bottom+g.size.margin.bottom-e.size.margin.top:g?e||(k.top=g.size.bottom+g.size.margin.bottom):k.top=e.size.top-e.size.margin.top;d.is(R)||l(k.top,b.scroll.y-15,b.scroll.y+5)?(k.top=a.inInlineMode?0:b.scroll.y,this.look(R)):d.is(K)||l(k.top,b.pane.bottom-5,b.pane.bottom+15)?(k.top=a.inInlineMode?b.editable.height+b.editable.padding.top+ +init:function(a){if(!a.plugins.detectConflict("image2",["easyimage"])){var b=a.config,c=a.lang.image2,d=f(a);b.filebrowserImage2BrowseUrl=b.filebrowserImageBrowseUrl;b.filebrowserImage2UploadUrl=b.filebrowserImageUploadUrl;d.pathName=c.pathName;d.editables.caption.pathName=c.pathNameCaption;a.widgets.add("image",d);a.ui.addButton&&a.ui.addButton("Image",{label:a.lang.common.image,command:"image",toolbar:"insert,10"});a.contextMenu&&(a.addMenuGroup("image",10),a.addMenuItem("image",{label:c.menu,command:"image", +group:"image"}));CKEDITOR.dialog.add("image2",this.path+"dialogs/image2.js")}},afterInit:function(a){var c={left:1,right:1,center:1,block:1},d=m(a),e;for(e in c)d(e);b(a)}});CKEDITOR.plugins.image2={stateShifter:function(a){function b(a,f){var g={};e?g.attributes={"class":e[1]}:g.styles={"text-align":"center"};g=d.createElement(a.activeEnterMode==CKEDITOR.ENTER_P?"p":"div",g);c(g,f);f.move(g);return g}function c(b,d){if(d.getParent()){var e=a.createRange();e.moveToPosition(d,CKEDITOR.POSITION_BEFORE_START); +d.remove();g.insertElementIntoRange(b,e)}else b.replace(d)}var d=a.document,e=a.config.image2_alignClasses,f=a.config.image2_captionedClass,g=a.editable(),h=["hasCaption","align","link"],k={align:function(c,d,f){var g=c.element;c.changed.align?c.newData.hasCaption||("center"==f&&(c.deflate(),c.element=b(a,g)),c.changed.hasCaption||"center"!=d||"center"==f||(c.deflate(),d=g.findOne("a,img"),d.replace(g),c.element=d)):"center"==f&&c.changed.hasCaption&&!c.newData.hasCaption&&(c.deflate(),c.element= +b(a,g));!e&&g.is("figure")&&("center"==f?g.setStyle("display","inline-block"):g.removeStyle("display"))},hasCaption:function(b,e,g){b.changed.hasCaption&&(e=b.element.is({img:1,a:1})?b.element:b.element.findOne("a,img"),b.deflate(),g?(g=CKEDITOR.dom.element.createFromHtml(w.output({captionedClass:f,captionPlaceholder:a.lang.image2.captionPlaceholder}),d),c(g,b.element),e.replace(g.findOne("img")),b.element=g):(e.replace(b.element),b.element=e))},link:function(b,c,e){if(b.changed.link){var f=b.element.is("img")? +b.element:b.element.findOne("img"),g=b.element.is("a")?b.element:b.element.findOne("a"),h=b.element.is("a")&&!e||b.element.is("img")&&e,k;h&&b.deflate();e?(c||(k=d.createElement("a",{attributes:{href:b.newData.link.url}}),k.replace(f),f.move(k)),e=CKEDITOR.plugins.image2.getLinkAttributesGetter()(a,e),CKEDITOR.tools.isEmpty(e.set)||(k||g).setAttributes(e.set),e.removed.length&&(k||g).removeAttributes(e.removed)):(e=g.findOne("img"),e.replace(g),k=e);h&&(b.element=k)}}};return function(a){var b,c; +a.changed={};for(c=0;c<h.length;c++)b=h[c],a.changed[b]=a.oldData?a.oldData[b]!==a.newData[b]:!1;for(c=0;c<h.length;c++)b=h[c],k[b](a,a.oldData?a.oldData[b]:null,a.newData[b]);a.inflate()}},checkHasNaturalRatio:function(a){var b=a.$;a=this.getNatural(a);return Math.round(b.clientWidth/a.width*a.height)==b.clientHeight||Math.round(b.clientHeight/a.height*a.width)==b.clientWidth},getNatural:function(a){if(a.$.naturalWidth)a={width:a.$.naturalWidth,height:a.$.naturalHeight};else{var b=new Image;b.src= +a.getAttribute("src");a={width:b.width,height:b.height}}return a},getLinkAttributesGetter:function(){return CKEDITOR.plugins.link.getLinkAttributes},getLinkAttributesParser:function(){return CKEDITOR.plugins.link.parseLinkAttributes}}}(),CKEDITOR.config.image2_captionedClass="image",function(){function f(f,d){var l,m;d.on("refresh",function(b){var d=[h],c;for(c in b.data.states)d.push(b.data.states[c]);this.setState(CKEDITOR.tools.search(d,e)?e:h)},d,null,100);d.on("exec",function(b){l=f.getSelection(); +m=l.createBookmarks(1);b.data||(b.data={});b.data.done=!1},d,null,0);d.on("exec",function(){f.forceNextSelectionCheck();l.selectBookmarks(m)},d,null,100)}var h=CKEDITOR.TRISTATE_DISABLED,e=CKEDITOR.TRISTATE_OFF;CKEDITOR.plugins.add("indent",{init:function(e){var d=CKEDITOR.plugins.indent.genericDefinition;f(e,e.addCommand("indent",new d(!0)));f(e,e.addCommand("outdent",new d));e.ui.addButton&&(e.ui.addButton("Indent",{label:e.lang.indent.indent,command:"indent",directional:!0,toolbar:"indent,20"}), +e.ui.addButton("Outdent",{label:e.lang.indent.outdent,command:"outdent",directional:!0,toolbar:"indent,10"}));e.on("dirChanged",function(d){var f=e.createRange(),b=d.data.node;f.setStartBefore(b);f.setEndAfter(b);for(var g=new CKEDITOR.dom.walker(f),c;c=g.next();)if(c.type==CKEDITOR.NODE_ELEMENT)if(!c.equals(b)&&c.getDirection())f.setStartAfter(c),g=new CKEDITOR.dom.walker(f);else{var a=e.config.indentClasses;if(a)for(var h="ltr"==d.data.dir?["_rtl",""]:["","_rtl"],w=0;w<a.length;w++)c.hasClass(a[w]+ +h[0])&&(c.removeClass(a[w]+h[0]),c.addClass(a[w]+h[1]));a=c.getStyle("margin-right");h=c.getStyle("margin-left");a?c.setStyle("margin-left",a):c.removeStyle("margin-left");h?c.setStyle("margin-right",h):c.removeStyle("margin-right")}})}});CKEDITOR.plugins.indent={genericDefinition:function(e){this.isIndent=!!e;this.startDisabled=!this.isIndent},specificDefinition:function(e,d,f){this.name=d;this.editor=e;this.jobs={};this.enterBr=e.config.enterMode==CKEDITOR.ENTER_BR;this.isIndent=!!f;this.relatedGlobal= +f?"indent":"outdent";this.indentKey=f?9:CKEDITOR.SHIFT+9;this.database={}},registerCommands:function(e,d){e.on("pluginsLoaded",function(){for(var e in d)(function(d,b){var e=d.getCommand(b.relatedGlobal),c;for(c in b.jobs)e.on("exec",function(a){a.data.done||(d.fire("lockSnapshot"),b.execJob(d,c)&&(a.data.done=!0),d.fire("unlockSnapshot"),CKEDITOR.dom.element.clearAllMarkers(b.database))},this,null,c),e.on("refresh",function(a){a.data.states||(a.data.states={});a.data.states[b.name+"@"+c]=b.refreshJob(d, +c,a.data.path)},this,null,c);d.addFeature(b)})(this,d[e])})}};CKEDITOR.plugins.indent.genericDefinition.prototype={context:"p",exec:function(){}};CKEDITOR.plugins.indent.specificDefinition.prototype={execJob:function(e,d){var f=this.jobs[d];if(f.state!=h)return f.exec.call(this,e)},refreshJob:function(e,d,f){d=this.jobs[d];e.activeFilter.checkFeature(this)?d.state=d.refresh.call(this,e,f):d.state=h;return d.state},getContext:function(e){return e.contains(this.context)}}}(),function(){function f(b){function d(g){for(var h= +k.startContainer,l=k.endContainer;h&&!h.getParent().equals(g);)h=h.getParent();for(;l&&!l.getParent().equals(g);)l=l.getParent();if(!h||!l)return!1;for(var m=[],t=!1;!t;)h.equals(l)&&(t=!0),m.push(h),h=h.getNext();if(1>m.length)return!1;h=g.getParents(!0);for(l=0;l<h.length;l++)if(h[l].getName&&f[h[l].getName()]){g=h[l];break}for(var h=c.isIndent?1:-1,l=m[0],m=m[m.length-1],t=CKEDITOR.plugins.list.listToArray(g,a),u=t[m.getCustomData("listarray_index")].indent,l=l.getCustomData("listarray_index");l<= +m.getCustomData("listarray_index");l++)if(t[l].indent+=h,0<h){for(var p=t[l].parent,x=l-1;0<=x;x--)if(t[x].indent===h){p=t[x].parent;break}t[l].parent=new CKEDITOR.dom.element(p.getName(),p.getDocument())}for(l=m.getCustomData("listarray_index")+1;l<t.length&&t[l].indent>u;l++)t[l].indent+=h;h=CKEDITOR.plugins.list.arrayToList(t,a,null,b.config.enterMode,g.getDirection());if(!c.isIndent){var z;if((z=g.getParent())&&z.is("li"))for(var m=h.listNode.getChildren(),v=[],F,l=m.count()-1;0<=l;l--)(F=m.getItem(l))&& +F.is&&F.is("li")&&v.push(F)}h&&h.listNode.replace(g);if(v&&v.length)for(l=0;l<v.length;l++){for(F=g=v[l];(F=F.getNext())&&F.is&&F.getName()in f;)CKEDITOR.env.needsNbspFiller&&!g.getFirst(e)&&g.append(k.document.createText(" ")),g.append(F);g.insertAfter(z)}h&&b.fire("contentDomInvalidated");return!0}for(var c=this,a=this.database,f=this.context,k,l=b.getSelection(),l=(l&&l.getRanges()).createIterator();k=l.getNextRange();){for(var m=k.getCommonAncestor();m&&(m.type!=CKEDITOR.NODE_ELEMENT||!f[m.getName()]);){if(b.editable().equals(m)){m= +!1;break}m=m.getParent()}m||(m=k.startPath().contains(f))&&k.setEndAt(m,CKEDITOR.POSITION_BEFORE_END);if(!m){var p=k.getEnclosedNode();p&&p.type==CKEDITOR.NODE_ELEMENT&&p.getName()in f&&(k.setStartAt(p,CKEDITOR.POSITION_AFTER_START),k.setEndAt(p,CKEDITOR.POSITION_BEFORE_END),m=p)}m&&k.startContainer.type==CKEDITOR.NODE_ELEMENT&&k.startContainer.getName()in f&&(p=new CKEDITOR.dom.walker(k),p.evaluator=h,k.startContainer=p.next());m&&k.endContainer.type==CKEDITOR.NODE_ELEMENT&&k.endContainer.getName()in +f&&(p=new CKEDITOR.dom.walker(k),p.evaluator=h,k.endContainer=p.previous());if(m)return d(m)}return 0}function h(b){return b.type==CKEDITOR.NODE_ELEMENT&&b.is("li")}function e(b){return k(b)&&d(b)}var k=CKEDITOR.dom.walker.whitespaces(!0),d=CKEDITOR.dom.walker.bookmark(!1,!0),l=CKEDITOR.TRISTATE_DISABLED,m=CKEDITOR.TRISTATE_OFF;CKEDITOR.plugins.add("indentlist",{requires:"indent",init:function(b){function d(a){c.specificDefinition.apply(this,arguments);this.requiredContent=["ul","ol"];a.on("key", +function(b){var c=a.elementPath();if("wysiwyg"==a.mode&&b.data.keyCode==this.indentKey&&c){var d=this.getContext(c);!d||this.isIndent&&CKEDITOR.plugins.indentList.firstItemInPath(this.context,c,d)||(a.execCommand(this.relatedGlobal),b.cancel())}},this);this.jobs[this.isIndent?10:30]={refresh:this.isIndent?function(a,b){var c=this.getContext(b),d=CKEDITOR.plugins.indentList.firstItemInPath(this.context,b,c);return c&&this.isIndent&&!d?m:l}:function(a,b){return!this.getContext(b)||this.isIndent?l:m}, +exec:CKEDITOR.tools.bind(f,this)}}var c=CKEDITOR.plugins.indent;c.registerCommands(b,{indentlist:new d(b,"indentlist",!0),outdentlist:new d(b,"outdentlist")});CKEDITOR.tools.extend(d.prototype,c.specificDefinition.prototype,{context:{ol:1,ul:1}})}});CKEDITOR.plugins.indentList={};CKEDITOR.plugins.indentList.firstItemInPath=function(b,d,c){var a=d.contains(h);c||(c=d.contains(b));return c&&a&&a.equals(c.getFirst(h))}}(),function(){function f(e,d){d=void 0===d||d;var f;if(d)f=e.getComputedStyle("text-align"); +else{for(;!e.hasAttribute||!e.hasAttribute("align")&&!e.getStyle("text-align");){f=e.getParent();if(!f)break;e=f}f=e.getStyle("text-align")||e.getAttribute("align")||""}f&&(f=f.replace(/(?:-(?:moz|webkit)-)?(?:start|auto)/i,""));!f&&d&&(f="rtl"==e.getComputedStyle("direction")?"right":"left");return f}function h(e,d,f){this.editor=e;this.name=d;this.value=f;this.context="p";d=e.config.justifyClasses;var h=e.config.enterMode==CKEDITOR.ENTER_P?"p":"div";if(d){switch(f){case "left":this.cssClassName= +d[0];break;case "center":this.cssClassName=d[1];break;case "right":this.cssClassName=d[2];break;case "justify":this.cssClassName=d[3]}this.cssClassRegex=new RegExp("(?:^|\\s+)(?:"+d.join("|")+")(?\x3d$|\\s)");this.requiredContent=h+"("+this.cssClassName+")"}else this.requiredContent=h+"{text-align}";this.allowedContent={"caption div h1 h2 h3 h4 h5 h6 p pre td th li":{propertiesOnly:!0,styles:this.cssClassName?null:"text-align",classes:this.cssClassName||null}};e.config.enterMode==CKEDITOR.ENTER_BR&& +(this.allowedContent.div=!0)}function e(e){var d=e.editor,f=d.createRange();f.setStartBefore(e.data.node);f.setEndAfter(e.data.node);for(var h=new CKEDITOR.dom.walker(f),b;b=h.next();)if(b.type==CKEDITOR.NODE_ELEMENT)if(!b.equals(e.data.node)&&b.getDirection())f.setStartAfter(b),h=new CKEDITOR.dom.walker(f);else{var g=d.config.justifyClasses;g&&(b.hasClass(g[0])?(b.removeClass(g[0]),b.addClass(g[2])):b.hasClass(g[2])&&(b.removeClass(g[2]),b.addClass(g[0])));g=b.getStyle("text-align");"left"==g?b.setStyle("text-align", +"right"):"right"==g&&b.setStyle("text-align","left")}}h.prototype={exec:function(e){var d=e.getSelection(),h=e.config.enterMode;if(d){for(var m=d.createBookmarks(),b=d.getRanges(),g=this.cssClassName,c,a,n=e.config.useComputedState,n=void 0===n||n,w=b.length-1;0<=w;w--)for(c=b[w].createIterator(),c.enlargeBr=h!=CKEDITOR.ENTER_BR;a=c.getNextParagraph(h==CKEDITOR.ENTER_P?"p":"div");)if(!a.isReadOnly()){var v=a.getName(),t;t=e.activeFilter.check(v+"{text-align}");if((v=e.activeFilter.check(v+"("+g+")"))|| +t){a.removeAttribute("align");a.removeStyle("text-align");var p=g&&(a.$.className=CKEDITOR.tools.ltrim(a.$.className.replace(this.cssClassRegex,""))),q=this.state==CKEDITOR.TRISTATE_OFF&&(!n||f(a,!0)!=this.value);g&&v?q?a.addClass(g):p||a.removeAttribute("class"):q&&t&&a.setStyle("text-align",this.value)}}e.focus();e.forceNextSelectionCheck();d.selectBookmarks(m)}},refresh:function(e,d){var h=d.block||d.blockLimit,m=h.getName(),b=h.equals(e.editable()),m=this.cssClassName?e.activeFilter.check(m+"("+ +this.cssClassName+")"):e.activeFilter.check(m+"{text-align}");b&&1===d.elements.length?this.setState(CKEDITOR.TRISTATE_OFF):!b&&m?this.setState(f(h,this.editor.config.useComputedState)==this.value?CKEDITOR.TRISTATE_ON:CKEDITOR.TRISTATE_OFF):this.setState(CKEDITOR.TRISTATE_DISABLED)}};CKEDITOR.plugins.add("justify",{init:function(f){if(!f.blockless){var d=new h(f,"justifyleft","left"),l=new h(f,"justifycenter","center"),m=new h(f,"justifyright","right"),b=new h(f,"justifyblock","justify");f.addCommand("justifyleft", +d);f.addCommand("justifycenter",l);f.addCommand("justifyright",m);f.addCommand("justifyblock",b);f.ui.addButton&&(f.ui.addButton("JustifyLeft",{label:f.lang.common.alignLeft,command:"justifyleft",toolbar:"align,10"}),f.ui.addButton("JustifyCenter",{label:f.lang.common.center,command:"justifycenter",toolbar:"align,20"}),f.ui.addButton("JustifyRight",{label:f.lang.common.alignRight,command:"justifyright",toolbar:"align,30"}),f.ui.addButton("JustifyBlock",{label:f.lang.common.justify,command:"justifyblock", +toolbar:"align,40"}));f.on("dirChanged",e)}}})}(),CKEDITOR.plugins.add("menubutton",{requires:"button,menu",onLoad:function(){var f=function(f){var e=this._,k=e.menu;e.state!==CKEDITOR.TRISTATE_DISABLED&&(e.on&&k?k.hide():(e.previousState=e.state,k||(k=e.menu=new CKEDITOR.menu(f,{panel:{className:"cke_menu_panel",attributes:{"aria-label":f.lang.common.options}}}),k.onHide=CKEDITOR.tools.bind(function(){var d=this.command?f.getCommand(this.command).modes:this.modes;this.setState(!d||d[f.mode]?e.previousState: +CKEDITOR.TRISTATE_DISABLED);e.on=0},this),this.onMenu&&k.addListener(this.onMenu)),this.setState(CKEDITOR.TRISTATE_ON),e.on=1,setTimeout(function(){k.show(CKEDITOR.document.getById(e.id),4)},0)))};CKEDITOR.ui.menuButton=CKEDITOR.tools.createClass({base:CKEDITOR.ui.button,$:function(h){delete h.panel;this.base(h);this.hasArrow=!0;this.click=f},statics:{handler:{create:function(f){return new CKEDITOR.ui.menuButton(f)}}}})},beforeInit:function(f){f.ui.addHandler(CKEDITOR.UI_MENUBUTTON,CKEDITOR.ui.menuButton.handler)}}), +CKEDITOR.UI_MENUBUTTON="menubutton","use strict",function(){CKEDITOR.plugins.add("language",{requires:"menubutton",init:function(f){var h=f.config.language_list||["ar:Arabic:rtl","fr:French","es:Spanish"],e=this,k=f.lang.language,d={},l,m,b,g;f.addCommand("language",{allowedContent:"span[!lang,!dir]",requiredContent:"span[lang,dir]",contextSensitive:!0,exec:function(b,a){var e=d["language_"+a];if(e)b[e.style.checkActive(b.elementPath(),b)?"removeStyle":"applyStyle"](e.style)},refresh:function(b){this.setState(e.getCurrentLangElement(b)? +CKEDITOR.TRISTATE_ON:CKEDITOR.TRISTATE_OFF)}});for(g=0;g<h.length;g++)l=h[g].split(":"),m=l[0],b="language_"+m,d[b]={label:l[1],langId:m,group:"language",order:g,ltr:"rtl"!=(""+l[2]).toLowerCase(),onClick:function(){f.execCommand("language",this.langId)},role:"menuitemcheckbox"},d[b].style=new CKEDITOR.style({element:"span",attributes:{lang:m,dir:d[b].ltr?"ltr":"rtl"}});d.language_remove={label:k.remove,group:"language_remove",state:CKEDITOR.TRISTATE_DISABLED,order:d.length,onClick:function(){var b= +e.getCurrentLangElement(f);b&&f.execCommand("language",b.getAttribute("lang"))}};f.addMenuGroup("language",1);f.addMenuGroup("language_remove");f.addMenuItems(d);f.ui.add("Language",CKEDITOR.UI_MENUBUTTON,{label:k.button,allowedContent:"span[!lang,!dir]",requiredContent:"span[lang,dir]",toolbar:"bidi,30",command:"language",onMenu:function(){var b={},a=e.getCurrentLangElement(f),g;for(g in d)b[g]=CKEDITOR.TRISTATE_OFF;b.language_remove=a?CKEDITOR.TRISTATE_OFF:CKEDITOR.TRISTATE_DISABLED;a&&(b["language_"+ +a.getAttribute("lang")]=CKEDITOR.TRISTATE_ON);return b}});f.addRemoveFormatFilter&&f.addRemoveFormatFilter(function(b){return!(b.is("span")&&b.getAttribute("dir")&&b.getAttribute("lang"))})},getCurrentLangElement:function(f){var h=f.elementPath();f=h&&h.elements;var e;if(h)for(var k=0;k<f.length;k++)h=f[k],!e&&"span"==h.getName()&&h.hasAttribute("dir")&&h.hasAttribute("lang")&&(e=h);return e}})}(),function(){function f(a,b,c){function d(c){if(!(!(l=k[c?"getFirst":"getLast"]())||l.is&&l.isBlockBoundary()|| +!(m=b.root[c?"getPrevious":"getNext"](CKEDITOR.dom.walker.invisible(!0)))||m.is&&m.isBlockBoundary({br:1})))a.document.createElement("br")[c?"insertBefore":"insertAfter"](l)}for(var e=CKEDITOR.plugins.list.listToArray(b.root,c),f=[],g=0;g<b.contents.length;g++){var h=b.contents[g];(h=h.getAscendant("li",!0))&&!h.getCustomData("list_item_processed")&&(f.push(h),CKEDITOR.dom.element.setMarker(c,h,"list_item_processed",!0))}h=null;for(g=0;g<f.length;g++)h=f[g].getCustomData("listarray_index"),e[h].indent= +-1;for(g=h+1;g<e.length;g++)if(e[g].indent>e[g-1].indent+1){f=e[g-1].indent+1-e[g].indent;for(h=e[g].indent;e[g]&&e[g].indent>=h;)e[g].indent+=f,g++;g--}var k=CKEDITOR.plugins.list.arrayToList(e,c,null,a.config.enterMode,b.root.getAttribute("dir")).listNode,l,m;d(!0);d();k.replace(b.root);a.fire("contentDomInvalidated")}function h(a,b){this.name=a;this.context=this.type=b;this.allowedContent=b+" li";this.requiredContent=b}function e(a,b,c,d){for(var e,f;e=a[d?"getLast":"getFirst"](v);)(f=e.getDirection(1))!== +b.getDirection(1)&&e.setAttribute("dir",f),e.remove(),c?e[d?"insertBefore":"insertAfter"](c):b.append(e,d)}function k(b){function c(d){var f=b[d?"getPrevious":"getNext"](a);f&&f.type==CKEDITOR.NODE_ELEMENT&&f.is(b.getName())&&(e(b,f,null,!d),b.remove(),b=f)}c();c(1)}function d(a){return a.type==CKEDITOR.NODE_ELEMENT&&(a.getName()in CKEDITOR.dtd.$block||a.getName()in CKEDITOR.dtd.$listItem)&&CKEDITOR.dtd[a.getName()]["#"]}function l(b,c,d){b.fire("saveSnapshot");d.enlarge(CKEDITOR.ENLARGE_LIST_ITEM_CONTENTS); +var f=d.extractContents();c.trim(!1,!0);var g=c.createBookmark(),h=new CKEDITOR.dom.elementPath(c.startContainer),l=h.block,h=h.lastElement.getAscendant("li",1)||l,u=new CKEDITOR.dom.elementPath(d.startContainer),y=u.contains(CKEDITOR.dtd.$listItem),u=u.contains(CKEDITOR.dtd.$list);l?(l=l.getBogus())&&l.remove():u&&(l=u.getPrevious(a))&&n(l)&&l.remove();(l=f.getLast())&&l.type==CKEDITOR.NODE_ELEMENT&&l.is("br")&&l.remove();(l=c.startContainer.getChild(c.startOffset))?f.insertBefore(l):c.startContainer.append(f); +y&&(f=m(y))&&(h.contains(y)?(e(f,y.getParent(),y),f.remove()):h.append(f));for(;d.checkStartOfBlock()&&d.checkEndOfBlock();){u=d.startPath();f=u.block;if(!f)break;f.is("li")&&(h=f.getParent(),f.equals(h.getLast(a))&&f.equals(h.getFirst(a))&&(f=h));d.moveToPosition(f,CKEDITOR.POSITION_BEFORE_START);f.remove()}d=d.clone();f=b.editable();d.setEndAt(f,CKEDITOR.POSITION_BEFORE_END);d=new CKEDITOR.dom.walker(d);d.evaluator=function(b){return a(b)&&!n(b)};(d=d.next())&&d.type==CKEDITOR.NODE_ELEMENT&&d.getName()in +CKEDITOR.dtd.$list&&k(d);c.moveToBookmark(g);c.select();b.fire("saveSnapshot")}function m(c){return(c=c.getLast(a))&&c.type==CKEDITOR.NODE_ELEMENT&&c.getName()in b?c:null}var b={ol:1,ul:1},g=CKEDITOR.dom.walker.whitespaces(),c=CKEDITOR.dom.walker.bookmark(),a=function(a){return!(g(a)||c(a))},n=CKEDITOR.dom.walker.bogus();CKEDITOR.plugins.list={listToArray:function(a,c,d,e,f){if(!b[a.getName()])return[];e||(e=0);d||(d=[]);for(var g=0,h=a.getChildCount();g<h;g++){var k=a.getChild(g);k.type==CKEDITOR.NODE_ELEMENT&& +k.getName()in CKEDITOR.dtd.$list&&CKEDITOR.plugins.list.listToArray(k,c,d,e+1);if("li"==k.$.nodeName.toLowerCase()){var l={parent:a,indent:e,element:k,contents:[]};f?l.grandparent=f:(l.grandparent=a.getParent(),l.grandparent&&"li"==l.grandparent.$.nodeName.toLowerCase()&&(l.grandparent=l.grandparent.getParent()));c&&CKEDITOR.dom.element.setMarker(c,k,"listarray_index",d.length);d.push(l);for(var m=0,n=k.getChildCount(),w;m<n;m++)w=k.getChild(m),w.type==CKEDITOR.NODE_ELEMENT&&b[w.getName()]?CKEDITOR.plugins.list.listToArray(w, +c,d,e+1,l.grandparent):l.contents.push(w)}}return d},arrayToList:function(d,e,f,g,h){f||(f=0);if(!d||d.length<f+1)return null;for(var k,l=d[f].parent.getDocument(),m=new CKEDITOR.dom.documentFragment(l),n=null,x=f,z=Math.max(d[f].indent,0),w=null,v,E,H=g==CKEDITOR.ENTER_P?"p":"div";;){var G=d[x];k=G.grandparent;v=G.element.getDirection(1);if(G.indent==z){n&&d[x].parent.getName()==n.getName()||(n=d[x].parent.clone(!1,1),h&&n.setAttribute("dir",h),m.append(n));w=n.append(G.element.clone(0,1));v!=n.getDirection(1)&& +w.setAttribute("dir",v);for(k=0;k<G.contents.length;k++)w.append(G.contents[k].clone(1,1));x++}else if(G.indent==Math.max(z,0)+1)G=d[x-1].element.getDirection(1),x=CKEDITOR.plugins.list.arrayToList(d,null,x,g,G!=v?v:null),!w.getChildCount()&&CKEDITOR.env.needsNbspFiller&&7>=l.$.documentMode&&w.append(l.createText(" ")),w.append(x.listNode),x=x.nextIndex;else if(-1==G.indent&&!f&&k){b[k.getName()]?(w=G.element.clone(!1,!0),v!=k.getDirection(1)&&w.setAttribute("dir",v)):w=new CKEDITOR.dom.documentFragment(l); +var n=k.getDirection(1)!=v,L=G.element,O=L.getAttribute("class"),D=L.getAttribute("style"),S=w.type==CKEDITOR.NODE_DOCUMENT_FRAGMENT&&(g!=CKEDITOR.ENTER_BR||n||D||O),J,R=G.contents.length,K;for(k=0;k<R;k++)if(J=G.contents[k],c(J)&&1<R)S?K=J.clone(1,1):w.append(J.clone(1,1));else if(J.type==CKEDITOR.NODE_ELEMENT&&J.isBlockBoundary()){n&&!J.getDirection()&&J.setAttribute("dir",v);E=J;var U=L.getAttribute("style");U&&E.setAttribute("style",U.replace(/([^;])$/,"$1;")+(E.getAttribute("style")||""));O&& +J.addClass(O);E=null;K&&(w.append(K),K=null);w.append(J.clone(1,1))}else S?(E||(E=l.createElement(H),w.append(E),n&&E.setAttribute("dir",v)),D&&E.setAttribute("style",D),O&&E.setAttribute("class",O),K&&(E.append(K),K=null),E.append(J.clone(1,1))):w.append(J.clone(1,1));K&&((E||w).append(K),K=null);w.type==CKEDITOR.NODE_DOCUMENT_FRAGMENT&&x!=d.length-1&&(CKEDITOR.env.needsBrFiller&&(v=w.getLast())&&v.type==CKEDITOR.NODE_ELEMENT&&v.is("br")&&v.remove(),(v=w.getLast(a))&&v.type==CKEDITOR.NODE_ELEMENT&& +v.is(CKEDITOR.dtd.$block)||w.append(l.createElement("br")));v=w.$.nodeName.toLowerCase();"div"!=v&&"p"!=v||w.appendBogus();m.append(w);n=null;x++}else return null;E=null;if(d.length<=x||Math.max(d[x].indent,0)<z)break}if(e)for(d=m.getFirst();d;){if(d.type==CKEDITOR.NODE_ELEMENT&&(CKEDITOR.dom.element.clearMarkers(e,d),d.getName()in CKEDITOR.dtd.$listItem&&(f=d,l=h=g=void 0,g=f.getDirection()))){for(h=f.getParent();h&&!(l=h.getDirection());)h=h.getParent();g==l&&f.removeAttribute("dir")}d=d.getNextSourceNode()}return{listNode:m, +nextIndex:x}}};var w=/^h[1-6]$/,v=CKEDITOR.dom.walker.nodeType(CKEDITOR.NODE_ELEMENT);h.prototype={exec:function(c){this.refresh(c,c.elementPath());var d=c.config,e=c.getSelection(),g=e&&e.getRanges();if(this.state==CKEDITOR.TRISTATE_OFF){var h=c.editable();if(h.getFirst(a)){var l=1==g.length&&g[0];(d=l&&l.getEnclosedNode())&&d.is&&this.type==d.getName()&&this.setState(CKEDITOR.TRISTATE_ON)}else d.enterMode==CKEDITOR.ENTER_BR?h.appendBogus():g[0].fixBlock(1,d.enterMode==CKEDITOR.ENTER_P?"p":"div"), +e.selectRanges(g)}for(var d=e.createBookmarks(!0),h=[],m={},g=g.createIterator(),n=0;(l=g.getNextRange())&&++n;){var y=l.getBoundaryNodes(),x=y.startNode,z=y.endNode;x.type==CKEDITOR.NODE_ELEMENT&&"td"==x.getName()&&l.setStartAt(y.startNode,CKEDITOR.POSITION_AFTER_START);z.type==CKEDITOR.NODE_ELEMENT&&"td"==z.getName()&&l.setEndAt(y.endNode,CKEDITOR.POSITION_BEFORE_END);l=l.createIterator();for(l.forceBrBreak=this.state==CKEDITOR.TRISTATE_OFF;y=l.getNextParagraph();)if(!y.getCustomData("list_block")){CKEDITOR.dom.element.setMarker(m, +y,"list_block",1);for(var v=c.elementPath(y),x=v.elements,z=0,v=v.blockLimit,F,E=x.length-1;0<=E&&(F=x[E]);E--)if(b[F.getName()]&&v.contains(F)){v.removeCustomData("list_group_object_"+n);(x=F.getCustomData("list_group_object"))?x.contents.push(y):(x={root:F,contents:[y]},h.push(x),CKEDITOR.dom.element.setMarker(m,F,"list_group_object",x));z=1;break}z||(z=v,z.getCustomData("list_group_object_"+n)?z.getCustomData("list_group_object_"+n).contents.push(y):(x={root:z,contents:[y]},CKEDITOR.dom.element.setMarker(m, +z,"list_group_object_"+n,x),h.push(x)))}}for(F=[];0<h.length;)if(x=h.shift(),this.state==CKEDITOR.TRISTATE_OFF)if(b[x.root.getName()]){g=c;n=x;x=m;l=F;z=CKEDITOR.plugins.list.listToArray(n.root,x);v=[];for(y=0;y<n.contents.length;y++)E=n.contents[y],(E=E.getAscendant("li",!0))&&!E.getCustomData("list_item_processed")&&(v.push(E),CKEDITOR.dom.element.setMarker(x,E,"list_item_processed",!0));for(var E=n.root.getDocument(),H=void 0,G=void 0,y=0;y<v.length;y++){var L=v[y].getCustomData("listarray_index"), +H=z[L].parent;H.is(this.type)||(G=E.createElement(this.type),H.copyAttributes(G,{start:1,type:1}),G.removeStyle("list-style-type"),z[L].parent=G)}x=CKEDITOR.plugins.list.arrayToList(z,x,null,g.config.enterMode);z=void 0;v=x.listNode.getChildCount();for(y=0;y<v&&(z=x.listNode.getChild(y));y++)z.getName()==this.type&&l.push(z);x.listNode.replace(n.root);g.fire("contentDomInvalidated")}else{z=c;l=x;y=F;v=l.contents;g=l.root.getDocument();n=[];1==v.length&&v[0].equals(l.root)&&(x=g.createElement("div"), +v[0].moveChildren&&v[0].moveChildren(x),v[0].append(x),v[0]=x);l=l.contents[0].getParent();for(E=0;E<v.length;E++)l=l.getCommonAncestor(v[E].getParent());H=z.config.useComputedState;z=x=void 0;H=void 0===H||H;for(E=0;E<v.length;E++)for(G=v[E];L=G.getParent();){if(L.equals(l)){n.push(G);!z&&G.getDirection()&&(z=1);G=G.getDirection(H);null!==x&&(x=x&&x!=G?null:G);break}G=L}if(!(1>n.length)){v=n[n.length-1].getNext();E=g.createElement(this.type);y.push(E);for(H=y=void 0;n.length;)y=n.shift(),H=g.createElement("li"), +G=y,G.is("pre")||w.test(G.getName())||"false"==G.getAttribute("contenteditable")?y.appendTo(H):(y.copyAttributes(H),x&&y.getDirection()&&(H.removeStyle("direction"),H.removeAttribute("dir")),y.moveChildren(H),y.remove()),H.appendTo(E);x&&z&&E.setAttribute("dir",x);v?E.insertBefore(v):E.appendTo(l)}}else this.state==CKEDITOR.TRISTATE_ON&&b[x.root.getName()]&&f.call(this,c,x,m);for(E=0;E<F.length;E++)k(F[E]);CKEDITOR.dom.element.clearAllMarkers(m);e.selectBookmarks(d);c.focus()},refresh:function(a, +c){var d=c.contains(b,1),e=c.blockLimit||c.root;d&&e.contains(d)?this.setState(d.is(this.type)?CKEDITOR.TRISTATE_ON:CKEDITOR.TRISTATE_OFF):this.setState(CKEDITOR.TRISTATE_OFF)}};CKEDITOR.plugins.add("list",{requires:"indentlist",init:function(c){c.blockless||(c.addCommand("numberedlist",new h("numberedlist","ol")),c.addCommand("bulletedlist",new h("bulletedlist","ul")),c.ui.addButton&&(c.ui.addButton("NumberedList",{label:c.lang.list.numberedlist,command:"numberedlist",directional:!0,toolbar:"list,10"}), +c.ui.addButton("BulletedList",{label:c.lang.list.bulletedlist,command:"bulletedlist",directional:!0,toolbar:"list,20"})),c.on("key",function(e){var f=e.data.domEvent.getKey(),g;if("wysiwyg"==c.mode&&f in{8:1,46:1}){var h=c.getSelection().getRanges()[0],k=h&&h.startPath();if(h&&h.collapsed){var w=8==f,u=c.editable(),y=new CKEDITOR.dom.walker(h.clone());y.evaluator=function(b){return a(b)&&!n(b)};y.guard=function(a,b){return!(b&&a.type==CKEDITOR.NODE_ELEMENT&&a.is("table"))};f=h.clone();if(w){var x; +(x=k.contains(b))&&h.checkBoundaryOfElement(x,CKEDITOR.START)&&(x=x.getParent())&&x.is("li")&&(x=m(x))?(g=x,x=x.getPrevious(a),f.moveToPosition(x&&n(x)?x:g,CKEDITOR.POSITION_BEFORE_START)):(y.range.setStartAt(u,CKEDITOR.POSITION_AFTER_START),y.range.setEnd(h.startContainer,h.startOffset),(x=y.previous())&&x.type==CKEDITOR.NODE_ELEMENT&&(x.getName()in b||x.is("li"))&&(x.is("li")||(y.range.selectNodeContents(x),y.reset(),y.evaluator=d,x=y.previous()),g=x,f.moveToElementEditEnd(g),f.moveToPosition(f.endPath().block, +CKEDITOR.POSITION_BEFORE_END)));if(g)l(c,f,h),e.cancel();else{var v=k.contains(b);v&&h.checkBoundaryOfElement(v,CKEDITOR.START)&&(g=v.getFirst(a),h.checkBoundaryOfElement(g,CKEDITOR.START)&&(x=v.getPrevious(a),m(g)?x&&(h.moveToElementEditEnd(x),h.select()):c.execCommand("outdent"),e.cancel()))}}else if(g=k.contains("li")){if(y.range.setEndAt(u,CKEDITOR.POSITION_BEFORE_END),w=(u=g.getLast(a))&&d(u)?u:g,k=0,(x=y.next())&&x.type==CKEDITOR.NODE_ELEMENT&&x.getName()in b&&x.equals(u)?(k=1,x=y.next()):h.checkBoundaryOfElement(w, +CKEDITOR.END)&&(k=2),k&&x){h=h.clone();h.moveToElementEditStart(x);if(1==k&&(f.optimize(),!f.startContainer.equals(g))){for(g=f.startContainer;g.is(CKEDITOR.dtd.$inline);)v=g,g=g.getParent();v&&f.moveToPosition(v,CKEDITOR.POSITION_AFTER_END)}2==k&&(f.moveToPosition(f.endPath().block,CKEDITOR.POSITION_BEFORE_END),h.endPath().block&&h.moveToPosition(h.endPath().block,CKEDITOR.POSITION_AFTER_START));l(c,f,h);e.cancel()}}else y.range.setEndAt(u,CKEDITOR.POSITION_BEFORE_END),(x=y.next())&&x.type==CKEDITOR.NODE_ELEMENT&& +x.is(b)&&(x=x.getFirst(a),k.block&&h.checkStartOfBlock()&&h.checkEndOfBlock()?(k.block.remove(),h.moveToElementEditStart(x),h.select()):m(x)?(h.moveToElementEditStart(x),h.select()):(h=h.clone(),h.moveToElementEditStart(x),l(c,f,h)),e.cancel());setTimeout(function(){c.selectionChange(1)})}}}))}})}(),"use strict",function(){function f(a,b,c){return n(b)&&n(c)&&c.equals(b.getNext(function(a){return!(ba(a)||ca(a)||w(a))}))}function h(a){this.upper=a[0];this.lower=a[1];this.set.apply(this,a.slice(2))} +function e(a){var b=a.element;if(b&&n(b)&&(b=b.getAscendant(a.triggers,!0))&&a.editable.contains(b)){var c=m(b);if("true"==c.getAttribute("contenteditable"))return b;if(c.is(a.triggers))return c}return null}function k(a,b,c){B(a,b);B(a,c);a=b.size.bottom;c=c.size.top;return a&&c?0|(a+c)/2:a||c}function d(b,c,d){return c=c[d?"getPrevious":"getNext"](function(c){return c&&c.type==CKEDITOR.NODE_TEXT&&!ba(c)||n(c)&&!w(c)&&!a(b,c)})}function l(a,b,c){return a>b&&a<c}function m(a,b){if(a.data("cke-editable"))return null; +for(b||(a=a.getParent());a&&!a.data("cke-editable");){if(a.hasAttribute("contenteditable"))return a;a=a.getParent()}return null}function b(a){var b=a.doc,c=F('\x3cspan contenteditable\x3d"false" data-cke-magic-line\x3d"1" style\x3d"'+V+"position:absolute;border-top:1px dashed "+a.boxColor+'"\x3e\x3c/span\x3e',b),d=CKEDITOR.getUrl(this.path+"images/"+(E.hidpi?"hidpi/":"")+"icon"+(a.rtl?"-rtl":"")+".png");z(c,{attach:function(){this.wrap.getParent()||this.wrap.appendTo(a.editable,!0);return this},lineChildren:[z(F('\x3cspan title\x3d"'+ +a.editor.lang.magicline.title+'" contenteditable\x3d"false"\x3e\x26#8629;\x3c/span\x3e',b),{base:V+"height:17px;width:17px;"+(a.rtl?"left":"right")+":17px;background:url("+d+") center no-repeat "+a.boxColor+";cursor:pointer;"+(E.hc?"font-size: 15px;line-height:14px;border:1px solid #fff;text-align:center;":"")+(E.hidpi?"background-size: 9px 10px;":""),looks:["top:-8px; border-radius: 2px;","top:-17px; border-radius: 2px 2px 0px 0px;","top:-1px; border-radius: 0px 0px 2px 2px;"]}),z(F(P,b),{base:T+ +"left:0px;border-left-color:"+a.boxColor+";",looks:["border-width:8px 0 8px 8px;top:-8px","border-width:8px 0 0 8px;top:-8px","border-width:0 0 8px 8px;top:0px"]}),z(F(P,b),{base:T+"right:0px;border-right-color:"+a.boxColor+";",looks:["border-width:8px 8px 8px 0;top:-8px","border-width:8px 8px 0 0;top:-8px","border-width:0 8px 8px 0;top:0px"]})],detach:function(){this.wrap.getParent()&&this.wrap.remove();return this},mouseNear:function(){B(a,this);var b=a.holdDistance,c=this.size;return c&&l(a.mouse.y, +c.top-b,c.bottom+b)&&l(a.mouse.x,c.left-b,c.right+b)?!0:!1},place:function(){var b=a.view,c=a.editable,d=a.trigger,e=d.upper,f=d.lower,g=e||f,h=g.getParent(),k={};this.trigger=d;e&&B(a,e,!0);f&&B(a,f,!0);B(a,h,!0);a.inInlineMode&&u(a,!0);h.equals(c)?(k.left=b.scroll.x,k.right=-b.scroll.x,k.width=""):(k.left=g.size.left-g.size.margin.left+b.scroll.x-(a.inInlineMode?b.editable.left+b.editable.border.left:0),k.width=g.size.outerWidth+g.size.margin.left+g.size.margin.right+b.scroll.x,k.right="");e&&f? +k.top=e.size.margin.bottom===f.size.margin.top?0|e.size.bottom+e.size.margin.bottom/2:e.size.margin.bottom<f.size.margin.top?e.size.bottom+e.size.margin.bottom:e.size.bottom+e.size.margin.bottom-f.size.margin.top:e?f||(k.top=e.size.bottom+e.size.margin.bottom):k.top=f.size.top-f.size.margin.top;d.is(R)||l(k.top,b.scroll.y-15,b.scroll.y+5)?(k.top=a.inInlineMode?0:b.scroll.y,this.look(R)):d.is(K)||l(k.top,b.pane.bottom-5,b.pane.bottom+15)?(k.top=a.inInlineMode?b.editable.height+b.editable.padding.top+ b.editable.padding.bottom:b.pane.bottom-1,this.look(K)):(a.inInlineMode&&(k.top-=b.editable.top+b.editable.border.top),this.look(U));a.inInlineMode&&(k.top--,k.top+=b.editable.scroll.top,k.left+=b.editable.scroll.left);for(var m in k)k[m]=CKEDITOR.tools.cssLength(k[m]);this.setStyles(k)},look:function(a){if(this.oldLook!=a){for(var b=this.lineChildren.length,c;b--;)(c=this.lineChildren[b]).setAttribute("style",c.base+c.looks[0|a/2]);this.oldLook=a}},wrap:new I("span",a.doc)});for(b=c.lineChildren.length;b--;)c.lineChildren[b].appendTo(c); -c.look(U);c.appendTo(c.wrap);c.unselectable();c.lineChildren[0].on("mouseup",function(b){c.detach();g(a,function(b){var c=a.line.trigger;b[c.is(O)?"insertBefore":"insertAfter"](c.is(O)?c.lower:c.upper)},!0);a.editor.focus();F.ie||a.enterMode==CKEDITOR.ENTER_BR||a.hotNode.scrollIntoView();b.data.preventDefault(!0)});c.on("mousedown",function(a){a.data.preventDefault(!0)});a.line=c}function g(a,b,c){var d=new CKEDITOR.dom.range(a.doc),g=a.editor,e;F.ie&&a.enterMode==CKEDITOR.ENTER_BR?e=a.doc.createText(Y): -(e=(e=m(a.element,!0))&&e.data("cke-enter-mode")||a.enterMode,e=new I(L[e],a.doc),e.is("br")||a.doc.createText(Y).appendTo(e));c&&g.fire("saveSnapshot");b(e);d.moveToPosition(e,CKEDITOR.POSITION_AFTER_START);g.getSelection().selectRanges([d]);a.hotNode=e;c&&g.fire("saveSnapshot")}function c(a,b){return{canUndo:!0,modes:{wysiwyg:1},exec:function(){function c(d){var e=F.ie&&9>F.version?" ":Y,f=a.hotNode&&a.hotNode.getText()==e&&a.element.equals(a.hotNode)&&a.lastCmdDirection===!!b;g(a,function(c){f&& -a.hotNode&&a.hotNode.remove();c[b?"insertAfter":"insertBefore"](d);c.setAttributes({"data-cke-magicline-hot":1,"data-cke-magicline-dir":!!b});a.lastCmdDirection=!!b});F.ie||a.enterMode==CKEDITOR.ENTER_BR||a.hotNode.scrollIntoView();a.line.detach()}return function(g){g=g.getSelection().getStartElement();var f;g=g.getAscendant(Q,1);if(!r(a,g)&&g&&!g.equals(a.editable)&&!g.contains(a.editable)){(f=m(g))&&"false"==f.getAttribute("contenteditable")&&(g=f);a.element=g;f=d(a,g,!b);var h;n(f)&&f.is(a.triggers)&& -f.is(M)&&(!d(a,f,!b)||(h=d(a,f,!b))&&n(h)&&h.is(a.triggers))?c(f):(h=e(a,g),n(h)&&(d(a,h,!b)?(g=d(a,h,!b))&&n(g)&&g.is(a.triggers)&&c(h):c(h)))}}}()}}function a(a,b){if(!b||b.type!=CKEDITOR.NODE_ELEMENT||!b.$)return!1;var c=a.line;return c.wrap.equals(b)||c.wrap.contains(b)}function n(a){return a&&a.type==CKEDITOR.NODE_ELEMENT&&a.$}function w(a){if(!n(a))return!1;var b;(b=v(a))||(n(a)?(b={left:1,right:1,center:1},b=!(!b[a.getComputedStyle("float")]&&!b[a.getAttribute("align")])):b=!1);return b}function v(a){return!!{absolute:1, -fixed:1}[a.getComputedStyle("position")]}function p(a,b){return n(b)?b.is(a.triggers):null}function r(a,b){if(!b)return!1;for(var c=b.getParents(1),d=c.length;d--;)for(var g=a.tabuList.length;g--;)if(c[d].hasAttribute(a.tabuList[g]))return!0;return!1}function q(a,b,c){b=b[c?"getLast":"getFirst"](function(b){return a.isRelevant(b)&&!b.is(aa)});if(!b)return!1;D(a,b);return c?b.size.top>a.mouse.y:b.size.bottom<a.mouse.y}function u(b){var c=b.editable,d=b.mouse,g=b.view,e=b.triggerOffset;t(b);var f=d.y> -(b.inInlineMode?g.editable.top+g.editable.height/2:Math.min(g.editable.height,g.pane.height)/2),c=c[f?"getLast":"getFirst"](function(a){return!(ca(a)||W(a))});if(!c)return null;a(b,c)&&(c=b.line.wrap[f?"getPrevious":"getNext"](function(a){return!(ca(a)||W(a))}));if(!n(c)||w(c)||!p(b,c))return null;D(b,c);return!f&&0<=c.size.top&&l(d.y,0,c.size.top+e)?(b=b.inInlineMode||0===g.scroll.y?R:U,new h([null,c,O,J,b])):f&&c.size.bottom<=g.pane.height&&l(d.y,c.size.bottom-e,g.pane.height)?(b=b.inInlineMode|| -l(c.size.bottom,g.pane.height-e,g.pane.height)?K:U,new h([c,null,C,J,b])):null}function x(a){var b=a.mouse,c=a.view,g=a.triggerOffset,f=e(a);if(!f)return null;D(a,f);var g=Math.min(g,0|f.size.outerHeight/2),k=[],m,u;if(l(b.y,f.size.top-1,f.size.top+g))u=!1;else if(l(b.y,f.size.bottom-g,f.size.bottom+1))u=!0;else return null;if(w(f)||q(a,f,u)||f.getParent().is(Z))return null;var x=d(a,f,!u);if(x){if(x&&x.type==CKEDITOR.NODE_TEXT)return null;if(n(x)){if(w(x)||!p(a,x)||x.getParent().is(Z))return null; -k=[x,f][u?"reverse":"concat"]().concat([S,J])}}else f.equals(a.editable[u?"getLast":"getFirst"](a.isRelevant))?(t(a),u&&l(b.y,f.size.bottom-g,c.pane.height)&&l(f.size.bottom,c.pane.height-g,c.pane.height)?m=K:l(b.y,0,f.size.top+g)&&(m=R)):m=U,k=[null,f][u?"reverse":"concat"]().concat([u?C:O,J,m,f.equals(a.editable[u?"getLast":"getFirst"](a.isRelevant))?u?K:R:U]);return 0 in k?new h(k):null}function A(a,b,c,d){for(var g=b.getDocumentPosition(),e={},f={},h={},k={},l=da.length;l--;)e[da[l]]=parseInt(b.getComputedStyle.call(b, -"border-"+da[l]+"-width"),10)||0,h[da[l]]=parseInt(b.getComputedStyle.call(b,"padding-"+da[l]),10)||0,f[da[l]]=parseInt(b.getComputedStyle.call(b,"margin-"+da[l]),10)||0;c&&!d||B(a,d);k.top=g.y-(c?0:a.view.scroll.y);k.left=g.x-(c?0:a.view.scroll.x);k.outerWidth=b.$.offsetWidth;k.outerHeight=b.$.offsetHeight;k.height=k.outerHeight-(h.top+h.bottom+e.top+e.bottom);k.width=k.outerWidth-(h.left+h.right+e.left+e.right);k.bottom=k.top+k.outerHeight;k.right=k.left+k.outerWidth;a.inInlineMode&&(k.scroll={top:b.$.scrollTop, -left:b.$.scrollLeft});return z({border:e,padding:h,margin:f,ignoreScroll:c},k,!0)}function D(a,b,c){if(!n(b))return b.size=null;if(!b.size)b.size={};else if(b.size.ignoreScroll==c&&b.size.date>new Date-N)return null;return z(b.size,A(a,b,c),{date:+new Date},!0)}function t(a,b){a.view.editable=A(a,a.editable,b,!0)}function B(a,b){a.view||(a.view={});var c=a.view;if(!(!b&&c&&c.date>new Date-N)){var d=a.win,c=d.getScrollPosition(),d=d.getViewPaneSize();z(a.view,{scroll:{x:c.x,y:c.y,width:a.doc.$.documentElement.scrollWidth- -d.width,height:a.doc.$.documentElement.scrollHeight-d.height},pane:{width:d.width,height:d.height,bottom:d.height+c.y},date:+new Date},!0)}}function y(a,b,c,d){for(var g=d,e=d,f=0,k=!1,l=!1,m=a.view.pane.height,n=a.mouse;n.y+f<m&&0<n.y-f;){k||(k=b(g,d));l||(l=b(e,d));!k&&0<n.y-f&&(g=c(a,{x:n.x,y:n.y-f}));!l&&n.y+f<m&&(e=c(a,{x:n.x,y:n.y+f}));if(k&&l)break;f+=2}return new h([g,e,null,null])}CKEDITOR.plugins.add("magicline",{init:function(f){var k=f.config,l=k.magicline_triggerOffset||30,m={editor:f, -enterMode:k.enterMode,triggerOffset:l,holdDistance:0|l*(k.magicline_holdDistance||.5),boxColor:k.magicline_color||"#ff0000",rtl:"rtl"==k.contentsLangDirection,tabuList:["data-cke-hidden-sel"].concat(k.magicline_tabuList||[]),triggers:k.magicline_everywhere?Q:{table:1,hr:1,div:1,ul:1,ol:1,dl:1,form:1,blockquote:1}},q,p,y;m.isRelevant=function(b){return n(b)&&!a(m,b)&&!w(b)};f.on("contentDom",function(){var l=f.editable(),n=f.document,w=f.window;z(m,{editable:l,inInlineMode:l.isInline(),doc:n,win:w, -hotNode:null},!0);m.boundary=m.inInlineMode?m.editable:m.doc.getDocumentElement();l.is(G.$inline)||(m.inInlineMode&&!v(l)&&l.setStyles({position:"relative",top:null,left:null}),b.call(this,m),B(m),l.attachListener(f,"beforeUndoImage",function(){m.line.detach()}),l.attachListener(f,"beforeGetData",function(){m.line.wrap.getParent()&&(m.line.detach(),f.once("getData",function(){m.line.attach()},null,null,1E3))},null,null,0),l.attachListener(m.inInlineMode?n:n.getWindow().getFrame(),"mouseout",function(a){if("wysiwyg"== -f.mode)if(m.inInlineMode){var b=a.data.$.clientX;a=a.data.$.clientY;B(m);t(m,!0);var c=m.view.editable,d=m.view.scroll;b>c.left-d.x&&b<c.right-d.x&&a>c.top-d.y&&a<c.bottom-d.y||(clearTimeout(y),y=null,m.line.detach())}else clearTimeout(y),y=null,m.line.detach()}),l.attachListener(l,"keyup",function(){m.hiddenMode=0}),l.attachListener(l,"keydown",function(a){if("wysiwyg"==f.mode)switch(a.data.getKeystroke()){case 2228240:case 16:m.hiddenMode=1,m.line.detach()}}),l.attachListener(m.inInlineMode?l:n, -"mousemove",function(a){p=!0;if("wysiwyg"==f.mode&&!f.readOnly&&!y){var b={x:a.data.$.clientX,y:a.data.$.clientY};y=setTimeout(function(){m.mouse=b;y=m.trigger=null;B(m);p&&!m.hiddenMode&&f.focusManager.hasFocus&&!m.line.mouseNear()&&(m.element=X(m,!0))&&((m.trigger=u(m)||x(m)||ba(m))&&!r(m,m.trigger.upper||m.trigger.lower)?m.line.attach().place():(m.trigger=null,m.line.detach()),p=!1)},30)}}),l.attachListener(w,"scroll",function(){"wysiwyg"==f.mode&&(m.line.detach(),F.webkit&&(m.hiddenMode=1,clearTimeout(q), +c.look(U);c.appendTo(c.wrap);c.unselectable();c.lineChildren[0].on("mouseup",function(b){c.detach();g(a,function(b){var c=a.line.trigger;b[c.is(O)?"insertBefore":"insertAfter"](c.is(O)?c.lower:c.upper)},!0);a.editor.focus();E.ie||a.enterMode==CKEDITOR.ENTER_BR||a.hotNode.scrollIntoView();b.data.preventDefault(!0)});c.on("mousedown",function(a){a.data.preventDefault(!0)});a.line=c}function g(a,b,c){var d=new CKEDITOR.dom.range(a.doc),e=a.editor,f;E.ie&&a.enterMode==CKEDITOR.ENTER_BR?f=a.doc.createText(X): +(f=(f=m(a.element,!0))&&f.data("cke-enter-mode")||a.enterMode,f=new I(L[f],a.doc),f.is("br")||a.doc.createText(X).appendTo(f));c&&e.fire("saveSnapshot");b(f);d.moveToPosition(f,CKEDITOR.POSITION_AFTER_START);e.getSelection().selectRanges([d]);a.hotNode=f;c&&e.fire("saveSnapshot")}function c(a,b){return{canUndo:!0,modes:{wysiwyg:1},exec:function(){function c(d){var e=E.ie&&9>E.version?" ":X,f=a.hotNode&&a.hotNode.getText()==e&&a.element.equals(a.hotNode)&&a.lastCmdDirection===!!b;g(a,function(c){f&& +a.hotNode&&a.hotNode.remove();c[b?"insertAfter":"insertBefore"](d);c.setAttributes({"data-cke-magicline-hot":1,"data-cke-magicline-dir":!!b});a.lastCmdDirection=!!b});E.ie||a.enterMode==CKEDITOR.ENTER_BR||a.hotNode.scrollIntoView();a.line.detach()}return function(f){f=f.getSelection().getStartElement();var g;f=f.getAscendant(Q,1);if(!p(a,f)&&f&&!f.equals(a.editable)&&!f.contains(a.editable)){(g=m(f))&&"false"==g.getAttribute("contenteditable")&&(f=g);a.element=f;g=d(a,f,!b);var h;n(g)&&g.is(a.triggers)&& +g.is(M)&&(!d(a,g,!b)||(h=d(a,g,!b))&&n(h)&&h.is(a.triggers))?c(g):(h=e(a,f),n(h)&&(d(a,h,!b)?(f=d(a,h,!b))&&n(f)&&f.is(a.triggers)&&c(h):c(h)))}}}()}}function a(a,b){if(!b||b.type!=CKEDITOR.NODE_ELEMENT||!b.$)return!1;var c=a.line;return c.wrap.equals(b)||c.wrap.contains(b)}function n(a){return a&&a.type==CKEDITOR.NODE_ELEMENT&&a.$}function w(a){if(!n(a))return!1;var b;(b=v(a))||(n(a)?(b={left:1,right:1,center:1},b=!(!b[a.getComputedStyle("float")]&&!b[a.getAttribute("align")])):b=!1);return b}function v(a){return!!{absolute:1, +fixed:1}[a.getComputedStyle("position")]}function t(a,b){return n(b)?b.is(a.triggers):null}function p(a,b){if(!b)return!1;for(var c=b.getParents(1),d=c.length;d--;)for(var e=a.tabuList.length;e--;)if(c[d].hasAttribute(a.tabuList[e]))return!0;return!1}function q(a,b,c){b=b[c?"getLast":"getFirst"](function(b){return a.isRelevant(b)&&!b.is(Z)});if(!b)return!1;B(a,b);return c?b.size.top>a.mouse.y:b.size.bottom<a.mouse.y}function A(b){var c=b.editable,d=b.mouse,e=b.view,f=b.triggerOffset;u(b);var g=d.y> +(b.inInlineMode?e.editable.top+e.editable.height/2:Math.min(e.editable.height,e.pane.height)/2),c=c[g?"getLast":"getFirst"](function(a){return!(ba(a)||ca(a))});if(!c)return null;a(b,c)&&(c=b.line.wrap[g?"getPrevious":"getNext"](function(a){return!(ba(a)||ca(a))}));if(!n(c)||w(c)||!t(b,c))return null;B(b,c);return!g&&0<=c.size.top&&l(d.y,0,c.size.top+f)?(b=b.inInlineMode||0===e.scroll.y?R:U,new h([null,c,O,J,b])):g&&c.size.bottom<=e.pane.height&&l(d.y,c.size.bottom-f,e.pane.height)?(b=b.inInlineMode|| +l(c.size.bottom,e.pane.height-f,e.pane.height)?K:U,new h([c,null,D,J,b])):null}function r(a){var b=a.mouse,c=a.view,f=a.triggerOffset,g=e(a);if(!g)return null;B(a,g);var f=Math.min(f,0|g.size.outerHeight/2),k=[],m,r;if(l(b.y,g.size.top-1,g.size.top+f))r=!1;else if(l(b.y,g.size.bottom-f,g.size.bottom+1))r=!0;else return null;if(w(g)||q(a,g,r)||g.getParent().is(Y))return null;var p=d(a,g,!r);if(p){if(p&&p.type==CKEDITOR.NODE_TEXT)return null;if(n(p)){if(w(p)||!t(a,p)||p.getParent().is(Y))return null; +k=[p,g][r?"reverse":"concat"]().concat([S,J])}}else g.equals(a.editable[r?"getLast":"getFirst"](a.isRelevant))?(u(a),r&&l(b.y,g.size.bottom-f,c.pane.height)&&l(g.size.bottom,c.pane.height-f,c.pane.height)?m=K:l(b.y,0,g.size.top+f)&&(m=R)):m=U,k=[null,g][r?"reverse":"concat"]().concat([r?D:O,J,m,g.equals(a.editable[r?"getLast":"getFirst"](a.isRelevant))?r?K:R:U]);return 0 in k?new h(k):null}function C(a,b,c,d){for(var e=b.getDocumentPosition(),f={},g={},h={},k={},l=da.length;l--;)f[da[l]]=parseInt(b.getComputedStyle.call(b, +"border-"+da[l]+"-width"),10)||0,h[da[l]]=parseInt(b.getComputedStyle.call(b,"padding-"+da[l]),10)||0,g[da[l]]=parseInt(b.getComputedStyle.call(b,"margin-"+da[l]),10)||0;c&&!d||y(a,d);k.top=e.y-(c?0:a.view.scroll.y);k.left=e.x-(c?0:a.view.scroll.x);k.outerWidth=b.$.offsetWidth;k.outerHeight=b.$.offsetHeight;k.height=k.outerHeight-(h.top+h.bottom+f.top+f.bottom);k.width=k.outerWidth-(h.left+h.right+f.left+f.right);k.bottom=k.top+k.outerHeight;k.right=k.left+k.outerWidth;a.inInlineMode&&(k.scroll={top:b.$.scrollTop, +left:b.$.scrollLeft});return z({border:f,padding:h,margin:g,ignoreScroll:c},k,!0)}function B(a,b,c){if(!n(b))return b.size=null;if(!b.size)b.size={};else if(b.size.ignoreScroll==c&&b.size.date>new Date-N)return null;return z(b.size,C(a,b,c),{date:+new Date},!0)}function u(a,b){a.view.editable=C(a,a.editable,b,!0)}function y(a,b){a.view||(a.view={});var c=a.view;if(!(!b&&c&&c.date>new Date-N)){var d=a.win,c=d.getScrollPosition(),d=d.getViewPaneSize();z(a.view,{scroll:{x:c.x,y:c.y,width:a.doc.$.documentElement.scrollWidth- +d.width,height:a.doc.$.documentElement.scrollHeight-d.height},pane:{width:d.width,height:d.height,bottom:d.height+c.y},date:+new Date},!0)}}function x(a,b,c,d){for(var e=d,f=d,g=0,k=!1,l=!1,m=a.view.pane.height,n=a.mouse;n.y+g<m&&0<n.y-g;){k||(k=b(e,d));l||(l=b(f,d));!k&&0<n.y-g&&(e=c(a,{x:n.x,y:n.y-g}));!l&&n.y+g<m&&(f=c(a,{x:n.x,y:n.y+g}));if(k&&l)break;g+=2}return new h([e,f,null,null])}CKEDITOR.plugins.add("magicline",{init:function(f){var k=f.config,l=k.magicline_triggerOffset||30,m={editor:f, +enterMode:k.enterMode,triggerOffset:l,holdDistance:0|l*(k.magicline_holdDistance||.5),boxColor:k.magicline_color||"#ff0000",rtl:"rtl"==k.contentsLangDirection,tabuList:["data-cke-hidden-sel"].concat(k.magicline_tabuList||[]),triggers:k.magicline_everywhere?Q:{table:1,hr:1,div:1,ul:1,ol:1,dl:1,form:1,blockquote:1}},q,t,x;m.isRelevant=function(b){return n(b)&&!a(m,b)&&!w(b)};f.on("contentDom",function(){var l=f.editable(),n=f.document,w=f.window;z(m,{editable:l,inInlineMode:l.isInline(),doc:n,win:w, +hotNode:null},!0);m.boundary=m.inInlineMode?m.editable:m.doc.getDocumentElement();l.is(G.$inline)||(m.inInlineMode&&!v(l)&&l.setStyles({position:"relative",top:null,left:null}),b.call(this,m),y(m),l.attachListener(f,"beforeUndoImage",function(){m.line.detach()}),l.attachListener(f,"beforeGetData",function(){m.line.wrap.getParent()&&(m.line.detach(),f.once("getData",function(){m.line.attach()},null,null,1E3))},null,null,0),l.attachListener(m.inInlineMode?n:n.getWindow().getFrame(),"mouseout",function(a){if("wysiwyg"== +f.mode)if(m.inInlineMode){var b=a.data.$.clientX;a=a.data.$.clientY;y(m);u(m,!0);var c=m.view.editable,d=m.view.scroll;b>c.left-d.x&&b<c.right-d.x&&a>c.top-d.y&&a<c.bottom-d.y||(clearTimeout(x),x=null,m.line.detach())}else clearTimeout(x),x=null,m.line.detach()}),l.attachListener(l,"keyup",function(){m.hiddenMode=0}),l.attachListener(l,"keydown",function(a){if("wysiwyg"==f.mode)switch(a.data.getKeystroke()){case 2228240:case 16:m.hiddenMode=1,m.line.detach()}}),l.attachListener(m.inInlineMode?l:n, +"mousemove",function(a){t=!0;if("wysiwyg"==f.mode&&!f.readOnly&&!x){var b={x:a.data.$.clientX,y:a.data.$.clientY};x=setTimeout(function(){m.mouse=b;x=m.trigger=null;y(m);t&&!m.hiddenMode&&f.focusManager.hasFocus&&!m.line.mouseNear()&&(m.element=W(m,!0))&&((m.trigger=A(m)||r(m)||aa(m))&&!p(m,m.trigger.upper||m.trigger.lower)?m.line.attach().place():(m.trigger=null,m.line.detach()),t=!1)},30)}}),l.attachListener(w,"scroll",function(){"wysiwyg"==f.mode&&(m.line.detach(),E.webkit&&(m.hiddenMode=1,clearTimeout(q), q=setTimeout(function(){m.mouseDown||(m.hiddenMode=0)},50)))}),l.attachListener(H?n:w,"mousedown",function(){"wysiwyg"==f.mode&&(m.line.detach(),m.hiddenMode=1,m.mouseDown=1)}),l.attachListener(H?n:w,"mouseup",function(){m.hiddenMode=0;m.mouseDown=0}),f.addCommand("accessPreviousSpace",c(m)),f.addCommand("accessNextSpace",c(m,!0)),f.setKeystroke([[k.magicline_keystrokePrevious,"accessPreviousSpace"],[k.magicline_keystrokeNext,"accessNextSpace"]]),f.on("loadSnapshot",function(){var a,b,c,d;for(d in{p:1, -br:1,div:1})for(a=f.document.getElementsByTag(d),c=a.count();c--;)if((b=a.getItem(c)).data("cke-magicline-hot")){m.hotNode=b;m.lastCmdDirection="true"===b.data("cke-magicline-dir")?!0:!1;return}}),this.backdoor={accessFocusSpace:g,boxTrigger:h,isLine:a,getAscendantTrigger:e,getNonEmptyNeighbour:d,getSize:A,that:m,triggerEdge:x,triggerEditable:u,triggerExpand:ba})},this)}});var z=CKEDITOR.tools.extend,I=CKEDITOR.dom.element,E=I.createFromHtml,F=CKEDITOR.env,H=CKEDITOR.env.ie&&9>CKEDITOR.env.version, -G=CKEDITOR.dtd,L={},O=128,C=64,S=32,J=16,R=4,K=2,U=1,Y=" ",Z=G.$listItem,aa=G.$tableContent,M=z({},G.$nonEditable,G.$empty),Q=G.$block,N=100,V="width:0px;height:0px;padding:0px;margin:0px;display:block;z-index:9999;color:#fff;position:absolute;font-size: 0px;line-height:0px;",T=V+"border-color:transparent;display:block;border-style:solid;",P="\x3cspan\x3e"+Y+"\x3c/span\x3e";L[CKEDITOR.ENTER_BR]="br";L[CKEDITOR.ENTER_P]="p";L[CKEDITOR.ENTER_DIV]="div";h.prototype={set:function(a,b,c){this.properties= -a+b+(c||U);return this},is:function(a){return(this.properties&a)==a}};var X=function(){function b(a,c){var d=a.$.elementFromPoint(c.x,c.y);return d&&d.nodeType?new CKEDITOR.dom.element(d):null}return function(c,d,g){if(!c.mouse)return null;var e=c.doc,f=c.line.wrap;g=g||c.mouse;var h=b(e,g);d&&a(c,h)&&(f.hide(),h=b(e,g),f.show());return!h||h.type!=CKEDITOR.NODE_ELEMENT||!h.$||F.ie&&9>F.version&&!c.boundary.equals(h)&&!c.boundary.contains(h)?null:h}}(),ca=CKEDITOR.dom.walker.whitespaces(),W=CKEDITOR.dom.walker.nodeType(CKEDITOR.NODE_COMMENT), -ba=function(){function b(a){var d=a.element,g,e,h;if(!n(d)||d.contains(a.editable)||d.isReadOnly())return null;h=y(a,function(a,b){return!b.equals(a)},function(a,b){return X(a,!0,b)},d);g=h.upper;e=h.lower;if(f(a,g,e))return h.set(S,8);if(g&&d.contains(g))for(;!g.getParent().equals(d);)g=g.getParent();else g=d.getFirst(function(b){return c(a,b)});if(e&&d.contains(e))for(;!e.getParent().equals(d);)e=e.getParent();else e=d.getLast(function(b){return c(a,b)});if(!g||!e)return null;D(a,g);D(a,e);if(!l(a.mouse.y, -g.size.top,e.size.bottom))return null;for(var d=Number.MAX_VALUE,m,t,q,u;e&&!e.equals(g)&&(t=g.getNext(a.isRelevant));)m=Math.abs(k(a,g,t)-a.mouse.y),m<d&&(d=m,q=g,u=t),g=t,D(a,g);if(!q||!u||!l(a.mouse.y,q.size.top,u.size.bottom))return null;h.upper=q;h.lower=u;return h.set(S,8)}function c(b,d){return!(d&&d.type==CKEDITOR.NODE_TEXT||W(d)||w(d)||a(b,d)||d.type==CKEDITOR.NODE_ELEMENT&&d.$&&d.is("br"))}return function(a){var c=b(a),d;if(d=c){d=c.upper;var g=c.lower;d=!d||!g||w(g)||w(d)||g.equals(d)|| -d.equals(g)||g.contains(d)||d.contains(g)?!1:p(a,d)&&p(a,g)&&f(a,d,g)?!0:!1}return d?c:null}}(),da=["top","left","right","bottom"]}(),CKEDITOR.config.magicline_keystrokePrevious=CKEDITOR.CTRL+CKEDITOR.SHIFT+51,CKEDITOR.config.magicline_keystrokeNext=CKEDITOR.CTRL+CKEDITOR.SHIFT+52,function(){function f(d){if(!d||d.type!=CKEDITOR.NODE_ELEMENT||"form"!=d.getName())return[];for(var e=[],b=["style","className"],g=0;g<b.length;g++){var c=d.$.elements.namedItem(b[g]);c&&(c=new CKEDITOR.dom.element(c),e.push([c, -c.nextSibling]),c.remove())}return e}function h(d,e){if(d&&d.type==CKEDITOR.NODE_ELEMENT&&"form"==d.getName()&&0<e.length)for(var b=e.length-1;0<=b;b--){var g=e[b][0],c=e[b][1];c?g.insertBefore(c):g.appendTo(d)}}function e(d,e){var b=f(d),g={},c=d.$;e||(g["class"]=c.className||"",c.className="");g.inline=c.style.cssText||"";e||(c.style.cssText="position: static; overflow: visible");h(b);return g}function k(d,e){var b=f(d),g=d.$;"class"in e&&(g.className=e["class"]);"inline"in e&&(g.style.cssText= -e.inline);h(b)}function d(d){if(!d.editable().isInline()){var e=CKEDITOR.instances,b;for(b in e){var g=e[b];"wysiwyg"!=g.mode||g.readOnly||(g=g.document.getBody(),g.setAttribute("contentEditable",!1),g.setAttribute("contentEditable",!0))}d.editable().hasFocus&&(d.toolbox.focus(),d.focus())}}CKEDITOR.plugins.add("maximize",{init:function(f){function h(){var a=c.getViewPaneSize();f.resize(a.width,a.height,null,!0)}if(f.elementMode!=CKEDITOR.ELEMENT_MODE_INLINE){var b=f.lang,g=CKEDITOR.document,c=g.getWindow(), -a,n,w,v=CKEDITOR.TRISTATE_OFF;f.addCommand("maximize",{modes:{wysiwyg:!CKEDITOR.env.iOS,source:!CKEDITOR.env.iOS},readOnly:1,editorFocus:!1,exec:function(){var p=f.container.getFirst(function(a){return a.type==CKEDITOR.NODE_ELEMENT&&a.hasClass("cke_inner")}),r=f.ui.space("contents");if("wysiwyg"==f.mode){var q=f.getSelection();a=q&&q.getRanges();n=c.getScrollPosition()}else{var u=f.editable().$;a=!CKEDITOR.env.ie&&[u.selectionStart,u.selectionEnd];n=[u.scrollLeft,u.scrollTop]}if(this.state==CKEDITOR.TRISTATE_OFF){c.on("resize", -h);w=c.getScrollPosition();for(q=f.container;q=q.getParent();)q.setCustomData("maximize_saved_styles",e(q)),q.setStyle("z-index",f.config.baseFloatZIndex-5);r.setCustomData("maximize_saved_styles",e(r,!0));p.setCustomData("maximize_saved_styles",e(p,!0));r={overflow:CKEDITOR.env.webkit?"":"hidden",width:0,height:0};g.getDocumentElement().setStyles(r);!CKEDITOR.env.gecko&&g.getDocumentElement().setStyle("position","fixed");CKEDITOR.env.gecko&&CKEDITOR.env.quirks||g.getBody().setStyles(r);CKEDITOR.env.ie? -setTimeout(function(){c.$.scrollTo(0,0)},0):c.$.scrollTo(0,0);p.setStyle("position",CKEDITOR.env.gecko&&CKEDITOR.env.quirks?"fixed":"absolute");p.$.offsetLeft;p.setStyles({"z-index":f.config.baseFloatZIndex-5,left:"0px",top:"0px"});p.addClass("cke_maximized");h();r=p.getDocumentPosition();p.setStyles({left:-1*r.x+"px",top:-1*r.y+"px"});CKEDITOR.env.gecko&&d(f)}else if(this.state==CKEDITOR.TRISTATE_ON){c.removeListener("resize",h);for(var q=[r,p],x=0;x<q.length;x++)k(q[x],q[x].getCustomData("maximize_saved_styles")), -q[x].removeCustomData("maximize_saved_styles");for(q=f.container;q=q.getParent();)k(q,q.getCustomData("maximize_saved_styles")),q.removeCustomData("maximize_saved_styles");CKEDITOR.env.ie?setTimeout(function(){c.$.scrollTo(w.x,w.y)},0):c.$.scrollTo(w.x,w.y);p.removeClass("cke_maximized");CKEDITOR.env.webkit&&(p.setStyle("display","inline"),setTimeout(function(){p.setStyle("display","block")},0));f.fire("resize",{outerHeight:f.container.$.offsetHeight,contentsHeight:r.$.offsetHeight,outerWidth:f.container.$.offsetWidth})}this.toggleState(); -if(q=this.uiItems[0])r=this.state==CKEDITOR.TRISTATE_OFF?b.maximize.maximize:b.maximize.minimize,q=CKEDITOR.document.getById(q._.id),q.getChild(1).setHtml(r),q.setAttribute("title",r),q.setAttribute("href",'javascript:void("'+r+'");');"wysiwyg"==f.mode?a?(CKEDITOR.env.gecko&&d(f),f.getSelection().selectRanges(a),(u=f.getSelection().getStartElement())&&u.scrollIntoView(!0)):c.$.scrollTo(n.x,n.y):(a&&(u.selectionStart=a[0],u.selectionEnd=a[1]),u.scrollLeft=n[0],u.scrollTop=n[1]);a=n=null;v=this.state; +br:1,div:1})for(a=f.document.getElementsByTag(d),c=a.count();c--;)if((b=a.getItem(c)).data("cke-magicline-hot")){m.hotNode=b;m.lastCmdDirection="true"===b.data("cke-magicline-dir")?!0:!1;return}}),this.backdoor={accessFocusSpace:g,boxTrigger:h,isLine:a,getAscendantTrigger:e,getNonEmptyNeighbour:d,getSize:C,that:m,triggerEdge:r,triggerEditable:A,triggerExpand:aa})},this)}});var z=CKEDITOR.tools.extend,I=CKEDITOR.dom.element,F=I.createFromHtml,E=CKEDITOR.env,H=CKEDITOR.env.ie&&9>CKEDITOR.env.version, +G=CKEDITOR.dtd,L={},O=128,D=64,S=32,J=16,R=4,K=2,U=1,X=" ",Y=G.$listItem,Z=G.$tableContent,M=z({},G.$nonEditable,G.$empty),Q=G.$block,N=100,V="width:0px;height:0px;padding:0px;margin:0px;display:block;z-index:9999;color:#fff;position:absolute;font-size: 0px;line-height:0px;",T=V+"border-color:transparent;display:block;border-style:solid;",P="\x3cspan\x3e"+X+"\x3c/span\x3e";L[CKEDITOR.ENTER_BR]="br";L[CKEDITOR.ENTER_P]="p";L[CKEDITOR.ENTER_DIV]="div";h.prototype={set:function(a,b,c){this.properties= +a+b+(c||U);return this},is:function(a){return(this.properties&a)==a}};var W=function(){function b(a,c){var d=a.$.elementFromPoint(c.x,c.y);return d&&d.nodeType?new CKEDITOR.dom.element(d):null}return function(c,d,e){if(!c.mouse)return null;var f=c.doc,g=c.line.wrap;e=e||c.mouse;var h=b(f,e);d&&a(c,h)&&(g.hide(),h=b(f,e),g.show());return!h||h.type!=CKEDITOR.NODE_ELEMENT||!h.$||E.ie&&9>E.version&&!c.boundary.equals(h)&&!c.boundary.contains(h)?null:h}}(),ba=CKEDITOR.dom.walker.whitespaces(),ca=CKEDITOR.dom.walker.nodeType(CKEDITOR.NODE_COMMENT), +aa=function(){function b(a){var d=a.element,e,g,h;if(!n(d)||d.contains(a.editable)||d.isReadOnly())return null;h=x(a,function(a,b){return!b.equals(a)},function(a,b){return W(a,!0,b)},d);e=h.upper;g=h.lower;if(f(a,e,g))return h.set(S,8);if(e&&d.contains(e))for(;!e.getParent().equals(d);)e=e.getParent();else e=d.getFirst(function(b){return c(a,b)});if(g&&d.contains(g))for(;!g.getParent().equals(d);)g=g.getParent();else g=d.getLast(function(b){return c(a,b)});if(!e||!g)return null;B(a,e);B(a,g);if(!l(a.mouse.y, +e.size.top,g.size.bottom))return null;for(var d=Number.MAX_VALUE,m,q,u,r;g&&!g.equals(e)&&(q=e.getNext(a.isRelevant));)m=Math.abs(k(a,e,q)-a.mouse.y),m<d&&(d=m,u=e,r=q),e=q,B(a,e);if(!u||!r||!l(a.mouse.y,u.size.top,r.size.bottom))return null;h.upper=u;h.lower=r;return h.set(S,8)}function c(b,d){return!(d&&d.type==CKEDITOR.NODE_TEXT||ca(d)||w(d)||a(b,d)||d.type==CKEDITOR.NODE_ELEMENT&&d.$&&d.is("br"))}return function(a){var c=b(a),d;if(d=c){d=c.upper;var e=c.lower;d=!d||!e||w(e)||w(d)||e.equals(d)|| +d.equals(e)||e.contains(d)||d.contains(e)?!1:t(a,d)&&t(a,e)&&f(a,d,e)?!0:!1}return d?c:null}}(),da=["top","left","right","bottom"]}(),CKEDITOR.config.magicline_keystrokePrevious=CKEDITOR.CTRL+CKEDITOR.SHIFT+51,CKEDITOR.config.magicline_keystrokeNext=CKEDITOR.CTRL+CKEDITOR.SHIFT+52,function(){function f(d){if(!d||d.type!=CKEDITOR.NODE_ELEMENT||"form"!=d.getName())return[];for(var e=[],b=["style","className"],f=0;f<b.length;f++){var c=d.$.elements.namedItem(b[f]);c&&(c=new CKEDITOR.dom.element(c),e.push([c, +c.nextSibling]),c.remove())}return e}function h(d,e){if(d&&d.type==CKEDITOR.NODE_ELEMENT&&"form"==d.getName()&&0<e.length)for(var b=e.length-1;0<=b;b--){var f=e[b][0],c=e[b][1];c?f.insertBefore(c):f.appendTo(d)}}function e(d,e){var b=f(d),g={},c=d.$;e||(g["class"]=c.className||"",c.className="");g.inline=c.style.cssText||"";e||(c.style.cssText="position: static; overflow: visible");h(b);return g}function k(d,e){var b=f(d),g=d.$;"class"in e&&(g.className=e["class"]);"inline"in e&&(g.style.cssText= +e.inline);h(b)}function d(d){if(!d.editable().isInline()){var e=CKEDITOR.instances,b;for(b in e){var f=e[b];"wysiwyg"!=f.mode||f.readOnly||(f=f.document.getBody(),f.setAttribute("contentEditable",!1),f.setAttribute("contentEditable",!0))}d.editable().hasFocus&&(d.toolbox.focus(),d.focus())}}CKEDITOR.plugins.add("maximize",{init:function(f){function h(){var a=c.getViewPaneSize();f.resize(a.width,a.height,null,!0)}if(f.elementMode!=CKEDITOR.ELEMENT_MODE_INLINE){var b=f.lang,g=CKEDITOR.document,c=g.getWindow(), +a,n,w,v=CKEDITOR.TRISTATE_OFF;f.addCommand("maximize",{modes:{wysiwyg:!CKEDITOR.env.iOS,source:!CKEDITOR.env.iOS},readOnly:1,editorFocus:!1,exec:function(){var t=f.container.getFirst(function(a){return a.type==CKEDITOR.NODE_ELEMENT&&a.hasClass("cke_inner")}),p=f.ui.space("contents");if("wysiwyg"==f.mode){var q=f.getSelection();a=q&&q.getRanges();n=c.getScrollPosition()}else{var A=f.editable().$;a=!CKEDITOR.env.ie&&[A.selectionStart,A.selectionEnd];n=[A.scrollLeft,A.scrollTop]}if(this.state==CKEDITOR.TRISTATE_OFF){c.on("resize", +h);w=c.getScrollPosition();for(q=f.container;q=q.getParent();)q.setCustomData("maximize_saved_styles",e(q)),q.setStyle("z-index",f.config.baseFloatZIndex-5);p.setCustomData("maximize_saved_styles",e(p,!0));t.setCustomData("maximize_saved_styles",e(t,!0));p={overflow:CKEDITOR.env.webkit?"":"hidden",width:0,height:0};g.getDocumentElement().setStyles(p);!CKEDITOR.env.gecko&&g.getDocumentElement().setStyle("position","fixed");CKEDITOR.env.gecko&&CKEDITOR.env.quirks||g.getBody().setStyles(p);CKEDITOR.env.ie? +setTimeout(function(){c.$.scrollTo(0,0)},0):c.$.scrollTo(0,0);t.setStyle("position",CKEDITOR.env.gecko&&CKEDITOR.env.quirks?"fixed":"absolute");t.$.offsetLeft;t.setStyles({"z-index":f.config.baseFloatZIndex-5,left:"0px",top:"0px"});t.addClass("cke_maximized");h();p=t.getDocumentPosition();t.setStyles({left:-1*p.x+"px",top:-1*p.y+"px"});CKEDITOR.env.gecko&&d(f)}else if(this.state==CKEDITOR.TRISTATE_ON){c.removeListener("resize",h);for(var q=[p,t],r=0;r<q.length;r++)k(q[r],q[r].getCustomData("maximize_saved_styles")), +q[r].removeCustomData("maximize_saved_styles");for(q=f.container;q=q.getParent();)k(q,q.getCustomData("maximize_saved_styles")),q.removeCustomData("maximize_saved_styles");CKEDITOR.env.ie?setTimeout(function(){c.$.scrollTo(w.x,w.y)},0):c.$.scrollTo(w.x,w.y);t.removeClass("cke_maximized");CKEDITOR.env.webkit&&(t.setStyle("display","inline"),setTimeout(function(){t.setStyle("display","block")},0));f.fire("resize",{outerHeight:f.container.$.offsetHeight,contentsHeight:p.$.offsetHeight,outerWidth:f.container.$.offsetWidth})}this.toggleState(); +if(q=this.uiItems[0])p=this.state==CKEDITOR.TRISTATE_OFF?b.maximize.maximize:b.maximize.minimize,q=CKEDITOR.document.getById(q._.id),q.getChild(1).setHtml(p),q.setAttribute("title",p),q.setAttribute("href",'javascript:void("'+p+'");');"wysiwyg"==f.mode?a?(CKEDITOR.env.gecko&&d(f),f.getSelection().selectRanges(a),(A=f.getSelection().getStartElement())&&A.scrollIntoView(!0)):c.$.scrollTo(n.x,n.y):(a&&(A.selectionStart=a[0],A.selectionEnd=a[1]),A.scrollLeft=n[0],A.scrollTop=n[1]);a=n=null;v=this.state; f.fire("maximize",this.state)},canUndo:!1});f.ui.addButton&&f.ui.addButton("Maximize",{label:b.maximize.maximize,command:"maximize",toolbar:"tools,10"});f.on("mode",function(){var a=f.getCommand("maximize");a.setState(a.state==CKEDITOR.TRISTATE_DISABLED?CKEDITOR.TRISTATE_DISABLED:v)},null,null,100)}}})}(),function(){function f(f,e,k){var d=CKEDITOR.cleanWord;d?k():(f=CKEDITOR.getUrl(f.config.pasteFromWordCleanupFile||e+"filter/default.js"),CKEDITOR.scriptLoader.load(f,k,null,!0));return!d}CKEDITOR.plugins.add("pastefromword", -{requires:"clipboard",init:function(h){function e(d){var b=CKEDITOR.plugins.pastefromword&&CKEDITOR.plugins.pastefromword.images,g,c=[];if(b&&d.editor.filter.check("img[src]")&&(g=b.extractTagsFromHtml(d.data.dataValue),0!==g.length&&(b=b.extractFromRtf(d.data.dataTransfer["text/rtf"]),0!==b.length&&(CKEDITOR.tools.array.forEach(b,function(a){c.push(a.type?"data:"+a.type+";base64,"+CKEDITOR.tools.convertBytesToBase64(CKEDITOR.tools.convertHexStringToBytes(a.hex)):null)},this),g.length===c.length))))for(b= -0;b<g.length;b++)0===g[b].indexOf("file://")&&c[b]&&(d.data.dataValue=d.data.dataValue.replace(g[b],c[b]))}var k=0,d=this.path,l=void 0===h.config.pasteFromWord_inlineImages?!0:h.config.pasteFromWord_inlineImages;h.addCommand("pastefromword",{canUndo:!1,async:!0,exec:function(d,b){k=1;d.execCommand("paste",{type:"html",notification:b&&"undefined"!==typeof b.notification?b.notification:!0})}});CKEDITOR.plugins.clipboard.addPasteButton(h,"PasteFromWord",{label:h.lang.pastefromword.toolbar,command:"pastefromword", +{requires:"clipboard",init:function(h){function e(d){var b=CKEDITOR.plugins.pastefromword&&CKEDITOR.plugins.pastefromword.images,e,c=[];if(b&&d.editor.filter.check("img[src]")&&(e=b.extractTagsFromHtml(d.data.dataValue),0!==e.length&&(b=b.extractFromRtf(d.data.dataTransfer["text/rtf"]),0!==b.length&&(CKEDITOR.tools.array.forEach(b,function(a){c.push(a.type?"data:"+a.type+";base64,"+CKEDITOR.tools.convertBytesToBase64(CKEDITOR.tools.convertHexStringToBytes(a.hex)):null)},this),e.length===c.length))))for(b= +0;b<e.length;b++)0===e[b].indexOf("file://")&&c[b]&&(d.data.dataValue=d.data.dataValue.replace(e[b],c[b]))}var k=0,d=this.path,l=void 0===h.config.pasteFromWord_inlineImages?!0:h.config.pasteFromWord_inlineImages;h.addCommand("pastefromword",{canUndo:!1,async:!0,exec:function(d,b){k=1;d.execCommand("paste",{type:"html",notification:b&&"undefined"!==typeof b.notification?b.notification:!0})}});CKEDITOR.plugins.clipboard.addPasteButton(h,"PasteFromWord",{label:h.lang.pastefromword.toolbar,command:"pastefromword", toolbar:"clipboard,50"});h.on("paste",function(e){var b=e.data,g=CKEDITOR.plugins.clipboard.isCustomDataTypesSupported?b.dataTransfer.getData("text/html",!0):null,c=CKEDITOR.plugins.clipboard.isCustomDataTypesSupported?b.dataTransfer.getData("text/rtf"):null,g=g||b.dataValue,a={dataValue:g,dataTransfer:{"text/rtf":c}},c=/(class=\"?Mso|style=(?:\"|\')[^\"]*?\bmso\-|w:WordDocument|<o:\w+>|<\/font>)/,c=/<meta\s*name=(?:\"|\')?generator(?:\"|\')?\s*content=(?:\"|\')?microsoft/gi.test(g)||c.test(g);if(g&& -(k||c)&&(!1!==h.fire("pasteFromWord",a)||k)){b.dontFilter=!0;var l=f(h,d,function(){if(l)h.fire("paste",b);else if(!h.config.pasteFromWordPromptCleanup||k||confirm(h.lang.pastefromword.confirmCleanup))a.dataValue=CKEDITOR.cleanWord(a.dataValue,h),h.fire("afterPasteFromWord",a),b.dataValue=a.dataValue,!0===h.config.forcePasteAsPlainText?b.type="text":CKEDITOR.env.ie&&"allow-word"===h.config.forcePasteAsPlainText&&(b.type="html");k=0});l&&e.cancel()}},null,null,3);if(CKEDITOR.plugins.clipboard.isCustomDataTypesSupported&& -l)h.on("afterPasteFromWord",e)}})}(),function(){var f={canUndo:!1,async:!0,exec:function(f,e){var k=f.lang,d=CKEDITOR.tools.keystrokeToString(k.common.keyboard,f.getCommandKeystroke(CKEDITOR.env.ie?f.commands.paste:this)),l=e&&"undefined"!==typeof e.notification?e.notification:!e||!e.from||"keystrokeHandler"===e.from&&CKEDITOR.env.ie,k=l&&"string"===typeof l?l:k.pastetext.pasteNotification.replace(/%1/,'\x3ckbd aria-label\x3d"'+d.aria+'"\x3e'+d.display+"\x3c/kbd\x3e");f.execCommand("paste",{type:"text", -notification:l?k:!1})}};CKEDITOR.plugins.add("pastetext",{requires:"clipboard",init:function(h){var e=CKEDITOR.env.safari?CKEDITOR.CTRL+CKEDITOR.ALT+CKEDITOR.SHIFT+86:CKEDITOR.CTRL+CKEDITOR.SHIFT+86;h.addCommand("pastetext",f);h.setKeystroke(e,"pastetext");CKEDITOR.plugins.clipboard.addPasteButton(h,"PasteText",{label:h.lang.pastetext.button,command:"pastetext",toolbar:"clipboard,40"});if(h.config.forcePasteAsPlainText)h.on("beforePaste",function(e){"html"!=e.data.type&&(e.data.type="text")});h.on("pasteState", -function(e){h.getCommand("pastetext").setState(e.data)})}})}(),CKEDITOR.plugins.add("removeformat",{init:function(f){f.addCommand("removeFormat",CKEDITOR.plugins.removeformat.commands.removeformat);f.ui.addButton&&f.ui.addButton("RemoveFormat",{label:f.lang.removeformat.toolbar,command:"removeFormat",toolbar:"cleanup,10"})}}),CKEDITOR.plugins.removeformat={commands:{removeformat:{exec:function(f){for(var h=f._.removeFormatRegex||(f._.removeFormatRegex=new RegExp("^(?:"+f.config.removeFormatTags.replace(/,/g, -"|")+")$","i")),e=f._.removeAttributes||(f._.removeAttributes=f.config.removeFormatAttributes.split(",")),k=CKEDITOR.plugins.removeformat.filter,d=f.getSelection().getRanges(),l=d.createIterator(),m=function(a){return a.type==CKEDITOR.NODE_ELEMENT},b;b=l.getNextRange();){b.collapsed||b.enlarge(CKEDITOR.ENLARGE_ELEMENT);var g=b.createBookmark(),c=g.startNode,a=g.endNode,n=function(a){for(var b=f.elementPath(a),c=b.elements,d=1,g;(g=c[d])&&!g.equals(b.block)&&!g.equals(b.blockLimit);d++)h.test(g.getName())&& -k(f,g)&&a.breakParent(g)};n(c);if(a)for(n(a),c=c.getNextSourceNode(!0,CKEDITOR.NODE_ELEMENT);c&&!c.equals(a);)if(c.isReadOnly()){if(c.getPosition(a)&CKEDITOR.POSITION_CONTAINS)break;c=c.getNext(m)}else n=c.getNextSourceNode(!1,CKEDITOR.NODE_ELEMENT),"img"==c.getName()&&c.data("cke-realelement")||!k(f,c)||(h.test(c.getName())?c.remove(1):(c.removeAttributes(e),f.fire("removeFormatCleanup",c))),c=n;b.moveToBookmark(g)}f.forceNextSelectionCheck();f.getSelection().selectRanges(d)}}},filter:function(f, -h){for(var e=f._.removeFormatFilters||[],k=0;k<e.length;k++)if(!1===e[k](h))return!1;return!0}},CKEDITOR.editor.prototype.addRemoveFormatFilter=function(f){this._.removeFormatFilters||(this._.removeFormatFilters=[]);this._.removeFormatFilters.push(f)},CKEDITOR.config.removeFormatTags="b,big,cite,code,del,dfn,em,font,i,ins,kbd,q,s,samp,small,span,strike,strong,sub,sup,tt,u,var",CKEDITOR.config.removeFormatAttributes="class,style,lang,width,height,align,hspace,valign",function(){function f(e,f,d){var l, -m;if(d="string"==typeof d?CKEDITOR.document.getById(d):new CKEDITOR.dom.element(d))if(l=e.fire("uiSpace",{space:f,html:""}).html)e.on("uiSpace",function(b){b.data.space==f&&b.cancel()},null,null,1),m=d.append(CKEDITOR.dom.element.createFromHtml(h.output({id:e.id,name:e.name,langDir:e.lang.dir,langCode:e.langCode,space:f,spaceId:e.ui.spaceId(f),content:l}))),d.getCustomData("cke_hasshared")?m.hide():d.setCustomData("cke_hasshared",1),m.unselectable(),m.on("mousedown",function(b){b=b.data;b.getTarget().hasAscendant("a", -1)||b.preventDefault()}),e.focusManager.add(m,1),e.on("focus",function(){for(var b=0,g,c=d.getChildren();g=c.getItem(b);b++)g.type==CKEDITOR.NODE_ELEMENT&&!g.equals(m)&&g.hasClass("cke_shared")&&g.hide();m.show()}),e.on("destroy",function(){m.remove()})}var h=CKEDITOR.addTemplate("sharedcontainer",'\x3cdiv id\x3d"cke_{name}" class\x3d"cke {id} cke_reset_all cke_chrome cke_editor_{name} cke_shared cke_detached cke_{langDir} '+CKEDITOR.env.cssClass+'" dir\x3d"{langDir}" title\x3d"'+(CKEDITOR.env.gecko? -" ":"")+'" lang\x3d"{langCode}" role\x3d"presentation"\x3e\x3cdiv class\x3d"cke_inner"\x3e\x3cdiv id\x3d"{spaceId}" class\x3d"cke_{space}" role\x3d"presentation"\x3e{content}\x3c/div\x3e\x3c/div\x3e\x3c/div\x3e');CKEDITOR.plugins.add("sharedspace",{init:function(e){e.on("loaded",function(){var h=e.config.sharedSpaces;if(h)for(var d in h)f(e,d,h[d])},null,null,9)}})}(),function(){var f={readOnly:1,preserveState:!0,editorFocus:!1,exec:function(f){this.toggleState();this.refresh(f)},refresh:function(f){if(f.document){var e= -this.state!=CKEDITOR.TRISTATE_ON||f.elementMode==CKEDITOR.ELEMENT_MODE_INLINE&&!f.focusManager.hasFocus?"removeClass":"attachClass";f.editable()[e]("cke_show_blocks")}}};CKEDITOR.plugins.add("showblocks",{onLoad:function(){var f="p div pre address blockquote h1 h2 h3 h4 h5 h6".split(" "),e,k,d,l,m=CKEDITOR.getUrl(this.path),b=!(CKEDITOR.env.ie&&9>CKEDITOR.env.version),g=b?":not([contenteditable\x3dfalse]):not(.cke_show_blocks_off)":"",c,a;for(e=k=d=l="";c=f.pop();)a=f.length?",":"",e+=".cke_show_blocks "+ -c+g+a,d+=".cke_show_blocks.cke_contents_ltr "+c+g+a,l+=".cke_show_blocks.cke_contents_rtl "+c+g+a,k+=".cke_show_blocks "+c+g+"{background-image:url("+CKEDITOR.getUrl(m+"images/block_"+c+".png")+")}";CKEDITOR.addCss((e+"{background-repeat:no-repeat;border:1px dotted gray;padding-top:8px}").concat(k,d+"{background-position:top left;padding-left:8px}",l+"{background-position:top right;padding-right:8px}"));b||CKEDITOR.addCss(".cke_show_blocks [contenteditable\x3dfalse],.cke_show_blocks .cke_show_blocks_off{border:none;padding-top:0;background-image:none}.cke_show_blocks.cke_contents_rtl [contenteditable\x3dfalse],.cke_show_blocks.cke_contents_rtl .cke_show_blocks_off{padding-right:0}.cke_show_blocks.cke_contents_ltr [contenteditable\x3dfalse],.cke_show_blocks.cke_contents_ltr .cke_show_blocks_off{padding-left:0}")}, +(k||c)&&(!1!==h.fire("pasteFromWord",a)||k)){b.dontFilter=!0;var l=f(h,d,function(){if(l)h.fire("paste",b);else if(!h.config.pasteFromWordPromptCleanup||k||confirm(h.lang.pastefromword.confirmCleanup))a.dataValue=CKEDITOR.cleanWord(a.dataValue,h),h.fire("afterPasteFromWord",a),b.dataValue=a.dataValue,!0===h.config.forcePasteAsPlainText?b.type="text":CKEDITOR.plugins.clipboard.isCustomCopyCutSupported||"allow-word"!==h.config.forcePasteAsPlainText||(b.type="html");k=0});l&&e.cancel()}},null,null,3); +if(CKEDITOR.plugins.clipboard.isCustomDataTypesSupported&&l)h.on("afterPasteFromWord",e)}})}(),function(){var f={canUndo:!1,async:!0,exec:function(f,e){var k=f.lang,d=CKEDITOR.tools.keystrokeToString(k.common.keyboard,f.getCommandKeystroke(CKEDITOR.env.ie?f.commands.paste:this)),l=e&&"undefined"!==typeof e.notification?e.notification:!e||!e.from||"keystrokeHandler"===e.from&&CKEDITOR.env.ie,k=l&&"string"===typeof l?l:k.pastetext.pasteNotification.replace(/%1/,'\x3ckbd aria-label\x3d"'+d.aria+'"\x3e'+ +d.display+"\x3c/kbd\x3e");f.execCommand("paste",{type:"text",notification:l?k:!1})}};CKEDITOR.plugins.add("pastetext",{requires:"clipboard",init:function(h){var e=CKEDITOR.env.safari?CKEDITOR.CTRL+CKEDITOR.ALT+CKEDITOR.SHIFT+86:CKEDITOR.CTRL+CKEDITOR.SHIFT+86;h.addCommand("pastetext",f);h.setKeystroke(e,"pastetext");CKEDITOR.plugins.clipboard.addPasteButton(h,"PasteText",{label:h.lang.pastetext.button,command:"pastetext",toolbar:"clipboard,40"});if(h.config.forcePasteAsPlainText)h.on("beforePaste", +function(e){"html"!=e.data.type&&(e.data.type="text")});h.on("pasteState",function(e){h.getCommand("pastetext").setState(e.data)})}})}(),CKEDITOR.plugins.add("removeformat",{init:function(f){f.addCommand("removeFormat",CKEDITOR.plugins.removeformat.commands.removeformat);f.ui.addButton&&f.ui.addButton("RemoveFormat",{label:f.lang.removeformat.toolbar,command:"removeFormat",toolbar:"cleanup,10"})}}),CKEDITOR.plugins.removeformat={commands:{removeformat:{exec:function(f){for(var h=f._.removeFormatRegex|| +(f._.removeFormatRegex=new RegExp("^(?:"+f.config.removeFormatTags.replace(/,/g,"|")+")$","i")),e=f._.removeAttributes||(f._.removeAttributes=f.config.removeFormatAttributes.split(",")),k=CKEDITOR.plugins.removeformat.filter,d=f.getSelection().getRanges(),l=d.createIterator(),m=function(a){return a.type==CKEDITOR.NODE_ELEMENT},b;b=l.getNextRange();){b.collapsed||b.enlarge(CKEDITOR.ENLARGE_ELEMENT);var g=b.createBookmark(),c=g.startNode,a=g.endNode,n=function(a){for(var b=f.elementPath(a),c=b.elements, +d=1,e;(e=c[d])&&!e.equals(b.block)&&!e.equals(b.blockLimit);d++)h.test(e.getName())&&k(f,e)&&a.breakParent(e)};n(c);if(a)for(n(a),c=c.getNextSourceNode(!0,CKEDITOR.NODE_ELEMENT);c&&!c.equals(a);)if(c.isReadOnly()){if(c.getPosition(a)&CKEDITOR.POSITION_CONTAINS)break;c=c.getNext(m)}else n=c.getNextSourceNode(!1,CKEDITOR.NODE_ELEMENT),"img"==c.getName()&&c.data("cke-realelement")||!k(f,c)||(h.test(c.getName())?c.remove(1):(c.removeAttributes(e),f.fire("removeFormatCleanup",c))),c=n;b.moveToBookmark(g)}f.forceNextSelectionCheck(); +f.getSelection().selectRanges(d)}}},filter:function(f,h){for(var e=f._.removeFormatFilters||[],k=0;k<e.length;k++)if(!1===e[k](h))return!1;return!0}},CKEDITOR.editor.prototype.addRemoveFormatFilter=function(f){this._.removeFormatFilters||(this._.removeFormatFilters=[]);this._.removeFormatFilters.push(f)},CKEDITOR.config.removeFormatTags="b,big,cite,code,del,dfn,em,font,i,ins,kbd,q,s,samp,small,span,strike,strong,sub,sup,tt,u,var",CKEDITOR.config.removeFormatAttributes="class,style,lang,width,height,align,hspace,valign", +function(){function f(e,f,d){var l,m;if(d="string"==typeof d?CKEDITOR.document.getById(d):new CKEDITOR.dom.element(d))if(l=e.fire("uiSpace",{space:f,html:""}).html)e.on("uiSpace",function(b){b.data.space==f&&b.cancel()},null,null,1),m=d.append(CKEDITOR.dom.element.createFromHtml(h.output({id:e.id,name:e.name,langDir:e.lang.dir,langCode:e.langCode,space:f,spaceId:e.ui.spaceId(f),content:l}))),d.getCustomData("cke_hasshared")?m.hide():d.setCustomData("cke_hasshared",1),m.unselectable(),m.on("mousedown", +function(b){b=b.data;b.getTarget().hasAscendant("a",1)||b.preventDefault()}),e.focusManager.add(m,1),e.on("focus",function(){for(var b=0,e,c=d.getChildren();e=c.getItem(b);b++)e.type==CKEDITOR.NODE_ELEMENT&&!e.equals(m)&&e.hasClass("cke_shared")&&e.hide();m.show()}),e.on("destroy",function(){m.remove()})}var h=CKEDITOR.addTemplate("sharedcontainer",'\x3cdiv id\x3d"cke_{name}" class\x3d"cke {id} cke_reset_all cke_chrome cke_editor_{name} cke_shared cke_detached cke_{langDir} '+CKEDITOR.env.cssClass+ +'" dir\x3d"{langDir}" title\x3d"'+(CKEDITOR.env.gecko?" ":"")+'" lang\x3d"{langCode}" role\x3d"presentation"\x3e\x3cdiv class\x3d"cke_inner"\x3e\x3cdiv id\x3d"{spaceId}" class\x3d"cke_{space}" role\x3d"presentation"\x3e{content}\x3c/div\x3e\x3c/div\x3e\x3c/div\x3e');CKEDITOR.plugins.add("sharedspace",{init:function(e){e.on("loaded",function(){var h=e.config.sharedSpaces;if(h)for(var d in h)f(e,d,h[d])},null,null,9)}})}(),function(){var f={readOnly:1,preserveState:!0,editorFocus:!1,exec:function(f){this.toggleState(); +this.refresh(f)},refresh:function(f){if(f.document){var e=this.state!=CKEDITOR.TRISTATE_ON||f.elementMode==CKEDITOR.ELEMENT_MODE_INLINE&&!f.focusManager.hasFocus?"removeClass":"attachClass";f.editable()[e]("cke_show_blocks")}}};CKEDITOR.plugins.add("showblocks",{onLoad:function(){var f="p div pre address blockquote h1 h2 h3 h4 h5 h6".split(" "),e,k,d,l,m=CKEDITOR.getUrl(this.path),b=!(CKEDITOR.env.ie&&9>CKEDITOR.env.version),g=b?":not([contenteditable\x3dfalse]):not(.cke_show_blocks_off)":"",c,a; +for(e=k=d=l="";c=f.pop();)a=f.length?",":"",e+=".cke_show_blocks "+c+g+a,d+=".cke_show_blocks.cke_contents_ltr "+c+g+a,l+=".cke_show_blocks.cke_contents_rtl "+c+g+a,k+=".cke_show_blocks "+c+g+"{background-image:url("+CKEDITOR.getUrl(m+"images/block_"+c+".png")+")}";CKEDITOR.addCss((e+"{background-repeat:no-repeat;border:1px dotted gray;padding-top:8px}").concat(k,d+"{background-position:top left;padding-left:8px}",l+"{background-position:top right;padding-right:8px}"));b||CKEDITOR.addCss(".cke_show_blocks [contenteditable\x3dfalse],.cke_show_blocks .cke_show_blocks_off{border:none;padding-top:0;background-image:none}.cke_show_blocks.cke_contents_rtl [contenteditable\x3dfalse],.cke_show_blocks.cke_contents_rtl .cke_show_blocks_off{padding-right:0}.cke_show_blocks.cke_contents_ltr [contenteditable\x3dfalse],.cke_show_blocks.cke_contents_ltr .cke_show_blocks_off{padding-left:0}")}, init:function(h){function e(){k.refresh(h)}if(!h.blockless){var k=h.addCommand("showblocks",f);k.canUndo=!1;h.config.startupOutlineBlocks&&k.setState(CKEDITOR.TRISTATE_ON);h.ui.addButton&&h.ui.addButton("ShowBlocks",{label:h.lang.showblocks.toolbar,command:"showblocks",toolbar:"tools,20"});h.on("mode",function(){k.state!=CKEDITOR.TRISTATE_DISABLED&&k.refresh(h)});h.elementMode==CKEDITOR.ELEMENT_MODE_INLINE&&(h.on("focus",e),h.on("blur",e));h.on("contentDom",function(){k.state!=CKEDITOR.TRISTATE_DISABLED&& k.refresh(h)})}}})}(),function(){var f={preserveState:!0,editorFocus:!1,readOnly:1,exec:function(f){this.toggleState();this.refresh(f)},refresh:function(f){if(f.document){var e=this.state==CKEDITOR.TRISTATE_ON?"attachClass":"removeClass";f.editable()[e]("cke_show_borders")}}};CKEDITOR.plugins.add("showborders",{modes:{wysiwyg:1},onLoad:function(){var f;f=(CKEDITOR.env.ie6Compat?[".%1 table.%2,",".%1 table.%2 td, .%1 table.%2 th","{","border : #d3d3d3 1px dotted","}"]:".%1 table.%2,;.%1 table.%2 \x3e tr \x3e td, .%1 table.%2 \x3e tr \x3e th,;.%1 table.%2 \x3e tbody \x3e tr \x3e td, .%1 table.%2 \x3e tbody \x3e tr \x3e th,;.%1 table.%2 \x3e thead \x3e tr \x3e td, .%1 table.%2 \x3e thead \x3e tr \x3e th,;.%1 table.%2 \x3e tfoot \x3e tr \x3e td, .%1 table.%2 \x3e tfoot \x3e tr \x3e th;{;border : #d3d3d3 1px dotted;}".split(";")).join("").replace(/%2/g, "cke_show_border").replace(/%1/g,"cke_show_borders ");CKEDITOR.addCss(f)},init:function(h){var e=h.addCommand("showborders",f);e.canUndo=!1;!1!==h.config.startupShowBorders&&e.setState(CKEDITOR.TRISTATE_ON);h.on("mode",function(){e.state!=CKEDITOR.TRISTATE_DISABLED&&e.refresh(h)},null,null,100);h.on("contentDom",function(){e.state!=CKEDITOR.TRISTATE_DISABLED&&e.refresh(h)});h.on("removeFormatCleanup",function(e){e=e.data;h.getCommand("showborders").state==CKEDITOR.TRISTATE_ON&&e.is("table")&&(!e.hasAttribute("border")|| @@ -1059,36 +1059,36 @@ requires:"dialog",init:function(f){var h=this;CKEDITOR.dialog.add("specialchar", {label:f.lang.specialchar.toolbar,command:"specialchar",toolbar:"insert,50"})}}),CKEDITOR.config.specialChars="! \x26quot; # $ % \x26amp; ' ( ) * + - . / 0 1 2 3 4 5 6 7 8 9 : ; \x26lt; \x3d \x26gt; ? @ A B C D E F G H I J K L M N O P Q R S T U V W X Y Z [ ] ^ _ ` a b c d e f g h i j k l m n o p q r s t u v w x y z { | } ~ \x26euro; \x26lsquo; \x26rsquo; \x26ldquo; \x26rdquo; \x26ndash; \x26mdash; \x26iexcl; \x26cent; \x26pound; \x26curren; \x26yen; \x26brvbar; \x26sect; \x26uml; \x26copy; \x26ordf; \x26laquo; \x26not; \x26reg; \x26macr; \x26deg; \x26sup2; \x26sup3; \x26acute; \x26micro; \x26para; \x26middot; \x26cedil; \x26sup1; \x26ordm; \x26raquo; \x26frac14; \x26frac12; \x26frac34; \x26iquest; \x26Agrave; \x26Aacute; \x26Acirc; \x26Atilde; \x26Auml; \x26Aring; \x26AElig; \x26Ccedil; \x26Egrave; \x26Eacute; \x26Ecirc; \x26Euml; \x26Igrave; \x26Iacute; \x26Icirc; \x26Iuml; \x26ETH; \x26Ntilde; \x26Ograve; \x26Oacute; \x26Ocirc; \x26Otilde; \x26Ouml; \x26times; \x26Oslash; \x26Ugrave; \x26Uacute; \x26Ucirc; \x26Uuml; \x26Yacute; \x26THORN; \x26szlig; \x26agrave; \x26aacute; \x26acirc; \x26atilde; \x26auml; \x26aring; \x26aelig; \x26ccedil; \x26egrave; \x26eacute; \x26ecirc; \x26euml; \x26igrave; \x26iacute; \x26icirc; \x26iuml; \x26eth; \x26ntilde; \x26ograve; \x26oacute; \x26ocirc; \x26otilde; \x26ouml; \x26divide; \x26oslash; \x26ugrave; \x26uacute; \x26ucirc; \x26uuml; \x26yacute; \x26thorn; \x26yuml; \x26OElig; \x26oelig; \x26#372; \x26#374 \x26#373 \x26#375; \x26sbquo; \x26#8219; \x26bdquo; \x26hellip; \x26trade; \x26#9658; \x26bull; \x26rarr; \x26rArr; \x26hArr; \x26diams; \x26asymp;".split(" "), function(){CKEDITOR.plugins.add("stylescombo",{requires:"richcombo",init:function(f){var h=f.config,e=f.lang.stylescombo,k={},d=[],l=[];f.on("stylesSet",function(e){if(e=e.data.styles){for(var b,g,c,a=0,n=e.length;a<n;a++)(b=e[a],f.blockless&&b.element in CKEDITOR.dtd.$block||"string"==typeof b.type&&!CKEDITOR.style.customHandlers[b.type]||(g=b.name,b=new CKEDITOR.style(b),f.filter.customConfig&&!f.filter.check(b)))||(b._name=g,b._.enterMode=h.enterMode,b._.type=c=b.assignedTo||b.type,b._.weight= a+1E3*(c==CKEDITOR.STYLE_OBJECT?1:c==CKEDITOR.STYLE_BLOCK?2:3),k[g]=b,d.push(b),l.push(b));d.sort(function(a,b){return a._.weight-b._.weight})}});f.ui.addRichCombo("Styles",{label:e.label,title:e.panelTitle,toolbar:"styles,10",allowedContent:l,panel:{css:[CKEDITOR.skin.getPath("editor")].concat(h.contentsCss),multiSelect:!0,attributes:{"aria-label":e.panelTitle}},init:function(){var f,b,g,c,a,h;a=0;for(h=d.length;a<h;a++)f=d[a],b=f._name,c=f._.type,c!=g&&(this.startGroup(e["panelTitle"+String(c)]), -g=c),this.add(b,f.type==CKEDITOR.STYLE_OBJECT?b:f.buildPreview(),b);this.commit()},onClick:function(d){f.focus();f.fire("saveSnapshot");d=k[d];var b=f.elementPath();if(d.group&&d.removeStylesFromSameGroup(f))f.applyStyle(d);else f[d.checkActive(b,f)?"removeStyle":"applyStyle"](d);f.fire("saveSnapshot")},onRender:function(){f.on("selectionChange",function(d){var b=this.getValue();d=d.data.path.elements;for(var g=0,c=d.length,a;g<c;g++){a=d[g];for(var e in k)if(k[e].checkElementRemovable(a,!0,f)){e!= -b&&this.setValue(e);return}}this.setValue("")},this)},onOpen:function(){var d=f.getSelection(),d=d.getSelectedElement()||d.getStartElement()||f.editable(),d=f.elementPath(d),b=[0,0,0,0];this.showAll();this.unmarkAll();for(var g in k){var c=k[g],a=c._.type;c.checkApplicable(d,f,f.activeFilter)?b[a]++:this.hideItem(g);c.checkActive(d,f)&&this.mark(g)}b[CKEDITOR.STYLE_BLOCK]||this.hideGroup(e["panelTitle"+String(CKEDITOR.STYLE_BLOCK)]);b[CKEDITOR.STYLE_INLINE]||this.hideGroup(e["panelTitle"+String(CKEDITOR.STYLE_INLINE)]); +g=c),this.add(b,f.type==CKEDITOR.STYLE_OBJECT?b:f.buildPreview(),b);this.commit()},onClick:function(d){f.focus();f.fire("saveSnapshot");d=k[d];var b=f.elementPath();if(d.group&&d.removeStylesFromSameGroup(f))f.applyStyle(d);else f[d.checkActive(b,f)?"removeStyle":"applyStyle"](d);f.fire("saveSnapshot")},onRender:function(){f.on("selectionChange",function(d){var b=this.getValue();d=d.data.path.elements;for(var e=0,c=d.length,a;e<c;e++){a=d[e];for(var h in k)if(k[h].checkElementRemovable(a,!0,f)){h!= +b&&this.setValue(h);return}}this.setValue("")},this)},onOpen:function(){var d=f.getSelection(),d=d.getSelectedElement()||d.getStartElement()||f.editable(),d=f.elementPath(d),b=[0,0,0,0];this.showAll();this.unmarkAll();for(var g in k){var c=k[g],a=c._.type;c.checkApplicable(d,f,f.activeFilter)?b[a]++:this.hideItem(g);c.checkActive(d,f)&&this.mark(g)}b[CKEDITOR.STYLE_BLOCK]||this.hideGroup(e["panelTitle"+String(CKEDITOR.STYLE_BLOCK)]);b[CKEDITOR.STYLE_INLINE]||this.hideGroup(e["panelTitle"+String(CKEDITOR.STYLE_INLINE)]); b[CKEDITOR.STYLE_OBJECT]||this.hideGroup(e["panelTitle"+String(CKEDITOR.STYLE_OBJECT)])},refresh:function(){var d=f.elementPath();if(d){for(var b in k)if(k[b].checkApplicable(d,f,f.activeFilter))return;this.setState(CKEDITOR.TRISTATE_DISABLED)}},reset:function(){k={};d=[]}})}})}(),function(){function f(d){return{editorFocus:!1,canUndo:!1,modes:{wysiwyg:1},exec:function(e){if(e.editable().hasFocus){var f=e.getSelection(),b;if(b=(new CKEDITOR.dom.elementPath(f.getCommonAncestor(),f.root)).contains({td:1, th:1},1)){var f=e.createRange(),g=CKEDITOR.tools.tryThese(function(){var a=b.getParent().$.cells[b.$.cellIndex+(d?-1:1)];a.parentNode.parentNode;return a},function(){var a=b.getParent(),a=a.getAscendant("table").$.rows[a.$.rowIndex+(d?-1:1)];return a.cells[d?a.cells.length-1:0]});if(g||d)if(g)g=new CKEDITOR.dom.element(g),f.moveToElementEditStart(g),f.checkStartOfBlock()&&f.checkEndOfBlock()||f.selectNodeContents(g);else return!0;else{for(var c=b.getAscendant("table").$,g=b.getParent().$.cells,c= new CKEDITOR.dom.element(c.insertRow(-1),e.document),a=0,h=g.length;a<h;a++)c.append((new CKEDITOR.dom.element(g[a],e.document)).clone(!1,!1)).appendBogus();f.moveToElementEditStart(c)}f.select(!0);return!0}}return!1}}}var h={editorFocus:!1,modes:{wysiwyg:1,source:1}},e={exec:function(d){d.container.focusNext(!0,d.tabIndex)}},k={exec:function(d){d.container.focusPrevious(!0,d.tabIndex)}};CKEDITOR.plugins.add("tab",{init:function(d){for(var l=!1!==d.config.enableTabKeyTools,m=d.config.tabSpaces||0, -b="";m--;)b+=" ";if(b)d.on("key",function(g){9==g.data.keyCode&&(d.insertText(b),g.cancel())});if(l)d.on("key",function(b){(9==b.data.keyCode&&d.execCommand("selectNextCell")||b.data.keyCode==CKEDITOR.SHIFT+9&&d.execCommand("selectPreviousCell"))&&b.cancel()});d.addCommand("blur",CKEDITOR.tools.extend(e,h));d.addCommand("blurBack",CKEDITOR.tools.extend(k,h));d.addCommand("selectNextCell",f());d.addCommand("selectPreviousCell",f(!0))}})}(),CKEDITOR.dom.element.prototype.focusNext=function(f,h){var e= +b="";m--;)b+=" ";if(b)d.on("key",function(e){9==e.data.keyCode&&(d.insertText(b),e.cancel())});if(l)d.on("key",function(b){(9==b.data.keyCode&&d.execCommand("selectNextCell")||b.data.keyCode==CKEDITOR.SHIFT+9&&d.execCommand("selectPreviousCell"))&&b.cancel()});d.addCommand("blur",CKEDITOR.tools.extend(e,h));d.addCommand("blurBack",CKEDITOR.tools.extend(k,h));d.addCommand("selectNextCell",f());d.addCommand("selectPreviousCell",f(!0))}})}(),CKEDITOR.dom.element.prototype.focusNext=function(f,h){var e= void 0===h?this.getTabIndex():h,k,d,l,m,b,g;if(0>=e)for(b=this.getNextSourceNode(f,CKEDITOR.NODE_ELEMENT);b;){if(b.isVisible()&&0===b.getTabIndex()){l=b;break}b=b.getNextSourceNode(!1,CKEDITOR.NODE_ELEMENT)}else for(b=this.getDocument().getBody().getFirst();b=b.getNextSourceNode(!1,CKEDITOR.NODE_ELEMENT);){if(!k)if(!d&&b.equals(this)){if(d=!0,f){if(!(b=b.getNextSourceNode(!0,CKEDITOR.NODE_ELEMENT)))break;k=1}}else d&&!this.contains(b)&&(k=1);if(b.isVisible()&&!(0>(g=b.getTabIndex()))){if(k&&g==e){l= b;break}g>e&&(!l||!m||g<m)?(l=b,m=g):l||0!==g||(l=b,m=g)}}l&&l.focus()},CKEDITOR.dom.element.prototype.focusPrevious=function(f,h){for(var e=void 0===h?this.getTabIndex():h,k,d,l,m=0,b,g=this.getDocument().getBody().getLast();g=g.getPreviousSourceNode(!1,CKEDITOR.NODE_ELEMENT);){if(!k)if(!d&&g.equals(this)){if(d=!0,f){if(!(g=g.getPreviousSourceNode(!0,CKEDITOR.NODE_ELEMENT)))break;k=1}}else d&&!this.contains(g)&&(k=1);if(g.isVisible()&&!(0>(b=g.getTabIndex())))if(0>=e){if(k&&0===b){l=g;break}b>m&& (l=g,m=b)}else{if(k&&b==e){l=g;break}b<e&&(!l||b>m)&&(l=g,m=b)}}l&&l.focus()},CKEDITOR.plugins.add("table",{requires:"dialog",init:function(f){function h(e){return CKEDITOR.tools.extend(e||{},{contextSensitive:1,refresh:function(d,e){this.setState(e.contains("table",1)?CKEDITOR.TRISTATE_OFF:CKEDITOR.TRISTATE_DISABLED)}})}if(!f.blockless){var e=f.lang.table;f.addCommand("table",new CKEDITOR.dialogCommand("table",{context:"table",allowedContent:"table{width,height}[align,border,cellpadding,cellspacing,summary];caption tbody thead tfoot;th td tr[scope];"+ (f.plugins.dialogadvtab?"table"+f.plugins.dialogadvtab.allowedContent():""),requiredContent:"table",contentTransformations:[["table{width}: sizeToStyle","table[width]: sizeToAttribute"],["td: splitBorderShorthand"],[{element:"table",right:function(e){if(e.styles){var d;if(e.styles.border)d=CKEDITOR.tools.style.parse.border(e.styles.border);else if(CKEDITOR.env.ie&&8===CKEDITOR.env.version){var f=e.styles;f["border-left"]&&f["border-left"]===f["border-right"]&&f["border-right"]===f["border-top"]&& f["border-top"]===f["border-bottom"]&&(d=CKEDITOR.tools.style.parse.border(f["border-top"]))}d&&d.style&&"solid"===d.style&&d.width&&0!==parseFloat(d.width)&&(e.attributes.border=1);"collapse"==e.styles["border-collapse"]&&(e.attributes.cellspacing=0)}}}]]}));f.addCommand("tableProperties",new CKEDITOR.dialogCommand("tableProperties",h()));f.addCommand("tableDelete",h({exec:function(e){var d=e.elementPath().contains("table",1);if(d){var f=d.getParent(),h=e.editable();1!=f.getChildCount()||f.is("td", "th")||f.equals(h)||(d=f);e=e.createRange();e.moveToPosition(d,CKEDITOR.POSITION_BEFORE_START);d.remove();e.select()}}}));f.ui.addButton&&f.ui.addButton("Table",{label:e.toolbar,command:"table",toolbar:"insert,30"});CKEDITOR.dialog.add("table",this.path+"dialogs/table.js");CKEDITOR.dialog.add("tableProperties",this.path+"dialogs/table.js");f.addMenuItems&&f.addMenuItems({table:{label:e.menu,command:"tableProperties",group:"table",order:5},tabledelete:{label:e.deleteTable,command:"tableDelete",group:"table", -order:1}});f.on("doubleclick",function(e){e.data.element.is("table")&&(e.data.dialog="tableProperties")});f.contextMenu&&f.contextMenu.addListener(function(){return{tabledelete:CKEDITOR.TRISTATE_OFF,table:CKEDITOR.TRISTATE_OFF}})}}}),function(){function f(a,b){function c(a){return b?b.contains(a)&&a.getAscendant("table",!0).equals(b):!0}function d(a){0<g.length||a.type!=CKEDITOR.NODE_ELEMENT||!p.test(a.getName())||a.getCustomData("selected_cell")||(CKEDITOR.dom.element.setMarker(e,a,"selected_cell", -!0),g.push(a))}var g=[],e={};if(!a)return g;for(var f=a.getRanges(),h=0;h<f.length;h++){var k=f[h];if(k.collapsed)(k=k.getCommonAncestor().getAscendant({td:1,th:1},!0))&&c(k)&&g.push(k);else{var k=new CKEDITOR.dom.walker(k),l;for(k.guard=d;l=k.next();)l.type==CKEDITOR.NODE_ELEMENT&&l.is(CKEDITOR.dtd.table)||(l=l.getAscendant({td:1,th:1},!0))&&!l.getCustomData("selected_cell")&&c(l)&&(CKEDITOR.dom.element.setMarker(e,l,"selected_cell",!0),g.push(l))}}CKEDITOR.dom.element.clearAllMarkers(e);return g} -function h(a,b){for(var c=r(a)?a:f(a),d=c[0],g=d.getAscendant("table"),d=d.getDocument(),e=c[0].getParent(),h=e.$.rowIndex,c=c[c.length-1],k=c.getParent().$.rowIndex+c.$.rowSpan-1,c=new CKEDITOR.dom.element(g.$.rows[k]),h=b?h:k,e=b?e:c,c=CKEDITOR.tools.buildTableMap(g),g=c[h],h=b?c[h-1]:c[h+1],c=c[0].length,d=d.createElement("tr"),k=0;g[k]&&k<c;k++){var l;1<g[k].rowSpan&&h&&g[k]==h[k]?(l=g[k],l.rowSpan+=1):(l=(new CKEDITOR.dom.element(g[k])).clone(),l.removeAttribute("rowSpan"),l.appendBogus(),d.append(l), -l=l.$);k+=l.colSpan-1}b?d.insertBefore(e):d.insertAfter(e);return d}function e(a){if(a instanceof CKEDITOR.dom.selection){var b=a.getRanges(),c=f(a),d=c[0].getAscendant("table"),g=CKEDITOR.tools.buildTableMap(d),h=c[0].getParent().$.rowIndex,c=c[c.length-1],k=c.getParent().$.rowIndex+c.$.rowSpan-1,c=[];a.reset();for(a=h;a<=k;a++){for(var l=g[a],m=new CKEDITOR.dom.element(d.$.rows[a]),n=0;n<l.length;n++){var p=new CKEDITOR.dom.element(l[n]),r=p.getParent().$.rowIndex;1==p.$.rowSpan?p.remove():(--p.$.rowSpan, -r==a&&(r=g[a+1],r[n-1]?p.insertAfter(new CKEDITOR.dom.element(r[n-1])):(new CKEDITOR.dom.element(d.$.rows[a+1])).append(p,1)));n+=p.$.colSpan-1}c.push(m)}g=d.$.rows;b[0].moveToPosition(d,CKEDITOR.POSITION_BEFORE_START);h=new CKEDITOR.dom.element(g[k+1]||(0<h?g[h-1]:null)||d.$.parentNode);for(a=c.length;0<=a;a--)e(c[a]);return d.$.parentNode?h:(b[0].select(),null)}a instanceof CKEDITOR.dom.element&&(d=a.getAscendant("table"),1==d.$.rows.length?d.remove():a.remove());return null}function k(a){for(var b= -a.getParent().$.cells,c=0,d=0;d<b.length;d++){var g=b[d],c=c+g.colSpan;if(g==a.$)break}return c-1}function d(a,b){for(var c=b?Infinity:0,d=0;d<a.length;d++){var g=k(a[d]);if(b?g<c:g>c)c=g}return c}function l(a,b){for(var c=r(a)?a:f(a),g=c[0].getAscendant("table"),e=d(c,1),c=d(c),h=b?e:c,k=CKEDITOR.tools.buildTableMap(g),g=[],e=[],c=[],l=k.length,m=0;m<l;m++)g.push(k[m][h]),e.push(b?k[m][h-1]:k[m][h+1]);for(m=0;m<l;m++)g[m]&&(1<g[m].colSpan&&e[m]==g[m]?(k=g[m],k.colSpan+=1):(h=new CKEDITOR.dom.element(g[m]), -k=h.clone(),k.removeAttribute("colSpan"),k.appendBogus(),k[b?"insertBefore":"insertAfter"].call(k,h),c.push(k),k=k.$),m+=k.rowSpan-1);return c}function m(a){function b(a){var c,d,g;c=a.getRanges();if(1!==c.length)return a;c=c[0];if(c.collapsed||0!==c.endOffset)return a;d=c.endContainer;g=d.getName().toLowerCase();if("td"!==g&&"th"!==g)return a;for((g=d.getPrevious())||(g=d.getParent().getPrevious().getLast());g.type!==CKEDITOR.NODE_TEXT&&"br"!==g.getName().toLowerCase();)if(g=g.getLast(),!g)return a; -c.setEndAt(g,CKEDITOR.POSITION_BEFORE_END);return c.select()}CKEDITOR.env.webkit&&!a.isFake&&(a=b(a));var c=a.getRanges(),d=f(a),g=d[0],e=d[d.length-1],d=g.getAscendant("table"),h=CKEDITOR.tools.buildTableMap(d),k,l,m=[];a.reset();var n=0;for(a=h.length;n<a;n++)for(var p=0,r=h[n].length;p<r;p++)void 0===k&&h[n][p]==g.$&&(k=p),h[n][p]==e.$&&(l=p);for(n=k;n<=l;n++)for(p=0;p<h.length;p++)e=h[p],g=new CKEDITOR.dom.element(d.$.rows[p]),e=new CKEDITOR.dom.element(e[n]),e.$&&(1==e.$.colSpan?e.remove():--e.$.colSpan, -p+=e.$.rowSpan-1,g.$.cells.length||m.push(g));k=h[0].length-1>l?new CKEDITOR.dom.element(h[0][l+1]):k&&-1!==h[0][k-1].cellIndex?new CKEDITOR.dom.element(h[0][k-1]):new CKEDITOR.dom.element(d.$.parentNode);m.length==a&&(c[0].moveToPosition(d,CKEDITOR.POSITION_AFTER_END),c[0].select(),d.remove());return k}function b(a,b){var c=a.getStartElement().getAscendant({td:1,th:1},!0);if(c){var d=c.clone();d.appendBogus();b?d.insertBefore(c):d.insertAfter(c)}}function g(a){if(a instanceof CKEDITOR.dom.selection){var b= +order:1}});f.on("doubleclick",function(e){e.data.element.is("table")&&(e.data.dialog="tableProperties")});f.contextMenu&&f.contextMenu.addListener(function(){return{tabledelete:CKEDITOR.TRISTATE_OFF,table:CKEDITOR.TRISTATE_OFF}})}}}),function(){function f(a,b){function c(a){return b?b.contains(a)&&a.getAscendant("table",!0).equals(b):!0}function d(a){0<e.length||a.type!=CKEDITOR.NODE_ELEMENT||!t.test(a.getName())||a.getCustomData("selected_cell")||(CKEDITOR.dom.element.setMarker(f,a,"selected_cell", +!0),e.push(a))}var e=[],f={};if(!a)return e;for(var g=a.getRanges(),h=0;h<g.length;h++){var k=g[h];if(k.collapsed)(k=k.getCommonAncestor().getAscendant({td:1,th:1},!0))&&c(k)&&e.push(k);else{var k=new CKEDITOR.dom.walker(k),l;for(k.guard=d;l=k.next();)l.type==CKEDITOR.NODE_ELEMENT&&l.is(CKEDITOR.dtd.table)||(l=l.getAscendant({td:1,th:1},!0))&&!l.getCustomData("selected_cell")&&c(l)&&(CKEDITOR.dom.element.setMarker(f,l,"selected_cell",!0),e.push(l))}}CKEDITOR.dom.element.clearAllMarkers(f);return e} +function h(a,b){for(var c=p(a)?a:f(a),d=c[0],e=d.getAscendant("table"),d=d.getDocument(),g=c[0].getParent(),h=g.$.rowIndex,c=c[c.length-1],k=c.getParent().$.rowIndex+c.$.rowSpan-1,c=new CKEDITOR.dom.element(e.$.rows[k]),h=b?h:k,g=b?g:c,c=CKEDITOR.tools.buildTableMap(e),e=c[h],h=b?c[h-1]:c[h+1],c=c[0].length,d=d.createElement("tr"),k=0;e[k]&&k<c;k++){var l;1<e[k].rowSpan&&h&&e[k]==h[k]?(l=e[k],l.rowSpan+=1):(l=(new CKEDITOR.dom.element(e[k])).clone(),l.removeAttribute("rowSpan"),l.appendBogus(),d.append(l), +l=l.$);k+=l.colSpan-1}b?d.insertBefore(g):d.insertAfter(g);return d}function e(a){if(a instanceof CKEDITOR.dom.selection){var b=a.getRanges(),c=f(a),d=c[0].getAscendant("table"),g=CKEDITOR.tools.buildTableMap(d),h=c[0].getParent().$.rowIndex,c=c[c.length-1],k=c.getParent().$.rowIndex+c.$.rowSpan-1,c=[];a.reset();for(a=h;a<=k;a++){for(var l=g[a],m=new CKEDITOR.dom.element(d.$.rows[a]),n=0;n<l.length;n++){var p=new CKEDITOR.dom.element(l[n]),t=p.getParent().$.rowIndex;1==p.$.rowSpan?p.remove():(--p.$.rowSpan, +t==a&&(t=g[a+1],t[n-1]?p.insertAfter(new CKEDITOR.dom.element(t[n-1])):(new CKEDITOR.dom.element(d.$.rows[a+1])).append(p,1)));n+=p.$.colSpan-1}c.push(m)}g=d.$.rows;b[0].moveToPosition(d,CKEDITOR.POSITION_BEFORE_START);h=new CKEDITOR.dom.element(g[k+1]||(0<h?g[h-1]:null)||d.$.parentNode);for(a=c.length;0<=a;a--)e(c[a]);return d.$.parentNode?h:(b[0].select(),null)}a instanceof CKEDITOR.dom.element&&(d=a.getAscendant("table"),1==d.$.rows.length?d.remove():a.remove());return null}function k(a){for(var b= +a.getParent().$.cells,c=0,d=0;d<b.length;d++){var e=b[d],c=c+e.colSpan;if(e==a.$)break}return c-1}function d(a,b){for(var c=b?Infinity:0,d=0;d<a.length;d++){var e=k(a[d]);if(b?e<c:e>c)c=e}return c}function l(a,b){for(var c=p(a)?a:f(a),e=c[0].getAscendant("table"),g=d(c,1),c=d(c),h=b?g:c,k=CKEDITOR.tools.buildTableMap(e),e=[],g=[],c=[],l=k.length,m=0;m<l;m++)e.push(k[m][h]),g.push(b?k[m][h-1]:k[m][h+1]);for(m=0;m<l;m++)e[m]&&(1<e[m].colSpan&&g[m]==e[m]?(k=e[m],k.colSpan+=1):(h=new CKEDITOR.dom.element(e[m]), +k=h.clone(),k.removeAttribute("colSpan"),k.appendBogus(),k[b?"insertBefore":"insertAfter"].call(k,h),c.push(k),k=k.$),m+=k.rowSpan-1);return c}function m(a){function b(a){var c,d,e;c=a.getRanges();if(1!==c.length)return a;c=c[0];if(c.collapsed||0!==c.endOffset)return a;d=c.endContainer;e=d.getName().toLowerCase();if("td"!==e&&"th"!==e)return a;for((e=d.getPrevious())||(e=d.getParent().getPrevious().getLast());e.type!==CKEDITOR.NODE_TEXT&&"br"!==e.getName().toLowerCase();)if(e=e.getLast(),!e)return a; +c.setEndAt(e,CKEDITOR.POSITION_BEFORE_END);return c.select()}CKEDITOR.env.webkit&&!a.isFake&&(a=b(a));var c=a.getRanges(),d=f(a),e=d[0],g=d[d.length-1],d=e.getAscendant("table"),h=CKEDITOR.tools.buildTableMap(d),k,l,m=[];a.reset();var n=0;for(a=h.length;n<a;n++)for(var p=0,t=h[n].length;p<t;p++)void 0===k&&h[n][p]==e.$&&(k=p),h[n][p]==g.$&&(l=p);for(n=k;n<=l;n++)for(p=0;p<h.length;p++)g=h[p],e=new CKEDITOR.dom.element(d.$.rows[p]),g=new CKEDITOR.dom.element(g[n]),g.$&&(1==g.$.colSpan?g.remove():--g.$.colSpan, +p+=g.$.rowSpan-1,e.$.cells.length||m.push(e));k=h[0].length-1>l?new CKEDITOR.dom.element(h[0][l+1]):k&&-1!==h[0][k-1].cellIndex?new CKEDITOR.dom.element(h[0][k-1]):new CKEDITOR.dom.element(d.$.parentNode);m.length==a&&(c[0].moveToPosition(d,CKEDITOR.POSITION_AFTER_END),c[0].select(),d.remove());return k}function b(a,b){var c=a.getStartElement().getAscendant({td:1,th:1},!0);if(c){var d=c.clone();d.appendBogus();b?d.insertBefore(c):d.insertAfter(c)}}function g(a){if(a instanceof CKEDITOR.dom.selection){var b= a.getRanges(),d=f(a),e=d[0]&&d[0].getAscendant("table"),h;a:{var k=0;h=d.length-1;for(var l={},m,n;m=d[k++];)CKEDITOR.dom.element.setMarker(l,m,"delete_cell",!0);for(k=0;m=d[k++];)if((n=m.getPrevious())&&!n.getCustomData("delete_cell")||(n=m.getNext())&&!n.getCustomData("delete_cell")){CKEDITOR.dom.element.clearAllMarkers(l);h=n;break a}CKEDITOR.dom.element.clearAllMarkers(l);k=d[0].getParent();(k=k.getPrevious())?h=k.getLast():(k=d[h].getParent(),h=(k=k.getNext())?k.getChild(0):null)}a.reset();for(a= d.length-1;0<=a;a--)g(d[a]);h?c(h,!0):e&&(b[0].moveToPosition(e,CKEDITOR.POSITION_BEFORE_START),b[0].select(),e.remove())}else a instanceof CKEDITOR.dom.element&&(b=a.getParent(),1==b.getChildCount()?b.remove():a.remove())}function c(a,b){var c=a.getDocument(),d=CKEDITOR.document;CKEDITOR.env.ie&&10==CKEDITOR.env.version&&(d.focus(),c.focus());c=new CKEDITOR.dom.range(c);c["moveToElementEdit"+(b?"End":"Start")](a)||(c.selectNodeContents(a),c.collapse(b?!1:!0));c.select(!0)}function a(a,b,c){a=a[b]; -if("undefined"==typeof c)return a;for(b=0;a&&b<a.length;b++){if(c.is&&a[b]==c.$)return b;if(b==c)return new CKEDITOR.dom.element(a[b])}return c.is?-1:null}function n(b,c,d){var g=f(b),e;if((c?1!=g.length:2>g.length)||(e=b.getCommonAncestor())&&e.type==CKEDITOR.NODE_ELEMENT&&e.is("table"))return!1;var h;b=g[0];e=b.getAscendant("table");var k=CKEDITOR.tools.buildTableMap(e),l=k.length,m=k[0].length,n=b.getParent().$.rowIndex,p=a(k,n,b);if(c){var r;try{var v=parseInt(b.getAttribute("rowspan"),10)||1; -h=parseInt(b.getAttribute("colspan"),10)||1;r=k["up"==c?n-v:"down"==c?n+v:n]["left"==c?p-h:"right"==c?p+h:p]}catch(w){return!1}if(!r||b.$==r)return!1;g["up"==c||"left"==c?"unshift":"push"](new CKEDITOR.dom.element(r))}c=b.getDocument();var L=n,v=r=0,O=!d&&new CKEDITOR.dom.documentFragment(c),C=0;for(c=0;c<g.length;c++){h=g[c];var S=h.getParent(),J=h.getFirst(),R=h.$.colSpan,K=h.$.rowSpan,S=S.$.rowIndex,U=a(k,S,h),C=C+R*K,v=Math.max(v,U-p+R);r=Math.max(r,S-n+K);d||(R=h,(K=R.getBogus())&&K.remove(), -R.trim(),h.getChildren().count()&&(S==L||!J||J.isBlockBoundary&&J.isBlockBoundary({br:1})||(L=O.getLast(CKEDITOR.dom.walker.whitespaces(!0)),!L||L.is&&L.is("br")||O.append("br")),h.moveChildren(O)),c?h.remove():h.setHtml(""));L=S}if(d)return r*v==C;O.moveChildren(b);b.appendBogus();v>=m?b.removeAttribute("rowSpan"):b.$.rowSpan=r;r>=l?b.removeAttribute("colSpan"):b.$.colSpan=v;d=new CKEDITOR.dom.nodeList(e.$.rows);g=d.count();for(c=g-1;0<=c;c--)e=d.getItem(c),e.$.cells.length||(e.remove(),g++);return b} -function w(b,c){var d=f(b);if(1<d.length)return!1;if(c)return!0;var d=d[0],g=d.getParent(),e=g.getAscendant("table"),h=CKEDITOR.tools.buildTableMap(e),k=g.$.rowIndex,l=a(h,k,d),m=d.$.rowSpan,n;if(1<m){n=Math.ceil(m/2);for(var m=Math.floor(m/2),g=k+n,e=new CKEDITOR.dom.element(e.$.rows[g]),h=a(h,g),p,g=d.clone(),k=0;k<h.length;k++)if(p=h[k],p.parentNode==e.$&&k>l){g.insertBefore(new CKEDITOR.dom.element(p));break}else p=null;p||e.append(g)}else for(m=n=1,e=g.clone(),e.insertAfter(g),e.append(g=d.clone()), -p=a(h,k),l=0;l<p.length;l++)p[l].rowSpan++;g.appendBogus();d.$.rowSpan=n;g.$.rowSpan=m;1==n&&d.removeAttribute("rowSpan");1==m&&g.removeAttribute("rowSpan");return g}function v(b,c){var d=f(b);if(1<d.length)return!1;if(c)return!0;var d=d[0],g=d.getParent(),e=g.getAscendant("table"),e=CKEDITOR.tools.buildTableMap(e),h=a(e,g.$.rowIndex,d),k=d.$.colSpan;if(1<k)g=Math.ceil(k/2),k=Math.floor(k/2);else{for(var k=g=1,l=[],m=0;m<e.length;m++){var n=e[m];l.push(n[h]);1<n[h].rowSpan&&(m+=n[h].rowSpan-1)}for(e= -0;e<l.length;e++)l[e].colSpan++}e=d.clone();e.insertAfter(d);e.appendBogus();d.$.colSpan=g;e.$.colSpan=k;1==g&&d.removeAttribute("colSpan");1==k&&e.removeAttribute("colSpan");return e}var p=/^(?:td|th)$/,r=CKEDITOR.tools.isArray;CKEDITOR.plugins.tabletools={requires:"table,dialog,contextmenu",init:function(a){function d(a){return CKEDITOR.tools.extend(a||{},{contextSensitive:1,refresh:function(a,b){this.setState(b.contains({td:1,th:1},1)?CKEDITOR.TRISTATE_OFF:CKEDITOR.TRISTATE_DISABLED)}})}function k(b, -c){var d=a.addCommand(b,c);a.addFeature(d)}var p=a.lang.table,r=CKEDITOR.tools.style.parse;k("cellProperties",new CKEDITOR.dialogCommand("cellProperties",d({allowedContent:"td th{width,height,border-color,background-color,white-space,vertical-align,text-align}[colspan,rowspan]",requiredContent:"table",contentTransformations:[[{element:"td",left:function(a){return a.styles.background&&r.background(a.styles.background).color},right:function(a){a.styles["background-color"]=r.background(a.styles.background).color}}, +if("undefined"==typeof c)return a;for(b=0;a&&b<a.length;b++){if(c.is&&a[b]==c.$)return b;if(b==c)return new CKEDITOR.dom.element(a[b])}return c.is?-1:null}function n(b,c,d){var e=f(b),g;if((c?1!=e.length:2>e.length)||(g=b.getCommonAncestor())&&g.type==CKEDITOR.NODE_ELEMENT&&g.is("table"))return!1;var h;b=e[0];g=b.getAscendant("table");var k=CKEDITOR.tools.buildTableMap(g),l=k.length,m=k[0].length,n=b.getParent().$.rowIndex,p=a(k,n,b);if(c){var t;try{var v=parseInt(b.getAttribute("rowspan"),10)||1; +h=parseInt(b.getAttribute("colspan"),10)||1;t=k["up"==c?n-v:"down"==c?n+v:n]["left"==c?p-h:"right"==c?p+h:p]}catch(w){return!1}if(!t||b.$==t)return!1;e["up"==c||"left"==c?"unshift":"push"](new CKEDITOR.dom.element(t))}c=b.getDocument();var L=n,v=t=0,O=!d&&new CKEDITOR.dom.documentFragment(c),D=0;for(c=0;c<e.length;c++){h=e[c];var S=h.getParent(),J=h.getFirst(),R=h.$.colSpan,K=h.$.rowSpan,S=S.$.rowIndex,U=a(k,S,h),D=D+R*K,v=Math.max(v,U-p+R);t=Math.max(t,S-n+K);d||(R=h,(K=R.getBogus())&&K.remove(), +R.trim(),h.getChildren().count()&&(S==L||!J||J.isBlockBoundary&&J.isBlockBoundary({br:1})||(L=O.getLast(CKEDITOR.dom.walker.whitespaces(!0)),!L||L.is&&L.is("br")||O.append("br")),h.moveChildren(O)),c?h.remove():h.setHtml(""));L=S}if(d)return t*v==D;O.moveChildren(b);b.appendBogus();v>=m?b.removeAttribute("rowSpan"):b.$.rowSpan=t;t>=l?b.removeAttribute("colSpan"):b.$.colSpan=v;d=new CKEDITOR.dom.nodeList(g.$.rows);e=d.count();for(c=e-1;0<=c;c--)g=d.getItem(c),g.$.cells.length||(g.remove(),e++);return b} +function w(b,c){var d=f(b);if(1<d.length)return!1;if(c)return!0;var d=d[0],e=d.getParent(),g=e.getAscendant("table"),h=CKEDITOR.tools.buildTableMap(g),k=e.$.rowIndex,l=a(h,k,d),m=d.$.rowSpan,n;if(1<m){n=Math.ceil(m/2);for(var m=Math.floor(m/2),e=k+n,g=new CKEDITOR.dom.element(g.$.rows[e]),h=a(h,e),p,e=d.clone(),k=0;k<h.length;k++)if(p=h[k],p.parentNode==g.$&&k>l){e.insertBefore(new CKEDITOR.dom.element(p));break}else p=null;p||g.append(e)}else for(m=n=1,g=e.clone(),g.insertAfter(e),g.append(e=d.clone()), +p=a(h,k),l=0;l<p.length;l++)p[l].rowSpan++;e.appendBogus();d.$.rowSpan=n;e.$.rowSpan=m;1==n&&d.removeAttribute("rowSpan");1==m&&e.removeAttribute("rowSpan");return e}function v(b,c){var d=f(b);if(1<d.length)return!1;if(c)return!0;var d=d[0],e=d.getParent(),g=e.getAscendant("table"),g=CKEDITOR.tools.buildTableMap(g),h=a(g,e.$.rowIndex,d),k=d.$.colSpan;if(1<k)e=Math.ceil(k/2),k=Math.floor(k/2);else{for(var k=e=1,l=[],m=0;m<g.length;m++){var n=g[m];l.push(n[h]);1<n[h].rowSpan&&(m+=n[h].rowSpan-1)}for(g= +0;g<l.length;g++)l[g].colSpan++}g=d.clone();g.insertAfter(d);g.appendBogus();d.$.colSpan=e;g.$.colSpan=k;1==e&&d.removeAttribute("colSpan");1==k&&g.removeAttribute("colSpan");return g}var t=/^(?:td|th)$/,p=CKEDITOR.tools.isArray;CKEDITOR.plugins.tabletools={requires:"table,dialog,contextmenu",init:function(a){function d(a){return CKEDITOR.tools.extend(a||{},{contextSensitive:1,refresh:function(a,b){this.setState(b.contains({td:1,th:1},1)?CKEDITOR.TRISTATE_OFF:CKEDITOR.TRISTATE_DISABLED)}})}function k(b, +c){var d=a.addCommand(b,c);a.addFeature(d)}var p=a.lang.table,t=CKEDITOR.tools.style.parse;k("cellProperties",new CKEDITOR.dialogCommand("cellProperties",d({allowedContent:"td th{width,height,border-color,background-color,white-space,vertical-align,text-align}[colspan,rowspan]",requiredContent:"table",contentTransformations:[[{element:"td",left:function(a){return a.styles.background&&t.background(a.styles.background).color},right:function(a){a.styles["background-color"]=t.background(a.styles.background).color}}, {element:"td",check:"td{vertical-align}",left:function(a){return a.attributes&&a.attributes.valign},right:function(a){a.styles["vertical-align"]=a.attributes.valign;delete a.attributes.valign}}],[{element:"tr",check:"td{height}",left:function(a){return a.styles&&a.styles.height},right:function(a){CKEDITOR.tools.array.forEach(a.children,function(b){b.name in{td:1,th:1}&&(b.attributes["cke-row-height"]=a.styles.height)});delete a.styles.height}}],[{element:"td",check:"td{height}",left:function(a){return(a= a.attributes)&&a["cke-row-height"]},right:function(a){a.styles.height=a.attributes["cke-row-height"];delete a.attributes["cke-row-height"]}}]]})));CKEDITOR.dialog.add("cellProperties",this.path+"dialogs/tableCell.js");k("rowDelete",d({requiredContent:"table",exec:function(a){a=a.getSelection();(a=e(a))&&c(a)}}));k("rowInsertBefore",d({requiredContent:"table",exec:function(a){a=a.getSelection();a=f(a);h(a,!0)}}));k("rowInsertAfter",d({requiredContent:"table",exec:function(a){a=a.getSelection();a=f(a); h(a)}}));k("columnDelete",d({requiredContent:"table",exec:function(a){a=a.getSelection();(a=m(a))&&c(a,!0)}}));k("columnInsertBefore",d({requiredContent:"table",exec:function(a){a=a.getSelection();a=f(a);l(a,!0)}}));k("columnInsertAfter",d({requiredContent:"table",exec:function(a){a=a.getSelection();a=f(a);l(a)}}));k("cellDelete",d({requiredContent:"table",exec:function(a){a=a.getSelection();g(a)}}));k("cellMerge",d({allowedContent:"td[colspan,rowspan]",requiredContent:"td[colspan,rowspan]",exec:function(a, @@ -1101,14 +1101,14 @@ tablerow_insertAfter:CKEDITOR.TRISTATE_OFF,tablerow_delete:CKEDITOR.TRISTATE_OFF tablecolumn_insertAfter:CKEDITOR.TRISTATE_OFF,tablecolumn_delete:CKEDITOR.TRISTATE_OFF}}},tablecolumn_insertBefore:{label:p.column.insertBefore,group:"tablecolumn",command:"columnInsertBefore",order:5},tablecolumn_insertAfter:{label:p.column.insertAfter,group:"tablecolumn",command:"columnInsertAfter",order:10},tablecolumn_delete:{label:p.column.deleteColumn,group:"tablecolumn",command:"columnDelete",order:15}});a.contextMenu&&a.contextMenu.addListener(function(a,b,c){return(a=c.contains({td:1,th:1}, 1))&&!a.isReadOnly()?{tablecell:CKEDITOR.TRISTATE_OFF,tablerow:CKEDITOR.TRISTATE_OFF,tablecolumn:CKEDITOR.TRISTATE_OFF}:null})},getCellColIndex:k,insertRow:h,insertColumn:l,getSelectedCells:f};CKEDITOR.plugins.add("tabletools",CKEDITOR.plugins.tabletools)}(),CKEDITOR.tools.buildTableMap=function(f,h,e,k,d){f=f.$.rows;e=e||0;k="number"===typeof k?k:f.length-1;d="number"===typeof d?d:-1;var l=-1,m=[];for(h=h||0;h<=k;h++){l++;!m[l]&&(m[l]=[]);for(var b=-1,g=e;g<=(-1===d?f[h].cells.length-1:d);g++){var c= f[h].cells[g];if(!c)break;for(b++;m[l][b];)b++;for(var a=isNaN(c.colSpan)?1:c.colSpan,c=isNaN(c.rowSpan)?1:c.rowSpan,n=0;n<c&&!(h+n>k);n++){m[l+n]||(m[l+n]=[]);for(var w=0;w<a;w++)m[l+n][b+w]=f[h].cells[g]}b+=a-1;if(-1!==d&&b>=d)break}}return m},function(){function f(b){return CKEDITOR.env.ie?b.$.clientWidth:parseInt(b.getComputedStyle("width"),10)}function h(b,c){var a=b.getComputedStyle("border-"+c+"-width"),d={thin:"0px",medium:"1px",thick:"2px"};0>a.indexOf("px")&&(a=a in d&&"none"!=b.getComputedStyle("border-style")? -d[a]:0);return parseInt(a,10)}function e(b){var c=[],a={},d="rtl"==b.getComputedStyle("direction");CKEDITOR.tools.array.forEach(b.$.rows,function(e,f){var k=-1,l=0,m=null;e?(l=new CKEDITOR.dom.element(e),m={height:l.$.offsetHeight,position:l.getDocumentPosition()}):m=void 0;for(var l=m.height,m=m.position,u=0,x=e.cells.length;u<x;u++){var A=new CKEDITOR.dom.element(e.cells[u]),D=e.cells[u+1]&&new CKEDITOR.dom.element(e.cells[u+1]),k=k+(A.$.colSpan||1),t,B,y=A.getDocumentPosition().x;d?B=y+h(A,"left"): -t=y+A.$.offsetWidth-h(A,"right");D?(y=D.getDocumentPosition().x,d?t=y+D.$.offsetWidth-h(D,"right"):B=y+h(D,"left")):(y=b.getDocumentPosition().x,d?t=y:B=y+b.$.offsetWidth);A=Math.max(B-t,3);A={table:b,index:k,x:t,y:m.y,width:A,height:l,rtl:d};a[k]=a[k]||[];a[k].push(A);A.alignedPillars=a[k];c.push(A)}});return c}function k(b){(b.data||b).preventDefault()}function d(d){function c(){u=0;q.setOpacity(0);A&&a();var b=p.table;setTimeout(function(){b.removeCustomData("_cke_table_pillars")},0);r.removeListener("dragstart", -k)}function a(){for(var a=p.rtl,b=a?B.length:t.length,c=0,e=0;e<b;e++){var k=t[e],l=B[e],n=p.table;CKEDITOR.tools.setTimeout(function(e,f,h,k,l,p){e&&e.setStyle("width",m(Math.max(f+p,1)));h&&h.setStyle("width",m(Math.max(k-p,1)));l&&n.setStyle("width",m(l+p*(a?-1:1)));++c==b&&d.fire("saveSnapshot")},0,this,[k,k&&f(k),l,l&&f(l),(!k||!l)&&f(n)+h(n,"left")+h(n,"right"),A])}}function e(a){k(a);d.fire("saveSnapshot");a=p.index;for(var b=CKEDITOR.tools.buildTableMap(p.table),c=[],h=[],m=Number.MAX_VALUE, -n=m,D=p.rtl,C=0,S=b.length;C<S;C++){var J=b[C],R=J[a+(D?1:0)],J=J[a+(D?0:1)],R=R&&new CKEDITOR.dom.element(R),J=J&&new CKEDITOR.dom.element(J);R&&J&&R.equals(J)||(R&&(m=Math.min(m,f(R))),J&&(n=Math.min(n,f(J))),c.push(R),h.push(J))}t=c;B=h;y=p.x-m;z=p.x+n;q.setOpacity(.5);x=parseInt(q.getStyle("left"),10);A=0;u=1;q.on("mousemove",v);r.on("dragstart",k);r.on("mouseup",l,this)}function l(a){a.removeListener();c()}function v(a){D(a.data.getPageOffset().x)}var p,r,q,u,x,A,D,t,B,y,z;r=d.document;q=CKEDITOR.dom.element.createFromHtml('\x3cdiv data-cke-temp\x3d1 contenteditable\x3dfalse unselectable\x3don style\x3d"position:absolute;cursor:col-resize;filter:alpha(opacity\x3d0);opacity:0;padding:0;background-color:#004;background-image:none;border:0px none;z-index:10"\x3e\x3c/div\x3e', -r);d.on("destroy",function(){q.remove()});b||r.getDocumentElement().append(q);this.attachTo=function(a){var c,d,g;u||(b&&(r.getBody().append(q),A=0),p=a,c=p.alignedPillars[0],d=p.alignedPillars[p.alignedPillars.length-1],g=c.y,c=d.height+d.y-c.y,q.setStyles({width:m(a.width),height:m(c),left:m(a.x),top:m(g)}),b&&q.setOpacity(.25),q.on("mousedown",e,this),r.getBody().setStyle("cursor","col-resize"),q.show())};D=this.move=function(a,c){if(!p)return 0;if(!(u||a>=p.x&&a<=p.x+p.width&&c>=p.y&&c<=p.y+p.height))return p= -null,u=A=0,r.removeListener("mouseup",l),q.removeListener("mousedown",e),q.removeListener("mousemove",v),r.getBody().setStyle("cursor","auto"),b?q.remove():q.hide(),0;var d=a-Math.round(q.$.offsetWidth/2);if(u){if(d==y||d==z)return 1;d=Math.max(d,y);d=Math.min(d,z);A=d-x}q.setStyle("left",m(d));return 1}}function l(b){var c=b.data.getTarget();if("mouseout"==b.name){if(!c.is("table"))return;for(var a=new CKEDITOR.dom.element(b.data.$.relatedTarget||b.data.$.toElement);a&&a.$&&!a.equals(c)&&!a.is("body");)a= +d[a]:0);return parseInt(a,10)}function e(b){var c=[],a={},d="rtl"==b.getComputedStyle("direction");CKEDITOR.tools.array.forEach(b.$.rows,function(e,f){var k=-1,l=0,m=null;e?(l=new CKEDITOR.dom.element(e),m={height:l.$.offsetHeight,position:l.getDocumentPosition()}):m=void 0;for(var l=m.height,m=m.position,A=0,r=e.cells.length;A<r;A++){var C=new CKEDITOR.dom.element(e.cells[A]),B=e.cells[A+1]&&new CKEDITOR.dom.element(e.cells[A+1]),k=k+(C.$.colSpan||1),u,y,x=C.getDocumentPosition().x;d?y=x+h(C,"left"): +u=x+C.$.offsetWidth-h(C,"right");B?(x=B.getDocumentPosition().x,d?u=x+B.$.offsetWidth-h(B,"right"):y=x+h(B,"left")):(x=b.getDocumentPosition().x,d?u=x:y=x+b.$.offsetWidth);C=Math.max(y-u,3);C={table:b,index:k,x:u,y:m.y,width:C,height:l,rtl:d};a[k]=a[k]||[];a[k].push(C);C.alignedPillars=a[k];c.push(C)}});return c}function k(b){(b.data||b).preventDefault()}function d(d){function c(){A=0;q.setOpacity(0);C&&a();var b=t.table;setTimeout(function(){b.removeCustomData("_cke_table_pillars")},0);p.removeListener("dragstart", +k)}function a(){for(var a=t.rtl,b=a?y.length:u.length,c=0,e=0;e<b;e++){var k=u[e],l=y[e],n=t.table;CKEDITOR.tools.setTimeout(function(e,f,h,k,l,p){e&&e.setStyle("width",m(Math.max(f+p,1)));h&&h.setStyle("width",m(Math.max(k-p,1)));l&&n.setStyle("width",m(l+p*(a?-1:1)));++c==b&&d.fire("saveSnapshot")},0,this,[k,k&&f(k),l,l&&f(l),(!k||!l)&&f(n)+h(n,"left")+h(n,"right"),C])}}function e(a){k(a);d.fire("saveSnapshot");a=t.index;for(var b=CKEDITOR.tools.buildTableMap(t.table),c=[],h=[],m=Number.MAX_VALUE, +n=m,B=t.rtl,D=0,S=b.length;D<S;D++){var J=b[D],R=J[a+(B?1:0)],J=J[a+(B?0:1)],R=R&&new CKEDITOR.dom.element(R),J=J&&new CKEDITOR.dom.element(J);R&&J&&R.equals(J)||(R&&(m=Math.min(m,f(R))),J&&(n=Math.min(n,f(J))),c.push(R),h.push(J))}u=c;y=h;x=t.x-m;z=t.x+n;q.setOpacity(.5);r=parseInt(q.getStyle("left"),10);C=0;A=1;q.on("mousemove",v);p.on("dragstart",k);p.on("mouseup",l,this)}function l(a){a.removeListener();c()}function v(a){B(a.data.getPageOffset().x)}var t,p,q,A,r,C,B,u,y,x,z;p=d.document;q=CKEDITOR.dom.element.createFromHtml('\x3cdiv data-cke-temp\x3d1 contenteditable\x3dfalse unselectable\x3don style\x3d"position:absolute;cursor:col-resize;filter:alpha(opacity\x3d0);opacity:0;padding:0;background-color:#004;background-image:none;border:0px none;z-index:10"\x3e\x3c/div\x3e', +p);d.on("destroy",function(){q.remove()});b||p.getDocumentElement().append(q);this.attachTo=function(a){var c,d,f;A||(b&&(p.getBody().append(q),C=0),t=a,c=t.alignedPillars[0],d=t.alignedPillars[t.alignedPillars.length-1],f=c.y,c=d.height+d.y-c.y,q.setStyles({width:m(a.width),height:m(c),left:m(a.x),top:m(f)}),b&&q.setOpacity(.25),q.on("mousedown",e,this),p.getBody().setStyle("cursor","col-resize"),q.show())};B=this.move=function(a,c){if(!t)return 0;if(!(A||a>=t.x&&a<=t.x+t.width&&c>=t.y&&c<=t.y+t.height))return t= +null,A=C=0,p.removeListener("mouseup",l),q.removeListener("mousedown",e),q.removeListener("mousemove",v),p.getBody().setStyle("cursor","auto"),b?q.remove():q.hide(),0;var d=a-Math.round(q.$.offsetWidth/2);if(A){if(d==x||d==z)return 1;d=Math.max(d,x);d=Math.min(d,z);C=d-r}q.setStyle("left",m(d));return 1}}function l(b){var c=b.data.getTarget();if("mouseout"==b.name){if(!c.is("table"))return;for(var a=new CKEDITOR.dom.element(b.data.$.relatedTarget||b.data.$.toElement);a&&a.$&&!a.equals(c)&&!a.is("body");)a= a.getParent();if(!a||a.equals(c))return}c.getAscendant("table",1).removeCustomData("_cke_table_pillars");b.removeListener()}var m=CKEDITOR.tools.cssLength,b=CKEDITOR.env.ie&&(CKEDITOR.env.ie7Compat||CKEDITOR.env.quirks);CKEDITOR.plugins.add("tableresize",{requires:"tabletools",init:function(b){b.on("contentDom",function(){var c,a=b.editable();a.attachListener(a.isInline()?a:b.document,"mousemove",function(a){a=a.data;var f=a.getTarget();if(f.type==CKEDITOR.NODE_ELEMENT){var h=a.getPageOffset().x, -m=a.getPageOffset().y;if(c&&c.move(h,m))k(a);else if(f.is("table")||f.getAscendant({thead:1,tbody:1,tfoot:1},1))if(a=f.getAscendant("table",1),b.editable().contains(a)){(f=a.getCustomData("_cke_table_pillars"))||(a.setCustomData("_cke_table_pillars",f=e(a)),a.on("mouseout",l),a.on("mousedown",l));a:{a=f;for(var f=0,r=a.length;f<r;f++){var q=a[f];if(h>=q.x&&h<=q.x+q.width&&m>=q.y&&m<=q.y+q.height){h=q;break a}}h=null}h&&(!c&&(c=new d(b)),c.attachTo(h))}}})})}})}(),"use strict",function(){var f=[CKEDITOR.CTRL+ +m=a.getPageOffset().y;if(c&&c.move(h,m))k(a);else if(f.is("table")||f.getAscendant({thead:1,tbody:1,tfoot:1},1))if(a=f.getAscendant("table",1),b.editable().contains(a)){(f=a.getCustomData("_cke_table_pillars"))||(a.setCustomData("_cke_table_pillars",f=e(a)),a.on("mouseout",l),a.on("mousedown",l));a:{a=f;for(var f=0,p=a.length;f<p;f++){var q=a[f];if(h>=q.x&&h<=q.x+q.width&&m>=q.y&&m<=q.y+q.height){h=q;break a}}h=null}h&&(!c&&(c=new d(b)),c.attachTo(h))}}})})}})}(),"use strict",function(){var f=[CKEDITOR.CTRL+ 90,CKEDITOR.CTRL+89,CKEDITOR.CTRL+CKEDITOR.SHIFT+90],h={8:1,46:1};CKEDITOR.plugins.add("undo",{init:function(b){function d(b){a.enabled&&!1!==b.data.command.canUndo&&a.save()}function c(){a.enabled=b.readOnly?!1:"wysiwyg"==b.mode;a.onChange()}var a=b.undoManager=new e(b),h=a.editingHandler=new l(a),k=b.addCommand("undo",{exec:function(){a.undo()&&(b.selectionChange(),this.fire("afterUndo"))},startDisabled:!0,canUndo:!1}),m=b.addCommand("redo",{exec:function(){a.redo()&&(b.selectionChange(),this.fire("afterRedo"))}, startDisabled:!0,canUndo:!1});b.setKeystroke([[f[0],"undo"],[f[1],"redo"],[f[2],"redo"]]);a.onChange=function(){k.setState(a.undoable()?CKEDITOR.TRISTATE_OFF:CKEDITOR.TRISTATE_DISABLED);m.setState(a.redoable()?CKEDITOR.TRISTATE_OFF:CKEDITOR.TRISTATE_DISABLED)};b.on("beforeCommandExec",d);b.on("afterCommandExec",d);b.on("saveSnapshot",function(b){a.save(b.data&&b.data.contentOnly)});b.on("contentDom",h.attachListeners,h);b.on("instanceReady",function(){b.fire("saveSnapshot")});b.on("beforeModeUnload", function(){"wysiwyg"==b.mode&&a.save(!0)});b.on("mode",c);b.on("readOnly",c);b.ui.addButton&&(b.ui.addButton("Undo",{label:b.lang.undo.undo,command:"undo",toolbar:"undo,10"}),b.ui.addButton("Redo",{label:b.lang.undo.redo,command:"redo",toolbar:"undo,20"}));b.resetUndo=function(){a.reset();b.fire("saveSnapshot")};b.on("updateSnapshot",function(){a.currentImage&&a.update()});b.on("lockSnapshot",function(b){b=b.data;a.lock(b&&b.dontUpdate,b&&b.forceUpdate)});b.on("unlockSnapshot",a.unlock,a)}});CKEDITOR.plugins.undo= diff --git a/web/core/assets/vendor/ckeditor/lang/af.js b/web/core/assets/vendor/ckeditor/lang/af.js index 0f199f922451d7361faaf6af4a72edc2e367f965..a856816d5f7a2d1c587eb428c19c3871e3edc712 100644 --- a/web/core/assets/vendor/ckeditor/lang/af.js +++ b/web/core/assets/vendor/ckeditor/lang/af.js @@ -2,4 +2,4 @@ Copyright (c) 2003-2018, CKSource - Frederico Knabben. All rights reserved. For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license */ -CKEDITOR.lang['af']={"widget":{"move":"Klik en trek on te beweeg","label":"%1 widget"},"undo":{"redo":"Oordoen","undo":"Ontdoen"},"toolbar":{"toolbarCollapse":"Verklein werkbalk","toolbarExpand":"Vergroot werkbalk","toolbarGroups":{"document":"Dokument","clipboard":"Knipbord/Undo","editing":"Verander","forms":"Vorms","basicstyles":"Eenvoudige Styl","paragraph":"Paragraaf","links":"Skakels","insert":"Toevoeg","styles":"Style","colors":"Kleure","tools":"Gereedskap"},"toolbars":"Werkbalke"},"table":{"border":"Randbreedte","caption":"Naam","cell":{"menu":"Sel","insertBefore":"Voeg sel in voor","insertAfter":"Voeg sel in na","deleteCell":"Verwyder sel","merge":"Voeg selle saam","mergeRight":"Voeg saam na regs","mergeDown":"Voeg saam ondertoe","splitHorizontal":"Splits sel horisontaal","splitVertical":"Splits sel vertikaal","title":"Sel eienskappe","cellType":"Sel tipe","rowSpan":"Omspan rye","colSpan":"Omspan kolomme","wordWrap":"Woord terugloop","hAlign":"Horisontale oplyning","vAlign":"Vertikale oplyning","alignBaseline":"Basislyn","bgColor":"Agtergrondkleur","borderColor":"Randkleur","data":"Inhoud","header":"Opskrif","yes":"Ja","no":"Nee","invalidWidth":"Selbreedte moet 'n getal wees.","invalidHeight":"Selhoogte moet 'n getal wees.","invalidRowSpan":"Omspan rye moet 'n heelgetal wees.","invalidColSpan":"Omspan kolomme moet 'n heelgetal wees.","chooseColor":"Kies"},"cellPad":"Sel-spasie","cellSpace":"Sel-afstand","column":{"menu":"Kolom","insertBefore":"Voeg kolom in voor","insertAfter":"Voeg kolom in na","deleteColumn":"Verwyder kolom"},"columns":"Kolomme","deleteTable":"Verwyder tabel","headers":"Opskrifte","headersBoth":"Beide ","headersColumn":"Eerste kolom","headersNone":"Geen","headersRow":"Eerste ry","invalidBorder":"Randbreedte moet 'n getal wees.","invalidCellPadding":"Sel-spasie moet 'n getal wees.","invalidCellSpacing":"Sel-afstand moet 'n getal wees.","invalidCols":"Aantal kolomme moet 'n getal groter as 0 wees.","invalidHeight":"Tabelhoogte moet 'n getal wees.","invalidRows":"Aantal rye moet 'n getal groter as 0 wees.","invalidWidth":"Tabelbreedte moet 'n getal wees.","menu":"Tabel eienskappe","row":{"menu":"Ry","insertBefore":"Voeg ry in voor","insertAfter":"Voeg ry in na","deleteRow":"Verwyder ry"},"rows":"Rye","summary":"Opsomming","title":"Tabel eienskappe","toolbar":"Tabel","widthPc":"persent","widthPx":"piksels","widthUnit":"breedte-eenheid"},"stylescombo":{"label":"Styl","panelTitle":"Vormaat style","panelTitle1":"Blok style","panelTitle2":"Inlyn style","panelTitle3":"Objek style"},"specialchar":{"options":"Spesiale karakter-opsies","title":"Kies spesiale karakter","toolbar":"Voeg spesiaale karakter in"},"sourcedialog":{"toolbar":"Bron","title":"Bron"},"sourcearea":{"toolbar":"Bron"},"showblocks":{"toolbar":"Toon blokke"},"removeformat":{"toolbar":"Verwyder opmaak"},"pastetext":{"button":"Plak as eenvoudige teks","pasteNotification":"Press %1 to paste. Your browser doesn‘t support pasting with the toolbar button or context menu option.","title":"Plak as eenvoudige teks"},"pastefromword":{"confirmCleanup":"Die teks wat u wil plak lyk asof dit uit Word gekopiëer is. Wil u dit eers skoonmaak voordat dit geplak word?","error":"Die geplakte teks kon nie skoongemaak word nie, weens 'n interne fout","title":"Plak vanuit Word","toolbar":"Plak vanuit Word"},"notification":{"closed":"Notification closed."},"maximize":{"maximize":"Maksimaliseer","minimize":"Minimaliseer"},"magicline":{"title":"Voeg paragraaf hier in"},"list":{"bulletedlist":"Ongenommerde lys","numberedlist":"Genommerde lys"},"language":{"button":"Set language","remove":"Remove language"},"indent":{"indent":"Vergroot inspring","outdent":"Verklein inspring"},"image2":{"alt":"Alternatiewe teks","btnUpload":"Stuur na bediener","captioned":"Captioned image","captionPlaceholder":"Caption","infoTab":"Afbeelding informasie","lockRatio":"Vaste proporsie","menu":"Afbeelding eienskappe","pathName":"image","pathNameCaption":"caption","resetSize":"Herstel grootte","resizer":"Click and drag to resize","title":"Afbeelding eienskappe","uploadTab":"Oplaai","urlMissing":"Die URL na die afbeelding ontbreek.","altMissing":"Alternative text is missing."},"horizontalrule":{"toolbar":"Horisontale lyn invoeg"},"format":{"label":"Opmaak","panelTitle":"Opmaak","tag_address":"Adres","tag_div":"Normaal (DIV)","tag_h1":"Opskrif 1","tag_h2":"Opskrif 2","tag_h3":"Opskrif 3","tag_h4":"Opskrif 4","tag_h5":"Opskrif 5","tag_h6":"Opskrif 6","tag_p":"Normaal","tag_pre":"Opgemaak"},"filetools":{"loadError":"Error occurred during file read.","networkError":"Network error occurred during file upload.","httpError404":"HTTP error occurred during file upload (404: File not found).","httpError403":"HTTP error occurred during file upload (403: Forbidden).","httpError":"HTTP error occurred during file upload (error status: %1).","noUrlError":"Upload URL is not defined.","responseError":"Incorrect server response."},"elementspath":{"eleLabel":"Elemente-pad","eleTitle":"%1 element"},"contextmenu":{"options":"Konteks Spyskaart-opsies"},"clipboard":{"copy":"Kopiëer","copyError":"U blaaier se sekuriteitsinstelling belet die kopiëringsaksie. Gebruik die sleutelbordkombinasie (Ctrl/Cmd+C).","cut":"Knip","cutError":"U blaaier se sekuriteitsinstelling belet die outomatiese knip-aksie. Gebruik die sleutelbordkombinasie (Ctrl/Cmd+X).","paste":"Plak","pasteNotification":"Press %1 to paste. Your browser doesn‘t support pasting with the toolbar button or context menu option.","pasteArea":"Plak-area","pasteMsg":"Paste your content inside the area below and press OK.","title":"Byvoeg"},"button":{"selectedLabel":"%1 uitgekies"},"blockquote":{"toolbar":"Sitaatblok"},"basicstyles":{"bold":"Vet","italic":"Skuins","strike":"Deurgestreep","subscript":"Onderskrif","superscript":"Bo-skrif","underline":"Onderstreep"},"about":{"copy":"Kopiereg © $1. Alle regte voorbehou.","dlgTitle":"Meer oor CKEditor 4","moreInfo":"Vir lisensie-informasie, besoek asb. ons webwerf:"},"editor":"Woordverwerker","editorPanel":"Woordverwerkerpaneel","common":{"editorHelp":"Druk op ALT 0 vir hulp","browseServer":"Blaai op bediener","url":"URL","protocol":"Protokol","upload":"Oplaai","uploadSubmit":"Stuur aan die bediener","image":"Beeld","flash":"Flash","form":"Vorm","checkbox":"Merkhokkie","radio":"Radioknoppie","textField":"Teksveld","textarea":"Teksarea","hiddenField":"Versteekteveld","button":"Knop","select":"Keuseveld","imageButton":"Beeldknop","notSet":"<geen instelling>","id":"Id","name":"Naam","langDir":"Skryfrigting","langDirLtr":"Links na regs (LTR)","langDirRtl":"Regs na links (RTL)","langCode":"Taalkode","longDescr":"Lang beskrywing URL","cssClass":"CSS klasse","advisoryTitle":"Aanbevole titel","cssStyle":"Styl","ok":"OK","cancel":"Kanselleer","close":"Sluit","preview":"Voorbeeld","resize":"Skalierung","generalTab":"Algemeen","advancedTab":"Gevorderd","validateNumberFailed":"Hierdie waarde is nie 'n nommer nie.","confirmNewPage":"Alle wysiginge sal verlore gaan. Is jy seker dat jy 'n nuwe bladsy wil laai?","confirmCancel":"Sommige opsies is gewysig. Is jy seker dat jy hierdie dialoogvenster wil sluit?","options":"Opsies","target":"Teiken","targetNew":"Nuwe venster (_blank)","targetTop":"Boonste venster (_top)","targetSelf":"Selfde venster (_self)","targetParent":"Oorspronklike venster (_parent)","langDirLTR":"Links na Regs (LTR)","langDirRTL":"Regs na Links (RTL)","styles":"Styl","cssClasses":"CSS klasse","width":"Breedte","height":"Hoogte","align":"Orienteerung","left":"Links","right":"Regs","center":"Middel","justify":"Eweredig","alignLeft":"Links oplyn","alignRight":"Regs oplyn","alignCenter":"Align Center","alignTop":"Bo","alignMiddle":"Middel","alignBottom":"Onder","alignNone":"Geen","invalidValue":"Ongeldige waarde","invalidHeight":"Hoogte moet 'n getal wees","invalidWidth":"Breedte moet 'n getal wees.","invalidLength":"Value specified for the \"%1\" field must be a positive number with or without a valid measurement unit (%2).","invalidCssLength":"Die waarde vir die \"%1\" veld moet 'n posetiewe getal wees met of sonder 'n geldige CSS eenheid (px, %, in, cm, mm, em, ex, pt, of pc).","invalidHtmlLength":"Die waarde vir die \"%1\" veld moet 'n posetiewe getal wees met of sonder 'n geldige HTML eenheid (px of %).","invalidInlineStyle":"Ongeldige CSS. Formaat is een of meer sleutel-wert paare, \"naam : wert\" met kommapunte gesky.","cssLengthTooltip":"Voeg 'n getal wert in pixel in, of 'n waarde met geldige CSS eenheid (px, %, in, cm, mm, em, ex, pt, of pc).","unavailable":"%1<span class=\"cke_accessibility\">, nie beskikbaar nie</span>","keyboard":{"8":"Backspace","13":"Enter","16":"Skuif","17":"Ctrl","18":"Alt","32":"Spasie","35":"Einde","36":"Tuis","46":"Verwyder","112":"F1","113":"F2","114":"F3","115":"F4","116":"F5","117":"F6","118":"F7","119":"F8","120":"F9","121":"F10","122":"F11","123":"F12","124":"F13","125":"F14","126":"F15","127":"F16","128":"F17","129":"F18","130":"F19","131":"F20","132":"F21","133":"F22","134":"F23","135":"F24","224":"Bevel"},"keyboardShortcut":"Sleutel kombenasie","optionDefault":"Default"}}; \ No newline at end of file +CKEDITOR.lang['af']={"widget":{"move":"Klik en trek on te beweeg","label":"%1 widget"},"undo":{"redo":"Oordoen","undo":"Ontdoen"},"toolbar":{"toolbarCollapse":"Verklein werkbalk","toolbarExpand":"Vergroot werkbalk","toolbarGroups":{"document":"Dokument","clipboard":"Knipbord/Undo","editing":"Verander","forms":"Vorms","basicstyles":"Eenvoudige Styl","paragraph":"Paragraaf","links":"Skakels","insert":"Toevoeg","styles":"Style","colors":"Kleure","tools":"Gereedskap"},"toolbars":"Werkbalke"},"table":{"border":"Randbreedte","caption":"Naam","cell":{"menu":"Sel","insertBefore":"Voeg sel in voor","insertAfter":"Voeg sel in na","deleteCell":"Verwyder sel","merge":"Voeg selle saam","mergeRight":"Voeg saam na regs","mergeDown":"Voeg saam ondertoe","splitHorizontal":"Splits sel horisontaal","splitVertical":"Splits sel vertikaal","title":"Sel eienskappe","cellType":"Sel tipe","rowSpan":"Omspan rye","colSpan":"Omspan kolomme","wordWrap":"Woord terugloop","hAlign":"Horisontale oplyning","vAlign":"Vertikale oplyning","alignBaseline":"Basislyn","bgColor":"Agtergrondkleur","borderColor":"Randkleur","data":"Inhoud","header":"Opskrif","yes":"Ja","no":"Nee","invalidWidth":"Selbreedte moet 'n getal wees.","invalidHeight":"Selhoogte moet 'n getal wees.","invalidRowSpan":"Omspan rye moet 'n heelgetal wees.","invalidColSpan":"Omspan kolomme moet 'n heelgetal wees.","chooseColor":"Kies"},"cellPad":"Sel-spasie","cellSpace":"Sel-afstand","column":{"menu":"Kolom","insertBefore":"Voeg kolom in voor","insertAfter":"Voeg kolom in na","deleteColumn":"Verwyder kolom"},"columns":"Kolomme","deleteTable":"Verwyder tabel","headers":"Opskrifte","headersBoth":"Beide ","headersColumn":"Eerste kolom","headersNone":"Geen","headersRow":"Eerste ry","invalidBorder":"Randbreedte moet 'n getal wees.","invalidCellPadding":"Sel-spasie moet 'n getal wees.","invalidCellSpacing":"Sel-afstand moet 'n getal wees.","invalidCols":"Aantal kolomme moet 'n getal groter as 0 wees.","invalidHeight":"Tabelhoogte moet 'n getal wees.","invalidRows":"Aantal rye moet 'n getal groter as 0 wees.","invalidWidth":"Tabelbreedte moet 'n getal wees.","menu":"Tabel eienskappe","row":{"menu":"Ry","insertBefore":"Voeg ry in voor","insertAfter":"Voeg ry in na","deleteRow":"Verwyder ry"},"rows":"Rye","summary":"Opsomming","title":"Tabel eienskappe","toolbar":"Tabel","widthPc":"persent","widthPx":"piksels","widthUnit":"breedte-eenheid"},"stylescombo":{"label":"Styl","panelTitle":"Vormaat style","panelTitle1":"Blok style","panelTitle2":"Inlyn style","panelTitle3":"Objek style"},"specialchar":{"options":"Spesiale karakter-opsies","title":"Kies spesiale karakter","toolbar":"Voeg spesiaale karakter in"},"sourcedialog":{"toolbar":"Bron","title":"Bron"},"sourcearea":{"toolbar":"Bron"},"showblocks":{"toolbar":"Toon blokke"},"removeformat":{"toolbar":"Verwyder opmaak"},"pastetext":{"button":"Voeg by as eenvoudige teks","pasteNotification":"Druk %1 om by te voeg. Jou leser ondersteun nie byvoeg deur die toolbar knoppie of die konteks kieslys nie","title":"Voeg by as eenvoudige teks"},"pastefromword":{"confirmCleanup":"Die teks wat u wil byvoeg lyk asof dit uit Word gekopiëer is. Wil u dit eers skoonmaak voordat dit bygevoeg word?","error":"Die bygevoegte teks kon nie skoongemaak word nie, weens 'n interne fout","title":"Uit Word byvoeg","toolbar":"Uit Word byvoeg"},"notification":{"closed":"Notification closed."},"maximize":{"maximize":"Maksimaliseer","minimize":"Minimaliseer"},"magicline":{"title":"Voeg paragraaf hier in"},"list":{"bulletedlist":"Ongenommerde lys","numberedlist":"Genommerde lys"},"language":{"button":"Set language","remove":"Remove language"},"indent":{"indent":"Vergroot inspring","outdent":"Verklein inspring"},"image2":{"alt":"Alternatiewe teks","btnUpload":"Stuur na bediener","captioned":"Captioned image","captionPlaceholder":"Caption","infoTab":"Afbeelding informasie","lockRatio":"Vaste proporsie","menu":"Afbeelding eienskappe","pathName":"image","pathNameCaption":"caption","resetSize":"Herstel grootte","resizer":"Click and drag to resize","title":"Afbeelding eienskappe","uploadTab":"Oplaai","urlMissing":"Die URL na die afbeelding ontbreek.","altMissing":"Alternative text is missing."},"horizontalrule":{"toolbar":"Horisontale lyn invoeg"},"format":{"label":"Opmaak","panelTitle":"Opmaak","tag_address":"Adres","tag_div":"Normaal (DIV)","tag_h1":"Opskrif 1","tag_h2":"Opskrif 2","tag_h3":"Opskrif 3","tag_h4":"Opskrif 4","tag_h5":"Opskrif 5","tag_h6":"Opskrif 6","tag_p":"Normaal","tag_pre":"Opgemaak"},"filetools":{"loadError":"Error occurred during file read.","networkError":"Network error occurred during file upload.","httpError404":"HTTP error occurred during file upload (404: File not found).","httpError403":"HTTP error occurred during file upload (403: Forbidden).","httpError":"HTTP error occurred during file upload (error status: %1).","noUrlError":"Upload URL is not defined.","responseError":"Incorrect server response."},"elementspath":{"eleLabel":"Elemente-pad","eleTitle":"%1 element"},"contextmenu":{"options":"Konteks Spyskaart-opsies"},"clipboard":{"copy":"Kopiëer","copyError":"U leser se sekuriteitsinstelling belet die kopiëringsaksie. Gebruik die sleutelbordkombinasie (Ctrl/Cmd+C).","cut":"Uitsnei","cutError":"U leser se sekuriteitsinstelling belet die outomatiese uitsnei-aksie. Gebruik die sleutelbordkombinasie (Ctrl/Cmd+X).","paste":"Byvoeg","pasteNotification":"Druk %1 om by te voeg. You leser ondersteun nie die toolbar knoppie of inoud kieslysie opsie nie. ","pasteArea":"Area byvoeg","pasteMsg":"Voeg jou inhoud in die gebied onder by en druk OK","title":"Byvoeg"},"button":{"selectedLabel":"%1 uitgekies"},"blockquote":{"toolbar":"Sitaatblok"},"basicstyles":{"bold":"Vet","italic":"Skuins","strike":"Deurgestreep","subscript":"Onderskrif","superscript":"Bo-skrif","underline":"Onderstreep"},"about":{"copy":"Kopiereg © $1. Alle regte voorbehou.","dlgTitle":"Meer oor CKEditor 4","moreInfo":"Vir lisensie-informasie, besoek asb. ons webwerf:"},"editor":"Woordverwerker","editorPanel":"Woordverwerkerpaneel","common":{"editorHelp":"Druk op ALT 0 vir hulp","browseServer":"Blaai op bediener","url":"URL","protocol":"Protokol","upload":"Oplaai","uploadSubmit":"Stuur aan die bediener","image":"Beeld","flash":"Flash","form":"Vorm","checkbox":"Merkhokkie","radio":"Radioknoppie","textField":"Teksveld","textarea":"Teksarea","hiddenField":"Versteekteveld","button":"Knop","select":"Keuseveld","imageButton":"Beeldknop","notSet":"<geen instelling>","id":"Id","name":"Naam","langDir":"Skryfrigting","langDirLtr":"Links na regs (LTR)","langDirRtl":"Regs na links (RTL)","langCode":"Taalkode","longDescr":"Lang beskrywing URL","cssClass":"CSS klasse","advisoryTitle":"Aanbevole titel","cssStyle":"Styl","ok":"OK","cancel":"Kanselleer","close":"Sluit","preview":"Voorbeeld","resize":"Skalierung","generalTab":"Algemeen","advancedTab":"Gevorderd","validateNumberFailed":"Hierdie waarde is nie 'n nommer nie.","confirmNewPage":"Alle wysiginge sal verlore gaan. Is jy seker dat jy 'n nuwe bladsy wil laai?","confirmCancel":"Sommige opsies is gewysig. Is jy seker dat jy hierdie dialoogvenster wil sluit?","options":"Opsies","target":"Teiken","targetNew":"Nuwe venster (_blank)","targetTop":"Boonste venster (_top)","targetSelf":"Selfde venster (_self)","targetParent":"Oorspronklike venster (_parent)","langDirLTR":"Links na Regs (LTR)","langDirRTL":"Regs na Links (RTL)","styles":"Styl","cssClasses":"CSS klasse","width":"Breedte","height":"Hoogte","align":"Orienteerung","left":"Links","right":"Regs","center":"Middel","justify":"Eweredig","alignLeft":"Links oplyn","alignRight":"Regs oplyn","alignCenter":"Middel oplyn","alignTop":"Bo","alignMiddle":"Middel","alignBottom":"Onder","alignNone":"Geen","invalidValue":"Ongeldige waarde","invalidHeight":"Hoogte moet 'n getal wees","invalidWidth":"Breedte moet 'n getal wees.","invalidLength":"Die waarde vir die veld \"%1\" moet 'n posetiewe nommer wees met of sonder die meeteenheid (%2).","invalidCssLength":"Die waarde vir die \"%1\" veld moet 'n posetiewe getal wees met of sonder 'n geldige CSS eenheid (px, %, in, cm, mm, em, ex, pt, of pc).","invalidHtmlLength":"Die waarde vir die \"%1\" veld moet 'n posetiewe getal wees met of sonder 'n geldige HTML eenheid (px of %).","invalidInlineStyle":"Ongeldige CSS. Formaat is een of meer sleutel-wert paare, \"naam : wert\" met kommapunte gesky.","cssLengthTooltip":"Voeg 'n getal wert in pixel in, of 'n waarde met geldige CSS eenheid (px, %, in, cm, mm, em, ex, pt, of pc).","unavailable":"%1<span class=\"cke_accessibility\">, nie beskikbaar nie</span>","keyboard":{"8":"Backspace","13":"Enter","16":"Skuif","17":"Ctrl","18":"Alt","32":"Spasie","35":"Einde","36":"Tuis","46":"Verwyder","112":"F1","113":"F2","114":"F3","115":"F4","116":"F5","117":"F6","118":"F7","119":"F8","120":"F9","121":"F10","122":"F11","123":"F12","124":"F13","125":"F14","126":"F15","127":"F16","128":"F17","129":"F18","130":"F19","131":"F20","132":"F21","133":"F22","134":"F23","135":"F24","224":"Bevel"},"keyboardShortcut":"Sleutel kombenasie","optionDefault":"Verstek"}}; \ No newline at end of file diff --git a/web/core/assets/vendor/ckeditor/lang/fa.js b/web/core/assets/vendor/ckeditor/lang/fa.js index 9e337c5be55116e8b79f5056aef3913535d4e958..294b5a93b14bdbcd5dc622698ea9034b077a1ffe 100644 --- a/web/core/assets/vendor/ckeditor/lang/fa.js +++ b/web/core/assets/vendor/ckeditor/lang/fa.js @@ -2,4 +2,4 @@ Copyright (c) 2003-2018, CKSource - Frederico Knabben. All rights reserved. For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license */ -CKEDITOR.lang['fa']={"widget":{"move":"کلیک و کشیدن برای جابجایی","label":"ابزارک %1"},"undo":{"redo":"بازچیدن","undo":"واچیدن"},"toolbar":{"toolbarCollapse":"بستن نوار ابزار","toolbarExpand":"بازکردن نوار ابزار","toolbarGroups":{"document":"سند","clipboard":"حافظه موقت/برگشت","editing":"در حال ویرایش","forms":"فرمها","basicstyles":"سبکهای پایه","paragraph":"بند","links":"پیوندها","insert":"ورود","styles":"سبکها","colors":"رنگها","tools":"ابزارها"},"toolbars":"نوار ابزارهای ویرایشگر"},"table":{"border":"اندازهٴ لبه","caption":"عنوان","cell":{"menu":"سلول","insertBefore":"افزودن سلول قبل از","insertAfter":"افزودن سلول بعد از","deleteCell":"حذف سلولها","merge":"ادغام سلولها","mergeRight":"ادغام به راست","mergeDown":"ادغام به پایین","splitHorizontal":"جدا کردن افقی سلول","splitVertical":"جدا کردن عمودی سلول","title":"ویژگیهای سلول","cellType":"نوع سلول","rowSpan":"محدوده ردیفها","colSpan":"محدوده ستونها","wordWrap":"شکستن کلمه","hAlign":"چینش افقی","vAlign":"چینش عمودی","alignBaseline":"خط مبنا","bgColor":"رنگ زمینه","borderColor":"رنگ خطوط","data":"اطلاعات","header":"سرنویس","yes":"بله","no":"خیر","invalidWidth":"عرض سلول باید یک عدد باشد.","invalidHeight":"ارتفاع سلول باید عدد باشد.","invalidRowSpan":"مقدار محدوده ردیفها باید یک عدد باشد.","invalidColSpan":"مقدار محدوده ستونها باید یک عدد باشد.","chooseColor":"انتخاب"},"cellPad":"فاصلهٴ پرشده در سلول","cellSpace":"فاصلهٴ میان سلولها","column":{"menu":"ستون","insertBefore":"افزودن ستون قبل از","insertAfter":"افزودن ستون بعد از","deleteColumn":"حذف ستونها"},"columns":"ستونها","deleteTable":"پاک کردن جدول","headers":"سرنویسها","headersBoth":"هردو","headersColumn":"اولین ستون","headersNone":"هیچ","headersRow":"اولین ردیف","invalidBorder":"مقدار اندازه خطوط باید یک عدد باشد.","invalidCellPadding":"بالشتک سلول باید یک عدد باشد.","invalidCellSpacing":"مقدار فاصلهگذاری سلول باید یک عدد باشد.","invalidCols":"تعداد ستونها باید یک عدد بزرگتر از 0 باشد.","invalidHeight":"مقدار ارتفاع جدول باید یک عدد باشد.","invalidRows":"تعداد ردیفها باید یک عدد بزرگتر از 0 باشد.","invalidWidth":"مقدار پهنای جدول باید یک عدد باشد.","menu":"ویژگیهای جدول","row":{"menu":"سطر","insertBefore":"افزودن سطر قبل از","insertAfter":"افزودن سطر بعد از","deleteRow":"حذف سطرها"},"rows":"سطرها","summary":"خلاصه","title":"ویژگیهای جدول","toolbar":"جدول","widthPc":"درصد","widthPx":"پیکسل","widthUnit":"واحد پهنا"},"stylescombo":{"label":"سبک","panelTitle":"سبکهای قالببندی","panelTitle1":"سبکهای بلوک","panelTitle2":"سبکهای درونخطی","panelTitle3":"سبکهای شیء"},"specialchar":{"options":"گزینههای نویسههای ویژه","title":"گزینش نویسهی ویژه","toolbar":"گنجاندن نویسهی ویژه"},"sourcedialog":{"toolbar":"منبع","title":"منبع"},"sourcearea":{"toolbar":"منبع"},"showblocks":{"toolbar":"نمایش بلوکها"},"removeformat":{"toolbar":"برداشتن فرمت"},"pastetext":{"button":"چسباندن به عنوان متن ساده","pasteNotification":"Press %1 to paste. Your browser doesn‘t support pasting with the toolbar button or context menu option.","title":"چسباندن به عنوان متن ساده"},"pastefromword":{"confirmCleanup":"متنی که میخواهید بچسبانید به نظر میرسد که از Word کپی شده است. آیا میخواهید قبل از چسباندن آن را پاکسازی کنید؟","error":"به دلیل بروز خطای داخلی امکان پاکسازی اطلاعات بازنشانی شده وجود ندارد.","title":"چسباندن از Word","toolbar":"چسباندن از Word"},"notification":{"closed":"Notification closed."},"maximize":{"maximize":"بیشنه کردن","minimize":"کمینه کردن"},"magicline":{"title":"قرار دادن بند در اینجا"},"list":{"bulletedlist":"فهرست نقطهای","numberedlist":"فهرست شمارهدار"},"language":{"button":"تعیین زبان","remove":"حذف زبان"},"indent":{"indent":"افزایش تورفتگی","outdent":"کاهش تورفتگی"},"image2":{"alt":"متن جایگزین","btnUpload":"به سرور بفرست","captioned":"تصویر زیرنویس شده","captionPlaceholder":"عنوان","infoTab":"اطلاعات تصویر","lockRatio":"قفل کردن نسبت","menu":"ویژگیهای تصویر","pathName":"تصویر","pathNameCaption":"عنوان","resetSize":"بازنشانی اندازه","resizer":"کلیک و کشیدن برای تغییر اندازه","title":"ویژگیهای تصویر","uploadTab":"بالاگذاری","urlMissing":"آدرس URL اصلی تصویر یافت نشد.","altMissing":"Alternative text is missing."},"horizontalrule":{"toolbar":"گنجاندن خط افقی"},"format":{"label":"قالب","panelTitle":"قالب بند","tag_address":"نشانی","tag_div":"بند","tag_h1":"سرنویس ۱","tag_h2":"سرنویس ۲","tag_h3":"سرنویس ۳","tag_h4":"سرنویس ۴","tag_h5":"سرنویس ۵","tag_h6":"سرنویس ۶","tag_p":"معمولی","tag_pre":"قالبدار"},"filetools":{"loadError":"Error occurred during file read.","networkError":"Network error occurred during file upload.","httpError404":"HTTP error occurred during file upload (404: File not found).","httpError403":"HTTP error occurred during file upload (403: Forbidden).","httpError":"HTTP error occurred during file upload (error status: %1).","noUrlError":"Upload URL is not defined.","responseError":"Incorrect server response."},"elementspath":{"eleLabel":"مسیر عناصر","eleTitle":"%1 عنصر"},"contextmenu":{"options":"گزینههای منوی زمینه"},"clipboard":{"copy":"رونوشت","copyError":"تنظیمات امنیتی مرورگر شما اجازه نمیدهد که ویرایشگر به طور خودکار عملکردهای کپی کردن را انجام دهد. لطفا با دکمههای صفحه کلید این کار را انجام دهید (Ctrl/Cmd+C).","cut":"برش","cutError":"تنظیمات امنیتی مرورگر شما اجازه نمیدهد که ویرایشگر به طور خودکار عملکردهای برش را انجام دهد. لطفا با دکمههای صفحه کلید این کار را انجام دهید (Ctrl/Cmd+X).","paste":"چسباندن","pasteNotification":"Press %1 to paste. Your browser doesn‘t support pasting with the toolbar button or context menu option.","pasteArea":"محل چسباندن","pasteMsg":"Paste your content inside the area below and press OK.","title":"چسباندن"},"button":{"selectedLabel":"%1 (انتخاب شده)"},"blockquote":{"toolbar":"بلوک نقل قول"},"basicstyles":{"bold":"درشت","italic":"خمیده","strike":"خطخورده","subscript":"زیرنویس","superscript":"بالانویس","underline":"زیرخطدار"},"about":{"copy":"حق نشر © $1. کلیه حقوق محفوظ است.","dlgTitle":"درباره CKEditor","moreInfo":"برای کسب اطلاعات مجوز لطفا به وب سایت ما مراجعه کنید:"},"editor":"ویرایشگر متن غنی","editorPanel":"پنل ویرایشگر متن غنی","common":{"editorHelp":"کلید Alt+0 را برای راهنمایی بفشارید","browseServer":"فهرستنمایی سرور","url":"URL","protocol":"قرارداد","upload":"بالاگذاری","uploadSubmit":"به سرور بفرست","image":"تصویر","flash":"فلش","form":"فرم","checkbox":"چکباکس","radio":"دکمهی رادیویی","textField":"فیلد متنی","textarea":"ناحیهٴ متنی","hiddenField":"فیلد پنهان","button":"دکمه","select":"فیلد انتخاب چند گزینهای","imageButton":"دکمهی تصویری","notSet":"<تعییننشده>","id":"شناسه","name":"نام","langDir":"جهت زبان","langDirLtr":"چپ به راست","langDirRtl":"راست به چپ","langCode":"کد زبان","longDescr":"URL توصیف طولانی","cssClass":"کلاسهای شیوهنامه (Stylesheet)","advisoryTitle":"عنوان کمکی","cssStyle":"سبک","ok":"پذیرش","cancel":"انصراف","close":"بستن","preview":"پیشنمایش","resize":"تغییر اندازه","generalTab":"عمومی","advancedTab":"پیشرفته","validateNumberFailed":"این مقدار یک عدد نیست.","confirmNewPage":"هر تغییر ایجاد شدهی ذخیره نشده از بین خواهد رفت. آیا اطمینان دارید که قصد بارگیری صفحه جدیدی را دارید؟","confirmCancel":"برخی از گزینهها تغییر کردهاند. آیا واقعا قصد بستن این پنجره را دارید؟","options":"گزینهها","target":"مقصد","targetNew":"پنجره جدید","targetTop":"بالاترین پنجره","targetSelf":"همان پنجره","targetParent":"پنجره والد","langDirLTR":"چپ به راست","langDirRTL":"راست به چپ","styles":"سبک","cssClasses":"کلاسهای سبکنامه","width":"عرض","height":"طول","align":"چینش","left":"چپ","right":"راست","center":"وسط","justify":"بلوک چین","alignLeft":"چپ چین","alignRight":"راست چین","alignCenter":"مرکز قرار بده","alignTop":"بالا","alignMiddle":"میانه","alignBottom":"پائین","alignNone":"هیچ","invalidValue":"مقدار نامعتبر.","invalidHeight":"ارتفاع باید یک عدد باشد.","invalidWidth":"عرض باید یک عدد باشد.","invalidLength":"عدد تعیین شده برای فیلد \"%1\" باید یک عدد مثبت با یا بدون یک واحد اندازه گیری معتبر (\"%2\") باشد.","invalidCssLength":"عدد تعیین شده برای فیلد \"%1\" باید یک عدد مثبت با یا بدون یک واحد اندازه گیری CSS معتبر باشد (px, %, in, cm, mm, em, ex, pt, or pc).","invalidHtmlLength":"عدد تعیین شده برای فیلد \"%1\" باید یک عدد مثبت با یا بدون یک واحد اندازه گیری HTML معتبر باشد (px or %).","invalidInlineStyle":"عدد تعیین شده برای سبک درونخطی -Inline Style- باید دارای یک یا چند چندتایی با شکلی شبیه \"name : value\" که باید با یک \";\" از هم جدا شوند.","cssLengthTooltip":"یک عدد برای یک مقدار بر حسب پیکسل و یا یک عدد با یک واحد CSS معتبر وارد کنید (px, %, in, cm, mm, em, ex, pt, or pc).","unavailable":"%1<span class=\"cke_accessibility\">، غیر قابل دسترس</span>","keyboard":{"8":"عقبگرد","13":"ورود","16":"تعویض","17":"کنترل","18":"دگرساز","32":"فاصله","35":"پایان","36":"خانه","46":"حذف","112":"F1","113":"F2","114":"F3","115":"F4","116":"F5","117":"F6","118":"F7","119":"F8","120":"F9","121":"F10","122":"F11","123":"F12","124":"F13","125":"F14","126":"F15","127":"F16","128":"F17","129":"F18","130":"F19","131":"F20","132":"F21","133":"F22","134":"F23","135":"F24","224":"فرمان"},"keyboardShortcut":"میانبر صفحه کلید","optionDefault":"پیش فرض"}}; \ No newline at end of file +CKEDITOR.lang['fa']={"widget":{"move":"کلیک و کشیدن برای جابجایی","label":"ابزارک %1"},"undo":{"redo":"بازچیدن","undo":"واچیدن"},"toolbar":{"toolbarCollapse":"بستن نوار ابزار","toolbarExpand":"بازکردن نوار ابزار","toolbarGroups":{"document":"سند","clipboard":"حافظه موقت/برگشت","editing":"در حال ویرایش","forms":"فرمها","basicstyles":"سبکهای پایه","paragraph":"بند","links":"پیوندها","insert":"ورود","styles":"سبکها","colors":"رنگها","tools":"ابزارها"},"toolbars":"نوار ابزارهای ویرایشگر"},"table":{"border":"اندازهٴ لبه","caption":"عنوان","cell":{"menu":"سلول","insertBefore":"افزودن سلول قبل از","insertAfter":"افزودن سلول بعد از","deleteCell":"حذف سلولها","merge":"ادغام سلولها","mergeRight":"ادغام به راست","mergeDown":"ادغام به پایین","splitHorizontal":"جدا کردن افقی سلول","splitVertical":"جدا کردن عمودی سلول","title":"ویژگیهای سلول","cellType":"نوع سلول","rowSpan":"محدوده ردیفها","colSpan":"محدوده ستونها","wordWrap":"شکستن کلمه","hAlign":"چینش افقی","vAlign":"چینش عمودی","alignBaseline":"خط مبنا","bgColor":"رنگ زمینه","borderColor":"رنگ خطوط","data":"اطلاعات","header":"سرنویس","yes":"بله","no":"خیر","invalidWidth":"عرض سلول باید یک عدد باشد.","invalidHeight":"ارتفاع سلول باید عدد باشد.","invalidRowSpan":"مقدار محدوده ردیفها باید یک عدد باشد.","invalidColSpan":"مقدار محدوده ستونها باید یک عدد باشد.","chooseColor":"انتخاب"},"cellPad":"فاصلهٴ پرشده در سلول","cellSpace":"فاصلهٴ میان سلولها","column":{"menu":"ستون","insertBefore":"افزودن ستون قبل از","insertAfter":"افزودن ستون بعد از","deleteColumn":"حذف ستونها"},"columns":"ستونها","deleteTable":"پاک کردن جدول","headers":"سرنویسها","headersBoth":"هردو","headersColumn":"اولین ستون","headersNone":"هیچ","headersRow":"اولین ردیف","invalidBorder":"مقدار اندازه خطوط باید یک عدد باشد.","invalidCellPadding":"بالشتک سلول باید یک عدد باشد.","invalidCellSpacing":"مقدار فاصلهگذاری سلول باید یک عدد باشد.","invalidCols":"تعداد ستونها باید یک عدد بزرگتر از 0 باشد.","invalidHeight":"مقدار ارتفاع جدول باید یک عدد باشد.","invalidRows":"تعداد ردیفها باید یک عدد بزرگتر از 0 باشد.","invalidWidth":"مقدار پهنای جدول باید یک عدد باشد.","menu":"ویژگیهای جدول","row":{"menu":"سطر","insertBefore":"افزودن سطر قبل از","insertAfter":"افزودن سطر بعد از","deleteRow":"حذف سطرها"},"rows":"سطرها","summary":"خلاصه","title":"ویژگیهای جدول","toolbar":"جدول","widthPc":"درصد","widthPx":"پیکسل","widthUnit":"واحد پهنا"},"stylescombo":{"label":"سبک","panelTitle":"سبکهای قالببندی","panelTitle1":"سبکهای بلوک","panelTitle2":"سبکهای درونخطی","panelTitle3":"سبکهای شیء"},"specialchar":{"options":"گزینههای نویسههای ویژه","title":"گزینش نویسهی ویژه","toolbar":"گنجاندن نویسهی ویژه"},"sourcedialog":{"toolbar":"منبع","title":"منبع"},"sourcearea":{"toolbar":"منبع"},"showblocks":{"toolbar":"نمایش بلوکها"},"removeformat":{"toolbar":"برداشتن فرمت"},"pastetext":{"button":"چسباندن به عنوان متن ساده","pasteNotification":"Press %1 to paste. Your browser doesn‘t support pasting with the toolbar button or context menu option.","title":"چسباندن به عنوان متن ساده"},"pastefromword":{"confirmCleanup":"متنی که میخواهید بچسبانید به نظر میرسد که از Word کپی شده است. آیا میخواهید قبل از چسباندن آن را پاکسازی کنید؟","error":"به دلیل بروز خطای داخلی امکان پاکسازی اطلاعات بازنشانی شده وجود ندارد.","title":"چسباندن از Word","toolbar":"چسباندن از Word"},"notification":{"closed":"آگاهسازی بسته شد"},"maximize":{"maximize":"بیشنه کردن","minimize":"کمینه کردن"},"magicline":{"title":"قرار دادن بند در اینجا"},"list":{"bulletedlist":"فهرست نقطهای","numberedlist":"فهرست شمارهدار"},"language":{"button":"تعیین زبان","remove":"حذف زبان"},"indent":{"indent":"افزایش تورفتگی","outdent":"کاهش تورفتگی"},"image2":{"alt":"متن جایگزین","btnUpload":"به سرور بفرست","captioned":"تصویر زیرنویس شده","captionPlaceholder":"عنوان","infoTab":"اطلاعات تصویر","lockRatio":"قفل کردن نسبت","menu":"ویژگیهای تصویر","pathName":"تصویر","pathNameCaption":"عنوان","resetSize":"بازنشانی اندازه","resizer":"کلیک و کشیدن برای تغییر اندازه","title":"ویژگیهای تصویر","uploadTab":"بالاگذاری","urlMissing":"آدرس URL اصلی تصویر یافت نشد.","altMissing":"متن جایگزین یافت نشد."},"horizontalrule":{"toolbar":"گنجاندن خط افقی"},"format":{"label":"قالب","panelTitle":"قالب بند","tag_address":"نشانی","tag_div":"بند","tag_h1":"سرنویس ۱","tag_h2":"سرنویس ۲","tag_h3":"سرنویس ۳","tag_h4":"سرنویس ۴","tag_h5":"سرنویس ۵","tag_h6":"سرنویس ۶","tag_p":"معمولی","tag_pre":"قالبدار"},"filetools":{"loadError":"هنگام خواندن فایل، خطایی رخ داد.","networkError":"هنگام آپلود فایل خطای شبکه رخ داد.","httpError404":"هنگام آپلود فایل خطای HTTP رخ داد (404: فایل یافت نشد).","httpError403":"هنگام آپلود فایل، خطای HTTP رخ داد (403: ممنوع).","httpError":"خطای HTTP در آپلود فایل رخ داده است (وضعیت خطا: %1).","noUrlError":"آدرس آپلود تعریف نشده است.","responseError":"پاسخ نادرست سرور."},"elementspath":{"eleLabel":"مسیر عناصر","eleTitle":"%1 عنصر"},"contextmenu":{"options":"گزینههای منوی زمینه"},"clipboard":{"copy":"رونوشت","copyError":"تنظیمات امنیتی مرورگر شما اجازه نمیدهد که ویرایشگر به طور خودکار عملکردهای کپی کردن را انجام دهد. لطفا با دکمههای صفحه کلید این کار را انجام دهید (Ctrl/Cmd+C).","cut":"برش","cutError":"تنظیمات امنیتی مرورگر شما اجازه نمیدهد که ویرایشگر به طور خودکار عملکردهای برش را انجام دهد. لطفا با دکمههای صفحه کلید این کار را انجام دهید (Ctrl/Cmd+X).","paste":"چسباندن","pasteNotification":"Press %1 to paste. Your browser doesn‘t support pasting with the toolbar button or context menu option.","pasteArea":"محل چسباندن","pasteMsg":"Paste your content inside the area below and press OK.","title":"چسباندن"},"button":{"selectedLabel":"%1 (انتخاب شده)"},"blockquote":{"toolbar":"بلوک نقل قول"},"basicstyles":{"bold":"درشت","italic":"خمیده","strike":"خطخورده","subscript":"زیرنویس","superscript":"بالانویس","underline":"زیرخطدار"},"about":{"copy":"حق نشر © $1. کلیه حقوق محفوظ است.","dlgTitle":"درباره CKEditor","moreInfo":"برای کسب اطلاعات مجوز لطفا به وب سایت ما مراجعه کنید:"},"editor":"ویرایشگر متن غنی","editorPanel":"پنل ویرایشگر متن غنی","common":{"editorHelp":"کلید Alt+0 را برای راهنمایی بفشارید","browseServer":"فهرستنمایی سرور","url":"URL","protocol":"قرارداد","upload":"بالاگذاری","uploadSubmit":"به سرور بفرست","image":"تصویر","flash":"فلش","form":"فرم","checkbox":"چکباکس","radio":"دکمهی رادیویی","textField":"فیلد متنی","textarea":"ناحیهٴ متنی","hiddenField":"فیلد پنهان","button":"دکمه","select":"فیلد انتخاب چند گزینهای","imageButton":"دکمهی تصویری","notSet":"<تعییننشده>","id":"شناسه","name":"نام","langDir":"جهت زبان","langDirLtr":"چپ به راست","langDirRtl":"راست به چپ","langCode":"کد زبان","longDescr":"URL توصیف طولانی","cssClass":"کلاسهای شیوهنامه (Stylesheet)","advisoryTitle":"عنوان کمکی","cssStyle":"سبک","ok":"پذیرش","cancel":"انصراف","close":"بستن","preview":"پیشنمایش","resize":"تغییر اندازه","generalTab":"عمومی","advancedTab":"پیشرفته","validateNumberFailed":"این مقدار یک عدد نیست.","confirmNewPage":"هر تغییر ایجاد شدهی ذخیره نشده از بین خواهد رفت. آیا اطمینان دارید که قصد بارگیری صفحه جدیدی را دارید؟","confirmCancel":"برخی از گزینهها تغییر کردهاند. آیا واقعا قصد بستن این پنجره را دارید؟","options":"گزینهها","target":"مقصد","targetNew":"پنجره جدید","targetTop":"بالاترین پنجره","targetSelf":"همان پنجره","targetParent":"پنجره والد","langDirLTR":"چپ به راست","langDirRTL":"راست به چپ","styles":"سبک","cssClasses":"کلاسهای سبکنامه","width":"عرض","height":"طول","align":"چینش","left":"چپ","right":"راست","center":"وسط","justify":"بلوک چین","alignLeft":"چپ چین","alignRight":"راست چین","alignCenter":"مرکز قرار بده","alignTop":"بالا","alignMiddle":"میانه","alignBottom":"پائین","alignNone":"هیچ","invalidValue":"مقدار نامعتبر.","invalidHeight":"ارتفاع باید یک عدد باشد.","invalidWidth":"عرض باید یک عدد باشد.","invalidLength":"عدد تعیین شده برای فیلد \"%1\" باید یک عدد مثبت با یا بدون یک واحد اندازه گیری معتبر (\"%2\") باشد.","invalidCssLength":"عدد تعیین شده برای فیلد \"%1\" باید یک عدد مثبت با یا بدون یک واحد اندازه گیری CSS معتبر باشد (px, %, in, cm, mm, em, ex, pt, or pc).","invalidHtmlLength":"عدد تعیین شده برای فیلد \"%1\" باید یک عدد مثبت با یا بدون یک واحد اندازه گیری HTML معتبر باشد (px or %).","invalidInlineStyle":"عدد تعیین شده برای سبک درونخطی -Inline Style- باید دارای یک یا چند چندتایی با شکلی شبیه \"name : value\" که باید با یک \";\" از هم جدا شوند.","cssLengthTooltip":"یک عدد برای یک مقدار بر حسب پیکسل و یا یک عدد با یک واحد CSS معتبر وارد کنید (px, %, in, cm, mm, em, ex, pt, or pc).","unavailable":"%1<span class=\"cke_accessibility\">، غیر قابل دسترس</span>","keyboard":{"8":"عقبگرد","13":"ورود","16":"تعویض","17":"کنترل","18":"دگرساز","32":"فاصله","35":"پایان","36":"خانه","46":"حذف","112":"F1","113":"F2","114":"F3","115":"F4","116":"F5","117":"F6","118":"F7","119":"F8","120":"F9","121":"F10","122":"F11","123":"F12","124":"F13","125":"F14","126":"F15","127":"F16","128":"F17","129":"F18","130":"F19","131":"F20","132":"F21","133":"F22","134":"F23","135":"F24","224":"فرمان"},"keyboardShortcut":"میانبر صفحه کلید","optionDefault":"پیش فرض"}}; \ No newline at end of file diff --git a/web/core/assets/vendor/ckeditor/lang/fr.js b/web/core/assets/vendor/ckeditor/lang/fr.js index 431ac349a92b486f54510f5a13dd9574817e4c17..44653da5215c15897fda073bccf53b6b5dc973ff 100644 --- a/web/core/assets/vendor/ckeditor/lang/fr.js +++ b/web/core/assets/vendor/ckeditor/lang/fr.js @@ -2,4 +2,4 @@ Copyright (c) 2003-2018, CKSource - Frederico Knabben. All rights reserved. For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license */ -CKEDITOR.lang['fr']={"widget":{"move":"Cliquer et glisser pour déplacer","label":"Élément %1"},"undo":{"redo":"Rétablir","undo":"Annuler"},"toolbar":{"toolbarCollapse":"Enrouler la barre d'outils","toolbarExpand":"Dérouler la barre d'outils","toolbarGroups":{"document":"Document","clipboard":"Presse-papier/Défaire","editing":"Édition","forms":"Formulaires","basicstyles":"Styles de base","paragraph":"Paragraphe","links":"Liens","insert":"Insérer","styles":"Styles","colors":"Couleurs","tools":"Outils"},"toolbars":"Barres d'outils de l'éditeur"},"table":{"border":"Taille de la bordure","caption":"Titre du tableau","cell":{"menu":"Cellule","insertBefore":"Insérer une cellule avant","insertAfter":"Insérer une cellule après","deleteCell":"Supprimer les cellules","merge":"Fusionner les cellules","mergeRight":"Fusionner vers la droite","mergeDown":"Fusionner vers le bas","splitHorizontal":"Scinder la cellule horizontalement","splitVertical":"Scinder la cellule verticalement","title":"Propriétés de la cellule","cellType":"Type de cellule","rowSpan":"Lignes occupées","colSpan":"Colonnes occupées","wordWrap":"Césure","hAlign":"Alignement horizontal","vAlign":"Alignement vertical","alignBaseline":"Ligne de base","bgColor":"Couleur d'arrière-plan","borderColor":"Couleur de bordure","data":"Données","header":"En-tête","yes":"Oui","no":"Non","invalidWidth":"La largeur de la cellule doit être un nombre.","invalidHeight":"La hauteur de la cellule doit être un nombre.","invalidRowSpan":"Le nombre de colonnes occupées doit être un nombre entier.","invalidColSpan":"Le nombre de colonnes occupées doit être un nombre entier.","chooseColor":"Choisir"},"cellPad":"Marge interne des cellules","cellSpace":"Espacement entre les cellules","column":{"menu":"Colonne","insertBefore":"Insérer une colonne avant","insertAfter":"Insérer une colonne après","deleteColumn":"Supprimer les colonnes"},"columns":"Colonnes","deleteTable":"Supprimer le tableau","headers":"En-têtes","headersBoth":"Les deux","headersColumn":"Première colonne","headersNone":"Aucun","headersRow":"Première ligne","invalidBorder":"La taille de la bordure doit être un nombre.","invalidCellPadding":"La marge interne des cellules doit être un nombre positif.","invalidCellSpacing":"L'espacement entre les cellules doit être un nombre positif.","invalidCols":"Le nombre de colonnes doit être supérieur à 0.","invalidHeight":"La hauteur du tableau doit être un nombre.","invalidRows":"Le nombre de lignes doit être supérieur à 0.","invalidWidth":"La largeur du tableau doit être un nombre.","menu":"Propriétés du tableau","row":{"menu":"Ligne","insertBefore":"Insérer une ligne avant","insertAfter":"Insérer une ligne après","deleteRow":"Supprimer les lignes"},"rows":"Lignes","summary":"Résumé (description)","title":"Propriétés du tableau","toolbar":"Tableau","widthPc":"pour cent","widthPx":"pixels","widthUnit":"unité de largeur"},"stylescombo":{"label":"Styles","panelTitle":"Styles de mise en forme","panelTitle1":"Styles de bloc","panelTitle2":"Styles en ligne","panelTitle3":"Styles d'objet"},"specialchar":{"options":"Options des caractères spéciaux","title":"Sélectionner un caractère","toolbar":"Insérer un caractère spécial"},"sourcedialog":{"toolbar":"Source","title":"Source"},"sourcearea":{"toolbar":"Source"},"showblocks":{"toolbar":"Afficher les blocs"},"removeformat":{"toolbar":"Supprimer la mise en forme"},"pastetext":{"button":"Coller comme texte brut","pasteNotification":"Press %1 to paste. Your browser doesn‘t support pasting with the toolbar button or context menu option.","title":"Coller comme texte brut"},"pastefromword":{"confirmCleanup":"Le texte à coller semble provenir de Word. Désirez-vous le nettoyer avant de coller ?","error":"Les données collées n'ont pas pu être nettoyées à cause d'une erreur interne","title":"Coller depuis Word","toolbar":"Coller depuis Word"},"notification":{"closed":"Notification fermée."},"maximize":{"maximize":"Agrandir","minimize":"Réduire"},"magicline":{"title":"Insérer un paragraphe ici"},"list":{"bulletedlist":"Insérer/Supprimer une liste à puces","numberedlist":"Insérer/Supprimer une liste numérotée"},"language":{"button":"Définir la langue","remove":"Supprimer la langue"},"indent":{"indent":"Augmenter le retrait","outdent":"Diminuer le retrait"},"image2":{"alt":"Texte alternatif","btnUpload":"Envoyer sur le serveur","captioned":"Image légendée","captionPlaceholder":"Légende","infoTab":"Informations sur l'image","lockRatio":"Conserver les proportions","menu":"Propriétés de l'image","pathName":"image","pathNameCaption":"légende","resetSize":"Réinitialiser la taille","resizer":"Cliquer et glisser pour redimensionner","title":"Propriétés de l'image","uploadTab":"Téléverser","urlMissing":"L'URL source de l'image est manquante.","altMissing":"Vous n'avez pas indiqué de texte de remplacement."},"horizontalrule":{"toolbar":"Ligne horizontale"},"format":{"label":"Format","panelTitle":"Format de paragraphe","tag_address":"Adresse","tag_div":"Division","tag_h1":"Titre 1","tag_h2":"Titre 2","tag_h3":"Titre 3","tag_h4":"Titre 4","tag_h5":"Titre 5","tag_h6":"Titre 6","tag_p":"Normal","tag_pre":"Préformaté"},"filetools":{"loadError":"Une erreur est survenue lors de la lecture du fichier.","networkError":"Une erreur réseau est survenue lors du téléversement du fichier.","httpError404":"Une erreur HTTP est survenue durant le téléversement du fichier (404 : fichier non trouvé).","httpError403":"Une erreur HTTP est survenue durant le téléversement du fichier (403 : accès refusé).","httpError":"Une erreur HTTP est survenue durant le téléversement du fichier (erreur : %1).","noUrlError":"L'URL de téléversement n'est pas spécifiée.","responseError":"Réponse du serveur incorrecte."},"elementspath":{"eleLabel":"Chemin des éléments","eleTitle":"Élément %1"},"contextmenu":{"options":"Options du menu contextuel"},"clipboard":{"copy":"Copier","copyError":"Les paramètres de sécurité de votre navigateur n'autorisent pas l'éditeur à exécuter automatiquement l'opération « Copier ». Veuillez utiliser le raccourci clavier à cet effet (Ctrl/Cmd+C).","cut":"Couper","cutError":"Les paramètres de sécurité de votre navigateur n'autorisent pas l'éditeur à exécuter automatiquement l'opération « Couper ». Veuillez utiliser le raccourci clavier à cet effet (Ctrl/Cmd+X).","paste":"Coller","pasteNotification":"Press %1 to paste. Your browser doesn‘t support pasting with the toolbar button or context menu option.","pasteArea":"Coller la zone","pasteMsg":"Paste your content inside the area below and press OK.","title":"Coller"},"button":{"selectedLabel":"%1 (Sélectionné)"},"blockquote":{"toolbar":"Citation"},"basicstyles":{"bold":"Gras","italic":"Italique","strike":"Barré","subscript":"Indice","superscript":"Exposant","underline":"Souligné"},"about":{"copy":"Copyright © $1. Tous droits réservés.","dlgTitle":"À propos de CKEditor 4","moreInfo":"Pour les informations de licence, veuillez visiter notre site web :"},"editor":"Éditeur de texte enrichi","editorPanel":"Tableau de bord de l'éditeur de texte enrichi","common":{"editorHelp":"Utilisez le raccourci Alt-0 pour obtenir de l'aide","browseServer":"Parcourir le serveur","url":"URL","protocol":"Protocole","upload":"Télécharger","uploadSubmit":"Envoyer sur le serveur","image":"Image","flash":"Flash","form":"Formulaire","checkbox":"Case à cocher","radio":"Bouton radio","textField":"Champ texte","textarea":"Zone de texte","hiddenField":"Champ invisible","button":"Bouton","select":"Liste déroulante","imageButton":"Bouton avec image","notSet":"<indéfini>","id":"ID","name":"Nom","langDir":"Sens d'écriture","langDirLtr":"Gauche à droite (LTR)","langDirRtl":"Droite à gauche (RTL)","langCode":"Code de langue","longDescr":"URL de description longue","cssClass":"Classes de style","advisoryTitle":"Infobulle","cssStyle":"Style","ok":"OK","cancel":"Annuler","close":"Fermer","preview":"Aperçu","resize":"Redimensionner","generalTab":"Général","advancedTab":"Avancé","validateNumberFailed":"Cette valeur n'est pas un nombre.","confirmNewPage":"Les changements non sauvegardés seront perdus. Êtes-vous sûr de vouloir charger une nouvelle page ?","confirmCancel":"Certaines options ont été modifiées. Êtes-vous sûr de vouloir fermer ?","options":"Options","target":"Cible","targetNew":"Nouvelle fenêtre (_blank)","targetTop":"Fenêtre supérieure (_top)","targetSelf":"Même fenêtre (_self)","targetParent":"Fenêtre parent (_parent)","langDirLTR":"Gauche à droite (LTR)","langDirRTL":"Droite à gauche (RTL)","styles":"Style","cssClasses":"Classes de style","width":"Largeur","height":"Hauteur","align":"Alignement","left":"Gauche","right":"Droite","center":"Centrer","justify":"Justifier","alignLeft":"Aligner à gauche","alignRight":"Aligner à droite","alignCenter":"Align Center","alignTop":"Haut","alignMiddle":"Milieu","alignBottom":"Bas","alignNone":"Aucun","invalidValue":"Valeur invalide.","invalidHeight":"La hauteur doit être un nombre.","invalidWidth":"La largeur doit être un nombre.","invalidLength":"Value specified for the \"%1\" field must be a positive number with or without a valid measurement unit (%2).","invalidCssLength":"La valeur spécifiée pour le champ « %1 » doit être un nombre positif avec ou sans unité de mesure CSS valide (px, %, in, cm, mm, em, ex, pt, ou pc).","invalidHtmlLength":"La valeur spécifiée pour le champ « %1 » doit être un nombre positif avec ou sans unité de mesure HTML valide (px ou %).","invalidInlineStyle":"La valeur spécifiée pour le style en ligne doit être composée d'un ou plusieurs couples au format « nom : valeur », séparés par des points-virgules.","cssLengthTooltip":"Entrer un nombre pour une valeur en pixels ou un nombre avec une unité de mesure CSS valide (px, %, in, cm, mm, em, ex, pt, ou pc).","unavailable":"%1<span class=\"cke_accessibility\">, indisponible</span>","keyboard":{"8":"Retour arrière","13":"Entrée","16":"Majuscule","17":"Ctrl","18":"Alt","32":"Espace","35":"Fin","36":"Origine","46":"Supprimer","112":"F1","113":"F2","114":"F3","115":"F4","116":"F5","117":"F6","118":"F7","119":"F8","120":"F9","121":"F10","122":"F11","123":"F12","124":"F13","125":"F14","126":"F15","127":"F16","128":"F17","129":"F18","130":"F19","131":"F20","132":"F21","133":"F22","134":"F23","135":"F24","224":"Commande"},"keyboardShortcut":"Raccourci clavier","optionDefault":"Par défaut"}}; \ No newline at end of file +CKEDITOR.lang['fr']={"widget":{"move":"Cliquer et glisser pour déplacer","label":"Élément %1"},"undo":{"redo":"Rétablir","undo":"Annuler"},"toolbar":{"toolbarCollapse":"Enrouler la barre d'outils","toolbarExpand":"Dérouler la barre d'outils","toolbarGroups":{"document":"Document","clipboard":"Presse-papier/Défaire","editing":"Édition","forms":"Formulaires","basicstyles":"Styles de base","paragraph":"Paragraphe","links":"Liens","insert":"Insérer","styles":"Styles","colors":"Couleurs","tools":"Outils"},"toolbars":"Barres d'outils de l'éditeur"},"table":{"border":"Taille de la bordure","caption":"Titre du tableau","cell":{"menu":"Cellule","insertBefore":"Insérer une cellule avant","insertAfter":"Insérer une cellule après","deleteCell":"Supprimer les cellules","merge":"Fusionner les cellules","mergeRight":"Fusionner vers la droite","mergeDown":"Fusionner vers le bas","splitHorizontal":"Scinder la cellule horizontalement","splitVertical":"Scinder la cellule verticalement","title":"Propriétés de la cellule","cellType":"Type de cellule","rowSpan":"Lignes occupées","colSpan":"Colonnes occupées","wordWrap":"Césure","hAlign":"Alignement horizontal","vAlign":"Alignement vertical","alignBaseline":"Ligne de base","bgColor":"Couleur d'arrière-plan","borderColor":"Couleur de bordure","data":"Données","header":"En-tête","yes":"Oui","no":"Non","invalidWidth":"La largeur de la cellule doit être un nombre.","invalidHeight":"La hauteur de la cellule doit être un nombre.","invalidRowSpan":"Le nombre de colonnes occupées doit être un nombre entier.","invalidColSpan":"Le nombre de colonnes occupées doit être un nombre entier.","chooseColor":"Choisir"},"cellPad":"Marge interne des cellules","cellSpace":"Espacement entre les cellules","column":{"menu":"Colonne","insertBefore":"Insérer une colonne avant","insertAfter":"Insérer une colonne après","deleteColumn":"Supprimer les colonnes"},"columns":"Colonnes","deleteTable":"Supprimer le tableau","headers":"En-têtes","headersBoth":"Les deux","headersColumn":"Première colonne","headersNone":"Aucun","headersRow":"Première ligne","invalidBorder":"La taille de la bordure doit être un nombre.","invalidCellPadding":"La marge interne des cellules doit être un nombre positif.","invalidCellSpacing":"L'espacement entre les cellules doit être un nombre positif.","invalidCols":"Le nombre de colonnes doit être supérieur à 0.","invalidHeight":"La hauteur du tableau doit être un nombre.","invalidRows":"Le nombre de lignes doit être supérieur à 0.","invalidWidth":"La largeur du tableau doit être un nombre.","menu":"Propriétés du tableau","row":{"menu":"Ligne","insertBefore":"Insérer une ligne avant","insertAfter":"Insérer une ligne après","deleteRow":"Supprimer les lignes"},"rows":"Lignes","summary":"Résumé (description)","title":"Propriétés du tableau","toolbar":"Tableau","widthPc":"pour cent","widthPx":"pixels","widthUnit":"unité de largeur"},"stylescombo":{"label":"Styles","panelTitle":"Styles de mise en forme","panelTitle1":"Styles de bloc","panelTitle2":"Styles en ligne","panelTitle3":"Styles d'objet"},"specialchar":{"options":"Options des caractères spéciaux","title":"Sélectionner un caractère","toolbar":"Insérer un caractère spécial"},"sourcedialog":{"toolbar":"Source","title":"Source"},"sourcearea":{"toolbar":"Source"},"showblocks":{"toolbar":"Afficher les blocs"},"removeformat":{"toolbar":"Supprimer la mise en forme"},"pastetext":{"button":"Coller comme texte brut","pasteNotification":"Utilisez le raccourci %1 pour coller. Votre navigateur n'accepte pas de coller à l'aide du bouton ou du menu contextuel.","title":"Coller comme texte brut"},"pastefromword":{"confirmCleanup":"Le texte à coller semble provenir de Word. Désirez-vous le nettoyer avant de coller ?","error":"Les données collées n'ont pas pu être nettoyées à cause d'une erreur interne","title":"Coller depuis Word","toolbar":"Coller depuis Word"},"notification":{"closed":"Notification fermée."},"maximize":{"maximize":"Agrandir","minimize":"Réduire"},"magicline":{"title":"Insérer un paragraphe ici"},"list":{"bulletedlist":"Insérer/Supprimer une liste à puces","numberedlist":"Insérer/Supprimer une liste numérotée"},"language":{"button":"Définir la langue","remove":"Supprimer la langue"},"indent":{"indent":"Augmenter le retrait","outdent":"Diminuer le retrait"},"image2":{"alt":"Texte alternatif","btnUpload":"Envoyer sur le serveur","captioned":"Image légendée","captionPlaceholder":"Légende","infoTab":"Informations sur l'image","lockRatio":"Conserver les proportions","menu":"Propriétés de l'image","pathName":"image","pathNameCaption":"légende","resetSize":"Réinitialiser la taille","resizer":"Cliquer et glisser pour redimensionner","title":"Propriétés de l'image","uploadTab":"Téléverser","urlMissing":"L'URL source de l'image est manquante.","altMissing":"Vous n'avez pas indiqué de texte de remplacement."},"horizontalrule":{"toolbar":"Ligne horizontale"},"format":{"label":"Format","panelTitle":"Format de paragraphe","tag_address":"Adresse","tag_div":"Division","tag_h1":"Titre 1","tag_h2":"Titre 2","tag_h3":"Titre 3","tag_h4":"Titre 4","tag_h5":"Titre 5","tag_h6":"Titre 6","tag_p":"Normal","tag_pre":"Préformaté"},"filetools":{"loadError":"Une erreur est survenue lors de la lecture du fichier.","networkError":"Une erreur réseau est survenue lors du téléversement du fichier.","httpError404":"Une erreur HTTP est survenue durant le téléversement du fichier (404 : fichier non trouvé).","httpError403":"Une erreur HTTP est survenue durant le téléversement du fichier (403 : accès refusé).","httpError":"Une erreur HTTP est survenue durant le téléversement du fichier (erreur : %1).","noUrlError":"L'URL de téléversement n'est pas spécifiée.","responseError":"Réponse du serveur incorrecte."},"elementspath":{"eleLabel":"Chemin des éléments","eleTitle":"Élément %1"},"contextmenu":{"options":"Options du menu contextuel"},"clipboard":{"copy":"Copier","copyError":"Les paramètres de sécurité de votre navigateur n'autorisent pas l'éditeur à exécuter automatiquement l'opération « Copier ». Veuillez utiliser le raccourci clavier à cet effet (Ctrl/Cmd+C).","cut":"Couper","cutError":"Les paramètres de sécurité de votre navigateur n'autorisent pas l'éditeur à exécuter automatiquement l'opération « Couper ». Veuillez utiliser le raccourci clavier à cet effet (Ctrl/Cmd+X).","paste":"Coller","pasteNotification":"Utilisez le raccourci %1 pour coller. Votre navigateur n'accepte pas de coller à l'aide du bouton ou du menu contextuel.","pasteArea":"Coller la zone","pasteMsg":"Collez votre contenu dans la zone de saisie ci-dessous et cliquez OK.","title":"Coller"},"button":{"selectedLabel":"%1 (Sélectionné)"},"blockquote":{"toolbar":"Citation"},"basicstyles":{"bold":"Gras","italic":"Italique","strike":"Barré","subscript":"Indice","superscript":"Exposant","underline":"Souligné"},"about":{"copy":"Copyright © $1. Tous droits réservés.","dlgTitle":"À propos de CKEditor 4","moreInfo":"Pour les informations de licence, veuillez visiter notre site web :"},"editor":"Éditeur de texte enrichi","editorPanel":"Tableau de bord de l'éditeur de texte enrichi","common":{"editorHelp":"Utilisez le raccourci Alt-0 pour obtenir de l'aide","browseServer":"Parcourir le serveur","url":"URL","protocol":"Protocole","upload":"Télécharger","uploadSubmit":"Envoyer sur le serveur","image":"Image","flash":"Flash","form":"Formulaire","checkbox":"Case à cocher","radio":"Bouton radio","textField":"Champ texte","textarea":"Zone de texte","hiddenField":"Champ invisible","button":"Bouton","select":"Liste déroulante","imageButton":"Bouton avec image","notSet":"<indéfini>","id":"ID","name":"Nom","langDir":"Sens d'écriture","langDirLtr":"Gauche à droite (LTR)","langDirRtl":"Droite à gauche (RTL)","langCode":"Code de langue","longDescr":"URL de description longue","cssClass":"Classes de style","advisoryTitle":"Infobulle","cssStyle":"Style","ok":"OK","cancel":"Annuler","close":"Fermer","preview":"Aperçu","resize":"Redimensionner","generalTab":"Général","advancedTab":"Avancé","validateNumberFailed":"Cette valeur n'est pas un nombre.","confirmNewPage":"Les changements non sauvegardés seront perdus. Êtes-vous sûr de vouloir charger une nouvelle page ?","confirmCancel":"Certaines options ont été modifiées. Êtes-vous sûr de vouloir fermer ?","options":"Options","target":"Cible","targetNew":"Nouvelle fenêtre (_blank)","targetTop":"Fenêtre supérieure (_top)","targetSelf":"Même fenêtre (_self)","targetParent":"Fenêtre parent (_parent)","langDirLTR":"Gauche à droite (LTR)","langDirRTL":"Droite à gauche (RTL)","styles":"Style","cssClasses":"Classes de style","width":"Largeur","height":"Hauteur","align":"Alignement","left":"Gauche","right":"Droite","center":"Centrer","justify":"Justifier","alignLeft":"Aligner à gauche","alignRight":"Aligner à droite","alignCenter":"Aligner au centre","alignTop":"Haut","alignMiddle":"Milieu","alignBottom":"Bas","alignNone":"Aucun","invalidValue":"Valeur invalide.","invalidHeight":"La hauteur doit être un nombre.","invalidWidth":"La largeur doit être un nombre.","invalidLength":"La valeur de \"%1\" doit être un nombre positif avec ou sans unité de mesure (%2).","invalidCssLength":"La valeur spécifiée pour le champ « %1 » doit être un nombre positif avec ou sans unité de mesure CSS valide (px, %, in, cm, mm, em, ex, pt, ou pc).","invalidHtmlLength":"La valeur spécifiée pour le champ « %1 » doit être un nombre positif avec ou sans unité de mesure HTML valide (px ou %).","invalidInlineStyle":"La valeur spécifiée pour le style en ligne doit être composée d'un ou plusieurs couples au format « nom : valeur », séparés par des points-virgules.","cssLengthTooltip":"Entrer un nombre pour une valeur en pixels ou un nombre avec une unité de mesure CSS valide (px, %, in, cm, mm, em, ex, pt, ou pc).","unavailable":"%1<span class=\"cke_accessibility\">, indisponible</span>","keyboard":{"8":"Retour arrière","13":"Entrée","16":"Majuscule","17":"Ctrl","18":"Alt","32":"Espace","35":"Fin","36":"Origine","46":"Supprimer","112":"F1","113":"F2","114":"F3","115":"F4","116":"F5","117":"F6","118":"F7","119":"F8","120":"F9","121":"F10","122":"F11","123":"F12","124":"F13","125":"F14","126":"F15","127":"F16","128":"F17","129":"F18","130":"F19","131":"F20","132":"F21","133":"F22","134":"F23","135":"F24","224":"Commande"},"keyboardShortcut":"Raccourci clavier","optionDefault":"Par défaut"}}; \ No newline at end of file diff --git a/web/core/assets/vendor/ckeditor/lang/lv.js b/web/core/assets/vendor/ckeditor/lang/lv.js index f40bf1a974d8e49f7dbf69821c71bf789d6c9fad..680765f52d1908cdcfa2408228a078d09c182246 100644 --- a/web/core/assets/vendor/ckeditor/lang/lv.js +++ b/web/core/assets/vendor/ckeditor/lang/lv.js @@ -2,4 +2,4 @@ Copyright (c) 2003-2018, CKSource - Frederico Knabben. All rights reserved. For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license */ -CKEDITOR.lang['lv']={"widget":{"move":"Klikšķina un velc, lai pārvietotu","label":"%1 widget"},"undo":{"redo":"Atkārtot","undo":"Atcelt"},"toolbar":{"toolbarCollapse":"Aizvērt rīkjoslu","toolbarExpand":"Atvērt rīkjoslu","toolbarGroups":{"document":"Dokuments","clipboard":"Starpliktuve/Atcelt","editing":"Labošana","forms":"Formas","basicstyles":"Pamata stili","paragraph":"Paragrāfs","links":"Saites","insert":"Ievietot","styles":"Stili","colors":"Krāsas","tools":"Rīki"},"toolbars":"Redaktora rīkjoslas"},"table":{"border":"Rāmja izmērs","caption":"Leģenda","cell":{"menu":"Šūna","insertBefore":"Pievienot šūnu pirms","insertAfter":"Pievienot šūnu pēc","deleteCell":"Dzēst rūtiņas","merge":"Apvienot rūtiņas","mergeRight":"Apvieno pa labi","mergeDown":"Apvienot uz leju","splitHorizontal":"Sadalīt šūnu horizontāli","splitVertical":"Sadalīt šūnu vertikāli","title":"Šūnas uzstādījumi","cellType":"Šūnas tips","rowSpan":"Apvienotas rindas","colSpan":"Apvienotas kolonas","wordWrap":"Vārdu pārnese","hAlign":"Horizontālais novietojums","vAlign":"Vertikālais novietojums","alignBaseline":"Pamatrinda","bgColor":"Fona krāsa","borderColor":"Rāmja krāsa","data":"Dati","header":"Virsraksts","yes":"Jā","no":"Nē","invalidWidth":"Šūnas platumam jābūt skaitlim","invalidHeight":"Šūnas augstumam jābūt skaitlim","invalidRowSpan":"Apvienojamo rindu skaitam jābūt veselam skaitlim","invalidColSpan":"Apvienojamo kolonu skaitam jābūt veselam skaitlim","chooseColor":"Izvēlēties"},"cellPad":"Rūtiņu nobīde","cellSpace":"Rūtiņu atstatums","column":{"menu":"Kolonna","insertBefore":"Ievietot kolonu pirms","insertAfter":"Ievieto kolonu pēc","deleteColumn":"Dzēst kolonnas"},"columns":"Kolonnas","deleteTable":"Dzēst tabulu","headers":"Virsraksti","headersBoth":"Abi","headersColumn":"Pirmā kolona","headersNone":"Nekas","headersRow":"Pirmā rinda","invalidBorder":"Rāmju izmēram jābūt skaitlim","invalidCellPadding":"Šūnu atkāpēm jābūt pozitīvam skaitlim","invalidCellSpacing":"Šūnu atstarpēm jābūt pozitīvam skaitlim","invalidCols":"Kolonu skaitam jābūt lielākam par 0","invalidHeight":"Tabulas augstumam jābūt skaitlim","invalidRows":"Rindu skaitam jābūt lielākam par 0","invalidWidth":"Tabulas platumam jābūt skaitlim","menu":"Tabulas īpašības","row":{"menu":"Rinda","insertBefore":"Ievietot rindu pirms","insertAfter":"Ievietot rindu pēc","deleteRow":"Dzēst rindas"},"rows":"Rindas","summary":"Anotācija","title":"Tabulas īpašības","toolbar":"Tabula","widthPc":"procentuāli","widthPx":"pikseļos","widthUnit":"platuma mērvienība"},"stylescombo":{"label":"Stils","panelTitle":"Formatēšanas stili","panelTitle1":"Bloka stili","panelTitle2":"iekļautie stili","panelTitle3":"Objekta stili"},"specialchar":{"options":"Speciālo simbolu uzstādījumi","title":"Ievietot īpašu simbolu","toolbar":"Ievietot speciālo simbolu"},"sourcedialog":{"toolbar":"HTML kods","title":"HTML kods"},"sourcearea":{"toolbar":"HTML kods"},"showblocks":{"toolbar":"Parādīt blokus"},"removeformat":{"toolbar":"Noņemt stilus"},"pastetext":{"button":"Ievietot kā vienkāršu tekstu","pasteNotification":"Press %1 to paste. Your browser doesn‘t support pasting with the toolbar button or context menu option.","title":"Ievietot kā vienkāršu tekstu"},"pastefromword":{"confirmCleanup":"Teksts, kuru vēlaties ielīmēt, izskatās ir nokopēts no Word. Vai vēlaties to iztīrīt pirms ielīmēšanas?","error":"Iekšējas kļūdas dēļ, neizdevās iztīrīt ielīmētos datus.","title":"Ievietot no Worda","toolbar":"Ievietot no Worda"},"notification":{"closed":"Notification closed."},"maximize":{"maximize":"Maksimizēt","minimize":"Minimizēt"},"magicline":{"title":"Ievietot šeit rindkopu"},"list":{"bulletedlist":"Pievienot/Noņemt vienkāršu sarakstu","numberedlist":"Numurēts saraksts"},"language":{"button":"Set language","remove":"Remove language"},"indent":{"indent":"Palielināt atkāpi","outdent":"Samazināt atkāpi"},"image2":{"alt":"Alternatīvais teksts","btnUpload":"Nosūtīt serverim","captioned":"Captioned image","captionPlaceholder":"Caption","infoTab":"Informācija par attēlu","lockRatio":"Nemainīga Augstuma/Platuma attiecība","menu":"Attēla īpašības","pathName":"image","pathNameCaption":"caption","resetSize":"Atjaunot sākotnējo izmēru","resizer":"Click and drag to resize","title":"Attēla īpašības","uploadTab":"Augšupielādēt","urlMissing":"Trūkst attēla atrašanās adrese.","altMissing":"Alternative text is missing."},"horizontalrule":{"toolbar":"Ievietot horizontālu Atdalītājsvītru"},"format":{"label":"Formāts","panelTitle":"Formāts","tag_address":"Adrese","tag_div":"Rindkopa (DIV)","tag_h1":"Virsraksts 1","tag_h2":"Virsraksts 2","tag_h3":"Virsraksts 3","tag_h4":"Virsraksts 4","tag_h5":"Virsraksts 5","tag_h6":"Virsraksts 6","tag_p":"Normāls teksts","tag_pre":"Formatēts teksts"},"filetools":{"loadError":"Error occurred during file read.","networkError":"Network error occurred during file upload.","httpError404":"HTTP error occurred during file upload (404: File not found).","httpError403":"HTTP error occurred during file upload (403: Forbidden).","httpError":"HTTP error occurred during file upload (error status: %1).","noUrlError":"Upload URL is not defined.","responseError":"Incorrect server response."},"elementspath":{"eleLabel":"Elementa ceļš","eleTitle":"%1 elements"},"contextmenu":{"options":"Uznirstošās izvēlnes uzstādījumi"},"clipboard":{"copy":"Kopēt","copyError":"Jūsu pārlūkprogrammas drošības iestatījumi nepieļauj redaktoram automātiski veikt kopēšanas darbību. Lūdzu, izmantojiet (Ctrl/Cmd+C), lai veiktu šo darbību.","cut":"Izgriezt","cutError":"Jūsu pārlūkprogrammas drošības iestatījumi nepieļauj redaktoram automātiski veikt izgriezšanas darbību. Lūdzu, izmantojiet (Ctrl/Cmd+X), lai veiktu šo darbību.","paste":"Ielīmēt","pasteNotification":"Press %1 to paste. Your browser doesn‘t support pasting with the toolbar button or context menu option.","pasteArea":"Ielīmēšanas zona","pasteMsg":"Paste your content inside the area below and press OK.","title":"Ievietot"},"button":{"selectedLabel":"%1 (Selected)"},"blockquote":{"toolbar":"Bloka citāts"},"basicstyles":{"bold":"Treknināts","italic":"Kursīvs","strike":"Pārsvītrots","subscript":"Apakšrakstā","superscript":"Augšrakstā","underline":"Pasvītrots"},"about":{"copy":"Kopēšanas tiesības © $1. Visas tiesības rezervētas.","dlgTitle":"Par CKEditor 4","moreInfo":"Informācijai par licenzēšanu apmeklējiet mūsu mājas lapu:"},"editor":"Bagātinātā teksta redaktors","editorPanel":"Bagātinātā teksta redaktora panelis","common":{"editorHelp":"Palīdzībai, nospiediet ALT 0 ","browseServer":"Skatīt servera saturu","url":"URL","protocol":"Protokols","upload":"Augšupielādēt","uploadSubmit":"Nosūtīt serverim","image":"Attēls","flash":"Flash","form":"Forma","checkbox":"Atzīmēšanas kastīte","radio":"Izvēles poga","textField":"Teksta rinda","textarea":"Teksta laukums","hiddenField":"Paslēpta teksta rinda","button":"Poga","select":"Iezīmēšanas lauks","imageButton":"Attēlpoga","notSet":"<nav iestatīts>","id":"Id","name":"Nosaukums","langDir":"Valodas lasīšanas virziens","langDirLtr":"No kreisās uz labo (LTR)","langDirRtl":"No labās uz kreiso (RTL)","langCode":"Valodas kods","longDescr":"Gara apraksta Hipersaite","cssClass":"Stilu saraksta klases","advisoryTitle":"Konsultatīvs virsraksts","cssStyle":"Stils","ok":"Darīts!","cancel":"Atcelt","close":"Aizvērt","preview":"Priekšskatījums","resize":"Mērogot","generalTab":"Vispārīgi","advancedTab":"Izvērstais","validateNumberFailed":"Šī vērtība nav skaitlis","confirmNewPage":"Jebkuras nesaglabātās izmaiņas tiks zaudētas. Vai tiešām vēlaties atvērt jaunu lapu?","confirmCancel":"Daži no uzstādījumiem ir mainīti. Vai tiešām vēlaties aizvērt šo dialogu?","options":"Uzstādījumi","target":"Mērķis","targetNew":"Jauns logs (_blank)","targetTop":"Virsējais logs (_top)","targetSelf":"Tas pats logs (_self)","targetParent":"Avota logs (_parent)","langDirLTR":"Kreisais uz Labo (LTR)","langDirRTL":"Labais uz Kreiso (RTL)","styles":"Stils","cssClasses":"Stilu klases","width":"Platums","height":"Augstums","align":"Nolīdzināt","left":"Pa kreisi","right":"Pa labi","center":"Centrēti","justify":"Izlīdzināt malas","alignLeft":"Izlīdzināt pa kreisi","alignRight":"Izlīdzināt pa labi","alignCenter":"Align Center","alignTop":"Augšā","alignMiddle":"Vertikāli centrēts","alignBottom":"Apakšā","alignNone":"Nekas","invalidValue":"Nekorekta vērtība","invalidHeight":"Augstumam jābūt skaitlim.","invalidWidth":"Platumam jābūt skaitlim","invalidLength":"Laukam \"%1\" norādītajai vērtībai jābūt pozitīvam skaitlim ar vai bez korektām mērvienībām (%2).","invalidCssLength":"Laukam \"%1\" norādītajai vērtībai jābūt pozitīvam skaitlim ar vai bez korektām CSS mērvienībām (px, %, in, cm, mm, em, ex, pt, vai pc).","invalidHtmlLength":"Laukam \"%1\" norādītajai vērtībai jābūt pozitīvam skaitlim ar vai bez korektām HTML mērvienībām (px vai %).","invalidInlineStyle":"Iekļautajā stilā norādītajai vērtībai jāsastāv no viena vai vairākiem pāriem pēc formāta \"nosaukums: vērtība\", atdalītiem ar semikolu.","cssLengthTooltip":"Ievadiet vērtību pikseļos vai skaitli ar derīgu CSS mērvienību (px, %, in, cm, mm, em, ex, pt, vai pc).","unavailable":"%1<span class=\"cke_accessibility\">, nav pieejams</span>","keyboard":{"8":"Backspace","13":"Enter","16":"Shift","17":"Ctrl","18":"Alt","32":"Space","35":"End","36":"Home","46":"Delete","112":"F1","113":"F2","114":"F3","115":"F4","116":"F5","117":"F6","118":"F7","119":"F8","120":"F9","121":"F10","122":"F11","123":"F12","124":"F13","125":"F14","126":"F15","127":"F16","128":"F17","129":"F18","130":"F19","131":"F20","132":"F21","133":"F22","134":"F23","135":"F24","224":"Command"},"keyboardShortcut":"Keyboard shortcut","optionDefault":"Default"}}; \ No newline at end of file +CKEDITOR.lang['lv']={"widget":{"move":"Klikšķina un velc, lai pārvietotu","label":"logrīks %1"},"undo":{"redo":"Atkārtot","undo":"Atcelt"},"toolbar":{"toolbarCollapse":"Aizvērt rīkjoslu","toolbarExpand":"Atvērt rīkjoslu","toolbarGroups":{"document":"Dokuments","clipboard":"Starpliktuve/Atcelt","editing":"Labošana","forms":"Formas","basicstyles":"Pamata stili","paragraph":"Paragrāfs","links":"Saites","insert":"Ievietot","styles":"Stili","colors":"Krāsas","tools":"Rīki"},"toolbars":"Redaktora rīkjoslas"},"table":{"border":"Rāmja izmērs","caption":"Leģenda","cell":{"menu":"Šūna","insertBefore":"Pievienot šūnu pirms","insertAfter":"Pievienot šūnu pēc","deleteCell":"Dzēst rūtiņas","merge":"Apvienot rūtiņas","mergeRight":"Apvieno pa labi","mergeDown":"Apvienot uz leju","splitHorizontal":"Sadalīt šūnu horizontāli","splitVertical":"Sadalīt šūnu vertikāli","title":"Šūnas uzstādījumi","cellType":"Šūnas tips","rowSpan":"Apvienotas rindas","colSpan":"Apvienotas kolonas","wordWrap":"Vārdu pārnese","hAlign":"Horizontālais novietojums","vAlign":"Vertikālais novietojums","alignBaseline":"Pamatrinda","bgColor":"Fona krāsa","borderColor":"Rāmja krāsa","data":"Dati","header":"Virsraksts","yes":"Jā","no":"Nē","invalidWidth":"Šūnas platumam jābūt skaitlim","invalidHeight":"Šūnas augstumam jābūt skaitlim","invalidRowSpan":"Apvienojamo rindu skaitam jābūt veselam skaitlim","invalidColSpan":"Apvienojamo kolonu skaitam jābūt veselam skaitlim","chooseColor":"Izvēlēties"},"cellPad":"Rūtiņu nobīde","cellSpace":"Rūtiņu atstatums","column":{"menu":"Kolonna","insertBefore":"Ievietot kolonu pirms","insertAfter":"Ievieto kolonu pēc","deleteColumn":"Dzēst kolonnas"},"columns":"Kolonnas","deleteTable":"Dzēst tabulu","headers":"Virsraksti","headersBoth":"Abi","headersColumn":"Pirmā kolona","headersNone":"Nekas","headersRow":"Pirmā rinda","invalidBorder":"Rāmju izmēram jābūt skaitlim","invalidCellPadding":"Šūnu atkāpēm jābūt pozitīvam skaitlim","invalidCellSpacing":"Šūnu atstarpēm jābūt pozitīvam skaitlim","invalidCols":"Kolonu skaitam jābūt lielākam par 0","invalidHeight":"Tabulas augstumam jābūt skaitlim","invalidRows":"Rindu skaitam jābūt lielākam par 0","invalidWidth":"Tabulas platumam jābūt skaitlim","menu":"Tabulas īpašības","row":{"menu":"Rinda","insertBefore":"Ievietot rindu pirms","insertAfter":"Ievietot rindu pēc","deleteRow":"Dzēst rindas"},"rows":"Rindas","summary":"Anotācija","title":"Tabulas īpašības","toolbar":"Tabula","widthPc":"procentuāli","widthPx":"pikseļos","widthUnit":"platuma mērvienība"},"stylescombo":{"label":"Stils","panelTitle":"Formatēšanas stili","panelTitle1":"Bloka stili","panelTitle2":"iekļautie stili","panelTitle3":"Objekta stili"},"specialchar":{"options":"Speciālo simbolu uzstādījumi","title":"Ievietot īpašu simbolu","toolbar":"Ievietot speciālo simbolu"},"sourcedialog":{"toolbar":"HTML kods","title":"HTML kods"},"sourcearea":{"toolbar":"HTML kods"},"showblocks":{"toolbar":"Parādīt blokus"},"removeformat":{"toolbar":"Noņemt stilus"},"pastetext":{"button":"Ievietot kā vienkāršu tekstu","pasteNotification":"Nospied %1 lai ielīmētu. Tavs pārlūks neatbalsta ielīmēšanu ar rīkjoslas pogām vai uznirstošās izvēlnes opciju.","title":"Ievietot kā vienkāršu tekstu"},"pastefromword":{"confirmCleanup":"Teksts, kuru vēlaties ielīmēt, izskatās ir nokopēts no Word. Vai vēlaties to iztīrīt pirms ielīmēšanas?","error":"Iekšējas kļūdas dēļ, neizdevās iztīrīt ielīmētos datus.","title":"Ievietot no Worda","toolbar":"Ievietot no Worda"},"notification":{"closed":"Paziņojums aizvērts."},"maximize":{"maximize":"Maksimizēt","minimize":"Minimizēt"},"magicline":{"title":"Ievietot šeit rindkopu"},"list":{"bulletedlist":"Pievienot/Noņemt vienkāršu sarakstu","numberedlist":"Numurēts saraksts"},"language":{"button":"Uzstādīt valodu","remove":"Noņemt valodu"},"indent":{"indent":"Palielināt atkāpi","outdent":"Samazināt atkāpi"},"image2":{"alt":"Alternatīvais teksts","btnUpload":"Nosūtīt serverim","captioned":"Attēls ar parakstu","captionPlaceholder":"Paraksts","infoTab":"Informācija par attēlu","lockRatio":"Nemainīga Augstuma/Platuma attiecība","menu":"Attēla īpašības","pathName":"Attēls","pathNameCaption":"paraksts","resetSize":"Atjaunot sākotnējo izmēru","resizer":"Noklikšķini un pavelc lai mērogotu","title":"Attēla īpašības","uploadTab":"Augšupielādēt","urlMissing":"Trūkst attēla atrašanās adrese.","altMissing":"Trūkst alternatīvais teksts"},"horizontalrule":{"toolbar":"Ievietot horizontālu Atdalītājsvītru"},"format":{"label":"Formāts","panelTitle":"Formāts","tag_address":"Adrese","tag_div":"Rindkopa (DIV)","tag_h1":"Virsraksts 1","tag_h2":"Virsraksts 2","tag_h3":"Virsraksts 3","tag_h4":"Virsraksts 4","tag_h5":"Virsraksts 5","tag_h6":"Virsraksts 6","tag_p":"Normāls teksts","tag_pre":"Formatēts teksts"},"filetools":{"loadError":"Radās kļūda nolasot failu.","networkError":"Radās tīkla kļūda, kamēr tika ielādēts fails.","httpError404":"Ielādējot failu, radās HTTP kļūda (404: Fails nav atrasts)","httpError403":"Ielādējot failu, radās HTTP kļūda (403: Pieeja liegta)","httpError":"Ielādējot failu, radās HTTP kļūda (kļūdas statuss: %1)","noUrlError":"Augšupielādes adrese nav norādīta.","responseError":"Nekorekta servera atbilde."},"elementspath":{"eleLabel":"Elementa ceļš","eleTitle":"%1 elements"},"contextmenu":{"options":"Uznirstošās izvēlnes uzstādījumi"},"clipboard":{"copy":"Kopēt","copyError":"Jūsu pārlūkprogrammas drošības iestatījumi nepieļauj redaktoram automātiski veikt kopēšanas darbību. Lūdzu, izmantojiet (Ctrl/Cmd+C), lai veiktu šo darbību.","cut":"Izgriezt","cutError":"Jūsu pārlūkprogrammas drošības iestatījumi nepieļauj redaktoram automātiski veikt izgriezšanas darbību. Lūdzu, izmantojiet (Ctrl/Cmd+X), lai veiktu šo darbību.","paste":"Ielīmēt","pasteNotification":"Nospied %1 lai ielīmētu. Tavs pārlūks neatbalsta ielīmēšanu ar rīkjoslas pogām vai uznirstošās izvēlnes opciju.","pasteArea":"Ielīmēšanas zona","pasteMsg":"Ielīmē saturu zemāk esošajā laukā un nospied OK.","title":"Ievietot"},"button":{"selectedLabel":"%1 (Atzīmēts)"},"blockquote":{"toolbar":"Bloka citāts"},"basicstyles":{"bold":"Treknināts","italic":"Kursīvs","strike":"Pārsvītrots","subscript":"Apakšrakstā","superscript":"Augšrakstā","underline":"Pasvītrots"},"about":{"copy":"Kopēšanas tiesības © $1. Visas tiesības rezervētas.","dlgTitle":"Par CKEditor 4","moreInfo":"Informācijai par licenzēšanu apmeklējiet mūsu mājas lapu:"},"editor":"Bagātinātā teksta redaktors","editorPanel":"Bagātinātā teksta redaktora panelis","common":{"editorHelp":"Palīdzībai, nospiediet ALT 0 ","browseServer":"Skatīt servera saturu","url":"URL","protocol":"Protokols","upload":"Augšupielādēt","uploadSubmit":"Nosūtīt serverim","image":"Attēls","flash":"Flash","form":"Forma","checkbox":"Atzīmēšanas kastīte","radio":"Izvēles poga","textField":"Teksta rinda","textarea":"Teksta laukums","hiddenField":"Paslēpta teksta rinda","button":"Poga","select":"Iezīmēšanas lauks","imageButton":"Attēlpoga","notSet":"<nav iestatīts>","id":"Id","name":"Nosaukums","langDir":"Valodas lasīšanas virziens","langDirLtr":"No kreisās uz labo (LTR)","langDirRtl":"No labās uz kreiso (RTL)","langCode":"Valodas kods","longDescr":"Gara apraksta Hipersaite","cssClass":"Stilu saraksta klases","advisoryTitle":"Konsultatīvs virsraksts","cssStyle":"Stils","ok":"Darīts!","cancel":"Atcelt","close":"Aizvērt","preview":"Priekšskatījums","resize":"Mērogot","generalTab":"Vispārīgi","advancedTab":"Izvērstais","validateNumberFailed":"Šī vērtība nav skaitlis","confirmNewPage":"Jebkuras nesaglabātās izmaiņas tiks zaudētas. Vai tiešām vēlaties atvērt jaunu lapu?","confirmCancel":"Daži no uzstādījumiem ir mainīti. Vai tiešām vēlaties aizvērt šo dialogu?","options":"Uzstādījumi","target":"Mērķis","targetNew":"Jauns logs (_blank)","targetTop":"Virsējais logs (_top)","targetSelf":"Tas pats logs (_self)","targetParent":"Avota logs (_parent)","langDirLTR":"Kreisais uz Labo (LTR)","langDirRTL":"Labais uz Kreiso (RTL)","styles":"Stils","cssClasses":"Stilu klases","width":"Platums","height":"Augstums","align":"Nolīdzināt","left":"Pa kreisi","right":"Pa labi","center":"Centrēti","justify":"Izlīdzināt malas","alignLeft":"Izlīdzināt pa kreisi","alignRight":"Izlīdzināt pa labi","alignCenter":"Centrēt","alignTop":"Augšā","alignMiddle":"Vertikāli centrēts","alignBottom":"Apakšā","alignNone":"Nekas","invalidValue":"Nekorekta vērtība","invalidHeight":"Augstumam jābūt skaitlim.","invalidWidth":"Platumam jābūt skaitlim","invalidLength":"Laukam \"%1\" norādītajai vērtībai jābūt pozitīvam skaitlim ar vai bez korektām mērvienībām (%2).","invalidCssLength":"Laukam \"%1\" norādītajai vērtībai jābūt pozitīvam skaitlim ar vai bez korektām CSS mērvienībām (px, %, in, cm, mm, em, ex, pt, vai pc).","invalidHtmlLength":"Laukam \"%1\" norādītajai vērtībai jābūt pozitīvam skaitlim ar vai bez korektām HTML mērvienībām (px vai %).","invalidInlineStyle":"Iekļautajā stilā norādītajai vērtībai jāsastāv no viena vai vairākiem pāriem pēc formāta \"nosaukums: vērtība\", atdalītiem ar semikolu.","cssLengthTooltip":"Ievadiet vērtību pikseļos vai skaitli ar derīgu CSS mērvienību (px, %, in, cm, mm, em, ex, pt, vai pc).","unavailable":"%1<span class=\"cke_accessibility\">, nav pieejams</span>","keyboard":{"8":" atkāpšanās taustiņš","13":"Ievadīt","16":"pārslēgšanas taustiņš","17":"vadīšanas taustiņš","18":"alternēšanas taustiņš","32":"Atstarpe","35":"Beigas","36":"Mājup","46":"Dzēst","112":"F1","113":"F2","114":"F3","115":"F4","116":"F5","117":"F6","118":"F7","119":"F8","120":"F9","121":"F10","122":"F11","123":"F12","124":"F13","125":"F14","126":"F15","127":"F16","128":"F17","129":"F18","130":"F19","131":"F20","132":"F21","133":"F22","134":"F23","135":"F24","224":"Komanda"},"keyboardShortcut":"Klaviatūras saīsne","optionDefault":"Noklusēts"}}; \ No newline at end of file diff --git a/web/core/assets/vendor/ckeditor/lang/ro.js b/web/core/assets/vendor/ckeditor/lang/ro.js index bcdc13dc6d66f15101ce338630b8c35abb8bc140..90d1e1aafee6dce73427162ae434f3813724fa7b 100644 --- a/web/core/assets/vendor/ckeditor/lang/ro.js +++ b/web/core/assets/vendor/ckeditor/lang/ro.js @@ -2,4 +2,4 @@ Copyright (c) 2003-2018, CKSource - Frederico Knabben. All rights reserved. For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license */ -CKEDITOR.lang['ro']={"widget":{"move":"Apasă și trage pentru a muta","label":"%1 widget"},"undo":{"redo":"Starea ulterioară (redo)","undo":"Starea anterioară (undo)"},"toolbar":{"toolbarCollapse":"Micșorează Bara","toolbarExpand":"Mărește Bara","toolbarGroups":{"document":"Document","clipboard":"Clipboard/Undo","editing":"Editing","forms":"Forms","basicstyles":"Basic Styles","paragraph":"Paragraph","links":"Links","insert":"Insert","styles":"Styles","colors":"Colors","tools":"Tools"},"toolbars":"Editează bara de unelte"},"table":{"border":"Mărimea marginii","caption":"Titlu (Caption)","cell":{"menu":"Celulă","insertBefore":"Inserează celulă înainte","insertAfter":"Inserează celulă după","deleteCell":"Şterge celule","merge":"Uneşte celule","mergeRight":"Uneşte la dreapta","mergeDown":"Uneşte jos","splitHorizontal":"Împarte celula pe orizontală","splitVertical":"Împarte celula pe verticală","title":"Proprietăți celulă","cellType":"Tipul celulei","rowSpan":"Rows Span","colSpan":"Columns Span","wordWrap":"Word Wrap","hAlign":"Aliniament orizontal","vAlign":"Aliniament vertical","alignBaseline":"Baseline","bgColor":"Culoare fundal","borderColor":"Culoare bordură","data":"Data","header":"Antet","yes":"Da","no":"Nu","invalidWidth":"Lățimea celulei trebuie să fie un număr.","invalidHeight":"Înălțimea celulei trebuie să fie un număr.","invalidRowSpan":"Rows span must be a whole number.","invalidColSpan":"Columns span must be a whole number.","chooseColor":"Alege"},"cellPad":"Spaţiu în cadrul celulei","cellSpace":"Spaţiu între celule","column":{"menu":"Coloană","insertBefore":"Inserează coloană înainte","insertAfter":"Inserează coloană după","deleteColumn":"Şterge celule"},"columns":"Coloane","deleteTable":"Şterge tabel","headers":"Antente","headersBoth":"Ambele","headersColumn":"Prima coloană","headersNone":"Nimic","headersRow":"Primul rând","invalidBorder":"Dimensiunea bordurii trebuie să aibe un număr.","invalidCellPadding":"Spațierea celulei trebuie sa fie un număr pozitiv","invalidCellSpacing":"Spațierea celului trebuie să fie un număr pozitiv.","invalidCols":"Numărul coloanelor trebuie să fie mai mare decât 0.","invalidHeight":"Inaltimea celulei trebuie sa fie un numar.","invalidRows":"Numărul rândurilor trebuie să fie mai mare decât 0.","invalidWidth":"Lățimea tabelului trebuie să fie un număr.","menu":"Proprietăţile tabelului","row":{"menu":"Rând","insertBefore":"Inserează rând înainte","insertAfter":"Inserează rând după","deleteRow":"Şterge rânduri"},"rows":"Rânduri","summary":"Rezumat","title":"Proprietăţile tabelului","toolbar":"Tabel","widthPc":"procente","widthPx":"pixeli","widthUnit":"unitate lățime"},"stylescombo":{"label":"Stil","panelTitle":"Formatare stilurilor","panelTitle1":"Bloc stiluri","panelTitle2":"Stiluri înșiruite","panelTitle3":"Stiluri obiect"},"specialchar":{"options":"Opțiuni caractere speciale","title":"Selectează caracter special","toolbar":"Inserează caracter special"},"sourcedialog":{"toolbar":"Sursa","title":"Sursa"},"sourcearea":{"toolbar":"Sursa"},"showblocks":{"toolbar":"Arată blocurile"},"removeformat":{"toolbar":"Înlătură formatarea"},"pastetext":{"button":"Adaugă ca text simplu (Plain Text)","pasteNotification":"Press %1 to paste. Your browser doesn‘t support pasting with the toolbar button or context menu option.","title":"Adaugă ca text simplu (Plain Text)"},"pastefromword":{"confirmCleanup":"Textul pe care doriți să-l lipiți este din Word. Doriți curățarea textului înante de a-l adăuga?","error":"Nu a fost posibilă curățarea datelor adăugate datorită unei erori interne","title":"Adaugă din Word","toolbar":"Adaugă din Word"},"notification":{"closed":"Notificare închisă."},"maximize":{"maximize":"Mărește","minimize":"Micșorează"},"magicline":{"title":"Inserează paragraf aici"},"list":{"bulletedlist":"Inserează / Elimină Listă cu puncte","numberedlist":"Inserează / Elimină Listă numerotată"},"language":{"button":"Alege limba","remove":"Șterge limba deja selectată"},"indent":{"indent":"Creşte indentarea","outdent":"Scade indentarea"},"image2":{"alt":"Text alternativ","btnUpload":"Încarcă pe server","captioned":"Descris","captionPlaceholder":"Descriere implicită","infoTab":"Informaţii despre imagine","lockRatio":"Păstrează proporţiile","menu":"Proprietăţile imaginii","pathName":"Adresa căii","pathNameCaption":"Descrierea numelui căii","resetSize":"Resetează mărimea","resizer":"Redimensionare dinamică","title":"Proprietăţile imaginii","uploadTab":"Încarcă","urlMissing":"Sursa URL a imaginii lipsește.","altMissing":"Textul alternativ descriptive lipsește!"},"horizontalrule":{"toolbar":"Inserează linie orizontală"},"format":{"label":"Formatare","panelTitle":"Formatare","tag_address":"Adresă","tag_div":"Normal (DIV)","tag_h1":"Heading 1","tag_h2":"Heading 2","tag_h3":"Heading 3","tag_h4":"Heading 4","tag_h5":"Heading 5","tag_h6":"Heading 6","tag_p":"Normal","tag_pre":"Formatat"},"filetools":{"loadError":"Eroare în timpul citirii fișierului.","networkError":"Eroare de rețea în timpul încărcării fișierului.","httpError404":"Eroare HTTP în timpul încărcării fișierului (404: Fișier negăsit).","httpError403":"Eroare HTTP în timpul încărcării fișierului (403: Operașie nepermisă).","httpError":"Eroare HTTP în timpul încărcării fișierului (stare eroiare: %1).","noUrlError":"URL-ul de ăncărcare nu este specificat.","responseError":"Răspuns server incorect."},"elementspath":{"eleLabel":"Calea elementelor","eleTitle":"Nume element"},"contextmenu":{"options":"Opțiuni Meniu Contextual"},"clipboard":{"copy":"Copiază","copyError":"Setările de securitate ale navigatorului (browser) pe care îl folosiţi nu permit editorului să execute automat operaţiunea de copiere. Vă rugăm folosiţi tastatura (Ctrl/Cmd+C).","cut":"Decupează","cutError":"Setările de securitate ale navigatorului (browser) pe care îl folosiţi nu permit editorului să execute automat operaţiunea de tăiere. Vă rugăm folosiţi tastatura (Ctrl/Cmd+X).","paste":"Adaugă din clipboard","pasteNotification":"Press %1 to paste. Your browser doesn‘t support pasting with the toolbar button or context menu option.","pasteArea":"Suprafața de adăugare","pasteMsg":"Paste your content inside the area below and press OK.","title":"Adaugă"},"button":{"selectedLabel":"%1 (Selectat)"},"blockquote":{"toolbar":"Citat"},"basicstyles":{"bold":"Îngroşat (bold)","italic":"Înclinat (italic)","strike":"Tăiat (strike through)","subscript":"Indice (subscript)","superscript":"Putere (superscript)","underline":"Subliniat (underline)"},"about":{"copy":"Copyright © $1. Toate drepturile rezervate.","dlgTitle":"Despre CKEeditor 4","moreInfo":"Pentru informații despre licențiere, vă rugăm vizitați web site-ul nostru:"},"editor":"Editor de text îmbogățit","editorPanel":"Panoul editorului de text îmbogățit","common":{"editorHelp":"Apasă ALT 0 pentru ajutor","browseServer":"Răsfoiește fișiere","url":"URL","protocol":"Protocol","upload":"Încarcă","uploadSubmit":"Trimite la server","image":"Imagine","flash":"Flash","form":"Formular (Form)","checkbox":"Bifă (Checkbox)","radio":"Buton radio (RadioButton)","textField":"Câmp text (TextField)","textarea":"Suprafaţă text (Textarea)","hiddenField":"Câmp ascuns (HiddenField)","button":"Buton","select":"Câmp selecţie (SelectionField)","imageButton":"Buton imagine (ImageButton)","notSet":"fără setări","id":"identificator","name":"Nume","langDir":"Direcţia cuvintelor","langDirLtr":"de la stânga la dreapta (LTR)","langDirRtl":"de la dreapta la stânga (RTL)","langCode":"Codul limbii","longDescr":"Descrierea completă URL","cssClass":"Clasele cu stilul paginii (CSS)","advisoryTitle":"Titlul consultativ","cssStyle":"Stil","ok":"OK","cancel":"Anulare","close":"Închide","preview":"Previzualizare","resize":"Redimensionează","generalTab":"General","advancedTab":"Avansat","validateNumberFailed":"Această valoare nu este un număr!","confirmNewPage":"Orice modificări nesalvate ale acestui conținut, vor fi pierdute. Sigur doriți încărcarea unei noi pagini?","confirmCancel":"Ai schimbat câteva opțiuni. Ești sigur că dorești să închiz fereastra de dialog?","options":"Opțiuni","target":"Țintă","targetNew":"Fereastră nouă (_blank)","targetTop":"Topmost Window (_top)","targetSelf":"În aceeași fereastră (_self)","targetParent":"Parent Window (_parent)","langDirLTR":"Stânga spre Dreapta (LTR)","langDirRTL":"Dreapta spre Stânga (RTL)","styles":"Stil","cssClasses":"Clase foaie de stil","width":"Lăţime","height":"Înălţime","align":"Aliniere","left":"Aliniază la stânga","right":"Aliniază la dreapta","center":"Aliniază pe centru","justify":"Aliniere în bloc (Justify)","alignLeft":"Aliniere la stânga","alignRight":"Aliniere la dreapta","alignCenter":"Aliniere centru","alignTop":"Aliniere sus","alignMiddle":"Aliniere la mijloc","alignBottom":"Aliniere jos","alignNone":"Fără aliniere","invalidValue":"Valoare invalidă","invalidHeight":"Înălțimea trebuie să fie un număr.","invalidWidth":"Lățimea trebuie să fie un număr.","invalidLength":"Valoarea specificată pentru câmpul \"%1\" trebuie să fie un număr pozitiv cu sau fără o unitate de măsură validă (%2).","invalidCssLength":"Valoarea specificată pentru câmpul \"%1\" trebuie să fie un număr pozitiv cu sau fără o unitate de măsură validă CSS (px, %, in, cm, mm, em, ex, pt, sau pc).","invalidHtmlLength":"Valoarea specificată pentru câmpul \"%1\" trebuie să fie un număr pozitiv cu sau fără o unitate de măsură validă HTML (px sau %).","invalidInlineStyle":"Valoarea specificată pentru stil trebuie să conțină una sau mai multe construcții de tipul \"name : value\", separate prin punct și virgulă.","cssLengthTooltip":"Introdu un număr pentru o valoare în pixeli sau un număr pentru o unitate de măsură validă CSS (px, %, in, cm, mm, em, ex, pt, sau pc).","unavailable":"%1<span class=\"cke_accessibility\">, nu este disponibil</span>","keyboard":{"8":"Backspace","13":"Enter","16":"Shift","17":"Ctrl","18":"Alt","32":"Bară spațiu","35":"End","36":"Home","46":"Delete","112":"F1","113":"F2","114":"F3","115":"F4","116":"F5","117":"F6","118":"F7","119":"F8","120":"F9","121":"F10","122":"F11","123":"F12","124":"F13","125":"F14","126":"F15","127":"F16","128":"F17","129":"F18","130":"F19","131":"F20","132":"F21","133":"F22","134":"F23","135":"F24","224":"Command"},"keyboardShortcut":"Scurtături tastatură","optionDefault":"Implicit"}}; \ No newline at end of file +CKEDITOR.lang['ro']={"widget":{"move":"Apasă și trage pentru a muta","label":"%1 widget"},"undo":{"redo":"Starea ulterioară (redo)","undo":"Starea anterioară (undo)"},"toolbar":{"toolbarCollapse":"Micșorează Bara","toolbarExpand":"Mărește Bara","toolbarGroups":{"document":"Document","clipboard":"Clipboard/Undo","editing":"Editing","forms":"Forms","basicstyles":"Basic Styles","paragraph":"Paragraph","links":"Links","insert":"Insert","styles":"Styles","colors":"Colors","tools":"Tools"},"toolbars":"Editează bara de unelte"},"table":{"border":"Mărimea marginii","caption":"Titlu (Caption)","cell":{"menu":"Celulă","insertBefore":"Inserează celulă înainte","insertAfter":"Inserează celulă după","deleteCell":"Şterge celule","merge":"Uneşte celule","mergeRight":"Uneşte la dreapta","mergeDown":"Uneşte jos","splitHorizontal":"Împarte celula pe orizontală","splitVertical":"Împarte celula pe verticală","title":"Proprietăți celulă","cellType":"Tipul celulei","rowSpan":"Rows Span","colSpan":"Columns Span","wordWrap":"Word Wrap","hAlign":"Aliniament orizontal","vAlign":"Aliniament vertical","alignBaseline":"Baseline","bgColor":"Culoare fundal","borderColor":"Culoare bordură","data":"Data","header":"Antet","yes":"Da","no":"Nu","invalidWidth":"Lățimea celulei trebuie să fie un număr.","invalidHeight":"Înălțimea celulei trebuie să fie un număr.","invalidRowSpan":"Rows span must be a whole number.","invalidColSpan":"Columns span must be a whole number.","chooseColor":"Alege"},"cellPad":"Spaţiu în cadrul celulei","cellSpace":"Spaţiu între celule","column":{"menu":"Coloană","insertBefore":"Inserează coloană înainte","insertAfter":"Inserează coloană după","deleteColumn":"Şterge celule"},"columns":"Coloane","deleteTable":"Şterge tabel","headers":"Antente","headersBoth":"Ambele","headersColumn":"Prima coloană","headersNone":"Nimic","headersRow":"Primul rând","invalidBorder":"Dimensiunea bordurii trebuie să aibe un număr.","invalidCellPadding":"Spațierea celulei trebuie sa fie un număr pozitiv","invalidCellSpacing":"Spațierea celului trebuie să fie un număr pozitiv.","invalidCols":"Numărul coloanelor trebuie să fie mai mare decât 0.","invalidHeight":"Inaltimea celulei trebuie sa fie un numar.","invalidRows":"Numărul rândurilor trebuie să fie mai mare decât 0.","invalidWidth":"Lățimea tabelului trebuie să fie un număr.","menu":"Proprietăţile tabelului","row":{"menu":"Rând","insertBefore":"Inserează rând înainte","insertAfter":"Inserează rând după","deleteRow":"Şterge rânduri"},"rows":"Rânduri","summary":"Rezumat","title":"Proprietăţile tabelului","toolbar":"Tabel","widthPc":"procente","widthPx":"pixeli","widthUnit":"unitate lățime"},"stylescombo":{"label":"Stil","panelTitle":"Formatare stilurilor","panelTitle1":"Bloc stiluri","panelTitle2":"Stiluri înșiruite","panelTitle3":"Stiluri obiect"},"specialchar":{"options":"Opțiuni caractere speciale","title":"Selectează caracter special","toolbar":"Inserează caracter special"},"sourcedialog":{"toolbar":"Sursa","title":"Sursa"},"sourcearea":{"toolbar":"Sursa"},"showblocks":{"toolbar":"Arată blocurile"},"removeformat":{"toolbar":"Înlătură formatarea"},"pastetext":{"button":"Adaugă ca text simplu (Plain Text)","pasteNotification":"Press %1 to paste. Your browser doesn‘t support pasting with the toolbar button or context menu option.","title":"Adaugă ca text simplu (Plain Text)"},"pastefromword":{"confirmCleanup":"Textul pe care doriți să-l lipiți este din Word. Doriți curățarea textului înante de a-l adăuga?","error":"Nu a fost posibilă curățarea datelor adăugate datorită unei erori interne","title":"Adaugă din Word","toolbar":"Adaugă din Word"},"notification":{"closed":"Notificare închisă."},"maximize":{"maximize":"Mărește","minimize":"Micșorează"},"magicline":{"title":"Inserează paragraf aici"},"list":{"bulletedlist":"Inserează / Elimină Listă cu puncte","numberedlist":"Inserează / Elimină Listă numerotată"},"language":{"button":"Alege limba","remove":"Șterge limba deja selectată"},"indent":{"indent":"Creşte indentarea","outdent":"Scade indentarea"},"image2":{"alt":"Text alternativ","btnUpload":"Încarcă pe server","captioned":"Descris","captionPlaceholder":"Descriere implicită","infoTab":"Informaţii despre imagine","lockRatio":"Păstrează proporţiile","menu":"Proprietăţile imaginii","pathName":"Adresa căii","pathNameCaption":"Descrierea numelui căii","resetSize":"Resetează mărimea","resizer":"Redimensionare dinamică","title":"Proprietăţile imaginii","uploadTab":"Încarcă","urlMissing":"Sursa URL a imaginii lipsește.","altMissing":"Textul alternativ descriptive lipsește!"},"horizontalrule":{"toolbar":"Inserează linie orizontală"},"format":{"label":"Formatare","panelTitle":"Formatare","tag_address":"Adresă","tag_div":"Normal (DIV)","tag_h1":"Heading 1","tag_h2":"Heading 2","tag_h3":"Heading 3","tag_h4":"Heading 4","tag_h5":"Heading 5","tag_h6":"Heading 6","tag_p":"Normal","tag_pre":"Formatat"},"filetools":{"loadError":"Eroare în timpul citirii fișierului.","networkError":"Eroare de rețea în timpul încărcării fișierului.","httpError404":"Eroare HTTP în timpul încărcării fișierului (404: Fișier negăsit).","httpError403":"Eroare HTTP în timpul încărcării fișierului (403: Operașie nepermisă).","httpError":"Eroare HTTP în timpul încărcării fișierului (stare eroiare: %1).","noUrlError":"URL-ul de ăncărcare nu este specificat.","responseError":"Răspuns server incorect."},"elementspath":{"eleLabel":"Calea elementelor","eleTitle":"Nume element"},"contextmenu":{"options":"Opțiuni Meniu Contextual"},"clipboard":{"copy":"Copiază","copyError":"Setările de securitate ale navigatorului (browser) pe care îl folosiţi nu permit editorului să execute automat operaţiunea de copiere. Vă rugăm folosiţi tastatura (Ctrl/Cmd+C).","cut":"Tăiere","cutError":"Setările de securitate ale navigatorului (browser) pe care îl folosiţi nu permit editorului să execute automat operaţiunea de tăiere. Vă rugăm folosiţi tastatura (Ctrl/Cmd+X).","paste":"Adaugă din clipboard","pasteNotification":"Apasă %1 pentru adăugare. Navigatorul (browser) tău nu suportă adăugarea din clipboard cu butonul din toolbar sau cu opțiunea din meniul contextual.","pasteArea":"Suprafața de adăugare","pasteMsg":"Adaugă conținutul tău înăuntru zonei de mai jos și apasă OK.","title":"Adaugă"},"button":{"selectedLabel":"%1 (Selectat)"},"blockquote":{"toolbar":"Citat"},"basicstyles":{"bold":"Îngroşat (bold)","italic":"Înclinat (italic)","strike":"Tăiat (strike through)","subscript":"Indice (subscript)","superscript":"Putere (superscript)","underline":"Subliniat (underline)"},"about":{"copy":"Copyright © $1. Toate drepturile rezervate.","dlgTitle":"Despre CKEeditor 4","moreInfo":"Pentru informații despre licențiere, vă rugăm vizitați web site-ul nostru:"},"editor":"Editor de text îmbogățit","editorPanel":"Panoul editorului de text îmbogățit","common":{"editorHelp":"Apasă ALT 0 pentru ajutor","browseServer":"Răsfoiește fișiere","url":"URL","protocol":"Protocol","upload":"Încarcă","uploadSubmit":"Trimite la server","image":"Imagine","flash":"Flash","form":"Formular (Form)","checkbox":"Bifă (Checkbox)","radio":"Buton radio (RadioButton)","textField":"Câmp text (TextField)","textarea":"Suprafaţă text (Textarea)","hiddenField":"Câmp ascuns (HiddenField)","button":"Buton","select":"Câmp selecţie (SelectionField)","imageButton":"Buton imagine (ImageButton)","notSet":"fără setări","id":"identificator","name":"Nume","langDir":"Direcţia cuvintelor","langDirLtr":"de la stânga la dreapta (LTR)","langDirRtl":"de la dreapta la stânga (RTL)","langCode":"Codul limbii","longDescr":"Descrierea completă URL","cssClass":"Clasele cu stilul paginii (CSS)","advisoryTitle":"Titlul consultativ","cssStyle":"Stil","ok":"OK","cancel":"Anulare","close":"Închide","preview":"Previzualizare","resize":"Redimensionează","generalTab":"General","advancedTab":"Avansat","validateNumberFailed":"Această valoare nu este un număr!","confirmNewPage":"Orice modificări nesalvate ale acestui conținut, vor fi pierdute. Sigur doriți încărcarea unei noi pagini?","confirmCancel":"Ai schimbat câteva opțiuni. Ești sigur că dorești să închiz fereastra de dialog?","options":"Opțiuni","target":"Țintă","targetNew":"Fereastră nouă (_blank)","targetTop":"Topmost Window (_top)","targetSelf":"În aceeași fereastră (_self)","targetParent":"Parent Window (_parent)","langDirLTR":"Stânga spre Dreapta (LTR)","langDirRTL":"Dreapta spre Stânga (RTL)","styles":"Stil","cssClasses":"Clase foaie de stil","width":"Lăţime","height":"Înălţime","align":"Aliniere","left":"Aliniază la stânga","right":"Aliniază la dreapta","center":"Aliniază pe centru","justify":"Aliniere în bloc (Justify)","alignLeft":"Aliniere la stânga","alignRight":"Aliniere la dreapta","alignCenter":"Aliniere centru","alignTop":"Aliniere sus","alignMiddle":"Aliniere la mijloc","alignBottom":"Aliniere jos","alignNone":"Fără aliniere","invalidValue":"Valoare invalidă","invalidHeight":"Înălțimea trebuie să fie un număr.","invalidWidth":"Lățimea trebuie să fie un număr.","invalidLength":"Valoarea specificată pentru câmpul \"%1\" trebuie să fie un număr pozitiv cu sau fără o unitate de măsură validă (%2).","invalidCssLength":"Valoarea specificată pentru câmpul \"%1\" trebuie să fie un număr pozitiv cu sau fără o unitate de măsură validă CSS (px, %, in, cm, mm, em, ex, pt, sau pc).","invalidHtmlLength":"Valoarea specificată pentru câmpul \"%1\" trebuie să fie un număr pozitiv cu sau fără o unitate de măsură validă HTML (px sau %).","invalidInlineStyle":"Valoarea specificată pentru stil trebuie să conțină una sau mai multe construcții de tipul \"name : value\", separate prin punct și virgulă.","cssLengthTooltip":"Introdu un număr pentru o valoare în pixeli sau un număr pentru o unitate de măsură validă CSS (px, %, in, cm, mm, em, ex, pt, sau pc).","unavailable":"%1<span class=\"cke_accessibility\">, nu este disponibil</span>","keyboard":{"8":"Backspace","13":"Enter","16":"Shift","17":"Ctrl","18":"Alt","32":"Bară spațiu","35":"End","36":"Home","46":"Delete","112":"F1","113":"F2","114":"F3","115":"F4","116":"F5","117":"F6","118":"F7","119":"F8","120":"F9","121":"F10","122":"F11","123":"F12","124":"F13","125":"F14","126":"F15","127":"F16","128":"F17","129":"F18","130":"F19","131":"F20","132":"F21","133":"F22","134":"F23","135":"F24","224":"Command"},"keyboardShortcut":"Scurtături tastatură","optionDefault":"Implicit"}}; \ No newline at end of file diff --git a/web/core/assets/vendor/ckeditor/lang/sk.js b/web/core/assets/vendor/ckeditor/lang/sk.js index 7a3498f5e079d7b4ea4272cca236fb7dc231b725..43881e12e78efc15dd8b5501f3717247499cd942 100644 --- a/web/core/assets/vendor/ckeditor/lang/sk.js +++ b/web/core/assets/vendor/ckeditor/lang/sk.js @@ -2,4 +2,4 @@ Copyright (c) 2003-2018, CKSource - Frederico Knabben. All rights reserved. For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license */ -CKEDITOR.lang['sk']={"widget":{"move":"Kliknite a potiahnite pre presunutie","label":"%1 widget"},"undo":{"redo":"Znovu","undo":"Späť"},"toolbar":{"toolbarCollapse":"Zbaliť lištu nástrojov","toolbarExpand":"Rozbaliť lištu nástrojov","toolbarGroups":{"document":"Dokument","clipboard":"Schránka pre kopírovanie/Späť","editing":"Upravovanie","forms":"Formuláre","basicstyles":"Základné štýly","paragraph":"Odsek","links":"Odkazy","insert":"Vložiť","styles":"Štýly","colors":"Farby","tools":"Nástroje"},"toolbars":"Lišty nástrojov editora"},"table":{"border":"Šírka orámovania","caption":"Popis","cell":{"menu":"Bunka","insertBefore":"Vložiť bunku pred","insertAfter":"Vložiť bunku za","deleteCell":"Vymazať bunky","merge":"Zlúčiť bunky","mergeRight":"Zlúčiť doprava","mergeDown":"Zlúčiť dole","splitHorizontal":"Rozdeliť bunky horizontálne","splitVertical":"Rozdeliť bunky vertikálne","title":"Vlastnosti bunky","cellType":"Typ bunky","rowSpan":"Rozsah riadkov","colSpan":"Rozsah stĺpcov","wordWrap":"Zalamovanie riadkov","hAlign":"Horizontálne zarovnanie","vAlign":"Vertikálne zarovnanie","alignBaseline":"Základná čiara (baseline)","bgColor":"Farba pozadia","borderColor":"Farba orámovania","data":"Dáta","header":"Hlavička","yes":"Áno","no":"Nie","invalidWidth":"Šírka bunky musí byť číslo.","invalidHeight":"Výška bunky musí byť číslo.","invalidRowSpan":"Rozsah riadkov musí byť celé číslo.","invalidColSpan":"Rozsah stĺpcov musí byť celé číslo.","chooseColor":"Vybrať"},"cellPad":"Odsadenie obsahu (cell padding)","cellSpace":"Vzdialenosť buniek (cell spacing)","column":{"menu":"Stĺpec","insertBefore":"Vložiť stĺpec pred","insertAfter":"Vložiť stĺpec po","deleteColumn":"Zmazať stĺpce"},"columns":"Stĺpce","deleteTable":"Vymazať tabuľku","headers":"Hlavička","headersBoth":"Obe","headersColumn":"Prvý stĺpec","headersNone":"Žiadne","headersRow":"Prvý riadok","invalidBorder":"Šírka orámovania musí byť číslo.","invalidCellPadding":"Odsadenie v bunkách (cell padding) musí byť kladné číslo.","invalidCellSpacing":"Medzera mädzi bunkami (cell spacing) musí byť kladné číslo.","invalidCols":"Počet stĺpcov musí byť číslo väčšie ako 0.","invalidHeight":"Výška tabuľky musí byť číslo.","invalidRows":"Počet riadkov musí byť číslo väčšie ako 0.","invalidWidth":"Širka tabuľky musí byť číslo.","menu":"Vlastnosti tabuľky","row":{"menu":"Riadok","insertBefore":"Vložiť riadok pred","insertAfter":"Vložiť riadok po","deleteRow":"Vymazať riadky"},"rows":"Riadky","summary":"Prehľad","title":"Vlastnosti tabuľky","toolbar":"Tabuľka","widthPc":"percent","widthPx":"pixelov","widthUnit":"jednotka šírky"},"stylescombo":{"label":"Štýly","panelTitle":"Formátovanie štýlov","panelTitle1":"Štýly bloku","panelTitle2":"Znakové štýly","panelTitle3":"Štýly objeku"},"specialchar":{"options":"Možnosti špeciálneho znaku","title":"Výber špeciálneho znaku","toolbar":"Vložiť špeciálny znak"},"sourcedialog":{"toolbar":"Zdroj","title":"Zdroj"},"sourcearea":{"toolbar":"Zdroj"},"showblocks":{"toolbar":"Ukázať bloky"},"removeformat":{"toolbar":"Odstrániť formátovanie"},"pastetext":{"button":"Vložiť ako čistý text","pasteNotification":"Press %1 to paste. Your browser doesn‘t support pasting with the toolbar button or context menu option.","title":"Vložiť ako čistý text"},"pastefromword":{"confirmCleanup":"Zdá sa, že vkladaný text pochádza z programu MS Word. Chcete ho pred vkladaním automaticky vyčistiť?","error":"Kvôli internej chybe nebolo možné vložené dáta vyčistiť","title":"Vložiť z Wordu","toolbar":"Vložiť z Wordu"},"notification":{"closed":"Notifikácia zatvorená."},"maximize":{"maximize":"Maximalizovať","minimize":"Minimalizovať"},"magicline":{"title":"Odsek vložiť sem"},"list":{"bulletedlist":"Vložiť/odstrániť zoznam s odrážkami","numberedlist":"Vložiť/odstrániť číslovaný zoznam"},"language":{"button":"Nastaviť jazyk","remove":"Odstrániť jazyk"},"indent":{"indent":"Zväčšiť odsadenie","outdent":"Zmenšiť odsadenie"},"image2":{"alt":"Alternatívny text","btnUpload":"Odoslať to na server","captioned":"Opísaný obrázok","captionPlaceholder":"Popis","infoTab":"Informácie o obrázku","lockRatio":"Pomer zámky","menu":"Vlastnosti obrázka","pathName":"obrázok","pathNameCaption":"popis","resetSize":"Pôvodná veľkosť","resizer":"Kliknite a potiahnite pre zmenu veľkosti","title":"Vlastnosti obrázka","uploadTab":"Nahrať","urlMissing":"Chýba URL zdroja obrázka.","altMissing":"Chýba alternatívny text."},"horizontalrule":{"toolbar":"Vložiť vodorovnú čiaru"},"format":{"label":"Formát","panelTitle":"Odsek","tag_address":"Adresa","tag_div":"Normálny (DIV)","tag_h1":"Nadpis 1","tag_h2":"Nadpis 2","tag_h3":"Nadpis 3","tag_h4":"Nadpis 4","tag_h5":"Nadpis 5","tag_h6":"Nadpis 6","tag_p":"Normálny","tag_pre":"Formátovaný"},"filetools":{"loadError":"Počas čítania súboru nastala chyba.","networkError":"Počas nahrávania súboru nastala chyba siete.","httpError404":"Počas nahrávania súboru nastala HTTP chyba (404: Súbor nebol nájdený).","httpError403":"Počas nahrávania súboru nastala HTTP chyba (403: Zakázaný).","httpError":"Počas nahrávania súboru nastala HTTP chyba (error status: %1).","noUrlError":"URL nahrávania nie je definovaný.","responseError":"Nesprávna odpoveď servera."},"elementspath":{"eleLabel":"Cesta prvkov","eleTitle":"%1 prvok"},"contextmenu":{"options":"Možnosti kontextového menu"},"clipboard":{"copy":"Kopírovať","copyError":"Bezpečnostné nastavenia vášho prehliadača nedovoľujú editoru automaticky spustiť operáciu kopírovania. Použite na to klávesnicu (Ctrl/Cmd+C).","cut":"Vystrihnúť","cutError":"Bezpečnostné nastavenia vášho prehliadača nedovoľujú editoru automaticky spustiť operáciu vystrihnutia. Použite na to klávesnicu (Ctrl/Cmd+X).","paste":"Vložiť","pasteNotification":"Stlačte %1 na vloženie. Váš prehliadač nepodporuje vloženie prostredníctvom tlačidla v nástrojovej lište alebo voľby v kontextovom menu.","pasteArea":"Miesto pre vloženie","pasteMsg":"Vložte svoj obsah do nasledujúcej oblasti a stlačte OK.","title":"Vložiť"},"button":{"selectedLabel":"%1 (Vybrané)"},"blockquote":{"toolbar":"Citácia"},"basicstyles":{"bold":"Tučné","italic":"Kurzíva","strike":"Prečiarknuté","subscript":"Dolný index","superscript":"Horný index","underline":"Podčiarknuté"},"about":{"copy":"Copyright © $1. Všetky práva vyhradené.","dlgTitle":"O aplikácii CKEditor 4","moreInfo":"Pre informácie o licenciách, prosíme, navštívte našu web stránku:"},"editor":"Editor formátovaného textu","editorPanel":"Panel editora formátovaného textu","common":{"editorHelp":"Stlačením ALT 0 spustiť pomocníka","browseServer":"Prehliadať server","url":"URL","protocol":"Protokol","upload":"Odoslať","uploadSubmit":"Odoslať na server","image":"Obrázok","flash":"Flash","form":"Formulár","checkbox":"Zaškrtávacie pole","radio":"Prepínač","textField":"Textové pole","textarea":"Textová oblasť","hiddenField":"Skryté pole","button":"Tlačidlo","select":"Rozbaľovací zoznam","imageButton":"Obrázkové tlačidlo","notSet":"<nenastavené>","id":"Id","name":"Meno","langDir":"Orientácia jazyka","langDirLtr":"Zľava doprava (LTR)","langDirRtl":"Sprava doľava (RTL)","langCode":"Kód jazyka","longDescr":"Dlhý popis URL","cssClass":"Trieda štýlu","advisoryTitle":"Pomocný titulok","cssStyle":"Štýl","ok":"OK","cancel":"Zrušiť","close":"Zatvoriť","preview":"Náhľad","resize":"Zmeniť veľkosť","generalTab":"Hlavné","advancedTab":"Rozšírené","validateNumberFailed":"Hodnota nie je číslo.","confirmNewPage":"Prajete si načítat novú stránku? Všetky neuložené zmeny budú stratené. ","confirmCancel":"Niektore možnosti boli zmenené. Naozaj chcete zavrieť okno?","options":"Možnosti","target":"Cieľ","targetNew":"Nové okno (_blank)","targetTop":"Najvrchnejšie okno (_top)","targetSelf":"To isté okno (_self)","targetParent":"Rodičovské okno (_parent)","langDirLTR":"Zľava doprava (LTR)","langDirRTL":"Sprava doľava (RTL)","styles":"Štýl","cssClasses":"Triedy štýlu","width":"Šírka","height":"Výška","align":"Zarovnanie","left":"Vľavo","right":"Vpravo","center":"Na stred","justify":"Do bloku","alignLeft":"Zarovnať vľavo","alignRight":"Zarovnať vpravo","alignCenter":"Zarovnať na stred","alignTop":"Nahor","alignMiddle":"Na stred","alignBottom":"Dole","alignNone":"Žiadne","invalidValue":"Neplatná hodnota.","invalidHeight":"Výška musí byť číslo.","invalidWidth":"Šírka musí byť číslo.","invalidLength":"Hodnota uvedená v poli \"%1\" musí byť kladné číslo a s platnou mernou jednotkou (%2), alebo bez nej.","invalidCssLength":"Špecifikovaná hodnota pre pole \"%1\" musí byť kladné číslo s alebo bez platnej CSS mernej jednotky (px, %, in, cm, mm, em, ex, pt alebo pc).","invalidHtmlLength":"Špecifikovaná hodnota pre pole \"%1\" musí byť kladné číslo s alebo bez platnej HTML mernej jednotky (px alebo %).","invalidInlineStyle":"Zadaná hodnota pre inline štýl musí pozostávať s jedného, alebo viac dvojíc formátu \"názov: hodnota\", oddelených bodkočiarkou.","cssLengthTooltip":"Vložte číslo pre hodnotu v pixeloch alebo číslo so správnou CSS jednotou (px, %, in, cm, mm, em, ex, pt alebo pc).","unavailable":"%1<span class=\"cke_accessibility\">, nedostupný</span>","keyboard":{"8":"Backspace","13":"Enter","16":"Shift","17":"Ctrl","18":"Alt","32":"Medzerník","35":"End","36":"Home","46":"Delete","112":"F1","113":"F2","114":"F3","115":"F4","116":"F5","117":"F6","118":"F7","119":"F8","120":"F9","121":"F10","122":"F11","123":"F12","124":"F13","125":"F14","126":"F15","127":"F16","128":"F17","129":"F18","130":"F19","131":"F20","132":"F21","133":"F22","134":"F23","135":"F24","224":"Command"},"keyboardShortcut":"Klávesová skratka","optionDefault":"Predvolený"}}; \ No newline at end of file +CKEDITOR.lang['sk']={"widget":{"move":"Kliknite a potiahnite pre presunutie","label":"%1 widget"},"undo":{"redo":"Znovu","undo":"Späť"},"toolbar":{"toolbarCollapse":"Zbaliť lištu nástrojov","toolbarExpand":"Rozbaliť lištu nástrojov","toolbarGroups":{"document":"Dokument","clipboard":"Schránka pre kopírovanie/Späť","editing":"Upravovanie","forms":"Formuláre","basicstyles":"Základné štýly","paragraph":"Odsek","links":"Odkazy","insert":"Vložiť","styles":"Štýly","colors":"Farby","tools":"Nástroje"},"toolbars":"Lišty nástrojov editora"},"table":{"border":"Šírka orámovania","caption":"Popis","cell":{"menu":"Bunka","insertBefore":"Vložiť bunku pred","insertAfter":"Vložiť bunku za","deleteCell":"Vymazať bunky","merge":"Zlúčiť bunky","mergeRight":"Zlúčiť doprava","mergeDown":"Zlúčiť dole","splitHorizontal":"Rozdeliť bunky horizontálne","splitVertical":"Rozdeliť bunky vertikálne","title":"Vlastnosti bunky","cellType":"Typ bunky","rowSpan":"Rozsah riadkov","colSpan":"Rozsah stĺpcov","wordWrap":"Zalamovanie riadkov","hAlign":"Horizontálne zarovnanie","vAlign":"Vertikálne zarovnanie","alignBaseline":"Základná čiara (baseline)","bgColor":"Farba pozadia","borderColor":"Farba orámovania","data":"Dáta","header":"Hlavička","yes":"Áno","no":"Nie","invalidWidth":"Šírka bunky musí byť číslo.","invalidHeight":"Výška bunky musí byť číslo.","invalidRowSpan":"Rozsah riadkov musí byť celé číslo.","invalidColSpan":"Rozsah stĺpcov musí byť celé číslo.","chooseColor":"Vybrať"},"cellPad":"Odsadenie obsahu (cell padding)","cellSpace":"Vzdialenosť buniek (cell spacing)","column":{"menu":"Stĺpec","insertBefore":"Vložiť stĺpec pred","insertAfter":"Vložiť stĺpec po","deleteColumn":"Zmazať stĺpce"},"columns":"Stĺpce","deleteTable":"Vymazať tabuľku","headers":"Hlavička","headersBoth":"Obe","headersColumn":"Prvý stĺpec","headersNone":"Žiadne","headersRow":"Prvý riadok","invalidBorder":"Šírka orámovania musí byť číslo.","invalidCellPadding":"Odsadenie v bunkách (cell padding) musí byť kladné číslo.","invalidCellSpacing":"Medzera mädzi bunkami (cell spacing) musí byť kladné číslo.","invalidCols":"Počet stĺpcov musí byť číslo väčšie ako 0.","invalidHeight":"Výška tabuľky musí byť číslo.","invalidRows":"Počet riadkov musí byť číslo väčšie ako 0.","invalidWidth":"Širka tabuľky musí byť číslo.","menu":"Vlastnosti tabuľky","row":{"menu":"Riadok","insertBefore":"Vložiť riadok pred","insertAfter":"Vložiť riadok po","deleteRow":"Vymazať riadky"},"rows":"Riadky","summary":"Prehľad","title":"Vlastnosti tabuľky","toolbar":"Tabuľka","widthPc":"percent","widthPx":"pixelov","widthUnit":"jednotka šírky"},"stylescombo":{"label":"Štýly","panelTitle":"Formátovanie štýlov","panelTitle1":"Štýly bloku","panelTitle2":"Znakové štýly","panelTitle3":"Štýly objektu"},"specialchar":{"options":"Možnosti špeciálneho znaku","title":"Výber špeciálneho znaku","toolbar":"Vložiť špeciálny znak"},"sourcedialog":{"toolbar":"Zdroj","title":"Zdroj"},"sourcearea":{"toolbar":"Zdroj"},"showblocks":{"toolbar":"Ukázať bloky"},"removeformat":{"toolbar":"Odstrániť formátovanie"},"pastetext":{"button":"Vložiť ako čistý text","pasteNotification":"Press %1 to paste. Your browser doesn‘t support pasting with the toolbar button or context menu option.","title":"Vložiť ako čistý text"},"pastefromword":{"confirmCleanup":"Zdá sa, že vkladaný text pochádza z programu MS Word. Chcete ho pred vkladaním automaticky vyčistiť?","error":"Kvôli internej chybe nebolo možné vložené dáta vyčistiť","title":"Vložiť z Wordu","toolbar":"Vložiť z Wordu"},"notification":{"closed":"Notifikácia zatvorená."},"maximize":{"maximize":"Maximalizovať","minimize":"Minimalizovať"},"magicline":{"title":"Odsek vložiť sem"},"list":{"bulletedlist":"Vložiť/odstrániť zoznam s odrážkami","numberedlist":"Vložiť/odstrániť číslovaný zoznam"},"language":{"button":"Nastaviť jazyk","remove":"Odstrániť jazyk"},"indent":{"indent":"Zväčšiť odsadenie","outdent":"Zmenšiť odsadenie"},"image2":{"alt":"Alternatívny text","btnUpload":"Odoslať to na server","captioned":"Opísaný obrázok","captionPlaceholder":"Popis","infoTab":"Informácie o obrázku","lockRatio":"Pomer zámky","menu":"Vlastnosti obrázka","pathName":"obrázok","pathNameCaption":"popis","resetSize":"Pôvodná veľkosť","resizer":"Kliknite a potiahnite pre zmenu veľkosti","title":"Vlastnosti obrázka","uploadTab":"Nahrať","urlMissing":"Chýba URL zdroja obrázka.","altMissing":"Chýba alternatívny text."},"horizontalrule":{"toolbar":"Vložiť vodorovnú čiaru"},"format":{"label":"Formát","panelTitle":"Odsek","tag_address":"Adresa","tag_div":"Normálny (DIV)","tag_h1":"Nadpis 1","tag_h2":"Nadpis 2","tag_h3":"Nadpis 3","tag_h4":"Nadpis 4","tag_h5":"Nadpis 5","tag_h6":"Nadpis 6","tag_p":"Normálny","tag_pre":"Formátovaný"},"filetools":{"loadError":"Počas čítania súboru nastala chyba.","networkError":"Počas nahrávania súboru nastala chyba siete.","httpError404":"Počas nahrávania súboru nastala HTTP chyba (404: Súbor nebol nájdený).","httpError403":"Počas nahrávania súboru nastala HTTP chyba (403: Zakázaný).","httpError":"Počas nahrávania súboru nastala HTTP chyba (error status: %1).","noUrlError":"URL nahrávania nie je definovaný.","responseError":"Nesprávna odpoveď servera."},"elementspath":{"eleLabel":"Cesta prvkov","eleTitle":"%1 prvok"},"contextmenu":{"options":"Možnosti kontextového menu"},"clipboard":{"copy":"Kopírovať","copyError":"Bezpečnostné nastavenia vášho prehliadača nedovoľujú editoru automaticky spustiť operáciu kopírovania. Použite na to klávesnicu (Ctrl/Cmd+C).","cut":"Vystrihnúť","cutError":"Bezpečnostné nastavenia vášho prehliadača nedovoľujú editoru automaticky spustiť operáciu vystrihnutia. Použite na to klávesnicu (Ctrl/Cmd+X).","paste":"Vložiť","pasteNotification":"Stlačte %1 na vloženie. Váš prehliadač nepodporuje vloženie prostredníctvom tlačidla v nástrojovej lište alebo voľby v kontextovom menu.","pasteArea":"Miesto pre vloženie","pasteMsg":"Vložte svoj obsah do nasledujúcej oblasti a stlačte OK.","title":"Vložiť"},"button":{"selectedLabel":"%1 (Vybrané)"},"blockquote":{"toolbar":"Citácia"},"basicstyles":{"bold":"Tučné","italic":"Kurzíva","strike":"Prečiarknuté","subscript":"Dolný index","superscript":"Horný index","underline":"Podčiarknuté"},"about":{"copy":"Copyright © $1. Všetky práva vyhradené.","dlgTitle":"O aplikácii CKEditor 4","moreInfo":"Pre informácie o licenciách, prosíme, navštívte našu web stránku:"},"editor":"Editor formátovaného textu","editorPanel":"Panel editora formátovaného textu","common":{"editorHelp":"Stlačením ALT 0 spustiť pomocníka","browseServer":"Prehliadať server","url":"URL","protocol":"Protokol","upload":"Odoslať","uploadSubmit":"Odoslať na server","image":"Obrázok","flash":"Flash","form":"Formulár","checkbox":"Zaškrtávacie pole","radio":"Prepínač","textField":"Textové pole","textarea":"Textová oblasť","hiddenField":"Skryté pole","button":"Tlačidlo","select":"Rozbaľovací zoznam","imageButton":"Obrázkové tlačidlo","notSet":"<nenastavené>","id":"Id","name":"Meno","langDir":"Orientácia jazyka","langDirLtr":"Zľava doprava (LTR)","langDirRtl":"Sprava doľava (RTL)","langCode":"Kód jazyka","longDescr":"Dlhý popis URL","cssClass":"Trieda štýlu","advisoryTitle":"Pomocný titulok","cssStyle":"Štýl","ok":"OK","cancel":"Zrušiť","close":"Zatvoriť","preview":"Náhľad","resize":"Zmeniť veľkosť","generalTab":"Hlavné","advancedTab":"Rozšírené","validateNumberFailed":"Hodnota nie je číslo.","confirmNewPage":"Prajete si načítat novú stránku? Všetky neuložené zmeny budú stratené. ","confirmCancel":"Niektore možnosti boli zmenené. Naozaj chcete zavrieť okno?","options":"Možnosti","target":"Cieľ","targetNew":"Nové okno (_blank)","targetTop":"Najvrchnejšie okno (_top)","targetSelf":"To isté okno (_self)","targetParent":"Rodičovské okno (_parent)","langDirLTR":"Zľava doprava (LTR)","langDirRTL":"Sprava doľava (RTL)","styles":"Štýl","cssClasses":"Triedy štýlu","width":"Šírka","height":"Výška","align":"Zarovnanie","left":"Vľavo","right":"Vpravo","center":"Na stred","justify":"Do bloku","alignLeft":"Zarovnať vľavo","alignRight":"Zarovnať vpravo","alignCenter":"Zarovnať na stred","alignTop":"Nahor","alignMiddle":"Na stred","alignBottom":"Dole","alignNone":"Žiadne","invalidValue":"Neplatná hodnota.","invalidHeight":"Výška musí byť číslo.","invalidWidth":"Šírka musí byť číslo.","invalidLength":"Hodnota uvedená v poli \"%1\" musí byť kladné číslo a s platnou mernou jednotkou (%2), alebo bez nej.","invalidCssLength":"Špecifikovaná hodnota pre pole \"%1\" musí byť kladné číslo s alebo bez platnej CSS mernej jednotky (px, %, in, cm, mm, em, ex, pt alebo pc).","invalidHtmlLength":"Špecifikovaná hodnota pre pole \"%1\" musí byť kladné číslo s alebo bez platnej HTML mernej jednotky (px alebo %).","invalidInlineStyle":"Zadaná hodnota pre inline štýl musí pozostávať s jedného, alebo viac dvojíc formátu \"názov: hodnota\", oddelených bodkočiarkou.","cssLengthTooltip":"Vložte číslo pre hodnotu v pixeloch alebo číslo so správnou CSS jednotou (px, %, in, cm, mm, em, ex, pt alebo pc).","unavailable":"%1<span class=\"cke_accessibility\">, nedostupný</span>","keyboard":{"8":"Backspace","13":"Enter","16":"Shift","17":"Ctrl","18":"Alt","32":"Medzerník","35":"End","36":"Home","46":"Delete","112":"F1","113":"F2","114":"F3","115":"F4","116":"F5","117":"F6","118":"F7","119":"F8","120":"F9","121":"F10","122":"F11","123":"F12","124":"F13","125":"F14","126":"F15","127":"F16","128":"F17","129":"F18","130":"F19","131":"F20","132":"F21","133":"F22","134":"F23","135":"F24","224":"Command"},"keyboardShortcut":"Klávesová skratka","optionDefault":"Predvolený"}}; \ No newline at end of file diff --git a/web/core/assets/vendor/ckeditor/plugins/icons.png b/web/core/assets/vendor/ckeditor/plugins/icons.png index cf5548c7b0fc1518a7f18edebdfd836a0a4ffe32..331a155f7e77d608bcecc95060556417af6da4b2 100644 --- a/web/core/assets/vendor/ckeditor/plugins/icons.png +++ b/web/core/assets/vendor/ckeditor/plugins/icons.png @@ -1,12 +1,30 @@ �PNG -��� IHDR������������1��QIDATx��]��U^ -Q�*�5���mPK��VYw�;�ٙ�I7ݭ�55�ڤ�H�H;ؘ��"5�hֈ����J()M��PL�>(h(�!��$3�;��ܽs�������Knf��=���s�{���}}�B.�۽v��:OgGGG�zgf�FFFt�/��t���d&$��� MV��{%!��ĉ�������*���J5źFhU�$��h�y�T��3��3jK]�2�$Ԧt_��� ������4x�w����+��B�S�c5�"�������@��E� {( -{}�П ��H8�%�w��^.i��%���D0w s^D�$���K�b�R�J<&�����RZ�Qu@��;^�b���B�Q���f��%_ ���q�wW��H,�}��@����.�Y"��|�e�:�`��`�;J�2�CCC�F ��I�m���r6�4J%M>�����SƝI�gL���������C��rK�q@$hn0H���:آ�|L�S�a^P�����}K��f/���'yc^���(�ܐ�Q�T~:���^���~��\.��2�흱T*��U7>��*�$M��Q�V/��7zk�*;��]�@��X�'�x�`��� ���l�dk��ჺι8lذ��:�̝��c�9q���� �Hua@���.R��j��d;�m��Z�1N���ھ�I��I������N���������WՍ�իY���X�&s�X�M"�Fb��{�!��R���`������G|�e��P�L�J���"Hv��w���/�vy�c�-Ԅ�Y_b -�yS��O'?*e�i������#y�0�'UT�������$���t�X,�p�F����t�5��1O_��o���a��W�[o�0P -����49����ѕ�'�~���\�:G<z�dSenݺu��e���9�����"]橩�x��6/�.���j')�z�d�|���&:���1C|7U�$l��Ʃ��`�>���'�t��{�bB>�$f��<�8�-�R{�!M���ׅ�Z�*�E�+����x��^���d�)�ט��7��ݟ����.�f�:�/S���#�� R��r�@���x�3e�,{�;($\�T^gy6i�Wk���+Tk֬Y=n�fS���G��\q�')�)���R+���c/��b�$g���D:"U�\���"��Zm�e�&�C�N*L��&�\�)juJ��u.�*�G��/�����`��p=�x��^�/���"�9�R�4*���΄��s��H��a��v�R�XB&ԝ�%��LJS�d -�m����LJ�Fk@n:�i<-���x��^�/�@昞���$h0=�,1��ڛ��Е���-��484c�C�B����� ^C��F ��P(�I�=�����*�������gu�G���V���~[3N~�T��Fw$����N��0�#Z�g�g��� �ŗt�LT��o�u@����`xiж:�~�[��pB����M_j�8k&E�6{�&X���Qu�A�uУ�����Z6Vn�Д�|��<_0j����ZnH��1��Y�2)�וu�5����:H� �:��~��@��$�����BE�� cT��7&?�Y~qVj����J����I�ؙ���/r�n-��j��|!��:o��Τ��(�ʝw��/���bnqEpC�sx�:��`z>���4$q�N~V}F�~��j��W�7c��d��2g�( ��lꚮ���̋�Y��|��z����U��Ii�+{j�"O.����,f�Z��*��3�w�#q}�N[4#��� 6�����2������KR!#�ּ��A�Q��?�� -�N%�S��ewF�.v:���JL�+����n,u�Cs?���;-���+����:P(v��J��V֝��w�Y���.��EH��,�1�#eڕ�� ��2�oߺ<l����v�]�')�����(lǍl+�W��DV>K�Xi�������ni �\R?��^���6��k���zί�e���i�6W4������=8_Hl�nw�������}�����]� ������� ;&���W�N��$#���r+���d4�i���U*���b��U����� @��VI��b*�@e�8z\U~��/���c��O�f�����^�/�����������ե�I��놆8��\������$�9>�z�\���R�:�ry����pA@���G�BaPh�~_3�����,%�A]b�fV� C \���`lll�m�-z�Q���������b���٘������~mEh -F@��������?|�_K4P���m�r�%�V6θ��\���WXyA�t\^��g1���|>����\����>���Ӓ����S=,��?"{"*�aot�'�Xy����#ǝ�F�ɯ��,$��N H�f?|��?Ͷ�'^�]L}����[��Z.`m��>� -����2͝�7n���G��ca<8;�N\ �!H�����#!�p�g�$�+w�O8����+2gX5`����i��yބ���q�� ��B9!/s8�0_�|������0_�|�Z�R������}�A)�������k�(?!J�1�+}N<�J>��F�ϯtĠ٤ЪR�,T�y�������C����<���Ź�;/oR�ғ n2i�g�I{^�V[ ��f�I�y�ƍ�K�mѕoL�0 ����*��_�2?�~�Z��n�ur�Y�߾��h�W��_I���j�+�o.��W0���V�K��^f�u��-���`��5��>cA��J�t%��F�[e4X��R�y��9�˝ьwQ����W���[\/�J���$b�R6�����V.� -a_ 2U"�ӱǹ����HZ�zu�֑��m05��ܠN���I����L�0NP�,s�ƌ��{�u歷��us�/��|�J,�'x���x�Ǚ�7U��z�6B�|}t3�||rG����^�/���8�H�#�|�ҥK�)�orr��o߾�����_���144�M6,/s���}������W.���6�l�����$�d��AFk��+<o���D�4�Fk��;00�A#���,I�Zb�Ł���/�6�!��`����IEND�B`� \ No newline at end of file +��� IHDR������������1��cIDATx^��U�$������ +%> +������vw�i���55[l1����"1!*���`�`���J +A$�0(>@0�!�@�(����a�����;��7��G{~�a��=s���~��[����E�b|||��ݫW�ކ>Q8���[r?�PO;ٙ�LLL\D��L�ר$[1��8RМ�S�kK��Z@����&�S�iRڲ���8����2�G!�U`!���[�&��I(覲��h�7Pw�7�%hK2;;{��@/��Ľhˆ*y>��Y�����+�̇��� 9�^'@ٵk�!S��~%;IU�\ 9�%���H@�W�>��t>�ο# ��0��$�djj�X����$y@'��g0�^�@�W%�����LI@[�k��F�xJX�R��'n$z/Ę�V.R�ҽ��i`ӦMG�,,'�g�ׄ/�����}QIND[��+W+��-Z�.��і���v5ڲ��Jށ�$�lw�~ +����S��e�����R�H�*$����8N&�l0J�I=#�j����qJkA�����Ǖ�c�|kVU�uh�B*(����mi�A�(T�$^���������^+gff^BWfNOO�u���(����H�{����{1���]^+ +m{oŘ����+�)��./���8ΰ@�u7O[��G�N�����5�V��h_���>�E��\.&�C�(:Ir��� +��7R,]�ik;�t���Rp��D�<��s�=�0��wh_&H���}��k��}���q�׃���q=h�XH��� �����zд��z��I�^r� +��ic�E�.�R�6�_k_�q�2�iv^o�ij?������Z�k�<��7j}�b&��ߨ� �oKՈ]�Z`wj}�8��@�%1ɕZ@������֍�?"\�15��ƎRUԄ��o���Oη��Pe�G��'V:J��8 +M�9zS�G��f͚SiZoF������6�Ї���v�hUe��Z�Ǖ}�kS{/�o>M��QE� ��qrrr�rx�;�_��ի�F=}]hE>��z��|��>��l۶��^f�]A��:�m\�e�G��ٴi�ae�/�6�nݺז��..����+�4[�&P�$O���棲�Y��:���w�!C/ZhQ���6;���G����%`�$נ�FS&eO;��8�"�oY t[(��*���p���6��u�@ʞtHٓ){�!eO:��A� �8Nw�.�}���S$X�+�n�/�!eO:��I��=鐲�5&�8Cݦ�NMM��z�V�ShUڍ���#�轞�sg�s �l��Sf9�F����9R�'���=m)�C��ު�]���}���X�A����0��U��@�F�w�7BAO���D�@{��(��2�G�'ݏK��:����({������l��������%�a~~�`>'�O꒩}#Ƀ���I�����%|)b��ϕ �Kx�Y����xˁt�`R���q�����X&�}�\�$������3l��*-���^-�Gc>g�zti���v>oJ@�e�Q S��5�L_S�L`��5&���H`G���g�����H`G��T@r�n+}�Z�{�@���>p����͘��� ��kL*0���� +ic�Z��������������l߾}��`|w���`|w���`���E�,^���_��`|w���`|w���`�����J-�ʗ����X.��q��03�Y^3�\V����L�����%.>�fZ'�w��^��&����q��-c��+ݐ���(�%X%y�L@��ѹIj (�萒Z�A�J�8N����Y��zRǥ�ٴ +Е`������"g��?˞$�a��A��1�c6����v�����u���Z/��y� +�X�W���V�����{�썕TA�X��u�]�� +�+i]�9���Gt�����kDVBM��] V00V�q�M��d�:Y�l��� +�M��${�g?��Dj�@f��X�cM����U�~��ҙXk"�c������ +�/J+gfx��qZ�S5%�=Ag���`|���R���t{H �wO�8�"277��uZ��٩I�qذa��XnJ7�������X���A��2,5%�`�^�9����z�aP���^�cЩI0vq�^,���l �,.�[J0�{�q�"8[�Fj��5�K�`l:5 �..؛%S�-���`)��� ���0}bbbϯ��D� CΏ�����ǫ)(�����Y�����n�&��{ս����a�X���س��uh�T �Y6f�X�dT ���8�7 -��_:?C>&ۙ:>ܙ�Ɔ +L}6�/a���nc��*dV`��| ��d�3Lf�<��L��10�K�]A�$bc�=��W!�X�� +b��8ξ&wڊ�ֵ�L�[c&hC�VUC@� �O�K01�K� +��6t��qp�ϙ��2e�|i*h�>�Xk��D+{� +�Yh��8���r3���*#���j�-'At2E��199y�iT>"⫍?��*&�p6�b�dltD6t}+�,D����Vn=�g���e�kY���!�e|ޔ��ǜ�2��k*#��5 X�l]�$�ڱ])А� +4��"u�]sD��]K@��<���J@�G�� +�7|jm���w,;��VO`��5&���H`G��s��"�� +t�+P�Q,q4�-�W��9�)K�/���M �y���@;�+����TѶ(ڶE�v�hj��y�9�X�}��� �q�Ƥ` 쨐6����?P�m���@Ѷ-�</��y�q�����wB�Ÿ +�TN�I����LLJդ��t}�w��ξ�Ld&4����^�z�Iha�X%�ړp�����H�'�t��\-[��= ��C�˺A����p�j|��C�]�z�p�$:>X�T[@zl�-�ѦE$�ﲪ˂=��%��������;I��y��q����G������{>u,�����I,M$�%�f���J���!u,���J�f�~���"r�F�Q~� �Xn�,��I$Гijjj���ek >�r��G��MG���ne�IW����Z�\� ��p��� r�&�w�%�G`P-7bK8� �<Pk�ne�/Xb�M&���Эz5��Zп����UM�\c�T0M�e���h�������?�#UU�c���:�M�|�˫�������>����� :�����Ы�/���m<�e�76&�#%��$+��p��ij�_�6p�zg��x���p��(��֣_E��D�ؐ+�8CުZx�E������3/���є�I&I%`8I�rr0Q?4�^�/��*����i���m�_ 1��_m�6/���B��A�|Y��#X/{��U����r)~����%ܪ������'��~5�@{�Dy��C�UD @ԏ ����3���B3Q?4��y�����3$୪%�[�t�tn|��4%`�IR N���L� ���y��"���3�LOO�A���t�+ +�a�&���:�����%�S�(�Ü�\�ߣm��[��Pe������kF2\�3]����:������H%��f��2�_Z;�|GQ��}�?��ΏUp�i�(��L������ +z�ίK6o�|��j}���֔��If�mtt��L�m+����(��̎�K-��D��T��[A����?���P������9��H�.�9�@� +�PU��(k=�J�8KޞmeI`�K�.j��E ���!W���"�̹��!W5�ꢆ\���`R�q���2���x�Q�E�-���z՟���{��HΣ����9�c�ѴD�{(����K�G�@~Z9���@D~#N�{�$;��F�e���NP�t#��R�9�3�4M�,da�EmY�u���݄���xOЋ)/��_�k>X���VP�c$�57�xO�`����2�^��M��{��U���z�3���elZ�;�H����sւ҄^���/b^�����u�ʩ ���H�%��H�s�p���/t���7.�رc �ؑ�����+W��AZ8����+;�nݺ�.2233�^�"��P �o߾�F8���r� +�XYy���pLK������WPĮX�b� +�XI�=�$H0U�a�ҥsg���/�6�u�Do����IEND�B`� \ No newline at end of file diff --git a/web/core/assets/vendor/ckeditor/plugins/icons_hidpi.png b/web/core/assets/vendor/ckeditor/plugins/icons_hidpi.png index 9547434aee1bdd3b25b319413d8ac4a17c531e35..1979dd167ea54095b328ad3ca96850e7546b56fe 100644 --- a/web/core/assets/vendor/ckeditor/plugins/icons_hidpi.png +++ b/web/core/assets/vendor/ckeditor/plugins/icons_hidpi.png @@ -1,39 +1,53 @@ �PNG -��� IHDR��� �� �����N:��*IDATx��]�eEy^A#"|P���%FEE�G2��w治0d�uɺ(�5���u�ĀE�*�@H�����e@y�F��@T�Y�l���[������>ݧ��3��}U]�ι���Nw�3��_�ϚT@���2�`����*�}��=������&o����Rn�n���5Rٌ̹B �Bb�����7o�T�����1s�=ϼ��R����8#q�<���c�X��uxxx����ҵ%wȿp�EO�]��ʕ+_h������*�Su�$�����#HW���-z����3L���7p�6J�>)�ѹs��@���ƨ�[�+��1�bŊ��]# б7�f����ibK�.gW<Q��/jkiP7e�Z���Ӎ�9s��*��5n���Ϋ1��4��ؒ%K�u����-t���x2�QC��F6###��Ɖ�C�74����W̄��ߎ�N��A�5n�^h(>��?�7j���[%�*�#@�b���ٳg�*�?���G��/f������`�����'|�x���tl��~5��J����2�Z�r��yw�"�`aXw�&Z���a��<[�F5���, e������y���z��'A���5���/^����s��N���]�ҹ7�s -�?�F�����8j�42��� ��[�U���Z�FH�3�s���%�'H�?��L@q\2d# �w��c��2z����9��9/��sH�N.��<���2zľ[��M��:����)�=A`�R�KM�����wE,�p����ּ�ݰ�2��0}u;���B��ܸ�w��~�IWm�+����$t)D��I����Uf"���+o^���<X��(��N�J���M�L�"��o���������������'�|�e5��t�DZ�v`?Z�������#���uυ;����d��t�n������F` -;�1s��9�{�ۈ%��j0��1���'�!ʊ��n��ϒO���Sin�����>��ǿ���D`[�?;���nc�/^�Z鮝={�p���G�K��.u�����u��x3��A�%�E�4<_�N�6R*�S����������8�~��i� ��Q����t��L���+����x.�V�1������_V�y9��1� K�����n�G��/�g�jz�2�{��,~C�K �̀z}Y�"mi?]����vZ��u���W<)��X����x�� ȥ�E�LDי@�چ���q���-�s�H*>�6XEK&����ꗆ���ض�4�+&�d|E-?��Or� ����R����P�K����zO �6rǐ��[�q-�H<�8Tn�*_I�r�%�,D�����?��K���+�+Ж����H�>LGe!x?]��]�T矒z@����|%�;Abl�!�I"@�|��oX�hqEɛ���������F!�ׇ�c��?N��/�������������t���[��_�p�C�9900�d�S*�U�y�?�]�q�ԱC9og-5r����`ƟRrϘ��d�d�^�҉������*��)D�L���cJ)��rG���a���k�-���.��Kߨ��@c��ko��s��U�q;�K�o��ٗ�m|L3D=�mz��A�\��q��]윟�����&v�ӚnP����S�9Q�whD�^$��ez��$��=d�sp�TAY�x�K�K�����{n2�\ #�]��! !�lo�@-��.f�H��� ���<�hm���������Y�._��g��4#Cc�.����C��`{�C �!���= �b�b �z�6��v��+g�q�bb\q�T@�e�b|��ڞ!�������z�:���S���?�o3|�������wxR�*&��O�����M1�Ʒ���ʕׯ�����7L��WL�Ѓ.�w� x�cܖ��e|�t���V�m|L['N�M�� ��2~�c��]윟8�ߔ��f���Y<�2S?5z���}���9m;�B�p2z���(&���������@4�T?7n|��|��F&��v�K*��9.9�nI���1�n2x�<�ȿ�2�n<��}~�<�����rY��|2v�<?�@��Z��IC��ZP�� ��m2wQ��qzܦ샜F F���ؑ� �%`Vb��R-)�Rw�RY����I(<���_�!<f [G6���R�������X�lȸ���}����y��Z��<�������ʮ=퇆�^i�9�A]���(@�q������ �>�g�����;fu���J\�Z�[oA-_R�����4$;"cT~K��+��|xb�K���!���'A��������������]�`�Ӆ�����7̣_џ��� -��l5�����ի�#��p�ehh訲6/^��#��M�� -g倝��/��g����V�.�8p��']Ʃ��\��� -��ǔʮ|3R|�)&��a/s٫m�����L�k�@@枉�5�O�4�s�{���1w�ܿ�6J��}���QzI����H�YƼ��Km<� ���s��'�B3B�LRu_����@��n����y"���JT٤�����d�����w����Mf,���*�Wα�q�}�৹c��>2�8չ�_�dɫ����V��P3c��暿�j׳�lL���>V��5���T<6ZQ�D�_me[NL� -�r���/�]ydd���6������� -�g� �q��~ZV�}l];:��d'r����K�~��8���ul��Y�&.1���0�D���|���BcC �Yv*��T?��TL{e�[�+~v4�+��NG�����lb)S[kl{�n7�D��X7+����6gd!�-5��I�A���`$�n����)�]��.T/���U�%ïJ���L�$��u7��HM���.hZH�7������g�?K�r-�w��ϒ�b|�d���������N@/�^���z����@/�^Pw��@/�^���������ؽ��vyfJF[0YZ�T��͠���<]�9k����V�&�=SG�Z�d� �CSB`T��������^OD 㫬"ڜp� /r�1q�< �}%R�$M"��A��Ij -1?ˑgL9w���1��%=<z�(������N"@����q�{��N�3�I!tA�'"�Fw��-����>�5Մ���j��� ��L#�t�җ���$e�����?$��E�zes����Y��q���}n-Ƈ���[h[Q�ϩ'����l=M�>EW��LH�9�z�|�|T**d��lb�B�f`<u�op�K�uO/}ӱ���f��`�L�&�~�m���o�!c�k6�w%ȡ���ӱ����M���C����NDO-㇅�b���k����%=w��.��[��c�9����1{�҈��6���b ��"`R��@�t^�]a�gj���秺>��O+#p?�|���yj���)4�� �#�+V�M�����<��!=�m�M���<.�ēt���o �`;���,�����������^���z�����^01�@/�^���z���������f.�W����u����k� 0)Q�L���5x7o����jᒽG�;���j�qW�`O����O����e�^2�u�uF��_�X���]_������7L�lG^�zb��v�$0�{ �i�k�Nf�Q�-�J�$'�y�����y�J33���י�'���'�e� )Q|^,W�܋��g]Pz���IqJ ��@홙bRC�<�!H" =�Ux��@JB��(KZ�#)N�������-*m ��=η��ԃeW�H^"���̢�#/QRVW��ؒ��(-)RL���?r������P��@/� -x��QL�@/�^���z���lO@/p�j�^������P/N:��:��'�`����E�4[&b�J��������R_��i����7��C�r��Y0��70�����������!�-�e���K�s����*���+��$�O�}`�n��V2��T��_�J�� ]�|fم�a�K@n�#�!�@mC����u�s�̹�7�sL�(U���^��4�i'5n@�Jz]l'j�A.T��N;9�S���v��Av|���+�/��O�Ƀ?�>�\K�E��Q�s\�>��k������s�7d�?�o�"@��v5f����U��<�����ל�cvhT�H�z��C(mQ���B�B`\��ZU3���!�q��"A�����m��*W�O!�����R�����HB!���C��������l0�ԁ��ͭH� :��QO�9�j�;289$�C��T�EH���5�Pp��ݎ�E7���$P� ���:Ǽq���D���X�z�s���1��|s��^W֖W1��)%��X�Q)��>� A -�����zAx���]�9��MɈ�:��&H�t%1����N���#�$\=�%N�u�Z\�Z �y�����������8�U��b��M�[688x@[�ot:��k1@��n�+�߷wͅ�?�/� ��d�.0�@�e�K��/�Z�O�2��^�����@���&9|�qj#@ρ v���R�Lݼ�6��ڇ������~�,��J D/�s�d��"� Fs�B P'�D���6�����T�g�M�z��7 W�Z���c�LB�mhz����I]��j -�ȑ����M���ʖ-[�����Nh�+�<w���裏.����*n�s@K"�|�5����oe��M����/��[�8�����V�:��������,_��� ����kȉ�í���!���s2e�/( �2⼒���^`�$���B��+���9Wj�e@|�_�����������o;��}7}�>�� ��'����Z��l�Ҁ�����]�B-�����m p���/�e�J�1c_M ��Y�RB���Ј���n���1q�ĸ�����I�CCC�#���� -i�V!�n�l!1�$ �J-=Ъ��v�D���o�n_�sV��|B���=��u7�s'������������=u��\J��b7������9In�:��'��b -r� ߐ���;�&j' �&�E�|��`1��}�5���QC�y��"��RJ��v�)��CJ4k4W "Pg�$/Ee�B��|�r_c�Yr�Fʾ���-.�h��|�s��������P �zA2�T� +�V������6$)zAVU�Zq�Ch������������U���_��F���ZGk:�E]zAU�� ���0�+ AJ|Ae����_�D�q�z���������� ��#�!PK>�P@W��Ѻn�Z|AL�_`���i�����%��@�n|��z���������f6\o�����;��k���T���I���y��yQ�[TΣ�_$#��S�B��B�g���-��i�ᣫ~5����d`��x�譅���e�l�`e{�}l�s�.������~cT��s'��!�իR�.�ݚN����c��:���Բ�R=ߕ HO�v<�@����e�h9w�� ٵ�sB�O"����W�B��E yhbp�s��:ԧ��u����@HCe{�֟�A���M�(��.`�iCL�,C3��[�#���������������0��c��D�lS]6����\nyW����jue��Zυlj����'�C�Z��3Ʋp�%>BZ��ٮ!0�2�{���y��o\9�=���� _&&W�!t�obԦc�����bb�f��ZH�u�G/��*���0�o^�B��y�ѱM�����]L�f__��d4�����������F����� �GT����c��F3p �����wON����3�Fgx��{��Qf`��t_�F�$������/� �۰�~ȥ��N�a�����k������k]+����C��`��A��?��0 2�P+�~�����������4��q��o�V�R9� -�E��݇@���gP�@�8�@�ٙ@�U�/31q�W;2�T������w��Z϶N ��m��.�$&:�e�P�1w���}@�]^'�V3�Ε:o��rG����������@�����K�<z��Ҹ������q���E�.@hp�����o9�!�|�e��ϳ�@�C����¥���m��U/��ڻ�݅�'4��W�s����AC��́Z� -,�i�fo�@k~�ٳgo��}��������������=00P�k� �1xJE��\�|��kC/���^[�c����Col��۞+O��#�bŊ��0u|m��ޭ���P��ܲ�4Z�q �Z>�&s�v9�/ר{�@s6�c4�Vy&ߪ��N�5;�j*|��U�U�|��>�����t�v�@q� �G6�������0����\F�aYo)�^;w��I�����[�'���>�>�<S7�c��������M����L� -���LBj���9�y�U�j�}���n.��!�v5��Tqc�^�%qY�78�.<�W�� �9�ه`�� Z��J� Eۺ�Zs��F�k��*�c{�V_[�?�ׅ.�?]A�s�4ʓ,��j�6>(�AE}%Ӯ��D���Rj�D�u��)�I�X�6������m��w�Q����1�]�0{7[���2.�h`S��M�����������R~)o�2����v��������L+��ݼAz��~k^���=���t�|��+7��z�Y�������UW �<����x��ҵ���=�����~�~��+eK� -��2���ڭ��Fݻ����iO�nw������9p��w�'��E;.��x� x�s����O;! r�g�A�:`�9�l��I �eُ=����e�SϏj������ۼo���o�pyo��E�� �E�e����.n�Ndi�&�{M�^pW�d�o��z�^[�_��>���cz��o)� &_���Ŗ���E/�7 u������X�O��\Z����tzH������������v�u�6��R�4�����b�����R��/^�.|Q7�^�J^��\�u%��zA�����QL[�=SF�h�^ �i��y`��Y^Z���-�J�nP�[����1��u��5���@�N�#�D ����BR�t�O� -�}-�ә� -ҕϏ��nې�|�2����vwxխ��>S\�J��e]��Ң���Z�SB`���%��FU]�5d�ǥ�ן[W����T�@�����ȥ'Ė��lGi�EL��������P�/@|�R<��/@|�_�{��"S�g%�����_PF0w�����W׃�D��;{|Alٗ���yk_�������� +�^ ��7�h �5�z24�@ -.�`ψ/0>~��Ct�˦H}��t:�To��/�/p�ҥ���t����X-��S�U��~��=n��\�� v��C7������ԭ+D�d'�Oj=�@s�������)?َ*� �t� -�������P -�������6d�������U��{wk���n+�e˖���F l���r��\G���T:����Ͽ�^o7u����ߜuX���RG�|��ya�<i�����l����p3^u����n��%|c댤�'�����*�9�2_����Z#h��.���Φm5[�?�n����6�6�&�'���'y��~xxx�Fh~>���w�|� �e���q׃��3}�1�� -���h^N���okH>%��ƺܬ����i�Z���4.Xn����S����5 �J�pBJH[D�3A|;w;v��V�L��*�>�����h(�-H���?-v|�؆����� �jnD�Fu2{��_-=����|�E����?�����������T���<����䈶�j��e��`���G��P����hat3;�98. �;�W��KW��$`w�j�9���@حG������ݘc:�@*!g}�\.�O��;�|�Yc.���:>�G������>(Ͷ��4"P��@ِ��=ɐv�ӂ@#C0-hn6�Q�E@�[�4�fH;.�{ KB�=���@l�|k��� -�����8.v�NЩ���9�jX�4�.��k���ح��"�o�ff -�k����%v���k4伐}JsR������@���s�?���{'�X?��?�M���Rb� �?���� M������;T�u\ -L#�g�!��;�-��r����u ��{vAJׄJ;����W�?�2�p N�sn7|�����!�`H�����I@�{�8 K��_qɏf!��w�m��W^�U����S۩����nx~W��������St�Mک����]0Iz�+�(�vh������������088x��GK��%A����Z��В`�EΡ51u��ĕ����D���X�J����ʫ�=����M��z�&��ֱL�ץ�=���59��^��wj!��?�MY/�L٠9�Q��b҇UmOe�@����T凵 #���B���sA�l�k|xx�%� -��G����Llbr�:�Ng��0����d^2~�gr��%ϊ���N�9s�c�E�;}�ݞWL��J=���8Q&7q���#\�E(��0W&�M7ǻ��Ae�p�z��nz��ʕ+_�ԋ#�OAYR�hgxH��e�)Tz���m�@���7�u�e�^ۿ ����������� -I'�������3.?��y��t�u��]����Tw�$1u�����phW&P�[��D���,������$r��J"�k��l[F{h�@Ab͞�pm�,f(�N@o�:�����2vU0Z�KR<|��J�h�Z�s�A�]�0������h|� 9��x��u�2)���y{�u�i��<wơZN�$���ƌ�����:;��@�S����jAL�p��g��Ot�M����]b�\uo4���J hM�hK���E��'��:�쁔*�B�}s�h%1�N����������3���Ti��/@|�_��� ����/�n����������}��� ����/@|�_��� ���� ���������n�!�r��Y*W/X��*����o�N���ϟ?�\20%�B*)Ey��=<�aj蓮ݛ�uk���1���d�y@i��ڢւ��%Y�w���U1��b�K!u=։�{���n�K���0n}��-zM��TU���z]�7��1����T�C�ʢ�9+ ��������j�����4��N|p�K2 �>�]F�V����by�r�����c�9��'�e}���R�h�1����m�����K�2u�B>�=�:���.����]��d2x���2�/�_�x�~���� -###ϵ�����=0u��J���[��\2&2ߨB@�zzؽ:��a������4�P|'��ު��������=���SJ2�[�G��Gb&�;��7�F6'����)�4�[�9�|�w�ME2p�8�+^�r��<D�yZ�D�C�J8�� -����z�ܒ��� ���r#��&*W3�j��0�������kL�S�!�����.��iDs����~h�k�m�8�M�+B�8��8z� -y��!�����������p U�'(�;Z?8��~NE� -�?K;Y�r�J�Y! �YfYי=�����Nl�Y�'?���k:ɋ�Z�O_�Ė�O9&��U���<�.�e�b�[B���k;/t�}�"���>o�b�,�yDCW��tm-j;o�!� ]M?�g+�F�<.�I�?K:��*z���>�~����ΛBV>�6��}⼘ -�D�.(��B����+�9/�� u^����U� �'�_[<Ah}�8������� .�ފ����?��Z��\h�8}|���z��<M�i�LF~��Qkt���d[N>��}���Ʃ�܈\e-�xϘ�+*��L�meW-��+�����>E[�R4ݐ�E��J �P�� :y��ԯz���<��)�9�,�i7�k�NBA>I��Q���K���������ұ_��'R�� -j�:��<$R�>;���+/"*;�]�<��\K�������"�����=��� �wS�50b{���3:;���u�V�>qT6-]I��d���g�-���������� �i��.���� -c`��� �`�)4�J�!5�z�=`5A����he�uC�8=s\��F�.{�Q�/��������xM/�-"�����%hDN)3��u?:i�k9~��~V�6)�2��+^@�D���q�Pb��F0�@��!�l�m�R@�F�5��*=f���Yo|�Bx ����86/�~�.˞�2��0��j����`�.#����/�J=C �IU~U�������������z����@/�^���z����������`f����������������������������,8蠃�SJ2�N8a�����TL�dK�.��������L�~�U�S7����;�R� ,Z�h�����z�9����c -���n�;�F]�0��Y�����K��@WK?O��S��Y ��U�f!���������������8���������IEND�B`� \ No newline at end of file +��� IHDR��� �� �����N:��5�IDATx^� �vWY�Ѷjűu ֊V]b�e��x��~�&_���Ơ����C��|jpI.m��8���.�D�8���$�X!*���Z��$}���x���}�>�����zr�������}sﳿ����_0��ju������{vvvւ����;�i�?��_����9�^�誏���FfKbkkk����ӝ�&�Y����j��Z� �����2յ�g0&�����'�n5�}W��:�����x��Uq�W|�x1��W=EW����N�`_�>F��{�$ݻj�\xᅟu�=�|���3u<�-�����, +��:uj� +��-��x��j� +�[��/���x�h��5�;�\|�=���`/r3n���\mf#P�C�v�`�� 'O�\����3g�Y�f�fvO��+�.���ͬX�k|��i�]�CH���,ʹs�>���ީ:����,���Ա��Jx �����߫��ۊ�W�E�����W�-� ���o��[�_�!��8qb-�������AA?�9s�G�VLay�ZQ�h�5=I}L�|OBlww��HJL����(�ѷ��Z��� ������8�?S���+@�HH���&4K�8��G��d׃��/T�j��X��BX7>{��ת^5CP]���'�_����N���Uo><���hs�x��7���q��V�$�_V� Ir���V_�� ��'h�W_�0�� �4��s�� |� ���Z�GY������U�b�ȳ�o5H�g��p���� +�z��[l��OD�<��$�xի¯��nJ����U12��v���W����z�|���.T�*���d�T��G��l����Շ�~5\̚/1u��zM�S�o5x'�@C��]�9��Ǐ_�ɮk���6�:�<W�����'�T�%����#���� �'� � �`P)Ay�W��շ������X�V�S �pL�'cN_�YVȋ�~2� Y�d/V�Y� o`0�pU�Ea鶩�bƯR������*�IX�cUo1N�<�4_!G[u���g����y�����!X�k��J��>MP�E����7����ds�����`���Kp��� �Xw���u�����:�q���/�r�'Uo1l�8%[/;kŪ3;��Ή�N����$'���-�34g �Bl{~I�'C�5�5�p*� � ������'دjo�� ���/˿��5����s�c&s���<��~�3 +s�|�����/��Dg�h��x=�7��{�C����m�hoo����a��_mן3�7rf�zgnA~U��;[��V�Ͷ�k�fA��R��b43n# x&l���<Q�D`M�-������ς������[w�~?I��O3����wCJ�W�j���&_�e��T��Q��R��Jy���_i3x��[�c_�~f_�g�����5�?�n,�0(�������+0>3�E����s��E�����{����?�q��}��5_��/'^mo_e ���?�d�|���w���%�l������!��8�SAR�s�p�4˿R��0'?e����g R�3hd��r;v���slV���;Ŀ�Z��L~y{�Ƀ � � ���ժ=�0�MǕ���w�8�����:>TJY�l�w���h�Tu�*ǚ�?�wWBoz��7P��3^!�M���:��Z{PE-�x���y�=#o�Y7����)�ğ0 &�kB~O�g�ޖ�2�������[�_Q�ٱ��π +8u������i/�_��,���r�n���9�;{��v}��7�^�3 +s��s�y��v�Ǭ��$�ԍۏx��G|�܋��I�x����oP=$J���۾�x_G����u�C,ٷ��A���r����wI��M�~�رO�q���\X�;]՜[ٮ��ώ� ��{炁�c�+��l7�yw���X��C��C��F� � � X�M��-����[��^Tc�w�-�S�}�[� �71 �M�5��Ą����y'����=����u�pY2����ӧ?�u}@��Fh�sbb��/�i�KH�>`���OLT��M��?� +pڝ��� z�^��@ ���u���3����Ĝ�������_��Ĝ�ƺ�*3_�����>��o�t;W!!˞�X�%��,sbb��B�>th��'d�sx7K�n/�W&��sbb�ެ�������x#ӿ�Q���91I% +[����kys�=1����R,Du��f��z/��XЗ"0�kNL� � � ���R�?��o������z���z��UCG�v��xL�M��%�Hի�A�����N�-�oQ�jP�T�j��ת�j�z��UL�%Y��X�ת��TT��`M{|�����+P��V6�N�u�Yh*⬌����z��=-��0<|ԟ�F��K ���T�����k�j�����د�~/)}�C?C������c!�V��U��˿�����T�0I�@Tg����%p��[��/�Җ9s��?����j��������Ē�֯������$�V˹s�>I� �f�����rX�G�y�\��F���� ^sb/�m�1��!�aI��$r��_�����&�?��<?%^'%^G�d�K@� +��pj� � � �{'�������7��OE�����y�[�������j�Z��p��W�?������G��r����Q������M����_�¿�v�Q��YcK����s�A�%��FTǠ�۴o����&��t�+Em���}�V�j{�K��@��������V[d�UΉ�N�F������ + TdW��-���G����_r� �Q3U)�~��{�hJ0�}%���TL�VŇ,�P;�Q�ƶ��w\�-�c�ׇ�,�㟪^��'O�p�yU���z�Tn��>��OWPli��:%��v?{K�{T'�>f�����x��X:5K�p�)a6/��/��/V�,4Bpۊkt����gо�q��d�}{7 �ɋu�o�?��Ylٞ����a�����M��ߏ��c�5Ίt�K���G�ON���<e���^��@NJ�;w.�Os� � �`#���ꅿ�����'��I�1�U����O���Щ�������������0�ki3Kp4�zq��o�O��,IБ��@`&�Z�~Zǫ�{��b��u<��e��tS��'����Ş����^�H��䋎�Dx�����YJ�A�?��z�����%Q +�Yi�]�;cH�J�$�7����((����3\���4����=Q��~�ҭ��R�� ����K �(���> �6C�j?��T���ڷ_����L���`���/ßj?��T���ڷ@�k�j�������������j|@ �����7� � hɝ��㼀�L���! ��8/h��2�~������xJP�Ӿ8/��8/�N��4���pI��R��xx&���dN���1�$(>�R�%��>�OBǽ���Ov0�~�������S�';�j?��=�~�����L��\�j�AA�}������;w��8[���h���O����B������G4��#/a6�or= Svww��:9L�=U����M��'��z��<\�7�����W�W:���K?[u >���jI=Cu���j��mS�ի�2+�^�i���>�k���B�;��:��8����`���p�:�l���W�ՙDP�?W���^FoP�x����9��o>}0 �Ϛ����,��������_��> �٫�j3+�yح�-�?+���C<h�� ��m��,������ �d5m��J<F�'��%�1���x 9�������Ds�:f �����q�x�1�7�9�e�%��� }$����ς=�!�^�]�!���KQm(x[W�����t�9�~�ϭ�#�zbU�L�q�y/t�D��A�����_m:0[�ɏ�ƚ���t��{���I�k�����/+۳���S��د�1s�uL��gv�Nǎ@E[�kt�����1��;_�1���/�L�m���O���������!�$����>�����/���v=�f_~��d�U�㞓#��?Z��X�/b�b��̫^˦��Ɔr����,� � ��9��&��eؔ>D������ ��okB���,������ň��@(��p:�⼠I ��$� �� � ��~��%W~��d���e�?;�T0���1�o���Vδ$���ovvH�M���/+�4HI�>���vS�_�n��N��8�:��ͫ���شU�,)��n�R�x[�~=���L����X(Ve:�j�Պ���'�֦PJ��Nվ�8����A�O��X��w�k�w�K ��K�K +��E��j<~��%Q}�w�`_K� L�����:���PJ��J+T�俨��/���CI��F�k��x}��}5P� +����Y�'����J3�P�$ԯI����V)�&�$}���>�w�z?�j{��g���h����:��t?E�o5��#�ɸ�*9~�x�� � ���v�TH���8/�N����?�j�Պ���{�KSJ�t��K�K +��E�� +W~��%Q}�w�`_!Q� L�uB/�� t()�á���V�D�QA�y_��}���)�%����J5P� +��k�����J3�P�$ԯI ��`%�}�(q^AA�8�{���YR4^5�[4^�A�ln�x�`n�xA]��E�uP��E�A�B�O@ƈ�o�j�D�}�1m�trc]��R;�騶_�Sz?Y�[R4~���<���A ��t�%�[4^5�[4^�A�ln�x�`n�xAAAТ��r�}5�%IVɴ��@����� +�l���� F�N����e���Sq֠ӯ���f3�<o3�sd�g�-��i�4���p� (���X�~t`�-H֊Y��}'O�|�����2(��|�v�fd㰤��c�,�z��e�db>n��f�|Et6N� a�f�S�3�T�l�����c߅�i���Z��%�OJL��z����X���#tP''6�B�e���Q���n}�WuRb���a���Ig�]�N(Xf[�/���u�vW���[�<3�"�M��4�N��@������$X���;�C|�5~��V�!��M@� �̟�� +��W�{t��{p�������j��?�+���ˉ�� � � *������M�>X�����z��o����i�Y!O ����-��,O"����>��x?;LL�7�b �-P�%OV>�� ,2�hU�R0)���_k�����?9����Ft| ����+��T�>�p/�u��Q�W�i� ��A|ߨ-������?�~�T���~6|~ui��m7 +����# ��V��0���ЇR�h�^S�πO�� +�����q�H�@4�����$� � ����>��,��H�����tl#X�P-;s��tl#X��V����,�������=���Y�<�ۯ�/��/�� �d1��yEkw�8�����l^��m� ������m���I�ܣ$������6�O�m��ƌۖ�ӵ[��o��S����}���ά �%ˉ�|�������|4r�*�D@�O����}ZG,b +#{��݂x�����Ch�7����+�-�v�LZ�ZlK: ��*j?lAS�=?[�0�K.�d�,�u�m����xb���|dq��+���%��������4ؤJ���3p�رe~$+a�oB'N�8??�� +�ڬ����ܞ�'β�AAAL���|��GZN�5'�����{�x�>�\Bj��TB����01���%�@E�|�:`�VL����`RگX��}�P��t�Z~��?I��p/kD��'P��<G�ߢ�}'���f��FQ��?G��0��+�;<<Lo�Xtr�ΰ���S�g�����=�jV`1f+>��}}4,���A��>���>�z�E�}|B|Vx_��X���o�{E��� � � �o���{~�s�E��"��Y<��ϼG0���:&T+�ˢ�H���O=^}ۏ�n4t���^����%<��:ے+�{��> ��|�)h�$�evBg������Xп��>��&ꟁ�]˘��uF������x������{M��� �������| +�U�o;pz^K��͌�9��� +p<%�%�e�k��O%���v�ф6�F��o���=� � � >~�A�/^}�v<%�������^''���-���-/����R��:�6�F�vpeA�m����a�C�DJ0Ƥ%P+>��x��:������ۺCD�u�4>T���x4���%���-/���R�j4�h�P�F�,9%�?�ܧ�x��n��KII��~ � � ��c����ߗ�:(�+�c���`��1�������h�yn�xP�T# +�L���ɶ�����0ġO"%c҃��DJ�E�E�l,4��[�'�o0>>Tt�ʉ�L)@I��`��PQA-@�)U[�Fs�����8/� � � �o������ߧ~F��n/}��g4�V��h�q���`4Zp�K4N&�"�����z)�8YjB|)�:'�:� %^G�Y���շu+R�~��4�g߸�[�`С�~�QGcE��hzN��5�[4^(�yAAAAP������)�c�����Ѩ�ZQ?�Qǵ�~�,Zx�K4N5��Ȅ+�l�^�h�,j��DJ0Ƥ'��R�H�סh���%��ױ�~�I%��jE�V��Ɗ��F��t���R�j4�h�P�� � � ���x��ǔ]W����=���o��x����~����&϶�gZ�������j}w��OF�푗�ϙ��dl��hο�fv�ص%�U�PBA���'�S�::J%��U�zڿ1J+�8\1����T�K�.eS�oaT �շ������{���X����g�%*��+�z-�9�����5�����6��\!�eu݆���t��|�59��x;u^#>�Gگ��ޗ��g���s�Q�t�8R,F{�>Ծ�֑��&NԾ3P+c�Ծ�}���N�T_E�[������}��>O:��DvFAAAC�?�O������:��M�A[�;�R{���A)�����=E����n"啘 +W+%}[��_��c^}ۮ�-�@&@R8�rhc�-@���\{�-���ѧz���̃�c�n���U�NC�����L�n Pب�J�/�Y�l58�j%��@Z�`L�[l�n5( l~:zX~\���oI�$5#�I����[�R�I%�(ǎkF�u<� � � (�ʶ+�g��_��:�/�6����yDT�̀�}}b:�_�[0[5p�ٕ���`L�gA��VGR `9}E��>�݂mW�fP��>�O"���S?G�N�3�[���A�8[M��yOȾS���K�)�9�9��`�Td����� ��S�[�Y�3V�XB�����{����z_�9IM�P��5Te47\ �zAA�F��s�ﯨc��:��dW!="��������; `r�v���R�@�����=���ڿ1���o�H�a��P��z��N�:9?��^�5PN\��[qΏ�m��@u�۔ڥ����U`�~�M�N��M��o��R�U��z��Klcl|Ɗ.}�"�ge1,؝��|�QAA�aP�Gy�)������T��ok9ߕ��11��|aZ��� +(���N�?jϑK`c��X��~,�/���.��-H�xSK ��ɭ���l�c�+�*��\��rz�Q}��>�O��:?�4�&��S$����x�Ne�;Ut>��\��Q{H�x^T�;����T���q�I@���wsq�ĉu�_E�� � �`vR�V-����?������ݑ��F����&���ޯ������d������~ ���cE�{����?_�K�F�@q� +� ���z��䀮/ѦDmڒl* \�>��.��o&ъ��*�����Rm �J�l�m[�5��MnPCo��F���u=o{�j����j�-x%�}�:��m��{�/�!F�n�>S��NP�`;UnC_J>T7+�=P?�g�@���lUo6��샧V@�a�:A0<Pxi���Uu���M�y�����)�$��4z�/CS�9��������d:oD�Xk���oTgch�hߊ��ʔ}[|6��}���b+����X��$�oh|��վ�����ڌe�wlo�W���l-�g�j�G� ���I�l�]�H� ��H�H�S�d.��Ja�~�����Y�/ArR�;����}&��>*I�: �&쏴�f��WJ���tr���vAAA5(�i�����2՟_OU�U4��Mޡ��� ,Ŧ��M����=���M���ό}�$j���Ŕo���u��w�4zɶ����w� +���X���g!�m�}6۷%�~;Љ�O%7����O�:�%W��o��@��[ͽ"�L�������T����}��ώ��~ ���E���%կvꗔ��(ٗ�� +J����+C�ߗ��Ɠ���.���w꽢�z���d�����R�(�{� ���mO�+������+��x�6���G�WJ�8g��{��{�����R*�5�=D� ���28�C�q=����^Q��&������s X������}jP{�{���0�����oV1?sBW�?":�%xM`0�p=B�h"�goR�H� � ���v�(����F�� �TUBk��9/(�������> R��O��b�77���y���Vȫ��{^��P\���:!�3�Jnb�X��@��V+$V��+8.N)k��U�R�<8�P�-4�~�i�Z���R��E��Bi�DѾ��-��}�Ձ�+����>��B�a)a���?�a����}�����{{��� +h�x�CIu��Ý���������j��_%��*����8W�b?�~����M@ ����k�?4���[u�6N�� +:!�O�3W�J�=Vٳ"�~������������� +=/���Ǐ� � � Jl�����G�T[l�=/�����N|� AuK�@��jŁ,巚{E���|A1�%��xY�@ɾ4�Q� + +W����WJ�*8�0�V}�+���u���b_�p�����E��Nj +(H��O�/�pK��W9�:~�8�/�9�D3O���}��x�*������ � 6�vs^����l伀5__�OU�'�:/��ܹ����H����t^�����(�����8�j�ʿ�����w;���ڿZ����X:����&ց3���T��VH�@5�Wp\�R���P��lSt����OC�'� >P����XJ�4^�h_R(��(ڗtm��OѾ�}k?ђ,�?\�������Ce�}1åNj +K��/*�0�7>վStVJ�گgPr��8��e��*y�1�?�j{�G��z?������LOg�ʶ���1�[�?W��}}^�\!� � ���r�j�jφ���y͌o��*�h��~TQ�[�%�\���sp���[�f��+��:M��&دomm�Ʈ����Z�o��I���]� 4�����`3|����h_v�eT�E��f +�P�E�e~�ov8K��^��Z�q��:s��-���R6���B�7��_R�E��~�r�b䷨�"��z�`o�������.���S��%�Qx�p3o���ș�}xx����Z�c�G�g�K�ϳ���mڗł�h�&��T]��|ў����� 6�/u, ip<���V]�_�7��E[���~��`� ��~�����>��ې��cA ���xpb+��7���|��u���ZQ?@u,��P��� I%����>]ugG�~ض��%����l���+q�@���f�����q{�rod�O�g�رc����Ol�;-���?� � �`�R�����e���Y�=��^�K�G�o�^TY�&T�o�l�����[���J�g\�?;�*>jX��^-�-�� +��Y��_�^g���̸�._�?;�@گ�C���W����| �W��k�9�f<7��r���zN�?�R�������P�������韝\�K�]f'�����M�o����s0���/�T�����gARe�\����gm�"��e���i�S���'�JHǽ�*����ݿ�q���X�������D.;�ׄ��Z�59�j�ӫE��`Yti�n�^ӧW�%��4�;�z�O��V;�# ;.s6�����))�� � �N�]�D['8��:ޢJ����ܳLQ���N�?� +��$�_���+~��'���/o.P���`(�o��_*P�v$������������ޗ����){�{���d�pn�H��N�"��d9�Ztis��q����ޗ�g'(�?;���?Y��������@�/���f�럝\ Mt1r ��[l�fd���1��� '(& �#�R}}�m���a�8�E�ub^��??P l��"珫��Y�Ztis�T�[�d7x`�8nFl��K���S-ϳ����w>�4J9�}����~GV�W/� � q�̙��$��,K���}�������>�g�\۪���Q08�Y�I:����jd���x�I 8K�h�x Zʭ��|lp��T����`� +�t�-��=W'��z�sП�gA�c�A�E�v��R7�1�����*�{Fn�{ڼJ^�u<%��@��2������ ���Kʗks}��9YRp���~���a>1�{۔�^�@�c�;_��Z�N�&�B�O��r�ئX�W}b��.�@�A+�T��'O�|�Q�jߥ����]�?x|��c�DLj����l��ly��K�j������y۔�^���o}�Cg~�'p�W|����ڟ�d��g�^ф��,�wX�[�9BiF�9�����(1����?�� PR��\ۗ�uL�dQ��q_.!^5NAAt������^�V�| (�O@���=����N������'�nrc�fs�,I��/. a��:�Ǭ�����-�LJB�{c�}٫��%:W�g �����,��?�.|f�������|�HѶ=���xJ�:�ʩ����^����'�G9gK���/Q�LbI���9YR���(�q�[��3�sܯH��E �:>H����8;�z> � ���bA�6g^�>|� +��<�3T��ޢ��.��j��@���1�+Aǩ�І��~��y�^R��s&:��|���C����r���3���h��s����,%VAs�JnBYj�LW��)� u(��*� xI`�� .���%U~ϵ�\��4Nu�����U�AA�$��p�*����d�����k>)g�lp�����_��|lp�{-�apN ��N|����2{�E؎����m��>*����0 ֓U?�/ٞ��4�������M�H͒y�5�%�#�f��*�!,�@������N��*���Z��c'�:���s �q� � ��C���v|��v����؎�4LNb�x&%��������v��C��$�����[����|�߁3�K>h|�v'>_��/� +��Wr�R�d�~L)M�CiF�T�l��HC�opY���(��{���z?�q��C︯?��'� � >��_D��~�I�뷷��l�n������V�Ǩ�llmm=�9A�4庶�e�A�}���9z�8�o���c�^����9y{��ߢ0�����M�{{{�[Č?��3��B�hlW�����-0b��q�B���g���/�R��L�E�J�n���^*{�U8�z5�|���êײ���mj�Q�Z��;T_��,�Uٞ��Uox�������t�[�Z2�\���W�`1Ӷ�2�[C%����������%�>MS�&��V�!� +�~���i�S�5~�(�� +���k�1�[C�vpŃs�ĉg��4x3�m�[c���/�&�z��={����^T��ܹs���|����� ���������fl����ՠ~ �f�%��A����cǾR���������7U/�-�7�1�P���gI�=��:V?�����h�dR�v�a"��U/����]�k� �mA~���0��t�w���~��? -��H��U��&/��čC�iܧ�q�������8���p3�e��z����%:�� +��ߚ����y���.��`��?��Y�/�����Un��Dp�J�v��C��R=������ڮ1/�9�y ����_���W�����6� � ���˪��ׯ:9�\�o)�z�uꈞ���?���7��W�����6!��+7;|�Or6C��,5�>���הn��ϾS�W%����>�h����r���ܘ�C�P���?(��a�j ����b ̭�Nh����kE��`������bz� +֫5h +�E=�@W�<��~�����}�HU�+���>���T��KQ`1����?(��R똅L�WZ�!����+P�@��������� q���ת�@�گ�N��*��ھ��c5�����;���9T�\?�te� � � ���s��m�����:mz�?��E�����Y�����>(�l[����W�PM��/�?{{{��:jQ�ꪫ>�zZ�'a���AP��շ5��D��&OT���X���K�*N��ۚ�`O�C�?�l{_�N��3%�1�ߧ1���0@����o^���ls\�c��\���>�X):N%�q���XY�2�K�b��*۾k���oYTNj%u���Ŝ��(��3��{�پE'�{�-b�;��d]�xU����}���ȏ�!��2 ��䰠W��0�W�x5��W`Hd��e�$,��X {�=bL�Il&�~$;~��S�/� � � Fs��� �+��mT=X��Y��/���>�Y��&|D�)����/g�3I$��'�3�hP$����g�&�c5U0^!�*�{@��f]^g�X%��%r���b��㜤�xUiy��;�)}��%�L�(���۾���|��9�c�Z��������8ζ�9� 4V3�A���˜����y�wF�U �#���/C�F��b���C (��߈L�$+�0���U'E��&��o�[�-?���_��9\����?#:��~�L��x5X:���a&�@2��j�AAAA�F�4u�8/8"q^� V*�؎��g��z�&�|�l�yAAR bfg��<�����Ɖ���v*�� � � �`Ӝ����>"/���}D}�G���G��V|Qs�XY���<��c9}e�W�M�G��rY���� � � ��=�A�L�7�K/����������o0_|�ڙ��MѠ^`��c��u� +l��`��G�3E��`.����N�ض��<�9Ϲg�x�I���v2Ŷ��:Òx�I�n�}�L�ma�DgXo;�1u2Ŷ�Nt�%�d�m����je�� � � � ����8���:5�����IEND�B`� \ No newline at end of file diff --git a/web/core/assets/vendor/ckeditor/plugins/image2/dialogs/image2.js b/web/core/assets/vendor/ckeditor/plugins/image2/dialogs/image2.js index df2c7d1c8c110fa0bee203987f0a6cba0fb46323..979ebd23024d03f45457c1a39c0bfbac639f5509 100644 --- a/web/core/assets/vendor/ckeditor/plugins/image2/dialogs/image2.js +++ b/web/core/assets/vendor/ckeditor/plugins/image2/dialogs/image2.js @@ -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"]}]}]}}); \ No newline at end of file diff --git a/web/core/assets/vendor/ckeditor/skins/moono-lisa/editor.css b/web/core/assets/vendor/ckeditor/skins/moono-lisa/editor.css index a7e9929ad5742cda976a3bba2229a4a4b81343b6..051a127ce316627c03cc7106df5ce7f9a0f6e40a 100644 --- a/web/core/assets/vendor/ckeditor/skins/moono-lisa/editor.css +++ b/web/core/assets/vendor/ckeditor/skins/moono-lisa/editor.css @@ -2,4 +2,4 @@ Copyright (c) 2003-2018, CKSource - Frederico Knabben. All rights reserved. For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license */ -.cke_reset{margin:0;padding:0;border:0;background:transparent;text-decoration:none;width:auto;height:auto;vertical-align:baseline;box-sizing:content-box;position:static;transition:none}.cke_reset_all,.cke_reset_all *,.cke_reset_all a,.cke_reset_all textarea{margin:0;padding:0;border:0;background:transparent;text-decoration:none;width:auto;height:auto;vertical-align:baseline;box-sizing:content-box;position:static;transition:none;border-collapse:collapse;font:normal normal normal 12px Arial,Helvetica,Tahoma,Verdana,Sans-Serif;color:#000;text-align:left;white-space:nowrap;cursor:auto;float:none}.cke_reset_all .cke_rtl *{text-align:right}.cke_reset_all iframe{vertical-align:inherit}.cke_reset_all textarea{white-space:pre-wrap}.cke_reset_all textarea,.cke_reset_all input[type="text"],.cke_reset_all input[type="password"]{cursor:text}.cke_reset_all textarea[disabled],.cke_reset_all input[type="text"][disabled],.cke_reset_all input[type="password"][disabled]{cursor:default}.cke_reset_all fieldset{padding:10px;border:2px groove #e0dfe3}.cke_reset_all select{box-sizing:border-box}.cke_reset_all table{table-layout:auto}.cke_chrome{display:block;border:1px solid #d1d1d1;padding:0}.cke_inner{display:block;background:#fff;padding:0;-webkit-touch-callout:none}.cke_float{border:0}.cke_float .cke_inner{padding-bottom:0}.cke_top,.cke_contents,.cke_bottom{display:block;overflow:hidden}.cke_top{border-bottom:1px solid #d1d1d1;background:#f8f8f8;padding:6px 8px 2px;white-space:normal}.cke_float .cke_top{border:1px solid #d1d1d1}.cke_bottom{padding:6px 8px 2px;position:relative;border-top:1px solid #d1d1d1;background:#f8f8f8}.cke_browser_ios .cke_contents{overflow-y:auto;-webkit-overflow-scrolling:touch}.cke_resizer{width:0;height:0;overflow:hidden;border-width:10px 10px 0 0;border-color:transparent #bcbcbc transparent transparent;border-style:dashed solid dashed dashed;font-size:0;vertical-align:bottom;margin-top:6px;margin-bottom:2px}.cke_hc .cke_resizer{font-size:15px;width:auto;height:auto;border-width:0}.cke_resizer_ltr{cursor:se-resize;float:right;margin-right:-4px}.cke_resizer_rtl{border-width:10px 0 0 10px;border-color:transparent transparent transparent #bcbcbc;border-style:dashed dashed dashed solid;cursor:sw-resize;float:left;margin-left:-4px;right:auto}.cke_wysiwyg_div{display:block;height:100%;overflow:auto;padding:0 8px;outline-style:none;box-sizing:border-box}.cke_panel{visibility:visible;width:120px;height:100px;overflow:hidden;background-color:#fff;border:1px solid #d1d1d1}.cke_menu_panel{padding:0;margin:0}.cke_combopanel{width:150px;height:170px}.cke_panel_frame{width:100%;height:100%;font-size:12px;overflow:auto;overflow-x:hidden}.cke_panel_container{overflow-y:auto;overflow-x:hidden}.cke_panel_block:focus{outline:0}.cke_panel_list{margin:0;padding:0;list-style-type:none;white-space:nowrap}.cke_panel_listItem{margin:0;padding:0}.cke_panel_listItem a{padding:6px 7px;display:block;color:inherit!important;text-decoration:none;overflow:hidden;text-overflow:ellipsis}.cke_hc .cke_panel_listItem a{border-style:none}.cke_panel_listItem.cke_selected a,.cke_panel_listItem a:hover,.cke_panel_listItem a:focus,.cke_panel_listItem a:active{background-color:#e9e9e9}.cke_panel_listItem a:focus{outline:1px dotted #000}.cke_hc .cke_panel_listItem a:hover,.cke_hc .cke_panel_listItem a:focus,.cke_hc .cke_panel_listItem a:active{border:2px solid;padding:4px 5px}.cke_panel_listItem p,.cke_panel_listItem h1,.cke_panel_listItem h2,.cke_panel_listItem h3,.cke_panel_listItem h4,.cke_panel_listItem h5,.cke_panel_listItem h6,.cke_panel_listItem pre{margin-top:0;margin-bottom:0}.cke_panel_grouptitle{cursor:default;font-size:11px;font-weight:bold;white-space:nowrap;margin:0;padding:6px 6px 7px 6px;color:#484848;border-bottom:1px solid #d1d1d1;background:#f8f8f8}.cke_colorblock{padding:10px;font-size:11px;font-family:'Microsoft Sans Serif',Tahoma,Arial,Verdana,Sans-Serif}.cke_colorblock,.cke_colorblock a{text-decoration:none;color:#000}a.cke_colorbox{padding:2px;float:left;width:20px;height:20px}.cke_rtl a.cke_colorbox{float:right}a:hover.cke_colorbox,a:focus.cke_colorbox,a:active.cke_colorbox{outline:0;padding:0;border:2px solid #139ff7}a:hover.cke_colorbox{border-color:#bcbcbc}span.cke_colorbox{width:20px;height:20px;float:left}.cke_rtl span.cke_colorbox{float:right}a.cke_colorauto,a.cke_colormore{border:#fff 1px solid;padding:3px;display:block;cursor:pointer}a.cke_colorauto{padding:0;border:1px solid transparent;margin-bottom:6px;height:26px;line-height:26px}a.cke_colormore{margin-top:10px;height:20px;line-height:19px}a:hover.cke_colorauto,a:hover.cke_colormore,a:focus.cke_colorauto,a:focus.cke_colormore,a:active.cke_colorauto,a:active.cke_colormore{outline:0;border:#139ff7 1px solid;background-color:#f8f8f8}a:hover.cke_colorauto,a:hover.cke_colormore{border-color:#bcbcbc}.cke_colorauto span.cke_colorbox{width:18px;height:18px;border:1px solid #808080;margin-left:1px;margin-top:3px}.cke_rtl .cke_colorauto span.cke_colorbox{margin-left:0;margin-right:1px}span.cke_colorbox[style*="#ffffff"],span.cke_colorbox[style*="#FFFFFF"],span.cke_colorbox[style="background-color:#fff"],span.cke_colorbox[style="background-color:#FFF"],span.cke_colorbox[style*="rgb(255,255,255)"],span.cke_colorbox[style*="rgb(255, 255, 255)"]{border:1px solid #808080;width:18px;height:18px}.cke_toolbar{float:left}.cke_rtl .cke_toolbar{float:right}.cke_toolgroup{border:0;float:left;margin:1px 2px 6px 0;padding-right:3px}.cke_rtl .cke_toolgroup{float:right;margin:1px 0 6px 2px;padding-left:3px;padding-right:0}.cke_hc .cke_toolgroup{margin-right:5px;margin-bottom:5px}.cke_hc.cke_rtl .cke_toolgroup{margin-right:0;margin-left:5px}a.cke_button{display:inline-block;height:18px;padding:4px 6px;outline:0;cursor:default;float:left;border:0;position:relative}.cke_rtl a.cke_button{float:right}.cke_hc a.cke_button{border:1px solid black;padding:3px 5px;margin:0 3px 5px 0}.cke_hc.cke_rtl a.cke_button{margin:0 0 5px 3px}a.cke_button_on{background:#fff;border:1px #bcbcbc solid;padding:3px 5px}a.cke_button_off:hover,a.cke_button_off:focus,a.cke_button_off:active{background:#e5e5e5;border:1px #bcbcbc solid;padding:3px 5px}.cke_hc a.cke_button_on,.cke_hc a.cke_button_off:hover,.cke_hc a.cke_button_off:focus,.cke_hc a.cke_button_off:active{background:#e5e5e5;border:3px solid #000;padding:1px 3px}a.cke_button_disabled:hover,a.cke_button_disabled:focus,a.cke_button_disabled:active{border:0;padding:4px 6px;background-color:transparent}a.cke_button_disabled:focus{border:1px #bcbcbc solid;padding:3px 5px}.cke_hc a.cke_button_disabled:hover,.cke_hc a.cke_button_disabled:focus,.cke_hc a.cke_button_disabled:active{border:1px solid #acacac;padding:3px 5px;margin:0 3px 5px 0}.cke_hc a.cke_button_disabled:focus{border:3px solid #000;padding:1px 3px}.cke_hc.cke_rtl a.cke_button_disabled:hover,.cke_hc.cke_rtl a.cke_button_disabled:focus,.cke_hc.cke_rtl a.cke_button_disabled:active{margin:0 0 5px 3px}a.cke_button_disabled .cke_button_icon,a.cke_button_disabled .cke_button_arrow{opacity:.3}.cke_hc a.cke_button_disabled{border-color:#acacac}.cke_hc a.cke_button_disabled .cke_button_icon,.cke_hc a.cke_button_disabled .cke_button_label{opacity:.5}.cke_toolgroup a.cke_button:last-child:after,.cke_toolgroup a.cke_button.cke_button_disabled:hover:last-child:after{content:"";position:absolute;height:18px;width:0;border-right:1px solid #bcbcbc;margin-top:4px;top:0;right:-3px}.cke_rtl .cke_toolgroup a.cke_button:last-child:after,.cke_rtl .cke_toolgroup a.cke_button.cke_button_disabled:hover:last-child:after{border-right:0;right:auto;border-left:1px solid #bcbcbc;top:0;left:-3px}.cke_hc .cke_toolgroup a.cke_button:last-child:after,.cke_hc .cke_toolgroup a.cke_button.cke_button_disabled:last-child:after,.cke_hc .cke_toolgroup a.cke_button.cke_button_disabled:hover:last-child:after{border-color:#000;top:0;right:-7px}.cke_hc.cke_rtl .cke_toolgroup a.cke_button:last-child:after,.cke_hc.cke_rtl .cke_toolgroup a.cke_button.cke_button_disabled:last-child:after,.cke_hc.cke_rtl .cke_toolgroup a.cke_button.cke_button_disabled:hover:last-child:after{top:0;right:auto;left:-7px}.cke_toolgroup a.cke_button:hover:last-child:after,.cke_toolgroup a.cke_button.cke_button_on:last-child:after{top:-1px;right:-4px}.cke_rtl .cke_toolgroup a.cke_button:hover:last-child:after,.cke_rtl .cke_toolgroup a.cke_button.cke_button_on:last-child:after{top:-1px;right:auto;left:-4px}.cke_hc .cke_toolgroup a.cke_button:hover:last-child:after,.cke_hc .cke_toolgroup a.cke_button.cke_button_on:last-child:after{top:-2px;right:-9px}.cke_hc.cke_rtl .cke_toolgroup a.cke_button:hover:last-child:after,.cke_hc.cke_rtl .cke_toolgroup a.cke_button.cke_button_on:last-child:after{top:-2px;right:auto;left:-9px}.cke_toolbar.cke_toolbar_last .cke_toolgroup a.cke_button:last-child:after{content:none;border:0;width:0;height:0}.cke_button_icon{cursor:inherit;background-repeat:no-repeat;margin-top:1px;width:16px;height:16px;float:left;display:inline-block}.cke_rtl .cke_button_icon{float:right}.cke_hc .cke_button_icon{display:none}.cke_button_label{display:none;padding-left:3px;margin-top:1px;line-height:17px;vertical-align:middle;float:left;cursor:default;color:#484848}.cke_rtl .cke_button_label{padding-right:3px;padding-left:0;float:right}.cke_hc .cke_button_label{padding:0;display:inline-block;font-size:12px}.cke_button_arrow{display:inline-block;margin:8px 0 0 1px;width:0;height:0;cursor:default;vertical-align:top;border-left:3px solid transparent;border-right:3px solid transparent;border-top:3px solid #484848}.cke_rtl .cke_button_arrow{margin-right:5px;margin-left:0}.cke_hc .cke_button_arrow{font-size:10px;margin:3px 0 0 3px;width:auto;border:0}.cke_toolbar_separator{float:left;background-color:#bcbcbc;margin:4px 2px 0 2px;height:18px;width:1px}.cke_rtl .cke_toolbar_separator{float:right}.cke_hc .cke_toolbar_separator{background-color:#000;margin-left:2px;margin-right:5px;margin-bottom:9px}.cke_hc.cke_rtl .cke_toolbar_separator{margin-left:5px;margin-right:2px}.cke_toolbar_break{display:block;clear:left}.cke_rtl .cke_toolbar_break{clear:right}a.cke_toolbox_collapser{width:12px;height:11px;float:right;margin:11px 0 0;font-size:0;cursor:default;text-align:center;border:1px solid #bcbcbc}.cke_rtl .cke_toolbox_collapser{float:left}.cke_toolbox_collapser:hover{background:#e5e5e5}.cke_toolbox_collapser.cke_toolbox_collapser_min{margin:0 2px 4px}.cke_toolbox_collapser .cke_arrow{display:inline-block;height:0;width:0;font-size:0;margin-top:1px;border:3px solid transparent;border-bottom-color:#484848}.cke_toolbox_collapser.cke_toolbox_collapser_min .cke_arrow{margin-top:4px;border-bottom-color:transparent;border-top-color:#484848}.cke_hc .cke_toolbox_collapser .cke_arrow{font-size:8px;width:auto;border:0;margin-top:0}.cke_menuitem span{cursor:default}.cke_menubutton{display:block}.cke_hc .cke_menubutton{padding:2px}.cke_menubutton:hover,.cke_menubutton:focus,.cke_menubutton:active{background-color:#e9e9e9;display:block;outline:1px dotted}.cke_menubutton:hover{outline:0}.cke_hc .cke_menubutton:hover,.cke_hc .cke_menubutton:focus,.cke_hc .cke_menubutton:active{border:2px solid;padding:0}.cke_menubutton_disabled:hover,.cke_menubutton_disabled:focus,.cke_menubutton_disabled:active{background-color:transparent;outline:0}.cke_menubutton_inner{display:table-row}.cke_menubutton_icon,.cke_menubutton_label,.cke_menuarrow{display:table-cell}.cke_menubutton_icon{background-color:#f8f8f8;padding:6px 4px}.cke_hc .cke_menubutton_icon{height:16px;width:0;padding:4px 0}.cke_menubutton:hover .cke_menubutton_icon,.cke_menubutton:focus .cke_menubutton_icon,.cke_menubutton:active .cke_menubutton_icon{background-color:#e9e9e9}.cke_menubutton_disabled:hover .cke_menubutton_icon,.cke_menubutton_disabled:focus .cke_menubutton_icon,.cke_menubutton_disabled:active .cke_menubutton_icon{background-color:#f8f8f8;outline:0}.cke_menuitem .cke_menubutton_on{background-color:#e9e9e9;border:1px solid #dedede;outline:0}.cke_menubutton_on .cke_menubutton_icon{padding-right:3px;background-color:#e9e9e9}.cke_menubutton_label{padding:0 5px;background-color:transparent;width:100%;vertical-align:middle}.cke_menubutton_shortcut{color:#979797}.cke_menubutton_disabled .cke_menubutton_label{opacity:.3;filter:alpha(opacity=30)}.cke_panel_frame .cke_menubutton_label{display:none}.cke_menuseparator{background-color:#d1d1d1;height:1px}.cke_menuarrow{background:transparent url(images/arrow.png) no-repeat 0 10px;padding:0 5px}.cke_rtl .cke_menuarrow{background-position:5px -13px;background-repeat:no-repeat}.cke_hc .cke_menuarrow{background-image:none}.cke_menuarrow span{display:none}.cke_hc .cke_menuarrow span{vertical-align:middle;display:inline}.cke_combo{display:inline-block;float:left;position:relative;margin-bottom:5px}.cke_rtl .cke_combo{float:right}.cke_hc .cke_combo{margin-top:1px;margin-bottom:10px}.cke_combo:after{content:"";position:absolute;height:18px;width:0;border-right:1px solid #bcbcbc;margin-top:5px;top:0;right:0}.cke_rtl .cke_combo:after{border-right:0;border-left:1px solid #bcbcbc;right:auto;left:0}.cke_hc .cke_combo:after{border-color:#000}a.cke_combo_button{cursor:default;display:inline-block;float:left;margin:0;padding:1px}.cke_rtl a.cke_combo_button{float:right}.cke_hc a.cke_combo_button{padding:4px}.cke_combo_on a.cke_combo_button,.cke_combo_off a.cke_combo_button:hover,.cke_combo_off a.cke_combo_button:focus,.cke_combo_off a.cke_combo_button:active{background:#e5e5e5;border:1px solid #bcbcbc;padding:0 0 0 1px;margin-left:-1px}.cke_combo_off a.cke_combo_button:focus{outline:0}.cke_combo_on a.cke_combo_button,.cke_combo_off a.cke_combo_button:active{background:#fff}.cke_rtl .cke_combo_on a.cke_combo_button,.cke_rtl .cke_combo_off a.cke_combo_button:hover,.cke_rtl .cke_combo_off a.cke_combo_button:focus,.cke_rtl .cke_combo_off a.cke_combo_button:active{padding:0 1px 0 0;margin-left:0;margin-right:-1px}.cke_hc .cke_combo_on a.cke_combo_button,.cke_hc .cke_combo_off a.cke_combo_button:hover,.cke_hc .cke_combo_off a.cke_combo_button:focus,.cke_hc .cke_combo_off a.cke_combo_button:active{border:3px solid #000;padding:1px 1px 1px 2px}.cke_hc.cke_rtl .cke_combo_on a.cke_combo_button,.cke_hc.cke_rtl .cke_combo_off a.cke_combo_button:hover,.cke_hc.cke_rtl .cke_combo_off a.cke_combo_button:focus,.cke_hc.cke_rtl .cke_combo_off a.cke_combo_button:active{padding:1px 2px 1px 1px}.cke_toolbar_start+.cke_combo_on a.cke_combo_button,.cke_toolbar_start+.cke_combo_off a.cke_combo_button:hover,.cke_toolbar_start+.cke_combo_off a.cke_combo_button:focus,.cke_toolbar_start+.cke_combo_off a.cke_combo_button:active{padding:0 0 0 3px;margin-left:-3px}.cke_rtl .cke_toolbar_start+.cke_combo_on a.cke_combo_button,.cke_rtl .cke_toolbar_start+.cke_combo_off a.cke_combo_button:hover,.cke_rtl .cke_toolbar_start+.cke_combo_off a.cke_combo_button:focus,.cke_rtl .cke_toolbar_start+.cke_combo_off a.cke_combo_button:active{padding:0 3px 0 0;margin-left:0;margin-right:-3px}.cke_hc .cke_toolbar>.cke_toolbar_start+.cke_combo_on a.cke_combo_button,.cke_hc .cke_toolbar>.cke_toolbar_start+.cke_combo_off a.cke_combo_button:hover,.cke_hc .cke_toolbar>.cke_toolbar_start+.cke_combo_off a.cke_combo_button:focus,.cke_hc .cke_toolbar>.cke_toolbar_start+.cke_combo_off a.cke_combo_button:active{padding:1px 1px 1px 7px;margin-left:-6px}.cke_hc.cke_rtl .cke_toolbar>.cke_toolbar_start+.cke_combo_on a.cke_combo_button,.cke_hc.cke_rtl .cke_toolbar>.cke_toolbar_start+.cke_combo_off a.cke_combo_button:hover,.cke_hc.cke_rtl .cke_toolbar>.cke_toolbar_start+.cke_combo_off a.cke_combo_button:focus,.cke_hc.cke_rtl .cke_toolbar>.cke_toolbar_start+.cke_combo_off a.cke_combo_button:active{padding:1px 7px 1px 1px;margin-left:0;margin-right:-6px}.cke_toolbox .cke_toolbar:first-child>.cke_toolbar_start+.cke_combo_on a.cke_combo_button,.cke_toolbox .cke_toolbar:first-child>.cke_toolbar_start+.cke_combo_off a.cke_combo_button:hover,.cke_toolbox .cke_toolbar:first-child>.cke_toolbar_start+.cke_combo_off a.cke_combo_button:focus,.cke_toolbox .cke_toolbar:first-child>.cke_toolbar_start+.cke_combo_off a.cke_combo_button:active,.cke_toolbar_break+.cke_toolbar>.cke_toolbar_start+.cke_combo_on a.cke_combo_button,.cke_toolbar_break+.cke_toolbar>.cke_toolbar_start+.cke_combo_off a.cke_combo_button:hover,.cke_toolbar_break+.cke_toolbar>.cke_toolbar_start+.cke_combo_off a.cke_combo_button:focus,.cke_toolbar_break+.cke_toolbar>.cke_toolbar_start+.cke_combo_off a.cke_combo_button:active{padding:0;margin:0}.cke_hc .cke_toolbox .cke_toolbar:first-child>.cke_toolbar_start+.cke_combo_on a.cke_combo_button,.cke_hc .cke_toolbox .cke_toolbar:first-child>.cke_toolbar_start+.cke_combo_off a.cke_combo_button:hover,.cke_hc .cke_toolbox .cke_toolbar:first-child>.cke_toolbar_start+.cke_combo_off a.cke_combo_button:focus,.cke_hc .cke_toolbox .cke_toolbar:first-child>.cke_toolbar_start+.cke_combo_off a.cke_combo_button:active,.cke_hc .cke_toolbar_break+.cke_toolbar>.cke_toolbar_start+.cke_combo_on a.cke_combo_button,.cke_hc .cke_toolbar_break+.cke_toolbar>.cke_toolbar_start+.cke_combo_off a.cke_combo_button:hover,.cke_hc .cke_toolbar_break+.cke_toolbar>.cke_toolbar_start+.cke_combo_off a.cke_combo_button:focus,.cke_hc .cke_toolbar_break+.cke_toolbar>.cke_toolbar_start+.cke_combo_off a.cke_combo_button:active{padding:1px;margin:0}.cke_toolbar .cke_combo+.cke_toolbar_end,.cke_toolbar .cke_combo+.cke_toolgroup{margin-right:0;margin-left:2px}.cke_rtl .cke_toolbar .cke_combo+.cke_toolbar_end,.cke_rtl .cke_toolbar .cke_combo+.cke_toolgroup{margin-left:0;margin-right:2px}.cke_hc .cke_toolbar .cke_combo+.cke_toolbar_end,.cke_hc .cke_toolbar .cke_combo+.cke_toolgroup{margin-left:5px}.cke_hc.cke_rtl .cke_toolbar .cke_combo+.cke_toolbar_end,.cke_hc.cke_rtl .cke_toolbar .cke_combo+.cke_toolgroup{margin-left:0;margin-right:5px}.cke_toolbar.cke_toolbar_last .cke_combo:nth-last-child(-n+2):after{content:none;border:0;width:0;height:0}.cke_combo_text{line-height:26px;padding-left:10px;text-overflow:ellipsis;overflow:hidden;float:left;cursor:default;color:#484848;width:60px}.cke_rtl .cke_combo_text{float:right;text-align:right;padding-left:0;padding-right:10px}.cke_hc .cke_combo_text{line-height:18px;font-size:12px}.cke_combo_open{cursor:default;display:inline-block;font-size:0;height:19px;line-height:17px;margin:1px 10px 1px;width:5px}.cke_hc .cke_combo_open{height:12px}.cke_combo_arrow{cursor:default;margin:11px 0 0;float:left;height:0;width:0;font-size:0;border-left:3px solid transparent;border-right:3px solid transparent;border-top:3px solid #484848}.cke_hc .cke_combo_arrow{font-size:10px;width:auto;border:0;margin-top:3px}.cke_combo_label{display:none;float:left;line-height:26px;vertical-align:top;margin-right:5px}.cke_rtl .cke_combo_label{float:right;margin-left:5px;margin-right:0}.cke_combo_disabled .cke_combo_inlinelabel,.cke_combo_disabled .cke_combo_open{opacity:.3}.cke_path{float:left;margin:-2px 0 2px}a.cke_path_item,span.cke_path_empty{display:inline-block;float:left;padding:3px 4px;margin-right:2px;cursor:default;text-decoration:none;outline:0;border:0;color:#484848;font-weight:bold;font-size:11px}.cke_rtl .cke_path,.cke_rtl .cke_path_item,.cke_rtl .cke_path_empty{float:right}a.cke_path_item:hover,a.cke_path_item:focus,a.cke_path_item:active{background-color:#e5e5e5}.cke_hc a.cke_path_item:hover,.cke_hc a.cke_path_item:focus,.cke_hc a.cke_path_item:active{border:2px solid;padding:1px 2px}.cke_button__source_label,.cke_button__sourcedialog_label{display:inline}.cke_combopanel__fontsize{width:135px}textarea.cke_source{font-family:'Courier New',Monospace;font-size:small;background-color:#fff;white-space:pre-wrap;border:0;padding:0;margin:0;display:block}.cke_wysiwyg_frame,.cke_wysiwyg_div{background-color:#fff}.cke_notifications_area{pointer-events:none}.cke_notification{pointer-events:auto;position:relative;margin:10px;width:300px;color:white;text-align:center;opacity:.95;filter:alpha(opacity = 95);-webkit-animation:fadeIn .7s;animation:fadeIn .7s}.cke_notification_message a{color:#12306f}@-webkit-keyframes fadeIn{from{opacity:.4}to{opacity:.95}}@keyframes fadeIn{from{opacity:.4}to{opacity:.95}}.cke_notification_success{background:#72b572;border:1px solid #63a563}.cke_notification_warning{background:#c83939;border:1px solid #902b2b}.cke_notification_info{background:#2e9ad0;border:1px solid #0f74a8}.cke_notification_info span.cke_notification_progress{background-color:#0f74a8;display:block;padding:0;margin:0;height:100%;overflow:hidden;position:absolute;z-index:1}.cke_notification_message{position:relative;margin:4px 23px 3px;font-family:Arial,Helvetica,sans-serif;font-size:12px;line-height:18px;z-index:4;text-overflow:ellipsis;overflow:hidden}.cke_notification_close{background-image:url(images/close.png);background-repeat:no-repeat;background-position:50%;position:absolute;cursor:pointer;text-align:center;height:20px;width:20px;top:1px;right:1px;padding:0;margin:0;z-index:5;opacity:.6;filter:alpha(opacity = 60)}.cke_notification_close:hover{opacity:1;filter:alpha(opacity = 100)}.cke_notification_close span{display:none}.cke_notification_warning a.cke_notification_close{opacity:.8;filter:alpha(opacity = 80)}.cke_notification_warning a.cke_notification_close:hover{opacity:1;filter:alpha(opacity = 100)}.cke_chrome{visibility:inherit}.cke_voice_label{display:none}legend.cke_voice_label{display:none}.cke_button__about_icon{background:url(icons.png?t=I648) no-repeat 0 -0px!important}.cke_button__bold_icon{background:url(icons.png?t=I648) no-repeat 0 -24px!important}.cke_button__italic_icon{background:url(icons.png?t=I648) no-repeat 0 -48px!important}.cke_button__strike_icon{background:url(icons.png?t=I648) no-repeat 0 -72px!important}.cke_button__subscript_icon{background:url(icons.png?t=I648) no-repeat 0 -96px!important}.cke_button__superscript_icon{background:url(icons.png?t=I648) no-repeat 0 -120px!important}.cke_button__underline_icon{background:url(icons.png?t=I648) no-repeat 0 -144px!important}.cke_button__blockquote_icon{background:url(icons.png?t=I648) no-repeat 0 -168px!important}.cke_rtl .cke_button__copy_icon,.cke_mixed_dir_content .cke_rtl .cke_button__copy_icon{background:url(icons.png?t=I648) no-repeat 0 -192px!important}.cke_ltr .cke_button__copy_icon{background:url(icons.png?t=I648) no-repeat 0 -216px!important}.cke_rtl .cke_button__cut_icon,.cke_mixed_dir_content .cke_rtl .cke_button__cut_icon{background:url(icons.png?t=I648) no-repeat 0 -240px!important}.cke_ltr .cke_button__cut_icon{background:url(icons.png?t=I648) no-repeat 0 -264px!important}.cke_rtl .cke_button__paste_icon,.cke_mixed_dir_content .cke_rtl .cke_button__paste_icon{background:url(icons.png?t=I648) no-repeat 0 -288px!important}.cke_ltr .cke_button__paste_icon{background:url(icons.png?t=I648) no-repeat 0 -312px!important}.cke_button__horizontalrule_icon{background:url(icons.png?t=I648) no-repeat 0 -336px!important}.cke_button__image_icon{background:url(icons.png?t=I648) no-repeat 0 -360px!important}.cke_rtl .cke_button__indent_icon,.cke_mixed_dir_content .cke_rtl .cke_button__indent_icon{background:url(icons.png?t=I648) no-repeat 0 -384px!important}.cke_ltr .cke_button__indent_icon{background:url(icons.png?t=I648) no-repeat 0 -408px!important}.cke_rtl .cke_button__outdent_icon,.cke_mixed_dir_content .cke_rtl .cke_button__outdent_icon{background:url(icons.png?t=I648) no-repeat 0 -432px!important}.cke_ltr .cke_button__outdent_icon{background:url(icons.png?t=I648) no-repeat 0 -456px!important}.cke_button__justifyblock_icon{background:url(icons.png?t=I648) no-repeat 0 -480px!important}.cke_button__justifycenter_icon{background:url(icons.png?t=I648) no-repeat 0 -504px!important}.cke_button__justifyleft_icon{background:url(icons.png?t=I648) no-repeat 0 -528px!important}.cke_button__justifyright_icon{background:url(icons.png?t=I648) no-repeat 0 -552px!important}.cke_button__language_icon{background:url(icons.png?t=I648) no-repeat 0 -576px!important}.cke_rtl .cke_button__bulletedlist_icon,.cke_mixed_dir_content .cke_rtl .cke_button__bulletedlist_icon{background:url(icons.png?t=I648) no-repeat 0 -600px!important}.cke_ltr .cke_button__bulletedlist_icon{background:url(icons.png?t=I648) no-repeat 0 -624px!important}.cke_rtl .cke_button__numberedlist_icon,.cke_mixed_dir_content .cke_rtl .cke_button__numberedlist_icon{background:url(icons.png?t=I648) no-repeat 0 -648px!important}.cke_ltr .cke_button__numberedlist_icon{background:url(icons.png?t=I648) no-repeat 0 -672px!important}.cke_button__maximize_icon{background:url(icons.png?t=I648) no-repeat 0 -696px!important}.cke_rtl .cke_button__pastefromword_icon,.cke_mixed_dir_content .cke_rtl .cke_button__pastefromword_icon{background:url(icons.png?t=I648) no-repeat 0 -720px!important}.cke_ltr .cke_button__pastefromword_icon{background:url(icons.png?t=I648) no-repeat 0 -744px!important}.cke_rtl .cke_button__pastetext_icon,.cke_mixed_dir_content .cke_rtl .cke_button__pastetext_icon{background:url(icons.png?t=I648) no-repeat 0 -768px!important}.cke_ltr .cke_button__pastetext_icon{background:url(icons.png?t=I648) no-repeat 0 -792px!important}.cke_button__removeformat_icon{background:url(icons.png?t=I648) no-repeat 0 -816px!important}.cke_rtl .cke_button__showblocks_icon,.cke_mixed_dir_content .cke_rtl .cke_button__showblocks_icon{background:url(icons.png?t=I648) no-repeat 0 -840px!important}.cke_ltr .cke_button__showblocks_icon{background:url(icons.png?t=I648) no-repeat 0 -864px!important}.cke_rtl .cke_button__source_icon,.cke_mixed_dir_content .cke_rtl .cke_button__source_icon{background:url(icons.png?t=I648) no-repeat 0 -888px!important}.cke_ltr .cke_button__source_icon{background:url(icons.png?t=I648) no-repeat 0 -912px!important}.cke_rtl .cke_button__sourcedialog_icon,.cke_mixed_dir_content .cke_rtl .cke_button__sourcedialog_icon{background:url(icons.png?t=I648) no-repeat 0 -936px!important}.cke_ltr .cke_button__sourcedialog_icon{background:url(icons.png?t=I648) no-repeat 0 -960px!important}.cke_button__specialchar_icon{background:url(icons.png?t=I648) no-repeat 0 -984px!important}.cke_button__table_icon{background:url(icons.png?t=I648) no-repeat 0 -1008px!important}.cke_rtl .cke_button__redo_icon,.cke_mixed_dir_content .cke_rtl .cke_button__redo_icon{background:url(icons.png?t=I648) no-repeat 0 -1032px!important}.cke_ltr .cke_button__redo_icon{background:url(icons.png?t=I648) no-repeat 0 -1056px!important}.cke_rtl .cke_button__undo_icon,.cke_mixed_dir_content .cke_rtl .cke_button__undo_icon{background:url(icons.png?t=I648) no-repeat 0 -1080px!important}.cke_ltr .cke_button__undo_icon{background:url(icons.png?t=I648) no-repeat 0 -1104px!important}.cke_button__simplebox_icon{background:url(icons.png?t=I648) no-repeat 0 -1128px!important}.cke_hidpi .cke_button__about_icon{background:url(icons_hidpi.png?t=I648) no-repeat 0 -0px!important;background-size:16px!important}.cke_hidpi .cke_button__bold_icon{background:url(icons_hidpi.png?t=I648) no-repeat 0 -24px!important;background-size:16px!important}.cke_hidpi .cke_button__italic_icon{background:url(icons_hidpi.png?t=I648) no-repeat 0 -48px!important;background-size:16px!important}.cke_hidpi .cke_button__strike_icon{background:url(icons_hidpi.png?t=I648) no-repeat 0 -72px!important;background-size:16px!important}.cke_hidpi .cke_button__subscript_icon{background:url(icons_hidpi.png?t=I648) no-repeat 0 -96px!important;background-size:16px!important}.cke_hidpi .cke_button__superscript_icon{background:url(icons_hidpi.png?t=I648) no-repeat 0 -120px!important;background-size:16px!important}.cke_hidpi .cke_button__underline_icon{background:url(icons_hidpi.png?t=I648) no-repeat 0 -144px!important;background-size:16px!important}.cke_hidpi .cke_button__blockquote_icon{background:url(icons_hidpi.png?t=I648) no-repeat 0 -168px!important;background-size:16px!important}.cke_rtl.cke_hidpi .cke_button__copy_icon,.cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__copy_icon{background:url(icons_hidpi.png?t=I648) no-repeat 0 -192px!important;background-size:16px!important}.cke_hidpi .cke_ltr .cke_button__copy_icon,.cke_ltr.cke_hidpi .cke_button__copy_icon{background:url(icons_hidpi.png?t=I648) no-repeat 0 -216px!important;background-size:16px!important}.cke_rtl.cke_hidpi .cke_button__cut_icon,.cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__cut_icon{background:url(icons_hidpi.png?t=I648) no-repeat 0 -240px!important;background-size:16px!important}.cke_hidpi .cke_ltr .cke_button__cut_icon,.cke_ltr.cke_hidpi .cke_button__cut_icon{background:url(icons_hidpi.png?t=I648) no-repeat 0 -264px!important;background-size:16px!important}.cke_rtl.cke_hidpi .cke_button__paste_icon,.cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__paste_icon{background:url(icons_hidpi.png?t=I648) no-repeat 0 -288px!important;background-size:16px!important}.cke_hidpi .cke_ltr .cke_button__paste_icon,.cke_ltr.cke_hidpi .cke_button__paste_icon{background:url(icons_hidpi.png?t=I648) no-repeat 0 -312px!important;background-size:16px!important}.cke_hidpi .cke_button__horizontalrule_icon{background:url(icons_hidpi.png?t=I648) no-repeat 0 -336px!important;background-size:16px!important}.cke_hidpi .cke_button__image_icon{background:url(icons_hidpi.png?t=I648) no-repeat 0 -360px!important;background-size:16px!important}.cke_rtl.cke_hidpi .cke_button__indent_icon,.cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__indent_icon{background:url(icons_hidpi.png?t=I648) no-repeat 0 -384px!important;background-size:16px!important}.cke_hidpi .cke_ltr .cke_button__indent_icon,.cke_ltr.cke_hidpi .cke_button__indent_icon{background:url(icons_hidpi.png?t=I648) no-repeat 0 -408px!important;background-size:16px!important}.cke_rtl.cke_hidpi .cke_button__outdent_icon,.cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__outdent_icon{background:url(icons_hidpi.png?t=I648) no-repeat 0 -432px!important;background-size:16px!important}.cke_hidpi .cke_ltr .cke_button__outdent_icon,.cke_ltr.cke_hidpi .cke_button__outdent_icon{background:url(icons_hidpi.png?t=I648) no-repeat 0 -456px!important;background-size:16px!important}.cke_hidpi .cke_button__justifyblock_icon{background:url(icons_hidpi.png?t=I648) no-repeat 0 -480px!important;background-size:16px!important}.cke_hidpi .cke_button__justifycenter_icon{background:url(icons_hidpi.png?t=I648) no-repeat 0 -504px!important;background-size:16px!important}.cke_hidpi .cke_button__justifyleft_icon{background:url(icons_hidpi.png?t=I648) no-repeat 0 -528px!important;background-size:16px!important}.cke_hidpi .cke_button__justifyright_icon{background:url(icons_hidpi.png?t=I648) no-repeat 0 -552px!important;background-size:16px!important}.cke_hidpi .cke_button__language_icon{background:url(icons_hidpi.png?t=I648) no-repeat 0 -576px!important;background-size:16px!important}.cke_rtl.cke_hidpi .cke_button__bulletedlist_icon,.cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__bulletedlist_icon{background:url(icons_hidpi.png?t=I648) no-repeat 0 -600px!important;background-size:16px!important}.cke_hidpi .cke_ltr .cke_button__bulletedlist_icon,.cke_ltr.cke_hidpi .cke_button__bulletedlist_icon{background:url(icons_hidpi.png?t=I648) no-repeat 0 -624px!important;background-size:16px!important}.cke_rtl.cke_hidpi .cke_button__numberedlist_icon,.cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__numberedlist_icon{background:url(icons_hidpi.png?t=I648) no-repeat 0 -648px!important;background-size:16px!important}.cke_hidpi .cke_ltr .cke_button__numberedlist_icon,.cke_ltr.cke_hidpi .cke_button__numberedlist_icon{background:url(icons_hidpi.png?t=I648) no-repeat 0 -672px!important;background-size:16px!important}.cke_hidpi .cke_button__maximize_icon{background:url(icons_hidpi.png?t=I648) no-repeat 0 -696px!important;background-size:16px!important}.cke_rtl.cke_hidpi .cke_button__pastefromword_icon,.cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__pastefromword_icon{background:url(icons_hidpi.png?t=I648) no-repeat 0 -720px!important;background-size:16px!important}.cke_hidpi .cke_ltr .cke_button__pastefromword_icon,.cke_ltr.cke_hidpi .cke_button__pastefromword_icon{background:url(icons_hidpi.png?t=I648) no-repeat 0 -744px!important;background-size:16px!important}.cke_rtl.cke_hidpi .cke_button__pastetext_icon,.cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__pastetext_icon{background:url(icons_hidpi.png?t=I648) no-repeat 0 -768px!important;background-size:16px!important}.cke_hidpi .cke_ltr .cke_button__pastetext_icon,.cke_ltr.cke_hidpi .cke_button__pastetext_icon{background:url(icons_hidpi.png?t=I648) no-repeat 0 -792px!important;background-size:16px!important}.cke_hidpi .cke_button__removeformat_icon{background:url(icons_hidpi.png?t=I648) no-repeat 0 -816px!important;background-size:16px!important}.cke_rtl.cke_hidpi .cke_button__showblocks_icon,.cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__showblocks_icon{background:url(icons_hidpi.png?t=I648) no-repeat 0 -840px!important;background-size:16px!important}.cke_hidpi .cke_ltr .cke_button__showblocks_icon,.cke_ltr.cke_hidpi .cke_button__showblocks_icon{background:url(icons_hidpi.png?t=I648) no-repeat 0 -864px!important;background-size:16px!important}.cke_rtl.cke_hidpi .cke_button__source_icon,.cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__source_icon{background:url(icons_hidpi.png?t=I648) no-repeat 0 -888px!important;background-size:16px!important}.cke_hidpi .cke_ltr .cke_button__source_icon,.cke_ltr.cke_hidpi .cke_button__source_icon{background:url(icons_hidpi.png?t=I648) no-repeat 0 -912px!important;background-size:16px!important}.cke_rtl.cke_hidpi .cke_button__sourcedialog_icon,.cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__sourcedialog_icon{background:url(icons_hidpi.png?t=I648) no-repeat 0 -936px!important;background-size:16px!important}.cke_hidpi .cke_ltr .cke_button__sourcedialog_icon,.cke_ltr.cke_hidpi .cke_button__sourcedialog_icon{background:url(icons_hidpi.png?t=I648) no-repeat 0 -960px!important;background-size:16px!important}.cke_hidpi .cke_button__specialchar_icon{background:url(icons_hidpi.png?t=I648) no-repeat 0 -984px!important;background-size:16px!important}.cke_hidpi .cke_button__table_icon{background:url(icons_hidpi.png?t=I648) no-repeat 0 -1008px!important;background-size:16px!important}.cke_rtl.cke_hidpi .cke_button__redo_icon,.cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__redo_icon{background:url(icons_hidpi.png?t=I648) no-repeat 0 -1032px!important;background-size:16px!important}.cke_hidpi .cke_ltr .cke_button__redo_icon,.cke_ltr.cke_hidpi .cke_button__redo_icon{background:url(icons_hidpi.png?t=I648) no-repeat 0 -1056px!important;background-size:16px!important}.cke_rtl.cke_hidpi .cke_button__undo_icon,.cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__undo_icon{background:url(icons_hidpi.png?t=I648) no-repeat 0 -1080px!important;background-size:16px!important}.cke_hidpi .cke_ltr .cke_button__undo_icon,.cke_ltr.cke_hidpi .cke_button__undo_icon{background:url(icons_hidpi.png?t=I648) no-repeat 0 -1104px!important;background-size:16px!important}.cke_hidpi .cke_button__simplebox_icon{background:url(icons_hidpi.png?t=I648) no-repeat 0 -2256px!important} \ No newline at end of file +.cke_reset{margin:0;padding:0;border:0;background:transparent;text-decoration:none;width:auto;height:auto;vertical-align:baseline;box-sizing:content-box;position:static;transition:none}.cke_reset_all,.cke_reset_all *,.cke_reset_all a,.cke_reset_all textarea{margin:0;padding:0;border:0;background:transparent;text-decoration:none;width:auto;height:auto;vertical-align:baseline;box-sizing:content-box;position:static;transition:none;border-collapse:collapse;font:normal normal normal 12px Arial,Helvetica,Tahoma,Verdana,Sans-Serif;color:#000;text-align:left;white-space:nowrap;cursor:auto;float:none}.cke_reset_all .cke_rtl *{text-align:right}.cke_reset_all iframe{vertical-align:inherit}.cke_reset_all textarea{white-space:pre-wrap}.cke_reset_all textarea,.cke_reset_all input[type="text"],.cke_reset_all input[type="password"]{cursor:text}.cke_reset_all textarea[disabled],.cke_reset_all input[type="text"][disabled],.cke_reset_all input[type="password"][disabled]{cursor:default}.cke_reset_all fieldset{padding:10px;border:2px groove #e0dfe3}.cke_reset_all select{box-sizing:border-box}.cke_reset_all table{table-layout:auto}.cke_chrome{display:block;border:1px solid #d1d1d1;padding:0}.cke_inner{display:block;background:#fff;padding:0;-webkit-touch-callout:none}.cke_float{border:0}.cke_float .cke_inner{padding-bottom:0}.cke_top,.cke_contents,.cke_bottom{display:block;overflow:hidden}.cke_top{border-bottom:1px solid #d1d1d1;background:#f8f8f8;padding:6px 8px 2px;white-space:normal}.cke_float .cke_top{border:1px solid #d1d1d1}.cke_bottom{padding:6px 8px 2px;position:relative;border-top:1px solid #d1d1d1;background:#f8f8f8}.cke_browser_ios .cke_contents{overflow-y:auto;-webkit-overflow-scrolling:touch}.cke_resizer{width:0;height:0;overflow:hidden;border-width:10px 10px 0 0;border-color:transparent #bcbcbc transparent transparent;border-style:dashed solid dashed dashed;font-size:0;vertical-align:bottom;margin-top:6px;margin-bottom:2px}.cke_hc .cke_resizer{font-size:15px;width:auto;height:auto;border-width:0}.cke_resizer_ltr{cursor:se-resize;float:right;margin-right:-4px}.cke_resizer_rtl{border-width:10px 0 0 10px;border-color:transparent transparent transparent #bcbcbc;border-style:dashed dashed dashed solid;cursor:sw-resize;float:left;margin-left:-4px;right:auto}.cke_wysiwyg_div{display:block;height:100%;overflow:auto;padding:0 8px;outline-style:none;box-sizing:border-box}.cke_panel{visibility:visible;width:120px;height:100px;overflow:hidden;background-color:#fff;border:1px solid #d1d1d1}.cke_menu_panel{padding:0;margin:0}.cke_combopanel{width:150px;height:170px}.cke_panel_frame{width:100%;height:100%;font-size:12px;overflow:auto;overflow-x:hidden}.cke_panel_container{overflow-y:auto;overflow-x:hidden}.cke_panel_block:focus{outline:0}.cke_panel_list{margin:0;padding:0;list-style-type:none;white-space:nowrap}.cke_panel_listItem{margin:0;padding:0}.cke_panel_listItem a{padding:6px 7px;display:block;color:inherit!important;text-decoration:none;overflow:hidden;text-overflow:ellipsis}.cke_hc .cke_panel_listItem a{border-style:none}.cke_panel_listItem.cke_selected a,.cke_panel_listItem a:hover,.cke_panel_listItem a:focus,.cke_panel_listItem a:active{background-color:#e9e9e9}.cke_panel_listItem a:focus{outline:1px dotted #000}.cke_hc .cke_panel_listItem a:hover,.cke_hc .cke_panel_listItem a:focus,.cke_hc .cke_panel_listItem a:active{border:2px solid;padding:4px 5px}.cke_panel_listItem p,.cke_panel_listItem h1,.cke_panel_listItem h2,.cke_panel_listItem h3,.cke_panel_listItem h4,.cke_panel_listItem h5,.cke_panel_listItem h6,.cke_panel_listItem pre{margin-top:0;margin-bottom:0}.cke_panel_grouptitle{cursor:default;font-size:11px;font-weight:bold;white-space:nowrap;margin:0;padding:6px 6px 7px 6px;color:#484848;border-bottom:1px solid #d1d1d1;background:#f8f8f8}.cke_colorblock{padding:10px;font-size:11px;font-family:'Microsoft Sans Serif',Tahoma,Arial,Verdana,Sans-Serif}.cke_colorblock,.cke_colorblock a{text-decoration:none;color:#000}a.cke_colorbox{padding:2px;float:left;width:20px;height:20px}.cke_rtl a.cke_colorbox{float:right}a:hover.cke_colorbox,a:focus.cke_colorbox,a:active.cke_colorbox{outline:0;padding:0;border:2px solid #139ff7}a:hover.cke_colorbox{border-color:#bcbcbc}span.cke_colorbox{width:20px;height:20px;float:left}.cke_rtl span.cke_colorbox{float:right}a.cke_colorauto,a.cke_colormore{border:#fff 1px solid;padding:3px;display:block;cursor:pointer}a.cke_colorauto{padding:0;border:1px solid transparent;margin-bottom:6px;height:26px;line-height:26px}a.cke_colormore{margin-top:10px;height:20px;line-height:19px}a:hover.cke_colorauto,a:hover.cke_colormore,a:focus.cke_colorauto,a:focus.cke_colormore,a:active.cke_colorauto,a:active.cke_colormore{outline:0;border:#139ff7 1px solid;background-color:#f8f8f8}a:hover.cke_colorauto,a:hover.cke_colormore{border-color:#bcbcbc}.cke_colorauto span.cke_colorbox{width:18px;height:18px;border:1px solid #808080;margin-left:1px;margin-top:3px}.cke_rtl .cke_colorauto span.cke_colorbox{margin-left:0;margin-right:1px}span.cke_colorbox[style*="#ffffff"],span.cke_colorbox[style*="#FFFFFF"],span.cke_colorbox[style="background-color:#fff"],span.cke_colorbox[style="background-color:#FFF"],span.cke_colorbox[style*="rgb(255,255,255)"],span.cke_colorbox[style*="rgb(255, 255, 255)"]{border:1px solid #808080;width:18px;height:18px}.cke_toolbar{float:left}.cke_rtl .cke_toolbar{float:right}.cke_toolgroup{border:0;float:left;margin:1px 2px 6px 0;padding-right:3px}.cke_rtl .cke_toolgroup{float:right;margin:1px 0 6px 2px;padding-left:3px;padding-right:0}.cke_hc .cke_toolgroup{margin-right:5px;margin-bottom:5px}.cke_hc.cke_rtl .cke_toolgroup{margin-right:0;margin-left:5px}a.cke_button{display:inline-block;height:18px;padding:4px 6px;outline:0;cursor:default;float:left;border:0;position:relative}.cke_rtl a.cke_button{float:right}.cke_hc a.cke_button{border:1px solid black;padding:3px 5px;margin:0 3px 5px 0}.cke_hc.cke_rtl a.cke_button{margin:0 0 5px 3px}a.cke_button_on{background:#fff;border:1px #bcbcbc solid;padding:3px 5px}a.cke_button_off:hover,a.cke_button_off:focus,a.cke_button_off:active{background:#e5e5e5;border:1px #bcbcbc solid;padding:3px 5px}.cke_hc a.cke_button_on,.cke_hc a.cke_button_off:hover,.cke_hc a.cke_button_off:focus,.cke_hc a.cke_button_off:active{background:#e5e5e5;border:3px solid #000;padding:1px 3px}a.cke_button_disabled:hover,a.cke_button_disabled:focus,a.cke_button_disabled:active{border:0;padding:4px 6px;background-color:transparent}a.cke_button_disabled:focus{border:1px #bcbcbc solid;padding:3px 5px}.cke_hc a.cke_button_disabled:hover,.cke_hc a.cke_button_disabled:focus,.cke_hc a.cke_button_disabled:active{border:1px solid #acacac;padding:3px 5px;margin:0 3px 5px 0}.cke_hc a.cke_button_disabled:focus{border:3px solid #000;padding:1px 3px}.cke_hc.cke_rtl a.cke_button_disabled:hover,.cke_hc.cke_rtl a.cke_button_disabled:focus,.cke_hc.cke_rtl a.cke_button_disabled:active{margin:0 0 5px 3px}a.cke_button_disabled .cke_button_icon,a.cke_button_disabled .cke_button_arrow{opacity:.3}.cke_hc a.cke_button_disabled{border-color:#acacac}.cke_hc a.cke_button_disabled .cke_button_icon,.cke_hc a.cke_button_disabled .cke_button_label{opacity:.5}.cke_toolgroup a.cke_button:last-child:after,.cke_toolgroup a.cke_button.cke_button_disabled:hover:last-child:after{content:"";position:absolute;height:18px;width:0;border-right:1px solid #bcbcbc;margin-top:4px;top:0;right:-3px}.cke_rtl .cke_toolgroup a.cke_button:last-child:after,.cke_rtl .cke_toolgroup a.cke_button.cke_button_disabled:hover:last-child:after{border-right:0;right:auto;border-left:1px solid #bcbcbc;top:0;left:-3px}.cke_hc .cke_toolgroup a.cke_button:last-child:after,.cke_hc .cke_toolgroup a.cke_button.cke_button_disabled:last-child:after,.cke_hc .cke_toolgroup a.cke_button.cke_button_disabled:hover:last-child:after{border-color:#000;top:0;right:-7px}.cke_hc.cke_rtl .cke_toolgroup a.cke_button:last-child:after,.cke_hc.cke_rtl .cke_toolgroup a.cke_button.cke_button_disabled:last-child:after,.cke_hc.cke_rtl .cke_toolgroup a.cke_button.cke_button_disabled:hover:last-child:after{top:0;right:auto;left:-7px}.cke_toolgroup a.cke_button:hover:last-child:after,.cke_toolgroup a.cke_button.cke_button_on:last-child:after{top:-1px;right:-4px}.cke_rtl .cke_toolgroup a.cke_button:hover:last-child:after,.cke_rtl .cke_toolgroup a.cke_button.cke_button_on:last-child:after{top:-1px;right:auto;left:-4px}.cke_hc .cke_toolgroup a.cke_button:hover:last-child:after,.cke_hc .cke_toolgroup a.cke_button.cke_button_on:last-child:after{top:-2px;right:-9px}.cke_hc.cke_rtl .cke_toolgroup a.cke_button:hover:last-child:after,.cke_hc.cke_rtl .cke_toolgroup a.cke_button.cke_button_on:last-child:after{top:-2px;right:auto;left:-9px}.cke_toolbar.cke_toolbar_last .cke_toolgroup a.cke_button:last-child:after{content:none;border:0;width:0;height:0}.cke_button_icon{cursor:inherit;background-repeat:no-repeat;margin-top:1px;width:16px;height:16px;float:left;display:inline-block}.cke_rtl .cke_button_icon{float:right}.cke_hc .cke_button_icon{display:none}.cke_button_label{display:none;padding-left:3px;margin-top:1px;line-height:17px;vertical-align:middle;float:left;cursor:default;color:#484848}.cke_rtl .cke_button_label{padding-right:3px;padding-left:0;float:right}.cke_hc .cke_button_label{padding:0;display:inline-block;font-size:12px}.cke_button_arrow{display:inline-block;margin:8px 0 0 1px;width:0;height:0;cursor:default;vertical-align:top;border-left:3px solid transparent;border-right:3px solid transparent;border-top:3px solid #484848}.cke_rtl .cke_button_arrow{margin-right:5px;margin-left:0}.cke_hc .cke_button_arrow{font-size:10px;margin:3px 0 0 3px;width:auto;border:0}.cke_toolbar_separator{float:left;background-color:#bcbcbc;margin:4px 2px 0 2px;height:18px;width:1px}.cke_rtl .cke_toolbar_separator{float:right}.cke_hc .cke_toolbar_separator{background-color:#000;margin-left:2px;margin-right:5px;margin-bottom:9px}.cke_hc.cke_rtl .cke_toolbar_separator{margin-left:5px;margin-right:2px}.cke_toolbar_break{display:block;clear:left}.cke_rtl .cke_toolbar_break{clear:right}a.cke_toolbox_collapser{width:12px;height:11px;float:right;margin:11px 0 0;font-size:0;cursor:default;text-align:center;border:1px solid #bcbcbc}.cke_rtl .cke_toolbox_collapser{float:left}.cke_toolbox_collapser:hover{background:#e5e5e5}.cke_toolbox_collapser.cke_toolbox_collapser_min{margin:0 2px 4px}.cke_toolbox_collapser .cke_arrow{display:inline-block;height:0;width:0;font-size:0;margin-top:1px;border:3px solid transparent;border-bottom-color:#484848}.cke_toolbox_collapser.cke_toolbox_collapser_min .cke_arrow{margin-top:4px;border-bottom-color:transparent;border-top-color:#484848}.cke_hc .cke_toolbox_collapser .cke_arrow{font-size:8px;width:auto;border:0;margin-top:0}.cke_menuitem span{cursor:default}.cke_menubutton{display:block}.cke_hc .cke_menubutton{padding:2px}.cke_menubutton:hover,.cke_menubutton:focus,.cke_menubutton:active{background-color:#e9e9e9;display:block;outline:1px dotted}.cke_menubutton:hover{outline:0}.cke_hc .cke_menubutton:hover,.cke_hc .cke_menubutton:focus,.cke_hc .cke_menubutton:active{border:2px solid;padding:0}.cke_menubutton_disabled:hover,.cke_menubutton_disabled:focus,.cke_menubutton_disabled:active{background-color:transparent;outline:0}.cke_menubutton_inner{display:table-row}.cke_menubutton_icon,.cke_menubutton_label,.cke_menuarrow{display:table-cell}.cke_menubutton_icon{background-color:#f8f8f8;padding:6px 4px}.cke_hc .cke_menubutton_icon{height:16px;width:0;padding:4px 0}.cke_menubutton:hover .cke_menubutton_icon,.cke_menubutton:focus .cke_menubutton_icon,.cke_menubutton:active .cke_menubutton_icon{background-color:#e9e9e9}.cke_menubutton_disabled:hover .cke_menubutton_icon,.cke_menubutton_disabled:focus .cke_menubutton_icon,.cke_menubutton_disabled:active .cke_menubutton_icon{background-color:#f8f8f8;outline:0}.cke_menuitem .cke_menubutton_on{background-color:#e9e9e9;border:1px solid #dedede;outline:0}.cke_menubutton_on .cke_menubutton_icon{padding-right:3px;background-color:#e9e9e9}.cke_menubutton_label{padding:0 5px;background-color:transparent;width:100%;vertical-align:middle}.cke_menubutton_shortcut{color:#979797}.cke_menubutton_disabled .cke_menubutton_label{opacity:.3;filter:alpha(opacity=30)}.cke_panel_frame .cke_menubutton_label{display:none}.cke_menuseparator{background-color:#d1d1d1;height:1px}.cke_menuarrow{background:transparent url(images/arrow.png) no-repeat 0 10px;padding:0 5px}.cke_rtl .cke_menuarrow{background-position:5px -13px;background-repeat:no-repeat}.cke_hc .cke_menuarrow{background-image:none}.cke_menuarrow span{display:none}.cke_hc .cke_menuarrow span{vertical-align:middle;display:inline}.cke_combo{display:inline-block;float:left;position:relative;margin-bottom:5px}.cke_rtl .cke_combo{float:right}.cke_hc .cke_combo{margin-top:1px;margin-bottom:10px}.cke_combo:after{content:"";position:absolute;height:18px;width:0;border-right:1px solid #bcbcbc;margin-top:5px;top:0;right:0}.cke_rtl .cke_combo:after{border-right:0;border-left:1px solid #bcbcbc;right:auto;left:0}.cke_hc .cke_combo:after{border-color:#000}a.cke_combo_button{cursor:default;display:inline-block;float:left;margin:0;padding:1px}.cke_rtl a.cke_combo_button{float:right}.cke_hc a.cke_combo_button{padding:4px}.cke_combo_on a.cke_combo_button,.cke_combo_off a.cke_combo_button:hover,.cke_combo_off a.cke_combo_button:focus,.cke_combo_off a.cke_combo_button:active{background:#e5e5e5;border:1px solid #bcbcbc;padding:0 0 0 1px;margin-left:-1px}.cke_combo_off a.cke_combo_button:focus{outline:0}.cke_combo_on a.cke_combo_button,.cke_combo_off a.cke_combo_button:active{background:#fff}.cke_rtl .cke_combo_on a.cke_combo_button,.cke_rtl .cke_combo_off a.cke_combo_button:hover,.cke_rtl .cke_combo_off a.cke_combo_button:focus,.cke_rtl .cke_combo_off a.cke_combo_button:active{padding:0 1px 0 0;margin-left:0;margin-right:-1px}.cke_hc .cke_combo_on a.cke_combo_button,.cke_hc .cke_combo_off a.cke_combo_button:hover,.cke_hc .cke_combo_off a.cke_combo_button:focus,.cke_hc .cke_combo_off a.cke_combo_button:active{border:3px solid #000;padding:1px 1px 1px 2px}.cke_hc.cke_rtl .cke_combo_on a.cke_combo_button,.cke_hc.cke_rtl .cke_combo_off a.cke_combo_button:hover,.cke_hc.cke_rtl .cke_combo_off a.cke_combo_button:focus,.cke_hc.cke_rtl .cke_combo_off a.cke_combo_button:active{padding:1px 2px 1px 1px}.cke_toolbar_start+.cke_combo_on a.cke_combo_button,.cke_toolbar_start+.cke_combo_off a.cke_combo_button:hover,.cke_toolbar_start+.cke_combo_off a.cke_combo_button:focus,.cke_toolbar_start+.cke_combo_off a.cke_combo_button:active{padding:0 0 0 3px;margin-left:-3px}.cke_rtl .cke_toolbar_start+.cke_combo_on a.cke_combo_button,.cke_rtl .cke_toolbar_start+.cke_combo_off a.cke_combo_button:hover,.cke_rtl .cke_toolbar_start+.cke_combo_off a.cke_combo_button:focus,.cke_rtl .cke_toolbar_start+.cke_combo_off a.cke_combo_button:active{padding:0 3px 0 0;margin-left:0;margin-right:-3px}.cke_hc .cke_toolbar>.cke_toolbar_start+.cke_combo_on a.cke_combo_button,.cke_hc .cke_toolbar>.cke_toolbar_start+.cke_combo_off a.cke_combo_button:hover,.cke_hc .cke_toolbar>.cke_toolbar_start+.cke_combo_off a.cke_combo_button:focus,.cke_hc .cke_toolbar>.cke_toolbar_start+.cke_combo_off a.cke_combo_button:active{padding:1px 1px 1px 7px;margin-left:-6px}.cke_hc.cke_rtl .cke_toolbar>.cke_toolbar_start+.cke_combo_on a.cke_combo_button,.cke_hc.cke_rtl .cke_toolbar>.cke_toolbar_start+.cke_combo_off a.cke_combo_button:hover,.cke_hc.cke_rtl .cke_toolbar>.cke_toolbar_start+.cke_combo_off a.cke_combo_button:focus,.cke_hc.cke_rtl .cke_toolbar>.cke_toolbar_start+.cke_combo_off a.cke_combo_button:active{padding:1px 7px 1px 1px;margin-left:0;margin-right:-6px}.cke_toolbox .cke_toolbar:first-child>.cke_toolbar_start+.cke_combo_on a.cke_combo_button,.cke_toolbox .cke_toolbar:first-child>.cke_toolbar_start+.cke_combo_off a.cke_combo_button:hover,.cke_toolbox .cke_toolbar:first-child>.cke_toolbar_start+.cke_combo_off a.cke_combo_button:focus,.cke_toolbox .cke_toolbar:first-child>.cke_toolbar_start+.cke_combo_off a.cke_combo_button:active,.cke_toolbar_break+.cke_toolbar>.cke_toolbar_start+.cke_combo_on a.cke_combo_button,.cke_toolbar_break+.cke_toolbar>.cke_toolbar_start+.cke_combo_off a.cke_combo_button:hover,.cke_toolbar_break+.cke_toolbar>.cke_toolbar_start+.cke_combo_off a.cke_combo_button:focus,.cke_toolbar_break+.cke_toolbar>.cke_toolbar_start+.cke_combo_off a.cke_combo_button:active{padding:0;margin:0}.cke_hc .cke_toolbox .cke_toolbar:first-child>.cke_toolbar_start+.cke_combo_on a.cke_combo_button,.cke_hc .cke_toolbox .cke_toolbar:first-child>.cke_toolbar_start+.cke_combo_off a.cke_combo_button:hover,.cke_hc .cke_toolbox .cke_toolbar:first-child>.cke_toolbar_start+.cke_combo_off a.cke_combo_button:focus,.cke_hc .cke_toolbox .cke_toolbar:first-child>.cke_toolbar_start+.cke_combo_off a.cke_combo_button:active,.cke_hc .cke_toolbar_break+.cke_toolbar>.cke_toolbar_start+.cke_combo_on a.cke_combo_button,.cke_hc .cke_toolbar_break+.cke_toolbar>.cke_toolbar_start+.cke_combo_off a.cke_combo_button:hover,.cke_hc .cke_toolbar_break+.cke_toolbar>.cke_toolbar_start+.cke_combo_off a.cke_combo_button:focus,.cke_hc .cke_toolbar_break+.cke_toolbar>.cke_toolbar_start+.cke_combo_off a.cke_combo_button:active{padding:1px;margin:0}.cke_toolbar .cke_combo+.cke_toolbar_end,.cke_toolbar .cke_combo+.cke_toolgroup{margin-right:0;margin-left:2px}.cke_rtl .cke_toolbar .cke_combo+.cke_toolbar_end,.cke_rtl .cke_toolbar .cke_combo+.cke_toolgroup{margin-left:0;margin-right:2px}.cke_hc .cke_toolbar .cke_combo+.cke_toolbar_end,.cke_hc .cke_toolbar .cke_combo+.cke_toolgroup{margin-left:5px}.cke_hc.cke_rtl .cke_toolbar .cke_combo+.cke_toolbar_end,.cke_hc.cke_rtl .cke_toolbar .cke_combo+.cke_toolgroup{margin-left:0;margin-right:5px}.cke_toolbar.cke_toolbar_last .cke_combo:nth-last-child(-n+2):after{content:none;border:0;width:0;height:0}.cke_combo_text{line-height:26px;padding-left:10px;text-overflow:ellipsis;overflow:hidden;float:left;cursor:default;color:#484848;width:60px}.cke_rtl .cke_combo_text{float:right;text-align:right;padding-left:0;padding-right:10px}.cke_hc .cke_combo_text{line-height:18px;font-size:12px}.cke_combo_open{cursor:default;display:inline-block;font-size:0;height:19px;line-height:17px;margin:1px 10px 1px;width:5px}.cke_hc .cke_combo_open{height:12px}.cke_combo_arrow{cursor:default;margin:11px 0 0;float:left;height:0;width:0;font-size:0;border-left:3px solid transparent;border-right:3px solid transparent;border-top:3px solid #484848}.cke_hc .cke_combo_arrow{font-size:10px;width:auto;border:0;margin-top:3px}.cke_combo_label{display:none;float:left;line-height:26px;vertical-align:top;margin-right:5px}.cke_rtl .cke_combo_label{float:right;margin-left:5px;margin-right:0}.cke_combo_disabled .cke_combo_inlinelabel,.cke_combo_disabled .cke_combo_open{opacity:.3}.cke_path{float:left;margin:-2px 0 2px}a.cke_path_item,span.cke_path_empty{display:inline-block;float:left;padding:3px 4px;margin-right:2px;cursor:default;text-decoration:none;outline:0;border:0;color:#484848;font-weight:bold;font-size:11px}.cke_rtl .cke_path,.cke_rtl .cke_path_item,.cke_rtl .cke_path_empty{float:right}a.cke_path_item:hover,a.cke_path_item:focus,a.cke_path_item:active{background-color:#e5e5e5}.cke_hc a.cke_path_item:hover,.cke_hc a.cke_path_item:focus,.cke_hc a.cke_path_item:active{border:2px solid;padding:1px 2px}.cke_button__source_label,.cke_button__sourcedialog_label{display:inline}.cke_combopanel__fontsize{width:135px}textarea.cke_source{font-family:'Courier New',Monospace;font-size:small;background-color:#fff;white-space:pre-wrap;border:0;padding:0;margin:0;display:block}.cke_wysiwyg_frame,.cke_wysiwyg_div{background-color:#fff}.cke_notifications_area{pointer-events:none}.cke_notification{pointer-events:auto;position:relative;margin:10px;width:300px;color:white;text-align:center;opacity:.95;filter:alpha(opacity = 95);-webkit-animation:fadeIn .7s;animation:fadeIn .7s}.cke_notification_message a{color:#12306f}@-webkit-keyframes fadeIn{from{opacity:.4}to{opacity:.95}}@keyframes fadeIn{from{opacity:.4}to{opacity:.95}}.cke_notification_success{background:#72b572;border:1px solid #63a563}.cke_notification_warning{background:#c83939;border:1px solid #902b2b}.cke_notification_info{background:#2e9ad0;border:1px solid #0f74a8}.cke_notification_info span.cke_notification_progress{background-color:#0f74a8;display:block;padding:0;margin:0;height:100%;overflow:hidden;position:absolute;z-index:1}.cke_notification_message{position:relative;margin:4px 23px 3px;font-family:Arial,Helvetica,sans-serif;font-size:12px;line-height:18px;z-index:4;text-overflow:ellipsis;overflow:hidden}.cke_notification_close{background-image:url(images/close.png);background-repeat:no-repeat;background-position:50%;position:absolute;cursor:pointer;text-align:center;height:20px;width:20px;top:1px;right:1px;padding:0;margin:0;z-index:5;opacity:.6;filter:alpha(opacity = 60)}.cke_notification_close:hover{opacity:1;filter:alpha(opacity = 100)}.cke_notification_close span{display:none}.cke_notification_warning a.cke_notification_close{opacity:.8;filter:alpha(opacity = 80)}.cke_notification_warning a.cke_notification_close:hover{opacity:1;filter:alpha(opacity = 100)}.cke_chrome{visibility:inherit}.cke_voice_label{display:none}legend.cke_voice_label{display:none}.cke_button__about_icon{background:url(icons.png?t=I8E8) no-repeat 0 -0px!important}.cke_button__bold_icon{background:url(icons.png?t=I8E8) no-repeat 0 -24px!important}.cke_button__italic_icon{background:url(icons.png?t=I8E8) no-repeat 0 -48px!important}.cke_button__strike_icon{background:url(icons.png?t=I8E8) no-repeat 0 -72px!important}.cke_button__subscript_icon{background:url(icons.png?t=I8E8) no-repeat 0 -96px!important}.cke_button__superscript_icon{background:url(icons.png?t=I8E8) no-repeat 0 -120px!important}.cke_button__underline_icon{background:url(icons.png?t=I8E8) no-repeat 0 -144px!important}.cke_button__blockquote_icon{background:url(icons.png?t=I8E8) no-repeat 0 -168px!important}.cke_rtl .cke_button__copy_icon,.cke_mixed_dir_content .cke_rtl .cke_button__copy_icon{background:url(icons.png?t=I8E8) no-repeat 0 -192px!important}.cke_ltr .cke_button__copy_icon{background:url(icons.png?t=I8E8) no-repeat 0 -216px!important}.cke_rtl .cke_button__cut_icon,.cke_mixed_dir_content .cke_rtl .cke_button__cut_icon{background:url(icons.png?t=I8E8) no-repeat 0 -240px!important}.cke_ltr .cke_button__cut_icon{background:url(icons.png?t=I8E8) no-repeat 0 -264px!important}.cke_rtl .cke_button__paste_icon,.cke_mixed_dir_content .cke_rtl .cke_button__paste_icon{background:url(icons.png?t=I8E8) no-repeat 0 -288px!important}.cke_ltr .cke_button__paste_icon{background:url(icons.png?t=I8E8) no-repeat 0 -312px!important}.cke_button__horizontalrule_icon{background:url(icons.png?t=I8E8) no-repeat 0 -336px!important}.cke_button__image_icon{background:url(icons.png?t=I8E8) no-repeat 0 -360px!important}.cke_rtl .cke_button__indent_icon,.cke_mixed_dir_content .cke_rtl .cke_button__indent_icon{background:url(icons.png?t=I8E8) no-repeat 0 -384px!important}.cke_ltr .cke_button__indent_icon{background:url(icons.png?t=I8E8) no-repeat 0 -408px!important}.cke_rtl .cke_button__outdent_icon,.cke_mixed_dir_content .cke_rtl .cke_button__outdent_icon{background:url(icons.png?t=I8E8) no-repeat 0 -432px!important}.cke_ltr .cke_button__outdent_icon{background:url(icons.png?t=I8E8) no-repeat 0 -456px!important}.cke_button__justifyblock_icon{background:url(icons.png?t=I8E8) no-repeat 0 -480px!important}.cke_button__justifycenter_icon{background:url(icons.png?t=I8E8) no-repeat 0 -504px!important}.cke_button__justifyleft_icon{background:url(icons.png?t=I8E8) no-repeat 0 -528px!important}.cke_button__justifyright_icon{background:url(icons.png?t=I8E8) no-repeat 0 -552px!important}.cke_button__language_icon{background:url(icons.png?t=I8E8) no-repeat 0 -576px!important}.cke_rtl .cke_button__bulletedlist_icon,.cke_mixed_dir_content .cke_rtl .cke_button__bulletedlist_icon{background:url(icons.png?t=I8E8) no-repeat 0 -600px!important}.cke_ltr .cke_button__bulletedlist_icon{background:url(icons.png?t=I8E8) no-repeat 0 -624px!important}.cke_rtl .cke_button__numberedlist_icon,.cke_mixed_dir_content .cke_rtl .cke_button__numberedlist_icon{background:url(icons.png?t=I8E8) no-repeat 0 -648px!important}.cke_ltr .cke_button__numberedlist_icon{background:url(icons.png?t=I8E8) no-repeat 0 -672px!important}.cke_button__maximize_icon{background:url(icons.png?t=I8E8) no-repeat 0 -696px!important}.cke_rtl .cke_button__pastefromword_icon,.cke_mixed_dir_content .cke_rtl .cke_button__pastefromword_icon{background:url(icons.png?t=I8E8) no-repeat 0 -720px!important}.cke_ltr .cke_button__pastefromword_icon{background:url(icons.png?t=I8E8) no-repeat 0 -744px!important}.cke_rtl .cke_button__pastetext_icon,.cke_mixed_dir_content .cke_rtl .cke_button__pastetext_icon{background:url(icons.png?t=I8E8) no-repeat 0 -768px!important}.cke_ltr .cke_button__pastetext_icon{background:url(icons.png?t=I8E8) no-repeat 0 -792px!important}.cke_button__removeformat_icon{background:url(icons.png?t=I8E8) no-repeat 0 -816px!important}.cke_rtl .cke_button__showblocks_icon,.cke_mixed_dir_content .cke_rtl .cke_button__showblocks_icon{background:url(icons.png?t=I8E8) no-repeat 0 -840px!important}.cke_ltr .cke_button__showblocks_icon{background:url(icons.png?t=I8E8) no-repeat 0 -864px!important}.cke_rtl .cke_button__source_icon,.cke_mixed_dir_content .cke_rtl .cke_button__source_icon{background:url(icons.png?t=I8E8) no-repeat 0 -888px!important}.cke_ltr .cke_button__source_icon{background:url(icons.png?t=I8E8) no-repeat 0 -912px!important}.cke_rtl .cke_button__sourcedialog_icon,.cke_mixed_dir_content .cke_rtl .cke_button__sourcedialog_icon{background:url(icons.png?t=I8E8) no-repeat 0 -936px!important}.cke_ltr .cke_button__sourcedialog_icon{background:url(icons.png?t=I8E8) no-repeat 0 -960px!important}.cke_button__specialchar_icon{background:url(icons.png?t=I8E8) no-repeat 0 -984px!important}.cke_button__table_icon{background:url(icons.png?t=I8E8) no-repeat 0 -1008px!important}.cke_rtl .cke_button__redo_icon,.cke_mixed_dir_content .cke_rtl .cke_button__redo_icon{background:url(icons.png?t=I8E8) no-repeat 0 -1032px!important}.cke_ltr .cke_button__redo_icon{background:url(icons.png?t=I8E8) no-repeat 0 -1056px!important}.cke_rtl .cke_button__undo_icon,.cke_mixed_dir_content .cke_rtl .cke_button__undo_icon{background:url(icons.png?t=I8E8) no-repeat 0 -1080px!important}.cke_ltr .cke_button__undo_icon{background:url(icons.png?t=I8E8) no-repeat 0 -1104px!important}.cke_button__simplebox_icon{background:url(icons.png?t=I8E8) no-repeat 0 -1128px!important}.cke_hidpi .cke_button__about_icon{background:url(icons_hidpi.png?t=I8E8) no-repeat 0 -0px!important;background-size:16px!important}.cke_hidpi .cke_button__bold_icon{background:url(icons_hidpi.png?t=I8E8) no-repeat 0 -24px!important;background-size:16px!important}.cke_hidpi .cke_button__italic_icon{background:url(icons_hidpi.png?t=I8E8) no-repeat 0 -48px!important;background-size:16px!important}.cke_hidpi .cke_button__strike_icon{background:url(icons_hidpi.png?t=I8E8) no-repeat 0 -72px!important;background-size:16px!important}.cke_hidpi .cke_button__subscript_icon{background:url(icons_hidpi.png?t=I8E8) no-repeat 0 -96px!important;background-size:16px!important}.cke_hidpi .cke_button__superscript_icon{background:url(icons_hidpi.png?t=I8E8) no-repeat 0 -120px!important;background-size:16px!important}.cke_hidpi .cke_button__underline_icon{background:url(icons_hidpi.png?t=I8E8) no-repeat 0 -144px!important;background-size:16px!important}.cke_hidpi .cke_button__blockquote_icon{background:url(icons_hidpi.png?t=I8E8) no-repeat 0 -168px!important;background-size:16px!important}.cke_rtl.cke_hidpi .cke_button__copy_icon,.cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__copy_icon{background:url(icons_hidpi.png?t=I8E8) no-repeat 0 -192px!important;background-size:16px!important}.cke_hidpi .cke_ltr .cke_button__copy_icon,.cke_ltr.cke_hidpi .cke_button__copy_icon{background:url(icons_hidpi.png?t=I8E8) no-repeat 0 -216px!important;background-size:16px!important}.cke_rtl.cke_hidpi .cke_button__cut_icon,.cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__cut_icon{background:url(icons_hidpi.png?t=I8E8) no-repeat 0 -240px!important;background-size:16px!important}.cke_hidpi .cke_ltr .cke_button__cut_icon,.cke_ltr.cke_hidpi .cke_button__cut_icon{background:url(icons_hidpi.png?t=I8E8) no-repeat 0 -264px!important;background-size:16px!important}.cke_rtl.cke_hidpi .cke_button__paste_icon,.cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__paste_icon{background:url(icons_hidpi.png?t=I8E8) no-repeat 0 -288px!important;background-size:16px!important}.cke_hidpi .cke_ltr .cke_button__paste_icon,.cke_ltr.cke_hidpi .cke_button__paste_icon{background:url(icons_hidpi.png?t=I8E8) no-repeat 0 -312px!important;background-size:16px!important}.cke_hidpi .cke_button__horizontalrule_icon{background:url(icons_hidpi.png?t=I8E8) no-repeat 0 -336px!important;background-size:16px!important}.cke_hidpi .cke_button__image_icon{background:url(icons_hidpi.png?t=I8E8) no-repeat 0 -360px!important;background-size:16px!important}.cke_rtl.cke_hidpi .cke_button__indent_icon,.cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__indent_icon{background:url(icons_hidpi.png?t=I8E8) no-repeat 0 -384px!important;background-size:16px!important}.cke_hidpi .cke_ltr .cke_button__indent_icon,.cke_ltr.cke_hidpi .cke_button__indent_icon{background:url(icons_hidpi.png?t=I8E8) no-repeat 0 -408px!important;background-size:16px!important}.cke_rtl.cke_hidpi .cke_button__outdent_icon,.cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__outdent_icon{background:url(icons_hidpi.png?t=I8E8) no-repeat 0 -432px!important;background-size:16px!important}.cke_hidpi .cke_ltr .cke_button__outdent_icon,.cke_ltr.cke_hidpi .cke_button__outdent_icon{background:url(icons_hidpi.png?t=I8E8) no-repeat 0 -456px!important;background-size:16px!important}.cke_hidpi .cke_button__justifyblock_icon{background:url(icons_hidpi.png?t=I8E8) no-repeat 0 -480px!important;background-size:16px!important}.cke_hidpi .cke_button__justifycenter_icon{background:url(icons_hidpi.png?t=I8E8) no-repeat 0 -504px!important;background-size:16px!important}.cke_hidpi .cke_button__justifyleft_icon{background:url(icons_hidpi.png?t=I8E8) no-repeat 0 -528px!important;background-size:16px!important}.cke_hidpi .cke_button__justifyright_icon{background:url(icons_hidpi.png?t=I8E8) no-repeat 0 -552px!important;background-size:16px!important}.cke_hidpi .cke_button__language_icon{background:url(icons_hidpi.png?t=I8E8) no-repeat 0 -576px!important;background-size:16px!important}.cke_rtl.cke_hidpi .cke_button__bulletedlist_icon,.cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__bulletedlist_icon{background:url(icons_hidpi.png?t=I8E8) no-repeat 0 -600px!important;background-size:16px!important}.cke_hidpi .cke_ltr .cke_button__bulletedlist_icon,.cke_ltr.cke_hidpi .cke_button__bulletedlist_icon{background:url(icons_hidpi.png?t=I8E8) no-repeat 0 -624px!important;background-size:16px!important}.cke_rtl.cke_hidpi .cke_button__numberedlist_icon,.cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__numberedlist_icon{background:url(icons_hidpi.png?t=I8E8) no-repeat 0 -648px!important;background-size:16px!important}.cke_hidpi .cke_ltr .cke_button__numberedlist_icon,.cke_ltr.cke_hidpi .cke_button__numberedlist_icon{background:url(icons_hidpi.png?t=I8E8) no-repeat 0 -672px!important;background-size:16px!important}.cke_hidpi .cke_button__maximize_icon{background:url(icons_hidpi.png?t=I8E8) no-repeat 0 -696px!important;background-size:16px!important}.cke_rtl.cke_hidpi .cke_button__pastefromword_icon,.cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__pastefromword_icon{background:url(icons_hidpi.png?t=I8E8) no-repeat 0 -720px!important;background-size:16px!important}.cke_hidpi .cke_ltr .cke_button__pastefromword_icon,.cke_ltr.cke_hidpi .cke_button__pastefromword_icon{background:url(icons_hidpi.png?t=I8E8) no-repeat 0 -744px!important;background-size:16px!important}.cke_rtl.cke_hidpi .cke_button__pastetext_icon,.cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__pastetext_icon{background:url(icons_hidpi.png?t=I8E8) no-repeat 0 -768px!important;background-size:16px!important}.cke_hidpi .cke_ltr .cke_button__pastetext_icon,.cke_ltr.cke_hidpi .cke_button__pastetext_icon{background:url(icons_hidpi.png?t=I8E8) no-repeat 0 -792px!important;background-size:16px!important}.cke_hidpi .cke_button__removeformat_icon{background:url(icons_hidpi.png?t=I8E8) no-repeat 0 -816px!important;background-size:16px!important}.cke_rtl.cke_hidpi .cke_button__showblocks_icon,.cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__showblocks_icon{background:url(icons_hidpi.png?t=I8E8) no-repeat 0 -840px!important;background-size:16px!important}.cke_hidpi .cke_ltr .cke_button__showblocks_icon,.cke_ltr.cke_hidpi .cke_button__showblocks_icon{background:url(icons_hidpi.png?t=I8E8) no-repeat 0 -864px!important;background-size:16px!important}.cke_rtl.cke_hidpi .cke_button__source_icon,.cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__source_icon{background:url(icons_hidpi.png?t=I8E8) no-repeat 0 -888px!important;background-size:16px!important}.cke_hidpi .cke_ltr .cke_button__source_icon,.cke_ltr.cke_hidpi .cke_button__source_icon{background:url(icons_hidpi.png?t=I8E8) no-repeat 0 -912px!important;background-size:16px!important}.cke_rtl.cke_hidpi .cke_button__sourcedialog_icon,.cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__sourcedialog_icon{background:url(icons_hidpi.png?t=I8E8) no-repeat 0 -936px!important;background-size:16px!important}.cke_hidpi .cke_ltr .cke_button__sourcedialog_icon,.cke_ltr.cke_hidpi .cke_button__sourcedialog_icon{background:url(icons_hidpi.png?t=I8E8) no-repeat 0 -960px!important;background-size:16px!important}.cke_hidpi .cke_button__specialchar_icon{background:url(icons_hidpi.png?t=I8E8) no-repeat 0 -984px!important;background-size:16px!important}.cke_hidpi .cke_button__table_icon{background:url(icons_hidpi.png?t=I8E8) no-repeat 0 -1008px!important;background-size:16px!important}.cke_rtl.cke_hidpi .cke_button__redo_icon,.cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__redo_icon{background:url(icons_hidpi.png?t=I8E8) no-repeat 0 -1032px!important;background-size:16px!important}.cke_hidpi .cke_ltr .cke_button__redo_icon,.cke_ltr.cke_hidpi .cke_button__redo_icon{background:url(icons_hidpi.png?t=I8E8) no-repeat 0 -1056px!important;background-size:16px!important}.cke_rtl.cke_hidpi .cke_button__undo_icon,.cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__undo_icon{background:url(icons_hidpi.png?t=I8E8) no-repeat 0 -1080px!important;background-size:16px!important}.cke_hidpi .cke_ltr .cke_button__undo_icon,.cke_ltr.cke_hidpi .cke_button__undo_icon{background:url(icons_hidpi.png?t=I8E8) no-repeat 0 -1104px!important;background-size:16px!important}.cke_hidpi .cke_button__simplebox_icon{background:url(icons_hidpi.png?t=I8E8) no-repeat 0 -2256px!important} \ No newline at end of file diff --git a/web/core/assets/vendor/ckeditor/skins/moono-lisa/editor_gecko.css b/web/core/assets/vendor/ckeditor/skins/moono-lisa/editor_gecko.css index 587e700ca7993a98335b904a47c71dc523c4696a..90badc081650e0ce78cd4facac7dbafee1c0a7da 100644 --- a/web/core/assets/vendor/ckeditor/skins/moono-lisa/editor_gecko.css +++ b/web/core/assets/vendor/ckeditor/skins/moono-lisa/editor_gecko.css @@ -2,4 +2,4 @@ Copyright (c) 2003-2018, CKSource - Frederico Knabben. All rights reserved. For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license */ -.cke_reset{margin:0;padding:0;border:0;background:transparent;text-decoration:none;width:auto;height:auto;vertical-align:baseline;box-sizing:content-box;position:static;transition:none}.cke_reset_all,.cke_reset_all *,.cke_reset_all a,.cke_reset_all textarea{margin:0;padding:0;border:0;background:transparent;text-decoration:none;width:auto;height:auto;vertical-align:baseline;box-sizing:content-box;position:static;transition:none;border-collapse:collapse;font:normal normal normal 12px Arial,Helvetica,Tahoma,Verdana,Sans-Serif;color:#000;text-align:left;white-space:nowrap;cursor:auto;float:none}.cke_reset_all .cke_rtl *{text-align:right}.cke_reset_all iframe{vertical-align:inherit}.cke_reset_all textarea{white-space:pre-wrap}.cke_reset_all textarea,.cke_reset_all input[type="text"],.cke_reset_all input[type="password"]{cursor:text}.cke_reset_all textarea[disabled],.cke_reset_all input[type="text"][disabled],.cke_reset_all input[type="password"][disabled]{cursor:default}.cke_reset_all fieldset{padding:10px;border:2px groove #e0dfe3}.cke_reset_all select{box-sizing:border-box}.cke_reset_all table{table-layout:auto}.cke_chrome{display:block;border:1px solid #d1d1d1;padding:0}.cke_inner{display:block;background:#fff;padding:0;-webkit-touch-callout:none}.cke_float{border:0}.cke_float .cke_inner{padding-bottom:0}.cke_top,.cke_contents,.cke_bottom{display:block;overflow:hidden}.cke_top{border-bottom:1px solid #d1d1d1;background:#f8f8f8;padding:6px 8px 2px;white-space:normal}.cke_float .cke_top{border:1px solid #d1d1d1}.cke_bottom{padding:6px 8px 2px;position:relative;border-top:1px solid #d1d1d1;background:#f8f8f8}.cke_browser_ios .cke_contents{overflow-y:auto;-webkit-overflow-scrolling:touch}.cke_resizer{width:0;height:0;overflow:hidden;border-width:10px 10px 0 0;border-color:transparent #bcbcbc transparent transparent;border-style:dashed solid dashed dashed;font-size:0;vertical-align:bottom;margin-top:6px;margin-bottom:2px}.cke_hc .cke_resizer{font-size:15px;width:auto;height:auto;border-width:0}.cke_resizer_ltr{cursor:se-resize;float:right;margin-right:-4px}.cke_resizer_rtl{border-width:10px 0 0 10px;border-color:transparent transparent transparent #bcbcbc;border-style:dashed dashed dashed solid;cursor:sw-resize;float:left;margin-left:-4px;right:auto}.cke_wysiwyg_div{display:block;height:100%;overflow:auto;padding:0 8px;outline-style:none;box-sizing:border-box}.cke_panel{visibility:visible;width:120px;height:100px;overflow:hidden;background-color:#fff;border:1px solid #d1d1d1}.cke_menu_panel{padding:0;margin:0}.cke_combopanel{width:150px;height:170px}.cke_panel_frame{width:100%;height:100%;font-size:12px;overflow:auto;overflow-x:hidden}.cke_panel_container{overflow-y:auto;overflow-x:hidden}.cke_panel_block:focus{outline:0}.cke_panel_list{margin:0;padding:0;list-style-type:none;white-space:nowrap}.cke_panel_listItem{margin:0;padding:0}.cke_panel_listItem a{padding:6px 7px;display:block;color:inherit!important;text-decoration:none;overflow:hidden;text-overflow:ellipsis}.cke_hc .cke_panel_listItem a{border-style:none}.cke_panel_listItem.cke_selected a,.cke_panel_listItem a:hover,.cke_panel_listItem a:focus,.cke_panel_listItem a:active{background-color:#e9e9e9}.cke_panel_listItem a:focus{outline:1px dotted #000}.cke_hc .cke_panel_listItem a:hover,.cke_hc .cke_panel_listItem a:focus,.cke_hc .cke_panel_listItem a:active{border:2px solid;padding:4px 5px}.cke_panel_listItem p,.cke_panel_listItem h1,.cke_panel_listItem h2,.cke_panel_listItem h3,.cke_panel_listItem h4,.cke_panel_listItem h5,.cke_panel_listItem h6,.cke_panel_listItem pre{margin-top:0;margin-bottom:0}.cke_panel_grouptitle{cursor:default;font-size:11px;font-weight:bold;white-space:nowrap;margin:0;padding:6px 6px 7px 6px;color:#484848;border-bottom:1px solid #d1d1d1;background:#f8f8f8}.cke_colorblock{padding:10px;font-size:11px;font-family:'Microsoft Sans Serif',Tahoma,Arial,Verdana,Sans-Serif}.cke_colorblock,.cke_colorblock a{text-decoration:none;color:#000}a.cke_colorbox{padding:2px;float:left;width:20px;height:20px}.cke_rtl a.cke_colorbox{float:right}a:hover.cke_colorbox,a:focus.cke_colorbox,a:active.cke_colorbox{outline:0;padding:0;border:2px solid #139ff7}a:hover.cke_colorbox{border-color:#bcbcbc}span.cke_colorbox{width:20px;height:20px;float:left}.cke_rtl span.cke_colorbox{float:right}a.cke_colorauto,a.cke_colormore{border:#fff 1px solid;padding:3px;display:block;cursor:pointer}a.cke_colorauto{padding:0;border:1px solid transparent;margin-bottom:6px;height:26px;line-height:26px}a.cke_colormore{margin-top:10px;height:20px;line-height:19px}a:hover.cke_colorauto,a:hover.cke_colormore,a:focus.cke_colorauto,a:focus.cke_colormore,a:active.cke_colorauto,a:active.cke_colormore{outline:0;border:#139ff7 1px solid;background-color:#f8f8f8}a:hover.cke_colorauto,a:hover.cke_colormore{border-color:#bcbcbc}.cke_colorauto span.cke_colorbox{width:18px;height:18px;border:1px solid #808080;margin-left:1px;margin-top:3px}.cke_rtl .cke_colorauto span.cke_colorbox{margin-left:0;margin-right:1px}span.cke_colorbox[style*="#ffffff"],span.cke_colorbox[style*="#FFFFFF"],span.cke_colorbox[style="background-color:#fff"],span.cke_colorbox[style="background-color:#FFF"],span.cke_colorbox[style*="rgb(255,255,255)"],span.cke_colorbox[style*="rgb(255, 255, 255)"]{border:1px solid #808080;width:18px;height:18px}.cke_toolbar{float:left}.cke_rtl .cke_toolbar{float:right}.cke_toolgroup{border:0;float:left;margin:1px 2px 6px 0;padding-right:3px}.cke_rtl .cke_toolgroup{float:right;margin:1px 0 6px 2px;padding-left:3px;padding-right:0}.cke_hc .cke_toolgroup{margin-right:5px;margin-bottom:5px}.cke_hc.cke_rtl .cke_toolgroup{margin-right:0;margin-left:5px}a.cke_button{display:inline-block;height:18px;padding:4px 6px;outline:0;cursor:default;float:left;border:0;position:relative}.cke_rtl a.cke_button{float:right}.cke_hc a.cke_button{border:1px solid black;padding:3px 5px;margin:0 3px 5px 0}.cke_hc.cke_rtl a.cke_button{margin:0 0 5px 3px}a.cke_button_on{background:#fff;border:1px #bcbcbc solid;padding:3px 5px}a.cke_button_off:hover,a.cke_button_off:focus,a.cke_button_off:active{background:#e5e5e5;border:1px #bcbcbc solid;padding:3px 5px}.cke_hc a.cke_button_on,.cke_hc a.cke_button_off:hover,.cke_hc a.cke_button_off:focus,.cke_hc a.cke_button_off:active{background:#e5e5e5;border:3px solid #000;padding:1px 3px}a.cke_button_disabled:hover,a.cke_button_disabled:focus,a.cke_button_disabled:active{border:0;padding:4px 6px;background-color:transparent}a.cke_button_disabled:focus{border:1px #bcbcbc solid;padding:3px 5px}.cke_hc a.cke_button_disabled:hover,.cke_hc a.cke_button_disabled:focus,.cke_hc a.cke_button_disabled:active{border:1px solid #acacac;padding:3px 5px;margin:0 3px 5px 0}.cke_hc a.cke_button_disabled:focus{border:3px solid #000;padding:1px 3px}.cke_hc.cke_rtl a.cke_button_disabled:hover,.cke_hc.cke_rtl a.cke_button_disabled:focus,.cke_hc.cke_rtl a.cke_button_disabled:active{margin:0 0 5px 3px}a.cke_button_disabled .cke_button_icon,a.cke_button_disabled .cke_button_arrow{opacity:.3}.cke_hc a.cke_button_disabled{border-color:#acacac}.cke_hc a.cke_button_disabled .cke_button_icon,.cke_hc a.cke_button_disabled .cke_button_label{opacity:.5}.cke_toolgroup a.cke_button:last-child:after,.cke_toolgroup a.cke_button.cke_button_disabled:hover:last-child:after{content:"";position:absolute;height:18px;width:0;border-right:1px solid #bcbcbc;margin-top:4px;top:0;right:-3px}.cke_rtl .cke_toolgroup a.cke_button:last-child:after,.cke_rtl .cke_toolgroup a.cke_button.cke_button_disabled:hover:last-child:after{border-right:0;right:auto;border-left:1px solid #bcbcbc;top:0;left:-3px}.cke_hc .cke_toolgroup a.cke_button:last-child:after,.cke_hc .cke_toolgroup a.cke_button.cke_button_disabled:last-child:after,.cke_hc .cke_toolgroup a.cke_button.cke_button_disabled:hover:last-child:after{border-color:#000;top:0;right:-7px}.cke_hc.cke_rtl .cke_toolgroup a.cke_button:last-child:after,.cke_hc.cke_rtl .cke_toolgroup a.cke_button.cke_button_disabled:last-child:after,.cke_hc.cke_rtl .cke_toolgroup a.cke_button.cke_button_disabled:hover:last-child:after{top:0;right:auto;left:-7px}.cke_toolgroup a.cke_button:hover:last-child:after,.cke_toolgroup a.cke_button.cke_button_on:last-child:after{top:-1px;right:-4px}.cke_rtl .cke_toolgroup a.cke_button:hover:last-child:after,.cke_rtl .cke_toolgroup a.cke_button.cke_button_on:last-child:after{top:-1px;right:auto;left:-4px}.cke_hc .cke_toolgroup a.cke_button:hover:last-child:after,.cke_hc .cke_toolgroup a.cke_button.cke_button_on:last-child:after{top:-2px;right:-9px}.cke_hc.cke_rtl .cke_toolgroup a.cke_button:hover:last-child:after,.cke_hc.cke_rtl .cke_toolgroup a.cke_button.cke_button_on:last-child:after{top:-2px;right:auto;left:-9px}.cke_toolbar.cke_toolbar_last .cke_toolgroup a.cke_button:last-child:after{content:none;border:0;width:0;height:0}.cke_button_icon{cursor:inherit;background-repeat:no-repeat;margin-top:1px;width:16px;height:16px;float:left;display:inline-block}.cke_rtl .cke_button_icon{float:right}.cke_hc .cke_button_icon{display:none}.cke_button_label{display:none;padding-left:3px;margin-top:1px;line-height:17px;vertical-align:middle;float:left;cursor:default;color:#484848}.cke_rtl .cke_button_label{padding-right:3px;padding-left:0;float:right}.cke_hc .cke_button_label{padding:0;display:inline-block;font-size:12px}.cke_button_arrow{display:inline-block;margin:8px 0 0 1px;width:0;height:0;cursor:default;vertical-align:top;border-left:3px solid transparent;border-right:3px solid transparent;border-top:3px solid #484848}.cke_rtl .cke_button_arrow{margin-right:5px;margin-left:0}.cke_hc .cke_button_arrow{font-size:10px;margin:3px 0 0 3px;width:auto;border:0}.cke_toolbar_separator{float:left;background-color:#bcbcbc;margin:4px 2px 0 2px;height:18px;width:1px}.cke_rtl .cke_toolbar_separator{float:right}.cke_hc .cke_toolbar_separator{background-color:#000;margin-left:2px;margin-right:5px;margin-bottom:9px}.cke_hc.cke_rtl .cke_toolbar_separator{margin-left:5px;margin-right:2px}.cke_toolbar_break{display:block;clear:left}.cke_rtl .cke_toolbar_break{clear:right}a.cke_toolbox_collapser{width:12px;height:11px;float:right;margin:11px 0 0;font-size:0;cursor:default;text-align:center;border:1px solid #bcbcbc}.cke_rtl .cke_toolbox_collapser{float:left}.cke_toolbox_collapser:hover{background:#e5e5e5}.cke_toolbox_collapser.cke_toolbox_collapser_min{margin:0 2px 4px}.cke_toolbox_collapser .cke_arrow{display:inline-block;height:0;width:0;font-size:0;margin-top:1px;border:3px solid transparent;border-bottom-color:#484848}.cke_toolbox_collapser.cke_toolbox_collapser_min .cke_arrow{margin-top:4px;border-bottom-color:transparent;border-top-color:#484848}.cke_hc .cke_toolbox_collapser .cke_arrow{font-size:8px;width:auto;border:0;margin-top:0}.cke_menuitem span{cursor:default}.cke_menubutton{display:block}.cke_hc .cke_menubutton{padding:2px}.cke_menubutton:hover,.cke_menubutton:focus,.cke_menubutton:active{background-color:#e9e9e9;display:block;outline:1px dotted}.cke_menubutton:hover{outline:0}.cke_hc .cke_menubutton:hover,.cke_hc .cke_menubutton:focus,.cke_hc .cke_menubutton:active{border:2px solid;padding:0}.cke_menubutton_disabled:hover,.cke_menubutton_disabled:focus,.cke_menubutton_disabled:active{background-color:transparent;outline:0}.cke_menubutton_inner{display:table-row}.cke_menubutton_icon,.cke_menubutton_label,.cke_menuarrow{display:table-cell}.cke_menubutton_icon{background-color:#f8f8f8;padding:6px 4px}.cke_hc .cke_menubutton_icon{height:16px;width:0;padding:4px 0}.cke_menubutton:hover .cke_menubutton_icon,.cke_menubutton:focus .cke_menubutton_icon,.cke_menubutton:active .cke_menubutton_icon{background-color:#e9e9e9}.cke_menubutton_disabled:hover .cke_menubutton_icon,.cke_menubutton_disabled:focus .cke_menubutton_icon,.cke_menubutton_disabled:active .cke_menubutton_icon{background-color:#f8f8f8;outline:0}.cke_menuitem .cke_menubutton_on{background-color:#e9e9e9;border:1px solid #dedede;outline:0}.cke_menubutton_on .cke_menubutton_icon{padding-right:3px;background-color:#e9e9e9}.cke_menubutton_label{padding:0 5px;background-color:transparent;width:100%;vertical-align:middle}.cke_menubutton_shortcut{color:#979797}.cke_menubutton_disabled .cke_menubutton_label{opacity:.3;filter:alpha(opacity=30)}.cke_panel_frame .cke_menubutton_label{display:none}.cke_menuseparator{background-color:#d1d1d1;height:1px}.cke_menuarrow{background:transparent url(images/arrow.png) no-repeat 0 10px;padding:0 5px}.cke_rtl .cke_menuarrow{background-position:5px -13px;background-repeat:no-repeat}.cke_hc .cke_menuarrow{background-image:none}.cke_menuarrow span{display:none}.cke_hc .cke_menuarrow span{vertical-align:middle;display:inline}.cke_combo{display:inline-block;float:left;position:relative;margin-bottom:5px}.cke_rtl .cke_combo{float:right}.cke_hc .cke_combo{margin-top:1px;margin-bottom:10px}.cke_combo:after{content:"";position:absolute;height:18px;width:0;border-right:1px solid #bcbcbc;margin-top:5px;top:0;right:0}.cke_rtl .cke_combo:after{border-right:0;border-left:1px solid #bcbcbc;right:auto;left:0}.cke_hc .cke_combo:after{border-color:#000}a.cke_combo_button{cursor:default;display:inline-block;float:left;margin:0;padding:1px}.cke_rtl a.cke_combo_button{float:right}.cke_hc a.cke_combo_button{padding:4px}.cke_combo_on a.cke_combo_button,.cke_combo_off a.cke_combo_button:hover,.cke_combo_off a.cke_combo_button:focus,.cke_combo_off a.cke_combo_button:active{background:#e5e5e5;border:1px solid #bcbcbc;padding:0 0 0 1px;margin-left:-1px}.cke_combo_off a.cke_combo_button:focus{outline:0}.cke_combo_on a.cke_combo_button,.cke_combo_off a.cke_combo_button:active{background:#fff}.cke_rtl .cke_combo_on a.cke_combo_button,.cke_rtl .cke_combo_off a.cke_combo_button:hover,.cke_rtl .cke_combo_off a.cke_combo_button:focus,.cke_rtl .cke_combo_off a.cke_combo_button:active{padding:0 1px 0 0;margin-left:0;margin-right:-1px}.cke_hc .cke_combo_on a.cke_combo_button,.cke_hc .cke_combo_off a.cke_combo_button:hover,.cke_hc .cke_combo_off a.cke_combo_button:focus,.cke_hc .cke_combo_off a.cke_combo_button:active{border:3px solid #000;padding:1px 1px 1px 2px}.cke_hc.cke_rtl .cke_combo_on a.cke_combo_button,.cke_hc.cke_rtl .cke_combo_off a.cke_combo_button:hover,.cke_hc.cke_rtl .cke_combo_off a.cke_combo_button:focus,.cke_hc.cke_rtl .cke_combo_off a.cke_combo_button:active{padding:1px 2px 1px 1px}.cke_toolbar_start+.cke_combo_on a.cke_combo_button,.cke_toolbar_start+.cke_combo_off a.cke_combo_button:hover,.cke_toolbar_start+.cke_combo_off a.cke_combo_button:focus,.cke_toolbar_start+.cke_combo_off a.cke_combo_button:active{padding:0 0 0 3px;margin-left:-3px}.cke_rtl .cke_toolbar_start+.cke_combo_on a.cke_combo_button,.cke_rtl .cke_toolbar_start+.cke_combo_off a.cke_combo_button:hover,.cke_rtl .cke_toolbar_start+.cke_combo_off a.cke_combo_button:focus,.cke_rtl .cke_toolbar_start+.cke_combo_off a.cke_combo_button:active{padding:0 3px 0 0;margin-left:0;margin-right:-3px}.cke_hc .cke_toolbar>.cke_toolbar_start+.cke_combo_on a.cke_combo_button,.cke_hc .cke_toolbar>.cke_toolbar_start+.cke_combo_off a.cke_combo_button:hover,.cke_hc .cke_toolbar>.cke_toolbar_start+.cke_combo_off a.cke_combo_button:focus,.cke_hc .cke_toolbar>.cke_toolbar_start+.cke_combo_off a.cke_combo_button:active{padding:1px 1px 1px 7px;margin-left:-6px}.cke_hc.cke_rtl .cke_toolbar>.cke_toolbar_start+.cke_combo_on a.cke_combo_button,.cke_hc.cke_rtl .cke_toolbar>.cke_toolbar_start+.cke_combo_off a.cke_combo_button:hover,.cke_hc.cke_rtl .cke_toolbar>.cke_toolbar_start+.cke_combo_off a.cke_combo_button:focus,.cke_hc.cke_rtl .cke_toolbar>.cke_toolbar_start+.cke_combo_off a.cke_combo_button:active{padding:1px 7px 1px 1px;margin-left:0;margin-right:-6px}.cke_toolbox .cke_toolbar:first-child>.cke_toolbar_start+.cke_combo_on a.cke_combo_button,.cke_toolbox .cke_toolbar:first-child>.cke_toolbar_start+.cke_combo_off a.cke_combo_button:hover,.cke_toolbox .cke_toolbar:first-child>.cke_toolbar_start+.cke_combo_off a.cke_combo_button:focus,.cke_toolbox .cke_toolbar:first-child>.cke_toolbar_start+.cke_combo_off a.cke_combo_button:active,.cke_toolbar_break+.cke_toolbar>.cke_toolbar_start+.cke_combo_on a.cke_combo_button,.cke_toolbar_break+.cke_toolbar>.cke_toolbar_start+.cke_combo_off a.cke_combo_button:hover,.cke_toolbar_break+.cke_toolbar>.cke_toolbar_start+.cke_combo_off a.cke_combo_button:focus,.cke_toolbar_break+.cke_toolbar>.cke_toolbar_start+.cke_combo_off a.cke_combo_button:active{padding:0;margin:0}.cke_hc .cke_toolbox .cke_toolbar:first-child>.cke_toolbar_start+.cke_combo_on a.cke_combo_button,.cke_hc .cke_toolbox .cke_toolbar:first-child>.cke_toolbar_start+.cke_combo_off a.cke_combo_button:hover,.cke_hc .cke_toolbox .cke_toolbar:first-child>.cke_toolbar_start+.cke_combo_off a.cke_combo_button:focus,.cke_hc .cke_toolbox .cke_toolbar:first-child>.cke_toolbar_start+.cke_combo_off a.cke_combo_button:active,.cke_hc .cke_toolbar_break+.cke_toolbar>.cke_toolbar_start+.cke_combo_on a.cke_combo_button,.cke_hc .cke_toolbar_break+.cke_toolbar>.cke_toolbar_start+.cke_combo_off a.cke_combo_button:hover,.cke_hc .cke_toolbar_break+.cke_toolbar>.cke_toolbar_start+.cke_combo_off a.cke_combo_button:focus,.cke_hc .cke_toolbar_break+.cke_toolbar>.cke_toolbar_start+.cke_combo_off a.cke_combo_button:active{padding:1px;margin:0}.cke_toolbar .cke_combo+.cke_toolbar_end,.cke_toolbar .cke_combo+.cke_toolgroup{margin-right:0;margin-left:2px}.cke_rtl .cke_toolbar .cke_combo+.cke_toolbar_end,.cke_rtl .cke_toolbar .cke_combo+.cke_toolgroup{margin-left:0;margin-right:2px}.cke_hc .cke_toolbar .cke_combo+.cke_toolbar_end,.cke_hc .cke_toolbar .cke_combo+.cke_toolgroup{margin-left:5px}.cke_hc.cke_rtl .cke_toolbar .cke_combo+.cke_toolbar_end,.cke_hc.cke_rtl .cke_toolbar .cke_combo+.cke_toolgroup{margin-left:0;margin-right:5px}.cke_toolbar.cke_toolbar_last .cke_combo:nth-last-child(-n+2):after{content:none;border:0;width:0;height:0}.cke_combo_text{line-height:26px;padding-left:10px;text-overflow:ellipsis;overflow:hidden;float:left;cursor:default;color:#484848;width:60px}.cke_rtl .cke_combo_text{float:right;text-align:right;padding-left:0;padding-right:10px}.cke_hc .cke_combo_text{line-height:18px;font-size:12px}.cke_combo_open{cursor:default;display:inline-block;font-size:0;height:19px;line-height:17px;margin:1px 10px 1px;width:5px}.cke_hc .cke_combo_open{height:12px}.cke_combo_arrow{cursor:default;margin:11px 0 0;float:left;height:0;width:0;font-size:0;border-left:3px solid transparent;border-right:3px solid transparent;border-top:3px solid #484848}.cke_hc .cke_combo_arrow{font-size:10px;width:auto;border:0;margin-top:3px}.cke_combo_label{display:none;float:left;line-height:26px;vertical-align:top;margin-right:5px}.cke_rtl .cke_combo_label{float:right;margin-left:5px;margin-right:0}.cke_combo_disabled .cke_combo_inlinelabel,.cke_combo_disabled .cke_combo_open{opacity:.3}.cke_path{float:left;margin:-2px 0 2px}a.cke_path_item,span.cke_path_empty{display:inline-block;float:left;padding:3px 4px;margin-right:2px;cursor:default;text-decoration:none;outline:0;border:0;color:#484848;font-weight:bold;font-size:11px}.cke_rtl .cke_path,.cke_rtl .cke_path_item,.cke_rtl .cke_path_empty{float:right}a.cke_path_item:hover,a.cke_path_item:focus,a.cke_path_item:active{background-color:#e5e5e5}.cke_hc a.cke_path_item:hover,.cke_hc a.cke_path_item:focus,.cke_hc a.cke_path_item:active{border:2px solid;padding:1px 2px}.cke_button__source_label,.cke_button__sourcedialog_label{display:inline}.cke_combopanel__fontsize{width:135px}textarea.cke_source{font-family:'Courier New',Monospace;font-size:small;background-color:#fff;white-space:pre-wrap;border:0;padding:0;margin:0;display:block}.cke_wysiwyg_frame,.cke_wysiwyg_div{background-color:#fff}.cke_notifications_area{pointer-events:none}.cke_notification{pointer-events:auto;position:relative;margin:10px;width:300px;color:white;text-align:center;opacity:.95;filter:alpha(opacity = 95);-webkit-animation:fadeIn .7s;animation:fadeIn .7s}.cke_notification_message a{color:#12306f}@-webkit-keyframes fadeIn{from{opacity:.4}to{opacity:.95}}@keyframes fadeIn{from{opacity:.4}to{opacity:.95}}.cke_notification_success{background:#72b572;border:1px solid #63a563}.cke_notification_warning{background:#c83939;border:1px solid #902b2b}.cke_notification_info{background:#2e9ad0;border:1px solid #0f74a8}.cke_notification_info span.cke_notification_progress{background-color:#0f74a8;display:block;padding:0;margin:0;height:100%;overflow:hidden;position:absolute;z-index:1}.cke_notification_message{position:relative;margin:4px 23px 3px;font-family:Arial,Helvetica,sans-serif;font-size:12px;line-height:18px;z-index:4;text-overflow:ellipsis;overflow:hidden}.cke_notification_close{background-image:url(images/close.png);background-repeat:no-repeat;background-position:50%;position:absolute;cursor:pointer;text-align:center;height:20px;width:20px;top:1px;right:1px;padding:0;margin:0;z-index:5;opacity:.6;filter:alpha(opacity = 60)}.cke_notification_close:hover{opacity:1;filter:alpha(opacity = 100)}.cke_notification_close span{display:none}.cke_notification_warning a.cke_notification_close{opacity:.8;filter:alpha(opacity = 80)}.cke_notification_warning a.cke_notification_close:hover{opacity:1;filter:alpha(opacity = 100)}.cke_chrome{visibility:inherit}.cke_voice_label{display:none}legend.cke_voice_label{display:none}.cke_button__about_icon{background:url(icons.png?t=I648) no-repeat 0 -0px!important}.cke_button__bold_icon{background:url(icons.png?t=I648) no-repeat 0 -24px!important}.cke_button__italic_icon{background:url(icons.png?t=I648) no-repeat 0 -48px!important}.cke_button__strike_icon{background:url(icons.png?t=I648) no-repeat 0 -72px!important}.cke_button__subscript_icon{background:url(icons.png?t=I648) no-repeat 0 -96px!important}.cke_button__superscript_icon{background:url(icons.png?t=I648) no-repeat 0 -120px!important}.cke_button__underline_icon{background:url(icons.png?t=I648) no-repeat 0 -144px!important}.cke_button__blockquote_icon{background:url(icons.png?t=I648) no-repeat 0 -168px!important}.cke_rtl .cke_button__copy_icon,.cke_mixed_dir_content .cke_rtl .cke_button__copy_icon{background:url(icons.png?t=I648) no-repeat 0 -192px!important}.cke_ltr .cke_button__copy_icon{background:url(icons.png?t=I648) no-repeat 0 -216px!important}.cke_rtl .cke_button__cut_icon,.cke_mixed_dir_content .cke_rtl .cke_button__cut_icon{background:url(icons.png?t=I648) no-repeat 0 -240px!important}.cke_ltr .cke_button__cut_icon{background:url(icons.png?t=I648) no-repeat 0 -264px!important}.cke_rtl .cke_button__paste_icon,.cke_mixed_dir_content .cke_rtl .cke_button__paste_icon{background:url(icons.png?t=I648) no-repeat 0 -288px!important}.cke_ltr .cke_button__paste_icon{background:url(icons.png?t=I648) no-repeat 0 -312px!important}.cke_button__horizontalrule_icon{background:url(icons.png?t=I648) no-repeat 0 -336px!important}.cke_button__image_icon{background:url(icons.png?t=I648) no-repeat 0 -360px!important}.cke_rtl .cke_button__indent_icon,.cke_mixed_dir_content .cke_rtl .cke_button__indent_icon{background:url(icons.png?t=I648) no-repeat 0 -384px!important}.cke_ltr .cke_button__indent_icon{background:url(icons.png?t=I648) no-repeat 0 -408px!important}.cke_rtl .cke_button__outdent_icon,.cke_mixed_dir_content .cke_rtl .cke_button__outdent_icon{background:url(icons.png?t=I648) no-repeat 0 -432px!important}.cke_ltr .cke_button__outdent_icon{background:url(icons.png?t=I648) no-repeat 0 -456px!important}.cke_button__justifyblock_icon{background:url(icons.png?t=I648) no-repeat 0 -480px!important}.cke_button__justifycenter_icon{background:url(icons.png?t=I648) no-repeat 0 -504px!important}.cke_button__justifyleft_icon{background:url(icons.png?t=I648) no-repeat 0 -528px!important}.cke_button__justifyright_icon{background:url(icons.png?t=I648) no-repeat 0 -552px!important}.cke_button__language_icon{background:url(icons.png?t=I648) no-repeat 0 -576px!important}.cke_rtl .cke_button__bulletedlist_icon,.cke_mixed_dir_content .cke_rtl .cke_button__bulletedlist_icon{background:url(icons.png?t=I648) no-repeat 0 -600px!important}.cke_ltr .cke_button__bulletedlist_icon{background:url(icons.png?t=I648) no-repeat 0 -624px!important}.cke_rtl .cke_button__numberedlist_icon,.cke_mixed_dir_content .cke_rtl .cke_button__numberedlist_icon{background:url(icons.png?t=I648) no-repeat 0 -648px!important}.cke_ltr .cke_button__numberedlist_icon{background:url(icons.png?t=I648) no-repeat 0 -672px!important}.cke_button__maximize_icon{background:url(icons.png?t=I648) no-repeat 0 -696px!important}.cke_rtl .cke_button__pastefromword_icon,.cke_mixed_dir_content .cke_rtl .cke_button__pastefromword_icon{background:url(icons.png?t=I648) no-repeat 0 -720px!important}.cke_ltr .cke_button__pastefromword_icon{background:url(icons.png?t=I648) no-repeat 0 -744px!important}.cke_rtl .cke_button__pastetext_icon,.cke_mixed_dir_content .cke_rtl .cke_button__pastetext_icon{background:url(icons.png?t=I648) no-repeat 0 -768px!important}.cke_ltr .cke_button__pastetext_icon{background:url(icons.png?t=I648) no-repeat 0 -792px!important}.cke_button__removeformat_icon{background:url(icons.png?t=I648) no-repeat 0 -816px!important}.cke_rtl .cke_button__showblocks_icon,.cke_mixed_dir_content .cke_rtl .cke_button__showblocks_icon{background:url(icons.png?t=I648) no-repeat 0 -840px!important}.cke_ltr .cke_button__showblocks_icon{background:url(icons.png?t=I648) no-repeat 0 -864px!important}.cke_rtl .cke_button__source_icon,.cke_mixed_dir_content .cke_rtl .cke_button__source_icon{background:url(icons.png?t=I648) no-repeat 0 -888px!important}.cke_ltr .cke_button__source_icon{background:url(icons.png?t=I648) no-repeat 0 -912px!important}.cke_rtl .cke_button__sourcedialog_icon,.cke_mixed_dir_content .cke_rtl .cke_button__sourcedialog_icon{background:url(icons.png?t=I648) no-repeat 0 -936px!important}.cke_ltr .cke_button__sourcedialog_icon{background:url(icons.png?t=I648) no-repeat 0 -960px!important}.cke_button__specialchar_icon{background:url(icons.png?t=I648) no-repeat 0 -984px!important}.cke_button__table_icon{background:url(icons.png?t=I648) no-repeat 0 -1008px!important}.cke_rtl .cke_button__redo_icon,.cke_mixed_dir_content .cke_rtl .cke_button__redo_icon{background:url(icons.png?t=I648) no-repeat 0 -1032px!important}.cke_ltr .cke_button__redo_icon{background:url(icons.png?t=I648) no-repeat 0 -1056px!important}.cke_rtl .cke_button__undo_icon,.cke_mixed_dir_content .cke_rtl .cke_button__undo_icon{background:url(icons.png?t=I648) no-repeat 0 -1080px!important}.cke_ltr .cke_button__undo_icon{background:url(icons.png?t=I648) no-repeat 0 -1104px!important}.cke_button__simplebox_icon{background:url(icons.png?t=I648) no-repeat 0 -1128px!important}.cke_hidpi .cke_button__about_icon{background:url(icons_hidpi.png?t=I648) no-repeat 0 -0px!important;background-size:16px!important}.cke_hidpi .cke_button__bold_icon{background:url(icons_hidpi.png?t=I648) no-repeat 0 -24px!important;background-size:16px!important}.cke_hidpi .cke_button__italic_icon{background:url(icons_hidpi.png?t=I648) no-repeat 0 -48px!important;background-size:16px!important}.cke_hidpi .cke_button__strike_icon{background:url(icons_hidpi.png?t=I648) no-repeat 0 -72px!important;background-size:16px!important}.cke_hidpi .cke_button__subscript_icon{background:url(icons_hidpi.png?t=I648) no-repeat 0 -96px!important;background-size:16px!important}.cke_hidpi .cke_button__superscript_icon{background:url(icons_hidpi.png?t=I648) no-repeat 0 -120px!important;background-size:16px!important}.cke_hidpi .cke_button__underline_icon{background:url(icons_hidpi.png?t=I648) no-repeat 0 -144px!important;background-size:16px!important}.cke_hidpi .cke_button__blockquote_icon{background:url(icons_hidpi.png?t=I648) no-repeat 0 -168px!important;background-size:16px!important}.cke_rtl.cke_hidpi .cke_button__copy_icon,.cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__copy_icon{background:url(icons_hidpi.png?t=I648) no-repeat 0 -192px!important;background-size:16px!important}.cke_hidpi .cke_ltr .cke_button__copy_icon,.cke_ltr.cke_hidpi .cke_button__copy_icon{background:url(icons_hidpi.png?t=I648) no-repeat 0 -216px!important;background-size:16px!important}.cke_rtl.cke_hidpi .cke_button__cut_icon,.cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__cut_icon{background:url(icons_hidpi.png?t=I648) no-repeat 0 -240px!important;background-size:16px!important}.cke_hidpi .cke_ltr .cke_button__cut_icon,.cke_ltr.cke_hidpi .cke_button__cut_icon{background:url(icons_hidpi.png?t=I648) no-repeat 0 -264px!important;background-size:16px!important}.cke_rtl.cke_hidpi .cke_button__paste_icon,.cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__paste_icon{background:url(icons_hidpi.png?t=I648) no-repeat 0 -288px!important;background-size:16px!important}.cke_hidpi .cke_ltr .cke_button__paste_icon,.cke_ltr.cke_hidpi .cke_button__paste_icon{background:url(icons_hidpi.png?t=I648) no-repeat 0 -312px!important;background-size:16px!important}.cke_hidpi .cke_button__horizontalrule_icon{background:url(icons_hidpi.png?t=I648) no-repeat 0 -336px!important;background-size:16px!important}.cke_hidpi .cke_button__image_icon{background:url(icons_hidpi.png?t=I648) no-repeat 0 -360px!important;background-size:16px!important}.cke_rtl.cke_hidpi .cke_button__indent_icon,.cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__indent_icon{background:url(icons_hidpi.png?t=I648) no-repeat 0 -384px!important;background-size:16px!important}.cke_hidpi .cke_ltr .cke_button__indent_icon,.cke_ltr.cke_hidpi .cke_button__indent_icon{background:url(icons_hidpi.png?t=I648) no-repeat 0 -408px!important;background-size:16px!important}.cke_rtl.cke_hidpi .cke_button__outdent_icon,.cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__outdent_icon{background:url(icons_hidpi.png?t=I648) no-repeat 0 -432px!important;background-size:16px!important}.cke_hidpi .cke_ltr .cke_button__outdent_icon,.cke_ltr.cke_hidpi .cke_button__outdent_icon{background:url(icons_hidpi.png?t=I648) no-repeat 0 -456px!important;background-size:16px!important}.cke_hidpi .cke_button__justifyblock_icon{background:url(icons_hidpi.png?t=I648) no-repeat 0 -480px!important;background-size:16px!important}.cke_hidpi .cke_button__justifycenter_icon{background:url(icons_hidpi.png?t=I648) no-repeat 0 -504px!important;background-size:16px!important}.cke_hidpi .cke_button__justifyleft_icon{background:url(icons_hidpi.png?t=I648) no-repeat 0 -528px!important;background-size:16px!important}.cke_hidpi .cke_button__justifyright_icon{background:url(icons_hidpi.png?t=I648) no-repeat 0 -552px!important;background-size:16px!important}.cke_hidpi .cke_button__language_icon{background:url(icons_hidpi.png?t=I648) no-repeat 0 -576px!important;background-size:16px!important}.cke_rtl.cke_hidpi .cke_button__bulletedlist_icon,.cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__bulletedlist_icon{background:url(icons_hidpi.png?t=I648) no-repeat 0 -600px!important;background-size:16px!important}.cke_hidpi .cke_ltr .cke_button__bulletedlist_icon,.cke_ltr.cke_hidpi .cke_button__bulletedlist_icon{background:url(icons_hidpi.png?t=I648) no-repeat 0 -624px!important;background-size:16px!important}.cke_rtl.cke_hidpi .cke_button__numberedlist_icon,.cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__numberedlist_icon{background:url(icons_hidpi.png?t=I648) no-repeat 0 -648px!important;background-size:16px!important}.cke_hidpi .cke_ltr .cke_button__numberedlist_icon,.cke_ltr.cke_hidpi .cke_button__numberedlist_icon{background:url(icons_hidpi.png?t=I648) no-repeat 0 -672px!important;background-size:16px!important}.cke_hidpi .cke_button__maximize_icon{background:url(icons_hidpi.png?t=I648) no-repeat 0 -696px!important;background-size:16px!important}.cke_rtl.cke_hidpi .cke_button__pastefromword_icon,.cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__pastefromword_icon{background:url(icons_hidpi.png?t=I648) no-repeat 0 -720px!important;background-size:16px!important}.cke_hidpi .cke_ltr .cke_button__pastefromword_icon,.cke_ltr.cke_hidpi .cke_button__pastefromword_icon{background:url(icons_hidpi.png?t=I648) no-repeat 0 -744px!important;background-size:16px!important}.cke_rtl.cke_hidpi .cke_button__pastetext_icon,.cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__pastetext_icon{background:url(icons_hidpi.png?t=I648) no-repeat 0 -768px!important;background-size:16px!important}.cke_hidpi .cke_ltr .cke_button__pastetext_icon,.cke_ltr.cke_hidpi .cke_button__pastetext_icon{background:url(icons_hidpi.png?t=I648) no-repeat 0 -792px!important;background-size:16px!important}.cke_hidpi .cke_button__removeformat_icon{background:url(icons_hidpi.png?t=I648) no-repeat 0 -816px!important;background-size:16px!important}.cke_rtl.cke_hidpi .cke_button__showblocks_icon,.cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__showblocks_icon{background:url(icons_hidpi.png?t=I648) no-repeat 0 -840px!important;background-size:16px!important}.cke_hidpi .cke_ltr .cke_button__showblocks_icon,.cke_ltr.cke_hidpi .cke_button__showblocks_icon{background:url(icons_hidpi.png?t=I648) no-repeat 0 -864px!important;background-size:16px!important}.cke_rtl.cke_hidpi .cke_button__source_icon,.cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__source_icon{background:url(icons_hidpi.png?t=I648) no-repeat 0 -888px!important;background-size:16px!important}.cke_hidpi .cke_ltr .cke_button__source_icon,.cke_ltr.cke_hidpi .cke_button__source_icon{background:url(icons_hidpi.png?t=I648) no-repeat 0 -912px!important;background-size:16px!important}.cke_rtl.cke_hidpi .cke_button__sourcedialog_icon,.cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__sourcedialog_icon{background:url(icons_hidpi.png?t=I648) no-repeat 0 -936px!important;background-size:16px!important}.cke_hidpi .cke_ltr .cke_button__sourcedialog_icon,.cke_ltr.cke_hidpi .cke_button__sourcedialog_icon{background:url(icons_hidpi.png?t=I648) no-repeat 0 -960px!important;background-size:16px!important}.cke_hidpi .cke_button__specialchar_icon{background:url(icons_hidpi.png?t=I648) no-repeat 0 -984px!important;background-size:16px!important}.cke_hidpi .cke_button__table_icon{background:url(icons_hidpi.png?t=I648) no-repeat 0 -1008px!important;background-size:16px!important}.cke_rtl.cke_hidpi .cke_button__redo_icon,.cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__redo_icon{background:url(icons_hidpi.png?t=I648) no-repeat 0 -1032px!important;background-size:16px!important}.cke_hidpi .cke_ltr .cke_button__redo_icon,.cke_ltr.cke_hidpi .cke_button__redo_icon{background:url(icons_hidpi.png?t=I648) no-repeat 0 -1056px!important;background-size:16px!important}.cke_rtl.cke_hidpi .cke_button__undo_icon,.cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__undo_icon{background:url(icons_hidpi.png?t=I648) no-repeat 0 -1080px!important;background-size:16px!important}.cke_hidpi .cke_ltr .cke_button__undo_icon,.cke_ltr.cke_hidpi .cke_button__undo_icon{background:url(icons_hidpi.png?t=I648) no-repeat 0 -1104px!important;background-size:16px!important}.cke_hidpi .cke_button__simplebox_icon{background:url(icons_hidpi.png?t=I648) no-repeat 0 -2256px!important}.cke_bottom{padding-bottom:3px}.cke_combo_text{margin-bottom:-1px;margin-top:1px} \ No newline at end of file +.cke_reset{margin:0;padding:0;border:0;background:transparent;text-decoration:none;width:auto;height:auto;vertical-align:baseline;box-sizing:content-box;position:static;transition:none}.cke_reset_all,.cke_reset_all *,.cke_reset_all a,.cke_reset_all textarea{margin:0;padding:0;border:0;background:transparent;text-decoration:none;width:auto;height:auto;vertical-align:baseline;box-sizing:content-box;position:static;transition:none;border-collapse:collapse;font:normal normal normal 12px Arial,Helvetica,Tahoma,Verdana,Sans-Serif;color:#000;text-align:left;white-space:nowrap;cursor:auto;float:none}.cke_reset_all .cke_rtl *{text-align:right}.cke_reset_all iframe{vertical-align:inherit}.cke_reset_all textarea{white-space:pre-wrap}.cke_reset_all textarea,.cke_reset_all input[type="text"],.cke_reset_all input[type="password"]{cursor:text}.cke_reset_all textarea[disabled],.cke_reset_all input[type="text"][disabled],.cke_reset_all input[type="password"][disabled]{cursor:default}.cke_reset_all fieldset{padding:10px;border:2px groove #e0dfe3}.cke_reset_all select{box-sizing:border-box}.cke_reset_all table{table-layout:auto}.cke_chrome{display:block;border:1px solid #d1d1d1;padding:0}.cke_inner{display:block;background:#fff;padding:0;-webkit-touch-callout:none}.cke_float{border:0}.cke_float .cke_inner{padding-bottom:0}.cke_top,.cke_contents,.cke_bottom{display:block;overflow:hidden}.cke_top{border-bottom:1px solid #d1d1d1;background:#f8f8f8;padding:6px 8px 2px;white-space:normal}.cke_float .cke_top{border:1px solid #d1d1d1}.cke_bottom{padding:6px 8px 2px;position:relative;border-top:1px solid #d1d1d1;background:#f8f8f8}.cke_browser_ios .cke_contents{overflow-y:auto;-webkit-overflow-scrolling:touch}.cke_resizer{width:0;height:0;overflow:hidden;border-width:10px 10px 0 0;border-color:transparent #bcbcbc transparent transparent;border-style:dashed solid dashed dashed;font-size:0;vertical-align:bottom;margin-top:6px;margin-bottom:2px}.cke_hc .cke_resizer{font-size:15px;width:auto;height:auto;border-width:0}.cke_resizer_ltr{cursor:se-resize;float:right;margin-right:-4px}.cke_resizer_rtl{border-width:10px 0 0 10px;border-color:transparent transparent transparent #bcbcbc;border-style:dashed dashed dashed solid;cursor:sw-resize;float:left;margin-left:-4px;right:auto}.cke_wysiwyg_div{display:block;height:100%;overflow:auto;padding:0 8px;outline-style:none;box-sizing:border-box}.cke_panel{visibility:visible;width:120px;height:100px;overflow:hidden;background-color:#fff;border:1px solid #d1d1d1}.cke_menu_panel{padding:0;margin:0}.cke_combopanel{width:150px;height:170px}.cke_panel_frame{width:100%;height:100%;font-size:12px;overflow:auto;overflow-x:hidden}.cke_panel_container{overflow-y:auto;overflow-x:hidden}.cke_panel_block:focus{outline:0}.cke_panel_list{margin:0;padding:0;list-style-type:none;white-space:nowrap}.cke_panel_listItem{margin:0;padding:0}.cke_panel_listItem a{padding:6px 7px;display:block;color:inherit!important;text-decoration:none;overflow:hidden;text-overflow:ellipsis}.cke_hc .cke_panel_listItem a{border-style:none}.cke_panel_listItem.cke_selected a,.cke_panel_listItem a:hover,.cke_panel_listItem a:focus,.cke_panel_listItem a:active{background-color:#e9e9e9}.cke_panel_listItem a:focus{outline:1px dotted #000}.cke_hc .cke_panel_listItem a:hover,.cke_hc .cke_panel_listItem a:focus,.cke_hc .cke_panel_listItem a:active{border:2px solid;padding:4px 5px}.cke_panel_listItem p,.cke_panel_listItem h1,.cke_panel_listItem h2,.cke_panel_listItem h3,.cke_panel_listItem h4,.cke_panel_listItem h5,.cke_panel_listItem h6,.cke_panel_listItem pre{margin-top:0;margin-bottom:0}.cke_panel_grouptitle{cursor:default;font-size:11px;font-weight:bold;white-space:nowrap;margin:0;padding:6px 6px 7px 6px;color:#484848;border-bottom:1px solid #d1d1d1;background:#f8f8f8}.cke_colorblock{padding:10px;font-size:11px;font-family:'Microsoft Sans Serif',Tahoma,Arial,Verdana,Sans-Serif}.cke_colorblock,.cke_colorblock a{text-decoration:none;color:#000}a.cke_colorbox{padding:2px;float:left;width:20px;height:20px}.cke_rtl a.cke_colorbox{float:right}a:hover.cke_colorbox,a:focus.cke_colorbox,a:active.cke_colorbox{outline:0;padding:0;border:2px solid #139ff7}a:hover.cke_colorbox{border-color:#bcbcbc}span.cke_colorbox{width:20px;height:20px;float:left}.cke_rtl span.cke_colorbox{float:right}a.cke_colorauto,a.cke_colormore{border:#fff 1px solid;padding:3px;display:block;cursor:pointer}a.cke_colorauto{padding:0;border:1px solid transparent;margin-bottom:6px;height:26px;line-height:26px}a.cke_colormore{margin-top:10px;height:20px;line-height:19px}a:hover.cke_colorauto,a:hover.cke_colormore,a:focus.cke_colorauto,a:focus.cke_colormore,a:active.cke_colorauto,a:active.cke_colormore{outline:0;border:#139ff7 1px solid;background-color:#f8f8f8}a:hover.cke_colorauto,a:hover.cke_colormore{border-color:#bcbcbc}.cke_colorauto span.cke_colorbox{width:18px;height:18px;border:1px solid #808080;margin-left:1px;margin-top:3px}.cke_rtl .cke_colorauto span.cke_colorbox{margin-left:0;margin-right:1px}span.cke_colorbox[style*="#ffffff"],span.cke_colorbox[style*="#FFFFFF"],span.cke_colorbox[style="background-color:#fff"],span.cke_colorbox[style="background-color:#FFF"],span.cke_colorbox[style*="rgb(255,255,255)"],span.cke_colorbox[style*="rgb(255, 255, 255)"]{border:1px solid #808080;width:18px;height:18px}.cke_toolbar{float:left}.cke_rtl .cke_toolbar{float:right}.cke_toolgroup{border:0;float:left;margin:1px 2px 6px 0;padding-right:3px}.cke_rtl .cke_toolgroup{float:right;margin:1px 0 6px 2px;padding-left:3px;padding-right:0}.cke_hc .cke_toolgroup{margin-right:5px;margin-bottom:5px}.cke_hc.cke_rtl .cke_toolgroup{margin-right:0;margin-left:5px}a.cke_button{display:inline-block;height:18px;padding:4px 6px;outline:0;cursor:default;float:left;border:0;position:relative}.cke_rtl a.cke_button{float:right}.cke_hc a.cke_button{border:1px solid black;padding:3px 5px;margin:0 3px 5px 0}.cke_hc.cke_rtl a.cke_button{margin:0 0 5px 3px}a.cke_button_on{background:#fff;border:1px #bcbcbc solid;padding:3px 5px}a.cke_button_off:hover,a.cke_button_off:focus,a.cke_button_off:active{background:#e5e5e5;border:1px #bcbcbc solid;padding:3px 5px}.cke_hc a.cke_button_on,.cke_hc a.cke_button_off:hover,.cke_hc a.cke_button_off:focus,.cke_hc a.cke_button_off:active{background:#e5e5e5;border:3px solid #000;padding:1px 3px}a.cke_button_disabled:hover,a.cke_button_disabled:focus,a.cke_button_disabled:active{border:0;padding:4px 6px;background-color:transparent}a.cke_button_disabled:focus{border:1px #bcbcbc solid;padding:3px 5px}.cke_hc a.cke_button_disabled:hover,.cke_hc a.cke_button_disabled:focus,.cke_hc a.cke_button_disabled:active{border:1px solid #acacac;padding:3px 5px;margin:0 3px 5px 0}.cke_hc a.cke_button_disabled:focus{border:3px solid #000;padding:1px 3px}.cke_hc.cke_rtl a.cke_button_disabled:hover,.cke_hc.cke_rtl a.cke_button_disabled:focus,.cke_hc.cke_rtl a.cke_button_disabled:active{margin:0 0 5px 3px}a.cke_button_disabled .cke_button_icon,a.cke_button_disabled .cke_button_arrow{opacity:.3}.cke_hc a.cke_button_disabled{border-color:#acacac}.cke_hc a.cke_button_disabled .cke_button_icon,.cke_hc a.cke_button_disabled .cke_button_label{opacity:.5}.cke_toolgroup a.cke_button:last-child:after,.cke_toolgroup a.cke_button.cke_button_disabled:hover:last-child:after{content:"";position:absolute;height:18px;width:0;border-right:1px solid #bcbcbc;margin-top:4px;top:0;right:-3px}.cke_rtl .cke_toolgroup a.cke_button:last-child:after,.cke_rtl .cke_toolgroup a.cke_button.cke_button_disabled:hover:last-child:after{border-right:0;right:auto;border-left:1px solid #bcbcbc;top:0;left:-3px}.cke_hc .cke_toolgroup a.cke_button:last-child:after,.cke_hc .cke_toolgroup a.cke_button.cke_button_disabled:last-child:after,.cke_hc .cke_toolgroup a.cke_button.cke_button_disabled:hover:last-child:after{border-color:#000;top:0;right:-7px}.cke_hc.cke_rtl .cke_toolgroup a.cke_button:last-child:after,.cke_hc.cke_rtl .cke_toolgroup a.cke_button.cke_button_disabled:last-child:after,.cke_hc.cke_rtl .cke_toolgroup a.cke_button.cke_button_disabled:hover:last-child:after{top:0;right:auto;left:-7px}.cke_toolgroup a.cke_button:hover:last-child:after,.cke_toolgroup a.cke_button.cke_button_on:last-child:after{top:-1px;right:-4px}.cke_rtl .cke_toolgroup a.cke_button:hover:last-child:after,.cke_rtl .cke_toolgroup a.cke_button.cke_button_on:last-child:after{top:-1px;right:auto;left:-4px}.cke_hc .cke_toolgroup a.cke_button:hover:last-child:after,.cke_hc .cke_toolgroup a.cke_button.cke_button_on:last-child:after{top:-2px;right:-9px}.cke_hc.cke_rtl .cke_toolgroup a.cke_button:hover:last-child:after,.cke_hc.cke_rtl .cke_toolgroup a.cke_button.cke_button_on:last-child:after{top:-2px;right:auto;left:-9px}.cke_toolbar.cke_toolbar_last .cke_toolgroup a.cke_button:last-child:after{content:none;border:0;width:0;height:0}.cke_button_icon{cursor:inherit;background-repeat:no-repeat;margin-top:1px;width:16px;height:16px;float:left;display:inline-block}.cke_rtl .cke_button_icon{float:right}.cke_hc .cke_button_icon{display:none}.cke_button_label{display:none;padding-left:3px;margin-top:1px;line-height:17px;vertical-align:middle;float:left;cursor:default;color:#484848}.cke_rtl .cke_button_label{padding-right:3px;padding-left:0;float:right}.cke_hc .cke_button_label{padding:0;display:inline-block;font-size:12px}.cke_button_arrow{display:inline-block;margin:8px 0 0 1px;width:0;height:0;cursor:default;vertical-align:top;border-left:3px solid transparent;border-right:3px solid transparent;border-top:3px solid #484848}.cke_rtl .cke_button_arrow{margin-right:5px;margin-left:0}.cke_hc .cke_button_arrow{font-size:10px;margin:3px 0 0 3px;width:auto;border:0}.cke_toolbar_separator{float:left;background-color:#bcbcbc;margin:4px 2px 0 2px;height:18px;width:1px}.cke_rtl .cke_toolbar_separator{float:right}.cke_hc .cke_toolbar_separator{background-color:#000;margin-left:2px;margin-right:5px;margin-bottom:9px}.cke_hc.cke_rtl .cke_toolbar_separator{margin-left:5px;margin-right:2px}.cke_toolbar_break{display:block;clear:left}.cke_rtl .cke_toolbar_break{clear:right}a.cke_toolbox_collapser{width:12px;height:11px;float:right;margin:11px 0 0;font-size:0;cursor:default;text-align:center;border:1px solid #bcbcbc}.cke_rtl .cke_toolbox_collapser{float:left}.cke_toolbox_collapser:hover{background:#e5e5e5}.cke_toolbox_collapser.cke_toolbox_collapser_min{margin:0 2px 4px}.cke_toolbox_collapser .cke_arrow{display:inline-block;height:0;width:0;font-size:0;margin-top:1px;border:3px solid transparent;border-bottom-color:#484848}.cke_toolbox_collapser.cke_toolbox_collapser_min .cke_arrow{margin-top:4px;border-bottom-color:transparent;border-top-color:#484848}.cke_hc .cke_toolbox_collapser .cke_arrow{font-size:8px;width:auto;border:0;margin-top:0}.cke_menuitem span{cursor:default}.cke_menubutton{display:block}.cke_hc .cke_menubutton{padding:2px}.cke_menubutton:hover,.cke_menubutton:focus,.cke_menubutton:active{background-color:#e9e9e9;display:block;outline:1px dotted}.cke_menubutton:hover{outline:0}.cke_hc .cke_menubutton:hover,.cke_hc .cke_menubutton:focus,.cke_hc .cke_menubutton:active{border:2px solid;padding:0}.cke_menubutton_disabled:hover,.cke_menubutton_disabled:focus,.cke_menubutton_disabled:active{background-color:transparent;outline:0}.cke_menubutton_inner{display:table-row}.cke_menubutton_icon,.cke_menubutton_label,.cke_menuarrow{display:table-cell}.cke_menubutton_icon{background-color:#f8f8f8;padding:6px 4px}.cke_hc .cke_menubutton_icon{height:16px;width:0;padding:4px 0}.cke_menubutton:hover .cke_menubutton_icon,.cke_menubutton:focus .cke_menubutton_icon,.cke_menubutton:active .cke_menubutton_icon{background-color:#e9e9e9}.cke_menubutton_disabled:hover .cke_menubutton_icon,.cke_menubutton_disabled:focus .cke_menubutton_icon,.cke_menubutton_disabled:active .cke_menubutton_icon{background-color:#f8f8f8;outline:0}.cke_menuitem .cke_menubutton_on{background-color:#e9e9e9;border:1px solid #dedede;outline:0}.cke_menubutton_on .cke_menubutton_icon{padding-right:3px;background-color:#e9e9e9}.cke_menubutton_label{padding:0 5px;background-color:transparent;width:100%;vertical-align:middle}.cke_menubutton_shortcut{color:#979797}.cke_menubutton_disabled .cke_menubutton_label{opacity:.3;filter:alpha(opacity=30)}.cke_panel_frame .cke_menubutton_label{display:none}.cke_menuseparator{background-color:#d1d1d1;height:1px}.cke_menuarrow{background:transparent url(images/arrow.png) no-repeat 0 10px;padding:0 5px}.cke_rtl .cke_menuarrow{background-position:5px -13px;background-repeat:no-repeat}.cke_hc .cke_menuarrow{background-image:none}.cke_menuarrow span{display:none}.cke_hc .cke_menuarrow span{vertical-align:middle;display:inline}.cke_combo{display:inline-block;float:left;position:relative;margin-bottom:5px}.cke_rtl .cke_combo{float:right}.cke_hc .cke_combo{margin-top:1px;margin-bottom:10px}.cke_combo:after{content:"";position:absolute;height:18px;width:0;border-right:1px solid #bcbcbc;margin-top:5px;top:0;right:0}.cke_rtl .cke_combo:after{border-right:0;border-left:1px solid #bcbcbc;right:auto;left:0}.cke_hc .cke_combo:after{border-color:#000}a.cke_combo_button{cursor:default;display:inline-block;float:left;margin:0;padding:1px}.cke_rtl a.cke_combo_button{float:right}.cke_hc a.cke_combo_button{padding:4px}.cke_combo_on a.cke_combo_button,.cke_combo_off a.cke_combo_button:hover,.cke_combo_off a.cke_combo_button:focus,.cke_combo_off a.cke_combo_button:active{background:#e5e5e5;border:1px solid #bcbcbc;padding:0 0 0 1px;margin-left:-1px}.cke_combo_off a.cke_combo_button:focus{outline:0}.cke_combo_on a.cke_combo_button,.cke_combo_off a.cke_combo_button:active{background:#fff}.cke_rtl .cke_combo_on a.cke_combo_button,.cke_rtl .cke_combo_off a.cke_combo_button:hover,.cke_rtl .cke_combo_off a.cke_combo_button:focus,.cke_rtl .cke_combo_off a.cke_combo_button:active{padding:0 1px 0 0;margin-left:0;margin-right:-1px}.cke_hc .cke_combo_on a.cke_combo_button,.cke_hc .cke_combo_off a.cke_combo_button:hover,.cke_hc .cke_combo_off a.cke_combo_button:focus,.cke_hc .cke_combo_off a.cke_combo_button:active{border:3px solid #000;padding:1px 1px 1px 2px}.cke_hc.cke_rtl .cke_combo_on a.cke_combo_button,.cke_hc.cke_rtl .cke_combo_off a.cke_combo_button:hover,.cke_hc.cke_rtl .cke_combo_off a.cke_combo_button:focus,.cke_hc.cke_rtl .cke_combo_off a.cke_combo_button:active{padding:1px 2px 1px 1px}.cke_toolbar_start+.cke_combo_on a.cke_combo_button,.cke_toolbar_start+.cke_combo_off a.cke_combo_button:hover,.cke_toolbar_start+.cke_combo_off a.cke_combo_button:focus,.cke_toolbar_start+.cke_combo_off a.cke_combo_button:active{padding:0 0 0 3px;margin-left:-3px}.cke_rtl .cke_toolbar_start+.cke_combo_on a.cke_combo_button,.cke_rtl .cke_toolbar_start+.cke_combo_off a.cke_combo_button:hover,.cke_rtl .cke_toolbar_start+.cke_combo_off a.cke_combo_button:focus,.cke_rtl .cke_toolbar_start+.cke_combo_off a.cke_combo_button:active{padding:0 3px 0 0;margin-left:0;margin-right:-3px}.cke_hc .cke_toolbar>.cke_toolbar_start+.cke_combo_on a.cke_combo_button,.cke_hc .cke_toolbar>.cke_toolbar_start+.cke_combo_off a.cke_combo_button:hover,.cke_hc .cke_toolbar>.cke_toolbar_start+.cke_combo_off a.cke_combo_button:focus,.cke_hc .cke_toolbar>.cke_toolbar_start+.cke_combo_off a.cke_combo_button:active{padding:1px 1px 1px 7px;margin-left:-6px}.cke_hc.cke_rtl .cke_toolbar>.cke_toolbar_start+.cke_combo_on a.cke_combo_button,.cke_hc.cke_rtl .cke_toolbar>.cke_toolbar_start+.cke_combo_off a.cke_combo_button:hover,.cke_hc.cke_rtl .cke_toolbar>.cke_toolbar_start+.cke_combo_off a.cke_combo_button:focus,.cke_hc.cke_rtl .cke_toolbar>.cke_toolbar_start+.cke_combo_off a.cke_combo_button:active{padding:1px 7px 1px 1px;margin-left:0;margin-right:-6px}.cke_toolbox .cke_toolbar:first-child>.cke_toolbar_start+.cke_combo_on a.cke_combo_button,.cke_toolbox .cke_toolbar:first-child>.cke_toolbar_start+.cke_combo_off a.cke_combo_button:hover,.cke_toolbox .cke_toolbar:first-child>.cke_toolbar_start+.cke_combo_off a.cke_combo_button:focus,.cke_toolbox .cke_toolbar:first-child>.cke_toolbar_start+.cke_combo_off a.cke_combo_button:active,.cke_toolbar_break+.cke_toolbar>.cke_toolbar_start+.cke_combo_on a.cke_combo_button,.cke_toolbar_break+.cke_toolbar>.cke_toolbar_start+.cke_combo_off a.cke_combo_button:hover,.cke_toolbar_break+.cke_toolbar>.cke_toolbar_start+.cke_combo_off a.cke_combo_button:focus,.cke_toolbar_break+.cke_toolbar>.cke_toolbar_start+.cke_combo_off a.cke_combo_button:active{padding:0;margin:0}.cke_hc .cke_toolbox .cke_toolbar:first-child>.cke_toolbar_start+.cke_combo_on a.cke_combo_button,.cke_hc .cke_toolbox .cke_toolbar:first-child>.cke_toolbar_start+.cke_combo_off a.cke_combo_button:hover,.cke_hc .cke_toolbox .cke_toolbar:first-child>.cke_toolbar_start+.cke_combo_off a.cke_combo_button:focus,.cke_hc .cke_toolbox .cke_toolbar:first-child>.cke_toolbar_start+.cke_combo_off a.cke_combo_button:active,.cke_hc .cke_toolbar_break+.cke_toolbar>.cke_toolbar_start+.cke_combo_on a.cke_combo_button,.cke_hc .cke_toolbar_break+.cke_toolbar>.cke_toolbar_start+.cke_combo_off a.cke_combo_button:hover,.cke_hc .cke_toolbar_break+.cke_toolbar>.cke_toolbar_start+.cke_combo_off a.cke_combo_button:focus,.cke_hc .cke_toolbar_break+.cke_toolbar>.cke_toolbar_start+.cke_combo_off a.cke_combo_button:active{padding:1px;margin:0}.cke_toolbar .cke_combo+.cke_toolbar_end,.cke_toolbar .cke_combo+.cke_toolgroup{margin-right:0;margin-left:2px}.cke_rtl .cke_toolbar .cke_combo+.cke_toolbar_end,.cke_rtl .cke_toolbar .cke_combo+.cke_toolgroup{margin-left:0;margin-right:2px}.cke_hc .cke_toolbar .cke_combo+.cke_toolbar_end,.cke_hc .cke_toolbar .cke_combo+.cke_toolgroup{margin-left:5px}.cke_hc.cke_rtl .cke_toolbar .cke_combo+.cke_toolbar_end,.cke_hc.cke_rtl .cke_toolbar .cke_combo+.cke_toolgroup{margin-left:0;margin-right:5px}.cke_toolbar.cke_toolbar_last .cke_combo:nth-last-child(-n+2):after{content:none;border:0;width:0;height:0}.cke_combo_text{line-height:26px;padding-left:10px;text-overflow:ellipsis;overflow:hidden;float:left;cursor:default;color:#484848;width:60px}.cke_rtl .cke_combo_text{float:right;text-align:right;padding-left:0;padding-right:10px}.cke_hc .cke_combo_text{line-height:18px;font-size:12px}.cke_combo_open{cursor:default;display:inline-block;font-size:0;height:19px;line-height:17px;margin:1px 10px 1px;width:5px}.cke_hc .cke_combo_open{height:12px}.cke_combo_arrow{cursor:default;margin:11px 0 0;float:left;height:0;width:0;font-size:0;border-left:3px solid transparent;border-right:3px solid transparent;border-top:3px solid #484848}.cke_hc .cke_combo_arrow{font-size:10px;width:auto;border:0;margin-top:3px}.cke_combo_label{display:none;float:left;line-height:26px;vertical-align:top;margin-right:5px}.cke_rtl .cke_combo_label{float:right;margin-left:5px;margin-right:0}.cke_combo_disabled .cke_combo_inlinelabel,.cke_combo_disabled .cke_combo_open{opacity:.3}.cke_path{float:left;margin:-2px 0 2px}a.cke_path_item,span.cke_path_empty{display:inline-block;float:left;padding:3px 4px;margin-right:2px;cursor:default;text-decoration:none;outline:0;border:0;color:#484848;font-weight:bold;font-size:11px}.cke_rtl .cke_path,.cke_rtl .cke_path_item,.cke_rtl .cke_path_empty{float:right}a.cke_path_item:hover,a.cke_path_item:focus,a.cke_path_item:active{background-color:#e5e5e5}.cke_hc a.cke_path_item:hover,.cke_hc a.cke_path_item:focus,.cke_hc a.cke_path_item:active{border:2px solid;padding:1px 2px}.cke_button__source_label,.cke_button__sourcedialog_label{display:inline}.cke_combopanel__fontsize{width:135px}textarea.cke_source{font-family:'Courier New',Monospace;font-size:small;background-color:#fff;white-space:pre-wrap;border:0;padding:0;margin:0;display:block}.cke_wysiwyg_frame,.cke_wysiwyg_div{background-color:#fff}.cke_notifications_area{pointer-events:none}.cke_notification{pointer-events:auto;position:relative;margin:10px;width:300px;color:white;text-align:center;opacity:.95;filter:alpha(opacity = 95);-webkit-animation:fadeIn .7s;animation:fadeIn .7s}.cke_notification_message a{color:#12306f}@-webkit-keyframes fadeIn{from{opacity:.4}to{opacity:.95}}@keyframes fadeIn{from{opacity:.4}to{opacity:.95}}.cke_notification_success{background:#72b572;border:1px solid #63a563}.cke_notification_warning{background:#c83939;border:1px solid #902b2b}.cke_notification_info{background:#2e9ad0;border:1px solid #0f74a8}.cke_notification_info span.cke_notification_progress{background-color:#0f74a8;display:block;padding:0;margin:0;height:100%;overflow:hidden;position:absolute;z-index:1}.cke_notification_message{position:relative;margin:4px 23px 3px;font-family:Arial,Helvetica,sans-serif;font-size:12px;line-height:18px;z-index:4;text-overflow:ellipsis;overflow:hidden}.cke_notification_close{background-image:url(images/close.png);background-repeat:no-repeat;background-position:50%;position:absolute;cursor:pointer;text-align:center;height:20px;width:20px;top:1px;right:1px;padding:0;margin:0;z-index:5;opacity:.6;filter:alpha(opacity = 60)}.cke_notification_close:hover{opacity:1;filter:alpha(opacity = 100)}.cke_notification_close span{display:none}.cke_notification_warning a.cke_notification_close{opacity:.8;filter:alpha(opacity = 80)}.cke_notification_warning a.cke_notification_close:hover{opacity:1;filter:alpha(opacity = 100)}.cke_chrome{visibility:inherit}.cke_voice_label{display:none}legend.cke_voice_label{display:none}.cke_button__about_icon{background:url(icons.png?t=I8E8) no-repeat 0 -0px!important}.cke_button__bold_icon{background:url(icons.png?t=I8E8) no-repeat 0 -24px!important}.cke_button__italic_icon{background:url(icons.png?t=I8E8) no-repeat 0 -48px!important}.cke_button__strike_icon{background:url(icons.png?t=I8E8) no-repeat 0 -72px!important}.cke_button__subscript_icon{background:url(icons.png?t=I8E8) no-repeat 0 -96px!important}.cke_button__superscript_icon{background:url(icons.png?t=I8E8) no-repeat 0 -120px!important}.cke_button__underline_icon{background:url(icons.png?t=I8E8) no-repeat 0 -144px!important}.cke_button__blockquote_icon{background:url(icons.png?t=I8E8) no-repeat 0 -168px!important}.cke_rtl .cke_button__copy_icon,.cke_mixed_dir_content .cke_rtl .cke_button__copy_icon{background:url(icons.png?t=I8E8) no-repeat 0 -192px!important}.cke_ltr .cke_button__copy_icon{background:url(icons.png?t=I8E8) no-repeat 0 -216px!important}.cke_rtl .cke_button__cut_icon,.cke_mixed_dir_content .cke_rtl .cke_button__cut_icon{background:url(icons.png?t=I8E8) no-repeat 0 -240px!important}.cke_ltr .cke_button__cut_icon{background:url(icons.png?t=I8E8) no-repeat 0 -264px!important}.cke_rtl .cke_button__paste_icon,.cke_mixed_dir_content .cke_rtl .cke_button__paste_icon{background:url(icons.png?t=I8E8) no-repeat 0 -288px!important}.cke_ltr .cke_button__paste_icon{background:url(icons.png?t=I8E8) no-repeat 0 -312px!important}.cke_button__horizontalrule_icon{background:url(icons.png?t=I8E8) no-repeat 0 -336px!important}.cke_button__image_icon{background:url(icons.png?t=I8E8) no-repeat 0 -360px!important}.cke_rtl .cke_button__indent_icon,.cke_mixed_dir_content .cke_rtl .cke_button__indent_icon{background:url(icons.png?t=I8E8) no-repeat 0 -384px!important}.cke_ltr .cke_button__indent_icon{background:url(icons.png?t=I8E8) no-repeat 0 -408px!important}.cke_rtl .cke_button__outdent_icon,.cke_mixed_dir_content .cke_rtl .cke_button__outdent_icon{background:url(icons.png?t=I8E8) no-repeat 0 -432px!important}.cke_ltr .cke_button__outdent_icon{background:url(icons.png?t=I8E8) no-repeat 0 -456px!important}.cke_button__justifyblock_icon{background:url(icons.png?t=I8E8) no-repeat 0 -480px!important}.cke_button__justifycenter_icon{background:url(icons.png?t=I8E8) no-repeat 0 -504px!important}.cke_button__justifyleft_icon{background:url(icons.png?t=I8E8) no-repeat 0 -528px!important}.cke_button__justifyright_icon{background:url(icons.png?t=I8E8) no-repeat 0 -552px!important}.cke_button__language_icon{background:url(icons.png?t=I8E8) no-repeat 0 -576px!important}.cke_rtl .cke_button__bulletedlist_icon,.cke_mixed_dir_content .cke_rtl .cke_button__bulletedlist_icon{background:url(icons.png?t=I8E8) no-repeat 0 -600px!important}.cke_ltr .cke_button__bulletedlist_icon{background:url(icons.png?t=I8E8) no-repeat 0 -624px!important}.cke_rtl .cke_button__numberedlist_icon,.cke_mixed_dir_content .cke_rtl .cke_button__numberedlist_icon{background:url(icons.png?t=I8E8) no-repeat 0 -648px!important}.cke_ltr .cke_button__numberedlist_icon{background:url(icons.png?t=I8E8) no-repeat 0 -672px!important}.cke_button__maximize_icon{background:url(icons.png?t=I8E8) no-repeat 0 -696px!important}.cke_rtl .cke_button__pastefromword_icon,.cke_mixed_dir_content .cke_rtl .cke_button__pastefromword_icon{background:url(icons.png?t=I8E8) no-repeat 0 -720px!important}.cke_ltr .cke_button__pastefromword_icon{background:url(icons.png?t=I8E8) no-repeat 0 -744px!important}.cke_rtl .cke_button__pastetext_icon,.cke_mixed_dir_content .cke_rtl .cke_button__pastetext_icon{background:url(icons.png?t=I8E8) no-repeat 0 -768px!important}.cke_ltr .cke_button__pastetext_icon{background:url(icons.png?t=I8E8) no-repeat 0 -792px!important}.cke_button__removeformat_icon{background:url(icons.png?t=I8E8) no-repeat 0 -816px!important}.cke_rtl .cke_button__showblocks_icon,.cke_mixed_dir_content .cke_rtl .cke_button__showblocks_icon{background:url(icons.png?t=I8E8) no-repeat 0 -840px!important}.cke_ltr .cke_button__showblocks_icon{background:url(icons.png?t=I8E8) no-repeat 0 -864px!important}.cke_rtl .cke_button__source_icon,.cke_mixed_dir_content .cke_rtl .cke_button__source_icon{background:url(icons.png?t=I8E8) no-repeat 0 -888px!important}.cke_ltr .cke_button__source_icon{background:url(icons.png?t=I8E8) no-repeat 0 -912px!important}.cke_rtl .cke_button__sourcedialog_icon,.cke_mixed_dir_content .cke_rtl .cke_button__sourcedialog_icon{background:url(icons.png?t=I8E8) no-repeat 0 -936px!important}.cke_ltr .cke_button__sourcedialog_icon{background:url(icons.png?t=I8E8) no-repeat 0 -960px!important}.cke_button__specialchar_icon{background:url(icons.png?t=I8E8) no-repeat 0 -984px!important}.cke_button__table_icon{background:url(icons.png?t=I8E8) no-repeat 0 -1008px!important}.cke_rtl .cke_button__redo_icon,.cke_mixed_dir_content .cke_rtl .cke_button__redo_icon{background:url(icons.png?t=I8E8) no-repeat 0 -1032px!important}.cke_ltr .cke_button__redo_icon{background:url(icons.png?t=I8E8) no-repeat 0 -1056px!important}.cke_rtl .cke_button__undo_icon,.cke_mixed_dir_content .cke_rtl .cke_button__undo_icon{background:url(icons.png?t=I8E8) no-repeat 0 -1080px!important}.cke_ltr .cke_button__undo_icon{background:url(icons.png?t=I8E8) no-repeat 0 -1104px!important}.cke_button__simplebox_icon{background:url(icons.png?t=I8E8) no-repeat 0 -1128px!important}.cke_hidpi .cke_button__about_icon{background:url(icons_hidpi.png?t=I8E8) no-repeat 0 -0px!important;background-size:16px!important}.cke_hidpi .cke_button__bold_icon{background:url(icons_hidpi.png?t=I8E8) no-repeat 0 -24px!important;background-size:16px!important}.cke_hidpi .cke_button__italic_icon{background:url(icons_hidpi.png?t=I8E8) no-repeat 0 -48px!important;background-size:16px!important}.cke_hidpi .cke_button__strike_icon{background:url(icons_hidpi.png?t=I8E8) no-repeat 0 -72px!important;background-size:16px!important}.cke_hidpi .cke_button__subscript_icon{background:url(icons_hidpi.png?t=I8E8) no-repeat 0 -96px!important;background-size:16px!important}.cke_hidpi .cke_button__superscript_icon{background:url(icons_hidpi.png?t=I8E8) no-repeat 0 -120px!important;background-size:16px!important}.cke_hidpi .cke_button__underline_icon{background:url(icons_hidpi.png?t=I8E8) no-repeat 0 -144px!important;background-size:16px!important}.cke_hidpi .cke_button__blockquote_icon{background:url(icons_hidpi.png?t=I8E8) no-repeat 0 -168px!important;background-size:16px!important}.cke_rtl.cke_hidpi .cke_button__copy_icon,.cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__copy_icon{background:url(icons_hidpi.png?t=I8E8) no-repeat 0 -192px!important;background-size:16px!important}.cke_hidpi .cke_ltr .cke_button__copy_icon,.cke_ltr.cke_hidpi .cke_button__copy_icon{background:url(icons_hidpi.png?t=I8E8) no-repeat 0 -216px!important;background-size:16px!important}.cke_rtl.cke_hidpi .cke_button__cut_icon,.cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__cut_icon{background:url(icons_hidpi.png?t=I8E8) no-repeat 0 -240px!important;background-size:16px!important}.cke_hidpi .cke_ltr .cke_button__cut_icon,.cke_ltr.cke_hidpi .cke_button__cut_icon{background:url(icons_hidpi.png?t=I8E8) no-repeat 0 -264px!important;background-size:16px!important}.cke_rtl.cke_hidpi .cke_button__paste_icon,.cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__paste_icon{background:url(icons_hidpi.png?t=I8E8) no-repeat 0 -288px!important;background-size:16px!important}.cke_hidpi .cke_ltr .cke_button__paste_icon,.cke_ltr.cke_hidpi .cke_button__paste_icon{background:url(icons_hidpi.png?t=I8E8) no-repeat 0 -312px!important;background-size:16px!important}.cke_hidpi .cke_button__horizontalrule_icon{background:url(icons_hidpi.png?t=I8E8) no-repeat 0 -336px!important;background-size:16px!important}.cke_hidpi .cke_button__image_icon{background:url(icons_hidpi.png?t=I8E8) no-repeat 0 -360px!important;background-size:16px!important}.cke_rtl.cke_hidpi .cke_button__indent_icon,.cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__indent_icon{background:url(icons_hidpi.png?t=I8E8) no-repeat 0 -384px!important;background-size:16px!important}.cke_hidpi .cke_ltr .cke_button__indent_icon,.cke_ltr.cke_hidpi .cke_button__indent_icon{background:url(icons_hidpi.png?t=I8E8) no-repeat 0 -408px!important;background-size:16px!important}.cke_rtl.cke_hidpi .cke_button__outdent_icon,.cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__outdent_icon{background:url(icons_hidpi.png?t=I8E8) no-repeat 0 -432px!important;background-size:16px!important}.cke_hidpi .cke_ltr .cke_button__outdent_icon,.cke_ltr.cke_hidpi .cke_button__outdent_icon{background:url(icons_hidpi.png?t=I8E8) no-repeat 0 -456px!important;background-size:16px!important}.cke_hidpi .cke_button__justifyblock_icon{background:url(icons_hidpi.png?t=I8E8) no-repeat 0 -480px!important;background-size:16px!important}.cke_hidpi .cke_button__justifycenter_icon{background:url(icons_hidpi.png?t=I8E8) no-repeat 0 -504px!important;background-size:16px!important}.cke_hidpi .cke_button__justifyleft_icon{background:url(icons_hidpi.png?t=I8E8) no-repeat 0 -528px!important;background-size:16px!important}.cke_hidpi .cke_button__justifyright_icon{background:url(icons_hidpi.png?t=I8E8) no-repeat 0 -552px!important;background-size:16px!important}.cke_hidpi .cke_button__language_icon{background:url(icons_hidpi.png?t=I8E8) no-repeat 0 -576px!important;background-size:16px!important}.cke_rtl.cke_hidpi .cke_button__bulletedlist_icon,.cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__bulletedlist_icon{background:url(icons_hidpi.png?t=I8E8) no-repeat 0 -600px!important;background-size:16px!important}.cke_hidpi .cke_ltr .cke_button__bulletedlist_icon,.cke_ltr.cke_hidpi .cke_button__bulletedlist_icon{background:url(icons_hidpi.png?t=I8E8) no-repeat 0 -624px!important;background-size:16px!important}.cke_rtl.cke_hidpi .cke_button__numberedlist_icon,.cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__numberedlist_icon{background:url(icons_hidpi.png?t=I8E8) no-repeat 0 -648px!important;background-size:16px!important}.cke_hidpi .cke_ltr .cke_button__numberedlist_icon,.cke_ltr.cke_hidpi .cke_button__numberedlist_icon{background:url(icons_hidpi.png?t=I8E8) no-repeat 0 -672px!important;background-size:16px!important}.cke_hidpi .cke_button__maximize_icon{background:url(icons_hidpi.png?t=I8E8) no-repeat 0 -696px!important;background-size:16px!important}.cke_rtl.cke_hidpi .cke_button__pastefromword_icon,.cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__pastefromword_icon{background:url(icons_hidpi.png?t=I8E8) no-repeat 0 -720px!important;background-size:16px!important}.cke_hidpi .cke_ltr .cke_button__pastefromword_icon,.cke_ltr.cke_hidpi .cke_button__pastefromword_icon{background:url(icons_hidpi.png?t=I8E8) no-repeat 0 -744px!important;background-size:16px!important}.cke_rtl.cke_hidpi .cke_button__pastetext_icon,.cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__pastetext_icon{background:url(icons_hidpi.png?t=I8E8) no-repeat 0 -768px!important;background-size:16px!important}.cke_hidpi .cke_ltr .cke_button__pastetext_icon,.cke_ltr.cke_hidpi .cke_button__pastetext_icon{background:url(icons_hidpi.png?t=I8E8) no-repeat 0 -792px!important;background-size:16px!important}.cke_hidpi .cke_button__removeformat_icon{background:url(icons_hidpi.png?t=I8E8) no-repeat 0 -816px!important;background-size:16px!important}.cke_rtl.cke_hidpi .cke_button__showblocks_icon,.cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__showblocks_icon{background:url(icons_hidpi.png?t=I8E8) no-repeat 0 -840px!important;background-size:16px!important}.cke_hidpi .cke_ltr .cke_button__showblocks_icon,.cke_ltr.cke_hidpi .cke_button__showblocks_icon{background:url(icons_hidpi.png?t=I8E8) no-repeat 0 -864px!important;background-size:16px!important}.cke_rtl.cke_hidpi .cke_button__source_icon,.cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__source_icon{background:url(icons_hidpi.png?t=I8E8) no-repeat 0 -888px!important;background-size:16px!important}.cke_hidpi .cke_ltr .cke_button__source_icon,.cke_ltr.cke_hidpi .cke_button__source_icon{background:url(icons_hidpi.png?t=I8E8) no-repeat 0 -912px!important;background-size:16px!important}.cke_rtl.cke_hidpi .cke_button__sourcedialog_icon,.cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__sourcedialog_icon{background:url(icons_hidpi.png?t=I8E8) no-repeat 0 -936px!important;background-size:16px!important}.cke_hidpi .cke_ltr .cke_button__sourcedialog_icon,.cke_ltr.cke_hidpi .cke_button__sourcedialog_icon{background:url(icons_hidpi.png?t=I8E8) no-repeat 0 -960px!important;background-size:16px!important}.cke_hidpi .cke_button__specialchar_icon{background:url(icons_hidpi.png?t=I8E8) no-repeat 0 -984px!important;background-size:16px!important}.cke_hidpi .cke_button__table_icon{background:url(icons_hidpi.png?t=I8E8) no-repeat 0 -1008px!important;background-size:16px!important}.cke_rtl.cke_hidpi .cke_button__redo_icon,.cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__redo_icon{background:url(icons_hidpi.png?t=I8E8) no-repeat 0 -1032px!important;background-size:16px!important}.cke_hidpi .cke_ltr .cke_button__redo_icon,.cke_ltr.cke_hidpi .cke_button__redo_icon{background:url(icons_hidpi.png?t=I8E8) no-repeat 0 -1056px!important;background-size:16px!important}.cke_rtl.cke_hidpi .cke_button__undo_icon,.cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__undo_icon{background:url(icons_hidpi.png?t=I8E8) no-repeat 0 -1080px!important;background-size:16px!important}.cke_hidpi .cke_ltr .cke_button__undo_icon,.cke_ltr.cke_hidpi .cke_button__undo_icon{background:url(icons_hidpi.png?t=I8E8) no-repeat 0 -1104px!important;background-size:16px!important}.cke_hidpi .cke_button__simplebox_icon{background:url(icons_hidpi.png?t=I8E8) no-repeat 0 -2256px!important}.cke_bottom{padding-bottom:3px}.cke_combo_text{margin-bottom:-1px;margin-top:1px} \ No newline at end of file diff --git a/web/core/assets/vendor/ckeditor/skins/moono-lisa/editor_ie.css b/web/core/assets/vendor/ckeditor/skins/moono-lisa/editor_ie.css index ce8ca951492a7c641af00682bd54184a5d0b9274..3be1d66592edb35bff072e46954b01500913fb17 100644 --- a/web/core/assets/vendor/ckeditor/skins/moono-lisa/editor_ie.css +++ b/web/core/assets/vendor/ckeditor/skins/moono-lisa/editor_ie.css @@ -2,4 +2,4 @@ Copyright (c) 2003-2018, CKSource - Frederico Knabben. All rights reserved. For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license */ -.cke_reset{margin:0;padding:0;border:0;background:transparent;text-decoration:none;width:auto;height:auto;vertical-align:baseline;box-sizing:content-box;position:static;transition:none}.cke_reset_all,.cke_reset_all *,.cke_reset_all a,.cke_reset_all textarea{margin:0;padding:0;border:0;background:transparent;text-decoration:none;width:auto;height:auto;vertical-align:baseline;box-sizing:content-box;position:static;transition:none;border-collapse:collapse;font:normal normal normal 12px Arial,Helvetica,Tahoma,Verdana,Sans-Serif;color:#000;text-align:left;white-space:nowrap;cursor:auto;float:none}.cke_reset_all .cke_rtl *{text-align:right}.cke_reset_all iframe{vertical-align:inherit}.cke_reset_all textarea{white-space:pre-wrap}.cke_reset_all textarea,.cke_reset_all input[type="text"],.cke_reset_all input[type="password"]{cursor:text}.cke_reset_all textarea[disabled],.cke_reset_all input[type="text"][disabled],.cke_reset_all input[type="password"][disabled]{cursor:default}.cke_reset_all fieldset{padding:10px;border:2px groove #e0dfe3}.cke_reset_all select{box-sizing:border-box}.cke_reset_all table{table-layout:auto}.cke_chrome{display:block;border:1px solid #d1d1d1;padding:0}.cke_inner{display:block;background:#fff;padding:0;-webkit-touch-callout:none}.cke_float{border:0}.cke_float .cke_inner{padding-bottom:0}.cke_top,.cke_contents,.cke_bottom{display:block;overflow:hidden}.cke_top{border-bottom:1px solid #d1d1d1;background:#f8f8f8;padding:6px 8px 2px;white-space:normal}.cke_float .cke_top{border:1px solid #d1d1d1}.cke_bottom{padding:6px 8px 2px;position:relative;border-top:1px solid #d1d1d1;background:#f8f8f8}.cke_browser_ios .cke_contents{overflow-y:auto;-webkit-overflow-scrolling:touch}.cke_resizer{width:0;height:0;overflow:hidden;border-width:10px 10px 0 0;border-color:transparent #bcbcbc transparent transparent;border-style:dashed solid dashed dashed;font-size:0;vertical-align:bottom;margin-top:6px;margin-bottom:2px}.cke_hc .cke_resizer{font-size:15px;width:auto;height:auto;border-width:0}.cke_resizer_ltr{cursor:se-resize;float:right;margin-right:-4px}.cke_resizer_rtl{border-width:10px 0 0 10px;border-color:transparent transparent transparent #bcbcbc;border-style:dashed dashed dashed solid;cursor:sw-resize;float:left;margin-left:-4px;right:auto}.cke_wysiwyg_div{display:block;height:100%;overflow:auto;padding:0 8px;outline-style:none;box-sizing:border-box}.cke_panel{visibility:visible;width:120px;height:100px;overflow:hidden;background-color:#fff;border:1px solid #d1d1d1}.cke_menu_panel{padding:0;margin:0}.cke_combopanel{width:150px;height:170px}.cke_panel_frame{width:100%;height:100%;font-size:12px;overflow:auto;overflow-x:hidden}.cke_panel_container{overflow-y:auto;overflow-x:hidden}.cke_panel_block:focus{outline:0}.cke_panel_list{margin:0;padding:0;list-style-type:none;white-space:nowrap}.cke_panel_listItem{margin:0;padding:0}.cke_panel_listItem a{padding:6px 7px;display:block;color:inherit!important;text-decoration:none;overflow:hidden;text-overflow:ellipsis}.cke_hc .cke_panel_listItem a{border-style:none}.cke_panel_listItem.cke_selected a,.cke_panel_listItem a:hover,.cke_panel_listItem a:focus,.cke_panel_listItem a:active{background-color:#e9e9e9}.cke_panel_listItem a:focus{outline:1px dotted #000}.cke_hc .cke_panel_listItem a:hover,.cke_hc .cke_panel_listItem a:focus,.cke_hc .cke_panel_listItem a:active{border:2px solid;padding:4px 5px}.cke_panel_listItem p,.cke_panel_listItem h1,.cke_panel_listItem h2,.cke_panel_listItem h3,.cke_panel_listItem h4,.cke_panel_listItem h5,.cke_panel_listItem h6,.cke_panel_listItem pre{margin-top:0;margin-bottom:0}.cke_panel_grouptitle{cursor:default;font-size:11px;font-weight:bold;white-space:nowrap;margin:0;padding:6px 6px 7px 6px;color:#484848;border-bottom:1px solid #d1d1d1;background:#f8f8f8}.cke_colorblock{padding:10px;font-size:11px;font-family:'Microsoft Sans Serif',Tahoma,Arial,Verdana,Sans-Serif}.cke_colorblock,.cke_colorblock a{text-decoration:none;color:#000}a.cke_colorbox{padding:2px;float:left;width:20px;height:20px}.cke_rtl a.cke_colorbox{float:right}a:hover.cke_colorbox,a:focus.cke_colorbox,a:active.cke_colorbox{outline:0;padding:0;border:2px solid #139ff7}a:hover.cke_colorbox{border-color:#bcbcbc}span.cke_colorbox{width:20px;height:20px;float:left}.cke_rtl span.cke_colorbox{float:right}a.cke_colorauto,a.cke_colormore{border:#fff 1px solid;padding:3px;display:block;cursor:pointer}a.cke_colorauto{padding:0;border:1px solid transparent;margin-bottom:6px;height:26px;line-height:26px}a.cke_colormore{margin-top:10px;height:20px;line-height:19px}a:hover.cke_colorauto,a:hover.cke_colormore,a:focus.cke_colorauto,a:focus.cke_colormore,a:active.cke_colorauto,a:active.cke_colormore{outline:0;border:#139ff7 1px solid;background-color:#f8f8f8}a:hover.cke_colorauto,a:hover.cke_colormore{border-color:#bcbcbc}.cke_colorauto span.cke_colorbox{width:18px;height:18px;border:1px solid #808080;margin-left:1px;margin-top:3px}.cke_rtl .cke_colorauto span.cke_colorbox{margin-left:0;margin-right:1px}span.cke_colorbox[style*="#ffffff"],span.cke_colorbox[style*="#FFFFFF"],span.cke_colorbox[style="background-color:#fff"],span.cke_colorbox[style="background-color:#FFF"],span.cke_colorbox[style*="rgb(255,255,255)"],span.cke_colorbox[style*="rgb(255, 255, 255)"]{border:1px solid #808080;width:18px;height:18px}.cke_toolbar{float:left}.cke_rtl .cke_toolbar{float:right}.cke_toolgroup{border:0;float:left;margin:1px 2px 6px 0;padding-right:3px}.cke_rtl .cke_toolgroup{float:right;margin:1px 0 6px 2px;padding-left:3px;padding-right:0}.cke_hc .cke_toolgroup{margin-right:5px;margin-bottom:5px}.cke_hc.cke_rtl .cke_toolgroup{margin-right:0;margin-left:5px}a.cke_button{display:inline-block;height:18px;padding:4px 6px;outline:0;cursor:default;float:left;border:0;position:relative}.cke_rtl a.cke_button{float:right}.cke_hc a.cke_button{border:1px solid black;padding:3px 5px;margin:0 3px 5px 0}.cke_hc.cke_rtl a.cke_button{margin:0 0 5px 3px}a.cke_button_on{background:#fff;border:1px #bcbcbc solid;padding:3px 5px}a.cke_button_off:hover,a.cke_button_off:focus,a.cke_button_off:active{background:#e5e5e5;border:1px #bcbcbc solid;padding:3px 5px}.cke_hc a.cke_button_on,.cke_hc a.cke_button_off:hover,.cke_hc a.cke_button_off:focus,.cke_hc a.cke_button_off:active{background:#e5e5e5;border:3px solid #000;padding:1px 3px}a.cke_button_disabled:hover,a.cke_button_disabled:focus,a.cke_button_disabled:active{border:0;padding:4px 6px;background-color:transparent}a.cke_button_disabled:focus{border:1px #bcbcbc solid;padding:3px 5px}.cke_hc a.cke_button_disabled:hover,.cke_hc a.cke_button_disabled:focus,.cke_hc a.cke_button_disabled:active{border:1px solid #acacac;padding:3px 5px;margin:0 3px 5px 0}.cke_hc a.cke_button_disabled:focus{border:3px solid #000;padding:1px 3px}.cke_hc.cke_rtl a.cke_button_disabled:hover,.cke_hc.cke_rtl a.cke_button_disabled:focus,.cke_hc.cke_rtl a.cke_button_disabled:active{margin:0 0 5px 3px}a.cke_button_disabled .cke_button_icon,a.cke_button_disabled .cke_button_arrow{opacity:.3}.cke_hc a.cke_button_disabled{border-color:#acacac}.cke_hc a.cke_button_disabled .cke_button_icon,.cke_hc a.cke_button_disabled .cke_button_label{opacity:.5}.cke_toolgroup a.cke_button:last-child:after,.cke_toolgroup a.cke_button.cke_button_disabled:hover:last-child:after{content:"";position:absolute;height:18px;width:0;border-right:1px solid #bcbcbc;margin-top:4px;top:0;right:-3px}.cke_rtl .cke_toolgroup a.cke_button:last-child:after,.cke_rtl .cke_toolgroup a.cke_button.cke_button_disabled:hover:last-child:after{border-right:0;right:auto;border-left:1px solid #bcbcbc;top:0;left:-3px}.cke_hc .cke_toolgroup a.cke_button:last-child:after,.cke_hc .cke_toolgroup a.cke_button.cke_button_disabled:last-child:after,.cke_hc .cke_toolgroup a.cke_button.cke_button_disabled:hover:last-child:after{border-color:#000;top:0;right:-7px}.cke_hc.cke_rtl .cke_toolgroup a.cke_button:last-child:after,.cke_hc.cke_rtl .cke_toolgroup a.cke_button.cke_button_disabled:last-child:after,.cke_hc.cke_rtl .cke_toolgroup a.cke_button.cke_button_disabled:hover:last-child:after{top:0;right:auto;left:-7px}.cke_toolgroup a.cke_button:hover:last-child:after,.cke_toolgroup a.cke_button.cke_button_on:last-child:after{top:-1px;right:-4px}.cke_rtl .cke_toolgroup a.cke_button:hover:last-child:after,.cke_rtl .cke_toolgroup a.cke_button.cke_button_on:last-child:after{top:-1px;right:auto;left:-4px}.cke_hc .cke_toolgroup a.cke_button:hover:last-child:after,.cke_hc .cke_toolgroup a.cke_button.cke_button_on:last-child:after{top:-2px;right:-9px}.cke_hc.cke_rtl .cke_toolgroup a.cke_button:hover:last-child:after,.cke_hc.cke_rtl .cke_toolgroup a.cke_button.cke_button_on:last-child:after{top:-2px;right:auto;left:-9px}.cke_toolbar.cke_toolbar_last .cke_toolgroup a.cke_button:last-child:after{content:none;border:0;width:0;height:0}.cke_button_icon{cursor:inherit;background-repeat:no-repeat;margin-top:1px;width:16px;height:16px;float:left;display:inline-block}.cke_rtl .cke_button_icon{float:right}.cke_hc .cke_button_icon{display:none}.cke_button_label{display:none;padding-left:3px;margin-top:1px;line-height:17px;vertical-align:middle;float:left;cursor:default;color:#484848}.cke_rtl .cke_button_label{padding-right:3px;padding-left:0;float:right}.cke_hc .cke_button_label{padding:0;display:inline-block;font-size:12px}.cke_button_arrow{display:inline-block;margin:8px 0 0 1px;width:0;height:0;cursor:default;vertical-align:top;border-left:3px solid transparent;border-right:3px solid transparent;border-top:3px solid #484848}.cke_rtl .cke_button_arrow{margin-right:5px;margin-left:0}.cke_hc .cke_button_arrow{font-size:10px;margin:3px 0 0 3px;width:auto;border:0}.cke_toolbar_separator{float:left;background-color:#bcbcbc;margin:4px 2px 0 2px;height:18px;width:1px}.cke_rtl .cke_toolbar_separator{float:right}.cke_hc .cke_toolbar_separator{background-color:#000;margin-left:2px;margin-right:5px;margin-bottom:9px}.cke_hc.cke_rtl .cke_toolbar_separator{margin-left:5px;margin-right:2px}.cke_toolbar_break{display:block;clear:left}.cke_rtl .cke_toolbar_break{clear:right}a.cke_toolbox_collapser{width:12px;height:11px;float:right;margin:11px 0 0;font-size:0;cursor:default;text-align:center;border:1px solid #bcbcbc}.cke_rtl .cke_toolbox_collapser{float:left}.cke_toolbox_collapser:hover{background:#e5e5e5}.cke_toolbox_collapser.cke_toolbox_collapser_min{margin:0 2px 4px}.cke_toolbox_collapser .cke_arrow{display:inline-block;height:0;width:0;font-size:0;margin-top:1px;border:3px solid transparent;border-bottom-color:#484848}.cke_toolbox_collapser.cke_toolbox_collapser_min .cke_arrow{margin-top:4px;border-bottom-color:transparent;border-top-color:#484848}.cke_hc .cke_toolbox_collapser .cke_arrow{font-size:8px;width:auto;border:0;margin-top:0}.cke_menuitem span{cursor:default}.cke_menubutton{display:block}.cke_hc .cke_menubutton{padding:2px}.cke_menubutton:hover,.cke_menubutton:focus,.cke_menubutton:active{background-color:#e9e9e9;display:block;outline:1px dotted}.cke_menubutton:hover{outline:0}.cke_hc .cke_menubutton:hover,.cke_hc .cke_menubutton:focus,.cke_hc .cke_menubutton:active{border:2px solid;padding:0}.cke_menubutton_disabled:hover,.cke_menubutton_disabled:focus,.cke_menubutton_disabled:active{background-color:transparent;outline:0}.cke_menubutton_inner{display:table-row}.cke_menubutton_icon,.cke_menubutton_label,.cke_menuarrow{display:table-cell}.cke_menubutton_icon{background-color:#f8f8f8;padding:6px 4px}.cke_hc .cke_menubutton_icon{height:16px;width:0;padding:4px 0}.cke_menubutton:hover .cke_menubutton_icon,.cke_menubutton:focus .cke_menubutton_icon,.cke_menubutton:active .cke_menubutton_icon{background-color:#e9e9e9}.cke_menubutton_disabled:hover .cke_menubutton_icon,.cke_menubutton_disabled:focus .cke_menubutton_icon,.cke_menubutton_disabled:active .cke_menubutton_icon{background-color:#f8f8f8;outline:0}.cke_menuitem .cke_menubutton_on{background-color:#e9e9e9;border:1px solid #dedede;outline:0}.cke_menubutton_on .cke_menubutton_icon{padding-right:3px;background-color:#e9e9e9}.cke_menubutton_label{padding:0 5px;background-color:transparent;width:100%;vertical-align:middle}.cke_menubutton_shortcut{color:#979797}.cke_menubutton_disabled .cke_menubutton_label{opacity:.3;filter:alpha(opacity=30)}.cke_panel_frame .cke_menubutton_label{display:none}.cke_menuseparator{background-color:#d1d1d1;height:1px}.cke_menuarrow{background:transparent url(images/arrow.png) no-repeat 0 10px;padding:0 5px}.cke_rtl .cke_menuarrow{background-position:5px -13px;background-repeat:no-repeat}.cke_hc .cke_menuarrow{background-image:none}.cke_menuarrow span{display:none}.cke_hc .cke_menuarrow span{vertical-align:middle;display:inline}.cke_combo{display:inline-block;float:left;position:relative;margin-bottom:5px}.cke_rtl .cke_combo{float:right}.cke_hc .cke_combo{margin-top:1px;margin-bottom:10px}.cke_combo:after{content:"";position:absolute;height:18px;width:0;border-right:1px solid #bcbcbc;margin-top:5px;top:0;right:0}.cke_rtl .cke_combo:after{border-right:0;border-left:1px solid #bcbcbc;right:auto;left:0}.cke_hc .cke_combo:after{border-color:#000}a.cke_combo_button{cursor:default;display:inline-block;float:left;margin:0;padding:1px}.cke_rtl a.cke_combo_button{float:right}.cke_hc a.cke_combo_button{padding:4px}.cke_combo_on a.cke_combo_button,.cke_combo_off a.cke_combo_button:hover,.cke_combo_off a.cke_combo_button:focus,.cke_combo_off a.cke_combo_button:active{background:#e5e5e5;border:1px solid #bcbcbc;padding:0 0 0 1px;margin-left:-1px}.cke_combo_off a.cke_combo_button:focus{outline:0}.cke_combo_on a.cke_combo_button,.cke_combo_off a.cke_combo_button:active{background:#fff}.cke_rtl .cke_combo_on a.cke_combo_button,.cke_rtl .cke_combo_off a.cke_combo_button:hover,.cke_rtl .cke_combo_off a.cke_combo_button:focus,.cke_rtl .cke_combo_off a.cke_combo_button:active{padding:0 1px 0 0;margin-left:0;margin-right:-1px}.cke_hc .cke_combo_on a.cke_combo_button,.cke_hc .cke_combo_off a.cke_combo_button:hover,.cke_hc .cke_combo_off a.cke_combo_button:focus,.cke_hc .cke_combo_off a.cke_combo_button:active{border:3px solid #000;padding:1px 1px 1px 2px}.cke_hc.cke_rtl .cke_combo_on a.cke_combo_button,.cke_hc.cke_rtl .cke_combo_off a.cke_combo_button:hover,.cke_hc.cke_rtl .cke_combo_off a.cke_combo_button:focus,.cke_hc.cke_rtl .cke_combo_off a.cke_combo_button:active{padding:1px 2px 1px 1px}.cke_toolbar_start+.cke_combo_on a.cke_combo_button,.cke_toolbar_start+.cke_combo_off a.cke_combo_button:hover,.cke_toolbar_start+.cke_combo_off a.cke_combo_button:focus,.cke_toolbar_start+.cke_combo_off a.cke_combo_button:active{padding:0 0 0 3px;margin-left:-3px}.cke_rtl .cke_toolbar_start+.cke_combo_on a.cke_combo_button,.cke_rtl .cke_toolbar_start+.cke_combo_off a.cke_combo_button:hover,.cke_rtl .cke_toolbar_start+.cke_combo_off a.cke_combo_button:focus,.cke_rtl .cke_toolbar_start+.cke_combo_off a.cke_combo_button:active{padding:0 3px 0 0;margin-left:0;margin-right:-3px}.cke_hc .cke_toolbar>.cke_toolbar_start+.cke_combo_on a.cke_combo_button,.cke_hc .cke_toolbar>.cke_toolbar_start+.cke_combo_off a.cke_combo_button:hover,.cke_hc .cke_toolbar>.cke_toolbar_start+.cke_combo_off a.cke_combo_button:focus,.cke_hc .cke_toolbar>.cke_toolbar_start+.cke_combo_off a.cke_combo_button:active{padding:1px 1px 1px 7px;margin-left:-6px}.cke_hc.cke_rtl .cke_toolbar>.cke_toolbar_start+.cke_combo_on a.cke_combo_button,.cke_hc.cke_rtl .cke_toolbar>.cke_toolbar_start+.cke_combo_off a.cke_combo_button:hover,.cke_hc.cke_rtl .cke_toolbar>.cke_toolbar_start+.cke_combo_off a.cke_combo_button:focus,.cke_hc.cke_rtl .cke_toolbar>.cke_toolbar_start+.cke_combo_off a.cke_combo_button:active{padding:1px 7px 1px 1px;margin-left:0;margin-right:-6px}.cke_toolbox .cke_toolbar:first-child>.cke_toolbar_start+.cke_combo_on a.cke_combo_button,.cke_toolbox .cke_toolbar:first-child>.cke_toolbar_start+.cke_combo_off a.cke_combo_button:hover,.cke_toolbox .cke_toolbar:first-child>.cke_toolbar_start+.cke_combo_off a.cke_combo_button:focus,.cke_toolbox .cke_toolbar:first-child>.cke_toolbar_start+.cke_combo_off a.cke_combo_button:active,.cke_toolbar_break+.cke_toolbar>.cke_toolbar_start+.cke_combo_on a.cke_combo_button,.cke_toolbar_break+.cke_toolbar>.cke_toolbar_start+.cke_combo_off a.cke_combo_button:hover,.cke_toolbar_break+.cke_toolbar>.cke_toolbar_start+.cke_combo_off a.cke_combo_button:focus,.cke_toolbar_break+.cke_toolbar>.cke_toolbar_start+.cke_combo_off a.cke_combo_button:active{padding:0;margin:0}.cke_hc .cke_toolbox .cke_toolbar:first-child>.cke_toolbar_start+.cke_combo_on a.cke_combo_button,.cke_hc .cke_toolbox .cke_toolbar:first-child>.cke_toolbar_start+.cke_combo_off a.cke_combo_button:hover,.cke_hc .cke_toolbox .cke_toolbar:first-child>.cke_toolbar_start+.cke_combo_off a.cke_combo_button:focus,.cke_hc .cke_toolbox .cke_toolbar:first-child>.cke_toolbar_start+.cke_combo_off a.cke_combo_button:active,.cke_hc .cke_toolbar_break+.cke_toolbar>.cke_toolbar_start+.cke_combo_on a.cke_combo_button,.cke_hc .cke_toolbar_break+.cke_toolbar>.cke_toolbar_start+.cke_combo_off a.cke_combo_button:hover,.cke_hc .cke_toolbar_break+.cke_toolbar>.cke_toolbar_start+.cke_combo_off a.cke_combo_button:focus,.cke_hc .cke_toolbar_break+.cke_toolbar>.cke_toolbar_start+.cke_combo_off a.cke_combo_button:active{padding:1px;margin:0}.cke_toolbar .cke_combo+.cke_toolbar_end,.cke_toolbar .cke_combo+.cke_toolgroup{margin-right:0;margin-left:2px}.cke_rtl .cke_toolbar .cke_combo+.cke_toolbar_end,.cke_rtl .cke_toolbar .cke_combo+.cke_toolgroup{margin-left:0;margin-right:2px}.cke_hc .cke_toolbar .cke_combo+.cke_toolbar_end,.cke_hc .cke_toolbar .cke_combo+.cke_toolgroup{margin-left:5px}.cke_hc.cke_rtl .cke_toolbar .cke_combo+.cke_toolbar_end,.cke_hc.cke_rtl .cke_toolbar .cke_combo+.cke_toolgroup{margin-left:0;margin-right:5px}.cke_toolbar.cke_toolbar_last .cke_combo:nth-last-child(-n+2):after{content:none;border:0;width:0;height:0}.cke_combo_text{line-height:26px;padding-left:10px;text-overflow:ellipsis;overflow:hidden;float:left;cursor:default;color:#484848;width:60px}.cke_rtl .cke_combo_text{float:right;text-align:right;padding-left:0;padding-right:10px}.cke_hc .cke_combo_text{line-height:18px;font-size:12px}.cke_combo_open{cursor:default;display:inline-block;font-size:0;height:19px;line-height:17px;margin:1px 10px 1px;width:5px}.cke_hc .cke_combo_open{height:12px}.cke_combo_arrow{cursor:default;margin:11px 0 0;float:left;height:0;width:0;font-size:0;border-left:3px solid transparent;border-right:3px solid transparent;border-top:3px solid #484848}.cke_hc .cke_combo_arrow{font-size:10px;width:auto;border:0;margin-top:3px}.cke_combo_label{display:none;float:left;line-height:26px;vertical-align:top;margin-right:5px}.cke_rtl .cke_combo_label{float:right;margin-left:5px;margin-right:0}.cke_combo_disabled .cke_combo_inlinelabel,.cke_combo_disabled .cke_combo_open{opacity:.3}.cke_path{float:left;margin:-2px 0 2px}a.cke_path_item,span.cke_path_empty{display:inline-block;float:left;padding:3px 4px;margin-right:2px;cursor:default;text-decoration:none;outline:0;border:0;color:#484848;font-weight:bold;font-size:11px}.cke_rtl .cke_path,.cke_rtl .cke_path_item,.cke_rtl .cke_path_empty{float:right}a.cke_path_item:hover,a.cke_path_item:focus,a.cke_path_item:active{background-color:#e5e5e5}.cke_hc a.cke_path_item:hover,.cke_hc a.cke_path_item:focus,.cke_hc a.cke_path_item:active{border:2px solid;padding:1px 2px}.cke_button__source_label,.cke_button__sourcedialog_label{display:inline}.cke_combopanel__fontsize{width:135px}textarea.cke_source{font-family:'Courier New',Monospace;font-size:small;background-color:#fff;white-space:pre-wrap;border:0;padding:0;margin:0;display:block}.cke_wysiwyg_frame,.cke_wysiwyg_div{background-color:#fff}.cke_notifications_area{pointer-events:none}.cke_notification{pointer-events:auto;position:relative;margin:10px;width:300px;color:white;text-align:center;opacity:.95;filter:alpha(opacity = 95);-webkit-animation:fadeIn .7s;animation:fadeIn .7s}.cke_notification_message a{color:#12306f}@-webkit-keyframes fadeIn{from{opacity:.4}to{opacity:.95}}@keyframes fadeIn{from{opacity:.4}to{opacity:.95}}.cke_notification_success{background:#72b572;border:1px solid #63a563}.cke_notification_warning{background:#c83939;border:1px solid #902b2b}.cke_notification_info{background:#2e9ad0;border:1px solid #0f74a8}.cke_notification_info span.cke_notification_progress{background-color:#0f74a8;display:block;padding:0;margin:0;height:100%;overflow:hidden;position:absolute;z-index:1}.cke_notification_message{position:relative;margin:4px 23px 3px;font-family:Arial,Helvetica,sans-serif;font-size:12px;line-height:18px;z-index:4;text-overflow:ellipsis;overflow:hidden}.cke_notification_close{background-image:url(images/close.png);background-repeat:no-repeat;background-position:50%;position:absolute;cursor:pointer;text-align:center;height:20px;width:20px;top:1px;right:1px;padding:0;margin:0;z-index:5;opacity:.6;filter:alpha(opacity = 60)}.cke_notification_close:hover{opacity:1;filter:alpha(opacity = 100)}.cke_notification_close span{display:none}.cke_notification_warning a.cke_notification_close{opacity:.8;filter:alpha(opacity = 80)}.cke_notification_warning a.cke_notification_close:hover{opacity:1;filter:alpha(opacity = 100)}.cke_chrome{visibility:inherit}.cke_voice_label{display:none}legend.cke_voice_label{display:none}.cke_button__about_icon{background:url(icons.png?t=I648) no-repeat 0 -0px!important}.cke_button__bold_icon{background:url(icons.png?t=I648) no-repeat 0 -24px!important}.cke_button__italic_icon{background:url(icons.png?t=I648) no-repeat 0 -48px!important}.cke_button__strike_icon{background:url(icons.png?t=I648) no-repeat 0 -72px!important}.cke_button__subscript_icon{background:url(icons.png?t=I648) no-repeat 0 -96px!important}.cke_button__superscript_icon{background:url(icons.png?t=I648) no-repeat 0 -120px!important}.cke_button__underline_icon{background:url(icons.png?t=I648) no-repeat 0 -144px!important}.cke_button__blockquote_icon{background:url(icons.png?t=I648) no-repeat 0 -168px!important}.cke_rtl .cke_button__copy_icon,.cke_mixed_dir_content .cke_rtl .cke_button__copy_icon{background:url(icons.png?t=I648) no-repeat 0 -192px!important}.cke_ltr .cke_button__copy_icon{background:url(icons.png?t=I648) no-repeat 0 -216px!important}.cke_rtl .cke_button__cut_icon,.cke_mixed_dir_content .cke_rtl .cke_button__cut_icon{background:url(icons.png?t=I648) no-repeat 0 -240px!important}.cke_ltr .cke_button__cut_icon{background:url(icons.png?t=I648) no-repeat 0 -264px!important}.cke_rtl .cke_button__paste_icon,.cke_mixed_dir_content .cke_rtl .cke_button__paste_icon{background:url(icons.png?t=I648) no-repeat 0 -288px!important}.cke_ltr .cke_button__paste_icon{background:url(icons.png?t=I648) no-repeat 0 -312px!important}.cke_button__horizontalrule_icon{background:url(icons.png?t=I648) no-repeat 0 -336px!important}.cke_button__image_icon{background:url(icons.png?t=I648) no-repeat 0 -360px!important}.cke_rtl .cke_button__indent_icon,.cke_mixed_dir_content .cke_rtl .cke_button__indent_icon{background:url(icons.png?t=I648) no-repeat 0 -384px!important}.cke_ltr .cke_button__indent_icon{background:url(icons.png?t=I648) no-repeat 0 -408px!important}.cke_rtl .cke_button__outdent_icon,.cke_mixed_dir_content .cke_rtl .cke_button__outdent_icon{background:url(icons.png?t=I648) no-repeat 0 -432px!important}.cke_ltr .cke_button__outdent_icon{background:url(icons.png?t=I648) no-repeat 0 -456px!important}.cke_button__justifyblock_icon{background:url(icons.png?t=I648) no-repeat 0 -480px!important}.cke_button__justifycenter_icon{background:url(icons.png?t=I648) no-repeat 0 -504px!important}.cke_button__justifyleft_icon{background:url(icons.png?t=I648) no-repeat 0 -528px!important}.cke_button__justifyright_icon{background:url(icons.png?t=I648) no-repeat 0 -552px!important}.cke_button__language_icon{background:url(icons.png?t=I648) no-repeat 0 -576px!important}.cke_rtl .cke_button__bulletedlist_icon,.cke_mixed_dir_content .cke_rtl .cke_button__bulletedlist_icon{background:url(icons.png?t=I648) no-repeat 0 -600px!important}.cke_ltr .cke_button__bulletedlist_icon{background:url(icons.png?t=I648) no-repeat 0 -624px!important}.cke_rtl .cke_button__numberedlist_icon,.cke_mixed_dir_content .cke_rtl .cke_button__numberedlist_icon{background:url(icons.png?t=I648) no-repeat 0 -648px!important}.cke_ltr .cke_button__numberedlist_icon{background:url(icons.png?t=I648) no-repeat 0 -672px!important}.cke_button__maximize_icon{background:url(icons.png?t=I648) no-repeat 0 -696px!important}.cke_rtl .cke_button__pastefromword_icon,.cke_mixed_dir_content .cke_rtl .cke_button__pastefromword_icon{background:url(icons.png?t=I648) no-repeat 0 -720px!important}.cke_ltr .cke_button__pastefromword_icon{background:url(icons.png?t=I648) no-repeat 0 -744px!important}.cke_rtl .cke_button__pastetext_icon,.cke_mixed_dir_content .cke_rtl .cke_button__pastetext_icon{background:url(icons.png?t=I648) no-repeat 0 -768px!important}.cke_ltr .cke_button__pastetext_icon{background:url(icons.png?t=I648) no-repeat 0 -792px!important}.cke_button__removeformat_icon{background:url(icons.png?t=I648) no-repeat 0 -816px!important}.cke_rtl .cke_button__showblocks_icon,.cke_mixed_dir_content .cke_rtl .cke_button__showblocks_icon{background:url(icons.png?t=I648) no-repeat 0 -840px!important}.cke_ltr .cke_button__showblocks_icon{background:url(icons.png?t=I648) no-repeat 0 -864px!important}.cke_rtl .cke_button__source_icon,.cke_mixed_dir_content .cke_rtl .cke_button__source_icon{background:url(icons.png?t=I648) no-repeat 0 -888px!important}.cke_ltr .cke_button__source_icon{background:url(icons.png?t=I648) no-repeat 0 -912px!important}.cke_rtl .cke_button__sourcedialog_icon,.cke_mixed_dir_content .cke_rtl .cke_button__sourcedialog_icon{background:url(icons.png?t=I648) no-repeat 0 -936px!important}.cke_ltr .cke_button__sourcedialog_icon{background:url(icons.png?t=I648) no-repeat 0 -960px!important}.cke_button__specialchar_icon{background:url(icons.png?t=I648) no-repeat 0 -984px!important}.cke_button__table_icon{background:url(icons.png?t=I648) no-repeat 0 -1008px!important}.cke_rtl .cke_button__redo_icon,.cke_mixed_dir_content .cke_rtl .cke_button__redo_icon{background:url(icons.png?t=I648) no-repeat 0 -1032px!important}.cke_ltr .cke_button__redo_icon{background:url(icons.png?t=I648) no-repeat 0 -1056px!important}.cke_rtl .cke_button__undo_icon,.cke_mixed_dir_content .cke_rtl .cke_button__undo_icon{background:url(icons.png?t=I648) no-repeat 0 -1080px!important}.cke_ltr .cke_button__undo_icon{background:url(icons.png?t=I648) no-repeat 0 -1104px!important}.cke_button__simplebox_icon{background:url(icons.png?t=I648) no-repeat 0 -1128px!important}.cke_hidpi .cke_button__about_icon{background:url(icons_hidpi.png?t=I648) no-repeat 0 -0px!important;background-size:16px!important}.cke_hidpi .cke_button__bold_icon{background:url(icons_hidpi.png?t=I648) no-repeat 0 -24px!important;background-size:16px!important}.cke_hidpi .cke_button__italic_icon{background:url(icons_hidpi.png?t=I648) no-repeat 0 -48px!important;background-size:16px!important}.cke_hidpi .cke_button__strike_icon{background:url(icons_hidpi.png?t=I648) no-repeat 0 -72px!important;background-size:16px!important}.cke_hidpi .cke_button__subscript_icon{background:url(icons_hidpi.png?t=I648) no-repeat 0 -96px!important;background-size:16px!important}.cke_hidpi .cke_button__superscript_icon{background:url(icons_hidpi.png?t=I648) no-repeat 0 -120px!important;background-size:16px!important}.cke_hidpi .cke_button__underline_icon{background:url(icons_hidpi.png?t=I648) no-repeat 0 -144px!important;background-size:16px!important}.cke_hidpi .cke_button__blockquote_icon{background:url(icons_hidpi.png?t=I648) no-repeat 0 -168px!important;background-size:16px!important}.cke_rtl.cke_hidpi .cke_button__copy_icon,.cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__copy_icon{background:url(icons_hidpi.png?t=I648) no-repeat 0 -192px!important;background-size:16px!important}.cke_hidpi .cke_ltr .cke_button__copy_icon,.cke_ltr.cke_hidpi .cke_button__copy_icon{background:url(icons_hidpi.png?t=I648) no-repeat 0 -216px!important;background-size:16px!important}.cke_rtl.cke_hidpi .cke_button__cut_icon,.cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__cut_icon{background:url(icons_hidpi.png?t=I648) no-repeat 0 -240px!important;background-size:16px!important}.cke_hidpi .cke_ltr .cke_button__cut_icon,.cke_ltr.cke_hidpi .cke_button__cut_icon{background:url(icons_hidpi.png?t=I648) no-repeat 0 -264px!important;background-size:16px!important}.cke_rtl.cke_hidpi .cke_button__paste_icon,.cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__paste_icon{background:url(icons_hidpi.png?t=I648) no-repeat 0 -288px!important;background-size:16px!important}.cke_hidpi .cke_ltr .cke_button__paste_icon,.cke_ltr.cke_hidpi .cke_button__paste_icon{background:url(icons_hidpi.png?t=I648) no-repeat 0 -312px!important;background-size:16px!important}.cke_hidpi .cke_button__horizontalrule_icon{background:url(icons_hidpi.png?t=I648) no-repeat 0 -336px!important;background-size:16px!important}.cke_hidpi .cke_button__image_icon{background:url(icons_hidpi.png?t=I648) no-repeat 0 -360px!important;background-size:16px!important}.cke_rtl.cke_hidpi .cke_button__indent_icon,.cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__indent_icon{background:url(icons_hidpi.png?t=I648) no-repeat 0 -384px!important;background-size:16px!important}.cke_hidpi .cke_ltr .cke_button__indent_icon,.cke_ltr.cke_hidpi .cke_button__indent_icon{background:url(icons_hidpi.png?t=I648) no-repeat 0 -408px!important;background-size:16px!important}.cke_rtl.cke_hidpi .cke_button__outdent_icon,.cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__outdent_icon{background:url(icons_hidpi.png?t=I648) no-repeat 0 -432px!important;background-size:16px!important}.cke_hidpi .cke_ltr .cke_button__outdent_icon,.cke_ltr.cke_hidpi .cke_button__outdent_icon{background:url(icons_hidpi.png?t=I648) no-repeat 0 -456px!important;background-size:16px!important}.cke_hidpi .cke_button__justifyblock_icon{background:url(icons_hidpi.png?t=I648) no-repeat 0 -480px!important;background-size:16px!important}.cke_hidpi .cke_button__justifycenter_icon{background:url(icons_hidpi.png?t=I648) no-repeat 0 -504px!important;background-size:16px!important}.cke_hidpi .cke_button__justifyleft_icon{background:url(icons_hidpi.png?t=I648) no-repeat 0 -528px!important;background-size:16px!important}.cke_hidpi .cke_button__justifyright_icon{background:url(icons_hidpi.png?t=I648) no-repeat 0 -552px!important;background-size:16px!important}.cke_hidpi .cke_button__language_icon{background:url(icons_hidpi.png?t=I648) no-repeat 0 -576px!important;background-size:16px!important}.cke_rtl.cke_hidpi .cke_button__bulletedlist_icon,.cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__bulletedlist_icon{background:url(icons_hidpi.png?t=I648) no-repeat 0 -600px!important;background-size:16px!important}.cke_hidpi .cke_ltr .cke_button__bulletedlist_icon,.cke_ltr.cke_hidpi .cke_button__bulletedlist_icon{background:url(icons_hidpi.png?t=I648) no-repeat 0 -624px!important;background-size:16px!important}.cke_rtl.cke_hidpi .cke_button__numberedlist_icon,.cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__numberedlist_icon{background:url(icons_hidpi.png?t=I648) no-repeat 0 -648px!important;background-size:16px!important}.cke_hidpi .cke_ltr .cke_button__numberedlist_icon,.cke_ltr.cke_hidpi .cke_button__numberedlist_icon{background:url(icons_hidpi.png?t=I648) no-repeat 0 -672px!important;background-size:16px!important}.cke_hidpi .cke_button__maximize_icon{background:url(icons_hidpi.png?t=I648) no-repeat 0 -696px!important;background-size:16px!important}.cke_rtl.cke_hidpi .cke_button__pastefromword_icon,.cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__pastefromword_icon{background:url(icons_hidpi.png?t=I648) no-repeat 0 -720px!important;background-size:16px!important}.cke_hidpi .cke_ltr .cke_button__pastefromword_icon,.cke_ltr.cke_hidpi .cke_button__pastefromword_icon{background:url(icons_hidpi.png?t=I648) no-repeat 0 -744px!important;background-size:16px!important}.cke_rtl.cke_hidpi .cke_button__pastetext_icon,.cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__pastetext_icon{background:url(icons_hidpi.png?t=I648) no-repeat 0 -768px!important;background-size:16px!important}.cke_hidpi .cke_ltr .cke_button__pastetext_icon,.cke_ltr.cke_hidpi .cke_button__pastetext_icon{background:url(icons_hidpi.png?t=I648) no-repeat 0 -792px!important;background-size:16px!important}.cke_hidpi .cke_button__removeformat_icon{background:url(icons_hidpi.png?t=I648) no-repeat 0 -816px!important;background-size:16px!important}.cke_rtl.cke_hidpi .cke_button__showblocks_icon,.cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__showblocks_icon{background:url(icons_hidpi.png?t=I648) no-repeat 0 -840px!important;background-size:16px!important}.cke_hidpi .cke_ltr .cke_button__showblocks_icon,.cke_ltr.cke_hidpi .cke_button__showblocks_icon{background:url(icons_hidpi.png?t=I648) no-repeat 0 -864px!important;background-size:16px!important}.cke_rtl.cke_hidpi .cke_button__source_icon,.cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__source_icon{background:url(icons_hidpi.png?t=I648) no-repeat 0 -888px!important;background-size:16px!important}.cke_hidpi .cke_ltr .cke_button__source_icon,.cke_ltr.cke_hidpi .cke_button__source_icon{background:url(icons_hidpi.png?t=I648) no-repeat 0 -912px!important;background-size:16px!important}.cke_rtl.cke_hidpi .cke_button__sourcedialog_icon,.cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__sourcedialog_icon{background:url(icons_hidpi.png?t=I648) no-repeat 0 -936px!important;background-size:16px!important}.cke_hidpi .cke_ltr .cke_button__sourcedialog_icon,.cke_ltr.cke_hidpi .cke_button__sourcedialog_icon{background:url(icons_hidpi.png?t=I648) no-repeat 0 -960px!important;background-size:16px!important}.cke_hidpi .cke_button__specialchar_icon{background:url(icons_hidpi.png?t=I648) no-repeat 0 -984px!important;background-size:16px!important}.cke_hidpi .cke_button__table_icon{background:url(icons_hidpi.png?t=I648) no-repeat 0 -1008px!important;background-size:16px!important}.cke_rtl.cke_hidpi .cke_button__redo_icon,.cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__redo_icon{background:url(icons_hidpi.png?t=I648) no-repeat 0 -1032px!important;background-size:16px!important}.cke_hidpi .cke_ltr .cke_button__redo_icon,.cke_ltr.cke_hidpi .cke_button__redo_icon{background:url(icons_hidpi.png?t=I648) no-repeat 0 -1056px!important;background-size:16px!important}.cke_rtl.cke_hidpi .cke_button__undo_icon,.cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__undo_icon{background:url(icons_hidpi.png?t=I648) no-repeat 0 -1080px!important;background-size:16px!important}.cke_hidpi .cke_ltr .cke_button__undo_icon,.cke_ltr.cke_hidpi .cke_button__undo_icon{background:url(icons_hidpi.png?t=I648) no-repeat 0 -1104px!important;background-size:16px!important}.cke_hidpi .cke_button__simplebox_icon{background:url(icons_hidpi.png?t=I648) no-repeat 0 -2256px!important}a.cke_button_disabled,a.cke_button_disabled:hover,a.cke_button_disabled:focus,a.cke_button_disabled:active{filter:alpha(opacity = 30)}.cke_button_disabled .cke_button_icon{filter:progid:DXImageTransform.Microsoft.gradient(startColorstr=#00ffffff,endColorstr=#00ffffff)}.cke_button_off:hover,.cke_button_off:focus,.cke_button_off:active{filter:alpha(opacity = 100)}.cke_combo_disabled .cke_combo_inlinelabel,.cke_combo_disabled .cke_combo_open{filter:alpha(opacity = 30)}.cke_toolbox_collapser{border:1px solid #a6a6a6}.cke_toolbox_collapser .cke_arrow{margin-top:1px}.cke_hc .cke_top,.cke_hc .cke_bottom,.cke_hc .cke_combo_button,.cke_hc a.cke_combo_button:hover,.cke_hc a.cke_combo_button:focus,.cke_hc .cke_toolgroup,.cke_hc .cke_button_on,.cke_hc a.cke_button_off:hover,.cke_hc a.cke_button_off:focus,.cke_hc a.cke_button_off:active,.cke_hc .cke_toolbox_collapser,.cke_hc .cke_toolbox_collapser:hover,.cke_hc .cke_panel_grouptitle{filter:progid:DXImageTransform.Microsoft.gradient(enabled=false)} \ No newline at end of file +.cke_reset{margin:0;padding:0;border:0;background:transparent;text-decoration:none;width:auto;height:auto;vertical-align:baseline;box-sizing:content-box;position:static;transition:none}.cke_reset_all,.cke_reset_all *,.cke_reset_all a,.cke_reset_all textarea{margin:0;padding:0;border:0;background:transparent;text-decoration:none;width:auto;height:auto;vertical-align:baseline;box-sizing:content-box;position:static;transition:none;border-collapse:collapse;font:normal normal normal 12px Arial,Helvetica,Tahoma,Verdana,Sans-Serif;color:#000;text-align:left;white-space:nowrap;cursor:auto;float:none}.cke_reset_all .cke_rtl *{text-align:right}.cke_reset_all iframe{vertical-align:inherit}.cke_reset_all textarea{white-space:pre-wrap}.cke_reset_all textarea,.cke_reset_all input[type="text"],.cke_reset_all input[type="password"]{cursor:text}.cke_reset_all textarea[disabled],.cke_reset_all input[type="text"][disabled],.cke_reset_all input[type="password"][disabled]{cursor:default}.cke_reset_all fieldset{padding:10px;border:2px groove #e0dfe3}.cke_reset_all select{box-sizing:border-box}.cke_reset_all table{table-layout:auto}.cke_chrome{display:block;border:1px solid #d1d1d1;padding:0}.cke_inner{display:block;background:#fff;padding:0;-webkit-touch-callout:none}.cke_float{border:0}.cke_float .cke_inner{padding-bottom:0}.cke_top,.cke_contents,.cke_bottom{display:block;overflow:hidden}.cke_top{border-bottom:1px solid #d1d1d1;background:#f8f8f8;padding:6px 8px 2px;white-space:normal}.cke_float .cke_top{border:1px solid #d1d1d1}.cke_bottom{padding:6px 8px 2px;position:relative;border-top:1px solid #d1d1d1;background:#f8f8f8}.cke_browser_ios .cke_contents{overflow-y:auto;-webkit-overflow-scrolling:touch}.cke_resizer{width:0;height:0;overflow:hidden;border-width:10px 10px 0 0;border-color:transparent #bcbcbc transparent transparent;border-style:dashed solid dashed dashed;font-size:0;vertical-align:bottom;margin-top:6px;margin-bottom:2px}.cke_hc .cke_resizer{font-size:15px;width:auto;height:auto;border-width:0}.cke_resizer_ltr{cursor:se-resize;float:right;margin-right:-4px}.cke_resizer_rtl{border-width:10px 0 0 10px;border-color:transparent transparent transparent #bcbcbc;border-style:dashed dashed dashed solid;cursor:sw-resize;float:left;margin-left:-4px;right:auto}.cke_wysiwyg_div{display:block;height:100%;overflow:auto;padding:0 8px;outline-style:none;box-sizing:border-box}.cke_panel{visibility:visible;width:120px;height:100px;overflow:hidden;background-color:#fff;border:1px solid #d1d1d1}.cke_menu_panel{padding:0;margin:0}.cke_combopanel{width:150px;height:170px}.cke_panel_frame{width:100%;height:100%;font-size:12px;overflow:auto;overflow-x:hidden}.cke_panel_container{overflow-y:auto;overflow-x:hidden}.cke_panel_block:focus{outline:0}.cke_panel_list{margin:0;padding:0;list-style-type:none;white-space:nowrap}.cke_panel_listItem{margin:0;padding:0}.cke_panel_listItem a{padding:6px 7px;display:block;color:inherit!important;text-decoration:none;overflow:hidden;text-overflow:ellipsis}.cke_hc .cke_panel_listItem a{border-style:none}.cke_panel_listItem.cke_selected a,.cke_panel_listItem a:hover,.cke_panel_listItem a:focus,.cke_panel_listItem a:active{background-color:#e9e9e9}.cke_panel_listItem a:focus{outline:1px dotted #000}.cke_hc .cke_panel_listItem a:hover,.cke_hc .cke_panel_listItem a:focus,.cke_hc .cke_panel_listItem a:active{border:2px solid;padding:4px 5px}.cke_panel_listItem p,.cke_panel_listItem h1,.cke_panel_listItem h2,.cke_panel_listItem h3,.cke_panel_listItem h4,.cke_panel_listItem h5,.cke_panel_listItem h6,.cke_panel_listItem pre{margin-top:0;margin-bottom:0}.cke_panel_grouptitle{cursor:default;font-size:11px;font-weight:bold;white-space:nowrap;margin:0;padding:6px 6px 7px 6px;color:#484848;border-bottom:1px solid #d1d1d1;background:#f8f8f8}.cke_colorblock{padding:10px;font-size:11px;font-family:'Microsoft Sans Serif',Tahoma,Arial,Verdana,Sans-Serif}.cke_colorblock,.cke_colorblock a{text-decoration:none;color:#000}a.cke_colorbox{padding:2px;float:left;width:20px;height:20px}.cke_rtl a.cke_colorbox{float:right}a:hover.cke_colorbox,a:focus.cke_colorbox,a:active.cke_colorbox{outline:0;padding:0;border:2px solid #139ff7}a:hover.cke_colorbox{border-color:#bcbcbc}span.cke_colorbox{width:20px;height:20px;float:left}.cke_rtl span.cke_colorbox{float:right}a.cke_colorauto,a.cke_colormore{border:#fff 1px solid;padding:3px;display:block;cursor:pointer}a.cke_colorauto{padding:0;border:1px solid transparent;margin-bottom:6px;height:26px;line-height:26px}a.cke_colormore{margin-top:10px;height:20px;line-height:19px}a:hover.cke_colorauto,a:hover.cke_colormore,a:focus.cke_colorauto,a:focus.cke_colormore,a:active.cke_colorauto,a:active.cke_colormore{outline:0;border:#139ff7 1px solid;background-color:#f8f8f8}a:hover.cke_colorauto,a:hover.cke_colormore{border-color:#bcbcbc}.cke_colorauto span.cke_colorbox{width:18px;height:18px;border:1px solid #808080;margin-left:1px;margin-top:3px}.cke_rtl .cke_colorauto span.cke_colorbox{margin-left:0;margin-right:1px}span.cke_colorbox[style*="#ffffff"],span.cke_colorbox[style*="#FFFFFF"],span.cke_colorbox[style="background-color:#fff"],span.cke_colorbox[style="background-color:#FFF"],span.cke_colorbox[style*="rgb(255,255,255)"],span.cke_colorbox[style*="rgb(255, 255, 255)"]{border:1px solid #808080;width:18px;height:18px}.cke_toolbar{float:left}.cke_rtl .cke_toolbar{float:right}.cke_toolgroup{border:0;float:left;margin:1px 2px 6px 0;padding-right:3px}.cke_rtl .cke_toolgroup{float:right;margin:1px 0 6px 2px;padding-left:3px;padding-right:0}.cke_hc .cke_toolgroup{margin-right:5px;margin-bottom:5px}.cke_hc.cke_rtl .cke_toolgroup{margin-right:0;margin-left:5px}a.cke_button{display:inline-block;height:18px;padding:4px 6px;outline:0;cursor:default;float:left;border:0;position:relative}.cke_rtl a.cke_button{float:right}.cke_hc a.cke_button{border:1px solid black;padding:3px 5px;margin:0 3px 5px 0}.cke_hc.cke_rtl a.cke_button{margin:0 0 5px 3px}a.cke_button_on{background:#fff;border:1px #bcbcbc solid;padding:3px 5px}a.cke_button_off:hover,a.cke_button_off:focus,a.cke_button_off:active{background:#e5e5e5;border:1px #bcbcbc solid;padding:3px 5px}.cke_hc a.cke_button_on,.cke_hc a.cke_button_off:hover,.cke_hc a.cke_button_off:focus,.cke_hc a.cke_button_off:active{background:#e5e5e5;border:3px solid #000;padding:1px 3px}a.cke_button_disabled:hover,a.cke_button_disabled:focus,a.cke_button_disabled:active{border:0;padding:4px 6px;background-color:transparent}a.cke_button_disabled:focus{border:1px #bcbcbc solid;padding:3px 5px}.cke_hc a.cke_button_disabled:hover,.cke_hc a.cke_button_disabled:focus,.cke_hc a.cke_button_disabled:active{border:1px solid #acacac;padding:3px 5px;margin:0 3px 5px 0}.cke_hc a.cke_button_disabled:focus{border:3px solid #000;padding:1px 3px}.cke_hc.cke_rtl a.cke_button_disabled:hover,.cke_hc.cke_rtl a.cke_button_disabled:focus,.cke_hc.cke_rtl a.cke_button_disabled:active{margin:0 0 5px 3px}a.cke_button_disabled .cke_button_icon,a.cke_button_disabled .cke_button_arrow{opacity:.3}.cke_hc a.cke_button_disabled{border-color:#acacac}.cke_hc a.cke_button_disabled .cke_button_icon,.cke_hc a.cke_button_disabled .cke_button_label{opacity:.5}.cke_toolgroup a.cke_button:last-child:after,.cke_toolgroup a.cke_button.cke_button_disabled:hover:last-child:after{content:"";position:absolute;height:18px;width:0;border-right:1px solid #bcbcbc;margin-top:4px;top:0;right:-3px}.cke_rtl .cke_toolgroup a.cke_button:last-child:after,.cke_rtl .cke_toolgroup a.cke_button.cke_button_disabled:hover:last-child:after{border-right:0;right:auto;border-left:1px solid #bcbcbc;top:0;left:-3px}.cke_hc .cke_toolgroup a.cke_button:last-child:after,.cke_hc .cke_toolgroup a.cke_button.cke_button_disabled:last-child:after,.cke_hc .cke_toolgroup a.cke_button.cke_button_disabled:hover:last-child:after{border-color:#000;top:0;right:-7px}.cke_hc.cke_rtl .cke_toolgroup a.cke_button:last-child:after,.cke_hc.cke_rtl .cke_toolgroup a.cke_button.cke_button_disabled:last-child:after,.cke_hc.cke_rtl .cke_toolgroup a.cke_button.cke_button_disabled:hover:last-child:after{top:0;right:auto;left:-7px}.cke_toolgroup a.cke_button:hover:last-child:after,.cke_toolgroup a.cke_button.cke_button_on:last-child:after{top:-1px;right:-4px}.cke_rtl .cke_toolgroup a.cke_button:hover:last-child:after,.cke_rtl .cke_toolgroup a.cke_button.cke_button_on:last-child:after{top:-1px;right:auto;left:-4px}.cke_hc .cke_toolgroup a.cke_button:hover:last-child:after,.cke_hc .cke_toolgroup a.cke_button.cke_button_on:last-child:after{top:-2px;right:-9px}.cke_hc.cke_rtl .cke_toolgroup a.cke_button:hover:last-child:after,.cke_hc.cke_rtl .cke_toolgroup a.cke_button.cke_button_on:last-child:after{top:-2px;right:auto;left:-9px}.cke_toolbar.cke_toolbar_last .cke_toolgroup a.cke_button:last-child:after{content:none;border:0;width:0;height:0}.cke_button_icon{cursor:inherit;background-repeat:no-repeat;margin-top:1px;width:16px;height:16px;float:left;display:inline-block}.cke_rtl .cke_button_icon{float:right}.cke_hc .cke_button_icon{display:none}.cke_button_label{display:none;padding-left:3px;margin-top:1px;line-height:17px;vertical-align:middle;float:left;cursor:default;color:#484848}.cke_rtl .cke_button_label{padding-right:3px;padding-left:0;float:right}.cke_hc .cke_button_label{padding:0;display:inline-block;font-size:12px}.cke_button_arrow{display:inline-block;margin:8px 0 0 1px;width:0;height:0;cursor:default;vertical-align:top;border-left:3px solid transparent;border-right:3px solid transparent;border-top:3px solid #484848}.cke_rtl .cke_button_arrow{margin-right:5px;margin-left:0}.cke_hc .cke_button_arrow{font-size:10px;margin:3px 0 0 3px;width:auto;border:0}.cke_toolbar_separator{float:left;background-color:#bcbcbc;margin:4px 2px 0 2px;height:18px;width:1px}.cke_rtl .cke_toolbar_separator{float:right}.cke_hc .cke_toolbar_separator{background-color:#000;margin-left:2px;margin-right:5px;margin-bottom:9px}.cke_hc.cke_rtl .cke_toolbar_separator{margin-left:5px;margin-right:2px}.cke_toolbar_break{display:block;clear:left}.cke_rtl .cke_toolbar_break{clear:right}a.cke_toolbox_collapser{width:12px;height:11px;float:right;margin:11px 0 0;font-size:0;cursor:default;text-align:center;border:1px solid #bcbcbc}.cke_rtl .cke_toolbox_collapser{float:left}.cke_toolbox_collapser:hover{background:#e5e5e5}.cke_toolbox_collapser.cke_toolbox_collapser_min{margin:0 2px 4px}.cke_toolbox_collapser .cke_arrow{display:inline-block;height:0;width:0;font-size:0;margin-top:1px;border:3px solid transparent;border-bottom-color:#484848}.cke_toolbox_collapser.cke_toolbox_collapser_min .cke_arrow{margin-top:4px;border-bottom-color:transparent;border-top-color:#484848}.cke_hc .cke_toolbox_collapser .cke_arrow{font-size:8px;width:auto;border:0;margin-top:0}.cke_menuitem span{cursor:default}.cke_menubutton{display:block}.cke_hc .cke_menubutton{padding:2px}.cke_menubutton:hover,.cke_menubutton:focus,.cke_menubutton:active{background-color:#e9e9e9;display:block;outline:1px dotted}.cke_menubutton:hover{outline:0}.cke_hc .cke_menubutton:hover,.cke_hc .cke_menubutton:focus,.cke_hc .cke_menubutton:active{border:2px solid;padding:0}.cke_menubutton_disabled:hover,.cke_menubutton_disabled:focus,.cke_menubutton_disabled:active{background-color:transparent;outline:0}.cke_menubutton_inner{display:table-row}.cke_menubutton_icon,.cke_menubutton_label,.cke_menuarrow{display:table-cell}.cke_menubutton_icon{background-color:#f8f8f8;padding:6px 4px}.cke_hc .cke_menubutton_icon{height:16px;width:0;padding:4px 0}.cke_menubutton:hover .cke_menubutton_icon,.cke_menubutton:focus .cke_menubutton_icon,.cke_menubutton:active .cke_menubutton_icon{background-color:#e9e9e9}.cke_menubutton_disabled:hover .cke_menubutton_icon,.cke_menubutton_disabled:focus .cke_menubutton_icon,.cke_menubutton_disabled:active .cke_menubutton_icon{background-color:#f8f8f8;outline:0}.cke_menuitem .cke_menubutton_on{background-color:#e9e9e9;border:1px solid #dedede;outline:0}.cke_menubutton_on .cke_menubutton_icon{padding-right:3px;background-color:#e9e9e9}.cke_menubutton_label{padding:0 5px;background-color:transparent;width:100%;vertical-align:middle}.cke_menubutton_shortcut{color:#979797}.cke_menubutton_disabled .cke_menubutton_label{opacity:.3;filter:alpha(opacity=30)}.cke_panel_frame .cke_menubutton_label{display:none}.cke_menuseparator{background-color:#d1d1d1;height:1px}.cke_menuarrow{background:transparent url(images/arrow.png) no-repeat 0 10px;padding:0 5px}.cke_rtl .cke_menuarrow{background-position:5px -13px;background-repeat:no-repeat}.cke_hc .cke_menuarrow{background-image:none}.cke_menuarrow span{display:none}.cke_hc .cke_menuarrow span{vertical-align:middle;display:inline}.cke_combo{display:inline-block;float:left;position:relative;margin-bottom:5px}.cke_rtl .cke_combo{float:right}.cke_hc .cke_combo{margin-top:1px;margin-bottom:10px}.cke_combo:after{content:"";position:absolute;height:18px;width:0;border-right:1px solid #bcbcbc;margin-top:5px;top:0;right:0}.cke_rtl .cke_combo:after{border-right:0;border-left:1px solid #bcbcbc;right:auto;left:0}.cke_hc .cke_combo:after{border-color:#000}a.cke_combo_button{cursor:default;display:inline-block;float:left;margin:0;padding:1px}.cke_rtl a.cke_combo_button{float:right}.cke_hc a.cke_combo_button{padding:4px}.cke_combo_on a.cke_combo_button,.cke_combo_off a.cke_combo_button:hover,.cke_combo_off a.cke_combo_button:focus,.cke_combo_off a.cke_combo_button:active{background:#e5e5e5;border:1px solid #bcbcbc;padding:0 0 0 1px;margin-left:-1px}.cke_combo_off a.cke_combo_button:focus{outline:0}.cke_combo_on a.cke_combo_button,.cke_combo_off a.cke_combo_button:active{background:#fff}.cke_rtl .cke_combo_on a.cke_combo_button,.cke_rtl .cke_combo_off a.cke_combo_button:hover,.cke_rtl .cke_combo_off a.cke_combo_button:focus,.cke_rtl .cke_combo_off a.cke_combo_button:active{padding:0 1px 0 0;margin-left:0;margin-right:-1px}.cke_hc .cke_combo_on a.cke_combo_button,.cke_hc .cke_combo_off a.cke_combo_button:hover,.cke_hc .cke_combo_off a.cke_combo_button:focus,.cke_hc .cke_combo_off a.cke_combo_button:active{border:3px solid #000;padding:1px 1px 1px 2px}.cke_hc.cke_rtl .cke_combo_on a.cke_combo_button,.cke_hc.cke_rtl .cke_combo_off a.cke_combo_button:hover,.cke_hc.cke_rtl .cke_combo_off a.cke_combo_button:focus,.cke_hc.cke_rtl .cke_combo_off a.cke_combo_button:active{padding:1px 2px 1px 1px}.cke_toolbar_start+.cke_combo_on a.cke_combo_button,.cke_toolbar_start+.cke_combo_off a.cke_combo_button:hover,.cke_toolbar_start+.cke_combo_off a.cke_combo_button:focus,.cke_toolbar_start+.cke_combo_off a.cke_combo_button:active{padding:0 0 0 3px;margin-left:-3px}.cke_rtl .cke_toolbar_start+.cke_combo_on a.cke_combo_button,.cke_rtl .cke_toolbar_start+.cke_combo_off a.cke_combo_button:hover,.cke_rtl .cke_toolbar_start+.cke_combo_off a.cke_combo_button:focus,.cke_rtl .cke_toolbar_start+.cke_combo_off a.cke_combo_button:active{padding:0 3px 0 0;margin-left:0;margin-right:-3px}.cke_hc .cke_toolbar>.cke_toolbar_start+.cke_combo_on a.cke_combo_button,.cke_hc .cke_toolbar>.cke_toolbar_start+.cke_combo_off a.cke_combo_button:hover,.cke_hc .cke_toolbar>.cke_toolbar_start+.cke_combo_off a.cke_combo_button:focus,.cke_hc .cke_toolbar>.cke_toolbar_start+.cke_combo_off a.cke_combo_button:active{padding:1px 1px 1px 7px;margin-left:-6px}.cke_hc.cke_rtl .cke_toolbar>.cke_toolbar_start+.cke_combo_on a.cke_combo_button,.cke_hc.cke_rtl .cke_toolbar>.cke_toolbar_start+.cke_combo_off a.cke_combo_button:hover,.cke_hc.cke_rtl .cke_toolbar>.cke_toolbar_start+.cke_combo_off a.cke_combo_button:focus,.cke_hc.cke_rtl .cke_toolbar>.cke_toolbar_start+.cke_combo_off a.cke_combo_button:active{padding:1px 7px 1px 1px;margin-left:0;margin-right:-6px}.cke_toolbox .cke_toolbar:first-child>.cke_toolbar_start+.cke_combo_on a.cke_combo_button,.cke_toolbox .cke_toolbar:first-child>.cke_toolbar_start+.cke_combo_off a.cke_combo_button:hover,.cke_toolbox .cke_toolbar:first-child>.cke_toolbar_start+.cke_combo_off a.cke_combo_button:focus,.cke_toolbox .cke_toolbar:first-child>.cke_toolbar_start+.cke_combo_off a.cke_combo_button:active,.cke_toolbar_break+.cke_toolbar>.cke_toolbar_start+.cke_combo_on a.cke_combo_button,.cke_toolbar_break+.cke_toolbar>.cke_toolbar_start+.cke_combo_off a.cke_combo_button:hover,.cke_toolbar_break+.cke_toolbar>.cke_toolbar_start+.cke_combo_off a.cke_combo_button:focus,.cke_toolbar_break+.cke_toolbar>.cke_toolbar_start+.cke_combo_off a.cke_combo_button:active{padding:0;margin:0}.cke_hc .cke_toolbox .cke_toolbar:first-child>.cke_toolbar_start+.cke_combo_on a.cke_combo_button,.cke_hc .cke_toolbox .cke_toolbar:first-child>.cke_toolbar_start+.cke_combo_off a.cke_combo_button:hover,.cke_hc .cke_toolbox .cke_toolbar:first-child>.cke_toolbar_start+.cke_combo_off a.cke_combo_button:focus,.cke_hc .cke_toolbox .cke_toolbar:first-child>.cke_toolbar_start+.cke_combo_off a.cke_combo_button:active,.cke_hc .cke_toolbar_break+.cke_toolbar>.cke_toolbar_start+.cke_combo_on a.cke_combo_button,.cke_hc .cke_toolbar_break+.cke_toolbar>.cke_toolbar_start+.cke_combo_off a.cke_combo_button:hover,.cke_hc .cke_toolbar_break+.cke_toolbar>.cke_toolbar_start+.cke_combo_off a.cke_combo_button:focus,.cke_hc .cke_toolbar_break+.cke_toolbar>.cke_toolbar_start+.cke_combo_off a.cke_combo_button:active{padding:1px;margin:0}.cke_toolbar .cke_combo+.cke_toolbar_end,.cke_toolbar .cke_combo+.cke_toolgroup{margin-right:0;margin-left:2px}.cke_rtl .cke_toolbar .cke_combo+.cke_toolbar_end,.cke_rtl .cke_toolbar .cke_combo+.cke_toolgroup{margin-left:0;margin-right:2px}.cke_hc .cke_toolbar .cke_combo+.cke_toolbar_end,.cke_hc .cke_toolbar .cke_combo+.cke_toolgroup{margin-left:5px}.cke_hc.cke_rtl .cke_toolbar .cke_combo+.cke_toolbar_end,.cke_hc.cke_rtl .cke_toolbar .cke_combo+.cke_toolgroup{margin-left:0;margin-right:5px}.cke_toolbar.cke_toolbar_last .cke_combo:nth-last-child(-n+2):after{content:none;border:0;width:0;height:0}.cke_combo_text{line-height:26px;padding-left:10px;text-overflow:ellipsis;overflow:hidden;float:left;cursor:default;color:#484848;width:60px}.cke_rtl .cke_combo_text{float:right;text-align:right;padding-left:0;padding-right:10px}.cke_hc .cke_combo_text{line-height:18px;font-size:12px}.cke_combo_open{cursor:default;display:inline-block;font-size:0;height:19px;line-height:17px;margin:1px 10px 1px;width:5px}.cke_hc .cke_combo_open{height:12px}.cke_combo_arrow{cursor:default;margin:11px 0 0;float:left;height:0;width:0;font-size:0;border-left:3px solid transparent;border-right:3px solid transparent;border-top:3px solid #484848}.cke_hc .cke_combo_arrow{font-size:10px;width:auto;border:0;margin-top:3px}.cke_combo_label{display:none;float:left;line-height:26px;vertical-align:top;margin-right:5px}.cke_rtl .cke_combo_label{float:right;margin-left:5px;margin-right:0}.cke_combo_disabled .cke_combo_inlinelabel,.cke_combo_disabled .cke_combo_open{opacity:.3}.cke_path{float:left;margin:-2px 0 2px}a.cke_path_item,span.cke_path_empty{display:inline-block;float:left;padding:3px 4px;margin-right:2px;cursor:default;text-decoration:none;outline:0;border:0;color:#484848;font-weight:bold;font-size:11px}.cke_rtl .cke_path,.cke_rtl .cke_path_item,.cke_rtl .cke_path_empty{float:right}a.cke_path_item:hover,a.cke_path_item:focus,a.cke_path_item:active{background-color:#e5e5e5}.cke_hc a.cke_path_item:hover,.cke_hc a.cke_path_item:focus,.cke_hc a.cke_path_item:active{border:2px solid;padding:1px 2px}.cke_button__source_label,.cke_button__sourcedialog_label{display:inline}.cke_combopanel__fontsize{width:135px}textarea.cke_source{font-family:'Courier New',Monospace;font-size:small;background-color:#fff;white-space:pre-wrap;border:0;padding:0;margin:0;display:block}.cke_wysiwyg_frame,.cke_wysiwyg_div{background-color:#fff}.cke_notifications_area{pointer-events:none}.cke_notification{pointer-events:auto;position:relative;margin:10px;width:300px;color:white;text-align:center;opacity:.95;filter:alpha(opacity = 95);-webkit-animation:fadeIn .7s;animation:fadeIn .7s}.cke_notification_message a{color:#12306f}@-webkit-keyframes fadeIn{from{opacity:.4}to{opacity:.95}}@keyframes fadeIn{from{opacity:.4}to{opacity:.95}}.cke_notification_success{background:#72b572;border:1px solid #63a563}.cke_notification_warning{background:#c83939;border:1px solid #902b2b}.cke_notification_info{background:#2e9ad0;border:1px solid #0f74a8}.cke_notification_info span.cke_notification_progress{background-color:#0f74a8;display:block;padding:0;margin:0;height:100%;overflow:hidden;position:absolute;z-index:1}.cke_notification_message{position:relative;margin:4px 23px 3px;font-family:Arial,Helvetica,sans-serif;font-size:12px;line-height:18px;z-index:4;text-overflow:ellipsis;overflow:hidden}.cke_notification_close{background-image:url(images/close.png);background-repeat:no-repeat;background-position:50%;position:absolute;cursor:pointer;text-align:center;height:20px;width:20px;top:1px;right:1px;padding:0;margin:0;z-index:5;opacity:.6;filter:alpha(opacity = 60)}.cke_notification_close:hover{opacity:1;filter:alpha(opacity = 100)}.cke_notification_close span{display:none}.cke_notification_warning a.cke_notification_close{opacity:.8;filter:alpha(opacity = 80)}.cke_notification_warning a.cke_notification_close:hover{opacity:1;filter:alpha(opacity = 100)}.cke_chrome{visibility:inherit}.cke_voice_label{display:none}legend.cke_voice_label{display:none}.cke_button__about_icon{background:url(icons.png?t=I8E8) no-repeat 0 -0px!important}.cke_button__bold_icon{background:url(icons.png?t=I8E8) no-repeat 0 -24px!important}.cke_button__italic_icon{background:url(icons.png?t=I8E8) no-repeat 0 -48px!important}.cke_button__strike_icon{background:url(icons.png?t=I8E8) no-repeat 0 -72px!important}.cke_button__subscript_icon{background:url(icons.png?t=I8E8) no-repeat 0 -96px!important}.cke_button__superscript_icon{background:url(icons.png?t=I8E8) no-repeat 0 -120px!important}.cke_button__underline_icon{background:url(icons.png?t=I8E8) no-repeat 0 -144px!important}.cke_button__blockquote_icon{background:url(icons.png?t=I8E8) no-repeat 0 -168px!important}.cke_rtl .cke_button__copy_icon,.cke_mixed_dir_content .cke_rtl .cke_button__copy_icon{background:url(icons.png?t=I8E8) no-repeat 0 -192px!important}.cke_ltr .cke_button__copy_icon{background:url(icons.png?t=I8E8) no-repeat 0 -216px!important}.cke_rtl .cke_button__cut_icon,.cke_mixed_dir_content .cke_rtl .cke_button__cut_icon{background:url(icons.png?t=I8E8) no-repeat 0 -240px!important}.cke_ltr .cke_button__cut_icon{background:url(icons.png?t=I8E8) no-repeat 0 -264px!important}.cke_rtl .cke_button__paste_icon,.cke_mixed_dir_content .cke_rtl .cke_button__paste_icon{background:url(icons.png?t=I8E8) no-repeat 0 -288px!important}.cke_ltr .cke_button__paste_icon{background:url(icons.png?t=I8E8) no-repeat 0 -312px!important}.cke_button__horizontalrule_icon{background:url(icons.png?t=I8E8) no-repeat 0 -336px!important}.cke_button__image_icon{background:url(icons.png?t=I8E8) no-repeat 0 -360px!important}.cke_rtl .cke_button__indent_icon,.cke_mixed_dir_content .cke_rtl .cke_button__indent_icon{background:url(icons.png?t=I8E8) no-repeat 0 -384px!important}.cke_ltr .cke_button__indent_icon{background:url(icons.png?t=I8E8) no-repeat 0 -408px!important}.cke_rtl .cke_button__outdent_icon,.cke_mixed_dir_content .cke_rtl .cke_button__outdent_icon{background:url(icons.png?t=I8E8) no-repeat 0 -432px!important}.cke_ltr .cke_button__outdent_icon{background:url(icons.png?t=I8E8) no-repeat 0 -456px!important}.cke_button__justifyblock_icon{background:url(icons.png?t=I8E8) no-repeat 0 -480px!important}.cke_button__justifycenter_icon{background:url(icons.png?t=I8E8) no-repeat 0 -504px!important}.cke_button__justifyleft_icon{background:url(icons.png?t=I8E8) no-repeat 0 -528px!important}.cke_button__justifyright_icon{background:url(icons.png?t=I8E8) no-repeat 0 -552px!important}.cke_button__language_icon{background:url(icons.png?t=I8E8) no-repeat 0 -576px!important}.cke_rtl .cke_button__bulletedlist_icon,.cke_mixed_dir_content .cke_rtl .cke_button__bulletedlist_icon{background:url(icons.png?t=I8E8) no-repeat 0 -600px!important}.cke_ltr .cke_button__bulletedlist_icon{background:url(icons.png?t=I8E8) no-repeat 0 -624px!important}.cke_rtl .cke_button__numberedlist_icon,.cke_mixed_dir_content .cke_rtl .cke_button__numberedlist_icon{background:url(icons.png?t=I8E8) no-repeat 0 -648px!important}.cke_ltr .cke_button__numberedlist_icon{background:url(icons.png?t=I8E8) no-repeat 0 -672px!important}.cke_button__maximize_icon{background:url(icons.png?t=I8E8) no-repeat 0 -696px!important}.cke_rtl .cke_button__pastefromword_icon,.cke_mixed_dir_content .cke_rtl .cke_button__pastefromword_icon{background:url(icons.png?t=I8E8) no-repeat 0 -720px!important}.cke_ltr .cke_button__pastefromword_icon{background:url(icons.png?t=I8E8) no-repeat 0 -744px!important}.cke_rtl .cke_button__pastetext_icon,.cke_mixed_dir_content .cke_rtl .cke_button__pastetext_icon{background:url(icons.png?t=I8E8) no-repeat 0 -768px!important}.cke_ltr .cke_button__pastetext_icon{background:url(icons.png?t=I8E8) no-repeat 0 -792px!important}.cke_button__removeformat_icon{background:url(icons.png?t=I8E8) no-repeat 0 -816px!important}.cke_rtl .cke_button__showblocks_icon,.cke_mixed_dir_content .cke_rtl .cke_button__showblocks_icon{background:url(icons.png?t=I8E8) no-repeat 0 -840px!important}.cke_ltr .cke_button__showblocks_icon{background:url(icons.png?t=I8E8) no-repeat 0 -864px!important}.cke_rtl .cke_button__source_icon,.cke_mixed_dir_content .cke_rtl .cke_button__source_icon{background:url(icons.png?t=I8E8) no-repeat 0 -888px!important}.cke_ltr .cke_button__source_icon{background:url(icons.png?t=I8E8) no-repeat 0 -912px!important}.cke_rtl .cke_button__sourcedialog_icon,.cke_mixed_dir_content .cke_rtl .cke_button__sourcedialog_icon{background:url(icons.png?t=I8E8) no-repeat 0 -936px!important}.cke_ltr .cke_button__sourcedialog_icon{background:url(icons.png?t=I8E8) no-repeat 0 -960px!important}.cke_button__specialchar_icon{background:url(icons.png?t=I8E8) no-repeat 0 -984px!important}.cke_button__table_icon{background:url(icons.png?t=I8E8) no-repeat 0 -1008px!important}.cke_rtl .cke_button__redo_icon,.cke_mixed_dir_content .cke_rtl .cke_button__redo_icon{background:url(icons.png?t=I8E8) no-repeat 0 -1032px!important}.cke_ltr .cke_button__redo_icon{background:url(icons.png?t=I8E8) no-repeat 0 -1056px!important}.cke_rtl .cke_button__undo_icon,.cke_mixed_dir_content .cke_rtl .cke_button__undo_icon{background:url(icons.png?t=I8E8) no-repeat 0 -1080px!important}.cke_ltr .cke_button__undo_icon{background:url(icons.png?t=I8E8) no-repeat 0 -1104px!important}.cke_button__simplebox_icon{background:url(icons.png?t=I8E8) no-repeat 0 -1128px!important}.cke_hidpi .cke_button__about_icon{background:url(icons_hidpi.png?t=I8E8) no-repeat 0 -0px!important;background-size:16px!important}.cke_hidpi .cke_button__bold_icon{background:url(icons_hidpi.png?t=I8E8) no-repeat 0 -24px!important;background-size:16px!important}.cke_hidpi .cke_button__italic_icon{background:url(icons_hidpi.png?t=I8E8) no-repeat 0 -48px!important;background-size:16px!important}.cke_hidpi .cke_button__strike_icon{background:url(icons_hidpi.png?t=I8E8) no-repeat 0 -72px!important;background-size:16px!important}.cke_hidpi .cke_button__subscript_icon{background:url(icons_hidpi.png?t=I8E8) no-repeat 0 -96px!important;background-size:16px!important}.cke_hidpi .cke_button__superscript_icon{background:url(icons_hidpi.png?t=I8E8) no-repeat 0 -120px!important;background-size:16px!important}.cke_hidpi .cke_button__underline_icon{background:url(icons_hidpi.png?t=I8E8) no-repeat 0 -144px!important;background-size:16px!important}.cke_hidpi .cke_button__blockquote_icon{background:url(icons_hidpi.png?t=I8E8) no-repeat 0 -168px!important;background-size:16px!important}.cke_rtl.cke_hidpi .cke_button__copy_icon,.cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__copy_icon{background:url(icons_hidpi.png?t=I8E8) no-repeat 0 -192px!important;background-size:16px!important}.cke_hidpi .cke_ltr .cke_button__copy_icon,.cke_ltr.cke_hidpi .cke_button__copy_icon{background:url(icons_hidpi.png?t=I8E8) no-repeat 0 -216px!important;background-size:16px!important}.cke_rtl.cke_hidpi .cke_button__cut_icon,.cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__cut_icon{background:url(icons_hidpi.png?t=I8E8) no-repeat 0 -240px!important;background-size:16px!important}.cke_hidpi .cke_ltr .cke_button__cut_icon,.cke_ltr.cke_hidpi .cke_button__cut_icon{background:url(icons_hidpi.png?t=I8E8) no-repeat 0 -264px!important;background-size:16px!important}.cke_rtl.cke_hidpi .cke_button__paste_icon,.cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__paste_icon{background:url(icons_hidpi.png?t=I8E8) no-repeat 0 -288px!important;background-size:16px!important}.cke_hidpi .cke_ltr .cke_button__paste_icon,.cke_ltr.cke_hidpi .cke_button__paste_icon{background:url(icons_hidpi.png?t=I8E8) no-repeat 0 -312px!important;background-size:16px!important}.cke_hidpi .cke_button__horizontalrule_icon{background:url(icons_hidpi.png?t=I8E8) no-repeat 0 -336px!important;background-size:16px!important}.cke_hidpi .cke_button__image_icon{background:url(icons_hidpi.png?t=I8E8) no-repeat 0 -360px!important;background-size:16px!important}.cke_rtl.cke_hidpi .cke_button__indent_icon,.cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__indent_icon{background:url(icons_hidpi.png?t=I8E8) no-repeat 0 -384px!important;background-size:16px!important}.cke_hidpi .cke_ltr .cke_button__indent_icon,.cke_ltr.cke_hidpi .cke_button__indent_icon{background:url(icons_hidpi.png?t=I8E8) no-repeat 0 -408px!important;background-size:16px!important}.cke_rtl.cke_hidpi .cke_button__outdent_icon,.cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__outdent_icon{background:url(icons_hidpi.png?t=I8E8) no-repeat 0 -432px!important;background-size:16px!important}.cke_hidpi .cke_ltr .cke_button__outdent_icon,.cke_ltr.cke_hidpi .cke_button__outdent_icon{background:url(icons_hidpi.png?t=I8E8) no-repeat 0 -456px!important;background-size:16px!important}.cke_hidpi .cke_button__justifyblock_icon{background:url(icons_hidpi.png?t=I8E8) no-repeat 0 -480px!important;background-size:16px!important}.cke_hidpi .cke_button__justifycenter_icon{background:url(icons_hidpi.png?t=I8E8) no-repeat 0 -504px!important;background-size:16px!important}.cke_hidpi .cke_button__justifyleft_icon{background:url(icons_hidpi.png?t=I8E8) no-repeat 0 -528px!important;background-size:16px!important}.cke_hidpi .cke_button__justifyright_icon{background:url(icons_hidpi.png?t=I8E8) no-repeat 0 -552px!important;background-size:16px!important}.cke_hidpi .cke_button__language_icon{background:url(icons_hidpi.png?t=I8E8) no-repeat 0 -576px!important;background-size:16px!important}.cke_rtl.cke_hidpi .cke_button__bulletedlist_icon,.cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__bulletedlist_icon{background:url(icons_hidpi.png?t=I8E8) no-repeat 0 -600px!important;background-size:16px!important}.cke_hidpi .cke_ltr .cke_button__bulletedlist_icon,.cke_ltr.cke_hidpi .cke_button__bulletedlist_icon{background:url(icons_hidpi.png?t=I8E8) no-repeat 0 -624px!important;background-size:16px!important}.cke_rtl.cke_hidpi .cke_button__numberedlist_icon,.cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__numberedlist_icon{background:url(icons_hidpi.png?t=I8E8) no-repeat 0 -648px!important;background-size:16px!important}.cke_hidpi .cke_ltr .cke_button__numberedlist_icon,.cke_ltr.cke_hidpi .cke_button__numberedlist_icon{background:url(icons_hidpi.png?t=I8E8) no-repeat 0 -672px!important;background-size:16px!important}.cke_hidpi .cke_button__maximize_icon{background:url(icons_hidpi.png?t=I8E8) no-repeat 0 -696px!important;background-size:16px!important}.cke_rtl.cke_hidpi .cke_button__pastefromword_icon,.cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__pastefromword_icon{background:url(icons_hidpi.png?t=I8E8) no-repeat 0 -720px!important;background-size:16px!important}.cke_hidpi .cke_ltr .cke_button__pastefromword_icon,.cke_ltr.cke_hidpi .cke_button__pastefromword_icon{background:url(icons_hidpi.png?t=I8E8) no-repeat 0 -744px!important;background-size:16px!important}.cke_rtl.cke_hidpi .cke_button__pastetext_icon,.cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__pastetext_icon{background:url(icons_hidpi.png?t=I8E8) no-repeat 0 -768px!important;background-size:16px!important}.cke_hidpi .cke_ltr .cke_button__pastetext_icon,.cke_ltr.cke_hidpi .cke_button__pastetext_icon{background:url(icons_hidpi.png?t=I8E8) no-repeat 0 -792px!important;background-size:16px!important}.cke_hidpi .cke_button__removeformat_icon{background:url(icons_hidpi.png?t=I8E8) no-repeat 0 -816px!important;background-size:16px!important}.cke_rtl.cke_hidpi .cke_button__showblocks_icon,.cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__showblocks_icon{background:url(icons_hidpi.png?t=I8E8) no-repeat 0 -840px!important;background-size:16px!important}.cke_hidpi .cke_ltr .cke_button__showblocks_icon,.cke_ltr.cke_hidpi .cke_button__showblocks_icon{background:url(icons_hidpi.png?t=I8E8) no-repeat 0 -864px!important;background-size:16px!important}.cke_rtl.cke_hidpi .cke_button__source_icon,.cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__source_icon{background:url(icons_hidpi.png?t=I8E8) no-repeat 0 -888px!important;background-size:16px!important}.cke_hidpi .cke_ltr .cke_button__source_icon,.cke_ltr.cke_hidpi .cke_button__source_icon{background:url(icons_hidpi.png?t=I8E8) no-repeat 0 -912px!important;background-size:16px!important}.cke_rtl.cke_hidpi .cke_button__sourcedialog_icon,.cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__sourcedialog_icon{background:url(icons_hidpi.png?t=I8E8) no-repeat 0 -936px!important;background-size:16px!important}.cke_hidpi .cke_ltr .cke_button__sourcedialog_icon,.cke_ltr.cke_hidpi .cke_button__sourcedialog_icon{background:url(icons_hidpi.png?t=I8E8) no-repeat 0 -960px!important;background-size:16px!important}.cke_hidpi .cke_button__specialchar_icon{background:url(icons_hidpi.png?t=I8E8) no-repeat 0 -984px!important;background-size:16px!important}.cke_hidpi .cke_button__table_icon{background:url(icons_hidpi.png?t=I8E8) no-repeat 0 -1008px!important;background-size:16px!important}.cke_rtl.cke_hidpi .cke_button__redo_icon,.cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__redo_icon{background:url(icons_hidpi.png?t=I8E8) no-repeat 0 -1032px!important;background-size:16px!important}.cke_hidpi .cke_ltr .cke_button__redo_icon,.cke_ltr.cke_hidpi .cke_button__redo_icon{background:url(icons_hidpi.png?t=I8E8) no-repeat 0 -1056px!important;background-size:16px!important}.cke_rtl.cke_hidpi .cke_button__undo_icon,.cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__undo_icon{background:url(icons_hidpi.png?t=I8E8) no-repeat 0 -1080px!important;background-size:16px!important}.cke_hidpi .cke_ltr .cke_button__undo_icon,.cke_ltr.cke_hidpi .cke_button__undo_icon{background:url(icons_hidpi.png?t=I8E8) no-repeat 0 -1104px!important;background-size:16px!important}.cke_hidpi .cke_button__simplebox_icon{background:url(icons_hidpi.png?t=I8E8) no-repeat 0 -2256px!important}a.cke_button_disabled,a.cke_button_disabled:hover,a.cke_button_disabled:focus,a.cke_button_disabled:active{filter:alpha(opacity = 30)}.cke_button_disabled .cke_button_icon{filter:progid:DXImageTransform.Microsoft.gradient(startColorstr=#00ffffff,endColorstr=#00ffffff)}.cke_button_off:hover,.cke_button_off:focus,.cke_button_off:active{filter:alpha(opacity = 100)}.cke_combo_disabled .cke_combo_inlinelabel,.cke_combo_disabled .cke_combo_open{filter:alpha(opacity = 30)}.cke_toolbox_collapser{border:1px solid #a6a6a6}.cke_toolbox_collapser .cke_arrow{margin-top:1px}.cke_hc .cke_top,.cke_hc .cke_bottom,.cke_hc .cke_combo_button,.cke_hc a.cke_combo_button:hover,.cke_hc a.cke_combo_button:focus,.cke_hc .cke_toolgroup,.cke_hc .cke_button_on,.cke_hc a.cke_button_off:hover,.cke_hc a.cke_button_off:focus,.cke_hc a.cke_button_off:active,.cke_hc .cke_toolbox_collapser,.cke_hc .cke_toolbox_collapser:hover,.cke_hc .cke_panel_grouptitle{filter:progid:DXImageTransform.Microsoft.gradient(enabled=false)} \ No newline at end of file diff --git a/web/core/assets/vendor/ckeditor/skins/moono-lisa/editor_ie8.css b/web/core/assets/vendor/ckeditor/skins/moono-lisa/editor_ie8.css index a048282520f04519a367115ef93f37e13c5c06a6..c69af6be2acb9c4d164d0df127d5ea5347557261 100644 --- a/web/core/assets/vendor/ckeditor/skins/moono-lisa/editor_ie8.css +++ b/web/core/assets/vendor/ckeditor/skins/moono-lisa/editor_ie8.css @@ -2,4 +2,4 @@ Copyright (c) 2003-2018, CKSource - Frederico Knabben. All rights reserved. For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license */ -.cke_reset{margin:0;padding:0;border:0;background:transparent;text-decoration:none;width:auto;height:auto;vertical-align:baseline;box-sizing:content-box;position:static;transition:none}.cke_reset_all,.cke_reset_all *,.cke_reset_all a,.cke_reset_all textarea{margin:0;padding:0;border:0;background:transparent;text-decoration:none;width:auto;height:auto;vertical-align:baseline;box-sizing:content-box;position:static;transition:none;border-collapse:collapse;font:normal normal normal 12px Arial,Helvetica,Tahoma,Verdana,Sans-Serif;color:#000;text-align:left;white-space:nowrap;cursor:auto;float:none}.cke_reset_all .cke_rtl *{text-align:right}.cke_reset_all iframe{vertical-align:inherit}.cke_reset_all textarea{white-space:pre-wrap}.cke_reset_all textarea,.cke_reset_all input[type="text"],.cke_reset_all input[type="password"]{cursor:text}.cke_reset_all textarea[disabled],.cke_reset_all input[type="text"][disabled],.cke_reset_all input[type="password"][disabled]{cursor:default}.cke_reset_all fieldset{padding:10px;border:2px groove #e0dfe3}.cke_reset_all select{box-sizing:border-box}.cke_reset_all table{table-layout:auto}.cke_chrome{display:block;border:1px solid #d1d1d1;padding:0}.cke_inner{display:block;background:#fff;padding:0;-webkit-touch-callout:none}.cke_float{border:0}.cke_float .cke_inner{padding-bottom:0}.cke_top,.cke_contents,.cke_bottom{display:block;overflow:hidden}.cke_top{border-bottom:1px solid #d1d1d1;background:#f8f8f8;padding:6px 8px 2px;white-space:normal}.cke_float .cke_top{border:1px solid #d1d1d1}.cke_bottom{padding:6px 8px 2px;position:relative;border-top:1px solid #d1d1d1;background:#f8f8f8}.cke_browser_ios .cke_contents{overflow-y:auto;-webkit-overflow-scrolling:touch}.cke_resizer{width:0;height:0;overflow:hidden;border-width:10px 10px 0 0;border-color:transparent #bcbcbc transparent transparent;border-style:dashed solid dashed dashed;font-size:0;vertical-align:bottom;margin-top:6px;margin-bottom:2px}.cke_hc .cke_resizer{font-size:15px;width:auto;height:auto;border-width:0}.cke_resizer_ltr{cursor:se-resize;float:right;margin-right:-4px}.cke_resizer_rtl{border-width:10px 0 0 10px;border-color:transparent transparent transparent #bcbcbc;border-style:dashed dashed dashed solid;cursor:sw-resize;float:left;margin-left:-4px;right:auto}.cke_wysiwyg_div{display:block;height:100%;overflow:auto;padding:0 8px;outline-style:none;box-sizing:border-box}.cke_panel{visibility:visible;width:120px;height:100px;overflow:hidden;background-color:#fff;border:1px solid #d1d1d1}.cke_menu_panel{padding:0;margin:0}.cke_combopanel{width:150px;height:170px}.cke_panel_frame{width:100%;height:100%;font-size:12px;overflow:auto;overflow-x:hidden}.cke_panel_container{overflow-y:auto;overflow-x:hidden}.cke_panel_block:focus{outline:0}.cke_panel_list{margin:0;padding:0;list-style-type:none;white-space:nowrap}.cke_panel_listItem{margin:0;padding:0}.cke_panel_listItem a{padding:6px 7px;display:block;color:inherit!important;text-decoration:none;overflow:hidden;text-overflow:ellipsis}.cke_hc .cke_panel_listItem a{border-style:none}.cke_panel_listItem.cke_selected a,.cke_panel_listItem a:hover,.cke_panel_listItem a:focus,.cke_panel_listItem a:active{background-color:#e9e9e9}.cke_panel_listItem a:focus{outline:1px dotted #000}.cke_hc .cke_panel_listItem a:hover,.cke_hc .cke_panel_listItem a:focus,.cke_hc .cke_panel_listItem a:active{border:2px solid;padding:4px 5px}.cke_panel_listItem p,.cke_panel_listItem h1,.cke_panel_listItem h2,.cke_panel_listItem h3,.cke_panel_listItem h4,.cke_panel_listItem h5,.cke_panel_listItem h6,.cke_panel_listItem pre{margin-top:0;margin-bottom:0}.cke_panel_grouptitle{cursor:default;font-size:11px;font-weight:bold;white-space:nowrap;margin:0;padding:6px 6px 7px 6px;color:#484848;border-bottom:1px solid #d1d1d1;background:#f8f8f8}.cke_colorblock{padding:10px;font-size:11px;font-family:'Microsoft Sans Serif',Tahoma,Arial,Verdana,Sans-Serif}.cke_colorblock,.cke_colorblock a{text-decoration:none;color:#000}a.cke_colorbox{padding:2px;float:left;width:20px;height:20px}.cke_rtl a.cke_colorbox{float:right}a:hover.cke_colorbox,a:focus.cke_colorbox,a:active.cke_colorbox{outline:0;padding:0;border:2px solid #139ff7}a:hover.cke_colorbox{border-color:#bcbcbc}span.cke_colorbox{width:20px;height:20px;float:left}.cke_rtl span.cke_colorbox{float:right}a.cke_colorauto,a.cke_colormore{border:#fff 1px solid;padding:3px;display:block;cursor:pointer}a.cke_colorauto{padding:0;border:1px solid transparent;margin-bottom:6px;height:26px;line-height:26px}a.cke_colormore{margin-top:10px;height:20px;line-height:19px}a:hover.cke_colorauto,a:hover.cke_colormore,a:focus.cke_colorauto,a:focus.cke_colormore,a:active.cke_colorauto,a:active.cke_colormore{outline:0;border:#139ff7 1px solid;background-color:#f8f8f8}a:hover.cke_colorauto,a:hover.cke_colormore{border-color:#bcbcbc}.cke_colorauto span.cke_colorbox{width:18px;height:18px;border:1px solid #808080;margin-left:1px;margin-top:3px}.cke_rtl .cke_colorauto span.cke_colorbox{margin-left:0;margin-right:1px}span.cke_colorbox[style*="#ffffff"],span.cke_colorbox[style*="#FFFFFF"],span.cke_colorbox[style="background-color:#fff"],span.cke_colorbox[style="background-color:#FFF"],span.cke_colorbox[style*="rgb(255,255,255)"],span.cke_colorbox[style*="rgb(255, 255, 255)"]{border:1px solid #808080;width:18px;height:18px}.cke_toolbar{float:left}.cke_rtl .cke_toolbar{float:right}.cke_toolgroup{border:0;float:left;margin:1px 2px 6px 0;padding-right:3px}.cke_rtl .cke_toolgroup{float:right;margin:1px 0 6px 2px;padding-left:3px;padding-right:0}.cke_hc .cke_toolgroup{margin-right:5px;margin-bottom:5px}.cke_hc.cke_rtl .cke_toolgroup{margin-right:0;margin-left:5px}a.cke_button{display:inline-block;height:18px;padding:4px 6px;outline:0;cursor:default;float:left;border:0;position:relative}.cke_rtl a.cke_button{float:right}.cke_hc a.cke_button{border:1px solid black;padding:3px 5px;margin:0 3px 5px 0}.cke_hc.cke_rtl a.cke_button{margin:0 0 5px 3px}a.cke_button_on{background:#fff;border:1px #bcbcbc solid;padding:3px 5px}a.cke_button_off:hover,a.cke_button_off:focus,a.cke_button_off:active{background:#e5e5e5;border:1px #bcbcbc solid;padding:3px 5px}.cke_hc a.cke_button_on,.cke_hc a.cke_button_off:hover,.cke_hc a.cke_button_off:focus,.cke_hc a.cke_button_off:active{background:#e5e5e5;border:3px solid #000;padding:1px 3px}a.cke_button_disabled:hover,a.cke_button_disabled:focus,a.cke_button_disabled:active{border:0;padding:4px 6px;background-color:transparent}a.cke_button_disabled:focus{border:1px #bcbcbc solid;padding:3px 5px}.cke_hc a.cke_button_disabled:hover,.cke_hc a.cke_button_disabled:focus,.cke_hc a.cke_button_disabled:active{border:1px solid #acacac;padding:3px 5px;margin:0 3px 5px 0}.cke_hc a.cke_button_disabled:focus{border:3px solid #000;padding:1px 3px}.cke_hc.cke_rtl a.cke_button_disabled:hover,.cke_hc.cke_rtl a.cke_button_disabled:focus,.cke_hc.cke_rtl a.cke_button_disabled:active{margin:0 0 5px 3px}a.cke_button_disabled .cke_button_icon,a.cke_button_disabled .cke_button_arrow{opacity:.3}.cke_hc a.cke_button_disabled{border-color:#acacac}.cke_hc a.cke_button_disabled .cke_button_icon,.cke_hc a.cke_button_disabled .cke_button_label{opacity:.5}.cke_toolgroup a.cke_button:last-child:after,.cke_toolgroup a.cke_button.cke_button_disabled:hover:last-child:after{content:"";position:absolute;height:18px;width:0;border-right:1px solid #bcbcbc;margin-top:4px;top:0;right:-3px}.cke_rtl .cke_toolgroup a.cke_button:last-child:after,.cke_rtl .cke_toolgroup a.cke_button.cke_button_disabled:hover:last-child:after{border-right:0;right:auto;border-left:1px solid #bcbcbc;top:0;left:-3px}.cke_hc .cke_toolgroup a.cke_button:last-child:after,.cke_hc .cke_toolgroup a.cke_button.cke_button_disabled:last-child:after,.cke_hc .cke_toolgroup a.cke_button.cke_button_disabled:hover:last-child:after{border-color:#000;top:0;right:-7px}.cke_hc.cke_rtl .cke_toolgroup a.cke_button:last-child:after,.cke_hc.cke_rtl .cke_toolgroup a.cke_button.cke_button_disabled:last-child:after,.cke_hc.cke_rtl .cke_toolgroup a.cke_button.cke_button_disabled:hover:last-child:after{top:0;right:auto;left:-7px}.cke_toolgroup a.cke_button:hover:last-child:after,.cke_toolgroup a.cke_button.cke_button_on:last-child:after{top:-1px;right:-4px}.cke_rtl .cke_toolgroup a.cke_button:hover:last-child:after,.cke_rtl .cke_toolgroup a.cke_button.cke_button_on:last-child:after{top:-1px;right:auto;left:-4px}.cke_hc .cke_toolgroup a.cke_button:hover:last-child:after,.cke_hc .cke_toolgroup a.cke_button.cke_button_on:last-child:after{top:-2px;right:-9px}.cke_hc.cke_rtl .cke_toolgroup a.cke_button:hover:last-child:after,.cke_hc.cke_rtl .cke_toolgroup a.cke_button.cke_button_on:last-child:after{top:-2px;right:auto;left:-9px}.cke_toolbar.cke_toolbar_last .cke_toolgroup a.cke_button:last-child:after{content:none;border:0;width:0;height:0}.cke_button_icon{cursor:inherit;background-repeat:no-repeat;margin-top:1px;width:16px;height:16px;float:left;display:inline-block}.cke_rtl .cke_button_icon{float:right}.cke_hc .cke_button_icon{display:none}.cke_button_label{display:none;padding-left:3px;margin-top:1px;line-height:17px;vertical-align:middle;float:left;cursor:default;color:#484848}.cke_rtl .cke_button_label{padding-right:3px;padding-left:0;float:right}.cke_hc .cke_button_label{padding:0;display:inline-block;font-size:12px}.cke_button_arrow{display:inline-block;margin:8px 0 0 1px;width:0;height:0;cursor:default;vertical-align:top;border-left:3px solid transparent;border-right:3px solid transparent;border-top:3px solid #484848}.cke_rtl .cke_button_arrow{margin-right:5px;margin-left:0}.cke_hc .cke_button_arrow{font-size:10px;margin:3px 0 0 3px;width:auto;border:0}.cke_toolbar_separator{float:left;background-color:#bcbcbc;margin:4px 2px 0 2px;height:18px;width:1px}.cke_rtl .cke_toolbar_separator{float:right}.cke_hc .cke_toolbar_separator{background-color:#000;margin-left:2px;margin-right:5px;margin-bottom:9px}.cke_hc.cke_rtl .cke_toolbar_separator{margin-left:5px;margin-right:2px}.cke_toolbar_break{display:block;clear:left}.cke_rtl .cke_toolbar_break{clear:right}a.cke_toolbox_collapser{width:12px;height:11px;float:right;margin:11px 0 0;font-size:0;cursor:default;text-align:center;border:1px solid #bcbcbc}.cke_rtl .cke_toolbox_collapser{float:left}.cke_toolbox_collapser:hover{background:#e5e5e5}.cke_toolbox_collapser.cke_toolbox_collapser_min{margin:0 2px 4px}.cke_toolbox_collapser .cke_arrow{display:inline-block;height:0;width:0;font-size:0;margin-top:1px;border:3px solid transparent;border-bottom-color:#484848}.cke_toolbox_collapser.cke_toolbox_collapser_min .cke_arrow{margin-top:4px;border-bottom-color:transparent;border-top-color:#484848}.cke_hc .cke_toolbox_collapser .cke_arrow{font-size:8px;width:auto;border:0;margin-top:0}.cke_menuitem span{cursor:default}.cke_menubutton{display:block}.cke_hc .cke_menubutton{padding:2px}.cke_menubutton:hover,.cke_menubutton:focus,.cke_menubutton:active{background-color:#e9e9e9;display:block;outline:1px dotted}.cke_menubutton:hover{outline:0}.cke_hc .cke_menubutton:hover,.cke_hc .cke_menubutton:focus,.cke_hc .cke_menubutton:active{border:2px solid;padding:0}.cke_menubutton_disabled:hover,.cke_menubutton_disabled:focus,.cke_menubutton_disabled:active{background-color:transparent;outline:0}.cke_menubutton_inner{display:table-row}.cke_menubutton_icon,.cke_menubutton_label,.cke_menuarrow{display:table-cell}.cke_menubutton_icon{background-color:#f8f8f8;padding:6px 4px}.cke_hc .cke_menubutton_icon{height:16px;width:0;padding:4px 0}.cke_menubutton:hover .cke_menubutton_icon,.cke_menubutton:focus .cke_menubutton_icon,.cke_menubutton:active .cke_menubutton_icon{background-color:#e9e9e9}.cke_menubutton_disabled:hover .cke_menubutton_icon,.cke_menubutton_disabled:focus .cke_menubutton_icon,.cke_menubutton_disabled:active .cke_menubutton_icon{background-color:#f8f8f8;outline:0}.cke_menuitem .cke_menubutton_on{background-color:#e9e9e9;border:1px solid #dedede;outline:0}.cke_menubutton_on .cke_menubutton_icon{padding-right:3px;background-color:#e9e9e9}.cke_menubutton_label{padding:0 5px;background-color:transparent;width:100%;vertical-align:middle}.cke_menubutton_shortcut{color:#979797}.cke_menubutton_disabled .cke_menubutton_label{opacity:.3;filter:alpha(opacity=30)}.cke_panel_frame .cke_menubutton_label{display:none}.cke_menuseparator{background-color:#d1d1d1;height:1px}.cke_menuarrow{background:transparent url(images/arrow.png) no-repeat 0 10px;padding:0 5px}.cke_rtl .cke_menuarrow{background-position:5px -13px;background-repeat:no-repeat}.cke_hc .cke_menuarrow{background-image:none}.cke_menuarrow span{display:none}.cke_hc .cke_menuarrow span{vertical-align:middle;display:inline}.cke_combo{display:inline-block;float:left;position:relative;margin-bottom:5px}.cke_rtl .cke_combo{float:right}.cke_hc .cke_combo{margin-top:1px;margin-bottom:10px}.cke_combo:after{content:"";position:absolute;height:18px;width:0;border-right:1px solid #bcbcbc;margin-top:5px;top:0;right:0}.cke_rtl .cke_combo:after{border-right:0;border-left:1px solid #bcbcbc;right:auto;left:0}.cke_hc .cke_combo:after{border-color:#000}a.cke_combo_button{cursor:default;display:inline-block;float:left;margin:0;padding:1px}.cke_rtl a.cke_combo_button{float:right}.cke_hc a.cke_combo_button{padding:4px}.cke_combo_on a.cke_combo_button,.cke_combo_off a.cke_combo_button:hover,.cke_combo_off a.cke_combo_button:focus,.cke_combo_off a.cke_combo_button:active{background:#e5e5e5;border:1px solid #bcbcbc;padding:0 0 0 1px;margin-left:-1px}.cke_combo_off a.cke_combo_button:focus{outline:0}.cke_combo_on a.cke_combo_button,.cke_combo_off a.cke_combo_button:active{background:#fff}.cke_rtl .cke_combo_on a.cke_combo_button,.cke_rtl .cke_combo_off a.cke_combo_button:hover,.cke_rtl .cke_combo_off a.cke_combo_button:focus,.cke_rtl .cke_combo_off a.cke_combo_button:active{padding:0 1px 0 0;margin-left:0;margin-right:-1px}.cke_hc .cke_combo_on a.cke_combo_button,.cke_hc .cke_combo_off a.cke_combo_button:hover,.cke_hc .cke_combo_off a.cke_combo_button:focus,.cke_hc .cke_combo_off a.cke_combo_button:active{border:3px solid #000;padding:1px 1px 1px 2px}.cke_hc.cke_rtl .cke_combo_on a.cke_combo_button,.cke_hc.cke_rtl .cke_combo_off a.cke_combo_button:hover,.cke_hc.cke_rtl .cke_combo_off a.cke_combo_button:focus,.cke_hc.cke_rtl .cke_combo_off a.cke_combo_button:active{padding:1px 2px 1px 1px}.cke_toolbar_start+.cke_combo_on a.cke_combo_button,.cke_toolbar_start+.cke_combo_off a.cke_combo_button:hover,.cke_toolbar_start+.cke_combo_off a.cke_combo_button:focus,.cke_toolbar_start+.cke_combo_off a.cke_combo_button:active{padding:0 0 0 3px;margin-left:-3px}.cke_rtl .cke_toolbar_start+.cke_combo_on a.cke_combo_button,.cke_rtl .cke_toolbar_start+.cke_combo_off a.cke_combo_button:hover,.cke_rtl .cke_toolbar_start+.cke_combo_off a.cke_combo_button:focus,.cke_rtl .cke_toolbar_start+.cke_combo_off a.cke_combo_button:active{padding:0 3px 0 0;margin-left:0;margin-right:-3px}.cke_hc .cke_toolbar>.cke_toolbar_start+.cke_combo_on a.cke_combo_button,.cke_hc .cke_toolbar>.cke_toolbar_start+.cke_combo_off a.cke_combo_button:hover,.cke_hc .cke_toolbar>.cke_toolbar_start+.cke_combo_off a.cke_combo_button:focus,.cke_hc .cke_toolbar>.cke_toolbar_start+.cke_combo_off a.cke_combo_button:active{padding:1px 1px 1px 7px;margin-left:-6px}.cke_hc.cke_rtl .cke_toolbar>.cke_toolbar_start+.cke_combo_on a.cke_combo_button,.cke_hc.cke_rtl .cke_toolbar>.cke_toolbar_start+.cke_combo_off a.cke_combo_button:hover,.cke_hc.cke_rtl .cke_toolbar>.cke_toolbar_start+.cke_combo_off a.cke_combo_button:focus,.cke_hc.cke_rtl .cke_toolbar>.cke_toolbar_start+.cke_combo_off a.cke_combo_button:active{padding:1px 7px 1px 1px;margin-left:0;margin-right:-6px}.cke_toolbox .cke_toolbar:first-child>.cke_toolbar_start+.cke_combo_on a.cke_combo_button,.cke_toolbox .cke_toolbar:first-child>.cke_toolbar_start+.cke_combo_off a.cke_combo_button:hover,.cke_toolbox .cke_toolbar:first-child>.cke_toolbar_start+.cke_combo_off a.cke_combo_button:focus,.cke_toolbox .cke_toolbar:first-child>.cke_toolbar_start+.cke_combo_off a.cke_combo_button:active,.cke_toolbar_break+.cke_toolbar>.cke_toolbar_start+.cke_combo_on a.cke_combo_button,.cke_toolbar_break+.cke_toolbar>.cke_toolbar_start+.cke_combo_off a.cke_combo_button:hover,.cke_toolbar_break+.cke_toolbar>.cke_toolbar_start+.cke_combo_off a.cke_combo_button:focus,.cke_toolbar_break+.cke_toolbar>.cke_toolbar_start+.cke_combo_off a.cke_combo_button:active{padding:0;margin:0}.cke_hc .cke_toolbox .cke_toolbar:first-child>.cke_toolbar_start+.cke_combo_on a.cke_combo_button,.cke_hc .cke_toolbox .cke_toolbar:first-child>.cke_toolbar_start+.cke_combo_off a.cke_combo_button:hover,.cke_hc .cke_toolbox .cke_toolbar:first-child>.cke_toolbar_start+.cke_combo_off a.cke_combo_button:focus,.cke_hc .cke_toolbox .cke_toolbar:first-child>.cke_toolbar_start+.cke_combo_off a.cke_combo_button:active,.cke_hc .cke_toolbar_break+.cke_toolbar>.cke_toolbar_start+.cke_combo_on a.cke_combo_button,.cke_hc .cke_toolbar_break+.cke_toolbar>.cke_toolbar_start+.cke_combo_off a.cke_combo_button:hover,.cke_hc .cke_toolbar_break+.cke_toolbar>.cke_toolbar_start+.cke_combo_off a.cke_combo_button:focus,.cke_hc .cke_toolbar_break+.cke_toolbar>.cke_toolbar_start+.cke_combo_off a.cke_combo_button:active{padding:1px;margin:0}.cke_toolbar .cke_combo+.cke_toolbar_end,.cke_toolbar .cke_combo+.cke_toolgroup{margin-right:0;margin-left:2px}.cke_rtl .cke_toolbar .cke_combo+.cke_toolbar_end,.cke_rtl .cke_toolbar .cke_combo+.cke_toolgroup{margin-left:0;margin-right:2px}.cke_hc .cke_toolbar .cke_combo+.cke_toolbar_end,.cke_hc .cke_toolbar .cke_combo+.cke_toolgroup{margin-left:5px}.cke_hc.cke_rtl .cke_toolbar .cke_combo+.cke_toolbar_end,.cke_hc.cke_rtl .cke_toolbar .cke_combo+.cke_toolgroup{margin-left:0;margin-right:5px}.cke_toolbar.cke_toolbar_last .cke_combo:nth-last-child(-n+2):after{content:none;border:0;width:0;height:0}.cke_combo_text{line-height:26px;padding-left:10px;text-overflow:ellipsis;overflow:hidden;float:left;cursor:default;color:#484848;width:60px}.cke_rtl .cke_combo_text{float:right;text-align:right;padding-left:0;padding-right:10px}.cke_hc .cke_combo_text{line-height:18px;font-size:12px}.cke_combo_open{cursor:default;display:inline-block;font-size:0;height:19px;line-height:17px;margin:1px 10px 1px;width:5px}.cke_hc .cke_combo_open{height:12px}.cke_combo_arrow{cursor:default;margin:11px 0 0;float:left;height:0;width:0;font-size:0;border-left:3px solid transparent;border-right:3px solid transparent;border-top:3px solid #484848}.cke_hc .cke_combo_arrow{font-size:10px;width:auto;border:0;margin-top:3px}.cke_combo_label{display:none;float:left;line-height:26px;vertical-align:top;margin-right:5px}.cke_rtl .cke_combo_label{float:right;margin-left:5px;margin-right:0}.cke_combo_disabled .cke_combo_inlinelabel,.cke_combo_disabled .cke_combo_open{opacity:.3}.cke_path{float:left;margin:-2px 0 2px}a.cke_path_item,span.cke_path_empty{display:inline-block;float:left;padding:3px 4px;margin-right:2px;cursor:default;text-decoration:none;outline:0;border:0;color:#484848;font-weight:bold;font-size:11px}.cke_rtl .cke_path,.cke_rtl .cke_path_item,.cke_rtl .cke_path_empty{float:right}a.cke_path_item:hover,a.cke_path_item:focus,a.cke_path_item:active{background-color:#e5e5e5}.cke_hc a.cke_path_item:hover,.cke_hc a.cke_path_item:focus,.cke_hc a.cke_path_item:active{border:2px solid;padding:1px 2px}.cke_button__source_label,.cke_button__sourcedialog_label{display:inline}.cke_combopanel__fontsize{width:135px}textarea.cke_source{font-family:'Courier New',Monospace;font-size:small;background-color:#fff;white-space:pre-wrap;border:0;padding:0;margin:0;display:block}.cke_wysiwyg_frame,.cke_wysiwyg_div{background-color:#fff}.cke_notifications_area{pointer-events:none}.cke_notification{pointer-events:auto;position:relative;margin:10px;width:300px;color:white;text-align:center;opacity:.95;filter:alpha(opacity = 95);-webkit-animation:fadeIn .7s;animation:fadeIn .7s}.cke_notification_message a{color:#12306f}@-webkit-keyframes fadeIn{from{opacity:.4}to{opacity:.95}}@keyframes fadeIn{from{opacity:.4}to{opacity:.95}}.cke_notification_success{background:#72b572;border:1px solid #63a563}.cke_notification_warning{background:#c83939;border:1px solid #902b2b}.cke_notification_info{background:#2e9ad0;border:1px solid #0f74a8}.cke_notification_info span.cke_notification_progress{background-color:#0f74a8;display:block;padding:0;margin:0;height:100%;overflow:hidden;position:absolute;z-index:1}.cke_notification_message{position:relative;margin:4px 23px 3px;font-family:Arial,Helvetica,sans-serif;font-size:12px;line-height:18px;z-index:4;text-overflow:ellipsis;overflow:hidden}.cke_notification_close{background-image:url(images/close.png);background-repeat:no-repeat;background-position:50%;position:absolute;cursor:pointer;text-align:center;height:20px;width:20px;top:1px;right:1px;padding:0;margin:0;z-index:5;opacity:.6;filter:alpha(opacity = 60)}.cke_notification_close:hover{opacity:1;filter:alpha(opacity = 100)}.cke_notification_close span{display:none}.cke_notification_warning a.cke_notification_close{opacity:.8;filter:alpha(opacity = 80)}.cke_notification_warning a.cke_notification_close:hover{opacity:1;filter:alpha(opacity = 100)}.cke_chrome{visibility:inherit}.cke_voice_label{display:none}legend.cke_voice_label{display:none}.cke_button__about_icon{background:url(icons.png?t=I648) no-repeat 0 -0px!important}.cke_button__bold_icon{background:url(icons.png?t=I648) no-repeat 0 -24px!important}.cke_button__italic_icon{background:url(icons.png?t=I648) no-repeat 0 -48px!important}.cke_button__strike_icon{background:url(icons.png?t=I648) no-repeat 0 -72px!important}.cke_button__subscript_icon{background:url(icons.png?t=I648) no-repeat 0 -96px!important}.cke_button__superscript_icon{background:url(icons.png?t=I648) no-repeat 0 -120px!important}.cke_button__underline_icon{background:url(icons.png?t=I648) no-repeat 0 -144px!important}.cke_button__blockquote_icon{background:url(icons.png?t=I648) no-repeat 0 -168px!important}.cke_rtl .cke_button__copy_icon,.cke_mixed_dir_content .cke_rtl .cke_button__copy_icon{background:url(icons.png?t=I648) no-repeat 0 -192px!important}.cke_ltr .cke_button__copy_icon{background:url(icons.png?t=I648) no-repeat 0 -216px!important}.cke_rtl .cke_button__cut_icon,.cke_mixed_dir_content .cke_rtl .cke_button__cut_icon{background:url(icons.png?t=I648) no-repeat 0 -240px!important}.cke_ltr .cke_button__cut_icon{background:url(icons.png?t=I648) no-repeat 0 -264px!important}.cke_rtl .cke_button__paste_icon,.cke_mixed_dir_content .cke_rtl .cke_button__paste_icon{background:url(icons.png?t=I648) no-repeat 0 -288px!important}.cke_ltr .cke_button__paste_icon{background:url(icons.png?t=I648) no-repeat 0 -312px!important}.cke_button__horizontalrule_icon{background:url(icons.png?t=I648) no-repeat 0 -336px!important}.cke_button__image_icon{background:url(icons.png?t=I648) no-repeat 0 -360px!important}.cke_rtl .cke_button__indent_icon,.cke_mixed_dir_content .cke_rtl .cke_button__indent_icon{background:url(icons.png?t=I648) no-repeat 0 -384px!important}.cke_ltr .cke_button__indent_icon{background:url(icons.png?t=I648) no-repeat 0 -408px!important}.cke_rtl .cke_button__outdent_icon,.cke_mixed_dir_content .cke_rtl .cke_button__outdent_icon{background:url(icons.png?t=I648) no-repeat 0 -432px!important}.cke_ltr .cke_button__outdent_icon{background:url(icons.png?t=I648) no-repeat 0 -456px!important}.cke_button__justifyblock_icon{background:url(icons.png?t=I648) no-repeat 0 -480px!important}.cke_button__justifycenter_icon{background:url(icons.png?t=I648) no-repeat 0 -504px!important}.cke_button__justifyleft_icon{background:url(icons.png?t=I648) no-repeat 0 -528px!important}.cke_button__justifyright_icon{background:url(icons.png?t=I648) no-repeat 0 -552px!important}.cke_button__language_icon{background:url(icons.png?t=I648) no-repeat 0 -576px!important}.cke_rtl .cke_button__bulletedlist_icon,.cke_mixed_dir_content .cke_rtl .cke_button__bulletedlist_icon{background:url(icons.png?t=I648) no-repeat 0 -600px!important}.cke_ltr .cke_button__bulletedlist_icon{background:url(icons.png?t=I648) no-repeat 0 -624px!important}.cke_rtl .cke_button__numberedlist_icon,.cke_mixed_dir_content .cke_rtl .cke_button__numberedlist_icon{background:url(icons.png?t=I648) no-repeat 0 -648px!important}.cke_ltr .cke_button__numberedlist_icon{background:url(icons.png?t=I648) no-repeat 0 -672px!important}.cke_button__maximize_icon{background:url(icons.png?t=I648) no-repeat 0 -696px!important}.cke_rtl .cke_button__pastefromword_icon,.cke_mixed_dir_content .cke_rtl .cke_button__pastefromword_icon{background:url(icons.png?t=I648) no-repeat 0 -720px!important}.cke_ltr .cke_button__pastefromword_icon{background:url(icons.png?t=I648) no-repeat 0 -744px!important}.cke_rtl .cke_button__pastetext_icon,.cke_mixed_dir_content .cke_rtl .cke_button__pastetext_icon{background:url(icons.png?t=I648) no-repeat 0 -768px!important}.cke_ltr .cke_button__pastetext_icon{background:url(icons.png?t=I648) no-repeat 0 -792px!important}.cke_button__removeformat_icon{background:url(icons.png?t=I648) no-repeat 0 -816px!important}.cke_rtl .cke_button__showblocks_icon,.cke_mixed_dir_content .cke_rtl .cke_button__showblocks_icon{background:url(icons.png?t=I648) no-repeat 0 -840px!important}.cke_ltr .cke_button__showblocks_icon{background:url(icons.png?t=I648) no-repeat 0 -864px!important}.cke_rtl .cke_button__source_icon,.cke_mixed_dir_content .cke_rtl .cke_button__source_icon{background:url(icons.png?t=I648) no-repeat 0 -888px!important}.cke_ltr .cke_button__source_icon{background:url(icons.png?t=I648) no-repeat 0 -912px!important}.cke_rtl .cke_button__sourcedialog_icon,.cke_mixed_dir_content .cke_rtl .cke_button__sourcedialog_icon{background:url(icons.png?t=I648) no-repeat 0 -936px!important}.cke_ltr .cke_button__sourcedialog_icon{background:url(icons.png?t=I648) no-repeat 0 -960px!important}.cke_button__specialchar_icon{background:url(icons.png?t=I648) no-repeat 0 -984px!important}.cke_button__table_icon{background:url(icons.png?t=I648) no-repeat 0 -1008px!important}.cke_rtl .cke_button__redo_icon,.cke_mixed_dir_content .cke_rtl .cke_button__redo_icon{background:url(icons.png?t=I648) no-repeat 0 -1032px!important}.cke_ltr .cke_button__redo_icon{background:url(icons.png?t=I648) no-repeat 0 -1056px!important}.cke_rtl .cke_button__undo_icon,.cke_mixed_dir_content .cke_rtl .cke_button__undo_icon{background:url(icons.png?t=I648) no-repeat 0 -1080px!important}.cke_ltr .cke_button__undo_icon{background:url(icons.png?t=I648) no-repeat 0 -1104px!important}.cke_button__simplebox_icon{background:url(icons.png?t=I648) no-repeat 0 -1128px!important}.cke_hidpi .cke_button__about_icon{background:url(icons_hidpi.png?t=I648) no-repeat 0 -0px!important;background-size:16px!important}.cke_hidpi .cke_button__bold_icon{background:url(icons_hidpi.png?t=I648) no-repeat 0 -24px!important;background-size:16px!important}.cke_hidpi .cke_button__italic_icon{background:url(icons_hidpi.png?t=I648) no-repeat 0 -48px!important;background-size:16px!important}.cke_hidpi .cke_button__strike_icon{background:url(icons_hidpi.png?t=I648) no-repeat 0 -72px!important;background-size:16px!important}.cke_hidpi .cke_button__subscript_icon{background:url(icons_hidpi.png?t=I648) no-repeat 0 -96px!important;background-size:16px!important}.cke_hidpi .cke_button__superscript_icon{background:url(icons_hidpi.png?t=I648) no-repeat 0 -120px!important;background-size:16px!important}.cke_hidpi .cke_button__underline_icon{background:url(icons_hidpi.png?t=I648) no-repeat 0 -144px!important;background-size:16px!important}.cke_hidpi .cke_button__blockquote_icon{background:url(icons_hidpi.png?t=I648) no-repeat 0 -168px!important;background-size:16px!important}.cke_rtl.cke_hidpi .cke_button__copy_icon,.cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__copy_icon{background:url(icons_hidpi.png?t=I648) no-repeat 0 -192px!important;background-size:16px!important}.cke_hidpi .cke_ltr .cke_button__copy_icon,.cke_ltr.cke_hidpi .cke_button__copy_icon{background:url(icons_hidpi.png?t=I648) no-repeat 0 -216px!important;background-size:16px!important}.cke_rtl.cke_hidpi .cke_button__cut_icon,.cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__cut_icon{background:url(icons_hidpi.png?t=I648) no-repeat 0 -240px!important;background-size:16px!important}.cke_hidpi .cke_ltr .cke_button__cut_icon,.cke_ltr.cke_hidpi .cke_button__cut_icon{background:url(icons_hidpi.png?t=I648) no-repeat 0 -264px!important;background-size:16px!important}.cke_rtl.cke_hidpi .cke_button__paste_icon,.cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__paste_icon{background:url(icons_hidpi.png?t=I648) no-repeat 0 -288px!important;background-size:16px!important}.cke_hidpi .cke_ltr .cke_button__paste_icon,.cke_ltr.cke_hidpi .cke_button__paste_icon{background:url(icons_hidpi.png?t=I648) no-repeat 0 -312px!important;background-size:16px!important}.cke_hidpi .cke_button__horizontalrule_icon{background:url(icons_hidpi.png?t=I648) no-repeat 0 -336px!important;background-size:16px!important}.cke_hidpi .cke_button__image_icon{background:url(icons_hidpi.png?t=I648) no-repeat 0 -360px!important;background-size:16px!important}.cke_rtl.cke_hidpi .cke_button__indent_icon,.cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__indent_icon{background:url(icons_hidpi.png?t=I648) no-repeat 0 -384px!important;background-size:16px!important}.cke_hidpi .cke_ltr .cke_button__indent_icon,.cke_ltr.cke_hidpi .cke_button__indent_icon{background:url(icons_hidpi.png?t=I648) no-repeat 0 -408px!important;background-size:16px!important}.cke_rtl.cke_hidpi .cke_button__outdent_icon,.cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__outdent_icon{background:url(icons_hidpi.png?t=I648) no-repeat 0 -432px!important;background-size:16px!important}.cke_hidpi .cke_ltr .cke_button__outdent_icon,.cke_ltr.cke_hidpi .cke_button__outdent_icon{background:url(icons_hidpi.png?t=I648) no-repeat 0 -456px!important;background-size:16px!important}.cke_hidpi .cke_button__justifyblock_icon{background:url(icons_hidpi.png?t=I648) no-repeat 0 -480px!important;background-size:16px!important}.cke_hidpi .cke_button__justifycenter_icon{background:url(icons_hidpi.png?t=I648) no-repeat 0 -504px!important;background-size:16px!important}.cke_hidpi .cke_button__justifyleft_icon{background:url(icons_hidpi.png?t=I648) no-repeat 0 -528px!important;background-size:16px!important}.cke_hidpi .cke_button__justifyright_icon{background:url(icons_hidpi.png?t=I648) no-repeat 0 -552px!important;background-size:16px!important}.cke_hidpi .cke_button__language_icon{background:url(icons_hidpi.png?t=I648) no-repeat 0 -576px!important;background-size:16px!important}.cke_rtl.cke_hidpi .cke_button__bulletedlist_icon,.cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__bulletedlist_icon{background:url(icons_hidpi.png?t=I648) no-repeat 0 -600px!important;background-size:16px!important}.cke_hidpi .cke_ltr .cke_button__bulletedlist_icon,.cke_ltr.cke_hidpi .cke_button__bulletedlist_icon{background:url(icons_hidpi.png?t=I648) no-repeat 0 -624px!important;background-size:16px!important}.cke_rtl.cke_hidpi .cke_button__numberedlist_icon,.cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__numberedlist_icon{background:url(icons_hidpi.png?t=I648) no-repeat 0 -648px!important;background-size:16px!important}.cke_hidpi .cke_ltr .cke_button__numberedlist_icon,.cke_ltr.cke_hidpi .cke_button__numberedlist_icon{background:url(icons_hidpi.png?t=I648) no-repeat 0 -672px!important;background-size:16px!important}.cke_hidpi .cke_button__maximize_icon{background:url(icons_hidpi.png?t=I648) no-repeat 0 -696px!important;background-size:16px!important}.cke_rtl.cke_hidpi .cke_button__pastefromword_icon,.cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__pastefromword_icon{background:url(icons_hidpi.png?t=I648) no-repeat 0 -720px!important;background-size:16px!important}.cke_hidpi .cke_ltr .cke_button__pastefromword_icon,.cke_ltr.cke_hidpi .cke_button__pastefromword_icon{background:url(icons_hidpi.png?t=I648) no-repeat 0 -744px!important;background-size:16px!important}.cke_rtl.cke_hidpi .cke_button__pastetext_icon,.cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__pastetext_icon{background:url(icons_hidpi.png?t=I648) no-repeat 0 -768px!important;background-size:16px!important}.cke_hidpi .cke_ltr .cke_button__pastetext_icon,.cke_ltr.cke_hidpi .cke_button__pastetext_icon{background:url(icons_hidpi.png?t=I648) no-repeat 0 -792px!important;background-size:16px!important}.cke_hidpi .cke_button__removeformat_icon{background:url(icons_hidpi.png?t=I648) no-repeat 0 -816px!important;background-size:16px!important}.cke_rtl.cke_hidpi .cke_button__showblocks_icon,.cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__showblocks_icon{background:url(icons_hidpi.png?t=I648) no-repeat 0 -840px!important;background-size:16px!important}.cke_hidpi .cke_ltr .cke_button__showblocks_icon,.cke_ltr.cke_hidpi .cke_button__showblocks_icon{background:url(icons_hidpi.png?t=I648) no-repeat 0 -864px!important;background-size:16px!important}.cke_rtl.cke_hidpi .cke_button__source_icon,.cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__source_icon{background:url(icons_hidpi.png?t=I648) no-repeat 0 -888px!important;background-size:16px!important}.cke_hidpi .cke_ltr .cke_button__source_icon,.cke_ltr.cke_hidpi .cke_button__source_icon{background:url(icons_hidpi.png?t=I648) no-repeat 0 -912px!important;background-size:16px!important}.cke_rtl.cke_hidpi .cke_button__sourcedialog_icon,.cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__sourcedialog_icon{background:url(icons_hidpi.png?t=I648) no-repeat 0 -936px!important;background-size:16px!important}.cke_hidpi .cke_ltr .cke_button__sourcedialog_icon,.cke_ltr.cke_hidpi .cke_button__sourcedialog_icon{background:url(icons_hidpi.png?t=I648) no-repeat 0 -960px!important;background-size:16px!important}.cke_hidpi .cke_button__specialchar_icon{background:url(icons_hidpi.png?t=I648) no-repeat 0 -984px!important;background-size:16px!important}.cke_hidpi .cke_button__table_icon{background:url(icons_hidpi.png?t=I648) no-repeat 0 -1008px!important;background-size:16px!important}.cke_rtl.cke_hidpi .cke_button__redo_icon,.cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__redo_icon{background:url(icons_hidpi.png?t=I648) no-repeat 0 -1032px!important;background-size:16px!important}.cke_hidpi .cke_ltr .cke_button__redo_icon,.cke_ltr.cke_hidpi .cke_button__redo_icon{background:url(icons_hidpi.png?t=I648) no-repeat 0 -1056px!important;background-size:16px!important}.cke_rtl.cke_hidpi .cke_button__undo_icon,.cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__undo_icon{background:url(icons_hidpi.png?t=I648) no-repeat 0 -1080px!important;background-size:16px!important}.cke_hidpi .cke_ltr .cke_button__undo_icon,.cke_ltr.cke_hidpi .cke_button__undo_icon{background:url(icons_hidpi.png?t=I648) no-repeat 0 -1104px!important;background-size:16px!important}.cke_hidpi .cke_button__simplebox_icon{background:url(icons_hidpi.png?t=I648) no-repeat 0 -2256px!important}a.cke_button_disabled,a.cke_button_disabled:hover,a.cke_button_disabled:focus,a.cke_button_disabled:active{filter:alpha(opacity = 30)}.cke_button_disabled .cke_button_icon{filter:progid:DXImageTransform.Microsoft.gradient(startColorstr=#00ffffff,endColorstr=#00ffffff)}.cke_button_off:hover,.cke_button_off:focus,.cke_button_off:active{filter:alpha(opacity = 100)}.cke_combo_disabled .cke_combo_inlinelabel,.cke_combo_disabled .cke_combo_open{filter:alpha(opacity = 30)}.cke_toolbox_collapser{border:1px solid #a6a6a6}.cke_toolbox_collapser .cke_arrow{margin-top:1px}.cke_hc .cke_top,.cke_hc .cke_bottom,.cke_hc .cke_combo_button,.cke_hc a.cke_combo_button:hover,.cke_hc a.cke_combo_button:focus,.cke_hc .cke_toolgroup,.cke_hc .cke_button_on,.cke_hc a.cke_button_off:hover,.cke_hc a.cke_button_off:focus,.cke_hc a.cke_button_off:active,.cke_hc .cke_toolbox_collapser,.cke_hc .cke_toolbox_collapser:hover,.cke_hc .cke_panel_grouptitle{filter:progid:DXImageTransform.Microsoft.gradient(enabled=false)}.cke_toolbox_collapser .cke_arrow{border-width:4px}.cke_toolbox_collapser.cke_toolbox_collapser_min .cke_arrow{border-width:3px}.cke_toolbox_collapser .cke_arrow{margin-top:0}.cke_toolbar{position:relative}.cke_rtl .cke_toolbar_end{right:auto;left:0}.cke_toolbar_end:after{content:"";position:absolute;height:18px;width:0;border-right:1px solid #bcbcbc;margin-top:4px;top:1px;right:2px}.cke_rtl .cke_toolbar_end:after{right:auto;left:2px}.cke_hc .cke_toolbar_end:after{top:2px;right:5px;border-color:#000}.cke_hc.cke_rtl .cke_toolbar_end:after{right:auto;left:5px}.cke_combo+.cke_toolbar_end:after,.cke_toolbar.cke_toolbar_last .cke_toolbar_end:after{content:none;border:0}.cke_combo+.cke_toolgroup+.cke_toolbar_end:after{right:0}.cke_rtl .cke_combo+.cke_toolgroup+.cke_toolbar_end:after{right:auto;left:0} \ No newline at end of file +.cke_reset{margin:0;padding:0;border:0;background:transparent;text-decoration:none;width:auto;height:auto;vertical-align:baseline;box-sizing:content-box;position:static;transition:none}.cke_reset_all,.cke_reset_all *,.cke_reset_all a,.cke_reset_all textarea{margin:0;padding:0;border:0;background:transparent;text-decoration:none;width:auto;height:auto;vertical-align:baseline;box-sizing:content-box;position:static;transition:none;border-collapse:collapse;font:normal normal normal 12px Arial,Helvetica,Tahoma,Verdana,Sans-Serif;color:#000;text-align:left;white-space:nowrap;cursor:auto;float:none}.cke_reset_all .cke_rtl *{text-align:right}.cke_reset_all iframe{vertical-align:inherit}.cke_reset_all textarea{white-space:pre-wrap}.cke_reset_all textarea,.cke_reset_all input[type="text"],.cke_reset_all input[type="password"]{cursor:text}.cke_reset_all textarea[disabled],.cke_reset_all input[type="text"][disabled],.cke_reset_all input[type="password"][disabled]{cursor:default}.cke_reset_all fieldset{padding:10px;border:2px groove #e0dfe3}.cke_reset_all select{box-sizing:border-box}.cke_reset_all table{table-layout:auto}.cke_chrome{display:block;border:1px solid #d1d1d1;padding:0}.cke_inner{display:block;background:#fff;padding:0;-webkit-touch-callout:none}.cke_float{border:0}.cke_float .cke_inner{padding-bottom:0}.cke_top,.cke_contents,.cke_bottom{display:block;overflow:hidden}.cke_top{border-bottom:1px solid #d1d1d1;background:#f8f8f8;padding:6px 8px 2px;white-space:normal}.cke_float .cke_top{border:1px solid #d1d1d1}.cke_bottom{padding:6px 8px 2px;position:relative;border-top:1px solid #d1d1d1;background:#f8f8f8}.cke_browser_ios .cke_contents{overflow-y:auto;-webkit-overflow-scrolling:touch}.cke_resizer{width:0;height:0;overflow:hidden;border-width:10px 10px 0 0;border-color:transparent #bcbcbc transparent transparent;border-style:dashed solid dashed dashed;font-size:0;vertical-align:bottom;margin-top:6px;margin-bottom:2px}.cke_hc .cke_resizer{font-size:15px;width:auto;height:auto;border-width:0}.cke_resizer_ltr{cursor:se-resize;float:right;margin-right:-4px}.cke_resizer_rtl{border-width:10px 0 0 10px;border-color:transparent transparent transparent #bcbcbc;border-style:dashed dashed dashed solid;cursor:sw-resize;float:left;margin-left:-4px;right:auto}.cke_wysiwyg_div{display:block;height:100%;overflow:auto;padding:0 8px;outline-style:none;box-sizing:border-box}.cke_panel{visibility:visible;width:120px;height:100px;overflow:hidden;background-color:#fff;border:1px solid #d1d1d1}.cke_menu_panel{padding:0;margin:0}.cke_combopanel{width:150px;height:170px}.cke_panel_frame{width:100%;height:100%;font-size:12px;overflow:auto;overflow-x:hidden}.cke_panel_container{overflow-y:auto;overflow-x:hidden}.cke_panel_block:focus{outline:0}.cke_panel_list{margin:0;padding:0;list-style-type:none;white-space:nowrap}.cke_panel_listItem{margin:0;padding:0}.cke_panel_listItem a{padding:6px 7px;display:block;color:inherit!important;text-decoration:none;overflow:hidden;text-overflow:ellipsis}.cke_hc .cke_panel_listItem a{border-style:none}.cke_panel_listItem.cke_selected a,.cke_panel_listItem a:hover,.cke_panel_listItem a:focus,.cke_panel_listItem a:active{background-color:#e9e9e9}.cke_panel_listItem a:focus{outline:1px dotted #000}.cke_hc .cke_panel_listItem a:hover,.cke_hc .cke_panel_listItem a:focus,.cke_hc .cke_panel_listItem a:active{border:2px solid;padding:4px 5px}.cke_panel_listItem p,.cke_panel_listItem h1,.cke_panel_listItem h2,.cke_panel_listItem h3,.cke_panel_listItem h4,.cke_panel_listItem h5,.cke_panel_listItem h6,.cke_panel_listItem pre{margin-top:0;margin-bottom:0}.cke_panel_grouptitle{cursor:default;font-size:11px;font-weight:bold;white-space:nowrap;margin:0;padding:6px 6px 7px 6px;color:#484848;border-bottom:1px solid #d1d1d1;background:#f8f8f8}.cke_colorblock{padding:10px;font-size:11px;font-family:'Microsoft Sans Serif',Tahoma,Arial,Verdana,Sans-Serif}.cke_colorblock,.cke_colorblock a{text-decoration:none;color:#000}a.cke_colorbox{padding:2px;float:left;width:20px;height:20px}.cke_rtl a.cke_colorbox{float:right}a:hover.cke_colorbox,a:focus.cke_colorbox,a:active.cke_colorbox{outline:0;padding:0;border:2px solid #139ff7}a:hover.cke_colorbox{border-color:#bcbcbc}span.cke_colorbox{width:20px;height:20px;float:left}.cke_rtl span.cke_colorbox{float:right}a.cke_colorauto,a.cke_colormore{border:#fff 1px solid;padding:3px;display:block;cursor:pointer}a.cke_colorauto{padding:0;border:1px solid transparent;margin-bottom:6px;height:26px;line-height:26px}a.cke_colormore{margin-top:10px;height:20px;line-height:19px}a:hover.cke_colorauto,a:hover.cke_colormore,a:focus.cke_colorauto,a:focus.cke_colormore,a:active.cke_colorauto,a:active.cke_colormore{outline:0;border:#139ff7 1px solid;background-color:#f8f8f8}a:hover.cke_colorauto,a:hover.cke_colormore{border-color:#bcbcbc}.cke_colorauto span.cke_colorbox{width:18px;height:18px;border:1px solid #808080;margin-left:1px;margin-top:3px}.cke_rtl .cke_colorauto span.cke_colorbox{margin-left:0;margin-right:1px}span.cke_colorbox[style*="#ffffff"],span.cke_colorbox[style*="#FFFFFF"],span.cke_colorbox[style="background-color:#fff"],span.cke_colorbox[style="background-color:#FFF"],span.cke_colorbox[style*="rgb(255,255,255)"],span.cke_colorbox[style*="rgb(255, 255, 255)"]{border:1px solid #808080;width:18px;height:18px}.cke_toolbar{float:left}.cke_rtl .cke_toolbar{float:right}.cke_toolgroup{border:0;float:left;margin:1px 2px 6px 0;padding-right:3px}.cke_rtl .cke_toolgroup{float:right;margin:1px 0 6px 2px;padding-left:3px;padding-right:0}.cke_hc .cke_toolgroup{margin-right:5px;margin-bottom:5px}.cke_hc.cke_rtl .cke_toolgroup{margin-right:0;margin-left:5px}a.cke_button{display:inline-block;height:18px;padding:4px 6px;outline:0;cursor:default;float:left;border:0;position:relative}.cke_rtl a.cke_button{float:right}.cke_hc a.cke_button{border:1px solid black;padding:3px 5px;margin:0 3px 5px 0}.cke_hc.cke_rtl a.cke_button{margin:0 0 5px 3px}a.cke_button_on{background:#fff;border:1px #bcbcbc solid;padding:3px 5px}a.cke_button_off:hover,a.cke_button_off:focus,a.cke_button_off:active{background:#e5e5e5;border:1px #bcbcbc solid;padding:3px 5px}.cke_hc a.cke_button_on,.cke_hc a.cke_button_off:hover,.cke_hc a.cke_button_off:focus,.cke_hc a.cke_button_off:active{background:#e5e5e5;border:3px solid #000;padding:1px 3px}a.cke_button_disabled:hover,a.cke_button_disabled:focus,a.cke_button_disabled:active{border:0;padding:4px 6px;background-color:transparent}a.cke_button_disabled:focus{border:1px #bcbcbc solid;padding:3px 5px}.cke_hc a.cke_button_disabled:hover,.cke_hc a.cke_button_disabled:focus,.cke_hc a.cke_button_disabled:active{border:1px solid #acacac;padding:3px 5px;margin:0 3px 5px 0}.cke_hc a.cke_button_disabled:focus{border:3px solid #000;padding:1px 3px}.cke_hc.cke_rtl a.cke_button_disabled:hover,.cke_hc.cke_rtl a.cke_button_disabled:focus,.cke_hc.cke_rtl a.cke_button_disabled:active{margin:0 0 5px 3px}a.cke_button_disabled .cke_button_icon,a.cke_button_disabled .cke_button_arrow{opacity:.3}.cke_hc a.cke_button_disabled{border-color:#acacac}.cke_hc a.cke_button_disabled .cke_button_icon,.cke_hc a.cke_button_disabled .cke_button_label{opacity:.5}.cke_toolgroup a.cke_button:last-child:after,.cke_toolgroup a.cke_button.cke_button_disabled:hover:last-child:after{content:"";position:absolute;height:18px;width:0;border-right:1px solid #bcbcbc;margin-top:4px;top:0;right:-3px}.cke_rtl .cke_toolgroup a.cke_button:last-child:after,.cke_rtl .cke_toolgroup a.cke_button.cke_button_disabled:hover:last-child:after{border-right:0;right:auto;border-left:1px solid #bcbcbc;top:0;left:-3px}.cke_hc .cke_toolgroup a.cke_button:last-child:after,.cke_hc .cke_toolgroup a.cke_button.cke_button_disabled:last-child:after,.cke_hc .cke_toolgroup a.cke_button.cke_button_disabled:hover:last-child:after{border-color:#000;top:0;right:-7px}.cke_hc.cke_rtl .cke_toolgroup a.cke_button:last-child:after,.cke_hc.cke_rtl .cke_toolgroup a.cke_button.cke_button_disabled:last-child:after,.cke_hc.cke_rtl .cke_toolgroup a.cke_button.cke_button_disabled:hover:last-child:after{top:0;right:auto;left:-7px}.cke_toolgroup a.cke_button:hover:last-child:after,.cke_toolgroup a.cke_button.cke_button_on:last-child:after{top:-1px;right:-4px}.cke_rtl .cke_toolgroup a.cke_button:hover:last-child:after,.cke_rtl .cke_toolgroup a.cke_button.cke_button_on:last-child:after{top:-1px;right:auto;left:-4px}.cke_hc .cke_toolgroup a.cke_button:hover:last-child:after,.cke_hc .cke_toolgroup a.cke_button.cke_button_on:last-child:after{top:-2px;right:-9px}.cke_hc.cke_rtl .cke_toolgroup a.cke_button:hover:last-child:after,.cke_hc.cke_rtl .cke_toolgroup a.cke_button.cke_button_on:last-child:after{top:-2px;right:auto;left:-9px}.cke_toolbar.cke_toolbar_last .cke_toolgroup a.cke_button:last-child:after{content:none;border:0;width:0;height:0}.cke_button_icon{cursor:inherit;background-repeat:no-repeat;margin-top:1px;width:16px;height:16px;float:left;display:inline-block}.cke_rtl .cke_button_icon{float:right}.cke_hc .cke_button_icon{display:none}.cke_button_label{display:none;padding-left:3px;margin-top:1px;line-height:17px;vertical-align:middle;float:left;cursor:default;color:#484848}.cke_rtl .cke_button_label{padding-right:3px;padding-left:0;float:right}.cke_hc .cke_button_label{padding:0;display:inline-block;font-size:12px}.cke_button_arrow{display:inline-block;margin:8px 0 0 1px;width:0;height:0;cursor:default;vertical-align:top;border-left:3px solid transparent;border-right:3px solid transparent;border-top:3px solid #484848}.cke_rtl .cke_button_arrow{margin-right:5px;margin-left:0}.cke_hc .cke_button_arrow{font-size:10px;margin:3px 0 0 3px;width:auto;border:0}.cke_toolbar_separator{float:left;background-color:#bcbcbc;margin:4px 2px 0 2px;height:18px;width:1px}.cke_rtl .cke_toolbar_separator{float:right}.cke_hc .cke_toolbar_separator{background-color:#000;margin-left:2px;margin-right:5px;margin-bottom:9px}.cke_hc.cke_rtl .cke_toolbar_separator{margin-left:5px;margin-right:2px}.cke_toolbar_break{display:block;clear:left}.cke_rtl .cke_toolbar_break{clear:right}a.cke_toolbox_collapser{width:12px;height:11px;float:right;margin:11px 0 0;font-size:0;cursor:default;text-align:center;border:1px solid #bcbcbc}.cke_rtl .cke_toolbox_collapser{float:left}.cke_toolbox_collapser:hover{background:#e5e5e5}.cke_toolbox_collapser.cke_toolbox_collapser_min{margin:0 2px 4px}.cke_toolbox_collapser .cke_arrow{display:inline-block;height:0;width:0;font-size:0;margin-top:1px;border:3px solid transparent;border-bottom-color:#484848}.cke_toolbox_collapser.cke_toolbox_collapser_min .cke_arrow{margin-top:4px;border-bottom-color:transparent;border-top-color:#484848}.cke_hc .cke_toolbox_collapser .cke_arrow{font-size:8px;width:auto;border:0;margin-top:0}.cke_menuitem span{cursor:default}.cke_menubutton{display:block}.cke_hc .cke_menubutton{padding:2px}.cke_menubutton:hover,.cke_menubutton:focus,.cke_menubutton:active{background-color:#e9e9e9;display:block;outline:1px dotted}.cke_menubutton:hover{outline:0}.cke_hc .cke_menubutton:hover,.cke_hc .cke_menubutton:focus,.cke_hc .cke_menubutton:active{border:2px solid;padding:0}.cke_menubutton_disabled:hover,.cke_menubutton_disabled:focus,.cke_menubutton_disabled:active{background-color:transparent;outline:0}.cke_menubutton_inner{display:table-row}.cke_menubutton_icon,.cke_menubutton_label,.cke_menuarrow{display:table-cell}.cke_menubutton_icon{background-color:#f8f8f8;padding:6px 4px}.cke_hc .cke_menubutton_icon{height:16px;width:0;padding:4px 0}.cke_menubutton:hover .cke_menubutton_icon,.cke_menubutton:focus .cke_menubutton_icon,.cke_menubutton:active .cke_menubutton_icon{background-color:#e9e9e9}.cke_menubutton_disabled:hover .cke_menubutton_icon,.cke_menubutton_disabled:focus .cke_menubutton_icon,.cke_menubutton_disabled:active .cke_menubutton_icon{background-color:#f8f8f8;outline:0}.cke_menuitem .cke_menubutton_on{background-color:#e9e9e9;border:1px solid #dedede;outline:0}.cke_menubutton_on .cke_menubutton_icon{padding-right:3px;background-color:#e9e9e9}.cke_menubutton_label{padding:0 5px;background-color:transparent;width:100%;vertical-align:middle}.cke_menubutton_shortcut{color:#979797}.cke_menubutton_disabled .cke_menubutton_label{opacity:.3;filter:alpha(opacity=30)}.cke_panel_frame .cke_menubutton_label{display:none}.cke_menuseparator{background-color:#d1d1d1;height:1px}.cke_menuarrow{background:transparent url(images/arrow.png) no-repeat 0 10px;padding:0 5px}.cke_rtl .cke_menuarrow{background-position:5px -13px;background-repeat:no-repeat}.cke_hc .cke_menuarrow{background-image:none}.cke_menuarrow span{display:none}.cke_hc .cke_menuarrow span{vertical-align:middle;display:inline}.cke_combo{display:inline-block;float:left;position:relative;margin-bottom:5px}.cke_rtl .cke_combo{float:right}.cke_hc .cke_combo{margin-top:1px;margin-bottom:10px}.cke_combo:after{content:"";position:absolute;height:18px;width:0;border-right:1px solid #bcbcbc;margin-top:5px;top:0;right:0}.cke_rtl .cke_combo:after{border-right:0;border-left:1px solid #bcbcbc;right:auto;left:0}.cke_hc .cke_combo:after{border-color:#000}a.cke_combo_button{cursor:default;display:inline-block;float:left;margin:0;padding:1px}.cke_rtl a.cke_combo_button{float:right}.cke_hc a.cke_combo_button{padding:4px}.cke_combo_on a.cke_combo_button,.cke_combo_off a.cke_combo_button:hover,.cke_combo_off a.cke_combo_button:focus,.cke_combo_off a.cke_combo_button:active{background:#e5e5e5;border:1px solid #bcbcbc;padding:0 0 0 1px;margin-left:-1px}.cke_combo_off a.cke_combo_button:focus{outline:0}.cke_combo_on a.cke_combo_button,.cke_combo_off a.cke_combo_button:active{background:#fff}.cke_rtl .cke_combo_on a.cke_combo_button,.cke_rtl .cke_combo_off a.cke_combo_button:hover,.cke_rtl .cke_combo_off a.cke_combo_button:focus,.cke_rtl .cke_combo_off a.cke_combo_button:active{padding:0 1px 0 0;margin-left:0;margin-right:-1px}.cke_hc .cke_combo_on a.cke_combo_button,.cke_hc .cke_combo_off a.cke_combo_button:hover,.cke_hc .cke_combo_off a.cke_combo_button:focus,.cke_hc .cke_combo_off a.cke_combo_button:active{border:3px solid #000;padding:1px 1px 1px 2px}.cke_hc.cke_rtl .cke_combo_on a.cke_combo_button,.cke_hc.cke_rtl .cke_combo_off a.cke_combo_button:hover,.cke_hc.cke_rtl .cke_combo_off a.cke_combo_button:focus,.cke_hc.cke_rtl .cke_combo_off a.cke_combo_button:active{padding:1px 2px 1px 1px}.cke_toolbar_start+.cke_combo_on a.cke_combo_button,.cke_toolbar_start+.cke_combo_off a.cke_combo_button:hover,.cke_toolbar_start+.cke_combo_off a.cke_combo_button:focus,.cke_toolbar_start+.cke_combo_off a.cke_combo_button:active{padding:0 0 0 3px;margin-left:-3px}.cke_rtl .cke_toolbar_start+.cke_combo_on a.cke_combo_button,.cke_rtl .cke_toolbar_start+.cke_combo_off a.cke_combo_button:hover,.cke_rtl .cke_toolbar_start+.cke_combo_off a.cke_combo_button:focus,.cke_rtl .cke_toolbar_start+.cke_combo_off a.cke_combo_button:active{padding:0 3px 0 0;margin-left:0;margin-right:-3px}.cke_hc .cke_toolbar>.cke_toolbar_start+.cke_combo_on a.cke_combo_button,.cke_hc .cke_toolbar>.cke_toolbar_start+.cke_combo_off a.cke_combo_button:hover,.cke_hc .cke_toolbar>.cke_toolbar_start+.cke_combo_off a.cke_combo_button:focus,.cke_hc .cke_toolbar>.cke_toolbar_start+.cke_combo_off a.cke_combo_button:active{padding:1px 1px 1px 7px;margin-left:-6px}.cke_hc.cke_rtl .cke_toolbar>.cke_toolbar_start+.cke_combo_on a.cke_combo_button,.cke_hc.cke_rtl .cke_toolbar>.cke_toolbar_start+.cke_combo_off a.cke_combo_button:hover,.cke_hc.cke_rtl .cke_toolbar>.cke_toolbar_start+.cke_combo_off a.cke_combo_button:focus,.cke_hc.cke_rtl .cke_toolbar>.cke_toolbar_start+.cke_combo_off a.cke_combo_button:active{padding:1px 7px 1px 1px;margin-left:0;margin-right:-6px}.cke_toolbox .cke_toolbar:first-child>.cke_toolbar_start+.cke_combo_on a.cke_combo_button,.cke_toolbox .cke_toolbar:first-child>.cke_toolbar_start+.cke_combo_off a.cke_combo_button:hover,.cke_toolbox .cke_toolbar:first-child>.cke_toolbar_start+.cke_combo_off a.cke_combo_button:focus,.cke_toolbox .cke_toolbar:first-child>.cke_toolbar_start+.cke_combo_off a.cke_combo_button:active,.cke_toolbar_break+.cke_toolbar>.cke_toolbar_start+.cke_combo_on a.cke_combo_button,.cke_toolbar_break+.cke_toolbar>.cke_toolbar_start+.cke_combo_off a.cke_combo_button:hover,.cke_toolbar_break+.cke_toolbar>.cke_toolbar_start+.cke_combo_off a.cke_combo_button:focus,.cke_toolbar_break+.cke_toolbar>.cke_toolbar_start+.cke_combo_off a.cke_combo_button:active{padding:0;margin:0}.cke_hc .cke_toolbox .cke_toolbar:first-child>.cke_toolbar_start+.cke_combo_on a.cke_combo_button,.cke_hc .cke_toolbox .cke_toolbar:first-child>.cke_toolbar_start+.cke_combo_off a.cke_combo_button:hover,.cke_hc .cke_toolbox .cke_toolbar:first-child>.cke_toolbar_start+.cke_combo_off a.cke_combo_button:focus,.cke_hc .cke_toolbox .cke_toolbar:first-child>.cke_toolbar_start+.cke_combo_off a.cke_combo_button:active,.cke_hc .cke_toolbar_break+.cke_toolbar>.cke_toolbar_start+.cke_combo_on a.cke_combo_button,.cke_hc .cke_toolbar_break+.cke_toolbar>.cke_toolbar_start+.cke_combo_off a.cke_combo_button:hover,.cke_hc .cke_toolbar_break+.cke_toolbar>.cke_toolbar_start+.cke_combo_off a.cke_combo_button:focus,.cke_hc .cke_toolbar_break+.cke_toolbar>.cke_toolbar_start+.cke_combo_off a.cke_combo_button:active{padding:1px;margin:0}.cke_toolbar .cke_combo+.cke_toolbar_end,.cke_toolbar .cke_combo+.cke_toolgroup{margin-right:0;margin-left:2px}.cke_rtl .cke_toolbar .cke_combo+.cke_toolbar_end,.cke_rtl .cke_toolbar .cke_combo+.cke_toolgroup{margin-left:0;margin-right:2px}.cke_hc .cke_toolbar .cke_combo+.cke_toolbar_end,.cke_hc .cke_toolbar .cke_combo+.cke_toolgroup{margin-left:5px}.cke_hc.cke_rtl .cke_toolbar .cke_combo+.cke_toolbar_end,.cke_hc.cke_rtl .cke_toolbar .cke_combo+.cke_toolgroup{margin-left:0;margin-right:5px}.cke_toolbar.cke_toolbar_last .cke_combo:nth-last-child(-n+2):after{content:none;border:0;width:0;height:0}.cke_combo_text{line-height:26px;padding-left:10px;text-overflow:ellipsis;overflow:hidden;float:left;cursor:default;color:#484848;width:60px}.cke_rtl .cke_combo_text{float:right;text-align:right;padding-left:0;padding-right:10px}.cke_hc .cke_combo_text{line-height:18px;font-size:12px}.cke_combo_open{cursor:default;display:inline-block;font-size:0;height:19px;line-height:17px;margin:1px 10px 1px;width:5px}.cke_hc .cke_combo_open{height:12px}.cke_combo_arrow{cursor:default;margin:11px 0 0;float:left;height:0;width:0;font-size:0;border-left:3px solid transparent;border-right:3px solid transparent;border-top:3px solid #484848}.cke_hc .cke_combo_arrow{font-size:10px;width:auto;border:0;margin-top:3px}.cke_combo_label{display:none;float:left;line-height:26px;vertical-align:top;margin-right:5px}.cke_rtl .cke_combo_label{float:right;margin-left:5px;margin-right:0}.cke_combo_disabled .cke_combo_inlinelabel,.cke_combo_disabled .cke_combo_open{opacity:.3}.cke_path{float:left;margin:-2px 0 2px}a.cke_path_item,span.cke_path_empty{display:inline-block;float:left;padding:3px 4px;margin-right:2px;cursor:default;text-decoration:none;outline:0;border:0;color:#484848;font-weight:bold;font-size:11px}.cke_rtl .cke_path,.cke_rtl .cke_path_item,.cke_rtl .cke_path_empty{float:right}a.cke_path_item:hover,a.cke_path_item:focus,a.cke_path_item:active{background-color:#e5e5e5}.cke_hc a.cke_path_item:hover,.cke_hc a.cke_path_item:focus,.cke_hc a.cke_path_item:active{border:2px solid;padding:1px 2px}.cke_button__source_label,.cke_button__sourcedialog_label{display:inline}.cke_combopanel__fontsize{width:135px}textarea.cke_source{font-family:'Courier New',Monospace;font-size:small;background-color:#fff;white-space:pre-wrap;border:0;padding:0;margin:0;display:block}.cke_wysiwyg_frame,.cke_wysiwyg_div{background-color:#fff}.cke_notifications_area{pointer-events:none}.cke_notification{pointer-events:auto;position:relative;margin:10px;width:300px;color:white;text-align:center;opacity:.95;filter:alpha(opacity = 95);-webkit-animation:fadeIn .7s;animation:fadeIn .7s}.cke_notification_message a{color:#12306f}@-webkit-keyframes fadeIn{from{opacity:.4}to{opacity:.95}}@keyframes fadeIn{from{opacity:.4}to{opacity:.95}}.cke_notification_success{background:#72b572;border:1px solid #63a563}.cke_notification_warning{background:#c83939;border:1px solid #902b2b}.cke_notification_info{background:#2e9ad0;border:1px solid #0f74a8}.cke_notification_info span.cke_notification_progress{background-color:#0f74a8;display:block;padding:0;margin:0;height:100%;overflow:hidden;position:absolute;z-index:1}.cke_notification_message{position:relative;margin:4px 23px 3px;font-family:Arial,Helvetica,sans-serif;font-size:12px;line-height:18px;z-index:4;text-overflow:ellipsis;overflow:hidden}.cke_notification_close{background-image:url(images/close.png);background-repeat:no-repeat;background-position:50%;position:absolute;cursor:pointer;text-align:center;height:20px;width:20px;top:1px;right:1px;padding:0;margin:0;z-index:5;opacity:.6;filter:alpha(opacity = 60)}.cke_notification_close:hover{opacity:1;filter:alpha(opacity = 100)}.cke_notification_close span{display:none}.cke_notification_warning a.cke_notification_close{opacity:.8;filter:alpha(opacity = 80)}.cke_notification_warning a.cke_notification_close:hover{opacity:1;filter:alpha(opacity = 100)}.cke_chrome{visibility:inherit}.cke_voice_label{display:none}legend.cke_voice_label{display:none}.cke_button__about_icon{background:url(icons.png?t=I8E8) no-repeat 0 -0px!important}.cke_button__bold_icon{background:url(icons.png?t=I8E8) no-repeat 0 -24px!important}.cke_button__italic_icon{background:url(icons.png?t=I8E8) no-repeat 0 -48px!important}.cke_button__strike_icon{background:url(icons.png?t=I8E8) no-repeat 0 -72px!important}.cke_button__subscript_icon{background:url(icons.png?t=I8E8) no-repeat 0 -96px!important}.cke_button__superscript_icon{background:url(icons.png?t=I8E8) no-repeat 0 -120px!important}.cke_button__underline_icon{background:url(icons.png?t=I8E8) no-repeat 0 -144px!important}.cke_button__blockquote_icon{background:url(icons.png?t=I8E8) no-repeat 0 -168px!important}.cke_rtl .cke_button__copy_icon,.cke_mixed_dir_content .cke_rtl .cke_button__copy_icon{background:url(icons.png?t=I8E8) no-repeat 0 -192px!important}.cke_ltr .cke_button__copy_icon{background:url(icons.png?t=I8E8) no-repeat 0 -216px!important}.cke_rtl .cke_button__cut_icon,.cke_mixed_dir_content .cke_rtl .cke_button__cut_icon{background:url(icons.png?t=I8E8) no-repeat 0 -240px!important}.cke_ltr .cke_button__cut_icon{background:url(icons.png?t=I8E8) no-repeat 0 -264px!important}.cke_rtl .cke_button__paste_icon,.cke_mixed_dir_content .cke_rtl .cke_button__paste_icon{background:url(icons.png?t=I8E8) no-repeat 0 -288px!important}.cke_ltr .cke_button__paste_icon{background:url(icons.png?t=I8E8) no-repeat 0 -312px!important}.cke_button__horizontalrule_icon{background:url(icons.png?t=I8E8) no-repeat 0 -336px!important}.cke_button__image_icon{background:url(icons.png?t=I8E8) no-repeat 0 -360px!important}.cke_rtl .cke_button__indent_icon,.cke_mixed_dir_content .cke_rtl .cke_button__indent_icon{background:url(icons.png?t=I8E8) no-repeat 0 -384px!important}.cke_ltr .cke_button__indent_icon{background:url(icons.png?t=I8E8) no-repeat 0 -408px!important}.cke_rtl .cke_button__outdent_icon,.cke_mixed_dir_content .cke_rtl .cke_button__outdent_icon{background:url(icons.png?t=I8E8) no-repeat 0 -432px!important}.cke_ltr .cke_button__outdent_icon{background:url(icons.png?t=I8E8) no-repeat 0 -456px!important}.cke_button__justifyblock_icon{background:url(icons.png?t=I8E8) no-repeat 0 -480px!important}.cke_button__justifycenter_icon{background:url(icons.png?t=I8E8) no-repeat 0 -504px!important}.cke_button__justifyleft_icon{background:url(icons.png?t=I8E8) no-repeat 0 -528px!important}.cke_button__justifyright_icon{background:url(icons.png?t=I8E8) no-repeat 0 -552px!important}.cke_button__language_icon{background:url(icons.png?t=I8E8) no-repeat 0 -576px!important}.cke_rtl .cke_button__bulletedlist_icon,.cke_mixed_dir_content .cke_rtl .cke_button__bulletedlist_icon{background:url(icons.png?t=I8E8) no-repeat 0 -600px!important}.cke_ltr .cke_button__bulletedlist_icon{background:url(icons.png?t=I8E8) no-repeat 0 -624px!important}.cke_rtl .cke_button__numberedlist_icon,.cke_mixed_dir_content .cke_rtl .cke_button__numberedlist_icon{background:url(icons.png?t=I8E8) no-repeat 0 -648px!important}.cke_ltr .cke_button__numberedlist_icon{background:url(icons.png?t=I8E8) no-repeat 0 -672px!important}.cke_button__maximize_icon{background:url(icons.png?t=I8E8) no-repeat 0 -696px!important}.cke_rtl .cke_button__pastefromword_icon,.cke_mixed_dir_content .cke_rtl .cke_button__pastefromword_icon{background:url(icons.png?t=I8E8) no-repeat 0 -720px!important}.cke_ltr .cke_button__pastefromword_icon{background:url(icons.png?t=I8E8) no-repeat 0 -744px!important}.cke_rtl .cke_button__pastetext_icon,.cke_mixed_dir_content .cke_rtl .cke_button__pastetext_icon{background:url(icons.png?t=I8E8) no-repeat 0 -768px!important}.cke_ltr .cke_button__pastetext_icon{background:url(icons.png?t=I8E8) no-repeat 0 -792px!important}.cke_button__removeformat_icon{background:url(icons.png?t=I8E8) no-repeat 0 -816px!important}.cke_rtl .cke_button__showblocks_icon,.cke_mixed_dir_content .cke_rtl .cke_button__showblocks_icon{background:url(icons.png?t=I8E8) no-repeat 0 -840px!important}.cke_ltr .cke_button__showblocks_icon{background:url(icons.png?t=I8E8) no-repeat 0 -864px!important}.cke_rtl .cke_button__source_icon,.cke_mixed_dir_content .cke_rtl .cke_button__source_icon{background:url(icons.png?t=I8E8) no-repeat 0 -888px!important}.cke_ltr .cke_button__source_icon{background:url(icons.png?t=I8E8) no-repeat 0 -912px!important}.cke_rtl .cke_button__sourcedialog_icon,.cke_mixed_dir_content .cke_rtl .cke_button__sourcedialog_icon{background:url(icons.png?t=I8E8) no-repeat 0 -936px!important}.cke_ltr .cke_button__sourcedialog_icon{background:url(icons.png?t=I8E8) no-repeat 0 -960px!important}.cke_button__specialchar_icon{background:url(icons.png?t=I8E8) no-repeat 0 -984px!important}.cke_button__table_icon{background:url(icons.png?t=I8E8) no-repeat 0 -1008px!important}.cke_rtl .cke_button__redo_icon,.cke_mixed_dir_content .cke_rtl .cke_button__redo_icon{background:url(icons.png?t=I8E8) no-repeat 0 -1032px!important}.cke_ltr .cke_button__redo_icon{background:url(icons.png?t=I8E8) no-repeat 0 -1056px!important}.cke_rtl .cke_button__undo_icon,.cke_mixed_dir_content .cke_rtl .cke_button__undo_icon{background:url(icons.png?t=I8E8) no-repeat 0 -1080px!important}.cke_ltr .cke_button__undo_icon{background:url(icons.png?t=I8E8) no-repeat 0 -1104px!important}.cke_button__simplebox_icon{background:url(icons.png?t=I8E8) no-repeat 0 -1128px!important}.cke_hidpi .cke_button__about_icon{background:url(icons_hidpi.png?t=I8E8) no-repeat 0 -0px!important;background-size:16px!important}.cke_hidpi .cke_button__bold_icon{background:url(icons_hidpi.png?t=I8E8) no-repeat 0 -24px!important;background-size:16px!important}.cke_hidpi .cke_button__italic_icon{background:url(icons_hidpi.png?t=I8E8) no-repeat 0 -48px!important;background-size:16px!important}.cke_hidpi .cke_button__strike_icon{background:url(icons_hidpi.png?t=I8E8) no-repeat 0 -72px!important;background-size:16px!important}.cke_hidpi .cke_button__subscript_icon{background:url(icons_hidpi.png?t=I8E8) no-repeat 0 -96px!important;background-size:16px!important}.cke_hidpi .cke_button__superscript_icon{background:url(icons_hidpi.png?t=I8E8) no-repeat 0 -120px!important;background-size:16px!important}.cke_hidpi .cke_button__underline_icon{background:url(icons_hidpi.png?t=I8E8) no-repeat 0 -144px!important;background-size:16px!important}.cke_hidpi .cke_button__blockquote_icon{background:url(icons_hidpi.png?t=I8E8) no-repeat 0 -168px!important;background-size:16px!important}.cke_rtl.cke_hidpi .cke_button__copy_icon,.cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__copy_icon{background:url(icons_hidpi.png?t=I8E8) no-repeat 0 -192px!important;background-size:16px!important}.cke_hidpi .cke_ltr .cke_button__copy_icon,.cke_ltr.cke_hidpi .cke_button__copy_icon{background:url(icons_hidpi.png?t=I8E8) no-repeat 0 -216px!important;background-size:16px!important}.cke_rtl.cke_hidpi .cke_button__cut_icon,.cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__cut_icon{background:url(icons_hidpi.png?t=I8E8) no-repeat 0 -240px!important;background-size:16px!important}.cke_hidpi .cke_ltr .cke_button__cut_icon,.cke_ltr.cke_hidpi .cke_button__cut_icon{background:url(icons_hidpi.png?t=I8E8) no-repeat 0 -264px!important;background-size:16px!important}.cke_rtl.cke_hidpi .cke_button__paste_icon,.cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__paste_icon{background:url(icons_hidpi.png?t=I8E8) no-repeat 0 -288px!important;background-size:16px!important}.cke_hidpi .cke_ltr .cke_button__paste_icon,.cke_ltr.cke_hidpi .cke_button__paste_icon{background:url(icons_hidpi.png?t=I8E8) no-repeat 0 -312px!important;background-size:16px!important}.cke_hidpi .cke_button__horizontalrule_icon{background:url(icons_hidpi.png?t=I8E8) no-repeat 0 -336px!important;background-size:16px!important}.cke_hidpi .cke_button__image_icon{background:url(icons_hidpi.png?t=I8E8) no-repeat 0 -360px!important;background-size:16px!important}.cke_rtl.cke_hidpi .cke_button__indent_icon,.cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__indent_icon{background:url(icons_hidpi.png?t=I8E8) no-repeat 0 -384px!important;background-size:16px!important}.cke_hidpi .cke_ltr .cke_button__indent_icon,.cke_ltr.cke_hidpi .cke_button__indent_icon{background:url(icons_hidpi.png?t=I8E8) no-repeat 0 -408px!important;background-size:16px!important}.cke_rtl.cke_hidpi .cke_button__outdent_icon,.cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__outdent_icon{background:url(icons_hidpi.png?t=I8E8) no-repeat 0 -432px!important;background-size:16px!important}.cke_hidpi .cke_ltr .cke_button__outdent_icon,.cke_ltr.cke_hidpi .cke_button__outdent_icon{background:url(icons_hidpi.png?t=I8E8) no-repeat 0 -456px!important;background-size:16px!important}.cke_hidpi .cke_button__justifyblock_icon{background:url(icons_hidpi.png?t=I8E8) no-repeat 0 -480px!important;background-size:16px!important}.cke_hidpi .cke_button__justifycenter_icon{background:url(icons_hidpi.png?t=I8E8) no-repeat 0 -504px!important;background-size:16px!important}.cke_hidpi .cke_button__justifyleft_icon{background:url(icons_hidpi.png?t=I8E8) no-repeat 0 -528px!important;background-size:16px!important}.cke_hidpi .cke_button__justifyright_icon{background:url(icons_hidpi.png?t=I8E8) no-repeat 0 -552px!important;background-size:16px!important}.cke_hidpi .cke_button__language_icon{background:url(icons_hidpi.png?t=I8E8) no-repeat 0 -576px!important;background-size:16px!important}.cke_rtl.cke_hidpi .cke_button__bulletedlist_icon,.cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__bulletedlist_icon{background:url(icons_hidpi.png?t=I8E8) no-repeat 0 -600px!important;background-size:16px!important}.cke_hidpi .cke_ltr .cke_button__bulletedlist_icon,.cke_ltr.cke_hidpi .cke_button__bulletedlist_icon{background:url(icons_hidpi.png?t=I8E8) no-repeat 0 -624px!important;background-size:16px!important}.cke_rtl.cke_hidpi .cke_button__numberedlist_icon,.cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__numberedlist_icon{background:url(icons_hidpi.png?t=I8E8) no-repeat 0 -648px!important;background-size:16px!important}.cke_hidpi .cke_ltr .cke_button__numberedlist_icon,.cke_ltr.cke_hidpi .cke_button__numberedlist_icon{background:url(icons_hidpi.png?t=I8E8) no-repeat 0 -672px!important;background-size:16px!important}.cke_hidpi .cke_button__maximize_icon{background:url(icons_hidpi.png?t=I8E8) no-repeat 0 -696px!important;background-size:16px!important}.cke_rtl.cke_hidpi .cke_button__pastefromword_icon,.cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__pastefromword_icon{background:url(icons_hidpi.png?t=I8E8) no-repeat 0 -720px!important;background-size:16px!important}.cke_hidpi .cke_ltr .cke_button__pastefromword_icon,.cke_ltr.cke_hidpi .cke_button__pastefromword_icon{background:url(icons_hidpi.png?t=I8E8) no-repeat 0 -744px!important;background-size:16px!important}.cke_rtl.cke_hidpi .cke_button__pastetext_icon,.cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__pastetext_icon{background:url(icons_hidpi.png?t=I8E8) no-repeat 0 -768px!important;background-size:16px!important}.cke_hidpi .cke_ltr .cke_button__pastetext_icon,.cke_ltr.cke_hidpi .cke_button__pastetext_icon{background:url(icons_hidpi.png?t=I8E8) no-repeat 0 -792px!important;background-size:16px!important}.cke_hidpi .cke_button__removeformat_icon{background:url(icons_hidpi.png?t=I8E8) no-repeat 0 -816px!important;background-size:16px!important}.cke_rtl.cke_hidpi .cke_button__showblocks_icon,.cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__showblocks_icon{background:url(icons_hidpi.png?t=I8E8) no-repeat 0 -840px!important;background-size:16px!important}.cke_hidpi .cke_ltr .cke_button__showblocks_icon,.cke_ltr.cke_hidpi .cke_button__showblocks_icon{background:url(icons_hidpi.png?t=I8E8) no-repeat 0 -864px!important;background-size:16px!important}.cke_rtl.cke_hidpi .cke_button__source_icon,.cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__source_icon{background:url(icons_hidpi.png?t=I8E8) no-repeat 0 -888px!important;background-size:16px!important}.cke_hidpi .cke_ltr .cke_button__source_icon,.cke_ltr.cke_hidpi .cke_button__source_icon{background:url(icons_hidpi.png?t=I8E8) no-repeat 0 -912px!important;background-size:16px!important}.cke_rtl.cke_hidpi .cke_button__sourcedialog_icon,.cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__sourcedialog_icon{background:url(icons_hidpi.png?t=I8E8) no-repeat 0 -936px!important;background-size:16px!important}.cke_hidpi .cke_ltr .cke_button__sourcedialog_icon,.cke_ltr.cke_hidpi .cke_button__sourcedialog_icon{background:url(icons_hidpi.png?t=I8E8) no-repeat 0 -960px!important;background-size:16px!important}.cke_hidpi .cke_button__specialchar_icon{background:url(icons_hidpi.png?t=I8E8) no-repeat 0 -984px!important;background-size:16px!important}.cke_hidpi .cke_button__table_icon{background:url(icons_hidpi.png?t=I8E8) no-repeat 0 -1008px!important;background-size:16px!important}.cke_rtl.cke_hidpi .cke_button__redo_icon,.cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__redo_icon{background:url(icons_hidpi.png?t=I8E8) no-repeat 0 -1032px!important;background-size:16px!important}.cke_hidpi .cke_ltr .cke_button__redo_icon,.cke_ltr.cke_hidpi .cke_button__redo_icon{background:url(icons_hidpi.png?t=I8E8) no-repeat 0 -1056px!important;background-size:16px!important}.cke_rtl.cke_hidpi .cke_button__undo_icon,.cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__undo_icon{background:url(icons_hidpi.png?t=I8E8) no-repeat 0 -1080px!important;background-size:16px!important}.cke_hidpi .cke_ltr .cke_button__undo_icon,.cke_ltr.cke_hidpi .cke_button__undo_icon{background:url(icons_hidpi.png?t=I8E8) no-repeat 0 -1104px!important;background-size:16px!important}.cke_hidpi .cke_button__simplebox_icon{background:url(icons_hidpi.png?t=I8E8) no-repeat 0 -2256px!important}a.cke_button_disabled,a.cke_button_disabled:hover,a.cke_button_disabled:focus,a.cke_button_disabled:active{filter:alpha(opacity = 30)}.cke_button_disabled .cke_button_icon{filter:progid:DXImageTransform.Microsoft.gradient(startColorstr=#00ffffff,endColorstr=#00ffffff)}.cke_button_off:hover,.cke_button_off:focus,.cke_button_off:active{filter:alpha(opacity = 100)}.cke_combo_disabled .cke_combo_inlinelabel,.cke_combo_disabled .cke_combo_open{filter:alpha(opacity = 30)}.cke_toolbox_collapser{border:1px solid #a6a6a6}.cke_toolbox_collapser .cke_arrow{margin-top:1px}.cke_hc .cke_top,.cke_hc .cke_bottom,.cke_hc .cke_combo_button,.cke_hc a.cke_combo_button:hover,.cke_hc a.cke_combo_button:focus,.cke_hc .cke_toolgroup,.cke_hc .cke_button_on,.cke_hc a.cke_button_off:hover,.cke_hc a.cke_button_off:focus,.cke_hc a.cke_button_off:active,.cke_hc .cke_toolbox_collapser,.cke_hc .cke_toolbox_collapser:hover,.cke_hc .cke_panel_grouptitle{filter:progid:DXImageTransform.Microsoft.gradient(enabled=false)}.cke_toolbox_collapser .cke_arrow{border-width:4px}.cke_toolbox_collapser.cke_toolbox_collapser_min .cke_arrow{border-width:3px}.cke_toolbox_collapser .cke_arrow{margin-top:0}.cke_toolbar{position:relative}.cke_rtl .cke_toolbar_end{right:auto;left:0}.cke_toolbar_end:after{content:"";position:absolute;height:18px;width:0;border-right:1px solid #bcbcbc;margin-top:4px;top:1px;right:2px}.cke_rtl .cke_toolbar_end:after{right:auto;left:2px}.cke_hc .cke_toolbar_end:after{top:2px;right:5px;border-color:#000}.cke_hc.cke_rtl .cke_toolbar_end:after{right:auto;left:5px}.cke_combo+.cke_toolbar_end:after,.cke_toolbar.cke_toolbar_last .cke_toolbar_end:after{content:none;border:0}.cke_combo+.cke_toolgroup+.cke_toolbar_end:after{right:0}.cke_rtl .cke_combo+.cke_toolgroup+.cke_toolbar_end:after{right:auto;left:0} \ No newline at end of file diff --git a/web/core/assets/vendor/ckeditor/skins/moono-lisa/editor_iequirks.css b/web/core/assets/vendor/ckeditor/skins/moono-lisa/editor_iequirks.css index b8e2ffdb15cfa8294566026d340f3c66f34e7bf8..ea37062486c36b253134839650a05dacbdc70aff 100644 --- a/web/core/assets/vendor/ckeditor/skins/moono-lisa/editor_iequirks.css +++ b/web/core/assets/vendor/ckeditor/skins/moono-lisa/editor_iequirks.css @@ -2,4 +2,4 @@ Copyright (c) 2003-2018, CKSource - Frederico Knabben. All rights reserved. For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license */ -.cke_reset{margin:0;padding:0;border:0;background:transparent;text-decoration:none;width:auto;height:auto;vertical-align:baseline;box-sizing:content-box;position:static;transition:none}.cke_reset_all,.cke_reset_all *,.cke_reset_all a,.cke_reset_all textarea{margin:0;padding:0;border:0;background:transparent;text-decoration:none;width:auto;height:auto;vertical-align:baseline;box-sizing:content-box;position:static;transition:none;border-collapse:collapse;font:normal normal normal 12px Arial,Helvetica,Tahoma,Verdana,Sans-Serif;color:#000;text-align:left;white-space:nowrap;cursor:auto;float:none}.cke_reset_all .cke_rtl *{text-align:right}.cke_reset_all iframe{vertical-align:inherit}.cke_reset_all textarea{white-space:pre-wrap}.cke_reset_all textarea,.cke_reset_all input[type="text"],.cke_reset_all input[type="password"]{cursor:text}.cke_reset_all textarea[disabled],.cke_reset_all input[type="text"][disabled],.cke_reset_all input[type="password"][disabled]{cursor:default}.cke_reset_all fieldset{padding:10px;border:2px groove #e0dfe3}.cke_reset_all select{box-sizing:border-box}.cke_reset_all table{table-layout:auto}.cke_chrome{display:block;border:1px solid #d1d1d1;padding:0}.cke_inner{display:block;background:#fff;padding:0;-webkit-touch-callout:none}.cke_float{border:0}.cke_float .cke_inner{padding-bottom:0}.cke_top,.cke_contents,.cke_bottom{display:block;overflow:hidden}.cke_top{border-bottom:1px solid #d1d1d1;background:#f8f8f8;padding:6px 8px 2px;white-space:normal}.cke_float .cke_top{border:1px solid #d1d1d1}.cke_bottom{padding:6px 8px 2px;position:relative;border-top:1px solid #d1d1d1;background:#f8f8f8}.cke_browser_ios .cke_contents{overflow-y:auto;-webkit-overflow-scrolling:touch}.cke_resizer{width:0;height:0;overflow:hidden;border-width:10px 10px 0 0;border-color:transparent #bcbcbc transparent transparent;border-style:dashed solid dashed dashed;font-size:0;vertical-align:bottom;margin-top:6px;margin-bottom:2px}.cke_hc .cke_resizer{font-size:15px;width:auto;height:auto;border-width:0}.cke_resizer_ltr{cursor:se-resize;float:right;margin-right:-4px}.cke_resizer_rtl{border-width:10px 0 0 10px;border-color:transparent transparent transparent #bcbcbc;border-style:dashed dashed dashed solid;cursor:sw-resize;float:left;margin-left:-4px;right:auto}.cke_wysiwyg_div{display:block;height:100%;overflow:auto;padding:0 8px;outline-style:none;box-sizing:border-box}.cke_panel{visibility:visible;width:120px;height:100px;overflow:hidden;background-color:#fff;border:1px solid #d1d1d1}.cke_menu_panel{padding:0;margin:0}.cke_combopanel{width:150px;height:170px}.cke_panel_frame{width:100%;height:100%;font-size:12px;overflow:auto;overflow-x:hidden}.cke_panel_container{overflow-y:auto;overflow-x:hidden}.cke_panel_block:focus{outline:0}.cke_panel_list{margin:0;padding:0;list-style-type:none;white-space:nowrap}.cke_panel_listItem{margin:0;padding:0}.cke_panel_listItem a{padding:6px 7px;display:block;color:inherit!important;text-decoration:none;overflow:hidden;text-overflow:ellipsis}.cke_hc .cke_panel_listItem a{border-style:none}.cke_panel_listItem.cke_selected a,.cke_panel_listItem a:hover,.cke_panel_listItem a:focus,.cke_panel_listItem a:active{background-color:#e9e9e9}.cke_panel_listItem a:focus{outline:1px dotted #000}.cke_hc .cke_panel_listItem a:hover,.cke_hc .cke_panel_listItem a:focus,.cke_hc .cke_panel_listItem a:active{border:2px solid;padding:4px 5px}.cke_panel_listItem p,.cke_panel_listItem h1,.cke_panel_listItem h2,.cke_panel_listItem h3,.cke_panel_listItem h4,.cke_panel_listItem h5,.cke_panel_listItem h6,.cke_panel_listItem pre{margin-top:0;margin-bottom:0}.cke_panel_grouptitle{cursor:default;font-size:11px;font-weight:bold;white-space:nowrap;margin:0;padding:6px 6px 7px 6px;color:#484848;border-bottom:1px solid #d1d1d1;background:#f8f8f8}.cke_colorblock{padding:10px;font-size:11px;font-family:'Microsoft Sans Serif',Tahoma,Arial,Verdana,Sans-Serif}.cke_colorblock,.cke_colorblock a{text-decoration:none;color:#000}a.cke_colorbox{padding:2px;float:left;width:20px;height:20px}.cke_rtl a.cke_colorbox{float:right}a:hover.cke_colorbox,a:focus.cke_colorbox,a:active.cke_colorbox{outline:0;padding:0;border:2px solid #139ff7}a:hover.cke_colorbox{border-color:#bcbcbc}span.cke_colorbox{width:20px;height:20px;float:left}.cke_rtl span.cke_colorbox{float:right}a.cke_colorauto,a.cke_colormore{border:#fff 1px solid;padding:3px;display:block;cursor:pointer}a.cke_colorauto{padding:0;border:1px solid transparent;margin-bottom:6px;height:26px;line-height:26px}a.cke_colormore{margin-top:10px;height:20px;line-height:19px}a:hover.cke_colorauto,a:hover.cke_colormore,a:focus.cke_colorauto,a:focus.cke_colormore,a:active.cke_colorauto,a:active.cke_colormore{outline:0;border:#139ff7 1px solid;background-color:#f8f8f8}a:hover.cke_colorauto,a:hover.cke_colormore{border-color:#bcbcbc}.cke_colorauto span.cke_colorbox{width:18px;height:18px;border:1px solid #808080;margin-left:1px;margin-top:3px}.cke_rtl .cke_colorauto span.cke_colorbox{margin-left:0;margin-right:1px}span.cke_colorbox[style*="#ffffff"],span.cke_colorbox[style*="#FFFFFF"],span.cke_colorbox[style="background-color:#fff"],span.cke_colorbox[style="background-color:#FFF"],span.cke_colorbox[style*="rgb(255,255,255)"],span.cke_colorbox[style*="rgb(255, 255, 255)"]{border:1px solid #808080;width:18px;height:18px}.cke_toolbar{float:left}.cke_rtl .cke_toolbar{float:right}.cke_toolgroup{border:0;float:left;margin:1px 2px 6px 0;padding-right:3px}.cke_rtl .cke_toolgroup{float:right;margin:1px 0 6px 2px;padding-left:3px;padding-right:0}.cke_hc .cke_toolgroup{margin-right:5px;margin-bottom:5px}.cke_hc.cke_rtl .cke_toolgroup{margin-right:0;margin-left:5px}a.cke_button{display:inline-block;height:18px;padding:4px 6px;outline:0;cursor:default;float:left;border:0;position:relative}.cke_rtl a.cke_button{float:right}.cke_hc a.cke_button{border:1px solid black;padding:3px 5px;margin:0 3px 5px 0}.cke_hc.cke_rtl a.cke_button{margin:0 0 5px 3px}a.cke_button_on{background:#fff;border:1px #bcbcbc solid;padding:3px 5px}a.cke_button_off:hover,a.cke_button_off:focus,a.cke_button_off:active{background:#e5e5e5;border:1px #bcbcbc solid;padding:3px 5px}.cke_hc a.cke_button_on,.cke_hc a.cke_button_off:hover,.cke_hc a.cke_button_off:focus,.cke_hc a.cke_button_off:active{background:#e5e5e5;border:3px solid #000;padding:1px 3px}a.cke_button_disabled:hover,a.cke_button_disabled:focus,a.cke_button_disabled:active{border:0;padding:4px 6px;background-color:transparent}a.cke_button_disabled:focus{border:1px #bcbcbc solid;padding:3px 5px}.cke_hc a.cke_button_disabled:hover,.cke_hc a.cke_button_disabled:focus,.cke_hc a.cke_button_disabled:active{border:1px solid #acacac;padding:3px 5px;margin:0 3px 5px 0}.cke_hc a.cke_button_disabled:focus{border:3px solid #000;padding:1px 3px}.cke_hc.cke_rtl a.cke_button_disabled:hover,.cke_hc.cke_rtl a.cke_button_disabled:focus,.cke_hc.cke_rtl a.cke_button_disabled:active{margin:0 0 5px 3px}a.cke_button_disabled .cke_button_icon,a.cke_button_disabled .cke_button_arrow{opacity:.3}.cke_hc a.cke_button_disabled{border-color:#acacac}.cke_hc a.cke_button_disabled .cke_button_icon,.cke_hc a.cke_button_disabled .cke_button_label{opacity:.5}.cke_toolgroup a.cke_button:last-child:after,.cke_toolgroup a.cke_button.cke_button_disabled:hover:last-child:after{content:"";position:absolute;height:18px;width:0;border-right:1px solid #bcbcbc;margin-top:4px;top:0;right:-3px}.cke_rtl .cke_toolgroup a.cke_button:last-child:after,.cke_rtl .cke_toolgroup a.cke_button.cke_button_disabled:hover:last-child:after{border-right:0;right:auto;border-left:1px solid #bcbcbc;top:0;left:-3px}.cke_hc .cke_toolgroup a.cke_button:last-child:after,.cke_hc .cke_toolgroup a.cke_button.cke_button_disabled:last-child:after,.cke_hc .cke_toolgroup a.cke_button.cke_button_disabled:hover:last-child:after{border-color:#000;top:0;right:-7px}.cke_hc.cke_rtl .cke_toolgroup a.cke_button:last-child:after,.cke_hc.cke_rtl .cke_toolgroup a.cke_button.cke_button_disabled:last-child:after,.cke_hc.cke_rtl .cke_toolgroup a.cke_button.cke_button_disabled:hover:last-child:after{top:0;right:auto;left:-7px}.cke_toolgroup a.cke_button:hover:last-child:after,.cke_toolgroup a.cke_button.cke_button_on:last-child:after{top:-1px;right:-4px}.cke_rtl .cke_toolgroup a.cke_button:hover:last-child:after,.cke_rtl .cke_toolgroup a.cke_button.cke_button_on:last-child:after{top:-1px;right:auto;left:-4px}.cke_hc .cke_toolgroup a.cke_button:hover:last-child:after,.cke_hc .cke_toolgroup a.cke_button.cke_button_on:last-child:after{top:-2px;right:-9px}.cke_hc.cke_rtl .cke_toolgroup a.cke_button:hover:last-child:after,.cke_hc.cke_rtl .cke_toolgroup a.cke_button.cke_button_on:last-child:after{top:-2px;right:auto;left:-9px}.cke_toolbar.cke_toolbar_last .cke_toolgroup a.cke_button:last-child:after{content:none;border:0;width:0;height:0}.cke_button_icon{cursor:inherit;background-repeat:no-repeat;margin-top:1px;width:16px;height:16px;float:left;display:inline-block}.cke_rtl .cke_button_icon{float:right}.cke_hc .cke_button_icon{display:none}.cke_button_label{display:none;padding-left:3px;margin-top:1px;line-height:17px;vertical-align:middle;float:left;cursor:default;color:#484848}.cke_rtl .cke_button_label{padding-right:3px;padding-left:0;float:right}.cke_hc .cke_button_label{padding:0;display:inline-block;font-size:12px}.cke_button_arrow{display:inline-block;margin:8px 0 0 1px;width:0;height:0;cursor:default;vertical-align:top;border-left:3px solid transparent;border-right:3px solid transparent;border-top:3px solid #484848}.cke_rtl .cke_button_arrow{margin-right:5px;margin-left:0}.cke_hc .cke_button_arrow{font-size:10px;margin:3px 0 0 3px;width:auto;border:0}.cke_toolbar_separator{float:left;background-color:#bcbcbc;margin:4px 2px 0 2px;height:18px;width:1px}.cke_rtl .cke_toolbar_separator{float:right}.cke_hc .cke_toolbar_separator{background-color:#000;margin-left:2px;margin-right:5px;margin-bottom:9px}.cke_hc.cke_rtl .cke_toolbar_separator{margin-left:5px;margin-right:2px}.cke_toolbar_break{display:block;clear:left}.cke_rtl .cke_toolbar_break{clear:right}a.cke_toolbox_collapser{width:12px;height:11px;float:right;margin:11px 0 0;font-size:0;cursor:default;text-align:center;border:1px solid #bcbcbc}.cke_rtl .cke_toolbox_collapser{float:left}.cke_toolbox_collapser:hover{background:#e5e5e5}.cke_toolbox_collapser.cke_toolbox_collapser_min{margin:0 2px 4px}.cke_toolbox_collapser .cke_arrow{display:inline-block;height:0;width:0;font-size:0;margin-top:1px;border:3px solid transparent;border-bottom-color:#484848}.cke_toolbox_collapser.cke_toolbox_collapser_min .cke_arrow{margin-top:4px;border-bottom-color:transparent;border-top-color:#484848}.cke_hc .cke_toolbox_collapser .cke_arrow{font-size:8px;width:auto;border:0;margin-top:0}.cke_menuitem span{cursor:default}.cke_menubutton{display:block}.cke_hc .cke_menubutton{padding:2px}.cke_menubutton:hover,.cke_menubutton:focus,.cke_menubutton:active{background-color:#e9e9e9;display:block;outline:1px dotted}.cke_menubutton:hover{outline:0}.cke_hc .cke_menubutton:hover,.cke_hc .cke_menubutton:focus,.cke_hc .cke_menubutton:active{border:2px solid;padding:0}.cke_menubutton_disabled:hover,.cke_menubutton_disabled:focus,.cke_menubutton_disabled:active{background-color:transparent;outline:0}.cke_menubutton_inner{display:table-row}.cke_menubutton_icon,.cke_menubutton_label,.cke_menuarrow{display:table-cell}.cke_menubutton_icon{background-color:#f8f8f8;padding:6px 4px}.cke_hc .cke_menubutton_icon{height:16px;width:0;padding:4px 0}.cke_menubutton:hover .cke_menubutton_icon,.cke_menubutton:focus .cke_menubutton_icon,.cke_menubutton:active .cke_menubutton_icon{background-color:#e9e9e9}.cke_menubutton_disabled:hover .cke_menubutton_icon,.cke_menubutton_disabled:focus .cke_menubutton_icon,.cke_menubutton_disabled:active .cke_menubutton_icon{background-color:#f8f8f8;outline:0}.cke_menuitem .cke_menubutton_on{background-color:#e9e9e9;border:1px solid #dedede;outline:0}.cke_menubutton_on .cke_menubutton_icon{padding-right:3px;background-color:#e9e9e9}.cke_menubutton_label{padding:0 5px;background-color:transparent;width:100%;vertical-align:middle}.cke_menubutton_shortcut{color:#979797}.cke_menubutton_disabled .cke_menubutton_label{opacity:.3;filter:alpha(opacity=30)}.cke_panel_frame .cke_menubutton_label{display:none}.cke_menuseparator{background-color:#d1d1d1;height:1px}.cke_menuarrow{background:transparent url(images/arrow.png) no-repeat 0 10px;padding:0 5px}.cke_rtl .cke_menuarrow{background-position:5px -13px;background-repeat:no-repeat}.cke_hc .cke_menuarrow{background-image:none}.cke_menuarrow span{display:none}.cke_hc .cke_menuarrow span{vertical-align:middle;display:inline}.cke_combo{display:inline-block;float:left;position:relative;margin-bottom:5px}.cke_rtl .cke_combo{float:right}.cke_hc .cke_combo{margin-top:1px;margin-bottom:10px}.cke_combo:after{content:"";position:absolute;height:18px;width:0;border-right:1px solid #bcbcbc;margin-top:5px;top:0;right:0}.cke_rtl .cke_combo:after{border-right:0;border-left:1px solid #bcbcbc;right:auto;left:0}.cke_hc .cke_combo:after{border-color:#000}a.cke_combo_button{cursor:default;display:inline-block;float:left;margin:0;padding:1px}.cke_rtl a.cke_combo_button{float:right}.cke_hc a.cke_combo_button{padding:4px}.cke_combo_on a.cke_combo_button,.cke_combo_off a.cke_combo_button:hover,.cke_combo_off a.cke_combo_button:focus,.cke_combo_off a.cke_combo_button:active{background:#e5e5e5;border:1px solid #bcbcbc;padding:0 0 0 1px;margin-left:-1px}.cke_combo_off a.cke_combo_button:focus{outline:0}.cke_combo_on a.cke_combo_button,.cke_combo_off a.cke_combo_button:active{background:#fff}.cke_rtl .cke_combo_on a.cke_combo_button,.cke_rtl .cke_combo_off a.cke_combo_button:hover,.cke_rtl .cke_combo_off a.cke_combo_button:focus,.cke_rtl .cke_combo_off a.cke_combo_button:active{padding:0 1px 0 0;margin-left:0;margin-right:-1px}.cke_hc .cke_combo_on a.cke_combo_button,.cke_hc .cke_combo_off a.cke_combo_button:hover,.cke_hc .cke_combo_off a.cke_combo_button:focus,.cke_hc .cke_combo_off a.cke_combo_button:active{border:3px solid #000;padding:1px 1px 1px 2px}.cke_hc.cke_rtl .cke_combo_on a.cke_combo_button,.cke_hc.cke_rtl .cke_combo_off a.cke_combo_button:hover,.cke_hc.cke_rtl .cke_combo_off a.cke_combo_button:focus,.cke_hc.cke_rtl .cke_combo_off a.cke_combo_button:active{padding:1px 2px 1px 1px}.cke_toolbar_start+.cke_combo_on a.cke_combo_button,.cke_toolbar_start+.cke_combo_off a.cke_combo_button:hover,.cke_toolbar_start+.cke_combo_off a.cke_combo_button:focus,.cke_toolbar_start+.cke_combo_off a.cke_combo_button:active{padding:0 0 0 3px;margin-left:-3px}.cke_rtl .cke_toolbar_start+.cke_combo_on a.cke_combo_button,.cke_rtl .cke_toolbar_start+.cke_combo_off a.cke_combo_button:hover,.cke_rtl .cke_toolbar_start+.cke_combo_off a.cke_combo_button:focus,.cke_rtl .cke_toolbar_start+.cke_combo_off a.cke_combo_button:active{padding:0 3px 0 0;margin-left:0;margin-right:-3px}.cke_hc .cke_toolbar>.cke_toolbar_start+.cke_combo_on a.cke_combo_button,.cke_hc .cke_toolbar>.cke_toolbar_start+.cke_combo_off a.cke_combo_button:hover,.cke_hc .cke_toolbar>.cke_toolbar_start+.cke_combo_off a.cke_combo_button:focus,.cke_hc .cke_toolbar>.cke_toolbar_start+.cke_combo_off a.cke_combo_button:active{padding:1px 1px 1px 7px;margin-left:-6px}.cke_hc.cke_rtl .cke_toolbar>.cke_toolbar_start+.cke_combo_on a.cke_combo_button,.cke_hc.cke_rtl .cke_toolbar>.cke_toolbar_start+.cke_combo_off a.cke_combo_button:hover,.cke_hc.cke_rtl .cke_toolbar>.cke_toolbar_start+.cke_combo_off a.cke_combo_button:focus,.cke_hc.cke_rtl .cke_toolbar>.cke_toolbar_start+.cke_combo_off a.cke_combo_button:active{padding:1px 7px 1px 1px;margin-left:0;margin-right:-6px}.cke_toolbox .cke_toolbar:first-child>.cke_toolbar_start+.cke_combo_on a.cke_combo_button,.cke_toolbox .cke_toolbar:first-child>.cke_toolbar_start+.cke_combo_off a.cke_combo_button:hover,.cke_toolbox .cke_toolbar:first-child>.cke_toolbar_start+.cke_combo_off a.cke_combo_button:focus,.cke_toolbox .cke_toolbar:first-child>.cke_toolbar_start+.cke_combo_off a.cke_combo_button:active,.cke_toolbar_break+.cke_toolbar>.cke_toolbar_start+.cke_combo_on a.cke_combo_button,.cke_toolbar_break+.cke_toolbar>.cke_toolbar_start+.cke_combo_off a.cke_combo_button:hover,.cke_toolbar_break+.cke_toolbar>.cke_toolbar_start+.cke_combo_off a.cke_combo_button:focus,.cke_toolbar_break+.cke_toolbar>.cke_toolbar_start+.cke_combo_off a.cke_combo_button:active{padding:0;margin:0}.cke_hc .cke_toolbox .cke_toolbar:first-child>.cke_toolbar_start+.cke_combo_on a.cke_combo_button,.cke_hc .cke_toolbox .cke_toolbar:first-child>.cke_toolbar_start+.cke_combo_off a.cke_combo_button:hover,.cke_hc .cke_toolbox .cke_toolbar:first-child>.cke_toolbar_start+.cke_combo_off a.cke_combo_button:focus,.cke_hc .cke_toolbox .cke_toolbar:first-child>.cke_toolbar_start+.cke_combo_off a.cke_combo_button:active,.cke_hc .cke_toolbar_break+.cke_toolbar>.cke_toolbar_start+.cke_combo_on a.cke_combo_button,.cke_hc .cke_toolbar_break+.cke_toolbar>.cke_toolbar_start+.cke_combo_off a.cke_combo_button:hover,.cke_hc .cke_toolbar_break+.cke_toolbar>.cke_toolbar_start+.cke_combo_off a.cke_combo_button:focus,.cke_hc .cke_toolbar_break+.cke_toolbar>.cke_toolbar_start+.cke_combo_off a.cke_combo_button:active{padding:1px;margin:0}.cke_toolbar .cke_combo+.cke_toolbar_end,.cke_toolbar .cke_combo+.cke_toolgroup{margin-right:0;margin-left:2px}.cke_rtl .cke_toolbar .cke_combo+.cke_toolbar_end,.cke_rtl .cke_toolbar .cke_combo+.cke_toolgroup{margin-left:0;margin-right:2px}.cke_hc .cke_toolbar .cke_combo+.cke_toolbar_end,.cke_hc .cke_toolbar .cke_combo+.cke_toolgroup{margin-left:5px}.cke_hc.cke_rtl .cke_toolbar .cke_combo+.cke_toolbar_end,.cke_hc.cke_rtl .cke_toolbar .cke_combo+.cke_toolgroup{margin-left:0;margin-right:5px}.cke_toolbar.cke_toolbar_last .cke_combo:nth-last-child(-n+2):after{content:none;border:0;width:0;height:0}.cke_combo_text{line-height:26px;padding-left:10px;text-overflow:ellipsis;overflow:hidden;float:left;cursor:default;color:#484848;width:60px}.cke_rtl .cke_combo_text{float:right;text-align:right;padding-left:0;padding-right:10px}.cke_hc .cke_combo_text{line-height:18px;font-size:12px}.cke_combo_open{cursor:default;display:inline-block;font-size:0;height:19px;line-height:17px;margin:1px 10px 1px;width:5px}.cke_hc .cke_combo_open{height:12px}.cke_combo_arrow{cursor:default;margin:11px 0 0;float:left;height:0;width:0;font-size:0;border-left:3px solid transparent;border-right:3px solid transparent;border-top:3px solid #484848}.cke_hc .cke_combo_arrow{font-size:10px;width:auto;border:0;margin-top:3px}.cke_combo_label{display:none;float:left;line-height:26px;vertical-align:top;margin-right:5px}.cke_rtl .cke_combo_label{float:right;margin-left:5px;margin-right:0}.cke_combo_disabled .cke_combo_inlinelabel,.cke_combo_disabled .cke_combo_open{opacity:.3}.cke_path{float:left;margin:-2px 0 2px}a.cke_path_item,span.cke_path_empty{display:inline-block;float:left;padding:3px 4px;margin-right:2px;cursor:default;text-decoration:none;outline:0;border:0;color:#484848;font-weight:bold;font-size:11px}.cke_rtl .cke_path,.cke_rtl .cke_path_item,.cke_rtl .cke_path_empty{float:right}a.cke_path_item:hover,a.cke_path_item:focus,a.cke_path_item:active{background-color:#e5e5e5}.cke_hc a.cke_path_item:hover,.cke_hc a.cke_path_item:focus,.cke_hc a.cke_path_item:active{border:2px solid;padding:1px 2px}.cke_button__source_label,.cke_button__sourcedialog_label{display:inline}.cke_combopanel__fontsize{width:135px}textarea.cke_source{font-family:'Courier New',Monospace;font-size:small;background-color:#fff;white-space:pre-wrap;border:0;padding:0;margin:0;display:block}.cke_wysiwyg_frame,.cke_wysiwyg_div{background-color:#fff}.cke_notifications_area{pointer-events:none}.cke_notification{pointer-events:auto;position:relative;margin:10px;width:300px;color:white;text-align:center;opacity:.95;filter:alpha(opacity = 95);-webkit-animation:fadeIn .7s;animation:fadeIn .7s}.cke_notification_message a{color:#12306f}@-webkit-keyframes fadeIn{from{opacity:.4}to{opacity:.95}}@keyframes fadeIn{from{opacity:.4}to{opacity:.95}}.cke_notification_success{background:#72b572;border:1px solid #63a563}.cke_notification_warning{background:#c83939;border:1px solid #902b2b}.cke_notification_info{background:#2e9ad0;border:1px solid #0f74a8}.cke_notification_info span.cke_notification_progress{background-color:#0f74a8;display:block;padding:0;margin:0;height:100%;overflow:hidden;position:absolute;z-index:1}.cke_notification_message{position:relative;margin:4px 23px 3px;font-family:Arial,Helvetica,sans-serif;font-size:12px;line-height:18px;z-index:4;text-overflow:ellipsis;overflow:hidden}.cke_notification_close{background-image:url(images/close.png);background-repeat:no-repeat;background-position:50%;position:absolute;cursor:pointer;text-align:center;height:20px;width:20px;top:1px;right:1px;padding:0;margin:0;z-index:5;opacity:.6;filter:alpha(opacity = 60)}.cke_notification_close:hover{opacity:1;filter:alpha(opacity = 100)}.cke_notification_close span{display:none}.cke_notification_warning a.cke_notification_close{opacity:.8;filter:alpha(opacity = 80)}.cke_notification_warning a.cke_notification_close:hover{opacity:1;filter:alpha(opacity = 100)}.cke_chrome{visibility:inherit}.cke_voice_label{display:none}legend.cke_voice_label{display:none}.cke_button__about_icon{background:url(icons.png?t=I648) no-repeat 0 -0px!important}.cke_button__bold_icon{background:url(icons.png?t=I648) no-repeat 0 -24px!important}.cke_button__italic_icon{background:url(icons.png?t=I648) no-repeat 0 -48px!important}.cke_button__strike_icon{background:url(icons.png?t=I648) no-repeat 0 -72px!important}.cke_button__subscript_icon{background:url(icons.png?t=I648) no-repeat 0 -96px!important}.cke_button__superscript_icon{background:url(icons.png?t=I648) no-repeat 0 -120px!important}.cke_button__underline_icon{background:url(icons.png?t=I648) no-repeat 0 -144px!important}.cke_button__blockquote_icon{background:url(icons.png?t=I648) no-repeat 0 -168px!important}.cke_rtl .cke_button__copy_icon,.cke_mixed_dir_content .cke_rtl .cke_button__copy_icon{background:url(icons.png?t=I648) no-repeat 0 -192px!important}.cke_ltr .cke_button__copy_icon{background:url(icons.png?t=I648) no-repeat 0 -216px!important}.cke_rtl .cke_button__cut_icon,.cke_mixed_dir_content .cke_rtl .cke_button__cut_icon{background:url(icons.png?t=I648) no-repeat 0 -240px!important}.cke_ltr .cke_button__cut_icon{background:url(icons.png?t=I648) no-repeat 0 -264px!important}.cke_rtl .cke_button__paste_icon,.cke_mixed_dir_content .cke_rtl .cke_button__paste_icon{background:url(icons.png?t=I648) no-repeat 0 -288px!important}.cke_ltr .cke_button__paste_icon{background:url(icons.png?t=I648) no-repeat 0 -312px!important}.cke_button__horizontalrule_icon{background:url(icons.png?t=I648) no-repeat 0 -336px!important}.cke_button__image_icon{background:url(icons.png?t=I648) no-repeat 0 -360px!important}.cke_rtl .cke_button__indent_icon,.cke_mixed_dir_content .cke_rtl .cke_button__indent_icon{background:url(icons.png?t=I648) no-repeat 0 -384px!important}.cke_ltr .cke_button__indent_icon{background:url(icons.png?t=I648) no-repeat 0 -408px!important}.cke_rtl .cke_button__outdent_icon,.cke_mixed_dir_content .cke_rtl .cke_button__outdent_icon{background:url(icons.png?t=I648) no-repeat 0 -432px!important}.cke_ltr .cke_button__outdent_icon{background:url(icons.png?t=I648) no-repeat 0 -456px!important}.cke_button__justifyblock_icon{background:url(icons.png?t=I648) no-repeat 0 -480px!important}.cke_button__justifycenter_icon{background:url(icons.png?t=I648) no-repeat 0 -504px!important}.cke_button__justifyleft_icon{background:url(icons.png?t=I648) no-repeat 0 -528px!important}.cke_button__justifyright_icon{background:url(icons.png?t=I648) no-repeat 0 -552px!important}.cke_button__language_icon{background:url(icons.png?t=I648) no-repeat 0 -576px!important}.cke_rtl .cke_button__bulletedlist_icon,.cke_mixed_dir_content .cke_rtl .cke_button__bulletedlist_icon{background:url(icons.png?t=I648) no-repeat 0 -600px!important}.cke_ltr .cke_button__bulletedlist_icon{background:url(icons.png?t=I648) no-repeat 0 -624px!important}.cke_rtl .cke_button__numberedlist_icon,.cke_mixed_dir_content .cke_rtl .cke_button__numberedlist_icon{background:url(icons.png?t=I648) no-repeat 0 -648px!important}.cke_ltr .cke_button__numberedlist_icon{background:url(icons.png?t=I648) no-repeat 0 -672px!important}.cke_button__maximize_icon{background:url(icons.png?t=I648) no-repeat 0 -696px!important}.cke_rtl .cke_button__pastefromword_icon,.cke_mixed_dir_content .cke_rtl .cke_button__pastefromword_icon{background:url(icons.png?t=I648) no-repeat 0 -720px!important}.cke_ltr .cke_button__pastefromword_icon{background:url(icons.png?t=I648) no-repeat 0 -744px!important}.cke_rtl .cke_button__pastetext_icon,.cke_mixed_dir_content .cke_rtl .cke_button__pastetext_icon{background:url(icons.png?t=I648) no-repeat 0 -768px!important}.cke_ltr .cke_button__pastetext_icon{background:url(icons.png?t=I648) no-repeat 0 -792px!important}.cke_button__removeformat_icon{background:url(icons.png?t=I648) no-repeat 0 -816px!important}.cke_rtl .cke_button__showblocks_icon,.cke_mixed_dir_content .cke_rtl .cke_button__showblocks_icon{background:url(icons.png?t=I648) no-repeat 0 -840px!important}.cke_ltr .cke_button__showblocks_icon{background:url(icons.png?t=I648) no-repeat 0 -864px!important}.cke_rtl .cke_button__source_icon,.cke_mixed_dir_content .cke_rtl .cke_button__source_icon{background:url(icons.png?t=I648) no-repeat 0 -888px!important}.cke_ltr .cke_button__source_icon{background:url(icons.png?t=I648) no-repeat 0 -912px!important}.cke_rtl .cke_button__sourcedialog_icon,.cke_mixed_dir_content .cke_rtl .cke_button__sourcedialog_icon{background:url(icons.png?t=I648) no-repeat 0 -936px!important}.cke_ltr .cke_button__sourcedialog_icon{background:url(icons.png?t=I648) no-repeat 0 -960px!important}.cke_button__specialchar_icon{background:url(icons.png?t=I648) no-repeat 0 -984px!important}.cke_button__table_icon{background:url(icons.png?t=I648) no-repeat 0 -1008px!important}.cke_rtl .cke_button__redo_icon,.cke_mixed_dir_content .cke_rtl .cke_button__redo_icon{background:url(icons.png?t=I648) no-repeat 0 -1032px!important}.cke_ltr .cke_button__redo_icon{background:url(icons.png?t=I648) no-repeat 0 -1056px!important}.cke_rtl .cke_button__undo_icon,.cke_mixed_dir_content .cke_rtl .cke_button__undo_icon{background:url(icons.png?t=I648) no-repeat 0 -1080px!important}.cke_ltr .cke_button__undo_icon{background:url(icons.png?t=I648) no-repeat 0 -1104px!important}.cke_button__simplebox_icon{background:url(icons.png?t=I648) no-repeat 0 -1128px!important}.cke_hidpi .cke_button__about_icon{background:url(icons_hidpi.png?t=I648) no-repeat 0 -0px!important;background-size:16px!important}.cke_hidpi .cke_button__bold_icon{background:url(icons_hidpi.png?t=I648) no-repeat 0 -24px!important;background-size:16px!important}.cke_hidpi .cke_button__italic_icon{background:url(icons_hidpi.png?t=I648) no-repeat 0 -48px!important;background-size:16px!important}.cke_hidpi .cke_button__strike_icon{background:url(icons_hidpi.png?t=I648) no-repeat 0 -72px!important;background-size:16px!important}.cke_hidpi .cke_button__subscript_icon{background:url(icons_hidpi.png?t=I648) no-repeat 0 -96px!important;background-size:16px!important}.cke_hidpi .cke_button__superscript_icon{background:url(icons_hidpi.png?t=I648) no-repeat 0 -120px!important;background-size:16px!important}.cke_hidpi .cke_button__underline_icon{background:url(icons_hidpi.png?t=I648) no-repeat 0 -144px!important;background-size:16px!important}.cke_hidpi .cke_button__blockquote_icon{background:url(icons_hidpi.png?t=I648) no-repeat 0 -168px!important;background-size:16px!important}.cke_rtl.cke_hidpi .cke_button__copy_icon,.cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__copy_icon{background:url(icons_hidpi.png?t=I648) no-repeat 0 -192px!important;background-size:16px!important}.cke_hidpi .cke_ltr .cke_button__copy_icon,.cke_ltr.cke_hidpi .cke_button__copy_icon{background:url(icons_hidpi.png?t=I648) no-repeat 0 -216px!important;background-size:16px!important}.cke_rtl.cke_hidpi .cke_button__cut_icon,.cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__cut_icon{background:url(icons_hidpi.png?t=I648) no-repeat 0 -240px!important;background-size:16px!important}.cke_hidpi .cke_ltr .cke_button__cut_icon,.cke_ltr.cke_hidpi .cke_button__cut_icon{background:url(icons_hidpi.png?t=I648) no-repeat 0 -264px!important;background-size:16px!important}.cke_rtl.cke_hidpi .cke_button__paste_icon,.cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__paste_icon{background:url(icons_hidpi.png?t=I648) no-repeat 0 -288px!important;background-size:16px!important}.cke_hidpi .cke_ltr .cke_button__paste_icon,.cke_ltr.cke_hidpi .cke_button__paste_icon{background:url(icons_hidpi.png?t=I648) no-repeat 0 -312px!important;background-size:16px!important}.cke_hidpi .cke_button__horizontalrule_icon{background:url(icons_hidpi.png?t=I648) no-repeat 0 -336px!important;background-size:16px!important}.cke_hidpi .cke_button__image_icon{background:url(icons_hidpi.png?t=I648) no-repeat 0 -360px!important;background-size:16px!important}.cke_rtl.cke_hidpi .cke_button__indent_icon,.cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__indent_icon{background:url(icons_hidpi.png?t=I648) no-repeat 0 -384px!important;background-size:16px!important}.cke_hidpi .cke_ltr .cke_button__indent_icon,.cke_ltr.cke_hidpi .cke_button__indent_icon{background:url(icons_hidpi.png?t=I648) no-repeat 0 -408px!important;background-size:16px!important}.cke_rtl.cke_hidpi .cke_button__outdent_icon,.cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__outdent_icon{background:url(icons_hidpi.png?t=I648) no-repeat 0 -432px!important;background-size:16px!important}.cke_hidpi .cke_ltr .cke_button__outdent_icon,.cke_ltr.cke_hidpi .cke_button__outdent_icon{background:url(icons_hidpi.png?t=I648) no-repeat 0 -456px!important;background-size:16px!important}.cke_hidpi .cke_button__justifyblock_icon{background:url(icons_hidpi.png?t=I648) no-repeat 0 -480px!important;background-size:16px!important}.cke_hidpi .cke_button__justifycenter_icon{background:url(icons_hidpi.png?t=I648) no-repeat 0 -504px!important;background-size:16px!important}.cke_hidpi .cke_button__justifyleft_icon{background:url(icons_hidpi.png?t=I648) no-repeat 0 -528px!important;background-size:16px!important}.cke_hidpi .cke_button__justifyright_icon{background:url(icons_hidpi.png?t=I648) no-repeat 0 -552px!important;background-size:16px!important}.cke_hidpi .cke_button__language_icon{background:url(icons_hidpi.png?t=I648) no-repeat 0 -576px!important;background-size:16px!important}.cke_rtl.cke_hidpi .cke_button__bulletedlist_icon,.cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__bulletedlist_icon{background:url(icons_hidpi.png?t=I648) no-repeat 0 -600px!important;background-size:16px!important}.cke_hidpi .cke_ltr .cke_button__bulletedlist_icon,.cke_ltr.cke_hidpi .cke_button__bulletedlist_icon{background:url(icons_hidpi.png?t=I648) no-repeat 0 -624px!important;background-size:16px!important}.cke_rtl.cke_hidpi .cke_button__numberedlist_icon,.cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__numberedlist_icon{background:url(icons_hidpi.png?t=I648) no-repeat 0 -648px!important;background-size:16px!important}.cke_hidpi .cke_ltr .cke_button__numberedlist_icon,.cke_ltr.cke_hidpi .cke_button__numberedlist_icon{background:url(icons_hidpi.png?t=I648) no-repeat 0 -672px!important;background-size:16px!important}.cke_hidpi .cke_button__maximize_icon{background:url(icons_hidpi.png?t=I648) no-repeat 0 -696px!important;background-size:16px!important}.cke_rtl.cke_hidpi .cke_button__pastefromword_icon,.cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__pastefromword_icon{background:url(icons_hidpi.png?t=I648) no-repeat 0 -720px!important;background-size:16px!important}.cke_hidpi .cke_ltr .cke_button__pastefromword_icon,.cke_ltr.cke_hidpi .cke_button__pastefromword_icon{background:url(icons_hidpi.png?t=I648) no-repeat 0 -744px!important;background-size:16px!important}.cke_rtl.cke_hidpi .cke_button__pastetext_icon,.cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__pastetext_icon{background:url(icons_hidpi.png?t=I648) no-repeat 0 -768px!important;background-size:16px!important}.cke_hidpi .cke_ltr .cke_button__pastetext_icon,.cke_ltr.cke_hidpi .cke_button__pastetext_icon{background:url(icons_hidpi.png?t=I648) no-repeat 0 -792px!important;background-size:16px!important}.cke_hidpi .cke_button__removeformat_icon{background:url(icons_hidpi.png?t=I648) no-repeat 0 -816px!important;background-size:16px!important}.cke_rtl.cke_hidpi .cke_button__showblocks_icon,.cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__showblocks_icon{background:url(icons_hidpi.png?t=I648) no-repeat 0 -840px!important;background-size:16px!important}.cke_hidpi .cke_ltr .cke_button__showblocks_icon,.cke_ltr.cke_hidpi .cke_button__showblocks_icon{background:url(icons_hidpi.png?t=I648) no-repeat 0 -864px!important;background-size:16px!important}.cke_rtl.cke_hidpi .cke_button__source_icon,.cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__source_icon{background:url(icons_hidpi.png?t=I648) no-repeat 0 -888px!important;background-size:16px!important}.cke_hidpi .cke_ltr .cke_button__source_icon,.cke_ltr.cke_hidpi .cke_button__source_icon{background:url(icons_hidpi.png?t=I648) no-repeat 0 -912px!important;background-size:16px!important}.cke_rtl.cke_hidpi .cke_button__sourcedialog_icon,.cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__sourcedialog_icon{background:url(icons_hidpi.png?t=I648) no-repeat 0 -936px!important;background-size:16px!important}.cke_hidpi .cke_ltr .cke_button__sourcedialog_icon,.cke_ltr.cke_hidpi .cke_button__sourcedialog_icon{background:url(icons_hidpi.png?t=I648) no-repeat 0 -960px!important;background-size:16px!important}.cke_hidpi .cke_button__specialchar_icon{background:url(icons_hidpi.png?t=I648) no-repeat 0 -984px!important;background-size:16px!important}.cke_hidpi .cke_button__table_icon{background:url(icons_hidpi.png?t=I648) no-repeat 0 -1008px!important;background-size:16px!important}.cke_rtl.cke_hidpi .cke_button__redo_icon,.cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__redo_icon{background:url(icons_hidpi.png?t=I648) no-repeat 0 -1032px!important;background-size:16px!important}.cke_hidpi .cke_ltr .cke_button__redo_icon,.cke_ltr.cke_hidpi .cke_button__redo_icon{background:url(icons_hidpi.png?t=I648) no-repeat 0 -1056px!important;background-size:16px!important}.cke_rtl.cke_hidpi .cke_button__undo_icon,.cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__undo_icon{background:url(icons_hidpi.png?t=I648) no-repeat 0 -1080px!important;background-size:16px!important}.cke_hidpi .cke_ltr .cke_button__undo_icon,.cke_ltr.cke_hidpi .cke_button__undo_icon{background:url(icons_hidpi.png?t=I648) no-repeat 0 -1104px!important;background-size:16px!important}.cke_hidpi .cke_button__simplebox_icon{background:url(icons_hidpi.png?t=I648) no-repeat 0 -2256px!important}a.cke_button_disabled,a.cke_button_disabled:hover,a.cke_button_disabled:focus,a.cke_button_disabled:active{filter:alpha(opacity = 30)}.cke_button_disabled .cke_button_icon{filter:progid:DXImageTransform.Microsoft.gradient(startColorstr=#00ffffff,endColorstr=#00ffffff)}.cke_button_off:hover,.cke_button_off:focus,.cke_button_off:active{filter:alpha(opacity = 100)}.cke_combo_disabled .cke_combo_inlinelabel,.cke_combo_disabled .cke_combo_open{filter:alpha(opacity = 30)}.cke_toolbox_collapser{border:1px solid #a6a6a6}.cke_toolbox_collapser .cke_arrow{margin-top:1px}.cke_hc .cke_top,.cke_hc .cke_bottom,.cke_hc .cke_combo_button,.cke_hc a.cke_combo_button:hover,.cke_hc a.cke_combo_button:focus,.cke_hc .cke_toolgroup,.cke_hc .cke_button_on,.cke_hc a.cke_button_off:hover,.cke_hc a.cke_button_off:focus,.cke_hc a.cke_button_off:active,.cke_hc .cke_toolbox_collapser,.cke_hc .cke_toolbox_collapser:hover,.cke_hc .cke_panel_grouptitle{filter:progid:DXImageTransform.Microsoft.gradient(enabled=false)}.cke_top,.cke_contents,.cke_bottom{width:100%}.cke_button_arrow{font-size:0}.cke_rtl .cke_toolgroup,.cke_rtl .cke_toolbar_separator,.cke_rtl .cke_button,.cke_rtl .cke_button *,.cke_rtl .cke_combo,.cke_rtl .cke_combo *,.cke_rtl .cke_path_item,.cke_rtl .cke_path_item *,.cke_rtl .cke_path_empty{float:none}.cke_rtl .cke_toolgroup,.cke_rtl .cke_toolbar_separator,.cke_rtl .cke_combo_button,.cke_rtl .cke_combo_button *,.cke_rtl .cke_button,.cke_rtl .cke_button_icon{display:inline-block;vertical-align:top}.cke_rtl .cke_button_icon{float:none}.cke_resizer{width:10px}.cke_source{white-space:normal}.cke_bottom{position:static}.cke_colorbox{font-size:0} \ No newline at end of file +.cke_reset{margin:0;padding:0;border:0;background:transparent;text-decoration:none;width:auto;height:auto;vertical-align:baseline;box-sizing:content-box;position:static;transition:none}.cke_reset_all,.cke_reset_all *,.cke_reset_all a,.cke_reset_all textarea{margin:0;padding:0;border:0;background:transparent;text-decoration:none;width:auto;height:auto;vertical-align:baseline;box-sizing:content-box;position:static;transition:none;border-collapse:collapse;font:normal normal normal 12px Arial,Helvetica,Tahoma,Verdana,Sans-Serif;color:#000;text-align:left;white-space:nowrap;cursor:auto;float:none}.cke_reset_all .cke_rtl *{text-align:right}.cke_reset_all iframe{vertical-align:inherit}.cke_reset_all textarea{white-space:pre-wrap}.cke_reset_all textarea,.cke_reset_all input[type="text"],.cke_reset_all input[type="password"]{cursor:text}.cke_reset_all textarea[disabled],.cke_reset_all input[type="text"][disabled],.cke_reset_all input[type="password"][disabled]{cursor:default}.cke_reset_all fieldset{padding:10px;border:2px groove #e0dfe3}.cke_reset_all select{box-sizing:border-box}.cke_reset_all table{table-layout:auto}.cke_chrome{display:block;border:1px solid #d1d1d1;padding:0}.cke_inner{display:block;background:#fff;padding:0;-webkit-touch-callout:none}.cke_float{border:0}.cke_float .cke_inner{padding-bottom:0}.cke_top,.cke_contents,.cke_bottom{display:block;overflow:hidden}.cke_top{border-bottom:1px solid #d1d1d1;background:#f8f8f8;padding:6px 8px 2px;white-space:normal}.cke_float .cke_top{border:1px solid #d1d1d1}.cke_bottom{padding:6px 8px 2px;position:relative;border-top:1px solid #d1d1d1;background:#f8f8f8}.cke_browser_ios .cke_contents{overflow-y:auto;-webkit-overflow-scrolling:touch}.cke_resizer{width:0;height:0;overflow:hidden;border-width:10px 10px 0 0;border-color:transparent #bcbcbc transparent transparent;border-style:dashed solid dashed dashed;font-size:0;vertical-align:bottom;margin-top:6px;margin-bottom:2px}.cke_hc .cke_resizer{font-size:15px;width:auto;height:auto;border-width:0}.cke_resizer_ltr{cursor:se-resize;float:right;margin-right:-4px}.cke_resizer_rtl{border-width:10px 0 0 10px;border-color:transparent transparent transparent #bcbcbc;border-style:dashed dashed dashed solid;cursor:sw-resize;float:left;margin-left:-4px;right:auto}.cke_wysiwyg_div{display:block;height:100%;overflow:auto;padding:0 8px;outline-style:none;box-sizing:border-box}.cke_panel{visibility:visible;width:120px;height:100px;overflow:hidden;background-color:#fff;border:1px solid #d1d1d1}.cke_menu_panel{padding:0;margin:0}.cke_combopanel{width:150px;height:170px}.cke_panel_frame{width:100%;height:100%;font-size:12px;overflow:auto;overflow-x:hidden}.cke_panel_container{overflow-y:auto;overflow-x:hidden}.cke_panel_block:focus{outline:0}.cke_panel_list{margin:0;padding:0;list-style-type:none;white-space:nowrap}.cke_panel_listItem{margin:0;padding:0}.cke_panel_listItem a{padding:6px 7px;display:block;color:inherit!important;text-decoration:none;overflow:hidden;text-overflow:ellipsis}.cke_hc .cke_panel_listItem a{border-style:none}.cke_panel_listItem.cke_selected a,.cke_panel_listItem a:hover,.cke_panel_listItem a:focus,.cke_panel_listItem a:active{background-color:#e9e9e9}.cke_panel_listItem a:focus{outline:1px dotted #000}.cke_hc .cke_panel_listItem a:hover,.cke_hc .cke_panel_listItem a:focus,.cke_hc .cke_panel_listItem a:active{border:2px solid;padding:4px 5px}.cke_panel_listItem p,.cke_panel_listItem h1,.cke_panel_listItem h2,.cke_panel_listItem h3,.cke_panel_listItem h4,.cke_panel_listItem h5,.cke_panel_listItem h6,.cke_panel_listItem pre{margin-top:0;margin-bottom:0}.cke_panel_grouptitle{cursor:default;font-size:11px;font-weight:bold;white-space:nowrap;margin:0;padding:6px 6px 7px 6px;color:#484848;border-bottom:1px solid #d1d1d1;background:#f8f8f8}.cke_colorblock{padding:10px;font-size:11px;font-family:'Microsoft Sans Serif',Tahoma,Arial,Verdana,Sans-Serif}.cke_colorblock,.cke_colorblock a{text-decoration:none;color:#000}a.cke_colorbox{padding:2px;float:left;width:20px;height:20px}.cke_rtl a.cke_colorbox{float:right}a:hover.cke_colorbox,a:focus.cke_colorbox,a:active.cke_colorbox{outline:0;padding:0;border:2px solid #139ff7}a:hover.cke_colorbox{border-color:#bcbcbc}span.cke_colorbox{width:20px;height:20px;float:left}.cke_rtl span.cke_colorbox{float:right}a.cke_colorauto,a.cke_colormore{border:#fff 1px solid;padding:3px;display:block;cursor:pointer}a.cke_colorauto{padding:0;border:1px solid transparent;margin-bottom:6px;height:26px;line-height:26px}a.cke_colormore{margin-top:10px;height:20px;line-height:19px}a:hover.cke_colorauto,a:hover.cke_colormore,a:focus.cke_colorauto,a:focus.cke_colormore,a:active.cke_colorauto,a:active.cke_colormore{outline:0;border:#139ff7 1px solid;background-color:#f8f8f8}a:hover.cke_colorauto,a:hover.cke_colormore{border-color:#bcbcbc}.cke_colorauto span.cke_colorbox{width:18px;height:18px;border:1px solid #808080;margin-left:1px;margin-top:3px}.cke_rtl .cke_colorauto span.cke_colorbox{margin-left:0;margin-right:1px}span.cke_colorbox[style*="#ffffff"],span.cke_colorbox[style*="#FFFFFF"],span.cke_colorbox[style="background-color:#fff"],span.cke_colorbox[style="background-color:#FFF"],span.cke_colorbox[style*="rgb(255,255,255)"],span.cke_colorbox[style*="rgb(255, 255, 255)"]{border:1px solid #808080;width:18px;height:18px}.cke_toolbar{float:left}.cke_rtl .cke_toolbar{float:right}.cke_toolgroup{border:0;float:left;margin:1px 2px 6px 0;padding-right:3px}.cke_rtl .cke_toolgroup{float:right;margin:1px 0 6px 2px;padding-left:3px;padding-right:0}.cke_hc .cke_toolgroup{margin-right:5px;margin-bottom:5px}.cke_hc.cke_rtl .cke_toolgroup{margin-right:0;margin-left:5px}a.cke_button{display:inline-block;height:18px;padding:4px 6px;outline:0;cursor:default;float:left;border:0;position:relative}.cke_rtl a.cke_button{float:right}.cke_hc a.cke_button{border:1px solid black;padding:3px 5px;margin:0 3px 5px 0}.cke_hc.cke_rtl a.cke_button{margin:0 0 5px 3px}a.cke_button_on{background:#fff;border:1px #bcbcbc solid;padding:3px 5px}a.cke_button_off:hover,a.cke_button_off:focus,a.cke_button_off:active{background:#e5e5e5;border:1px #bcbcbc solid;padding:3px 5px}.cke_hc a.cke_button_on,.cke_hc a.cke_button_off:hover,.cke_hc a.cke_button_off:focus,.cke_hc a.cke_button_off:active{background:#e5e5e5;border:3px solid #000;padding:1px 3px}a.cke_button_disabled:hover,a.cke_button_disabled:focus,a.cke_button_disabled:active{border:0;padding:4px 6px;background-color:transparent}a.cke_button_disabled:focus{border:1px #bcbcbc solid;padding:3px 5px}.cke_hc a.cke_button_disabled:hover,.cke_hc a.cke_button_disabled:focus,.cke_hc a.cke_button_disabled:active{border:1px solid #acacac;padding:3px 5px;margin:0 3px 5px 0}.cke_hc a.cke_button_disabled:focus{border:3px solid #000;padding:1px 3px}.cke_hc.cke_rtl a.cke_button_disabled:hover,.cke_hc.cke_rtl a.cke_button_disabled:focus,.cke_hc.cke_rtl a.cke_button_disabled:active{margin:0 0 5px 3px}a.cke_button_disabled .cke_button_icon,a.cke_button_disabled .cke_button_arrow{opacity:.3}.cke_hc a.cke_button_disabled{border-color:#acacac}.cke_hc a.cke_button_disabled .cke_button_icon,.cke_hc a.cke_button_disabled .cke_button_label{opacity:.5}.cke_toolgroup a.cke_button:last-child:after,.cke_toolgroup a.cke_button.cke_button_disabled:hover:last-child:after{content:"";position:absolute;height:18px;width:0;border-right:1px solid #bcbcbc;margin-top:4px;top:0;right:-3px}.cke_rtl .cke_toolgroup a.cke_button:last-child:after,.cke_rtl .cke_toolgroup a.cke_button.cke_button_disabled:hover:last-child:after{border-right:0;right:auto;border-left:1px solid #bcbcbc;top:0;left:-3px}.cke_hc .cke_toolgroup a.cke_button:last-child:after,.cke_hc .cke_toolgroup a.cke_button.cke_button_disabled:last-child:after,.cke_hc .cke_toolgroup a.cke_button.cke_button_disabled:hover:last-child:after{border-color:#000;top:0;right:-7px}.cke_hc.cke_rtl .cke_toolgroup a.cke_button:last-child:after,.cke_hc.cke_rtl .cke_toolgroup a.cke_button.cke_button_disabled:last-child:after,.cke_hc.cke_rtl .cke_toolgroup a.cke_button.cke_button_disabled:hover:last-child:after{top:0;right:auto;left:-7px}.cke_toolgroup a.cke_button:hover:last-child:after,.cke_toolgroup a.cke_button.cke_button_on:last-child:after{top:-1px;right:-4px}.cke_rtl .cke_toolgroup a.cke_button:hover:last-child:after,.cke_rtl .cke_toolgroup a.cke_button.cke_button_on:last-child:after{top:-1px;right:auto;left:-4px}.cke_hc .cke_toolgroup a.cke_button:hover:last-child:after,.cke_hc .cke_toolgroup a.cke_button.cke_button_on:last-child:after{top:-2px;right:-9px}.cke_hc.cke_rtl .cke_toolgroup a.cke_button:hover:last-child:after,.cke_hc.cke_rtl .cke_toolgroup a.cke_button.cke_button_on:last-child:after{top:-2px;right:auto;left:-9px}.cke_toolbar.cke_toolbar_last .cke_toolgroup a.cke_button:last-child:after{content:none;border:0;width:0;height:0}.cke_button_icon{cursor:inherit;background-repeat:no-repeat;margin-top:1px;width:16px;height:16px;float:left;display:inline-block}.cke_rtl .cke_button_icon{float:right}.cke_hc .cke_button_icon{display:none}.cke_button_label{display:none;padding-left:3px;margin-top:1px;line-height:17px;vertical-align:middle;float:left;cursor:default;color:#484848}.cke_rtl .cke_button_label{padding-right:3px;padding-left:0;float:right}.cke_hc .cke_button_label{padding:0;display:inline-block;font-size:12px}.cke_button_arrow{display:inline-block;margin:8px 0 0 1px;width:0;height:0;cursor:default;vertical-align:top;border-left:3px solid transparent;border-right:3px solid transparent;border-top:3px solid #484848}.cke_rtl .cke_button_arrow{margin-right:5px;margin-left:0}.cke_hc .cke_button_arrow{font-size:10px;margin:3px 0 0 3px;width:auto;border:0}.cke_toolbar_separator{float:left;background-color:#bcbcbc;margin:4px 2px 0 2px;height:18px;width:1px}.cke_rtl .cke_toolbar_separator{float:right}.cke_hc .cke_toolbar_separator{background-color:#000;margin-left:2px;margin-right:5px;margin-bottom:9px}.cke_hc.cke_rtl .cke_toolbar_separator{margin-left:5px;margin-right:2px}.cke_toolbar_break{display:block;clear:left}.cke_rtl .cke_toolbar_break{clear:right}a.cke_toolbox_collapser{width:12px;height:11px;float:right;margin:11px 0 0;font-size:0;cursor:default;text-align:center;border:1px solid #bcbcbc}.cke_rtl .cke_toolbox_collapser{float:left}.cke_toolbox_collapser:hover{background:#e5e5e5}.cke_toolbox_collapser.cke_toolbox_collapser_min{margin:0 2px 4px}.cke_toolbox_collapser .cke_arrow{display:inline-block;height:0;width:0;font-size:0;margin-top:1px;border:3px solid transparent;border-bottom-color:#484848}.cke_toolbox_collapser.cke_toolbox_collapser_min .cke_arrow{margin-top:4px;border-bottom-color:transparent;border-top-color:#484848}.cke_hc .cke_toolbox_collapser .cke_arrow{font-size:8px;width:auto;border:0;margin-top:0}.cke_menuitem span{cursor:default}.cke_menubutton{display:block}.cke_hc .cke_menubutton{padding:2px}.cke_menubutton:hover,.cke_menubutton:focus,.cke_menubutton:active{background-color:#e9e9e9;display:block;outline:1px dotted}.cke_menubutton:hover{outline:0}.cke_hc .cke_menubutton:hover,.cke_hc .cke_menubutton:focus,.cke_hc .cke_menubutton:active{border:2px solid;padding:0}.cke_menubutton_disabled:hover,.cke_menubutton_disabled:focus,.cke_menubutton_disabled:active{background-color:transparent;outline:0}.cke_menubutton_inner{display:table-row}.cke_menubutton_icon,.cke_menubutton_label,.cke_menuarrow{display:table-cell}.cke_menubutton_icon{background-color:#f8f8f8;padding:6px 4px}.cke_hc .cke_menubutton_icon{height:16px;width:0;padding:4px 0}.cke_menubutton:hover .cke_menubutton_icon,.cke_menubutton:focus .cke_menubutton_icon,.cke_menubutton:active .cke_menubutton_icon{background-color:#e9e9e9}.cke_menubutton_disabled:hover .cke_menubutton_icon,.cke_menubutton_disabled:focus .cke_menubutton_icon,.cke_menubutton_disabled:active .cke_menubutton_icon{background-color:#f8f8f8;outline:0}.cke_menuitem .cke_menubutton_on{background-color:#e9e9e9;border:1px solid #dedede;outline:0}.cke_menubutton_on .cke_menubutton_icon{padding-right:3px;background-color:#e9e9e9}.cke_menubutton_label{padding:0 5px;background-color:transparent;width:100%;vertical-align:middle}.cke_menubutton_shortcut{color:#979797}.cke_menubutton_disabled .cke_menubutton_label{opacity:.3;filter:alpha(opacity=30)}.cke_panel_frame .cke_menubutton_label{display:none}.cke_menuseparator{background-color:#d1d1d1;height:1px}.cke_menuarrow{background:transparent url(images/arrow.png) no-repeat 0 10px;padding:0 5px}.cke_rtl .cke_menuarrow{background-position:5px -13px;background-repeat:no-repeat}.cke_hc .cke_menuarrow{background-image:none}.cke_menuarrow span{display:none}.cke_hc .cke_menuarrow span{vertical-align:middle;display:inline}.cke_combo{display:inline-block;float:left;position:relative;margin-bottom:5px}.cke_rtl .cke_combo{float:right}.cke_hc .cke_combo{margin-top:1px;margin-bottom:10px}.cke_combo:after{content:"";position:absolute;height:18px;width:0;border-right:1px solid #bcbcbc;margin-top:5px;top:0;right:0}.cke_rtl .cke_combo:after{border-right:0;border-left:1px solid #bcbcbc;right:auto;left:0}.cke_hc .cke_combo:after{border-color:#000}a.cke_combo_button{cursor:default;display:inline-block;float:left;margin:0;padding:1px}.cke_rtl a.cke_combo_button{float:right}.cke_hc a.cke_combo_button{padding:4px}.cke_combo_on a.cke_combo_button,.cke_combo_off a.cke_combo_button:hover,.cke_combo_off a.cke_combo_button:focus,.cke_combo_off a.cke_combo_button:active{background:#e5e5e5;border:1px solid #bcbcbc;padding:0 0 0 1px;margin-left:-1px}.cke_combo_off a.cke_combo_button:focus{outline:0}.cke_combo_on a.cke_combo_button,.cke_combo_off a.cke_combo_button:active{background:#fff}.cke_rtl .cke_combo_on a.cke_combo_button,.cke_rtl .cke_combo_off a.cke_combo_button:hover,.cke_rtl .cke_combo_off a.cke_combo_button:focus,.cke_rtl .cke_combo_off a.cke_combo_button:active{padding:0 1px 0 0;margin-left:0;margin-right:-1px}.cke_hc .cke_combo_on a.cke_combo_button,.cke_hc .cke_combo_off a.cke_combo_button:hover,.cke_hc .cke_combo_off a.cke_combo_button:focus,.cke_hc .cke_combo_off a.cke_combo_button:active{border:3px solid #000;padding:1px 1px 1px 2px}.cke_hc.cke_rtl .cke_combo_on a.cke_combo_button,.cke_hc.cke_rtl .cke_combo_off a.cke_combo_button:hover,.cke_hc.cke_rtl .cke_combo_off a.cke_combo_button:focus,.cke_hc.cke_rtl .cke_combo_off a.cke_combo_button:active{padding:1px 2px 1px 1px}.cke_toolbar_start+.cke_combo_on a.cke_combo_button,.cke_toolbar_start+.cke_combo_off a.cke_combo_button:hover,.cke_toolbar_start+.cke_combo_off a.cke_combo_button:focus,.cke_toolbar_start+.cke_combo_off a.cke_combo_button:active{padding:0 0 0 3px;margin-left:-3px}.cke_rtl .cke_toolbar_start+.cke_combo_on a.cke_combo_button,.cke_rtl .cke_toolbar_start+.cke_combo_off a.cke_combo_button:hover,.cke_rtl .cke_toolbar_start+.cke_combo_off a.cke_combo_button:focus,.cke_rtl .cke_toolbar_start+.cke_combo_off a.cke_combo_button:active{padding:0 3px 0 0;margin-left:0;margin-right:-3px}.cke_hc .cke_toolbar>.cke_toolbar_start+.cke_combo_on a.cke_combo_button,.cke_hc .cke_toolbar>.cke_toolbar_start+.cke_combo_off a.cke_combo_button:hover,.cke_hc .cke_toolbar>.cke_toolbar_start+.cke_combo_off a.cke_combo_button:focus,.cke_hc .cke_toolbar>.cke_toolbar_start+.cke_combo_off a.cke_combo_button:active{padding:1px 1px 1px 7px;margin-left:-6px}.cke_hc.cke_rtl .cke_toolbar>.cke_toolbar_start+.cke_combo_on a.cke_combo_button,.cke_hc.cke_rtl .cke_toolbar>.cke_toolbar_start+.cke_combo_off a.cke_combo_button:hover,.cke_hc.cke_rtl .cke_toolbar>.cke_toolbar_start+.cke_combo_off a.cke_combo_button:focus,.cke_hc.cke_rtl .cke_toolbar>.cke_toolbar_start+.cke_combo_off a.cke_combo_button:active{padding:1px 7px 1px 1px;margin-left:0;margin-right:-6px}.cke_toolbox .cke_toolbar:first-child>.cke_toolbar_start+.cke_combo_on a.cke_combo_button,.cke_toolbox .cke_toolbar:first-child>.cke_toolbar_start+.cke_combo_off a.cke_combo_button:hover,.cke_toolbox .cke_toolbar:first-child>.cke_toolbar_start+.cke_combo_off a.cke_combo_button:focus,.cke_toolbox .cke_toolbar:first-child>.cke_toolbar_start+.cke_combo_off a.cke_combo_button:active,.cke_toolbar_break+.cke_toolbar>.cke_toolbar_start+.cke_combo_on a.cke_combo_button,.cke_toolbar_break+.cke_toolbar>.cke_toolbar_start+.cke_combo_off a.cke_combo_button:hover,.cke_toolbar_break+.cke_toolbar>.cke_toolbar_start+.cke_combo_off a.cke_combo_button:focus,.cke_toolbar_break+.cke_toolbar>.cke_toolbar_start+.cke_combo_off a.cke_combo_button:active{padding:0;margin:0}.cke_hc .cke_toolbox .cke_toolbar:first-child>.cke_toolbar_start+.cke_combo_on a.cke_combo_button,.cke_hc .cke_toolbox .cke_toolbar:first-child>.cke_toolbar_start+.cke_combo_off a.cke_combo_button:hover,.cke_hc .cke_toolbox .cke_toolbar:first-child>.cke_toolbar_start+.cke_combo_off a.cke_combo_button:focus,.cke_hc .cke_toolbox .cke_toolbar:first-child>.cke_toolbar_start+.cke_combo_off a.cke_combo_button:active,.cke_hc .cke_toolbar_break+.cke_toolbar>.cke_toolbar_start+.cke_combo_on a.cke_combo_button,.cke_hc .cke_toolbar_break+.cke_toolbar>.cke_toolbar_start+.cke_combo_off a.cke_combo_button:hover,.cke_hc .cke_toolbar_break+.cke_toolbar>.cke_toolbar_start+.cke_combo_off a.cke_combo_button:focus,.cke_hc .cke_toolbar_break+.cke_toolbar>.cke_toolbar_start+.cke_combo_off a.cke_combo_button:active{padding:1px;margin:0}.cke_toolbar .cke_combo+.cke_toolbar_end,.cke_toolbar .cke_combo+.cke_toolgroup{margin-right:0;margin-left:2px}.cke_rtl .cke_toolbar .cke_combo+.cke_toolbar_end,.cke_rtl .cke_toolbar .cke_combo+.cke_toolgroup{margin-left:0;margin-right:2px}.cke_hc .cke_toolbar .cke_combo+.cke_toolbar_end,.cke_hc .cke_toolbar .cke_combo+.cke_toolgroup{margin-left:5px}.cke_hc.cke_rtl .cke_toolbar .cke_combo+.cke_toolbar_end,.cke_hc.cke_rtl .cke_toolbar .cke_combo+.cke_toolgroup{margin-left:0;margin-right:5px}.cke_toolbar.cke_toolbar_last .cke_combo:nth-last-child(-n+2):after{content:none;border:0;width:0;height:0}.cke_combo_text{line-height:26px;padding-left:10px;text-overflow:ellipsis;overflow:hidden;float:left;cursor:default;color:#484848;width:60px}.cke_rtl .cke_combo_text{float:right;text-align:right;padding-left:0;padding-right:10px}.cke_hc .cke_combo_text{line-height:18px;font-size:12px}.cke_combo_open{cursor:default;display:inline-block;font-size:0;height:19px;line-height:17px;margin:1px 10px 1px;width:5px}.cke_hc .cke_combo_open{height:12px}.cke_combo_arrow{cursor:default;margin:11px 0 0;float:left;height:0;width:0;font-size:0;border-left:3px solid transparent;border-right:3px solid transparent;border-top:3px solid #484848}.cke_hc .cke_combo_arrow{font-size:10px;width:auto;border:0;margin-top:3px}.cke_combo_label{display:none;float:left;line-height:26px;vertical-align:top;margin-right:5px}.cke_rtl .cke_combo_label{float:right;margin-left:5px;margin-right:0}.cke_combo_disabled .cke_combo_inlinelabel,.cke_combo_disabled .cke_combo_open{opacity:.3}.cke_path{float:left;margin:-2px 0 2px}a.cke_path_item,span.cke_path_empty{display:inline-block;float:left;padding:3px 4px;margin-right:2px;cursor:default;text-decoration:none;outline:0;border:0;color:#484848;font-weight:bold;font-size:11px}.cke_rtl .cke_path,.cke_rtl .cke_path_item,.cke_rtl .cke_path_empty{float:right}a.cke_path_item:hover,a.cke_path_item:focus,a.cke_path_item:active{background-color:#e5e5e5}.cke_hc a.cke_path_item:hover,.cke_hc a.cke_path_item:focus,.cke_hc a.cke_path_item:active{border:2px solid;padding:1px 2px}.cke_button__source_label,.cke_button__sourcedialog_label{display:inline}.cke_combopanel__fontsize{width:135px}textarea.cke_source{font-family:'Courier New',Monospace;font-size:small;background-color:#fff;white-space:pre-wrap;border:0;padding:0;margin:0;display:block}.cke_wysiwyg_frame,.cke_wysiwyg_div{background-color:#fff}.cke_notifications_area{pointer-events:none}.cke_notification{pointer-events:auto;position:relative;margin:10px;width:300px;color:white;text-align:center;opacity:.95;filter:alpha(opacity = 95);-webkit-animation:fadeIn .7s;animation:fadeIn .7s}.cke_notification_message a{color:#12306f}@-webkit-keyframes fadeIn{from{opacity:.4}to{opacity:.95}}@keyframes fadeIn{from{opacity:.4}to{opacity:.95}}.cke_notification_success{background:#72b572;border:1px solid #63a563}.cke_notification_warning{background:#c83939;border:1px solid #902b2b}.cke_notification_info{background:#2e9ad0;border:1px solid #0f74a8}.cke_notification_info span.cke_notification_progress{background-color:#0f74a8;display:block;padding:0;margin:0;height:100%;overflow:hidden;position:absolute;z-index:1}.cke_notification_message{position:relative;margin:4px 23px 3px;font-family:Arial,Helvetica,sans-serif;font-size:12px;line-height:18px;z-index:4;text-overflow:ellipsis;overflow:hidden}.cke_notification_close{background-image:url(images/close.png);background-repeat:no-repeat;background-position:50%;position:absolute;cursor:pointer;text-align:center;height:20px;width:20px;top:1px;right:1px;padding:0;margin:0;z-index:5;opacity:.6;filter:alpha(opacity = 60)}.cke_notification_close:hover{opacity:1;filter:alpha(opacity = 100)}.cke_notification_close span{display:none}.cke_notification_warning a.cke_notification_close{opacity:.8;filter:alpha(opacity = 80)}.cke_notification_warning a.cke_notification_close:hover{opacity:1;filter:alpha(opacity = 100)}.cke_chrome{visibility:inherit}.cke_voice_label{display:none}legend.cke_voice_label{display:none}.cke_button__about_icon{background:url(icons.png?t=I8E8) no-repeat 0 -0px!important}.cke_button__bold_icon{background:url(icons.png?t=I8E8) no-repeat 0 -24px!important}.cke_button__italic_icon{background:url(icons.png?t=I8E8) no-repeat 0 -48px!important}.cke_button__strike_icon{background:url(icons.png?t=I8E8) no-repeat 0 -72px!important}.cke_button__subscript_icon{background:url(icons.png?t=I8E8) no-repeat 0 -96px!important}.cke_button__superscript_icon{background:url(icons.png?t=I8E8) no-repeat 0 -120px!important}.cke_button__underline_icon{background:url(icons.png?t=I8E8) no-repeat 0 -144px!important}.cke_button__blockquote_icon{background:url(icons.png?t=I8E8) no-repeat 0 -168px!important}.cke_rtl .cke_button__copy_icon,.cke_mixed_dir_content .cke_rtl .cke_button__copy_icon{background:url(icons.png?t=I8E8) no-repeat 0 -192px!important}.cke_ltr .cke_button__copy_icon{background:url(icons.png?t=I8E8) no-repeat 0 -216px!important}.cke_rtl .cke_button__cut_icon,.cke_mixed_dir_content .cke_rtl .cke_button__cut_icon{background:url(icons.png?t=I8E8) no-repeat 0 -240px!important}.cke_ltr .cke_button__cut_icon{background:url(icons.png?t=I8E8) no-repeat 0 -264px!important}.cke_rtl .cke_button__paste_icon,.cke_mixed_dir_content .cke_rtl .cke_button__paste_icon{background:url(icons.png?t=I8E8) no-repeat 0 -288px!important}.cke_ltr .cke_button__paste_icon{background:url(icons.png?t=I8E8) no-repeat 0 -312px!important}.cke_button__horizontalrule_icon{background:url(icons.png?t=I8E8) no-repeat 0 -336px!important}.cke_button__image_icon{background:url(icons.png?t=I8E8) no-repeat 0 -360px!important}.cke_rtl .cke_button__indent_icon,.cke_mixed_dir_content .cke_rtl .cke_button__indent_icon{background:url(icons.png?t=I8E8) no-repeat 0 -384px!important}.cke_ltr .cke_button__indent_icon{background:url(icons.png?t=I8E8) no-repeat 0 -408px!important}.cke_rtl .cke_button__outdent_icon,.cke_mixed_dir_content .cke_rtl .cke_button__outdent_icon{background:url(icons.png?t=I8E8) no-repeat 0 -432px!important}.cke_ltr .cke_button__outdent_icon{background:url(icons.png?t=I8E8) no-repeat 0 -456px!important}.cke_button__justifyblock_icon{background:url(icons.png?t=I8E8) no-repeat 0 -480px!important}.cke_button__justifycenter_icon{background:url(icons.png?t=I8E8) no-repeat 0 -504px!important}.cke_button__justifyleft_icon{background:url(icons.png?t=I8E8) no-repeat 0 -528px!important}.cke_button__justifyright_icon{background:url(icons.png?t=I8E8) no-repeat 0 -552px!important}.cke_button__language_icon{background:url(icons.png?t=I8E8) no-repeat 0 -576px!important}.cke_rtl .cke_button__bulletedlist_icon,.cke_mixed_dir_content .cke_rtl .cke_button__bulletedlist_icon{background:url(icons.png?t=I8E8) no-repeat 0 -600px!important}.cke_ltr .cke_button__bulletedlist_icon{background:url(icons.png?t=I8E8) no-repeat 0 -624px!important}.cke_rtl .cke_button__numberedlist_icon,.cke_mixed_dir_content .cke_rtl .cke_button__numberedlist_icon{background:url(icons.png?t=I8E8) no-repeat 0 -648px!important}.cke_ltr .cke_button__numberedlist_icon{background:url(icons.png?t=I8E8) no-repeat 0 -672px!important}.cke_button__maximize_icon{background:url(icons.png?t=I8E8) no-repeat 0 -696px!important}.cke_rtl .cke_button__pastefromword_icon,.cke_mixed_dir_content .cke_rtl .cke_button__pastefromword_icon{background:url(icons.png?t=I8E8) no-repeat 0 -720px!important}.cke_ltr .cke_button__pastefromword_icon{background:url(icons.png?t=I8E8) no-repeat 0 -744px!important}.cke_rtl .cke_button__pastetext_icon,.cke_mixed_dir_content .cke_rtl .cke_button__pastetext_icon{background:url(icons.png?t=I8E8) no-repeat 0 -768px!important}.cke_ltr .cke_button__pastetext_icon{background:url(icons.png?t=I8E8) no-repeat 0 -792px!important}.cke_button__removeformat_icon{background:url(icons.png?t=I8E8) no-repeat 0 -816px!important}.cke_rtl .cke_button__showblocks_icon,.cke_mixed_dir_content .cke_rtl .cke_button__showblocks_icon{background:url(icons.png?t=I8E8) no-repeat 0 -840px!important}.cke_ltr .cke_button__showblocks_icon{background:url(icons.png?t=I8E8) no-repeat 0 -864px!important}.cke_rtl .cke_button__source_icon,.cke_mixed_dir_content .cke_rtl .cke_button__source_icon{background:url(icons.png?t=I8E8) no-repeat 0 -888px!important}.cke_ltr .cke_button__source_icon{background:url(icons.png?t=I8E8) no-repeat 0 -912px!important}.cke_rtl .cke_button__sourcedialog_icon,.cke_mixed_dir_content .cke_rtl .cke_button__sourcedialog_icon{background:url(icons.png?t=I8E8) no-repeat 0 -936px!important}.cke_ltr .cke_button__sourcedialog_icon{background:url(icons.png?t=I8E8) no-repeat 0 -960px!important}.cke_button__specialchar_icon{background:url(icons.png?t=I8E8) no-repeat 0 -984px!important}.cke_button__table_icon{background:url(icons.png?t=I8E8) no-repeat 0 -1008px!important}.cke_rtl .cke_button__redo_icon,.cke_mixed_dir_content .cke_rtl .cke_button__redo_icon{background:url(icons.png?t=I8E8) no-repeat 0 -1032px!important}.cke_ltr .cke_button__redo_icon{background:url(icons.png?t=I8E8) no-repeat 0 -1056px!important}.cke_rtl .cke_button__undo_icon,.cke_mixed_dir_content .cke_rtl .cke_button__undo_icon{background:url(icons.png?t=I8E8) no-repeat 0 -1080px!important}.cke_ltr .cke_button__undo_icon{background:url(icons.png?t=I8E8) no-repeat 0 -1104px!important}.cke_button__simplebox_icon{background:url(icons.png?t=I8E8) no-repeat 0 -1128px!important}.cke_hidpi .cke_button__about_icon{background:url(icons_hidpi.png?t=I8E8) no-repeat 0 -0px!important;background-size:16px!important}.cke_hidpi .cke_button__bold_icon{background:url(icons_hidpi.png?t=I8E8) no-repeat 0 -24px!important;background-size:16px!important}.cke_hidpi .cke_button__italic_icon{background:url(icons_hidpi.png?t=I8E8) no-repeat 0 -48px!important;background-size:16px!important}.cke_hidpi .cke_button__strike_icon{background:url(icons_hidpi.png?t=I8E8) no-repeat 0 -72px!important;background-size:16px!important}.cke_hidpi .cke_button__subscript_icon{background:url(icons_hidpi.png?t=I8E8) no-repeat 0 -96px!important;background-size:16px!important}.cke_hidpi .cke_button__superscript_icon{background:url(icons_hidpi.png?t=I8E8) no-repeat 0 -120px!important;background-size:16px!important}.cke_hidpi .cke_button__underline_icon{background:url(icons_hidpi.png?t=I8E8) no-repeat 0 -144px!important;background-size:16px!important}.cke_hidpi .cke_button__blockquote_icon{background:url(icons_hidpi.png?t=I8E8) no-repeat 0 -168px!important;background-size:16px!important}.cke_rtl.cke_hidpi .cke_button__copy_icon,.cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__copy_icon{background:url(icons_hidpi.png?t=I8E8) no-repeat 0 -192px!important;background-size:16px!important}.cke_hidpi .cke_ltr .cke_button__copy_icon,.cke_ltr.cke_hidpi .cke_button__copy_icon{background:url(icons_hidpi.png?t=I8E8) no-repeat 0 -216px!important;background-size:16px!important}.cke_rtl.cke_hidpi .cke_button__cut_icon,.cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__cut_icon{background:url(icons_hidpi.png?t=I8E8) no-repeat 0 -240px!important;background-size:16px!important}.cke_hidpi .cke_ltr .cke_button__cut_icon,.cke_ltr.cke_hidpi .cke_button__cut_icon{background:url(icons_hidpi.png?t=I8E8) no-repeat 0 -264px!important;background-size:16px!important}.cke_rtl.cke_hidpi .cke_button__paste_icon,.cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__paste_icon{background:url(icons_hidpi.png?t=I8E8) no-repeat 0 -288px!important;background-size:16px!important}.cke_hidpi .cke_ltr .cke_button__paste_icon,.cke_ltr.cke_hidpi .cke_button__paste_icon{background:url(icons_hidpi.png?t=I8E8) no-repeat 0 -312px!important;background-size:16px!important}.cke_hidpi .cke_button__horizontalrule_icon{background:url(icons_hidpi.png?t=I8E8) no-repeat 0 -336px!important;background-size:16px!important}.cke_hidpi .cke_button__image_icon{background:url(icons_hidpi.png?t=I8E8) no-repeat 0 -360px!important;background-size:16px!important}.cke_rtl.cke_hidpi .cke_button__indent_icon,.cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__indent_icon{background:url(icons_hidpi.png?t=I8E8) no-repeat 0 -384px!important;background-size:16px!important}.cke_hidpi .cke_ltr .cke_button__indent_icon,.cke_ltr.cke_hidpi .cke_button__indent_icon{background:url(icons_hidpi.png?t=I8E8) no-repeat 0 -408px!important;background-size:16px!important}.cke_rtl.cke_hidpi .cke_button__outdent_icon,.cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__outdent_icon{background:url(icons_hidpi.png?t=I8E8) no-repeat 0 -432px!important;background-size:16px!important}.cke_hidpi .cke_ltr .cke_button__outdent_icon,.cke_ltr.cke_hidpi .cke_button__outdent_icon{background:url(icons_hidpi.png?t=I8E8) no-repeat 0 -456px!important;background-size:16px!important}.cke_hidpi .cke_button__justifyblock_icon{background:url(icons_hidpi.png?t=I8E8) no-repeat 0 -480px!important;background-size:16px!important}.cke_hidpi .cke_button__justifycenter_icon{background:url(icons_hidpi.png?t=I8E8) no-repeat 0 -504px!important;background-size:16px!important}.cke_hidpi .cke_button__justifyleft_icon{background:url(icons_hidpi.png?t=I8E8) no-repeat 0 -528px!important;background-size:16px!important}.cke_hidpi .cke_button__justifyright_icon{background:url(icons_hidpi.png?t=I8E8) no-repeat 0 -552px!important;background-size:16px!important}.cke_hidpi .cke_button__language_icon{background:url(icons_hidpi.png?t=I8E8) no-repeat 0 -576px!important;background-size:16px!important}.cke_rtl.cke_hidpi .cke_button__bulletedlist_icon,.cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__bulletedlist_icon{background:url(icons_hidpi.png?t=I8E8) no-repeat 0 -600px!important;background-size:16px!important}.cke_hidpi .cke_ltr .cke_button__bulletedlist_icon,.cke_ltr.cke_hidpi .cke_button__bulletedlist_icon{background:url(icons_hidpi.png?t=I8E8) no-repeat 0 -624px!important;background-size:16px!important}.cke_rtl.cke_hidpi .cke_button__numberedlist_icon,.cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__numberedlist_icon{background:url(icons_hidpi.png?t=I8E8) no-repeat 0 -648px!important;background-size:16px!important}.cke_hidpi .cke_ltr .cke_button__numberedlist_icon,.cke_ltr.cke_hidpi .cke_button__numberedlist_icon{background:url(icons_hidpi.png?t=I8E8) no-repeat 0 -672px!important;background-size:16px!important}.cke_hidpi .cke_button__maximize_icon{background:url(icons_hidpi.png?t=I8E8) no-repeat 0 -696px!important;background-size:16px!important}.cke_rtl.cke_hidpi .cke_button__pastefromword_icon,.cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__pastefromword_icon{background:url(icons_hidpi.png?t=I8E8) no-repeat 0 -720px!important;background-size:16px!important}.cke_hidpi .cke_ltr .cke_button__pastefromword_icon,.cke_ltr.cke_hidpi .cke_button__pastefromword_icon{background:url(icons_hidpi.png?t=I8E8) no-repeat 0 -744px!important;background-size:16px!important}.cke_rtl.cke_hidpi .cke_button__pastetext_icon,.cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__pastetext_icon{background:url(icons_hidpi.png?t=I8E8) no-repeat 0 -768px!important;background-size:16px!important}.cke_hidpi .cke_ltr .cke_button__pastetext_icon,.cke_ltr.cke_hidpi .cke_button__pastetext_icon{background:url(icons_hidpi.png?t=I8E8) no-repeat 0 -792px!important;background-size:16px!important}.cke_hidpi .cke_button__removeformat_icon{background:url(icons_hidpi.png?t=I8E8) no-repeat 0 -816px!important;background-size:16px!important}.cke_rtl.cke_hidpi .cke_button__showblocks_icon,.cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__showblocks_icon{background:url(icons_hidpi.png?t=I8E8) no-repeat 0 -840px!important;background-size:16px!important}.cke_hidpi .cke_ltr .cke_button__showblocks_icon,.cke_ltr.cke_hidpi .cke_button__showblocks_icon{background:url(icons_hidpi.png?t=I8E8) no-repeat 0 -864px!important;background-size:16px!important}.cke_rtl.cke_hidpi .cke_button__source_icon,.cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__source_icon{background:url(icons_hidpi.png?t=I8E8) no-repeat 0 -888px!important;background-size:16px!important}.cke_hidpi .cke_ltr .cke_button__source_icon,.cke_ltr.cke_hidpi .cke_button__source_icon{background:url(icons_hidpi.png?t=I8E8) no-repeat 0 -912px!important;background-size:16px!important}.cke_rtl.cke_hidpi .cke_button__sourcedialog_icon,.cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__sourcedialog_icon{background:url(icons_hidpi.png?t=I8E8) no-repeat 0 -936px!important;background-size:16px!important}.cke_hidpi .cke_ltr .cke_button__sourcedialog_icon,.cke_ltr.cke_hidpi .cke_button__sourcedialog_icon{background:url(icons_hidpi.png?t=I8E8) no-repeat 0 -960px!important;background-size:16px!important}.cke_hidpi .cke_button__specialchar_icon{background:url(icons_hidpi.png?t=I8E8) no-repeat 0 -984px!important;background-size:16px!important}.cke_hidpi .cke_button__table_icon{background:url(icons_hidpi.png?t=I8E8) no-repeat 0 -1008px!important;background-size:16px!important}.cke_rtl.cke_hidpi .cke_button__redo_icon,.cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__redo_icon{background:url(icons_hidpi.png?t=I8E8) no-repeat 0 -1032px!important;background-size:16px!important}.cke_hidpi .cke_ltr .cke_button__redo_icon,.cke_ltr.cke_hidpi .cke_button__redo_icon{background:url(icons_hidpi.png?t=I8E8) no-repeat 0 -1056px!important;background-size:16px!important}.cke_rtl.cke_hidpi .cke_button__undo_icon,.cke_hidpi .cke_mixed_dir_content .cke_rtl .cke_button__undo_icon{background:url(icons_hidpi.png?t=I8E8) no-repeat 0 -1080px!important;background-size:16px!important}.cke_hidpi .cke_ltr .cke_button__undo_icon,.cke_ltr.cke_hidpi .cke_button__undo_icon{background:url(icons_hidpi.png?t=I8E8) no-repeat 0 -1104px!important;background-size:16px!important}.cke_hidpi .cke_button__simplebox_icon{background:url(icons_hidpi.png?t=I8E8) no-repeat 0 -2256px!important}a.cke_button_disabled,a.cke_button_disabled:hover,a.cke_button_disabled:focus,a.cke_button_disabled:active{filter:alpha(opacity = 30)}.cke_button_disabled .cke_button_icon{filter:progid:DXImageTransform.Microsoft.gradient(startColorstr=#00ffffff,endColorstr=#00ffffff)}.cke_button_off:hover,.cke_button_off:focus,.cke_button_off:active{filter:alpha(opacity = 100)}.cke_combo_disabled .cke_combo_inlinelabel,.cke_combo_disabled .cke_combo_open{filter:alpha(opacity = 30)}.cke_toolbox_collapser{border:1px solid #a6a6a6}.cke_toolbox_collapser .cke_arrow{margin-top:1px}.cke_hc .cke_top,.cke_hc .cke_bottom,.cke_hc .cke_combo_button,.cke_hc a.cke_combo_button:hover,.cke_hc a.cke_combo_button:focus,.cke_hc .cke_toolgroup,.cke_hc .cke_button_on,.cke_hc a.cke_button_off:hover,.cke_hc a.cke_button_off:focus,.cke_hc a.cke_button_off:active,.cke_hc .cke_toolbox_collapser,.cke_hc .cke_toolbox_collapser:hover,.cke_hc .cke_panel_grouptitle{filter:progid:DXImageTransform.Microsoft.gradient(enabled=false)}.cke_top,.cke_contents,.cke_bottom{width:100%}.cke_button_arrow{font-size:0}.cke_rtl .cke_toolgroup,.cke_rtl .cke_toolbar_separator,.cke_rtl .cke_button,.cke_rtl .cke_button *,.cke_rtl .cke_combo,.cke_rtl .cke_combo *,.cke_rtl .cke_path_item,.cke_rtl .cke_path_item *,.cke_rtl .cke_path_empty{float:none}.cke_rtl .cke_toolgroup,.cke_rtl .cke_toolbar_separator,.cke_rtl .cke_combo_button,.cke_rtl .cke_combo_button *,.cke_rtl .cke_button,.cke_rtl .cke_button_icon{display:inline-block;vertical-align:top}.cke_rtl .cke_button_icon{float:none}.cke_resizer{width:10px}.cke_source{white-space:normal}.cke_bottom{position:static}.cke_colorbox{font-size:0} \ No newline at end of file diff --git a/web/core/assets/vendor/ckeditor/skins/moono-lisa/icons.png b/web/core/assets/vendor/ckeditor/skins/moono-lisa/icons.png index cf5548c7b0fc1518a7f18edebdfd836a0a4ffe32..331a155f7e77d608bcecc95060556417af6da4b2 100644 --- a/web/core/assets/vendor/ckeditor/skins/moono-lisa/icons.png +++ b/web/core/assets/vendor/ckeditor/skins/moono-lisa/icons.png @@ -1,12 +1,30 @@ �PNG -��� IHDR������������1��QIDATx��]��U^ -Q�*�5���mPK��VYw�;�ٙ�I7ݭ�55�ڤ�H�H;ؘ��"5�hֈ����J()M��PL�>(h(�!��$3�;��ܽs�������Knf��=���s�{���}}�B.�۽v��:OgGGG�zgf�FFFt�/��t���d&$��� MV��{%!��ĉ�������*���J5źFhU�$��h�y�T��3��3jK]�2�$Ԧt_��� ������4x�w����+��B�S�c5�"�������@��E� {( -{}�П ��H8�%�w��^.i��%���D0w s^D�$���K�b�R�J<&�����RZ�Qu@��;^�b���B�Q���f��%_ ���q�wW��H,�}��@����.�Y"��|�e�:�`��`�;J�2�CCC�F ��I�m���r6�4J%M>�����SƝI�gL���������C��rK�q@$hn0H���:آ�|L�S�a^P�����}K��f/���'yc^���(�ܐ�Q�T~:���^���~��\.��2�흱T*��U7>��*�$M��Q�V/��7zk�*;��]�@��X�'�x�`��� ���l�dk��ჺι8lذ��:�̝��c�9q���� �Hua@���.R��j��d;�m��Z�1N���ھ�I��I������N���������WՍ�իY���X�&s�X�M"�Fb��{�!��R���`������G|�e��P�L�J���"Hv��w���/�vy�c�-Ԅ�Y_b -�yS��O'?*e�i������#y�0�'UT�������$���t�X,�p�F����t�5��1O_��o���a��W�[o�0P -����49����ѕ�'�~���\�:G<z�dSenݺu��e���9�����"]橩�x��6/�.���j')�z�d�|���&:���1C|7U�$l��Ʃ��`�>���'�t��{�bB>�$f��<�8�-�R{�!M���ׅ�Z�*�E�+����x��^���d�)�ט��7��ݟ����.�f�:�/S���#�� R��r�@���x�3e�,{�;($\�T^gy6i�Wk���+Tk֬Y=n�fS���G��\q�')�)���R+���c/��b�$g���D:"U�\���"��Zm�e�&�C�N*L��&�\�)juJ��u.�*�G��/�����`��p=�x��^�/���"�9�R�4*���΄��s��H��a��v�R�XB&ԝ�%��LJS�d -�m����LJ�Fk@n:�i<-���x��^�/�@昞���$h0=�,1��ڛ��Е���-��484c�C�B����� ^C��F ��P(�I�=�����*�������gu�G���V���~[3N~�T��Fw$����N��0�#Z�g�g��� �ŗt�LT��o�u@����`xiж:�~�[��pB����M_j�8k&E�6{�&X���Qu�A�uУ�����Z6Vn�Д�|��<_0j����ZnH��1��Y�2)�וu�5����:H� �:��~��@��$�����BE�� cT��7&?�Y~qVj����J����I�ؙ���/r�n-��j��|!��:o��Τ��(�ʝw��/���bnqEpC�sx�:��`z>���4$q�N~V}F�~��j��W�7c��d��2g�( ��lꚮ���̋�Y��|��z����U��Ii�+{j�"O.����,f�Z��*��3�w�#q}�N[4#��� 6�����2������KR!#�ּ��A�Q��?�� -�N%�S��ewF�.v:���JL�+����n,u�Cs?���;-���+����:P(v��J��V֝��w�Y���.��EH��,�1�#eڕ�� ��2�oߺ<l����v�]�')�����(lǍl+�W��DV>K�Xi�������ni �\R?��^���6��k���zί�e���i�6W4������=8_Hl�nw�������}�����]� ������� ;&���W�N��$#���r+���d4�i���U*���b��U����� @��VI��b*�@e�8z\U~��/���c��O�f�����^�/�����������ե�I��놆8��\������$�9>�z�\���R�:�ry����pA@���G�BaPh�~_3�����,%�A]b�fV� C \���`lll�m�-z�Q���������b���٘������~mEh -F@��������?|�_K4P���m�r�%�V6θ��\���WXyA�t\^��g1���|>����\����>���Ӓ����S=,��?"{"*�aot�'�Xy����#ǝ�F�ɯ��,$��N H�f?|��?Ͷ�'^�]L}����[��Z.`m��>� -����2͝�7n���G��ca<8;�N\ �!H�����#!�p�g�$�+w�O8����+2gX5`����i��yބ���q�� ��B9!/s8�0_�|������0_�|�Z�R������}�A)�������k�(?!J�1�+}N<�J>��F�ϯtĠ٤ЪR�,T�y�������C����<���Ź�;/oR�ғ n2i�g�I{^�V[ ��f�I�y�ƍ�K�mѕoL�0 ����*��_�2?�~�Z��n�ur�Y�߾��h�W��_I���j�+�o.��W0���V�K��^f�u��-���`��5��>cA��J�t%��F�[e4X��R�y��9�˝ьwQ����W���[\/�J���$b�R6�����V.� -a_ 2U"�ӱǹ����HZ�zu�֑��m05��ܠN���I����L�0NP�,s�ƌ��{�u歷��us�/��|�J,�'x���x�Ǚ�7U��z�6B�|}t3�||rG����^�/���8�H�#�|�ҥK�)�orr��o߾�����_���144�M6,/s���}������W.���6�l�����$�d��AFk��+<o���D�4�Fk��;00�A#���,I�Zb�Ł���/�6�!��`����IEND�B`� \ No newline at end of file +��� IHDR������������1��cIDATx^��U�$������ +%> +������vw�i���55[l1����"1!*���`�`���J +A$�0(>@0�!�@�(����a�����;��7��G{~�a��=s���~��[����E�b|||��ݫW�ކ>Q8���[r?�PO;ٙ�LLL\D��L�ר$[1��8RМ�S�kK��Z@����&�S�iRڲ���8����2�G!�U`!���[�&��I(覲��h�7Pw�7�%hK2;;{��@/��Ľhˆ*y>��Y�����+�̇��� 9�^'@ٵk�!S��~%;IU�\ 9�%���H@�W�>��t>�ο# ��0��$�djj�X����$y@'��g0�^�@�W%�����LI@[�k��F�xJX�R��'n$z/Ę�V.R�ҽ��i`ӦMG�,,'�g�ׄ/�����}QIND[��+W+��-Z�.��і���v5ڲ��Jށ�$�lw�~ +����S��e�����R�H�*$����8N&�l0J�I=#�j����qJkA�����Ǖ�c�|kVU�uh�B*(����mi�A�(T�$^���������^+gff^BWfNOO�u���(����H�{����{1���]^+ +m{oŘ����+�)��./���8ΰ@�u7O[��G�N�����5�V��h_���>�E��\.&�C�(:Ir��� +��7R,]�ik;�t���Rp��D�<��s�=�0��wh_&H���}��k��}���q�׃���q=h�XH��� �����zд��z��I�^r� +��ic�E�.�R�6�_k_�q�2�iv^o�ij?������Z�k�<��7j}�b&��ߨ� �oKՈ]�Z`wj}�8��@�%1ɕZ@������֍�?"\�15��ƎRUԄ��o���Oη��Pe�G��'V:J��8 +M�9zS�G��f͚SiZoF������6�Ї���v�hUe��Z�Ǖ}�kS{/�o>M��QE� ��qrrr�rx�;�_��ի�F=}]hE>��z��|��>��l۶��^f�]A��:�m\�e�G��ٴi�ae�/�6�nݺז��..����+�4[�&P�$O���棲�Y��:���w�!C/ZhQ���6;���G����%`�$נ�FS&eO;��8�"�oY t[(��*���p���6��u�@ʞtHٓ){�!eO:��A� �8Nw�.�}���S$X�+�n�/�!eO:��I��=鐲�5&�8Cݦ�NMM��z�V�ShUڍ���#�轞�sg�s �l��Sf9�F����9R�'���=m)�C��ު�]���}���X�A����0��U��@�F�w�7BAO���D�@{��(��2�G�'ݏK��:����({������l��������%�a~~�`>'�O꒩}#Ƀ���I�����%|)b��ϕ �Kx�Y����xˁt�`R���q�����X&�}�\�$������3l��*-���^-�Gc>g�zti���v>oJ@�e�Q S��5�L_S�L`��5&���H`G���g�����H`G��T@r�n+}�Z�{�@���>p����͘��� ��kL*0���� +ic�Z��������������l߾}��`|w���`|w���`���E�,^���_��`|w���`|w���`�����J-�ʗ����X.��q��03�Y^3�\V����L�����%.>�fZ'�w��^��&����q��-c��+ݐ���(�%X%y�L@��ѹIj (�萒Z�A�J�8N����Y��zRǥ�ٴ +Е`������"g��?˞$�a��A��1�c6����v�����u���Z/��y� +�X�W���V�����{�썕TA�X��u�]�� +�+i]�9���Gt�����kDVBM��] V00V�q�M��d�:Y�l��� +�M��${�g?��Dj�@f��X�cM����U�~��ҙXk"�c������ +�/J+gfx��qZ�S5%�=Ag���`|���R���t{H �wO�8�"277��uZ��٩I�qذa��XnJ7�������X���A��2,5%�`�^�9����z�aP���^�cЩI0vq�^,���l �,.�[J0�{�q�"8[�Fj��5�K�`l:5 �..؛%S�-���`)��� ���0}bbbϯ��D� CΏ�����ǫ)(�����Y�����n�&��{ս����a�X���س��uh�T �Y6f�X�dT ���8�7 -��_:?C>&ۙ:>ܙ�Ɔ +L}6�/a���nc��*dV`��| ��d�3Lf�<��L��10�K�]A�$bc�=��W!�X�� +b��8ξ&wڊ�ֵ�L�[c&hC�VUC@� �O�K01�K� +��6t��qp�ϙ��2e�|i*h�>�Xk��D+{� +�Yh��8���r3���*#���j�-'At2E��199y�iT>"⫍?��*&�p6�b�dltD6t}+�,D����Vn=�g���e�kY���!�e|ޔ��ǜ�2��k*#��5 X�l]�$�ڱ])А� +4��"u�]sD��]K@��<���J@�G�� +�7|jm���w,;��VO`��5&���H`G��s��"�� +t�+P�Q,q4�-�W��9�)K�/���M �y���@;�+����TѶ(ڶE�v�hj��y�9�X�}��� �q�Ƥ` 쨐6����?P�m���@Ѷ-�</��y�q�����wB�Ÿ +�TN�I����LLJդ��t}�w��ξ�Ld&4����^�z�Iha�X%�ړp�����H�'�t��\-[��= ��C�˺A����p�j|��C�]�z�p�$:>X�T[@zl�-�ѦE$�ﲪ˂=��%��������;I��y��q����G������{>u,�����I,M$�%�f���J���!u,���J�f�~���"r�F�Q~� �Xn�,��I$Гijjj���ek >�r��G��MG���ne�IW����Z�\� ��p��� r�&�w�%�G`P-7bK8� �<Pk�ne�/Xb�M&���Эz5��Zп����UM�\c�T0M�e���h�������?�#UU�c���:�M�|�˫�������>����� :�����Ы�/���m<�e�76&�#%��$+��p��ij�_�6p�zg��x���p��(��֣_E��D�ؐ+�8CުZx�E������3/���є�I&I%`8I�rr0Q?4�^�/��*����i���m�_ 1��_m�6/���B��A�|Y��#X/{��U����r)~����%ܪ������'��~5�@{�Dy��C�UD @ԏ ����3���B3Q?4��y�����3$୪%�[�t�tn|��4%`�IR N���L� ���y��"���3�LOO�A���t�+ +�a�&���:�����%�S�(�Ü�\�ߣm��[��Pe������kF2\�3]����:������H%��f��2�_Z;�|GQ��}�?��ΏUp�i�(��L������ +z�ίK6o�|��j}���֔��If�mtt��L�m+����(��̎�K-��D��T��[A����?���P������9��H�.�9�@� +�PU��(k=�J�8KޞmeI`�K�.j��E ���!W���"�̹��!W5�ꢆ\���`R�q���2���x�Q�E�-���z՟���{��HΣ����9�c�ѴD�{(����K�G�@~Z9���@D~#N�{�$;��F�e���NP�t#��R�9�3�4M�,da�EmY�u���݄���xOЋ)/��_�k>X���VP�c$�57�xO�`����2�^��M��{��U���z�3���elZ�;�H����sւ҄^���/b^�����u�ʩ ���H�%��H�s�p���/t���7.�رc �ؑ�����+W��AZ8����+;�nݺ�.2233�^�"��P �o߾�F8���r� +�XYy���pLK������WPĮX�b� +�XI�=�$H0U�a�ҥsg���/�6�u�Do����IEND�B`� \ No newline at end of file diff --git a/web/core/assets/vendor/ckeditor/skins/moono-lisa/icons_hidpi.png b/web/core/assets/vendor/ckeditor/skins/moono-lisa/icons_hidpi.png index 9547434aee1bdd3b25b319413d8ac4a17c531e35..1979dd167ea54095b328ad3ca96850e7546b56fe 100644 --- a/web/core/assets/vendor/ckeditor/skins/moono-lisa/icons_hidpi.png +++ b/web/core/assets/vendor/ckeditor/skins/moono-lisa/icons_hidpi.png @@ -1,39 +1,53 @@ �PNG -��� IHDR��� �� �����N:��*IDATx��]�eEy^A#"|P���%FEE�G2��w治0d�uɺ(�5���u�ĀE�*�@H�����e@y�F��@T�Y�l���[������>ݧ��3��}U]�ι���Nw�3��_�ϚT@���2�`����*�}��=������&o����Rn�n���5Rٌ̹B �Bb�����7o�T�����1s�=ϼ��R����8#q�<���c�X��uxxx����ҵ%wȿp�EO�]��ʕ+_h������*�Su�$�����#HW���-z����3L���7p�6J�>)�ѹs��@���ƨ�[�+��1�bŊ��]# б7�f����ibK�.gW<Q��/jkiP7e�Z���Ӎ�9s��*��5n���Ϋ1��4��ؒ%K�u����-t���x2�QC��F6###��Ɖ�C�74����W̄��ߎ�N��A�5n�^h(>��?�7j���[%�*�#@�b���ٳg�*�?���G��/f������`�����'|�x���tl��~5��J����2�Z�r��yw�"�`aXw�&Z���a��<[�F5���, e������y���z��'A���5���/^����s��N���]�ҹ7�s -�?�F�����8j�42��� ��[�U���Z�FH�3�s���%�'H�?��L@q\2d# �w��c��2z����9��9/��sH�N.��<���2zľ[��M��:����)�=A`�R�KM�����wE,�p����ּ�ݰ�2��0}u;���B��ܸ�w��~�IWm�+����$t)D��I����Uf"���+o^���<X��(��N�J���M�L�"��o���������������'�|�e5��t�DZ�v`?Z�������#���uυ;����d��t�n������F` -;�1s��9�{�ۈ%��j0��1���'�!ʊ��n��ϒO���Sin�����>��ǿ���D`[�?;���nc�/^�Z鮝={�p���G�K��.u�����u��x3��A�%�E�4<_�N�6R*�S����������8�~��i� ��Q����t��L���+����x.�V�1������_V�y9��1� K�����n�G��/�g�jz�2�{��,~C�K �̀z}Y�"mi?]����vZ��u���W<)��X����x�� ȥ�E�LDי@�چ���q���-�s�H*>�6XEK&����ꗆ���ض�4�+&�d|E-?��Or� ����R����P�K����zO �6rǐ��[�q-�H<�8Tn�*_I�r�%�,D�����?��K���+�+Ж����H�>LGe!x?]��]�T矒z@����|%�;Abl�!�I"@�|��oX�hqEɛ���������F!�ׇ�c��?N��/�������������t���[��_�p�C�9900�d�S*�U�y�?�]�q�ԱC9og-5r����`ƟRrϘ��d�d�^�҉������*��)D�L���cJ)��rG���a���k�-���.��Kߨ��@c��ko��s��U�q;�K�o��ٗ�m|L3D=�mz��A�\��q��]윟�����&v�ӚnP����S�9Q�whD�^$��ez��$��=d�sp�TAY�x�K�K�����{n2�\ #�]��! !�lo�@-��.f�H��� ���<�hm���������Y�._��g��4#Cc�.����C��`{�C �!���= �b�b �z�6��v��+g�q�bb\q�T@�e�b|��ڞ!�������z�:���S���?�o3|�������wxR�*&��O�����M1�Ʒ���ʕׯ�����7L��WL�Ѓ.�w� x�cܖ��e|�t���V�m|L['N�M�� ��2~�c��]윟8�ߔ��f���Y<�2S?5z���}���9m;�B�p2z���(&���������@4�T?7n|��|��F&��v�K*��9.9�nI���1�n2x�<�ȿ�2�n<��}~�<�����rY��|2v�<?�@��Z��IC��ZP�� ��m2wQ��qzܦ샜F F���ؑ� �%`Vb��R-)�Rw�RY����I(<���_�!<f [G6���R�������X�lȸ���}����y��Z��<�������ʮ=퇆�^i�9�A]���(@�q������ �>�g�����;fu���J\�Z�[oA-_R�����4$;"cT~K��+��|xb�K���!���'A��������������]�`�Ӆ�����7̣_џ��� -��l5�����ի�#��p�ehh訲6/^��#��M�� -g倝��/��g����V�.�8p��']Ʃ��\��� -��ǔʮ|3R|�)&��a/s٫m�����L�k�@@枉�5�O�4�s�{���1w�ܿ�6J��}���QzI����H�YƼ��Km<� ���s��'�B3B�LRu_����@��n����y"���JT٤�����d�����w����Mf,���*�Wα�q�}�৹c��>2�8չ�_�dɫ����V��P3c��暿�j׳�lL���>V��5���T<6ZQ�D�_me[NL� -�r���/�]ydd���6������� -�g� �q��~ZV�}l];:��d'r����K�~��8���ul��Y�&.1���0�D���|���BcC �Yv*��T?��TL{e�[�+~v4�+��NG�����lb)S[kl{�n7�D��X7+����6gd!�-5��I�A���`$�n����)�]��.T/���U�%ïJ���L�$��u7��HM���.hZH�7������g�?K�r-�w��ϒ�b|�d���������N@/�^���z����@/�^Pw��@/�^���������ؽ��vyfJF[0YZ�T��͠���<]�9k����V�&�=SG�Z�d� �CSB`T��������^OD 㫬"ڜp� /r�1q�< �}%R�$M"��A��Ij -1?ˑgL9w���1��%=<z�(������N"@����q�{��N�3�I!tA�'"�Fw��-����>�5Մ���j��� ��L#�t�җ���$e�����?$��E�zes����Y��q���}n-Ƈ���[h[Q�ϩ'����l=M�>EW��LH�9�z�|�|T**d��lb�B�f`<u�op�K�uO/}ӱ���f��`�L�&�~�m���o�!c�k6�w%ȡ���ӱ����M���C����NDO-㇅�b���k����%=w��.��[��c�9����1{�҈��6���b ��"`R��@�t^�]a�gj���秺>��O+#p?�|���yj���)4�� �#�+V�M�����<��!=�m�M���<.�ēt���o �`;���,�����������^���z�����^01�@/�^���z���������f.�W����u����k� 0)Q�L���5x7o����jᒽG�;���j�qW�`O����O����e�^2�u�uF��_�X���]_������7L�lG^�zb��v�$0�{ �i�k�Nf�Q�-�J�$'�y�����y�J33���י�'���'�e� )Q|^,W�܋��g]Pz���IqJ ��@홙bRC�<�!H" =�Ux��@JB��(KZ�#)N�������-*m ��=η��ԃeW�H^"���̢�#/QRVW��ؒ��(-)RL���?r������P��@/� -x��QL�@/�^���z���lO@/p�j�^������P/N:��:��'�`����E�4[&b�J��������R_��i����7��C�r��Y0��70�����������!�-�e���K�s����*���+��$�O�}`�n��V2��T��_�J�� ]�|fم�a�K@n�#�!�@mC����u�s�̹�7�sL�(U���^��4�i'5n@�Jz]l'j�A.T��N;9�S���v��Av|���+�/��O�Ƀ?�>�\K�E��Q�s\�>��k������s�7d�?�o�"@��v5f����U��<�����ל�cvhT�H�z��C(mQ���B�B`\��ZU3���!�q��"A�����m��*W�O!�����R�����HB!���C��������l0�ԁ��ͭH� :��QO�9�j�;289$�C��T�EH���5�Pp��ݎ�E7���$P� ���:Ǽq���D���X�z�s���1��|s��^W֖W1��)%��X�Q)��>� A -�����zAx���]�9��MɈ�:��&H�t%1����N���#�$\=�%N�u�Z\�Z �y�����������8�U��b��M�[688x@[�ot:��k1@��n�+�߷wͅ�?�/� ��d�.0�@�e�K��/�Z�O�2��^�����@���&9|�qj#@ρ v���R�Lݼ�6��ڇ������~�,��J D/�s�d��"� Fs�B P'�D���6�����T�g�M�z��7 W�Z���c�LB�mhz����I]��j -�ȑ����M���ʖ-[�����Nh�+�<w���裏.����*n�s@K"�|�5����oe��M����/��[�8�����V�:��������,_��� ����kȉ�í���!���s2e�/( �2⼒���^`�$���B��+���9Wj�e@|�_�����������o;��}7}�>�� ��'����Z��l�Ҁ�����]�B-�����m p���/�e�J�1c_M ��Y�RB���Ј���n���1q�ĸ�����I�CCC�#���� -i�V!�n�l!1�$ �J-=Ъ��v�D���o�n_�sV��|B���=��u7�s'������������=u��\J��b7������9In�:��'��b -r� ߐ���;�&j' �&�E�|��`1��}�5���QC�y��"��RJ��v�)��CJ4k4W "Pg�$/Ee�B��|�r_c�Yr�Fʾ���-.�h��|�s��������P �zA2�T� +�V������6$)zAVU�Zq�Ch������������U���_��F���ZGk:�E]zAU�� ���0�+ AJ|Ae����_�D�q�z���������� ��#�!PK>�P@W��Ѻn�Z|AL�_`���i�����%��@�n|��z���������f6\o�����;��k���T���I���y��yQ�[TΣ�_$#��S�B��B�g���-��i�ᣫ~5����d`��x�譅���e�l�`e{�}l�s�.������~cT��s'��!�իR�.�ݚN����c��:���Բ�R=ߕ HO�v<�@����e�h9w�� ٵ�sB�O"����W�B��E yhbp�s��:ԧ��u����@HCe{�֟�A���M�(��.`�iCL�,C3��[�#���������������0��c��D�lS]6����\nyW����jue��Zυlj����'�C�Z��3Ʋp�%>BZ��ٮ!0�2�{���y��o\9�=���� _&&W�!t�obԦc�����bb�f��ZH�u�G/��*���0�o^�B��y�ѱM�����]L�f__��d4�����������F����� �GT����c��F3p �����wON����3�Fgx��{��Qf`��t_�F�$������/� �۰�~ȥ��N�a�����k������k]+����C��`��A��?��0 2�P+�~�����������4��q��o�V�R9� -�E��݇@���gP�@�8�@�ٙ@�U�/31q�W;2�T������w��Z϶N ��m��.�$&:�e�P�1w���}@�]^'�V3�Ε:o��rG����������@�����K�<z��Ҹ������q���E�.@hp�����o9�!�|�e��ϳ�@�C����¥���m��U/��ڻ�݅�'4��W�s����AC��́Z� -,�i�fo�@k~�ٳgo��}��������������=00P�k� �1xJE��\�|��kC/���^[�c����Col��۞+O��#�bŊ��0u|m��ޭ���P��ܲ�4Z�q �Z>�&s�v9�/ר{�@s6�c4�Vy&ߪ��N�5;�j*|��U�U�|��>�����t�v�@q� �G6�������0����\F�aYo)�^;w��I�����[�'���>�>�<S7�c��������M����L� -���LBj���9�y�U�j�}���n.��!�v5��Tqc�^�%qY�78�.<�W�� �9�ه`�� Z��J� Eۺ�Zs��F�k��*�c{�V_[�?�ׅ.�?]A�s�4ʓ,��j�6>(�AE}%Ӯ��D���Rj�D�u��)�I�X�6������m��w�Q����1�]�0{7[���2.�h`S��M�����������R~)o�2����v��������L+��ݼAz��~k^���=���t�|��+7��z�Y�������UW �<����x��ҵ���=�����~�~��+eK� -��2���ڭ��Fݻ����iO�nw������9p��w�'��E;.��x� x�s����O;! r�g�A�:`�9�l��I �eُ=����e�SϏj������ۼo���o�pyo��E�� �E�e����.n�Ndi�&�{M�^pW�d�o��z�^[�_��>���cz��o)� &_���Ŗ���E/�7 u������X�O��\Z����tzH������������v�u�6��R�4�����b�����R��/^�.|Q7�^�J^��\�u%��zA�����QL[�=SF�h�^ �i��y`��Y^Z���-�J�nP�[����1��u��5���@�N�#�D ����BR�t�O� -�}-�ә� -ҕϏ��nې�|�2����vwxխ��>S\�J��e]��Ң���Z�SB`���%��FU]�5d�ǥ�ן[W����T�@�����ȥ'Ė��lGi�EL��������P�/@|�R<��/@|�_�{��"S�g%�����_PF0w�����W׃�D��;{|Alٗ���yk_�������� +�^ ��7�h �5�z24�@ -.�`ψ/0>~��Ct�˦H}��t:�To��/�/p�ҥ���t����X-��S�U��~��=n��\�� v��C7������ԭ+D�d'�Oj=�@s�������)?َ*� �t� -�������P -�������6d�������U��{wk���n+�e˖���F l���r��\G���T:����Ͽ�^o7u����ߜuX���RG�|��ya�<i�����l����p3^u����n��%|c댤�'�����*�9�2_����Z#h��.���Φm5[�?�n����6�6�&�'���'y��~xxx�Fh~>���w�|� �e���q׃��3}�1�� -���h^N���okH>%��ƺܬ����i�Z���4.Xn����S����5 �J�pBJH[D�3A|;w;v��V�L��*�>�����h(�-H���?-v|�؆����� �jnD�Fu2{��_-=����|�E����?�����������T���<����䈶�j��e��`���G��P����hat3;�98. �;�W��KW��$`w�j�9���@حG������ݘc:�@*!g}�\.�O��;�|�Yc.���:>�G������>(Ͷ��4"P��@ِ��=ɐv�ӂ@#C0-hn6�Q�E@�[�4�fH;.�{ KB�=���@l�|k��� -�����8.v�NЩ���9�jX�4�.��k���ح��"�o�ff -�k����%v���k4伐}JsR������@���s�?���{'�X?��?�M���Rb� �?���� M������;T�u\ -L#�g�!��;�-��r����u ��{vAJׄJ;����W�?�2�p N�sn7|�����!�`H�����I@�{�8 K��_qɏf!��w�m��W^�U����S۩����nx~W��������St�Mک����]0Iz�+�(�vh������������088x��GK��%A����Z��В`�EΡ51u��ĕ����D���X�J����ʫ�=����M��z�&��ֱL�ץ�=���59��^��wj!��?�MY/�L٠9�Q��b҇UmOe�@����T凵 #���B���sA�l�k|xx�%� -��G����Llbr�:�Ng��0����d^2~�gr��%ϊ���N�9s�c�E�;}�ݞWL��J=���8Q&7q���#\�E(��0W&�M7ǻ��Ae�p�z��nz��ʕ+_�ԋ#�OAYR�hgxH��e�)Tz���m�@���7�u�e�^ۿ ����������� -I'�������3.?��y��t�u��]����Tw�$1u�����phW&P�[��D���,������$r��J"�k��l[F{h�@Ab͞�pm�,f(�N@o�:�����2vU0Z�KR<|��J�h�Z�s�A�]�0������h|� 9��x��u�2)���y{�u�i��<wơZN�$���ƌ�����:;��@�S����jAL�p��g��Ot�M����]b�\uo4���J hM�hK���E��'��:�쁔*�B�}s�h%1�N����������3���Ti��/@|�_��� ����/�n����������}��� ����/@|�_��� ���� ���������n�!�r��Y*W/X��*����o�N���ϟ?�\20%�B*)Ey��=<�aj蓮ݛ�uk���1���d�y@i��ڢւ��%Y�w���U1��b�K!u=։�{���n�K���0n}��-zM��TU���z]�7��1����T�C�ʢ�9+ ��������j�����4��N|p�K2 �>�]F�V����by�r�����c�9��'�e}���R�h�1����m�����K�2u�B>�=�:���.����]��d2x���2�/�_�x�~���� -###ϵ�����=0u��J���[��\2&2ߨB@�zzؽ:��a������4�P|'��ު��������=���SJ2�[�G��Gb&�;��7�F6'����)�4�[�9�|�w�ME2p�8�+^�r��<D�yZ�D�C�J8�� -����z�ܒ��� ���r#��&*W3�j��0�������kL�S�!�����.��iDs����~h�k�m�8�M�+B�8��8z� -y��!�����������p U�'(�;Z?8��~NE� -�?K;Y�r�J�Y! �YfYי=�����Nl�Y�'?���k:ɋ�Z�O_�Ė�O9&��U���<�.�e�b�[B���k;/t�}�"���>o�b�,�yDCW��tm-j;o�!� ]M?�g+�F�<.�I�?K:��*z���>�~����ΛBV>�6��}⼘ -�D�.(��B����+�9/�� u^����U� �'�_[<Ah}�8������� .�ފ����?��Z��\h�8}|���z��<M�i�LF~��Qkt���d[N>��}���Ʃ�܈\e-�xϘ�+*��L�meW-��+�����>E[�R4ݐ�E��J �P�� :y��ԯz���<��)�9�,�i7�k�NBA>I��Q���K���������ұ_��'R�� -j�:��<$R�>;���+/"*;�]�<��\K�������"�����=��� �wS�50b{���3:;���u�V�>qT6-]I��d���g�-���������� �i��.���� -c`��� �`�)4�J�!5�z�=`5A����he�uC�8=s\��F�.{�Q�/��������xM/�-"�����%hDN)3��u?:i�k9~��~V�6)�2��+^@�D���q�Pb��F0�@��!�l�m�R@�F�5��*=f���Yo|�Bx ����86/�~�.˞�2��0��j����`�.#����/�J=C �IU~U�������������z����@/�^���z����������`f����������������������������,8蠃�SJ2�N8a�����TL�dK�.��������L�~�U�S7����;�R� ,Z�h�����z�9����c -���n�;�F]�0��Y�����K��@WK?O��S��Y ��U�f!���������������8���������IEND�B`� \ No newline at end of file +��� IHDR��� �� �����N:��5�IDATx^� �vWY�Ѷjűu ֊V]b�e��x��~�&_���Ơ����C��|jpI.m��8���.�D�8���$�X!*���Z��$}���x���}�>�����zr�������}sﳿ����_0��ju������{vvvւ����;�i�?��_����9�^�誏���FfKbkkk����ӝ�&�Y����j��Z� �����2յ�g0&�����'�n5�}W��:�����x��Uq�W|�x1��W=EW����N�`_�>F��{�$ݻj�\xᅟu�=�|���3u<�-�����, +��:uj� +��-��x��j� +�[��/���x�h��5�;�\|�=���`/r3n���\mf#P�C�v�`�� 'O�\����3g�Y�f�fvO��+�.���ͬX�k|��i�]�CH���,ʹs�>���ީ:����,���Ա��Jx �����߫��ۊ�W�E�����W�-� ���o��[�_�!��8qb-�������AA?�9s�G�VLay�ZQ�h�5=I}L�|OBlww��HJL����(�ѷ��Z��� ������8�?S���+@�HH���&4K�8��G��d׃��/T�j��X��BX7>{��ת^5CP]���'�_����N���Uo><���hs�x��7���q��V�$�_V� Ir���V_�� ��'h�W_�0�� �4��s�� |� ���Z�GY������U�b�ȳ�o5H�g��p���� +�z��[l��OD�<��$�xի¯��nJ����U12��v���W����z�|���.T�*���d�T��G��l����Շ�~5\̚/1u��zM�S�o5x'�@C��]�9��Ǐ_�ɮk���6�:�<W�����'�T�%����#���� �'� � �`P)Ay�W��շ������X�V�S �pL�'cN_�YVȋ�~2� Y�d/V�Y� o`0�pU�Ea鶩�bƯR������*�IX�cUo1N�<�4_!G[u���g����y�����!X�k��J��>MP�E����7����ds�����`���Kp��� �Xw���u�����:�q���/�r�'Uo1l�8%[/;kŪ3;��Ή�N����$'���-�34g �Bl{~I�'C�5�5�p*� � ������'دjo�� ���/˿��5����s�c&s���<��~�3 +s�|�����/��Dg�h��x=�7��{�C����m�hoo����a��_mן3�7rf�zgnA~U��;[��V�Ͷ�k�fA��R��b43n# x&l���<Q�D`M�-������ς������[w�~?I��O3����wCJ�W�j���&_�e��T��Q��R��Jy���_i3x��[�c_�~f_�g�����5�?�n,�0(�������+0>3�E����s��E�����{����?�q��}��5_��/'^mo_e ���?�d�|���w���%�l������!��8�SAR�s�p�4˿R��0'?e����g R�3hd��r;v���slV���;Ŀ�Z��L~y{�Ƀ � � ���ժ=�0�MǕ���w�8�����:>TJY�l�w���h�Tu�*ǚ�?�wWBoz��7P��3^!�M���:��Z{PE-�x���y�=#o�Y7����)�ğ0 &�kB~O�g�ޖ�2�������[�_Q�ٱ��π +8u������i/�_��,���r�n���9�;{��v}��7�^�3 +s��s�y��v�Ǭ��$�ԍۏx��G|�܋��I�x����oP=$J���۾�x_G����u�C,ٷ��A���r����wI��M�~�رO�q���\X�;]՜[ٮ��ώ� ��{炁�c�+��l7�yw���X��C��C��F� � � X�M��-����[��^Tc�w�-�S�}�[� �71 �M�5��Ą����y'����=����u�pY2����ӧ?�u}@��Fh�sbb��/�i�KH�>`���OLT��M��?� +pڝ��� z�^��@ ���u���3����Ĝ�������_��Ĝ�ƺ�*3_�����>��o�t;W!!˞�X�%��,sbb��B�>th��'d�sx7K�n/�W&��sbb�ެ�������x#ӿ�Q���91I% +[����kys�=1����R,Du��f��z/��XЗ"0�kNL� � � ���R�?��o������z���z��UCG�v��xL�M��%�Hի�A�����N�-�oQ�jP�T�j��ת�j�z��UL�%Y��X�ת��TT��`M{|�����+P��V6�N�u�Yh*⬌����z��=-��0<|ԟ�F��K ���T�����k�j�����د�~/)}�C?C������c!�V��U��˿�����T�0I�@Tg����%p��[��/�Җ9s��?����j��������Ē�֯������$�V˹s�>I� �f�����rX�G�y�\��F���� ^sb/�m�1��!�aI��$r��_�����&�?��<?%^'%^G�d�K@� +��pj� � � �{'�������7��OE�����y�[�������j�Z��p��W�?������G��r����Q������M����_�¿�v�Q��YcK����s�A�%��FTǠ�۴o����&��t�+Em���}�V�j{�K��@��������V[d�UΉ�N�F������ + TdW��-���G����_r� �Q3U)�~��{�hJ0�}%���TL�VŇ,�P;�Q�ƶ��w\�-�c�ׇ�,�㟪^��'O�p�yU���z�Tn��>��OWPli��:%��v?{K�{T'�>f�����x��X:5K�p�)a6/��/��/V�,4Bpۊkt����gо�q��d�}{7 �ɋu�o�?��Ylٞ����a�����M��ߏ��c�5Ίt�K���G�ON���<e���^��@NJ�;w.�Os� � �`#���ꅿ�����'��I�1�U����O���Щ�������������0�ki3Kp4�zq��o�O��,IБ��@`&�Z�~Zǫ�{��b��u<��e��tS��'����Ş����^�H��䋎�Dx�����YJ�A�?��z�����%Q +�Yi�]�;cH�J�$�7����((����3\���4����=Q��~�ҭ��R�� ����K �(���> �6C�j?��T���ڷ_����L���`���/ßj?��T���ڷ@�k�j�������������j|@ �����7� � hɝ��㼀�L���! ��8/h��2�~������xJP�Ӿ8/��8/�N��4���pI��R��xx&���dN���1�$(>�R�%��>�OBǽ���Ov0�~�������S�';�j?��=�~�����L��\�j�AA�}������;w��8[���h���O����B������G4��#/a6�or= Svww��:9L�=U����M��'��z��<\�7�����W�W:���K?[u >���jI=Cu���j��mS�ի�2+�^�i���>�k���B�;��:��8����`���p�:�l���W�ՙDP�?W���^FoP�x����9��o>}0 �Ϛ����,��������_��> �٫�j3+�yح�-�?+���C<h�� ��m��,������ �d5m��J<F�'��%�1���x 9�������Ds�:f �����q�x�1�7�9�e�%��� }$����ς=�!�^�]�!���KQm(x[W�����t�9�~�ϭ�#�zbU�L�q�y/t�D��A�����_m:0[�ɏ�ƚ���t��{���I�k�����/+۳���S��د�1s�uL��gv�Nǎ@E[�kt�����1��;_�1���/�L�m���O���������!�$����>�����/���v=�f_~��d�U�㞓#��?Z��X�/b�b��̫^˦��Ɔr����,� � ��9��&��eؔ>D������ ��okB���,������ň��@(��p:�⼠I ��$� �� � ��~��%W~��d���e�?;�T0���1�o���Vδ$���ovvH�M���/+�4HI�>���vS�_�n��N��8�:��ͫ���شU�,)��n�R�x[�~=���L����X(Ve:�j�Պ���'�֦PJ��Nվ�8����A�O��X��w�k�w�K ��K�K +��E��j<~��%Q}�w�`_K� L�����:���PJ��J+T�俨��/���CI��F�k��x}��}5P� +����Y�'����J3�P�$ԯI����V)�&�$}���>�w�z?�j{��g���h����:��t?E�o5��#�ɸ�*9~�x�� � ���v�TH���8/�N����?�j�Պ���{�KSJ�t��K�K +��E�� +W~��%Q}�w�`_!Q� L�uB/�� t()�á���V�D�QA�y_��}���)�%����J5P� +��k�����J3�P�$ԯI ��`%�}�(q^AA�8�{���YR4^5�[4^�A�ln�x�`n�xA]��E�uP��E�A�B�O@ƈ�o�j�D�}�1m�trc]��R;�騶_�Sz?Y�[R4~���<���A ��t�%�[4^5�[4^�A�ln�x�`n�xAAAТ��r�}5�%IVɴ��@����� +�l���� F�N����e���Sq֠ӯ���f3�<o3�sd�g�-��i�4���p� (���X�~t`�-H֊Y��}'O�|�����2(��|�v�fd㰤��c�,�z��e�db>n��f�|Et6N� a�f�S�3�T�l�����c߅�i���Z��%�OJL��z����X���#tP''6�B�e���Q���n}�WuRb���a���Ig�]�N(Xf[�/���u�vW���[�<3�"�M��4�N��@������$X���;�C|�5~��V�!��M@� �̟�� +��W�{t��{p�������j��?�+���ˉ�� � � *������M�>X�����z��o����i�Y!O ����-��,O"����>��x?;LL�7�b �-P�%OV>�� ,2�hU�R0)���_k�����?9����Ft| ����+��T�>�p/�u��Q�W�i� ��A|ߨ-������?�~�T���~6|~ui��m7 +����# ��V��0���ЇR�h�^S�πO�� +�����q�H�@4�����$� � ����>��,��H�����tl#X�P-;s��tl#X��V����,�������=���Y�<�ۯ�/��/�� �d1��yEkw�8�����l^��m� ������m���I�ܣ$������6�O�m��ƌۖ�ӵ[��o��S����}���ά �%ˉ�|�������|4r�*�D@�O����}ZG,b +#{��݂x�����Ch�7����+�-�v�LZ�ZlK: ��*j?lAS�=?[�0�K.�d�,�u�m����xb���|dq��+���%��������4ؤJ���3p�رe~$+a�oB'N�8??�� +�ڬ����ܞ�'β�AAAL���|��GZN�5'�����{�x�>�\Bj��TB����01���%�@E�|�:`�VL����`RگX��}�P��t�Z~��?I��p/kD��'P��<G�ߢ�}'���f��FQ��?G��0��+�;<<Lo�Xtr�ΰ���S�g�����=�jV`1f+>��}}4,���A��>���>�z�E�}|B|Vx_��X���o�{E��� � � �o���{~�s�E��"��Y<��ϼG0���:&T+�ˢ�H���O=^}ۏ�n4t���^����%<��:ے+�{��> ��|�)h�$�evBg������Xп��>��&ꟁ�]˘��uF������x������{M��� �������| +�U�o;pz^K��͌�9��� +p<%�%�e�k��O%���v�ф6�F��o���=� � � >~�A�/^}�v<%�������^''���-���-/����R��:�6�F�vpeA�m����a�C�DJ0Ƥ%P+>��x��:������ۺCD�u�4>T���x4���%���-/���R�j4�h�P�F�,9%�?�ܧ�x��n��KII��~ � � ��c����ߗ�:(�+�c���`��1�������h�yn�xP�T# +�L���ɶ�����0ġO"%c҃��DJ�E�E�l,4��[�'�o0>>Tt�ʉ�L)@I��`��PQA-@�)U[�Fs�����8/� � � �o������ߧ~F��n/}��g4�V��h�q���`4Zp�K4N&�"�����z)�8YjB|)�:'�:� %^G�Y���շu+R�~��4�g߸�[�`С�~�QGcE��hzN��5�[4^(�yAAAAP������)�c�����Ѩ�ZQ?�Qǵ�~�,Zx�K4N5��Ȅ+�l�^�h�,j��DJ0Ƥ'��R�H�סh���%��ױ�~�I%��jE�V��Ɗ��F��t���R�j4�h�P�� � � ���x��ǔ]W����=���o��x����~����&϶�gZ�������j}w��OF�푗�ϙ��dl��hο�fv�ص%�U�PBA���'�S�::J%��U�zڿ1J+�8\1����T�K�.eS�oaT �շ������{���X����g�%*��+�z-�9�����5�����6��\!�eu݆���t��|�59��x;u^#>�Gگ��ޗ��g���s�Q�t�8R,F{�>Ծ�֑��&NԾ3P+c�Ծ�}���N�T_E�[������}��>O:��DvFAAAC�?�O������:��M�A[�;�R{���A)�����=E����n"啘 +W+%}[��_��c^}ۮ�-�@&@R8�rhc�-@���\{�-���ѧz���̃�c�n���U�NC�����L�n Pب�J�/�Y�l58�j%��@Z�`L�[l�n5( l~:zX~\���oI�$5#�I����[�R�I%�(ǎkF�u<� � � (�ʶ+�g��_��:�/�6����yDT�̀�}}b:�_�[0[5p�ٕ���`L�gA��VGR `9}E��>�݂mW�fP��>�O"���S?G�N�3�[���A�8[M��yOȾS���K�)�9�9��`�Td����� ��S�[�Y�3V�XB�����{����z_�9IM�P��5Te47\ �zAA�F��s�ﯨc��:��dW!="��������; `r�v���R�@�����=���ڿ1���o�H�a��P��z��N�:9?��^�5PN\��[qΏ�m��@u�۔ڥ����U`�~�M�N��M��o��R�U��z��Klcl|Ɗ.}�"�ge1,؝��|�QAA�aP�Gy�)������T��ok9ߕ��11��|aZ��� +(���N�?jϑK`c��X��~,�/���.��-H�xSK ��ɭ���l�c�+�*��\��rz�Q}��>�O��:?�4�&��S$����x�Ne�;Ut>��\��Q{H�x^T�;����T���q�I@���wsq�ĉu�_E�� � �`vR�V-����?������ݑ��F����&���ޯ������d������~ ���cE�{����?_�K�F�@q� +� ���z��䀮/ѦDmڒl* \�>��.��o&ъ��*�����Rm �J�l�m[�5��MnPCo��F���u=o{�j����j�-x%�}�:��m��{�/�!F�n�>S��NP�`;UnC_J>T7+�=P?�g�@���lUo6��샧V@�a�:A0<Pxi���Uu���M�y�����)�$��4z�/CS�9��������d:oD�Xk���oTgch�hߊ��ʔ}[|6��}���b+����X��$�oh|��վ�����ڌe�wlo�W���l-�g�j�G� ���I�l�]�H� ��H�H�S�d.��Ja�~�����Y�/ArR�;����}&��>*I�: �&쏴�f��WJ���tr���vAAA5(�i�����2՟_OU�U4��Mޡ��� ,Ŧ��M����=���M���ό}�$j���Ŕo���u��w�4zɶ����w� +���X���g!�m�}6۷%�~;Љ�O%7����O�:�%W��o��@��[ͽ"�L�������T����}��ώ��~ ���E���%կvꗔ��(ٗ�� +J����+C�ߗ��Ɠ���.���w꽢�z���d�����R�(�{� ���mO�+������+��x�6���G�WJ�8g��{��{�����R*�5�=D� ���28�C�q=����^Q��&������s X������}jP{�{���0�����oV1?sBW�?":�%xM`0�p=B�h"�goR�H� � ���v�(����F�� �TUBk��9/(�������> R��O��b�77���y���Vȫ��{^��P\���:!�3�Jnb�X��@��V+$V��+8.N)k��U�R�<8�P�-4�~�i�Z���R��E��Bi�DѾ��-��}�Ձ�+����>��B�a)a���?�a����}�����{{��� +h�x�CIu��Ý���������j��_%��*����8W�b?�~����M@ ����k�?4���[u�6N�� +:!�O�3W�J�=Vٳ"�~������������� +=/���Ǐ� � � Jl�����G�T[l�=/�����N|� AuK�@��jŁ,巚{E���|A1�%��xY�@ɾ4�Q� + +W����WJ�*8�0�V}�+���u���b_�p�����E��Nj +(H��O�/�pK��W9�:~�8�/�9�D3O���}��x�*������ � 6�vs^����l伀5__�OU�'�:/��ܹ����H����t^�����(�����8�j�ʿ�����w;���ڿZ����X:����&ց3���T��VH�@5�Wp\�R���P��lSt����OC�'� >P����XJ�4^�h_R(��(ڗtm��OѾ�}k?ђ,�?\�������Ce�}1åNj +K��/*�0�7>վStVJ�گgPr��8��e��*y�1�?�j{�G��z?������LOg�ʶ���1�[�?W��}}^�\!� � ���r�j�jφ���y͌o��*�h��~TQ�[�%�\���sp���[�f��+��:M��&دomm�Ʈ����Z�o��I���]� 4�����`3|����h_v�eT�E��f +�P�E�e~�ov8K��^��Z�q��:s��-���R6���B�7��_R�E��~�r�b䷨�"��z�`o�������.���S��%�Qx�p3o���ș�}xx����Z�c�G�g�K�ϳ���mڗł�h�&��T]��|ў����� 6�/u, ip<���V]�_�7��E[���~��`� ��~�����>��ې��cA ���xpb+��7���|��u���ZQ?@u,��P��� I%����>]ugG�~ض��%����l���+q�@���f�����q{�rod�O�g�رc����Ol�;-���?� � �`�R�����e���Y�=��^�K�G�o�^TY�&T�o�l�����[���J�g\�?;�*>jX��^-�-�� +��Y��_�^g���̸�._�?;�@گ�C���W����| �W��k�9�f<7��r���zN�?�R�������P�������韝\�K�]f'�����M�o����s0���/�T�����gARe�\����gm�"��e���i�S���'�JHǽ�*����ݿ�q���X�������D.;�ׄ��Z�59�j�ӫE��`Yti�n�^ӧW�%��4�;�z�O��V;�# ;.s6�����))�� � �N�]�D['8��:ޢJ����ܳLQ���N�?� +��$�_���+~��'���/o.P���`(�o��_*P�v$������������ޗ����){�{���d�pn�H��N�"��d9�Ztis��q����ޗ�g'(�?;���?Y��������@�/���f�럝\ Mt1r ��[l�fd���1��� '(& �#�R}}�m���a�8�E�ub^��??P l��"珫��Y�Ztis�T�[�d7x`�8nFl��K���S-ϳ����w>�4J9�}����~GV�W/� � q�̙��$��,K���}�������>�g�\۪���Q08�Y�I:����jd���x�I 8K�h�x Zʭ��|lp��T����`� +�t�-��=W'��z�sП�gA�c�A�E�v��R7�1�����*�{Fn�{ڼJ^�u<%��@��2������ ���Kʗks}��9YRp���~���a>1�{۔�^�@�c�;_��Z�N�&�B�O��r�ئX�W}b��.�@�A+�T��'O�|�Q�jߥ����]�?x|��c�DLj����l��ly��K�j������y۔�^���o}�Cg~�'p�W|����ڟ�d��g�^ф��,�wX�[�9BiF�9�����(1����?�� PR��\ۗ�uL�dQ��q_.!^5NAAt������^�V�| (�O@���=����N������'�nrc�fs�,I��/. a��:�Ǭ�����-�LJB�{c�}٫��%:W�g �����,��?�.|f�������|�HѶ=���xJ�:�ʩ����^����'�G9gK���/Q�LbI���9YR���(�q�[��3�sܯH��E �:>H����8;�z> � ���bA�6g^�>|� +��<�3T��ޢ��.��j��@���1�+Aǩ�І��~��y�^R��s&:��|���C����r���3���h��s����,%VAs�JnBYj�LW��)� u(��*� xI`�� .���%U~ϵ�\��4Nu�����U�AA�$��p�*����d�����k>)g�lp�����_��|lp�{-�apN ��N|����2{�E؎����m��>*����0 ֓U?�/ٞ��4�������M�H͒y�5�%�#�f��*�!,�@������N��*���Z��c'�:���s �q� � ��C���v|��v����؎�4LNb�x&%��������v��C��$�����[����|�߁3�K>h|�v'>_��/� +��Wr�R�d�~L)M�CiF�T�l��HC�opY���(��{���z?�q��C︯?��'� � >��_D��~�I�뷷��l�n������V�Ǩ�llmm=�9A�4庶�e�A�}���9z�8�o���c�^����9y{��ߢ0�����M�{{{�[Č?��3��B�hlW�����-0b��q�B���g���/�R��L�E�J�n���^*{�U8�z5�|���êײ���mj�Q�Z��;T_��,�Uٞ��Uox�������t�[�Z2�\���W�`1Ӷ�2�[C%����������%�>MS�&��V�!� +�~���i�S�5~�(�� +���k�1�[C�vpŃs�ĉg��4x3�m�[c���/�&�z��={����^T��ܹs���|����� ���������fl����ՠ~ �f�%��A����cǾR���������7U/�-�7�1�P���gI�=��:V?�����h�dR�v�a"��U/����]�k� �mA~���0��t�w���~��? -��H��U��&/��čC�iܧ�q�������8���p3�e��z����%:�� +��ߚ����y���.��`��?��Y�/�����Un��Dp�J�v��C��R=������ڮ1/�9�y ����_���W�����6� � ���˪��ׯ:9�\�o)�z�uꈞ���?���7��W�����6!��+7;|�Or6C��,5�>���הn��ϾS�W%����>�h����r���ܘ�C�P���?(��a�j ����b ̭�Nh����kE��`������bz� +֫5h +�E=�@W�<��~�����}�HU�+���>���T��KQ`1����?(��R똅L�WZ�!����+P�@��������� q���ת�@�گ�N��*��ھ��c5�����;���9T�\?�te� � � ���s��m�����:mz�?��E�����Y�����>(�l[����W�PM��/�?{{{��:jQ�ꪫ>�zZ�'a���AP��շ5��D��&OT���X���K�*N��ۚ�`O�C�?�l{_�N��3%�1�ߧ1���0@����o^���ls\�c��\���>�X):N%�q���XY�2�K�b��*۾k���oYTNj%u���Ŝ��(��3��{�پE'�{�-b�;��d]�xU����}���ȏ�!��2 ��䰠W��0�W�x5��W`Hd��e�$,��X {�=bL�Il&�~$;~��S�/� � � Fs��� �+��mT=X��Y��/���>�Y��&|D�)����/g�3I$��'�3�hP$����g�&�c5U0^!�*�{@��f]^g�X%��%r���b��㜤�xUiy��;�)}��%�L�(���۾���|��9�c�Z��������8ζ�9� 4V3�A���˜����y�wF�U �#���/C�F��b���C (��߈L�$+�0���U'E��&��o�[�-?���_��9\����?#:��~�L��x5X:���a&�@2��j�AAAA�F�4u�8/8"q^� V*�؎��g��z�&�|�l�yAAR bfg��<�����Ɖ���v*�� � � �`Ӝ����>"/���}D}�G���G��V|Qs�XY���<��c9}e�W�M�G��rY���� � � ��=�A�L�7�K/����������o0_|�ڙ��MѠ^`��c��u� +l��`��G�3E��`.����N�ض��<�9Ϲg�x�I���v2Ŷ��:Òx�I�n�}�L�ma�DgXo;�1u2Ŷ�Nt�%�d�m����je�� � � � ����8���:5�����IEND�B`� \ No newline at end of file diff --git a/web/core/authorize.php b/web/core/authorize.php index 9ab60dcdcb726403268662bed2c52c6c50686650..a965e60b0e9f932c604e9c8943af89f8e69c85e9 100644 --- a/web/core/authorize.php +++ b/web/core/authorize.php @@ -125,7 +125,7 @@ function authorize_access_allowed(Request $request) { $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 diff --git a/web/core/composer.json b/web/core/composer.json index 020498f834b2493336d573ce771b4d36f4a7765e..34fed39b1ae5d60bc43e5c7eee9274f9c516b1d5 100644 --- a/web/core/composer.json +++ b/web/core/composer.json @@ -31,6 +31,7 @@ "symfony/process": "~3.4.0", "symfony/polyfill-iconv": "^1.0", "symfony/yaml": "~3.4.5", + "typo3/phar-stream-wrapper": "^2.0.1", "twig/twig": "^1.35.0", "doctrine/common": "^2.5", "doctrine/annotations": "^1.2", @@ -59,7 +60,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" diff --git a/web/core/core.libraries.yml b/web/core/core.libraries.yml index 54abfa74ca950f64ac03f67255a328dec137a2a6..918a36afd309cc9772aedb0c1f6b33cf1d56c186 100644 --- a/web/core/core.libraries.yml +++ b/web/core/core.libraries.yml @@ -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 } diff --git a/web/core/core.services.yml b/web/core/core.services.yml index df50344fc7094511ca51c04e48e5c8c1ed99e38f..eb562afea7435d192190ef2ee5d5945567a747b7 100644 --- a/web/core/core.services.yml +++ b/web/core/core.services.yml @@ -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'] diff --git a/web/core/includes/bootstrap.inc b/web/core/includes/bootstrap.inc index 45c9490713bb313fcea0639eb5f66643a5f49cfb..d58779d5374ec92465814f6f13039dc873392d51 100644 --- a/web/core/includes/bootstrap.inc +++ b/web/core/includes/bootstrap.inc @@ -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 diff --git a/web/core/includes/common.inc b/web/core/includes/common.inc index 49cf6e104a72aafac9435f9aaf721716d9ab9634..5090c45fa541a2ee8b240ef9a4565ede6f3b0a7e 100644 --- a/web/core/includes/common.inc +++ b/web/core/includes/common.inc @@ -251,42 +251,46 @@ function check_url($uri) { * A translated string representation of the size. */ function format_size($size, $langcode = NULL) { - if ($size < Bytes::KILOBYTE) { + $absolute_size = abs($size); + if ($absolute_size < Bytes::KILOBYTE) { return \Drupal::translation()->formatPlural($size, '1 byte', '@count bytes', [], ['langcode' => $langcode]); } - else { - // Convert bytes to kilobytes. - $size = $size / Bytes::KILOBYTE; - $units = ['KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB']; - foreach ($units as $unit) { - if (round($size, 2) >= Bytes::KILOBYTE) { - $size = $size / Bytes::KILOBYTE; - } - else { - break; - } - } - $args = ['@size' => round($size, 2)]; - $options = ['langcode' => $langcode]; - switch ($unit) { - case 'KB': - return new TranslatableMarkup('@size KB', $args, $options); - case 'MB': - return new TranslatableMarkup('@size MB', $args, $options); - case 'GB': - return new TranslatableMarkup('@size GB', $args, $options); - case 'TB': - return new TranslatableMarkup('@size TB', $args, $options); - case 'PB': - return new TranslatableMarkup('@size PB', $args, $options); - case 'EB': - return new TranslatableMarkup('@size EB', $args, $options); - case 'ZB': - return new TranslatableMarkup('@size ZB', $args, $options); - case 'YB': - return new TranslatableMarkup('@size YB', $args, $options); + // Create a multiplier to preserve the sign of $size. + $sign = $absolute_size / $size; + foreach (['KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'] as $unit) { + $absolute_size /= Bytes::KILOBYTE; + $rounded_size = round($absolute_size, 2); + if ($rounded_size < Bytes::KILOBYTE) { + break; } } + $args = ['@size' => $rounded_size * $sign]; + $options = ['langcode' => $langcode]; + switch ($unit) { + case 'KB': + return new TranslatableMarkup('@size KB', $args, $options); + + case 'MB': + return new TranslatableMarkup('@size MB', $args, $options); + + case 'GB': + return new TranslatableMarkup('@size GB', $args, $options); + + case 'TB': + return new TranslatableMarkup('@size TB', $args, $options); + + case 'PB': + return new TranslatableMarkup('@size PB', $args, $options); + + case 'EB': + return new TranslatableMarkup('@size EB', $args, $options); + + case 'ZB': + return new TranslatableMarkup('@size ZB', $args, $options); + + case 'YB': + return new TranslatableMarkup('@size YB', $args, $options); + } } /** @@ -490,7 +494,7 @@ function drupal_js_defaults($data = NULL) { * * Every condition is a key/value pair, whose key is a jQuery selector that * denotes another element on the page, and whose value is an array of - * conditions, which must bet met on that element: + * conditions, which must be met on that element: * @code * array( * 'visible' => array( diff --git a/web/core/includes/install.core.inc b/web/core/includes/install.core.inc index 34e68241ab4d0f5adbad46306ccea4aa8fc045f8..aed688d8be7f7f836d7b6668c58175e2253cda31 100644 --- a/web/core/includes/install.core.inc +++ b/web/core/includes/install.core.inc @@ -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)); } diff --git a/web/core/includes/install.inc b/web/core/includes/install.inc index c7e414aaa290d8715cefb8f10ba108e6c25b5659..03dea88c331f91f334db8e972a30da51b43a9899 100644 --- a/web/core/includes/install.inc +++ b/web/core/includes/install.inc @@ -11,6 +11,7 @@ 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]); diff --git a/web/core/lib/Drupal.php b/web/core/lib/Drupal.php index 130183e734c058bf8f25ad06a62c8daf3af9cb1f..76dba3c8aa489460dfc32042caa7437dc89d2bf6 100644 --- a/web/core/lib/Drupal.php +++ b/web/core/lib/Drupal.php @@ -82,7 +82,7 @@ class Drupal { /** * The current system version. */ - const VERSION = '8.6.2'; + const VERSION = '8.6.6'; /** * Core API compatibility. @@ -229,7 +229,7 @@ public static function request() { } /** - * Retrives the request stack. + * Retrieves the request stack. * * @return \Symfony\Component\HttpFoundation\RequestStack * The request stack diff --git a/web/core/lib/Drupal/Component/DependencyInjection/PhpArrayContainer.php b/web/core/lib/Drupal/Component/DependencyInjection/PhpArrayContainer.php index 5d615dbd05e4c9592c0774e7d858abf6fae12d3d..ba454682389f8016593bdd02b61b6a0532955183 100644 --- a/web/core/lib/Drupal/Component/DependencyInjection/PhpArrayContainer.php +++ b/web/core/lib/Drupal/Component/DependencyInjection/PhpArrayContainer.php @@ -200,7 +200,7 @@ protected function resolveServicesAndParameters($arguments) { // 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; diff --git a/web/core/lib/Drupal/Component/Gettext/PoStreamReader.php b/web/core/lib/Drupal/Component/Gettext/PoStreamReader.php index f95b43b13d4b84e392e450bbeecf88b6d2648699..a69c03ce88daf1bf0dd50b7b3e4a148e20da7b86 100644 --- a/web/core/lib/Drupal/Component/Gettext/PoStreamReader.php +++ b/web/core/lib/Drupal/Component/Gettext/PoStreamReader.php @@ -394,7 +394,7 @@ private function readLine() { ($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; diff --git a/web/core/lib/Drupal/Component/HttpFoundation/SecuredRedirectResponse.php b/web/core/lib/Drupal/Component/HttpFoundation/SecuredRedirectResponse.php index 931f816062f4f45bbe748ecd41b9149862028401..03c44faac3fd5a1f688b27bed5d15d91f944318b 100644 --- a/web/core/lib/Drupal/Component/HttpFoundation/SecuredRedirectResponse.php +++ b/web/core/lib/Drupal/Component/HttpFoundation/SecuredRedirectResponse.php @@ -36,7 +36,7 @@ public static function createFromRedirectResponse(RedirectResponse $response) { * 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()); diff --git a/web/core/lib/Drupal/Component/Plugin/ContextAwarePluginBase.php b/web/core/lib/Drupal/Component/Plugin/ContextAwarePluginBase.php index b9f6e02217ad136bb9fe539152250d580f4dfe9c..2d499fd7dd16219f3109daf23a70bb7d3317d881 100644 --- a/web/core/lib/Drupal/Component/Plugin/ContextAwarePluginBase.php +++ b/web/core/lib/Drupal/Component/Plugin/ContextAwarePluginBase.php @@ -3,6 +3,7 @@ namespace Drupal\Component\Plugin; use Drupal\Component\Plugin\Context\ContextInterface; +use Drupal\Component\Plugin\Definition\ContextAwarePluginDefinitionInterface; use Drupal\Component\Plugin\Exception\ContextException; use Drupal\Component\Plugin\Context\Context; use Symfony\Component\Validator\ConstraintViolationList; @@ -67,7 +68,12 @@ protected function createContextFromConfiguration(array $context_configuration) */ public function getContextDefinitions() { $definition = $this->getPluginDefinition(); - return !empty($definition['context']) ? $definition['context'] : []; + if ($definition instanceof ContextAwarePluginDefinitionInterface) { + return $definition->getContextDefinitions(); + } + else { + return !empty($definition['context']) ? $definition['context'] : []; + } } /** @@ -75,10 +81,15 @@ public function getContextDefinitions() { */ public function getContextDefinition($name) { $definition = $this->getPluginDefinition(); - if (empty($definition['context'][$name])) { - throw new ContextException(sprintf("The %s context is not a valid context.", $name)); + if ($definition instanceof ContextAwarePluginDefinitionInterface) { + if ($definition->hasContextDefinition($name)) { + return $definition->getContextDefinition($name); + } + } + elseif (!empty($definition['context'][$name])) { + return $definition['context'][$name]; } - return $definition['context'][$name]; + throw new ContextException(sprintf("The %s context is not a valid context.", $name)); } /** diff --git a/web/core/lib/Drupal/Component/Plugin/PluginManagerBase.php b/web/core/lib/Drupal/Component/Plugin/PluginManagerBase.php index bc285e501f0f6215113aaa0aba80ddf3f513b37a..d7342da2ed18c69bb05fe2b124aca55e88d616bd 100644 --- a/web/core/lib/Drupal/Component/Plugin/PluginManagerBase.php +++ b/web/core/lib/Drupal/Component/Plugin/PluginManagerBase.php @@ -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 @@ protected function handlePluginNotFound($plugin_id, array $configuration) { * {@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); } diff --git a/web/core/lib/Drupal/Component/Transliteration/PhpTransliteration.php b/web/core/lib/Drupal/Component/Transliteration/PhpTransliteration.php index 3cd8d6856500ba50ca7e44317d110c41b0c33f55..2f6397406ae2004202bc58e3a71d754aaaeee258 100644 --- a/web/core/lib/Drupal/Component/Transliteration/PhpTransliteration.php +++ b/web/core/lib/Drupal/Component/Transliteration/PhpTransliteration.php @@ -107,6 +107,29 @@ public function removeDiacritics($string) { public function transliterate($string, $langcode = 'en', $unknown_character = '?', $max_length = NULL) { $result = ''; $length = 0; + $hash = FALSE; + + // Replace question marks with a unique hash if necessary. This because + // mb_convert_encoding() replaces all invalid characters with a question + // mark. + if ($unknown_character != '?' && strpos($string, '?') !== FALSE) { + $hash = hash('sha256', $string); + $string = str_replace('?', $hash, $string); + } + + // Ensure the string is valid UTF8 for preg_split(). Unknown characters will + // be replaced by a question mark. + $string = mb_convert_encoding($string, 'UTF-8', 'UTF-8'); + + // Use the provided unknown character instead of a question mark. + if ($unknown_character != '?') { + $string = str_replace('?', $unknown_character, $string); + // Restore original question marks if necessary. + if ($hash !== FALSE) { + $string = str_replace($hash, '?', $string); + } + } + // Split into Unicode characters and transliterate each one. foreach (preg_split('//u', $string, 0, PREG_SPLIT_NO_EMPTY) as $character) { $code = self::ordUTF8($character); diff --git a/web/core/lib/Drupal/Component/Utility/Mail.php b/web/core/lib/Drupal/Component/Utility/Mail.php new file mode 100644 index 0000000000000000000000000000000000000000..423cfb2668d88971311f5244d5ffb5fbcba0a88d --- /dev/null +++ b/web/core/lib/Drupal/Component/Utility/Mail.php @@ -0,0 +1,67 @@ +<?php + +namespace Drupal\Component\Utility; + +/** + * Provides helpers to ensure emails are compliant with RFCs. + * + * @ingroup utility + */ +class Mail { + + /** + * RFC-2822 "specials" characters. + */ + const RFC_2822_SPECIALS = '()<>[]:;@\,."'; + + /** + * Return a RFC-2822 compliant "display-name" component. + * + * The "display-name" component is used in mail header "Originator" fields + * (From, Sender, Reply-to) to give a human-friendly description of the + * address, i.e. From: My Display Name <xyz@example.org>. RFC-822 and + * RFC-2822 define its syntax and rules. This method gets as input a string + * to be used as "display-name" and formats it to be RFC compliant. + * + * @param string $string + * A string to be used as "display-name". + * + * @return string + * A RFC compliant version of the string, ready to be used as + * "display-name" in mail originator header fields. + */ + public static function formatDisplayName($string) { + // Make sure we don't process html-encoded characters. They may create + // unneeded trouble if left encoded, besides they will be correctly + // processed if decoded. + $string = Html::decodeEntities($string); + + // If string contains non-ASCII characters it must be (short) encoded + // according to RFC-2047. The output of a "B" (Base64) encoded-word is + // always safe to be used as display-name. + $safe_display_name = Unicode::mimeHeaderEncode($string, TRUE); + + // Encoded-words are always safe to be used as display-name because don't + // contain any RFC 2822 "specials" characters. However + // Unicode::mimeHeaderEncode() encodes a string only if it contains any + // non-ASCII characters, and leaves its value untouched (un-encoded) if + // ASCII only. For this reason in order to produce a valid display-name we + // still need to make sure there are no "specials" characters left. + if (preg_match('/[' . preg_quote(Mail::RFC_2822_SPECIALS) . ']/', $safe_display_name)) { + + // If string is already quoted, it may or may not be escaped properly, so + // don't trust it and reset. + if (preg_match('/^"(.+)"$/', $safe_display_name, $matches)) { + $safe_display_name = str_replace(['\\\\', '\\"'], ['\\', '"'], $matches[1]); + } + + // Transform the string in a RFC-2822 "quoted-string" by wrapping it in + // double-quotes. Also make sure '"' and '\' occurrences are escaped. + $safe_display_name = '"' . str_replace(['\\', '"'], ['\\\\', '\\"'], $safe_display_name) . '"'; + + } + + return $safe_display_name; + } + +} diff --git a/web/core/lib/Drupal/Core/Archiver/ArchiveTar.php b/web/core/lib/Drupal/Core/Archiver/ArchiveTar.php index 1570a1e83abe8d249cd5c2147a196df042cc06e7..abee870c0bf8c2acf8b26deeddd6572c4c5af25c 100644 --- a/web/core/lib/Drupal/Core/Archiver/ArchiveTar.php +++ b/web/core/lib/Drupal/Core/Archiver/ArchiveTar.php @@ -42,14 +42,14 @@ /** * Note on Drupal 8 porting. - * This file origin is Tar.php, release 1.4.0 (stable) with some code + * This file origin is Tar.php, release 1.4.5 (stable) with some code * from PEAR.php, release 1.9.5 (stable) both at http://pear.php.net. * To simplify future porting from pear of this file, you should not * do cosmetic or other non significant changes to this file. * 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(). @@ -151,6 +151,13 @@ class ArchiveTar */ public $error_object = null; + /** + * Format for data extraction + * + * @var string + */ + public $_fmt =''; + /** * Archive_Tar Class constructor. This flavour of the constructor only * declare a new Archive_Tar object, identifying it by the name of the @@ -181,7 +188,7 @@ public function __construct($p_tarname, $p_compress = null) 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'; @@ -257,6 +264,18 @@ public function __construct($p_tarname, $p_compress = null) return false; } } + + if (version_compare(PHP_VERSION, "5.5.0-dev") < 0) { + $this->_fmt = "a100filename/a8mode/a8uid/a8gid/a12size/a12mtime/" . + "a8checksum/a1typeflag/a100link/a6magic/a2version/" . + "a32uname/a32gname/a8devmajor/a8devminor/a131prefix"; + } else { + $this->_fmt = "Z100filename/Z8mode/Z8uid/Z8gid/Z12size/Z12mtime/" . + "Z8checksum/Z1typeflag/Z100link/Z6magic/Z2version/" . + "Z32uname/Z32gname/Z8devmajor/Z8devminor/Z131prefix"; + } + + } public function __destruct() @@ -712,7 +731,7 @@ public function setAttribute() } // ----- Get the arguments - $v_att_list = & func_get_args(); + $v_att_list = func_get_args(); // ----- Read the attributes $i = 0; @@ -1392,10 +1411,20 @@ public function _writeHeader($p_filename, $p_stored_filename) if ($p_stored_filename == '') { $p_stored_filename = $p_filename; } - $v_reduce_filename = $this->_pathReduction($p_stored_filename); + $v_reduced_filename = $this->_pathReduction($p_stored_filename); - if (strlen($v_reduce_filename) > 99) { - if (!$this->_writeLongHeader($v_reduce_filename)) { + if (strlen($v_reduced_filename) > 99) { + if (!$this->_writeLongHeader($v_reduced_filename, false)) { + return false; + } + } + + $v_linkname = ''; + if (@is_link($p_filename)) { + $v_linkname = readlink($p_filename); + } + if (strlen($v_linkname) > 99) { + if (!$this->_writeLongHeader($v_linkname, true)) { return false; } } @@ -1404,14 +1433,10 @@ public function _writeHeader($p_filename, $p_stored_filename) $v_uid = sprintf("%07s", DecOct($v_info[4])); $v_gid = sprintf("%07s", DecOct($v_info[5])); $v_perms = sprintf("%07s", DecOct($v_info['mode'] & 000777)); - $v_mtime = sprintf("%011s", DecOct($v_info['mtime'])); - $v_linkname = ''; - if (@is_link($p_filename)) { $v_typeflag = '2'; - $v_linkname = readlink($p_filename); $v_size = sprintf("%011s", DecOct(0)); } elseif (@is_dir($p_filename)) { $v_typeflag = "5"; @@ -1423,7 +1448,6 @@ public function _writeHeader($p_filename, $p_stored_filename) } $v_magic = 'ustar '; - $v_version = ' '; if (function_exists('posix_getpwuid')) { @@ -1438,14 +1462,12 @@ public function _writeHeader($p_filename, $p_stored_filename) } $v_devmajor = ''; - $v_devminor = ''; $v_prefix = ''; $v_binary_data_first = pack( "a100a8a8a8a12a12", - $v_reduce_filename, $v_perms, $v_uid, $v_gid, @@ -1485,7 +1507,7 @@ public function _writeHeader($p_filename, $p_stored_filename) $this->_writeBlock($v_binary_data_first, 148); // ----- Write the calculated checksum - $v_checksum = sprintf("%06s ", DecOct($v_checksum)); + $v_checksum = sprintf("%06s\0 ", DecOct($v_checksum)); $v_binary_data = pack("a8", $v_checksum); $this->_writeBlock($v_binary_data, 8); @@ -1517,7 +1539,7 @@ public function _writeHeaderBlock( $p_filename = $this->_pathReduction($p_filename); if (strlen($p_filename) > 99) { - if (!$this->_writeLongHeader($p_filename)) { + if (!$this->_writeLongHeader($p_filename, false)) { return false; } } @@ -1613,36 +1635,31 @@ public function _writeHeaderBlock( * @param string $p_filename * @return bool */ - public function _writeLongHeader($p_filename) + public function _writeLongHeader($p_filename, $is_link = false) { - $v_size = sprintf("%11s ", DecOct(strlen($p_filename))); - - $v_typeflag = 'L'; - + $v_uid = sprintf("%07s", 0); + $v_gid = sprintf("%07s", 0); + $v_perms = sprintf("%07s", 0); + $v_size = sprintf("%'011s", DecOct(strlen($p_filename))); + $v_mtime = sprintf("%011s", 0); + $v_typeflag = ($is_link ? 'K' : 'L'); $v_linkname = ''; - - $v_magic = ''; - - $v_version = ''; - + $v_magic = 'ustar '; + $v_version = ' '; $v_uname = ''; - $v_gname = ''; - $v_devmajor = ''; - $v_devminor = ''; - $v_prefix = ''; $v_binary_data_first = pack( "a100a8a8a8a12a12", '././@LongLink', - 0, - 0, - 0, + $v_perms, + $v_uid, + $v_gid, $v_size, - 0 + $v_mtime ); $v_binary_data_last = pack( "a1a100a6a2a32a32a8a8a155a12", @@ -1677,7 +1694,7 @@ public function _writeLongHeader($p_filename) $this->_writeBlock($v_binary_data_first, 148); // ----- Write the calculated checksum - $v_checksum = sprintf("%06s ", DecOct($v_checksum)); + $v_checksum = sprintf("%06s\0 ", DecOct($v_checksum)); $v_binary_data = pack("a8", $v_checksum); $this->_writeBlock($v_binary_data, 8); @@ -1718,28 +1735,12 @@ public function _readHeader($v_binary_data, &$v_header) // ----- Calculate the checksum $v_checksum = 0; // ..... First part of the header - for ($i = 0; $i < 148; $i++) { - $v_checksum += ord(substr($v_binary_data, $i, 1)); - } - // ..... Ignore the checksum value and replace it by ' ' (space) - for ($i = 148; $i < 156; $i++) { - $v_checksum += ord(' '); - } - // ..... Last part of the header - for ($i = 156; $i < 512; $i++) { - $v_checksum += ord(substr($v_binary_data, $i, 1)); - } + $v_binary_split = str_split($v_binary_data); + $v_checksum += array_sum(array_map('ord', array_slice($v_binary_split, 0, 148))); + $v_checksum += array_sum(array_map('ord', array(' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ',))); + $v_checksum += array_sum(array_map('ord', array_slice($v_binary_split, 156, 512))); - if (version_compare(PHP_VERSION, "5.5.0-dev") < 0) { - $fmt = "a100filename/a8mode/a8uid/a8gid/a12size/a12mtime/" . - "a8checksum/a1typeflag/a100link/a6magic/a2version/" . - "a32uname/a32gname/a8devmajor/a8devminor/a131prefix"; - } else { - $fmt = "Z100filename/Z8mode/Z8uid/Z8gid/Z12size/Z12mtime/" . - "Z8checksum/Z1typeflag/Z100link/Z6magic/Z2version/" . - "Z32uname/Z32gname/Z8devmajor/Z8devminor/Z131prefix"; - } - $v_data = unpack($fmt, $v_binary_data); + $v_data = unpack($this->_fmt, $v_binary_data); if (strlen($v_data["prefix"]) > 0) { $v_data["filename"] = "$v_data[prefix]/$v_data[filename]"; @@ -1775,7 +1776,7 @@ public function _readHeader($v_binary_data, &$v_header) $v_header['mode'] = OctDec(trim($v_data['mode'])); $v_header['uid'] = OctDec(trim($v_data['uid'])); $v_header['gid'] = OctDec(trim($v_data['gid'])); - $v_header['size'] = OctDec(trim($v_data['size'])); + $v_header['size'] = $this->_tarRecToSize($v_data['size']); $v_header['mtime'] = OctDec(trim($v_data['mtime'])); if (($v_header['typeflag'] = $v_data['typeflag']) == "5") { $v_header['size'] = 0; @@ -1794,6 +1795,41 @@ public function _readHeader($v_binary_data, &$v_header) return true; } + /** + * Convert Tar record size to actual size + * + * @param string $tar_size + * @return size of tar record in bytes + */ + private function _tarRecToSize($tar_size) + { + /* + * First byte of size has a special meaning if bit 7 is set. + * + * Bit 7 indicates base-256 encoding if set. + * Bit 6 is the sign bit. + * Bits 5:0 are most significant value bits. + */ + $ch = ord($tar_size[0]); + if ($ch & 0x80) { + // Full 12-bytes record is required. + $rec_str = $tar_size . "\x00"; + + $size = ($ch & 0x40) ? -1 : 0; + $size = ($size << 6) | ($ch & 0x3f); + + for ($num_ch = 1; $num_ch < 12; ++$num_ch) { + $size = ($size * 256) + ord($rec_str[$num_ch]); + } + + return $size; + + } else { + return OctDec(trim($tar_size)); + } + } + + /** * Detect and report a malicious file name * @@ -1803,10 +1839,13 @@ public function _readHeader($v_binary_data, &$v_header) */ private function _maliciousFilename($file) { - if (strpos($file, '/../') !== false) { + if (strpos($file, 'phar://') === 0) { return true; } - if (strpos($file, '../') === 0) { + if (strpos($file, DIRECTORY_SEPARATOR . '..' . DIRECTORY_SEPARATOR) !== false) { + return true; + } + if (strpos($file, '..' . DIRECTORY_SEPARATOR) === 0) { return true; } return false; @@ -1871,11 +1910,20 @@ private function _extractInString($p_filename) continue; } - // ----- Look for long filename - if ($v_header['typeflag'] == 'L') { - if (!$this->_readLongHeader($v_header)) { - return null; - } + switch ($v_header['typeflag']) { + case 'L': { + if (!$this->_readLongHeader($v_header)) { + return null; + } + } break; + + case 'K': { + $v_link_header = $v_header; + if (!$this->_readLongHeader($v_link_header)) { + return null; + } + $v_header['link'] = $v_link_header['filename']; + } break; } if ($v_header['filename'] == $p_filename) { @@ -1976,11 +2024,20 @@ public function _extractList( continue; } - // ----- Look for long filename - if ($v_header['typeflag'] == 'L') { - if (!$this->_readLongHeader($v_header)) { - return false; - } + switch ($v_header['typeflag']) { + case 'L': { + if (!$this->_readLongHeader($v_header)) { + return null; + } + } break; + + case 'K': { + $v_link_header = $v_header; + if (!$this->_readLongHeader($v_link_header)) { + return null; + } + $v_header['link'] = $v_link_header['filename']; + } break; } // ignore extended / pax headers @@ -2385,7 +2442,7 @@ public function _dirCheck($p_dir) /** * 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 * diff --git a/web/core/lib/Drupal/Core/Block/BlockBase.php b/web/core/lib/Drupal/Core/Block/BlockBase.php index a5f7fa9ed9d6997fafb7558fd7807082ead42846..bebdf09bd41041d863d41addd77e08484ac122de 100644 --- a/web/core/lib/Drupal/Core/Block/BlockBase.php +++ b/web/core/lib/Drupal/Core/Block/BlockBase.php @@ -11,6 +11,7 @@ use Drupal\Core\Language\LanguageInterface; use Drupal\Core\Plugin\PluginWithFormsInterface; use Drupal\Core\Plugin\PluginWithFormsTrait; +use Drupal\Core\Render\PreviewFallbackInterface; use Drupal\Core\Session\AccountInterface; use Drupal\Component\Transliteration\TransliterationInterface; @@ -23,7 +24,7 @@ * * @ingroup block_api */ -abstract class BlockBase extends ContextAwarePluginBase implements BlockPluginInterface, PluginWithFormsInterface { +abstract class BlockBase extends ContextAwarePluginBase implements BlockPluginInterface, PluginWithFormsInterface, PreviewFallbackInterface { use ContextAwarePluginAssignmentTrait; use MessengerTrait; @@ -252,6 +253,13 @@ public function getMachineNameSuggestion() { return $transliterated; } + /** + * {@inheritdoc} + */ + public function getPreviewFallbackString() { + return $this->t('Placeholder for the "@block" block', ['@block' => $this->label()]); + } + /** * Wraps the transliteration service. * diff --git a/web/core/lib/Drupal/Core/Cache/CacheBackendInterface.php b/web/core/lib/Drupal/Core/Cache/CacheBackendInterface.php index 852305f8f140ffcdd7ab102dbd4ba17e0248d3d3..bf2ed7c48eee773f903ab5dbb760ee889e6a6c1c 100644 --- a/web/core/lib/Drupal/Core/Cache/CacheBackendInterface.php +++ b/web/core/lib/Drupal/Core/Cache/CacheBackendInterface.php @@ -9,7 +9,7 @@ * 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 */ diff --git a/web/core/lib/Drupal/Core/Cache/MemoryBackend.php b/web/core/lib/Drupal/Core/Cache/MemoryBackend.php index 99e6e3a3c60f7cee12d3fe45fd5259f5856b037e..c1276923754b2df85c8ab39c45e6ba9db3ec2917 100644 --- a/web/core/lib/Drupal/Core/Cache/MemoryBackend.php +++ b/web/core/lib/Drupal/Core/Cache/MemoryBackend.php @@ -156,10 +156,9 @@ public function invalidate($cid) { * {@inheritdoc} */ public function invalidateMultiple(array $cids) { - foreach ($cids as $cid) { - if (isset($this->cache[$cid])) { - $this->cache[$cid]->expire = $this->getRequestTime() - 1; - } + $items = array_intersect_key($this->cache, array_flip($cids)); + foreach ($items as $cid => $item) { + $this->cache[$cid]->expire = $this->getRequestTime() - 1; } } diff --git a/web/core/lib/Drupal/Core/Command/DbDumpCommand.php b/web/core/lib/Drupal/Core/Command/DbDumpCommand.php index 26b4363cdd3cac504389aa5b315cfbb96c461367..a7d6d090502b3173452d712bcdea4a5136e63293 100644 --- a/web/core/lib/Drupal/Core/Command/DbDumpCommand.php +++ b/web/core/lib/Drupal/Core/Command/DbDumpCommand.php @@ -162,12 +162,19 @@ protected function getTableSchema(Connection $connection, $table) { $definition['fields'][$name]['precision'] = $matches[2]; $definition['fields'][$name]['scale'] = $matches[3]; } - elseif ($type === 'time' || $type === 'datetime') { + elseif ($type === 'time') { // @todo Core doesn't support these, but copied from `migrate-db.sh` for now. // Convert to varchar. $definition['fields'][$name]['type'] = 'varchar'; $definition['fields'][$name]['length'] = '100'; } + elseif ($type === 'datetime') { + // Adjust for other database types. + $definition['fields'][$name]['mysql_type'] = 'datetime'; + $definition['fields'][$name]['pgsql_type'] = 'timestamp without time zone'; + $definition['fields'][$name]['sqlite_type'] = 'varchar'; + $definition['fields'][$name]['sqlsrv_type'] = 'smalldatetime'; + } elseif (!isset($definition['fields'][$name]['size'])) { // Try use the provided length, if it doesn't exist default to 100. It's // not great but good enough for our dumps at this point. diff --git a/web/core/lib/Drupal/Core/Config/ConfigInstaller.php b/web/core/lib/Drupal/Core/Config/ConfigInstaller.php index b1ea748e7b2ce71f897f5571a127c4b858f83c8f..4a198a72527971928c083594f9aed9d099b53313 100644 --- a/web/core/lib/Drupal/Core/Config/ConfigInstaller.php +++ b/web/core/lib/Drupal/Core/Config/ConfigInstaller.php @@ -160,7 +160,10 @@ public function installDefaultConfig($type, $name) { */ 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 @@ public function installOptionalConfig(StorageInterface $storage = NULL, $depende // 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 @@ public function installOptionalConfig(StorageInterface $storage = NULL, $depende $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 @@ public function installOptionalConfig(StorageInterface $storage = NULL, $depende 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); } diff --git a/web/core/lib/Drupal/Core/Config/ConfigInstallerInterface.php b/web/core/lib/Drupal/Core/Config/ConfigInstallerInterface.php index 3d7077b53bd59161bce90a132d11ccfc51be6a92..41b015e61bb27373272e75f753474be353a74bd1 100644 --- a/web/core/lib/Drupal/Core/Config/ConfigInstallerInterface.php +++ b/web/core/lib/Drupal/Core/Config/ConfigInstallerInterface.php @@ -43,7 +43,8 @@ public function installDefaultConfig($type, $name); * @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', diff --git a/web/core/lib/Drupal/Core/Config/Entity/ConfigEntityInterface.php b/web/core/lib/Drupal/Core/Config/Entity/ConfigEntityInterface.php index 248701e7f32884b01b30e88a9b25ece0d416db3a..8931f1ed04927b99479851834774296f98f773dd 100644 --- a/web/core/lib/Drupal/Core/Config/Entity/ConfigEntityInterface.php +++ b/web/core/lib/Drupal/Core/Config/Entity/ConfigEntityInterface.php @@ -189,7 +189,7 @@ public function getDependencies(); * 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(); diff --git a/web/core/lib/Drupal/Core/Config/FileStorage.php b/web/core/lib/Drupal/Core/Config/FileStorage.php index 84d23d32745abe6d6d9b6b6ef088a77a33e1c8c4..60c5fa11d65555a44da5e1817e634277c3b2d1e7 100644 --- a/web/core/lib/Drupal/Core/Config/FileStorage.php +++ b/web/core/lib/Drupal/Core/Config/FileStorage.php @@ -46,7 +46,7 @@ public function __construct($directory, $collection = StorageInterface::DEFAULT_ $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 @@ public function getCollectionName() { * {@inheritdoc} */ public function getAllCollectionNames() { + if (!is_dir($this->directory)) { + return []; + } $collections = $this->getAllCollectionNamesHelper($this->directory); sort($collections); return $collections; @@ -305,7 +308,8 @@ public function getAllCollectionNames() { * @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. diff --git a/web/core/lib/Drupal/Core/Database/Driver/mysql/Install/Tasks.php b/web/core/lib/Drupal/Core/Database/Driver/mysql/Install/Tasks.php index 6a639d7eb3b11e1039281661ae89623e303b2d68..17fc9a3dfc84d7cffad83b63bcc1855071ac6c4a 100644 --- a/web/core/lib/Drupal/Core/Database/Driver/mysql/Install/Tasks.php +++ b/web/core/lib/Drupal/Core/Database/Driver/mysql/Install/Tasks.php @@ -65,7 +65,7 @@ protected function connect() { 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(); diff --git a/web/core/lib/Drupal/Core/Database/Driver/pgsql/Connection.php b/web/core/lib/Drupal/Core/Database/Driver/pgsql/Connection.php index e696f242fd30492164c065a7580c347f0e73dee3..80b30893cab6a01fa7ed4e41a5f56e8851c04897 100644 --- a/web/core/lib/Drupal/Core/Database/Driver/pgsql/Connection.php +++ b/web/core/lib/Drupal/Core/Database/Driver/pgsql/Connection.php @@ -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 = [ diff --git a/web/core/lib/Drupal/Core/Database/Install/Tasks.php b/web/core/lib/Drupal/Core/Database/Install/Tasks.php index 44bddea81da7979006223c434c33671a2ef6d4f2..90a0772005eaaa67e40f5816b6b696345a58f848 100644 --- a/web/core/lib/Drupal/Core/Database/Install/Tasks.php +++ b/web/core/lib/Drupal/Core/Database/Install/Tasks.php @@ -33,7 +33,7 @@ abstract class Tasks { ], [ 'arguments' => [ - 'CREATE TABLE {drupal_install_test} (id int NULL)', + 'CREATE TABLE {drupal_install_test} (id int NOT NULL PRIMARY KEY)', 'Drupal can use CREATE TABLE database commands.', 'Failed to <strong>CREATE</strong> a test table on your database server with the command %query. The server reports the following message: %error.<p>Are you sure the configured username has the necessary permissions to create tables in the database?</p>', TRUE, diff --git a/web/core/lib/Drupal/Core/Database/Query/Select.php b/web/core/lib/Drupal/Core/Database/Query/Select.php index c38638a75d1cc431741d5b8d17262cc160963c41..fe88f84172873c05dd9ae233e68bd6b72b59f1b9 100644 --- a/web/core/lib/Drupal/Core/Database/Query/Select.php +++ b/web/core/lib/Drupal/Core/Database/Query/Select.php @@ -914,6 +914,8 @@ public function __toString() { * {@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 @@ public function __clone() { 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']; + } + } } } diff --git a/web/core/lib/Drupal/Core/Database/StatementPrefetch.php b/web/core/lib/Drupal/Core/Database/StatementPrefetch.php index de60d73bf9015a3e8eafea2b8013ccf87affae83..fb7b0b4e0a03d2ae281ee64af5b66c57caf618fb 100644 --- a/web/core/lib/Drupal/Core/Database/StatementPrefetch.php +++ b/web/core/lib/Drupal/Core/Database/StatementPrefetch.php @@ -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', diff --git a/web/core/lib/Drupal/Core/Database/database.api.php b/web/core/lib/Drupal/Core/Database/database.api.php index 4cf34f8dd3006b771948290dadb4bbb20381dc6c..c39cf78cf4a9f9d7c15182fa4d952b189b78e985 100644 --- a/web/core/lib/Drupal/Core/Database/database.api.php +++ b/web/core/lib/Drupal/Core/Database/database.api.php @@ -248,18 +248,15 @@ * * The following keys are defined: * - 'description': A string in non-markup plain text describing this table - * and its purpose. References to other tables should be enclosed in - * curly-brackets. For example, the node_field_revision table - * description field might contain "Stores per-revision title and - * body data for each {node}." + * and its purpose. References to other tables should be enclosed in curly + * brackets. * - 'fields': An associative array ('fieldname' => specification) * that describes the table's database columns. The specification * is also an array. The following specification parameters are defined: * - 'description': A string in non-markup plain text describing this field - * and its purpose. References to other tables should be enclosed in - * curly-brackets. For example, the node table vid field - * description might contain "Always holds the largest (most - * recent) {node_field_revision}.vid value for this nid." + * and its purpose. References to other tables should be enclosed in curly + * brackets. For example, the users_data table 'uid' field description + * might contain "The {users}.uid this record affects." * - 'type': The generic datatype: 'char', 'varchar', 'text', 'blob', 'int', * 'float', 'numeric', or 'serial'. Most types just map to the according * database engine specific data types. Use 'serial' for auto incrementing @@ -322,64 +319,70 @@ * key column specifiers (see below) that form an index on the * table. * - * A key column specifier is either a string naming a column or an - * array of two elements, column name and length, specifying a prefix - * of the named column. + * A key column specifier is either a string naming a column or an array of two + * elements, column name and length, specifying a prefix of the named column. * - * As an example, here is a SUBSET of the schema definition for - * Drupal's 'node' table. It show four fields (nid, vid, type, and - * title), the primary key on field 'nid', a unique key named 'vid' on - * field 'vid', and two indexes, one named 'nid' on field 'nid' and - * one named 'node_title_type' on the field 'title' and the first four - * bytes of the field 'type': + * As an example, this is the schema definition for the 'users_data' table. It + * shows five fields ('uid', 'module', 'name', 'value', and 'serialized'), the + * primary key (on the 'uid', 'module', and 'name' fields), and two indexes (the + * 'module' index on the 'module' field and the 'name' index on the 'name' + * field). * * @code - * $schema['node'] = array( - * 'description' => 'The base table for nodes.', - * 'fields' => array( - * 'nid' => array('type' => 'serial', 'unsigned' => TRUE, 'not null' => TRUE), - * 'vid' => array('type' => 'int', 'unsigned' => TRUE, 'not null' => TRUE,'default' => 0), - * 'type' => array('type' => 'varchar','length' => 32,'not null' => TRUE, 'default' => ''), - * 'language' => array('type' => 'varchar','length' => 12,'not null' => TRUE,'default' => ''), - * 'title' => array('type' => 'varchar','length' => 255,'not null' => TRUE, 'default' => ''), - * 'uid' => array('type' => 'int', 'not null' => TRUE, 'default' => 0), - * 'status' => array('type' => 'int', 'not null' => TRUE, 'default' => 1), - * 'created' => array('type' => 'int', 'not null' => TRUE, 'default' => 0), - * 'changed' => array('type' => 'int', 'not null' => TRUE, 'default' => 0), - * 'comment' => array('type' => 'int', 'not null' => TRUE, 'default' => 0), - * 'promote' => array('type' => 'int', 'not null' => TRUE, 'default' => 0), - * 'moderate' => array('type' => 'int', 'not null' => TRUE,'default' => 0), - * 'sticky' => array('type' => 'int', 'not null' => TRUE, 'default' => 0), - * 'translate' => array('type' => 'int', 'not null' => TRUE, 'default' => 0), - * ), - * 'indexes' => array( - * 'node_changed' => array('changed'), - * 'node_created' => array('created'), - * 'node_moderate' => array('moderate'), - * 'node_frontpage' => array('promote', 'status', 'sticky', 'created'), - * 'node_status_type' => array('status', 'type', 'nid'), - * 'node_title_type' => array('title', array('type', 4)), - * 'node_type' => array(array('type', 4)), - * 'uid' => array('uid'), - * 'translate' => array('translate'), - * ), - * 'unique keys' => array( - * 'vid' => array('vid'), - * ), + * $schema['users_data'] = [ + * 'description' => 'Stores module data as key/value pairs per user.', + * 'fields' => [ + * 'uid' => [ + * 'description' => 'The {users}.uid this record affects.', + * 'type' => 'int', + * 'unsigned' => TRUE, + * 'not null' => TRUE, + * 'default' => 0, + * ], + * 'module' => [ + * 'description' => 'The name of the module declaring the variable.', + * 'type' => 'varchar_ascii', + * 'length' => DRUPAL_EXTENSION_NAME_MAX_LENGTH, + * 'not null' => TRUE, + * 'default' => '', + * ], + * 'name' => [ + * 'description' => 'The identifier of the data.', + * 'type' => 'varchar_ascii', + * 'length' => 128, + * 'not null' => TRUE, + * 'default' => '', + * ], + * 'value' => [ + * 'description' => 'The value.', + * 'type' => 'blob', + * 'not null' => FALSE, + * 'size' => 'big', + * ], + * 'serialized' => [ + * 'description' => 'Whether value is serialized.', + * 'type' => 'int', + * 'size' => 'tiny', + * 'unsigned' => TRUE, + * 'default' => 0, + * ], + * ], + * 'primary key' => ['uid', 'module', 'name'], + * 'indexes' => [ + * 'module' => ['module'], + * 'name' => ['name'], + * ], * // For documentation purposes only; foreign keys are not created in the * // database. - * 'foreign keys' => array( - * 'node_revision' => array( - * 'table' => 'node_field_revision', - * 'columns' => array('vid' => 'vid'), - * ), - * 'node_author' => array( + * 'foreign keys' => [ + * 'data_user' => [ * 'table' => 'users', - * 'columns' => array('uid' => 'uid'), - * ), - * ), - * 'primary key' => array('nid'), - * ); + * 'columns' => [ + * 'uid' => 'uid', + * ], + * ], + * ], + * ]; * @endcode * * @see drupal_install_schema() @@ -490,60 +493,61 @@ function hook_query_TAG_alter(Drupal\Core\Database\Query\AlterableInterface $que * @ingroup schemaapi */ function hook_schema() { - $schema['node'] = [ - // Example (partial) specification for table "node". - 'description' => 'The base table for nodes.', + $schema['users_data'] = [ + 'description' => 'Stores module data as key/value pairs per user.', 'fields' => [ - 'nid' => [ - 'description' => 'The primary identifier for a node.', - 'type' => 'serial', - 'unsigned' => TRUE, - 'not null' => TRUE, - ], - 'vid' => [ - 'description' => 'The current {node_field_revision}.vid version identifier.', + 'uid' => [ + 'description' => 'The {users}.uid this record affects.', 'type' => 'int', 'unsigned' => TRUE, 'not null' => TRUE, 'default' => 0, ], - 'type' => [ - 'description' => 'The type of this node.', - 'type' => 'varchar', - 'length' => 32, + 'module' => [ + 'description' => 'The name of the module declaring the variable.', + 'type' => 'varchar_ascii', + 'length' => DRUPAL_EXTENSION_NAME_MAX_LENGTH, 'not null' => TRUE, 'default' => '', ], - 'title' => [ - 'description' => 'The node title.', - 'type' => 'varchar', - 'length' => 255, + 'name' => [ + 'description' => 'The identifier of the data.', + 'type' => 'varchar_ascii', + 'length' => 128, 'not null' => TRUE, 'default' => '', ], + 'value' => [ + 'description' => 'The value.', + 'type' => 'blob', + 'not null' => FALSE, + 'size' => 'big', + ], + 'serialized' => [ + 'description' => 'Whether value is serialized.', + 'type' => 'int', + 'size' => 'tiny', + 'unsigned' => TRUE, + 'default' => 0, + ], ], + 'primary key' => ['uid', 'module', 'name'], 'indexes' => [ - 'node_changed' => ['changed'], - 'node_created' => ['created'], - ], - 'unique keys' => [ - 'nid_vid' => ['nid', 'vid'], - 'vid' => ['vid'], + 'module' => ['module'], + 'name' => ['name'], ], // For documentation purposes only; foreign keys are not created in the // database. 'foreign keys' => [ - 'node_revision' => [ - 'table' => 'node_field_revision', - 'columns' => ['vid' => 'vid'], - ], - 'node_author' => [ + 'data_user' => [ 'table' => 'users', - 'columns' => ['uid' => 'uid'], + 'columns' => [ + 'uid' => 'uid', + ], ], ], - 'primary key' => ['nid'], ]; + return $schema; } diff --git a/web/core/lib/Drupal/Core/DependencyInjection/Compiler/CorsCompilerPass.php b/web/core/lib/Drupal/Core/DependencyInjection/Compiler/CorsCompilerPass.php index 207e094094f4870b401bf377972e95f75e6d53ee..3e0344a0f276456efe3e3e94362388b244b71c55 100644 --- a/web/core/lib/Drupal/Core/DependencyInjection/Compiler/CorsCompilerPass.php +++ b/web/core/lib/Drupal/Core/DependencyInjection/Compiler/CorsCompilerPass.php @@ -22,7 +22,7 @@ public function process(ContainerBuilder $container) { $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'); } diff --git a/web/core/lib/Drupal/Core/DrupalKernel.php b/web/core/lib/Drupal/Core/DrupalKernel.php index 73022a5f541e358af5124260dbeeea239b244b35..3b14d4d447d431ed1fb759444a3aebba44bc60e7 100644 --- a/web/core/lib/Drupal/Core/DrupalKernel.php +++ b/web/core/lib/Drupal/Core/DrupalKernel.php @@ -19,6 +19,7 @@ use Drupal\Core\Http\TrustedHostsRequestFactory; use Drupal\Core\Installer\InstallerRedirectTrait; use Drupal\Core\Language\Language; +use Drupal\Core\Security\PharExtensionInterceptor; use Drupal\Core\Security\RequestSanitizer; use Drupal\Core\Site\Settings; use Drupal\Core\Test\TestDatabase; @@ -35,6 +36,9 @@ use Symfony\Component\HttpKernel\Exception\HttpExceptionInterface; use Symfony\Component\HttpKernel\TerminableInterface; use Symfony\Component\Routing\Route; +use TYPO3\PharStreamWrapper\Manager as PharStreamWrapperManager; +use TYPO3\PharStreamWrapper\Behavior as PharStreamWrapperBehavior; +use TYPO3\PharStreamWrapper\PharStreamWrapper; /** * The DrupalKernel class is the core of Drupal itself. @@ -298,12 +302,16 @@ public function __construct($environment, $class_loader, $allow_dumping = TRUE, } /** - * 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__)))); } @@ -467,6 +475,26 @@ public function boot() { // Initialize the container. $this->initializeContainer(); + if (in_array('phar', stream_get_wrappers(), TRUE)) { + // Set up a stream wrapper to handle insecurities due to PHP's builtin + // phar stream wrapper. This is not registered as a regular stream wrapper + // to prevent \Drupal\Core\File\FileSystem::validScheme() treating "phar" + // as a valid scheme. + try { + $behavior = new PharStreamWrapperBehavior(); + PharStreamWrapperManager::initialize( + $behavior->withAssertion(new PharExtensionInterceptor()) + ); + } + catch (\LogicException $e) { + // Continue if the PharStreamWrapperManager is already initialized. For + // example, this occurs during a module install. + // @see \Drupal\Core\Extension\ModuleInstaller::install() + }; + stream_wrapper_unregister('phar'); + stream_wrapper_register('phar', PharStreamWrapper::class); + } + $this->booted = TRUE; return $this; @@ -1091,7 +1119,7 @@ protected function initializeSettings(Request $request) { // 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); diff --git a/web/core/lib/Drupal/Core/Entity/ContentEntityDeleteForm.php b/web/core/lib/Drupal/Core/Entity/ContentEntityDeleteForm.php index 94af017758cfe827ae3224c06a1a2d0fb519287e..27dd2b7d79dba656ba265c3d56ba02701504820c 100644 --- a/web/core/lib/Drupal/Core/Entity/ContentEntityDeleteForm.php +++ b/web/core/lib/Drupal/Core/Entity/ContentEntityDeleteForm.php @@ -60,6 +60,7 @@ public function buildForm(array $form, FormStateInterface $form_state) { 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 @@ public function submitForm(array &$form, FormStateInterface $form_state) { $form_state->setRedirectUrl($this->getRedirectUrl()); } - $this->messenger()->addStatus($this->getDeletionMessage()); + $this->messenger()->addStatus($message); $this->logDeletionMessage(); } diff --git a/web/core/lib/Drupal/Core/Entity/Element/EntityAutocomplete.php b/web/core/lib/Drupal/Core/Entity/Element/EntityAutocomplete.php index cbe91d987a8705667ada26abc6441dfe9cbd6fd6..0691239dfa4d7c0d7e034240b74106a72b898bae 100644 --- a/web/core/lib/Drupal/Core/Entity/Element/EntityAutocomplete.php +++ b/web/core/lib/Drupal/Core/Entity/Element/EntityAutocomplete.php @@ -251,8 +251,8 @@ public static function validateEntityAutocomplete(array &$element, FormStateInte /** * 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. diff --git a/web/core/lib/Drupal/Core/Entity/Entity/EntityViewDisplay.php b/web/core/lib/Drupal/Core/Entity/Entity/EntityViewDisplay.php index cd36418d14ea62291363bc84db9d377d6cd9a875..6783522ac9baca6262bd5f3c57a383c042c19c0d 100644 --- a/web/core/lib/Drupal/Core/Entity/Entity/EntityViewDisplay.php +++ b/web/core/lib/Drupal/Core/Entity/Entity/EntityViewDisplay.php @@ -8,6 +8,7 @@ use Drupal\Core\Entity\EntityStorageInterface; use Drupal\Core\Entity\FieldableEntityInterface; use Drupal\Core\Entity\EntityDisplayBase; +use Drupal\Core\Render\Element; use Drupal\Core\TypedData\TranslatableInterface as TranslatableDataInterface; /** @@ -269,7 +270,7 @@ public function buildMultiple(array $entities) { foreach ($entities as $id => $entity) { // Assign the configured weights. foreach ($this->getComponents() as $name => $options) { - if (isset($build_list[$id][$name])) { + if (isset($build_list[$id][$name]) && !Element::isEmpty($build_list[$id][$name])) { $build_list[$id][$name]['#weight'] = $options['weight']; } } diff --git a/web/core/lib/Drupal/Core/Entity/EntityBundleListener.php b/web/core/lib/Drupal/Core/Entity/EntityBundleListener.php index e3b219b39c17d8f31b5a24b7e8c890ebc3741dbf..e37317a020c06f62f9044dcc91a3ff8d7d980b9f 100644 --- a/web/core/lib/Drupal/Core/Entity/EntityBundleListener.php +++ b/web/core/lib/Drupal/Core/Entity/EntityBundleListener.php @@ -68,6 +68,7 @@ public function onBundleCreate($bundle, $entity_type_id) { } // Invoke hook_entity_bundle_create() hook. $this->moduleHandler->invokeAll('entity_bundle_create', [$entity_type_id, $bundle]); + $this->entityFieldManager->clearCachedFieldDefinitions(); } /** diff --git a/web/core/lib/Drupal/Core/Entity/EntityFieldManager.php b/web/core/lib/Drupal/Core/Entity/EntityFieldManager.php index f847cfa3840bb99cfab6044ded65e7e57308b888..88186c6706881e2276c3981596c3e436b20904b1 100644 --- a/web/core/lib/Drupal/Core/Entity/EntityFieldManager.php +++ b/web/core/lib/Drupal/Core/Entity/EntityFieldManager.php @@ -497,7 +497,7 @@ public function getFieldMap() { } } - $this->cacheSet($cid, $this->fieldMap, Cache::PERMANENT, ['entity_types']); + $this->cacheSet($cid, $this->fieldMap, Cache::PERMANENT, ['entity_types', 'entity_field_info']); } } return $this->fieldMap; diff --git a/web/core/lib/Drupal/Core/Entity/EntityStorageBase.php b/web/core/lib/Drupal/Core/Entity/EntityStorageBase.php index 97e6657920b7dab13d160d9bcf7336f7e176a68b..d7263dc316196eddb9f86126b2cef965aa928e88 100644 --- a/web/core/lib/Drupal/Core/Entity/EntityStorageBase.php +++ b/web/core/lib/Drupal/Core/Entity/EntityStorageBase.php @@ -194,7 +194,7 @@ protected function setStaticCache(array $entities) { * 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. diff --git a/web/core/lib/Drupal/Core/Entity/Plugin/DataType/ConfigEntityAdapter.php b/web/core/lib/Drupal/Core/Entity/Plugin/DataType/ConfigEntityAdapter.php index 093c77dd16b110db2f1f78c7852e155d87243002..55a8bba0b988e2216dfb97035248470865e8f94d 100644 --- a/web/core/lib/Drupal/Core/Entity/Plugin/DataType/ConfigEntityAdapter.php +++ b/web/core/lib/Drupal/Core/Entity/Plugin/DataType/ConfigEntityAdapter.php @@ -2,7 +2,9 @@ namespace Drupal\Core\Entity\Plugin\DataType; +use Drupal\Core\Config\TypedConfigManagerInterface; use Drupal\Core\TypedData\Exception\MissingDataException; +use Drupal\Core\TypedData\TypedDataManagerInterface; /** * Enhances EntityAdapter for config entities. @@ -16,6 +18,13 @@ class ConfigEntityAdapter extends EntityAdapter { */ protected $entity; + /** + * The typed config manager. + * + * @var \Drupal\Core\Config\TypedConfigManagerInterface + */ + protected $typedConfigManager; + /** * {@inheritdoc} */ @@ -68,10 +77,31 @@ public function getIterator() { } /** - * Gets the typed data manager. + * Gets the typed config manager. * * @return \Drupal\Core\Config\TypedConfigManagerInterface - * The typed data manager. + * The typed config manager. + */ + protected function getTypedConfigManager() { + if (empty($this->typedConfigManager)) { + // Use the typed data manager if it is also the typed config manager. + // @todo Remove this in https://www.drupal.org/node/3011137. + $typed_data_manager = $this->getTypedDataManager(); + if ($typed_data_manager instanceof TypedConfigManagerInterface) { + $this->typedConfigManager = $typed_data_manager; + } + else { + $this->typedConfigManager = \Drupal::service('config.typed'); + } + } + + return $this->typedConfigManager; + } + + /** + * {@inheritdoc} + * + * @todo Remove this in https://www.drupal.org/node/3011137. */ public function getTypedDataManager() { if (empty($this->typedDataManager)) { @@ -81,6 +111,19 @@ public function getTypedDataManager() { return $this->typedDataManager; } + /** + * {@inheritdoc} + * + * @todo Remove this in https://www.drupal.org/node/3011137. + */ + public function setTypedDataManager(TypedDataManagerInterface $typed_data_manager) { + $this->typedDataManager = $typed_data_manager; + if ($typed_data_manager instanceof TypedConfigManagerInterface) { + $this->typedConfigManager = $typed_data_manager; + } + return $this; + } + /** * {@inheritdoc} */ @@ -97,7 +140,7 @@ public function applyDefaultValue($notify = TRUE) { * The typed data. */ protected function getConfigTypedData() { - return $this->getTypedDataManager()->createFromNameAndData($this->entity->getConfigDependencyName(), $this->entity->toArray()); + return $this->getTypedConfigManager()->createFromNameAndData($this->entity->getConfigDependencyName(), $this->entity->toArray()); } } diff --git a/web/core/lib/Drupal/Core/Entity/Plugin/DataType/EntityReference.php b/web/core/lib/Drupal/Core/Entity/Plugin/DataType/EntityReference.php index 6cf57eb1bef5fd6e87d96a7118d0539f95f17e9e..a07e63dfee79711fff27fe84fa9e5566b190eb62 100644 --- a/web/core/lib/Drupal/Core/Entity/Plugin/DataType/EntityReference.php +++ b/web/core/lib/Drupal/Core/Entity/Plugin/DataType/EntityReference.php @@ -16,7 +16,7 @@ * 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) diff --git a/web/core/lib/Drupal/Core/Entity/Query/Sql/Tables.php b/web/core/lib/Drupal/Core/Entity/Query/Sql/Tables.php index a9ff4b136dcc6aac9f4e0db3b6944b12e889a865..1f99d0f7716b74c734e6ffb99d7fa750964fee5a 100644 --- a/web/core/lib/Drupal/Core/Entity/Query/Sql/Tables.php +++ b/web/core/lib/Drupal/Core/Entity/Query/Sql/Tables.php @@ -184,6 +184,7 @@ public function addField($field, $type, $langcode) { // finds the property first. The data table is preferred, which is why // it gets added before the base table. $entity_tables = []; + $revision_table = NULL; if ($all_revisions && $field_storage && $field_storage->isRevisionable()) { $data_table = $entity_type->getRevisionDataTable(); $entity_base_table = $entity_type->getRevisionTable(); @@ -191,11 +192,18 @@ public function addField($field, $type, $langcode) { else { $data_table = $entity_type->getDataTable(); $entity_base_table = $entity_type->getBaseTable(); + + if ($field_storage && $field_storage->isRevisionable() && in_array($field_storage->getName(), $entity_type->getRevisionMetadataKeys())) { + $revision_table = $entity_type->getRevisionTable(); + } } if ($data_table) { $this->sqlQuery->addMetaData('simple_query', FALSE); $entity_tables[$data_table] = $this->getTableMapping($data_table, $entity_type_id); } + if ($revision_table) { + $entity_tables[$revision_table] = $this->getTableMapping($revision_table, $entity_type_id); + } $entity_tables[$entity_base_table] = $this->getTableMapping($entity_base_table, $entity_type_id); $sql_column = $specifier; diff --git a/web/core/lib/Drupal/Core/Entity/Sql/SqlContentEntityStorage.php b/web/core/lib/Drupal/Core/Entity/Sql/SqlContentEntityStorage.php index 422120061663cf75afe0d43921db6e3e9c1d7ed5..48545d22ded94b4a7f6b651200196095f18458a5 100644 --- a/web/core/lib/Drupal/Core/Entity/Sql/SqlContentEntityStorage.php +++ b/web/core/lib/Drupal/Core/Entity/Sql/SqlContentEntityStorage.php @@ -518,7 +518,7 @@ protected function loadFromSharedTables(array &$values, array &$translations, $l // 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. @@ -821,10 +821,13 @@ protected function doSaveFieldItems(ContentEntityInterface $entity, array $names if ($update) { $default_revision = $entity->isDefaultRevision(); if ($default_revision) { + // Remove the ID from the record to enable updates on SQL variants + // that prevent updating serial columns, for example, mssql. + unset($record->{$this->idKey}); $this->database ->update($this->baseTable) ->fields((array) $record) - ->condition($this->idKey, $record->{$this->idKey}) + ->condition($this->idKey, $entity->get($this->idKey)->value) ->execute(); } if ($this->revisionTable) { @@ -833,11 +836,15 @@ protected function doSaveFieldItems(ContentEntityInterface $entity, array $names } else { $record = $this->mapToStorageRecord($entity->getUntranslated(), $this->revisionTable); + // Remove the revision ID from the record to enable updates on SQL + // variants that prevent updating serial columns, for example, + // mssql. + unset($record->{$this->revisionKey}); $entity->preSaveRevision($this, $record); $this->database ->update($this->revisionTable) ->fields((array) $record) - ->condition($this->revisionKey, $record->{$this->revisionKey}) + ->condition($this->revisionKey, $entity->getRevisionId()) ->execute(); } } @@ -1064,19 +1071,21 @@ protected function saveRevision(ContentEntityInterface $entity) { ->condition($this->idKey, $record->{$this->idKey}) ->execute(); } + // Make sure to update the new revision key for the entity. + $entity->{$this->revisionKey}->value = $record->{$this->revisionKey}; } else { + // Remove the revision ID from the record to enable updates on SQL + // variants that prevent updating serial columns, for example, + // mssql. + unset($record->{$this->revisionKey}); $this->database ->update($this->revisionTable) ->fields((array) $record) - ->condition($this->revisionKey, $record->{$this->revisionKey}) + ->condition($this->revisionKey, $entity->getRevisionId()) ->execute(); } - - // Make sure to update the new revision key for the entity. - $entity->{$this->revisionKey}->value = $record->{$this->revisionKey}; - - return $record->{$this->revisionKey}; + return $entity->getRevisionId(); } /** diff --git a/web/core/lib/Drupal/Core/Entity/Sql/SqlContentEntityStorageSchema.php b/web/core/lib/Drupal/Core/Entity/Sql/SqlContentEntityStorageSchema.php index c73a28ca943557afdabeb143c11e077690a3fbfb..f4505bdbbf750519563e4da4e484fe0375bac89d 100644 --- a/web/core/lib/Drupal/Core/Entity/Sql/SqlContentEntityStorageSchema.php +++ b/web/core/lib/Drupal/Core/Entity/Sql/SqlContentEntityStorageSchema.php @@ -1174,12 +1174,12 @@ protected function addTableDefaults(&$schema) { * 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 @@ protected function processBaseTable(ContentEntityTypeInterface $entity_type, arr * 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 @@ protected function createSharedTableSchema(FieldStorageDefinitionInterface $stor // 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'])) { diff --git a/web/core/lib/Drupal/Core/Entity/entity.api.php b/web/core/lib/Drupal/Core/Entity/entity.api.php index ac137330f8dc7e1ae1e82663dca095741c7ef76f..65b913d125b45f56f28f512fb10ec204ccc10cd2 100644 --- a/web/core/lib/Drupal/Core/Entity/entity.api.php +++ b/web/core/lib/Drupal/Core/Entity/entity.api.php @@ -811,10 +811,10 @@ function hook_entity_view_mode_info_alter(&$view_modes) { * An associative array of all entity bundles, keyed by the entity * type name, and then the bundle name, with the following keys: * - label: The human-readable name of the bundle. - * - uri_callback: The same as the 'uri_callback' key defined for the entity - * type in the EntityManager, but for the bundle only. When determining - * the URI of an entity, if a 'uri_callback' is defined for both the - * entity type and the bundle, the one for the bundle is used. + * - uri_callback: (optional) The same as the 'uri_callback' key defined for + * the entity type in the EntityManager, but for the bundle only. When + * determining the URI of an entity, if a 'uri_callback' is defined for both + * the entity type and the bundle, the one for the bundle is used. * - translatable: (optional) A boolean value specifying whether this bundle * has translation support enabled. Defaults to FALSE. * diff --git a/web/core/lib/Drupal/Core/EventSubscriber/KernelDestructionSubscriber.php b/web/core/lib/Drupal/Core/EventSubscriber/KernelDestructionSubscriber.php index 19272abecb6b083850cdc91f5539a43f5d8d344f..d89f816dfcaf1290e0bb8a9ad9e3bd2a591291b2 100644 --- a/web/core/lib/Drupal/Core/EventSubscriber/KernelDestructionSubscriber.php +++ b/web/core/lib/Drupal/Core/EventSubscriber/KernelDestructionSubscriber.php @@ -60,10 +60,7 @@ public function onKernelTerminate(PostResponseEvent $event) { * 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; } diff --git a/web/core/lib/Drupal/Core/Extension/module.api.php b/web/core/lib/Drupal/Core/Extension/module.api.php index 76c49b5b72e4ed6ce0a7d5858802605538de6367..a7d94ff3aa3dfe32b98b3c984cc1e1fbde7ee94e 100644 --- a/web/core/lib/Drupal/Core/Extension/module.api.php +++ b/web/core/lib/Drupal/Core/Extension/module.api.php @@ -684,6 +684,20 @@ function hook_update_N(&$sandbox) { * Drupal also ensures to not execute the same hook_post_update_NAME() function * twice. * + * @section sec_bulk Batch updates + * If running your update all at once could possibly cause PHP to time out, use + * the $sandbox parameter to indicate that the Batch API should be used for your + * update. In this case, your update function acts as an implementation of + * callback_batch_operation(), and $sandbox acts as the batch context + * parameter. In your function, read the state information from the previous + * run from $sandbox (or initialize), run a chunk of updates, save the state in + * $sandbox, and set $sandbox['#finished'] to a value between 0 and 1 to + * indicate the percent completed, or 1 if it is finished (you need to do this + * explicitly in each pass). + * + * See the @link batch Batch operations topic @endlink for more information on + * how to use the Batch API. + * * @param array $sandbox * Stores information for batch updates. See above for more information. * diff --git a/web/core/lib/Drupal/Core/Field/Plugin/Field/FieldFormatter/StringFormatter.php b/web/core/lib/Drupal/Core/Field/Plugin/Field/FieldFormatter/StringFormatter.php index 320005ceef003029eb1fc2b1539f1511b9432404..ef2f43c283e9edf302c369e5e41e70c98ff5c2ef 100644 --- a/web/core/lib/Drupal/Core/Field/Plugin/Field/FieldFormatter/StringFormatter.php +++ b/web/core/lib/Drupal/Core/Field/Plugin/Field/FieldFormatter/StringFormatter.php @@ -124,7 +124,6 @@ public function viewElements(FieldItemListInterface $items, $langcode) { $elements = []; $url = NULL; if ($this->getSetting('link_to_entity')) { - // For the default revision this falls back to 'canonical'. $url = $this->getEntityUrl($items->getEntity()); } @@ -173,8 +172,11 @@ protected function viewValue(FieldItemInterface $item) { * The URI elements of the entity. */ protected function getEntityUrl(EntityInterface $entity) { - // For the default revision this falls back to 'canonical'. - return $entity->toUrl('revision'); + // For the default revision, the 'revision' link template falls back to + // 'canonical'. + // @see \Drupal\Core\Entity\Entity::toUrl() + $rel = $entity->getEntityType()->hasLinkTemplate('revision') ? 'revision' : 'canonical'; + return $entity->toUrl($rel); } } diff --git a/web/core/lib/Drupal/Core/Field/Plugin/Field/FieldFormatter/TimestampAgoFormatter.php b/web/core/lib/Drupal/Core/Field/Plugin/Field/FieldFormatter/TimestampAgoFormatter.php index c8465529447ddb4a20b8141b72e30fca7d1946cd..e4c3d9171e2ecf7655c7f07293fda33a5bbb5443 100644 --- a/web/core/lib/Drupal/Core/Field/Plugin/Field/FieldFormatter/TimestampAgoFormatter.php +++ b/web/core/lib/Drupal/Core/Field/Plugin/Field/FieldFormatter/TimestampAgoFormatter.php @@ -5,6 +5,7 @@ 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 @@ public static function defaultSettings() { * {@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 @@ public function settingsForm(array $form, FormStateInterface $form_state) { '#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 @@ public function settingsForm(array $form, FormStateInterface $form_state) { '#max' => 6, ]; - return $elements; + return $form; } /** @@ -138,10 +139,19 @@ public function settingsForm(array $form, FormStateInterface $form_state) { 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; } diff --git a/web/core/lib/Drupal/Core/Form/ConfirmFormInterface.php b/web/core/lib/Drupal/Core/Form/ConfirmFormInterface.php index 55ec252bc103a2038b551aad927d82ebed4e7cad..bdfdafcc2ae735afc9d3463d88c201b53bd460c8 100644 --- a/web/core/lib/Drupal/Core/Form/ConfirmFormInterface.php +++ b/web/core/lib/Drupal/Core/Form/ConfirmFormInterface.php @@ -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 @@ public function getCancelUrl(); /** * 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 @@ public function getDescription(); /** * 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 @@ public function getConfirmText(); /** * Returns a caption for the link which cancels the action. * - * @return string + * @return \Drupal\Core\StringTranslation\TranslatableMarkup * The form cancellation text. */ public function getCancelText(); diff --git a/web/core/lib/Drupal/Core/Form/FormBuilder.php b/web/core/lib/Drupal/Core/Form/FormBuilder.php index d94b9109b6dd5ecf08d473556a90e2d1b8c254f7..d64c1df5b8b53f422c3e038cb31a451b55b16a1a 100644 --- a/web/core/lib/Drupal/Core/Form/FormBuilder.php +++ b/web/core/lib/Drupal/Core/Form/FormBuilder.php @@ -687,7 +687,7 @@ public function prepareForm($form_id, &$form, FormStateInterface &$form_state) { // 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'; diff --git a/web/core/lib/Drupal/Core/Form/FormState.php b/web/core/lib/Drupal/Core/Form/FormState.php index 595079f4ad7a475f011e9328566e448454ff128b..8264371c832deda8aa65f2edbe1ca77fc524371a 100644 --- a/web/core/lib/Drupal/Core/Form/FormState.php +++ b/web/core/lib/Drupal/Core/Form/FormState.php @@ -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. diff --git a/web/core/lib/Drupal/Core/Http/HandlerStackConfigurator.php b/web/core/lib/Drupal/Core/Http/HandlerStackConfigurator.php index 69e3913084a45f0226e7752d7241a4f5d8709453..4a0bfdefa15f362caca207f549c59fc220e0d36b 100644 --- a/web/core/lib/Drupal/Core/Http/HandlerStackConfigurator.php +++ b/web/core/lib/Drupal/Core/Http/HandlerStackConfigurator.php @@ -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. diff --git a/web/core/lib/Drupal/Core/Http/TrustedHostsRequestFactory.php b/web/core/lib/Drupal/Core/Http/TrustedHostsRequestFactory.php index 3aa0490f4fe3ac22f9b0f89ef66790e41289786f..f1ddd55a747036d89d1828ee96414e0a84d36e95 100644 --- a/web/core/lib/Drupal/Core/Http/TrustedHostsRequestFactory.php +++ b/web/core/lib/Drupal/Core/Http/TrustedHostsRequestFactory.php @@ -44,7 +44,7 @@ public function __construct($host) { * @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 diff --git a/web/core/lib/Drupal/Core/Installer/Exception/InstallProfileMismatchException.php b/web/core/lib/Drupal/Core/Installer/Exception/InstallProfileMismatchException.php index 7717b094b32d4a940eb74ca5bc559840c20c60bf..bca7cca562163c0e18c5c154b2c3bb2fcfad5a33 100644 --- a/web/core/lib/Drupal/Core/Installer/Exception/InstallProfileMismatchException.php +++ b/web/core/lib/Drupal/Core/Installer/Exception/InstallProfileMismatchException.php @@ -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. * diff --git a/web/core/lib/Drupal/Core/Layout/LayoutPluginManager.php b/web/core/lib/Drupal/Core/Layout/LayoutPluginManager.php index a5a465293775b4b75c7d84899d44bcba1f28eb3a..2cd0c689573591a414b4732cc3be1bfc0412c6df 100644 --- a/web/core/lib/Drupal/Core/Layout/LayoutPluginManager.php +++ b/web/core/lib/Drupal/Core/Layout/LayoutPluginManager.php @@ -13,6 +13,7 @@ use Drupal\Core\Plugin\Discovery\YamlDiscoveryDecorator; use Drupal\Core\Layout\Annotation\Layout; use Drupal\Core\Plugin\FilteredPluginManagerTrait; +use Drupal\Core\StringTranslation\TranslatableMarkup; /** * Provides a plugin manager for layouts. @@ -71,6 +72,10 @@ protected function getDiscovery() { if (!$this->discovery) { $discovery = new AnnotatedClassDiscovery($this->subdir, $this->namespaces, $this->pluginDefinitionAnnotationName, $this->additionalAnnotationNamespaces); $discovery = new YamlDiscoveryDecorator($discovery, 'layouts', $this->moduleHandler->getModuleDirectories() + $this->themeHandler->getThemeDirectories()); + $discovery + ->addTranslatableProperty('label') + ->addTranslatableProperty('description') + ->addTranslatableProperty('category'); $discovery = new AnnotationBridgeDecorator($discovery, $this->pluginDefinitionAnnotationName); $discovery = new ContainerDerivativeDiscoveryDecorator($discovery); $this->discovery = $discovery; @@ -140,6 +145,15 @@ public function processDefinition(&$definition, $plugin_id) { if (!$definition->getDefaultRegion()) { $definition->setDefaultRegion(key($definition->getRegions())); } + // Makes sure region names are translatable. + $regions = array_map(function ($region) { + if (!$region['label'] instanceof TranslatableMarkup) { + // Region labels from YAML discovery needs translation. + $region['label'] = new TranslatableMarkup($region['label'], [], ['context' => 'layout_region']); + } + return $region; + }, $definition->getRegions()); + $definition->setRegions($regions); } /** diff --git a/web/core/lib/Drupal/Core/Mail/MailManager.php b/web/core/lib/Drupal/Core/Mail/MailManager.php index 3a7a93f8b193df088f01cc16fd54b00e9bd3be65..5cf3c9ea05b1b0e0872235941c05659ac43ef054 100644 --- a/web/core/lib/Drupal/Core/Mail/MailManager.php +++ b/web/core/lib/Drupal/Core/Mail/MailManager.php @@ -2,14 +2,17 @@ namespace Drupal\Core\Mail; +use Drupal\Component\Render\MarkupInterface; use Drupal\Component\Render\PlainTextOutput; -use Drupal\Component\Utility\Unicode; +use Drupal\Component\Utility\Html; +use Drupal\Component\Utility\Mail as MailHelper; use Drupal\Core\Logger\LoggerChannelFactoryInterface; use Drupal\Core\Messenger\MessengerTrait; 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; @@ -251,12 +254,8 @@ public function doMail($module, $key, $to, $langcode, $params = [], $reply = NUL // Return-Path headers should have a domain authorized to use the // originating SMTP server. $headers['Sender'] = $headers['Return-Path'] = $site_mail; - // Headers are usually encoded in the mail plugin that implements - // \Drupal\Core\Mail\MailInterface::mail(), for example, - // \Drupal\Core\Mail\Plugin\Mail\PhpMail::mail(). The site name must be - // encoded here to prevent mail plugins from encoding the email address, - // which would break the header. - $headers['From'] = Unicode::mimeHeaderEncode($site_config->get('name'), TRUE) . ' <' . $site_mail . '>'; + // Make sure the site-name is a RFC-2822 compliant 'display-name'. + $headers['From'] = MailHelper::formatDisplayName($site_config->get('name')) . ' <' . $site_mail . '>'; if ($reply) { $headers['Reply-to'] = $reply; } @@ -277,6 +276,13 @@ public function doMail($module, $key, $to, $langcode, $params = [], $reply = NUL // 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); diff --git a/web/core/lib/Drupal/Core/Menu/LocalActionDefault.php b/web/core/lib/Drupal/Core/Menu/LocalActionDefault.php index ab562e6ddb4c8dee3c195d024c872c083559106d..5e161ec1de31d717fcf7c204ccb010ac307364aa 100644 --- a/web/core/lib/Drupal/Core/Menu/LocalActionDefault.php +++ b/web/core/lib/Drupal/Core/Menu/LocalActionDefault.php @@ -83,33 +83,36 @@ public function getWeight() { * {@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; } /** diff --git a/web/core/lib/Drupal/Core/Menu/LocalActionManager.php b/web/core/lib/Drupal/Core/Menu/LocalActionManager.php index bd527375e46dee82df808f584520981678b0e2f2..a95f445dada24fecfda925e9c4fce422736de045 100644 --- a/web/core/lib/Drupal/Core/Menu/LocalActionManager.php +++ b/web/core/lib/Drupal/Core/Menu/LocalActionManager.php @@ -196,9 +196,10 @@ public function getActionsForRoute($route_appears) { } } $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 @@ public function getActionsForRoute($route_appears) { '#weight' => $plugin->getWeight(), ]; $cacheability->addCacheableDependency($access)->addCacheableDependency($plugin); - $cacheability->applyTo($links[$plugin_id]); } - $links['#cache']['contexts'][] = 'route'; + $cacheability->applyTo($links); return $links; } diff --git a/web/core/lib/Drupal/Core/Menu/LocalTaskDefault.php b/web/core/lib/Drupal/Core/Menu/LocalTaskDefault.php index 30fba4fb43fcb2f5c4f2e1d9a356edf86e449c29..49a7a2cc686268baa04ccb2757e8ef5a086ebe96 100644 --- a/web/core/lib/Drupal/Core/Menu/LocalTaskDefault.php +++ b/web/core/lib/Drupal/Core/Menu/LocalTaskDefault.php @@ -41,34 +41,36 @@ public function getRouteName() { * {@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; } /** diff --git a/web/core/lib/Drupal/Core/Menu/MenuLinkTreeInterface.php b/web/core/lib/Drupal/Core/Menu/MenuLinkTreeInterface.php index 8bd3c3810c927ac6fc95fdcf70bb8e7837419fdc..32a06833e80f65b2bd4ba6878a26667ef75b66fc 100644 --- a/web/core/lib/Drupal/Core/Menu/MenuLinkTreeInterface.php +++ b/web/core/lib/Drupal/Core/Menu/MenuLinkTreeInterface.php @@ -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 diff --git a/web/core/lib/Drupal/Core/PageCache/RequestPolicy/NoSessionOpen.php b/web/core/lib/Drupal/Core/PageCache/RequestPolicy/NoSessionOpen.php index fd583a84b9793d8d826988b526afabdd165889b5..e29ae0bd032b0db29da5c75ff9cf103b400ce7cd 100644 --- a/web/core/lib/Drupal/Core/PageCache/RequestPolicy/NoSessionOpen.php +++ b/web/core/lib/Drupal/Core/PageCache/RequestPolicy/NoSessionOpen.php @@ -11,7 +11,7 @@ * * 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 { diff --git a/web/core/lib/Drupal/Core/Path/AliasStorage.php b/web/core/lib/Drupal/Core/Path/AliasStorage.php index a02bc3534d0157ba61813f0dad1a9b8e567acdf5..b6898487197d0b2d9b67644918613fcedc9abb96 100644 --- a/web/core/lib/Drupal/Core/Path/AliasStorage.php +++ b/web/core/lib/Drupal/Core/Path/AliasStorage.php @@ -106,11 +106,11 @@ public function save($source, $alias, $langcode = LanguageInterface::LANGCODE_NO $this->catchException($e); $original = FALSE; } - $fields['pid'] = $pid; $query = $this->connection->update(static::TABLE) ->fields($fields) ->condition('pid', $pid); $pid = $query->execute(); + $fields['pid'] = $pid; $fields['original'] = $original; $operation = 'update'; } diff --git a/web/core/lib/Drupal/Core/PathProcessor/InboundPathProcessorInterface.php b/web/core/lib/Drupal/Core/PathProcessor/InboundPathProcessorInterface.php index ed9d187524fee21541538e228c240d95e132da2b..c859359612efc361a38924419a5047584dd76dc7 100644 --- a/web/core/lib/Drupal/Core/PathProcessor/InboundPathProcessorInterface.php +++ b/web/core/lib/Drupal/Core/PathProcessor/InboundPathProcessorInterface.php @@ -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. diff --git a/web/core/lib/Drupal/Core/Plugin/Context/Context.php b/web/core/lib/Drupal/Core/Plugin/Context/Context.php index a33eca2a454efb4ddd8c09053fb8fd9811e4694a..ac541c430f0630b17b4374e6012134a4fd74aa7c 100644 --- a/web/core/lib/Drupal/Core/Plugin/Context/Context.php +++ b/web/core/lib/Drupal/Core/Plugin/Context/Context.php @@ -6,6 +6,7 @@ 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 @@ class Context extends ComponentContext implements ContextInterface { use TypedDataTrait; + use DependencySerializationTrait; /** * The data associated with the context. diff --git a/web/core/lib/Drupal/Core/Plugin/Context/ContextDefinition.php b/web/core/lib/Drupal/Core/Plugin/Context/ContextDefinition.php index 9d8c81f588714182d5cb4de1ea695b73dd7396d8..be1d5784693b9e975f60acc113fe9b4236120d09 100644 --- a/web/core/lib/Drupal/Core/Plugin/Context/ContextDefinition.php +++ b/web/core/lib/Drupal/Core/Plugin/Context/ContextDefinition.php @@ -270,7 +270,7 @@ public function getConstraint($constraint_name) { public function setConstraints(array $constraints) { // If the backwards compatibility layer is present, delegate to that. if ($this->entityContextDefinition) { - $this->entityContextDefinition->setConstraint(); + $this->entityContextDefinition->setConstraints($constraints); } $this->constraints = $constraints; diff --git a/web/core/lib/Drupal/Core/Plugin/ContextAwarePluginAssignmentTrait.php b/web/core/lib/Drupal/Core/Plugin/ContextAwarePluginAssignmentTrait.php index 31ff649fafff6d6c2091bf3ec37664802edc6d88..75cbc681f82e21926454277ab75d4deb4c8ebebc 100644 --- a/web/core/lib/Drupal/Core/Plugin/ContextAwarePluginAssignmentTrait.php +++ b/web/core/lib/Drupal/Core/Plugin/ContextAwarePluginAssignmentTrait.php @@ -48,7 +48,10 @@ protected function addContextAssignmentElement(ContextAwarePluginInterface $plug ]; } - if (count($options) > 1 || !$definition->isRequired()) { + // Show the context selector only if there is more than 1 option to choose + // from. Also, show if there is a single option but the plugin does not + // require a context. + if (count($options) > 1 || (count($options) == 1 && !$definition->isRequired())) { $assignments = $plugin->getContextMapping(); $element[$context_slot] = [ '#title' => $definition->getLabel() ?: $this->t('Select a @context value:', ['@context' => $context_slot]), diff --git a/web/core/lib/Drupal/Core/Plugin/ContextAwarePluginBase.php b/web/core/lib/Drupal/Core/Plugin/ContextAwarePluginBase.php index 80f10d202149dff797e5ea8e1a2158ec06d56925..ed8abf17fad0af571d1a68a6723cae3cf1200958 100644 --- a/web/core/lib/Drupal/Core/Plugin/ContextAwarePluginBase.php +++ b/web/core/lib/Drupal/Core/Plugin/ContextAwarePluginBase.php @@ -70,7 +70,7 @@ public function setContext($name, ComponentContextInterface $context) { * {@inheritdoc} */ public function setContextValue($name, $value) { - $this->context[$name] = Context::createFromContext($this->getContext($name), $value); + $this->setContext($name, Context::createFromContext($this->getContext($name), $value)); return $this; } diff --git a/web/core/lib/Drupal/Core/ProxyBuilder/ProxyBuilder.php b/web/core/lib/Drupal/Core/ProxyBuilder/ProxyBuilder.php index a718a958e22e7d7441c1b2feadbec44ff37b6a0e..f808fba223af43698c704a91a8021de5390030a9 100644 --- a/web/core/lib/Drupal/Core/ProxyBuilder/ProxyBuilder.php +++ b/web/core/lib/Drupal/Core/ProxyBuilder/ProxyBuilder.php @@ -5,7 +5,7 @@ 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 { diff --git a/web/core/lib/Drupal/Core/Render/Element/Email.php b/web/core/lib/Drupal/Core/Render/Element/Email.php index dce2a344c4953a45737654dc4e8fa6141534b8e4..84bb35265c34215facefe4c03f5f2430ec562b47 100644 --- a/web/core/lib/Drupal/Core/Render/Element/Email.php +++ b/web/core/lib/Drupal/Core/Render/Element/Email.php @@ -11,12 +11,14 @@ * 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 * diff --git a/web/core/lib/Drupal/Core/Render/Element/File.php b/web/core/lib/Drupal/Core/Render/Element/File.php index 07bd415078d7f2754ac396968701d94c1633b790..bf2310a4afaf0417b3f67eb18f5831e7fa965dd3 100644 --- a/web/core/lib/Drupal/Core/Render/Element/File.php +++ b/web/core/lib/Drupal/Core/Render/Element/File.php @@ -44,7 +44,7 @@ public function getInfo() { */ public static function processFile(&$element, FormStateInterface $form_state, &$complete_form) { if ($element['#multiple']) { - $element['#attributes'] = ['multiple' => 'multiple']; + $element['#attributes']['multiple'] = 'multiple'; $element['#name'] .= '[]'; } return $element; diff --git a/web/core/lib/Drupal/Core/Render/Element/Password.php b/web/core/lib/Drupal/Core/Render/Element/Password.php index 4ba2058397dc01f6c455749c1a8c6b6daa6872ad..c40bb4c25abafd6a4ac8a44b2355814b26d78cc9 100644 --- a/web/core/lib/Drupal/Core/Render/Element/Password.php +++ b/web/core/lib/Drupal/Core/Render/Element/Password.php @@ -10,6 +10,7 @@ * * 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 @@ * '#type' => 'password', * '#title' => $this->t('Password'), * '#size' => 25, + * '#pattern' => '[01]+', * ); * @endcode * diff --git a/web/core/lib/Drupal/Core/Render/Element/RenderElement.php b/web/core/lib/Drupal/Core/Render/Element/RenderElement.php index 5a26db0c005abf21696a448a7325fec9c4bcd990..35814589b3d981dba7b43675601aedf90d4b45f1 100644 --- a/web/core/lib/Drupal/Core/Render/Element/RenderElement.php +++ b/web/core/lib/Drupal/Core/Render/Element/RenderElement.php @@ -32,7 +32,7 @@ * 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. * diff --git a/web/core/lib/Drupal/Core/Render/Element/StatusMessages.php b/web/core/lib/Drupal/Core/Render/Element/StatusMessages.php index a5a28429812f4a0152c834071f1171366499bd1d..d8627343eea01bb766de507d518bd0c139492fa7 100644 --- a/web/core/lib/Drupal/Core/Render/Element/StatusMessages.php +++ b/web/core/lib/Drupal/Core/Render/Element/StatusMessages.php @@ -76,7 +76,9 @@ public static function generatePlaceholder(array $element) { public static function renderMessages($type = NULL) { $render = []; if (isset($type)) { - $messages = \Drupal::messenger()->deleteByType($type); + $messages = [ + $type => \Drupal::messenger()->deleteByType($type), + ]; } else { $messages = \Drupal::messenger()->deleteAll(); diff --git a/web/core/lib/Drupal/Core/Render/Element/Tel.php b/web/core/lib/Drupal/Core/Render/Element/Tel.php index 9289a1d028ce711b50af325ec196b37504a27bf1..041f68a6549d6e081ab094b6ba31d76f9d9ed505 100644 --- a/web/core/lib/Drupal/Core/Render/Element/Tel.php +++ b/web/core/lib/Drupal/Core/Render/Element/Tel.php @@ -12,12 +12,14 @@ * * 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 * diff --git a/web/core/lib/Drupal/Core/Render/Element/Textfield.php b/web/core/lib/Drupal/Core/Render/Element/Textfield.php index 0bdc294a096b8ded27c23d9ce3d7ed06f2316c5f..763646b7a475d403ed83b14b5021d0646628d8dc 100644 --- a/web/core/lib/Drupal/Core/Render/Element/Textfield.php +++ b/web/core/lib/Drupal/Core/Render/Element/Textfield.php @@ -15,6 +15,7 @@ * 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 @@ * '#default_value' => $node->title, * '#size' => 60, * '#maxlength' => 128, - * '#required' => TRUE, + * '#pattern' => 'some-prefix-[a-z]+', + * '#required' => TRUE, * ); * @endcode * diff --git a/web/core/lib/Drupal/Core/Render/Element/Url.php b/web/core/lib/Drupal/Core/Render/Element/Url.php index c3574b095ef089d1b9c5b14f58b179555b5934bb..66e2141a894ba2ddd3f60beda59a5d73bdc69443 100644 --- a/web/core/lib/Drupal/Core/Render/Element/Url.php +++ b/web/core/lib/Drupal/Core/Render/Element/Url.php @@ -12,6 +12,7 @@ * 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 @@ * '#type' => 'url', * '#title' => $this->t('Home Page'), * '#size' => 30, + * '#pattern' => '*.example.com', * ... * ); * @endcode diff --git a/web/core/lib/Drupal/Core/Render/PreviewFallbackInterface.php b/web/core/lib/Drupal/Core/Render/PreviewFallbackInterface.php new file mode 100644 index 0000000000000000000000000000000000000000..cbaf6ac20a4985ec8e6a94114a1b0ce74e41a2d4 --- /dev/null +++ b/web/core/lib/Drupal/Core/Render/PreviewFallbackInterface.php @@ -0,0 +1,21 @@ +<?php + +namespace Drupal\Core\Render; + +/** + * Allows an element to provide a fallback representation of itself for preview. + */ +interface PreviewFallbackInterface { + + /** + * Returns a string to be used as a fallback during preview. + * + * This is typically used when an element has no output and must be displayed, + * for example during configuration. + * + * @return string|\Drupal\Core\StringTranslation\TranslatableMarkup + * A string representing for this. + */ + public function getPreviewFallbackString(); + +} diff --git a/web/core/lib/Drupal/Core/Routing/Router.php b/web/core/lib/Drupal/Core/Routing/Router.php index ee2dc28acd041f38549f84c272d61a874fab2cb3..c6c5dc0aa7662d805ee1688f0c80adc8f800d017 100644 --- a/web/core/lib/Drupal/Core/Routing/Router.php +++ b/web/core/lib/Drupal/Core/Routing/Router.php @@ -125,6 +125,7 @@ public function matchRequest(Request $request) { throw new ResourceNotFoundException(sprintf('No routes found for "%s".', $this->currentPath->getPath())); } $collection = $this->applyRouteFilters($collection, $request); + $collection = $this->applyFitOrder($collection); if ($ret = $this->matchCollection(rawurldecode($this->currentPath->getPath($request)), $collection)) { return $this->applyRouteEnhancers($ret, $request); @@ -286,6 +287,44 @@ protected function applyRouteFilters(RouteCollection $collection, Request $reque return $collection; } + /** + * Reapplies the fit order to a RouteCollection object. + * + * Route filters can reorder route collections. For example, routes with an + * explicit _format requirement will be preferred. This can result in a less + * fit route being used. For example, as a result of filtering /user/% comes + * before /user/login. In order to not break this fundamental property of + * routes, we need to reapply the fit order. We also need to ensure that order + * within each group of the same fit is preserved. + * + * @param \Symfony\Component\Routing\RouteCollection $collection + * The route collection. + * + * @return \Symfony\Component\Routing\RouteCollection + * The reordered route collection. + */ + protected function applyFitOrder(RouteCollection $collection) { + $buckets = []; + // Sort all the routes by fit descending. + foreach ($collection->all() as $name => $route) { + $fit = $route->compile()->getFit(); + $buckets += [$fit => []]; + $buckets[$fit][] = [$name, $route]; + } + krsort($buckets); + + $flattened = array_reduce($buckets, 'array_merge', []); + + // Add them back onto a new route collection. + $collection = new RouteCollection(); + foreach ($flattened as $pair) { + $name = $pair[0]; + $route = $pair[1]; + $collection->add($name, $route); + } + return $collection; + } + /** * {@inheritdoc} */ diff --git a/web/core/lib/Drupal/Core/Security/PharExtensionInterceptor.php b/web/core/lib/Drupal/Core/Security/PharExtensionInterceptor.php new file mode 100644 index 0000000000000000000000000000000000000000..a77e9f84c267cfa2b180db38792b989a80580a23 --- /dev/null +++ b/web/core/lib/Drupal/Core/Security/PharExtensionInterceptor.php @@ -0,0 +1,73 @@ +<?php + +namespace Drupal\Core\Security; + +use TYPO3\PharStreamWrapper\Assertable; +use TYPO3\PharStreamWrapper\Helper; +use TYPO3\PharStreamWrapper\Exception; + +/** + * An alternate PharExtensionInterceptor to support phar-based CLI tools. + * + * @see \TYPO3\PharStreamWrapper\Interceptor\PharExtensionInterceptor + */ +class PharExtensionInterceptor implements Assertable { + + /** + * Determines whether phar file is allowed to execute. + * + * The phar file is allowed to execute if: + * - the base file name has a ".phar" suffix. + * - it is the CLI tool that has invoked the interceptor. + * + * @param string $path + * The path of the phar file to check. + * + * @param string $command + * The command being carried out. + * + * @return bool + * TRUE if the phar file is allowed to execute. + * + * @throws Exception + * Thrown when the file is not allowed to execute. + */ + public function assert($path, $command) { + if ($this->baseFileContainsPharExtension($path)) { + return TRUE; + } + throw new Exception( + sprintf( + 'Unexpected file extension in "%s"', + $path + ), + 1535198703 + ); + } + + /** + * @param string $path + * The path of the phar file to check. + * + * @return bool + * TRUE if the file has a .phar extension or if the execution has been + * invoked by the phar file. + */ + private function baseFileContainsPharExtension($path) { + $baseFile = Helper::determineBaseFile($path); + if ($baseFile === NULL) { + return FALSE; + } + // If the stream wrapper is registered by invoking a phar file that does + // not not have .phar extension then this should be allowed. For + // example, some CLI tools recommend removing the extension. + $backtrace = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS); + $caller = array_pop($backtrace); + if (isset($caller['file']) && $baseFile === $caller['file']) { + return TRUE; + } + $fileExtension = pathinfo($baseFile, PATHINFO_EXTENSION); + return strtolower($fileExtension) === 'phar'; + } + +} diff --git a/web/core/lib/Drupal/Core/Session/SessionConfiguration.php b/web/core/lib/Drupal/Core/Session/SessionConfiguration.php index 49dc63e915e65b4a09c830ee121dfe208d394444..bbdde7cb5d67ed7e0a5787d845a6b1aef8cab57a 100644 --- a/web/core/lib/Drupal/Core/Session/SessionConfiguration.php +++ b/web/core/lib/Drupal/Core/Session/SessionConfiguration.php @@ -106,7 +106,7 @@ protected function getUnprefixedName(Request $request) { * 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 diff --git a/web/core/lib/Drupal/Core/Session/SessionManager.php b/web/core/lib/Drupal/Core/Session/SessionManager.php index 607103109dbcc809520b236665fd2ca0b4377670..79813986786bc1567d495d1cc0ba2f63151c2eea 100644 --- a/web/core/lib/Drupal/Core/Session/SessionManager.php +++ b/web/core/lib/Drupal/Core/Session/SessionManager.php @@ -218,6 +218,11 @@ public function regenerate($destroy = FALSE, $lifetime = NULL) { if ($this->isStarted()) { $old_session_id = $this->getId(); + // Save and close the old session. Call the parent method to avoid issue + // with session destruction due to the session being considered obsolete. + parent::save(); + // Ensure the session is reloaded correctly. + $this->startedLazy = TRUE; } session_id(Crypt::randomBytesBase64()); @@ -230,10 +235,7 @@ public function regenerate($destroy = FALSE, $lifetime = NULL) { $this->migrateStoredSession($old_session_id); } - if (!$this->isStarted()) { - // Start the session when it doesn't exist yet. - $this->startNow(); - } + $this->startNow(); } /** diff --git a/web/core/lib/Drupal/Core/Session/WriteSafeSessionHandlerInterface.php b/web/core/lib/Drupal/Core/Session/WriteSafeSessionHandlerInterface.php index 46dc7ef01fb655f479bf97fb3b656c9a6c348a84..b164fc2a37097eb1519c938e05b8c3acb14b2b2e 100644 --- a/web/core/lib/Drupal/Core/Session/WriteSafeSessionHandlerInterface.php +++ b/web/core/lib/Drupal/Core/Session/WriteSafeSessionHandlerInterface.php @@ -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 @@ public function setSessionWritable($flag); * 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(); diff --git a/web/core/lib/Drupal/Core/State/State.php b/web/core/lib/Drupal/Core/State/State.php index cefcb6273e6bcae88681f8b8c84960bc18b07c2a..f35c954596fc260e31aff65816e553a418405089 100644 --- a/web/core/lib/Drupal/Core/State/State.php +++ b/web/core/lib/Drupal/Core/State/State.php @@ -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 @@ public function __construct(KeyValueFactoryInterface $key_value_factory, CacheBa * {@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 @@ protected function resolveCacheMiss($key) { */ 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 @@ public function getMultiple(array $keys) { * {@inheritdoc} */ public function set($key, $value) { - parent::set($key, $value); + $this->cache[$key] = $value; $this->keyValueStore->set($key, $value); } @@ -76,7 +89,7 @@ public function set($key, $value) { */ 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 @@ public function setMultiple(array $data) { * {@inheritdoc} */ public function delete($key) { - parent::delete($key); - $this->keyValueStore->delete($key); + $this->deleteMultiple([$key]); } /** @@ -94,7 +106,7 @@ public function delete($key) { */ public function deleteMultiple(array $keys) { foreach ($keys as $key) { - parent::delete($key); + unset($this->cache[$key]); } $this->keyValueStore->deleteMultiple($keys); } @@ -103,7 +115,7 @@ public function deleteMultiple(array $keys) { * {@inheritdoc} */ public function resetCache() { - $this->clear(); + $this->cache = []; } } diff --git a/web/core/lib/Drupal/Core/StreamWrapper/StreamWrapperInterface.php b/web/core/lib/Drupal/Core/StreamWrapper/StreamWrapperInterface.php index 1845b8722dbf4c84d4585884f7e6ef0af003d20c..84ab52c8c0130094e71ede6bed1236f2522800ea 100644 --- a/web/core/lib/Drupal/Core/StreamWrapper/StreamWrapperInterface.php +++ b/web/core/lib/Drupal/Core/StreamWrapper/StreamWrapperInterface.php @@ -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 diff --git a/web/core/lib/Drupal/Core/TempStore/PrivateTempStore.php b/web/core/lib/Drupal/Core/TempStore/PrivateTempStore.php index 67d6e32d6cd6bbb4b017a65c71997bc0a126edc1..606a0dc9e8db4952383cc2a6e892cc0c68854995 100644 --- a/web/core/lib/Drupal/Core/TempStore/PrivateTempStore.php +++ b/web/core/lib/Drupal/Core/TempStore/PrivateTempStore.php @@ -2,6 +2,7 @@ namespace Drupal\Core\TempStore; +use Drupal\Core\DependencyInjection\DependencySerializationTrait; use Drupal\Core\KeyValueStore\KeyValueStoreExpirableInterface; use Drupal\Core\Lock\LockBackendInterface; use Drupal\Core\Session\AccountProxyInterface; @@ -27,6 +28,7 @@ * \Drupal\Core\TempStore\SharedTempStore. */ class PrivateTempStore { + use DependencySerializationTrait; /** * The key/value storage object used for this data. @@ -123,6 +125,7 @@ public function set($key, $value) { 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 +222,34 @@ protected function createkey($key) { * 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(); + } } } diff --git a/web/core/lib/Drupal/Core/TypedData/TypedDataManager.php b/web/core/lib/Drupal/Core/TypedData/TypedDataManager.php index 228722fdf04d640d8c242e8c992a7d252135d747..9ac018c37efdb48cfd06d528e88542ea65311e49 100644 --- a/web/core/lib/Drupal/Core/TypedData/TypedDataManager.php +++ b/web/core/lib/Drupal/Core/TypedData/TypedDataManager.php @@ -188,7 +188,7 @@ public function getPropertyInstance(TypedDataInterface $object, $property_name, 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); } diff --git a/web/core/lib/Drupal/Core/TypedData/Validation/RecursiveContextualValidator.php b/web/core/lib/Drupal/Core/TypedData/Validation/RecursiveContextualValidator.php index a5d453ae58e5a6b8bf3b879e0bf5ddb7f78f6496..449996710eb60a9fa54d933801b7f2b713e9105d 100644 --- a/web/core/lib/Drupal/Core/TypedData/Validation/RecursiveContextualValidator.php +++ b/web/core/lib/Drupal/Core/TypedData/Validation/RecursiveContextualValidator.php @@ -126,10 +126,16 @@ protected function validateNode(TypedDataInterface $data, $constraints = NULL, $ $metadata = $this->metadataFactory->getMetadataFor($data); $cache_key = spl_object_hash($data); $property_path = $is_root_call ? '' : PropertyPath::append($previous_path, $data->getName()); + + // Prefer a specific instance of the typed data manager stored by the data + // if it is available. This is necessary for specialized typed data objects, + // for example those using the typed config subclass of the manager. + $typed_data_manager = method_exists($data, 'getTypedDataManager') ? $data->getTypedDataManager() : $this->typedDataManager; + // Pass the canonical representation of the data as validated value to // constraint validators, such that they do not have to care about Typed // Data. - $value = $this->typedDataManager->getCanonicalRepresentation($data); + $value = $typed_data_manager->getCanonicalRepresentation($data); $this->context->setNode($value, $data, $metadata, $property_path); if (isset($constraints) || !$this->context->isGroupValidated($cache_key, Constraint::DEFAULT_GROUP)) { diff --git a/web/core/lib/Drupal/Core/Update/UpdateKernel.php b/web/core/lib/Drupal/Core/Update/UpdateKernel.php index 24a5755e3061696b1c0c7467958a3ac41deb5bb7..2b74dabb67be3e17a9a0c886e4913fd8cd8eae57 100644 --- a/web/core/lib/Drupal/Core/Update/UpdateKernel.php +++ b/web/core/lib/Drupal/Core/Update/UpdateKernel.php @@ -5,6 +5,7 @@ use Drupal\Core\DrupalKernel; use Drupal\Core\Session\AnonymousUserSession; use Drupal\Core\Site\Settings; +use Drupal\Core\StackMiddleware\ReverseProxyMiddleware; use Symfony\Cmf\Component\Routing\RouteObjectInterface; use Symfony\Component\HttpFoundation\ParameterBag; use Symfony\Component\HttpFoundation\Request; @@ -59,6 +60,7 @@ public function handle(Request $request, $type = self::MASTER_REQUEST, $catch = // First boot up basic things, like loading the include files. $this->initializeSettings($request); + ReverseProxyMiddleware::setSettingsOnRequest($request, Settings::getInstance()); $this->boot(); $container = $this->getContainer(); /** @var \Symfony\Component\HttpFoundation\RequestStack $request_stack */ diff --git a/web/core/lib/Drupal/Core/Update/UpdateRegistry.php b/web/core/lib/Drupal/Core/Update/UpdateRegistry.php index a4e0081cf16d82ee7b4514108d6bd3ec4af2734d..76ac81cb8ad7c668d64dacad1cb35d1e9bbbe322 100644 --- a/web/core/lib/Drupal/Core/Update/UpdateRegistry.php +++ b/web/core/lib/Drupal/Core/Update/UpdateRegistry.php @@ -197,7 +197,7 @@ public function getPendingUpdateInformation() { } /** - * Registers that update fucntions got executed. + * Registers that update functions were executed. * * @param string[] $function_names * The executed update functions. diff --git a/web/core/lib/Drupal/Core/Updater/Module.php b/web/core/lib/Drupal/Core/Updater/Module.php index 35232b3c0d4df7737238dcfde9d2f6a456c182a1..4829c5380754e4082001742fe4d903fa7b3581cc 100644 --- a/web/core/lib/Drupal/Core/Updater/Module.php +++ b/web/core/lib/Drupal/Core/Updater/Module.php @@ -105,7 +105,7 @@ public function getSchemaUpdates() { * {@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 diff --git a/web/core/lib/Drupal/Core/Updater/Theme.php b/web/core/lib/Drupal/Core/Updater/Theme.php index 7ac70f098fd1813583037dc9c4aaddb85fab8840..4b6cd408109adbc9dddbab351d319ff91baeff0d 100644 --- a/web/core/lib/Drupal/Core/Updater/Theme.php +++ b/web/core/lib/Drupal/Core/Updater/Theme.php @@ -87,7 +87,7 @@ public function postInstall() { * {@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 diff --git a/web/core/lib/Drupal/Core/Utility/UnroutedUrlAssembler.php b/web/core/lib/Drupal/Core/Utility/UnroutedUrlAssembler.php index 2569ee4adbaba186634f2a542674a1cd40806c9e..5e50f5e2b30617633100d69e24f1c5f11e2410de 100644 --- a/web/core/lib/Drupal/Core/Utility/UnroutedUrlAssembler.php +++ b/web/core/lib/Drupal/Core/Utility/UnroutedUrlAssembler.php @@ -78,7 +78,6 @@ protected function buildExternalUrl($uri, array $options = [], $collect_bubbleab $options += ['query' => []]; $options['query'] = NestedArray::mergeDeep($parsed['query'], $options['query']); - ksort($options['query']); if ($parsed['fragment'] && !$options['fragment']) { $options['fragment'] = '#' . $parsed['fragment']; diff --git a/web/core/misc/announce.es6.js b/web/core/misc/announce.es6.js index f8ab348c731b99a0dd5eb5f50b65222a7aa0f97b..2d852f7bf191f1c94d6b77dc5cfc07cceda08d56 100644 --- a/web/core/misc/announce.es6.js +++ b/web/core/misc/announce.es6.js @@ -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) { diff --git a/web/core/misc/autocomplete.es6.js b/web/core/misc/autocomplete.es6.js index 17993cf0ba34b0e28f65f35ae4a961a7ac00d0a2..65f6332af69738e6ca6e82fe83ee14b01f77da15 100644 --- a/web/core/misc/autocomplete.es6.js +++ b/web/core/misc/autocomplete.es6.js @@ -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', ); diff --git a/web/core/misc/normalize-fixes.css b/web/core/misc/normalize-fixes.css index 9df0fa0aed4ab774491a2415872c2633f6d7bd45..b400831192a84023f2941408eaef253bb61dcf87 100644 --- a/web/core/misc/normalize-fixes.css +++ b/web/core/misc/normalize-fixes.css @@ -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; } diff --git a/web/core/misc/states.es6.js b/web/core/misc/states.es6.js index dd2c315539703d5c2c5cb358ca007c91eba34527..811a5112d1746cbc3bd65608cf54e56f12dc0e2d 100644 --- a/web/core/misc/states.es6.js +++ b/web/core/misc/states.es6.js @@ -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; }, diff --git a/web/core/misc/states.js b/web/core/misc/states.js index fcdc37accd751c14d4f41b39c1b4379719fac995..7b451b07dec9c55526461602ac7860ae7738dee0 100644 --- a/web/core/misc/states.js +++ b/web/core/misc/states.js @@ -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]); }); } diff --git a/web/core/misc/tableheader.es6.js b/web/core/misc/tableheader.es6.js index 9e26be5fc223b0934cd1cd25721d0d37c7f0d3b9..c43d1dece3cfbe72588d1d030b24da2a0ec4953a 100644 --- a/web/core/misc/tableheader.es6.js +++ b/web/core/misc/tableheader.es6.js @@ -326,4 +326,4 @@ // Expose constructor in the public space. Drupal.TableHeader = TableHeader; -})(jQuery, Drupal, window.parent.Drupal.displace); +})(jQuery, Drupal, window.Drupal.displace); diff --git a/web/core/misc/tableheader.js b/web/core/misc/tableheader.js index 1fd60086db89dc1a0516c7d2c3944f725c9d9926..d5ad0a235e699fca2d6b4590c519ea4f7564fe6d 100644 --- a/web/core/misc/tableheader.js +++ b/web/core/misc/tableheader.js @@ -164,4 +164,4 @@ }); Drupal.TableHeader = TableHeader; -})(jQuery, Drupal, window.parent.Drupal.displace); \ No newline at end of file +})(jQuery, Drupal, window.Drupal.displace); \ No newline at end of file diff --git a/web/core/modules/action/src/Plugin/Action/GotoAction.php b/web/core/modules/action/src/Plugin/Action/GotoAction.php index 13a9a0d404d07ff65911954306a177f853262095..ce9a4e3f6eec9179c37b8be481aae40ff95638fe 100644 --- a/web/core/modules/action/src/Plugin/Action/GotoAction.php +++ b/web/core/modules/action/src/Plugin/Action/GotoAction.php @@ -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. diff --git a/web/core/modules/aggregator/src/ItemsImporter.php b/web/core/modules/aggregator/src/ItemsImporter.php index aa18d65c9afc946603185edc1991ffc72fa1fad4..156c7fb4823ddfe628dc0e0a2ae416043037f2fa 100644 --- a/web/core/modules/aggregator/src/ItemsImporter.php +++ b/web/core/modules/aggregator/src/ItemsImporter.php @@ -94,7 +94,7 @@ public function refresh(FeedInterface $feed) { 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 { diff --git a/web/core/modules/aggregator/src/Tests/AggregatorTestBase.php b/web/core/modules/aggregator/src/Tests/AggregatorTestBase.php index f42248975ae9f27eb4b3bc29f67033567575781b..00827a223c94e0faaa8dcb38e329dc4cea079345 100644 --- a/web/core/modules/aggregator/src/Tests/AggregatorTestBase.php +++ b/web/core/modules/aggregator/src/Tests/AggregatorTestBase.php @@ -70,9 +70,9 @@ public function createFeed($feed_url = NULL, array $edit = []) { $view_link = $this->xpath('//div[@class="messages"]//a[contains(@href, :href)]', [':href' => 'aggregator/sources/']); $this->assert(isset($view_link), 'The message area contains a link to a feed'); - $fid = db_query("SELECT fid FROM {aggregator_feed} WHERE title = :title AND url = :url", [':title' => $edit['title[0][value]'], ':url' => $edit['url[0][value]']])->fetchField(); - $this->assertTrue(!empty($fid), 'The feed found in database.'); - return Feed::load($fid); + $fids = \Drupal::entityQuery('aggregator_feed')->condition('title', $edit['title[0][value]'])->condition('url', $edit['url[0][value]'])->execute(); + $this->assertNotEmpty($fids, 'The feed found in database.'); + return Feed::load(array_values($fids)[0]); } /** @@ -179,10 +179,10 @@ public function updateFeedItems(FeedInterface $feed, $expected_count = NULL) { $this->clickLink('Update items'); // Ensure we have the right number of items. - $result = db_query('SELECT iid FROM {aggregator_item} WHERE fid = :fid', [':fid' => $feed->id()]); + $iids = \Drupal::entityQuery('aggregator_item')->condition('fid', $feed->id())->execute(); $feed->items = []; - foreach ($result as $item) { - $feed->items[] = $item->iid; + foreach ($iids as $iid) { + $feed->items[] = $iid; } if ($expected_count !== NULL) { @@ -211,11 +211,12 @@ public function deleteFeedItems(FeedInterface $feed) { * Expected number of feed items. */ public function updateAndDelete(FeedInterface $feed, $expected_count) { + $count_query = \Drupal::entityQuery('aggregator_item')->condition('fid', $feed->id())->count(); $this->updateFeedItems($feed, $expected_count); - $count = db_query('SELECT COUNT(*) FROM {aggregator_item} WHERE fid = :fid', [':fid' => $feed->id()])->fetchField(); + $count = $count_query->execute(); $this->assertTrue($count); $this->deleteFeedItems($feed); - $count = db_query('SELECT COUNT(*) FROM {aggregator_item} WHERE fid = :fid', [':fid' => $feed->id()])->fetchField(); + $count = $count_query->execute(); $this->assertTrue($count == 0); } @@ -231,7 +232,7 @@ public function updateAndDelete(FeedInterface $feed, $expected_count) { * TRUE if feed is unique. */ public function uniqueFeed($feed_name, $feed_url) { - $result = db_query("SELECT COUNT(*) FROM {aggregator_feed} WHERE title = :title AND url = :url", [':title' => $feed_name, ':url' => $feed_url])->fetchField(); + $result = \Drupal::entityQuery('aggregator_feed')->condition('title', $feed_name)->condition('url', $feed_url)->count()->execute(); return (1 == $result); } diff --git a/web/core/modules/aggregator/tests/src/Functional/AggregatorCronTest.php b/web/core/modules/aggregator/tests/src/Functional/AggregatorCronTest.php index bb7c90ae32f238f02fe266ee3270e064755eb64d..4a3ca0b07d9016e048a41b7d6de59c3a60bf66e6 100644 --- a/web/core/modules/aggregator/tests/src/Functional/AggregatorCronTest.php +++ b/web/core/modules/aggregator/tests/src/Functional/AggregatorCronTest.php @@ -20,31 +20,23 @@ public function testCron() { // Create feed and test basic updating on cron. $this->createSampleNodes(); $feed = $this->createFeed(); + $count_query = \Drupal::entityQuery('aggregator_item')->condition('fid', $feed->id())->count(); + $this->cronRun(); - $this->assertEqual(5, db_query('SELECT COUNT(*) FROM {aggregator_item} WHERE fid = :fid', [':fid' => $feed->id()])->fetchField()); + $this->assertEqual(5, $count_query->execute()); $this->deleteFeedItems($feed); - $this->assertEqual(0, db_query('SELECT COUNT(*) FROM {aggregator_item} WHERE fid = :fid', [':fid' => $feed->id()])->fetchField()); + $this->assertEqual(0, $count_query->execute()); $this->cronRun(); - $this->assertEqual(5, db_query('SELECT COUNT(*) FROM {aggregator_item} WHERE fid = :fid', [':fid' => $feed->id()])->fetchField()); + $this->assertEqual(5, $count_query->execute()); // Test feed locking when queued for update. $this->deleteFeedItems($feed); - db_update('aggregator_feed') - ->condition('fid', $feed->id()) - ->fields([ - 'queued' => REQUEST_TIME, - ]) - ->execute(); + $feed->setQueuedTime(REQUEST_TIME)->save(); $this->cronRun(); - $this->assertEqual(0, db_query('SELECT COUNT(*) FROM {aggregator_item} WHERE fid = :fid', [':fid' => $feed->id()])->fetchField()); - db_update('aggregator_feed') - ->condition('fid', $feed->id()) - ->fields([ - 'queued' => 0, - ]) - ->execute(); + $this->assertEqual(0, $count_query->execute()); + $feed->setQueuedTime(0)->save(); $this->cronRun(); - $this->assertEqual(5, db_query('SELECT COUNT(*) FROM {aggregator_item} WHERE fid = :fid', [':fid' => $feed->id()])->fetchField()); + $this->assertEqual(5, $count_query->execute()); } } diff --git a/web/core/modules/aggregator/tests/src/Functional/AggregatorTestBase.php b/web/core/modules/aggregator/tests/src/Functional/AggregatorTestBase.php index ddd98bb82f48fce4426fed8be7376a45e5abef8f..71c19031ac680682bcd22dd86b41cc9d965a093f 100644 --- a/web/core/modules/aggregator/tests/src/Functional/AggregatorTestBase.php +++ b/web/core/modules/aggregator/tests/src/Functional/AggregatorTestBase.php @@ -67,9 +67,9 @@ public function createFeed($feed_url = NULL, array $edit = []) { $view_link = $this->xpath('//div[@class="messages"]//a[contains(@href, :href)]', [':href' => 'aggregator/sources/']); $this->assert(isset($view_link), 'The message area contains a link to a feed'); - $fid = db_query("SELECT fid FROM {aggregator_feed} WHERE title = :title AND url = :url", [':title' => $edit['title[0][value]'], ':url' => $edit['url[0][value]']])->fetchField(); - $this->assertTrue(!empty($fid), 'The feed found in database.'); - return Feed::load($fid); + $fids = \Drupal::entityQuery('aggregator_feed')->condition('title', $edit['title[0][value]'])->condition('url', $edit['url[0][value]'])->execute(); + $this->assertNotEmpty($fids, 'The feed found in database.'); + return Feed::load(array_values($fids)[0]); } /** @@ -176,10 +176,10 @@ public function updateFeedItems(FeedInterface $feed, $expected_count = NULL) { $this->clickLink('Update items'); // Ensure we have the right number of items. - $result = db_query('SELECT iid FROM {aggregator_item} WHERE fid = :fid', [':fid' => $feed->id()]); + $iids = \Drupal::entityQuery('aggregator_item')->condition('fid', $feed->id())->execute(); $feed->items = []; - foreach ($result as $item) { - $feed->items[] = $item->iid; + foreach ($iids as $iid) { + $feed->items[] = $iid; } if ($expected_count !== NULL) { @@ -208,11 +208,12 @@ public function deleteFeedItems(FeedInterface $feed) { * Expected number of feed items. */ public function updateAndDelete(FeedInterface $feed, $expected_count) { + $count_query = \Drupal::entityQuery('aggregator_item')->condition('fid', $feed->id())->count(); $this->updateFeedItems($feed, $expected_count); - $count = db_query('SELECT COUNT(*) FROM {aggregator_item} WHERE fid = :fid', [':fid' => $feed->id()])->fetchField(); + $count = $count_query->execute(); $this->assertTrue($count); $this->deleteFeedItems($feed); - $count = db_query('SELECT COUNT(*) FROM {aggregator_item} WHERE fid = :fid', [':fid' => $feed->id()])->fetchField(); + $count = $count_query->execute(); $this->assertTrue($count == 0); } @@ -228,7 +229,7 @@ public function updateAndDelete(FeedInterface $feed, $expected_count) { * TRUE if feed is unique. */ public function uniqueFeed($feed_name, $feed_url) { - $result = db_query("SELECT COUNT(*) FROM {aggregator_feed} WHERE title = :title AND url = :url", [':title' => $feed_name, ':url' => $feed_url])->fetchField(); + $result = \Drupal::entityQuery('aggregator_feed')->condition('title', $feed_name)->condition('url', $feed_url)->count()->execute(); return (1 == $result); } diff --git a/web/core/modules/aggregator/tests/src/Functional/DeleteFeedTest.php b/web/core/modules/aggregator/tests/src/Functional/DeleteFeedTest.php index 557720658da2555fb0174c73ae88526b6dd97360..7f6a4087f750c803a88aa253fb0ac584860d981c 100644 --- a/web/core/modules/aggregator/tests/src/Functional/DeleteFeedTest.php +++ b/web/core/modules/aggregator/tests/src/Functional/DeleteFeedTest.php @@ -43,8 +43,8 @@ public function testDeleteFeed() { $this->assertResponse(404, 'Deleted feed source does not exist.'); // Check database for feed. - $result = db_query("SELECT COUNT(*) FROM {aggregator_feed} WHERE title = :title AND url = :url", [':title' => $feed1->label(), ':url' => $feed1->getUrl()])->fetchField(); - $this->assertFalse($result, 'Feed not found in database'); + $result = \Drupal::entityQuery('aggregator_feed')->condition('title', $feed1->label())->condition('url', $feed1->getUrl())->count()->execute(); + $this->assertEquals(0, $result, 'Feed not found in database'); } } diff --git a/web/core/modules/aggregator/tests/src/Functional/FeedParserTest.php b/web/core/modules/aggregator/tests/src/Functional/FeedParserTest.php index ecb2e50c76e587759d62324ed912974f8b733550..e340b27a9819cd5a01305c9761c0681fffce936e 100644 --- a/web/core/modules/aggregator/tests/src/Functional/FeedParserTest.php +++ b/web/core/modules/aggregator/tests/src/Functional/FeedParserTest.php @@ -4,6 +4,7 @@ use Drupal\Core\Url; use Drupal\aggregator\Entity\Feed; +use Drupal\aggregator\Entity\Item; /** * Tests the built-in feed parser with valid feed samples. @@ -57,16 +58,17 @@ public function testAtomSample() { $this->assertText('Atom-Powered Robots Run Amok'); $this->assertLinkByHref('http://example.org/2003/12/13/atom03'); $this->assertText('Some text.'); - $this->assertEqual('urn:uuid:1225c695-cfb8-4ebb-aaaa-80da344efa6a', db_query('SELECT guid FROM {aggregator_item} WHERE link = :link', [':link' => 'http://example.org/2003/12/13/atom03'])->fetchField(), 'Atom entry id element is parsed correctly.'); + $iids = \Drupal::entityQuery('aggregator_item')->condition('link', 'http://example.org/2003/12/13/atom03')->execute(); + $item = Item::load(array_values($iids)[0]); + $this->assertEqual('urn:uuid:1225c695-cfb8-4ebb-aaaa-80da344efa6a', $item->getGuid(), 'Atom entry id element is parsed correctly.'); // Check for second feed entry. $this->assertText('We tried to stop them, but we failed.'); $this->assertLinkByHref('http://example.org/2003/12/14/atom03'); $this->assertText('Some other text.'); - $db_guid = db_query('SELECT guid FROM {aggregator_item} WHERE link = :link', [ - ':link' => 'http://example.org/2003/12/14/atom03', - ])->fetchField(); - $this->assertEqual('urn:uuid:1225c695-cfb8-4ebb-bbbb-80da344efa6a', $db_guid, 'Atom entry id element is parsed correctly.'); + $iids = \Drupal::entityQuery('aggregator_item')->condition('link', 'http://example.org/2003/12/14/atom03')->execute(); + $item = Item::load(array_values($iids)[0]); + $this->assertEqual('urn:uuid:1225c695-cfb8-4ebb-bbbb-80da344efa6a', $item->getGuid(), 'Atom entry id element is parsed correctly.'); } /** diff --git a/web/core/modules/aggregator/tests/src/Functional/ImportOpmlTest.php b/web/core/modules/aggregator/tests/src/Functional/ImportOpmlTest.php index 2500b9ebb541b19670ee6d215e10531c61679b2e..f9099e0eb8210bf54962ea88cec23f5ecede372d 100644 --- a/web/core/modules/aggregator/tests/src/Functional/ImportOpmlTest.php +++ b/web/core/modules/aggregator/tests/src/Functional/ImportOpmlTest.php @@ -2,6 +2,8 @@ namespace Drupal\Tests\aggregator\Functional; +use Drupal\aggregator\Entity\Feed; + /** * Tests OPML import. * @@ -44,7 +46,8 @@ public function openImportForm() { * Submits form filled with invalid fields. */ public function validateImportFormFields() { - $before = db_query('SELECT COUNT(*) FROM {aggregator_feed}')->fetchField(); + $count_query = \Drupal::entityQuery('aggregator_feed')->count(); + $before = $count_query->execute(); $edit = []; $this->drupalPostForm('admin/config/services/aggregator/add/opml', $edit, t('Import')); @@ -62,7 +65,7 @@ public function validateImportFormFields() { $this->drupalPostForm('admin/config/services/aggregator/add/opml', $edit, t('Import')); $this->assertText(t('The URL invalidUrl://empty is not valid.'), 'Error if the URL is invalid.'); - $after = db_query('SELECT COUNT(*) FROM {aggregator_feed}')->fetchField(); + $after = $count_query->execute(); $this->assertEqual($before, $after, 'No feeds were added during the three last form submissions.'); } @@ -70,7 +73,8 @@ public function validateImportFormFields() { * Submits form with invalid, empty, and valid OPML files. */ protected function submitImportForm() { - $before = db_query('SELECT COUNT(*) FROM {aggregator_feed}')->fetchField(); + $count_query = \Drupal::entityQuery('aggregator_feed')->count(); + $before = $count_query->execute(); $form['files[upload]'] = $this->getInvalidOpml(); $this->drupalPostForm('admin/config/services/aggregator/add/opml', $form, t('Import')); @@ -80,10 +84,12 @@ protected function submitImportForm() { $this->drupalPostForm('admin/config/services/aggregator/add/opml', $edit, t('Import')); $this->assertText(t('No new feed has been added.'), 'Attempting to load empty OPML from remote URL.'); - $after = db_query('SELECT COUNT(*) FROM {aggregator_feed}')->fetchField(); + $after = $count_query->execute(); $this->assertEqual($before, $after, 'No feeds were added during the two last form submissions.'); - db_delete('aggregator_feed')->execute(); + foreach (Feed::loadMultiple() as $feed) { + $feed->delete(); + } $feeds[0] = $this->getFeedEditArray(); $feeds[1] = $this->getFeedEditArray(); @@ -96,15 +102,15 @@ protected function submitImportForm() { $this->assertRaw(t('A feed with the URL %url already exists.', ['%url' => $feeds[0]['url[0][value]']]), 'Verifying that a duplicate URL was identified'); $this->assertRaw(t('A feed named %title already exists.', ['%title' => $feeds[1]['title[0][value]']]), 'Verifying that a duplicate title was identified'); - $after = db_query('SELECT COUNT(*) FROM {aggregator_feed}')->fetchField(); + $after = $count_query->execute(); $this->assertEqual($after, 2, 'Verifying that two distinct feeds were added.'); - $feeds_from_db = db_query("SELECT title, url, refresh FROM {aggregator_feed}"); + $feed_entities = Feed::loadMultiple(); $refresh = TRUE; - foreach ($feeds_from_db as $feed) { - $title[$feed->url] = $feed->title; - $url[$feed->title] = $feed->url; - $refresh = $refresh && $feed->refresh == 900; + foreach ($feed_entities as $feed_entity) { + $title[$feed_entity->getUrl()] = $feed_entity->label(); + $url[$feed_entity->label()] = $feed_entity->getUrl(); + $refresh = $refresh && $feed_entity->getRefreshRate() == 900; } $this->assertEqual($title[$feeds[0]['url[0][value]']], $feeds[0]['title[0][value]'], 'First feed was added correctly.'); diff --git a/web/core/modules/aggregator/tests/src/Functional/UpdateFeedItemTest.php b/web/core/modules/aggregator/tests/src/Functional/UpdateFeedItemTest.php index a7ec0edd5a33777f3da44ee05ca08c5c6cdfbd95..fd2a742443cb2cbf9d4fb181e56c99729f78ae6e 100644 --- a/web/core/modules/aggregator/tests/src/Functional/UpdateFeedItemTest.php +++ b/web/core/modules/aggregator/tests/src/Functional/UpdateFeedItemTest.php @@ -3,6 +3,7 @@ namespace Drupal\Tests\aggregator\Functional; use Drupal\aggregator\Entity\Feed; +use Drupal\aggregator\Entity\Item; /** * Update feed items from a feed. @@ -43,26 +44,24 @@ public function testUpdateFeedItem() { $view_link = $this->xpath('//div[@class="messages"]//a[contains(@href, :href)]', [':href' => 'aggregator/sources/']); $this->assert(isset($view_link), 'The message area contains a link to a feed'); - $fid = db_query("SELECT fid FROM {aggregator_feed} WHERE url = :url", [':url' => $edit['url[0][value]']])->fetchField(); - $feed = Feed::load($fid); + $fids = \Drupal::entityQuery('aggregator_feed')->condition('url', $edit['url[0][value]'])->execute(); + $feed = Feed::load(array_values($fids)[0]); $feed->refreshItems(); - $before = db_query('SELECT timestamp FROM {aggregator_item} WHERE fid = :fid', [':fid' => $feed->id()])->fetchField(); + $iids = \Drupal::entityQuery('aggregator_item')->condition('fid', $feed->id())->execute(); + $before = Item::load(array_values($iids)[0])->getPostedTime(); // Sleep for 3 second. sleep(3); - db_update('aggregator_feed') - ->condition('fid', $feed->id()) - ->fields([ - 'checked' => 0, - 'hash' => '', - 'etag' => '', - 'modified' => 0, - ]) - ->execute(); + $feed + ->setLastCheckedTime(0) + ->setHash('') + ->setEtag('') + ->setLastModified(0) + ->save(); $feed->refreshItems(); - $after = db_query('SELECT timestamp FROM {aggregator_item} WHERE fid = :fid', [':fid' => $feed->id()])->fetchField(); + $after = Item::load(array_values($iids)[0])->getPostedTime(); $this->assertTrue($before === $after, format_string('Publish timestamp of feed item was not updated (@before === @after)', ['@before' => $before, '@after' => $after])); // Make sure updating items works even after uninstalling a module diff --git a/web/core/modules/ban/src/Plugin/migrate/destination/BlockedIp.php b/web/core/modules/ban/src/Plugin/migrate/destination/BlockedIp.php index 7c570bb793cc3779f7ee0cf70bf4b15ac4c7dfd4..203905f27ad996dc6b80cdf9c80ba0a8d8fb2627 100644 --- a/web/core/modules/ban/src/Plugin/migrate/destination/BlockedIp.php +++ b/web/core/modules/ban/src/Plugin/migrate/destination/BlockedIp.php @@ -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 diff --git a/web/core/modules/block/js/block.admin.es6.js b/web/core/modules/block/js/block.admin.es6.js index 197bc4beadd6460a4f9383152e68e76f2e613361..ff4d8eb20df24b7bb589b5473b55131371eebd4c 100644 --- a/web/core/modules/block/js/block.admin.es6.js +++ b/web/core/modules/block/js/block.admin.es6.js @@ -93,7 +93,8 @@ */ Drupal.behaviors.blockHighlightPlacement = { attach(context, settings) { - if (settings.blockPlacement) { + // Ensure that the block we are attempting to scroll to actually exists. + if (settings.blockPlacement && $('.js-block-placed').length) { $(context) .find('[data-drupal-selector="edit-blocks"]') .once('block-highlight') diff --git a/web/core/modules/block/js/block.admin.js b/web/core/modules/block/js/block.admin.js index 7cafed16ac64cf2108a40a7c33a39312cc0dadef..641f12d3f3a09c53b9d003657078e7ffc3750353 100644 --- a/web/core/modules/block/js/block.admin.js +++ b/web/core/modules/block/js/block.admin.js @@ -41,7 +41,7 @@ Drupal.behaviors.blockHighlightPlacement = { attach: function attach(context, settings) { - if (settings.blockPlacement) { + if (settings.blockPlacement && $('.js-block-placed').length) { $(context).find('[data-drupal-selector="edit-blocks"]').once('block-highlight').each(function () { var $container = $(this); diff --git a/web/core/modules/block/src/BlockListBuilder.php b/web/core/modules/block/src/BlockListBuilder.php index c1ccc504dbcacc811770079ef20b7c60ed26e105..3884d27f21ea79f86aa4a4d8ff0d5bdbf1c151b4 100644 --- a/web/core/modules/block/src/BlockListBuilder.php +++ b/web/core/modules/block/src/BlockListBuilder.php @@ -193,6 +193,9 @@ protected function buildBlocksForm() { if ($this->request->query->has('block-placement')) { $placement = $this->request->query->get('block-placement'); $form['#attached']['drupalSettings']['blockPlacement'] = $placement; + // Remove the block placement from the current request so that it is not + // passed on to any redirect destinations. + $this->request->query->remove('block-placement'); } // Loop over each region and build blocks. @@ -378,9 +381,6 @@ public function submitForm(array &$form, FormStateInterface $form_state) { $entity->save(); } $this->messenger->addStatus($this->t('The block settings have been updated.')); - - // Remove any previously set block placement. - $this->request->query->remove('block-placement'); } /** diff --git a/web/core/modules/block/src/Plugin/migrate/source/d7/BlockTranslation.php b/web/core/modules/block/src/Plugin/migrate/source/d7/BlockTranslation.php new file mode 100644 index 0000000000000000000000000000000000000000..acf9e2b7c8ae544b9ef8fc2e230ea66ccd8c0515 --- /dev/null +++ b/web/core/modules/block/src/Plugin/migrate/source/d7/BlockTranslation.php @@ -0,0 +1,99 @@ +<?php + +namespace Drupal\block\Plugin\migrate\source\d7; + +use Drupal\block\Plugin\migrate\source\Block; + +/** + * Gets i18n block data from source database. + * + * @MigrateSource( + * id = "d7_block_translation", + * source_module = "i18n_block" + * ) + */ +class BlockTranslation extends Block { + + /** + * {@inheritdoc} + */ + public function query() { + // Let the parent set the block table to use, but do not use the parent + // query. Instead build a query so can use an inner join to the selected + // block table. + parent::query(); + $query = $this->select('i18n_string', 'i18n') + ->fields('i18n') + ->fields('b', [ + 'bid', + 'module', + 'delta', + 'theme', + 'status', + 'weight', + 'region', + 'custom', + 'visibility', + 'pages', + 'title', + 'cache', + 'i18n_mode', + ]) + ->fields('lt', [ + 'lid', + 'translation', + 'language', + 'plid', + 'plural', + 'i18n_status', + ]) + ->condition('i18n_mode', 1); + $query->leftjoin($this->blockTable, 'b', ('b.delta = i18n.objectid')); + $query->leftjoin('locales_target', 'lt', 'lt.lid = i18n.lid'); + return $query; + } + + /** + * {@inheritdoc} + */ + public function fields() { + return [ + 'bid' => $this->t('The block numeric identifier.'), + 'module' => $this->t('The module providing the block.'), + 'delta' => $this->t("The block's delta."), + 'theme' => $this->t('Which theme the block is placed in.'), + 'status' => $this->t('Block enabled status'), + 'weight' => $this->t('Block weight within region'), + 'region' => $this->t('Theme region within which the block is set'), + 'visibility' => $this->t('Visibility'), + 'pages' => $this->t('Pages list.'), + 'title' => $this->t('Block title.'), + 'cache' => $this->t('Cache rule.'), + 'i18n_mode' => $this->t('Multilingual mode'), + 'lid' => $this->t('Language string ID'), + 'textgroup' => $this->t('A module defined group of translations'), + 'context' => $this->t('Full string ID for quick search: type:objectid:property.'), + 'objectid' => $this->t('Object ID'), + 'type' => $this->t('Object type for this string'), + 'property' => $this->t('Object property for this string'), + 'objectindex' => $this->t('Integer value of Object ID'), + 'format' => $this->t('The {filter_format}.format of the string'), + 'translation' => $this->t('Translation'), + 'language' => $this->t('Language code'), + 'plid' => $this->t('Parent lid'), + 'plural' => $this->t('Plural index number'), + 'i18n_status' => $this->t('Translation needs update'), + ]; + } + + /** + * {@inheritdoc} + */ + public function getIds() { + $ids['delta']['type'] = 'string'; + $ids['delta']['alias'] = 'b'; + $ids['language']['type'] = 'string'; + return $ids; + } + +} diff --git a/web/core/modules/block/tests/modules/block_test/src/Plugin/Block/TestContextAwareNoValidContextOptionsBlock.php b/web/core/modules/block/tests/modules/block_test/src/Plugin/Block/TestContextAwareNoValidContextOptionsBlock.php new file mode 100644 index 0000000000000000000000000000000000000000..234bf9a3015d763b17699ba432a0bd51c0f47b2d --- /dev/null +++ b/web/core/modules/block/tests/modules/block_test/src/Plugin/Block/TestContextAwareNoValidContextOptionsBlock.php @@ -0,0 +1,29 @@ +<?php + +namespace Drupal\block_test\Plugin\Block; + +use Drupal\Core\Block\BlockBase; + +/** + * Provides a context-aware block that uses a not-passed, non-required context. + * + * @Block( + * id = "test_context_aware_no_valid_context_options", + * admin_label = @Translation("Test context-aware block - no valid context options"), + * context_definitions = { + * "email" = @ContextDefinition("email", required = FALSE) + * } + * ) + */ +class TestContextAwareNoValidContextOptionsBlock extends BlockBase { + + /** + * {@inheritdoc} + */ + public function build() { + return [ + '#markup' => 'Rendered block with no valid context options', + ]; + } + +} diff --git a/web/core/modules/block/tests/src/Functional/BlockUiTest.php b/web/core/modules/block/tests/src/Functional/BlockUiTest.php index e6c187544ed902c5e534d35eb272cc6b32604f48..a2b53e8f59f7b29805f8e9d8fbfcd6adbab384bb 100644 --- a/web/core/modules/block/tests/src/Functional/BlockUiTest.php +++ b/web/core/modules/block/tests/src/Functional/BlockUiTest.php @@ -3,6 +3,8 @@ namespace Drupal\Tests\block\Functional; use Drupal\Component\Utility\Html; +use Drupal\language\Entity\ConfigurableLanguage; +use Drupal\language\Plugin\LanguageNegotiation\LanguageNegotiationUrl; use Drupal\Tests\BrowserTestBase; /** @@ -239,6 +241,13 @@ public function testContextAwareBlocks() { $this->assertText('User context found.'); $this->assertRaw($expected_text); + // Test context mapping form element is not visible if there are no valid + // context options for the block (the test_context_aware_no_valid_context_options + // block has one context defined which is not available for it on the + // Block Layout interface). + $this->drupalGet('admin/structure/block/add/test_context_aware_no_valid_context_options/classy'); + $this->assertSession()->fieldNotExists('edit-settings-context-mapping-email'); + // Test context mapping allows empty selection for optional contexts. $this->drupalGet('admin/structure/block/manage/testcontextawareblock'); $edit = [ @@ -281,6 +290,24 @@ public function testMachineNameSuggestion() { * Tests the block placement indicator. */ public function testBlockPlacementIndicator() { + // Test the block placement indicator with using the domain as URL language + // indicator. This causes destination query parameters to be absolute URLs. + \Drupal::service('module_installer')->install(['language', 'locale']); + $this->container = \Drupal::getContainer(); + ConfigurableLanguage::createFromLangcode('it')->save(); + $config = $this->config('language.types'); + $config->set('negotiation.language_interface.enabled', [ + LanguageNegotiationUrl::METHOD_ID => -10, + ]); + $config->save(); + $config = $this->config('language.negotiation'); + $config->set('url.source', LanguageNegotiationUrl::CONFIG_DOMAIN); + $config->set('url.domains', [ + 'en' => \Drupal::request()->getHost(), + 'it' => 'it.example.com', + ]); + $config->save(); + // Select the 'Powered by Drupal' block to be placed. $block = []; $block['id'] = strtolower($this->randomMachineName()); @@ -289,11 +316,30 @@ public function testBlockPlacementIndicator() { // After adding a block, it will indicate which block was just added. $this->drupalPostForm('admin/structure/block/add/system_powered_by_block', $block, t('Save block')); - $this->assertUrl('admin/structure/block/list/classy?block-placement=' . Html::getClass($block['id'])); + $this->assertSession()->addressEquals('admin/structure/block/list/classy?block-placement=' . Html::getClass($block['id'])); - // Resaving the block page will remove the block indicator. + // Resaving the block page will remove the block placement indicator. $this->drupalPostForm(NULL, [], t('Save blocks')); - $this->assertUrl('admin/structure/block/list/classy'); + $this->assertSession()->addressEquals('admin/structure/block/list/classy'); + + // Place another block and test the remove functionality works with the + // block placement indicator. Click the first 'Place block' link to bring up + // the list of blocks to place in the first available region. + $this->clickLink('Place block'); + // Select the first available block. + $this->clickLink('Place block'); + $block = []; + $block['id'] = strtolower($this->randomMachineName()); + $block['theme'] = 'classy'; + $this->submitForm([], 'Save block'); + $this->assertSession()->addressEquals('admin/structure/block/list/classy?block-placement=' . Html::getClass($block['id'])); + + // Removing a block will remove the block placement indicator. + $this->clickLink('Remove'); + $this->submitForm([], 'Remove'); + // @todo https://www.drupal.org/project/drupal/issues/2980527 this should be + // 'admin/structure/block/list/classy' but there is a bug. + $this->assertSession()->addressEquals('admin/structure/block'); } /** diff --git a/web/core/modules/block/tests/src/Kernel/Migrate/d7/MigrateBlockContentTranslationTest.php b/web/core/modules/block/tests/src/Kernel/Migrate/d7/MigrateBlockContentTranslationTest.php new file mode 100644 index 0000000000000000000000000000000000000000..0d082a8e06f255004e48760bd4bbd50d4c3d730f --- /dev/null +++ b/web/core/modules/block/tests/src/Kernel/Migrate/d7/MigrateBlockContentTranslationTest.php @@ -0,0 +1,69 @@ +<?php + +namespace Drupal\Tests\block\Kernel\Migrate\d7; + +use Drupal\Tests\migrate_drupal\Kernel\d7\MigrateDrupal7TestBase; + +/** + * Tests migration of i18n block translations. + * + * @group migrate_drupal_7 + */ +class MigrateBlockContentTranslationTest extends MigrateDrupal7TestBase { + + /** + * {@inheritdoc} + */ + public static $modules = [ + 'node', + 'text', + 'aggregator', + 'book', + 'block', + 'comment', + 'forum', + 'views', + 'block_content', + 'config_translation', + 'content_translation', + 'language', + 'statistics', + 'taxonomy', + // Required for translation migrations. + 'migrate_drupal_multilingual', + ]; + + /** + * {@inheritdoc} + */ + protected function setUp() { + parent::setUp(); + $this->installConfig(['block']); + $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_user_role', + 'd7_block', + 'd7_block_translation', + ]); + block_rebuild(); + } + + /** + * Tests the migration of block title translation. + */ + public function testBlockContentTranslation() { + /** @var \Drupal\language\ConfigurableLanguageManagerInterface $language_manager */ + $language_manager = $this->container->get('language_manager'); + + $config = $language_manager->getLanguageConfigOverride('fr', 'block.block.bartik_user_login'); + $this->assertSame('fr - User login title', $config->get('settings.label')); + } + +} diff --git a/web/core/modules/block/tests/src/Kernel/Migrate/d7/MigrateBlockTest.php b/web/core/modules/block/tests/src/Kernel/Migrate/d7/MigrateBlockTest.php index 6f07dc9c21e7bc38f865e94d2b2ba48574f2e9ff..d56b9ed19625ff0173bbbf200a93abd46cbdd07e 100644 --- a/web/core/modules/block/tests/src/Kernel/Migrate/d7/MigrateBlockTest.php +++ b/web/core/modules/block/tests/src/Kernel/Migrate/d7/MigrateBlockTest.php @@ -112,10 +112,10 @@ public function assertEntity($id, $plugin_id, array $roles, $pages, $region, $th public function testBlockMigration() { $this->assertEntity('bartik_system_main', 'system_main_block', [], '', 'content', 'bartik', 0, '', '0'); $this->assertEntity('bartik_search_form', 'search_form_block', [], '', 'sidebar_first', 'bartik', -1, '', '0'); - $this->assertEntity('bartik_user_login', 'user_login_block', [], '', 'sidebar_first', 'bartik', 0, '', '0'); + $this->assertEntity('bartik_user_login', 'user_login_block', [], '', 'sidebar_first', 'bartik', 0, 'User login title', 'visible'); $this->assertEntity('bartik_system_powered_by', 'system_powered_by_block', [], '', 'footer_fifth', 'bartik', 10, '', '0'); $this->assertEntity('seven_system_main', 'system_main_block', [], '', 'content', 'seven', 0, '', '0'); - $this->assertEntity('seven_user_login', 'user_login_block', [], '', 'content', 'seven', 10, '', '0'); + $this->assertEntity('seven_user_login', 'user_login_block', [], '', 'content', 'seven', 10, 'User login title', 'visible'); // The d7_custom_block migration should have migrated a block containing a // mildly amusing limerick. We'll need its UUID to determine diff --git a/web/core/modules/block/tests/src/Kernel/Plugin/migrate/source/d7/BlockTranslationTest.php b/web/core/modules/block/tests/src/Kernel/Plugin/migrate/source/d7/BlockTranslationTest.php new file mode 100644 index 0000000000000000000000000000000000000000..01b2dced662c266ef0b5b141da6497aaf2cbc616 --- /dev/null +++ b/web/core/modules/block/tests/src/Kernel/Plugin/migrate/source/d7/BlockTranslationTest.php @@ -0,0 +1,147 @@ +<?php + +namespace Drupal\Tests\block\Kernel\Plugin\migrate\source\d7; + +use Drupal\Tests\migrate\Kernel\MigrateSqlSourceTestBase; + +/** + * Tests i18n block source plugin. + * + * @covers \Drupal\block\Plugin\migrate\source\d7\BlockTranslation + * + * @group content_translation + */ +class BlockTranslationTest extends MigrateSqlSourceTestBase { + + /** + * {@inheritdoc} + */ + public static $modules = ['block', 'migrate_drupal']; + + /** + * {@inheritdoc} + */ + public function providerSource() { + + // The source data. + $tests[0]['source_data']['block'] = [ + [ + 'bid' => 1, + 'module' => 'system', + 'delta' => 'main', + 'theme' => 'bartik', + 'status' => 1, + 'weight' => 0, + 'region' => 'content', + 'custom' => '0', + 'visibility' => 0, + 'pages' => '', + 'title' => '', + 'cache' => -1, + 'i18n_mode' => 0, + ], + [ + 'bid' => 2, + 'module' => 'system', + 'delta' => 'navigation', + 'theme' => 'bartik', + 'status' => 1, + 'weight' => 0, + 'region' => 'sidebar_first', + 'custom' => '0', + 'visibility' => 0, + 'pages' => '', + 'title' => 'Navigation', + 'cache' => -1, + 'i18n_mode' => 1, + ], + ]; + $tests[0]['source_data']['block_role'] = [ + [ + 'module' => 'block', + 'delta' => 1, + 'rid' => 2, + ], + [ + 'module' => 'block', + 'delta' => 2, + 'rid' => 2, + ], + [ + 'module' => 'block', + 'delta' => 2, + 'rid' => 100, + ], + ]; + $tests[0]['source_data']['i18n_string'] = [ + [ + 'lid' => 1, + 'textgroup' => 'block', + 'context' => '1', + 'objectid' => 'navigation', + 'type' => 'system', + 'property' => 'title', + 'objectindex' => 0, + 'format' => '', + ], + ]; + + $tests[0]['source_data']['locales_target'] = [ + [ + 'lid' => 1, + 'translation' => 'fr - Navigation', + 'language' => 'fr', + 'plid' => 0, + 'plural' => 0, + 'i18n_status' => 0, + ], + ]; + $tests[0]['source_data']['role'] = [ + [ + 'rid' => 2, + 'name' => 'authenticated user', + ], + ]; + $tests[0]['source_data']['system'] = [ + [ + 'filename' => 'modules/system/system.module', + 'name' => 'system', + 'type' => 'module', + 'owner' => '', + 'status' => '1', + 'throttle' => '0', + 'bootstrap' => '0', + 'schema_version' => '7055', + 'weight' => '0', + 'info' => 'a:0:{}', + ], + ]; + // The expected results. + $tests[0]['expected_data'] = [ + [ + 'bid' => 2, + 'module' => 'system', + 'delta' => 'navigation', + 'theme' => 'bartik', + 'status' => 1, + 'weight' => 0, + 'region' => 'sidebar_first', + 'custom' => '0', + 'visibility' => 0, + 'pages' => '', + 'title' => 'Navigation', + 'cache' => -1, + 'i18n_mode' => 1, + 'lid' => 1, + 'translation' => 'fr - Navigation', + 'language' => 'fr', + 'plid' => 0, + 'plural' => 0, + 'i18n_status' => 0, + ], + ]; + + return $tests; + } + +} diff --git a/web/core/modules/block_content/src/Plugin/migrate/source/d6/BoxTranslation.php b/web/core/modules/block_content/src/Plugin/migrate/source/d6/BoxTranslation.php index d5dffd961adcf537f3b4a0c91931da6770d4dd0c..23cf11800225b4f780421ea12701c5c1e29b6aa2 100644 --- a/web/core/modules/block_content/src/Plugin/migrate/source/d6/BoxTranslation.php +++ b/web/core/modules/block_content/src/Plugin/migrate/source/d6/BoxTranslation.php @@ -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 @@ * 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'; } diff --git a/web/core/modules/block_content/src/Plugin/migrate/source/d7/BlockCustomTranslation.php b/web/core/modules/block_content/src/Plugin/migrate/source/d7/BlockCustomTranslation.php new file mode 100644 index 0000000000000000000000000000000000000000..6115e12c619e69d03c1baf195c7b90e50f7e85cd --- /dev/null +++ b/web/core/modules/block_content/src/Plugin/migrate/source/d7/BlockCustomTranslation.php @@ -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; + } + +} diff --git a/web/core/modules/block_content/tests/src/Kernel/BlockContentAccessHandlerTest.php b/web/core/modules/block_content/tests/src/Kernel/BlockContentAccessHandlerTest.php index 64b524d80b89273049ca86fed288b9b3d84bef62..1767e363b8b6ddf71061b067f66b84fd09c3ef93 100644 --- a/web/core/modules/block_content/tests/src/Kernel/BlockContentAccessHandlerTest.php +++ b/web/core/modules/block_content/tests/src/Kernel/BlockContentAccessHandlerTest.php @@ -293,8 +293,8 @@ public function providerTestAccess() { 'forbidden', ], ]; - return $cases; } + return $cases; } } diff --git a/web/core/modules/block_content/tests/src/Kernel/Migrate/d7/MigrateCustomBlockContentTranslationTest.php b/web/core/modules/block_content/tests/src/Kernel/Migrate/d7/MigrateCustomBlockContentTranslationTest.php new file mode 100644 index 0000000000000000000000000000000000000000..092eb0a853d44fcda40ae3ebbcb3c4c1fa4b9a97 --- /dev/null +++ b/web/core/modules/block_content/tests/src/Kernel/Migrate/d7/MigrateCustomBlockContentTranslationTest.php @@ -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); + } + +} diff --git a/web/core/modules/block_content/tests/src/Kernel/Plugin/migrate/source/d7/BlockCustomTranslationTest.php b/web/core/modules/block_content/tests/src/Kernel/Plugin/migrate/source/d7/BlockCustomTranslationTest.php new file mode 100644 index 0000000000000000000000000000000000000000..c5bffaf0ebc7b8dc58815f98642dadce659ad660 --- /dev/null +++ b/web/core/modules/block_content/tests/src/Kernel/Plugin/migrate/source/d7/BlockCustomTranslationTest.php @@ -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; + } + +} diff --git a/web/core/modules/book/tests/src/Functional/BookTest.php b/web/core/modules/book/tests/src/Functional/BookTest.php index d02dfd50d9c3f1fddd4deca01beda884b5726141..6fe03dec877da42f0dc6856aa25078d4c0e67744 100644 --- a/web/core/modules/book/tests/src/Functional/BookTest.php +++ b/web/core/modules/book/tests/src/Functional/BookTest.php @@ -177,7 +177,7 @@ public function testBook() { $this->checkBookNode($other_book, [$node], FALSE, FALSE, $node, []); $this->checkBookNode($node, NULL, $other_book, $other_book, FALSE, [$other_book]); - // Test that we can save a book programatically. + // Test that we can save a book programmatically. $this->drupalLogin($this->bookAuthor); $book = $this->createBookNode('new'); $book->save(); @@ -282,7 +282,7 @@ public function testGetTableOfContents() { $nodes[$child] = $this->createBookNode($book->id(), $nodes[$parent]->id()); } $this->drupalGet($nodes[0]->toUrl('edit-form')); - // Snice Node 0 has children 2 levels deep, nodes 10 and 11 should not + // Since Node 0 has children 2 levels deep, nodes 10 and 11 should not // appear in the selector. $this->assertNoOption('edit-book-pid', $nodes[10]->id()); $this->assertNoOption('edit-book-pid', $nodes[11]->id()); diff --git a/web/core/modules/ckeditor/js/ckeditor.es6.js b/web/core/modules/ckeditor/js/ckeditor.es6.js index 2ce094913d05c1692a8cf79f24a1c19692f4b722..7f725dbabd02740772d6a86e747f0632dbbac5dc 100644 --- a/web/core/modules/ckeditor/js/ckeditor.es6.js +++ b/web/core/modules/ckeditor/js/ckeditor.es6.js @@ -68,7 +68,7 @@ * Reacts on a change in the editor element. * * @param {HTMLElement} element - * The element where the change occured. + * The element where the change occurred. * @param {function} callback * Callback called with the value of the editor. * diff --git a/web/core/modules/ckeditor/src/Annotation/CKEditorPlugin.php b/web/core/modules/ckeditor/src/Annotation/CKEditorPlugin.php index 3b4c2c58445462e1ffe99c84a662fb7eb7949e11..155d5dd496108e8a5fb123d499860fcf147b3b1a 100644 --- a/web/core/modules/ckeditor/src/Annotation/CKEditorPlugin.php +++ b/web/core/modules/ckeditor/src/Annotation/CKEditorPlugin.php @@ -24,6 +24,10 @@ class CKEditorPlugin extends Plugin { /** * The plugin ID. * + * This MUST match the name of the CKEditor plugin itself (written in + * JavaScript). Otherwise CKEditor will throw JavaScript errors when it runs, + * because it fails to load this CKEditor plugin. + * * @var string */ public $id; diff --git a/web/core/modules/ckeditor/tests/modules/src/Plugin/CKEditorPlugin/LlamaContextualAndButton.php b/web/core/modules/ckeditor/tests/modules/src/Plugin/CKEditorPlugin/LlamaContextualAndButton.php index 2894fc905f367c40f2de92d18d352ccb7da29873..450a3966c110e24d0eccda98e3163f78f1b6d57b 100644 --- a/web/core/modules/ckeditor/tests/modules/src/Plugin/CKEditorPlugin/LlamaContextualAndButton.php +++ b/web/core/modules/ckeditor/tests/modules/src/Plugin/CKEditorPlugin/LlamaContextualAndButton.php @@ -9,7 +9,7 @@ use Drupal\editor\Entity\Editor; /** - * Defines a "LlamaContextualAndbutton" plugin, with a contextually OR toolbar + * Defines a "LlamaContextualAndButton" plugin, with a contextually OR toolbar * builder-enabled "llama" feature. * * @CKEditorPlugin( diff --git a/web/core/modules/ckeditor/tests/src/FunctionalJavascript/CKEditorIntegrationTest.php b/web/core/modules/ckeditor/tests/src/FunctionalJavascript/CKEditorIntegrationTest.php index a9ee69719b54a0f046062e81c6a9902a3d38b63e..9e7b8df53a6ee2d22d166da6ff8175f62a7e922f 100644 --- a/web/core/modules/ckeditor/tests/src/FunctionalJavascript/CKEditorIntegrationTest.php +++ b/web/core/modules/ckeditor/tests/src/FunctionalJavascript/CKEditorIntegrationTest.php @@ -24,6 +24,13 @@ class CKEditorIntegrationTest extends WebDriverTestBase { */ protected $account; + /** + * The FilterFormat config entity used for testing. + * + * @var \Drupal\filter\FilterFormatInterface + */ + protected $filterFormat; + /** * {@inheritdoc} */ @@ -36,12 +43,12 @@ protected function setUp() { parent::setUp(); // Create a text format and associate CKEditor. - $filtered_html_format = FilterFormat::create([ + $this->filterFormat = FilterFormat::create([ 'format' => 'filtered_html', 'name' => 'Filtered HTML', 'weight' => 0, ]); - $filtered_html_format->save(); + $this->filterFormat->save(); Editor::create([ 'format' => 'filtered_html', @@ -119,4 +126,55 @@ public function testFragmentLink() { self::assertEquals($before_url, $after_url, 'History back works.'); } + /** + * Tests if the Image button appears and works as expected. + */ + public function testDrupalImageDialog() { + $session = $this->getSession(); + $web_assert = $this->assertSession(); + + $this->drupalGet('node/add/page'); + $session->getPage(); + + // Asserts the Image button is present in the toolbar. + $web_assert->elementExists('css', '#cke_edit-body-0-value .cke_button__drupalimage'); + + // Asserts the image dialog opens when clicking the Image button. + $this->click('.cke_button__drupalimage'); + $this->assertNotEmpty($web_assert->waitForElement('css', '.ui-dialog')); + + $web_assert->elementContains('css', '.ui-dialog .ui-dialog-titlebar', 'Insert Image'); + } + + /** + * Tests if the Drupal Image Caption plugin appears and works as expected. + */ + public function testDrupalImageCaptionDialog() { + $web_assert = $this->assertSession(); + + // Disable the caption filter. + $this->filterFormat->setFilterConfig('filter_caption', [ + 'status' => FALSE, + ]); + $this->filterFormat->save(); + + // If the caption filter is disabled, its checkbox should be absent. + $this->drupalGet('node/add/page'); + $this->click('.cke_button__drupalimage'); + $this->assertNotEmpty($web_assert->waitForElement('css', '.ui-dialog')); + $web_assert->elementNotExists('css', '.ui-dialog input[name="attributes[hasCaption]"]'); + + // Enable the caption filter again. + $this->filterFormat->setFilterConfig('filter_caption', [ + 'status' => TRUE, + ]); + $this->filterFormat->save(); + + // If the caption filter is enabled, its checkbox should be present. + $this->drupalGet('node/add/page'); + $this->click('.cke_button__drupalimage'); + $this->assertNotEmpty($web_assert->waitForElement('css', '.ui-dialog')); + $web_assert->elementExists('css', '.ui-dialog input[name="attributes[hasCaption]"]'); + } + } diff --git a/web/core/modules/comment/comment.module b/web/core/modules/comment/comment.module index b9d786e35a1c9bffacc094f436c71cdc806209ed..78f857057df6f61d6a68ae3df376f512eb3c02ea 100644 --- a/web/core/modules/comment/comment.module +++ b/web/core/modules/comment/comment.module @@ -25,6 +25,7 @@ use Drupal\field\FieldStorageConfigInterface; use Drupal\node\NodeInterface; use Drupal\user\RoleInterface; +use Drupal\user\UserInterface; /** * Anonymous posters cannot enter their contact information. @@ -518,7 +519,7 @@ function comment_node_search_result(EntityInterface $node) { /** * Implements hook_user_cancel(). */ -function comment_user_cancel($edit, $account, $method) { +function comment_user_cancel($edit, UserInterface $account, $method) { switch ($method) { case 'user_cancel_block_unpublish': $comments = entity_load_multiple_by_properties('comment', ['uid' => $account->id()]); diff --git a/web/core/modules/comment/migrations/d6_comment.yml b/web/core/modules/comment/migrations/d6_comment.yml index 32978de82eb7ba57bddc2201f29835e0bc3be1d8..278e6ee21ab41513ed30ab6a5c256447870d1d5d 100644 --- a/web/core/modules/comment/migrations/d6_comment.yml +++ b/web/core/modules/comment/migrations/d6_comment.yml @@ -16,7 +16,16 @@ process: plugin: migration_lookup migration: d6_comment source: pid - entity_id: nid + entity_id: + - + plugin: migration_lookup + migration: + - d6_node + - d6_node_translation + source: nid + - + plugin: skip_on_empty + method: row entity_type: 'constants/entity_type' comment_type: - @@ -26,6 +35,7 @@ process: - plugin: skip_on_empty method: row + langcode: language field_name: '@comment_type' subject: subject uid: uid @@ -52,3 +62,5 @@ migration_dependencies: - d6_comment_entity_form_display - d6_user - d6_filter_format + optional: + - d6_node_translation diff --git a/web/core/modules/comment/migrations/d7_comment.yml b/web/core/modules/comment/migrations/d7_comment.yml index 4bcafd8e5d958bf79c100b140b9a4ad94a75d1ed..29c439e98ae9608f024155a718321c99d3637967 100644 --- a/web/core/modules/comment/migrations/d7_comment.yml +++ b/web/core/modules/comment/migrations/d7_comment.yml @@ -17,7 +17,16 @@ process: plugin: migration_lookup migration: d7_comment source: pid - entity_id: nid + entity_id: + - + plugin: migration_lookup + migration: + - d7_node + - d7_node_translation + source: nid + - + plugin: skip_on_empty + method: row entity_type: 'constants/entity_type' comment_type: - @@ -27,6 +36,7 @@ process: - plugin: skip_on_empty method: row + langcode: language field_name: '@comment_type' subject: subject uid: uid @@ -45,3 +55,5 @@ migration_dependencies: required: - d7_node - d7_comment_type + optional: + - d7_node_translation diff --git a/web/core/modules/comment/src/CommentFieldItemList.php b/web/core/modules/comment/src/CommentFieldItemList.php index 7a4cdad4e6d82ef9d0e7cda048dd13a76684163e..73215e86981615aa6cf6d395cee3de263ce56be3 100644 --- a/web/core/modules/comment/src/CommentFieldItemList.php +++ b/web/core/modules/comment/src/CommentFieldItemList.php @@ -50,7 +50,7 @@ public function access($operation = 'view', AccountInterface $account = NULL, $r return $return_as_object ? $result : $result->isAllowed(); } if ($operation === 'view') { - // Only users with either post comments or access comments permisison can + // Only users with "post comments" or "access comments" permission can // view the field value. The formatter, // Drupal\comment\Plugin\Field\FieldFormatter\CommentDefaultFormatter, // takes care of showing the thread and form based on individual diff --git a/web/core/modules/comment/src/CommentInterface.php b/web/core/modules/comment/src/CommentInterface.php index e80e5edfdcd1b83a58a98dd2390019d65f4cfefa..55405629ce570b63bd657300a7146006ae7cb7db 100644 --- a/web/core/modules/comment/src/CommentInterface.php +++ b/web/core/modules/comment/src/CommentInterface.php @@ -56,8 +56,9 @@ public function getParentComment(); /** * Returns the entity to which the comment is attached. * - * @return \Drupal\Core\Entity\FieldableEntityInterface - * The entity on which the comment is attached. + * @return \Drupal\Core\Entity\FieldableEntityInterface|null + * The entity on which the comment is attached or NULL if the comment is an + * orphan. */ public function getCommentedEntity(); diff --git a/web/core/modules/comment/src/Plugin/migrate/source/d6/Comment.php b/web/core/modules/comment/src/Plugin/migrate/source/d6/Comment.php index b2511c59a53e9da92e4a2f9e2b58d87e4e61a5fa..5671d4f15665a95fab2b5c4be2341abfe763a6ea 100644 --- a/web/core/modules/comment/src/Plugin/migrate/source/d6/Comment.php +++ b/web/core/modules/comment/src/Plugin/migrate/source/d6/Comment.php @@ -25,7 +25,7 @@ public function query() { 'mail', 'homepage', 'format', ]); $query->innerJoin('node', 'n', 'c.nid = n.nid'); - $query->fields('n', ['type']); + $query->fields('n', ['type', 'language']); $query->orderBy('c.timestamp'); return $query; } @@ -61,6 +61,13 @@ protected function prepareComment(Row $row) { // In D6, status=0 means published, while in D8 means the opposite. // See https://www.drupal.org/node/237636. $row->setSourceProperty('status', !$row->getSourceProperty('status')); + + // If node did not have a language, use site default language as a fallback. + if (!$row->getSourceProperty('language')) { + $language_default = $this->variableGet('language_default', NULL); + $language = $language_default ? $language_default->language : 'en'; + $row->setSourceProperty('language', $language); + } return $row; } @@ -84,6 +91,7 @@ public function fields() { 'mail' => $this->t("The comment author's email address from the comment form, if user is anonymous, and the 'Anonymous users may/must leave their contact information' setting is turned on."), 'homepage' => $this->t("The comment author's home page address from the comment form, if user is anonymous, and the 'Anonymous users may/must leave their contact information' setting is turned on."), 'type' => $this->t("The {node}.type to which this comment is a reply."), + 'language' => $this->t("The {node}.language to which this comment is a reply. Site default language is used as a fallback if node does not have a language."), ]; } diff --git a/web/core/modules/comment/src/Plugin/migrate/source/d7/Comment.php b/web/core/modules/comment/src/Plugin/migrate/source/d7/Comment.php index 42fe68e8c15edf504348cfaef1d9dd7e0f8f6111..73c2d8f4f7045c3a1191bd89b32e8191e9ccfd32 100644 --- a/web/core/modules/comment/src/Plugin/migrate/source/d7/Comment.php +++ b/web/core/modules/comment/src/Plugin/migrate/source/d7/Comment.php @@ -36,8 +36,20 @@ public function prepareRow(Row $row) { $comment_type = 'comment_node_' . $node_type; $row->setSourceProperty('comment_type', 'comment_node_' . $node_type); - foreach (array_keys($this->getFields('comment', $comment_type)) as $field) { - $row->setSourceProperty($field, $this->getFieldValues('comment', $field, $cid)); + // If this entity was translated using Entity Translation, we need to get + // its source language to get the field values in the right language. + // The translations will be migrated by the d7_comment_entity_translation + // migration. + $entity_translatable = $this->isEntityTranslatable('comment') && (int) $this->variableGet('language_content_type_' . $node_type, 0) === 4; + $source_language = $this->getEntityTranslationSourceLanguage('comment', $cid); + $language = $entity_translatable && $source_language ? $source_language : $row->getSourceProperty('language'); + + // Get Field API field values. + foreach ($this->getFields('comment', $comment_type) as $field_name => $field) { + // Ensure we're using the right language if the entity and the field are + // translatable. + $field_language = $entity_translatable && $field['translatable'] ? $language : NULL; + $row->setSourceProperty($field_name, $this->getFieldValues('comment', $field_name, $cid, NULL, $field_language)); } // If the comment subject was replaced by a real field using the Drupal 7 @@ -72,6 +84,7 @@ public function fields() { 'name' => $this->t("The comment author's name. Uses {users}.name if the user is logged in, otherwise uses the value typed into the comment form."), 'mail' => $this->t("The comment author's email address from the comment form, if user is anonymous, and the 'Anonymous users may/must leave their contact information' setting is turned on."), 'homepage' => $this->t("The comment author's home page address from the comment form, if user is anonymous, and the 'Anonymous users may/must leave their contact information' setting is turned on."), + 'language' => $this->t('The comment language.'), 'type' => $this->t("The {node}.type to which this comment is a reply."), ]; } diff --git a/web/core/modules/comment/src/Plugin/migrate/source/d7/CommentEntityTranslation.php b/web/core/modules/comment/src/Plugin/migrate/source/d7/CommentEntityTranslation.php new file mode 100644 index 0000000000000000000000000000000000000000..a749f7107c555808c00ca36f88770d83d8ab14b0 --- /dev/null +++ b/web/core/modules/comment/src/Plugin/migrate/source/d7/CommentEntityTranslation.php @@ -0,0 +1,103 @@ +<?php + +namespace Drupal\comment\Plugin\migrate\source\d7; + +use Drupal\migrate\Row; +use Drupal\migrate_drupal\Plugin\migrate\source\d7\FieldableEntity; + +/** + * Provides Drupal 7 comment entity translation source plugin. + * + * @MigrateSource( + * id = "d7_comment_entity_translation", + * source_module = "entity_translation" + * ) + */ +class CommentEntityTranslation extends FieldableEntity { + + /** + * {@inheritdoc} + */ + public function query() { + $query = $this->select('entity_translation', 'et') + ->fields('et') + ->fields('c', [ + 'subject', + ]) + ->condition('et.entity_type', 'comment') + ->condition('et.source', '', '<>'); + + $query->innerJoin('comment', 'c', 'c.cid = et.entity_id'); + $query->innerJoin('node', 'n', 'n.nid = c.nid'); + + $query->addField('n', 'type', 'node_type'); + + $query->orderBy('et.created'); + + return $query; + } + + /** + * {@inheritdoc} + */ + public function prepareRow(Row $row) { + $cid = $row->getSourceProperty('entity_id'); + $language = $row->getSourceProperty('language'); + $node_type = $row->getSourceProperty('node_type'); + $comment_type = 'comment_node_' . $node_type; + + // Get Field API field values. + foreach ($this->getFields('comment', $comment_type) as $field_name => $field) { + // Ensure we're using the right language if the entity is translatable. + $field_language = $field['translatable'] ? $language : NULL; + $row->setSourceProperty($field_name, $this->getFieldValues('comment', $field_name, $cid, NULL, $field_language)); + } + + // If the comment subject was replaced by a real field using the Drupal 7 + // Title module, use the field value instead of the comment subject. + if ($this->moduleExists('title')) { + $subject_field = $row->getSourceProperty('subject_field'); + if (isset($subject_field[0]['value'])) { + $row->setSourceProperty('subject', $subject_field[0]['value']); + } + } + + return parent::prepareRow($row); + } + + /** + * {@inheritdoc} + */ + public function fields() { + return [ + 'entity_type' => $this->t('The entity type this translation relates to'), + 'entity_id' => $this->t('The entity ID this translation relates to'), + 'revision_id' => $this->t('The entity revision ID this translation relates to'), + 'language' => $this->t('The target language for this translation.'), + 'source' => $this->t('The source language from which this translation was created.'), + 'uid' => $this->t('The author of this translation.'), + 'status' => $this->t('Boolean indicating whether the translation is published (visible to non-administrators).'), + 'translate' => $this->t('A boolean indicating whether this translation needs to be updated.'), + 'created' => $this->t('The Unix timestamp when the translation was created.'), + 'changed' => $this->t('The Unix timestamp when the translation was most recently saved.'), + 'subject' => $this->t('The comment title.'), + ]; + } + + /** + * {@inheritdoc} + */ + public function getIds() { + return [ + 'entity_id' => [ + 'type' => 'integer', + 'alias' => 'et', + ], + 'language' => [ + 'type' => 'string', + 'alias' => 'et', + ], + ]; + } + +} diff --git a/web/core/modules/comment/tests/src/Functional/CommentNonNodeTest.php b/web/core/modules/comment/tests/src/Functional/CommentNonNodeTest.php index 27c096444acc11102a2b7cc7b0ad0621939e50b2..ae94da1444e403574ecec5370e90c1ac195ad7aa 100644 --- a/web/core/modules/comment/tests/src/Functional/CommentNonNodeTest.php +++ b/web/core/modules/comment/tests/src/Functional/CommentNonNodeTest.php @@ -10,9 +10,9 @@ use Drupal\entity_test\Entity\EntityTest; use Drupal\field\Entity\FieldConfig; use Drupal\field\Entity\FieldStorageConfig; -use Drupal\field_ui\Tests\FieldUiTestTrait; use Drupal\Tests\BrowserTestBase; use Drupal\Core\Entity\EntityInterface; +use Drupal\Tests\field_ui\Traits\FieldUiTestTrait; use Drupal\user\RoleInterface; /** diff --git a/web/core/modules/comment/tests/src/Functional/Hal/CommentHalJsonAnonTest.php b/web/core/modules/comment/tests/src/Functional/Hal/CommentHalJsonAnonTest.php index f9e9958a5651bc56155c41d6a0da75e56e9d53d1..723df956012adb77a0852f8d15b772ed5c73e623 100644 --- a/web/core/modules/comment/tests/src/Functional/Hal/CommentHalJsonAnonTest.php +++ b/web/core/modules/comment/tests/src/Functional/Hal/CommentHalJsonAnonTest.php @@ -14,7 +14,7 @@ class CommentHalJsonAnonTest extends CommentHalJsonTestBase { /** * {@inheritdoc} * - * Anononymous users cannot edit their own comments. + * Anonymous users cannot edit their own comments. * * @see \Drupal\comment\CommentAccessControlHandler::checkAccess * diff --git a/web/core/modules/comment/tests/src/Functional/Rest/CommentJsonAnonTest.php b/web/core/modules/comment/tests/src/Functional/Rest/CommentJsonAnonTest.php index ffced7a241413e3551f25130e34c1ae69342a0ea..54925dd98374281dbbcb5f4d4bc6631a36b6a517 100644 --- a/web/core/modules/comment/tests/src/Functional/Rest/CommentJsonAnonTest.php +++ b/web/core/modules/comment/tests/src/Functional/Rest/CommentJsonAnonTest.php @@ -24,7 +24,7 @@ class CommentJsonAnonTest extends CommentResourceTestBase { /** * {@inheritdoc} * - * Anononymous users cannot edit their own comments. + * Anonymous users cannot edit their own comments. * * @see \Drupal\comment\CommentAccessControlHandler::checkAccess * diff --git a/web/core/modules/comment/tests/src/Functional/Rest/CommentResourceTestBase.php b/web/core/modules/comment/tests/src/Functional/Rest/CommentResourceTestBase.php index 7d1abdbb680536aca73af637529e33edb17f66af..bd71e4fa329fd7ea0428b8dff7a453aac737b486 100644 --- a/web/core/modules/comment/tests/src/Functional/Rest/CommentResourceTestBase.php +++ b/web/core/modules/comment/tests/src/Functional/Rest/CommentResourceTestBase.php @@ -60,7 +60,7 @@ protected function setUpAuthorization($method) { $this->grantPermissionsToTestedRole(['post comments']); break; case 'PATCH': - // Anononymous users are not ever allowed to edit their own comments. To + // Anonymous users are not ever allowed to edit their own comments. To // be able to test PATCHing comments as the anonymous user, the more // permissive 'administer comments' permission must be granted. // @see \Drupal\comment\CommentAccessControlHandler::checkAccess diff --git a/web/core/modules/comment/tests/src/Functional/Rest/CommentXmlAnonTest.php b/web/core/modules/comment/tests/src/Functional/Rest/CommentXmlAnonTest.php index c2e529e3dd996233f656f67f4a9659e8b6602123..22c1b858f5e35a75345f91010085cb36253e6dd1 100644 --- a/web/core/modules/comment/tests/src/Functional/Rest/CommentXmlAnonTest.php +++ b/web/core/modules/comment/tests/src/Functional/Rest/CommentXmlAnonTest.php @@ -26,7 +26,7 @@ class CommentXmlAnonTest extends CommentResourceTestBase { /** * {@inheritdoc} * - * Anononymous users cannot edit their own comments. + * Anonymous users cannot edit their own comments. * * @see \Drupal\comment\CommentAccessControlHandler::checkAccess * diff --git a/web/core/modules/comment/tests/src/Kernel/Migrate/d6/MigrateCommentTest.php b/web/core/modules/comment/tests/src/Kernel/Migrate/d6/MigrateCommentTest.php index 06ca65582e532674ad47590707f1834ed3649d3e..e040ac0deb05aa807ab12e8573937cf530e96ee7 100644 --- a/web/core/modules/comment/tests/src/Kernel/Migrate/d6/MigrateCommentTest.php +++ b/web/core/modules/comment/tests/src/Kernel/Migrate/d6/MigrateCommentTest.php @@ -20,7 +20,12 @@ class MigrateCommentTest extends MigrateDrupal6TestBase { /** * {@inheritdoc} */ - public static $modules = ['comment', 'menu_ui']; + public static $modules = [ + 'comment', + 'content_translation', + 'language', + 'menu_ui', + ]; /** * {@inheritdoc} @@ -31,6 +36,7 @@ protected function setUp() { $this->installEntitySchema('node'); $this->installEntitySchema('comment'); $this->installSchema('comment', ['comment_entity_statistics']); + $this->installSchema('node', ['node_access']); $this->installConfig(['comment']); // The entity.node.canonical route must exist when the RDF hook is called. @@ -38,7 +44,10 @@ protected function setUp() { $this->migrateContent(); $this->executeMigrations([ + 'language', + 'd6_language_content_settings', 'd6_node', + 'd6_node_translation', 'd6_comment_type', 'd6_comment_field', 'd6_comment_field_instance', @@ -84,6 +93,31 @@ public function testMigration() { $node = $comment->getCommentedEntity(); $this->assertInstanceOf(NodeInterface::class, $node); $this->assertSame('1', $node->id()); + + // Tests that the language of the comment is migrated from the node. + $comment = Comment::load(7); + $this->assertSame('Comment to John Smith - EN', $comment->subject->value); + $this->assertSame('This is an English comment.', $comment->comment_body->value); + $this->assertSame('21', $comment->getCommentedEntityId()); + $this->assertSame('node', $comment->getCommentedEntityTypeId()); + $this->assertSame('en', $comment->language()->getId()); + + $node = $comment->getCommentedEntity(); + $this->assertInstanceOf(NodeInterface::class, $node); + $this->assertSame('21', $node->id()); + + // Tests that the comment language is correct and that the commented entity + // is correctly migrated when the comment was posted to a node translation. + $comment = Comment::load(8); + $this->assertSame('Comment to John Smith - FR', $comment->subject->value); + $this->assertSame('This is a French comment.', $comment->comment_body->value); + $this->assertSame('21', $comment->getCommentedEntityId()); + $this->assertSame('node', $comment->getCommentedEntityTypeId()); + $this->assertSame('fr', $comment->language()->getId()); + + $node = $comment->getCommentedEntity(); + $this->assertInstanceOf(NodeInterface::class, $node); + $this->assertSame('21', $node->id()); } } diff --git a/web/core/modules/comment/tests/src/Kernel/Migrate/d7/MigrateCommentTest.php b/web/core/modules/comment/tests/src/Kernel/Migrate/d7/MigrateCommentTest.php index 68df72f376907f5f7240ffdfcc4c79a1cbac4a82..58c70f62032dc5559e5ba01d115a5b34096695ae 100644 --- a/web/core/modules/comment/tests/src/Kernel/Migrate/d7/MigrateCommentTest.php +++ b/web/core/modules/comment/tests/src/Kernel/Migrate/d7/MigrateCommentTest.php @@ -19,11 +19,15 @@ class MigrateCommentTest extends MigrateDrupal7TestBase { */ public static $modules = [ 'comment', + 'content_translation', 'datetime', 'filter', 'image', + 'language', 'link', 'menu_ui', + // Required for translation migrations. + 'migrate_drupal_multilingual', 'node', 'taxonomy', 'telephone', @@ -38,14 +42,19 @@ protected function setUp() { $this->installEntitySchema('node'); $this->installEntitySchema('comment'); + $this->installEntitySchema('taxonomy_term'); $this->installConfig(['comment', 'node']); $this->installSchema('comment', ['comment_entity_statistics']); - + $this->installSchema('node', ['node_access']); $this->executeMigrations([ + 'language', + 'd7_node_type', + 'd7_language_content_settings', 'd7_user_role', 'd7_user', 'd7_node_type', 'd7_node', + 'd7_node_translation', 'd7_comment_type', 'd7_comment_field', 'd7_comment_field_instance', @@ -55,6 +64,8 @@ protected function setUp() { 'd7_field', 'd7_field_instance', 'd7_comment', + 'd7_entity_translation_settings', + 'd7_comment_entity_translation', ]); } @@ -64,7 +75,7 @@ protected function setUp() { public function testMigration() { $comment = Comment::load(1); $this->assertInstanceOf(Comment::class, $comment); - $this->assertSame('A comment', $comment->getSubject()); + $this->assertSame('Subject field in English', $comment->getSubject()); $this->assertSame('1421727536', $comment->getCreatedTime()); $this->assertSame('1421727536', $comment->getChangedTime()); $this->assertTrue($comment->getStatus()); @@ -73,6 +84,7 @@ public function testMigration() { $this->assertSame('This is a comment', $comment->comment_body->value); $this->assertSame('filtered_html', $comment->comment_body->format); $this->assertSame('2001:db8:ffff:ffff:ffff:ffff:ffff:ffff', $comment->getHostname()); + $this->assertSame('en', $comment->language()->getId()); $this->assertSame('1000000', $comment->field_integer->value); $node = $comment->getCommentedEntity(); @@ -85,6 +97,59 @@ public function testMigration() { $this->assertInstanceOf(Comment::class, $comment); $this->assertSame('TNG for the win!', $comment->getSubject()); $this->assertSame('TNG is better than DS9.', $comment->comment_body->value); + $this->assertSame('en', $comment->language()->getId()); + + // Tests that the commented entity is correctly migrated when the comment + // was posted to a node translation. + $comment = Comment::load(3); + $this->assertInstanceOf(Comment::class, $comment); + $this->assertSame('Comment to IS translation', $comment->getSubject()); + $this->assertSame('This is a comment to an Icelandic translation.', $comment->comment_body->value); + $this->assertSame('2', $comment->getCommentedEntityId()); + $this->assertSame('node', $comment->getCommentedEntityTypeId()); + $this->assertSame('is', $comment->language()->getId()); + + $node = $comment->getCommentedEntity(); + $this->assertInstanceOf(NodeInterface::class, $node); + $this->assertSame('2', $node->id()); + } + + /** + * Tests the migration of comment entity translations. + */ + public function testCommentEntityTranslations() { + $manager = $this->container->get('content_translation.manager'); + + // Get the comment and its translations. + $comment = Comment::load(1); + $comment_fr = $comment->getTranslation('fr'); + $comment_is = $comment->getTranslation('is'); + + // Test that fields translated with Entity Translation are migrated. + $this->assertSame('Subject field in English', $comment->getSubject()); + $this->assertSame('Subject field in French', $comment_fr->getSubject()); + $this->assertSame('Subject field in Icelandic', $comment_is->getSubject()); + $this->assertSame('1000000', $comment->field_integer->value); + $this->assertSame('2000000', $comment_fr->field_integer->value); + $this->assertSame('3000000', $comment_is->field_integer->value); + + // Test that the French translation metadata is correctly migrated. + $metadata_fr = $manager->getTranslationMetadata($comment_fr); + $this->assertFalse($metadata_fr->isPublished()); + $this->assertSame('en', $metadata_fr->getSource()); + $this->assertSame('1', $metadata_fr->getAuthor()->uid->value); + $this->assertSame('1531837764', $metadata_fr->getCreatedTime()); + $this->assertSame('1531837764', $metadata_fr->getChangedTime()); + $this->assertFalse($metadata_fr->isOutdated()); + + // Test that the Icelandic translation metadata is correctly migrated. + $metadata_is = $manager->getTranslationMetadata($comment_is); + $this->assertTrue($metadata_is->isPublished()); + $this->assertSame('en', $metadata_is->getSource()); + $this->assertSame('2', $metadata_is->getAuthor()->uid->value); + $this->assertSame('1531838064', $metadata_is->getCreatedTime()); + $this->assertSame('1531838064', $metadata_is->getChangedTime()); + $this->assertTrue($metadata_is->isOutdated()); } } diff --git a/web/core/modules/comment/tests/src/Kernel/Migrate/d7/MigrateCommentTypeTest.php b/web/core/modules/comment/tests/src/Kernel/Migrate/d7/MigrateCommentTypeTest.php index b0c96dab837ce78a3a18efb7cba016a816d6a255..9a82b5b0cb743bcd7b53129d5fc6665bcd86a8fc 100644 --- a/web/core/modules/comment/tests/src/Kernel/Migrate/d7/MigrateCommentTypeTest.php +++ b/web/core/modules/comment/tests/src/Kernel/Migrate/d7/MigrateCommentTypeTest.php @@ -46,6 +46,17 @@ protected function assertEntity($id, $label) { * Tests the migrated comment types. */ public function testMigration() { + $comment_fields = [ + 'comment' => 'Default comment setting', + 'comment_default_mode' => 'Default display mode', + 'comment_default_per_page' => 'Default comments per page', + 'comment_anonymous' => 'Anonymous commenting', + 'comment_subject_field' => 'Comment subject field', + 'comment_preview' => 'Preview comment', + 'comment_form_location' => 'Location of comment submission form', + ]; + $this->assertArraySubset($comment_fields, $this->migration->getSourcePlugin()->fields()); + $this->assertEntity('comment_node_article', 'Article comment'); $this->assertEntity('comment_node_blog', 'Blog entry comment'); $this->assertEntity('comment_node_book', 'Book page comment'); diff --git a/web/core/modules/comment/tests/src/Kernel/Plugin/migrate/source/d6/CommentSourceWithHighWaterTest.php b/web/core/modules/comment/tests/src/Kernel/Plugin/migrate/source/d6/CommentSourceWithHighWaterTest.php index a4d91c468611da328c6e63c19593846f6c288817..26b95d7fcedef3050170100c33702e3fffe4cc4f 100644 --- a/web/core/modules/comment/tests/src/Kernel/Plugin/migrate/source/d6/CommentSourceWithHighWaterTest.php +++ b/web/core/modules/comment/tests/src/Kernel/Plugin/migrate/source/d6/CommentSourceWithHighWaterTest.php @@ -66,10 +66,12 @@ public function providerSource() { [ 'nid' => 2, 'type' => 'story', + 'language' => 'en', ], [ 'nid' => 3, 'type' => 'page', + 'language' => 'fr', ], ]; @@ -91,6 +93,7 @@ public function providerSource() { 'homepage' => '', 'format' => 'testformat2', 'type' => 'page', + 'language' => 'fr', ], ]; diff --git a/web/core/modules/comment/tests/src/Kernel/Plugin/migrate/source/d6/CommentTest.php b/web/core/modules/comment/tests/src/Kernel/Plugin/migrate/source/d6/CommentTest.php index 0372f0f9ac06088b9d8d71552d69a3fd0e96bd9c..d5a4aa3e30851f900f9cc6a2fc81880c94e8f025 100644 --- a/web/core/modules/comment/tests/src/Kernel/Plugin/migrate/source/d6/CommentTest.php +++ b/web/core/modules/comment/tests/src/Kernel/Plugin/migrate/source/d6/CommentTest.php @@ -65,10 +65,12 @@ public function providerSource() { [ 'nid' => 2, 'type' => 'story', + 'language' => 'en', ], [ 'nid' => 3, 'type' => 'page', + 'language' => 'fr', ], ]; @@ -90,6 +92,7 @@ public function providerSource() { 'homepage' => '', 'format' => 'testformat1', 'type' => 'story', + 'language' => 'en', ], [ 'cid' => 2, @@ -107,6 +110,7 @@ public function providerSource() { 'homepage' => '', 'format' => 'testformat2', 'type' => 'page', + 'language' => 'fr', ], ]; diff --git a/web/core/modules/comment/tests/src/Kernel/Plugin/migrate/source/d7/CommentEntityTranslationTest.php b/web/core/modules/comment/tests/src/Kernel/Plugin/migrate/source/d7/CommentEntityTranslationTest.php new file mode 100644 index 0000000000000000000000000000000000000000..548e7fc25d44506c8a1f182fdcb9e6b3cbcafb24 --- /dev/null +++ b/web/core/modules/comment/tests/src/Kernel/Plugin/migrate/source/d7/CommentEntityTranslationTest.php @@ -0,0 +1,281 @@ +<?php + +namespace Drupal\Tests\comment\Kernel\Plugin\migrate\source\d7; + +use Drupal\Tests\migrate\Kernel\MigrateSqlSourceTestBase; + +/** + * Tests D7 comment entity translation source plugin. + * + * @covers \Drupal\comment\Plugin\migrate\source\d7\CommentEntityTranslation + * @group comment + */ +class CommentEntityTranslationTest extends MigrateSqlSourceTestBase { + + /** + * {@inheritdoc} + */ + public static $modules = ['comment', 'migrate_drupal']; + + /** + * {@inheritdoc} + */ + public function providerSource() { + $tests = []; + + // The source data. + $tests[0]['source_data']['comment'] = [ + [ + 'cid' => '1', + 'pid' => '0', + 'nid' => '1', + 'uid' => '1', + 'subject' => 'A comment', + 'hostname' => '::1', + 'created' => '1421727536', + 'changed' => '1421727536', + 'status' => '1', + 'thread' => '01/', + 'name' => 'admin', + 'mail' => '', + 'homepage' => '', + 'language' => 'en', + ], + ]; + $tests[0]['source_data']['entity_translation'] = [ + [ + 'entity_type' => 'comment', + 'entity_id' => 1, + 'revision_id' => 1, + 'language' => 'en', + 'source' => '', + 'uid' => 1, + 'status' => 1, + 'translate' => 0, + 'created' => '1421727536', + 'changed' => '1421727536', + ], + [ + 'entity_type' => 'comment', + 'entity_id' => 1, + 'revision_id' => 1, + 'language' => 'fr', + 'source' => 'en', + 'uid' => 1, + 'status' => 0, + 'translate' => 0, + 'created' => 1531343508, + 'changed' => 1531343508, + ], + [ + 'entity_type' => 'comment', + 'entity_id' => 1, + 'revision_id' => 1, + 'language' => 'es', + 'source' => 'en', + 'uid' => 2, + 'status' => 1, + 'translate' => 1, + 'created' => 1531343528, + 'changed' => 1531343528, + ], + ]; + $tests[0]['source_data']['field_config'] = [ + [ + 'id' => 1, + 'field_name' => 'field_test', + 'type' => 'text', + 'module' => 'text', + 'active' => 1, + 'storage_type' => 'field_sql_storage', + 'storage_module' => 'field_sql_storage', + 'storage_active' => 1, + 'locked' => 1, + 'data' => 'a:0:{}', + 'cardinality' => 1, + 'translatable' => 1, + 'deleted' => 0, + ], + [ + 'id' => 2, + 'field_name' => 'subject_field', + 'type' => 'text', + 'module' => 'text', + 'active' => 1, + 'storage_type' => 'field_sql_storage', + 'storage_module' => 'field_sql_storage', + 'storage_active' => 1, + 'locked' => 1, + 'data' => 'a:0:{}', + 'cardinality' => 1, + 'translatable' => 1, + 'deleted' => 0, + ], + ]; + $tests[0]['source_data']['field_config_instance'] = [ + [ + 'id' => '1', + 'field_id' => '1', + 'field_name' => 'field_test', + 'entity_type' => 'comment', + 'bundle' => 'comment_node_test_content_type', + 'data' => 'a:0:{}', + 'deleted' => '0', + ], + [ + 'id' => '2', + 'field_id' => '2', + 'field_name' => 'subject_field', + 'entity_type' => 'comment', + 'bundle' => 'comment_node_test_content_type', + 'data' => 'a:0:{}', + 'deleted' => '0', + ], + ]; + $tests[0]['source_data']['field_data_field_test'] = [ + [ + 'entity_type' => 'comment', + 'bundle' => 'comment_node_test_content_type', + 'deleted' => '0', + 'entity_id' => '1', + 'revision_id' => '1', + 'language' => 'en', + 'delta' => '0', + 'field_test_value' => 'This is an English comment', + 'field_test_format' => NULL, + ], + [ + 'entity_type' => 'comment', + 'bundle' => 'comment_node_test_content_type', + 'deleted' => '0', + 'entity_id' => '1', + 'revision_id' => '1', + 'language' => 'fr', + 'delta' => '0', + 'field_test_value' => 'This is a French comment', + 'field_test_format' => NULL, + ], + [ + 'entity_type' => 'comment', + 'bundle' => 'comment_node_test_content_type', + 'deleted' => '0', + 'entity_id' => '1', + 'revision_id' => '1', + 'language' => 'es', + 'delta' => '0', + 'field_test_value' => 'This is a Spanish comment', + 'field_test_format' => NULL, + ], + ]; + $tests[0]['source_data']['field_data_subject_field'] = [ + [ + 'entity_type' => 'comment', + 'bundle' => 'comment_node_test_content_type', + 'deleted' => '0', + 'entity_id' => '1', + 'revision_id' => '1', + 'language' => 'en', + 'delta' => '0', + 'subject_field_value' => 'Comment subject in English', + 'subject_field_format' => NULL, + ], + [ + 'entity_type' => 'comment', + 'bundle' => 'comment_node_test_content_type', + 'deleted' => '0', + 'entity_id' => '1', + 'revision_id' => '1', + 'language' => 'fr', + 'delta' => '0', + 'subject_field_value' => 'Comment subject in French', + 'subject_field_format' => NULL, + ], + [ + 'entity_type' => 'comment', + 'bundle' => 'comment_node_test_content_type', + 'deleted' => '0', + 'entity_id' => '1', + 'revision_id' => '1', + 'language' => 'es', + 'delta' => '0', + 'subject_field_value' => 'Comment subject in Spanish', + 'subject_field_format' => NULL, + ], + ]; + $tests[0]['source_data']['node'] = [ + [ + 'nid' => '1', + 'vid' => '1', + 'type' => 'test_content_type', + 'language' => 'en', + 'title' => 'A Node', + 'uid' => '1', + 'status' => '1', + 'created' => '1421727515', + 'changed' => '1421727515', + 'comment' => '2', + 'promote' => '1', + 'sticky' => '0', + 'tnid' => '0', + 'translate' => '0', + ], + ]; + + // The expected results. + $tests[0]['expected_data'] = [ + [ + 'subject' => 'A comment', + 'entity_type' => 'comment', + 'entity_id' => '1', + 'revision_id' => '1', + 'language' => 'fr', + 'source' => 'en', + 'uid' => '1', + 'status' => '0', + 'translate' => '0', + 'created' => '1531343508', + 'changed' => '1531343508', + 'field_test' => [ + [ + 'value' => 'This is a French comment', + 'format' => NULL, + ], + ], + 'subject_field' => [ + [ + 'value' => 'Comment subject in French', + 'format' => NULL, + ], + ], + ], + [ + 'subject' => 'A comment', + 'entity_type' => 'comment', + 'entity_id' => '1', + 'revision_id' => '1', + 'language' => 'es', + 'source' => 'en', + 'uid' => '2', + 'status' => '1', + 'translate' => '1', + 'created' => '1531343528', + 'changed' => '1531343528', + 'field_test' => [ + [ + 'value' => 'This is a Spanish comment', + 'format' => NULL, + ], + ], + 'subject_field' => [ + [ + 'value' => 'Comment subject in Spanish', + 'format' => NULL, + ], + ], + ], + ]; + + return $tests; + } + +} diff --git a/web/core/modules/config/tests/src/Functional/ConfigInstallProfileOverrideTest.php b/web/core/modules/config/tests/src/Functional/ConfigInstallProfileOverrideTest.php index 187155f70eaeb8425bf9faadf79a0ff406e4e05b..8615da5865b8e1130d4947b09f1d228226a46951 100644 --- a/web/core/modules/config/tests/src/Functional/ConfigInstallProfileOverrideTest.php +++ b/web/core/modules/config/tests/src/Functional/ConfigInstallProfileOverrideTest.php @@ -107,7 +107,16 @@ public function testInstallProfileConfigOverwrite() { $this->container->get('module_installer')->install(['dblog']); $this->rebuildContainer(); $this->assertEqual($config_test_storage->load('override_unmet')->label(), 'Override', 'The optional config_test entity is overridden by the profile optional configuration and is installed when its dependencies are met.'); - $this->assertEqual($config_test_storage->load('completely_new')->label(), 'Completely new optional configuration', 'The optional config_test entity is provided by the profile optional configuration and is installed when its dependencies are met.'); + $config_test_new = $config_test_storage->load('completely_new'); + $this->assertEqual($config_test_new->label(), 'Completely new optional configuration', 'The optional config_test entity is provided by the profile optional configuration and is installed when its dependencies are met.'); + $config_test_new->delete(); + + // Install another module that provides optional configuration and ensure + // that deleted profile configuration is not re-created. + $this->container->get('module_installer')->install(['config_other_module_config_test']); + $this->rebuildContainer(); + $config_test_storage = \Drupal::entityManager()->getStorage('config_test'); + $this->assertNull($config_test_storage->load('completely_new')); } } diff --git a/web/core/modules/config/tests/src/Kernel/ConfigUninstallViaCliImportTest.php b/web/core/modules/config/tests/src/Kernel/ConfigUninstallViaCliImportTest.php index 0ab0fd1764e8068c68c8fb23f1db943f6f4a52de..722546fe303b3f67d2d2f87ebc8bfeed712fa9a1 100644 --- a/web/core/modules/config/tests/src/Kernel/ConfigUninstallViaCliImportTest.php +++ b/web/core/modules/config/tests/src/Kernel/ConfigUninstallViaCliImportTest.php @@ -55,7 +55,7 @@ protected function setUp() { } /** - * Tests that the config mopdule can be uninstalled via CLI config import. + * Tests that the config module can be uninstalled via CLI config import. * * @see \Drupal\config\ConfigSubscriber */ diff --git a/web/core/modules/config_translation/migrations/d6_field_instance_label_description_translation.yml b/web/core/modules/config_translation/migrations/d6_field_instance_label_description_translation.yml new file mode 100644 index 0000000000000000000000000000000000000000..41d729263bf18385c64e9f47cffe65d5f9df25b4 --- /dev/null +++ b/web/core/modules/config_translation/migrations/d6_field_instance_label_description_translation.yml @@ -0,0 +1,57 @@ +id: d6_field_instance_label_description_translation +label: Field label and description translation +migration_tags: + - Drupal 6 + - Configuration + - Multilingual +source: + plugin: d6_field_instance_label_description_translation + constants: + entity_type: node +process: + langcode: + plugin: skip_on_empty + source: language + method: row + translation: + plugin: skip_on_empty + source: translation + method: row + field_name_parts: + plugin: explode + source: objectid + delimiter: '-' + field_name: + plugin: extract + source: '@field_name_parts' + index: + - 1 + bundle: + plugin: extract + source: '@field_name_parts' + index: + - 0 + exists: + - + plugin: migration_lookup + migration: d6_field_instance + source: + - '@field_name' + - '@bundle' + - + plugin: skip_on_empty + method: row + entity_type: 'constants/entity_type' + property: + plugin: static_map + source: property + bypass: true + map: + widget_label: label + widget_description: description +destination: + plugin: entity:field_config + translations: true +migration_dependencies: + required: + - d6_field_instance diff --git a/web/core/modules/config_translation/migrations/d6_field_instance_option_translation.yml b/web/core/modules/config_translation/migrations/d6_field_instance_option_translation.yml new file mode 100644 index 0000000000000000000000000000000000000000..7c59018d7bef5aa63dadd91ebc51b579ae282a02 --- /dev/null +++ b/web/core/modules/config_translation/migrations/d6_field_instance_option_translation.yml @@ -0,0 +1,178 @@ +id: d6_field_instance_option_translation +label: Field instance option configuration translation +migration_tags: + - Drupal 6 + - Configuration + - Multilingual +source: + plugin: d6_field_instance_option_translation + skip_count: true + constants: + entity_type: node + property: settings +process: + # We skip field types that don't exist because they weren't migrated by the + # field migration. + field_type_exists: + - + plugin: migration_lookup + migration: d6_field + source: + - objectid + - + plugin: extract + index: + - 1 + - + plugin: skip_on_empty + method: row + # Use the process from d6_field to determine the field type. + type: + plugin: field_type + source: + - type + - widget_type + map: + userreference: + userreference_select: entity_reference + userreference_buttons: entity_reference + userreference_autocomplete: entity_reference + nodereference: + nodereference_select: entity_reference + number_integer: + number: integer + optionwidgets_select: list_integer + optionwidgets_buttons: list_integer + optionwidgets_onoff: boolean + number_decimal: + number: decimal + optionwidgets_select: list_float + optionwidgets_buttons: list_float + optionwidgets_onoff: boolean + number_float: + number: float + optionwidgets_select: list_float + optionwidgets_buttons: list_float + optionwidgets_onoff: boolean + email: + email_textfield: email + filefield: + imagefield_widget: image + filefield_widget: file + fr_phone: + phone_textfield: telephone + be_phone: + phone_textfield: telephone + it_phone: + phone_textfield: telephone + el_phone: + phone_textfield: telephone + ch_phone: + phone_textfield: telephone + ca_phone: + phone_textfield: telephone + cr_phone: + phone_textfield: telephone + pa_phone: + phone_textfield: telephone + gb_phone: + phone_textfield: telephone + ru_phone: + phone_textfield: telephone + ua_phone: + phone_textfield: telephone + es_phone: + phone_textfield: telephone + au_phone: + phone_textfield: telephone + cs_phone: + phone_textfield: telephone + hu_phone: + phone_textfield: telephone + pl_phone: + phone_textfield: telephone + nl_phone: + phone_textfield: telephone + se_phone: + phone_textfield: telephone + za_phone: + phone_textfield: telephone + il_phone: + phone_textfield: telephone + nz_phone: + phone_textfield: telephone + br_phone: + phone_textfield: telephone + cl_phone: + phone_textfield: telephone + cn_phone: + phone_textfield: telephone + hk_phone: + phone_textfield: telephone + mo_phone: + phone_textfield: telephone + ph_phone: + phone_textfield: telephone + sg_phone: + phone_textfield: telephone + jo_phone: + phone_textfield: telephone + eg_phone: + phone_textfield: telephone + pk_phone: + phone_textfield: telephone + int_phone: + phone_textfield: telephone + boolean_type: + - + plugin: static_map + source: '@type' + map: + boolean: boolean + default_value: false + - + plugin: skip_on_empty + method: row + bundle: + - + plugin: migration_lookup + migration: d6_node_type + source: type_name + - + plugin: skip_on_empty + method: row + langcode: + plugin: skip_on_empty + source: language + method: row + field_name: objectid + entity_type: 'constants/entity_type' + results: + plugin: d6_field_instance_option_translation + source: + - '@type' + - global_settings + translation: + - + plugin: extract + source: '@results' + index: [1] + - + plugin: skip_on_empty + method: row + property: + - + plugin: extract + source: '@results' + index: [0] + - + plugin: skip_on_empty + method: row +destination: + plugin: entity:field_config + translations: true +migration_dependencies: + required: + - d6_node_type + - d6_field_instance + - d6_field_option_translation diff --git a/web/core/modules/config_translation/migrations/d6_field_option_translation.yml b/web/core/modules/config_translation/migrations/d6_field_option_translation.yml new file mode 100644 index 0000000000000000000000000000000000000000..bea24a2562dd1312004d853d72fc1eb73f28fb1c --- /dev/null +++ b/web/core/modules/config_translation/migrations/d6_field_option_translation.yml @@ -0,0 +1,144 @@ +id: d6_field_option_translation +label: Field option configuration translation +migration_tags: + - Drupal 6 + - Configuration + - Multilingual +source: + plugin: d6_field_option_translation + skip_count: true + constants: + entity_type: node + allowed_values: settings +process: + entity_type: 'constants/entity_type' + status: active + langcode: + plugin: skip_on_empty + source: language + method: row + field_name: objectid + # Use the process from d6_field to determine the field type. + type: + plugin: field_type + source: + - type + - widget_type + map: + userreference: + userreference_select: entity_reference + userreference_buttons: entity_reference + userreference_autocomplete: entity_reference + nodereference: + nodereference_select: entity_reference + number_integer: + number: integer + optionwidgets_select: list_integer + optionwidgets_buttons: list_integer + optionwidgets_onoff: boolean + number_decimal: + number: decimal + optionwidgets_select: list_float + optionwidgets_buttons: list_float + optionwidgets_onoff: boolean + number_float: + number: float + optionwidgets_select: list_float + optionwidgets_buttons: list_float + optionwidgets_onoff: boolean + email: + email_textfield: email + filefield: + imagefield_widget: image + filefield_widget: file + fr_phone: + phone_textfield: telephone + be_phone: + phone_textfield: telephone + it_phone: + phone_textfield: telephone + el_phone: + phone_textfield: telephone + ch_phone: + phone_textfield: telephone + ca_phone: + phone_textfield: telephone + cr_phone: + phone_textfield: telephone + pa_phone: + phone_textfield: telephone + gb_phone: + phone_textfield: telephone + ru_phone: + phone_textfield: telephone + ua_phone: + phone_textfield: telephone + es_phone: + phone_textfield: telephone + au_phone: + phone_textfield: telephone + cs_phone: + phone_textfield: telephone + hu_phone: + phone_textfield: telephone + pl_phone: + phone_textfield: telephone + nl_phone: + phone_textfield: telephone + se_phone: + phone_textfield: telephone + za_phone: + phone_textfield: telephone + il_phone: + phone_textfield: telephone + nz_phone: + phone_textfield: telephone + br_phone: + phone_textfield: telephone + cl_phone: + phone_textfield: telephone + cn_phone: + phone_textfield: telephone + hk_phone: + phone_textfield: telephone + mo_phone: + phone_textfield: telephone + ph_phone: + phone_textfield: telephone + sg_phone: + phone_textfield: telephone + jo_phone: + phone_textfield: telephone + eg_phone: + phone_textfield: telephone + pk_phone: + phone_textfield: telephone + int_phone: + phone_textfield: telephone + results: + plugin: d6_field_option_translation + source: + - '@type' + - global_settings + translation: + - + plugin: extract + source: '@results' + index: [1] + - + plugin: skip_on_empty + method: row + property: + - + plugin: extract + source: '@results' + index: [0] + - + plugin: skip_on_empty + method: row +destination: + plugin: entity:field_storage_config + translations: true +migration_dependencies: + required: + - d6_field diff --git a/web/core/modules/config_translation/migrations/d6_system_maintenance_translation.yml b/web/core/modules/config_translation/migrations/d6_system_maintenance_translation.yml index 5a3593c27e8d835a117fe5b966129f5ac15fecc7..022cc24a604bcdd8e1ffe088f0fe1b1ec6c477ca 100644 --- a/web/core/modules/config_translation/migrations/d6_system_maintenance_translation.yml +++ b/web/core/modules/config_translation/migrations/d6_system_maintenance_translation.yml @@ -5,7 +5,7 @@ migration_tags: - Configuration - Multilingual source: - plugin: variable_translation + plugin: d6_variable_translation variables: - site_offline_message source_module: i18n diff --git a/web/core/modules/config_translation/migrations/d6_system_site_translation.yml b/web/core/modules/config_translation/migrations/d6_system_site_translation.yml index a246aa97d3bdcf3e4fe4d0a70d13a09cde6d3022..ad52d6b71a3fc9b9afd28baaf0eabe65041bb6c0 100644 --- a/web/core/modules/config_translation/migrations/d6_system_site_translation.yml +++ b/web/core/modules/config_translation/migrations/d6_system_site_translation.yml @@ -5,7 +5,7 @@ migration_tags: - Configuration - Multilingual source: - plugin: variable_translation + plugin: d6_variable_translation constants: slash: '/' variables: diff --git a/web/core/modules/config_translation/migrations/d6_user_mail_translation.yml b/web/core/modules/config_translation/migrations/d6_user_mail_translation.yml index 2fb3429e6f6323100831db74b31dde3ed03eff81..5417ceb2de1480cb272e078d86aac2addf989e88 100644 --- a/web/core/modules/config_translation/migrations/d6_user_mail_translation.yml +++ b/web/core/modules/config_translation/migrations/d6_user_mail_translation.yml @@ -5,7 +5,7 @@ migration_tags: - Configuration - Multilingual source: - plugin: variable_translation + plugin: d6_variable_translation variables: - user_mail_status_activated_subject - user_mail_status_activated_body diff --git a/web/core/modules/config_translation/migrations/d6_user_settings_translation.yml b/web/core/modules/config_translation/migrations/d6_user_settings_translation.yml index f947ff92766acaeeeb42445de61e5c8f7ee56ae3..a934dda609caeaa1e9387b3f8741da84f84f8a97 100644 --- a/web/core/modules/config_translation/migrations/d6_user_settings_translation.yml +++ b/web/core/modules/config_translation/migrations/d6_user_settings_translation.yml @@ -5,7 +5,7 @@ migration_tags: - Configuration - Multilingual source: - plugin: variable_translation + plugin: d6_variable_translation variables: - user_mail_status_blocked_notify - user_mail_status_activated_notify diff --git a/web/core/modules/config_translation/migrations/d7_system_maintenance_translation.yml b/web/core/modules/config_translation/migrations/d7_system_maintenance_translation.yml new file mode 100644 index 0000000000000000000000000000000000000000..f787d4aaf4e3ddc2b3fc93a90cd4cad4a895d76b --- /dev/null +++ b/web/core/modules/config_translation/migrations/d7_system_maintenance_translation.yml @@ -0,0 +1,17 @@ +id: d7_system_maintenance_translation +label: Maintenance page configuration +migration_tags: + - Drupal 7 + - Configuration + - Multilingual +source: + plugin: d7_variable_translation + variables: + - maintenance_mode_message +process: + langcode: language + message: maintenance_mode_message +destination: + plugin: config + config_name: system.maintenance + translations: true diff --git a/web/core/modules/config_translation/migrations/d7_system_site_translation.yml b/web/core/modules/config_translation/migrations/d7_system_site_translation.yml new file mode 100644 index 0000000000000000000000000000000000000000..9aac86df53aec5ed9827ad29e7b309eb141e038c --- /dev/null +++ b/web/core/modules/config_translation/migrations/d7_system_site_translation.yml @@ -0,0 +1,27 @@ +id: d7_system_site_translation +label: Site configuration translation +migration_tags: + - Drupal 7 + - Configuration + - Multilingual +source: + plugin: d7_variable_translation + variables: + - site_name + - site_mail + - site_slogan + - site_frontpage + - site_403 + - site_404 +process: + langcode: language + name: site_name + mail: site_mail + slogan: site_slogan + 'page/front': site_frontpage + 'page/403': site_403 + 'page/404': site_404 +destination: + plugin: config + config_name: system.site + translations: true diff --git a/web/core/modules/config_translation/migrations/d7_user_mail_translation.yml b/web/core/modules/config_translation/migrations/d7_user_mail_translation.yml new file mode 100644 index 0000000000000000000000000000000000000000..73b6b1d46329d7b80ea7df6c540e80a4a9bfb009 --- /dev/null +++ b/web/core/modules/config_translation/migrations/d7_user_mail_translation.yml @@ -0,0 +1,79 @@ +id: d7_user_mail_translation +label: User mail configuration translation +migration_tags: + - Drupal 7 + - Configuration + - Multilingual +source: + plugin: d7_variable_translation + variables: + - user_mail_cancel_confirm_subject + - user_mail_cancel_confirm_body + - user_mail_password_reset_subject + - user_mail_password_reset_body + - user_mail_register_admin_created_subject + - user_mail_register_admin_created_body + - user_mail_register_no_approval_required_subject + - user_mail_register_no_approval_required_body + - user_mail_register_pending_approval_subject + - user_mail_register_pending_approval_body + - user_mail_status_activated_subject + - user_mail_status_activated_body + - user_mail_status_blocked_subject + - user_mail_status_blocked_body + - user_mail_status_canceled_subject + - user_mail_status_canceled_body +process: + langcode: language + 'cancel_confirm/subject': + plugin: convert_tokens + source: user_mail_cancel_confirm_subject + 'cancel_confirm/body': + plugin: convert_tokens + source: user_mail_cancel_confirm_body + 'password_reset/subject': + plugin: convert_tokens + source: user_mail_password_reset_subject + 'password_reset/body': + plugin: convert_tokens + source: user_mail_password_reset_body + 'register_admin_created/subject': + plugin: convert_tokens + source: user_mail_register_admin_created_subject + 'register_admin_created/body': + plugin: convert_tokens + source: user_mail_register_admin_created_body + 'register_no_approval_required/subject': + plugin: convert_tokens + source: user_mail_register_no_approval_required_subject + 'register_no_approval_required/body': + plugin: convert_tokens + source: user_mail_register_no_approval_required_body + 'register_pending_approval/subject': + plugin: convert_tokens + source: user_mail_register_pending_approval_subject + 'register_pending_approval/body': + plugin: convert_tokens + source: user_mail_register_pending_approval_body + 'status_activated/subject': + plugin: convert_tokens + source: user_mail_status_activated_subject + 'status_activated/body': + plugin: convert_tokens + source: user_mail_status_activated_body + 'status_blocked/subject': + plugin: convert_tokens + source: user_mail_status_blocked_subject + 'status_blocked/body': + plugin: convert_tokens + source: user_mail_status_blocked_body + 'status_canceled/subject': + plugin: convert_tokens + source: user_mail_status_canceled_subject + 'status_canceled/body': + plugin: convert_tokens + source: user_mail_status_canceled_body +destination: + plugin: config + config_name: user.mail + translations: true diff --git a/web/core/modules/config_translation/migrations/d7_user_settings_translation.yml b/web/core/modules/config_translation/migrations/d7_user_settings_translation.yml new file mode 100644 index 0000000000000000000000000000000000000000..56c3880b04f5907034856431b6cf918679ba12aa --- /dev/null +++ b/web/core/modules/config_translation/migrations/d7_user_settings_translation.yml @@ -0,0 +1,17 @@ +id: d7_user_settings_translation +label: User settings configuration translation +migration_tags: + - Drupal 7 + - Configuration + - Multilingual +source: + plugin: d7_variable_translation + variables: + - anonymous +process: + langcode: language + anonymous: anonymous +destination: + plugin: config + config_name: user.settings + translations: true diff --git a/web/core/modules/config_translation/src/FormElement/ElementInterface.php b/web/core/modules/config_translation/src/FormElement/ElementInterface.php index 936b5573a8d2356ccd7fda353638c1ec02ea3f10..8df5c013fbe0554d9d26676e55400216798bed6f 100644 --- a/web/core/modules/config_translation/src/FormElement/ElementInterface.php +++ b/web/core/modules/config_translation/src/FormElement/ElementInterface.php @@ -23,7 +23,7 @@ interface ElementInterface { public static function create(TypedDataInterface $schema); /** - * Builds a render array containg the source and translation form elements. + * Builds a render array containing the source and translation form elements. * * @param \Drupal\Core\Language\LanguageInterface $source_language * The source language of the configuration object. diff --git a/web/core/modules/config_translation/tests/src/Kernel/Migrate/d7/MigrateSystemMaintenanceTranslationTest.php b/web/core/modules/config_translation/tests/src/Kernel/Migrate/d7/MigrateSystemMaintenanceTranslationTest.php new file mode 100644 index 0000000000000000000000000000000000000000..df44e407d4594556e1787bf45d249051185c38f2 --- /dev/null +++ b/web/core/modules/config_translation/tests/src/Kernel/Migrate/d7/MigrateSystemMaintenanceTranslationTest.php @@ -0,0 +1,37 @@ +<?php + +namespace Drupal\Tests\config_translation\Kernel\Migrate\d7; + +use Drupal\Tests\migrate_drupal\Kernel\d7\MigrateDrupal7TestBase; + +/** + * Tests migrations of i18n maintenance variable. + * + * @group migrate_drupal_7 + */ +class MigrateSystemMaintenanceTranslationTest extends MigrateDrupal7TestBase { + + public static $modules = [ + 'language', + 'config_translation', + // Required for translation migrations. + 'migrate_drupal_multilingual', + ]; + + /** + * {@inheritdoc} + */ + protected function setUp() { + parent::setUp(); + $this->executeMigration('d7_system_maintenance_translation'); + } + + /** + * Tests migrations of i18n maintenance variable. + */ + public function testSystemMaintenance() { + $config = \Drupal::service('language_manager')->getLanguageConfigOverride('is', 'system.maintenance'); + $this->assertSame('is - This is a custom maintenance mode message.', $config->get('message')); + } + +} diff --git a/web/core/modules/config_translation/tests/src/Kernel/Migrate/d7/MigrateSystemSiteTranslationTest.php b/web/core/modules/config_translation/tests/src/Kernel/Migrate/d7/MigrateSystemSiteTranslationTest.php new file mode 100644 index 0000000000000000000000000000000000000000..e25a0f8fb9375664403d66eb582ffeb40c2efede --- /dev/null +++ b/web/core/modules/config_translation/tests/src/Kernel/Migrate/d7/MigrateSystemSiteTranslationTest.php @@ -0,0 +1,54 @@ +<?php + +namespace Drupal\Tests\config_translation\Kernel\Migrate\d7; + +use Drupal\Tests\migrate_drupal\Kernel\d7\MigrateDrupal7TestBase; + +/** + * Migrate multilingual site variables. + * + * @group migrate_drupal_7 + */ +class MigrateSystemSiteTranslationTest extends MigrateDrupal7TestBase { + + /** + * {@inheritdoc} + */ + public static $modules = [ + 'language', + 'config_translation', + // Required for translation migrations. + 'migrate_drupal_multilingual', + ]; + + /** + * {@inheritdoc} + */ + protected function setUp() { + parent::setUp(); + $this->executeMigration('d7_system_site_translation'); + } + + /** + * Tests migration of system (site) variables to system.site.yml. + */ + public function testSystemSite() { + $language_manager = \Drupal::service('language_manager'); + $config_translation = $language_manager->getLanguageConfigOverride('fr', 'system.site'); + $this->assertSame('The Site Name', $config_translation->get('name')); + $this->assertSame('fr - The Slogan', $config_translation->get('slogan')); + $this->assertSame('node', $config_translation->get('page.403')); + $this->assertSame('node', $config_translation->get('page.404')); + $this->assertSame('node', $config_translation->get('page.front')); + $this->assertSame(NULL, $config_translation->get('admin_compact_mode')); + + $config_translation = $language_manager->getLanguageConfigOverride('is', 'system.site'); + $this->assertSame('is - The Site Name', $config_translation->get('name')); + $this->assertSame('is - The Slogan', $config_translation->get('slogan')); + $this->assertSame('node/1', $config_translation->get('page.403')); + $this->assertSame('node/6', $config_translation->get('page.404')); + $this->assertSame('node/4', $config_translation->get('page.front')); + $this->assertNULL($config_translation->get('admin_compact_mode')); + } + +} diff --git a/web/core/modules/config_translation/tests/src/Kernel/Migrate/d7/MigrateUserConfigsTranslationTest.php b/web/core/modules/config_translation/tests/src/Kernel/Migrate/d7/MigrateUserConfigsTranslationTest.php new file mode 100644 index 0000000000000000000000000000000000000000..85d6867bd4e7988a031d812bdfa9cc85a172147b --- /dev/null +++ b/web/core/modules/config_translation/tests/src/Kernel/Migrate/d7/MigrateUserConfigsTranslationTest.php @@ -0,0 +1,74 @@ +<?php + +namespace Drupal\Tests\config_translation\Kernel\Migrate\d7; + +use Drupal\Tests\SchemaCheckTestTrait; +use Drupal\Tests\migrate_drupal\Kernel\d7\MigrateDrupal7TestBase; + +/** + * Test migration of i18n user variables. + * + * @group migrate_drupal_7 + */ +class MigrateUserConfigsTranslationTest extends MigrateDrupal7TestBase { + + use SchemaCheckTestTrait; + + /** + * {@inheritdoc} + */ + public static $modules = [ + 'language', + 'locale', + 'config_translation', + // Required for translation migrations. + 'migrate_drupal_multilingual', + ]; + + /** + * {@inheritdoc} + */ + protected function setUp() { + parent::setUp(); + $this->installSchema('locale', [ + 'locales_source', + 'locales_target', + 'locales_location', + ]); + $this->executeMigrations([ + 'd7_user_mail_translation', + 'd7_user_settings_translation', + ]); + } + + /** + * Tests migration of i18n user variables to user.mail and user.settings. + */ + public function testUserConfig() { + // Tests migration of i18n user variables to user.mail.yml. + $language_manager = \Drupal::service('language_manager'); + $config = $language_manager->getLanguageConfigOverride('is', 'user.mail'); + $this->assertSame('is - Are you sure?', $config->get('cancel_confirm.subject')); + $this->assertSame('is - A little birdie said you wanted to cancel your account.', $config->get('cancel_confirm.body')); + $this->assertSame('is - Fix your password', $config->get('password_reset.subject')); + $this->assertSame("is - Nope! You're locked out forever.", $config->get('password_reset.body')); + $this->assertSame('is - Gawd made you an account', $config->get('register_admin_created.subject')); + $this->assertSame("is - ...and she could take it away.\r\n[site:name], [site:url]", $config->get('register_admin_created.body')); + $this->assertSame('is - Welcome!', $config->get('register_no_approval_required.subject')); + $this->assertSame('is - You can now log in if you can figure out how to use Drupal!', $config->get('register_no_approval_required.body')); + $this->assertSame('is - Soon...', $config->get('register_pending_approval.subject')); + $this->assertSame('is - ...you will join our Circle. Let the Drupal flow through you.', $config->get('register_pending_approval.body')); + $this->assertSame('is - Your account is approved!', $config->get('status_activated.subject')); + $this->assertSame('is - Your account was activated, and there was much rejoicing.', $config->get('status_activated.body')); + $this->assertSame('is - BEGONE!', $config->get('status_blocked.subject')); + $this->assertSame('is - You no longer please the robot overlords. Go to your room and chill out.', $config->get('status_blocked.body')); + $this->assertSame('is - So long, bub', $config->get('status_canceled.subject')); + $this->assertSame('is - The gates of Drupal are closed to you. Now you will work in the salt mines.', $config->get('status_canceled.body')); + $this->assertConfigSchema(\Drupal::service('config.typed'), 'user.mail', $config->get()); + + // Tests migration of i18n user variables to user.settings.yml. + $config = $language_manager->getLanguageConfigOverride('is', 'user.settings'); + $this->assertSame('is - anonymous', $config->get('anonymous')); + } + +} diff --git a/web/core/modules/contact/tests/src/Functional/ContactSitewideTest.php b/web/core/modules/contact/tests/src/Functional/ContactSitewideTest.php index 2c881b01806c6d1171b5e18644d08ae28b141156..1002d5ac55bf15a169b4cb7f34eb7dc4f09a7576 100644 --- a/web/core/modules/contact/tests/src/Functional/ContactSitewideTest.php +++ b/web/core/modules/contact/tests/src/Functional/ContactSitewideTest.php @@ -5,9 +5,9 @@ use Drupal\contact\Entity\ContactForm; use Drupal\Core\Mail\MailFormatHelper; use Drupal\Core\Test\AssertMailTrait; -use Drupal\field_ui\Tests\FieldUiTestTrait; use Drupal\Tests\BrowserTestBase; use Drupal\Core\Entity\EntityTypeInterface; +use Drupal\Tests\field_ui\Traits\FieldUiTestTrait; use Drupal\user\RoleInterface; /** diff --git a/web/core/modules/content_moderation/src/EntityOperations.php b/web/core/modules/content_moderation/src/EntityOperations.php index 9ab40eac05691fb70202c4bbfb4f26377690d5a2..8c6d3325089840426b950cfebeaef7f20fe03ad8 100644 --- a/web/core/modules/content_moderation/src/EntityOperations.php +++ b/web/core/modules/content_moderation/src/EntityOperations.php @@ -184,11 +184,16 @@ protected function updateOrCreateFromEntity(EntityInterface $entity) { // Sync translations. if ($entity->getEntityType()->hasKey('langcode')) { $entity_langcode = $entity->language()->getId(); - if (!$content_moderation_state->hasTranslation($entity_langcode)) { - $content_moderation_state->addTranslation($entity_langcode); + if ($entity->isDefaultTranslation()) { + $content_moderation_state->langcode = $entity_langcode; } - if ($content_moderation_state->language()->getId() !== $entity_langcode) { - $content_moderation_state = $content_moderation_state->getTranslation($entity_langcode); + else { + if (!$content_moderation_state->hasTranslation($entity_langcode)) { + $content_moderation_state->addTranslation($entity_langcode); + } + if ($content_moderation_state->language()->getId() !== $entity_langcode) { + $content_moderation_state = $content_moderation_state->getTranslation($entity_langcode); + } } } diff --git a/web/core/modules/content_moderation/src/Plugin/Field/FieldWidget/ModerationStateWidget.php b/web/core/modules/content_moderation/src/Plugin/Field/FieldWidget/ModerationStateWidget.php index 8a33c76ed8a8d802060f6bf3e1b800940cf249b3..0d4c43a3334329358e97854b33858d834923da75 100644 --- a/web/core/modules/content_moderation/src/Plugin/Field/FieldWidget/ModerationStateWidget.php +++ b/web/core/modules/content_moderation/src/Plugin/Field/FieldWidget/ModerationStateWidget.php @@ -127,7 +127,7 @@ public function formElement(FieldItemListInterface $items, $delta, array $elemen $transitions = $this->validator->getValidTransitions($entity, $this->currentUser); $transition_labels = []; - $default_value = NULL; + $default_value = $items->value; foreach ($transitions as $transition) { $transition_to_state = $transition->to(); $transition_labels[$transition_to_state->id()] = $transition_to_state->label(); diff --git a/web/core/modules/content_moderation/src/Plugin/Field/ModerationStateFieldItemList.php b/web/core/modules/content_moderation/src/Plugin/Field/ModerationStateFieldItemList.php index c33ccacdeec1e692effaab457e3c280d21fe9cfa..357c60c9b300e40db3153395059309174519edf6 100644 --- a/web/core/modules/content_moderation/src/Plugin/Field/ModerationStateFieldItemList.php +++ b/web/core/modules/content_moderation/src/Plugin/Field/ModerationStateFieldItemList.php @@ -16,7 +16,6 @@ class ModerationStateFieldItemList extends FieldItemList { use ComputedItemListTrait { - ensureComputedValue as traitEnsureComputedValue; get as traitGet; } @@ -34,19 +33,6 @@ protected function computeValue() { } } - /** - * {@inheritdoc} - */ - protected function ensureComputedValue() { - // If the moderation state field is set to an empty value, always recompute - // the state. Empty is not a valid moderation state value, when none is - // present the default state is used. - if (!isset($this->list[0]) || $this->list[0]->isEmpty()) { - $this->valueComputed = FALSE; - } - $this->traitEnsureComputedValue(); - } - /** * Gets the moderation state ID linked to a content entity revision. * @@ -107,7 +93,7 @@ protected function loadContentModerationStateRevision(ContentEntityInterface $en if ($entity->getEntityType()->hasKey('langcode')) { $langcode = $entity->language()->getId(); if (!$content_moderation_state->hasTranslation($langcode)) { - $content_moderation_state->addTranslation($langcode); + $content_moderation_state->addTranslation($langcode, $content_moderation_state->toArray()); } if ($content_moderation_state->language()->getId() !== $langcode) { $content_moderation_state = $content_moderation_state->getTranslation($langcode); @@ -140,10 +126,8 @@ public function onChange($delta) { */ public function setValue($values, $notify = TRUE) { parent::setValue($values, $notify); + $this->valueComputed = TRUE; - if (isset($this->list[0])) { - $this->valueComputed = TRUE; - } // If the parent created a field item and if the parent should be notified // about the change (e.g. this is not initialized with the current value), // update the moderated entity. diff --git a/web/core/modules/content_moderation/src/Plugin/Validation/Constraint/ModerationStateConstraintValidator.php b/web/core/modules/content_moderation/src/Plugin/Validation/Constraint/ModerationStateConstraintValidator.php index c3b9c815fe05d156ec6216b3404a8290e41e5d04..7894cadf752c21eded941e73389fbd00efdfe69b 100644 --- a/web/core/modules/content_moderation/src/Plugin/Validation/Constraint/ModerationStateConstraintValidator.php +++ b/web/core/modules/content_moderation/src/Plugin/Validation/Constraint/ModerationStateConstraintValidator.php @@ -9,6 +9,7 @@ use Drupal\Core\Entity\EntityTypeManagerInterface; use Drupal\content_moderation\ModerationInformationInterface; use Drupal\Core\Session\AccountInterface; +use Drupal\Core\Validation\Plugin\Validation\Constraint\NotNullConstraint; use Symfony\Component\DependencyInjection\ContainerInterface; use Symfony\Component\Validator\Constraint; use Symfony\Component\Validator\ConstraintValidator; @@ -89,6 +90,13 @@ public function validate($value, Constraint $constraint) { return; } + // If the entity is moderated and the item list is empty, ensure users see + // the same required message as typical NotNull constraints. + if ($value->isEmpty()) { + $this->context->addViolation((new NotNullConstraint())->message); + return; + } + $workflow = $this->moderationInformation->getWorkflowForEntity($entity); if (!$workflow->getTypePlugin()->hasState($entity->moderation_state->value)) { diff --git a/web/core/modules/content_moderation/tests/src/Functional/ModerationContentTranslationTest.php b/web/core/modules/content_moderation/tests/src/Functional/ModerationContentTranslationTest.php new file mode 100644 index 0000000000000000000000000000000000000000..4afa97de6f4c8f1744f77acb8463d514e1daf1db --- /dev/null +++ b/web/core/modules/content_moderation/tests/src/Functional/ModerationContentTranslationTest.php @@ -0,0 +1,109 @@ +<?php + +namespace Drupal\Tests\content_moderation\Functional; + +use Drupal\Tests\BrowserTestBase; +use Drupal\Tests\content_moderation\Traits\ContentModerationTestTrait; + +/** + * Test content_moderation functionality with content_translation. + * + * @group content_moderation + */ +class ModerationContentTranslationTest extends BrowserTestBase { + + use ContentModerationTestTrait; + + /** + * A user with permission to bypass access content. + * + * @var \Drupal\Core\Session\AccountInterface + */ + protected $adminUser; + + /** + * Modules to enable. + * + * @var array + */ + public static $modules = [ + 'node', + 'locale', + 'content_translation', + ]; + + /** + * {@inheritdoc} + */ + protected function setUp() { + parent::setUp(); + $this->drupalLogin($this->rootUser); + // Create an Article content type. + $this->drupalCreateContentType(['type' => 'article', 'name' => 'Article'])->save(); + $edit = [ + 'predefined_langcode' => 'fr', + ]; + $this->drupalPostForm('admin/config/regional/language/add', $edit, 'Add language'); + // Enable content translation on articles. + $this->drupalGet('admin/config/regional/content-language'); + $edit = [ + 'entity_types[node]' => TRUE, + 'settings[node][article][translatable]' => TRUE, + 'settings[node][article][settings][language][language_alterable]' => TRUE, + ]; + $this->drupalPostForm(NULL, $edit, 'Save configuration'); + // Adding languages requires a container rebuild in the test running + // environment so that multilingual services are used. + $this->rebuildContainer(); + } + + /** + * Tests existing translations being edited after enabling content moderation. + */ + public function testModerationWithExistingContent() { + // Create a published article in English. + $edit = [ + 'title[0][value]' => 'Published English node', + 'langcode[0][value]' => 'en', + ]; + $this->drupalPostForm('node/add/article', $edit, 'Save'); + $this->assertSession()->pageTextContains('Article Published English node has been created.'); + $english_node = $this->drupalGetNodeByTitle('Published English node'); + + // Add a French translation. + $this->drupalGet('node/' . $english_node->id() . '/translations'); + $this->clickLink('Add'); + $edit = [ + 'title[0][value]' => 'Published French node', + ]; + $this->drupalPostForm(NULL, $edit, 'Save (this translation)'); + $this->assertSession()->pageTextContains('Article Published French node has been updated.'); + + // Install content moderation and enable moderation on Article node type. + \Drupal::service('module_installer')->install(['content_moderation']); + $workflow = $this->createEditorialWorkflow(); + $workflow->getTypePlugin()->addEntityTypeAndBundle('node', 'article'); + $workflow->save(); + $this->drupalLogin($this->rootUser); + + // Edit the English node. + $this->drupalGet('node/' . $english_node->id() . '/edit'); + $this->assertSession()->statusCodeEquals(200); + $edit = [ + 'title[0][value]' => 'Published English new node', + ]; + $this->drupalPostForm(NULL, $edit, 'Save'); + $this->assertSession()->statusCodeEquals(200); + $this->assertSession()->pageTextContains('Article Published English new node has been updated.'); + // Edit the French translation. + $this->drupalGet('fr/node/' . $english_node->id() . '/edit'); + $this->assertSession()->statusCodeEquals(200); + $edit = [ + 'title[0][value]' => 'Published French new node', + ]; + $this->drupalPostForm(NULL, $edit, 'Save (this translation)'); + $this->assertSession()->statusCodeEquals(200); + $this->assertSession()->pageTextContains('Article Published French new node has been updated.'); + } + +} diff --git a/web/core/modules/content_moderation/tests/src/Kernel/ContentModerationStateTest.php b/web/core/modules/content_moderation/tests/src/Kernel/ContentModerationStateTest.php index 8574ad6a171b4c60ce082132835b0b084090e862..4b7d75be4dba4ab2db6258bccb6912c1650fee8d 100644 --- a/web/core/modules/content_moderation/tests/src/Kernel/ContentModerationStateTest.php +++ b/web/core/modules/content_moderation/tests/src/Kernel/ContentModerationStateTest.php @@ -296,7 +296,7 @@ public function testMultilingualModeration() { // Create a French translation. $french_node = $english_node->addTranslation('fr', ['title' => 'French title']); $french_node->setUnpublished(); - // Revision 1 (fr). + // Revision 2 (fr). $french_node->save(); $french_node = $this->reloadEntity($english_node)->getTranslation('fr'); $this->assertEquals('draft', $french_node->moderation_state->value); @@ -305,7 +305,7 @@ public function testMultilingualModeration() { // Move English node to create another draft. $english_node = $this->reloadEntity($english_node); $english_node->moderation_state->value = 'draft'; - // Revision 2 (en, fr). + // Revision 3 (en, fr). $english_node->save(); $english_node = $this->reloadEntity($english_node); $this->assertEquals('draft', $english_node->moderation_state->value); @@ -316,7 +316,7 @@ public function testMultilingualModeration() { // Publish the French node. $french_node->moderation_state->value = 'published'; - // Revision 3 (en, fr). + // Revision 4 (en, fr). $french_node->save(); $french_node = $this->reloadEntity($french_node)->getTranslation('fr'); $this->assertTrue($french_node->isPublished()); @@ -327,7 +327,7 @@ public function testMultilingualModeration() { // Publish the English node. $english_node->moderation_state->value = 'published'; - // Revision 4 (en, fr). + // Revision 5 (en, fr). $english_node->save(); $english_node = $this->reloadEntity($english_node); $this->assertTrue($english_node->isPublished()); @@ -336,15 +336,15 @@ public function testMultilingualModeration() { $french_node = $this->reloadEntity($english_node)->getTranslation('fr'); $this->assertTrue($french_node->isPublished()); $french_node->moderation_state->value = 'draft'; - // Revision 5 (en, fr). + // Revision 6 (en, fr). $french_node->save(); - $french_node = $this->reloadEntity($english_node, 5)->getTranslation('fr'); + $french_node = $this->reloadEntity($english_node, 6)->getTranslation('fr'); $this->assertFalse($french_node->isPublished()); $this->assertTrue($french_node->getTranslation('en')->isPublished()); // Republish the French node. $french_node->moderation_state->value = 'published'; - // Revision 6 (en, fr). + // Revision 7 (en, fr). $french_node->save(); $french_node = $this->reloadEntity($english_node)->getTranslation('fr'); $this->assertTrue($french_node->isPublished()); @@ -353,7 +353,7 @@ public function testMultilingualModeration() { $content_moderation_state = ContentModerationState::load(1); $content_moderation_state->set('moderation_state', 'draft'); $content_moderation_state->setNewRevision(TRUE); - // Revision 7 (en, fr). + // Revision 8 (en, fr). $content_moderation_state->save(); $english_node = $this->reloadEntity($french_node, $french_node->getRevisionId() + 1); @@ -366,12 +366,12 @@ public function testMultilingualModeration() { $content_moderation_state = $content_moderation_state->getTranslation('fr'); $content_moderation_state->set('moderation_state', 'draft'); $content_moderation_state->setNewRevision(TRUE); - // Revision 8 (en, fr). + // Revision 9 (en, fr). $content_moderation_state->save(); $english_node = $this->reloadEntity($english_node, $english_node->getRevisionId()); $this->assertEquals('draft', $english_node->moderation_state->value); - $french_node = $this->reloadEntity($english_node, '8')->getTranslation('fr'); + $french_node = $this->reloadEntity($english_node, '9')->getTranslation('fr'); $this->assertEquals('draft', $french_node->moderation_state->value); // Switching the moderation state to an unpublished state should update the // entity. @@ -380,7 +380,7 @@ public function testMultilingualModeration() { // Get the default english node. $english_node = $this->reloadEntity($english_node); $this->assertTrue($english_node->isPublished()); - $this->assertEquals(6, $english_node->getRevisionId()); + $this->assertEquals(7, $english_node->getRevisionId()); } /** @@ -416,25 +416,83 @@ public function testModerationWithFieldConfigOverride() { /** * Tests that entities with special languages can be moderated. + * + * @dataProvider moderationWithSpecialLanguagesTestCases */ - public function testModerationWithSpecialLanguages() { + public function testModerationWithSpecialLanguages($original_language, $updated_language) { $workflow = $this->createEditorialWorkflow(); $workflow->getTypePlugin()->addEntityTypeAndBundle('entity_test_rev', 'entity_test_rev'); $workflow->save(); // Create a test entity. $entity = EntityTestRev::create([ - 'langcode' => LanguageInterface::LANGCODE_NOT_SPECIFIED, + 'langcode' => $original_language, ]); $entity->save(); $this->assertEquals('draft', $entity->moderation_state->value); $entity->moderation_state->value = 'published'; + $entity->langcode = $updated_language; $entity->save(); $this->assertEquals('published', EntityTestRev::load($entity->id())->moderation_state->value); } + /** + * Test cases for ::testModerationWithSpecialLanguages(). + */ + public function moderationWithSpecialLanguagesTestCases() { + return [ + 'Not specified to not specified' => [ + LanguageInterface::LANGCODE_NOT_SPECIFIED, + LanguageInterface::LANGCODE_NOT_SPECIFIED, + ], + 'English to not specified' => [ + 'en', + LanguageInterface::LANGCODE_NOT_SPECIFIED, + ], + 'Not specified to english' => [ + LanguageInterface::LANGCODE_NOT_SPECIFIED, + 'en', + ], + ]; + } + + /** + * Test changing the language of content without adding a translation. + */ + public function testChangingContentLangcode() { + ConfigurableLanguage::createFromLangcode('fr')->save(); + NodeType::create([ + 'type' => 'test_type', + ])->save(); + $workflow = $this->createEditorialWorkflow(); + $workflow->getTypePlugin()->addEntityTypeAndBundle('node', 'test_type'); + $workflow->save(); + + $entity = Node::create([ + 'title' => 'Test node', + 'langcode' => 'en', + 'type' => 'test_type', + ]); + $entity->save(); + + $content_moderation_state = ContentModerationState::loadFromModeratedEntity($entity); + $this->assertCount(1, $entity->getTranslationLanguages()); + $this->assertCount(1, $content_moderation_state->getTranslationLanguages()); + $this->assertEquals('en', $entity->langcode->value); + $this->assertEquals('en', $content_moderation_state->langcode->value); + + $entity->langcode = 'fr'; + $entity->save(); + + $content_moderation_state = ContentModerationState::loadFromModeratedEntity($entity); + $this->assertCount(1, $entity->getTranslationLanguages()); + $this->assertCount(1, $content_moderation_state->getTranslationLanguages()); + $this->assertEquals('fr', $entity->langcode->value); + $this->assertEquals('fr', $content_moderation_state->langcode->value); + } + /** * Tests that a non-translatable entity type with a langcode can be moderated. */ diff --git a/web/core/modules/content_moderation/tests/src/Kernel/ModerationStateFieldItemListTest.php b/web/core/modules/content_moderation/tests/src/Kernel/ModerationStateFieldItemListTest.php index af0bb4fd7d6de24f053d62005141ab6b633dacc2..0c8db872a5597cc3fdbe07115ef728bfc661d91d 100644 --- a/web/core/modules/content_moderation/tests/src/Kernel/ModerationStateFieldItemListTest.php +++ b/web/core/modules/content_moderation/tests/src/Kernel/ModerationStateFieldItemListTest.php @@ -3,9 +3,11 @@ namespace Drupal\Tests\content_moderation\Kernel; use Drupal\KernelTests\KernelTestBase; +use Drupal\language\Entity\ConfigurableLanguage; use Drupal\node\Entity\Node; use Drupal\node\Entity\NodeType; use Drupal\Tests\content_moderation\Traits\ContentModerationTestTrait; +use Drupal\workflows\Entity\Workflow; /** * @coversDefaultClass \Drupal\content_moderation\Plugin\Field\ModerationStateFieldItemList @@ -64,6 +66,8 @@ protected function setUp() { $this->testNode->save(); \Drupal::entityTypeManager()->getStorage('node')->resetCache(); $this->testNode = Node::load($this->testNode->id()); + + ConfigurableLanguage::createFromLangcode('de')->save(); } /** @@ -102,20 +106,70 @@ public function testGet() { } /** - * Tests the computed field when it is unset or set to an empty value. + * Tests the item list when it is emptied and appended to. + */ + public function testEmptyStateAndAppend() { + // This test case mimics the lifecycle of an entity that is being patched in + // a rest resource. + $this->testNode->moderation_state->setValue([]); + $this->assertTrue($this->testNode->moderation_state->isEmpty()); + $this->assertEmptiedModerationFieldItemList(); + + $this->testNode->moderation_state->appendItem(); + $this->assertEquals(1, $this->testNode->moderation_state->count()); + $this->assertEquals(NULL, $this->testNode->moderation_state->value); + $this->assertEmptiedModerationFieldItemList(); + } + + /** + * Test an empty value assigned to the field item. */ - public function testSetEmptyState() { + public function testEmptyFieldItem() { $this->testNode->moderation_state->value = ''; - $this->assertEquals('draft', $this->testNode->moderation_state->value); + $this->assertEquals('', $this->testNode->moderation_state->value); + $this->assertEmptiedModerationFieldItemList(); + } + /** + * Test an empty value assigned to the field item list. + */ + public function testEmptyFieldItemList() { $this->testNode->moderation_state = ''; - $this->assertEquals('draft', $this->testNode->moderation_state->value); + $this->assertEquals('', $this->testNode->moderation_state->value); + $this->assertEmptiedModerationFieldItemList(); + } + /** + * Test the field item when it is unset. + */ + public function testUnsetItemList() { unset($this->testNode->moderation_state); - $this->assertEquals('draft', $this->testNode->moderation_state->value); + $this->assertEquals(NULL, $this->testNode->moderation_state->value); + $this->assertEmptiedModerationFieldItemList(); + } + /** + * Test the field item when it is assigned NULL. + */ + public function testAssignNullItemList() { $this->testNode->moderation_state = NULL; - $this->assertEquals('draft', $this->testNode->moderation_state->value); + $this->assertEquals(NULL, $this->testNode->moderation_state->value); + $this->assertEmptiedModerationFieldItemList(); + } + + /** + * Assert the set of expectations when the moderation state field is emptied. + */ + protected function assertEmptiedModerationFieldItemList() { + $this->assertTrue($this->testNode->moderation_state->isEmpty()); + // Test the empty value causes a violation in the entity. + $violations = $this->testNode->validate(); + $this->assertCount(1, $violations); + $this->assertEquals('This value should not be null.', $violations->get(0)->getMessage()); + // Test that incorrectly saving the entity regardless will not produce a + // change in the moderation state. + $this->testNode->save(); + $this->assertEquals('draft', Node::load($this->testNode->id())->moderation_state->value); } /** @@ -131,6 +185,7 @@ public function testNonModeratedEntity() { $unmoderated_node->moderation_state = NULL; $this->assertEquals(0, $unmoderated_node->moderation_state->count()); + $this->assertCount(0, $unmoderated_node->validate()); } /** @@ -281,4 +336,37 @@ public function moderatedEntityWithExistingIdTestCases() { ]; } + /** + * Test the field item list when used with existing unmoderated content. + */ + public function testWithExistingUnmoderatedContent() { + $node = Node::create([ + 'title' => 'Test title', + 'type' => 'unmoderated', + ]); + $node->save(); + $translation = $node->addTranslation('de', $node->toArray()); + $translation->title = 'Translated'; + $translation->save(); + + $workflow = Workflow::load('editorial'); + $workflow->getTypePlugin()->addEntityTypeAndBundle('node', 'unmoderated'); + $workflow->save(); + + // After enabling moderation, both the original node and translation should + // have a published moderation state. + $node = Node::load($node->id()); + $translation = $node->getTranslation('de'); + $this->assertEquals('published', $node->moderation_state->value); + $this->assertEquals('published', $translation->moderation_state->value); + + // After the node has been updated, both the original node and translation + // should still have a value. + $node->title = 'Updated title'; + $node->save(); + $translation = $node->getTranslation('de'); + $this->assertEquals('published', $node->moderation_state->value); + $this->assertEquals('published', $translation->moderation_state->value); + } + } diff --git a/web/core/modules/content_translation/migrations/d6_taxonomy_term_localized_translation.yml b/web/core/modules/content_translation/migrations/d6_taxonomy_term_localized_translation.yml new file mode 100644 index 0000000000000000000000000000000000000000..980baf4ae6a994a73a9a2a11c61f4cb48314655c --- /dev/null +++ b/web/core/modules/content_translation/migrations/d6_taxonomy_term_localized_translation.yml @@ -0,0 +1,44 @@ +id: d6_taxonomy_term_localized_translation +label: Taxonomy localized term translations +migration_tags: + - Drupal 6 + - Content + - Multilingual +source: + plugin: d6_term_localized_translation + translations: true +process: + # If you are using this file to build a custom migration consider removing + # the tid field to allow incremental migrations. + tid: tid + langcode: language + vid: + plugin: migration + migration: d6_taxonomy_vocabulary + source: vid + name: + - + plugin: callback + source: + - name_translated + - name + callable: array_filter + - + plugin: callback + callable: current + description: + - + plugin: callback + source: + - description_translated + - description + callable: array_filter + - + plugin: callback + callable: current +destination: + plugin: entity:taxonomy_term + translations: true +migration_dependencies: + required: + - d6_taxonomy_term diff --git a/web/core/modules/content_translation/migrations/d7_block_translation.yml b/web/core/modules/content_translation/migrations/d7_block_translation.yml new file mode 100644 index 0000000000000000000000000000000000000000..a664ec17f391ef9850cd33597cf318b6bb28237d --- /dev/null +++ b/web/core/modules/content_translation/migrations/d7_block_translation.yml @@ -0,0 +1,77 @@ +id: d7_block_translation +label: Block translation +migration_tags: + - Drupal 7 + - Configuration + - Multilingual +source: + plugin: d7_block_translation + constants: + dest_label: 'settings/label' +process: + multilingual: + plugin: skip_on_empty + source: i18n_mode + method: row + langcode: language + property: constants/dest_label + translation: translation + id: + - + plugin: migration_lookup + migration: d7_block + source: + - module + - delta + - + plugin: skip_on_empty + method: row + # The plugin process is copied from d7_block.yml + plugin: + - + plugin: static_map + bypass: true + source: + - module + - delta + map: + book: + navigation: book_navigation + comment: + recent: views_block:comments_recent-block_1 + forum: + active: forum_active_block + new: forum_new_block + # locale: + # 0: language_block + node: + syndicate: node_syndicate_block + search: + form: search_form_block + statistics: + popular: statistics_popular_block + system: + main: system_main_block + 'powered-by': system_powered_by_block + user: + login: user_login_block + # 1: system_menu_block:tools + new: views_block:who_s_new-block_1 + online: views_block:who_s_online-who_s_online_block + - + plugin: block_plugin_id + - + plugin: skip_on_empty + method: row + # The theme process is copied from d7_block.yml + theme: + plugin: block_theme + source: + - theme + - default_theme + - admin_theme +destination: + plugin: entity:block +migration_dependencies: + optional: + - d7_block diff --git a/web/core/modules/content_translation/migrations/d7_comment_entity_translation.yml b/web/core/modules/content_translation/migrations/d7_comment_entity_translation.yml new file mode 100644 index 0000000000000000000000000000000000000000..c3a8052f31d73dbf6fc5acd86f29b823ceb47b28 --- /dev/null +++ b/web/core/modules/content_translation/migrations/d7_comment_entity_translation.yml @@ -0,0 +1,28 @@ +id: d7_comment_entity_translation +label: Comment entity translations +migration_tags: + - Drupal 7 + - translation + - Content +class: Drupal\comment\Plugin\migrate\D7Comment +source: + plugin: d7_comment_entity_translation +process: + cid: entity_id + subject: subject + langcode: language + uid: uid + status: status + created: created + changed: changed + content_translation_source: source + content_translation_outdated: translate +destination: + plugin: entity:comment + translations: true + destination_module: content_translation +migration_dependencies: + required: + - language + - d7_entity_translation_settings + - d7_comment diff --git a/web/core/modules/content_translation/migrations/d7_custom_block_translation.yml b/web/core/modules/content_translation/migrations/d7_custom_block_translation.yml new file mode 100644 index 0000000000000000000000000000000000000000..32ed6582fdedf9600082e099236227a66134f8f7 --- /dev/null +++ b/web/core/modules/content_translation/migrations/d7_custom_block_translation.yml @@ -0,0 +1,50 @@ +id: d7_custom_block_translation +label: Custom block translations +migration_tags: + - Drupal 7 + - Content + - Multilingual +source: + plugin: d7_block_custom_translation +process: + id: + plugin: migration_lookup + migration: d7_custom_block + source: + - bid + langcode: language + info: + - + plugin: callback + source: + - title_translated + - title + callable: array_filter + - + plugin: callback + callable: current + 'body/value': + - + plugin: callback + source: + - body_translated + - body + callable: array_filter + - + plugin: callback + callable: current + 'body/format': + plugin: migration_lookup + migration: d7_filter_format + source: format +destination: + plugin: entity:block_content + no_stub: true + translations: true + destination_module: content_translation +migration_dependencies: + required: + - d7_filter_format + - block_content_body_field + - d7_custom_block + - language diff --git a/web/core/modules/node/migrations/d7_node_entity_translation.yml b/web/core/modules/content_translation/migrations/d7_node_entity_translation.yml similarity index 80% rename from web/core/modules/node/migrations/d7_node_entity_translation.yml rename to web/core/modules/content_translation/migrations/d7_node_entity_translation.yml index 80c5c504201044ea71d7b576437c1123950c18ed..612c1f2f65641f4d061d3e8e17e2c7fc6ee4e655 100644 --- a/web/core/modules/node/migrations/d7_node_entity_translation.yml +++ b/web/core/modules/content_translation/migrations/d7_node_entity_translation.yml @@ -23,10 +23,14 @@ process: revision_log: log revision_timestamp: timestamp content_translation_source: source + # Boolean indicating whether this translation needs to be updated. + content_translation_outdated: translate destination: plugin: entity:node translations: true destination_module: content_translation migration_dependencies: required: + - language + - d7_entity_translation_settings - d7_node diff --git a/web/core/modules/content_translation/migrations/d7_taxonomy_term_entity_translation.yml b/web/core/modules/content_translation/migrations/d7_taxonomy_term_entity_translation.yml new file mode 100644 index 0000000000000000000000000000000000000000..f4ab6731bfa20e1318a96391557e8c4c3181e80a --- /dev/null +++ b/web/core/modules/content_translation/migrations/d7_taxonomy_term_entity_translation.yml @@ -0,0 +1,32 @@ +id: d7_taxonomy_term_entity_translation +label: Taxonomy term entity translations +migration_tags: + - Drupal 7 + - translation + - Content + - Multilingual +deriver: Drupal\taxonomy\Plugin\migrate\D7TaxonomyTermDeriver +source: + plugin: d7_taxonomy_term_entity_translation +process: + tid: entity_id + name: name + description/value: description + description/format: format + langcode: language + status: status + content_translation_source: source + content_translation_outdated: translate + content_translation_uid: uid + content_translation_created: created + changed: changed + forum_container: is_container +destination: + plugin: entity:taxonomy_term + translations: true + destination_module: content_translation +migration_dependencies: + required: + - language + - d7_entity_translation_settings + - d7_taxonomy_term diff --git a/web/core/modules/content_translation/src/Controller/ContentTranslationController.php b/web/core/modules/content_translation/src/Controller/ContentTranslationController.php index 3f5891b73a8514ffed987bb71e382c24c32c8c14..e5af1c31f43c0b309c600abcc26eba34b84c76ed 100644 --- a/web/core/modules/content_translation/src/Controller/ContentTranslationController.php +++ b/web/core/modules/content_translation/src/Controller/ContentTranslationController.php @@ -145,37 +145,14 @@ public function overview(RouteMatchInterface $route_match, $entity_type_id = NUL $translations = $entity->getTranslationLanguages(); } - $add_url = new Url( - "entity.$entity_type_id.content_translation_add", - [ - 'source' => $original, - 'target' => $language->getId(), - $entity_type_id => $entity->id(), - ], - [ - 'language' => $language, - ] - ); - $edit_url = new Url( - "entity.$entity_type_id.content_translation_edit", - [ - 'language' => $language->getId(), - $entity_type_id => $entity->id(), - ], - [ - 'language' => $language, - ] - ); - $delete_url = new Url( - "entity.$entity_type_id.content_translation_delete", - [ - 'language' => $language->getId(), - $entity_type_id => $entity->id(), - ], - [ - 'language' => $language, - ] - ); + $options = ['language' => $language]; + $add_url = $entity->toUrl('drupal:content-translation-add', $options) + ->setRouteParameter('source', $original) + ->setRouteParameter('target', $language->getId()); + $edit_url = $entity->toUrl('drupal:content-translation-edit', $options) + ->setRouteParameter('language', $language->getId()); + $delete_url = $entity->toUrl('drupal:content-translation-delete', $options) + ->setRouteParameter('language', $language->getId()); $operations = [ 'data' => [ '#type' => 'operations', diff --git a/web/core/modules/content_translation/src/Plugin/migrate/source/I18nQueryTrait.php b/web/core/modules/content_translation/src/Plugin/migrate/source/I18nQueryTrait.php new file mode 100644 index 0000000000000000000000000000000000000000..145cfb2caafba3924426bc811c6ea29b20ecabaf --- /dev/null +++ b/web/core/modules/content_translation/src/Plugin/migrate/source/I18nQueryTrait.php @@ -0,0 +1,87 @@ +<?php + +namespace Drupal\content_translation\Plugin\migrate\source; + +use Drupal\migrate\Plugin\MigrateIdMapInterface; +use Drupal\migrate\MigrateException; +use Drupal\migrate\Row; + +/** + * Gets an i18n translation from the source database. + */ +trait I18nQueryTrait { + + /** + * The i18n string table name. + * + * @var string + */ + protected $i18nStringTable; + + /** + * Gets the translation for the property not already in the row. + * + * For some i18n migrations there are two translation values, such as a + * translated title and a translated description, that need to be retrieved. + * Since these values are stored in separate rows of the i18nStringTable + * table we get them individually, one in the source plugin query() and the + * other in prepareRow(). The names of the properties varies, for example, + * in BoxTranslation they are 'body' and 'title' whereas in + * MenuLinkTranslation they are 'title' and 'description'. This will save both + * translations to the row. + * + * @param \Drupal\migrate\Row $row + * The current migration row which must include both a 'language' property + * and an 'objectid' property. The 'objectid' is the value for the + * 'objectid' field in the i18n_string table. + * @param string $property_not_in_row + * The name of the property to get the translation for. + * @param string $object_id_name + * The value of the objectid in the i18n table. + * @param \Drupal\migrate\Plugin\MigrateIdMapInterface $id_map + * The ID map. + * + * @return bool + * FALSE if the property has already been migrated. + * + * @throws \Drupal\migrate\MigrateException + */ + protected function getPropertyNotInRowTranslation(Row $row, $property_not_in_row, $object_id_name, MigrateIdMapInterface $id_map) { + $language = $row->getSourceProperty('language'); + if (!$language) { + throw new MigrateException('No language found.'); + } + $object_id = $row->getSourceProperty($object_id_name); + if (!$object_id) { + throw new MigrateException('No objectid found.'); + } + + // If this row has been migrated it is a duplicate so skip it. + if ($id_map->lookupDestinationIds([$object_id_name => $object_id, 'language' => $language])) { + return FALSE; + } + + // Save the translation for the property already in the row. + $property_in_row = $row->getSourceProperty('property'); + $row->setSourceProperty($property_in_row . '_translated', $row->getSourceProperty('translation')); + + // Get the translation, if one exists, for the property not already in the + // row. + $query = $this->select($this->i18nStringTable, 'i18n') + ->fields('i18n', ['lid']) + ->condition('i18n.property', $property_not_in_row) + ->condition('i18n.objectid', $object_id); + $query->leftJoin('locales_target', 'lt', 'i18n.lid = lt.lid'); + $query->condition('lt.language', $language); + $query->addField('lt', 'translation'); + $results = $query->execute()->fetchAssoc(); + if (!$results) { + $row->setSourceProperty($property_not_in_row . '_translated', NULL); + } + else { + $row->setSourceProperty($property_not_in_row . '_translated', $results['translation']); + } + return TRUE; + } + +} diff --git a/web/core/modules/content_translation/src/Routing/ContentTranslationRouteSubscriber.php b/web/core/modules/content_translation/src/Routing/ContentTranslationRouteSubscriber.php index fa1ac3bbf902a582ef2c2f40c2d3b5ef42ba3575..6cd3b350dfe80009660fc218409b9e638e5d4a0a 100644 --- a/web/core/modules/content_translation/src/Routing/ContentTranslationRouteSubscriber.php +++ b/web/core/modules/content_translation/src/Routing/ContentTranslationRouteSubscriber.php @@ -36,18 +36,6 @@ public function __construct(ContentTranslationManagerInterface $content_translat */ protected function alterRoutes(RouteCollection $collection) { foreach ($this->contentTranslationManager->getSupportedEntityTypes() as $entity_type_id => $entity_type) { - // Try to get the route from the current collection. - $link_template = $entity_type->getLinkTemplate('canonical'); - if (strpos($link_template, '/') !== FALSE) { - $base_path = '/' . $link_template; - } - else { - if (!$entity_route = $collection->get("entity.$entity_type_id.canonical")) { - continue; - } - $base_path = $entity_route->getPath(); - } - // Inherit admin route status from edit route, if exists. $is_admin = FALSE; $route_name = "entity.$entity_type_id.edit_form"; @@ -55,115 +43,122 @@ protected function alterRoutes(RouteCollection $collection) { $is_admin = (bool) $edit_route->getOption('_admin_route'); } - $path = $base_path . '/translations'; $load_latest_revision = ContentTranslationManager::isPendingRevisionSupportEnabled($entity_type_id); - $route = new Route( - $path, - [ - '_controller' => '\Drupal\content_translation\Controller\ContentTranslationController::overview', - 'entity_type_id' => $entity_type_id, - ], - [ - '_entity_access' => $entity_type_id . '.view', - '_access_content_translation_overview' => $entity_type_id, - ], - [ - 'parameters' => [ - $entity_type_id => [ - 'type' => 'entity:' . $entity_type_id, - 'load_latest_revision' => $load_latest_revision, - ], + if ($entity_type->hasLinkTemplate('drupal:content-translation-overview')) { + $route = new Route( + $entity_type->getLinkTemplate('drupal:content-translation-overview'), + [ + '_controller' => '\Drupal\content_translation\Controller\ContentTranslationController::overview', + 'entity_type_id' => $entity_type_id, + ], + [ + '_entity_access' => $entity_type_id . '.view', + '_access_content_translation_overview' => $entity_type_id, ], - '_admin_route' => $is_admin, - ] - ); - $route_name = "entity.$entity_type_id.content_translation_overview"; - $collection->add($route_name, $route); + [ + 'parameters' => [ + $entity_type_id => [ + 'type' => 'entity:' . $entity_type_id, + 'load_latest_revision' => $load_latest_revision, + ], + ], + '_admin_route' => $is_admin, + ] + ); + $route_name = "entity.$entity_type_id.content_translation_overview"; + $collection->add($route_name, $route); + } - $route = new Route( - $path . '/add/{source}/{target}', - [ - '_controller' => '\Drupal\content_translation\Controller\ContentTranslationController::add', - 'source' => NULL, - 'target' => NULL, - '_title' => 'Add', - 'entity_type_id' => $entity_type_id, + if ($entity_type->hasLinkTemplate('drupal:content-translation-add')) { + $route = new Route( + $entity_type->getLinkTemplate('drupal:content-translation-add'), + [ + '_controller' => '\Drupal\content_translation\Controller\ContentTranslationController::add', + 'source' => NULL, + 'target' => NULL, + '_title' => 'Add', + 'entity_type_id' => $entity_type_id, - ], - [ - '_entity_access' => $entity_type_id . '.view', - '_access_content_translation_manage' => 'create', - ], - [ - 'parameters' => [ - 'source' => [ - 'type' => 'language', - ], - 'target' => [ - 'type' => 'language', - ], - $entity_type_id => [ - 'type' => 'entity:' . $entity_type_id, - 'load_latest_revision' => $load_latest_revision, - ], ], - '_admin_route' => $is_admin, - ] - ); - $collection->add("entity.$entity_type_id.content_translation_add", $route); - - $route = new Route( - $path . '/edit/{language}', - [ - '_controller' => '\Drupal\content_translation\Controller\ContentTranslationController::edit', - 'language' => NULL, - '_title' => 'Edit', - 'entity_type_id' => $entity_type_id, - ], - [ - '_access_content_translation_manage' => 'update', - ], - [ - 'parameters' => [ - 'language' => [ - 'type' => 'language', - ], - $entity_type_id => [ - 'type' => 'entity:' . $entity_type_id, - 'load_latest_revision' => $load_latest_revision, - ], + [ + '_entity_access' => $entity_type_id . '.view', + '_access_content_translation_manage' => 'create', ], - '_admin_route' => $is_admin, - ] - ); - $collection->add("entity.$entity_type_id.content_translation_edit", $route); - - $route = new Route( - $path . '/delete/{language}', - [ - '_entity_form' => $entity_type_id . '.content_translation_deletion', - 'language' => NULL, - '_title' => 'Delete', - 'entity_type_id' => $entity_type_id, - ], - [ - '_access_content_translation_manage' => 'delete', - ], - [ - 'parameters' => [ - 'language' => [ - 'type' => 'language', + [ + 'parameters' => [ + 'source' => [ + 'type' => 'language', + ], + 'target' => [ + 'type' => 'language', + ], + $entity_type_id => [ + 'type' => 'entity:' . $entity_type_id, + 'load_latest_revision' => $load_latest_revision, + ], ], - $entity_type_id => [ - 'type' => 'entity:' . $entity_type_id, - 'load_latest_revision' => $load_latest_revision, + '_admin_route' => $is_admin, + ] + ); + $collection->add("entity.$entity_type_id.content_translation_add", $route); + } + + if ($entity_type->hasLinkTemplate('drupal:content-translation-edit')) { + $route = new Route( + $entity_type->getLinkTemplate('drupal:content-translation-edit'), + [ + '_controller' => '\Drupal\content_translation\Controller\ContentTranslationController::edit', + 'language' => NULL, + '_title' => 'Edit', + 'entity_type_id' => $entity_type_id, + ], + [ + '_access_content_translation_manage' => 'update', + ], + [ + 'parameters' => [ + 'language' => [ + 'type' => 'language', + ], + $entity_type_id => [ + 'type' => 'entity:' . $entity_type_id, + 'load_latest_revision' => $load_latest_revision, + ], ], + '_admin_route' => $is_admin, + ] + ); + $collection->add("entity.$entity_type_id.content_translation_edit", $route); + } + + if ($entity_type->hasLinkTemplate('drupal:content-translation-delete')) { + $route = new Route( + $entity_type->getLinkTemplate('drupal:content-translation-delete'), + [ + '_entity_form' => $entity_type_id . '.content_translation_deletion', + 'language' => NULL, + '_title' => 'Delete', + 'entity_type_id' => $entity_type_id, ], - '_admin_route' => $is_admin, - ] - ); - $collection->add("entity.$entity_type_id.content_translation_delete", $route); + [ + '_access_content_translation_manage' => 'delete', + ], + [ + 'parameters' => [ + 'language' => [ + 'type' => 'language', + ], + $entity_type_id => [ + 'type' => 'entity:' . $entity_type_id, + 'load_latest_revision' => $load_latest_revision, + ], + ], + '_admin_route' => $is_admin, + ] + ); + $collection->add("entity.$entity_type_id.content_translation_delete", $route); + } // Add our custom translation deletion access checker. if ($load_latest_revision) { diff --git a/web/core/modules/content_translation/tests/src/Kernel/ContentTranslationSyncUnitTest.php b/web/core/modules/content_translation/tests/src/Kernel/ContentTranslationSyncUnitTest.php index 5c4784aa62e601d3df9c171063b36144d1f8e9e1..01e1a0d374d37e3d66cef94551232f164b45f456 100644 --- a/web/core/modules/content_translation/tests/src/Kernel/ContentTranslationSyncUnitTest.php +++ b/web/core/modules/content_translation/tests/src/Kernel/ContentTranslationSyncUnitTest.php @@ -249,7 +249,7 @@ public function testDifferingSyncedColumns() { for ($delta = 0; $delta < $this->cardinality; $delta++) { foreach ($this->columns as $column) { // If the column is synchronized, the value should have been synced, - // for unsychronized columns, the value must not change. + // for unsynchronized columns, the value must not change. $expected_value = in_array($column, $this->synchronized) ? $changed_items[$delta][$column] : $this->unchangedFieldValues[$langcode][$delta][$column]; $this->assertEqual($field_values[$langcode][$delta][$column], $expected_value, "Differing Item $delta column $column for langcode $langcode synced correctly"); } diff --git a/web/core/modules/content_translation/tests/src/Kernel/Migrate/d6/MigrateTaxonomyTermTranslationTest.php b/web/core/modules/content_translation/tests/src/Kernel/Migrate/d6/MigrateTaxonomyTermTranslationTest.php index 3e32406d28db764bb783c90f2236ffe3ee039e88..1baf584efe01333b26aa04cef3780e1dc97430d8 100644 --- a/web/core/modules/content_translation/tests/src/Kernel/Migrate/d6/MigrateTaxonomyTermTranslationTest.php +++ b/web/core/modules/content_translation/tests/src/Kernel/Migrate/d6/MigrateTaxonomyTermTranslationTest.php @@ -108,7 +108,12 @@ protected function assertHierarchy($vid, $tid, array $parent_ids) { $this->assertArrayHasKey($tid, $this->treeData[$vid], "Term $tid exists in taxonomy tree"); $term = $this->treeData[$vid][$tid]; - $this->assertEquals($parent_ids, array_filter($term->parents), "Term $tid has correct parents in taxonomy tree"); + // PostgreSQL, MySQL and SQLite may not return the parent terms in the same + // order so sort before testing. + sort($parent_ids); + $actual_terms = array_filter($term->parents); + sort($actual_terms); + $this->assertEquals($parent_ids, $actual_terms, "Term $tid has correct parents in taxonomy tree"); } /** diff --git a/web/core/modules/contextual/js/contextual.es6.js b/web/core/modules/contextual/js/contextual.es6.js index f52059ae61c2cb6bdbfc3b32a235bac050e3a0e7..2b26ee2a8377131ff1ee6766b11ebc419c9460f9 100644 --- a/web/core/modules/contextual/js/contextual.es6.js +++ b/web/core/modules/contextual/js/contextual.es6.js @@ -99,7 +99,7 @@ // Set the destination parameter on each of the contextual links. const destination = `destination=${Drupal.encodePath( - drupalSettings.path.currentPath, + Drupal.url(drupalSettings.path.currentPath), )}`; $contextual.find('.contextual-links a').each(function() { const url = this.getAttribute('href'); diff --git a/web/core/modules/contextual/js/contextual.js b/web/core/modules/contextual/js/contextual.js index d51eba21a94445292907307279b31095932341df..6264b74c20999a0a529e3248ef6d756100ca657d 100644 --- a/web/core/modules/contextual/js/contextual.js +++ b/web/core/modules/contextual/js/contextual.js @@ -55,7 +55,7 @@ $contextual.html(html).addClass('contextual').prepend(Drupal.theme('contextualTrigger')); - var destination = 'destination=' + Drupal.encodePath(drupalSettings.path.currentPath); + var destination = 'destination=' + Drupal.encodePath(Drupal.url(drupalSettings.path.currentPath)); $contextual.find('.contextual-links a').each(function () { var url = this.getAttribute('href'); var glue = url.indexOf('?') === -1 ? '?' : '&'; diff --git a/web/core/modules/contextual/js/toolbar/views/AuralView.es6.js b/web/core/modules/contextual/js/toolbar/views/AuralView.es6.js index 3d343354e190f77cd21e6abd6eb983ec558d7d63..0fb25e17d8de6a1b1793de92da3121a20d9d01e7 100644 --- a/web/core/modules/contextual/js/toolbar/views/AuralView.es6.js +++ b/web/core/modules/contextual/js/toolbar/views/AuralView.es6.js @@ -96,9 +96,9 @@ * The keypress event. */ onKeypress(event) { - // The first tab key press is tracked so that an annoucement about tabbing - // constraints can be raised if edit mode is enabled when the page is - // loaded. + // The first tab key press is tracked so that an announcement about + // tabbing constraints can be raised if edit mode is enabled when the page + // is loaded. if ( !this.announcedOnce && event.keyCode === 9 && diff --git a/web/core/modules/contextual/tests/src/FunctionalJavascript/ContextualLinksTest.php b/web/core/modules/contextual/tests/src/FunctionalJavascript/ContextualLinksTest.php index 7435dada23f3810456a3bb1e8988f6f9457ac873..29d2ec7be5b88975e28f3c046b11adc078b9fa50 100644 --- a/web/core/modules/contextual/tests/src/FunctionalJavascript/ContextualLinksTest.php +++ b/web/core/modules/contextual/tests/src/FunctionalJavascript/ContextualLinksTest.php @@ -92,4 +92,19 @@ public function testContextualLinksClick() { $this->assertSession()->pageTextContains('Everything is contextual!'); } + /** + * Test the contextual links destination. + */ + public function testContextualLinksDestination() { + $this->grantPermissions(Role::load(Role::AUTHENTICATED_ID), [ + 'access contextual links', + 'administer blocks', + ]); + $this->drupalGet('user'); + $this->assertSession()->waitForElement('css', '.contextual button'); + $expected_destination_value = (string) $this->loggedInUser->toUrl()->toString(); + $contextual_link_url_parsed = parse_url($this->getSession()->getPage()->findLink('Configure block')->getAttribute('href')); + $this->assertEquals("destination=$expected_destination_value", $contextual_link_url_parsed['query']); + } + } diff --git a/web/core/modules/datetime/src/Plugin/Field/FieldFormatter/DateTimeTimeAgoFormatter.php b/web/core/modules/datetime/src/Plugin/Field/FieldFormatter/DateTimeTimeAgoFormatter.php index 294d40a5b8de69acdd827a6ec8d3dfea8fc28ea8..104ba39d0d37c3593644324bcbbeddbe1a2cb199 100644 --- a/web/core/modules/datetime/src/Plugin/Field/FieldFormatter/DateTimeTimeAgoFormatter.php +++ b/web/core/modules/datetime/src/Plugin/Field/FieldFormatter/DateTimeTimeAgoFormatter.php @@ -2,17 +2,9 @@ namespace Drupal\datetime\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; -use Drupal\Core\Form\FormStateInterface; -use Drupal\Core\Plugin\ContainerFactoryPluginInterface; -use Symfony\Component\HttpFoundation\Request; -use Symfony\Component\DependencyInjection\ContainerInterface; +use Drupal\Core\Field\Plugin\Field\FieldFormatter\TimestampAgoFormatter; /** * Plugin implementation of the 'Time ago' formatter for 'datetime' fields. @@ -25,80 +17,7 @@ * } * ) */ -class DateTimeTimeAgoFormatter extends FormatterBase implements ContainerFactoryPluginInterface { - - /** - * The date formatter service. - * - * @var \Drupal\Core\Datetime\DateFormatterInterface - */ - protected $dateFormatter; - - /** - * The current Request object. - * - * @var \Symfony\Component\HttpFoundation\Request - */ - protected $request; - - /** - * Constructs a DateTimeTimeAgoFormatter object. - * - * @param string $plugin_id - * The plugin_id for the formatter. - * @param mixed $plugin_definition - * The plugin implementation definition. - * @param \Drupal\Core\Field\FieldDefinitionInterface $field_definition - * The definition of the field to which the formatter is associated. - * @param array $settings - * The formatter settings. - * @param string $label - * The formatter label display setting. - * @param string $view_mode - * The view mode. - * @param array $third_party_settings - * Third party settings. - * @param \Drupal\Core\Datetime\DateFormatterInterface $date_formatter - * The date formatter service. - * @param \Symfony\Component\HttpFoundation\Request $request - * The current request. - */ - public function __construct($plugin_id, $plugin_definition, FieldDefinitionInterface $field_definition, array $settings, $label, $view_mode, array $third_party_settings, DateFormatterInterface $date_formatter, Request $request) { - parent::__construct($plugin_id, $plugin_definition, $field_definition, $settings, $label, $view_mode, $third_party_settings); - - $this->dateFormatter = $date_formatter; - $this->request = $request; - } - - /** - * {@inheritdoc} - */ - public static function defaultSettings() { - $settings = [ - 'future_format' => '@interval hence', - 'past_format' => '@interval ago', - 'granularity' => 2, - ] + parent::defaultSettings(); - - return $settings; - } - - /** - * {@inheritdoc} - */ - public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) { - return new static( - $plugin_id, - $plugin_definition, - $configuration['field_definition'], - $configuration['settings'], - $configuration['label'], - $configuration['view_mode'], - $configuration['third_party_settings'], - $container->get('date.formatter'), - $container->get('request_stack')->getCurrentRequest() - ); - } +class DateTimeTimeAgoFormatter extends TimestampAgoFormatter { /** * {@inheritdoc} @@ -118,50 +37,6 @@ public function viewElements(FieldItemListInterface $items, $langcode) { return $elements; } - /** - * {@inheritdoc} - */ - public function settingsForm(array $form, FormStateInterface $form_state) { - $form = parent::settingsForm($form, $form_state); - - $form['future_format'] = [ - '#type' => 'textfield', - '#title' => $this->t('Future format'), - '#default_value' => $this->getSetting('future_format'), - '#description' => $this->t('Use <em>@interval</em> where you want the formatted interval text to appear.'), - ]; - - $form['past_format'] = [ - '#type' => 'textfield', - '#title' => $this->t('Past format'), - '#default_value' => $this->getSetting('past_format'), - '#description' => $this->t('Use <em>@interval</em> where you want the formatted interval text to appear.'), - ]; - - $form['granularity'] = [ - '#type' => 'number', - '#title' => $this->t('Granularity'), - '#default_value' => $this->getSetting('granularity'), - '#description' => $this->t('How many time units should be shown in the formatted output.'), - ]; - - return $form; - } - - /** - * {@inheritdoc} - */ - public function settingsSummary() { - $summary = parent::settingsSummary(); - - $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'); - $summary[] = t('Future date: %display', ['%display' => $this->formatDate($future_date)]); - $summary[] = t('Past date: %display', ['%display' => $this->formatDate($past_date)]); - - return $summary; - } - /** * Formats a date/time as a time interval. * @@ -172,27 +47,7 @@ public function settingsSummary() { * The formatted date/time string using the past or future format setting. */ protected function formatDate(DrupalDateTime $date) { - $granularity = $this->getSetting('granularity'); - $timestamp = $date->getTimestamp(); - $options = [ - 'granularity' => $granularity, - 'return_as_object' => TRUE, - ]; - - if ($this->request->server->get('REQUEST_TIME') > $timestamp) { - $result = $this->dateFormatter->formatTimeDiffSince($timestamp, $options); - $build = [ - '#markup' => new FormattableMarkup($this->getSetting('past_format'), ['@interval' => $result->getString()]), - ]; - } - else { - $result = $this->dateFormatter->formatTimeDiffUntil($timestamp, $options); - $build = [ - '#markup' => new FormattableMarkup($this->getSetting('future_format'), ['@interval' => $result->getString()]), - ]; - } - CacheableMetadata::createFromObject($result)->applyTo($build); - return $build; + return parent::formatTimestamp($date->getTimestamp()); } } diff --git a/web/core/modules/datetime/src/Plugin/views/filter/Date.php b/web/core/modules/datetime/src/Plugin/views/filter/Date.php index 14215206c58ea2739a77ede2ee3869ae643cec87..41c4726f0eb738ce01cf2896cdb8cd4014f0b07e 100644 --- a/web/core/modules/datetime/src/Plugin/views/filter/Date.php +++ b/web/core/modules/datetime/src/Plugin/views/filter/Date.php @@ -50,7 +50,7 @@ class Date extends NumericDate implements ContainerFactoryPluginInterface { protected $calculateOffset = TRUE; /** - * The request stack used to determin current time. + * The request stack used to determine current time. * * @var \Symfony\Component\HttpFoundation\RequestStack */ diff --git a/web/core/modules/datetime/tests/src/Functional/DateTimeFieldTest.php b/web/core/modules/datetime/tests/src/Functional/DateTimeFieldTest.php index 89a7605df3ba12ae72be73eea7cd696c1449a3e2..a994cc82c84977870b9f21deecde04c664b5cb29 100644 --- a/web/core/modules/datetime/tests/src/Functional/DateTimeFieldTest.php +++ b/web/core/modules/datetime/tests/src/Functional/DateTimeFieldTest.php @@ -171,7 +171,7 @@ public function testDateField() { // past. First update the test entity so that the date difference always // has the same interval. Since the database always stores UTC, and the // interval will use this, force the test date to use UTC and not the local - // or user timezome. + // or user timezone. $timestamp = REQUEST_TIME - 87654321; $entity = EntityTest::load($id); $field_name = $this->fieldStorage->getName(); @@ -201,7 +201,7 @@ public function testDateField() { // future. First update the test entity so that the date difference always // has the same interval. Since the database always stores UTC, and the // interval will use this, force the test date to use UTC and not the local - // or user timezome. + // or user timezone. $timestamp = REQUEST_TIME + 87654321; $entity = EntityTest::load($id); $field_name = $this->fieldStorage->getName(); @@ -323,7 +323,7 @@ public function testDatetimeField() { // past. First update the test entity so that the date difference always // has the same interval. Since the database always stores UTC, and the // interval will use this, force the test date to use UTC and not the local - // or user timezome. + // or user timezone. $timestamp = REQUEST_TIME - 87654321; $entity = EntityTest::load($id); $field_name = $this->fieldStorage->getName(); @@ -350,7 +350,7 @@ public function testDatetimeField() { // future. First update the test entity so that the date difference always // has the same interval. Since the database always stores UTC, and the // interval will use this, force the test date to use UTC and not the local - // or user timezome. + // or user timezone. $timestamp = REQUEST_TIME + 87654321; $entity = EntityTest::load($id); $field_name = $this->fieldStorage->getName(); diff --git a/web/core/modules/datetime/tests/src/Functional/DateTimeTimeAgoFormatterTest.php b/web/core/modules/datetime/tests/src/Functional/DateTimeTimeAgoFormatterTest.php new file mode 100644 index 0000000000000000000000000000000000000000..5c9bafb13b84aadb61d497fa69ceb36bececd95a --- /dev/null +++ b/web/core/modules/datetime/tests/src/Functional/DateTimeTimeAgoFormatterTest.php @@ -0,0 +1,122 @@ +<?php + +namespace Drupal\Tests\datetime\Functional; + +use Drupal\Core\Entity\Entity\EntityFormDisplay; +use Drupal\Core\Entity\Entity\EntityViewDisplay; +use Drupal\field\Entity\FieldConfig; +use Drupal\field\Entity\FieldStorageConfig; +use Drupal\Tests\BrowserTestBase; + +/** + * Tests the functionality of DateTimeTimeAgoFormatter field formatter. + * + * @group field + */ +class DateTimeTimeAgoFormatterTest extends BrowserTestBase { + + /** + * An array of display options to pass to entity_get_display(). + * + * @var array + */ + protected $displayOptions; + + /** + * A field storage to use in this test class. + * + * @var \Drupal\field\Entity\FieldStorageConfig + */ + protected $fieldStorage; + + /** + * The field used in this test class. + * + * @var \Drupal\field\Entity\FieldConfig + */ + protected $field; + + /** + * {@inheritdoc} + */ + public static $modules = ['datetime', 'entity_test', 'field_ui']; + + /** + * {@inheritdoc} + */ + protected function setUp() { + parent::setUp(); + + $web_user = $this->drupalCreateUser([ + 'access administration pages', + 'view test entity', + 'administer entity_test content', + 'administer entity_test fields', + 'administer entity_test display', + 'administer entity_test form display', + 'view the administration theme', + ]); + $this->drupalLogin($web_user); + + $field_name = 'field_datetime'; + $type = 'datetime'; + $widget_type = 'datetime_default'; + $formatter_type = 'datetime_time_ago'; + + $this->fieldStorage = FieldStorageConfig::create([ + 'field_name' => $field_name, + 'entity_type' => 'entity_test', + 'type' => $type, + ]); + $this->fieldStorage->save(); + $this->field = FieldConfig::create([ + 'field_storage' => $this->fieldStorage, + 'bundle' => 'entity_test', + 'required' => TRUE, + ]); + $this->field->save(); + + EntityFormDisplay::load('entity_test.entity_test.default') + ->setComponent($field_name, ['type' => $widget_type]) + ->save(); + + $this->displayOptions = [ + 'type' => $formatter_type, + 'label' => 'hidden', + ]; + + EntityViewDisplay::create([ + 'targetEntityType' => $this->field->getTargetEntityTypeId(), + 'bundle' => $this->field->getTargetBundle(), + 'mode' => 'full', + 'status' => TRUE, + ])->setComponent($field_name, $this->displayOptions) + ->save(); + } + + /** + * Tests the formatter settings. + */ + public function testSettings() { + $this->drupalGet('entity_test/structure/entity_test/display'); + + $edit = [ + 'fields[field_datetime][region]' => 'content', + 'fields[field_datetime][type]' => 'datetime_time_ago', + ]; + $this->drupalPostForm(NULL, $edit, t('Save')); + + $this->drupalPostForm(NULL, [], 'field_datetime_settings_edit'); + $edit = [ + 'fields[field_datetime][settings_edit_form][settings][future_format]' => 'ends in @interval', + 'fields[field_datetime][settings_edit_form][settings][past_format]' => 'started @interval ago', + 'fields[field_datetime][settings_edit_form][settings][granularity]' => 3, + ]; + $this->drupalPostForm(NULL, $edit, 'Update'); + $this->drupalPostForm(NULL, [], 'Save'); + + $this->assertSession()->pageTextContains('ends in 1 year 1 month 1 week'); + $this->assertSession()->pageTextContains('started 1 year 1 month 1 week ago'); + } + +} diff --git a/web/core/modules/datetime/tests/src/Functional/Views/FilterDateTest.php b/web/core/modules/datetime/tests/src/Functional/Views/FilterDateTest.php new file mode 100644 index 0000000000000000000000000000000000000000..6c106497ae2d2544d23d0e0f625fca0a95ceab97 --- /dev/null +++ b/web/core/modules/datetime/tests/src/Functional/Views/FilterDateTest.php @@ -0,0 +1,147 @@ +<?php + +namespace Drupal\Tests\datetime\Functional\Views; + +use Drupal\Core\Datetime\DrupalDateTime; +use Drupal\datetime\Plugin\Field\FieldType\DateTimeItem; +use Drupal\datetime\Plugin\Field\FieldType\DateTimeItemInterface; +use Drupal\field\Entity\FieldStorageConfig; +use Drupal\field\Entity\FieldConfig; +use Drupal\Tests\BrowserTestBase; +use Drupal\views\Tests\ViewTestData; + +/** + * Tests Views filters for datetime fields. + * + * @group datetime + */ +class FilterDateTest extends BrowserTestBase { + + /** + * Name of the field. + * + * Note, this is used in the default test view. + * + * @var string + */ + protected $fieldName = 'field_date'; + + /** + * Nodes to test. + * + * @var \Drupal\node\NodeInterface[] + */ + protected $nodes = []; + + /** + * {@inheritdoc} + */ + public static $modules = [ + 'datetime', + 'datetime_test', + 'node', + 'views', + 'views_ui', + ]; + + /** + * {@inheritdoc} + */ + public static $testViews = ['test_filter_datetime']; + + /** + * {@inheritdoc} + * + * Create nodes with relative dates of yesterday, today, and tomorrow. + */ + protected function setUp() { + parent::setUp(); + + $now = \Drupal::time()->getRequestTime(); + + $admin_user = $this->drupalCreateUser(['administer views']); + $this->drupalLogin($admin_user); + + $this->drupalCreateContentType(['type' => 'page', 'name' => 'Basic page']); + + // Add a date field to page nodes. + $fieldStorage = FieldStorageConfig::create([ + 'field_name' => $this->fieldName, + 'entity_type' => 'node', + 'type' => 'datetime', + 'settings' => ['datetime_type' => DateTimeItem::DATETIME_TYPE_DATETIME], + ]); + $fieldStorage->save(); + $field = FieldConfig::create([ + 'field_storage' => $fieldStorage, + 'bundle' => 'page', + 'required' => TRUE, + ]); + $field->save(); + + // Create some nodes. + $dates = [ + // Tomorrow. + DrupalDateTime::createFromTimestamp($now + 86400, DateTimeItemInterface::STORAGE_TIMEZONE)->format(DateTimeItemInterface::DATE_STORAGE_FORMAT), + // Today. + DrupalDateTime::createFromTimestamp($now, DateTimeItemInterface::STORAGE_TIMEZONE)->format(DateTimeItemInterface::DATE_STORAGE_FORMAT), + // Yesterday. + DrupalDateTime::createFromTimestamp($now - 86400, DateTimeItemInterface::STORAGE_TIMEZONE)->format(DateTimeItemInterface::DATE_STORAGE_FORMAT), + ]; + + $this->nodes = []; + foreach ($dates as $date) { + $this->nodes[] = $this->drupalCreateNode([ + $this->fieldName => [ + 'value' => $date, + ], + ]); + } + // Add a node where the date field is empty. + $this->nodes[] = $this->drupalCreateNode(); + + // Views needs to be aware of the new field. + $this->container->get('views.views_data')->clear(); + + // Load test views. + ViewTestData::createTestViews(get_class($this), ['datetime_test']); + } + + /** + * Tests exposed grouped filters. + */ + public function testExposedGroupedFilters() { + // Expose the empty and not empty operators in a grouped filter. + $this->drupalPostForm('admin/structure/views/nojs/handler/test_filter_datetime/default/filter/' . $this->fieldName . '_value', [], t('Expose filter')); + $this->drupalPostForm(NULL, [], 'Grouped filters'); + + $edit = []; + $edit['options[group_info][group_items][1][title]'] = 'empty'; + $edit['options[group_info][group_items][1][operator]'] = 'empty'; + $edit['options[group_info][group_items][2][title]'] = 'not empty'; + $edit['options[group_info][group_items][2][operator]'] = 'not empty'; + + $this->drupalPostForm(NULL, $edit, 'Apply'); + + // Test that the exposed filter works as expected. + $path = 'test_filter_datetime-path'; + $this->drupalPostForm('admin/structure/views/view/test_filter_datetime/edit', [], 'Add Page'); + $this->drupalPostForm('admin/structure/views/nojs/display/test_filter_datetime/page_1/path', ['path' => $path], 'Apply'); + $this->drupalPostForm(NULL, [], t('Save')); + + $this->drupalGet($path); + + // Filter the Preview by 'empty'. + $this->getSession()->getPage()->findField($this->fieldName . '_value')->selectOption(1); + $this->getSession()->getPage()->pressButton('Apply'); + $results = $this->cssSelect('.view-content .field-content'); + $this->assertEquals(1, count($results)); + + // Filter the Preview by 'not empty'. + $this->getSession()->getPage()->findField($this->fieldName . '_value')->selectOption(2); + $this->getSession()->getPage()->pressButton('Apply'); + $results = $this->cssSelect('.view-content .field-content'); + $this->assertEquals(3, count($results)); + } + +} diff --git a/web/core/modules/datetime/tests/src/Kernel/Views/FilterDateTest.php b/web/core/modules/datetime/tests/src/Kernel/Views/FilterDateTest.php index f7386cc2c79438e571f3f968fdfa2f1692e4d22e..314d18fb166a95a1806b1be7a9b9e6f4e16079cc 100644 --- a/web/core/modules/datetime/tests/src/Kernel/Views/FilterDateTest.php +++ b/web/core/modules/datetime/tests/src/Kernel/Views/FilterDateTest.php @@ -71,6 +71,15 @@ protected function setUp($import_test_views = TRUE) { $node->save(); $this->nodes[] = $node; } + + // Add a node where the date field is empty. + $node = Node::create([ + 'title' => $this->randomMachineName(8), + 'type' => 'page', + 'field_date' => [], + ]); + $node->save(); + $this->nodes[] = $node; } /** @@ -130,6 +139,30 @@ public function testDateOffsets() { ]; $this->assertIdenticalResultset($view, $expected_result, $this->map); $view->destroy(); + + // Test the empty operator. + $view->initHandlers(); + $view->filter[$field]->operator = 'empty'; + $view->setDisplay('default'); + $this->executeView($view); + $expected_result = [ + ['nid' => $this->nodes[3]->id()], + ]; + $this->assertIdenticalResultset($view, $expected_result, $this->map); + $view->destroy(); + + // Test the not empty operator. + $view->initHandlers(); + $view->filter[$field]->operator = 'not empty'; + $view->setDisplay('default'); + $this->executeView($view); + $expected_result = [ + ['nid' => $this->nodes[0]->id()], + ['nid' => $this->nodes[1]->id()], + ['nid' => $this->nodes[2]->id()], + ]; + $this->assertIdenticalResultset($view, $expected_result, $this->map); + $view->destroy(); } } diff --git a/web/core/modules/datetime_range/datetime_range.module b/web/core/modules/datetime_range/datetime_range.module index 99d0e89c2eee8d783c3d8dc1bb8b5fa05823178d..3c6b1f9c107e577a6b09e86e28d0c4f5facfe0c5 100644 --- a/web/core/modules/datetime_range/datetime_range.module +++ b/web/core/modules/datetime_range/datetime_range.module @@ -53,9 +53,13 @@ function datetime_range_view_presave(ViewEntityInterface $view) { if (isset($display['display_options']['filters'])) { foreach ($display['display_options']['filters'] as $field_name => &$filter) { if ($filter['plugin_id'] === 'string') { + $table_data = Views::viewsData()->get($filter['table']); + if (!$table_data) { + continue; + } // Get field config. - $filter_views_data = Views::viewsData()->get($filter['table'])[$filter['field']]['filter']; + $filter_views_data = $table_data[$filter['field']]['filter']; if (!isset($filter_views_data['entity_type']) || !isset($filter_views_data['field_name'])) { continue; } @@ -128,9 +132,13 @@ function datetime_range_view_presave(ViewEntityInterface $view) { if (isset($display['display_options']['sorts'])) { foreach ($display['display_options']['sorts'] as $field_name => &$sort) { if ($sort['plugin_id'] === 'standard') { + $table_data = Views::viewsData()->get($sort['table']); + if (!$table_data) { + continue; + } // Get field config. - $sort_views_data = Views::viewsData()->get($sort['table'])[$sort['field']]['sort']; + $sort_views_data = $table_data[$sort['field']]['sort']; if (!isset($sort_views_data['entity_type']) || !isset($sort_views_data['field_name'])) { continue; } diff --git a/web/core/modules/datetime_range/tests/modules/datetime_range_test/datetime_range_test.info.yml b/web/core/modules/datetime_range/tests/modules/datetime_range_test/datetime_range_test.info.yml new file mode 100644 index 0000000000000000000000000000000000000000..8e5bddee3448f107a0ad858c13651b960b53433a --- /dev/null +++ b/web/core/modules/datetime_range/tests/modules/datetime_range_test/datetime_range_test.info.yml @@ -0,0 +1,8 @@ +name: 'Datetime range test' +type: module +description: 'Provides a testing module for datetime_range.' +package: Testing +version: VERSION +core: 8.x +dependencies: + - drupal:taxonomy diff --git a/web/core/modules/datetime_range/tests/modules/datetime_range_test/datetime_range_test.module b/web/core/modules/datetime_range/tests/modules/datetime_range_test/datetime_range_test.module new file mode 100644 index 0000000000000000000000000000000000000000..4f15a91ed6bab6e604257b83a7d478177b6c7a2f --- /dev/null +++ b/web/core/modules/datetime_range/tests/modules/datetime_range_test/datetime_range_test.module @@ -0,0 +1,17 @@ +<?php + +/** + * @file + * Contains datetime_range_test.module + */ + +/** + * Implements hook_entity_type_alter(). + */ +function datetime_range_test_entity_type_alter(array &$entity_types) { + // Inhibit views data for the 'taxonomy_term' entity type in order to cover + // the case when an entity type provides no views data. + // @see https://www.drupal.org/project/drupal/issues/2995578 + // @see \Drupal\Tests\datetime_range\Kernel\Views\EntityTypeWithoutViewsDataTest + $entity_types['taxonomy_term']->setHandlerClass('views_data', NULL); +} diff --git a/web/core/modules/datetime_range/tests/src/Kernel/Views/EntityTypeWithoutViewsDataTest.php b/web/core/modules/datetime_range/tests/src/Kernel/Views/EntityTypeWithoutViewsDataTest.php new file mode 100644 index 0000000000000000000000000000000000000000..4631f3c131ce7cb43fc61db307894b1cd433a169 --- /dev/null +++ b/web/core/modules/datetime_range/tests/src/Kernel/Views/EntityTypeWithoutViewsDataTest.php @@ -0,0 +1,43 @@ +<?php + +namespace Drupal\Tests\datetime_range\Kernel\Views; + +use Drupal\Core\Config\InstallStorage; +use Drupal\Core\Serialization\Yaml; +use Drupal\KernelTests\KernelTestBase; +use Drupal\views\Entity\View; + +/** + * Tests datetime_range.module when an entity type provides no views data. + * + * @group datetime + */ +class EntityTypeWithoutViewsDataTest extends KernelTestBase { + + /** + * {@inheritdoc} + */ + protected static $modules = [ + 'datetime_range', + 'datetime_range_test', + 'node', + 'system', + 'taxonomy', + 'text', + 'user', + 'views', + ]; + + /** + * Tests the case when an entity type provides no views data. + * + * @see datetime_test_entity_type_alter() + * @see datetime_range_view_presave() + */ + public function testEntityTypeWithoutViewsData() { + $view_yaml = drupal_get_path('module', 'taxonomy') . '/' . InstallStorage::CONFIG_OPTIONAL_DIRECTORY . '/views.view.taxonomy_term.yml'; + $values = Yaml::decode(file_get_contents($view_yaml)); + $this->assertEquals(SAVED_NEW, View::create($values)->save()); + } + +} diff --git a/web/core/modules/dblog/tests/src/Functional/DbLogTest.php b/web/core/modules/dblog/tests/src/Functional/DbLogTest.php index 2b2f388cb2f7e7a2d3e945c01fa8cd647301bf80..c36004e075f848560570f8c226b692e4fcf93fb3 100644 --- a/web/core/modules/dblog/tests/src/Functional/DbLogTest.php +++ b/web/core/modules/dblog/tests/src/Functional/DbLogTest.php @@ -8,7 +8,6 @@ use Drupal\Core\Url; use Drupal\dblog\Controller\DbLogController; use Drupal\Tests\BrowserTestBase; -use Drupal\Tests\Traits\Core\CronRunTrait; /** * Generate events and verify dblog entries; verify user access to log reports @@ -17,7 +16,6 @@ * @group dblog */ class DbLogTest extends BrowserTestBase { - use CronRunTrait; use FakeLogEntries; /** @@ -67,7 +65,6 @@ public function testDbLog() { $row_limit = 100; $this->verifyRowLimit($row_limit); - $this->verifyCron($row_limit); $this->verifyEvents(); $this->verifyReports(); $this->verifyBreadcrumbs(); @@ -137,52 +134,6 @@ private function verifyRowLimit($row_limit) { $this->assertTrue($current_limit == $row_limit, format_string('[Cache] Row limit variable of @count equals row limit of @limit', ['@count' => $current_limit, '@limit' => $row_limit])); } - /** - * Verifies that cron correctly applies the database log row limit. - * - * @param int $row_limit - * The row limit. - */ - private function verifyCron($row_limit) { - // Generate additional log entries. - $this->generateLogEntries($row_limit + 10); - // Verify that the database log row count exceeds the row limit. - $count = db_query('SELECT COUNT(wid) FROM {watchdog}')->fetchField(); - $this->assertTrue($count > $row_limit, format_string('Dblog row count of @count exceeds row limit of @limit', ['@count' => $count, '@limit' => $row_limit])); - - // Get the number of enabled modules. Cron adds a log entry for each module. - $list = \Drupal::moduleHandler()->getImplementations('cron'); - $module_count = count($list); - $cron_detailed_count = $this->runCron(); - $this->assertTrue($cron_detailed_count == $module_count + 2, format_string('Cron added @count of @expected new log entries', ['@count' => $cron_detailed_count, '@expected' => $module_count + 2])); - - // Test disabling of detailed cron logging. - $this->config('system.cron')->set('logging', 0)->save(); - $cron_count = $this->runCron(); - $this->assertTrue($cron_count = 1, format_string('Cron added @count of @expected new log entries', ['@count' => $cron_count, '@expected' => 1])); - } - - /** - * Runs cron and returns number of new log entries. - * - * @return int - * Number of new watchdog entries. - */ - private function runCron() { - // Get last ID to compare against; log entries get deleted, so we can't - // reliably add the number of newly created log entries to the current count - // to measure number of log entries created by cron. - $last_id = db_query('SELECT MAX(wid) FROM {watchdog}')->fetchField(); - - // Run a cron job. - $this->cronRun(); - - // Get last ID after cron was run. - $current_id = db_query('SELECT MAX(wid) FROM {watchdog}')->fetchField(); - - return $current_id - $last_id; - } - /** * Clear the entry logs by clicking on 'Clear log messages' button. */ diff --git a/web/core/modules/dblog/tests/src/Functional/Update/DblogFiltersAndFieldsUpgradeTest.php b/web/core/modules/dblog/tests/src/Functional/Update/DblogFiltersAndFieldsUpgradeTest.php index 6610363ccfabf4843acaba147f567f9bd1bc6844..8c33494ef41d2a8d67e604cd5821fed33848baa3 100644 --- a/web/core/modules/dblog/tests/src/Functional/Update/DblogFiltersAndFieldsUpgradeTest.php +++ b/web/core/modules/dblog/tests/src/Functional/Update/DblogFiltersAndFieldsUpgradeTest.php @@ -65,7 +65,7 @@ public function testDblogUpgradePath() { // Now save the view. This trigger dblog_view_presave(). $view->save(); - // Finally check the same convertion proccess ran. + // Finally check the same conversion process ran. $data = $view->storage->toArray(); $fields = $data['display']['default']['display_options']['fields']; $filters = $data['display']['default']['display_options']['filters']; diff --git a/web/core/modules/dblog/tests/src/Functional/Update/DblogNoLogsAvailableUpgradeTest.php b/web/core/modules/dblog/tests/src/Functional/Update/DblogNoLogsAvailableUpgradeTest.php index e3545d9ae6612c47c17698bcc6aa2b55eb19e09f..5002f251647a107545060e740ee0e3a2e9eb315a 100644 --- a/web/core/modules/dblog/tests/src/Functional/Update/DblogNoLogsAvailableUpgradeTest.php +++ b/web/core/modules/dblog/tests/src/Functional/Update/DblogNoLogsAvailableUpgradeTest.php @@ -6,7 +6,7 @@ use Drupal\views\Views; /** - * Test the upgrade path of changing the emtpy text area for watchdog view. + * Test the upgrade path of changing the empty text area for watchdog view. * * @see dblog_update_8600() * diff --git a/web/core/modules/dblog/tests/src/Functional/Update/DblogRecentLogsUsingViewsUpdateTest.php b/web/core/modules/dblog/tests/src/Functional/Update/DblogRecentLogsUsingViewsUpdateTest.php index 37e1b090e6eb813d538e7ad37a0d8b48074ee413..3f54207e673176cbc5896978abe07d0315da529f 100644 --- a/web/core/modules/dblog/tests/src/Functional/Update/DblogRecentLogsUsingViewsUpdateTest.php +++ b/web/core/modules/dblog/tests/src/Functional/Update/DblogRecentLogsUsingViewsUpdateTest.php @@ -5,7 +5,7 @@ use Drupal\FunctionalTests\Update\UpdatePathTestBase; /** - * Ensures that update hook that creates the watchdog view ran sucessfully. + * Ensures that update hook that creates the watchdog view ran successfully. * * @group Update * @group legacy @@ -25,7 +25,7 @@ protected function setDatabaseDumpFiles() { * Ensures that update hook is run for dblog module. */ public function testUpdate() { - // Make sure the watchog view doesn't exist before the updates. + // Make sure the watchdog view doesn't exist before the updates. $view = \Drupal::entityTypeManager()->getStorage('view')->load('watchdog'); $this->assertNull($view); diff --git a/web/core/modules/dblog/tests/src/Kernel/DbLogTest.php b/web/core/modules/dblog/tests/src/Kernel/DbLogTest.php new file mode 100644 index 0000000000000000000000000000000000000000..fc5eac7af18b74f4dab24d1f332bd5eddd9c9cf6 --- /dev/null +++ b/web/core/modules/dblog/tests/src/Kernel/DbLogTest.php @@ -0,0 +1,77 @@ +<?php + +namespace Drupal\Tests\dblog\Kernel; + +use Drupal\KernelTests\KernelTestBase; +use Drupal\Tests\dblog\Functional\FakeLogEntries; + +/** + * Generate events and verify dblog entries. + * + * @group dblog + */ +class DbLogTest extends KernelTestBase { + + use FakeLogEntries; + + /** + * {@inheritdoc} + */ + protected static $modules = ['dblog', 'system']; + + /** + * {@inheritdoc} + */ + protected function setUp() { + parent::setUp(); + + $this->installSchema('dblog', ['watchdog']); + $this->installSchema('system', ['key_value_expire', 'sequences']); + $this->installConfig(['system']); + } + + /** + * Tests that cron correctly applies the database log row limit. + */ + public function testDbLogCron() { + $row_limit = 100; + // Generate additional log entries. + $this->generateLogEntries($row_limit + 10); + // Verify that the database log row count exceeds the row limit. + $count = db_query('SELECT COUNT(wid) FROM {watchdog}')->fetchField(); + $this->assertGreaterThan($row_limit, $count, format_string('Dblog row count of @count exceeds row limit of @limit', ['@count' => $count, '@limit' => $row_limit])); + + // Get the number of enabled modules. Cron adds a log entry for each module. + $list = $this->container->get('module_handler')->getImplementations('cron'); + $module_count = count($list); + $cron_detailed_count = $this->runCron(); + $this->assertEquals($module_count + 2, $cron_detailed_count, format_string('Cron added @count of @expected new log entries', ['@count' => $cron_detailed_count, '@expected' => $module_count + 2])); + + // Test disabling of detailed cron logging. + $this->config('system.cron')->set('logging', 0)->save(); + $cron_count = $this->runCron(); + $this->assertEquals(1, $cron_count, format_string('Cron added @count of @expected new log entries', ['@count' => $cron_count, '@expected' => 1])); + } + + /** + * Runs cron and returns number of new log entries. + * + * @return int + * Number of new watchdog entries. + */ + private function runCron() { + // Get last ID to compare against; log entries get deleted, so we can't + // reliably add the number of newly created log entries to the current count + // to measure number of log entries created by cron. + $last_id = db_query('SELECT MAX(wid) FROM {watchdog}')->fetchField(); + + // Run a cron job. + $this->container->get('cron')->run(); + + // Get last ID after cron was run. + $current_id = db_query('SELECT MAX(wid) FROM {watchdog}')->fetchField(); + + return $current_id - $last_id; + } + +} diff --git a/web/core/modules/field/field.api.php b/web/core/modules/field/field.api.php index 64e2893e71b948dfbf38ee368e6f54f50785825d..5115e42b39b3750a6d1d02bfdc4bf67d3b2ad7ba 100644 --- a/web/core/modules/field/field.api.php +++ b/web/core/modules/field/field.api.php @@ -292,7 +292,7 @@ function hook_field_widget_multivalue_WIDGET_TYPE_form_alter(array &$elements, \ // Code here will only act on widgets of type WIDGET_TYPE. For example, // hook_field_widget_multivalue_mymodule_autocomplete_form_alter() will only // act on widgets of type 'mymodule_autocomplete'. - // Change the autcomplete route for each autocomplete element within the + // Change the autocomplete route for each autocomplete element within the // multivalue widget. foreach (Element::children($elements) as $delta => $element) { $elements[$delta]['#autocomplete_route_name'] = 'mymodule.autocomplete_route'; diff --git a/web/core/modules/field/src/Plugin/migrate/process/d6/FieldInstanceOptionTranslation.php b/web/core/modules/field/src/Plugin/migrate/process/d6/FieldInstanceOptionTranslation.php new file mode 100644 index 0000000000000000000000000000000000000000..72e954bf0cb4141d8c7333981ca90c1759dfc058 --- /dev/null +++ b/web/core/modules/field/src/Plugin/migrate/process/d6/FieldInstanceOptionTranslation.php @@ -0,0 +1,53 @@ +<?php + +namespace Drupal\field\Plugin\migrate\process\d6; + +use Drupal\migrate\MigrateExecutableInterface; +use Drupal\migrate\ProcessPluginBase; +use Drupal\migrate\Row; + +/** + * Determines the settings property and translation for boolean fields. + * + * @MigrateProcessPlugin( + * id = "d6_field_instance_option_translation", + * handle_multiples = TRUE + * ) + */ +class FieldInstanceOptionTranslation extends ProcessPluginBase { + + /** + * {@inheritdoc} + */ + public function transform($value, MigrateExecutableInterface $migrate_executable, Row $row, $destination_property) { + list($field_type, $global_settings) = $value; + + $option_key = 0; + $translation = ''; + if (isset($global_settings['allowed_values'])) { + $list = explode("\n", $global_settings['allowed_values']); + $list = array_map('trim', $list); + $list = array_filter($list, 'strlen'); + switch ($field_type) { + case 'boolean'; + $option = preg_replace('/^option_/', '', $row->getSourceProperty('property')); + for ($i = 0; $i < 2; $i++) { + $value = $list[$i]; + $tmp = explode("|", $value); + $original_option_key = isset($tmp[0]) ? $tmp[0] : NULL; + $option_key = ($i === 0) ? 'off_label' : 'on_label'; + // Find property with name matching the original option. + if ($option == $original_option_key) { + $translation = $row->getSourceProperty('translation'); + break; + } + } + break; + + default: + } + } + return ['settings.' . $option_key, $translation]; + } + +} diff --git a/web/core/modules/field/src/Plugin/migrate/process/d6/FieldOptionTranslation.php b/web/core/modules/field/src/Plugin/migrate/process/d6/FieldOptionTranslation.php new file mode 100644 index 0000000000000000000000000000000000000000..05bb2ad0d626f7946b327b2065462d7f3ee7483c --- /dev/null +++ b/web/core/modules/field/src/Plugin/migrate/process/d6/FieldOptionTranslation.php @@ -0,0 +1,59 @@ +<?php + +namespace Drupal\field\Plugin\migrate\process\d6; + +use Drupal\migrate\MigrateExecutableInterface; +use Drupal\migrate\ProcessPluginBase; +use Drupal\migrate\Row; + +/** + * Determines the allowed values translation for select lists. + * + * @MigrateProcessPlugin( + * id = "d6_field_option_translation", + * handle_multiples = TRUE + * ) + */ +class FieldOptionTranslation extends ProcessPluginBase { + + /** + * {@inheritdoc} + * + * Get the field default/mapped settings. + */ + public function transform($value, MigrateExecutableInterface $migrate_executable, Row $row, $destination_property) { + list($field_type, $global_settings) = $value; + + $allowed_values = ''; + $i = 0; + if (isset($global_settings['allowed_values'])) { + $list = explode("\n", $global_settings['allowed_values']); + $list = array_map('trim', $list); + $list = array_filter($list, 'strlen'); + switch ($field_type) { + case 'list_string': + case 'list_integer': + case 'list_float': + // Remove the prefix used in the i18n_strings table for field options + // to get the option value. + $option = preg_replace('/^option_/', '', $row->getSourceProperty('property')); + $i = 0; + foreach ($list as $allowed_value) { + // Get the key for this allowed value which may be a key|label pair + // or or just key. + $value = explode("|", $allowed_value); + if (isset($value[0]) && ($value[0] == $option)) { + $allowed_values = ['label' => $row->getSourceProperty('translation')]; + break; + } + $i++; + } + break; + + default: + } + } + return ["settings.allowed_values.$i", $allowed_values]; + } + +} diff --git a/web/core/modules/field/src/Plugin/migrate/source/d6/FieldInstanceOptionTranslation.php b/web/core/modules/field/src/Plugin/migrate/source/d6/FieldInstanceOptionTranslation.php new file mode 100644 index 0000000000000000000000000000000000000000..15ec9b9415a7e54e340bdce84b743065d85c98bb --- /dev/null +++ b/web/core/modules/field/src/Plugin/migrate/source/d6/FieldInstanceOptionTranslation.php @@ -0,0 +1,35 @@ +<?php + +namespace Drupal\field\Plugin\migrate\source\d6; + +/** + * Gets field instance option label translations. + * + * @MigrateSource( + * id = "d6_field_instance_option_translation", + * source_module = "i18ncck" + * ) + */ +class FieldInstanceOptionTranslation extends FieldOptionTranslation { + + /** + * {@inheritdoc} + */ + public function query() { + $query = parent::query(); + $query->join('content_node_field_instance', 'cnfi', 'cnf.field_name = cnfi.field_name'); + $query->addField('cnfi', 'type_name'); + return $query; + } + + /** + * {@inheritdoc} + */ + public function fields() { + $fields = [ + 'type_name' => $this->t('Type (article, page, ....)'), + ]; + return parent::fields() + $fields; + } + +} diff --git a/web/core/modules/field/src/Plugin/migrate/source/d6/FieldLabelDescriptionTranslation.php b/web/core/modules/field/src/Plugin/migrate/source/d6/FieldLabelDescriptionTranslation.php new file mode 100644 index 0000000000000000000000000000000000000000..e9961297fe587b457231156034c749cb4d1a3ef0 --- /dev/null +++ b/web/core/modules/field/src/Plugin/migrate/source/d6/FieldLabelDescriptionTranslation.php @@ -0,0 +1,60 @@ +<?php + +namespace Drupal\field\Plugin\migrate\source\d6; + +use Drupal\migrate_drupal\Plugin\migrate\source\DrupalSqlBase; + +/** + * Gets field label and description translations. + * + * @MigrateSource( + * id = "d6_field_instance_label_description_translation", + * source_module = "i18ncck" + * ) + */ +class FieldLabelDescriptionTranslation extends DrupalSqlBase { + + /** + * {@inheritdoc} + */ + public function query() { + // Get translations for field labels and descriptions. + $query = $this->select('i18n_strings', 'i18n') + ->fields('i18n', ['property', 'objectid', 'type']) + ->fields('lt', ['lid', 'translation', 'language']) + ->condition('i18n.type', 'field') + ->isNotNull('language') + ->isNotNull('translation'); + $condition = $query->orConditionGroup() + ->condition('property', 'widget_label') + ->condition('property', 'widget_description'); + $query->condition($condition); + $query->leftJoin('locales_target', 'lt', 'lt.lid = i18n.lid'); + + return $query; + } + + /** + * {@inheritdoc} + */ + public function fields() { + return [ + 'property' => $this->t('Profile field ID.'), + 'lid' => $this->t('Locales target language ID.'), + 'language' => $this->t('Language for this field.'), + 'translation' => $this->t('Translation of either the title or explanation.'), + ]; + } + + /** + * {@inheritdoc} + */ + public function getIds() { + $ids['property']['type'] = 'string'; + $ids['language']['type'] = 'string'; + $ids['lid']['type'] = 'integer'; + $ids['lid']['alias'] = 'lt'; + return $ids; + } + +} diff --git a/web/core/modules/field/src/Plugin/migrate/source/d6/FieldOptionTranslation.php b/web/core/modules/field/src/Plugin/migrate/source/d6/FieldOptionTranslation.php new file mode 100644 index 0000000000000000000000000000000000000000..bc2671a9c4a5dab8b97609ad5ea4577836795c23 --- /dev/null +++ b/web/core/modules/field/src/Plugin/migrate/source/d6/FieldOptionTranslation.php @@ -0,0 +1,78 @@ +<?php + +namespace Drupal\field\Plugin\migrate\source\d6; + +/** + * Gets field option label translations. + * + * @MigrateSource( + * id = "d6_field_option_translation", + * source_module = "i18ncck" + * ) + */ +class FieldOptionTranslation extends Field { + + /** + * {@inheritdoc} + */ + public function query() { + // Get the fields that have field options translations. + $query = $this->select('i18n_strings', 'i18n') + ->fields('i18n') + ->fields('lt', [ + 'translation', + 'language', + 'plid', + 'plural', + 'i18n_status', + ]) + ->condition('i18n.type', 'field') + ->condition('property', 'option\_%', 'LIKE') + ->isNotNull('translation'); + $query->leftJoin('locales_target', 'lt', 'lt.lid = i18n.lid'); + $query->leftjoin('content_node_field', 'cnf', 'cnf.field_name = i18n.objectid'); + $query->addField('cnf', 'field_name'); + $query->addField('cnf', 'global_settings'); + // Minimise changes to the d6_field_option_translation.yml, which is copied + // from d6_field.yml, by ensuring the 'type' property is from + // content_node_field table. + $query->addField('cnf', 'type'); + $query->addField('i18n', 'type', 'i18n_type'); + + return $query; + } + + /** + * {@inheritdoc} + */ + public function fields() { + $fields = [ + 'property' => $this->t('Option ID.'), + 'objectid' => $this->t('Object ID'), + 'objectindex' => $this->t('Integer value of Object ID'), + 'format' => $this->t('The input format used by this string'), + 'lid' => $this->t('Source string ID'), + 'language' => $this->t('Language code'), + 'translation' => $this->t('Translation of the option'), + 'plid' => $this->t('Parent lid'), + 'plural' => $this->t('Plural index number in case of plural strings'), + ]; + return parent::fields() + $fields; + } + + /** + * {@inheritdoc} + */ + + /** + * {@inheritdoc} + */ + public function getIds() { + return parent::getIds() + + [ + 'language' => ['type' => 'string'], + 'property' => ['type' => 'string'], + ]; + } + +} diff --git a/web/core/modules/field/src/Tests/EntityReference/EntityReferenceTestTrait.php b/web/core/modules/field/src/Tests/EntityReference/EntityReferenceTestTrait.php index 568cd4d5fcbd5019da951de8e3f7923d0b3a8f27..2d1ec20e426f862337e43c46e08624d4671f24dc 100644 --- a/web/core/modules/field/src/Tests/EntityReference/EntityReferenceTestTrait.php +++ b/web/core/modules/field/src/Tests/EntityReference/EntityReferenceTestTrait.php @@ -2,63 +2,18 @@ namespace Drupal\field\Tests\EntityReference; -use Drupal\field\Entity\FieldConfig; -use Drupal\field\Entity\FieldStorageConfig; +use Drupal\Tests\field\Traits\EntityReferenceTestTrait as nonDeprecatedEntityReferenceTestTrait; /** * Provides common functionality for the EntityReference test classes. + * + * @deprecated in Drupal 8.6.2 for removal before 9.0.0. Use + * Drupal\Tests\field\Traits\EntityReferenceTestTrait instead. + * + * @see https://www.drupal.org/node/2998888 */ trait EntityReferenceTestTrait { - /** - * Creates a field of an entity reference field storage on the specified bundle. - * - * @param string $entity_type - * The type of entity the field will be attached to. - * @param string $bundle - * The bundle name of the entity the field will be attached to. - * @param string $field_name - * The name of the field; if it already exists, a new instance of the existing - * field will be created. - * @param string $field_label - * The label of the field. - * @param string $target_entity_type - * The type of the referenced entity. - * @param string $selection_handler - * The selection handler used by this field. - * @param array $selection_handler_settings - * An array of settings supported by the selection handler specified above. - * (e.g. 'target_bundles', 'sort', 'auto_create', etc). - * @param int $cardinality - * The cardinality of the field. - * - * @see \Drupal\Core\Entity\Plugin\EntityReferenceSelection\SelectionBase::buildConfigurationForm() - */ - protected function createEntityReferenceField($entity_type, $bundle, $field_name, $field_label, $target_entity_type, $selection_handler = 'default', $selection_handler_settings = [], $cardinality = 1) { - // Look for or add the specified field to the requested entity bundle. - if (!FieldStorageConfig::loadByName($entity_type, $field_name)) { - FieldStorageConfig::create([ - 'field_name' => $field_name, - 'type' => 'entity_reference', - 'entity_type' => $entity_type, - 'cardinality' => $cardinality, - 'settings' => [ - 'target_type' => $target_entity_type, - ], - ])->save(); - } - if (!FieldConfig::loadByName($entity_type, $bundle, $field_name)) { - FieldConfig::create([ - 'field_name' => $field_name, - 'entity_type' => $entity_type, - 'bundle' => $bundle, - 'label' => $field_label, - 'settings' => [ - 'handler' => $selection_handler, - 'handler_settings' => $selection_handler_settings, - ], - ])->save(); - } - } + use nonDeprecatedEntityReferenceTestTrait; } diff --git a/web/core/modules/field/src/Tests/EntityReference/EntityReferenceAdminTest.php b/web/core/modules/field/tests/src/Functional/EntityReference/EntityReferenceAdminTest.php similarity index 64% rename from web/core/modules/field/src/Tests/EntityReference/EntityReferenceAdminTest.php rename to web/core/modules/field/tests/src/Functional/EntityReference/EntityReferenceAdminTest.php index 7a5e3ea4cc7e8e827ef0be09d9e8d0760c54c021..8510539c56834748ec363ea7ae1633545da5fd91 100644 --- a/web/core/modules/field/src/Tests/EntityReference/EntityReferenceAdminTest.php +++ b/web/core/modules/field/tests/src/Functional/EntityReference/EntityReferenceAdminTest.php @@ -1,20 +1,21 @@ <?php -namespace Drupal\field\Tests\EntityReference; +namespace Drupal\Tests\field\Functional\EntityReference; -use Drupal\field\Entity\FieldConfig; +use Behat\Mink\Element\NodeElement; use Drupal\Core\Field\FieldStorageDefinitionInterface; -use Drupal\field_ui\Tests\FieldUiTestTrait; +use Drupal\field\Entity\FieldConfig; use Drupal\node\Entity\Node; -use Drupal\simpletest\WebTestBase; use Drupal\taxonomy\Entity\Vocabulary; +use Drupal\Tests\BrowserTestBase; +use Drupal\Tests\field_ui\Traits\FieldUiTestTrait; /** * Tests for the administrative UI. * * @group entity_reference */ -class EntityReferenceAdminTest extends WebTestBase { +class EntityReferenceAdminTest extends BrowserTestBase { use FieldUiTestTrait; @@ -65,145 +66,6 @@ protected function setUp() { */ public function testFieldAdminHandler() { $bundle_path = 'admin/structure/types/manage/' . $this->type; - - // First step: 'Add new field' on the 'Manage fields' page. - $this->drupalGet($bundle_path . '/fields/add-field'); - - // Check if the commonly referenced entity types appear in the list. - $this->assertOption('edit-new-storage-type', 'field_ui:entity_reference:node'); - $this->assertOption('edit-new-storage-type', 'field_ui:entity_reference:user'); - - $this->drupalPostForm(NULL, [ - 'label' => 'Test label', - 'field_name' => 'test', - 'new_storage_type' => 'entity_reference', - ], t('Save and continue')); - - // Node should be selected by default. - $this->assertFieldByName('settings[target_type]', 'node'); - - // Check that all entity types can be referenced. - $this->assertFieldSelectOptions('settings[target_type]', array_keys(\Drupal::entityManager()->getDefinitions())); - - // Second step: 'Field settings' form. - $this->drupalPostForm(NULL, [], t('Save field settings')); - - // The base handler should be selected by default. - $this->assertFieldByName('settings[handler]', 'default:node'); - - // The base handler settings should be displayed. - $entity_type_id = 'node'; - // Check that the type label is correctly displayed. - $this->assertText('Content type'); - $bundles = $this->container->get('entity_type.bundle.info')->getBundleInfo($entity_type_id); - foreach ($bundles as $bundle_name => $bundle_info) { - $this->assertFieldByName('settings[handler_settings][target_bundles][' . $bundle_name . ']'); - } - - reset($bundles); - - // Test the sort settings. - // Option 0: no sort. - $this->assertFieldByName('settings[handler_settings][sort][field]', '_none'); - $this->assertNoFieldByName('settings[handler_settings][sort][direction]'); - // Option 1: sort by field. - $this->drupalPostAjaxForm(NULL, ['settings[handler_settings][sort][field]' => 'nid'], 'settings[handler_settings][sort][field]'); - $this->assertFieldByName('settings[handler_settings][sort][direction]', 'ASC'); - - // Test that a non-translatable base field is a sort option. - $this->assertFieldByXPath("//select[@name='settings[handler_settings][sort][field]']/option[@value='nid']"); - // Test that a translatable base field is a sort option. - $this->assertFieldByXPath("//select[@name='settings[handler_settings][sort][field]']/option[@value='title']"); - // Test that a configurable field is a sort option. - $this->assertFieldByXPath("//select[@name='settings[handler_settings][sort][field]']/option[@value='body.value']"); - - // Set back to no sort. - $this->drupalPostAjaxForm(NULL, ['settings[handler_settings][sort][field]' => '_none'], 'settings[handler_settings][sort][field]'); - $this->assertNoFieldByName('settings[handler_settings][sort][direction]'); - - // Third step: confirm. - $this->drupalPostForm(NULL, [ - 'required' => '1', - 'settings[handler_settings][target_bundles][' . key($bundles) . ']' => key($bundles), - ], t('Save settings')); - - // Check that the field appears in the overview form. - $this->assertFieldByXPath('//table[@id="field-overview"]//tr[@id="field-test"]/td[1]', 'Test label', 'Field was created and appears in the overview page.'); - - // Check that the field settings form can be submitted again, even when the - // field is required. - // The first 'Edit' link is for the Body field. - $this->clickLink(t('Edit'), 1); - $this->drupalPostForm(NULL, [], t('Save settings')); - - // Switch the target type to 'taxonomy_term' and check that the settings - // specific to its selection handler are displayed. - $field_name = 'node.' . $this->type . '.field_test'; - $edit = [ - 'settings[target_type]' => 'taxonomy_term', - ]; - $this->drupalPostForm($bundle_path . '/fields/' . $field_name . '/storage', $edit, t('Save field settings')); - $this->drupalGet($bundle_path . '/fields/' . $field_name); - $this->assertFieldByName('settings[handler_settings][auto_create]'); - - // Switch the target type to 'user' and check that the settings specific to - // its selection handler are displayed. - $field_name = 'node.' . $this->type . '.field_test'; - $edit = [ - 'settings[target_type]' => 'user', - ]; - $this->drupalPostForm($bundle_path . '/fields/' . $field_name . '/storage', $edit, t('Save field settings')); - $this->drupalGet($bundle_path . '/fields/' . $field_name); - $this->assertFieldByName('settings[handler_settings][filter][type]', '_none'); - - // Switch the target type to 'node'. - $field_name = 'node.' . $this->type . '.field_test'; - $edit = [ - 'settings[target_type]' => 'node', - ]; - $this->drupalPostForm($bundle_path . '/fields/' . $field_name . '/storage', $edit, t('Save field settings')); - - // Try to select the views handler. - $edit = [ - 'settings[handler]' => 'views', - ]; - $this->drupalPostAjaxForm($bundle_path . '/fields/' . $field_name, $edit, 'settings[handler]'); - $this->assertRaw(t('No eligible views were found. <a href=":create">Create a view</a> with an <em>Entity Reference</em> display, or add such a display to an <a href=":existing">existing view</a>.', [ - ':create' => \Drupal::url('views_ui.add'), - ':existing' => \Drupal::url('entity.view.collection'), - ])); - $this->drupalPostForm(NULL, $edit, t('Save settings')); - // If no eligible view is available we should see a message. - $this->assertText('The views entity selection mode requires a view.'); - - // Enable the entity_reference_test module which creates an eligible view. - $this->container->get('module_installer')->install(['entity_reference_test']); - $this->resetAll(); - $this->drupalGet($bundle_path . '/fields/' . $field_name); - $this->drupalPostAjaxForm($bundle_path . '/fields/' . $field_name, $edit, 'settings[handler]'); - $edit = [ - 'settings[handler_settings][view][view_and_display]' => 'test_entity_reference:entity_reference_1', - ]; - $this->drupalPostForm(NULL, $edit, t('Save settings')); - $this->assertResponse(200); - - // Switch the target type to 'entity_test'. - $edit = [ - 'settings[target_type]' => 'entity_test', - ]; - $this->drupalPostForm($bundle_path . '/fields/' . $field_name . '/storage', $edit, t('Save field settings')); - $this->drupalGet($bundle_path . '/fields/' . $field_name); - $edit = [ - 'settings[handler]' => 'views', - ]; - $this->drupalPostAjaxForm($bundle_path . '/fields/' . $field_name, $edit, 'settings[handler]'); - $edit = [ - 'required' => FALSE, - 'settings[handler_settings][view][view_and_display]' => 'test_entity_reference_entity_test:entity_reference_1', - ]; - $this->drupalPostForm(NULL, $edit, t('Save settings')); - $this->assertResponse(200); - // Create a new view and display it as a entity reference. $edit = [ 'id' => 'node_test_view', @@ -253,7 +115,7 @@ public function testFieldAdminHandler() { $edit = [ 'settings[handler]' => 'views', ]; - $this->drupalPostAjaxForm(NULL, $edit, 'settings[handler]'); + $this->drupalPostForm(NULL, $edit, t('Change handler')); $edit = [ 'required' => FALSE, 'settings[handler_settings][view][view_and_display]' => 'node_test_view:entity_reference_1', @@ -275,7 +137,7 @@ public function testFieldAdminHandler() { // Try to add a new node and fill the entity reference field. $this->drupalGet('node/add/' . $this->type); $result = $this->xpath('//input[@name="field_test_entity_ref_field[0][target_id]" and contains(@data-autocomplete-path, "/entity_reference_autocomplete/node/views/")]'); - $target_url = $this->getAbsoluteUrl($result[0]['data-autocomplete-path']); + $target_url = $this->getAbsoluteUrl($result[0]->getAttribute('data-autocomplete-path')); $this->drupalGet($target_url, ['query' => ['q' => 'Foo']]); $this->assertRaw($node1->getTitle() . ' (' . $node1->id() . ')'); $this->assertRaw($node2->getTitle() . ' (' . $node2->id() . ')'); @@ -446,7 +308,8 @@ public function testMultipleTargetBundles() { 'settings[handler_settings][target_bundles][' . $vocabularies[1]->id() . ']' => TRUE, ]; // Enable the second vocabulary as a target bundle. - $this->drupalPostAjaxForm($path, $edit, key($edit)); + $this->drupalPostForm($path, $edit, 'Save settings'); + $this->drupalGet($path); // Expect a select element with the two vocabularies as options. $this->assertFieldByXPath("//select[@name='settings[handler_settings][auto_create_bundle]']/option[@value='" . $vocabularies[0]->id() . "']"); $this->assertFieldByXPath("//select[@name='settings[handler_settings][auto_create_bundle]']/option[@value='" . $vocabularies[1]->id() . "']"); @@ -513,49 +376,23 @@ protected function createEntityReferenceField($target_type, $bundles = []) { * The field name. * @param array $expected_options * An array of expected options. - * - * @return bool - * TRUE if the assertion succeeded, FALSE otherwise. */ protected function assertFieldSelectOptions($name, array $expected_options) { $xpath = $this->buildXPathQuery('//select[@name=:name]', [':name' => $name]); $fields = $this->xpath($xpath); if ($fields) { $field = $fields[0]; - $options = $this->getAllOptionsList($field); - + $options = $field->findAll('xpath', 'option'); + array_walk($options, function (NodeElement &$option) { + $option = $option->getValue(); + }); sort($options); sort($expected_options); - - return $this->assertIdentical($options, $expected_options); + $this->assertIdentical($options, $expected_options); } else { - return $this->fail('Unable to find field ' . $name); + $this->fail('Unable to find field ' . $name); } } - /** - * Extracts all options from a select element. - * - * @param \SimpleXMLElement $element - * The select element field information. - * - * @return array - * An array of option values as strings. - */ - protected function getAllOptionsList(\SimpleXMLElement $element) { - $options = []; - // Add all options items. - foreach ($element->option as $option) { - $options[] = (string) $option['value']; - } - - // Loops trough all the option groups - foreach ($element->optgroup as $optgroup) { - $options = array_merge($this->getAllOptionsList($optgroup), $options); - } - - return $options; - } - } diff --git a/web/core/modules/field/tests/src/Functional/EntityReference/EntityReferenceAutoCreateTest.php b/web/core/modules/field/tests/src/Functional/EntityReference/EntityReferenceAutoCreateTest.php index 84f2b58a07a1e457a2d9afae7a8ab0f131ad2b8a..2e1fabdd533cd334eed5ea8a6a151edb3eaa41f1 100644 --- a/web/core/modules/field/tests/src/Functional/EntityReference/EntityReferenceAutoCreateTest.php +++ b/web/core/modules/field/tests/src/Functional/EntityReference/EntityReferenceAutoCreateTest.php @@ -5,7 +5,7 @@ use Drupal\Core\Field\FieldStorageDefinitionInterface; use Drupal\field\Entity\FieldConfig; use Drupal\Tests\BrowserTestBase; -use Drupal\field\Tests\EntityReference\EntityReferenceTestTrait; +use Drupal\Tests\field\Traits\EntityReferenceTestTrait; use Drupal\taxonomy\Entity\Vocabulary; use Drupal\node\Entity\Node; use Drupal\field\Entity\FieldStorageConfig; diff --git a/web/core/modules/field/tests/src/Functional/EntityReference/EntityReferenceIntegrationTest.php b/web/core/modules/field/tests/src/Functional/EntityReference/EntityReferenceIntegrationTest.php index 11e5b2813be61cb522eace9643a166aaf0f308d3..15326b9952708cc0cc813e5442546345d6414efe 100644 --- a/web/core/modules/field/tests/src/Functional/EntityReference/EntityReferenceIntegrationTest.php +++ b/web/core/modules/field/tests/src/Functional/EntityReference/EntityReferenceIntegrationTest.php @@ -6,8 +6,8 @@ use Drupal\entity_test\Entity\EntityTest; use Drupal\field\Entity\FieldConfig; use Drupal\Tests\BrowserTestBase; -use Drupal\field\Tests\EntityReference\EntityReferenceTestTrait; use Drupal\Tests\config\Traits\AssertConfigEntityImportTrait; +use Drupal\Tests\field\Traits\EntityReferenceTestTrait; /** * Tests various Entity reference UI components. diff --git a/web/core/modules/field/tests/src/Functional/EntityReference/EntityReferenceXSSTest.php b/web/core/modules/field/tests/src/Functional/EntityReference/EntityReferenceXSSTest.php index dc4caea212c5f0bb3532ef1da823fe0b58398a8e..a1867c2589bcec1689360fa31eee4448e05fedd4 100644 --- a/web/core/modules/field/tests/src/Functional/EntityReference/EntityReferenceXSSTest.php +++ b/web/core/modules/field/tests/src/Functional/EntityReference/EntityReferenceXSSTest.php @@ -5,7 +5,7 @@ use Drupal\Core\Entity\Entity\EntityFormDisplay; use Drupal\Core\Entity\Entity\EntityViewDisplay; use Drupal\Tests\BrowserTestBase; -use Drupal\field\Tests\EntityReference\EntityReferenceTestTrait; +use Drupal\Tests\field\Traits\EntityReferenceTestTrait; /** * Tests possible XSS security issues in entity references. diff --git a/web/core/modules/field/tests/src/FunctionalJavascript/EntityReference/EntityReferenceAdminTest.php b/web/core/modules/field/tests/src/FunctionalJavascript/EntityReference/EntityReferenceAdminTest.php new file mode 100644 index 0000000000000000000000000000000000000000..89a8ce1e45cad99d32944516855862b36a747c28 --- /dev/null +++ b/web/core/modules/field/tests/src/FunctionalJavascript/EntityReference/EntityReferenceAdminTest.php @@ -0,0 +1,244 @@ +<?php + +namespace Drupal\Tests\field\FunctionalJavascript\EntityReference; + +use Behat\Mink\Element\NodeElement; +use Drupal\Component\Render\FormattableMarkup; +use Drupal\FunctionalJavascriptTests\WebDriverTestBase; +use Drupal\Tests\field_ui\Traits\FieldUiTestTrait; + +/** + * Tests for the administrative UI. + * + * @group entity_reference + */ +class EntityReferenceAdminTest extends WebDriverTestBase { + + use FieldUiTestTrait; + + /** + * Modules to install. + * + * Enable path module to ensure that the selection handler does not fail for + * entities with a path field. + * + * @var array + */ + public static $modules = ['node', 'field_ui', 'path', 'taxonomy', 'block', 'views_ui']; + + /** + * The name of the content type created for testing purposes. + * + * @var string + */ + protected $type; + + /** + * {@inheritdoc} + */ + protected function setUp() { + parent::setUp(); + $this->drupalPlaceBlock('system_breadcrumb_block'); + + // Create a content type, with underscores. + $type_name = strtolower($this->randomMachineName(8)) . '_test'; + $type = $this->drupalCreateContentType(['name' => $type_name, 'type' => $type_name]); + $this->type = $type->id(); + + // Create test user. + $admin_user = $this->drupalCreateUser([ + 'access content', + 'administer node fields', + 'administer node display', + 'administer views', + 'create ' . $type_name . ' content', + 'edit own ' . $type_name . ' content', + ]); + $this->drupalLogin($admin_user); + } + + /** + * Tests the Entity Reference Admin UI. + */ + public function testFieldAdminHandler() { + $bundle_path = 'admin/structure/types/manage/' . $this->type; + + $page = $this->getSession()->getPage(); + $assert_session = $this->assertSession(); + + // First step: 'Add new field' on the 'Manage fields' page. + $this->drupalGet($bundle_path . '/fields/add-field'); + + // Check if the commonly referenced entity types appear in the list. + $this->assertOption('edit-new-storage-type', 'field_ui:entity_reference:node'); + $this->assertOption('edit-new-storage-type', 'field_ui:entity_reference:user'); + + $page->findField('new_storage_type')->setValue('entity_reference'); + $assert_session->waitForField('label')->setValue('Test'); + $machine_name = $assert_session->waitForElement('xpath', '//*[@id="edit-label-machine-name-suffix"]/span[2]/span[contains(text(), "field_test")]'); + $this->assertNotEmpty($machine_name); + $page->pressButton('Save and continue'); + + // Node should be selected by default. + $this->assertFieldByName('settings[target_type]', 'node'); + + // Check that all entity types can be referenced. + $this->assertFieldSelectOptions('settings[target_type]', array_keys(\Drupal::entityManager()->getDefinitions())); + + // Second step: 'Field settings' form. + $this->drupalPostForm(NULL, [], t('Save field settings')); + + // The base handler should be selected by default. + $this->assertFieldByName('settings[handler]', 'default:node'); + + // The base handler settings should be displayed. + $entity_type_id = 'node'; + // Check that the type label is correctly displayed. + $assert_session->pageTextContains('Content type'); + $bundles = $this->container->get('entity_type.bundle.info')->getBundleInfo($entity_type_id); + foreach ($bundles as $bundle_name => $bundle_info) { + $this->assertFieldByName('settings[handler_settings][target_bundles][' . $bundle_name . ']'); + } + + reset($bundles); + + // Test the sort settings. + // Option 0: no sort. + $this->assertFieldByName('settings[handler_settings][sort][field]', '_none'); + $this->assertNoFieldByName('settings[handler_settings][sort][direction]'); + // Option 1: sort by field. + $page->findField('settings[handler_settings][sort][field]')->setValue('nid'); + $assert_session->waitForField('settings[handler_settings][sort][direction]'); + $this->assertFieldByName('settings[handler_settings][sort][direction]', 'ASC'); + + // Test that a non-translatable base field is a sort option. + $this->assertFieldByXPath("//select[@name='settings[handler_settings][sort][field]']/option[@value='nid']"); + // Test that a translatable base field is a sort option. + $this->assertFieldByXPath("//select[@name='settings[handler_settings][sort][field]']/option[@value='title']"); + // Test that a configurable field is a sort option. + $this->assertFieldByXPath("//select[@name='settings[handler_settings][sort][field]']/option[@value='body.value']"); + + // Set back to no sort. + $page->findField('settings[handler_settings][sort][field]')->setValue('_none'); + $assert_session->assertWaitOnAjaxRequest(); + $this->assertNoFieldByName('settings[handler_settings][sort][direction]'); + + // Third step: confirm. + $page->findField('settings[handler_settings][target_bundles][' . key($bundles) . ']')->setValue(key($bundles)); + $assert_session->assertWaitOnAjaxRequest(); + $this->drupalPostForm(NULL, [ + 'required' => '1', + ], t('Save settings')); + + // Check that the field appears in the overview form. + $this->assertFieldByXPath('//table[@id="field-overview"]//tr[@id="field-test"]/td[1]', 'Test', 'Field was created and appears in the overview page.'); + + // Check that the field settings form can be submitted again, even when the + // field is required. + // The first 'Edit' link is for the Body field. + $this->clickLink(t('Edit'), 1); + $this->drupalPostForm(NULL, [], t('Save settings')); + + // Switch the target type to 'taxonomy_term' and check that the settings + // specific to its selection handler are displayed. + $field_name = 'node.' . $this->type . '.field_test'; + $edit = [ + 'settings[target_type]' => 'taxonomy_term', + ]; + $this->drupalPostForm($bundle_path . '/fields/' . $field_name . '/storage', $edit, t('Save field settings')); + $this->drupalGet($bundle_path . '/fields/' . $field_name); + $this->assertFieldByName('settings[handler_settings][auto_create]'); + + // Switch the target type to 'user' and check that the settings specific to + // its selection handler are displayed. + $field_name = 'node.' . $this->type . '.field_test'; + $edit = [ + 'settings[target_type]' => 'user', + ]; + $this->drupalPostForm($bundle_path . '/fields/' . $field_name . '/storage', $edit, t('Save field settings')); + $this->drupalGet($bundle_path . '/fields/' . $field_name); + $this->assertFieldByName('settings[handler_settings][filter][type]', '_none'); + + // Switch the target type to 'node'. + $field_name = 'node.' . $this->type . '.field_test'; + $edit = [ + 'settings[target_type]' => 'node', + ]; + $this->drupalPostForm($bundle_path . '/fields/' . $field_name . '/storage', $edit, t('Save field settings')); + + // Try to select the views handler. + $this->drupalGet($bundle_path . '/fields/' . $field_name); + $page->findField('settings[handler]')->setValue('views'); + $views_text = (string) new FormattableMarkup('No eligible views were found. <a href=":create">Create a view</a> with an <em>Entity Reference</em> display, or add such a display to an <a href=":existing">existing view</a>.', [ + ':create' => \Drupal::url('views_ui.add'), + ':existing' => \Drupal::url('entity.view.collection'), + ]); + $assert_session->waitForElement('xpath', '//a[contains(text(), "Create a view")]'); + $assert_session->responseContains($views_text); + + $this->drupalPostForm(NULL, [], t('Save settings')); + // If no eligible view is available we should see a message. + $assert_session->pageTextContains('The views entity selection mode requires a view.'); + + // Enable the entity_reference_test module which creates an eligible view. + $this->container->get('module_installer') + ->install(['entity_reference_test']); + $this->resetAll(); + $this->drupalGet($bundle_path . '/fields/' . $field_name); + $page->findField('settings[handler]')->setValue('views'); + $assert_session + ->waitForField('settings[handler_settings][view][view_and_display]') + ->setValue('test_entity_reference:entity_reference_1'); + $this->drupalPostForm(NULL, [], t('Save settings')); + $assert_session->pageTextContains('Saved Test configuration.'); + + // Switch the target type to 'entity_test'. + $edit = [ + 'settings[target_type]' => 'entity_test', + ]; + $this->drupalPostForm($bundle_path . '/fields/' . $field_name . '/storage', $edit, t('Save field settings')); + $this->drupalGet($bundle_path . '/fields/' . $field_name); + $page->findField('settings[handler]')->setValue('views'); + $assert_session + ->waitForField('settings[handler_settings][view][view_and_display]') + ->setValue('test_entity_reference_entity_test:entity_reference_1'); + $edit = [ + 'required' => FALSE, + ]; + $this->drupalPostForm(NULL, $edit, t('Save settings')); + $assert_session->pageTextContains('Saved Test configuration.'); + } + + /** + * Checks if a select element contains the specified options. + * + * @param string $name + * The field name. + * @param array $expected_options + * An array of expected options. + */ + protected function assertFieldSelectOptions($name, array $expected_options) { + $xpath = $this->buildXPathQuery('//select[@name=:name]', [':name' => $name]); + $fields = $this->xpath($xpath); + if ($fields) { + $field = $fields[0]; + $options = $field->findAll('xpath', 'option'); + $optgroups = $field->findAll('xpath', 'optgroup'); + foreach ($optgroups as $optgroup) { + $options = array_merge($options, $optgroup->findAll('xpath', 'option')); + } + array_walk($options, function (NodeElement &$option) { + $option = $option->getAttribute('value'); + }); + + sort($options); + sort($expected_options); + + $this->assertIdentical($options, $expected_options); + } + else { + $this->fail('Unable to find field ' . $name); + } + } + +} diff --git a/web/core/modules/field/tests/src/Kernel/DisplayApiTest.php b/web/core/modules/field/tests/src/Kernel/DisplayApiTest.php index 3cbf63eb19beea0bd4c88a52a1c3f8fbe6aece8b..0afb23700c5a4ab3c5340ac5b4b3be0661147899 100644 --- a/web/core/modules/field/tests/src/Kernel/DisplayApiTest.php +++ b/web/core/modules/field/tests/src/Kernel/DisplayApiTest.php @@ -31,7 +31,7 @@ class DisplayApiTest extends FieldKernelTestBase { /** * The field cardinality to use in this test. * - * @var number + * @var int */ protected $cardinality; diff --git a/web/core/modules/field/tests/src/Kernel/EntityReference/EntityReferenceFormatterTest.php b/web/core/modules/field/tests/src/Kernel/EntityReference/EntityReferenceFormatterTest.php index dd9e7d4c0860c4eb7103d4b34a78cef1baf67182..88a693277c8be11503e0e136b90e380c25060fab 100644 --- a/web/core/modules/field/tests/src/Kernel/EntityReference/EntityReferenceFormatterTest.php +++ b/web/core/modules/field/tests/src/Kernel/EntityReference/EntityReferenceFormatterTest.php @@ -8,12 +8,12 @@ use Drupal\Core\Field\Plugin\Field\FieldFormatter\EntityReferenceEntityFormatter; use Drupal\field\Entity\FieldConfig; use Drupal\field\Entity\FieldStorageConfig; -use Drupal\field\Tests\EntityReference\EntityReferenceTestTrait; use Drupal\filter\Entity\FilterFormat; use Drupal\KernelTests\Core\Entity\EntityKernelTestBase; use Drupal\user\Entity\Role; use Drupal\user\RoleInterface; use Drupal\entity_test\Entity\EntityTestLabel; +use Drupal\Tests\field\Traits\EntityReferenceTestTrait; /** * Tests the formatters functionality. diff --git a/web/core/modules/field/tests/src/Kernel/EntityReference/EntityReferenceItemTest.php b/web/core/modules/field/tests/src/Kernel/EntityReference/EntityReferenceItemTest.php index 627fdba5dce8f821b0288341db9fde131b1e6fae..c35d1607bfdcfb108ceaa9a725d745cc42b4281f 100644 --- a/web/core/modules/field/tests/src/Kernel/EntityReference/EntityReferenceItemTest.php +++ b/web/core/modules/field/tests/src/Kernel/EntityReference/EntityReferenceItemTest.php @@ -14,7 +14,6 @@ use Drupal\entity_test\Entity\EntityTestStringId; use Drupal\field\Entity\FieldConfig; use Drupal\field\Entity\FieldStorageConfig; -use Drupal\field\Tests\EntityReference\EntityReferenceTestTrait; use Drupal\node\Entity\NodeType; use Drupal\node\NodeInterface; use Drupal\taxonomy\TermInterface; @@ -24,6 +23,7 @@ use Drupal\taxonomy\Entity\Term; use Drupal\taxonomy\Entity\Vocabulary; use Drupal\user\Entity\User; +use Drupal\Tests\field\Traits\EntityReferenceTestTrait; /** * Tests the new entity API for the entity reference field type. diff --git a/web/core/modules/field/tests/src/Kernel/EntityReference/EntityReferenceSettingsTest.php b/web/core/modules/field/tests/src/Kernel/EntityReference/EntityReferenceSettingsTest.php index 93c39257b3624caf1bc9191242980976518c069e..dc3da86dc5a811eef00cdd513f64139f483aa01d 100644 --- a/web/core/modules/field/tests/src/Kernel/EntityReference/EntityReferenceSettingsTest.php +++ b/web/core/modules/field/tests/src/Kernel/EntityReference/EntityReferenceSettingsTest.php @@ -5,10 +5,10 @@ use Drupal\Core\DependencyInjection\ContainerBuilder; use Drupal\Core\Logger\RfcLogLevel; use Drupal\field\Entity\FieldConfig; -use Drupal\field\Tests\EntityReference\EntityReferenceTestTrait; use Drupal\node\Entity\NodeType; use Drupal\KernelTests\KernelTestBase; use Drupal\taxonomy\Entity\Vocabulary; +use Drupal\Tests\field\Traits\EntityReferenceTestTrait; use Symfony\Component\Debug\BufferingLogger; /** diff --git a/web/core/modules/field/tests/src/Kernel/EntityReference/Views/EntityReferenceRelationshipTest.php b/web/core/modules/field/tests/src/Kernel/EntityReference/Views/EntityReferenceRelationshipTest.php index 095e4bd8d8a2a2357ec9eca121822b39977ccf66..b93a4a9c1d9971dd8cdb3a209aaef9884bdea99e 100644 --- a/web/core/modules/field/tests/src/Kernel/EntityReference/Views/EntityReferenceRelationshipTest.php +++ b/web/core/modules/field/tests/src/Kernel/EntityReference/Views/EntityReferenceRelationshipTest.php @@ -4,9 +4,9 @@ use Drupal\entity_test\Entity\EntityTestMulChanged; use Drupal\field\Entity\FieldStorageConfig; -use Drupal\field\Tests\EntityReference\EntityReferenceTestTrait; use Drupal\entity_test\Entity\EntityTest; use Drupal\entity_test\Entity\EntityTestMul; +use Drupal\Tests\field\Traits\EntityReferenceTestTrait; use Drupal\Tests\views\Kernel\ViewsKernelTestBase; use Drupal\views\Tests\ViewTestData; use Drupal\views\Views; @@ -331,6 +331,15 @@ public function testGroupByWithEmptyRelationships() { // Fourth result has no reference from EntityTestMul hence the output for // should be empty. $this->assertEqual('', $view->getStyle()->getField(3, 'name_2')); + + $fields = $view->field; + // Check getValue for reference with a value. The first 3 rows reference + // EntityTestMul, so have value 'name1'. + $this->assertEquals('name1', $fields['name_2']->getValue($view->result[0])); + $this->assertEquals('name1', $fields['name_2']->getValue($view->result[1])); + $this->assertEquals('name1', $fields['name_2']->getValue($view->result[2])); + // Ensure getValue works on empty references. + $this->assertNull($fields['name_2']->getValue($view->result[3])); } } diff --git a/web/core/modules/field/tests/src/Kernel/Migrate/d6/MigrateFieldInstanceLabelDescriptionTest.php b/web/core/modules/field/tests/src/Kernel/Migrate/d6/MigrateFieldInstanceLabelDescriptionTest.php new file mode 100644 index 0000000000000000000000000000000000000000..5d51972d72f589e05d40327ab12c20478a0fa7e4 --- /dev/null +++ b/web/core/modules/field/tests/src/Kernel/Migrate/d6/MigrateFieldInstanceLabelDescriptionTest.php @@ -0,0 +1,134 @@ +<?php + +namespace Drupal\Tests\field\Kernel\Migrate\d6; + +use Drupal\KernelTests\KernelTestBase; +use Drupal\Core\Database\Database; +use Drupal\Tests\migrate\Kernel\MigrateDumpAlterInterface; +use Drupal\Tests\migrate_drupal\Kernel\d6\MigrateDrupal6TestBase; + +/** + * Tests migration field label and description i18n translations. + * + * @group migrate_drupal_6 + * @group legacy + */ +class MigrateFieldInstanceLabelDescriptionTest extends MigrateDrupal6TestBase implements MigrateDumpAlterInterface { + + /** + * {@inheritdoc} + */ + public static $modules = [ + 'config_translation', + 'locale', + 'language', + 'menu_ui', + 'node', + 'field', + ]; + + /** + * {@inheritdoc} + */ + public function setUp() { + parent::setUp(); + $this->migrateFields(); + + $this->installEntitySchema('node'); + $this->installConfig(['node']); + $this->installSchema('node', ['node_access']); + $this->installSchema('system', ['sequences']); + $this->executeMigration('language'); + $this->executeMigration('d6_field_instance_label_description_translation'); + } + + /** + * {@inheritdoc} + */ + public static function migrateDumpAlter(KernelTestBase $test) { + $db = Database::getConnection('default', 'migrate'); + // Alter the database to test the migration is successful when a translated + // field is deleted but the translation data for that field remains in both + // the i18n_strings and locales_target tables. + $db->delete('content_node_field_instance') + ->condition('field_name', 'field_test') + ->condition('type_name', 'story') + ->execute(); + } + + /** + * Tests migration of file variables to file.settings.yml. + */ + public function testFieldInstanceLabelDescriptionTranslationMigration() { + $language_manager = $this->container->get('language_manager'); + + // Tests fields on 'story' node type. + // Check that the deleted field with translations was skipped. + $config_translation = $language_manager->getLanguageConfigOverride('fr', 'field.field.node.story.field_test'); + $this->assertNull($config_translation->get('label')); + $this->assertNull($config_translation->get('description')); + + $config_translation = $language_manager->getLanguageConfigOverride('fr', 'field.field.node.story.field_test_two'); + $this->assertSame("fr - Integer Field", $config_translation->get('label')); + $this->assertSame("fr - An example integer field.", $config_translation->get('description')); + + $config_translation = $language_manager->getLanguageConfigOverride('fr', 'field.field.node.story.field_test_four'); + $this->assertSame("fr - Float Field", $config_translation->get('label')); + $this->assertSame("fr - An example float field.", $config_translation->get('description')); + + $config_translation = $language_manager->getLanguageConfigOverride('fr', 'field.field.node.story.field_test_email'); + $this->assertSame("fr - Email Field", $config_translation->get('label')); + $this->assertSame("fr - An example email field.", $config_translation->get('description')); + + $config_translation = $language_manager->getLanguageConfigOverride('fr', 'field.field.node.story.field_test_imagefield'); + $this->assertSame("fr - Image Field", $config_translation->get('label')); + $this->assertSame("fr - An example image field.", $config_translation->get('description')); + + $config_translation = $language_manager->getLanguageConfigOverride('zu', 'field.field.node.story.field_test_imagefield'); + $this->assertSame("zu - Image Field", $config_translation->get('label')); + $this->assertSame("zu - An example image field.", $config_translation->get('description')); + + $config_translation = $language_manager->getLanguageConfigOverride('fr', 'field.field.node.story.field_test_filefield'); + $this->assertSame("fr - File Field", $config_translation->get('label')); + $this->assertSame("fr - An example file field.", $config_translation->get('description')); + + $config_translation = $language_manager->getLanguageConfigOverride('fr', 'field.field.node.story.field_test_link'); + $this->assertSame("fr - Link Field", $config_translation->get('label')); + $this->assertSame("fr - An example link field.", $config_translation->get('description')); + + $config_translation = $language_manager->getLanguageConfigOverride('fr', 'field.field.node.story.field_test_date'); + $this->assertSame("fr - Date Field", $config_translation->get('label')); + $this->assertSame("fr - An example date field.", $config_translation->get('description')); + + $config_translation = $language_manager->getLanguageConfigOverride('fr', 'field.field.node.story.field_test_datetime'); + $this->assertSame("fr - Datetime Field", $config_translation->get('label')); + $this->assertSame("fr - An example datetime field.", $config_translation->get('description')); + + $config_translation = $language_manager->getLanguageConfigOverride('fr', 'field.field.node.story.field_test_datestamp'); + $this->assertSame("fr - Date Stamp Field", $config_translation->get('label')); + $this->assertSame("fr - An example date stamp field.", $config_translation->get('description')); + + $config_translation = $language_manager->getLanguageConfigOverride('fr', 'field.field.node.story.field_test_date'); + $this->assertSame("fr - Date Field", $config_translation->get('label')); + $this->assertSame("fr - An example date field.", $config_translation->get('description')); + + $config_translation = $language_manager->getLanguageConfigOverride('fr', 'field.field.node.story.field_test_phone'); + $this->assertSame("fr - Phone Field", $config_translation->get('label')); + $this->assertSame("fr - An example phone field.", $config_translation->get('description')); + + // Tests fields on 'test_page' node type. + $config_translation = $language_manager->getLanguageConfigOverride('fr', 'field.field.node.test_page.field_test'); + $this->assertSame("Champ de texte", $config_translation->get('label')); + $this->assertSame("fr - An example text field.", $config_translation->get('description')); + + // Tests fields on 'test_planet' node type. + $config_translation = $language_manager->getLanguageConfigOverride('fr', 'field.field.node.test_planet.field_multivalue'); + $this->assertSame("fr - Decimal Field", $config_translation->get('label')); + $this->assertSame("Un exemple plusieurs valeurs champ décimal.", $config_translation->get('description')); + + $config_translation = $language_manager->getLanguageConfigOverride('fr', 'field.field.node.test_planet.field_test_text_single_checkbox'); + $this->assertNull($config_translation->get('label')); + $this->assertSame('fr - An example text field using a single on/off checkbox.', $config_translation->get('description')); + } + +} diff --git a/web/core/modules/field/tests/src/Kernel/Migrate/d6/MigrateFieldInstanceOptionTranslationTest.php b/web/core/modules/field/tests/src/Kernel/Migrate/d6/MigrateFieldInstanceOptionTranslationTest.php new file mode 100644 index 0000000000000000000000000000000000000000..c413e3fa0103b82b9bf492b9aa691271d9bc02f0 --- /dev/null +++ b/web/core/modules/field/tests/src/Kernel/Migrate/d6/MigrateFieldInstanceOptionTranslationTest.php @@ -0,0 +1,75 @@ +<?php + +namespace Drupal\Tests\field\Kernel\Migrate\d6; + +use Drupal\Tests\migrate_drupal\Kernel\d6\MigrateDrupal6TestBase; + +/** + * Migrate field instance option translations. + * + * @group migrate_drupal_6 + */ +class MigrateFieldInstanceOptionTranslationTest extends MigrateDrupal6TestBase { + + /** + * {@inheritdoc} + */ + public static $modules = + [ + 'config_translation', + 'language', + 'locale', + 'menu_ui', + ]; + + /** + * {@inheritdoc} + */ + protected function setUp() { + parent::setUp(); + $this->installConfig(['node']); + $this->executeMigrations([ + 'language', + 'd6_node_type', + 'd6_field', + 'd6_field_instance', + 'd6_field_option_translation', + 'd6_field_instance_option_translation', + ]); + } + + /** + * Tests migration of file variables to file.settings.yml. + */ + public function testFieldInstanceOptionTranslation() { + $language_manager = $this->container->get('language_manager'); + + /** @var \Drupal\language\Config\LanguageConfigOverride $config_translation */ + $config_translation = $language_manager->getLanguageConfigOverride('fr', 'field.field.node.story.field_test_float_single_checkbox'); + $option_translation = ['on_label' => 'fr - 1.234']; + $this->assertSame($option_translation, $config_translation->get('settings')); + + $config_translation = $language_manager->getLanguageConfigOverride('zu', 'field.field.node.story.field_test_float_single_checkbox'); + $option_translation = ['on_label' => 'zu - 1.234']; + $this->assertSame($option_translation, $config_translation->get('settings')); + + $config_translation = $language_manager->getLanguageConfigOverride('fr', 'field.field.node.story.field_test_text_single_checkbox'); + $option_translation = [ + 'off_label' => 'fr - Hello', + 'on_label' => 'fr - Goodbye', + ]; + $this->assertSame($option_translation, $config_translation->get('settings')); + + $config_translation = $language_manager->getLanguageConfigOverride('fr', 'field.field.node.story.field_test_text_single_checkbox2'); + $option_translation = [ + 'off_label' => 'fr - Off', + 'on_label' => 'fr - Hello', + ]; + $this->assertSame($option_translation, $config_translation->get('settings')); + + $config_translation = $language_manager->getLanguageConfigOverride('zu', 'field.field.node.story.field_test_text_single_checkbox2'); + $option_translation = ['on_label' => 'zu - Hello']; + $this->assertSame($option_translation, $config_translation->get('settings')); + } + +} diff --git a/web/core/modules/field/tests/src/Kernel/Migrate/d6/MigrateFieldOptionTranslationTest.php b/web/core/modules/field/tests/src/Kernel/Migrate/d6/MigrateFieldOptionTranslationTest.php new file mode 100644 index 0000000000000000000000000000000000000000..af0e57e1b5f4eada0b4319f4b340a363fb0d7f33 --- /dev/null +++ b/web/core/modules/field/tests/src/Kernel/Migrate/d6/MigrateFieldOptionTranslationTest.php @@ -0,0 +1,84 @@ +<?php + +namespace Drupal\Tests\field\Kernel\Migrate\d6; + +use Drupal\Tests\migrate_drupal\Kernel\d6\MigrateDrupal6TestBase; + +/** + * Migrate field option translations. + * + * @group migrate_drupal_6 + */ +class MigrateFieldOptionTranslationTest extends MigrateDrupal6TestBase { + + /** + * {@inheritdoc} + */ + public static $modules = [ + 'config_translation', + 'language', + 'locale', + 'menu_ui', + ]; + + /** + * {@inheritdoc} + */ + protected function setUp() { + parent::setUp(); + $this->executeMigrations([ + 'language', + 'd6_field', + 'd6_field_option_translation', + ]); + } + + /** + * Tests the Drupal 6 field to Drupal 8 migration. + */ + public function testFieldOptionTranslation() { + $language_manager = $this->container->get('language_manager'); + + // Test a select list with allowed values of key only. + /** @var \Drupal\language\Config\LanguageConfigOverride $config_translation */ + $config_translation = $language_manager->getLanguageConfigOverride('fr', 'field.storage.node.field_test_integer_selectlist'); + $allowed_values = [ + 1 => [ + 'label' => 'fr - 2341', + ], + 3 => [ + 'label' => 'fr - 4123', + ], + ]; + $this->assertSame($allowed_values, $config_translation->get('settings.allowed_values')); + + $config_translation = $language_manager->getLanguageConfigOverride('zu', 'field.storage.node.field_test_integer_selectlist'); + $allowed_values = [ + 1 => [ + 'label' => 'zu - 2341', + ], + ]; + $this->assertSame($allowed_values, $config_translation->get('settings.allowed_values')); + + // Test a select list with allowed values of key|label. + $config_translation = $language_manager->getLanguageConfigOverride('fr', 'field.storage.node.field_test_string_selectlist'); + $allowed_values = [ + 0 => [ + 'label' => 'Noir', + ], + ]; + $this->assertSame($allowed_values, $config_translation->get('settings.allowed_values')); + + $config_translation = $language_manager->getLanguageConfigOverride('zu', 'field.storage.node.field_test_string_selectlist'); + $allowed_values = [ + 0 => [ + 'label' => 'Okumnyama', + ], + 1 => [ + 'label' => 'Mhlophe', + ], + ]; + $this->assertSame($allowed_values, $config_translation->get('settings.allowed_values')); + } + +} diff --git a/web/core/modules/field/tests/src/Kernel/Plugin/migrate/source/d6/FieldInstanceLabelDescriptionTranslationTest.php b/web/core/modules/field/tests/src/Kernel/Plugin/migrate/source/d6/FieldInstanceLabelDescriptionTranslationTest.php new file mode 100644 index 0000000000000000000000000000000000000000..c7dbf27790e87d19d30bafefd74a006604b9b8c9 --- /dev/null +++ b/web/core/modules/field/tests/src/Kernel/Plugin/migrate/source/d6/FieldInstanceLabelDescriptionTranslationTest.php @@ -0,0 +1,79 @@ +<?php + +namespace Drupal\Tests\field\Kernel\Plugin\migrate\source\d6; + +use Drupal\Tests\migrate\Kernel\MigrateSqlSourceTestBase; + +/** + * Tests the field label and description translation source plugin. + * + * @covers \Drupal\field\Plugin\migrate\source\d6\FieldLabelDescriptionTranslation + * @group migrate_drupal + */ +class FieldInstanceLabelDescriptionTranslationTest extends MigrateSqlSourceTestBase { + + /** + * {@inheritdoc} + */ + public static $modules = ['config_translation', 'migrate_drupal', 'field']; + + /** + * {@inheritdoc} + */ + public function providerSource() { + $test = []; + + // The source data. + $test[0]['source_data'] = [ + 'i18n_strings' => [ + [ + 'lid' => 10, + 'objectid' => 'story-field_test_two', + 'type' => 'field', + 'property' => 'widget_label', + ], + [ + 'lid' => 11, + 'objectid' => 'story-field_test_two', + 'type' => 'field', + 'property' => 'widget_description', + ], + [ + 'lid' => 12, + 'objectid' => 'story-field_test_two', + 'type' => 'field', + 'property' => 'widget_description', + ], + ], + 'locales_target' => [ + [ + 'lid' => 10, + 'translation' => "fr - Integer Field", + 'language' => 'fr', + ], + [ + 'lid' => 11, + 'translation' => 'fr - An example integer field.', + 'language' => 'fr', + ], + ], + ]; + + $test[0]['expected_results'] = [ + [ + 'property' => 'widget_label', + 'translation' => "fr - Integer Field", + 'language' => 'fr', + 'lid' => '10', + ], + [ + 'property' => 'widget_description', + 'translation' => 'fr - An example integer field.', + 'language' => 'fr', + 'lid' => '11', + ], + ]; + return $test; + } + +} diff --git a/web/core/modules/field/tests/src/Kernel/Plugin/migrate/source/d6/FieldInstanceOptionTranslationTest.php b/web/core/modules/field/tests/src/Kernel/Plugin/migrate/source/d6/FieldInstanceOptionTranslationTest.php new file mode 100644 index 0000000000000000000000000000000000000000..ee6548853ec711c0e50301bb5d5773563f2b6b63 --- /dev/null +++ b/web/core/modules/field/tests/src/Kernel/Plugin/migrate/source/d6/FieldInstanceOptionTranslationTest.php @@ -0,0 +1,34 @@ +<?php + +namespace Drupal\Tests\field\Kernel\Plugin\migrate\source\d6; + +/** + * Tests the field instance option translation source plugin. + * + * @covers \Drupal\field\Plugin\migrate\source\d6\FieldInstanceOptionTranslation + * @group migrate_drupal + */ +class FieldInstanceOptionTranslationTest extends FieldOptionTranslationTest { + + /** + * {@inheritdoc} + */ + public static $modules = ['field', 'migrate_drupal']; + + /** + * {@inheritdoc} + */ + public function providerSource() { + $test = parent::providerSource(); + + // FieldInstanceOptionTranslation extends FieldOptionTranslation so the + // same test can be used with the addition of the 'type' field to the + // output. + $test[0]['expected_results'][0]['type'] = 'text'; + $test[0]['expected_results'][1]['type'] = 'text'; + $test[0]['expected_results'][2]['type'] = 'number_integer'; + $test[0]['expected_results'][3]['type'] = 'number_integer'; + return $test; + } + +} diff --git a/web/core/modules/field/tests/src/Kernel/Plugin/migrate/source/d6/FieldOptionTranslationTest.php b/web/core/modules/field/tests/src/Kernel/Plugin/migrate/source/d6/FieldOptionTranslationTest.php new file mode 100644 index 0000000000000000000000000000000000000000..8503a3f581fa8b652227a61400b50c8de1f3f233 --- /dev/null +++ b/web/core/modules/field/tests/src/Kernel/Plugin/migrate/source/d6/FieldOptionTranslationTest.php @@ -0,0 +1,242 @@ +<?php + +namespace Drupal\Tests\field\Kernel\Plugin\migrate\source\d6; + +use Drupal\Tests\migrate\Kernel\MigrateSqlSourceTestBase; + +/** + * Tests the field option translation source plugin. + * + * @covers \Drupal\field\Plugin\migrate\source\d6\FieldOptionTranslation + * @group migrate_drupal + */ +class FieldOptionTranslationTest extends MigrateSqlSourceTestBase { + + /** + * {@inheritdoc} + */ + public static $modules = ['field', 'migrate_drupal']; + + /** + * {@inheritdoc} + */ + public function providerSource() { + $test = []; + + // The source data. + $test[0]['source_data']['content_node_field'] = [ + [ + 'field_name' => 'field_test_text_single_checkbox', + 'type' => 'text', + 'global_settings' => 'a:4:{s:15:"text_processing";s:1:"0";s:10:"max_length";s:0:"";s:14:"allowed_values";s:10:"Off\\nHello";s:18:"allowed_values_php";s:0:"";}', + 'required' => 0, + 'multiple' => 0, + 'db_storage' => 1, + 'module' => 'text', + ], + [ + 'field_name' => 'field_test_integer_selectlist', + 'type' => 'number_integer', + 'global_settings' => 'a:6:{s:6:"prefix";s:0:"";s:6:"suffix";s:0:"";s:3:"min";s:0:"";s:3:"max";s:0:"";s:14:"allowed_values";s:22:"1234\\n2341\\n3412\\n4123";s:18:"allowed_values_php";s:0:"";}', + 'required' => 0, + 'multiple' => 0, + 'db_storage' => 1, + 'module' => 'text', + ], + ]; + $test[0]['source_data']['content_node_field_instance'] = [ + [ + 'field_name' => 'field_test_text_single_checkbox', + 'type_name' => 'story', + 'weight' => 1, + 'label' => 'Text Single Checkbox Field', + 'widget_type' => 'optionwidgets_onoff', + 'description' => 'An example text field using a single on/off checkbox.', + 'widget_module' => 'optionwidgets', + 'widget_active' => 1, + 'required' => 1, + 'active' => 1, + 'global_settings' => 'a:0;', + 'widget_settings' => 'a:0;', + 'display_settings' => 'a:0;', + ], + [ + 'field_name' => 'field_test_integer_selectlist', + 'type_name' => 'story', + 'weight' => 1, + 'label' => 'Integer Select List Field', + 'widget_type' => 'optionwidgets_select', + 'description' => 'An example integer field using a select list.', + 'widget_module' => 'optionwidgets', + 'widget_active' => 1, + 'required' => 1, + 'active' => 1, + 'global_settings' => 'a:0;', + 'widget_settings' => 'a:0;', + 'display_settings' => 'a:0;', + ], + ]; + + $test[0]['source_data']['i18n_strings'] = [ + [ + 'lid' => 10, + 'objectid' => 'field_test_text_single_checkbox', + 'type' => 'field', + 'property' => 'option_0', + 'objectindex' => 0, + 'format' => 0, + ], + [ + 'lid' => 11, + 'objectid' => 'field_test_text_single_checkbox', + 'type' => 'field', + 'property' => 'option_1', + 'objectindex' => 0, + 'format' => 0, + ], + [ + 'lid' => 20, + 'objectid' => 'field_test_integer_selectlist', + 'type' => 'field', + 'property' => 'option_1234', + 'objectindex' => 0, + 'format' => 0, + ], + [ + 'lid' => 21, + 'objectid' => 'field_test_integer_selectlist', + 'type' => 'field', + 'property' => 'option_4123', + 'objectindex' => 0, + 'format' => 0, + ], + ]; + $test[0]['source_data']['locales_target'] = [ + [ + 'lid' => 10, + 'translation' => "fr - Hello", + 'language' => 'fr', + 'plid' => 0, + 'plural' => 0, + 'i18n_status' => 0, + ], + [ + 'lid' => 11, + 'translation' => 'fr - Goodbye', + 'language' => 'fr', + 'plid' => 0, + 'plural' => 0, + 'i18n_status' => 0, + ], + [ + 'lid' => 20, + 'translation' => "fr - 4444", + 'language' => 'fr', + 'plid' => 0, + 'plural' => 0, + 'i18n_status' => 0, + ], + [ + 'lid' => 21, + 'translation' => 'fr - 5555', + 'language' => 'fr', + 'plid' => 0, + 'plural' => 0, + 'i18n_status' => 0, + ], + ]; + + $test[0]['expected_results'] = [ + [ + 'field_name' => 'field_test_text_single_checkbox', + 'type' => 'text', + 'widget_type' => 'optionwidgets_onoff', + 'global_settings' => [ + 'allowed_values' => 'Off\nHello', + 'allowed_values_php' => '', + 'max_length' => '', + 'text_processing' => '0', + ], + 'db_columns' => '', + 'property' => 'option_0', + 'objectid' => 'field_test_text_single_checkbox', + 'language' => 'fr', + 'translation' => 'fr - Hello', + 'objectindex' => 0, + 'format' => 0, + 'plid' => 0, + 'plural' => 0, + 'i18n_status' => 0, + ], + [ + 'field_name' => 'field_test_text_single_checkbox', + 'type' => 'text', + 'widget_type' => 'optionwidgets_onoff', + 'global_settings' => [ + 'allowed_values' => 'Off\nHello', + 'allowed_values_php' => '', + 'max_length' => '', + 'text_processing' => '0', + ], + 'db_columns' => '', + 'property' => 'option_1', + 'objectid' => 'field_test_text_single_checkbox', + 'language' => 'fr', + 'translation' => 'fr - Goodbye', + 'objectindex' => 0, + 'format' => 0, + 'plid' => 0, + 'plural' => 0, + 'i18n_status' => 0, + ], + [ + 'field_name' => 'field_test_integer_selectlist', + 'type' => 'number_integer', + 'widget_type' => 'optionwidgets_select', + 'global_settings' => [ + 'allowed_values' => '1234\n2341\n3412\n4123', + 'max' => '', + 'min' => '', + 'prefix' => '', + 'suffix' => '', + 'allowed_values_php' => '', + ], + 'db_columns' => '', + 'property' => 'option_1234', + 'objectid' => 'field_test_integer_selectlist', + 'language' => 'fr', + 'translation' => 'fr - 4444', + 'objectindex' => 0, + 'format' => 0, + 'plid' => 0, + 'plural' => 0, + 'i18n_status' => 0, + ], + [ + 'field_name' => 'field_test_integer_selectlist', + 'type' => 'number_integer', + 'widget_type' => 'optionwidgets_select', + 'global_settings' => [ + 'allowed_values' => '1234\n2341\n3412\n4123', + 'max' => '', + 'min' => '', + 'prefix' => '', + 'suffix' => '', + 'allowed_values_php' => '', + ], + 'db_columns' => '', + 'property' => 'option_4123', + 'objectid' => 'field_test_integer_selectlist', + 'language' => 'fr', + 'translation' => 'fr - 5555', + 'objectindex' => 0, + 'format' => 0, + 'plid' => 0, + 'plural' => 0, + 'i18n_status' => 0, + ], + ]; + return $test; + } + +} diff --git a/web/core/modules/field/tests/src/Kernel/String/StringFormatterTest.php b/web/core/modules/field/tests/src/Kernel/String/StringFormatterTest.php index ae3a371c81d94bc8e3c1b102d25ce156641efecb..74f16d582a514e7b3e0a581aab770ea75e99abf6 100644 --- a/web/core/modules/field/tests/src/Kernel/String/StringFormatterTest.php +++ b/web/core/modules/field/tests/src/Kernel/String/StringFormatterTest.php @@ -24,6 +24,13 @@ class StringFormatterTest extends KernelTestBase { */ public static $modules = ['field', 'text', 'entity_test', 'system', 'filter', 'user']; + /** + * The entity type manager. + * + * @var \Drupal\Core\Entity\EntityTypeManagerInterface + */ + protected $entityTypeManager; + /** * @var string */ @@ -79,6 +86,8 @@ protected function setUp() { 'settings' => [], ]); $this->display->save(); + + $this->entityTypeManager = \Drupal::entityTypeManager(); } /** @@ -145,7 +154,7 @@ public function testStringFormatter() { $value2 = $this->randomMachineName(); $entity->{$this->fieldName}->value = $value2; $entity->save(); - $entity_new_revision = \Drupal::entityManager()->getStorage('entity_test_rev')->loadRevision($old_revision_id); + $entity_new_revision = $this->entityTypeManager->getStorage('entity_test_rev')->loadRevision($old_revision_id); $this->renderEntityFields($entity, $this->display); $this->assertLink($value2, 0); @@ -154,6 +163,19 @@ public function testStringFormatter() { $this->renderEntityFields($entity_new_revision, $this->display); $this->assertLink($value, 0); $this->assertLinkByHref('/entity_test_rev/' . $entity_new_revision->id() . '/revision/' . $entity_new_revision->getRevisionId() . '/view'); + + // Check that linking to a revisionable entity works if the entity type does + // not specify a 'revision' link template. + $entity_type = clone $this->entityTypeManager->getDefinition('entity_test_rev'); + $link_templates = $entity_type->getLinkTemplates(); + unset($link_templates['revision']); + $entity_type->set('links', $link_templates); + \Drupal::state()->set('entity_test_rev.entity_type', $entity_type); + $this->entityTypeManager->clearCachedDefinitions(); + + $this->renderEntityFields($entity_new_revision, $this->display); + $this->assertLink($value, 0); + $this->assertLinkByHref($entity->url('canonical')); } } diff --git a/web/core/modules/field/tests/src/Traits/EntityReferenceTestTrait.php b/web/core/modules/field/tests/src/Traits/EntityReferenceTestTrait.php new file mode 100644 index 0000000000000000000000000000000000000000..26c4aaa81b5c60692755d7d8f109f18507e726fd --- /dev/null +++ b/web/core/modules/field/tests/src/Traits/EntityReferenceTestTrait.php @@ -0,0 +1,64 @@ +<?php + +namespace Drupal\Tests\field\Traits; + +use Drupal\field\Entity\FieldConfig; +use Drupal\field\Entity\FieldStorageConfig; + +/** + * Provides common functionality for the EntityReference test classes. + */ +trait EntityReferenceTestTrait { + + /** + * Creates a field of an entity reference field storage on the specified bundle. + * + * @param string $entity_type + * The type of entity the field will be attached to. + * @param string $bundle + * The bundle name of the entity the field will be attached to. + * @param string $field_name + * The name of the field; if it already exists, a new instance of the existing + * field will be created. + * @param string $field_label + * The label of the field. + * @param string $target_entity_type + * The type of the referenced entity. + * @param string $selection_handler + * The selection handler used by this field. + * @param array $selection_handler_settings + * An array of settings supported by the selection handler specified above. + * (e.g. 'target_bundles', 'sort', 'auto_create', etc). + * @param int $cardinality + * The cardinality of the field. + * + * @see \Drupal\Core\Entity\Plugin\EntityReferenceSelection\SelectionBase::buildConfigurationForm() + */ + protected function createEntityReferenceField($entity_type, $bundle, $field_name, $field_label, $target_entity_type, $selection_handler = 'default', $selection_handler_settings = [], $cardinality = 1) { + // Look for or add the specified field to the requested entity bundle. + if (!FieldStorageConfig::loadByName($entity_type, $field_name)) { + FieldStorageConfig::create([ + 'field_name' => $field_name, + 'type' => 'entity_reference', + 'entity_type' => $entity_type, + 'cardinality' => $cardinality, + 'settings' => [ + 'target_type' => $target_entity_type, + ], + ])->save(); + } + if (!FieldConfig::loadByName($entity_type, $bundle, $field_name)) { + FieldConfig::create([ + 'field_name' => $field_name, + 'entity_type' => $entity_type, + 'bundle' => $bundle, + 'label' => $field_label, + 'settings' => [ + 'handler' => $selection_handler, + 'handler_settings' => $selection_handler_settings, + ], + ])->save(); + } + } + +} diff --git a/web/core/modules/field_layout/field_layout.install b/web/core/modules/field_layout/field_layout.install index 5956bf1095412e89993b8381d7fd96fb0e8e7094..88882d39289dfd17cf266ac155f9b8fa2e5e4fcf 100644 --- a/web/core/modules/field_layout/field_layout.install +++ b/web/core/modules/field_layout/field_layout.install @@ -6,6 +6,7 @@ */ use Drupal\Core\Cache\Cache; +use Drupal\Core\Entity\Display\EntityDisplayInterface; use Drupal\Core\Entity\Entity\EntityFormDisplay; use Drupal\Core\Entity\Entity\EntityViewDisplay; use Drupal\field_layout\Display\EntityDisplayWithLayoutInterface; @@ -15,8 +16,10 @@ */ function field_layout_install() { // Ensure each entity display has a layout. - $entity_save = function (EntityDisplayWithLayoutInterface $entity) { - $entity->ensureLayout()->save(); + $entity_save = function (EntityDisplayInterface $entity) { + if ($entity instanceof EntityDisplayWithLayoutInterface) { + $entity->ensureLayout()->save(); + } }; array_map($entity_save, EntityViewDisplay::loadMultiple()); array_map($entity_save, EntityFormDisplay::loadMultiple()); @@ -31,8 +34,10 @@ function field_layout_install() { function field_layout_uninstall() { // Reset each entity display to use the one-column layout to best approximate // the absence of layouts. - $entity_save = function (EntityDisplayWithLayoutInterface $entity) { - $entity->setLayoutId('layout_onecol')->save(); + $entity_save = function (EntityDisplayInterface $entity) { + if ($entity instanceof EntityDisplayWithLayoutInterface) { + $entity->setLayoutId('layout_onecol')->save(); + } }; array_map($entity_save, EntityViewDisplay::loadMultiple()); array_map($entity_save, EntityFormDisplay::loadMultiple()); diff --git a/web/core/modules/field_layout/tests/src/FunctionalJavascript/FieldLayoutTest.php b/web/core/modules/field_layout/tests/src/FunctionalJavascript/FieldLayoutTest.php index 9e65b270be7d745b8c81ae708ea1103f95a53a36..8a36c8489f51954974848b6afa58c139ffa9dca0 100644 --- a/web/core/modules/field_layout/tests/src/FunctionalJavascript/FieldLayoutTest.php +++ b/web/core/modules/field_layout/tests/src/FunctionalJavascript/FieldLayoutTest.php @@ -239,6 +239,40 @@ public function testLayoutForms() { $this->assertSession()->pageTextContains('Blah: Test text'); } + /** + * Tests changing the formatter and region at the same time. + */ + public function testChangingFormatterAndRegion() { + $assert_session = $this->assertSession(); + $page = $this->getSession()->getPage(); + + // Add the test field to the content region. + $this->drupalGet('entity_test/structure/entity_test/display'); + $page->find('css', '#field-test-text .handle')->dragTo($page->find('css', '.region-content-message')); + $assert_session->assertWaitOnAjaxRequest(); + $page->pressButton('Save'); + $assert_session->fieldValueEquals('fields[field_test_text][region]', 'content'); + $assert_session->fieldValueEquals('fields[field_test_text][type]', 'text_default'); + + // Switch the layout to two columns. + $this->click('#edit-field-layouts'); + $page->selectFieldOption('field_layout', 'layout_twocol'); + $assert_session->assertWaitOnAjaxRequest(); + $page->pressButton('Save'); + $assert_session->fieldValueEquals('fields[field_test_text][region]', 'first'); + + // Change the formatter and move to another region. + $page->selectFieldOption('fields[field_test_text][type]', 'text_trimmed'); + $assert_session->assertWaitOnAjaxRequest(); + $page->find('css', '#field-test-text .handle')->dragTo($page->find('css', '.region-second-message')); + $assert_session->assertWaitOnAjaxRequest(); + $page->pressButton('Save'); + + // Assert that both the formatter and region change are persisted. + $assert_session->fieldValueEquals('fields[field_test_text][region]', 'second'); + $assert_session->fieldValueEquals('fields[field_test_text][type]', 'text_trimmed'); + } + /** * Gets the region titles on the page. * diff --git a/web/core/modules/field_layout/tests/src/Kernel/FieldLayoutUninstallTest.php b/web/core/modules/field_layout/tests/src/Kernel/FieldLayoutUninstallTest.php new file mode 100644 index 0000000000000000000000000000000000000000..387e6b235bb0a34416d3e42cf444e284431a9d81 --- /dev/null +++ b/web/core/modules/field_layout/tests/src/Kernel/FieldLayoutUninstallTest.php @@ -0,0 +1,29 @@ +<?php + +namespace Drupal\Tests\field_layout\Kernel; + +use Drupal\Tests\layout_builder\Kernel\LayoutBuilderCompatibilityTestBase; + +/** + * @group field_layout + */ +class FieldLayoutUninstallTest extends LayoutBuilderCompatibilityTestBase { + + /** + * Ensures field layout can be uninstalled with layout builder enabled. + */ + public function testFieldLayoutUninstall() { + // Setup user schema so user hook uninstall hook doesn't break. + $this->installSchema('user', 'users_data'); + + // Setup layout builder and same displays. + $this->installLayoutBuilder(); + + // Ensure install hook can handle displays without a layout. + $this->container->get('module_installer')->install(['field_layout']); + + // Ensure uninstall hook can handle displays without a layout. + $this->container->get('module_installer')->uninstall(['field_layout']); + } + +} diff --git a/web/core/modules/field_ui/field_ui.es6.js b/web/core/modules/field_ui/field_ui.es6.js index e183704a8dfa4d1e8aaaf9f9c57c267e1a136a1e..f3dd277a79031f94dcd4825ee483bc5633369b2c 100644 --- a/web/core/modules/field_ui/field_ui.es6.js +++ b/web/core/modules/field_ui/field_ui.es6.js @@ -343,16 +343,18 @@ // Set the region of the select list. this.$regionSelect.val(region); - // Restore the formatter back to the default formatter. Pseudo-fields - // do not have default formatters, we just return to 'visible' for - // those. - const value = - typeof this.defaultPlugin !== 'undefined' - ? this.defaultPlugin - : this.$pluginSelect.find('option').val(); - - if (typeof value !== 'undefined') { - this.$pluginSelect.val(value); + // Restore the formatter back to the default formatter only if it was + // disabled previously. Pseudo-fields do not have default formatters, + // we just return to 'visible' for those. + if (this.region === 'hidden') { + const value = + typeof this.defaultPlugin !== 'undefined' + ? this.defaultPlugin + : this.$pluginSelect.find('option').val(); + + if (typeof value !== 'undefined') { + this.$pluginSelect.val(value); + } } const refreshRows = {}; diff --git a/web/core/modules/field_ui/field_ui.js b/web/core/modules/field_ui/field_ui.js index 5cbeb6458b35c366b4d2da6b97f5424a45599492..985790d46ab499b07fcf726f1cfd92df4779d634 100644 --- a/web/core/modules/field_ui/field_ui.js +++ b/web/core/modules/field_ui/field_ui.js @@ -163,10 +163,12 @@ this.$regionSelect.val(region); - var value = typeof this.defaultPlugin !== 'undefined' ? this.defaultPlugin : this.$pluginSelect.find('option').val(); + if (this.region === 'hidden') { + var value = typeof this.defaultPlugin !== 'undefined' ? this.defaultPlugin : this.$pluginSelect.find('option').val(); - if (typeof value !== 'undefined') { - this.$pluginSelect.val(value); + if (typeof value !== 'undefined') { + this.$pluginSelect.val(value); + } } var refreshRows = {}; diff --git a/web/core/modules/field_ui/src/Tests/ManageDisplayTest.php b/web/core/modules/field_ui/src/Tests/ManageDisplayTest.php index 783e7fec21c1aa7fc2e05c44a98dcbd858d9cda6..4975299947c973ecdb33906a7666f8eca0481e9c 100644 --- a/web/core/modules/field_ui/src/Tests/ManageDisplayTest.php +++ b/web/core/modules/field_ui/src/Tests/ManageDisplayTest.php @@ -487,7 +487,7 @@ public function assertNodeViewNoText(EntityInterface $node, $view_mode, $text, $ } /** - * Asserts that a string is (not) found in the rendered nodein a view mode. + * Asserts that a string is (not) found in the rendered node in a view mode. * * This helper function is used by assertNodeViewText() and * assertNodeViewNoText(). diff --git a/web/core/modules/field_ui/src/Tests/FieldUIDeleteTest.php b/web/core/modules/field_ui/tests/src/Functional/FieldUIDeleteTest.php similarity index 96% rename from web/core/modules/field_ui/src/Tests/FieldUIDeleteTest.php rename to web/core/modules/field_ui/tests/src/Functional/FieldUIDeleteTest.php index 631d3368d070cd7ada2edc23c6dfc3bac59304bb..5236905581e486549c55e80e80bd419a47a084c6 100644 --- a/web/core/modules/field_ui/src/Tests/FieldUIDeleteTest.php +++ b/web/core/modules/field_ui/tests/src/Functional/FieldUIDeleteTest.php @@ -1,10 +1,11 @@ <?php -namespace Drupal\field_ui\Tests; +namespace Drupal\Tests\field_ui\Functional; use Drupal\field\Entity\FieldConfig; use Drupal\field\Entity\FieldStorageConfig; -use Drupal\simpletest\WebTestBase; +use Drupal\Tests\BrowserTestBase; +use Drupal\Tests\field_ui\Traits\FieldUiTestTrait; use Drupal\views\Entity\View; use Drupal\views\Tests\ViewTestData; @@ -13,7 +14,7 @@ * * @group field_ui */ -class FieldUIDeleteTest extends WebTestBase { +class FieldUIDeleteTest extends BrowserTestBase { use FieldUiTestTrait; diff --git a/web/core/modules/field_ui/src/Tests/ManageFieldsTest.php b/web/core/modules/field_ui/tests/src/Functional/ManageFieldsFunctionalTest.php similarity index 95% rename from web/core/modules/field_ui/src/Tests/ManageFieldsTest.php rename to web/core/modules/field_ui/tests/src/Functional/ManageFieldsFunctionalTest.php index bc7a2c54b9da707d5d236bc52e26a1fb2480d0ea..85a5017cb1d129764aa2881660c747b06f9e6850 100644 --- a/web/core/modules/field_ui/src/Tests/ManageFieldsTest.php +++ b/web/core/modules/field_ui/tests/src/Functional/ManageFieldsFunctionalTest.php @@ -1,22 +1,23 @@ <?php -namespace Drupal\field_ui\Tests; +namespace Drupal\Tests\field_ui\Functional; use Drupal\Component\Render\FormattableMarkup; use Drupal\Core\Field\FieldStorageDefinitionInterface; use Drupal\Core\Language\LanguageInterface; -use Drupal\field\Tests\EntityReference\EntityReferenceTestTrait; use Drupal\field\Entity\FieldConfig; use Drupal\field\Entity\FieldStorageConfig; -use Drupal\simpletest\WebTestBase; use Drupal\taxonomy\Entity\Vocabulary; +use Drupal\Tests\BrowserTestBase; +use Drupal\Tests\field\Traits\EntityReferenceTestTrait; +use Drupal\Tests\field_ui\Traits\FieldUiTestTrait; /** * Tests the Field UI "Manage fields" screen. * * @group field_ui */ -class ManageFieldsTest extends WebTestBase { +class ManageFieldsFunctionalTest extends BrowserTestBase { use FieldUiTestTrait; use EntityReferenceTestTrait; @@ -153,17 +154,17 @@ public function manageFieldsPage($type = '') { $url = base_path() . "admin/structure/types/manage/$type/fields/node.$type.body"; foreach ($operation_links as $link) { - switch ($link['title']) { + switch ($link->getAttribute('title')) { case 'Edit field settings.': - $this->assertIdentical($url, (string) $link['href']); + $this->assertIdentical($url, $link->getAttribute('href')); $number_of_links_found++; break; case 'Edit storage settings.': - $this->assertIdentical("$url/storage", (string) $link['href']); + $this->assertIdentical("$url/storage", $link->getAttribute('href')); $number_of_links_found++; break; case 'Delete field.': - $this->assertIdentical("$url/delete", (string) $link['href']); + $this->assertIdentical("$url/delete", $link->getAttribute('href')); $number_of_links_found++; break; } @@ -175,7 +176,7 @@ public function manageFieldsPage($type = '') { /** * Tests adding a new field. * - * @todo Assert properties can bet set in the form and read back in + * @todo Assert properties can be set in the form and read back in * $field_storage and $fields. */ public function createField() { @@ -449,7 +450,7 @@ public function testDefaultValue() { $this->drupalPostForm(NULL, $edit, t('Save settings')); $this->assertText("Saved $field_name configuration", 'The form was successfully submitted.'); $field = FieldConfig::loadByName('node', $this->contentType, $field_name); - $this->assertEqual($field->getDefaultValueLiteral(), NULL, 'The default value was correctly saved.'); + $this->assertEqual($field->getDefaultValueLiteral(), [], 'The default value was correctly saved.'); // Check that the default value can be empty when the field is marked as // required and can store unlimited values. @@ -467,7 +468,7 @@ public function testDefaultValue() { $this->drupalPostForm(NULL, [], t('Save settings')); $this->assertText("Saved $field_name configuration", 'The form was successfully submitted.'); $field = FieldConfig::loadByName('node', $this->contentType, $field_name); - $this->assertEqual($field->getDefaultValueLiteral(), NULL, 'The default value was correctly saved.'); + $this->assertEqual($field->getDefaultValueLiteral(), [], 'The default value was correctly saved.'); // Check that the default widget is used when the field is hidden. entity_get_form_display($field->getTargetEntityTypeId(), $field->getTargetBundle(), 'default') @@ -564,11 +565,7 @@ public function testLockedField() { // Check that the links for edit and delete are not present. $this->drupalGet('admin/structure/types/manage/' . $this->contentType . '/fields'); $locked = $this->xpath('//tr[@id=:field_name]/td[4]', [':field_name' => $field_name]); - $this->assertTrue(in_array('Locked', $locked), 'Field is marked as Locked in the UI'); - $edit_link = $this->xpath('//tr[@id=:field_name]/td[4]', [':field_name' => $field_name]); - $this->assertFalse(in_array('edit', $edit_link), 'Edit option for locked field is not present the UI'); - $delete_link = $this->xpath('//tr[@id=:field_name]/td[4]', [':field_name' => $field_name]); - $this->assertFalse(in_array('delete', $delete_link), 'Delete option for locked field is not present the UI'); + $this->assertSame('Locked', $locked[0]->getHtml(), 'Field is marked as Locked in the UI'); $this->drupalGet('admin/structure/types/manage/' . $this->contentType . '/fields/node.' . $this->contentType . '.' . $field_name . '/delete'); $this->assertResponse(403); } @@ -720,7 +717,7 @@ public function testHelpDescriptions() { public function fieldListAdminPage() { $this->drupalGet('admin/reports/fields'); $this->assertText($this->fieldName, 'Field name is displayed in field list.'); - $this->assertTrue($this->assertLinkByHref('admin/structure/types/manage/' . $this->contentType . '/fields'), 'Link to content type using field is displayed in field list.'); + $this->assertLinkByHref('admin/structure/types/manage/' . $this->contentType . '/fields'); } /** diff --git a/web/core/modules/field_ui/tests/src/Traits/FieldUiTestTrait.php b/web/core/modules/field_ui/tests/src/Traits/FieldUiTestTrait.php new file mode 100644 index 0000000000000000000000000000000000000000..52e75cfc98976d6153538af6e85145df814191c7 --- /dev/null +++ b/web/core/modules/field_ui/tests/src/Traits/FieldUiTestTrait.php @@ -0,0 +1,125 @@ +<?php + +namespace Drupal\Tests\field_ui\Traits; + +/** + * Provides common functionality for the Field UI test classes. + */ +trait FieldUiTestTrait { + + /** + * Creates a new field through the Field UI. + * + * @param string $bundle_path + * Admin path of the bundle that the new field is to be attached to. + * @param string $field_name + * The field name of the new field storage. + * @param string $label + * (optional) The label of the new field. Defaults to a random string. + * @param string $field_type + * (optional) The field type of the new field storage. Defaults to + * 'test_field'. + * @param array $storage_edit + * (optional) $edit parameter for drupalPostForm() on the second step + * ('Storage settings' form). + * @param array $field_edit + * (optional) $edit parameter for drupalPostForm() on the third step ('Field + * settings' form). + */ + public function fieldUIAddNewField($bundle_path, $field_name, $label = NULL, $field_type = 'test_field', array $storage_edit = [], array $field_edit = []) { + $label = $label ?: $this->randomString(); + $initial_edit = [ + 'new_storage_type' => $field_type, + 'label' => $label, + 'field_name' => $field_name, + ]; + + // Allow the caller to set a NULL path in case they navigated to the right + // page before calling this method. + if ($bundle_path !== NULL) { + $bundle_path = "$bundle_path/fields/add-field"; + } + + // First step: 'Add field' page. + $this->drupalPostForm($bundle_path, $initial_edit, t('Save and continue')); + $this->assertRaw(t('These settings apply to the %label field everywhere it is used.', ['%label' => $label]), 'Storage settings page was displayed.'); + // Test Breadcrumbs. + $this->assertLink($label, 0, 'Field label is correct in the breadcrumb of the storage settings page.'); + + // Second step: 'Storage settings' form. + $this->drupalPostForm(NULL, $storage_edit, t('Save field settings')); + $this->assertRaw(t('Updated field %label field settings.', ['%label' => $label]), 'Redirected to field settings page.'); + + // Third step: 'Field settings' form. + $this->drupalPostForm(NULL, $field_edit, t('Save settings')); + $this->assertRaw(t('Saved %label configuration.', ['%label' => $label]), 'Redirected to "Manage fields" page.'); + + // Check that the field appears in the overview form. + $this->assertFieldByXPath('//table[@id="field-overview"]//tr/td[1]', $label, 'Field was created and appears in the overview page.'); + } + + /** + * Adds an existing field through the Field UI. + * + * @param string $bundle_path + * Admin path of the bundle that the field is to be attached to. + * @param string $existing_storage_name + * The name of the existing field storage for which we want to add a new + * field. + * @param string $label + * (optional) The label of the new field. Defaults to a random string. + * @param array $field_edit + * (optional) $edit parameter for drupalPostForm() on the second step + * ('Field settings' form). + */ + public function fieldUIAddExistingField($bundle_path, $existing_storage_name, $label = NULL, array $field_edit = []) { + $label = $label ?: $this->randomString(); + $initial_edit = [ + 'existing_storage_name' => $existing_storage_name, + 'existing_storage_label' => $label, + ]; + + // First step: 'Re-use existing field' on the 'Add field' page. + $this->drupalPostForm("$bundle_path/fields/add-field", $initial_edit, t('Save and continue')); + // Set the main content to only the content region because the label can + // contain HTML which will be auto-escaped by Twig. + $this->assertRaw('field-config-edit-form', 'The field config edit form is present.'); + $this->assertNoRaw('&lt;', 'The page does not have double escaped HTML tags.'); + + // Second step: 'Field settings' form. + $this->drupalPostForm(NULL, $field_edit, t('Save settings')); + $this->assertRaw(t('Saved %label configuration.', ['%label' => $label]), 'Redirected to "Manage fields" page.'); + + // Check that the field appears in the overview form. + $this->assertFieldByXPath('//table[@id="field-overview"]//tr/td[1]', $label, 'Field was created and appears in the overview page.'); + } + + /** + * Deletes a field through the Field UI. + * + * @param string $bundle_path + * Admin path of the bundle that the field is to be deleted from. + * @param string $field_name + * The name of the field. + * @param string $label + * The label of the field. + * @param string $bundle_label + * The label of the bundle. + */ + public function fieldUIDeleteField($bundle_path, $field_name, $label, $bundle_label) { + // Display confirmation form. + $this->drupalGet("$bundle_path/fields/$field_name/delete"); + $this->assertRaw(t('Are you sure you want to delete the field %label', ['%label' => $label]), 'Delete confirmation was found.'); + + // Test Breadcrumbs. + $this->assertLink($label, 0, 'Field label is correct in the breadcrumb of the field delete page.'); + + // Submit confirmation form. + $this->drupalPostForm(NULL, [], t('Delete')); + $this->assertRaw(t('The field %label has been deleted from the %type content type.', ['%label' => $label, '%type' => $bundle_label]), 'Delete message was found.'); + + // Check that the field does not appear in the overview form. + $this->assertNoFieldByXPath('//table[@id="field-overview"]//span[@class="label-field"]', $label, 'Field does not appear in the overview page.'); + } + +} diff --git a/web/core/modules/file/file.es6.js b/web/core/modules/file/file.es6.js index 762a18fb07b891343ce9297c2d06174f4dccc9b1..dc8a807424e33008fbef9bdd83108ba5e85cb1c4 100644 --- a/web/core/modules/file/file.es6.js +++ b/web/core/modules/file/file.es6.js @@ -215,6 +215,7 @@ */ disableFields(event) { const $clickedButton = $(this); + $clickedButton.trigger('formUpdated'); // Check if we're working with an "Upload" button. let $enabledFields = []; diff --git a/web/core/modules/file/file.js b/web/core/modules/file/file.js index 604ccb772f83242bab770ba6805e4f344a6509dd..79aa8288c07810e26c3afb36dcf6bd4104164b49 100644 --- a/web/core/modules/file/file.js +++ b/web/core/modules/file/file.js @@ -96,6 +96,7 @@ }, disableFields: function disableFields(event) { var $clickedButton = $(this); + $clickedButton.trigger('formUpdated'); var $enabledFields = []; if ($clickedButton.closest('div.js-form-managed-file').length > 0) { diff --git a/web/core/modules/file/file.module b/web/core/modules/file/file.module index c0003b350af3d7943d8f3b808605d7b709cd84b4..0eb9a64ec7aad0c633fe21009f8dd449340ccbdd 100644 --- a/web/core/modules/file/file.module +++ b/web/core/modules/file/file.module @@ -23,7 +23,7 @@ /** * The regex pattern used when checking for insecure file types. */ -define('FILE_INSECURE_EXTENSION_REGEX', '/\.(php|pl|py|cgi|asp|js)(\.|$)/i'); +define('FILE_INSECURE_EXTENSION_REGEX', '/\.(phar|php|pl|py|cgi|asp|js)(\.|$)/i'); // Load all Field module hooks for File. require_once __DIR__ . '/file.field.inc'; @@ -859,7 +859,6 @@ function _file_save_upload_from_form(array $element, FormStateInterface $form_st * @todo: move this logic to a service in https://www.drupal.org/node/2244513. */ function file_save_upload($form_field_name, $validators = [], $destination = FALSE, $delta = NULL, $replace = FILE_EXISTS_RENAME) { - $user = \Drupal::currentUser(); static $upload_cache; $all_files = \Drupal::request()->files->get('files', []); @@ -887,182 +886,208 @@ function file_save_upload($form_field_name, $validators = [], $destination = FAL $files = []; foreach ($uploaded_files as $i => $file_info) { - // Check for file upload errors and return FALSE for this file if a lower - // level system error occurred. For a complete list of errors: - // See http://php.net/manual/features.file-upload.errors.php. - switch ($file_info->getError()) { - case UPLOAD_ERR_INI_SIZE: - case UPLOAD_ERR_FORM_SIZE: - \Drupal::messenger()->addError(t('The file %file could not be saved because it exceeds %maxsize, the maximum allowed size for uploads.', ['%file' => $file_info->getFilename(), '%maxsize' => format_size(file_upload_max_size())])); - $files[$i] = FALSE; - continue; - - case UPLOAD_ERR_PARTIAL: - case UPLOAD_ERR_NO_FILE: - \Drupal::messenger()->addError(t('The file %file could not be saved because the upload did not complete.', ['%file' => $file_info->getFilename()])); - $files[$i] = FALSE; - continue; - - case UPLOAD_ERR_OK: - // Final check that this is a valid upload, if it isn't, use the - // default error handler. - if (is_uploaded_file($file_info->getRealPath())) { - break; - } + $files[$i] = _file_save_upload_single($file_info, $form_field_name, $validators, $destination, $replace); + } - // Unknown error - default: - \Drupal::messenger()->addError(t('The file %file could not be saved. An unknown error has occurred.', ['%file' => $file_info->getFilename()])); - $files[$i] = FALSE; - continue; + // Add files to the cache. + $upload_cache[$form_field_name] = $files; - } - // Begin building file entity. - $values = [ - 'uid' => $user->id(), - 'status' => 0, - 'filename' => $file_info->getClientOriginalName(), - 'uri' => $file_info->getRealPath(), - 'filesize' => $file_info->getSize(), - ]; - $values['filemime'] = \Drupal::service('file.mime_type.guesser')->guess($values['filename']); - $file = File::create($values); - - $extensions = ''; - if (isset($validators['file_validate_extensions'])) { - if (isset($validators['file_validate_extensions'][0])) { - // Build the list of non-munged extensions if the caller provided them. - $extensions = $validators['file_validate_extensions'][0]; - } - else { - // If 'file_validate_extensions' is set and the list is empty then the - // caller wants to allow any extension. In this case we have to remove the - // validator or else it will reject all extensions. - unset($validators['file_validate_extensions']); - } - } - else { - // No validator was provided, so add one using the default list. - // Build a default non-munged safe list for file_munge_filename(). - $extensions = 'jpg jpeg gif png txt doc xls pdf ppt pps odt ods odp'; - $validators['file_validate_extensions'] = []; - $validators['file_validate_extensions'][0] = $extensions; - } + return isset($delta) ? $files[$delta] : $files; +} - if (!empty($extensions)) { - // Munge the filename to protect against possible malicious extension - // hiding within an unknown file type (ie: filename.html.foo). - $file->setFilename(file_munge_filename($file->getFilename(), $extensions)); - } +/** + * Saves a file upload to a new location. + * + * @param \SplFileInfo $file_info + * The file upload to save. + * @param string $form_field_name + * A string that is the associative array key of the upload form element in + * the form array. + * @param array $validators + * (optional) An associative array of callback functions used to validate the + * file. + * @param bool $destination + * (optional) A string containing the URI that the file should be copied to. + * @param int $replace + * (optional) The replace behavior when the destination file already exists. + * + * @return \Drupal\file\FileInterface|false + * The created file entity or FALSE if the uploaded file not saved. + * + * @throws \Drupal\Core\Entity\EntityStorageException + * + * @internal + * This method should only be called from file_save_upload(). Use that method + * instead. + * + * @see file_save_upload() + */ +function _file_save_upload_single(\SplFileInfo $file_info, $form_field_name, $validators = [], $destination = FALSE, $replace = FILE_EXISTS_RENAME) { + $user = \Drupal::currentUser(); + // Check for file upload errors and return FALSE for this file if a lower + // level system error occurred. For a complete list of errors: + // See http://php.net/manual/features.file-upload.errors.php. + switch ($file_info->getError()) { + case UPLOAD_ERR_INI_SIZE: + case UPLOAD_ERR_FORM_SIZE: + \Drupal::messenger()->addError(t('The file %file could not be saved because it exceeds %maxsize, the maximum allowed size for uploads.', ['%file' => $file_info->getFilename(), '%maxsize' => format_size(file_upload_max_size())])); + return FALSE; + + case UPLOAD_ERR_PARTIAL: + case UPLOAD_ERR_NO_FILE: + \Drupal::messenger()->addError(t('The file %file could not be saved because the upload did not complete.', ['%file' => $file_info->getFilename()])); + return FALSE; - // Rename potentially executable files, to help prevent exploits (i.e. will - // rename filename.php.foo and filename.php to filename.php.foo.txt and - // filename.php.txt, respectively). Don't rename if 'allow_insecure_uploads' - // evaluates to TRUE. - if (!\Drupal::config('system.file')->get('allow_insecure_uploads') && preg_match(FILE_INSECURE_EXTENSION_REGEX, $file->getFilename()) && (substr($file->getFilename(), -4) != '.txt')) { - $file->setMimeType('text/plain'); - // The destination filename will also later be used to create the URI. - $file->setFilename($file->getFilename() . '.txt'); - // The .txt extension may not be in the allowed list of extensions. We have - // to add it here or else the file upload will fail. - if (!empty($extensions)) { - $validators['file_validate_extensions'][0] .= ' txt'; - \Drupal::messenger()->addStatus(t('For security reasons, your upload has been renamed to %filename.', ['%filename' => $file->getFilename()])); + case UPLOAD_ERR_OK: + // Final check that this is a valid upload, if it isn't, use the + // default error handler. + if (is_uploaded_file($file_info->getRealPath())) { + break; } - } - // If the destination is not provided, use the temporary directory. - if (empty($destination)) { - $destination = 'temporary://'; - } + default: + // Unknown error + \Drupal::messenger()->addError(t('The file %file could not be saved. An unknown error has occurred.', ['%file' => $file_info->getFilename()])); + return FALSE; - // Assert that the destination contains a valid stream. - $destination_scheme = file_uri_scheme($destination); - if (!file_stream_wrapper_valid_scheme($destination_scheme)) { - \Drupal::messenger()->addError(t('The file could not be uploaded because the destination %destination is invalid.', ['%destination' => $destination])); - $files[$i] = FALSE; - continue; + } + // Begin building file entity. + $values = [ + 'uid' => $user->id(), + 'status' => 0, + 'filename' => $file_info->getClientOriginalName(), + 'uri' => $file_info->getRealPath(), + 'filesize' => $file_info->getSize(), + ]; + $values['filemime'] = \Drupal::service('file.mime_type.guesser')->guess($values['filename']); + $file = File::create($values); + + $extensions = ''; + if (isset($validators['file_validate_extensions'])) { + if (isset($validators['file_validate_extensions'][0])) { + // Build the list of non-munged extensions if the caller provided them. + $extensions = $validators['file_validate_extensions'][0]; } - - $file->source = $form_field_name; - // A file URI may already have a trailing slash or look like "public://". - if (substr($destination, -1) != '/') { - $destination .= '/'; + else { + // If 'file_validate_extensions' is set and the list is empty then the + // caller wants to allow any extension. In this case we have to remove the + // validator or else it will reject all extensions. + unset($validators['file_validate_extensions']); } - $file->destination = file_destination($destination . $file->getFilename(), $replace); - // If file_destination() returns FALSE then $replace === FILE_EXISTS_ERROR and - // there's an existing file so we need to bail. - if ($file->destination === FALSE) { - \Drupal::messenger()->addError(t('The file %source could not be uploaded because a file by that name already exists in the destination %directory.', ['%source' => $form_field_name, '%directory' => $destination])); - $files[$i] = FALSE; - continue; + } + else { + // No validator was provided, so add one using the default list. + // Build a default non-munged safe list for file_munge_filename(). + $extensions = 'jpg jpeg gif png txt doc xls pdf ppt pps odt ods odp'; + $validators['file_validate_extensions'] = []; + $validators['file_validate_extensions'][0] = $extensions; + } + + if (!empty($extensions)) { + // Munge the filename to protect against possible malicious extension + // hiding within an unknown file type (ie: filename.html.foo). + $file->setFilename(file_munge_filename($file->getFilename(), $extensions)); + } + + // Rename potentially executable files, to help prevent exploits (i.e. will + // rename filename.php.foo and filename.php to filename.php.foo.txt and + // filename.php.txt, respectively). Don't rename if 'allow_insecure_uploads' + // evaluates to TRUE. + if (!\Drupal::config('system.file')->get('allow_insecure_uploads') && preg_match(FILE_INSECURE_EXTENSION_REGEX, $file->getFilename()) && (substr($file->getFilename(), -4) != '.txt')) { + $file->setMimeType('text/plain'); + // The destination filename will also later be used to create the URI. + $file->setFilename($file->getFilename() . '.txt'); + // The .txt extension may not be in the allowed list of extensions. We have + // to add it here or else the file upload will fail. + if (!empty($extensions)) { + $validators['file_validate_extensions'][0] .= ' txt'; + \Drupal::messenger()->addStatus(t('For security reasons, your upload has been renamed to %filename.', ['%filename' => $file->getFilename()])); } + } - // Add in our check of the file name length. - $validators['file_validate_name_length'] = []; + // If the destination is not provided, use the temporary directory. + if (empty($destination)) { + $destination = 'temporary://'; + } - // Call the validation functions specified by this function's caller. - $errors = file_validate($file, $validators); + // Assert that the destination contains a valid stream. + $destination_scheme = file_uri_scheme($destination); + if (!file_stream_wrapper_valid_scheme($destination_scheme)) { + \Drupal::messenger()->addError(t('The file could not be uploaded because the destination %destination is invalid.', ['%destination' => $destination])); + return FALSE; + } - // Check for errors. - if (!empty($errors)) { - $message = [ - 'error' => [ - '#markup' => t('The specified file %name could not be uploaded.', ['%name' => $file->getFilename()]), - ], - 'item_list' => [ - '#theme' => 'item_list', - '#items' => $errors, - ], - ]; - // @todo Add support for render arrays in - // \Drupal\Core\Messenger\MessengerInterface::addMessage()? - // @see https://www.drupal.org/node/2505497. - \Drupal::messenger()->addError(\Drupal::service('renderer')->renderPlain($message)); - $files[$i] = FALSE; - continue; - } + $file->source = $form_field_name; + // A file URI may already have a trailing slash or look like "public://". + if (substr($destination, -1) != '/') { + $destination .= '/'; + } + $file->destination = file_destination($destination . $file->getFilename(), $replace); + // If file_destination() returns FALSE then $replace === FILE_EXISTS_ERROR and + // there's an existing file so we need to bail. + if ($file->destination === FALSE) { + \Drupal::messenger()->addError(t('The file %source could not be uploaded because a file by that name already exists in the destination %directory.', ['%source' => $form_field_name, '%directory' => $destination])); + return FALSE; + } - $file->setFileUri($file->destination); - if (!drupal_move_uploaded_file($file_info->getRealPath(), $file->getFileUri())) { - \Drupal::messenger()->addError(t('File upload error. Could not move uploaded file.')); - \Drupal::logger('file')->notice('Upload error. Could not move uploaded file %file to destination %destination.', ['%file' => $file->getFilename(), '%destination' => $file->getFileUri()]); - $files[$i] = FALSE; - continue; - } + // Add in our check of the file name length. + $validators['file_validate_name_length'] = []; - // Set the permissions on the new file. - drupal_chmod($file->getFileUri()); + // Call the validation functions specified by this function's caller. + $errors = file_validate($file, $validators); + + // Check for errors. + if (!empty($errors)) { + $message = [ + 'error' => [ + '#markup' => t('The specified file %name could not be uploaded.', ['%name' => $file->getFilename()]), + ], + 'item_list' => [ + '#theme' => 'item_list', + '#items' => $errors, + ], + ]; + // @todo Add support for render arrays in + // \Drupal\Core\Messenger\MessengerInterface::addMessage()? + // @see https://www.drupal.org/node/2505497. + \Drupal::messenger()->addError(\Drupal::service('renderer')->renderPlain($message)); + return FALSE; + } - // If we are replacing an existing file re-use its database record. - // @todo Do not create a new entity in order to update it. See - // https://www.drupal.org/node/2241865. - if ($replace == FILE_EXISTS_REPLACE) { - $existing_files = entity_load_multiple_by_properties('file', ['uri' => $file->getFileUri()]); - if (count($existing_files)) { - $existing = reset($existing_files); - $file->fid = $existing->id(); - $file->setOriginalId($existing->id()); - } - } + $file->setFileUri($file->destination); + if (!drupal_move_uploaded_file($file_info->getRealPath(), $file->getFileUri())) { + \Drupal::messenger()->addError(t('File upload error. Could not move uploaded file.')); + \Drupal::logger('file')->notice('Upload error. Could not move uploaded file %file to destination %destination.', ['%file' => $file->getFilename(), '%destination' => $file->getFileUri()]); + return FALSE; + } - // If we made it this far it's safe to record this file in the database. - $file->save(); - $files[$i] = $file; - // Allow an anonymous user who creates a non-public file to see it. See - // \Drupal\file\FileAccessControlHandler::checkAccess(). - if ($user->isAnonymous() && $destination_scheme !== 'public') { - $session = \Drupal::request()->getSession(); - $allowed_temp_files = $session->get('anonymous_allowed_file_ids', []); - $allowed_temp_files[$file->id()] = $file->id(); - $session->set('anonymous_allowed_file_ids', $allowed_temp_files); + // Set the permissions on the new file. + drupal_chmod($file->getFileUri()); + + // If we are replacing an existing file re-use its database record. + // @todo Do not create a new entity in order to update it. See + // https://www.drupal.org/node/2241865. + if ($replace == FILE_EXISTS_REPLACE) { + $existing_files = entity_load_multiple_by_properties('file', ['uri' => $file->getFileUri()]); + if (count($existing_files)) { + $existing = reset($existing_files); + $file->fid = $existing->id(); + $file->setOriginalId($existing->id()); } } - // Add files to the cache. - $upload_cache[$form_field_name] = $files; + // If we made it this far it's safe to record this file in the database. + $file->save(); - return isset($delta) ? $files[$delta] : $files; + // Allow an anonymous user who creates a non-public file to see it. See + // \Drupal\file\FileAccessControlHandler::checkAccess(). + if ($user->isAnonymous() && $destination_scheme !== 'public') { + $session = \Drupal::request()->getSession(); + $allowed_temp_files = $session->get('anonymous_allowed_file_ids', []); + $allowed_temp_files[$file->id()] = $file->id(); + $session->set('anonymous_allowed_file_ids', $allowed_temp_files); + } + return $file; } /** diff --git a/web/core/modules/file/src/Tests/FileManagedFileElementTest.php b/web/core/modules/file/tests/src/Functional/FileManagedFileElementTest.php similarity index 72% rename from web/core/modules/file/src/Tests/FileManagedFileElementTest.php rename to web/core/modules/file/tests/src/Functional/FileManagedFileElementTest.php index de9b46111051b553b7031720f41a1bc4676473d6..94d00ef9f2b78ea1182c5b58c98e127210571668 100644 --- a/web/core/modules/file/src/Tests/FileManagedFileElementTest.php +++ b/web/core/modules/file/tests/src/Functional/FileManagedFileElementTest.php @@ -1,6 +1,6 @@ <?php -namespace Drupal\file\Tests; +namespace Drupal\Tests\file\Functional; /** * Tests the 'managed_file' element type. @@ -36,11 +36,13 @@ public function testManagedFile() { // Submit with a file, but with an invalid form token. Ensure the file // was not saved. $last_fid_prior = $this->getLastFileId(); + $this->drupalGet($path); + $form_token_field = $this->assertSession()->hiddenFieldExists('form_token'); + $form_token_field->setValue('invalid token'); $edit = [ $file_field_name => \Drupal::service('file_system')->realpath($test_file->getFileUri()), - 'form_token' => 'invalid token', ]; - $this->drupalPostForm($path, $edit, t('Save')); + $this->drupalPostForm(NULL, $edit, t('Save')); $this->assertText('The form has become outdated. Copy any unsaved work in the form below'); $last_fid = $this->getLastFileId(); $this->assertEqual($last_fid_prior, $last_fid, 'File was not saved when uploaded with an invalid form token.'); @@ -57,64 +59,41 @@ public function testManagedFile() { $this->drupalPostForm($path . '/' . $last_fid, [], t('Save')); $this->assertRaw(t('The file ids are %fids.', ['%fids' => implode(',', [$last_fid])]), 'Empty submission did not change an existing file.'); - // Now, test the Upload and Remove buttons, with and without Ajax. - foreach ([FALSE, TRUE] as $ajax) { - // Upload, then Submit. - $last_fid_prior = $this->getLastFileId(); - $this->drupalGet($path); - $edit = [$file_field_name => \Drupal::service('file_system')->realpath($test_file->getFileUri())]; - if ($ajax) { - $this->drupalPostAjaxForm(NULL, $edit, $input_base_name . '_upload_button'); - } - else { - $this->drupalPostForm(NULL, $edit, t('Upload')); - } - $last_fid = $this->getLastFileId(); - $this->assertTrue($last_fid > $last_fid_prior, 'New file got uploaded.'); - $this->drupalPostForm(NULL, [], t('Save')); - $this->assertRaw(t('The file ids are %fids.', ['%fids' => implode(',', [$last_fid])]), 'Submit handler has correct file info.'); - - // Remove, then Submit. - $remove_button_title = $multiple ? t('Remove selected') : t('Remove'); - $remove_edit = []; - if ($multiple) { - $selected_checkbox = ($tree ? 'nested[file]' : 'file') . '[file_' . $last_fid . '][selected]'; - $remove_edit = [$selected_checkbox => '1']; - } - $this->drupalGet($path . '/' . $last_fid); - if ($ajax) { - $this->drupalPostAjaxForm(NULL, $remove_edit, $input_base_name . '_remove_button'); - } - else { - $this->drupalPostForm(NULL, $remove_edit, $remove_button_title); - } - $this->drupalPostForm(NULL, [], t('Save')); - $this->assertRaw(t('The file ids are %fids.', ['%fids' => '']), 'Submission after file removal was successful.'); - - // Upload, then Remove, then Submit. - $this->drupalGet($path); - $edit = [$file_field_name => \Drupal::service('file_system')->realpath($test_file->getFileUri())]; - if ($ajax) { - $this->drupalPostAjaxForm(NULL, $edit, $input_base_name . '_upload_button'); - } - else { - $this->drupalPostForm(NULL, $edit, t('Upload')); - } - $remove_edit = []; - if ($multiple) { - $selected_checkbox = ($tree ? 'nested[file]' : 'file') . '[file_' . $this->getLastFileId() . '][selected]'; - $remove_edit = [$selected_checkbox => '1']; - } - if ($ajax) { - $this->drupalPostAjaxForm(NULL, $remove_edit, $input_base_name . '_remove_button'); - } - else { - $this->drupalPostForm(NULL, $remove_edit, $remove_button_title); - } - - $this->drupalPostForm(NULL, [], t('Save')); - $this->assertRaw(t('The file ids are %fids.', ['%fids' => '']), 'Submission after file upload and removal was successful.'); + // Upload, then Submit. + $last_fid_prior = $this->getLastFileId(); + $this->drupalGet($path); + $edit = [$file_field_name => \Drupal::service('file_system')->realpath($test_file->getFileUri())]; + $this->drupalPostForm(NULL, $edit, t('Upload')); + $last_fid = $this->getLastFileId(); + $this->assertTrue($last_fid > $last_fid_prior, 'New file got uploaded.'); + $this->drupalPostForm(NULL, [], t('Save')); + $this->assertRaw(t('The file ids are %fids.', ['%fids' => implode(',', [$last_fid])]), 'Submit handler has correct file info.'); + + // Remove, then Submit. + $remove_button_title = $multiple ? t('Remove selected') : t('Remove'); + $remove_edit = []; + if ($multiple) { + $selected_checkbox = ($tree ? 'nested[file]' : 'file') . '[file_' . $last_fid . '][selected]'; + $remove_edit = [$selected_checkbox => '1']; } + $this->drupalGet($path . '/' . $last_fid); + $this->drupalPostForm(NULL, $remove_edit, $remove_button_title); + $this->drupalPostForm(NULL, [], t('Save')); + $this->assertRaw(t('The file ids are %fids.', ['%fids' => '']), 'Submission after file removal was successful.'); + + // Upload, then Remove, then Submit. + $this->drupalGet($path); + $edit = [$file_field_name => \Drupal::service('file_system')->realpath($test_file->getFileUri())]; + $this->drupalPostForm(NULL, $edit, t('Upload')); + $remove_edit = []; + if ($multiple) { + $selected_checkbox = ($tree ? 'nested[file]' : 'file') . '[file_' . $this->getLastFileId() . '][selected]'; + $remove_edit = [$selected_checkbox => '1']; + } + $this->drupalPostForm(NULL, $remove_edit, $remove_button_title); + + $this->drupalPostForm(NULL, [], t('Save')); + $this->assertRaw(t('The file ids are %fids.', ['%fids' => '']), 'Submission after file upload and removal was successful.'); } } } @@ -212,7 +191,7 @@ public function testUnusedPermanentFileValidation() { $this->assertNoText('The file used in the Managed file & butter field may not be referenced.'); $this->assertText('The file ids are ' . $file->id()); - // Enable marking unused files as tempory, unused permanent files must not + // Enable marking unused files as temporary, unused permanent files must not // be referenced now. $this->config('file.settings') ->set('make_unused_managed_files_temporary', TRUE) diff --git a/web/core/modules/file/tests/src/Functional/MultipleFileUploadTest.php b/web/core/modules/file/tests/src/Functional/MultipleFileUploadTest.php new file mode 100644 index 0000000000000000000000000000000000000000..587d4479efebf555a8fb8c20e9927bf0be31cb1e --- /dev/null +++ b/web/core/modules/file/tests/src/Functional/MultipleFileUploadTest.php @@ -0,0 +1,59 @@ +<?php + +namespace Drupal\Tests\file\Functional; + +use Drupal\Tests\BrowserTestBase; + +/** + * Tests multiple file upload. + * + * @group file + */ +class MultipleFileUploadTest extends BrowserTestBase { + + /** + * {@inheritdoc} + */ + public static $modules = ['file']; + + /** + * {@inheritdoc} + */ + protected function setUp() { + parent::setUp(); + + $admin = $this->drupalCreateUser(['administer themes']); + $this->drupalLogin($admin); + } + + /** + * Tests multiple file field with all file extensions. + */ + public function testMultipleFileFieldWithAllFileExtensions() { + $theme = 'test_theme_settings'; + \Drupal::service('theme_handler')->install([$theme]); + $this->drupalGet("admin/appearance/settings/$theme"); + + $edit = []; + // Create few files with non-typical extensions. + foreach (['file1.wtf', 'file2.wtf'] as $i => $file) { + $file_path = $this->root . "/sites/default/files/simpletest/$file"; + file_put_contents($file_path, 'File with non-default extension.', FILE_APPEND | LOCK_EX); + $edit["files[multi_file][$i]"] = $file_path; + } + + // @todo: Replace after https://www.drupal.org/project/drupal/issues/2917885 + $this->drupalGet("admin/appearance/settings/$theme"); + $submit_xpath = $this->assertSession()->buttonExists('Save configuration')->getXpath(); + $client = $this->getSession()->getDriver()->getClient(); + $form = $client->getCrawler()->filterXPath($submit_xpath)->form(); + $client->request($form->getMethod(), $form->getUri(), $form->getPhpValues(), $edit); + + $page = $this->getSession()->getPage(); + $this->assertNotContains('Only files with the following extensions are allowed', $page->getContent()); + $this->assertContains('The configuration options have been saved.', $page->getContent()); + $this->assertContains('file1.wtf', $page->getContent()); + $this->assertContains('file2.wtf', $page->getContent()); + } + +} diff --git a/web/core/modules/file/tests/src/FunctionalJavascript/FileManagedFileElementTest.php b/web/core/modules/file/tests/src/FunctionalJavascript/FileManagedFileElementTest.php new file mode 100644 index 0000000000000000000000000000000000000000..8c42178114045f7d81b60cb4f505055754090021 --- /dev/null +++ b/web/core/modules/file/tests/src/FunctionalJavascript/FileManagedFileElementTest.php @@ -0,0 +1,101 @@ +<?php + +namespace Drupal\Tests\file\FunctionalJavascript; + +use Drupal\Core\Database\Database; +use Drupal\FunctionalJavascriptTests\WebDriverTestBase; + +/** + * Tests the 'managed_file' element type. + * + * @group file + */ +class FileManagedFileElementTest extends WebDriverTestBase { + + /** + * {@inheritdoc} + */ + protected static $modules = ['node', 'file', 'file_module_test', 'field_ui']; + + /** + * A user with administration permissions. + * + * @var \Drupal\user\UserInterface + */ + protected $adminUser; + + /** + * {@inheritdoc} + */ + protected function setUp() { + parent::setUp(); + $this->adminUser = $this->drupalCreateUser(['access content', 'access administration pages', 'administer site configuration', 'administer users', 'administer permissions', 'administer content types', 'administer node fields', 'administer node display', 'administer nodes', 'bypass node access']); + $this->drupalLogin($this->adminUser); + $this->drupalCreateContentType(['type' => 'article', 'name' => 'Article']); + } + + /** + * Tests the managed_file element type. + */ + public function testManagedFile() { + // Perform the tests with all permutations of $form['#tree'], + // $element['#extended'], and $element['#multiple']. + $filename = \Drupal::service('file_system')->tempnam('temporary://', "testManagedFile") . '.txt'; + file_put_contents($filename, $this->randomString(128)); + foreach ([0, 1] as $tree) { + foreach ([0, 1] as $extended) { + foreach ([0, 1] as $multiple) { + $path = 'file/test/' . $tree . '/' . $extended . '/' . $multiple; + $input_base_name = $tree ? 'nested_file' : 'file'; + $file_field_name = $multiple ? 'files[' . $input_base_name . '][]' : 'files[' . $input_base_name . ']'; + + // Now, test the Upload and Remove buttons, with Ajax. + // Upload, then Submit. + $last_fid_prior = $this->getLastFileId(); + $this->drupalGet($path); + $this->getSession()->getPage()->attachFileToField($file_field_name, $this->container->get('file_system')->realpath($filename)); + $uploaded_file = $this->assertSession()->waitForElement('css', '.file--mime-text-plain'); + $this->assertNotEmpty($uploaded_file); + $last_fid = $this->getLastFileId(); + $this->assertGreaterThan($last_fid_prior, $last_fid, 'New file got uploaded.'); + $this->drupalPostForm(NULL, [], t('Save')); + + // Remove, then Submit. + $remove_button_title = $multiple ? t('Remove selected') : t('Remove'); + $this->drupalGet($path . '/' . $last_fid); + if ($multiple) { + $selected_checkbox = ($tree ? 'nested[file]' : 'file') . '[file_' . $last_fid . '][selected]'; + $this->getSession()->getPage()->checkField($selected_checkbox); + } + $this->getSession()->getPage()->pressButton($remove_button_title); + $this->assertSession()->assertWaitOnAjaxRequest(); + $this->drupalPostForm(NULL, [], t('Save')); + $this->assertSession()->responseContains(t('The file ids are %fids.', ['%fids' => ''])); + + // Upload, then Remove, then Submit. + $this->drupalGet($path); + $this->getSession()->getPage()->attachFileToField($file_field_name, $this->container->get('file_system')->realpath($filename)); + $uploaded_file = $this->assertSession()->waitForElement('css', '.file--mime-text-plain'); + $this->assertNotEmpty($uploaded_file); + if ($multiple) { + $selected_checkbox = ($tree ? 'nested[file]' : 'file') . '[file_' . $this->getLastFileId() . '][selected]'; + $this->getSession()->getPage()->checkField($selected_checkbox); + } + $this->getSession()->getPage()->pressButton($remove_button_title); + $this->assertSession()->assertWaitOnAjaxRequest(); + + $this->drupalPostForm(NULL, [], t('Save')); + $this->assertSession()->responseContains(t('The file ids are %fids.', ['%fids' => ''])); + } + } + } + } + + /** + * Retrieves the fid of the last inserted file. + */ + protected function getLastFileId() { + return (int) Database::getConnection()->query('SELECT MAX(fid) FROM {file_managed}')->fetchField(); + } + +} diff --git a/web/core/modules/filter/tests/src/Kernel/Plugin/migrate/process/FilterIdTest.php b/web/core/modules/filter/tests/src/Kernel/Plugin/migrate/process/FilterIdTest.php index eb5f7eacab463ca98ff6c01045a0d586e18d67b9..f633debad867894db63f4ab827d3d4340ad5419a 100644 --- a/web/core/modules/filter/tests/src/Kernel/Plugin/migrate/process/FilterIdTest.php +++ b/web/core/modules/filter/tests/src/Kernel/Plugin/migrate/process/FilterIdTest.php @@ -87,31 +87,25 @@ public function testTransform($value, $expected_value, $invalid_id = NULL) { */ public function provideFilters() { return [ - // The filter ID is mapped, and the plugin exists. - [ + 'filter ID mapped to plugin that exists' => [ 'foo', 'filter_html', ], - // The filter ID isn't mapped, but it's unchanged from the source (i.e., - // it bypasses the static map) and the plugin exists. - [ + 'filter ID not mapped but unchanged from the source and the plugin exists' => [ 'filter_html', 'filter_html', ], - // The filter ID is mapped, but the plugin does not exist. - [ + 'filter ID mapped to plugin that does not exist' => [ 'baz', 'filter_null', 'php_code', ], - // The filter ID isn't mapped, but it's unchanged from the source (i.e., - // it bypasses the static map) but the plugin does not exist. - [ + 'filter ID not mapped but unchanged from the source and the plugin does not exist' => [ 'php_code', 'filter_null', 'php_code', ], - [ + 'filter ID set and the plugin does not exist' => [ ['filter', 1], 'filter_null', 'filter:1', diff --git a/web/core/modules/filter/tests/src/Unit/FilterHtmlTest.php b/web/core/modules/filter/tests/src/Unit/FilterHtmlTest.php index 664c2a3001af991f8e45174e0e8c907b9ad56718..f8285ec5aed9f637d7f260cf30ae82a3713b84e3 100644 --- a/web/core/modules/filter/tests/src/Unit/FilterHtmlTest.php +++ b/web/core/modules/filter/tests/src/Unit/FilterHtmlTest.php @@ -66,11 +66,11 @@ public function providerFilterAttributes() { ['<code class="invalid alpaca">foreach ($a as $b) {}</code>', '<code>foreach ($a as $b) {}</code>'], ['<h3 class="big">a heading</h3>', '<h3>a heading</h3>'], ['<h3 id="first">a heading</h3>', '<h3 id="first">a heading</h3>'], - // Wilcard value. Case matters, so upper case doesn't match. + // Wildcard value. Case matters, so upper case doesn't match. ['<code class="align-left bold">foreach ($a as $b) {}</code>', '<code class="align-left">foreach ($a as $b) {}</code>'], ['<code class="align-right ">foreach ($a as $b) {}</code>', '<code class="align-right">foreach ($a as $b) {}</code>'], ['<code class="Align-right ">foreach ($a as $b) {}</code>', '<code>foreach ($a as $b) {}</code>'], - // Wilcard name, case is ignored. + // Wildcard name, case is ignored. ['<ol style="display: none;" llama-wim="noble majestic"></ol>', '<ol llama-wim="noble majestic"></ol>'], ['<ol style="display: none;" LlamA-Wim="majestic"></ol>', '<ol llama-wim="majestic"></ol>'], ['<ol style="display: none;" llama-="noble majestic"></ol>', '<ol llama-="noble majestic"></ol>'], diff --git a/web/core/modules/hal/src/Normalizer/ContentEntityNormalizer.php b/web/core/modules/hal/src/Normalizer/ContentEntityNormalizer.php index 4a9f7c440d7aba8510fe163c1c2bcde4bf40fe7c..c8ceb1ca8e5a9d1be99566ee58449f88dc7a36fa 100644 --- a/web/core/modules/hal/src/Normalizer/ContentEntityNormalizer.php +++ b/web/core/modules/hal/src/Normalizer/ContentEntityNormalizer.php @@ -126,7 +126,7 @@ public function denormalize($data, $class, $format = NULL, array $context = []) // Figure out the language to use. if (isset($data[$default_langcode_key])) { - // Find the field item for which the default_lancode value is set to 1 and + // Find the field item for which the default_langcode value is set to 1 and // set the langcode the right default language. foreach ($data[$default_langcode_key] as $item) { if (!empty($item['value']) && isset($item['lang'])) { diff --git a/web/core/modules/hal/src/Normalizer/EntityReferenceItemNormalizer.php b/web/core/modules/hal/src/Normalizer/EntityReferenceItemNormalizer.php index a9fc7e6b3b58120f766840ec24f2fae65303e155..4b9565b72e24cbcda32dd6369f75f391cfce1ee3 100644 --- a/web/core/modules/hal/src/Normalizer/EntityReferenceItemNormalizer.php +++ b/web/core/modules/hal/src/Normalizer/EntityReferenceItemNormalizer.php @@ -127,7 +127,7 @@ protected function targetEntityIsFieldable(EntityReferenceItem $item) { $target_entity_type_id = $item->getFieldDefinition()->getSetting('target_type'); // If the entity type is the same as the parent, we can check that. This is - // just a shortcut to avoid getting the entity type defintition and checking + // just a shortcut to avoid getting the entity type definition and checking // the class. if ($target_entity_type_id === $referencing_entity->getEntityTypeId()) { return $referencing_entity instanceof FieldableEntityInterface; diff --git a/web/core/modules/history/history.module b/web/core/modules/history/history.module index fddbe44c8ad47cbb0463431224bda32924dbbd4d..db563d10e8f6c668366197e42ce06ede18270c1e 100644 --- a/web/core/modules/history/history.module +++ b/web/core/modules/history/history.module @@ -12,6 +12,7 @@ use Drupal\Core\Entity\EntityInterface; use Drupal\Core\Entity\Display\EntityViewDisplayInterface; use Drupal\Core\Routing\RouteMatchInterface; +use Drupal\user\UserInterface; /** * Entities changed before this time are always shown as read. @@ -159,7 +160,7 @@ function history_node_delete(EntityInterface $node) { /** * Implements hook_user_cancel(). */ -function history_user_cancel($edit, $account, $method) { +function history_user_cancel($edit, UserInterface $account, $method) { switch ($method) { case 'user_cancel_reassign': db_delete('history') diff --git a/web/core/modules/image/tests/src/Functional/ImageStylesPathAndUrlTest.php b/web/core/modules/image/tests/src/Functional/ImageStylesPathAndUrlTest.php index c5b81e7ce3f65253f49ff156edc651f558dbaba6..c905c04b4bd17091b38c68483aee4e87ab369b69 100644 --- a/web/core/modules/image/tests/src/Functional/ImageStylesPathAndUrlTest.php +++ b/web/core/modules/image/tests/src/Functional/ImageStylesPathAndUrlTest.php @@ -287,7 +287,7 @@ public function doImageStyleUrlAndPathTests($scheme, $clean_url = TRUE, $extra_s $this->drupalGet($generate_url); $this->assertResponse(200, 'Image was accessible at the URL with a missing token.'); - // Stop supressing the security token in the URL. + // Stop suppressing the security token in the URL. $this->config('image.settings')->set('suppress_itok_output', FALSE)->save(); // Ensure allow_insecure_derivatives is enabled. $this->assertEqual($this->config('image.settings') diff --git a/web/core/modules/language/language.module b/web/core/modules/language/language.module index 0ce68d7d94a64625806741b694278be21fd5556b..e4c132040a39112ad21bffbdcfc559763f637a7f 100644 --- a/web/core/modules/language/language.module +++ b/web/core/modules/language/language.module @@ -204,7 +204,7 @@ function language_configuration_element_submit(&$form, FormStateInterface $form_ $config->setLanguageAlterable($form_state->getValue([$element_name, 'language_alterable'])); $config->save(); - // Set the form_state languaged with the updated bundle. + // Set the form_state language with the updated bundle. $form_state->set('language', $language); } } diff --git a/web/core/modules/language/migrations/d6_language_content_taxonomy_vocabulary_settings.yml b/web/core/modules/language/migrations/d6_language_content_taxonomy_vocabulary_settings.yml new file mode 100644 index 0000000000000000000000000000000000000000..9af288c3bbb79ab1a398f13ff1749a9874462db9 --- /dev/null +++ b/web/core/modules/language/migrations/d6_language_content_taxonomy_vocabulary_settings.yml @@ -0,0 +1,53 @@ +id: d6_language_content_taxonomy_vocabulary_settings +label: Drupal 6 language taxonomy vocabulary settings +migration_tags: + - Drupal 6 + - Configuration +source: + plugin: d6_language_content_settings_taxonomy_vocabulary + constants: + target_type: 'taxonomy_term' + default_langcode: 'site_default' +process: + target_bundle: + - + plugin: migration_lookup + migration: d6_taxonomy_vocabulary + source: vid + - + plugin: skip_on_empty + method: row + # State is the value in the i18ntaxonomy_vocabulary array defined as: + # 0: No multilingual options. + # 1: Localizable terms. Run through the localization system. + # 2: Predefined language for a vocabulary and its terms. + # 3: Per-language terms, translatable (referencing terms with different + # languages) but not localizable. + language_alterable: + plugin: static_map + source: state + map: + 0: false + 1: true + 2: false + 3: true + 'third_party_settings/content_translation/enabled': + plugin: static_map + source: state + map: + 0: false + 1: true + 2: false + 3: false + target_entity_type_id: 'constants/target_type' + default_langcode: + plugin: default_value + default_value: site_default + source: language +destination: + plugin: entity:language_content_settings + content_translation_update_definitions: + - taxonomy_term +migration_dependencies: + required: + - d6_taxonomy_vocabulary diff --git a/web/core/modules/language/src/Config/LanguageConfigFactoryOverride.php b/web/core/modules/language/src/Config/LanguageConfigFactoryOverride.php index 4c60a72a21f8d450a38539b4f92269ad5f118448..11fcb925b3beafeeb2f51bc5ff213d26a0e04496 100644 --- a/web/core/modules/language/src/Config/LanguageConfigFactoryOverride.php +++ b/web/core/modules/language/src/Config/LanguageConfigFactoryOverride.php @@ -75,7 +75,7 @@ public function __construct(StorageInterface $storage, EventDispatcherInterface $this->baseStorage = $storage; $this->eventDispatcher = $event_dispatcher; $this->typedConfigManager = $typed_config; - // Prior to negiotiation the override language should be the default + // Prior to negotiation the override language should be the default // language. $this->language = $default_language->get(); } diff --git a/web/core/modules/language/src/ConfigurableLanguageManager.php b/web/core/modules/language/src/ConfigurableLanguageManager.php index 13079f85541b8bc280a7c078307608129d70a17e..25927b52532c789b818f96a2a87f8a9de12c9893 100644 --- a/web/core/modules/language/src/ConfigurableLanguageManager.php +++ b/web/core/modules/language/src/ConfigurableLanguageManager.php @@ -90,11 +90,11 @@ class ConfigurableLanguageManager extends LanguageManager implements Configurabl protected $initialized = FALSE; /** - * Whether already in the process of language initialization. + * Whether language types are in the process of language initialization. * - * @var bool + * @var bool[] */ - protected $initializing = FALSE; + protected $initializing = []; /** * {@inheritdoc} @@ -213,12 +213,12 @@ public function getCurrentLanguage($type = LanguageInterface::TYPE_INTERFACE) { $this->negotiatedLanguages[$type] = $this->getDefaultLanguage(); if ($this->negotiator && $this->isMultilingual()) { - if (!$this->initializing) { - $this->initializing = TRUE; + if (!isset($this->initializing[$type])) { + $this->initializing[$type] = TRUE; $negotiation = $this->negotiator->initializeType($type); $this->negotiatedLanguages[$type] = reset($negotiation); $this->negotiatedMethods[$type] = key($negotiation); - $this->initializing = FALSE; + unset($this->initializing[$type]); } // If the current interface language needs to be retrieved during // initialization we return the system language. This way string diff --git a/web/core/modules/language/src/Plugin/migrate/source/d6/LanguageContentSettingsTaxonomyVocabulary.php b/web/core/modules/language/src/Plugin/migrate/source/d6/LanguageContentSettingsTaxonomyVocabulary.php new file mode 100644 index 0000000000000000000000000000000000000000..4cde5687f6a4a984bddc803ffd0b2f5829c12f69 --- /dev/null +++ b/web/core/modules/language/src/Plugin/migrate/source/d6/LanguageContentSettingsTaxonomyVocabulary.php @@ -0,0 +1,65 @@ +<?php + +namespace Drupal\language\Plugin\migrate\source\d6; + +use Drupal\migrate\Row; +use Drupal\migrate_drupal\Plugin\migrate\source\DrupalSqlBase; + +/** + * Drupal 6 i18n vocabularies source from database. + * + * @MigrateSource( + * id = "d6_language_content_settings_taxonomy_vocabulary", + * source_module = "taxonomy" + * ) + */ +class LanguageContentSettingsTaxonomyVocabulary extends DrupalSqlBase { + + /** + * {@inheritdoc} + */ + public function query() { + return $this->select('vocabulary', 'v') + ->fields('v', ['vid', 'language']); + } + + /** + * {@inheritdoc} + */ + public function fields() { + return [ + 'vid' => $this->t('The vocabulary ID.'), + 'language' => $this->t('The default language for new terms.'), + 'state' => $this->t('The i18n taxonomy translation setting.'), + ]; + } + + /** + * {@inheritdoc} + */ + public function prepareRow(Row $row) { + // Get the i18n taxonomy translation setting for this vocabulary. + // 0 - No multilingual options + // 1 - Localizable terms. Run through the localization system. + // 2 - Predefined language for a vocabulary and its terms. + // 3 - Per-language terms, translatable (referencing terms with different + // languages) but not localizable. + $i18ntaxonomy_vocabulary = $this->variableGet('i18ntaxonomy_vocabulary', NULL); + $vid = $row->getSourceProperty('vid'); + $state = FALSE; + if (array_key_exists($vid, $i18ntaxonomy_vocabulary)) { + $state = $i18ntaxonomy_vocabulary[$vid]; + } + $row->setSourceProperty('state', $state); + return parent::prepareRow($row); + } + + /** + * {@inheritdoc} + */ + public function getIds() { + $ids['vid']['type'] = 'integer'; + return $ids; + } + +} diff --git a/web/core/modules/language/tests/src/Functional/ConfigurableLanguageManagerTest.php b/web/core/modules/language/tests/src/Functional/ConfigurableLanguageManagerTest.php new file mode 100644 index 0000000000000000000000000000000000000000..d36aee0ac70ddc6cee9b77bfc56e8a20d32deab3 --- /dev/null +++ b/web/core/modules/language/tests/src/Functional/ConfigurableLanguageManagerTest.php @@ -0,0 +1,189 @@ +<?php + +namespace Drupal\Tests\language\Functional; + +use Drupal\Core\Cache\Cache; +use Drupal\language\Entity\ConfigurableLanguage; +use Drupal\language\Entity\ContentLanguageSettings; +use Drupal\node\Entity\Node; +use Drupal\node\Entity\NodeType; +use Drupal\Tests\BrowserTestBase; + +/** + * Tests Language Negotiation. + * + * Uses different negotiators for content and interface. + * + * @group language + */ +class ConfigurableLanguageManagerTest extends BrowserTestBase { + + /** + * {@inheritdoc} + */ + public static $modules = [ + 'language', + 'content_translation', + 'node', + 'locale', + 'block', + 'system', + 'user', + ]; + + /** + * {@inheritdoc} + */ + protected function setUp() { + parent::setUp(); + + /** @var \Drupal\user\UserInterface $user */ + $user = $this->createUser([], '', TRUE); + $this->drupalLogin($user); + ConfigurableLanguage::createFromLangcode('es')->save(); + + // Create a page node type and make it translatable. + NodeType::create([ + 'type' => 'page', + 'name' => t('Page'), + ])->save(); + + $config = ContentLanguageSettings::loadByEntityTypeBundle('node', 'page'); + $config->setDefaultLangcode('en') + ->setLanguageAlterable(TRUE) + ->save(); + + // Create a Node with title 'English' and translate it to Spanish. + $node = Node::create([ + 'type' => 'page', + 'title' => 'English', + ]); + $node->save(); + $node->addTranslation('es', ['title' => 'Español']); + $node->save(); + + // Enable both language_interface and language_content language negotiation. + \Drupal::getContainer()->get('language_negotiator')->updateConfiguration([ + 'language_interface', + 'language_content', + ]); + + // Set the preferred language of the user for admin pages to English. + $user->set('preferred_admin_langcode', 'en')->save(); + + // Make sure node edit pages are administration pages. + $this->config('node.settings')->set('use_admin_theme', '1')->save(); + $this->container->get('router.builder')->rebuild(); + + // Place a Block with a translatable string on the page. + $this->placeBlock('system_powered_by_block', ['region' => 'content']); + + // Load the Spanish Node page once, to register the translatable string. + $this->drupalGet('/es/node/1'); + + // Translate the Powered by string. + /** @var \Drupal\locale\StringStorageInterface $string_storage */ + $string_storage = \Drupal::getContainer()->get('locale.storage'); + $source = $string_storage->findString(['source' => 'Powered by <a href=":poweredby">Drupal</a>']); + $string_storage->createTranslation([ + 'lid' => $source->lid, + 'language' => 'es', + 'translation' => 'Funciona con ...', + ])->save(); + // Invalidate caches so that the new translation will be used. + Cache::invalidateTags(['rendered', 'locale']); + } + + /** + * Test translation with URL and Preferred Admin Language negotiators. + * + * The interface language uses the preferred language for admin pages of the + * user and after that the URL. The Content uses just the URL. + */ + public function testUrlContentTranslationWithPreferredAdminLanguage() { + $assert_session = $this->assertSession(); + // Set the interface language to use the preferred administration language + // and then the URL. + /** @var \Drupal\language\LanguageNegotiatorInterface $language_negotiator */ + $language_negotiator = \Drupal::getContainer()->get('language_negotiator'); + $language_negotiator->saveConfiguration('language_interface', [ + 'language-user-admin' => 1, + 'language-url' => 2, + 'language-selected' => 3, + ]); + // Set Content Language Negotiator to use just the URL. + $language_negotiator->saveConfiguration('language_content', [ + 'language-url' => 4, + 'language-selected' => 5, + ]); + + // See if the full view of the node in english is present and the + // string in the Powered By Block is in English. + $this->drupalGet('/node/1'); + $assert_session->pageTextContains('English'); + $assert_session->pageTextContains('Powered by'); + + // Load the spanish node page again and see if both the node and the string + // are translated. + $this->drupalGet('/es/node/1'); + $assert_session->pageTextContains('Español'); + $assert_session->pageTextContains('Funciona con'); + $assert_session->pageTextNotContains('Powered by'); + + // Check if the Powered by string is shown in English on an + // administration page, and the node content is shown in Spanish. + $this->drupalGet('/es/node/1/edit'); + $assert_session->pageTextContains('Español'); + $assert_session->pageTextContains('Powered by'); + $assert_session->pageTextNotContains('Funciona con'); + } + + /** + * Test translation with URL and Session Language Negotiators. + */ + public function testUrlContentTranslationWithSessionLanguage() { + $assert_session = $this->assertSession(); + /** @var \Drupal\language\LanguageNegotiatorInterface $language_negotiator */ + $language_negotiator = \Drupal::getContainer()->get('language_negotiator'); + // Set Interface Language Negotiator to Session. + $language_negotiator->saveConfiguration('language_interface', [ + 'language-session' => 1, + 'language-url' => 2, + 'language-selected' => 3, + ]); + + // Set Content Language Negotiator to URL. + $language_negotiator->saveConfiguration('language_content', [ + 'language-url' => 4, + 'language-selected' => 5, + ]); + + // See if the full view of the node in english is present and the + // string in the Powered By Block is in English. + $this->drupalGet('/node/1'); + $assert_session->pageTextContains('English'); + $assert_session->pageTextContains('Powered by'); + + // The language session variable has not been set yet, so + // The string should be in Spanish. + $this->drupalGet('/es/node/1'); + $assert_session->pageTextContains('Español'); + $assert_session->pageTextNotContains('Powered by'); + $assert_session->pageTextContains('Funciona con'); + + // Set the session language to Spanish but load the English node page. + $this->drupalGet('/node/1', ['query' => ['language' => 'es']]); + $assert_session->pageTextContains('English'); + $assert_session->pageTextNotContains('Español'); + $assert_session->pageTextContains('Funciona con'); + $assert_session->pageTextNotContains('Powered by'); + + // Set the session language to English but load the node page in Spanish. + $this->drupalGet('/es/node/1', ['query' => ['language' => 'en']]); + $assert_session->pageTextNotContains('English'); + $assert_session->pageTextContains('Español'); + $assert_session->pageTextNotContains('Funciona con'); + $assert_session->pageTextContains('Powered by'); + } + +} diff --git a/web/core/modules/language/tests/src/Functional/LanguageUILanguageNegotiationTest.php b/web/core/modules/language/tests/src/Functional/LanguageUILanguageNegotiationTest.php index 34f0c81f01acd8015303acc33cef706c3c5dddc5..976f892f68297c1b41909393e9f98b0a29871b81 100644 --- a/web/core/modules/language/tests/src/Functional/LanguageUILanguageNegotiationTest.php +++ b/web/core/modules/language/tests/src/Functional/LanguageUILanguageNegotiationTest.php @@ -2,7 +2,9 @@ namespace Drupal\Tests\language\Functional; +use Drupal\Core\Cache\Cache; use Drupal\Core\Url; +use Drupal\file\Entity\File; use Drupal\language\Entity\ConfigurableLanguage; use Drupal\language\Plugin\LanguageNegotiation\LanguageNegotiationBrowser; use Drupal\language\Plugin\LanguageNegotiation\LanguageNegotiationSelected; @@ -39,6 +41,13 @@ */ class LanguageUILanguageNegotiationTest extends BrowserTestBase { + /** + * The admin user for testing. + * + * @var \Drupal\user\Entity\User + */ + protected $adminUser; + /** * Modules to enable. * @@ -53,8 +62,8 @@ class LanguageUILanguageNegotiationTest extends BrowserTestBase { protected function setUp() { parent::setUp(); - $admin_user = $this->drupalCreateUser(['administer languages', 'translate interface', 'access administration pages', 'administer blocks']); - $this->drupalLogin($admin_user); + $this->adminUser = $this->drupalCreateUser(['administer languages', 'translate interface', 'access administration pages', 'administer blocks']); + $this->drupalLogin($this->adminUser); } /** @@ -73,6 +82,17 @@ public function testUILanguageNegotiation() { // For setting browser language preference to some unknown. $http_header_blah = ["Accept-Language" => "blah;q=1"]; + // Create a private file for testing accessible by the admin user. + drupal_mkdir($this->privateFilesDirectory . '/test'); + $filepath = 'private://test/private-file-test.txt'; + $contents = "file_put_contents() doesn't seem to appreciate empty strings so let's put in some data."; + file_put_contents($filepath, $contents); + $file = File::create([ + 'uri' => $filepath, + 'uid' => $this->adminUser->id(), + ]); + $file->save(); + // Setup the site languages by installing two languages. // Set the default language in order for the translated string to be registered // into database when seen by t(). Without doing this, our target string @@ -242,6 +262,21 @@ public function testUILanguageNegotiation() { ]; $this->doRunTest($test); + // Set preferred langcode for user to default langcode. + $account = $this->loggedInUser; + $account->preferred_langcode = $default_language->getId(); + $account->save(); + + $test = [ + 'language_negotiation' => [LanguageNegotiationUser::METHOD_ID, LanguageNegotiationUrl::METHOD_ID], + 'path' => "$langcode/admin/config", + 'expect' => $default_string, + 'expected_method_id' => LanguageNegotiationUser::METHOD_ID, + 'http_header' => [], + 'message' => 'USER > URL: User has default language as preferred user language setting, the UI language is default', + ]; + $this->doRunTest($test); + // Set preferred langcode for user to unknown language. $account = $this->loggedInUser; $account->preferred_langcode = $langcode_unknown; @@ -359,6 +394,13 @@ protected function doRunTest($test) { $this->drupalGet($test['path'], $test['path_options'], $test['http_header']); $this->assertText($test['expect'], $test['message']); $this->assertText(t('Language negotiation method: @name', ['@name' => $test['expected_method_id']])); + + // Get the private file and ensure it is a 200. It is important to + // invalidate the router cache to ensure the routing system runs a full + // match. + Cache::invalidateTags(['route_match']); + $this->drupalGet('system/files/test/private-file-test.txt'); + $this->assertResponse(200); } /** diff --git a/web/core/modules/language/tests/src/Kernel/Migrate/d6/MigrateLanguageContentSettingsTest.php b/web/core/modules/language/tests/src/Kernel/Migrate/d6/MigrateLanguageContentSettingsTest.php index 546ab25e03414209ef5b3d73146042994bebe77c..57439d588d1bb6f31ac87123ae71af98cd90e3d3 100644 --- a/web/core/modules/language/tests/src/Kernel/Migrate/d6/MigrateLanguageContentSettingsTest.php +++ b/web/core/modules/language/tests/src/Kernel/Migrate/d6/MigrateLanguageContentSettingsTest.php @@ -25,6 +25,7 @@ protected function setUp() { parent::setUp(); $this->installConfig(['node']); + $this->installEntitySchema('node'); $this->executeMigrations(['d6_node_type', 'd6_language_content_settings']); } diff --git a/web/core/modules/language/tests/src/Kernel/Migrate/d6/MigrateLanguageContentTaxonomyVocabularySettingsTest.php b/web/core/modules/language/tests/src/Kernel/Migrate/d6/MigrateLanguageContentTaxonomyVocabularySettingsTest.php new file mode 100644 index 0000000000000000000000000000000000000000..b7b3f4b8f3919320cfcf0d2901a59960fd39c9fa --- /dev/null +++ b/web/core/modules/language/tests/src/Kernel/Migrate/d6/MigrateLanguageContentTaxonomyVocabularySettingsTest.php @@ -0,0 +1,80 @@ +<?php + +namespace Drupal\Tests\language\Kernel\Migrate\d6; + +use Drupal\language\Entity\ContentLanguageSettings; +use Drupal\Core\Language\LanguageInterface; +use Drupal\Tests\migrate_drupal\Kernel\d6\MigrateDrupal6TestBase; + +/** + * Tests migration of i18ntaxonomy vocabulary settings. + * + * @group migrate_drupal_6 + */ +class MigrateLanguageContentTaxonomyVocabularySettingsTest extends MigrateDrupal6TestBase { + + /** + * {@inheritdoc} + */ + public static $modules = [ + 'language', + 'content_translation', + 'taxonomy', + ]; + + /** + * {@inheritdoc} + */ + protected function setUp() { + parent::setUp(); + $this->installEntitySchema('taxonomy_term'); + $this->executeMigrations([ + 'language', + 'd6_taxonomy_vocabulary', + 'd6_language_content_taxonomy_vocabulary_settings', + ]); + } + + /** + * Tests migration of 18ntaxonomy vocabulary settings. + */ + public function testLanguageContentTaxonomy() { + $target_entity = 'taxonomy_term'; + // Per Language. + $this->assertLanguageContentSettings($target_entity, 'vocabulary_1_i_0_', LanguageInterface::LANGCODE_SITE_DEFAULT, TRUE, ['enabled' => FALSE]); + // Set language to vocabulary. + $this->assertLanguageContentSettings($target_entity, 'vocabulary_2_i_1_', 'fr', FALSE, ['enabled' => FALSE]); + // Localize terms. + $this->assertLanguageContentSettings($target_entity, 'vocabulary_3_i_2_', LanguageInterface::LANGCODE_SITE_DEFAULT, TRUE, ['enabled' => FALSE]); + // None translation enabled. + $this->assertLanguageContentSettings($target_entity, 'vocabulary_name_much_longer_than', LanguageInterface::LANGCODE_SITE_DEFAULT, TRUE, ['enabled' => TRUE]); + $this->assertLanguageContentSettings($target_entity, 'tags', LanguageInterface::LANGCODE_SITE_DEFAULT, FALSE, ['enabled' => FALSE]); + $this->assertLanguageContentSettings($target_entity, 'forums', LanguageInterface::LANGCODE_SITE_DEFAULT, FALSE, ['enabled' => FALSE]); + $this->assertLanguageContentSettings($target_entity, 'type', LanguageInterface::LANGCODE_SITE_DEFAULT, FALSE, ['enabled' => FALSE]); + } + + /** + * Asserts a content language settings configuration. + * + * @param string $target_entity + * The expected target entity type. + * @param string $bundle + * The expected bundle. + * @param string $default_langcode + * The default language code. + * @param bool $language_alterable + * The expected state of language alterable. + * @param array $third_party_settings + * The content translation setting. + */ + public function assertLanguageContentSettings($target_entity, $bundle, $default_langcode, $language_alterable, array $third_party_settings) { + $config = ContentLanguageSettings::load($target_entity . "." . $bundle); + $this->assertInstanceOf(ContentLanguageSettings::class, $config); + $this->assertSame($target_entity, $config->getTargetEntityTypeId()); + $this->assertSame($bundle, $config->getTargetBundle()); + $this->assertSame($default_langcode, $config->getDefaultLangcode()); + $this->assertSame($language_alterable, $config->isLanguageAlterable()); + $this->assertSame($third_party_settings, $config->getThirdPartySettings('content_translation')); + } + +} diff --git a/web/core/modules/language/tests/src/Kernel/Migrate/d7/MigrateLanguageContentSettingsTest.php b/web/core/modules/language/tests/src/Kernel/Migrate/d7/MigrateLanguageContentSettingsTest.php index e584467c92174c628e9f9ca0eb890225b5b0c952..3a07698d322c9134b1bb8eef78b09cb3d0e7dc89 100644 --- a/web/core/modules/language/tests/src/Kernel/Migrate/d7/MigrateLanguageContentSettingsTest.php +++ b/web/core/modules/language/tests/src/Kernel/Migrate/d7/MigrateLanguageContentSettingsTest.php @@ -25,6 +25,7 @@ protected function setUp() { parent::setUp(); $this->installConfig(['node']); + $this->installEntitySchema('node'); $this->executeMigrations(['d7_node_type', 'd7_language_content_settings']); } diff --git a/web/core/modules/language/tests/src/Kernel/Plugin/migrate/source/d6/LanguageContentTaxonomyVocabularySettingsTest.php b/web/core/modules/language/tests/src/Kernel/Plugin/migrate/source/d6/LanguageContentTaxonomyVocabularySettingsTest.php new file mode 100644 index 0000000000000000000000000000000000000000..c709859f764e42438153ebcc974ba40a2b40e4a7 --- /dev/null +++ b/web/core/modules/language/tests/src/Kernel/Plugin/migrate/source/d6/LanguageContentTaxonomyVocabularySettingsTest.php @@ -0,0 +1,81 @@ +<?php + +namespace Drupal\Tests\language\Kernel\Plugin\migrate\source\d6; + +use Drupal\Tests\migrate\Kernel\MigrateSqlSourceTestBase; + +/** + * Tests i18ntaxonomy vocabulary setting source plugin. + * + * @covers \Drupal\language\Plugin\migrate\source\d6\LanguageContentSettingsTaxonomyVocabulary + * + * @group language + */ +class LanguageContentTaxonomyVocabularySettingsTest extends MigrateSqlSourceTestBase { + + /** + * {@inheritdoc} + */ + public static $modules = ['taxonomy', 'language', 'migrate_drupal']; + + /** + * {@inheritdoc} + */ + public function providerSource() { + $tests = []; + + // The source data. + $tests[0]['source_data']['vocabulary'] = [ + [ + 'vid' => 1, + 'name' => 'Tags', + 'description' => 'Tags description.', + 'help' => 1, + 'relations' => 0, + 'hierarchy' => 0, + 'multiple' => 0, + 'required' => 0, + 'tags' => 1, + 'module' => 'taxonomy', + 'weight' => 0, + 'language' => '', + ], + [ + 'vid' => 2, + 'name' => 'Categories', + 'description' => 'Categories description.', + 'help' => 1, + 'relations' => 1, + 'hierarchy' => 1, + 'multiple' => 0, + 'required' => 1, + 'tags' => 0, + 'module' => 'taxonomy', + 'weight' => 0, + 'language' => 'zu', + ], + ]; + $tests[0]['source_data']['variable'] = [ + [ + 'name' => 'i18ntaxonomy_vocabulary', + 'value' => 'a:4:{i:1;s:1:"3";i:2;s:1:"2";i:3;s:1:"3";i:5;s:1:"1";}', + ], + ]; + + $tests[0]['expected_data'] = [ + [ + 'vid' => 1, + 'language' => '', + 'state' => 3, + ], + [ + 'vid' => 2, + 'language' => 'zu', + 'state' => 2, + ], + ]; + + return $tests; + } + +} diff --git a/web/core/modules/layout_builder/css/layout-builder.css b/web/core/modules/layout_builder/css/layout-builder.css index c920f23bd40bcb3b8c4b542b27099aa767695d2f..edb0c48cb75af3915a923711844fb15d93ffb0b6 100644 --- a/web/core/modules/layout_builder/css/layout-builder.css +++ b/web/core/modules/layout_builder/css/layout-builder.css @@ -85,3 +85,32 @@ display: block; padding-top: 0.55em; } + +#drupal-off-canvas .inline-block-create-button { + display: block; + padding: 24px; + padding-left: 44px; + font-size: 16px; + color: #eee; + background: url(../../../misc/icons/bebebe/plus.svg) transparent 16px no-repeat; +} + +#drupal-off-canvas .inline-block-create-button, +#drupal-off-canvas .inline-block-list__item { + margin: 0 -20px; + background-color: #444; +} + +#drupal-off-canvas .inline-block-create-button:hover, +#drupal-off-canvas .inline-block-list__item:hover { + background-color: #333; +} + +#drupal-off-canvas .inline-block-list { + margin-bottom: 15px; +} + +#drupal-off-canvas .inline-block-list__item { + display: block; + padding: 15px 0 15px 25px; +} diff --git a/web/core/modules/layout_builder/layout_builder.info.yml b/web/core/modules/layout_builder/layout_builder.info.yml index dfd9922df05c8e680b2d2b0ca5f844170262b987..f70cdcaec06729a1edca5d6957b6163511ac1bee 100644 --- a/web/core/modules/layout_builder/layout_builder.info.yml +++ b/web/core/modules/layout_builder/layout_builder.info.yml @@ -9,3 +9,5 @@ dependencies: - drupal:contextual # @todo Discuss removing in https://www.drupal.org/project/drupal/issues/2935999. - drupal:field_ui + # @todo Discuss removing in https://www.drupal.org/project/drupal/issues/3003610. + - drupal:block diff --git a/web/core/modules/layout_builder/layout_builder.module b/web/core/modules/layout_builder/layout_builder.module index 5d7c60615cf0f4924e0ce30dbcc1be7e13a218c9..373f7d8a0f1e3bfa4cc59ee0589503fb257626c4 100644 --- a/web/core/modules/layout_builder/layout_builder.module +++ b/web/core/modules/layout_builder/layout_builder.module @@ -19,6 +19,7 @@ use Drupal\layout_builder\InlineBlockEntityOperations; use Drupal\Core\Session\AccountInterface; use Drupal\Core\Access\AccessResult; +use Drupal\layout_builder\Plugin\SectionStorage\OverridesSectionStorage; /** * Implements hook_help(). @@ -62,8 +63,8 @@ function layout_builder_entity_type_alter(array &$entity_types) { function layout_builder_form_entity_form_display_edit_form_alter(&$form, FormStateInterface $form_state) { // Hides the Layout Builder field. It is rendered directly in // \Drupal\layout_builder\Entity\LayoutBuilderEntityViewDisplay::buildMultiple(). - unset($form['fields']['layout_builder__layout']); - $key = array_search('layout_builder__layout', $form['#fields']); + unset($form['fields'][OverridesSectionStorage::FIELD_NAME]); + $key = array_search(OverridesSectionStorage::FIELD_NAME, $form['#fields']); if ($key !== FALSE) { unset($form['#fields'][$key]); } @@ -177,7 +178,7 @@ function layout_builder_cron() { function layout_builder_plugin_filter_block_alter(array &$definitions, array $extra, $consumer) { // @todo Determine the 'inline_block' blocks should be allowed outside // of layout_builder https://www.drupal.org/node/2979142. - if ($consumer !== 'layout_builder') { + if ($consumer !== 'layout_builder' || !isset($extra['list']) || $extra['list'] !== 'inline_blocks') { foreach ($definitions as $id => $definition) { if ($definition['id'] === 'inline_block') { unset($definitions[$id]); @@ -202,3 +203,21 @@ function layout_builder_block_content_access(EntityInterface $entity, $operation } return AccessResult::forbidden(); } + +/** + * Implements hook_plugin_filter_TYPE__CONSUMER_alter(). + */ +function layout_builder_plugin_filter_block__block_ui_alter(array &$definitions, array $extra) { + foreach ($definitions as $id => $definition) { + // Filter out any layout_builder definition with required contexts. + if ($definition['provider'] === 'layout_builder' && !empty($definition['context'])) { + /** @var \Drupal\Core\Plugin\Context\ContextDefinitionInterface $context */ + foreach ($definition['context'] as $context) { + if ($context->isRequired()) { + unset($definitions[$id]); + break; + } + } + } + } +} diff --git a/web/core/modules/layout_builder/layout_builder.routing.yml b/web/core/modules/layout_builder/layout_builder.routing.yml index 54c9cf25b23a46e5d64ca004a0e67c55c6d303c5..3e3ee1b0241ca371ccd507b7006a1592e6a2b431 100644 --- a/web/core/modules/layout_builder/layout_builder.routing.yml +++ b/web/core/modules/layout_builder/layout_builder.routing.yml @@ -80,6 +80,19 @@ layout_builder.add_block: section_storage: layout_builder_tempstore: TRUE +layout_builder.choose_inline_block: + path: '/layout_builder/choose/inline-block/{section_storage_type}/{section_storage}/{delta}/{region}' + defaults: + _controller: '\Drupal\layout_builder\Controller\ChooseBlockController::inlineBlockList' + _title: 'Add a new Inline Block' + requirements: + _permission: 'configure any layout' + options: + _admin_route: TRUE + parameters: + section_storage: + layout_builder_tempstore: TRUE + layout_builder.update_block: path: '/layout_builder/update/block/{section_storage_type}/{section_storage}/{delta}/{region}/{uuid}' defaults: diff --git a/web/core/modules/layout_builder/src/Controller/ChooseBlockController.php b/web/core/modules/layout_builder/src/Controller/ChooseBlockController.php index 4f25eb09bd1bb12faa1719e44c12a51da850c9b4..9bd76bacc13f7df47d918053e167a034e4bdeb5a 100644 --- a/web/core/modules/layout_builder/src/Controller/ChooseBlockController.php +++ b/web/core/modules/layout_builder/src/Controller/ChooseBlockController.php @@ -5,6 +5,8 @@ use Drupal\Core\Ajax\AjaxHelperTrait; use Drupal\Core\Block\BlockManagerInterface; use Drupal\Core\DependencyInjection\ContainerInjectionInterface; +use Drupal\Core\Entity\EntityTypeManagerInterface; +use Drupal\Core\StringTranslation\StringTranslationTrait; use Drupal\Core\Url; use Drupal\layout_builder\Context\LayoutBuilderContextTrait; use Drupal\layout_builder\SectionStorageInterface; @@ -19,6 +21,7 @@ class ChooseBlockController implements ContainerInjectionInterface { use AjaxHelperTrait; use LayoutBuilderContextTrait; + use StringTranslationTrait; /** * The block manager. @@ -27,14 +30,24 @@ class ChooseBlockController implements ContainerInjectionInterface { */ protected $blockManager; + /** + * The entity type manager. + * + * @var \Drupal\Core\Entity\EntityTypeManagerInterface + */ + protected $entityTypeManager; + /** * ChooseBlockController constructor. * * @param \Drupal\Core\Block\BlockManagerInterface $block_manager * The block manager. + * @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager + * The entity type manager. */ - public function __construct(BlockManagerInterface $block_manager) { + public function __construct(BlockManagerInterface $block_manager, EntityTypeManagerInterface $entity_type_manager) { $this->blockManager = $block_manager; + $this->entityTypeManager = $entity_type_manager; } /** @@ -42,7 +55,8 @@ public function __construct(BlockManagerInterface $block_manager) { */ public static function create(ContainerInterface $container) { return new static( - $container->get('plugin.manager.block') + $container->get('plugin.manager.block'), + $container->get('entity_type.manager') ); } @@ -60,8 +74,44 @@ public static function create(ContainerInterface $container) { * A render array. */ public function build(SectionStorageInterface $section_storage, $delta, $region) { - $build['#type'] = 'container'; - $build['#attributes']['class'][] = 'block-categories'; + $build['#title'] = $this->t('Choose a block'); + if ($this->entityTypeManager->hasDefinition('block_content_type') && $types = $this->entityTypeManager->getStorage('block_content_type')->loadMultiple()) { + if (count($types) === 1) { + $type = reset($types); + $plugin_id = 'inline_block:' . $type->id(); + if ($this->blockManager->hasDefinition($plugin_id)) { + $url = Url::fromRoute('layout_builder.add_block', [ + 'section_storage_type' => $section_storage->getStorageType(), + 'section_storage' => $section_storage->getStorageId(), + 'delta' => $delta, + 'region' => $region, + 'plugin_id' => $plugin_id, + ]); + } + } + else { + $url = Url::fromRoute('layout_builder.choose_inline_block', [ + 'section_storage_type' => $section_storage->getStorageType(), + 'section_storage' => $section_storage->getStorageId(), + 'delta' => $delta, + 'region' => $region, + ]); + } + if (isset($url)) { + $build['add_block'] = [ + '#type' => 'link', + '#url' => $url, + '#title' => $this->t('Create @entity_type', [ + '@entity_type' => $this->entityTypeManager->getDefinition('block_content')->getSingularLabel(), + ]), + '#attributes' => $this->getAjaxAttributes(), + ]; + $build['add_block']['#attributes']['class'][] = 'inline-block-create-button'; + } + } + + $block_categories['#type'] = 'container'; + $block_categories['#attributes']['class'][] = 'block-categories'; // @todo Explicitly cast delta to an integer, remove this in // https://www.drupal.org/project/drupal/issues/2984509. @@ -72,35 +122,116 @@ public function build(SectionStorageInterface $section_storage, $delta, $region) 'delta' => $delta, 'region' => $region, ]); - foreach ($this->blockManager->getGroupedDefinitions($definitions) as $category => $blocks) { - $build[$category]['#type'] = 'details'; - $build[$category]['#open'] = TRUE; - $build[$category]['#title'] = $category; - $build[$category]['links'] = [ - '#theme' => 'links', - ]; - foreach ($blocks as $block_id => $block) { - $link = [ - 'title' => $block['admin_label'], - 'url' => Url::fromRoute('layout_builder.add_block', - [ - 'section_storage_type' => $section_storage->getStorageType(), - 'section_storage' => $section_storage->getStorageId(), - 'delta' => $delta, - 'region' => $region, - 'plugin_id' => $block_id, - ] - ), - ]; - if ($this->isAjax()) { - $link['attributes']['class'][] = 'use-ajax'; - $link['attributes']['data-dialog-type'][] = 'dialog'; - $link['attributes']['data-dialog-renderer'][] = 'off_canvas'; - } - $build[$category]['links']['#links'][] = $link; + $grouped_definitions = $this->blockManager->getGroupedDefinitions($definitions); + foreach ($grouped_definitions as $category => $blocks) { + $block_categories[$category]['#type'] = 'details'; + $block_categories[$category]['#open'] = TRUE; + $block_categories[$category]['#title'] = $category; + $block_categories[$category]['links'] = $this->getBlockLinks($section_storage, $delta, $region, $blocks); + } + $build['block_categories'] = $block_categories; + return $build; + } + + /** + * Provides the UI for choosing a new inline block. + * + * @param \Drupal\layout_builder\SectionStorageInterface $section_storage + * The section storage. + * @param int $delta + * The delta of the section to splice. + * @param string $region + * The region the block is going in. + * + * @return array + * A render array. + */ + public function inlineBlockList(SectionStorageInterface $section_storage, $delta, $region) { + $definitions = $this->blockManager->getFilteredDefinitions('layout_builder', $this->getAvailableContexts($section_storage), [ + 'section_storage' => $section_storage, + 'region' => $region, + 'list' => 'inline_blocks', + ]); + $blocks = $this->blockManager->getGroupedDefinitions($definitions); + $build = []; + if (isset($blocks['Inline blocks'])) { + $build['links'] = $this->getBlockLinks($section_storage, $delta, $region, $blocks['Inline blocks']); + $build['links']['#attributes']['class'][] = 'inline-block-list'; + foreach ($build['links']['#links'] as &$link) { + $link['attributes']['class'][] = 'inline-block-list__item'; } + $build['back_button'] = [ + '#type' => 'link', + '#url' => Url::fromRoute('layout_builder.choose_block', + [ + 'section_storage_type' => $section_storage->getStorageType(), + 'section_storage' => $section_storage->getStorageId(), + 'delta' => $delta, + 'region' => $region, + ] + ), + '#title' => $this->t('Back'), + '#attributes' => $this->getAjaxAttributes(), + ]; } return $build; } + /** + * Gets a render array of block links. + * + * @param \Drupal\layout_builder\SectionStorageInterface $section_storage + * The section storage. + * @param int $delta + * The delta of the section to splice. + * @param string $region + * The region the block is going in. + * @param array $blocks + * The information for each block. + * + * @return array + * The block links render array. + */ + protected function getBlockLinks(SectionStorageInterface $section_storage, $delta, $region, array $blocks) { + $links = []; + foreach ($blocks as $block_id => $block) { + $link = [ + 'title' => $block['admin_label'], + 'url' => Url::fromRoute('layout_builder.add_block', + [ + 'section_storage_type' => $section_storage->getStorageType(), + 'section_storage' => $section_storage->getStorageId(), + 'delta' => $delta, + 'region' => $region, + 'plugin_id' => $block_id, + ] + ), + 'attributes' => $this->getAjaxAttributes(), + ]; + + $links[] = $link; + } + return [ + '#theme' => 'links', + '#links' => $links, + ]; + } + + /** + * Get dialog attributes if an ajax request. + * + * @return array + * The attributes array. + */ + protected function getAjaxAttributes() { + if ($this->isAjax()) { + return [ + 'class' => ['use-ajax'], + 'data-dialog-type' => 'dialog', + 'data-dialog-renderer' => 'off_canvas', + ]; + } + return []; + } + } diff --git a/web/core/modules/layout_builder/src/Controller/LayoutBuilderController.php b/web/core/modules/layout_builder/src/Controller/LayoutBuilderController.php index c01fea544b2bf3320b5f871d71738cdf7d541b7d..00bb40261911761f30bc0a22dcf0082578ce97e8 100644 --- a/web/core/modules/layout_builder/src/Controller/LayoutBuilderController.php +++ b/web/core/modules/layout_builder/src/Controller/LayoutBuilderController.php @@ -2,6 +2,7 @@ namespace Drupal\layout_builder\Controller; +use Drupal\Core\Ajax\AjaxHelperTrait; use Drupal\Core\DependencyInjection\ContainerInjectionInterface; use Drupal\Core\Messenger\MessengerInterface; use Drupal\Core\Plugin\PluginFormInterface; @@ -24,6 +25,7 @@ class LayoutBuilderController implements ContainerInjectionInterface { use LayoutBuilderContextTrait; use StringTranslationTrait; + use AjaxHelperTrait; /** * The layout tempstore repository. @@ -90,6 +92,11 @@ public function layout(SectionStorageInterface $section_storage, $is_rebuilding $this->prepareLayout($section_storage, $is_rebuilding); $output = []; + if ($this->isAjax()) { + $output['status_messages'] = [ + '#type' => 'status_messages', + ]; + } $count = 0; for ($i = 0; $i < $section_storage->count(); $i++) { $output[] = $this->buildAddSectionLink($section_storage, $count); @@ -114,6 +121,11 @@ public function layout(SectionStorageInterface $section_storage, $is_rebuilding * Indicates if the layout is rebuilding. */ protected function prepareLayout(SectionStorageInterface $section_storage, $is_rebuilding) { + // If the layout has pending changes, add a warning. + if ($this->layoutTempstoreRepository->has($section_storage)) { + $this->messenger->addWarning($this->t('You have unsaved changes.')); + } + // Only add sections if the layout is new and empty. if (!$is_rebuilding && $section_storage->count() === 0) { $sections = []; @@ -269,7 +281,7 @@ protected function buildAdministrativeSection(SectionStorageInterface $section_s ], 'remove' => [ '#type' => 'link', - '#title' => $this->t('Remove section'), + '#title' => $this->t('Remove section <span class="visually-hidden">@section</span>', ['@section' => $delta + 1]), '#url' => Url::fromRoute('layout_builder.remove_section', [ 'section_storage_type' => $storage_type, 'section_storage' => $storage_id, diff --git a/web/core/modules/layout_builder/src/Entity/LayoutBuilderEntityViewDisplay.php b/web/core/modules/layout_builder/src/Entity/LayoutBuilderEntityViewDisplay.php index 78ff430b00959d780f223ff47aff29573697563a..7f10d6f51f9c186490989115e28f137768f04195 100644 --- a/web/core/modules/layout_builder/src/Entity/LayoutBuilderEntityViewDisplay.php +++ b/web/core/modules/layout_builder/src/Entity/LayoutBuilderEntityViewDisplay.php @@ -9,6 +9,7 @@ use Drupal\Core\StringTranslation\TranslatableMarkup; use Drupal\field\Entity\FieldConfig; use Drupal\field\Entity\FieldStorageConfig; +use Drupal\layout_builder\Plugin\SectionStorage\OverridesSectionStorage; use Drupal\layout_builder\Section; use Drupal\layout_builder\SectionComponent; use Drupal\layout_builder\SectionStorage\SectionStorageTrait; @@ -110,10 +111,10 @@ public function preSave(EntityStorageInterface $storage) { $bundle = $this->getTargetBundle(); if ($new_value) { - $this->addSectionField($entity_type_id, $bundle, 'layout_builder__layout'); + $this->addSectionField($entity_type_id, $bundle, OverridesSectionStorage::FIELD_NAME); } - elseif ($field = FieldConfig::loadByName($entity_type_id, $bundle, 'layout_builder__layout')) { - $field->delete(); + else { + $this->removeSectionField($entity_type_id, $bundle, OverridesSectionStorage::FIELD_NAME); } } @@ -139,6 +140,31 @@ public function preSave(EntityStorageInterface $storage) { } } + /** + * Removes a layout section field if it is no longer needed. + * + * Because the field is shared across all view modes, the field will only be + * removed if no other view modes are using it. + * + * @param string $entity_type_id + * The entity type ID. + * @param string $bundle + * The bundle. + * @param string $field_name + * The name for the layout section field. + */ + protected function removeSectionField($entity_type_id, $bundle, $field_name) { + $query = $this->entityTypeManager()->getStorage($this->getEntityTypeId())->getQuery() + ->condition('targetEntityType', $this->getTargetEntityTypeId()) + ->condition('bundle', $this->getTargetBundle()) + ->condition('mode', $this->getMode(), '<>') + ->condition('third_party_settings.layout_builder.allow_custom', TRUE); + $enabled = (bool) $query->count()->execute(); + if (!$enabled && $field = FieldConfig::loadByName($entity_type_id, $bundle, $field_name)) { + $field->delete(); + } + } + /** * Adds a layout section field to a given bundle. * @@ -172,6 +198,16 @@ protected function addSectionField($entity_type_id, $bundle, $field_name) { } } + /** + * {@inheritdoc} + */ + public function createCopy($mode) { + // Disable Layout Builder and remove any sections copied from the original. + return parent::createCopy($mode) + ->setSections([]) + ->disableLayoutBuilder(); + } + /** * {@inheritdoc} */ @@ -239,8 +275,8 @@ public function buildMultiple(array $entities) { * The sections. */ protected function getRuntimeSections(FieldableEntityInterface $entity) { - if ($this->isOverridable() && !$entity->get('layout_builder__layout')->isEmpty()) { - return $entity->get('layout_builder__layout')->getSections(); + if ($this->isOverridable() && !$entity->get(OverridesSectionStorage::FIELD_NAME)->isEmpty()) { + return $entity->get(OverridesSectionStorage::FIELD_NAME)->getSections(); } return $this->getSections(); diff --git a/web/core/modules/layout_builder/src/EventSubscriber/BlockComponentRenderArray.php b/web/core/modules/layout_builder/src/EventSubscriber/BlockComponentRenderArray.php index c2e3bfb188899606daad512542260c377b03d872..8b445bd77361e23fe24cf861e9b701570823c527 100644 --- a/web/core/modules/layout_builder/src/EventSubscriber/BlockComponentRenderArray.php +++ b/web/core/modules/layout_builder/src/EventSubscriber/BlockComponentRenderArray.php @@ -5,6 +5,8 @@ use Drupal\block_content\Access\RefinableDependentAccessInterface; use Drupal\Core\Access\AccessResult; use Drupal\Core\Block\BlockPluginInterface; +use Drupal\Core\Render\Element; +use Drupal\Core\Render\PreviewFallbackInterface; use Drupal\Core\Session\AccountInterface; use Drupal\layout_builder\Access\LayoutPreviewAccessAllowed; use Drupal\layout_builder\Event\SectionComponentBuildRenderArrayEvent; @@ -88,6 +90,14 @@ public function onBuildRender(SectionComponentBuildRenderArrayEvent $event) { if ($access->isAllowed()) { $event->addCacheableDependency($block); + $content = $block->build(); + $is_content_empty = Element::isEmpty($content); + $is_placeholder_ready = $event->inPreview() && $block instanceof PreviewFallbackInterface; + // If the content is empty and no placeholder is available, return. + if ($is_content_empty && !$is_placeholder_ready) { + return; + } + $build = [ // @todo Move this to BlockBase in https://www.drupal.org/node/2931040. '#theme' => 'block', @@ -96,8 +106,11 @@ public function onBuildRender(SectionComponentBuildRenderArrayEvent $event) { '#base_plugin_id' => $block->getBaseId(), '#derivative_plugin_id' => $block->getDerivativeId(), '#weight' => $event->getComponent()->getWeight(), - 'content' => $block->build(), + 'content' => $content, ]; + if ($is_content_empty && $is_placeholder_ready) { + $build['content']['#markup'] = $block->getPreviewFallbackString(); + } $event->setBuild($build); } } diff --git a/web/core/modules/layout_builder/src/Field/LayoutSectionItemList.php b/web/core/modules/layout_builder/src/Field/LayoutSectionItemList.php index a2ceca1373819bc00c91a9d323385c8e5cab1b45..c2603192f21689a11b76d93313e08ad45e22c0b4 100644 --- a/web/core/modules/layout_builder/src/Field/LayoutSectionItemList.php +++ b/web/core/modules/layout_builder/src/Field/LayoutSectionItemList.php @@ -47,9 +47,12 @@ protected function setSections(array $sections) { /** * {@inheritdoc} */ - public function __wakeup() { + public function getEntity() { + $entity = parent::getEntity(); + // Ensure the entity is updated with the latest value. - $this->getEntity()->set($this->getName(), $this->getValue()); + $entity->set($this->getName(), $this->getValue()); + return $entity; } } diff --git a/web/core/modules/layout_builder/src/Form/LayoutBuilderEntityViewDisplayForm.php b/web/core/modules/layout_builder/src/Form/LayoutBuilderEntityViewDisplayForm.php index b24549d9efa8e39eb7b8869372b68eaa2f4ac4db..72edc2f5b78901ca6c9409c4b29785d52ff13fb2 100644 --- a/web/core/modules/layout_builder/src/Form/LayoutBuilderEntityViewDisplayForm.php +++ b/web/core/modules/layout_builder/src/Form/LayoutBuilderEntityViewDisplayForm.php @@ -7,6 +7,7 @@ use Drupal\Core\Form\FormStateInterface; use Drupal\field_ui\Form\EntityViewDisplayEditForm; use Drupal\layout_builder\Entity\LayoutEntityDisplayInterface; +use Drupal\layout_builder\Plugin\SectionStorage\OverridesSectionStorage; use Drupal\layout_builder\SectionStorageInterface; /** @@ -47,6 +48,10 @@ public function buildForm(array $form, FormStateInterface $form_state, SectionSt public function form(array $form, FormStateInterface $form_state) { $form = parent::form($form, $form_state); + // Remove the Layout Builder field from the list. + $form['#fields'] = array_diff($form['#fields'], [OverridesSectionStorage::FIELD_NAME]); + unset($form['fields'][OverridesSectionStorage::FIELD_NAME]); + $is_enabled = $this->entity->isLayoutBuilderEnabled(); if ($is_enabled) { // Hide the table of fields. @@ -54,10 +59,6 @@ public function form(array $form, FormStateInterface $form_state) { $form['#fields'] = []; $form['#extra'] = []; } - else { - // Remove the Layout Builder field from the list. - $form['#fields'] = array_diff($form['#fields'], ['layout_builder__layout']); - } $form['manage_layout'] = [ '#type' => 'link', @@ -133,7 +134,7 @@ protected function hasOverrides(LayoutEntityDisplayInterface $display) { $entity_type = $this->entityTypeManager->getDefinition($display->getTargetEntityTypeId()); $query = $this->entityTypeManager->getStorage($display->getTargetEntityTypeId())->getQuery() - ->exists('layout_builder__layout'); + ->exists(OverridesSectionStorage::FIELD_NAME); if ($bundle_key = $entity_type->getKey('bundle')) { $query->condition($bundle_key, $display->getTargetBundle()); } @@ -180,7 +181,7 @@ public function entityFormEntityBuild($entity_type_id, LayoutEntityDisplayInterf * {@inheritdoc} */ protected function buildFieldRow(FieldDefinitionInterface $field_definition, array $form, FormStateInterface $form_state) { - if ($this->entity->isLayoutBuilderEnabled() || $field_definition->getType() === 'layout_section') { + if ($this->entity->isLayoutBuilderEnabled()) { return []; } diff --git a/web/core/modules/layout_builder/src/Form/RevertOverridesForm.php b/web/core/modules/layout_builder/src/Form/RevertOverridesForm.php index 837140ecf85fe8a18cc1dc7eb0a72f3ba1847b3d..b6d07d90890c39ea1dc8bd6747fe4a1ac776b761 100644 --- a/web/core/modules/layout_builder/src/Form/RevertOverridesForm.php +++ b/web/core/modules/layout_builder/src/Form/RevertOverridesForm.php @@ -103,10 +103,6 @@ public function buildForm(array $form, FormStateInterface $form_state, SectionSt * {@inheritdoc} */ public function submitForm(array &$form, FormStateInterface $form_state) { - // Ensure the section storage is loaded from the database. - // @todo Remove after https://www.drupal.org/node/2970801. - $this->sectionStorage = \Drupal::service('plugin.manager.layout_builder.section_storage')->loadFromStorageId($this->sectionStorage->getStorageType(), $this->sectionStorage->getStorageId()); - // Remove all sections. while ($this->sectionStorage->count()) { $this->sectionStorage->removeSection(0); diff --git a/web/core/modules/layout_builder/src/InlineBlockUsage.php b/web/core/modules/layout_builder/src/InlineBlockUsage.php index 098177ddc13f9501a8cc123153e63c5ca00e6322..063986212312e60cf23732f7a6087f4a3aa15b78 100644 --- a/web/core/modules/layout_builder/src/InlineBlockUsage.php +++ b/web/core/modules/layout_builder/src/InlineBlockUsage.php @@ -87,8 +87,10 @@ public function removeByLayoutEntity(EntityInterface $entity) { * The block content entity IDs. */ public function deleteUsage(array $block_content_ids) { - $query = $this->database->delete('inline_block_usage')->condition('block_content_id', $block_content_ids, 'IN'); - $query->execute(); + if (!empty($block_content_ids)) { + $query = $this->database->delete('inline_block_usage')->condition('block_content_id', $block_content_ids, 'IN'); + $query->execute(); + } } /** diff --git a/web/core/modules/layout_builder/src/LayoutEntityHelperTrait.php b/web/core/modules/layout_builder/src/LayoutEntityHelperTrait.php index 9124027542ef13cfdba94f2b30775032e1ea0311..fc22168a99e5fb0afb6824c048944b0edaf6b473 100644 --- a/web/core/modules/layout_builder/src/LayoutEntityHelperTrait.php +++ b/web/core/modules/layout_builder/src/LayoutEntityHelperTrait.php @@ -6,6 +6,7 @@ use Drupal\Core\Entity\EntityInterface; use Drupal\Core\Entity\FieldableEntityInterface; use Drupal\layout_builder\Entity\LayoutEntityDisplayInterface; +use Drupal\layout_builder\Plugin\SectionStorage\OverridesSectionStorage; /** * Methods to help with entities using the layout builder. @@ -65,7 +66,7 @@ protected function getEntitySections(EntityInterface $entity) { return $entity->getSections(); } elseif ($this->isEntityUsingFieldOverride($entity)) { - return $entity->get('layout_builder__layout')->getSections(); + return $entity->get(OverridesSectionStorage::FIELD_NAME)->getSections(); } return NULL; } @@ -102,7 +103,7 @@ protected function getInlineBlockComponents(array $sections) { * TRUE if the entity is using a field for a layout override. */ protected function isEntityUsingFieldOverride(EntityInterface $entity) { - return $entity instanceof FieldableEntityInterface && $entity->hasField('layout_builder__layout'); + return $entity instanceof FieldableEntityInterface && $entity->hasField(OverridesSectionStorage::FIELD_NAME); } } diff --git a/web/core/modules/layout_builder/src/LayoutTempstoreRepository.php b/web/core/modules/layout_builder/src/LayoutTempstoreRepository.php index 39725afc7e20068e9d25fdea0af447d0c32c117f..69676861db43583b426fe836d6d36ac3f71cf660 100644 --- a/web/core/modules/layout_builder/src/LayoutTempstoreRepository.php +++ b/web/core/modules/layout_builder/src/LayoutTempstoreRepository.php @@ -45,6 +45,15 @@ public function get(SectionStorageInterface $section_storage) { return $section_storage; } + /** + * {@inheritdoc} + */ + public function has(SectionStorageInterface $section_storage) { + $id = $section_storage->getStorageId(); + $tempstore = $this->getTempstore($section_storage)->get($id); + return !empty($tempstore['section_storage']); + } + /** * {@inheritdoc} */ diff --git a/web/core/modules/layout_builder/src/LayoutTempstoreRepositoryInterface.php b/web/core/modules/layout_builder/src/LayoutTempstoreRepositoryInterface.php index 4972a47f6f058359b5702b84c12ab2ca164dbf77..67dc59ca99d807d34b60a44778a138f5df88dca4 100644 --- a/web/core/modules/layout_builder/src/LayoutTempstoreRepositoryInterface.php +++ b/web/core/modules/layout_builder/src/LayoutTempstoreRepositoryInterface.php @@ -35,6 +35,17 @@ public function get(SectionStorageInterface $section_storage); */ public function set(SectionStorageInterface $section_storage); + /** + * Checks for the existence of a tempstore version of a section storage. + * + * @param \Drupal\layout_builder\SectionStorageInterface $section_storage + * The section storage to check for in tempstore. + * + * @return bool + * TRUE if there is a tempstore version of this section storage. + */ + public function has(SectionStorageInterface $section_storage); + /** * Removes the tempstore version of a section storage. * diff --git a/web/core/modules/layout_builder/src/Plugin/Block/ExtraFieldBlock.php b/web/core/modules/layout_builder/src/Plugin/Block/ExtraFieldBlock.php index ddb7f01fd9bfa3047c57499b49e81486e1bfa316..6b991037687d4d9c9ae76afadad3a74a5e8aa602 100644 --- a/web/core/modules/layout_builder/src/Plugin/Block/ExtraFieldBlock.php +++ b/web/core/modules/layout_builder/src/Plugin/Block/ExtraFieldBlock.php @@ -130,13 +130,22 @@ public function build() { // render array. If the hook is invoked the placeholder will be // replaced. // @see ::replaceFieldPlaceholder() - '#markup' => new TranslatableMarkup('Placeholder for the "@field" field', ['@field' => $extra_fields['display'][$this->fieldName]['label']]), + '#markup' => $this->getPreviewFallbackString(), ]; } CacheableMetadata::createFromObject($this)->applyTo($build); return $build; } + /** + * {@inheritdoc} + */ + public function getPreviewFallbackString() { + $entity = $this->getEntity(); + $extra_fields = $this->entityFieldManager->getExtraFields($entity->getEntityTypeId(), $entity->bundle()); + return new TranslatableMarkup('Placeholder for the "@field" field', ['@field' => $extra_fields['display'][$this->fieldName]['label']]); + } + /** * Replaces all placeholders for a given field. * diff --git a/web/core/modules/layout_builder/src/Plugin/Block/FieldBlock.php b/web/core/modules/layout_builder/src/Plugin/Block/FieldBlock.php index bb8ed11797cf04f4314f36d1d7868a4eb193677a..88e608f6f465d8a2e62da64b251cb227136db0e7 100644 --- a/web/core/modules/layout_builder/src/Plugin/Block/FieldBlock.php +++ b/web/core/modules/layout_builder/src/Plugin/Block/FieldBlock.php @@ -17,7 +17,6 @@ use Drupal\Core\Form\FormStateInterface; use Drupal\Core\Plugin\ContainerFactoryPluginInterface; use Drupal\Core\Plugin\ContextAwarePluginInterface; -use Drupal\Core\Render\Element; use Drupal\Core\Session\AccountInterface; use Drupal\Core\StringTranslation\TranslatableMarkup; use Psr\Log\LoggerInterface; @@ -160,13 +159,17 @@ public function build() { $build = []; $this->logger->warning('The field "%field" failed to render with the error of "%error".', ['%field' => $this->fieldName, '%error' => $e->getMessage()]); } - if (!empty($entity->in_preview) && !Element::getVisibleChildren($build)) { - $build['content']['#markup'] = new TranslatableMarkup('Placeholder for the "@field" field', ['@field' => $this->getFieldDefinition()->getLabel()]); - } CacheableMetadata::createFromObject($this)->applyTo($build); return $build; } + /** + * {@inheritdoc} + */ + public function getPreviewFallbackString() { + return new TranslatableMarkup('Placeholder for the "@field" field', ['@field' => $this->getFieldDefinition()->getLabel()]); + } + /** * {@inheritdoc} */ diff --git a/web/core/modules/layout_builder/src/Plugin/Derivative/FieldBlockDeriver.php b/web/core/modules/layout_builder/src/Plugin/Derivative/FieldBlockDeriver.php index 3e15fcd78227aa021080a0c8e9bc00996003176d..57d2c1ec7c4596b382241d3ac71fc971abaf86f9 100644 --- a/web/core/modules/layout_builder/src/Plugin/Derivative/FieldBlockDeriver.php +++ b/web/core/modules/layout_builder/src/Plugin/Derivative/FieldBlockDeriver.php @@ -106,7 +106,7 @@ public function getDerivativeDefinitions($base_plugin_definition) { $derivative['default_formatter'] = $field_type_definition['default_formatter']; } - $derivative['category'] = $this->t('@entity', ['@entity' => $entity_type_labels[$entity_type_id]]); + $derivative['category'] = $this->t('@entity fields', ['@entity' => $entity_type_labels[$entity_type_id]]); $derivative['admin_label'] = $field_definition->getLabel(); diff --git a/web/core/modules/layout_builder/src/Plugin/Derivative/LayoutBuilderLocalTaskDeriver.php b/web/core/modules/layout_builder/src/Plugin/Derivative/LayoutBuilderLocalTaskDeriver.php index e2053f342eebb9f052154d4d22b35e1d06a70dfb..9e4a2ce42c4fd5bb41ce4ec084d3054d11467372 100644 --- a/web/core/modules/layout_builder/src/Plugin/Derivative/LayoutBuilderLocalTaskDeriver.php +++ b/web/core/modules/layout_builder/src/Plugin/Derivative/LayoutBuilderLocalTaskDeriver.php @@ -3,11 +3,11 @@ namespace Drupal\layout_builder\Plugin\Derivative; use Drupal\Component\Plugin\Derivative\DeriverBase; -use Drupal\Core\Entity\EntityTypeInterface; use Drupal\Core\Entity\EntityTypeManagerInterface; -use Drupal\Core\Entity\FieldableEntityInterface; use Drupal\Core\Plugin\Discovery\ContainerDeriverInterface; use Drupal\Core\StringTranslation\StringTranslationTrait; +use Drupal\layout_builder\Plugin\SectionStorage\SectionStorageLocalTaskProviderInterface; +use Drupal\layout_builder\SectionStorage\SectionStorageManagerInterface; use Symfony\Component\DependencyInjection\ContainerInterface; /** @@ -28,14 +28,24 @@ class LayoutBuilderLocalTaskDeriver extends DeriverBase implements ContainerDeri */ protected $entityTypeManager; + /** + * The section storage manager. + * + * @var \Drupal\layout_builder\SectionStorage\SectionStorageManagerInterface + */ + protected $sectionStorageManager; + /** * Constructs a new LayoutBuilderLocalTaskDeriver. * * @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager * The entity type manager. + * @param \Drupal\layout_builder\SectionStorage\SectionStorageManagerInterface $section_storage_manager + * The section storage manager. */ - public function __construct(EntityTypeManagerInterface $entity_type_manager) { + public function __construct(EntityTypeManagerInterface $entity_type_manager, SectionStorageManagerInterface $section_storage_manager) { $this->entityTypeManager = $entity_type_manager; + $this->sectionStorageManager = $section_storage_manager; } /** @@ -43,7 +53,8 @@ public function __construct(EntityTypeManagerInterface $entity_type_manager) { */ public static function create(ContainerInterface $container, $base_plugin_id) { return new static( - $container->get('entity_type.manager') + $container->get('entity_type.manager'), + $container->get('plugin.manager.layout_builder.section_storage') ); } @@ -51,84 +62,13 @@ public static function create(ContainerInterface $container, $base_plugin_id) { * {@inheritdoc} */ public function getDerivativeDefinitions($base_plugin_definition) { - foreach ($this->getEntityTypesForOverrides() as $entity_type_id => $entity_type) { - // Overrides. - $this->derivatives["layout_builder.overrides.$entity_type_id.view"] = $base_plugin_definition + [ - 'route_name' => "layout_builder.overrides.$entity_type_id.view", - 'weight' => 15, - 'title' => $this->t('Layout'), - 'base_route' => "entity.$entity_type_id.canonical", - 'cache_contexts' => ['layout_builder_is_active:' . $entity_type_id], - ]; - $this->derivatives["layout_builder.overrides.$entity_type_id.save"] = $base_plugin_definition + [ - 'route_name' => "layout_builder.overrides.$entity_type_id.save", - 'title' => $this->t('Save Layout'), - 'parent_id' => "layout_builder_ui:layout_builder.overrides.$entity_type_id.view", - 'cache_contexts' => ['layout_builder_is_active:' . $entity_type_id], - ]; - $this->derivatives["layout_builder.overrides.$entity_type_id.cancel"] = $base_plugin_definition + [ - 'route_name' => "layout_builder.overrides.$entity_type_id.cancel", - 'title' => $this->t('Cancel Layout'), - 'parent_id' => "layout_builder_ui:layout_builder.overrides.$entity_type_id.view", - 'weight' => 5, - 'cache_contexts' => ['layout_builder_is_active:' . $entity_type_id], - ]; - // @todo This link should be conditionally displayed, see - // https://www.drupal.org/node/2917777. - $this->derivatives["layout_builder.overrides.$entity_type_id.revert"] = $base_plugin_definition + [ - 'route_name' => "layout_builder.overrides.$entity_type_id.revert", - 'title' => $this->t('Revert to defaults'), - 'parent_id' => "layout_builder_ui:layout_builder.overrides.$entity_type_id.view", - 'weight' => 10, - 'cache_contexts' => ['layout_builder_is_active:' . $entity_type_id], - ]; + foreach ($this->sectionStorageManager->getDefinitions() as $plugin_id => $definition) { + $section_storage = $this->sectionStorageManager->loadEmpty($plugin_id); + if ($section_storage instanceof SectionStorageLocalTaskProviderInterface) { + $this->derivatives += $section_storage->buildLocalTasks($base_plugin_definition); + } } - - foreach ($this->getEntityTypesForDefaults() as $entity_type_id => $entity_type) { - // Defaults. - $this->derivatives["layout_builder.defaults.$entity_type_id.view"] = $base_plugin_definition + [ - 'route_name' => "layout_builder.defaults.$entity_type_id.view", - 'title' => $this->t('Manage layout'), - 'base_route' => "layout_builder.defaults.$entity_type_id.view", - ]; - $this->derivatives["layout_builder.defaults.$entity_type_id.save"] = $base_plugin_definition + [ - 'route_name' => "layout_builder.defaults.$entity_type_id.save", - 'title' => $this->t('Save Layout'), - 'parent_id' => "layout_builder_ui:layout_builder.defaults.$entity_type_id.view", - ]; - $this->derivatives["layout_builder.defaults.$entity_type_id.cancel"] = $base_plugin_definition + [ - 'route_name' => "layout_builder.defaults.$entity_type_id.cancel", - 'title' => $this->t('Cancel Layout'), - 'weight' => 5, - 'parent_id' => "layout_builder_ui:layout_builder.defaults.$entity_type_id.view", - ]; - } - return $this->derivatives; } - /** - * Returns an array of entity types relevant for defaults. - * - * @return \Drupal\Core\Entity\EntityTypeInterface[] - * An array of entity types. - */ - protected function getEntityTypesForDefaults() { - return array_filter($this->entityTypeManager->getDefinitions(), function (EntityTypeInterface $entity_type) { - return $entity_type->entityClassImplements(FieldableEntityInterface::class) && $entity_type->hasViewBuilderClass() && $entity_type->get('field_ui_base_route'); - }); - } - - /** - * Returns an array of entity types relevant for overrides. - * - * @return \Drupal\Core\Entity\EntityTypeInterface[] - * An array of entity types. - */ - protected function getEntityTypesForOverrides() { - return array_filter($this->entityTypeManager->getDefinitions(), function (EntityTypeInterface $entity_type) { - return $entity_type->entityClassImplements(FieldableEntityInterface::class) && $entity_type->hasViewBuilderClass() && $entity_type->hasLinkTemplate('canonical'); - }); - } - } diff --git a/web/core/modules/layout_builder/src/Plugin/SectionStorage/DefaultsSectionStorage.php b/web/core/modules/layout_builder/src/Plugin/SectionStorage/DefaultsSectionStorage.php index 6fab11996b02d3de386112ad6268370ea5cd6167..d35041d03d8fe09835e442cf85cd3b538b2d5c20 100644 --- a/web/core/modules/layout_builder/src/Plugin/SectionStorage/DefaultsSectionStorage.php +++ b/web/core/modules/layout_builder/src/Plugin/SectionStorage/DefaultsSectionStorage.php @@ -32,7 +32,7 @@ * experimental modules and development releases of contributed modules. * See https://www.drupal.org/core/experimental for more information. */ -class DefaultsSectionStorage extends SectionStorageBase implements ContainerFactoryPluginInterface, DefaultsSectionStorageInterface { +class DefaultsSectionStorage extends SectionStorageBase implements ContainerFactoryPluginInterface, DefaultsSectionStorageInterface, SectionStorageLocalTaskProviderInterface { /** * The entity type manager. @@ -196,6 +196,32 @@ public function buildRoutes(RouteCollection $collection) { } } + /** + * {@inheritdoc} + */ + public function buildLocalTasks($base_plugin_definition) { + $local_tasks = []; + foreach ($this->getEntityTypes() as $entity_type_id => $entity_type) { + $local_tasks["layout_builder.defaults.$entity_type_id.view"] = $base_plugin_definition + [ + 'route_name' => "layout_builder.defaults.$entity_type_id.view", + 'title' => $this->t('Manage layout'), + 'base_route' => "layout_builder.defaults.$entity_type_id.view", + ]; + $local_tasks["layout_builder.defaults.$entity_type_id.save"] = $base_plugin_definition + [ + 'route_name' => "layout_builder.defaults.$entity_type_id.save", + 'title' => $this->t('Save Layout'), + 'parent_id' => "layout_builder_ui:layout_builder.defaults.$entity_type_id.view", + ]; + $local_tasks["layout_builder.defaults.$entity_type_id.cancel"] = $base_plugin_definition + [ + 'route_name' => "layout_builder.defaults.$entity_type_id.cancel", + 'title' => $this->t('Cancel Layout'), + 'weight' => 5, + 'parent_id' => "layout_builder_ui:layout_builder.defaults.$entity_type_id.view", + ]; + } + return $local_tasks; + } + /** * Returns an array of relevant entity types. * diff --git a/web/core/modules/layout_builder/src/Plugin/SectionStorage/OverridesSectionStorage.php b/web/core/modules/layout_builder/src/Plugin/SectionStorage/OverridesSectionStorage.php index 3a92ee63fab7fe21fbfd5f50243c25650f7da1ad..bba10ef67f39959df3f61592d18b25bfca836261 100644 --- a/web/core/modules/layout_builder/src/Plugin/SectionStorage/OverridesSectionStorage.php +++ b/web/core/modules/layout_builder/src/Plugin/SectionStorage/OverridesSectionStorage.php @@ -30,7 +30,14 @@ * experimental modules and development releases of contributed modules. * See https://www.drupal.org/core/experimental for more information. */ -class OverridesSectionStorage extends SectionStorageBase implements ContainerFactoryPluginInterface, OverridesSectionStorageInterface { +class OverridesSectionStorage extends SectionStorageBase implements ContainerFactoryPluginInterface, OverridesSectionStorageInterface, SectionStorageLocalTaskProviderInterface { + + /** + * The field name used by this storage. + * + * @var string + */ + const FIELD_NAME = 'layout_builder__layout'; /** * The entity type manager. @@ -127,8 +134,8 @@ public function getSectionListFromId($id) { if (strpos($id, '.') !== FALSE) { list($entity_type_id, $entity_id) = explode('.', $id, 2); $entity = $this->entityTypeManager->getStorage($entity_type_id)->load($entity_id); - if ($entity instanceof FieldableEntityInterface && $entity->hasField('layout_builder__layout')) { - return $entity->get('layout_builder__layout'); + if ($entity instanceof FieldableEntityInterface && $entity->hasField(static::FIELD_NAME)) { + return $entity->get(static::FIELD_NAME); } } throw new \InvalidArgumentException(sprintf('The "%s" ID for the "%s" section storage type is invalid', $id, $this->getStorageType())); @@ -157,6 +164,45 @@ public function buildRoutes(RouteCollection $collection) { } } + /** + * {@inheritdoc} + */ + public function buildLocalTasks($base_plugin_definition) { + $local_tasks = []; + foreach ($this->getEntityTypes() as $entity_type_id => $entity_type) { + $local_tasks["layout_builder.overrides.$entity_type_id.view"] = $base_plugin_definition + [ + 'route_name' => "layout_builder.overrides.$entity_type_id.view", + 'weight' => 15, + 'title' => $this->t('Layout'), + 'base_route' => "entity.$entity_type_id.canonical", + 'cache_contexts' => ['layout_builder_is_active:' . $entity_type_id], + ]; + $local_tasks["layout_builder.overrides.$entity_type_id.save"] = $base_plugin_definition + [ + 'route_name' => "layout_builder.overrides.$entity_type_id.save", + 'title' => $this->t('Save Layout'), + 'parent_id' => "layout_builder_ui:layout_builder.overrides.$entity_type_id.view", + 'cache_contexts' => ['layout_builder_is_active:' . $entity_type_id], + ]; + $local_tasks["layout_builder.overrides.$entity_type_id.cancel"] = $base_plugin_definition + [ + 'route_name' => "layout_builder.overrides.$entity_type_id.cancel", + 'title' => $this->t('Cancel Layout'), + 'parent_id' => "layout_builder_ui:layout_builder.overrides.$entity_type_id.view", + 'weight' => 5, + 'cache_contexts' => ['layout_builder_is_active:' . $entity_type_id], + ]; + // @todo This link should be conditionally displayed, see + // https://www.drupal.org/node/2917777. + $local_tasks["layout_builder.overrides.$entity_type_id.revert"] = $base_plugin_definition + [ + 'route_name' => "layout_builder.overrides.$entity_type_id.revert", + 'title' => $this->t('Revert to defaults'), + 'parent_id' => "layout_builder_ui:layout_builder.overrides.$entity_type_id.view", + 'weight' => 10, + 'cache_contexts' => ['layout_builder_is_active:' . $entity_type_id], + ]; + } + return $local_tasks; + } + /** * Determines if this entity type's ID is stored as an integer. * diff --git a/web/core/modules/layout_builder/src/Plugin/SectionStorage/SectionStorageLocalTaskProviderInterface.php b/web/core/modules/layout_builder/src/Plugin/SectionStorage/SectionStorageLocalTaskProviderInterface.php new file mode 100644 index 0000000000000000000000000000000000000000..a275d6340dd6504163d2547fa0eec557c2144d58 --- /dev/null +++ b/web/core/modules/layout_builder/src/Plugin/SectionStorage/SectionStorageLocalTaskProviderInterface.php @@ -0,0 +1,29 @@ +<?php + +namespace Drupal\layout_builder\Plugin\SectionStorage; + +/** + * Allows section storage plugins to provide local tasks. + * + * @see \Drupal\layout_builder\Plugin\Derivative\LayoutBuilderLocalTaskDeriver + * @see \Drupal\layout_builder\SectionStorageInterface + * + * @internal + * Layout Builder is currently experimental and should only be leveraged by + * experimental modules and development releases of contributed modules. + * See https://www.drupal.org/core/experimental for more information. + */ +interface SectionStorageLocalTaskProviderInterface { + + /** + * Provides the local tasks dynamically for Layout Builder plugins. + * + * @param mixed $base_plugin_definition + * The definition of the base plugin. + * + * @return array + * An array of full derivative definitions keyed on derivative ID. + */ + public function buildLocalTasks($base_plugin_definition); + +} diff --git a/web/core/modules/layout_builder/src/Section.php b/web/core/modules/layout_builder/src/Section.php index 30d903a30ab8a8f15eb116389a41c385d833313c..1ec0b8af10aea6d433106e59d99758836cdc8b4d 100644 --- a/web/core/modules/layout_builder/src/Section.php +++ b/web/core/modules/layout_builder/src/Section.php @@ -356,4 +356,13 @@ public static function fromArray(array $section) { ); } + /** + * Magic method: Implements a deep clone. + */ + public function __clone() { + foreach ($this->components as $uuid => $component) { + $this->components[$uuid] = clone $component; + } + } + } diff --git a/web/core/modules/layout_builder/src/SectionStorage/SectionStorageTrait.php b/web/core/modules/layout_builder/src/SectionStorage/SectionStorageTrait.php index 9d942c7ad85982898e0480f3f7cac4d075b2f83e..36729d2ba6240d0377c9adf6cc7734d317c5c5fc 100644 --- a/web/core/modules/layout_builder/src/SectionStorage/SectionStorageTrait.php +++ b/web/core/modules/layout_builder/src/SectionStorage/SectionStorageTrait.php @@ -111,4 +111,17 @@ protected function hasSection($delta) { return isset($this->getSections()[$delta]); } + /** + * Magic method: Implements a deep clone. + */ + public function __clone() { + $sections = $this->getSections(); + + foreach ($sections as $delta => $item) { + $sections[$delta] = clone $item; + } + + $this->setSections($sections); + } + } diff --git a/web/core/modules/layout_builder/tests/modules/layout_builder_fieldblock_test/config/schema/layout_builder_fieldblock_test.schema.yml b/web/core/modules/layout_builder/tests/modules/layout_builder_fieldblock_test/config/schema/layout_builder_fieldblock_test.schema.yml new file mode 100644 index 0000000000000000000000000000000000000000..92ce34d00634ce13b6c767550262c9364a1553ee --- /dev/null +++ b/web/core/modules/layout_builder/tests/modules/layout_builder_fieldblock_test/config/schema/layout_builder_fieldblock_test.schema.yml @@ -0,0 +1,3 @@ +# See \Drupal\layout_builder_fieldblock_test\Plugin\Block\FieldBlock. +block.settings.field_block_test:*:*:*: + type: block.settings.field_block:*:*:* diff --git a/web/core/modules/layout_builder/tests/modules/layout_builder_fieldblock_test/layout_builder_fieldblock_test.info.yml b/web/core/modules/layout_builder/tests/modules/layout_builder_fieldblock_test/layout_builder_fieldblock_test.info.yml new file mode 100644 index 0000000000000000000000000000000000000000..607877e78081aee3f45d28c322e40b697546c654 --- /dev/null +++ b/web/core/modules/layout_builder/tests/modules/layout_builder_fieldblock_test/layout_builder_fieldblock_test.info.yml @@ -0,0 +1,6 @@ +name: 'Layout Builder test' +type: module +description: 'Support module for testing layout building.' +package: Testing +version: VERSION +core: 8.x diff --git a/web/core/modules/layout_builder/tests/modules/layout_builder_fieldblock_test/src/Plugin/Block/FieldBlock.php b/web/core/modules/layout_builder/tests/modules/layout_builder_fieldblock_test/src/Plugin/Block/FieldBlock.php new file mode 100644 index 0000000000000000000000000000000000000000..07a00f5412b70fa258605683591f5130cc5a879f --- /dev/null +++ b/web/core/modules/layout_builder/tests/modules/layout_builder_fieldblock_test/src/Plugin/Block/FieldBlock.php @@ -0,0 +1,27 @@ +<?php + +namespace Drupal\layout_builder_fieldblock_test\Plugin\Block; + +use Drupal\layout_builder\Plugin\Block\FieldBlock as LayoutBuilderFieldBlock; + +/** + * Provides test field block to test with Block UI. + * + * \Drupal\Tests\layout_builder\FunctionalJavascript\FieldBlockTest provides + * test coverage of complex AJAX interactions within certain field blocks. + * layout_builder_plugin_filter_block__block_ui_alter() removes certain blocks + * with 'layout_builder' as the provider. To make these blocks available during + * testing, this plugin uses the same deriver but each derivative will have a + * different provider. + * + * @Block( + * id = "field_block_test", + * deriver = "\Drupal\layout_builder\Plugin\Derivative\FieldBlockDeriver", + * ) + * + * @see \Drupal\Tests\layout_builder\FunctionalJavascript\FieldBlockTest + * @see layout_builder_plugin_filter_block__block_ui_alter() + */ +class FieldBlock extends LayoutBuilderFieldBlock { + +} diff --git a/web/core/modules/layout_builder/tests/src/Functional/LayoutBuilderTest.php b/web/core/modules/layout_builder/tests/src/Functional/LayoutBuilderTest.php index 293f7b9f7c164a53287dfa2e298f27379657ac64..be04c32ab3860acbeade2567dd3a35442ce7837e 100644 --- a/web/core/modules/layout_builder/tests/src/Functional/LayoutBuilderTest.php +++ b/web/core/modules/layout_builder/tests/src/Functional/LayoutBuilderTest.php @@ -22,6 +22,7 @@ class LayoutBuilderTest extends BrowserTestBase { 'layout_builder_views_test', 'layout_test', 'block', + 'block_test', 'node', 'layout_builder_test', ]; @@ -90,7 +91,7 @@ public function testLayoutBuilderUi() { // The body field is only present once. $assert_session->elementsCount('css', '.field--name-body', 1); // The extra field is only present once. - $this->assertTextAppearsOnce('Placeholder for the "Extra label" field'); + $assert_session->pageTextContainsOnce('Placeholder for the "Extra label" field'); // Save the defaults. $assert_session->linkExists('Save Layout'); $this->clickLink('Save Layout'); @@ -105,7 +106,7 @@ public function testLayoutBuilderUi() { // The body field is only present once. $assert_session->elementsCount('css', '.field--name-body', 1); // The extra field is only present once. - $this->assertTextAppearsOnce('Placeholder for the "Extra label" field'); + $assert_session->pageTextContainsOnce('Placeholder for the "Extra label" field'); // Add a new block. $assert_session->linkExists('Add Block'); @@ -191,11 +192,21 @@ public function testLayoutBuilderUi() { // Reverting the override returns it to the defaults. $this->clickLink('Layout'); + $assert_session->linkExists('Add Block'); + $this->clickLink('Add Block'); + $assert_session->linkExists('ID'); + $this->clickLink('ID'); + $page->pressButton('Add Block'); + // The title field is present. + $assert_session->elementExists('css', '.field--name-nid'); + $assert_session->pageTextContains('ID'); + $assert_session->pageTextContains('1'); $assert_session->linkExists('Revert to defaults'); $this->clickLink('Revert to defaults'); $page->pressButton('Revert'); $assert_session->pageTextContains('The layout has been reverted back to defaults.'); $assert_session->elementExists('css', '.field--name-title'); + $assert_session->elementNotExists('css', '.field--name-nid'); $assert_session->pageTextContains('The first node body'); $assert_session->pageTextContains('Powered by Drupal'); $assert_session->pageTextContains('Placeholder for the "Extra label" field'); @@ -225,6 +236,63 @@ public function testLayoutBuilderUi() { $assert_session->elementNotExists('css', '.field--name-field-my-text'); } + /** + * Tests that a non-default view mode works as expected. + */ + public function testNonDefaultViewMode() { + $assert_session = $this->assertSession(); + $page = $this->getSession()->getPage(); + + $this->drupalLogin($this->drupalCreateUser([ + 'configure any layout', + 'administer node display', + ])); + + $field_ui_prefix = 'admin/structure/types/manage/bundle_with_section_field'; + // Allow overrides for the layout. + $this->drupalGet("$field_ui_prefix/display/default"); + $page->checkField('layout[enabled]'); + $page->pressButton('Save'); + $page->checkField('layout[allow_custom]'); + $page->pressButton('Save'); + + $this->clickLink('Manage layout'); + // Confirm the body field only is shown once. + $assert_session->elementsCount('css', '.field--name-body', 1); + $this->clickLink('Cancel Layout'); + + $this->clickLink('Teaser'); + // Enabling Layout Builder for the default mode does not affect the teaser. + $assert_session->addressEquals("$field_ui_prefix/display/teaser"); + $assert_session->elementNotExists('css', '#layout-builder__layout'); + $assert_session->checkboxNotChecked('layout[enabled]'); + $page->checkField('layout[enabled]'); + $page->pressButton('Save'); + $assert_session->linkExists('Manage layout'); + $page->clickLink('Manage layout'); + // Confirm the body field only is shown once. + $assert_session->elementsCount('css', '.field--name-body', 1); + + // Enable a disabled view mode. + $page->clickLink('Cancel Layout'); + $assert_session->addressEquals("$field_ui_prefix/display/teaser"); + $page->clickLink('Default'); + $assert_session->addressEquals("$field_ui_prefix/display"); + $assert_session->linkNotExists('Full content'); + $page->checkField('display_modes_custom[full]'); + $page->pressButton('Save'); + + $assert_session->linkExists('Full content'); + $page->clickLink('Full content'); + $assert_session->addressEquals("$field_ui_prefix/display/full"); + $page->checkField('layout[enabled]'); + $page->pressButton('Save'); + $assert_session->linkExists('Manage layout'); + $page->clickLink('Manage layout'); + // Confirm the body field only is shown once. + $assert_session->elementsCount('css', '.field--name-body', 1); + } + /** * Tests that component's dependencies are respected during removal. */ @@ -249,6 +317,11 @@ public function testPluginDependencies() { $page->fillField('id', 'myothermenu'); $page->pressButton('Save'); + $page->clickLink('Add link'); + $page->fillField('title[0][value]', 'My link'); + $page->fillField('link[0][uri]', '/'); + $page->pressButton('Save'); + $this->drupalPostForm('admin/structure/types/manage/bundle_with_section_field/display', ['layout[enabled]' => TRUE], 'Save'); $assert_session->linkExists('Manage layout'); $this->clickLink('Manage layout'); @@ -335,6 +408,7 @@ public function testLayoutBuilderUiFullViewMode() { // Enable the full view mode and customize it. $this->drupalPostForm("$field_ui_prefix/display/default", ['display_modes_custom[full]' => TRUE], 'Save'); + $this->drupalPostForm("$field_ui_prefix/display/full", ['layout[enabled]' => TRUE], 'Save'); $this->drupalGet("$field_ui_prefix/display-layout/full"); $this->clickLink('Add Block'); $this->clickLink('Powered by Drupal'); @@ -446,13 +520,68 @@ public function testDeletedView() { } /** - * Asserts that a text string only appears once on the page. + * Tests the usage of placeholders for empty blocks. * - * @param string $needle - * The string to look for. + * @see \Drupal\Core\Block\BlockPluginInterface::getPlaceholderString() + * @see \Drupal\layout_builder\EventSubscriber\BlockComponentRenderArray::onBuildRender() + */ + public function testBlockPlaceholder() { + $assert_session = $this->assertSession(); + $page = $this->getSession()->getPage(); + + $this->drupalLogin($this->drupalCreateUser([ + 'configure any layout', + 'administer node display', + ])); + + $field_ui_prefix = 'admin/structure/types/manage/bundle_with_section_field'; + $this->drupalPostForm("$field_ui_prefix/display/default", ['layout[enabled]' => TRUE], 'Save'); + + // Customize the default view mode. + $this->drupalGet("$field_ui_prefix/display-layout/default"); + + // Add a block whose content is controlled by state and is empty by default. + $this->clickLink('Add Block'); + $this->clickLink('Test block caching'); + $page->fillField('settings[label]', 'The block label'); + $page->pressButton('Add Block'); + + $block_content = 'I am content'; + $placeholder_content = 'Placeholder for the "The block label" block'; + + // The block placeholder is displayed and there is no content. + $assert_session->pageTextContains($placeholder_content); + $assert_session->pageTextNotContains($block_content); + + // Set block content and reload the page. + \Drupal::state()->set('block_test.content', $block_content); + $this->getSession()->reload(); + + // The block placeholder is no longer displayed and the content is visible. + $assert_session->pageTextNotContains($placeholder_content); + $assert_session->pageTextContains($block_content); + } + + /** + * Tests the Block UI when Layout Builder is installed. */ - protected function assertTextAppearsOnce($needle) { - $this->assertEquals(1, substr_count($this->getSession()->getPage()->getContent(), $needle), "'$needle' only appears once on the page."); + public function testBlockUiListing() { + $assert_session = $this->assertSession(); + $page = $this->getSession()->getPage(); + + $this->drupalLogin($this->drupalCreateUser([ + 'administer blocks', + ])); + + $this->drupalGet('admin/structure/block'); + $page->clickLink('Place block'); + + // Ensure that blocks expected to appear are available. + $assert_session->pageTextContains('Test HTML block'); + $assert_session->pageTextContains('Block test'); + // Ensure that blocks not expected to appear are not available. + $assert_session->pageTextNotContains('Body'); + $assert_session->pageTextNotContains('Content fields'); } } diff --git a/web/core/modules/layout_builder/tests/src/Functional/LayoutDisplayTest.php b/web/core/modules/layout_builder/tests/src/Functional/LayoutDisplayTest.php new file mode 100644 index 0000000000000000000000000000000000000000..4b26c628bc93d11fdda74f83519ea39d5a987309 --- /dev/null +++ b/web/core/modules/layout_builder/tests/src/Functional/LayoutDisplayTest.php @@ -0,0 +1,94 @@ +<?php + +namespace Drupal\Tests\layout_builder\Functional; + +use Drupal\Tests\BrowserTestBase; + +/** + * Tests functionality of the entity view display with regard to Layout Builder. + * + * @group layout_builder + */ +class LayoutDisplayTest extends BrowserTestBase { + + /** + * {@inheritdoc} + */ + protected static $modules = ['field_ui', 'layout_builder', 'block', 'node']; + + /** + * {@inheritdoc} + */ + protected function setUp() { + parent::setUp(); + + // @todo The Layout Builder UI relies on local tasks; fix in + // https://www.drupal.org/project/drupal/issues/2917777. + $this->drupalPlaceBlock('local_tasks_block'); + + $this->createContentType([ + 'type' => 'bundle_with_section_field', + ]); + $this->createNode(['type' => 'bundle_with_section_field']); + + $this->drupalLogin($this->drupalCreateUser([ + 'configure any layout', + 'administer node display', + 'administer display modes', + ], 'foobar')); + } + + /** + * Tests the interaction between multiple view modes. + */ + public function testMultipleViewModes() { + $assert_session = $this->assertSession(); + $page = $this->getSession()->getPage(); + $field_ui_prefix = 'admin/structure/types/manage/bundle_with_section_field/display'; + + // Enable Layout Builder for the default view modes, and overrides. + $this->drupalGet("$field_ui_prefix/default"); + $page->checkField('layout[enabled]'); + $page->pressButton('Save'); + $page->checkField('layout[allow_custom]'); + $page->pressButton('Save'); + + $this->drupalGet('node/1'); + $assert_session->pageTextNotContains('Powered by Drupal'); + + $assert_session->linkExists('Layout'); + $this->clickLink('Layout'); + $assert_session->linkExists('Add Block'); + $this->clickLink('Add Block'); + $assert_session->linkExists('Powered by Drupal'); + $this->clickLink('Powered by Drupal'); + $page->pressButton('Add Block'); + $assert_session->linkExists('Save Layout'); + $this->clickLink('Save Layout'); + $assert_session->pageTextContains('Powered by Drupal'); + + // Add a new view mode. + $this->drupalGet('admin/structure/display-modes/view/add/node'); + $page->fillField('label', 'New'); + $page->fillField('id', 'new'); + $page->pressButton('Save'); + + // Enable the new view mode. + $this->drupalGet("$field_ui_prefix/default"); + $page->checkField('display_modes_custom[new]'); + $page->pressButton('Save'); + + // Enable and disable Layout Builder for the new view mode. + $this->drupalGet("$field_ui_prefix/new"); + $page->checkField('layout[enabled]'); + $page->pressButton('Save'); + $page->uncheckField('layout[enabled]'); + $page->pressButton('Save'); + $page->pressButton('Confirm'); + + // The node using the default view mode still contains its overrides. + $this->drupalGet('node/1'); + $assert_session->pageTextContains('Powered by Drupal'); + } + +} diff --git a/web/core/modules/layout_builder/tests/src/Functional/LayoutSectionTest.php b/web/core/modules/layout_builder/tests/src/Functional/LayoutSectionTest.php index e4af3290c468475cbfda28acfe6490fe5041c08e..e29609b30e712a11fc7ad7b37f626a3089d2c159 100644 --- a/web/core/modules/layout_builder/tests/src/Functional/LayoutSectionTest.php +++ b/web/core/modules/layout_builder/tests/src/Functional/LayoutSectionTest.php @@ -4,6 +4,7 @@ use Drupal\language\Entity\ConfigurableLanguage; use Drupal\layout_builder\Entity\LayoutBuilderEntityViewDisplay; +use Drupal\layout_builder\Plugin\SectionStorage\OverridesSectionStorage; use Drupal\layout_builder\Section; use Drupal\layout_builder\SectionComponent; use Drupal\Tests\BrowserTestBase; @@ -20,13 +21,6 @@ class LayoutSectionTest extends BrowserTestBase { */ public static $modules = ['field_ui', 'layout_builder', 'node', 'block_test']; - /** - * The name of the layout section field. - * - * @var string - */ - protected $fieldName = 'layout_builder__layout'; - /** * {@inheritdoc} */ @@ -226,7 +220,7 @@ public function testMultilingualLayoutSectionFormatter() { ]); $entity->addTranslation('es', [ 'title' => 'Translated node title', - $this->fieldName => [ + OverridesSectionStorage::FIELD_NAME => [ [ 'section' => new Section('layout_twocol', [], [ 'foo' => new SectionComponent('foo', 'first', [ @@ -373,7 +367,7 @@ protected function createSectionNode(array $section_values) { 'value' => 'The node body', ], ], - $this->fieldName => $section_values, + OverridesSectionStorage::FIELD_NAME => $section_values, ]); } diff --git a/web/core/modules/layout_builder/tests/src/FunctionalJavascript/FieldBlockTest.php b/web/core/modules/layout_builder/tests/src/FunctionalJavascript/FieldBlockTest.php index f2ecd52b3bf47bdc853fd32f67f4f0ee9fa57846..bd4d1843c76fdb33ffae13a236c2f0494f900fd0 100644 --- a/web/core/modules/layout_builder/tests/src/FunctionalJavascript/FieldBlockTest.php +++ b/web/core/modules/layout_builder/tests/src/FunctionalJavascript/FieldBlockTest.php @@ -16,7 +16,14 @@ class FieldBlockTest extends WebDriverTestBase { /** * {@inheritdoc} */ - public static $modules = ['block', 'datetime', 'layout_builder', 'user']; + protected static $modules = [ + 'block', + 'datetime', + 'layout_builder', + 'user', + // See \Drupal\layout_builder_fieldblock_test\Plugin\Block\FieldBlock. + 'layout_builder_fieldblock_test', + ]; /** * {@inheritdoc} @@ -67,7 +74,7 @@ public function testFieldBlock() { $assert_session->pageTextNotContains('Initial email'); $assert_session->pageTextContains('Date field'); - $block_url = 'admin/structure/block/add/field_block%3Auser%3Auser%3Afield_date/classy'; + $block_url = 'admin/structure/block/add/field_block_test%3Auser%3Auser%3Afield_date/classy'; $assert_session->linkByHrefExists($block_url); $this->drupalGet($block_url); diff --git a/web/core/modules/layout_builder/tests/src/FunctionalJavascript/InlineBlockPrivateFilesTest.php b/web/core/modules/layout_builder/tests/src/FunctionalJavascript/InlineBlockPrivateFilesTest.php index 05892bd314735b1436d54eddd43e660da70f630f..a94be8ba17db5229498125442c45e336c0fd91f8 100644 --- a/web/core/modules/layout_builder/tests/src/FunctionalJavascript/InlineBlockPrivateFilesTest.php +++ b/web/core/modules/layout_builder/tests/src/FunctionalJavascript/InlineBlockPrivateFilesTest.php @@ -192,8 +192,8 @@ protected function addInlineFileBlockToLayout($title, File $file) { $page = $this->getSession()->getPage(); $page->clickLink('Add Block'); $assert_session->assertWaitOnAjaxRequest(); - $this->assertNotEmpty($assert_session->waitForElementVisible('css', '.block-categories details:contains(Create new block)')); - $this->clickLink('Basic block'); + $this->assertNotEmpty($assert_session->waitForLink('Create custom block')); + $this->clickLink('Create custom block'); $assert_session->assertWaitOnAjaxRequest(); $assert_session->fieldValueEquals('Title', ''); $page->findField('Title')->setValue($title); diff --git a/web/core/modules/layout_builder/tests/src/FunctionalJavascript/InlineBlockTest.php b/web/core/modules/layout_builder/tests/src/FunctionalJavascript/InlineBlockTest.php index 9fdc8fdd3cca27a32e26fa6b7ac3dde17ed1fc4f..4f463192d150bde3a9b787b4ffcbddeba55e3509 100644 --- a/web/core/modules/layout_builder/tests/src/FunctionalJavascript/InlineBlockTest.php +++ b/web/core/modules/layout_builder/tests/src/FunctionalJavascript/InlineBlockTest.php @@ -428,4 +428,74 @@ public function testAccess() { $assert_session->pageTextNotContains('You are not authorized to access this page'); } + /** + * Tests the workflow for adding an inline block depending on number of types. + * + * @throws \Behat\Mink\Exception\ElementNotFoundException + * @throws \Behat\Mink\Exception\ExpectationException + */ + public function testAddWorkFlow() { + $assert_session = $this->assertSession(); + $page = $this->getSession()->getPage(); + $type_storage = $this->container->get('entity_type.manager')->getStorage('block_content_type'); + foreach ($type_storage->loadByProperties() as $type) { + $type->delete(); + } + + $this->drupalLogin($this->drupalCreateUser([ + 'access contextual links', + 'configure any layout', + 'administer node display', + 'administer node fields', + ])); + + // Enable layout builder and overrides. + $this->drupalPostForm( + static::FIELD_UI_PREFIX . '/display/default', + ['layout[enabled]' => TRUE, 'layout[allow_custom]' => TRUE], + 'Save' + ); + + $layout_default_path = 'admin/structure/types/manage/bundle_with_section_field/display-layout/default'; + $this->drupalGet($layout_default_path); + // Add a basic block with the body field set. + $page->clickLink('Add Block'); + $assert_session->assertWaitOnAjaxRequest(); + // Confirm that with no block content types the link does not appear. + $assert_session->linkNotExists('Create custom block'); + + $this->createBlockContentType('basic', 'Basic block'); + + $this->drupalGet($layout_default_path); + // Add a basic block with the body field set. + $page->clickLink('Add Block'); + $assert_session->assertWaitOnAjaxRequest(); + // Confirm with only 1 type the "Create custom block" link goes directly t + // block add form. + $assert_session->linkNotExists('Basic block'); + $this->clickLink('Create custom block'); + $assert_session->assertWaitOnAjaxRequest(); + $assert_session->fieldExists('Title'); + + $this->createBlockContentType('advanced', 'Advanced block'); + + $this->drupalGet($layout_default_path); + // Add a basic block with the body field set. + $page->clickLink('Add Block'); + // Confirm that, when more than 1 type exists, "Create custom block" shows a + // list of block types. + $assert_session->assertWaitOnAjaxRequest(); + $assert_session->linkNotExists('Basic block'); + $assert_session->linkNotExists('Advanced block'); + $this->clickLink('Create custom block'); + $assert_session->assertWaitOnAjaxRequest(); + $assert_session->fieldNotExists('Title'); + $assert_session->linkExists('Basic block'); + $assert_session->linkExists('Advanced block'); + + $this->clickLink('Advanced block'); + $assert_session->assertWaitOnAjaxRequest(); + $assert_session->fieldExists('Title'); + } + } diff --git a/web/core/modules/layout_builder/tests/src/FunctionalJavascript/InlineBlockTestBase.php b/web/core/modules/layout_builder/tests/src/FunctionalJavascript/InlineBlockTestBase.php index 6c99c6c39f107068d21fe5d46edf3d581d58e781..2b781766a03812ace2b4f649f2a9236788438734 100644 --- a/web/core/modules/layout_builder/tests/src/FunctionalJavascript/InlineBlockTestBase.php +++ b/web/core/modules/layout_builder/tests/src/FunctionalJavascript/InlineBlockTestBase.php @@ -71,13 +71,7 @@ protected function setUp() { ], ], ]); - $bundle = BlockContentType::create([ - 'id' => 'basic', - 'label' => 'Basic block', - 'revision' => 1, - ]); - $bundle->save(); - block_content_add_body_field($bundle->id()); + $this->createBlockContentType('basic', 'Basic block'); $this->blockStorage = $this->container->get('entity_type.manager')->getStorage('block_content'); } @@ -146,8 +140,8 @@ protected function addInlineBlockToLayout($title, $body) { $page = $this->getSession()->getPage(); $page->clickLink('Add Block'); $assert_session->assertWaitOnAjaxRequest(); - $this->assertNotEmpty($assert_session->waitForElementVisible('css', '.block-categories details:contains(Create new block)')); - $this->clickLink('Basic block'); + $this->assertNotEmpty($assert_session->waitForLink('Create custom block')); + $this->clickLink('Create custom block'); $assert_session->assertWaitOnAjaxRequest(); $textarea = $assert_session->waitForElement('css', '[name="settings[block_form][body][0][value]"]'); $this->assertNotEmpty($textarea); @@ -219,4 +213,22 @@ protected function assertDialogClosedAndTextVisible($text, $css_locator = NULL) } } + /** + * Creates a block content type. + * + * @param string $id + * The block type id. + * @param string $label + * The block type label. + */ + protected function createBlockContentType($id, $label) { + $bundle = BlockContentType::create([ + 'id' => $id, + 'label' => $label, + 'revision' => 1, + ]); + $bundle->save(); + block_content_add_body_field($bundle->id()); + } + } diff --git a/web/core/modules/layout_builder/tests/src/FunctionalJavascript/LayoutBuilderUiTest.php b/web/core/modules/layout_builder/tests/src/FunctionalJavascript/LayoutBuilderUiTest.php new file mode 100644 index 0000000000000000000000000000000000000000..c5510e9d5fc7e3eb92d121c35bee84dad8e83b3c --- /dev/null +++ b/web/core/modules/layout_builder/tests/src/FunctionalJavascript/LayoutBuilderUiTest.php @@ -0,0 +1,94 @@ +<?php + +namespace Drupal\Tests\layout_builder\FunctionalJavascript; + +use Drupal\FunctionalJavascriptTests\WebDriverTestBase; + +/** + * Tests the Layout Builder UI. + * + * @group layout_builder + */ +class LayoutBuilderUiTest extends WebDriverTestBase { + + /** + * Path prefix for the field UI for the test bundle. + * + * @var string + */ + const FIELD_UI_PREFIX = 'admin/structure/types/manage/bundle_with_section_field'; + + public static $modules = [ + 'layout_builder', + 'block', + 'node', + ]; + + /** + * {@inheritdoc} + */ + protected function setUp() { + parent::setUp(); + + // @todo The Layout Builder UI relies on local tasks; fix in + // https://www.drupal.org/project/drupal/issues/2917777. + $this->drupalPlaceBlock('local_tasks_block'); + + $this->createContentType(['type' => 'bundle_with_section_field']); + + $this->drupalLogin($this->drupalCreateUser([ + 'configure any layout', + 'administer node display', + 'administer node fields', + ])); + } + + /** + * Tests the message indicating unsaved changes. + */ + public function testUnsavedChangesMessage() { + $assert_session = $this->assertSession(); + $page = $this->getSession()->getPage(); + + // Enable layout builder. + $this->drupalPostForm( + static::FIELD_UI_PREFIX . '/display/default', + ['layout[enabled]' => TRUE], + 'Save' + ); + + // Make and then cancel changes. + $this->assertModifiedLayout(static::FIELD_UI_PREFIX . '/display-layout/default'); + $page->clickLink('Cancel Layout'); + $assert_session->pageTextNotContains('You have unsaved changes.'); + + // Make and then save changes. + $this->assertModifiedLayout(static::FIELD_UI_PREFIX . '/display-layout/default'); + $page->clickLink('Save Layout'); + $assert_session->pageTextNotContains('You have unsaved changes.'); + } + + /** + * Asserts that modifying a layout works as expected. + * + * @param string $path + * The path to a Layout Builder UI page. + */ + protected function assertModifiedLayout($path) { + $assert_session = $this->assertSession(); + $page = $this->getSession()->getPage(); + + $this->drupalGet($path); + $page->clickLink('Add Section'); + $assert_session->assertWaitOnAjaxRequest(); + $assert_session->pageTextNotContains('You have unsaved changes.'); + $page->clickLink('One column'); + $assert_session->assertWaitOnAjaxRequest(); + $assert_session->pageTextContainsOnce('You have unsaved changes.'); + + // Reload the page. + $this->drupalGet($path); + $assert_session->pageTextContainsOnce('You have unsaved changes.'); + } + +} diff --git a/web/core/modules/layout_builder/tests/src/Kernel/FieldBlockTest.php b/web/core/modules/layout_builder/tests/src/Kernel/FieldBlockTest.php index d5246a0c2cd0342e65a1211f6f067b45f091009f..aaeb4ca8115e28c4f64162c9c73a989ea0c6cd4d 100644 --- a/web/core/modules/layout_builder/tests/src/Kernel/FieldBlockTest.php +++ b/web/core/modules/layout_builder/tests/src/Kernel/FieldBlockTest.php @@ -230,11 +230,10 @@ protected function getTestBlock(ProphecyInterface $entity_prophecy, array $confi * @covers ::build * @dataProvider providerTestBuild */ - public function testBuild(PromiseInterface $promise, $in_preview, $expected_markup, $log_message = '', $log_arguments = []) { + public function testBuild(PromiseInterface $promise, $expected_markup, $log_message = '', $log_arguments = []) { $entity = $this->prophesize(FieldableEntityInterface::class); $field = $this->prophesize(FieldItemListInterface::class); $entity->get('the_field_name')->willReturn($field->reveal()); - $entity->in_preview = $in_preview; $field->view(Argument::type('array'))->will($promise); $field_definition = $this->prophesize(FieldDefinitionInterface::class); @@ -269,40 +268,20 @@ public function testBuild(PromiseInterface $promise, $in_preview, $expected_mark */ public function providerTestBuild() { $data = []; - $data['array, no preview'] = [ + $data['array'] = [ new ReturnPromise([['content' => ['#markup' => 'The field value']]]), - FALSE, - 'The field value', - ]; - $data['array, preview'] = [ - new ReturnPromise([['content' => ['#markup' => 'The field value']]]), - TRUE, 'The field value', ]; - $data['empty array, no preview'] = [ + $data['empty array'] = [ new ReturnPromise([[]]), - FALSE, '', ]; - $data['empty array, preview'] = [ - new ReturnPromise([[]]), - TRUE, - 'Placeholder for the "The Field Label" field', - ]; - $data['exception, no preview'] = [ + $data['exception'] = [ new ThrowPromise(new \Exception('The exception message')), - FALSE, '', 'The field "%field" failed to render with the error of "%error".', ['%field' => 'the_field_name', '%error' => 'The exception message'], ]; - $data['exception, preview'] = [ - new ThrowPromise(new \Exception('The exception message')), - TRUE, - 'Placeholder for the "The Field Label" field', - 'The field "%field" failed to render with the error of "%error".', - ['%field' => 'the_field_name', '%error' => 'The exception message'], - ]; return $data; } diff --git a/web/core/modules/layout_builder/tests/src/Kernel/LayoutBuilderFieldLayoutCompatibilityTest.php b/web/core/modules/layout_builder/tests/src/Kernel/LayoutBuilderFieldLayoutCompatibilityTest.php index 57dacb5b18ce030d343e93d1fa58fc289616c8ba..12fd813f4fbf2db3a0e45f26cfffd9256052b492 100644 --- a/web/core/modules/layout_builder/tests/src/Kernel/LayoutBuilderFieldLayoutCompatibilityTest.php +++ b/web/core/modules/layout_builder/tests/src/Kernel/LayoutBuilderFieldLayoutCompatibilityTest.php @@ -2,6 +2,7 @@ namespace Drupal\Tests\layout_builder\Kernel; +use Drupal\layout_builder\Plugin\SectionStorage\OverridesSectionStorage; use Drupal\layout_builder\Section; /** @@ -56,7 +57,7 @@ public function testCompatibility() { // Add a layout override. $this->enableOverrides(); /** @var \Drupal\layout_builder\SectionStorageInterface $field_list */ - $field_list = $this->entity->get('layout_builder__layout'); + $field_list = $this->entity->get(OverridesSectionStorage::FIELD_NAME); $field_list->appendSection(new Section('layout_onecol')); $this->entity->save(); diff --git a/web/core/modules/layout_builder/tests/src/Kernel/LayoutBuilderInstallTest.php b/web/core/modules/layout_builder/tests/src/Kernel/LayoutBuilderInstallTest.php index aa1b9942c8538e19589e1b25ecdb5ee102d45497..a3ae736da1c84e86b13fc0696eae7cb145d80624 100644 --- a/web/core/modules/layout_builder/tests/src/Kernel/LayoutBuilderInstallTest.php +++ b/web/core/modules/layout_builder/tests/src/Kernel/LayoutBuilderInstallTest.php @@ -4,6 +4,7 @@ use Drupal\field\Entity\FieldConfig; use Drupal\field\Entity\FieldStorageConfig; +use Drupal\layout_builder\Plugin\SectionStorage\OverridesSectionStorage; use Drupal\layout_builder\Section; /** @@ -35,7 +36,7 @@ public function testCompatibility() { // Add a layout override. $this->enableOverrides(); $this->entity = $this->reloadEntity($this->entity); - $this->entity->get('layout_builder__layout')->appendSection(new Section('layout_onecol')); + $this->entity->get(OverridesSectionStorage::FIELD_NAME)->appendSection(new Section('layout_onecol')); $this->entity->save(); // The rendered entity has now changed. The non-configurable field is shown @@ -50,7 +51,7 @@ public function testCompatibility() { $this->assertNotEmpty($this->cssSelect('.layout--onecol')); // Removing the layout restores the original rendering of the entity. - $this->entity->get('layout_builder__layout')->removeSection(0); + $this->entity->get(OverridesSectionStorage::FIELD_NAME)->removeSection(0); $this->entity->save(); $this->assertFieldAttributes($this->entity, $expected_fields); diff --git a/web/core/modules/layout_builder/tests/src/Kernel/LayoutSectionItemListTest.php b/web/core/modules/layout_builder/tests/src/Kernel/LayoutSectionItemListTest.php index 5bd354675cb843e7293054ad25134c53ca5325a3..4231530fd7acd6f7afdc90c87a3ac2b5103806b6 100644 --- a/web/core/modules/layout_builder/tests/src/Kernel/LayoutSectionItemListTest.php +++ b/web/core/modules/layout_builder/tests/src/Kernel/LayoutSectionItemListTest.php @@ -4,6 +4,7 @@ use Drupal\entity_test\Entity\EntityTestBaseFieldDisplay; use Drupal\layout_builder\Entity\LayoutBuilderEntityViewDisplay; +use Drupal\layout_builder\Plugin\SectionStorage\OverridesSectionStorage; /** * Tests the field type for Layout Sections. @@ -42,10 +43,10 @@ protected function getSectionStorage(array $section_data) { }, $section_data); $entity = EntityTestBaseFieldDisplay::create([ 'name' => 'The test entity', - 'layout_builder__layout' => $section_data, + OverridesSectionStorage::FIELD_NAME => $section_data, ]); $entity->save(); - return $entity->get('layout_builder__layout'); + return $entity->get(OverridesSectionStorage::FIELD_NAME); } } diff --git a/web/core/modules/layout_builder/tests/src/Kernel/SectionStorageTestBase.php b/web/core/modules/layout_builder/tests/src/Kernel/SectionStorageTestBase.php index 1879977633e3abc9b192d8fafc41c22f082c3311..6c54d6c9e4ff75fb48e628d533fa33d86e2e32a0 100644 --- a/web/core/modules/layout_builder/tests/src/Kernel/SectionStorageTestBase.php +++ b/web/core/modules/layout_builder/tests/src/Kernel/SectionStorageTestBase.php @@ -137,6 +137,17 @@ public function testRemoveSection() { $this->assertSections($expected); } + /** + * Tests __clone(). + */ + public function testClone() { + $this->assertSame([], $this->sectionStorage->getSection(0)->getLayoutSettings()); + + $new_section_storage = clone $this->sectionStorage; + $new_section_storage->getSection(0)->setLayoutSettings(['asdf' => 'qwer']); + $this->assertSame([], $this->sectionStorage->getSection(0)->getLayoutSettings()); + } + /** * Asserts that the field list has the expected sections. * diff --git a/web/core/modules/layout_builder/tests/src/Unit/BlockComponentRenderArrayTest.php b/web/core/modules/layout_builder/tests/src/Unit/BlockComponentRenderArrayTest.php index 30820846cd534be9bc1b622f4a6a6f78a60990aa..2ac7994d74cdbe7723125aaca4ef8d0a941f578f 100644 --- a/web/core/modules/layout_builder/tests/src/Unit/BlockComponentRenderArrayTest.php +++ b/web/core/modules/layout_builder/tests/src/Unit/BlockComponentRenderArrayTest.php @@ -11,6 +11,7 @@ use Drupal\Core\DependencyInjection\ContainerBuilder; use Drupal\Core\Entity\EntityInterface; use Drupal\Core\Plugin\Context\ContextHandlerInterface; +use Drupal\Core\Render\PreviewFallbackInterface; use Drupal\Core\Session\AccountInterface; use Drupal\layout_builder\Access\LayoutPreviewAccessAllowed; use Drupal\layout_builder\Event\SectionComponentBuildRenderArrayEvent; @@ -252,6 +253,98 @@ public function testOnBuildRenderInPreview($refinable_dependent_access) { $this->assertEquals($expected_cache, $result); } + /** + * @covers ::onBuildRender + */ + public function testOnBuildRenderInPreviewEmptyBuild() { + $block = $this->prophesize(BlockPluginInterface::class)->willImplement(PreviewFallbackInterface::class); + + $block->access($this->account->reveal(), TRUE)->shouldNotBeCalled(); + $block->getCacheContexts()->willReturn([]); + $block->getCacheTags()->willReturn(['test']); + $block->getCacheMaxAge()->willReturn(Cache::PERMANENT); + $block->getConfiguration()->willReturn([]); + $block->getPluginId()->willReturn('block_plugin_id'); + $block->getBaseId()->willReturn('block_plugin_id'); + $block->getDerivativeId()->willReturn(NULL); + $placeholder_string = 'The placeholder string'; + $block->getPreviewFallbackString()->willReturn($placeholder_string); + + $block_content = []; + $block->build()->willReturn($block_content); + $this->blockManager->createInstance('some_block_id', ['id' => 'some_block_id'])->willReturn($block->reveal()); + + $component = new SectionComponent('some-uuid', 'some-region', ['id' => 'some_block_id']); + $event = new SectionComponentBuildRenderArrayEvent($component, [], TRUE); + + $subscriber = new BlockComponentRenderArray($this->account->reveal()); + + $expected_build = [ + '#theme' => 'block', + '#weight' => 0, + '#configuration' => [], + '#plugin_id' => 'block_plugin_id', + '#base_plugin_id' => 'block_plugin_id', + '#derivative_plugin_id' => NULL, + 'content' => $block_content, + ]; + $expected_build['content']['#markup'] = $placeholder_string; + + $expected_cache = $expected_build + [ + '#cache' => [ + 'contexts' => [], + 'tags' => ['test'], + 'max-age' => 0, + ], + ]; + + $subscriber->onBuildRender($event); + $result = $event->getBuild(); + $this->assertEquals($expected_build, $result); + $event->getCacheableMetadata()->applyTo($result); + $this->assertEquals($expected_cache, $result); + } + + /** + * @covers ::onBuildRender + */ + public function testOnBuildRenderEmptyBuild() { + $block = $this->prophesize(BlockPluginInterface::class); + $access_result = AccessResult::allowed(); + $block->access($this->account->reveal(), TRUE)->willReturn($access_result)->shouldBeCalled(); + $block->getCacheContexts()->willReturn([]); + $block->getCacheTags()->willReturn(['test']); + $block->getCacheMaxAge()->willReturn(Cache::PERMANENT); + $block->getConfiguration()->willReturn([]); + $block->getPluginId()->willReturn('block_plugin_id'); + $block->getBaseId()->willReturn('block_plugin_id'); + $block->getDerivativeId()->willReturn(NULL); + + $block->build()->willReturn([]); + $this->blockManager->createInstance('some_block_id', ['id' => 'some_block_id'])->willReturn($block->reveal()); + + $component = new SectionComponent('some-uuid', 'some-region', ['id' => 'some_block_id']); + $event = new SectionComponentBuildRenderArrayEvent($component, [], FALSE); + + $subscriber = new BlockComponentRenderArray($this->account->reveal()); + + $expected_build = []; + + $expected_cache = $expected_build + [ + '#cache' => [ + 'contexts' => [], + 'tags' => ['test'], + 'max-age' => -1, + ], + ]; + + $subscriber->onBuildRender($event); + $result = $event->getBuild(); + $this->assertEquals($expected_build, $result); + $event->getCacheableMetadata()->applyTo($result); + $this->assertEquals($expected_cache, $result); + } + /** * @covers ::onBuildRender */ diff --git a/web/core/modules/layout_builder/tests/src/Unit/InlineBlockUsageTest.php b/web/core/modules/layout_builder/tests/src/Unit/InlineBlockUsageTest.php new file mode 100644 index 0000000000000000000000000000000000000000..49cba472ccafab578e4b7ced570f2d67fb54b91b --- /dev/null +++ b/web/core/modules/layout_builder/tests/src/Unit/InlineBlockUsageTest.php @@ -0,0 +1,28 @@ +<?php + +namespace Drupal\Tests\layout_builder\Unit; + +use Drupal\Core\Database\Connection; +use Drupal\layout_builder\InlineBlockUsage; +use Drupal\Tests\UnitTestCase; + +/** + * @coversDefaultClass \Drupal\layout_builder\InlineBlockUsage + * + * @group layout_builder + */ +class InlineBlockUsageTest extends UnitTestCase { + + /** + * Tests calling deleteUsage() with empty array. + * + * @covers ::deleteUsage + */ + public function testEmptyDeleteUsageCall() { + $connection = $this->prophesize(Connection::class); + $connection->delete('inline_block_usage')->shouldNotBeCalled(); + + (new InlineBlockUsage($connection->reveal()))->deleteUsage([]); + } + +} diff --git a/web/core/modules/layout_builder/tests/src/Unit/LayoutTempstoreRepositoryTest.php b/web/core/modules/layout_builder/tests/src/Unit/LayoutTempstoreRepositoryTest.php index 0c74d01763290cc9d33daeda8ea5b2f8d4fc2894..fb46e608ae33b165db7ae8ddaf56f0e86d55d7ad 100644 --- a/web/core/modules/layout_builder/tests/src/Unit/LayoutTempstoreRepositoryTest.php +++ b/web/core/modules/layout_builder/tests/src/Unit/LayoutTempstoreRepositoryTest.php @@ -16,6 +16,7 @@ class LayoutTempstoreRepositoryTest extends UnitTestCase { /** * @covers ::get + * @covers ::has */ public function testGetEmptyTempstore() { $section_storage = $this->prophesize(SectionStorageInterface::class); @@ -30,12 +31,15 @@ public function testGetEmptyTempstore() { $repository = new LayoutTempstoreRepository($tempstore_factory->reveal()); + $this->assertFalse($repository->has($section_storage->reveal())); + $result = $repository->get($section_storage->reveal()); $this->assertSame($section_storage->reveal(), $result); } /** * @covers ::get + * @covers ::has */ public function testGetLoadedTempstore() { $section_storage = $this->prophesize(SectionStorageInterface::class); @@ -50,6 +54,8 @@ public function testGetLoadedTempstore() { $repository = new LayoutTempstoreRepository($tempstore_factory->reveal()); + $this->assertTrue($repository->has($section_storage->reveal())); + $result = $repository->get($section_storage->reveal()); $this->assertSame($tempstore_section_storage->reveal(), $result); $this->assertNotSame($section_storage->reveal(), $result); diff --git a/web/core/modules/layout_builder/tests/src/Unit/OverridesSectionStorageTest.php b/web/core/modules/layout_builder/tests/src/Unit/OverridesSectionStorageTest.php index 110ec2021e657d067791dd0f439e57d9dec07361..3691fb6c711fa5c5d54df5817ce8d747d0196641 100644 --- a/web/core/modules/layout_builder/tests/src/Unit/OverridesSectionStorageTest.php +++ b/web/core/modules/layout_builder/tests/src/Unit/OverridesSectionStorageTest.php @@ -112,13 +112,13 @@ public function testGetSectionListFromId($success, $expected_entity_type_id, $id $entity_storage = $this->prophesize(EntityStorageInterface::class); $entity_without_layout = $this->prophesize(FieldableEntityInterface::class); - $entity_without_layout->hasField('layout_builder__layout')->willReturn(FALSE); - $entity_without_layout->get('layout_builder__layout')->shouldNotBeCalled(); + $entity_without_layout->hasField(OverridesSectionStorage::FIELD_NAME)->willReturn(FALSE); + $entity_without_layout->get(OverridesSectionStorage::FIELD_NAME)->shouldNotBeCalled(); $entity_storage->load('entity_without_layout')->willReturn($entity_without_layout->reveal()); $entity_with_layout = $this->prophesize(FieldableEntityInterface::class); - $entity_with_layout->hasField('layout_builder__layout')->willReturn(TRUE); - $entity_with_layout->get('layout_builder__layout')->willReturn('the_return_value'); + $entity_with_layout->hasField(OverridesSectionStorage::FIELD_NAME)->willReturn(TRUE); + $entity_with_layout->get(OverridesSectionStorage::FIELD_NAME)->willReturn('the_return_value'); $entity_storage->load('entity_with_layout')->willReturn($entity_with_layout->reveal()); $this->entityTypeManager->getStorage($expected_entity_type_id)->willReturn($entity_storage->reveal()); diff --git a/web/core/modules/layout_builder/tests/src/Unit/SectionRenderTest.php b/web/core/modules/layout_builder/tests/src/Unit/SectionRenderTest.php index 079a220a450e78ee968406e0f800ee6811dd4d17..ad94e14e1826724aeaec940538d03da9f93788e2 100644 --- a/web/core/modules/layout_builder/tests/src/Unit/SectionRenderTest.php +++ b/web/core/modules/layout_builder/tests/src/Unit/SectionRenderTest.php @@ -231,6 +231,7 @@ public function testToRenderArrayEmpty() { * @covers ::toRenderArray */ public function testContextAwareBlock() { + $block_content = ['#markup' => 'The block content.']; $render_array = [ '#theme' => 'block', '#weight' => 0, @@ -238,7 +239,7 @@ public function testContextAwareBlock() { '#plugin_id' => 'block_plugin_id', '#base_plugin_id' => 'block_plugin_id', '#derivative_plugin_id' => NULL, - 'content' => [], + 'content' => $block_content, '#cache' => [ 'contexts' => [], 'tags' => [], @@ -251,7 +252,7 @@ public function testContextAwareBlock() { $access_result = AccessResult::allowed(); $block->access($this->account->reveal(), TRUE)->willReturn($access_result); - $block->build()->willReturn([]); + $block->build()->willReturn($block_content); $block->getCacheContexts()->willReturn([]); $block->getCacheTags()->willReturn([]); $block->getCacheMaxAge()->willReturn(Cache::PERMANENT); diff --git a/web/core/modules/link/tests/src/Functional/LinkFieldUITest.php b/web/core/modules/link/tests/src/Functional/LinkFieldUITest.php index bd2433f903d1aa2a3936450d9ff0ca7c3220a351..5be9e21349af1c65c37172c6c03f5f42ec359e43 100644 --- a/web/core/modules/link/tests/src/Functional/LinkFieldUITest.php +++ b/web/core/modules/link/tests/src/Functional/LinkFieldUITest.php @@ -6,9 +6,9 @@ use Drupal\Core\Entity\Entity\EntityFormDisplay; use Drupal\field\Entity\FieldConfig; use Drupal\field\Entity\FieldStorageConfig; -use Drupal\field_ui\Tests\FieldUiTestTrait; use Drupal\link\LinkItemInterface; use Drupal\Tests\BrowserTestBase; +use Drupal\Tests\field_ui\Traits\FieldUiTestTrait; /** * Tests link field UI functionality. diff --git a/web/core/modules/link/src/Tests/Views/LinkViewsTokensTest.php b/web/core/modules/link/tests/src/Functional/Views/LinkViewsTokensTest.php similarity index 96% rename from web/core/modules/link/src/Tests/Views/LinkViewsTokensTest.php rename to web/core/modules/link/tests/src/Functional/Views/LinkViewsTokensTest.php index f3ff80a1bc0c410fe7ae84de8acbc2c04d3342f7..b1cce75d0e3abf190a64c6a5707f40667e2751e6 100644 --- a/web/core/modules/link/src/Tests/Views/LinkViewsTokensTest.php +++ b/web/core/modules/link/tests/src/Functional/Views/LinkViewsTokensTest.php @@ -1,10 +1,10 @@ <?php -namespace Drupal\link\Tests\Views; +namespace Drupal\Tests\link\Functional\Views; use Drupal\field\Entity\FieldConfig; use Drupal\field\Entity\FieldStorageConfig; -use Drupal\views\Tests\ViewTestBase; +use Drupal\Tests\views\Functional\ViewTestBase; use Drupal\views\Tests\ViewTestData; /** diff --git a/web/core/modules/locale/locale.libraries.yml b/web/core/modules/locale/locale.libraries.yml index 9711d01122b800b6aaeacaa9d34938ea11061efa..e01d0d6bddc1b6359ed3bdb2348576922717d09e 100644 --- a/web/core/modules/locale/locale.libraries.yml +++ b/web/core/modules/locale/locale.libraries.yml @@ -25,6 +25,6 @@ translations: # any time. js: # This file does not actually exist; it's a placeholder file that will be - # overriden by locale_js_alter(), to use the file that contains the actual + # overridden by locale_js_alter(), to use the file that contains the actual # translations, for the language used in the current request. locale.translation.js: {} diff --git a/web/core/modules/locale/src/PluralFormula.php b/web/core/modules/locale/src/PluralFormula.php index 638d60fac863a023212887ab94b7c3f9c69dfa01..8f1920e64930ac22939bc0d2f7501e7f1dd55a7f 100644 --- a/web/core/modules/locale/src/PluralFormula.php +++ b/web/core/modules/locale/src/PluralFormula.php @@ -36,7 +36,7 @@ class PluralFormula implements PluralFormulaInterface { * ], * ] * @endcode - * @var [] + * @var array */ protected $formulae; diff --git a/web/core/modules/media/src/Controller/OEmbedIframeController.php b/web/core/modules/media/src/Controller/OEmbedIframeController.php index 72f2831154b2a12c1dbb04519483300ca824eb3e..7a103d4c6f51337192729fc7266d5f0bff92f2db 100644 --- a/web/core/modules/media/src/Controller/OEmbedIframeController.php +++ b/web/core/modules/media/src/Controller/OEmbedIframeController.php @@ -6,7 +6,6 @@ use Drupal\Core\Cache\CacheableMetadata; use Drupal\Core\Cache\CacheableResponse; use Drupal\Core\DependencyInjection\ContainerInjectionInterface; -use Drupal\Core\Logger\LoggerChannelInterface; use Drupal\Core\Render\RenderContext; use Drupal\Core\Render\RendererInterface; use Drupal\Core\Url; @@ -15,6 +14,7 @@ use Drupal\media\OEmbed\ResourceException; use Drupal\media\OEmbed\ResourceFetcherInterface; use Drupal\media\OEmbed\UrlResolverInterface; +use Psr\Log\LoggerInterface; use Symfony\Component\DependencyInjection\ContainerInterface; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException; @@ -58,7 +58,7 @@ class OEmbedIframeController implements ContainerInjectionInterface { /** * The logger channel. * - * @var \Drupal\Core\Logger\LoggerChannelInterface + * @var \Psr\Log\LoggerInterface */ protected $logger; @@ -78,12 +78,12 @@ class OEmbedIframeController implements ContainerInjectionInterface { * The oEmbed URL resolver service. * @param \Drupal\Core\Render\RendererInterface $renderer * The renderer service. - * @param \Drupal\Core\Logger\LoggerChannelInterface $logger + * @param \Psr\Log\LoggerInterface $logger * The logger channel. * @param \Drupal\media\IFrameUrlHelper $iframe_url_helper * The iFrame URL helper service. */ - public function __construct(ResourceFetcherInterface $resource_fetcher, UrlResolverInterface $url_resolver, RendererInterface $renderer, LoggerChannelInterface $logger, IFrameUrlHelper $iframe_url_helper) { + public function __construct(ResourceFetcherInterface $resource_fetcher, UrlResolverInterface $url_resolver, RendererInterface $renderer, LoggerInterface $logger, IFrameUrlHelper $iframe_url_helper) { $this->resourceFetcher = $resource_fetcher; $this->urlResolver = $url_resolver; $this->renderer = $renderer; diff --git a/web/core/modules/media/src/Entity/Media.php b/web/core/modules/media/src/Entity/Media.php index 1bbaf0881d22d4dad8e8dfd54a86ca00b4e192a1..d68a0a451c35b35c6e83f49a79ba4ab639de33f1 100644 --- a/web/core/modules/media/src/Entity/Media.php +++ b/web/core/modules/media/src/Entity/Media.php @@ -91,15 +91,14 @@ class Media extends EditorialContentEntityBase implements MediaInterface { * {@inheritdoc} */ public function getName() { - $name = $this->get('name'); + $name = $this->getEntityKey('label'); - if ($name->isEmpty()) { + if (empty($name)) { $media_source = $this->getSource(); return $media_source->getMetadata($this, $media_source->getPluginDefinition()['default_name_metadata_attribute']); } - else { - return $name->value; - } + + return $name; } /** @@ -186,20 +185,11 @@ protected function updateThumbnail($from_queue = FALSE) { // Set the thumbnail alt. $media_source = $this->getSource(); $plugin_definition = $media_source->getPluginDefinition(); + + $this->thumbnail->alt = ''; if (!empty($plugin_definition['thumbnail_alt_metadata_attribute'])) { $this->thumbnail->alt = $media_source->getMetadata($this, $plugin_definition['thumbnail_alt_metadata_attribute']); } - else { - $this->thumbnail->alt = $this->t('Thumbnail', [], ['langcode' => $this->langcode->value]); - } - - // Set the thumbnail title. - if (!empty($plugin_definition['thumbnail_title_metadata_attribute'])) { - $this->thumbnail->title = $media_source->getMetadata($this, $plugin_definition['thumbnail_title_metadata_attribute']); - } - else { - $this->thumbnail->title = $this->label(); - } return $this; } diff --git a/web/core/modules/media/src/MediaTypeForm.php b/web/core/modules/media/src/MediaTypeForm.php index fb4915fa3d0c5a93162a7a60dd433841e5e82603..f2aea499c49bece28f3f3b74f915cf6db31fa60d 100644 --- a/web/core/modules/media/src/MediaTypeForm.php +++ b/web/core/modules/media/src/MediaTypeForm.php @@ -304,6 +304,17 @@ function ($item) { */ protected function actions(array $form, FormStateInterface $form_state) { $actions = parent::actions($form, $form_state); + + // If the media source has not been chosen yet, turn the submit button into + // a button. This rebuilds the form with the media source's configuration + // form visible, instead of saving the media type. This allows users to + // create a media type without JavaScript enabled. With JavaScript enabled, + // this rebuild occurs during an AJAX request. + // @see \Drupal\media\MediaTypeForm::ajaxHandlerData() + if (empty($this->getEntity()->get('source'))) { + $actions['submit']['#type'] = 'button'; + } + $actions['submit']['#value'] = $this->t('Save'); $actions['delete']['#value'] = $this->t('Delete'); $actions['delete']['#access'] = $this->entity->access('delete'); diff --git a/web/core/modules/media/src/OEmbed/ResourceFetcher.php b/web/core/modules/media/src/OEmbed/ResourceFetcher.php index 0c210878feaa823f24a1c90fc1cc9f266ffa05fc..e58e7e26adae0494d5925b09d20f83dee4c4d29d 100644 --- a/web/core/modules/media/src/OEmbed/ResourceFetcher.php +++ b/web/core/modules/media/src/OEmbed/ResourceFetcher.php @@ -7,7 +7,6 @@ use Drupal\Core\Cache\UseCacheBackendTrait; use GuzzleHttp\ClientInterface; use GuzzleHttp\Exception\RequestException; -use Symfony\Component\Serializer\Encoder\XmlEncoder; /** * Fetches and caches oEmbed resources. @@ -69,8 +68,7 @@ public function fetchResource($url) { $content = (string) $response->getBody(); if (strstr($format, 'text/xml') || strstr($format, 'application/xml')) { - $encoder = new XmlEncoder(); - $data = $encoder->decode($content, 'xml'); + $data = $this->parseResourceXml($content, $url); } elseif (strstr($format, 'text/javascript') || strstr($format, 'application/json')) { $data = Json::decode($content); @@ -194,4 +192,42 @@ protected function createResource(array $data, $url) { } } + /** + * Parses XML resource data. + * + * @param string $data + * The raw XML for the resource. + * @param string $url + * The resource URL. + * + * @return array + * The parsed resource data. + * + * @throws \Drupal\media\OEmbed\ResourceException + * If the resource data could not be parsed. + */ + protected function parseResourceXml($data, $url) { + // Enable userspace error handling. + $was_using_internal_errors = libxml_use_internal_errors(TRUE); + libxml_clear_errors(); + + $content = simplexml_load_string($data, 'SimpleXMLElement', LIBXML_NOCDATA); + // Restore the previous error handling behavior. + libxml_use_internal_errors($was_using_internal_errors); + + $error = libxml_get_last_error(); + if ($error) { + libxml_clear_errors(); + throw new ResourceException($error->message, $url); + } + elseif ($content === FALSE) { + throw new ResourceException('The fetched resource could not be parsed.', $url); + } + + // Convert XML to JSON so that the parsed resource has a consistent array + // structure, regardless of any XML attributes or quirks of the XML parser. + $data = Json::encode($content); + return Json::decode($data); + } + } diff --git a/web/core/modules/media/src/Plugin/EntityReferenceSelection/MediaSelection.php b/web/core/modules/media/src/Plugin/EntityReferenceSelection/MediaSelection.php new file mode 100644 index 0000000000000000000000000000000000000000..5bfe1ba611e914ca636e633d3c89423a992508dd --- /dev/null +++ b/web/core/modules/media/src/Plugin/EntityReferenceSelection/MediaSelection.php @@ -0,0 +1,62 @@ +<?php + +namespace Drupal\media\Plugin\EntityReferenceSelection; + +use Drupal\Core\Entity\Plugin\EntityReferenceSelection\DefaultSelection; + +/** + * Provides specific access control for the media entity type. + * + * @EntityReferenceSelection( + * id = "default:media", + * label = @Translation("Media selection"), + * entity_types = {"media"}, + * group = "default", + * weight = 1 + * ) + */ +class MediaSelection extends DefaultSelection { + + /** + * {@inheritdoc} + */ + protected function buildEntityQuery($match = NULL, $match_operator = 'CONTAINS') { + $query = parent::buildEntityQuery($match, $match_operator); + + // Ensure that users with insufficient permission cannot see unpublished + // entities. + if (!$this->currentUser->hasPermission('administer media')) { + $query->condition('status', 1); + } + return $query; + } + + /** + * {@inheritdoc} + */ + public function createNewEntity($entity_type_id, $bundle, $label, $uid) { + $media = parent::createNewEntity($entity_type_id, $bundle, $label, $uid); + + // In order to create a referenceable media, it needs to published. + /** @var \Drupal\media\MediaInterface $media */ + $media->setPublished(); + + return $media; + } + + /** + * {@inheritdoc} + */ + public function validateReferenceableNewEntities(array $entities) { + $entities = parent::validateReferenceableNewEntities($entities); + // Mirror the conditions checked in buildEntityQuery(). + if (!$this->currentUser->hasPermission('administer media')) { + $entities = array_filter($entities, function ($media) { + /** @var \Drupal\media\MediaInterface $media */ + return $media->isPublished(); + }); + } + return $entities; + } + +} diff --git a/web/core/modules/media/src/Plugin/Field/FieldFormatter/OEmbedFormatter.php b/web/core/modules/media/src/Plugin/Field/FieldFormatter/OEmbedFormatter.php index 01fc0d377818e5382d603cf3f94d8098c4bcf6cf..443df18098824ef50e99b07cf5a2a715b980b88a 100644 --- a/web/core/modules/media/src/Plugin/Field/FieldFormatter/OEmbedFormatter.php +++ b/web/core/modules/media/src/Plugin/Field/FieldFormatter/OEmbedFormatter.php @@ -64,7 +64,7 @@ class OEmbedFormatter extends FormatterBase implements ContainerFactoryPluginInt /** * The logger service. * - * @var \Drupal\Core\Logger\LoggerChannelInterface + * @var \Psr\Log\LoggerInterface */ protected $logger; diff --git a/web/core/modules/media/src/Plugin/media/Source/Image.php b/web/core/modules/media/src/Plugin/media/Source/Image.php index a83a5144d24b7416c27320330aac45730e25ceb4..34b565c05449af1df78e2b31e606816e6e32c43b 100644 --- a/web/core/modules/media/src/Plugin/media/Source/Image.php +++ b/web/core/modules/media/src/Plugin/media/Source/Image.php @@ -22,7 +22,8 @@ * label = @Translation("Image"), * description = @Translation("Use local images for reusable media."), * allowed_field_types = {"image"}, - * default_thumbnail_filename = "no-thumbnail.png" + * default_thumbnail_filename = "no-thumbnail.png", + * thumbnail_alt_metadata_attribute = "thumbnail_alt_value" * ) */ class Image extends File { @@ -138,6 +139,9 @@ public function getMetadata(MediaInterface $media, $name) { case 'thumbnail_uri': return $uri; + + case 'thumbnail_alt_value': + return $media->get($this->configuration['source_field'])->alt ?: parent::getMetadata($media, $name); } return parent::getMetadata($media, $name); diff --git a/web/core/modules/media/src/Plugin/media/Source/OEmbed.php b/web/core/modules/media/src/Plugin/media/Source/OEmbed.php index a376366ce1ab248424492e669e55e745efc2a18b..83ac5852444ef532f52c2a3330e99a9880ff92f7 100644 --- a/web/core/modules/media/src/Plugin/media/Source/OEmbed.php +++ b/web/core/modules/media/src/Plugin/media/Source/OEmbed.php @@ -10,7 +10,6 @@ use Drupal\Core\Entity\EntityTypeManagerInterface; use Drupal\Core\Field\FieldTypePluginManagerInterface; use Drupal\Core\Form\FormStateInterface; -use Drupal\Core\Logger\LoggerChannelInterface; use Drupal\Core\Messenger\MessengerInterface; use Drupal\Core\Url; use Drupal\media\IFrameUrlHelper; @@ -23,6 +22,7 @@ use Drupal\media\OEmbed\UrlResolverInterface; use GuzzleHttp\ClientInterface; use GuzzleHttp\Exception\RequestException; +use Psr\Log\LoggerInterface; use Symfony\Component\DependencyInjection\ContainerInterface; /** @@ -75,7 +75,7 @@ class OEmbed extends MediaSourceBase implements OEmbedInterface { /** * The logger channel for media. * - * @var \Drupal\Core\Logger\LoggerChannelInterface + * @var \Psr\Log\LoggerInterface */ protected $logger; @@ -131,7 +131,7 @@ class OEmbed extends MediaSourceBase implements OEmbedInterface { * The config factory service. * @param \Drupal\Core\Field\FieldTypePluginManagerInterface $field_type_manager * The field type plugin manager service. - * @param \Drupal\Core\Logger\LoggerChannelInterface $logger + * @param \Psr\Log\LoggerInterface $logger * The logger channel for media. * @param \Drupal\Core\Messenger\MessengerInterface $messenger * The messenger service. @@ -144,7 +144,7 @@ class OEmbed extends MediaSourceBase implements OEmbedInterface { * @param \Drupal\media\IFrameUrlHelper $iframe_url_helper * The iFrame URL helper service. */ - public function __construct(array $configuration, $plugin_id, $plugin_definition, EntityTypeManagerInterface $entity_type_manager, EntityFieldManagerInterface $entity_field_manager, ConfigFactoryInterface $config_factory, FieldTypePluginManagerInterface $field_type_manager, LoggerChannelInterface $logger, MessengerInterface $messenger, ClientInterface $http_client, ResourceFetcherInterface $resource_fetcher, UrlResolverInterface $url_resolver, IFrameUrlHelper $iframe_url_helper) { + public function __construct(array $configuration, $plugin_id, $plugin_definition, EntityTypeManagerInterface $entity_type_manager, EntityFieldManagerInterface $entity_field_manager, ConfigFactoryInterface $config_factory, FieldTypePluginManagerInterface $field_type_manager, LoggerInterface $logger, MessengerInterface $messenger, ClientInterface $http_client, ResourceFetcherInterface $resource_fetcher, UrlResolverInterface $url_resolver, IFrameUrlHelper $iframe_url_helper) { parent::__construct($configuration, $plugin_id, $plugin_definition, $entity_type_manager, $entity_field_manager, $field_type_manager, $config_factory); $this->logger = $logger; $this->messenger = $messenger; diff --git a/web/core/modules/media/tests/fixtures/oembed/video_collegehumor.xml b/web/core/modules/media/tests/fixtures/oembed/video_collegehumor.xml index 696b5bf84eeb271c05f766ac07863523a2b79ea9..9c0b08bfcc8e3de0e5731afe879bc00426a27a43 100644 --- a/web/core/modules/media/tests/fixtures/oembed/video_collegehumor.xml +++ b/web/core/modules/media/tests/fixtures/oembed/video_collegehumor.xml @@ -1,7 +1,7 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> <oembed> <type>video</type> - <version>1.0</version> + <version type="float">1.0</version> <title>Let's Not Get a Drink Sometime</title> <https/> <author_name>CollegeHumor</author_name> diff --git a/web/core/modules/media/tests/src/Functional/MediaTranslationUITest.php b/web/core/modules/media/tests/src/Functional/MediaTranslationUITest.php new file mode 100644 index 0000000000000000000000000000000000000000..78a4e176953a32e30ee50b1772e03befc3c404ac --- /dev/null +++ b/web/core/modules/media/tests/src/Functional/MediaTranslationUITest.php @@ -0,0 +1,96 @@ +<?php + +namespace Drupal\Tests\media\Functional; + +use Drupal\Tests\content_translation\Functional\ContentTranslationUITestBase; +use Drupal\Tests\media\Traits\MediaTypeCreationTrait; + +/** + * Tests the Media Translation UI. + * + * @group media + */ +class MediaTranslationUITest extends ContentTranslationUITestBase { + + use MediaTypeCreationTrait; + + /** + * {inheritdoc} + */ + protected $defaultCacheContexts = [ + 'languages:language_interface', + 'theme', + 'timezone', + 'url.query_args:_wrapper_format', + 'user.permissions', + ]; + + /** + * {inheritdoc} + */ + public static $modules = [ + 'language', + 'content_translation', + 'media', + 'media_test_source', + ]; + + /** + * {@inheritdoc} + */ + protected function setUp() { + $this->entityTypeId = 'media'; + $this->bundle = 'test'; + parent::setUp(); + } + + /** + * {@inheritdoc} + */ + public function setupBundle() { + $this->createMediaType('test', [ + 'id' => $this->bundle, + 'queue_thumbnail_downloads' => FALSE, + ]); + } + + /** + * {@inheritdoc} + */ + protected function getTranslatorPermissions() { + return array_merge(parent::getTranslatorPermissions(), [ + 'administer media', + 'edit any test media', + ]); + } + + /** + * {@inheritdoc} + */ + protected function getEditorPermissions() { + return ['administer media', 'create test media']; + } + + /** + * {@inheritdoc} + */ + protected function getAdministratorPermissions() { + return array_merge(parent::getAdministratorPermissions(), [ + 'access administration pages', + 'administer media types', + 'access media overview', + 'administer languages', + ]); + } + + /** + * {@inheritdoc} + */ + protected function getNewEntityValues($langcode) { + return [ + 'name' => [['value' => $this->randomMachineName()]], + 'field_media_test' => [['value' => $this->randomMachineName()]], + ] + parent::getNewEntityValues($langcode); + } + +} diff --git a/web/core/modules/media/tests/src/Functional/MediaTypeCreationTest.php b/web/core/modules/media/tests/src/Functional/MediaTypeCreationTest.php new file mode 100644 index 0000000000000000000000000000000000000000..7de1cd8276d9e3e9bd40fdfc2e9b161a372e8b9c --- /dev/null +++ b/web/core/modules/media/tests/src/Functional/MediaTypeCreationTest.php @@ -0,0 +1,42 @@ +<?php + +namespace Drupal\Tests\media\Functional; + +use Drupal\media\Entity\MediaType; + +/** + * Ensures that media UI works correctly without JavaScript. + * + * @group media + */ +class MediaTypeCreationTest extends MediaFunctionalTestBase { + + /** + * {@inheritdoc} + */ + public static $modules = [ + 'media_test_source', + ]; + + /** + * Tests the media type creation form with only the mandatory options. + */ + public function testMediaTypeCreationForm() { + $machine_name = mb_strtolower($this->randomMachineName()); + + $this->drupalGet('/admin/structure/media/add'); + $this->assertSession()->statusCodeEquals(200); + $this->assertSession()->fieldExists('label')->setValue($this->randomString()); + $this->assertSession()->fieldExists('id')->setValue($machine_name); + $this->assertSession()->selectExists('source')->selectOption('test'); + $this->assertSession()->buttonExists('Save')->press(); + $this->assertSession()->statusCodeEquals(200); + $this->assertSession()->fieldValueEquals('Test config value', 'This is default value.'); + $this->assertSession()->buttonExists('Save')->press(); + $this->assertSession()->statusCodeEquals(200); + $this->assertSession()->addressEquals('admin/structure/media'); + + $this->assertInstanceOf(MediaType::class, MediaType::load($machine_name)); + } + +} diff --git a/web/core/modules/media/tests/src/Functional/MediaUiFunctionalTest.php b/web/core/modules/media/tests/src/Functional/MediaUiFunctionalTest.php index fe39fd828ebfe6d17d90c1a3b40d3a6ae0d6cedd..de25f3d12bf7565783fc250b370f74edaa6e11e4 100644 --- a/web/core/modules/media/tests/src/Functional/MediaUiFunctionalTest.php +++ b/web/core/modules/media/tests/src/Functional/MediaUiFunctionalTest.php @@ -248,7 +248,7 @@ public function providerTestMediaReferenceWidget() { // Unlimited value field. 'unlimited_value:single_type:create_list' => [FieldStorageDefinitionInterface::CARDINALITY_UNLIMITED, [TRUE], TRUE], // Unlimited value field with the tags widget. - 'unlimited_value:single_type:create_list' => [FieldStorageDefinitionInterface::CARDINALITY_UNLIMITED, [TRUE], TRUE, 'entity_reference_autocomplete_tags'], + 'unlimited_value:single_type:create_list:tags' => [FieldStorageDefinitionInterface::CARDINALITY_UNLIMITED, [TRUE], TRUE, 'entity_reference_autocomplete_tags'], ]; } diff --git a/web/core/modules/media/tests/src/Functional/Rest/MediaResourceTestBase.php b/web/core/modules/media/tests/src/Functional/Rest/MediaResourceTestBase.php index 85e4e5d7314470375e77a91e67d34281be9ff7b3..de352e001ac2019d94b777f8666e7978e27ad49e 100644 --- a/web/core/modules/media/tests/src/Functional/Rest/MediaResourceTestBase.php +++ b/web/core/modules/media/tests/src/Functional/Rest/MediaResourceTestBase.php @@ -167,13 +167,13 @@ protected function getExpectedNormalizedEntity() { ], 'thumbnail' => [ [ - 'alt' => 'Thumbnail', + 'alt' => '', 'width' => 180, 'height' => 180, 'target_id' => (int) $thumbnail->id(), 'target_type' => 'file', 'target_uuid' => $thumbnail->uuid(), - 'title' => 'Llama', + 'title' => NULL, 'url' => $thumbnail->url(), ], ], diff --git a/web/core/modules/media/tests/src/FunctionalJavascript/MediaDisplayTest.php b/web/core/modules/media/tests/src/FunctionalJavascript/MediaDisplayTest.php index 19ebf9dc2cdc2010669fe4cdcfe0ad21d2617f42..8a55c5045872632a68a5d6acd824d17b9e74731e 100644 --- a/web/core/modules/media/tests/src/FunctionalJavascript/MediaDisplayTest.php +++ b/web/core/modules/media/tests/src/FunctionalJavascript/MediaDisplayTest.php @@ -125,7 +125,7 @@ public function testMediaDisplay() { ]); $node_type->save(); - // Reference the created media using an entity_refernce field and make sure + // Reference the created media using an entity_reference field and make sure // the output is what we expect. $storage = FieldStorageConfig::create([ 'entity_type' => 'node', diff --git a/web/core/modules/media/tests/src/FunctionalJavascript/MediaSourceImageTest.php b/web/core/modules/media/tests/src/FunctionalJavascript/MediaSourceImageTest.php index faf58c1a39b6d6753b61bc1ce16ee0d7c309bc26..cb013805ad278c528bbaa01385f806ff9fccc4e1 100644 --- a/web/core/modules/media/tests/src/FunctionalJavascript/MediaSourceImageTest.php +++ b/web/core/modules/media/tests/src/FunctionalJavascript/MediaSourceImageTest.php @@ -59,6 +59,8 @@ public function testMediaImageSource() { // Make sure the thumbnail is displayed from uploaded image. $assert_session->elementAttributeContains('css', '.image-style-thumbnail', 'src', 'example_1.jpeg'); + // Ensure the thumbnail has the correct alt attribute. + $assert_session->elementAttributeContains('css', '.image-style-thumbnail', 'alt', 'Image Alt Text 1'); // Load the media and check that all fields are properly populated. $media = Media::load(1); diff --git a/web/core/modules/media/tests/src/Kernel/MediaSourceTest.php b/web/core/modules/media/tests/src/Kernel/MediaSourceTest.php index 79cb7b41462f262c6f9ba295db946f7e9841a81b..ecf17785047e07786aa270aa5c031b2f6b68bc92 100644 --- a/web/core/modules/media/tests/src/Kernel/MediaSourceTest.php +++ b/web/core/modules/media/tests/src/Kernel/MediaSourceTest.php @@ -40,7 +40,6 @@ public function testSave() { 'value' => 'Snowball', ], 'thumbnail_uri' => [ - 'title' => 'Thumbnail', 'value' => 'public://TheSisko.png', ], ]); @@ -230,7 +229,7 @@ public function testThumbnail() { // Save a media item and make sure thumbnail was added. \Drupal::state()->set('media_source_test_attributes', [ - 'thumbnail_uri' => ['title' => 'Thumbnail', 'value' => 'public://thumbnail1.jpg'], + 'thumbnail_uri' => ['value' => 'public://thumbnail1.jpg'], ]); /** @var \Drupal\media\MediaInterface $media */ $media = Media::create([ @@ -242,45 +241,46 @@ public function testThumbnail() { $this->assertSame('public://thumbnail1.jpg', $media_source->getMetadata($media, 'thumbnail_uri'), 'Value of the thumbnail metadata attribute is not correct.'); $media->save(); $this->assertSame('public://thumbnail1.jpg', $media->thumbnail->entity->getFileUri(), 'Thumbnail was not added to the media item.'); - $this->assertSame('Mr. Jones', $media->thumbnail->title, 'Title text was not set on the thumbnail.'); - $this->assertEquals('Thumbnail', $media->thumbnail->alt, 'Alt text was not set on the thumbnail.'); + // We expect the title not to be present on the Thumbnail. + $this->assertEmpty($media->thumbnail->title); + $this->assertSame('', $media->thumbnail->alt); // Now change the metadata attribute and make sure that the thumbnail stays // the same. \Drupal::state()->set('media_source_test_attributes', [ - 'thumbnail_uri' => ['title' => 'Thumbnail', 'value' => 'public://thumbnail2.jpg'], + 'thumbnail_uri' => ['value' => 'public://thumbnail2.jpg'], ]); $this->assertSame('public://thumbnail2.jpg', $media_source->getMetadata($media, 'thumbnail_uri'), 'Value of the thumbnail metadata attribute is not correct.'); $media->save(); $this->assertSame('public://thumbnail1.jpg', $media->thumbnail->entity->getFileUri(), 'Thumbnail was not preserved.'); - $this->assertSame('Mr. Jones', $media->thumbnail->title, 'Title text was not set on the thumbnail.'); - $this->assertEquals('Thumbnail', $media->thumbnail->alt, 'Alt text was not set on the thumbnail.'); + $this->assertEmpty($media->thumbnail->title); + $this->assertSame('', $media->thumbnail->alt); // Remove the thumbnail and make sure that it is auto-updated on save. $media->thumbnail->target_id = NULL; $this->assertSame('public://thumbnail2.jpg', $media_source->getMetadata($media, 'thumbnail_uri'), 'Value of the thumbnail metadata attribute is not correct.'); $media->save(); $this->assertSame('public://thumbnail2.jpg', $media->thumbnail->entity->getFileUri(), 'New thumbnail was not added to the media item.'); - $this->assertSame('Mr. Jones', $media->thumbnail->title, 'Title text was not set on the thumbnail.'); - $this->assertEquals('Thumbnail', $media->thumbnail->alt, 'Alt text was not set on the thumbnail.'); + $this->assertEmpty($media->thumbnail->title); + $this->assertSame('', $media->thumbnail->alt); // Change the metadata attribute again, change the source field value too // and make sure that the thumbnail updates. \Drupal::state()->set('media_source_test_attributes', [ - 'thumbnail_uri' => ['title' => 'Thumbnail', 'value' => 'public://thumbnail1.jpg'], + 'thumbnail_uri' => ['value' => 'public://thumbnail1.jpg'], ]); $media->field_media_test->value = 'some_new_value'; $this->assertSame('public://thumbnail1.jpg', $media_source->getMetadata($media, 'thumbnail_uri'), 'Value of the thumbnail metadata attribute is not correct.'); $media->save(); $this->assertSame('public://thumbnail1.jpg', $media->thumbnail->entity->getFileUri(), 'New thumbnail was not added to the media item.'); - $this->assertSame('Mr. Jones', $media->thumbnail->title, 'Title text was not set on the thumbnail.'); - $this->assertEquals('Thumbnail', $media->thumbnail->alt, 'Alt text was not set on the thumbnail.'); + $this->assertEmpty($media->thumbnail->title); + $this->assertSame('', $media->thumbnail->alt); // Change the thumbnail metadata attribute and make sure that the thumbnail // is set correctly. \Drupal::state()->set('media_source_test_attributes', [ - 'thumbnail_uri' => ['title' => 'Should not be used', 'value' => 'public://thumbnail1.jpg'], - 'alternative_thumbnail_uri' => ['title' => 'Should be used', 'value' => 'public://thumbnail2.jpg'], + 'thumbnail_uri' => ['value' => 'public://thumbnail1.jpg'], + 'alternative_thumbnail_uri' => ['value' => 'public://thumbnail2.jpg'], ]); \Drupal::state()->set('media_source_test_definition', ['thumbnail_uri_metadata_attribute' => 'alternative_thumbnail_uri']); $media = Media::create([ @@ -293,14 +293,14 @@ public function testThumbnail() { $this->assertSame('public://thumbnail2.jpg', $media_source->getMetadata($media, 'alternative_thumbnail_uri'), 'Value of the thumbnail metadata attribute is not correct.'); $media->save(); $this->assertSame('public://thumbnail2.jpg', $media->thumbnail->entity->getFileUri(), 'Correct metadata attribute was not used for the thumbnail.'); - $this->assertSame('Mr. Jones', $media->thumbnail->title, 'Title text was not set on the thumbnail.'); - $this->assertEquals('Thumbnail', $media->thumbnail->alt, 'Alt text was not set on the thumbnail.'); + $this->assertEmpty($media->thumbnail->title); + $this->assertSame('', $media->thumbnail->alt); // Enable queued thumbnails and make sure that the entity gets the default // thumbnail initially. \Drupal::state()->set('media_source_test_definition', []); \Drupal::state()->set('media_source_test_attributes', [ - 'thumbnail_uri' => ['title' => 'Should not be used', 'value' => 'public://thumbnail1.jpg'], + 'thumbnail_uri' => ['value' => 'public://thumbnail1.jpg'], ]); $this->testMediaType->setQueueThumbnailDownloadsStatus(TRUE)->save(); $media = Media::create([ @@ -311,8 +311,8 @@ public function testThumbnail() { $this->assertSame('public://thumbnail1.jpg', $media->getSource()->getMetadata($media, 'thumbnail_uri'), 'Value of the metadata attribute is not correct.'); $media->save(); $this->assertSame('public://media-icons/generic/generic.png', $media->thumbnail->entity->getFileUri(), 'Default thumbnail was not set initially.'); - $this->assertSame('Mr. Jones', $media->thumbnail->title, 'Title text was not set on the thumbnail.'); - $this->assertEquals('Thumbnail', $media->thumbnail->alt, 'Alt text was not set on the thumbnail.'); + $this->assertEmpty($media->thumbnail->title); + $this->assertSame('', $media->thumbnail->alt); // Process the queue item and make sure that the thumbnail was updated too. $queue_name = 'media_entity_thumbnail'; @@ -330,18 +330,15 @@ public function testThumbnail() { $media = Media::load($media->id()); $this->assertSame('public://thumbnail1.jpg', $media->thumbnail->entity->getFileUri(), 'Thumbnail was not updated by the queue.'); - $this->assertSame('Mr. Jones', $media->thumbnail->title, 'Title text was not set on the thumbnail.'); - $this->assertSame('Thumbnail', $media->thumbnail->alt, 'Alt text was not set on the thumbnail.'); + $this->assertEmpty($media->thumbnail->title); + $this->assertSame('', $media->thumbnail->alt); - // Set alt and title metadata attributes and make sure they are used for the - // thumbnail. + // Set the alt metadata attribute and make sure it's used for the thumbnail. \Drupal::state()->set('media_source_test_definition', [ 'thumbnail_alt_metadata_attribute' => 'alt', - 'thumbnail_title_metadata_attribute' => 'title', ]); \Drupal::state()->set('media_source_test_attributes', [ - 'alt' => ['title' => 'Alt text', 'value' => 'This will be alt.'], - 'title' => ['title' => 'Title text', 'value' => 'This will be title.'], + 'alt' => ['value' => 'This will be alt.'], ]); $media = Media::create([ 'bundle' => $this->testMediaType->id(), @@ -350,8 +347,8 @@ public function testThumbnail() { ]); $media->save(); $this->assertSame('Boxer', $media->getName(), 'Correct name was not set on the media item.'); - $this->assertSame('This will be title.', $media->thumbnail->title, 'Title text was not set on the thumbnail.'); - $this->assertSame('This will be alt.', $media->thumbnail->alt, 'Alt text was not set on the thumbnail.'); + $this->assertEmpty($media->thumbnail->title); + $this->assertSame('This will be alt.', $media->thumbnail->alt); } /** diff --git a/web/core/modules/menu_link_content/src/Plugin/Menu/MenuLinkContent.php b/web/core/modules/menu_link_content/src/Plugin/Menu/MenuLinkContent.php index 98e8cdfcb03c6591fb8bccad6d812e63f3fca294..1888eb12110c01226e49e3af1d2c92379ef151b5 100644 --- a/web/core/modules/menu_link_content/src/Plugin/Menu/MenuLinkContent.php +++ b/web/core/modules/menu_link_content/src/Plugin/Menu/MenuLinkContent.php @@ -198,7 +198,7 @@ public function getTranslateRoute() { * The menu link ID. */ protected function getUuid() { - $this->getDerivativeId(); + return $this->getDerivativeId(); } /** diff --git a/web/core/modules/menu_link_content/src/Plugin/migrate/source/d6/MenuLinkTranslation.php b/web/core/modules/menu_link_content/src/Plugin/migrate/source/d6/MenuLinkTranslation.php index 50b4d144221a9a49fd4b35a022d29c205ebd3f66..983c3159914a6126ec821be8760507e417e32713 100644 --- a/web/core/modules/menu_link_content/src/Plugin/migrate/source/d6/MenuLinkTranslation.php +++ b/web/core/modules/menu_link_content/src/Plugin/migrate/source/d6/MenuLinkTranslation.php @@ -2,6 +2,7 @@ namespace Drupal\menu_link_content\Plugin\migrate\source\d6; +use Drupal\content_translation\Plugin\migrate\source\I18nQueryTrait; use Drupal\migrate\Row; use Drupal\menu_link_content\Plugin\migrate\source\MenuLink; @@ -15,6 +16,13 @@ */ class MenuLinkTranslation extends MenuLink { + use I18nQueryTrait; + + /** + * Drupal 6 table names. + */ + const I18N_STRING_TABLE = 'i18n_strings'; + /** * {@inheritdoc} */ @@ -32,7 +40,7 @@ public function query() { // Add in the property, which is either title or description. Cast the mlid // to text so PostgreSQL can make the join. - $query->leftJoin('i18n_strings', 'i18n', 'CAST(ml.mlid as CHAR(255)) = i18n.objectid'); + $query->leftJoin(static::I18N_STRING_TABLE, 'i18n', 'CAST(ml.mlid as CHAR(255)) = i18n.objectid'); $query->isNotNull('i18n.lid'); $query->addField('i18n', 'lid'); $query->addField('i18n', 'property'); @@ -48,31 +56,17 @@ public function query() { * {@inheritdoc} */ public function prepareRow(Row $row) { - $language = $row->getSourceProperty('language'); - $mlid = $row->getSourceProperty('mlid'); - - // If this row has been migrated it is a duplicate then skip it. - if ($this->idMap->lookupDestinationIds(['mlid' => $mlid, 'language' => $language])) { - return FALSE; - } + parent::prepareRow($row); // Save the translation for this property. - $property = $row->getSourceProperty('property'); - $row->setSourceProperty($property . '_translated', $row->getSourceProperty('translation')); + $property_in_row = $row->getSourceProperty('property'); - // Get the translation, if one exists, for the property not already in the - // row. - $other_property = ($property == 'title') ? 'description' : 'title'; - $query = $this->select('i18n_strings', 'i18n') - ->fields('i18n', ['lid']) - ->condition('i18n.property', $other_property) - ->condition('i18n.objectid', $mlid); - $query->leftJoin('locales_target', 'lt', 'i18n.lid = lt.lid'); - $query->condition('lt.language', $language); - $query->addField('lt', 'translation'); - $results = $query->execute()->fetchAssoc(); - $row->setSourceProperty($other_property . '_translated', $results['translation']); - parent::prepareRow($row); + // Set the i18n string table for use in I18nQueryTrait. + $this->i18nStringTable = static::I18N_STRING_TABLE; + // 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') ? 'description' : 'title'; + return $this->getPropertyNotInRowTranslation($row, $property_not_in_row, 'mlid', $this->idMap); } /** diff --git a/web/core/modules/menu_link_content/tests/src/Unit/MenuLinkPluginTest.php b/web/core/modules/menu_link_content/tests/src/Unit/MenuLinkPluginTest.php new file mode 100644 index 0000000000000000000000000000000000000000..a6af5800c6b697be0c7ee16a7d02dc89a92a2c2b --- /dev/null +++ b/web/core/modules/menu_link_content/tests/src/Unit/MenuLinkPluginTest.php @@ -0,0 +1,31 @@ +<?php + +namespace Drupal\Tests\menu_link_content\Unit; + +use Drupal\menu_link_content\Plugin\Menu\MenuLinkContent; +use Drupal\Tests\UnitTestCase; + +/** + * @coversDefaultClass \Drupal\menu_link_content\Plugin\Menu\MenuLinkContent + * + * @group Menu + */ +class MenuLinkPluginTest extends UnitTestCase { + + /** + * @covers ::getUuid + */ + public function testGetInstanceReflection() { + /** @var \Drupal\menu_link_content\Plugin\Menu\MenuLinkContent $menu_link_content_plugin */ + $menu_link_content_plugin = $this->prophesize(MenuLinkContent::class); + $menu_link_content_plugin->getDerivativeId()->willReturn('test_id'); + $menu_link_content_plugin = $menu_link_content_plugin->reveal(); + + $class = new \ReflectionClass(MenuLinkContent::class); + $instance_method = $class->getMethod('getUuid'); + $instance_method->setAccessible(TRUE); + + $this->assertEquals('test_id', $instance_method->invoke($menu_link_content_plugin)); + } + +} diff --git a/web/core/modules/menu_ui/menu_ui.module b/web/core/modules/menu_ui/menu_ui.module index b9adbdd8eaa348de396b1ec9c1b6693daff2f289..7e37cafbdf3c946257716eb4c6a71d9befcac098 100644 --- a/web/core/modules/menu_ui/menu_ui.module +++ b/web/core/modules/menu_ui/menu_ui.module @@ -221,11 +221,15 @@ function menu_ui_form_node_form_alter(&$form, FormStateInterface $form_state) { $node_type = $node->type->entity; /** @var \Drupal\Core\Menu\MenuParentFormSelectorInterface $menu_parent_selector */ $menu_parent_selector = \Drupal::service('menu.parent_form_selector'); - $menu_names = menu_ui_get_menus(); - $type_menus = $node_type->getThirdPartySetting('menu_ui', 'available_menus', ['main']); + $type_menus_ids = $node_type->getThirdPartySetting('menu_ui', 'available_menus', ['main']); + if (empty($type_menus_ids)) { + return; + } + /** @var \Drupal\system\MenuInterface[] $type_menus */ + $type_menus = Menu::loadMultiple($type_menus_ids); $available_menus = []; foreach ($type_menus as $menu) { - $available_menus[$menu] = $menu_names[$menu]; + $available_menus[$menu->id()] = $menu->label(); } if ($defaults['id']) { $default = $defaults['menu_name'] . ':' . $defaults['parent']; diff --git a/web/core/modules/migrate/src/Plugin/Migration.php b/web/core/modules/migrate/src/Plugin/Migration.php index ee499b097d5c9f48b21ecbfa1ef259c61e4c8c33..20b8ae877b9033cd8f6d314b20d467b9dc05b959 100644 --- a/web/core/modules/migrate/src/Plugin/Migration.php +++ b/web/core/modules/migrate/src/Plugin/Migration.php @@ -216,7 +216,7 @@ class Migration extends PluginBase implements MigrationInterface, RequirementsIn protected $sourcePluginManager; /** - * Thep process plugin manager. + * The process plugin manager. * * @var \Drupal\migrate\Plugin\MigratePluginManager */ diff --git a/web/core/modules/migrate/src/Plugin/MigrationPluginManager.php b/web/core/modules/migrate/src/Plugin/MigrationPluginManager.php index dde8a9f0a0b18fb6adf4adc7d5e45e0aa6b4b094..6d364e77fc565600dc6ed4a6d864cae19206efa8 100644 --- a/web/core/modules/migrate/src/Plugin/MigrationPluginManager.php +++ b/web/core/modules/migrate/src/Plugin/MigrationPluginManager.php @@ -208,7 +208,14 @@ public function buildDependencyMigration(array $migrations, array $dynamic_ids) $migration->set('requirements', $required_dependency_graph[$migration_id]['paths']); } } - array_multisort($weights, SORT_DESC, SORT_NUMERIC, $migrations); + // Sort weights, labels, and keys in the same order as each other. + array_multisort( + // Use the numerical weight as the primary sort. + $weights, SORT_DESC, SORT_NUMERIC, + // When migrations have the same weight, sort them alphabetically by ID. + array_keys($migrations), SORT_ASC, SORT_NATURAL, + $migrations + ); return $migrations; } diff --git a/web/core/modules/migrate/src/Plugin/migrate/destination/EntityConfigBase.php b/web/core/modules/migrate/src/Plugin/migrate/destination/EntityConfigBase.php index af9f35c37fe287b9156261d732c23c1b4d197bf6..b934a70635c15f5a5acff8eee7bae4931e338c1b 100644 --- a/web/core/modules/migrate/src/Plugin/migrate/destination/EntityConfigBase.php +++ b/web/core/modules/migrate/src/Plugin/migrate/destination/EntityConfigBase.php @@ -268,7 +268,7 @@ public function rollback(array $destination_identifier) { // The entity id does not include the langcode. $id_values = []; foreach ($destination_identifier as $key => $value) { - if ($this->isTranslationDestination() && $key == 'langcode') { + if ($this->isTranslationDestination() && $key === 'langcode') { continue; } $id_values[] = $value; diff --git a/web/core/modules/migrate/src/Plugin/migrate/destination/EntityFieldStorageConfig.php b/web/core/modules/migrate/src/Plugin/migrate/destination/EntityFieldStorageConfig.php index 80ea9f628b8b3cdb253b22d36f5decb5e333965e..0b9714a79b11e1de973ee63d3253456f185ec090 100644 --- a/web/core/modules/migrate/src/Plugin/migrate/destination/EntityFieldStorageConfig.php +++ b/web/core/modules/migrate/src/Plugin/migrate/destination/EntityFieldStorageConfig.php @@ -58,6 +58,10 @@ class EntityFieldStorageConfig extends EntityConfigBase { public function getIds() { $ids['entity_type']['type'] = 'string'; $ids['field_name']['type'] = 'string'; + // @todo: Remove conditional. https://www.drupal.org/node/3004574 + if ($this->isTranslationDestination()) { + $ids['langcode']['type'] = 'string'; + } return $ids; } @@ -65,8 +69,18 @@ public function getIds() { * {@inheritdoc} */ public function rollback(array $destination_identifier) { - $destination_identifier = implode('.', $destination_identifier); - parent::rollback([$destination_identifier]); + if ($this->isTranslationDestination()) { + $language = $destination_identifier['langcode']; + unset($destination_identifier['langcode']); + $destination_identifier = [ + implode('.', $destination_identifier), + 'langcode' => $language, + ]; + } + else { + $destination_identifier = [implode('.', $destination_identifier)]; + } + parent::rollback($destination_identifier); } } diff --git a/web/core/modules/migrate/src/Plugin/migrate/id_map/Sql.php b/web/core/modules/migrate/src/Plugin/migrate/id_map/Sql.php index 0de83485ffa9a1c9f1bc38f1bb732ace7d4a637e..216eecd755b74f9f6c70b5a000e1876a70c5e490 100644 --- a/web/core/modules/migrate/src/Plugin/migrate/id_map/Sql.php +++ b/web/core/modules/migrate/src/Plugin/migrate/id_map/Sql.php @@ -584,7 +584,7 @@ public function lookupDestinationIds(array $source_id_values) { if (!empty($source_id_values)) { $var_dump = var_export($source_id_values, TRUE); - throw new MigrateException(sprintf("Extra unknown items in source IDs: %s", $var_dump)); + throw new MigrateException(sprintf("Extra unknown items for map %s in source IDs: %s", $this->mapTableName(), $var_dump)); } $query = $this->getDatabase()->select($this->mapTableName(), 'map') diff --git a/web/core/modules/migrate/src/Plugin/migrate/process/FormatDate.php b/web/core/modules/migrate/src/Plugin/migrate/process/FormatDate.php index 9448ca2fff269dd7badaf11db7e9d91fad26d775..c9b75a9d7c23a74936da02349046bc732adae2b3 100644 --- a/web/core/modules/migrate/src/Plugin/migrate/process/FormatDate.php +++ b/web/core/modules/migrate/src/Plugin/migrate/process/FormatDate.php @@ -82,7 +82,8 @@ * @endcode * * If the source value was '2004-12-19T10:19:42-0600' the transformed value - * would be 2004-12-19T10:19:42. + * would be 2004-12-19T10:19:42. Set validate_format to false if your source + * value is '0000-00-00 00:00:00'. * * @see \DateTime::createFromFormat() * @see \Drupal\Component\Datetime\DateTimePlus::__construct() @@ -99,7 +100,7 @@ class FormatDate extends ProcessPluginBase { * {@inheritdoc} */ public function transform($value, MigrateExecutableInterface $migrate_executable, Row $row, $destination_property) { - if (empty($value)) { + if (empty($value) && $value !== '0' && $value !== 0) { return ''; } diff --git a/web/core/modules/migrate/src/Plugin/migrate/process/MigrationLookup.php b/web/core/modules/migrate/src/Plugin/migrate/process/MigrationLookup.php index e8a075606e68194d8a65347b84bfb61f1f262b32..be51465268d34b56234ccf49fd71d8afa46d1736 100644 --- a/web/core/modules/migrate/src/Plugin/migrate/process/MigrationLookup.php +++ b/web/core/modules/migrate/src/Plugin/migrate/process/MigrationLookup.php @@ -238,7 +238,7 @@ public function transform($value, MigrateExecutableInterface $migrate_executable /** * Skips the migration process entirely if the value is FALSE. * - * @param mixed $value + * @param array $value * The incoming value to transform. * * @throws \Drupal\migrate\MigrateSkipProcessException diff --git a/web/core/modules/migrate/src/Plugin/migrate/source/DummyQueryTrait.php b/web/core/modules/migrate/src/Plugin/migrate/source/DummyQueryTrait.php index efe56b41fa2629869a40bb6c79decf833608c7d6..51a456a017a765a528b3438ca4014534f50c5c1e 100644 --- a/web/core/modules/migrate/src/Plugin/migrate/source/DummyQueryTrait.php +++ b/web/core/modules/migrate/src/Plugin/migrate/source/DummyQueryTrait.php @@ -16,7 +16,7 @@ trait DummyQueryTrait { * {@inheritdoc} */ public function query() { - // Pass an arbritrary table name - the query should never be executed + // Pass an arbitrary table name - the query should never be executed // anyway. $query = $this->select(uniqid(), 's') ->range(0, 1); diff --git a/web/core/modules/migrate/src/Plugin/migrate/source/SourcePluginBase.php b/web/core/modules/migrate/src/Plugin/migrate/source/SourcePluginBase.php index 3dd7144b8fc59a6c6412004806526bd0a0636794..8267bac783541046ee7b7aa63cf3a32f1aee34e8 100644 --- a/web/core/modules/migrate/src/Plugin/migrate/source/SourcePluginBase.php +++ b/web/core/modules/migrate/src/Plugin/migrate/source/SourcePluginBase.php @@ -353,7 +353,7 @@ public function next() { $row_data = $this->getIterator()->current() + $this->configuration; $this->fetchNextRow(); - $row = new Row($row_data, $this->migration->getSourcePlugin()->getIds(), $this->migration->getDestinationIds()); + $row = new Row($row_data, $this->getIds()); // Populate the source key for this row. $this->currentSourceIds = $row->getSourceIdValues(); diff --git a/web/core/modules/migrate/src/Plugin/migrate/source/SqlBase.php b/web/core/modules/migrate/src/Plugin/migrate/source/SqlBase.php index b9e8e731ab6bdc123e14ba6b0a0a7e8f9ce5e2e4..4bf846e854eb0dd250be2d5eb6c8a3141736c5f7 100644 --- a/web/core/modules/migrate/src/Plugin/migrate/source/SqlBase.php +++ b/web/core/modules/migrate/src/Plugin/migrate/source/SqlBase.php @@ -108,6 +108,11 @@ abstract class SqlBase extends SourcePluginBase implements ContainerFactoryPlugi public function __construct(array $configuration, $plugin_id, $plugin_definition, MigrationInterface $migration, StateInterface $state) { parent::__construct($configuration, $plugin_id, $plugin_definition, $migration); $this->state = $state; + // If we are using high water, but haven't yet set a high water mark, skip + // joining the map table, as we want to get all available records. + if ($this->getHighWaterProperty() && $this->getHighWater() === NULL) { + $this->configuration['ignore_map'] = TRUE; + } } /** @@ -322,7 +327,9 @@ protected function initializeIterator() { if ($this->getHighWaterProperty()) { $high_water_field = $this->getHighWaterField(); $high_water = $this->getHighWater(); - if ($high_water) { + // We check against NULL because 0 is an acceptable value for the high + // water mark. + if ($high_water !== NULL) { $conditions->condition($high_water_field, $high_water, '>'); $condition_added = TRUE; } diff --git a/web/core/modules/migrate/tests/src/Kernel/HighWaterTest.php b/web/core/modules/migrate/tests/src/Kernel/HighWaterTest.php index faffb663585cd8337481ab76fdb339eca63a06b3..27f826603c464988e9299986bf9aade87c95f836 100644 --- a/web/core/modules/migrate/tests/src/Kernel/HighWaterTest.php +++ b/web/core/modules/migrate/tests/src/Kernel/HighWaterTest.php @@ -136,6 +136,72 @@ public function testHighWater() { $this->assertNodeDoesNotExist('Item 3'); } + /** + * Tests that the high water value can be 0. + */ + public function testZeroHighwater() { + // Assert all of the nodes have been imported. + $this->assertNodeExists('Item 1'); + $this->assertNodeExists('Item 2'); + $this->assertNodeExists('Item 3'); + $migration = $this->container->get('plugin.manager.migration')->CreateInstance('high_water_test', []); + $source = $migration->getSourcePlugin(); + $source->rewind(); + $count = 0; + while ($source->valid()) { + $count++; + $source->next(); + } + + // Expect no rows as everything is below the high water mark. + $this->assertSame(0, $count); + + // Test resetting the high water mark to 0. + $this->container->get('keyvalue')->get('migrate:high_water')->set('high_water_test', 0); + $migration = $this->container->get('plugin.manager.migration')->CreateInstance('high_water_test', []); + $source = $migration->getSourcePlugin(); + $source->rewind(); + $count = 0; + while ($source->valid()) { + $count++; + $source->next(); + } + $this->assertSame(3, $count); + } + + /** + * Tests that deleting the high water value causes all rows to be reimported. + */ + public function testNullHighwater() { + // Assert all of the nodes have been imported. + $this->assertNodeExists('Item 1'); + $this->assertNodeExists('Item 2'); + $this->assertNodeExists('Item 3'); + $migration = $this->container->get('plugin.manager.migration')->CreateInstance('high_water_test', []); + $source = $migration->getSourcePlugin(); + $source->rewind(); + $count = 0; + while ($source->valid()) { + $count++; + $source->next(); + } + + // Expect no rows as everything is below the high water mark. + $this->assertSame(0, $count); + + // Test resetting the high water mark. + $this->container->get('keyvalue')->get('migrate:high_water')->delete('high_water_test'); + $migration = $this->container->get('plugin.manager.migration')->CreateInstance('high_water_test', []); + $source = $migration->getSourcePlugin(); + $source->rewind(); + $count = 0; + while ($source->valid()) { + $count++; + $source->next(); + } + $this->assertSame(3, $count); + } + /** * Tests high water property of SqlBase when rows marked for update. */ diff --git a/web/core/modules/migrate/tests/src/Kernel/MigrateEmbeddedDataTest.php b/web/core/modules/migrate/tests/src/Kernel/MigrateEmbeddedDataTest.php index 019ac42ab9e7529e88ca1bc1cad5051bbfa57574..7be474e014e3384d96c0c040739709d08d17599b 100644 --- a/web/core/modules/migrate/tests/src/Kernel/MigrateEmbeddedDataTest.php +++ b/web/core/modules/migrate/tests/src/Kernel/MigrateEmbeddedDataTest.php @@ -45,6 +45,11 @@ public function testEmbeddedData() { $results = []; /** @var \Drupal\migrate\Row $row */ foreach ($source as $row) { + // The plugin should not mark any rows as stubs. We need to use + // assertSame() here because assertFalse() will pass falsy values (e.g., + // empty arrays). + $this->assertSame(FALSE, $row->isStub()); + $data_row = $row->getSource(); // The "data" row returned by getSource() also includes all source // configuration - we remove it so we see only the data itself. diff --git a/web/core/modules/migrate/tests/src/Kernel/Plugin/MigrationPluginListTest.php b/web/core/modules/migrate/tests/src/Kernel/Plugin/MigrationPluginListTest.php index 7bfba70f27a12a92e55ce0375d3a2e0abe2a8cc6..b256e3f3a3eaff7b95ae12bb828283177615a04a 100644 --- a/web/core/modules/migrate/tests/src/Kernel/Plugin/MigrationPluginListTest.php +++ b/web/core/modules/migrate/tests/src/Kernel/Plugin/MigrationPluginListTest.php @@ -3,11 +3,11 @@ namespace Drupal\Tests\migrate\Kernel\Plugin; use Drupal\Core\Database\Database; -use Drupal\field\Tests\EntityReference\EntityReferenceTestTrait; use Drupal\KernelTests\KernelTestBase; use Drupal\migrate\Exception\RequirementsException; use Drupal\migrate\Plugin\migrate\source\SqlBase; use Drupal\migrate\Plugin\RequirementsInterface; +use Drupal\Tests\field\Traits\EntityReferenceTestTrait; /** * Tests the migration plugin manager. diff --git a/web/core/modules/migrate/tests/src/Unit/MigrateSqlIdMapTest.php b/web/core/modules/migrate/tests/src/Unit/MigrateSqlIdMapTest.php index b0f3d1a35594e579db44b0eb24bd6040b5f2597d..417ede6f75e0c28362422621ea8b31f600db166f 100644 --- a/web/core/modules/migrate/tests/src/Unit/MigrateSqlIdMapTest.php +++ b/web/core/modules/migrate/tests/src/Unit/MigrateSqlIdMapTest.php @@ -529,14 +529,14 @@ public function testLookupDestinationIds() { $this->fail('Too many source IDs should throw'); } catch (MigrateException $e) { - $this->assertEquals("Extra unknown items in source IDs: array (\n 0 => 3,\n)", $e->getMessage()); + $this->assertEquals("Extra unknown items for map migrate_map_sql_idmap_test in source IDs: array (\n 0 => 3,\n)", $e->getMessage()); } try { $id_map->lookupDestinationIds(['nid' => 1, 'aaa' => '2']); $this->fail('Unknown source ID key should throw'); } catch (MigrateException $e) { - $this->assertEquals("Extra unknown items in source IDs: array (\n 'aaa' => '2',\n)", $e->getMessage()); + $this->assertEquals("Extra unknown items for map migrate_map_sql_idmap_test in source IDs: array (\n 'aaa' => '2',\n)", $e->getMessage()); } // Verify that we are looking up by source_id_hash when all source IDs are diff --git a/web/core/modules/migrate/tests/src/Unit/process/CallbackTest.php b/web/core/modules/migrate/tests/src/Unit/process/CallbackTest.php index e7d1718706483d38eb518e355dfa14a228279904..6d894c09c269e5ae4c4331dbbefce27ef7b08909 100644 --- a/web/core/modules/migrate/tests/src/Unit/process/CallbackTest.php +++ b/web/core/modules/migrate/tests/src/Unit/process/CallbackTest.php @@ -34,7 +34,7 @@ public function providerCallback() { } /** - * Test callback excpetions. + * Test callback exceptions. * * @dataProvider providerCallbackExceptions */ diff --git a/web/core/modules/migrate/tests/src/Unit/process/FormatDateTest.php b/web/core/modules/migrate/tests/src/Unit/process/FormatDateTest.php index 994de3855fbd9a8ae3c598a0206c4a15113de4d0..d11e95e4f11540915058e827f68b17dc0abd7bfd 100644 --- a/web/core/modules/migrate/tests/src/Unit/process/FormatDateTest.php +++ b/web/core/modules/migrate/tests/src/Unit/process/FormatDateTest.php @@ -175,6 +175,42 @@ public function datesDataProvider() { // converted from Australia/Sydney to America/Managua timezone. 'expected' => '2004-12-18 17:19:42 America/Managua', ], + 'integer_0' => [ + 'configuration' => [ + 'from_format' => 'U', + 'to_format' => 'Y-m-d', + ], + 'value' => 0, + 'expected' => '1970-01-01', + ], + 'string_0' => [ + 'configuration' => [ + 'from_format' => 'U', + 'to_format' => 'Y-m-d', + ], + 'value' => '0', + 'expected' => '1970-01-01', + ], + 'zeros' => [ + 'configuration' => [ + 'from_format' => 'Y-m-d H:i:s', + 'to_format' => 'Y-m-d H:i:s e', + 'settings' => ['validate_format' => FALSE], + ], + 'value' => '0000-00-00 00:00:00', + 'expected' => '-0001-11-30 00:00:00 Australia/Sydney', + ], + 'zeros_same_timezone' => [ + 'configuration' => [ + 'from_format' => 'Y-m-d H:i:s', + 'to_format' => 'Y-m-d H:i:s', + 'settings' => ['validate_format' => FALSE], + 'from_timezone' => 'UTC', + 'to_timezone' => 'UTC', + ], + 'value' => '0000-00-00 00:00:00', + 'expected' => '-0001-11-30 00:00:00', + ], ]; } diff --git a/web/core/modules/migrate_drupal/src/Plugin/MigrationWithFollowUpInterface.php b/web/core/modules/migrate_drupal/src/Plugin/MigrationWithFollowUpInterface.php index 93ef8f91171a5bbd9c4309874b98db7ae26c6c96..02db0d40036e603cac2c647c7945109b4438237b 100644 --- a/web/core/modules/migrate_drupal/src/Plugin/MigrationWithFollowUpInterface.php +++ b/web/core/modules/migrate_drupal/src/Plugin/MigrationWithFollowUpInterface.php @@ -28,7 +28,7 @@ interface MigrationWithFollowUpInterface { /** * Generates follow-up migrations. * - * When the migration implementing this interface has been succesfully + * When the migration implementing this interface has been successfully * executed, this method will be used to generate the follow-up migrations * which depends on the now migrated data. * diff --git a/web/core/modules/migrate_drupal/src/Plugin/migrate/source/DrupalSqlBase.php b/web/core/modules/migrate_drupal/src/Plugin/migrate/source/DrupalSqlBase.php index c8b44f894e46951134b318beaa135c513b981064..15acb0213fb60130ed275cd451df9042314f9385 100644 --- a/web/core/modules/migrate_drupal/src/Plugin/migrate/source/DrupalSqlBase.php +++ b/web/core/modules/migrate_drupal/src/Plugin/migrate/source/DrupalSqlBase.php @@ -102,6 +102,7 @@ public static function create(ContainerInterface $container, array $configuratio * {@inheritdoc} */ public function checkRequirements() { + parent::checkRequirements(); if ($this->pluginDefinition['requirements_met'] === TRUE) { if (isset($this->pluginDefinition['source_module'])) { if ($this->moduleExists($this->pluginDefinition['source_module'])) { @@ -114,7 +115,6 @@ public function checkRequirements() { } } } - parent::checkRequirements(); } /** diff --git a/web/core/modules/migrate_drupal/src/Plugin/migrate/source/d6/D6VariableTranslation.php b/web/core/modules/migrate_drupal/src/Plugin/migrate/source/d6/D6VariableTranslation.php new file mode 100644 index 0000000000000000000000000000000000000000..a4a3a9f085c770deb6735143a10bab93a2e3e8e4 --- /dev/null +++ b/web/core/modules/migrate_drupal/src/Plugin/migrate/source/d6/D6VariableTranslation.php @@ -0,0 +1,32 @@ +<?php + +namespace Drupal\migrate_drupal\Plugin\migrate\source\d6; + +use Drupal\Core\Entity\EntityManagerInterface; +use Drupal\Core\State\StateInterface; +use Drupal\migrate\Plugin\MigrationInterface; + +/** + * Gets Drupal i18n_variable source from database. + * + * @deprecated in Drupal 8.7.x and will be removed in Drupal 9.0.x. + * Use \Drupal\migrate_drupal\Plugin\migrate\source\d6\VariableTranslation. + * + * @see https://www.drupal.org/node/3006487 + * + * @MigrateSource( + * id = "variable_translation", + * source_module = "system", + * ) + */ +class D6VariableTranslation extends VariableTranslation { + + /** + * {@inheritdoc} + */ + public function __construct(array $configuration, $plugin_id, $plugin_definition, MigrationInterface $migration, StateInterface $state, EntityManagerInterface $entity_manager) { + @trigger_error('The ' . __NAMESPACE__ . '\D6VariableTranslation is deprecated in Drupal 8.7.0 and will be removed before Drupal 9.0.0. Instead, use ' . __NAMESPACE__ . '\VariableTranslation. See https://www.drupal.org/node/3006487.', E_USER_DEPRECATED); + parent::__construct($configuration, $plugin_id, $plugin_definition, $migration, $state, $entity_manager); + } + +} diff --git a/web/core/modules/migrate_drupal/src/Plugin/migrate/source/d6/VariableTranslation.php b/web/core/modules/migrate_drupal/src/Plugin/migrate/source/d6/VariableTranslation.php index ce57716a03cd9f72e61e20c5e96ee70b0eb5e641..e11a305c8b9da84905e68910b77f6ed51d778f07 100644 --- a/web/core/modules/migrate_drupal/src/Plugin/migrate/source/d6/VariableTranslation.php +++ b/web/core/modules/migrate_drupal/src/Plugin/migrate/source/d6/VariableTranslation.php @@ -11,7 +11,7 @@ * Drupal i18n_variable source from database. * * @MigrateSource( - * id = "variable_translation", + * id = "d6_variable_translation", * source_module = "system", * ) */ diff --git a/web/core/modules/migrate_drupal/src/Plugin/migrate/source/d7/VariableTranslation.php b/web/core/modules/migrate_drupal/src/Plugin/migrate/source/d7/VariableTranslation.php new file mode 100644 index 0000000000000000000000000000000000000000..4df6a8702dc67f12e916b730c0ab03387ebc592e --- /dev/null +++ b/web/core/modules/migrate_drupal/src/Plugin/migrate/source/d7/VariableTranslation.php @@ -0,0 +1,106 @@ +<?php + +namespace Drupal\migrate_drupal\Plugin\migrate\source\d7; + +use Drupal\Core\Entity\EntityManagerInterface; +use Drupal\Core\State\StateInterface; +use Drupal\migrate\Plugin\MigrationInterface; +use Drupal\migrate_drupal\Plugin\migrate\source\DrupalSqlBase; + +/** + * Gets Drupal variable_store source from database. + * + * @MigrateSource( + * id = "d7_variable_translation", + * source_module = "i18n_variable", + * ) + */ +class VariableTranslation extends DrupalSqlBase { + /** + * The variable names to fetch. + * + * @var array + */ + protected $variables; + + /** + * {@inheritdoc} + */ + public function __construct(array $configuration, $plugin_id, $plugin_definition, MigrationInterface $migration, StateInterface $state, EntityManagerInterface $entity_manager) { + parent::__construct($configuration, $plugin_id, $plugin_definition, $migration, $state, $entity_manager); + $this->variables = $this->configuration['variables']; + } + + /** + * {@inheritdoc} + */ + protected function initializeIterator() { + return new \ArrayIterator($this->values()); + } + + /** + * Return the values of the variables specified in the plugin configuration. + * + * @return array + * An associative array where the keys are the variables specified in the + * plugin configuration and the values are the values found in the source. + * A key/value pair is added for the language code. Only those values are + * returned that are actually in the database. + */ + protected function values() { + $values = []; + $result = $this->prepareQuery()->execute()->FetchAllAssoc('realm_key'); + foreach ($result as $variable_store) { + $values[]['language'] = $variable_store['realm_key']; + } + $result = $this->prepareQuery()->execute()->FetchAll(); + foreach ($result as $variable_store) { + foreach ($values as $key => $value) { + if ($values[$key]['language'] === $variable_store['realm_key']) { + if ($variable_store['serialized']) { + $values[$key][$variable_store['name']] = unserialize($variable_store['value']); + break; + } + else { + $values[$key][$variable_store['name']] = $variable_store['value']; + break; + } + } + } + } + return $values; + } + + /** + * {@inheritdoc} + */ + public function count($refresh = FALSE) { + return $this->initializeIterator()->count(); + } + + /** + * {@inheritdoc} + */ + public function fields() { + return array_combine($this->variables, $this->variables); + } + + /** + * {@inheritdoc} + */ + public function getIds() { + $ids['language']['type'] = 'string'; + return $ids; + } + + /** + * {@inheritdoc} + */ + public function query() { + return $this->select('variable_store', 'vs') + ->fields('vs') + ->condition('realm', 'language') + ->condition('name', (array) $this->configuration['variables'], 'IN'); + } + +} diff --git a/web/core/modules/migrate_drupal/tests/fixtures/drupal6.php b/web/core/modules/migrate_drupal/tests/fixtures/drupal6.php index d9b1c2cd72af8c12b0acb7241aa605b8b3879548..6c009573998e80b485aab33e7fbdcef91c55d48e 100644 --- a/web/core/modules/migrate_drupal/tests/fixtures/drupal6.php +++ b/web/core/modules/migrate_drupal/tests/fixtures/drupal6.php @@ -292,7 +292,6 @@ 'description' => 'Block current user', )) ->execute(); - $connection->schema()->createTable('actions_aid', array( 'fields' => array( 'aid' => array( @@ -331,7 +330,6 @@ 'aid' => '6', )) ->execute(); - $connection->schema()->createTable('aggregator_category', array( 'fields' => array( 'cid' => array( @@ -463,7 +461,6 @@ 'block' => '7', )) ->execute(); - $connection->schema()->createTable('aggregator_item', array( 'fields' => array( 'iid' => array( @@ -539,7 +536,6 @@ 'guid' => '395218 at https://groups.drupal.org', )) ->execute(); - $connection->schema()->createTable('authmap', array( 'fields' => array( 'aid' => array( @@ -617,7 +613,6 @@ 'batch' => NULL, )) ->execute(); - $connection->schema()->createTable('blocks', array( 'fields' => array( 'bid' => array( @@ -1080,7 +1075,6 @@ 'cache' => '-1', )) ->execute(); - $connection->schema()->createTable('blocks_roles', array( 'fields' => array( 'module' => array( @@ -1125,7 +1119,6 @@ 'rid' => '3', )) ->execute(); - $connection->schema()->createTable('book', array( 'fields' => array( 'mlid' => array( @@ -1188,7 +1181,6 @@ 'bid' => '8', )) ->execute(); - $connection->schema()->createTable('boxes', array( 'fields' => array( 'bid' => array( @@ -1241,7 +1233,6 @@ 'format' => '2', )) ->execute(); - $connection->schema()->createTable('cache', array( 'fields' => array( 'cid' => array( @@ -1990,8 +1981,39 @@ 'mail' => '', 'homepage' => '', )) +->values(array( + 'cid' => '7', + 'pid' => '0', + 'nid' => '21', + 'uid' => '1', + 'subject' => 'Comment to John Smith - EN', + 'comment' => 'This is an English comment.', + 'hostname' => '2001:14ba:13f8:300:d9d0:363c:9fe4:66e1', + 'timestamp' => '1534014729', + 'status' => '0', + 'format' => '1', + 'thread' => '01/', + 'name' => 'root', + 'mail' => '', + 'homepage' => '', +)) +->values(array( + 'cid' => '8', + 'pid' => '0', + 'nid' => '22', + 'uid' => '1', + 'subject' => 'Comment to John Smith - FR', + 'comment' => 'This is a French comment.', + 'hostname' => '2001:14ba:13f8:300:d9d0:363c:9fe4:66e1', + 'timestamp' => '1534014763', + 'status' => '0', + 'format' => '1', + 'thread' => '01/', + 'name' => 'root', + 'mail' => '', + 'homepage' => '', +)) ->execute(); - $connection->schema()->createTable('config', array( 'fields' => array( 'collection' => array( @@ -2031,7 +2053,6 @@ 'data' => 'a:1:{s:4:"path";a:1:{s:9:"temporary";s:4:"/tmp";}}', )) ->execute(); - $connection->schema()->createTable('contact', array( 'fields' => array( 'cid' => array( @@ -2109,7 +2130,6 @@ 'selected' => '0', )) ->execute(); - $connection->schema()->createTable('content_field_company', array( 'fields' => array( 'vid' => array( @@ -2168,6 +2188,18 @@ 'delta' => '0', 'field_company_nid' => '15', )) +->values(array( + 'vid' => '2002', + 'nid' => '21', + 'delta' => '0', + 'field_company_nid' => NULL, +)) +->values(array( + 'vid' => '2003', + 'nid' => '22', + 'delta' => '0', + 'field_company_nid' => NULL, +)) ->values(array( 'vid' => '21', 'nid' => '18', @@ -2175,7 +2207,6 @@ 'field_company_nid' => '16', )) ->execute(); - $connection->schema()->createTable('content_field_image', array( 'fields' => array( 'vid' => array( @@ -2244,7 +2275,6 @@ 'field_image_data' => 'a:2:{s:3:"alt";s:0:"";s:5:"title";s:0:"";}', )) ->execute(); - $connection->schema()->createTable('content_field_multivalue', array( 'fields' => array( 'vid' => array( @@ -2307,7 +2337,6 @@ 'delta' => '1', )) ->execute(); - $connection->schema()->createTable('content_field_test', array( 'fields' => array( 'vid' => array( @@ -2385,7 +2414,6 @@ 'field_test_format' => '1', )) ->execute(); - $connection->schema()->createTable('content_field_test_text_single_checkbox', array( 'fields' => array( 'vid' => array( @@ -2451,7 +2479,6 @@ 'field_test_text_single_checkbox_value' => '0', )) ->execute(); - $connection->schema()->createTable('content_field_test_two', array( 'fields' => array( 'vid' => array( @@ -2537,7 +2564,6 @@ 'field_test_two_value' => '20', )) ->execute(); - $connection->schema()->createTable('content_group', array( 'fields' => array( 'group_type' => array( @@ -2968,6 +2994,18 @@ 'active' => '1', 'locked' => '0', )) +->values(array( + 'field_name' => 'field_test_string_selectlist', + 'type' => 'text', + 'global_settings' => "a:4:{s:15:\"text_processing\";s:1:\"0\";s:10:\"max_length\";s:0:\"\";s:14:\"allowed_values\";s:18:\"A|Black\r\nB|White\r\n\";s:18:\"allowed_values_php\";s:0:\"\";}", + 'required' => '0', + 'multiple' => '0', + 'db_storage' => '1', + 'module' => 'text', + 'db_columns' => 'a:1:{s:5:"value";a:5:{s:4:"type";s:4:"text";s:4:"size";s:3:"big";s:8:"not null";b:0;s:8:"sortable";b:1;s:5:"views";b:1;}}', + 'active' => '1', + 'locked' => '0', +)) ->values(array( 'field_name' => 'field_test_text_single_checkbox', 'type' => 'text', @@ -3017,7 +3055,6 @@ 'locked' => '0', )) ->execute(); - $connection->schema()->createTable('content_node_field_instance', array( 'fields' => array( 'field_name' => array( @@ -3386,6 +3423,18 @@ 'widget_module' => 'phone', 'widget_active' => '1', )) +->values(array( + 'field_name' => 'field_test_string_selectlist', + 'type_name' => 'story', + 'weight' => '31', + 'label' => 'String Select List Field', + 'widget_type' => 'optionwidgets_select', + 'widget_settings' => 'a:2:{s:13:"default_value";a:1:{i:0;a:1:{s:5:"value";s:0:"";}}s:17:"default_value_php";N;}', + 'display_settings' => 'a:5:{s:5:"label";a:2:{s:6:"format";s:5:"above";s:7:"exclude";i:0;}i:5;a:2:{s:6:"format";s:7:"default";s:7:"exclude";i:0;}s:6:"teaser";a:2:{s:6:"format";s:7:"default";s:7:"exclude";i:0;}s:4:"full";a:2:{s:6:"format";s:7:"default";s:7:"exclude";i:0;}i:4;a:2:{s:6:"format";s:7:"default";s:7:"exclude";i:0;}}', + 'description' => '', + 'widget_module' => 'optionwidgets', + 'widget_active' => '1', +)) ->values(array( 'field_name' => 'field_test_text_single_checkbox', 'type_name' => 'story', @@ -3447,7 +3496,6 @@ 'widget_active' => '1', )) ->execute(); - $connection->schema()->createTable('content_type_employee', array( 'fields' => array( 'vid' => array( @@ -3518,8 +3566,21 @@ 'field_company_2_nid' => '15', 'field_company_3_nid' => '16', )) +->values(array( + 'vid' => '2002', + 'nid' => '21', + 'field_commander_uid' => NULL, + 'field_company_2_nid' => NULL, + 'field_company_3_nid' => NULL, +)) +->values(array( + 'vid' => '2003', + 'nid' => '22', + 'field_commander_uid' => NULL, + 'field_company_2_nid' => NULL, + 'field_company_3_nid' => NULL, +)) ->execute(); - $connection->schema()->createTable('content_type_page', array( 'fields' => array( 'vid' => array( @@ -3605,7 +3666,6 @@ 'field_reference_2_nid' => '11', )) ->execute(); - $connection->schema()->createTable('content_type_story', array( 'fields' => array( 'nid' => array( @@ -3764,6 +3824,11 @@ 'not null' => FALSE, 'length' => '100', ), + 'field_test_string_selectlist_value' => array( + 'type' => 'text', + 'not null' => FALSE, + 'size' => 'big', + ), ), 'primary key' => array( 'vid', @@ -3807,6 +3872,7 @@ 'field_test_text_single_checkbox2_value', 'field_test_datestamp_value2', 'field_test_datetime_value2', + 'field_test_string_selectlist_value', )) ->values(array( 'nid' => '1', @@ -3838,6 +3904,7 @@ 'field_test_text_single_checkbox2_value' => 'Hello', 'field_test_datestamp_value2' => NULL, 'field_test_datetime_value2' => NULL, + 'field_test_string_selectlist_value' => NULL, )) ->values(array( 'nid' => '1', @@ -3869,6 +3936,7 @@ 'field_test_text_single_checkbox2_value' => NULL, 'field_test_datestamp_value2' => NULL, 'field_test_datetime_value2' => NULL, + 'field_test_string_selectlist_value' => NULL, )) ->values(array( 'nid' => '2', @@ -3900,6 +3968,7 @@ 'field_test_text_single_checkbox2_value' => NULL, 'field_test_datestamp_value2' => NULL, 'field_test_datetime_value2' => NULL, + 'field_test_string_selectlist_value' => NULL, )) ->values(array( 'nid' => '2', @@ -3931,6 +4000,7 @@ 'field_test_text_single_checkbox2_value' => NULL, 'field_test_datestamp_value2' => NULL, 'field_test_datetime_value2' => NULL, + 'field_test_string_selectlist_value' => NULL, )) ->values(array( 'nid' => '9', @@ -3962,9 +4032,9 @@ 'field_test_text_single_checkbox2_value' => 'Off', 'field_test_datestamp_value2' => '1391357160', 'field_test_datetime_value2' => '2015-03-04 06:07:00', + 'field_test_string_selectlist_value' => NULL, )) ->execute(); - $connection->schema()->createTable('content_type_test_page', array( 'fields' => array( 'vid' => array( @@ -4055,7 +4125,6 @@ 'vid' => '11', )) ->execute(); - $connection->schema()->createTable('date_format_locale', array( 'fields' => array( 'format' => array( @@ -4128,7 +4197,6 @@ 'locked' => '1', )) ->execute(); - $connection->schema()->createTable('date_formats', array( 'fields' => array( 'dfid' => array( @@ -4378,7 +4446,6 @@ 'locked' => '1', )) ->execute(); - $connection->schema()->createTable('event', array( 'fields' => array( 'nid' => array( @@ -8178,7 +8245,6 @@ 'is_dst' => '0', )) ->execute(); - $connection->schema()->createTable('files', array( 'fields' => array( 'fid' => array( @@ -8301,7 +8367,6 @@ 'timestamp' => '1420858106', )) ->execute(); - $connection->schema()->createTable('filter_formats', array( 'fields' => array( 'format' => array( @@ -8366,7 +8431,6 @@ 'cache' => '0', )) ->execute(); - $connection->schema()->createTable('filters', array( 'fields' => array( 'fid' => array( @@ -8498,7 +8562,6 @@ 'weight' => '10', )) ->execute(); - $connection->schema()->createTable('flood', array( 'fields' => array( 'fid' => array( @@ -8581,7 +8644,6 @@ 'tid' => '8', )) ->execute(); - $connection->schema()->createTable('history', array( 'fields' => array( 'uid' => array( @@ -8666,8 +8728,17 @@ 'nid' => '19', 'timestamp' => '1501955803', )) +->values(array( + 'uid' => '1', + 'nid' => '21', + 'timestamp' => '1534014729', +)) +->values(array( + 'uid' => '1', + 'nid' => '22', + 'timestamp' => '1534014763', +)) ->execute(); - $connection->schema()->createTable('i18n_blocks', array( 'fields' => array( 'ibid' => array( @@ -8729,7 +8800,6 @@ 'language' => 'zu', )) ->execute(); - $connection->schema()->createTable('i18n_strings', array( 'fields' => array( 'lid' => array( @@ -9888,8 +9958,111 @@ 'objectindex' => '0', 'format' => '0', )) +->values(array( + 'lid' => '1680', + 'objectid' => 'employee-field_company', + 'type' => 'field', + 'property' => 'widget_label', + 'objectindex' => '0', + 'format' => '0', +)) +->values(array( + 'lid' => '1681', + 'objectid' => 'employee-field_commander', + 'type' => 'field', + 'property' => 'widget_label', + 'objectindex' => '0', + 'format' => '0', +)) +->values(array( + 'lid' => '1682', + 'objectid' => 'employee-field_company_2', + 'type' => 'field', + 'property' => 'widget_label', + 'objectindex' => '0', + 'format' => '0', +)) +->values(array( + 'lid' => '1683', + 'objectid' => 'employee-field_company_3', + 'type' => 'field', + 'property' => 'widget_label', + 'objectindex' => '0', + 'format' => '0', +)) +->values(array( + 'lid' => '1684', + 'objectid' => 'page-field_reference', + 'type' => 'field', + 'property' => 'widget_label', + 'objectindex' => '0', + 'format' => '0', +)) +->values(array( + 'lid' => '1685', + 'objectid' => 'page-field_reference_2', + 'type' => 'field', + 'property' => 'widget_label', + 'objectindex' => '0', + 'format' => '0', +)) +->values(array( + 'lid' => '1686', + 'objectid' => 'story-field_test_string_selectlist', + 'type' => 'field', + 'property' => 'widget_label', + 'objectindex' => '0', + 'format' => '0', +)) +->values(array( + 'lid' => '1689', + 'objectid' => 'test_planet-field_test_text_single_checkbox', + 'type' => 'field', + 'property' => 'widget_label', + 'objectindex' => '0', + 'format' => '0', +)) +->values(array( + 'lid' => '1690', + 'objectid' => 'field_test_string_selectlist', + 'type' => 'field', + 'property' => 'option_A', + 'objectindex' => '0', + 'format' => '0', +)) +->values(array( + 'lid' => '1691', + 'objectid' => 'field_test_string_selectlist', + 'type' => 'field', + 'property' => 'option_B', + 'objectindex' => '0', + 'format' => '0', +)) +->values(array( + 'lid' => '1692', + 'objectid' => '14', + 'type' => 'term', + 'property' => 'name', + 'objectindex' => '14', + 'format' => '0', +)) +->values(array( + 'lid' => '1693', + 'objectid' => '15', + 'type' => 'term', + 'property' => 'name', + 'objectindex' => '15', + 'format' => '0', +)) +->values(array( + 'lid' => '1694', + 'objectid' => '14', + 'type' => 'term', + 'property' => 'description', + 'objectindex' => '14', + 'format' => '0', +)) ->execute(); - $connection->schema()->createTable('i18n_variable', array( 'fields' => array( 'name' => array( @@ -10329,7 +10502,6 @@ 'value' => 's:1:"1";', )) ->execute(); - $connection->schema()->createTable('imagecache_action', array( 'fields' => array( 'actionid' => array( @@ -10415,7 +10587,6 @@ 'data' => 'a:3:{s:7:"degrees";s:2:"55";s:6:"random";i:0;s:7:"bgcolor";s:0:"";}', )) ->execute(); - $connection->schema()->createTable('imagecache_preset', array( 'fields' => array( 'presetid' => array( @@ -10450,7 +10621,6 @@ 'presetname' => 'big_blue_cheese', )) ->execute(); - $connection->schema()->createTable('languages', array( 'fields' => array( 'language' => array( @@ -10586,7 +10756,6 @@ 'javascript' => '', )) ->execute(); - $connection->schema()->createTable('locales_source', array( 'fields' => array( 'lid' => array( @@ -15018,13 +15187,6 @@ 'source' => 'An example multi-valued decimal field.', 'version' => '1', )) -->values(array( - 'lid' => '626', - 'location' => 'field:test_planet-field_test_text_single_checkbox:widget_label', - 'textgroup' => 'cck', - 'source' => 'Text Single Checkbox Field', - 'version' => '1', -)) ->values(array( 'lid' => '627', 'location' => 'field:test_planet-field_test_text_single_checkbox:widget_description', @@ -22396,8 +22558,98 @@ 'source' => 'Translation test', 'version' => '1', )) +->values(array( + 'lid' => '1680', + 'location' => 'field:employee-field_company:widget_label', + 'textgroup' => 'cck', + 'source' => 'Company', + 'version' => '1', +)) +->values(array( + 'lid' => '1681', + 'location' => 'field:employee-field_commander:widget_label', + 'textgroup' => 'cck', + 'source' => 'Commanding Officer', + 'version' => '1', +)) +->values(array( + 'lid' => '1682', + 'location' => 'field:employee-field_company_2:widget_label', + 'textgroup' => 'cck', + 'source' => 'Company 2', + 'version' => '1', +)) +->values(array( + 'lid' => '1683', + 'location' => 'field:employee-field_company_3:widget_label', + 'textgroup' => 'cck', + 'source' => 'Company 3', + 'version' => '1', +)) +->values(array( + 'lid' => '1684', + 'location' => 'field:page-field_reference:widget_label', + 'textgroup' => 'cck', + 'source' => 'Reference', + 'version' => '1', +)) +->values(array( + 'lid' => '1685', + 'location' => 'field:page-field_reference_2:widget_label', + 'textgroup' => 'cck', + 'source' => 'Reference', + 'version' => '1', +)) +->values(array( + 'lid' => '1686', + 'location' => 'field:story-field_test_string_selectlist:widget_label', + 'textgroup' => 'cck', + 'source' => 'String Select List Field', + 'version' => '1', +)) +->values(array( + 'lid' => '1689', + 'location' => 'field:test_planet-field_test_text_single_checkbox:widget_label', + 'textgroup' => 'cck', + 'source' => 'Text Single Checkbox Field', + 'version' => '1', +)) +->values(array( + 'lid' => '1690', + 'location' => 'field:field_test_string_selectlist:option_A', + 'textgroup' => 'cck', + 'source' => 'Black', + 'version' => '1', +)) +->values(array( + 'lid' => '1691', + 'location' => 'field:field_test_string_selectlist:option_B', + 'textgroup' => 'cck', + 'source' => 'White', + 'version' => '1', +)) +->values(array( + 'lid' => '1692', + 'location' => 'term:14:name', + 'textgroup' => 'taxonomy', + 'source' => 'Talos IV', + 'version' => '1', +)) +->values(array( + 'lid' => '1693', + 'location' => 'term:15:name', + 'textgroup' => 'taxonomy', + 'source' => 'Vulcan', + 'version' => '1', +)) +->values(array( + 'lid' => '1694', + 'location' => 'term:14:description', + 'textgroup' => 'taxonomy', + 'source' => 'The home of Captain Christopher Pike.', + 'version' => '1', +)) ->execute(); - $connection->schema()->createTable('locales_target', array( 'fields' => array( 'lid' => array( @@ -27002,7 +27254,7 @@ )) ->values(array( 'lid' => '575', - 'translation' => 'fr - An example text field.', + 'translation' => 'fr - An example text field.', 'language' => 'fr', 'plid' => '0', 'plural' => '0', @@ -27114,7 +27366,7 @@ )) ->values(array( 'lid' => '589', - 'translation' => 'fr - An example image field.', + 'translation' => 'fr - An example file field.', 'language' => 'fr', 'plid' => '0', 'plural' => '0', @@ -27232,6 +27484,14 @@ 'plural' => '0', 'i18n_status' => '0', )) +->values(array( + 'lid' => '607', + 'translation' => 'fr - 1.234', + 'language' => 'fr', + 'plid' => '0', + 'plural' => '0', + 'i18n_status' => '0', +)) ->values(array( 'lid' => '608', 'translation' => 'fr - Integer Select List Field', @@ -27248,6 +27508,22 @@ 'plural' => '0', 'i18n_status' => '0', )) +->values(array( + 'lid' => '611', + 'translation' => 'fr - 2341', + 'language' => 'fr', + 'plid' => '0', + 'plural' => '0', + 'i18n_status' => '0', +)) +->values(array( + 'lid' => '613', + 'translation' => 'fr - 4123', + 'language' => 'fr', + 'plid' => '0', + 'plural' => '0', + 'i18n_status' => '0', +)) ->values(array( 'lid' => '614', 'translation' => 'fr - Text Single Checkbox Field', @@ -27344,14 +27620,6 @@ 'plural' => '0', 'i18n_status' => '0', )) -->values(array( - 'lid' => '626', - 'translation' => 'fr - Text Single Checkbox Field', - 'language' => 'fr', - 'plid' => '0', - 'plural' => '0', - 'i18n_status' => '0', -)) ->values(array( 'lid' => '627', 'translation' => 'fr - An example text field using a single on/off checkbox.', @@ -27440,6 +27708,14 @@ 'plural' => '0', 'i18n_status' => '0', )) +->values(array( + 'lid' => '1672', + 'translation' => 'fr - Type', + 'language' => 'fr', + 'plid' => '0', + 'plural' => '0', + 'i18n_status' => '0', +)) ->values(array( 'lid' => '1678', 'translation' => 'fr - I really, really, really love migrating ', @@ -27448,6 +27724,30 @@ 'plural' => '0', 'i18n_status' => '0', )) +->values(array( + 'lid' => '1690', + 'translation' => 'Noir', + 'language' => 'fr', + 'plid' => '0', + 'plural' => '0', + 'i18n_status' => '0', +)) +->values(array( + 'lid' => '1692', + 'translation' => 'fr - Talos IV', + 'language' => 'fr', + 'plid' => '0', + 'plural' => '0', + 'i18n_status' => '0', +)) +->values(array( + 'lid' => '1694', + 'translation' => 'fr - The home of Captain Christopher Pike.', + 'language' => 'fr', + 'plid' => '0', + 'plural' => '0', + 'i18n_status' => '0', +)) ->values(array( 'lid' => '66', 'translation' => 'zu - CCK - Aucune Intégration aux Vues', @@ -27528,6 +27828,22 @@ 'plural' => '0', 'i18n_status' => '0', )) +->values(array( + 'lid' => '607', + 'translation' => 'zu - 1.234', + 'language' => 'zu', + 'plid' => '0', + 'plural' => '0', + 'i18n_status' => '0', +)) +->values(array( + 'lid' => '611', + 'translation' => 'zu - 2341', + 'language' => 'zu', + 'plid' => '0', + 'plural' => '0', + 'i18n_status' => '0', +)) ->values(array( 'lid' => '621', 'translation' => 'zu - Hello', @@ -27544,8 +27860,47 @@ 'plural' => '0', 'i18n_status' => '0', )) +->values(array( + 'lid' => '1672', + 'translation' => 'zu - Type', + 'language' => 'zu', + 'plid' => '0', + 'plural' => '0', + 'i18n_status' => '0', +)) +->values(array( + 'lid' => '1690', + 'translation' => 'Okumnyama', + 'language' => 'zu', + 'plid' => '0', + 'plural' => '0', + 'i18n_status' => '0', +)) +->values(array( + 'lid' => '1691', + 'translation' => 'Mhlophe', + 'language' => 'zu', + 'plid' => '0', + 'plural' => '0', + 'i18n_status' => '0', +)) +->values(array( + 'lid' => '1693', + 'translation' => 'zu - Vulcan', + 'language' => 'zu', + 'plid' => '0', + 'plural' => '0', + 'i18n_status' => '0', +)) +->values(array( + 'lid' => '1694', + 'translation' => 'zu - The home of Captain Christopher Pike.', + 'language' => 'zu', + 'plid' => '0', + 'plural' => '0', + 'i18n_status' => '0', +)) ->execute(); - $connection->schema()->createTable('menu_custom', array( 'fields' => array( 'menu_name' => array( @@ -27594,7 +27949,6 @@ 'description' => 'Secondary links are often used for pages like legal notices, contact details, and other secondary navigation items that play a lesser role than primary links', )) ->execute(); - $connection->schema()->createTable('menu_links', array( 'fields' => array( 'menu_name' => array( @@ -34083,7 +34437,6 @@ 'updated' => '0', )) ->execute(); - $connection->schema()->createTable('menu_router', array( 'fields' => array( 'path' => array( @@ -40632,6 +40985,28 @@ 'weight' => '0', 'file' => 'sites/all/modules/i18n/i18n.admin.inc', )) +->values(array( + 'path' => 'admin/settings/language/i18n/variables', + 'load_functions' => '', + 'to_arg_functions' => '', + 'access_callback' => 'user_access', + 'access_arguments' => 'a:1:{i:0;s:29:"administer site configuration";}', + 'page_callback' => 'drupal_get_form', + 'page_arguments' => 'a:1:{i:0;s:25:"i18n_admin_variables_form";}', + 'fit' => '31', + 'number_parts' => '5', + 'tab_parent' => 'admin/settings/language/i18n', + 'tab_root' => 'admin/settings/language', + 'title' => 'Variables', + 'title_callback' => 't', + 'title_arguments' => '', + 'type' => '128', + 'block_callback' => '', + 'description' => 'Multilingual variables.', + 'position' => '', + 'weight' => '0', + 'file' => 'sites/all/modules/i18n/i18n.admin.inc', +)) ->values(array( 'path' => 'admin/settings/language/overview', 'load_functions' => '', @@ -43273,7 +43648,6 @@ 'file' => '', )) ->execute(); - $connection->schema()->createTable('node', array( 'fields' => array( 'nid' => array( @@ -43733,8 +44107,41 @@ 'tnid' => '12', 'translate' => '0', )) +->values(array( + 'nid' => '21', + 'vid' => '2002', + 'type' => 'employee', + 'language' => 'en', + 'title' => 'John Smith - EN', + 'uid' => '1', + 'status' => '1', + 'created' => '1534014650', + 'changed' => '1534014650', + 'comment' => '2', + 'promote' => '1', + 'moderate' => '0', + 'sticky' => '0', + 'tnid' => '21', + 'translate' => '0', +)) +->values(array( + 'nid' => '22', + 'vid' => '2003', + 'type' => 'employee', + 'language' => 'fr', + 'title' => 'John Smith - FR', + 'uid' => '1', + 'status' => '1', + 'created' => '1534014687', + 'changed' => '1534014687', + 'comment' => '2', + 'promote' => '1', + 'moderate' => '0', + 'sticky' => '0', + 'tnid' => '21', + 'translate' => '0', +)) ->execute(); - $connection->schema()->createTable('node_access', array( 'fields' => array( 'nid' => array( @@ -43805,7 +44212,6 @@ 'grant_delete' => '0', )) ->execute(); - $connection->schema()->createTable('node_comment_statistics', array( 'fields' => array( 'nid' => array( @@ -43939,8 +44345,21 @@ 'last_comment_uid' => '1', 'comment_count' => '3', )) +->values(array( + 'nid' => '21', + 'last_comment_timestamp' => '1534014729', + 'last_comment_name' => '', + 'last_comment_uid' => '1', + 'comment_count' => '1', +)) +->values(array( + 'nid' => '22', + 'last_comment_timestamp' => '1534014763', + 'last_comment_name' => '', + 'last_comment_uid' => '1', + 'comment_count' => '1', +)) ->execute(); - $connection->schema()->createTable('node_counter', array( 'fields' => array( 'nid' => array( @@ -44074,8 +44493,19 @@ 'daycount' => '4', 'timestamp' => '1501955803', )) +->values(array( + 'nid' => '21', + 'totalcount' => '3', + 'daycount' => '3', + 'timestamp' => '1534014729', +)) +->values(array( + 'nid' => '22', + 'totalcount' => '3', + 'daycount' => '3', + 'timestamp' => '1534014763', +)) ->execute(); - $connection->schema()->createTable('node_revisions', array( 'fields' => array( 'nid' => array( @@ -44402,8 +44832,29 @@ 'timestamp' => '1390095702', 'format' => '1', )) +->values(array( + 'nid' => '21', + 'vid' => '2002', + 'uid' => '1', + 'title' => 'John Smith - EN', + 'body' => 'This is an English Bio text for employee John Smith. There is also a French translation to this node. Both language versions have comments.', + 'teaser' => 'This is an English Bio text for employee John Smith. There is also a French translation to this node. Both language versions have comments.', + 'log' => '', + 'timestamp' => '1534014650', + 'format' => '1', +)) +->values(array( + 'nid' => '22', + 'vid' => '2003', + 'uid' => '1', + 'title' => 'John Smith - FR', + 'body' => 'This is a French Bio text for employee John Smith. The original node is in English. Both language versions have comments.', + 'teaser' => 'This is a French Bio text for employee John Smith. The original node is in English. Both language versions have comments.', + 'log' => '', + 'timestamp' => '1534014687', + 'format' => '1', +)) ->execute(); - $connection->schema()->createTable('node_type', array( 'fields' => array( 'type' => array( @@ -44703,7 +45154,6 @@ 'orig_type' => 'test_story', )) ->execute(); - $connection->schema()->createTable('permission', array( 'fields' => array( 'pid' => array( @@ -44769,7 +45219,6 @@ 'tid' => '0', )) ->execute(); - $connection->schema()->createTable('profile_fields', array( 'fields' => array( 'fid' => array( @@ -45002,7 +45451,6 @@ 'options' => '', )) ->execute(); - $connection->schema()->createTable('profile_values', array( 'fields' => array( 'fid' => array( @@ -45219,7 +45667,6 @@ 'value' => '1', )) ->execute(); - $connection->schema()->createTable('role', array( 'fields' => array( 'rid' => array( @@ -45267,7 +45714,6 @@ 'name' => 'migrate test role 3 that is longer than thirty two characters', )) ->execute(); - $connection->schema()->createTable('semaphore', array( 'fields' => array( 'name' => array( @@ -46573,7 +47019,6 @@ 'info' => 'a:13:{s:4:"name";s:10:"Pushbutton";s:11:"description";s:52:"Tabled, multi-column theme in blue and orange tones.";s:7:"version";s:4:"6.38";s:4:"core";s:3:"6.x";s:6:"engine";s:11:"phptemplate";s:7:"project";s:6:"drupal";s:9:"datestamp";s:10:"1456343372";s:7:"regions";a:5:{s:4:"left";s:12:"Left sidebar";s:5:"right";s:13:"Right sidebar";s:7:"content";s:7:"Content";s:6:"header";s:6:"Header";s:6:"footer";s:6:"Footer";}s:8:"features";a:10:{i:0;s:20:"comment_user_picture";i:1;s:7:"favicon";i:2;s:7:"mission";i:3;s:4:"logo";i:4;s:4:"name";i:5;s:17:"node_user_picture";i:6;s:6:"search";i:7;s:6:"slogan";i:8;s:13:"primary_links";i:9;s:15:"secondary_links";}s:11:"stylesheets";a:1:{s:3:"all";a:1:{s:9:"style.css";s:27:"themes/pushbutton/style.css";}}s:7:"scripts";a:1:{s:9:"script.js";s:27:"themes/pushbutton/script.js";}s:10:"screenshot";s:32:"themes/pushbutton/screenshot.png";s:3:"php";s:5:"4.3.5";}', )) ->execute(); - $connection->schema()->createTable('term_data', array( 'fields' => array( 'tid' => array( @@ -46707,8 +47152,70 @@ 'language' => '', 'trid' => '0', )) +->values(array( + 'tid' => '9', + 'vid' => '3', + 'name' => 'fr - term 4 of vocabulary 3', + 'description' => '', + 'weight' => '0', + 'language' => 'fr', + 'trid' => '1', +)) +->values(array( + 'tid' => '10', + 'vid' => '3', + 'name' => 'zu - term 4 of vocabulary 3', + 'description' => '', + 'weight' => '0', + 'language' => 'zu', + 'trid' => '1', +)) +->values(array( + 'tid' => '11', + 'vid' => '3', + 'name' => 'term 7 of vocabulary 3', + 'description' => '', + 'weight' => '0', + 'language' => 'en', + 'trid' => '2', +)) +->values(array( + 'tid' => '12', + 'vid' => '3', + 'name' => 'fr - term 7 of vocabulary 3', + 'description' => '', + 'weight' => '0', + 'language' => 'fr', + 'trid' => '2', +)) +->values(array( + 'tid' => '13', + 'vid' => '3', + 'name' => 'zu - term 7 of vocabulary 3', + 'description' => '', + 'weight' => '0', + 'language' => 'zu', + 'trid' => '2', +)) +->values(array( + 'tid' => '14', + 'vid' => '5', + 'name' => 'Talos IV', + 'description' => 'The home of Captain Christopher Pike.', + 'weight' => '0', + 'language' => '', + 'trid' => '0', +)) +->values(array( + 'tid' => '15', + 'vid' => '5', + 'name' => 'Vulcan', + 'description' => '', + 'weight' => '0', + 'language' => '', + 'trid' => '0', +)) ->execute(); - $connection->schema()->createTable('term_hierarchy', array( 'fields' => array( 'tid' => array( @@ -46758,6 +47265,34 @@ 'tid' => '8', 'parent' => '0', )) +->values(array( + 'tid' => '9', + 'parent' => '0', +)) +->values(array( + 'tid' => '10', + 'parent' => '0', +)) +->values(array( + 'tid' => '11', + 'parent' => '0', +)) +->values(array( + 'tid' => '12', + 'parent' => '0', +)) +->values(array( + 'tid' => '13', + 'parent' => '0', +)) +->values(array( + 'tid' => '14', + 'parent' => '0', +)) +->values(array( + 'tid' => '15', + 'parent' => '0', +)) ->values(array( 'tid' => '3', 'parent' => '2', @@ -46775,7 +47310,6 @@ 'parent' => '5', )) ->execute(); - $connection->schema()->createTable('term_node', array( 'fields' => array( 'nid' => array( @@ -46849,7 +47383,6 @@ 'tid' => '8', )) ->execute(); - $connection->schema()->createTable('term_relation', array( 'fields' => array( 'trid' => array( @@ -47013,7 +47546,6 @@ 'weight' => '0', )) ->execute(); - $connection->schema()->createTable('url_alias', array( 'fields' => array( 'pid' => array( @@ -47103,7 +47635,6 @@ 'language' => '', )) ->execute(); - $connection->schema()->createTable('users', array( 'fields' => array( 'uid' => array( @@ -47425,7 +47956,6 @@ 'timezone_id' => '0', )) ->execute(); - $connection->schema()->createTable('users_roles', array( 'fields' => array( 'uid' => array( @@ -47492,7 +48022,6 @@ 'rid' => '5', )) ->execute(); - $connection->schema()->createTable('variable', array( 'fields' => array( 'name' => array( @@ -48356,7 +48885,7 @@ )) ->values(array( 'name' => 'i18ntaxonomy_vocabulary', - 'value' => 'a:2:{i:1;s:1:"3";i:2;s:1:"2";}', + 'value' => 'a:4:{i:1;s:1:"3";i:2;s:1:"2";i:3;s:1:"3";i:5;s:1:"1";}', )) ->values(array( 'name' => 'i18n_lock_node_article', @@ -48759,7 +49288,6 @@ 'value' => 's:1:"1";', )) ->execute(); - $connection->schema()->createTable('vocabulary', array( 'fields' => array( 'vid' => array( @@ -48959,7 +49487,6 @@ 'language' => '', )) ->execute(); - $connection->schema()->createTable('vocabulary_node_types', array( 'fields' => array( 'vid' => array( @@ -49017,7 +49544,6 @@ 'type' => 'story', )) ->execute(); - $connection->schema()->createTable('watchdog', array( 'fields' => array( 'wid' => array( diff --git a/web/core/modules/migrate_drupal/tests/fixtures/drupal7.php b/web/core/modules/migrate_drupal/tests/fixtures/drupal7.php index c41b20ee31afe3f3d7eebd1c001dac8873246ca3..68171683d8277dd6e6700ef3a85fddf33671a74c 100644 --- a/web/core/modules/migrate_drupal/tests/fixtures/drupal7.php +++ b/web/core/modules/migrate_drupal/tests/fixtures/drupal7.php @@ -371,7 +371,6 @@ 'timestamp' => '1444945246', )) ->execute(); - $connection->schema()->createTable('actions', array( 'fields' => array( 'aid' => array( @@ -545,7 +544,6 @@ 'label' => 'Block current user', )) ->execute(); - $connection->schema()->createTable('aggregator_category', array( 'fields' => array( 'cid' => array( @@ -735,7 +733,6 @@ 'block' => '5', )) ->execute(); - $connection->schema()->createTable('aggregator_item', array( 'fields' => array( 'iid' => array( @@ -900,7 +897,6 @@ 'guid' => 'post:18829', )) ->execute(); - $connection->schema()->createTable('authmap', array( 'fields' => array( 'aid' => array( @@ -1036,6 +1032,12 @@ 'size' => 'normal', 'default' => '1', ), + 'i18n_mode' => array( + 'type' => 'int', + 'not null' => TRUE, + 'size' => 'normal', + 'default' => '0', + ), ), 'primary key' => array( 'bid', @@ -1057,6 +1059,7 @@ 'pages', 'title', 'cache', + 'i18n_mode', )) ->values(array( 'bid' => '1', @@ -1071,6 +1074,7 @@ 'pages' => '', 'title' => '', 'cache' => '-1', + 'i18n_mode' => '0', )) ->values(array( 'bid' => '2', @@ -1085,6 +1089,7 @@ 'pages' => '', 'title' => '', 'cache' => '-1', + 'i18n_mode' => '0', )) ->values(array( 'bid' => '3', @@ -1099,6 +1104,7 @@ 'pages' => '', 'title' => '', 'cache' => '-1', + 'i18n_mode' => '0', )) ->values(array( 'bid' => '4', @@ -1111,8 +1117,9 @@ 'custom' => '0', 'visibility' => '0', 'pages' => '', - 'title' => '', + 'title' => 'User login title', 'cache' => '-1', + 'i18n_mode' => '1', )) ->values(array( 'bid' => '5', @@ -1127,6 +1134,7 @@ 'pages' => '', 'title' => '', 'cache' => '-1', + 'i18n_mode' => '0', )) ->values(array( 'bid' => '6', @@ -1141,6 +1149,7 @@ 'pages' => '', 'title' => '', 'cache' => '-1', + 'i18n_mode' => '0', )) ->values(array( 'bid' => '7', @@ -1155,6 +1164,7 @@ 'pages' => '', 'title' => '', 'cache' => '-1', + 'i18n_mode' => '0', )) ->values(array( 'bid' => '8', @@ -1169,6 +1179,7 @@ 'pages' => '', 'title' => '', 'cache' => '-1', + 'i18n_mode' => '0', )) ->values(array( 'bid' => '9', @@ -1183,6 +1194,7 @@ 'pages' => '', 'title' => '', 'cache' => '-1', + 'i18n_mode' => '0', )) ->values(array( 'bid' => '10', @@ -1195,8 +1207,9 @@ 'custom' => '0', 'visibility' => '0', 'pages' => '', - 'title' => '', + 'title' => 'User login title', 'cache' => '-1', + 'i18n_mode' => '1', )) ->values(array( 'bid' => '11', @@ -1211,6 +1224,7 @@ 'pages' => '', 'title' => '', 'cache' => '-1', + 'i18n_mode' => '0', )) ->values(array( 'bid' => '12', @@ -1225,6 +1239,7 @@ 'pages' => '', 'title' => '', 'cache' => '-1', + 'i18n_mode' => '0', )) ->values(array( 'bid' => '13', @@ -1239,6 +1254,7 @@ 'pages' => '', 'title' => '', 'cache' => '1', + 'i18n_mode' => '0', )) ->values(array( 'bid' => '14', @@ -1253,6 +1269,7 @@ 'pages' => '', 'title' => '', 'cache' => '-1', + 'i18n_mode' => '0', )) ->values(array( 'bid' => '15', @@ -1267,6 +1284,7 @@ 'pages' => '', 'title' => '', 'cache' => '1', + 'i18n_mode' => '0', )) ->values(array( 'bid' => '16', @@ -1281,6 +1299,7 @@ 'pages' => '', 'title' => '', 'cache' => '-1', + 'i18n_mode' => '0', )) ->values(array( 'bid' => '17', @@ -1295,6 +1314,7 @@ 'pages' => '', 'title' => '', 'cache' => '-1', + 'i18n_mode' => '0', )) ->values(array( 'bid' => '18', @@ -1309,6 +1329,7 @@ 'pages' => '', 'title' => '', 'cache' => '-1', + 'i18n_mode' => '0', )) ->values(array( 'bid' => '19', @@ -1323,6 +1344,7 @@ 'pages' => '', 'title' => '', 'cache' => '-1', + 'i18n_mode' => '0', )) ->values(array( 'bid' => '20', @@ -1337,6 +1359,7 @@ 'pages' => '', 'title' => '', 'cache' => '1', + 'i18n_mode' => '0', )) ->values(array( 'bid' => '21', @@ -1351,6 +1374,7 @@ 'pages' => '', 'title' => '', 'cache' => '-1', + 'i18n_mode' => '0', )) ->values(array( 'bid' => '22', @@ -1365,6 +1389,7 @@ 'pages' => '', 'title' => '', 'cache' => '1', + 'i18n_mode' => '0', )) ->values(array( 'bid' => '23', @@ -1379,6 +1404,7 @@ 'pages' => '', 'title' => '', 'cache' => '-1', + 'i18n_mode' => '0', )) ->values(array( 'bid' => '24', @@ -1393,6 +1419,7 @@ 'pages' => '', 'title' => '', 'cache' => '-1', + 'i18n_mode' => '0', )) ->values(array( 'bid' => '25', @@ -1407,6 +1434,7 @@ 'pages' => '', 'title' => '', 'cache' => '-1', + 'i18n_mode' => '0', )) ->values(array( 'bid' => '26', @@ -1421,6 +1449,7 @@ 'pages' => '', 'title' => '', 'cache' => '-1', + 'i18n_mode' => '0', )) ->values(array( 'bid' => '27', @@ -1435,6 +1464,7 @@ 'pages' => '', 'title' => '', 'cache' => '-1', + 'i18n_mode' => '0', )) ->values(array( 'bid' => '28', @@ -1449,6 +1479,7 @@ 'pages' => '', 'title' => '', 'cache' => '-1', + 'i18n_mode' => '0', )) ->values(array( 'bid' => '29', @@ -1463,6 +1494,7 @@ 'pages' => '', 'title' => '', 'cache' => '-1', + 'i18n_mode' => '0', )) ->values(array( 'bid' => '30', @@ -1477,6 +1509,7 @@ 'pages' => '', 'title' => '', 'cache' => '-1', + 'i18n_mode' => '0', )) ->values(array( 'bid' => '31', @@ -1491,6 +1524,7 @@ 'pages' => '', 'title' => '', 'cache' => '1', + 'i18n_mode' => '0', )) ->values(array( 'bid' => '32', @@ -1505,6 +1539,7 @@ 'pages' => '', 'title' => '', 'cache' => '5', + 'i18n_mode' => '0', )) ->values(array( 'bid' => '33', @@ -1519,6 +1554,7 @@ 'pages' => '', 'title' => '', 'cache' => '-1', + 'i18n_mode' => '0', )) ->values(array( 'bid' => '34', @@ -1533,6 +1569,7 @@ 'pages' => '', 'title' => '', 'cache' => '-2', + 'i18n_mode' => '0', )) ->values(array( 'bid' => '35', @@ -1547,6 +1584,7 @@ 'pages' => '', 'title' => '', 'cache' => '-2', + 'i18n_mode' => '0', )) ->values(array( 'bid' => '36', @@ -1561,6 +1599,7 @@ 'pages' => '', 'title' => '', 'cache' => '1', + 'i18n_mode' => '0', )) ->values(array( 'bid' => '37', @@ -1575,6 +1614,7 @@ 'pages' => '', 'title' => '', 'cache' => '5', + 'i18n_mode' => '0', )) ->values(array( 'bid' => '38', @@ -1589,6 +1629,7 @@ 'pages' => '', 'title' => '', 'cache' => '-1', + 'i18n_mode' => '0', )) ->values(array( 'bid' => '39', @@ -1603,6 +1644,7 @@ 'pages' => '', 'title' => '', 'cache' => '-2', + 'i18n_mode' => '0', )) ->values(array( 'bid' => '40', @@ -1617,6 +1659,7 @@ 'pages' => '', 'title' => '', 'cache' => '-2', + 'i18n_mode' => '0', )) ->values(array( 'bid' => '41', @@ -1631,6 +1674,7 @@ 'pages' => '', 'title' => '', 'cache' => '-1', + 'i18n_mode' => '0', )) ->values(array( 'bid' => '42', @@ -1645,6 +1689,7 @@ 'pages' => '', 'title' => '', 'cache' => '-1', + 'i18n_mode' => '0', )) ->values(array( 'bid' => '43', @@ -1659,6 +1704,7 @@ 'pages' => '', 'title' => '', 'cache' => '-1', + 'i18n_mode' => '0', )) ->values(array( 'bid' => '44', @@ -1673,6 +1719,7 @@ 'pages' => '', 'title' => '', 'cache' => '-1', + 'i18n_mode' => '0', )) ->values(array( 'bid' => '45', @@ -1687,6 +1734,7 @@ 'pages' => '', 'title' => 'Mildly amusing limerick of the day', 'cache' => '-1', + 'i18n_mode' => '0', )) ->values(array( 'bid' => '46', @@ -1701,6 +1749,7 @@ 'pages' => '', 'title' => 'Mildly amusing limerick of the day', 'cache' => '-1', + 'i18n_mode' => '0', )) ->values(array( 'bid' => '47', @@ -1715,6 +1764,7 @@ 'pages' => '', 'title' => '', 'cache' => '1', + 'i18n_mode' => '0', )) ->values(array( 'bid' => '48', @@ -1729,9 +1779,39 @@ 'pages' => '', 'title' => '', 'cache' => '1', + 'i18n_mode' => '0', +)) +->values(array( + 'bid' => '49', + 'module' => 'locale', + 'delta' => 'language_content', + 'theme' => 'bartik', + 'status' => '0', + 'weight' => '0', + 'region' => '-1', + 'custom' => '0', + 'visibility' => '0', + 'pages' => '', + 'title' => '', + 'cache' => '-1', + 'i18n_mode' => '0', +)) +->values(array( + 'bid' => '50', + 'module' => 'locale', + 'delta' => 'language_content', + 'theme' => 'seven', + 'status' => '0', + 'weight' => '0', + 'region' => '-1', + 'custom' => '0', + 'visibility' => '0', + 'pages' => '', + 'title' => '', + 'cache' => '-1', + 'i18n_mode' => '0', )) ->execute(); - $connection->schema()->createTable('block_custom', array( 'fields' => array( 'bid' => array( @@ -1777,7 +1857,6 @@ 'format' => 'filtered_html', )) ->execute(); - $connection->schema()->createTable('block_node_type', array( 'fields' => array( 'module' => array( @@ -1843,7 +1922,6 @@ 'rid' => '2', )) ->execute(); - $connection->schema()->createTable('blocked_ips', array( 'fields' => array( 'iid' => array( @@ -1875,7 +1953,6 @@ 'ip' => '111.111.111.111', )) ->execute(); - $connection->schema()->createTable('book', array( 'fields' => array( 'mlid' => array( @@ -1907,33 +1984,32 @@ )); $connection->insert('book') - ->fields(array( - 'mlid', - 'nid', - 'bid', - )) - ->values(array( - 'mlid' => '480', - 'nid' => '4', - 'bid' => '4', - )) - ->values(array( - 'mlid' => '481', - 'nid' => '6', - 'bid' => '4', - )) - ->values(array( - 'mlid' => '482', - 'nid' => '2', - 'bid' => '4', - )) - ->values(array( - 'mlid' => '483', - 'nid' => '1', - 'bid' => '8', - )) - ->execute(); - +->fields(array( + 'mlid', + 'nid', + 'bid', +)) +->values(array( + 'mlid' => '480', + 'nid' => '4', + 'bid' => '4', +)) +->values(array( + 'mlid' => '481', + 'nid' => '6', + 'bid' => '4', +)) +->values(array( + 'mlid' => '482', + 'nid' => '2', + 'bid' => '4', +)) +->values(array( + 'mlid' => '483', + 'nid' => '1', + 'bid' => '8', +)) +->execute(); $connection->schema()->createTable('cache', array( 'fields' => array( 'cid' => array( @@ -2352,6 +2428,49 @@ 'mysql_character_set' => 'utf8', )); +$connection->schema()->createTable('cache_variable', array( + 'fields' => array( + 'cid' => array( + 'type' => 'varchar', + 'not null' => TRUE, + 'length' => '255', + 'default' => '', + ), + 'data' => array( + 'type' => 'blob', + 'not null' => FALSE, + 'size' => 'big', + ), + 'expire' => array( + 'type' => 'int', + 'not null' => TRUE, + 'size' => 'normal', + 'default' => '0', + ), + 'created' => array( + 'type' => 'int', + 'not null' => TRUE, + 'size' => 'normal', + 'default' => '0', + ), + 'serialized' => array( + 'type' => 'int', + 'not null' => TRUE, + 'size' => 'small', + 'default' => '0', + ), + ), + 'primary key' => array( + 'cid', + ), + 'indexes' => array( + 'expire' => array( + 'expire', + ), + ), + 'mysql_character_set' => 'utf8', +)); + $connection->schema()->createTable('cache_views', array( 'fields' => array( 'cid' => array( @@ -2548,7 +2667,7 @@ 'name' => 'admin', 'mail' => '', 'homepage' => '', - 'language' => 'und', + 'language' => 'en', )) ->values(array( 'cid' => '2', @@ -2566,8 +2685,23 @@ 'homepage' => '', 'language' => 'en', )) +->values(array( + 'cid' => '3', + 'pid' => '0', + 'nid' => '3', + 'uid' => '1', + 'subject' => 'Comment to IS translation', + 'hostname' => '46.132.185.242', + 'created' => '1533031490', + 'changed' => '1533031490', + 'status' => '1', + 'thread' => '01/', + 'name' => 'admin', + 'mail' => '', + 'homepage' => '', + 'language' => 'is', +)) ->execute(); - $connection->schema()->createTable('contact', array( 'fields' => array( 'cid' => array( @@ -2629,7 +2763,6 @@ 'selected' => '1', )) ->execute(); - $connection->schema()->createTable('ctools_css_cache', array( 'fields' => array( 'cid' => array( @@ -2770,7 +2903,6 @@ 'locked' => '1', )) ->execute(); - $connection->schema()->createTable('date_formats', array( 'fields' => array( 'dfid' => array( @@ -3026,7 +3158,6 @@ 'locked' => '0', )) ->execute(); - $connection->schema()->createTable('entity_translation', array( 'fields' => array( 'entity_type' => array( @@ -3115,7 +3246,7 @@ 'entity_type' => 'comment', 'entity_id' => '1', 'revision_id' => '1', - 'language' => 'und', + 'language' => 'en', 'source' => '', 'uid' => '1', 'status' => '1', @@ -3123,6 +3254,30 @@ 'created' => '1421727536', 'changed' => '1421727536', )) +->values(array( + 'entity_type' => 'comment', + 'entity_id' => '1', + 'revision_id' => '1', + 'language' => 'fr', + 'source' => 'en', + 'uid' => '1', + 'status' => '0', + 'translate' => '0', + 'created' => '1531837764', + 'changed' => '1531837764', +)) +->values(array( + 'entity_type' => 'comment', + 'entity_id' => '1', + 'revision_id' => '1', + 'language' => 'is', + 'source' => 'en', + 'uid' => '2', + 'status' => '1', + 'translate' => '1', + 'created' => '1531838064', + 'changed' => '1531838064', +)) ->values(array( 'entity_type' => 'node', 'entity_id' => '1', @@ -3141,9 +3296,9 @@ 'revision_id' => '1', 'language' => 'fr', 'source' => 'en', - 'uid' => '1', + 'uid' => '2', 'status' => '1', - 'translate' => '0', + 'translate' => '1', 'created' => '1529615802', 'changed' => '1529615802', )) @@ -3154,7 +3309,7 @@ 'language' => 'is', 'source' => 'en', 'uid' => '1', - 'status' => '1', + 'status' => '0', 'translate' => '0', 'created' => '1529615813', 'changed' => '1529615813', @@ -3195,8 +3350,43 @@ 'created' => '1531663925', 'changed' => '1531663925', )) +->values(array( + 'entity_type' => 'taxonomy_term', + 'entity_id' => '4', + 'revision_id' => '4', + 'language' => 'en', + 'source' => '', + 'uid' => '1', + 'status' => '1', + 'translate' => '0', + 'created' => '1531922259', + 'changed' => '1531922259', +)) +->values(array( + 'entity_type' => 'taxonomy_term', + 'entity_id' => '4', + 'revision_id' => '4', + 'language' => 'fr', + 'source' => 'en', + 'uid' => '2', + 'status' => '1', + 'translate' => '1', + 'created' => '1531922267', + 'changed' => '1531922268', +)) +->values(array( + 'entity_type' => 'taxonomy_term', + 'entity_id' => '4', + 'revision_id' => '4', + 'language' => 'is', + 'source' => 'en', + 'uid' => '1', + 'status' => '0', + 'translate' => '0', + 'created' => '1531922278', + 'changed' => '1531922279', +)) ->execute(); - $connection->schema()->createTable('entity_translation_revision', array( 'fields' => array( 'entity_type' => array( @@ -4002,7 +4192,6 @@ 'deleted' => '0', )) ->execute(); - $connection->schema()->createTable('field_config_instance', array( 'fields' => array( 'id' => array( @@ -4673,8 +4862,16 @@ 'data' => 'a:6:{s:8:"required";b:0;s:5:"label";s:11:"Description";s:11:"description";s:0:"";s:8:"settings";a:5:{s:15:"text_processing";i:1;s:10:"hide_label";a:2:{s:4:"page";b:0;s:6:"entity";b:0;}s:15:"display_summary";i:0;s:18:"user_register_form";b:0;s:23:"entity_translation_sync";b:0;}s:6:"widget";a:4:{s:6:"weight";i:-5;s:4:"type";s:26:"text_textarea_with_summary";s:8:"settings";a:2:{s:4:"rows";i:20;s:12:"summary_rows";i:5;}s:6:"module";s:4:"text";}s:7:"display";a:1:{s:7:"default";a:4:{s:4:"type";s:6:"hidden";s:5:"label";s:5:"above";s:8:"settings";a:0:{}s:6:"weight";i:15;}}}', 'deleted' => '0', )) +->values(array( + 'id' => '71', + 'field_id' => '41', + 'field_name' => 'subject_field', + 'entity_type' => 'comment', + 'bundle' => 'comment_node_test_content_type', + 'data' => 'a:6:{s:5:"label";s:7:"Subject";s:11:"description";s:0:"";s:8:"required";b:1;s:8:"settings";a:4:{s:15:"text_processing";i:0;s:10:"hide_label";a:2:{s:4:"page";b:0;s:6:"entity";b:0;}s:18:"user_register_form";b:0;s:23:"entity_translation_sync";b:0;}s:6:"widget";a:4:{s:6:"weight";i:-5;s:4:"type";s:14:"text_textfield";s:8:"settings";a:1:{s:4:"size";i:60;}s:6:"module";s:4:"text";}s:7:"display";a:1:{s:7:"default";a:4:{s:4:"type";s:6:"hidden";s:5:"label";s:5:"above";s:8:"settings";a:0:{}s:6:"weight";i:1;}}}', + 'deleted' => '0', +)) ->execute(); - $connection->schema()->createTable('field_data_body', array( 'fields' => array( 'entity_type' => array( @@ -4783,7 +4980,6 @@ 'body_format' => 'filtered_html', )) ->execute(); - $connection->schema()->createTable('field_data_comment_body', array( 'fields' => array( 'entity_type' => array( @@ -4883,8 +5079,18 @@ 'comment_body_value' => 'TNG is better than DS9.', 'comment_body_format' => 'filtered_html', )) +->values(array( + 'entity_type' => 'comment', + 'bundle' => 'comment_node_article', + 'deleted' => '0', + 'entity_id' => '3', + 'revision_id' => '3', + 'language' => 'und', + 'delta' => '0', + 'comment_body_value' => 'This is a comment to an Icelandic translation.', + 'comment_body_format' => 'filtered_html', +)) ->execute(); - $connection->schema()->createTable('field_data_description_field', array( 'fields' => array( 'entity_type' => array( @@ -4972,7 +5178,10 @@ 'language', ), 'description_field_format' => array( - 'description_field_format', + array( + 'description_field_format', + '191', + ), ), ), 'mysql_character_set' => 'utf8', @@ -5023,12 +5232,35 @@ 'revision_id' => '4', 'language' => 'en', 'delta' => '0', - 'description_field_value' => 'The third term.', + 'description_field_value' => 'The third term in plain old English.', 'description_field_summary' => '', 'description_field_format' => 'full_html', )) +->values(array( + 'entity_type' => 'taxonomy_term', + 'bundle' => 'test_vocabulary', + 'deleted' => '0', + 'entity_id' => '4', + 'revision_id' => '4', + 'language' => 'fr', + 'delta' => '0', + 'description_field_value' => "The third term en français s'il vous plaît.", + 'description_field_summary' => '', + 'description_field_format' => 'filtered_html', +)) +->values(array( + 'entity_type' => 'taxonomy_term', + 'bundle' => 'test_vocabulary', + 'deleted' => '0', + 'entity_id' => '4', + 'revision_id' => '4', + 'language' => 'is', + 'delta' => '0', + 'description_field_value' => 'The third term á íslensku.', + 'description_field_summary' => '', + 'description_field_format' => 'plain_text', +)) ->execute(); - $connection->schema()->createTable('field_data_field_boolean', array( 'fields' => array( 'entity_type' => array( @@ -5111,7 +5343,6 @@ 'field_boolean_value' => '1', )) ->execute(); - $connection->schema()->createTable('field_data_field_date', array( 'fields' => array( 'entity_type' => array( @@ -5194,7 +5425,6 @@ 'field_date_value' => '2015-01-20 04:15:00', )) ->execute(); - $connection->schema()->createTable('field_data_field_date_with_end_time', array( 'fields' => array( 'entity_type' => array( @@ -5284,8 +5514,7 @@ 'field_date_with_end_time_value2' => '1421727300', )) ->execute(); - -$connection->schema()->createTable('field_data_field_datetime_without_time', array( +$connection->schema()->createTable('field_data_field_date_without_time', array( 'fields' => array( 'entity_type' => array( 'type' => 'varchar', @@ -5329,12 +5558,10 @@ 'size' => 'normal', 'unsigned' => TRUE, ), - 'field_datetime_without_time_value' => array( - 'mysql_type' => 'datetime', - 'pgsql_type' => 'timestamp without time zone', - 'sqlite_type' => 'varchar', - 'sqlsrv_type' => 'smalldatetime', + 'field_date_without_time_value' => array( + 'type' => 'varchar', 'not null' => FALSE, + 'length' => '100', ), ), 'primary key' => array( @@ -5347,7 +5574,7 @@ 'mysql_character_set' => 'utf8', )); -$connection->insert('field_data_field_datetime_without_time') +$connection->insert('field_data_field_date_without_time') ->fields(array( 'entity_type', 'bundle', @@ -5356,7 +5583,7 @@ 'revision_id', 'language', 'delta', - 'field_datetime_without_time_value', + 'field_date_without_time_value', )) ->values(array( 'entity_type' => 'node', @@ -5366,11 +5593,10 @@ 'revision_id' => '1', 'language' => 'und', 'delta' => '0', - 'field_datetime_without_time_value' => '2015-01-20 00:00:00', + 'field_date_without_time_value' => '2015-01-20T00:00:00', )) ->execute(); - -$connection->schema()->createTable('field_data_field_date_without_time', array( +$connection->schema()->createTable('field_data_field_datetime_without_time', array( 'fields' => array( 'entity_type' => array( 'type' => 'varchar', @@ -5414,10 +5640,13 @@ 'size' => 'normal', 'unsigned' => TRUE, ), - 'field_date_without_time_value' => array( - 'type' => 'varchar', + 'field_datetime_without_time_value' => array( + 'type' => 'datetime', 'not null' => FALSE, - 'length' => '100', + 'mysql_type' => 'datetime', + 'pgsql_type' => 'timestamp without time zone', + 'sqlite_type' => 'varchar', + 'sqlsrv_type' => 'smalldatetime', ), ), 'primary key' => array( @@ -5430,7 +5659,7 @@ 'mysql_character_set' => 'utf8', )); -$connection->insert('field_data_field_date_without_time') +$connection->insert('field_data_field_datetime_without_time') ->fields(array( 'entity_type', 'bundle', @@ -5439,7 +5668,7 @@ 'revision_id', 'language', 'delta', - 'field_date_without_time_value', + 'field_datetime_without_time_value', )) ->values(array( 'entity_type' => 'node', @@ -5449,10 +5678,9 @@ 'revision_id' => '1', 'language' => 'und', 'delta' => '0', - 'field_date_without_time_value' => '2015-01-20T00:00:00', + 'field_datetime_without_time_value' => '2015-01-20 00:00:00', )) ->execute(); - $connection->schema()->createTable('field_data_field_email', array( 'fields' => array( 'entity_type' => array( @@ -5545,7 +5773,6 @@ 'field_email_email' => 'another@example.com', )) ->execute(); - $connection->schema()->createTable('field_data_field_file', array( 'fields' => array( 'entity_type' => array( @@ -5657,7 +5884,6 @@ 'field_file_description' => 'file desc', )) ->execute(); - $connection->schema()->createTable('field_data_field_float', array( 'fields' => array( 'entity_type' => array( @@ -5741,7 +5967,6 @@ 'field_float_value' => '1', )) ->execute(); - $connection->schema()->createTable('field_data_field_float_list', array( 'fields' => array( 'entity_type' => array( @@ -5847,7 +6072,6 @@ 'field_float_list_value' => '3.1416', )) ->execute(); - $connection->schema()->createTable('field_data_field_image', array( 'fields' => array( 'entity_type' => array( @@ -6044,7 +6268,6 @@ 'field_images_height' => '93', )) ->execute(); - $connection->schema()->createTable('field_data_field_integer', array( 'fields' => array( 'entity_type' => array( @@ -6122,10 +6345,30 @@ 'deleted' => '0', 'entity_id' => '1', 'revision_id' => '1', - 'language' => 'und', + 'language' => 'en', 'delta' => '0', 'field_integer_value' => '1000000', )) +->values(array( + 'entity_type' => 'comment', + 'bundle' => 'comment_node_test_content_type', + 'deleted' => '0', + 'entity_id' => '1', + 'revision_id' => '1', + 'language' => 'fr', + 'delta' => '0', + 'field_integer_value' => '2000000', +)) +->values(array( + 'entity_type' => 'comment', + 'bundle' => 'comment_node_test_content_type', + 'deleted' => '0', + 'entity_id' => '1', + 'revision_id' => '1', + 'language' => 'is', + 'delta' => '0', + 'field_integer_value' => '3000000', +)) ->values(array( 'entity_type' => 'node', 'bundle' => 'test_content_type', @@ -6196,8 +6439,27 @@ 'delta' => '0', 'field_integer_value' => '6', )) +->values(array( + 'entity_type' => 'taxonomy_term', + 'bundle' => 'test_vocabulary', + 'deleted' => '0', + 'entity_id' => '4', + 'revision_id' => '4', + 'language' => 'fr', + 'delta' => '0', + 'field_integer_value' => '5', +)) +->values(array( + 'entity_type' => 'taxonomy_term', + 'bundle' => 'test_vocabulary', + 'deleted' => '0', + 'entity_id' => '4', + 'revision_id' => '4', + 'language' => 'is', + 'delta' => '0', + 'field_integer_value' => '4', +)) ->execute(); - $connection->schema()->createTable('field_data_field_integer_list', array( 'fields' => array( 'entity_type' => array( @@ -6280,7 +6542,6 @@ 'field_integer_list_value' => '7', )) ->execute(); - $connection->schema()->createTable('field_data_field_link', array( 'fields' => array( 'entity_type' => array( @@ -6401,7 +6662,6 @@ 'field_link_attributes' => 'a:1:{s:5:"title";s:0:"";}', )) ->execute(); - $connection->schema()->createTable('field_data_field_long_text', array( 'fields' => array( 'entity_type' => array( @@ -6578,7 +6838,6 @@ 'field_node_entityreference_target_id' => '2', )) ->execute(); - $connection->schema()->createTable('field_data_field_phone', array( 'fields' => array( 'entity_type' => array( @@ -6661,7 +6920,6 @@ 'field_phone_value' => '99-99-99-99', )) ->execute(); - $connection->schema()->createTable('field_data_field_private_file', array( 'fields' => array( 'entity_type' => array( @@ -6784,7 +7042,6 @@ 'field_private_file_description' => '', )) ->execute(); - $connection->schema()->createTable('field_data_field_reference', array( 'fields' => array( 'entity_type' => array( @@ -6921,7 +7178,6 @@ 'field_reference_target_id' => '2', )) ->execute(); - $connection->schema()->createTable('field_data_field_reference_2', array( 'fields' => array( 'entity_type' => array( @@ -7058,7 +7314,6 @@ 'field_reference_2_target_id' => '2', )) ->execute(); - $connection->schema()->createTable('field_data_field_tags', array( 'fields' => array( 'entity_type' => array( @@ -7145,11 +7400,11 @@ 'entity_type' => 'node', 'bundle' => 'article', 'deleted' => '0', - 'entity_id' => '2', - 'revision_id' => '2', + 'entity_id' => '3', + 'revision_id' => '3', 'language' => 'und', - 'delta' => '1', - 'field_tags_tid' => '14', + 'delta' => '0', + 'field_tags_tid' => '9', )) ->values(array( 'entity_type' => 'node', @@ -7158,8 +7413,8 @@ 'entity_id' => '2', 'revision_id' => '2', 'language' => 'und', - 'delta' => '2', - 'field_tags_tid' => '17', + 'delta' => '1', + 'field_tags_tid' => '14', )) ->values(array( 'entity_type' => 'node', @@ -7168,18 +7423,18 @@ 'entity_id' => '3', 'revision_id' => '3', 'language' => 'und', - 'delta' => '0', - 'field_tags_tid' => '9', + 'delta' => '1', + 'field_tags_tid' => '14', )) ->values(array( 'entity_type' => 'node', 'bundle' => 'article', 'deleted' => '0', - 'entity_id' => '3', - 'revision_id' => '3', + 'entity_id' => '2', + 'revision_id' => '2', 'language' => 'und', - 'delta' => '1', - 'field_tags_tid' => '14', + 'delta' => '2', + 'field_tags_tid' => '17', )) ->values(array( 'entity_type' => 'node', @@ -7192,7 +7447,6 @@ 'field_tags_tid' => '17', )) ->execute(); - $connection->schema()->createTable('field_data_field_term_entityreference', array( 'fields' => array( 'entity_type' => array( @@ -7309,7 +7563,6 @@ 'field_term_entityreference_target_id' => '15', )) ->execute(); - $connection->schema()->createTable('field_data_field_term_reference', array( 'fields' => array( 'entity_type' => array( @@ -7403,7 +7656,6 @@ 'field_term_reference_tid' => '3', )) ->execute(); - $connection->schema()->createTable('field_data_field_text', array( 'fields' => array( 'entity_type' => array( @@ -7493,7 +7745,6 @@ 'field_text_format' => NULL, )) ->execute(); - $connection->schema()->createTable('field_data_field_text_filtered', array( 'fields' => array( 'entity_type' => array( @@ -7576,7 +7827,10 @@ 'language', ), 'field_text_filtered_format' => array( - 'field_text_filtered_format', + array( + 'field_text_filtered_format', + '191', + ), ), ), 'mysql_character_set' => 'utf8', @@ -7664,7 +7918,6 @@ 'field_text_list_value' => 'Some more text', )) ->execute(); - $connection->schema()->createTable('field_data_field_text_long_filtered', array( 'fields' => array( 'entity_type' => array( @@ -7747,7 +8000,10 @@ 'language', ), 'field_text_long_filtered_format' => array( - 'field_text_long_filtered_format', + array( + 'field_text_long_filtered_format', + '191', + ), ), ), 'mysql_character_set' => 'utf8', @@ -7835,7 +8091,10 @@ 'language', ), 'field_text_long_plain_format' => array( - 'field_text_long_plain_format', + array( + 'field_text_long_plain_format', + '191', + ), ), ), 'mysql_character_set' => 'utf8', @@ -7923,7 +8182,10 @@ 'language', ), 'field_text_long_plain_filtered_format' => array( - 'field_text_long_plain_filtered_format', + array( + 'field_text_long_plain_filtered_format', + '191', + ), ), ), 'mysql_character_set' => 'utf8', @@ -8011,7 +8273,10 @@ 'language', ), 'field_text_plain_format' => array( - 'field_text_plain_format', + array( + 'field_text_plain_format', + '191', + ), ), ), 'mysql_character_set' => 'utf8', @@ -8099,7 +8364,10 @@ 'language', ), 'field_text_plain_filtered_format' => array( - 'field_text_plain_filtered_format', + array( + 'field_text_plain_filtered_format', + '191', + ), ), ), 'mysql_character_set' => 'utf8', @@ -8192,7 +8460,10 @@ 'language', ), 'field_text_sum_filtered_format' => array( - 'field_text_sum_filtered_format', + array( + 'field_text_sum_filtered_format', + '191', + ), ), ), 'mysql_character_set' => 'utf8', @@ -8285,7 +8556,10 @@ 'language', ), 'field_text_sum_plain_format' => array( - 'field_text_sum_plain_format', + array( + 'field_text_sum_plain_format', + '191', + ), ), ), 'mysql_character_set' => 'utf8', @@ -8378,7 +8652,10 @@ 'language', ), 'field_text_sum_plain_filtered_format' => array( - 'field_text_sum_plain_filtered_format', + array( + 'field_text_sum_plain_filtered_format', + '191', + ), ), ), 'mysql_character_set' => 'utf8', @@ -8490,7 +8767,6 @@ 'field_user_entityreference_target_id' => '2', )) ->execute(); - $connection->schema()->createTable('field_data_name_field', array( 'fields' => array( 'entity_type' => array( @@ -8573,7 +8849,10 @@ 'language', ), 'name_field_format' => array( - 'name_field_format', + array( + 'name_field_format', + '191', + ), ), ), 'mysql_character_set' => 'utf8', @@ -8621,11 +8900,32 @@ 'revision_id' => '4', 'language' => 'en', 'delta' => '0', - 'name_field_value' => 'Term3', + 'name_field_value' => 'Term3 in plain old English', + 'name_field_format' => NULL, +)) +->values(array( + 'entity_type' => 'taxonomy_term', + 'bundle' => 'test_vocabulary', + 'deleted' => '0', + 'entity_id' => '4', + 'revision_id' => '4', + 'language' => 'fr', + 'delta' => '0', + 'name_field_value' => "Term3 en français s'il vous plaît", + 'name_field_format' => NULL, +)) +->values(array( + 'entity_type' => 'taxonomy_term', + 'bundle' => 'test_vocabulary', + 'deleted' => '0', + 'entity_id' => '4', + 'revision_id' => '4', + 'language' => 'is', + 'delta' => '0', + 'name_field_value' => 'Term3 á íslensku', 'name_field_format' => NULL, )) ->execute(); - $connection->schema()->createTable('field_data_subject_field', array( 'fields' => array( 'entity_type' => array( @@ -8708,7 +9008,10 @@ 'language', ), 'subject_field_format' => array( - 'subject_field_format', + array( + 'subject_field_format', + '191', + ), ), ), 'mysql_character_set' => 'utf8', @@ -8726,6 +9029,39 @@ 'subject_field_value', 'subject_field_format', )) +->values(array( + 'entity_type' => 'comment', + 'bundle' => 'comment_node_test_content_type', + 'deleted' => '0', + 'entity_id' => '1', + 'revision_id' => '1', + 'language' => 'en', + 'delta' => '0', + 'subject_field_value' => 'Subject field in English', + 'subject_field_format' => NULL, +)) +->values(array( + 'entity_type' => 'comment', + 'bundle' => 'comment_node_test_content_type', + 'deleted' => '0', + 'entity_id' => '1', + 'revision_id' => '1', + 'language' => 'fr', + 'delta' => '0', + 'subject_field_value' => 'Subject field in French', + 'subject_field_format' => NULL, +)) +->values(array( + 'entity_type' => 'comment', + 'bundle' => 'comment_node_test_content_type', + 'deleted' => '0', + 'entity_id' => '1', + 'revision_id' => '1', + 'language' => 'is', + 'delta' => '0', + 'subject_field_value' => 'Subject field in Icelandic', + 'subject_field_format' => NULL, +)) ->values(array( 'entity_type' => 'comment', 'bundle' => 'comment_node_article', @@ -8737,8 +9073,18 @@ 'subject_field_value' => 'TNG for the win!', 'subject_field_format' => NULL, )) +->values(array( + 'entity_type' => 'comment', + 'bundle' => 'comment_node_article', + 'deleted' => '0', + 'entity_id' => '3', + 'revision_id' => '3', + 'language' => 'is', + 'delta' => '0', + 'subject_field_value' => 'Comment to IS translation', + 'subject_field_format' => NULL, +)) ->execute(); - $connection->schema()->createTable('field_data_taxonomy_forums', array( 'fields' => array( 'entity_type' => array( @@ -8832,7 +9178,6 @@ 'taxonomy_forums_tid' => '1', )) ->execute(); - $connection->schema()->createTable('field_data_title_field', array( 'fields' => array( 'entity_type' => array( @@ -8915,7 +9260,10 @@ 'language', ), 'title_field_format' => array( - 'title_field_format', + array( + 'title_field_format', + '191', + ), ), ), 'mysql_character_set' => 'utf8', @@ -8967,7 +9315,6 @@ 'title_field_format' => NULL, )) ->execute(); - $connection->schema()->createTable('field_revision_body', array( 'fields' => array( 'entity_type' => array( @@ -9101,7 +9448,6 @@ 'body_format' => 'filtered_html', )) ->execute(); - $connection->schema()->createTable('field_revision_comment_body', array( 'fields' => array( 'entity_type' => array( @@ -9202,8 +9548,18 @@ 'comment_body_value' => 'TNG is better than DS9.', 'comment_body_format' => 'filtered_html', )) +->values(array( + 'entity_type' => 'comment', + 'bundle' => 'comment_node_article', + 'deleted' => '0', + 'entity_id' => '3', + 'revision_id' => '3', + 'language' => 'und', + 'delta' => '0', + 'comment_body_value' => 'This is a comment to an Icelandic translation.', + 'comment_body_format' => 'filtered_html', +)) ->execute(); - $connection->schema()->createTable('field_revision_description_field', array( 'fields' => array( 'entity_type' => array( @@ -9292,7 +9648,10 @@ 'language', ), 'description_field_format' => array( - 'description_field_format', + array( + 'description_field_format', + '191', + ), ), ), 'mysql_character_set' => 'utf8', @@ -9343,97 +9702,119 @@ 'revision_id' => '4', 'language' => 'en', 'delta' => '0', - 'description_field_value' => 'The third term.', - 'description_field_summary' => NULL, + 'description_field_value' => 'The third term in plain old English.', + 'description_field_summary' => '', 'description_field_format' => 'full_html', )) -->execute(); - -$connection->schema()->createTable('field_revision_field_boolean', array( - 'fields' => array( - 'entity_type' => array( - 'type' => 'varchar', - 'not null' => TRUE, - 'length' => '128', - 'default' => '', - ), - 'bundle' => array( - 'type' => 'varchar', - 'not null' => TRUE, - 'length' => '128', - 'default' => '', - ), - 'deleted' => array( - 'type' => 'int', - 'not null' => TRUE, - 'size' => 'normal', - 'default' => '0', - ), - 'entity_id' => array( - 'type' => 'int', - 'not null' => TRUE, - 'size' => 'normal', - 'unsigned' => TRUE, - ), - 'revision_id' => array( - 'type' => 'int', - 'not null' => TRUE, - 'size' => 'normal', - 'unsigned' => TRUE, - ), - 'language' => array( - 'type' => 'varchar', - 'not null' => TRUE, - 'length' => '32', - 'default' => '', - ), - 'delta' => array( - 'type' => 'int', - 'not null' => TRUE, - 'size' => 'normal', - 'unsigned' => TRUE, - ), - 'field_boolean_value' => array( - 'type' => 'int', - 'not null' => FALSE, - 'size' => 'normal', - ), - ), - 'primary key' => array( - 'entity_type', - 'deleted', - 'entity_id', - 'revision_id', - 'language', - 'delta', - ), - 'mysql_character_set' => 'utf8', -)); - -$connection->insert('field_revision_field_boolean') -->fields(array( - 'entity_type', - 'bundle', - 'deleted', - 'entity_id', - 'revision_id', - 'language', - 'delta', - 'field_boolean_value', +->values(array( + 'entity_type' => 'taxonomy_term', + 'bundle' => 'test_vocabulary', + 'deleted' => '0', + 'entity_id' => '4', + 'revision_id' => '4', + 'language' => 'fr', + 'delta' => '0', + 'description_field_value' => "The third term en français s'il vous plaît.", + 'description_field_summary' => '', + 'description_field_format' => 'full_html', )) ->values(array( - 'entity_type' => 'node', - 'bundle' => 'test_content_type', + 'entity_type' => 'taxonomy_term', + 'bundle' => 'test_vocabulary', 'deleted' => '0', - 'entity_id' => '1', - 'revision_id' => '1', - 'language' => 'und', + 'entity_id' => '4', + 'revision_id' => '4', + 'language' => 'is', 'delta' => '0', - 'field_boolean_value' => '1', + 'description_field_value' => 'The third term á íslensku.', + 'description_field_summary' => '', + 'description_field_format' => 'full_html', )) ->execute(); - -$connection->schema()->createTable('field_revision_field_date', array( +$connection->schema()->createTable('field_revision_field_boolean', array( + 'fields' => array( + 'entity_type' => array( + 'type' => 'varchar', + 'not null' => TRUE, + 'length' => '128', + 'default' => '', + ), + 'bundle' => array( + 'type' => 'varchar', + 'not null' => TRUE, + 'length' => '128', + 'default' => '', + ), + 'deleted' => array( + 'type' => 'int', + 'not null' => TRUE, + 'size' => 'normal', + 'default' => '0', + ), + 'entity_id' => array( + 'type' => 'int', + 'not null' => TRUE, + 'size' => 'normal', + 'unsigned' => TRUE, + ), + 'revision_id' => array( + 'type' => 'int', + 'not null' => TRUE, + 'size' => 'normal', + 'unsigned' => TRUE, + ), + 'language' => array( + 'type' => 'varchar', + 'not null' => TRUE, + 'length' => '32', + 'default' => '', + ), + 'delta' => array( + 'type' => 'int', + 'not null' => TRUE, + 'size' => 'normal', + 'unsigned' => TRUE, + ), + 'field_boolean_value' => array( + 'type' => 'int', + 'not null' => FALSE, + 'size' => 'normal', + ), + ), + 'primary key' => array( + 'entity_type', + 'deleted', + 'entity_id', + 'revision_id', + 'language', + 'delta', + ), + 'mysql_character_set' => 'utf8', +)); + +$connection->insert('field_revision_field_boolean') +->fields(array( + 'entity_type', + 'bundle', + 'deleted', + 'entity_id', + 'revision_id', + 'language', + 'delta', + 'field_boolean_value', +)) +->values(array( + 'entity_type' => 'node', + 'bundle' => 'test_content_type', + 'deleted' => '0', + 'entity_id' => '1', + 'revision_id' => '1', + 'language' => 'und', + 'delta' => '0', + 'field_boolean_value' => '1', +)) +->execute(); +$connection->schema()->createTable('field_revision_field_date', array( 'fields' => array( 'entity_type' => array( 'type' => 'varchar', @@ -9516,7 +9897,6 @@ 'field_date_value' => '2015-01-20 04:15:00', )) ->execute(); - $connection->schema()->createTable('field_revision_field_date_with_end_time', array( 'fields' => array( 'entity_type' => array( @@ -9607,8 +9987,7 @@ 'field_date_with_end_time_value2' => '1421727300', )) ->execute(); - -$connection->schema()->createTable('field_revision_field_datetime_without_time', array( +$connection->schema()->createTable('field_revision_field_date_without_time', array( 'fields' => array( 'entity_type' => array( 'type' => 'varchar', @@ -9652,12 +10031,10 @@ 'size' => 'normal', 'unsigned' => TRUE, ), - 'field_datetime_without_time_value' => array( - 'mysql_type' => 'datetime', - 'pgsql_type' => 'timestamp without time zone', - 'sqlite_type' => 'varchar', - 'sqlsrv_type' => 'smalldatetime', + 'field_date_without_time_value' => array( + 'type' => 'varchar', 'not null' => FALSE, + 'length' => '100', ), ), 'primary key' => array( @@ -9671,7 +10048,7 @@ 'mysql_character_set' => 'utf8', )); -$connection->insert('field_revision_field_datetime_without_time') +$connection->insert('field_revision_field_date_without_time') ->fields(array( 'entity_type', 'bundle', @@ -9680,7 +10057,7 @@ 'revision_id', 'language', 'delta', - 'field_datetime_without_time_value', + 'field_date_without_time_value', )) ->values(array( 'entity_type' => 'node', @@ -9690,11 +10067,10 @@ 'revision_id' => '1', 'language' => 'und', 'delta' => '0', - 'field_datetime_without_time_value' => '2015-01-20 00:00:00', + 'field_date_without_time_value' => '2015-01-20T00:00:00', )) ->execute(); - -$connection->schema()->createTable('field_revision_field_date_without_time', array( +$connection->schema()->createTable('field_revision_field_datetime_without_time', array( 'fields' => array( 'entity_type' => array( 'type' => 'varchar', @@ -9738,10 +10114,13 @@ 'size' => 'normal', 'unsigned' => TRUE, ), - 'field_date_without_time_value' => array( - 'type' => 'varchar', + 'field_datetime_without_time_value' => array( + 'type' => 'datetime', 'not null' => FALSE, - 'length' => '100', + 'mysql_type' => 'datetime', + 'pgsql_type' => 'timestamp without time zone', + 'sqlite_type' => 'varchar', + 'sqlsrv_type' => 'smalldatetime', ), ), 'primary key' => array( @@ -9755,7 +10134,7 @@ 'mysql_character_set' => 'utf8', )); -$connection->insert('field_revision_field_date_without_time') +$connection->insert('field_revision_field_datetime_without_time') ->fields(array( 'entity_type', 'bundle', @@ -9764,7 +10143,7 @@ 'revision_id', 'language', 'delta', - 'field_date_without_time_value', + 'field_datetime_without_time_value', )) ->values(array( 'entity_type' => 'node', @@ -9774,10 +10153,9 @@ 'revision_id' => '1', 'language' => 'und', 'delta' => '0', - 'field_date_without_time_value' => '2015-01-20T00:00:00', + 'field_datetime_without_time_value' => '2015-01-20 00:00:00', )) ->execute(); - $connection->schema()->createTable('field_revision_field_email', array( 'fields' => array( 'entity_type' => array( @@ -9871,7 +10249,6 @@ 'field_email_email' => 'another@example.com', )) ->execute(); - $connection->schema()->createTable('field_revision_field_file', array( 'fields' => array( 'entity_type' => array( @@ -9984,7 +10361,6 @@ 'field_file_description' => 'file desc', )) ->execute(); - $connection->schema()->createTable('field_revision_field_float', array( 'fields' => array( 'entity_type' => array( @@ -10069,7 +10445,6 @@ 'field_float_value' => '1', )) ->execute(); - $connection->schema()->createTable('field_revision_field_float_list', array( 'fields' => array( 'entity_type' => array( @@ -10176,7 +10551,6 @@ 'field_float_list_value' => '3.1416', )) ->execute(); - $connection->schema()->createTable('field_revision_field_image', array( 'fields' => array( 'entity_type' => array( @@ -10375,7 +10749,6 @@ 'field_images_height' => '93', )) ->execute(); - $connection->schema()->createTable('field_revision_field_integer', array( 'fields' => array( 'entity_type' => array( @@ -10454,10 +10827,30 @@ 'deleted' => '0', 'entity_id' => '1', 'revision_id' => '1', - 'language' => 'und', + 'language' => 'en', 'delta' => '0', 'field_integer_value' => '1000000', )) +->values(array( + 'entity_type' => 'comment', + 'bundle' => 'comment_node_test_content_type', + 'deleted' => '0', + 'entity_id' => '1', + 'revision_id' => '1', + 'language' => 'fr', + 'delta' => '0', + 'field_integer_value' => '2000000', +)) +->values(array( + 'entity_type' => 'comment', + 'bundle' => 'comment_node_test_content_type', + 'deleted' => '0', + 'entity_id' => '1', + 'revision_id' => '1', + 'language' => 'is', + 'delta' => '0', + 'field_integer_value' => '3000000', +)) ->values(array( 'entity_type' => 'node', 'bundle' => 'test_content_type', @@ -10508,8 +10901,27 @@ 'delta' => '0', 'field_integer_value' => '6', )) +->values(array( + 'entity_type' => 'taxonomy_term', + 'bundle' => 'test_vocabulary', + 'deleted' => '0', + 'entity_id' => '4', + 'revision_id' => '4', + 'language' => 'fr', + 'delta' => '0', + 'field_integer_value' => '5', +)) +->values(array( + 'entity_type' => 'taxonomy_term', + 'bundle' => 'test_vocabulary', + 'deleted' => '0', + 'entity_id' => '4', + 'revision_id' => '4', + 'language' => 'is', + 'delta' => '0', + 'field_integer_value' => '4', +)) ->execute(); - $connection->schema()->createTable('field_revision_field_integer_list', array( 'fields' => array( 'entity_type' => array( @@ -10593,7 +11005,6 @@ 'field_integer_list_value' => '7', )) ->execute(); - $connection->schema()->createTable('field_revision_field_link', array( 'fields' => array( 'entity_type' => array( @@ -10715,7 +11126,6 @@ 'field_link_attributes' => 'a:1:{s:5:"title";s:0:"";}', )) ->execute(); - $connection->schema()->createTable('field_revision_field_long_text', array( 'fields' => array( 'entity_type' => array( @@ -10894,7 +11304,6 @@ 'field_node_entityreference_target_id' => '2', )) ->execute(); - $connection->schema()->createTable('field_revision_field_phone', array( 'fields' => array( 'entity_type' => array( @@ -10988,7 +11397,6 @@ 'field_phone_value' => '99-99-99-99', )) ->execute(); - $connection->schema()->createTable('field_revision_field_private_file', array( 'fields' => array( 'entity_type' => array( @@ -11112,7 +11520,6 @@ 'field_private_file_description' => '', )) ->execute(); - $connection->schema()->createTable('field_revision_field_reference', array( 'fields' => array( 'entity_type' => array( @@ -11250,7 +11657,6 @@ 'field_reference_target_id' => '2', )) ->execute(); - $connection->schema()->createTable('field_revision_field_reference_2', array( 'fields' => array( 'entity_type' => array( @@ -11388,7 +11794,6 @@ 'field_reference_2_target_id' => '2', )) ->execute(); - $connection->schema()->createTable('field_revision_field_tags', array( 'fields' => array( 'entity_type' => array( @@ -11523,7 +11928,6 @@ 'field_tags_tid' => '17', )) ->execute(); - $connection->schema()->createTable('field_revision_field_term_entityreference', array( 'fields' => array( 'entity_type' => array( @@ -11641,7 +12045,6 @@ 'field_term_entityreference_target_id' => '15', )) ->execute(); - $connection->schema()->createTable('field_revision_field_term_reference', array( 'fields' => array( 'entity_type' => array( @@ -11736,7 +12139,6 @@ 'field_term_reference_tid' => '3', )) ->execute(); - $connection->schema()->createTable('field_revision_field_text', array( 'fields' => array( 'entity_type' => array( @@ -11827,7 +12229,6 @@ 'field_text_format' => NULL, )) ->execute(); - $connection->schema()->createTable('field_revision_field_text_filtered', array( 'fields' => array( 'entity_type' => array( @@ -11911,7 +12312,10 @@ 'language', ), 'field_text_filtered_format' => array( - 'field_text_filtered_format', + array( + 'field_text_filtered_format', + '191', + ), ), ), 'mysql_character_set' => 'utf8', @@ -12000,7 +12404,6 @@ 'field_text_list_value' => 'Some more text', )) ->execute(); - $connection->schema()->createTable('field_revision_field_text_long_filtered', array( 'fields' => array( 'entity_type' => array( @@ -12084,7 +12487,10 @@ 'language', ), 'field_text_long_filtered_format' => array( - 'field_text_long_filtered_format', + array( + 'field_text_long_filtered_format', + '191', + ), ), ), 'mysql_character_set' => 'utf8', @@ -12173,7 +12579,10 @@ 'language', ), 'field_text_long_plain_format' => array( - 'field_text_long_plain_format', + array( + 'field_text_long_plain_format', + '191', + ), ), ), 'mysql_character_set' => 'utf8', @@ -12262,7 +12671,10 @@ 'language', ), 'field_text_long_plain_filtered_format' => array( - 'field_text_long_plain_filtered_format', + array( + 'field_text_long_plain_filtered_format', + '191', + ), ), ), 'mysql_character_set' => 'utf8', @@ -12351,7 +12763,10 @@ 'language', ), 'field_text_plain_format' => array( - 'field_text_plain_format', + array( + 'field_text_plain_format', + '191', + ), ), ), 'mysql_character_set' => 'utf8', @@ -12440,7 +12855,10 @@ 'language', ), 'field_text_plain_filtered_format' => array( - 'field_text_plain_filtered_format', + array( + 'field_text_plain_filtered_format', + '191', + ), ), ), 'mysql_character_set' => 'utf8', @@ -12534,7 +12952,10 @@ 'language', ), 'field_text_sum_filtered_format' => array( - 'field_text_sum_filtered_format', + array( + 'field_text_sum_filtered_format', + '191', + ), ), ), 'mysql_character_set' => 'utf8', @@ -12628,7 +13049,10 @@ 'language', ), 'field_text_sum_plain_format' => array( - 'field_text_sum_plain_format', + array( + 'field_text_sum_plain_format', + '191', + ), ), ), 'mysql_character_set' => 'utf8', @@ -12722,7 +13146,10 @@ 'language', ), 'field_text_sum_plain_filtered_format' => array( - 'field_text_sum_plain_filtered_format', + array( + 'field_text_sum_plain_filtered_format', + '191', + ), ), ), 'mysql_character_set' => 'utf8', @@ -12813,28 +13240,6 @@ 'mysql_character_set' => 'utf8', )); -$connection->insert('field_revision_field_user_entityreference') -->fields(array( - 'entity_type', - 'bundle', - 'deleted', - 'entity_id', - 'revision_id', - 'language', - 'delta', - 'field_user_entityreference_target_id', -)) -->values(array( - 'entity_type' => 'node', - 'bundle' => 'test_content_type', - 'deleted' => '0', - 'entity_id' => '1', - 'revision_id' => '1', - 'language' => 'und', - 'delta' => '0', - 'field_user_entityreference_target_id' => '2', -)); - $connection->schema()->createTable('field_revision_name_field', array( 'fields' => array( 'entity_type' => array( @@ -12918,7 +13323,10 @@ 'language', ), 'name_field_format' => array( - 'name_field_format', + array( + 'name_field_format', + '191', + ), ), ), 'mysql_character_set' => 'utf8', @@ -12966,11 +13374,32 @@ 'revision_id' => '4', 'language' => 'en', 'delta' => '0', - 'name_field_value' => 'Term3', + 'name_field_value' => 'Term3 in plain old English', + 'name_field_format' => NULL, +)) +->values(array( + 'entity_type' => 'taxonomy_term', + 'bundle' => 'test_vocabulary', + 'deleted' => '0', + 'entity_id' => '4', + 'revision_id' => '4', + 'language' => 'fr', + 'delta' => '0', + 'name_field_value' => "Term3 en français s'il vous plaît", + 'name_field_format' => NULL, +)) +->values(array( + 'entity_type' => 'taxonomy_term', + 'bundle' => 'test_vocabulary', + 'deleted' => '0', + 'entity_id' => '4', + 'revision_id' => '4', + 'language' => 'is', + 'delta' => '0', + 'name_field_value' => 'Term3 á íslensku', 'name_field_format' => NULL, )) ->execute(); - $connection->schema()->createTable('field_revision_subject_field', array( 'fields' => array( 'entity_type' => array( @@ -13054,7 +13483,10 @@ 'language', ), 'subject_field_format' => array( - 'subject_field_format', + array( + 'subject_field_format', + '191', + ), ), ), 'mysql_character_set' => 'utf8', @@ -13072,6 +13504,39 @@ 'subject_field_value', 'subject_field_format', )) +->values(array( + 'entity_type' => 'comment', + 'bundle' => 'comment_node_test_content_type', + 'deleted' => '0', + 'entity_id' => '1', + 'revision_id' => '1', + 'language' => 'en', + 'delta' => '0', + 'subject_field_value' => 'Subject field in English', + 'subject_field_format' => NULL, +)) +->values(array( + 'entity_type' => 'comment', + 'bundle' => 'comment_node_test_content_type', + 'deleted' => '0', + 'entity_id' => '1', + 'revision_id' => '1', + 'language' => 'fr', + 'delta' => '0', + 'subject_field_value' => 'Subject field in French', + 'subject_field_format' => NULL, +)) +->values(array( + 'entity_type' => 'comment', + 'bundle' => 'comment_node_test_content_type', + 'deleted' => '0', + 'entity_id' => '1', + 'revision_id' => '1', + 'language' => 'is', + 'delta' => '0', + 'subject_field_value' => 'Subject field in Icelandic', + 'subject_field_format' => NULL, +)) ->values(array( 'entity_type' => 'comment', 'bundle' => 'comment_node_article', @@ -13083,8 +13548,18 @@ 'subject_field_value' => 'TNG for the win!', 'subject_field_format' => NULL, )) +->values(array( + 'entity_type' => 'comment', + 'bundle' => 'comment_node_article', + 'deleted' => '0', + 'entity_id' => '3', + 'revision_id' => '3', + 'language' => 'is', + 'delta' => '0', + 'subject_field_value' => 'Comment to IS translation', + 'subject_field_format' => NULL, +)) ->execute(); - $connection->schema()->createTable('field_revision_taxonomy_forums', array( 'fields' => array( 'entity_type' => array( @@ -13179,7 +13654,6 @@ 'taxonomy_forums_tid' => '1', )) ->execute(); - $connection->schema()->createTable('field_revision_title_field', array( 'fields' => array( 'entity_type' => array( @@ -13263,7 +13737,10 @@ 'language', ), 'title_field_format' => array( - 'title_field_format', + array( + 'title_field_format', + '191', + ), ), ), 'mysql_character_set' => 'utf8', @@ -13315,7 +13792,6 @@ 'title_field_format' => NULL, )) ->execute(); - $connection->schema()->createTable('file_managed', array( 'fields' => array( 'fid' => array( @@ -13427,9 +13903,7 @@ 'status' => '1', 'timestamp' => '1421747516', )) - ->execute(); - $connection->schema()->createTable('file_usage', array( 'fields' => array( 'fid' => array( @@ -13511,7 +13985,6 @@ 'count' => '1', )) ->execute(); - $connection->schema()->createTable('filter', array( 'fields' => array( 'format' => array( @@ -13774,7 +14247,6 @@ 'settings' => 'a:1:{s:17:"filter_url_length";i:72;}', )) ->execute(); - $connection->schema()->createTable('filter_format', array( 'fields' => array( 'format' => array( @@ -13858,7 +14330,6 @@ 'weight' => '10', )) ->execute(); - $connection->schema()->createTable('flood', array( 'fields' => array( 'fid' => array( @@ -13944,7 +14415,6 @@ 'tid' => '1', )) ->execute(); - $connection->schema()->createTable('forum_index', array( 'fields' => array( 'nid' => array( @@ -14026,7 +14496,6 @@ 'comment_count' => '0', )) ->execute(); - $connection->schema()->createTable('history', array( 'fields' => array( 'uid' => array( @@ -14055,6 +14524,295 @@ 'mysql_character_set' => 'utf8', )); +$connection->schema()->createTable('i18n_block_language', array( + 'fields' => array( + 'module' => array( + 'type' => 'varchar', + 'not null' => TRUE, + 'length' => '64', + ), + 'delta' => array( + 'type' => 'varchar', + 'not null' => TRUE, + 'length' => '32', + ), + 'language' => array( + 'type' => 'varchar', + 'not null' => TRUE, + 'length' => '12', + 'default' => '', + ), + ), + 'primary key' => array( + 'module', + 'delta', + 'language', + ), + 'indexes' => array( + 'language' => array( + 'language', + ), + ), + 'mysql_character_set' => 'utf8', +)); + +$connection->schema()->createTable('i18n_string', array( + 'fields' => array( + 'lid' => array( + 'type' => 'int', + 'not null' => TRUE, + 'size' => 'normal', + 'default' => '0', + ), + 'textgroup' => array( + 'type' => 'varchar', + 'not null' => TRUE, + 'length' => '50', + 'default' => 'default', + ), + 'context' => array( + 'type' => 'varchar', + 'not null' => TRUE, + 'length' => '255', + 'default' => '', + ), + 'objectid' => array( + 'type' => 'varchar', + 'not null' => TRUE, + 'length' => '255', + 'default' => '', + ), + 'type' => array( + 'type' => 'varchar', + 'not null' => TRUE, + 'length' => '255', + 'default' => '', + ), + 'property' => array( + 'type' => 'varchar', + 'not null' => TRUE, + 'length' => '255', + 'default' => '', + ), + 'objectindex' => array( + 'type' => 'int', + 'not null' => TRUE, + 'size' => 'big', + 'default' => '0', + ), + 'format' => array( + 'type' => 'varchar', + 'not null' => FALSE, + 'length' => '255', + ), + ), + 'primary key' => array( + 'lid', + ), + 'indexes' => array( + 'group_context' => array( + 'textgroup', + array( + 'context', + '50', + ), + ), + ), + 'mysql_character_set' => 'utf8', +)); + +$connection->insert('i18n_string') +->fields(array( + 'lid', + 'textgroup', + 'context', + 'objectid', + 'type', + 'property', + 'objectindex', + 'format', +)) +->values(array( + 'lid' => '57', + 'textgroup' => 'blocks', + 'context' => 'block:1:title', + 'objectid' => '1', + 'type' => 'block', + 'property' => 'title', + 'objectindex' => '1', + 'format' => '', +)) +->values(array( + 'lid' => '60', + 'textgroup' => 'blocks', + 'context' => 'block:1:body', + 'objectid' => '1', + 'type' => 'block', + 'property' => 'body', + 'objectindex' => '1', + 'format' => 'filtered_html', +)) +->values(array( + 'lid' => '61', + 'textgroup' => 'node', + 'context' => 'type:article:name', + 'objectid' => 'article', + 'type' => 'type', + 'property' => 'name', + 'objectindex' => '0', + 'format' => '', +)) +->values(array( + 'lid' => '62', + 'textgroup' => 'node', + 'context' => 'type:article:title_label', + 'objectid' => 'article', + 'type' => 'type', + 'property' => 'title_label', + 'objectindex' => '0', + 'format' => '', +)) +->values(array( + 'lid' => '63', + 'textgroup' => 'node', + 'context' => 'type:article:description', + 'objectid' => 'article', + 'type' => 'type', + 'property' => 'description', + 'objectindex' => '0', + 'format' => '', +)) +->values(array( + 'lid' => '64', + 'textgroup' => 'node', + 'context' => 'type:article:help', + 'objectid' => 'article', + 'type' => 'type', + 'property' => 'help', + 'objectindex' => '0', + 'format' => '', +)) +->values(array( + 'lid' => '65', + 'textgroup' => 'node', + 'context' => 'type:book:name', + 'objectid' => 'book', + 'type' => 'type', + 'property' => 'name', + 'objectindex' => '0', + 'format' => '', +)) +->values(array( + 'lid' => '66', + 'textgroup' => 'node', + 'context' => 'type:book:title_label', + 'objectid' => 'book', + 'type' => 'type', + 'property' => 'title_label', + 'objectindex' => '0', + 'format' => '', +)) +->values(array( + 'lid' => '67', + 'textgroup' => 'node', + 'context' => 'type:book:description', + 'objectid' => 'book', + 'type' => 'type', + 'property' => 'description', + 'objectindex' => '0', + 'format' => '', +)) +->values(array( + 'lid' => '68', + 'textgroup' => 'node', + 'context' => 'type:page:name', + 'objectid' => 'page', + 'type' => 'type', + 'property' => 'name', + 'objectindex' => '0', + 'format' => '', +)) +->values(array( + 'lid' => '69', + 'textgroup' => 'node', + 'context' => 'type:page:title_label', + 'objectid' => 'page', + 'type' => 'type', + 'property' => 'title_label', + 'objectindex' => '0', + 'format' => '', +)) +->values(array( + 'lid' => '70', + 'textgroup' => 'node', + 'context' => 'type:page:description', + 'objectid' => 'page', + 'type' => 'type', + 'property' => 'description', + 'objectindex' => '0', + 'format' => '', +)) +->values(array( + 'lid' => '71', + 'textgroup' => 'node', + 'context' => 'type:page:help', + 'objectid' => 'page', + 'type' => 'type', + 'property' => 'help', + 'objectindex' => '0', + 'format' => '', +)) +->values(array( + 'lid' => '72', + 'textgroup' => 'node', + 'context' => 'type:test_content_type:name', + 'objectid' => 'test_content_type', + 'type' => 'type', + 'property' => 'name', + 'objectindex' => '0', + 'format' => '', +)) +->values(array( + 'lid' => '73', + 'textgroup' => 'node', + 'context' => 'type:test_content_type:title_label', + 'objectid' => 'test_content_type', + 'type' => 'type', + 'property' => 'title_label', + 'objectindex' => '0', + 'format' => '', +)) +->values(array( + 'lid' => '74', + 'textgroup' => 'node', + 'context' => 'type:test_content_type:description', + 'objectid' => 'test_content_type', + 'type' => 'type', + 'property' => 'description', + 'objectindex' => '0', + 'format' => '', +)) +->values(array( + 'lid' => '75', + 'textgroup' => 'node', + 'context' => 'type:test_content_type:help', + 'objectid' => 'test_content_type', + 'type' => 'type', + 'property' => 'help', + 'objectindex' => '0', + 'format' => '', +)) +->values(array( + 'lid' => '76', + 'textgroup' => 'blocks', + 'context' => 'user:login:title', + 'objectid' => 'login', + 'type' => 'user', + 'property' => 'title', + 'objectindex' => '0', + 'format' => '', +)) +->execute(); $connection->schema()->createTable('image_effects', array( 'fields' => array( 'ieid' => array( @@ -14144,7 +14902,6 @@ 'data' => 'a:3:{s:5:"width";s:2:"50";s:6:"height";s:2:"50";s:6:"anchor";s:8:"left-top";}', )) ->execute(); - $connection->schema()->createTable('image_styles', array( 'fields' => array( 'isid' => array( @@ -14193,7 +14950,6 @@ 'label' => 'Custom image style 3', )) ->execute(); - $connection->schema()->createTable('languages', array( 'fields' => array( 'language' => array( @@ -14323,7 +15079,6 @@ 'javascript' => '', )) ->execute(); - $connection->schema()->createTable('locales_source', array( 'fields' => array( 'lid' => array( @@ -14363,6 +15118,18 @@ 'primary key' => array( 'lid', ), + 'indexes' => array( + 'textgroup_context' => array( + array( + 'textgroup', + '191', + ), + array( + 'context', + '50', + ), + ), + ), 'mysql_character_set' => 'utf8', )); @@ -14759,8 +15526,231 @@ 'context' => '', 'version' => 'none', )) +->values(array( + 'lid' => '49', + 'location' => 'modules/block/block.js; sites/all/modules/i18n/i18n_block/i18n_block.js', + 'textgroup' => 'default', + 'source' => 'Not restricted', + 'context' => '', + 'version' => 'none', +)) +->values(array( + 'lid' => '50', + 'location' => 'modules/block/block.js', + 'textgroup' => 'default', + 'source' => 'Restricted to certain pages', + 'context' => '', + 'version' => 'none', +)) +->values(array( + 'lid' => '51', + 'location' => 'modules/block/block.js', + 'textgroup' => 'default', + 'source' => 'Not customizable', + 'context' => '', + 'version' => 'none', +)) +->values(array( + 'lid' => '52', + 'location' => 'modules/block/block.js', + 'textgroup' => 'default', + 'source' => 'The changes to these blocks will not be saved until the <em>Save blocks</em> button is clicked.', + 'context' => '', + 'version' => 'none', +)) +->values(array( + 'lid' => '53', + 'location' => 'modules/block/block.js', + 'textgroup' => 'default', + 'source' => 'The block cannot be placed in this region.', + 'context' => '', + 'version' => 'none', +)) +->values(array( + 'lid' => '54', + 'location' => 'sites/all/modules/i18n/i18n_block/i18n_block.js', + 'textgroup' => 'default', + 'source' => 'Translatable', + 'context' => '', + 'version' => 'none', +)) +->values(array( + 'lid' => '55', + 'location' => 'sites/all/modules/i18n/i18n_block/i18n_block.js', + 'textgroup' => 'default', + 'source' => 'Not translatable', + 'context' => '', + 'version' => 'none', +)) +->values(array( + 'lid' => '56', + 'location' => 'sites/all/modules/i18n/i18n_block/i18n_block.js', + 'textgroup' => 'default', + 'source' => 'Restricted to certain languages', + 'context' => '', + 'version' => 'none', +)) +->values(array( + 'lid' => '57', + 'location' => 'blocks:block:1:title', + 'textgroup' => 'blocks', + 'source' => 'Mildly amusing limerick of the day', + 'context' => 'block:1:title', + 'version' => '1', +)) +->values(array( + 'lid' => '58', + 'location' => 'misc/ajax.js', + 'textgroup' => 'default', + 'source' => 'The response failed verification so will not be processed.', + 'context' => '', + 'version' => 'none', +)) +->values(array( + 'lid' => '59', + 'location' => 'misc/ajax.js', + 'textgroup' => 'default', + 'source' => 'The callback URL is not local and not trusted: !url', + 'context' => '', + 'version' => 'none', +)) +->values(array( + 'lid' => '60', + 'location' => 'blocks:block:1:body', + 'textgroup' => 'blocks', + 'source' => "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", + 'context' => 'block:1:body', + 'version' => '1', +)) +->values(array( + 'lid' => '61', + 'location' => 'node:type:article:name', + 'textgroup' => 'node', + 'source' => 'Article', + 'context' => 'type:article:name', + 'version' => '1', +)) +->values(array( + 'lid' => '62', + 'location' => 'node:type:article:title_label', + 'textgroup' => 'node', + 'source' => 'Title', + 'context' => 'type:article:title_label', + 'version' => '1', +)) +->values(array( + 'lid' => '63', + 'location' => 'node:type:article:description', + 'textgroup' => 'node', + 'source' => 'Use <em>articles</em> for time-sensitive content like news, press releases or blog posts.', + 'context' => 'type:article:description', + 'version' => '1', +)) +->values(array( + 'lid' => '64', + 'location' => 'node:type:article:help', + 'textgroup' => 'node', + 'source' => 'Help text for articles', + 'context' => 'type:article:help', + 'version' => '1', +)) +->values(array( + 'lid' => '65', + 'location' => 'node:type:book:name', + 'textgroup' => 'node', + 'source' => 'Book page', + 'context' => 'type:book:name', + 'version' => '1', +)) +->values(array( + 'lid' => '66', + 'location' => 'node:type:book:title_label', + 'textgroup' => 'node', + 'source' => 'Title', + 'context' => 'type:book:title_label', + 'version' => '1', +)) +->values(array( + 'lid' => '67', + 'location' => 'node:type:book:description', + 'textgroup' => 'node', + 'source' => '<em>Books</em> have a built-in hierarchical navigation. Use for handbooks or tutorials.', + 'context' => 'type:book:description', + 'version' => '1', +)) +->values(array( + 'lid' => '68', + 'location' => 'node:type:page:name', + 'textgroup' => 'node', + 'source' => 'Basic page', + 'context' => 'type:page:name', + 'version' => '1', +)) +->values(array( + 'lid' => '69', + 'location' => 'node:type:page:title_label', + 'textgroup' => 'node', + 'source' => 'Title', + 'context' => 'type:page:title_label', + 'version' => '1', +)) +->values(array( + 'lid' => '70', + 'location' => 'node:type:page:description', + 'textgroup' => 'node', + 'source' => "Use <em>basic pages</em> for your static content, such as an 'About us' page.", + 'context' => 'type:page:description', + 'version' => '1', +)) +->values(array( + 'lid' => '71', + 'location' => 'node:type:page:help', + 'textgroup' => 'node', + 'source' => 'Help text for basic pages', + 'context' => 'type:page:help', + 'version' => '1', +)) +->values(array( + 'lid' => '72', + 'location' => 'node:type:test_content_type:name', + 'textgroup' => 'node', + 'source' => 'Test content type', + 'context' => 'type:test_content_type:name', + 'version' => '1', +)) +->values(array( + 'lid' => '73', + 'location' => 'node:type:test_content_type:title_label', + 'textgroup' => 'node', + 'source' => 'Title', + 'context' => 'type:test_content_type:title_label', + 'version' => '1', +)) +->values(array( + 'lid' => '74', + 'location' => 'node:type:test_content_type:description', + 'textgroup' => 'node', + 'source' => 'This is the description of the test content type.', + 'context' => 'type:test_content_type:description', + 'version' => '1', +)) +->values(array( + 'lid' => '75', + 'location' => 'node:type:test_content_type:help', + 'textgroup' => 'node', + 'source' => 'Help text for test content type', + 'context' => 'type:test_content_type:help', + 'version' => '1', +)) +->values(array( + 'lid' => '76', + 'location' => 'blocks:user:login:title', + 'textgroup' => 'blocks', + 'source' => 'User login title', + 'context' => 'user:login:title', + 'version' => '1', +)) ->execute(); - $connection->schema()->createTable('locales_target', array( 'fields' => array( 'lid' => array( @@ -14792,6 +15782,12 @@ 'size' => 'normal', 'default' => '0', ), + 'i18n_status' => array( + 'type' => 'int', + 'not null' => TRUE, + 'size' => 'normal', + 'default' => '0', + ), ), 'primary key' => array( 'lid', @@ -14801,6 +15797,48 @@ 'mysql_character_set' => 'utf8', )); +$connection->insert('locales_target') +->fields(array( + 'lid', + 'translation', + 'language', + 'plid', + 'plural', + 'i18n_status', +)) +->values(array( + 'lid' => '57', + 'translation' => 'fr - Mildly amusing limerick of the day', + 'language' => 'fr', + 'plid' => '0', + 'plural' => '0', + 'i18n_status' => '0', +)) +->values(array( + 'lid' => '60', + '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", + 'language' => 'fr', + 'plid' => '0', + 'plural' => '0', + 'i18n_status' => '0', +)) +->values(array( + 'lid' => '76', + 'translation' => 'fr - User login title', + 'language' => 'fr', + 'plid' => '0', + 'plural' => '0', + 'i18n_status' => '0', +)) +->values(array( + 'lid' => '57', + 'translation' => 'is - Mildly amusing limerick of the day', + 'language' => 'is', + 'plid' => '0', + 'plural' => '0', + 'i18n_status' => '0', +)) +->execute(); $connection->schema()->createTable('menu_custom', array( 'fields' => array( 'menu_name' => array( @@ -14859,7 +15897,6 @@ 'description' => "The <em>User</em> menu contains links related to the user's account, as well as the 'Log out' link.", )) ->execute(); - $connection->schema()->createTable('menu_links', array( 'fields' => array( 'menu_name' => array( @@ -25370,114 +26407,114 @@ 'p9' => '0', 'updated' => '0', )) - ->values(array( - 'menu_name' => 'book-toc-1', - 'mlid' => '480', - 'plid' => '0', - 'link_path' => 'node/4', - 'router_path' => 'node/%', - 'link_title' => 'Test top book title', - 'options' => 'a:0:{}', - 'module' => 'book', - 'hidden' => '0', - 'external' => '0', - 'has_children' => '1', - 'expanded' => '0', - 'weight' => '-10', - 'depth' => '1', - 'customized' => '0', - 'p1' => '480', - 'p2' => '0', - 'p3' => '0', - 'p4' => '0', - 'p5' => '0', - 'p6' => '0', - 'p7' => '0', - 'p8' => '0', - 'p9' => '0', - 'updated' => '0', - )) - ->values(array( - 'menu_name' => 'book-toc-1', - 'mlid' => '481', - 'plid' => '480', - 'link_path' => 'node/6', - 'router_path' => 'node/%', - 'link_title' => 'Test book title child 1', - 'options' => 'a:0:{}', - 'module' => 'book', - 'hidden' => '0', - 'external' => '0', - 'has_children' => '1', - 'expanded' => '0', - 'weight' => '0', - 'depth' => '2', - 'customized' => '0', - 'p1' => '480', - 'p2' => '481', - 'p3' => '0', - 'p4' => '0', - 'p5' => '0', - 'p6' => '0', - 'p7' => '0', - 'p8' => '0', - 'p9' => '0', - 'updated' => '0', - )) - ->values(array( - 'menu_name' => 'book-toc-1', - 'mlid' => '482', - 'plid' => '481', - 'link_path' => 'node/2', - 'router_path' => 'node/%', - 'link_title' => 'Test book title child 1.1', - 'options' => 'a:0:{}', - 'module' => 'book', - 'hidden' => '0', - 'external' => '0', - 'has_children' => '0', - 'expanded' => '0', - 'weight' => '0', - 'depth' => '3', - 'customized' => '0', - 'p1' => '480', - 'p2' => '481', - 'p3' => '482', - 'p4' => '0', - 'p5' => '0', - 'p6' => '0', - 'p7' => '0', - 'p8' => '0', - 'p9' => '0', - 'updated' => '0', - )) - ->values(array( - 'menu_name' => 'book-toc-2', - 'mlid' => '483', - 'plid' => '481', - 'link_path' => 'node/1', - 'router_path' => 'node/%', - 'link_title' => 'Test book title 2', - 'options' => 'a:0:{}', - 'module' => 'book', - 'hidden' => '0', - 'external' => '0', - 'has_children' => '0', - 'expanded' => '0', - 'weight' => '0', - 'depth' => '3', - 'customized' => '0', - 'p1' => '480', - 'p2' => '481', - 'p3' => '483', - 'p4' => '0', - 'p5' => '0', - 'p6' => '0', - 'p7' => '0', - 'p8' => '0', - 'p9' => '0', - 'updated' => '0', - )) +->values(array( + 'menu_name' => 'book-toc-1', + 'mlid' => '480', + 'plid' => '0', + 'link_path' => 'node/4', + 'router_path' => 'node/%', + 'link_title' => 'Test top book title', + 'options' => 'a:0:{}', + 'module' => 'book', + 'hidden' => '0', + 'external' => '0', + 'has_children' => '1', + 'expanded' => '0', + 'weight' => '-10', + 'depth' => '1', + 'customized' => '0', + 'p1' => '480', + 'p2' => '0', + 'p3' => '0', + 'p4' => '0', + 'p5' => '0', + 'p6' => '0', + 'p7' => '0', + 'p8' => '0', + 'p9' => '0', + 'updated' => '0', +)) +->values(array( + 'menu_name' => 'book-toc-1', + 'mlid' => '481', + 'plid' => '480', + 'link_path' => 'node/6', + 'router_path' => 'node/%', + 'link_title' => 'Test book title child 1', + 'options' => 'a:0:{}', + 'module' => 'book', + 'hidden' => '0', + 'external' => '0', + 'has_children' => '1', + 'expanded' => '0', + 'weight' => '0', + 'depth' => '2', + 'customized' => '0', + 'p1' => '480', + 'p2' => '481', + 'p3' => '0', + 'p4' => '0', + 'p5' => '0', + 'p6' => '0', + 'p7' => '0', + 'p8' => '0', + 'p9' => '0', + 'updated' => '0', +)) +->values(array( + 'menu_name' => 'book-toc-1', + 'mlid' => '482', + 'plid' => '481', + 'link_path' => 'node/2', + 'router_path' => 'node/%', + 'link_title' => 'Test book title child 1.1', + 'options' => 'a:0:{}', + 'module' => 'book', + 'hidden' => '0', + 'external' => '0', + 'has_children' => '0', + 'expanded' => '0', + 'weight' => '0', + 'depth' => '3', + 'customized' => '0', + 'p1' => '480', + 'p2' => '481', + 'p3' => '482', + 'p4' => '0', + 'p5' => '0', + 'p6' => '0', + 'p7' => '0', + 'p8' => '0', + 'p9' => '0', + 'updated' => '0', +)) +->values(array( + 'menu_name' => 'book-toc-2', + 'mlid' => '483', + 'plid' => '481', + 'link_path' => 'node/1', + 'router_path' => 'node/%', + 'link_title' => 'Test book title 2', + 'options' => 'a:0:{}', + 'module' => 'book', + 'hidden' => '0', + 'external' => '0', + 'has_children' => '0', + 'expanded' => '0', + 'weight' => '0', + 'depth' => '3', + 'customized' => '0', + 'p1' => '480', + 'p2' => '481', + 'p3' => '483', + 'p4' => '0', + 'p5' => '0', + 'p6' => '0', + 'p7' => '0', + 'p8' => '0', + 'p9' => '0', + 'updated' => '0', +)) ->values(array( 'menu_name' => 'navigation', 'mlid' => '484', @@ -25614,7 +26651,6 @@ 'updated' => '0', )) ->execute(); - $connection->schema()->createTable('menu_router', array( 'fields' => array( 'path' => array( @@ -36208,7 +37244,6 @@ 'include_file' => 'modules/user/user.pages.inc', )) ->execute(); - $connection->schema()->createTable('node', array( 'fields' => array( 'nid' => array( @@ -36433,7 +37468,6 @@ 'translate' => '0', )) ->execute(); - $connection->schema()->createTable('node_access', array( 'fields' => array( 'nid' => array( @@ -36504,7 +37538,6 @@ 'grant_delete' => '0', )) ->execute(); - $connection->schema()->createTable('node_comment_statistics', array( 'fields' => array( 'nid' => array( @@ -36570,11 +37603,11 @@ )) ->values(array( 'nid' => '3', - 'cid' => '0', - 'last_comment_timestamp' => '1471428152', - 'last_comment_name' => NULL, + 'cid' => '3', + 'last_comment_timestamp' => '1533031490', + 'last_comment_name' => '', 'last_comment_uid' => '1', - 'comment_count' => '0', + 'comment_count' => '1', )) ->values(array( 'nid' => '4', @@ -36609,7 +37642,6 @@ 'comment_count' => '0', )) ->execute(); - $connection->schema()->createTable('node_counter', array( 'fields' => array( 'nid' => array( @@ -36696,7 +37728,6 @@ 'timestamp' => '1504715438', )) ->execute(); - $connection->schema()->createTable('node_revision', array( 'fields' => array( 'nid' => array( @@ -36864,7 +37895,6 @@ 'sticky' => '0', )) ->execute(); - $connection->schema()->createTable('node_type', array( 'fields' => array( 'type' => array( @@ -37054,7 +38084,6 @@ 'orig_type' => 'test_content_type', )) ->execute(); - $connection->schema()->createTable('queue', array( 'fields' => array( 'item_id' => array( @@ -37150,7 +38179,6 @@ 'mapping' => 'a:9:{s:7:"rdftype";a:1:{i:0;s:13:"foaf:Document";}s:5:"title";a:1:{s:10:"predicates";a:1:{i:0;s:8:"dc:title";}}s:7:"created";a:3:{s:10:"predicates";a:2:{i:0;s:7:"dc:date";i:1;s:10:"dc:created";}s:8:"datatype";s:12:"xsd:dateTime";s:8:"callback";s:12:"date_iso8601";}s:7:"changed";a:3:{s:10:"predicates";a:1:{i:0;s:11:"dc:modified";}s:8:"datatype";s:12:"xsd:dateTime";s:8:"callback";s:12:"date_iso8601";}s:4:"body";a:1:{s:10:"predicates";a:1:{i:0;s:15:"content:encoded";}}s:3:"uid";a:2:{s:10:"predicates";a:1:{i:0;s:16:"sioc:has_creator";}s:4:"type";s:3:"rel";}s:4:"name";a:1:{s:10:"predicates";a:1:{i:0;s:9:"foaf:name";}}s:13:"comment_count";a:2:{s:10:"predicates";a:1:{i:0;s:16:"sioc:num_replies";}s:8:"datatype";s:11:"xsd:integer";}s:13:"last_activity";a:3:{s:10:"predicates";a:1:{i:0;s:23:"sioc:last_activity_date";}s:8:"datatype";s:12:"xsd:dateTime";s:8:"callback";s:12:"date_iso8601";}}', )) ->execute(); - $connection->schema()->createTable('registry', array( 'fields' => array( 'name' => array( @@ -37870,6 +38898,13 @@ 'module' => 'phone', 'weight' => '0', )) +->values(array( + 'name' => 'CSPhoneNumberTestCase', + 'type' => 'class', + 'filename' => 'sites/all/modules/phone/tests/phone.cs.test', + 'module' => 'phone', + 'weight' => '0', +)) ->values(array( 'name' => 'CtoolsContextKeywordsSubstitutionTestCase', 'type' => 'class', @@ -37975,14 +39010,6 @@ 'module' => 'ctools', 'weight' => '0', )) -->values(array( - 'name' => 'CSPhoneNumberTestCase', - 'type' => 'class', - 'filename' => 'sites/all/modules/phone/tests/phone.cs.test', - 'module' => 'phone', - 'weight' => '0', -)) - ->values(array( 'name' => 'DashboardBlocksTestCase', 'type' => 'class', @@ -43528,7 +44555,6 @@ 'weight' => '0', )) ->execute(); - $connection->schema()->createTable('registry_file', array( 'fields' => array( 'filename' => array( @@ -44882,7 +45908,6 @@ 'hash' => 'a52e010d27cc2eb29804a3acd30f574adf11fad1f5860e431178b61cddbdbb69', )) ->execute(); - $connection->schema()->createTable('role', array( 'fields' => array( 'rid' => array( @@ -44932,7 +45957,6 @@ 'weight' => '2', )) ->execute(); - $connection->schema()->createTable('role_permission', array( 'fields' => array( 'rid' => array( @@ -45352,6 +46376,16 @@ 'permission' => 'switch shortcut sets', 'module' => 'shortcut', )) +->values(array( + 'rid' => '3', + 'permission' => 'translate admin strings', + 'module' => 'i18n_string', +)) +->values(array( + 'rid' => '3', + 'permission' => 'translate blocks', + 'module' => 'i18n_block', +)) ->values(array( 'rid' => '3', 'permission' => 'translate content', @@ -45362,6 +46396,11 @@ 'permission' => 'translate interface', 'module' => 'locale', )) +->values(array( + 'rid' => '3', + 'permission' => 'translate user-defined strings', + 'module' => 'i18n_string', +)) ->values(array( 'rid' => '3', 'permission' => 'use advanced search', @@ -45423,7 +46462,6 @@ 'module' => 'system', )) ->execute(); - $connection->schema()->createTable('search_dataset', array( 'fields' => array( 'sid' => array( @@ -45478,7 +46516,6 @@ 'reindex' => '0', )) ->execute(); - $connection->schema()->createTable('search_index', array( 'fields' => array( 'word' => array( @@ -45804,7 +46841,6 @@ 'score' => '1', )) ->execute(); - $connection->schema()->createTable('search_node_links', array( 'fields' => array( 'sid' => array( @@ -46052,7 +47088,6 @@ 'count' => '0', )) ->execute(); - $connection->schema()->createTable('semaphore', array( 'fields' => array( 'name' => array( @@ -46103,7 +47138,6 @@ 'value' => '2', )) ->execute(); - $connection->schema()->createTable('sessions', array( 'fields' => array( 'uid' => array( @@ -46189,7 +47223,6 @@ 'title' => 'Alternative shortcut set', )) ->execute(); - $connection->schema()->createTable('shortcut_set_users', array( 'fields' => array( 'uid' => array( @@ -46222,7 +47255,6 @@ 'set_name' => 'shortcut-set-2', )) ->execute(); - $connection->schema()->createTable('simpletest', array( 'fields' => array( 'message_id' => array( @@ -47962,7 +48994,227 @@ 'bootstrap' => '0', 'schema_version' => '7009', 'weight' => '11', - 'info' => 'a:14:{s:4:"name";s:18:"Entity Translation";s:11:"description";s:58:"Allows entities to be translated into different languages.";s:7:"package";s:33:"Multilingual - Entity Translation";s:4:"core";s:3:"7.x";s:9:"configure";s:40:"admin/config/regional/entity_translation";s:12:"dependencies";a:1:{i:0;s:14:"locale (>7.14)";}s:17:"test_dependencies";a:2:{i:0;s:17:"pathauto:pathauto";i:1;s:5:"title";}s:5:"files";a:15:{i:0;s:40:"includes/translation.handler_factory.inc";i:1;s:32:"includes/translation.handler.inc";i:2;s:40:"includes/translation.handler.comment.inc";i:3;s:37:"includes/translation.handler.node.inc";i:4;s:46:"includes/translation.handler.taxonomy_term.inc";i:5;s:37:"includes/translation.handler.user.inc";i:6;s:32:"includes/translation.migrate.inc";i:7;s:29:"tests/entity_translation.test";i:8;s:49:"views/entity_translation_handler_relationship.inc";i:9;s:57:"views/entity_translation_handler_field_translate_link.inc";i:10;s:48:"views/entity_translation_handler_field_label.inc";i:11;s:55:"views/entity_translation_handler_filter_entity_type.inc";i:12;s:52:"views/entity_translation_handler_filter_language.inc";i:13;s:62:"views/entity_translation_handler_filter_translation_exists.inc";i:14;s:48:"views/entity_translation_handler_field_field.inc";}s:7:"version";s:7:"7.x-1.0";s:7:"project";s:18:"entity_translation";s:9:"datestamp";s:10:"1522600694";s:5:"mtime";i:1522600694;s:3:"php";s:5:"5.2.4";s:9:"bootstrap";i:0;}', + 'info' => 'a:14:{s:4:"name";s:18:"Entity Translation";s:11:"description";s:58:"Allows entities to be translated into different languages.";s:7:"package";s:33:"Multilingual - Entity Translation";s:4:"core";s:3:"7.x";s:9:"configure";s:40:"admin/config/regional/entity_translation";s:12:"dependencies";a:1:{i:0;s:14:"locale (>7.14)";}s:17:"test_dependencies";a:2:{i:0;s:17:"pathauto:pathauto";i:1;s:5:"title";}s:5:"files";a:15:{i:0;s:40:"includes/translation.handler_factory.inc";i:1;s:32:"includes/translation.handler.inc";i:2;s:40:"includes/translation.handler.comment.inc";i:3;s:37:"includes/translation.handler.node.inc";i:4;s:46:"includes/translation.handler.taxonomy_term.inc";i:5;s:37:"includes/translation.handler.user.inc";i:6;s:32:"includes/translation.migrate.inc";i:7;s:29:"tests/entity_translation.test";i:8;s:49:"views/entity_translation_handler_relationship.inc";i:9;s:57:"views/entity_translation_handler_field_translate_link.inc";i:10;s:48:"views/entity_translation_handler_field_label.inc";i:11;s:55:"views/entity_translation_handler_filter_entity_type.inc";i:12;s:52:"views/entity_translation_handler_filter_language.inc";i:13;s:62:"views/entity_translation_handler_filter_translation_exists.inc";i:14;s:48:"views/entity_translation_handler_field_field.inc";}s:7:"version";s:7:"7.x-1.0";s:7:"project";s:18:"entity_translation";s:9:"datestamp";s:10:"1522600694";s:5:"mtime";i:1535762879;s:3:"php";s:5:"5.2.4";s:9:"bootstrap";i:0;}', +)) +->values(array( + 'filename' => 'sites/all/modules/entity_translation/entity_translation_i18n_menu/entity_translation_i18n_menu.module', + 'name' => 'entity_translation_i18n_menu', + 'type' => 'module', + 'owner' => '', + 'status' => '0', + 'bootstrap' => '0', + 'schema_version' => '-1', + 'weight' => '0', + 'info' => 'a:12:{s:4:"name";s:23:"Entity Translation Menu";s:11:"description";s:54:"Allows menu items to be translated on the entity form.";s:7:"package";s:33:"Multilingual - Entity Translation";s:4:"core";s:3:"7.x";s:12:"dependencies";a:3:{i:0;s:18:"entity_translation";i:1;s:4:"i18n";i:2;s:9:"i18n_menu";}s:5:"files";a:1:{i:0;s:33:"entity_translation_i18n_menu.test";}s:7:"version";s:7:"7.x-1.0";s:7:"project";s:18:"entity_translation";s:9:"datestamp";s:10:"1522600694";s:5:"mtime";i:1535762879;s:3:"php";s:5:"5.2.4";s:9:"bootstrap";i:0;}', +)) +->values(array( + 'filename' => 'sites/all/modules/entity_translation/entity_translation_upgrade/entity_translation_upgrade.module', + 'name' => 'entity_translation_upgrade', + 'type' => 'module', + 'owner' => '', + 'status' => '0', + 'bootstrap' => '0', + 'schema_version' => '-1', + 'weight' => '0', + 'info' => 'a:12:{s:4:"name";s:26:"Entity Translation Upgrade";s:11:"description";s:80:"Provides an upgrade path from node-based translation to field-based translation.";s:7:"package";s:33:"Multilingual - Entity Translation";s:4:"core";s:3:"7.x";s:12:"dependencies";a:1:{i:0;s:18:"entity_translation";}s:5:"files";a:1:{i:0;s:31:"entity_translation_upgrade.test";}s:7:"version";s:7:"7.x-1.0";s:7:"project";s:18:"entity_translation";s:9:"datestamp";s:10:"1522600694";s:5:"mtime";i:1535762879;s:3:"php";s:5:"5.2.4";s:9:"bootstrap";i:0;}', +)) +->values(array( + 'filename' => 'sites/all/modules/entity_translation/tests/entity_translation_test.module', + 'name' => 'entity_translation_test', + 'type' => 'module', + 'owner' => '', + 'status' => '0', + 'bootstrap' => '0', + 'schema_version' => '-1', + 'weight' => '0', + 'info' => 'a:13:{s:4:"name";s:26:"Entity Translation testing";s:11:"description";s:61:"Tests Entity Translation module functionality. Do not enable.";s:4:"core";s:3:"7.x";s:7:"package";s:7:"Testing";s:6:"hidden";b:1;s:12:"dependencies";a:1:{i:0;s:18:"entity_translation";}s:5:"files";a:1:{i:0;s:30:"entity_translation_test.module";}s:7:"version";s:7:"7.x-1.0";s:7:"project";s:18:"entity_translation";s:9:"datestamp";s:10:"1522600694";s:5:"mtime";i:1535762879;s:3:"php";s:5:"5.2.4";s:9:"bootstrap";i:0;}', +)) +->values(array( + 'filename' => 'sites/all/modules/i18n/i18n.module', + 'name' => 'i18n', + 'type' => 'module', + 'owner' => '', + 'status' => '1', + 'bootstrap' => '1', + 'schema_version' => '7001', + 'weight' => '10', + 'info' => 'a:13:{s:4:"name";s:20:"Internationalization";s:11:"description";s:49:"Extends Drupal support for multilingual features.";s:12:"dependencies";a:2:{i:0;s:6:"locale";i:1;s:8:"variable";}s:7:"package";s:35:"Multilingual - Internationalization";s:4:"core";s:3:"7.x";s:5:"files";a:2:{i:0;s:15:"i18n_object.inc";i:1;s:9:"i18n.test";}s:9:"configure";s:26:"admin/config/regional/i18n";s:7:"version";s:8:"7.x-1.26";s:7:"project";s:4:"i18n";s:9:"datestamp";s:10:"1534531985";s:5:"mtime";i:1534531985;s:3:"php";s:5:"5.2.4";s:9:"bootstrap";i:0;}', +)) +->values(array( + 'filename' => 'sites/all/modules/i18n/i18n_block/i18n_block.module', + 'name' => 'i18n_block', + 'type' => 'module', + 'owner' => '', + 'status' => '1', + 'bootstrap' => '0', + 'schema_version' => '7001', + 'weight' => '100', + 'info' => 'a:12:{s:4:"name";s:15:"Block languages";s:11:"description";s:68:"Enables language selector for blocks and optional block translation.";s:12:"dependencies";a:2:{i:0;s:5:"block";i:1;s:11:"i18n_string";}s:7:"package";s:35:"Multilingual - Internationalization";s:4:"core";s:3:"7.x";s:5:"files";a:2:{i:0;s:14:"i18n_block.inc";i:1;s:15:"i18n_block.test";}s:7:"version";s:8:"7.x-1.25";s:7:"project";s:4:"i18n";s:9:"datestamp";s:10:"1531342125";s:5:"mtime";i:1537747250;s:3:"php";s:5:"5.2.4";s:9:"bootstrap";i:0;}', +)) +->values(array( + 'filename' => 'sites/all/modules/i18n/i18n_contact/i18n_contact.module', + 'name' => 'i18n_contact', + 'type' => 'module', + 'owner' => '', + 'status' => '0', + 'bootstrap' => '0', + 'schema_version' => '-1', + 'weight' => '0', + 'info' => 'a:12:{s:4:"name";s:19:"Contact translation";s:11:"description";s:63:"Makes contact categories and replies available for translation.";s:12:"dependencies";a:2:{i:0;s:7:"contact";i:1;s:11:"i18n_string";}s:7:"package";s:35:"Multilingual - Internationalization";s:4:"core";s:3:"7.x";s:7:"version";s:8:"7.x-1.26";s:7:"project";s:4:"i18n";s:9:"datestamp";s:10:"1534531985";s:5:"mtime";i:1534531985;s:3:"php";s:5:"5.2.4";s:5:"files";a:0:{}s:9:"bootstrap";i:0;}', +)) +->values(array( + 'filename' => 'sites/all/modules/i18n/i18n_field/i18n_field.module', + 'name' => 'i18n_field', + 'type' => 'module', + 'owner' => '', + 'status' => '0', + 'bootstrap' => '0', + 'schema_version' => '-1', + 'weight' => '0', + 'info' => 'a:12:{s:4:"name";s:17:"Field translation";s:11:"description";s:26:"Translate field properties";s:12:"dependencies";a:2:{i:0;s:5:"field";i:1;s:11:"i18n_string";}s:7:"package";s:35:"Multilingual - Internationalization";s:4:"core";s:3:"7.x";s:5:"files";a:2:{i:0;s:14:"i18n_field.inc";i:1;s:15:"i18n_field.test";}s:7:"version";s:8:"7.x-1.26";s:7:"project";s:4:"i18n";s:9:"datestamp";s:10:"1534531985";s:5:"mtime";i:1534531985;s:3:"php";s:5:"5.2.4";s:9:"bootstrap";i:0;}', +)) +->values(array( + 'filename' => 'sites/all/modules/i18n/i18n_forum/i18n_forum.module', + 'name' => 'i18n_forum', + 'type' => 'module', + 'owner' => '', + 'status' => '0', + 'bootstrap' => '0', + 'schema_version' => '-1', + 'weight' => '0', + 'info' => 'a:12:{s:4:"name";s:18:"Multilingual forum";s:11:"description";s:60:"Enables multilingual forum, translates names and containers.";s:12:"dependencies";a:3:{i:0;s:5:"forum";i:1;s:13:"i18n_taxonomy";i:2;s:9:"i18n_node";}s:7:"package";s:35:"Multilingual - Internationalization";s:4:"core";s:3:"7.x";s:5:"files";a:1:{i:0;s:15:"i18n_forum.test";}s:7:"version";s:8:"7.x-1.26";s:7:"project";s:4:"i18n";s:9:"datestamp";s:10:"1534531985";s:5:"mtime";i:1534531985;s:3:"php";s:5:"5.2.4";s:9:"bootstrap";i:0;}', +)) +->values(array( + 'filename' => 'sites/all/modules/i18n/i18n_menu/i18n_menu.module', + 'name' => 'i18n_menu', + 'type' => 'module', + 'owner' => '', + 'status' => '0', + 'bootstrap' => '0', + 'schema_version' => '-1', + 'weight' => '0', + 'info' => 'a:12:{s:4:"name";s:16:"Menu translation";s:11:"description";s:40:"Supports translatable custom menu items.";s:12:"dependencies";a:4:{i:0;s:4:"i18n";i:1;s:4:"menu";i:2;s:11:"i18n_string";i:3;s:16:"i18n_translation";}s:7:"package";s:35:"Multilingual - Internationalization";s:4:"core";s:3:"7.x";s:5:"files";a:2:{i:0;s:13:"i18n_menu.inc";i:1;s:14:"i18n_menu.test";}s:7:"version";s:8:"7.x-1.26";s:7:"project";s:4:"i18n";s:9:"datestamp";s:10:"1534531985";s:5:"mtime";i:1534531985;s:3:"php";s:5:"5.2.4";s:9:"bootstrap";i:0;}', +)) +->values(array( + 'filename' => 'sites/all/modules/i18n/i18n_node/i18n_node.module', + 'name' => 'i18n_node', + 'type' => 'module', + 'owner' => '', + 'status' => '0', + 'bootstrap' => '0', + 'schema_version' => '-1', + 'weight' => '0', + 'info' => 'a:13:{s:4:"name";s:20:"Multilingual content";s:11:"description";s:46:"Extended node options for multilingual content";s:12:"dependencies";a:3:{i:0;s:11:"translation";i:1;s:4:"i18n";i:2;s:11:"i18n_string";}s:7:"package";s:35:"Multilingual - Internationalization";s:4:"core";s:3:"7.x";s:9:"configure";s:31:"admin/config/regional/i18n/node";s:5:"files";a:2:{i:0;s:14:"i18n_node.test";i:1;s:22:"i18n_node.variable.inc";}s:7:"version";s:8:"7.x-1.26";s:7:"project";s:4:"i18n";s:9:"datestamp";s:10:"1534531985";s:5:"mtime";i:1534531985;s:3:"php";s:5:"5.2.4";s:9:"bootstrap";i:0;}', +)) +->values(array( + 'filename' => 'sites/all/modules/i18n/i18n_path/i18n_path.module', + 'name' => 'i18n_path', + 'type' => 'module', + 'owner' => '', + 'status' => '0', + 'bootstrap' => '0', + 'schema_version' => '-1', + 'weight' => '0', + 'info' => 'a:12:{s:4:"name";s:16:"Path translation";s:11:"description";s:37:"Define translations for generic paths";s:12:"dependencies";a:1:{i:0;s:16:"i18n_translation";}s:7:"package";s:35:"Multilingual - Internationalization";s:4:"core";s:3:"7.x";s:5:"files";a:2:{i:0;s:13:"i18n_path.inc";i:1;s:14:"i18n_path.test";}s:7:"version";s:8:"7.x-1.26";s:7:"project";s:4:"i18n";s:9:"datestamp";s:10:"1534531985";s:5:"mtime";i:1534531985;s:3:"php";s:5:"5.2.4";s:9:"bootstrap";i:0;}', +)) +->values(array( + 'filename' => 'sites/all/modules/i18n/i18n_redirect/i18n_redirect.module', + 'name' => 'i18n_redirect', + 'type' => 'module', + 'owner' => '', + 'status' => '0', + 'bootstrap' => '0', + 'schema_version' => '-1', + 'weight' => '0', + 'info' => 'a:12:{s:4:"name";s:20:"Translation redirect";s:11:"description";s:71:"Redirect to translated page when available. SEO for multilingual sites.";s:12:"dependencies";a:1:{i:0;s:4:"i18n";}s:7:"package";s:35:"Multilingual - Internationalization";s:4:"core";s:3:"7.x";s:7:"version";s:8:"7.x-1.26";s:7:"project";s:4:"i18n";s:9:"datestamp";s:10:"1534531985";s:5:"mtime";i:1534531985;s:3:"php";s:5:"5.2.4";s:5:"files";a:0:{}s:9:"bootstrap";i:0;}', +)) +->values(array( + 'filename' => 'sites/all/modules/i18n/i18n_select/i18n_select.module', + 'name' => 'i18n_select', + 'type' => 'module', + 'owner' => '', + 'status' => '0', + 'bootstrap' => '0', + 'schema_version' => '-1', + 'weight' => '0', + 'info' => 'a:13:{s:4:"name";s:19:"Multilingual select";s:11:"description";s:45:"API module for multilingual content selection";s:12:"dependencies";a:1:{i:0;s:4:"i18n";}s:7:"package";s:35:"Multilingual - Internationalization";s:4:"core";s:3:"7.x";s:9:"configure";s:33:"admin/config/regional/i18n/select";s:5:"files";a:1:{i:0;s:16:"i18n_select.test";}s:7:"version";s:8:"7.x-1.26";s:7:"project";s:4:"i18n";s:9:"datestamp";s:10:"1534531985";s:5:"mtime";i:1534531985;s:3:"php";s:5:"5.2.4";s:9:"bootstrap";i:0;}', +)) +->values(array( + 'filename' => 'sites/all/modules/i18n/i18n_string/i18n_string.module', + 'name' => 'i18n_string', + 'type' => 'module', + 'owner' => '', + 'status' => '0', + 'bootstrap' => '0', + 'schema_version' => '-1', + 'weight' => '0', + 'info' => 'a:13:{s:4:"name";s:18:"String translation";s:11:"description";s:57:"Provides support for translation of user defined strings.";s:12:"dependencies";a:2:{i:0;s:6:"locale";i:1;s:4:"i18n";}s:7:"package";s:35:"Multilingual - Internationalization";s:4:"core";s:3:"7.x";s:5:"files";a:3:{i:0;s:21:"i18n_string.admin.inc";i:1;s:15:"i18n_string.inc";i:2;s:16:"i18n_string.test";}s:9:"configure";s:34:"admin/config/regional/i18n/strings";s:7:"version";s:8:"7.x-1.26";s:7:"project";s:4:"i18n";s:9:"datestamp";s:10:"1534531985";s:5:"mtime";i:1534531985;s:3:"php";s:5:"5.2.4";s:9:"bootstrap";i:0;}', +)) +->values(array( + 'filename' => 'sites/all/modules/i18n/i18n_sync/i18n_sync.module', + 'name' => 'i18n_sync', + 'type' => 'module', + 'owner' => '', + 'status' => '0', + 'bootstrap' => '0', + 'schema_version' => '-1', + 'weight' => '0', + 'info' => 'a:12:{s:4:"name";s:24:"Synchronize translations";s:11:"description";s:73:"Synchronizes taxonomy and fields across translations of the same content.";s:12:"dependencies";a:2:{i:0;s:4:"i18n";i:1;s:11:"translation";}s:7:"package";s:35:"Multilingual - Internationalization";s:4:"core";s:3:"7.x";s:5:"files";a:5:{i:0;s:16:"i18n_sync.module";i:1;s:17:"i18n_sync.install";i:2;s:20:"i18n_sync.module.inc";i:3;s:18:"i18n_sync.node.inc";i:4;s:14:"i18n_sync.test";}s:7:"version";s:8:"7.x-1.26";s:7:"project";s:4:"i18n";s:9:"datestamp";s:10:"1534531985";s:5:"mtime";i:1534531985;s:3:"php";s:5:"5.2.4";s:9:"bootstrap";i:0;}', +)) +->values(array( + 'filename' => 'sites/all/modules/i18n/i18n_taxonomy/i18n_taxonomy.module', + 'name' => 'i18n_taxonomy', + 'type' => 'module', + 'owner' => '', + 'status' => '0', + 'bootstrap' => '0', + 'schema_version' => '-1', + 'weight' => '0', + 'info' => 'a:12:{s:4:"name";s:20:"Taxonomy translation";s:11:"description";s:30:"Enables multilingual taxonomy.";s:12:"dependencies";a:3:{i:0;s:8:"taxonomy";i:1;s:11:"i18n_string";i:2;s:16:"i18n_translation";}s:7:"package";s:35:"Multilingual - Internationalization";s:4:"core";s:3:"7.x";s:5:"files";a:4:{i:0;s:17:"i18n_taxonomy.inc";i:1;s:23:"i18n_taxonomy.pages.inc";i:2;s:23:"i18n_taxonomy.admin.inc";i:3;s:18:"i18n_taxonomy.test";}s:7:"version";s:8:"7.x-1.26";s:7:"project";s:4:"i18n";s:9:"datestamp";s:10:"1534531985";s:5:"mtime";i:1534531985;s:3:"php";s:5:"5.2.4";s:9:"bootstrap";i:0;}', +)) +->values(array( + 'filename' => 'sites/all/modules/i18n/i18n_translation/i18n_translation.module', + 'name' => 'i18n_translation', + 'type' => 'module', + 'owner' => '', + 'status' => '0', + 'bootstrap' => '0', + 'schema_version' => '-1', + 'weight' => '0', + 'info' => 'a:12:{s:4:"name";s:16:"Translation sets";s:11:"description";s:47:"Simple translation sets API for generic objects";s:12:"dependencies";a:1:{i:0;s:4:"i18n";}s:7:"package";s:35:"Multilingual - Internationalization";s:4:"core";s:3:"7.x";s:5:"files";a:1:{i:0;s:20:"i18n_translation.inc";}s:7:"version";s:8:"7.x-1.26";s:7:"project";s:4:"i18n";s:9:"datestamp";s:10:"1534531985";s:5:"mtime";i:1534531985;s:3:"php";s:5:"5.2.4";s:9:"bootstrap";i:0;}', +)) +->values(array( + 'filename' => 'sites/all/modules/i18n/i18n_user/i18n_user.module', + 'name' => 'i18n_user', + 'type' => 'module', + 'owner' => '', + 'status' => '0', + 'bootstrap' => '0', + 'schema_version' => '-1', + 'weight' => '0', + 'info' => 'a:12:{s:4:"name";s:21:"User mail translation";s:11:"description";s:43:"Translate emails sent from the User module.";s:4:"core";s:3:"7.x";s:7:"package";s:35:"Multilingual - Internationalization";s:12:"dependencies";a:1:{i:0;s:13:"i18n_variable";}s:7:"version";s:8:"7.x-1.26";s:7:"project";s:4:"i18n";s:9:"datestamp";s:10:"1534531985";s:5:"mtime";i:1534531985;s:3:"php";s:5:"5.2.4";s:5:"files";a:0:{}s:9:"bootstrap";i:0;}', +)) +->values(array( + 'filename' => 'sites/all/modules/i18n/i18n_variable/i18n_variable.module', + 'name' => 'i18n_variable', + 'type' => 'module', + 'owner' => '', + 'status' => '1', + 'bootstrap' => '1', + 'schema_version' => '7004', + 'weight' => '-900', + 'info' => 'a:13:{s:4:"name";s:20:"Variable translation";s:11:"description";s:71:"Multilingual variables that switch language depending on page language.";s:12:"dependencies";a:3:{i:0;s:4:"i18n";i:1;s:24:"variable_store (7.x-2.x)";i:2;s:24:"variable_realm (7.x-2.x)";}s:7:"package";s:35:"Multilingual - Internationalization";s:4:"core";s:3:"7.x";s:9:"configure";s:35:"admin/config/regional/i18n/variable";s:5:"files";a:2:{i:0;s:23:"i18n_variable.class.inc";i:1;s:18:"i18n_variable.test";}s:7:"version";s:8:"7.x-1.26";s:7:"project";s:4:"i18n";s:9:"datestamp";s:10:"1534531985";s:5:"mtime";i:1534531985;s:3:"php";s:5:"5.2.4";s:9:"bootstrap";i:0;}', +)) +->values(array( + 'filename' => 'sites/all/modules/i18n/tests/i18n_test.module', + 'name' => 'i18n_test', + 'type' => 'module', + 'owner' => '', + 'status' => '0', + 'bootstrap' => '0', + 'schema_version' => '-1', + 'weight' => '0', + 'info' => 'a:13:{s:4:"name";s:26:"Internationalization tests";s:11:"description";s:55:"Helper module for testing i18n (do not enable manually)";s:12:"dependencies";a:3:{i:0;s:6:"locale";i:1;s:11:"translation";i:2;s:4:"i18n";}s:7:"package";s:7:"Testing";s:4:"core";s:3:"7.x";s:6:"hidden";b:1;s:7:"version";s:8:"7.x-1.26";s:7:"project";s:4:"i18n";s:9:"datestamp";s:10:"1534531985";s:5:"mtime";i:1534531985;s:3:"php";s:5:"5.2.4";s:5:"files";a:0:{}s:9:"bootstrap";i:0;}', )) ->values(array( 'filename' => 'sites/all/modules/link/link.module', @@ -47997,6 +49249,83 @@ 'weight' => '100', 'info' => 'a:13:{s:4:"name";s:5:"Title";s:11:"description";s:50:"Replaces entity legacy fields with regular fields.";s:4:"core";s:3:"7.x";s:7:"package";s:6:"Fields";s:9:"configure";s:26:"admin/config/content/title";s:12:"dependencies";a:1:{i:0;s:14:"system (>7.14)";}s:5:"files";a:3:{i:0;s:12:"title.module";i:1;s:35:"views/views_handler_title_field.inc";i:2;s:16:"tests/title.test";}s:7:"version";s:14:"7.x-1.0-alpha9";s:7:"project";s:5:"title";s:9:"datestamp";s:10:"1484302985";s:5:"mtime";i:1484302985;s:3:"php";s:5:"5.2.4";s:9:"bootstrap";i:0;}', )) +->values(array( + 'filename' => 'sites/all/modules/variable/variable.module', + 'name' => 'variable', + 'type' => 'module', + 'owner' => '', + 'status' => '1', + 'bootstrap' => '1', + 'schema_version' => '0', + 'weight' => '0', + 'info' => 'a:12:{s:4:"name";s:8:"Variable";s:11:"description";s:43:"Variable Information and basic variable API";s:7:"package";s:8:"Variable";s:4:"core";s:3:"7.x";s:5:"files";a:9:{i:0;s:27:"includes/forum.variable.inc";i:1;s:28:"includes/locale.variable.inc";i:2;s:26:"includes/menu.variable.inc";i:3;s:26:"includes/node.variable.inc";i:4;s:28:"includes/system.variable.inc";i:5;s:30:"includes/taxonomy.variable.inc";i:6;s:33:"includes/translation.variable.inc";i:7;s:26:"includes/user.variable.inc";i:8;s:13:"variable.test";}s:7:"version";s:7:"7.x-2.5";s:7:"project";s:8:"variable";s:9:"datestamp";s:10:"1398250128";s:5:"mtime";i:1398250128;s:12:"dependencies";a:0:{}s:3:"php";s:5:"5.2.4";s:9:"bootstrap";i:0;}', +)) +->values(array( + 'filename' => 'sites/all/modules/variable/variable_admin/variable_admin.module', + 'name' => 'variable_admin', + 'type' => 'module', + 'owner' => '', + 'status' => '0', + 'bootstrap' => '0', + 'schema_version' => '-1', + 'weight' => '0', + 'info' => 'a:12:{s:4:"name";s:14:"Variable admin";s:11:"description";s:26:"Variable Administration UI";s:12:"dependencies";a:1:{i:0;s:8:"variable";}s:7:"package";s:8:"Variable";s:4:"core";s:3:"7.x";s:7:"version";s:7:"7.x-2.5";s:7:"project";s:8:"variable";s:9:"datestamp";s:10:"1398250128";s:5:"mtime";i:1398250128;s:3:"php";s:5:"5.2.4";s:5:"files";a:0:{}s:9:"bootstrap";i:0;}', +)) +->values(array( + 'filename' => 'sites/all/modules/variable/variable_example/variable_example.module', + 'name' => 'variable_example', + 'type' => 'module', + 'owner' => '', + 'status' => '0', + 'bootstrap' => '0', + 'schema_version' => '-1', + 'weight' => '0', + 'info' => 'a:12:{s:4:"name";s:16:"Variable example";s:11:"description";s:83:"An example module showing how to use the Variable API and providing some variables.";s:12:"dependencies";a:2:{i:0;s:8:"variable";i:1;s:14:"variable_store";}s:7:"package";s:15:"Example modules";s:4:"core";s:3:"7.x";s:5:"files";a:1:{i:0;s:29:"variable_example.variable.inc";}s:7:"version";s:7:"7.x-2.5";s:7:"project";s:8:"variable";s:9:"datestamp";s:10:"1398250128";s:5:"mtime";i:1398250128;s:3:"php";s:5:"5.2.4";s:9:"bootstrap";i:0;}', +)) +->values(array( + 'filename' => 'sites/all/modules/variable/variable_realm/variable_realm.module', + 'name' => 'variable_realm', + 'type' => 'module', + 'owner' => '', + 'status' => '1', + 'bootstrap' => '1', + 'schema_version' => '7000', + 'weight' => '-1000', + 'info' => 'a:12:{s:4:"name";s:14:"Variable realm";s:11:"description";s:49:"API to use variable realms from different modules";s:12:"dependencies";a:1:{i:0;s:8:"variable";}s:7:"package";s:8:"Variable";s:4:"core";s:3:"7.x";s:7:"version";s:7:"7.x-2.5";s:5:"files";a:2:{i:0;s:24:"variable_realm.class.inc";i:1;s:30:"variable_realm_union.class.inc";}s:7:"project";s:8:"variable";s:9:"datestamp";s:10:"1398250128";s:5:"mtime";i:1398250128;s:3:"php";s:5:"5.2.4";s:9:"bootstrap";i:0;}', +)) +->values(array( + 'filename' => 'sites/all/modules/variable/variable_store/variable_store.module', + 'name' => 'variable_store', + 'type' => 'module', + 'owner' => '', + 'status' => '1', + 'bootstrap' => '1', + 'schema_version' => '7000', + 'weight' => '-1000', + 'info' => 'a:12:{s:4:"name";s:14:"Variable store";s:11:"description";s:60:"Database storage for variable realms. This is an API module.";s:12:"dependencies";a:1:{i:0;s:8:"variable";}s:7:"package";s:8:"Variable";s:4:"core";s:3:"7.x";s:7:"version";s:7:"7.x-2.5";s:5:"files";a:2:{i:0;s:24:"variable_store.class.inc";i:1;s:19:"variable_store.test";}s:7:"project";s:8:"variable";s:9:"datestamp";s:10:"1398250128";s:5:"mtime";i:1398250128;s:3:"php";s:5:"5.2.4";s:9:"bootstrap";i:0;}', +)) +->values(array( + 'filename' => 'sites/all/modules/variable/variable_views/variable_views.module', + 'name' => 'variable_views', + 'type' => 'module', + 'owner' => '', + 'status' => '0', + 'bootstrap' => '0', + 'schema_version' => '-1', + 'weight' => '0', + 'info' => 'a:12:{s:4:"name";s:14:"Variable views";s:11:"description";s:78:"Provides views integration for variable, included a default variable argument.";s:12:"dependencies";a:2:{i:0;s:8:"variable";i:1;s:5:"views";}s:7:"package";s:8:"Variable";s:4:"core";s:3:"7.x";s:5:"files";a:3:{i:0;s:51:"includes/views_plugin_argument_default_variable.inc";i:1;s:47:"includes/views_handler_field_variable_title.inc";i:2;s:47:"includes/views_handler_field_variable_value.inc";}s:7:"version";s:7:"7.x-2.5";s:7:"project";s:8:"variable";s:9:"datestamp";s:10:"1398250128";s:5:"mtime";i:1398250128;s:3:"php";s:5:"5.2.4";s:9:"bootstrap";i:0;}', +)) +->values(array( + 'filename' => 'sites/all/modules/views/tests/views_test.module', + 'name' => 'views_test', + 'type' => 'module', + 'owner' => '', + 'status' => '0', + 'bootstrap' => '0', + 'schema_version' => '-1', + 'weight' => '0', + 'info' => 'a:13:{s:4:"name";s:10:"Views Test";s:11:"description";s:22:"Test module for Views.";s:7:"package";s:5:"Views";s:4:"core";s:3:"7.x";s:12:"dependencies";a:1:{i:0;s:5:"views";}s:6:"hidden";b:1;s:7:"version";s:8:"7.x-3.20";s:7:"project";s:5:"views";s:9:"datestamp";s:10:"1523668093";s:5:"mtime";i:1535762879;s:3:"php";s:5:"5.2.4";s:5:"files";a:0:{}s:9:"bootstrap";i:0;}', +)) ->values(array( 'filename' => 'sites/all/modules/views/views.module', 'name' => 'views', @@ -48064,7 +49393,6 @@ 'info' => "a:17:{s:4:\"name\";s:5:\"Stark\";s:11:\"description\";s:208:\"This theme demonstrates Drupal's default HTML markup and CSS styles. To learn how to build your own theme and override Drupal's default code, see the <a href=\"http://drupal.org/theme-guide\">Theming Guide</a>.\";s:7:\"package\";s:4:\"Core\";s:7:\"version\";s:4:\"7.40\";s:4:\"core\";s:3:\"7.x\";s:11:\"stylesheets\";a:1:{s:3:\"all\";a:1:{s:10:\"layout.css\";s:23:\"themes/stark/layout.css\";}}s:7:\"project\";s:6:\"drupal\";s:9:\"datestamp\";s:10:\"1444866674\";s:6:\"engine\";s:11:\"phptemplate\";s:7:\"regions\";a:9:{s:13:\"sidebar_first\";s:12:\"Left sidebar\";s:14:\"sidebar_second\";s:13:\"Right sidebar\";s:7:\"content\";s:7:\"Content\";s:6:\"header\";s:6:\"Header\";s:6:\"footer\";s:6:\"Footer\";s:11:\"highlighted\";s:11:\"Highlighted\";s:4:\"help\";s:4:\"Help\";s:8:\"page_top\";s:8:\"Page top\";s:11:\"page_bottom\";s:11:\"Page bottom\";}s:8:\"features\";a:9:{i:0;s:4:\"logo\";i:1;s:7:\"favicon\";i:2;s:4:\"name\";i:3;s:6:\"slogan\";i:4;s:17:\"node_user_picture\";i:5;s:20:\"comment_user_picture\";i:6;s:25:\"comment_user_verification\";i:7;s:9:\"main_menu\";i:8;s:14:\"secondary_menu\";}s:10:\"screenshot\";s:27:\"themes/stark/screenshot.png\";s:3:\"php\";s:5:\"5.2.4\";s:7:\"scripts\";a:0:{}s:5:\"mtime\";i:1444866674;s:14:\"regions_hidden\";a:2:{i:0;s:8:\"page_top\";i:1;s:11:\"page_bottom\";}s:28:\"overlay_supplemental_regions\";a:1:{i:0;s:8:\"page_top\";}}", )) ->execute(); - $connection->schema()->createTable('taxonomy_index', array( 'fields' => array( 'nid' => array( @@ -48177,7 +49505,6 @@ 'created' => '1504715432', )) ->execute(); - $connection->schema()->createTable('taxonomy_term_data', array( 'fields' => array( 'tid' => array( @@ -48376,7 +49703,6 @@ 'weight' => '0', )) ->execute(); - $connection->schema()->createTable('taxonomy_term_hierarchy', array( 'fields' => array( 'tid' => array( @@ -48479,7 +49805,6 @@ 'parent' => '6', )) ->execute(); - $connection->schema()->createTable('taxonomy_vocabulary', array( 'fields' => array( 'vid' => array( @@ -48578,7 +49903,6 @@ 'weight' => '0', )) ->execute(); - $connection->schema()->createTable('tracker_node', array( 'fields' => array( 'nid' => array( @@ -48620,7 +49944,6 @@ 'changed' => '1421727536', )) ->execute(); - $connection->schema()->createTable('tracker_user', array( 'fields' => array( 'nid' => array( @@ -48671,7 +49994,6 @@ 'changed' => '1421727536', )) ->execute(); - $connection->schema()->createTable('trigger_assignments', array( 'fields' => array( 'hook' => array( @@ -48712,7 +50034,6 @@ 'weight' => '1', )) ->execute(); - $connection->schema()->createTable('url_alias', array( 'fields' => array( 'pid' => array( @@ -48790,7 +50111,6 @@ 'language' => 'und', )) ->execute(); - $connection->schema()->createTable('users', array( 'fields' => array( 'uid' => array( @@ -48968,7 +50288,6 @@ 'data' => 'a:1:{s:7:"contact";i:1;}', )) ->execute(); - $connection->schema()->createTable('users_roles', array( 'fields' => array( 'uid' => array( @@ -49011,7 +50330,6 @@ 'rid' => '3', )) ->execute(); - $connection->schema()->createTable('variable', array( 'fields' => array( 'name' => array( @@ -49194,12 +50512,12 @@ 'value' => 'a:9:{s:3:"top";s:7:"#d0d0d0";s:6:"bottom";s:7:"#c2c4c5";s:2:"bg";s:7:"#ffffff";s:7:"sidebar";s:7:"#ffffff";s:14:"sidebarborders";s:7:"#cccccc";s:6:"footer";s:7:"#24272c";s:11:"titleslogan";s:7:"#000000";s:4:"text";s:7:"#4a4a4a";s:4:"link";s:7:"#019dbf";}', )) ->values(array( - 'name' => 'color_bartik_stylesheets', - 'value' => 'a:1:{i:0;s:41:"public://color/bartik-e0e23ad7/colors.css";}', + 'name' => 'color_bartik_screenshot', + 'value' => 's:72:"/var/www/drupal/sites/default/files/color/bartik-b69cfcec/screenshot.png";', )) ->values(array( - 'name' => 'color_bartik_screenshot', - 'value' => 's:72:"/var/www/drupal/sites/default/files/color/bartik-b69cfcec/screenshot.png";' + 'name' => 'color_bartik_stylesheets', + 'value' => 'a:1:{i:0;s:41:"public://color/bartik-e0e23ad7/colors.css";}', )) ->values(array( 'name' => 'color_garland_files', @@ -49207,7 +50525,7 @@ )) ->values(array( 'name' => 'color_garland_logo', - 'value' => 's:40:"public://color/garland-b69cfcec/logo.png";' + 'value' => 's:40:"public://color/garland-b69cfcec/logo.png";', )) ->values(array( 'name' => 'color_garland_palette', @@ -49215,7 +50533,7 @@ )) ->values(array( 'name' => 'color_garland_screenshot', - 'value' => 's:73:"/var/www/drupal/sites/default/files/color/garland-b69cfcec/screenshot.png";' + 'value' => 's:73:"/var/www/drupal/sites/default/files/color/garland-b69cfcec/screenshot.png";', )) ->values(array( 'name' => 'color_garland_stylesheets', @@ -49477,6 +50795,10 @@ 'name' => 'empty_timezone_message', 'value' => 'b:1;', )) +->values(array( + 'name' => 'entityreference:base-tables', + 'value' => 'a:6:{s:7:"comment";a:2:{i:0;s:7:"comment";i:1;s:3:"cid";}s:4:"node";a:2:{i:0;s:4:"node";i:1;s:3:"nid";}s:4:"file";a:2:{i:0;s:12:"file_managed";i:1;s:3:"fid";}s:13:"taxonomy_term";a:2:{i:0;s:18:"taxonomy_term_data";i:1;s:3:"tid";}s:19:"taxonomy_vocabulary";a:2:{i:0;s:19:"taxonomy_vocabulary";i:1;s:3:"vid";}s:4:"user";a:2:{i:0;s:5:"users";i:1;s:3:"uid";}}', +)) ->values(array( 'name' => 'entity_translation_entity_types', 'value' => 'a:4:{s:7:"comment";s:7:"comment";s:4:"node";s:4:"node";s:13:"taxonomy_term";s:13:"taxonomy_term";s:4:"user";s:4:"user";}', @@ -49513,10 +50835,6 @@ 'name' => 'feed_item_length', 'value' => 's:8:"fulltext";', )) -->values(array( - 'name' => 'entityreference:base-tables', - 'value' => 'a:6:{s:7:"comment";a:2:{i:0;s:7:"comment";i:1;s:3:"cid";}s:4:"node";a:2:{i:0;s:4:"node";i:1;s:3:"nid";}s:4:"file";a:2:{i:0;s:12:"file_managed";i:1;s:3:"fid";}s:13:"taxonomy_term";a:2:{i:0;s:18:"taxonomy_term_data";i:1;s:3:"tid";}s:19:"taxonomy_vocabulary";a:2:{i:0;s:19:"taxonomy_vocabulary";i:1;s:3:"vid";}s:4:"user";a:2:{i:0;s:5:"users";i:1;s:3:"uid";}}', -)) ->values(array( 'name' => 'field_bundle_settings_comment__comment_node_test_content_type', 'value' => 'a:2:{s:10:"view_modes";a:0:{}s:12:"extra_fields";a:2:{s:4:"form";a:2:{s:6:"author";a:1:{s:6:"weight";s:2:"-2";}s:7:"subject";a:1:{s:6:"weight";s:2:"-1";}}s:7:"display";a:0:{}}}', @@ -49593,6 +50911,10 @@ 'name' => 'forum_per_page', 'value' => 'i:25;', )) +->values(array( + 'name' => 'i18n_node_options_blog', + 'value' => 'a:2:{i:0;s:8:"required";i:1;s:4:"lock";}', +)) ->values(array( 'name' => 'image_jpeg_quality', 'value' => 'i:80;', @@ -49641,10 +50963,6 @@ 'name' => 'language_content_type_test_content_type', 'value' => 's:1:"4";', )) -->values(array( - 'name' => 'i18n_node_options_blog', - 'value' => 'a:2:{i:0;s:8:"required";i:1;s:4:"lock";}', -)) ->values(array( 'name' => 'language_count', 'value' => 'i:3;', @@ -50005,6 +51323,10 @@ 'name' => 'teaser_length', 'value' => 'i:1024;', )) +->values(array( + 'name' => 'theme_bartik_settings', + 'value' => 'a:18:{s:11:"toggle_logo";i:1;s:11:"toggle_name";i:1;s:13:"toggle_slogan";i:1;s:24:"toggle_node_user_picture";i:1;s:27:"toggle_comment_user_picture";i:1;s:32:"toggle_comment_user_verification";i:1;s:14:"toggle_favicon";i:1;s:16:"toggle_main_menu";i:1;s:21:"toggle_secondary_menu";i:1;s:12:"default_logo";i:0;s:9:"logo_path";s:16:"public://gnu.png";s:15:"default_favicon";i:1;s:12:"favicon_path";s:0:"";s:14:"favicon_upload";s:0:"";s:6:"scheme";s:7:"default";s:7:"palette";a:9:{s:3:"top";s:7:"#0779bf";s:6:"bottom";s:7:"#48a9e4";s:2:"bg";s:7:"#ffffff";s:7:"sidebar";s:7:"#f6f6f2";s:14:"sidebarborders";s:7:"#f9f9f9";s:6:"footer";s:7:"#292929";s:11:"titleslogan";s:7:"#fffeff";s:4:"text";s:7:"#3b3b3b";s:4:"link";s:7:"#0071B3";}s:5:"theme";s:6:"bartik";s:4:"info";a:12:{s:6:"fields";a:9:{s:3:"top";s:10:"Header top";s:6:"bottom";s:13:"Header bottom";s:2:"bg";s:15:"Main background";s:7:"sidebar";s:18:"Sidebar background";s:14:"sidebarborders";s:15:"Sidebar borders";s:6:"footer";s:17:"Footer background";s:11:"titleslogan";s:16:"Title and slogan";s:4:"text";s:10:"Text color";s:4:"link";s:10:"Link color";}s:7:"schemes";a:6:{s:7:"default";a:2:{s:5:"title";s:21:"Blue Lagoon (default)";s:6:"colors";a:9:{s:3:"top";s:7:"#0779bf";s:6:"bottom";s:7:"#48a9e4";s:2:"bg";s:7:"#ffffff";s:7:"sidebar";s:7:"#f6f6f2";s:14:"sidebarborders";s:7:"#f9f9f9";s:6:"footer";s:7:"#292929";s:11:"titleslogan";s:7:"#fffeff";s:4:"text";s:7:"#3b3b3b";s:4:"link";s:7:"#0071B3";}}s:9:"firehouse";a:2:{s:5:"title";s:9:"Firehouse";s:6:"colors";a:9:{s:3:"top";s:7:"#cd2d2d";s:6:"bottom";s:7:"#cf3535";s:2:"bg";s:7:"#ffffff";s:7:"sidebar";s:7:"#f1f4f0";s:14:"sidebarborders";s:7:"#ededed";s:6:"footer";s:7:"#1f1d1c";s:11:"titleslogan";s:7:"#fffeff";s:4:"text";s:7:"#3b3b3b";s:4:"link";s:7:"#d6121f";}}s:3:"ice";a:2:{s:5:"title";s:3:"Ice";s:6:"colors";a:9:{s:3:"top";s:7:"#d0d0d0";s:6:"bottom";s:7:"#c2c4c5";s:2:"bg";s:7:"#ffffff";s:7:"sidebar";s:7:"#ffffff";s:14:"sidebarborders";s:7:"#cccccc";s:6:"footer";s:7:"#24272c";s:11:"titleslogan";s:7:"#000000";s:4:"text";s:7:"#4a4a4a";s:4:"link";s:7:"#019dbf";}}s:4:"plum";a:2:{s:5:"title";s:4:"Plum";s:6:"colors";a:9:{s:3:"top";s:7:"#4c1c58";s:6:"bottom";s:7:"#593662";s:2:"bg";s:7:"#fffdf7";s:7:"sidebar";s:7:"#edede7";s:14:"sidebarborders";s:7:"#e7e7e7";s:6:"footer";s:7:"#2c2c28";s:11:"titleslogan";s:7:"#ffffff";s:4:"text";s:7:"#301313";s:4:"link";s:7:"#9d408d";}}s:5:"slate";a:2:{s:5:"title";s:5:"Slate";s:6:"colors";a:9:{s:3:"top";s:7:"#4a4a4a";s:6:"bottom";s:7:"#4e4e4e";s:2:"bg";s:7:"#ffffff";s:7:"sidebar";s:7:"#ffffff";s:14:"sidebarborders";s:7:"#d0d0d0";s:6:"footer";s:7:"#161617";s:11:"titleslogan";s:7:"#ffffff";s:4:"text";s:7:"#3b3b3b";s:4:"link";s:7:"#0073b6";}}s:0:"";a:2:{s:5:"title";s:6:"Custom";s:6:"colors";a:0:{}}}s:3:"css";a:1:{i:0;s:14:"css/colors.css";}s:4:"copy";a:1:{i:0;s:8:"logo.png";}s:9:"gradients";a:1:{i:0;a:3:{s:9:"dimension";a:4:{i:0;i:0;i:1;i:0;i:2;i:0;i:3;i:0;}s:9:"direction";s:8:"vertical";s:6:"colors";a:2:{i:0;s:3:"top";i:1;s:6:"bottom";}}}s:4:"fill";a:0:{}s:6:"slices";a:0:{}s:12:"blend_target";s:7:"#ffffff";s:11:"preview_css";s:17:"color/preview.css";s:10:"preview_js";s:16:"color/preview.js";s:12:"preview_html";s:18:"color/preview.html";s:10:"base_image";s:14:"color/base.png";}}', +)) ->values(array( 'name' => 'theme_default', 'value' => 's:6:"bartik";', @@ -50013,10 +51335,6 @@ 'name' => 'theme_settings', 'value' => 'a:16:{s:11:"toggle_logo";i:0;s:11:"toggle_name";i:1;s:13:"toggle_slogan";i:0;s:24:"toggle_node_user_picture";i:0;s:27:"toggle_comment_user_picture";i:0;s:32:"toggle_comment_user_verification";i:0;s:14:"toggle_favicon";i:0;s:16:"toggle_main_menu";i:0;s:21:"toggle_secondary_menu";i:0;s:12:"default_logo";i:1;s:9:"logo_path";s:23:"public://customlogo.png";s:11:"logo_upload";s:0:"";s:15:"default_favicon";i:0;s:12:"favicon_path";s:24:"public://somefavicon.png";s:14:"favicon_upload";s:0:"";s:16:"favicon_mimetype";s:9:"image/png";}', )) -->values(array( - 'name' => 'theme_bartik_settings', - 'value' => 'a:18:{s:11:"toggle_logo";i:1;s:11:"toggle_name";i:1;s:13:"toggle_slogan";i:1;s:24:"toggle_node_user_picture";i:1;s:27:"toggle_comment_user_picture";i:1;s:32:"toggle_comment_user_verification";i:1;s:14:"toggle_favicon";i:1;s:16:"toggle_main_menu";i:1;s:21:"toggle_secondary_menu";i:1;s:12:"default_logo";i:0;s:9:"logo_path";s:16:"public://gnu.png";s:15:"default_favicon";i:1;s:12:"favicon_path";s:0:"";s:14:"favicon_upload";s:0:"";s:6:"scheme";s:7:"default";s:7:"palette";a:9:{s:3:"top";s:7:"#0779bf";s:6:"bottom";s:7:"#48a9e4";s:2:"bg";s:7:"#ffffff";s:7:"sidebar";s:7:"#f6f6f2";s:14:"sidebarborders";s:7:"#f9f9f9";s:6:"footer";s:7:"#292929";s:11:"titleslogan";s:7:"#fffeff";s:4:"text";s:7:"#3b3b3b";s:4:"link";s:7:"#0071B3";}s:5:"theme";s:6:"bartik";s:4:"info";a:12:{s:6:"fields";a:9:{s:3:"top";s:10:"Header top";s:6:"bottom";s:13:"Header bottom";s:2:"bg";s:15:"Main background";s:7:"sidebar";s:18:"Sidebar background";s:14:"sidebarborders";s:15:"Sidebar borders";s:6:"footer";s:17:"Footer background";s:11:"titleslogan";s:16:"Title and slogan";s:4:"text";s:10:"Text color";s:4:"link";s:10:"Link color";}s:7:"schemes";a:6:{s:7:"default";a:2:{s:5:"title";s:21:"Blue Lagoon (default)";s:6:"colors";a:9:{s:3:"top";s:7:"#0779bf";s:6:"bottom";s:7:"#48a9e4";s:2:"bg";s:7:"#ffffff";s:7:"sidebar";s:7:"#f6f6f2";s:14:"sidebarborders";s:7:"#f9f9f9";s:6:"footer";s:7:"#292929";s:11:"titleslogan";s:7:"#fffeff";s:4:"text";s:7:"#3b3b3b";s:4:"link";s:7:"#0071B3";}}s:9:"firehouse";a:2:{s:5:"title";s:9:"Firehouse";s:6:"colors";a:9:{s:3:"top";s:7:"#cd2d2d";s:6:"bottom";s:7:"#cf3535";s:2:"bg";s:7:"#ffffff";s:7:"sidebar";s:7:"#f1f4f0";s:14:"sidebarborders";s:7:"#ededed";s:6:"footer";s:7:"#1f1d1c";s:11:"titleslogan";s:7:"#fffeff";s:4:"text";s:7:"#3b3b3b";s:4:"link";s:7:"#d6121f";}}s:3:"ice";a:2:{s:5:"title";s:3:"Ice";s:6:"colors";a:9:{s:3:"top";s:7:"#d0d0d0";s:6:"bottom";s:7:"#c2c4c5";s:2:"bg";s:7:"#ffffff";s:7:"sidebar";s:7:"#ffffff";s:14:"sidebarborders";s:7:"#cccccc";s:6:"footer";s:7:"#24272c";s:11:"titleslogan";s:7:"#000000";s:4:"text";s:7:"#4a4a4a";s:4:"link";s:7:"#019dbf";}}s:4:"plum";a:2:{s:5:"title";s:4:"Plum";s:6:"colors";a:9:{s:3:"top";s:7:"#4c1c58";s:6:"bottom";s:7:"#593662";s:2:"bg";s:7:"#fffdf7";s:7:"sidebar";s:7:"#edede7";s:14:"sidebarborders";s:7:"#e7e7e7";s:6:"footer";s:7:"#2c2c28";s:11:"titleslogan";s:7:"#ffffff";s:4:"text";s:7:"#301313";s:4:"link";s:7:"#9d408d";}}s:5:"slate";a:2:{s:5:"title";s:5:"Slate";s:6:"colors";a:9:{s:3:"top";s:7:"#4a4a4a";s:6:"bottom";s:7:"#4e4e4e";s:2:"bg";s:7:"#ffffff";s:7:"sidebar";s:7:"#ffffff";s:14:"sidebarborders";s:7:"#d0d0d0";s:6:"footer";s:7:"#161617";s:11:"titleslogan";s:7:"#ffffff";s:4:"text";s:7:"#3b3b3b";s:4:"link";s:7:"#0073b6";}}s:0:"";a:2:{s:5:"title";s:6:"Custom";s:6:"colors";a:0:{}}}s:3:"css";a:1:{i:0;s:14:"css/colors.css";}s:4:"copy";a:1:{i:0;s:8:"logo.png";}s:9:"gradients";a:1:{i:0;a:3:{s:9:"dimension";a:4:{i:0;i:0;i:1;i:0;i:2;i:0;i:3;i:0;}s:9:"direction";s:8:"vertical";s:6:"colors";a:2:{i:0;s:3:"top";i:1;s:6:"bottom";}}}s:4:"fill";a:0:{}s:6:"slices";a:0:{}s:12:"blend_target";s:7:"#ffffff";s:11:"preview_css";s:17:"color/preview.css";s:10:"preview_js";s:16:"color/preview.js";s:12:"preview_html";s:18:"color/preview.html";s:10:"base_image";s:14:"color/base.png";}}', -)) ->values(array( 'name' => 'theme_seven_settings', 'value' => 'a:15:{s:11:"toggle_logo";i:1;s:11:"toggle_name";i:1;s:13:"toggle_slogan";i:1;s:24:"toggle_node_user_picture";i:1;s:27:"toggle_comment_user_picture";i:0;s:32:"toggle_comment_user_verification";i:1;s:14:"toggle_favicon";i:1;s:16:"toggle_main_menu";i:1;s:21:"toggle_secondary_menu";i:0;s:12:"default_logo";i:1;s:9:"logo_path";s:0:"";s:11:"logo_upload";s:0:"";s:15:"default_favicon";i:1;s:12:"favicon_path";s:0:"";s:14:"favicon_upload";s:0:"";}', @@ -50197,8 +51515,280 @@ 'name' => 'user_signatures', 'value' => 'i:0;', )) +->values(array( + 'name' => 'variable_module_list', + 'value' => 'a:4:{s:6:"locale";a:5:{i:0;s:29:"language_content_type_article";i:1;s:26:"language_content_type_page";i:2;s:26:"language_content_type_book";i:3;s:39:"language_content_type_test_content_type";i:4;s:16:"language_default";}s:4:"i18n";a:1:{i:0;s:18:"i18n_language_list";}s:14:"variable_realm";a:4:{i:0;s:26:"variable_realm_list_global";i:1;s:28:"variable_realm_list_language";i:2;s:28:"variable_realm_weight_global";i:3;s:30:"variable_realm_weight_language";}s:13:"i18n_variable";a:2:{i:0;s:18:"i18n_variable_conf";i:1;s:18:"i18n_variable_list";}}', +)) +->values(array( + 'name' => 'variable_realm_list_language', + 'value' => 'a:3:{i:0;s:9:"site_name";i:1;s:11:"site_slogan";i:2;s:24:"maintenance_mode_message";}', +)) ->execute(); +$connection->schema()->createTable('variable_store', array( + 'fields' => array( + 'realm' => array( + 'type' => 'varchar', + 'not null' => TRUE, + 'length' => '50', + 'default' => '', + ), + 'realm_key' => array( + 'type' => 'varchar', + 'not null' => TRUE, + 'length' => '50', + 'default' => '', + ), + 'name' => array( + 'type' => 'varchar', + 'not null' => TRUE, + 'length' => '128', + 'default' => '', + ), + 'value' => array( + 'type' => 'text', + 'not null' => TRUE, + 'size' => 'big', + ), + 'serialized' => array( + 'type' => 'int', + 'not null' => TRUE, + 'size' => 'small', + 'default' => '1', + ), + ), + 'primary key' => array( + 'realm', + 'realm_key', + 'name', + ), + 'indexes' => array( + 'realm_value' => array( + 'realm', + 'realm_key', + ), + ), + 'mysql_character_set' => 'utf8', +)); +$connection->insert('variable_store') +->fields(array( + 'realm', + 'realm_key', + 'name', + 'value', + 'serialized', +)) +->values(array( + 'realm' => 'language', + 'realm_key' => 'is', + 'name' => 'anonymous', + 'value' => 'is - anonymous', + 'serialized' => '0', +)) +->values(array( + 'realm' => 'language', + 'realm_key' => 'is', + 'name' => 'maintenance_mode_message', + 'value' => 'is - This is a custom maintenance mode message.', + 'serialized' => '0', +)) +->values(array( + 'realm' => 'language', + 'realm_key' => 'fr', + 'name' => 'site_403', + 'value' => 'node', + 'serialized' => '0', +)) +->values(array( + 'realm' => 'language', + 'realm_key' => 'is', + 'name' => 'site_403', + 'value' => 'node/1', + 'serialized' => '0', +)) +->values(array( + 'realm' => 'language', + 'realm_key' => 'fr', + 'name' => 'site_404', + 'value' => 'node', + 'serialized' => '0', +)) +->values(array( + 'realm' => 'language', + 'realm_key' => 'is', + 'name' => 'site_404', + 'value' => 'node/6', + 'serialized' => '0', +)) +->values(array( + 'realm' => 'language', + 'realm_key' => 'fr', + 'name' => 'site_frontpage', + 'value' => 'node', + 'serialized' => '0', +)) +->values(array( + 'realm' => 'language', + 'realm_key' => 'is', + 'name' => 'site_frontpage', + 'value' => 'node/4', + 'serialized' => '0', +)) +->values(array( + 'realm' => 'language', + 'realm_key' => 'fr', + 'name' => 'site_name', + 'value' => 'The Site Name', + 'serialized' => '0', +)) +->values(array( + 'realm' => 'language', + 'realm_key' => 'is', + 'name' => 'site_name', + 'value' => 'is - The Site Name', + 'serialized' => '0', +)) +->values(array( + 'realm' => 'language', + 'realm_key' => 'fr', + 'name' => 'site_slogan', + 'value' => 'fr - The Slogan', + 'serialized' => '0', +)) +->values(array( + 'realm' => 'language', + 'realm_key' => 'is', + 'name' => 'site_slogan', + 'value' => 'is - The Slogan', + 'serialized' => '0', +)) +->values(array( + 'realm' => 'language', + 'realm_key' => 'en', + 'name' => 'user_default_timezone', + 'value' => '2', + 'serialized' => '0', +)) +->values(array( + 'realm' => 'language', + 'realm_key' => 'fr', + 'name' => 'user_default_timezone', + 'value' => '0', + 'serialized' => '0', +)) +->values(array( + 'realm' => 'language', + 'realm_key' => 'is', + 'name' => 'user_mail_cancel_confirm_body', + 'value' => 'is - A little birdie said you wanted to cancel your account.', + 'serialized' => '0', +)) +->values(array( + 'realm' => 'language', + 'realm_key' => 'is', + 'name' => 'user_mail_cancel_confirm_subject', + 'value' => 'is - Are you sure?', + 'serialized' => '0', +)) +->values(array( + 'realm' => 'language', + 'realm_key' => 'is', + 'name' => 'user_mail_password_reset_body', + 'value' => "is - Nope! You're locked out forever.", + 'serialized' => '0', +)) +->values(array( + 'realm' => 'language', + 'realm_key' => 'is', + 'name' => 'user_mail_password_reset_subject', + 'value' => 'is - Fix your password', + 'serialized' => '0', +)) +->values(array( + 'realm' => 'language', + 'realm_key' => 'is', + 'name' => 'user_mail_register_admin_created_body', + 'value' => "is - ...and she could take it away.\r\n[site:name], [site:url]", + 'serialized' => '0', +)) +->values(array( + 'realm' => 'language', + 'realm_key' => 'is', + 'name' => 'user_mail_register_admin_created_subject', + 'value' => 'is - Gawd made you an account', + 'serialized' => '0', +)) +->values(array( + 'realm' => 'language', + 'realm_key' => 'is', + 'name' => 'user_mail_register_no_approval_required_body', + 'value' => 'is - You can now log in if you can figure out how to use Drupal!', + 'serialized' => '0', +)) +->values(array( + 'realm' => 'language', + 'realm_key' => 'is', + 'name' => 'user_mail_register_no_approval_required_subject', + 'value' => 'is - Welcome!', + 'serialized' => '0', +)) +->values(array( + 'realm' => 'language', + 'realm_key' => 'is', + 'name' => 'user_mail_register_pending_approval_body', + 'value' => 'is - ...you will join our Circle. Let the Drupal flow through you.', + 'serialized' => '0', +)) +->values(array( + 'realm' => 'language', + 'realm_key' => 'is', + 'name' => 'user_mail_register_pending_approval_subject', + 'value' => 'is - Soon...', + 'serialized' => '0', +)) +->values(array( + 'realm' => 'language', + 'realm_key' => 'is', + 'name' => 'user_mail_status_activated_body', + 'value' => 'is - Your account was activated, and there was much rejoicing.', + 'serialized' => '0', +)) +->values(array( + 'realm' => 'language', + 'realm_key' => 'is', + 'name' => 'user_mail_status_activated_subject', + 'value' => 'is - Your account is approved!', + 'serialized' => '0', +)) +->values(array( + 'realm' => 'language', + 'realm_key' => 'is', + 'name' => 'user_mail_status_blocked_body', + 'value' => 'is - You no longer please the robot overlords. Go to your room and chill out.', + 'serialized' => '0', +)) +->values(array( + 'realm' => 'language', + 'realm_key' => 'is', + 'name' => 'user_mail_status_blocked_subject', + 'value' => 'is - BEGONE!', + 'serialized' => '0', +)) +->values(array( + 'realm' => 'language', + 'realm_key' => 'is', + 'name' => 'user_mail_status_canceled_body', + 'value' => 'is - The gates of Drupal are closed to you. Now you will work in the salt mines.', + 'serialized' => '0', +)) +->values(array( + 'realm' => 'language', + 'realm_key' => 'is', + 'name' => 'user_mail_status_canceled_subject', + 'value' => 'is - So long, bub', + 'serialized' => '0', +)) +->execute(); $connection->schema()->createTable('watchdog', array( 'fields' => array( 'wid' => array( diff --git a/web/core/modules/migrate_drupal/tests/src/Kernel/Plugin/migrate/source/ContentEntityTest.php b/web/core/modules/migrate_drupal/tests/src/Kernel/Plugin/migrate/source/ContentEntityTest.php index 1bcedcfa67663ff990c0bbc6e11a86350dfb022c..cf5d3da4f89f39d780a3f3dcda974dd8d4e9e1fb 100644 --- a/web/core/modules/migrate_drupal/tests/src/Kernel/Plugin/migrate/source/ContentEntityTest.php +++ b/web/core/modules/migrate_drupal/tests/src/Kernel/Plugin/migrate/source/ContentEntityTest.php @@ -5,7 +5,6 @@ use Drupal\Component\Plugin\Exception\InvalidPluginDefinitionException; use Drupal\Core\Field\FieldStorageDefinitionInterface; use Drupal\Core\Language\LanguageInterface; -use Drupal\field\Tests\EntityReference\EntityReferenceTestTrait; use Drupal\file\Entity\File; use Drupal\KernelTests\KernelTestBase; use Drupal\language\Entity\ConfigurableLanguage; @@ -16,6 +15,7 @@ use Drupal\node\Entity\NodeType; use Drupal\taxonomy\Entity\Term; use Drupal\taxonomy\Entity\Vocabulary; +use Drupal\Tests\field\Traits\EntityReferenceTestTrait; use Drupal\Tests\media\Traits\MediaTypeCreationTrait; use Drupal\user\Entity\User; @@ -371,7 +371,7 @@ public function testMediaSource() { $values = $media_source->current()->getSource(); $this->assertEquals(1, $values['mid']); $this->assertEquals('Foo media', $values['name'][0]['value']); - $this->assertEquals('Foo media', $values['thumbnail'][0]['title']); + $this->assertNull($values['thumbnail'][0]['title']); $this->assertEquals(1, $values['uid'][0]['target_id']); $this->assertEquals('image', $values['bundle'][0]['target_id']); } diff --git a/web/core/modules/migrate_drupal/tests/src/Kernel/Plugin/migrate/source/d6/i18nVariableTest.php b/web/core/modules/migrate_drupal/tests/src/Kernel/Plugin/migrate/source/d6/i18nVariableTest.php index 8c3e6044eb527c347369a798ed4ee2f54c3d8803..d2a3d0f572c4281da996907f54924789d89b34b8 100644 --- a/web/core/modules/migrate_drupal/tests/src/Kernel/Plugin/migrate/source/d6/i18nVariableTest.php +++ b/web/core/modules/migrate_drupal/tests/src/Kernel/Plugin/migrate/source/d6/i18nVariableTest.php @@ -10,6 +10,7 @@ * @covers \Drupal\migrate_drupal\Plugin\migrate\source\d6\i18nVariable * * @group migrate_drupal + * @group legacy */ class i18nVariableTest extends MigrateSqlSourceTestBase { diff --git a/web/core/modules/migrate_drupal/tests/src/Kernel/Plugin/migrate/source/d7/VariableTranslationTest.php b/web/core/modules/migrate_drupal/tests/src/Kernel/Plugin/migrate/source/d7/VariableTranslationTest.php new file mode 100644 index 0000000000000000000000000000000000000000..685590647b1c2b71859b8bf7c03d1e210e72d0ea --- /dev/null +++ b/web/core/modules/migrate_drupal/tests/src/Kernel/Plugin/migrate/source/d7/VariableTranslationTest.php @@ -0,0 +1,77 @@ +<?php + +namespace Drupal\Tests\migrate_drupal\Kernel\Plugin\migrate\source\d7; + +use Drupal\Tests\migrate\Kernel\MigrateSqlSourceTestBase; + +/** + * Tests the variable source plugin. + * + * @covers \Drupal\migrate_drupal\Plugin\migrate\source\d7\VariableTranslation + * + * @group migrate_drupal + */ +class VariableTranslationTest extends MigrateSqlSourceTestBase { + + /** + * {@inheritdoc} + */ + public static $modules = ['migrate_drupal']; + + /** + * {@inheritdoc} + */ + public function providerSource() { + $tests = []; + + // The source data. + $tests[0]['source_data']['variable_store'] = [ + [ + 'realm' => 'language', + 'realm_key' => 'fr', + 'name' => 'site_slogan', + 'value' => 'fr - site slogan', + 'serialized' => '0', + ], + [ + 'realm' => 'language', + 'realm_key' => 'fr', + 'name' => 'user_mail_status_blocked_subject', + 'value' => 'fr - BEGONE!', + 'serialized' => '0', + ], + [ + 'realm' => 'language', + 'realm_key' => 'is', + 'name' => 'site_slogan', + 'value' => 's:16:"is - site slogan";', + 'serialized' => '1', + ], + ]; + + // The expected results. + $tests[0]['expected_data'] = [ + [ + 'language' => 'fr', + 'site_slogan' => 'fr - site slogan', + 'user_mail_status_blocked_subject' => 'fr - BEGONE!', + ], + [ + 'language' => 'is', + 'site_slogan' => 'is - site slogan', + ], + ]; + + // The expected count. + $tests[0]['expected_count'] = NULL; + + // The migration configuration. + $tests[0]['configuration']['variables'] = [ + 'site_slogan', + 'user_mail_status_blocked_subject', + ]; + + return $tests; + } + +} diff --git a/web/core/modules/migrate_drupal/tests/src/Kernel/d6/MigrateDrupal6AuditIdsTest.php b/web/core/modules/migrate_drupal/tests/src/Kernel/d6/MigrateDrupal6AuditIdsTest.php index 961a5c549af5dcb09a4b271a642c2ad964b6c992..a02853f6e12faa834eb871283bbfd3a9cdf3e150 100644 --- a/web/core/modules/migrate_drupal/tests/src/Kernel/d6/MigrateDrupal6AuditIdsTest.php +++ b/web/core/modules/migrate_drupal/tests/src/Kernel/d6/MigrateDrupal6AuditIdsTest.php @@ -59,7 +59,7 @@ public function testMultipleMigrationWithoutIdConflicts() { $node->moderation_state->value = 'published'; $node->save(); - // Insert data in the d6_node:page migration mappping table to simulate a + // Insert data in the d6_node:page migration mapping table to simulate a // previously migrated node. $id_map = $this->getMigration('d6_node:page')->getIdMap(); $table_name = $id_map->mapTableName(); @@ -158,8 +158,8 @@ public function testDraftRevisionIdConflicts() { $node->setNewRevision(TRUE); $node->save(); - // Insert data in the d6_node_revision:page migration mappping table to - // simulate a previously migrated node revison. + // Insert data in the d6_node_revision:page migration mapping table to + // simulate a previously migrated node revision. $id_map = $this->getMigration('d6_node_revision:page')->getIdMap(); $table_name = $id_map->mapTableName(); $id_map->getDatabase()->insert($table_name) diff --git a/web/core/modules/migrate_drupal/tests/src/Kernel/d7/MigrateDrupal7AuditIdsTest.php b/web/core/modules/migrate_drupal/tests/src/Kernel/d7/MigrateDrupal7AuditIdsTest.php index 385915775c164aaa56149689fb96a032cf107765..1693ce16232097692a1fd852d081285fd5586c6c 100644 --- a/web/core/modules/migrate_drupal/tests/src/Kernel/d7/MigrateDrupal7AuditIdsTest.php +++ b/web/core/modules/migrate_drupal/tests/src/Kernel/d7/MigrateDrupal7AuditIdsTest.php @@ -59,7 +59,7 @@ public function testMultipleMigrationWithoutIdConflicts() { $node->moderation_state->value = 'published'; $node->save(); - // Insert data in the d7_node:page migration mappping table to simulate a + // Insert data in the d7_node:page migration mapping table to simulate a // previously migrated node. $id_map = $this->getMigration('d7_node:page')->getIdMap(); $table_name = $id_map->mapTableName(); @@ -157,8 +157,8 @@ public function testDraftRevisionIdConflicts() { $node->setNewRevision(TRUE); $node->save(); - // Insert data in the d7_node_revision:page migration mappping table to - // simulate a previously migrated node revison. + // Insert data in the d7_node_revision:page migration mapping table to + // simulate a previously migrated node revision. $id_map = $this->getMigration('d7_node_revision:page')->getIdMap(); $table_name = $id_map->mapTableName(); $id_map->getDatabase()->insert($table_name) diff --git a/web/core/modules/migrate_drupal/tests/src/Unit/source/DrupalSqlBaseTest.php b/web/core/modules/migrate_drupal/tests/src/Unit/source/DrupalSqlBaseTest.php index ebd9334a2d4fe1feb062da020b7a3750246ff258..fdaf4b10af7ca99ea67c8be49abcb425e5725108 100644 --- a/web/core/modules/migrate_drupal/tests/src/Unit/source/DrupalSqlBaseTest.php +++ b/web/core/modules/migrate_drupal/tests/src/Unit/source/DrupalSqlBaseTest.php @@ -63,6 +63,22 @@ public function testSourceProviderNotActive() { } } + /** + * @covers ::checkRequirements + */ + public function testSourceDatabaseError() { + $plugin_definition['requirements_met'] = TRUE; + $plugin_definition['source_module'] = 'module1'; + /** @var \Drupal\Core\State\StateInterface $state */ + $state = $this->getMock('Drupal\Core\State\StateInterface'); + /** @var \Drupal\Core\Entity\EntityManagerInterface $entity_manager */ + $entity_manager = $this->getMock('Drupal\Core\Entity\EntityManagerInterface'); + $plugin = new TestDrupalSqlBase([], 'test', $plugin_definition, $this->getMigration(), $state, $entity_manager); + $system_data = $plugin->getSystemData(); + $this->setExpectedException(RequirementsException::class, 'No database connection configured for source plugin test'); + $plugin->checkRequirements(); + } + } namespace Drupal\Tests\migrate_drupal\Unit\source; diff --git a/web/core/modules/migrate_drupal/tests/src/Unit/source/d6/VariableTranslationTest.php b/web/core/modules/migrate_drupal/tests/src/Unit/source/d6/VariableTranslationTest.php index 1d7f2d944bc4876d831add8e64a069e405979eb2..4b548923d29b5ab67a4caa2af6664be8d7bbdc3f 100644 --- a/web/core/modules/migrate_drupal/tests/src/Unit/source/d6/VariableTranslationTest.php +++ b/web/core/modules/migrate_drupal/tests/src/Unit/source/d6/VariableTranslationTest.php @@ -8,6 +8,7 @@ * Tests the variable source plugin. * * @group migrate_drupal + * @group legacy */ class VariableTranslationTest extends MigrateSqlSourceTestCase { diff --git a/web/core/modules/migrate_drupal_ui/src/Batch/MigrateUpgradeImportBatch.php b/web/core/modules/migrate_drupal_ui/src/Batch/MigrateUpgradeImportBatch.php index 0543bb70320632c02fda1cf9964f8242ae3857a8..c9c19a5c30a46a7762cdcbf5006fd9f602278d83 100644 --- a/web/core/modules/migrate_drupal_ui/src/Batch/MigrateUpgradeImportBatch.php +++ b/web/core/modules/migrate_drupal_ui/src/Batch/MigrateUpgradeImportBatch.php @@ -262,7 +262,7 @@ public static function finished($success, $results, $operations, $elapsed) { } // If we had failures, log them and show the migration failed. if ($failures > 0) { - \Drupal::messenger()->addStatus(\Drupal::translation() + \Drupal::messenger()->addError(\Drupal::translation() ->formatPlural($failures, '1 upgrade failed', '@count upgrades failed')); \Drupal::messenger()->addError(t('Upgrade process not completed')); } diff --git a/web/core/modules/migrate_drupal_ui/tests/src/Functional/d6/MigrateUpgrade6ReviewPageTest.php b/web/core/modules/migrate_drupal_ui/tests/src/Functional/d6/MigrateUpgrade6ReviewPageTest.php index d2fe095b5044ad2b8f885f604624a3081085772d..91657f742a067ef7a8d38b82dc9a5e80cb107191 100644 --- a/web/core/modules/migrate_drupal_ui/tests/src/Functional/d6/MigrateUpgrade6ReviewPageTest.php +++ b/web/core/modules/migrate_drupal_ui/tests/src/Functional/d6/MigrateUpgrade6ReviewPageTest.php @@ -65,6 +65,7 @@ protected function getAvailablePaths() { 'forum', 'i18n', 'i18nblocks', + 'i18ncck', 'i18nmenu', 'i18nprofile', 'i18nstrings', @@ -142,7 +143,6 @@ protected function getMissingPaths() { 'devel', 'devel_generate', 'devel_node_access', - 'i18ncck', 'i18ncontent', 'i18npoll', 'i18nsync', diff --git a/web/core/modules/migrate_drupal_ui/tests/src/Functional/d6/MigrateUpgrade6Test.php b/web/core/modules/migrate_drupal_ui/tests/src/Functional/d6/MigrateUpgrade6Test.php index d8ffd0296437255a4a8a806ee7fb09973e9c9fbe..b37b45b638a97178c4315d86a450ad005c236be9 100644 --- a/web/core/modules/migrate_drupal_ui/tests/src/Functional/d6/MigrateUpgrade6Test.php +++ b/web/core/modules/migrate_drupal_ui/tests/src/Functional/d6/MigrateUpgrade6Test.php @@ -60,21 +60,21 @@ protected function getEntityCounts() { 'block' => 35, 'block_content' => 2, 'block_content_type' => 1, - 'comment' => 6, + 'comment' => 8, // The 'standard' profile provides the 'comment' comment type, and the // migration creates 12 comment types, one per node type. 'comment_type' => 13, 'contact_form' => 5, 'configurable_language' => 5, 'editor' => 2, - 'field_config' => 89, - 'field_storage_config' => 63, + 'field_config' => 90, + 'field_storage_config' => 64, 'file' => 7, 'filter_format' => 7, 'image_style' => 5, - 'language_content_settings' => 3, + 'language_content_settings' => 10, 'migration' => 105, - 'node' => 17, + 'node' => 18, // The 'book' module provides the 'book' node type, and the migration // creates 12 node types. 'node_type' => 13, @@ -84,7 +84,7 @@ protected function getEntityCounts() { 'shortcut_set' => 1, 'action' => 23, 'menu' => 8, - 'taxonomy_term' => 8, + 'taxonomy_term' => 15, 'taxonomy_vocabulary' => 7, 'tour' => 5, 'user' => 7, @@ -106,13 +106,13 @@ protected function getEntityCounts() { protected function getEntityCountsIncremental() { $counts = $this->getEntityCounts(); $counts['block_content'] = 3; - $counts['comment'] = 7; + $counts['comment'] = 9; $counts['entity_view_display'] = 55; $counts['entity_view_mode'] = 14; $counts['file'] = 8; $counts['menu_link_content'] = 11; - $counts['node'] = 18; - $counts['taxonomy_term'] = 9; + $counts['node'] = 19; + $counts['taxonomy_term'] = 16; $counts['user'] = 8; $counts['view'] = 16; return $counts; @@ -137,6 +137,7 @@ protected function getAvailablePaths() { 'forum', 'i18n', 'i18nblocks', + 'i18ncck', 'i18nmenu', 'i18nprofile', 'i18nstrings', @@ -179,7 +180,6 @@ protected function getAvailablePaths() { */ protected function getMissingPaths() { return [ - 'i18ncck', 'i18ncontent', ]; } diff --git a/web/core/modules/migrate_drupal_ui/tests/src/Functional/d7/MigrateUpgrade7NoMultilingualTest.php b/web/core/modules/migrate_drupal_ui/tests/src/Functional/d7/MigrateUpgrade7NoMultilingualTest.php index 350c10295c2a0606171fb82544f4026a0f28488c..a8f51e7718d391a0b11e8aee6229113e48b3aed8 100644 --- a/web/core/modules/migrate_drupal_ui/tests/src/Functional/d7/MigrateUpgrade7NoMultilingualTest.php +++ b/web/core/modules/migrate_drupal_ui/tests/src/Functional/d7/MigrateUpgrade7NoMultilingualTest.php @@ -20,6 +20,7 @@ class MigrateUpgrade7NoMultilingualTest extends MigrateUpgradeExecuteTestBase { 'file', 'language', 'content_translation', + 'config_translation', 'migrate_drupal_ui', 'telephone', 'aggregator', @@ -61,7 +62,7 @@ protected function getEntityCounts() { 'configurable_language' => 4, 'contact_form' => 3, 'editor' => 2, - 'field_config' => 67, + 'field_config' => 68, 'field_storage_config' => 50, 'file' => 3, 'filter_format' => 7, @@ -207,7 +208,7 @@ public function testMigrateUpgradeExecute() { } $edits = $this->translatePostValues($edit); $this->drupalPostForm(NULL, $edits, t('Review upgrade')); - $session->pageTextContains("Install migrate_drupal_multilingual to run migration 'd7_node_entity_translation:article'."); + $session->pageTextContains("Install migrate_drupal_multilingual to run migration 'd7_system_maintenance_translation'."); } } diff --git a/web/core/modules/migrate_drupal_ui/tests/src/Functional/d7/MigrateUpgrade7ReviewPageTest.php b/web/core/modules/migrate_drupal_ui/tests/src/Functional/d7/MigrateUpgrade7ReviewPageTest.php index c1686db643738913d0dad42401a7bbd1faae99cc..9e68d9dba15b84bfd2a93aed0eaefb92b496cec7 100644 --- a/web/core/modules/migrate_drupal_ui/tests/src/Functional/d7/MigrateUpgrade7ReviewPageTest.php +++ b/web/core/modules/migrate_drupal_ui/tests/src/Functional/d7/MigrateUpgrade7ReviewPageTest.php @@ -65,6 +65,7 @@ protected function getAvailablePaths() { 'filter', 'forum', 'image', + 'i18n_block', 'language', 'link', 'list', @@ -138,6 +139,28 @@ protected function getAvailablePaths() { */ protected function getMissingPaths() { return [ + 'entity_translation_i18n_menu', + 'entity_translation_upgrade', + 'i18n', + 'i18n_contact', + 'i18n_field', + 'i18n_forum', + 'i18n_menu', + 'i18n_node', + 'i18n_path', + 'i18n_redirect', + 'i18n_select', + 'i18n_string', + 'i18n_sync', + 'i18n_taxonomy', + 'i18n_translation', + 'i18n_user', + 'i18n_variable', + 'variable', + 'variable_admin', + 'variable_realm', + 'variable_store', + 'variable_views', 'views', ]; } diff --git a/web/core/modules/migrate_drupal_ui/tests/src/Functional/d7/MigrateUpgrade7Test.php b/web/core/modules/migrate_drupal_ui/tests/src/Functional/d7/MigrateUpgrade7Test.php index c5fbacc1a11c9541be75a9464098e1fc6b25b224..b1718011f0917e6e1097288c7df2d6a85461ec4c 100644 --- a/web/core/modules/migrate_drupal_ui/tests/src/Functional/d7/MigrateUpgrade7Test.php +++ b/web/core/modules/migrate_drupal_ui/tests/src/Functional/d7/MigrateUpgrade7Test.php @@ -23,12 +23,14 @@ class MigrateUpgrade7Test extends MigrateUpgradeExecuteTestBase { public static $modules = [ 'file', 'language', + 'config_translation', 'content_translation', 'migrate_drupal_ui', 'telephone', 'aggregator', 'book', 'forum', + 'rdf', 'statistics', 'migration_provider_test', // Required for translation migrations. @@ -60,7 +62,7 @@ protected function getEntityCounts() { 'block' => 25, 'block_content' => 1, 'block_content_type' => 1, - 'comment' => 2, + 'comment' => 3, // The 'standard' profile provides the 'comment' comment type, and the // migration creates 6 comment types, one per node type. 'comment_type' => 7, @@ -86,7 +88,7 @@ protected function getEntityCounts() { 'menu' => 6, 'taxonomy_term' => 18, 'taxonomy_vocabulary' => 4, - 'tour' => 4, + 'tour' => 5, 'user' => 4, 'user_role' => 3, 'menu_link_content' => 12, @@ -106,7 +108,7 @@ protected function getEntityCounts() { protected function getEntityCountsIncremental() { $counts = $this->getEntityCounts(); $counts['block_content'] = 2; - $counts['comment'] = 3; + $counts['comment'] = 4; $counts['file'] = 4; $counts['menu_link_content'] = 13; $counts['node'] = 6; @@ -135,6 +137,7 @@ protected function getAvailablePaths() { 'file', 'filter', 'forum', + 'i18n_variable', 'image', 'language', 'link', @@ -176,6 +179,10 @@ protected function getAvailablePaths() { */ protected function getMissingPaths() { return [ + 'i18n', + 'variable', + 'variable_realm', + 'variable_store', // These modules are in the missing path list because they are installed // on the source site but they are not installed on the destination site. 'syslog', diff --git a/web/core/modules/node/node.api.php b/web/core/modules/node/node.api.php index e18cf66df56d67316dcb499942f7a4c1451886ed..a5f4e9e36823331a8ff0427811091568de4b7886 100644 --- a/web/core/modules/node/node.api.php +++ b/web/core/modules/node/node.api.php @@ -338,19 +338,19 @@ function hook_node_access(\Drupal\node\NodeInterface $node, $op, \Drupal\Core\Se return AccessResult::allowedIfHasPermission($account, 'create ' . $type . ' content'); case 'update': - if ($account->hasPermission('edit any ' . $type . ' content', $account)) { + if ($account->hasPermission('edit any ' . $type . ' content')) { return AccessResult::allowed()->cachePerPermissions(); } else { - return AccessResult::allowedIf($account->hasPermission('edit own ' . $type . ' content', $account) && ($account->id() == $node->getOwnerId()))->cachePerPermissions()->cachePerUser()->addCacheableDependency($node); + return AccessResult::allowedIf($account->hasPermission('edit own ' . $type . ' content') && ($account->id() == $node->getOwnerId()))->cachePerPermissions()->cachePerUser()->addCacheableDependency($node); } case 'delete': - if ($account->hasPermission('delete any ' . $type . ' content', $account)) { + if ($account->hasPermission('delete any ' . $type . ' content')) { return AccessResult::allowed()->cachePerPermissions(); } else { - return AccessResult::allowedIf($account->hasPermission('delete own ' . $type . ' content', $account) && ($account->id() == $node->getOwnerId()))->cachePerPermissions()->cachePerUser()->addCacheableDependency($node); + return AccessResult::allowedIf($account->hasPermission('delete own ' . $type . ' content') && ($account->id() == $node->getOwnerId()))->cachePerPermissions()->cachePerUser()->addCacheableDependency($node); } default: diff --git a/web/core/modules/node/node.module b/web/core/modules/node/node.module index 818fc899ac30b075c0a34b8f53c8087aa2a0ba9c..b2df3783ad5c3e94d5dc0175cb801e191660595e 100644 --- a/web/core/modules/node/node.module +++ b/web/core/modules/node/node.module @@ -28,6 +28,7 @@ use Drupal\node\Entity\NodeType; use Drupal\node\NodeInterface; use Drupal\node\NodeTypeInterface; +use Drupal\user\UserInterface; /** * Denotes that the node is not published. @@ -713,7 +714,7 @@ function node_ranking() { /** * Implements hook_user_cancel(). */ -function node_user_cancel($edit, $account, $method) { +function node_user_cancel($edit, UserInterface $account, $method) { switch ($method) { case 'user_cancel_block_unpublish': // Unpublish nodes (current revisions). @@ -943,19 +944,19 @@ function node_node_access(NodeInterface $node, $op, $account) { return AccessResult::allowedIfHasPermission($account, 'create ' . $type . ' content'); case 'update': - if ($account->hasPermission('edit any ' . $type . ' content', $account)) { + if ($account->hasPermission('edit any ' . $type . ' content')) { return AccessResult::allowed()->cachePerPermissions(); } else { - return AccessResult::allowedIf($account->hasPermission('edit own ' . $type . ' content', $account) && ($account->id() == $node->getOwnerId()))->cachePerPermissions()->cachePerUser()->addCacheableDependency($node); + return AccessResult::allowedIf($account->hasPermission('edit own ' . $type . ' content') && ($account->id() == $node->getOwnerId()))->cachePerPermissions()->cachePerUser()->addCacheableDependency($node); } case 'delete': - if ($account->hasPermission('delete any ' . $type . ' content', $account)) { + if ($account->hasPermission('delete any ' . $type . ' content')) { return AccessResult::allowed()->cachePerPermissions(); } else { - return AccessResult::allowedIf($account->hasPermission('delete own ' . $type . ' content', $account) && ($account->id() == $node->getOwnerId()))->cachePerPermissions()->cachePerUser()->addCacheableDependency($node); + return AccessResult::allowedIf($account->hasPermission('delete own ' . $type . ' content') && ($account->id() == $node->getOwnerId()))->cachePerPermissions()->cachePerUser()->addCacheableDependency($node); } default: diff --git a/web/core/modules/node/node.post_update.php b/web/core/modules/node/node.post_update.php index 43e3cd6acc32935142d61ea0109bd6f3b7ad8a99..913137757c2bddeaf66e43e58254242fa0ec61ac 100644 --- a/web/core/modules/node/node.post_update.php +++ b/web/core/modules/node/node.post_update.php @@ -27,3 +27,10 @@ function node_post_update_configure_status_field_widget() { ])->save(); } } + +/** + * Clear caches due to updated views data. + */ +function node_post_update_node_revision_views_data() { + // Empty post-update hook. +} diff --git a/web/core/modules/node/src/NodeViewsData.php b/web/core/modules/node/src/NodeViewsData.php index 2e095648c4d704801bd0f69967b977884970343e..35ef2978ea09eb55d02ea4380b959bd7b0ac028e 100644 --- a/web/core/modules/node/src/NodeViewsData.php +++ b/web/core/modules/node/src/NodeViewsData.php @@ -216,6 +216,10 @@ public function getViewsData() { $data['node_field_revision']['nid']['relationship']['base field'] = 'nid'; $data['node_field_revision']['nid']['relationship']['title'] = $this->t('Content'); $data['node_field_revision']['nid']['relationship']['label'] = $this->t('Get the actual content from a content revision.'); + $data['node_field_revision']['nid']['relationship']['extra'][] = [ + 'field' => 'langcode', + 'left_field' => 'langcode', + ]; $data['node_field_revision']['vid'] = [ 'argument' => [ @@ -228,6 +232,12 @@ public function getViewsData() { 'base field' => 'vid', 'title' => $this->t('Content'), 'label' => $this->t('Get the actual content from a content revision.'), + 'extra' => [ + [ + 'field' => 'langcode', + 'left_field' => 'langcode', + ], + ], ], ] + $data['node_field_revision']['vid']; diff --git a/web/core/modules/node/src/Plugin/migrate/source/d7/Node.php b/web/core/modules/node/src/Plugin/migrate/source/d7/Node.php index 75cba448423ce24a6ac7d1470ccbc896d8ddc6d1..931a2b94311c02f892cac258c7e9a8504b9d5966 100644 --- a/web/core/modules/node/src/Plugin/migrate/source/d7/Node.php +++ b/web/core/modules/node/src/Plugin/migrate/source/d7/Node.php @@ -113,7 +113,8 @@ public function prepareRow(Row $row) { // The translations will be migrated by the d7_node_entity_translation // migration. $entity_translatable = $this->isEntityTranslatable('node') && (int) $this->variableGet('language_content_type_' . $type, 0) === 4; - $language = $entity_translatable ? $this->getEntityTranslationSourceLanguage('node', $nid) : $row->getSourceProperty('language'); + $source_language = $this->getEntityTranslationSourceLanguage('node', $nid); + $language = $entity_translatable && $source_language ? $source_language : $row->getSourceProperty('language'); // Get Field API field values. foreach ($this->getFields('node', $type) as $field_name => $field) { diff --git a/web/core/modules/node/src/Plugin/migrate/source/d7/NodeEntityTranslation.php b/web/core/modules/node/src/Plugin/migrate/source/d7/NodeEntityTranslation.php index f438b0054f0ab83f3ee9c33eb542cdb73f155a99..ce698161634cd5af8a8adc9407309c298d608c2b 100644 --- a/web/core/modules/node/src/Plugin/migrate/source/d7/NodeEntityTranslation.php +++ b/web/core/modules/node/src/Plugin/migrate/source/d7/NodeEntityTranslation.php @@ -20,16 +20,7 @@ class NodeEntityTranslation extends FieldableEntity { */ public function query() { $query = $this->select('entity_translation', 'et') - ->fields('et', [ - 'entity_id', - 'revision_id', - 'language', - 'source', - 'uid', - 'status', - 'created', - 'changed', - ]) + ->fields('et') ->fields('n', [ 'title', 'type', @@ -88,14 +79,16 @@ public function prepareRow(Row $row) { */ public function fields() { return [ - 'entity_id' => $this->t('Entity ID'), - 'revision_id' => $this->t('Revision ID'), - 'language' => $this->t('Node translation language'), - 'source' => $this->t('Node translation source language'), - 'uid' => $this->t('Node translation authored by (uid)'), - 'status' => $this->t('Published'), - 'created' => $this->t('Created timestamp'), - 'changed' => $this->t('Modified timestamp'), + 'entity_type' => $this->t('The entity type this translation relates to'), + 'entity_id' => $this->t('The entity ID this translation relates to'), + 'revision_id' => $this->t('The entity revision ID this translation relates to'), + 'language' => $this->t('The target language for this translation.'), + 'source' => $this->t('The source language from which this translation was created.'), + 'uid' => $this->t('The author of this translation.'), + 'status' => $this->t('Boolean indicating whether the translation is published (visible to non-administrators).'), + 'translate' => $this->t('A boolean indicating whether this translation needs to be updated.'), + 'created' => $this->t('The Unix timestamp when the translation was created.'), + 'changed' => $this->t('The Unix timestamp when the translation was most recently saved.'), 'title' => $this->t('Node title'), 'type' => $this->t('Node type'), 'promote' => $this->t('Promoted to front page'), diff --git a/web/core/modules/node/src/Plugin/migrate/source/d7/NodeType.php b/web/core/modules/node/src/Plugin/migrate/source/d7/NodeType.php index 44f0b5e06031f8ec9cdc80b387117c6ed47c70e9..e64b98908898650c84548acda5bd148114965d1b 100644 --- a/web/core/modules/node/src/Plugin/migrate/source/d7/NodeType.php +++ b/web/core/modules/node/src/Plugin/migrate/source/d7/NodeType.php @@ -40,7 +40,7 @@ public function query() { * {@inheritdoc} */ public function fields() { - return [ + $fields = [ 'type' => $this->t('Machine name of the node type.'), 'name' => $this->t('Human name of the node type.'), 'description' => $this->t('Description of the node type.'), diff --git a/web/core/modules/node/tests/modules/node_access_test/node_access_test.module b/web/core/modules/node/tests/modules/node_access_test/node_access_test.module index 5a9756b51adc8f80b58fab29aadb3a6b71aff342..9fca50c4e7786425a4693df3828c36b76c84d95c 100644 --- a/web/core/modules/node/tests/modules/node_access_test/node_access_test.module +++ b/web/core/modules/node/tests/modules/node_access_test/node_access_test.module @@ -52,7 +52,7 @@ function node_access_test_node_grants($account, $op) { $grants = []; $grants['node_access_test_author'] = [$account->id()]; - if ($op == 'view' && $account->hasPermission('node test view', $account)) { + if ($op == 'view' && $account->hasPermission('node test view')) { $grants['node_access_test'] = [8888, 8889]; } diff --git a/web/core/modules/node/tests/modules/node_test_views/test_views/views.view.test_node_revision_nid.yml b/web/core/modules/node/tests/modules/node_test_views/test_views/views.view.test_node_revision_nid.yml index 179e1401c1da775ccdeee2acad6b7054f181e02f..8c5d4cb4b2c769f3ebb31202106c11d4a4b097e0 100644 --- a/web/core/modules/node/tests/modules/node_test_views/test_views/views.view.test_node_revision_nid.yml +++ b/web/core/modules/node/tests/modules/node_test_views/test_views/views.view.test_node_revision_nid.yml @@ -44,6 +44,13 @@ display: plugin_id: field entity_type: node entity_field: nid + langcode: + id: langcode + table: node_field_revision + field: langcode + plugin_id: field + entity_type: node + entity_field: langcode arguments: nid: id: nid @@ -61,6 +68,21 @@ display: plugin_id: field entity_type: node entity_field: vid + langcode: + id: langcode + table: node_field_revision + field: langcode + relationship: none + group_type: group + admin_label: '' + order: DESC + exposed: false + expose: + label: '' + entity_type: node + entity_field: langcode + plugin_id: standard + display_extenders: { } display_plugin: default display_title: Master id: default diff --git a/web/core/modules/node/tests/modules/node_test_views/test_views/views.view.test_node_revision_vid.yml b/web/core/modules/node/tests/modules/node_test_views/test_views/views.view.test_node_revision_vid.yml index a2783a56d742997e03f87f0c66fc641141b965d0..3c9aac56f286ebf342779b62bd3c53e09d8c75f5 100644 --- a/web/core/modules/node/tests/modules/node_test_views/test_views/views.view.test_node_revision_vid.yml +++ b/web/core/modules/node/tests/modules/node_test_views/test_views/views.view.test_node_revision_vid.yml @@ -44,6 +44,13 @@ display: plugin_id: field entity_type: node entity_field: nid + langcode: + id: langcode + table: node_field_revision + field: langcode + entity_type: node + entity_field: langcode + plugin_id: field arguments: nid: id: nid @@ -52,6 +59,22 @@ display: plugin_id: node_nid entity_type: node entity_field: nid + display_extenders: { } + sorts: + langcode: + id: langcode + table: node_field_revision + field: langcode + relationship: none + group_type: group + admin_label: '' + order: ASC + exposed: false + expose: + label: '' + entity_type: node + entity_field: langcode + plugin_id: standard display_plugin: default display_title: Master id: default diff --git a/web/core/modules/node/tests/src/Functional/NodeEditFormTest.php b/web/core/modules/node/tests/src/Functional/NodeEditFormTest.php index c15ca70bbe3beeb27754b07997325a6dbc9ee52d..17f0734f697c8102998ca1bfaeb197d7b93eacb1 100644 --- a/web/core/modules/node/tests/src/Functional/NodeEditFormTest.php +++ b/web/core/modules/node/tests/src/Functional/NodeEditFormTest.php @@ -165,7 +165,7 @@ public function testNodeEditAuthoredBy() { $this->drupalGet('node/' . $node->id() . '/edit'); $this->assertNoFieldByName('uid[0][target_id]'); - // Now test with the Autcomplete (Tags) field widget. + // Now test with the Autocomplete (Tags) field widget. /** @var \Drupal\Core\Entity\Display\EntityFormDisplayInterface $form_display */ $form_display = \Drupal::entityManager()->getStorage('entity_form_display')->load('node.page.default'); $widget = $form_display->getComponent('uid'); diff --git a/web/core/modules/node/tests/src/Functional/NodeRevisionPermissionsTest.php b/web/core/modules/node/tests/src/Functional/NodeRevisionPermissionsTest.php index ed632a7e92b7f12dc22a83682b079926068aa239..d0aa88efbb2f40735b9d2b51d7f89340af6245b2 100644 --- a/web/core/modules/node/tests/src/Functional/NodeRevisionPermissionsTest.php +++ b/web/core/modules/node/tests/src/Functional/NodeRevisionPermissionsTest.php @@ -153,7 +153,7 @@ public function testNodeRevisionAccessPerType() { foreach ($permutations as $case) { // Skip this test if there are no revisions for the node. if (!($revision->isDefaultRevision() && (db_query('SELECT COUNT(vid) FROM {node_field_revision} WHERE nid = :nid', [':nid' => $revision->id()])->fetchField() == 1 || $case['op'] == 'update' || $case['op'] == 'delete'))) { - if (!empty($case['account']->is_admin) || $case['account']->hasPermission($this->typeMap[$case['op']], $case['account'])) { + if (!empty($case['account']->is_admin) || $case['account']->hasPermission($this->typeMap[$case['op']])) { $this->assertTrue($node_revision_access->checkAccess($revision, $case['account'], $case['op']), "{$this->typeMap[$case['op']]} granted."); } else { diff --git a/web/core/modules/node/tests/src/Functional/NodeTranslationUITest.php b/web/core/modules/node/tests/src/Functional/NodeTranslationUITest.php index 513c074932e3c26ee1dfc12ae7bf7a425fb0b49f..54d9c7303846acd4dbbb0b665f71623c7e80b52d 100644 --- a/web/core/modules/node/tests/src/Functional/NodeTranslationUITest.php +++ b/web/core/modules/node/tests/src/Functional/NodeTranslationUITest.php @@ -27,6 +27,7 @@ class NodeTranslationUITest extends ContentTranslationUITestBase { 'url.path.parent', 'url.query_args:_wrapper_format', 'user.roles', + 'url.path.is_front', // These two cache contexts are added by BigPipe. 'cookies:big_pipe_nojs', 'session.exists', diff --git a/web/core/modules/node/tests/src/Functional/PagePreviewTest.php b/web/core/modules/node/tests/src/Functional/PagePreviewTest.php index 70305349d46d1859fdaf651c3ec234007e1c3f35..bbdf9b1e1c79cc47e5a67f8b1e43e0851ef322e4 100644 --- a/web/core/modules/node/tests/src/Functional/PagePreviewTest.php +++ b/web/core/modules/node/tests/src/Functional/PagePreviewTest.php @@ -6,12 +6,12 @@ use Drupal\Core\Field\FieldStorageDefinitionInterface; use Drupal\Core\Language\LanguageInterface; use Drupal\Core\Url; -use Drupal\field\Tests\EntityReference\EntityReferenceTestTrait; use Drupal\field\Entity\FieldConfig; use Drupal\field\Entity\FieldStorageConfig; use Drupal\node\Entity\NodeType; use Drupal\taxonomy\Entity\Term; use Drupal\taxonomy\Entity\Vocabulary; +use Drupal\Tests\field\Traits\EntityReferenceTestTrait; use Drupal\Tests\TestFileCreationTrait; /** diff --git a/web/core/modules/node/tests/src/Kernel/Migrate/d7/MigrateNodeTest.php b/web/core/modules/node/tests/src/Kernel/Migrate/d7/MigrateNodeTest.php index da930ec6844edf014c931d2bbf9f6a4adcbdf906..4bbd6ef49c393f5ee724e28a007dfb6c053a62b7 100644 --- a/web/core/modules/node/tests/src/Kernel/Migrate/d7/MigrateNodeTest.php +++ b/web/core/modules/node/tests/src/Kernel/Migrate/d7/MigrateNodeTest.php @@ -70,6 +70,7 @@ protected function setUp() { 'd7_field_instance', 'd7_node', 'd7_node_translation', + 'd7_entity_translation_settings', 'd7_node_entity_translation', ]); } @@ -181,14 +182,6 @@ public function testNode() { $this->assertEquals(CommentItemInterface::OPEN, $node->comment_node_test_content_type->status); $this->assertEquals('3.1416', $node->field_float_list[0]->value); - // Test that fields translated with Entity Translation are migrated. - $node_fr = $node->getTranslation('fr'); - $this->assertEquals('A French Node', $node_fr->getTitle()); - $this->assertEquals('6', $node_fr->field_integer->value); - $node_is = $node->getTranslation('is'); - $this->assertEquals('An Icelandic Node', $node_is->getTitle()); - $this->assertEquals('7', $node_is->field_integer->value); - $node = Node::load(2); $this->assertEquals('en', $node->langcode->value); $this->assertEquals("...is that it's the absolute best show ever. Trust me, I would know.", $node->body->value); @@ -228,4 +221,42 @@ public function testNode() { $this->assertEquals(CommentItemInterface::OPEN, $node->comment_forum->status); } + /** + * Test node entity translations migration from Drupal 7 to 8. + */ + public function testNodeEntityTranslations() { + $manager = $this->container->get('content_translation.manager'); + + // Get the node and its translations. + $node = Node::load(1); + $node_fr = $node->getTranslation('fr'); + $node_is = $node->getTranslation('is'); + + // Test that fields translated with Entity Translation are migrated. + $this->assertSame('An English Node', $node->getTitle()); + $this->assertSame('A French Node', $node_fr->getTitle()); + $this->assertSame('An Icelandic Node', $node_is->getTitle()); + $this->assertSame('5', $node->field_integer->value); + $this->assertSame('6', $node_fr->field_integer->value); + $this->assertSame('7', $node_is->field_integer->value); + + // Test that the French translation metadata is correctly migrated. + $metadata_fr = $manager->getTranslationMetadata($node_fr); + $this->assertSame('en', $metadata_fr->getSource()); + $this->assertTrue($metadata_fr->isOutdated()); + $this->assertSame('2', $node_fr->getOwnerId()); + $this->assertSame('1529615802', $node_fr->getCreatedTime()); + $this->assertSame('1529615802', $node_fr->getChangedTime()); + $this->assertTrue($node_fr->isPublished()); + + // Test that the Icelandic translation metadata is correctly migrated. + $metadata_is = $manager->getTranslationMetadata($node_is); + $this->assertSame('en', $metadata_is->getSource()); + $this->assertFalse($metadata_is->isOutdated()); + $this->assertSame('1', $node_is->getOwnerId()); + $this->assertSame('1529615813', $node_is->getCreatedTime()); + $this->assertSame('1529615813', $node_is->getChangedTime()); + $this->assertFalse($node_is->isPublished()); + } + } diff --git a/web/core/modules/node/tests/src/Kernel/Plugin/migrate/source/d7/NodeEntityTranslationTest.php b/web/core/modules/node/tests/src/Kernel/Plugin/migrate/source/d7/NodeEntityTranslationTest.php index ef33a9624e011d2e82c8758d37d51e1616d25d71..79fedae640c68ed6ebe215dbed3a0afb682e83d7 100644 --- a/web/core/modules/node/tests/src/Kernel/Plugin/migrate/source/d7/NodeEntityTranslationTest.php +++ b/web/core/modules/node/tests/src/Kernel/Plugin/migrate/source/d7/NodeEntityTranslationTest.php @@ -44,9 +44,9 @@ public function providerSource() { 'revision_id' => 2, 'language' => 'fr', 'source' => 'en', - 'uid' => 1, + 'uid' => 2, 'status' => 1, - 'translate' => 0, + 'translate' => 1, 'created' => 1531343508, 'changed' => 1531343508, ], @@ -57,7 +57,7 @@ public function providerSource() { 'language' => 'es', 'source' => 'en', 'uid' => 1, - 'status' => 1, + 'status' => 0, 'translate' => 0, 'created' => 1531343528, 'changed' => 1531343528, @@ -280,12 +280,14 @@ public function providerSource() { // The expected results. $tests[0]['expected_data'] = [ [ + 'entity_type' => 'node', 'entity_id' => 2, 'revision_id' => 2, 'language' => 'fr', 'source' => 'en', - 'uid' => 1, + 'uid' => 2, 'status' => 1, + 'translate' => 1, 'created' => 1531343508, 'changed' => 1531343508, 'type' => 'page', @@ -304,12 +306,14 @@ public function providerSource() { ], ], [ + 'entity_type' => 'node', 'entity_id' => 2, 'revision_id' => 2, 'language' => 'es', 'source' => 'en', 'uid' => 1, - 'status' => 1, + 'status' => 0, + 'translate' => 0, 'created' => 1531343528, 'changed' => 1531343528, 'type' => 'page', diff --git a/web/core/modules/node/tests/src/Kernel/Plugin/migrate/source/d7/NodeTest.php b/web/core/modules/node/tests/src/Kernel/Plugin/migrate/source/d7/NodeTest.php index 010b90dc03762258a6bdb94d6002a74cbacb4f83..3b75837a686230f0c4d73e9e35e219534c689624 100644 --- a/web/core/modules/node/tests/src/Kernel/Plugin/migrate/source/d7/NodeTest.php +++ b/web/core/modules/node/tests/src/Kernel/Plugin/migrate/source/d7/NodeTest.php @@ -422,6 +422,169 @@ public function providerSource() { ], ]; + // The source data with a correct 'entity_translation' table. + $tests[1]['source_data']['entity_translation'] = [ + [ + 'entity_type' => 'node', + 'entity_id' => 1, + 'revision_id' => 1, + 'language' => 'en', + 'source' => '', + 'uid' => 1, + 'status' => 1, + 'translate' => 0, + 'created' => 1279051598, + 'changed' => 1279051598, + ], + [ + 'entity_type' => 'node', + 'entity_id' => 1, + 'revision_id' => 1, + 'language' => 'fr', + 'source' => 'en', + 'uid' => 1, + 'status' => 1, + 'translate' => 0, + 'created' => 1279051598, + 'changed' => 1279051598, + ], + ]; + $tests[1]['source_data']['field_config'] = [ + [ + 'id' => '1', + 'translatable' => '1', + ], + ]; + $tests[1]['source_data']['field_config_instance'] = [ + [ + 'id' => '1', + 'field_id' => '1', + 'field_name' => 'body', + 'entity_type' => 'node', + 'bundle' => 'page', + 'data' => 'a:0:{}', + 'deleted' => '0', + ], + ]; + $tests[1]['source_data']['field_revision_body'] = [ + [ + 'entity_type' => 'node', + 'bundle' => 'page', + 'deleted' => '0', + 'entity_id' => '1', + 'revision_id' => '1', + 'language' => 'en', + 'delta' => '0', + 'body_value' => 'English body', + 'body_summary' => '', + 'body_format' => 'filtered_html', + ], + [ + 'entity_type' => 'node', + 'bundle' => 'page', + 'deleted' => '0', + 'entity_id' => '1', + 'revision_id' => '1', + 'language' => 'fr', + 'delta' => '0', + 'body_value' => 'French body', + 'body_summary' => '', + 'body_format' => 'filtered_html', + ], + ]; + $tests[1]['source_data']['node'] = [ + [ + 'nid' => 1, + 'vid' => 1, + 'type' => 'page', + 'language' => 'en', + 'title' => 'Node Title', + 'uid' => 1, + 'status' => 1, + 'created' => 1279051598, + 'changed' => 1279051598, + 'comment' => 2, + 'promote' => 1, + 'sticky' => 0, + 'tnid' => 0, + 'translate' => 0, + ], + ]; + $tests[1]['source_data']['node_revision'] = [ + [ + 'nid' => 1, + 'vid' => 1, + 'uid' => 1, + 'title' => 'Node Title', + 'log' => '', + 'timestamp' => 1279051598, + 'status' => 1, + 'comment' => 2, + 'promote' => 1, + 'sticky' => 0, + ], + ]; + $tests[1]['source_data']['variable'] = [ + [ + 'name' => 'entity_translation_entity_types', + 'value' => 'a:4:{s:7:"comment";i:0;s:4:"node";s:4:"node";s:13:"taxonomy_term";i:0;s:4:"user";i:0;}', + ], + [ + 'name' => 'language_content_type_page', + 'value' => 's:1:"4";', + ], + ]; + + // The expected results with a correct 'entity_translation' table. + // entity_translation table. + $tests[1]['expected_data'] = [ + [ + 'nid' => 1, + 'vid' => 1, + 'type' => 'page', + 'language' => 'en', + 'title' => 'Node Title', + 'node_uid' => 1, + 'revision_uid' => 1, + 'status' => 1, + 'created' => 1279051598, + 'changed' => 1279051598, + 'comment' => 2, + 'promote' => 1, + 'sticky' => 0, + 'tnid' => 1, + 'translate' => 0, + 'log' => '', + 'timestamp' => 1279051598, + 'body' => [ + [ + 'value' => 'English body', + 'summary' => '', + 'format' => 'filtered_html', + ], + ], + ], + ]; + + // Repeat the previous test with an incorrect 'entity_translation' table + // where the row with the empty 'source' property is missing. + $tests[2]['source_data'] = $tests[1]['source_data']; + $tests[2]['source_data']['entity_translation'] = [ + [ + 'entity_type' => 'node', + 'entity_id' => 1, + 'revision_id' => 1, + 'language' => 'fr', + 'source' => 'en', + 'uid' => 1, + 'status' => 1, + 'translate' => 0, + 'created' => 1279051598, + 'changed' => 1279051598, + ], + ]; + $tests[2]['expected_data'] = $tests[1]['expected_data']; + return $tests; } diff --git a/web/core/modules/node/tests/src/Kernel/Views/RevisionRelationshipsTest.php b/web/core/modules/node/tests/src/Kernel/Views/RevisionRelationshipsTest.php index e47bdd038b328123265d29007e4625ef59646b31..b21610c5fde7d9438ffe21ecfd95bf58550d891c 100644 --- a/web/core/modules/node/tests/src/Kernel/Views/RevisionRelationshipsTest.php +++ b/web/core/modules/node/tests/src/Kernel/Views/RevisionRelationshipsTest.php @@ -2,6 +2,7 @@ namespace Drupal\Tests\node\Kernel\Views; +use Drupal\language\Entity\ConfigurableLanguage; use Drupal\node\Entity\Node; use Drupal\node\Entity\NodeType; use Drupal\Tests\views\Kernel\ViewsKernelTestBase; @@ -20,7 +21,12 @@ class RevisionRelationshipsTest extends ViewsKernelTestBase { * * @var array */ - public static $modules = ['node' , 'node_test_views']; + public static $modules = [ + 'node', + 'node_test_views', + 'language', + 'content_translation', + ]; /** * {@inheritdoc} @@ -33,6 +39,8 @@ protected function setUp($import_test_views = TRUE) { $this->installEntitySchema('user'); $this->installEntitySchema('node'); + ConfigurableLanguage::createFromLangcode('fr')->save(); + ViewTestData::createTestViews(get_class($this), ['node_test_views']); } @@ -51,16 +59,22 @@ public function testNodeRevisionRelationship() { $type->save(); $node = Node::create(['type' => 'page', 'title' => 'test', 'uid' => 1]); $node->save(); + + // Add a translation. + $translation = $node->addTranslation('fr', $node->toArray()); + $translation->save(); // Create revision of the node. $node->setNewRevision(TRUE); $node->save(); + $column_map = [ 'vid' => 'vid', 'node_field_data_node_field_revision_nid' => 'node_node_revision_nid', 'nid_1' => 'nid_1', + 'node_field_revision_langcode' => 'node_field_revision_langcode', ]; - // Here should be two rows. + // Here should be two rows for each translation. $view_nid = Views::getView('test_node_revision_nid'); $this->executeView($view_nid, [$node->id()]); $resultset_nid = [ @@ -68,17 +82,32 @@ public function testNodeRevisionRelationship() { 'vid' => '1', 'node_node_revision_nid' => '1', 'nid_1' => '1', + 'node_field_revision_langcode' => 'fr', + ], + [ + 'vid' => '1', + 'node_node_revision_nid' => '1', + 'nid_1' => '1', + 'node_field_revision_langcode' => 'en', ], [ 'vid' => '2', 'node_revision_nid' => '1', 'node_node_revision_nid' => '1', 'nid_1' => '1', + 'node_field_revision_langcode' => 'fr', + ], + [ + 'vid' => '2', + 'node_revision_nid' => '1', + 'node_node_revision_nid' => '1', + 'nid_1' => '1', + 'node_field_revision_langcode' => 'en', ], ]; $this->assertIdenticalResultset($view_nid, $resultset_nid, $column_map); - // There should be only one row with active revision 2. + // There should be one row with active revision 2 for each translation. $view_vid = Views::getView('test_node_revision_vid'); $this->executeView($view_vid, [$node->id()]); $resultset_vid = [ @@ -86,6 +115,13 @@ public function testNodeRevisionRelationship() { 'vid' => '2', 'node_node_revision_nid' => '1', 'nid_1' => '1', + 'node_field_revision_langcode' => 'en', + ], + [ + 'vid' => '2', + 'node_node_revision_nid' => '1', + 'nid_1' => '1', + 'node_field_revision_langcode' => 'fr', ], ]; $this->assertIdenticalResultset($view_vid, $resultset_vid, $column_map); diff --git a/web/core/modules/path/src/Plugin/Field/FieldType/PathFieldItemList.php b/web/core/modules/path/src/Plugin/Field/FieldType/PathFieldItemList.php index 1a5fbe0858e0e51774cf9315646e2842b74dcc1d..1985499dee5278a4db62b9921fb6a31b025bfb4c 100644 --- a/web/core/modules/path/src/Plugin/Field/FieldType/PathFieldItemList.php +++ b/web/core/modules/path/src/Plugin/Field/FieldType/PathFieldItemList.php @@ -4,6 +4,7 @@ use Drupal\Core\Access\AccessResult; use Drupal\Core\Field\FieldItemList; +use Drupal\Core\Language\LanguageInterface; use Drupal\Core\Session\AccountInterface; use Drupal\Core\TypedData\ComputedItemListTrait; @@ -26,12 +27,18 @@ protected function computeValue() { $entity = $this->getEntity(); if (!$entity->isNew()) { - // @todo Support loading languge neutral aliases in - // https://www.drupal.org/node/2511968. - $alias = \Drupal::service('path.alias_storage')->load([ + $conditions = [ 'source' => '/' . $entity->toUrl()->getInternalPath(), 'langcode' => $this->getLangcode(), - ]); + ]; + $alias = \Drupal::service('path.alias_storage')->load($conditions); + if ($alias === FALSE) { + // Fall back to non-specific language. + if ($this->getLangcode() !== LanguageInterface::LANGCODE_NOT_SPECIFIED) { + $conditions['langcode'] = LanguageInterface::LANGCODE_NOT_SPECIFIED; + $alias = \Drupal::service('path.alias_storage')->load($conditions); + } + } if ($alias) { $value = $alias; diff --git a/web/core/modules/path/src/Plugin/Field/FieldType/PathItem.php b/web/core/modules/path/src/Plugin/Field/FieldType/PathItem.php index cd62bea662e6121be96bddaff95c7ae21a5c7c9b..fc263ce60afcdd573b6df721448c5507a619b776 100644 --- a/web/core/modules/path/src/Plugin/Field/FieldType/PathItem.php +++ b/web/core/modules/path/src/Plugin/Field/FieldType/PathItem.php @@ -63,10 +63,15 @@ public function preSave() { * {@inheritdoc} */ public function postSave($update) { + // If specified, rely on the langcode property for the language, so that the + // existing language of an alias can be kept. That could for example be + // unspecified even if the field/entity has a specific langcode. + $alias_langcode = ($this->langcode && $this->pid) ? $this->langcode : $this->getLangcode(); + if (!$update) { if ($this->alias) { $entity = $this->getEntity(); - if ($path = \Drupal::service('path.alias_storage')->save('/' . $entity->urlInfo()->getInternalPath(), $this->alias, $this->getLangcode())) { + if ($path = \Drupal::service('path.alias_storage')->save('/' . $entity->urlInfo()->getInternalPath(), $this->alias, $alias_langcode)) { $this->pid = $path['pid']; } } @@ -79,7 +84,7 @@ public function postSave($update) { // Only save a non-empty alias. elseif ($this->alias) { $entity = $this->getEntity(); - \Drupal::service('path.alias_storage')->save('/' . $entity->urlInfo()->getInternalPath(), $this->alias, $this->getLangcode(), $this->pid); + \Drupal::service('path.alias_storage')->save('/' . $entity->urlInfo()->getInternalPath(), $this->alias, $alias_langcode, $this->pid); } } } diff --git a/web/core/modules/path/src/Plugin/Validation/Constraint/PathAliasConstraintValidator.php b/web/core/modules/path/src/Plugin/Validation/Constraint/PathAliasConstraintValidator.php index e6771f76d2fab7d0e2875f407811a4af52f27aa3..be6350f75b24866cb8fcd01b44ec80a6772c77dd 100644 --- a/web/core/modules/path/src/Plugin/Validation/Constraint/PathAliasConstraintValidator.php +++ b/web/core/modules/path/src/Plugin/Validation/Constraint/PathAliasConstraintValidator.php @@ -48,8 +48,14 @@ public function validate($value, Constraint $constraint) { if ($entity && !$entity->isNew() && !$entity->isDefaultRevision()) { /** @var \Drupal\Core\Entity\ContentEntityInterface $original */ $original = $this->entityTypeManager->getStorage($entity->getEntityTypeId())->loadUnchanged($entity->id()); - if ($value->alias != $original->path->alias) { - $this->context->addViolation($constraint->message); + $entity_langcode = $entity->language()->getId(); + + // Only add the violation if the current translation does not have the + // same path alias. + if ($original->hasTranslation($entity_langcode)) { + if ($value->alias != $original->getTranslation($entity_langcode)->path->alias) { + $this->context->addViolation($constraint->message); + } } } } diff --git a/web/core/modules/path/tests/src/Functional/PathContentModerationTest.php b/web/core/modules/path/tests/src/Functional/PathContentModerationTest.php index 953f1116bafdf208afc85a9c9eef46d5b4c6b703..b69a5dbe5b5dd95a32efb9e58356c08274ba8214 100644 --- a/web/core/modules/path/tests/src/Functional/PathContentModerationTest.php +++ b/web/core/modules/path/tests/src/Functional/PathContentModerationTest.php @@ -2,7 +2,7 @@ namespace Drupal\Tests\path\Functional; -use Drupal\node\Entity\NodeType; +use Drupal\language\Entity\ConfigurableLanguage; use Drupal\Tests\BrowserTestBase; use Drupal\Tests\content_moderation\Traits\ContentModerationTestTrait; @@ -21,17 +21,26 @@ class PathContentModerationTest extends BrowserTestBase { * * @var array */ - public static $modules = ['node', 'path', 'content_moderation']; + public static $modules = [ + 'node', + 'path', + 'content_moderation', + 'content_translation', + ]; /** * {@inheritdoc} */ protected function setUp() { parent::setUp(); + ConfigurableLanguage::createFromLangcode('fr')->save(); + $this->rebuildContainer(); // Created a content type. - $node_type = NodeType::create(['name' => 'moderated', 'type' => 'moderated']); - $node_type->save(); + $this->drupalCreateContentType([ + 'name' => 'moderated', + 'type' => 'moderated', + ]); // Set the content type as moderated. $workflow = $this->createEditorialWorkflow(); @@ -39,6 +48,21 @@ protected function setUp() { $workflow->save(); $this->drupalLogin($this->rootUser); + + // Enable URL language detection and selection. + $edit = ['language_interface[enabled][language-url]' => 1]; + $this->drupalPostForm('admin/config/regional/language/detection', $edit, 'Save settings'); + + // Enable translation for moderated node. + $edit = [ + 'entity_types[node]' => 1, + 'settings[node][moderated][translatable]' => 1, + 'settings[node][moderated][fields][path]' => 1, + 'settings[node][moderated][fields][body]' => 1, + 'settings[node][moderated][settings][language][language_alterable]' => 1, + ]; + $this->drupalPostForm('admin/config/regional/content-language', $edit, 'Save configuration'); + \Drupal::entityTypeManager()->clearCachedDefinitions(); } /** @@ -106,4 +130,104 @@ public function testNodePathAlias() { $this->assertSession()->pageTextNotContains('You can only change the URL alias for the published version of this content.'); } + /** + * Tests that translated and moderated node can get new draft revision. + */ + public function testTranslatedModeratedNodeAlias() { + // Create one node with a random alias. + $default_node = $this->drupalCreateNode([ + 'type' => 'moderated', + 'langcode' => 'en', + 'moderation_state' => 'published', + 'path' => '/' . $this->randomMachineName(), + ]); + + // Add published translation with another alias. + $this->drupalGet('node/' . $default_node->id()); + $this->drupalGet('node/' . $default_node->id() . '/translations'); + $this->clickLink('Add'); + $edit_translation = [ + 'body[0][value]' => $this->randomMachineName(), + 'moderation_state[0][state]' => 'published', + 'path[0][alias]' => '/' . $this->randomMachineName(), + ]; + $this->drupalPostForm(NULL, $edit_translation, 'Save (this translation)'); + // Confirm that the alias works. + $this->drupalGet('fr' . $edit_translation['path[0][alias]']); + $this->assertSession()->pageTextContains($edit_translation['body[0][value]']); + + $default_path = $default_node->path->alias; + $translation_path = 'fr' . $edit_translation['path[0][alias]']; + + $this->assertPathsAreAccessible([$default_path, $translation_path]); + + // Try to create new draft revision for translation with a new path alias. + $edit_new_translation_draft_with_alias = [ + 'moderation_state[0][state]' => 'draft', + 'path[0][alias]' => '/' . $this->randomMachineName(), + ]; + $this->drupalPostForm('fr/node/' . $default_node->id() . '/edit', $edit_new_translation_draft_with_alias, 'Save (this translation)'); + // Confirm the expected error. + $this->assertSession()->pageTextContains('You can only change the URL alias for the published version of this content.'); + + // Create new draft revision for translation without changing path alias. + $edit_new_translation_draft = [ + 'body[0][value]' => $this->randomMachineName(), + 'moderation_state[0][state]' => 'draft', + ]; + $this->drupalPostForm('fr/node/' . $default_node->id() . '/edit', $edit_new_translation_draft, t('Save (this translation)')); + // Confirm that the new draft revision was created. + $this->assertSession()->pageTextNotContains('You can only change the URL alias for the published version of this content.'); + $this->assertSession()->pageTextContains($edit_new_translation_draft['body[0][value]']); + $this->assertPathsAreAccessible([$default_path, $translation_path]); + + // Try to create a new draft revision for translation with path alias from + // the original language's default revision. + $edit_new_translation_draft_with_defaults_alias = [ + 'moderation_state[0][state]' => 'draft', + 'path[0][alias]' => $default_node->path->alias, + ]; + $this->drupalPostForm('fr/node/' . $default_node->id() . '/edit', $edit_new_translation_draft_with_defaults_alias, 'Save (this translation)'); + // Verify the expected error. + $this->assertSession()->pageTextContains('You can only change the URL alias for the published version of this content.'); + + // Try to create new draft revision for translation with deleted (empty) + // path alias. + $edit_new_translation_draft_empty_alias = [ + 'body[0][value]' => $this->randomMachineName(), + 'moderation_state[0][state]' => 'draft', + 'path[0][alias]' => '', + ]; + $this->drupalPostForm('fr/node/' . $default_node->id() . '/edit', $edit_new_translation_draft_empty_alias, 'Save (this translation)'); + // Confirm the expected error. + $this->assertSession()->pageTextContains('You can only change the URL alias for the published version of this content.'); + + // Create new default (published) revision for translation with new path + // alias. + $edit_new_translation = [ + 'body[0][value]' => $this->randomMachineName(), + 'moderation_state[0][state]' => 'published', + 'path[0][alias]' => '/' . $this->randomMachineName(), + ]; + $this->drupalPostForm('fr/node/' . $default_node->id() . '/edit', $edit_new_translation, 'Save (this translation)'); + // Confirm that the new published revision was created. + $this->assertSession()->pageTextNotContains('You can only change the URL alias for the published version of this content.'); + $this->assertSession()->pageTextContains($edit_new_translation['body[0][value]']); + $this->assertSession()->addressEquals('fr' . $edit_new_translation['path[0][alias]']); + $this->assertPathsAreAccessible([$default_path]); + } + + /** + * Helper callback to verify paths are responding with status 200. + * + * @param string[] $paths + * An array of paths to check for. + */ + public function assertPathsAreAccessible(array $paths) { + foreach ($paths as $path) { + $this->drupalGet($path); + $this->assertSession()->statusCodeEquals(200); + } + } + } diff --git a/web/core/modules/path/tests/src/Functional/PathLanguageUiTest.php b/web/core/modules/path/tests/src/Functional/PathLanguageUiTest.php index c2e3276246fa1270448a7c88d10fd578824d7c40..c76284515b65e570c89f2255c1e8468b00d1f185 100644 --- a/web/core/modules/path/tests/src/Functional/PathLanguageUiTest.php +++ b/web/core/modules/path/tests/src/Functional/PathLanguageUiTest.php @@ -2,6 +2,8 @@ namespace Drupal\Tests\path\Functional; +use Drupal\Core\Language\LanguageInterface; + /** * Confirm that the Path module user interface works with languages. * @@ -78,4 +80,36 @@ public function testNonDefaultUrl() { $this->assertText(t('Filter aliases'), 'Foreign URL alias works'); } + /** + * Test that language unspecific aliases are shown and saved in the node form. + */ + public function testNotSpecifiedNode() { + // Create test node. + $node = $this->drupalCreateNode(); + + // Create a language-unspecific alias in the admin UI, ensure that is + // displayed and the langcode is not changed when saving. + $edit = [ + 'source' => '/node/' . $node->id(), + 'alias' => '/' . $this->getRandomGenerator()->word(8), + 'langcode' => LanguageInterface::LANGCODE_NOT_SPECIFIED, + ]; + $this->drupalPostForm('admin/config/search/path/add', $edit, t('Save')); + + $this->drupalGet($node->toUrl('edit-form')); + $this->assertSession()->fieldValueEquals('path[0][alias]', $edit['alias']); + $this->drupalPostForm(NULL, [], t('Save')); + + $this->drupalGet('admin/config/search/path'); + $this->assertSession()->pageTextContains('None'); + $this->assertSession()->pageTextNotContains('English'); + + // Create another node, with no alias, to ensure non-language specific + // aliases are loaded correctly. + $node = $this->drupalCreateNode(); + $this->drupalget($node->toUrl('edit-form')); + $this->drupalPostForm(NULL, [], t('Save')); + $this->assertSession()->pageTextNotContains(t('The alias is already in use.')); + } + } diff --git a/web/core/modules/quickedit/src/Form/QuickEditFieldForm.php b/web/core/modules/quickedit/src/Form/QuickEditFieldForm.php index c092167a794799c9ef2b24fbc157658f66a7e3ee..0f5aa8c8f664265b2685017a822288821ce324f5 100644 --- a/web/core/modules/quickedit/src/Form/QuickEditFieldForm.php +++ b/web/core/modules/quickedit/src/Form/QuickEditFieldForm.php @@ -12,7 +12,6 @@ use Drupal\Core\Entity\Entity\EntityFormDisplay; use Drupal\Core\TempStore\PrivateTempStoreFactory; use Symfony\Component\DependencyInjection\ContainerInterface; -use Symfony\Component\Validator\Validator\ValidatorInterface; /** * Builds and process a form for editing a single entity field. @@ -42,13 +41,6 @@ class QuickEditFieldForm extends FormBase { */ protected $nodeTypeStorage; - /** - * The typed data validator. - * - * @var \Symfony\Component\Validator\Validator\ValidatorInterface - */ - protected $validator; - /** * Constructs a new EditFieldForm. * @@ -58,14 +50,11 @@ class QuickEditFieldForm extends FormBase { * The module handler. * @param \Drupal\Core\Entity\EntityStorageInterface $node_type_storage * The node type storage. - * @param \Symfony\Component\Validator\Validator\ValidatorInterface $validator - * The typed data validator service. */ - public function __construct(PrivateTempStoreFactory $temp_store_factory, ModuleHandlerInterface $module_handler, EntityStorageInterface $node_type_storage, ValidatorInterface $validator) { + public function __construct(PrivateTempStoreFactory $temp_store_factory, ModuleHandlerInterface $module_handler, EntityStorageInterface $node_type_storage) { $this->moduleHandler = $module_handler; $this->nodeTypeStorage = $node_type_storage; $this->tempStoreFactory = $temp_store_factory; - $this->validator = $validator; } /** @@ -75,8 +64,7 @@ public static function create(ContainerInterface $container) { return new static( $container->get('tempstore.private'), $container->get('module_handler'), - $container->get('entity.manager')->getStorage('node_type'), - $container->get('typed_data_manager')->getValidator() + $container->get('entity.manager')->getStorage('node_type') ); } diff --git a/web/core/modules/quickedit/src/Tests/QuickEditAutocompleteTermTest.php b/web/core/modules/quickedit/src/Tests/QuickEditAutocompleteTermTest.php index a1ef6cd2e8bbf615839fdca2f532a4206e9abceb..97ccc77710588542c64d28114ee48341cface921 100644 --- a/web/core/modules/quickedit/src/Tests/QuickEditAutocompleteTermTest.php +++ b/web/core/modules/quickedit/src/Tests/QuickEditAutocompleteTermTest.php @@ -6,10 +6,10 @@ use Drupal\Core\EventSubscriber\MainContentViewSubscriber; use Drupal\Core\Field\FieldStorageDefinitionInterface; use Drupal\Core\Language\LanguageInterface; -use Drupal\field\Tests\EntityReference\EntityReferenceTestTrait; use Drupal\simpletest\WebTestBase; use Drupal\taxonomy\Entity\Vocabulary; use Drupal\taxonomy\Entity\Term; +use Drupal\Tests\field\Traits\EntityReferenceTestTrait; /** * Tests in-place editing of autocomplete tags. diff --git a/web/core/modules/quickedit/tests/src/FunctionalJavascript/QuickEditFileTest.php b/web/core/modules/quickedit/tests/src/FunctionalJavascript/QuickEditFileTest.php new file mode 100644 index 0000000000000000000000000000000000000000..a1de95c01bf78f626941296b4ea5760589101f09 --- /dev/null +++ b/web/core/modules/quickedit/tests/src/FunctionalJavascript/QuickEditFileTest.php @@ -0,0 +1,100 @@ +<?php + +namespace Drupal\Tests\quickedit\FunctionalJavascript; + +use Drupal\file\Entity\File; +use Drupal\node\Entity\Node; +use Drupal\Tests\file\Functional\FileFieldCreationTrait; +use Drupal\Tests\TestFileCreationTrait; + +/** + * @group quickedit + */ +class QuickEditFileTest extends QuickEditJavascriptTestBase { + + use FileFieldCreationTrait; + use TestFileCreationTrait; + + /** + * {@inheritdoc} + */ + public static $modules = [ + 'node', + 'file', + ]; + + /** + * {@inheritdoc} + */ + protected function setUp() { + parent::setUp(); + + // Create the Article node type. + $this->drupalCreateContentType(['type' => 'article', 'name' => 'Article']); + + // Add file field to Article node type. + $this->createFileField('field_file', 'node', 'article', ['file_extensions' => 'txt']); + + // Log in as a content author who can use Quick Edit and edit Articles. + $user = $this->drupalCreateUser([ + 'access contextual links', + 'access toolbar', + 'access in-place editing', + 'access content', + 'create article content', + 'edit any article content', + ]); + $this->drupalLogin($user); + } + + /** + * Tests if a file can be in-place removed with Quick Edit. + */ + public function testRemove() { + $assert_session = $this->assertSession(); + + // Create test file. + $this->generateFile('test', 64, 10, 'text'); + $file = File::create([ + 'uri' => 'public://test.txt', + 'filename' => 'test.txt', + ]); + $file->setPermanent(); + $file->save(); + + // Create test node. + $node = $this->drupalCreateNode([ + 'type' => 'article', + 'title' => t('My Test Node'), + 'field_file' => [ + 'target_id' => $file->id(), + ], + ]); + + $this->drupalGet($node->toUrl()->toString()); + + // Start Quick Edit. + $this->awaitQuickEditForEntity('node', 1); + $this->startQuickEditViaToolbar('node', 1, 0); + + // Click the file field. + $assert_session->waitForElementVisible('css', '[data-quickedit-field-id="node/1/field_file/en/full"]'); + $this->click('[data-quickedit-field-id="node/1/field_file/en/full"]'); + $assert_session->waitForElement('css', '.quickedit-toolbar-field div[id*="file"]'); + + // Remove the file. + $remove = $assert_session->waitForButton('Remove'); + $remove->click(); + // Wait for remove. + $assert_session->waitForElement('css', 'input[name="files[field_file_0]"]'); + $this->saveQuickEdit(); + // Wait for save. + $this->assertJsCondition("Drupal.quickedit.collections.entities.get('node/1[0]').get('state') === 'closed'"); + + // Assert file is removed from node. + $assert_session->pageTextNotContains('test.txt'); + $node = Node::load($node->id()); + $this->assertEmpty($node->get('field_file')->getValue()); + } + +} diff --git a/web/core/modules/quickedit/tests/src/FunctionalJavascript/QuickEditIntegrationTest.php b/web/core/modules/quickedit/tests/src/FunctionalJavascript/QuickEditIntegrationTest.php index cb3f141b067e0c7fdd1c2c7ab13c0ed1b35044ff..52d645f0f8c1f77bfdd86f3a28f33cba070ea325 100644 --- a/web/core/modules/quickedit/tests/src/FunctionalJavascript/QuickEditIntegrationTest.php +++ b/web/core/modules/quickedit/tests/src/FunctionalJavascript/QuickEditIntegrationTest.php @@ -6,10 +6,10 @@ use Drupal\block_content\Entity\BlockContentType; use Drupal\Core\Field\FieldStorageDefinitionInterface; use Drupal\editor\Entity\Editor; -use Drupal\field\Tests\EntityReference\EntityReferenceTestTrait; use Drupal\filter\Entity\FilterFormat; use Drupal\taxonomy\Entity\Term; use Drupal\taxonomy\Entity\Vocabulary; +use Drupal\Tests\field\Traits\EntityReferenceTestTrait; /** * @group quickedit diff --git a/web/core/modules/rdf/migrations/d7_rdf_mapping.yml b/web/core/modules/rdf/migrations/d7_rdf_mapping.yml index de60bd3c528b075bdeacc424a9aeb4359dbc15f6..29fffe410cdd676f28e0654c2f36d0346abc8161 100644 --- a/web/core/modules/rdf/migrations/d7_rdf_mapping.yml +++ b/web/core/modules/rdf/migrations/d7_rdf_mapping.yml @@ -6,6 +6,12 @@ migration_tags: source: plugin: d7_rdf_mapping process: + id: + plugin: concat + source: + - type + - bundle + delimiter: . targetEntityType: type bundle: bundle types: types @@ -15,7 +21,12 @@ process: process: properties: predicates datatype: datatype - datatype_callback/callable: callback + datatype_callback/callable: + plugin: static_map + source: callback + bypass: true + map: + date_iso8601: Drupal\rdf\CommonDataConverter::dateIso8601Value mapping_type: type destination: plugin: entity:rdf_mapping diff --git a/web/core/modules/rdf/tests/src/Kernel/Field/EntityReferenceRdfaTest.php b/web/core/modules/rdf/tests/src/Kernel/Field/EntityReferenceRdfaTest.php index 9312fbc929504c0c6976c22d81e10622e6b813e0..b8e8e4be6857321b9d1a06324419cf423c36b079 100644 --- a/web/core/modules/rdf/tests/src/Kernel/Field/EntityReferenceRdfaTest.php +++ b/web/core/modules/rdf/tests/src/Kernel/Field/EntityReferenceRdfaTest.php @@ -2,7 +2,7 @@ namespace Drupal\Tests\rdf\Kernel\Field; -use Drupal\field\Tests\EntityReference\EntityReferenceTestTrait; +use Drupal\Tests\field\Traits\EntityReferenceTestTrait; use Drupal\user\Entity\Role; use Drupal\user\RoleInterface; diff --git a/web/core/modules/rdf/tests/src/Kernel/Migrate/d7/MigrateRdfMappingTest.php b/web/core/modules/rdf/tests/src/Kernel/Migrate/d7/MigrateRdfMappingTest.php index c61a7c4039e849889858302ff33239862b90aed7..67ea0c41c3db25929e4b1737083bfd35bf4da092 100644 --- a/web/core/modules/rdf/tests/src/Kernel/Migrate/d7/MigrateRdfMappingTest.php +++ b/web/core/modules/rdf/tests/src/Kernel/Migrate/d7/MigrateRdfMappingTest.php @@ -98,7 +98,7 @@ public function testRdfMappingMigration() { ], 'datatype' => 'xsd:dateTime', 'datatype_callback' => [ - 'callable' => 'date_iso8601', + 'callable' => 'Drupal\rdf\CommonDataConverter::dateIso8601Value', ], ], 'changed' => [ @@ -107,7 +107,7 @@ public function testRdfMappingMigration() { ], 'datatype' => 'xsd:dateTime', 'datatype_callback' => [ - 'callable' => 'date_iso8601', + 'callable' => 'Drupal\rdf\CommonDataConverter::dateIso8601Value', ], ], 'body' => [ @@ -138,7 +138,7 @@ public function testRdfMappingMigration() { ], 'datatype' => 'xsd:dateTime', 'datatype_callback' => [ - 'callable' => 'date_iso8601', + 'callable' => 'Drupal\rdf\CommonDataConverter::dateIso8601Value', ], ], ] @@ -165,7 +165,7 @@ public function testRdfMappingMigration() { ], 'datatype' => 'xsd:dateTime', 'datatype_callback' => [ - 'callable' => 'date_iso8601', + 'callable' => 'Drupal\rdf\CommonDataConverter::dateIso8601Value', ], ], 'changed' => [ @@ -174,7 +174,7 @@ public function testRdfMappingMigration() { ], 'datatype' => 'xsd:dateTime', 'datatype_callback' => [ - 'callable' => 'date_iso8601', + 'callable' => 'Drupal\rdf\CommonDataConverter::dateIso8601Value', ], ], 'body' => [ @@ -205,7 +205,7 @@ public function testRdfMappingMigration() { ], 'datatype' => 'xsd:dateTime', 'datatype_callback' => [ - 'callable' => 'date_iso8601', + 'callable' => 'Drupal\rdf\CommonDataConverter::dateIso8601Value', ], ], ] @@ -238,7 +238,7 @@ public function testRdfMappingMigration() { ], 'datatype' => 'xsd:dateTime', 'datatype_callback' => [ - 'callable' => 'date_iso8601', + 'callable' => 'Drupal\rdf\CommonDataConverter::dateIso8601Value', ], ], 'changed' => [ @@ -247,7 +247,7 @@ public function testRdfMappingMigration() { ], 'datatype' => 'xsd:dateTime', 'datatype_callback' => [ - 'callable' => 'date_iso8601', + 'callable' => 'Drupal\rdf\CommonDataConverter::dateIso8601Value', ], ], 'body' => [ @@ -278,7 +278,7 @@ public function testRdfMappingMigration() { ], 'datatype' => 'xsd:dateTime', 'datatype_callback' => [ - 'callable' => 'date_iso8601', + 'callable' => 'Drupal\rdf\CommonDataConverter::dateIso8601Value', ], ], ] @@ -304,7 +304,7 @@ public function testRdfMappingMigration() { ], 'datatype' => 'xsd:dateTime', 'datatype_callback' => [ - 'callable' => 'date_iso8601', + 'callable' => 'Drupal\rdf\CommonDataConverter::dateIso8601Value', ], ], 'changed' => [ @@ -313,7 +313,7 @@ public function testRdfMappingMigration() { ], 'datatype' => 'xsd:dateTime', 'datatype_callback' => [ - 'callable' => 'date_iso8601', + 'callable' => 'Drupal\rdf\CommonDataConverter::dateIso8601Value', ], ], 'body' => [ @@ -344,7 +344,7 @@ public function testRdfMappingMigration() { ], 'datatype' => 'xsd:dateTime', 'datatype_callback' => [ - 'callable' => 'date_iso8601', + 'callable' => 'Drupal\rdf\CommonDataConverter::dateIso8601Value', ], ], ] @@ -384,6 +384,12 @@ public function testRdfMappingMigration() { ], ] ); + + // Clear the map table and check that the migration runs successfully when + // the rdf mappings already exist. + $id_map = $this->getMigration('d7_rdf_mapping')->getIdMap(); + $id_map->destroy(); + $this->executeMigration('d7_rdf_mapping'); } } diff --git a/web/core/modules/responsive_image/src/Tests/ResponsiveImageFieldDisplayTest.php b/web/core/modules/responsive_image/tests/src/Functional/ResponsiveImageFieldDisplayTest.php similarity index 95% rename from web/core/modules/responsive_image/src/Tests/ResponsiveImageFieldDisplayTest.php rename to web/core/modules/responsive_image/tests/src/Functional/ResponsiveImageFieldDisplayTest.php index 3828ab0d75e918f26c7fe7565706100749f55133..11697637d1da32b878212c5f36da89d6182ff593 100644 --- a/web/core/modules/responsive_image/src/Tests/ResponsiveImageFieldDisplayTest.php +++ b/web/core/modules/responsive_image/tests/src/Functional/ResponsiveImageFieldDisplayTest.php @@ -1,13 +1,14 @@ <?php -namespace Drupal\responsive_image\Tests; +namespace Drupal\Tests\responsive_image\Functional; -use Drupal\image\Tests\ImageFieldTestBase; use Drupal\image\Entity\ImageStyle; use Drupal\node\Entity\Node; use Drupal\file\Entity\File; use Drupal\responsive_image\Plugin\Field\FieldFormatter\ResponsiveImageFormatter; use Drupal\responsive_image\Entity\ResponsiveImageStyle; +use Drupal\Tests\image\Functional\ImageFieldTestBase; +use Drupal\Tests\TestFileCreationTrait; use Drupal\user\RoleInterface; /** @@ -17,6 +18,8 @@ */ class ResponsiveImageFieldDisplayTest extends ImageFieldTestBase { + use TestFileCreationTrait; + protected $dumpHeaders = TRUE; /** @@ -172,7 +175,7 @@ protected function doTestResponsiveImageFieldFormatters($scheme, $empty_styles = $this->createImageField($field_name, 'article', ['uri_scheme' => $scheme]); // Create a new node with an image attached. Make sure we use a large image // so the scale effects of the image styles always have an effect. - $test_image = current($this->drupalGetTestFiles('image', 39325)); + $test_image = current($this->getTestFiles('image', 39325)); // Create alt text for the image. $alt = $this->randomMachineName(); @@ -240,13 +243,11 @@ protected function doTestResponsiveImageFieldFormatters($scheme, $empty_styles = $display->setComponent($field_name, $display_options) ->save(); - $default_output = '<a href="' . file_url_transform_relative(file_create_url($image_uri)) . '"><picture'; $this->drupalGet('node/' . $nid); $cache_tags_header = $this->drupalGetHeader('X-Drupal-Cache-Tags'); $this->assertTrue(!preg_match('/ image_style\:/', $cache_tags_header), 'No image style cache tag found.'); - $this->removeWhiteSpace(); - $this->assertRaw($default_output, 'Image linked to file formatter displaying correctly on full node view.'); + $this->assertPattern('/<a(.*?)href="' . preg_quote(file_url_transform_relative(file_create_url($image_uri)), '/') . '"(.*?)>\s*<picture/'); // Verify that the image can be downloaded. $this->assertEqual(file_get_contents($test_image->uri), $this->drupalGet(file_create_url($image_uri)), 'File was downloaded successfully.'); if ($scheme == 'private') { @@ -369,7 +370,7 @@ public function testResponsiveImageFieldFormattersEmptyMediaQuery() { $field_name = mb_strtolower($this->randomMachineName()); $this->createImageField($field_name, 'article', ['uri_scheme' => 'public']); // Create a new node with an image attached. - $test_image = current($this->drupalGetTestFiles('image')); + $test_image = current($this->getTestFiles('image')); $nid = $this->uploadNodeImage($test_image, $field_name, 'article', $this->randomMachineName()); $node_storage->resetCache([$nid]); @@ -389,7 +390,7 @@ public function testResponsiveImageFieldFormattersEmptyMediaQuery() { $this->drupalGet('node/' . $nid); // Assert an empty media attribute is not output. - $this->assertNoPattern('@srcset="data:image/gif;base64,R0lGODlhAQABAIABAP///wAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw== 1x".+?media=".+?/><source@'); + $this->assertSession()->responseNotMatches('@srcset="data:image/gif;base64,R0lGODlhAQABAIABAP///wAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw== 1x".+?media=".+?/><source@'); // Assert the media attribute is present if it has a value. $thumbnail_style = ImageStyle::load('thumbnail'); @@ -417,7 +418,7 @@ public function testResponsiveImageFieldFormattersOneSource() { $field_name = mb_strtolower($this->randomMachineName()); $this->createImageField($field_name, 'article', ['uri_scheme' => 'public']); // Create a new node with an image attached. - $test_image = current($this->drupalGetTestFiles('image')); + $test_image = current($this->getTestFiles('image')); $nid = $this->uploadNodeImage($test_image, $field_name, 'article', $this->randomMachineName()); $node_storage->resetCache([$nid]); @@ -455,7 +456,7 @@ private function assertResponsiveImageFieldFormattersLink($link_type) { $field_settings = ['alt_field_required' => 0]; $this->createImageField($field_name, 'article', ['uri_scheme' => 'public'], $field_settings); // Create a new node with an image attached. - $test_image = current($this->drupalGetTestFiles('image')); + $test_image = current($this->getTestFiles('image')); // Test the image linked to file formatter. $display_options = [ @@ -497,16 +498,15 @@ private function assertResponsiveImageFieldFormattersLink($link_type) { // Output should contain all image styles and all breakpoints. $this->drupalGet('node/' . $nid); - $this->removeWhiteSpace(); switch ($link_type) { case 'file': // Make sure the link to the file is present. - $this->assertPattern('/<a(.*?)href="' . preg_quote(file_url_transform_relative(file_create_url($image_uri)), '/') . '"(.*?)><picture/'); + $this->assertPattern('/<a(.*?)href="' . preg_quote(file_url_transform_relative(file_create_url($image_uri)), '/') . '"(.*?)>\s*<picture/'); break; case 'content': // Make sure the link to the node is present. - $this->assertPattern('/<a(.*?)href="' . preg_quote($node->url(), '/') . '"(.*?)><picture/'); + $this->assertPattern('/<a(.*?)href="' . preg_quote($node->url(), '/') . '"(.*?)>\s*<picture/'); break; } } diff --git a/web/core/modules/rest/src/Plugin/rest/resource/EntityResource.php b/web/core/modules/rest/src/Plugin/rest/resource/EntityResource.php index 9dce5df2b77742072460b1929b15958f0050c998..ebfd0750414e95512e21af492e3c89cf9c71e15e 100644 --- a/web/core/modules/rest/src/Plugin/rest/resource/EntityResource.php +++ b/web/core/modules/rest/src/Plugin/rest/resource/EntityResource.php @@ -229,6 +229,8 @@ public function patch(EntityInterface $original_entity, EntityInterface $entity } // Overwrite the received fields. + // @todo Remove $changed_fields in https://www.drupal.org/project/drupal/issues/2862574. + $changed_fields = []; foreach ($entity->_restSubmittedFields as $field_name) { $field = $entity->get($field_name); // It is not possible to set the language to NULL as it is automatically @@ -238,12 +240,18 @@ public function patch(EntityInterface $original_entity, EntityInterface $entity continue; } if ($this->checkPatchFieldAccess($original_entity->get($field_name), $field)) { + $changed_fields[] = $field_name; $original_entity->set($field_name, $field->getValue()); } } + // If no fields are changed, we can send a response immediately! + if (empty($changed_fields)) { + return new ModifiedResourceResponse($original_entity, 200); + } + // Validate the received data before saving. - $this->validate($original_entity); + $this->validate($original_entity, $changed_fields); try { $original_entity->save(); $this->logger->notice('Updated entity %type with ID %id.', ['%type' => $original_entity->getEntityTypeId(), '%id' => $original_entity->id()]); @@ -275,13 +283,6 @@ public function patch(EntityInterface $original_entity, EntityInterface $entity * @internal */ protected function checkPatchFieldAccess(FieldItemListInterface $original_field, FieldItemListInterface $received_field) { - // If the user is allowed to edit the field, it is always safe to set the - // received value. We may be setting an unchanged value, but that is ok. - $field_edit_access = $original_field->access('edit', NULL, TRUE); - if ($field_edit_access->isAllowed()) { - return TRUE; - } - // The user might not have access to edit the field, but still needs to // submit the current field value as part of the PATCH request. For // example, the entity keys required by denormalizers. Therefore, if the @@ -294,6 +295,13 @@ protected function checkPatchFieldAccess(FieldItemListInterface $original_field, return FALSE; } + // If the user is allowed to edit the field, it is always safe to set the + // received value. We may be setting an unchanged value, but that is ok. + $field_edit_access = $original_field->access('edit', NULL, TRUE); + if ($field_edit_access->isAllowed()) { + return TRUE; + } + // It's helpful and safe to let the user know when they are not allowed to // update a field. $field_name = $received_field->getName(); diff --git a/web/core/modules/rest/src/Plugin/rest/resource/EntityResourceValidationTrait.php b/web/core/modules/rest/src/Plugin/rest/resource/EntityResourceValidationTrait.php index 09b4b64baec0f47956107060f8068a899d0f8231..03201922f47d35c84a18c5ea729cb6d4c7910688 100644 --- a/web/core/modules/rest/src/Plugin/rest/resource/EntityResourceValidationTrait.php +++ b/web/core/modules/rest/src/Plugin/rest/resource/EntityResourceValidationTrait.php @@ -14,16 +14,23 @@ trait EntityResourceValidationTrait { /** - * Verifies that the whole entity does not violate any validation constraints. + * Verifies that an entity does not violate any validation constraints. + * + * The validation errors will be filtered to not include fields to which the + * current user does not have access and if $fields_to_validate is provided + * will only include fields in that array. * * @param \Drupal\Core\Entity\EntityInterface $entity * The entity to validate. + * @param string[] $fields_to_validate + * (optional) An array of field names. If specified, filters the violations + * list to include only this set of fields. * * @throws \Symfony\Component\HttpKernel\Exception\UnprocessableEntityHttpException * If validation errors are found. */ - protected function validate(EntityInterface $entity) { - // @todo Remove when https://www.drupal.org/node/2164373 is committed. + protected function validate(EntityInterface $entity, array $fields_to_validate = []) { + // @todo Update this check in https://www.drupal.org/node/2300677. if (!$entity instanceof FieldableEntityInterface) { return; } @@ -33,6 +40,11 @@ protected function validate(EntityInterface $entity) { // changes. $violations->filterByFieldAccess(); + if ($fields_to_validate) { + // Filter violations by explicitly provided array of field names. + $violations->filterByFields(array_diff(array_keys($entity->getFieldDefinitions()), $fields_to_validate)); + } + if ($violations->count() > 0) { $message = "Unprocessable Entity: validation failed.\n"; foreach ($violations as $violation) { diff --git a/web/core/modules/rest/tests/modules/rest_test/rest_test.module b/web/core/modules/rest/tests/modules/rest_test/rest_test.module index 8897fb98116b88bdf7a861785c2e7729c04a5708..9839edbf39a180e2305f516da95c3118265fa219 100644 --- a/web/core/modules/rest/tests/modules/rest_test/rest_test.module +++ b/web/core/modules/rest/tests/modules/rest_test/rest_test.module @@ -5,6 +5,8 @@ * Contains hook implementations for testing REST module. */ +use Drupal\Core\Entity\EntityTypeInterface; +use Drupal\Core\Field\BaseFieldDefinition; use Drupal\Core\Field\FieldDefinitionInterface; use Drupal\Core\Session\AccountInterface; use Drupal\Core\Field\FieldItemListInterface; @@ -40,6 +42,30 @@ function rest_test_entity_field_access($operation, FieldDefinitionInterface $fie } } + // @see \Drupal\Tests\rest\Functional\EntityResource\EntityResourceTestBase::testGet() + // @see \Drupal\Tests\rest\Functional\EntityResource\EntityResourceTestBase::testPatch() + if ($field_definition->getName() === 'rest_test_validation') { + switch ($operation) { + case 'view': + // Never ever allow this field to be viewed: this lets + // EntityResourceTestBase::testGet() test in a "vanilla" way. + return AccessResult::forbidden(); + } + } + // No opinion. return AccessResult::neutral(); } + +/** + * Implements hook_entity_base_field_info(). + */ +function rest_test_entity_base_field_info(EntityTypeInterface $entity_type) { + $fields = []; + $fields['rest_test_validation'] = BaseFieldDefinition::create('string') + ->setLabel(t('REST test validation field')) + ->setDescription(t('A text field with some special validations attached used for testing purposes')) + ->addConstraint('rest_test_validation'); + + return $fields; +} diff --git a/web/core/modules/rest/tests/modules/rest_test/src/Plugin/Validation/Constraint/RestTestConstraint.php b/web/core/modules/rest/tests/modules/rest_test/src/Plugin/Validation/Constraint/RestTestConstraint.php new file mode 100644 index 0000000000000000000000000000000000000000..ab4f1fe15639ca17e49c9779656f8992eefd4e0f --- /dev/null +++ b/web/core/modules/rest/tests/modules/rest_test/src/Plugin/Validation/Constraint/RestTestConstraint.php @@ -0,0 +1,21 @@ +<?php + +namespace Drupal\rest_test\Plugin\Validation\Constraint; + +use Symfony\Component\Validator\Constraint; + +/** + * Adds some validations for a REST test field. + * + * @Constraint( + * id = "rest_test_validation", + * label = @Translation("REST test validation", context = "Validation") + * ) + * + * @see \Drupal\Core\TypedData\OptionsProviderInterface + */ +class RestTestConstraint extends Constraint { + + public $message = 'REST test validation failed'; + +} diff --git a/web/core/modules/rest/tests/modules/rest_test/src/Plugin/Validation/Constraint/RestTestConstraintValidator.php b/web/core/modules/rest/tests/modules/rest_test/src/Plugin/Validation/Constraint/RestTestConstraintValidator.php new file mode 100644 index 0000000000000000000000000000000000000000..e71c148bce3817a9397d974c98f79bb06f8ea148 --- /dev/null +++ b/web/core/modules/rest/tests/modules/rest_test/src/Plugin/Validation/Constraint/RestTestConstraintValidator.php @@ -0,0 +1,26 @@ +<?php + +namespace Drupal\rest_test\Plugin\Validation\Constraint; + +use Drupal\Core\Field\FieldItemListInterface; +use Symfony\Component\Validator\Constraint; +use Symfony\Component\Validator\ConstraintValidator; + +/** + * Validator for \Drupal\rest_test\Plugin\Validation\Constraint\RestTestConstraint. + */ +class RestTestConstraintValidator extends ConstraintValidator { + + /** + * {@inheritdoc} + */ + public function validate($value, Constraint $constraint) { + if ($value instanceof FieldItemListInterface) { + $value = $value->getValue(); + if (!empty($value[0]['value']) && $value[0]['value'] === 'ALWAYS_FAIL') { + $this->context->addViolation($constraint->message); + } + } + } + +} diff --git a/web/core/modules/rest/tests/src/Functional/EntityResource/EntityResourceTestBase.php b/web/core/modules/rest/tests/src/Functional/EntityResource/EntityResourceTestBase.php index 5e0d4e51764f6993821ec42ba50076c4ddda66a6..17e0c0a7b5fd230a7d4bef98922f5bed24b758d4 100644 --- a/web/core/modules/rest/tests/src/Functional/EntityResource/EntityResourceTestBase.php +++ b/web/core/modules/rest/tests/src/Functional/EntityResource/EntityResourceTestBase.php @@ -236,6 +236,7 @@ public function setUp() { // Set a default value on the fields. $this->entity->set('field_rest_test', ['value' => 'All the faith he had had had had no effect on the outcome of his life.']); $this->entity->set('field_rest_test_multivalue', [['value' => 'One'], ['value' => 'Two']]); + $this->entity->set('rest_test_validation', ['value' => 'allowed value']); $this->entity->save(); } } @@ -667,6 +668,7 @@ public function testGet() { // ::formatExpectedTimestampValue() to generate the timestamp value. This // will take into account the above config setting. $expected = $this->getExpectedNormalizedEntity(); + // Config entities are not affected. // @see \Drupal\serialization\Normalizer\ConfigEntityNormalizer::normalize() static::recursiveKSort($expected); @@ -1144,6 +1146,39 @@ public function testPatch() { $modified_entity->get($patch_protected_field_name)->setValue($original_values[$patch_protected_field_name]); } + if ($this->entity instanceof FieldableEntityInterface) { + // Change the rest_test_validation field to prove that then its validation + // does run. + $override = [ + 'rest_test_validation' => [ + [ + 'value' => 'ALWAYS_FAIL', + ], + ], + ]; + $valid_request_body = $override + $this->getNormalizedPatchEntity() + $this->serializer->normalize($modified_entity, static::$format); + $request_options[RequestOptions::BODY] = $this->serializer->serialize($valid_request_body, static::$format); + $response = $this->request('PATCH', $url, $request_options); + $this->assertResourceErrorResponse(422, "Unprocessable Entity: validation failed.\nrest_test_validation: REST test validation failed\n", $response); + + // Set the rest_test_validation field to always fail validation, which + // allows asserting that not modifying that field does not trigger + // validation errors. + $this->entity->set('rest_test_validation', 'ALWAYS_FAIL'); + $this->entity->save(); + + // Information disclosure prevented: when a malicious user correctly + // guesses the current invalid value of a field, ensure a 200 is not sent + // because this would disclose to the attacker what the current value is. + // @see rest_test_entity_field_access() + $response = $this->request('PATCH', $url, $request_options); + $this->assertResourceErrorResponse(422, "Unprocessable Entity: validation failed.\nrest_test_validation: REST test validation failed\n", $response); + + // All requests after the above one will not include this field (neither + // its current value nor any other), and therefore all subsequent test + // assertions should not trigger a validation error. + } + // 200 for well-formed PATCH request that sends all fields (even including // read-only ones, but with unchanged values). $valid_request_body = $this->getNormalizedPatchEntity() + $this->serializer->normalize($this->entity, static::$format); diff --git a/web/core/modules/rest/tests/src/Functional/EntityResource/ModeratedNode/ModeratedNodeJsonAnonTest.php b/web/core/modules/rest/tests/src/Functional/EntityResource/ModeratedNode/ModeratedNodeJsonAnonTest.php new file mode 100644 index 0000000000000000000000000000000000000000..f28788ac80183f80a8cbb6a17af4ba455ed9cebc --- /dev/null +++ b/web/core/modules/rest/tests/src/Functional/EntityResource/ModeratedNode/ModeratedNodeJsonAnonTest.php @@ -0,0 +1,24 @@ +<?php + +namespace Drupal\Tests\rest\Functional\EntityResource\ModeratedNode; + +use Drupal\Tests\rest\Functional\AnonResourceTestTrait; + +/** + * @group rest + */ +class ModeratedNodeJsonAnonTest extends ModeratedNodeResourceTestBase { + + use AnonResourceTestTrait; + + /** + * {@inheritdoc} + */ + protected static $format = 'json'; + + /** + * {@inheritdoc} + */ + protected static $mimeType = 'application/json'; + +} diff --git a/web/core/modules/rest/tests/src/Functional/EntityResource/ModeratedNode/ModeratedNodeJsonBasicAuthTest.php b/web/core/modules/rest/tests/src/Functional/EntityResource/ModeratedNode/ModeratedNodeJsonBasicAuthTest.php new file mode 100644 index 0000000000000000000000000000000000000000..b47a86f65ffb959b7f4ddf59c85c967400af38c2 --- /dev/null +++ b/web/core/modules/rest/tests/src/Functional/EntityResource/ModeratedNode/ModeratedNodeJsonBasicAuthTest.php @@ -0,0 +1,34 @@ +<?php + +namespace Drupal\Tests\rest\Functional\EntityResource\ModeratedNode; + +use Drupal\Tests\rest\Functional\BasicAuthResourceTestTrait; + +/** + * @group rest + */ +class ModeratedNodeJsonBasicAuthTest extends ModeratedNodeResourceTestBase { + + use BasicAuthResourceTestTrait; + + /** + * {@inheritdoc} + */ + public static $modules = ['basic_auth']; + + /** + * {@inheritdoc} + */ + protected static $format = 'json'; + + /** + * {@inheritdoc} + */ + protected static $mimeType = 'application/json'; + + /** + * {@inheritdoc} + */ + protected static $auth = 'basic_auth'; + +} diff --git a/web/core/modules/rest/tests/src/Functional/EntityResource/ModeratedNode/ModeratedNodeJsonCookieTest.php b/web/core/modules/rest/tests/src/Functional/EntityResource/ModeratedNode/ModeratedNodeJsonCookieTest.php new file mode 100644 index 0000000000000000000000000000000000000000..08fc4b5f4fb087427a297d08b04caebf6a4bef3e --- /dev/null +++ b/web/core/modules/rest/tests/src/Functional/EntityResource/ModeratedNode/ModeratedNodeJsonCookieTest.php @@ -0,0 +1,29 @@ +<?php + +namespace Drupal\Tests\rest\Functional\EntityResource\ModeratedNode; + +use Drupal\Tests\rest\Functional\CookieResourceTestTrait; + +/** + * @group rest + */ +class ModeratedNodeJsonCookieTest extends ModeratedNodeResourceTestBase { + + use CookieResourceTestTrait; + + /** + * {@inheritdoc} + */ + protected static $format = 'json'; + + /** + * {@inheritdoc} + */ + protected static $mimeType = 'application/json'; + + /** + * {@inheritdoc} + */ + protected static $auth = 'cookie'; + +} diff --git a/web/core/modules/rest/tests/src/Functional/EntityResource/ModeratedNode/ModeratedNodeResourceTestBase.php b/web/core/modules/rest/tests/src/Functional/EntityResource/ModeratedNode/ModeratedNodeResourceTestBase.php new file mode 100644 index 0000000000000000000000000000000000000000..054259dbc5619b9bf56662f6f59fd4f5ec128e75 --- /dev/null +++ b/web/core/modules/rest/tests/src/Functional/EntityResource/ModeratedNode/ModeratedNodeResourceTestBase.php @@ -0,0 +1,74 @@ +<?php + +namespace Drupal\Tests\rest\Functional\EntityResource\ModeratedNode; + +use Drupal\Tests\content_moderation\Traits\ContentModerationTestTrait; +use Drupal\Tests\node\Functional\Rest\NodeResourceTestBase; + +/** + * Extend the Node resource test base and apply moderation to the entity. + */ +abstract class ModeratedNodeResourceTestBase extends NodeResourceTestBase { + + use ContentModerationTestTrait; + + /** + * {@inheritdoc} + */ + public static $modules = ['content_moderation']; + + /** + * The test editorial workflow. + * + * @var \Drupal\workflows\WorkflowInterface + */ + protected $workflow; + + /** + * {@inheritdoc} + */ + protected function setUpAuthorization($method) { + parent::setUpAuthorization($method); + + switch ($method) { + case 'POST': + case 'PATCH': + case 'DELETE': + $this->grantPermissionsToTestedRole(['use editorial transition publish', 'use editorial transition create_new_draft']); + break; + } + } + + /** + * {@inheritdoc} + */ + protected function createEntity() { + $entity = parent::createEntity(); + if (!$this->workflow) { + $this->workflow = $this->createEditorialWorkflow(); + } + $this->workflow->getTypePlugin()->addEntityTypeAndBundle($entity->getEntityTypeId(), $entity->bundle()); + $this->workflow->save(); + + return $entity; + } + + /** + * {@inheritdoc} + */ + protected function getExpectedNormalizedEntity() { + return array_merge(parent::getExpectedNormalizedEntity(), [ + 'moderation_state' => [ + [ + 'value' => 'published', + ], + ], + 'vid' => [ + [ + 'value' => (int) $this->entity->getRevisionId(), + ], + ], + ]); + } + +} diff --git a/web/core/modules/rest/tests/src/Functional/EntityResource/ModeratedNode/ModeratedNodeXmlAnonTest.php b/web/core/modules/rest/tests/src/Functional/EntityResource/ModeratedNode/ModeratedNodeXmlAnonTest.php new file mode 100644 index 0000000000000000000000000000000000000000..4b91d766c6f4c977246650bdea498b708c396401 --- /dev/null +++ b/web/core/modules/rest/tests/src/Functional/EntityResource/ModeratedNode/ModeratedNodeXmlAnonTest.php @@ -0,0 +1,34 @@ +<?php + +namespace Drupal\Tests\rest\Functional\EntityResource\ModeratedNode; + +use Drupal\Tests\rest\Functional\AnonResourceTestTrait; +use Drupal\Tests\rest\Functional\EntityResource\XmlEntityNormalizationQuirksTrait; + +/** + * @group rest + */ +class ModeratedNodeXmlAnonTest extends ModeratedNodeResourceTestBase { + + use AnonResourceTestTrait; + use XmlEntityNormalizationQuirksTrait; + + /** + * {@inheritdoc} + */ + protected static $format = 'xml'; + + /** + * {@inheritdoc} + */ + protected static $mimeType = 'text/xml; charset=UTF-8'; + + /** + * {@inheritdoc} + */ + public function testPatchPath() { + // Deserialization of the XML format is not supported. + $this->markTestSkipped(); + } + +} diff --git a/web/core/modules/rest/tests/src/Functional/EntityResource/ModeratedNode/ModeratedNodeXmlBasicAuthTest.php b/web/core/modules/rest/tests/src/Functional/EntityResource/ModeratedNode/ModeratedNodeXmlBasicAuthTest.php new file mode 100644 index 0000000000000000000000000000000000000000..a321e03cb25f0227081f4fcc38c38897ac0869d0 --- /dev/null +++ b/web/core/modules/rest/tests/src/Functional/EntityResource/ModeratedNode/ModeratedNodeXmlBasicAuthTest.php @@ -0,0 +1,44 @@ +<?php + +namespace Drupal\Tests\rest\Functional\EntityResource\ModeratedNode; + +use Drupal\Tests\rest\Functional\BasicAuthResourceTestTrait; +use Drupal\Tests\rest\Functional\EntityResource\XmlEntityNormalizationQuirksTrait; + +/** + * @group rest + */ +class ModeratedNodeXmlBasicAuthTest extends ModeratedNodeResourceTestBase { + + use BasicAuthResourceTestTrait; + use XmlEntityNormalizationQuirksTrait; + + /** + * {@inheritdoc} + */ + public static $modules = ['basic_auth']; + + /** + * {@inheritdoc} + */ + protected static $format = 'xml'; + + /** + * {@inheritdoc} + */ + protected static $mimeType = 'text/xml; charset=UTF-8'; + + /** + * {@inheritdoc} + */ + protected static $auth = 'basic_auth'; + + /** + * {@inheritdoc} + */ + public function testPatchPath() { + // Deserialization of the XML format is not supported. + $this->markTestSkipped(); + } + +} diff --git a/web/core/modules/rest/tests/src/Functional/EntityResource/ModeratedNode/ModeratedNodeXmlCookieTest.php b/web/core/modules/rest/tests/src/Functional/EntityResource/ModeratedNode/ModeratedNodeXmlCookieTest.php new file mode 100644 index 0000000000000000000000000000000000000000..2014a56ff43d407e00eaca5778a80db192304d5e --- /dev/null +++ b/web/core/modules/rest/tests/src/Functional/EntityResource/ModeratedNode/ModeratedNodeXmlCookieTest.php @@ -0,0 +1,39 @@ +<?php + +namespace Drupal\Tests\rest\Functional\EntityResource\ModeratedNode; + +use Drupal\Tests\rest\Functional\CookieResourceTestTrait; +use Drupal\Tests\rest\Functional\EntityResource\XmlEntityNormalizationQuirksTrait; + +/** + * @group rest + */ +class ModeratedNodeXmlCookieTest extends ModeratedNodeResourceTestBase { + + use CookieResourceTestTrait; + use XmlEntityNormalizationQuirksTrait; + + /** + * {@inheritdoc} + */ + protected static $format = 'xml'; + + /** + * {@inheritdoc} + */ + protected static $mimeType = 'text/xml; charset=UTF-8'; + + /** + * {@inheritdoc} + */ + protected static $auth = 'cookie'; + + /** + * {@inheritdoc} + */ + public function testPatchPath() { + // Deserialization of the XML format is not supported. + $this->markTestSkipped(); + } + +} diff --git a/web/core/modules/rest/tests/src/Functional/Views/StyleSerializerTest.php b/web/core/modules/rest/tests/src/Functional/Views/StyleSerializerTest.php index 269b96b9cc13a4db85186ecfab74890746169e4b..b86ede1e9705f2ce7e64e9819f041268afc13382 100644 --- a/web/core/modules/rest/tests/src/Functional/Views/StyleSerializerTest.php +++ b/web/core/modules/rest/tests/src/Functional/Views/StyleSerializerTest.php @@ -661,7 +661,7 @@ public function testFieldapiField() { } // Test that multiple raw body fields are shown. - // Make the body field unlimited cardinatlity. + // Set the body field to unlimited cardinality. $storage_definition = $node->getFieldDefinition('body')->getFieldStorageDefinition(); $storage_definition->setCardinality(FieldStorageDefinitionInterface::CARDINALITY_UNLIMITED); $storage_definition->save(); diff --git a/web/core/modules/search/search.module b/web/core/modules/search/search.module index c7707fd51c9927df15baaefb29df10c71710b10d..06d0d72ab08350349ad02e522f3c8a60b4f3e5eb 100644 --- a/web/core/modules/search/search.module +++ b/web/core/modules/search/search.module @@ -510,7 +510,7 @@ function search_index($type, $sid, $langcode, $text) { foreach ($words as $word) { // Add word to accumulator $accum .= $word . ' '; - // Check wordlength + // Check word length. if (is_numeric($word) || mb_strlen($word) >= $minimum_word_size) { if (!isset($scored_words[$word])) { $scored_words[$word] = 0; diff --git a/web/core/modules/settings_tray/tests/src/FunctionalJavascript/QuickEditIntegrationTest.php b/web/core/modules/settings_tray/tests/src/FunctionalJavascript/QuickEditIntegrationTest.php index 6f623cb1bcf10dd5d7f96140931c22cb7f5cb2ea..a543baf1262e7b061244b4e321bce65e12541498 100644 --- a/web/core/modules/settings_tray/tests/src/FunctionalJavascript/QuickEditIntegrationTest.php +++ b/web/core/modules/settings_tray/tests/src/FunctionalJavascript/QuickEditIntegrationTest.php @@ -145,7 +145,8 @@ public function testCustomBlockLinks() { $href = array_search('Quick edit', $link_labels); $this->assertEquals('', $href); $href = array_search('Quick edit settings', $link_labels); - $this->assertTrue(strstr($href, '/admin/structure/block/manage/custom/settings-tray?destination=user/2') !== FALSE); + $destination = (string) $this->loggedInUser->toUrl()->toString(); + $this->assertTrue(strstr($href, "/admin/structure/block/manage/custom/settings-tray?destination=$destination") !== FALSE); } /** diff --git a/web/core/modules/settings_tray/tests/src/FunctionalJavascript/SettingsTrayBlockFormTest.php b/web/core/modules/settings_tray/tests/src/FunctionalJavascript/SettingsTrayBlockFormTest.php index 0e6b9d6251e0372d5d481b2cad03c97c39018bf4..d505a0befcb33e1d05b4dec5c8853cd7dd9c7b57 100644 --- a/web/core/modules/settings_tray/tests/src/FunctionalJavascript/SettingsTrayBlockFormTest.php +++ b/web/core/modules/settings_tray/tests/src/FunctionalJavascript/SettingsTrayBlockFormTest.php @@ -69,7 +69,8 @@ protected function doTestBlocks($theme, $block_plugin, $new_page_text, $element_ $link = $web_assert->waitForElement('css', "$block_selector .contextual-links li a"); $this->assertEquals('Quick edit', $link->getHtml(), "'Quick edit' is the first contextual link for the block."); - $this->assertContains("/admin/structure/block/manage/$block_id/settings-tray?destination=user/2", $link->getAttribute('href')); + $destination = (string) $this->loggedInUser->toUrl()->toString(); + $this->assertContains("/admin/structure/block/manage/$block_id/settings-tray?destination=$destination", $link->getAttribute('href')); if (isset($toolbar_item)) { // Check that you can open a toolbar tray and it will be closed after diff --git a/web/core/modules/shortcut/src/ShortcutForm.php b/web/core/modules/shortcut/src/ShortcutForm.php index 26a52629b2f7536bcfc66dd8ba73aef06c0566d0..f41ba253157afb6346195fdb5f12fae1da8b6578 100644 --- a/web/core/modules/shortcut/src/ShortcutForm.php +++ b/web/core/modules/shortcut/src/ShortcutForm.php @@ -19,6 +19,16 @@ class ShortcutForm extends ContentEntityForm { */ protected $entity; + /** + * {@inheritdoc} + */ + public function form(array $form, FormStateInterface $form_state) { + $form = parent::form($form, $form_state); + $form['#attached']['library'][] = 'core/drupal.form'; + + return $form; + } + /** * {@inheritdoc} */ diff --git a/web/core/modules/simpletest/files/phar-1.phar b/web/core/modules/simpletest/files/phar-1.phar new file mode 100644 index 0000000000000000000000000000000000000000..8d25e6d4403979bf0fb37b7d10ff721bc804130d --- /dev/null +++ b/web/core/modules/simpletest/files/phar-1.phar @@ -0,0 +1,301 @@ +<?php + +$web = 'index.php'; + +if (in_array('phar', stream_get_wrappers()) && class_exists('Phar', 0)) { +Phar::interceptFileFuncs(); +set_include_path('phar://' . __FILE__ . PATH_SEPARATOR . get_include_path()); +Phar::webPhar(null, $web); +include 'phar://' . __FILE__ . '/' . Extract_Phar::START; +return; +} + +if (@(isset($_SERVER['REQUEST_URI']) && isset($_SERVER['REQUEST_METHOD']) && ($_SERVER['REQUEST_METHOD'] == 'GET' || $_SERVER['REQUEST_METHOD'] == 'POST'))) { +Extract_Phar::go(true); +$mimes = array( +'phps' => 2, +'c' => 'text/plain', +'cc' => 'text/plain', +'cpp' => 'text/plain', +'c++' => 'text/plain', +'dtd' => 'text/plain', +'h' => 'text/plain', +'log' => 'text/plain', +'rng' => 'text/plain', +'txt' => 'text/plain', +'xsd' => 'text/plain', +'php' => 1, +'inc' => 1, +'avi' => 'video/avi', +'bmp' => 'image/bmp', +'css' => 'text/css', +'gif' => 'image/gif', +'htm' => 'text/html', +'html' => 'text/html', +'htmls' => 'text/html', +'ico' => 'image/x-ico', +'jpe' => 'image/jpeg', +'jpg' => 'image/jpeg', +'jpeg' => 'image/jpeg', +'js' => 'application/x-javascript', +'midi' => 'audio/midi', +'mid' => 'audio/midi', +'mod' => 'audio/mod', +'mov' => 'movie/quicktime', +'mp3' => 'audio/mp3', +'mpg' => 'video/mpeg', +'mpeg' => 'video/mpeg', +'pdf' => 'application/pdf', +'png' => 'image/png', +'swf' => 'application/shockwave-flash', +'tif' => 'image/tiff', +'tiff' => 'image/tiff', +'wav' => 'audio/wav', +'xbm' => 'image/xbm', +'xml' => 'text/xml', +); + +header("Cache-Control: no-cache, must-revalidate"); +header("Pragma: no-cache"); + +$basename = basename(__FILE__); +if (!strpos($_SERVER['REQUEST_URI'], $basename)) { +chdir(Extract_Phar::$temp); +include $web; +return; +} +$pt = substr($_SERVER['REQUEST_URI'], strpos($_SERVER['REQUEST_URI'], $basename) + strlen($basename)); +if (!$pt || $pt == '/') { +$pt = $web; +header('HTTP/1.1 301 Moved Permanently'); +header('Location: ' . $_SERVER['REQUEST_URI'] . '/' . $pt); +exit; +} +$a = realpath(Extract_Phar::$temp . DIRECTORY_SEPARATOR . $pt); +if (!$a || strlen(dirname($a)) < strlen(Extract_Phar::$temp)) { +header('HTTP/1.0 404 Not Found'); +echo "<html>\n <head>\n <title>File Not Found<title>\n </head>\n <body>\n <h1>404 - File Not Found</h1>\n </body>\n</html>"; +exit; +} +$b = pathinfo($a); +if (!isset($b['extension'])) { +header('Content-Type: text/plain'); +header('Content-Length: ' . filesize($a)); +readfile($a); +exit; +} +if (isset($mimes[$b['extension']])) { +if ($mimes[$b['extension']] === 1) { +include $a; +exit; +} +if ($mimes[$b['extension']] === 2) { +highlight_file($a); +exit; +} +header('Content-Type: ' .$mimes[$b['extension']]); +header('Content-Length: ' . filesize($a)); +readfile($a); +exit; +} +} + +class Extract_Phar +{ +static $temp; +static $origdir; +const GZ = 0x1000; +const BZ2 = 0x2000; +const MASK = 0x3000; +const START = 'index.php'; +const LEN = 6643; + +static function go($return = false) +{ +$fp = fopen(__FILE__, 'rb'); +fseek($fp, self::LEN); +$L = unpack('V', $a = fread($fp, 4)); +$m = ''; + +do { +$read = 8192; +if ($L[1] - strlen($m) < 8192) { +$read = $L[1] - strlen($m); +} +$last = fread($fp, $read); +$m .= $last; +} while (strlen($last) && strlen($m) < $L[1]); + +if (strlen($m) < $L[1]) { +die('ERROR: manifest length read was "' . +strlen($m) .'" should be "' . +$L[1] . '"'); +} + +$info = self::_unpack($m); +$f = $info['c']; + +if ($f & self::GZ) { +if (!function_exists('gzinflate')) { +die('Error: zlib extension is not enabled -' . +' gzinflate() function needed for zlib-compressed .phars'); +} +} + +if ($f & self::BZ2) { +if (!function_exists('bzdecompress')) { +die('Error: bzip2 extension is not enabled -' . +' bzdecompress() function needed for bz2-compressed .phars'); +} +} + +$temp = self::tmpdir(); + +if (!$temp || !is_writable($temp)) { +$sessionpath = session_save_path(); +if (strpos ($sessionpath, ";") !== false) +$sessionpath = substr ($sessionpath, strpos ($sessionpath, ";")+1); +if (!file_exists($sessionpath) || !is_dir($sessionpath)) { +die('Could not locate temporary directory to extract phar'); +} +$temp = $sessionpath; +} + +$temp .= '/pharextract/'.basename(__FILE__, '.phar'); +self::$temp = $temp; +self::$origdir = getcwd(); +@mkdir($temp, 0777, true); +$temp = realpath($temp); + +if (!file_exists($temp . DIRECTORY_SEPARATOR . md5_file(__FILE__))) { +self::_removeTmpFiles($temp, getcwd()); +@mkdir($temp, 0777, true); +@file_put_contents($temp . '/' . md5_file(__FILE__), ''); + +foreach ($info['m'] as $path => $file) { +$a = !file_exists(dirname($temp . '/' . $path)); +@mkdir(dirname($temp . '/' . $path), 0777, true); +clearstatcache(); + +if ($path[strlen($path) - 1] == '/') { +@mkdir($temp . '/' . $path, 0777); +} else { +file_put_contents($temp . '/' . $path, self::extractFile($path, $file, $fp)); +@chmod($temp . '/' . $path, 0666); +} +} +} + +chdir($temp); + +if (!$return) { +include self::START; +} +} + +static function tmpdir() +{ +if (strpos(PHP_OS, 'WIN') !== false) { +if ($var = getenv('TMP') ? getenv('TMP') : getenv('TEMP')) { +return $var; +} +if (is_dir('/temp') || mkdir('/temp')) { +return realpath('/temp'); +} +return false; +} +if ($var = getenv('TMPDIR')) { +return $var; +} +return realpath('/tmp'); +} + +static function _unpack($m) +{ +$info = unpack('V', substr($m, 0, 4)); + $l = unpack('V', substr($m, 10, 4)); +$m = substr($m, 14 + $l[1]); +$s = unpack('V', substr($m, 0, 4)); +$o = 0; +$start = 4 + $s[1]; +$ret['c'] = 0; + +for ($i = 0; $i < $info[1]; $i++) { + $len = unpack('V', substr($m, $start, 4)); +$start += 4; + $savepath = substr($m, $start, $len[1]); +$start += $len[1]; + $ret['m'][$savepath] = array_values(unpack('Va/Vb/Vc/Vd/Ve/Vf', substr($m, $start, 24))); +$ret['m'][$savepath][3] = sprintf('%u', $ret['m'][$savepath][3] +& 0xffffffff); +$ret['m'][$savepath][7] = $o; +$o += $ret['m'][$savepath][2]; +$start += 24 + $ret['m'][$savepath][5]; +$ret['c'] |= $ret['m'][$savepath][4] & self::MASK; +} +return $ret; +} + +static function extractFile($path, $entry, $fp) +{ +$data = ''; +$c = $entry[2]; + +while ($c) { +if ($c < 8192) { +$data .= @fread($fp, $c); +$c = 0; +} else { +$c -= 8192; +$data .= @fread($fp, 8192); +} +} + +if ($entry[4] & self::GZ) { +$data = gzinflate($data); +} elseif ($entry[4] & self::BZ2) { +$data = bzdecompress($data); +} + +if (strlen($data) != $entry[0]) { +die("Invalid internal .phar file (size error " . strlen($data) . " != " . +$stat[7] . ")"); +} + +if ($entry[3] != sprintf("%u", crc32($data) & 0xffffffff)) { +die("Invalid internal .phar file (checksum error)"); +} + +return $data; +} + +static function _removeTmpFiles($temp, $origdir) +{ +chdir($temp); + +foreach (glob('*') as $f) { +if (file_exists($f)) { +is_dir($f) ? @rmdir($f) : @unlink($f); +if (file_exists($f) && is_dir($f)) { +self::_removeTmpFiles($f, getcwd()); +} +} +} + +@rmdir($temp); +clearstatcache(); +chdir($origdir); +} +} + +Extract_Phar::go(); +__HALT_COMPILER(); ?>7������������������ ���index.php����8!�[����u��������<?php +/** + * @file + * This test file is used to test Drupal's phar stream wrapper functionality. + * + * @see \Drupal\KernelTests\Core\File\PharWrapperTest + */ + +echo 'Hello, world!'; +�1qV�5�['�y� R�C�A���GBMB \ No newline at end of file diff --git a/web/core/modules/simpletest/simpletest.module b/web/core/modules/simpletest/simpletest.module index 0814d882d7101ed22a46130614e71bb4f3b35f0a..35fdd92cc19d1e4fb67ad894ca593cfcf7c37347 100644 --- a/web/core/modules/simpletest/simpletest.module +++ b/web/core/modules/simpletest/simpletest.module @@ -855,6 +855,7 @@ function simpletest_phpunit_testcase_to_row($test_id, \SimpleXMLElement $testcas $attributes = $testcase->attributes(); + $function = $attributes->class . '->' . $attributes->name . '()'; $record = [ 'test_id' => $test_id, 'test_class' => (string) $attributes->class, @@ -862,9 +863,11 @@ function simpletest_phpunit_testcase_to_row($test_id, \SimpleXMLElement $testcas 'message' => $message, // @todo: Check on the proper values for this. 'message_group' => 'Other', - 'function' => $attributes->class . '->' . $attributes->name . '()', + 'function' => $function, 'line' => $attributes->line ?: 0, - 'file' => $attributes->file, + // There are situations when the file will not be present because a PHPUnit + // @requires has caused a test to be skipped. + 'file' => $attributes->file ?: $function, ]; return $record; } diff --git a/web/core/modules/simpletest/src/TestBase.php b/web/core/modules/simpletest/src/TestBase.php index 12a061fd00e3f6772497856a8fb7d12b602edb11..1c7982f07e740b90f504dd783bb6232d107e4b62 100644 --- a/web/core/modules/simpletest/src/TestBase.php +++ b/web/core/modules/simpletest/src/TestBase.php @@ -28,7 +28,7 @@ abstract class TestBase { use TestSetupTrait; use RandomGeneratorTrait; use GeneratePermutationsTrait; - // For backwards compatibility switch the visbility of the methods to public. + // For backwards compatibility switch the visibility of the methods to public. use ConfigTestTrait { configImporter as public; copyConfig as public; @@ -51,7 +51,7 @@ abstract class TestBase { /** * Current results of this test case. * - * @var Array + * @var array */ public $results = [ '#pass' => 0, @@ -63,7 +63,7 @@ abstract class TestBase { /** * Assertions thrown in that test case. * - * @var Array + * @var array */ protected $assertions = []; diff --git a/web/core/modules/simpletest/src/Tests/InstallationProfileModuleTestsTest.php b/web/core/modules/simpletest/src/Tests/InstallationProfileModuleTestsTest.php index 7a7a0367afdd3c36312684ff5fae6031fe62119c..113748f18d5ec2bb0c4fedb337c83cceebb2b29f 100644 --- a/web/core/modules/simpletest/src/Tests/InstallationProfileModuleTestsTest.php +++ b/web/core/modules/simpletest/src/Tests/InstallationProfileModuleTestsTest.php @@ -19,7 +19,7 @@ class InstallationProfileModuleTestsTest extends WebTestBase { public static $modules = ['simpletest']; /** - * An administrative user with permission to adminsiter unit tests. + * An administrative user with permission to administer unit tests. * * @var \Drupal\user\UserInterface */ diff --git a/web/core/modules/simpletest/src/Tests/SimpleTestErrorCollectorTest.php b/web/core/modules/simpletest/src/Tests/SimpleTestErrorCollectorTest.php index b401fc999425319335aedf8c2bdd91791dfef97d..61bd5432b4dbbf9952a206ff9e6d1afe5b4f65e8 100644 --- a/web/core/modules/simpletest/src/Tests/SimpleTestErrorCollectorTest.php +++ b/web/core/modules/simpletest/src/Tests/SimpleTestErrorCollectorTest.php @@ -24,7 +24,7 @@ class SimpleTestErrorCollectorTest extends WebTestBase { * Errors are intercepted by the overridden implementation * of Drupal\simpletest\WebTestBase::error() below. * - * @var Array + * @var array */ protected $collectedErrors = []; diff --git a/web/core/modules/statistics/src/Tests/Views/IntegrationTest.php b/web/core/modules/statistics/tests/src/Functional/Views/IntegrationTest.php similarity index 95% rename from web/core/modules/statistics/src/Tests/Views/IntegrationTest.php rename to web/core/modules/statistics/tests/src/Functional/Views/IntegrationTest.php index 740ecf5e53f3abf80040c0ec9da21942bff687bf..56e18eefad4bbef28667e4435d12ed248d05ceca 100644 --- a/web/core/modules/statistics/src/Tests/Views/IntegrationTest.php +++ b/web/core/modules/statistics/tests/src/Functional/Views/IntegrationTest.php @@ -1,8 +1,8 @@ <?php -namespace Drupal\statistics\Tests\Views; +namespace Drupal\Tests\statistics\Functional\Views; -use Drupal\views\Tests\ViewTestBase; +use Drupal\Tests\views\Functional\ViewTestBase; use Drupal\views\Tests\ViewTestData; /** @@ -74,7 +74,7 @@ public function testNodeCounterIntegration() { // @see \Drupal\statistics\Tests\StatisticsLoggingTest::testLogging(). global $base_url; $stats_path = $base_url . '/' . drupal_get_path('module', 'statistics') . '/statistics.php'; - $client = \Drupal::httpClient(); + $client = $this->getHttpClient(); $client->post($stats_path, ['form_params' => ['nid' => $this->node->id()]]); $this->drupalGet('test_statistics_integration'); diff --git a/web/core/modules/system/src/Form/ModulesListForm.php b/web/core/modules/system/src/Form/ModulesListForm.php index 3c6f2a8991451fb028b7dc5dc5234076ab9505d0..ef0b240ecffc593f246b486cb41fa578af50ff19 100644 --- a/web/core/modules/system/src/Form/ModulesListForm.php +++ b/web/core/modules/system/src/Form/ModulesListForm.php @@ -7,6 +7,7 @@ use Drupal\Core\Config\UnmetDependenciesException; use Drupal\Core\Access\AccessManagerInterface; use Drupal\Core\Extension\Extension; +use Drupal\Core\Extension\InfoParserException; use Drupal\Core\Extension\ModuleHandlerInterface; use Drupal\Core\Extension\ModuleInstallerInterface; use Drupal\Core\Form\FormBase; @@ -143,8 +144,14 @@ public function buildForm(array $form, FormStateInterface $form_state) { ]; // Sort all modules by their names. - $modules = system_rebuild_module_data(); - uasort($modules, 'system_sort_modules_by_info_name'); + try { + $modules = system_rebuild_module_data(); + uasort($modules, 'system_sort_modules_by_info_name'); + } + catch (InfoParserException $e) { + $this->messenger()->addError($this->t('Modules could not be listed due to an error: %error', ['%error' => $e->getMessage()])); + $modules = []; + } // Iterate over each of the modules. $form['modules']['#tree'] = TRUE; diff --git a/web/core/modules/system/src/PathBasedBreadcrumbBuilder.php b/web/core/modules/system/src/PathBasedBreadcrumbBuilder.php index ebc5df0b756bf71f3570b9ca7a17369911aa83ce..261ae32a2491184b6aa2614d037fb4b0a686bf18 100644 --- a/web/core/modules/system/src/PathBasedBreadcrumbBuilder.php +++ b/web/core/modules/system/src/PathBasedBreadcrumbBuilder.php @@ -144,7 +144,7 @@ public function build(RouteMatchInterface $route_match) { // Add the url.path.parent cache context. This code ignores the last path // part so the result only depends on the path parents. - $breadcrumb->addCacheContexts(['url.path.parent']); + $breadcrumb->addCacheContexts(['url.path.parent', 'url.path.is_front']); // Do not display a breadcrumb on the frontpage. if ($this->pathMatcher->isFrontPage()) { diff --git a/web/core/modules/system/src/Tests/Ajax/CommandsTest.php b/web/core/modules/system/src/Tests/Ajax/CommandsTest.php deleted file mode 100644 index b91ac98271cae95c395cedd57eda662deb0198ec..0000000000000000000000000000000000000000 --- a/web/core/modules/system/src/Tests/Ajax/CommandsTest.php +++ /dev/null @@ -1,159 +0,0 @@ -<?php - -namespace Drupal\system\Tests\Ajax; - -use Drupal\Core\Ajax\AddCssCommand; -use Drupal\Core\Ajax\AfterCommand; -use Drupal\Core\Ajax\AjaxResponse; -use Drupal\Core\Ajax\AlertCommand; -use Drupal\Core\Ajax\AppendCommand; -use Drupal\Core\Ajax\BeforeCommand; -use Drupal\Core\Ajax\ChangedCommand; -use Drupal\Core\Ajax\CssCommand; -use Drupal\Core\Ajax\DataCommand; -use Drupal\Core\Ajax\HtmlCommand; -use Drupal\Core\Ajax\InvokeCommand; -use Drupal\Core\Ajax\InsertCommand; -use Drupal\Core\Ajax\PrependCommand; -use Drupal\Core\Ajax\RemoveCommand; -use Drupal\Core\Ajax\RestripeCommand; -use Drupal\Core\Ajax\SettingsCommand; -use Drupal\Core\EventSubscriber\AjaxResponseSubscriber; -use Symfony\Component\HttpFoundation\Request; -use Symfony\Component\HttpKernel\Event\FilterResponseEvent; -use Symfony\Component\HttpKernel\HttpKernelInterface; - -/** - * Performs tests on AJAX framework commands. - * - * @group Ajax - */ -class CommandsTest extends AjaxTestBase { - - /** - * Tests the various Ajax Commands. - */ - public function testAjaxCommands() { - $form_path = 'ajax_forms_test_ajax_commands_form'; - $web_user = $this->drupalCreateUser(['access content']); - $this->drupalLogin($web_user); - - $edit = []; - - // Tests the 'add_css' command. - $commands = $this->drupalPostAjaxForm($form_path, $edit, ['op' => t("AJAX 'add_css' command")]); - $expected = new AddCssCommand('my/file.css'); - $this->assertCommand($commands, $expected->render(), "'add_css' AJAX command issued with correct data."); - - // Tests the 'after' command. - $commands = $this->drupalPostAjaxForm($form_path, $edit, ['op' => t("AJAX 'After': Click to put something after the div")]); - $expected = new AfterCommand('#after_div', 'This will be placed after'); - $this->assertCommand($commands, $expected->render(), "'after' AJAX command issued with correct data."); - - // Tests the 'alert' command. - $commands = $this->drupalPostAjaxForm($form_path, $edit, ['op' => t("AJAX 'Alert': Click to alert")]); - $expected = new AlertCommand(t('Alert')); - $this->assertCommand($commands, $expected->render(), "'alert' AJAX Command issued with correct text."); - - // Tests the 'append' command. - $commands = $this->drupalPostAjaxForm($form_path, $edit, ['op' => t("AJAX 'Append': Click to append something")]); - $expected = new AppendCommand('#append_div', 'Appended text'); - $this->assertCommand($commands, $expected->render(), "'append' AJAX command issued with correct data."); - - // Tests the 'before' command. - $commands = $this->drupalPostAjaxForm($form_path, $edit, ['op' => t("AJAX 'before': Click to put something before the div")]); - $expected = new BeforeCommand('#before_div', 'Before text'); - $this->assertCommand($commands, $expected->render(), "'before' AJAX command issued with correct data."); - - // Tests the 'changed' command. - $commands = $this->drupalPostAjaxForm($form_path, $edit, ['op' => t("AJAX changed: Click to mark div changed.")]); - $expected = new ChangedCommand('#changed_div'); - $this->assertCommand($commands, $expected->render(), "'changed' AJAX command issued with correct selector."); - - // Tests the 'changed' command using the second argument. - $commands = $this->drupalPostAjaxForm($form_path, $edit, ['op' => t("AJAX changed: Click to mark div changed with asterisk.")]); - $expected = new ChangedCommand('#changed_div', '#changed_div_mark_this'); - $this->assertCommand($commands, $expected->render(), "'changed' AJAX command (with asterisk) issued with correct selector."); - - // Tests the 'css' command. - $commands = $this->drupalPostAjaxForm($form_path, $edit, ['op' => t("Set the '#box' div to be blue.")]); - $expected = new CssCommand('#css_div', ['background-color' => 'blue']); - $this->assertCommand($commands, $expected->render(), "'css' AJAX command issued with correct selector."); - - // Tests the 'data' command. - $commands = $this->drupalPostAjaxForm($form_path, $edit, ['op' => t("AJAX data command: Issue command.")]); - $expected = new DataCommand('#data_div', 'testkey', 'testvalue'); - $this->assertCommand($commands, $expected->render(), "'data' AJAX command issued with correct key and value."); - - // Tests the 'html' command. - $commands = $this->drupalPostAjaxForm($form_path, $edit, ['op' => t("AJAX html: Replace the HTML in a selector.")]); - $expected = new HtmlCommand('#html_div', 'replacement text'); - $this->assertCommand($commands, $expected->render(), "'html' AJAX command issued with correct data."); - - // Tests the 'insert' command. - $commands = $this->drupalPostAjaxForm($form_path, $edit, ['op' => t("AJAX insert: Let client insert based on #ajax['method'].")]); - $expected = new InsertCommand('#insert_div', 'insert replacement text'); - $this->assertCommand($commands, $expected->render(), "'insert' AJAX command issued with correct data."); - - // Tests the 'invoke' command. - $commands = $this->drupalPostAjaxForm($form_path, $edit, ['op' => t("AJAX invoke command: Invoke addClass() method.")]); - $expected = new InvokeCommand('#invoke_div', 'addClass', ['error']); - $this->assertCommand($commands, $expected->render(), "'invoke' AJAX command issued with correct method and argument."); - - // Tests the 'prepend' command. - $commands = $this->drupalPostAjaxForm($form_path, $edit, ['op' => t("AJAX 'prepend': Click to prepend something")]); - $expected = new PrependCommand('#prepend_div', 'prepended text'); - $this->assertCommand($commands, $expected->render(), "'prepend' AJAX command issued with correct data."); - - // Tests the 'remove' command. - $commands = $this->drupalPostAjaxForm($form_path, $edit, ['op' => t("AJAX 'remove': Click to remove text")]); - $expected = new RemoveCommand('#remove_text'); - $this->assertCommand($commands, $expected->render(), "'remove' AJAX command issued with correct command and selector."); - - // Tests the 'restripe' command. - $commands = $this->drupalPostAjaxForm($form_path, $edit, ['op' => t("AJAX 'restripe' command")]); - $expected = new RestripeCommand('#restripe_table'); - $this->assertCommand($commands, $expected->render(), "'restripe' AJAX command issued with correct selector."); - - // Tests the 'settings' command. - $commands = $this->drupalPostAjaxForm($form_path, $edit, ['op' => t("AJAX 'settings' command")]); - $expected = new SettingsCommand(['ajax_forms_test' => ['foo' => 42]]); - $this->assertCommand($commands, $expected->render(), "'settings' AJAX command issued with correct data."); - } - - /** - * Regression test: Settings command exists regardless of JS aggregation. - */ - public function testAttachedSettings() { - $assert = function ($message) { - $response = new AjaxResponse(); - $response->setAttachments([ - 'library' => ['core/drupalSettings'], - 'drupalSettings' => ['foo' => 'bar'], - ]); - - $ajax_response_attachments_processor = \Drupal::service('ajax_response.attachments_processor'); - $subscriber = new AjaxResponseSubscriber($ajax_response_attachments_processor); - $event = new FilterResponseEvent( - \Drupal::service('http_kernel'), - new Request(), - HttpKernelInterface::MASTER_REQUEST, - $response - ); - $subscriber->onResponse($event); - $expected = [ - 'command' => 'settings', - ]; - $this->assertCommand($response->getCommands(), $expected, $message); - }; - - $config = $this->config('system.performance'); - - $config->set('js.preprocess', FALSE)->save(); - $assert('Settings command exists when JS aggregation is disabled.'); - - $config->set('js.preprocess', TRUE)->save(); - $assert('Settings command exists when JS aggregation is enabled.'); - } - -} diff --git a/web/core/modules/system/src/Tests/Ajax/DialogTest.php b/web/core/modules/system/src/Tests/Ajax/DialogTest.php deleted file mode 100644 index 76ab6fb160f5bc9b1c97cdf5b82fff61a14896fe..0000000000000000000000000000000000000000 --- a/web/core/modules/system/src/Tests/Ajax/DialogTest.php +++ /dev/null @@ -1,216 +0,0 @@ -<?php - -namespace Drupal\system\Tests\Ajax; - -use Drupal\ajax_test\Controller\AjaxTestController; -use Drupal\Core\EventSubscriber\MainContentViewSubscriber; -use Drupal\Core\Form\FormBuilderInterface; -use Drupal\Core\Url; - -/** - * Performs tests on opening and manipulating dialogs via AJAX commands. - * - * @group Ajax - */ -class DialogTest extends AjaxTestBase { - - /** - * Modules to enable. - * - * @var array - */ - public static $modules = ['ajax_test', 'ajax_forms_test', 'contact']; - - /** - * Test sending non-JS and AJAX requests to open and manipulate modals. - */ - public function testDialog() { - $this->drupalLogin($this->drupalCreateUser(['administer contact forms'])); - // Ensure the elements render without notices or exceptions. - $this->drupalGet('ajax-test/dialog'); - - // Set up variables for this test. - $dialog_renderable = AjaxTestController::dialogContents(); - $dialog_contents = \Drupal::service('renderer')->renderRoot($dialog_renderable); - $modal_expected_response = [ - 'command' => 'openDialog', - 'selector' => '#drupal-modal', - 'settings' => NULL, - 'data' => $dialog_contents, - 'dialogOptions' => [ - 'modal' => TRUE, - 'title' => 'AJAX Dialog & contents', - ], - ]; - $form_expected_response = [ - 'command' => 'openDialog', - 'selector' => '#drupal-modal', - 'settings' => NULL, - 'dialogOptions' => [ - 'modal' => TRUE, - 'title' => 'Ajax Form contents', - ], - ]; - $entity_form_expected_response = [ - 'command' => 'openDialog', - 'selector' => '#drupal-modal', - 'settings' => NULL, - 'dialogOptions' => [ - 'modal' => TRUE, - 'title' => 'Add contact form', - ], - ]; - $normal_expected_response = [ - 'command' => 'openDialog', - 'selector' => '#ajax-test-dialog-wrapper-1', - 'settings' => NULL, - 'data' => $dialog_contents, - 'dialogOptions' => [ - 'modal' => FALSE, - 'title' => 'AJAX Dialog & contents', - ], - ]; - $no_target_expected_response = [ - 'command' => 'openDialog', - 'selector' => '#drupal-dialog-ajax-testdialog-contents', - 'settings' => NULL, - 'data' => $dialog_contents, - 'dialogOptions' => [ - 'modal' => FALSE, - 'title' => 'AJAX Dialog & contents', - ], - ]; - $close_expected_response = [ - 'command' => 'closeDialog', - 'selector' => '#ajax-test-dialog-wrapper-1', - 'persist' => FALSE, - ]; - - // Check that requesting a modal dialog without JS goes to a page. - $this->drupalGet('ajax-test/dialog-contents'); - $this->assertRaw($dialog_contents, 'Non-JS modal dialog page present.'); - - // Check that requesting a modal dialog with XMLHttpRequest goes to a page. - $this->drupalGetXHR('ajax-test/dialog-contents'); - $this->assertRaw($dialog_contents, 'Modal dialog page on XMLHttpRequest present.'); - - // Emulate going to the JS version of the page and check the JSON response. - $ajax_result = $this->drupalGetAjax('ajax-test/dialog-contents', ['query' => [MainContentViewSubscriber::WRAPPER_FORMAT => 'drupal_modal']]); - $this->assertEqual($modal_expected_response, $ajax_result[3], 'Modal dialog JSON response matches.'); - // Test the HTML escaping of & character. - $this->assertEqual($ajax_result[3]['dialogOptions']['title'], 'AJAX Dialog & contents'); - $this->assertNotEqual($ajax_result[3]['dialogOptions']['title'], 'AJAX Dialog & contents'); - - // Check that requesting a "normal" dialog without JS goes to a page. - $this->drupalGet('ajax-test/dialog-contents'); - $this->assertRaw($dialog_contents, 'Non-JS normal dialog page present.'); - - // Emulate going to the JS version of the page and check the JSON response. - // This needs to use WebTestBase::drupalPostAjaxForm() so that the correct - // dialog options are sent. - $ajax_result = $this->drupalPostAjaxForm('ajax-test/dialog', [ - // We have to mock a form element to make drupalPost submit from a link. - 'textfield' => 'test', - ], [], 'ajax-test/dialog-contents', ['query' => [MainContentViewSubscriber::WRAPPER_FORMAT => 'drupal_dialog']], [], NULL, [ - 'submit' => [ - 'dialogOptions[target]' => 'ajax-test-dialog-wrapper-1', - ], - ]); - $this->assertEqual($normal_expected_response, $ajax_result[3], 'Normal dialog JSON response matches.'); - - // Emulate going to the JS version of the page and check the JSON response. - // This needs to use WebTestBase::drupalPostAjaxForm() so that the correct - // dialog options are sent. - $ajax_result = $this->drupalPostAjaxForm('ajax-test/dialog', [ - // We have to mock a form element to make drupalPost submit from a link. - 'textfield' => 'test', - ], [], 'ajax-test/dialog-contents', ['query' => [MainContentViewSubscriber::WRAPPER_FORMAT => 'drupal_dialog']], [], NULL, [ - // Don't send a target. - 'submit' => [], - ]); - // Make sure the selector ID starts with the right string. - $this->assert(strpos($ajax_result[3]['selector'], $no_target_expected_response['selector']) === 0, 'Selector starts with right string.'); - unset($ajax_result[3]['selector']); - unset($no_target_expected_response['selector']); - $this->assertEqual($no_target_expected_response, $ajax_result[3], 'Normal dialog with no target JSON response matches.'); - - // Emulate closing the dialog via an AJAX request. There is no non-JS - // version of this test. - $ajax_result = $this->drupalGetAjax('ajax-test/dialog-close'); - $this->assertEqual($close_expected_response, $ajax_result[0], 'Close dialog JSON response matches.'); - - // Test submitting via a POST request through the button for modals. This - // approach more accurately reflects the real responses by Drupal because - // all of the necessary page variables are emulated. - $ajax_result = $this->drupalPostAjaxForm('ajax-test/dialog', [], 'button1'); - - // Check that CSS and JavaScript are "added" to the page dynamically. - $this->assertTrue(in_array('core/drupal.dialog.ajax', explode(',', $ajax_result[0]['settings']['ajaxPageState']['libraries'])), 'core/drupal.dialog.ajax library is added to the page.'); - $dialog_css_exists = strpos($ajax_result[1]['data'], 'dialog.css') !== FALSE; - $this->assertTrue($dialog_css_exists, 'jQuery UI dialog CSS added to the page.'); - $dialog_js_exists = strpos($ajax_result[2]['data'], 'dialog-min.js') !== FALSE; - $this->assertTrue($dialog_js_exists, 'jQuery UI dialog JS added to the page.'); - $dialog_js_exists = strpos($ajax_result[2]['data'], 'dialog.ajax.js') !== FALSE; - $this->assertTrue($dialog_js_exists, 'Drupal dialog JS added to the page.'); - - // Check that the response matches the expected value. - $this->assertEqual($modal_expected_response, $ajax_result[4], 'POST request modal dialog JSON response matches.'); - // Test the HTML escaping of & character. - $this->assertNotEqual($ajax_result[4]['dialogOptions']['title'], 'AJAX Dialog & contents'); - - // Abbreviated test for "normal" dialogs, testing only the difference. - $ajax_result = $this->drupalPostAjaxForm('ajax-test/dialog', [], 'button2'); - $this->assertEqual($normal_expected_response, $ajax_result[4], 'POST request normal dialog JSON response matches.'); - - // Check that requesting a form dialog without JS goes to a page. - $this->drupalGet('ajax-test/dialog-form'); - // Check we get a chunk of the code, we can't test the whole form as form - // build id and token with be different. - $form = $this->xpath("//form[@id='ajax-test-form']"); - $this->assertTrue(!empty($form), 'Non-JS form page present.'); - - // Emulate going to the JS version of the form and check the JSON response. - $ajax_result = $this->drupalGetAjax('ajax-test/dialog-form', ['query' => [MainContentViewSubscriber::WRAPPER_FORMAT => 'drupal_modal']]); - $expected_ajax_settings = [ - 'edit-preview' => [ - 'callback' => '::preview', - 'event' => 'click', - 'url' => Url::fromRoute('ajax_test.dialog_form', [], [ - 'query' => [ - MainContentViewSubscriber::WRAPPER_FORMAT => 'drupal_modal', - FormBuilderInterface::AJAX_FORM_REQUEST => TRUE, - ], - ])->toString(), - 'dialogType' => 'ajax', - 'submit' => [ - '_triggering_element_name' => 'op', - '_triggering_element_value' => 'Preview', - ], - ], - ]; - $this->assertEqual($expected_ajax_settings, $ajax_result[0]['settings']['ajax']); - $this->setRawContent($ajax_result[3]['data']); - // Remove the data, the form build id and token will never match. - unset($ajax_result[3]['data']); - $form = $this->xpath("//form[@id='ajax-test-form']"); - $this->assertTrue(!empty($form), 'Modal dialog JSON contains form.'); - $this->assertEqual($form_expected_response, $ajax_result[3]); - - // Check that requesting an entity form dialog without JS goes to a page. - $this->drupalGet('admin/structure/contact/add'); - // Check we get a chunk of the code, we can't test the whole form as form - // build id and token with be different. - $form = $this->xpath("//form[@id='contact-form-add-form']"); - $this->assertTrue(!empty($form), 'Non-JS entity form page present.'); - - // Emulate going to the JS version of the form and check the JSON response. - $ajax_result = $this->drupalGetAjax('admin/structure/contact/add', ['query' => [MainContentViewSubscriber::WRAPPER_FORMAT => 'drupal_modal']]); - $this->setRawContent($ajax_result[3]['data']); - // Remove the data, the form build id and token will never match. - unset($ajax_result[3]['data']); - $form = $this->xpath("//form[@id='contact-form-add-form']"); - $this->assertTrue(!empty($form), 'Modal dialog JSON contains entity form.'); - $this->assertEqual($entity_form_expected_response, $ajax_result[3]); - } - -} diff --git a/web/core/modules/system/src/Tests/Ajax/ElementValidationTest.php b/web/core/modules/system/src/Tests/Ajax/ElementValidationTest.php deleted file mode 100644 index 169a38900be357440e3135c325ec551aafa689d3..0000000000000000000000000000000000000000 --- a/web/core/modules/system/src/Tests/Ajax/ElementValidationTest.php +++ /dev/null @@ -1,39 +0,0 @@ -<?php - -namespace Drupal\system\Tests\Ajax; - -/** - * Various tests of AJAX behavior. - * - * @group Ajax - */ -class ElementValidationTest extends AjaxTestBase { - - /** - * Tries to post an Ajax change to a form that has a validated element. - * - * The drivertext field is Ajax-enabled. An additional field is not, but - * is set to be a required field. In this test the required field is not - * filled in, and we want to see if the activation of the "drivertext" - * Ajax-enabled field fails due to the required field being empty. - */ - public function testAjaxElementValidation() { - $edit = ['drivertext' => t('some dumb text')]; - - // Post with 'drivertext' as the triggering element. - $this->drupalPostAjaxForm('ajax_validation_test', $edit, 'drivertext'); - // Look for a validation failure in the resultant JSON. - $this->assertNoText(t('Error message'), 'No error message in resultant JSON'); - $this->assertText('ajax_forms_test_validation_form_callback invoked', 'The correct callback was invoked'); - - $this->drupalGet('ajax_validation_test'); - $edit = ['drivernumber' => 12345]; - - // Post with 'drivernumber' as the triggering element. - $this->drupalPostAjaxForm('ajax_validation_test', $edit, 'drivernumber'); - // Look for a validation failure in the resultant JSON. - $this->assertNoText(t('Error message'), 'No error message in resultant JSON'); - $this->assertText('ajax_forms_test_validation_number_form_callback invoked', 'The correct callback was invoked'); - } - -} diff --git a/web/core/modules/system/src/Tests/Ajax/FormValuesTest.php b/web/core/modules/system/src/Tests/Ajax/FormValuesTest.php deleted file mode 100644 index 358db893388b4865766b30c09fc516904edebbbd..0000000000000000000000000000000000000000 --- a/web/core/modules/system/src/Tests/Ajax/FormValuesTest.php +++ /dev/null @@ -1,65 +0,0 @@ -<?php - -namespace Drupal\system\Tests\Ajax; - -use Drupal\Core\Ajax\DataCommand; - -/** - * Tests that form values are properly delivered to AJAX callbacks. - * - * @group Ajax - */ -class FormValuesTest extends AjaxTestBase { - - protected function setUp() { - parent::setUp(); - - $this->drupalLogin($this->drupalCreateUser(['access content'])); - } - - /** - * Submits forms with select and checkbox elements via Ajax. - */ - public function testSimpleAjaxFormValue() { - // Verify form values of a select element. - foreach (['red', 'green', 'blue'] as $item) { - $edit = [ - 'select' => $item, - ]; - $commands = $this->drupalPostAjaxForm('ajax_forms_test_get_form', $edit, 'select'); - $expected = new DataCommand('#ajax_selected_color', 'form_state_value_select', $item); - $this->assertCommand($commands, $expected->render(), 'Verification of AJAX form values from a selectbox issued with a correct value.'); - } - - // Verify form values of a checkbox element. - foreach ([FALSE, TRUE] as $item) { - $edit = [ - 'checkbox' => $item, - ]; - $commands = $this->drupalPostAjaxForm('ajax_forms_test_get_form', $edit, 'checkbox'); - $expected = new DataCommand('#ajax_checkbox_value', 'form_state_value_select', (int) $item); - $this->assertCommand($commands, $expected->render(), 'Verification of AJAX form values from a checkbox issued with a correct value.'); - } - - // Verify that AJAX elements with invalid callbacks return error code 500. - // Ensure the test error log is empty before these tests. - $this->assertNoErrorsLogged(); - // We don't need to check for the X-Drupal-Ajax-Token header with these - // invalid requests. - $this->assertAjaxHeader = FALSE; - foreach (['null', 'empty', 'nonexistent'] as $key) { - $element_name = 'select_' . $key . '_callback'; - $edit = [ - $element_name => 'red', - ]; - $commands = $this->drupalPostAjaxForm('ajax_forms_test_get_form', $edit, $element_name); - $this->assertResponse(500); - } - // Switch this back to the default. - $this->assertAjaxHeader = TRUE; - // The exceptions are expected. Do not interpret them as a test failure. - // Not using File API; a potential error must trigger a PHP warning. - unlink(\Drupal::root() . '/' . $this->siteDirectory . '/error.log'); - } - -} diff --git a/web/core/modules/system/src/Tests/Ajax/FrameworkTest.php b/web/core/modules/system/src/Tests/Ajax/FrameworkTest.php deleted file mode 100644 index 507493b7d09b5d5069c794fcc6deb2eda9b22344..0000000000000000000000000000000000000000 --- a/web/core/modules/system/src/Tests/Ajax/FrameworkTest.php +++ /dev/null @@ -1,216 +0,0 @@ -<?php - -namespace Drupal\system\Tests\Ajax; - -use Drupal\Core\Ajax\AddCssCommand; -use Drupal\Core\Ajax\AlertCommand; -use Drupal\Core\Ajax\AppendCommand; -use Drupal\Core\Ajax\HtmlCommand; -use Drupal\Core\Ajax\PrependCommand; -use Drupal\Core\Ajax\SettingsCommand; -use Drupal\Core\Asset\AttachedAssets; - -/** - * Performs tests on AJAX framework functions. - * - * @group Ajax - */ -class FrameworkTest extends AjaxTestBase { - - /** - * Verifies the Ajax rendering of a command in the settings. - */ - public function testAJAXRender() { - // Verify that settings command is generated if JavaScript settings exist. - $commands = $this->drupalGetAjax('ajax-test/render'); - $expected = new SettingsCommand(['ajax' => 'test'], TRUE); - $this->assertCommand($commands, $expected->render(), 'JavaScript settings command is present.'); - } - - /** - * Tests AjaxResponse::prepare() AJAX commands ordering. - */ - public function testOrder() { - $expected_commands = []; - - // Expected commands, in a very specific order. - $asset_resolver = \Drupal::service('asset.resolver'); - $css_collection_renderer = \Drupal::service('asset.css.collection_renderer'); - $js_collection_renderer = \Drupal::service('asset.js.collection_renderer'); - $renderer = \Drupal::service('renderer'); - $expected_commands[0] = new SettingsCommand(['ajax' => 'test'], TRUE); - $build['#attached']['library'][] = 'ajax_test/order-css-command'; - $assets = AttachedAssets::createFromRenderArray($build); - $css_render_array = $css_collection_renderer->render($asset_resolver->getCssAssets($assets, FALSE)); - $expected_commands[1] = new AddCssCommand($renderer->renderRoot($css_render_array)); - $build['#attached']['library'][] = 'ajax_test/order-header-js-command'; - $build['#attached']['library'][] = 'ajax_test/order-footer-js-command'; - $assets = AttachedAssets::createFromRenderArray($build); - list($js_assets_header, $js_assets_footer) = $asset_resolver->getJsAssets($assets, FALSE); - $js_header_render_array = $js_collection_renderer->render($js_assets_header); - $js_footer_render_array = $js_collection_renderer->render($js_assets_footer); - $expected_commands[2] = new PrependCommand('head', $js_header_render_array); - $expected_commands[3] = new AppendCommand('body', $js_footer_render_array); - $expected_commands[4] = new HtmlCommand('body', 'Hello, world!'); - - // Load any page with at least one CSS file, at least one JavaScript file - // and at least one #ajax-powered element. The latter is an assumption of - // drupalPostAjaxForm(), the two former are assumptions of the Ajax - // renderer. - // @todo refactor AJAX Framework + tests to make less assumptions. - $this->drupalGet('ajax_forms_test_lazy_load_form'); - - // Verify AJAX command order — this should always be the order: - // 1. JavaScript settings - // 2. CSS files - // 3. JavaScript files in the header - // 4. JavaScript files in the footer - // 5. Any other AJAX commands, in whatever order they were added. - $commands = $this->drupalPostAjaxForm(NULL, [], NULL, 'ajax-test/order', [], [], NULL, []); - $this->assertCommand(array_slice($commands, 0, 1), $expected_commands[0]->render(), 'Settings command is first.'); - $this->assertCommand(array_slice($commands, 1, 1), $expected_commands[1]->render(), 'CSS command is second (and CSS files are ordered correctly).'); - $this->assertCommand(array_slice($commands, 2, 1), $expected_commands[2]->render(), 'Header JS command is third.'); - $this->assertCommand(array_slice($commands, 3, 1), $expected_commands[3]->render(), 'Footer JS command is fourth.'); - $this->assertCommand(array_slice($commands, 4, 1), $expected_commands[4]->render(), 'HTML command is fifth.'); - } - - /** - * Tests the behavior of an error alert command. - */ - public function testAJAXRenderError() { - // Verify custom error message. - $edit = [ - 'message' => 'Custom error message.', - ]; - $commands = $this->drupalGetAjax('ajax-test/render-error', ['query' => $edit]); - $expected = new AlertCommand($edit['message']); - $this->assertCommand($commands, $expected->render(), 'Custom error message is output.'); - } - - /** - * Tests that new JavaScript and CSS files are lazy-loaded on an AJAX request. - */ - public function testLazyLoad() { - $asset_resolver = \Drupal::service('asset.resolver'); - $css_collection_renderer = \Drupal::service('asset.css.collection_renderer'); - $js_collection_renderer = \Drupal::service('asset.js.collection_renderer'); - $renderer = \Drupal::service('renderer'); - - $expected = [ - 'setting_name' => 'ajax_forms_test_lazy_load_form_submit', - 'setting_value' => 'executed', - 'library_1' => 'system/admin', - 'library_2' => 'system/drupal.system', - ]; - - // Get the base page. - $this->drupalGet('ajax_forms_test_lazy_load_form'); - $original_settings = $this->getDrupalSettings(); - $original_libraries = explode(',', $original_settings['ajaxPageState']['libraries']); - - // Verify that the base page doesn't have the settings and files that are to - // be lazy loaded as part of the next requests. - $this->assertTrue(!isset($original_settings[$expected['setting_name']]), format_string('Page originally lacks the %setting, as expected.', ['%setting' => $expected['setting_name']])); - $this->assertTrue(!in_array($expected['library_1'], $original_libraries), format_string('Page originally lacks the %library library, as expected.', ['%library' => $expected['library_1']])); - $this->assertTrue(!in_array($expected['library_2'], $original_libraries), format_string('Page originally lacks the %library library, as expected.', ['%library' => $expected['library_2']])); - - // Calculate the expected CSS and JS. - $assets = new AttachedAssets(); - $assets->setLibraries([$expected['library_1']]) - ->setAlreadyLoadedLibraries($original_libraries); - $css_render_array = $css_collection_renderer->render($asset_resolver->getCssAssets($assets, FALSE)); - $expected_css_html = $renderer->renderRoot($css_render_array); - - $assets->setLibraries([$expected['library_2']]) - ->setAlreadyLoadedLibraries($original_libraries); - $js_assets = $asset_resolver->getJsAssets($assets, FALSE)[1]; - unset($js_assets['drupalSettings']); - $js_render_array = $js_collection_renderer->render($js_assets); - $expected_js_html = $renderer->renderRoot($js_render_array); - - // Submit the AJAX request without triggering files getting added. - $commands = $this->drupalPostAjaxForm(NULL, ['add_files' => FALSE], ['op' => t('Submit')]); - $new_settings = $this->getDrupalSettings(); - $new_libraries = explode(',', $new_settings['ajaxPageState']['libraries']); - - // Verify the setting was not added when not expected. - $this->assertTrue(!isset($new_settings[$expected['setting_name']]), format_string('Page still lacks the %setting, as expected.', ['%setting' => $expected['setting_name']])); - $this->assertTrue(!in_array($expected['library_1'], $new_libraries), format_string('Page still lacks the %library library, as expected.', ['%library' => $expected['library_1']])); - $this->assertTrue(!in_array($expected['library_2'], $new_libraries), format_string('Page still lacks the %library library, as expected.', ['%library' => $expected['library_2']])); - // Verify a settings command does not add CSS or scripts to drupalSettings - // and no command inserts the corresponding tags on the page. - $found_settings_command = FALSE; - $found_markup_command = FALSE; - foreach ($commands as $command) { - if ($command['command'] == 'settings' && (array_key_exists('css', $command['settings']['ajaxPageState']) || array_key_exists('js', $command['settings']['ajaxPageState']))) { - $found_settings_command = TRUE; - } - if (isset($command['data']) && ($command['data'] == $expected_js_html || $command['data'] == $expected_css_html)) { - $found_markup_command = TRUE; - } - } - $this->assertFalse($found_settings_command, format_string('Page state still lacks the %library_1 and %library_2 libraries, as expected.', ['%library_1' => $expected['library_1'], '%library_2' => $expected['library_2']])); - $this->assertFalse($found_markup_command, format_string('Page still lacks the %library_1 and %library_2 libraries, as expected.', ['%library_1' => $expected['library_1'], '%library_2' => $expected['library_2']])); - - // Submit the AJAX request and trigger adding files. - $commands = $this->drupalPostAjaxForm(NULL, ['add_files' => TRUE], ['op' => t('Submit')]); - $new_settings = $this->getDrupalSettings(); - $new_libraries = explode(',', $new_settings['ajaxPageState']['libraries']); - - // Verify the expected setting was added, both to drupalSettings, and as - // the first AJAX command. - $this->assertIdentical($new_settings[$expected['setting_name']], $expected['setting_value'], format_string('Page now has the %setting.', ['%setting' => $expected['setting_name']])); - $expected_command = new SettingsCommand([$expected['setting_name'] => $expected['setting_value']], TRUE); - $this->assertCommand(array_slice($commands, 0, 1), $expected_command->render(), 'The settings command was first.'); - - // Verify the expected CSS file was added, both to drupalSettings, and as - // the second AJAX command for inclusion into the HTML. - $this->assertTrue(in_array($expected['library_1'], $new_libraries), format_string('Page state now has the %library library.', ['%library' => $expected['library_1']])); - $this->assertCommand(array_slice($commands, 1, 1), ['data' => $expected_css_html], format_string('Page now has the %library library.', ['%library' => $expected['library_1']])); - - // Verify the expected JS file was added, both to drupalSettings, and as - // the third AJAX command for inclusion into the HTML. By testing for an - // exact HTML string containing the SCRIPT tag, we also ensure that - // unexpected JavaScript code, such as a jQuery.extend() that would - // potentially clobber rather than properly merge settings, didn't - // accidentally get added. - $this->assertTrue(in_array($expected['library_2'], $new_libraries), format_string('Page state now has the %library library.', ['%library' => $expected['library_2']])); - $this->assertCommand(array_slice($commands, 2, 1), ['data' => $expected_js_html], format_string('Page now has the %library library.', ['%library' => $expected['library_2']])); - } - - /** - * Tests that drupalSettings.currentPath is not updated on AJAX requests. - */ - public function testCurrentPathChange() { - $commands = $this->drupalPostAjaxForm('ajax_forms_test_lazy_load_form', ['add_files' => FALSE], ['op' => t('Submit')]); - foreach ($commands as $command) { - if ($command['command'] == 'settings') { - $this->assertFalse(isset($command['settings']['currentPath']), 'Value of drupalSettings.currentPath is not updated after an AJAX request.'); - } - } - } - - /** - * Tests that overridden CSS files are not added during lazy load. - */ - public function testLazyLoadOverriddenCSS() { - // The test theme overrides js.module.css without an implementation, - // thereby removing it. - \Drupal::service('theme_handler')->install(['test_theme']); - $this->config('system.theme') - ->set('default', 'test_theme') - ->save(); - - // This gets the form, and emulates an Ajax submission on it, including - // adding markup to the HEAD and BODY for any lazy loaded JS/CSS files. - $this->drupalPostAjaxForm('ajax_forms_test_lazy_load_form', ['add_files' => TRUE], ['op' => t('Submit')]); - - // Verify that the resulting HTML does not load the overridden CSS file. - // We add a "?" to the assertion, because drupalSettings may include - // information about the file; we only really care about whether it appears - // in a LINK or STYLE tag, for which Drupal always adds a query string for - // cache control. - $this->assertNoText('js.module.css?', 'Ajax lazy loading does not add overridden CSS files.'); - } - -} diff --git a/web/core/modules/system/src/Tests/Ajax/MultiFormTest.php b/web/core/modules/system/src/Tests/Ajax/MultiFormTest.php deleted file mode 100644 index 96844ed051a1bdd4c4cdd1b06c278173f127983d..0000000000000000000000000000000000000000 --- a/web/core/modules/system/src/Tests/Ajax/MultiFormTest.php +++ /dev/null @@ -1,98 +0,0 @@ -<?php - -namespace Drupal\system\Tests\Ajax; - -use Drupal\Core\Field\FieldStorageDefinitionInterface; -use Drupal\field\Entity\FieldConfig; -use Drupal\field\Entity\FieldStorageConfig; - -/** - * Tests that AJAX-enabled forms work when multiple instances of the same form - * are on a page. - * - * @group Ajax - */ -class MultiFormTest extends AjaxTestBase { - - /** - * Modules to enable. - * - * @var array - */ - public static $modules = ['form_test']; - - protected function setUp() { - parent::setUp(); - - $this->drupalCreateContentType(['type' => 'page', 'name' => 'Page']); - - // Create a multi-valued field for 'page' nodes to use for Ajax testing. - $field_name = 'field_ajax_test'; - FieldStorageConfig::create([ - 'entity_type' => 'node', - 'field_name' => $field_name, - 'type' => 'text', - 'cardinality' => FieldStorageDefinitionInterface::CARDINALITY_UNLIMITED, - ])->save(); - FieldConfig::create([ - 'field_name' => $field_name, - 'entity_type' => 'node', - 'bundle' => 'page', - ])->save(); - entity_get_form_display('node', 'page', 'default') - ->setComponent($field_name, ['type' => 'text_textfield']) - ->save(); - - // Log in a user who can create 'page' nodes. - $this->drupalLogin($this->drupalCreateUser(['create page content'])); - } - - /** - * Tests that pages with the 'node_page_form' included twice work correctly. - */ - public function testMultiForm() { - // HTML IDs for elements within the field are potentially modified with - // each Ajax submission, but these variables are stable and help target the - // desired elements. - $field_name = 'field_ajax_test'; - - $form_xpath = '//form[starts-with(@id, "node-page-form")]'; - $field_xpath = '//div[contains(@class, "field--name-field-ajax-test")]'; - $button_name = $field_name . '_add_more'; - $button_value = t('Add another item'); - $button_xpath_suffix = '//input[@name="' . $button_name . '"]'; - $field_items_xpath_suffix = '//input[@type="text"]'; - - // Ensure the initial page contains both node forms and the correct number - // of field items and "add more" button for the multi-valued field within - // each form. - $this->drupalGet('form-test/two-instances-of-same-form'); - - $fields = $this->xpath($form_xpath . $field_xpath); - $this->assertEqual(count($fields), 2); - foreach ($fields as $field) { - $this->assertEqual(count($field->xpath('.' . $field_items_xpath_suffix)), 1, 'Found the correct number of field items on the initial page.'); - $this->assertFieldsByValue($field->xpath('.' . $button_xpath_suffix), NULL, 'Found the "add more" button on the initial page.'); - } - - $this->assertNoDuplicateIds(t('Initial page contains unique IDs'), 'Other'); - - // Submit the "add more" button of each form twice. After each corresponding - // page update, ensure the same as above. - - for ($i = 0; $i < 2; $i++) { - $forms = $this->xpath($form_xpath); - foreach ($forms as $offset => $form) { - $form_html_id = (string) $form['id']; - $this->drupalPostAjaxForm(NULL, [], [$button_name => $button_value], NULL, [], [], $form_html_id); - $form = $this->xpath($form_xpath)[$offset]; - $field = $form->xpath('.' . $field_xpath); - - $this->assertEqual(count($field[0]->xpath('.' . $field_items_xpath_suffix)), $i + 2, 'Found the correct number of field items after an AJAX submission.'); - $this->assertFieldsByValue($field[0]->xpath('.' . $button_xpath_suffix), NULL, 'Found the "add more" button after an AJAX submission.'); - $this->assertNoDuplicateIds(t('Updated page contains unique IDs'), 'Other'); - } - } - } - -} diff --git a/web/core/modules/system/src/Tests/Form/TriggeringElementTest.php b/web/core/modules/system/src/Tests/Form/TriggeringElementTest.php deleted file mode 100644 index fb59cb5e8ac6addb837a8fe64ff384881f496544..0000000000000000000000000000000000000000 --- a/web/core/modules/system/src/Tests/Form/TriggeringElementTest.php +++ /dev/null @@ -1,97 +0,0 @@ -<?php - -namespace Drupal\system\Tests\Form; - -use Drupal\simpletest\WebTestBase; - -/** - * Tests that FAPI correctly determines the triggering element. - * - * @group Form - */ -class TriggeringElementTest extends WebTestBase { - - /** - * Modules to enable. - * - * @var array - */ - public static $modules = ['form_test']; - - /** - * Test the determination of the triggering element when no button - * information is included in the POST data, as is sometimes the case when - * the ENTER key is pressed in a textfield in Internet Explorer. - */ - public function testNoButtonInfoInPost() { - $path = 'form-test/clicked-button'; - $edit = []; - $form_html_id = 'form-test-clicked-button'; - - // Ensure submitting a form with no buttons results in no triggering element - // and the form submit handler not running. - $this->drupalPostForm($path, $edit, NULL, [], [], $form_html_id); - $this->assertText('There is no clicked button.', '$form_state->getTriggeringElement() set to NULL.'); - $this->assertNoText('Submit handler for form_test_clicked_button executed.', 'Form submit handler did not execute.'); - - // Ensure submitting a form with one or more submit buttons results in the - // triggering element being set to the first one the user has access to. An - // argument with 'r' in it indicates a restricted (#access=FALSE) button. - $this->drupalPostForm($path . '/s', $edit, NULL, [], [], $form_html_id); - $this->assertText('The clicked button is button1.', '$form_state->getTriggeringElement() set to only button.'); - $this->assertText('Submit handler for form_test_clicked_button executed.', 'Form submit handler executed.'); - - $this->drupalPostForm($path . '/s/s', $edit, NULL, [], [], $form_html_id); - $this->assertText('The clicked button is button1.', '$form_state->getTriggeringElement() set to first button.'); - $this->assertText('Submit handler for form_test_clicked_button executed.', 'Form submit handler executed.'); - - $this->drupalPostForm($path . '/rs/s', $edit, NULL, [], [], $form_html_id); - $this->assertText('The clicked button is button2.', '$form_state->getTriggeringElement() set to first available button.'); - $this->assertText('Submit handler for form_test_clicked_button executed.', 'Form submit handler executed.'); - - // Ensure submitting a form with buttons of different types results in the - // triggering element being set to the first button, regardless of type. For - // the FAPI 'button' type, this should result in the submit handler not - // executing. The types are 's'(ubmit), 'b'(utton), and 'i'(mage_button). - $this->drupalPostForm($path . '/s/b/i', $edit, NULL, [], [], $form_html_id); - $this->assertText('The clicked button is button1.', '$form_state->getTriggeringElement() set to first button.'); - $this->assertText('Submit handler for form_test_clicked_button executed.', 'Form submit handler executed.'); - - $this->drupalPostForm($path . '/b/s/i', $edit, NULL, [], [], $form_html_id); - $this->assertText('The clicked button is button1.', '$form_state->getTriggeringElement() set to first button.'); - $this->assertNoText('Submit handler for form_test_clicked_button executed.', 'Form submit handler did not execute.'); - - $this->drupalPostForm($path . '/i/s/b', $edit, NULL, [], [], $form_html_id); - $this->assertText('The clicked button is button1.', '$form_state->getTriggeringElement() set to first button.'); - $this->assertText('Submit handler for form_test_clicked_button executed.', 'Form submit handler executed.'); - } - - /** - * Test that the triggering element does not get set to a button with - * #access=FALSE. - */ - public function testAttemptAccessControlBypass() { - $path = 'form-test/clicked-button'; - $form_html_id = 'form-test-clicked-button'; - - // Retrieve a form where 'button1' has #access=FALSE and 'button2' doesn't. - $this->drupalGet($path . '/rs/s'); - - // Submit the form with 'button1=button1' in the POST data, which someone - // trying to get around security safeguards could easily do. We have to do - // a little trickery here, to work around the safeguards in drupalPostForm(): by - // renaming the text field that is in the form to 'button1', we can get the - // data we want into \Drupal::request()->request. - $elements = $this->xpath('//form[@id="' . $form_html_id . '"]//input[@name="text"]'); - $elements[0]['name'] = 'button1'; - $this->drupalPostForm(NULL, ['button1' => 'button1'], NULL, [], [], $form_html_id); - - // Ensure that the triggering element was not set to the restricted button. - // Do this with both a negative and positive assertion, because negative - // assertions alone can be brittle. See testNoButtonInfoInPost() for why the - // triggering element gets set to 'button2'. - $this->assertNoText('The clicked button is button1.', '$form_state->getTriggeringElement() not set to a restricted button.'); - $this->assertText('The clicked button is button2.', '$form_state->getTriggeringElement() not set to a restricted button.'); - } - -} diff --git a/web/core/modules/system/src/Tests/Session/SessionHttpsTest.php b/web/core/modules/system/src/Tests/Session/SessionHttpsTest.php index 6ba70da52bb52a403502ce4d74e50987f2b2c88a..9a4666fd615e7bf9a3699dd85fad77e280bda77d 100644 --- a/web/core/modules/system/src/Tests/Session/SessionHttpsTest.php +++ b/web/core/modules/system/src/Tests/Session/SessionHttpsTest.php @@ -190,7 +190,7 @@ protected function getPathFromLocationHeader($https = FALSE, $response_code = 30 } // The mock front controllers (http.php and https.php) add the script name - // to $_SERVER['REQEUST_URI'] and friends. Therefore it is necessary to + // to $_SERVER['REQUEST_URI'] and friends. Therefore it is necessary to // strip that also. $base_url .= 'index.php/'; diff --git a/web/core/modules/system/src/Tests/Session/StackSessionHandlerIntegrationTest.php b/web/core/modules/system/src/Tests/Session/StackSessionHandlerIntegrationTest.php deleted file mode 100644 index ac368685db070dc0faa554559e2c0b9674cd6ce2..0000000000000000000000000000000000000000 --- a/web/core/modules/system/src/Tests/Session/StackSessionHandlerIntegrationTest.php +++ /dev/null @@ -1,47 +0,0 @@ -<?php - -namespace Drupal\system\Tests\Session; - -use Drupal\simpletest\WebTestBase; - -/** - * Tests the stacked session handler functionality. - * - * @group Session - */ -class StackSessionHandlerIntegrationTest extends WebTestBase { - - /** - * Modules to enable. - * - * @var array - */ - public static $modules = ['session_test']; - - /** - * Tests a request. - */ - public function testRequest() { - $actual_trace = $this->drupalGetAjax('session-test/trace-handler'); - $expect_trace = [ - ['BEGIN', 'test_argument', 'open'], - ['BEGIN', NULL, 'open'], - ['END', NULL, 'open'], - ['END', 'test_argument', 'open'], - ['BEGIN', 'test_argument', 'read', $this->sessionId], - ['BEGIN', NULL, 'read', $this->sessionId], - ['END', NULL, 'read', $this->sessionId], - ['END', 'test_argument', 'read', $this->sessionId], - ['BEGIN', 'test_argument', 'write', $this->sessionId], - ['BEGIN', NULL, 'write', $this->sessionId], - ['END', NULL, 'write', $this->sessionId], - ['END', 'test_argument', 'write', $this->sessionId], - ['BEGIN', 'test_argument', 'close'], - ['BEGIN', NULL, 'close'], - ['END', NULL, 'close'], - ['END', 'test_argument', 'close'], - ]; - $this->assertEqual($expect_trace, $actual_trace); - } - -} diff --git a/web/core/modules/system/system.post_update.php b/web/core/modules/system/system.post_update.php index 0662853339d412b5517c3255977c6bf598d2b235..ba8e798ca1536532aed80516aad10466852e7dd0 100644 --- a/web/core/modules/system/system.post_update.php +++ b/web/core/modules/system/system.post_update.php @@ -169,3 +169,12 @@ function system_post_update_extra_fields(&$sandbox = NULL) { $config_entity_updater->update($sandbox, 'entity_form_display', $callback); $config_entity_updater->update($sandbox, 'entity_view_display', $callback); } + +/** + * Force cache clear to ensure aggregated JavaScript files are regenerated. + * + * @see https://www.drupal.org/project/drupal/issues/2995570 + */ +function system_post_update_states_clear_cache() { + // Empty post-update hook. +} diff --git a/web/core/modules/system/tests/fixtures/update/drupal-8.views-taxonomy-parent-2543726.php b/web/core/modules/system/tests/fixtures/update/drupal-8.views-taxonomy-parent-2543726.php index 70e0ad4964997d9b5eb3af0f4065aed4b5060459..6d2c41c56e192e33b5c9bc3a9511787518a0e9a0 100644 --- a/web/core/modules/system/tests/fixtures/update/drupal-8.views-taxonomy-parent-2543726.php +++ b/web/core/modules/system/tests/fixtures/update/drupal-8.views-taxonomy-parent-2543726.php @@ -60,4 +60,8 @@ } } +// Insert an extra record with no corresponding term. +// See https://www.drupal.org/project/drupal/issues/2997982 +$query->values(['tid' => max($tids) + 1, 'parent' => 0]); + $query->execute(); diff --git a/web/core/modules/system/tests/modules/accept_header_routing_test/src/AcceptHeaderMiddleware.php b/web/core/modules/system/tests/modules/accept_header_routing_test/src/AcceptHeaderMiddleware.php index 1252f1bb0268902d93d0232105e315b7c9e0196c..f607a895accce21e17142d453677e200b594534d 100644 --- a/web/core/modules/system/tests/modules/accept_header_routing_test/src/AcceptHeaderMiddleware.php +++ b/web/core/modules/system/tests/modules/accept_header_routing_test/src/AcceptHeaderMiddleware.php @@ -6,7 +6,7 @@ use Symfony\Component\HttpKernel\HttpKernelInterface; /** - * Example implementation of accept header based content negotation. + * Example implementation of "accept header"-based content negotiation. */ class AcceptHeaderMiddleware implements HttpKernelInterface { diff --git a/web/core/modules/system/tests/modules/accept_header_routing_test/src/AcceptHeaderRoutingTestServiceProvider.php b/web/core/modules/system/tests/modules/accept_header_routing_test/src/AcceptHeaderRoutingTestServiceProvider.php index 983a60ca58ae90d3f9e9fc823f9c411b74a13241..8d8fefe0aac8af98c3e97e6c210bfac678ba33a1 100644 --- a/web/core/modules/system/tests/modules/accept_header_routing_test/src/AcceptHeaderRoutingTestServiceProvider.php +++ b/web/core/modules/system/tests/modules/accept_header_routing_test/src/AcceptHeaderRoutingTestServiceProvider.php @@ -14,7 +14,7 @@ class AcceptHeaderRoutingTestServiceProvider implements ServiceModifierInterface * {@inheritdoc} */ public function alter(ContainerBuilder $container) { - // Remove the basic content negotation middleware and replace it with a + // Remove the basic content negotiation middleware and replace it with a // basic header based one. $container->register('http_middleware.negotiation', 'Drupal\accept_header_routing_test\AcceptHeaderMiddleware') ->addTag('http_middleware', ['priority' => 400]); diff --git a/web/core/modules/system/tests/modules/ajax_forms_test/src/Callbacks.php b/web/core/modules/system/tests/modules/ajax_forms_test/src/Callbacks.php index 71350305ffee40430a1dc791e911e20bbe1be09b..cf821515b2d724c9cdd5d7990ca7feb747321c04 100644 --- a/web/core/modules/system/tests/modules/ajax_forms_test/src/Callbacks.php +++ b/web/core/modules/system/tests/modules/ajax_forms_test/src/Callbacks.php @@ -50,7 +50,7 @@ public function datetimeCallback($form, FormStateInterface $form_state) { */ public function checkboxCallback($form, FormStateInterface $form_state) { $response = new AjaxResponse(); - $response->addCommand(new HtmlCommand('#ajax_checkbox_value', (int) $form_state->getValue('checkbox'))); + $response->addCommand(new HtmlCommand('#ajax_checkbox_value', $form_state->getValue('checkbox') ? 'checked' : 'unchecked')); $response->addCommand(new DataCommand('#ajax_checkbox_value', 'form_state_value_select', (int) $form_state->getValue('checkbox'))); return $response; } diff --git a/web/core/modules/system/tests/modules/ajax_forms_test/src/Form/AjaxFormsTestSimpleForm.php b/web/core/modules/system/tests/modules/ajax_forms_test/src/Form/AjaxFormsTestSimpleForm.php index 3cb8105315e157170666c156d40a2e291f55a88b..35e0b08e2020d0950ef02c406c43c36b63a6e8ab 100644 --- a/web/core/modules/system/tests/modules/ajax_forms_test/src/Form/AjaxFormsTestSimpleForm.php +++ b/web/core/modules/system/tests/modules/ajax_forms_test/src/Form/AjaxFormsTestSimpleForm.php @@ -65,7 +65,7 @@ public function buildForm(array $form, FormStateInterface $form_state) { $form['select_' . $key . '_callback'] = [ '#type' => 'select', '#title' => $this->t('Test %key callbacks', ['%key' => $key]), - '#options' => ['red' => 'red'], + '#options' => ['red' => 'red', 'green' => 'green'], '#ajax' => ['callback' => $value], ]; } diff --git a/web/core/modules/system/tests/modules/conneg_test/src/Controller/TestController.php b/web/core/modules/system/tests/modules/conneg_test/src/Controller/TestController.php index 4638b0916b84d8b38b39d8a75917ec59ac0563e0..c26c01cf7bbf42d41ca67ee01011385dbb0d2909 100644 --- a/web/core/modules/system/tests/modules/conneg_test/src/Controller/TestController.php +++ b/web/core/modules/system/tests/modules/conneg_test/src/Controller/TestController.php @@ -7,7 +7,7 @@ use Symfony\Component\HttpFoundation\Response; /** - * Test controller for content negotation tests. + * Test controller for content negotiation tests. */ class TestController { diff --git a/web/core/modules/system/tests/modules/entity_test/src/EntityTestAccessControlHandler.php b/web/core/modules/system/tests/modules/entity_test/src/EntityTestAccessControlHandler.php index 1bd49ddaa3c27cab081cc5cd3fc0da583a4bbb46..20766528b774373a1fdb5a2aa673ab1654ce1e5b 100644 --- a/web/core/modules/system/tests/modules/entity_test/src/EntityTestAccessControlHandler.php +++ b/web/core/modules/system/tests/modules/entity_test/src/EntityTestAccessControlHandler.php @@ -36,7 +36,7 @@ protected function checkAccess(EntityInterface $entity, $operation, AccountInter /** @var \Drupal\entity_test\Entity\EntityTest $entity */ // Always forbid access to entities with the label 'forbid_access', used for - // \Drupal\system\Tests\Entity\EntityAccessHControlandlerTest::testDefaultEntityAccess(). + // \Drupal\system\Tests\Entity\EntityAccessControlHandlerTest::testDefaultEntityAccess(). if ($entity->label() == 'forbid_access') { return AccessResult::forbidden(); } diff --git a/web/core/modules/system/tests/modules/form_test/form_test.routing.yml b/web/core/modules/system/tests/modules/form_test/form_test.routing.yml index f2de1264743415bfcefb0ed06aa5cd16fb2b8d04..ce4dfa98fb3ef928644c2e99adcee89bdc4c4157 100644 --- a/web/core/modules/system/tests/modules/form_test/form_test.routing.yml +++ b/web/core/modules/system/tests/modules/form_test/form_test.routing.yml @@ -513,3 +513,10 @@ form_test.optional_container: _title: 'Optional container testing' requirements: _access: 'TRUE' + +form_test.javascript_states_form: + path: '/form-test/javascript-states-form' + defaults: + _form: '\Drupal\form_test\Form\JavascriptStatesForm' + requirements: + _access: 'TRUE' diff --git a/web/core/modules/system/tests/modules/form_test/src/Form/FormTestFileForm.php b/web/core/modules/system/tests/modules/form_test/src/Form/FormTestFileForm.php new file mode 100644 index 0000000000000000000000000000000000000000..985a59c98c5a78396425bc21240170eb5b6253bd --- /dev/null +++ b/web/core/modules/system/tests/modules/form_test/src/Form/FormTestFileForm.php @@ -0,0 +1,42 @@ +<?php + +namespace Drupal\form_test\Form; + +use Drupal\Core\Form\FormBase; +use Drupal\Core\Form\FormStateInterface; + +/** + * Form constructor for testing #type 'file' elements. + * + * @internal + */ +class FormTestFileForm extends FormBase { + + /** + * {@inheritdoc} + */ + public function getFormId() { + return 'form_test_file'; + } + + /** + * {@inheritdoc} + */ + public function buildForm(array $form, FormStateInterface $form_state) { + $form['file'] = [ + '#type' => 'file', + '#multiple' => TRUE, + '#attributes' => [ + 'class' => ['cagatio'], + ], + ]; + return $form; + } + + /** + * {@inheritdoc} + */ + public function submitForm(array &$form, FormStateInterface $form_state) { + } + +} diff --git a/web/core/modules/system/tests/modules/form_test/src/Form/JavascriptStatesForm.php b/web/core/modules/system/tests/modules/form_test/src/Form/JavascriptStatesForm.php new file mode 100644 index 0000000000000000000000000000000000000000..5debb5bb7e8c181e91435cf1f11e318bf9183424 --- /dev/null +++ b/web/core/modules/system/tests/modules/form_test/src/Form/JavascriptStatesForm.php @@ -0,0 +1,55 @@ +<?php + +namespace Drupal\form_test\Form; + +use Drupal\Core\Form\FormBase; +use Drupal\Core\Form\FormStateInterface; + +/** + * Builds a simple form to test states. + * + * @see \Drupal\FunctionalJavascriptTests\Core\Form\JavascriptStatesTest + */ +class JavascriptStatesForm extends FormBase { + + /** + * {@inheritdoc} + */ + public function getFormId() { + return 'javascript_states_form'; + } + + /** + * {@inheritdoc} + */ + public function buildForm(array $form, FormStateInterface $form_state) { + $form['select'] = [ + '#type' => 'select', + '#title' => 'select 1', + '#options' => [0 => 0, 1 => 1, 2 => 2], + ]; + $form['number'] = [ + '#type' => 'number', + '#title' => 'enter 1', + ]; + $form['textfield'] = [ + '#type' => 'textfield', + '#title' => 'textfield', + '#states' => [ + 'visible' => [ + [':input[name="select"]' => ['value' => '1']], + 'or', + [':input[name="number"]' => ['value' => '1']], + ], + ], + ]; + return $form; + } + + /** + * {@inheritdoc} + */ + public function submitForm(array &$form, FormStateInterface $form_state) { + } + +} diff --git a/web/core/modules/system/tests/modules/mail_html_test/mail_html_test.info.yml b/web/core/modules/system/tests/modules/mail_html_test/mail_html_test.info.yml new file mode 100644 index 0000000000000000000000000000000000000000..08ae1e8f0ce32868d912f55544662fc0031b4ebd --- /dev/null +++ b/web/core/modules/system/tests/modules/mail_html_test/mail_html_test.info.yml @@ -0,0 +1,6 @@ +name: 'HTML mail test support' +description: 'Test if HTML in mails works as expected.' +type: module +package: Testing +version: VERSION +core: 8.x diff --git a/web/core/modules/system/tests/modules/mail_html_test/mail_html_test.module b/web/core/modules/system/tests/modules/mail_html_test/mail_html_test.module new file mode 100644 index 0000000000000000000000000000000000000000..f873c89b50aa3783d9b7cb00258c67f73b19f316 --- /dev/null +++ b/web/core/modules/system/tests/modules/mail_html_test/mail_html_test.module @@ -0,0 +1,17 @@ +<?php + +/** + * @file + * Helper module for the html mail and url conversion tests. + */ + +/** + * Implements hook_mail(). + */ +function mail_html_test_mail($key, &$message, $params) { + switch ($key) { + case 'render_from_message_param': + $message['body'][] = \Drupal::service('renderer')->renderPlain($params['message']); + break; + } +} diff --git a/web/core/modules/system/tests/modules/mail_html_test/src/Plugin/Mail/TestHtmlMailCollector.php b/web/core/modules/system/tests/modules/mail_html_test/src/Plugin/Mail/TestHtmlMailCollector.php new file mode 100644 index 0000000000000000000000000000000000000000..43e413596d5fb00373b3942b8b6e45537076df95 --- /dev/null +++ b/web/core/modules/system/tests/modules/mail_html_test/src/Plugin/Mail/TestHtmlMailCollector.php @@ -0,0 +1,33 @@ +<?php + +namespace Drupal\mail_html_test\Plugin\Mail; + +use Drupal\Core\Mail\MailFormatHelper; +use Drupal\Core\Mail\Plugin\Mail\TestMailCollector; + +/** + * Defines a mail backend that captures sent HTML messages in the state system. + * + * This class is for running tests or for development and does not convert HTML + * to plaintext. + * + * @Mail( + * id = "test_html_mail_collector", + * label = @Translation("HTML mail collector"), + * description = @Translation("Does not send the message, but stores its HTML in Drupal within the state system. Used for testing.") + * ) + */ +class TestHtmlMailCollector extends TestMailCollector { + + /** + * {@inheritdoc} + */ + public function format(array $message) { + // Join the body array into one string. + $message['body'] = implode(PHP_EOL, $message['body']); + // Wrap the mail body for sending. + $message['body'] = MailFormatHelper::wrapMail($message['body']); + return $message; + } + +} diff --git a/web/core/modules/system/tests/modules/menu_test/menu_test.links.action.yml b/web/core/modules/system/tests/modules/menu_test/menu_test.links.action.yml index 3d90eb3a39175e8a724e16afda867f5267f05806..f52a0171aee29c5f41c08b020b1ac48ef3db5b9d 100644 --- a/web/core/modules/system/tests/modules/menu_test/menu_test.links.action.yml +++ b/web/core/modules/system/tests/modules/menu_test/menu_test.links.action.yml @@ -50,6 +50,18 @@ menu_test.local_action6: appears_on: - menu_test.local_action1 +menu_test.local_action7: + route_name: menu_test.local_action7 + title: 'Local action with access' + appears_on: + - menu_test.local_action7 + +menu_test.local_action8: + route_name: menu_test.local_action8 + title: 'Local action without access' + appears_on: + - menu_test.local_action7 + menu_test.hidden_menu_add: route_name: menu_test.hidden_menu_add title: 'Add menu' diff --git a/web/core/modules/system/tests/modules/menu_test/menu_test.routing.yml b/web/core/modules/system/tests/modules/menu_test/menu_test.routing.yml index 28418115249db362d6b41c707506f3cf3a45aec0..38de862eee7d400d386662f48d941aae6584ec6c 100644 --- a/web/core/modules/system/tests/modules/menu_test/menu_test.routing.yml +++ b/web/core/modules/system/tests/modules/menu_test/menu_test.routing.yml @@ -125,6 +125,20 @@ menu_test.local_action6: requirements: _access: 'TRUE' +menu_test.local_action7: + path: '/menu-test-local-action-7/cache-check' + defaults: + _controller: '\Drupal\menu_test\TestControllers::test2' + requirements: + _custom_access: '\Drupal\menu_test\Access\AccessCheck::menuLocalAction7' + +menu_test.local_action8: + path: '/menu-test-local-action-8/cache-check' + defaults: + _controller: '\Drupal\menu_test\TestControllers::test2' + requirements: + _custom_access: '\Drupal\menu_test\Access\AccessCheck::menuLocalAction8' + menu_test.contextual_test: path: '/menu-test-contextual/default' defaults: diff --git a/web/core/modules/system/tests/modules/menu_test/src/Access/AccessCheck.php b/web/core/modules/system/tests/modules/menu_test/src/Access/AccessCheck.php index 1b67579eba15a6908722d84cad596eead73fa972..e87fcfa0225728c764b660194879e4784c856c99 100644 --- a/web/core/modules/system/tests/modules/menu_test/src/Access/AccessCheck.php +++ b/web/core/modules/system/tests/modules/menu_test/src/Access/AccessCheck.php @@ -26,4 +26,18 @@ public function access() { return $result->setCacheMaxAge(0); } + /** + * @return \Drupal\Core\Access\AccessResultForbidden + */ + public function menuLocalAction7() { + return AccessResult::forbidden()->addCacheTags(['menu_local_action7'])->addCacheContexts(['url.query_args:menu_local_action7']); + } + + /** + * @return \Drupal\Core\Access\AccessResultAllowed + */ + public function menuLocalAction8() { + return AccessResult::allowed()->addCacheTags(['menu_local_action8'])->addCacheContexts(['url.query_args:menu_local_action8']); + } + } diff --git a/web/core/modules/system/tests/modules/session_test/session_test.module b/web/core/modules/system/tests/modules/session_test/session_test.module index b3ceff80a5cff5dfa9eeef2eab6cb8d44ed091b5..6eb48afbc7174892d66e711650666a55c237d705 100644 --- a/web/core/modules/system/tests/modules/session_test/session_test.module +++ b/web/core/modules/system/tests/modules/session_test/session_test.module @@ -5,10 +5,12 @@ * Test module. */ +use Drupal\user\UserInterface; + /** * Implements hook_user_login(). */ -function session_test_user_login($account) { +function session_test_user_login(UserInterface $account) { if ($account->getUsername() == 'session_test_user') { // Exit so we can verify that the session was regenerated // before hook_user_login() was called. diff --git a/web/core/modules/system/tests/modules/system_test/src/Controller/SystemTestController.php b/web/core/modules/system/tests/modules/system_test/src/Controller/SystemTestController.php index 3f489759d315159db9e1f5eb0eb8752faab55e74..cfd0f2f79679043a09dd78e0a99a12556ba68b80 100644 --- a/web/core/modules/system/tests/modules/system_test/src/Controller/SystemTestController.php +++ b/web/core/modules/system/tests/modules/system_test/src/Controller/SystemTestController.php @@ -287,7 +287,7 @@ public function respondWithReponse(Request $request) { } /** - * A plain Symfony reponse with Cache-Control: public, max-age=60. + * A plain Symfony response with Cache-Control: public, max-age=60. */ public function respondWithPublicResponse() { return (new Response('test'))->setPublic()->setMaxAge(60); diff --git a/web/core/modules/system/tests/modules/theme_test/src/EventSubscriber/ThemeTestSubscriber.php b/web/core/modules/system/tests/modules/theme_test/src/EventSubscriber/ThemeTestSubscriber.php index 99fe19230852d6fd879ed95e3351d17c84c030b3..38fee503ec49ed84deee8ead252a604a9276c06a 100644 --- a/web/core/modules/system/tests/modules/theme_test/src/EventSubscriber/ThemeTestSubscriber.php +++ b/web/core/modules/system/tests/modules/theme_test/src/EventSubscriber/ThemeTestSubscriber.php @@ -17,7 +17,7 @@ class ThemeTestSubscriber implements EventSubscriberInterface { /** * The used container. * - * @todo This variable is never initialzed, so we don't know what it is. + * @todo This variable is never initialized, so we don't know what it is. * See https://www.drupal.org/node/2721315 */ protected $container; diff --git a/web/core/modules/system/tests/src/Functional/Ajax/FrameworkTest.php b/web/core/modules/system/tests/src/Functional/Ajax/FrameworkTest.php new file mode 100644 index 0000000000000000000000000000000000000000..cc7b782d5114a994e651e5a41ad326de2ed69ae6 --- /dev/null +++ b/web/core/modules/system/tests/src/Functional/Ajax/FrameworkTest.php @@ -0,0 +1,158 @@ +<?php + +namespace Drupal\Tests\system\Functional\Ajax; + +use Drupal\Component\Serialization\Json; +use Drupal\Core\Ajax\AddCssCommand; +use Drupal\Core\Ajax\AlertCommand; +use Drupal\Core\Ajax\AppendCommand; +use Drupal\Core\Ajax\HtmlCommand; +use Drupal\Core\Ajax\PrependCommand; +use Drupal\Core\Ajax\SettingsCommand; +use Drupal\Core\Asset\AttachedAssets; +use Drupal\Core\EventSubscriber\MainContentViewSubscriber; +use Drupal\Tests\BrowserTestBase; + +/** + * Performs tests on AJAX framework functions. + * + * @group Ajax + */ +class FrameworkTest extends BrowserTestBase { + + /** + * {@inheritdoc} + */ + protected static $modules = ['node', 'ajax_test', 'ajax_forms_test']; + + /** + * Verifies the Ajax rendering of a command in the settings. + */ + public function testAJAXRender() { + // Verify that settings command is generated if JavaScript settings exist. + $commands = $this->drupalGetAjax('ajax-test/render'); + $expected = new SettingsCommand(['ajax' => 'test'], TRUE); + $this->assertCommand($commands, $expected->render(), 'JavaScript settings command is present.'); + } + + /** + * Tests AjaxResponse::prepare() AJAX commands ordering. + */ + public function testOrder() { + $expected_commands = []; + + // Expected commands, in a very specific order. + $asset_resolver = \Drupal::service('asset.resolver'); + $css_collection_renderer = \Drupal::service('asset.css.collection_renderer'); + $js_collection_renderer = \Drupal::service('asset.js.collection_renderer'); + $renderer = \Drupal::service('renderer'); + $build['#attached']['library'][] = 'ajax_test/order-css-command'; + $assets = AttachedAssets::createFromRenderArray($build); + $css_render_array = $css_collection_renderer->render($asset_resolver->getCssAssets($assets, FALSE)); + $expected_commands[1] = new AddCssCommand($renderer->renderRoot($css_render_array)); + $build['#attached']['library'][] = 'ajax_test/order-header-js-command'; + $build['#attached']['library'][] = 'ajax_test/order-footer-js-command'; + $assets = AttachedAssets::createFromRenderArray($build); + list($js_assets_header, $js_assets_footer) = $asset_resolver->getJsAssets($assets, FALSE); + $js_header_render_array = $js_collection_renderer->render($js_assets_header); + $js_footer_render_array = $js_collection_renderer->render($js_assets_footer); + $expected_commands[2] = new PrependCommand('head', $js_header_render_array); + $expected_commands[3] = new AppendCommand('body', $js_footer_render_array); + $expected_commands[4] = new HtmlCommand('body', 'Hello, world!'); + + // Load any page with at least one CSS file, at least one JavaScript file + // and at least one #ajax-powered element. The latter is an assumption of + // drupalPostAjaxForm(), the two former are assumptions of the Ajax + // renderer. + // @todo refactor AJAX Framework + tests to make less assumptions. + $this->drupalGet('ajax_forms_test_lazy_load_form'); + + // Verify AJAX command order — this should always be the order: + // 1. CSS files + // 2. JavaScript files in the header + // 3. JavaScript files in the footer + // 4. Any other AJAX commands, in whatever order they were added. + $commands = $this->drupalGetAjax('ajax-test/order'); + $this->assertCommand(array_slice($commands, 0, 1), $expected_commands[1]->render()); + $this->assertCommand(array_slice($commands, 1, 1), $expected_commands[2]->render()); + $this->assertCommand(array_slice($commands, 2, 1), $expected_commands[3]->render()); + $this->assertCommand(array_slice($commands, 3, 1), $expected_commands[4]->render()); + } + + /** + * Tests the behavior of an error alert command. + */ + public function testAJAXRenderError() { + // Verify custom error message. + $edit = [ + 'message' => 'Custom error message.', + ]; + $commands = $this->drupalGetAjax('ajax-test/render-error', ['query' => $edit]); + $expected = new AlertCommand($edit['message']); + $this->assertCommand($commands, $expected->render(), 'Custom error message is output.'); + } + + /** + * Asserts the array of Ajax commands contains the searched command. + * + * An AjaxResponse object stores an array of Ajax commands. This array + * sometimes includes commands automatically provided by the framework in + * addition to commands returned by a particular controller. During testing, + * we're usually interested that a particular command is present, and don't + * care whether other commands precede or follow the one we're interested in. + * Additionally, the command we're interested in may include additional data + * that we're not interested in. Therefore, this function simply asserts that + * one of the commands in $haystack contains all of the keys and values in + * $needle. Furthermore, if $needle contains a 'settings' key with an array + * value, we simply assert that all keys and values within that array are + * present in the command we're checking, and do not consider it a failure if + * the actual command contains additional settings that aren't part of + * $needle. + * + * @param $haystack + * An array of rendered Ajax commands returned by the server. + * @param $needle + * Array of info we're expecting in one of those commands. + */ + protected function assertCommand($haystack, $needle) { + $found = FALSE; + foreach ($haystack as $command) { + // If the command has additional settings that we're not testing for, do + // not consider that a failure. + if (isset($command['settings']) && is_array($command['settings']) && isset($needle['settings']) && is_array($needle['settings'])) { + $command['settings'] = array_intersect_key($command['settings'], $needle['settings']); + } + // If the command has additional data that we're not testing for, do not + // consider that a failure. Also, == instead of ===, because we don't + // require the key/value pairs to be in any particular order + // (http://php.net/manual/language.operators.array.php). + if (array_intersect_key($command, $needle) == $needle) { + $found = TRUE; + break; + } + } + $this->assertTrue($found); + } + + /** + * Requests a path or URL in drupal_ajax format and JSON-decodes the response. + * + * @param \Drupal\Core\Url|string $path + * Drupal path or URL to request from. + * @param array $options + * Array of URL options. + * @param array $headers + * Array of headers. + * + * @return array + * Decoded JSON. + */ + protected function drupalGetAjax($path, array $options = [], array $headers = []) { + $headers[] = 'X-Requested-With: XMLHttpRequest'; + if (!isset($options['query'][MainContentViewSubscriber::WRAPPER_FORMAT])) { + $options['query'][MainContentViewSubscriber::WRAPPER_FORMAT] = 'drupal_ajax'; + } + return Json::decode($this->drupalGet($path, $options, $headers)); + } + +} diff --git a/web/core/modules/system/tests/src/Functional/Common/UrlTest.php b/web/core/modules/system/tests/src/Functional/Common/UrlTest.php index 8e4d7b121c5852a7d7ca65ebf85d2350f7734d9e..362868c3178321f939f803507a9a268ddde73d6e 100644 --- a/web/core/modules/system/tests/src/Functional/Common/UrlTest.php +++ b/web/core/modules/system/tests/src/Functional/Common/UrlTest.php @@ -314,7 +314,7 @@ public function testExternalUrls() { $url = $test_url . '?drupal=awesome'; $query = ['awesome' => 'drupal']; $result = Url::fromUri($url, ['query' => $query])->toString(); - $this->assertEqual('https://www.drupal.org/?awesome=drupal&drupal=awesome', $result); + $this->assertEqual('https://www.drupal.org/?drupal=awesome&awesome=drupal', $result); } } diff --git a/web/core/modules/system/src/Tests/Condition/ConditionFormTest.php b/web/core/modules/system/tests/src/Functional/Condition/ConditionFormTest.php similarity index 90% rename from web/core/modules/system/src/Tests/Condition/ConditionFormTest.php rename to web/core/modules/system/tests/src/Functional/Condition/ConditionFormTest.php index 42945b250a805f6a4f05f490dfe93c91c1cf4df1..adefc4392e620dbba4ae3b6f0eed63ded38a5c3f 100644 --- a/web/core/modules/system/src/Tests/Condition/ConditionFormTest.php +++ b/web/core/modules/system/tests/src/Functional/Condition/ConditionFormTest.php @@ -1,9 +1,9 @@ <?php -namespace Drupal\system\Tests\Condition; +namespace Drupal\Tests\system\Functional\Condition; use Drupal\node\Entity\Node; -use Drupal\simpletest\WebTestBase; +use Drupal\Tests\BrowserTestBase; /** * Tests that condition plugins basic form handling is working. @@ -14,7 +14,7 @@ * * @group Condition */ -class ConditionFormTest extends WebTestBase { +class ConditionFormTest extends BrowserTestBase { public static $modules = ['node', 'condition_test']; diff --git a/web/core/modules/system/tests/src/Functional/Entity/EntityReferenceSelection/EntityReferenceSelectionAccessTest.php b/web/core/modules/system/tests/src/Functional/Entity/EntityReferenceSelection/EntityReferenceSelectionAccessTest.php index c037d12e3f1eff61dd6976db9a72d9c953c7437a..70944b9750b78116947e09ec60e747d8d07d60d8 100644 --- a/web/core/modules/system/tests/src/Functional/Entity/EntityReferenceSelection/EntityReferenceSelectionAccessTest.php +++ b/web/core/modules/system/tests/src/Functional/Entity/EntityReferenceSelection/EntityReferenceSelectionAccessTest.php @@ -7,10 +7,12 @@ use Drupal\Core\Language\LanguageInterface; use Drupal\comment\CommentInterface; use Drupal\KernelTests\KernelTestBase; +use Drupal\media\Entity\Media; use Drupal\node\Entity\Node; use Drupal\taxonomy\Entity\Term; use Drupal\taxonomy\Entity\Vocabulary; use Drupal\node\NodeInterface; +use Drupal\Tests\media\Traits\MediaTypeCreationTrait; use Drupal\Tests\node\Traits\ContentTypeCreationTrait; use Drupal\Tests\user\Traits\UserCreationTrait; use Drupal\user\Entity\User; @@ -25,6 +27,7 @@ class EntityReferenceSelectionAccessTest extends KernelTestBase { use CommentTestTrait; use ContentTypeCreationTrait; + use MediaTypeCreationTrait; use UserCreationTrait; /** @@ -32,7 +35,7 @@ class EntityReferenceSelectionAccessTest extends KernelTestBase { * * @var array */ - public static $modules = ['comment', 'field', 'node', 'system', 'taxonomy', 'text', 'user']; + public static $modules = ['comment', 'field', 'file', 'image', 'node', 'media', 'system', 'taxonomy', 'text', 'user']; /** * {@inheritdoc} @@ -42,13 +45,16 @@ protected function setUp() { $this->installSchema('system', 'sequences'); $this->installSchema('comment', ['comment_entity_statistics']); + $this->installSchema('file', ['file_usage']); $this->installEntitySchema('comment'); + $this->installEntitySchema('file'); + $this->installEntitySchema('media'); $this->installEntitySchema('node'); $this->installEntitySchema('taxonomy_term'); $this->installEntitySchema('user'); - $this->installConfig(['comment', 'field', 'node', 'taxonomy', 'user']); + $this->installConfig(['comment', 'field', 'media', 'node', 'taxonomy', 'user']); // Create the anonymous and the admin users. $anonymous_user = User::create([ @@ -681,4 +687,92 @@ public function testTermHandler() { $this->assertReferenceable($selection_options, $referenceable_tests, 'Term handler (admin)'); } + /** + * Tests the selection handler for the media entity type. + */ + public function testMediaHandler() { + $selection_options = [ + 'target_type' => 'media', + 'handler' => 'default', + 'target_bundles' => NULL, + ]; + + // Build a set of test data. + $media_type = $this->createMediaType('file'); + $media_values = [ + 'published' => [ + 'bundle' => $media_type->id(), + 'status' => 1, + 'name' => 'Media published', + 'uid' => 1, + ], + 'unpublished' => [ + 'bundle' => $media_type->id(), + 'status' => 0, + 'name' => 'Media unpublished', + 'uid' => 1, + ], + ]; + + $media_entities = []; + $media_labels = []; + foreach ($media_values as $key => $values) { + $media = Media::create($values); + $media->save(); + $media_entities[$key] = $media; + $media_labels[$key] = Html::escape($media->label()); + } + + // Test as a non-admin. + $normal_user = $this->createUser(['view media']); + $this->setCurrentUser($normal_user); + $referenceable_tests = [ + [ + 'arguments' => [ + [NULL, 'CONTAINS'], + ], + 'result' => [ + $media_type->id() => [ + $media_entities['published']->id() => $media_labels['published'], + ], + ], + ], + [ + 'arguments' => [ + ['Media unpublished', 'CONTAINS'], + ], + 'result' => [], + ], + ]; + $this->assertReferenceable($selection_options, $referenceable_tests, 'Media handler'); + + // Test as an admin. + $admin_user = $this->createUser(['view media', 'administer media']); + $this->setCurrentUser($admin_user); + $referenceable_tests = [ + [ + 'arguments' => [ + [NULL, 'CONTAINS'], + ], + 'result' => [ + $media_type->id() => [ + $media_entities['published']->id() => $media_labels['published'], + $media_entities['unpublished']->id() => $media_labels['unpublished'], + ], + ], + ], + [ + 'arguments' => [ + ['Media unpublished', 'CONTAINS'], + ], + 'result' => [ + $media_type->id() => [ + $media_entities['unpublished']->id() => $media_labels['unpublished'], + ], + ], + ], + ]; + $this->assertReferenceable($selection_options, $referenceable_tests, 'Media handler (admin)'); + } + } diff --git a/web/core/modules/system/tests/src/Functional/File/FileSaveHtaccessLoggingTest.php b/web/core/modules/system/tests/src/Functional/File/FileSaveHtaccessLoggingTest.php index 442591d1539111bf71786b436f7dadef7d7acc70..003373de718e5f310ae40126e1febf04669265a3 100644 --- a/web/core/modules/system/tests/src/Functional/File/FileSaveHtaccessLoggingTest.php +++ b/web/core/modules/system/tests/src/Functional/File/FileSaveHtaccessLoggingTest.php @@ -6,7 +6,7 @@ use Drupal\Tests\BrowserTestBase; /** - * Tests the log message added by file_save_htacess(). + * Tests the log message added by file_save_htaccess(). * * @group File */ diff --git a/web/core/modules/system/src/Tests/Form/ElementsTableSelectTest.php b/web/core/modules/system/tests/src/Functional/Form/ElementsTableSelectTest.php similarity index 65% rename from web/core/modules/system/src/Tests/Form/ElementsTableSelectTest.php rename to web/core/modules/system/tests/src/Functional/Form/ElementsTableSelectTest.php index 030526eef9fa42c2ecff07c9416fe28c9b7e641f..f377c0abf60ace5a0af955fc8e3e871415a92516 100644 --- a/web/core/modules/system/src/Tests/Form/ElementsTableSelectTest.php +++ b/web/core/modules/system/tests/src/Functional/Form/ElementsTableSelectTest.php @@ -1,17 +1,16 @@ <?php -namespace Drupal\system\Tests\Form; +namespace Drupal\Tests\system\Functional\Form; use Drupal\Core\Form\FormState; -use Drupal\simpletest\WebTestBase; -use Drupal\Tests\system\Functional\Form\StubForm; +use Drupal\Tests\BrowserTestBase; /** * Tests the tableselect form element for expected behavior. * * @group Form */ -class ElementsTableSelectTest extends WebTestBase { +class ElementsTableSelectTest extends BrowserTestBase { /** * Modules to enable. @@ -27,35 +26,14 @@ public function testMultipleTrue() { $this->drupalGet('form_test/tableselect/multiple-true'); - $this->assertNoText(t('Empty text.'), 'Empty text should not be displayed.'); + $this->assertSession()->responseNotContains('Empty text.', 'Empty text should not be displayed.'); // Test for the presence of the Select all rows tableheader. - $this->assertFieldByXPath('//th[@class="select-all"]', NULL, 'Presence of the "Select all" checkbox.'); + $this->assertNotEmpty($this->xpath('//th[@class="select-all"]'), 'Presence of the "Select all" checkbox.'); $rows = ['row1', 'row2', 'row3']; foreach ($rows as $row) { - $this->assertFieldByXPath('//input[@type="checkbox"]', $row, format_string('Checkbox for value @row.', ['@row' => $row])); - } - } - - /** - * Test the presence of ajax functionality for all options. - */ - public function testAjax() { - $rows = ['row1', 'row2', 'row3']; - // Test checkboxes (#multiple == TRUE). - foreach ($rows as $row) { - $element = 'tableselect[' . $row . ']'; - $edit = [$element => TRUE]; - $result = $this->drupalPostAjaxForm('form_test/tableselect/multiple-true', $edit, $element); - $this->assertFalse(empty($result), t('Ajax triggers on checkbox for @row.', ['@row' => $row])); - } - // Test radios (#multiple == FALSE). - $element = 'tableselect'; - foreach ($rows as $row) { - $edit = [$element => $row]; - $result = $this->drupalPostAjaxForm('form_test/tableselect/multiple-false', $edit, $element); - $this->assertFalse(empty($result), t('Ajax triggers on radio for @row.', ['@row' => $row])); + $this->assertNotEmpty($this->xpath('//input[@type="checkbox"]', [$row]), "Checkbox for the value $row."); } } @@ -65,40 +43,39 @@ public function testAjax() { public function testMultipleFalse() { $this->drupalGet('form_test/tableselect/multiple-false'); - $this->assertNoText(t('Empty text.'), 'Empty text should not be displayed.'); + $this->assertSession()->pageTextNotContains('Empty text.'); // Test for the absence of the Select all rows tableheader. - $this->assertNoFieldByXPath('//th[@class="select-all"]', '', 'Absence of the "Select all" checkbox.'); + $this->assertFalse($this->xpath('//th[@class="select-all"]')); $rows = ['row1', 'row2', 'row3']; foreach ($rows as $row) { - $this->assertFieldByXPath('//input[@type="radio"]', $row, format_string('Radio button for value @row.', ['@row' => $row])); + $this->assertNotEmpty($this->xpath('//input[@type="radio"]', [$row], "Radio button value: $row")); } } /** * Tests the display when #colspan is set. */ - public function testTableselectColSpan() { + public function testTableSelectColSpan() { $this->drupalGet('form_test/tableselect/colspan'); - $this->assertText(t('Three'), 'Presence of the third column'); - $this->assertNoText(t('Four'), 'Absence of a fourth column'); + $this->assertSession()->pageTextContains('Three', 'Presence of the third column'); + $this->assertSession()->pageTextNotContains('Four', 'Absence of a fourth column'); // There should be three labeled column headers and 1 for the input. - $table_head = $this->xpath('//thead'); - $this->assertEqual(count($table_head[0]->tr->th), 4, 'There are four column headers'); + $table_head = $this->xpath('//thead/tr/th'); + $this->assertEquals(count($table_head), 4, 'There are four column headers'); - $table_body = $this->xpath('//tbody'); // The first two body rows should each have 5 table cells: One for the // radio, one cell in the first column, one cell in the second column, // and two cells in the third column which has colspan 2. for ($i = 0; $i <= 1; $i++) { - $this->assertEqual(count($table_body[0]->tr[$i]->td), 5, format_string('There are five cells in row @row.', ['@row' => $i])); + $this->assertEquals(count($this->xpath('//tbody/tr[' . ($i + 1) . ']/td')), 5, 'There are five cells in row ' . $i); } // The third row should have 3 cells, one for the radio, one spanning the // first and second column, and a third in column 3 (which has colspan 3). - $this->assertEqual(count($table_body[0]->tr[2]->td), 3, 'There are three cells in row 3.'); + $this->assertEquals(count($this->xpath('//tbody/tr[3]/td')), 3, 'There are three cells in row 3.'); } /** @@ -106,7 +83,7 @@ public function testTableselectColSpan() { */ public function testEmptyText() { $this->drupalGet('form_test/tableselect/empty-text'); - $this->assertText(t('Empty text.'), 'Empty text should be displayed.'); + $this->assertSession()->pageTextContains('Empty text.', 'Empty text should be displayed.'); } /** @@ -119,18 +96,19 @@ public function testMultipleTrueSubmit() { $edit['tableselect[row1]'] = TRUE; $this->drupalPostForm('form_test/tableselect/multiple-true', $edit, 'Submit'); - $this->assertText(t('Submitted: row1 = row1'), 'Checked checkbox row1'); - $this->assertText(t('Submitted: row2 = 0'), 'Unchecked checkbox row2.'); - $this->assertText(t('Submitted: row3 = 0'), 'Unchecked checkbox row3.'); + $assert_session = $this->assertSession(); + $assert_session->pageTextContains('Submitted: row1 = row1', 'Checked checkbox row1'); + $assert_session->pageTextContains('Submitted: row2 = 0', 'Unchecked checkbox row2.'); + $assert_session->pageTextContains('Submitted: row3 = 0', 'Unchecked checkbox row3.'); // Test a submission with multiple checkboxes checked. $edit['tableselect[row1]'] = TRUE; $edit['tableselect[row3]'] = TRUE; $this->drupalPostForm('form_test/tableselect/multiple-true', $edit, 'Submit'); - $this->assertText(t('Submitted: row1 = row1'), 'Checked checkbox row1.'); - $this->assertText(t('Submitted: row2 = 0'), 'Unchecked checkbox row2.'); - $this->assertText(t('Submitted: row3 = row3'), 'Checked checkbox row3.'); + $assert_session->pageTextContains('Submitted: row1 = row1', 'Checked checkbox row1.'); + $assert_session->pageTextContains('Submitted: row2 = 0', 'Unchecked checkbox row2.'); + $assert_session->pageTextContains('Submitted: row3 = row3', 'Checked checkbox row3.'); } @@ -140,7 +118,7 @@ public function testMultipleTrueSubmit() { public function testMultipleFalseSubmit() { $edit['tableselect'] = 'row1'; $this->drupalPostForm('form_test/tableselect/multiple-false', $edit, 'Submit'); - $this->assertText(t('Submitted: row1'), 'Selected radio button'); + $this->assertSession()->pageTextContains('Submitted: row1', 'Selected radio button'); } /** @@ -149,18 +127,18 @@ public function testMultipleFalseSubmit() { public function testAdvancedSelect() { // When #multiple = TRUE a Select all checkbox should be displayed by default. $this->drupalGet('form_test/tableselect/advanced-select/multiple-true-default'); - $this->assertFieldByXPath('//th[@class="select-all"]', NULL, 'Display a "Select all" checkbox by default when #multiple is TRUE.'); + $this->xpath('//th[@class="select-all"]'); // When #js_select is set to FALSE, a "Select all" checkbox should not be displayed. $this->drupalGet('form_test/tableselect/advanced-select/multiple-true-no-advanced-select'); - $this->assertNoFieldByXPath('//th[@class="select-all"]', NULL, 'Do not display a "Select all" checkbox when #js_select is FALSE.'); + $this->assertFalse($this->xpath('//th[@class="select-all"]')); // A "Select all" checkbox never makes sense when #multiple = FALSE, regardless of the value of #js_select. $this->drupalGet('form_test/tableselect/advanced-select/multiple-false-default'); - $this->assertNoFieldByXPath('//th[@class="select-all"]', NULL, 'Do not display a "Select all" checkbox when #multiple is FALSE.'); + $this->assertFalse($this->xpath('//th[@class="select-all"]')); $this->drupalGet('form_test/tableselect/advanced-select/multiple-false-advanced-select'); - $this->assertNoFieldByXPath('//th[@class="select-all"]', NULL, 'Do not display a "Select all" checkbox when #multiple is FALSE, even when #js_select is TRUE.'); + $this->assertFalse($this->xpath('//th[@class="select-all"]')); } /** diff --git a/web/core/modules/system/tests/src/Functional/Form/ModulesListFormWebTest.php b/web/core/modules/system/tests/src/Functional/Form/ModulesListFormWebTest.php index dc63e64d72d8cf623d6202d26f828082dca1c7a6..52e4160cda9084f6d289c54ee9feda7d5c00b0b0 100644 --- a/web/core/modules/system/tests/src/Functional/Form/ModulesListFormWebTest.php +++ b/web/core/modules/system/tests/src/Functional/Form/ModulesListFormWebTest.php @@ -51,4 +51,29 @@ public function testModuleListForm() { $this->assertText('simpletest'); } + public function testModulesListFormWithInvalidInfoFile() { + $broken_info_yml = <<<BROKEN +name: Module With Broken Info file +type: module +BROKEN; + $path = \Drupal::service('site.path') . "/modules/broken"; + mkdir($path, 0777, TRUE); + file_put_contents("$path/broken.info.yml", $broken_info_yml); + + $this->drupalLogin( + $this->drupalCreateUser( + ['administer modules', 'administer permissions'] + ) + ); + $this->drupalGet('admin/modules'); + $this->assertSession()->statusCodeEquals(200); + + // Confirm that the error message is shown. + $this->assertSession() + ->pageTextContains('Modules could not be listed due to an error: Missing required keys (core) in ' . $path . '/broken.info.yml'); + + // Check that the module filter text box is available. + $this->assertTrue($this->xpath('//input[@name="text"]')); + } + } diff --git a/web/core/modules/system/tests/src/Functional/Form/RebuildTest.php b/web/core/modules/system/tests/src/Functional/Form/RebuildTest.php new file mode 100644 index 0000000000000000000000000000000000000000..3e951e2e802c9d5012879c4109b2c8f749a8b617 --- /dev/null +++ b/web/core/modules/system/tests/src/Functional/Form/RebuildTest.php @@ -0,0 +1,61 @@ +<?php + +namespace Drupal\Tests\system\Functional\Form; + +use Drupal\Tests\BrowserTestBase; + +/** + * Tests functionality of \Drupal\Core\Form\FormBuilderInterface::rebuildForm(). + * + * @group Form + */ +class RebuildTest extends BrowserTestBase { + + /** + * Modules to enable. + * + * @var array + */ + public static $modules = ['node', 'form_test']; + + /** + * A user for testing. + * + * @var \Drupal\user\UserInterface + */ + protected $webUser; + + protected function setUp() { + parent::setUp(); + + $this->drupalCreateContentType(['type' => 'page', 'name' => 'Basic page']); + + $this->webUser = $this->drupalCreateUser(['access content']); + $this->drupalLogin($this->webUser); + } + + /** + * Tests preservation of values. + */ + public function testRebuildPreservesValues() { + $edit = [ + 'checkbox_1_default_off' => TRUE, + 'checkbox_1_default_on' => FALSE, + 'text_1' => 'foo', + ]; + $this->drupalPostForm('form-test/form-rebuild-preserve-values', $edit, 'Add more'); + + $assert_session = $this->assertSession(); + + // Verify that initial elements retained their submitted values. + $assert_session->checkboxChecked('edit-checkbox-1-default-off'); + $assert_session->checkboxNotChecked('edit-checkbox-1-default-on'); + $assert_session->fieldValueEquals('edit-text-1', 'foo'); + + // Verify that newly added elements were initialized with their default values. + $assert_session->checkboxChecked('edit-checkbox-2-default-on'); + $assert_session->checkboxNotChecked('edit-checkbox-2-default-off'); + $assert_session->fieldValueEquals('edit-text-2', 'DEFAULT 2'); + } + +} diff --git a/web/core/modules/system/src/Tests/Form/StorageTest.php b/web/core/modules/system/tests/src/Functional/Form/StorageTest.php similarity index 61% rename from web/core/modules/system/src/Tests/Form/StorageTest.php rename to web/core/modules/system/tests/src/Functional/Form/StorageTest.php index a1f7fee3df5891bf0e5b376b1dafdf89fcdf5186..95969fde5a2c82af4a2e399b634fe882dbf1142e 100644 --- a/web/core/modules/system/src/Tests/Form/StorageTest.php +++ b/web/core/modules/system/tests/src/Functional/Form/StorageTest.php @@ -1,8 +1,10 @@ <?php -namespace Drupal\system\Tests\Form; +namespace Drupal\Tests\system\Functional\Form; -use Drupal\simpletest\WebTestBase; +use Drupal\Core\Database\Database; +use Drupal\Core\EventSubscriber\MainContentViewSubscriber; +use Drupal\Tests\BrowserTestBase; /** * Tests a multistep form using form storage and makes sure validation and @@ -16,7 +18,7 @@ * * @group Form */ -class StorageTest extends WebTestBase { +class StorageTest extends BrowserTestBase { /** * Modules to enable. @@ -25,6 +27,9 @@ class StorageTest extends WebTestBase { */ public static $modules = ['form_test', 'dblog']; + /** + * {@inheritdoc} + */ protected function setUp() { parent::setUp(); @@ -36,25 +41,27 @@ protected function setUp() { */ public function testForm() { $this->drupalGet('form_test/form-storage'); - $this->assertText('Form constructions: 1'); + + $assert_session = $this->assertSession(); + $assert_session->pageTextContains('Form constructions: 1'); $edit = ['title' => 'new', 'value' => 'value_is_set']; // Use form rebuilding triggered by a submit button. $this->drupalPostForm(NULL, $edit, 'Continue submit'); - $this->assertText('Form constructions: 2'); - $this->assertText('Form constructions: 3'); + $assert_session->pageTextContains('Form constructions: 2'); + $assert_session->pageTextContains('Form constructions: 3'); // Reset the form to the values of the storage, using a form rebuild // triggered by button of type button. $this->drupalPostForm(NULL, ['title' => 'changed'], 'Reset'); - $this->assertFieldByName('title', 'new', 'Values have been reset.'); + $assert_session->fieldValueEquals('title', 'new'); // After rebuilding, the form has been cached. - $this->assertText('Form constructions: 4'); + $assert_session->pageTextContains('Form constructions: 4'); $this->drupalPostForm(NULL, $edit, 'Save'); - $this->assertText('Form constructions: 4'); - $this->assertText('Title: new', 'The form storage has stored the values.'); + $assert_session->pageTextContains('Form constructions: 4'); + $assert_session->pageTextContains('Title: new', 'The form storage has stored the values.'); } /** @@ -62,26 +69,26 @@ public function testForm() { */ public function testFormCached() { $this->drupalGet('form_test/form-storage', ['query' => ['cache' => 1]]); - $this->assertText('Form constructions: 1'); + $this->assertSession()->pageTextContains('Form constructions: 1'); $edit = ['title' => 'new', 'value' => 'value_is_set']; // Use form rebuilding triggered by a submit button. $this->drupalPostForm(NULL, $edit, 'Continue submit'); // The first one is for the building of the form. - $this->assertText('Form constructions: 2'); + $this->assertSession()->pageTextContains('Form constructions: 2'); // The second one is for the rebuilding of the form. - $this->assertText('Form constructions: 3'); + $this->assertSession()->pageTextContains('Form constructions: 3'); // Reset the form to the values of the storage, using a form rebuild // triggered by button of type button. $this->drupalPostForm(NULL, ['title' => 'changed'], 'Reset'); - $this->assertFieldByName('title', 'new', 'Values have been reset.'); - $this->assertText('Form constructions: 4'); + $this->assertSession()->fieldValueEquals('title', 'new'); + $this->assertSession()->pageTextContains('Form constructions: 4'); $this->drupalPostForm(NULL, $edit, 'Save'); - $this->assertText('Form constructions: 4'); - $this->assertText('Title: new', 'The form storage has stored the values.'); + $this->assertSession()->pageTextContains('Form constructions: 4'); + $this->assertSession()->pageTextContains('Title: new', 'The form storage has stored the values.'); } /** @@ -124,7 +131,7 @@ public function testCachedFormStorageValidation() { // validation error. Post again and verify that the rebuilt form contains // the values of the updated form storage. $this->drupalPostForm(NULL, ['title' => 'foo', 'value' => 'bar'], 'Save'); - $this->assertText("The thing has been changed.", 'The altered form storage value was updated in cache and taken over.'); + $this->assertSession()->pageTextContains("The thing has been changed.", 'The altered form storage value was updated in cache and taken over.'); } /** @@ -135,27 +142,27 @@ public function testImmutableForm() { // Request the form with 'cache' query parameter to enable form caching. $this->drupalGet('form_test/form-storage', ['query' => ['cache' => 1, 'immutable' => 1]]); $buildIdFields = $this->xpath('//input[@name="form_build_id"]'); - $this->assertEqual(count($buildIdFields), 1, 'One form build id field on the page'); - $buildId = (string) $buildIdFields[0]['value']; + $this->assertEquals(count($buildIdFields), 1, 'One form build id field on the page'); + $buildId = $buildIdFields[0]->getValue(); // Trigger validation error by submitting an empty title. $edit = ['title' => '']; $this->drupalPostForm(NULL, $edit, 'Continue submit'); // Verify that the build-id did change. - $this->assertNoFieldByName('form_build_id', $buildId, 'Build id changes when form validation fails'); + $this->assertSession()->hiddenFieldValueNotEquals('form_build_id', $buildId); // Retrieve the new build-id. $buildIdFields = $this->xpath('//input[@name="form_build_id"]'); - $this->assertEqual(count($buildIdFields), 1, 'One form build id field on the page'); - $buildId = (string) $buildIdFields[0]['value']; + $this->assertEquals(count($buildIdFields), 1, 'One form build id field on the page'); + $buildId = (string) $buildIdFields[0]->getValue(); // Trigger validation error by again submitting an empty title. $edit = ['title' => '']; $this->drupalPostForm(NULL, $edit, 'Continue submit'); // Verify that the build-id does not change the second time. - $this->assertFieldByName('form_build_id', $buildId, 'Build id remains the same when form validation fails subsequently'); + $this->assertSession()->hiddenFieldValueEquals('form_build_id', $buildId); } /** @@ -164,25 +171,28 @@ public function testImmutableForm() { public function testImmutableFormLegacyProtection() { $this->drupalGet('form_test/form-storage', ['query' => ['cache' => 1, 'immutable' => 1]]); $build_id_fields = $this->xpath('//input[@name="form_build_id"]'); - $this->assertEqual(count($build_id_fields), 1, 'One form build id field on the page'); - $build_id = (string) $build_id_fields[0]['value']; + $this->assertEquals(count($build_id_fields), 1, 'One form build id field on the page'); + $build_id = $build_id_fields[0]->getValue(); // Try to poison the form cache. - $original = $this->drupalGetAjax('form-test/form-storage-legacy/' . $build_id); - $this->assertEqual($original['form']['#build_id_old'], $build_id, 'Original build_id was recorded'); - $this->assertNotEqual($original['form']['#build_id'], $build_id, 'New build_id was generated'); + $response = $this->drupalGet('form-test/form-storage-legacy/' . $build_id, ['query' => [MainContentViewSubscriber::WRAPPER_FORMAT => 'drupal_ajax']], ['X-Requested-With: XMLHttpRequest']); + $original = json_decode($response, TRUE); + + $this->assertEquals($original['form']['#build_id_old'], $build_id, 'Original build_id was recorded'); + $this->assertNotEquals($original['form']['#build_id'], $build_id, 'New build_id was generated'); // Assert that a watchdog message was logged by // \Drupal::formBuilder()->setCache(). - $status = (bool) db_query_range('SELECT 1 FROM {watchdog} WHERE message = :message', 0, 1, [':message' => 'Form build-id mismatch detected while attempting to store a form in the cache.']); - $this->assert($status, 'A watchdog message was logged by \Drupal::formBuilder()->setCache'); + $status = (bool) Database::getConnection()->queryRange('SELECT 1 FROM {watchdog} WHERE message = :message', 0, 1, [':message' => 'Form build-id mismatch detected while attempting to store a form in the cache.']); + $this->assertTrue($status, 'A watchdog message was logged by \Drupal::formBuilder()->setCache'); // Ensure that the form state was not poisoned by the preceding call. - $original = $this->drupalGetAjax('form-test/form-storage-legacy/' . $build_id); - $this->assertEqual($original['form']['#build_id_old'], $build_id, 'Original build_id was recorded'); - $this->assertNotEqual($original['form']['#build_id'], $build_id, 'New build_id was generated'); - $this->assert(empty($original['form']['#poisoned']), 'Original form structure was preserved'); - $this->assert(empty($original['form_state']['poisoned']), 'Original form state was preserved'); + $response = $this->drupalGet('form-test/form-storage-legacy/' . $build_id, ['query' => [MainContentViewSubscriber::WRAPPER_FORMAT => 'drupal_ajax']], ['X-Requested-With: XMLHttpRequest']); + $original = json_decode($response, TRUE); + $this->assertEquals($original['form']['#build_id_old'], $build_id, 'Original build_id was recorded'); + $this->assertNotEquals($original['form']['#build_id'], $build_id, 'New build_id was generated'); + $this->assertTrue(empty($original['form']['#poisoned']), 'Original form structure was preserved'); + $this->assertTrue(empty($original['form_state']['poisoned']), 'Original form state was preserved'); } } diff --git a/web/core/modules/system/tests/src/Functional/Mail/MailTest.php b/web/core/modules/system/tests/src/Functional/Mail/MailTest.php index e8accddb6f4e2f2bd6fbec57e6f082e1a3c4e7f0..ef59d0128d142f08dbeff9859654c697376787e0 100644 --- a/web/core/modules/system/tests/src/Functional/Mail/MailTest.php +++ b/web/core/modules/system/tests/src/Functional/Mail/MailTest.php @@ -2,8 +2,13 @@ namespace Drupal\Tests\system\Functional\Mail; +use Drupal\Component\Utility\Random; use Drupal\Component\Utility\Unicode; +use Drupal\Core\Mail\MailFormatHelper; use Drupal\Core\Mail\Plugin\Mail\TestMailCollector; +use Drupal\Core\Render\Markup; +use Drupal\Core\Url; +use Drupal\file\Entity\File; use Drupal\Tests\BrowserTestBase; use Drupal\system_mail_failure_test\Plugin\Mail\TestPhpMailFailure; @@ -19,7 +24,7 @@ class MailTest extends BrowserTestBase { * * @var array */ - public static $modules = ['simpletest', 'system_mail_failure_test']; + public static $modules = ['simpletest', 'system_mail_failure_test', 'mail_html_test', 'file', 'image']; /** * Assert that the pluggable mail system is functional. @@ -102,6 +107,206 @@ public function testFromAndReplyToHeader() { $this->assertEquals('Drépal this is a very long test sentence to te <simpletest@example.com>', Unicode::mimeHeaderDecode($sent_message['headers']['From']), 'From header is correctly encoded.'); $this->assertFalse(isset($sent_message['headers']['Reply-to']), 'Message reply-to is not set if not specified.'); $this->assertFalse(isset($sent_message['headers']['Errors-To']), 'Errors-to header must not be set, it is deprecated.'); + + // Test RFC-2822 rules are respected for 'display-name' component of + // 'From:' header. Specials characters are not allowed, so randomly add one + // of them to the site name and check the string is wrapped in quotes. Also + // hardcode some double-quotes and backslash to validate these are escaped + // properly too. + $specials = '()<>[]:;@\,."'; + $site_name = 'Drupal' . $specials[rand(0, strlen($specials) - 1)] . ' "si\te"'; + $this->config('system.site')->set('name', $site_name)->save(); + // Send an email and check that the From-header contains the site name + // within double-quotes. Also make sure double-quotes and "\" are escaped. + \Drupal::service('plugin.manager.mail')->mail('simpletest', 'from_test', 'from_test@example.com', $language); + $captured_emails = \Drupal::state()->get('system.test_mail_collector'); + $sent_message = end($captured_emails); + $escaped_site_name = str_replace(['\\', '"'], ['\\\\', '\\"'], $site_name); + $this->assertEquals('"' . $escaped_site_name . '" <simpletest@example.com>', $sent_message['headers']['From'], 'From header is correctly quoted.'); + + // Make sure display-name is not quoted nor escaped if part on an encoding. + $site_name = 'Drépal, "si\te"'; + $this->config('system.site')->set('name', $site_name)->save(); + // Send an email and check that the From-header contains the site name. + \Drupal::service('plugin.manager.mail')->mail('simpletest', 'from_test', 'from_test@example.com', $language); + $captured_emails = \Drupal::state()->get('system.test_mail_collector'); + $sent_message = end($captured_emails); + $this->assertEquals('=?UTF-8?B?RHLDqXBhbCwgInNpXHRlIg==?= <simpletest@example.com>', $sent_message['headers']['From'], 'From header is correctly encoded.'); + $this->assertEquals($site_name . ' <simpletest@example.com>', Unicode::mimeHeaderDecode($sent_message['headers']['From']), 'From header is correctly encoded.'); + } + + /** + * Checks that relative paths in mails are converted into absolute URLs. + */ + public function testConvertRelativeUrlsIntoAbsolute() { + $language_interface = \Drupal::languageManager()->getCurrentLanguage(); + + // Use the HTML compatible state system collector mail backend. + $this->config('system.mail')->set('interface.default', 'test_html_mail_collector')->save(); + + // Fetch the hostname and port for matching against. + $http_host = \Drupal::request()->getSchemeAndHttpHost(); + + // Random generator. + $random = new Random(); + + // One random tag name. + $tag_name = strtolower($random->name(8, TRUE)); + + // Test root relative urls. + foreach (['href', 'src'] as $attribute) { + // Reset the state variable that holds sent messages. + \Drupal::state()->set('system.test_mail_collector', []); + + $html = "<$tag_name $attribute=\"/root-relative\">root relative url in mail test</$tag_name>"; + $expected_html = "<$tag_name $attribute=\"{$http_host}/root-relative\">root relative url in mail test</$tag_name>"; + + // Prepare render array. + $render = ['#markup' => Markup::create($html)]; + + // Send a test message that simpletest_mail_alter should cancel. + \Drupal::service('plugin.manager.mail')->mail('mail_html_test', 'render_from_message_param', 'relative_url@example.com', $language_interface->getId(), ['message' => $render]); + // Retrieve sent message. + $captured_emails = \Drupal::state()->get('system.test_mail_collector'); + $sent_message = end($captured_emails); + + // Wrap the expected HTML and assert. + $expected_html = MailFormatHelper::wrapMail($expected_html); + $this->assertSame($expected_html, $sent_message['body'], "Asserting that {$attribute} is properly converted for mails."); + } + + // Test protocol relative urls. + foreach (['href', 'src'] as $attribute) { + // Reset the state variable that holds sent messages. + \Drupal::state()->set('system.test_mail_collector', []); + + $html = "<$tag_name $attribute=\"//example.com/protocol-relative\">protocol relative url in mail test</$tag_name>"; + $expected_html = "<$tag_name $attribute=\"//example.com/protocol-relative\">protocol relative url in mail test</$tag_name>"; + + // Prepare render array. + $render = ['#markup' => Markup::create($html)]; + + // Send a test message that simpletest_mail_alter should cancel. + \Drupal::service('plugin.manager.mail')->mail('mail_html_test', 'render_from_message_param', 'relative_url@example.com', $language_interface->getId(), ['message' => $render]); + // Retrieve sent message. + $captured_emails = \Drupal::state()->get('system.test_mail_collector'); + $sent_message = end($captured_emails); + + // Wrap the expected HTML and assert. + $expected_html = MailFormatHelper::wrapMail($expected_html); + $this->assertSame($expected_html, $sent_message['body'], "Asserting that {$attribute} is properly converted for mails."); + } + + // Test absolute urls. + foreach (['href', 'src'] as $attribute) { + // Reset the state variable that holds sent messages. + \Drupal::state()->set('system.test_mail_collector', []); + + $html = "<$tag_name $attribute=\"http://example.com/absolute\">absolute url in mail test</$tag_name>"; + $expected_html = "<$tag_name $attribute=\"http://example.com/absolute\">absolute url in mail test</$tag_name>"; + + // Prepare render array. + $render = ['#markup' => Markup::create($html)]; + + // Send a test message that simpletest_mail_alter should cancel. + \Drupal::service('plugin.manager.mail')->mail('mail_html_test', 'render_from_message_param', 'relative_url@example.com', $language_interface->getId(), ['message' => $render]); + // Retrieve sent message. + $captured_emails = \Drupal::state()->get('system.test_mail_collector'); + $sent_message = end($captured_emails); + + // Wrap the expected HTML and assert. + $expected_html = MailFormatHelper::wrapMail($expected_html); + $this->assertSame($expected_html, $sent_message['body'], "Asserting that {$attribute} is properly converted for mails."); + } + } + + /** + * Checks that mails built from render arrays contain absolute paths. + * + * By default Drupal uses relative paths for images and links. When sending + * emails, absolute paths should be used instead. + */ + public function testRenderedElementsUseAbsolutePaths() { + $language_interface = \Drupal::languageManager()->getCurrentLanguage(); + + // Use the HTML compatible state system collector mail backend. + $this->config('system.mail')->set('interface.default', 'test_html_mail_collector')->save(); + + // Fetch the hostname and port for matching against. + $http_host = \Drupal::request()->getSchemeAndHttpHost(); + + // Random generator. + $random = new Random(); + $image_name = $random->name(); + + // Create an image file. + $file = File::create(['uri' => "public://{$image_name}.png", 'filename' => "{$image_name}.png"]); + $file->save(); + + $base_path = base_path(); + + $path_pairs = [ + 'root relative' => [$file->getFileUri(), "{$http_host}{$base_path}{$this->publicFilesDirectory}/{$image_name}.png"], + 'protocol relative' => ['//example.com/image.png', '//example.com/image.png'], + 'absolute' => ['http://example.com/image.png', 'http://example.com/image.png'], + ]; + + // Test images. + foreach ($path_pairs as $test_type => $paths) { + list($input_path, $expected_path) = $paths; + + // Reset the state variable that holds sent messages. + \Drupal::state()->set('system.test_mail_collector', []); + + // Build the render array. + $render = [ + '#theme' => 'image', + '#uri' => $input_path, + ]; + $expected_html = "<img src=\"$expected_path\" alt=\"\" />"; + + // Send a test message that simpletest_mail_alter should cancel. + \Drupal::service('plugin.manager.mail')->mail('mail_html_test', 'render_from_message_param', 'relative_url@example.com', $language_interface->getId(), ['message' => $render]); + // Retrieve sent message. + $captured_emails = \Drupal::state()->get('system.test_mail_collector'); + $sent_message = end($captured_emails); + + // Wrap the expected HTML and assert. + $expected_html = MailFormatHelper::wrapMail($expected_html); + $this->assertSame($expected_html, $sent_message['body'], "Asserting that {$test_type} paths are converted properly."); + } + + // Test links. + $path_pairs = [ + 'root relative' => [Url::fromUserInput('/path/to/something'), "{$http_host}{$base_path}path/to/something"], + 'protocol relative' => [Url::fromUri('//example.com/image.png'), '//example.com/image.png'], + 'absolute' => [Url::fromUri('http://example.com/image.png'), 'http://example.com/image.png'], + ]; + + foreach ($path_pairs as $paths) { + list($input_path, $expected_path) = $paths; + + // Reset the state variable that holds sent messages. + \Drupal::state()->set('system.test_mail_collector', []); + + // Build the render array. + $render = [ + '#title' => 'Link', + '#type' => 'link', + '#url' => $input_path, + ]; + $expected_html = "<a href=\"$expected_path\">Link</a>"; + + // Send a test message that simpletest_mail_alter should cancel. + \Drupal::service('plugin.manager.mail')->mail('mail_html_test', 'render_from_message_param', 'relative_url@example.com', $language_interface->getId(), ['message' => $render]); + // Retrieve sent message. + $captured_emails = \Drupal::state()->get('system.test_mail_collector'); + $sent_message = end($captured_emails); + + // Wrap the expected HTML and assert. + $expected_html = MailFormatHelper::wrapMail($expected_html); + $this->assertSame($expected_html, $sent_message['body']); + } } } diff --git a/web/core/modules/system/tests/src/Functional/Menu/BreadcrumbFrontCacheContextsTest.php b/web/core/modules/system/tests/src/Functional/Menu/BreadcrumbFrontCacheContextsTest.php new file mode 100644 index 0000000000000000000000000000000000000000..90272094672355c6b6246856b3b7e9dc64670ccf --- /dev/null +++ b/web/core/modules/system/tests/src/Functional/Menu/BreadcrumbFrontCacheContextsTest.php @@ -0,0 +1,91 @@ +<?php + +namespace Drupal\Tests\system\Functional\Menu; + +use Drupal\Tests\BrowserTestBase; + +/** + * Tests breadcrumbs functionality. + * + * @group Menu + */ +class BreadcrumbFrontCacheContextsTest extends BrowserTestBase { + + use AssertBreadcrumbTrait; + + /** + * Modules to enable. + * + * @var array + */ + public static $modules = [ + 'block', + 'node', + 'path', + 'user', + ]; + + /** + * A test node with path alias. + * + * @var \Drupal\node\NodeInterface + */ + protected $nodeWithAlias; + + /** + * {@inheritdoc} + */ + protected function setUp() { + parent::setUp(); + + $this->drupalPlaceBlock('system_breadcrumb_block'); + + $user = $this->drupalCreateUser(); + + $this->drupalCreateContentType([ + 'type' => 'page', + ]); + + // Create a node for front page. + $node_front = $this->drupalCreateNode([ + 'uid' => $user->id(), + ]); + + // Create a node with a random alias. + $this->nodeWithAlias = $this->drupalCreateNode([ + 'uid' => $user->id(), + 'type' => 'page', + 'path' => '/' . $this->randomMachineName(), + ]); + + // Configure 'node' as front page. + $this->config('system.site') + ->set('page.front', '/node/' . $node_front->id()) + ->save(); + + \Drupal::cache('render')->deleteAll(); + } + + /** + * Validate that breadcrumb markup get the right cache contexts. + * + * Checking that the breadcrumb will be printed on node canonical routes even + * if it was rendered for the <front> page first. + */ + public function testBreadcrumbsFrontPageCache() { + // Hit front page first as anonymous user with 'cold' render cache. + $this->drupalGet('<front>'); + $web_assert = $this->assertSession(); + // Verify that no breadcrumb block presents. + $web_assert->elementNotExists('css', '.block-system-breadcrumb-block'); + + // Verify that breadcrumb appears correctly for the test content + // (which is not set as front page). + $this->drupalGet($this->nodeWithAlias->path->alias); + $breadcrumbs = $this->assertSession()->elementExists('css', '.block-system-breadcrumb-block'); + $crumbs = $breadcrumbs->findAll('css', 'ol li'); + $this->assertTrue(count($crumbs) === 1); + $this->assertTrue($crumbs[0]->getText() === 'Home'); + } + +} diff --git a/web/core/modules/system/tests/src/Functional/Menu/MenuAccessTest.php b/web/core/modules/system/tests/src/Functional/Menu/MenuAccessTest.php index 10af396a6d74497d4af5a30e9f2ae752de42d63c..7d3c0a4b3ddd5a2bfe89abf714d673c72caafd02 100644 --- a/web/core/modules/system/tests/src/Functional/Menu/MenuAccessTest.php +++ b/web/core/modules/system/tests/src/Functional/Menu/MenuAccessTest.php @@ -38,7 +38,7 @@ public function testMenuBlockLinksAccessCheck() { // Test that there's link rendered on the route. $this->drupalGet('menu_test_access_check_session'); $this->assertLink('Test custom route access check'); - // Page still accessible but thre should not be menu link. + // Page is still accessible but there should be no menu link. $this->drupalGet('menu_test_access_check_session'); $this->assertResponse(200); $this->assertNoLink('Test custom route access check'); diff --git a/web/core/modules/system/src/Tests/Page/DefaultMetatagsTest.php b/web/core/modules/system/tests/src/Functional/Page/DefaultMetatagsTest.php similarity index 74% rename from web/core/modules/system/src/Tests/Page/DefaultMetatagsTest.php rename to web/core/modules/system/tests/src/Functional/Page/DefaultMetatagsTest.php index e0228efad78970b3bd854b3d4c8a0f71ad8c4c49..d020368c525b84e88b9f05b6cc52c10cae9433df 100644 --- a/web/core/modules/system/src/Tests/Page/DefaultMetatagsTest.php +++ b/web/core/modules/system/tests/src/Functional/Page/DefaultMetatagsTest.php @@ -1,15 +1,15 @@ <?php -namespace Drupal\system\Tests\Page; +namespace Drupal\Tests\system\Functional\Page; -use Drupal\simpletest\WebTestBase; +use Drupal\Tests\BrowserTestBase; /** * Tests default HTML metatags on a page. * * @group Page */ -class DefaultMetatagsTest extends WebTestBase { +class DefaultMetatagsTest extends BrowserTestBase { /** * Tests meta tags. @@ -22,7 +22,7 @@ public function testMetaTag() { // Ensure that the charset one is the first metatag. $result = $this->xpath('//meta'); - $this->assertEqual((string) $result[0]->attributes()->charset, 'utf-8'); + $this->assertEqual((string) $result[0]->getAttribute('charset'), 'utf-8'); // Ensure that the shortcut icon is on the page. $result = $this->xpath('//link[@rel = "shortcut icon"]'); diff --git a/web/core/modules/system/src/Tests/Pager/PagerTest.php b/web/core/modules/system/tests/src/Functional/Pager/PagerTest.php similarity index 80% rename from web/core/modules/system/src/Tests/Pager/PagerTest.php rename to web/core/modules/system/tests/src/Functional/Pager/PagerTest.php index 71413f283e536951e194031099b10886a9b43dfc..e0d5c543446201ca02a6b280cd8eb0380f931245 100644 --- a/web/core/modules/system/src/Tests/Pager/PagerTest.php +++ b/web/core/modules/system/tests/src/Functional/Pager/PagerTest.php @@ -1,15 +1,19 @@ <?php -namespace Drupal\system\Tests\Pager; +namespace Drupal\Tests\system\Functional\Pager; -use Drupal\simpletest\WebTestBase; +use Behat\Mink\Element\NodeElement; +use Drupal\Tests\BrowserTestBase; +use Drupal\Tests\system\Functional\Cache\AssertPageCacheContextsAndTagsTrait; /** * Tests pager functionality. * * @group Pager */ -class PagerTest extends WebTestBase { +class PagerTest extends BrowserTestBase { + + use AssertPageCacheContextsAndTagsTrait; /** * Modules to enable. @@ -58,9 +62,9 @@ public function testActiveClass() { // Verify last page. $elements = $this->xpath('//li[contains(@class, :class)]/a', [':class' => 'pager__item--last']); - preg_match('@page=(\d+)@', $elements[0]['href'], $matches); + preg_match('@page=(\d+)@', $elements[0]->getAttribute('href'), $matches); $current_page = (int) $matches[1]; - $this->drupalGet($GLOBALS['base_root'] . parse_url($this->getUrl())['path'] . $elements[0]['href'], ['external' => TRUE]); + $this->drupalGet($GLOBALS['base_root'] . parse_url($this->getUrl())['path'] . $elements[0]->getAttribute('href'), ['external' => TRUE]); $this->assertPagerItems($current_page); } @@ -76,15 +80,18 @@ public function testPagerQueryParametersAndCacheContext() { // Go to last page, the count of pager calls need to go to 1. $elements = $this->xpath('//li[contains(@class, :class)]/a', [':class' => 'pager__item--last']); - $this->drupalGet($this->getAbsoluteUrl($elements[0]['href'])); + $elements[0]->click(); $this->assertText(t('Pager calls: 1'), 'First link call to pager shows 1 calls.'); $this->assertText('[url.query_args.pagers:0]=0.60'); $this->assertCacheContext('url.query_args'); + // Reset counter to 0. + $this->drupalGet('pager-test/query-parameters'); // Go back to first page, the count of pager calls need to go to 2. + $elements = $this->xpath('//li[contains(@class, :class)]/a', [':class' => 'pager__item--last']); + $elements[0]->click(); $elements = $this->xpath('//li[contains(@class, :class)]/a', [':class' => 'pager__item--first']); - $this->drupalGet($this->getAbsoluteUrl($elements[0]['href'])); - $this->drupalGet($GLOBALS['base_root'] . parse_url($this->getUrl())['path'] . $elements[0]['href'], ['external' => TRUE]); + $elements[0]->click(); $this->assertText(t('Pager calls: 2'), 'Second link call to pager shows 2 calls.'); $this->assertText('[url.query_args.pagers:0]=0.0'); $this->assertCacheContext('url.query_args'); @@ -167,7 +174,7 @@ public function testMultiplePagers() { $this->drupalGet($GLOBALS['base_root'] . parse_url($this->getUrl())['path'] . $input_query, ['external' => TRUE]); foreach ([0, 1, 4] as $pager_element) { $active_page = $this->cssSelect("div.test-pager-{$pager_element} ul.pager__items li.is-active:contains('{$data['expected_page'][$pager_element]}')"); - $destination = str_replace('%2C', ',', $active_page[0]->a['href'][0]->__toString()); + $destination = str_replace('%2C', ',', $active_page[0]->find('css', 'a')->getAttribute('href')); $this->assertEqual($destination, $data['expected_query']); } } @@ -232,16 +239,18 @@ protected function assertPagerItems($current_page) { if ($current_page == $page) { $this->assertClass($element, 'is-active', 'Element for current page has .is-active class.'); - $this->assertTrue($element->a, 'Element for current page has link.'); - $destination = $element->a['href'][0]->__toString(); + $link = $element->find('css', 'a'); + $this->assertTrue($link, 'Element for current page has link.'); + $destination = $link->getAttribute('href'); // URL query string param is 0-indexed. $this->assertEqual($destination, '?page=' . ($page - 1)); } else { $this->assertNoClass($element, 'is-active', "Element for page $page has no .is-active class."); $this->assertClass($element, 'pager__item', "Element for page $page has .pager__item class."); - $this->assertTrue($element->a, "Link to page $page found."); - $destination = $element->a['href'][0]->__toString(); + $link = $element->find('css', 'a'); + $this->assertTrue($link, "Link to page $page found."); + $destination = $link->getAttribute('href'); $this->assertEqual($destination, '?page=' . ($page - 1)); } unset($elements[--$page]); @@ -252,32 +261,36 @@ protected function assertPagerItems($current_page) { // Verify first/previous and next/last items and links. if (isset($first)) { $this->assertClass($first, 'pager__item--first', 'Element for first page has .pager__item--first class.'); - $this->assertTrue($first->a, 'Link to first page found.'); - $this->assertNoClass($first->a, 'is-active', 'Link to first page is not active.'); - $destination = $first->a['href'][0]->__toString(); + $link = $first->find('css', 'a'); + $this->assertTrue($link, 'Link to first page found.'); + $this->assertNoClass($link, 'is-active', 'Link to first page is not active.'); + $destination = $link->getAttribute('href'); $this->assertEqual($destination, '?page=0'); } if (isset($previous)) { $this->assertClass($previous, 'pager__item--previous', 'Element for first page has .pager__item--previous class.'); - $this->assertTrue($previous->a, 'Link to previous page found.'); - $this->assertNoClass($previous->a, 'is-active', 'Link to previous page is not active.'); - $destination = $previous->a['href'][0]->__toString(); + $link = $previous->find('css', 'a'); + $this->assertTrue($link, 'Link to previous page found.'); + $this->assertNoClass($link, 'is-active', 'Link to previous page is not active.'); + $destination = $link->getAttribute('href'); // URL query string param is 0-indexed, $current_page is 1-indexed. $this->assertEqual($destination, '?page=' . ($current_page - 2)); } if (isset($next)) { $this->assertClass($next, 'pager__item--next', 'Element for next page has .pager__item--next class.'); - $this->assertTrue($next->a, 'Link to next page found.'); - $this->assertNoClass($next->a, 'is-active', 'Link to next page is not active.'); - $destination = $next->a['href'][0]->__toString(); + $link = $next->find('css', 'a'); + $this->assertTrue($link, 'Link to next page found.'); + $this->assertNoClass($link, 'is-active', 'Link to next page is not active.'); + $destination = $link->getAttribute('href'); // URL query string param is 0-indexed, $current_page is 1-indexed. $this->assertEqual($destination, '?page=' . $current_page); } if (isset($last)) { + $link = $last->find('css', 'a'); $this->assertClass($last, 'pager__item--last', 'Element for last page has .pager__item--last class.'); - $this->assertTrue($last->a, 'Link to last page found.'); - $this->assertNoClass($last->a, 'is-active', 'Link to last page is not active.'); - $destination = $last->a['href'][0]->__toString(); + $this->assertTrue($link, 'Link to last page found.'); + $this->assertNoClass($link, 'is-active', 'Link to last page is not active.'); + $destination = $link->getAttribute('href'); // URL query string param is 0-indexed. $this->assertEqual($destination, '?page=' . ($total_pages - 1)); } @@ -286,35 +299,35 @@ protected function assertPagerItems($current_page) { /** * Asserts that an element has a given class. * - * @param \SimpleXMLElement $element + * @param \Behat\Mink\Element\NodeElement $element * The element to test. * @param string $class * The class to assert. * @param string $message * (optional) A verbose message to output. */ - protected function assertClass(\SimpleXMLElement $element, $class, $message = NULL) { + protected function assertClass(NodeElement $element, $class, $message = NULL) { if (!isset($message)) { $message = "Class .$class found."; } - $this->assertTrue(strpos($element['class'], $class) !== FALSE, $message); + $this->assertTrue($element->hasClass($class) !== FALSE, $message); } /** * Asserts that an element does not have a given class. * - * @param \SimpleXMLElement $element + * @param \Behat\Mink\Element\NodeElement $element * The element to test. * @param string $class * The class to assert. * @param string $message * (optional) A verbose message to output. */ - protected function assertNoClass(\SimpleXMLElement $element, $class, $message = NULL) { + protected function assertNoClass(NodeElement $element, $class, $message = NULL) { if (!isset($message)) { $message = "Class .$class not found."; } - $this->assertTrue(strpos($element['class'], $class) === FALSE, $message); + $this->assertTrue($element->hasClass($class) === FALSE, $message); } } diff --git a/web/core/modules/system/src/Tests/Render/HtmlResponseAttachmentsTest.php b/web/core/modules/system/tests/src/Functional/Render/HtmlResponseAttachmentsTest.php similarity index 83% rename from web/core/modules/system/src/Tests/Render/HtmlResponseAttachmentsTest.php rename to web/core/modules/system/tests/src/Functional/Render/HtmlResponseAttachmentsTest.php index 6060fcc30caf3b78a9060fcd641274b7ff70d7dc..2bd6d289c6f807817e78c7587aa150e1076e3181 100644 --- a/web/core/modules/system/src/Tests/Render/HtmlResponseAttachmentsTest.php +++ b/web/core/modules/system/tests/src/Functional/Render/HtmlResponseAttachmentsTest.php @@ -1,15 +1,15 @@ <?php -namespace Drupal\system\Tests\Render; +namespace Drupal\Tests\system\Functional\Render; -use Drupal\simpletest\WebTestBase; +use Drupal\Tests\BrowserTestBase; /** * Functional tests for HtmlResponseAttachmentsProcessor. * * @group Render */ -class HtmlResponseAttachmentsTest extends WebTestBase { +class HtmlResponseAttachmentsTest extends BrowserTestBase { /** * Modules to enable. @@ -61,7 +61,7 @@ public function testAttachments() { '</foo?bar=<baz>&baz=false>; rel="alternate"', '</foo/bar>; hreflang="nl"; rel="alternate"', ]; - $this->assertEqual($this->drupalGetHeader('link'), implode(',', $expected_link_headers)); + $this->assertEqual($this->getSession()->getResponseHeaders()['Link'], $expected_link_headers); } /** @@ -93,9 +93,10 @@ public function testRenderCachedBlock() { * Helper function to make assertions about added HTTP headers. */ protected function assertTeapotHeaders() { - $this->assertHeader('X-Test-Teapot', 'Teapot Mode Active'); - $this->assertHeader('X-Test-Teapot-Replace', 'Teapot replaced'); - $this->assertHeader('X-Test-Teapot-No-Replace', 'This value is not replaced,This one is added'); + $headers = $this->getSession()->getResponseHeaders(); + $this->assertEquals($headers['X-Test-Teapot'], ['Teapot Mode Active']); + $this->assertEquals($headers['X-Test-Teapot-Replace'], ['Teapot replaced']); + $this->assertEquals($headers['X-Test-Teapot-No-Replace'], ['This value is not replaced', 'This one is added']); } /** @@ -117,8 +118,8 @@ protected function assertFeed() { $this->fail('Unable to find feed link.'); } else { - foreach ($test_meta->attributes() as $attribute => $value) { - $this->assertEqual($value, $test_meta_attributes[$attribute]); + foreach ($test_meta_attributes as $attribute => $value) { + $this->assertEquals($value, $test_meta->getAttribute($attribute)); } } } @@ -136,8 +137,7 @@ protected function assertHead() { $this->fail('Unable to find the head meta.'); } else { - $test_meta_attributes = $test_meta->attributes(); - $this->assertEqual($test_meta_attributes['test-attribute'], 'testvalue'); + $this->assertEqual($test_meta->getAttribute('test-attribute'), 'testvalue'); } } diff --git a/web/core/modules/system/src/Tests/Render/UrlBubbleableMetadataBubblingTest.php b/web/core/modules/system/tests/src/Functional/Render/UrlBubbleableMetadataBubblingTest.php similarity index 72% rename from web/core/modules/system/src/Tests/Render/UrlBubbleableMetadataBubblingTest.php rename to web/core/modules/system/tests/src/Functional/Render/UrlBubbleableMetadataBubblingTest.php index a55037f74b4d53874a2652c8f1796149d0a0a6d4..37d20ce3b83a03043820f27ccbf90bf6228bbe99 100644 --- a/web/core/modules/system/src/Tests/Render/UrlBubbleableMetadataBubblingTest.php +++ b/web/core/modules/system/tests/src/Functional/Render/UrlBubbleableMetadataBubblingTest.php @@ -1,16 +1,19 @@ <?php -namespace Drupal\system\Tests\Render; +namespace Drupal\Tests\system\Functional\Render; use Drupal\Core\Url; -use Drupal\simpletest\WebTestBase; +use Drupal\Tests\BrowserTestBase; +use Drupal\Tests\system\Functional\Cache\AssertPageCacheContextsAndTagsTrait; /** * Tests that URL bubbleable metadata is correctly bubbled. * * @group Render */ -class UrlBubbleableMetadataBubblingTest extends WebTestBase { +class UrlBubbleableMetadataBubblingTest extends BrowserTestBase { + + use AssertPageCacheContextsAndTagsTrait; /** * Modules to enable. @@ -24,7 +27,6 @@ class UrlBubbleableMetadataBubblingTest extends WebTestBase { */ protected function setUp() { parent::setUp(); - $this->dumpHeaders = TRUE; } /** diff --git a/web/core/modules/system/src/Tests/Routing/DestinationTest.php b/web/core/modules/system/tests/src/Functional/Routing/DestinationTest.php similarity index 76% rename from web/core/modules/system/src/Tests/Routing/DestinationTest.php rename to web/core/modules/system/tests/src/Functional/Routing/DestinationTest.php index d959c7ad4aad806951357d14aa3d860817ea6ceb..109d8000074d954fad337b36b107bb6b585446c7 100644 --- a/web/core/modules/system/src/Tests/Routing/DestinationTest.php +++ b/web/core/modules/system/tests/src/Functional/Routing/DestinationTest.php @@ -1,9 +1,9 @@ <?php -namespace Drupal\system\Tests\Routing; +namespace Drupal\Tests\system\Functional\Routing; use Drupal\Core\Url; -use Drupal\simpletest\WebTestBase; +use Drupal\Tests\BrowserTestBase; /** * Tests for $_GET['destination'] and $_REQUEST['destination'] validation. @@ -15,7 +15,7 @@ * * @group Routing */ -class DestinationTest extends WebTestBase { +class DestinationTest extends BrowserTestBase { /** * {@inheritdoc} @@ -26,6 +26,9 @@ class DestinationTest extends WebTestBase { * Tests that $_GET/$_REQUEST['destination'] only contain internal URLs. */ public function testDestination() { + $http_client = $this->getHttpClient(); + $session = $this->getSession(); + $test_cases = [ [ 'input' => 'node', @@ -61,10 +64,12 @@ public function testDestination() { foreach ($test_cases as $test_case) { // Test $_GET['destination']. $this->drupalGet('system-test/get-destination', ['query' => ['destination' => $test_case['input']]]); - $this->assertIdentical($test_case['output'], $this->getRawContent(), $test_case['message']); + $this->assertIdentical($test_case['output'], $session->getPage()->getContent(), $test_case['message']); // Test $_REQUEST['destination']. - $post_output = $this->drupalPost('system-test/request-destination', '*', ['destination' => $test_case['input']]); - $this->assertIdentical($test_case['output'], $post_output, $test_case['message']); + $post_output = $http_client->request('POST', $this->buildUrl('system-test/request-destination'), [ + 'form_params' => ['destination' => $test_case['input']], + ]); + $this->assertIdentical($test_case['output'], (string) $post_output->getBody(), $test_case['message']); } // Make sure that 404 pages do not populate $_GET['destination'] with @@ -72,7 +77,7 @@ public function testDestination() { \Drupal::configFactory()->getEditable('system.site')->set('page.404', '/system-test/get-destination')->save(); $this->drupalGet('http://example.com', ['external' => FALSE]); $this->assertResponse(404); - $this->assertIdentical(Url::fromRoute('<front>')->toString(), $this->getRawContent(), 'External URL is not allowed on 404 pages.'); + $this->assertIdentical(Url::fromRoute('<front>')->toString(), $session->getPage()->getContent(), 'External URL is not allowed on 404 pages.'); } } diff --git a/web/core/modules/system/src/Tests/Routing/RouterTest.php b/web/core/modules/system/tests/src/Functional/Routing/RouterTest.php similarity index 79% rename from web/core/modules/system/src/Tests/Routing/RouterTest.php rename to web/core/modules/system/tests/src/Functional/Routing/RouterTest.php index 8d7c43e86a883a2b06167a3a9d27dacb615ce771..0cb10bd80f39e894a89337e84e9a6803334bd228 100644 --- a/web/core/modules/system/src/Tests/Routing/RouterTest.php +++ b/web/core/modules/system/tests/src/Functional/Routing/RouterTest.php @@ -1,11 +1,11 @@ <?php -namespace Drupal\system\Tests\Routing; +namespace Drupal\Tests\system\Functional\Routing; use Drupal\Core\Cache\Cache; use Drupal\Core\EventSubscriber\MainContentViewSubscriber; use Drupal\Core\Language\LanguageInterface; -use Drupal\simpletest\WebTestBase; +use Drupal\Tests\BrowserTestBase; use Symfony\Component\Routing\Exception\RouteNotFoundException; use Drupal\Core\Url; @@ -14,7 +14,7 @@ * * @group Routing */ -class RouterTest extends WebTestBase { +class RouterTest extends BrowserTestBase { /** * Modules to enable. @@ -34,69 +34,72 @@ public function testFinishResponseSubscriber() { $this->drupalGet('router_test/test1'); $this->assertRaw('test1', 'The correct string was returned because the route was successful.'); // Check expected headers from FinishResponseSubscriber. - $headers = $this->drupalGetHeaders(); - $this->assertEqual($headers['x-ua-compatible'], 'IE=edge'); - $this->assertEqual($headers['content-language'], 'en'); - $this->assertEqual($headers['x-content-type-options'], 'nosniff'); - $this->assertEqual($headers['x-frame-options'], 'SAMEORIGIN'); + $headers = $this->getSession()->getResponseHeaders(); + + $this->assertEquals($headers['X-UA-Compatible'], ['IE=edge']); + $this->assertEquals($headers['Content-language'], ['en']); + $this->assertEquals($headers['X-Content-Type-Options'], ['nosniff']); + $this->assertEquals($headers['X-Frame-Options'], ['SAMEORIGIN']); $this->drupalGet('router_test/test2'); $this->assertRaw('test2', 'The correct string was returned because the route was successful.'); // Check expected headers from FinishResponseSubscriber. $headers = $this->drupalGetHeaders(); - $this->assertEqual($headers['x-drupal-cache-contexts'], implode(' ', $expected_cache_contexts)); - $this->assertEqual($headers['x-drupal-cache-tags'], 'config:user.role.anonymous http_response rendered'); + $this->assertEqual($headers['X-Drupal-Cache-Contexts'], [implode(' ', $expected_cache_contexts)]); + $this->assertEqual($headers['X-Drupal-Cache-Tags'], ['config:user.role.anonymous http_response rendered']); // Confirm that the page wrapping is being added, so we're not getting a // raw body returned. $this->assertRaw('</html>', 'Page markup was found.'); // In some instances, the subrequest handling may get confused and render // a page inception style. This test verifies that is not happening. - $this->assertNoPattern('#</body>.*</body>#s', 'There was no double-page effect from a misrendered subrequest.'); + $this->assertSession()->responseNotMatches('#</body>.*</body>#s', 'There was no double-page effect from a misrendered subrequest.'); // Confirm that route-level access check's cacheability is applied to the // X-Drupal-Cache-Contexts and X-Drupal-Cache-Tags headers. // 1. controller result: render array, globally cacheable route access. $this->drupalGet('router_test/test18'); $headers = $this->drupalGetHeaders(); - $this->assertEqual($headers['x-drupal-cache-contexts'], implode(' ', Cache::mergeContexts($renderer_required_cache_contexts, ['url']))); - $this->assertEqual($headers['x-drupal-cache-tags'], 'config:user.role.anonymous foo http_response rendered'); + $this->assertEqual($headers['X-Drupal-Cache-Contexts'], [implode(' ', Cache::mergeContexts($renderer_required_cache_contexts, ['url']))]); + $this->assertEqual($headers['X-Drupal-Cache-Tags'], ['config:user.role.anonymous foo http_response rendered']); // 2. controller result: render array, per-role cacheable route access. $this->drupalGet('router_test/test19'); $headers = $this->drupalGetHeaders(); - $this->assertEqual($headers['x-drupal-cache-contexts'], implode(' ', Cache::mergeContexts($renderer_required_cache_contexts, ['url', 'user.roles']))); - $this->assertEqual($headers['x-drupal-cache-tags'], 'config:user.role.anonymous foo http_response rendered'); + $this->assertEqual($headers['X-Drupal-Cache-Contexts'], [implode(' ', Cache::mergeContexts($renderer_required_cache_contexts, ['url', 'user.roles']))]); + $this->assertEqual($headers['X-Drupal-Cache-Tags'], ['config:user.role.anonymous foo http_response rendered']); // 3. controller result: Response object, globally cacheable route access. $this->drupalGet('router_test/test1'); $headers = $this->drupalGetHeaders(); - $this->assertFalse(isset($headers['x-drupal-cache-contexts'])); - $this->assertFalse(isset($headers['x-drupal-cache-tags'])); + $this->assertFalse(isset($headers['X-Drupal-Cache-Contexts'])); + $this->assertFalse(isset($headers['X-Drupal-Cache-Tags'])); // 4. controller result: Response object, per-role cacheable route access. $this->drupalGet('router_test/test20'); $headers = $this->drupalGetHeaders(); - $this->assertFalse(isset($headers['x-drupal-cache-contexts'])); - $this->assertFalse(isset($headers['x-drupal-cache-tags'])); + $this->assertFalse(isset($headers['X-Drupal-Cache-Contexts'])); + $this->assertFalse(isset($headers['X-Drupal-Cache-Tags'])); // 5. controller result: CacheableResponse object, globally cacheable route access. $this->drupalGet('router_test/test21'); $headers = $this->drupalGetHeaders(); - $this->assertEqual($headers['x-drupal-cache-contexts'], ''); - $this->assertEqual($headers['x-drupal-cache-tags'], 'http_response'); + $this->assertEqual($headers['X-Drupal-Cache-Contexts'], ['']); + $this->assertEqual($headers['X-Drupal-Cache-Tags'], ['http_response']); // 6. controller result: CacheableResponse object, per-role cacheable route access. $this->drupalGet('router_test/test22'); $headers = $this->drupalGetHeaders(); - $this->assertEqual($headers['x-drupal-cache-contexts'], 'user.roles'); - $this->assertEqual($headers['x-drupal-cache-tags'], 'http_response'); + $this->assertEqual($headers['X-Drupal-Cache-Contexts'], ['user.roles']); + $this->assertEqual($headers['X-Drupal-Cache-Tags'], ['http_response']); // Finally, verify that the X-Drupal-Cache-Contexts and X-Drupal-Cache-Tags // headers are not sent when their container parameter is set to FALSE. $this->drupalGet('router_test/test18'); $headers = $this->drupalGetHeaders(); - $this->assertTrue(isset($headers['x-drupal-cache-contexts'])); - $this->assertTrue(isset($headers['x-drupal-cache-tags'])); - $this->setHttpResponseDebugCacheabilityHeaders(FALSE); + $this->assertTrue(isset($headers['X-Drupal-Cache-Contexts'])); + $this->assertTrue(isset($headers['X-Drupal-Cache-Tags'])); + $this->setContainerParameter('http.response.debug_cacheability_headers', FALSE); + $this->rebuildContainer(); + $this->resetAll(); $this->drupalGet('router_test/test18'); $headers = $this->drupalGetHeaders(); - $this->assertFalse(isset($headers['x-drupal-cache-contexts'])); - $this->assertFalse(isset($headers['x-drupal-cache-tags'])); + $this->assertFalse(isset($headers['X-Drupal-Cache-Contexts'])); + $this->assertFalse(isset($headers['X-Drupal-Cache-Tags'])); } /** @@ -145,7 +148,7 @@ public function testControllerPlaceholders() { // In some instances, the subrequest handling may get confused and render // a page inception style. This test verifies that is not happening. - $this->assertNoPattern('#</body>.*</body>#s', 'There was no double-page effect from a misrendered subrequest.'); + $this->assertSession()->responseNotMatches('#</body>.*</body>#s', 'There was no double-page effect from a misrendered subrequest.'); } /** @@ -162,7 +165,7 @@ public function testControllerPlaceholdersDefaultValues() { // In some instances, the subrequest handling may get confused and render // a page inception style. This test verifies that is not happening. - $this->assertNoPattern('#</body>.*</body>#s', 'There was no double-page effect from a misrendered subrequest.'); + $this->assertSession()->responseNotMatches('#</body>.*</body>#s', 'There was no double-page effect from a misrendered subrequest.'); } /** @@ -179,7 +182,7 @@ public function testControllerPlaceholdersDefaultValuesProvided() { // In some instances, the subrequest handling may get confused and render // a page inception style. This test verifies that is not happening. - $this->assertNoPattern('#</body>.*</body>#s', 'There was no double-page effect from a misrendered subrequest.'); + $this->assertSession()->responseNotMatches('#</body>.*</body>#s', 'There was no double-page effect from a misrendered subrequest.'); } /** @@ -208,7 +211,7 @@ public function testControllerResolutionPage() { // In some instances, the subrequest handling may get confused and render // a page inception style. This test verifies that is not happening. - $this->assertNoPattern('#</body>.*</body>#s', 'There was no double-page effect from a misrendered subrequest.'); + $this->assertSession()->responseNotMatches('#</body>.*</body>#s', 'There was no double-page effect from a misrendered subrequest.'); } /** @@ -277,7 +280,9 @@ public function testUserAccount() { public function testControllerResolutionAjax() { // This will fail with a JSON parse error if the request is not routed to // The correct controller. - $this->drupalGetAjax('/router_test/test10'); + $options['query'][MainContentViewSubscriber::WRAPPER_FORMAT] = 'drupal_ajax'; + $headers[] = 'X-Requested-With: XMLHttpRequest'; + $this->drupalGet('/router_test/test10', $options, $headers); $this->assertEqual($this->drupalGetHeader('Content-Type'), 'application/json', 'Correct mime content type was returned'); @@ -311,21 +316,18 @@ public function testLeadingSlashes() { $request = $this->container->get('request_stack')->getCurrentRequest(); $url = $request->getUriForPath('//router_test/test1'); $this->drupalGet($url); - $this->assertEqual(1, $this->redirectCount, $url . " redirected to " . $this->url); $this->assertUrl($request->getUriForPath('/router_test/test1')); // It should not matter how many leading slashes are used and query strings // should be preserved. $url = $request->getUriForPath('/////////////////////////////////////////////////router_test/test1') . '?qs=test'; $this->drupalGet($url); - $this->assertEqual(1, $this->redirectCount, $url . " redirected to " . $this->url); $this->assertUrl($request->getUriForPath('/router_test/test1') . '?qs=test'); // Ensure that external URLs in destination query params are not redirected // to. $url = $request->getUriForPath('/////////////////////////////////////////////////router_test/test1') . '?qs=test&destination=http://www.example.com%5c@drupal8alt.test'; $this->drupalGet($url); - $this->assertEqual(1, $this->redirectCount, $url . " redirected to " . $this->url); $this->assertUrl($request->getUriForPath('/router_test/test1') . '?qs=test'); } diff --git a/web/core/modules/system/src/Tests/Session/SessionAuthenticationTest.php b/web/core/modules/system/tests/src/Functional/Session/SessionAuthenticationTest.php similarity index 77% rename from web/core/modules/system/src/Tests/Session/SessionAuthenticationTest.php rename to web/core/modules/system/tests/src/Functional/Session/SessionAuthenticationTest.php index ffdc08d1928974add2e740f055f51fcae9627615..10a35020e23eb78d770acfb4ddd9887b1eb5515d 100644 --- a/web/core/modules/system/src/Tests/Session/SessionAuthenticationTest.php +++ b/web/core/modules/system/tests/src/Functional/Session/SessionAuthenticationTest.php @@ -1,17 +1,17 @@ <?php -namespace Drupal\system\Tests\Session; +namespace Drupal\Tests\system\Functional\Session; use Drupal\Core\Url; -use Drupal\basic_auth\Tests\BasicAuthTestTrait; -use Drupal\simpletest\WebTestBase; +use Drupal\Tests\basic_auth\Traits\BasicAuthTestTrait; +use Drupal\Tests\BrowserTestBase; /** * Tests if sessions are correctly handled when a user authenticates. * * @group Session */ -class SessionAuthenticationTest extends WebTestBase { +class SessionAuthenticationTest extends BrowserTestBase { use BasicAuthTestTrait; @@ -52,20 +52,22 @@ public function testSessionFromBasicAuthenticationDoesNotLeak() { // Test that the route is not accessible as an anonymous user. $this->drupalGet($protected_url); + $session = $this->getSession(); $this->assertResponse(401, 'An anonymous user cannot access a route protected with basic authentication.'); // We should be able to access the route with basic authentication. - $this->basicAuthGet($protected_url, $this->user->getUsername(), $this->user->pass_raw); + $this->basicAuthGet($protected_url, $this->user->getAccountName(), $this->user->passRaw); $this->assertResponse(200, 'A route protected with basic authentication can be accessed by an authenticated user.'); // Check that the correct user is logged in. - $this->assertEqual($this->user->id(), json_decode($this->getRawContent())->user, 'The correct user is authenticated on a route with basic authentication.'); + $this->assertEqual($this->user->id(), json_decode($session->getPage()->getContent())->user, 'The correct user is authenticated on a route with basic authentication.'); + $session->restart(); // If we now try to access a page without basic authentication then we // should no longer be logged in. $this->drupalGet($unprotected_url); $this->assertResponse(200, 'An unprotected route can be accessed without basic authentication.'); - $this->assertFalse(json_decode($this->getRawContent())->user, 'The user is no longer authenticated after visiting a page without basic authentication.'); + $this->assertFalse(json_decode($session->getPage()->getContent())->user, 'The user is no longer authenticated after visiting a page without basic authentication.'); // If we access the protected page again without basic authentication we // should get 401 Unauthorized. @@ -113,20 +115,24 @@ public function testBasicAuthNoSession() { $no_cookie_url = Url::fromRoute('session_test.get_session_basic_auth'); // A route that is authorized with standard cookie authentication. - $cookie_url = '<front>'; + $cookie_url = 'user/login'; // If we authenticate with a third party authentication system then no // session cookie should be set, the third party system is responsible for // sustaining the session. - $this->basicAuthGet($no_cookie_url, $this->user->getUsername(), $this->user->pass_raw); + $this->basicAuthGet($no_cookie_url, $this->user->getAccountName(), $this->user->passRaw); $this->assertResponse(200, 'The user is successfully authenticated using basic authentication.'); - $this->assertFalse($this->drupalGetHeader('set-cookie', TRUE), 'No cookie is set on a route protected with basic authentication.'); + $this->assertEmpty($this->getSessionCookies()); + // Mink stores some information in the session that breaks the next check if + // not reset. + $this->getSession()->restart(); // On the other hand, authenticating using Cookie sets a cookie. - $edit = ['name' => $this->user->getUsername(), 'pass' => $this->user->pass_raw]; + $this->drupalGet($cookie_url); + $this->assertEmpty($this->getSessionCookies()); + $edit = ['name' => $this->user->getAccountName(), 'pass' => $this->user->passRaw]; $this->drupalPostForm($cookie_url, $edit, t('Log in')); - $this->assertResponse(200, 'The user is successfully authenticated using cookie authentication.'); - $this->assertTrue($this->drupalGetHeader('set-cookie', TRUE), 'A cookie is set on a route protected with cookie authentication.'); + $this->assertNotEmpty($this->getSessionCookies()); } } diff --git a/web/core/modules/system/src/Tests/Session/SessionTest.php b/web/core/modules/system/tests/src/Functional/Session/SessionTest.php similarity index 89% rename from web/core/modules/system/src/Tests/Session/SessionTest.php rename to web/core/modules/system/tests/src/Functional/Session/SessionTest.php index 0f219c5036b5c1c162008e0ff8f603cfb70536aa..f0ce98cef5eb7880aaed0b9998325629a1e7f793 100644 --- a/web/core/modules/system/src/Tests/Session/SessionTest.php +++ b/web/core/modules/system/tests/src/Functional/Session/SessionTest.php @@ -1,15 +1,15 @@ <?php -namespace Drupal\system\Tests\Session; +namespace Drupal\Tests\system\Functional\Session; -use Drupal\simpletest\WebTestBase; +use Drupal\Tests\BrowserTestBase; /** * Drupal session handling tests. * * @group Session */ -class SessionTest extends WebTestBase { +class SessionTest extends BrowserTestBase { /** * Modules to enable. @@ -36,12 +36,15 @@ public function testSessionSaveRegenerate() { $user = $this->drupalCreateUser(); // Enable sessions. - $this->sessionReset($user->id()); + $this->sessionReset(); - // Make sure the session cookie is set as HttpOnly. - $this->drupalLogin($user); + // Make sure the session cookie is set as HttpOnly. We can only test this in + // the header, with the test setup + // \GuzzleHttp\Cookie\SetCookie::getHttpOnly() always returns FALSE. + // Start a new session by setting a message. + $this->drupalGet('session-test/set-message'); + $this->assertSessionCookie(TRUE); $this->assertTrue(preg_match('/HttpOnly/i', $this->drupalGetHeader('Set-Cookie', TRUE)), 'Session cookie is set as HttpOnly.'); - $this->drupalLogout(); // Verify that the session is regenerated if a module calls exit // in hook_user_login(). @@ -49,15 +52,15 @@ public function testSessionSaveRegenerate() { $user->save(); $this->drupalGet('session-test/id'); $matches = []; - preg_match('/\s*session_id:(.*)\n/', $this->getRawContent(), $matches); + preg_match('/\s*session_id:(.*)\n/', $this->getSession()->getPage()->getContent(), $matches); $this->assertTrue(!empty($matches[1]), 'Found session ID before logging in.'); $original_session = $matches[1]; // We cannot use $this->drupalLogin($user); because we exit in // session_test_user_login() which breaks a normal assertion. $edit = [ - 'name' => $user->getUsername(), - 'pass' => $user->pass_raw, + 'name' => $user->getAccountName(), + 'pass' => $user->passRaw, ]; $this->drupalPostForm('user/login', $edit, t('Log in')); $this->drupalGet('user'); @@ -66,7 +69,7 @@ public function testSessionSaveRegenerate() { $this->drupalGet('session-test/id'); $matches = []; - preg_match('/\s*session_id:(.*)\n/', $this->getRawContent(), $matches); + preg_match('/\s*session_id:(.*)\n/', $this->getSession()->getPage()->getContent(), $matches); $this->assertTrue(!empty($matches[1]), 'Found session ID after logging in.'); $this->assertTrue($matches[1] != $original_session, 'Session ID changed after login.'); } @@ -91,14 +94,22 @@ public function testDataPersistence() { // properly, val_1 will still be set. $value_2 = $this->randomMachineName(); $this->drupalGet('session-test/no-set/' . $value_2); + $session = $this->getSession(); $this->assertText($value_2, 'The session value was correctly passed to session-test/no-set.', 'Session'); $this->drupalGet('session-test/get'); $this->assertText($value_1, 'Session data is not saved for drupal_save_session(FALSE).', 'Session'); // Switch browser cookie to anonymous user, then back to user 1. - $this->sessionReset(); - $this->sessionReset($user->id()); + $session_cookie_name = $this->getSessionName(); + $session_cookie_value = $session->getCookie($session_cookie_name); + $session->restart(); + $this->initFrontPage(); + // Session restart always resets all the cookies by design, so we need to + // add the old session cookie again. + $session->setCookie($session_cookie_name, $session_cookie_value); + $this->drupalGet('session-test/get'); $this->assertText($value_1, 'Session data persists through browser close.', 'Session'); + $this->mink->setDefaultSessionName('default'); // Logout the user and make sure the stored value no longer persists. $this->drupalLogout(); @@ -242,8 +253,6 @@ public function testSessionWrite() { $this->assertEqual($times4->timestamp, $times3->timestamp, 'Sessions table was not updated.'); // Force updating of users and sessions table once per second. - $this->settingsSet('session_write_interval', 0); - // Write that value also into the test settings.php file. $settings['settings']['session_write_interval'] = (object) [ 'value' => 0, 'required' => TRUE, @@ -270,8 +279,7 @@ public function testEmptySessionID() { // Send a blank sid in the session cookie, and the session should no longer // be valid. Closing the curl handler will stop the previous session ID // from persisting. - $this->curlClose(); - $this->additionalCurlOptions[CURLOPT_COOKIE] = rawurlencode($this->getSessionName()) . '=;'; + $this->mink->resetSessions(); $this->drupalGet('session-test/id-from-cookie'); $this->assertRaw("session_id:\n", 'Session ID is blank as sent from cookie header.'); // Assert that we have an anonymous session now. @@ -281,19 +289,13 @@ public function testEmptySessionID() { /** * Reset the cookie file so that it refers to the specified user. - * - * @param $uid - * User id to set as the active session. */ - public function sessionReset($uid = 0) { + public function sessionReset() { // Close the internal browser. - $this->curlClose(); + $this->mink->resetSessions(); $this->loggedInUser = FALSE; // Change cookie file for user. - $this->cookieFile = \Drupal::service('stream_wrapper_manager')->getViaScheme('temporary')->getDirectoryPath() . '/cookie.' . $uid . '.txt'; - $this->additionalCurlOptions[CURLOPT_COOKIEFILE] = $this->cookieFile; - $this->additionalCurlOptions[CURLOPT_COOKIESESSION] = TRUE; $this->drupalGet('session-test/get'); $this->assertResponse(200, 'Session test module is correctly enabled.', 'Session'); } @@ -303,10 +305,10 @@ public function sessionReset($uid = 0) { */ public function assertSessionCookie($sent) { if ($sent) { - $this->assertNotNull($this->sessionId, 'Session cookie was sent.'); + $this->assertNotEmpty($this->getSessionCookies()->count(), 'Session cookie was sent.'); } else { - $this->assertNull($this->sessionId, 'Session cookie was not sent.'); + $this->assertEmpty($this->getSessionCookies()->count(), 'Session cookie was not sent.'); } } diff --git a/web/core/modules/system/tests/src/Functional/Session/StackSessionHandlerIntegrationTest.php b/web/core/modules/system/tests/src/Functional/Session/StackSessionHandlerIntegrationTest.php new file mode 100644 index 0000000000000000000000000000000000000000..d65ba4216044fa6e63b262d4df6fce8f9de683b0 --- /dev/null +++ b/web/core/modules/system/tests/src/Functional/Session/StackSessionHandlerIntegrationTest.php @@ -0,0 +1,49 @@ +<?php + +namespace Drupal\Tests\system\Functional\Session; + +use Drupal\Core\EventSubscriber\MainContentViewSubscriber; +use Drupal\Tests\BrowserTestBase; + +/** + * Tests the stacked session handler functionality. + * + * @group Session + */ +class StackSessionHandlerIntegrationTest extends BrowserTestBase { + + /** + * {@inheritdoc} + */ + protected static $modules = ['session_test']; + + /** + * Tests a request. + */ + public function testRequest() { + $options['query'][MainContentViewSubscriber::WRAPPER_FORMAT] = 'drupal_ajax'; + $headers[] = 'X-Requested-With: XMLHttpRequest'; + $actual_trace = json_decode($this->drupalGet('session-test/trace-handler', $options, $headers)); + $sessionId = $this->getSessionCookies()->getCookieByName($this->getSessionName())->getValue(); + $expect_trace = [ + ['BEGIN', 'test_argument', 'open'], + ['BEGIN', NULL, 'open'], + ['END', NULL, 'open'], + ['END', 'test_argument', 'open'], + ['BEGIN', 'test_argument', 'read', $sessionId], + ['BEGIN', NULL, 'read', $sessionId], + ['END', NULL, 'read', $sessionId], + ['END', 'test_argument', 'read', $sessionId], + ['BEGIN', 'test_argument', 'write', $sessionId], + ['BEGIN', NULL, 'write', $sessionId], + ['END', NULL, 'write', $sessionId], + ['END', 'test_argument', 'write', $sessionId], + ['BEGIN', 'test_argument', 'close'], + ['BEGIN', NULL, 'close'], + ['END', NULL, 'close'], + ['END', 'test_argument', 'close'], + ]; + $this->assertEqual($expect_trace, $actual_trace); + } + +} diff --git a/web/core/modules/system/src/Tests/System/ErrorHandlerTest.php b/web/core/modules/system/tests/src/Functional/System/ErrorHandlerTest.php similarity index 68% rename from web/core/modules/system/src/Tests/System/ErrorHandlerTest.php rename to web/core/modules/system/tests/src/Functional/System/ErrorHandlerTest.php index dc661fec914fa73647b4a04f7b88dfff02fda007..3ab502e8644630b7bbd7af4e4834dc05964aea21 100644 --- a/web/core/modules/system/src/Tests/System/ErrorHandlerTest.php +++ b/web/core/modules/system/tests/src/Functional/System/ErrorHandlerTest.php @@ -1,16 +1,16 @@ <?php -namespace Drupal\system\Tests\System; +namespace Drupal\Tests\system\Functional\System; use Drupal\Component\Render\FormattableMarkup; -use Drupal\simpletest\WebTestBase; +use Drupal\Tests\BrowserTestBase; /** * Performs tests on the Drupal error and exception handler. * * @group system */ -class ErrorHandlerTest extends WebTestBase { +class ErrorHandlerTest extends BrowserTestBase { /** * Modules to enable. @@ -42,17 +42,6 @@ public function testErrorHandler() { '%function' => 'Drupal\error_test\Controller\ErrorTestController->generateWarnings()', '%file' => drupal_get_path('module', 'error_test') . '/error_test.module', ]; - $fatal_error = [ - '%type' => 'Recoverable fatal error', - '%function' => 'Drupal\error_test\Controller\ErrorTestController->Drupal\error_test\Controller\{closure}()', - '@message' => 'Argument 1 passed to Drupal\error_test\Controller\ErrorTestController::Drupal\error_test\Controller\{closure}() must be of the type array, string given, called in ' . \Drupal::root() . '/core/modules/system/tests/modules/error_test/src/Controller/ErrorTestController.php on line 62 and defined', - ]; - if (version_compare(PHP_VERSION, '7.0.0-dev') >= 0) { - // In PHP 7, instead of a recoverable fatal error we get a TypeError. - $fatal_error['%type'] = 'TypeError'; - // The error message also changes in PHP 7. - $fatal_error['@message'] = 'Argument 1 passed to Drupal\error_test\Controller\ErrorTestController::Drupal\error_test\Controller\{closure}() must be of the type array, string given, called in ' . \Drupal::root() . '/core/modules/system/tests/modules/error_test/src/Controller/ErrorTestController.php on line 62'; - } // Set error reporting to display verbose notices. $this->config('system.logging')->set('error_level', ERROR_REPORTING_DISPLAY_VERBOSE)->save(); @@ -68,25 +57,6 @@ public function testErrorHandler() { // Set error reporting to display verbose notices. $this->config('system.logging')->set('error_level', ERROR_REPORTING_DISPLAY_VERBOSE)->save(); - $this->drupalGet('error-test/generate-fatals'); - $this->assertResponse(500, 'Received expected HTTP status code.'); - $this->assertErrorMessage($fatal_error); - $this->assertRaw('<pre class="backtrace">', 'Found pre element with backtrace class.'); - // Ensure we are escaping but not double escaping. - $this->assertRaw('''); - $this->assertNoRaw('&#039;'); - - // Remove the recoverable fatal error from the assertions, it's wanted here. - // Ensure that we just remove this one recoverable fatal error (in PHP 7 this - // is a TypeError). - foreach ($this->assertions as $key => $assertion) { - if (in_array($assertion['message_group'], ['Recoverable fatal error', 'TypeError']) && strpos($assertion['message'], 'Argument 1 passed to Drupal\error_test\Controller\ErrorTestController::Drupal\error_test\Controller\{closure}() must be of the type array, string given, called in') !== FALSE) { - unset($this->assertions[$key]); - $this->deleteAssert($assertion['message_id']); - } - } - // Drop the single exception. - $this->results['#exception']--; // Set error reporting to collect notices. $config->set('error_level', ERROR_REPORTING_DISPLAY_ALL)->save(); @@ -96,7 +66,6 @@ public function testErrorHandler() { $this->assertErrorMessage($error_warning); $this->assertErrorMessage($error_user_notice); $this->assertNoRaw('<pre class="backtrace">', 'Did not find pre element with backtrace class.'); - $this->assertErrorLogged($fatal_error['@message']); // Set error reporting to not collect notices. $config->set('error_level', ERROR_REPORTING_DISPLAY_SOME)->save(); @@ -122,9 +91,6 @@ public function testErrorHandler() { * Test the exception handler. */ public function testExceptionHandler() { - // Ensure the test error log is empty before these tests. - $this->assertNoErrorsLogged(); - $error_exception = [ '%type' => 'Exception', '@message' => 'Drupal & awesome', @@ -148,11 +114,11 @@ public function testExceptionHandler() { ]; $this->drupalGet('error-test/trigger-exception'); - $this->assertTrue(strpos($this->drupalGetHeader(':status'), '500 Service unavailable (with message)'), 'Received expected HTTP status line.'); + $this->assertSession()->statusCodeEquals(500); $this->assertErrorMessage($error_exception); $this->drupalGet('error-test/trigger-pdo-exception'); - $this->assertTrue(strpos($this->drupalGetHeader(':status'), '500 Service unavailable (with message)'), 'Received expected HTTP status line.'); + $this->assertSession()->statusCodeEquals(500); // We cannot use assertErrorMessage() since the exact error reported // varies from database to database. Check that the SQL string is displayed. $this->assertText($error_pdo_exception['%type'], format_string('Found %type in error page.', $error_pdo_exception)); @@ -161,7 +127,7 @@ public function testExceptionHandler() { $this->assertRaw($error_details, format_string("Found '@message' in error page.", ['@message' => $error_details])); $this->drupalGet('error-test/trigger-renderer-exception'); - $this->assertTrue(strpos($this->drupalGetHeader(':status'), '500 Service unavailable (with message)'), 'Received expected HTTP status line.'); + $this->assertSession()->statusCodeEquals(500); $this->assertErrorMessage($error_renderer_exception); // Disable error reporting, ensure that 5xx responses are not cached. @@ -172,12 +138,8 @@ public function testExceptionHandler() { $this->drupalGet('error-test/trigger-exception'); $this->assertFalse($this->drupalGetHeader('X-Drupal-Cache')); $this->assertIdentical(strpos($this->drupalGetHeader('Cache-Control'), 'public'), FALSE, 'Received expected HTTP status line.'); - $this->assertTrue(strpos($this->drupalGetHeader(':status'), '500 Service unavailable (with message)'), 'Received expected HTTP status line.'); + $this->assertSession()->statusCodeEquals(500); $this->assertNoErrorMessage($error_exception); - - // The exceptions are expected. Do not interpret them as a test failure. - // Not using File API; a potential error must trigger a PHP warning. - unlink(\Drupal::root() . '/' . $this->siteDirectory . '/error.log'); } /** diff --git a/web/core/modules/system/tests/src/Functional/Theme/ThemeTest.php b/web/core/modules/system/tests/src/Functional/Theme/ThemeTest.php index 3d534d8e750337515910f9d3f81144eb54186c90..b70ee859c65044e6bf32b010a4d245d06c55ed4c 100644 --- a/web/core/modules/system/tests/src/Functional/Theme/ThemeTest.php +++ b/web/core/modules/system/tests/src/Functional/Theme/ThemeTest.php @@ -94,7 +94,11 @@ public function testCSSOverride() { $config->set('css.preprocess', 0); $config->save(); $this->drupalGet('theme-test/suggestion'); - $this->assertNoText('js.module.css', 'The theme\'s .info.yml file is able to override a module CSS file from being added to the page.'); + // We add a "?" to the assertion, because drupalSettings may include + // information about the file; we only really care about whether it appears + // in a LINK or STYLE tag, for which Drupal always adds a query string for + // cache control. + $this->assertSession()->responseNotContains('js.module.css?'); // Also test with aggregation enabled, simply ensuring no PHP errors are // triggered during drupal_build_css_cache() when a source file doesn't diff --git a/web/core/modules/system/tests/src/Functional/Update/FilterHtmlUpdateTest.php b/web/core/modules/system/tests/src/Functional/Update/FilterHtmlUpdateTest.php index 01edaab42a551eb58b11a8444009427469e125c0..ea591fcbd8b053c1bec634255a26960eb96581ae 100644 --- a/web/core/modules/system/tests/src/Functional/Update/FilterHtmlUpdateTest.php +++ b/web/core/modules/system/tests/src/Functional/Update/FilterHtmlUpdateTest.php @@ -6,7 +6,7 @@ use Drupal\FunctionalTests\Update\UpdatePathTestBase; /** - * Tests that the allowed html configutations are updated with attributes. + * Tests that the allowed html configurations are updated with attributes. * * @group Entity * @group legacy diff --git a/web/core/modules/system/tests/src/FunctionalJavascript/Form/ElementsTableSelectTest.php b/web/core/modules/system/tests/src/FunctionalJavascript/Form/ElementsTableSelectTest.php new file mode 100644 index 0000000000000000000000000000000000000000..b565bfd74381ac2fd7c89e8401e527bbdd7a96ae --- /dev/null +++ b/web/core/modules/system/tests/src/FunctionalJavascript/Form/ElementsTableSelectTest.php @@ -0,0 +1,58 @@ +<?php + +namespace Drupal\Tests\system\FunctionalJavascript\Form; + +use Drupal\FunctionalJavascriptTests\WebDriverTestBase; + +/** + * Tests the tableselect form element for expected behavior. + * + * @group Form + */ +class ElementsTableSelectTest extends WebDriverTestBase { + + /** + * {@inheritdoc} + */ + protected static $modules = ['form_test']; + + /** + * Test the presence of ajax functionality for all options. + */ + public function testAjax() { + // Test checkboxes (#multiple == TRUE). + $this->drupalGet('form_test/tableselect/multiple-true'); + $session = $this->getSession(); + $page = $session->getPage(); + for ($i = 1; $i <= 3; $i++) { + $row = 'row' . $i; + $page->hasUncheckedField($row); + $page->checkField($row); + $this->assertSession()->assertWaitOnAjaxRequest(); + // Check current row and previous rows are checked. + for ($j = 1; $j <= $i; $j++) { + $other_row = 'row' . $j; + $page->hasCheckedField($other_row); + } + } + + // Test radios (#multiple == FALSE). + $this->drupalGet('form_test/tableselect/multiple-false'); + for ($i = 1; $i <= 3; $i++) { + $row = 'input[value="row' . $i . '"]'; + $page->hasUncheckedField($row); + $this->click($row); + $this->assertSession()->assertWaitOnAjaxRequest(); + $page->hasCheckedField($row); + // Check other rows are not checked + for ($j = 1; $j <= 3; $j++) { + if ($j == $i) { + continue; + } + $other_row = 'edit-tableselect-row' . $j; + $page->hasUncheckedField($other_row); + } + } + } + +} diff --git a/web/core/modules/system/src/Tests/Form/RebuildTest.php b/web/core/modules/system/tests/src/FunctionalJavascript/Form/RebuildTest.php similarity index 53% rename from web/core/modules/system/src/Tests/Form/RebuildTest.php rename to web/core/modules/system/tests/src/FunctionalJavascript/Form/RebuildTest.php index 2e138bdfb322ce200baf9a1a431321569fc04eeb..caf52094d574c9f12d402da7b40dc11dbbd58646 100644 --- a/web/core/modules/system/src/Tests/Form/RebuildTest.php +++ b/web/core/modules/system/tests/src/FunctionalJavascript/Form/RebuildTest.php @@ -1,12 +1,12 @@ <?php -namespace Drupal\system\Tests\Form; +namespace Drupal\Tests\system\FunctionalJavascript\Form; use Drupal\Core\Field\FieldStorageDefinitionInterface; use Drupal\Core\Url; use Drupal\field\Entity\FieldConfig; -use Drupal\simpletest\WebTestBase; use Drupal\field\Entity\FieldStorageConfig; +use Drupal\FunctionalJavascriptTests\WebDriverTestBase; /** * Tests functionality of \Drupal\Core\Form\FormBuilderInterface::rebuildForm(). @@ -14,14 +14,12 @@ * @group Form * @todo Add tests for other aspects of form rebuilding. */ -class RebuildTest extends WebTestBase { +class RebuildTest extends WebDriverTestBase { /** - * Modules to enable. - * - * @var array + * {@inheritdoc} */ - public static $modules = ['node', 'form_test']; + protected static $modules = ['node', 'form_test']; /** * A user for testing. @@ -30,6 +28,9 @@ class RebuildTest extends WebTestBase { */ protected $webUser; + /** + * {@inheritdoc} + */ protected function setUp() { parent::setUp(); @@ -39,28 +40,6 @@ protected function setUp() { $this->drupalLogin($this->webUser); } - /** - * Tests preservation of values. - */ - public function testRebuildPreservesValues() { - $edit = [ - 'checkbox_1_default_off' => TRUE, - 'checkbox_1_default_on' => FALSE, - 'text_1' => 'foo', - ]; - $this->drupalPostForm('form-test/form-rebuild-preserve-values', $edit, 'Add more'); - - // Verify that initial elements retained their submitted values. - $this->assertFieldChecked('edit-checkbox-1-default-off', 'A submitted checked checkbox retained its checked state during a rebuild.'); - $this->assertNoFieldChecked('edit-checkbox-1-default-on', 'A submitted unchecked checkbox retained its unchecked state during a rebuild.'); - $this->assertFieldById('edit-text-1', 'foo', 'A textfield retained its submitted value during a rebuild.'); - - // Verify that newly added elements were initialized with their default values. - $this->assertFieldChecked('edit-checkbox-2-default-on', 'A newly added checkbox was initialized with a default checked state.'); - $this->assertNoFieldChecked('edit-checkbox-2-default-off', 'A newly added checkbox was initialized with a default unchecked state.'); - $this->assertFieldById('edit-text-2', 'DEFAULT 2', 'A newly added textfield was initialized with its default value.'); - } - /** * Tests that a form's action is retained after an Ajax submission. * @@ -68,6 +47,7 @@ public function testRebuildPreservesValues() { * followed by a non-Ajax submission, which triggers a validation error. */ public function testPreserveFormActionAfterAJAX() { + $page = $this->getSession()->getPage(); // Create a multi-valued field for 'page' nodes to use for Ajax testing. $field_name = 'field_ajax_test'; FieldStorageConfig::create([ @@ -81,8 +61,26 @@ public function testPreserveFormActionAfterAJAX() { 'entity_type' => 'node', 'bundle' => 'page', ])->save(); + + // Also create a file field to test server side validation error. + $field_file_name = 'field_file_test'; + FieldStorageConfig::create([ + 'field_name' => $field_file_name, + 'entity_type' => 'node', + 'type' => 'file', + 'cardinality' => 1, + ])->save(); + FieldConfig::create([ + 'field_name' => $field_file_name, + 'entity_type' => 'node', + 'bundle' => 'page', + 'label' => 'Test file', + 'required' => TRUE, + ])->save(); + entity_get_form_display('node', 'page', 'default') ->setComponent($field_name, ['type' => 'text_textfield']) + ->setComponent($field_file_name, ['type' => 'file_generic']) ->save(); // Log in a user who can create 'page' nodes. @@ -93,27 +91,31 @@ public function testPreserveFormActionAfterAJAX() { // submission and verify it worked by ensuring the updated page has two text // field items in the field for which we just added an item. $this->drupalGet('node/add/page'); - $this->drupalPostAjaxForm(NULL, [], ['field_ajax_test_add_more' => t('Add another item')], NULL, [], [], 'node-page-form'); - $this->assert(count($this->xpath('//div[contains(@class, "field--name-field-ajax-test")]//input[@type="text"]')) == 2, 'AJAX submission succeeded.'); + $page->find('css', '[value="Add another item"]')->click(); + $this->assertSession()->assertWaitOnAjaxRequest(); + $this->assertTrue(count($this->xpath('//div[contains(@class, "field--name-field-ajax-test")]//input[@type="text"]')) == 2, 'AJAX submission succeeded.'); - // Submit the form with the non-Ajax "Save" button, leaving the title field + // Submit the form with the non-Ajax "Save" button, leaving the file field // blank to trigger a validation error, and ensure that a validation error // occurred, because this test is for testing what happens when a form is // re-rendered without being re-built, which is what happens when there's - // a validation error. - $this->drupalPostForm(NULL, [], t('Save')); - $this->assertText('Title field is required.', 'Non-AJAX submission correctly triggered a validation error.'); + // a server side validation error. + $edit = [ + 'title[0][value]' => $this->randomString(), + ]; + $this->drupalPostForm(NULL, $edit, 'Save'); + $this->assertSession()->pageTextContains('Test file field is required.', 'Non-AJAX submission correctly triggered a validation error.'); // Ensure that the form contains two items in the multi-valued field, so we // know we're testing a form that was correctly retrieved from cache. - $this->assert(count($this->xpath('//form[contains(@id, "node-page-form")]//div[contains(@class, "js-form-item-field-ajax-test")]//input[@type="text"]')) == 2, 'Form retained its state from cache.'); + $this->assertTrue(count($this->xpath('//form[contains(@id, "node-page-form")]//div[contains(@class, "js-form-item-field-ajax-test")]//input[@type="text"]')) == 2, 'Form retained its state from cache.'); // Ensure that the form's action is correct. $forms = $this->xpath('//form[contains(@class, "node-page-form")]'); - $this->assertEqual(1, count($forms)); + $this->assertEquals(1, count($forms)); // Strip query params off the action before asserting. - $url = parse_url($forms[0]['action'])['path']; - $this->assertEqual(Url::fromRoute('node.add', ['node_type' => 'page'])->toString(), $url); + $url = parse_url($forms[0]->getAttribute('action'))['path']; + $this->assertEquals(Url::fromRoute('node.add', ['node_type' => 'page'])->toString(), $url); } } diff --git a/web/core/modules/system/tests/src/FunctionalJavascript/Form/TriggeringElementTest.php b/web/core/modules/system/tests/src/FunctionalJavascript/Form/TriggeringElementTest.php new file mode 100644 index 0000000000000000000000000000000000000000..41733ec46e3db89d9624a06bc1a3fe48880e76c2 --- /dev/null +++ b/web/core/modules/system/tests/src/FunctionalJavascript/Form/TriggeringElementTest.php @@ -0,0 +1,111 @@ +<?php + +namespace Drupal\Tests\system\FunctionalJavascript\Form; + +use Drupal\FunctionalJavascriptTests\WebDriverTestBase; + +/** + * Tests that FAPI correctly determines the triggering element. + * + * @group Form + */ +class TriggeringElementTest extends WebDriverTestBase { + + /** + * {@inheritdoc} + */ + protected static $modules = ['form_test']; + + /** + * Tests the the triggering element when no button information is included. + * + * Test the determination of the triggering element when no button + * information is included in the POST data, as is sometimes the case when + * the ENTER key is pressed in a textfield in Internet Explorer. + */ + public function testNoButtonInfoInPost() { + $path = '/form-test/clicked-button'; + $form_html_id = 'form-test-clicked-button'; + + // Ensure submitting a form with no buttons results in no triggering element + // and the form submit handler not running. + $this->drupalGet($path); + + $assert_session = $this->assertSession(); + $this->getSession()->getDriver()->submitForm('//form[@id="' . $form_html_id . '"]'); + $assert_session->pageTextContains('There is no clicked button.'); + $assert_session->pageTextNotContains('Submit handler for form_test_clicked_button executed.'); + + // Ensure submitting a form with one or more submit buttons results in the + // triggering element being set to the first one the user has access to. An + // argument with 'r' in it indicates a restricted (#access=FALSE) button. + $this->drupalGet($path . '/s'); + $this->getSession()->getDriver()->submitForm('//form[@id="' . $form_html_id . '"]'); + $assert_session->pageTextContains('The clicked button is button1.'); + $assert_session->pageTextContains('Submit handler for form_test_clicked_button executed.'); + + $this->drupalGet($path . '/s/s'); + $this->getSession()->getDriver()->submitForm('//form[@id="' . $form_html_id . '"]'); + $assert_session->pageTextContains('The clicked button is button1.'); + $assert_session->pageTextContains('Submit handler for form_test_clicked_button executed.'); + + $this->drupalGet($path . '/rs/s'); + $this->getSession()->getDriver()->submitForm('//form[@id="' . $form_html_id . '"]'); + $assert_session->pageTextContains('The clicked button is button2.'); + $assert_session->pageTextContains('Submit handler for form_test_clicked_button executed.'); + + // Ensure submitting a form with buttons of different types results in the + // triggering element being set to the first button, regardless of type. For + // the FAPI 'button' type, this should result in the submit handler not + // executing. The types are 's'(ubmit), 'b'(utton), and 'i'(mage_button). + $this->drupalGet($path . '/s/b/i'); + $this->getSession()->getDriver()->submitForm('//form[@id="' . $form_html_id . '"]'); + $assert_session->pageTextContains('The clicked button is button1.'); + $assert_session->pageTextContains('Submit handler for form_test_clicked_button executed.'); + + $this->drupalGet($path . '/b/s/i'); + $this->getSession()->getDriver()->submitForm('//form[@id="' . $form_html_id . '"]'); + $assert_session->pageTextContains('The clicked button is button1.'); + $assert_session->pageTextNotContains('Submit handler for form_test_clicked_button executed.'); + + $this->drupalGet($path . '/i/s/b'); + $this->getSession()->getDriver()->submitForm('//form[@id="' . $form_html_id . '"]'); + $assert_session->pageTextContains('The clicked button is button1.'); + $assert_session->pageTextContains('Submit handler for form_test_clicked_button executed.'); + } + + /** + * Tests attempts to bypass access control. + * + * Test that the triggering element does not get set to a button with + * #access=FALSE. + */ + public function testAttemptAccessControlBypass() { + $path = 'form-test/clicked-button'; + $form_html_id = 'form-test-clicked-button'; + + // Retrieve a form where 'button1' has #access=FALSE and 'button2' doesn't. + $this->drupalGet($path . '/rs/s'); + + // Submit the form with 'button1=button1' in the POST data, which someone + // trying to get around security safeguards could easily do. We have to do + // a little trickery here, to work around the safeguards in drupalPostForm() + // by renaming the text field and value that is in the form to 'button1', + // we can get the data we want into \Drupal::request()->request. + $page = $this->getSession()->getPage(); + $input = $page->find('css', 'input[name="text"]'); + $this->assertNotNull($input, 'text input located.'); + + $input->setValue('name', 'button1'); + $input->setValue('value', 'button1'); + $this->xpath('//form[@id="' . $form_html_id . '"]//input[@type="submit"]')[0]->click(); + + // Ensure that the triggering element was not set to the restricted button. + // Do this with both a negative and positive assertion, because negative + // assertions alone can be brittle. See testNoButtonInfoInPost() for why the + // triggering element gets set to 'button2'. + $this->assertSession()->pageTextNotContains('The clicked button is button1.'); + $this->assertSession()->pageTextContains('The clicked button is button2.'); + } + +} diff --git a/web/core/modules/system/tests/src/FunctionalJavascript/FrameworkTest.php b/web/core/modules/system/tests/src/FunctionalJavascript/FrameworkTest.php new file mode 100644 index 0000000000000000000000000000000000000000..60f10b35f9314bb91202120fee5fbc406335db9a --- /dev/null +++ b/web/core/modules/system/tests/src/FunctionalJavascript/FrameworkTest.php @@ -0,0 +1,122 @@ +<?php + +namespace Drupal\Tests\system\FunctionalJavascript; + +use Drupal\FunctionalJavascriptTests\WebDriverTestBase; + +/** + * Tests the off-canvas dialog functionality. + * + * @group system + */ +class FrameworkTest extends WebDriverTestBase { + + /** + * {@inheritdoc} + */ + protected static $modules = ['node', 'ajax_test', 'ajax_forms_test']; + + /** + * Tests that new JavaScript and CSS files are lazy-loaded on an AJAX request. + */ + public function testLazyLoad() { + $expected = [ + 'setting_name' => 'ajax_forms_test_lazy_load_form_submit', + 'setting_value' => 'executed', + 'library_1' => 'system/admin', + 'library_2' => 'system/drupal.system', + ]; + + // Get the base page. + $this->drupalGet('ajax_forms_test_lazy_load_form'); + $page = $this->getSession()->getPage(); + $assert = $this->assertSession(); + + $original_settings = $this->getDrupalSettings(); + $original_libraries = explode(',', $original_settings['ajaxPageState']['libraries']); + + // Verify that the base page doesn't have the settings and files that are to + // be lazy loaded as part of the next requests. + $this->assertTrue(!isset($original_settings[$expected['setting_name']]), format_string('Page originally lacks the %setting, as expected.', ['%setting' => $expected['setting_name']])); + $this->assertTrue(!in_array($expected['library_1'], $original_libraries), format_string('Page originally lacks the %library library, as expected.', ['%library' => $expected['library_1']])); + $this->assertTrue(!in_array($expected['library_2'], $original_libraries), format_string('Page originally lacks the %library library, as expected.', ['%library' => $expected['library_2']])); + + // Submit the AJAX request without triggering files getting added. + $page->pressButton('Submit'); + $assert->assertWaitOnAjaxRequest(); + $new_settings = $this->getDrupalSettings(); + $new_libraries = explode(',', $new_settings['ajaxPageState']['libraries']); + + // Verify the setting was not added when not expected. + $this->assertTrue(!isset($new_settings[$expected['setting_name']]), format_string('Page still lacks the %setting, as expected.', ['%setting' => $expected['setting_name']])); + $this->assertTrue(!in_array($expected['library_1'], $new_libraries), format_string('Page still lacks the %library library, as expected.', ['%library' => $expected['library_1']])); + $this->assertTrue(!in_array($expected['library_2'], $new_libraries), format_string('Page still lacks the %library library, as expected.', ['%library' => $expected['library_2']])); + + // Submit the AJAX request and trigger adding files. + $page->checkField('add_files'); + $page->pressButton('Submit'); + $assert->assertWaitOnAjaxRequest(); + $new_settings = $this->getDrupalSettings(); + $new_libraries = explode(',', $new_settings['ajaxPageState']['libraries']); + + // Verify the expected setting was added, both to drupalSettings, and as + // the first AJAX command. + $this->assertIdentical($new_settings[$expected['setting_name']], $expected['setting_value'], format_string('Page now has the %setting.', ['%setting' => $expected['setting_name']])); + + // Verify the expected CSS file was added, both to drupalSettings, and as + // the second AJAX command for inclusion into the HTML. + $this->assertTrue(in_array($expected['library_1'], $new_libraries), format_string('Page state now has the %library library.', ['%library' => $expected['library_1']])); + + // Verify the expected JS file was added, both to drupalSettings, and as + // the third AJAX command for inclusion into the HTML. By testing for an + // exact HTML string containing the SCRIPT tag, we also ensure that + // unexpected JavaScript code, such as a jQuery.extend() that would + // potentially clobber rather than properly merge settings, didn't + // accidentally get added. + $this->assertTrue(in_array($expected['library_2'], $new_libraries), format_string('Page state now has the %library library.', ['%library' => $expected['library_2']])); + } + + /** + * Tests that drupalSettings.currentPath is not updated on AJAX requests. + */ + public function testCurrentPathChange() { + $this->drupalGet('ajax_forms_test_lazy_load_form'); + $page = $this->getSession()->getPage(); + $assert = $this->assertSession(); + + $old_settings = $this->getDrupalSettings(); + $page->pressButton('Submit'); + $assert->assertWaitOnAjaxRequest(); + $new_settings = $this->getDrupalSettings(); + $this->assertEquals($old_settings['path']['currentPath'], $new_settings['path']['currentPath']); + } + + /** + * Tests that overridden CSS files are not added during lazy load. + */ + public function testLazyLoadOverriddenCSS() { + // The test theme overrides js.module.css without an implementation, + // thereby removing it. + \Drupal::service('theme_handler')->install(['test_theme']); + $this->config('system.theme') + ->set('default', 'test_theme') + ->save(); + + // This gets the form, and does an Ajax submission on it. + $this->drupalGet('ajax_forms_test_lazy_load_form'); + $page = $this->getSession()->getPage(); + $assert = $this->assertSession(); + + $page->checkField('add_files'); + $page->pressButton('Submit'); + $assert->assertWaitOnAjaxRequest(); + + // Verify that the resulting HTML does not load the overridden CSS file. + // We add a "?" to the assertion, because drupalSettings may include + // information about the file; we only really care about whether it appears + // in a LINK or STYLE tag, for which Drupal always adds a query string for + // cache control. + $assert->responseNotContains('js.module.css?', 'Ajax lazy loading does not add overridden CSS files.'); + } + +} diff --git a/web/core/modules/system/tests/src/Kernel/Entity/EntityReferenceSelectionReferenceableTest.php b/web/core/modules/system/tests/src/Kernel/Entity/EntityReferenceSelectionReferenceableTest.php index 058f83bb933fe2c03724849d80b7da72b9c181c2..15a53decf8caf00a654ff00c24d4ff3b8d85b85b 100644 --- a/web/core/modules/system/tests/src/Kernel/Entity/EntityReferenceSelectionReferenceableTest.php +++ b/web/core/modules/system/tests/src/Kernel/Entity/EntityReferenceSelectionReferenceableTest.php @@ -3,10 +3,10 @@ namespace Drupal\Tests\system\Kernel\Entity; use Drupal\Component\Utility\Html; -use Drupal\field\Tests\EntityReference\EntityReferenceTestTrait; use Drupal\field\Entity\FieldConfig; use Drupal\node\Entity\NodeType; use Drupal\KernelTests\KernelTestBase; +use Drupal\Tests\field\Traits\EntityReferenceTestTrait; /** * Tests entity reference selection plugins. diff --git a/web/core/modules/system/tests/src/Kernel/Extension/ModuleHandlerTest.php b/web/core/modules/system/tests/src/Kernel/Extension/ModuleHandlerTest.php index 708d517a321200d83c28e1d1bd5790918fc820c7..fd22de13977cf0f8184c8c0a711bfa3ba85af401 100644 --- a/web/core/modules/system/tests/src/Kernel/Extension/ModuleHandlerTest.php +++ b/web/core/modules/system/tests/src/Kernel/Extension/ModuleHandlerTest.php @@ -233,11 +233,11 @@ public function testUninstallProfileDependency() { $result = $this->moduleInstaller()->uninstall([$non_dependency]); $this->assertTrue($result, 'ModuleInstaller::uninstall() returns TRUE.'); $this->assertFalse($this->moduleHandler()->moduleExists($non_dependency)); - $this->assertEquals(drupal_get_installed_schema_version($non_dependency), SCHEMA_UNINSTALLED, "$dependency module was uninstalled."); + $this->assertEquals(drupal_get_installed_schema_version($non_dependency), SCHEMA_UNINSTALLED, "$non_dependency module was uninstalled."); // Verify that the installation profile itself was not uninstalled. $uninstalled_modules = \Drupal::state()->get('module_test.uninstall_order') ?: []; - $this->assertContains($non_dependency, $uninstalled_modules, "$dependency module is in the list of uninstalled modules."); + $this->assertContains($non_dependency, $uninstalled_modules, "$non_dependency module is in the list of uninstalled modules."); $this->assertNotContains($profile, $uninstalled_modules, 'The installation profile is not in the list of uninstalled modules.'); // Try uninstalling the required module. diff --git a/web/core/modules/system/tests/src/Kernel/Form/FileElementTest.php b/web/core/modules/system/tests/src/Kernel/Form/FileElementTest.php new file mode 100644 index 0000000000000000000000000000000000000000..267489f4cd27e58c46771f7d5f545c4f1d01608b --- /dev/null +++ b/web/core/modules/system/tests/src/Kernel/Form/FileElementTest.php @@ -0,0 +1,32 @@ +<?php + +namespace Drupal\Tests\system\Kernel\Form; + +use Drupal\form_test\Form\FormTestFileForm; +use Drupal\KernelTests\KernelTestBase; + +/** + * Tests for the 'file' form element. + * + * @group Form + */ +class FileElementTest extends KernelTestBase { + + /** + * {@inheritdoc} + */ + protected static $modules = ['form_test']; + + /** + * Tests that file elements are built and processed correctly. + */ + public function testFileElement() { + $form = $this->container->get('form_builder') + ->getForm(FormTestFileForm::class); + + $this->assertSame('file', $form['file']['#type']); + $this->assertTrue($form['file']['#multiple']); + $this->assertContains('cagatio', $form['file']['#attributes']['class']); + } + +} diff --git a/web/core/modules/system/tests/src/Kernel/Installer/InstallerMissingDependenciesTest.php b/web/core/modules/system/tests/src/Kernel/Installer/InstallerDependenciesResolutionTest.php similarity index 76% rename from web/core/modules/system/tests/src/Kernel/Installer/InstallerMissingDependenciesTest.php rename to web/core/modules/system/tests/src/Kernel/Installer/InstallerDependenciesResolutionTest.php index 052c0afb80028209cb8946a9be4435181f6b2ab6..d4d4c3194a74ada27d93fba273a7cf4880c5f3f0 100644 --- a/web/core/modules/system/tests/src/Kernel/Installer/InstallerMissingDependenciesTest.php +++ b/web/core/modules/system/tests/src/Kernel/Installer/InstallerDependenciesResolutionTest.php @@ -5,11 +5,11 @@ use Drupal\KernelTests\KernelTestBase; /** - * Tests that we handle the absence of a module dependency during install. + * Tests that we handle module dependency resolution during install. * * @group Installer */ -class InstallerMissingDependenciesTest extends KernelTestBase { +class InstallerDependenciesResolutionTest extends KernelTestBase { /** * {@inheritdoc} @@ -19,7 +19,7 @@ class InstallerMissingDependenciesTest extends KernelTestBase { /** * Verifies that the exception message in the profile step is correct. */ - public function testSetUpWithMissingDependencies() { + public function testDependenciesResolution() { // Prime the drupal_get_filename() static cache with the location of the // testing profile as it is not the currently active profile and we don't // yet have any cached way to retrieve its location. @@ -32,8 +32,11 @@ public function testSetUpWithMissingDependencies() { ]); $message = $info['required_modules']['description']->render(); + $this->assertContains('Fictional', $message); $this->assertContains('Missing_module1', $message); $this->assertContains('Missing_module2', $message); + $this->assertNotContains('Block', $message); + $this->assertNotContains('Node', $message); } } diff --git a/web/core/modules/system/tests/src/Unit/Breadcrumbs/PathBasedBreadcrumbBuilderTest.php b/web/core/modules/system/tests/src/Unit/Breadcrumbs/PathBasedBreadcrumbBuilderTest.php index a24313f4affb81347c628952e44c8ae18d961956..b07f31f62f4470f3b7fa311e21baa5aedd6246a3 100644 --- a/web/core/modules/system/tests/src/Unit/Breadcrumbs/PathBasedBreadcrumbBuilderTest.php +++ b/web/core/modules/system/tests/src/Unit/Breadcrumbs/PathBasedBreadcrumbBuilderTest.php @@ -151,7 +151,7 @@ public function testBuildOnFrontpage() { $breadcrumb = $this->builder->build($this->getMock('Drupal\Core\Routing\RouteMatchInterface')); $this->assertEquals([], $breadcrumb->getLinks()); - $this->assertEquals(['url.path.parent'], $breadcrumb->getCacheContexts()); + $this->assertEquals(['url.path.is_front', 'url.path.parent'], $breadcrumb->getCacheContexts()); $this->assertEquals([], $breadcrumb->getCacheTags()); $this->assertEquals(Cache::PERMANENT, $breadcrumb->getCacheMaxAge()); } @@ -168,7 +168,7 @@ public function testBuildWithOnePathElement() { $breadcrumb = $this->builder->build($this->getMock('Drupal\Core\Routing\RouteMatchInterface')); $this->assertEquals([0 => new Link('Home', new Url('<front>'))], $breadcrumb->getLinks()); - $this->assertEquals(['url.path.parent'], $breadcrumb->getCacheContexts()); + $this->assertEquals(['url.path.is_front', 'url.path.parent'], $breadcrumb->getCacheContexts()); $this->assertEquals([], $breadcrumb->getCacheTags()); $this->assertEquals(Cache::PERMANENT, $breadcrumb->getCacheMaxAge()); } @@ -203,7 +203,11 @@ public function testBuildWithTwoPathElements() { $breadcrumb = $this->builder->build($this->getMock('Drupal\Core\Routing\RouteMatchInterface')); $this->assertEquals([0 => new Link('Home', new Url('<front>')), 1 => new Link('Example', new Url('example'))], $breadcrumb->getLinks()); - $this->assertEquals(['url.path.parent', 'user.permissions'], $breadcrumb->getCacheContexts()); + $this->assertEquals([ + 'url.path.is_front', + 'url.path.parent', + 'user.permissions', + ], $breadcrumb->getCacheContexts()); $this->assertEquals([], $breadcrumb->getCacheTags()); $this->assertEquals(Cache::PERMANENT, $breadcrumb->getCacheMaxAge()); } @@ -254,7 +258,12 @@ public function testBuildWithThreePathElements() { new Link('Example', new Url('example')), new Link('Bar', new Url('example_bar')), ], $breadcrumb->getLinks()); - $this->assertEquals(['bar', 'url.path.parent', 'user.permissions'], $breadcrumb->getCacheContexts()); + $this->assertEquals([ + 'bar', + 'url.path.is_front', + 'url.path.parent', + 'user.permissions', + ], $breadcrumb->getCacheContexts()); $this->assertEquals(['example'], $breadcrumb->getCacheTags()); $this->assertEquals(Cache::PERMANENT, $breadcrumb->getCacheMaxAge()); } @@ -281,7 +290,7 @@ public function testBuildWithException($exception_class, $exception_argument) { // No path matched, though at least the frontpage is displayed. $this->assertEquals([0 => new Link('Home', new Url('<front>'))], $breadcrumb->getLinks()); - $this->assertEquals(['url.path.parent'], $breadcrumb->getCacheContexts()); + $this->assertEquals(['url.path.is_front', 'url.path.parent'], $breadcrumb->getCacheContexts()); $this->assertEquals([], $breadcrumb->getCacheTags()); $this->assertEquals(Cache::PERMANENT, $breadcrumb->getCacheMaxAge()); } @@ -325,7 +334,7 @@ public function testBuildWithNonProcessedPath() { // No path matched, though at least the frontpage is displayed. $this->assertEquals([0 => new Link('Home', new Url('<front>'))], $breadcrumb->getLinks()); - $this->assertEquals(['url.path.parent'], $breadcrumb->getCacheContexts()); + $this->assertEquals(['url.path.is_front', 'url.path.parent'], $breadcrumb->getCacheContexts()); $this->assertEquals([], $breadcrumb->getCacheTags()); $this->assertEquals(Cache::PERMANENT, $breadcrumb->getCacheMaxAge()); } @@ -373,7 +382,11 @@ public function testBuildWithUserPath() { $breadcrumb = $this->builder->build($this->getMock('Drupal\Core\Routing\RouteMatchInterface')); $this->assertEquals([0 => new Link('Home', new Url('<front>')), 1 => new Link('Admin', new Url('user_page'))], $breadcrumb->getLinks()); - $this->assertEquals(['url.path.parent', 'user.permissions'], $breadcrumb->getCacheContexts()); + $this->assertEquals([ + 'url.path.is_front', + 'url.path.parent', + 'user.permissions', + ], $breadcrumb->getCacheContexts()); $this->assertEquals([], $breadcrumb->getCacheTags()); $this->assertEquals(Cache::PERMANENT, $breadcrumb->getCacheMaxAge()); } diff --git a/web/core/modules/system/tests/themes/test_theme/test_theme.info.yml b/web/core/modules/system/tests/themes/test_theme/test_theme.info.yml index b73a45d7c6221855c78aea1dfc6d309f2604a049..b9660a45f52a654a2be8c2f159ab59318529e1c5 100644 --- a/web/core/modules/system/tests/themes/test_theme/test_theme.info.yml +++ b/web/core/modules/system/tests/themes/test_theme/test_theme.info.yml @@ -16,7 +16,7 @@ base theme: classy core: 8.x logo: images/logo2.svg stylesheets-remove: - - '@system/css/js.module.css' + - '@stable/css/system/components/js.module.css' libraries: - test_theme/global-styling libraries-override: diff --git a/web/core/modules/system/tests/themes/test_theme_settings/config/schema/test_theme_settings.schema.yml b/web/core/modules/system/tests/themes/test_theme_settings/config/schema/test_theme_settings.schema.yml index a53e94a0c563afb02f3c7cbd2e734b92d02cb2c9..482577f2d1e236d0841b9666fb4b35de57bbaaa7 100644 --- a/web/core/modules/system/tests/themes/test_theme_settings/config/schema/test_theme_settings.schema.yml +++ b/web/core/modules/system/tests/themes/test_theme_settings/config/schema/test_theme_settings.schema.yml @@ -10,3 +10,9 @@ test_theme_settings.settings: sequence: type: integer label: 'fids' + multi_file: + type: sequence + label: 'Multiple file field with all file extensions' + sequence: + type: integer + label: 'fids' diff --git a/web/core/modules/system/tests/themes/test_theme_settings/theme-settings.php b/web/core/modules/system/tests/themes/test_theme_settings/theme-settings.php index 7f3c1395f9fb5b199831f2c1d254c7dc34176ce9..1255c65379a054e64edc47a79db873a52079bacf 100644 --- a/web/core/modules/system/tests/themes/test_theme_settings/theme-settings.php +++ b/web/core/modules/system/tests/themes/test_theme_settings/theme-settings.php @@ -24,6 +24,17 @@ function test_theme_settings_form_system_theme_settings_alter(&$form, FormStateI ], ]; + $form['multi_file'] = [ + '#type' => 'managed_file', + '#title' => t('Multiple file field with all file extensions'), + '#multiple' => TRUE, + '#default_value' => theme_get_setting('multi_file'), + '#upload_location' => 'public://test', + '#upload_validators' => [ + 'file_validate_extensions' => [], + ], + ]; + $form['#submit'][] = 'test_theme_settings_form_system_theme_settings_submit'; } diff --git a/web/core/modules/taxonomy/migrations/d6_vocabulary_field_instance.yml b/web/core/modules/taxonomy/migrations/d6_vocabulary_field_instance.yml index 2c482e2f325d8837901f656136e83551e5d78265..2206cfb57aaad4a5b49a84651d7a0ddb0bf68a4a 100644 --- a/web/core/modules/taxonomy/migrations/d6_vocabulary_field_instance.yml +++ b/web/core/modules/taxonomy/migrations/d6_vocabulary_field_instance.yml @@ -51,6 +51,21 @@ process: 'settings/handler_settings/target_bundles/0': '@field_name' 'settings/handler_settings/auto_create': 'constants/auto_create' required: required + # Get the i18n taxonomy translation setting for this vocabulary. + # 0 - No multilingual options + # 1 - Localizable terms. Run through the localization system. + # 2 - Predefined language for a vocabulary and its terms. + # 3 - Per-language terms, translatable (referencing terms with different + # languages) but not localizable. + translatable: + plugin: static_map + source: i18ntaxonomy_vocabulary + default_value: 0 + map: + 0: false + 1: false + 2: false + 3: true destination: plugin: entity:field_config migration_dependencies: diff --git a/web/core/modules/taxonomy/migrations/d7_taxonomy_term.yml b/web/core/modules/taxonomy/migrations/d7_taxonomy_term.yml index 0331cf057253ef4580ae7ec985c30aa7f4a0df7e..1bae2d6e32f9d8e6903d3db377b88c16164b877c 100644 --- a/web/core/modules/taxonomy/migrations/d7_taxonomy_term.yml +++ b/web/core/modules/taxonomy/migrations/d7_taxonomy_term.yml @@ -34,6 +34,7 @@ process: source: '@parent_id' forum_container: is_container changed: timestamp + langcode: language destination: plugin: entity:taxonomy_term migration_dependencies: diff --git a/web/core/modules/taxonomy/src/Entity/Vocabulary.php b/web/core/modules/taxonomy/src/Entity/Vocabulary.php index ec8b8663e7e5f51fcc54e63ddfc86e52bfe2c048..2f2833ae3999e02307775053e60f314a4f77d0c7 100644 --- a/web/core/modules/taxonomy/src/Entity/Vocabulary.php +++ b/web/core/modules/taxonomy/src/Entity/Vocabulary.php @@ -87,7 +87,7 @@ class Vocabulary extends ConfigEntityBundleBase implements VocabularyInterface { * Possible values: * - VocabularyInterface::HIERARCHY_DISABLED: No parents. * - VocabularyInterface::HIERARCHY_SINGLE: Single parent. - * - VocabularyInterface::HIERARCHY_MULTIPL: Multiple parents. + * - VocabularyInterface::HIERARCHY_MULTIPLE: Multiple parents. * * @var int */ diff --git a/web/core/modules/taxonomy/src/Plugin/migrate/source/d6/TermLocalizedTranslation.php b/web/core/modules/taxonomy/src/Plugin/migrate/source/d6/TermLocalizedTranslation.php new file mode 100644 index 0000000000000000000000000000000000000000..5348ee23e508ccf2300879afb0ab46cd6e008105 --- /dev/null +++ b/web/core/modules/taxonomy/src/Plugin/migrate/source/d6/TermLocalizedTranslation.php @@ -0,0 +1,100 @@ +<?php + +namespace Drupal\taxonomy\Plugin\migrate\source\d6; + +use Drupal\migrate\Row; + +/** + * Gets i18n taxonomy terms from source database. + * + * @MigrateSource( + * id = "d6_term_localized_translation", + * source_module = "i18ntaxonomy" + * ) + */ +class TermLocalizedTranslation extends Term { + + /** + * {@inheritdoc} + */ + public function query() { + // Ideally, the query would return rows for each language for each taxonomy + // term with the translations for both the name and description or just the + // name translation or just the description translation. That query quickly + // became complex and would be difficult to maintain. + // Therefore, build a query based on i18nstrings table where each row has + // the translation for only one property, either name or description. The + // method prepareRow() is then used to obtain the translation for the other + // property. + $query = parent::query(); + $query->addField('td', 'language', 'td.language'); + + // Add in the property, which is either name or description. + // Cast td.tid as char for PostgreSQL compatibility. + $query->leftJoin('i18n_strings', 'i18n', 'CAST(td.tid AS CHAR(255)) = i18n.objectid'); + $query->isNotNull('i18n.lid'); + $query->addField('i18n', 'lid'); + $query->addField('i18n', 'property'); + + // Add in the translation for the property. + $query->innerJoin('locales_target', 'lt', 'i18n.lid = lt.lid'); + $query->addField('lt', 'language', 'lt.language'); + $query->addField('lt', 'translation'); + return $query; + } + + /** + * {@inheritdoc} + */ + public function prepareRow(Row $row) { + $language = $row->getSourceProperty('ltlanguage'); + $row->setSourceProperty('language', $language); + $tid = $row->getSourceProperty('tid'); + + // If this row has been migrated it is a duplicate then skip it. + if ($this->idMap->lookupDestinationIds(['tid' => $tid, 'language' => $language])) { + return FALSE; + } + + // Save the translation for this property. + $property = $row->getSourceProperty('property'); + $row->setSourceProperty($property . '_translated', $row->getSourceProperty('translation')); + + // Get the translation, if one exists, for the property not already in the + // row. + $other_property = ($property == 'name') ? 'description' : 'name'; + $query = $this->select('i18n_strings', 'i18n') + ->fields('i18n', ['lid']) + ->condition('i18n.property', $other_property) + ->condition('i18n.objectid', $tid); + $query->leftJoin('locales_target', 'lt', 'i18n.lid = lt.lid'); + $query->condition('lt.language', $language); + $query->addField('lt', 'translation'); + $results = $query->execute()->fetchAssoc(); + $row->setSourceProperty($other_property . '_translated', $results['translation']); + + parent::prepareRow($row); + } + + /** + * {@inheritdoc} + */ + public function fields() { + $fields = [ + 'language' => $this->t('Language for this term.'), + 'name_translated' => $this->t('Term name translation.'), + 'description_translated' => $this->t('Term description translation.'), + ]; + return parent::fields() + $fields; + } + + /** + * {@inheritdoc} + */ + public function getIds() { + $ids['language']['type'] = 'string'; + $ids['language']['alias'] = 'lt'; + return parent::getIds() + $ids; + } + +} diff --git a/web/core/modules/taxonomy/src/Plugin/migrate/source/d6/VocabularyPerType.php b/web/core/modules/taxonomy/src/Plugin/migrate/source/d6/VocabularyPerType.php index ba736ea8ac8ebeac7dac8a1c8300701222ed8fc9..db752eaac57bb939e547d8e4c6069d3e38b436a9 100644 --- a/web/core/modules/taxonomy/src/Plugin/migrate/source/d6/VocabularyPerType.php +++ b/web/core/modules/taxonomy/src/Plugin/migrate/source/d6/VocabularyPerType.php @@ -2,6 +2,8 @@ namespace Drupal\taxonomy\Plugin\migrate\source\d6; +use Drupal\migrate\Row; + /** * Gets all the vocabularies based on the node types that have Taxonomy enabled. * @@ -22,6 +24,26 @@ public function query() { return $query; } + /** + * {@inheritdoc} + */ + public function prepareRow(Row $row) { + // Get the i18n taxonomy translation setting for this vocabulary. + // 0 - No multilingual options + // 1 - Localizable terms. Run through the localization system. + // 2 - Predefined language for a vocabulary and its terms. + // 3 - Per-language terms, translatable (referencing terms with different + // languages) but not localizable. + $i18ntaxonomy_vocab = $this->variableGet('i18ntaxonomy_vocabulary', NULL); + $vid = $row->getSourceProperty('vid'); + $i18ntaxonomy_vocabulary = FALSE; + if (array_key_exists($vid, $i18ntaxonomy_vocab)) { + $i18ntaxonomy_vocabulary = $i18ntaxonomy_vocab[$vid]; + } + $row->setSourceProperty('i18ntaxonomy_vocabulary', $i18ntaxonomy_vocabulary); + return parent::prepareRow($row); + } + /** * {@inheritdoc} */ diff --git a/web/core/modules/taxonomy/src/Plugin/migrate/source/d7/Term.php b/web/core/modules/taxonomy/src/Plugin/migrate/source/d7/Term.php index 658f4422b48014e527d605355b9fff6b25c35bd9..18d94ff5d0920aa22e2b8dfe102634619d51f820 100644 --- a/web/core/modules/taxonomy/src/Plugin/migrate/source/d7/Term.php +++ b/web/core/modules/taxonomy/src/Plugin/migrate/source/d7/Term.php @@ -56,10 +56,26 @@ public function fields() { * {@inheritdoc} */ public function prepareRow(Row $row) { + $tid = $row->getSourceProperty('tid'); + $vocabulary = $row->getSourceProperty('machine_name'); + $default_language = (array) $this->variableGet('language_default', ['language' => 'en']); + + // If this entity was translated using Entity Translation, we need to get + // its source language to get the field values in the right language. + // The translations will be migrated by the d7_node_entity_translation + // migration. + $translatable_vocabularies = array_keys(array_filter($this->variableGet('entity_translation_taxonomy', []))); + $entity_translatable = $this->isEntityTranslatable('taxonomy_term') && in_array($vocabulary, $translatable_vocabularies, TRUE); + $source_language = $this->getEntityTranslationSourceLanguage('taxonomy_term', $tid); + $language = $entity_translatable && $source_language ? $source_language : $default_language['language']; + $row->setSourceProperty('language', $language); + // Get Field API field values. - foreach (array_keys($this->getFields('taxonomy_term', $row->getSourceProperty('machine_name'))) as $field) { - $tid = $row->getSourceProperty('tid'); - $row->setSourceProperty($field, $this->getFieldValues('taxonomy_term', $field, $tid)); + foreach ($this->getFields('taxonomy_term', $vocabulary) as $field_name => $field) { + // Ensure we're using the right language if the entity and the field are + // translatable. + $field_language = $entity_translatable && $field['translatable'] ? $language : NULL; + $row->setSourceProperty($field_name, $this->getFieldValues('taxonomy_term', $field_name, $tid, NULL, $field_language)); } // Find parents for this row. @@ -87,6 +103,9 @@ public function prepareRow(Row $row) { if (isset($description_field[0]['value'])) { $row->setSourceProperty('description', $description_field[0]['value']); } + if (isset($description_field[0]['format'])) { + $row->setSourceProperty('format', $description_field[0]['format']); + } } return parent::prepareRow($row); diff --git a/web/core/modules/taxonomy/src/Plugin/migrate/source/d7/TermEntityTranslation.php b/web/core/modules/taxonomy/src/Plugin/migrate/source/d7/TermEntityTranslation.php new file mode 100644 index 0000000000000000000000000000000000000000..0ba70c8d2b03eea797a68f4e75f93665637bbb1a --- /dev/null +++ b/web/core/modules/taxonomy/src/Plugin/migrate/source/d7/TermEntityTranslation.php @@ -0,0 +1,122 @@ +<?php + +namespace Drupal\taxonomy\Plugin\migrate\source\d7; + +use Drupal\migrate\Row; +use Drupal\migrate_drupal\Plugin\migrate\source\d7\FieldableEntity; + +/** + * Provides Drupal 7 taxonomy term entity translation source plugin. + * + * @MigrateSource( + * id = "d7_taxonomy_term_entity_translation", + * source_module = "entity_translation" + * ) + */ +class TermEntityTranslation extends FieldableEntity { + + /** + * {@inheritdoc} + */ + public function query() { + $query = $this->select('entity_translation', 'et') + ->fields('et') + ->fields('td', [ + 'name', + 'description', + 'format', + ]) + ->fields('tv', [ + 'machine_name', + ]) + ->condition('et.entity_type', 'taxonomy_term') + ->condition('et.source', '', '<>'); + + $query->innerJoin('taxonomy_term_data', 'td', 'td.tid = et.entity_id'); + $query->innerJoin('taxonomy_vocabulary', 'tv', 'td.vid = tv.vid'); + + if (isset($this->configuration['bundle'])) { + $query->condition('tv.machine_name', (array) $this->configuration['bundle'], 'IN'); + } + + return $query; + } + + /** + * {@inheritdoc} + */ + public function prepareRow(Row $row) { + $tid = $row->getSourceProperty('entity_id'); + $vocabulary = $row->getSourceProperty('machine_name'); + $language = $row->getSourceProperty('language'); + + // Get Field API field values. + foreach ($this->getFields('taxonomy_term', $vocabulary) as $field_name => $field) { + // Ensure we're using the right language if the entity is translatable. + $field_language = $field['translatable'] ? $language : NULL; + $row->setSourceProperty($field_name, $this->getFieldValues('taxonomy_term', $field_name, $tid, NULL, $field_language)); + } + + // If the term name or term description were replaced by real fields using + // the Drupal 7 Title module, use the fields value instead of the term name + // or term description. + if ($this->moduleExists('title')) { + $name_field = $row->getSourceProperty('name_field'); + if (isset($name_field[0]['value'])) { + $row->setSourceProperty('name', $name_field[0]['value']); + } + $description_field = $row->getSourceProperty('description_field'); + if (isset($description_field[0]['value'])) { + $row->setSourceProperty('description', $description_field[0]['value']); + } + if (isset($description_field[0]['format'])) { + $row->setSourceProperty('format', $description_field[0]['format']); + } + } + + // Determine if this is a forum container. + $forum_container_tids = $this->variableGet('forum_containers', []); + $row->setSourceProperty('is_container', in_array($tid, $forum_container_tids)); + + return parent::prepareRow($row); + } + + /** + * {@inheritdoc} + */ + public function fields() { + return [ + 'entity_type' => $this->t('The entity type this translation relates to'), + 'entity_id' => $this->t('The entity ID this translation relates to'), + 'revision_id' => $this->t('The entity revision ID this translation relates to'), + 'language' => $this->t('The target language for this translation.'), + 'source' => $this->t('The source language from which this translation was created.'), + 'uid' => $this->t('The author of this translation.'), + 'status' => $this->t('Boolean indicating whether the translation is published (visible to non-administrators).'), + 'translate' => $this->t('A boolean indicating whether this translation needs to be updated.'), + 'created' => $this->t('The Unix timestamp when the translation was created.'), + 'changed' => $this->t('The Unix timestamp when the translation was most recently saved.'), + 'name' => $this->t('The name of the term.'), + 'description' => $this->t('The term description.'), + 'format' => $this->t('Format of the term description.'), + 'machine_name' => $this->t('Vocabulary machine name'), + ]; + } + + /** + * {@inheritdoc} + */ + public function getIds() { + return [ + 'entity_id' => [ + 'type' => 'integer', + 'alias' => 'et', + ], + 'language' => [ + 'type' => 'string', + 'alias' => 'et', + ], + ]; + } + +} diff --git a/web/core/modules/taxonomy/src/TermStorageSchema.php b/web/core/modules/taxonomy/src/TermStorageSchema.php index 4351b60a2fdc9186b64282f7ccc99b9b017f17de..4892b52ccb56399c2a7766fadee63131490fb878 100644 --- a/web/core/modules/taxonomy/src/TermStorageSchema.php +++ b/web/core/modules/taxonomy/src/TermStorageSchema.php @@ -15,7 +15,7 @@ class TermStorageSchema extends SqlContentEntityStorageSchema { * {@inheritdoc} */ protected function getEntitySchema(ContentEntityTypeInterface $entity_type, $reset = FALSE) { - $schema = parent::getEntitySchema($entity_type, $reset = FALSE); + $schema = parent::getEntitySchema($entity_type, $reset); if ($data_table = $this->storage->getDataTable()) { $schema[$data_table]['indexes'] += [ diff --git a/web/core/modules/taxonomy/src/Tests/TaxonomyTestBase.php b/web/core/modules/taxonomy/src/Tests/TaxonomyTestBase.php index b4f941da5b666d7f62dc15e9ebaea37b9224f4f3..eb9e5e983b3489c1125bc3f0afaec18cff1c4c74 100644 --- a/web/core/modules/taxonomy/src/Tests/TaxonomyTestBase.php +++ b/web/core/modules/taxonomy/src/Tests/TaxonomyTestBase.php @@ -4,8 +4,8 @@ @trigger_error(__NAMESPACE__ . '\TaxonomyTestBase is deprecated in Drupal 8.4.0 and will be removed before Drupal 9.0.0. Instead, use \Drupal\Tests\taxonomy\Functional\TaxonomyTestBase', E_USER_DEPRECATED); -use Drupal\field\Tests\EntityReference\EntityReferenceTestTrait; use Drupal\simpletest\WebTestBase; +use Drupal\Tests\field\Traits\EntityReferenceTestTrait; use Drupal\Tests\taxonomy\Functional\TaxonomyTestTrait; /** diff --git a/web/core/modules/taxonomy/src/Tests/TaxonomyTranslationTestTrait.php b/web/core/modules/taxonomy/src/Tests/TaxonomyTranslationTestTrait.php index 6f2f1198733f0293386eb5f31522a1e2bbb1c717..98d5906fb9bee64f2e29dcb9850a1f96a881798d 100644 --- a/web/core/modules/taxonomy/src/Tests/TaxonomyTranslationTestTrait.php +++ b/web/core/modules/taxonomy/src/Tests/TaxonomyTranslationTestTrait.php @@ -5,9 +5,9 @@ @trigger_error(__NAMESPACE__ . '\TaxonomyTranslationTestTrait is deprecated in Drupal 8.4.0 and will be removed before Drupal 9.0.0. Instead, use \Drupal\Tests\taxonomy\Functional\TaxonomyTranslationTestTrait', E_USER_DEPRECATED); use Drupal\Core\Field\FieldStorageDefinitionInterface; -use Drupal\field\Tests\EntityReference\EntityReferenceTestTrait; use Drupal\field\Entity\FieldStorageConfig; use Drupal\language\Entity\ConfigurableLanguage; +use Drupal\Tests\field\Traits\EntityReferenceTestTrait; /** * Provides common testing base for translated taxonomy terms. diff --git a/web/core/modules/taxonomy/taxonomy.install b/web/core/modules/taxonomy/taxonomy.install index bbcb8349ae820deb85b20d246e7be9a59c3abda5..54a84d5ac24c2e91169c92620a82dd81711882b0 100644 --- a/web/core/modules/taxonomy/taxonomy.install +++ b/web/core/modules/taxonomy/taxonomy.install @@ -32,7 +32,12 @@ function taxonomy_update_8502(&$sandbox) { $sandbox['tid'] = -1; $sandbox['delta'] = 0; $sandbox['limit'] = Settings::get('entity_update_batch_size', 50); - $sandbox['max'] = $database->select('taxonomy_term_hierarchy') + + // Count records using a join, as there might be orphans in the hierarchy + // table. See https://www.drupal.org/project/drupal/issues/2997982. + $select = $database->select('taxonomy_term_hierarchy', 'h'); + $select->join('taxonomy_term_data', 'd', 'h.tid = d.tid'); + $sandbox['max'] = $select ->countQuery() ->execute() ->fetchField(); diff --git a/web/core/modules/taxonomy/src/Tests/RssTest.php b/web/core/modules/taxonomy/tests/src/Functional/RssTest.php similarity index 92% rename from web/core/modules/taxonomy/src/Tests/RssTest.php rename to web/core/modules/taxonomy/tests/src/Functional/RssTest.php index c4f48846b436e6f2911f25f988cef7fa67143d7d..2f22196469154f9dc3ff69bbaf7be7507ac909de 100644 --- a/web/core/modules/taxonomy/src/Tests/RssTest.php +++ b/web/core/modules/taxonomy/tests/src/Functional/RssTest.php @@ -1,6 +1,6 @@ <?php -namespace Drupal\taxonomy\Tests; +namespace Drupal\Tests\taxonomy\Functional; use Drupal\Core\Field\FieldStorageDefinitionInterface; use Drupal\views\Views; @@ -106,7 +106,11 @@ public function testTaxonomyRss() { // Test that the feed page exists for the term. $this->drupalGet("taxonomy/term/{$term1->id()}/feed"); - $this->assertTrue(!empty($this->cssSelect('rss[version="2.0"]')), "Feed page is RSS."); + $assert = $this->assertSession(); + $assert->responseHeaderContains('Content-Type', 'application/rss+xml'); + // Ensure the RSS version is 2.0. + $rss_array = $this->getSession()->getDriver()->find('rss'); + $this->assertEquals('2.0', reset($rss_array)->getAttribute('version')); // Check that the "Exception value" is disabled by default. $this->drupalGet('taxonomy/term/all/feed'); diff --git a/web/core/modules/taxonomy/src/Tests/TaxonomyTermIndentationTest.php b/web/core/modules/taxonomy/tests/src/Functional/TaxonomyTermIndentationTest.php similarity index 68% rename from web/core/modules/taxonomy/src/Tests/TaxonomyTermIndentationTest.php rename to web/core/modules/taxonomy/tests/src/Functional/TaxonomyTermIndentationTest.php index 599b6fb2c7a790244aa18e90ba71017c0a23337e..c701dfeebaf5e36b5c143783e313c8dbafa991e1 100644 --- a/web/core/modules/taxonomy/src/Tests/TaxonomyTermIndentationTest.php +++ b/web/core/modules/taxonomy/tests/src/Functional/TaxonomyTermIndentationTest.php @@ -1,6 +1,6 @@ <?php -namespace Drupal\taxonomy\Tests; +namespace Drupal\Tests\taxonomy\Functional; /** * Ensure that the term indentation works properly. @@ -33,6 +33,7 @@ protected function setUp() { * Tests term indentation. */ public function testTermIndentation() { + $assert = $this->assertSession(); // Create three taxonomy terms. $term1 = $this->createTerm($this->vocabulary); $term2 = $this->createTerm($this->vocabulary); @@ -42,15 +43,23 @@ public function testTermIndentation() { $taxonomy_storage = $this->container->get('entity.manager')->getStorage('taxonomy_term'); // Indent the second term under the first one. - $edit = [ + $this->drupalGet('admin/structure/taxonomy/manage/' . $this->vocabulary->get('vid') . '/overview'); + $hidden_edit = [ 'terms[tid:' . $term2->id() . ':0][term][tid]' => 2, 'terms[tid:' . $term2->id() . ':0][term][parent]' => 1, 'terms[tid:' . $term2->id() . ':0][term][depth]' => 1, + ]; + // Because we can't post hidden form elements, we have to change them in + // code here, and then submit. + foreach ($hidden_edit as $field => $value) { + $node = $assert->hiddenFieldExists($field); + $node->setValue($value); + } + $edit = [ 'terms[tid:' . $term2->id() . ':0][weight]' => 1, ]; - // Submit the edited form and check for HTML indentation element presence. - $this->drupalPostForm('admin/structure/taxonomy/manage/' . $this->vocabulary->get('vid') . '/overview', $edit, t('Save')); + $this->drupalPostForm(NULL, $edit, t('Save')); $this->assertPattern('|<div class="js-indentation indentation"> </div>|'); // Check explicitly that term 2's parent is term 1. @@ -58,16 +67,24 @@ public function testTermIndentation() { $this->assertEqual(key($parents), 1, 'Term 1 is the term 2\'s parent'); // Move the second term back out to the root level. - $edit = [ + $this->drupalGet('admin/structure/taxonomy/manage/' . $this->vocabulary->get('vid') . '/overview'); + $hidden_edit = [ 'terms[tid:' . $term2->id() . ':0][term][tid]' => 2, 'terms[tid:' . $term2->id() . ':0][term][parent]' => 0, 'terms[tid:' . $term2->id() . ':0][term][depth]' => 0, + ]; + // Because we can't post hidden form elements, we have to change them in + // code here, and then submit. + foreach ($hidden_edit as $field => $value) { + $node = $assert->hiddenFieldExists($field); + $node->setValue($value); + } + $edit = [ 'terms[tid:' . $term2->id() . ':0][weight]' => 1, ]; - - $this->drupalPostForm('admin/structure/taxonomy/manage/' . $this->vocabulary->get('vid') . '/overview', $edit, t('Save')); + $this->drupalPostForm(NULL, $edit, t('Save')); // All terms back at the root level, no indentation should be present. - $this->assertNoPattern('|<div class="js-indentation indentation"> </div>|'); + $this->assertSession()->responseNotMatches('|<div class="js-indentation indentation"> </div>|'); // Check explicitly that term 2 has no parents. \Drupal::entityManager()->getStorage('taxonomy_term')->resetCache(); diff --git a/web/core/modules/taxonomy/tests/src/Functional/TaxonomyTestBase.php b/web/core/modules/taxonomy/tests/src/Functional/TaxonomyTestBase.php index fdbfccd30341c1badd0624b0f0f28023f71f37be..b75295ad0de2bac152ff20867cd2facb86c52b14 100644 --- a/web/core/modules/taxonomy/tests/src/Functional/TaxonomyTestBase.php +++ b/web/core/modules/taxonomy/tests/src/Functional/TaxonomyTestBase.php @@ -2,8 +2,8 @@ namespace Drupal\Tests\taxonomy\Functional; -use Drupal\field\Tests\EntityReference\EntityReferenceTestTrait; use Drupal\Tests\BrowserTestBase; +use Drupal\Tests\field\Traits\EntityReferenceTestTrait; /** * Provides common helper methods for Taxonomy module tests. diff --git a/web/core/modules/taxonomy/tests/src/Functional/TaxonomyTranslationTestTrait.php b/web/core/modules/taxonomy/tests/src/Functional/TaxonomyTranslationTestTrait.php index a817e12354a82339493ef9fb0d0ee4c3e1311c7e..36ac06954dc971ca501aa9022e898aeda3179ba0 100644 --- a/web/core/modules/taxonomy/tests/src/Functional/TaxonomyTranslationTestTrait.php +++ b/web/core/modules/taxonomy/tests/src/Functional/TaxonomyTranslationTestTrait.php @@ -3,9 +3,9 @@ namespace Drupal\Tests\taxonomy\Functional; use Drupal\Core\Field\FieldStorageDefinitionInterface; -use Drupal\field\Tests\EntityReference\EntityReferenceTestTrait; use Drupal\field\Entity\FieldStorageConfig; use Drupal\language\Entity\ConfigurableLanguage; +use Drupal\Tests\field\Traits\EntityReferenceTestTrait; /** * Provides common testing base for translated taxonomy terms. diff --git a/web/core/modules/taxonomy/src/Tests/TermAutocompleteTest.php b/web/core/modules/taxonomy/tests/src/Functional/TermAutocompleteTest.php similarity index 82% rename from web/core/modules/taxonomy/src/Tests/TermAutocompleteTest.php rename to web/core/modules/taxonomy/tests/src/Functional/TermAutocompleteTest.php index ce28b1285d76055eabb959f07ae8596ef3d899cb..6304976176a7cf935a6d8395115c753104688523 100644 --- a/web/core/modules/taxonomy/src/Tests/TermAutocompleteTest.php +++ b/web/core/modules/taxonomy/tests/src/Functional/TermAutocompleteTest.php @@ -1,7 +1,8 @@ <?php -namespace Drupal\taxonomy\Tests; +namespace Drupal\Tests\taxonomy\Functional; +use Drupal\Component\Serialization\Json; use Drupal\Core\Entity\Entity\EntityFormDisplay; use Drupal\Core\Entity\Entity\EntityViewDisplay; use Drupal\Core\Field\FieldStorageDefinitionInterface; @@ -15,6 +16,13 @@ */ class TermAutocompleteTest extends TaxonomyTestBase { + /** + * Modules to enable. + * + * @var array + */ + public static $modules = ['node']; + /** * The vocabulary. * @@ -127,7 +135,25 @@ protected function setUp() { // Retrieve the autocomplete url. $this->drupalGet('node/add/article'); $result = $this->xpath('//input[@name="' . $this->fieldName . '[0][target_id]"]'); - $this->autocompleteUrl = $this->getAbsoluteUrl($result[0]['data-autocomplete-path']); + $this->autocompleteUrl = $this->getAbsoluteUrl($result[0]->getAttribute('data-autocomplete-path')); + } + + /** + * Helper function for JSON formatted requests. + * + * @param string|\Drupal\Core\Url $path + * Drupal path or URL to load into Mink controlled browser. + * @param array $options + * (optional) Options to be forwarded to the url generator. + * @param string[] $headers + * (optional) An array containing additional HTTP request headers. + * + * @return string[] + * Array representing decoded JSON response. + */ + protected function drupalGetJson($path, array $options = [], array $headers = []) { + $options = array_merge_recursive(['query' => ['_format' => 'json']], $options); + return Json::decode($this->drupalGet($path, $options, $headers)); } /** @@ -137,21 +163,21 @@ protected function setUp() { */ public function testAutocompleteCountResults() { // Test that no matching term found. - $data = $this->drupalGetJSON( + $data = $this->drupalGetJson( $this->autocompleteUrl, ['query' => ['q' => 'zzz']] ); $this->assertTrue(empty($data), 'Autocomplete returned no results'); // Test that only one matching term found, when only one matches. - $data = $this->drupalGetJSON( + $data = $this->drupalGetJson( $this->autocompleteUrl, ['query' => ['q' => 'aaa 10']] ); $this->assertEqual(1, count($data), 'Autocomplete returned 1 result'); // Test the correct number of matches when multiple are partial matches. - $data = $this->drupalGetJSON( + $data = $this->drupalGetJson( $this->autocompleteUrl, ['query' => ['q' => 'aaa 1']] ); @@ -159,7 +185,7 @@ public function testAutocompleteCountResults() { // Tests that only 10 results are returned, even if there are more than 10 // matches. - $data = $this->drupalGetJSON( + $data = $this->drupalGetJson( $this->autocompleteUrl, ['query' => ['q' => 'aaa']] ); @@ -192,7 +218,7 @@ public function testAutocompleteOrderedResults() { ]; } - $data = $this->drupalGetJSON( + $data = $this->drupalGetJson( $this->autocompleteUrl, ['query' => ['q' => 'bbb']] ); diff --git a/web/core/modules/taxonomy/src/Tests/TermTest.php b/web/core/modules/taxonomy/tests/src/Functional/TermTest.php similarity index 95% rename from web/core/modules/taxonomy/src/Tests/TermTest.php rename to web/core/modules/taxonomy/tests/src/Functional/TermTest.php index 54309c4237e2a8f5089c93fc2c1aea53880a7eaf..cce58da942ba60ea483ace7408bcb89caaa4f209 100644 --- a/web/core/modules/taxonomy/src/Tests/TermTest.php +++ b/web/core/modules/taxonomy/tests/src/Functional/TermTest.php @@ -1,6 +1,6 @@ <?php -namespace Drupal\taxonomy\Tests; +namespace Drupal\Tests\taxonomy\Functional; use Drupal\Component\Utility\Tags; use Drupal\Core\Field\FieldStorageDefinitionInterface; @@ -389,6 +389,7 @@ public function testTermInterface() { * Save, edit and delete a term using the user interface. */ public function testTermReorder() { + $assert = $this->assertSession(); $this->createTerm($this->vocabulary); $this->createTerm($this->vocabulary); $this->createTerm($this->vocabulary); @@ -406,21 +407,30 @@ public function testTermReorder() { // "tid:1:0[depth]", and "tid:1:0[weight]". Change the order to term2, // term3, term1 by setting weight property, make term3 a child of term2 by // setting the parent and depth properties, and update all hidden fields. - $edit = [ + $hidden_edit = [ 'terms[tid:' . $term2->id() . ':0][term][tid]' => $term2->id(), 'terms[tid:' . $term2->id() . ':0][term][parent]' => 0, 'terms[tid:' . $term2->id() . ':0][term][depth]' => 0, - 'terms[tid:' . $term2->id() . ':0][weight]' => 0, 'terms[tid:' . $term3->id() . ':0][term][tid]' => $term3->id(), 'terms[tid:' . $term3->id() . ':0][term][parent]' => $term2->id(), 'terms[tid:' . $term3->id() . ':0][term][depth]' => 1, - 'terms[tid:' . $term3->id() . ':0][weight]' => 1, 'terms[tid:' . $term1->id() . ':0][term][tid]' => $term1->id(), 'terms[tid:' . $term1->id() . ':0][term][parent]' => 0, 'terms[tid:' . $term1->id() . ':0][term][depth]' => 0, + ]; + // Because we can't post hidden form elements, we have to change them in + // code here, and then submit. + foreach ($hidden_edit as $field => $value) { + $node = $assert->hiddenFieldExists($field); + $node->setValue($value); + } + // Edit non-hidden elements within drupalPostForm(). + $edit = [ + 'terms[tid:' . $term2->id() . ':0][weight]' => 0, + 'terms[tid:' . $term3->id() . ':0][weight]' => 1, 'terms[tid:' . $term1->id() . ':0][weight]' => 2, ]; - $this->drupalPostForm(NULL, $edit, t('Save')); + $this->drupalPostForm(NULL, $edit, 'Save'); $taxonomy_storage->resetCache(); $terms = $taxonomy_storage->loadTree($this->vocabulary->id()); @@ -570,7 +580,7 @@ public function testTermBreadcrumbs() { ]; // Create the term. - $this->drupalPostForm('admin/structure/taxonomy/manage/' . $this->vocabulary->id() . '/add', $edit, t('Save')); + $this->drupalPostForm('admin/structure/taxonomy/manage/' . $this->vocabulary->id() . '/add', $edit, 'Save'); $terms = taxonomy_term_load_multiple_by_name($edit['name[0][value]']); $term = reset($terms); @@ -578,19 +588,19 @@ public function testTermBreadcrumbs() { // Check the breadcrumb on the term edit page. $this->drupalGet('taxonomy/term/' . $term->id() . '/edit'); - $breadcrumbs = $this->cssSelect('nav.breadcrumb ol li a'); + $breadcrumbs = $this->getSession()->getPage()->findAll('css', 'nav.breadcrumb ol li a'); $this->assertIdentical(count($breadcrumbs), 2, 'The breadcrumbs are present on the page.'); - $this->assertIdentical((string) $breadcrumbs[0], 'Home', 'First breadcrumb text is Home'); - $this->assertIdentical((string) $breadcrumbs[1], $term->label(), 'Second breadcrumb text is term name on term edit page.'); - $this->assertEscaped((string) $breadcrumbs[1], 'breadcrumbs displayed and escaped.'); + $this->assertIdentical($breadcrumbs[0]->getText(), 'Home', 'First breadcrumb text is Home'); + $this->assertIdentical($breadcrumbs[1]->getText(), $term->label(), 'Second breadcrumb text is term name on term edit page.'); + $this->assertEscaped($breadcrumbs[1]->getText(), 'breadcrumbs displayed and escaped.'); // Check the breadcrumb on the term delete page. $this->drupalGet('taxonomy/term/' . $term->id() . '/delete'); - $breadcrumbs = $this->cssSelect('nav.breadcrumb ol li a'); + $breadcrumbs = $this->getSession()->getPage()->findAll('css', 'nav.breadcrumb ol li a'); $this->assertIdentical(count($breadcrumbs), 2, 'The breadcrumbs are present on the page.'); - $this->assertIdentical((string) $breadcrumbs[0], 'Home', 'First breadcrumb text is Home'); - $this->assertIdentical((string) $breadcrumbs[1], $term->label(), 'Second breadcrumb text is term name on term delete page.'); - $this->assertEscaped((string) $breadcrumbs[1], 'breadcrumbs displayed and escaped.'); + $this->assertIdentical($breadcrumbs[0]->getText(), 'Home', 'First breadcrumb text is Home'); + $this->assertIdentical($breadcrumbs[1]->getText(), $term->label(), 'Second breadcrumb text is term name on term delete page.'); + $this->assertEscaped($breadcrumbs[1]->getText(), 'breadcrumbs displayed and escaped.'); } } diff --git a/web/core/modules/taxonomy/src/Tests/TermTranslationTest.php b/web/core/modules/taxonomy/tests/src/Functional/TermTranslationTest.php similarity index 97% rename from web/core/modules/taxonomy/src/Tests/TermTranslationTest.php rename to web/core/modules/taxonomy/tests/src/Functional/TermTranslationTest.php index ccb16f611db5b7471a9252b4d8ca1ab58c16cf3a..bd9085017b64c6da7fef6e745c909a8ee9d5b9d2 100644 --- a/web/core/modules/taxonomy/src/Tests/TermTranslationTest.php +++ b/web/core/modules/taxonomy/tests/src/Functional/TermTranslationTest.php @@ -1,9 +1,9 @@ <?php -namespace Drupal\taxonomy\Tests; +namespace Drupal\Tests\taxonomy\Functional; use Drupal\Core\Url; -use Drupal\system\Tests\Menu\AssertBreadcrumbTrait; +use Drupal\Tests\system\Functional\Menu\AssertBreadcrumbTrait; /** * Tests for proper breadcrumb translation. diff --git a/web/core/modules/taxonomy/tests/src/Functional/Views/TaxonomyIndexTidUiTest.php b/web/core/modules/taxonomy/tests/src/Functional/Views/TaxonomyIndexTidUiTest.php index 992e5bee18ccd3aefaf90241851f81789b8c68a4..8b1b822e3e32140cf7b8d9adf7a60a29b0f1a20e 100644 --- a/web/core/modules/taxonomy/tests/src/Functional/Views/TaxonomyIndexTidUiTest.php +++ b/web/core/modules/taxonomy/tests/src/Functional/Views/TaxonomyIndexTidUiTest.php @@ -2,7 +2,7 @@ namespace Drupal\Tests\taxonomy\Functional\Views; -use Drupal\field\Tests\EntityReference\EntityReferenceTestTrait; +use Drupal\Tests\field\Traits\EntityReferenceTestTrait; use Drupal\taxonomy\Entity\Term; use Drupal\taxonomy\Entity\Vocabulary; use Drupal\Tests\views_ui\Functional\UITestBase; diff --git a/web/core/modules/taxonomy/tests/src/Functional/Views/TaxonomyTestBase.php b/web/core/modules/taxonomy/tests/src/Functional/Views/TaxonomyTestBase.php index a2d8ec14a380545f77b3c81c98bfdd5122b9a215..d22c109f9d72f01000a408576d91ca9940e62b37 100644 --- a/web/core/modules/taxonomy/tests/src/Functional/Views/TaxonomyTestBase.php +++ b/web/core/modules/taxonomy/tests/src/Functional/Views/TaxonomyTestBase.php @@ -4,7 +4,7 @@ use Drupal\Core\Field\FieldStorageDefinitionInterface; use Drupal\Core\Language\LanguageInterface; -use Drupal\field\Tests\EntityReference\EntityReferenceTestTrait; +use Drupal\Tests\field\Traits\EntityReferenceTestTrait; use Drupal\Tests\views\Functional\ViewTestBase; use Drupal\views\Tests\ViewTestData; use Drupal\taxonomy\Entity\Vocabulary; diff --git a/web/core/modules/taxonomy/tests/src/Kernel/Migrate/d6/MigrateTaxonomyTermTest.php b/web/core/modules/taxonomy/tests/src/Kernel/Migrate/d6/MigrateTaxonomyTermTest.php index 75c79241e0c8eeed939f7cc60dcf9cebbb39be58..20ecb6390346241c7f29b610c7b5e4aaf8d8f840 100644 --- a/web/core/modules/taxonomy/tests/src/Kernel/Migrate/d6/MigrateTaxonomyTermTest.php +++ b/web/core/modules/taxonomy/tests/src/Kernel/Migrate/d6/MigrateTaxonomyTermTest.php @@ -104,7 +104,14 @@ public function testTaxonomyTerms() { $this->assertArrayHasKey($tid, $tree_terms, "Term $tid exists in vocabulary tree"); $tree_term = $tree_terms[$tid]; - $this->assertEquals($values['parent'], $tree_term->parents, "Term $tid has correct parents in vocabulary tree"); + + // PostgreSQL, MySQL and SQLite may not return the parent terms in the + // same order so sort before testing. + $expected_parents = $values['parent']; + sort($expected_parents); + $actual_parents = $tree_term->parents; + sort($actual_parents); + $this->assertEquals($expected_parents, $actual_parents, "Term $tid has correct parents in vocabulary tree"); } } diff --git a/web/core/modules/taxonomy/tests/src/Kernel/Migrate/d6/MigrateTermLocalizedTranslationTest.php b/web/core/modules/taxonomy/tests/src/Kernel/Migrate/d6/MigrateTermLocalizedTranslationTest.php new file mode 100644 index 0000000000000000000000000000000000000000..b051ce689f1c6ded0a7a607fc5261525a75ebe83 --- /dev/null +++ b/web/core/modules/taxonomy/tests/src/Kernel/Migrate/d6/MigrateTermLocalizedTranslationTest.php @@ -0,0 +1,142 @@ +<?php + +namespace Drupal\Tests\taxonomy\Kernel\Migrate\d6; + +use Drupal\Tests\migrate_drupal\Kernel\d6\MigrateDrupal6TestBase; +use Drupal\taxonomy\Entity\Term; +use Drupal\taxonomy\TermInterface; + +/** + * Tests migration of localized translated taxonomy terms. + * + * @group migrate_drupal_6 + */ +class MigrateTermLocalizedTranslationTest extends MigrateDrupal6TestBase { + + /** + * {@inheritdoc} + */ + public static $modules = [ + 'content_translation', + 'language', + 'menu_ui', + 'node', + 'taxonomy', + // Required for translation migrations. + 'migrate_drupal_multilingual', + ]; + + /** + * The cached taxonomy tree items, keyed by vid and tid. + * + * @var array + */ + protected $treeData = []; + + /** + * {@inheritdoc} + */ + protected function setUp() { + parent::setUp(); + $this->installEntitySchema('taxonomy_term'); + $this->installConfig(static::$modules); + $this->executeMigrations([ + 'language', + 'd6_node_type', + 'd6_field', + 'd6_taxonomy_vocabulary', + 'd6_field_instance', + 'd6_taxonomy_term', + 'd6_taxonomy_term_localized_translation', + ]); + } + + /** + * Validates a migrated term contains the expected values. + * + * @param int $id + * Entity ID to load and check. + * @param string $expected_language + * The language code for this term. + * @param string $expected_label + * The label the migrated entity should have. + * @param string $expected_vid + * The parent vocabulary the migrated entity should have. + * @param string $expected_description + * The description the migrated entity should have. + * @param string $expected_format + * The format the migrated entity should have. + * @param int $expected_weight + * The weight the migrated entity should have. + * @param array $expected_parents + * The parent terms the migrated entity should have. + * @param int $expected_field_integer_value + * The value the migrated entity field should have. + * @param int $expected_term_reference_tid + * The term reference ID the migrated entity field should have. + */ + protected function assertEntity($id, $expected_language, $expected_label, $expected_vid, $expected_description = '', $expected_format = NULL, $expected_weight = 0, array $expected_parents = [], $expected_field_integer_value = NULL, $expected_term_reference_tid = NULL) { + /** @var \Drupal\taxonomy\TermInterface $entity */ + $entity = Term::load($id); + $this->assertInstanceOf(TermInterface::class, $entity); + $this->assertSame($expected_language, $entity->language()->getId()); + $this->assertSame($expected_label, $entity->label()); + $this->assertSame($expected_vid, $entity->bundle()); + $this->assertSame($expected_description, $entity->getDescription()); + $this->assertSame($expected_format, $entity->getFormat()); + $this->assertSame($expected_weight, $entity->getWeight()); + $this->assertHierarchy($expected_vid, $id, $expected_parents); + } + + /** + * Asserts that a term is present in the tree storage, with the right parents. + * + * @param string $vid + * Vocabulary ID. + * @param int $tid + * ID of the term to check. + * @param array $parent_ids + * The expected parent term IDs. + */ + protected function assertHierarchy($vid, $tid, array $parent_ids) { + if (!isset($this->treeData[$vid])) { + $tree = \Drupal::entityTypeManager()->getStorage('taxonomy_term')->loadTree($vid); + $this->treeData[$vid] = []; + foreach ($tree as $item) { + $this->treeData[$vid][$item->tid] = $item; + } + } + + $this->assertArrayHasKey($tid, $this->treeData[$vid], "Term $tid exists in taxonomy tree"); + $term = $this->treeData[$vid][$tid]; + $this->assertEquals($parent_ids, array_filter($term->parents), "Term $tid has correct parents in taxonomy tree"); + } + + /** + * Tests the Drupal 6 i18n localized taxonomy term to Drupal 8 migration. + */ + public function testTranslatedLocalizedTaxonomyTerms() { + $this->assertEntity(14, 'en', 'Talos IV', 'vocabulary_name_much_longer_than', 'The home of Captain Christopher Pike.', NULL, '0', []); + $this->assertEntity(15, 'en', 'Vulcan', 'vocabulary_name_much_longer_than', NULL, NULL, '0', []); + + /** @var \Drupal\taxonomy\TermInterface $entity */ + $entity = Term::load(14); + $this->assertTrue($entity->hasTranslation('fr')); + $translation = $entity->getTranslation('fr'); + $this->assertSame('fr - Talos IV', $translation->label()); + $this->assertSame('fr - The home of Captain Christopher Pike.', $translation->getDescription()); + + $this->assertTrue($entity->hasTranslation('zu')); + $translation = $entity->getTranslation('zu'); + $this->assertSame('Talos IV', $translation->label()); + $this->assertSame('zu - The home of Captain Christopher Pike.', $translation->getDescription()); + + $entity = Term::load(15); + $this->assertFalse($entity->hasTranslation('fr')); + $this->assertTrue($entity->hasTranslation('zu')); + $translation = $entity->getTranslation('zu'); + $this->assertSame('zu - Vulcan', $translation->label()); + $this->assertSame('', $translation->getDescription()); + } + +} diff --git a/web/core/modules/taxonomy/tests/src/Kernel/Migrate/d6/MigrateVocabularyFieldInstanceTest.php b/web/core/modules/taxonomy/tests/src/Kernel/Migrate/d6/MigrateVocabularyFieldInstanceTest.php index 77cb3e9069d8f5a3a12770994a5891cec730aced..46d60a6398e1fc61f1afbac3514975e9b413cae5 100644 --- a/web/core/modules/taxonomy/tests/src/Kernel/Migrate/d6/MigrateVocabularyFieldInstanceTest.php +++ b/web/core/modules/taxonomy/tests/src/Kernel/Migrate/d6/MigrateVocabularyFieldInstanceTest.php @@ -39,19 +39,21 @@ protected function setUp() { public function testVocabularyFieldInstance() { $this->executeMigration('d6_vocabulary_field_instance'); - // Test that the field exists. + // Test that the field exists. Tags has a multilingual option of 'None'. $field_id = 'node.article.field_tags'; $field = FieldConfig::load($field_id); $this->assertSame($field_id, $field->id(), 'Field instance exists on article bundle.'); $this->assertSame('Tags', $field->label()); $this->assertTrue($field->isRequired(), 'Field is required'); + $this->assertFalse($field->isTranslatable()); - // Test the page bundle as well. + // Test the page bundle as well. Tags has a multilingual option of 'None'. $field_id = 'node.page.field_tags'; $field = FieldConfig::load($field_id); $this->assertSame($field_id, $field->id(), 'Field instance exists on page bundle.'); $this->assertSame('Tags', $field->label()); $this->assertTrue($field->isRequired(), 'Field is required'); + $this->assertFalse($field->isTranslatable()); $settings = $field->getSettings(); $this->assertSame('default:taxonomy_term', $settings['handler'], 'The handler plugin ID is correct.'); @@ -60,15 +62,32 @@ public function testVocabularyFieldInstance() { $this->assertSame(['node', 'article', 'field_tags'], $this->getMigration('d6_vocabulary_field_instance')->getIdMap()->lookupDestinationId([4, 'article'])); - // Test the the field vocabulary_1_i_0_. + // Test the the field vocabulary_1_i_0_ with multilingual option, + // 'per language terms'. $field_id = 'node.story.field_vocabulary_1_i_0_'; $field = FieldConfig::load($field_id); $this->assertFalse($field->isRequired(), 'Field is not required'); + $this->assertTrue($field->isTranslatable()); + + // Test the the field vocabulary_2_i_0_ with multilingual option, + // 'Set language to vocabulary'. + $field_id = 'node.story.field_vocabulary_2_i_1_'; + $field = FieldConfig::load($field_id); + $this->assertFalse($field->isRequired(), 'Field is not required'); + $this->assertFalse($field->isTranslatable()); + + // Test the the field vocabulary_3_i_0_ with multilingual option, + // 'Localize terms'. + $field_id = 'node.story.field_vocabulary_3_i_2_'; + $field = FieldConfig::load($field_id); + $this->assertFalse($field->isRequired(), 'Field is not required'); + $this->assertTrue($field->isTranslatable()); // Tests that a vocabulary named like a D8 base field will be migrated and // prefixed with 'field_' to avoid conflicts. $field_type = FieldConfig::load('node.sponsor.field_type'); $this->assertInstanceOf(FieldConfig::class, $field_type); + $this->assertTrue($field->isTranslatable()); } /** diff --git a/web/core/modules/taxonomy/tests/src/Kernel/Migrate/d7/MigrateTaxonomyTermTest.php b/web/core/modules/taxonomy/tests/src/Kernel/Migrate/d7/MigrateTaxonomyTermTest.php index e4246594a91d48ff37ec49b3331027702aad3dcd..8a7d912571179e797691a16e3676c73134304a29 100644 --- a/web/core/modules/taxonomy/tests/src/Kernel/Migrate/d7/MigrateTaxonomyTermTest.php +++ b/web/core/modules/taxonomy/tests/src/Kernel/Migrate/d7/MigrateTaxonomyTermTest.php @@ -15,11 +15,15 @@ class MigrateTaxonomyTermTest extends MigrateDrupal7TestBase { public static $modules = [ 'comment', + 'content_translation', 'datetime', 'forum', 'image', + 'language', 'link', 'menu_ui', + // Required for translation migrations. + 'migrate_drupal_multilingual', 'node', 'taxonomy', 'telephone', @@ -38,16 +42,23 @@ class MigrateTaxonomyTermTest extends MigrateDrupal7TestBase { */ protected function setUp() { parent::setUp(); + $this->installEntitySchema('comment'); + $this->installEntitySchema('node'); $this->installEntitySchema('taxonomy_term'); $this->installConfig(static::$modules); $this->executeMigrations([ + 'language', + 'd7_user_role', + 'd7_user', 'd7_node_type', 'd7_comment_type', 'd7_field', 'd7_taxonomy_vocabulary', 'd7_field_instance', 'd7_taxonomy_term', + 'd7_entity_translation_settings', + 'd7_taxonomy_term_entity_translation', ]); } @@ -110,7 +121,7 @@ public function testTaxonomyTerms() { $this->assertEntity(2, 'Term1 (This is a real field!)', 'test_vocabulary', 'The first term. (This is a real field!)', 'filtered_html', 0, [], NULL, 3); $this->assertEntity(3, 'Term2', 'test_vocabulary', 'The second term.', 'filtered_html'); - $this->assertEntity(4, 'Term3', 'test_vocabulary', 'The third term.', 'full_html', 0, [3], 6); + $this->assertEntity(4, 'Term3 in plain old English', 'test_vocabulary', 'The third term in plain old English.', 'full_html', 0, [3], 6); $this->assertEntity(5, 'Custom Forum', 'forums', 'Where the cool kids are.', NULL, 3); $this->assertEntity(6, 'Games', 'forums', '', NULL, 4, [], NULL, NULL, 1); $this->assertEntity(7, 'Minecraft', 'forums', '', NULL, 1, [6]); @@ -142,7 +153,7 @@ protected function getParentIDs($tid) { * Assert that a term is present in the tree storage, with the right parents. * * @param string $vid - * Vocabular ID. + * Vocabulary ID. * @param int $tid * ID of the term to check. * @param array $parent_ids @@ -162,4 +173,56 @@ protected function assertHierarchy($vid, $tid, array $parent_ids) { $this->assertEquals($parent_ids, array_filter($term->parents), "Term $tid has correct parents in taxonomy tree"); } + /** + * Tests the migration of taxonomy term entity translations. + */ + public function testTaxonomyTermEntityTranslations() { + $manager = $this->container->get('content_translation.manager'); + + // Get the term and its translations. + $term = Term::load(4); + $term_fr = $term->getTranslation('fr'); + $term_is = $term->getTranslation('is'); + + // Test that fields translated with Entity Translation are migrated. + $this->assertSame('Term3 in plain old English', $term->getName()); + $this->assertSame('Term3 en français s\'il vous plaît', $term_fr->getName()); + $this->assertSame('Term3 á íslensku', $term_is->getName()); + $this->assertSame('The third term in plain old English.', $term->getDescription()); + $this->assertSame('The third term en français s\'il vous plaît.', $term_fr->getDescription()); + $this->assertSame('The third term á íslensku.', $term_is->getDescription()); + $this->assertSame('full_html', $term->getFormat()); + $this->assertSame('filtered_html', $term_fr->getFormat()); + $this->assertSame('plain_text', $term_is->getFormat()); + $this->assertSame('6', $term->field_integer->value); + $this->assertSame('5', $term_fr->field_integer->value); + $this->assertSame('4', $term_is->field_integer->value); + + // Test that the French translation metadata is correctly migrated. + $metadata_fr = $manager->getTranslationMetadata($term_fr); + $this->assertTrue($metadata_fr->isPublished()); + $this->assertSame('en', $metadata_fr->getSource()); + $this->assertSame('2', $metadata_fr->getAuthor()->uid->value); + $this->assertSame('1531922267', $metadata_fr->getCreatedTime()); + $this->assertSame('1531922268', $metadata_fr->getChangedTime()); + $this->assertTrue($metadata_fr->isOutdated()); + + // Test that the Icelandic translation metadata is correctly migrated. + $metadata_is = $manager->getTranslationMetadata($term_is); + $this->assertFalse($metadata_is->isPublished()); + $this->assertSame('en', $metadata_is->getSource()); + $this->assertSame('1', $metadata_is->getAuthor()->uid->value); + $this->assertSame('1531922278', $metadata_is->getCreatedTime()); + $this->assertSame('1531922279', $metadata_is->getChangedTime()); + $this->assertFalse($metadata_is->isOutdated()); + + // Test that untranslatable properties are the same as the source language. + $this->assertSame($term->bundle(), $term_fr->bundle()); + $this->assertSame($term->bundle(), $term_is->bundle()); + $this->assertSame($term->getWeight(), $term_fr->getWeight()); + $this->assertSame($term->getWeight(), $term_is->getWeight()); + $this->assertSame($term->parent->terget_id, $term_fr->parent->terget_id); + $this->assertSame($term->parent->terget_id, $term_is->parent->terget_id); + } + } diff --git a/web/core/modules/taxonomy/tests/src/Kernel/Plugin/migrate/source/d6/TermLocalizedTranslationTest.php b/web/core/modules/taxonomy/tests/src/Kernel/Plugin/migrate/source/d6/TermLocalizedTranslationTest.php new file mode 100644 index 0000000000000000000000000000000000000000..c2fea26d1040f3315f2de4f2f391208c41622993 --- /dev/null +++ b/web/core/modules/taxonomy/tests/src/Kernel/Plugin/migrate/source/d6/TermLocalizedTranslationTest.php @@ -0,0 +1,179 @@ +<?php + +namespace Drupal\Tests\taxonomy\Kernel\Plugin\migrate\source\d6; + +use Drupal\Tests\migrate\Kernel\MigrateSqlSourceTestBase; + +/** + * Tests D6 i18n term localized source plugin. + * + * @covers \Drupal\taxonomy\Plugin\migrate\source\d6\TermLocalizedTranslation + * @group taxonomy + */ +class TermLocalizedTranslationTest extends MigrateSqlSourceTestBase { + + /** + * {@inheritdoc} + */ + public static $modules = ['taxonomy', 'migrate_drupal']; + + /** + * {@inheritdoc} + */ + public function providerSource() { + $tests = []; + + // The source data. + $tests[0]['source_data']['term_data'] = [ + [ + 'tid' => 1, + 'vid' => 5, + 'name' => 'name value 1', + 'description' => 'description value 1', + 'weight' => 0, + 'language' => NULL, + ], + [ + 'tid' => 2, + 'vid' => 6, + 'name' => 'name value 2', + 'description' => 'description value 2', + 'weight' => 0, + 'language' => NULL, + ], + [ + 'tid' => 3, + 'vid' => 6, + 'name' => 'name value 3', + 'description' => 'description value 3', + 'weight' => 0, + 'language' => NULL, + ], + [ + 'tid' => 4, + 'vid' => 5, + 'name' => 'name value 4', + 'description' => 'description value 4', + 'weight' => 1, + 'language' => NULL, + ], + ]; + $tests[0]['source_data']['term_hierarchy'] = [ + [ + 'tid' => 1, + 'parent' => 0, + ], + [ + 'tid' => 2, + 'parent' => 0, + ], + [ + 'tid' => 3, + 'parent' => 0, + ], + [ + 'tid' => 4, + 'parent' => 1, + ], + ]; + $tests[0]['source_data']['i18n_strings'] = [ + [ + 'lid' => 6, + 'objectid' => 1, + 'type' => 'term', + 'property' => 'name', + 'objectindex' => '1', + 'format' => 0, + ], + [ + 'lid' => 7, + 'objectid' => 1, + 'type' => 'term', + 'property' => 'description', + 'objectindex' => '1', + 'format' => 0, + ], + [ + 'lid' => 8, + 'objectid' => 3, + 'type' => 'term', + 'property' => 'name', + 'objectindex' => '3', + 'format' => 0, + ], + ]; + $tests[0]['source_data']['locales_target'] = [ + [ + 'lid' => 6, + 'language' => 'fr', + 'translation' => 'fr - name value 1 translation', + 'plid' => 0, + 'plural' => 0, + 'i18n_status' => 0, + ], + [ + 'lid' => 7, + 'language' => 'fr', + 'translation' => 'fr - description value 1 translation', + 'plid' => 0, + 'plural' => 0, + 'i18n_status' => 0, + ], + [ + 'lid' => 8, + 'language' => 'zu', + 'translation' => 'zu - description value 2 translation', + 'plid' => 0, + 'plural' => 0, + 'i18n_status' => 0, + ], + ]; + + // The expected results. + $tests[0]['expected_data'] = [ + [ + 'tid' => 1, + 'vid' => 5, + 'name' => 'name value 1', + 'description' => 'description value 1', + 'weight' => 0, + 'parent' => [0], + 'property' => 'name', + 'language' => 'fr', + 'name_translated' => 'fr - name value 1 translation', + 'description_translated' => 'fr - description value 1 translation', + ], + [ + 'tid' => 1, + 'vid' => 5, + 'name' => 'name value 1', + 'description' => 'description value 1', + 'weight' => 0, + 'parent' => [0], + 'property' => 'description', + 'language' => 'fr', + 'name_translated' => 'fr - name value 1 translation', + 'description_translated' => 'fr - description value 1 translation', + ], + [ + 'tid' => 3, + 'vid' => 6, + 'name' => 'name value 3', + 'description' => 'description value 3', + 'weight' => 0, + 'parent' => [0], + 'property' => 'name', + 'language' => 'zu', + 'name_translated' => 'zu - description value 2 translation', + 'description_translated' => NULL, + ], + ]; + + $tests[0]['expected_count'] = NULL; + // Empty configuration will return terms for all vocabularies. + $tests[0]['configuration'] = []; + + return $tests; + } + +} diff --git a/web/core/modules/taxonomy/tests/src/Kernel/Plugin/migrate/source/d7/TermEntityTranslationTest.php b/web/core/modules/taxonomy/tests/src/Kernel/Plugin/migrate/source/d7/TermEntityTranslationTest.php new file mode 100644 index 0000000000000000000000000000000000000000..3a9145171371f1dc3269f3d5e3a1041714838ce1 --- /dev/null +++ b/web/core/modules/taxonomy/tests/src/Kernel/Plugin/migrate/source/d7/TermEntityTranslationTest.php @@ -0,0 +1,334 @@ +<?php + +namespace Drupal\Tests\taxonomy\Kernel\Plugin\migrate\source\d7; + +use Drupal\Tests\migrate\Kernel\MigrateSqlSourceTestBase; + +/** + * Tests taxonomy term entity translation source plugin. + * + * @covers \Drupal\taxonomy\Plugin\migrate\source\d7\TermEntityTranslation + * @group taxonomy + */ +class TermEntityTranslationTest extends MigrateSqlSourceTestBase { + + /** + * {@inheritdoc} + */ + public static $modules = ['taxonomy', 'migrate_drupal']; + + /** + * {@inheritdoc} + */ + public function providerSource() { + $tests = []; + + // The source data. + $tests[0]['source_data']['entity_translation'] = [ + [ + 'entity_type' => 'taxonomy_term', + 'entity_id' => 1, + 'revision_id' => 1, + 'language' => 'en', + 'source' => '', + 'uid' => 1, + 'status' => 1, + 'translate' => 0, + 'created' => 1531343498, + 'changed' => 1531343498, + ], + [ + 'entity_type' => 'taxonomy_term', + 'entity_id' => 1, + 'revision_id' => 1, + 'language' => 'fr', + 'source' => 'en', + 'uid' => 2, + 'status' => 1, + 'translate' => 1, + 'created' => 1531343508, + 'changed' => 1531343508, + ], + [ + 'entity_type' => 'taxonomy_term', + 'entity_id' => 1, + 'revision_id' => 1, + 'language' => 'es', + 'source' => 'en', + 'uid' => 1, + 'status' => 0, + 'translate' => 0, + 'created' => 1531343528, + 'changed' => 1531343528, + ], + ]; + $tests[0]['source_data']['field_config'] = [ + [ + 'id' => 1, + 'field_name' => 'field_test', + 'type' => 'text', + 'module' => 'text', + 'active' => 1, + 'storage_type' => 'field_sql_storage', + 'storage_module' => 'field_sql_storage', + 'storage_active' => 1, + 'locked' => 1, + 'data' => 'a:0:{}', + 'cardinality' => 1, + 'translatable' => 1, + 'deleted' => 0, + ], + [ + 'id' => 2, + 'field_name' => 'name_field', + 'type' => 'text', + 'module' => 'text', + 'active' => 1, + 'storage_type' => 'field_sql_storage', + 'storage_module' => 'field_sql_storage', + 'storage_active' => 1, + 'locked' => 1, + 'data' => 'a:0:{}', + 'cardinality' => 1, + 'translatable' => 1, + 'deleted' => 0, + ], + [ + 'id' => 3, + 'field_name' => 'description_field', + 'type' => 'text', + 'module' => 'text', + 'active' => 1, + 'storage_type' => 'field_sql_storage', + 'storage_module' => 'field_sql_storage', + 'storage_active' => 1, + 'locked' => 1, + 'data' => 'a:0:{}', + 'cardinality' => 1, + 'translatable' => 1, + 'deleted' => 0, + ], + ]; + $tests[0]['source_data']['field_config_instance'] = [ + [ + 'id' => '1', + 'field_id' => 1, + 'field_name' => 'field_test', + 'entity_type' => 'taxonomy_term', + 'bundle' => 'tags', + 'data' => 'a:0:{}', + 'deleted' => 0, + ], + [ + 'id' => 2, + 'field_id' => 2, + 'field_name' => 'name_field', + 'entity_type' => 'taxonomy_term', + 'bundle' => 'tags', + 'data' => 'a:0:{}', + 'deleted' => 0, + ], + [ + 'id' => 3, + 'field_id' => 3, + 'field_name' => 'description_field', + 'entity_type' => 'taxonomy_term', + 'bundle' => 'tags', + 'data' => 'a:0:{}', + 'deleted' => 0, + ], + ]; + $tests[0]['source_data']['field_data_field_test'] = [ + [ + 'entity_type' => 'taxonomy_term', + 'bundle' => 'tags', + 'deleted' => 0, + 'entity_id' => 1, + 'revision_id' => 1, + 'language' => 'en', + 'delta' => 0, + 'field_test_value' => 'English field', + 'field_test_format' => 'filtered_html', + ], + [ + 'entity_type' => 'taxonomy_term', + 'bundle' => 'tags', + 'deleted' => 0, + 'entity_id' => 1, + 'revision_id' => 1, + 'language' => 'fr', + 'delta' => 0, + 'field_test_value' => 'French field', + 'field_test_format' => 'filtered_html', + ], + [ + 'entity_type' => 'taxonomy_term', + 'bundle' => 'tags', + 'deleted' => 0, + 'entity_id' => 1, + 'revision_id' => 1, + 'language' => 'es', + 'delta' => 0, + 'field_test_value' => 'Spanish field', + 'field_test_format' => 'filtered_html', + ], + ]; + $tests[0]['source_data']['field_data_name_field'] = [ + [ + 'entity_type' => 'taxonomy_term', + 'bundle' => 'tags', + 'deleted' => '0', + 'entity_id' => '1', + 'revision_id' => '1', + 'language' => 'en', + 'delta' => '0', + 'name_field_value' => 'Term Name EN', + 'name_field_format' => NULL, + ], + [ + 'entity_type' => 'taxonomy_term', + 'bundle' => 'tags', + 'deleted' => '0', + 'entity_id' => '1', + 'revision_id' => '1', + 'language' => 'fr', + 'delta' => '0', + 'name_field_value' => 'Term Name FR', + 'name_field_format' => NULL, + ], + [ + 'entity_type' => 'taxonomy_term', + 'bundle' => 'tags', + 'deleted' => '0', + 'entity_id' => '1', + 'revision_id' => '1', + 'language' => 'es', + 'delta' => '0', + 'name_field_value' => 'Term Name ES', + 'name_field_format' => NULL, + ], + ]; + $tests[0]['source_data']['field_data_description_field'] = [ + [ + 'entity_type' => 'taxonomy_term', + 'bundle' => 'tags', + 'deleted' => '0', + 'entity_id' => '1', + 'revision_id' => '1', + 'language' => 'en', + 'delta' => '0', + 'description_field_value' => 'Term Description EN', + 'description_field_format' => 'full_html', + ], + [ + 'entity_type' => 'taxonomy_term', + 'bundle' => 'tags', + 'deleted' => '0', + 'entity_id' => '1', + 'revision_id' => '1', + 'language' => 'fr', + 'delta' => '0', + 'description_field_value' => 'Term Description FR', + 'description_field_format' => 'full_html', + ], + [ + 'entity_type' => 'taxonomy_term', + 'bundle' => 'tags', + 'deleted' => '0', + 'entity_id' => '1', + 'revision_id' => '1', + 'language' => 'es', + 'delta' => '0', + 'description_field_value' => 'Term Description ES', + 'description_field_format' => 'full_html', + ], + ]; + $tests[0]['source_data']['system'] = [ + [ + 'name' => 'title', + 'type' => 'module', + 'status' => 1, + ], + ]; + $tests[0]['source_data']['taxonomy_term_data'] = [ + [ + 'tid' => 1, + 'vid' => 1, + 'name' => 'Term Name', + 'description' => 'Term Description', + 'format' => 'filtered_html', + 'weight' => 0, + ], + ]; + $tests[0]['source_data']['taxonomy_term_hierarchy'] = [ + [ + 'tid' => 1, + 'parent' => 0, + ], + ]; + $tests[0]['source_data']['taxonomy_vocabulary'] = [ + [ + 'vid' => 1, + 'name' => 'Tags', + 'machine_name' => 'tags', + 'description' => '', + 'hierarchy' => 0, + 'module' => 'taxonomy', + 'weight' => 0, + ], + ]; + + // The expected results. + $tests[0]['expected_data'] = [ + [ + 'entity_type' => 'taxonomy_term', + 'entity_id' => 1, + 'revision_id' => 1, + 'language' => 'fr', + 'source' => 'en', + 'uid' => 2, + 'status' => 1, + 'translate' => 1, + 'created' => 1531343508, + 'changed' => 1531343508, + 'name' => 'Term Name FR', + 'description' => 'Term Description FR', + 'format' => 'full_html', + 'machine_name' => 'tags', + 'is_container' => FALSE, + 'field_test' => [ + [ + 'value' => 'French field', + 'format' => 'filtered_html', + ], + ], + ], + [ + 'entity_type' => 'taxonomy_term', + 'entity_id' => 1, + 'revision_id' => 1, + 'language' => 'es', + 'source' => 'en', + 'uid' => 1, + 'status' => 0, + 'translate' => 0, + 'created' => 1531343528, + 'changed' => 1531343528, + 'name' => 'Term Name ES', + 'description' => 'Term Description ES', + 'format' => 'full_html', + 'machine_name' => 'tags', + 'is_container' => FALSE, + 'field_test' => [ + [ + 'value' => 'Spanish field', + 'format' => 'filtered_html', + ], + ], + ], + ]; + + return $tests; + } + +} diff --git a/web/core/modules/taxonomy/tests/src/Kernel/Plugin/migrate/source/d7/TermTest.php b/web/core/modules/taxonomy/tests/src/Kernel/Plugin/migrate/source/d7/TermTest.php index ef002cfec89b3270d9e7a4522d17e0f8e4e0985a..0466d750e9d0d79bd0ea0fbec9b40a63f30d02c0 100644 --- a/web/core/modules/taxonomy/tests/src/Kernel/Plugin/migrate/source/d7/TermTest.php +++ b/web/core/modules/taxonomy/tests/src/Kernel/Plugin/migrate/source/d7/TermTest.php @@ -254,6 +254,10 @@ public function providerSource() { 'name' => 'forum_containers', 'value' => 'a:3:{i:0;s:1:"5";i:1;s:1:"6";i:2;s:1:"7";}', ], + [ + 'name' => 'language_default', + 'value' => 'O:8:"stdClass":1:{s:8:"language";s:2:"en";}', + ], ]; // The expected results. @@ -265,6 +269,7 @@ public function providerSource() { 'description' => 'description value 1 (description_field)', 'weight' => 0, 'parent' => [0], + 'language' => 'en', ], [ 'tid' => 2, @@ -273,6 +278,7 @@ public function providerSource() { 'description' => 'description value 2', 'weight' => 0, 'parent' => [0], + 'language' => 'en', ], [ 'tid' => 3, @@ -281,6 +287,7 @@ public function providerSource() { 'description' => 'description value 3', 'weight' => 0, 'parent' => [0], + 'language' => 'en', ], [ 'tid' => 4, @@ -289,6 +296,7 @@ public function providerSource() { 'description' => 'description value 4 (description_field)', 'weight' => 1, 'parent' => [1], + 'language' => 'en', ], [ 'tid' => 5, @@ -297,6 +305,7 @@ public function providerSource() { 'description' => 'description value 5', 'weight' => 1, 'parent' => [2], + 'language' => 'en', ], [ 'tid' => 6, @@ -305,6 +314,7 @@ public function providerSource() { 'description' => 'description value 6', 'weight' => 0, 'parent' => [3, 2], + 'language' => 'en', ], [ 'tid' => 7, @@ -313,6 +323,7 @@ public function providerSource() { 'description' => 'description value 7', 'weight' => 0, 'parent' => [0], + 'language' => 'en', ], ]; @@ -330,6 +341,7 @@ public function providerSource() { 'description' => 'description value 1 (description_field)', 'weight' => 0, 'parent' => [0], + 'language' => 'en', ], [ 'tid' => 4, @@ -338,6 +350,7 @@ public function providerSource() { 'description' => 'description value 4 (description_field)', 'weight' => 1, 'parent' => [1], + 'language' => 'en', ], ]; $tests[1]['expected_count'] = NULL; diff --git a/web/core/modules/taxonomy/tests/src/Kernel/Views/TaxonomyTestBase.php b/web/core/modules/taxonomy/tests/src/Kernel/Views/TaxonomyTestBase.php index a9f4c474be1cd322c7d76357c33b76264b140cec..588a3587b448c3be0bfc6b9c5a1451d4129214d3 100644 --- a/web/core/modules/taxonomy/tests/src/Kernel/Views/TaxonomyTestBase.php +++ b/web/core/modules/taxonomy/tests/src/Kernel/Views/TaxonomyTestBase.php @@ -4,7 +4,7 @@ use Drupal\Core\Field\FieldStorageDefinitionInterface; use Drupal\Core\Language\LanguageInterface; -use Drupal\field\Tests\EntityReference\EntityReferenceTestTrait; +use Drupal\Tests\field\Traits\EntityReferenceTestTrait; use Drupal\Tests\node\Traits\ContentTypeCreationTrait; use Drupal\Tests\node\Traits\NodeCreationTrait; use Drupal\Tests\views\Kernel\ViewsKernelTestBase; diff --git a/web/core/modules/telephone/src/Plugin/Field/FieldFormatter/TelephoneLinkFormatter.php b/web/core/modules/telephone/src/Plugin/Field/FieldFormatter/TelephoneLinkFormatter.php index afdf54146d660629e51edff9b41f8fa5d9def47a..60ee25cbc3d91d4cdf028324d364772f7be24db1 100644 --- a/web/core/modules/telephone/src/Plugin/Field/FieldFormatter/TelephoneLinkFormatter.php +++ b/web/core/modules/telephone/src/Plugin/Field/FieldFormatter/TelephoneLinkFormatter.php @@ -67,6 +67,21 @@ public function viewElements(FieldItemListInterface $items, $langcode) { $title_setting = $this->getSetting('title'); foreach ($items as $delta => $item) { + // If the telephone number is 5 or less digits, parse_url() will think + // it's a port number rather than a phone number which causes the link + // formatter to throw an InvalidArgumentException. Avoid this by inserting + // a dash (-) after the first digit - RFC 3966 defines the dash as a + // visual separator character and so will be removed before the phone + // number is used. See https://bugs.php.net/bug.php?id=70588 for more. + // While the bug states this only applies to numbers <= 65535, a 5 digit + // number greater than 65535 will cause parse_url() to return FALSE so + // we need the work around on any 5 digit (or less) number. + // First we strip whitespace so we're counting actual digits. + $phone_number = preg_replace('/\s+/', '', $item->value); + if (strlen($phone_number) <= 5) { + $phone_number = substr_replace($phone_number, '-', 1, 0); + } + // Render each element as link. $element[$delta] = [ '#type' => 'link', @@ -74,7 +89,7 @@ public function viewElements(FieldItemListInterface $items, $langcode) { // itself as title. '#title' => $title_setting ?: $item->value, // Prepend 'tel:' to the telephone number. - '#url' => Url::fromUri('tel:' . rawurlencode(preg_replace('/\s+/', '', $item->value))), + '#url' => Url::fromUri('tel:' . rawurlencode($phone_number)), '#options' => ['external' => TRUE], ]; diff --git a/web/core/modules/telephone/tests/src/Functional/TelephoneFieldTest.php b/web/core/modules/telephone/tests/src/Functional/TelephoneFieldTest.php index 75e626f66dd5c3b6f592b4705fc70cc7bea9f7c1..8d351819397b255ecd8a57546622e3876f266b36 100644 --- a/web/core/modules/telephone/tests/src/Functional/TelephoneFieldTest.php +++ b/web/core/modules/telephone/tests/src/Functional/TelephoneFieldTest.php @@ -31,20 +31,15 @@ class TelephoneFieldTest extends BrowserTestBase { */ protected $webUser; + /** + * {@inheritdoc} + */ protected function setUp() { parent::setUp(); $this->drupalCreateContentType(['type' => 'article']); $this->webUser = $this->drupalCreateUser(['create article content', 'edit own article content']); $this->drupalLogin($this->webUser); - } - - // Test fields. - - /** - * Helper function for testTelephoneField(). - */ - public function testTelephoneField() { // Add the telephone field to the article content type. FieldStorageConfig::create([ @@ -74,29 +69,54 @@ public function testTelephoneField() { 'weight' => 1, ]) ->save(); + } - // Display creation form. + /** + * Test to confirm the widget is setup. + * + * @covers \Drupal\telephone\Plugin\Field\FieldWidget\TelephoneDefaultWidget::formElement + */ + public function testTelephoneWidget() { $this->drupalGet('node/add/article'); $this->assertFieldByName("field_telephone[0][value]", '', 'Widget found.'); $this->assertRaw('placeholder="123-456-7890"'); + } + /** + * Test the telephone formatter. + * + * @covers \Drupal\telephone\Plugin\Field\FieldFormatter\TelephoneLinkFormatter::viewElements + * + * @dataProvider providerPhoneNumbers + */ + public function testTelephoneFormatter($input, $expected) { // Test basic entry of telephone field. $edit = [ 'title[0][value]' => $this->randomMachineName(), - 'field_telephone[0][value]' => "123456789", + 'field_telephone[0][value]' => $input, ]; - $this->drupalPostForm(NULL, $edit, t('Save')); - $this->assertRaw('<a href="tel:123456789">', 'A telephone link is provided on the article node page.'); + $this->drupalPostForm('node/add/article', $edit, t('Save')); + $this->assertRaw('<a href="tel:' . $expected . '">'); + } - // Add number with a space in it. Need to ensure it is stripped on output. - $edit = [ - 'title[0][value]' => $this->randomMachineName(), - 'field_telephone[0][value]' => "1234 56789", + /** + * Provides the phone numbers to check and expected results. + */ + public function providerPhoneNumbers() { + return [ + 'standard phone number' => ['123456789', '123456789'], + 'whitespace is removed' => ['1234 56789', '123456789'], + 'parse_url(0) return FALSE workaround' => ['0', '0-'], + 'php bug 70588 workaround - lower edge check' => ['1', '1-'], + 'php bug 70588 workaround' => ['123', '1-23'], + 'php bug 70588 workaround - with whitespace removal' => ['1 2 3 4 5', '1-2345'], + 'php bug 70588 workaround - upper edge check' => ['65534', '6-5534'], + 'php bug 70588 workaround - edge check' => ['65535', '6-5535'], + 'php bug 70588 workaround - invalid port number - lower edge check' => ['65536', '6-5536'], + 'php bug 70588 workaround - invalid port number - upper edge check' => ['99999', '9-9999'], + 'lowest number not affected by php bug 70588' => ['100000', '100000'], ]; - - $this->drupalPostForm('node/add/article', $edit, t('Save')); - $this->assertRaw('<a href="tel:123456789">', 'Telephone link is output with whitespace removed.'); } } diff --git a/web/core/modules/update/update.authorize.inc b/web/core/modules/update/update.authorize.inc index 664f25f9c501bb4867e84156fc36c946ecb78a50..fea365a2cb19bee41633a71b27e49607ba6069f3 100644 --- a/web/core/modules/update/update.authorize.inc +++ b/web/core/modules/update/update.authorize.inc @@ -253,7 +253,7 @@ function update_authorize_update_batch_finished($success, $results) { '#type' => 'link', '#url' => $url, '#title' => t('Run database updates'), - // 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 diff --git a/web/core/modules/user/src/AccountForm.php b/web/core/modules/user/src/AccountForm.php index 3624a9c934c8fa53e5493879088cd5f86b503072..080f0bf3f9c1992af2df2a7c2b501a0fc30b725d 100644 --- a/web/core/modules/user/src/AccountForm.php +++ b/web/core/modules/user/src/AccountForm.php @@ -161,7 +161,7 @@ public function form(array $form, FormStateInterface $form_state) { // When not building the user registration form, prevent web browsers from // autofilling/prefilling the email, username, and password fields. - if ($this->getOperation() != 'register') { + if (!$register) { foreach (['mail', 'name', 'pass'] as $key) { if (isset($form['account'][$key])) { $form['account'][$key]['#attributes']['autocomplete'] = 'off'; diff --git a/web/core/modules/user/src/Plugin/Action/CancelUser.php b/web/core/modules/user/src/Plugin/Action/CancelUser.php index e9726b436d7a686229c3420c724b02ef2d3d9b30..0fa74c021bcf1e3a70b5cc0828b914336f3a09ce 100644 --- a/web/core/modules/user/src/Plugin/Action/CancelUser.php +++ b/web/core/modules/user/src/Plugin/Action/CancelUser.php @@ -35,7 +35,7 @@ class CancelUser extends ActionBase implements ContainerFactoryPluginInterface { protected $currentUser; /** - * Constructs a DeleteNode object. + * Constructs a CancelUser object. * * @param array $configuration * A configuration array containing information about the plugin instance. diff --git a/web/core/modules/user/src/Plugin/Block/UserLoginBlock.php b/web/core/modules/user/src/Plugin/Block/UserLoginBlock.php index 8649494b929caf6d9780cd5469adee53e55996c8..8da11e7b8fcc60be12c588a4ca6b51ce65c1200c 100644 --- a/web/core/modules/user/src/Plugin/Block/UserLoginBlock.php +++ b/web/core/modules/user/src/Plugin/Block/UserLoginBlock.php @@ -96,7 +96,7 @@ public function build() { // 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\user\Plugin\Block\UserLoginBlock::build'); // This is based on the implementation in diff --git a/web/core/modules/user/src/Plugin/EntityReferenceSelection/UserSelection.php b/web/core/modules/user/src/Plugin/EntityReferenceSelection/UserSelection.php index d06a81c41e2db684283618df2316b6128d23bdbe..b2887afb05f9936f24aa43e051b61b99686b344c 100644 --- a/web/core/modules/user/src/Plugin/EntityReferenceSelection/UserSelection.php +++ b/web/core/modules/user/src/Plugin/EntityReferenceSelection/UserSelection.php @@ -242,7 +242,7 @@ public function entityQueryAlter(SelectInterface $query) { $value_part->condition('anonymous_name', $condition['value'], $condition['operator']); $value_part->compile($this->connection, $query); $or->condition((new Condition('AND')) - ->where(str_replace('anonymous_name', ':anonymous_name', (string) $value_part), $value_part->arguments() + [':anonymous_name' => \Drupal::config('user.settings')->get('anonymous')]) + ->where(str_replace($query->escapeField('anonymous_name'), ':anonymous_name', (string) $value_part), $value_part->arguments() + [':anonymous_name' => \Drupal::config('user.settings')->get('anonymous')]) ->condition('base_table.uid', 0) ); $query->condition($or); diff --git a/web/core/modules/user/src/Plugin/LanguageNegotiation/LanguageNegotiationUser.php b/web/core/modules/user/src/Plugin/LanguageNegotiation/LanguageNegotiationUser.php index da8aaf000e89dee7cca8a2e68e99b3d1a4ea1a05..0e8108a9c8d3ee54efc02a9939aa3bed4a3afc50 100644 --- a/web/core/modules/user/src/Plugin/LanguageNegotiation/LanguageNegotiationUser.php +++ b/web/core/modules/user/src/Plugin/LanguageNegotiation/LanguageNegotiationUser.php @@ -30,10 +30,9 @@ public function getLangcode(Request $request = NULL) { // User preference (only for authenticated users). if ($this->languageManager && $this->currentUser->isAuthenticated()) { - $preferred_langcode = $this->currentUser->getPreferredLangcode(); - $default_langcode = $this->languageManager->getDefaultLanguage()->getId(); + $preferred_langcode = $this->currentUser->getPreferredLangcode(FALSE); $languages = $this->languageManager->getLanguages(); - if (!empty($preferred_langcode) && $preferred_langcode != $default_langcode && isset($languages[$preferred_langcode])) { + if (!empty($preferred_langcode) && isset($languages[$preferred_langcode])) { $langcode = $preferred_langcode; } } diff --git a/web/core/modules/user/src/Plugin/LanguageNegotiation/LanguageNegotiationUserAdmin.php b/web/core/modules/user/src/Plugin/LanguageNegotiation/LanguageNegotiationUserAdmin.php index c00509f598777a19f9653fba7934823ef17d2881..56186053d7f8fe68bb1918af1973f6a2ac495ef7 100644 --- a/web/core/modules/user/src/Plugin/LanguageNegotiation/LanguageNegotiationUserAdmin.php +++ b/web/core/modules/user/src/Plugin/LanguageNegotiation/LanguageNegotiationUserAdmin.php @@ -127,10 +127,14 @@ protected function isAdminPath(Request $request) { $route_match = $this->stackedRouteMatch->getRouteMatchFromRequest($request); if ($route_match && !$route_object = $route_match->getRouteObject()) { try { + // Some inbound path processors make changes to the request. Make a + // copy as we're not actually routing the request so we do not want to + // make changes. + $cloned_request = clone $request; // Process the path as an inbound path. This will remove any language // prefixes and other path components that inbound processing would // clear out, so we can attempt to load the route clearly. - $path = $this->pathProcessorManager->processInbound(urldecode(rtrim($request->getPathInfo(), '/')), $request); + $path = $this->pathProcessorManager->processInbound(urldecode(rtrim($cloned_request->getPathInfo(), '/')), $cloned_request); $attributes = $this->router->match($path); } catch (ResourceNotFoundException $e) { diff --git a/web/core/modules/user/src/Plugin/migrate/process/UserLangcode.php b/web/core/modules/user/src/Plugin/migrate/process/UserLangcode.php index 5373dad671c39b982a8e4757a3153c170588aac5..174c8a557c18dfc5cf89d6ff72f2246b572e33ce 100644 --- a/web/core/modules/user/src/Plugin/migrate/process/UserLangcode.php +++ b/web/core/modules/user/src/Plugin/migrate/process/UserLangcode.php @@ -33,7 +33,7 @@ class UserLangcode extends ProcessPluginBase implements ContainerFactoryPluginIn * @param string $plugin_id * The plugin ID. * @param mixed $plugin_definition - * The plugin definiiton. + * The plugin definition. * @param \Drupal\Core\Language\LanguageManager $language_manager * The language manager service. */ diff --git a/web/core/modules/user/src/Tests/RestRegisterUserTest.php b/web/core/modules/user/src/Tests/RestRegisterUserTest.php deleted file mode 100644 index 31bcce4d295c96a5b3d606c3e7fa47a31d2b5f81..0000000000000000000000000000000000000000 --- a/web/core/modules/user/src/Tests/RestRegisterUserTest.php +++ /dev/null @@ -1,173 +0,0 @@ -<?php - -namespace Drupal\user\Tests; - -use Drupal\Core\Url; -use Drupal\rest\Tests\RESTTestBase; -use Drupal\user\Entity\Role; -use Drupal\user\RoleInterface; - -/** - * Tests user registration via REST resource. - * - * @group user - */ -class RestRegisterUserTest extends RESTTestBase { - - /** - * {@inheritdoc} - */ - public static $modules = ['hal']; - - /** - * {@inheritdoc} - */ - public function setUp() { - parent::setUp(); - - $this->enableService('user_registration', 'POST', 'hal_json'); - - Role::load(RoleInterface::ANONYMOUS_ID) - ->grantPermission('restful post user_registration') - ->save(); - - Role::load(RoleInterface::AUTHENTICATED_ID) - ->grantPermission('restful post user_registration') - ->save(); - } - - /** - * Tests that only anonymous users can register users. - */ - public function testRegisterUser() { - // Verify that an authenticated user cannot register a new user, despite - // being granted permission to do so because only anonymous users can - // register themselves, authenticated users with the necessary permissions - // can POST a new user to the "user" REST resource. - $user = $this->createUser(); - $this->drupalLogin($user); - $this->registerRequest('palmer.eldritch'); - $this->assertResponse('403', 'Only anonymous users can register users.'); - $this->drupalLogout(); - - $user_settings = $this->config('user.settings'); - - // Test out different setting User Registration and Email Verification. - // Allow visitors to register with no email verification. - $user_settings->set('register', USER_REGISTER_VISITORS); - $user_settings->set('verify_mail', 0); - $user_settings->save(); - $user = $this->registerUser('Palmer.Eldritch'); - $this->assertFalse($user->isBlocked()); - $this->assertFalse(empty($user->getPassword())); - $email_count = count($this->drupalGetMails()); - $this->assertEqual(0, $email_count); - - // Attempt to register without sending a password. - $this->registerRequest('Rick.Deckard', FALSE); - $this->assertResponse('422', 'No password provided'); - - // Allow visitors to register with email verification. - $user_settings->set('register', USER_REGISTER_VISITORS); - $user_settings->set('verify_mail', 1); - $user_settings->save(); - $user = $this->registerUser('Jason.Taverner', FALSE); - $this->assertTrue(empty($user->getPassword())); - $this->assertTrue($user->isBlocked()); - $this->assertMailString('body', 'You may now log in by clicking this link', 1); - - // Attempt to register with a password when e-mail verification is on. - $this->registerRequest('Estraven', TRUE); - $this->assertResponse('422', 'A Password cannot be specified. It will be generated on login.'); - - // Allow visitors to register with Admin approval and e-mail verification. - $user_settings->set('register', USER_REGISTER_VISITORS_ADMINISTRATIVE_APPROVAL); - $user_settings->set('verify_mail', 1); - $user_settings->save(); - $user = $this->registerUser('Bob.Arctor', FALSE); - $this->assertTrue(empty($user->getPassword())); - $this->assertTrue($user->isBlocked()); - $this->assertMailString('body', 'Your application for an account is', 2); - $this->assertMailString('body', 'Bob.Arctor has applied for an account', 2); - - // Attempt to register with a password when e-mail verification is on. - $this->registerRequest('Ursula', TRUE); - $this->assertResponse('422', 'A Password cannot be specified. It will be generated on login.'); - - // Allow visitors to register with Admin approval and no email verification. - $user_settings->set('register', USER_REGISTER_VISITORS_ADMINISTRATIVE_APPROVAL); - $user_settings->set('verify_mail', 0); - $user_settings->save(); - $user = $this->registerUser('Argaven'); - $this->assertFalse(empty($user->getPassword())); - $this->assertTrue($user->isBlocked()); - $this->assertMailString('body', 'Your application for an account is', 2); - $this->assertMailString('body', 'Argaven has applied for an account', 2); - - // Attempt to register without sending a password. - $this->registerRequest('Tibe', FALSE); - $this->assertResponse('422', 'No password provided'); - } - - /** - * Creates serialize user values. - * - * @param string $name - * The name of the user. Use only valid values for emails. - * - * @param bool $include_password - * Whether to include a password in the user values. - * - * @return string - * Serialized user values. - */ - protected function createSerializedUser($name, $include_password = TRUE) { - global $base_url; - // New user info to be serialized. - $data = [ - "_links" => ["type" => ["href" => $base_url . "/rest/type/user/user"]], - "langcode" => [["value" => "en"]], - "name" => [["value" => $name]], - "mail" => [["value" => "$name@example.com"]], - ]; - if ($include_password) { - $data['pass']['value'] = 'SuperSecretPassword'; - } - - // Create a HAL+JSON version for the user entity we want to create. - $serialized = $this->container->get('serializer') - ->serialize($data, 'hal_json'); - return $serialized; - } - - /** - * Registers a user via REST resource. - * - * @param $name - * User name. - * - * @param bool $include_password - * - * @return bool|\Drupal\user\Entity\User - */ - protected function registerUser($name, $include_password = TRUE) { - // Verify that an anonymous user can register. - $this->registerRequest($name, $include_password); - $this->assertResponse('200', 'HTTP response code is correct.'); - $user = user_load_by_name($name); - $this->assertFalse(empty($user), 'User was create as expected'); - return $user; - } - - /** - * Make a REST user registration request. - * - * @param $name - * @param $include_password - */ - protected function registerRequest($name, $include_password = TRUE) { - $serialized = $this->createSerializedUser($name, $include_password); - $this->httpRequest(Url::fromRoute('rest.user_registration.POST', ['_format' => 'hal_json']), 'POST', $serialized, 'application/hal+json'); - } - -} diff --git a/web/core/modules/user/src/Tests/UserResetEmailTestTrait.php b/web/core/modules/user/src/Tests/UserResetEmailTestTrait.php index 2fbbbbf78d001732e537a4d8e88567082dd7da11..1272ebb5d5f98dc958b10600c5c5a1e6a529ad0a 100644 --- a/web/core/modules/user/src/Tests/UserResetEmailTestTrait.php +++ b/web/core/modules/user/src/Tests/UserResetEmailTestTrait.php @@ -2,10 +2,17 @@ namespace Drupal\user\Tests; +@trigger_error(__NAMESPACE__ . '\UserResetEmailTestTrait is deprecated and scheduled for removal before Drupal 9.0.0. Add the method to the test class instead, see https://www.drupal.org/node/2999766', E_USER_DEPRECATED); + use Drupal\Core\Test\AssertMailTrait; /** * Helper function for logging in from reset password email. + * + * @deprecated Scheduled for removal before Drupal 9.0.0. + * Add the method to the test class instead. + * + * @see https://www.drupal.org/node/2999766 */ trait UserResetEmailTestTrait { diff --git a/web/core/modules/user/tests/modules/user_hooks_test/user_hooks_test.module b/web/core/modules/user/tests/modules/user_hooks_test/user_hooks_test.module index cafaf908a38428a1ba7ed619102f9e3c2ecaaaec..5f3d19d0333feee547229befc1cf0cc86dcefdb2 100644 --- a/web/core/modules/user/tests/modules/user_hooks_test/user_hooks_test.module +++ b/web/core/modules/user/tests/modules/user_hooks_test/user_hooks_test.module @@ -6,11 +6,12 @@ */ use Drupal\Component\Render\FormattableMarkup; +use Drupal\Core\Session\AccountInterface; /** * Implements hook_user_format_name_alter(). */ -function user_hooks_test_user_format_name_alter(&$name, $account) { +function user_hooks_test_user_format_name_alter(&$name, AccountInterface $account) { if (\Drupal::state()->get('user_hooks_test_user_format_name_alter', FALSE)) { if (\Drupal::state()->get('user_hooks_test_user_format_name_alter_safe', FALSE)) { $name = new FormattableMarkup('<em>@uid</em>', ['@uid' => $account->id()]); diff --git a/web/core/modules/user/tests/src/Functional/RestRegisterUserTest.php b/web/core/modules/user/tests/src/Functional/RestRegisterUserTest.php new file mode 100644 index 0000000000000000000000000000000000000000..32e875cc315b247ddf9c0adac2f42a98892123a5 --- /dev/null +++ b/web/core/modules/user/tests/src/Functional/RestRegisterUserTest.php @@ -0,0 +1,270 @@ +<?php + +namespace Drupal\Tests\user\Functional; + +use Drupal\Core\Url; +use Drupal\Tests\rest\Functional\CookieResourceTestTrait; +use Drupal\Tests\rest\Functional\ResourceTestBase; +use GuzzleHttp\RequestOptions; +use Drupal\Core\Test\AssertMailTrait; + +/** + * Tests user registration via REST resource. + * + * @group user + */ +class RestRegisterUserTest extends ResourceTestBase { + + use CookieResourceTestTrait; + + use AssertMailTrait { + getMails as drupalGetMails; + } + + /** + * {@inheritdoc} + */ + protected static $format = 'hal_json'; + + /** + * {@inheritdoc} + */ + protected static $mimeType = 'application/hal+json'; + + /** + * {@inheritdoc} + */ + protected static $auth = 'cookie'; + + /** + * {@inheritdoc} + */ + protected static $resourceConfigId = 'user_registration'; + + /** + * {@inheritdoc} + */ + public static $modules = ['hal', 'user']; + + const USER_EMAIL_DOMAIN = '@example.com'; + + const TEST_EMAIL_DOMAIN = 'simpletest@example.com'; + + /** + * {@inheritdoc} + */ + public function setUp() { + parent::setUp(); + + $auth = isset(static::$auth) ? [static::$auth] : []; + $this->provisionResource([static::$format], $auth); + + $this->setUpAuthorization('POST'); + } + + /** + * Tests that only anonymous users can register users. + */ + public function testRegisterUser() { + $config = $this->config('user.settings'); + + // Test out different setting User Registration and Email Verification. + // Allow visitors to register with no email verification. + $config->set('register', USER_REGISTER_VISITORS); + $config->set('verify_mail', 0); + $config->save(); + $user = $this->registerUser('Palmer.Eldritch'); + $this->assertFalse($user->isBlocked()); + $this->assertFalse(empty($user->getPassword())); + $email_count = count($this->drupalGetMails()); + + $this->assertEquals($email_count, 0); + + // Attempt to register without sending a password. + $response = $this->registerRequest('Rick.Deckard', FALSE); + $this->assertResourceErrorResponse(422, "No password provided.", $response); + + // Attempt to register with a password when e-mail verification is on. + $config->set('register', USER_REGISTER_VISITORS); + $config->set('verify_mail', 1); + $config->save(); + $response = $this->registerRequest('Estraven', TRUE); + $this->assertResourceErrorResponse(422, 'A Password cannot be specified. It will be generated on login.', $response); + + // Allow visitors to register with email verification. + $config->set('register', USER_REGISTER_VISITORS); + $config->set('verify_mail', 1); + $config->save(); + $name = 'Jason.Taverner'; + $user = $this->registerUser($name, FALSE); + $this->assertTrue(empty($user->getPassword())); + $this->assertTrue($user->isBlocked()); + $this->resetAll(); + + $this->assertMailString('body', 'You may now log in by clicking this link', 1); + + // Allow visitors to register with Admin approval and no email verification. + $config->set('register', USER_REGISTER_VISITORS_ADMINISTRATIVE_APPROVAL); + $config->set('verify_mail', 0); + $config->save(); + $name = 'Argaven'; + $user = $this->registerUser($name); + $this->resetAll(); + $this->assertFalse(empty($user->getPassword())); + $this->assertTrue($user->isBlocked()); + $this->assertMailString('body', 'Your application for an account is', 2); + $this->assertMailString('body', 'Argaven has applied for an account', 2); + + // Allow visitors to register with Admin approval and e-mail verification. + $config->set('register', USER_REGISTER_VISITORS_ADMINISTRATIVE_APPROVAL); + $config->set('verify_mail', 1); + $config->save(); + $name = 'Bob.Arctor'; + $user = $this->registerUser($name, FALSE); + $this->resetAll(); + $this->assertTrue(empty($user->getPassword())); + $this->assertTrue($user->isBlocked()); + + $this->assertMailString('body', 'Your application for an account is', 2); + $this->assertMailString('body', 'Bob.Arctor has applied for an account', 2); + + // Verify that an authenticated user cannot register a new user, despite + // being granted permission to do so because only anonymous users can + // register themselves, authenticated users with the necessary permissions + // can POST a new user to the "user" REST resource. + $this->initAuthentication(); + $response = $this->registerRequest($this->account->getAccountName()); + $this->assertResourceErrorResponse(403, "Only anonymous users can register a user.", $response); + } + + /** + * Create the request body. + * + * @param string $name + * Name. + * @param bool $include_password + * Include Password. + * @param bool $include_email + * Include Email. + * + * @return array + * Return the request body. + */ + protected function createRequestBody($name, $include_password = TRUE, $include_email = TRUE) { + global $base_url; + $request_body = [ + '_links' => ['type' => ["href" => $base_url . "/rest/type/user/user"]], + 'langcode' => [['value' => 'en']], + 'name' => [['value' => $name]], + ]; + + if ($include_email) { + $request_body['mail'] = [['value' => $name . self::USER_EMAIL_DOMAIN]]; + } + + if ($include_password) { + $request_body['pass']['value'] = 'SuperSecretPassword'; + } + + return $request_body; + } + + /** + * Helper function to generate the request body. + * + * @param array $request_body + * The request body array. + * + * @return array + * Return the request options. + */ + protected function createRequestOptions(array $request_body) { + $request_options = $this->getAuthenticationRequestOptions('POST'); + $request_options[RequestOptions::BODY] = $this->serializer->encode($request_body, static::$format); + $request_options[RequestOptions::HEADERS]['Content-Type'] = static::$mimeType; + + return $request_options; + } + + /** + * Registers a user via REST resource. + * + * @param string $name + * User name. + * @param bool $include_password + * Include the password. + * @param bool $include_email + * Include the email? + * + * @return bool|\Drupal\user\Entity\User + * Return bool or the user. + */ + protected function registerUser($name, $include_password = TRUE, $include_email = TRUE) { + // Verify that an anonymous user can register. + $response = $this->registerRequest($name, $include_password, $include_email); + $this->assertResourceResponse(200, FALSE, $response); + $user = user_load_by_name($name); + $this->assertFalse(empty($user), 'User was create as expected'); + return $user; + } + + /** + * Make a REST user registration request. + * + * @param string $name + * The name. + * @param bool $include_password + * Include the password? + * @param bool $include_email + * Include the email? + * + * @return \Psr\Http\Message\ResponseInterface + * Return the Response. + */ + protected function registerRequest($name, $include_password = TRUE, $include_email = TRUE) { + + $user_register_url = Url::fromRoute('user.register') + ->setRouteParameter('_format', static::$format); + $request_body = $this->createRequestBody($name, $include_password, $include_email); + $request_options = $this->createRequestOptions($request_body); + $response = $this->request('POST', $user_register_url, $request_options); + + return $response; + } + + /** + * {@inheritdoc} + */ + protected function setUpAuthorization($method) { + switch ($method) { + case 'POST': + $this->grantPermissionsToAuthenticatedRole(['restful post user_registration']); + $this->grantPermissionsToAnonymousRole(['restful post user_registration']); + break; + + default: + throw new \UnexpectedValueException(); + } + } + + /** + * {@inheritdoc} + */ + protected function assertNormalizationEdgeCases($method, Url $url, array $request_options) {} + + /** + * {@inheritdoc} + */ + protected function getExpectedUnauthorizedAccessMessage($method) {} + + /** + * {@inheritdoc} + */ + protected function getExpectedBcUnauthorizedAccessMessage($method) {} + + /** + * {@inheritdoc} + */ + protected function getExpectedUnauthorizedAccessCacheability() {} + +} diff --git a/web/core/modules/user/src/Tests/UserAdminLanguageTest.php b/web/core/modules/user/tests/src/Functional/UserAdminLanguageTest.php similarity index 98% rename from web/core/modules/user/src/Tests/UserAdminLanguageTest.php rename to web/core/modules/user/tests/src/Functional/UserAdminLanguageTest.php index cd6cc657bf0d2a071ac80f54376448487fbfc1f7..5e9f3ee465062d89cce3bc6ab8d7a3fc811f1e02 100644 --- a/web/core/modules/user/src/Tests/UserAdminLanguageTest.php +++ b/web/core/modules/user/tests/src/Functional/UserAdminLanguageTest.php @@ -1,16 +1,16 @@ <?php -namespace Drupal\user\Tests; +namespace Drupal\Tests\user\Functional; use Drupal\Core\Language\LanguageInterface; -use Drupal\simpletest\WebTestBase; +use Drupal\Tests\BrowserTestBase; /** * Tests users' ability to change their own administration language. * * @group user */ -class UserAdminLanguageTest extends WebTestBase { +class UserAdminLanguageTest extends BrowserTestBase { /** * A user with permission to access admin pages and administer languages. diff --git a/web/core/modules/user/src/Tests/UserBlocksTest.php b/web/core/modules/user/tests/src/Functional/UserBlocksTest.php similarity index 96% rename from web/core/modules/user/src/Tests/UserBlocksTest.php rename to web/core/modules/user/tests/src/Functional/UserBlocksTest.php index b7e6cad7e32b80bf5ae2a52242751b39020c7aa8..509aab69fb4c137b35c5f50d715e47a97407cae2 100644 --- a/web/core/modules/user/src/Tests/UserBlocksTest.php +++ b/web/core/modules/user/tests/src/Functional/UserBlocksTest.php @@ -1,16 +1,16 @@ <?php -namespace Drupal\user\Tests; +namespace Drupal\Tests\user\Functional; use Drupal\dynamic_page_cache\EventSubscriber\DynamicPageCacheSubscriber; -use Drupal\simpletest\WebTestBase; +use Drupal\Tests\BrowserTestBase; /** * Tests user blocks. * * @group user */ -class UserBlocksTest extends WebTestBase { +class UserBlocksTest extends BrowserTestBase { /** * Modules to enable. @@ -69,7 +69,7 @@ public function testUserLoginBlock() { // Log in using the block. $edit = []; $edit['name'] = $user->getUsername(); - $edit['pass'] = $user->pass_raw; + $edit['pass'] = $user->passRaw; $this->drupalPostForm('admin/people/permissions', $edit, t('Log in')); $this->assertNoText(t('User login'), 'Logged in.'); diff --git a/web/core/modules/user/src/Tests/UserCreateTest.php b/web/core/modules/user/tests/src/Functional/UserCreateTest.php similarity index 94% rename from web/core/modules/user/src/Tests/UserCreateTest.php rename to web/core/modules/user/tests/src/Functional/UserCreateTest.php index 7b534435a0c2c068f44fb7308700f372f5f97ac4..8c281111459dbd236dd1ec3c4b3328be3b671f30 100644 --- a/web/core/modules/user/src/Tests/UserCreateTest.php +++ b/web/core/modules/user/tests/src/Functional/UserCreateTest.php @@ -1,17 +1,22 @@ <?php -namespace Drupal\user\Tests; +namespace Drupal\Tests\user\Functional; +use Drupal\Core\Test\AssertMailTrait; use Drupal\field\Entity\FieldConfig; -use Drupal\simpletest\WebTestBase; use Drupal\field\Entity\FieldStorageConfig; +use Drupal\Tests\BrowserTestBase; /** * Tests the create user administration page. * * @group user */ -class UserCreateTest extends WebTestBase { +class UserCreateTest extends BrowserTestBase { + + use AssertMailTrait { + getMails as drupalGetMails; + } /** * Modules to enable. @@ -109,7 +114,7 @@ public function testUserAdd() { $this->drupalGet('admin/people'); $this->assertText($edit['name'], 'User found in list of users'); $user = user_load_by_name($name); - $this->assertEqual($user->isActive(), 'User is not blocked'); + $this->assertTrue($user->isActive(), 'User is not blocked'); } // Test that the password '0' is considered a password. diff --git a/web/core/modules/user/tests/src/Functional/UserLoginHttpTest.php b/web/core/modules/user/tests/src/Functional/UserLoginHttpTest.php index b12a72b58e8c4d4aee5f095b11576608fffed932..079affaf54aed8f16c3a335ac58f92547276d959 100644 --- a/web/core/modules/user/tests/src/Functional/UserLoginHttpTest.php +++ b/web/core/modules/user/tests/src/Functional/UserLoginHttpTest.php @@ -3,10 +3,10 @@ namespace Drupal\Tests\user\Functional; use Drupal\Core\Flood\DatabaseBackend; +use Drupal\Core\Test\AssertMailTrait; use Drupal\Core\Url; use Drupal\Tests\BrowserTestBase; use Drupal\user\Controller\UserAuthenticationController; -use Drupal\user\Tests\UserResetEmailTestTrait; use GuzzleHttp\Cookie\CookieJar; use Psr\Http\Message\ResponseInterface; use Symfony\Component\Serializer\Encoder\JsonEncoder; @@ -21,7 +21,9 @@ */ class UserLoginHttpTest extends BrowserTestBase { - use UserResetEmailTestTrait; + use AssertMailTrait { + getMails as drupalGetMails; + } /** * Modules to install. @@ -526,4 +528,17 @@ protected function doTestPasswordReset($format, $account) { $this->drupalLogout(); } + /** + * Login from reset password email. + */ + protected function loginFromResetEmail() { + $_emails = $this->drupalGetMails(); + $email = end($_emails); + $urls = []; + preg_match('#.+user/reset/.+#', $email['body'], $urls); + $resetURL = $urls[0]; + $this->drupalGet($resetURL); + $this->drupalPostForm(NULL, NULL, 'Log in'); + } + } diff --git a/web/core/modules/user/src/Tests/Functional/UserPasswordResetTest.php b/web/core/modules/user/tests/src/Functional/UserPasswordResetTest.php similarity index 99% rename from web/core/modules/user/src/Tests/Functional/UserPasswordResetTest.php rename to web/core/modules/user/tests/src/Functional/UserPasswordResetTest.php index 11d0691350acd4c7d66910acd4bc3f155c209373..81db6eeb3e288ebc49389859360576210c41ebcb 100644 --- a/web/core/modules/user/src/Tests/Functional/UserPasswordResetTest.php +++ b/web/core/modules/user/tests/src/Functional/UserPasswordResetTest.php @@ -1,6 +1,6 @@ <?php -namespace Drupal\user\Tests\Functional; +namespace Drupal\Tests\user\Functional; use Drupal\Component\Render\FormattableMarkup; use Drupal\Core\Test\AssertMailTrait; diff --git a/web/core/modules/user/src/Tests/UserRegistrationTest.php b/web/core/modules/user/tests/src/Functional/UserRegistrationTest.php similarity index 99% rename from web/core/modules/user/src/Tests/UserRegistrationTest.php rename to web/core/modules/user/tests/src/Functional/UserRegistrationTest.php index 95fd7a0999d5c2c4c2b368596c76c4c54c323640..78c1af42ce9acc1d20022128b521e7b1c0544e86 100644 --- a/web/core/modules/user/src/Tests/UserRegistrationTest.php +++ b/web/core/modules/user/tests/src/Functional/UserRegistrationTest.php @@ -1,20 +1,20 @@ <?php -namespace Drupal\user\Tests; +namespace Drupal\Tests\user\Functional; -use Drupal\Core\Entity\Entity\EntityFormDisplay; use Drupal\Component\Render\FormattableMarkup; +use Drupal\Core\Entity\Entity\EntityFormDisplay; use Drupal\Core\Field\FieldStorageDefinitionInterface; use Drupal\field\Entity\FieldConfig; use Drupal\field\Entity\FieldStorageConfig; -use Drupal\simpletest\WebTestBase; +use Drupal\Tests\BrowserTestBase; /** * Tests registration of user under different configurations. * * @group user */ -class UserRegistrationTest extends WebTestBase { +class UserRegistrationTest extends BrowserTestBase { /** * Modules to enable. diff --git a/web/core/modules/user/src/Tests/FunctionalJavascript/UserPasswordResetTest.php b/web/core/modules/user/tests/src/FunctionalJavascript/UserPasswordResetTest.php similarity index 98% rename from web/core/modules/user/src/Tests/FunctionalJavascript/UserPasswordResetTest.php rename to web/core/modules/user/tests/src/FunctionalJavascript/UserPasswordResetTest.php index caad739175ef4c22749724cb47787e47df24f455..26143d0153816d89d7d92c5b40026a30fb5326fe 100644 --- a/web/core/modules/user/src/Tests/FunctionalJavascript/UserPasswordResetTest.php +++ b/web/core/modules/user/tests/src/FunctionalJavascript/UserPasswordResetTest.php @@ -1,6 +1,6 @@ <?php -namespace Drupal\user\Tests\FunctionalJavascript; +namespace Drupal\Tests\user\FunctionalJavascript; use Drupal\Core\Test\AssertMailTrait; use Drupal\Core\Url; diff --git a/web/core/modules/user/src/Tests/UserAdminSettingsFormTest.php b/web/core/modules/user/tests/src/Kernel/UserAdminSettingsFormTest.php similarity index 97% rename from web/core/modules/user/src/Tests/UserAdminSettingsFormTest.php rename to web/core/modules/user/tests/src/Kernel/UserAdminSettingsFormTest.php index 784d5e1e62e1978e243d6cb4fb73cfa7889364ca..5f43c2841c8ba8ca4b9a9bdb1c7700aeebf949f6 100644 --- a/web/core/modules/user/src/Tests/UserAdminSettingsFormTest.php +++ b/web/core/modules/user/tests/src/Kernel/UserAdminSettingsFormTest.php @@ -1,6 +1,6 @@ <?php -namespace Drupal\user\Tests; +namespace Drupal\Tests\user\Kernel; use Drupal\KernelTests\ConfigFormTestBase; use Drupal\user\AccountSettingsForm; diff --git a/web/core/modules/user/tests/src/Kernel/UserEntityReferenceTest.php b/web/core/modules/user/tests/src/Kernel/UserEntityReferenceTest.php index 3ad8e7b327b23ec3a5e81753336bd0b15bfa6220..b847f17c5bc6dc9b641f596a0b38067c2689a88b 100644 --- a/web/core/modules/user/tests/src/Kernel/UserEntityReferenceTest.php +++ b/web/core/modules/user/tests/src/Kernel/UserEntityReferenceTest.php @@ -2,9 +2,9 @@ namespace Drupal\Tests\user\Kernel; -use Drupal\field\Tests\EntityReference\EntityReferenceTestTrait; use Drupal\field\Entity\FieldConfig; use Drupal\KernelTests\Core\Entity\EntityKernelTestBase; +use Drupal\Tests\field\Traits\EntityReferenceTestTrait; use Drupal\user\Entity\Role; /** diff --git a/web/core/modules/user/user.api.php b/web/core/modules/user/user.api.php index 823c08da6755b4326766958e71a328b74608cc42..01e460233f0c6199a85c6aee9ae56e3af31bc395 100644 --- a/web/core/modules/user/user.api.php +++ b/web/core/modules/user/user.api.php @@ -5,6 +5,9 @@ * Hooks provided by the User module. */ +use Drupal\Core\Session\AccountInterface; +use Drupal\user\UserInterface; + /** * @addtogroup hooks * @{ @@ -28,7 +31,7 @@ * * @param array $edit * The array of form values submitted by the user. - * @param \Drupal\Core\Session\AccountInterface $account + * @param \Drupal\user\UserInterface $account * The user object on which the operation is being performed. * @param string $method * The account cancellation method. @@ -36,7 +39,7 @@ * @see user_cancel_methods() * @see hook_user_cancel_methods_alter() */ -function hook_user_cancel($edit, $account, $method) { +function hook_user_cancel($edit, UserInterface $account, $method) { switch ($method) { case 'user_cancel_block_unpublish': // Unpublish nodes (current revisions). @@ -107,7 +110,8 @@ function hook_user_cancel_methods_alter(&$methods) { * * Called by $account->getDisplayName() to allow modules to alter the username * that is displayed. Can be used to ensure user privacy in situations where - * $account->getDisplayName() is too revealing. + * $account->getDisplayName() is too revealing. This hook is invoked both for + * user entities and the anonymous user session object. * * @param string|Drupal\Component\Render\MarkupInterface $name * The username that is displayed for a user. If a hook implementation changes @@ -115,12 +119,19 @@ function hook_user_cancel_methods_alter(&$methods) { * the implementation to ensure the user's name is escaped properly. String * values will be autoescaped. * @param \Drupal\Core\Session\AccountInterface $account - * The user object on which the operation is being performed. + * The object on which the operation is being performed. This object may be a + * user entity. If the object is an implementation of UserInterface you can + * use instanceof operator before accessing user entity methods. For example: + * @code + * if ($account instanceof UserInterface) { + * // Access user entity methods. + * } + * @endcode * * @see \Drupal\Core\Session\AccountInterface::getDisplayName() * @see sanitization */ -function hook_user_format_name_alter(&$name, $account) { +function hook_user_format_name_alter(&$name, AccountInterface $account) { // Display the user's uid instead of name. if ($account->id()) { $name = t('User @uid', ['@uid' => $account->id()]); @@ -130,10 +141,10 @@ function hook_user_format_name_alter(&$name, $account) { /** * The user just logged in. * - * @param object $account + * @param \Drupal\user\UserInterface $account * The user object on which the operation was just performed. */ -function hook_user_login($account) { +function hook_user_login(UserInterface $account) { $config = \Drupal::config('system.date'); // If the user has a NULL time zone, notify them to set a time zone. if (!$account->getTimezone() && $config->get('timezone.user.configurable') && $config->get('timezone.user.warn')) { @@ -151,10 +162,10 @@ function hook_user_login($account) { /** * The user just logged out. * - * @param $account + * @param \Drupal\Core\Session\AccountInterface $account * The user object on which the operation was just performed. */ -function hook_user_logout($account) { +function hook_user_logout(AccountInterface $account) { db_insert('logouts') ->fields([ 'uid' => $account->id(), diff --git a/web/core/modules/user/user.module b/web/core/modules/user/user.module index b18408ab5f129b089669aaa5db1e37ddad43adb9..053429f4b87f84abaa609ad8d6b6dd1906b64283 100644 --- a/web/core/modules/user/user.module +++ b/web/core/modules/user/user.module @@ -569,7 +569,7 @@ function user_login_finalize(UserInterface $account) { /** * Implements hook_user_login(). */ -function user_user_login($account) { +function user_user_login(UserInterface $account) { // Reset static cache of default variables in template_preprocess() to reflect // the new user. drupal_static_reset('template_preprocess'); @@ -578,7 +578,7 @@ function user_user_login($account) { /** * Implements hook_user_logout(). */ -function user_user_logout($account) { +function user_user_logout(AccountInterface $account) { // Reset static cache of default variables in template_preprocess() to reflect // the new user. drupal_static_reset('template_preprocess'); diff --git a/web/core/modules/user/user.views_execution.inc b/web/core/modules/user/user.views_execution.inc index 255fbf2683868e2502cdaa599df07b5641fa6892..e0c5c0c635d19f5fbf91a826cdda2116d8ba9fa9 100644 --- a/web/core/modules/user/user.views_execution.inc +++ b/web/core/modules/user/user.views_execution.inc @@ -10,7 +10,7 @@ /** * Implements hook_views_query_substitutions(). * - * Allow replacement of current userid so we can cache these queries. + * Allow replacement of current user ID so we can cache these queries. */ function user_views_query_substitutions(ViewExecutable $view) { return ['***CURRENT_USER***' => \Drupal::currentUser()->id()]; diff --git a/web/core/modules/views/src/Plugin/Block/ViewsBlockBase.php b/web/core/modules/views/src/Plugin/Block/ViewsBlockBase.php index 4e3020ca0ab09d9f8d9829e3c6690e3cf8d8ee18..9ed369c045dc8a680f730bb7758f49624f0d6e10 100644 --- a/web/core/modules/views/src/Plugin/Block/ViewsBlockBase.php +++ b/web/core/modules/views/src/Plugin/Block/ViewsBlockBase.php @@ -105,6 +105,13 @@ public function defaultConfiguration() { return ['views_label' => '']; } + /** + * {@inheritdoc} + */ + public function getPreviewFallbackString() { + return $this->t('Placeholder for the "@view" views block', ['@view' => $this->view->storage->label()]); + } + /** * {@inheritdoc} */ diff --git a/web/core/modules/views/src/Plugin/views/field/EntityField.php b/web/core/modules/views/src/Plugin/views/field/EntityField.php index faf8da14b11f65e859c64b3ceccb45908f56919e..f26c188d3ba69abeb9c57dcf5bb28e922de6baad 100644 --- a/web/core/modules/views/src/Plugin/views/field/EntityField.php +++ b/web/core/modules/views/src/Plugin/views/field/EntityField.php @@ -1052,6 +1052,12 @@ protected function getTableMapping() { */ public function getValue(ResultRow $values, $field = NULL) { $entity = $this->getEntity($values); + + // Ensure the object is not NULL before attempting to translate it. + if ($entity === NULL) { + return NULL; + } + // Retrieve the translated object. $translated_entity = $this->getEntityFieldRenderer()->getEntityTranslation($entity, $values); diff --git a/web/core/modules/views/src/Plugin/views/field/FieldPluginBase.php b/web/core/modules/views/src/Plugin/views/field/FieldPluginBase.php index cbae7e0b1d004bfcc0d06cd11122f379ccf0b98f..be10f7f46f5095014fb2bb6ef4dfa9354651a224 100644 --- a/web/core/modules/views/src/Plugin/views/field/FieldPluginBase.php +++ b/web/core/modules/views/src/Plugin/views/field/FieldPluginBase.php @@ -106,7 +106,7 @@ abstract class FieldPluginBase extends HandlerBase implements FieldHandlerInterf /** * Keeps track of the last render index. * - * @var int|NULL + * @var int|null */ protected $lastRenderIndex; diff --git a/web/core/modules/views/src/Plugin/views/field/MultiItemsFieldHandlerInterface.php b/web/core/modules/views/src/Plugin/views/field/MultiItemsFieldHandlerInterface.php index 4949548867999c520dbfed363476abf1eead42b8..27f8b18e2bd2d8d66b17cf5cdf3720ed95b91ee4 100644 --- a/web/core/modules/views/src/Plugin/views/field/MultiItemsFieldHandlerInterface.php +++ b/web/core/modules/views/src/Plugin/views/field/MultiItemsFieldHandlerInterface.php @@ -5,7 +5,7 @@ use Drupal\views\ResultRow; /** - * Defines a field hander which renders multiple items per row. + * Defines a field handler which renders multiple items per row. */ interface MultiItemsFieldHandlerInterface extends FieldHandlerInterface { diff --git a/web/core/modules/views/src/Plugin/views/filter/Date.php b/web/core/modules/views/src/Plugin/views/filter/Date.php index 92e77dff7cd6ccbe0a34b1124f706c5d9a5d2baf..b7d1821bfd48f353a4eddbd6b57c6a76d69fe363 100644 --- a/web/core/modules/views/src/Plugin/views/filter/Date.php +++ b/web/core/modules/views/src/Plugin/views/filter/Date.php @@ -148,11 +148,15 @@ public function acceptExposedInput($input) { } if ($operators[$operator]['values'] == 1) { + // When the operator is either <, <=, =, !=, >=, > or regular_expression + // the input contains only one value. if ($this->value['value'] == '') { return FALSE; } } - else { + elseif ($operators[$operator]['values'] == 2) { + // When the operator is either between or not between the input contains + // two values. if ($this->value['min'] == '' || $this->value['max'] == '') { return FALSE; } diff --git a/web/core/modules/views/src/Plugin/views/query/PostgresqlDateSql.php b/web/core/modules/views/src/Plugin/views/query/PostgresqlDateSql.php index c03c416456a88a4d0eb8875c9d815ff105efef66..c919fadb671f6e6885703ab9aeb9d71e7c7a4558 100644 --- a/web/core/modules/views/src/Plugin/views/query/PostgresqlDateSql.php +++ b/web/core/modules/views/src/Plugin/views/query/PostgresqlDateSql.php @@ -3,6 +3,7 @@ namespace Drupal\views\Plugin\views\query; use Drupal\Core\Database\Connection; +use Drupal\Core\DependencyInjection\DependencySerializationTrait; /** * PostgreSQL-specific date handling. @@ -14,6 +15,8 @@ */ class PostgresqlDateSql implements DateSqlInterface { + use DependencySerializationTrait; + /** * The database connection. * diff --git a/web/core/modules/views/src/Plugin/views/query/SqliteDateSql.php b/web/core/modules/views/src/Plugin/views/query/SqliteDateSql.php index 628e1c68faec5c2a3613bc710ce814cb37b009fb..2275d4c6c3aca5deb2e3d4e5aa1f0d1d04f372e6 100644 --- a/web/core/modules/views/src/Plugin/views/query/SqliteDateSql.php +++ b/web/core/modules/views/src/Plugin/views/query/SqliteDateSql.php @@ -3,6 +3,7 @@ namespace Drupal\views\Plugin\views\query; use Drupal\Core\Database\Connection; +use Drupal\Core\DependencyInjection\DependencySerializationTrait; /** * SQLite-specific date handling. @@ -14,6 +15,8 @@ */ class SqliteDateSql implements DateSqlInterface { + use DependencySerializationTrait; + /** * The database connection. * diff --git a/web/core/modules/views/src/Plugin/views/wizard/WizardPluginBase.php b/web/core/modules/views/src/Plugin/views/wizard/WizardPluginBase.php index 890432aa84c32b9ce9822897c7e47b61b934b6fb..badfdbe3d27b02d0a86e9832e62f023cda36528e 100644 --- a/web/core/modules/views/src/Plugin/views/wizard/WizardPluginBase.php +++ b/web/core/modules/views/src/Plugin/views/wizard/WizardPluginBase.php @@ -103,7 +103,7 @@ abstract class WizardPluginBase extends PluginBase implements WizardInterface { * By default, filters are not exposed and added to the first non-reserved * filter group. * - * @var array() + * @var array */ protected $filter_defaults = [ 'id' => NULL, diff --git a/web/core/modules/views/src/Tests/ViewKernelTestBase.php b/web/core/modules/views/src/Tests/ViewKernelTestBase.php index 5a232859183607f4e492bac1d5398c83b4d1f78c..ed666ece77e21dda7ffa3731e7a88468f63cffc6 100644 --- a/web/core/modules/views/src/Tests/ViewKernelTestBase.php +++ b/web/core/modules/views/src/Tests/ViewKernelTestBase.php @@ -32,7 +32,7 @@ abstract class ViewKernelTestBase extends KernelTestBase { * {@inheritdoc} * * @param bool $import_test_views - * Should the views specififed on the test class be imported. If you need + * Should the views specified on the test class be imported. If you need * to setup some additional stuff, like fields, you need to call false and * then call createTestViews for your own. */ diff --git a/web/core/modules/views/src/ViewExecutable.php b/web/core/modules/views/src/ViewExecutable.php index 82504661f0ae55b971eb7de1967d56f4cfb332c5..1adaf55dad39f49e3664e90d1902e4a785412c73 100644 --- a/web/core/modules/views/src/ViewExecutable.php +++ b/web/core/modules/views/src/ViewExecutable.php @@ -114,7 +114,7 @@ class ViewExecutable { /** * Attachments to place before the view. * - * @var array() + * @var array */ public $attachment_before = []; @@ -1522,7 +1522,7 @@ public function render($display_id = NULL) { // Let modules modify the view just prior to rendering it. $module_handler->invokeAll('views_pre_render', [$this]); - // Let the themes play too, because pre render is a very themey thing. + // Let the themes play too, because prerender is a very themey thing. foreach ($themes as $theme_name) { $function = $theme_name . '_views_pre_render'; if (function_exists($function)) { diff --git a/web/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_click_sort_ajax.yml b/web/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_click_sort_ajax.yml new file mode 100644 index 0000000000000000000000000000000000000000..514655f9f3b8559fc5ff5c863c6fc287d79265e8 --- /dev/null +++ b/web/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_click_sort_ajax.yml @@ -0,0 +1,65 @@ +langcode: en +status: true +dependencies: { } +id: test_click_sort_ajax +module: views +description: '' +tag: '' +base_table: views_test_data +base_field: nid +core: '8' +display: + default: + display_options: + use_ajax: true + fields: + id: + id: id + table: views_test_data + field: id + label: ID + plugin_id: numeric + name: + id: name + table: views_test_data + field: name + label: Name + plugin_id: string + created: + id: created + table: views_test_data + field: created + label: created + plugin_id: field + type: timestamp + settings: + date_format: medium + custom_date_format: '' + timezone: '' + access: + type: none + cache: + type: tag + style: + type: table + options: + info: + id: + sortable: true + default_sort_order: asc + name: + sortable: true + default_sort_order: desc + created: + sortable: false + display_plugin: default + display_title: Master + id: default + position: 0 + page_1: + display_options: + path: test_click_sort + display_plugin: page + display_title: Page + id: page_1 + position: 0 diff --git a/web/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_mini_pager_ajax.yml b/web/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_mini_pager_ajax.yml new file mode 100644 index 0000000000000000000000000000000000000000..c49ef340e1a08acf8c6a73c775e39d853f85bd81 --- /dev/null +++ b/web/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_mini_pager_ajax.yml @@ -0,0 +1,88 @@ +langcode: en +status: true +dependencies: + module: + - node + - user +id: test_mini_pager_ajax +label: test_mini_pager +module: views +description: '' +tag: '' +base_table: node_field_data +base_field: nid +core: 8.x +display: + default: + display_plugin: default + id: default + display_title: Master + position: null + display_options: + use_ajax: true + access: + type: perm + cache: + type: tag + query: + type: views_query + exposed_form: + type: basic + pager: + type: mini + options: + items_per_page: 3 + offset: 0 + id: 0 + total_pages: null + tags: + previous: '‹‹ test' + next: '›› test' + expose: + items_per_page: false + items_per_page_label: 'Items per page' + items_per_page_options: '5, 10, 25, 50' + items_per_page_options_all: false + items_per_page_options_all_label: '- All -' + offset: false + offset_label: Offset + style: + type: default + row: + type: 'entity:node' + options: + view_mode: teaser + fields: + title: + id: title + table: node_field_data + field: title + label: '' + alter: + alter_text: false + make_link: false + absolute: false + trim: false + word_boundary: false + ellipsis: false + strip_tags: false + html: false + hide_empty: false + empty_zero: false + plugin_id: field + entity_type: node + entity_field: title + filters: { } + sorts: + nid: + id: nid + table: node_field_data + field: nid + plugin_id: standard + order: ASC + entity_type: node + entity_field: nid + title: test_mini_pager + filter_groups: + operator: AND + groups: { } diff --git a/web/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_pager_full_ajax.yml b/web/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_pager_full_ajax.yml new file mode 100644 index 0000000000000000000000000000000000000000..31b4a26ac3523f72fde4541a9fccd0b0613dfc77 --- /dev/null +++ b/web/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_pager_full_ajax.yml @@ -0,0 +1,37 @@ +langcode: en +status: true +dependencies: + module: + - node +id: test_pager_full_ajax +label: '' +module: views +description: '' +tag: '' +base_table: node_field_data +base_field: nid +core: '8' +display: + default: + display_options: + use_ajax: true + access: + type: none + cache: + type: tag + exposed_form: + type: basic + pager: + options: + id: 0 + items_per_page: 5 + offset: 0 + type: full + style: + type: default + row: + type: 'entity:node' + display_plugin: default + display_title: Master + id: default + position: 0 diff --git a/web/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_user_path.yml b/web/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_user_path.yml new file mode 100644 index 0000000000000000000000000000000000000000..a5e629f06c0df7ce9f4c3b619115b8b11797aa80 --- /dev/null +++ b/web/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_user_path.yml @@ -0,0 +1,158 @@ +langcode: en +status: true +dependencies: + module: + - user +id: test_user_path +label: 'user break' +module: views +description: '' +tag: '' +base_table: users_field_data +base_field: uid +core: 8.x +display: + default: + display_plugin: default + id: default + display_title: Master + position: 0 + display_options: + access: + type: perm + options: + perm: 'access user profiles' + cache: + type: tag + options: { } + query: + type: views_query + options: + disable_sql_rewrite: false + distinct: false + replica: false + query_comment: '' + query_tags: { } + exposed_form: + type: basic + options: + submit_button: Toepassen + reset_button: false + reset_button_label: Reset + exposed_sorts_label: 'Sorteren op' + expose_sort_order: true + sort_asc_label: Oplopend + sort_desc_label: Aflopend + pager: + type: mini + options: + items_per_page: 10 + offset: 0 + id: 0 + total_pages: null + expose: + items_per_page: false + items_per_page_label: 'Items per pagina' + items_per_page_options: '5, 10, 25, 50' + items_per_page_options_all: false + items_per_page_options_all_label: '- Alle -' + offset: false + offset_label: Startpunt + tags: + previous: ‹‹ + next: ›› + style: + type: default + row: + type: fields + fields: + name: + id: name + table: users_field_data + field: name + entity_type: user + entity_field: name + label: '' + alter: + alter_text: false + make_link: false + absolute: false + trim: false + word_boundary: false + ellipsis: false + strip_tags: false + html: false + hide_empty: false + empty_zero: false + plugin_id: field + relationship: none + group_type: group + admin_label: '' + exclude: false + element_type: '' + element_class: '' + element_label_type: '' + element_label_class: '' + element_label_colon: true + element_wrapper_type: '' + element_wrapper_class: '' + element_default_classes: true + empty: '' + hide_alter_empty: true + click_sort_column: value + type: user_name + settings: { } + group_column: value + group_columns: { } + group_rows: true + delta_limit: 0 + delta_offset: 0 + delta_reversed: false + delta_first_last: false + multi_type: separator + separator: ', ' + field_api_classes: false + filters: + status: + value: '1' + table: users_field_data + field: status + plugin_id: boolean + entity_type: user + entity_field: status + id: status + expose: + operator: '' + group: 1 + sorts: { } + title: 'user break' + header: { } + footer: { } + empty: { } + relationships: { } + arguments: { } + display_extenders: { } + cache_metadata: + max-age: -1 + contexts: + - 'languages:language_content' + - 'languages:language_interface' + - url.query_args + - user.permissions + tags: { } + page_1: + display_plugin: page + id: page_1 + display_title: Page + position: 1 + display_options: + display_extenders: { } + path: user/% + cache_metadata: + max-age: -1 + contexts: + - 'languages:language_content' + - 'languages:language_interface' + - url.query_args + - user.permissions + tags: { } diff --git a/web/core/modules/views/tests/src/Functional/DefaultViewsTest.php b/web/core/modules/views/tests/src/Functional/DefaultViewsTest.php index b6120707d98c629fad5fe2e577be5fd037e441cd..a4ae23aa487c9d517b3986f23633ef3679d15fda 100644 --- a/web/core/modules/views/tests/src/Functional/DefaultViewsTest.php +++ b/web/core/modules/views/tests/src/Functional/DefaultViewsTest.php @@ -7,11 +7,11 @@ use Drupal\Core\Field\FieldStorageDefinitionInterface; use Drupal\Core\Language\LanguageInterface; use Drupal\Core\Url; -use Drupal\field\Tests\EntityReference\EntityReferenceTestTrait; use Drupal\views\Views; use Drupal\comment\Entity\Comment; use Drupal\taxonomy\Entity\Vocabulary; use Drupal\taxonomy\Entity\Term; +use Drupal\Tests\field\Traits\EntityReferenceTestTrait; /** * Tests the default views provided by views. diff --git a/web/core/modules/views/src/Tests/FieldApiDataTest.php b/web/core/modules/views/tests/src/Functional/FieldApiDataTest.php similarity index 98% rename from web/core/modules/views/src/Tests/FieldApiDataTest.php rename to web/core/modules/views/tests/src/Functional/FieldApiDataTest.php index b20a8712e615eb05ef3e0416c8ed7cbfe97ffc55..3c0fec42b31369929ec67777347a0a1492deac8e 100644 --- a/web/core/modules/views/src/Tests/FieldApiDataTest.php +++ b/web/core/modules/views/tests/src/Functional/FieldApiDataTest.php @@ -1,14 +1,14 @@ <?php -namespace Drupal\views\Tests; +namespace Drupal\Tests\views\Functional; use Drupal\Component\Render\MarkupInterface; use Drupal\field\Entity\FieldConfig; -use Drupal\field\Tests\Views\FieldTestBase; use Drupal\language\Entity\ConfigurableLanguage; use Drupal\language\Entity\ContentLanguageSettings; use Drupal\node\Entity\Node; use Drupal\node\Entity\NodeType; +use Drupal\Tests\field\Functional\Views\FieldTestBase; use Drupal\views\Views; /** @@ -263,7 +263,7 @@ protected function getViewsData() { } /** - * Tests filtering entries with different translatabilty. + * Tests filtering entries with different translatability. */ public function testEntityFieldFilter() { $map = [ diff --git a/web/core/modules/views/tests/src/Functional/Handler/FieldWebTest.php b/web/core/modules/views/tests/src/Functional/Handler/FieldWebTest.php index eda5b81abe1f4ae8c1220f1b21d1a881de39a461..816fce1f27bc35ad768360bfb5cec72e0f39d142 100644 --- a/web/core/modules/views/tests/src/Functional/Handler/FieldWebTest.php +++ b/web/core/modules/views/tests/src/Functional/Handler/FieldWebTest.php @@ -339,7 +339,7 @@ public function testAlterUrl() { $this->assertSubString($output, UrlHelper::encodePath('Drupal Has A Great Community')); unset($id_field->options['alter']['path_case']); - // Tests the linkclass setting and see whether it actually exists in the + // Tests the link_class setting and see whether it actually exists in the // output. $id_field->options['alter']['link_class'] = $class = $this->randomMachineName(); $output = $renderer->executeInRenderContext(new RenderContext(), function () use ($id_field, $row) { diff --git a/web/core/modules/views/tests/src/Functional/Plugin/DisplayEntityReferenceTest.php b/web/core/modules/views/tests/src/Functional/Plugin/DisplayEntityReferenceTest.php index 499d1b2c8abf1ef723b3b97a25b0bd8bfc69b073..817c51d7875adf8e0b3bab69f0a2cfcad1c5a28d 100644 --- a/web/core/modules/views/tests/src/Functional/Plugin/DisplayEntityReferenceTest.php +++ b/web/core/modules/views/tests/src/Functional/Plugin/DisplayEntityReferenceTest.php @@ -5,7 +5,7 @@ use Drupal\entity_test\Entity\EntityTest; use Drupal\field\Entity\FieldConfig; use Drupal\field\Entity\FieldStorageConfig; -use Drupal\field\Tests\EntityReference\EntityReferenceTestTrait; +use Drupal\Tests\field\Traits\EntityReferenceTestTrait; use Drupal\Tests\views\Functional\ViewTestBase; use Drupal\views\Views; @@ -213,7 +213,7 @@ public function testEntityReferenceDisplay() { $this->drupalPostForm('admin/structure/views/nojs/display/test_display_entity_reference/entity_reference_1/style_options', ['style_options[search_fields][uid]' => 'uid'], t('Apply')); $this->drupalPostForm(NULL, [], t('Save')); - // Test that the search still works with the ralated field. + // Test that the search still works with the related field. $view = Views::getView('test_display_entity_reference'); $view->setDisplay('entity_reference_1'); diff --git a/web/core/modules/views/src/Tests/Plugin/DisplayFeedTest.php b/web/core/modules/views/tests/src/Functional/Plugin/DisplayFeedTest.php similarity index 84% rename from web/core/modules/views/src/Tests/Plugin/DisplayFeedTest.php rename to web/core/modules/views/tests/src/Functional/Plugin/DisplayFeedTest.php index 04ba4cab993eeeef1594f39eef2304a7a534aacd..6599a4416fd61b09b2af4daf12265f1cde958acc 100644 --- a/web/core/modules/views/src/Tests/Plugin/DisplayFeedTest.php +++ b/web/core/modules/views/tests/src/Functional/Plugin/DisplayFeedTest.php @@ -1,7 +1,8 @@ <?php -namespace Drupal\views\Tests\Plugin; +namespace Drupal\Tests\views\Functional\Plugin; +use Drupal\Tests\views\Functional\ViewTestBase; use Drupal\views\Views; /** @@ -10,7 +11,7 @@ * @group views * @see \Drupal\views\Plugin\views\display\Feed */ -class DisplayFeedTest extends PluginTestBase { +class DisplayFeedTest extends ViewTestBase { /** * Views used by this test. @@ -58,9 +59,8 @@ public function testFeedOutput() { $this->config('system.site')->set('name', $site_name)->save(); $this->drupalGet('test-feed-display.xml'); - $result = $this->xpath('//title'); - $this->assertEqual($result[0], $site_name, 'The site title is used for the feed title.'); - $this->assertEqual($result[1], $node_title, 'Node title with HTML entities displays correctly.'); + $this->assertEquals($site_name, $this->getSession()->getDriver()->getText('//title')); + $this->assertEquals($node_title, $this->getSession()->getDriver()->getText('//item/title')); // Verify HTML is properly escaped in the description field. $this->assertRaw('<p>A paragraph</p>'); @@ -70,8 +70,7 @@ public function testFeedOutput() { $view->save(); $this->drupalGet('test-feed-display.xml'); - $result = $this->xpath('//title'); - $this->assertEqual($result[0], 'test_display_feed', 'The display title is used for the feed title.'); + $this->assertEquals('test_display_feed', $this->getSession()->getDriver()->getText('//title')); // Add a block display and attach the feed. $view->getExecutable()->newDisplay('block', NULL, 'test'); @@ -82,14 +81,14 @@ public function testFeedOutput() { $this->drupalPlaceBlock('views_block:test_display_feed-test'); $this->drupalGet('<front>'); $feed_icon = $this->cssSelect('div.view-id-test_display_feed a.feed-icon'); - $this->assertTrue(strpos($feed_icon[0]['href'], 'test-feed-display.xml'), 'The feed icon was found.'); + $this->assertTrue(strpos($feed_icon[0]->getAttribute('href'), 'test-feed-display.xml'), 'The feed icon was found.'); // Test feed display attached to page display with arguments. $this->drupalGet('test-feed-icon/' . $node->id()); $page_url = $this->getUrl(); - $icon_href = $this->cssSelect('a.feed-icon[href *= "test-feed-icon"]')[0]['href']; + $icon_href = $this->cssSelect('a.feed-icon[href *= "test-feed-icon"]')[0]->getAttribute('href'); $this->assertEqual($icon_href, $page_url . '/feed', 'The feed icon was found.'); - $link_href = $this->cssSelect('link[type = "application/rss+xml"][href *= "test-feed-icon"]')[0]['href']; + $link_href = $this->cssSelect('link[type = "application/rss+xml"][href *= "test-feed-icon"]')[0]->getAttribute('href'); $this->assertEqual($link_href, $page_url . '/feed', 'The RSS link was found.'); $feed_link = simplexml_load_string($this->drupalGet($icon_href))->channel->link; $this->assertEqual($feed_link, $page_url, 'The channel link was found.'); @@ -114,8 +113,7 @@ public function testFeedFieldOutput() { ]); $this->drupalGet('test-feed-display-fields.xml'); - $result = $this->xpath('//title/a'); - $this->assertEqual($result[0], $node_title, 'Node title with HTML entities displays correctly.'); + $this->assertEquals($node_title, $this->getSession()->getDriver()->getText('//title/a')); // Verify HTML is properly escaped in the description field. $this->assertRaw('<p>A paragraph</p>'); } @@ -136,8 +134,8 @@ public function testDisabledFeed() { // Check that the rss header is output on the page display. $this->drupalGet('/test-attached-disabled'); $feed_header = $this->xpath('//link[@rel="alternate"]'); - $this->assertEqual($feed_header[0]['type'], 'application/rss+xml', 'The feed link has the type application/rss+xml.'); - $this->assertTrue(strpos($feed_header[0]['href'], 'test-attached-disabled.xml'), 'Page display contains the correct feed URL.'); + $this->assertEqual($feed_header[0]->getAttribute('type'), 'application/rss+xml', 'The feed link has the type application/rss+xml.'); + $this->assertTrue(strpos($feed_header[0]->getAttribute('href'), 'test-attached-disabled.xml'), 'Page display contains the correct feed URL.'); // Disable the feed display. $view->displayHandlers->get('feed_1')->setOption('enabled', FALSE); diff --git a/web/core/modules/views/tests/src/Functional/Plugin/ExposedFormCheckboxesTest.php b/web/core/modules/views/tests/src/Functional/Plugin/ExposedFormCheckboxesTest.php index f5901a080d155dc5bb07109efa43f9823e297cd3..3f807f67d6806bd4c29e167767f380c09c9f5606 100644 --- a/web/core/modules/views/tests/src/Functional/Plugin/ExposedFormCheckboxesTest.php +++ b/web/core/modules/views/tests/src/Functional/Plugin/ExposedFormCheckboxesTest.php @@ -3,9 +3,9 @@ namespace Drupal\Tests\views\Functional\Plugin; use Drupal\Core\Field\FieldStorageDefinitionInterface; -use Drupal\field\Tests\EntityReference\EntityReferenceTestTrait; use Drupal\taxonomy\Entity\Term; use Drupal\taxonomy\Entity\Vocabulary; +use Drupal\Tests\field\Traits\EntityReferenceTestTrait; use Drupal\Tests\views\Functional\ViewTestBase; use Drupal\views\Tests\ViewTestData; use Drupal\views\Views; diff --git a/web/core/modules/views/src/Tests/Plugin/StyleOpmlTest.php b/web/core/modules/views/tests/src/Functional/Plugin/StyleOpmlTest.php similarity index 61% rename from web/core/modules/views/src/Tests/Plugin/StyleOpmlTest.php rename to web/core/modules/views/tests/src/Functional/Plugin/StyleOpmlTest.php index 66a8bc826be43cb9ffef0adc95530ca24ad22af5..bf0f2a1adba82ed1fd849f021b1be28a92f35207 100644 --- a/web/core/modules/views/src/Tests/Plugin/StyleOpmlTest.php +++ b/web/core/modules/views/tests/src/Functional/Plugin/StyleOpmlTest.php @@ -1,6 +1,8 @@ <?php -namespace Drupal\views\Tests\Plugin; +namespace Drupal\Tests\views\Functional\Plugin; + +use Drupal\Tests\views\Functional\ViewTestBase; /** * Tests the OPML feed style plugin. @@ -8,7 +10,7 @@ * @group views * @see \Drupal\views\Plugin\views\style\Opml */ -class StyleOpmlTest extends PluginTestBase { +class StyleOpmlTest extends ViewTestBase { /** * Views used by this test. @@ -52,10 +54,10 @@ public function testOpmlOutput() { $feed->save(); $this->drupalGet('test-feed-opml-style'); - $outline = $this->xpath('//outline[1]'); - $this->assertEqual($outline[0]['type'], 'rss', 'The correct type attribute is used for rss OPML.'); - $this->assertEqual($outline[0]['text'], $feed->label(), 'The correct text attribute is used for rss OPML.'); - $this->assertEqual($outline[0]['xmlurl'], $feed->getUrl(), 'The correct xmlUrl attribute is used for rss OPML.'); + $outline = $this->getSession()->getDriver()->find('//outline[1]')[0]; + $this->assertEquals('rss', $outline->getAttribute('type')); + $this->assertEquals($feed->label(), $outline->getAttribute('text')); + $this->assertEquals($feed->getUrl(), $outline->getAttribute('xmlUrl')); $view = $this->container->get('entity.manager') ->getStorage('view') @@ -66,12 +68,12 @@ public function testOpmlOutput() { $view->save(); $this->drupalGet('test-feed-opml-style'); - $outline = $this->xpath('//outline[1]'); - $this->assertEqual($outline[0]['type'], 'link', 'The correct type attribute is used for link OPML.'); - $this->assertEqual($outline[0]['text'], $feed->label(), 'The correct text attribute is used for link OPML.'); - $this->assertEqual($outline[0]['url'], $feed->getUrl(), 'The correct URL attribute is used for link OPML.'); + $outline = $this->getSession()->getDriver()->find('//outline[1]')[0]; + $this->assertEquals('link', $outline->getAttribute('type')); + $this->assertEquals($feed->label(), $outline->getAttribute('text')); + $this->assertEquals($feed->getUrl(), $outline->getAttribute('url')); // xmlUrl should not be present when type is link. - $this->assertNull($outline[0]['xmlUrl'], 'The xmlUrl attribute is not used for link OPML.'); + $this->assertNull($outline->getAttribute('xmlUrl')); } } diff --git a/web/core/modules/views/tests/src/Functional/UserPathTest.php b/web/core/modules/views/tests/src/Functional/UserPathTest.php new file mode 100644 index 0000000000000000000000000000000000000000..27a0f27a9bbaa500bf4c9e6528e632fc4bef7ed4 --- /dev/null +++ b/web/core/modules/views/tests/src/Functional/UserPathTest.php @@ -0,0 +1,32 @@ +<?php + +namespace Drupal\Tests\views\Functional; + +/** + * Tests overriding user paths using wildcards. + * + * @group views + */ +class UserPathTest extends ViewTestBase { + + /** + * {@inheritdoc} + */ + public static $modules = ['views', 'user']; + + /** + * The test views to use. + * + * @var array + */ + public static $testViews = ['test_user_path']; + + /** + * Tests if the login page is still available when using a wildcard path. + */ + public function testUserLoginPage() { + $this->drupalGet('user/login'); + $this->assertSession()->statusCodeEquals(200); + } + +} diff --git a/web/core/modules/views/tests/src/Functional/Wizard/TaggedWithTest.php b/web/core/modules/views/tests/src/Functional/Wizard/TaggedWithTest.php index 680d64496edc5b1cb93402ebd0bbbfad70cd441d..54e0e3de3176d28311c8d71b575dddd39401d1a2 100644 --- a/web/core/modules/views/tests/src/Functional/Wizard/TaggedWithTest.php +++ b/web/core/modules/views/tests/src/Functional/Wizard/TaggedWithTest.php @@ -4,8 +4,8 @@ use Drupal\Core\Field\FieldStorageDefinitionInterface; use Drupal\field\Entity\FieldConfig; -use Drupal\field\Tests\EntityReference\EntityReferenceTestTrait; use Drupal\taxonomy\Entity\Vocabulary; +use Drupal\Tests\field\Traits\EntityReferenceTestTrait; /** * Tests the ability of the views wizard to create views filtered by taxonomy. diff --git a/web/core/modules/views/tests/src/Kernel/ModuleTest.php b/web/core/modules/views/tests/src/Kernel/ModuleTest.php index f61c856200f673dda84a8570e3dcc077c4398fb3..1333c6225b9828357988ecb5a22fe97d36354428 100644 --- a/web/core/modules/views/tests/src/Kernel/ModuleTest.php +++ b/web/core/modules/views/tests/src/Kernel/ModuleTest.php @@ -37,9 +37,9 @@ class ModuleTest extends ViewsKernelTestBase { protected $lastErrorMessage; /** - * Tests the views_get_handler method. + * Tests the ViewsHandlerManager::getHandler() method. * - * @see views_get_handler() + * @see \Drupal\views\Plugin\ViewsHandlerManager::getHandler() */ public function testViewsGetHandler() { $types = ['field', 'area', 'filter']; diff --git a/web/core/modules/views/tests/src/Kernel/ViewElementTest.php b/web/core/modules/views/tests/src/Kernel/ViewElementTest.php index c6149e90e9364935ae8f337c5540985cb6166fb4..2dbc31ca0a3408af26c2d6df2d8e33d9e4fdbb12 100644 --- a/web/core/modules/views/tests/src/Kernel/ViewElementTest.php +++ b/web/core/modules/views/tests/src/Kernel/ViewElementTest.php @@ -82,6 +82,9 @@ public function testViewElementEmbed() { $this->assertEqual($render['#embed'], TRUE); $this->setRawContent($renderer->renderRoot($render)); + // Ensure that the render array can be serialized. + serialize($render); + $xpath = $this->xpath('//div[@class="views-element-container"]'); $this->assertTrue($xpath, 'The view container has been found in the rendered output.'); diff --git a/web/core/modules/views/tests/src/Kernel/ViewExecutableTest.php b/web/core/modules/views/tests/src/Kernel/ViewExecutableTest.php index 1290d54d85b0b9478fb184ee8cc3bf830ed2b666..cb548c0afbaf34880a4f28ec187babe9e00bbb23 100644 --- a/web/core/modules/views/tests/src/Kernel/ViewExecutableTest.php +++ b/web/core/modules/views/tests/src/Kernel/ViewExecutableTest.php @@ -136,7 +136,7 @@ public function testInitMethods() { // Test the initStyle() method. $view->initStyle(); $this->assertTrue($view->style_plugin instanceof DefaultStyle, 'Make sure a reference to the style plugin is set.'); - // Test the plugin has been inited and view have references to the view and + // Test the plugin has been invited and view have references to the view and // display handler. $this->assertEqual(spl_object_hash($view->style_plugin->view), $view_hash); $this->assertEqual(spl_object_hash($view->style_plugin->displayHandler), $display_hash); diff --git a/web/core/modules/views/views.views.inc b/web/core/modules/views/views.views.inc index 633ce9b9da802408b922f3b16478b90f125438bf..024d499738c1b0d279901e28d9b2745372b3ed8a 100644 --- a/web/core/modules/views/views.views.inc +++ b/web/core/modules/views/views.views.inc @@ -375,9 +375,13 @@ function views_field_default_views_data(FieldStorageConfigInterface $field_stora else { // https://www.drupal.org/node/2451657#comment-11462881 \Drupal::logger('views')->error( - t('A non-existent config entity name returned by FieldStorageConfigInterface::getBundles(): field name: %field, bundle: %bundle', - ['%field' => $field_name, '%bundle' => $bundle] - )); + 'A non-existent config entity name returned by FieldStorageConfigInterface::getBundles(): entity type: %entity_type, bundle: %bundle, field name: %field', + [ + '%entity_type' => $entity_type->id(), + '%bundle' => $bundle, + '%field' => $field_name, + ] + ); } } diff --git a/web/core/modules/views_ui/js/views-admin.es6.js b/web/core/modules/views_ui/js/views-admin.es6.js index f265b2ce74258100bb4e180e9fe1acf22e6479e9..758d8d10023479269f06f0cc8396253403d8bdff 100644 --- a/web/core/modules/views_ui/js/views-admin.es6.js +++ b/web/core/modules/views_ui/js/views-admin.es6.js @@ -642,7 +642,7 @@ * @type {Drupal~behavior} * * @prop {Drupal~behaviorAttach} attach - * Attach handlers to make it possible to rearange the filters in the form + * Attach handlers to make it possible to rearrange the filters in the form * in question. * @see Drupal.viewsUi.RearrangeFilterHandler */ diff --git a/web/core/modules/views_ui/src/Tests/PreviewTest.php b/web/core/modules/views_ui/src/Tests/PreviewTest.php deleted file mode 100644 index c8bd7bd14c2cf6a658c8f248b77051de97f76991..0000000000000000000000000000000000000000 --- a/web/core/modules/views_ui/src/Tests/PreviewTest.php +++ /dev/null @@ -1,386 +0,0 @@ -<?php - -namespace Drupal\views_ui\Tests; - -use Drupal\Component\Serialization\Json; -use Drupal\Core\EventSubscriber\MainContentViewSubscriber; - -/** - * Tests the UI preview functionality. - * - * @group views_ui - */ -class PreviewTest extends UITestBase { - - /** - * Views used by this test. - * - * @var array - */ - public static $testViews = ['test_preview', 'test_preview_error', 'test_pager_full', 'test_mini_pager', 'test_click_sort']; - - /** - * Tests contextual links in the preview form. - */ - public function testPreviewContextual() { - \Drupal::service('module_installer')->install(['contextual']); - $this->resetAll(); - - $this->drupalGet('admin/structure/views/view/test_preview/edit'); - $this->assertResponse(200); - $this->drupalPostForm(NULL, $edit = [], t('Update preview')); - - $elements = $this->xpath('//div[@id="views-live-preview"]//ul[contains(@class, :ul-class)]/li[contains(@class, :li-class)]', [':ul-class' => 'contextual-links', ':li-class' => 'filter-add']); - $this->assertEqual(count($elements), 1, 'The contextual link to add a new field is shown.'); - - $this->drupalPostForm(NULL, $edit = ['view_args' => '100'], t('Update preview')); - - // Test that area text and exposed filters are present and rendered. - $this->assertFieldByName('id', NULL, 'ID exposed filter field found.'); - $this->assertText('Test header text', 'Rendered header text found'); - $this->assertText('Test footer text', 'Rendered footer text found.'); - $this->assertText('Test empty text', 'Rendered empty text found.'); - } - - /** - * Tests arguments in the preview form. - */ - public function testPreviewUI() { - $this->drupalGet('admin/structure/views/view/test_preview/edit'); - $this->assertResponse(200); - - $this->drupalPostForm(NULL, $edit = [], t('Update preview')); - - $elements = $this->xpath('//div[@class = "view-content"]/div[contains(@class, views-row)]'); - $this->assertEqual(count($elements), 5); - - // Filter just the first result. - $this->drupalPostForm(NULL, $edit = ['view_args' => '1'], t('Update preview')); - - $elements = $this->xpath('//div[@class = "view-content"]/div[contains(@class, views-row)]'); - $this->assertEqual(count($elements), 1); - - // Filter for no results. - $this->drupalPostForm(NULL, $edit = ['view_args' => '100'], t('Update preview')); - - $elements = $this->xpath('//div[@class = "view-content"]/div[contains(@class, views-row)]'); - $this->assertEqual(count($elements), 0); - - // Test that area text and exposed filters are present and rendered. - $this->assertFieldByName('id', NULL, 'ID exposed filter field found.'); - $this->assertText('Test header text', 'Rendered header text found'); - $this->assertText('Test footer text', 'Rendered footer text found.'); - $this->assertText('Test empty text', 'Rendered empty text found.'); - - // Test feed preview. - $view = []; - $view['label'] = $this->randomMachineName(16); - $view['id'] = strtolower($this->randomMachineName(16)); - $view['page[create]'] = 1; - $view['page[title]'] = $this->randomMachineName(16); - $view['page[path]'] = $this->randomMachineName(16); - $view['page[feed]'] = 1; - $view['page[feed_properties][path]'] = $this->randomMachineName(16); - $this->drupalPostForm('admin/structure/views/add', $view, t('Save and edit')); - $this->clickLink(t('Feed')); - $this->drupalPostForm(NULL, [], t('Update preview')); - $result = $this->xpath('//div[@id="views-live-preview"]/pre'); - $this->assertTrue(strpos($result[0], '<title>' . $view['page[title]'] . '</title>'), 'The Feed RSS preview was rendered.'); - - // Test the non-default UI display options. - // Statistics only, no query. - $settings = \Drupal::configFactory()->getEditable('views.settings'); - $settings->set('ui.show.performance_statistics', TRUE)->save(); - $this->drupalGet('admin/structure/views/view/test_preview/edit'); - $this->drupalPostForm(NULL, $edit = ['view_args' => '100'], t('Update preview')); - $this->assertText(t('Query build time')); - $this->assertText(t('Query execute time')); - $this->assertText(t('View render time')); - $this->assertNoRaw('<strong>Query</strong>'); - - // Statistics and query. - $settings->set('ui.show.sql_query.enabled', TRUE)->save(); - $this->drupalPostForm(NULL, $edit = ['view_args' => '100'], t('Update preview')); - $this->assertText(t('Query build time')); - $this->assertText(t('Query execute time')); - $this->assertText(t('View render time')); - $this->assertRaw('<strong>Query</strong>'); - $query_string = <<<SQL -SELECT views_test_data.name AS views_test_data_name -FROM -{views_test_data} views_test_data -WHERE (views_test_data.id = '100') -SQL; - $this->assertEscaped($query_string); - - // Test that the statistics and query are rendered above the preview. - $this->assertTrue(strpos($this->getRawContent(), 'views-query-info') < strpos($this->getRawContent(), 'view-test-preview'), 'Statistics shown above the preview.'); - - // Test that statistics and query rendered below the preview. - $settings->set('ui.show.sql_query.where', 'below')->save(); - $this->drupalPostForm(NULL, $edit = ['view_args' => '100'], t('Update preview')); - $this->assertTrue(strpos($this->getRawContent(), 'view-test-preview') < strpos($this->getRawContent(), 'views-query-info'), 'Statistics shown below the preview.'); - - // Test that the preview title isn't double escaped. - $this->drupalPostForm("admin/structure/views/nojs/display/test_preview/default/title", $edit = ['title' => 'Double & escaped'], t('Apply')); - $this->drupalPostForm(NULL, [], t('Update preview')); - $elements = $this->xpath('//div[@id="views-live-preview"]/div[contains(@class, views-query-info)]//td[text()=:text]', [':text' => t('Double & escaped')]); - $this->assertEqual(1, count($elements)); - } - - /** - * Tests the taxonomy term preview AJAX. - * - * This tests a specific regression in the taxonomy term view preview. - * - * @see https://www.drupal.org/node/2452659 - */ - public function testTaxonomyAJAX() { - \Drupal::service('module_installer')->install(['taxonomy']); - $this->getPreviewAJAX('taxonomy_term', 'page_1', 0); - } - - /** - * Tests pagers in the preview form. - */ - public function testPreviewWithPagersUI() { - - // Create 11 nodes and make sure that everyone is returned. - $this->drupalCreateContentType(['type' => 'page']); - for ($i = 0; $i < 11; $i++) { - $this->drupalCreateNode(); - } - - // Test Full Pager. - $this->getPreviewAJAX('test_pager_full', 'default', 5); - - // Test that the pager is present and rendered. - $elements = $this->xpath('//ul[contains(@class, :class)]/li', [':class' => 'pager__items']); - $this->assertTrue(!empty($elements), 'Full pager found.'); - - // Verify elements and links to pages. - // We expect to find 5 elements: current page == 1, links to pages 2 and - // and 3, links to 'next >' and 'last >>' pages. - $this->assertClass($elements[0], 'is-active', 'Element for current page has .is-active class.'); - $this->assertTrue($elements[0]->a, 'Element for current page has link.'); - - $this->assertClass($elements[1], 'pager__item', 'Element for page 2 has .pager__item class.'); - $this->assertTrue($elements[1]->a, 'Link to page 2 found.'); - - $this->assertClass($elements[2], 'pager__item', 'Element for page 3 has .pager__item class.'); - $this->assertTrue($elements[2]->a, 'Link to page 3 found.'); - - $this->assertClass($elements[3], 'pager__item--next', 'Element for next page has .pager__item--next class.'); - $this->assertTrue($elements[3]->a, 'Link to next page found.'); - - $this->assertClass($elements[4], 'pager__item--last', 'Element for last page has .pager__item--last class.'); - $this->assertTrue($elements[4]->a, 'Link to last page found.'); - - // Navigate to next page. - $elements = $this->xpath('//li[contains(@class, :class)]/a', [':class' => 'pager__item--next']); - $this->clickPreviewLinkAJAX($elements[0]['href'], 5); - - // Test that the pager is present and rendered. - $elements = $this->xpath('//ul[contains(@class, :class)]/li', [':class' => 'pager__items']); - $this->assertTrue(!empty($elements), 'Full pager found.'); - - // Verify elements and links to pages. - // We expect to find 7 elements: links to '<< first' and '< previous' - // pages, link to page 1, current page == 2, link to page 3 and links - // to 'next >' and 'last >>' pages. - $this->assertClass($elements[0], 'pager__item--first', 'Element for first page has .pager__item--first class.'); - $this->assertTrue($elements[0]->a, 'Link to first page found.'); - - $this->assertClass($elements[1], 'pager__item--previous', 'Element for previous page has .pager__item--previous class.'); - $this->assertTrue($elements[1]->a, 'Link to previous page found.'); - - $this->assertClass($elements[2], 'pager__item', 'Element for page 1 has .pager__item class.'); - $this->assertTrue($elements[2]->a, 'Link to page 1 found.'); - - $this->assertClass($elements[3], 'is-active', 'Element for current page has .is-active class.'); - $this->assertTrue($elements[3]->a, 'Element for current page has link.'); - - $this->assertClass($elements[4], 'pager__item', 'Element for page 3 has .pager__item class.'); - $this->assertTrue($elements[4]->a, 'Link to page 3 found.'); - - $this->assertClass($elements[5], 'pager__item--next', 'Element for next page has .pager__item--next class.'); - $this->assertTrue($elements[5]->a, 'Link to next page found.'); - - $this->assertClass($elements[6], 'pager__item--last', 'Element for last page has .pager__item--last class.'); - $this->assertTrue($elements[6]->a, 'Link to last page found.'); - - // Test Mini Pager. - $this->getPreviewAJAX('test_mini_pager', 'default', 3); - - // Test that the pager is present and rendered. - $elements = $this->xpath('//ul[contains(@class, :class)]/li', [':class' => 'pager__items']); - $this->assertTrue(!empty($elements), 'Mini pager found.'); - - // Verify elements and links to pages. - // We expect to find current pages element with no link, next page element - // with a link, and not to find previous page element. - $this->assertClass($elements[0], 'is-active', 'Element for current page has .is-active class.'); - - $this->assertClass($elements[1], 'pager__item--next', 'Element for next page has .pager__item--next class.'); - $this->assertTrue($elements[1]->a, 'Link to next page found.'); - - // Navigate to next page. - $elements = $this->xpath('//li[contains(@class, :class)]/a', [':class' => 'pager__item--next']); - $this->clickPreviewLinkAJAX($elements[0]['href'], 3); - - // Test that the pager is present and rendered. - $elements = $this->xpath('//ul[contains(@class, :class)]/li', [':class' => 'pager__items']); - $this->assertTrue(!empty($elements), 'Mini pager found.'); - - // Verify elements and links to pages. - // We expect to find 3 elements: previous page with a link, current - // page with no link, and next page with a link. - $this->assertClass($elements[0], 'pager__item--previous', 'Element for previous page has .pager__item--previous class.'); - $this->assertTrue($elements[0]->a, 'Link to previous page found.'); - - $this->assertClass($elements[1], 'is-active', 'Element for current page has .is-active class.'); - $this->assertFalse(isset($elements[1]->a), 'Element for current page has no link.'); - - $this->assertClass($elements[2], 'pager__item--next', 'Element for next page has .pager__item--next class.'); - $this->assertTrue($elements[2]->a, 'Link to next page found.'); - } - - /** - * Tests the additional information query info area. - */ - public function testPreviewAdditionalInfo() { - \Drupal::service('module_installer')->install(['views_ui_test']); - $this->resetAll(); - - $this->drupalGet('admin/structure/views/view/test_preview/edit'); - $this->assertResponse(200); - - $this->drupalPostForm(NULL, $edit = [], t('Update preview')); - - // Check for implementation of hook_views_preview_info_alter(). - // @see views_ui_test.module - $elements = $this->xpath('//div[@id="views-live-preview"]/div[contains(@class, views-query-info)]//td[text()=:text]', [':text' => t('Test row count')]); - $this->assertEqual(count($elements), 1, 'Views Query Preview Info area altered.'); - // Check that additional assets are attached. - $this->assertTrue(strpos($this->getDrupalSettings()['ajaxPageState']['libraries'], 'views_ui_test/views_ui_test.test') !== FALSE, 'Attached library found.'); - $this->assertRaw('css/views_ui_test.test.css', 'Attached CSS asset found.'); - } - - /** - * Tests view validation error messages in the preview. - */ - public function testPreviewError() { - $this->drupalGet('admin/structure/views/view/test_preview_error/edit'); - $this->assertResponse(200); - - $this->drupalPostForm(NULL, $edit = [], t('Update preview')); - - $this->assertText('Unable to preview due to validation errors.', 'Preview error text found.'); - } - - /** - * Tests the link to sort in the preview form. - */ - public function testPreviewSortLink() { - - // Get the preview. - $this->getPreviewAJAX('test_click_sort', 'page_1', 0); - - // Test that the header label is present. - $elements = $this->xpath('//th[contains(@class, :class)]/a', [':class' => 'views-field views-field-name']); - $this->assertTrue(!empty($elements), 'The header label is present.'); - - // Verify link. - $this->assertLinkByHref('preview/page_1?_wrapper_format=drupal_ajax&order=name&sort=desc', 0, 'The output URL is as expected.'); - - // Click link to sort. - $this->clickPreviewLinkAJAX($elements[0]['href'], 0); - - // Test that the header label is present. - $elements = $this->xpath('//th[contains(@class, :class)]/a', [':class' => 'views-field views-field-name is-active']); - $this->assertTrue(!empty($elements), 'The header label is present.'); - - // Verify link. - $this->assertLinkByHref('preview/page_1?_wrapper_format=drupal_ajax&order=name&sort=asc', 0, 'The output URL is as expected.'); - } - - /** - * Get the preview form and force an AJAX preview update. - * - * @param string $view_name - * The view to test. - * @param string $panel_id - * The view panel to test. - * @param int $row_count - * The expected number of rows in the preview. - */ - protected function getPreviewAJAX($view_name, $panel_id, $row_count) { - $this->drupalGet('admin/structure/views/view/' . $view_name . '/preview/' . $panel_id); - $result = $this->drupalPostAjaxForm(NULL, [], ['op' => t('Update preview')]); - $this->assertPreviewAJAX($result, $row_count); - } - - /** - * Mimic clicking on a preview link. - * - * @param string $url - * The url to navigate to. - * @param int $row_count - * The expected number of rows in the preview. - */ - protected function clickPreviewLinkAJAX($url, $row_count) { - $content = $this->content; - $drupal_settings = $this->drupalSettings; - $ajax_settings = [ - 'wrapper' => 'views-preview-wrapper', - 'method' => 'replaceWith', - ]; - $url = $this->getAbsoluteUrl($url); - $post = ['js' => 'true'] + $this->getAjaxPageStatePostData(); - $result = Json::decode($this->drupalPost($url, '', $post, ['query' => [MainContentViewSubscriber::WRAPPER_FORMAT => 'drupal_ajax']])); - if (!empty($result)) { - $this->drupalProcessAjaxResponse($content, $result, $ajax_settings, $drupal_settings); - } - $this->assertPreviewAJAX($result, $row_count); - } - - /** - * Assert that the AJAX response contains expected data. - * - * @param array $result - * An array of AJAX commands. - * @param int $row_count - * The expected number of rows in the preview. - */ - protected function assertPreviewAJAX($result, $row_count) { - // Has AJAX callback replied with an insert command? If so, we can - // assume that the page content was updated with AJAX returned data. - $result_commands = []; - foreach ($result as $command) { - $result_commands[$command['command']] = $command; - } - $this->assertTrue(isset($result_commands['insert']), 'AJAX insert command received.'); - - // Test if preview contains the expected number of rows. - $elements = $this->xpath('//div[@class = "view-content"]/div[contains(@class, views-row)]'); - $this->assertEqual(count($elements), $row_count, 'Expected items found on page.'); - } - - /** - * Asserts that an element has a given class. - * - * @param \SimpleXMLElement $element - * The element to test. - * @param string $class - * The class to assert. - * @param string $message - * (optional) A verbose message to output. - */ - protected function assertClass(\SimpleXMLElement $element, $class, $message = NULL) { - if (!isset($message)) { - $message = "Class .$class found."; - } - $this->assertTrue(strpos($element['class'], $class) !== FALSE, $message); - } - -} diff --git a/web/core/modules/views_ui/src/ViewUI.php b/web/core/modules/views_ui/src/ViewUI.php index 6b49fdc92d3b8cb22f04c9b63228c46331b37459..de323bd277ae9f7d9a4f205ef160d37080013d19 100644 --- a/web/core/modules/views_ui/src/ViewUI.php +++ b/web/core/modules/views_ui/src/ViewUI.php @@ -51,7 +51,7 @@ class ViewUI implements ViewEntityInterface { * \Drupal\Core\TempStore\SharedTempStore::getMetadata(). Which can be a stdClass or * NULL. * - * @var stdClass + * @var object */ public $lock; diff --git a/web/core/modules/views_ui/tests/src/Functional/PreviewTest.php b/web/core/modules/views_ui/tests/src/Functional/PreviewTest.php new file mode 100644 index 0000000000000000000000000000000000000000..b76e464c8c341a50ef0b4b77d6f2d911b2473bc0 --- /dev/null +++ b/web/core/modules/views_ui/tests/src/Functional/PreviewTest.php @@ -0,0 +1,161 @@ +<?php + +namespace Drupal\Tests\views_ui\Functional; + +/** + * Tests the UI preview functionality. + * + * @group views_ui + */ +class PreviewTest extends UITestBase { + + /** + * Views used by this test. + * + * @var array + */ + public static $testViews = ['test_preview', 'test_preview_error', 'test_pager_full', 'test_mini_pager', 'test_click_sort']; + + /** + * Tests contextual links in the preview form. + */ + public function testPreviewContextual() { + \Drupal::service('module_installer')->install(['contextual']); + $this->resetAll(); + + $this->drupalGet('admin/structure/views/view/test_preview/edit'); + $this->assertResponse(200); + $this->drupalPostForm(NULL, $edit = [], t('Update preview')); + + $elements = $this->xpath('//div[@id="views-live-preview"]//ul[contains(@class, :ul-class)]/li[contains(@class, :li-class)]', [':ul-class' => 'contextual-links', ':li-class' => 'filter-add']); + $this->assertEqual(count($elements), 1, 'The contextual link to add a new field is shown.'); + + $this->drupalPostForm(NULL, $edit = ['view_args' => '100'], t('Update preview')); + + // Test that area text and exposed filters are present and rendered. + $this->assertFieldByName('id', NULL, 'ID exposed filter field found.'); + $this->assertText('Test header text', 'Rendered header text found'); + $this->assertText('Test footer text', 'Rendered footer text found.'); + $this->assertText('Test empty text', 'Rendered empty text found.'); + } + + /** + * Tests arguments in the preview form. + */ + public function testPreviewUI() { + $this->drupalGet('admin/structure/views/view/test_preview/edit'); + $this->assertResponse(200); + + $this->drupalPostForm(NULL, $edit = [], t('Update preview')); + + $elements = $this->xpath('//div[@class = "view-content"]/div[contains(@class, views-row)]'); + $this->assertEqual(count($elements), 5); + + // Filter just the first result. + $this->drupalPostForm(NULL, $edit = ['view_args' => '1'], t('Update preview')); + + $elements = $this->xpath('//div[@class = "view-content"]/div[contains(@class, views-row)]'); + $this->assertEqual(count($elements), 1); + + // Filter for no results. + $this->drupalPostForm(NULL, $edit = ['view_args' => '100'], t('Update preview')); + + $elements = $this->xpath('//div[@class = "view-content"]/div[contains(@class, views-row)]'); + $this->assertEqual(count($elements), 0); + + // Test that area text and exposed filters are present and rendered. + $this->assertFieldByName('id', NULL, 'ID exposed filter field found.'); + $this->assertText('Test header text', 'Rendered header text found'); + $this->assertText('Test footer text', 'Rendered footer text found.'); + $this->assertText('Test empty text', 'Rendered empty text found.'); + + // Test feed preview. + $view = []; + $view['label'] = $this->randomMachineName(16); + $view['id'] = strtolower($this->randomMachineName(16)); + $view['page[create]'] = 1; + $view['page[title]'] = $this->randomMachineName(16); + $view['page[path]'] = $this->randomMachineName(16); + $view['page[feed]'] = 1; + $view['page[feed_properties][path]'] = $this->randomMachineName(16); + $this->drupalPostForm('admin/structure/views/add', $view, t('Save and edit')); + $this->clickLink(t('Feed')); + $this->drupalPostForm(NULL, [], t('Update preview')); + $result = $this->xpath('//div[@id="views-live-preview"]/pre'); + $this->assertTrue(strpos($result[0]->getText(), '<title>' . $view['page[title]'] . '</title>'), 'The Feed RSS preview was rendered.'); + + // Test the non-default UI display options. + // Statistics only, no query. + $settings = \Drupal::configFactory()->getEditable('views.settings'); + $settings->set('ui.show.performance_statistics', TRUE)->save(); + $this->drupalGet('admin/structure/views/view/test_preview/edit'); + $this->drupalPostForm(NULL, $edit = ['view_args' => '100'], t('Update preview')); + $this->assertText(t('Query build time')); + $this->assertText(t('Query execute time')); + $this->assertText(t('View render time')); + $this->assertNoRaw('<strong>Query</strong>'); + + // Statistics and query. + $settings->set('ui.show.sql_query.enabled', TRUE)->save(); + $this->drupalPostForm(NULL, $edit = ['view_args' => '100'], t('Update preview')); + $this->assertText(t('Query build time')); + $this->assertText(t('Query execute time')); + $this->assertText(t('View render time')); + $this->assertRaw('<strong>Query</strong>'); + $query_string = <<<SQL +SELECT views_test_data.name AS views_test_data_name +FROM +{views_test_data} views_test_data +WHERE (views_test_data.id = '100') +SQL; + $this->assertEscaped($query_string); + + // Test that the statistics and query are rendered above the preview. + $this->assertTrue(strpos($this->getSession()->getPage()->getContent(), 'views-query-info') < strpos($this->getSession()->getPage()->getContent(), 'view-test-preview'), 'Statistics shown above the preview.'); + + // Test that statistics and query rendered below the preview. + $settings->set('ui.show.sql_query.where', 'below')->save(); + $this->drupalPostForm(NULL, $edit = ['view_args' => '100'], t('Update preview')); + $this->assertTrue(strpos($this->getSession()->getPage()->getContent(), 'view-test-preview') < strpos($this->getSession()->getPage()->getContent(), 'views-query-info'), 'Statistics shown below the preview.'); + + // Test that the preview title isn't double escaped. + $this->drupalPostForm("admin/structure/views/nojs/display/test_preview/default/title", $edit = ['title' => 'Double & escaped'], t('Apply')); + $this->drupalPostForm(NULL, [], t('Update preview')); + $elements = $this->xpath('//div[@id="views-live-preview"]/div[contains(@class, views-query-info)]//td[text()=:text]', [':text' => 'Double & escaped']); + $this->assertEqual(1, count($elements)); + } + + /** + * Tests the additional information query info area. + */ + public function testPreviewAdditionalInfo() { + \Drupal::service('module_installer')->install(['views_ui_test']); + $this->resetAll(); + + $this->drupalGet('admin/structure/views/view/test_preview/edit'); + $this->assertResponse(200); + + $this->drupalPostForm(NULL, $edit = [], t('Update preview')); + + // Check for implementation of hook_views_preview_info_alter(). + // @see views_ui_test.module + $elements = $this->xpath('//div[@id="views-live-preview"]/div[contains(@class, views-query-info)]//td[text()=:text]', [':text' => 'Test row count']); + $this->assertEqual(count($elements), 1, 'Views Query Preview Info area altered.'); + // Check that additional assets are attached. + $this->assertTrue(strpos($this->getDrupalSettings()['ajaxPageState']['libraries'], 'views_ui_test/views_ui_test.test') !== FALSE, 'Attached library found.'); + $this->assertRaw('css/views_ui_test.test.css', 'Attached CSS asset found.'); + } + + /** + * Tests view validation error messages in the preview. + */ + public function testPreviewError() { + $this->drupalGet('admin/structure/views/view/test_preview_error/edit'); + $this->assertResponse(200); + + $this->drupalPostForm(NULL, $edit = [], t('Update preview')); + + $this->assertText('Unable to preview due to validation errors.', 'Preview error text found.'); + } + +} diff --git a/web/core/modules/views_ui/src/Tests/RowUITest.php b/web/core/modules/views_ui/tests/src/Functional/RowUITest.php similarity index 80% rename from web/core/modules/views_ui/src/Tests/RowUITest.php rename to web/core/modules/views_ui/tests/src/Functional/RowUITest.php index e8aa2c31010fe4b040e32718603e78f72eea8834..8b256f4373eb391dbab9f29e3308e0d8f4d98cdf 100644 --- a/web/core/modules/views_ui/src/Tests/RowUITest.php +++ b/web/core/modules/views_ui/tests/src/Functional/RowUITest.php @@ -1,6 +1,6 @@ <?php -namespace Drupal\views_ui\Tests; +namespace Drupal\Tests\views_ui\Functional; use Drupal\Core\Entity\Entity\EntityViewMode; use Drupal\views\Views; @@ -55,20 +55,7 @@ public function testRowUI() { $this->assertEqual($row['type'], 'test_row', 'Make sure that the test_row got saved as used row plugin.'); $this->assertEqual($row['options']['test_option'], $random_name, 'Make sure that the custom settings field got saved as expected.'); - // Change the row plugin to fields using ajax. - // Note: this is the best approximation we can achieve, because we cannot - // simulate the 'openDialog' command in - // WebTestBase::drupalProcessAjaxResponse(), hence we have to make do. - $row_plugin_url_ajax = str_replace('/nojs/', '/ajax/', $row_plugin_url); - $ajax_settings = [ - 'accepts' => 'application/vnd.drupal-ajax', - 'submit' => [ - '_triggering_element_name' => 'op', - '_triggering_element_value' => 'Apply', - ], - 'url' => $row_plugin_url_ajax, - ]; - $this->drupalPostAjaxForm($row_plugin_url, ['row[type]' => 'fields'], NULL, $row_plugin_url_ajax, [], [], NULL, $ajax_settings); + $this->drupalPostForm($row_plugin_url, ['row[type]' => 'fields'], 'Apply'); $this->drupalGet($row_plugin_url); $this->assertResponse(200); $this->assertFieldByName('row[type]', 'fields', 'Make sure that the fields got saved as used row plugin.'); diff --git a/web/core/modules/views_ui/tests/src/Functional/TranslatedViewTest.php b/web/core/modules/views_ui/tests/src/Functional/TranslatedViewTest.php index 7238ffad64f9a18ec663cf36dbea7e28bee3485a..a8d3c8b96f514084c8890c09d4067f38e34958d3 100644 --- a/web/core/modules/views_ui/tests/src/Functional/TranslatedViewTest.php +++ b/web/core/modules/views_ui/tests/src/Functional/TranslatedViewTest.php @@ -63,7 +63,7 @@ public function testTranslatedStrings() { $translation_url = 'admin/structure/views/view/files/translate/fr/add'; $edit_url = 'admin/structure/views/view/files'; - // Check origial string. + // Check the original string. $this->drupalGet($edit_url); $this->assertTitle('Files (File) | Drupal'); diff --git a/web/core/modules/views_ui/tests/src/FunctionalJavascript/DisplayTest.php b/web/core/modules/views_ui/tests/src/FunctionalJavascript/DisplayTest.php index 7dcaccdd241ada9fec90b7c285af28e68edcf8f6..df3134f7013fc3049df659c557323491d3de37e0 100644 --- a/web/core/modules/views_ui/tests/src/FunctionalJavascript/DisplayTest.php +++ b/web/core/modules/views_ui/tests/src/FunctionalJavascript/DisplayTest.php @@ -63,7 +63,7 @@ public function testAddDisplay() { // Wait for the animation to complete. $this->assertSession()->assertWaitOnAjaxRequest(); - // Add the diplay. + // Add the display. $page->find('css', '#edit-displays-top-add-display-block')->click(); $element = $page->findById('views-display-menu-tabs')->findLink('Block'); diff --git a/web/core/modules/views_ui/tests/src/FunctionalJavascript/PreviewTest.php b/web/core/modules/views_ui/tests/src/FunctionalJavascript/PreviewTest.php new file mode 100644 index 0000000000000000000000000000000000000000..489a3748df44a59498cf0630ea6cfea359367530 --- /dev/null +++ b/web/core/modules/views_ui/tests/src/FunctionalJavascript/PreviewTest.php @@ -0,0 +1,304 @@ +<?php + +namespace Drupal\Tests\views_ui\FunctionalJavascript; + +use Behat\Mink\Element\NodeElement; +use Drupal\Core\Database\Database; +use Drupal\FunctionalJavascriptTests\WebDriverTestBase; +use Drupal\views\Tests\ViewTestData; + +/** + * Tests the UI preview functionality. + * + * @group views_ui + */ +class PreviewTest extends WebDriverTestBase { + + /** + * Views used by this test. + * + * @var array + */ + public static $testViews = ['test_preview', 'test_pager_full_ajax', 'test_mini_pager_ajax', 'test_click_sort_ajax']; + + /** + * {@inheritdoc} + */ + public static $modules = [ + 'node', + 'views', + 'views_ui', + 'views_test_config', + ]; + + /** + * {@inheritdoc} + */ + public function setUp() { + parent::setUp(); + + ViewTestData::createTestViews(self::class, ['views_test_config']); + + $this->enableViewsTestModule(); + + $admin_user = $this->drupalCreateUser([ + 'administer site configuration', + 'administer views', + 'administer nodes', + 'access content overview', + ]); + + // Disable automatic live preview to make the sequence of calls clearer. + \Drupal::configFactory()->getEditable('views.settings')->set('ui.always_live_preview', FALSE)->save(); + $this->drupalLogin($admin_user); + } + + /** + * Sets up the views_test_data.module. + * + * Because the schema of views_test_data.module is dependent on the test + * using it, it cannot be enabled normally. + */ + protected function enableViewsTestModule() { + // Define the schema and views data variable before enabling the test module. + \Drupal::state()->set('views_test_data_schema', $this->schemaDefinition()); + \Drupal::state()->set('views_test_data_views_data', $this->viewsData()); + + \Drupal::service('module_installer')->install(['views_test_data']); + $this->resetAll(); + $this->rebuildContainer(); + $this->container->get('module_handler')->reload(); + + // Load the test dataset. + $data_set = $this->dataSet(); + $query = Database::getConnection()->insert('views_test_data') + ->fields(array_keys($data_set[0])); + foreach ($data_set as $record) { + $query->values($record); + } + $query->execute(); + } + + /** + * Returns the schema definition. + * + * @internal + */ + protected function schemaDefinition() { + return ViewTestData::schemaDefinition(); + } + + /** + * Returns the views data definition. + */ + protected function viewsData() { + return ViewTestData::viewsData(); + } + + /** + * Returns a very simple test dataset. + */ + protected function dataSet() { + return ViewTestData::dataSet(); + } + + /** + * Tests the taxonomy term preview AJAX. + * + * This tests a specific regression in the taxonomy term view preview. + * + * @see https://www.drupal.org/node/2452659 + */ + public function testTaxonomyAJAX() { + \Drupal::service('module_installer')->install(['taxonomy']); + $this->getPreviewAJAX('taxonomy_term', 'page_1', 0); + } + + /** + * Tests pagers in the preview form. + */ + public function testPreviewWithPagersUI() { + // Create 11 nodes and make sure that everyone is returned. + $this->drupalCreateContentType(['type' => 'page']); + for ($i = 0; $i < 11; $i++) { + $this->drupalCreateNode(); + } + + // Test Full Pager. + $this->getPreviewAJAX('test_pager_full_ajax', 'default', 5); + + // Test that the pager is present and rendered. + $elements = $this->xpath('//ul[contains(@class, :class)]/li', [':class' => 'pager__items']); + $this->assertTrue(!empty($elements), 'Full pager found.'); + + // Verify elements and links to pages. + // We expect to find 5 elements: current page == 1, links to pages 2 and + // and 3, links to 'next >' and 'last >>' pages. + $this->assertClass($elements[0], 'is-active', 'Element for current page has .is-active class.'); + $this->assertTrue($elements[0]->find('css', 'a'), 'Element for current page has link.'); + + $this->assertClass($elements[1], 'pager__item', 'Element for page 2 has .pager__item class.'); + $this->assertTrue($elements[1]->find('css', 'a'), 'Link to page 2 found.'); + + $this->assertClass($elements[2], 'pager__item', 'Element for page 3 has .pager__item class.'); + $this->assertTrue($elements[2]->find('css', 'a'), 'Link to page 3 found.'); + + $this->assertClass($elements[3], 'pager__item--next', 'Element for next page has .pager__item--next class.'); + $this->assertTrue($elements[3]->find('css', 'a'), 'Link to next page found.'); + + $this->assertClass($elements[4], 'pager__item--last', 'Element for last page has .pager__item--last class.'); + $this->assertTrue($elements[4]->find('css', 'a'), 'Link to last page found.'); + + // Navigate to next page. + $elements = $this->xpath('//li[contains(@class, :class)]/a', [':class' => 'pager__item--next']); + $this->clickPreviewLinkAJAX($elements[0], 5); + + // Test that the pager is present and rendered. + $elements = $this->xpath('//ul[contains(@class, :class)]/li', [':class' => 'pager__items']); + $this->assertTrue(!empty($elements), 'Full pager found.'); + + // Verify elements and links to pages. + // We expect to find 7 elements: links to '<< first' and '< previous' + // pages, link to page 1, current page == 2, link to page 3 and links + // to 'next >' and 'last >>' pages. + $this->assertClass($elements[0], 'pager__item--first', 'Element for first page has .pager__item--first class.'); + $this->assertTrue($elements[0]->find('css', 'a'), 'Link to first page found.'); + + $this->assertClass($elements[1], 'pager__item--previous', 'Element for previous page has .pager__item--previous class.'); + $this->assertTrue($elements[1]->find('css', 'a'), 'Link to previous page found.'); + + $this->assertClass($elements[2], 'pager__item', 'Element for page 1 has .pager__item class.'); + $this->assertTrue($elements[2]->find('css', 'a'), 'Link to page 1 found.'); + + $this->assertClass($elements[3], 'is-active', 'Element for current page has .is-active class.'); + $this->assertTrue($elements[3]->find('css', 'a'), 'Element for current page has link.'); + + $this->assertClass($elements[4], 'pager__item', 'Element for page 3 has .pager__item class.'); + $this->assertTrue($elements[4]->find('css', 'a'), 'Link to page 3 found.'); + + $this->assertClass($elements[5], 'pager__item--next', 'Element for next page has .pager__item--next class.'); + $this->assertTrue($elements[5]->find('css', 'a'), 'Link to next page found.'); + + $this->assertClass($elements[6], 'pager__item--last', 'Element for last page has .pager__item--last class.'); + $this->assertTrue($elements[6]->find('css', 'a'), 'Link to last page found.'); + + // Test Mini Pager. + $this->getPreviewAJAX('test_mini_pager_ajax', 'default', 3); + + // Test that the pager is present and rendered. + $elements = $this->xpath('//ul[contains(@class, :class)]/li', [':class' => 'pager__items']); + $this->assertTrue(!empty($elements), 'Mini pager found.'); + + // Verify elements and links to pages. + // We expect to find current pages element with no link, next page element + // with a link, and not to find previous page element. + $this->assertClass($elements[0], 'is-active', 'Element for current page has .is-active class.'); + + $this->assertClass($elements[1], 'pager__item--next', 'Element for next page has .pager__item--next class.'); + $this->assertTrue($elements[1]->find('css', 'a'), 'Link to next page found.'); + + // Navigate to next page. + $elements = $this->xpath('//li[contains(@class, :class)]/a', [':class' => 'pager__item--next']); + $this->clickPreviewLinkAJAX($elements[0], 3); + + // Test that the pager is present and rendered. + $elements = $this->xpath('//ul[contains(@class, :class)]/li', [':class' => 'pager__items']); + $this->assertTrue(!empty($elements), 'Mini pager found.'); + + // Verify elements and links to pages. + // We expect to find 3 elements: previous page with a link, current + // page with no link, and next page with a link. + $this->assertClass($elements[0], 'pager__item--previous', 'Element for previous page has .pager__item--previous class.'); + $this->assertTrue($elements[0]->find('css', 'a'), 'Link to previous page found.'); + + $this->assertClass($elements[1], 'is-active', 'Element for current page has .is-active class.'); + $this->assertEmpty($elements[1]->find('css', 'a'), 'Element for current page has no link.'); + + $this->assertClass($elements[2], 'pager__item--next', 'Element for next page has .pager__item--next class.'); + $this->assertTrue($elements[2]->find('css', 'a'), 'Link to next page found.'); + } + + /** + * Tests the link to sort in the preview form. + */ + public function testPreviewSortLink() { + // Get the preview. + $this->getPreviewAJAX('test_click_sort_ajax', 'page_1', 0); + + // Test that the header label is present. + $elements = $this->xpath('//th[contains(@class, :class)]/a', [':class' => 'views-field views-field-name']); + $this->assertTrue(!empty($elements), 'The header label is present.'); + + // Verify link. + $this->assertLinkByHref('preview/page_1?_wrapper_format=drupal_ajax&order=name&sort=desc', 0, 'The output URL is as expected.'); + + // Click link to sort. + $elements[0]->click(); + $sort_link = $this->assertSession()->waitForElement('xpath', '//th[contains(@class, \'views-field views-field-name is-active\')]/a'); + + $this->assertNotEmpty($sort_link); + + // Verify link. + $this->assertLinkByHref('preview/page_1?_wrapper_format=drupal_ajax&order=name&sort=asc', 0, 'The output URL is as expected.'); + } + + /** + * Get the preview form and force an AJAX preview update. + * + * @param string $view_name + * The view to test. + * @param string $panel_id + * The view panel to test. + * @param int $row_count + * The expected number of rows in the preview. + */ + protected function getPreviewAJAX($view_name, $panel_id, $row_count) { + $this->drupalGet('admin/structure/views/view/' . $view_name . '/edit/' . $panel_id); + $this->getSession()->getPage()->pressButton('Update preview'); + $this->assertSession()->assertWaitOnAjaxRequest(); + $this->assertPreviewAJAX($row_count); + } + + /** + * Click on a preview link. + * + * @param \Behat\Mink\Element\NodeElement $element + * The element to click. + * @param int $row_count + * The expected number of rows in the preview. + */ + protected function clickPreviewLinkAJAX(NodeElement $element, $row_count) { + $element->click(); + $this->assertSession()->assertWaitOnAjaxRequest(); + $this->assertPreviewAJAX($row_count); + } + + /** + * Assert that the preview contains expected data. + * + * @param int $row_count + * The expected number of rows in the preview. + */ + protected function assertPreviewAJAX($row_count) { + $elements = $this->getSession()->getPage()->findAll('css', '.view-content .views-row'); + $this->assertCount($row_count, $elements, 'Expected items found on page.'); + } + + /** + * Asserts that an element has a given class. + * + * @param \Behat\Mink\Element\NodeElement $element + * The element to test. + * @param string $class + * The class to assert. + * @param string $message + * (optional) A verbose message to output. + */ + protected function assertClass(NodeElement $element, $class, $message = NULL) { + if (!isset($message)) { + $message = "Class .$class found."; + } + $this->assertTrue(strpos($element->getAttribute('class'), $class) !== FALSE, $message); + } + +} diff --git a/web/core/modules/workspaces/css/workspaces.toolbar.css b/web/core/modules/workspaces/css/workspaces.toolbar.css index 71fd50f98afc57449b8f9107011a1c61b8ab681e..37982fc72845be8522efeed4278127a22c203919 100644 --- a/web/core/modules/workspaces/css/workspaces.toolbar.css +++ b/web/core/modules/workspaces/css/workspaces.toolbar.css @@ -184,17 +184,18 @@ } @media all and (max-width: 766px) { - .toolbar .toolbar-icon-workspace { + .toolbar .toolbar-bar .workspaces-toolbar-tab .toolbar-icon-workspace { padding-left: 2.75em; padding-right: 1.3333em; text-indent: 0; - width: 8em; + width: auto; + max-width: 8em; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; } - .toolbar .toolbar-icon-workspace:before { + .toolbar .toolbar-bar .workspaces-toolbar-tab .toolbar-icon-workspace:before { background-size: 100% auto; left: 0.6667em; width: 20px; diff --git a/web/core/modules/workspaces/src/EntityOperations.php b/web/core/modules/workspaces/src/EntityOperations.php index 857934f07d3422f17ce825ca2ff48a90f6212cbc..6e033418017e9b08b4b9bc459b32db8c0fb393bc 100644 --- a/web/core/modules/workspaces/src/EntityOperations.php +++ b/web/core/modules/workspaces/src/EntityOperations.php @@ -319,7 +319,7 @@ public function entityFormAlter(array &$form, FormStateInterface $form_state, $f // be a pending one. $active_workspace = $this->workspaceManager->getActiveWorkspace(); if (!$active_workspace->isDefaultWorkspace()) { - $form['#entity_builders'][] = [$this, 'entityFormEntityBuild']; + $form['#entity_builders'][] = [get_called_class(), 'entityFormEntityBuild']; } /** @var \Drupal\workspaces\WorkspaceAssociationStorageInterface $workspace_association_storage */ @@ -340,7 +340,7 @@ public function entityFormAlter(array &$form, FormStateInterface $form_state, $f /** * Entity builder that marks all supported entities as pending revisions. */ - public function entityFormEntityBuild($entity_type_id, RevisionableInterface $entity, &$form, FormStateInterface &$form_state) { + public static function entityFormEntityBuild($entity_type_id, RevisionableInterface $entity, &$form, FormStateInterface &$form_state) { // Set the non-default revision flag so that validation constraints are also // aware that a pending revision is about to be created. $entity->isDefaultRevision(FALSE); diff --git a/web/core/modules/workspaces/src/EntityTypeInfo.php b/web/core/modules/workspaces/src/EntityTypeInfo.php index 3b91f84e519ef75a99c4462b7cfca51a7dd16a48..5495c7fa4e7c09c31db6484bc881ad7126279341 100644 --- a/web/core/modules/workspaces/src/EntityTypeInfo.php +++ b/web/core/modules/workspaces/src/EntityTypeInfo.php @@ -70,4 +70,18 @@ public function entityTypeBuild(array &$entity_types) { } } + /** + * Alters field plugin definitions. + * + * @param array[] $definitions + * An array of field plugin definitions. + * + * @see hook_field_info_alter() + */ + public function fieldInfoAlter(&$definitions) { + if (isset($definitions['entity_reference'])) { + $definitions['entity_reference']['constraints']['EntityReferenceSupportedNewEntities'] = []; + } + } + } diff --git a/web/core/modules/workspaces/src/FormOperations.php b/web/core/modules/workspaces/src/FormOperations.php index eb1893d7f6d15e69e5cef4aedbeb7d557b610d43..6795f20a9f2124a6999dd301534b8c17c4f4b40d 100644 --- a/web/core/modules/workspaces/src/FormOperations.php +++ b/web/core/modules/workspaces/src/FormOperations.php @@ -5,7 +5,7 @@ use Drupal\Core\DependencyInjection\ContainerInjectionInterface; use Drupal\Core\Form\FormStateInterface; use Drupal\Core\Render\Element; -use Drupal\Core\StringTranslation\StringTranslationTrait; +use Drupal\Core\StringTranslation\TranslatableMarkup; use Drupal\views\Form\ViewsExposedForm; use Drupal\workspaces\Form\WorkspaceFormInterface; use Symfony\Component\DependencyInjection\ContainerInterface; @@ -17,8 +17,6 @@ */ class FormOperations implements ContainerInjectionInterface { - use StringTranslationTrait; - /** * The workspace manager service. * @@ -104,16 +102,16 @@ protected function addWorkspaceValidation(array &$element) { } if (isset($element['#validate'])) { - $element['#validate'][] = [$this, 'validateDefaultWorkspace']; + $element['#validate'][] = [get_called_class(), 'validateDefaultWorkspace']; } } /** * Validation handler which sets a validation error for all unsupported forms. */ - public function validateDefaultWorkspace(array &$form, FormStateInterface $form_state) { + public static function validateDefaultWorkspace(array &$form, FormStateInterface $form_state) { if ($form_state->get('workspace_safe') !== TRUE) { - $form_state->setError($form, $this->t('This form can only be submitted in the default workspace.')); + $form_state->setError($form, new TranslatableMarkup('This form can only be submitted in the default workspace.')); } } diff --git a/web/core/modules/workspaces/src/Plugin/Validation/Constraint/EntityReferenceSupportedNewEntitiesConstraint.php b/web/core/modules/workspaces/src/Plugin/Validation/Constraint/EntityReferenceSupportedNewEntitiesConstraint.php new file mode 100644 index 0000000000000000000000000000000000000000..894e34374c8166e8f6614171e784245464e4eb8c --- /dev/null +++ b/web/core/modules/workspaces/src/Plugin/Validation/Constraint/EntityReferenceSupportedNewEntitiesConstraint.php @@ -0,0 +1,24 @@ +<?php + +namespace Drupal\workspaces\Plugin\Validation\Constraint; + +use Symfony\Component\Validator\Constraint; + +/** + * The entity reference supported new entities constraint. + * + * @Constraint( + * id = "EntityReferenceSupportedNewEntities", + * label = @Translation("Entity Reference Supported New Entities", context = "Validation"), + * ) + */ +class EntityReferenceSupportedNewEntitiesConstraint extends Constraint { + + /** + * The default violation message. + * + * @var string + */ + public $message = '%collection_label can only be created in the default workspace.'; + +} diff --git a/web/core/modules/workspaces/src/Plugin/Validation/Constraint/EntityReferenceSupportedNewEntitiesConstraintValidator.php b/web/core/modules/workspaces/src/Plugin/Validation/Constraint/EntityReferenceSupportedNewEntitiesConstraintValidator.php new file mode 100644 index 0000000000000000000000000000000000000000..11083df0f631166d2b4795da9e1f87622a076f19 --- /dev/null +++ b/web/core/modules/workspaces/src/Plugin/Validation/Constraint/EntityReferenceSupportedNewEntitiesConstraintValidator.php @@ -0,0 +1,65 @@ +<?php + +namespace Drupal\workspaces\Plugin\Validation\Constraint; + +use Drupal\Core\DependencyInjection\ContainerInjectionInterface; +use Drupal\Core\Entity\EntityTypeManagerInterface; +use Drupal\workspaces\WorkspaceManagerInterface; +use Symfony\Component\DependencyInjection\ContainerInterface; +use Symfony\Component\Validator\Constraint; +use Symfony\Component\Validator\ConstraintValidator; + +/** + * Checks if new entities created for entity reference fields are supported. + */ +class EntityReferenceSupportedNewEntitiesConstraintValidator extends ConstraintValidator implements ContainerInjectionInterface { + + /** + * The workspace manager. + * + * @var \Drupal\workspaces\WorkspaceManagerInterface + */ + protected $workspaceManager; + + /** + * The entity type manager. + * + * @var \Drupal\Core\Entity\EntityTypeManagerInterface + */ + protected $entityTypeManager; + + /** + * Creates a new EntityReferenceSupportedNewEntitiesConstraintValidator instance. + */ + public function __construct(WorkspaceManagerInterface $workspaceManager, EntityTypeManagerInterface $entityTypeManager) { + $this->workspaceManager = $workspaceManager; + $this->entityTypeManager = $entityTypeManager; + } + + /** + * {@inheritdoc} + */ + public static function create(ContainerInterface $container) { + return new static( + $container->get('workspaces.manager'), + $container->get('entity_type.manager') + ); + } + + /** + * {@inheritdoc} + */ + public function validate($value, Constraint $constraint) { + if ($this->workspaceManager->getActiveWorkspace()->isDefaultWorkspace()) { + return; + } + + $target_entity_type_id = $value->getFieldDefinition()->getFieldStorageDefinition()->getSetting('target_type'); + $target_entity_type = $this->entityTypeManager->getDefinition($target_entity_type_id); + + if ($value->hasNewEntity() && !$this->workspaceManager->isEntityTypeSupported($target_entity_type)) { + $this->context->addViolation($constraint->message, ['%collection_label' => $target_entity_type->getCollectionLabel()]); + } + } + +} diff --git a/web/core/modules/workspaces/src/WorkspaceManager.php b/web/core/modules/workspaces/src/WorkspaceManager.php index faa5f8fface75f52454aedbfe06f0c5bc1aa7ebf..837edefe8493e821da464a4dc392be3a26303bb4 100644 --- a/web/core/modules/workspaces/src/WorkspaceManager.php +++ b/web/core/modules/workspaces/src/WorkspaceManager.php @@ -2,6 +2,7 @@ namespace Drupal\workspaces; +use Drupal\Core\Cache\MemoryCache\MemoryCacheInterface; use Drupal\Core\DependencyInjection\ClassResolverInterface; use Drupal\Core\Entity\EntityPublishedInterface; use Drupal\Core\Entity\EntityTypeInterface; @@ -47,6 +48,13 @@ class WorkspaceManager implements WorkspaceManagerInterface { */ protected $entityTypeManager; + /** + * The entity memory cache service. + * + * @var \Drupal\Core\Cache\MemoryCache\MemoryCacheInterface + */ + protected $entityMemoryCache; + /** * The current user. * @@ -96,6 +104,8 @@ class WorkspaceManager implements WorkspaceManagerInterface { * The request stack. * @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager * The entity type manager. + * @param \Drupal\Core\Cache\MemoryCache\MemoryCacheInterface $entity_memory_cache + * The entity memory cache service. * @param \Drupal\Core\Session\AccountProxyInterface $current_user * The current user. * @param \Drupal\Core\State\StateInterface $state @@ -107,9 +117,10 @@ class WorkspaceManager implements WorkspaceManagerInterface { * @param array $negotiator_ids * The workspace negotiator service IDs. */ - public function __construct(RequestStack $request_stack, EntityTypeManagerInterface $entity_type_manager, AccountProxyInterface $current_user, StateInterface $state, LoggerInterface $logger, ClassResolverInterface $class_resolver, array $negotiator_ids) { + public function __construct(RequestStack $request_stack, EntityTypeManagerInterface $entity_type_manager, MemoryCacheInterface $entity_memory_cache, AccountProxyInterface $current_user, StateInterface $state, LoggerInterface $logger, ClassResolverInterface $class_resolver, array $negotiator_ids) { $this->requestStack = $request_stack; $this->entityTypeManager = $entity_type_manager; + $this->entityMemoryCache = $entity_memory_cache; $this->currentUser = $current_user; $this->state = $state; $this->logger = $logger; @@ -167,6 +178,31 @@ public function getActiveWorkspace() { * {@inheritdoc} */ public function setActiveWorkspace(WorkspaceInterface $workspace) { + $this->doSwitchWorkspace($workspace); + + // Set the workspace on the proper negotiator. + $request = $this->requestStack->getCurrentRequest(); + foreach ($this->negotiatorIds as $negotiator_id) { + $negotiator = $this->classResolver->getInstanceFromDefinition($negotiator_id); + if ($negotiator->applies($request)) { + $negotiator->setActiveWorkspace($workspace); + break; + } + } + + return $this; + } + + /** + * Switches the current workspace. + * + * @param \Drupal\workspaces\WorkspaceInterface $workspace + * The workspace to set as active. + * + * @throws \Drupal\workspaces\WorkspaceAccessException + * Thrown when the current user doesn't have access to view the workspace. + */ + protected function doSwitchWorkspace(WorkspaceInterface $workspace) { // If the current user doesn't have access to view the workspace, they // shouldn't be allowed to switch to it. if (!$workspace->access('view') && !$workspace->isDefaultWorkspace()) { @@ -179,22 +215,30 @@ public function setActiveWorkspace(WorkspaceInterface $workspace) { $this->activeWorkspace = $workspace; - // Set the workspace on the proper negotiator. - $request = $this->requestStack->getCurrentRequest(); - foreach ($this->negotiatorIds as $negotiator_id) { - $negotiator = $this->classResolver->getInstanceFromDefinition($negotiator_id); - if ($negotiator->applies($request)) { - $negotiator->setActiveWorkspace($workspace); - break; - } - } + // Clear the static entity cache for the supported entity types. + $cache_tags_to_invalidate = array_map(function ($entity_type_id) { + return 'entity.memory_cache:' . $entity_type_id; + }, array_keys($this->getSupportedEntityTypes())); + $this->entityMemoryCache->invalidateTags($cache_tags_to_invalidate); + } - $supported_entity_types = $this->getSupportedEntityTypes(); - foreach ($supported_entity_types as $supported_entity_type) { - $this->entityTypeManager->getStorage($supported_entity_type->id())->resetCache(); + /** + * {@inheritdoc} + */ + public function executeInWorkspace($workspace_id, callable $function) { + /** @var \Drupal\workspaces\WorkspaceInterface $workspace */ + $workspace = $this->entityTypeManager->getStorage('workspace')->load($workspace_id); + + if (!$workspace) { + throw new \InvalidArgumentException('The ' . $workspace_id . ' workspace does not exist.'); } - return $this; + $previous_active_workspace = $this->getActiveWorkspace(); + $this->doSwitchWorkspace($workspace); + $result = $function(); + $this->doSwitchWorkspace($previous_active_workspace); + + return $result; } /** diff --git a/web/core/modules/workspaces/src/WorkspaceManagerInterface.php b/web/core/modules/workspaces/src/WorkspaceManagerInterface.php index 9ce720b3f148e6536a39ff1fe74c38307015114c..006a2bd86d8a1486539c07452108fb0030204f5d 100644 --- a/web/core/modules/workspaces/src/WorkspaceManagerInterface.php +++ b/web/core/modules/workspaces/src/WorkspaceManagerInterface.php @@ -49,6 +49,19 @@ public function getActiveWorkspace(); */ public function setActiveWorkspace(WorkspaceInterface $workspace); + /** + * Executes the given callback function in the context of a workspace. + * + * @param string $workspace_id + * The ID of a workspace. + * @param callable $function + * The callback to be executed. + * + * @return mixed + * The callable's return value. + */ + public function executeInWorkspace($workspace_id, callable $function); + /** * Determines whether runtime entity operations should be altered. * diff --git a/web/core/modules/workspaces/tests/src/Functional/WorkspaceTest.php b/web/core/modules/workspaces/tests/src/Functional/WorkspaceTest.php index 5c7bea6e6a60f4655d262f5859b2c470d909b634..00276ce0b63725b983e850c8cbb8d7255a82310e 100644 --- a/web/core/modules/workspaces/tests/src/Functional/WorkspaceTest.php +++ b/web/core/modules/workspaces/tests/src/Functional/WorkspaceTest.php @@ -16,7 +16,7 @@ class WorkspaceTest extends BrowserTestBase { /** * {@inheritdoc} */ - public static $modules = ['workspaces']; + public static $modules = ['workspaces', 'toolbar']; /** * A test user. @@ -43,6 +43,8 @@ public function setUp() { 'create workspace', 'edit own workspace', 'edit any workspace', + 'view own workspace', + 'access toolbar', ]; $this->editor1 = $this->drupalCreateUser($permissions); @@ -69,6 +71,36 @@ public function testSpecialCharacters() { $page->hasContent("This value is not valid"); } + /** + * Test that the toolbar correctly shows the active workspace. + */ + public function testWorkspaceToolbar() { + $this->drupalLogin($this->editor1); + + $this->drupalPostForm('/admin/config/workflow/workspaces/add', [ + 'id' => 'test_workspace', + 'label' => 'Test workspace', + ], 'Save'); + + // Activate the test workspace. + $this->drupalPostForm('/admin/config/workflow/workspaces/manage/test_workspace/activate', [], 'Confirm'); + + $this->drupalGet('<front>'); + $page = $this->getSession()->getPage(); + // Toolbar should show the correct label. + $this->assertTrue($page->hasLink('Test workspace')); + + // Change the workspace label. + $this->drupalPostForm('/admin/config/workflow/workspaces/manage/test_workspace/edit', [ + 'label' => 'New name', + ], 'Save'); + + $this->drupalGet('<front>'); + $page = $this->getSession()->getPage(); + // Toolbar should show the new label. + $this->assertTrue($page->hasLink('New name')); + } + /** * Test changing the owner of a workspace. */ diff --git a/web/core/modules/workspaces/tests/src/Kernel/EntityReferenceSupportedNewEntitiesConstraintValidatorTest.php b/web/core/modules/workspaces/tests/src/Kernel/EntityReferenceSupportedNewEntitiesConstraintValidatorTest.php new file mode 100644 index 0000000000000000000000000000000000000000..5cef79df930d94f29adba31100f8fd09b52b004b --- /dev/null +++ b/web/core/modules/workspaces/tests/src/Kernel/EntityReferenceSupportedNewEntitiesConstraintValidatorTest.php @@ -0,0 +1,81 @@ +<?php + +namespace Drupal\Tests\workspaces\Kernel; + +use Drupal\Core\Field\BaseFieldDefinition; +use Drupal\entity_test\Entity\EntityTest; +use Drupal\entity_test\Entity\EntityTestMulRevPub; +use Drupal\KernelTests\KernelTestBase; +use Drupal\Tests\user\Traits\UserCreationTrait; + +/** + * @coversDefaultClass \Drupal\workspaces\Plugin\Validation\Constraint\EntityReferenceSupportedNewEntitiesConstraintValidator + * @group workspaces + */ +class EntityReferenceSupportedNewEntitiesConstraintValidatorTest extends KernelTestBase { + + use UserCreationTrait; + use WorkspaceTestTrait; + + /** + * {@inheritdoc} + */ + protected static $modules = [ + 'system', + 'user', + 'workspaces', + 'entity_test', + ]; + + /** + * {@inheritdoc} + */ + protected function setUp() { + parent::setUp(); + + $this->installEntitySchema('user'); + $this->installSchema('system', ['sequences']); + $this->createUser(); + + $fields['supported_reference'] = BaseFieldDefinition::create('entity_reference')->setSetting('target_type', 'entity_test_mulrevpub'); + $fields['unsupported_reference'] = BaseFieldDefinition::create('entity_reference')->setSetting('target_type', 'entity_test'); + $this->container->get('state')->set('entity_test_mulrevpub.additional_base_field_definitions', $fields); + + $this->installEntitySchema('entity_test_mulrevpub'); + $this->initializeWorkspacesModule(); + } + + /** + * @covers ::validate + */ + public function testNewEntitiesAllowedInDefaultWorkspace() { + $entity = EntityTestMulRevPub::create([ + 'unsupported_reference' => [ + 'entity' => EntityTest::create([]), + ], + 'supported_reference' => [ + 'entity' => EntityTest::create([]), + ], + ]); + $this->assertCount(0, $entity->validate()); + } + + /** + * @covers ::validate + */ + public function testNewEntitiesForbiddenInNonDefaultWorkspace() { + $this->switchToWorkspace('stage'); + $entity = EntityTestMulRevPub::create([ + 'unsupported_reference' => [ + 'entity' => EntityTest::create([]), + ], + 'supported_reference' => [ + 'entity' => EntityTestMulRevPub::create([]), + ], + ]); + $violations = $entity->validate(); + $this->assertCount(1, $violations); + $this->assertEquals('<em class="placeholder">Test entity entities</em> can only be created in the default workspace.', $violations[0]->getMessage()); + } + +} diff --git a/web/core/modules/workspaces/tests/src/Kernel/WorkspaceIntegrationTest.php b/web/core/modules/workspaces/tests/src/Kernel/WorkspaceIntegrationTest.php index 785440295e4727ea3b1966fa6bf785169721e101..39c365b9468f42aa1ce0a73af51336a68352bee5 100644 --- a/web/core/modules/workspaces/tests/src/Kernel/WorkspaceIntegrationTest.php +++ b/web/core/modules/workspaces/tests/src/Kernel/WorkspaceIntegrationTest.php @@ -3,16 +3,17 @@ namespace Drupal\Tests\workspaces\Kernel; use Drupal\Core\Entity\EntityStorageException; +use Drupal\Core\Form\FormState; use Drupal\entity_test\Entity\EntityTestMulRev; use Drupal\entity_test\Entity\EntityTestMulRevPub; -use Drupal\field\Tests\EntityReference\EntityReferenceTestTrait; use Drupal\KernelTests\KernelTestBase; +use Drupal\system\Form\SiteInformationForm; +use Drupal\Tests\field\Traits\EntityReferenceTestTrait; use Drupal\Tests\node\Traits\ContentTypeCreationTrait; use Drupal\Tests\node\Traits\NodeCreationTrait; use Drupal\Tests\user\Traits\UserCreationTrait; use Drupal\views\Tests\ViewResultAssertionTrait; use Drupal\views\Views; -use Drupal\workspaces\Entity\Workspace; /** * Tests a complete deployment scenario across different workspaces. @@ -26,6 +27,7 @@ class WorkspaceIntegrationTest extends KernelTestBase { use NodeCreationTrait; use UserCreationTrait; use ViewResultAssertionTrait; + use WorkspaceTestTrait; /** * The entity type manager. @@ -34,13 +36,6 @@ class WorkspaceIntegrationTest extends KernelTestBase { */ protected $entityTypeManager; - /** - * An array of test workspaces, keyed by workspace ID. - * - * @var \Drupal\workspaces\WorkspaceInterface[] - */ - protected $workspaces = []; - /** * Creation timestamp that should be incremented for each new entity. * @@ -91,34 +86,6 @@ protected function setUp() { $this->createNode(['title' => 'live - 2 - r2 - unpublished', 'created' => $this->createdTimestamp++, 'status' => FALSE]); } - /** - * Enables the Workspaces module and creates two workspaces. - */ - protected function initializeWorkspacesModule() { - // Enable the Workspaces module here instead of the static::$modules array - // so we can test it with default content. - $this->enableModules(['workspaces']); - $this->container = \Drupal::getContainer(); - $this->entityTypeManager = \Drupal::entityTypeManager(); - - $this->installEntitySchema('workspace'); - $this->installEntitySchema('workspace_association'); - - // Create two workspaces by default, 'live' and 'stage'. - $this->workspaces['live'] = Workspace::create(['id' => 'live']); - $this->workspaces['live']->save(); - $this->workspaces['stage'] = Workspace::create(['id' => 'stage']); - $this->workspaces['stage']->save(); - - $permissions = [ - 'administer nodes', - 'create workspace', - 'edit any workspace', - 'view any workspace', - ]; - $this->setCurrentUser($this->createUser($permissions)); - } - /** * Tests various scenarios for creating and deploying content in workspaces. */ @@ -490,6 +457,57 @@ public function testDisallowedEntityCRUDInNonDefaultWorkspace() { $entity_test->delete(); } + /** + * @covers \Drupal\workspaces\WorkspaceManager::executeInWorkspace + */ + public function testExecuteInWorkspaceContext() { + $this->initializeWorkspacesModule(); + + // Create an entity in the default workspace. + $this->switchToWorkspace('live'); + $node = $this->createNode([ + 'title' => 'live node 1', + ]); + $node->save(); + + // Switch to the 'stage' workspace and change some values for the referenced + // entities. + $this->switchToWorkspace('stage'); + $node->title->value = 'stage node 1'; + $node->save(); + + // Switch back to the default workspace and run the baseline assertions. + $this->switchToWorkspace('live'); + $storage = $this->entityTypeManager->getStorage('node'); + + $this->assertEquals('live', $this->workspaceManager->getActiveWorkspace()->id()); + + $live_node = $storage->loadUnchanged($node->id()); + $this->assertEquals('live node 1', $live_node->title->value); + + $result = $storage->getQuery() + ->condition('title', 'live node 1') + ->execute(); + $this->assertEquals([$live_node->getRevisionId() => $node->id()], $result); + + // Try the same assertions in the context of the 'stage' workspace. + $this->workspaceManager->executeInWorkspace('stage', function () use ($node, $storage) { + $this->assertEquals('stage', $this->workspaceManager->getActiveWorkspace()->id()); + + $stage_node = $storage->loadUnchanged($node->id()); + $this->assertEquals('stage node 1', $stage_node->title->value); + + $result = $storage->getQuery() + ->condition('title', 'stage node 1') + ->execute(); + $this->assertEquals([$stage_node->getRevisionId() => $stage_node->id()], $result); + }); + + // Check that the 'stage' workspace was not persisted by the workspace + // manager. + $this->assertEquals('live', $this->workspaceManager->getActiveWorkspace()->id()); + } + /** * Checks entity load, entity queries and views results for a test scenario. * @@ -679,18 +697,6 @@ protected function assertWorkspaceAssociation(array $expected, $entity_type_id) } } - /** - * Sets a given workspace as active. - * - * @param string $workspace_id - * The ID of the workspace to switch to. - */ - protected function switchToWorkspace($workspace_id) { - // Switch the test runner's context to the specified workspace. - $workspace = $this->entityTypeManager->getStorage('workspace')->load($workspace_id); - \Drupal::service('workspaces.manager')->setActiveWorkspace($workspace); - } - /** * Flattens the expectations array defined by testWorkspaces(). * @@ -718,4 +724,35 @@ protected function flattenExpectedValues(array $expected, $entity_type_id) { return $flattened; } + /** + * Tests that entity forms can be stored in the form cache. + */ + public function testFormCacheForEntityForms() { + $this->initializeWorkspacesModule(); + $this->switchToWorkspace('stage'); + + $form_builder = $this->container->get('form_builder'); + + $form = $this->entityTypeManager->getFormObject('entity_test_mulrevpub', 'default'); + $form->setEntity(EntityTestMulRevPub::create([])); + + $form_state = new FormState(); + $built_form = $form_builder->buildForm($form, $form_state); + $form_builder->setCache($built_form['#build_id'], $built_form, $form_state); + } + + /** + * Tests that non-entity forms can be stored in the form cache. + */ + public function testFormCacheForRegularForms() { + $this->initializeWorkspacesModule(); + $this->switchToWorkspace('stage'); + + $form_builder = $this->container->get('form_builder'); + + $form_state = new FormState(); + $built_form = $form_builder->getForm(SiteInformationForm::class, $form_state); + $form_builder->setCache($built_form['#build_id'], $built_form, $form_state); + } + } diff --git a/web/core/modules/workspaces/tests/src/Kernel/WorkspaceTestTrait.php b/web/core/modules/workspaces/tests/src/Kernel/WorkspaceTestTrait.php new file mode 100644 index 0000000000000000000000000000000000000000..13cff6a3dfebf3dac95c51b25ef7e5b188ed3cd6 --- /dev/null +++ b/web/core/modules/workspaces/tests/src/Kernel/WorkspaceTestTrait.php @@ -0,0 +1,67 @@ +<?php + +namespace Drupal\Tests\workspaces\Kernel; + +use Drupal\workspaces\Entity\Workspace; + +/** + * A trait with common workspaces testing functionality. + */ +trait WorkspaceTestTrait { + + /** + * The workspaces manager. + * + * @var \Drupal\workspaces\WorkspaceManagerInterface + */ + protected $workspaceManager; + + /** + * An array of test workspaces, keyed by workspace ID. + * + * @var \Drupal\workspaces\WorkspaceInterface[] + */ + protected $workspaces = []; + + /** + * Enables the Workspaces module and creates two workspaces. + */ + protected function initializeWorkspacesModule() { + // Enable the Workspaces module here instead of the static::$modules array + // so we can test it with default content. + $this->enableModules(['workspaces']); + $this->container = \Drupal::getContainer(); + $this->entityTypeManager = \Drupal::entityTypeManager(); + $this->workspaceManager = \Drupal::service('workspaces.manager'); + + $this->installEntitySchema('workspace'); + $this->installEntitySchema('workspace_association'); + + // Create two workspaces by default, 'live' and 'stage'. + $this->workspaces['live'] = Workspace::create(['id' => 'live']); + $this->workspaces['live']->save(); + $this->workspaces['stage'] = Workspace::create(['id' => 'stage']); + $this->workspaces['stage']->save(); + + $permissions = array_intersect([ + 'administer nodes', + 'create workspace', + 'edit any workspace', + 'view any workspace', + ], array_keys($this->container->get('user.permissions')->getPermissions())); + $this->setCurrentUser($this->createUser($permissions)); + } + + /** + * Sets a given workspace as active. + * + * @param string $workspace_id + * The ID of the workspace to switch to. + */ + protected function switchToWorkspace($workspace_id) { + // Switch the test runner's context to the specified workspace. + $workspace = $this->entityTypeManager->getStorage('workspace')->load($workspace_id); + \Drupal::service('workspaces.manager')->setActiveWorkspace($workspace); + } + +} diff --git a/web/core/modules/workspaces/workspaces.info.yml b/web/core/modules/workspaces/workspaces.info.yml index b4c0725422da5d3167dd7532f87363aed46c3357..8461ec0f2484dfc48276b90d56f069070e060dfd 100644 --- a/web/core/modules/workspaces/workspaces.info.yml +++ b/web/core/modules/workspaces/workspaces.info.yml @@ -1,6 +1,6 @@ name: Workspaces type: module -description: 'Provides the ability to have multiple workspaces on a single site to facilitate things like full-site preview and content staging.' +description: 'Allows users to stage content or preview a full site by using multiple workspaces on a single site.' version: VERSION core: 8.x package: Core (Experimental) diff --git a/web/core/modules/workspaces/workspaces.module b/web/core/modules/workspaces/workspaces.module index f279c4389375284519a6d2f52ce0d5d15bda3331..8f4f2fa2e281a6ae0ca6353a2463c3cb2471e2dc 100644 --- a/web/core/modules/workspaces/workspaces.module +++ b/web/core/modules/workspaces/workspaces.module @@ -56,6 +56,15 @@ function workspaces_form_alter(&$form, FormStateInterface $form_state, $form_id) ->formAlter($form, $form_state, $form_id); } +/** + * Implements hook_field_info_alter(). + */ +function workspaces_field_info_alter(&$definitions) { + \Drupal::service('class_resolver') + ->getInstanceFromDefinition(EntityTypeInfo::class) + ->fieldInfoAlter($definitions); +} + /** * Implements hook_entity_load(). */ @@ -154,15 +163,15 @@ function workspaces_toolbar() { $current_user = \Drupal::currentUser(); if (!$current_user->hasPermission('administer workspaces') - || !$current_user->hasPermission('view own workspace') - || !$current_user->hasPermission('view any workspace')) { + && !$current_user->hasPermission('view own workspace') + && !$current_user->hasPermission('view any workspace')) { return $items; } /** @var \Drupal\workspaces\WorkspaceInterface $active_workspace */ $active_workspace = \Drupal::service('workspaces.manager')->getActiveWorkspace(); - $items['workspace'] = [ + $items['workspace'] += [ '#type' => 'toolbar_item', 'tab' => [ '#type' => 'link', @@ -180,6 +189,7 @@ function workspaces_toolbar() { ], ]), ], + '#cache' => ['tags' => $active_workspace->getCacheTags()], ], '#wrapper_attributes' => [ 'class' => ['workspaces-toolbar-tab'], diff --git a/web/core/modules/workspaces/workspaces.services.yml b/web/core/modules/workspaces/workspaces.services.yml index a238473d111eae878ff00d483305710fcc6f12ed..ab9e8bf89f71d0bd572a691a7d123f355c526284 100644 --- a/web/core/modules/workspaces/workspaces.services.yml +++ b/web/core/modules/workspaces/workspaces.services.yml @@ -1,7 +1,7 @@ services: workspaces.manager: class: Drupal\workspaces\WorkspaceManager - arguments: ['@request_stack', '@entity_type.manager', '@current_user', '@state', '@logger.channel.workspaces', '@class_resolver'] + arguments: ['@request_stack', '@entity_type.manager', '@entity.memory_cache', '@current_user', '@state', '@logger.channel.workspaces', '@class_resolver'] tags: - { name: service_id_collector, tag: workspace_negotiator } workspaces.operation_factory: diff --git a/web/core/package.json b/web/core/package.json index ea1fb2b924a41ecb5a1454587e2a2eb6aa568685..731a73d941d378bc0dc3e4ff98da18aab7802756 100644 --- a/web/core/package.json +++ b/web/core/package.json @@ -9,7 +9,7 @@ }, "scripts": { "build:js": "cross-env BABEL_ENV=legacy node ./scripts/js/babel-es6-build.js", - "build:js-dev": "cross-env NODE_ENV=development node BABEL_ENV=legacy ./scripts/js/babel-es6-build.js", + "build:js-dev": "cross-env NODE_ENV=development BABEL_ENV=legacy node ./scripts/js/babel-es6-build.js", "watch:js": "cross-env BABEL_ENV=legacy node ./scripts/js/babel-es6-watch.js", "watch:js-dev": "cross-env NODE_ENV=development BABEL_ENV=legacy node ./scripts/js/babel-es6-watch.js", "lint:core-js": "node ./node_modules/eslint/bin/eslint.js .", diff --git a/web/core/profiles/demo_umami/config/install/core.entity_form_display.node.recipe.default.yml b/web/core/profiles/demo_umami/config/install/core.entity_form_display.node.recipe.default.yml index 42cd68e0bea1de477b8c87eac041d37388129d3f..5c3431958d572dcb4cbe1396c78fcc7c488912a5 100644 --- a/web/core/profiles/demo_umami/config/install/core.entity_form_display.node.recipe.default.yml +++ b/web/core/profiles/demo_umami/config/install/core.entity_form_display.node.recipe.default.yml @@ -2,7 +2,6 @@ langcode: en status: true dependencies: config: - - field.field.node.recipe.field_author - field.field.node.recipe.field_cooking_time - field.field.node.recipe.field_difficulty - field.field.node.recipe.field_image @@ -31,15 +30,6 @@ content: region: content settings: { } third_party_settings: { } - field_author: - weight: 1 - settings: - match_operator: CONTAINS - size: 60 - placeholder: '' - third_party_settings: { } - type: entity_reference_autocomplete - region: content field_cooking_time: weight: 3 settings: diff --git a/web/core/profiles/demo_umami/config/install/core.entity_view_display.node.recipe.card.yml b/web/core/profiles/demo_umami/config/install/core.entity_view_display.node.recipe.card.yml index 6480eb8f31761828413c9ff2390ac6569e397823..915362cdab7439174f53e24f626e4b8d2f6bbf17 100644 --- a/web/core/profiles/demo_umami/config/install/core.entity_view_display.node.recipe.card.yml +++ b/web/core/profiles/demo_umami/config/install/core.entity_view_display.node.recipe.card.yml @@ -3,7 +3,6 @@ status: true dependencies: config: - core.entity_view_mode.node.card - - field.field.node.recipe.field_author - field.field.node.recipe.field_cooking_time - field.field.node.recipe.field_difficulty - field.field.node.recipe.field_image @@ -43,7 +42,6 @@ content: region: content hidden: content_moderation_control: true - field_author: true field_cooking_time: true field_ingredients: true field_number_of_servings: true diff --git a/web/core/profiles/demo_umami/config/install/core.entity_view_display.node.recipe.card_common.yml b/web/core/profiles/demo_umami/config/install/core.entity_view_display.node.recipe.card_common.yml index 166179db1e0849f43ffdb9602bb1a206500228d0..6315fe1f41a1f75a6567f2ed4203d652fe137510 100644 --- a/web/core/profiles/demo_umami/config/install/core.entity_view_display.node.recipe.card_common.yml +++ b/web/core/profiles/demo_umami/config/install/core.entity_view_display.node.recipe.card_common.yml @@ -3,7 +3,6 @@ status: true dependencies: config: - core.entity_view_mode.node.card_common - - field.field.node.recipe.field_author - field.field.node.recipe.field_cooking_time - field.field.node.recipe.field_difficulty - field.field.node.recipe.field_image @@ -35,7 +34,6 @@ content: third_party_settings: { } hidden: content_moderation_control: true - field_author: true field_cooking_time: true field_difficulty: true field_ingredients: true diff --git a/web/core/profiles/demo_umami/config/install/core.entity_view_display.node.recipe.card_common_alt.yml b/web/core/profiles/demo_umami/config/install/core.entity_view_display.node.recipe.card_common_alt.yml index a1824245af90f39da909cef19f1056ab81607eaf..2c099447ca2e6abf7c99d7b873a1fdf79d469c70 100644 --- a/web/core/profiles/demo_umami/config/install/core.entity_view_display.node.recipe.card_common_alt.yml +++ b/web/core/profiles/demo_umami/config/install/core.entity_view_display.node.recipe.card_common_alt.yml @@ -3,7 +3,6 @@ status: true dependencies: config: - core.entity_view_mode.node.card_common_alt - - field.field.node.recipe.field_author - field.field.node.recipe.field_cooking_time - field.field.node.recipe.field_difficulty - field.field.node.recipe.field_image @@ -35,7 +34,6 @@ content: region: content hidden: content_moderation_control: true - field_author: true field_cooking_time: true field_difficulty: true field_ingredients: true diff --git a/web/core/profiles/demo_umami/config/install/core.entity_view_display.node.recipe.default.yml b/web/core/profiles/demo_umami/config/install/core.entity_view_display.node.recipe.default.yml index 2e3a34540ab4a10548567f2b1c0e8ecbb5155834..ac8036822892560477652473c48ec2031cd0a00c 100644 --- a/web/core/profiles/demo_umami/config/install/core.entity_view_display.node.recipe.default.yml +++ b/web/core/profiles/demo_umami/config/install/core.entity_view_display.node.recipe.default.yml @@ -2,7 +2,6 @@ langcode: en status: true dependencies: config: - - field.field.node.recipe.field_author - field.field.node.recipe.field_cooking_time - field.field.node.recipe.field_difficulty - field.field.node.recipe.field_image @@ -113,4 +112,3 @@ content: third_party_settings: { } hidden: content_moderation_control: true - field_author: true diff --git a/web/core/profiles/demo_umami/config/install/core.entity_view_display.node.recipe.full.yml b/web/core/profiles/demo_umami/config/install/core.entity_view_display.node.recipe.full.yml index 742d1afe264c2570bd4323dea922cd704b30317d..de50c444439cc4538e6a7ff487574b11cfe70123 100644 --- a/web/core/profiles/demo_umami/config/install/core.entity_view_display.node.recipe.full.yml +++ b/web/core/profiles/demo_umami/config/install/core.entity_view_display.node.recipe.full.yml @@ -3,7 +3,6 @@ status: true dependencies: config: - core.entity_view_mode.node.full - - field.field.node.recipe.field_author - field.field.node.recipe.field_cooking_time - field.field.node.recipe.field_difficulty - field.field.node.recipe.field_image @@ -109,5 +108,4 @@ content: region: content hidden: content_moderation_control: true - field_author: true links: true diff --git a/web/core/profiles/demo_umami/config/install/core.entity_view_display.node.recipe.teaser.yml b/web/core/profiles/demo_umami/config/install/core.entity_view_display.node.recipe.teaser.yml index a576765dfa5a008cf52da9311f52cc32c72b8680..e149ba9d07970440cc429afee300fd2bed1cd3db 100644 --- a/web/core/profiles/demo_umami/config/install/core.entity_view_display.node.recipe.teaser.yml +++ b/web/core/profiles/demo_umami/config/install/core.entity_view_display.node.recipe.teaser.yml @@ -3,7 +3,6 @@ status: true dependencies: config: - core.entity_view_mode.node.teaser - - field.field.node.recipe.field_author - field.field.node.recipe.field_cooking_time - field.field.node.recipe.field_difficulty - field.field.node.recipe.field_image @@ -27,7 +26,6 @@ content: region: content hidden: content_moderation_control: true - field_author: true field_cooking_time: true field_difficulty: true field_image: true diff --git a/web/core/profiles/demo_umami/config/install/core.menu.static_menu_link_overrides.yml b/web/core/profiles/demo_umami/config/install/core.menu.static_menu_link_overrides.yml new file mode 100644 index 0000000000000000000000000000000000000000..114c789369a4d927f54850c8f500e0e0d8d73f4a --- /dev/null +++ b/web/core/profiles/demo_umami/config/install/core.menu.static_menu_link_overrides.yml @@ -0,0 +1,7 @@ +definitions: + contact__site_page: + enabled: true + menu_name: footer + parent: '' + weight: 0 + expanded: false diff --git a/web/core/profiles/demo_umami/config/install/field.field.node.article.field_tags.yml b/web/core/profiles/demo_umami/config/install/field.field.node.article.field_tags.yml index 1b9c4cc4ee1e1143722aeac9ef20e9aaaf27199d..a9425fd6bad42e6cbd064f186117c5cdaa4a1edd 100644 --- a/web/core/profiles/demo_umami/config/install/field.field.node.article.field_tags.yml +++ b/web/core/profiles/demo_umami/config/install/field.field.node.article.field_tags.yml @@ -10,7 +10,7 @@ field_name: field_tags entity_type: node bundle: article label: Tags -description: 'Enter a comma-separated list. For example: Amsterdam, Mexico City, "Cleveland, Ohio"' +description: 'Enter a comma-separated list. For example: Vegetarian, Chocolate brownies, Appetizers' required: false translatable: true default_value: { } diff --git a/web/core/profiles/demo_umami/config/install/field.field.node.recipe.field_author.yml b/web/core/profiles/demo_umami/config/install/field.field.node.recipe.field_author.yml deleted file mode 100644 index 386ee5956c57c8d5b571433b8c1dbd491746a1a1..0000000000000000000000000000000000000000 --- a/web/core/profiles/demo_umami/config/install/field.field.node.recipe.field_author.yml +++ /dev/null @@ -1,27 +0,0 @@ -langcode: en -status: true -dependencies: - config: - - field.storage.node.field_author - - node.type.recipe -id: node.recipe.field_author -field_name: field_author -entity_type: node -bundle: recipe -label: Author -description: 'The author of this recipe. Start typing their username to search.' -required: true -translatable: false -default_value: { } -default_value_callback: '' -settings: - handler: 'default:user' - handler_settings: - include_anonymous: true - filter: - type: _none - target_bundles: null - sort: - field: _none - auto_create: false -field_type: entity_reference diff --git a/web/core/profiles/demo_umami/config/install/field.field.node.recipe.field_tags.yml b/web/core/profiles/demo_umami/config/install/field.field.node.recipe.field_tags.yml index 8b305ca43616ade2ca055a6309336234c65fdbf6..87f7351dc89156ef7b8a4268e050a77f9807b1a6 100644 --- a/web/core/profiles/demo_umami/config/install/field.field.node.recipe.field_tags.yml +++ b/web/core/profiles/demo_umami/config/install/field.field.node.recipe.field_tags.yml @@ -10,7 +10,7 @@ field_name: field_tags entity_type: node bundle: recipe label: Tags -description: '' +description: 'Enter a comma-separated list. For example: Vegetarian, Chocolate brownies, Appetizers' required: false translatable: true default_value: { } diff --git a/web/core/profiles/demo_umami/config/install/field.storage.node.field_author.yml b/web/core/profiles/demo_umami/config/install/field.storage.node.field_author.yml deleted file mode 100644 index cb123cf6c0c5d7c08afe65136641ce51c0fab2df..0000000000000000000000000000000000000000 --- a/web/core/profiles/demo_umami/config/install/field.storage.node.field_author.yml +++ /dev/null @@ -1,19 +0,0 @@ -langcode: en -status: true -dependencies: - module: - - node - - user -id: node.field_author -field_name: field_author -entity_type: node -type: entity_reference -settings: - target_type: user -module: core -locked: false -cardinality: 1 -translatable: true -indexes: { } -persist_with_no_fields: false -custom_storage: false diff --git a/web/core/profiles/demo_umami/config/install/node.settings.yml b/web/core/profiles/demo_umami/config/install/node.settings.yml new file mode 100644 index 0000000000000000000000000000000000000000..6cb95cbc42a2670a4bdc9245a1e27f351bf88a9d --- /dev/null +++ b/web/core/profiles/demo_umami/config/install/node.settings.yml @@ -0,0 +1 @@ +use_admin_theme: true diff --git a/web/core/profiles/demo_umami/config/install/system.site.yml b/web/core/profiles/demo_umami/config/install/system.site.yml new file mode 100644 index 0000000000000000000000000000000000000000..46a19562fec11e77cc362fc0a864159409a69556 --- /dev/null +++ b/web/core/profiles/demo_umami/config/install/system.site.yml @@ -0,0 +1,12 @@ +uuid: '' +name: '' +mail: '' +slogan: '' +page: + 403: '' + 404: '' + front: /node +admin_compact_mode: false +weight_select_max: 100 +langcode: en +default_langcode: en diff --git a/web/core/profiles/demo_umami/config/install/taxonomy.vocabulary.recipe_category.yml b/web/core/profiles/demo_umami/config/install/taxonomy.vocabulary.recipe_category.yml index ee82773bbf0212f2dd0ad113a18d79940f8d5ebf..adbacf80747b620487059ed73581ba3db4b3a033 100644 --- a/web/core/profiles/demo_umami/config/install/taxonomy.vocabulary.recipe_category.yml +++ b/web/core/profiles/demo_umami/config/install/taxonomy.vocabulary.recipe_category.yml @@ -3,6 +3,6 @@ status: true dependencies: { } name: 'Recipe category' vid: recipe_category -description: '' +description: 'Use this taxonomy to group recipes of the same type together.' hierarchy: 0 weight: 0 diff --git a/web/core/profiles/demo_umami/config/install/user.role.anonymous.yml b/web/core/profiles/demo_umami/config/install/user.role.anonymous.yml new file mode 100644 index 0000000000000000000000000000000000000000..b860296d756636f188e9b816e9e57992694bf877 --- /dev/null +++ b/web/core/profiles/demo_umami/config/install/user.role.anonymous.yml @@ -0,0 +1,13 @@ +langcode: en +status: true +dependencies: { } +id: anonymous +label: 'Anonymous user' +weight: 0 +is_admin: false +permissions: + - 'access content' + - 'access site-wide contact form' + - 'search content' + - 'use text format restricted_html' + - 'view media' diff --git a/web/core/profiles/demo_umami/config/install/user.role.authenticated.yml b/web/core/profiles/demo_umami/config/install/user.role.authenticated.yml new file mode 100644 index 0000000000000000000000000000000000000000..ac4e409555a8761cf62245d9adaf40682cc5cb01 --- /dev/null +++ b/web/core/profiles/demo_umami/config/install/user.role.authenticated.yml @@ -0,0 +1,14 @@ +langcode: en +status: true +dependencies: { } +id: authenticated +label: 'Authenticated user' +weight: 1 +is_admin: false +permissions: + - 'access content' + - 'access shortcuts' + - 'access site-wide contact form' + - 'search content' + - 'use text format basic_html' + - 'view media' diff --git a/web/core/profiles/demo_umami/config/install/user.settings.yml b/web/core/profiles/demo_umami/config/install/user.settings.yml new file mode 100644 index 0000000000000000000000000000000000000000..e3b3a89b0878aa67c6b53cb62ad3d375694d5c6e --- /dev/null +++ b/web/core/profiles/demo_umami/config/install/user.settings.yml @@ -0,0 +1,16 @@ +anonymous: Anonymous +verify_mail: true +notify: + cancel_confirm: true + password_reset: true + status_activated: true + status_blocked: false + status_canceled: false + register_admin_created: true + register_no_approval_required: true + register_pending_approval: true +register: admin_only +cancel_method: user_cancel_block +password_reset_timeout: 86400 +password_strength: true +langcode: en diff --git a/web/core/profiles/demo_umami/config/install/views.view.articles_aside.yml b/web/core/profiles/demo_umami/config/install/views.view.articles_aside.yml index 8a4357f84fbd77718ef81bf70a567f1e548ba962..d65688686f8d86fc99f32ba51f31fed0ff9ad325 100644 --- a/web/core/profiles/demo_umami/config/install/views.view.articles_aside.yml +++ b/web/core/profiles/demo_umami/config/install/views.view.articles_aside.yml @@ -144,6 +144,20 @@ display: expose: label: '' granularity: second + nid: + id: nid + table: node_field_data + field: nid + relationship: none + group_type: group + admin_label: '' + order: ASC + exposed: false + expose: + label: '' + entity_type: node + entity_field: nid + plugin_id: standard title: 'More featured articles' header: { } footer: { } diff --git a/web/core/profiles/demo_umami/config/install/views.view.featured_articles.yml b/web/core/profiles/demo_umami/config/install/views.view.featured_articles.yml index 3ddc61bb755a9934c17cbd145be857e6ebc5e15a..9ce6c4cab1716f81079880a06dd9a8e79c68802f 100644 --- a/web/core/profiles/demo_umami/config/install/views.view.featured_articles.yml +++ b/web/core/profiles/demo_umami/config/install/views.view.featured_articles.yml @@ -158,6 +158,20 @@ display: expose: label: '' granularity: second + nid: + id: nid + table: node_field_data + field: nid + relationship: none + group_type: group + admin_label: '' + order: ASC + exposed: false + expose: + label: '' + entity_type: node + entity_field: nid + plugin_id: standard title: Articles header: { } footer: { } diff --git a/web/core/profiles/demo_umami/config/install/views.view.frontpage.yml b/web/core/profiles/demo_umami/config/install/views.view.frontpage.yml index 7f4f0db3f116c1c9d96db734d71d7fd4190e3192..a97299283bec7dedc1647c9b2c8e61f8ea1cca6b 100644 --- a/web/core/profiles/demo_umami/config/install/views.view.frontpage.yml +++ b/web/core/profiles/demo_umami/config/install/views.view.frontpage.yml @@ -249,6 +249,20 @@ display: granularity: second entity_type: node entity_field: created + nid: + id: nid + table: node_field_data + field: nid + relationship: none + group_type: group + admin_label: '' + order: ASC + exposed: false + expose: + label: '' + entity_type: node + entity_field: nid + plugin_id: standard style: type: default options: diff --git a/web/core/profiles/demo_umami/config/install/views.view.recipes.yml b/web/core/profiles/demo_umami/config/install/views.view.recipes.yml index e7cf9fd6f97c569387da2df5eed24ae9120a72be..7e273c970dedffff3980abcc6a8231fd148ddcba 100644 --- a/web/core/profiles/demo_umami/config/install/views.view.recipes.yml +++ b/web/core/profiles/demo_umami/config/install/views.view.recipes.yml @@ -158,6 +158,20 @@ display: expose: label: '' granularity: second + nid: + id: nid + table: node_field_data + field: nid + relationship: none + group_type: group + admin_label: '' + order: ASC + exposed: false + expose: + label: '' + entity_type: node + entity_field: nid + plugin_id: standard title: Recipes header: { } footer: { } diff --git a/web/core/profiles/demo_umami/demo_umami.install b/web/core/profiles/demo_umami/demo_umami.install index c26be61407416c52382a617a500dd630993cc20b..37025e0826840a23ff81be443afedb74cf05d21f 100644 --- a/web/core/profiles/demo_umami/demo_umami.install +++ b/web/core/profiles/demo_umami/demo_umami.install @@ -6,7 +6,6 @@ */ use Drupal\user\Entity\User; -use Drupal\user\RoleInterface; use Drupal\shortcut\Entity\Shortcut; /** @@ -35,13 +34,6 @@ function demo_umami_requirements($phase) { * @see system_install() */ function demo_umami_install() { - // Set front page to "node". - \Drupal::configFactory()->getEditable('system.site')->set('page.front', '/node')->save(TRUE); - - // Allow visitor account creation with administrative approval. - $user_settings = \Drupal::configFactory()->getEditable('user.settings'); - $user_settings->set('register', USER_REGISTER_ADMINISTRATORS_ONLY)->save(TRUE); - // Assign user 1 the "administrator" role. $user = User::load(1); $user->roles[] = 'administrator'; @@ -51,17 +43,6 @@ function demo_umami_install() { // menu links are valid. \Drupal::service('router.builder')->rebuildIfNeeded(); - // Enable the Contact link in the footer menu. - /** @var \Drupal\Core\Menu\MenuLinkManagerInterface $menu_link_manager */ - $menu_link_manager = \Drupal::service('plugin.manager.menu.link'); - $menu_link_manager->updateDefinition('contact.site_page', ['enabled' => TRUE]); - - user_role_grant_permissions(RoleInterface::ANONYMOUS_ID, ['access site-wide contact form']); - user_role_grant_permissions(RoleInterface::AUTHENTICATED_ID, ['access site-wide contact form']); - - // Allow authenticated users to use shortcuts. - user_role_grant_permissions(RoleInterface::AUTHENTICATED_ID, ['access shortcuts']); - // Populate the default shortcut set. $shortcut = Shortcut::create([ 'shortcut_set' => 'default', @@ -79,13 +60,6 @@ function demo_umami_install() { ]); $shortcut->save(); - // Allow all users to use search. - user_role_grant_permissions(RoleInterface::ANONYMOUS_ID, ['search content']); - user_role_grant_permissions(RoleInterface::AUTHENTICATED_ID, ['search content']); - - // Enable the admin theme. - \Drupal::configFactory()->getEditable('node.settings')->set('use_admin_theme', TRUE)->save(TRUE); - // Enable the demo content module. This can't be specified as a dependency // in the demo_umami.info.yml file, as it requires configuration provided by // the profile (fields etc.). diff --git a/web/core/profiles/demo_umami/modules/demo_umami_content/default_content/LICENCE.txt b/web/core/profiles/demo_umami/modules/demo_umami_content/default_content/LICENCE.txt index 6c421e59a812a5cfd79b487dcfe69d4cc980a70c..72077fc14a96825729ca9440b8a167269a43427a 100644 --- a/web/core/profiles/demo_umami/modules/demo_umami_content/default_content/LICENCE.txt +++ b/web/core/profiles/demo_umami/modules/demo_umami_content/default_content/LICENCE.txt @@ -13,12 +13,15 @@ pineapple-placeholder-10.jpg by Keith Jay pizza-umami.jpg by Keith Jay supermarket-savvy-umami.jpg by Keith Jay thai-green-curry-umami.jpg by Keith Jay +vegan-chocolate.jpg by Keith Jay veggie-pasta-bake-hero-umami.jpg by Keith Jay veggie-pasta-bake-umami.jpg by Keith Jay victoria-sponge-umami.jpg by Keith Jay watercress-soup-umami.jpg by Keith Jay crema-catalana-umami.jpg by Cristina Chumillas mojito-mocktail.jpg by Keith Jay +oatmeal-fruit-syrup-topping.jpg by Keith Jay + are all licensed under a http://creativecommons.org/licenses/by-sa/4.0/ Creative Commons Attribution-ShareAlike 4.0 International License. diff --git a/web/core/profiles/demo_umami/modules/demo_umami_content/default_content/article_body/dairy-free-delicious-milk-chocolate.html b/web/core/profiles/demo_umami/modules/demo_umami_content/default_content/article_body/dairy-free-delicious-milk-chocolate.html new file mode 100644 index 0000000000000000000000000000000000000000..ee137ff892c7699797c47d08b72af7680e49d1a9 --- /dev/null +++ b/web/core/profiles/demo_umami/modules/demo_umami_content/default_content/article_body/dairy-free-delicious-milk-chocolate.html @@ -0,0 +1,12 @@ +<p>The calendar is full of excuses for chocolate-lovers to indulge, from religious festivals to birthdays - and even World Chocolate Day on the 7th July. But for those who are vegan, or on dairy-free diets, there is no need to miss out, because there are plenty of delicious vegan chocolate varieties on offer.</p> +<p>Dairy-free milk chocolate is made in largely the same way as regular chocolate, until the point when the milk is added. Cacao beans are roasted for a couple of hours until they develop a rich flavor. The outer shells are removed, and the interior nibs are ground to make a paste that can be mixed with cocoa butter to produce the desired percentage of chocolate. Flavorings, sugar and milk are added in different quantities to get the type of chocolate being produced. The chocolate is grainy at this point and needs to be mashed until it is smooth - this can take days! Finally, it is tempered through a process of heating and cooling until it is ready to eat.</p> +<p>So, how do vegan chocolatiers get that creamy milk flavor and texture into their products?</p> +<h2>Rice milk</h2> +<p>The flavor of rice milk perfectly complements the cocoa beans and it was one of the first dairy milk alternatives to be used to create vegan milk chocolate. Rice milk is made from rice powder and is sometimes combined with hazelnut milk to create the correct texture and taste that is ideal for producing all kinds of chocolate bars.</p> +<h2>Coconut milk</h2> +<p>Coconut milk has to be the perfect ingredient for adding creaminess into a chocolate bar. With high fat levels, a sweet, but not overpowering taste and the correct consistency, coconut milk is a great choice for vegan milk chocolate. Chocolate made in this way will melt wonderfully for drizzling or dipping, and the coconut milk adds a slight tropical flavor that works well with other fruit flavors and nuts.</p> +<h2>Soy milk</h2> +<p>Soy has long been the mainstay of vegan and vegetarian diets, as it is rich in protein and is available in a wide variety of textures suitable for all kinds of dishes. Soy milk is widely available and is a great alternative to dairy milk in chocolate. It isn’t as rich in fat as some vegan milks, but does have a neutral taste that makes it easy to combine with almost any other flavor.</p> +<h2>Nut milks</h2> +<p>Milks made from almonds and hazelnuts are easy to find on supermarket shelves, and are perfect for chocolate production. Like soy milk, they can be quite low in fat and therefore a little less creamy, but they have that nutty taste that goes so well with chocolate of all kinds.</p> +<p>Many manufacturers will use a combination of the above milks to create the perfect consistency for their product. Using this milk mixture they are able to produce all kinds of milk chocolates, including white chocolate.</p> diff --git a/web/core/profiles/demo_umami/modules/demo_umami_content/default_content/article_body/give-your-oatmeal-the-ultimate-makeover.html b/web/core/profiles/demo_umami/modules/demo_umami_content/default_content/article_body/give-your-oatmeal-the-ultimate-makeover.html new file mode 100644 index 0000000000000000000000000000000000000000..945cc4c609c2ad8ca5dbb0be1d78fb63c7b05d91 --- /dev/null +++ b/web/core/profiles/demo_umami/modules/demo_umami_content/default_content/article_body/give-your-oatmeal-the-ultimate-makeover.html @@ -0,0 +1,43 @@ +<p> +It is vegan, gluten-free, low in fat, high in fiber, and can even lower cholesterol - but oatmeal is boring, right? Well, before you write off that boring jar of oats, you might want to take inspiration from our topping ideas that will take your oatmeal from bland to creatively delicious in just a few minutes. +</p> + +<p> +Call it oatmeal, porridge, hot cereal, or just plain oats, it is loved the world over; but recently, the humble oat is getting a funky makeover. Long gone are the days of stodgy breakfast bowls of thick gloop, because oats are getting served up as a delicious meal that can suit any time of the day. Trendy build-your-own oatmeal bars are popping up, and they are providing the ultimate oatmeal experience. Diners can choose their oats to be made with milk or water and then go to town with their choice of favorite toppings - sweet, savory, or even spicy. +</p> + +<p> +It sounds great, doesn’t it? So before you close the cupboard door on that bland-looking jar of oats, we think you should try some of these scrumptious topping ideas to inspire your very own oatmeal makeover. +</p> + + +<h2>Soaked dried fruit</h2> + +<p> +Sometimes plain dried fruit can be a bit chewy and harsh when combined with creamy oats. But if you simply soak your dried fruit in orange juice overnight, they develop a tang, and they swell up, making them softer and even more delicious. Plus the splash of color can really brighten your day. +</p> + + +<h2>Porridge crème brûlée</h2> + +<p> +So simple - but why has no one thought of it before? Put your cooked oatmeal into a ramekin, sprinkle with sugar, and pop under the grill. The sugar will harden, giving you the delight of cracking through the surface and scooping out the creamy deliciousness beneath. If you are really professional, you can use a blow torch. +</p> + +<h2>Super seeds</h2> + +<p> +For a more savory meal option, cook your oats with water, a little salt, and sprinkle with toasted seeds. You can choose any that you enjoy, but pumpkin seeds, sesame, linseed, and sunflower seeds are especially good. Some supermarkets also sell seed blends to make the job even easier. +</p> + +<h2>Deconstructed carrot cake</h2> + +<p> +Cook your oats with grated carrots and a little sugar, then top with a sprinkle of cinnamon, chopped walnuts, and a dollop of sweetened cream cheese. If you don’t love this, there’s something wrong with your taste buds. +</p> + +<h2>Dark chocolate</h2> + +<p> +This low-sugar delight will meet all of those chocolate cravings and is the perfect dessert. Add a spoonful of cocoa to your oatmeal as it cooks, then top with a few squares of dark chocolate. As it melts, simply swirl into the bowl as artfully as you can. If you are really decadent, a squirt of whipped cream will add further delights. +</p> diff --git a/web/core/profiles/demo_umami/modules/demo_umami_content/default_content/article_body/lets-hear-it-for-carrots.html b/web/core/profiles/demo_umami/modules/demo_umami_content/default_content/article_body/lets-hear-it-for-carrots.html index d198d8125219e519d80df58fe91209b556e00f96..86111e401f85d4ba3155132202010ffa8f544829 100644 --- a/web/core/profiles/demo_umami/modules/demo_umami_content/default_content/article_body/lets-hear-it-for-carrots.html +++ b/web/core/profiles/demo_umami/modules/demo_umami_content/default_content/article_body/lets-hear-it-for-carrots.html @@ -8,4 +8,4 @@ <h2>Nutrition</h2> <h2>Get them at their best</h2> <p>Young carrots, harvested when they are small have an especially sweet flavor and they are absolutely delicious. To cook them you can skip the peeling, give them a good wash and pop them in the steamer for just a few minutes. Carrots will taste the best when they are fresh, so make sure they are firm and bright in color when buying.</p> <h2>And that thing about carrots helping you see more in the dark?</h2> -<p>Of course it's a myth. During World War II the U.K. Ministry of Food promoted carrots as a super healthy veggie that would improve your ability to see during the blackouts and as an explanation for the succesfull night missions of UK fighter pilots. In reality, the only truth in the connection between carrots and improved eye sight is that vitamin A does indeed help to maintain vision.</p> +<p>Of course it's a myth. During World War II the UK Ministry of Food promoted carrots as a super healthy veggie that would improve your ability to see during the blackouts and as an explanation for the successful night missions of UK fighter pilots. In reality, the only truth in the connection between carrots and improved eye sight is that vitamin A does indeed help to maintain vision.</p> diff --git a/web/core/profiles/demo_umami/modules/demo_umami_content/default_content/article_body/the-umami-guide-to-our-favourite-mushrooms.html b/web/core/profiles/demo_umami/modules/demo_umami_content/default_content/article_body/the-umami-guide-to-our-favourite-mushrooms.html index b0bf7e1faefee17de934499df72ffa705f97ee88..76860e5e6db148d13b84b6fc4250412cf745e135 100644 --- a/web/core/profiles/demo_umami/modules/demo_umami_content/default_content/article_body/the-umami-guide-to-our-favourite-mushrooms.html +++ b/web/core/profiles/demo_umami/modules/demo_umami_content/default_content/article_body/the-umami-guide-to-our-favourite-mushrooms.html @@ -2,6 +2,6 @@ <p>One of the best things about mushrooms is their versatility. They can be fried, roasted, grilled, steamed, or even cooked in the microwave. And they can be served as the main ingredient for a dish, or simply added as part of the mix. This makes mushrooms an ideal choice for creating absolutely delicious vegetarian dishes.</p> <p>So let's take a look at some of our favorite types of mushroom. You might not have tried cooking with them before but don't let that put you off. With their delicious, distinctive flavors you can easily transform soups, starters, sauces and create amazing pasta, or stir-fry dishes.</p> <p>Try the lovely <strong>shiitake</strong>. Used in Asian cooking, these can be purchased dried and rehydrated for a strong, deep flavor. Or buy fresh and add to soups and stir-fries. Not only does this mushroom have an intense flavor, it looks lovely too. The deep brown and smooth shapes will provide texture to your meal. In their dried form and rehydrated, these are the perfect addition for a deep and flavorful stock for a risotto.</p> -<p>The gorgeous sunny <strong>chanterelle</strong> with its yellow flesh has a fruity flavor - but it is worth mentioning that there are many lookalikes out there and care should be taken to ensure you're eating the right ones. These look great in an omelette or an asian soup to complement the yellow tones.</p> +<p>The gorgeous sunny <strong>chanterelle</strong> with its yellow flesh has a fruity flavor - but it is worth mentioning that there are many lookalikes out there and care should be taken to ensure you're eating the right ones. These look great in an omelette or an Asian soup to complement the yellow tones.</p> <p>The brown <strong>morel</strong> offers a meaty and distinctive flavor and you'll probably love how extraordinary they look in a meal. The morel is a more popular mushroom during the spring, when their availability is high.</p> <p>For delicacy try the <strong>enoki</strong> with its tiny white heads that grow in a bunch. These can even be eaten raw in salads. Finally, you can choose the popular <strong>oyster</strong> mushroom. They are named thus because they look nothing like a mushroom and resemble the innards of an oyster and their sweet flavor is delicious.</p> diff --git a/web/core/profiles/demo_umami/modules/demo_umami_content/default_content/articles.csv b/web/core/profiles/demo_umami/modules/demo_umami_content/default_content/articles.csv index 54658fd182226fd57b099050e0e71db7359a9a90..4849654897f7cdb4919164e5fb7004b24f4c45a8 100644 --- a/web/core/profiles/demo_umami/modules/demo_umami_content/default_content/articles.csv +++ b/web/core/profiles/demo_umami/modules/demo_umami_content/default_content/articles.csv @@ -1,7 +1,9 @@ title,body,author,slug,image,alt,tags Give it a go and grow your own herbs,give-it-a-go-and-grow-your-own-herbs.html,Holly Foat,articles/give-it-a-go-and-grow-your-own-herbs,home-grown-herbs.jpg,"Fresh cut herbs including mint, parsley, thyme and dill","Grow your own,Seasonal,Herbs" +Dairy-free and delicious milk chocolate,dairy-free-delicious-milk-chocolate.html,Umami,articles/dairy-free-and-delicious-milk-chocolate,vegan-chocolate.jpg,"A delicious bar of dairy-free milk chocolate, broken into pieces.","Vegan,Chocolate" The real deal for supermarket savvy shopping,the-real-deal-for-supermarket-savvy-shopping.html,Megan Collins Quinlan,articles/the-real-deal-for-supermarket-savvy-shopping,supermarket-savvy-umami.jpg,Products presented on supermarket shelving.,"Supermarkets,Shopping" -The umami guide to our favorite mushrooms,the-umami-guide-to-our-favourite-mushrooms.html,Umami,articles/the-umami-guide-to-our-favourite-mushrooms,mushrooms-umami.jpg,A delightful selection of mushroom varieties laid out on a simple wooden plate.,"Mushrooms,Vegetarian" +The Umami guide to our favorite mushrooms,the-umami-guide-to-our-favourite-mushrooms.html,Umami,articles/the-umami-guide-to-our-favourite-mushrooms,mushrooms-umami.jpg,A delightful selection of mushroom varieties laid out on a simple wooden plate.,"Mushrooms,Vegetarian" Let's hear it for carrots,lets-hear-it-for-carrots.html,Umami,articles/lets-hear-it-for-carrots,heritage-carrots.jpg,"Purple, orange, yellow and white heritage carrots.","Carrots,Vegetarian,Healthy" Baking mishaps - our troubleshooting tips,baking-mishaps-our-troubleshooting-tips.html,"Umami",articles/baking-mishaps-our-troubleshooting-tips,chocolate-brownie-umami.jpg,"A delicious chocolate brownie","Baking,Learn to cook" Skip the spirits with delicious mocktails,skip-the-spirits-with-delicious-mocktails.html,Megan Collins Quinlan,articles/skip-the-spirits-with-delicious-mocktails,mojito-mocktail.jpg,"Fresh mojito mocktail with garnish of mint leaves, ice, and sliced lime","Alcohol free,Drinks,Party,Cocktail party,Dinner party" +Give your oatmeal the ultimate makeover,give-your-oatmeal-the-ultimate-makeover.html,Umami,articles/give-your-oatmeal-the-ultimate-makeover,oatmeal-fruit-syrup-topping.jpg,"Oatmeal topped with a vibrant mix of berries, nuts, and seeds","Vegan,Vegetarian,Oats,Breakfast,Dessert" diff --git a/web/core/profiles/demo_umami/modules/demo_umami_content/default_content/images/oatmeal-fruit-syrup-topping.jpg b/web/core/profiles/demo_umami/modules/demo_umami_content/default_content/images/oatmeal-fruit-syrup-topping.jpg new file mode 100644 index 0000000000000000000000000000000000000000..169341bc4df78e2a8bc0ba91c4bfdccfbb6dd5db --- /dev/null +++ b/web/core/profiles/demo_umami/modules/demo_umami_content/default_content/images/oatmeal-fruit-syrup-topping.jpg @@ -0,0 +1,278 @@ +�����JFIF���������C� + + !*$( %2%(,-/0/#484.7*./.���C +...................................................�����"�������������� +�������}�!1AQa"q2���#B��R��$3br� +%&'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz����������������������������������������������������������������������������������� +������w�!1AQaq"2�B���� #3R�br� +$4�%�&'()*56789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz�����������������������������������������������������������������������������?���g�QIϘ9�q���4)]�P��8�ӁerH��kѧ?3)�^c����g<TU���A�7/��k�n#�^_�N<h���rk�.K�֯rFF�H�O�Y^Fj��aV�1���nQ;�Rq��V�4�P�Ӻ +`6pA)�N1�yn�j'�kn݁M �Ȑ`�^%�,��?x�>���i���mc���>0�v�|�JƏ�v��y�<F,g���M-(6�A�Ll.�f"N� ��������d�Y{���J���P���� �9���T���Km�eN#f��?��އ�ED��K��k1��s��%\~���!����V�w�Ma<�J�`�"qʜt>���_jv�t��<�PE'�{W���7/i ϥ�3(�{ +�6��%$��F��=��d��`�$ +}I����#n�O@s^g�����^骬��<SD���D(�ǃ��֪�� �fI銊[�c9ǡ�Z*�J����и���q�T����&�ۭv�2 �N��FH��Py�ZK�f��ƈӕW� �XQ��4��� %K�ǡ��`$��������bin���q�5p�0&��t ��c�Z��̬���,���i�ѹ�kO5@�cP��MJo`Wp�)�ڎ<��:�8oˊ�x +��sZy��۷���\�I��>`F3��mb[p ��q�Er*X��:nD��W7��9]��P��hZ����I�jB���I�&�K�v+��05(�sJRrweF�������]:�v���k��A�E4�5!����p�\� �/��M�9���m��z9$0�� +����MX�x"$1_ņ*���0�3�=��5��۶)�d�n=+:oZ >^�?LU_��F�嵲v�Zƌ�"U!���D�x���繲�~yc��2Xx���cu��i����0�b%��.�V�c�5�$��Us,<>�� +�z��(̇����Z����������N����h����F[�5�^fy�5�O ���_:�V��ai�����D�I�F~��鼤�1�**���D��ei����������i"=��F��#:��wT�Fc���_���$R�m���T3�4so�H<��FYaҬ��������3z�]\�X��Я4���~|�}������XV��|�b�<�GFooaY7�7Z��I$�2�D�z����6"��dz�qƴ����vo� �%�tQ��*$<p<V�\����y�r7BV楂#&�4�h���� +�i�2E�TST�*�$�*U�(�$rj�E1EJ��C�52�b��E4��S@�@�$1J)qF(���R��;S�R0栝�\���듗&�\$Sگ�q�Q��5�ܥ���θ<���U+��04�q>$��b���\w��g� �X�1�^��E�9p2q^II���0@w��YQ���eO�VX���*vZ���8�{R�6!�ޡ�0���ۥC2���� �}�6h�F<�z��v�&>��"L|�E@�^b�Ҧ���0`pi�++/j��1M��Båj����*�T�F>�Ҹ3����FF�֯�v�31�5���%��*��]j���A�֪=Il�D:T(�x�*Η��7��Ժ�kuc"l�Ȭ �yLR}��U=,#�q�i��^i��n��R��E�+yez����i/#�����M��u�*�� ��:��.��|�o�Q�I�B��� 渿��y~�>�5Ջb��c!#�����t,���U�ҫD�ˎ1Vr*F�%�})ǭH}���m���L� ��W/u{k'��t�_Q��Mp�G�w�{��f���Ҹ��x{Gօ���%��a[n��_��TwLOc�> ���}^���e��x�b%�4�L���j�Z�T��~�s��������2?,}+����������F�<j��^�o��������������5۹\�#��Z��i�5[�Vv�9�j{�����r�F��}o�I��2J8�?ұ,mlo5�ŵ�k�������G��o+��=���������jz[�<��v���>�>�I���5��7eǑ;p�R`3ǡ�_j���g����݀B��$wC�{u��Z�0I�x^���������G_Ʊ���n��=���~���Ec%*o�i�&���Ɠ�B�EX��j�6�i]�<���kN���n�R�/���ί��Y�u� +u>$mO^��&�u�(g\����ҟ6?:,|h�Z��y�8��ƺ�����r=:I��xG\7$~5���x��f���)��b��Y�������y,q����VMEHb�n2*WH/9��x��/.�����7q����m�Oz���r����ʘ��8�T�1�� ��J;18��/��I?�BT����T���I������������G�T�%�E��Td�%WP:� eM��\�����Ձ�0P}*��B��x� ��EF��v2�|-nO��s�93��U�Í��7�=��] ����!c�I�����G�Ҕ`��Q�qx��6s����:������eI����Pr}v��Z��C����N����a�E���f���pi~#+���=�T&�������|c�W]�⣐n�th)k4���1ɶ���ė�E$��*H�+�~����������eCu4��%�A�8���N?o�k�H�x�K��:��IO�o��W^��TWp��U^)h���W��g8�����o_D��MiZNd;wUi���B�V�*�V&�q�q�Oԛ1����V}Ċ�''���Ff?,@����ƚ�JLq�s�G��ݢ���w#�d��S�Њ�FU��zy�U0�7<��ݺ~�Id,�2�{�U,-���:��&�b3�3O3���JYϙ*�U�*[��{�U���>�����u���xR��S�{���z��+�I-"�9\�e-Z��H���k��!�N]���R�L��+���d��\����v�z����lĺg����˪x�A����X����נ�+�0�kF��ݣ,K1<��ަSQ��R]GM�Ρt��(�9p����WMVp0 �{Uk�T�US��T� � ��r)9J���EX�6�)��RqK���,���2�W�H�l��h ���r�̢E���Z� Rt�2j$���V�'A�H)�*E��: +�EN���E"�j��)����E< +�D�(�R�L� ���Hx⫸�5`�3���ˆ��*��du�]�Hq�S'��jϩ] +�%y�EA&s��)�U>����ա3&�/0�#��&�ձ����7���w�/n���8���2��� +,4w��o4;y���ف~N+Ͼj2\�I��?�z�e`���= +kQ�Hm��4�M���x�ɔ�枻�wv��"�#/�X��Y#�V���P�Ϲ[�j�Ң�r�+�j�����q��y� ��}l�r"B@>����@3���SQwg51vF�J|hU� S����m�G=�8ɥmB��i�����/�j�7r+����k=�u�Ґ�d^�=hW;k ��7��+#O���nA�X��Q#��9���1E���+�k��9@%W�L˒:S�#�\����.����i~��o�wKs��S�s�z��N��N03^5��.�1��z�"�������i��c��]L���rO��<�_������c�V��}Mj�'�Q,9����zf�X`ۏu ���H7!��1֗G� ��OJq��LDC'5^��;�|��A9}EZA�Oj���"��$�O�0<s� +�A�+�:+��32=i�[m{²��b��n��fc�����u��Zҡ�ӡ���&�pB�h�g��_j�Ƒ[x7�:7�4ҩut�[�А9b~��R�N��K+�j�I�L�q(�Fʙ�]?�F��X��B��ec2/*���ּ�y����2�`d�����&�V��k)��������Q����nn�ZN���g攧���o-�d=��8<�ֹ����e�Z\H2^,�n}@��WV���Ϧ_B/tY�>C�-h���Ƿnޕ��h�*�ˊw����������T��� -��i{H�M��-K�x��X�v�3]=��wu8c�r^"�M��GO�f�5��¦Di1�Lvc�Kuyk-��2F�u�s߃ڹ�EoC��Vb����\DɶA�ҹ��;H�[ۨW�n�}j�k�j0T�-�S�J�S��f�:V�,�L�1[k7#��߭q��/�HU�S�j�`դuŽ�W +G�� ��w��`�`O�[��RY؞����/x�I-��U�H7n�e��WU��M�YH��~�kB��kq�pzWjm-dm���.�)kW��wG3 � �JJ}*w�VP���輛)ϗwl#������C>�nAx.}����o�2���r��HB~��{~�<�Mϒ0z�.�.#�|���Yk�O<���'�*��@�OS{��XЭ�V|���=�r�ͣI�3�jЎ����ŀ��yz�WY!����?�i�+Y�9�{�s�tj-�G�6wj��0�z���]�l����ְTe}n�{��[8n��S�<�qW�����$�ZL��Y�&��|���\����T&��ǹ �4g�S��������*$e��� +�[[1)!���̤��Z�s��� +���#�U��X^���E�@r� \{�[˻e�*1<��p����U�%O`����?v�{�5q���3!��GW%�[����F S��Dr�|4�n��Zǁ�. [{w}��VSN�t2\ܭ�z(R�~���B�K�Yl]�Q��&I3#�ج�j����u��Ͷ�c�fy��(�OAO]N�Zi6�f�%�|�����V�_Jh�d��!�����>㻦N+R�U��d�Y.�H���s�OA�ւx\���W���?�oð���_JX5�#E g�(<�P�\��P�>��Bo�p��v���주���]�w.��������/��K�� +�4�!F�����=O�~f�.e���3^M%��uʯ���AW���:Ox<�Gp�*�*�-YN�����ee��C��>��ծ`��L�l.{-i[�?�1LtzUz�[Z0C�A\R��6�R9��ZIB1���zV��G�AX6.����wߗ�5�4D�� �<Sc�<�&O�"��pj�ɸR\Ʌ������O�l�T���Uс���MH�L�T�T���:Ut� V�,�H�j$5*u�,�*u��XZ��J�Ԫi� ��L� Rbc��њbM�&�-E�RqT�_�S;Vu܃�ɩliA���Ƨ�=���g�U�~#ܽzLr����v�)�j�2Fx��$�&�o�8�c�q�G4N8�H�v�1�Z�ִ��D�FG84m�o������[1 W���CW�Z�t?���6����5�M"�+v�eգIl���� �$P����H�-�}��}�U�C�] �+��j(���!@'֭[0X�Ө��]Ir�����|Vn�1����zX别�P��+Qm7�?.:UH���V�J�����qX��;ą##=I���C��6�T/y��������ғ�ܞc����Ɍo�����)�{�]U������õa���"D� +�T��Jj��3�%�C�a�T�D��ǐMg�*nKx�?�����2X)��h�Ћ�ԓ �;S� �h|y��0A��s�w� f�Ie�p��漛�$�kD=N+�<~��FZ]��0=MyW����Ֆ�ޡ��=�����m�1��Ne�>_Z��ۤ[t�*��4� +ש�AW /�Lޫ��T�(h���-{�r�#���\�s@ �W=V�oa������ .��ӭۻ�#��Z�o�.��Q����tr��k��/�?`�� +���#�Z+�r���=q}�ŭ���K\�d����VU� �j����b�����8�'��ګh���ټ��NAk c�H�3I��,�� �u�$��8��A�Q%Х�.��-Ma%��{�BTVO����9巉dYl����ñ���5CQ�z��S�֢��Z<�`�=.��w,Ș}���8�K����J��`�Zf�8�dh�화��������^�:-�>R���������km����`�r*�MI���L����+K��dS�]J��w��`��v�ַ%}v�L�ּC�ǧ�&Vt�)���< +������5��f�6dA��B���w�E1xZ��H� +L������ky?����j�$�b�7���3j�,�����*b���zנhS��&=_�:}�`g̎��c��B�`� UW���Pۣo�%��������7�t�VL���3i�e��[��c?��\�òH��|Q������� +��2�(����?���zM�B=��0��~8�U�-$K���i�u�-�_�2��kF��E2^�W�E���)���[�q�+��Ry�I7�?�|���I>�'�k%���������!G����=���o$Ҍ�ޝ��~b�9��(d�s� �SC�x2��mKL�_��+<�܁����+{�K� �|�O�95��2�H�8���K��[pI�7pkv�~�y��+z�2*�s�maW3�A1�E���^�/t��YG�@�|�3��N�v)ʜ��:D1��c���N[�S'͊e?���HyI%�� +w*l[�%-$���@E/�-2�ƫo_80 �ҩ�jtB��R&�����H���:W�̀d�RG9�:~�?��-2�Czy��n�q��&����9���~����Ќ�"c�ˊ�mbS�����J�[�����E�/���;Tf�������N�Z�s�=.����=�?�f���OA�� ��\c�4*5�Q�SGM�k� +��څ��4i��c�.��� +�ϊ����s�-�#�o�����ֵ,��*��s�ڤ�2���O� ؟�ZG /��u�kɩ�HM��pOA9�zU�>��z���D��o0�]́�f�C�y�}�����b��7SpO����p��uY�G�Yڟ���V��N:�C�&i\h��gx�ćS�S��Y�3��~B�O���#��1���d#���ɬ��F�I��'�fO�GZГ���$���b��J�R�� 䔷2䳿ԮEֱy5���Kn���~��<��a�����_��t�渗δ[{x��gq���+����+!�1�GV�%U�6-SH�YM��k��#��ֶ�a�$��y����~�Rd�>�`�E c|ݤp�����M�5����}����:��e�:oN�˹d�2���f�$A��칧k"[���A������_��ztC0��R�W�mdd�l� �V�V�/�8����8���v�V%�s�ֺ[����b����XȤC�����y�kn7 +�fVF��hiڞ�n��Lv��!5a Q�e�C)U��Zj3VP�D5a h�-!�P� +x�PֈE�52����F�IaMJ���S�4�j�jv�`X HZ���M/N�'g�]�6���o�N�簤��7O5��4��z���s'��/aV�O��f�r��+)�Vc^( +�9�S�]�Uϻ��l����F���+ ��U#�+�5\�D���GJ[�`�{���*X�f��i��'a"�Yz�U}�ݏ+�G��=cT��� +�D�3Lנ%�ͽ�p�78Q�+V)f�A��9��V�zjq:�µId�h tpڥ�;��B9V��F~Rw��Z&a���Uؗ&�6����%\=��C!p7h巌~� +��V����M,I�*���v�A6�7��%��A��e,��� �OЃV�'�k�c�2GZ.3>�$I6ʤx>�Z���ʃ��J���Y.R��zV[b#�ه|�{ՋV�2[����q�g�S4o�]G�5r�6�/)e +������>I�f�ߚ� �h�i����� P`�y�U���"Ƥ�]|��w��Ԗ��g�Y�}��P����"7�H��f�(�3�o �LR�эr#��_F����ᷚ�a�����_�^�ⴂMV�l̼�q^w����F?���:�+������'DM�d��VB�械�X�=T�����S1�&A�R�Z�/���P!��Ͻ9�������ڞ���,YHmm�=C86��S����ι�䢱��a +������:����7�fa��� �)��� c�7��s�Y[�O��~�����lbx����-�JEW� �S�+�M�q�W���g��֯9����ǿ9?�w������s`(Z� �T�;�zS�\�MO@9˻Q >��+k�h��r3ZR�.p�U#�ϗ� ����îm��OT��m��82@AP��+�9�<םx�N{���)y�~��#=��-�1��ms^5��YG��UR9�;�<���� �ّQitpj�,��Z]*��$����ݏaW<G�H/�^�K���eIv�!?��8�5�|@�n� Ƙ[Αs�8Ϩ��u���i�xv]CV�e�y�V�1���Bֶ�Ir�&ܵ=7Ú�_��d�VD;N����E`7�����O�{�B;�#d�1�N9�@�+m������mt:���|2�~�93�U�է<���#?����VE)$NH�%q��q+7�n#��hx���4���V���;�#���U�,��Ԗ�eA��P6)���r��#���U�"E����L��U��D{8��[H����� +J������ע��v�c1\���Ё��@�Slj����Ā�����"BtQ���ۆ�u���ǟo�O�Tֹ��MRfv}jG,K� + '�������U�[M�.�%'�[I�?N��֧�>�w<��5����y�G�a���U9<�9�,�!�`?��K4q�$i��q��� ԑ���f�f>� +>�.�>��y4��ٿ}�Nq����Oe��C13K5ҕ*kaI����W��%�6ז>�����d��Y'A��_�)}n]�~�C�#�Z��1����A�un��-�l��n=���B��)"b_͐�3�+2�P��1��&%����r ��x������k�����8����m�X¦O�e�*�������$q�� +r*1�ȭ 9�G*�dYR=k�x���6��� ��ojdbLrbM���lu;|�r�s2�'�� ��mY�� q�CzV%�p�,�6�(RwJ��k5V�/�ƥ���%ŴѤ��$�c�j˞���NzQl�"N�ʄ�2�U���b��8+���ִ���m"}8�����%���p���ZI$����iI��PZ�1�-�I�����_������I�V�ks6�fj�5�7��.}}*��>P9Q��d�*�0@�@�ys�@a#2��v�!�2y� +�����U���� +8��>��Ի�q]*/���4ט��m�S��M*|�����aD���ёP��W�p8��:L���f]Z��]���GJ�45 �&�ǩ�a���+����u���{Vn#l�-/g�?)%} tv���v��eϦ��P{i#?t�R�Bh��^youun~IC[6�������V�h���[��Z�-��I���>����T�5����R�U�F�L%_QV�6.�b�����w� ��S���|��{�s*�Ʃͭ[� +Kj.��2`T]�˸S\���ę.��j�-��fGc��.k��l^�[�Ka���#�y<ɉf�J�gc��ӊ^����+a��z��@�oJH�ڥe�b�! b +1���MT#*��t�`�EPJ��Z%roa�s�ک4\����[P�~�H^��wB{�ciؓ�W6C�*i���`p:U�� D�l~�V,��eF3���g����X���cN[$e)�D�C�(�D�Hz{K��8���q�Ve�մg�i<�+��Zũ\�I���p��Fn�N͚��1F,�b�ɫ��N����g�y��\���54:�Q�n"G�@��i� +��CUc��.�-�j�HӀ=k>��������\�%����#�+ҬCa�^@��s����D�ng�t�+lek�uV�X��>&�Ɏ4f)�*���|�"��}���T������@9��ӄ(�wpr��dI6��]���'���v��볯�0rH�A��e�p��*AV�d���RQIbt�QN�7��f����|��s��]���QE(����ֵn����(c�Z��cW�qda��U,lٜp�W9K��8�-�1X�e֡kp��G���z�0kى���MX��1����MLU)r�8��@ƁX��&��ҤP��C?13+�[���������I#�y���sb���W���Z���u5�X�7� ��J����e�H[���{A@[��.-�{SH����P,�s�{�3L��c�R8�J�H��mH�*�=���~�sSA\K ������TҸ\��r.��Ynf+�������<{#����N|�[��?���]^�s���v�R>�gp�ǟ���?��)��9T�tl@装���mƎ�N�K :��1��{��C�jB�C&������L�K��+�������#��y����V�����O�ʼnbI�K����U�5X�`�V�!�ܼ�U�87��0{g���\�����CQ���*1�tf���#�o��]#�qh�^��a�<�ZY�#��+��t/������f�TzV�*t�����^��-An,�K9�( �\��3�' ��_����.�&��O��V6��1��l�+�5 +G֢ki~o4`�����6��~�,�b�{�������J5���C���>���Ѐ���\���F?!R�h�be���j�j�h�F��Ob�֭�]�O����+(��>M96u+�b�1� \2�������q����WTX|�I2F����Bi���n&��Y��v�4��?�,��c +1��|@ p&|�ʎ��P_kV�]}���s�v���U�GA��L��Rđr�mp{f�%�q}̋+Ŗy-��c4x�7aFk����HD��x���"���@�@�?VR��f�e�\��5i�C�`���^��=�oQ� ��ǩD$c���k9m��E��n'}�)f���mn�U����8�o3(������Cg���y����~n�LVv��VA,0L��yg�6��i<E�+=�� +�F6�FG�tQC�AZF�#� ��l��6�֚���r]��+%H��_;�-ɫ�@G1��{�Z��}g��m���y0�P�U���R�{MO���[j����TX�s���pd��E�漯� 5���V����C�8pG����O����V�绚��o��x���j1iڣ}� +n��.=rGCCi�:��6���G,S/����_�h\9����&S�����G�_ZBga�Fuv�2���8�خ�_3H��5�0���aQ(Y�Z�q�qI+�;�$��s}m�@L�F�~U�ҹv�}R�K�I�I��f�:�*������$����m��:��Ұܮ^M*7�#�#�0}���:��W3���bv��;�,hF�1n���Ev��"L|��`���&e&u�_��bjz���|��d�k|�1�##��S%�-J�ʲI7 ��ު�1la�E��3��}���.d�T�@�' ��ct�mx��jx늯�[ژ��hp��y +}�Gf��s2�B2(o�9=���o�3�n�4�1ZF~gmϏJ�m�������svD�<�"���J�f�WI��i���8�x��!� +qQ<d�j��#�F�v�4r��.���ҩ��3��[; �j?$�3�����9��Ē�~Z�&����t���a�9?)��ϰsǹ�M�+tNM"E?-wF۟�*i�����v2<��fN��E�D�+�{4a�)���2�ٴB���I�S����^���u��@�� +�o��O��ɬӞ�O +��4�a��S%���E��E-�|m��֮æN�$�,H��U� +�Qpi���95{�DQ�GJ���7�Eg,�mC�Z��l� +� +�����~�"4����tv ��8����<Ȃ8�ż��8�U����i��� ����,lm�H(<keI-�rl�a��P�K18 ����֟�n`m����4�9B�����Λ�Y��+���d����E�e8��z�tZ�e;Y +t�*���ܑퟍ���Ei�����r1�cҜ�����S���(wd�Y �e�����EE�k�*#�5��\�3A#瞽)��r1�=)�EF�+��t�I4�7�k[�6�T�Ӭ�EF�px5��X`���L��;���T[2\"��m���m!l�G�j�(�O`;�c�p PC��}=��*����q���ov5d\����2g�����+�C {���h#5�aw��x�L�,�{n�4s`��>��n��ݺ���ݚ& ��zVu��́�pA��ƍ��f��Bh�����O�kp�yQ���瀯;�t^��SMk6q!%8�AF��GpY��|���ּ���J�O�7r)�����|��J���M���21���w&�eMQKH\a]y�QӠIn#i3�F���Z70��|�61��T��Ct�C�ؤ�kS]�c$s��rqmV�-a֫J�j)��&���@6�^T +�{W��e<߈��tc^��bϨO����q\�����]��k6h���cZ��?J�N"Z����!��|ũNX�1Y�)�ĭ�����.�p��f��7�t'�eV�]�'�/��g�<[K ��!�M��|�sq�̊��-�u9���E�~��6� �Ν�f�u���{�db����B7~yc��k���4�۩M��<��z~��ޠ��-4��{(��[���+֗�Q� +Seە�6�J#ڑ�X-BD�L�d�Zy�T�)��A�� +W�7��V��X���g"8ԏ�=+��Ta��;R��-�֧ 6"zf(���$��R���H��ͧ�mI��L@�GG��b~�k����X�_,cj����A�O��e���s����� +��u�������g��ݻQV�{Y���m�%zz��?Z��V�Mf�wyY��do��( 7B�^N��o*�v�`r?\~F������[N����Iw�����.�UT�%&��n�7��ew��Q�!c�ԉfl�Z4��8b�b�֯\h��"5��r�ەF��O=��%����\�I&ʏf$����뻹�����n��"c��Z�W $������)�N�x'����g��xz��cG �P�rv*k�����P %�3��`��nCķ�aXn��W.�������ԭD����d2q�`SM��ڝrk�������zl�¸��p�Zˣ�;>��.��Zj�5���.��2��gȒ2N=���H�"%ژg#$�Mh��IQQz}�ūj�#�n�"�cI���w��X�+fy��3�_�T���Q*-��mǢ�Zڊ�8#$��}�^k'6]��As#�{�S=@��S:�8��[�r]�'�5��ܼr����A�< +ƽ�����2�' ���FWvbi��[ m�!�5�7ͻ��1S[�o��F���Ú�E�-&�H�ą�1�} �ZAm'>dM�7�Ҫ�z�+;;�&��B���9���j�Ωz��<��E�\���X�C w�X�ֹ��{y�h�5�R8j�&���Y��!}�+m��;�����u$���h���.W�=�]e�A�N`1����Z��l��VybA��|�dӿF;����=��L�I^��5�I���Hb%Zs��z���rF�F��z���՚W[; �H[;}��4��^�G�ʊdH�#=�����v�Apx�o�iZ�DQ�`n�s�WY���p�a�8��s�]r1xl��2N�r8_sZVP��ד����>���ټ�=��ʻ��ֺ��eX �0�e�U{&�!�-̋��kƹ�=[j��R�8�B����qӜ�ȴ���YK��j���Q�R3�-���՞�R��8�3E�-P]��"���� �|�O�1G��� +�.�i�Ac[��s)�$���U��#���VT��>��*����O�] +�CRO��e�<�=�&�Q��{�<ג1��5�|�U�%�%ɳ�7h� +a�N����psHNj�I����A�@85ϗ�=N .d��h��mB:�4}�F0y�2_ƍ���7����zQz����r�҆ph��3�S��Fw +焍�z���:֕�S�!�E;r�έ�/��J.�֥Ӌ��%���qOCF�k/��Y�P�1Y�=7Яk.���9F��q�iZ��� Tpz⹘�Y������pѶ�� l5Q�&�\@�H�a��ڞ��+W��u� ��79>��-5h�"�.��sI��, +]�ZD��kX��zSnVE2�3���;T#��g�G�,�ۜ��Y�U�r;�-4e-�A,wP)�$c���\����EQ�C�Zcf=zU��h�<.x�p3�S]���7Y�Tǖ��ǭ[V�P!�A\�U�������A���d�#`�} �f}����$�Ó�UT�����֭�-s�X9��3�~���H�J�tL�\yǠ�q� +�&�H07��Vd6�9 +���ֶ���*C�.V�]Z]�:21 +��/�'۠����P,��*��y4崇�ʅ99��\�ǘ�F���ZA��˩���@B�p9%j�������8��9Y�:�Bw(���VR<W +N6��洖��U]|�O�4�goݖa�#�S��h�c-N��~��=���ΪFF;��3&�T1 æ{TwWqƅ��1� f�rڹ��(����֟r��>K�#�wQ� +�'�@�*{��3ǀv�H:���d��U�(����69'�M&Y&���`�Ȩo�I#e*OQ�֨oa& "*��ѳ��CPMc��2���� +]")���P����o��.� �i-�'u�ܱ�qP].�;�V�+)#�W�:��湖��Z'��^cw��+��Z�g��n�V���[A�����"�?���ŷo���cO�f���ه�x늤X��BN#�UeURWg��3��k��B�2HB����2��zU�4�Ԭ�`/�@ϮÊ�nI�|B�in����Dxt韯'�j0h go�m`iGw贶w�R�����~SZ�DS���*���iu��,���`���Q�Ԥ�? ��"����rn.��<���z1!������n�Ϻ�=ɿ�`;։�>�Ң��o��b��og +��2٪˨�L��s���VT������y&���Q�zS���� +z��Y�K;�#\�Oa�כ�ŚK=%�,����9����U�x�Q�9ⷕ��7s�}����*�� ��m�R�����A���s�։�Ss��F��V�"���v�O4pGk$�6�9�}+�����qt�Sȋ�'��Tz�[Ã$�Y�I�gO��V�?�?�sR�)�i�Ԓ��'�t�%�7��&���.L]-�#��H�~&��?O�&���f��]B�7�L�o/���nbǫ1����);[��郚uj'�a{�͘OT��O8�A,q��2�� j���������Ȭ u����s"�+�H�2��q@�� \���Ͻd����P��v� �Ojչ��a��s���V^�=��g}����F �����Ы�V��5�k ���s����F��mp�ɋs�J1�];C�Ϲ�HٰO=O�5�Ov7�s���}�6r>+��Qjj�����S�J�n��J� �<U����<��̲���7f�)l�>�������eoih$'X�=j���oy�[[qԹ���U5(����AA��DYE�"��[��`�HQ��N6[�W/y��; 1Y���Ү�.�mlmⱅ���s���F�{k m5����.FF+\�[�+�<q�qn���;������p;V?ڒ�`�d +�r?J��,N��p�rSY�1��n%�ڹ��5\���>ƥ��.�;|�n0GZ���i�K�P"��l�?�m��>R*�uF��p���m+F�`�Ǫ�<�[�b��U/ҩ��R��K.�ۛ�����"I�ZKS��.G<�*�˨y���x.�����r��i�?ٷ2C{q! +]H�q�T�p�3ۨ������隖�m,w34h�<Ҵ�o ��"�0��W��p uR�N��V1�h�Bݺ���ߵK$'������jU��\�\�G�)���~����ƻᅄw��i?#B3�"D����S]X�~yL�;v�^�T���Ғ*�y$���7s��\���e�j�2�o?ATDG���y#�!�F�f�c��#�)@�r(��ly4�rx�$PNy� !�zd��c�jB3ޕ}���{zS�B�)q�'>�t�(�(��1�=�L��v3���(���Ҕ��N�}�6��h�{b�(�`T�ޗ��B)�}�0�j�@= �u�LC�M1g��zu��=��v*��<��p�-��7bq���v�i�3)�X�v�2u&�����m�\�x�#�zŴ�mͺ�+�d pM!Ƞ,u�}��qq���N�L���A)���-ee�Z6��չ\���j�s���UP����^3�z���g�����⇌G�ֹXu�Y���`O����7IavvV8#��BԎ�̈́L�� +O'ޛ<p�?��e�������l%g��HN>f秡�6բ��c�\�ga$����F�.]� g^�u6�(�-ޤ�f2ǖ8�*����^9��J�]�DX0*�D1�Zv�v<�qR3�ܓYies! ��NG�Wlm���|�Wv�J�ʧRw&�.'��cDS �ɬľ�f ��OoJ�ȅ�y8��mm��-��?/'�����yf"B.$����R��PnJ�����P)c�[< +TD-�"�pCT�Vf{�pz��9�O,����=�YB"���c�F(@a.���;X��jUA# dTr��V�l7c�I���c�����R)lf����JU����Z�,-m�6�ӭe���U����n��W�8��i�2��J��6�F�=��U��kw�1�ă���e�g��@GZ��.C����p�*Ys��dWc<�^��m�o:@w�J��=�~L�p9L����1��YZ�����b�1�k]H8*���%�~�W)��ڴ6R��X+V�ݯj{/�5������*�����'���T�e�d{d� �nAe��r����m�N2*�D�L�6�M>�h�p�&����t��8���f�oq3���U���e��*@���{�;���\o�u;�w:\Ym�N�i;���8�@�c��z�ĭ +���ǵa���`�`�;�I�,�dݡ=��¶�SZnJvg���l-���P���; +���K�� +?�n0+��][I��$���u���A{$����L@)�#��](�T��Wl�\�X�%��㫩�cW�|9����Ǧk<��9�}�xm��V�A���t�i~`�^7ee ��k�2�}����<v4�p�,��I$���$��`�F��6�ִ���kt����s'������d��Q�j�.�|�͕K�3�� +s�ǁ��_����%�m�{�OH�3���q^�u}v��+4!���ʿ�s�WY�UkO�xJ��$�f�p3�������m$����}ިuU�w����Gߔ~Lz�Vk��)���l��B��?=�inO�h�R�aU���\5+��-��NڽͨL����8�=j� �IT����Wr#��`06�N��xЈ���������2�����hc2r��Gac,/$���ˆ��#Dq5���q�q��'��x"���G3���0�:5�h����d�����4�*��O3�}͓&s�U���]���qpO����В�HVC�9 P��l�V9��˞9�*����@� IF ��P�5a��[���ZAqt7j� +���J��cNM}n;�-&[fÍ��w�5�m�<ѳCi�1�� +͒�� ���P:V_�����.e���Y���f�7��Ҋ$Եnn� n#T^��t{����$���|���=CH��u�JF}�\ +�j��6ֶOo��U�yp0�n����h�i���2�˨�T�֟���1�tr:��j��m.~�ƢN��u�y#�5V��f!Vfg��=�$�D;w+�����Lq��TL��t=vK��F�B�a.9ǥv�֖�>V�����Vuȵ����*� ���V��jE���0Oʱ���N�*�ڛ�+�����@dRW'���\�1�9���֮�'Q艩5qM���sǵ�OL +괽4ZB ��9�� V��)���z��X���S ���u5���Bl�YK�3����w0w���%�������DH8�s�\I1$�$��R&l�ld>[�fbYؓ��lܱ�X�x�����z."$�w Q��8�q��RCG��|٧����N �U@�=��g�P��ҀJP֜��^�"��ݸ1�@����ޜGlR08��lR��(��@�CK�zS���i�pFh���iH�zS�q�@ �}���W9��T���y�x$�����I�֞px��H0�gn3��')�u�!�g4����)�^�K� c�N���09���S֤�ozN��R&A��i�_�LF{I��0!;�G�I�*�H�=)H�p;SY�(��\»&��z5kF�^���_�L��\f +��ҁ#)��R��:���wCW���Zv��O +�5c��q��k��u��B��B�ȭ��L�����O���f�t�8���~k�a {�[X�T �G�[TR��ܓPM�o�h�;߁��� `-檑����Y�-�,f{6e��ې��)��L��\��[V���r�ˎy"�yѩ����vT�њ��X��LSV��2�#'$c�j5�$��^=�B�����NI�- �*����1��<S��r�|����e�c#�~{{Tkyn�ӶNrZ�@���+��aG�ֵ� l��{�Y-}e�I=�j�J�J>=�KȨ�Im�c�W�_p�^�5�e�&��b95F���>�� +��gb��o��O����bxb��٘��։x�X��8����Z%�Q0�Bp8��-��b0q�pL���E�ȑ��.y"�M�_bHq�`q�T��Ԗo�qI�E��d���r3�L���$�9RMS�Q�JJ�q�h�v@赓��$�O����\��\�ڞq��ep��R��?#�Σ'��Y�7;4�Fy�+s�LX���\~����4�C�e%J�u�w�7Ґ��UE G֕G�õG0p�3R�LG�~�H-���"2ē\w�<D,#�3��g% ���k�~-h-�h%�R���N��U�Rڻ 8&��՚b��������ŸK{��[�|����u�u��ǁ�Sy'����@7Kh[�s��!�s�8�W�h�*�Ҙe��xd'� +�� x�L�, ���O1��1�$=��CZ7mɱ��ռ�sKk4m�p�������w�~��죻IP��[������+�s�ږ�~�w�20?+���Pjf� ���X��,v��wW���=�4�bP;)�X��Z�F���J�ڻ�8u[iY@b<��\���b�+�ևs��N������Z�g��@pq��\��4����x��Nɦ" �v���ox���_�Ce�}�I��E��ݣ�j·� ?A���77�G�9�J�����eH��o#�q�]0�e!��T[�����g��-1��\���\ݝb�J�:�~�,�{l)��P�n��T�T.���|�nO��1N�Z��p�I"�� +���`h�$V�ױ��dy��U���m����ԓi�jq .n�Fz��CՔ�ܙ"����yn�0�։�gK����̼��Oӭ��Cmr����<U�(���?&�߽S��{�����o=av$�`f�̶�!�DX��9k�"�[�E��O�د�&�n핀v��^��-;���-:b%W�y �)��Jf�� d�K��Hۚ'(�+V�!�q-��$Ǧk�����)���n�a��1���c�75�_�����^�T�x�=��e�Z�jrE+�Ke;�G����Q�����ɭ�F�s�B#�ִzX��,H�1�0�M1X�g��H��� ���W1�luk�f���r��C�=k6MB��O.BG�<�h���:�j6S�'�RDE�3�i�Dѫ}wn�����W����V=����M�J��=�8^q]" <�m�3�BO֭�A�w���Z���W%�3��d������8�m�����k`-�$���Ҳ�}q�E���`u5���nO�F)+#���Ow}qu+<�'�j��o�R�4���U�5q�ޤ������^�U\f���0�O#����9s�iF? +U�3� �S�rx�{P�c��@�L�1�b������x�{c�9�8A����4(�����@ߧ�J~)����sހ#"��ӆ�u��F������I�;R���\DX<�sB�����c�M.1�<�x��4�jV�����G��?��&�N0;w��Lc#�!$�S����ry���i1�N��}��H8���}� zԣ ��q�ޘ ����FG��q�0r}=)��^*R9�1���cL����1R��E!�4[G���0 �RA��t�F�����j'�Ѻ�ƴ����N�6H��NWAV'�Mkw-��Hܫ�ҷ`���ܤrKҶ�<���U)�.�nqЊ��g� ����a�j;�Y-���~뎆��;�;�ġ�~6��Ur�n3����A��\�W +��08��Zh��b�6��Gz����7'�R����:�v��ݹ� ��5d]��y$���b�l[0�Ccz���`BXF�$���k[O�I��j㹤�!��p2:�Vt�#�vqN���PT��~�UK)Jͷ�Lor�f��n��z�)�'���dM�+/�Fz�V_7Lp�I��ū��q��Ԯ�u�(T\C�ӽG�m�(n�P�Ѷ��^��DA$t5�6��t�:P��a0$Pcjͱd>^��-����]�Z��d�b�X��oCe��~=e�ˑ�s��>����vG!�5��D�0Ǟ�q^��J����1�ji�,��ȑ�j~3�`�Ԫ0��B��(�z�� ���qP��N$SHL�o�)BRA����)�I5-*-�d�u�W�H���g�.�8XsUv��>?��t8x����U�.n��������{��؎⾢�|!�ꀻ[��@�p�?�m�7˓گ��p�_��:�q�%E��������= ww�v���#�[s3}�,$#π���Z�~\Z�$Y]Xt+���M���Q!2���$���U:=���Wt�z�I%T_�*���GPkg��5��}+j2LP8��Y�*��؞���a���L�m-Ү�4ѰŐ��5B�@�ܽ��Jm%��Yd� �-�����Sm�N��>1}M:^���OG������8�ڪ�F ;M� ���P��O8�C��{Q)\�R1�<�7+���Y�hj>c�`ԗq�Kˠ��)�r۲+���\ҍ�ͣ-,-ԪF �(5V��]X�ΥS��U1�d1��Xw�:M�[� s����YY�KTe�a��zV}���YmF6@�3�[B�f�������Ӵ���"F�Y�#�JO��2�+�6mq���\V��C,%�0�Ry�~�e��"��*�퐸�3�����+FK���LbfG���Y�Lj-�U���H8,:f��^�KUI��݀$~t��"�8m����m�V�-��-O��=ҹk�"�mR;ܮ ��$����K)t��v������u�-�� �Dy��aҲM�Q���x���j��d��kf���+r�M~[x�Ϧ��S(� �}i���k1�D�\�!#?Z�е-a.�[i���Hl���[ �e,�����Z�qG"��X�s����WJ��wIr��������xl�B�NFI>�B�� ��\�?�^� +��#��g�I������'s\����x�q������n�,�U� �y�D���r�0�f�q�4�JW�>���(��w�F���(�ӃKڑA�Q��P�h �ci�rq�@N�8��l�iq��)\����;�ԻsӜzS�GQ�m$`�J���x�ZQ���g<Ӱ~��J)q��\B�� +�N�1�Қ1�zW�=�v���NSK�t�;���L�U�H�<(ǯҜ������2��;䊓f9�����4�#"��JsHy�;�n1���p)������@Xkd�q�jP��q�A�N�!>��iHs�qM�8��p�Ӯ(�9���=i3�����qϽ'�ތ�����:{��`SO\t4����A���@��O<94��۽��qM���7�i�sO�A9M��@ * �Q2�jbG�Nx��� +�x5��j���6�[�Ҳ�2q��x(`u�[�F.l_|G��%�����$�k*�P��M�=A�klo�3�ae�^��QOp(��D�0'�����H�F*H� ��Cef���t?ݮiEŋbFc�1��܂;sV4�����O�)9*B��=i���&6���i��!2c�3���9�������G�iAq�C.I략��"o��`�սQlӵ�o+���1$�����*��>������'9�)t��J|�T����71�>��]�8;��ҕ8��<�d��Պ��\o��^�Z�`�'���90�(<���h��ЖWEe��^��M� ����W�|)����S�X�k�> ���-��?�+��:r����?�%���t��j��q�����S����ɧ�ސ�zT �j�'���p7ϖS��&UeW���I*��Q�qB����枩��n�"��Dn�D�SҦ�5��@⡹M�:(�p�Nz�cC<�w +x�E^�����"�槔��� +��3z��~���;v܊��*�0 �*Tr�w{U�����Y��Z��<�V.�i��R֎x�Z���4� +�Q�r�T�q�I��t��VL�s��6�n��l��)���#����soO��e���ǵm�z��%Ō��8��s��X8��T��K��oio�y,�'uZ6їޠ,ÿ�c�O�5��v���r+u����`>��e%Ի��r�9!���R=Ͳ�kFI;@��ˆgL(U�yk/�淪�P���W��h�`�j���P��rۃ�T���bѮ����Uc=T`b���7p�p��l*��-[E��8�a���MU���S�˝�2OAX#[7�y/ ����FX�+���$�cF���s\����˴fD+��*W�fE��L��e�����>����;�G���n��.I���]�),�X�u�)onT�Bƃ�v�GG�ߒӡ�Z|��uv��M!ʯ�_S\��ԗS�s��Q�{�0�s����ֽM�[�~�� +� +��)\dax�4��i��Ԙ���L|��\ۚ0rM<.y�+��qǽ?h �4��.4� �LS��⓷R�J��ߍ9GzfpzqJ�q�x�qҞ� m� 9ǥ!�b�9&��2��}�kI,X!y-���Y��N͔�ٟ��HA䊻t����[��İ���m���jr�BΑ�n�p��b��������Ȧu4�%�,��Ҧ�|���c�O u4�hwFD�x%[Jp�=뱼���[�(��=+����$�D�8�v��Q�Y�LV�{&�\!#�9|���'1\���:9��9��*���g�)� �(�r'�涏<��'�줗-�n�ԞEח�-��z��~���jb�E�`A��H�m���S_y�݆_�q�=+����]��4龥9%x���hY�~�+b�f���}k�m$dU��F`�q�>���]��`�Fy�XRx�V��fq�q���ͽݜd�0��c�Ě�U�k܊xJ�����{��}*�Ņ�jBν���KkDža1H� +�=�t?۾j��a��rU�� 倩OJ���ı�UXd�K�v�����W��eTi2S<�z�mnc�d�]*ʤnqΛ��?J����r֓�ks1���!�b�8��s��}j�+9�JJf�29��)���ڔF{�ǵ�⋊þ�4�Npix�K�8��L��)��sҤ��88�ۂ)9�N*By���f��}G�L`0jb0>��3�@pÞ��ֳ�2+��YOS�H�'Ҡd�N��t����� r+�껇�T�Ս��IR\��O���0'���L�uf2E�c�����ޞ�˷�r2*Ɲx�3>�=t�}+U�f��g����fZF~�#���� չ��h��5`����J�R�Ȼr��b��k��������[��1���me9*W�MT$�VU�1�ڋX��9(�O�OBÁ�{���H�` ��}�1��F͜�����if{�o����n�k�h�[���s>"��m#�\� "x����`���^���1�-1�B�^�N��N��G��G�i��[������I8��' + =�'!@�<R���'$�ds��G�&�ݸ�C��q��L���qT�C +�Ec�95$h�0n��K��E�T�71ϭpDr)p09$U��ڸ*�q��LF[>��WQ�����q���Kuac���K&��Z�hP\)����)�0���ϥ!�ܚf�1?��a'����ϽFᕸ�S�����AK��6���n0A�+R����rڧ�ܮN� ��WlWk�~�� �Ұ�7N�E��4p]�ޡ�F�n�ݼ�{��H�*���|I�KU7"�n1��k��#��y7�5��y��R��i�zB@�X[���0x泣Ӵ��.�]�G�Ź����z����,0��������P�~f��4RL�yy��.x#��V���v�[�1���G������}�*�����{=&��k�$w��I��C��������T������������m`��|�u�^��sJ�n��ҡ�f�"s�W1�E��!�������7E����z��n�'��E,ۛ�{�(�#�ջ�����<�~00E�pMʰ¢��I����I�Ȣ�4�h^�[��8��N;�R��e�)7��D�٥����f�y<���X�x�75_�>���U�3��E��)9%��w|�<ԉ�!\�HE,G�Q���w���Xa<oqɮ�I���b\.~�:�ֹ����5�+�q�E.e����8.��(�)�;,�{�e�B8"�[M=RB�\ +�%�a��61��k�թ'�7P�G'�i�v<���� o�s[<�$h����Y�\�{�#�yd�O���������*��adp� �}R�I��,��?�/o�ֹ9�O*Ļ /c�R��Q�%[+/��r@��a{�Xi�g�ڼ�)t� vR~VF o��9���5'�:��s#��!�JF6��V<R^�.�w0�� �˟/�f$z���G̊ ��9�?�{�KDaw��<;�_��;럷��$�-��n��x����"��n{{�X����#�?:N$��.9��=9fB�J�s����Q���mJ畭s�������S4v�<�d�~j�������0�#p��9����[��� ۴�G9Z�d�8Į���x�3���J�%/��%�rX���k����ޅ����א�[�K�e#�>��L������}�V`;�ύVF�2�CA�{V�O�&ɓW�봟]�D�W�o�8U2r�~=qV��z�l6�jC)p����㑑�%_5gM���w�@�}G�r�ARv�y��:�����t�5}�FzjI�?@ڳn��12*��}�:f�=Y��m�I�>�=��ԗ�%�c$���=����6 Aoi1f ;�2s����{I��$��,u����&��=�r���#��4;e�v��8SIX��B�Nh��ԙu�2�8 +p�W^,�(e�pcf�XU� x�Y�d߶��e���>�׳�3����+H�l|^/ :&p����Y��(|�vM?T���!�����I#���� ��MQ�E�nA��D�5 �0T"�Nj�ټ�&7���So�:T���S! +��]z�\ݎ�%����N�������v��)�G5Z.;��R� *%l���z�H��3]�9�$�)��?�z�R �4\V�����Q�L�@$�����q�n;�zrsF(��u���<qO#v)��dd3Iߎ*Lc���Q�c9<���V��;�L�O�y�6d��T��j �84�l �@$^��=k^��U��q�:��Z� �kI�a�}N�S(� ;l�&m��2sޥw� /�>ݫ2�E��7�8�ۏ�V�����O��5��͐֕2~P"��<q���ݏ@jl�W`���J�bVg�UL<�JL:�s�q�U�y(T�7�⥉���0LU6���2s�S�v1$g�!����N`����n��OZ�`>as���G���W���=�rT4��~5m�ڮ>��w�P%����v�E|���<J��������:���(����(s�:r +gn;�YJ�rǞ����t��eC�2��K��R���j9�yȹ���J�@��U�$ +v����Bp*;�p����N�9��,d�OL�y��M�O'�Խ�Lh!;SpL���&����H�.G��F0I�ON��H�����8��L��AS�l�`E��QH��&B{b�$�N�}i��\�4�Rqڤ�/ =ץ�V���˟�EEso �,�"��QV�P}j�h�IPy�L�����#\Zf)�+�o�K4�7�r���E{j|���b[#ŶE�Jb<���O��Z��an�p��B/A4rZ��>;_�a�ZzDžt��>x���S���Ķ��:T�G�+���c���Ϗ���Y���#?3rk'�zƇes-䅦���q!P��B��&2Hy�wa��q�s��G7c:w��Ҝ��Q��8�x�n���cM�曻��M��H=ǭ0���f�1�)��P&+6)��߭D_֚�z���9�L,GzBs�" ۛp�Y� +M�,;w�v��WX���g�;�if�=���p&u�G�V���,��ݳ�)���W4�h�kOve�q,�4ș�pҰ������>H�Le�#;���*ŝ��,UU# ��c��a�D��@�\����ٴab��08,�~�#�* $��Ȯc���Xef +GMv�J��c��ծ�Oh�;�O�q�a��Ҩ�<WR�� �})i{ '�'�4��q���q>6�X"�����B1]m���X!{���ڼ����Ηq؊c��'���cFS^�"RKs���[�V�S1��|�A���V^i��D�8�|�8�r���@���4�5�@����#��[���������Eط&�o���H�E8���5Ė;���h��B2��x��=�L[�(�Đ��>V�����[9� �*��=E����:|RNL���\zSo`�:�N +�R3W�,t]���)9>�+h�v!z�p��j��u/�K!10����{}En�_�h���s�_N�)���[]��fH�e+��9�=NGsD��+K��=z��R��8!�G�KҴ�d���q�w����T0p��3ֲ5'$�=1]M����Ls\���ţ��A�|�����v��t�0��gy�� w=��I�3�� +$��L�g���+��-�l�Q���$��=��|��}O�)֓�#���gX�O&fa��` +�5�p������H�u���J�s���֢���dh�e)�Wq�Ӛۚ�Tyۛܞ[渹d��@ +���X�g�X�)T���ˆ�=EaM +ڻ�T���N�=��:�ԋ#F�I;�܌����&�=��IT�C�4ψ6s8�P����b|�?�o���jefIbo���0��q��9�m�����5�INU���j�ϒ�h�����>dA�������?���#�����1����>#f�K�͍J;';z�ջ��ixeR��&Ң�e�Ѥ��q�eƯ���;��e���������H!�'���V��͵��!�W$`�\��:̽�ƍ!;�*�?26�WB�8�60t��J��k��q%������uO �*�"����.�=�ͳ�k��G���WN5�l�ʹ�0�eW�ʧMEn��ʖ��+X��f����zV��6�H��Q�Y��Brc:�p�%�YN�[���@�t���nO��9����ZJ�p� `��^��KbNG �߭7�����b2��G�q�Gۆ�̜Y�^wG@��Ԛ\`S���v�7�u��H�=)����$��ey�FW�J��r1�0�rh���~\g�JGaLe${w��R1Vm�ꤌS7v��H�P��[�#ß����۫�#����+����zq[zd�e�I�ܼ��9���} 幝]U_r��ï��:CJ<˰7 ��Q��)p~RNq��J�a,6� ��ǩkr6��1,����MB���:���i�=���ھda�v��u �`�b +����1�-����6��&�-ĺ�x���!�Wkj�D�z���jI�D��=+�{���mXy�/�q�d����{�W̃����#�*8��Ӛ�m#t� �F��(Fi������rX�� ^�l�1$�1��H.��'�.�gҥK}��c���Vݱ�xB�cE~@�i�C�HO�Ӛ����cHǥN���,hp���?Jbz�Ԅc�@v�'�*��ƒ3���(���`I�R'OƜ{P�H�JIG�J����A�4/Jz���*��zC!�IQ�9�I�zR0%�?����d�8�M�1ǥJ����C��SBdAG@�Ԁs�V:�5�\��>���s!2�vZ�u"$:��2���c>���iݤCz\�զ��1\}Ӗ|���g��\Ӓ_߲1�������qG g��l �sL��SKSI���i��T��)�� �sQ���"����f=z�M�*�!��dK�9���zM�j3+�em�������Cjz�/��`��g�ϩ�����P�v��\ݖ�����X��BP`�` +tVW��B��U.���I�,�?J�������1#�,�����h��ebA��V�Y�����YSj}��'�CP\]^���p�p!���3[w�l˸p����(xԢ�����KM����v��R��S�u4j��"�ȝ�rF�7�tɯ-���tg{]5V{�̬�����S�]�/6��4v/��p|�#���W���3�a�$��Пλ��e?~[��������02K�3d< +��]M4p��6��b�?��mm�2J�#m�O;��=��v��Z#y��r͞�8�+ыI$�f烀��q d��P��WH��1^a�jI',U�����x�0GQ�Sw�V���?�4�D�u�$P�qK�2��W��Ҹ���W��{�m�@�����1U|GqӉ%���0��k"��2L��hԐ�>ՓZ��m76Z����Ɉp�dw8#���F�kQ� �!##�֭���3G" v6Nu?�ۉ��M��I!��}+E�wƧͰK�-���ab9�ӷ�ұ,/�¾����L�Gb7���z�j�hS҉;H��MCs�y+N���2۲C���+�O֬��C+>���#����K?�U 'fvbyn3�X��X����SC#199�rb������T�=��l\ɻ�^p{���������{��碐N�7�h� �lb��y����9#En�E(���n��E^��3n���K8�H#��Rym����;)#�i�N�R#0h��v�GR�2V7,g2�3�De'�,1�����Z[y�[�B�p��QSZ��2Ur����Nk/\�i�b��QQ&��<qV�c��}���FҬ,n4�8Q��@�漶�Ś���^Y,Zeݽ��75����j��Ƴf���*�ǒ����+I2�Y�C+��'��[ӎ��O����m⫫�-��+s*��X�����V#��lķEpsW6��ĂDb�El��}+cN�h�������Q՛�sV�5����쑠�T'�<�Tnu�Ǔd0J����k;F����jy�$�,c9⺋Oh�@nE��c��/�g���g�xz�K��C+�+��S�'ڳu+_���i��u���M{M��]D�oH���+��muW����;$��/ +���*r��83ġ��s/ p�v����k���� Z�K6��b9� ����[�Ɵ�yږ�*$��#wֶ�]�$6,��9Q�����ѐ���\o�L\d\��n�z��j��L���s]M��=�Ċ�c2HG˟j�����������7��2Y�9���V�*r�fEh�+"(�v���B��� +Ȼ�r>����b��x�kίuAi�j[�=��b������Ј��4r?��)� �u���jB�c�M����?��W*p3�ژ�a���?��;�]����L�k<TLCE��*�sZ��dϸ5� �ϥZ��0�*�u0� �vO �89 ^[�J_�+�1��ŵ�� g���"6u,�[o��s�4�Sf�yS(A'9�{�1wPBˌr��Q8B�y�A6�s�a���E"��)�*�=W��gW�^N��:WK�Dc '�s�"k���:��D�(��:���E}=��,�y�_1xXy�8�?�ܟ�_Qi�� ��h�R� =@�+�0���*yU~f>��BTy�'�g>�t�(A�H4@`⢸��QҜ�"���2�ff������$n�7��2(�{RcE���6x�u��(dK�f>�������n(NW�D��/CJh(݅�}h=|�ҁ�S���5,}i��@'�i{��'!{��N)� +���u �h�f� �`z� i�TeO��7���5nh|�p�����r&Oٶ��2�u�R"C`��~VM�O ���˹T���֬�d� +et\��ɬ��XCƄ�^�ֺ(�x�G#�I�v��^I>�kPr]��Y8A]e�h5�j�6M>W�I'�ID� ���� ��QG�y�����2�C�G$���<�#i�ƽO��ݐ�r�I�Y�*�{TQ�����@N��zM;J��G�u/٬����U��mlѬ�h�#�=���� Z�Z-���"\�GE��� + �%^>v�6����3{�8©l�1\ZZ����Yf_p�q�ưG@�R=k�A�1^��;�u6C��!;o��l���"���y�ɯ#�����1��zr:U��M���S�sЀ)�6D�ek��k +���Z]N�����#�#�¼�I�i���;��2�V����.�=�����<�շg?�x�]�&*���]9n�m}s�P���:�P��#�O�� '�e0|��T�����2��GeBr�Y����R�9?+78��=4g2�����Y�����Fʬ �py���V~�#y����$G��;��C��W�e�gw���5HZ�" P�Pa���>��ƻ�J0����h�5۫i�b�� �$�D�`;��ۃ\6�r�Jʧ +IA�Q\�5���te3�ʥ,@�����$ZY6q�=�j�;]��dgǬ��+Ǒ�Ǧ}qV�g:����U�7GQ�˛t��W��?5WFR��l2���mUȓ%���CP�&|p����k�}*���[[6(�ߓԟ��\e���q˵�i� 溙|eml��3���#�ҳ��1�X�5[+�Hۓ���گ��<�JrǓXp<���J�V;�<���l�`�@��a�"L�⫳%�#d������\嵭̠�&uf�~��$3�7Sl�Qgh +��Z�|=��m*�y�����@g���I�J���t-��G�^�HfT8�iq�X�r�kӮ ����7R�mSǰ튆��ƾcĊ�B+NU��'o6�<��m8,��u�&��o���QO�k�r��U�aS���+��OO �tl��Io!V_��m:�P�G+��CҹKK���9@8���ү��M혡�2����8I5�=���PzF��6�h"71�d���?�qL"Tv��F�C�)��帐�0zZd���ᑥ�y��ے~�O��iG�b������o/+ɱK/��V� Q��KI�Mf����,��s���ں�=2l�<��I:��i�Ihe��S�k������dѨ$`�y_z��-��ꚍ͵����a���Eu�Z.��K˫�wET���� z����iz�kp���'����G�Q_Vr�w�ll�}ĒM1 ���Ҥ�+�am�=���;����Ckh��v�Mr����R�Y���Va����GСf͋��xc����p�JD7Wш��ڵ5F6�]>�D{��']���ښt����O�p�� +����1��ɒ���A�kB�\�N{\-��ݪ(�!~�q�>����ܴn���'���k?h�H����ݕ��,� +�Xs�1\�vL��۰�J��]��~j4l�8�����>%���q�)ԓ�D�Y�4��6�l���ޭ"�F�ѐܜc&����5���=*e�2�7c�W��,ü�/ ͜W������K���(����<W��b$���q'�ڋ0\���ºӵ��W�9�QK�u����Z��=+*��L��AS��S�j�H6I�@�>�� +U��g鸚9�� ���s���[���#�Jcd�u��ZF�&�ȸ�֘�ӵJEDz�֘șu���85e�V��i�Ɲ�oB�z���w�����C����>��g����ԷY��E�&�p���5����P��s�]�FI������e�9����z�\���ǒ�����a�#���W���ex�g-�{�P�<��Ec�zw-���0[��5ȍO-\n�R,`��D(�����Ēm���J�WCx�y������Ofs_P�[F@��f�Y�����k��U� +����J�|��Sޘ�t���������UɧD0�z�Q�c��Ǡ�/�U��d>��$#��D��D`҈T#)V��4�ܮGQҟ�D��zԱ���8�&�t���H��n��R(�b�V��J#ҁ +i�sL$`�NL�q�JOu����HbF��qOc��#�=��1�a@�����5�O�4һ�1�K��mn2��V�˕]�i�iK%��|ݝ��WD(�Ɵ$��7C$m���F���<��g�á���H]�<d�����6A�a��0c�^��Ss�C��;�W�v�3?'�dj�09�Z롭��#��o���Q1E���;������6��{�q�qY�O��{)��ŞS�g��*�Ƹ?�r;�SK�A�K��zP��~iؐ��<k +������B߸���{�𥻻�ʑa��s�=X�l-�S�o�}�+�����+�R��;���T�N��:�[T&���~���V�ZGh#e]�:��h�+>0n6�����(���Z����nP�zr1\m�qC +IF.ijD%���b`r��0�}������.��X�:����?�|���9���k70A};VF;�О���I�������V;�A�m���.~\�A95��v�����b�'�p�9�/����f�F +�������$���S 98�?��C@��Q4��uZ����@��!�O\�b������XHl���������.�)pFrI=�+P��T���;�<��+K�h|�c��U~�ͳ��RWr��9$��ϯҮ�� Z�n���,j�w�08�:ڻ=<�����t�㫊�tG�7z�C�{�V1��K�;�g��W������j�7�B�V\}5�q��ۂp����U[�gD����A�X}z�V����[#�5/���KS���O6�/��m����ON+R�xkA�Ym���Q5��!o�S��jo�7Z��~���h������s� +����M,"#r:��s���W���\Eއ��Q�R�Qu���KIu���ch�\]�Ok#+ ��1^�b�W��TG3I��*����Hm���m�U��k����nv�IU��yA�)@ÜzSe�=��c?�uW��gfUX؝�G���Gz��),g��g<85U/{.����S�(�Go�V���������r@�����-��5X`|mrI\��g�z߀����#`���J�9���9��W�'�WâL��C��be�p9'�����R���Ep��G�tM������d7�/�$s�US܌s�]���Omqk6�i,N0�/�����]0���q��F���wM�������3��4����s�]F�mi�-�X�9#'��Rh�D��8*��wJ�ks�����C2&>�?>���s���8��qԟ�^�� m�.�8�W���[���ּ�]�zVU~�����tY/Q�Ԍ/Rs]�xv�bC��E�rq��\�5�|�bN0�ֽe/�K�Bc�d��<�]#�2�����^�z-�B$L�Fr��If�%��H�r����n�RX.h%N6�8��b��5k�������� �NJ�t Z���̐yr)Âx>����<~z,fr�0NO�5�����<(�F���\E8�n��Tqv�v:ַ�hF����C��l|_n�w�w0W������3����l�Eи?;}Oa��Z[|��;��^I=�^_�w�ιIZ�}}�\j���Wh�$���U�Hm�I"�ܠ��v�'�>���]Eoic �_�;X�ˌs�� c�YKo$�n�J1���\u�z�1���t)�E���s,� �1�����N��1R +�s^34R"Y���J?��xv"��c_�a� � � N3z�wZ��mt���q�ju���%IYI�<� �rj(�M$�&q�SGț�kԞ�� rU���k#�V��ǭ�|��(�ݏ��� +��#b�!�ps�\�0�ZE�S��*y�)m�lG9<d�Gֲs{��|�ze�;J�ե � �p0��I�X/�%��l�نH|��(n�5�I�.Vc%���hDBN9��F;k舑U�z���.@*��9�VL��滽�C����{G>����ڞ�ݑ� �9R?���ղ,Y�-Ԛ�觜�J�h�E3��^���o� Z���T�x�20�NT�Ƌ[�=Hn~�zT*s+3��9]�ۨ�'c�iہ�#�z��i��0�d某i��1@șI95���zz�w�x�Wn�'� +��<zU#�p@����̽{��.�d�����A�~���f��ͼV����UPe�1�9���sW�.Eߕ��L���|c��V:\���7��y����pGc\�v+��2��N� yw�_m˞HS^�tB��g�y'�_n�rުk�����;���������E|��U �.l�5��aS9�+z�"#�V��)�8-�����@˹G�U�8��n����GL +c��]�*H[,ނ�����Oj�'�#�T�O �<{�Y'h�rs�O҆�r����riw�Onj�W(�����R� Y�����.9K Nጚ�5Lf@���d����3�E�Ų���rO@:T.�p���N��P�$�E��e�ˌ�pҡ��!e�����ip¨��J��sp��s��Й \c�X!���c��.H���*�����ɄJ5@>i��/\� �#︃ި��?�#m���[\�ٟ%J�rz��22kR��Mđ�� ��Գ,��Dr��x5�S���H�ʃ/�=�H� ��x�[�M�f�dU�.>a��Xڮ �vR�Ŕ��9�;Q�q[�&J�~��(=�U��MXԸ�LƩ\7 ������%�"��&9<ֆ�&7�.>c�c&kb�\s�[��x�=�$��؉��W +���߭L�erTn�m,��qw���Y��?>��i�&#�I�k�E���L,lO9�A�[�n�8�\H� �ˑ�F6��Wz�}�OK��l�'*��l��ǿ�]�-��IR�F��@S��5��6sL�yҞI�����jr�������p ?:���AN2�9cׯ�-���E�b58sv�k��O���U�r���=�֮^���,iE�XI$����>}ȃ~䉎ݪz�E�����y���ݗ�|�Ҷ4�2�����89��|%���[^=�*��a���*kO����[E4}�d���4�]�z2���ƾ�g���s�<�t�m�XvG�dsP�i�ݤ$���U����T.�.-���&��v�w!�kX����{;��+7��Pxiݕ\�sȯE��H�#A�(��5䷒J5�2I6��p�z��I��y�UBIS\�h�$�d�;�vE1�W�\������<3y���ֲ��%�R�L"����}�p6:���jO��ܢ�L��O�����Y]�r��u5�i��� ��m�#t$�#|���3�U�c�:�a�y0���ʮKFH�=�J���KD�U������m?�5�~#�����흱����'�?�+���VG�R����O�A��i�13�"f��v8��u7W��ò^m�hQ6eOϓJ}���2�Kg\���`d�G�k����?���-&�+��@0�����V��-�?GZ}��2I�9N�H��=���[�1�����0�L ;_�S�����_hz%����PY�'�r1����CP�V��kx����kH��g�~���Dv�>�铥���F�&V*�ַd��oΒVDr�U$}�2=��o]�m.��啑�ϧj�mt���;�m����S�ۻ���~"ӥBb��:��3��9'���Ҳ�]�}'O�om��b�P�B���bzNgӊ�{[��;�i;�$�8/����Fpq��{"�r�ko>�,�� +x#ںo�1(BB*�' }+��T�}��v�ӻ��%�&ۑ����R���!�i3���:�O6w�9�kyDW������I��"�'_,���u�ۑ���z�oDZ]FZ��B����m��7�BHaQ��s{�����^���2{Ф:�u�n���8l����ڼ�\�s�y�<��_Ұ������q�85�+�U��=*�Մ��7�������F�,O�Vf�|. �M�Y�ߊ������[+I&1�w��8Q��M��\��Sۊ�Ժ.���U��Z�� ڥ��yx���D>�����;B�1�%-!�]��觓��S�c��M�~��'9��>��Q�Cx�-Y�kM��u36Kc#������G����G�5�j~�X6 �@9��j����<H��f� ������WKS�<�ѓ*x�RX��yI�s�T��7ų�ۥ�k���� �R�Z�h��]���R�cnOnՌg=�G*Oc�t=_�e�2�Ͱ�Gp����ҷ-����fM���7��W��@^�=kW�C�,֘K��c�} +������͝�1�ʘ��=in,VW+ ���:�}� ^�Q�;*�8t�i��Z�҅eI���z}j%-o���{XܵDDTp X����`�8#�X֗�i��� '1��3ZA�c���@���؋5�s���8�(G̮s���!�ː�O�CO�X��8�5}�P�"�&Gִ����bi⍐��ֱf�c�ҵ���e� +�x�_Z�Ԧ0M�E�a����R1q��~�l���k��yt���.XF밷Q�k���q�������T)l��Jm;� +����_�Ab��U��e���0������קs+�MYخG<t���5#�}��:�犠����JygNI�Q��ݣ�\g�Un�Md�z��L�O�H�8OPr���Y�$\���"��4�eHG��I2����G8b��o�Atr�Il&3�GP=��wمԈ��2����x�I�ڲ���{�>]:��^C�<��pA�-z���n �Ex��.�0�O�=���E�6,��Ɏ��_@��cԁ^�!��㬩���K��GPkz��]�.�'hLb�9��.���pH������H=x�ǁ�W���K����@ +T��8�F 4�e�@��p}�̠��)�������4�b�Np����Pd��� V�:LH�g>�z�I +,V��@V � ��I.�8o�d���^��"�U�Q����E|]�Q� ��V�|���D�1ʍ��8��A1�U#`8,Oz͝�!�����X|�8�Rym=���`K!����C��f������j�<�� +s��4�@b�('4�yi�D2�3��L\��O��'�F85~*��tQ�FzV���i�6��D,:i�Y�@�S<�2U�??J[ ����'��U�N�~�@�����GF�E8l���D�P�=ā3ʄ9 SQ�vH=�F��������9��]���v�9'���MgR��7�]��Vر�:g�>�V�AՍ�������[����4��+<C���_����Y +�n6�������yz}��坛j���}_OT�D�2m ��}k���] ���F#w�8#�m��QK�]��U�음kZ{��Q�d �o� V���7�ȭ��X<�����p+�w!v�X��n�X�A�ws�����g�Ȭ���?J��Bl�[�j���Bsֳ���cW����N��t��}�\u��ƹ����p���֝d$��B�l���Id�˜�}�{� +�2Lg~�k +��SGY�綵@��w�� +����`A*���P͐��}z�?۳�7j��Oݰ�qQF!o,$���q����$}�T���-��^�oo;>�?)��{�{9oe�B��pi��k5�T��D*70�%}���I<�2)�X��q�T۹��Wi�Bo�%���q�FA��t�WS�,Y~�F:����J˼�,[D2I,���ϠjkKk�Ɂ�99'�S�Go�k����v#�Gvbq�Xt>��i��F .FХw`���>�GՒ5� m���9��z�72�28���G�4�s*��;�OQ�.nJ����h⹝Jo:���$�J�7�Ϙ���䓟ʩ�����*�$�������)Ɣo�����!��֯G�+b�|��=�� +���{��mf$�2k{H����/7,���y>�z�3���m��-�-�8�>��<�iop�?��m�>��-`��݂1&��yݑ���BLd�*�Np:��]Q�鴑�J���-iW��\FJL�a��_G�-�E��,Z�H��� �&px8�����W�6R�(����?�5��Y]B�o.P�����?���Ճ�=�Ǻm���q�B��7�����7g��p�w��+�m�G��`l�ǥ>�c�0���4+�����wDsg�6X�'�����V�n�;G�钦��:ݥ����2=���Z���<wRg �,���W/���`�-Һ@y�S�+/�^-�Y������|�y��҉M"����&�_�T,.�WH�C��EK*M��E�O4�¢�]ƃ��R�A6�4v�y�Ճ9���1�R|�v:(��SD�J�Yg�ݸR��/Ӥ�ki^9ˣ�!���k���Yi� ����l��m��wY��y����3r9���x��;���˫��[��N���zu�^L��9���5���Z���EK�U'�R��e�c01T@����zT+����>�Rvf���� +$���=+pX[M �F��7`n��>��YZ�Y�H6NՃ�����`�Íƻ�T�� ��q��6Ӭ�2�X�P~��r�Z���I+���J���,ɲh�4���sY�ZS�&�/.O� +�z�pe���.��= zǃ~]jpEy�^�m�V(�ϏrzRxGK���B�����;W�Y<Kb"�J�>��T���m�]sL�|=�MY4�4���h��]�m��k�t���Y.-ݟ�$c?A^��G�Œ�j��d� +��J�Ő[?�$��7I��t�ҹ��kE�8&V�L���3[,`���8㯽[�e��[Llp�9�������O]^[&��O,ҿ�"a�Q�=k���Zt&��#@0���(m�:b�5-�ԒZ�8�z��;i<���Ej�FI�a*�pU'��Z5{2��T���.J}�)M�]�f`_ڵ��9��G��_c�V����V9�R��X���⡏�ė~|�N�@l�zǾ�O�"x��W�]�����*�O�:�z3��T��q��T��Z���ie�`)�r}[T��Y]�?ד�֭a[���GR�^G?�r{y��o����9�t�BG�l,ȥ�a�⦚�3x��?���wzf�}�jm�ʪ�v�N*����$�r7+3r�Z�9F��)i�T�QI&%���� mZ�2�YFJ����O,g����Ԇ�ʻe��2r+�ȒRz*N��Q�U�5=Ҭ�s��:Wku;<�!%K|�� ꅚB�:ԬT�ЉQ]N�K}�]J��o����|�hԜJ�o�Mf��(�=�Eb��� +���r��cQ$�b�Z?�3���S�\���g G�i��;Tc�Vm�a�f�|�g�zt�dr�W(�Ɵ�l�mR0�LԮ�W����0݃��sH%;Xpk���8�Ucf<�暤�6x�HG9��й���SM=:ѝ�%!�2*KC��{�r�����i��DR9�����w,��>�#��+���m2Hdp�m��;C�H ���c�xĚl�I_�Oמ��OƼ��I!�&*0����;�d~�}jj�Ѿ o��?�ּ[���?=[�z牮���;fb^f���y�����v���y��;V�E�1mr����W�1pk�~���w��v�U덃��&���"4��L�)��L J�dc��4�GҤ���q�ԑ ���i +�iO@}�ã}*8v3O̔��7l�R2�F:�ɦ�k6�3���+@3F�W��U��J�2l�)�ȱ� ),i��c�M��a՛�5"ʁV]��(���fw�`��*})�d���oz�3b��-�\�%�����G��H�)���9���4�6$��A�BN=+�mn�[���N�/-P�OQ\�.o���h���3���2W��Ʊ��P��%=��ѽ���:'��+J�S�$������Ji�b����D0o�.$���t�$��̗R�A��#V�����ʅ�H�S隤�xֻm�܀��z�顇u�N�E��K�,�d�� `8U��e���&i!`������pYY��+�'>g���.�Z�y�7˼�3�3[���M�%y3;��~[]C0,���O���K�Ҁ����:�3�y�ڴׯ6�i�U(p�w:���kV,�% ��S�\�ޒ�V*�zjj1��7��8�)��$3�`@v���Tr<�U��?ʣ�W;�#���M�Y�ȷE=:M鱰8�V~�˙T3���ۨ��8A��Y��Ґ�����8=E-���0~����\c���z�m�{fpEyS�&x[�1����9�eq�W~pMv��F�"��w?�r�s�l%��������.����cUP��\V�#k�.��TzWk`�Xd�?�;W,���Zs���Y� b��A�t5����>��"�Ɯ"��@Z�լ�f7K�X��d�=<!�v{l/���M��Q�����$�K�!Q��n�2k4vWh�<�y���[��p��d;J/��6}O������<=`'Y.�ww)�G�����Y��{p��[�I8�� +α�[[#l2�ʣ��?�\�Y �n D^q��U'|~��4��6��H���~���-C/:���.7pz�ʋٮ�30�J#��Ov�3�3tِ���so��Z����4mgN��uۑ�l���s�f�+ۋ���܂��l�6�b��$�O�g��OoJ��4}/Y)-�>Uӹ��c�q����V����f�n"�n�]-�m�|�,yPs��>��i����Is� +&E��y=��M���c���YJ����}ֲm8�h�]�8��1^�[C��p�,ՙ�7�ٵ�Q��O0�Y��Y��9�ֱ��+e��i|���`�vjA��c*J��#��P�j�%�(rK0l�U��g=�����+�~�FT���Fq�LC�����Y�E���y�dhǫ�@*�:,��I�Er�}��潝��)���|OLdz��w"B�)@��Fs����泙%�MX�8��������]��31$嶷�;��+"�b""L1ڪ��^�Z�V:| $�v�'�����mի���%N95��]�Pƭz���۟A��y��[����%m+l�'�<i��V�r�����;Fz(�k��x��ى�%�`u�A7����'�?�UWT���s�� �_1V��7Rg�N�`�be.أ��Vb�,w�Y�e�C����+I}Mʻ�,u=��5gĺ~��i���q'�v=�iCR�}��!:����yϏm�;w�?v�x랕���H-��f2�[7�v�8�ެ%����4��p:��Z��}�{�%t2��܀~��e�#F>�S����zZf���1ܺn��z{���Ԟr��6y�:���V���#�Ao++���I�#c��I���uB`���Q�+�͜Zѝ����!f�w�w�Q�(�����I��\��JI�q��'�^K�4* .AE�j��k`����J�(5)٣8,8�k���B�ywyq����a^?�hw;��ό���FA>���_nH�[������A�M|�j�I�=XSmLV�jwB[����Rj�LF8#ln2(��z��$_1w�D�]P��:�q�Z�H��Ѱf��)�pj#8�n-=�[rb�X������u� ��"}�Ys��M�y�7$�zcֹ��N��5���|��1[|)�V�"����m�M([Bp�8m��ݫ�~Яo��H��\u���E6�0�9���V����it�Y��w�?�rB��{�� +v�GU�M�H�"��Đ>����z����[��|n�@'�ס_�qx�d@�m��; +�/��6yL�q�up��'��������%�� �YR)v�y ��ֆ���F�j%~D>cc���V�6w�w��;v �G��QY�k�$Q1G$��f�E��c�����ڥ�S$6�yd�(A�Gֶn�(�+�?O�^gmm3�^gH��r��WCmw+D|�!x�N���Sw��RM�2\��fe���B� +|��s�霓�}k&��+��%� �� ����gÆb�ۊ�W����p�c_,x�OZӃc� ��dA�*~�5�gk��o5� �L���F������kC-�GR+2�w��G�iC �1S��C�^�Z����+8�� +A$u��-�Dl�+�:f�����Bj���m��ֵP�ܭ���R<R�ѰbpOqUM�G'�~�J���H�< ���\�l.- �ۄ@��[Н��H����ޠ��V���- +����V��u5�nq�c�i�Ӯj=�<�K��jJLl�S�dK��U�#o�ݒ��ӈKc�%?��L�4y]���g�Ƽ� iH�2J��B>�|�o�����ǎ�]zo�Ao^y�^|%�.X��q�'���{�*��y�|w���*��~ +�8=���#1q��J���Z���������Kd��o5������c�ᤑ��W"�8��`&����dxF������P�)�P����B؎BZBPzS��A~���f�b��?�>.!N?�T�?�@�f�g`�M%��#�����[��z�)$#h*~r���l�3����6$/4�v1�֝�"U+P���)���Hd|�~���o5+8�G��R�A���u<�Aj�m�����4�KRw�הþ8Ī$nG=��ZF��t'%�[�W?��՚Wf䞆��ʹ��%�$7�H����c ��<��py#5,-��ۦ�팊Ԙ5�^[!e������>m:g��F�'�4D�{�վ�B�\2�Q����x��ޡׯl,t��!_��`(�|U��Q�0I{���a-��9-��9��z��Q����Vn*���|O��q�!f�]Ҫz��]�cvm����\+~��1隡�]���osh�m��{�ق�����n�n�k���N���3�T�wf�d��6��hw��hه�'9��QӍ��D�RCllt�s�Y[(D���>����+s�Y�b)�u��:RrwgdJ�ɶ�X�����֯E3��B9)��M>k��kِ��r��oO�+4�r����\�q�Hߑ�r�z#�e�s��Չ|�f�g}kO�11u�|���u��|�pÜ���Eܪ��\S��ER�m�6�X�,�n�L+IA���?)�K�#�ȘFj�Ԧ��n�1,,��^I�8�S~�?5�N̤r+��{���QyC��J�{M�c���P�ڸ{�++Ԃ?:�u/�,�p�.����W%M���i��@�oOS]4�{"��t:�Z~Ӣ�� +T��]ՠY��0�:ד:�KM��SMY�6�q�z�I���*cE�p P��H��gfv�Z��y5�Kh���{����k�G7w��*[�dĒ���B�/.�R��2��s��~5��'6H���W+�ئ��E*��trC�^�ߚ�uk#�ˢ�bb���;[�4�3���`��ZR��)n�~?u}Mb�D��`9�H8�SS��]�sm8����8# ~U7g��Ö��x��+m�a��Q�����Jͷ����g��RPW�n��i�x�[@�,>g'�7lT��T5�_�R��2#6��p�GM�p�M���r�̄�(`z{�(6����k��ۓ�f]�ʖ�Y�p�I#�1�j�0u�}��X�T`��2������V� �O��;&\�� �x���Y%��DG��rSY����7��0S���V��83�̰4��~���5��Դ�� ����\\.��X6B�rz�מ���B�B�*}�k�<=�", ��r���|��ʛe�,����� �}��VzL�<��{u̮�%�3�^բ�Q� +I/�xq�T�w�m�6ɺd��G 8bHݏַP[�93Þ#����ɨ���C���6�g�Uo�!��XEo���x�,{�r>�)��#�5��h���B���Ҷo4�ԝ��@����'�ҳQn6�U�9��>Y��b"���j�(��!��`���ƴnŶ���*�"P"|����[PI�O,��,=k���hZ[�|C�;��I����ہ$�b29㚯q∮n tLb�)�;�/¼�k�o|dPUFC�1[~�;1d�*�9����xU���mcڣ]����;�q����J.BF?S�Y#�$]4�Kng���8������z�V�������$'�v��H�������U��\tt���Q��l�w.�����~���Qk�N�h��7��G�f��Ö1�u�����8���6"��yW��A?��~ ͽ����Z팛���%��|o��T����Wt3���6���J� 7M�:-���ߖo�G��[�m�;���Q,����t�NO|n���� ����j1[}��c���>RG���0�RL��wF ��>���,���'��9�G6�uuh��ȼd*�ε.�}j�=.v��Н�pۙ��F{qL֭/,���遃���ި���}W�z�1���5�� +����� x���j���)Đ�����{�����\y��n�b�t�J��T���1��d_~�k��RW���Y���ͭ�D��p�}~������e�Fퟘ�8��-�:�x�����0c�1�����1�v��Q��� x�y�-��I^�4a�a�H�T�Q�Cw�U�fV�' +�N�w5�-mg;�J��Q�P��H tEDG̠sK�RV��*f]�$���7��H �'�����I�QG#3�j�� q��l �Wj�.X��|C$�\�xo0���0����W=K���t�^Ѩ�V$�n�����\�N��QԞ��$ۣ��F�~����|�v�Km�6]����+���F���0�|#.��:��:ZP�)�X���>d�h\��Rv�p�m��m9�qP]xq�Y'�jF�������k�^Kg����O�5b�_��v{�"���������5p�%������:m����4�6cp�0I�>�VΛ�Ig8KU�m���I�Wמ��˪in!���Eq3�d8N�8����sgww�n��+�ޟJ��dm)9C�"�ipZ:������_�β($�s]}ҙXl�|�w<�ۊ��X;4q2�8��ҭ%brF�z3R͠,��5{�H��"���W7mt��7���8?�O����B���\Ӫ�-�;�c�JSԊ|�� .���O��KmF3�]C���)bX��)�RI-�%�-��B�pz�y��ʨ�㟥S�����G�T�y�B���V�(�ë,���C�c��"Kw�m�3�sQVJ�3�W5�\ ��I� j�f����qn0�!�b���J����{$G���V�$0��^�'�#�k�T�TL�*ڜ�"��3]đU�%rkR����Ⲷ��� �9�X�Kb}ETP����{n��/��&��9���kϮ����x�1vV<��g��x+�֯���b� �ą�VFn�s�7_����f�R�=SWqX��\��l�@;�_lp1�|J��.{���,mqk)A�dݎv�q^�%�[��5�/�d��Q����1�ߙ��ߝ����Fa�u�=���|�[��[OvB!��go�bA��=��*7\R���H}�I�H���ROT-�zasO`Z(�S����e�&�9f� +R�e���d$�_�OR����-�H�}��FU"8?Ê{�9�o!u?�I��d���?�u1�a���Z� ӌ����.�N��+�nTP�{��I��DqN��\�;j�M�������.���O�AڡMM�e���j�Z%�afVۜ1��j�?6G1�m�v$S�S »LC���d0�)�u#��?ҭ"L� XϞ�<�"=ݏ�������%���5�����3��/����D��ڔ�w��O%}Ƿ�TefD�s��m�L\�l`c�y9/��k>��K����c0�����15���4O���b�����;�咪���E{k{h5���MBJ�e���JE�H��!�(+B��n2DX��G7�k���!��@d���8$�����6�iq1��X1$ې�k̩F���;H;$��x���1������������ƌ8��VN:TzZ\�"��ecߡ���%�y��'E��bn��(����c�юH5e'��ېG���� +���F���c1���1�Q@�ش*>a��8�Q<n%�#�;��{�ׇ��pSh$|�Gp=�N�v��߽�FGjV�1uh�+���2 �3ް��D���2Ȯ�\��(��H�95���Ga]�ќ�w>�l���{fm9J�+O;]�W,'�����h����2Ã�⼫OU�Q�9�,]�Y�F�i���:���l�sL�`T����S��x�W=nrVZs]��Vm���;ף�v�Cl ��-+JT��sn��5�i�aU���u�\�OSJ���P{�s\���ɖ��w+��ֺ��HR���W;�ɂ�Q�.?z�+t;�ٸb`��G,0+����[7?(8���]L���ً��=�WN���]�y{F�R��{f�Z��2�������g��P���i�s�E�!X��Y�:��ߥQ��?�@( ���q��I-�ͬ�r���E����5�-�U��_SI3x�7�a�������z��L�PS/��������*b�,�B� +�'a���MEu��%ɓ!(<g�c%5kI_\��1���^���݉#f��o�C���j�����B�1���W���K1�V�vy8�J��1`�o�$��q'����Gö�L�o$�1���9D���H���!*GC]w�u��v�'��Pg�T��w�� �0fm�=�ֹk#{��7�!�F���]+~}V+��������+�����Z�R��+�1_��j&;/98�A�VF�w��u<�Wkr�@��I,r;j��4lYAV����S��F���)�]A#��W�'�� �DPaaTuhR+�.�]����5v���9%�?�ߦ�\���K.�4�b��5�º�5̎����j��g�LH��h� �\����\�V�B�Cv���M�e}��\>0I�^V%G���Y(r��n"^���o>Q<rb�<*�3]7���[b� ���p�N��#nAQ��z�f�?�"����85�M^�[���z��O���d���m�Ȳr͵�����_��ead�J�����|��mb��ی�H���I�� +�O���C)�ѻ0��?�zv�5�V5�Zm�o ޛ���})����-��+`�<� +�ر+�����0������tM�h�>MΞ���Q�\�K{�~�F K��n�C�=3P���"T���Eojsy��<� �q��S���F at�1�����'��e\"��$PO��/0`�I����[KRlk�Z1qH�wC�{V��kٮ�P��"������W��;e��j(�'�?�P��M�l:������x`�a�� K��ϭz��� `�a�����u�P�A*�:E{n��Xj�K�k<k�UU�v0�_\�W�����N�R�=�C���Ss.q�����}x7�uȂ�+�ݝ��W���M0�02kǡ���=�ڔ�CDZ>�s�����d��c�;q������Q�l�����く�v�oc��rF쭺D����:�7��|��Y�p3�Ҵ�8'��T/�sB����V��&BT��_Ƿ��ZK��6�w.�(1F~O\�������ڵ�^<�#��'�L~9�Wim��Z�8]X +����XA��:%w�崳)���@FLs �������jI��#���tw��7�a͔��������vb�K���Ѻ����������14˗ү��+�BO���^�eu �y��hN +��yl� \̀>�ҷ|��F�,�\yl{�:���=yOFk��d� �*���Wt��>��4������^W5mS�U�IJ�=�FKYlk̞�~�`7�h��x��Ve������V��r�?�&`�ֱ"�e�2r��4�+�֜�ԞY�q^kkH���FG֣���Ȏ������tf� ��!�z +tp�RRDT��bG�E�A��7'����"�+p:b����r8��=EI#3E�U�������7m�V�FTVxr�˸³u�:��=����sZ�E2�: +f�̊�I�kHK�Տ=���K!����u-���5ps�+��k%��6�J�ڼ��('��� +�^��\�%H���qJ["� �Ȩ����X��̔������d��Gc�a������[����R�z���`���z�o�_ݨ��nv�*�c�U�� +�# 6�p��{v� Ri��K�~`:A��E[�����7��\z����Ud��\i�={ėQ˩x�&�eq���v�����/�Wn0V?μ�/�_۞�+��GS�O������p�����1�{V�����#�Y��El��@G|��{��c�v<Z���Ah�FČƦs�ǩ�~OU�:FX�ݛ +�i��f��)�g�c�+�ϧ҄rUTB�x.��$ԦA\Oo��7���HQ��?��d�:;aU�A�������-���3���jT���䚎!���O�ד��ג��GP'�6$2H��`T�@`R�nY_�U}�ڠV���,2G�L[��"'R;+|ª�vKE�n�ՖءNq��,7��0a�_� ����u�q,M3۵��<�l���pC<�<��ǃ����qw#SFc⋌+��Q�x�5����X�W:_*��@��j7��&��0� a�M;O���1<2Hď�8d�z�6mx7�� YCpq���ʾ���ʭrp|�0���Z����[��I!�en�P����⼋͋�y�pb i +��"QRVh�uM=��Yu-�f\��n���x,m��α���89o� W�M������h`����.�������j�2�%a<�$!�I�z:�)Y=N4� +�hz���@��a���<�pe�����=���i:�����V�m�N��\ ����+��A�TX�|�d�{{WZR��&vB���-G2<�_vG=��{9Q:H +�N��~���b�X�yB�8�yo`;ԓ]h��JX�n��g�±����`�ENC/QT�/Oܲ����V��\3*��� ��ozϻ�-n'V�%'����`˶Z��GS��8��Ga����E���%G�.���ٹ1�/�v� �,U[��T1�G����T��}���O.3�+������wX���r�E}1e2�E���j�~#xV={H��h[���ltaҪ��cJU9Y���*��T��oZ��$F`Tc<��iN���QC�˃��^�h�ȩ{��ȩEE�zP�٩j�.0�����j��9>�/290��H�F�nt�v����/� ���[4�L��� �G֭���n$f'�#5-ߗ��L�IP���Oݵ�tj:u#7ў<�R �Ř`��j���4�\����=�:�}oJ���T��v� =j̈́^cH����c�>� >����S���"���;ː:�jҀG�\<�x��T7W0¤�8��ϑ rݍ2�[������nR{���*��4p�i��3�rrAYW&��P����Ozg�L#���P�x-���@w�>٦��s�����NK�i�Wk��Ҥ������Pd�ƽ��G�^���L��O�i7���&��<Ch�ʾTm\�1��"vG��151���=.�+���$�Ȝ�/�~��,�Aq��e�~��9�o���+��q����}��/u�����T9�'�����>!u�mh6�'��䜕S��q��_5�3�(�W��p���Y����7 $C�Q�\��U[�:�W��[�c�ץ +髭N7 N��f3,�W<(ų�xn�p!�EWC �$�ГҔ�� � +'Qn +&��J�1�'8<��o���d !� �ڪ\��h���������LA +8�%V����/Z���n��v���@��6#��h]]*�*��k��k=*�{��̸�ù�?:�*>w~��&��d�ݭ��Z"`uc��a���WQ�+x/C�( +��@�u��5I<�1�L��rpN9�^���,�mˋfNߕ}��c5�,އ�R��4����?[��M����������]���s;\�X�}��__\�C�$�/;m�@���k�^�|A F�&�6�q�~+����qJ�V��QL�<3�,c�?y�? �5��lI�dlc�J{{��&x"����i�|�d+ l�^2? +��bt�[`+��3�SSԯuKٯ/gy&��O�J�{{�������I,1ya�����R]d����;U)kryY�%�IJ7�d��)�d}��ŋ�I����X-Зc�J���B��.��<2ų{gߑ�����4�M����sImN�v7Gj��ɥܕ�y%�����H��>-��:���y�(R2�#�WG$7��\��0c8�x�'ӯ�^Mj�����R���ͧ���4��g�W\���O��>mm\(�:�7!���~�_���Bˀ +��?�U�M{{�f�(lH]��O�?Zત�G\d��Y�}����O��F�.}�jվ� '١�É��5�[[��4D9�w=��*<(}���?*[Z�0�&e�����h�m��p +���#*s�q�Z�ak#��˨�+��[3�Zi>������T�)d�%e%q��}]_�q���o^1I�Ue����y���]GO����Y�&�S�6:�@q�z���V�;�)���� V��Y�$���|����kE7w����/y]}i<F(����7�8��K� k�&�Շ�u�85�-mc��|�����z�T=�QL�j��tq�*s�[{V��`�%%-KO(��Ҏ��A��~�h�U�'28��O5����a=�V��b��T#��*'X���g�����BҜ�q[��`x�L�I����U�v��`U�B��`�8�9J�M�R��h�\�O@¶�P���^qis,H h�_Q]F�}��B7�k|>'�ݒ�ƥ+j��"I����8�.5���^�ބ���.2͟jH�� ++og.k�9���m��oq�˅_98\��vs�*FH�g��v�����1<A1c�X���+���R�)h,�,;��Kn�L����FzV>�f�V� +�I>���'v�+5d��#�QH��Eǻ})���sVmW���c<��j�Z��j5)��u�O� 2����6�ҺmBa��A��q���]� \P�w?A]Df���\vTiFKHS�=�5 ��Zܢ���>��s�f�^ک�y��b<H�9�g}�����!�}�T�Cs�ӭakў���T����s�j��;���*��욒��ߜŜ�1'О?J�{���(���Q��xW%�é�'��X٦B���*��" +8 UK!��\��.��Z��#m�������S��_�5^�+�y������h%t� +.�U�����1��4���8M���A+T'��?O��P���n +�9PSQ[���*���:k���HT!��8�k��[������.Hn����\��g��j�n��}�bO��\���? +G7���J�b�z���_jz���gb�,Ƿ�k@�YdA +4��6XpF:��־�+�b�z#��/�~������&W��Mh-�DU��)�5�Ɠq�3 ����=�49���f�?4Nr���N�`��lŏȜ��H��Di�G�1D:�̀=x�+B��Ol���u�B·-��+4��0�$�ڦ*��gD�C)��A��)LP��d��G6�Y��e�($ 4�8�j�i%�"�4�Y������w�^�E�>O�ʻw ����T����,���9>�$7��.#}̣��tӉɗ�%v}����W�����y#e\�a\��tk���`�Chb~�N��ږV�z���gj7'�j�m�&A�C��)�pwD� +J��t���(4 �gi�^{f�];_�n%[���R ���R�-HpP3��$�2t��� ���T`��ۏ^���F���g7�)h�G|�k0I�E�'�O�`�Gw5�y�NH#`$c���&�|� ukp�K2�o,~_oC��j�R�S�s]�r�Ǖ����*:�4��Zu/����*!d�8_��&�����a� ���{V&�j�D��P7� �5^��$��0�������r9�?�s�U�m\F�(֗gO�H���#��n&��p7F�Gc[�Mot�eB0X���:�����W�u�X�.�O���,3�֙N��y/�`�o�= ^u[�y�9��hz�|;�=��CDp��cO�F�Q���Z�D��>)�Nq�{JB."�h�}���� k&yZ�x�.W�m��+��h�2���ï��-�^�&��|Q��7�}k�KNdu����G��$qҬ��+�G8���R������YD 庄?�Ey۽���y>\���sLT�����C[�q�0V`��s���V��F�楮]JN� ���u�H��+2��p8�:�4ۻ�6I#�h�#������h-����7�5���D��^F�9f�}h���f:/�:������v��k��I���:g�<G�^����I�K�Q��e����pJ���E�|�0�0t�Z���z���l¬���>)�t[�OS�����{�G\�~5���UM�j�ox��»���1i��k�P �B��d}������*�L�xʅ洖!�wc�����<G�!����I#N�,N=s\�ͭ�ϻ����g'z����P��!���n_j���j��neE��.F}�LR�N2n��I�Ǚ�6_�>%���&9I26q�$�܁��J��O+ek%�# +�8���ּ�i���_��Rg��zn���}�ң�6���]��F���Z��VFq�g���խ݃²��l������/��3�i'ʘ�@�+c5�F�y7�����G�L�z/���s�Y>9ӯt+�c���H��Ad�7l������R���+��;��k�<+�[�V�]�n`���<��W7u{��K��h��m��z`���ɺ�,�eh<�U�x\��<Q��RIEh��՞g�]*��c�$�2��}��OҸ��(������雰�ˉ"Ϯ8#�b��-�+�Y��tn�y'2n�i�r�s��5˲���},����Z����+n�@��hf�HX:(?�#����W�Α%���V�<dN@�ƽ�6AQWy6��֏��ih��b��ueK+`��������:U�ht�h��'tw����8�Tm�g��#(�+������[��(0Kt��;#K�#M2��88�GS�\�E��Z�h��l��������ʈ �$� k��.�Rwv<�� ���,Wj�䞄~�}ׂ��X�p�����~��}]�%��-c��)$�z�Y��E�����ې�rjX����Sk[��gv��A!U%K8����甲-��=���:>�cw��fdYH2��}�CL��k���m�3���z�?J�X�t�����;io�N�Hgh��;NS$g>�t��^��j���X����@�5�i:e�j��3ڹS�p0�����z��M8��́VE���\.��Q��k*J�U�K��k�%�&Y3�@�8�J�,-#k�,��lmt�E���X�����x�����W8�g�֊���˛TZh�KT�B�j�^x���\,K!�mW�}k�qF��q�T����,�@�8�jU���Ȫy�}W{�2T�����eA����j9bX����7�>�ֹ��[��d��v�d�9�~��;�W� ���]�|`?O�W<�Q���R�z;3n /R�H�~Ԩa�8m����^���0f�T��g ����Ry�x�;h� +�{��j��~�-�\�E��P�n�Ar�K�ݚ�&�������ػ� u�o����%��\YNO�*�Q��n���b~���P�F�}��5?�].6�F�:�T�_�q�vԏN����B��B��X(f���V����w~0�+��?yiu$�Q_t���ۿ?���Uh�^}��d�l�(��)�MjeV���Ҵ��m�z�;��q6U��緥7�~tj"u�[�����Y�:��\���ʑ�4�o+����zT��!C��T�c�����U+�4fʌ r5$����bHW�}��zV��w�H��{T0�э�p3����0�p3���4�^JW�%++ �X�3�2Gj��u�Hn|���?N��h�p~A�:��a.c�J�.��ʄn'5�^L�ҕ� g pk���9�+;Z�ў27���N^�st8������s��K +/�Y6Qܳ�t`sZ)&8k���49���^d��rqZР��'�UkHH۷�i5K�o�?;��;Oƺiǩ���ĺ�J���klOe���f�?u�r�yUmr��q]N�;�q�{ +��-�3"3X��(���+�Kk`��s'���'�'����M�����������{}}���-? +�Һ�T���\��:�[8T�H�/$}~��~!u���N܊��3��8��z���{&�#3^� ��>_?�����F��|gD���e��G�d��~�#�G��kż<�'���v�=0)�$m�6�;�����c6zSa�"{��v�@�O�#��yc M�� ��R�߽������cp"Y��Zor}�c�3��/x��F4[G��t��k���u#8���jrj�����p����J���1In�H�rO�vҊQ!�s6:]ל#!s�e���c�V��i`>�^��lI +Ki<���rq��c�\�1�� +�N � ؗQ�.5)I'ln#����Ha�qU�l�-����}u;Okr麚#�V9~B}9��u�N��M�P�� =1_.�������v�"�6��Q$�?���5�M5�z,:�[oyr�D�`��ݴ���#Cx���)�ym���I-�33q�GNk�MF�di���YF��;��֝e՚�s���j$��k(���X� �������gI���}�PpA������z~���*m.���v�y�_3�K;u�%��4^i���j�d�+1��#� ����Vn�c�d�0�?<���{~�=��qK,���#$����M�-H��K�"01P2K�Y����bY�H���M��u�f�U��.�b�'�����u�=+��K�q�D7��w��֪��%��YӴ����f:��4{_�c���^�u"KK�6�KJp0AÏJ�I0*���^����*U� �:��|�'���Э(��eJ2V8in1��}}�z�����$���G2�ڮ=��ߙ���.N;�>�Y�+ep�弜����~X������Lc8�2Ϋ��S8(�yb0y���qZ`&���;y��x��z`��+>}Nl�u��n}q�������H�.C�������n�\�/��ۺ�1]��euf�v�y��j��8�U-��<�71�F9W�^{�{U輢�#;���=+)BQ��IKam.^��^��� +]R��feQ%�����cU�s����A]��:z��WC�S���?�u6������]W�[��B�dV��aЉ�%�nU�T5�(!�W0��٫�����c��nu�b߉V!����8��5�~.՜)�c��n?���%��k�s^C��&8Rk�;NP�c�ěr�c���.�� ��ֿ��6��F��|�;sXz5Љ�ní_�OԼE�Iw�A��\�`VZ�:?�k�s|��89%GZ�Y����y�"�4��o�\��%9 ${b�=O]k��-��<��vS��9�#f_'4�5<I2�m2c;�0;�-3F��4������G�� +����O�5�H&[q�7d>�_X�7���Ztһ�-�g�Ϋ��aq��^l�:���g�e=��]f����y�K�x,��<4��a^���6q,����5�9]q���|:�D�$mj�4�m��ۈv���?�z��쏏JKQ +N��A�[�M�0#�T�qd'f�B��y�A�ٕ��jat�A��~I��[IE��ţ�7�����mV� �X���]�'ة�y�g�>iד���A�I�x��[��;�T|9���*c��g��P��{�]<��4[k*��k��c�#5�>2���5+I�Y%�,�7���bz��k4ڹi��/�.<���]� � y��/��ŢX����7V�q�}Z�++h����#f3�O�77�-�6�*���QIܸN�a|3ym�Y�m�G8-]J�_�-��0O�>��\��������]��jW-%��|�|����ڽ>��pA�: +�ʶ ����!�}9AK�w7J�4]hLR���=zɿ��"�H���H�^�����: i���1����*A��iD�m�_�d�\�ۿ�T^����q�ZMB�8�m�����\������YI*���V���Fԩ)����$q+(�A�������o� +���IIT'�=it9���7�6H��9?��k>�;�Ɇ ��1�IT��R�`�#�<M�5ԩ<�K(�wlc���|ͱ�}��,�DZ2N�N8퓜�+�n-���`��, �?Z��l+w��5�i2w�3��ET�9os�bb��4�q5�o�}�a�����8+&x8�U�!��_9�i{�d8�ڈ��`V�7��b0ͼ��wV�҂J�G�۹���'��Q����@,è��3���I��Ay����5LȆ��9z3����F��4�m(pX65�r�:4�`pU�+��kY`��\U�e�GqǯJ�n��֝۹���B{�(��5�� �{¸��h�w��T[[��q�k�qb��:�Wi�m�1�� +���h�Y�S�X��\��|�u9��[�.1�WJ:6�q�y�2�$A���0C\|��D�<2���fl�҆�\���ذ��>���R-{�������_����y�ɉ +��^1�\����"�B�r�6��3�]����G$��%�B�辢�oƱ2��>⛲��f�Pm'�3����q�C���[��]��R���´�Rh��#T�B�Q)�<�'߭v�6��fcX��kl�7�ś?z��6��f� �H,>�ce� �~POү8yj� d��SG˱U�#�'�ND�/j�Q�yS%Ի�VyVV����gҴ �cx�q��Q�1��r�� +�d��б��l��;�1��AEr��ޢ�Z�&����Oq(�p�jط�79#��;~J�]�� +��kI�Q\���ӆ�*lR��v�gG�FB���zQo-�;X���b���Bd��k��'��r��ͨ��ލN=�W��I������JQ�LIS�A��۲�RWlѓq�����;Pd�;���dipv�ֵ�DX����˵z�`��9j1�m����¯��T��_T�k��L(r3�m���ܽ�ꑯ�~X��~�P��"]�ܠ���]vVDG���1�H�]�=I0�s�w�p���%_����0Me� b+�;���|Iᩴ�݀�-$�}�Fw �������S;Yy�[.�#�5���8x�/�``v�N�@��#���?2� Ur���"���ҭ���BC�ݕ�<���F�gM�K������5�����ǖOgbO�סx����C\��7�dbB�\t7gD�>��m��Ԁ�:vP�pಁ���ke�����D �������nN�$w&��F �c�jm��� �̚~�y�:L +�'�� ���=Ȫ��;h�V���u���?���dm`f�H�?�� v��|�d�4����U��v����=�,ٴ�+�3�]g�=��j��Bm�bѶ=z���yĪ�M�nOZ�+ć��]j mb��Q،���c5������4ɮ���#�ǩ���W�����#6@�Oa��Z�%=q���z�N�Ԟ��:\q�[�jnrƠ � +��z�&-ӫ6v�ȯCѭwV##5�Y_@H�t�u�H\�H�~u���F9�ְ4M9������}k��-�q�<.=++ԶM����Wi�lE�۳�y>l���B�g�}jœn�G����n*��K�l,��ų�ي̎��Uu�TE����L؉n���������Te�� +�B=����~��V?}9�Ʃ= j�o�F�gs%�V���}�sR���O۬su��ƨ�\��%���e6�{��C�Kapn���Z.鞵I�D�uͻ���\��:����Ѽ��̇bE����Ozm��$[��XP�>����_�q�<G�ޯ�g�4�6���d]�&2��+�Ěj"����"�ᘕ>��}�,>�����He[ ��Ҫ�[��=�W����a��z���r]��rjf�l�Y�ϛ���c�1�f�kLK�>�3ȩ�%�<c��U�W~���<�A��Wt�|��R$q~}�I9�&����A��h�,�6�5����99P����0}Oz��{��5a�a�C�O��^�^?�Oh/ �EF٘����ߧ�^c*5����e�<�� +�x�>ǥzT�:Ԝ^���TM�cs`����j��\��Xf�����w�m^kM3�jX��x�nF���5=��7V�h��Q� e��ެY]�o&�n{�ч�h�q5c5�� ��?,���A��w�ܮ�e �:�+�綷�bi-�o�� ����6r�L�K��z���-\2�4N�u�H��[�V +�1�G��|?o:\<�d�m���J`0��5���63}��ǥyu,�;c���0P`����^Ҧ��#Hfd��>c���k��h�!����u�F�&�5�X'��I��SD����;XI{���ђs��/�2�}�P>}�9U���r���;�K�H�P1�'��k�%�c�6�m\v�nx���_h�,!�\8��X��� �7��ǽsZωh�^�=��/%��1�528�8��� ה�,P�mdu�w�.Ơ�Cm$��ÿLQ�]��!��PW����Ƹ�P�i�������}�!�Փ�����5X����Kg�ќ|��3ީxgP����h�7��渔�.?��Wk����#4J�1G��m͜�@d��=�VԜ��TqP�<��3h���\�@p@�=s�Tl$ɀ{��צx��)qgy&��b�������}n���Zm�A<eA�������V<�=��7`�ꏂ�,S1�}�ް�U����6r(��d �9#�}3\��fP5��4�w>S���I��Inʋ�-"aY���8��j:R���~�ՆY���6��g<��'�u���smi�;bcU���I�p��5�Q�*+.U����8��)�<�#� ��#���/sU+�c+��j���wų +�E'�z�Ы�OJ��� +N�vr,@y�!ڿ�]M��+Hc�/L�sњQ�v]H�-6&�\,n͌\62�W��(۳h�8�Vω5&����ϧ�F��+ �7;���j�芋p���V1�|���Tp7�À#��t���� �����R���yrr�����6�jF?z�B�Gj댔��2�rzj\���LH@Ϲ��D�.Lr�s��S��.X(eLP�$�j�h!H���MTcΛBr�e{'h�)U`;��B&h|���c�<mϥR����.�j*���A��@��A��e���� ����Ľ�x�KYƛw6Xrkj����_���}k �k�? ��d���V���x�|�d�>��ߠ��2��1}��O���ǯ+��� ��p#n�r9P?�v�l����Č�7Z�U`n�I!�d��1�zT┥K���U-#��0�, + ���9�:VȎ���5/��1�=N:z֬VpGn�C�9`?���`g�g0��o|s��pR�R����Rp��;q�Y�n�u Q����Cg�j�6�p���6�q���z���*Hbe.�!�?�����Cv�>���7֥��k^7��pc�|�_����wv���6�*���z�u$�ŵ���jڝ5IY\¥GQܡz�DY����k�^<�����ˍ��=0jE��l�>��/�'��{GB���S�判���|���Ќ�+9/�'ʖ&V�VR�_�R��FՕ�e������B��Z��.�>��Go�j��qߟҮ����ܱp��1X�C� �Z�Q�U����|J�^K�8�UZЃ\���v: Q� B�k���-Y�LI�0k?S� ���9ϭr��K~���ְ�.+�5�'���Cķ�!ki�s�s]w��ԭ������;��V]J�2-���� +�m>�+Kq!c�1�7`+�A�j}|MT�չ-�*�@ g=���J2���N��}iu�R/,�)l�}\���j��b��E�q�c��{I(��5����� �%����V���L��F@J������\>O�<10�`�'�����A�zS̐�퐐������r:�k&Rv=B�Y�&\�2���zױ�arr�We|6OpH�(}J�&��3��z�?ϵk���Q��(B�#��i] If���%�&�V �y�8�z�k�������O��H�1�a��+�ӵ�g +B@��5�'�o�O3ȞA�gǭ1��IJ�hג��/>������U�;-�o�?�ox�P�=����r{VW�%?�]H8�jVQ\t:�Oc�%\K��qA!F�諺��noj�g��NW9�d�����|��m���q�)�0��w'�*����Úb <9B�`�T�����jy�j�y�P�<��A'���7>D�x�c>�е`a�ze����i��(lr�z^ �?�hwo��Uk�J�䨹��U��h?Λwm���wʏ�����&��>;���C�LPOj��ᅌ��hd���z��k��� ��̑���s��x�ή<�B������/���R+�-< 0�,ܜ�s]>�����]�7K���+AЦ�Ź=+�4M��֭��F��Һk[%B��'r���ZH�z��S�حUR��N���K��>�͞���(0ʤgw���$�`���y"8d��.x����#��)�|�08�~T�B�bH�楕ZS��Vܹ�|��2�*ko�[�c�r3��O@ܢ�6��ɶ6s�o��3�!���8� �)$���Zg8>����f�|�2)�3>B�RK�op����N� ���� ��� ��-6������Ǿ*Kx�*��3��8�R}C���O-�!�9>��5��fHNx�,z��yw��B;d�0?�J�[����o����aZ6C4��H��6yaj/�5=B�;��,�ۗØ� +��*���P�)(f<l��>��J���6B�)$�3g +���Z�6�]�,'�5��{3ڞ^�YF0������"�:��sC��`����^�ike�����}��.��?���.l�ۣ�k���d��>�Ӈ��4�V��S���o|�\��ry@��0����;��ּ�Q����mF�\�����=}����E�fK�Ho�I1S�Oq�֘�J.�ٓBnJ�rîB�t���z�P�=+�c����ã�e�Ek�5���f������ϵ!kH˹6W��)v�,��5��i����B���^�g���v�t#������4�.�/�}>��5�Ѫ�ͩW���v�ӛ�m)�'}Ė���Z�[%Du#Xd��? �[�����%��Y6�� �O*F y2�:ZM���l�Zf�8o�:��N��Ix�&�)�m�'���kv��+�}��KpGcT������$�!#z.:{W-jQ����;w|�� ���ǃ�>����R�*< R>l����S[v�����#��U�q*���r=+C�/��6ݙ�W�w9��� +I."8,v��+�]jKuQ2��A泵Ox��i��Q�Ib� +�d?5e���-#����5�x[��ŵ�`�~�=�k)�y�� ��$FBW�3���^����Gp-�q_����Ԡ�}ʪ�b�9���[ $M�#a�����Ҹiuoj��/�i{�YQ�y>�꿈�w~%�ͮ�b/.B�C����0�6��;Í�B���WN�~"�)�7��K�B����Z�Laul9&3������OH���P�m�7!"&e���#+���׆.��� �[��b�&Ԯ��/�(of�\c�{�����J�2M���/l�)P�8�V���θl�k���<A�GKw)��D��b�$+�ӼY�<aB%�~ݷ�S�ʲ�+����+�ۛ�t+�}��a�8���U�����)f��F]�����+��k�K{�n�Q�ʟ\J�4����7�L� ���Mys��r�dv���'-�73��1�\,{淋�/-�0T`*����k����DӮ�q+)A'�Eaxw]��̥�g����O��D��z��7�z��^aھ����cy��n�-��6��$#ݳ���-u.cS���;׆��Oz�a �?d��H6�x���=�yIɜ�(����DfIT$�(nv��}�P�Z������������o�e. ^�#�{�ڶ&�2FD���9c�G�?ƕ:��K�:���K�qY"O\�U�/dUTv�{�VDS;\��D p���1�^��"mR�n>a�kuզa%�f���ʘ �q�W�% +w��s�\�-���V���V��B��=� 5���ʒ�G!����}^�Sr!��W%�G�;�k����#�l����������-�e�A �<������'cu�{���w�IiT�1�Z��^�s[y��(>�{f��K�����ߥQ�O���֩���#�ֱ�q�1r�FŘ��d�6=+n�Q,!�鑃\�rFfCA�֣��,q��G�ws��q��ѻ�� n\�7}}�m¡�律����²�y%����=EK��)A- �Z7���<�U�:��W,����D�����S��EU�J�d�..漗gA�+���2��G\d֓�=��u�\ʶ�ӼeCg��Z��B+s���`�x�E{z&�^5�6~c�O�j˵}�瓌�'S����Sں X��k��,�v�f�ilJ��#ֺ$�Ld0�"��߿�`�'�)�3�`���v�ˎP�*摢�p���@:ի�KA&�:�9��;��B�]1�bMw�r���Sn�-l[�,��{|�!�A�t�ұ�mW�L?$���{��MKT���p}��MkS[Eff�z�5����(���~rp��5��,E�FlK*���'��k��[��y\��p���Q�)����N=���VR��ևT�+��Ǣ�~���W��;C�~'=���p�qr��0%x��U��n#�dfRC`�~��T���v�F$�y<�� 6�;�����U�u��fm��䫑�r�k��֮Ug`ҀF���}+V h���A���.;�t�tuOo���)|>A���O���)�%��Q��c�*�J�w�C� �<���ArF��k��\�M&��{!]&��� +g�� �ޱ���q����j���Ұq��~���=ڍ���b�r�ٛˡ�*���9b3�Q1]�یI�V���Z`��?>i!0eHl����� �<�О}���Tù��~s�(��FG�����O�[��2��Gn���i��2�����v��E��nq����v�3��zq*�}�!RN���s����@R�r�@��V���Б�9�j��m��u�붚`ɕ�1M����Y�RN����x��?�\��C��H���B`�eI�z0��*[Y ��'��}���+UV�q����B���^�n1���8]��T���2��#0���� ������U͖P����z�E�m[��1-����Ct�e�R㑆9�55�Ts8�"@�x�C6�0P.A�����$iT�l���A�j�`�hX6=z�L6�9�u�X�m�)������ܜr��O=i,o�'uq���Q�I�g''AUTH�ya�̣,:q��S��>ߜ�8�ↀ��=OZl/����z~�L�d���3`�b�`�#'���<Ұ���^�@�@��Kn��gpp}錌ѐá�Jj�������3�jћ�D�cvd%�8>��Z̛�7����z[g]�HN"@z�ɪ7LD;���~�Mu!���Y��4baL���_�ZO8Z�Y�@y�r>��f3H�om��FM��<K2Z�kv|.6��r��^C�*O}���-�#���Ѐ}q�i�I5���P�6����8��u��'��ޤ�4;�2?,��v�pY6[�!' �v��E�<�UӣҐ���D�Q�����9��-�裁�M�pP:�m��n��H�����* ӊ��I`��n� ������F5���GF�N�ݹ#��Fz����i��dnp7`��R1�^t�����'�cz�駊����z�i{-���r����f�ޠ֊Bh�Eŝ�` ����s�����N�a +���z�JÃZVZ�� ������U5+0M���n��M���?y{}kV��)��I����w��1��S�����C)q��q�My�� ��ge<_�F(�s�ǽL�q"2� � T{Tu�1h۳�j��WΕܯBO�'f�o&��K_%���r@8���lH`Y2� ��Q[wQ�\��_r~t�km<G����=M`�7>n����c��<3e35���~������}A�p.�Px��Y�S�J���}����UC$���n�d4g��jÒ�C��^�7�.� 8�_z��"�P����0#$r=��g��>��S�̟vA��4�~(�ew\����/RT���7^���H +r� ^�vB��v]��\���j��<C�ד� +�TA��`���\{[^Xɴ�]z�s�ixKD�3��m��kiyf\i��A3ƌَQ��c��ғM��b�����݅������? +�o|�d?+��*}k�<+co�Cd�=����Z��_G�t����>��3Y;3�X!��0ϯ�z� +�Bqv�2�@�~wS409C�Ɖ���N���]�_%�ۊ[�����}k������KG���K1�Ԓ�6Hr>Fr~e�8�t�Dvw�Koh�dL�,��ǧqW��..Dq<J�2ђܞr{��X�i�&�Y$a�����i�GdtΪ�yz������DE� +ڧ�p>�[O�b�[c�u c���w��ܬ1K+�p����=;)�\qHRxHdp +���ۚ�FP������-ԯx�c+�4l�x9�x���I<��XᄕT9P�8���r�v����W����+��ό��raH��<ҔcX��SH��c��vs�O��}���E�(��KB���d��|Y�z����ڪ���=����&����0�r�=�i��ŵ��ѓwv='L�7+�ܺ��>�����<�<96� +-�j��{�� �}Eu���+�,�t�V�z�q���sW���Њ���vU1d�!��QZ� �������=kC�+�N@�������������3��F�$o�?�rOJ�# 1�H�TE�.ps�xzRn�� +;U;�t' �ؤP�Z�P��� ����2� W$sT����f���41N�Q�~���c�+:�nY$Aϯ5z�Q6�Q�NF@��jyy��+�"��W'�N�囙������/�1\�u� +�2Ó�C��*��ҙlڒ��)�>�yq�_hGތU'2A}\d�%��"�gM�y�E��{i-������s�G��?��8&���y�D�G͎���١`o����Z��0�Z�r������W�,�3���y�J}���J�N{F��\���Ms���Ȼ"u�kء��K]�s��iOG��}����[r%����\��]J^G<�s��P���{TZ��&60�tߢ3!�n����aӽy^��=��E݃����oj�;4hۗ�3ֹV@G,xl�?�Ք�m%}I@U@��NT�n�ךX� ��d�7�JFWP>Q�H���������<��Y�Jq��9� Y���+���?���ßo@n�Ա¡�؏P+��| j��Dڢȋ�G�bH�;t�T���8E2Jm9dc;����@�����DF *�J���e���%�%?y$����=?J��X���-��>sc%G'���E��n>�E���;wO�V��ed�×�)� ��s�s<�,��j�>��۾N����~��N�;"�"W�ٚE+�� �}�x�C���/�,��Q(\WS�/����R�q��L�?���b�߀Q�N��z���+ +:e�=�����$�DK`)�R��ƫ�����jP��t1$ۃ)s֫Ƥ����̎=����I&�d�T)��I8�r~�#ˍ1��$�*�K�6I$�)������{���h�1�ʃ���>��Co#e�27>���,����B�c�j�ú���a������>������T`Ԧ2��n�����S�8�8�l�ҫK��bH�PI�ь�''�5L�%��Y�s�֤�������Q��v����N{�j2\��3��\b��{b�?2c� +[��/����s��' ����������d �9��S�#a�Q��n�)���s�ӏ�-�(����҈p")�c�e�v�=��3��Fw3�g���Ky��b +���2�q�=q�֥�$��6r2U�Nr�������[`��$� q�QyQ�D�$�`R�+���sM��O�������zTS� �ۏ^�Ԉ�~G�Hp�ӃG3B�#Y�=��W'�1�ż�av߁���#�i�cu�7����]� (,% �;����[�hf�6W�H+������Z�~�!Ee�����ȳ��˥Ks�G����d/���*�_Gv�p�e#�h%��s�0� Au�H�{�OJ��L������I#�~*��v�;��,�b�`U<W�K�&��0������3�hLF��<��`����Ҽ���4��5�7�!|��I%H�{�]]ߊtX!q�J������kqe���&e89Ϲ5�*��D�*j��OjV�U�Ņ�'�3�F3��O�]�'��?�ry�k2�rG����ҨxZmE�d�����Cp����Zڪ�H��~��<�|�ۡ��ޘ�i$R+�� 0ғM<�Ri�#��C�WqXr�G�i���G��� �L'�H�:ɧ�p��H����zt���!�$9��V^*���=� '��)�+0M�T*�!�i1���+��ޡsq*ZO%�����B�s�x<�u+;����c�J%�����LS��z�<����Kfy��&��G�i�[Q��+��?�-'�0?��_9W-�2����X�����C���t韥r3�^��[�6e�aʼgk�橅i�X���;[I8�X��<�>���M�]��K?�����Mv�V�uq��ck[�ዡ���5�/.&�yܣ�yUT��G�J��*i�M��Ŝ���1���s���Rx��Zg��ō`R3�[�|��rP�Nx��gQ�[h�W�/�5��Qn��NM�-����v�'�E\X��{���wV�Q�p'*�`��kM�h��琐���r?�l�5!$H���'9�泍:���jӎ��V��w��>B�x �?J�,.�y��D*73����⋍ +��ʤy# �µm�(�X�_LV���2w0�V2Jŋk4G��n��u5y��|s؊������J���zڭ,�һ��rI��=�ݬ���,B����oǶ<�E�3�9�4��G8�������]��b{�&�kf�L�6����]%�Q+��ʞ0�/+�1�rփj�ޜ��W�6��ƆB�T^������Gz��0�K����+��-&g���@X}��k��[��u(;�a���ȩ�{���hצ����{��������R2>�����h�"�Fǖ G�jⴽ>��Z�@��zv��M�����}G�ָui'#��N�;R<�wv���$���Tn�C;7QQ��sx�aA�n?Z�>��HT�ð�z�澧%���L���ڿ�{����dg֪[y�X���"�����7Em�g-�;I�8fR�>�$�H����5�����ǭ$���-��tք���ur6�0ǩ���)Jc�Zנ�EG���4�M�e��Y�˟B��us;�9���~�f�r��٭VGGo�����[��/�]�ԛ�C)b �ԙ&�p�w��G i����_�n/��G�fG�b�x�B�`Q +�u��X8C}NiV�������"�����MC���|���ƹ��杷?Ry��ۏ_S]7Kc"�I5�/!+���M "DN8��܅Rs�R��r1-�O]Ǣ,]�+�v� +�u�K�m��'ލN�"2��w5�\��@�e�zc�f�v��<�W��n�����x݃��8>���=�n[�w&s��GC[z�ܱ��I�`�����9�5,ɷ�k�vA<����iZ¸��ʠ2 P����h�m�4�y +�"/���t�"��յ�İe�@,Ν�{s���c��t[� +���}�1��x�`c��(��u��o�u���a��8�q�׀kn{�����0��#9���p�^�KQ�i���;��7�1��)���`ay��-�54}x]$v���G) +��6��w�^���t��J��U8#i�/��8?�Nk��}��ʓ��@�1a�|��d"�O��g��K�K�h +<�r:�<���)'�i�Fq�PB^H���r7����rH�%l��aF8����eM�/�'P�;D0d ŗ��{�K�%��,~Z�6�yw �����:w�k�>c0(L�H|�ʡ�8�!z�q���Vfl�����c^���K�k��B��������)8��^��:=��o�I3cלVP��nzl�l���^o�� Nh��:RL�����F�Is8� +���\�2F,my��O�Ӑ+�d��˟|f�#�6�1��!������Yq�\�])B�MϜ�1��I�b�h��UW*t�����# _��?r���}�Z:RbI�*����O�{�ƣ +�����j-�y#y����Her�D�A[�ݿ�K(c,88R}�Ď�����T��0.�w�3M��ۜ#᷐~��S���c,�����j}�X1<d�C$v���t�#)��d�����><�˧֥����m��h���*r{Ta�����#����� +jϑ�n)��q������i���Ld����:v)'�y���iF�S��R��ɉ\c���*v_p�w收��F94����8�q�� ]X�O� ��]�b�+6~�Q;���s��CI��2['�q@���#��R�*�'���]����0l +��S��@40MҠ(F��$���["+QIОEfA?(<~4Jh�eR�?0n������Cmcn�m=�dnʫ�G��z��\�m�X�lT^�8��5���R��?u�g�T��mRR�0�r�I��үM�h�m�eY%[{}���O|z�[�b�K+KT���.�bG���j^٤�(��20��t�'}B}F��U�������� +��ӣ��"�-ϗ!� ]P���9�z������� ,`��I�*;;� 嵩��b8��Ϗr*���wD̻���>^��1T��X��f��f�,�kx� +��� +ޙ�<T���i���q��ʯ��~��*ѓtф>y26��Gϡ��4�n�I%��'$W5�n�1.-.#t2�!����y v���m^9%!]�v���_��e�Tb���{��q4��Dx<R)!4L&��&�$hcQ����ң'�oҘi�+�2��K�� �}A��0��H���u����z?5f=F�O���'�W6}�7�e�V�.S�qm8����*#d�,� Ȯ|\��ML����JQ��@�(��#dW�����6H�����`v�#� ~ +�b L��q�>��<���V7�.�wԱa�L���&x���K��4��t�x]��e���r��r0j>�$��[M��^F�c�+g$T��=�o��2n�9�武�8���^ +��r�&��D�7�y^�;*��=1YM��ʘ�Ɩ�SXؙ�z`���K�W��s`(\g9i3�s�x������I9�*%��8!��#5�R��Bۗe�l+���ҫ� +G��nO<g�ҫ˨G��g*z��)˨������j����ǹy�H��MT�U�>��F>�TRjJNDn};Q�$��K���@օ�ݖo�P`sϽZ��ڻČA*��5{�ePަ�X�%�[p�t�\VR��t�5��>]^��w*>��8�Y�o0`.1�f}��m@�TIs�q0��t�T�X��n��g���B���+[��ZA���Wԭ����tG��bo�6f���6}zTMs'A�~��.��sTg��� Uռp�㩛�6t�;�,[犭5�#���>�\uΩq'ޙ�:��.���(�c6���n<A@�"�y�b��w7��)Ǣ�+���@����E��ۖ<z +���ME$���isSp,��u��^��}�{T3J��4M<�k�� +B�m��Q�k��oG1)��7eq��mN��;Q��:�V}�IHiH.��$���Zo�f0�00��5�m�ֈ��3W�lA�[�,烟J��t;�8���y*O_j�K�-�������9���WKm�EcnC�� �>m��ǧ�R�.����b�(a{ic�E}ϟ�c���Z���ܤ����ٺBN߉=3銱c�,�bD�j���r����c�ҭ�mˑ��q�n��}(�F}��ˊ/0��*1��?\g��b O1�&��`H���>����"�iو�4��Cg8��rz��?T�I`��ۆ�N������KW"Q�rS��ʱ�&��<[�7=8'I�#��T�$�~��Tec�T>����U�$���z֤�+�9ݐ��S�~��:������e^F����g�Ct�� I��-��$�c��B���ʱ=�J��T�0ڛ��]����B㓸u��I���"h{Y�P��) �`k�՝�tX�>b�� , +���8�Q�k�$x����h��w�)��Yy]�75�/r��s���Z��"��Ɯ���S��YG�gK��t�9Q�֣�]�̥�9���eo�\2�V������J�Vp�t�g���$a��i��z�5Z9�̄y��R}x��n��F���ā� +������?�f��� �r��}:SpZ(���қ>Rg8��[�I�R�}�줂q���@nȵiY�9��S�G���(�:*4EêS +>�50p�3��� +�dJ\eF�����@9>�)�#h`8�ߟzi;$��珧ZL�G��IrS�S�6��*�v�=���Uȇ��Q�����`} L�K����[ck?��t����.G�c�^E'��f;^�I'>c�g��fx���b��e��8a�w�����:���#R� �5��!*�����E�<t'�ֆ����N��Q��xuS�����R�(�<��IC���~t��9���$ܨ2�9�Ғ6;���0�+�銅�� ���`,�����݁FP��Ң�����K�G�Qϵ ��n!p3߭:0�k*:p0����`$�e*���H�X��aך���MRe��ʑ��5-�?|��\֙a+��i�{��~u��B"��x�@��ު}�8eM�콪%ޠK��:ă1��1����H��������,��=�L�6�܊[���B��iQ�Z�[!���I�3B��y:u#=�uZѡ_�4�M�M͓����y�{<m+�����̶�n��T �X��{ +�](�Ά��̲�<~�I'��UMNy/�#��d�����z��ɀ�P:F�����N��2_�f�K���Q�����U~��_R�� ��neCpOA*�8�&���72�[��0����/nՎ��$�%�\�G��b��5��0��n���"�E�,lp1��^��ح�Ú?,��C�') ��k-�n�� +��6ܒq�=?�^�����EUƟB2j2i�����P�i��JM0��@ +Oj���i=逍L'4�i��7z��<���4�+y���K�F4�#jf�^�O5MI�D��E朷ε\����Sd�Eu6�'��#��VZ��z�s����V'�?�T�3\�-� 7{z��)֍[8?ʝ���Ȯ?{���L����r�������i�3������Zi�^���̂�^u����pI�+�{�����Mپ�=y�X$d0�q�t��F���M�t�k�z�&��ƱY���# ��\�^{�l|Ơk�'�TGjf�`QvQ9�۽F�q֓vW�C� ��l��N �SW�'�q��Dܰ_Қd�U3���$s���Xi;��IN*3 MV�CLh��m\�m����g�q����_f�{��)+�]��8����6��\�= 5�L�084��&p��a��e)\�+-m�BŃ����C����3���Ug�cK2��7N3�k�3��"�#��2����i��6�m��%�CE��)������H��+yX�����N��=kL��W���!9id�;Tv�zV���%��G ���� �9���$�\����w�0�F^�=�����uU� ���G;�����Ri�yp�|�b�#n +\�GgT�й��2�C���08+�}�g56�+[TjO +�B$Bwg8�����{2�]�c؟c�� ��6[[�,�*�t�����kj�����˜���5���ż�"�d���|��'w~O\����?������9��������nNd�B��rq�q�#_�U� 6���F}xzzL�Z�j2��5��hP�5ݹ;z��c�;���X��k$S��|Hd+1�\�H�ҹ�w$����e�#1d9��Gpy �k��h�q�(�$9�P6�N������}�+n�$��������ȵ�ゾe��''�ʾ��$^V��Aǧ���֬��Χ��w�r�q��?�jr2��:�c&�F���8����H��>o��ZD���� +�q�����`N��3�k6�� �ȑG����@)ӕ*e�^��@������i���>vǧdq酧ɶ8z�ϧz"������.q�@G�#�h_�r}骀,�>��8��a%�����Nq�?CMa��)U�����IB�09���̅���zc�i�̮�P !���j��Q@<�x�O�#W���P��m��f��ЩC�� �$�R�/�n�ܟ֙��1H<E��Ռ�Hr8��UU�9�H��RJs*8�"�X� �n�;��Xy���@���`��;�]��֖��A�=�! [�7�2����ѳy���+�I������5�z�Q0�l1��!���?�5H�cÚy,�'�j)N!��v���� ���M$4��<�_���$L�K7>��A�����~��%���'���\S�v{�P0s��y+D��F�r>�U�Uc'$n#w�)��iv��^����K�� =EF��r�r�`O�\z�R���/z����R�'9���k(�k�2(o/o�]����OGUQ����U�4�Fx�9l���3W}i\{�-)[]�[�J�Zt�&Y��_��c�ڳncc+���Vg�?���0e`�>������5խ-b(���sH�&}��Vs_�O��J�q�͓ی�]��dAx�[#pW?����qڪG4�2�z�s�ʗ;)���Ne� �r��N�=3[1I;Z��y � �¸-&�}&�L��J����Ul��2=��y#�-��v�����o��Xw�Ï�'��{�Jn$FN�>���4��,��V�ߎث�yR$r1t��~��D��5;/�8ÆV����{��)-��Q�Y�����T�=9!O1[�9E��Jhi�-4�Ԯ� S����� �5� �Ri����0$�d攚`����Jơf������PXt��c曞(�&�OqJ�5la���)�qM9�$��HXSdlu5����B����$���ު�ǜ�*�ĒE1�4�(Zb��)�����z@?�zԛ�Tj@�-�@-Mɦ3����@<��W���C7<�2�}h��&�j&l}i7Sm�y3�$��Wy1ɠd�&;�I'�'<TWK95�s|g%�O^�v)+���f1���#�c�Bs����Y>b�O����Rl�+ErmP oA�i�%q�/;Ƣ�Ɣg�+�Y���?�zF�em���v���P�����(�[����6���5�l�H�4���'�QS�����0 +9'��V��ncn ��`9$ ��հ4ln�V{��d��e9�}�V%���!�2��d�6���z����/.@�y��Ϸ�V��d�BI�������隁�r;]>�%%gr�a����B��y�+b��\Gs ^NG�:�OLf���˨�A�lsU�4���Ԙ�v�8�:��=i�-�-j6��E"9���d�?����M��X[O�<.]����>X��9S���S576�-x����Gӧ���^��+�x%�"�s�q�溶�8�!C&�&P��g�By�9�]G���p�����p�#�=:�W <��Y��1YH��^��3nNۋ��H���Tەʱa�c ��j��\j/�c�:�{Þ���Z᭥fIp�)�9~�}��^��xg�ң��U�O/ +��.�`q��-���� \ No newline at end of file diff --git a/web/core/profiles/demo_umami/modules/demo_umami_content/default_content/images/vegan-chocolate.jpg b/web/core/profiles/demo_umami/modules/demo_umami_content/default_content/images/vegan-chocolate.jpg new file mode 100644 index 0000000000000000000000000000000000000000..673589f3bc6bff3af6b3016e08504a9f6eec978d --- /dev/null +++ b/web/core/profiles/demo_umami/modules/demo_umami_content/default_content/images/vegan-chocolate.jpg @@ -0,0 +1,239 @@ +�����JFIF����������� + + + + + +������������������������ ���������-͵���o������A�c)A)7 &�!fkR����Q���0`��������@�K5�Y�{�Y�%K��Q��*�mL���}9KPI��Z����30fj0`����@����$����G>S��yF�ӓ�/A����;��BI$�R��� 5)@$�������ILh������zC�(��2�y��/�n�Fc_��V�I��"R���fA) �)f�0�0����@�@Ȓ�"Ń]i%���0|��5�6:*f���3kh�PIHR����Fjq@�H� +�����@� DLF� ���yk3���<u�I�G�ڥ�z��đ%*P!j�����2"`����"���faU�H}�(��2�q�\�H5"櫯j�,� ������4�0dJQ���Kl���C�330`7μ�CaZ����\Q��J��h�)k � +P0`�I �-��jۧ�ff����$�]_m,jd\�`j �� +Z��H�R�����H�`�B�h�0`��N άl�x��Y8��Ne�ie����@��ʐ�(� 0)F��`I$fd�q�(���#�l�N�VG��k�P(���f֛i���J30��R"���J��HR��0`%)30��l�Q���`��X���^����#�t�j��|3E��_Mp�Fj0�(h�W�'�JRf�kP0�0���P��330`�o�8��[m"=&R�qպBԸ�NE�����:9��)Ff��.jQ��%��h�%8�R�`�����$�`��:j3P��\���:�Si�u��V��%�9�k�ӹ�.���Q�8�[1l��&��N�E�vO3qF0 (BA�&<g&����.����Hz�.{m��{P �ny�2�w��O��B.s7X��j_3����]�݇T�˛>d��R�����6� + ���~Ff�u� ����b��W���G +3���u.�f��#S@�QL�F����:�e������N����0 �ғ4ǫ�wj����y�dˍ.�|d)\ﲺ���o6��[w a�(���Ĩ�b.Z�8*jNu��ϓ5�$�N��i���3������uU�tPR�g�U������u�wq���s��y�;��� 1+`�VSղy�1h-���˛l��#0��/��a��a<�ɝ[�3���,N��m��M����Iy�r��za��K���"�$kk�)�4���0#�'AIu`Ĉ�&�5���r��Bl�)}+�&lq/*��v�@; +FX舉�Fi��;uq4DG�K��� +D±�=���: +����*k��CsQs����t��JgX�0t���|#�O�����#1m��j��8ѣ��N�mVRn-�*<=Ek$,��L���kk���1�D����K���]]ԝ|���m$F���kн#s!ڿ��&�ҽ5(m���<iB,o���'Z�K��ί+a&TB�!njt45R�0 �J��Qb%p�6��Vul��[m�m����}>�_��x!�OͿ��DRQ����ʔ�in�օ���.QÃ�i���ϕ&#rܓ.�Ƶ 0�x�a��k�̑��µy��v0iA2��KE鴑f��`ld8��>���T�y62�q�����Jj-uf{6�z��M���� &I(a��V�~5�h�M�����մHKd�<���1ٮZ����D�C����Ez��lo7���3k��2BII��\斶Dٶ(V��QٲT��a�SS�H�Zd[�ƾ���-��v��ߦ�&X�K������Kr�����U�ٺ�g�.l���E��]������M\�jl./�|�Mڤe(`D��șR۠l�Y��Ӣ�-�|�wT�=p�.-}uG\����fwZ���(�+"6V}=ۊ/ ��eM���ު=E��f��\d��mGc�����dU65IY �@S�>���&�J���.�q�d<娖���ȣ��{���u ��))��LW���\�b"�Q4ۏW�78l�7��îۦ������ن_|g�r�ꌷ7J��4�G����I����T�ߙ����&D���^��D��kɸ�l���[�a�$�Q���˩�sm��d3U�sy����"丣�AImj� ��i�������+ws|������hlZ�9�NR:��H�Ά[�j��qZ���@�Xw1ZZ�S04qWC�˺i��AO��B'^�������Pi�)��w*�E�Y�^j�C� V���QC_W��%癃k������jPs-��d��6,ާ�db��m�ie��yV�VN�sj{=�!�5�+�)Ě��r��ousi�ug9ٗ\��D�*���ړ�Y[��me��«�Zw4�n�ˬ�*�Kӡr��h�S�!q���5T��a�#�6WFs�&N+ܤ����dM��J�;n+��_�E��m�i���}�,��(����q��%�D��I�R{L܇�sщ����AK��θ~_ +����h�/��\�f����<t_�M�7~E Ot��xw�r��je���}D��U����z*Y��s#˴�] ̶�WW�8�2��{�n��w�<�%��acd�7٭����7]��J���!K��6�K�9fX�}M�{��^���4�L�PV��_FfV�٩����2��=�E�p����?Wc�s���8F��m� +yUU�,nd�S����.���Kp�j��u�*��ӝ.R��nE��#���U�}�tk CƢc��>�N��j���.̨�ۯK�h|��7�ͽ˵�էwl����SLE���ޓ��S�QI��.��_*�~;?V·S����A=��ݎ���T�-�:/Zj�q�<�2���Pu^�ym�|�����ĝy*�g .U�d2Ğ:λf�\[��N��f�[��Td����Ӕt��H�o[�������d+��ߞ��c�=Ns��֏q;��MoOv�dd���u�ij���Q�Sv���V�\��y����~#(f�5��*�{�W- 3jV��Z��~��,����|�w�t[w�(�:]\�ׅ�zd�)շ]]�Z,��,�"��1?s5�!n1��G�-��:5D���i�t����$�N�w{ �3�N��n4�qI��F�:��ւ�B|b�lZ���n���ej����щ���Q�TQ{[&�2���O��͔�� �� +�K�u��8���q�\+u3����a�Pdt�FwG������ ��d)ؙf~U�����m˽L��9��#VR��n�����x�w]�{`0�����!�������:cŎOS��f:f=Ƣ/H��]>����M��r.�4Rܐf5%5m��6���ܣt�`:f����Ɠ��]���(�:�T���9�^���T _��h�L�m2��e�l�����<�_��7]�R�Д��L2���\�?ӡU��[ga�wj'zA@DW���jB\[g�4�������i��e��ϡ���$��l�]?�Z��R(��e�-��m�3u�gz[1�����k\/�WG���тm�3&إ�H�=����ac�T9f�a�Zk�z���ǜ8Cx�bl/c$(� �2n +.�غ�&i�M�k��f-������3J#�/�M�H��O��c������*c��a�Zog�C�NG�/%�������ط�(6�1-���i5�:r�H#�7o�Mm,`���チ�Ї�����]']u.Y�Ye 2�-�]�]{v�������a�~�Ϩܮ,h��<h�*+��RԤ%!&V1hk�� +ZhO��1�qɱ��Z�r!�'aѥ/ʹ�Í��if;I�������,r|�+f��m��dm!�9L�z��$�ChSm;�R���K��_Nԇ +|���,G��R�����;q�D��D�H�=nR2j� �9w/J�}��kZ�&-�T�6���� ���1�z���v�w��R]5z����](��o�<�Nۢ�� +%K��QUGM��7|�0���F��?��a�Դ�c������m2�m��)h O�"µ|�X�7�LD �T\���4~��Eb�l�Q��cUQP����L��Wy����Ņ�v��>���g NBH�6�+�ꩥ���c���Mt+��mE\��/�.>�Bn���$�-!(m�� L��&�e�Dzv�BH�=A�]zH��IQ�WV����vm�#���/��Gm�r1خ%�(��oB�n6ۍ���d�az;�@Ii��{ϳ9���I�Z�q��Ҁ�m$������L*��0�Gٍ�ӳ�C���o��q~y��B#6���:6��KP"!�w�9���CHLk������̗euWN� �6 �5�UlDP�k��a��G�k��5F�3]y�YI��x��L4�DF�˺���z����������6Py�9����3 +���� IE���� ��P�A��-2��"u�f�F��4�VT�~}��P�Ee����n������t�%�L�(<�C�����|�I��������+&�a��ƅ+,4�_W�\� ɓx[nm��S��If`�Ȍ��a���ҙ%�]Lt��Y4���Jf����7F��M�ͨ����FM2�vYj4H��i������Df�KRIj��% �� +O���f �(��ɱ�3���b]�_�`m��rfYT!���L��-G��vm �QBA)N:�6���A�M)BR�.~��Zi7j��~]���W%�������<� �l4�m�Xa1�n4vȊ)�KzD�Jx��+I#2�6����6?H���GpE���0���$��D0�W$��Ym���l4�[n;("L�\5-�/�Ŧ<Q�I� ��(�� :����jLFa��y�pL���[lLj��m�І�i�4�m��������֣pډ +v��M���������@t7�|���zȒ,x1H�J�%���m��M����J}d@��Lć���!��@�!%Q�p�W I�h����� BP�4�hmJH���}�B[i�cD���3 A)@��"JO����C<��|�)j;j)*b�H$��!-�-�)" �������������������������k˯��v$�]QD��TBKHAf�����I��$�TPEte�U=�l��l�ٚ-��.s����B�HL���Ha "($�aUY�=35�}��3C���wG�a� �F&`�BH�����0UQ#"�k��2��c�m�1c'L��ٓ+[d�PL�a��d�I0 �!�V��]Xݬ��-�����ݗ��m�2�z��2IHdPK0I&4BH� �@�]5�NWww��sl\^��;}e�s��gm6aH�ɂH�H�I&@�"��]U%.��k�BO+O��v0���.-�`��H�]��$�� ,L��$-uV��i��vf$�N#t='\ū��f�%��YI$-�0 #3$� ��bI)MpBu֔a�k�rĖ9�[�>�`����>���|A� ��A �HL1�1%j�%V�Jp쵘�%���WҺ<��*�K]e8��B"�Q�����d�� f,Yk���J�tX�Y�,ӑ_Wv�u���y����7;���Y�P#HU�8�U�H��D0�If,bUZ$$"-9�gr�K1���|8�����2�!��9�%W]�=k!$��(��� !0�IرZ�D��Nk�ٙ�1���x���~�[�l���[�9��XI2��BWѶ�>ͷ3���Ā�\��R*I����gvbY���z�m���t.���mҸ��w�W&�U9��:�@w�.����,��+�D�i̺�3M\�<lZ�;1r;{��l� m���-ժ�Y�F�R+�*�N��9�S���}�ėvr�Ԁ�>Q�%ؓ �ͷ�=$Ҝ����Y!9�X��s�: +�et�L�^�;�T��:����j���Νbʼn�Nx����ú�T����Э\��W75ާ��P@� +ꉞ�7߫���X�A2s^}�c8��EڠJ3T�bX��J{�ݹ���Ng�zI���x���z�Y @Vf���2t�+�8�e�H��C�ƲU�����y�uL2"��q�vS�e�sǓ����o+bIKw=�����h�E��M�^V�S�Z�{�ݯ��W���s>>O����U�X�A鯞0��z����)��]=�[u=�FW�YL��V9-��5."����n����Kk�? U����UW���I�\jHm:/8r��+ؙ�N�k�G��%�%��C�`� .r�� YS�m���Ҫ����t��I�t"��2y/�ٖ��ک=7m�X�NUN�c+h��Z[��m��Vyn��<U��ݲ䑤1�B�Q�qFO�sz�=+�a��:�Z!$�Ʉ�cSK2az큌e����ݪ�ؒ(�̚k�1-�5Ҩ�W���OGҕ%O������[���\庶�� ��Y��$�z5����Ѭ�ګ=$�t:��+��,�ȯ��b*�_��o��~��z�c^�a�ެ�d�Ka��2F��F$����z5\�_A��T�Z�~��SMT;��b���?����^��B��-���tbUbIt�?K'=�kZ˹~��QEoI��a=Y��ҰD�5i�XH�7��6v;] U9,�YaE�! w[��+�2 g[:v�R���fҞ����\�V�I�\]68��L�Y��P�=tuy�; ����W�]�]�.� ��;3��فV��]���N�ҡ]5w줭�����[2u���#�@ ����uzZ/#-7l�[��M]�9�^��� \~u��dω�b��[o�Kt�L�~�4A�V�o��B�V��J��x\�,�t_KE�^���@�}Z�7S�~�2�� �'6�z;s���s��Q��e�s���t<NB�b��{�����y�Y-�o��W�-;h���س?2{�KiJ�-q��s֠'������*�dy�0E{�y�c'�ʪ�_oo��9x^Q�ַ��h�s��ɷW0�B�3H����C\~i��(�u[�M�a�},k�f��%r�tl\~G���}�Z����ۜ�����vޚ���nj�H���E>���8���KڭQ;��a@+^܀!�Q}!7��U{�*��KO��F�n����>;6�������F���uUz����"���rMY�OF�WV�.y�VI%�ۙ=*��6y�쯷N�z���2�}����ע�k�B�IP�-��Wpx��Yי���S�ݮÞ�˞�$ǰ��l��U����?&�[��tuh�m�͓*=���S���y�lP"�M:�H����g�^S!�%/w8�֧/U��=<�����o��ѥ�t� ����Qٚ��s�Eٞi��Q�n�����l&��W{�`�L�6�<_/6l|T����:�r�$TE6i��v�2�B�4�Yo�n���\��j�ȷ_t�E�Z1=�K2�4��,�1���w>��U�KQUԪ��u�ѻ��U\ʬ���,Po�v�[1U�W-m��Ş��A�n��w���ڴ�8� +q�z�H�괦zђ��h���o���9�ZbP�r-�U����[<�5Ӟȝ�2���9������� ��������Xf@m��[7�uU���[2���^U���؛��M����,���D&U�Yو%��4���Z���W����y����]a4Y���Q�%�!էV���y�t�5��t��\��#Q�̀�q���^��S?+���%Ѻ�,��.�7u�e���$"%w�NkX���_M�`9�H%����Ij���aؘ�<�5(�-gCm���^� <*�I���QLzZI{��аf�$G�n���^XH ^O��Ci�쭘8�~dU@3gN�{M�9gw�I$$��`iϠ�̕�;^J�$Xh�F�d�Z5�..�^������k�v�rj��lZ��2AF�N���-i!�������5�2Çܘ�2,Oo�����q9>k��������9�������� ��b���Z�/��LGh��ՒJ�3>='�M��*��J��_f �s�L�h[h�{�##1�2� ��-&�My9^�����м%T�� ��Խ6YU9�0ʬ� �:5S����@���#9"�Y���h�M��=��.n^v8��EX���=l�������-8� 'W> +�$2�:چ7�e0N��]�m�k�Ս�����<0��R��ﵚ�d��N�|4�s ����f�hd �r��}�;�-�/�6����f{os_���o�tB��v�7E�����L�h�Bo�6����A�v7k�m�9f�!ԕn�Ҍ�S����/ � ��jݪT�EDT�*�֢��)�E�� 0���ãf��ٚ�`ϲ�(Ҭ�틞�Y�+���WGt������"��# ��2�&�z���wj���i�mي욫ͺ�-e��.N<�j::�7Zj@�b��)0�OE�c�Bdvb�^�t_����w�]6������w6��12B!G��\_?�u��eY�YB֭����6<Ն,�+Ye�;�u��e��/V�9ZT�$�H$�B%�7={�(�HP�(�]�!�>�i�R�2P]ʬ-e���u��c���Ru2�@A$�H$&HD��y��b����œ4�I�Z;}�y�֜u��sc��X�Yu���-Q ��A$Y� !�xXt%�X\y(s#���uh�� c������ƺ�$�$B@��I�"!�O���iiZ�g[�L�3]`�Ua���c�=�]�� &�c!$�A$%��$��-Q*�ɧP��$@I1vwgb�����Đ����$&H �H�Hd�<�0J�bϮ�0�K1&Fb�ř��ݝ��!���$&cI �I "�$ �by��XL�HZۮ�I bŋ;;31$�$�:���KI$@aH���1U9'L��e�n �Ifb��I$�$�I?��������������������i�Fؤ�������А�I%(D�I �@ ���04$ �۶�2�| ��?C39��RdH BH@����`� �ۭ풜���m���|w�k�qseM��H�1$�`!� {��T�2�(B���]?�\�1�Xd�SlR��I1��T���D�`0�`��ک�Yc�H@_����|/���e�E1H6��u`�dM�!�@��`Ǯ��̲�8I�.��ֿF��3�����M��c% wB$��������]���(R�~��A�?������&2� +@wB�Ć$�@ l��t�nL�I$/�a���}��Ek�DD�@2P��L�l@H `���n��@����<O������{Fh{�s��Ԡ�B�Cm�B��h���� ����������9��rq�?5�ڐ�J�j��Ht C��m�N�甁�?D��|�4\w?�����7��]t��AW����TJH N�M�zb��!z��m�g�đ�/C�}ß�pI�i�ʎ,�)�`)H ꄂ�i�HBuz��4^?����,r�����::�$�4��ˎ��>s���H� ]��H@��zz��4۟�8z=&����/�qW_l)�٪C5��g)�.76%H@UBJ��y��z��^��n��i�ώɕ������}=� #n�m7���y�W,g�s(HBn��Ѫ� t���c��s����o�(Fއ�1�k��V�Ұ�^��4 ry>w<�M��C�}O$�>���~����y6���Ⳮ�W���$Oj����:�YuX��/�w������)ӵ��o�>��O������^C��YK���.����vߡ�8i�q�N�̩Ha<�6)�����zi�� ����Ϙ�_��c�����}'��q���UT�����1�;���$kx��_AK�J|�i���+���Q�j���5��Ӯ���������{c��oa�KiƂ3�~סg�����֪^9tq���# �&+?��/k�I_/�:u�o�z��F���g�z��Ǐ�k���M ��W���� ���K�x%Y_NzH��E��?͔i�I��"�������T��O��[˛�o����A�J�|��~�QSx��4�"�֘�,8��R'3�M�ݿC��ܪ����9��{�����z��t�%χ��f�}^���Ly�o�k +|��eպ_�8������w>o��UWzm�}"zӌΥ��|�C�=�r$�O(:f�C�o���Y�� |2=/��O��q���^$�t��}7���{|�G��7��:JX�¦4-��z�2|~������w������/���� YNk|����o��Ή�'���ω�wZz��I1ͦ���e��%'���lO��ާowE�_�����-��5�Ƚ/���o�oG�����}>�DЀ1wh@ ��>�)�R�������zَ�7��3�۰�:S\���u���7����~��1=2��D�o�bm��:�n��#�٧�z~��,��߱'TRO�Ͱ���O�ў'�e�^��e���SF��&&m��Ƕ�X�i�~S�\y��n�s�yr~w�][��D��0t������|����)ߔ�44D:�N��$�LzV���:߫�J���Ds��o�|�^��m.'����T��|S {z=Z᥀�U��g�2M���r�.~��3��;I�G��x~N���*j3��g���ڕ���\�^�[�e�ҋ���<�O����8�~~�kbzi�$�^��8��:�zw��b���_w�:�B���+�F%tf���X�V���f�tO��ek�؛���u~���8|�m������{�������4v��2�i�ic:������aom4�(qv�UV����]/'��{���goMG�q�Ȱ���~�Ӝ�?-Ö��[)6��y������s��c��ɾ9����s_�4�>o�����vzL�z�0�ϯS�{�#8��~<3�zT��ۜ��Gng:���& �Z��v��F3�T~צ��|�ܟ���Z7�<|�[�:�2�.���?c�3���,�kT��T��'F��^|��q�"|q�~����^_��f��i�JÞ=���\�?#��1�G�x��Jb�#� �u4Us�h��!+�]����AW�GJ�َt_����wH��y3��mg0��s�8ߦ�4R��Q�� +u1&{v�� �u��5�?��h�?k��}}wm:6�W+�s,澎����g� 7{�Z(c���5�ߜ��$5�4��L#,��/;���D@W�����6��Ӳ����=����-��RM��.]�d�>��F4������3�mѷ��{���������������/WД�c{j����+m:�S��lLC��s�`L~ϧ��>ǝ�{}A�UM�^_/�9����g��6&��)�Y(9n4��]m&�fߟH&�=?Y��� u�^���S��^o�F|�����ե�`4m9�.X.msן%�s&��oo΄����<{?�~ ��߹�ZuT6p��6���>�^ՠLL�CxiqH9�թ��)�������Iӭ��8���y��~���t��Sl�/��\�~���=�wLI!1� �{4OJYF� �?�!1U;�,5���</�3�_��{�*�c��^7�[z��}+��,���w8i� A��KM> +4�S^Ǘ�����G�~/��.�[m�>��Y���B�X:h��6��: ��J��93�p���L���o����7o�|�=�����69�*�+^��Ζ%����Y<�T�40�Y�Jß�_;y=���ۘ�]>�TĢ��K����?K�ؗ���5�Z��0FJ�Xb�%������߃>��S<��vۛ�8!ͽO|4ޤ�Q���!����$�)K�z�,�9�e��]Z�:n9�]��u^w�;�^z�\�8N� �ML�`�fR��{�V�y��L�KZb[i�9����g�q@��]ץ�_k�M�����a1))�]�9�LJ^�-/��T!D*oM��p�YaWM���vM�`��9��D���v��ÿ���>�G�wujꂐFj^��tV>m��c�7���c�w��(����"T���y�5�i�s�ٯGGf�L!��Zv�m�x���g����0�Y��J� ��ДD)��}^k�Lz�ߣ{�1��:m>/0V��o������8�1C�*sB��%*T��^;m��6��`��`烟!餖���ުM%�[n��i������� l�bM���3,��+Fvww�㊡�Mh�+9�X� H�(h cl1�q�� (��{u�M ��[` �'(��RKBmH6�� �`�O?%sZ7���h��0�S�C�BJIR�RRē��B��\�˭��z�`�*Zbb@)IL�R$�19L�LlH` m���<�5�]��途̦$��IJ�b�6�@�c�J\\�7O���Ġ\��I$������&��������0 @P������"�UUG��ؒ#���^���u��w�}�߷}���`�a0t��cP�@�V$��^��<�Se���]u����}��}���b�(�7�T���W�l���WhI��R��6�XS�]u��}���llp�ʠ���gc�_%sK4���:�k��n����l!���~�{n�*k�ؒ?�A��h���������q���P��~��r+=$Q��a��3��5,���l"@���u��R�eH�clo k�Q�=�������p�H����q5�|v0�y�J�8� ���?�8�@��a�Ӝ��Ĝ�S_J(��=�m����>[�����$��׆=ѩSO +{{�X�eb�ƭ����gW�A�sg.�� ��+��qZ�d� ��#ۚ�Ci�ڎ@Q�#��h�V���p����颯K_Z��$v�G��o�$�Z6{��/䍍;��$���ٗ��MZ�7�c���~Qv�j�!�����,g����+vI �{9e���ME�r�$����vi��1r��^����G1�~����N���'�۳�{c_Z�$g�8��u����ZO�Wc��qI`�릌�x���vY������[k���ڥ�����*���O��3{�~���ZP�Qc��*ê��Hw3���ߙ`��힙3P�b�(���-��W^�3)����� +d�;��mW�����K�W�/ �ڭ�c����21�9?]��viE�kYaG-H�*g"�A8�߱�������U���ۼ�CG26finܙ���y/��Mud ��}���%o��7��EK�Ak�?��Y�r~�vm��+�\C�2��Y�L�I$�;�����3J=}5O^���;�y��ܳ5�]ȍ�Z���X�@�y뮳�������n�*����!l �{����y6��ȄB�J��X1��gaRJs,������* <uS�%ݙ��Ėobm�b�r�҂��cG�P��#�tڿ�hH-߅�W���E���Nr�O5�1��o fvb��I/�2�o���l�J:��a���Opy����Ѩ^��\�=��W�y,�e�i=լ�w�4X#e�f�'?��������#�nǺ[���+�ӷG��H�̳r^}s`[{��g%��Ì0�g��lɵ�Sٽ>��t�GD#��r�)�&�d���@"N��-9I��������^�Z3�����$�D�(�RE$.3Ui���{9�U�κ�s��M��-Pj|�_��2Op��P�ƹ*����F9�I���n��f9f��)�1��,Lf�H���"�N�\P�����ok5ϣ339���3�-,u�R�*R��K+I�T�O����b,���X,q��vK8l�R�uX0o��|:묔�{��}��OxrL�Q���&۾�������EI������������DI���ďNyUd�k|觡�ujXD*c��!�%��j�J��SB������{v]tr\�v2�@��?��DiCJh��h�ԉM�����A_f�!\�£�7"�I��$��«VI���3��k�3�kR6I�tïVRv�(\������J���}����[Y��m�����_de��&��Ū���*�IY��Kݓ���J:����Z��Ẕ�X�ffe�I�������rލ���]N뮳��ѣ�e����+��6u��\���� ��[:6�3N���/��b�P�m|W%��j�A/��zo����C�ʒ&�^�K���nVd8I'��z�<����F�A�6I������֖�hkM��{4��5~+s�q���fҭ��4�Y6X?�T�ZH���vhv5������_�����#��K��� �=V�����Z��=��i�Y�=i!h�&�+�d�.��#.6���UG��N�/ʂ%�S�.�n�����s���5Aā���cM��y�5�-3���\��P�����>PF�E6����E�nl���Ԥ�c��G:\�A�9a���i`�# +�;��������J��령zz����ʖɰ���ʭ�! ���s5b��A,�Ź}پ�_�����,6��c��?�n�����P�'��>���4�q����;��X��+�3��1�1�g��؞�iv��yҿ��w�9��/����?���?�����Qb[�l�8����g�*D%�c��F^�e@C>������`Y�'�?"+0X������/�u�z����#�Ѣt[Y#{���g +���"�]��d9r-u��U�{x�����X��]9؞��<����zkܩc���� ��4s�������nd���N�xzSbFop���C*�NH��݃1���:�d+#���w���u��\L�+��R���9hl�L���Ž����Z�r7h���nS.�Ma��֨�*D���|i��a�K�'�x����H�Y�>S�4��Ϫ�ScH�'��ʆ���2uA��U�zV3��vU�-�j{le���VZ��v��B�ڵ�G��nll��rL���-�����v�1�SS[C�n�UV1-�?5vϸ�������_J�{�W� `�˜�KM}�|�� �٧n�}�o�#A�¯�~3֒�W����V/��R�F�A]�����<U�A��Ľ�|-W5������W�W�d�jڲ!���X�����������9uE�)miy�Z�S��H�`��\���} Պ�r-mm�o�nUUϚ����8/�zz�A�r)P�;=%�7�([�%l �G��X���gsq�>I�i��H_*@N�if팸�{�,ɨy�:��~a=0���.��h�U�o�8�N�{M���&��Z��Ȥ�^��y nG �L\Ai�����%�Yj2�1�U��F��F��7����WS�&�܂��q�.H�쥒#�����5�ܚ�u}bk�"���B�����hm4h��6֑�I���É��ϣ�\��+J�Rd�l�V��� ��.ſ �6��q�Mrk�gW�� +�^:��ϯ�_�'�)���sjm�ۭ��!�˚�O$:�Z�ly>�a#��a�}Y �+�k�H��˗j�C�Of���Ǖ�;�%�ya]7���u/�k���Q��zV��r|�7M��kobG�uy���F8���E�9/Q/����7� �T�H��G�eBr���u��2 =n9���Ի97mi5�j�_g.��؇��^oh%�Cn +��Q��H$�����M������{"x�Q�FHd���������|~���� Mx�� .���N�z�z=qɟ��o����Aܶ�VȖ�������*d�e�zE���N���"h���r�Fl�ғ)C�A䀣;�l��BF�X�o�J�e3I�ڡ,F=7�8�;D����@Q�N�hE��ӫ��l�X���2����A�V�q�_�PSX�#�� +�%ֹ����=�o������-���w)\��FM ����)�Y�.HA|�+5f�Vgl��|?���|��5����l��ҧ�����^�VH� ��\�������T�RYV���X:�ܛ/N,~�_�� ������w⤡p�$#��h�-�2�/�%c� ��X2l�EQ�EV �}��I'#�=�5k��殳V�䬆]��I2XN#�l�D�d�i��e]�S�Ү=�/�y�� +��c���s�Nu�J!@͕� ��� Ԕ��6śJ��Z�_� ���r#�bD�:��EaPR���)*m#���ʵ��5��:]�W�;1%�td�Z�b�����3�A�f�X.s���\��,o�G��J�u���6������3X��5�%�خW!���+l��n�,���+:���U~��� ���R��* +���j�,�.�=�xt/��ƭf7����8�C-Vv4ޒ�! +<$Wie���ˣ�><4z�;.�B��}=$���ť���g���\������<��DV��ۄ�VJ��Ūj��G;$�R��/���^l゜b�bʶ�;�}�M4�nL|��A�=� V�������.��X�ֳY A������������NJ���C-�V+�J�B;R{��oV/ƈ� �U|�����{�_���������d�m��Ýp��8�P��Z�G�)�X�Ar9j�<:jt=}B�ש_R#����`�O�C��Q �'�֒*q���6��Yx�n!��|Y�҈�Xn����n��8��f�n�]|l�-I!��Çjj��T�!�J�S�c'��Σ^�zu�u�x ��a\�ޅ!Gf:����.�!;zp��Ig���]��Ç �=��������|����5L�ddk.G��p�Çi3Y��`�8��5�����V�,bt�G��zE�M���<x����m.��ޢ�c�4N"�Q�|l�������`V�$��j��?��'�4�;$a\%Ʌf�=��2!������� +��ƈ��!X�l%�ڑ���o��7�RH���[e�7"<�����;�۶��M6k+������Ӵ�I�OR�#���5(0>���d�aj��.�f�Ņ���/����9�m��4�.2���v_�������dM +�_/����1z�&>�iC!����g�����,KJ-dZ�i*����x�ܨ��n5���������S䵶�.JMo�h['��g^Z;:M������]���.�6�[����=�w�$ɦ�z��bC�u�N8�9l���^ +�Ʋ����ߟ,0ĭ,h<;��O(��u�$;�-ez: u�`XD�u�Iƥ��T�q�U$��#���)�KV�Z�1�0�X�2�f�u ��~�?�a�_k&[�����d��������.6������̔PWz���\a �����c�a�8��Y~���QS�~"!��bj��&��}n�^�G}۫�?�6~-�jư�l�Y��ɪ�V˓�}�>N8A�~��/%�.I3Jd/������Ό�:V��0��C�Aok����W�sU�5۸&��D_T����� +�_*�&��Ͷ���Ԟ� 3g_�L���^�X=��g]t���4�`���?�<��m�#E���7 D��`����ݫˠ����NE_g�&h�x*Q�6���9`\2���;��*���&'����ƖId��g�C��p�Ç͆���ͻuh�g-��M�)<#lE�|fv��k�����*'��J�� �%�v������T��� �'7�e��z���FE2^��6�y��x���,�4�'8p���9��˽�ْ��حn.i���_Ɍ�]gi��l5�l�k1l)sMw�Ư�V�0�l�I�3X�r��۾ϛp�mA���O=�j+1N�x��N�I$�6u���_8p��ɭ��mu�_���h߷��q��[�o�;+W��{��ZkOo� �\�]����F]��z;�|�8H���_ir��?ӯ����XY����_dzI,���I$�X�/��8p����Z�'�I�_�Oz=���[/;~n���"�h�K^�뮿Em�~gW�q^e����ÇŜ�4�Rx��㮢��r�[h-�*�x�G2��O$��d�X�ĒŋaÇͶ�]��Y9���n^��/}�����_?O_^�z뮿l��sj�|������GWk31��'mKj-����e$r��y,���X�bĖ,Y��� ����d�:�#X����u���lx'3�o�Í�lه��yL�S)��e2��{��Y�BkK���;�obŋ,X�n�Í������#��1�SӢ6�����������a��1������77�?+�+�M����5SUb������˗�.[��ܱon�쓇�x#�|�_?@��}Ftq������p�QǷ���o��.ͳ���_߲KiK��>�O�йr����-��_ܹoon��(A����.t<61b�Y���.g�ܤ�f�l^��]u�tKHek/h����O������d�}�O������}���z����ׂIb�p�����9ƛw�q�L6�h���}}}Y�W�%����}=����������C!on��#�:�� ���Ç���]u�]g]uוn�4����:�n���L�w�K2�{=������������������}�����J���!1"AQ 2aq#0B��3R��@br��$CP`�4Sc�����5DTs������??�X+���e�/�hL�{]bY]6=Jc���¿�_IM��ω8�-���ӣ�O��i}P��4?�m� +{�,iD별]pZ����{))�D ��i�4������f�ӹ� F&�,�����q���]Sd4P?�,,(��\��en�������k�kx�U���8XV90�����.{��N�������Vc��wl��2�2A�d�������,N�U��t�� �2A���&������e٥\���WᆭF��]����Gv�(�ll����X�W�����,(:{_f#�s�W�e��o L�c#�*�$g0�+%�E����rW +��X,Ր*����j��N����RHU�,<�Aj���_&$\:����͉�9�`� +���;T$���_�Y[ia��?�p��5����G�d�y �u�:gے��F)���1��� �I !��tOv�h�Ge�� �汞㷗+�]F�J����x�Qo�w�|\����8&i����j*�cK�� .�V +�FWXh��2X@�B1�@���wC�����,�D��E,'� ��ȱ��6p��'�ٞ�Ս�t�^������Ϊ�A���Y�`͎��UQ J�h��:�6P�gf����]��F�ў���5`�ʹ���� M��H4/�Qx�8�X�o}��8*Z���}�����8B������"s�m�)�3T��� + Qu��C�(��TC�Q; ��-{�@��:�P��Ls]�~5���л9��@��[�TG���U���UN�>���M:�3��ZU�г�5a��Z�%�od$�ul��3��,�;��L�ʎŮx +���%�Tl�=őv�+�1t��X۬g=V��ģ���98���� �QN'�*a���Um�g�J�n����i���}�Wi�����QIfO��棘]����g�p��$�y�[2��e����D�Lvo�r��R3�ߪ�Fְf��� �a�U���xG�{�w}W%�� �ea߲��� +�f��B�gT�B�����Ne8T����MkFY�{߳H1f�j����EԴ��NJ3���}����2����J +����z{�w`�J�1(�-QE��a����y�����+�_Tb���P|A5����X��f��Ľ�/&�+�h�~�m��l,���_����n��O��9��^�ޯx8©����=��鵅��E �ȼ��d"��"�sn~�A�V�MK1:�S������Q��2�Ш�m�oߏ��0@��?�:)�%3J��nIR����j����?�p�U��Q��.u�bj�w@؆��?F�\�6l�b�cn^eLd�#�i�o�a�X,N��/��.���^�kV3r�j�/�rX��rs��tA�a�D�X�>i�R{%V����:���D;�N[���O��2B~����\����X��P��(����w��o�R�x�� ���0��u��7# �Ɔ�U42o#qk��*ʇ����X�&��@ꨨ�z'o�t��z����QP�r;3����/ݕ#~(]�&J��}ն����u\+N�@���(�˚���V2�M���d�p��1'�?E���OEgߑX����S��N���sLU��^j������f�7ǙN~M +(����xV� ��Q��#�D�:�����sB��Ꮘ�-��dފ��t��MF�,����b�l���s +�i��]1�Z�S� }4�}�_?��zt'�8rXf.p��ܯge���#��-�(���IC6��u��@JmǸ�¼ך)���(�N���6U���}Ŗ�fv���cu�0�*��-�^l�ӻbExYs�6�M`�Z�K!̧�i�S��EJqD�F.�͘���p�f��,r1�Y�a!c`����_�j;�3���nh�!qD�ѩZFӓr�}��g%����挵ns|d�EH,o�l�2Q�y���94�%`��c�(���3��m��l�݁��� +�x����N����H�.H8\w�G<�ٕ�y�h�#[â#Q�!IJ�_��59�/>"n��u\+>�[��]ˢ��RI��9ɱ�� #���nsQ��ezm��3|ћ|K�M������C_��/s�q��`�zp���WE_T4�)�\��#��S��Q�y+�<,�j!U��r���!���g�3�_�߇�P�ᕧ樻o�d��s���N����������[Ɲ��=��k��� B�c��D:��y��@\+y-�kF���j�����4��� ���d�>� @f��q�̬u�vߢ��h9�'b�̓�6h��Gy�I1�N���A��D�~��n%,�NmF7!YO��xŽ����!�����{��@ o����&�ݙ�ʹ�%�e�[əL�v�7.K ���s��3����+�!��d�`8�yo�+��ń�������[�p����,�ٚ��v�?0�����+���dU�F裰�"6�f�y��Ce/#u0�0�nQs��l(������d����iW 1�������l,�M�Y^<]Qi#��ftPS�r|�7 ��\ꋽ���}��tZ�� �n9�e5�ao�W7+�1�Ǔ}U�k��m���Fi_1��K4�bt�Ѣ��+���%�wc���x��?��SWDod� +p��N���I�4� � +1��vZz�G��wT�F@���tn�)� f�٫�����(բ�ݻ�����j�� �\w? 6wШ��\z�_T���SSq�Ψ ���t� +��bmơs��E�\�d,M` ��t�Τ��6E���]1��)�`�N��7q�A����'�6�ٚ0M�g�洶��Pӓ����兹x��P�dp{�Y���,�d�Tͧn�k谰���44�Qg4;�/��X�)��?�&A&�_ �G��i0��<��$ +r-�e�=S��S�7����c$�lBc�:h��CC��T�F/"��|�݇��&` ��p�X��҄Ѐ +�-�eN|��wB����骤��덾��CMk�&h�#��kl*i�����-�TG$G���]�b/.Y�a��*|pru�~��Ko�{>W�b�����q��_ᝇ��T�T���q�/l��6]3 +#�������.{Y�s줈����Ts^��$5M��05O��ves\!欬���dzj���r�L�g�.>^�5M��9���~���(�|��z5��<��'䷓�O����,�ם������ڻA�<����\�r>w|Z_���(�i��:��B�c��?�ͳ��F3ȴ��8M��c浲<����mW�%w�y�T��B�h!�"��j��J8o���l�ƶ[��p�<������S)��6�����6f� ���%�� SCUͶ`�V'w%���(ե;��<�qw�Ò)�Y����[������HNa6�̩���$��Ļ:�����>��B�u�G+���6��UWD���l��{P��r�:gcr�]�b���b��X�WܛL||������T�L.��=��͌ۋU;�*^З�V�G���;,.�z������~?��wD�z"��:������_��в/:�=�(G�� ��5��a��?<<�آ�x�·�;�e��=�� +�xOȭ������MM��x#�G �F�����9�������r���Z-R�v9MER�iۆF�v�#]����Č�5�S�ُZ� ���,�t�.��ٮm�D�%m�������KM���*�����*'e�Qa���K�Tp����-7Y����1َ�K{2��3�<�@ ��O�e3A�:"o4����s�#;���Y�b�6_c�m���҉bu=E��r�M��e��^l���K�����OT�s8������4�}��aIZ����;������'gY�{e��x���hK)���7:ذ7qh�&�������; �K��G6y�.�����}^��k,������� +\�,]z���~�Ps���>ا��3� +��;#hɣ�i��J�Q��s�v�B�|�VvXr:�Էp<Nz�7��!×�a����ϒ���v�v�>���)�/��P:���t���Ƹ'gڛ��D�l��dx�����������誧';,oi���g߳�$j��%7U��r +�욽�ִ<ʆ�1m��@�(�y ��]Z��.����Nz!�N�B �9���p�r�T��$��n�H��5#�"�Z�2�62��Y��ʆaxR�I��6��窱-*�� ��|M� +��������k�����D�e�C��m�3u�v�햤����٩�3��\�Y4����hu���Y��W>K,C;|%_�*Zi�����5�fs��]�9 e@���ZU?oGSX�qlj����Ϧ�%/��PWT`s$��u�P���Ͷ�<~`�R�׳��;�g�GK���i*'�����氌C^���F\y��/F��V`aFox��X���G�z:�x['���� +�s&��p���]����5Y��x�k��p�yf�������6X�Ev�a���7�M�n������G�7���q�U�qc2��i�5 �'��EQEqpt�XNg�7*Z�o&`���1B���n�Pq�M߸'�-*��MG�%$�q�!����D#f�zLm>�5k?���(1���f�b�6�Xc8�QAQ���jb4��N��}�n'��E���2�w␗8��EJۿ^��� +z��R5���Z��QI��^ 曂�nM��p��AȎa88�@9;�S�X|�Nhp8G��`"ɤ��@%�i��8��?��T��#�zb������v�'ˆ�#���%൧�#䁜J��p����Yo�e������I���&���.��QE�r�n�e�a��N������p�����D�ɲ�џ��oSf�'���J?��OL��x��U��Nj���i���˟�Z��V��b�� ��tU��|e�zs/��|���v���T_���?���Q��g�Q#[yZM�u�;�]��d�VB٣yk��/��O�Q8�^<�I���$g���D��ӚC���*��Y����gcq�GP7�Ä~�b�D��(�� �����5�Y��Bcj$���� +�Zv��l����9XY\��Rpw��I�e�8T�d�pӏ��3Ȇ&�f���1���tWϚ��Kƥ&�Y�Y�Yc��(�5C�惛���|��Ky�lj��U���CJ�-7z��u��7�?@�d��"G[)�80t�I����*�::�(�q�Ø��h�� `�#{�=.�F0~������W�%K�".��FY+���W��]���J��ܾk��id�/{,Z�qo���ø��R5DŽY:��tn�e��(ɟ��'<��{�n���ca ݂�\<ةZƷpe`q7a�yr�IOJ�+�w��-#�C�E� 講�$���Pr)�7dl|V'����u�wi�\B0.j)���m��Ϫo�������QM���|W���Ӫ�8]�)��H<���nRQU�Q����\�$s�����VG\�qTG�&���>��!�|Mu�6�i3]�<R��u���T�a6˙]�;�2��w)�N`����N�T�����=���XJ�A�xݠC�@7L!gb���r7������I�XE�"�n�D�6�d2̠J���d�H��Z#�g2��0���D6����7N�B��ٚ�6� +���0VhYl� +k�6�r��\M�WN5Z��.h=��湨�n9 +��;�`m�N��s0_<O�D�:�\G���:|��e��$^�As�2�I�HCڬ�o��������d�|��tc�.��(q\�I�$Q��J�F��9ϸB2H��+�}�(�����X,��G�6�?$�����A/�B���f�)��0�r%RJ�6�ә9�)�|�1�д�� p7��lT�J�dN���al������p�|��Dϰiwm��Y���_/5Ct����!�}cv���[�6O�\y��tn9��?�l6Q9��og��J�g�)�Z�`;��z��&��.Enj�����A̬:d�z FzuO��E!��W���N(ݟ�� �5g-�0:齮�6+?�V0�<�tzƻK�$��Wڢ�|��s��Y\�!�=�{F��Df3 +G������{��VB&tꪂ�xU�����j���: �ZB�F�N�{���N +HZ�w9\��<��h�CB�SH7Oa-��4(%v)�J��}�fF�![ 3���@��broR���'�h�7e�Ik���1��_T�7@�S��q01��/RR�KM6R��Ǐ6�l�a�g>�F.�VKW�ω�G���̖VM���>J�iDg.����r.���7�^�3�ޚ�t�]GQKR���]��?�n�7�9S�Z�P�Okb.��?h�j)8�98A�B}���o�����g2܁�諣#z0��*'�L�@z����J��b����Qi�i�bn/��C�u,ؤ~�W0y!� ��9bh�� +�Ê0~Jf�a�D�\����� +���p�̐7'�AP��{�iZ��s�G(.��ߒ�3���M��=��tف�9���s(�n����=a�˒�˄l�J���,n6�:�g4�y,�y�*ʺ����9���.���T����h�-�rX�`ג�%m���h]a~���'<9��v��o2����U2�J�_ �;�_|�_c���gyOsoDu#5� ��Eڐ7�Ձ����44�3ۂ�� ��T�o�b]��+l�X�5�[�d�N��Ɉ�Xb·�o����XZs�<-��Dׅ�v�Ǝڝ���&8y���h�4�ǫ���6lۑ�e������^/�T��ڈwg�31�TU�f���?U���]�?��T:���u^h,r��Wpط�d�� mm���蚤o�I|���^�5*J�:���`�<sZ)����GG(�܊�0ػN=�t�G�Ϳ�衯����'f��XX+�n�4��2�k����B�J�\+��j��\#e�%f�8G���#[�٠�ZU[� +�ٿ5EɷQJ*Lq�, ��g�z]���-�E�pT����璪~PF:������I���|�8�q�>jCp̽�̔T/̷��A��o��������;,�j�ł�~h�lvn���xߙ�r��cF��M���W�����%���dq�D�����z}Fi�Q���l�S����,�U���h�/~3��+v�$?�� �X���l�e��v�=Bl�1�����,z�Y�u�B� �io�����s��S�-��]+���©..���Ey�4O4S��rr;��f�j� �Oɩ��4wb�8|��W�gg��[��7�賺�tY��?�ꄒ7�3 �l66�6�Q�}�O��Y���#|L�r:�*��]�B�0U�Pd{M�e�J[�ITҜ�USf�� �D|����6i�e�I+��#�T�p�:f��L%WTi�觗9 *6�!�P��QǔL�)����:\�H��<�Ln)_�F�g�2�eT� ��,���z�xGԭ�|�q���<5[ڦEȜ���&��ӈ���\6��=�ArW6�8���,NwV���,���,�ϐ�͏��Y"�D,S_�:-3�V�TAk8�˘UU�wW�M4N0 Zs��Ι�ҩ�����_�n/�==99999;��+O��2Ե�Ԧ��ٕn�=�P��U��@�%7hT�y� +X�l�aC�FI�R��]bm��H������X��6��0��Ү�x@:;�\��I��L]��? ���p����9\��G�S�/!Tp��|z)]�_R�pɹu(7�a�R���)7bhl"p�)^8�Ј7xn� ���,>�Q�gêݞə��QO���K$����ߚ�$�z4,�g�Z�Ce܄ծ���+y3BC�W�������<��t�4�yz|#�������4-r�k�jF���}"��Hh�Ϛ���Vya�&PN'�s^Ht^K�y/$:!�s���kI����oV�����x��6䥪�F�3��*I�m���4�[f�7'TT�_���.W��qtM��f���\���Wz�%���T8�c�����O���#��VnDŽ8�*8|y�2��)d6j{���=�xA>��'�9�*6�N$�$�xS��T��� �M�;+Y��u�侧D �t��㑠�5L�����sțlc �DVꝭ����R����~k�̯�l��?��2H��"�Ĭ��$�u�7��IO��*���ѿv����τg����(�����w��<����$I�'d.�i�^�]��3b"Ď�i~[:��ҋI� ���ńYx��X��n�� �:b�AAf���j�aw�w���`�:��������i2��Q�D#o��wR�+�w!� �ot��}V2\5:�4�l�AA�V*��4 ��!Y�qmmge�@~8����;v�k}7��8�ٝB-�����R=[Ǘ�5f�����s%�B�'w=�dv�i���\��fUUV���O��d���ɼ_��\S��E�*�>�C�5[7�N�~W��}z�ֵ���y;Y˟�[�[�6A�@�ee�f^�!#�K�o�;@�9��0��c' +.uΥ�F|��?����y�xS"��E2H|�.UU�k�y8��R20b8��А�u�#�n,�g��t��O��N���3S<Y�e�ܝ��geٕ��mU��O ���9�����oi��U�]4��&�T���.q�3�{)�h�O�h��Pk#��!A.�&���<NN|���4C�S���3�w�ap{ +l̿>}�$�ڨ"n'�C`�X@�3�����Hy"��;9�� �:y39 �~��"ݘV1}���[�ǚ�+��sz�-�hT�H�CE�Ed4�����nYsP�5�y��| dl�����'��pMӑ歖!u-�4�h��eِ��3;�aT������';2�F�)j����';�o�w4�MG��Hgg�J���o+1r�]f�+��:|�_�naq��Ѣ��bx �B2Cu+������.HE�u����_����ݎ��m������'6��a 15�6��a`{���]/�utu��f|�F�;��e!�~&i��-]�Q +Ǻ +�0��&b닢�3!Ñ +�=��JἎ 9�v|�W'�/���o� ��R��W��%䰶�7}��ų3���;�Є�e���v|�n�Q���"���I�ON�g�jj��,�'F� +8�1�Ln�0Hn�IVs��QiKx��r���4\ -�m'm=��Q���$������\��O�<�L�$9I;C���E,�H�E� ]�Q|/��`��G:Bʨ�FT�V ���R[��/Ѕ�0g��7�3E��,wC��s�lpЩ��28�3�*� ݮn���`\��h���_��F�`>���\E�.#�D[�˸-�d��^��=a�,`�W�[4:\�C���5v�f㨲Ya�sG�;7r�qE�w�8���C2�����G�����S6?�Ŏ��W�N8[��g��[��C��^HtA +�!��g�l[��i �yu]��/u=T�Jc���F��s��t��9<���r8����؊X�a�~�f����lϸ�j�Y���.}���U����T�\����.��}�x�c�O9RS��қ��]�ڭ.C�� ��T8�G�N���Ʋg���y�]vl���� F��>��D��_a��<!�7�E4h�N{��*����a6a�h� �bT�Xb'"��NO��ߪ����N��*�|�b��H��!�䋯ԭ����5���X���V+����|���I!����Uf�Zl9���<-��z曕�b�����=�k� o������ͽ<��n0�'��A,�I���ٯ�v} �07�w��.����5}v&hAC` �iJ�&"8SYf��-�7G(�5(e���Kp���u'fdy%aj���j*4�p�[aE���s�����p�mo�������Wc�kaB��UD��G16M�5&��G� +8clQ�l ��+��$�ݱ�k��N��2Cg�=�R��l,���-��Yi����t�Ra����e�{`�"QŇai�L�e�F:f�߈��`�,$���/n�����2��I�8c��矅QU�]S6�G�GB��M{q5�\���>�p�4\ߢܵ��$i���4�,N�� 6�>��\l{-�ڏw�����9``E8��}����D�Ovy��*�X,N��h&C̦�@�br4r@("욃/1a�T05 Tc@�i�_nJWf��M'�Q�Ł��7ۮ�h�k�xg<��p��s@&�S�]�# �3˜u7Aָ�cF��'���8��>Sm6�7 �M���E��@����+��T���g?L&� ��} +��1���������̳{V�|����FK�*��B�w�xȟP��s�m���L�6GXu=J!\��cy��%����������*����60b�t�F��2VX: �`� +�|�~�2�W�Ys:�6�"�S��=��[���8��]�s�ƈ��j�ɥ�j����mN����ܶ9�@^�'d��:�b�}�rn�,�sW�ai(�{�Ş�v ���.��1�9�h9'�)*��b|~�"���X�"��a�9k5%De���^r���#��������ݻ�]_iZtZ,��d��- N�F���Y9�\���K��X�j�,��\��qv �\��ٹ�@C|� +�Z#:9o�U�ylc�� +�ꌎ�� J-9d9)��eШ�����M/���(��N�<����r�S�j~�ħ��U=�v���*��!��U#U+uE�Ȍ��U��+2��0��עd��7�F�|��~�D��s��� \6�FvVFH,3-�G�g䡨���4>�� +�l���G���m��3��4#P�NM�t����DV*�z,�p���N&��ol���� ,�<��WiTK{��{eo���*�ÒP}�"w�5Mpޜ�q����6�+4ry 8]E 8fT#�Qrjo&�� ���):�y�[�N�-�,Z��D?���X����A��41���Y]���ڙ#�����$nM�B`�`���@p>N�"��g�?&��UM�a��Mlnl~����v�=�5�f��� 5氁~k ��@�� H�tT�U��<��t���2B�g�y�C;7��;���H�~�� *>���i"��7U+d������P<�tmYl��YN��Ua�},&��v�-��Z��w��C$pɑ٠ǽ�V�yS��d��(������@:�Yb(1�氅��� ��-�#�!ۇy��9ګ�C��4��p9��Dsj� v�� �e_!�����\��� �2��S\�eru%&\�S��*i]���֏ӧ�'��5?�O��{q0�F3x����q��o �6��-9���A��Dž�_�S�����k����v���h+�*�S���]�^�Hb�#�.~�f�*�:����a�E��������Zr=�E���,����w]���'m�E�'<Yb!6�X+�����5.XM�%f�@�YX���TLԪv�� �T:�6q�sO|a�S��7L9�<��M�e��XE���E�-��)��W��Px#Gt(����%×5#�vvU�f3���b�}����t"nI���9lN�S��~��A�p��HG��v���E_�D�f��'�G�Dr�e�б4{��b.e��]#!����W��"x���+t���)�#+]`���h�Ћ�qE�:�w=�������V��D1�g�r��bqr�Xo���1���(#�#�N���Mx�Ǣ�����y��>��[`9��j"������o2u%9��6�BK��nWYh��7y&C�|ϴ�dg��d0�N�n�p�V�5x�����2����O�8�$.朜���1?�Q�T�:�`�U4���@TNi�sO.��y/-� +ܶ�t�j�U$����--CX���UE/�o�ph +�� +��S�=��Pώ��� u��+��5�p9����h�u�d�_U#�r%���Mcx�w��2Me�$ ��Z�?u�phtWj���H�ɺrrr�sRuRuO��7��y��8��r�a���ɧ��kۅ�'o$��7ǡ�Ӣ{%�tp�gZ@�l|�_k���[uc�[�n�F�D+�;���*��x��bs%^Պ�*w�ȅLk�hET��v?"�6*���hs�鹎�:���)��e14���y�6[�c{+,��'hӾ +�Ø�z��O٤�O{��Q�h�&3��ų�a�ݖE��Q�`X��h�5�D��M�f,�<xF�nJ�?�\z��&5�B�������?"�S���#m�W��4+=�cŌ���F�vH�cȁ�/��;LmwARR1��B�}��7�Q�����a��~j��KU''�]�<ג�� Ŋ���y ��V�>&���[��RN� +OLx�&;�c�J-�!�,&�2��%�C�W5g+�W+5�E�p;Ę�1�X�����;�_��@���!`����V���mB��'潌1s�V��`�7����2�P�{09ڛY� +�vx��ַ',�ȏ�� +�� ��a�}����J�U��O}L��t�&�/�����0��>k<�"�Ĭ2U���3��v�3����4��*G��vt�b�4�9*����%��D�i�@��B+ �j���iW+2�+>�t5G�r���� }��;O� W���q�T�l-�-J�555�؝�,@ ��ڕ��專X�TػZ���N)H� Q����qI<�0��:���ka������t%���䦧�m-3qH��S���}��61��CY�$h!a�y�Z�4!�! )'�sjZn�x�k��0�q��� = +�]��!����ӊ������Wn�����Ⱚ����veE������* +�&i����G�z���DV��=��pĸ��\^�� +y:��^{]=��W��Svg�j2����'���}��n�w���?�7����罿'���\�����5��O�jU$��U���a 9� �.���e��O6.ϙΨ�p\�c�AG�Gp�S�.�.�&�e"ʦi_]N:xu�5-EV���v���!���ę%C!i�n�2��v�Cx%w��r~��8����ed�E���u�5T��L���%v��x��ʦ;6�#�曮˭�����dU<��|�O�q�h���������*�߽t�Z�����r*�����;�2��bQ�M5��|�TT����D�]�k����tf���9���>NJ@��ѣ��#��� ��m�)�plu�2���K3�%9吿�MU�2o�$��9���&7��X4uP����y��Tt���u��/h�ύ�6'>�NUsI�Īf7.�M'���S�hR}��h�{��1e/��F� a�P�����i�14�{���B�m�v��J6)Ѹ�� +Ng|�E|��dlNѮp�d���[�);^o�pS�3�t +���g�mf���I2��O�����֏� +�Dž�$ԃ���#~�܅4��u*c�'�R�(��-<������+"e5C�;2 ���A�\q�Ֆ�"Ow +�+y�t��tn�DdP<�r�uٖ��.��nѪia~����ǖ��d��Q��D��ʦUS��i�u +ե��Meh#��ĵ@]��|מ˅��=%#zl�ه�'�����Qؕ��7��ڡ�:X���� q�8J�V����u���Ȝ��$6�辿�)���=���~�:���<w�J�� +&����C`M������2����|���k���� Y�����@C`�u��c����R���J��TUq5�u��w�aZ�� 9�tG��(��i����2���Ц�FӚ�;�+4�@Y�4!�s�D�����)������!1AQaq��� ���0���@�����?ub&1��)W%�k֥@��{/H4ىCK��e�yQ�����>0������[�,[VI� r�.\�K����R�J�+� T���6�+)5�+�J��q��=���� +����8-����@_�Y��B\� = +�T�R�@��l����r�˗/�������ը�����9�� P��j���V�~�j���Z�� 5���a���TH�ʕ*T R�zT R�J��r����[�����ף�]�p]jn��r���F��Lm�&ޫ~�,��D��C�¸�U�Onc���1��2��SpM%D�$I^�T�^��J�b��!~�������J�*W�c0Ll�_~��pK��B�z�G(� �v�NIc;�٦�JBKn"F�ߘa�w7$��%@���T!*W��}HC��������c�q'�?�!�{����-q�C�^�D��%* +��`�n%�o�b��fp�z'�J��a~��C��������pLR�a������.&�ܷ�8�J��� ~�^�z��M��V��ۊ�����f^�*��?C��!��?��������E�Ń�ܷ������(�������7F�}6 E= +��=�?K��!��?�����=<������S��5V��).)�k�ԹY��t�#f= +ǥ�%�,���aı�d?K�o^������C��}o�0F$�7%����]u��@0F�Ѹ��u/�����`�E�����"ea>�s8��a{��<ˀL���?I�.r��C�����c$)G���,׆!8p��Ȕ,� ]�+a�����B�F��R��`ԂC +��4�b����]f�B퀧 +���@`�2��A�&2�\J��$?C������\>�}a���a���"��SLt-��HC^������ +<�/�lJ��2�b�9��9���23�w����p}Q�l>P�[��!�&P1V��2 8�W�@'�1�W�B�}˃G��C��c�%?E�J�j��K�@��bb�1�bRa�a@7�W� U�R�l�`(-k�!b�F��-���l�¬�R3�a�A��Sm�%!�x�(�Wv��$�F�!�au�lqd�k�2`�6�h>�._�~���c�0E7,}�Z.o�Y�}�!v��ԩq�Z5���]m/�KD,>�,���5`0�*�j-˱,df����k>�����^�Re��p�چ�oQ���D�q�U��z"v@`�F-��Y�e�3�U�AN���7(���+�\�~��~����\~��TE��9�*?�l�F���Ny�JA�IhLq c��H�Cj����0 ѻs��@2�) F�n%1�G4�w�7�iT�e��E��C��pa�V\/�IY^b ���?��h!%����e_2��u(z����*�N.��F�����7������%UU���'�6O�4�q����˄?[���Ԩec��r�J��+��۸UFM��a�F�.ARע���X_?��ir{�"D���9`��G�Ya E҇��m���:�LI]J�z�1�8��MAp���)Nw��F@���LS�fZz�q��<��I�@���PÙA�%���*��0����"�]� +��?p��y?���k��=0O�����J�l�ZT����_��?���!��)���Dsm7�N0˾���.R(TuW�x�f��ߥ���wif7�]E/��$4����-����p�`�� ^�+p\��|�2���)��h�¹�N���,:� +:=,��l(��)�O�2��.��LimQ�D_ ��R��C��C�0(#˚/o�A,�Z�./��#s5��+%�11�Vbǹd8�^���� 3(Âi#��h���FYDsx�P��:��jQ�7��],�n�%�����$D@�~"����/��6̢ˏ�c=��2��h��嫻2��n�`������Y�Q)��!̪�i��Xc2���N�R��M���qb�-U�O�$�w�͋]�m��g�j�N�M�F`��3m)��TҀ�P��>�-kU��a��q�.`�w����Z`;����w +��K3)�LBf��c���/{�jHq 0���'�QR�P����~'q0��r�W��ϑ-ge��V2 @��E�A� ˆ��feA[��n�Eo1�����"�c>����1r/z�N���b{�o8��V�|L����x��p5�������� eڿ�I䉕����Ků���"}�I�����)�w2]�����;b����V��l�?�fy!�J�e+~�Rl]x<�x�>��"��ic@X���8%�ϥR�`�s�a�E�E<DB����E��3_�/IUN��s�W�|�4sQ�D�?��&V��"�w9Ւ��c����¹�S��= +��;��Pn�Z�Ǚ��5�e��rɎ�%������E���s�$_k�L�NчL��-bpW��U����M)/+L���$�>����e���Q*��-�jZ��s,���B�������(<,��9�A�T�Z�|���fʇ�]B�A��e_q���n����*O��� +�����Or]��v�=*%g0�n�[�q�`�典� +[��&*9bl[yg�3AU1Ь +��2�}Jc�sw�_�ͦrJ>� s�;3ۨ������pY�9Dhamrm8M�|EJW���2��[������Yܧ�뙎��m��9y�Y��%\DX�y#�h������~#��f������7�nY��6�0E�}��-X���pe��n�*����S�?Ԣ�赗1-�3�e+Z�q퉐4�m�"I4��1!c�㚰s4C�4��a��)�\�a�pT邩��#D����B]�Iw�a�S2�G�Qw9�!�{"^c6bUeY�&.��#ȅw�:�S +�Q.`2�ͳ9�^�R�;�����bNa�ؚ�H'J {�4xq���]�����{h%�{��C��8�*�7q c�e�;�j��-�^5��Ks�pn�x�0�� rDXj_k��h'���W�I_�w*�l������WqJ��T���mǘ+�eeS�����6�2�5�Ƿ\�s5^r�%Y��`��)�=����Vy����4��j�Kk�3 +�V�N{�sd��k�X�UǼg�s\��70���7��#����+db����k�E���b��|�*_Gm��v�s��n�S��e2b$څ�����#�������]hB�D��LN����K"��d�*�*3?�K.����(�0k7�Of,L���yJ���n��9g�/����2|C,.�q��vMq��� Ӛ��k����S�p��,�:<j���\�L6w�q���2�!\w�˽o>e%W9 V�䱤b��,A��T��#W��Yy���K8��q��1¥�g(�jT˩�۲c�\��^� +��p�{�� �I���` 23��`�)G�_P +�ī7�y�(�S�b)�/H�H�/�l����rtdw)����bLekr,(�e�G�y�]�6�e��+�}Y��$�R�k���՚1C,�QW��q���a����K��uC���9���r9�����y����lL{���<�NX�@LQ�{���K��S�4�,,��Q;�x_�u[KMn"�)��Q-�K`㗨1K�O>��lw�G�cu쵂��S. u��]c���,$��h:.��`�9/} s��_2��n��Ym�+�<��dy�]����F�_��9��1��@��j�l�TLLsR�3��ˈ��J���&VP���qXb;E1�3լ�u���"1GLW�"X�A��x.a���C�c�cz ��Cs��Ă�c�ty�(�֟� -9�PY�hCsH@�݅��a��K�ޝ��8j2Ǥ��8p<�#�Ŗ������E�g&]�T���!��SGNhh�h��x=̹�0�؊�u�6��,\NUo��9��p�M;�U��pQ� u�球GI��Ĺ�Ӿ��7O��Y��`��] ��Db�\F�V�ǖ�3o%7I��P�@�Zƣ����Q?�A����5�V�5f���/0�{2ۂ���.���:�;�1,mXBXrL �IL4��pU�9��5�4�L{�?jV����G��p�MD�b����*&�_C��:�_�L�b/�Ij��8V��L���L��_�f��5�ڞi|AV�q0�p��pa��Hۃm]{K�K!I^�"-�#�R�L��f�ހmb�Q�&i�*�I�3*����H��D< �7g�#�����#0N71tb&J�?�/y��t�;� +��(�|�L��� ���h +3 �p����+Sm����n��Q�Ϙ��}��v�:ܬ������{G?��E��W��"Lњ�7u�t��Sl(�B�F �Z8\�4 �k�p��@@�����b�p�َ�K�y��$��a L�x��K���2�\?2��Z�|�u��,��9�0����1u�j�^q����C�&^.s�Ǫxa�n����{����b]��-wt����,&6�Dn��]�$O*�[)(����-�_�V����Cn<�۹xOb��!ĵ����Z�۟�H��%O�?�8#�l����Gb�U�Ol��UoGP�<8��)c-�v�%�R>?���l�1��FU���I��E�L�51�)���{�m$���P9f��M���� +(o¡��j��z,��*�LM�]\����2Q;�4V�9p�uPƋ�e������]~f&Sc���u��~s��q�����_�0�Vb��4���8\��Gq0�� 6�����癚�����Ve:YD�1.F���k��G�� HsǼ;��̈́I;vxe�b_��#�H�"r�#�W���r������7�<�̡��A�� ���|K��q`X"���1o�G(ј�����AB*x��WQ����B����:��ӻ�(luQ��pn�T-v]w����(tҝ�D�j�C���� ��6P��+c��:&'PDus ��� q;F�����d�KȉI�s�Թ�;���k3�w9�0�*�}�j��Kxr� �*\�*j�>�������Q#�U��lΨ4���I�BQ�>���LJ�QAq�_:�.�YP�{xU�u.�3tP>7qܱw-��É�i�i��07�"�]ÔA�2V�,j2Z���A+�}To;��)��?#_�(C&��]�}D�H�dvsT�U$:�;YD���Ŧ�i�R�����%���)> �E�����*�s,����5�|��d͛�h�x��s����桠�f��bH#Ddw,@�w�y&\�wܴX:/OP�TA\%̳f��;5q�V���� �-D4.��g�J�~�f;d�KT9�C3�oy��c�2�J�s�C,�5�=f�n�y�Α��Ƿ�l��l���*6�<������z�g���g�c�Ky� �,Y�>[C1�h�ܱ�����1S��\J� +]�Ç���++g^cu��+��l����}� w�ДF�P#���¸�K].�JaՏ1˯� +ϙ`mU����Af�Z����P^>H�Z��L�W.r���R�(:���ۢSɘi@�+Ε~�A����'�v�"��* ���7�~ҝ@�+�7)��u� +Q�_��X�x��!e6����-��ރ~�f�B��!�WK�'��+��쥑!�ӡg |�ng�!ȵ ����\����`�C��Y�!K �[�v\������i��ބ��5�� -��{��\�6x��ݕf��Qv�zZ��q�_���*��L��0n������r�m�2�BfM�F�[1�^*�"�̯�ً���ڷ��M|�v, +Top'R��r�p���F�Ȏ�W��e8�ʕ���z^pl�6Ǣ�19�q3��Q����,�?~�Q��WƂ�g��ڨ*�J\T5l^����Ϲv��u +ƈo��"��9���9�>��M�t�H51d۬g��H5�H�p�Z@�0i�[�Xwm�L����S Rk5{���b��,�7�x�|���8>�����ޗf��R)EX�{T�YOR.��8��8�A��-���o�5�}$����rݵO����8������(�ܩP�he�I�O8�6�,�JV��~b�y�{>!{J��b�<��;Cw6�!`B1�7�&'f�oci +��� +�Xk�z��>���6�u�B}1ˉ�CY��XJ�b�w�{�2����ŜF���K���V��шkĬ�����2 +���*���W�-ZU|E<G��Lq0�b��[p3��7GR�4�.���C�������g����1c���3P:{G.ٔ���`J����Ǿ%_�_ ��">��=���)���8��J=�5�-Z0}��%r�&/�A��w2u���6�� +�� +�8����\��}�$�g�ʘ��>e�JЧŎ �W�nߙgWW���`�q�՚f���j��_La�#��E%'�0s�ٵd�����e�Y�pd������N*�#���Ƞ}6�R��.l2�no���7I� +E��Ϻ���h�qT����JE����/��C_��&�%gj8?�W��?d�H���_�@-�T m]�%���]9�7 �/�+�Ak�1��.ʇ:j1{qA�n�����&u�9�L+Oefc�g����J\�T ���/B���Zk1�z��#�CR��!�W�J�������BP`�g���%���P�e�njbd��F�-�G2�O��!��UF�Qufڼ��Q�1��y��D)d��uM幬$b.N=��9�}3��i/.%2�$dr���.�2�9���nb)uϼw+������ax��k�\4F�XU��4v9}���(�P��b��E��1�e1h�A�J��6�Y���/V�;�@��)w]K�%���Vg�1 �DT34�B#(�b��� +���JJ7E� +�� �y�C�.l�+��{+7�3*�� +lj��F�.���:�XS���<Ë�� +����ij�P�Ɗ⠠ �2�DAeJ��2- ����U�\^ǚ1������!�(Ws�"19�>�bX���_��R�l��Qk#�MjX��_���{�O:�,�_.l�F�x��&;��D��ҙ��`�1���0`1�pܷ��A� n'pnEp)3�b0C��\����"�s.PF��ܱfֻ�رo[�\�'bAԡ������UX�x��O�d=ۀ�'��lƀø+�.��1���Gqs�1���a�%���K�U���/��9��l?���O�����a4�[��4>8���P��\�^�VY 6�s��"��:4�_��3ޠ���[ ���٫'h�:��j�pF�&�?� +��P[<c1; +�2���#@o�E�u���y� 4)]K�`�D�5W�1J�]�ov��.�Yvu� K�s��QU���E�p���sy�*�)�dM��<������,�p��nM27o�Rh^�w����nd��Vj�t�qB�Y�� q'�K�Gq���Ze*<� �0��@�D�P���J������ G33�2�j�[�5�[�>azO�>c�{a�K[05�jP��IAP�7��l*�{�I�s :��#��D{��bƥH�Yr��A��"�ī��.vm��x�Uj����J9~u:r_�!YC���X]�9j91 +�p|^�e{��8�(!t1J�P}��X�F[�����[_��1E�Fͳ2�We��;����-3U��f����1��_��þ¥��0����.�̼�s��x��_&F��6ow��)�J�� +_��)C�E���Կ ��i��a��]�c���(�(�0�nfB�Q�:_s1� 4j����]��K;����0��lt�H�$\�����G;e�����.!eR�R�2���0|�@F��?�%l@SP+n�a,����j�2�O���Ι���cĪ��[�m1������<LZf�d�2Tg�2�RY��>��I�`$��B�h�A,~�E� �8cX�=�/U5r��Bj���˖�tKl��35��N�f��7����q*E.j&��A��������( ���~1�F���@�(,��R����˕��)��ӯ�x!J�X�1m���Gf��Y��Gj��e�rq�R�"��\�b�g)G⡖�7�&iM�ጒ���>�7�t��^����2����8���W�1j�_=��V����0=J�����ŧ��_v����ܿaC��wí<��,[z�t���"����r������r�5+ڀ߹QE9{E�ba���?[��{ZŬ�#)i��j�;_��1Q�jF��Wo�TΊC�`ځ�B ��( .���r�� ���y���i�����E�J}�h��@=e�&a����P�M���<�Ȋļ�6�Q5�*!0��f6uRuWQz�Tu?1�m��*0ƴ�8��4�{�l`9V#R|�~e���7�\Ls��q��+<�� �5i�[��������@'��wp%���!��i�Q�7]8<�)���"�]n�x[_Z��d +0�e� �Vk��u������|�^�:iuw��e�����e���k�p+zx�FwQ.��ୠ��?�c�F�1s[O�R�E�aP��m����n*�� x�N�WO�i^+�&��c�hs9�2�^A6��i����r�"�,S�����*T��$,�c��u�6D3R�i���J��)��^��*j�PQ�z��0�T�О�����"l2E��U��J�74����:J�}��&�6�� �R���� Xl�6�xb�3r�A�k���1T6�ί���.�L%��iE�qM���cA���������"����T��Ĭ���C���P_���a7hخG�`-�JDy�_�9U���L��s�$�+}�f +������B�(�x��-c;��h�P��#l���HL�N>F߈�qm/�95�����.���#��b|������K�⇿���՛�E��VR��)�ۀg�@"��Qf�8��q��[_�:�N-������3fn�� �"^)1KZAgb�����}}GE*ܽ�v�� �a�0���� �\��F^1�ٛ��9����1҂Fru 4�=?ԯ�R�^Yzʢ� +.�a�-t�E8p:��Hyn�m�!xg)�ICp28�'8Ƶ�/���s�F�{b��G]������Z��XF���s����V�������4ǘ�8��0.�T?��h�4wlL�8�f� ,J�}E��>i�Q)Éjl6�HW��K6�R�ωFr2|��F!��P:��/�"��:�����E�'�e��vU}���s�z����X�\A��9vD��8���%��F&�ߙU�Ur�*�F ��&��v���7:h��,�Pj��� +?"ਠB�U��{�wJ1�N�SUd4�1��o�.���qpU��k��.�����3>j�=y"W"��J�15<3>�<C�#�:2���)͕ +�ϟS�:C�F'�6����NvL��~FFW�4/$\!�+�y���}�ec �m�}�bG� � x���uQ�:�}�.�l�h&Չ]��������=�̇��ڪ�e�8Y�1�����Ц�`�`���Yl�@���5qܧY^����������U��L�{���iy���J��(�Tٯ�_�K�������~�}R��'*>�H9�t�O0k�&�o�2������F�b�M��M�聅��NP9(�Df����^!X���GF�ڕ�����("�̴2>{�� +������,+8�̈f�߈��uwR���8E��\ױ�R��/��:��� �V7ɉD�((�s���;"XM��x�K����:���]�K��v��0��ߵCoQ6�.��+Nϗ�˦�Jb���G���}�*0� ��&�d##��C��$��r�3oOϴ=��p�,�[B�c{:<�/�'�>&s� \�;�����YQ��@S��� �W&�GG�,eg��C;3�k��ი\=h��W�IS�����D'\�eΜsw����8��~����z�L����h~����������(�/��XR���K�o�o&�,����%��}�Y�{��o�wF��|�a{;`&Pu����^�lbg}C���e��,�������X6�����t��&��7���Oa� +1T�[nN�"BL�J(�(Q��X������!���C4�YCJ��u���#�y#�n��7�-�[�m��3E�O�v� +{eh�vL��PX���"���V�3�����<�G�@��y9 ;����1PM~҈���P�m�֠sc��e#�A�0-������"���!w�lJy�Y���P���msZ�4L2@��+��.Ww�w��÷<3u^��yeҎ���H�nZ�u�A�l�h�����\D�`��2��� +V>2�lj��Y_x���fq�_G���J�]�_�5�r~8eu튾������,(&�`.��0P�t�Ƣ�v �?h\)}H@5�8v�cT־X`L�8D�K���y�h��J��a�5���&��G�*��KN=��{��0nJp�>c��)C8j"G=�u�S»*����m�~":��h^�x�m������]�x����⢣��N� +�7�UWO��k����*-S��0�צJ��!LD#r0>HV|So���|���3����`L�\CAo|���e��\�= j�1�+�� j�e�V�KČ�,.�1F"��~��¸Ĺ�� T7a��s-t�5� @����Y{�Uj��Q���5�;)��X�V@��k�oPu�`~ĩ�C,nO-L&ÀRa�|BO����Q��+��aec�7'��|�����2���6��X��CBv�i��7�?�d��(��&�ۼ�<�Ѻ��/Wk���]�������4<�u@���+�ן>b ��N��%���_$LuM(� +�;�v�4��-�eS�L��LJ�V��_L�,wd�\��mDsRG���l_kW1�B���\F��?Դty���CY������/y���E�(����3� +�9�'H�����8dy��sZk�S,,�� ����.G����������-����x�E��j#�%շ,H\��<D�����.��Ȧ ��֔���1����hs��/*C<�u�yDT2 +ޜ�-�(����8����;�E�A1���l��f��w�(.S���J��H88 @�c���,4���> wx� aTy2�/2�?�YS�K�Q +`�d�o�4���kL_;b�>��a�]��+5�Tb.U9:��t����6��R���1C�+p�F�t�V�9e0ԥ��Ki��M�-�v���D\��\���T�O�OL +�a}�XmM�O�D܃0��{��o�P Z���)����p� X��}��C����ϸ�&%U��9b����b�軘i�9�V)RǙ`[ �f���Tr�'s�L�&�,B����}W�7�AupL5Ġ��Z���F"����`�T�-�P��c�Co*�oQki\�.�`<���E�<�.�3Ԡs�3��6���v�(��Z�lZF��x��l�s1�L��~"C����©��J&8ױm2Mj�:�*��P�L:��)��á�[�p��F�b�����f�ނk�ȟ阈�|,��7(B + ���Mί +�k����4ڵ�����R��i�u�j*%`1��$1�^�y�!�����B<�4x��u�PQ=����x�b#najnv�����Ә�|���U� )b�KWU2�5��?h��l*��p�����.�疋�e�l^;��lp�'�pf����^ +d�+R^�(Q9��,�NT�eĭN%1��W%�6�Ҭ�Q{o*�etc�V� +;��������e��N��U;����������'3���Z�N<��\$�6���&~ c�Z�yHSR������F��#A���y�6�T8x�;Tt ��;c�Piz�u�#7�%�i�������X��(�vH�b<7�^�E)�߂,�@縶�R�]�9a�\�� +����祥W3%<E,� ��pN��hem���b��q,��.ոh-���^��2�`�/��2��U����FK/G�17\m���51�ߧA�����@��Q5�;�XԸGK�� �q/����}�٪L��l^i8�����Ƴ�T ~��G�~f4<�� l����,���4�<�=���|$ ߷ٓ�/Q}NT��8�O`+� z��avLx�0Sᅬ�(t4Lh0�m�z�"�S�[���A[\V� s��������t�/0S�x���9`���Lj�k+bT�/�8�7R�w�Eјy��\D�ce[��@,ڔ�2� 2� �+�;��p�4v��<L��B��N�cԎ<}�c6 +�qyL}a��= hŪP,>�X��zB��{KeW�Sq��&" +��0kQpEc�^�[���,��N5�*ί#?���n����7�= �fg��������c�H�Q9��~�4�wT�k��� ��lB+�/5�ྠS�-**J.���}B��_Q����B��q5u�u�|Y\KP�����Q25M��W����H[H�d�<)�9�a�P����pQ +�uܺ��O��壶f���3Q,F���Q���C;Xgv�0���e�Q��wq��LA���|�J�[�����b7�̰S���*�@Z���)/U�ܠH�`��r�IP�p��6��~$_q�`�Hn$��#�J"����cM䨧+!ɽ��}��P@EL�^��� fU^� 4Ĕ��ǘ:/Y�uM�,�0#�h�%}�Apܷ��m�2bm��!VVۉw�3I3`o�g�`ḛ�+�e����#sQ��}\u&����\��CN*�Qw~%�u�L0'�ĉ�;�0�S2��� r��y!�x��sB������I���'���v;��W0�ɚ��%s�` ,������VF�F$@g����ڤ�<���F7�Si�T�>IN�� �-/r�ʣ[-�svẈ���ܩ�G���;�^"�q3�`�,��z4l�~��|� ���2����U����9�r�S�n8!� ������!:e����MM| �He����A�q�qш]ͪ�Q7;~a��ȟ0�h��{�����yD������q,6bS����CK�q �x�p����fwO2���[A����u��h����~Q�d_�Y7���� +홳�s�( n�X%/��k%�a ��'_��*L��G�mQ6���R6�dJ��c��)�hxa���_2��vVu7 f�L��[�����ϳ��^c��e���P��+_�_�N��J>������C �%�rbVȬ��?MJ��G$����|�.[��,�ƪo�"ئ��Tq�}�6�Z� +�9H6��6+�bq9�%�!�e�*_���~�|X���lщe-K�S�3�D�u��%W���qQ�T}A���͑ +���Hj�Q "����P����K4�W+��/Y���tbR��``}��V0x����KENlTY���d�n�yc�ΦU�Ppi�ۯ�j~�{�8->!`iC�aV�אà��Y��N���&���5�CLx�:�Ɋ4��)p� +�j����T�3��5��g Keģ5P�֠�G"Yr�,r=7�ʮ�L:��_�@�B�r�˗�<uH��pl�a=�J$A�r17b��"��Tu��=j0�k.]�V����\?�f]9�?hdhbh����R�z��iSM{@��'>f�ڥ]&Fq�����hٻ�q�Z�lj�<D�.�h��v� +����<�yF����A�w�K�*W*�/�"_c�.ݱ��߆ Ҿa�:�}K B�8&GpN��ծt�PBų�����;!s���q�G�а��=*ȼ_�@8ST:O�|�U��;����tbh�#�/��CѨ* +U�H�*a��%����2�,��#����#��Ú��͋�T2����B��3��i��w�/@��Ś���b�8���Aж߉����Nu2�f-�E��PA�t�n��ʚ�t��.ܠeEAQGX�b�&`f��:*���,�S��d��Ey���#0�K�]ᕲg<��"��I��A;3V1o�Ո������O�1�l4w႕�=0���b�!w�#)��-��.0Y���F�P�9�A��`öJ�LWSQ���.^" ��Y^���X���B+l�1�*�'=�df�����f]Uz:"�D@���A,!����b{J�=� +y����.*V�����38����T��������,Yگ�� �4�G�;x/��ހ�^�,����'���@=9!e�������{JK��֜�(f3��NJ������{��]B�Eu.i�_��r�I�1���de����n,�O�A1}O� <���|<�~3T�m�����!���0�_�i�#)�<��ae}�7r�����aeˊ�ip��٨�F����?�b ��/�s�s��Ԡ������=;A�.��+��7W����$ķ�P��F�gF,,G�7O�E� +,g*�g�Y?�g��U�o��vx��|�Iئ�W�јP��� sm�Z�;%�v)�x8@7�� �����ZɎF-�.�K�$8e{��6��Of�y'��7�a���)5�H�_�YS�JQ��*��;,u|M Cl���lf��%G� �4ů��� ty� �`w�}&`�E��L�vCՌX��,������_3iz�w3�Q<b�?�����Fx�j'nu��D�Z��Y�2�aΝC&jȀ��C.: � +%7�ʹ��K��iY�#Dau6�"�0�Ļ�7��TCD��y�#)��?$So�^���h����)ဨ�����D�J�@�F.�gh�3дG�NP4S�b{�t�˴%���E�@ekz��W�s%˟���� c�r��) 8S�Xݢ�X����Mb�����S~ʊU�Q~�aG���$D��26|������>��D�fYq����^X�Ź��:�W��~�`�=����)�qk��!��(�(�O��Ĩ�o���?o1ϻ1�2��2��g-O��}�����&H��ނ�� a�#�ƯD9��������1��x��?�,�{ �6��p/�������j�'J5.� +�� ����͐��+D4�i�vva�����R�~��R��z��U���ܪ�U}d��c�- �78�7��J��L��|�� ��v˭u.V�(%��Q��4_��C$�!:�ꉍф��[��7��_�2�Fe�3�+7E�2)̨ ��8Ϸ��O��^���b�8�D���&=>�{��]��a���R� ��W�� +�(/��KӅ?ܵ�q���/�@�&��\�([��%��{���[��q�\�0�����Tc�R�J�(A2LC�k�?=X&�������r�k�k�K̳�X���������}eft��5��G� +<�&�t7��\��+c������Ʊ����3��y&��˹�2M�����,X�"��F�{�Y([�4pڶ�6���W��P�Pz�����0�+�D�x�T��X��A�C�����20�P�M�r.�FDϣH}U��c0�u��O3���̭a�(˕Q����j�����@��l����$�<1�����>�=Ϧ05���Q?�s,����%�Mb�qGՃ�x�8��� �P�P9%#S�U���������z3���P\��>f��zUzc��\������s +&�"[��Iۇ~%��rC��_ܵE<E֚�h��7���N�s�e��rO��>aH͘�2��J�̭\�x�y����l�#�7��2�.0ϛ�q�daa��<'���h��n~=�DUE�^b���ܼ��xOO��s�~��*U@���������p������#G(��ZV�b5Z�E�U�+�U��L�WQ��Q��a�\�g��B��~'�=�w�Ot|�-��yqf�![�_,~���s�q��}/7�B��b�0�&���q�X�a�(��r���ǘ����z���G�w*0Cf̑"�a:�%4 L,�����@�����U��Ku�o���lw,�L�+���y�OE�(�G��_8��G�y=�*����.\�O� ����[��w���C��"5�z_��Yq�W�B{@'��J̯���9(C����`�;��>�L�i��-h��x�]���\A��iᗘK̰�9b�S�z3b�c�8��v<�|�$X���E�K�.\��Xؗ����Υ��S�1��+���Թ�zW���(��.g>�r��J��Da���\��`\�y�L�����le=z�<����c�Y +2��+I�fGqw��r�d�D�k�s[���X����U�Щh��+�.**0˵���Qq�/�������$������ 0@P����<���� ��kQ��AY�MkZ�#Zրֵ���v���}������6a;�]z�c +��u��X ��X�6����Zֵ�4F��o`��۷m�{���&�7�a&41�������m�}S6�b��ֵ���n�����>&a���A}�e��pE��R�\h�~��Z�ׯ^��0�<<a��� ��[!�XWN1DZL!�������Z�kZ�0�ƚ���@�{@�N> W�,�! +�����:��?A4h��h��{PQM8㛒�<c�,W���A��?fa�<h��h�<��Z�"s� ���c�����}�����0�p��5���m()\u�.k �;��)r6����|?�aw0�x����j^�c�p��.g1�� +�>���EKAMk�<�V�}�a�0�c����JS\e�M1��־�Z�)�z�^- ղ�>���]O�Gц~L0�0�sa�c���o�fN=��;�B2����v�UX6�vF����1�KU�?;���0���ƆG��sV-����z�ض�!+�w�\q�hX��2��fk�ɕ3���ɧ�\�o��A���0��a'�A�e͊��J�4]V-�X��vM6p����Sh��w6�͡�+-��1�:�4.�9�}� �pa��İ:ЂGņ����]ar*�iacY��m�eie-b�J���������A�f5���k��e^��G����<��ɏ"��#��pa��Z��w0�5�A��Q�A��ۼ%�fÛ�6��Ȣ����u�fcUBՎR�#DkZ)�4o�8�-y�� �0��c&nk�{&�MVSmX��R�����-�a�[nm�A�K��V��η�7ض�%��*���6�������T�k��A�����|�Ō�����J(t� �ĉ�'��&��=�gdy�+aX���y�bx1�u@��:�^�&�-��{���L��ә]�� �4��Z�LL��-#_��^Ee�BA,'��Ei�h�Y>U/�۲����c۱$�c��@b���90�!SW�b�p-)d6!0��e��s"�4�K#C�5�kQV�Ⱥ� +,ŀO3~�6.�d��ウ���{?m�t�N��j��p[��@h�q�ti�.@��|e}x2�*�\�D{�U�,��+,��,�.�f��)z,[��5�Z��W,ł��.�0�����(��:�і- &�֯��x3P��,��Tr�b�KX�w>�`�ƅ�e�VPQ��#�G{n +!*�MVH���7�w��cH �oO#W�[L�"�|<�f�+,e�5��ƶ˼�}Y�ͼ#t��uL\��� �2K�,/&�X ���@<V� �R +�ڄ�H���˚��5���R�a$NĘg�ͺU) +X�A +��شb`��^�k���!j&*}��lӑ7� 1U��>A���XT j�V&_:�S���_.����'{�>_��)����7��� mY���U��l�36��k�m��6\�+h�#q��u%�4ɰ��#����C�/�&�4�P���@ A�lV������|t� �s��1.JW���|��z Dp�֪���Ii� ��ɭLb�7�A����5�Z��j�M�k����.hQ�ag`��С��z���l��|4�̲�Jb�w,G��ab%U������d�U�ZV�5��f��5�D�|]����Y��R�mI�W������(e���x֘~��k\ܫ�� +�qL"�X"�C�5� +kʱ����$�s������$���$�e�oY@�YH�4���K��wbuɀ�� �ee]v�b�"c�5�u��������G={X���C���qY��8X�w�E?Uf �<�֭�N-���U�|j���Z��@z���k\kP�)ef�l�;Q�a�V4l�����`#�J��ƵS���g���L���E��m�����t(� ��W�4��a�[��x����ze-��|� ���a�����،@U�<k],k���y�$'/*[�SY��4F�Ʈ�{r(��8�6�����7���efl��[�O�P�w������j��>���S\kPL1�8��~Qu�`�/�՜���S+�D;$�l�Y]e�QR�v˳�=獱°�r0��M.��ر:�7IE��B�z��fL�[}�Y��`� �X O\�r(0 ( �]���w��VR"Ƙ�Q�t��YɤDl���{w��;v��[;2�:�s���"����BWxk*l06a��р(��~>n!�q��������S�u-\ XR��dZ��m�۱ ��`�q��^cOp�:^ۛ<�Ї",�Ҫ�^)�xݘ����|k]B*�!Cqm���N�����ba�f"U]fgdg][��S�%"�"!�@����AH�Z˖�,g�ۊ��#�\�hC�2+�@x��b�KU��7|S��t�Ӡ@1�A��.�(Pg�d�"3 A�o�� '�-H���@��H�5� ;�؝�&إj����m�~<��TVQ��GKU�-��Y�9{�����_t�� �&����@f�1�Ⱥz�2ǣ*�YP@�pR�[FZ��]�'}�X�_�7P:��j˟ �f��b���7�!���6�Qc�W~ݻ��۷`kV����.)�b�&E��ead�����uabƮ0�,[�`@�B�]@8�Y�O��"�x@�l[9]�ٛ�k_ ��4�@&R�� P��&�G���Ľ8�WVR Y0B����.8�$,N�J�S�&���ZNL�hcjܠ�*�r�5nl� �l�Ř���(������{i�z��*��xȌ�y�ά� +օ�V$�0k�d�<Zm'��,*<�ύn���[pA�d��GM�ƺ���"2��P|n ���ֹ���M���G�Ǥ�����+ +&�,�S��3d�q�#ɦpuxV�W����GW�rE�8Cj��l����>��t�N�z�����2��<=ԩ6��s�Ǎ��vaa�H~� +8�)�_��?�9�g���oj�0y4�k�p���@@e*,"T��C۱��� ��@�ɘ��罈"ܞAs1q���ֹ�<���#S^%H��M �cׇZo')���[{�m���o�ٻ"�F�B4+���jk�͈%���5v^E�4N�L,MKKK�Ƈ�Z�1V� D*}�����7��op��n�e<i��i�������_���K�V ]��Zֹ�*��Q�ZD2�c\ǃ� m�����:,��&E���9�2����-?���kLz�Wu�$��SZ����V*��1B�e�籏Ʀ�4 +��,U�\p���M�8�T>���g�����,�^փ�,( �æ;�aƪ�����/<hC��:eUEx��4�Q�L�sx'�W)uT%�@�l�V��Y�R(��}>�W����������_F� � f@�3�V �,&�~7�6� +eL�R�:֦�I��e��_�.K�<�pళ�a��n݃ ���_�pJfW�=ͅ��x֚��@Jj�#���5&R���]k���eF�4�EZ��q�r80�2��jlr�P�1*�������R7��)�t��b�xU-��j�0���sd]o^�z��zM]Kw�ի5t� �^��1�2] �N��5�V,.�F�3H4̈@W����O����ul��8�HX�c�m�/ǹ_���}:��С�� t�L�M�~���.�+�D��샍q��nx�s�9"j��UQ`��&������A�gVR�.�)S��VN'��uu!}}:��ԯN��XfeW�4@>�5�T(������AVR�A�ќW1���h�-8��p�VV#/�g��ĜDf��ֵ��$B��$�d����B�Ϩ�M��"�|Q+�SB1�X�Z/DDִ�Y�������L �v$25DpAa��d�{��+�3z@l�5�,X � �0' x�T��Au�����h ���z������j�Zv�S��a����?�J=L�~�֡;� ��,Aq�ɘX��ۋf&EU�]�Z%�.�5����K-�/'�Y�kYS��ƍљ�F#���Bz��R9 &������,X � �ik��l��U����S!R��+c���� +hcC���.X�H��z^��=L���2��m������ +�X � �o�����N�۹nw���{�����V� �����[cحeoY�J��AB������ r�Ͽ�J���Gٍ���� �B��uQS%�sN��B� +(P�� �����"�x�Bx2�HU�����}=}:Z.kX�g^�� +/P�B�ր��u��7������Ef��������k]uנN��/P�B���/P�u�kS{����{���������0�e�D��]}~��: �'@�z� � @��Z��ɛ�������2�YC .)��76�QX��קN�:u��/N� ר]k_�ɛ��7�������+�43O/4����$ֵ��z��ׯ^�z�Z�����A�� ���!1 A"0Q2aq@B��PR`����#b���$3r�����C����?����`��vW����yR5:V5�/�Z�lK-�-�����jE������(��}���=S�����QY�8��oe�LQ]�W���;e����E���>�r�j-���*-��ؿ����f�����eje-�?؝��eD��|��F�xm��$,���/��ʼnA +9��{�3l��epW"yn(��5�����Kj��d��S66/%���q>7�y�_N�F<���1.��H>v!.��7l�9ey^ZwE!!(��{�X�J"|�L���(o�Dv�x���[�$�#�bq�F,~b{>M_���0/'&QfË��b�w����5Au&.Ã��!��[�j+l�Yj10�i����?������`��0_�F���}������d�!$o��Y�c���K�ztА� w��cJ���-�R��RD{u�G�}������ ��͓��ɯ����E���-��ݍ�r�4��V�}�,������7�j$WsД�)���"��(9P�v��ԈO����%�&.����t��W�MEDInj���O���,�kJ���VƌD��(�]��%'��n�_b��v%> /R�S/|��hB�#�ć���zq +K�}�� "XX����$C�!�?�����Gd[���N�xp��[�����*bN\��O��g��M�T<���eE��?L��$$&!��� wDKF�"��T��^͊�qeǡA[&�{��{�����듖蟳O�%����̎,T�����4�C�+e���kk���R�]�Z����UЖU��})!�Q��:v5RF�S�����ȷ|�ӴS�g��"��X��jJ���.i��YԾ���)+_a�͝��F�IK�M�YY�[�8�2��o��]d��P�E;-eh�F�TJE����LC���p��",Y&��]t������/��ȿ>���O���`4�)xQQ��k�r��R�,o�!��̳s���&�eد#T��yGМx�1������&���b�)�JċL�%���Ϥ\�L��Q�o�K�qܻ-�{չy�od:�h^U +<�� dؗOr�V�Ҭn�W��I��M#�҈Mn����ђI9;�����F��%�YXƇ?w�p=f�}4V�����,�È������N�|�+ȧ��rڽM��tR�������[�}T&8a)��R��z���i������~�L��<=k�Df���:b|u��|h��^L��yZ�Շ�������k*yKT���v�f�T$9�!ER�mQE��U�&�~��� +nE���B��p�t4������q�q�ŬD��#�^M�H����Y�\�G�h�i/����$��U��\�|�X��G)�������ի$Sb|�у._�)�K�%��T����lۢ���dV��+�w��6*5��i�_<��4��C�2�Kg�����)�U��T��N7��_!N)���66-���})r���B���2%���c�f�_���1B"��l�n�9� �~l���B���Ų�~N�ѾZ��[���=�+$�w�5�%��\_i<s�2�/;F��h���Ҹ���_&��+�Ϣ8J�<I]�]�OR~��4Nj�Ԟ�ƶf�P��<I[�scn�} +Q+�lr��F +���NO�%��!�&ۯ�aZi�}��1���%�D��Y����K��-��`��/-��ч�c +{�vd�^�5���5F��JB1#$�~F�R5�'�g�%�+}ٮ��r$(Dx�+766�L]�4�ɔ��`�ݕ��ߡ��mn%�C��Z�-�(�*�%��LX+qc�Ë[�_ՐĂ�]�A�/�M#Ҧ2�)N��k��G�`-O����1���i�[ZR���_�H�ԝ> ������d�5��nڢ�5��mБ�%K��J�M�᮪[آkt�ط���:�Ed���l��(-�s{��.Z%��j�6 �i2�^��K%VoG4xE%DS���Ƈ�7�o���)��ދ_����ω����b3]�� נ���.���K����|���O������c�*N.����z�K�L��%%�7_��v��E�7�$�'���.4�=����];��En��}2�#���,]����S}х/�&av�#+�C���Ta��TG�4j�Wr)r�{�۽ǩ�Mq���)�w���ؕ��Wo����'��-<��˔�(ү���#����M���-NP|E����a>�J�Vb�|6��:���B/���x�q��%�*}Y�/] ++T��#�?��Q��{e�U�S4J���d�V�0���Q9r�,ՃO�ؕ b�o�[}zi� ȓi�\6b.�v�$��_!���"�[,�%�I�U~O����?������$UJ;o�Kb�ܼ�6�цׇ�/b��{�?2k�GT���u�Y$��x�(!�Zl�m�ý���VZ�e<���"K�R��!���+�ا��R\�qJ*K���E$j����Un����[���O�_� �ᒂެ�]�V�O�I�o�F"��% ��L�Jt�%�|͗�4�!�h��cl��Ď�= A�(l�=ѫe�J(PF��/l�|���w��w{ ���&YC�e9p�ݑBGx�)m.sR��m���I:��i%�D����F��9oT8��+?S}������8r�G��scU�g-�7�!bƤ�)xLS �[�s�������E�$��%iCŝ�"�������d�#�םf��Ȼ��l��mOU�K�yj�o�-���v�\|�X�+yR54�Z7l6�,h�� ��.WD&�H�Tv�v�����;!��Ӣ:���{R�!����?��F��w�"�j�cc[���༶��*�$Q7��/�r}��dP�>�JN��>Y���ƙ� ����,�Y^2��o�>�(�!>�0�;� +O�]9%��SM��C���E�}3�ٮVnR)m�S���ى�ۦ�W�iP��G�����#u.H����x�/�eiD�^FƘ,�7��K���� �YE��97�S��-��������i��xQ%�嚓Y��]o���>��ѷO��7�|�β�/�Lo�!!� �M�'ȭ7�-R.Oȶ�E�Q���i+���Q%w��aI��n�͜ -�8_w��٥��V�ɗ���eyV�j,��F���Q�6����v졾 2B��O)J+c����Fy�B<$Z/-1l��it\���d��1�^�����|��v8��+��/���d��� o}�$���p�o���%��m��a(���2�r�3D�β���?ݡ�����E�o+ʲ���E�t\Y�h|1!�l� d���$cK�}H/�ه"�鼸EB�|�~��ѱx������O��ldžӭU��J��~?�x����r��G���^J<�'IY9w�,�/˔���$C;ri�>�D�c-�K$�]I��Ce��}n�$P�L��c������#6 ��E�0���[�䈵k��J�^��D��*)�y[�����;=�+�$Z(�]�n���� �i|�v����T6�#�*l�i�a�l�Y�.��i/|�����i�S��5Ћ�şj���K�=��+�Ȯ +wF/+u�Lj�1��C��O[&�"�F����v��*5I,�)yV������.�J�$�+�f.#�I��=��Ń�#�����xlŏ{11�%HI[ʋe/.�(�WRRO'��;\�F? +�����rm�_C��W�1"����;Km�{z�*C��Q\��8*�����ȣ�Ut�|��x6�d�'re�k!%o=����R��BBm ;��y�c�v��E��%]���HvR����(�Z�����`bm5f/�9i��,8��-O=n�ͧH��].�f����K�CđQY�V[�wF�4j�����9;y;Ҿ���{eE�3q;�6s�uL�v�M.�H�I}z�㦣���eHiŕD��X���=���lm���f͆�N��,k�If�!B")�"�Ye"ٿ[ka�njD\���-YSa�������qh�F9�\�`B�������tm�mյ�E +N�(�y&$&���H�� a�d����.Ƒ�/��� ;D�J��ɞ/.؞v_Z���'�[7�j-g��b�L���r�k��o�xY~F�t���y�o*����.�͍�I��r�w�-S����MI�n��G��U�!.�BH��~f��E䈾»N�H��H�ۏ�JE������БE��Q�ΟEd�.�t�bI3a�e��<�42�(R�-(}���RyIpɮ�\�gLߢ���%L�7���O뚍YK�ܵ�巛�++�!�'��%�Zr�t��RɷHQ^��^�cz<T{��Z���|<�I���SD��~��c#2P�tE�ǭo�~F�G�t^K�B=�S5o�$⤻��-4�-�Y�:����. +���p帛��R7L�IG:��T��(J��Y�~U?=]����];u�R-���`�����1REI��e�h��ɔ� +����i� +..�#���Lk�6F�C���+0��5�LŇc$�j��+���w��#�Ĺ��.L�g��h�K�L����A���Ӎ]��k ��O�Y-4�egO.�LO���.Uoᑈ�VN<����ͺ�M�\Q_n�~��oW�S��E~�Y��C��ݪF�Ը{�Zg���'��L]R�!7�� �E�$j�5J�ZNϢ�+��.��S?#��bǍ�Ȝ^�k6�����H����� �s�5��Hx��=��}��x�bK�o�,x\���1#�a�ZQgW=���a�:��CL���sf͞+5;Ck�q��O�{<�(W����/��hn���(��$8�;so6��:�]��O����K�%�7'��{=�O�D�K���b�W&�z��uRZ�<X��%)�(��%9X��R_e�xb��##�]��x�q/���ȣ|������*iaa�1����{���J%�8��#���QV�� pk����i�^��,���yi7�Io�d�u�uc�?��h��ǃ/����Y��e�+:%�O̳l��B����*��W�C����?�WhX��{�/����U��#�p�q{�W���c]�8��G�_���/���#������� 0@P������ fb~5�V5l�f����ֵ�kZֿ�B �͒ʼn?�e²�_Ūu'{���;��5�kZ��5 I��c�<g������,fN��ă7�����N���Zֵ� ,^��1?/G�����ʮ6��VC��7����PE�wI��ᱱk%�ɾE���y�!^77���c��b��I'办.����w"�a�����~�����E��!$������T�gfd�í�yPc����a��� ���BI���� 2�ϸ���� �R>�����@T�bO΅�,γ)��f�c�_���!��<%6>}�7&XX����U�[�*��*G�Q���Øy�y\��ŃC-&Z����JXY��f8����".����!� �;������IZ���Z1j²��`:���du���A��k�z���\�4)��.]n�����UTֵši����8�̏c���� R�@�ZZ��WE��D-�����4CG�+U߭uWV�I��n3����pue��@p�����f^�6� �B5�YU��2�֨}t�&�R���ba���Gǟp �8�����=t��kՑ\������&�)Y��u���WE��J�}4�� �Ub�{�Y��w�ݷ:_E�oO�A���#����n��[6��-^AA+īǦ6�sT�;� �@h@�Wom��+����QN ����mk�^�-�+6��V=�� ��#�J��}a)ã+#�մ�����STbb���M( �:���دW��xݭ�ڠ=@ � �T*�Y<��g���d\���`��Y��`�㒲#�f-�Aƴ �h�5�5�HAX6g�oֲ`�s�]lK���U��L|�"�E/X=�UZ�"�@����O-f& +۔r����*<k@hA5�˕XZ�ez�DJ�@ �aX���E%9� ή����zx�x<)��+삪��\5���1,�N= +�a��E>��I˨Ե��͈N�!YĬ��A����5�Vc�譓�D�X�LJ>�}2[�Y�EGpBZ4#J�8�"k\(i�' 9���tL��n!2�b��b �a��_�)(��/�*�������W��*j�vakV>Ƀ���e��Qm�^=t����1M�'�#�e�� "�Q�E���q�V��sy,��r �08��*u��K��[ƽR����PL� +ԕ���Ñ6�Z嗩�_�E��J�6��vk<ߒ�ɬ�g����I�3��� +�!k2w�����}��P��A��3r�b�]k�Jc_����URc����#/+���b����q��c�/�r|���ؗ�f�Llt\�7�b-X��-����C�F"�J�:jk\_J5V�b�kd�p�T?��-���zk�Ŗ��?#���ω�"�1U��6:�>D�5�T�ړ�bK$$ Mk�C �b{v��k��ͪ�Q��f�1*��B�����*�4 +��NG��u��q��<��a�5�RNk�XA1lن)�l�uR��/���������%���� �blY�"ƴ�[11������]O�G��D0qo���x�UPM��g�8SV@$Do�$�F���\8 +�8�Y߀U�Ζ��_�"G��h�pa��Yg�/*�z�!6�`bW]�%f�L�n+(x���@�1��5�IA��46;U��x��]i�^��r���eNu�b�=�0�y��x���l�юY0�Q[�B�w���WG�Gon���M��Mp����ִ���Y�Y���������=�=�d�P���c.����a?�9F `�QWC�$rOP�y0� +��B�S`� +��,uf[E���"ų�r��CZIgo"�Pg���pM�-C�tc���ٔGf=$��h�N��`W�z�*U_]��Qqi�R~��F���: +�d.Hx�f� w��l0��f����4a�ӕb�5od�DG��i�x��a����#�J�B�<h�c�Q� +E-VBe-��2����Zk�>G��C�6<E��D�C�Ø�W�������X\�l/�Tk����+Q�XPE�!]WB��Z.�קR\/��{��*�U�5ӆ8�32�Zqj��L�y�M�;�th]�6�Эk��sg`��T�~���bƇ�56CV �o ��l�jڋ���WJ��������T�T80�a&�a� ��<�l�_}Eau���\�ņ�>�<P��`� ��[�P�g����a�5�}�/,M�f%x�`���\��<a� R7� P&͆�ĩ#�M �� a@�#��!�< l`��.���o�����K��]��$�D��pA��6<P�ل�X_�oBk�A��dr~nk8 6���:&2�ºִ����*�Vz�a{&��Z� +��<�1ܷ)B@UN���ɆƼ�֠ +���܈�w2�KE�u��#+�i�9M�sϐo#��b��?0}r���cJ�=pr +�����1'��w-����8枅 j��s�<�%�9Ya��`H �R7�o s�8�a�9'$_��?�v3W�7�̀QR-ּt +X �(�a� ��.o@)t^�J?�H�قoPM�X�c�A41�>Ðo7~��m� ����(q�<O��۩Qk\z�����&7���ܒ+�.����`�z�Ň�ɍ[�@�����YI���w��۔�1ҵ�l��3ﺧu*Q!Z������<�1�B�We�y��Ҿw�R9�?��i��`���"�M�������'��b�&��V�5:�e_}p%s{������.n������|��R�(��r �m��;cW��Z�n����߿f;��F+;�p�CMAE��W��8["����<͖& ������L��o�AD����u����N�:u���IQ��V�f�!�o��A��F�ؘ�y�7�D���c(����3�[��̠�����kZ֏,T(?�b�l����3n7� Co#��_'w�������Ů����R��<�[�9|�d�f�߶�<b��>�o{�X�;nUWj��K��~$��;�-߿�/�ś�1,�� �����ױ����|�a �ol���:u�ҩЪ��\Cn)u*��P���͟��۷n݃�@��6�mkZ���VX�������d�&��>��+Z� ���+j�0fTsghgn����v ��-pp~C���'�PC�1�����{��������}յs&$��C�������aÆ���\X��p%��`�����7������a�fo�T<�#�̪ٔ��k�ka� +�e 4 pu����p��Lxe&����'�a��e�T�˞X���UKxe�PW5�;�_̩n��+��_]�"S�_�w�v~����r��E�����ی:�Q�5�)�u[R�c2�aȃ�Jx�|�y� �I;�a�����B�P�1Wc +�����\���ȃ�"T����M68�`{O���Uv��a�%�®���,F^W�"TR \��CBs��� ��V�{��kZӣ+J�����7�&(=G�a� ��e��a�D� C�������s|}7鯰�{� ��"W+�M��{'���{������]Q��#�ȕD�o{���o{����ݻv-۷n���7�~:���|̶�"T{oe���s{���w�v�n�������k�w��"��p%1&���$���{�;��������O���:������! 01A"Q@`aPb#2Rq�r����Bc�������?��f>�m�����W��/��c�X��E.E!,}3�$F0�hKL���co�g4��|4�HM�1�}}%r2�B�)w9���+e�_Hܑ�)��͗��/l�#���Cm�����h�R.[��l�/�-��E���U����E!?��j��5��ߝ�!��H�lk���ײ�6�P�=�s=��(t>$�3�i�};+e���o��z��{o%����+K��[�"M��I ��[+e!ɍ��91����2)��V�fF(KT��,Lh�����z*,Μ�[��7����2Y[�J���TR���9��?b~����^ {����zV�(���9���͒d�I%��X��K���U��o�Ǭ_�����~~�Y��&7�>c�/�Sձ��!,��+�e-���'s,��O���k�9Q�\I��&�[��8я�Nh�T��K��܌V�IO�#I =�!Ѣ2��q�n�b��F�q��O�Qʘ�춤��s>��\�����V�Ǹ����I���Jѱ.�h�5z[+�jֹ҅(�Oc��5� *]��qc�_Y��T6����dxJ�"ٍ��o2{i��EKVĺM����ҙ̋Tq,����о��C*'�do;h�\Ȯ���I +)���]9xQ_n��"Et�Z,��yѷ���dZ��Ѥ;$��pb�G��2��L�m�?�_G���+}����r(K}�E���oK.Z'܃ �bH� ���������Ț/e+��#�h��!=��\(}�C%��B<���B�J��n�ZWS�6y��/*ܤ�X����KD! +�\���)[)/miX��g���R�%ۧkK.W����J�m������)Ƙ�h��%g�s>�N\�����/�&�uHvgw!����hk��֕��V{�;�r�(|�-1��^:N��W���q=kJ���cl�|MS"�?�ZK�?c���)/r��)K2k�NOK��i ������iM�}���oEؤgo1˖x�/�n̋F5��C�8HSW�'ƅ�E3�J(��nm���z���V嗧�����/�N����o���+����W�8�JMW���})���ÙZ�gĖ�v2`��.^��E�J]kQҵƉ�e��َ�%ko++��c��Sg��V�u����ZI�G�_�=��?o����x����K�+�(ǒ:r��ѝ��u(�*?̬��������"_msB�vcc}��fӕׂ��i�땋&K)t�[�+���$�G<��Ҍ靍v3L�(��qI!��'=%4�IF*�ȅ������9�H���V�$1�-�&��d���ύ<� !��0d��=i�[�#?c�+b�6�+H?_f?�� m��JИ�Ȯ�B�!"�9�2R1�������!����T�ɓuζ�����L�$�`��4Hz1�h��=�O��%<��q��v��xd��u���e��H����,{�����ofL�fuΖ>�ޔ�Pދe��#��-�B�آM��9c�9d3�O�$_}�z�\%U��8O��}���}�� �e���3�<�.����O�[M��O��&4i�#.���L���Om+߂�zެ��.*����Ɗ�ؖ^��I�1�:/:�����B��-^�Hzᾥ�:[ѡK��^�"�j�B�=)�SdR"�Gh�Y p�kE�ޜ���vɒ)gD$�1 j�މizy-�,z�����.��D_g���}�>W���e��/���mM�%o��-�l�]I�� �sh�H��61T��z^���u-�==�Q[���11r��Ln-�_}��gZ��KzWCva��Ս��"�a��o��<i�t�ZވB�E6(�=hΔy3��w�S�:VFDZZ=1ѥ��oKyK�����1�c�E*9�>��H�HoD�d�����;9f��)V��H��L��o�E�i^��G�{ܛ��ض>����]�M^��w��e-+}-3��ie[ܓ�J^Gѷ������h�-QN�DR�l�-�"EDD$#�}ωFm�v<��^���nI��)4[���[��H�ę&1��$�kF{�Km�1Zv[�e2�'����~v61��͔H�ȥ�D�u�|H����r��o:[<iK}�1� nH�'<��!!i[��đ�m�����s"��=�9�1�nl��2��O�^=�g��}��R��M��^䥢]�6�re/�Oe�Ι9b߱��3�/������8?��u��Ƶ�����z$W�Y�)h��1dz$��f7����Lh������5����~���]�9��'��%���;�F�#�W�������S1��N�cHpb�7H���mq������y�����<8��RXI�?��ē��%.�7d�r�}��-hB�! �oZ�SK���|�3�G�i:H��_���Jo���=9x�=s���/�A�6�1��z[�6=��[k}�'Ɔ�/R����g_��#M�F/�q+o+����hG����ݍyX��p���(~<.#�Ar��z�����|x���!,� v����3��H�����գ�VZ�lTR���9�x}Ė71�/����q�#5�l�����en�JJ���J���E�ɂՖ��4S��U]6�1�z�/� �i��~A�[�V4ˏ��Wf�3��9��S�J�h�[sk[ܺ��/���x����`�W}����d�7��m:�sZj�wh\�zL=2cbg�D&-�7���c��Ql�?k�*5��L�$_ +��ߚ+�D���=6`}�&� x,[�Fz��W��q��T]G�N~,��zE$S�6��hw'�JHq�,{�z���ӦTP*%��L^ .�w�Euq�mC������s}�D\87��\;̌�)K��,ă��(�}�q]C��O����Qt:��J�/�ܮ�b)�������ǻ������O���U$'�q�)ƙ$�"^īD$%��C]�%e����ܟrST8Ɛ۷�D=��|��9_�4��� ~M̨qt�y� +����V���k���+�C?LYY���� \ No newline at end of file diff --git a/web/core/profiles/demo_umami/modules/demo_umami_content/default_content/pages.csv b/web/core/profiles/demo_umami/modules/demo_umami_content/default_content/pages.csv index 5050922b8cebdb0b6ed391aa21ac9a32f120cf50..a36c10bd5c7f14e524b10962fe9b0d4bbf9cea5d 100644 --- a/web/core/profiles/demo_umami/modules/demo_umami_content/default_content/pages.csv +++ b/web/core/profiles/demo_umami/modules/demo_umami_content/default_content/pages.csv @@ -1,2 +1,2 @@ title,body,author,slug -About Umami,"<p>Umami is a fictional food magazine that has been created to demonstrate how you might build a Drupal site using functionality provided 'out of the box'.</p><p>For more information visit <a href='https://www.drupal.org/project/ideas/issues/2847582'>https://www.drupal.org/project/ideas/issues/2847582</a>.</p>",Samuel Adamson,about-umami \ No newline at end of file +About Umami,"<p>Umami is a fictional food magazine that has been created to demonstrate how you might build a Drupal site using functionality provided 'out of the box'.</p><p>For more information visit <a href='https://www.drupal.org/docs/8/umami-drupal-8-demonstration-installation-profile'>https://www.drupal.org/docs/8/umami-drupal-8-demonstration-installation-profile</a>.</p>",Samuel Adamson,about-umami \ No newline at end of file diff --git a/web/core/profiles/demo_umami/modules/demo_umami_content/default_content/recipe_instructions/veggie-pasta-bake-umami.html b/web/core/profiles/demo_umami/modules/demo_umami_content/default_content/recipe_instructions/veggie-pasta-bake-umami.html index b114d857e7191ad0a50375b7ec102a9a0d35014f..5906064aea71a54e60bb74107ad83983b66b3aee 100644 --- a/web/core/profiles/demo_umami/modules/demo_umami_content/default_content/recipe_instructions/veggie-pasta-bake-umami.html +++ b/web/core/profiles/demo_umami/modules/demo_umami_content/default_content/recipe_instructions/veggie-pasta-bake-umami.html @@ -4,5 +4,5 @@ <li>Add the vegetarian sausages. Once browned, remove and chop into chunky bites.</li> <li>Pop the sausages back into the pan and add the tomatoes, sugar, pesto and sun dried tomatoes. Season to taste. Simmer until most of the water from the chopped tomatoes has gone.</li> <li>Drain the pasta and add to the pan with the sausages and tomatoes. Stir in half of the cheddar and transfer to a shallow dish. Sprinkle with the rest of the cheddar and dot the sliced mozzarella over the top.</li> - <li>Grill for 10 minutes or the cheese as melted and started to brown. Serve with basil leaves.</li> + <li>Grill for 10 minutes or until the cheese has melted and started to brown. Serve with basil leaves.</li> </ol> diff --git a/web/core/profiles/demo_umami/modules/demo_umami_content/default_content/recipes.csv b/web/core/profiles/demo_umami/modules/demo_umami_content/default_content/recipes.csv index 42d5ab4e755ab53e9c3c1712bb67eca3009c1aa2..6c9d6db2907f8f48c6200e610c9c7ca341b93f66 100644 --- a/web/core/profiles/demo_umami/modules/demo_umami_content/default_content/recipes.csv +++ b/web/core/profiles/demo_umami/modules/demo_umami_content/default_content/recipes.csv @@ -4,7 +4,7 @@ Vegan chocolate brownies,chocolate-brownie-umami.jpg,A white plate with a vegan Super easy vegetarian pasta bake,veggie-pasta-bake-umami.jpg,Cheesy pasta dish with vegetarian sausages and topped with mozzarella cheese and basil,A wholesome pasta bake is the ultimate comfort food. This delicious bake is super quick to prepare and an ideal midweek meal for all the family.,Umami,Main course,5,20,25,easy,"400g wholewheat pasta, 1 onion, 2 garlic cloves, 1 pack vegetarian sausages, 400g chopped tomatoes, 50g sliced sun dried tomatoes, 1 pinch sugar, 3 tbsp red pesto, 50g cheddar cheese, Basil or mixed herbs, 100g mozzarella",veggie-pasta-bake-umami.html,4,"Vegetarian,Pasta,Baked",recipes/super-easy-vegetarian-pasta-bake Watercress soup,watercress-soup-umami.jpg,Watercress soup with a sprig of coriander as garnish in a white bowl with green trim.,"A wonderfully simple and light soup, making the most of seasonal, local produce. ",Umami,Starter,10,20,30,easy,"3 bunches watercress,3 potatoes,3 onions,2 leeks,800ml stock,5 tbsp crème fraîche",watercress-soup-umami.html,4,"Soup,Vegetarian",recipes/watercress-soup Victoria sponge cake,victoria-sponge-umami.jpg,"A classic, uncut Victoria sponge with a deep filling of butter cream and jam","A traditional Victoria sponge cake, perfect for any afternoon with a cup of tea.",Umami,Dessert,20,20,40,easy,"225g butter or margarine,225g caster sugar,225g self-raising flour,4 eggs,1 tsp baking powder,3 tbsp of jam for the filling,Icing sugar to dust the top,Cream to serve",victoria-sponge-umami.html,10,Cake,recipes/victoria-sponge-cake -Gluten free pizza,pizza-umami.jpg,"Olives, basil, and mozzarella top a gluten free pizza crust with marinara sauce.","A gorgeous and simple gluten free pizza, with deliciously indulgent mozzeralla and Parma ham. Can easily be vegetarian by leaving out the ham.",Umami,Main course,15,15,30,,"400g gluten free flour, 125ml warm water, 125ml milk, 1 sachet dried yeast, 2 tsp sugar, 1 tsp salt, 2 tbsp olive oil, 4 tbsp tomato puree, 1 garlic clove, Fresh basil, 200g mozzarella, 100g rocket, 5 slices Parma ham",pizza-umami.html,4,,recipes/gluten-free-pizza +Gluten free pizza,pizza-umami.jpg,"Olives, basil, and mozzarella top a gluten free pizza crust with marinara sauce.","A gorgeous and simple gluten free pizza, with deliciously indulgent mozzarella and Parma ham. Can easily be vegetarian by leaving out the ham.",Umami,Main course,15,15,30,,"400g gluten free flour, 125ml warm water, 125ml milk, 1 sachet dried yeast, 2 tsp sugar, 1 tsp salt, 2 tbsp olive oil, 4 tbsp tomato puree, 1 garlic clove, Fresh basil, 200g mozzarella, 100g rocket, 5 slices Parma ham",pizza-umami.html,4,,recipes/gluten-free-pizza Thai green curry,thai-green-curry-umami.jpg,"A traditional bowl of creamy, aromatic Thai green curry with chunks of chicken in a small bowl with jasmine rice.",A quick and easy version of the classic Thai green curry. Perfect for a midweek meal!,Umami,Main course,10,15,25,,"400g coconut milk, 400g chicken or tofu, 1 tbsp Thai green curry paste, 1 garlic clove, 2 tsp fish sauce, 400g mushrooms, 200g green beans, Fresh coriander leaves, Jasmine rice",thai-green-curry-umami.html,4,,recipes/thai-green-curry Crema catalana,crema-catalana-umami.jpg,"Typical Catalan dessert made from cream and egg yolks, covered with a traditional layer of caramelized sugar to provide a crispy contrast.",Enjoy this sweet recipe for one of the oldest desserts in Europe. It requires very few ingredients!,Umami,Dessert,10,20,30,,"1l milk, 200g sugar, 6 egg yolks, 30g cornstarch, 1 cinnamon stick, 1 piece lemon peel",crema-catalana-umami.html,8,"Egg, Vegetarian",recipes/crema-catalana Fiery chili sauce,chili-sauce-umami.jpg,"An iridescent array of chilies, onions, and garlic, slowly sweating over a low heat","A rich and fiery chili sauce. Take care when handling chili peppers. And serve sparingly!",Umami,Accompaniment,10,50,60,easy,"2 red onions, 1 lemon, 2 limes, 250ml malt vinegar, 7 garlic cloves, 1 green bell pepper, 1 red bell pepper, 800g cherry tomatoes, 30 mixed chilies, Olive oil, 1 tbsp ground black pepper, 1 tbsp brown sugar",chili-sauce-umami.html,60,Vegetarian,recipes/fiery-chili-sauce diff --git a/web/core/profiles/demo_umami/modules/demo_umami_content/src/InstallHelper.php b/web/core/profiles/demo_umami/modules/demo_umami_content/src/InstallHelper.php index 1268189082556c1b102b49e87aeb9620f85c1f71..01e998e9b3d3da7bc4485790f0e87750987e4130 100644 --- a/web/core/profiles/demo_umami/modules/demo_umami_content/src/InstallHelper.php +++ b/web/core/profiles/demo_umami/modules/demo_umami_content/src/InstallHelper.php @@ -202,7 +202,6 @@ protected function importRecipes() { // Set article author. if (!empty($data['author'])) { $values['uid'] = $this->getUser($data['author']); - $values['field_author'] = $values['uid']; } // Set node alias if exists. if (!empty($data['slug'])) { diff --git a/web/core/profiles/demo_umami/tests/src/Functional/DemoUmamiProfileTest.php b/web/core/profiles/demo_umami/tests/src/Functional/DemoUmamiProfileTest.php index 940c8e2aa049861b15de8e97c232ab98bdb01735..e27c6a19a3e7ff17aeb6eae79e394bb5fa19d3a5 100644 --- a/web/core/profiles/demo_umami/tests/src/Functional/DemoUmamiProfileTest.php +++ b/web/core/profiles/demo_umami/tests/src/Functional/DemoUmamiProfileTest.php @@ -77,6 +77,9 @@ protected function assertDefaultConfig(StorageInterface $default_config_storage, 'filter.format.basic_html' => ['roles:', ' - authenticated'], 'filter.format.full_html' => ['roles:', ' - administrator'], 'filter.format.restricted_html' => ['roles:', ' - anonymous'], + // The system.site config is overwritten during tests by + // FunctionalTestSetupTrait::installParameters(). + 'system.site' => ['uuid:', 'name:', 'mail:'], ]); } else { diff --git a/web/core/profiles/demo_umami/themes/umami/README.txt b/web/core/profiles/demo_umami/themes/umami/README.txt new file mode 100644 index 0000000000000000000000000000000000000000..f425a363a6dc00317cbb479be8306641a21c446c --- /dev/null +++ b/web/core/profiles/demo_umami/themes/umami/README.txt @@ -0,0 +1,11 @@ +ABOUT UMAMI +----------- + +Umami is the theme used for the "Umami food magazine" demonstration site. +The Umami theme uses Classy as its base theme. + +ABOUT DRUPAL THEMING +-------------------- + +See https://www.drupal.org/docs/8/theming for more information on Drupal +theming. diff --git a/web/core/profiles/demo_umami/themes/umami/css/base.css b/web/core/profiles/demo_umami/themes/umami/css/base.css index 1db4aeb1e56d05b44c69e741e5f690eac59c57b2..cc0bd4434228c7a994d6b89d68c283b5467dc8a0 100644 --- a/web/core/profiles/demo_umami/themes/umami/css/base.css +++ b/web/core/profiles/demo_umami/themes/umami/css/base.css @@ -55,11 +55,7 @@ blockquote a:focus { background-color: #fdfcf9; } -button, -.button, -[type='button'], -[type='reset'], -[type='submit'] { +.button { background-color: #00836d; border: 3px solid #00836d; border-radius: 4px; diff --git a/web/core/profiles/demo_umami/themes/umami/css/components/blocks/footer-promo/footer-promo.css b/web/core/profiles/demo_umami/themes/umami/css/components/blocks/footer-promo/footer-promo.css index 8476f1a6a8362330b56bfe29dcb92674dac8a3d8..7486d488f3b7a1fbeea22bc05e08b6e181c7effa 100644 --- a/web/core/profiles/demo_umami/themes/umami/css/components/blocks/footer-promo/footer-promo.css +++ b/web/core/profiles/demo_umami/themes/umami/css/components/blocks/footer-promo/footer-promo.css @@ -36,6 +36,9 @@ background: url('../../../../images/svg/pointer--white.svg') no-repeat center center; vertical-align: middle; } +[dir=rtl] .block-type-footer-promo-block .footer-promo-content a:after { + transform: rotate(180deg); +} @media screen and (min-width: 60rem) { .block-type-footer-promo-block { diff --git a/web/core/profiles/demo_umami/themes/umami/css/components/blocks/search/search-results.css b/web/core/profiles/demo_umami/themes/umami/css/components/blocks/search/search-results.css index 06c196381216f8cd68fd0244f9f750058db048e0..b140da4adce6c6f12162923c87a74510e45f2252 100644 --- a/web/core/profiles/demo_umami/themes/umami/css/components/blocks/search/search-results.css +++ b/web/core/profiles/demo_umami/themes/umami/css/components/blocks/search/search-results.css @@ -19,6 +19,7 @@ .search-form #edit-basic { display: flex; align-items: flex-end; + flex: 1 1; } .search-form .form-type-search { margin: 0; @@ -43,6 +44,7 @@ .search-form .search-help-link { padding: 1.28rem; margin: 0 1rem 1rem 0; + flex: 1 1; } .search-form #edit-advanced { @@ -96,7 +98,11 @@ background: #fff; border: 1px solid #fcece7; padding: 1.28rem; - margin: 0 0 1rem 0; + margin: 0 0 1rem 0; /* LTR */ +} +/* Apply right margin to keep aligned with title and exposed filter. */ +[dir=rtl] .search-results li { + margin: 0 1rem 1rem 0; } .search-results .search-result__snippet { diff --git a/web/core/profiles/demo_umami/themes/umami/css/components/blocks/search/search.css b/web/core/profiles/demo_umami/themes/umami/css/components/blocks/search/search.css index fe3684298847e56c9b3bbd95714beb6dd1f2a3fe..176a09c44b59769d671fb53ed562862be5c470ff 100644 --- a/web/core/profiles/demo_umami/themes/umami/css/components/blocks/search/search.css +++ b/web/core/profiles/demo_umami/themes/umami/css/components/blocks/search/search.css @@ -4,7 +4,7 @@ */ .search-form + h2 { - margin: 0 14px 1rem; + margin: 0 1rem 1rem; } .search-block-form { @@ -67,22 +67,32 @@ width: 20em; max-width: calc(100vw - 6.25em); height: auto; - margin: 0 -2px 0 0; + margin: 0 -2px 0 0; /* LTR */ padding: 7px 8px 7px 32px; color: #464646; - border: 1px solid #dbdbdb; - border-right: none; + border: 1px solid #dbdbdb; /* LTR */ + border-right: none; /* LTR */ border-radius: 3px; background: url(../../../../images/svg/search.svg) no-repeat 0.5em center #fff; font-size: 0.875rem; line-height: normal; } +[dir=rtl] .form-search { + margin: 0 0 0 -2px; + border-left: none; + border-right: 1px solid #dbdbdb; +} .form-search:focus { - margin: 0 0 -2px -2px; + margin: 0 0 -2px -2px; /* LTR */ padding: 5px 8px 5px 32px; outline: none; } +[dir=rtl] .form-search:focus { + margin: 0 -2px -2px 0; + background-position: 0.35em; + border: 3px solid #00836d; +} .form-search::placeholder { opacity: 1; @@ -101,8 +111,16 @@ .search-block-form .form-submit, .search-form .form-submit { /* Take off the border radius on the left side as it bumps into the search field */ - border-top-left-radius: 0; - border-bottom-left-radius: 0; + border-top-left-radius: 0; /* LTR */ + border-bottom-left-radius: 0; /* LTR */ +} +[dir=rtl] .search-block-form .form-submit, +[dir=rtl] .search-form .form-submit { + /* Take off the border radius on the left side as it bumps into the search field */ + border-top-left-radius: 4px; + border-bottom-left-radius: 4px; + border-top-right-radius: 0; + border-bottom-right-radius: 0; } .search-block-form .form-submit:focus, @@ -110,6 +128,14 @@ .search-form .form-submit:focus, .search-form .form-submit:hover { margin: 0; - border-top-left-radius: 4px; - border-bottom-left-radius: 4px; + border-top-left-radius: 4px; /* LTR */ + border-bottom-left-radius: 4px; /* LTR */ +} +/* Apply border radius to all corners to override LTR and RTL (normal state) changes. */ +[dir=rtl] .search-block-form .form-submit:focus, +[dir=rtl] .search-block-form .form-submit:hover, +[dir=rtl] .search-form .form-submit:focus, +[dir=rtl] .search-form .form-submit:hover { + margin: 0; + border-radius: 4px; } diff --git a/web/core/profiles/demo_umami/themes/umami/css/components/content-types/recipe/recipe.css b/web/core/profiles/demo_umami/themes/umami/css/components/content-types/recipe/recipe.css index 453d8b24feb7da82072cd3a58b17f5a99948fa72..ac1aff73159960f892b2c5422218858dee2bbcc1 100644 --- a/web/core/profiles/demo_umami/themes/umami/css/components/content-types/recipe/recipe.css +++ b/web/core/profiles/demo_umami/themes/umami/css/components/content-types/recipe/recipe.css @@ -36,11 +36,19 @@ align-items: center; min-height: 40px; margin-bottom: 0.96em; - padding-left: 48px; + padding-left: 48px; /* LTR */ background-repeat: no-repeat; - background-position: left center; + background-position: left center; /* LTR */ background-size: 40px 40px; } +[dir=rtl] .node--type-recipe.node--view-mode-full .field--name-field-preparation-time, +[dir=rtl] .node--type-recipe.node--view-mode-full .field--name-field-cooking-time, +[dir=rtl] .node--type-recipe.node--view-mode-full .field--name-field-number-of-servings, +[dir=rtl] .node--type-recipe.node--view-mode-full .field--name-field-difficulty { + background-position: right center; + padding-left: 0; + padding-right: 48px; +} .node--type-recipe.node--view-mode-full .field--name-field-preparation-time { background-image: url(../../../../images/svg/knife.svg); } diff --git a/web/core/profiles/demo_umami/themes/umami/css/components/fields/recipe-instruction.css b/web/core/profiles/demo_umami/themes/umami/css/components/fields/recipe-instruction.css index af9ee7ee3069fccbb57edbbbe6340a2b47ab6824..6b3797e7179fe2af432ee676d569f13dffbd16f9 100644 --- a/web/core/profiles/demo_umami/themes/umami/css/components/fields/recipe-instruction.css +++ b/web/core/profiles/demo_umami/themes/umami/css/components/fields/recipe-instruction.css @@ -28,15 +28,22 @@ .field--name-field-recipe-instruction ol > li { position: relative; min-height: 1.5em; - padding: 0 0 0.6em 2.5em; + padding: 0 0 0.6em 2.5em; /* LTR */ list-style: none; counter-increment: step-counter; } +[dir=rtl] .field--name-field-recipe-instruction ol > li { + padding: 0 2.5em 0.6em 0; +} .field--name-field-recipe-instruction ol > li::before { position: absolute; top: 0; - left: 0; + left: 0; /* LTR */ content: counter(step-counter); color: #cc2a00; font-size: 1.5rem; } +[dir=rtl] .field--name-field-recipe-instruction ol > li::before { + right: 0; + left: auto; +} diff --git a/web/core/profiles/demo_umami/themes/umami/css/components/forms/contact.css b/web/core/profiles/demo_umami/themes/umami/css/components/forms/contact.css index 5ba7810ce644c319437fd9514247df16076d3f90..b1d265f31fc7f0918f6eb1892159f87728c18ef6 100644 --- a/web/core/profiles/demo_umami/themes/umami/css/components/forms/contact.css +++ b/web/core/profiles/demo_umami/themes/umami/css/components/forms/contact.css @@ -41,6 +41,10 @@ @media screen and (min-width: 30rem) { /* 480px */ .contact-form .form-actions .button { - margin-left: 1em; + margin-left: 1em; /* LTR */ + } + [dir=rtl] .contact-form .form-actions .button + .button { + margin-right: 1em; + margin-left: 0; } } diff --git a/web/core/profiles/demo_umami/themes/umami/css/components/messages/messages.css b/web/core/profiles/demo_umami/themes/umami/css/components/messages/messages.css index d7a4f049879f89bc6e3d0af6bd32c5264d914024..b49bc8e48cf5f3a8cac9f8d0f9f3f47522065c0d 100644 --- a/web/core/profiles/demo_umami/themes/umami/css/components/messages/messages.css +++ b/web/core/profiles/demo_umami/themes/umami/css/components/messages/messages.css @@ -17,7 +17,10 @@ margin-top: 1.538em; } .messages__content { - background: no-repeat 0 center; + background: no-repeat 0 center; /* LTR */ +} +[dir=rtl] .messages__content { + background-position: right; } .messages--status { background-color: #e6eee0; @@ -49,7 +52,11 @@ margin: 0; } .messages__item { - margin-left: 24px; + margin-left: 24px; /* LTR */ +} +[dir=rtl] .messages__item { + margin-left: 0; + margin-right: 24px; } .messages__item + .messages__item { margin-top: 0.769em; diff --git a/web/core/profiles/demo_umami/themes/umami/css/components/navigation/breadcrumbs/breadcrumbs.css b/web/core/profiles/demo_umami/themes/umami/css/components/navigation/breadcrumbs/breadcrumbs.css index f04578f0ea8a8cd34889bb5278f60b1174d66fd9..6cfde97e995244aadca3af2f658b937ca724c434 100644 --- a/web/core/profiles/demo_umami/themes/umami/css/components/navigation/breadcrumbs/breadcrumbs.css +++ b/web/core/profiles/demo_umami/themes/umami/css/components/navigation/breadcrumbs/breadcrumbs.css @@ -5,6 +5,9 @@ .breadcrumb { padding: 0.79rem 1.266rem; } +.breadcrumb li { + display: inline-block; +} /* Large */ @media screen and (min-width: 60rem) { /* 960px */ .breadcrumb { diff --git a/web/core/profiles/demo_umami/themes/umami/css/components/navigation/menu-account/menu-account.css b/web/core/profiles/demo_umami/themes/umami/css/components/navigation/menu-account/menu-account.css index ac4f3918525827373bf1e4a6d81bfa58eef1e9f9..563a902cca7bd8c4138976804f9df7b9f32bb4d1 100644 --- a/web/core/profiles/demo_umami/themes/umami/css/components/navigation/menu-account/menu-account.css +++ b/web/core/profiles/demo_umami/themes/umami/css/components/navigation/menu-account/menu-account.css @@ -7,7 +7,10 @@ .menu--account { display: block; flex: 0 1 50%; - text-align: right; + text-align: right; /* LTR */ + } + [dir="rtl"] .menu--account { + text-align: left; } } @@ -19,7 +22,11 @@ line-height: 1.5; } .menu-account__item + .menu-account__item { - margin-left: 1em; + margin-left: 1em; /* LTR */ +} +[dir="rtl"] .menu-account__item + .menu-account__item { + margin-left: 0; + margin-right: 1em; } .menu-account__link, .menu-account__link:hover { diff --git a/web/core/profiles/demo_umami/themes/umami/css/components/navigation/menu-main/menu-main.css b/web/core/profiles/demo_umami/themes/umami/css/components/navigation/menu-main/menu-main.css index 44b715b182438ce61476db248b2bf073423c6299..54c54d9a2957c4745142214cd419406e48d108b4 100644 --- a/web/core/profiles/demo_umami/themes/umami/css/components/navigation/menu-main/menu-main.css +++ b/web/core/profiles/demo_umami/themes/umami/css/components/navigation/menu-main/menu-main.css @@ -86,7 +86,11 @@ margin-bottom: 0; } .menu-main__item + .menu-main__item { - margin-left: 2.5em; + margin-left: 2.5em; /* LTR */ + } + [dir="rtl"] .menu-main__item + .menu-main__item { + margin-left: 0; + margin-right: 2.5em; } } diff --git a/web/core/profiles/demo_umami/themes/umami/css/components/navigation/tabs/tabs.css b/web/core/profiles/demo_umami/themes/umami/css/components/navigation/tabs/tabs.css index 79cc1194cdb4f34f10b97a1fd5f68c4d28aa30bf..84e0b097185a7d59115ec236d538b2c5cacb6492 100644 --- a/web/core/profiles/demo_umami/themes/umami/css/components/navigation/tabs/tabs.css +++ b/web/core/profiles/demo_umami/themes/umami/css/components/navigation/tabs/tabs.css @@ -13,9 +13,12 @@ padding: 0; } .tabs .tab { - margin: 0; + margin: 0; /* LTR */ background-color: #e6eee0; } +[dir=rtl] .tabs .tab { + margin: 0; +} .tabs .tab.is-active { background-color: #fff; } diff --git a/web/core/profiles/demo_umami/themes/umami/css/components/views/promoted-items.css b/web/core/profiles/demo_umami/themes/umami/css/components/views/promoted-items.css index b81adae5926b636df21a9d6a72d2a46139e7b438..0ad4107c25fdf25a5496fb8d1f7e6174f9c18cdd 100644 --- a/web/core/profiles/demo_umami/themes/umami/css/components/views/promoted-items.css +++ b/web/core/profiles/demo_umami/themes/umami/css/components/views/promoted-items.css @@ -47,9 +47,13 @@ @media screen and (min-width: 60rem) { /* 960px */ .view-promoted-items--single > .view-content { flex: 0 0 50%; - margin-right: 14px; + margin-right: 14px; /* LTR */ display: flex; } + [dir=rtl] .view-promoted-items--single > .view-content { + margin-right: 0; + margin-left: 14px; + } } .view-promoted-items--single > .view-content .views-row { @@ -72,9 +76,13 @@ /* Large */ @media screen and (min-width: 60rem) { /* 960px */ .view-promoted-items--single > .attachment-after { - margin-left: 14px; + margin-left: 14px; /* LTR */ display: flex; } + [dir=rtl] .view-promoted-items--single > .attachment-after { + margin-left: 0; + margin-right: 14px; + } } /* Large */ diff --git a/web/core/profiles/demo_umami/themes/umami/css/layout/layout-2-col.css b/web/core/profiles/demo_umami/themes/umami/css/layout/layout-2-col.css index 801b12ace63183b47bda3aca23fe6f170605cb50..6a7db18fd7a21245e70f00b175d5d6445320173b 100644 --- a/web/core/profiles/demo_umami/themes/umami/css/layout/layout-2-col.css +++ b/web/core/profiles/demo_umami/themes/umami/css/layout/layout-2-col.css @@ -13,7 +13,7 @@ } .two-columns .main .layout-content { - flex: 0 0 75%; + flex: 1 1 75%; } .layout-sidebar { diff --git a/web/core/profiles/demo_umami/themes/umami/favicon.ico b/web/core/profiles/demo_umami/themes/umami/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..4f975573a6de8e8f27e4d79ad82cbbf221133661 --- /dev/null +++ b/web/core/profiles/demo_umami/themes/umami/favicon.ico @@ -0,0 +1 @@ +������� �h��&��� ��� �������(������ ���� ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������Ll���y��Ҧ��P�������������������:���h�����������������������`Kf��A]��B^��Zr�����f�������i��Id��A]��Vo��Yq�������������[s��A]��A]��Sl��t��.n���"q���A]��A]��D`��Sl��`w����������r��TE`��A]��A]�����d����x�������Hc��A]��A]��by������������������n���A]��A]��Kf�������������0Nh��A]��A]��A]�����n����������������Fa��A]��A]��cz�������������ax��A]��A]��B^���������������������Jd��A]��A]��i�������������cy��A]��A]��Vo��������������������������A]��A]��h~��������������Gb��A]��A]��Vn�������������������������n���Rl��d{�����������������`Vo��A]��E`��������������������������������&���&�������������������$�������Z���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������@�����Ç��Ç��Ç��Ç����������������������(��� ���@���� ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������|���¬������������������������������������������������������������������������������������������������������������������2����F`��B^��B^��Pi���������B�����������������������������������������������������������������������������������������������2l���A]��A]��A]��A]��A]��A]��w������<���������������������2���cz��B^��A]��A]��Pj������F_�2���&���������������������������P����A]��A]��A]��A]��A]��Fa��^v��Rk��{������X���������������py���D_��A]��A]��A]��A]��A]��A]��Gb��l������������������������������Ea��A]��A]��A]��A]��D`��m��΄��Ze{�ZGb������������������i��A]��A]��A]��A]��A]��A]��E`��Zr��e|��Mg�������������������������vax��A]��A]��A]��A]��A]��Id����������������Tm����������s���A]��A]��A]��A]��A]��A]��Oi��bx�~Wu�"m��"���V������������������������Pj��A]��A]��A]��A]��A]����������������������Zr��[q������Xp��A]��A]��A]��A]��A]��E`��_u�������������������������������������^v��B^��A]��A]��A]��A]��A]��������������������������t�������Gc��A]��A]��A]��A]��A]��Sl�����r�����������������������������������Rp���A]��A]��A]��A]��A]��Je��������������������������Sl��Pi��A]��A]��A]��A]��A]��A]��z���������������������������������������u��RZr��A]��A]��A]��A]��A]��cz����������������������_w�*Wp��A]��A]��A]��A]��A]��A]��A]������������������������������������������Vk�RKe��A]��A]��A]��A]��A]��{��������������������������*x���A]��A]��A]��A]��A]��A]��A]�����������������������������������������=Y�RA]��A]��A]��A]��A]��A]�����������������������������*����A]��A]��A]��A]��A]��A]��Hb������������������������������������������D\�RB^��A]��A]��A]��A]��A]�����������������������������*����A]��A]��A]��A]��A]��A]��l�������������������������������������������\u�ROi��A]��A]��A]��A]��A]�����������������������������z���A]��A]��A]��A]��A]��A]��l����������������������������������������������Rl���A]��A]��A]��A]��A]������������������������������>Z�bA]��A]��A]��A]��A]��A]��l����������������������������������������������N����D`��A]��A]��A]��A]������������������������������Zq�bKf��A]��A]��A]��A]��A]��j��������������������������������������������������fi}��A]��A]��A]��A]��w������������������������������Hx���D`��A]��A]��A]��A]��Oh�����������������������������������������������������d����o���Zr��Wp�������������������������������������N����Uo��A]��A]��A]��E`���������������������������������������������������������H���Jp��Jm��J���J�����������������������������������>u��R������������Ys�X������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������|��0������������?��?��?��?��?��?��?��?������������������������������� \ No newline at end of file diff --git a/web/core/profiles/demo_umami/themes/umami/images/svg/search.svg b/web/core/profiles/demo_umami/themes/umami/images/svg/search.svg index 68865f32d07121c5599ad29e7795e56d258ef21d..e651f7ee916df9bae70ca0d6d31fada7d8505b6f 100644 --- a/web/core/profiles/demo_umami/themes/umami/images/svg/search.svg +++ b/web/core/profiles/demo_umami/themes/umami/images/svg/search.svg @@ -3,11 +3,11 @@ <g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd"> <g id="Group"> <g id="search"> - <path d="M5.40705882,9.76579186 L1.13049774,14.0423529 L1.95800905,14.8691403 L6.23384615,10.5925792 C5.93199325,10.3445547 5.65508327,10.0676448 5.40705882,9.76579186 L5.40705882,9.76579186 Z M10.0180995,1.21013575 C7.38262671,1.21013575 5.24615385,3.34660861 5.24615385,5.98208145 C5.24615385,8.61755429 7.38262671,10.7540271 10.0180995,10.7540271 C12.6534724,10.7540271 14.7898643,8.61763532 14.7898643,5.98226244 C14.7898643,3.34688957 12.6534724,1.21049774 10.0180995,1.21049774 L10.0180995,1.21013575 Z M6.91113122,5.46932127 C6.65303181,5.46932127 6.4438009,5.26009036 6.4438009,5.00199095 C6.4438009,4.74389154 6.65303181,4.53466063 6.91113122,4.53466063 C7.16923063,4.53466063 7.37846154,4.74389154 7.37846154,5.00199095 C7.37846154,5.12593466 7.32922509,5.24480195 7.24158366,5.33244339 C7.15394222,5.42008482 7.03507493,5.46932127 6.91113122,5.46932127 Z M7.94027149,4.33628959 C7.48843702,4.33549024 7.12272582,3.96869932 7.12325849,3.51686445 C7.12379115,3.06502958 7.49036615,2.69910196 7.94220126,2.69936794 C8.39403636,2.69963392 8.76018029,3.06599287 8.760181,3.51782805 C8.76018134,3.73514866 8.67375208,3.94354729 8.51994746,4.09708029 C8.36614283,4.2506133 8.15759176,4.33667406 7.94027149,4.33628959 Z M9.59276018,3.21158371 C9.3345954,3.21018605 9.12631234,3.00001615 9.12724286,2.74184926 C9.12817338,2.48368237 9.33796605,2.27501936 9.59613419,2.27548273 C9.85430234,2.27594609 10.0633446,2.48536085 10.0633484,2.74352941 C10.0633502,2.86810541 10.0136898,2.98754248 9.92536382,3.07539289 C9.83703781,3.16324331 9.71733436,3.21225814 9.59276018,3.21158371 L9.59276018,3.21158371 Z" id="Shape"></path> - <path d="M10.0180995,0.0170135747 C7.91074463,0.0175014928 5.95997609,1.12971952 4.88615078,2.94296087 C3.81232547,4.75620223 3.7747616,7.00144515 4.78733032,8.84959276 C4.63937697,8.9190674 4.50463812,9.01375207 4.38914027,9.12941176 L0.430769231,13.0888688 C-0.12045472,13.6401793 -0.12045472,14.5339384 0.430769231,15.0852489 L0.914751131,15.5692308 C1.1795314,15.8341616 1.53874087,15.9830108 1.91330317,15.9830108 C2.28786547,15.9830108 2.64707494,15.8341616 2.9118552,15.5692308 L6.86950226,11.6112217 C6.98533647,11.495791 7.08015077,11.361042 7.14968326,11.2130317 C9.3343265,12.4100266 12.0327729,12.1233591 13.9171704,10.4940926 C15.8015678,8.86482619 16.4750474,6.23609712 15.606203,3.90145101 C14.7373587,1.56680491 12.509176,0.0179366079 10.0180995,0.0170135747 L10.0180995,0.0170135747 Z M1.95800905,14.8691403 L1.13049774,14.0423529 L5.40705882,9.76579186 C5.65508327,10.0676448 5.93199325,10.3445547 6.23384615,10.5925792 L1.95800905,14.8691403 Z M10.0180995,10.7536652 C7.38272668,10.7538651 5.2461728,8.61763532 5.24597288,5.98226245 C5.24577296,3.34688959 7.38200271,1.2103357 10.0173756,1.21013577 C12.6527484,1.20993585 14.7893023,3.3461656 14.7895023,5.98153846 C14.7897904,7.24736947 14.2870686,8.46143806 13.3919909,9.35651577 C12.4969132,10.2515935 11.2828446,10.7543153 10.0170136,10.7540271 L10.0180995,10.7536652 Z" id="Shape" fill="#D93760" fill-rule="nonzero"></path> - <circle id="Oval" fill="#D93760" fill-rule="nonzero" cx="7.94027149" cy="3.51782805" r="1"></circle> - <circle id="Oval" fill="#D93760" fill-rule="nonzero" cx="9.59457014" cy="2.74352941" r="1"></circle> - <circle id="Oval" fill="#D93760" fill-rule="nonzero" cx="6.91113122" cy="5.00199095" r="1"></circle> + <path d="M5.40705882,9.76579186 L1.13049774,14.0423529 L1.95800905,14.8691403 L6.23384615,10.5925792 C5.93199325,10.3445547 5.65508327,10.0676448 5.40705882,9.76579186 L5.40705882,9.76579186 Z M10.0180995,1.21013575 C7.38262671,1.21013575 5.24615385,3.34660861 5.24615385,5.98208145 C5.24615385,8.61755429 7.38262671,10.7540271 10.0180995,10.7540271 C12.6534724,10.7540271 14.7898643,8.61763532 14.7898643,5.98226244 C14.7898643,3.34688957 12.6534724,1.21049774 10.0180995,1.21049774 L10.0180995,1.21013575 Z M6.91113122,5.46932127 C6.65303181,5.46932127 6.4438009,5.26009036 6.4438009,5.00199095 C6.4438009,4.74389154 6.65303181,4.53466063 6.91113122,4.53466063 C7.16923063,4.53466063 7.37846154,4.74389154 7.37846154,5.00199095 C7.37846154,5.12593466 7.32922509,5.24480195 7.24158366,5.33244339 C7.15394222,5.42008482 7.03507493,5.46932127 6.91113122,5.46932127 Z M7.94027149,4.33628959 C7.48843702,4.33549024 7.12272582,3.96869932 7.12325849,3.51686445 C7.12379115,3.06502958 7.49036615,2.69910196 7.94220126,2.69936794 C8.39403636,2.69963392 8.76018029,3.06599287 8.760181,3.51782805 C8.76018134,3.73514866 8.67375208,3.94354729 8.51994746,4.09708029 C8.36614283,4.2506133 8.15759176,4.33667406 7.94027149,4.33628959 Z M9.59276018,3.21158371 C9.3345954,3.21018605 9.12631234,3.00001615 9.12724286,2.74184926 C9.12817338,2.48368237 9.33796605,2.27501936 9.59613419,2.27548273 C9.85430234,2.27594609 10.0633446,2.48536085 10.0633484,2.74352941 C10.0633502,2.86810541 10.0136898,2.98754248 9.92536382,3.07539289 C9.83703781,3.16324331 9.71733436,3.21225814 9.59276018,3.21158371 L9.59276018,3.21158371 Z"></path> + <path d="M10.0180995,0.0170135747 C7.91074463,0.0175014928 5.95997609,1.12971952 4.88615078,2.94296087 C3.81232547,4.75620223 3.7747616,7.00144515 4.78733032,8.84959276 C4.63937697,8.9190674 4.50463812,9.01375207 4.38914027,9.12941176 L0.430769231,13.0888688 C-0.12045472,13.6401793 -0.12045472,14.5339384 0.430769231,15.0852489 L0.914751131,15.5692308 C1.1795314,15.8341616 1.53874087,15.9830108 1.91330317,15.9830108 C2.28786547,15.9830108 2.64707494,15.8341616 2.9118552,15.5692308 L6.86950226,11.6112217 C6.98533647,11.495791 7.08015077,11.361042 7.14968326,11.2130317 C9.3343265,12.4100266 12.0327729,12.1233591 13.9171704,10.4940926 C15.8015678,8.86482619 16.4750474,6.23609712 15.606203,3.90145101 C14.7373587,1.56680491 12.509176,0.0179366079 10.0180995,0.0170135747 L10.0180995,0.0170135747 Z M1.95800905,14.8691403 L1.13049774,14.0423529 L5.40705882,9.76579186 C5.65508327,10.0676448 5.93199325,10.3445547 6.23384615,10.5925792 L1.95800905,14.8691403 Z M10.0180995,10.7536652 C7.38272668,10.7538651 5.2461728,8.61763532 5.24597288,5.98226245 C5.24577296,3.34688959 7.38200271,1.2103357 10.0173756,1.21013577 C12.6527484,1.20993585 14.7893023,3.3461656 14.7895023,5.98153846 C14.7897904,7.24736947 14.2870686,8.46143806 13.3919909,9.35651577 C12.4969132,10.2515935 11.2828446,10.7543153 10.0170136,10.7540271 L10.0180995,10.7536652 Z" fill="#D93760" fill-rule="nonzero"></path> + <circle fill="#D93760" fill-rule="nonzero" cx="7.94027149" cy="3.51782805" r="1"></circle> + <circle fill="#D93760" fill-rule="nonzero" cx="9.59457014" cy="2.74352941" r="1"></circle> + <circle fill="#D93760" fill-rule="nonzero" cx="6.91113122" cy="5.00199095" r="1"></circle> </g> </g> </g> diff --git a/web/core/profiles/demo_umami/themes/umami/logo.svg b/web/core/profiles/demo_umami/themes/umami/logo.svg index 80f82088945dfcdb7bc87f63f857770fc183ca92..6b7936d0e741d47541accfc782da7e669ad7c6ec 100644 --- a/web/core/profiles/demo_umami/themes/umami/logo.svg +++ b/web/core/profiles/demo_umami/themes/umami/logo.svg @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="UTF-8" standalone="no"?> <svg width="205px" height="60px" viewBox="0 0 711 206" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"> - <title>umami logo</title> + <title>Umami logo</title> <defs></defs> <g id="Styleguide" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd"> <g id="Design-Styleguide:-v1" transform="translate(-88.000000, -8204.000000)" fill="#FF6138"> @@ -14,4 +14,4 @@ </g> </g> </g> -</svg> \ No newline at end of file +</svg> diff --git a/web/core/profiles/demo_umami/themes/umami/umami.libraries.yml b/web/core/profiles/demo_umami/themes/umami/umami.libraries.yml index 9f7fc585c7c9870ce5d1a7d44eef543b52945a92..88d844e1da98f42050ddab5d0b8148475a1395da 100644 --- a/web/core/profiles/demo_umami/themes/umami/umami.libraries.yml +++ b/web/core/profiles/demo_umami/themes/umami/umami.libraries.yml @@ -1,8 +1,9 @@ global: version: VERSION css: - component: + base: css/base.css: {} + component: css/components/blocks/banner/banner.css: {} css/components/blocks/branding/branding.css: {} css/components/blocks/disclaimer/disclaimer.css: {} @@ -14,7 +15,6 @@ global: css/components/forms/contact.css: {} css/components/content/node.css: {} css/components/content/full/node-full.css: {} - css/components/content-types/article/article.css: {} css/components/content-types/recipe/recipe.css: {} css/components/fields/field.css: {} css/components/fields/ingredients.css: {} diff --git a/web/core/profiles/testing/testing.info.yml b/web/core/profiles/testing/testing.info.yml index f5627e39062a8a2f1bc46a1276386afffa907bdf..9924817a3d6ff867acb34ec8ee64f6bc704c367c 100644 --- a/web/core/profiles/testing/testing.info.yml +++ b/web/core/profiles/testing/testing.info.yml @@ -7,7 +7,7 @@ hidden: true install: # Enable page_cache and dynamic_page_cache in testing, to ensure that as many # tests as possible run with them enabled. - - page_cache + - drupal:page_cache - dynamic_page_cache # @todo: Remove this in https://www.drupal.org/node/2352949 themes: diff --git a/web/core/profiles/testing_missing_dependencies/testing_missing_dependencies.info.yml b/web/core/profiles/testing_missing_dependencies/testing_missing_dependencies.info.yml index fe475b3be2d24e6dce16ab2bbf5aeb98570bc443..5532efdb7adf541a8296017fa7143e16a5dcc86c 100644 --- a/web/core/profiles/testing_missing_dependencies/testing_missing_dependencies.info.yml +++ b/web/core/profiles/testing_missing_dependencies/testing_missing_dependencies.info.yml @@ -5,6 +5,9 @@ version: VERSION core: 8.x hidden: true install: + - block + - drupal:node + - drupal:fictional - missing_module1 - missing_module2 keep_english: true diff --git a/web/core/profiles/testing_requirements/testing_requirements.info.yml b/web/core/profiles/testing_requirements/testing_requirements.info.yml new file mode 100644 index 0000000000000000000000000000000000000000..a0e3e4f01d7562453763643174703730ab84310d --- /dev/null +++ b/web/core/profiles/testing_requirements/testing_requirements.info.yml @@ -0,0 +1,6 @@ +name: 'Testing requirements' +type: profile +description: 'Profile for testing hook_requirements().' +version: VERSION +core: 8.x +hidden: true diff --git a/web/core/profiles/testing_requirements/testing_requirements.install b/web/core/profiles/testing_requirements/testing_requirements.install new file mode 100644 index 0000000000000000000000000000000000000000..f7935c145c88b51440e491c27a6d5a3929cdaa66 --- /dev/null +++ b/web/core/profiles/testing_requirements/testing_requirements.install @@ -0,0 +1,23 @@ +<?php + +/** + * @file + * Install hooks for test profile. + */ + +/** + * Implements hook_requirements(). + */ +function testing_requirements_requirements($phase) { + $requirements = []; + + if ($phase === 'install') { + $requirements['testing_requirements'] = [ + 'title' => t('Testing requirements'), + 'severity' => REQUIREMENT_ERROR, + 'description' => t('Testing requirements failed requirements.'), + ]; + } + + return $requirements; +} diff --git a/web/core/tests/Drupal/FunctionalJavascriptTests/Ajax/CommandsTest.php b/web/core/tests/Drupal/FunctionalJavascriptTests/Ajax/CommandsTest.php new file mode 100644 index 0000000000000000000000000000000000000000..0db5e5f74e4deb5b3dd69ab133be555741c454f6 --- /dev/null +++ b/web/core/tests/Drupal/FunctionalJavascriptTests/Ajax/CommandsTest.php @@ -0,0 +1,130 @@ +<?php + +namespace Drupal\FunctionalJavascriptTests\Ajax; + +use Drupal\FunctionalJavascriptTests\WebDriverTestBase; + +/** + * Performs tests on AJAX framework commands. + * + * @group Ajax + */ +class CommandsTest extends WebDriverTestBase { + + /** + * {@inheritdoc} + */ + public static $modules = ['node', 'ajax_test', 'ajax_forms_test']; + + /** + * Tests the various Ajax Commands. + */ + public function testAjaxCommands() { + $session = $this->getSession(); + $page = $this->getSession()->getPage(); + + $form_path = 'ajax_forms_test_ajax_commands_form'; + $web_user = $this->drupalCreateUser(['access content']); + $this->drupalLogin($web_user); + $this->drupalGet($form_path); + + // Tests the 'add_css' command. + $page->pressButton("AJAX 'add_css' command"); + $this->assertWaitPageContains('my/file.css'); + + // Tests the 'after' command. + $page->pressButton("AJAX 'After': Click to put something after the div"); + $this->assertWaitPageContains('<div id="after_div">Something can be inserted after this</div>This will be placed after'); + + // Tests the 'alert' command. + $test_alert_command = <<<JS +window.alert = function() { + document.body.innerHTML += '<div class="alert-command">Alert</div>'; +}; +JS; + $session->executeScript($test_alert_command); + $page->pressButton("AJAX 'Alert': Click to alert"); + $this->assertWaitPageContains('<div class="alert-command">Alert</div>'); + + // Tests the 'append' command. + $page->pressButton("AJAX 'Append': Click to append something"); + $this->assertWaitPageContains('<div id="append_div">Append inside this divAppended text</div>'); + + // Tests the 'before' command. + $page->pressButton("AJAX 'before': Click to put something before the div"); + $this->assertWaitPageContains('Before text<div id="before_div">Insert something before this.</div>'); + + // Tests the 'changed' command. + $page->pressButton("AJAX changed: Click to mark div changed."); + $this->assertWaitPageContains('<div id="changed_div" class="ajax-changed">'); + + // Tests the 'changed' command using the second argument. + // Refresh page for testing 'changed' command to same element again. + $this->drupalGet($form_path); + $page->pressButton("AJAX changed: Click to mark div changed with asterisk."); + $this->assertWaitPageContains('<div id="changed_div" class="ajax-changed"> <div id="changed_div_mark_this">This div can be marked as changed or not. <abbr class="ajax-changed" title="Changed">*</abbr> </div></div>'); + + // Tests the 'css' command. + $page->pressButton("Set the '#box' div to be blue."); + $this->assertWaitPageContains('<div id="css_div" style="background-color: blue;">'); + + // Tests the 'data' command. + $page->pressButton("AJAX data command: Issue command."); + $this->assertTrue($page->waitFor(10, function () use ($session) { + return 'testvalue' === $session->evaluateScript('window.jQuery("#data_div").data("testkey")'); + })); + + // Tests the 'html' command. + $page->pressButton("AJAX html: Replace the HTML in a selector."); + $this->assertWaitPageContains('<div id="html_div">replacement text</div>'); + + // Tests the 'insert' command. + $page->pressButton("AJAX insert: Let client insert based on #ajax['method']."); + $this->assertWaitPageContains('<div id="insert_div">insert replacement textOriginal contents</div>'); + + // Tests the 'invoke' command. + $page->pressButton("AJAX invoke command: Invoke addClass() method."); + $this->assertWaitPageContains('<div id="invoke_div" class="error">Original contents</div>'); + + // Tests the 'prepend' command. + $page->pressButton("AJAX 'prepend': Click to prepend something"); + $this->assertWaitPageContains('<div id="prepend_div">prepended textSomething will be prepended to this div. </div>'); + + // Tests the 'remove' command. + $page->pressButton("AJAX 'remove': Click to remove text"); + $this->assertWaitPageContains('<div id="remove_div"></div>'); + + // Tests the 'restripe' command. + $page->pressButton("AJAX 'restripe' command"); + $this->assertWaitPageContains('<tr id="table-first" class="odd"><td>first row</td></tr>'); + $this->assertWaitPageContains('<tr class="even"><td>second row</td></tr>'); + + // Tests the 'settings' command. + $test_settings_command = <<<JS +Drupal.behaviors.testSettingsCommand = { + attach: function (context, settings) { + window.jQuery('body').append('<div class="test-settings-command">' + settings.ajax_forms_test.foo + '</div>'); + } +}; +JS; + $session->executeScript($test_settings_command); + // @todo: Replace after https://www.drupal.org/project/drupal/issues/2616184 + $session->executeScript('window.jQuery("#edit-settings-command-example").mousedown();'); + $this->assertWaitPageContains('<div class="test-settings-command">42</div>'); + } + + /** + * Asserts that page contains a text after waiting. + * + * @param string $text + * A needle text. + */ + protected function assertWaitPageContains($text) { + $page = $this->getSession()->getPage(); + $page->waitFor(10, function () use ($page, $text) { + return stripos($page->getContent(), $text) !== FALSE; + }); + $this->assertContains($text, $page->getContent()); + } + +} diff --git a/web/core/tests/Drupal/FunctionalJavascriptTests/Ajax/DialogTest.php b/web/core/tests/Drupal/FunctionalJavascriptTests/Ajax/DialogTest.php new file mode 100644 index 0000000000000000000000000000000000000000..26bdd185e6c1ae73579c9238db47fd8e0e59c63b --- /dev/null +++ b/web/core/tests/Drupal/FunctionalJavascriptTests/Ajax/DialogTest.php @@ -0,0 +1,167 @@ +<?php + +namespace Drupal\FunctionalJavascriptTests\Ajax; + +use Drupal\ajax_test\Controller\AjaxTestController; +use Drupal\Component\Render\FormattableMarkup; +use Drupal\FunctionalJavascriptTests\WebDriverTestBase; + +/** + * Performs tests on opening and manipulating dialogs via AJAX commands. + * + * @group Ajax + */ +class DialogTest extends WebDriverTestBase { + + /** + * {@inheritdoc} + */ + protected static $modules = ['ajax_test', 'ajax_forms_test', 'contact']; + + /** + * Test sending non-JS and AJAX requests to open and manipulate modals. + */ + public function testDialog() { + $this->drupalLogin($this->drupalCreateUser(['administer contact forms'])); + // Ensure the elements render without notices or exceptions. + $this->drupalGet('ajax-test/dialog'); + + // Set up variables for this test. + $dialog_renderable = AjaxTestController::dialogContents(); + $dialog_contents = \Drupal::service('renderer')->renderRoot($dialog_renderable); + + // Check that requesting a modal dialog without JS goes to a page. + $this->drupalGet('ajax-test/dialog-contents'); + $this->assertSession()->responseContains($dialog_contents); + + // Visit the page containing the many test dialog links. + $this->drupalGet('ajax-test/dialog'); + + // Tests a basic modal dialog by verifying the contents of the dialog are as + // expected. + $this->getSession()->getPage()->clickLink('Link 1 (modal)'); + + // Clicking the link triggers a AJAX request/response. + // Opens a Dialog panel. + $link1_dialog_div = $this->assertSession()->waitForElementVisible('css', 'div.ui-dialog'); + $this->assertNotNull($link1_dialog_div, 'Link was used to open a dialog ( modal )'); + + $link1_modal = $link1_dialog_div->find('css', '#drupal-modal'); + $this->assertNotNull($link1_modal, 'Link was used to open a dialog ( non-modal )'); + $this->assertSession()->responseContains($dialog_contents); + + $dialog_title = $link1_dialog_div->find('css', "span.ui-dialog-title:contains('AJAX Dialog & contents')"); + $this->assertNotNull($dialog_title); + $dialog_title_amp = $link1_dialog_div->find('css', "span.ui-dialog-title:contains('AJAX Dialog & contents')"); + $this->assertNull($dialog_title_amp); + + // Close open dialog, return to the dialog links page. + $close_button = $link1_dialog_div->findButton('Close'); + $this->assertNotNull($close_button); + $close_button->press(); + + // Tests a modal with a dialog-option. + // Link 2 is similar to Link 1, except it submits additional width + // information which must be echoed in the resulting DOM update. + $this->getSession()->getPage()->clickLink('Link 2 (modal)'); + $dialog = $this->assertSession()->waitForElementVisible('css', 'div.ui-dialog'); + $this->assertNotNull($dialog, 'Link was used to open a dialog ( non-modal, with options )'); + $style = $dialog->getAttribute('style'); + $this->assertContains('width: 400px;', $style, new FormattableMarkup('Modal respected the dialog-options width parameter. Style = style', ['%style' => $style])); + + // Reset: Return to the dialog links page. + $this->drupalGet('ajax-test/dialog'); + + // Test a non-modal dialog ( with target ). + $this->clickLink('Link 3 (non-modal)'); + $non_modal_dialog = $this->assertSession()->waitForElementVisible('css', 'div.ui-dialog'); + $this->assertNotNull($non_modal_dialog, 'Link opens a non-modal dialog.'); + + // Tests the dialog contains a target element specified in the AJAX request. + $non_modal_dialog->find('css', 'div#ajax-test-dialog-wrapper-1'); + $this->assertSession()->responseContains($dialog_contents); + + // Reset: Return to the dialog links page. + $this->drupalGet('ajax-test/dialog'); + + // Tests a non-modal dialog ( without target ). + $this->clickLink('Link 7 (non-modal, no target)'); + $no_target_dialog = $this->assertSession()->waitForElementVisible('css', 'div.ui-dialog'); + $this->assertNotNull($no_target_dialog, 'Link opens a non-modal dialog.'); + + $contents_no_target = $no_target_dialog->find('css', 'div.ui-dialog-content'); + $this->assertNotNull($contents_no_target, 'non-modal dialog opens ( no target ). '); + $id = $contents_no_target->getAttribute('id'); + $partial_match = strpos($id, 'drupal-dialog-ajax-testdialog-contents') === 0; + $this->assertTrue($partial_match, 'The non-modal ID has the expected prefix.'); + + $no_target_button = $no_target_dialog->findButton('Close'); + $this->assertNotNull($no_target_button, 'Link dialog has a close button'); + $no_target_button->press(); + + $this->getSession()->getPage()->findButton('Button 1 (modal)')->press(); + $button1_dialog = $this->assertSession()->waitForElementVisible('css', 'div.ui-dialog'); + $this->assertNotNull($button1_dialog, 'Button opens a modal dialog.'); + + $button1_dialog_content = $button1_dialog->find('css', 'div.ui-dialog-content'); + $this->assertNotNull($button1_dialog_content, 'Button opens a modal dialog.'); + + // Test the HTML escaping of & character. + $button1_dialog_title = $button1_dialog->find('css', "span.ui-dialog-title:contains('AJAX Dialog & contents')"); + $this->assertNotNull($button1_dialog_title); + $button1_dialog_title_amp = $button1_dialog->find('css', "span.ui-dialog-title:contains('AJAX Dialog & contents')"); + $this->assertNull($button1_dialog_title_amp); + + // Reset: Close the dialog. + $button1_dialog->findButton('Close')->press(); + + // Abbreviated test for "normal" dialogs, testing only the difference. + $this->getSession()->getPage()->findButton('Button 2 (non-modal)')->press(); + $button2_dialog = $this->assertSession()->waitForElementVisible('css', 'div.ui-dialog-content'); + $this->assertNotNull($button2_dialog, 'Non-modal content displays as expected.'); + + // Use a link to close the pagnel opened by button 2. + $this->getSession()->getPage()->clickLink('Link 4 (close non-modal if open)'); + + // Form modal. + $this->clickLink('Link 5 (form)'); + // Two links have been clicked in succession - This time wait for a change + // in the title as the previous closing dialog may temporarily be open. + $form_dialog_title = $this->assertSession()->waitForElementVisible('css', "span.ui-dialog-title:contains('Ajax Form contents')"); + $this->assertNotNull($form_dialog_title, 'Dialog form has the expected title.'); + // Locate the newly opened dialog. + $form_dialog = $this->getSession()->getPage()->find('css', 'div.ui-dialog'); + $this->assertNotNull($form_dialog, 'Form dialog is visible'); + + $form_contents = $form_dialog->find('css', "p:contains('Ajax Form contents description.')"); + $this->assertNotNull($form_contents, 'For has the expected text.'); + $do_it = $form_dialog->findButton('Do it'); + $this->assertNotNull($do_it, 'The dialog has a "Do it" button.'); + $preview = $form_dialog->findButton('Preview'); + $this->assertNotNull($preview, 'The dialog contains a "Preview" button.'); + + // Reset: close the form. + $form_dialog->findButton('Close')->press(); + + // Non AJAX version of Link 6. + $this->drupalGet('admin/structure/contact/add'); + // Check we get a chunk of the code, we can't test the whole form as form + // build id and token with be different. + $contact_form = $this->xpath("//form[@id='contact-form-add-form']"); + $this->assertTrue(!empty($contact_form), 'Non-JS entity form page present.'); + + // Reset: Return to the dialog links page. + $this->drupalGet('ajax-test/dialog'); + + $this->clickLink('Link 6 (entity form)'); + $dialog_add = $this->assertSession()->waitForElementVisible('css', 'div.ui-dialog'); + $this->assertNotNull($dialog_add, 'Form dialog is visible'); + + $form_add = $dialog_add->find('css', 'form.contact-form-add-form'); + $this->assertNotNull($form_add, 'Modal dialog JSON contains entity form.'); + + $form_title = $dialog_add->find('css', "span.ui-dialog-title:contains('Add contact form')"); + $this->assertNotNull($form_title, 'The add form title is as expected.'); + } + +} diff --git a/web/core/tests/Drupal/FunctionalJavascriptTests/Ajax/ElementValidationTest.php b/web/core/tests/Drupal/FunctionalJavascriptTests/Ajax/ElementValidationTest.php new file mode 100644 index 0000000000000000000000000000000000000000..48bda56cdf930d02fd4f3f492400267220e7a90f --- /dev/null +++ b/web/core/tests/Drupal/FunctionalJavascriptTests/Ajax/ElementValidationTest.php @@ -0,0 +1,53 @@ +<?php + +namespace Drupal\FunctionalJavascriptTests\Ajax; + +use Drupal\FunctionalJavascriptTests\WebDriverTestBase; + +/** + * Various tests of AJAX behavior. + * + * @group Ajax + */ +class ElementValidationTest extends WebDriverTestBase { + + /** + * {@inheritdoc} + */ + public static $modules = ['ajax_test', 'ajax_forms_test']; + + /** + * Tries to post an Ajax change to a form that has a validated element. + * + * Drupal AJAX commands update the DOM echoing back the validated values in + * the form of messages that appear on the page. + */ + public function testAjaxElementValidation() { + $this->drupalGet('ajax_validation_test'); + $page = $this->getSession()->getPage(); + $assert = $this->assertSession(); + + // Partially complete the form with a string. + $page->fillField('drivertext', 'some dumb text'); + // Move focus away from this field to trigger AJAX. + $page->findField('spare_required_field')->focus(); + + // When the AJAX command updates the DOM a <ul> unsorted list + // "message__list" structure will appear on the page echoing back the + // "some dumb text" message. + $placeholder_text = $assert->waitForElement('css', "ul.messages__list li.messages__item em:contains('some dumb text')"); + $this->assertNotNull($placeholder_text, 'A callback successfully echoed back a string.'); + + $this->drupalGet('ajax_validation_test'); + // Partialy complete the form with a number. + $page->fillField('drivernumber', '12345'); + $page->findField('spare_required_field')->focus(); + + // The AJAX request/resonse will complete successfully when a InsertCommand + // injects a message with a placeholder element into the DOM with the + // submitted number. + $placeholder_number = $assert->waitForElement('css', "ul.messages__list li.messages__item em:contains('12345')"); + $this->assertNotNull($placeholder_number, 'A callback successfully echoed back a number.'); + } + +} diff --git a/web/core/tests/Drupal/FunctionalJavascriptTests/Ajax/FormValuesTest.php b/web/core/tests/Drupal/FunctionalJavascriptTests/Ajax/FormValuesTest.php new file mode 100644 index 0000000000000000000000000000000000000000..d1a3e5c2b92c82b0bce64d718d43878b478ac1a0 --- /dev/null +++ b/web/core/tests/Drupal/FunctionalJavascriptTests/Ajax/FormValuesTest.php @@ -0,0 +1,84 @@ +<?php + +namespace Drupal\FunctionalJavascriptTests\Ajax; + +use Drupal\FunctionalJavascriptTests\WebDriverTestBase; + +/** + * Tests that form values are properly delivered to AJAX callbacks. + * + * @group Ajax + */ +class FormValuesTest extends WebDriverTestBase { + + /** + * {@inheritdoc} + */ + public static $modules = ['node', 'ajax_test', 'ajax_forms_test']; + + /** + * {@inheritdoc} + */ + protected function setUp() { + parent::setUp(); + + $this->drupalLogin($this->drupalCreateUser(['access content'])); + } + + /** + * Submits forms with select and checkbox elements via Ajax. + */ + public function testSimpleAjaxFormValue() { + + $this->drupalGet('ajax_forms_test_get_form'); + + $session = $this->getSession(); + $assertSession = $this->assertSession(); + + // Verify form values of a select element. + foreach (['green', 'blue', 'red'] as $item) { + // Updating the field will trigger a AJAX request/response. + $session->getPage()->selectFieldOption('select', $item); + + // The AJAX command in the response will update the DOM + $select = $assertSession->waitForElement('css', "div#ajax_selected_color:contains('$item')"); + $this->assertNotNull($select, "DataCommand has updated the page with a value of $item."); + } + + // Verify form values of a checkbox element. + $session->getPage()->checkField('checkbox'); + $div0 = $this->assertSession()->waitForElement('css', "div#ajax_checkbox_value:contains('checked')"); + $this->assertNotNull($div0, 'DataCommand updates the DOM as expected when a checkbox is selected'); + + $session->getPage()->uncheckField('checkbox'); + $div1 = $this->assertSession()->waitForElement('css', "div#ajax_checkbox_value:contains('unchecked')"); + $this->assertNotNull($div1, 'DataCommand updates the DOM as expected when a checkbox is de-selected'); + + // Verify that AJAX elements with invalid callbacks return error code 500. + // Ensure the test error log is empty before these tests. + $this->assertFalse(file_exists(DRUPAL_ROOT . '/' . $this->siteDirectory . '/error.log'), 'PHP error.log is empty.'); + // We don't need to check for the X-Drupal-Ajax-Token header with these + // invalid requests. + $this->assertAjaxHeader = FALSE; + foreach (['null', 'empty', 'nonexistent'] as $key) { + $element_name = 'select_' . $key . '_callback'; + // Updating the field will trigger a AJAX request/response. + $session->getPage()->selectFieldOption($element_name, 'green'); + + // The select element is disabled as the AJAX request is issued. + $this->assertSession()->waitForElement('css', "select[name=\"$element_name\"]:disabled"); + + // The select element is enabled as the response is receieved. + $this->assertSession()->waitForElement('css', "select[name=\"$element_name\"]:enabled"); + $this->assertTrue(file_exists(DRUPAL_ROOT . '/' . $this->siteDirectory . '/error.log'), 'PHP error.log is not empty.'); + $this->assertContains('"The specified #ajax callback is empty or not callable."', file_get_contents(DRUPAL_ROOT . '/' . $this->siteDirectory . '/error.log')); + // The exceptions are expected. Do not interpret them as a test failure. + // Not using File API; a potential error must trigger a PHP warning. + unlink(\Drupal::root() . '/' . $this->siteDirectory . '/error.log'); + } + // We need to reload the page to kill any unfinished AJAX calls before + // tearDown() is called. + $this->drupalGet('ajax_forms_test_get_form'); + } + +} diff --git a/web/core/tests/Drupal/FunctionalJavascriptTests/Ajax/MultiFormTest.php b/web/core/tests/Drupal/FunctionalJavascriptTests/Ajax/MultiFormTest.php new file mode 100644 index 0000000000000000000000000000000000000000..902fa6894ee55a57527fda6b892f9a0b142ad465 --- /dev/null +++ b/web/core/tests/Drupal/FunctionalJavascriptTests/Ajax/MultiFormTest.php @@ -0,0 +1,139 @@ +<?php + +namespace Drupal\FunctionalJavascriptTests\Ajax; + +use Drupal\Component\Render\FormattableMarkup; +use Drupal\Core\Field\FieldStorageDefinitionInterface; +use Drupal\field\Entity\FieldConfig; +use Drupal\field\Entity\FieldStorageConfig; +use Drupal\FunctionalJavascriptTests\WebDriverTestBase; + +/** + * Tests that AJAX-enabled forms work when multiple instances of the same form + * are on a page. + * + * @group Ajax + */ +class MultiFormTest extends WebDriverTestBase { + + /** + * {@inheritdoc} + */ + public static $modules = ['node', 'form_test']; + + /** + * {@inheritdoc} + */ + protected function setUp() { + parent::setUp(); + + $this->drupalCreateContentType(['type' => 'page', 'name' => 'Page']); + + // Create a multi-valued field for 'page' nodes to use for Ajax testing. + $field_name = 'field_ajax_test'; + FieldStorageConfig::create([ + 'entity_type' => 'node', + 'field_name' => $field_name, + 'type' => 'text', + 'cardinality' => FieldStorageDefinitionInterface::CARDINALITY_UNLIMITED, + ])->save(); + FieldConfig::create([ + 'field_name' => $field_name, + 'entity_type' => 'node', + 'bundle' => 'page', + ])->save(); + entity_get_form_display('node', 'page', 'default') + ->setComponent($field_name, ['type' => 'text_textfield']) + ->save(); + + // Log in a user who can create 'page' nodes. + $this->drupalLogin($this->drupalCreateUser(['create page content'])); + } + + /** + * Tests that pages with the 'node_page_form' included twice work correctly. + */ + public function testMultiForm() { + // HTML IDs for elements within the field are potentially modified with + // each Ajax submission, but these variables are stable and help target the + // desired elements. + $field_name = 'field_ajax_test'; + + $form_xpath = '//form[starts-with(@id, "node-page-form")]'; + $field_xpath = '//div[contains(@class, "field--name-field-ajax-test")]'; + $button_name = $field_name . '_add_more'; + $button_value = t('Add another item'); + $button_xpath_suffix = '//input[@name="' . $button_name . '"]'; + $field_items_xpath_suffix = '//input[@type="text"]'; + + // Ensure the initial page contains both node forms and the correct number + // of field items and "add more" button for the multi-valued field within + // each form. + $this->drupalGet('form-test/two-instances-of-same-form'); + + // Wait for javascript on the page to prepare the form attributes. + $this->assertSession()->assertWaitOnAjaxRequest(); + + $session = $this->getSession(); + $page = $session->getPage(); + $fields = $page->findAll('xpath', $form_xpath . $field_xpath); + $this->assertEqual(count($fields), 2); + foreach ($fields as $field) { + $this->assertCount(1, $field->findAll('xpath', '.' . $field_items_xpath_suffix), 'Found the correct number of field items on the initial page.'); + $this->assertFieldsByValue($field->find('xpath', '.' . $button_xpath_suffix), NULL, 'Found the "add more" button on the initial page.'); + } + + $this->assertNoDuplicateIds(); + + // Submit the "add more" button of each form twice. After each corresponding + // page update, ensure the same as above. + + for ($i = 0; $i < 2; $i++) { + $forms = $page->find('xpath', $form_xpath); + foreach ($forms as $offset => $form) { + $button = $form->findButton($button_value); + $this->assertNotNull($button, 'Add Another Item button exists'); + $button->press(); + + // Wait for page update. + $this->assertSession()->assertWaitOnAjaxRequest(); + + // After AJAX request and response page will update. + $page_updated = $session->getPage(); + $field = $page_updated->findAll('xpath', '.' . $field_xpath); + $this->assertEqual(count($field[0]->find('xpath', '.' . $field_items_xpath_suffix)), $i + 2, 'Found the correct number of field items after an AJAX submission.'); + $this->assertFieldsByValue($field[0]->find('xpath', '.' . $button_xpath_suffix), NULL, 'Found the "add more" button after an AJAX submission.'); + $this->assertNoDuplicateIds(); + } + } + } + + /** + * Asserts that each HTML ID is used for just a single element on the page. + * + * @param string $message + * (optional) A message to display with the assertion. + */ + protected function assertNoDuplicateIds($message = '') { + $args = ['@url' => $this->getUrl()]; + + if (!$elements = $this->xpath('//*[@id]')) { + $this->fail(new FormattableMarkup('The page @url contains no HTML IDs.', $args)); + return; + } + + $message = $message ?: new FormattableMarkup('The page @url does not contain duplicate HTML IDs', $args); + + $seen_ids = []; + foreach ($elements as $element) { + $id = $element->getAttribute('id'); + if (isset($seen_ids[$id])) { + $this->fail($message); + return; + } + $seen_ids[$id] = TRUE; + } + $this->assertTrue(TRUE, $message); + } + +} diff --git a/web/core/tests/Drupal/FunctionalJavascriptTests/EntityReference/EntityReferenceAutocompleteWidgetTest.php b/web/core/tests/Drupal/FunctionalJavascriptTests/EntityReference/EntityReferenceAutocompleteWidgetTest.php index 3d0b402a4816708118c188473c92eb3d66ada868..03fed5446202800f907a79e014a4a347366e1009 100644 --- a/web/core/tests/Drupal/FunctionalJavascriptTests/EntityReference/EntityReferenceAutocompleteWidgetTest.php +++ b/web/core/tests/Drupal/FunctionalJavascriptTests/EntityReference/EntityReferenceAutocompleteWidgetTest.php @@ -2,10 +2,10 @@ namespace Drupal\FunctionalJavascriptTests\EntityReference; -use Drupal\field\Tests\EntityReference\EntityReferenceTestTrait; use Drupal\FunctionalJavascriptTests\WebDriverTestBase; use Drupal\simpletest\ContentTypeCreationTrait; use Drupal\simpletest\NodeCreationTrait; +use Drupal\Tests\field\Traits\EntityReferenceTestTrait; /** * Tests the output of entity reference autocomplete widgets. diff --git a/web/core/tests/Drupal/FunctionalTests/Bootstrap/UncaughtExceptionTest.php b/web/core/tests/Drupal/FunctionalTests/Bootstrap/UncaughtExceptionTest.php index 9885200808e3e61624400b96b3187a6b59fe0148..1bc789c92740ef0a904bc1cb4e8e8c4dd37bb291 100644 --- a/web/core/tests/Drupal/FunctionalTests/Bootstrap/UncaughtExceptionTest.php +++ b/web/core/tests/Drupal/FunctionalTests/Bootstrap/UncaughtExceptionTest.php @@ -2,6 +2,7 @@ namespace Drupal\FunctionalTests\Bootstrap; +use Drupal\Component\Render\FormattableMarkup; use Drupal\Tests\BrowserTestBase; /** @@ -37,7 +38,7 @@ class UncaughtExceptionTest extends BrowserTestBase { * * @var array */ - public static $modules = ['error_service_test']; + public static $modules = ['error_service_test', 'error_test']; /** * {@inheritdoc} @@ -99,6 +100,31 @@ public function testUncaughtException() { $this->assertErrorLogged($this->expectedExceptionMessage); } + /** + * Tests displaying an uncaught fatal error. + */ + public function testUncaughtFatalError() { + $fatal_error = [ + '%type' => 'Recoverable fatal error', + '@message' => 'Argument 1 passed to Drupal\error_test\Controller\ErrorTestController::Drupal\error_test\Controller\{closure}() must be of the type array, string given, called in ' . \Drupal::root() . '/core/modules/system/tests/modules/error_test/src/Controller/ErrorTestController.php on line 62 and defined', + '%function' => 'Drupal\error_test\Controller\ErrorTestController->Drupal\error_test\Controller\{closure}()', + ]; + if (version_compare(PHP_VERSION, '7.0.0-dev') >= 0) { + // In PHP 7, instead of a recoverable fatal error we get a TypeError. + $fatal_error['%type'] = 'TypeError'; + // The error message also changes in PHP 7. + $fatal_error['@message'] = 'Argument 1 passed to Drupal\error_test\Controller\ErrorTestController::Drupal\error_test\Controller\{closure}() must be of the type array, string given, called in ' . \Drupal::root() . '/core/modules/system/tests/modules/error_test/src/Controller/ErrorTestController.php on line 62'; + } + $this->drupalGet('error-test/generate-fatals'); + $this->assertResponse(500, 'Received expected HTTP status code.'); + $message = new FormattableMarkup('%type: @message in %function (line ', $fatal_error); + $this->assertRaw((string) $message); + $this->assertRaw('<pre class="backtrace">'); + // Ensure we are escaping but not double escaping. + $this->assertRaw('''); + $this->assertNoRaw('&#039;'); + } + /** * Tests uncaught exception handling with custom exception handler. */ diff --git a/web/core/tests/Drupal/FunctionalTests/BrowserTestBaseTest.php b/web/core/tests/Drupal/FunctionalTests/BrowserTestBaseTest.php index 49a9ac3dbf86f81b78df67efc740e5c35143a671..eb70f68ceae078b116671e6eca992ca255011f57 100644 --- a/web/core/tests/Drupal/FunctionalTests/BrowserTestBaseTest.php +++ b/web/core/tests/Drupal/FunctionalTests/BrowserTestBaseTest.php @@ -114,6 +114,7 @@ public function testForm() { // Test drupalPostForm(). $edit = ['bananas' => 'red']; + // Submit the form using the button label. $result = $this->drupalPostForm('form-test/object-builder', $edit, 'Save'); $this->assertSame($this->getSession()->getPage()->getContent(), $result); $value = $config_factory->get('form_test.object')->get('bananas'); @@ -123,6 +124,20 @@ public function testForm() { $value = $config_factory->get('form_test.object')->get('bananas'); $this->assertSame('', $value); + // Submit the form using the button id. + $edit = ['bananas' => 'blue']; + $result = $this->drupalPostForm('form-test/object-builder', $edit, 'edit-submit'); + $this->assertSame($this->getSession()->getPage()->getContent(), $result); + $value = $config_factory->get('form_test.object')->get('bananas'); + $this->assertSame('blue', $value); + + // Submit the form using the button name. + $edit = ['bananas' => 'purple']; + $result = $this->drupalPostForm('form-test/object-builder', $edit, 'op'); + $this->assertSame($this->getSession()->getPage()->getContent(), $result); + $value = $config_factory->get('form_test.object')->get('bananas'); + $this->assertSame('purple', $value); + // Test drupalPostForm() with no-html response. $values = Json::decode($this->drupalPostForm('form_test/form-state-values-clean', [], t('Submit'))); $this->assertTrue(1000, $values['beer']); @@ -576,7 +591,7 @@ public function testFieldAssertsForCheckbox() { $this->assertFieldChecked('edit-checkbox-enabled'); $this->assertNoFieldChecked('edit-checkbox-disabled'); - // Test that the assertion fails correctly with non-existant field id. + // Test that the assertion fails correctly with non-existent field id. try { $this->assertNoFieldChecked('incorrect_checkbox_id'); $this->fail('The "incorrect_checkbox_id" field was found'); diff --git a/web/core/tests/Drupal/FunctionalTests/Datetime/TimestampAgoFormatterTest.php b/web/core/tests/Drupal/FunctionalTests/Datetime/TimestampAgoFormatterTest.php new file mode 100644 index 0000000000000000000000000000000000000000..dde8a06a6ca4c5c4dc56fc53ab1893f8c2905f96 --- /dev/null +++ b/web/core/tests/Drupal/FunctionalTests/Datetime/TimestampAgoFormatterTest.php @@ -0,0 +1,122 @@ +<?php + +namespace Drupal\FunctionalTests\Datetime; + +use Drupal\Core\Entity\Entity\EntityFormDisplay; +use Drupal\Core\Entity\Entity\EntityViewDisplay; +use Drupal\field\Entity\FieldConfig; +use Drupal\field\Entity\FieldStorageConfig; +use Drupal\Tests\BrowserTestBase; + +/** + * Tests the functionality of TimestampAgoFormatter core field formatter. + * + * @group field + */ +class TimestampAgoFormatterTest extends BrowserTestBase { + + /** + * An array of display options to pass to entity_get_display(). + * + * @var array + */ + protected $displayOptions; + + /** + * A field storage to use in this test class. + * + * @var \Drupal\field\Entity\FieldStorageConfig + */ + protected $fieldStorage; + + /** + * The field used in this test class. + * + * @var \Drupal\field\Entity\FieldConfig + */ + protected $field; + + /** + * {@inheritdoc} + */ + public static $modules = ['entity_test', 'field_ui']; + + /** + * {@inheritdoc} + */ + protected function setUp() { + parent::setUp(); + + $web_user = $this->drupalCreateUser([ + 'access administration pages', + 'view test entity', + 'administer entity_test content', + 'administer entity_test fields', + 'administer entity_test display', + 'administer entity_test form display', + 'view the administration theme', + ]); + $this->drupalLogin($web_user); + + $field_name = 'field_timestamp'; + $type = 'timestamp'; + $widget_type = 'datetime_timestamp'; + $formatter_type = 'timestamp_ago'; + + $this->fieldStorage = FieldStorageConfig::create([ + 'field_name' => $field_name, + 'entity_type' => 'entity_test', + 'type' => $type, + ]); + $this->fieldStorage->save(); + $this->field = FieldConfig::create([ + 'field_storage' => $this->fieldStorage, + 'bundle' => 'entity_test', + 'required' => TRUE, + ]); + $this->field->save(); + + EntityFormDisplay::load('entity_test.entity_test.default') + ->setComponent($field_name, ['type' => $widget_type]) + ->save(); + + $this->displayOptions = [ + 'type' => $formatter_type, + 'label' => 'hidden', + ]; + + EntityViewDisplay::create([ + 'targetEntityType' => $this->field->getTargetEntityTypeId(), + 'bundle' => $this->field->getTargetBundle(), + 'mode' => 'full', + 'status' => TRUE, + ])->setComponent($field_name, $this->displayOptions) + ->save(); + } + + /** + * Tests the formatter settings. + */ + public function testSettings() { + $this->drupalGet('entity_test/structure/entity_test/display'); + + $edit = [ + 'fields[field_timestamp][region]' => 'content', + 'fields[field_timestamp][type]' => 'timestamp_ago', + ]; + $this->drupalPostForm(NULL, $edit, t('Save')); + + $this->drupalPostForm(NULL, [], 'field_timestamp_settings_edit'); + $edit = [ + 'fields[field_timestamp][settings_edit_form][settings][future_format]' => 'ends in @interval', + 'fields[field_timestamp][settings_edit_form][settings][past_format]' => 'started @interval ago', + 'fields[field_timestamp][settings_edit_form][settings][granularity]' => 3, + ]; + $this->drupalPostForm(NULL, $edit, 'Update'); + $this->drupalPostForm(NULL, [], 'Save'); + + $this->assertSession()->pageTextContains('ends in 1 year 1 month 1 week'); + $this->assertSession()->pageTextContains('started 1 year 1 month 1 week ago'); + } + +} diff --git a/web/core/tests/Drupal/FunctionalTests/Installer/InstallerDatabaseErrorMessagesTest.php b/web/core/tests/Drupal/FunctionalTests/Installer/InstallerDatabaseErrorMessagesTest.php index b6ad437677dde07201e96643b829641f940e43c2..69c209070389721255719335813e273556fbc7da 100644 --- a/web/core/tests/Drupal/FunctionalTests/Installer/InstallerDatabaseErrorMessagesTest.php +++ b/web/core/tests/Drupal/FunctionalTests/Installer/InstallerDatabaseErrorMessagesTest.php @@ -19,7 +19,7 @@ protected function setUpSettings() { // it will try and create the drupal_install_test table as this is part of // the standard database tests performed by the installer in // Drupal\Core\Database\Install\Tasks. - Database::getConnection('default')->query('CREATE TABLE {drupal_install_test} (id int NULL)'); + Database::getConnection('default')->query('CREATE TABLE {drupal_install_test} (id int NOT NULL PRIMARY KEY)'); parent::setUpSettings(); } diff --git a/web/core/tests/Drupal/FunctionalTests/Installer/InstallerExistingSettingsMismatchProfileTest.php b/web/core/tests/Drupal/FunctionalTests/Installer/InstallerExistingSettingsMismatchProfileTest.php index 18dd66daea528d2289542e51977d6c40848b8d66..9ec2c767dc850a624ce86683f9330a61be56f5ae 100644 --- a/web/core/tests/Drupal/FunctionalTests/Installer/InstallerExistingSettingsMismatchProfileTest.php +++ b/web/core/tests/Drupal/FunctionalTests/Installer/InstallerExistingSettingsMismatchProfileTest.php @@ -69,7 +69,7 @@ protected function visitInstaller() { * {@inheritdoc} */ protected function setUpLanguage() { - // This step is skipped, because there is a lagcode as a query param. + // This step is skipped, because there is a langcode as a query param. } /** diff --git a/web/core/tests/Drupal/FunctionalTests/Installer/InstallerProfileRequirementsTest.php b/web/core/tests/Drupal/FunctionalTests/Installer/InstallerProfileRequirementsTest.php new file mode 100644 index 0000000000000000000000000000000000000000..56e7e245370bf6c208b74aa187f8e5c1f090f995 --- /dev/null +++ b/web/core/tests/Drupal/FunctionalTests/Installer/InstallerProfileRequirementsTest.php @@ -0,0 +1,38 @@ +<?php + +namespace Drupal\FunctionalTests\Installer; + +/** + * Tests that an install profile can implement hook_requirements(). + * + * @group Installer + */ +class InstallerProfileRequirementsTest extends InstallerTestBase { + + /** + * {@inheritdoc} + */ + protected $profile = 'testing_requirements'; + + /** + * {@inheritdoc} + */ + protected function setUpSettings() { + // This form will never be reached. + } + + /** + * {@inheritdoc} + */ + protected function setUpSite() { + // This form will never be reached. + } + + /** + * Assert that the profile failed hook_requirements(). + */ + public function testHookRequirementsFailure() { + $this->assertSession()->pageTextContains('Testing requirements failed requirements.'); + } + +} diff --git a/web/core/tests/Drupal/FunctionalTests/Installer/InstallerTranslationTest.php b/web/core/tests/Drupal/FunctionalTests/Installer/InstallerTranslationTest.php index ecf7d8867a15038340a0e41d9678d64e6508a098..5fa84aba08da17eef0cedfab0edbfa9a0762a3ff 100644 --- a/web/core/tests/Drupal/FunctionalTests/Installer/InstallerTranslationTest.php +++ b/web/core/tests/Drupal/FunctionalTests/Installer/InstallerTranslationTest.php @@ -48,12 +48,12 @@ protected function setUpSettings() { // it will try and create the drupal_install_test table as this is part of // the standard database tests performed by the installer in // Drupal\Core\Database\Install\Tasks. - Database::getConnection('default')->query('CREATE TABLE {drupal_install_test} (id int NULL)'); + Database::getConnection('default')->query('CREATE TABLE {drupal_install_test} (id int NOT NULL PRIMARY KEY)'); parent::setUpSettings(); // Ensure that the error message translation is working. $this->assertRaw('Beheben Sie alle Probleme unten, um die Installation fortzusetzen. Informationen zur Konfiguration der Datenbankserver finden Sie in der <a href="https://www.drupal.org/getting-started/install">Installationshandbuch</a>, oder kontaktieren Sie Ihren Hosting-Anbieter.'); - $this->assertRaw('<strong>CREATE</strong> ein Test-Tabelle auf Ihrem Datenbankserver mit dem Befehl <em class="placeholder">CREATE TABLE {drupal_install_test} (id int NULL)</em> fehlgeschlagen.'); + $this->assertRaw('<strong>CREATE</strong> ein Test-Tabelle auf Ihrem Datenbankserver mit dem Befehl <em class="placeholder">CREATE TABLE {drupal_install_test} (id int NOT NULL PRIMARY KEY)</em> fehlgeschlagen.'); // Now do it successfully. Database::getConnection('default')->query('DROP TABLE {drupal_install_test}'); diff --git a/web/core/tests/Drupal/FunctionalTests/Update/UpdatePathTestBase.php b/web/core/tests/Drupal/FunctionalTests/Update/UpdatePathTestBase.php index 19598407bd98631b5a25344d8a3fb4a9d42ef7fa..f9fd6aaeae3526f2656901a74e9f4138e5b8570e 100644 --- a/web/core/tests/Drupal/FunctionalTests/Update/UpdatePathTestBase.php +++ b/web/core/tests/Drupal/FunctionalTests/Update/UpdatePathTestBase.php @@ -2,14 +2,9 @@ namespace Drupal\FunctionalTests\Update; -use Behat\Mink\Driver\GoutteDriver; -use Behat\Mink\Mink; -use Behat\Mink\Selector\SelectorsHandler; -use Behat\Mink\Session; use Drupal\Component\Utility\Crypt; use Drupal\Core\Test\TestRunnerKernel; use Drupal\Tests\BrowserTestBase; -use Drupal\Tests\HiddenFieldSelector; use Drupal\Tests\SchemaCheckTestTrait; use Drupal\Core\Database\Database; use Drupal\Core\DependencyInjection\ContainerBuilder; @@ -197,14 +192,7 @@ protected function setUp() { require_once $this->root . '/core/includes/update.inc'; // Setup Mink. - $session = $this->initMink(); - - $cookies = $this->extractCookiesFromRequest(\Drupal::request()); - foreach ($cookies as $cookie_name => $values) { - foreach ($values as $value) { - $session->setCookie($cookie_name, $value); - } - } + $this->initMink(); // Set up the browser test output file. $this->initBrowserOutputFile(); @@ -244,37 +232,8 @@ protected function doInstall() { /** * {@inheritdoc} */ - protected function initMink() { - $driver = $this->getDefaultDriverInstance(); - - if ($driver instanceof GoutteDriver) { - // Turn off curl timeout. Having a timeout is not a problem in a normal - // test running, but it is a problem when debugging. Also, disable SSL - // peer verification so that testing under HTTPS always works. - /** @var \GuzzleHttp\Client $client */ - $client = $this->container->get('http_client_factory')->fromOptions([ - 'timeout' => NULL, - 'verify' => FALSE, - ]); - - // Inject a Guzzle middleware to generate debug output for every request - // performed in the test. - $handler_stack = $client->getConfig('handler'); - $handler_stack->push($this->getResponseLogHandler()); - - $driver->getClient()->setClient($client); - } - - $selectors_handler = new SelectorsHandler([ - 'hidden_field_selector' => new HiddenFieldSelector(), - ]); - $session = new Session($driver, $selectors_handler); - $this->mink = new Mink(); - $this->mink->registerSession('default', $session); - $this->mink->setDefaultSessionName('default'); - $this->registerSessions(); - - return $session; + protected function initFrontPage() { + // Do nothing as Drupal is not installed yet. } /** @@ -337,7 +296,10 @@ protected function runUpdates() { // Ensure there are no failed updates. if ($this->checkFailedUpdates) { - $this->assertNoRaw('<strong>' . t('Failed:') . '</strong>'); + $failure = $this->cssSelect('.failure'); + if ($failure) { + $this->fail('The update failed with the following message: "' . reset($failure)->getText() . '"'); + } // Ensure that there are no pending updates. foreach (['update', 'post_update'] as $update_type) { diff --git a/web/core/tests/Drupal/KernelTests/AssertConfigTrait.php b/web/core/tests/Drupal/KernelTests/AssertConfigTrait.php index eb1588f18e8302f96dfa1bd47acf3ee5931d3c59..7acab53b06636c7493e178e92f1274609547e29f 100644 --- a/web/core/tests/Drupal/KernelTests/AssertConfigTrait.php +++ b/web/core/tests/Drupal/KernelTests/AssertConfigTrait.php @@ -40,7 +40,7 @@ protected function assertConfigDiff(Diff $result, $config_name, array $skipped_c // Allow to skip entire config files. if ($skipped_config[$config_name] === TRUE) { - continue; + break; } // Allow to skip some specific lines of imported config files. @@ -71,12 +71,12 @@ protected function assertConfigDiff(Diff $result, $config_name, array $skipped_c case 'Drupal\Component\Diff\Engine\DiffOpAdd': // The _core property does not exist in the default config. if ($op->closing[0] === '_core:') { - continue; + break; } foreach ($op->closing as $closing) { // The UUIDs don't exist in the default config. if (strpos($closing, 'uuid: ') === 0) { - continue; + break; } throw new \Exception($config_name . ': ' . var_export($op, TRUE)); } diff --git a/web/core/tests/Drupal/KernelTests/Core/Ajax/CommandsTest.php b/web/core/tests/Drupal/KernelTests/Core/Ajax/CommandsTest.php new file mode 100644 index 0000000000000000000000000000000000000000..472d14fcf292b4ed50c45e65d9d3de7d33a87fa7 --- /dev/null +++ b/web/core/tests/Drupal/KernelTests/Core/Ajax/CommandsTest.php @@ -0,0 +1,103 @@ +<?php + +namespace Drupal\KernelTests\Core\Ajax; + +use Drupal\Core\Ajax\AjaxResponse; +use Drupal\Core\EventSubscriber\AjaxResponseSubscriber; +use Drupal\KernelTests\KernelTestBase; +use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\HttpKernel\Event\FilterResponseEvent; +use Symfony\Component\HttpKernel\HttpKernelInterface; + +/** + * Performs tests on AJAX framework commands. + * + * @group Ajax + */ +class CommandsTest extends KernelTestBase { + + /** + * {@inheritdoc} + */ + public static $modules = ['system', 'node', 'ajax_test', 'ajax_forms_test']; + + /** + * Regression test: Settings command exists regardless of JS aggregation. + */ + public function testAttachedSettings() { + $assert = function ($message) { + $response = new AjaxResponse(); + $response->setAttachments([ + 'library' => ['core/drupalSettings'], + 'drupalSettings' => ['foo' => 'bar'], + ]); + + $ajax_response_attachments_processor = \Drupal::service('ajax_response.attachments_processor'); + $subscriber = new AjaxResponseSubscriber($ajax_response_attachments_processor); + $event = new FilterResponseEvent( + \Drupal::service('http_kernel'), + new Request(), + HttpKernelInterface::MASTER_REQUEST, + $response + ); + $subscriber->onResponse($event); + $expected = [ + 'command' => 'settings', + ]; + $this->assertCommand($response->getCommands(), $expected, $message); + }; + + $config = $this->config('system.performance'); + + $config->set('js.preprocess', FALSE)->save(); + $assert('Settings command exists when JS aggregation is disabled.'); + + $config->set('js.preprocess', TRUE)->save(); + $assert('Settings command exists when JS aggregation is enabled.'); + } + + /** + * Asserts the array of Ajax commands contains the searched command. + * + * An AjaxResponse object stores an array of Ajax commands. This array + * sometimes includes commands automatically provided by the framework in + * addition to commands returned by a particular controller. During testing, + * we're usually interested that a particular command is present, and don't + * care whether other commands precede or follow the one we're interested in. + * Additionally, the command we're interested in may include additional data + * that we're not interested in. Therefore, this function simply asserts that + * one of the commands in $haystack contains all of the keys and values in + * $needle. Furthermore, if $needle contains a 'settings' key with an array + * value, we simply assert that all keys and values within that array are + * present in the command we're checking, and do not consider it a failure if + * the actual command contains additional settings that aren't part of + * $needle. + * + * @param $haystack + * An array of rendered Ajax commands returned by the server. + * @param $needle + * Array of info we're expecting in one of those commands. + * @param $message + * An assertion message. + */ + protected function assertCommand($haystack, $needle, $message) { + $found = FALSE; + foreach ($haystack as $command) { + // If the command has additional settings that we're not testing for, do + // not consider that a failure. + if (isset($command['settings']) && is_array($command['settings']) && isset($needle['settings']) && is_array($needle['settings'])) { + $command['settings'] = array_intersect_key($command['settings'], $needle['settings']); + } + // If the command has additional data that we're not testing for, do not + // consider that a failure. Also, == instead of ===, because we don't + // require the key/value pairs to be in any particular order + // (http://php.net/manual/language.operators.array.php). + if (array_intersect_key($command, $needle) == $needle) { + $found = TRUE; + break; + } + } + $this->assertTrue($found, $message); + } + +} diff --git a/web/core/tests/Drupal/KernelTests/Core/Common/SizeTest.php b/web/core/tests/Drupal/KernelTests/Core/Common/SizeTest.php index 1ff31b951bb07d3f7dd28ea89c9f90f67c5d1902..f595cfcab5ec8dbfa2bf5aed11099fe62acae4ab 100644 --- a/web/core/tests/Drupal/KernelTests/Core/Common/SizeTest.php +++ b/web/core/tests/Drupal/KernelTests/Core/Common/SizeTest.php @@ -12,62 +12,49 @@ * @group Common */ class SizeTest extends KernelTestBase { - protected $exactTestCases; - protected $roundedTestCases; - - protected function setUp() { - parent::setUp(); - $kb = Bytes::KILOBYTE; - $this->exactTestCases = [ - '1 byte' => 1, - '1 KB' => $kb, - '1 MB' => $kb * $kb, - '1 GB' => $kb * $kb * $kb, - '1 TB' => $kb * $kb * $kb * $kb, - '1 PB' => $kb * $kb * $kb * $kb * $kb, - '1 EB' => $kb * $kb * $kb * $kb * $kb * $kb, - '1 ZB' => $kb * $kb * $kb * $kb * $kb * $kb * $kb, - '1 YB' => $kb * $kb * $kb * $kb * $kb * $kb * $kb * $kb, - ]; - $this->roundedTestCases = [ - '2 bytes' => 2, - // Rounded to 1 MB (not 1000 or 1024 kilobyte!). - '1 MB' => ($kb * $kb) - 1, - // Megabytes. - round(3623651 / ($this->exactTestCases['1 MB']), 2) . ' MB' => 3623651, - // Petabytes. - round(67234178751368124 / ($this->exactTestCases['1 PB']), 2) . ' PB' => 67234178751368124, - // Yottabytes. - round(235346823821125814962843827 / ($this->exactTestCases['1 YB']), 2) . ' YB' => 235346823821125814962843827, - ]; - } /** * Checks that format_size() returns the expected string. + * + * @dataProvider providerTestCommonFormatSize */ - public function testCommonFormatSize() { - foreach ([$this->exactTestCases, $this->roundedTestCases] as $test_cases) { - foreach ($test_cases as $expected => $input) { - $this->assertEqual( - ($result = format_size($input, NULL)), - $expected, - $expected . ' == ' . $result . ' (' . $input . ' bytes)' - ); - } - } + public function testCommonFormatSize($expected, $input) { + $size = format_size($input, NULL); + $this->assertEquals($expected, $size); } /** - * Cross-tests Bytes::toInt() and format_size(). + * Provides a list of byte size to test. */ - public function testCommonParseSizeFormatSize() { - foreach ($this->exactTestCases as $size) { - $this->assertEqual( - $size, - ($parsed_size = Bytes::toInt($string = format_size($size, NULL))), - $size . ' == ' . $parsed_size . ' (' . $string . ')' - ); - } + public function providerTestCommonFormatSize() { + $kb = Bytes::KILOBYTE; + return [ + ['0 bytes', 0], + ['1 byte', 1], + ['-1 bytes', -1], + ['2 bytes', 2], + ['-2 bytes', -2], + ['1023 bytes', $kb - 1], + ['1 KB', $kb], + ['1 MB', pow($kb, 2)], + ['1 GB', pow($kb, 3)], + ['1 TB', pow($kb, 4)], + ['1 PB', pow($kb, 5)], + ['1 EB', pow($kb, 6)], + ['1 ZB', pow($kb, 7)], + ['1 YB', pow($kb, 8)], + ['1024 YB', pow($kb, 9)], + // Rounded to 1 MB - not 1000 or 1024 kilobytes + ['1 MB', ($kb * $kb) - 1], + ['-1 MB', -(($kb * $kb) - 1)], + // Decimal Megabytes + ['3.46 MB', 3623651], + ['3.77 GB', 4053371676], + // Decimal Petabytes + ['59.72 PB', 67234178751368124], + // Decimal Yottabytes + ['194.67 YB', 235346823821125814962843827], + ]; } } diff --git a/web/core/tests/Drupal/KernelTests/Core/Config/ConfigImporterTest.php b/web/core/tests/Drupal/KernelTests/Core/Config/ConfigImporterTest.php index 41795e8c87d6042d3c8ae48ddf7ac0ba82e5a950..c8eb231a97cf747de592b7b14bdc68b1ef348261 100644 --- a/web/core/tests/Drupal/KernelTests/Core/Config/ConfigImporterTest.php +++ b/web/core/tests/Drupal/KernelTests/Core/Config/ConfigImporterTest.php @@ -623,7 +623,7 @@ public function testUnmetDependency() { } } - // Make a config entity have mulitple unmet dependencies. + // Make a config entity have multiple unmet dependencies. $config_entity_data = $sync->read('config_test.dynamic.dotted.default'); $config_entity_data['dependencies'] = ['module' => ['unknown', 'dblog']]; $sync->write('config_test.dynamic.dotted.module', $config_entity_data); @@ -848,7 +848,7 @@ public function testCustomStep() { } /** - * Helper meothd to test custom config installer steps. + * Helper method to test custom config installer steps. * * @param array $context * Batch context. diff --git a/web/core/tests/Drupal/KernelTests/Core/Config/Storage/ConfigStorageTestBase.php b/web/core/tests/Drupal/KernelTests/Core/Config/Storage/ConfigStorageTestBase.php index 5bdbc74deba86bf301023923b8451ea76d594bab..238dacfb5c25e4878a6c62c0ca3aab4c15d72047 100644 --- a/web/core/tests/Drupal/KernelTests/Core/Config/Storage/ConfigStorageTestBase.php +++ b/web/core/tests/Drupal/KernelTests/Core/Config/Storage/ConfigStorageTestBase.php @@ -151,6 +151,11 @@ public function testInvalidStorage() { // Listing on a non-existing storage bin returns an empty array. $result = $this->invalidStorage->listAll(); $this->assertIdentical($result, []); + + // Getting all collections on a non-existing storage bin return an empty + // array. + $this->assertSame([], $this->invalidStorage->getAllCollectionNames()); + // Writing to a non-existing storage bin creates the bin. $this->invalidStorage->write($name, ['foo' => 'bar']); $result = $this->invalidStorage->read($name); diff --git a/web/core/tests/Drupal/KernelTests/Core/Database/PrefixInfoTest.php b/web/core/tests/Drupal/KernelTests/Core/Database/PrefixInfoTest.php index 16fd05336b690f2cf99a0dfb0be16c302a19b933..ea5e8a9edd226a6623f0dbec4373ed55f6edc53a 100644 --- a/web/core/tests/Drupal/KernelTests/Core/Database/PrefixInfoTest.php +++ b/web/core/tests/Drupal/KernelTests/Core/Database/PrefixInfoTest.php @@ -30,7 +30,7 @@ public function testGetPrefixInfo() { $db1_schema = $db1_connection->schema(); $db2_connection = Database::getConnection('default', 'extra'); - // Get the prefix info for the first databse. + // Get the prefix info for the first database. $method = new \ReflectionMethod($db1_schema, 'getPrefixInfo'); $method->setAccessible(TRUE); $db1_info = $method->invoke($db1_schema); diff --git a/web/core/tests/Drupal/KernelTests/Core/Database/SelectCloneTest.php b/web/core/tests/Drupal/KernelTests/Core/Database/SelectCloneTest.php index 30a4f1b9410852cfc23dead0b0e01a6ba805295c..3b14283b3451691b110b18bb25922b40e23f2faf 100644 --- a/web/core/tests/Drupal/KernelTests/Core/Database/SelectCloneTest.php +++ b/web/core/tests/Drupal/KernelTests/Core/Database/SelectCloneTest.php @@ -22,6 +22,10 @@ public function testSelectConditionSubQueryCloning() { $query->condition('id', $subquery, 'IN'); $clone = clone $query; + + // Cloned query should have a different unique identifier. + $this->assertNotEquals($query->uniqueIdentifier(), $clone->uniqueIdentifier()); + // Cloned query should not be altered by the following modification // happening on original query. $subquery->condition('age', 25, '>'); @@ -34,4 +38,31 @@ public function testSelectConditionSubQueryCloning() { $this->assertEqual(2, $query_result, 'The query returns the expected number of rows'); } + /** + * Tests that nested SELECT queries are cloned properly. + */ + public function testNestedQueryCloning() { + $sub_query = $this->connection->select('test', 't'); + $sub_query->addField('t', 'id', 'id'); + $sub_query->condition('age', 28, '<'); + + $query = $this->connection->select($sub_query, 't'); + + $clone = clone $query; + + // Cloned query should have a different unique identifier. + $this->assertNotEquals($query->uniqueIdentifier(), $clone->uniqueIdentifier()); + + // Cloned query should not be altered by the following modification + // happening on original query. + $sub_query->condition('age', 25, '>'); + + $clone_result = $clone->countQuery()->execute()->fetchField(); + $query_result = $query->countQuery()->execute()->fetchField(); + + // Make sure the cloned query has not been modified. + $this->assertEquals(3, $clone_result, 'The cloned query returns the expected number of rows'); + $this->assertEquals(2, $query_result, 'The query returns the expected number of rows'); + } + } diff --git a/web/core/tests/Drupal/KernelTests/Core/Entity/EntityBundleListenerTest.php b/web/core/tests/Drupal/KernelTests/Core/Entity/EntityBundleListenerTest.php new file mode 100644 index 0000000000000000000000000000000000000000..c5ace377492b6713d38687d2d34d28de0cf93797 --- /dev/null +++ b/web/core/tests/Drupal/KernelTests/Core/Entity/EntityBundleListenerTest.php @@ -0,0 +1,35 @@ +<?php + +namespace Drupal\KernelTests\Core\Entity; + +/** + * @coversDefaultClass \Drupal\Core\Entity\EntityBundleListener + * + * @group Entity + */ +class EntityBundleListenerTest extends EntityKernelTestBase { + + /** + * @covers ::onBundleCreate + * + * Note: Installing the entity_schema_test module will mask the bug this test + * was written to cover, as the field map cache is cleared manually by + * \Drupal\Core\Field\FieldDefinitionListener::onFieldDefinitionCreate(). + */ + public function testOnBundleCreate() { + $field_map = $this->container->get('entity_field.manager')->getFieldMap(); + $expected = [ + 'entity_test' => 'entity_test', + ]; + $this->assertEquals($expected, $field_map['entity_test']['id']['bundles']); + + entity_test_create_bundle('custom'); + $field_map = $this->container->get('entity_field.manager')->getFieldMap(); + $expected = [ + 'entity_test' => 'entity_test', + 'custom' => 'custom', + ]; + $this->assertSame($expected, $field_map['entity_test']['id']['bundles']); + } + +} diff --git a/web/core/tests/Drupal/KernelTests/Core/Entity/EntityDecoupledTranslationRevisionsTest.php b/web/core/tests/Drupal/KernelTests/Core/Entity/EntityDecoupledTranslationRevisionsTest.php index d4fbcfcb205a9c13e067514ae3cf17081ddfabed..8fa31c32f76e1fde1eefa84efe727aad3cf6936e 100644 --- a/web/core/tests/Drupal/KernelTests/Core/Entity/EntityDecoupledTranslationRevisionsTest.php +++ b/web/core/tests/Drupal/KernelTests/Core/Entity/EntityDecoupledTranslationRevisionsTest.php @@ -57,7 +57,7 @@ class EntityDecoupledTranslationRevisionsTest extends EntityKernelTestBase { protected $previousRevisionId = []; /** - * The previous unstranslatable field value. + * The previous untranslatable field value. * * @var string[] */ diff --git a/web/core/tests/Drupal/KernelTests/Core/Entity/EntityFieldTest.php b/web/core/tests/Drupal/KernelTests/Core/Entity/EntityFieldTest.php index 3fd17d86b47798da09b4aa795e4a3663c7b66b10..1695d9378c9f0da75a96bae97e24383210c0114f 100644 --- a/web/core/tests/Drupal/KernelTests/Core/Entity/EntityFieldTest.php +++ b/web/core/tests/Drupal/KernelTests/Core/Entity/EntityFieldTest.php @@ -3,6 +3,7 @@ namespace Drupal\KernelTests\Core\Entity; use Drupal\Core\Entity\EntityInterface; +use Drupal\Core\Entity\EntityStorageException; use Drupal\Core\Entity\RevisionLogInterface; use Drupal\Core\Entity\TypedData\EntityDataDefinition; use Drupal\Core\Entity\TypedData\EntityDataDefinitionInterface; @@ -919,4 +920,33 @@ protected function doTestComputedProperties($entity_type) { $this->assertEqual($entity->field_test_text->processed, $target, format_string('%entity_type: Text is processed with the default filter.', ['%entity_type' => $entity_type])); } + /** + * Tests explicit entity ID assignment. + */ + public function testEntityIdAssignment() { + $entity_type = 'entity_test'; + /** @var \Drupal\Core\Entity\ContentEntityStorageInterface $storage */ + $storage = $this->container->get('entity_type.manager')->getStorage($entity_type); + + // Check that an ID can be explicitly assigned on creation. + /** @var \Drupal\Core\Entity\ContentEntityInterface $entity */ + $entity = $this->createTestEntity($entity_type); + $entity_id = 3; + $entity->set('id', $entity_id); + $this->assertSame($entity_id, $entity->id()); + $storage->save($entity); + $entity = $storage->loadUnchanged($entity->id()); + $this->assertTrue($entity); + + // Check that an explicitly-assigned ID is preserved on update. + $storage->save($entity); + $entity = $storage->loadUnchanged($entity->id()); + $this->assertTrue($entity); + + // Check that an ID cannot be explicitly assigned on update. + $this->setExpectedException(EntityStorageException::class); + $entity->set('id', $entity_id + 1); + $storage->save($entity); + } + } diff --git a/web/core/tests/Drupal/KernelTests/Core/Entity/EntityQueryRelationshipTest.php b/web/core/tests/Drupal/KernelTests/Core/Entity/EntityQueryRelationshipTest.php index 4e1f9d1e5d49183b523850b94e892eb1172cb59d..0c86ba8a707b309767cc3c336874e408df7b4b90 100644 --- a/web/core/tests/Drupal/KernelTests/Core/Entity/EntityQueryRelationshipTest.php +++ b/web/core/tests/Drupal/KernelTests/Core/Entity/EntityQueryRelationshipTest.php @@ -4,9 +4,9 @@ use Drupal\Component\Plugin\Exception\PluginNotFoundException; use Drupal\entity_test\Entity\EntityTest; -use Drupal\field\Tests\EntityReference\EntityReferenceTestTrait; use Drupal\taxonomy\Entity\Vocabulary; use Drupal\taxonomy\Entity\Term; +use Drupal\Tests\field\Traits\EntityReferenceTestTrait; /** * Tests the Entity Query relationship API. diff --git a/web/core/tests/Drupal/KernelTests/Core/Entity/EntityQueryTest.php b/web/core/tests/Drupal/KernelTests/Core/Entity/EntityQueryTest.php index a47d9a9a6f9ad0481d6e793e5544c1e3256019df..a6819f01905084c3b19557897dc70ad9b706f8fa 100644 --- a/web/core/tests/Drupal/KernelTests/Core/Entity/EntityQueryTest.php +++ b/web/core/tests/Drupal/KernelTests/Core/Entity/EntityQueryTest.php @@ -6,10 +6,10 @@ use Drupal\entity_test\Entity\EntityTestMulRev; use Drupal\field\Entity\FieldConfig; use Drupal\field\Entity\FieldStorageConfig; -use Drupal\field\Tests\EntityReference\EntityReferenceTestTrait; use Drupal\language\Entity\ConfigurableLanguage; use Drupal\taxonomy\Entity\Term; use Drupal\taxonomy\Entity\Vocabulary; +use Drupal\Tests\field\Traits\EntityReferenceTestTrait; use Symfony\Component\HttpFoundation\Request; /** @@ -138,8 +138,11 @@ protected function setUp() { } foreach (array_reverse(str_split(decbin($i))) as $key => $bit) { if ($bit) { - list($field_name, $langcode, $values) = $units[$key]; - $entity->getTranslation($langcode)->{$field_name}[] = $values; + // @todo https://www.drupal.org/project/drupal/issues/3001920 Doing + // list($field_name, $langcode, $values) = $units[$key]; causes + // problems in PHP 7.3. Revert to better variable names once + // https://bugs.php.net/bug.php?id=76937 is fixed. + $entity->getTranslation($units[$key][1])->{$units[$key][0]}[] = $units[$key][2]; } } $entity->save(); @@ -630,7 +633,7 @@ public function testDelta() { ->condition("$figures.%delta", 1) ->sort('id') ->execute(); - // Entity needs to have atleast two figures. + // Entity needs to have at least two figures. $this->assertResult(3, 7, 11, 15); // Numeric delta on single value base field should return results only if @@ -1160,4 +1163,42 @@ public function testWithTwoEntityReferenceFieldsToSameEntityType() { $this->assertEquals($entity->id(), reset($result)); } + /** + * Tests entity queries with condition on the revision metadata keys. + */ + public function testConditionOnRevisionMetadataKeys() { + $this->installModule('entity_test_revlog'); + $this->installEntitySchema('entity_test_revlog'); + + /** @var \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager */ + $entity_type_manager = $this->container->get('entity_type.manager'); + /** @var \Drupal\Core\Entity\ContentEntityTypeInterface $entity_type */ + $entity_type = $entity_type_manager->getDefinition('entity_test_revlog'); + /** @var \Drupal\Core\Entity\ContentEntityStorageInterface $storage */ + $storage = $entity_type_manager->getStorage('entity_test_revlog'); + + $revision_created_timestamp = time(); + $revision_created_field_name = $entity_type->getRevisionMetadataKey('revision_created'); + $entity = $storage->create([ + 'type' => 'entity_test', + $revision_created_field_name => $revision_created_timestamp, + ]); + $entity->save(); + + // Query only the default revision. + $result = $storage->getQuery() + ->condition($revision_created_field_name, $revision_created_timestamp) + ->execute(); + $this->assertCount(1, $result); + $this->assertEquals($entity->id(), reset($result)); + + // Query all revisions. + $result = $storage->getQuery() + ->condition($revision_created_field_name, $revision_created_timestamp) + ->allRevisions() + ->execute(); + $this->assertCount(1, $result); + $this->assertEquals($entity->id(), reset($result)); + } + } diff --git a/web/core/tests/Drupal/KernelTests/Core/Entity/EntityReferenceFieldTest.php b/web/core/tests/Drupal/KernelTests/Core/Entity/EntityReferenceFieldTest.php index 469f4a32a553f876654a3edd54c7758f1a5af9b0..fa138921a1a5b19947fd37cc7cbb6ac53a4f3d06 100644 --- a/web/core/tests/Drupal/KernelTests/Core/Entity/EntityReferenceFieldTest.php +++ b/web/core/tests/Drupal/KernelTests/Core/Entity/EntityReferenceFieldTest.php @@ -7,9 +7,9 @@ use Drupal\Core\Entity\EntityStorageException; use Drupal\Core\Field\BaseFieldDefinition; use Drupal\Core\Field\FieldStorageDefinitionInterface; -use Drupal\field\Tests\EntityReference\EntityReferenceTestTrait; use Drupal\field\Entity\FieldConfig; use Drupal\field\Entity\FieldStorageConfig; +use Drupal\Tests\field\Traits\EntityReferenceTestTrait; use Drupal\user\Entity\Role; use Drupal\user\Entity\User; use Drupal\user\RoleInterface; diff --git a/web/core/tests/Drupal/KernelTests/Core/Entity/EntitySchemaTest.php b/web/core/tests/Drupal/KernelTests/Core/Entity/EntitySchemaTest.php index 9a20bd3777d93ecfeac3a6239ae76bad0d1d27e6..4dd9ede70c70be10ebf15e570281b2ffae5ed183 100644 --- a/web/core/tests/Drupal/KernelTests/Core/Entity/EntitySchemaTest.php +++ b/web/core/tests/Drupal/KernelTests/Core/Entity/EntitySchemaTest.php @@ -3,11 +3,13 @@ namespace Drupal\KernelTests\Core\Entity; use Drupal\Component\Render\FormattableMarkup; +use Drupal\Core\Entity\EntityTypeInterface; +use Drupal\Core\Field\BaseFieldDefinition; /** - * Tests adding a custom bundle field. + * Tests the default entity storage schema handler. * - * @group system + * @group Entity */ class EntitySchemaTest extends EntityKernelTestBase { @@ -109,6 +111,178 @@ public function testEntitySchemaUpdate() { $this->assertTrue($schema_handler->tableExists($dedicated_tables[0]), new FormattableMarkup('Field schema correct for the @table table.', ['@table' => $table])); } + /** + * Tests deleting and creating a field that is part of a primary key. + * + * @param string $entity_type_id + * The ID of the entity type whose schema is being tested. + * @param string $field_name + * The name of the field that is being re-installed. + * + * @dataProvider providerTestPrimaryKeyUpdate + */ + public function testPrimaryKeyUpdate($entity_type_id, $field_name) { + // EntityKernelTestBase::setUp() already installs the schema for the + // 'entity_test' entity type. + if ($entity_type_id !== 'entity_test') { + $this->installEntitySchema($entity_type_id); + } + + /* @var \Drupal\Core\Entity\EntityDefinitionUpdateManagerInterface $update_manager */ + $update_manager = $this->container->get('entity.definition_update_manager'); + $entity_type = $update_manager->getEntityType($entity_type_id); + + /* @see \Drupal\Core\Entity\ContentEntityBase::baseFieldDefinitions() */ + switch ($field_name) { + case 'id': + $field = BaseFieldDefinition::create('integer') + ->setLabel('ID') + ->setReadOnly(TRUE) + ->setSetting('unsigned', TRUE); + break; + + case 'revision_id': + $field = BaseFieldDefinition::create('integer') + ->setLabel('Revision ID') + ->setReadOnly(TRUE) + ->setSetting('unsigned', TRUE); + break; + + case 'langcode': + $field = BaseFieldDefinition::create('language') + ->setLabel('Language'); + if ($entity_type->isRevisionable()) { + $field->setRevisionable(TRUE); + } + if ($entity_type->isTranslatable()) { + $field->setTranslatable(TRUE); + } + break; + } + + $field + ->setName($field_name) + ->setTargetEntityTypeId($entity_type_id) + ->setProvider($entity_type->getProvider()); + + // Build up a map of expected primary keys depending on the entity type + // configuration. + $id_key = $entity_type->getKey('id'); + $revision_key = $entity_type->getKey('revision'); + $langcode_key = $entity_type->getKey('langcode'); + + $expected = []; + $expected[$entity_type->getBaseTable()] = [$id_key]; + if ($entity_type->isRevisionable()) { + $expected[$entity_type->getRevisionTable()] = [$revision_key]; + } + if ($entity_type->isTranslatable()) { + $expected[$entity_type->getDataTable()] = [$id_key, $langcode_key]; + } + if ($entity_type->isRevisionable() && $entity_type->isTranslatable()) { + $expected[$entity_type->getRevisionDataTable()] = [$revision_key, $langcode_key]; + } + + // First, test explicitly deleting and re-installing a field. Make sure that + // all primary keys are there to start with. + $this->assertSame($expected, $this->findPrimaryKeys($entity_type)); + + // Then uninstall the field and make sure all primary keys that the field + // was part of have been updated. Since this is not a valid state of the + // entity type (for example a revisionable entity type without a revision ID + // field or a translatable entity type without a language code field) the + // actual primary keys at this point are irrelevant. + $update_manager->uninstallFieldStorageDefinition($field); + $this->assertNotEquals($expected, $this->findPrimaryKeys($entity_type)); + + // Finally, reinstall the field and make sure the primary keys have been + // recreated. + $update_manager->installFieldStorageDefinition($field->getName(), $entity_type_id, $field->getProvider(), $field); + $this->assertSame($expected, $this->findPrimaryKeys($entity_type)); + + // Now test updating a field without data. This will end up deleting + // and re-creating the field, similar to the code above. + $update_manager->updateFieldStorageDefinition($field); + $this->assertSame($expected, $this->findPrimaryKeys($entity_type)); + + // Now test updating a field with data. + /* @var \Drupal\Core\Entity\FieldableEntityStorageInterface $storage */ + $storage = $this->entityManager->getStorage($entity_type_id); + // The schema of ID fields is incorrectly recreated as 'int' instead of + // 'serial', so we manually have to specify an ID. + // @todo Remove this in https://www.drupal.org/project/drupal/issues/2928906 + $storage->create(['id' => 1, 'revision_id' => 1])->save(); + $this->assertTrue($storage->countFieldData($field, TRUE)); + $update_manager->updateFieldStorageDefinition($field); + $this->assertSame($expected, $this->findPrimaryKeys($entity_type)); + $this->assertTrue($storage->countFieldData($field, TRUE)); + } + + /** + * Finds the primary keys for a given entity type. + * + * @param \Drupal\Core\Entity\EntityTypeInterface $entity_type + * The entity type whose primary keys are being fetched. + * + * @return array[] + * An array where the keys are the table names of the entity type's tables + * and the values are a list of the respective primary keys. + */ + protected function findPrimaryKeys(EntityTypeInterface $entity_type) { + $base_table = $entity_type->getBaseTable(); + $revision_table = $entity_type->getRevisionTable(); + $data_table = $entity_type->getDataTable(); + $revision_data_table = $entity_type->getRevisionDataTable(); + + $schema = $this->database->schema(); + $find_primary_key_columns = new \ReflectionMethod(get_class($schema), 'findPrimaryKeyColumns'); + $find_primary_key_columns->setAccessible(TRUE); + + // Build up a map of primary keys depending on the entity type + // configuration. If the field that is being removed is part of a table's + // primary key, we skip the assertion for that table as this represents an + // intermediate and invalid state of the entity schema. + $primary_keys[$base_table] = $find_primary_key_columns->invoke($schema, $base_table); + if ($entity_type->isRevisionable()) { + $primary_keys[$revision_table] = $find_primary_key_columns->invoke($schema, $revision_table); + } + if ($entity_type->isTranslatable()) { + $primary_keys[$data_table] = $find_primary_key_columns->invoke($schema, $data_table); + } + if ($entity_type->isRevisionable() && $entity_type->isTranslatable()) { + $primary_keys[$revision_data_table] = $find_primary_key_columns->invoke($schema, $revision_data_table); + } + + return $primary_keys; + } + + /** + * Provides test cases for EntitySchemaTest::testPrimaryKeyUpdate() + * + * @return array + * An array of test cases consisting of an entity type ID and a field name. + */ + public function providerTestPrimaryKeyUpdate() { + // Build up test cases for all possible entity type configurations. + // For each entity type we test reinstalling each field that is part of + // any table's primary key. + $tests = []; + + $tests['entity_test:id'] = ['entity_test', 'id']; + + $tests['entity_test_rev:id'] = ['entity_test_rev', 'id']; + $tests['entity_test_rev:revision_id'] = ['entity_test_rev', 'revision_id']; + + $tests['entity_test_mul:id'] = ['entity_test_mul', 'id']; + $tests['entity_test_mul:langcode'] = ['entity_test_mul', 'langcode']; + + $tests['entity_test_mulrev:id'] = ['entity_test_mulrev', 'id']; + $tests['entity_test_mulrev:revision_id'] = ['entity_test_mulrev', 'revision_id']; + $tests['entity_test_mulrev:langcode'] = ['entity_test_mulrev', 'langcode']; + + return $tests; + } + /** * {@inheritdoc} */ diff --git a/web/core/tests/Drupal/KernelTests/Core/Entity/EntityViewBuilderTest.php b/web/core/tests/Drupal/KernelTests/Core/Entity/EntityViewBuilderTest.php index e1537bc809c6c3e93f26128a6d757ec119908353..bfc0aeaa4147dc46ff0f1f899f2c4af8748f9c06 100644 --- a/web/core/tests/Drupal/KernelTests/Core/Entity/EntityViewBuilderTest.php +++ b/web/core/tests/Drupal/KernelTests/Core/Entity/EntityViewBuilderTest.php @@ -4,8 +4,8 @@ use Drupal\Core\Entity\EntityViewBuilder; use Drupal\Core\Language\LanguageInterface; -use Drupal\field\Tests\EntityReference\EntityReferenceTestTrait; use Drupal\Core\Cache\Cache; +use Drupal\Tests\field\Traits\EntityReferenceTestTrait; use Drupal\user\Entity\Role; use Drupal\user\RoleInterface; diff --git a/web/core/tests/Drupal/KernelTests/Core/Entity/RevisionableContentEntityBaseTest.php b/web/core/tests/Drupal/KernelTests/Core/Entity/RevisionableContentEntityBaseTest.php index 74b2d6e4d85b51f01994daace4928f718f55a52e..0b5d7b19f9878eb12ca4cd41a8256d433edfaa41 100644 --- a/web/core/tests/Drupal/KernelTests/Core/Entity/RevisionableContentEntityBaseTest.php +++ b/web/core/tests/Drupal/KernelTests/Core/Entity/RevisionableContentEntityBaseTest.php @@ -154,12 +154,12 @@ public function testWasDefaultRevision() { } /** - * Asserts the ammount of items on entity related tables. + * Asserts the amount of items on entity related tables. * * @param int $count * The number of items expected to be in revisions related tables. * @param \Drupal\Core\Entity\EntityTypeInterface $definition - * The definition and metada of the entity being tested. + * The definition and metadata of the entity being tested. */ protected function assertItemsTableCount($count, EntityTypeInterface $definition) { $this->assertEqual(1, db_query('SELECT COUNT(*) FROM {' . $definition->getBaseTable() . '}')->fetchField()); diff --git a/web/core/tests/Drupal/KernelTests/Core/Entity/ValidReferenceConstraintValidatorTest.php b/web/core/tests/Drupal/KernelTests/Core/Entity/ValidReferenceConstraintValidatorTest.php index be609d8d712e21fe0c1e76930a4913b1361e108e..3ac600285e3ab3d9de3bfaa9d302b858cf69f6ea 100644 --- a/web/core/tests/Drupal/KernelTests/Core/Entity/ValidReferenceConstraintValidatorTest.php +++ b/web/core/tests/Drupal/KernelTests/Core/Entity/ValidReferenceConstraintValidatorTest.php @@ -6,9 +6,9 @@ use Drupal\Core\Field\FieldStorageDefinitionInterface; use Drupal\entity_test\Entity\EntityTest; use Drupal\field\Entity\FieldConfig; -use Drupal\field\Tests\EntityReference\EntityReferenceTestTrait; use Drupal\node\Entity\Node; use Drupal\node\NodeInterface; +use Drupal\Tests\field\Traits\EntityReferenceTestTrait; use Drupal\Tests\node\Traits\ContentTypeCreationTrait; use Drupal\user\Entity\Role; use Drupal\user\Entity\User; @@ -201,7 +201,7 @@ public function testPreExistingItemsValidation() { $violations = $referencing_entity->field_test->validate(); $this->assertCount(0, $violations); - // Remove one of the referencable bundles and check that a pre-existing node + // Remove one of the referenceable bundles and check that a pre-existing node // of that bundle can not be referenced anymore. $field = FieldConfig::loadByName('entity_test', 'entity_test', 'field_test'); $field->setSetting('handler_settings', ['target_bundles' => ['article']]); diff --git a/web/core/tests/Drupal/KernelTests/Core/File/MimeTypeTest.php b/web/core/tests/Drupal/KernelTests/Core/File/MimeTypeTest.php index 4eca9976f222c18000b13efda225afa5da6347cb..01bf221fca54ba63c89c4a6de9d6a6a5fcec046f 100644 --- a/web/core/tests/Drupal/KernelTests/Core/File/MimeTypeTest.php +++ b/web/core/tests/Drupal/KernelTests/Core/File/MimeTypeTest.php @@ -53,7 +53,7 @@ public function testFileMimeTypeDetection() { $this->assertIdentical($output, $expected, format_string('Mimetype (using default mappings) for %input is %output (expected: %expected).', ['%input' => $input, '%output' => $output, '%expected' => $expected])); } - // Now test the extension gusser by passing in a custom mapping. + // Now test the extension guesser by passing in a custom mapping. $mapping = [ 'mimetypes' => [ 0 => 'application/java-archive', diff --git a/web/core/tests/Drupal/KernelTests/Core/File/PharWrapperTest.php b/web/core/tests/Drupal/KernelTests/Core/File/PharWrapperTest.php new file mode 100644 index 0000000000000000000000000000000000000000..2cd2ab1ea94944b3cef1a759369f1df311d6eb0a --- /dev/null +++ b/web/core/tests/Drupal/KernelTests/Core/File/PharWrapperTest.php @@ -0,0 +1,33 @@ +<?php + +namespace Drupal\KernelTests\Core\File; + +use Drupal\KernelTests\KernelTestBase; + +/** + * Tests that the phar stream wrapper works. + * + * @group File + */ +class PharWrapperTest extends KernelTestBase { + + /** + * Tests that only valid phar files can be used. + */ + public function testPharFile() { + $base = $this->getDrupalRoot() . '/core/modules/simpletest/files'; + // Ensure that file operations via the phar:// stream wrapper work for phar + // files with the .phar extension. + $this->assertFalse(file_exists("phar://$base/phar-1.phar/no-such-file.php")); + $this->assertTrue(file_exists("phar://$base/phar-1.phar/index.php")); + $file_contents = file_get_contents("phar://$base/phar-1.phar/index.php"); + $expected_hash = 'c7e7904ea573c5ebea3ef00bb08c1f86af1a45961fbfbeb1892ff4a98fd73ad5'; + $this->assertSame($expected_hash, hash('sha256', $file_contents)); + + // Ensure that file operations via the phar:// stream wrapper throw an + // exception for files without the .phar extension. + $this->setExpectedException('TYPO3\PharStreamWrapper\Exception'); + file_exists("phar://$base/image-2.jpg/index.php"); + } + +} diff --git a/web/core/tests/Drupal/KernelTests/Core/File/StreamWrapperTest.php b/web/core/tests/Drupal/KernelTests/Core/File/StreamWrapperTest.php index 6c18b6654ccda69848b8851ae01feb81091fe681..070782fcba67537a178638197cafee33525dc9fc 100644 --- a/web/core/tests/Drupal/KernelTests/Core/File/StreamWrapperTest.php +++ b/web/core/tests/Drupal/KernelTests/Core/File/StreamWrapperTest.php @@ -144,4 +144,31 @@ public function testGetValidStreamScheme() { $this->assertFalse(file_stream_wrapper_valid_scheme(file_uri_scheme('foo://asdf')), 'Did not get a valid stream scheme from foo://asdf'); } + /** + * Tests that phar stream wrapper is registered as expected. + * + * @see \Drupal\Core\StreamWrapper\StreamWrapperManager::register() + */ + public function testPharStreamWrapperRegistration() { + if (!in_array('phar', stream_get_wrappers(), TRUE)) { + $this->markTestSkipped('There is no phar stream wrapper registered. PHP is probably compiled without phar support.'); + } + // Ensure that phar is not treated as a valid scheme. + $stream_wrapper_manager = $this->container->get('stream_wrapper_manager'); + $this->assertFalse($stream_wrapper_manager->getViaScheme('phar')); + + // Ensure that calling register again and unregister do not create errors + // due to the PharStreamWrapperManager singleton. + $stream_wrapper_manager->register(); + $this->assertContains('public', stream_get_wrappers()); + $this->assertContains('phar', stream_get_wrappers()); + $stream_wrapper_manager->unregister(); + $this->assertNotContains('public', stream_get_wrappers()); + // This will have reverted to the builtin phar stream wrapper. + $this->assertContains('phar', stream_get_wrappers()); + $stream_wrapper_manager->register(); + $this->assertContains('public', stream_get_wrappers()); + $this->assertContains('phar', stream_get_wrappers()); + } + } diff --git a/web/core/tests/Drupal/KernelTests/Core/Form/FormValidationMessageOrderTest.php b/web/core/tests/Drupal/KernelTests/Core/Form/FormValidationMessageOrderTest.php index 4e056cdd8bda0b30bcdbb27f6e3aa411d99e325b..6755fd53d89ab2c3efec2caf8b469a63bbeea470 100644 --- a/web/core/tests/Drupal/KernelTests/Core/Form/FormValidationMessageOrderTest.php +++ b/web/core/tests/Drupal/KernelTests/Core/Form/FormValidationMessageOrderTest.php @@ -8,7 +8,7 @@ use Drupal\KernelTests\KernelTestBase; /** - * Tests form validation mesages are displayed in the same order as the fields. + * Tests form validation messages are displayed in the same order as the fields. * * @group Form */ diff --git a/web/core/tests/Drupal/KernelTests/Core/Menu/LocalActionManagerTest.php b/web/core/tests/Drupal/KernelTests/Core/Menu/LocalActionManagerTest.php new file mode 100644 index 0000000000000000000000000000000000000000..13acd8b982b9b59d509570283a0b3a184986b611 --- /dev/null +++ b/web/core/tests/Drupal/KernelTests/Core/Menu/LocalActionManagerTest.php @@ -0,0 +1,50 @@ +<?php + +namespace Drupal\KernelTests\Core\Menu; + +use Drupal\KernelTests\KernelTestBase; + +/** + * Tests the local action manager. + * + * @coversDefaultClass \Drupal\Core\Menu\LocalActionManager + * @group Menu + */ +class LocalActionManagerTest extends KernelTestBase { + + /** + * {@inheritdoc} + */ + public static $modules = ['menu_test', 'user', 'system']; + + /** + * Tests the cacheability of local actions. + */ + public function testCacheability() { + /** @var \Drupal\Core\Menu\LocalActionManager $local_action_manager */ + $local_action_manager = \Drupal::service('plugin.manager.menu.local_action'); + $build = [ + '#cache' => [ + 'key' => 'foo', + ], + $local_action_manager->getActionsForRoute('menu_test.local_action7'), + ]; + + /** @var \Drupal\Core\Render\RendererInterface $renderer */ + $renderer = \Drupal::service('renderer'); + $renderer->renderRoot($build); + + $this->assertContains('menu_local_action7', $build[0]['menu_test.local_action7']['#cache']['tags']); + $this->assertContains('url.query_args:menu_local_action7', $build[0]['menu_test.local_action7']['#cache']['contexts']); + + $this->assertContains('menu_local_action8', $build[0]['menu_test.local_action8']['#cache']['tags']); + $this->assertContains('url.query_args:menu_local_action8', $build[0]['menu_test.local_action8']['#cache']['contexts']); + + $this->assertContains('menu_local_action7', $build['#cache']['tags']); + $this->assertContains('url.query_args:menu_local_action7', $build['#cache']['contexts']); + + $this->assertContains('menu_local_action8', $build['#cache']['tags']); + $this->assertContains('url.query_args:menu_local_action8', $build['#cache']['contexts']); + } + +} diff --git a/web/core/tests/Drupal/KernelTests/Core/Path/AliasTest.php b/web/core/tests/Drupal/KernelTests/Core/Path/AliasTest.php index 1f49b09ffdc5af3148f66950a596f56114bfc7dc..48d6b7d985d9bb771f4c333484ac32b25b4780ab 100644 --- a/web/core/tests/Drupal/KernelTests/Core/Path/AliasTest.php +++ b/web/core/tests/Drupal/KernelTests/Core/Path/AliasTest.php @@ -241,7 +241,7 @@ public function testWhitelistCacheDeletionMidRequest() { // Lookup admin path in whitelist. It will query the DB and figure out // that it indeed has an alias, and add it to the internal whitelist and - // flag it to be peristed to cache. + // flag it to be persisted to cache. $this->assertTrue($whitelist->get('admin')); // Destruct the whitelist so it persists its cache. diff --git a/web/core/tests/Drupal/KernelTests/Core/Plugin/ContextTypedDataTest.php b/web/core/tests/Drupal/KernelTests/Core/Plugin/ContextTypedDataTest.php new file mode 100644 index 0000000000000000000000000000000000000000..2ffec87a13a9cfba2781012a2a8f39f87ac308df --- /dev/null +++ b/web/core/tests/Drupal/KernelTests/Core/Plugin/ContextTypedDataTest.php @@ -0,0 +1,63 @@ +<?php + +namespace Drupal\KernelTests\Core\Plugin; + +use Drupal\Core\Plugin\Context\Context; +use Drupal\Core\Plugin\Context\ContextDefinition; +use Drupal\Core\TypedData\DataDefinition; +use Drupal\Core\TypedData\Plugin\DataType\StringData; +use Drupal\Core\TypedData\TypedDataManagerInterface; +use Drupal\KernelTests\KernelTestBase; + +/** + * Tests that contexts work properly with the typed data manager. + * + * @coversDefaultClass \Drupal\Core\Plugin\Context\Context + * @group Context + */ +class ContextTypedDataTest extends KernelTestBase { + + /** + * Tests that contexts can be serialized. + */ + public function testSerialize() { + $definition = new ContextDefinition('any'); + $data_definition = DataDefinition::create('string'); + $typed_data = new StringData($data_definition); + $typed_data->setValue('example string'); + $context = new Context($definition, $typed_data); + // getContextValue() will cause the context to reference the typed data + // manager service. + $value = $context->getContextValue(); + $context = serialize($context); + $context = unserialize($context); + $this->assertSame($value, $context->getContextValue()); + } + + /** + * Tests that getting a context value does not throw fatal errors. + * + * This test ensures that the typed data manager is set correctly on the + * Context class. + * + * @covers ::getContextValue + */ + public function testGetContextValue() { + $data_definition = DataDefinition::create('string'); + $typed_data = new StringData($data_definition); + $typed_data->setValue('example string'); + + // Prepare a container that holds the typed data manager mock. + $typed_data_manager = $this->prophesize(TypedDataManagerInterface::class); + $typed_data_manager->getCanonicalRepresentation($typed_data)->will(function ($arguments) { + return $arguments[0]->getValue(); + }); + $this->container->set('typed_data_manager', $typed_data_manager->reveal()); + + $definition = new ContextDefinition('any'); + $context = new Context($definition, $typed_data); + $value = $context->getContextValue(); + $this->assertSame($value, $typed_data->getValue()); + } + +} diff --git a/web/core/tests/Drupal/KernelTests/Core/Plugin/EntityContextTypedDataTest.php b/web/core/tests/Drupal/KernelTests/Core/Plugin/EntityContextTypedDataTest.php new file mode 100644 index 0000000000000000000000000000000000000000..c26a3f8a9afc704676bf4b5bc98fb33734ce89fe --- /dev/null +++ b/web/core/tests/Drupal/KernelTests/Core/Plugin/EntityContextTypedDataTest.php @@ -0,0 +1,37 @@ +<?php + +namespace Drupal\KernelTests\Core\Plugin; + +use Drupal\Core\Entity\Entity\EntityViewDisplay; +use Drupal\Core\Plugin\Context\EntityContext; +use Drupal\KernelTests\KernelTestBase; + +/** + * Tests the interaction between entity context and typed data. + * + * @group Context + */ +class EntityContextTypedDataTest extends KernelTestBase { + + /** + * {@inheritdoc} + */ + protected static $modules = ['entity_test']; + + /** + * Tests that entity contexts wrapping a config entity can be validated. + */ + public function testValidateConfigEntityContext() { + $display = EntityViewDisplay::create([ + 'targetEntityType' => 'entity_test', + 'bundle' => 'entity_test', + 'mode' => 'default', + 'status' => TRUE, + ]); + $display->save(); + + $violations = EntityContext::fromEntity($display)->validate(); + $this->assertCount(0, $violations); + } + +} diff --git a/web/core/tests/Drupal/KernelTests/Core/Routing/MatcherDumperTest.php b/web/core/tests/Drupal/KernelTests/Core/Routing/MatcherDumperTest.php index f37383d631df3463fe0fb76a51b88be3cbd84f72..4145b2369e71eb4557be5af0afd4739b3327e21f 100644 --- a/web/core/tests/Drupal/KernelTests/Core/Routing/MatcherDumperTest.php +++ b/web/core/tests/Drupal/KernelTests/Core/Routing/MatcherDumperTest.php @@ -2,9 +2,7 @@ namespace Drupal\KernelTests\Core\Routing; -use Drupal\Core\Cache\MemoryBackend; use Drupal\Core\KeyValueStore\KeyValueMemoryFactory; -use Drupal\Core\Lock\NullLockBackend; use Drupal\Core\State\State; use Drupal\KernelTests\KernelTestBase; use Symfony\Component\Routing\Route; @@ -38,7 +36,7 @@ protected function setUp() { parent::setUp(); $this->fixtures = new RoutingFixtures(); - $this->state = new State(new KeyValueMemoryFactory(), new MemoryBackend('test'), new NullLockBackend()); + $this->state = new State(new KeyValueMemoryFactory()); } /** diff --git a/web/core/tests/Drupal/KernelTests/Core/Routing/RouteProviderTest.php b/web/core/tests/Drupal/KernelTests/Core/Routing/RouteProviderTest.php index 44efa16479769cadc55e8e0a5a0d74046834a7f7..713eb3cd1ee44f0dcbe3fba3ac6c3ed601632a54 100644 --- a/web/core/tests/Drupal/KernelTests/Core/Routing/RouteProviderTest.php +++ b/web/core/tests/Drupal/KernelTests/Core/Routing/RouteProviderTest.php @@ -12,7 +12,6 @@ use Drupal\Core\Database\Database; use Drupal\Core\DependencyInjection\ContainerBuilder; use Drupal\Core\KeyValueStore\KeyValueMemoryFactory; -use Drupal\Core\Lock\NullLockBackend; use Drupal\Core\Path\CurrentPathStack; use Drupal\Core\Routing\MatcherDumper; use Drupal\Core\Routing\RouteProvider; @@ -84,7 +83,7 @@ class RouteProviderTest extends KernelTestBase { protected function setUp() { parent::setUp(); $this->fixtures = new RoutingFixtures(); - $this->state = new State(new KeyValueMemoryFactory(), new MemoryBackend('test'), new NullLockBackend()); + $this->state = new State(new KeyValueMemoryFactory()); $this->currentPath = new CurrentPathStack(new RequestStack()); $this->cache = new MemoryBackend(); $this->pathProcessor = \Drupal::service('path_processor_manager'); @@ -97,7 +96,7 @@ protected function setUp() { public function register(ContainerBuilder $container) { parent::register($container); - // Readd the incoming path alias for these tests. + // Read the incoming path alias for these tests. if ($container->hasDefinition('path_processor_alias')) { $definition = $container->getDefinition('path_processor_alias'); $definition->addTag('path_processor_inbound'); diff --git a/web/core/tests/Drupal/KernelTests/Core/TempStore/AnonymousPrivateTempStoreTest.php b/web/core/tests/Drupal/KernelTests/Core/TempStore/AnonymousPrivateTempStoreTest.php index 7b1faa86cce15d908b1859436d17db9d60c74718..77d229aee4676ced6c6a187487a0894d70d1a281 100644 --- a/web/core/tests/Drupal/KernelTests/Core/TempStore/AnonymousPrivateTempStoreTest.php +++ b/web/core/tests/Drupal/KernelTests/Core/TempStore/AnonymousPrivateTempStoreTest.php @@ -19,6 +19,13 @@ class AnonymousPrivateTempStoreTest extends KernelTestBase { */ public static $modules = ['system']; + /** + * The private temp store. + * + * @var \Drupal\Core\TempStore\PrivateTempStore + */ + protected $tempStore; + /** * {@inheritdoc} */ @@ -29,30 +36,35 @@ protected function setUp() { // full Drupal environment. $this->installSchema('system', ['key_value_expire']); - $session = $this->container->get('session'); $request = Request::create('/'); - $request->setSession($session); - $stack = $this->container->get('request_stack'); $stack->pop(); $stack->push($request); + $this->tempStore = $this->container->get('tempstore.private')->get('anonymous_private_temp_store'); + } + + /** + * Tests anonymous can get without a previous set. + */ + public function testAnonymousCanUsePrivateTempStoreGet() { + $actual = $this->tempStore->get('foo'); + $this->assertNull($actual); } /** * Tests anonymous can use the PrivateTempStore. */ - public function testAnonymousCanUsePrivateTempStore() { - $temp_store = $this->container->get('tempstore.private')->get('anonymous_private_temp_store'); - $temp_store->set('foo', 'bar'); - $metadata1 = $temp_store->getMetadata('foo'); + public function testAnonymousCanUsePrivateTempStoreSet() { + $this->tempStore->set('foo', 'bar'); + $metadata1 = $this->tempStore->getMetadata('foo'); - $this->assertEquals('bar', $temp_store->get('foo')); + $this->assertEquals('bar', $this->tempStore->get('foo')); $this->assertNotEmpty($metadata1->owner); - $temp_store->set('foo', 'bar2'); - $metadata2 = $temp_store->getMetadata('foo'); - $this->assertEquals('bar2', $temp_store->get('foo')); + $this->tempStore->set('foo', 'bar2'); + $metadata2 = $this->tempStore->getMetadata('foo'); + $this->assertEquals('bar2', $this->tempStore->get('foo')); $this->assertNotEmpty($metadata2->owner); $this->assertEquals($metadata2->owner, $metadata1->owner); } diff --git a/web/core/tests/Drupal/KernelTests/Core/Theme/MessageTest.php b/web/core/tests/Drupal/KernelTests/Core/Theme/MessageTest.php index 1b3796eff43132ffae02b937e3a339c6bbc38544..5552591ed1a422753ae5014b87ff07b583551058 100644 --- a/web/core/tests/Drupal/KernelTests/Core/Theme/MessageTest.php +++ b/web/core/tests/Drupal/KernelTests/Core/Theme/MessageTest.php @@ -32,6 +32,14 @@ public function testMessages() { $this->render($messages); $this->assertRaw('messages messages--error'); $this->assertRaw('messages messages--status'); + // Tests display of only one type of messages. + \Drupal::messenger()->addError('An error occurred'); + $messages = [ + '#type' => 'status_messages', + '#display' => 'error', + ]; + $this->render($messages); + $this->assertRaw('messages messages--error'); } } diff --git a/web/core/tests/Drupal/Nightwatch/Tests/statesTest.js b/web/core/tests/Drupal/Nightwatch/Tests/statesTest.js new file mode 100644 index 0000000000000000000000000000000000000000..f7ee1ba52219d1219b201e7eaa529c0c0211db2f --- /dev/null +++ b/web/core/tests/Drupal/Nightwatch/Tests/statesTest.js @@ -0,0 +1,23 @@ +module.exports = { + '@tags': ['core'], + before(browser) { + browser.drupalInstall().drupalLoginAsAdmin(() => { + browser + .drupalRelativeURL('/admin/modules') + .setValue('input[type="search"]', 'FormAPI') + .waitForElementVisible('input[name="modules[form_test][enable]"]', 1000) + .click('input[name="modules[form_test][enable]"]') + .click('input[type="submit"]') // Submit module form. + .click('input[type="submit"]'); // Confirm installation of dependencies. + }); + }, + after(browser) { + browser.drupalUninstall(); + }, + 'Test form with state API': browser => { + browser + .drupalRelativeURL('/form-test/javascript-states-form') + .waitForElementVisible('body', 1000) + .waitForElementNotVisible('input[name="textfield"]', 1000); + }, +}; diff --git a/web/core/tests/Drupal/Tests/BrowserTestBase.php b/web/core/tests/Drupal/Tests/BrowserTestBase.php index 3512520e359cb2d2b8ba18bceaf06e19ec6fc1f0..204eacb4f516fa2cdb535add5c2653d4147744cf 100644 --- a/web/core/tests/Drupal/Tests/BrowserTestBase.php +++ b/web/core/tests/Drupal/Tests/BrowserTestBase.php @@ -124,7 +124,7 @@ abstract class BrowserTestBase extends TestCase { /* * Mink class for the default driver to use. * - * Shoud be a fully qualified class name that implements + * Should be a fully-qualified class name that implements * Behat\Mink\Driver\DriverInterface. * * Value can be overridden using the environment variable MINK_DRIVER_CLASS. @@ -245,6 +245,16 @@ protected function initMink() { $this->initFrontPage(); + // Copies cookies from the current environment, for example, XDEBUG_SESSION + // in order to support Xdebug. + // @see BrowserTestBase::initFrontPage() + $cookies = $this->extractCookiesFromRequest(\Drupal::request()); + foreach ($cookies as $cookie_name => $values) { + foreach ($values as $value) { + $session->setCookie($cookie_name, $value); + } + } + return $session; } @@ -388,14 +398,7 @@ protected function setUp() { $this->installDrupal(); // Setup Mink. - $session = $this->initMink(); - - $cookies = $this->extractCookiesFromRequest(\Drupal::request()); - foreach ($cookies as $cookie_name => $values) { - foreach ($values as $value) { - $session->setCookie($cookie_name, $value); - } - } + $this->initMink(); // Set up the browser test output file. $this->initBrowserOutputFile(); @@ -677,7 +680,7 @@ protected function drupalGetHeader($name) { * The JSON decoded drupalSettings value from the current page. */ protected function getDrupalSettings() { - $html = $this->getSession()->getPage()->getHtml(); + $html = $this->getSession()->getPage()->getContent(); if (preg_match('@<script type="application/json" data-drupal-selector="drupal-settings-json">([^<]*)</script>@', $html, $matches)) { return Json::decode($matches[1]); } diff --git a/web/core/tests/Drupal/Tests/Component/Datetime/DateTimePlusTest.php b/web/core/tests/Drupal/Tests/Component/Datetime/DateTimePlusTest.php index 08eb2068ff5a97c191f40ac2010130c2e177ab99..6e7040adf13e0455c8c39df42b14277a006bc934 100644 --- a/web/core/tests/Drupal/Tests/Component/Datetime/DateTimePlusTest.php +++ b/web/core/tests/Drupal/Tests/Component/Datetime/DateTimePlusTest.php @@ -330,7 +330,9 @@ public function providerTestDates() { // Create a date object in the distant past. // @see https://www.drupal.org/node/2795489#comment-12127088 if (version_compare(PHP_VERSION, '5.6.15', '>=')) { - $dates[] = ['1809-02-12 10:30', 'America/Chicago', '1809-02-12T10:30:00-06:00']; + // Note that this date is after the United States standardized its + // timezones. + $dates[] = ['1883-11-19 10:30', 'America/Chicago', '1883-11-19T10:30:00-06:00']; } // Create a date object in the far future. $dates[] = ['2345-01-02 02:04', 'UTC', '2345-01-02T02:04:00+00:00']; @@ -366,7 +368,9 @@ public function providerTestDateArrays() { // Create a date object in the distant past. // @see https://www.drupal.org/node/2795489#comment-12127088 if (version_compare(PHP_VERSION, '5.6.15', '>=')) { - $dates[] = [['year' => 1809, 'month' => 2, 'day' => 12], 'America/Chicago', '1809-02-12T00:00:00-06:00']; + // Note that this date is after the United States standardized its + // timezones. + $dates[] = [['year' => 1883, 'month' => 11, 'day' => 19], 'America/Chicago', '1883-11-19T00:00:00-06:00']; } // Create a date object in the far future. $dates[] = [['year' => 2345, 'month' => 1, 'day' => 2], 'UTC', '2345-01-02T00:00:00+00:00']; @@ -807,7 +811,7 @@ public function providerTestInvalidConstructor() { public function testValidateFormat() { // Check that an input that does not strictly follow the input format will // produce the desired date. In this case the year string '11' doesn't - // precisely match the 'Y' formater parameter, but PHP will parse it + // precisely match the 'Y' formatter parameter, but PHP will parse it // regardless. However, when formatted with the same string, the year will // be output with four digits. With the ['validate_format' => FALSE] // $settings, this will not thrown an exception. diff --git a/web/core/tests/Drupal/Tests/Component/Plugin/PluginManagerBaseTest.php b/web/core/tests/Drupal/Tests/Component/Plugin/PluginManagerBaseTest.php index a4dd6a76bd9f7dba9abef84655c6f3566f01b0cc..2bad780dbcabefebaa6e12e60068898bd987ef8f 100644 --- a/web/core/tests/Drupal/Tests/Component/Plugin/PluginManagerBaseTest.php +++ b/web/core/tests/Drupal/Tests/Component/Plugin/PluginManagerBaseTest.php @@ -3,6 +3,8 @@ namespace Drupal\Tests\Component\Plugin; use Drupal\Component\Plugin\Exception\PluginNotFoundException; +use Drupal\Component\Plugin\Mapper\MapperInterface; +use Drupal\Component\Plugin\PluginManagerBase; use PHPUnit\Framework\TestCase; /** @@ -90,4 +92,43 @@ public function testCreateInstanceFallback() { $this->assertEquals($configuration_array, $fallback_result['configuration']); } + /** + * @covers ::getInstance + */ + public function testGetInstance() { + $options = [ + 'foo' => 'F00', + 'bar' => 'bAr', + ]; + $instance = new \stdClass(); + $mapper = $this->prophesize(MapperInterface::class); + $mapper->getInstance($options) + ->shouldBeCalledTimes(1) + ->willReturn($instance); + $manager = new StubPluginManagerBaseWithMapper($mapper->reveal()); + $this->assertEquals($instance, $manager->getInstance($options)); + } + + /** + * @covers ::getInstance + */ + public function testGetInstanceWithoutMapperShouldThrowException() { + $options = [ + 'foo' => 'F00', + 'bar' => 'bAr', + ]; + /** @var \Drupal\Component\Plugin\PluginManagerBase $manager */ + $manager = $this->getMockBuilder(PluginManagerBase::class) + ->getMockForAbstractClass(); + // Set the expected exception thrown by ::getInstance. + if (method_exists($this, 'expectException')) { + $this->expectException(\BadMethodCallException::class); + $this->expectExceptionMessage(sprintf('%s does not support this method unless %s::$mapper is set.', get_class($manager), get_class($manager))); + } + else { + $this->setExpectedException(\BadMethodCallException::class, sprintf('%s does not support this method unless %s::$mapper is set.', get_class($manager), get_class($manager))); + } + $manager->getInstance($options); + } + } diff --git a/web/core/tests/Drupal/Tests/Component/Plugin/StubPluginManagerBaseWithMapper.php b/web/core/tests/Drupal/Tests/Component/Plugin/StubPluginManagerBaseWithMapper.php new file mode 100644 index 0000000000000000000000000000000000000000..d3f3f94b078129afb3966db57862d064ef44aed7 --- /dev/null +++ b/web/core/tests/Drupal/Tests/Component/Plugin/StubPluginManagerBaseWithMapper.php @@ -0,0 +1,22 @@ +<?php + +namespace Drupal\Tests\Component\Plugin; + +use Drupal\Component\Plugin\Mapper\MapperInterface; +use Drupal\Component\Plugin\PluginManagerBase; + +/** + * Stubs \Drupal\Component\Plugin\PluginManagerBase to take a MapperInterface. + */ +final class StubPluginManagerBaseWithMapper extends PluginManagerBase { + + /** + * Constructs a new instance. + * + * @param \Drupal\Component\Plugin\Mapper\MapperInterface $mapper + */ + public function __construct(MapperInterface $mapper) { + $this->mapper = $mapper; + } + +} diff --git a/web/core/tests/Drupal/Tests/Component/Transliteration/PhpTransliterationTest.php b/web/core/tests/Drupal/Tests/Component/Transliteration/PhpTransliterationTest.php index dc71bd4cde25d9cb589cd68d3cd3ccfc2f6c2a67..b6a79b3a73aa53586bdd71dab2608548e71604d0 100644 --- a/web/core/tests/Drupal/Tests/Component/Transliteration/PhpTransliterationTest.php +++ b/web/core/tests/Drupal/Tests/Component/Transliteration/PhpTransliterationTest.php @@ -106,7 +106,7 @@ public function providerTestPhpTransliteration() { // Make some strings with two, three, and four-byte characters for testing. // Note that the 3-byte character is overridden by the 'kg' language. $two_byte = 'Ä Ö Ü Å Ø äöüåøhello'; - // This is a Cyrrillic character that looks something like a u. See + // This is a Cyrillic character that looks something like a "u". See // http://www.unicode.org/charts/PDF/U0400.pdf $three_byte = html_entity_decode('ц', ENT_NOQUOTES, 'UTF-8'); // This is a Canadian Aboriginal character like a triangle. See @@ -142,8 +142,6 @@ public function providerTestPhpTransliteration() { // Test strings in some other languages. // Turkish, provided by drupal.org user Kartagis. ['tr', 'Abayı serdiler bize. Söyleyeceğim yüzlerine. Sanırım hepimiz aynı şeyi düşünüyoruz.', 'Abayi serdiler bize. Soyleyecegim yuzlerine. Sanirim hepimiz ayni seyi dusunuyoruz.'], - // Illegal/unknown unicode. - ['en', chr(0xF8) . chr(0x80) . chr(0x80) . chr(0x80) . chr(0x80), '?'], // Max length. ['de', $two_byte, 'Ae Oe', '?', 5], ]; @@ -164,6 +162,60 @@ public function testTransliterationWithMaxLength() { $this->assertSame($trunc_output, $transliteration->transliterate($input, 'de', '?', 18), 'Truncating to 18 characters works'); } + /** + * Tests the unknown character replacement. + * + * @param string $langcode + * The language code to test. + * @param string $original + * The original string. + * @param string $expected + * The expected return from PhpTransliteration::transliterate(). + * @param string $unknown_character + * The character to substitute for characters in $string without + * transliterated equivalents. + * @param int $max_length + * The maximum length of the string that returns the transliteration. + * + * @dataProvider providerTestTransliterationUnknownCharacter + */ + public function testTransliterationUnknownCharacter($langcode, $original, $expected, $unknown_character = '?', $max_length = NULL) { + $transliteration = new PhpTransliteration(); + $actual = $transliteration->transliterate($original, $langcode, $unknown_character, $max_length); + $this->assertSame($expected, $actual); + } + + /** + * Provides data for self::testTransliterationUnknownCharacter(). + * + * @return array + * An array of arrays, each containing the parameters for + * self::testTransliterationUnknownCharacter(). + */ + public function providerTestTransliterationUnknownCharacter() { + return [ + // Each test case is (language code, input, output, unknown character, max + // length). + + // Illegal/unknown unicode. + ['en', chr(0xF8) . chr(0x80) . chr(0x80) . chr(0x80) . chr(0x80), '?????'], + ['en', chr(0xF8) . chr(0x80) . chr(0x80) . chr(0x80) . chr(0x80), '-----', '-'], + ['en', 'Hel' . chr(0x80) . 'o World', 'Hel?o World'], + ['en', 'Hell' . chr(0x80) . ' World', 'Hell? World'], + // Non default replacement. + ['en', chr(0x80) . 'ello World', '_ello World', '_'], + // Keep the original question marks. + ['en', chr(0xF8) . '?' . chr(0x80), '???'], + ['en', chr(0x80) . 'ello ? World?', '_ello ? World?', '_'], + ['pl', 'aąeę' . chr(0x80) . 'oółżźz ?', 'aaee?oolzzz ?'], + // Non-US-ASCII replacement. + ['en', chr(0x80) . 'ello World?', 'Oello World?', 'Ö'], + ['pl', chr(0x80) . 'óóść', 'ooosc', 'ó'], + // Ensure question marks are replaced when max length used. + ['en', chr(0x80) . 'ello ? World?', '_ello ?', '_', 7], + ]; + } + /** * Tests inclusion is safe. * diff --git a/web/core/tests/Drupal/Tests/Component/Utility/MailTest.php b/web/core/tests/Drupal/Tests/Component/Utility/MailTest.php new file mode 100644 index 0000000000000000000000000000000000000000..5f3032891900264401ab76e413c9d94f4ef2cc97 --- /dev/null +++ b/web/core/tests/Drupal/Tests/Component/Utility/MailTest.php @@ -0,0 +1,60 @@ +<?php + +namespace Drupal\Tests\Component\Utility; + +use Drupal\Component\Utility\Mail; +use PHPUnit\Framework\TestCase; + +/** + * Test mail helpers implemented in Mail component. + * + * @group Utility + * + * @coversDefaultClass \Drupal\Component\Utility\Mail + */ +class MailTest extends TestCase { + + /** + * Tests RFC-2822 'display-name' formatter. + * + * @dataProvider providerTestDisplayName + * @covers ::formatDisplayName + */ + public function testFormatDisplayName($string, $safe_display_name) { + $this->assertEquals($safe_display_name, Mail::formatDisplayName($string)); + } + + /** + * Data provider for testFormatDisplayName(). + * + * @see testFormatDisplayName() + * + * @return array + * An array containing a string and its 'display-name' safe value. + */ + public function providerTestDisplayName() { + return [ + // Simple ASCII characters. + ['Test site', 'Test site'], + // ASCII with html entity. + ['Test & site', 'Test & site'], + // Non-ASCII characters. + ['Tést site', '=?UTF-8?B?VMOpc3Qgc2l0ZQ==?='], + // Non-ASCII with special characters. + ['Tést; site', '=?UTF-8?B?VMOpc3Q7IHNpdGU=?='], + // Non-ASCII with html entity. + ['Tést; site', '=?UTF-8?B?VMOpc3Q7IHNpdGU=?='], + // ASCII with special characters. + ['Test; site', '"Test; site"'], + // ASCII with special characters as html entity. + ['Test < site', '"Test < site"'], + // ASCII with special characters and '\'. + ['Test; \ "site"', '"Test; \\\\ \"site\""'], + // String already RFC-2822 compliant. + ['"Test; site"', '"Test; site"'], + // String already RFC-2822 compliant. + ['"Test; \\\\ \"site\""', '"Test; \\\\ \"site\""'], + ]; + } + +} diff --git a/web/core/tests/Drupal/Tests/Core/Asset/CssOptimizerUnitTest.php b/web/core/tests/Drupal/Tests/Core/Asset/CssOptimizerUnitTest.php index 5b71a1ca5f64e19869e64bcd83b03303e7b33947..f39a93862d0b7b0401ffb85464e114859e698c2f 100644 --- a/web/core/tests/Drupal/Tests/Core/Asset/CssOptimizerUnitTest.php +++ b/web/core/tests/Drupal/Tests/Core/Asset/CssOptimizerUnitTest.php @@ -107,7 +107,7 @@ public function providerTestOptimize() { str_replace('url(../images/icon.png)', 'url(' . file_url_transform_relative(file_create_url($path . 'images/icon.png')) . ')', file_get_contents($absolute_path . 'css_subfolder/css_input_with_import.css.optimized.css')), ], // File. Tests: - // - Any @charaset declaration at the beginning of a file should be + // - Any @charset declaration at the beginning of a file should be // removed without breaking subsequent CSS. [ [ diff --git a/web/core/tests/Drupal/Tests/Core/Command/QuickStartTest.php b/web/core/tests/Drupal/Tests/Core/Command/QuickStartTest.php index c792d1abad5cc3cff904a8f873a60e5d124f4efc..5622aa23752840d85cbf350a550eb9ca19c3aee8 100644 --- a/web/core/tests/Drupal/Tests/Core/Command/QuickStartTest.php +++ b/web/core/tests/Drupal/Tests/Core/Command/QuickStartTest.php @@ -85,7 +85,15 @@ public function tearDown() { public function testQuickStartCommand() { // Install a site using the standard profile to ensure the one time login // link generation works. - $install_command = "{$this->php} core/scripts/drupal quick-start standard --site-name='Test site {$this->testDb->getDatabasePrefix()}' --suppress-login"; + + $install_command = [ + $this->php, + 'core/scripts/drupal', + 'quick-start', + 'standard', + "--site-name='Test site {$this->testDb->getDatabasePrefix()}'", + '--suppress-login', + ]; $process = new Process($install_command, NULL, ['DRUPAL_DEV_SITE_PATH' => $this->testDb->getTestSitePath()]); $process->inheritEnvironmentVariables(); $process->setTimeout(500); @@ -129,7 +137,13 @@ public function testQuickStartCommand() { */ public function testQuickStartInstallAndServerCommands() { // Install a site. - $install_command = "{$this->php} core/scripts/drupal install testing --site-name='Test site {$this->testDb->getDatabasePrefix()}'"; + $install_command = [ + $this->php, + 'core/scripts/drupal', + 'install', + 'testing', + "--site-name='Test site {$this->testDb->getDatabasePrefix()}'", + ]; $install_process = new Process($install_command, NULL, ['DRUPAL_DEV_SITE_PATH' => $this->testDb->getTestSitePath()]); $install_process->inheritEnvironmentVariables(); $install_process->setTimeout(500); @@ -139,7 +153,12 @@ public function testQuickStartInstallAndServerCommands() { $this->assertSame(0, $result); // Run the PHP built-in webserver. - $server_command = "{$this->php} core/scripts/drupal server --suppress-login"; + $server_command = [ + $this->php, + 'core/scripts/drupal', + 'server', + '--suppress-login', + ]; $server_process = new Process($server_command, NULL, ['DRUPAL_DEV_SITE_PATH' => $this->testDb->getTestSitePath()]); $server_process->inheritEnvironmentVariables(); $server_process->start(); @@ -173,7 +192,13 @@ public function testQuickStartInstallAndServerCommands() { $this->assertContains('Test site ' . $this->testDb->getDatabasePrefix(), $content); // Try to re-install over the top of an existing site. - $install_command = "{$this->php} core/scripts/drupal install testing --site-name='Test another site {$this->testDb->getDatabasePrefix()}'"; + $install_command = [ + $this->php, + 'core/scripts/drupal', + 'install', + 'testing', + "--site-name='Test another site {$this->testDb->getDatabasePrefix()}'", + ]; $install_process = new Process($install_command, NULL, ['DRUPAL_DEV_SITE_PATH' => $this->testDb->getTestSitePath()]); $install_process->inheritEnvironmentVariables(); $install_process->setTimeout(500); @@ -196,7 +221,13 @@ public function testQuickStartInstallAndServerCommands() { public function testQuickStartCommandProfileValidation() { // Install a site using the standard profile to ensure the one time login // link generation works. - $install_command = "{$this->php} core/scripts/drupal quick-start umami --site-name='Test site {$this->testDb->getDatabasePrefix()}' --suppress-login"; + $install_command = [ + $this->php, + 'core/scripts/drupal', + 'quick-start', + 'umami', + "--site-name='Test site {$this->testDb->getDatabasePrefix()}' --suppress-login", + ]; $process = new Process($install_command, NULL, ['DRUPAL_DEV_SITE_PATH' => $this->testDb->getTestSitePath()]); $process->inheritEnvironmentVariables(); $process->run(); @@ -207,7 +238,12 @@ public function testQuickStartCommandProfileValidation() { * Tests the server command when there is no installation. */ public function testServerWithNoInstall() { - $server_command = "{$this->php} core/scripts/drupal server --suppress-login"; + $server_command = [ + $this->php, + 'core/scripts/drupal', + 'server', + '--suppress-login', + ]; $server_process = new Process($server_command, NULL, ['DRUPAL_DEV_SITE_PATH' => $this->testDb->getTestSitePath()]); $server_process->inheritEnvironmentVariables(); $server_process->run(); diff --git a/web/core/tests/Drupal/Tests/Core/DrupalKernel/ValidateHostnameTest.php b/web/core/tests/Drupal/Tests/Core/DrupalKernel/ValidateHostnameTest.php index 96281bae2adb8ae68f5f50eed80def8b14f64851..2010f49ba4d1d8ebbb950622d120f053fbad23cd 100644 --- a/web/core/tests/Drupal/Tests/Core/DrupalKernel/ValidateHostnameTest.php +++ b/web/core/tests/Drupal/Tests/Core/DrupalKernel/ValidateHostnameTest.php @@ -50,7 +50,7 @@ public function providerTestValidateHostname() { $data[] = ['72.21.91.99:80', 'Properly formed HTTP_HOST with IPv4 address valid.', TRUE]; $data[] = ['2607:f8b0:4004:803::1002:80', 'Properly formed HTTP_HOST with IPv6 address valid.', TRUE]; - // Verfies that the IPv6 loopback address is valid. + // Verifies that the IPv6 loopback address is valid. $data[] = ['[::1]:80', 'HTTP_HOST containing IPv6 loopback is valid.', TRUE]; return $data; diff --git a/web/core/tests/Drupal/Tests/Core/Entity/Sql/SqlContentEntityStorageTest.php b/web/core/tests/Drupal/Tests/Core/Entity/Sql/SqlContentEntityStorageTest.php index 376b55642841d200734899fa5f95bc9b786362b7..3c88db7f9e535b835a84c65689141720b556088f 100644 --- a/web/core/tests/Drupal/Tests/Core/Entity/Sql/SqlContentEntityStorageTest.php +++ b/web/core/tests/Drupal/Tests/Core/Entity/Sql/SqlContentEntityStorageTest.php @@ -383,6 +383,14 @@ public function testOnEntityTypeCreate() { $this->entityType->expects($this->once()) ->method('getKeys') ->will($this->returnValue(['id' => 'id'])); + $this->entityType->expects($this->any()) + ->method('hasKey') + ->will($this->returnValueMap([ + // SqlContentEntityStorageSchema::initializeBaseTable() + ['revision', FALSE], + // SqlContentEntityStorageSchema::processBaseTable() + ['id', TRUE], + ])); $this->entityType->expects($this->any()) ->method('getKey') ->will($this->returnValueMap([ diff --git a/web/core/tests/Drupal/Tests/Core/EventSubscriber/RssResponseRelativeUrlFilterTest.php b/web/core/tests/Drupal/Tests/Core/EventSubscriber/RssResponseRelativeUrlFilterTest.php index d8290fe4753ae48965fbf4d9dcda242276a082af..e9c9549f2b09e345c5faa45819d21625c13db3f1 100644 --- a/web/core/tests/Drupal/Tests/Core/EventSubscriber/RssResponseRelativeUrlFilterTest.php +++ b/web/core/tests/Drupal/Tests/Core/EventSubscriber/RssResponseRelativeUrlFilterTest.php @@ -114,7 +114,7 @@ public function testOnResponse($content, $expected_content) { $event = new FilterResponseEvent( $this->prophesize(HttpKernelInterface::class)->reveal(), Request::create('/'), - 'foo', + HttpKernelInterface::MASTER_REQUEST, new Response($content, 200, [ 'Content-Type' => 'application/rss+xml', ]) diff --git a/web/core/tests/Drupal/Tests/Core/Extension/ThemeHandlerTest.php b/web/core/tests/Drupal/Tests/Core/Extension/ThemeHandlerTest.php index 8c105f25ae8d33e907ed83faa1c2eae682a98e05..f22419f985c046df770f794f1d4a4f683743ae36 100644 --- a/web/core/tests/Drupal/Tests/Core/Extension/ThemeHandlerTest.php +++ b/web/core/tests/Drupal/Tests/Core/Extension/ThemeHandlerTest.php @@ -7,12 +7,10 @@ namespace Drupal\Tests\Core\Extension; -use Drupal\Core\Cache\MemoryBackend; use Drupal\Core\Extension\Extension; use Drupal\Core\Extension\InfoParser; use Drupal\Core\Extension\ThemeHandler; use Drupal\Core\KeyValueStore\KeyValueMemoryFactory; -use Drupal\Core\Lock\NullLockBackend; use Drupal\Core\State\State; use Drupal\Tests\UnitTestCase; @@ -80,7 +78,7 @@ protected function setUp() { ], ]); $this->moduleHandler = $this->getMock('Drupal\Core\Extension\ModuleHandlerInterface'); - $this->state = new State(new KeyValueMemoryFactory(), new MemoryBackend('test'), new NullLockBackend()); + $this->state = new State(new KeyValueMemoryFactory()); $this->infoParser = $this->getMock('Drupal\Core\Extension\InfoParserInterface'); $this->extensionDiscovery = $this->getMockBuilder('Drupal\Core\Extension\ExtensionDiscovery') ->disableOriginalConstructor() diff --git a/web/core/tests/Drupal/Tests/Core/Form/FormStateDecoratorBaseTest.php b/web/core/tests/Drupal/Tests/Core/Form/FormStateDecoratorBaseTest.php index 7335603686eaf2ead1dc14e0b3680a55e4d25220..c677fd39d40c869ed6257877878709dd22b142a7 100644 --- a/web/core/tests/Drupal/Tests/Core/Form/FormStateDecoratorBaseTest.php +++ b/web/core/tests/Drupal/Tests/Core/Form/FormStateDecoratorBaseTest.php @@ -287,7 +287,7 @@ public function testSetLimitValidationErrors($limit_validation_errors) { * @dataProvider providerLimitValidationErrors * * @param array[]|null $limit_validation_errors - * Any valid vlaue for + * Any valid value for * \Drupal\Core\Form\FormStateInterface::getLimitValidationErrors()'s * return value; */ diff --git a/web/core/tests/Drupal/Tests/Core/Layout/LayoutPluginManagerTest.php b/web/core/tests/Drupal/Tests/Core/Layout/LayoutPluginManagerTest.php index 2d898591482370a889896207206c8ab755514b3b..139200cabeabfdb6243164171282cc30c9ebcf4e 100644 --- a/web/core/tests/Drupal/Tests/Core/Layout/LayoutPluginManagerTest.php +++ b/web/core/tests/Drupal/Tests/Core/Layout/LayoutPluginManagerTest.php @@ -12,6 +12,7 @@ use Drupal\Core\Layout\LayoutDefault; use Drupal\Core\Layout\LayoutDefinition; use Drupal\Core\Layout\LayoutPluginManager; +use Drupal\Core\StringTranslation\TranslatableMarkup; use Drupal\Tests\UnitTestCase; use org\bovigo\vfs\vfsStream; use Prophecy\Argument; @@ -114,8 +115,12 @@ public function testGetDefinition() { $theme_a_path = vfsStream::url('root/themes/theme_a'); $layout_definition = $this->layoutPluginManager->getDefinition('theme_a_provided_layout'); $this->assertSame('theme_a_provided_layout', $layout_definition->id()); - $this->assertSame('2 column layout', $layout_definition->getLabel()); - $this->assertSame('Columns: 2', $layout_definition->getCategory()); + $this->assertSame('2 column layout', (string) $layout_definition->getLabel()); + $this->assertSame('Columns: 2', (string) $layout_definition->getCategory()); + $this->assertSame('A theme provided layout', (string) $layout_definition->getDescription()); + $this->assertTrue($layout_definition->getLabel() instanceof TranslatableMarkup); + $this->assertTrue($layout_definition->getCategory() instanceof TranslatableMarkup); + $this->assertTrue($layout_definition->getDescription() instanceof TranslatableMarkup); $this->assertSame('twocol', $layout_definition->getTemplate()); $this->assertSame("$theme_a_path/templates", $layout_definition->getPath()); $this->assertSame('theme_a/twocol', $layout_definition->getLibrary()); @@ -126,19 +131,26 @@ public function testGetDefinition() { $this->assertSame(LayoutDefault::class, $layout_definition->getClass()); $expected_regions = [ 'left' => [ - 'label' => 'Left region', + 'label' => new TranslatableMarkup('Left region', [], ['context' => 'layout_region']), ], 'right' => [ - 'label' => 'Right region', + 'label' => new TranslatableMarkup('Right region', [], ['context' => 'layout_region']), ], ]; - $this->assertSame($expected_regions, $layout_definition->getRegions()); + $regions = $layout_definition->getRegions(); + $this->assertEquals($expected_regions, $regions); + $this->assertTrue($regions['left']['label'] instanceof TranslatableMarkup); + $this->assertTrue($regions['right']['label'] instanceof TranslatableMarkup); $module_a_path = vfsStream::url('root/modules/module_a'); $layout_definition = $this->layoutPluginManager->getDefinition('module_a_provided_layout'); $this->assertSame('module_a_provided_layout', $layout_definition->id()); - $this->assertSame('1 column layout', $layout_definition->getLabel()); - $this->assertSame('Columns: 1', $layout_definition->getCategory()); + $this->assertSame('1 column layout', (string) $layout_definition->getLabel()); + $this->assertSame('Columns: 1', (string) $layout_definition->getCategory()); + $this->assertSame('A module provided layout', (string) $layout_definition->getDescription()); + $this->assertTrue($layout_definition->getLabel() instanceof TranslatableMarkup); + $this->assertTrue($layout_definition->getCategory() instanceof TranslatableMarkup); + $this->assertTrue($layout_definition->getDescription() instanceof TranslatableMarkup); $this->assertSame(NULL, $layout_definition->getTemplate()); $this->assertSame("$module_a_path/layouts", $layout_definition->getPath()); $this->assertSame('module_a/onecol', $layout_definition->getLibrary()); @@ -149,19 +161,26 @@ public function testGetDefinition() { $this->assertSame(LayoutDefault::class, $layout_definition->getClass()); $expected_regions = [ 'top' => [ - 'label' => 'Top region', + 'label' => new TranslatableMarkup('Top region', [], ['context' => 'layout_region']), ], 'bottom' => [ - 'label' => 'Bottom region', + 'label' => new TranslatableMarkup('Bottom region', [], ['context' => 'layout_region']), ], ]; - $this->assertSame($expected_regions, $layout_definition->getRegions()); + $regions = $layout_definition->getRegions(); + $this->assertEquals($expected_regions, $regions); + $this->assertTrue($regions['top']['label'] instanceof TranslatableMarkup); + $this->assertTrue($regions['bottom']['label'] instanceof TranslatableMarkup); $core_path = '/core/lib/Drupal/Core'; $layout_definition = $this->layoutPluginManager->getDefinition('plugin_provided_layout'); $this->assertSame('plugin_provided_layout', $layout_definition->id()); $this->assertEquals('Layout plugin', $layout_definition->getLabel()); $this->assertEquals('Columns: 1', $layout_definition->getCategory()); + $this->assertEquals('Test layout', $layout_definition->getDescription()); + $this->assertTrue($layout_definition->getLabel() instanceof TranslatableMarkup); + $this->assertTrue($layout_definition->getCategory() instanceof TranslatableMarkup); + $this->assertTrue($layout_definition->getDescription() instanceof TranslatableMarkup); $this->assertSame('plugin-provided-layout', $layout_definition->getTemplate()); $this->assertSame($core_path, $layout_definition->getPath()); $this->assertSame(NULL, $layout_definition->getLibrary()); @@ -172,10 +191,12 @@ public function testGetDefinition() { $this->assertSame('Drupal\Core\Plugin\Layout\TestLayout', $layout_definition->getClass()); $expected_regions = [ 'main' => [ - 'label' => 'Main Region', + 'label' => new TranslatableMarkup('Main Region', [], ['context' => 'layout_region']), ], ]; - $this->assertEquals($expected_regions, $layout_definition->getRegions()); + $regions = $layout_definition->getRegions(); + $this->assertEquals($expected_regions, $regions); + $this->assertTrue($regions['main']['label'] instanceof TranslatableMarkup); } /** @@ -284,6 +305,7 @@ protected function setUpFilesystem() { module_a_provided_layout: label: 1 column layout category: 'Columns: 1' + description: 'A module provided layout' theme_hook: onecol path: layouts library: module_a/onecol @@ -301,6 +323,7 @@ protected function setUpFilesystem() { class: '\Drupal\Core\Layout\LayoutDefault' label: 2 column layout category: 'Columns: 2' + description: 'A theme provided layout' template: twocol path: templates library: theme_a/twocol @@ -325,7 +348,7 @@ class: '\Drupal\Core\Layout\LayoutDefault' * template = "templates/plugin-provided-layout", * regions = { * "main" = { - * "label" = @Translation("Main Region") + * "label" = @Translation("Main Region", context = "layout_region") * } * } * ) diff --git a/web/core/tests/Drupal/Tests/Core/Menu/LocalActionManagerTest.php b/web/core/tests/Drupal/Tests/Core/Menu/LocalActionManagerTest.php index 58b453a11b1ce84b5f18d65f9f553b20a5da6e3b..7a1cf86121ff1cdf52ac96fc84f260023f0adec2 100644 --- a/web/core/tests/Drupal/Tests/Core/Menu/LocalActionManagerTest.php +++ b/web/core/tests/Drupal/Tests/Core/Menu/LocalActionManagerTest.php @@ -13,7 +13,9 @@ use Drupal\Core\Access\AccessResult; use Drupal\Core\Access\AccessResultForbidden; use Drupal\Core\Cache\CacheBackendInterface; +use Drupal\Core\Cache\Context\CacheContextsManager; use Drupal\Core\Controller\ControllerResolver; +use Drupal\Core\DependencyInjection\Container; use Drupal\Core\Extension\ModuleHandlerInterface; use Drupal\Core\Language\Language; use Drupal\Core\Menu\LocalActionManager; @@ -23,6 +25,7 @@ use Drupal\Core\Session\AccountInterface; use Drupal\Core\Url; use Drupal\Tests\UnitTestCase; +use Prophecy\Argument; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\RequestStack; use Symfony\Component\HttpKernel\Controller\ArgumentResolverInterface; @@ -113,7 +116,15 @@ protected function setUp() { $this->moduleHandler = $this->getMock('Drupal\Core\Extension\ModuleHandlerInterface'); $this->cacheBackend = $this->getMock('Drupal\Core\Cache\CacheBackendInterface'); - $access_result = new AccessResultForbidden(); + $cache_contexts_manager = $this->prophesize(CacheContextsManager::class); + $cache_contexts_manager->assertValidTokens(Argument::any()) + ->willReturn(TRUE); + + $container = new Container(); + $container->set('cache_contexts_manager', $cache_contexts_manager->reveal()); + \Drupal::setContainer($container); + + $access_result = (new AccessResultForbidden())->cachePerPermissions(); $this->accessManager = $this->getMock('Drupal\Core\Access\AccessManagerInterface'); $this->accessManager->expects($this->any()) ->method('checkNamedRoute') @@ -186,6 +197,14 @@ public function testGetActionsForRoute($route_appears, array $plugin_definitions } public function getActionsForRouteProvider() { + $cache_contexts_manager = $this->prophesize(CacheContextsManager::class); + $cache_contexts_manager->assertValidTokens(Argument::any()) + ->willReturn(TRUE); + + $container = new Container(); + $container->set('cache_contexts_manager', $cache_contexts_manager->reveal()); + \Drupal::setContainer($container); + // Single available and single expected plugins. $data[] = [ 'test_route', @@ -201,7 +220,9 @@ public function getActionsForRouteProvider() { ], [ '#cache' => [ - 'contexts' => ['route'], + 'tags' => [], + 'contexts' => ['route', 'user.permissions'], + 'max-age' => 0, ], 'plugin_id_1' => [ '#theme' => 'menu_local_action', @@ -210,13 +231,8 @@ public function getActionsForRouteProvider() { 'url' => Url::fromRoute('test_route_2'), 'localized_options' => '', ], - '#access' => AccessResult::forbidden(), + '#access' => AccessResult::forbidden()->cachePerPermissions(), '#weight' => 0, - '#cache' => [ - 'contexts' => [], - 'tags' => [], - 'max-age' => 0, - ], ], ], ]; @@ -243,7 +259,9 @@ public function getActionsForRouteProvider() { ], [ '#cache' => [ - 'contexts' => ['route'], + 'tags' => [], + 'contexts' => ['route', 'user.permissions'], + 'max-age' => 0, ], 'plugin_id_1' => [ '#theme' => 'menu_local_action', @@ -252,13 +270,8 @@ public function getActionsForRouteProvider() { 'url' => Url::fromRoute('test_route_2'), 'localized_options' => '', ], - '#access' => AccessResult::forbidden(), + '#access' => AccessResult::forbidden()->cachePerPermissions(), '#weight' => 0, - '#cache' => [ - 'contexts' => [], - 'tags' => [], - 'max-age' => 0, - ], ], ], ]; @@ -286,7 +299,9 @@ public function getActionsForRouteProvider() { ], [ '#cache' => [ - 'contexts' => ['route'], + 'contexts' => ['route', 'user.permissions'], + 'tags' => [], + 'max-age' => 0, ], 'plugin_id_1' => [ '#theme' => 'menu_local_action', @@ -295,13 +310,8 @@ public function getActionsForRouteProvider() { 'url' => Url::fromRoute('test_route_2'), 'localized_options' => '', ], - '#access' => AccessResult::forbidden(), + '#access' => AccessResult::forbidden()->cachePerPermissions(), '#weight' => 1, - '#cache' => [ - 'contexts' => [], - 'tags' => [], - 'max-age' => 0, - ], ], 'plugin_id_2' => [ '#theme' => 'menu_local_action', @@ -310,13 +320,8 @@ public function getActionsForRouteProvider() { 'url' => Url::fromRoute('test_route_3'), 'localized_options' => '', ], - '#access' => AccessResult::forbidden(), + '#access' => AccessResult::forbidden()->cachePerPermissions(), '#weight' => 0, - '#cache' => [ - 'contexts' => [], - 'tags' => [], - 'max-age' => 0, - ], ], ], ]; @@ -346,7 +351,9 @@ public function getActionsForRouteProvider() { ], [ '#cache' => [ - 'contexts' => ['route'], + 'contexts' => ['route', 'user.permissions'], + 'tags' => [], + 'max-age' => 0, ], 'plugin_id_1' => [ '#theme' => 'menu_local_action', @@ -355,13 +362,8 @@ public function getActionsForRouteProvider() { 'url' => Url::fromRoute('test_route_2', ['test1']), 'localized_options' => '', ], - '#access' => AccessResult::forbidden(), + '#access' => AccessResult::forbidden()->cachePerPermissions(), '#weight' => 1, - '#cache' => [ - 'contexts' => [], - 'tags' => [], - 'max-age' => 0, - ], ], 'plugin_id_2' => [ '#theme' => 'menu_local_action', @@ -370,13 +372,8 @@ public function getActionsForRouteProvider() { 'url' => Url::fromRoute('test_route_2', ['test2']), 'localized_options' => '', ], - '#access' => AccessResult::forbidden(), + '#access' => AccessResult::forbidden()->cachePerPermissions(), '#weight' => 0, - '#cache' => [ - 'contexts' => [], - 'tags' => [], - 'max-age' => 0, - ], ], ], ]; diff --git a/web/core/tests/Drupal/Tests/Core/Menu/LocalTaskDefaultTest.php b/web/core/tests/Drupal/Tests/Core/Menu/LocalTaskDefaultTest.php index ea431bf3aa843b3dc0dd99ff8fad8aac4cf5a057..2f59ee1acb8b31b41db2d47356302f1d31a0af9b 100644 --- a/web/core/tests/Drupal/Tests/Core/Menu/LocalTaskDefaultTest.php +++ b/web/core/tests/Drupal/Tests/Core/Menu/LocalTaskDefaultTest.php @@ -162,6 +162,28 @@ public function testGetRouteParametersForDynamicRouteWithUpcastedParameters() { $this->assertEquals(['parameter' => 'example'], $this->localTaskBase->getRouteParameters($route_match)); } + /** + * Tests the getRouteParameters method for a route with upcasted parameters. + * + * @covers ::getRouteParameters + */ + public function testGetRouteParametersForDynamicRouteWithUpcastedParametersEmptyRawParameters() { + $this->pluginDefinition = [ + 'route_name' => 'test_route', + ]; + + $route = new Route('/test-route/{parameter}'); + $this->routeProvider->expects($this->once()) + ->method('getRouteByName') + ->with('test_route') + ->will($this->returnValue($route)); + + $this->setupLocalTaskDefault(); + + $route_match = new RouteMatch('', $route, ['parameter' => (object) 'example2']); + $this->assertEquals(['parameter' => (object) 'example2'], $this->localTaskBase->getRouteParameters($route_match)); + } + /** * Defines a data provider for testGetWeight(). * diff --git a/web/core/tests/Drupal/Tests/Core/Plugin/Context/ContextAwarePluginBaseTest.php b/web/core/tests/Drupal/Tests/Core/Plugin/Context/ContextAwarePluginBaseTest.php new file mode 100644 index 0000000000000000000000000000000000000000..66e54b215759cedbf9aeee45047af39cb59bb232 --- /dev/null +++ b/web/core/tests/Drupal/Tests/Core/Plugin/Context/ContextAwarePluginBaseTest.php @@ -0,0 +1,96 @@ +<?php + +namespace Drupal\Tests\Core\Plugin\Context; + +use Drupal\Component\Plugin\Context\ContextInterface as ComponentContextInterface; +use Drupal\Component\Plugin\Definition\ContextAwarePluginDefinitionInterface; +use Drupal\Component\Plugin\Definition\ContextAwarePluginDefinitionTrait; +use Drupal\Component\Plugin\Definition\PluginDefinition; +use Drupal\Component\Plugin\Exception\ContextException; +use Drupal\Core\DependencyInjection\ContainerBuilder; +use Drupal\Core\Plugin\Context\ContextDefinition; +use Drupal\Core\Plugin\ContextAwarePluginBase; +use Drupal\Core\TypedData\DataDefinition; +use Drupal\Core\TypedData\Plugin\DataType\StringData; +use Drupal\Core\TypedData\TypedDataManagerInterface; +use Drupal\Tests\UnitTestCase; + +/** + * @coversDefaultClass \Drupal\Core\Plugin\ContextAwarePluginBase + * @group Plugin + */ +class ContextAwarePluginBaseTest extends UnitTestCase { + + /** + * The plugin instance under test. + * + * @var \Drupal\Core\Plugin\ContextAwarePluginBase + */ + private $plugin; + + /** + * {@inheritdoc} + */ + public function setUp() { + parent::setUp(); + $this->plugin = new TestContextAwarePlugin([], 'the_sisko', new TestPluginDefinition()); + } + + /** + * @covers ::getContextDefinitions + */ + public function testGetContextDefinitions() { + $this->assertInternalType('array', $this->plugin->getContextDefinitions()); + } + + /** + * @covers ::getContextDefinition + */ + public function testGetContextDefinition() { + // The context is not defined, so an exception will be thrown. + $this->setExpectedException(ContextException::class, 'The person context is not a valid context.'); + $this->plugin->getContextDefinition('person'); + } + + /** + * @covers ::setContextValue + */ + public function testSetContextValue() { + $typed_data_manager = $this->prophesize(TypedDataManagerInterface::class); + $container = new ContainerBuilder(); + $container->set('typed_data_manager', $typed_data_manager->reveal()); + \Drupal::setContainer($container); + + $this->plugin->getPluginDefinition()->addContextDefinition('foo', new ContextDefinition('string')); + + $this->assertFalse($this->plugin->setContextCalled); + $this->plugin->setContextValue('foo', new StringData(new DataDefinition(), 'bar')); + $this->assertTrue($this->plugin->setContextCalled); + } + +} + +class TestPluginDefinition extends PluginDefinition implements ContextAwarePluginDefinitionInterface { + + use ContextAwarePluginDefinitionTrait; + +} + +class TestContextAwarePlugin extends ContextAwarePluginBase { + + /** + * Indicates if ::setContext() has been called or not. + * + * @var bool + */ + public $setContextCalled = FALSE; + + /** + * {@inheritdoc} + */ + public function setContext($name, ComponentContextInterface $context) { + parent::setContext($name, $context); + $this->setContextCalled = TRUE; + } + +} diff --git a/web/core/tests/Drupal/Tests/Core/Plugin/Context/ContextTypedDataTest.php b/web/core/tests/Drupal/Tests/Core/Plugin/Context/ContextTypedDataTest.php deleted file mode 100644 index aac6efc0e3a7c8040edf90c514cc4f517564a2c7..0000000000000000000000000000000000000000 --- a/web/core/tests/Drupal/Tests/Core/Plugin/Context/ContextTypedDataTest.php +++ /dev/null @@ -1,62 +0,0 @@ -<?php - -namespace Drupal\Tests\Core\Plugin\Context; - -use Drupal\Core\DependencyInjection\ContainerBuilder; -use Drupal\Core\Plugin\Context\Context; -use Drupal\Core\Plugin\Context\ContextDefinition; -use Drupal\Core\TypedData\DataDefinition; -use Drupal\Core\TypedData\Plugin\DataType\StringData; -use Drupal\Core\TypedData\TypedDataManagerInterface; -use Drupal\Tests\UnitTestCase; - -/** - * Tests that contexts work properly with the typed data manager. - * - * @coversDefaultClass \Drupal\Core\Plugin\Context\Context - * @group Context - */ -class ContextTypedDataTest extends UnitTestCase { - - /** - * The typed data object used during testing. - * - * @var \Drupal\Core\TypedData\Plugin\DataType\StringData - */ - protected $typedData; - - /** - * Tests that getting a context value does not throw fatal errors. - * - * This test ensures that the typed data manager is set correctly on the - * Context class. - * - * @covers ::getContextValue - */ - public function testGetContextValue() { - // Prepare a container that holds the typed data manager mock. - $typed_data_manager = $this->getMock(TypedDataManagerInterface::class); - $typed_data_manager->expects($this->once()) - ->method('getCanonicalRepresentation') - ->will($this->returnCallback([$this, 'getCanonicalRepresentation'])); - $container = new ContainerBuilder(); - $container->set('typed_data_manager', $typed_data_manager); - \Drupal::setContainer($container); - - $definition = new ContextDefinition('any'); - $data_definition = DataDefinition::create('string'); - $this->typedData = new StringData($data_definition); - $this->typedData->setValue('example string'); - $context = new Context($definition, $this->typedData); - $value = $context->getContextValue(); - $this->assertSame($value, $this->typedData->getValue()); - } - - /** - * Helper mock callback to return the typed data value. - */ - public function getCanonicalRepresentation() { - return $this->typedData->getValue(); - } - -} diff --git a/web/core/tests/Drupal/Tests/Core/Plugin/Context/EntityContextDefinitionDeprecationTest.php b/web/core/tests/Drupal/Tests/Core/Plugin/Context/EntityContextDefinitionDeprecationTest.php index 1a14692fb03731505d40f0a16df57aca501efcd3..a82995e5a164c926d6b2d553d449b69ca0612127 100644 --- a/web/core/tests/Drupal/Tests/Core/Plugin/Context/EntityContextDefinitionDeprecationTest.php +++ b/web/core/tests/Drupal/Tests/Core/Plugin/Context/EntityContextDefinitionDeprecationTest.php @@ -6,17 +6,38 @@ use Drupal\Core\Plugin\Context\Context; use Drupal\Core\Plugin\Context\ContextDefinition; use Drupal\Core\Plugin\Context\EntityContextDefinition; +use Drupal\Core\TypedData\TypedDataManagerInterface; +use Drupal\Core\Validation\ConstraintManager; use Drupal\Tests\UnitTestCase; use Prophecy\Argument; +use Symfony\Component\Validator\Validator\ValidatorInterface; /** + * Test deprecated use of ContextDefinition as an EntityContextDefinition. + * * @coversDefaultClass \Drupal\Core\Plugin\Context\ContextDefinition * * @group Plugin * @group legacy + * + * @see https://www.drupal.org/node/2976400 */ class EntityContextDefinitionDeprecationTest extends UnitTestCase { + /** + * The context definition under test. + * + * @var \Drupal\Core\Plugin\Context\ContextDefinition + */ + protected $definition; + + /** + * The compatibility layer property on the context definition under test. + * + * @var \ReflectionProperty + */ + protected $compatibilityLayer; + /** * {@inheritdoc} */ @@ -24,41 +45,134 @@ protected function setUp() { parent::setUp(); // Mock container services needed for constraint validation. - $constraint_manager = $this->prophesize('\Drupal\Core\Validation\ConstraintManager'); + $constraint_manager = $this->prophesize(ConstraintManager::class); $constraint_manager->create(Argument::type('string'), Argument::any())->willReturn(TRUE); - $typed_data_manager = $this->prophesize('\Drupal\Core\TypedData\TypedDataManagerInterface'); + $typed_data_manager = $this->prophesize(TypedDataManagerInterface::class); $typed_data_manager->getValidationConstraintManager()->willReturn($constraint_manager->reveal()); - $validator = $this->prophesize('\Symfony\Component\Validator\Validator\ValidatorInterface') + $validator = $this->prophesize(ValidatorInterface::class) ->reveal(); $typed_data_manager->getValidator()->willReturn($validator); $container = new ContainerBuilder(); $container->set('typed_data_manager', $typed_data_manager->reveal()); \Drupal::setContainer($container); - } - /** - * @expectedDeprecation Constructing a ContextDefinition object for an entity type is deprecated in Drupal 8.6.0. Use Drupal\Core\Plugin\Context\EntityContextDefinition instead. See https://www.drupal.org/node/2976400 for more information. - */ - public function testDeprecationNotice() { - $definition = new ContextDefinition('entity:node'); + // Create a deprecated entity context definition and prepare the + // compatibility layer to be overridden. + $this->definition = new ContextDefinition('entity:node'); // The code paths we're testing are private and protected, so use reflection // to manipulate protected properties. - $reflector = new \ReflectionObject($definition); + $reflector = new \ReflectionObject($this->definition); // Ensure that the BC object was created correctly. $this->assertTrue($reflector->hasProperty('entityContextDefinition')); - $property = $reflector->getProperty('entityContextDefinition'); - $property->setAccessible(TRUE); - $this->assertInstanceOf(EntityContextDefinition::class, $property->getValue($definition)); + $this->compatibilityLayer = $reflector->getProperty('entityContextDefinition'); + $this->compatibilityLayer->setAccessible(TRUE); + $this->assertInstanceOf(EntityContextDefinition::class, $this->compatibilityLayer->getValue($this->definition)); + } - // Ensure that getConstraintObjects() adds the EntityType constraint. - $method = $reflector->getMethod('getConstraintObjects'); - $method->setAccessible(TRUE); - $this->assertArrayHasKey('EntityType', $method->invoke($definition)); + /** + * Test that the BC layer survives serialization and unserialization. + * + * @expectedDeprecation Constructing a ContextDefinition object for an entity type is deprecated in Drupal 8.6.0. Use Drupal\Core\Plugin\Context\EntityContextDefinition instead. See https://www.drupal.org/node/2976400 for more information. + */ + public function testSerialization() { + $definition = unserialize(serialize($this->definition)); + $bc_layer = $this->compatibilityLayer->getValue($definition); + $this->assertInstanceOf(EntityContextDefinition::class, $bc_layer); + } + + /** + * Test that getConstraints() proxies to the compatibility layer. + * + * @covers ::getConstraints + * @expectedDeprecation Constructing a ContextDefinition object for an entity type is deprecated in Drupal 8.6.0. Use Drupal\Core\Plugin\Context\EntityContextDefinition instead. See https://www.drupal.org/node/2976400 for more information. + */ + public function testGetConstraints() { + $bc_mock = $this->getMockBuilder(EntityContextDefinition::class) + ->setMethods(['getConstraints']) + ->getMock(); + + $constraints = ['test_constraint']; + $bc_mock->expects($this->once()) + ->method('getConstraints') + ->willReturn($constraints); + $this->compatibilityLayer->setValue($this->definition, $bc_mock); + + $this->assertSame($constraints, $this->definition->getConstraints()); + } + + /** + * Test that getConstraint() proxies to the compatibility layer. + * + * @covers ::getConstraint + * @expectedDeprecation Constructing a ContextDefinition object for an entity type is deprecated in Drupal 8.6.0. Use Drupal\Core\Plugin\Context\EntityContextDefinition instead. See https://www.drupal.org/node/2976400 for more information. + */ + public function testGetConstraint() { + $bc_mock = $this->getMockBuilder(EntityContextDefinition::class) + ->setMethods(['getConstraint']) + ->getMock(); + + $bc_mock->expects($this->once()) + ->method('getConstraint') + ->with('constraint_name') + ->willReturn('test_constraint'); + $this->compatibilityLayer->setValue($this->definition, $bc_mock); + + $this->assertSame('test_constraint', $this->definition->getConstraint('constraint_name')); + } + + /** + * Test that setConstraints() proxies to the compatibility layer. + * + * @covers ::setConstraints + * @expectedDeprecation Constructing a ContextDefinition object for an entity type is deprecated in Drupal 8.6.0. Use Drupal\Core\Plugin\Context\EntityContextDefinition instead. See https://www.drupal.org/node/2976400 for more information. + */ + public function testSetConstraints() { + $bc_mock = $this->getMockBuilder(EntityContextDefinition::class) + ->setMethods(['setConstraints']) + ->getMock(); + + $constraints = ['TestConstraint' => []]; + $bc_mock->expects($this->once()) + ->method('setConstraints') + ->with($constraints) + ->willReturnSelf(); + $this->compatibilityLayer->setValue($this->definition, $bc_mock); + + $this->assertSame($this->definition, $this->definition->setConstraints($constraints)); + } + + /** + * Test that addConstraint() proxies to the compatibility layer. + * + * @covers ::addConstraint + * @expectedDeprecation Constructing a ContextDefinition object for an entity type is deprecated in Drupal 8.6.0. Use Drupal\Core\Plugin\Context\EntityContextDefinition instead. See https://www.drupal.org/node/2976400 for more information. + */ + public function testAddConstraint() { + $bc_mock = $this->getMockBuilder(EntityContextDefinition::class) + ->setMethods(['addConstraint']) + ->getMock(); + $options = ['options']; + $bc_mock->expects($this->once()) + ->method('addConstraint') + ->with('constraint_name', $options) + ->willReturnSelf(); + $this->compatibilityLayer->setValue($this->definition, $bc_mock); + + $this->assertSame($this->definition, $this->definition->addConstraint('constraint_name', $options)); + } + + /** + * Test that isSatisfiedBy() calls the compatibility layer. + * + * @covers ::isSatisfiedBy + * @expectedDeprecation Constructing a ContextDefinition object for an entity type is deprecated in Drupal 8.6.0. Use Drupal\Core\Plugin\Context\EntityContextDefinition instead. See https://www.drupal.org/node/2976400 for more information. + */ + public function testIsSatisfiedBy() { // Ensure that the BC object's getSampleValues() method is called during // validation. $bc_mock = $this->getMockBuilder(EntityContextDefinition::class) @@ -68,12 +182,21 @@ public function testDeprecationNotice() { $bc_mock->expects($this->atLeastOnce()) ->method('getSampleValues') ->willReturn([]); - $property->setValue($definition, $bc_mock); - $definition->isSatisfiedBy(new Context($definition)); + $this->compatibilityLayer->setValue($this->definition, $bc_mock); + $this->definition->isSatisfiedBy(new Context($this->definition)); + } - // Ensure that the BC layer survives serialization and unserialization. - $definition = unserialize(serialize($definition)); - $this->assertInstanceOf(EntityContextDefinition::class, $property->getValue($definition)); + /** + * Test that getConstraintObjects() adds the EntityType constraint. + * + * @covers ::getConstraintObjects + * @expectedDeprecation Constructing a ContextDefinition object for an entity type is deprecated in Drupal 8.6.0. Use Drupal\Core\Plugin\Context\EntityContextDefinition instead. See https://www.drupal.org/node/2976400 for more information. + */ + public function testGetConstraintObjects() { + $reflector = new \ReflectionObject($this->definition); + $method = $reflector->getMethod('getConstraintObjects'); + $method->setAccessible(TRUE); + $this->assertArrayHasKey('EntityType', $method->invoke($this->definition)); } } diff --git a/web/core/tests/Drupal/Tests/Core/Render/RendererBubblingTest.php b/web/core/tests/Drupal/Tests/Core/Render/RendererBubblingTest.php index 6ad2acbe0da35dff68fb8ad1de5e91c7dd6f4815..202c9efa71609847ea63ef3fbe8668231901fd86 100644 --- a/web/core/tests/Drupal/Tests/Core/Render/RendererBubblingTest.php +++ b/web/core/tests/Drupal/Tests/Core/Render/RendererBubblingTest.php @@ -9,7 +9,6 @@ use Drupal\Core\Cache\MemoryBackend; use Drupal\Core\KeyValueStore\KeyValueMemoryFactory; -use Drupal\Core\Lock\NullLockBackend; use Drupal\Core\State\State; use Drupal\Core\Cache\Cache; @@ -539,7 +538,7 @@ public function testBubblingWithPrerender($test_element) { $this->setupMemoryCache(); // Mock the State service. - $memory_state = new State(new KeyValueMemoryFactory(), new MemoryBackend('test'), new NullLockBackend()); + $memory_state = new State(new KeyValueMemoryFactory()); \Drupal::getContainer()->set('state', $memory_state); $this->controllerResolver->expects($this->any()) ->method('getControllerFromDefinition') diff --git a/web/core/tests/Drupal/Tests/Core/Routing/RouterTest.php b/web/core/tests/Drupal/Tests/Core/Routing/RouterTest.php new file mode 100644 index 0000000000000000000000000000000000000000..d6ba1d43fb0a4970ec375c302a1921234ad91967 --- /dev/null +++ b/web/core/tests/Drupal/Tests/Core/Routing/RouterTest.php @@ -0,0 +1,60 @@ +<?php + +namespace Drupal\Tests\Core\Routing; + +use Drupal\Core\Path\CurrentPathStack; +use Drupal\Core\Routing\RequestContext; +use Drupal\Core\Routing\RouteCompiler; +use Drupal\Core\Routing\RouteProviderInterface; +use Drupal\Core\Routing\Router; +use Drupal\Core\Routing\UrlGeneratorInterface; +use Drupal\Tests\UnitTestCase; +use Prophecy\Argument; +use Symfony\Component\Routing\Route; +use Symfony\Component\Routing\RouteCollection; + +/** + * @coversDefaultClass \Drupal\Core\Routing\Router + * @group Routing + */ +class RouterTest extends UnitTestCase { + + /** + * @covers ::applyFitOrder + */ + public function testMatchesWithDifferentFitOrder() { + $route_provider = $this->prophesize(RouteProviderInterface::class); + + $route_collection = new RouteCollection(); + + $route = new Route('/user/{user}'); + $route->setOption('compiler_class', RouteCompiler::class); + $route_collection->add('user_view', $route); + + $route = new Route('/user/login'); + $route->setOption('compiler_class', RouteCompiler::class); + $route_collection->add('user_login', $route); + + $route_provider->getRouteCollectionForRequest(Argument::any()) + ->willReturn($route_collection); + + $url_generator = $this->prophesize(UrlGeneratorInterface::class); + $current_path_stack = $this->prophesize(CurrentPathStack::class); + $router = new Router($route_provider->reveal(), $current_path_stack->reveal(), $url_generator->reveal()); + + $request_context = $this->prophesize(RequestContext::class); + $request_context->getScheme()->willReturn('http'); + $router->setContext($request_context->reveal()); + + $current_path_stack->getPath(Argument::any())->willReturn('/user/1'); + $result = $router->match('/user/1'); + + $this->assertEquals('user_view', $result['_route']); + + $current_path_stack->getPath(Argument::any())->willReturn('/user/login'); + $result = $router->match('/user/login'); + + $this->assertEquals('user_login', $result['_route']); + } + +} diff --git a/web/core/tests/Drupal/Tests/Core/Utility/UnroutedUrlAssemblerTest.php b/web/core/tests/Drupal/Tests/Core/Utility/UnroutedUrlAssemblerTest.php index 70b3880f4c1df8c7eebf4d5d3b1a6ddbb48ba34c..0a46582299c8cfdf3c1e4ff7e22bb1a80cc75cb4 100644 --- a/web/core/tests/Drupal/Tests/Core/Utility/UnroutedUrlAssemblerTest.php +++ b/web/core/tests/Drupal/Tests/Core/Utility/UnroutedUrlAssemblerTest.php @@ -97,8 +97,8 @@ public function providerTestAssembleWithExternalUrl() { ['https://example.com/test', ['https' => FALSE], 'http://example.com/test'], ['https://example.com/test?foo=1#bar', [], 'https://example.com/test?foo=1#bar'], 'override-query' => ['https://example.com/test?foo=1#bar', ['query' => ['foo' => 2]], 'https://example.com/test?foo=2#bar'], - 'override-query-merge' => ['https://example.com/test?foo=1#bar', ['query' => ['bar' => 2]], 'https://example.com/test?bar=2&foo=1#bar'], - 'override-deep-query-merge' => ['https://example.com/test?foo=1#bar', ['query' => ['bar' => ['baz' => 'foo']]], 'https://example.com/test?bar%5Bbaz%5D=foo&foo=1#bar'], + 'override-query-merge' => ['https://example.com/test?foo=1#bar', ['query' => ['bar' => 2]], 'https://example.com/test?foo=1&bar=2#bar'], + 'override-deep-query-merge' => ['https://example.com/test?foo=1#bar', ['query' => ['bar' => ['baz' => 'foo']]], 'https://example.com/test?foo=1&bar%5Bbaz%5D=foo#bar'], 'override-fragment' => ['https://example.com/test?foo=1#bar', ['fragment' => 'baz'], 'https://example.com/test?foo=1#baz'], ['//www.drupal.org', [], '//www.drupal.org'], ]; diff --git a/web/core/tests/Drupal/Tests/Listeners/DeprecationListenerTrait.php b/web/core/tests/Drupal/Tests/Listeners/DeprecationListenerTrait.php index db8312a4f19955bd14372b314f43700795269a3c..68380abd8f201fe003ef25d8eb857d5e93a353f6 100644 --- a/web/core/tests/Drupal/Tests/Listeners/DeprecationListenerTrait.php +++ b/web/core/tests/Drupal/Tests/Listeners/DeprecationListenerTrait.php @@ -92,10 +92,18 @@ private function willBeIsolated($test) { /** * A list of deprecations to ignore whilst fixes are put in place. * + * Do not add any new deprecations to this list. All deprecation errors will + * eventually be removed from this list. + * * @return string[] * A list of deprecations to ignore. * * @internal + * + * @todo Fix all these deprecations and remove them from this list. + * https://www.drupal.org/project/drupal/issues/2959269 + * + * @see https://www.drupal.org/node/2811561 */ public static function getSkippedDeprecations() { return [ diff --git a/web/core/tests/Drupal/Tests/UiHelperTrait.php b/web/core/tests/Drupal/Tests/UiHelperTrait.php index cc5a324adf07e4dec292955245ee064777a406b7..d315433ac923965538a7f6ef466b7a9aae1bf824 100644 --- a/web/core/tests/Drupal/Tests/UiHelperTrait.php +++ b/web/core/tests/Drupal/Tests/UiHelperTrait.php @@ -167,27 +167,12 @@ protected function submitForm(array $edit, $submit, $form_html_id = NULL) { * @todo change $edit to disallow NULL as a value for Drupal 9. * https://www.drupal.org/node/2802401 * @param string $submit - * Value of the submit button whose click is to be emulated. For example, - * 'Save'. The processing of the request depends on this value. For example, - * a form may have one button with the value 'Save' and another button with - * the value 'Delete', and execute different code depending on which one is - * clicked. - * - * This function can also be called to emulate an Ajax submission. In this - * case, this value needs to be an array with the following keys: - * - path: A path to submit the form values to for Ajax-specific processing. - * - triggering_element: If the value for the 'path' key is a generic Ajax - * processing path, this needs to be set to the name of the element. If - * the name doesn't identify the element uniquely, then this should - * instead be an array with a single key/value pair, corresponding to the - * element name and value. The \Drupal\Core\Form\FormAjaxResponseBuilder - * uses this to find the #ajax information for the element, including - * which specific callback to use for processing the request. - * - * This can also be set to NULL in order to emulate an Internet Explorer - * submission of a form with a single text field, and pressing ENTER in that - * textfield: under these conditions, no button information is added to the - * POST data. + * The id, name, label or value of the submit button which is to be clicked. + * For example, 'Save'. The first element matched by + * \Drupal\Tests\WebAssert::buttonExists() will be used. The processing of + * the request depends on this value. For example, a form may have one + * button with the value 'Save' and another button with the value 'Delete', + * and execute different code depending on which one is clicked. * @param array $options * Options to be forwarded to the url generator. * @param string|null $form_html_id @@ -202,6 +187,8 @@ protected function submitForm(array $edit, $submit, $form_html_id = NULL) { * (deprecated) The response content after submit form. It is necessary for * backwards compatibility and will be removed before Drupal 9.0. You should * just use the webAssert object for your assertions. + * + * @see \Drupal\Tests\WebAssert::buttonExists() */ protected function drupalPostForm($path, $edit, $submit, array $options = [], $form_html_id = NULL) { if (is_object($submit)) { @@ -371,7 +358,7 @@ protected function drupalGet($path, array $options = [], array $headers = []) { * Options to be passed to Url::fromUri(). * * @return string - * An absolute URL stsring. + * An absolute URL string. */ protected function buildUrl($path, array $options = []) { if ($path instanceof Url) { diff --git a/web/core/tests/Drupal/Tests/WebAssert.php b/web/core/tests/Drupal/Tests/WebAssert.php index e3d06d83549ca2729fe2f3063bb1962f5cadce35..fa7700ecedb67137d3df1ec90bbc214be7f37753 100644 --- a/web/core/tests/Drupal/Tests/WebAssert.php +++ b/web/core/tests/Drupal/Tests/WebAssert.php @@ -3,6 +3,7 @@ namespace Drupal\Tests; use Behat\Mink\Exception\ExpectationException; +use Behat\Mink\Exception\ResponseTextException; use Behat\Mink\WebAssert as MinkWebAssert; use Behat\Mink\Element\TraversableElement; use Behat\Mink\Exception\ElementNotFoundException; @@ -167,7 +168,7 @@ public function optionExists($select, $option, TraversableElement $container = N * @param string $select * One of id|name|label|value for the select field. * @param string $option - * The option value that shoulkd not exist. + * The option value that should not exist. * @param \Behat\Mink\Element\TraversableElement $container * (optional) The document to check against. Defaults to the current page. * @@ -545,4 +546,31 @@ public function hiddenFieldValueNotEquals($field, $value, TraversableElement $co $this->assert(!preg_match($regex, $actual), $message); } + /** + * Checks that current page contains text only once. + * + * @param string $text + * The string to look for. + * + * @see \Behat\Mink\WebAssert::pageTextContains() + */ + public function pageTextContainsOnce($text) { + $actual = $this->session->getPage()->getText(); + $actual = preg_replace('/\s+/u', ' ', $actual); + $regex = '/' . preg_quote($text, '/') . '/ui'; + $count = preg_match_all($regex, $actual); + if ($count === 1) { + return; + } + + if ($count > 1) { + $message = sprintf('The text "%s" appears in the text of this page more than once, but it should not.', $text); + } + else { + $message = sprintf('The text "%s" was not found anywhere in the text of the current page.', $text); + } + + throw new ResponseTextException($message, $this->session->getDriver()); + } + } diff --git a/web/core/tests/README.md b/web/core/tests/README.md index 7672d71e609675a41d182b6430ac9f53f622dd90..0ea2efc9ba4e36186c6a8594aee927d7845896e6 100644 --- a/web/core/tests/README.md +++ b/web/core/tests/README.md @@ -13,6 +13,11 @@ Note: functional tests have to be invoked with a user in the same group as the web server user. You can either configure Apache (or nginx) to run as your own system user or run tests as a privileged user instead. +Invoking tests with a user that is in the same group as the web server will +require you to ensure Drupal keeps gid stickybits when creating new directories. + +`$settings['file_chmod_directory'] = 02775;` + To develop locally, a straightforward - but also less secure - approach is to run tests as your own system user. To achieve that, change the default Apache user to run as your system user. Typically, you'd need to modify diff --git a/web/core/themes/bartik/bartik.theme b/web/core/themes/bartik/bartik.theme index 1c408cf3cc5cb95bee1deb881c68e0b15698b053..76394c16ae22886bdf07ab236467a7cbc5baf131 100644 --- a/web/core/themes/bartik/bartik.theme +++ b/web/core/themes/bartik/bartik.theme @@ -37,7 +37,7 @@ function bartik_preprocess_html(&$variables) { } /** - * Implements hook_preprocess_HOOK() for page templates. + * Implements hook_preprocess_HOOK() for page title templates. */ function bartik_preprocess_page_title(&$variables) { // Since the title and the shortcut link are both block level elements, diff --git a/web/core/themes/bartik/css/components/form.css b/web/core/themes/bartik/css/components/form.css index 03dc6e9b1726f1a2393e6e392be841a66a3dfc3c..e815233fbf08924887d590408911e4c8b09e2d05 100644 --- a/web/core/themes/bartik/css/components/form.css +++ b/web/core/themes/bartik/css/components/form.css @@ -23,7 +23,7 @@ fieldset { * @todo remove once this Mozilla bug is fixed. * See https://bugzilla.mozilla.org/show_bug.cgi?id=504622 */ -@-moz-document url-prefix() { +@media (min--moz-device-pixel-ratio: 0) { fieldset { display: table-cell; } diff --git a/web/core/themes/seven/css/components/form.css b/web/core/themes/seven/css/components/form.css index 44016abefc4ce33c61bfe4e7c15dbd48d16c04a5..68dedf1745fa278f8363d0228e9822a991faf7f4 100644 --- a/web/core/themes/seven/css/components/form.css +++ b/web/core/themes/seven/css/components/form.css @@ -19,7 +19,7 @@ fieldset:not(.fieldgroup) { * @todo remove once this Mozilla bug is fixed. * See https://bugzilla.mozilla.org/show_bug.cgi?id=504622 */ -@-moz-document url-prefix() { +@media (min--moz-device-pixel-ratio: 0) { fieldset:not(.fieldgroup) { display: table-cell; } @@ -41,7 +41,7 @@ fieldset:not(.fieldgroup) > legend { * @todo remove once this Mozilla bug is fixed. * See https://bugzilla.mozilla.org/show_bug.cgi?id=504622 */ -@-moz-document url-prefix() { +@media (min--moz-device-pixel-ratio: 0) { .fieldgroup { display: table-cell; } diff --git a/web/core/themes/seven/css/components/tabs.css b/web/core/themes/seven/css/components/tabs.css index f8b9966471d378feb060d9102cf052d9bf42e605..c8d00073bcaaa706f79decebe5b997630497952a 100644 --- a/web/core/themes/seven/css/components/tabs.css +++ b/web/core/themes/seven/css/components/tabs.css @@ -59,7 +59,7 @@ li.tabs__tab { display: block; padding: 0; } -/* This is required to win over specifity of [dir="rtl"] .tabs__tab */ +/* This is required to win over specificity of [dir="rtl"] .tabs__tab */ [dir="rtl"] li.tabs__tab { padding-left: 0; padding-right: 0; @@ -195,7 +195,7 @@ li.tabs__tab a { } [dir="rtl"] .is-horizontal .tabs__tab { float: right; - /* This is required to win over specifity of [dir="rtl"] .tabs > li */ + /* This is required to win over specificity of [dir="rtl"] .tabs > li */ margin-left: 0; } .is-horizontal .tabs__tab + .tabs__tab { @@ -336,7 +336,7 @@ li.tabs__tab a { padding: 0; } /** - * 1. This is required to win over specifity of + * 1. This is required to win over specificity of * [dir="rtl"] .tabs.secondary .tabs__tab:hover, * [dir="rtl"] .tabs.secondary .tabs__tab:focus */ diff --git a/web/core/themes/seven/css/components/views-ui.css b/web/core/themes/seven/css/components/views-ui.css index 714819ead3e90c9187b0a52944a3c5c61ce7f650..635d89eb6f4d2f662fc79dd0053b9bebad20a838 100644 --- a/web/core/themes/seven/css/components/views-ui.css +++ b/web/core/themes/seven/css/components/views-ui.css @@ -59,7 +59,7 @@ details.fieldset-no-legend { /* @group Dependent options */ -/* This is necessary to supercede the Seven .form-item +/* This is necessary to supersede the Seven .form-item * reset declaration that sets the margin to zero. */ .form-item-options-expose-required, diff --git a/web/sites/default/default.settings.php b/web/sites/default/default.settings.php index 52b6fde7f5e164f83cef8c89379d05150a617b1a..5bcecc267fabae54be86f51e9a3ea6751093e11c 100644 --- a/web/sites/default/default.settings.php +++ b/web/sites/default/default.settings.php @@ -1,5 +1,7 @@ <?php +// @codingStandardsIgnoreFile + /** * @file * Drupal site-specific configuration file. @@ -86,7 +88,7 @@ * ); * @endcode */ - $databases = array(); +$databases = []; /** * Customizing database settings. @@ -144,6 +146,11 @@ * @code * 'prefix' => 'main_', * @endcode + * + * Per-table prefixes are deprecated as of Drupal 8.2, and will be removed in + * Drupal 9.0. After that, only a single prefix for all tables will be + * supported. + * * To provide prefixes for specific tables, set 'prefix' as an array. * The array's keys are the table names and the values are the prefixes. * The 'default' element is mandatory and holds the prefix for any tables @@ -244,7 +251,7 @@ * ); * @endcode */ -$config_directories = array(); +$config_directories = []; /** * Settings: @@ -256,18 +263,6 @@ * @see \Drupal\Core\Site\Settings::get() */ -/** - * The active installation profile. - * - * Changing this after installation is not recommended as it changes which - * directories are scanned during extension discovery. If this is set prior to - * installation this value will be rewritten according to the profile selected - * by the user. - * - * @see install_select_profile() - */ -# $settings['install_profile'] = ''; - /** * Salt for one-time login links, cancel links, form tokens, etc. * @@ -367,7 +362,7 @@ * Specify every reverse proxy IP address in your environment. * This setting is required if $settings['reverse_proxy'] is TRUE. */ -# $settings['reverse_proxy_addresses'] = array('a.b.c.d', ...); +# $settings['reverse_proxy_addresses'] = ['a.b.c.d', ...]; /** * Set this value if your proxy server sends the client IP in a header @@ -430,6 +425,15 @@ */ # $settings['cache_ttl_4xx'] = 3600; +/** + * Expiration of cached forms. + * + * Drupal's Form API stores details of forms in a cache and these entries are + * kept for at least 6 hours by default. Expired entries are cleared by cron. + * + * @see \Drupal\Core\Form\FormCache::setCache() + */ +# $settings['form_cache_expiration'] = 21600; /** * Class Loader. @@ -552,10 +556,10 @@ * The "en" part of the variable name, is dynamic and can be any langcode of * any added language. (eg locale_custom_strings_de for german). */ -# $settings['locale_custom_strings_en'][''] = array( +# $settings['locale_custom_strings_en'][''] = [ # 'forum' => 'Discussion board', # '@count min' => '@count minutes', -# ); +# ]; /** * A custom theme for the offline page: @@ -609,7 +613,7 @@ * override in a services.yml file in the same directory as settings.php * (definitions in this file will override service definition defaults). */ -# $settings['bootstrap_config_storage'] = array('Drupal\Core\Config\BootstrapConfigStorageFactory', 'getFileStorage'); +# $settings['bootstrap_config_storage'] = ['Drupal\Core\Config\BootstrapConfigStorageFactory', 'getFileStorage']; /** * Configuration overrides. @@ -633,6 +637,7 @@ * configuration values in settings.php will not fire any of the configuration * change events. */ +# $config['system.file']['path']['temporary'] = '/tmp'; # $config['system.site']['name'] = 'My Drupal site'; # $config['system.theme']['default'] = 'stark'; # $config['user.settings']['anonymous'] = 'Visitor'; @@ -740,17 +745,14 @@ ]; /** - * Include the Pantheon-specific settings file. + * The default number of entities to update in a batch process. * - * n.b. The settings.pantheon.php file makes some changes - * that affect all envrionments that this site - * exists in. Always include this file, even in - * a local development environment, to insure that - * the site settings remain consistent. + * This is used by update and post-update functions that need to go through and + * change all the entities on a site, so it is useful to increase this number + * if your hosting configuration (i.e. RAM allocation, CPU speed) allows for a + * larger number of entities to be processed in a single batch run. */ -if (file_exists(__DIR__ . '/settings.pantheon.php')) { - include __DIR__ . "/settings.pantheon.php"; -} +$settings['entity_update_batch_size'] = 50; /** * Load local development override configuration, if available.