diff --git a/composer.json b/composer.json index a7bd8b57..94aebbe2 100644 --- a/composer.json +++ b/composer.json @@ -16,12 +16,19 @@ ], "require": { "composer/installers": "^1.9", + "drupal/audiofield": "^1.11", "drupal/bootstrap5": "^1.1", + "drupal/colorbox": "^1.7", "drupal/core-composer-scaffold": "^9.2", "drupal/core-project-message": "^9.2", "drupal/core-recommended": "^9.2", + "drupal/devel": "^4.1", + "drupal/linked_field": "^1.3", "drupal/pathauto": "^1.8", + "drupal/redis": "^1.5", + "drupal/responsive_menu": "^4.4", "drupal/views_slideshow": "^4.8", + "drupal/weight": "^3.3", "drush/drush": "^10.6" }, "conflict": { diff --git a/composer.lock b/composer.lock index 0e49f78e..3297bc94 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "661833152524e5f153d57b4704c9cb47", + "content-hash": "da05672b0cf32193fc2e544fe9b59f48", "packages": [ { "name": "asm89/stack-cors", @@ -56,6 +56,10 @@ "cors", "stack" ], + "support": { + "issues": "https://github.com/asm89/stack-cors/issues", + "source": "https://github.com/asm89/stack-cors/tree/1.3.0" + }, "time": "2019-12-24T22:41:47+00:00" }, { @@ -241,6 +245,10 @@ "zend", "zikula" ], + "support": { + "issues": "https://github.com/composer/installers/issues", + "source": "https://github.com/composer/installers/tree/v1.12.0" + }, "funding": [ { "url": "https://packagist.com", @@ -317,6 +325,11 @@ "validation", "versioning" ], + "support": { + "irc": "irc://irc.freenode.org/composer", + "issues": "https://github.com/composer/semver/issues", + "source": "https://github.com/composer/semver/tree/3.2.5" + }, "funding": [ { "url": "https://packagist.com", @@ -1053,8 +1066,471 @@ "docblock", "parser" ], + "support": { + "issues": "https://github.com/doctrine/annotations/issues", + "source": "https://github.com/doctrine/annotations/tree/1.13.1" + }, "time": "2021-05-16T18:07:53+00:00" }, + { + "name": "doctrine/cache", + "version": "1.12.1", + "source": { + "type": "git", + "url": "https://github.com/doctrine/cache.git", + "reference": "4cf401d14df219fa6f38b671f5493449151c9ad8" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/doctrine/cache/zipball/4cf401d14df219fa6f38b671f5493449151c9ad8", + "reference": "4cf401d14df219fa6f38b671f5493449151c9ad8", + "shasum": "" + }, + "require": { + "php": "~7.1 || ^8.0" + }, + "conflict": { + "doctrine/common": ">2.2,<2.4" + }, + "require-dev": { + "alcaeus/mongo-php-adapter": "^1.1", + "cache/integration-tests": "dev-master", + "doctrine/coding-standard": "^8.0", + "mongodb/mongodb": "^1.1", + "phpunit/phpunit": "^7.0 || ^8.0 || ^9.0", + "predis/predis": "~1.0", + "psr/cache": "^1.0 || ^2.0 || ^3.0", + "symfony/cache": "^4.4 || ^5.2 || ^6.0@dev", + "symfony/var-exporter": "^4.4 || ^5.2 || ^6.0@dev" + }, + "suggest": { + "alcaeus/mongo-php-adapter": "Required to use legacy MongoDB driver" + }, + "type": "library", + "autoload": { + "psr-4": { + "Doctrine\\Common\\Cache\\": "lib/Doctrine/Common/Cache" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Guilherme Blanco", + "email": "guilhermeblanco@gmail.com" + }, + { + "name": "Roman Borschel", + "email": "roman@code-factory.org" + }, + { + "name": "Benjamin Eberlei", + "email": "kontakt@beberlei.de" + }, + { + "name": "Jonathan Wage", + "email": "jonwage@gmail.com" + }, + { + "name": "Johannes Schmitt", + "email": "schmittjoh@gmail.com" + } + ], + "description": "PHP Doctrine Cache library is a popular cache implementation that supports many different drivers such as redis, memcache, apc, mongodb and others.", + "homepage": "https://www.doctrine-project.org/projects/cache.html", + "keywords": [ + "abstraction", + "apcu", + "cache", + "caching", + "couchdb", + "memcached", + "php", + "redis", + "xcache" + ], + "support": { + "issues": "https://github.com/doctrine/cache/issues", + "source": "https://github.com/doctrine/cache/tree/1.12.1" + }, + "funding": [ + { + "url": "https://www.doctrine-project.org/sponsorship.html", + "type": "custom" + }, + { + "url": "https://www.patreon.com/phpdoctrine", + "type": "patreon" + }, + { + "url": "https://tidelift.com/funding/github/packagist/doctrine%2Fcache", + "type": "tidelift" + } + ], + "time": "2021-07-17T14:39:21+00:00" + }, + { + "name": "doctrine/collections", + "version": "1.6.8", + "source": { + "type": "git", + "url": "https://github.com/doctrine/collections.git", + "reference": "1958a744696c6bb3bb0d28db2611dc11610e78af" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/doctrine/collections/zipball/1958a744696c6bb3bb0d28db2611dc11610e78af", + "reference": "1958a744696c6bb3bb0d28db2611dc11610e78af", + "shasum": "" + }, + "require": { + "php": "^7.1.3 || ^8.0" + }, + "require-dev": { + "doctrine/coding-standard": "^9.0", + "phpstan/phpstan": "^0.12", + "phpunit/phpunit": "^7.5 || ^8.5 || ^9.1.5", + "vimeo/psalm": "^4.2.1" + }, + "type": "library", + "autoload": { + "psr-4": { + "Doctrine\\Common\\Collections\\": "lib/Doctrine/Common/Collections" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Guilherme Blanco", + "email": "guilhermeblanco@gmail.com" + }, + { + "name": "Roman Borschel", + "email": "roman@code-factory.org" + }, + { + "name": "Benjamin Eberlei", + "email": "kontakt@beberlei.de" + }, + { + "name": "Jonathan Wage", + "email": "jonwage@gmail.com" + }, + { + "name": "Johannes Schmitt", + "email": "schmittjoh@gmail.com" + } + ], + "description": "PHP Doctrine Collections library that adds additional functionality on top of PHP arrays.", + "homepage": "https://www.doctrine-project.org/projects/collections.html", + "keywords": [ + "array", + "collections", + "iterators", + "php" + ], + "support": { + "issues": "https://github.com/doctrine/collections/issues", + "source": "https://github.com/doctrine/collections/tree/1.6.8" + }, + "time": "2021-08-10T18:51:53+00:00" + }, + { + "name": "doctrine/common", + "version": "2.13.3", + "source": { + "type": "git", + "url": "https://github.com/doctrine/common.git", + "reference": "f3812c026e557892c34ef37f6ab808a6b567da7f" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/doctrine/common/zipball/f3812c026e557892c34ef37f6ab808a6b567da7f", + "reference": "f3812c026e557892c34ef37f6ab808a6b567da7f", + "shasum": "" + }, + "require": { + "doctrine/annotations": "^1.0", + "doctrine/cache": "^1.0", + "doctrine/collections": "^1.0", + "doctrine/event-manager": "^1.0", + "doctrine/inflector": "^1.0", + "doctrine/lexer": "^1.0", + "doctrine/persistence": "^1.3.3", + "doctrine/reflection": "^1.0", + "php": "^7.1 || ^8.0" + }, + "require-dev": { + "doctrine/coding-standard": "^1.0", + "phpstan/phpstan": "^0.11", + "phpstan/phpstan-phpunit": "^0.11", + "phpunit/phpunit": "^7.0", + "squizlabs/php_codesniffer": "^3.0", + "symfony/phpunit-bridge": "^4.0.5" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.11.x-dev" + } + }, + "autoload": { + "psr-4": { + "Doctrine\\Common\\": "lib/Doctrine/Common" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Guilherme Blanco", + "email": "guilhermeblanco@gmail.com" + }, + { + "name": "Roman Borschel", + "email": "roman@code-factory.org" + }, + { + "name": "Benjamin Eberlei", + "email": "kontakt@beberlei.de" + }, + { + "name": "Jonathan Wage", + "email": "jonwage@gmail.com" + }, + { + "name": "Johannes Schmitt", + "email": "schmittjoh@gmail.com" + }, + { + "name": "Marco Pivetta", + "email": "ocramius@gmail.com" + } + ], + "description": "PHP Doctrine Common project is a library that provides additional functionality that other Doctrine projects depend on such as better reflection support, persistence interfaces, proxies, event system and much more.", + "homepage": "https://www.doctrine-project.org/projects/common.html", + "keywords": [ + "common", + "doctrine", + "php" + ], + "support": { + "issues": "https://github.com/doctrine/common/issues", + "source": "https://github.com/doctrine/common/tree/2.13.x" + }, + "funding": [ + { + "url": "https://www.doctrine-project.org/sponsorship.html", + "type": "custom" + }, + { + "url": "https://www.patreon.com/phpdoctrine", + "type": "patreon" + }, + { + "url": "https://tidelift.com/funding/github/packagist/doctrine%2Fcommon", + "type": "tidelift" + } + ], + "time": "2020-06-05T16:46:05+00:00" + }, + { + "name": "doctrine/event-manager", + "version": "1.1.1", + "source": { + "type": "git", + "url": "https://github.com/doctrine/event-manager.git", + "reference": "41370af6a30faa9dc0368c4a6814d596e81aba7f" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/doctrine/event-manager/zipball/41370af6a30faa9dc0368c4a6814d596e81aba7f", + "reference": "41370af6a30faa9dc0368c4a6814d596e81aba7f", + "shasum": "" + }, + "require": { + "php": "^7.1 || ^8.0" + }, + "conflict": { + "doctrine/common": "<2.9@dev" + }, + "require-dev": { + "doctrine/coding-standard": "^6.0", + "phpunit/phpunit": "^7.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Doctrine\\Common\\": "lib/Doctrine/Common" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Guilherme Blanco", + "email": "guilhermeblanco@gmail.com" + }, + { + "name": "Roman Borschel", + "email": "roman@code-factory.org" + }, + { + "name": "Benjamin Eberlei", + "email": "kontakt@beberlei.de" + }, + { + "name": "Jonathan Wage", + "email": "jonwage@gmail.com" + }, + { + "name": "Johannes Schmitt", + "email": "schmittjoh@gmail.com" + }, + { + "name": "Marco Pivetta", + "email": "ocramius@gmail.com" + } + ], + "description": "The Doctrine Event Manager is a simple PHP event system that was built to be used with the various Doctrine projects.", + "homepage": "https://www.doctrine-project.org/projects/event-manager.html", + "keywords": [ + "event", + "event dispatcher", + "event manager", + "event system", + "events" + ], + "support": { + "issues": "https://github.com/doctrine/event-manager/issues", + "source": "https://github.com/doctrine/event-manager/tree/1.1.x" + }, + "funding": [ + { + "url": "https://www.doctrine-project.org/sponsorship.html", + "type": "custom" + }, + { + "url": "https://www.patreon.com/phpdoctrine", + "type": "patreon" + }, + { + "url": "https://tidelift.com/funding/github/packagist/doctrine%2Fevent-manager", + "type": "tidelift" + } + ], + "time": "2020-05-29T18:28:51+00:00" + }, + { + "name": "doctrine/inflector", + "version": "1.4.4", + "source": { + "type": "git", + "url": "https://github.com/doctrine/inflector.git", + "reference": "4bd5c1cdfcd00e9e2d8c484f79150f67e5d355d9" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/doctrine/inflector/zipball/4bd5c1cdfcd00e9e2d8c484f79150f67e5d355d9", + "reference": "4bd5c1cdfcd00e9e2d8c484f79150f67e5d355d9", + "shasum": "" + }, + "require": { + "php": "^7.1 || ^8.0" + }, + "require-dev": { + "doctrine/coding-standard": "^8.0", + "phpstan/phpstan": "^0.12", + "phpstan/phpstan-phpunit": "^0.12", + "phpstan/phpstan-strict-rules": "^0.12", + "phpunit/phpunit": "^7.0 || ^8.0 || ^9.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Doctrine\\Common\\Inflector\\": "lib/Doctrine/Common/Inflector", + "Doctrine\\Inflector\\": "lib/Doctrine/Inflector" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Guilherme Blanco", + "email": "guilhermeblanco@gmail.com" + }, + { + "name": "Roman Borschel", + "email": "roman@code-factory.org" + }, + { + "name": "Benjamin Eberlei", + "email": "kontakt@beberlei.de" + }, + { + "name": "Jonathan Wage", + "email": "jonwage@gmail.com" + }, + { + "name": "Johannes Schmitt", + "email": "schmittjoh@gmail.com" + } + ], + "description": "PHP Doctrine Inflector is a small library that can perform string manipulations with regard to upper/lowercase and singular/plural forms of words.", + "homepage": "https://www.doctrine-project.org/projects/inflector.html", + "keywords": [ + "inflection", + "inflector", + "lowercase", + "manipulation", + "php", + "plural", + "singular", + "strings", + "uppercase", + "words" + ], + "support": { + "issues": "https://github.com/doctrine/inflector/issues", + "source": "https://github.com/doctrine/inflector/tree/1.4.4" + }, + "funding": [ + { + "url": "https://www.doctrine-project.org/sponsorship.html", + "type": "custom" + }, + { + "url": "https://www.patreon.com/phpdoctrine", + "type": "patreon" + }, + { + "url": "https://tidelift.com/funding/github/packagist/doctrine%2Finflector", + "type": "tidelift" + } + ], + "time": "2021-04-16T17:34:40+00:00" + }, { "name": "doctrine/lexer", "version": "1.2.1", @@ -1115,6 +1591,10 @@ "parser", "php" ], + "support": { + "issues": "https://github.com/doctrine/lexer/issues", + "source": "https://github.com/doctrine/lexer/tree/1.2.1" + }, "funding": [ { "url": "https://www.doctrine-project.org/sponsorship.html", @@ -1131,6 +1611,108 @@ ], "time": "2020-05-25T17:44:05+00:00" }, + { + "name": "doctrine/persistence", + "version": "1.3.8", + "source": { + "type": "git", + "url": "https://github.com/doctrine/persistence.git", + "reference": "7a6eac9fb6f61bba91328f15aa7547f4806ca288" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/doctrine/persistence/zipball/7a6eac9fb6f61bba91328f15aa7547f4806ca288", + "reference": "7a6eac9fb6f61bba91328f15aa7547f4806ca288", + "shasum": "" + }, + "require": { + "doctrine/annotations": "^1.0", + "doctrine/cache": "^1.0", + "doctrine/collections": "^1.0", + "doctrine/event-manager": "^1.0", + "doctrine/reflection": "^1.2", + "php": "^7.1 || ^8.0" + }, + "conflict": { + "doctrine/common": "<2.10@dev" + }, + "require-dev": { + "doctrine/coding-standard": "^6.0", + "phpstan/phpstan": "^0.11", + "phpunit/phpunit": "^7.0 || ^8.0 || ^9.0", + "vimeo/psalm": "^3.11" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.3.x-dev" + } + }, + "autoload": { + "psr-4": { + "Doctrine\\Common\\": "lib/Doctrine/Common", + "Doctrine\\Persistence\\": "lib/Doctrine/Persistence" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Guilherme Blanco", + "email": "guilhermeblanco@gmail.com" + }, + { + "name": "Roman Borschel", + "email": "roman@code-factory.org" + }, + { + "name": "Benjamin Eberlei", + "email": "kontakt@beberlei.de" + }, + { + "name": "Jonathan Wage", + "email": "jonwage@gmail.com" + }, + { + "name": "Johannes Schmitt", + "email": "schmittjoh@gmail.com" + }, + { + "name": "Marco Pivetta", + "email": "ocramius@gmail.com" + } + ], + "description": "The Doctrine Persistence project is a set of shared interfaces and functionality that the different Doctrine object mappers share.", + "homepage": "https://doctrine-project.org/projects/persistence.html", + "keywords": [ + "mapper", + "object", + "odm", + "orm", + "persistence" + ], + "support": { + "issues": "https://github.com/doctrine/persistence/issues", + "source": "https://github.com/doctrine/persistence/tree/1.3.x" + }, + "funding": [ + { + "url": "https://www.doctrine-project.org/sponsorship.html", + "type": "custom" + }, + { + "url": "https://www.patreon.com/phpdoctrine", + "type": "patreon" + }, + { + "url": "https://tidelift.com/funding/github/packagist/doctrine%2Fpersistence", + "type": "tidelift" + } + ], + "time": "2020-06-20T12:56:16+00:00" + }, { "name": "doctrine/reflection", "version": "1.2.2", @@ -1207,22 +1789,85 @@ "reflection", "static" ], + "support": { + "issues": "https://github.com/doctrine/reflection/issues", + "source": "https://github.com/doctrine/reflection/tree/1.2.2" + }, "abandoned": "roave/better-reflection", "time": "2020-10-27T21:46:55+00:00" }, { - "name": "drupal/bootstrap5", - "version": "1.1.0", + "name": "drupal/audiofield", + "version": "1.11.0", "source": { "type": "git", - "url": "https://git.drupalcode.org/project/bootstrap5.git", - "reference": "1.1.0" + "url": "https://git.drupalcode.org/project/audiofield.git", + "reference": "8.x-1.11" }, "dist": { "type": "zip", - "url": "https://ftp.drupal.org/files/projects/bootstrap5-1.1.0.zip", - "reference": "1.1.0", - "shasum": "5318f82ecaa2c189cda9eb2361b1a9bf21c52136" + "url": "https://ftp.drupal.org/files/projects/audiofield-8.x-1.11.zip", + "reference": "8.x-1.11", + "shasum": "b677d0b178f16baffec8b52bb0c05a06384daf67" + }, + "require": { + "drupal/core": "^8 || ^9" + }, + "type": "drupal-module", + "extra": { + "drupal": { + "version": "8.x-1.11", + "datestamp": "1630089337", + "security-coverage": { + "status": "covered", + "message": "Covered by Drupal's security advisory policy" + } + }, + "drush": { + "services": { + "drush.services.yml": "^9" + } + } + }, + "notification-url": "https://packages.drupal.org/8/downloads", + "license": [ + "GPL-2.0-or-later" + ], + "authors": [ + { + "name": "Daniel Moberly", + "homepage": "https://www.drupal.org/u/danielmoberly", + "role": "Maintainer" + }, + { + "name": "josipsaric", + "homepage": "https://www.drupal.org/user/3063287" + }, + { + "name": "tamerzg", + "homepage": "https://www.drupal.org/user/464564" + } + ], + "description": "AudioField Module", + "homepage": "https://www.drupal.org/project/audiofield", + "support": { + "source": "https://git.drupalcode.org/project/audiofield", + "issues": "https://www.drupal.org/project/issues/audiofield" + } + }, + { + "name": "drupal/bootstrap5", + "version": "1.1.2", + "source": { + "type": "git", + "url": "https://git.drupalcode.org/project/bootstrap5.git", + "reference": "1.1.2" + }, + "dist": { + "type": "zip", + "url": "https://ftp.drupal.org/files/projects/bootstrap5-1.1.2.zip", + "reference": "1.1.2", + "shasum": "c784d2294b5861d2f85de4d91a6d8b568701def5" }, "require": { "drupal/core": "^8.9 || ^9" @@ -1230,8 +1875,8 @@ "type": "drupal-theme", "extra": { "drupal": { - "version": "1.1.0", - "datestamp": "1633526861", + "version": "1.1.2", + "datestamp": "1637075148", "security-coverage": { "status": "covered", "message": "Covered by Drupal's security advisory policy" @@ -1257,17 +1902,88 @@ } }, { - "name": "drupal/core", - "version": "9.2.7", + "name": "drupal/colorbox", + "version": "1.7.0", "source": { "type": "git", - "url": "https://github.com/drupal/core.git", - "reference": "ce3220458c7a744bb00e9436e48d8e644e134576" + "url": "https://git.drupalcode.org/project/colorbox.git", + "reference": "8.x-1.7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/drupal/core/zipball/ce3220458c7a744bb00e9436e48d8e644e134576", - "reference": "ce3220458c7a744bb00e9436e48d8e644e134576", + "url": "https://ftp.drupal.org/files/projects/colorbox-8.x-1.7.zip", + "reference": "8.x-1.7", + "shasum": "64c7290be86fe1d3bf80dcf4003a37b3698bba50" + }, + "require": { + "drupal/core": "^8.8 || ^9" + }, + "suggest": { + "jackmoore/colorbox": "The Colorbox library is required to use the drupal/colorbox module." + }, + "type": "drupal-module", + "extra": { + "drupal": { + "version": "8.x-1.7", + "datestamp": "1615218004", + "security-coverage": { + "status": "covered", + "message": "Covered by Drupal's security advisory policy" + } + }, + "drush": { + "services": { + "drush.services.yml": "^9" + } + } + }, + "notification-url": "https://packages.drupal.org/8/downloads", + "license": [ + "GPL-2.0-or-later" + ], + "authors": [ + { + "name": "Neslee Canil Pinto", + "homepage": "https://www.drupal.org/u/neslee-canil-pinto", + "role": "Maintainer" + }, + { + "name": "Fredrik Jonsson", + "homepage": "https://www.drupal.org/u/frjo", + "role": "Maintainer" + }, + { + "name": "Sam152", + "homepage": "https://www.drupal.org/user/1485048" + }, + { + "name": "frjo", + "homepage": "https://www.drupal.org/user/5546" + }, + { + "name": "jdwfly", + "homepage": "https://www.drupal.org/user/298179" + } + ], + "description": "A light-weight, customizable lightbox plugin for jQuery.", + "homepage": "https://www.drupal.org/project/colorbox", + "support": { + "source": "https://git.drupalcode.org/project/colorbox", + "issues": "https://www.drupal.org/project/issues/colorbox" + } + }, + { + "name": "drupal/core", + "version": "9.2.10", + "source": { + "type": "git", + "url": "https://github.com/drupal/core.git", + "reference": "61248f85f78c02e7e0afde2b8a5113d3914bb50f" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/drupal/core/zipball/61248f85f78c02e7e0afde2b8a5113d3914bb50f", + "reference": "61248f85f78c02e7e0afde2b8a5113d3914bb50f", "shasum": "" }, "require": { @@ -1500,22 +2216,19 @@ "includes/bootstrap.inc" ] }, - "scripts": { - "pre-autoload-dump": [ - "Drupal\\Core\\Composer\\Composer::preAutoloadDump" - ], - "post-autoload-dump": [ - "Drupal\\Core\\Composer\\Composer::ensureHtaccess" - ] - }, + "notification-url": "https://packagist.org/downloads/", "license": [ "GPL-2.0-or-later" ], - "description": "Drupal is an open source content management platform powering millions of websites and applications." + "description": "Drupal is an open source content management platform powering millions of websites and applications.", + "support": { + "source": "https://github.com/drupal/core/tree/9.2.10" + }, + "time": "2021-11-24T14:27:27+00:00" }, { "name": "drupal/core-composer-scaffold", - "version": "9.2.7", + "version": "9.2.10", "source": { "type": "git", "url": "https://github.com/drupal/core-composer-scaffold.git", @@ -1549,6 +2262,7 @@ "Drupal\\Composer\\Plugin\\Scaffold\\": "" } }, + "notification-url": "https://packagist.org/downloads/", "license": [ "GPL-2.0-or-later" ], @@ -1556,11 +2270,15 @@ "homepage": "https://www.drupal.org/project/drupal", "keywords": [ "drupal" - ] + ], + "support": { + "source": "https://github.com/drupal/core-composer-scaffold/tree/9.2.10" + }, + "time": "2021-08-24T12:04:07+00:00" }, { "name": "drupal/core-project-message", - "version": "9.2.7", + "version": "9.2.10", "source": { "type": "git", "url": "https://github.com/drupal/core-project-message.git", @@ -1585,6 +2303,7 @@ "Drupal\\Composer\\Plugin\\ProjectMessage\\": "." } }, + "notification-url": "https://packagist.org/downloads/", "license": [ "GPL-2.0-or-later" ], @@ -1592,20 +2311,24 @@ "homepage": "https://www.drupal.org/project/drupal", "keywords": [ "drupal" - ] + ], + "support": { + "source": "https://github.com/drupal/core-project-message/tree/9.3.0-beta3" + }, + "time": "2020-09-14T13:40:36+00:00" }, { "name": "drupal/core-recommended", - "version": "9.2.7", + "version": "9.2.10", "source": { "type": "git", "url": "https://github.com/drupal/core-recommended.git", - "reference": "87c998e8d60d6b2452b21827fb7b16f77d02a38a" + "reference": "9beef737bbfd1db4f84ab3c19e5e7ae0b534383b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/drupal/core-recommended/zipball/87c998e8d60d6b2452b21827fb7b16f77d02a38a", - "reference": "87c998e8d60d6b2452b21827fb7b16f77d02a38a", + "url": "https://api.github.com/repos/drupal/core-recommended/zipball/9beef737bbfd1db4f84ab3c19e5e7ae0b534383b", + "reference": "9beef737bbfd1db4f84ab3c19e5e7ae0b534383b", "shasum": "" }, "require": { @@ -1614,7 +2337,7 @@ "doctrine/annotations": "1.13.1", "doctrine/lexer": "1.2.1", "doctrine/reflection": "1.2.2", - "drupal/core": "9.2.7", + "drupal/core": "9.2.10", "egulias/email-validator": "2.1.25", "guzzlehttp/guzzle": "6.5.5", "guzzlehttp/promises": "1.4.1", @@ -1657,7 +2380,7 @@ "symfony/process": "v4.4.25", "symfony/psr-http-message-bridge": "v2.1.0", "symfony/routing": "v4.4.25", - "symfony/serializer": "v4.4.25", + "symfony/serializer": "v4.4.35", "symfony/service-contracts": "v2.4.0", "symfony/translation": "v4.4.25", "symfony/translation-contracts": "v2.4.0", @@ -1671,10 +2394,15 @@ "webflo/drupal-core-strict": "*" }, "type": "metapackage", + "notification-url": "https://packagist.org/downloads/", "license": [ "GPL-2.0-or-later" ], - "description": "Locked core dependencies; require this project INSTEAD OF drupal/core." + "description": "Locked core dependencies; require this project INSTEAD OF drupal/core.", + "support": { + "source": "https://github.com/drupal/core-recommended/tree/9.2.10" + }, + "time": "2021-11-24T14:27:27+00:00" }, { "name": "drupal/ctools", @@ -1769,6 +2497,120 @@ "issues": "https://www.drupal.org/project/issues/ctools" } }, + { + "name": "drupal/devel", + "version": "4.1.1", + "source": { + "type": "git", + "url": "https://git.drupalcode.org/project/devel.git", + "reference": "4.1.1" + }, + "dist": { + "type": "zip", + "url": "https://ftp.drupal.org/files/projects/devel-4.1.1.zip", + "reference": "4.1.1", + "shasum": "88e5d49dda26a3136291ecd97bc6c8e897b24198" + }, + "require": { + "doctrine/common": "^2.7", + "drupal/core": "^8.8 || ^9", + "symfony/var-dumper": "^4 || ^5" + }, + "conflict": { + "kint-php/kint": "<3" + }, + "require-dev": { + "drush/drush": "^10" + }, + "suggest": { + "kint-php/kint": "Kint provides an informative display of arrays/objects. Useful for debugging and developing." + }, + "type": "drupal-module", + "extra": { + "drupal": { + "version": "4.1.1", + "datestamp": "1631968537", + "security-coverage": { + "status": "covered", + "message": "Covered by Drupal's security advisory policy" + } + }, + "drush": { + "services": { + "drush.services.yml": "^9 || ^10" + } + } + }, + "notification-url": "https://packages.drupal.org/8/downloads", + "license": [ + "GPL-2.0-or-later" + ], + "authors": [ + { + "name": "drupalspoons", + "homepage": "https://www.drupal.org/user/3647684" + }, + { + "name": "moshe weitzman", + "homepage": "https://www.drupal.org/user/23" + } + ], + "description": "Various blocks, pages, and functions for developers.", + "homepage": "https://www.drupal.org/project/devel", + "support": { + "source": "https://gitlab.com/drupalspoons/devel", + "issues": "https://gitlab.com/drupalspoons/devel/-/issues", + "slack": "https://drupal.slack.com/archives/C012WAW1MH6" + } + }, + { + "name": "drupal/linked_field", + "version": "1.3.0", + "source": { + "type": "git", + "url": "https://git.drupalcode.org/project/linked_field.git", + "reference": "8.x-1.3" + }, + "dist": { + "type": "zip", + "url": "https://ftp.drupal.org/files/projects/linked_field-8.x-1.3.zip", + "reference": "8.x-1.3", + "shasum": "0350c415eba6ff63d9fc8f3a162564dd4c2142e2" + }, + "require": { + "drupal/core": "^8 || ^9" + }, + "type": "drupal-module", + "extra": { + "drupal": { + "version": "8.x-1.3", + "datestamp": "1583855735", + "security-coverage": { + "status": "covered", + "message": "Covered by Drupal's security advisory policy" + } + } + }, + "notification-url": "https://packages.drupal.org/8/downloads", + "license": [ + "GPL-2.0-or-later" + ], + "authors": [ + { + "name": "hubdrop", + "homepage": "https://www.drupal.org/user/2750597" + }, + { + "name": "yannickoo", + "homepage": "https://www.drupal.org/user/531118" + } + ], + "description": "Adds the functionality to link fields to a specific destination.", + "homepage": "https://www.drupal.org/project/linked_field", + "support": { + "source": "https://git.drupalcode.org/project/linked_field" + } + }, { "name": "drupal/pathauto", "version": "1.8.0", @@ -1837,6 +2679,108 @@ "documentation": "https://www.drupal.org/docs/8/modules/pathauto" } }, + { + "name": "drupal/redis", + "version": "1.5.0", + "source": { + "type": "git", + "url": "https://git.drupalcode.org/project/redis.git", + "reference": "8.x-1.5" + }, + "dist": { + "type": "zip", + "url": "https://ftp.drupal.org/files/projects/redis-8.x-1.5.zip", + "reference": "8.x-1.5", + "shasum": "4283333dc2bf405045765b83ca662acc409a6543" + }, + "require": { + "drupal/core": "^8.8 || ^9" + }, + "suggest": { + "predis/predis": "^1.1.1" + }, + "type": "drupal-module", + "extra": { + "drupal": { + "version": "8.x-1.5", + "datestamp": "1609972488", + "security-coverage": { + "status": "covered", + "message": "Covered by Drupal's security advisory policy" + } + } + }, + "autoload": { + "psr-4": { + "Drupal\\redis\\": "src" + } + }, + "notification-url": "https://packages.drupal.org/8/downloads", + "license": [ + "GPL-2.0-or-later" + ], + "authors": [ + { + "name": "Berdir", + "homepage": "https://www.drupal.org/user/214652" + }, + { + "name": "pounard", + "homepage": "https://www.drupal.org/user/240164" + } + ], + "description": "Integration of Drupal with the Redis key-value store.", + "homepage": "https://www.drupal.org/project/redis", + "support": { + "source": "https://git.drupalcode.org/project/redis" + } + }, + { + "name": "drupal/responsive_menu", + "version": "4.4.2", + "source": { + "type": "git", + "url": "https://git.drupalcode.org/project/responsive_menu.git", + "reference": "4.4.2" + }, + "dist": { + "type": "zip", + "url": "https://ftp.drupal.org/files/projects/responsive_menu-4.4.2.zip", + "reference": "4.4.2", + "shasum": "26d13cc0fa3bbaf4a4a83f0012095e01cbcc5272" + }, + "require": { + "drupal/core": "^8 || ^9" + }, + "type": "drupal-module", + "extra": { + "drupal": { + "version": "4.4.2", + "datestamp": "1633530566", + "security-coverage": { + "status": "covered", + "message": "Covered by Drupal's security advisory policy" + } + } + }, + "notification-url": "https://packages.drupal.org/8/downloads", + "license": [ + "GPL-2.0+" + ], + "authors": [ + { + "name": "Tancredi D'Onofrio (tanc)", + "homepage": "https://www.drupal.org/u/tanc", + "role": "Maintainer" + } + ], + "description": "Provides a javascript based off-canvas responsive menu with depth. At wider browser widths it provides a horizontal menu capable of drop downs and flyouts", + "homepage": "https://drupal.org/project/responsive_menu", + "support": { + "source": "https://cgit.drupalcode.org/responsive_menu", + "issues": "https://drupal.org/project/issues/responsive_menu" + } + }, { "name": "drupal/token", "version": "1.9.0", @@ -1969,6 +2913,82 @@ "irc": "irc://irc.freenode.org/drupal-contribute" } }, + { + "name": "drupal/weight", + "version": "3.3.0", + "source": { + "type": "git", + "url": "https://git.drupalcode.org/project/weight.git", + "reference": "8.x-3.3" + }, + "dist": { + "type": "zip", + "url": "https://ftp.drupal.org/files/projects/weight-8.x-3.3.zip", + "reference": "8.x-3.3", + "shasum": "b225d54d4a8ce409ca1a899c6de41806eb1348e3" + }, + "require": { + "drupal/core": "^8 || ^9" + }, + "type": "drupal-module", + "extra": { + "drupal": { + "version": "8.x-3.3", + "datestamp": "1615219112", + "security-coverage": { + "status": "covered", + "message": "Covered by Drupal's security advisory policy" + } + } + }, + "notification-url": "https://packages.drupal.org/8/downloads", + "license": [ + "GPL-2.0-or-later" + ], + "authors": [ + { + "name": "Harry Slaughter", + "homepage": "https://www.drupal.org/user/28233" + }, + { + "name": "NancyDru", + "homepage": "https://www.drupal.org/user/101412" + }, + { + "name": "Neslee Canil Pinto", + "homepage": "https://www.drupal.org/user/3580850" + }, + { + "name": "Shreya Shetty", + "homepage": "https://www.drupal.org/user/2943029" + }, + { + "name": "davisben", + "homepage": "https://www.drupal.org/user/1204214" + }, + { + "name": "deviantintegral", + "homepage": "https://www.drupal.org/user/71291" + }, + { + "name": "jjeff", + "homepage": "https://www.drupal.org/user/17190" + }, + { + "name": "kevinquillen", + "homepage": "https://www.drupal.org/user/317279" + }, + { + "name": "ziomizar", + "homepage": "https://www.drupal.org/user/814348" + } + ], + "description": "Allows arbitrary ordering of entities.", + "homepage": "https://www.drupal.org/project/weight", + "support": { + "source": "https://git.drupalcode.org/project/weight" + } + }, { "name": "drush/drush", "version": "10.6.1", @@ -2170,6 +3190,10 @@ "validation", "validator" ], + "support": { + "issues": "https://github.com/egulias/EmailValidator/issues", + "source": "https://github.com/egulias/EmailValidator/tree/2.1.25" + }, "funding": [ { "url": "https://github.com/egulias", @@ -2412,6 +3436,10 @@ "rest", "web service" ], + "support": { + "issues": "https://github.com/guzzle/guzzle/issues", + "source": "https://github.com/guzzle/guzzle/tree/6.5" + }, "time": "2020-06-16T21:01:06+00:00" }, { @@ -2463,6 +3491,10 @@ "keywords": [ "promise" ], + "support": { + "issues": "https://github.com/guzzle/promises/issues", + "source": "https://github.com/guzzle/promises/tree/1.4.1" + }, "time": "2021-03-07T09:25:29+00:00" }, { @@ -2534,6 +3566,10 @@ "uri", "url" ], + "support": { + "issues": "https://github.com/guzzle/psr7/issues", + "source": "https://github.com/guzzle/psr7/tree/1.8.2" + }, "time": "2021-04-26T09:17:50+00:00" }, { @@ -2622,6 +3658,14 @@ "psr-17", "psr-7" ], + "support": { + "chat": "https://laminas.dev/chat", + "docs": "https://docs.laminas.dev/laminas-diactoros/", + "forum": "https://discourse.laminas.dev", + "issues": "https://github.com/laminas/laminas-diactoros/issues", + "rss": "https://github.com/laminas/laminas-diactoros/releases.atom", + "source": "https://github.com/laminas/laminas-diactoros" + }, "funding": [ { "url": "https://funding.communitybridge.org/projects/laminas-project", @@ -2677,6 +3721,14 @@ "escaper", "laminas" ], + "support": { + "chat": "https://laminas.dev/chat", + "docs": "https://docs.laminas.dev/laminas-escaper/", + "forum": "https://discourse.laminas.dev", + "issues": "https://github.com/laminas/laminas-escaper/issues", + "rss": "https://github.com/laminas/laminas-escaper/releases.atom", + "source": "https://github.com/laminas/laminas-escaper" + }, "funding": [ { "url": "https://funding.communitybridge.org/projects/laminas-project", @@ -2749,6 +3801,14 @@ "feed", "laminas" ], + "support": { + "chat": "https://laminas.dev/chat", + "docs": "https://docs.laminas.dev/laminas-feed/", + "forum": "https://discourse.laminas.dev", + "issues": "https://github.com/laminas/laminas-feed/issues", + "rss": "https://github.com/laminas/laminas-feed/releases.atom", + "source": "https://github.com/laminas/laminas-feed" + }, "funding": [ { "url": "https://funding.communitybridge.org/projects/laminas-project", @@ -2799,6 +3859,14 @@ "laminas", "stdlib" ], + "support": { + "chat": "https://laminas.dev/chat", + "docs": "https://docs.laminas.dev/laminas-stdlib/", + "forum": "https://discourse.laminas.dev", + "issues": "https://github.com/laminas/laminas-stdlib/issues", + "rss": "https://github.com/laminas/laminas-stdlib/releases.atom", + "source": "https://github.com/laminas/laminas-stdlib" + }, "funding": [ { "url": "https://funding.communitybridge.org/projects/laminas-project", @@ -2855,6 +3923,12 @@ "laminas", "zf" ], + "support": { + "forum": "https://discourse.laminas.dev/", + "issues": "https://github.com/laminas/laminas-zendframework-bridge/issues", + "rss": "https://github.com/laminas/laminas-zendframework-bridge/releases.atom", + "source": "https://github.com/laminas/laminas-zendframework-bridge" + }, "funding": [ { "url": "https://funding.communitybridge.org/projects/laminas-project", @@ -3005,20 +4079,24 @@ "serializer", "xml" ], + "support": { + "issues": "https://github.com/Masterminds/html5-php/issues", + "source": "https://github.com/Masterminds/html5-php/tree/2.7.4" + }, "time": "2020-10-01T13:52:52+00:00" }, { "name": "nikic/php-parser", - "version": "v4.13.0", + "version": "v4.13.1", "source": { "type": "git", "url": "https://github.com/nikic/PHP-Parser.git", - "reference": "50953a2691a922aa1769461637869a0a2faa3f53" + "reference": "63a79e8daa781cac14e5195e63ed8ae231dd10fd" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/50953a2691a922aa1769461637869a0a2faa3f53", - "reference": "50953a2691a922aa1769461637869a0a2faa3f53", + "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/63a79e8daa781cac14e5195e63ed8ae231dd10fd", + "reference": "63a79e8daa781cac14e5195e63ed8ae231dd10fd", "shasum": "" }, "require": { @@ -3059,9 +4137,9 @@ ], "support": { "issues": "https://github.com/nikic/PHP-Parser/issues", - "source": "https://github.com/nikic/PHP-Parser/tree/v4.13.0" + "source": "https://github.com/nikic/PHP-Parser/tree/v4.13.1" }, - "time": "2021-09-20T12:20:58+00:00" + "time": "2021-11-03T20:52:16+00:00" }, { "name": "pear/archive_tar", @@ -3127,6 +4205,10 @@ "archive", "tar" ], + "support": { + "issues": "http://pear.php.net/bugs/search.php?cmd=display&package_name[]=Archive_Tar", + "source": "https://github.com/pear/Archive_Tar" + }, "funding": [ { "url": "https://github.com/mrook", @@ -3184,6 +4266,10 @@ } ], "description": "More info available on: http://pear.php.net/package/Console_Getopt", + "support": { + "issues": "http://pear.php.net/bugs/search.php?cmd=display&package_name[]=Console_Getopt", + "source": "https://github.com/pear/Console_Getopt" + }, "time": "2019-11-20T18:27:48+00:00" }, { @@ -3228,6 +4314,10 @@ } ], "description": "Minimal set of PEAR core files to be used as composer dependency", + "support": { + "issues": "http://pear.php.net/bugs/search.php?cmd=display&package_name[]=PEAR", + "source": "https://github.com/pear/pear-core-minimal" + }, "time": "2019-11-19T19:00:24+00:00" }, { @@ -3283,6 +4373,10 @@ "keywords": [ "exception" ], + "support": { + "issues": "http://pear.php.net/bugs/search.php?cmd=display&package_name[]=PEAR_Exception", + "source": "https://github.com/pear/PEAR_Exception" + }, "time": "2021-03-21T15:43:46+00:00" }, { @@ -3329,6 +4423,9 @@ "psr", "psr-6" ], + "support": { + "source": "https://github.com/php-fig/cache/tree/master" + }, "time": "2016-08-06T20:24:11+00:00" }, { @@ -3373,6 +4470,10 @@ "container-interop", "psr" ], + "support": { + "issues": "https://github.com/php-fig/container/issues", + "source": "https://github.com/php-fig/container/tree/1.1.1" + }, "time": "2021-03-05T17:36:06+00:00" }, { @@ -3425,6 +4526,9 @@ "request", "response" ], + "support": { + "source": "https://github.com/php-fig/http-factory/tree/master" + }, "time": "2019-04-30T12:38:16+00:00" }, { @@ -3475,6 +4579,9 @@ "request", "response" ], + "support": { + "source": "https://github.com/php-fig/http-message/tree/master" + }, "time": "2016-08-06T14:39:51+00:00" }, { @@ -3522,20 +4629,23 @@ "psr", "psr-3" ], + "support": { + "source": "https://github.com/php-fig/log/tree/1.1.4" + }, "time": "2021-05-03T11:20:27+00:00" }, { "name": "psy/psysh", - "version": "v0.10.9", + "version": "v0.10.11", "source": { "type": "git", "url": "https://github.com/bobthecow/psysh.git", - "reference": "01281336c4ae557fe4a994544f30d3a1bc204375" + "reference": "38017532bba35d15d28dcc001b4274df0251c4a1" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/bobthecow/psysh/zipball/01281336c4ae557fe4a994544f30d3a1bc204375", - "reference": "01281336c4ae557fe4a994544f30d3a1bc204375", + "url": "https://api.github.com/repos/bobthecow/psysh/zipball/38017532bba35d15d28dcc001b4274df0251c4a1", + "reference": "38017532bba35d15d28dcc001b4274df0251c4a1", "shasum": "" }, "require": { @@ -3595,9 +4705,9 @@ ], "support": { "issues": "https://github.com/bobthecow/psysh/issues", - "source": "https://github.com/bobthecow/psysh/tree/v0.10.9" + "source": "https://github.com/bobthecow/psysh/tree/v0.10.11" }, - "time": "2021-10-10T13:37:39+00:00" + "time": "2021-11-23T15:02:17+00:00" }, { "name": "ralouphie/getallheaders", @@ -3637,6 +4747,10 @@ } ], "description": "A polyfill for getallheaders.", + "support": { + "issues": "https://github.com/ralouphie/getallheaders/issues", + "source": "https://github.com/ralouphie/getallheaders/tree/develop" + }, "time": "2019-03-08T08:55:37+00:00" }, { @@ -3687,6 +4801,10 @@ "keywords": [ "stack" ], + "support": { + "issues": "https://github.com/stackphp/builder/issues", + "source": "https://github.com/stackphp/builder/tree/v1.0.6" + }, "time": "2020-01-30T12:17:27+00:00" }, { @@ -3746,6 +4864,10 @@ "database", "routing" ], + "support": { + "issues": "https://github.com/symfony-cmf/Routing/issues", + "source": "https://github.com/symfony-cmf/Routing/tree/2.3.3" + }, "time": "2020-10-06T10:15:37+00:00" }, { @@ -3818,6 +4940,9 @@ ], "description": "Eases the creation of beautiful and testable command line interfaces", "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/console/tree/v4.4.25" + }, "funding": [ { "url": "https://symfony.com/sponsor", @@ -3884,6 +5009,9 @@ ], "description": "Provides tools to ease debugging PHP code", "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/debug/tree/v4.4.25" + }, "funding": [ { "url": "https://symfony.com/sponsor", @@ -3966,6 +5094,9 @@ ], "description": "Allows you to standardize and centralize the way objects are constructed in your application", "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/dependency-injection/tree/v4.4.25" + }, "funding": [ { "url": "https://symfony.com/sponsor", @@ -4030,6 +5161,9 @@ ], "description": "A generic function and convention to trigger deprecation notices", "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/deprecation-contracts/tree/v2.4.0" + }, "funding": [ { "url": "https://symfony.com/sponsor", @@ -4096,6 +5230,9 @@ ], "description": "Provides tools to manage errors and ease debugging PHP code", "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/error-handler/tree/v4.4.25" + }, "funding": [ { "url": "https://symfony.com/sponsor", @@ -4176,6 +5313,9 @@ ], "description": "Provides tools that allow your application components to communicate with each other by dispatching events and listening to them", "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/event-dispatcher/tree/v4.4.25" + }, "funding": [ { "url": "https://symfony.com/sponsor", @@ -4252,6 +5392,9 @@ "interoperability", "standards" ], + "support": { + "source": "https://github.com/symfony/event-dispatcher-contracts/tree/v1.1.9" + }, "funding": [ { "url": "https://symfony.com/sponsor", @@ -4452,6 +5595,9 @@ "interoperability", "standards" ], + "support": { + "source": "https://github.com/symfony/http-client-contracts/tree/v2.4.0" + }, "funding": [ { "url": "https://symfony.com/sponsor", @@ -4517,6 +5663,9 @@ ], "description": "Defines an object-oriented layer for the HTTP specification", "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/http-foundation/tree/v4.4.25" + }, "funding": [ { "url": "https://symfony.com/sponsor", @@ -4618,6 +5767,9 @@ ], "description": "Provides a structured process for converting a Request into a Response", "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/http-kernel/tree/v4.4.25" + }, "funding": [ { "url": "https://symfony.com/sponsor", @@ -4698,6 +5850,9 @@ "mime", "mime-type" ], + "support": { + "source": "https://github.com/symfony/mime/tree/v5.3.0" + }, "funding": [ { "url": "https://symfony.com/sponsor", @@ -4774,6 +5929,9 @@ "polyfill", "portable" ], + "support": { + "source": "https://github.com/symfony/polyfill-ctype/tree/v1.23.0" + }, "funding": [ { "url": "https://symfony.com/sponsor", @@ -4851,6 +6009,9 @@ "portable", "shim" ], + "support": { + "source": "https://github.com/symfony/polyfill-iconv/tree/v1.23.0" + }, "funding": [ { "url": "https://symfony.com/sponsor", @@ -4935,6 +6096,9 @@ "portable", "shim" ], + "support": { + "source": "https://github.com/symfony/polyfill-intl-idn/tree/v1.23.0" + }, "funding": [ { "url": "https://symfony.com/sponsor", @@ -5016,6 +6180,9 @@ "portable", "shim" ], + "support": { + "source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.23.0" + }, "funding": [ { "url": "https://symfony.com/sponsor", @@ -5093,6 +6260,9 @@ "portable", "shim" ], + "support": { + "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.23.0" + }, "funding": [ { "url": "https://symfony.com/sponsor", @@ -5166,6 +6336,9 @@ "portable", "shim" ], + "support": { + "source": "https://github.com/symfony/polyfill-php72/tree/v1.23.0" + }, "funding": [ { "url": "https://symfony.com/sponsor", @@ -5242,6 +6415,9 @@ "portable", "shim" ], + "support": { + "source": "https://github.com/symfony/polyfill-php73/tree/v1.23.0" + }, "funding": [ { "url": "https://symfony.com/sponsor", @@ -5322,6 +6498,9 @@ "portable", "shim" ], + "support": { + "source": "https://github.com/symfony/polyfill-php80/tree/v1.23.0" + }, "funding": [ { "url": "https://symfony.com/sponsor", @@ -5380,6 +6559,9 @@ ], "description": "Executes commands in sub-processes", "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/process/tree/v4.4.25" + }, "funding": [ { "url": "https://symfony.com/sponsor", @@ -5464,6 +6646,10 @@ "psr-17", "psr-7" ], + "support": { + "issues": "https://github.com/symfony/psr-http-message-bridge/issues", + "source": "https://github.com/symfony/psr-http-message-bridge/tree/v2.1.0" + }, "funding": [ { "url": "https://symfony.com/sponsor", @@ -5549,6 +6735,9 @@ "uri", "url" ], + "support": { + "source": "https://github.com/symfony/routing/tree/v4.4.25" + }, "funding": [ { "url": "https://symfony.com/sponsor", @@ -5567,21 +6756,22 @@ }, { "name": "symfony/serializer", - "version": "v4.4.25", + "version": "v4.4.35", "source": { "type": "git", "url": "https://github.com/symfony/serializer.git", - "reference": "6db3eb4f1bb437cd3730f52353ba4b568acaddf5" + "reference": "1b2ae02cb1b923987947e013688c51954a80b751" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/serializer/zipball/6db3eb4f1bb437cd3730f52353ba4b568acaddf5", - "reference": "6db3eb4f1bb437cd3730f52353ba4b568acaddf5", + "url": "https://api.github.com/repos/symfony/serializer/zipball/1b2ae02cb1b923987947e013688c51954a80b751", + "reference": "1b2ae02cb1b923987947e013688c51954a80b751", "shasum": "" }, "require": { "php": ">=7.1.3", - "symfony/polyfill-ctype": "~1.8" + "symfony/polyfill-ctype": "~1.8", + "symfony/polyfill-php80": "^1.16" }, "conflict": { "phpdocumentor/reflection-docblock": "<3.0|>=3.2.0,<3.2.2", @@ -5639,6 +6829,9 @@ ], "description": "Handles serializing and deserializing data structures, including object graphs, into array structures or other formats like XML and JSON.", "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/serializer/tree/v4.4.35" + }, "funding": [ { "url": "https://symfony.com/sponsor", @@ -5653,7 +6846,7 @@ "type": "tidelift" } ], - "time": "2021-05-26T11:20:16+00:00" + "time": "2021-11-24T08:12:42+00:00" }, { "name": "symfony/service-contracts", @@ -5715,6 +6908,9 @@ "interoperability", "standards" ], + "support": { + "source": "https://github.com/symfony/service-contracts/tree/v2.4.0" + }, "funding": [ { "url": "https://symfony.com/sponsor", @@ -5800,6 +6996,9 @@ ], "description": "Provides tools to internationalize your application", "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/translation/tree/v4.4.25" + }, "funding": [ { "url": "https://symfony.com/sponsor", @@ -5875,6 +7074,9 @@ "interoperability", "standards" ], + "support": { + "source": "https://github.com/symfony/translation-contracts/tree/v2.4.0" + }, "funding": [ { "url": "https://symfony.com/sponsor", @@ -5977,6 +7179,9 @@ ], "description": "Provides tools to validate values", "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/validator/tree/v4.4.25" + }, "funding": [ { "url": "https://symfony.com/sponsor", @@ -6062,6 +7267,9 @@ "debug", "dump" ], + "support": { + "source": "https://github.com/symfony/var-dumper/tree/v5.3.0" + }, "funding": [ { "url": "https://symfony.com/sponsor", @@ -6130,6 +7338,9 @@ ], "description": "Loads and dumps YAML files", "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/yaml/tree/v4.4.25" + }, "funding": [ { "url": "https://symfony.com/sponsor", @@ -6209,6 +7420,10 @@ "keywords": [ "templating" ], + "support": { + "issues": "https://github.com/twigphp/Twig/issues", + "source": "https://github.com/twigphp/Twig/tree/v2.14.6" + }, "funding": [ { "url": "https://github.com/fabpot", @@ -6270,6 +7485,10 @@ "security", "stream-wrapper" ], + "support": { + "issues": "https://github.com/TYPO3/phar-stream-wrapper/issues", + "source": "https://github.com/TYPO3/phar-stream-wrapper/tree/v3.1.6" + }, "time": "2020-11-07T09:06:16+00:00" }, { @@ -6422,6 +7641,7 @@ "issues": "https://github.com/webmozart/path-util/issues", "source": "https://github.com/webmozart/path-util/tree/2.3.0" }, + "abandoned": "symfony/filesystem", "time": "2015-12-17T08:42:14+00:00" } ], diff --git a/web/core/assets/vendor/ckeditor/CHANGES.md b/web/core/assets/vendor/ckeditor/CHANGES.md index 9a9f7b49..74ebc5b3 100644 --- a/web/core/assets/vendor/ckeditor/CHANGES.md +++ b/web/core/assets/vendor/ckeditor/CHANGES.md @@ -1,6 +1,78 @@ CKEditor 4 Changelog ==================== +## CKEditor 4.17.1 + +Fixed issues: + +* [#4979](https://github.com/ckeditor/ckeditor4/issues/3757): Added cache key in [#4761](https://github.com/ckeditor/ckeditor4/issues/4761) started to breaking relative links for external CSS resources. The fix had been reverted and will be corrected in the upcoming release. + +## CKEditor 4.17 + +**Security Updates:** + +* Fixed XSS vulnerability in the core module reported by [William Bowling](https://github.com/wbowling). + + Issue summary: The vulnerability allowed to inject malformed comments HTML bypassing content sanitization, which could result in executing JavaScript code. See [security advisory](https://github.com/ckeditor/ckeditor4/security/advisories/GHSA-7h26-63m7-qhf2) for more details. + +* Fixed XSS vulnerability in the core module reported by [Maurice Dauer](https://twitter.com/laytonctf). + + Issue summary: The vulnerability allowed to inject malformed HTML bypassing content sanitization, which could result in executing JavaScript code. See [security advisory](https://github.com/ckeditor/ckeditor4/security/advisories/GHSA-pvmx-g8h5-cprj) for more details. + +You can read more details in the relevant security advisory and [contact us](security@cksource.com) if you have more questions. + +**An upgrade is highly recommended!** + +**Highlights:** + +Adobe [ended support of Flash Player](https://www.adobe.com/products/flashplayer/end-of-life.html) on December 31, 2020 and blocked Flash content from running in Flash Player beginning January 12, 2021. +We have decided to deprecate and remove the [Flash](https://ckeditor.com/cke4/addon/flash) plugin from CKEditor 4 to help protect users' systems and discourage using insecure software. + +New Features: + +* [#3433](https://github.com/ckeditor/ckeditor4/issues/3433): Marked required fields in dialogs with asterisk (`*`) symbol. +* [#4374](https://github.com/ckeditor/ckeditor4/issues/4374): Integrated the [Maximize](https://ckeditor.com/cke4/addon/maximize) plugin with browser's History API. +* [#4461](https://github.com/ckeditor/ckeditor4/issues/4461): Introduced the possibility to delay editor initialization while it is in a detached DOM element. +* [#4462](https://github.com/ckeditor/ckeditor4/issues/4462): Introduced support for reattaching editor container element to DOM. +* [#4612](https://github.com/ckeditor/ckeditor4/issues/4612): Allow pasting images as Base64 from [clipboard](https://ckeditor.com/cke4/addon/clipboard) in all browsers except IE. +* [#4681](https://github.com/ckeditor/ckeditor4/issues/4681): Allow drag and drop images as Base64. +* [#4750](https://github.com/ckeditor/ckeditor4/issues/4750): Added notification for pasting and dropping unsupported file types into the editor. +* [#4807](https://github.com/ckeditor/ckeditor4/issues/4807): [Chrome] Improved the performance of pasting large images. Thanks to [FlowIT-JIT](https://github.com/FlowIT-JIT)! +* [#4850](https://github.com/ckeditor/ckeditor4/issues/4850): Added support for loading [content templates](https://ckeditor.com/cke4/addon/templates) from HTML files. Thanks to [Fynn96](https://github.com/Fynn96)! +* [#4874](https://github.com/ckeditor/ckeditor4/issues/4874): Added the [`config.clipboard_handleImages`](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_config.html#cfg-clipboard_handleImages) configuration option for enabling and disabling built-in support for pasting and dropping images in the [Clipboard](https://ckeditor.com/cke4/addon/clipboard) plugin. Thanks to [FlowIT-JIT](https://github.com/FlowIT-JIT)! +* [#4026](https://github.com/ckeditor/ckeditor4/issues/4026): [Preview](https://ckeditor.com/cke4/addon/preview) plugin now uses the [`editor#title`](http://localhost/ckeditor4-docs/build/docs/ckeditor4/latest/api/CKEDITOR_editor.html#property-title) property for the title of the preview window. Thanks to [Ely](https://github.com/Elyasin)! +* [#4467](https://github.com/ckeditor/ckeditor4/issues/4467): Added support for inserting content next to a block [widgets](https://ckeditor.com/cke4/addon/widget) using keyboard navigation. Thanks to [bunglegrind](https://github.com/bunglegrind)! + +Fixed Issues: + +* [#3757](https://github.com/ckeditor/ckeditor4/issues/3757): [Firefox] Fixed: images pasted from [clipboard](https://ckeditor.com/cke4/addon/clipboard) are not inserted as Base64-encoded images. +* [#3876](https://github.com/ckeditor/ckeditor4/issues/3876): Fixed: The [Print](https://ckeditor.com/cke4/addon/print) plugin incorrectly prints links and images. +* [#4444](https://github.com/ckeditor/ckeditor4/issues/4444): [Firefox] Fixed: Print preview is incorrectly loaded from CDN. +* [#4596](https://github.com/ckeditor/ckeditor4/issues/4596): Fixed: Incorrect handling of HSL/HSLA values in [`CKEDITOR.tools.color`](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_tools_color.html). +* [#4597](https://github.com/ckeditor/ckeditor4/issues/4597): Fixed: Incorrect color conversion for HSL/HSLA values in [`CKEDITOR.tools.color`](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_tools_color.html). +* [#4604](https://github.com/ckeditor/ckeditor4/issues/4604): Fixed: [`CKEDITOR.plugins.clipboard.dataTransfer#getTypes()`](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_plugins_clipboard_dataTransfer.html#method-getTypes) returns no types. +* [#4761](https://github.com/ckeditor/ckeditor4/issues/4761): Fixed: Not all resources loaded by the editor respect the cache key. +* [#4783](https://github.com/ckeditor/ckeditor4/issues/4783): Fixed: The [Accessibility Help](https://ckeditor.com/cke4/addon/a11yhelp) dialog does not contain info about focus being moved back to the editing area upon activating a toolbar button. +* [#4790](https://github.com/ckeditor/ckeditor4/issues/4790): Fixed: Printing page is invoked before the printed page is fully loaded. +* [#4874](https://github.com/ckeditor/ckeditor4/issues/4874): Fixed: Built-in support for pasting and dropping images in the [Clipboard](https://ckeditor.com/cke4/addon/clipboard) plugin restricts third party plugins from handling image pasting. Thanks to [FlowIT-JIT](https://github.com/FlowIT-JIT)! +* [#4888](https://github.com/ckeditor/ckeditor4/issues/4888): Fixed: The [`CKEDITOR.dialog#setState()`](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_dialog.html#method-setState) method throws error when there is no "OK" button in the dialog. +* [#4858](https://github.com/ckeditor/ckeditor4/issues/4858): Fixed: The [Autolink](https://ckeditor.com/cke4/addon/autolink) plugin incorrectly escapes the `&` characters when pasting links into the editor. +* [#4892](https://github.com/ckeditor/ckeditor4/issues/4892): Fixed: Focus of buttons in dialogs is not visible enough in High Contrast mode. +* [#3858](https://github.com/ckeditor/ckeditor4/issues/3858): Fixed: Pasting content in `ENTER_BR` [enter mode](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_config.html#cfg-enterMode) crashes the editor. +* [#4891](https://github.com/ckeditor/ckeditor4/issues/4891): Fixed: The [Autogrow](https://ckeditor.com/cke4/addon/autogrow) plugin applies fixed width to the editor. + +API Changes: + +* [#4462](https://github.com/ckeditor/ckeditor4/issues/4462): [`CKEDITOR.editor#getSelection()`](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_editor.html#method-getSelection) now returns `null` if the editor is in recreating state. +* [#4583](https://github.com/ckeditor/ckeditor4/issues/4583): Added support for new, comma-less color syntax to [`CKEDITOR.tools.color`](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_tools_color.html). +* [#4604](https://github.com/ckeditor/ckeditor4/issues/4604): Added the [`CKEDITOR.plugins.clipboard.dataTransfer#isFileTransfer()`](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_plugins_clipboard_dataTransfer.html#method-isFileTransfer) method. +* [#4790](https://github.com/ckeditor/ckeditor4/issues/4790): Added `callback` parameter to [`CKEDITOR.plugins.preview#createPreview()`](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_plugins_preview.html#method-createPreview) method. + +Other Changes: + +* [#4866](https://github.com/ckeditor/ckeditor4/issues/#4866): The [Flash](https://ckeditor.com/cke4/addon/flash) plugin is now deprecated and has been removed from CKEditor 4. +* [#4901](https://github.com/ckeditor/ckeditor4/issues/4901): Redesigned buttons placement in the [Content templates](https://ckeditor.com/cke4/addon/templates) dialog to make it more UX friendly. Thanks to [Fynn96](https://github.com/Fynn96)! + ## CKEditor 4.16.2 **Security Updates:** diff --git a/web/core/assets/vendor/ckeditor/SECURITY.md b/web/core/assets/vendor/ckeditor/SECURITY.md new file mode 100644 index 00000000..6e04d5a1 --- /dev/null +++ b/web/core/assets/vendor/ckeditor/SECURITY.md @@ -0,0 +1,10 @@ +# Reporting a security issues + +If you believe you have found a security issue in the CKEditor 4 software, please contact us immediately. + +When reporting a potential security problem, please bear this in mind: + +* Make sure to provide as many details as possible about the vulnerability. +* Please do not disclose publicly any security issues until we fix them and publish security releases. + +Contact the security team at security@cksource.com. As soon as we receive the security report, we will work promptly to confirm the issue and then to provide a security fix. diff --git a/web/core/assets/vendor/ckeditor/ckeditor.js b/web/core/assets/vendor/ckeditor/ckeditor.js index 16aec92b..7c4d6fd9 100644 --- a/web/core/assets/vendor/ckeditor/ckeditor.js +++ b/web/core/assets/vendor/ckeditor/ckeditor.js @@ -2,14 +2,14 @@ Copyright (c) 2003-2021, 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 b=/(^|.*[\\\/])ckeditor\.js(?:\?.*|;.*)?$/i,h={timestamp:"L7CE",version:"4.16.2",revision:"4e64f6721",rnd:Math.floor(900*Math.random())+100,_:{pending:[],basePathSrcPattern:b},status:"unloaded",basePath:function(){var a=window.CKEDITOR_BASEPATH||"";if(!a)for(var e=document.getElementsByTagName("script"),f=0;fy.getListenerIndex(e)){y=y.listeners;f||(f=this);isNaN(c)&&(c=10);d.fn=e;d.priority=c;for(var w=y.length-1;0<=w;w--)if(y[w].priority<=c)return y.splice(w+1,0,d),{removeListener:g};y.unshift(d)}return{removeListener:g}},once:function(){var a= -Array.prototype.slice.call(arguments),b=a[1];a[1]=function(a){a.removeListener();return b.apply(this,arguments)};return this.on.apply(this,a)},capture:function(){CKEDITOR.event.useCapture=1;var a=this.on.apply(this,arguments);CKEDITOR.event.useCapture=0;return a},fire:function(){var a=0,e=function(){a=1},h=0,l=function(){h=1};return function(c,d,g){var n=f(this)[c];c=a;var y=h;a=h=0;if(n){var w=n.listeners;if(w.length)for(var w=w.slice(0),p,t=0;ty.getListenerIndex(e)){y=y.listeners;f||(f=this);isNaN(c)&&(c=10);d.fn=e;d.priority=c;for(var v=y.length-1;0<=v;v--)if(y[v].priority<=c)return y.splice(v+1,0,d),{removeListener:g};y.unshift(d)}return{removeListener:g}},once:function(){var a= +Array.prototype.slice.call(arguments),b=a[1];a[1]=function(a){a.removeListener();return b.apply(this,arguments)};return this.on.apply(this,a)},capture:function(){CKEDITOR.event.useCapture=1;var a=this.on.apply(this,arguments);CKEDITOR.event.useCapture=0;return a},fire:function(){var a=0,e=function(){a=1},h=0,m=function(){h=1};return function(c,d,g){var n=f(this)[c];c=a;var y=h;a=h=0;if(n){var v=n.listeners;if(v.length)for(var v=v.slice(0),p,q=0;qdocument.documentMode),mobile:-1e||f.quirks);f.gecko&&(h=b.match(/rv:([\d\.]+)/))&&(h=h[1].split("."),e=1E4*h[0]+100*(h[1]||0)+1*(h[2]||0));f.air&&(e=parseFloat(b.match(/ adobeair\/(\d+)/)[1])); @@ -18,16 +18,16 @@ f.iOS&&(f.cssClass+=" cke_browser_ios");f.hidpi&&(f.cssClass+=" cke_hidpi");retu function(b){(this._.pending||(this._.pending=[])).push(b)};(function(){CKEDITOR.domReady(function(){var b=CKEDITOR.loadFullCore,h=CKEDITOR.loadFullCoreTimeout;b&&(CKEDITOR.status="basic_ready",b&&b._load?b():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(b,h){CKEDITOR.verbosity& CKEDITOR.VERBOSITY_WARN&&CKEDITOR.fire("log",{type:"warn",errorCode:b,additionalData:h})},CKEDITOR.error=function(b,h){CKEDITOR.verbosity&CKEDITOR.VERBOSITY_ERROR&&CKEDITOR.fire("log",{type:"error",errorCode:b,additionalData:h})},CKEDITOR.on("log",function(b){if(window.console&&window.console.log){var h=console[b.data.type]?b.data.type:"log",f=b.data.errorCode;if(b=b.data.additionalData)console[h]("[CKEDITOR] Error code: "+f+".",b);else console[h]("[CKEDITOR] Error code: "+f+".");console[h]("[CKEDITOR] For more information about this error go to https://ckeditor.com/docs/ckeditor4/latest/guide/dev_errors.html#"+ f)}},null,null,999),CKEDITOR.dom={},function(){function b(n,g,c){this._minInterval=n;this._context=c;this._lastOutput=this._scheduledTimer=0;this._output=CKEDITOR.tools.bind(g,c||{});var a=this;this.input=function(){function n(){a._lastOutput=(new Date).getTime();a._scheduledTimer=0;a._call()}if(!a._scheduledTimer||!1!==a._reschedule()){var g=(new Date).getTime()-a._lastOutput;g/g,k=//g,l=/|\s) /g,function(n,g){return g+"\x26nbsp;"}).replace(/ (?=<)/g,"\x26nbsp;")},getNextNumber:function(){var n=0;return function(){return++n}}(),getNextId:function(){return"cke_"+this.getNextNumber()},getUniqueId:function(){for(var n="e",g=0;8>g;g++)n+=Math.floor(65536* -(1+Math.random())).toString(16).substring(1);return n},override:function(n,g){var c=g(n);c.prototype=n.prototype;return c},setTimeout:function(n,g,c,a,d){d||(d=window);c||(c=d);return d.setTimeout(function(){a?n.apply(c,[].concat(a)):n.apply(c)},g||0)},throttle:function(n,g,c){return new this.buffers.throttle(n,g,c)},trim:function(){var n=/(?:^[ \t\n\r]+)|(?:[ \t\n\r]+$)/g;return function(g){return g.replace(n,"")}}(),ltrim:function(){var g=/^[ \t\n\r]+/g;return function(c){return c.replace(g,"")}}(), +"undefined"!=typeof n.styleFloat?"styleFloat":"float";return function(n){return"float"==n?g:n.replace(/-./g,function(n){return n.substr(1).toUpperCase()})}}(),buildStyleHtml:function(n){n=[].concat(n);for(var g,c=[],a=0;a|\s) /g,function(n,g){return g+"\x26nbsp;"}).replace(/ (?=<)/g,"\x26nbsp;")},getNextNumber:function(){var n=0;return function(){return++n}}(),getNextId:function(){return"cke_"+this.getNextNumber()},getUniqueId:function(){for(var n="e",g=0;8>g;g++)n+=Math.floor(65536* +(1+Math.random())).toString(16).substring(1);return n},override:function(n,g){var c=g(n);c.prototype=n.prototype;return c},setTimeout:function(n,g,c,a,d){d||(d=window);c||(c=d);return d.setTimeout(function(){a?n.apply(c,[].concat(a)):n.apply(c)},g||0)},throttle:function(n,g,c){return new this.buffers.throttle(n,g,c)},trim:function(){var n=/(?:^[ \t\n\r]+)|(?:[ \t\n\r]+$)/g;return function(g){return g.replace(n,"")}}(),ltrim:function(){var n=/^[ \t\n\r]+/g;return function(g){return g.replace(n,"")}}(), rtrim:function(){var g=/[ \t\n\r]+$/g;return function(c){return c.replace(g,"")}}(),indexOf:function(g,c){if("function"==typeof c)for(var a=0,d=g.length;aparseFloat(c);a&&(c=c.replace("-",""));g.setStyle("width",c);c=g.$.clientWidth;return a?-c:c}return c}}(),repeat:function(g,c){return Array(c+1).join(g)},tryThese:function(){for(var g,c=0,a=arguments.length;cc;c++)g[c]=("0"+parseInt(g[c],10).toString(16)).slice(-2);return"#"+g.join("")})},normalizeHex:function(g){return g.replace(/#(([0-9a-f]{3}){1,2})($|;|\s+)/gi,function(g,c,n,a){g=c.toLowerCase();3==g.length&& @@ -35,12 +35,12 @@ c)},0)}},normalizeCssText:function(g,c){var a=[],d,b=CKEDITOR.tools.parseCssText n.toLowerCase(),"font-family"==n&&(a=a.replace(/\s*,\s*/g,",")),a=CKEDITOR.tools.trim(a));d[n]=a});return d},writeCssText:function(g,c){var a,d=[];for(a in g)d.push(a+":"+g[a]);c&&d.sort();return d.join("; ")},objectCompare:function(g,c,a){var d;if(!g&&!c)return!0;if(!g||!c)return!1;for(d in g)if(g[d]!=c[d])return!1;if(!a)for(d in c)if(g[d]!=c[d])return!1;return!0},objectKeys:function(g){return CKEDITOR.tools.object.keys(g)},convertArrayToObject:function(g,c){var a={};1==arguments.length&&(c=!0); for(var d=0,b=g.length;da;a++)g.push(Math.floor(256*Math.random()));for(a=0;a=d||0==a&&48<= d&&57>=d||1==a&&48<=d&&57>=d&&45==e?b+("\\"+d.toString(16)+" "):0==a&&1==c&&45==d?b+("\\"+g.charAt(a)):128<=d||45==d||95==d||48<=d&&57>=d||65<=d&&90>=d||97<=d&&122>=d?b+g.charAt(a):b+("\\"+g.charAt(a));g=b}else g="";return g},getMouseButton:function(g){return(g=g&&g.data?g.data.$:g)?CKEDITOR.tools.normalizeMouseButton(g.button):!1},normalizeMouseButton:function(g,c){if(!CKEDITOR.env.ie||9<=CKEDITOR.env.version&&!CKEDITOR.env.ie6Compat)return g;for(var a=[[CKEDITOR.MOUSE_BUTTON_LEFT,1],[CKEDITOR.MOUSE_BUTTON_MIDDLE, -4],[CKEDITOR.MOUSE_BUTTON_RIGHT,2]],d=0;de)for(f=e;3>f;f++)b[f]=0;l[0]=(b[0]&252)>>2;l[1]=(b[0]&3)<<4|b[1]>>4;l[2]=(b[1]&15)<<2|(b[2]&192)>>6;l[3]=b[2]&63;for(f=0;4>f;f++)c=f<=e? -c+"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/".charAt(l[f]):c+"\x3d"}return c},style:{parse:{_borderStyle:"none hidden dotted dashed solid double groove ridge inset outset".split(" "),_widthRegExp:/^(thin|medium|thick|[\+-]?\d+(\.\d+)?[a-z%]+|[\+-]?0+(\.0+)?|\.\d+[a-z%]+)$/,_rgbaRegExp:/rgba?\(\s*\d+%?\s*,\s*\d+%?\s*,\s*\d+%?\s*(?:,\s*[0-9.]+\s*)?\)/gi,_hslaRegExp:/hsla?\(\s*[0-9.]+\s*,\s*\d+%\s*,\s*\d+%\s*(?:,\s*[0-9.]+\s*)?\)/gi,background:function(g){var c={},a=this._findColor(g); +4],[CKEDITOR.MOUSE_BUTTON_RIGHT,2]],d=0;de)for(f=e;3>f;f++)b[f]=0;m[0]=(b[0]&252)>>2;m[1]=(b[0]&3)<<4|b[1]>>4;m[2]=(b[1]&15)<<2|(b[2]&192)>>6;m[3]=b[2]&63;for(f=0;4>f;f++)c=f<=e? +c+"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/".charAt(m[f]):c+"\x3d"}return c},style:{parse:{_borderStyle:"none hidden dotted dashed solid double groove ridge inset outset".split(" "),_widthRegExp:/^(thin|medium|thick|[\+-]?\d+(\.\d+)?[a-z%]+|[\+-]?0+(\.0+)?|\.\d+[a-z%]+)$/,_rgbaRegExp:/rgba?\(\s*\d+%?\s*,\s*\d+%?\s*,\s*\d+%?\s*(?:,\s*[0-9.]+\s*)?\)/gi,_hslaRegExp:/hsla?\(\s*[0-9.]+\s*,\s*\d+%\s*,\s*\d+%\s*(?:,\s*[0-9.]+\s*)?\)/gi,background:function(g){var c={},a=this._findColor(g); a.length&&(c.color=a[0],CKEDITOR.tools.array.forEach(a,function(c){g=g.replace(c,"")}));if(g=CKEDITOR.tools.trim(g))c.unprocessed=g;return c},margin:function(g){return CKEDITOR.tools.style.parse.sideShorthand(g,function(g){return g.match(/(?:\-?[\.\d]+(?:%|\w*)|auto|inherit|initial|unset|revert)/g)||["0px"]})},sideShorthand:function(g,c){function a(g){d.top=b[g[0]];d.right=b[g[1]];d.bottom=b[g[2]];d.left=b[g[3]]}var d={},b=c?c(g):g.split(/\s+/);switch(b.length){case 1:a([0,0,0,0]);break;case 2:a([0, 1,0,1]);break;case 3:a([0,1,2,1]);break;case 4:a([0,1,2,3])}return d},border:function(g){return CKEDITOR.tools.style.border.fromCssRule(g)},_findColor:function(g){var c=[],a=CKEDITOR.tools.array,c=c.concat(g.match(this._rgbaRegExp)||[]),c=c.concat(g.match(this._hslaRegExp)||[]);return c=c.concat(a.filter(g.split(/\s+/),function(g){return g.match(/^\#[a-f0-9]{3}(?:[a-f0-9]{3})?$/gi)?!0:g.toLowerCase()in CKEDITOR.tools.style.parse._colors}))}}},array:{filter:function(g,c,a){var d=[];this.forEach(g, function(b,e){c.call(a,b,e,g)&&d.push(b)});return d},find:function(g,c,a){for(var d=g.length,b=0;bCKEDITOR.env.version&&(this.type==CKEDITOR.NODE_ELEMENT||this.type== -CKEDITOR.NODE_DOCUMENT_FRAGMENT)&&e(a);return a},hasPrevious:function(){return!!this.$.previousSibling},hasNext:function(){return!!this.$.nextSibling},insertAfter:function(b){b.$.parentNode.insertBefore(this.$,b.$.nextSibling);return b},insertBefore:function(b){b.$.parentNode.insertBefore(this.$,b.$);return b},insertBeforeMe:function(b){this.$.parentNode.insertBefore(b.$,this.$);return b},getAddress:function(b){for(var h=[],f=this.getDocument().$.documentElement,e=this;e&&e!=f;){var a=e.getParent(); -a&&h.unshift(this.getIndex.call(e,b));e=a}return h},getDocument:function(){return new CKEDITOR.dom.document(this.$.ownerDocument||this.$.parentNode.ownerDocument)},getIndex:function(b){function h(a,b){var e=b?a.getNext():a.getPrevious();return e&&e.type==CKEDITOR.NODE_TEXT?e.isEmpty()?h(e,b):e:null}var f=this,e=-1,a;if(!this.getParent()||b&&f.type==CKEDITOR.NODE_TEXT&&f.isEmpty()&&!h(f)&&!h(f,!0))return-1;do if(!b||f.equals(this)||f.type!=CKEDITOR.NODE_TEXT||!a&&!f.isEmpty())e++,a=f.type==CKEDITOR.NODE_TEXT; -while(f=f.getPrevious());return e},getNextSourceNode:function(b,h,f){if(f&&!f.call){var e=f;f=function(a){return!a.equals(e)}}b=!b&&this.getFirst&&this.getFirst();var a;if(!b){if(this.type==CKEDITOR.NODE_ELEMENT&&f&&!1===f(this,!0))return null;b=this.getNext()}for(;!b&&(a=(a||this).getParent());){if(f&&!1===f(a,!0))return null;b=a.getNext()}return!b||f&&!1===f(b)?null:h&&h!=b.type?b.getNextSourceNode(!1,h,f):b},getPreviousSourceNode:function(b,h,f){if(f&&!f.call){var e=f;f=function(a){return!a.equals(e)}}b= -!b&&this.getLast&&this.getLast();var a;if(!b){if(this.type==CKEDITOR.NODE_ELEMENT&&f&&!1===f(this,!0))return null;b=this.getPrevious()}for(;!b&&(a=(a||this).getParent());){if(f&&!1===f(a,!0))return null;b=a.getPrevious()}return!b||f&&!1===f(b)?null:h&&b.type!=h?b.getPreviousSourceNode(!1,h,f):b},getPrevious:function(b){var h=this.$,f;do f=(h=h.previousSibling)&&10!=h.nodeType&&new CKEDITOR.dom.node(h);while(f&&b&&!b(f));return f},getNext:function(b){var h=this.$,f;do f=(h=h.nextSibling)&&new CKEDITOR.dom.node(h); -while(f&&b&&!b(f));return f},getParent:function(b){var h=this.$.parentNode;return h&&(h.nodeType==CKEDITOR.NODE_ELEMENT||b&&h.nodeType==CKEDITOR.NODE_DOCUMENT_FRAGMENT)?new CKEDITOR.dom.node(h):null},getParents:function(b){var h=this,f=[];do f[b?"push":"unshift"](h);while(h=h.getParent());return f},getCommonAncestor:function(b){if(b.equals(this))return this;if(b.contains&&b.contains(this))return b;var h=this.contains?this:this.getParent();do if(h.contains(b))return h;while(h=h.getParent());return null}, -getPosition:function(b){var h=this.$,f=b.$;if(h.compareDocumentPosition)return h.compareDocumentPosition(f);if(h==f)return CKEDITOR.POSITION_IDENTICAL;if(this.type==CKEDITOR.NODE_ELEMENT&&b.type==CKEDITOR.NODE_ELEMENT){if(h.contains){if(h.contains(f))return CKEDITOR.POSITION_CONTAINS+CKEDITOR.POSITION_PRECEDING;if(f.contains(h))return CKEDITOR.POSITION_IS_CONTAINED+CKEDITOR.POSITION_FOLLOWING}if("sourceIndex"in h)return 0>h.sourceIndex||0>f.sourceIndex?CKEDITOR.POSITION_DISCONNECTED:h.sourceIndex< -f.sourceIndex?CKEDITOR.POSITION_PRECEDING:CKEDITOR.POSITION_FOLLOWING}h=this.getAddress();b=b.getAddress();for(var f=Math.min(h.length,b.length),e=0;eCKEDITOR.env.version&& +(this.type==CKEDITOR.NODE_ELEMENT||this.type==CKEDITOR.NODE_DOCUMENT_FRAGMENT)&&e(a);return a},hasPrevious:function(){return!!this.$.previousSibling},hasNext:function(){return!!this.$.nextSibling},insertAfter:function(b){b.$.parentNode.insertBefore(this.$,b.$.nextSibling);return b},insertBefore:function(b){b.$.parentNode.insertBefore(this.$,b.$);return b},insertBeforeMe:function(b){this.$.parentNode.insertBefore(b.$,this.$);return b},getAddress:function(b){for(var h=[],f=this.getDocument().$.documentElement, +e=this;e&&e!=f;){var a=e.getParent();a&&h.unshift(this.getIndex.call(e,b));e=a}return h},getDocument:function(){return new CKEDITOR.dom.document(this.$.ownerDocument||this.$.parentNode.ownerDocument)},getIndex:function(b){function h(a,b){var e=b?a.getNext():a.getPrevious();return e&&e.type==CKEDITOR.NODE_TEXT?e.isEmpty()?h(e,b):e:null}var f=this,e=-1,a;if(!this.getParent()||b&&f.type==CKEDITOR.NODE_TEXT&&f.isEmpty()&&!h(f)&&!h(f,!0))return-1;do if(!b||f.equals(this)||f.type!=CKEDITOR.NODE_TEXT||!a&& +!f.isEmpty())e++,a=f.type==CKEDITOR.NODE_TEXT;while(f=f.getPrevious());return e},getNextSourceNode:function(b,h,f){if(f&&!f.call){var e=f;f=function(a){return!a.equals(e)}}b=!b&&this.getFirst&&this.getFirst();var a;if(!b){if(this.type==CKEDITOR.NODE_ELEMENT&&f&&!1===f(this,!0))return null;b=this.getNext()}for(;!b&&(a=(a||this).getParent());){if(f&&!1===f(a,!0))return null;b=a.getNext()}return!b||f&&!1===f(b)?null:h&&h!=b.type?b.getNextSourceNode(!1,h,f):b},getPreviousSourceNode:function(b,h,f){if(f&& +!f.call){var e=f;f=function(a){return!a.equals(e)}}b=!b&&this.getLast&&this.getLast();var a;if(!b){if(this.type==CKEDITOR.NODE_ELEMENT&&f&&!1===f(this,!0))return null;b=this.getPrevious()}for(;!b&&(a=(a||this).getParent());){if(f&&!1===f(a,!0))return null;b=a.getPrevious()}return!b||f&&!1===f(b)?null:h&&b.type!=h?b.getPreviousSourceNode(!1,h,f):b},getPrevious:function(b){var h=this.$,f;do f=(h=h.previousSibling)&&10!=h.nodeType&&new CKEDITOR.dom.node(h);while(f&&b&&!b(f));return f},getNext:function(b){var h= +this.$,f;do f=(h=h.nextSibling)&&new CKEDITOR.dom.node(h);while(f&&b&&!b(f));return f},getParent:function(b){var h=this.$.parentNode;return h&&(h.nodeType==CKEDITOR.NODE_ELEMENT||b&&h.nodeType==CKEDITOR.NODE_DOCUMENT_FRAGMENT)?new CKEDITOR.dom.node(h):null},getParents:function(b){var h=this,f=[];do f[b?"push":"unshift"](h);while(h=h.getParent());return f},getCommonAncestor:function(b){if(b.equals(this))return this;if(b.contains&&b.contains(this))return b;var h=this.contains?this:this.getParent(); +do if(h.contains(b))return h;while(h=h.getParent());return null},getPosition:function(b){var h=this.$,f=b.$;if(h.compareDocumentPosition)return h.compareDocumentPosition(f);if(h==f)return CKEDITOR.POSITION_IDENTICAL;if(this.type==CKEDITOR.NODE_ELEMENT&&b.type==CKEDITOR.NODE_ELEMENT){if(h.contains){if(h.contains(f))return CKEDITOR.POSITION_CONTAINS+CKEDITOR.POSITION_PRECEDING;if(f.contains(h))return CKEDITOR.POSITION_IS_CONTAINED+CKEDITOR.POSITION_FOLLOWING}if("sourceIndex"in h)return 0>h.sourceIndex|| +0>f.sourceIndex?CKEDITOR.POSITION_DISCONNECTED:h.sourceIndex=document.documentMode||!h||(b=h+":"+b);return new CKEDITOR.dom.nodeList(this.$.getElementsByTagName(b))},getHead:function(){var b= +null},getByAddress:function(b,h){for(var f=this.$.documentElement,e=0;f&&e=document.documentMode||!h||(b=h+":"+b);return new CKEDITOR.dom.nodeList(this.$.getElementsByTagName(b))},getHead:function(){var b= this.$.getElementsByTagName("head")[0];return b=b?new CKEDITOR.dom.element(b):this.getDocumentElement().append(new CKEDITOR.dom.element("head"),!0)},getBody:function(){return new CKEDITOR.dom.element(this.$.body)},getDocumentElement:function(){return new CKEDITOR.dom.element(this.$.documentElement)},getWindow:function(){return new CKEDITOR.dom.window(this.$.parentWindow||this.$.defaultView)},write:function(b){this.$.open("text/html","replace");CKEDITOR.env.ie&&(b=b.replace(/(?:^\s*]*?>)|^/i, '$\x26\n\x3cscript data-cke-temp\x3d"1"\x3e('+CKEDITOR.tools.fixDomain+")();\x3c/script\x3e"));this.$.write(b);this.$.close()},find:function(b){return new CKEDITOR.dom.nodeList(this.$.querySelectorAll(b))},findOne:function(b){return(b=this.$.querySelector(b))?new CKEDITOR.dom.element(b):null},_getHtml5ShivFrag:function(){var b=this.getCustomData("html5ShivFrag");b||(b=this.$.createDocumentFragment(),CKEDITOR.tools.enableHtml5Elements(b,!0),this.setCustomData("html5ShivFrag",b));return b}}),CKEDITOR.dom.nodeList= function(b){this.$=b},CKEDITOR.dom.nodeList.prototype={count:function(){return this.$.length},getItem:function(b){return 0>b||b>=this.$.length?null:(b=this.$[b])?new CKEDITOR.dom.node(b):null},toArray:function(){return CKEDITOR.tools.array.map(this.$,function(b){return new CKEDITOR.dom.node(b)})}},CKEDITOR.dom.element=function(b,h){"string"==typeof b&&(b=(h?h.$:document).createElement(b));CKEDITOR.dom.domObject.call(this,b)},CKEDITOR.dom.element.get=function(b){return(b="string"==typeof b?document.getElementById(b)|| -document.getElementsByName(b)[0]:b)&&(b.$?b:new CKEDITOR.dom.element(b))},CKEDITOR.dom.element.prototype=new CKEDITOR.dom.node,CKEDITOR.dom.element.createFromHtml=function(b,h){var f=new CKEDITOR.dom.element("div",h);f.setHtml(b);return f.getFirst().remove()},CKEDITOR.dom.element.setMarker=function(b,h,f,e){var a=h.getCustomData("list_marker_id")||h.setCustomData("list_marker_id",CKEDITOR.tools.getNextNumber()).getCustomData("list_marker_id"),m=h.getCustomData("list_marker_names")||h.setCustomData("list_marker_names", -{}).getCustomData("list_marker_names");b[a]=h;m[f]=1;return h.setCustomData(f,e)},CKEDITOR.dom.element.clearAllMarkers=function(b){for(var h in b)CKEDITOR.dom.element.clearMarkers(b,b[h],1)},CKEDITOR.dom.element.clearMarkers=function(b,h,f){var e=h.getCustomData("list_marker_names"),a=h.getCustomData("list_marker_id"),m;for(m in e)h.removeCustomData(m);h.removeCustomData("list_marker_names");f&&(h.removeCustomData("list_marker_id"),delete b[a])},function(){function b(a,c){return-1<(" "+a+" ").replace(m, -" ").indexOf(" "+c+" ")}function h(a){var c=!0;a.$.id||(a.$.id="cke_tmp_"+CKEDITOR.tools.getNextNumber(),c=!1);return function(){c||a.removeAttribute("id")}}function f(a,c){var d=CKEDITOR.tools.escapeCss(a.$.id);return"#"+d+" "+c.split(/,\s*/).join(", #"+d+" ")}function e(a){for(var c=0,d=0,g=k[a].length;dCKEDITOR.env.version? this.$.text+=a:this.append(new CKEDITOR.dom.text(a))},appendBogus:function(a){if(a||CKEDITOR.env.needsBrFiller){for(a=this.getLast();a&&a.type==CKEDITOR.NODE_TEXT&&!CKEDITOR.tools.rtrim(a.getText());)a=a.getPrevious();a&&a.is&&a.is("br")||(a=this.getDocument().createElement("br"),CKEDITOR.env.gecko&&a.setAttribute("type","_moz"),this.append(a))}},breakParent:function(a,c){var d=new CKEDITOR.dom.range(this.getDocument());d.setStartAfter(this);d.setEndAfter(a);var g=d.extractContents(!1,c||!1),b;d.insertNode(this.remove()); if(CKEDITOR.env.ie&&!CKEDITOR.env.edge){for(d=new CKEDITOR.dom.element("div");b=g.getFirst();)b.$.style.backgroundColor&&(b.$.style.backgroundColor=b.$.style.backgroundColor),d.append(b);d.insertAfter(this);d.remove(!0)}else g.insertAfterNode(this)},contains:document.compareDocumentPosition?function(a){return!!(this.$.compareDocumentPosition(a.$)&16)}:function(a){var c=this.$;return a.type!=CKEDITOR.NODE_ELEMENT?c.contains(a.getParent().$):c!=a.$&&c.contains(a.$)},focus:function(){function a(){try{this.$.focus()}catch(c){}} return function(c){c?CKEDITOR.tools.setTimeout(a,100,this):a.call(this)}}(),getHtml:function(){var a=this.$.innerHTML;return CKEDITOR.env.ie?a.replace(/<\?[^>]*>/g,""):a},getOuterHtml:function(){if(this.$.outerHTML)return this.$.outerHTML.replace(/<\?[^>]*>/,"");var a=this.$.ownerDocument.createElement("div");a.appendChild(this.$.cloneNode(!0));return a.innerHTML},getClientRect:function(a){var c=CKEDITOR.tools.extend({},this.$.getBoundingClientRect());!c.width&&(c.width=c.right-c.left);!c.height&& (c.height=c.bottom-c.top);return a?CKEDITOR.tools.getAbsoluteRectPosition(this.getWindow(),c):c},setHtml:CKEDITOR.env.ie&&9>CKEDITOR.env.version?function(a){try{var c=this.$;if(this.getParent())return c.innerHTML=a;var d=this.getDocument()._getHtml5ShivFrag();d.appendChild(c);c.innerHTML=a;d.removeChild(c);return a}catch(g){this.$.innerHTML="";c=new CKEDITOR.dom.element("body",this.getDocument());c.$.innerHTML=a;for(c=c.getChildren();c.count();)this.append(c.getItem(0));return a}}:function(a){return this.$.innerHTML= -a},setText:function(){var a=document.createElement("p");a.innerHTML="x";a=a.textContent;return function(c){this.$[a?"textContent":"innerText"]=c}}(),getAttribute:function(){var a=function(c){return this.$.getAttribute(c,2)};return CKEDITOR.env.ie&&(CKEDITOR.env.ie7Compat||CKEDITOR.env.quirks)?function(c){switch(c){case "class":c="className";break;case "http-equiv":c="httpEquiv";break;case "name":return this.$.name;case "tabindex":return c=this.$.getAttribute(c,2),0!==c&&0===this.$.tabIndex&&(c=null), -c;case "checked":return c=this.$.attributes.getNamedItem(c),(c.specified?c.nodeValue:this.$.checked)?"checked":null;case "hspace":case "value":return this.$[c];case "style":return this.$.style.cssText;case "contenteditable":case "contentEditable":return this.$.attributes.getNamedItem("contentEditable").specified?this.$.getAttribute("contentEditable"):null}return this.$.getAttribute(c,2)}:a}(),getAttributes:function(a){var c={},d=this.$.attributes,g;a=CKEDITOR.tools.isArray(a)?a:[];for(g=0;g=document.documentMode){var c=this.$.scopeName;"HTML"!=c&&(a=c.toLowerCase()+":"+a)}this.getName=function(){return a};return this.getName()},getValue:function(){return this.$.value},getFirst:function(a){var c=this.$.firstChild;(c=c&&new CKEDITOR.dom.node(c))&&a&&!a(c)&&(c=c.getNext(a));return c},getLast:function(a){var c=this.$.lastChild;(c=c&&new CKEDITOR.dom.node(c))&&a&&!a(c)&&(c=c.getPrevious(a));return c},getStyle:function(a){return this.$.style[CKEDITOR.tools.cssStyleToDomStyle(a)]}, @@ -112,41 +112,41 @@ arguments)}catch(g){}else a.apply(this,arguments);return this}:a}(),setAttribute 0;cCKEDITOR.env.version?(a=Math.round(100*a),this.setStyle("filter",100<=a?"":"progid:DXImageTransform.Microsoft.Alpha(opacity\x3d"+a+")")):this.setStyle("opacity",a)},unselectable:function(){this.setStyles(CKEDITOR.tools.cssVendorPrefix("user-select", "none"));if(CKEDITOR.env.ie){this.setAttribute("unselectable","on");for(var a,c=this.getElementsByTag("*"),d=0,g=c.count();df||0f?f:b);d&&(0>e||0e?e:g,0)},setState:function(a,c,d){c=c||"cke";switch(a){case CKEDITOR.TRISTATE_ON:this.addClass(c+"_on");this.removeClass(c+ +e||(c+=this.$.clientLeft?1:0,d+=this.$.clientTop?1:0);return{x:c,y:d}},scrollIntoView:function(a){var c=this.getParent();if(c){do if((c.$.clientWidth&&c.$.clientWidthf||0f?f:b);d&&(0>e||0e?e:g,0)},setState:function(a,c,d){c=c||"cke";switch(a){case CKEDITOR.TRISTATE_ON:this.addClass(c+"_on");this.removeClass(c+ "_off");this.removeClass(c+"_disabled");d&&this.setAttribute("aria-pressed",!0);d&&this.removeAttribute("aria-disabled");break;case CKEDITOR.TRISTATE_DISABLED:this.addClass(c+"_disabled");this.removeClass(c+"_off");this.removeClass(c+"_on");d&&this.setAttribute("aria-disabled",!0);d&&this.removeAttribute("aria-pressed");break;default:this.addClass(c+"_off"),this.removeClass(c+"_on"),this.removeClass(c+"_disabled"),d&&this.removeAttribute("aria-pressed"),d&&this.removeAttribute("aria-disabled")}}, getFrameDocument:function(){var a=this.$;try{a.contentWindow.document}catch(c){a.src=a.src}return a&&new CKEDITOR.dom.document(a.contentWindow.document)},copyAttributes:function(a,c){var d=this.$.attributes;c=c||{};for(var g=0;gCKEDITOR.env.version){var b=g.ownerDocument.createEventObject(),e;for(e in c)b[e]=c[e];g.fireEvent(d, -b)}else g[g[a]?a:d](c)},isDetached:function(){var a=this.getDocument(),c=a.getDocumentElement();return c.equals(this)||c.contains(this)?!CKEDITOR.env.ie||8=B.getChildCount()?(B=B.getChild(A-1),F=!0):B=B.getChild(A):L=F=!0;v.type== -CKEDITOR.NODE_TEXT?q?C=!0:v.split(D):0da)for(;X;)X=f(X,P,!0);P=Y}q||m()}}function f(){var a=!1,c=CKEDITOR.dom.walker.whitespaces(),d=CKEDITOR.dom.walker.bookmark(!0),b=CKEDITOR.dom.walker.bogus();return function(e){return d(e)||c(e)?!0:b(e)&&!a?a=!0:e.type==CKEDITOR.NODE_TEXT&&(e.hasAscendant("pre")||CKEDITOR.tools.trim(e.getText()).length)||e.type==CKEDITOR.NODE_ELEMENT&&!e.is(m)?!1:!0}}function e(a){var c=CKEDITOR.dom.walker.whitespaces(), -d=CKEDITOR.dom.walker.bookmark(1);return function(b){return d(b)||c(b)?!0:!a&&k(b)||b.type==CKEDITOR.NODE_ELEMENT&&b.is(CKEDITOR.dtd.$removeEmpty)}}function a(a){return function(){var b;return this[a?"getPreviousNode":"getNextNode"](function(a){!b&&d(a)&&(b=a);return c(a)&&!(k(a)&&a.equals(b))})}}var m={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},k=CKEDITOR.dom.walker.bogus(), -l=/^[\t\r\n ]*(?: |\xa0)$/,c=CKEDITOR.dom.walker.editable(),d=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.startContainer=null;this.collapsed=!0;var h=b instanceof CKEDITOR.dom.document;this.document=h?b:b.getDocument();this.root=h?b.getBody():b},function(){function b(a){a.collapsed=a.startContainer&&a.endContainer&&a.startContainer.equals(a.endContainer)&&a.startOffset==a.endOffset}function h(a,c,d,b,e){function f(a,g,c,d){var b=c?a.getPrevious():a.getNext();if(d&&l)return b;u||d?g.append(a.clone(!0,e),c):(a.remove(),m&&g.append(a,c));return b}function k(){var a,g,c,d=Math.min(I.length, +L.length);for(a=0;a=B.getChildCount()?(B=B.getChild(A-1),F=!0):B=B.getChild(A):M=F=!0;w.type== +CKEDITOR.NODE_TEXT?u?D=!0:w.split(C):0ca)for(;X;)X=f(X,O,!0);O=Y}u||h()}}function f(){var a=!1,c=CKEDITOR.dom.walker.whitespaces(),d=CKEDITOR.dom.walker.bookmark(!0),b=CKEDITOR.dom.walker.bogus();return function(e){return d(e)||c(e)?!0:b(e)&&!a?a=!0:e.type==CKEDITOR.NODE_TEXT&&(e.hasAscendant("pre")||CKEDITOR.tools.trim(e.getText()).length)||e.type==CKEDITOR.NODE_ELEMENT&&!e.is(k)?!1:!0}}function e(a){var c=CKEDITOR.dom.walker.whitespaces(), +d=CKEDITOR.dom.walker.bookmark(1);return function(b){return d(b)||c(b)?!0:!a&&l(b)||b.type==CKEDITOR.NODE_ELEMENT&&b.is(CKEDITOR.dtd.$removeEmpty)}}function a(a){return function(){var b;return this[a?"getPreviousNode":"getNextNode"](function(a){!b&&d(a)&&(b=a);return c(a)&&!(l(a)&&a.equals(b))})}}var k={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},l=CKEDITOR.dom.walker.bogus(), +m=/^[\t\r\n ]*(?: |\xa0)$/,c=CKEDITOR.dom.walker.editable(),d=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 d=new CKEDITOR.dom.documentFragment(this.document);this.collapsed||h(this,1,d,a,"undefined"==typeof c?!0:c);return d},equals:function(a){return this.startOffset===a.startOffset&&this.endOffset===a.endOffset&& -this.startContainer.equals(a.startContainer)&&this.endContainer.equals(a.endContainer)},createBookmark:function(a){function c(a){return a.getAscendant(function(a){var g;if(g=a.data&&a.data("cke-temp"))g=-1===CKEDITOR.tools.array.indexOf(["cke_copybin","cke_pastebin"],a.getAttribute("id"));return g},!0)}var d=this.startContainer,b=this.endContainer,e=this.collapsed,f,h,m,k;f=this.document.createElement("span");f.data("cke-bookmark",1);f.setStyle("display","none");f.setHtml("\x26nbsp;");a&&(m="cke_bm_"+ -CKEDITOR.tools.getNextNumber(),f.setAttribute("id",m+(e?"C":"S")));e||(h=f.clone(),h.setHtml("\x26nbsp;"),a&&h.setAttribute("id",m+"E"),k=this.clone(),c(b)&&(b=c(b),k.moveToPosition(b,CKEDITOR.POSITION_AFTER_END)),k.collapse(),k.insertNode(h));k=this.clone();c(d)&&(b=c(d),k.moveToPosition(b,CKEDITOR.POSITION_BEFORE_START));k.collapse(!0);k.insertNode(f);h?(this.setStartAfter(f),this.setEndBefore(h)):this.moveToPosition(f,CKEDITOR.POSITION_AFTER_END);return{startNode:a?m+(e?"C":"S"):f,endNode:a?m+ -"E":h,serializable:a,collapsed:e}},createBookmark2:function(){function a(g){var c=g.container,b=g.offset,e;e=c;var n=b;e=e.type!=CKEDITOR.NODE_ELEMENT||0===n||n==e.getChildCount()?0:e.getChild(n-1).type==CKEDITOR.NODE_TEXT&&e.getChild(n).type==CKEDITOR.NODE_TEXT;e&&(c=c.getChild(b-1),b=c.getLength());if(c.type==CKEDITOR.NODE_ELEMENT&&0=a.offset&&(a.offset=b.getIndex(),a.container=b.getParent()))}}var d=CKEDITOR.dom.walker.nodeType(CKEDITOR.NODE_TEXT, !0);return function(d){var b=this.collapsed,e={container:this.startContainer,offset:this.startOffset},f={container:this.endContainer,offset:this.endOffset};d&&(a(e),c(e,this.root),b||(a(f),c(f,this.root)));return{start:e.container.getAddress(d),end:b?null:f.container.getAddress(d),startOffset:e.offset,endOffset:f.offset,normalized:d,collapsed:b,is2:!0}}}(),moveToBookmark:function(a){if(a.is2){var c=this.document.getByAddress(a.start,a.normalized),d=a.startOffset,b=a.end&&this.document.getByAddress(a.end, a.normalized);a=a.endOffset;this.setStart(c,d);b?this.setEnd(b,a):this.collapse(!0)}else c=(d=a.serializable)?this.document.getById(a.startNode):a.startNode,a=d?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,d=this.startOffset,b=this.endOffset,e;if(a.type==CKEDITOR.NODE_ELEMENT)if(e=a.getChildCount(),e>d)a=a.getChild(d);else if(1>e)a=a.getPreviousSourceNode(); @@ -154,32 +154,32 @@ else{for(a=a.$;a.lastChild;)a=a.lastChild;a=new CKEDITOR.dom.node(a);a=a.getNext this.startOffset==this.endOffset-1?d.getChild(this.startOffset):d:d.getCommonAncestor(b);return c&&!d.is?d.getParent():d},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 d=this.startContainer,b=this.startOffset,e=this.collapsed;if((!a||e)&&d&&d.type==CKEDITOR.NODE_TEXT){if(b)if(b>=d.getLength())b=d.getIndex()+1,d=d.getParent();else{var f=d.split(b),b=d.getIndex()+1,d=d.getParent();this.startContainer.equals(this.endContainer)?this.setEnd(f,this.endOffset-this.startOffset):d.equals(this.endContainer)&& (this.endOffset+=1)}else b=d.getIndex(),d=d.getParent();this.setStart(d,b);if(e){this.collapse(!0);return}}d=this.endContainer;b=this.endOffset;c||e||!d||d.type!=CKEDITOR.NODE_TEXT||(b?(b>=d.getLength()||d.split(b),b=d.getIndex()+1):b=d.getIndex(),d=d.getParent(),this.setEnd(d,b))},enlarge:function(a,c){function d(a){return a&&a.type==CKEDITOR.NODE_ELEMENT&&a.hasAttribute("contenteditable")?null:a}var b=new RegExp(/[^\s\ufeff]/);switch(a){case CKEDITOR.ENLARGE_INLINE:var e=1;case CKEDITOR.ENLARGE_ELEMENT:var f= -function(a,g){var c=new CKEDITOR.dom.range(m);c.setStart(a,g);c.setEndAt(m,CKEDITOR.POSITION_BEFORE_END);var c=new CKEDITOR.dom.walker(c),d;for(c.guard=function(a){return!(a.type==CKEDITOR.NODE_ELEMENT&&a.isBlockBoundary())};d=c.next();){if(d.type!=CKEDITOR.NODE_TEXT)return!1;E=d!=a?d.getText():d.substring(g);if(b.test(E))return!1}return!0};if(this.collapsed)break;var h=this.getCommonAncestor(),m=this.root,k,l,q,v,B,D=!1,A,E;A=this.startContainer;var F=this.startOffset;A.type==CKEDITOR.NODE_TEXT? -(F&&(A=!CKEDITOR.tools.trim(A.substring(0,F)).length&&A,D=!!A),A&&((v=A.getPrevious())||(q=A.getParent()))):(F&&(v=A.getChild(F-1)||A.getLast()),v||(q=A));for(q=d(q);q||v;){if(q&&!v){!B&&q.equals(h)&&(B=!0);if(e?q.isBlockBoundary():!m.contains(q))break;D&&"inline"==q.getComputedStyle("display")||(D=!1,B?k=q:this.setStartBefore(q));v=q.getPrevious()}for(;v;)if(A=!1,v.type==CKEDITOR.NODE_COMMENT)v=v.getPrevious();else{if(v.type==CKEDITOR.NODE_TEXT)E=v.getText(),b.test(E)&&(v=null),A=/[\s\ufeff]$/.test(E); -else if((v.$.offsetWidth>(CKEDITOR.env.webkit?1:0)||c&&v.is("br"))&&!v.data("cke-bookmark"))if(D&&CKEDITOR.dtd.$removeEmpty[v.getName()]){E=v.getText();if(b.test(E))v=null;else for(var F=v.$.getElementsByTagName("*"),K=0,L;L=F[K++];)if(!CKEDITOR.dtd.$removeEmpty[L.nodeName.toLowerCase()]){v=null;break}v&&(A=!!E.length)}else v=null;A&&(D?B?k=q:q&&this.setStartBefore(q):D=!0);if(v){A=v.getPrevious();if(!q&&!A){q=v;v=null;break}v=A}else q=null}q&&(q=d(q.getParent()))}A=this.endContainer;F=this.endOffset; -q=v=null;B=D=!1;A.type==CKEDITOR.NODE_TEXT?CKEDITOR.tools.trim(A.substring(F)).length?D=!0:(D=!A.getLength(),F==A.getLength()?(v=A.getNext())||(q=A.getParent()):f(A,F)&&(q=A.getParent())):(v=A.getChild(F))||(q=A);for(;q||v;){if(q&&!v){!B&&q.equals(h)&&(B=!0);if(e?q.isBlockBoundary():!m.contains(q))break;D&&"inline"==q.getComputedStyle("display")||(D=!1,B?l=q:q&&this.setEndAfter(q));v=q.getNext()}for(;v;){A=!1;if(v.type==CKEDITOR.NODE_TEXT)E=v.getText(),f(v,0)||(v=null),A=/^[\s\ufeff]/.test(E);else if(v.type== -CKEDITOR.NODE_ELEMENT){if((0=h.getLength()?f.setStartAfter(h):(f.setStartBefore(h),d=0):f.setStartBefore(h));m&&m.type==CKEDITOR.NODE_TEXT&&(l?l>=m.getLength()?f.setEndAfter(m):(f.setEndAfter(m),q=0):f.setEndBefore(m));var f=new CKEDITOR.dom.walker(f),v=CKEDITOR.dom.walker.bookmark(),B=CKEDITOR.dom.walker.bogus();f.evaluator= -function(c){return c.type==(a==CKEDITOR.SHRINK_ELEMENT?CKEDITOR.NODE_ELEMENT:CKEDITOR.NODE_TEXT)};var D;f.guard=function(c,d){if(e&&B(c)||v(c))return!0;if(a==CKEDITOR.SHRINK_ELEMENT&&c.type==CKEDITOR.NODE_TEXT||d&&c.equals(D)||!1===b&&c.type==CKEDITOR.NODE_ELEMENT&&c.isBlockBoundary()||c.type==CKEDITOR.NODE_ELEMENT&&c.hasAttribute("contenteditable"))return!1;d||c.type!=CKEDITOR.NODE_ELEMENT||(D=c);return!0};d&&(h=f[a==CKEDITOR.SHRINK_ELEMENT?"lastForward":"next"]())&&this.setStartAt(h,c?CKEDITOR.POSITION_AFTER_START: -CKEDITOR.POSITION_BEFORE_START);q&&(f.reset(),(f=f[a==CKEDITOR.SHRINK_ELEMENT?"lastBackward":"previous"]())&&this.setEndAt(f,c?CKEDITOR.POSITION_BEFORE_END:CKEDITOR.POSITION_AFTER_END));return!(!d&&!q)}},insertNode:function(a){this.optimizeBookmark();this.trim(!1,!0);var c=this.startContainer,d=c.getChild(this.startOffset);d?a.insertBefore(d):c.append(a);a.getParent()&&a.getParent().equals(this.endContainer)&&this.endOffset++;this.setStartBefore(a)},moveToPosition:function(a,c){this.setStartAt(a, +function(a,g){var c=new CKEDITOR.dom.range(h);c.setStart(a,g);c.setEndAt(h,CKEDITOR.POSITION_BEFORE_END);var c=new CKEDITOR.dom.walker(c),d;for(c.guard=function(a){return!(a.type==CKEDITOR.NODE_ELEMENT&&a.isBlockBoundary())};d=c.next();){if(d.type!=CKEDITOR.NODE_TEXT)return!1;E=d!=a?d.getText():d.substring(g);if(b.test(E))return!1}return!0};if(this.collapsed)break;var k=this.getCommonAncestor(),h=this.root,l,m,u,w,B,C=!1,A,E;A=this.startContainer;var F=this.startOffset;A.type==CKEDITOR.NODE_TEXT? +(F&&(A=!CKEDITOR.tools.trim(A.substring(0,F)).length&&A,C=!!A),A&&((w=A.getPrevious())||(u=A.getParent()))):(F&&(w=A.getChild(F-1)||A.getLast()),w||(u=A));for(u=d(u);u||w;){if(u&&!w){!B&&u.equals(k)&&(B=!0);if(e?u.isBlockBoundary():!h.contains(u))break;C&&"inline"==u.getComputedStyle("display")||(C=!1,B?l=u:this.setStartBefore(u));w=u.getPrevious()}for(;w;)if(A=!1,w.type==CKEDITOR.NODE_COMMENT)w=w.getPrevious();else{if(w.type==CKEDITOR.NODE_TEXT)E=w.getText(),b.test(E)&&(w=null),A=/[\s\ufeff]$/.test(E); +else if((w.$.offsetWidth>(CKEDITOR.env.webkit?1:0)||c&&w.is("br"))&&!w.data("cke-bookmark"))if(C&&CKEDITOR.dtd.$removeEmpty[w.getName()]){E=w.getText();if(b.test(E))w=null;else for(var F=w.$.getElementsByTagName("*"),K=0,M;M=F[K++];)if(!CKEDITOR.dtd.$removeEmpty[M.nodeName.toLowerCase()]){w=null;break}w&&(A=!!E.length)}else w=null;A&&(C?B?l=u:u&&this.setStartBefore(u):C=!0);if(w){A=w.getPrevious();if(!u&&!A){u=w;w=null;break}w=A}else u=null}u&&(u=d(u.getParent()))}A=this.endContainer;F=this.endOffset; +u=w=null;B=C=!1;A.type==CKEDITOR.NODE_TEXT?CKEDITOR.tools.trim(A.substring(F)).length?C=!0:(C=!A.getLength(),F==A.getLength()?(w=A.getNext())||(u=A.getParent()):f(A,F)&&(u=A.getParent())):(w=A.getChild(F))||(u=A);for(;u||w;){if(u&&!w){!B&&u.equals(k)&&(B=!0);if(e?u.isBlockBoundary():!h.contains(u))break;C&&"inline"==u.getComputedStyle("display")||(C=!1,B?m=u:u&&this.setEndAfter(u));w=u.getNext()}for(;w;){A=!1;if(w.type==CKEDITOR.NODE_TEXT)E=w.getText(),f(w,0)||(w=null),A=/^[\s\ufeff]/.test(E);else if(w.type== +CKEDITOR.NODE_ELEMENT){if((0=k.getLength()?f.setStartAfter(k):(f.setStartBefore(k),d=0):f.setStartBefore(k));h&&h.type==CKEDITOR.NODE_TEXT&&(m?m>=h.getLength()?f.setEndAfter(h):(f.setEndAfter(h),u=0):f.setEndBefore(h));var f=new CKEDITOR.dom.walker(f),w=CKEDITOR.dom.walker.bookmark(),B=CKEDITOR.dom.walker.bogus();f.evaluator= +function(c){return c.type==(a==CKEDITOR.SHRINK_ELEMENT?CKEDITOR.NODE_ELEMENT:CKEDITOR.NODE_TEXT)};var C;f.guard=function(c,d){if(e&&B(c)||w(c))return!0;if(a==CKEDITOR.SHRINK_ELEMENT&&c.type==CKEDITOR.NODE_TEXT||d&&c.equals(C)||!1===b&&c.type==CKEDITOR.NODE_ELEMENT&&c.isBlockBoundary()||c.type==CKEDITOR.NODE_ELEMENT&&c.hasAttribute("contenteditable"))return!1;d||c.type!=CKEDITOR.NODE_ELEMENT||(C=c);return!0};d&&(k=f[a==CKEDITOR.SHRINK_ELEMENT?"lastForward":"next"]())&&this.setStartAt(k,c?CKEDITOR.POSITION_AFTER_START: +CKEDITOR.POSITION_BEFORE_START);u&&(f.reset(),(f=f[a==CKEDITOR.SHRINK_ELEMENT?"lastBackward":"previous"]())&&this.setEndAt(f,c?CKEDITOR.POSITION_BEFORE_END:CKEDITOR.POSITION_AFTER_END));return!(!d&&!u)}},insertNode:function(a){this.optimizeBookmark();this.trim(!1,!0);var c=this.startContainer,d=c.getChild(this.startOffset);d?a.insertBefore(d):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);b(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);b(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)}b(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)}b(this)},fixBlock:function(a,c){var d=this.createBookmark(),b=this.document.createElement(c);this.collapse(a);this.enlarge(CKEDITOR.ENLARGE_BLOCK_CONTENTS);this.extractContents().appendTo(b);b.trim();this.insertNode(b);var e=b.getBogus();e&&e.remove();b.appendBogus();this.moveToBookmark(d);return b},splitBlock:function(a,c){var d= -new CKEDITOR.dom.elementPath(this.startContainer,this.root),b=new CKEDITOR.dom.elementPath(this.endContainer,this.root),e=d.block,f=b.block,h=null;if(!d.blockLimit.equals(b.blockLimit))return null;"br"!=a&&(e||(e=this.fixBlock(!0,a),f=(new CKEDITOR.dom.elementPath(this.endContainer,this.root)).block),f||(f=this.fixBlock(!1,a)));d=e&&this.checkStartOfBlock();b=f&&this.checkEndOfBlock();this.deleteContents();e&&e.equals(f)&&(b?(h=new CKEDITOR.dom.elementPath(this.startContainer,this.root),this.moveToPosition(f, -CKEDITOR.POSITION_AFTER_END),f=null):d?(h=new CKEDITOR.dom.elementPath(this.startContainer,this.root),this.moveToPosition(e,CKEDITOR.POSITION_BEFORE_START),e=null):(f=this.splitElement(e,c||!1),e.is("ul","ol")||e.appendBogus()));return{previousBlock:e,nextBlock:f,wasStartOfBlock:d,wasEndOfBlock:b,elementPath:h}},splitElement:function(a,c){if(!this.collapsed)return null;this.setEndAt(a,CKEDITOR.POSITION_BEFORE_END);var d=this.extractContents(!1,c||!1),b=a.clone(!1,c||!1);d.appendTo(b);b.insertAfter(a); +new CKEDITOR.dom.elementPath(this.startContainer,this.root),b=new CKEDITOR.dom.elementPath(this.endContainer,this.root),e=d.block,f=b.block,k=null;if(!d.blockLimit.equals(b.blockLimit))return null;"br"!=a&&(e||(e=this.fixBlock(!0,a),f=(new CKEDITOR.dom.elementPath(this.endContainer,this.root)).block),f||(f=this.fixBlock(!1,a)));d=e&&this.checkStartOfBlock();b=f&&this.checkEndOfBlock();this.deleteContents();e&&e.equals(f)&&(b?(k=new CKEDITOR.dom.elementPath(this.startContainer,this.root),this.moveToPosition(f, +CKEDITOR.POSITION_AFTER_END),f=null):d?(k=new CKEDITOR.dom.elementPath(this.startContainer,this.root),this.moveToPosition(e,CKEDITOR.POSITION_BEFORE_START),e=null):(f=this.splitElement(e,c||!1),e.is("ul","ol")||e.appendBogus()));return{previousBlock:e,nextBlock:f,wasStartOfBlock:d,wasEndOfBlock:b,elementPath:k}},splitElement:function(a,c){if(!this.collapsed)return null;this.setEndAt(a,CKEDITOR.POSITION_BEFORE_END);var d=this.extractContents(!1,c||!1),b=a.clone(!1,c||!1);d.appendTo(b);b.insertAfter(a); this.moveToPosition(a,CKEDITOR.POSITION_AFTER_END);return b},removeEmptyBlocksAtEnd:function(){function a(g){return function(a){return c(a)||d(a)||a.type==CKEDITOR.NODE_ELEMENT&&a.isEmptyInlineRemoveable()||g.is("table")&&a.is("caption")?!1:!0}}var c=CKEDITOR.dom.walker.whitespaces(),d=CKEDITOR.dom.walker.bookmark(!1);return function(c){for(var d=this.createBookmark(),b=this[c?"endPath":"startPath"](),e=b.block||b.blockLimit,f;e&&!e.equals(b.root)&&!e.getFirst(a(e));)f=e.getParent(),this[c?"setEndAt": "setStartAt"](e,CKEDITOR.POSITION_AFTER_END),e.remove(1),e=f;this.moveToBookmark(d)}}(),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 d=c==CKEDITOR.START,b=this.clone();b.collapse(d);b[d?"setStartAt":"setEndAt"](a,d?CKEDITOR.POSITION_AFTER_START:CKEDITOR.POSITION_BEFORE_END);b=new CKEDITOR.dom.walker(b);b.evaluator=e(d);return b[d? -"checkBackward":"checkForward"]()},checkStartOfBlock:function(a){var c=this.startContainer,d=this.startOffset;CKEDITOR.env.ie&&d&&c.type==CKEDITOR.NODE_TEXT&&(c=CKEDITOR.tools.ltrim(c.substring(0,d)),l.test(c)&&this.trim(0,1));a||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=f();return a.checkBackward()},checkEndOfBlock:function(a){var c= -this.endContainer,d=this.endOffset;CKEDITOR.env.ie&&c.type==CKEDITOR.NODE_TEXT&&(c=CKEDITOR.tools.rtrim(c.substring(d)),l.test(c)&&this.trim(1,0));a||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=f();return a.checkForward()},getPreviousNode:function(a,c,d){var b=this.clone();b.collapse(1);b.setStartAt(d||this.root,CKEDITOR.POSITION_AFTER_START); +"checkBackward":"checkForward"]()},checkStartOfBlock:function(a){var c=this.startContainer,d=this.startOffset;CKEDITOR.env.ie&&d&&c.type==CKEDITOR.NODE_TEXT&&(c=CKEDITOR.tools.ltrim(c.substring(0,d)),m.test(c)&&this.trim(0,1));a||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=f();return a.checkBackward()},checkEndOfBlock:function(a){var c= +this.endContainer,d=this.endOffset;CKEDITOR.env.ie&&c.type==CKEDITOR.NODE_TEXT&&(c=CKEDITOR.tools.rtrim(c.substring(d)),m.test(c)&&this.trim(1,0));a||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=f();return a.checkForward()},getPreviousNode:function(a,c,d){var b=this.clone();b.collapse(1);b.setStartAt(d||this.root,CKEDITOR.POSITION_AFTER_START); d=new CKEDITOR.dom.walker(b);d.evaluator=a;d.guard=c;return d.previous()},getNextNode:function(a,c,d){var b=this.clone();b.collapse();b.setEndAt(d||this.root,CKEDITOR.POSITION_BEFORE_END);d=new CKEDITOR.dom.walker(b);d.evaluator=a;d.guard=c;return d.next()},checkReadOnly:function(){function a(c,g){for(;c;){if(c.type==CKEDITOR.NODE_ELEMENT){if("false"==c.getAttribute("contentEditable")&&!c.data("cke-editable"))return 0;if(c.is("html")||"true"==c.getAttribute("contentEditable")&&(c.contains(g)||c.equals(g)))break}c= -c.getParent()}return 1}return function(){var c=this.startContainer,d=this.endContainer;return!(a(c,d)&&a(d,c))}}(),moveToElementEditablePosition:function(a,c){if(a.type==CKEDITOR.NODE_ELEMENT&&!a.isEditable(!1))return this.moveToPosition(a,c?CKEDITOR.POSITION_AFTER_END:CKEDITOR.POSITION_BEFORE_START),!0;for(var b=0;a;){if(a.type==CKEDITOR.NODE_TEXT){c&&this.endContainer&&this.checkEndOfBlock()&&l.test(a.getText())?this.moveToPosition(a,CKEDITOR.POSITION_BEFORE_START):this.moveToPosition(a,c?CKEDITOR.POSITION_AFTER_END: -CKEDITOR.POSITION_BEFORE_START);b=1;break}if(a.type==CKEDITOR.NODE_ELEMENT)if(a.isEditable())this.moveToPosition(a,c?CKEDITOR.POSITION_BEFORE_END:CKEDITOR.POSITION_AFTER_START),b=1;else if(c&&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,f=b,h=void 0;e.type==CKEDITOR.NODE_ELEMENT&&e.isEditable(!1)&& -(h=e[c?"getLast":"getFirst"](d));f||h||(h=e[c?"getPrevious":"getNext"](d));a=h}return!!b},moveToClosestEditablePosition:function(a,c){var d,b=0,e,f,h=[CKEDITOR.POSITION_AFTER_END,CKEDITOR.POSITION_BEFORE_START];a?(d=new CKEDITOR.dom.range(this.root),d.moveToPosition(a,h[c?0:1])):d=this.clone();if(a&&!a.is(CKEDITOR.dtd.$block))b=1;else if(e=d[c?"getNextEditableNode":"getPreviousEditableNode"]())b=1,(f=e.type==CKEDITOR.NODE_ELEMENT)&&e.is(CKEDITOR.dtd.$block)&&"false"==e.getAttribute("contenteditable")? -(d.setStartAt(e,CKEDITOR.POSITION_BEFORE_START),d.setEndAt(e,CKEDITOR.POSITION_AFTER_END)):!CKEDITOR.env.needsBrFiller&&f&&e.is(CKEDITOR.dom.walker.validEmptyBlockContainers)?(d.setEnd(e,0),d.collapse()):d.moveToPosition(e,h[c?1:0]);b&&this.moveToRange(d);return!!b},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!= +c.getParent()}return 1}return function(){var c=this.startContainer,d=this.endContainer;return!(a(c,d)&&a(d,c))}}(),moveToElementEditablePosition:function(a,c){if(a.type==CKEDITOR.NODE_ELEMENT&&!a.isEditable(!1))return this.moveToPosition(a,c?CKEDITOR.POSITION_AFTER_END:CKEDITOR.POSITION_BEFORE_START),!0;for(var b=0;a;){if(a.type==CKEDITOR.NODE_TEXT){c&&this.endContainer&&this.checkEndOfBlock()&&m.test(a.getText())?this.moveToPosition(a,CKEDITOR.POSITION_BEFORE_START):this.moveToPosition(a,c?CKEDITOR.POSITION_AFTER_END: +CKEDITOR.POSITION_BEFORE_START);b=1;break}if(a.type==CKEDITOR.NODE_ELEMENT)if(a.isEditable())this.moveToPosition(a,c?CKEDITOR.POSITION_BEFORE_END:CKEDITOR.POSITION_AFTER_START),b=1;else if(c&&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,f=b,k=void 0;e.type==CKEDITOR.NODE_ELEMENT&&e.isEditable(!1)&& +(k=e[c?"getLast":"getFirst"](d));f||k||(k=e[c?"getPrevious":"getNext"](d));a=k}return!!b},moveToClosestEditablePosition:function(a,c){var d,b=0,e,f,k=[CKEDITOR.POSITION_AFTER_END,CKEDITOR.POSITION_BEFORE_START];a?(d=new CKEDITOR.dom.range(this.root),d.moveToPosition(a,k[c?0:1])):d=this.clone();if(a&&!a.is(CKEDITOR.dtd.$block))b=1;else if(e=d[c?"getNextEditableNode":"getPreviousEditableNode"]())b=1,(f=e.type==CKEDITOR.NODE_ELEMENT)&&e.is(CKEDITOR.dtd.$block)&&"false"==e.getAttribute("contenteditable")? +(d.setStartAt(e,CKEDITOR.POSITION_BEFORE_START),d.setEndAt(e,CKEDITOR.POSITION_AFTER_END)):!CKEDITOR.env.needsBrFiller&&f&&e.is(CKEDITOR.dom.walker.validEmptyBlockContainers)?(d.setEnd(e,0),d.collapse()):d.moveToPosition(e,k[c?1:0]);b&&this.moveToRange(d);return!!b},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),d=CKEDITOR.dom.walker.whitespaces(!0);a.evaluator=function(a){return d(a)&&c(a)};var b=a.next();a.reset();return b&&b.equals(a.previous())?b: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:a(),getPreviousEditableNode:a(1),_getTableElement:function(a){a=a||{td:1,th:1,tr:1,tbody:1,thead:1,tfoot:1,table:1};var c=this.getTouchedStartNode(),d=this.getTouchedEndNode(),b=c.getAscendant("table",!0),d=d.getAscendant("table",!0);return b&&!this.root.contains(b)?null:this.getEnclosedNode()?this.getEnclosedNode().getAscendant(a,!0):b&&d&&(b.equals(d)||b.contains(d)||d.contains(b))?c.getAscendant(a,!0):null},scrollIntoView:function(){var a= new CKEDITOR.dom.element.createFromHtml("\x3cspan\x3e\x26nbsp;\x3c/span\x3e",this.document),c,d,b,e=this.clone();e.optimize();(b=e.startContainer.type==CKEDITOR.NODE_TEXT)?(d=e.startContainer.getText(),c=e.startContainer.split(e.startOffset),a.insertAfter(e.startContainer)):e.insertNode(a);a.scrollIntoView();b&&(e.startContainer.setText(d),c.remove());a.remove()},getClientRects:function(){function a(c,d){var g=CKEDITOR.tools.array.map(c,function(a){return a}),b=new CKEDITOR.dom.range(d.root),e,f, @@ -189,636 +189,645 @@ function(c,e){var f=CKEDITOR.tools.objectCompare(a[b],c);f||(f=CKEDITOR.tools.ob 1),e.insertAfter(g)),d.setStart(e.$,0),d.setEnd(e.$,0),a=d.getClientRects(),e.remove()):g.startContainer instanceof CKEDITOR.dom.text&&(""===g.startContainer.getText()?(g.startContainer.setText("​"),a=d.getClientRects(),g.startContainer.setText("")):a=[b(g.createBookmark())]):a=[b(g.createBookmark())];return a}function d(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 b(a){var c=a.startNode;a=a.endNode;var d;c.setText("​");c.removeStyle("display");a?(a.setText("​"),a.removeStyle("display"),d=[c.getClientRect(),a.getClientRect()],a.remove()):d=[c.getClientRect(),c.getClientRect()];c.remove();return{right:Math.max(d[0].right,d[1].right),bottom:Math.max(d[0].bottom,d[1].bottom),left:Math.min(d[0].left,d[1].left),top:Math.min(d[0].top,d[1].top),width:Math.abs(d[0].left-d[1].left),height:Math.max(d[0].bottom,d[1].bottom)-Math.min(d[0].top,d[1].top)}} return void 0!==this.document.getSelection?function(b){var e=this.root.getDocument().$.createRange(),f;e.setStart(this.startContainer.$,this.startOffset);e.setEnd(this.endContainer.$,this.endOffset);f=e.getClientRects();f=a(f,this);f.length||(f=c(f,e,this));return CKEDITOR.tools.array.map(f,function(a){return d(a,b,this)},this)}:function(a){return[d(b(this.createBookmark()),a,this)]}}(),_setStartContainer:function(a){this.startContainer=a},_setEndContainer:function(a){this.endContainer=a},_find:function(a, -c){var d=this.getCommonAncestor(),b=this.getBoundaryNodes(),e=[],f,h,m,k;if(d&&d.find)for(h=d.find(a),f=0;farguments.length||(this.range=a,this.forceBrBreak=0,this.enlargeBr=1,this.enforceRealBlocks=0,this._||(this._={}))}function h(a){var c=[];a.forEach(function(a){if("true"==a.getAttribute("contenteditable"))return c.push(a),!1},CKEDITOR.NODE_ELEMENT,!0);return c}function f(a,c,b,e){a:{null== -e&&(e=h(b));for(var m;m=e.shift();)if(m.getDtd().p){e={element:m,remaining:e};break a}e=null}if(!e)return 0;if((m=CKEDITOR.filter.instances[e.element.data("cke-filter")])&&!m.check(c))return f(a,c,b,e.remaining);c=new CKEDITOR.dom.range(e.element);c.selectNodeContents(e.element);c=c.createIterator();c.enlargeBr=a.enlargeBr;c.enforceRealBlocks=a.enforceRealBlocks;c.activeFilter=c.filter=m;a._.nestedEditable={element:e.element,container:b,remaining:e.remaining,iterator:c};return 1}function e(a,c,b){if(!c)return!1; -a=a.clone();a.collapse(!b);return a.checkBoundaryOfElement(c,b?CKEDITOR.START:CKEDITOR.END)}var a=/^[\r\n\t ]+$/,m=CKEDITOR.dom.walker.bookmark(!1,!0),k=CKEDITOR.dom.walker.whitespaces(!0),l=function(a){return m(a)&&k(a)},c={dd:1,dt:1,li:1};b.prototype={getNextParagraph:function(d){var g,b,h,k,p;d=d||"p";if(this._.nestedEditable){if(g=this._.nestedEditable.iterator.getNextParagraph(d))return this.activeFilter=this._.nestedEditable.iterator.activeFilter,g;this.activeFilter=this.filter;if(f(this,d, -this._.nestedEditable.container,this._.nestedEditable.remaining))return this.activeFilter=this._.nestedEditable.iterator.activeFilter,this._.nestedEditable.iterator.getNextParagraph(d);this._.nestedEditable=null}if(!this.range.root.getDtd()[d])return null;if(!this._.started){var t=this.range.clone();b=t.startPath();var r=t.endPath(),x=!t.collapsed&&e(t,b.block),u=!t.collapsed&&e(t,r.block,1);t.shrink(CKEDITOR.SHRINK_ELEMENT,!0);x&&t.setStartAt(b.block,CKEDITOR.POSITION_BEFORE_END);u&&t.setEndAt(r.block, -CKEDITOR.POSITION_AFTER_START);b=t.endContainer.hasAscendant("pre",!0)||t.startContainer.hasAscendant("pre",!0);t.enlarge(this.forceBrBreak&&!b||!this.enlargeBr?CKEDITOR.ENLARGE_LIST_ITEM_CONTENTS:CKEDITOR.ENLARGE_BLOCK_CONTENTS);t.collapsed||(b=new CKEDITOR.dom.walker(t.clone()),r=CKEDITOR.dom.walker.bookmark(!0,!0),b.evaluator=r,this._.nextNode=b.next(),b=new CKEDITOR.dom.walker(t.clone()),b.evaluator=r,b=b.previous(),this._.lastNode=b.getNextSourceNode(!0,null,t.root),this._.lastNode&&this._.lastNode.type== -CKEDITOR.NODE_TEXT&&!CKEDITOR.tools.trim(this._.lastNode.getText())&&this._.lastNode.getParent().isBlockBoundary()&&(r=this.range.clone(),r.moveToPosition(this._.lastNode,CKEDITOR.POSITION_AFTER_END),r.checkEndOfBlock()&&(r=new CKEDITOR.dom.elementPath(r.endContainer,r.root),this._.lastNode=(r.block||r.blockLimit).getNextSourceNode(!0))),this._.lastNode&&t.root.contains(this._.lastNode)||(this._.lastNode=this._.docEndMarker=t.document.createText(""),this._.lastNode.insertAfter(b)),t=null);this._.started= -1;b=t}r=this._.nextNode;t=this._.lastNode;for(this._.nextNode=null;r;){var x=0,u=r.hasAscendant("pre"),z=r.type!=CKEDITOR.NODE_ELEMENT,q=0;if(z)r.type==CKEDITOR.NODE_TEXT&&a.test(r.getText())&&(z=0);else{var v=r.getName();if(CKEDITOR.dtd.$block[v]&&"false"==r.getAttribute("contenteditable")){g=r;f(this,d,g);break}else if(r.isBlockBoundary(this.forceBrBreak&&!u&&{br:1})){if("br"==v)z=1;else if(!b&&!r.getChildCount()&&"hr"!=v){g=r;h=r.equals(t);break}b&&(b.setEndAt(r,CKEDITOR.POSITION_BEFORE_START), -"br"!=v&&(this._.nextNode=r));x=1}else{if(r.getFirst()){b||(b=this.range.clone(),b.setStartAt(r,CKEDITOR.POSITION_BEFORE_START));r=r.getFirst();continue}z=1}}z&&!b&&(b=this.range.clone(),b.setStartAt(r,CKEDITOR.POSITION_BEFORE_START));h=(!x||z)&&r.equals(t);if(b&&!x)for(;!r.getNext(l)&&!h;){v=r.getParent();if(v.isBlockBoundary(this.forceBrBreak&&!u&&{br:1})){x=1;z=0;h||v.equals(t);b.setEndAt(v,CKEDITOR.POSITION_BEFORE_END);break}r=v;z=1;h=r.equals(t);q=1}z&&b.setEndAt(r,CKEDITOR.POSITION_AFTER_END); -r=this._getNextSourceNode(r,q,t);if((h=!r)||x&&b)break}if(!g){if(!b)return this._.docEndMarker&&this._.docEndMarker.remove(),this._.nextNode=null;g=new CKEDITOR.dom.elementPath(b.startContainer,b.root);r=g.blockLimit;x={div:1,th:1,td:1};g=g.block;!g&&r&&!this.enforceRealBlocks&&x[r.getName()]&&b.checkStartOfBlock()&&b.checkEndOfBlock()&&!r.equals(b.root)?g=r:!g||this.enforceRealBlocks&&g.is(c)?(g=this.range.document.createElement(d),b.extractContents().appendTo(g),g.trim(),b.insertNode(g),k=p=!0): -"li"!=g.getName()?b.checkStartOfBlock()&&b.checkEndOfBlock()||(g=g.clone(!1),b.extractContents().appendTo(g),g.trim(),p=b.splitBlock(),k=!p.wasStartOfBlock,p=!p.wasEndOfBlock,b.insertNode(g)):h||(this._.nextNode=g.equals(t)?null:this._getNextSourceNode(b.getBoundaryNodes().endNode,1,t))}k&&(k=g.getPrevious())&&k.type==CKEDITOR.NODE_ELEMENT&&("br"==k.getName()?k.remove():k.getLast()&&"br"==k.getLast().$.nodeName.toLowerCase()&&k.getLast().remove());p&&(k=g.getLast())&&k.type==CKEDITOR.NODE_ELEMENT&& -"br"==k.getName()&&(!CKEDITOR.env.needsBrFiller||k.getPrevious(m)||k.getNext(m))&&k.remove();this._.nextNode||(this._.nextNode=h||g.equals(t)||!t?null:this._getNextSourceNode(g,1,t));return g},_getNextSourceNode:function(a,c,b){function e(a){return!(a.equals(b)||a.equals(f))}var f=this.range.root;for(a=a.getNextSourceNode(c,null,e);!m(a);)a=a.getNextSourceNode(c,null,e);return a}};CKEDITOR.dom.range.prototype.createIterator=function(){return new b(this)}}(),CKEDITOR.command=function(b,h){this.uiItems= +e&&(e=h(b));for(var k;k=e.shift();)if(k.getDtd().p){e={element:k,remaining:e};break a}e=null}if(!e)return 0;if((k=CKEDITOR.filter.instances[e.element.data("cke-filter")])&&!k.check(c))return f(a,c,b,e.remaining);c=new CKEDITOR.dom.range(e.element);c.selectNodeContents(e.element);c=c.createIterator();c.enlargeBr=a.enlargeBr;c.enforceRealBlocks=a.enforceRealBlocks;c.activeFilter=c.filter=k;a._.nestedEditable={element:e.element,container:b,remaining:e.remaining,iterator:c};return 1}function e(a,c,b){if(!c)return!1; +a=a.clone();a.collapse(!b);return a.checkBoundaryOfElement(c,b?CKEDITOR.START:CKEDITOR.END)}var a=/^[\r\n\t ]+$/,k=CKEDITOR.dom.walker.bookmark(!1,!0),l=CKEDITOR.dom.walker.whitespaces(!0),m=function(a){return k(a)&&l(a)},c={dd:1,dt:1,li:1};b.prototype={getNextParagraph:function(d){var g,b,h,l,p;d=d||"p";if(this._.nestedEditable){if(g=this._.nestedEditable.iterator.getNextParagraph(d))return this.activeFilter=this._.nestedEditable.iterator.activeFilter,g;this.activeFilter=this.filter;if(f(this,d, +this._.nestedEditable.container,this._.nestedEditable.remaining))return this.activeFilter=this._.nestedEditable.iterator.activeFilter,this._.nestedEditable.iterator.getNextParagraph(d);this._.nestedEditable=null}if(!this.range.root.getDtd()[d])return null;if(!this._.started){var q=this.range.clone();b=q.startPath();var r=q.endPath(),x=!q.collapsed&&e(q,b.block),t=!q.collapsed&&e(q,r.block,1);q.shrink(CKEDITOR.SHRINK_ELEMENT,!0);x&&q.setStartAt(b.block,CKEDITOR.POSITION_BEFORE_END);t&&q.setEndAt(r.block, +CKEDITOR.POSITION_AFTER_START);b=q.endContainer.hasAscendant("pre",!0)||q.startContainer.hasAscendant("pre",!0);q.enlarge(this.forceBrBreak&&!b||!this.enlargeBr?CKEDITOR.ENLARGE_LIST_ITEM_CONTENTS:CKEDITOR.ENLARGE_BLOCK_CONTENTS);q.collapsed||(b=new CKEDITOR.dom.walker(q.clone()),r=CKEDITOR.dom.walker.bookmark(!0,!0),b.evaluator=r,this._.nextNode=b.next(),b=new CKEDITOR.dom.walker(q.clone()),b.evaluator=r,b=b.previous(),this._.lastNode=b.getNextSourceNode(!0,null,q.root),this._.lastNode&&this._.lastNode.type== +CKEDITOR.NODE_TEXT&&!CKEDITOR.tools.trim(this._.lastNode.getText())&&this._.lastNode.getParent().isBlockBoundary()&&(r=this.range.clone(),r.moveToPosition(this._.lastNode,CKEDITOR.POSITION_AFTER_END),r.checkEndOfBlock()&&(r=new CKEDITOR.dom.elementPath(r.endContainer,r.root),this._.lastNode=(r.block||r.blockLimit).getNextSourceNode(!0))),this._.lastNode&&q.root.contains(this._.lastNode)||(this._.lastNode=this._.docEndMarker=q.document.createText(""),this._.lastNode.insertAfter(b)),q=null);this._.started= +1;b=q}r=this._.nextNode;q=this._.lastNode;for(this._.nextNode=null;r;){var x=0,t=r.hasAscendant("pre"),z=r.type!=CKEDITOR.NODE_ELEMENT,u=0;if(z)r.type==CKEDITOR.NODE_TEXT&&a.test(r.getText())&&(z=0);else{var w=r.getName();if(CKEDITOR.dtd.$block[w]&&"false"==r.getAttribute("contenteditable")){g=r;f(this,d,g);break}else if(r.isBlockBoundary(this.forceBrBreak&&!t&&{br:1})){if("br"==w)z=1;else if(!b&&!r.getChildCount()&&"hr"!=w){g=r;h=r.equals(q);break}b&&(b.setEndAt(r,CKEDITOR.POSITION_BEFORE_START), +"br"!=w&&(this._.nextNode=r));x=1}else{if(r.getFirst()){b||(b=this.range.clone(),b.setStartAt(r,CKEDITOR.POSITION_BEFORE_START));r=r.getFirst();continue}z=1}}z&&!b&&(b=this.range.clone(),b.setStartAt(r,CKEDITOR.POSITION_BEFORE_START));h=(!x||z)&&r.equals(q);if(b&&!x)for(;!r.getNext(m)&&!h;){w=r.getParent();if(w.isBlockBoundary(this.forceBrBreak&&!t&&{br:1})){x=1;z=0;h||w.equals(q);b.setEndAt(w,CKEDITOR.POSITION_BEFORE_END);break}r=w;z=1;h=r.equals(q);u=1}z&&b.setEndAt(r,CKEDITOR.POSITION_AFTER_END); +r=this._getNextSourceNode(r,u,q);if((h=!r)||x&&b)break}if(!g){if(!b)return this._.docEndMarker&&this._.docEndMarker.remove(),this._.nextNode=null;g=new CKEDITOR.dom.elementPath(b.startContainer,b.root);r=g.blockLimit;x={div:1,th:1,td:1};g=g.block;!g&&r&&!this.enforceRealBlocks&&x[r.getName()]&&b.checkStartOfBlock()&&b.checkEndOfBlock()&&!r.equals(b.root)?g=r:!g||this.enforceRealBlocks&&g.is(c)?(g=this.range.document.createElement(d),b.extractContents().appendTo(g),g.trim(),b.insertNode(g),l=p=!0): +"li"!=g.getName()?b.checkStartOfBlock()&&b.checkEndOfBlock()||(g=g.clone(!1),b.extractContents().appendTo(g),g.trim(),p=b.splitBlock(),l=!p.wasStartOfBlock,p=!p.wasEndOfBlock,b.insertNode(g)):h||(this._.nextNode=g.equals(q)?null:this._getNextSourceNode(b.getBoundaryNodes().endNode,1,q))}l&&(l=g.getPrevious())&&l.type==CKEDITOR.NODE_ELEMENT&&("br"==l.getName()?l.remove():l.getLast()&&"br"==l.getLast().$.nodeName.toLowerCase()&&l.getLast().remove());p&&(l=g.getLast())&&l.type==CKEDITOR.NODE_ELEMENT&& +"br"==l.getName()&&(!CKEDITOR.env.needsBrFiller||l.getPrevious(k)||l.getNext(k))&&l.remove();this._.nextNode||(this._.nextNode=h||g.equals(q)||!q?null:this._getNextSourceNode(g,1,q));return g},_getNextSourceNode:function(a,c,b){function e(a){return!(a.equals(b)||a.equals(f))}var f=this.range.root;for(a=a.getNextSourceNode(c,null,e);!k(a);)a=a.getNextSourceNode(c,null,e);return a}};CKEDITOR.dom.range.prototype.createIterator=function(){return new b(this)}}(),CKEDITOR.command=function(b,h){this.uiItems= [];this.exec=function(e){if(this.state==CKEDITOR.TRISTATE_DISABLED||!this.checkAllowed())return!1;this.editorFocus&&b.focus();return!1===this.fire("exec")?!0:!1!==h.exec.call(this,b,e)};this.refresh=function(b,a){if(!this.readOnly&&b.readOnly)return!0;if(this.context&&!a.isContextFor(this.context)||!this.checkAllowed(!0))return this.disable(),!0;this.startDisabled||this.enable();this.modes&&!this.modes[b.mode]&&this.disable();return!1===this.fire("refresh",{editor:b,path:a})?!0:h.refresh&&!1!==h.refresh.apply(this, arguments)};var f;this.checkAllowed=function(e){return e||"boolean"!=typeof f?f=b.activeFilter.checkFeature(this):f};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(b){if(this.state==b||b!=CKEDITOR.TRISTATE_DISABLED&&!this.checkAllowed())return!1;this.previousState=this.state;this.state=b;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 b(a,c,d,b,g){var e,f;a=[];for(e in c){f=c[e];f="boolean"==typeof f? -{}:"function"==typeof f?{match:f}:K(f);"$"!=e.charAt(0)&&(f.elements=e);d&&(f.featureName=d.toLowerCase());var h=f;h.elements=k(h.elements,/\s+/)||null;h.propertiesOnly=h.propertiesOnly||!0===h.elements;var m=/\s*,\s*/,n=void 0;for(n in O){h[n]=k(h[n],m)||null;var r=h,v=I[n],l=k(h[I[n]],m),G=h[n],H=[],t=!0,y=void 0;l?t=!1:l={};for(y in G)"!"==y.charAt(0)&&(y=y.slice(1),H.push(y),l[y]=!0,t=!1);for(;y=H.pop();)G[y]=G["!"+y],delete G["!"+y];r[v]=(t?!1:l)||null}h.match=h.match||null;b.push(f);a.push(f)}c= -g.elements;g=g.generic;var u;d=0;for(b=a.length;d=--c&&(m&&CKEDITOR.document.getDocumentElement().removeStyle("cursor"),n(b))},w=function(a,c){b[a]=1;var d=h[a];delete h[a];for(var g=0;g=CKEDITOR.env.version||CKEDITOR.env.ie9Compat)?d.$.onreadystatechange=function(){if("loaded"==d.$.readyState||"complete"== -d.$.readyState)d.$.onreadystatechange=null,w(a,!0)}:(d.$.onload=function(){setTimeout(function(){d.$.onload=null;d.$.onerror=null;w(a,!0)},0)},d.$.onerror=function(){d.$.onload=null;d.$.onerror=null;w(a,!1)}));d.appendTo(CKEDITOR.document.getHead())}}};m&&CKEDITOR.document.getDocumentElement().setStyle("cursor","wait");for(var t=0;t=--c&&(k&&CKEDITOR.document.getDocumentElement().removeStyle("cursor"),n(b))},v=function(a,c){b[a]=1;var d=h[a];delete h[a];for(var g=0;g=CKEDITOR.env.version||CKEDITOR.env.ie9Compat)?d.$.onreadystatechange=function(){if("loaded"==d.$.readyState||"complete"== +d.$.readyState)d.$.onreadystatechange=null,v(a,!0)}:(d.$.onload=function(){setTimeout(function(){d.$.onload=null;d.$.onerror=null;v(a,!0)},0)},d.$.onerror=function(){d.$.onload=null;d.$.onerror=null;v(a,!1)}));d.appendTo(CKEDITOR.document.getHead())}}};k&&CKEDITOR.document.getDocumentElement().setStyle("cursor","wait");for(var q=0;q]+)>)|(?:!--([\S|\s]*?)--!?>)|(?:([^\/\s>]+)((?:\s+[\w\-:.]+(?:\s*=\s*?(?:(?:"[^"]*")|(?:'[^']*')|[^\s"'\/>]+))?)*)[\S\s]*?(\/?)>))/g}}, -function(){var b=/([\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(f){for(var e,a,m=0,k;e=this._.htmlPartsRegex.exec(f);){a=e.index;if(a>m)if(m=f.substring(m,a),k)k.push(m);else this.onText(m); -m=this._.htmlPartsRegex.lastIndex;if(a=e[1])if(a=a.toLowerCase(),k&&CKEDITOR.dtd.$cdata[a]&&(this.onCDATA(k.join("")),k=null),!k){this.onTagClose(a);continue}if(k)k.push(e[0]);else if(a=e[3]){if(a=a.toLowerCase(),!/="/.test(a)){var l={},c,d=e[4];e=!!e[5];if(d)for(;c=b.exec(d);){var g=c[1].toLowerCase();c=c[2]||c[3]||c[4]||"";l[g]=!c&&h[g]?g:CKEDITOR.tools.htmlDecodeAttr(c)}this.onTagOpen(a,l,e);!k&&CKEDITOR.dtd.$cdata[a]&&(k=[])}}else if(a=e[2])this.onComment(a)}if(f.length>m)this.onText(f.substring(m, -f.length))}}}(),CKEDITOR.htmlParser.basicWriter=CKEDITOR.tools.createClass({$:function(){this._={output:[]}},proto:{openTag:function(b){this._.output.push("\x3c",b)},openTagClose:function(b,h){h?this._.output.push(" /\x3e"):this._.output.push("\x3e")},attribute:function(b,h){"string"==typeof h&&(h=CKEDITOR.tools.htmlEncodeAttr(h));this._.output.push(" ",b,'\x3d"',h,'"')},closeTag:function(b){this._.output.push("\x3c/",b,"\x3e")},text:function(b){this._.output.push(b)},comment:function(b){this._.output.push("\x3c!--", -b,"--\x3e")},write:function(b){this._.output.push(b)},reset:function(){this._.output=[];this._.indent=!1},getHtml:function(b){var h=this._.output.join("");b&&this.reset();return h}}}),"use strict",function(){CKEDITOR.htmlParser.node=function(){};CKEDITOR.htmlParser.node.prototype={remove:function(){var b=this.parent.children,h=CKEDITOR.tools.indexOf(b,this),f=this.previous,e=this.next;f&&(f.next=e);e&&(e.previous=f);b.splice(h,1);this.parent=null},replaceWith:function(b){var h=this.parent.children, -f=CKEDITOR.tools.indexOf(h,this),e=b.previous=this.previous,a=b.next=this.next;e&&(e.next=b);a&&(a.previous=b);h[f]=b;b.parent=this.parent;this.parent=null},insertAfter:function(b){var h=b.parent.children,f=CKEDITOR.tools.indexOf(h,b),e=b.next;h.splice(f+1,0,this);this.next=b.next;this.previous=b;b.next=this;e&&(e.previous=this);this.parent=b.parent},insertBefore:function(b){var h=b.parent.children,f=CKEDITOR.tools.indexOf(h,b);h.splice(f,0,this);this.next=b;(this.previous=b.previous)&&(b.previous.next= -this);b.previous=this;this.parent=b.parent},getAscendant:function(b){var h="function"==typeof b?b:"string"==typeof b?function(e){return e.name==b}:function(e){return e.name in b},f=this.parent;for(;f&&f.type==CKEDITOR.NODE_ELEMENT;){if(h(f))return f;f=f.parent}return null},wrapWith:function(b){this.replaceWith(b);b.add(this);return b},getIndex:function(){return CKEDITOR.tools.indexOf(this.parent.children,this)},getFilterContext:function(b){return b||{}}}}(),"use strict",CKEDITOR.htmlParser.comment= -function(b){this.value=b;this._={isBlockLike:!1}},CKEDITOR.htmlParser.comment.prototype=CKEDITOR.tools.extend(new CKEDITOR.htmlParser.node,{type:CKEDITOR.NODE_COMMENT,filter:function(b,h){var f=this.value;if(!(f=b.onComment(h,f,this)))return this.remove(),!1;if("string"!=typeof f)return this.replaceWith(f),!1;this.value=f;return!0},writeHtml:function(b,h){h&&this.filter(h);b.comment(this.value)}}),"use strict",function(){CKEDITOR.htmlParser.text=function(b){this.value=b;this._={isBlockLike:!1}};CKEDITOR.htmlParser.text.prototype= -CKEDITOR.tools.extend(new CKEDITOR.htmlParser.node,{type:CKEDITOR.NODE_TEXT,filter:function(b,h){if(!(this.value=b.onText(h,this.value,this)))return this.remove(),!1},writeHtml:function(b,h){h&&this.filter(h);b.text(this.value)}})}(),"use strict",function(){CKEDITOR.htmlParser.cdata=function(b){this.value=b};CKEDITOR.htmlParser.cdata.prototype=CKEDITOR.tools.extend(new CKEDITOR.htmlParser.node,{type:CKEDITOR.NODE_TEXT,filter:function(){},writeHtml:function(b){b.write(this.value)}})}(),"use strict", -CKEDITOR.htmlParser.fragment=function(){this.children=[];this.parent=null;this._={isBlockLike:!0,hasInlineStarted:!1}},function(){function b(a){return a.attributes["data-cke-survive"]?!1:"a"==a.name&&a.attributes.href||CKEDITOR.dtd.$removeEmpty[a.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),f={ol:1,ul:1},e=CKEDITOR.tools.extend({},{html:1},CKEDITOR.dtd.html,CKEDITOR.dtd.body,CKEDITOR.dtd.head,{style:1,script:1}),a={ul:"li", -ol:"li",dl:"dd",table:"tbody",tbody:"tr",thead:"tr",tfoot:"tr",tr:"td"};CKEDITOR.htmlParser.fragment.fromHtml=function(m,k,l){function c(a){var c;if(0k;k++)if(h=a[k]){h= -h.exec(b,e,this);if(!1===h)return null;if(h&&h!=e)return this.onNode(b,h);if(e.parent&&!e.name)break}return e},onNode:function(b,e){var a=e.type;return a==CKEDITOR.NODE_ELEMENT?this.onElement(b,e):a==CKEDITOR.NODE_TEXT?new CKEDITOR.htmlParser.text(this.onText(b,e.value,e)):a==CKEDITOR.NODE_COMMENT?new CKEDITOR.htmlParser.comment(this.onComment(b,e.value,e)):null},onAttribute:function(b,e,a,h){return(a=this.attributesRules[a])?a.exec(b,h,e,this):h}}});CKEDITOR.htmlParser.filterRulesGroup=b;b.prototype= -{add:function(b,e,a){this.rules.splice(this.findIndex(e),0,{value:b,priority:e,options:a})},addMany:function(b,e,a){for(var h=[this.findIndex(e),0],k=0,l=b.length;k/g,"\x26gt;")+"\x3c/textarea\x3e");return"\x3ccke:encoded\x3e"+encodeURIComponent(a)+"\x3c/cke:encoded\x3e"})}function n(a){return a.replace(I,function(a,c){return decodeURIComponent(c)})}function y(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 w(a){return a.replace(/\x3c!--\{cke_protected\}\{C\}([\s\S]+?)--\x3e/g,function(a,c){return decodeURIComponent(c)})}function p(a,c){var d=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 d&&d[c]||""})}function t(a,c){var d=[],b=c.config.protectedSource,g=c._.dataStore||(c._.dataStore= -{id:1}),e=/<\!--\{cke_temp(comment)?\}(\d*?)--\x3e/g,b=[/|$)/gi,//gi,//gi].concat(b);a=a.replace(/\x3c!--[\s\S]*?--\x3e/g,function(a){return"\x3c!--{cke_tempcomment}"+(d.push(a)-1)+"--\x3e"});for(var f=0;f]+\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,d,b,g){return"\x3c"+d+b+"\x3e"+p(w(g),c)+"\x3c/"+d+"\x3e"})}var r;CKEDITOR.htmlDataProcessor=function(a){var c, -e,f=this;this.editor=a;this.dataFilter=c=new CKEDITOR.htmlParser.filter;this.htmlFilter=e=new CKEDITOR.htmlParser.filter;this.writer=new CKEDITOR.htmlParser.basicWriter;c.addRules(B);c.addRules(D,{applyToAll:!0});c.addRules(b(a,"data"),{applyToAll:!0});e.addRules(A);e.addRules(E,{applyToAll:!0});e.addRules(b(a,"html"),{applyToAll:!0});a.on("toHtml",function(c){c=c.data;var b=c.dataValue,e,b=r(b),b=t(b,a),b=g(b,O),b=d(b),b=g(b,C),b=b.replace(M,"$1cke:$2"),b=b.replace(H,"\x3ccke:$1$2\x3e\x3c/cke:$1\x3e"), -b=b.replace(/(]*>)(\r\n|\n)/g,"$1$2$2"),b=b.replace(/([^a-z0-9<\-])(on\w{3,})(?!>)/gi,"$1data-cke-"+CKEDITOR.rnd+"-$2");e=c.context||a.editable().getName();var f;CKEDITOR.env.ie&&9>CKEDITOR.env.version&&"pre"==e&&(e="div",b="\x3cpre\x3e"+b+"\x3c/pre\x3e",f=1);e=a.document.createElement(e);e.setHtml("a"+b);b=e.getHtml().substr(1);b=b.replace(new RegExp("data-cke-"+CKEDITOR.rnd+"-","ig"),"");f&&(b=b.replace(/^
|<\/pre>$/gi,""));b=b.replace(Q,"$1$2");b=n(b);b=w(b);e=!1===c.fixForBody?!1:
+var c=CKEDITOR.dom.element.get(a);return c?c.getEditor()?(CKEDITOR.error("editor-element-conflict",{editorName:c.getEditor().name}),null):c:(CKEDITOR.error("editor-incorrect-element",{element:a}),null)};CKEDITOR.editor.initializeDelayedEditorCreation=function(a,c,d){if(c.delayIfDetached_callback)CKEDITOR.warn("editor-delayed-creation",{method:"callback"}),c.delayIfDetached_callback(function(){CKEDITOR[d](a,c);CKEDITOR.warn("editor-delayed-creation-success",{method:"callback"})});else{var g=void 0===
+c.delayIfDetached_interval?CKEDITOR.config.delayIfDetached_interval:c.delayIfDetached_interval,b;CKEDITOR.warn("editor-delayed-creation",{method:"interval - "+g+" ms"});b=setInterval(function(){a.isDetached()||(clearInterval(b),CKEDITOR[d](a,c),CKEDITOR.warn("editor-delayed-creation-success",{method:"interval - "+g+" ms"}))},g)}};CKEDITOR.editor.shouldDelayEditorCreation=function(a,c){CKEDITOR.editor.mergeDelayedCreationConfigs(c);return c&&c.delayIfDetached&&a.isDetached()};CKEDITOR.editor.mergeDelayedCreationConfigs=
+function(a){a&&(a.delayIfDetached="boolean"===typeof a.delayIfDetached?a.delayIfDetached:CKEDITOR.config.delayIfDetached,a.delayIfDetached_interval=isNaN(a.delayIfDetached_interval)?CKEDITOR.config.delayIfDetached_interval:a.delayIfDetached_interval,a.delayIfDetached_callback=a.delayIfDetached_callback||CKEDITOR.config.delayIfDetached_callback)}}(),CKEDITOR.ELEMENT_MODE_NONE=0,CKEDITOR.ELEMENT_MODE_REPLACE=1,CKEDITOR.ELEMENT_MODE_APPENDTO=2,CKEDITOR.ELEMENT_MODE_INLINE=3,CKEDITOR.config.delayIfDetached=
+!1,CKEDITOR.config.delayIfDetached_callback=void 0,CKEDITOR.config.delayIfDetached_interval=50,CKEDITOR.htmlParser=function(){this._={htmlPartsRegex:/<(?:(?:\/([^>]+)>)|(?:!--([\S|\s]*?)--!?>)|(?:([^\/\s>]+)((?:\s+[\w\-:.]+(?:\s*=\s*?(?:(?:"[^"]*")|(?:'[^']*')|[^\s"'\/>]+))?)*)[\S\s]*?(\/?)>))/g}},function(){var b=/([\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(f){for(var e,a,k=0,l;e=this._.htmlPartsRegex.exec(f);){a=e.index;if(a>k)if(k=f.substring(k,a),l)l.push(k);else this.onText(k);k=this._.htmlPartsRegex.lastIndex;if(a=e[1])if(a=a.toLowerCase(),l&&CKEDITOR.dtd.$cdata[a]&&(this.onCDATA(l.join("")),l=null),!l){this.onTagClose(a);continue}if(l)l.push(e[0]);else if(a=e[3]){if(a=
+a.toLowerCase(),!/="/.test(a)){var m={},c,d=e[4];e=!!e[5];if(d)for(;c=b.exec(d);){var g=c[1].toLowerCase();c=c[2]||c[3]||c[4]||"";m[g]=!c&&h[g]?g:CKEDITOR.tools.htmlDecodeAttr(c)}this.onTagOpen(a,m,e);!l&&CKEDITOR.dtd.$cdata[a]&&(l=[])}}else if(a=e[2])this.onComment(a)}if(f.length>k)this.onText(f.substring(k,f.length))}}}(),CKEDITOR.htmlParser.basicWriter=CKEDITOR.tools.createClass({$:function(){this._={output:[]}},proto:{openTag:function(b){this._.output.push("\x3c",b)},openTagClose:function(b,h){h?
+this._.output.push(" /\x3e"):this._.output.push("\x3e")},attribute:function(b,h){"string"==typeof h&&(h=CKEDITOR.tools.htmlEncodeAttr(h));this._.output.push(" ",b,'\x3d"',h,'"')},closeTag:function(b){this._.output.push("\x3c/",b,"\x3e")},text:function(b){this._.output.push(b)},comment:function(b){this._.output.push("\x3c!--",b,"--\x3e")},write:function(b){this._.output.push(b)},reset:function(){this._.output=[];this._.indent=!1},getHtml:function(b){var h=this._.output.join("");b&&this.reset();return h}}}),
+"use strict",function(){CKEDITOR.htmlParser.node=function(){};CKEDITOR.htmlParser.node.prototype={remove:function(){var b=this.parent.children,h=CKEDITOR.tools.indexOf(b,this),f=this.previous,e=this.next;f&&(f.next=e);e&&(e.previous=f);b.splice(h,1);this.parent=null},replaceWith:function(b){var h=this.parent.children,f=CKEDITOR.tools.indexOf(h,this),e=b.previous=this.previous,a=b.next=this.next;e&&(e.next=b);a&&(a.previous=b);h[f]=b;b.parent=this.parent;this.parent=null},insertAfter:function(b){var h=
+b.parent.children,f=CKEDITOR.tools.indexOf(h,b),e=b.next;h.splice(f+1,0,this);this.next=b.next;this.previous=b;b.next=this;e&&(e.previous=this);this.parent=b.parent},insertBefore:function(b){var h=b.parent.children,f=CKEDITOR.tools.indexOf(h,b);h.splice(f,0,this);this.next=b;(this.previous=b.previous)&&(b.previous.next=this);b.previous=this;this.parent=b.parent},getAscendant:function(b){var h="function"==typeof b?b:"string"==typeof b?function(e){return e.name==b}:function(e){return e.name in b},f=
+this.parent;for(;f&&f.type==CKEDITOR.NODE_ELEMENT;){if(h(f))return f;f=f.parent}return null},wrapWith:function(b){this.replaceWith(b);b.add(this);return b},getIndex:function(){return CKEDITOR.tools.indexOf(this.parent.children,this)},getFilterContext:function(b){return b||{}}}}(),"use strict",CKEDITOR.htmlParser.comment=function(b){this.value=b;this._={isBlockLike:!1}},CKEDITOR.htmlParser.comment.prototype=CKEDITOR.tools.extend(new CKEDITOR.htmlParser.node,{type:CKEDITOR.NODE_COMMENT,filter:function(b,
+h){var f=this.value;if(!(f=b.onComment(h,f,this)))return this.remove(),!1;if("string"!=typeof f)return this.replaceWith(f),!1;this.value=f;return!0},writeHtml:function(b,h){h&&this.filter(h);b.comment(this.value)}}),"use strict",function(){CKEDITOR.htmlParser.text=function(b){this.value=b;this._={isBlockLike:!1}};CKEDITOR.htmlParser.text.prototype=CKEDITOR.tools.extend(new CKEDITOR.htmlParser.node,{type:CKEDITOR.NODE_TEXT,filter:function(b,h){if(!(this.value=b.onText(h,this.value,this)))return this.remove(),
+!1},writeHtml:function(b,h){h&&this.filter(h);b.text(this.value)}})}(),"use strict",function(){CKEDITOR.htmlParser.cdata=function(b){this.value=b};CKEDITOR.htmlParser.cdata.prototype=CKEDITOR.tools.extend(new CKEDITOR.htmlParser.node,{type:CKEDITOR.NODE_TEXT,filter:function(b){var h=this.getAscendant("style");if(h&&h.getAscendant({math:1,svg:1})){var h=CKEDITOR.htmlParser.fragment.fromHtml(this.value),f=new CKEDITOR.htmlParser.basicWriter;b.applyTo(h);h.writeHtml(f);this.value=f.getHtml()}},writeHtml:function(b){b.write(this.value)}})}(),
+"use strict",CKEDITOR.htmlParser.fragment=function(){this.children=[];this.parent=null;this._={isBlockLike:!0,hasInlineStarted:!1}},function(){function b(a){return a.attributes["data-cke-survive"]?!1:"a"==a.name&&a.attributes.href||CKEDITOR.dtd.$removeEmpty[a.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),f={ol:1,ul:1},e=CKEDITOR.tools.extend({},{html:1},CKEDITOR.dtd.html,CKEDITOR.dtd.body,CKEDITOR.dtd.head,{style:1,script:1}),
+a={ul:"li",ol:"li",dl:"dd",table:"tbody",tbody:"tr",thead:"tr",tfoot:"tr",tr:"td"};CKEDITOR.htmlParser.fragment.fromHtml=function(k,l,m){function c(a){var c;if(0h;h++)if(k=a[h]){k=k.exec(b,e,this);if(!1===k)return null;if(k&&k!=e)return this.onNode(b,k);if(e.parent&&!e.name)break}return e},onNode:function(b,e){var a=e.type;return a==CKEDITOR.NODE_ELEMENT?this.onElement(b,e):a==CKEDITOR.NODE_TEXT?new CKEDITOR.htmlParser.text(this.onText(b,e.value,e)):a==CKEDITOR.NODE_COMMENT?new CKEDITOR.htmlParser.comment(this.onComment(b,e.value,e)):null},onAttribute:function(b,e,a,k){return(a=this.attributesRules[a])?a.exec(b,k,e,this):k}}});
+CKEDITOR.htmlParser.filterRulesGroup=b;b.prototype={add:function(b,e,a){this.rules.splice(this.findIndex(e),0,{value:b,priority:e,options:a})},addMany:function(b,e,a){for(var k=[this.findIndex(e),0],h=0,m=b.length;h/g,"\x26gt;")+"\x3c/textarea\x3e");return"\x3ccke:encoded\x3e"+encodeURIComponent(a)+"\x3c/cke:encoded\x3e"})}function n(a){return a.replace(I,function(a,c){return decodeURIComponent(c)})}function y(a){return a.replace(/\x3c!--(?!{cke_protected})[\s\S]+?--\x3e/g,
+function(a){return"\x3c!--"+t+"{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 d=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 d&&d[c]||""})}function q(a,c){var d=[],g=c.config.protectedSource,b=c._.dataStore||(c._.dataStore=
+{id:1}),e=/<\!--\{cke_temp(comment)?\}(\d*?)--\x3e/g,g=[/|$)/gi,//gi,//gi].concat(g);a=a.replace(/\x3c!--[\s\S]*?--\x3e/g,function(a){return"\x3c!--{cke_tempcomment}"+(d.push(a)-1)+"--\x3e"});for(var f=0;f]+\s*=\s*(?:[^'"\s>]+|'[^']*'|"[^"]*"))|[^\s=\/>]+))+\s*\/?>/g,function(a){return a.replace(/\x3c!--\{cke_protected\}([^>]*)--\x3e/g,function(a,c){b[b.id]=decodeURIComponent(c);return"{cke_protected_"+b.id++ +"}"})});return a=a.replace(/<(title|iframe|textarea)([^>]*)>([\s\S]*?)<\/\1>/g,function(a,d,g,b){return"\x3c"+d+g+"\x3e"+p(v(b),c)+"\x3c/"+d+"\x3e"})}var r;CKEDITOR.htmlDataProcessor=function(a){var c,
+e,f=this;this.editor=a;this.dataFilter=c=new CKEDITOR.htmlParser.filter;this.htmlFilter=e=new CKEDITOR.htmlParser.filter;this.writer=new CKEDITOR.htmlParser.basicWriter;c.addRules(B);c.addRules(C,{applyToAll:!0});c.addRules(b(a,"data"),{applyToAll:!0});e.addRules(A);e.addRules(E,{applyToAll:!0});e.addRules(b(a,"html"),{applyToAll:!0});a.on("toHtml",function(c){c=c.data;var b=c.dataValue,e,b=r(b),b=q(b,a),b=g(b,N),b=d(b),b=g(b,D),b=b.replace(L,"$1cke:$2"),b=b.replace(H,"\x3ccke:$1$2\x3e\x3c/cke:$1\x3e"),
+b=b.replace(/(]*>)(\r\n|\n)/g,"$1$2$2"),b=b.replace(/([^a-z0-9<\-])(on\w{3,})(?!>)/gi,"$1data-cke-"+CKEDITOR.rnd+"-$2");e=c.context||a.editable().getName();var f;CKEDITOR.env.ie&&9>CKEDITOR.env.version&&"pre"==e&&(e="div",b="\x3cpre\x3e"+b+"\x3c/pre\x3e",f=1);e=a.document.createElement(e);e.setHtml("a"+b);b=e.getHtml().substr(1);b=b.replace(new RegExp("data-cke-"+CKEDITOR.rnd+"-","ig"),"");f&&(b=b.replace(/^
|<\/pre>$/gi,""));b=b.replace(R,"$1$2");b=n(b);b=v(b);e=!1===c.fixForBody?!1:
 h(c.enterMode,a.config.autoParagraph);b=CKEDITOR.htmlParser.fragment.fromHtml(b,c.context,e);e&&(f=b,!f.children.length&&CKEDITOR.dtd[f.name][e]&&(e=new CKEDITOR.htmlParser.element(e),f.add(e)));c.dataValue=b},null,null,5);a.on("toHtml",function(c){c.data.filter.applyTo(c.data.dataValue,!0,c.data.dontFilter,c.data.enterMode)&&a.fire("dataFiltered")},null,null,6);a.on("toHtml",function(a){a.data.dataValue.filterChildren(f.dataFilter,!0)},null,null,10);a.on("toHtml",function(a){a=a.data;var c=a.dataValue,
 d=new CKEDITOR.htmlParser.basicWriter;c.writeChildrenHtml(d);c=d.getHtml(!0);a.dataValue=y(c)},null,null,15);a.on("toDataFormat",function(c){var d=c.data.dataValue;c.data.enterMode!=CKEDITOR.ENTER_BR&&(d=d.replace(/^
/i,""));c.data.dataValue=CKEDITOR.htmlParser.fragment.fromHtml(d,c.data.context,h(c.data.enterMode,a.config.autoParagraph))},null,null,5);a.on("toDataFormat",function(a){a.data.dataValue.filterChildren(f.htmlFilter,!0)},null,null,10);a.on("toDataFormat",function(a){a.data.filter.applyTo(a.data.dataValue, -!1,!0)},null,null,11);a.on("toDataFormat",function(c){var d=c.data.dataValue,b=f.writer;b.reset();d.writeChildrenHtml(b);d=b.getHtml(!0);d=w(d);d=p(d,a);c.data.dataValue=d},null,null,15)};CKEDITOR.htmlDataProcessor.prototype={toHtml:function(a,c,d,b){var g=this.editor,e,f,h,m;c&&"object"==typeof c?(e=c.context,d=c.fixForBody,b=c.dontFilter,f=c.filter,h=c.enterMode,m=c.protectedWhitespaces):e=c;e||null===e||(e=g.editable().getName());return g.fire("toHtml",{dataValue:a,context:e,fixForBody:d,dontFilter:b, -filter:f||g.filter,enterMode:h||g.enterMode,protectedWhitespaces:m}).dataValue},toDataFormat:function(a,c){var d,b,g;c&&(d=c.context,b=c.filter,g=c.enterMode);d||null===d||(d=this.editor.editable().getName());return this.editor.fire("toDataFormat",{dataValue:a,filter:b||this.editor.filter,context:d,enterMode:g||this.editor.enterMode}).dataValue},protectSource:function(a){return t(a,this.editor)},unprotectSource:function(a){return p(a,this.editor)},unprotectRealComments:function(a){return w(a)}};var x= -/(?: |\xa0)$/,u="{cke_protected}",z=CKEDITOR.dtd,q="caption colgroup col thead tfoot tbody".split(" "),v=CKEDITOR.tools.extend({},z.$blockLimit,z.$block),B={elements:{input:l,textarea:l}},D={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"]= +!1,!0)},null,null,11);a.on("toDataFormat",function(c){var d=c.data.dataValue,b=f.writer;b.reset();d.writeChildrenHtml(b);d=b.getHtml(!0);d=v(d);d=p(d,a);c.data.dataValue=d},null,null,15)};CKEDITOR.htmlDataProcessor.prototype={toHtml:function(a,c,d,b){var g=this.editor,e,f,k,h;c&&"object"==typeof c?(e=c.context,d=c.fixForBody,b=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:d,dontFilter:b, +filter:f||g.filter,enterMode:k||g.enterMode,protectedWhitespaces:h}).dataValue},toDataFormat:function(a,c){var d,b,g;c&&(d=c.context,b=c.filter,g=c.enterMode);d||null===d||(d=this.editor.editable().getName());return this.editor.fire("toDataFormat",{dataValue:a,filter:b||this.editor.filter,context:d,enterMode:g||this.editor.enterMode}).dataValue},protectSource:function(a){return q(a,this.editor)},unprotectSource:function(a){return p(a,this.editor)},unprotectRealComments:function(a){return v(a)}};var x= +/(?: |\xa0)$/,t="{cke_protected}",z=CKEDITOR.dtd,u="caption colgroup col thead tfoot tbody".split(" "),w=CKEDITOR.tools.extend({},z.$blockLimit,z.$block),B={elements:{input:m,textarea:m}},C={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}}}},A={elements:{embed:function(a){var c=a.parent;if(c&&"object"==c.name){var d=c.attributes.width,c=c.attributes.height;d&&(a.attributes.width=d);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}}},E={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 d=["name","href","src"],b,g=0;gb?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&&k(a,c=new CKEDITOR.htmlParser.text);c.value=a.attributes["data-cke-title"]||""},input:c,textarea:c},attributes:{"class":function(a){return CKEDITOR.tools.ltrim(a.replace(/(?:^|\s+)cke_[^\s]*/g, -""))||!1}}};CKEDITOR.env.ie&&(E.attributes.style=function(a){return a.replace(/(^|;)([^\:]+)/g,function(a){return a.toLowerCase()})});var F=/<(a|area|img|input|source)\b([^>]*)>/gi,K=/([\w-:]+)\s*=\s*(?:(?:"[^"]*")|(?:'[^']*')|(?:[^ "'>]+))/gi,L=/^(href|src|name)$/i,C=/(?:])[^>]*>[\s\S]*?<\/style>)|(?:<(:?link|meta|base)[^>]*>)/gi,O=/(])[^>]*>)([\s\S]*?)(?:<\/textarea>)/gi,I=/([^<]*)<\/cke:encoded>/gi,M=/(<\/?)((?:object|embed|param|html|body|head|title)([\s][^>]*)?>)/gi, -Q=/(<\/?)cke:((?:html|body|head|title)[^>]*>)/gi,H=/]*?)\/?>(?!\s*<\/cke:\1)/gi;r=function(){function a(d){return CKEDITOR.tools.array.reduce(d.split(""),function(a,d){var b=d.toLowerCase(),g=d.toUpperCase(),e=c(b);b!==g&&(e+="|"+c(g));return a+("("+e+")")},"")}function c(a){var d;d=a.charCodeAt(0);var b=d.toString(16);d={htmlCode:"\x26#"+d+";?",hex:"\x26#x0*"+b+";?",entity:{"\x3c":"\x26lt;","\x3e":"\x26gt;",":":"\x26colon;"}[a]};for(var g in d)d[g]&&(a+="|"+d[g]);return a}var d= -new RegExp("("+a("\x3ccke:encoded\x3e")+"(.*?)"+a("\x3c/cke:encoded\x3e")+")|("+a("\x3c")+a("/")+"?"+a("cke:encoded\x3e")+")","gi"),b=new RegExp("(("+a("{cke_protected")+")(_[0-9]*)?"+a("}")+")","gi");return function(a){return a.replace(d,"").replace(b,"")}}()}(),"use strict",CKEDITOR.htmlParser.element=function(b,h){this.name=b;this.attributes=h||{};this.children=[];var f=b||"",e=f.match(/^cke:(.*)/);e&&(f=e[1]);f=!!(CKEDITOR.dtd.$nonBodyContent[f]||CKEDITOR.dtd.$block[f]||CKEDITOR.dtd.$listItem[f]|| -CKEDITOR.dtd.$tableContent[f]||CKEDITOR.dtd.$nonEditable[f]||"br"==f);this.isEmpty=!!CKEDITOR.dtd.$empty[b];this.isUnknown=!CKEDITOR.dtd[b];this._={isBlockLike:f,hasInlineStarted:this.isEmpty||!f}},CKEDITOR.htmlParser.cssStyle=function(b){var h={};((b instanceof CKEDITOR.htmlParser.element?b.attributes.style:b)||"").replace(/"/g,'"').replace(/\s*([^ :;]+)\s*:\s*([^;]+)\s*(?=;|$)/g,function(b,e,a){"font-family"==e&&(a=a.replace(/["']/g,""));h[e.toLowerCase()]=a});return{rules:h,populate:function(b){var e= -this.toString();e&&(b instanceof CKEDITOR.dom.element?b.setAttribute("style",e):b instanceof CKEDITOR.htmlParser.element?b.attributes.style=e:b.style=e)},toString:function(){var b=[],e;for(e in h)h[e]&&b.push(e,":",h[e],";");return b.join("")}}},function(){function b(b){return function(a){return a.type==CKEDITOR.NODE_ELEMENT&&("string"==typeof b?a.name==b:a.name in b)}}var h=function(b,a){b=b[0];a=a[0];return ba?1:0},f=CKEDITOR.htmlParser.fragment.prototype;CKEDITOR.htmlParser.element.prototype= -CKEDITOR.tools.extend(new CKEDITOR.htmlParser.node,{type:CKEDITOR.NODE_ELEMENT,add:f.add,clone:function(){return new CKEDITOR.htmlParser.element(this.name,this.attributes)},filter:function(b,a){var f=this,h,l;a=f.getFilterContext(a);if(!f.parent)b.onRoot(a,f);for(;;){h=f.name;if(!(l=b.onElementName(a,h)))return this.remove(),!1;f.name=l;if(!(f=b.onElement(a,f)))return this.remove(),!1;if(f!==this)return this.replaceWith(f),!1;if(f.name==h)break;if(f.type!=CKEDITOR.NODE_ELEMENT)return this.replaceWith(f), -!1;if(!f.name)return this.replaceWithChildren(),!1}h=f.attributes;var c,d;for(c in h){for(l=h[c];;)if(d=b.onAttributeName(a,c))if(d!=c)delete h[c],c=d;else break;else{delete h[c];break}d&&(!1===(l=b.onAttribute(a,f,d,l))?delete h[d]:h[d]=l)}f.isEmpty||this.filterChildren(b,!1,a);return!0},filterChildren:f.filterChildren,writeHtml:function(b,a){a&&this.filter(a);var f=this.name,k=[],l=this.attributes,c,d;b.openTag(f,l);for(c in l)k.push([c,l[c]]);b.sortAttributes&&k.sort(h);c=0;for(d=k.length;cCKEDITOR.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()};z.eol.detect(a,this);z.bogus.exclude(a);z.cell.shrink(a);a.fragment=a.range.cloneContents();z.tree.rebuild(a,this);z.eol.fix(a,this);return new CKEDITOR.dom.documentFragment(a.fragment.$)},extractHtmlFromRange:function(a,c){var b=q,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(!y(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 a=this.editor;this.attachListener(a,"beforeGetData",function(){var c= -this.getData();this.is("textarea")||!1!==a.config.ignoreEmptyParagraph&&(c=c.replace(t,function(a,c){return c}));a.setData(c,null,1)},this);this.attachListener(a,"getSnapshot",function(a){a.data=this.getData(1)},this);this.attachListener(a,"afterSetData",function(){this.setData(a.getData(1))},this);this.attachListener(a,"loadSnapshot",function(a){this.setData(a.data,1)},this);this.attachListener(a,"beforeFocus",function(){var c=a.getSelection();(c=c&&c.getNative())&&"Control"==c.type||this.focus()}, -this);this.attachListener(a,"insertHtml",function(a){this.insertHtml(a.data.dataValue,a.data.mode,a.data.range)},this);this.attachListener(a,"insertElement",function(a){this.insertElement(a.data)},this);this.attachListener(a,"insertText",function(a){this.insertText(a.data)},this);this.setReadOnly(a.readOnly);this.attachClass("cke_editable");a.elementMode==CKEDITOR.ELEMENT_MODE_INLINE?this.attachClass("cke_editable_inline"):a.elementMode!=CKEDITOR.ELEMENT_MODE_REPLACE&&a.elementMode!=CKEDITOR.ELEMENT_MODE_APPENDTO|| -this.attachClass("cke_editable_themed");this.attachClass("cke_contents_"+a.config.contentsLangDirection);a.keystrokeHandler.blockedKeystrokes[8]=+a.readOnly;a.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(){a._.previousScrollTop=a.editable().$.scrollTop},null,null,-1);if(CKEDITOR.env.edge&&14CKEDITOR.env.version?k.$.styleSheet.cssText=h:k.setText(h)):(h=b.appendStyleText(h),h=new CKEDITOR.dom.element(h.ownerNode||h.owningElement),d.setCustomData("stylesheet",h),h.data("cke-temp",1))}d=b.getCustomData("stylesheet_ref")||0;b.setCustomData("stylesheet_ref", -d+1);this.setCustomData("cke_includeReadonly",!a.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 l={8:1,46:1};this.attachListener(a,"key",function(c){if(a.readOnly)return!0;var b=c.data.domEvent.getKey(),d;c=a.getSelection();if(0!==c.getRanges().length){if(b in l){var g,e=c.getRanges()[0],f=e.startPath(),h,k,r,b=8==b;CKEDITOR.env.ie&& -11>CKEDITOR.env.version&&(g=c.getSelectedElement())||(g=m(c))?(a.fire("saveSnapshot"),e.moveToPosition(g,CKEDITOR.POSITION_BEFORE_START),g.remove(),e.select(),a.fire("saveSnapshot"),d=1):e.collapsed&&((h=f.block)&&(r=h[b?"getPrevious":"getNext"](n))&&r.type==CKEDITOR.NODE_ELEMENT&&r.is("table")&&e[b?"checkStartOfBlock":"checkEndOfBlock"]()?(a.fire("saveSnapshot"),e[b?"checkEndOfBlock":"checkStartOfBlock"]()&&h.remove(),e["moveToElementEdit"+(b?"End":"Start")](r),e.select(),a.fire("saveSnapshot"), -d=1):f.blockLimit&&f.blockLimit.is("td")&&(k=f.blockLimit.getAscendant("table"))&&e.checkBoundaryOfElement(k,b?CKEDITOR.START:CKEDITOR.END)&&(r=k[b?"getPrevious":"getNext"](n))?(a.fire("saveSnapshot"),e["moveToElementEdit"+(b?"End":"Start")](r),e.checkStartOfBlock()&&e.checkEndOfBlock()?r.remove():e.select(),a.fire("saveSnapshot"),d=1):(k=f.contains(["td","th","caption"]))&&e.checkBoundaryOfElement(k,b?CKEDITOR.START:CKEDITOR.END)&&(d=1))}return!d}});a.blockless&&CKEDITOR.env.ie&&CKEDITOR.env.needsBrFiller&& -this.attachListener(this,"keyup",function(c){c.data.getKeystroke()in l&&!this.getFirst(e)&&(this.appendBogus(),c=a.createRange(),c.moveToPosition(this,CKEDITOR.POSITION_AFTER_START),c.select())});this.attachListener(this,"dblclick",function(c){if(a.readOnly)return!1;c={element:c.data.getTarget()};a.fire("doubleclick",c)});CKEDITOR.env.ie&&this.attachListener(this,"click",f);CKEDITOR.env.ie&&!CKEDITOR.env.edge||this.attachListener(this,"mousedown",function(c){var b=c.data.getTarget();b.is("img","hr", -"input","textarea","select")&&!b.isReadOnly()&&(a.getSelection().selectElement(b),b.is("input","textarea","select")&&c.data.preventDefault())});CKEDITOR.env.edge&&this.attachListener(this,"mouseup",function(c){(c=c.data.getTarget())&&c.is("img")&&!c.isReadOnly()&&a.getSelection().selectElement(c)});CKEDITOR.env.gecko&&this.attachListener(this,"mouseup",function(c){if(2==c.data.$.button&&(c=c.data.getTarget(),!c.getAscendant("table")&&!c.getOuterHtml().replace(t,""))){var b=a.createRange();b.moveToElementEditStart(c); -b.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(a,"key",function(c){if(a.readOnly)return!0;var b=c.data.domEvent.getKey();if(b in l&&(c=a.getSelection(),0!==c.getRanges().length)){var b=8==b,d=c.getRanges()[0];c=d.startPath();if(d.collapsed)a:{var e= -c.block;if(e&&d[b?"checkStartOfBlock":"checkEndOfBlock"](!0)&&d.moveToClosestEditablePosition(e,!b)&&d.collapsed){if(d.startContainer.type==CKEDITOR.NODE_ELEMENT){var f=d.startContainer.getChild(d.startOffset-(b?1:0));if(f&&f.type==CKEDITOR.NODE_ELEMENT&&f.is("hr")){a.fire("saveSnapshot");f.remove();c=!0;break a}}d=d.startPath().block;if(!d||d&&d.contains(e))c=void 0;else{a.fire("saveSnapshot");var h;(h=(b?d:e).getBogus())&&h.remove();h=a.getSelection();f=h.createBookmarks();(b?e:d).moveChildren(b? -d:e,!1);c.lastElement.mergeSiblings();g(e,d,!b);h.selectBookmarks(f);c=!0}}else c=!1}else b=d,h=c.block,d=b.endPath().block,h&&d&&!h.equals(d)?(a.fire("saveSnapshot"),(e=h.getBogus())&&e.remove(),b.enlarge(CKEDITOR.ENLARGE_INLINE),b.deleteContents(),d.getParent()&&(d.moveChildren(h,!1),c.lastElement.mergeSiblings(),g(h,d,!0)),b=a.getSelection().getRanges()[0],b.collapse(1),b.optimize(),""===b.startContainer.getHtml()&&b.startContainer.appendBogus(),b.select(),c=!0):c=!1;if(!c)return;a.getSelection().scrollIntoView(); -a.fire("saveSnapshot");return!1}},this,null,100)}},getUniqueId:function(){var a;try{this._.expandoNumber=a=CKEDITOR.dom.domObject.prototype.getUniqueId.call(this)}catch(c){a=this._&&this._.expandoNumber}return a}},_:{cleanCustomData:function(){this.removeClass("cke_editable");this.restoreAttrs();for(var a=this.removeCustomData("classes");a&&a.length;)this.removeClass(a.pop());if(!this.is("textarea")){var a=this.getDocument(),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())}}}}});CKEDITOR.editor.prototype.editable=function(a){var c=this._.editable;if(c&&a)return 0;if(!arguments.length)return c;a?c=a instanceof CKEDITOR.editable?a:new CKEDITOR.editable(this,a):(c&&c.detach(),c=null);return this._.editable=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 d=c.getSelection();d&&!d.isLocked&&(d=c.checkDirty(),c.fire("lockSnapshot"),b(a),c.fire("unlockSnapshot"),!d&&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}"); -n=CKEDITOR.dom.walker.whitespaces(!0);y=CKEDITOR.dom.walker.bookmark(!1,!0);w=CKEDITOR.dom.walker.empty();p=CKEDITOR.dom.walker.bogus();t=/(^|]*>)\s*<(p|div|address|h\d|center|pre)[^>]*>\s*(?:]*>| |\u00A0| )?\s*(:?<\/\2>)?\s*(?=$|<\/body>)/gi;r=function(){function a(c){return c.type==CKEDITOR.NODE_ELEMENT}function b(c,d){var g,e,f,h,n=[],k=d.range.startContainer;g=d.range.startPath();for(var k=m[k.getName()],l=0,r=c.getChildren(),t=r.count(),y=-1,u=-1,q=0,x=g.contains(m.$list);l< -t;++l)g=r.getItem(l),a(g)?(f=g.getName(),x&&f in CKEDITOR.dtd.$list?n=n.concat(b(g,d)):(h=!!k[f],"br"!=f||!g.data("cke-eol")||l&&l!=t-1||(q=(e=l?n[l-1].node:r.getItem(l+1))&&(!a(e)||!e.is("br")),e=e&&a(e)&&m.$block[e.getName()]),-1!=y||h||(y=l),h||(u=l),n.push({isElement:1,isLineBreak:q,isBlock:g.isBlockBoundary(),hasBlockSibling:e,node:g,name:f,allowed:h}),e=q=0)):n.push({isElement:0,node:g,allowed:1});-1CKEDITOR.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))}}();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,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())}}();z={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||!p(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 n=g.contains(CKEDITOR.dtd.$list).getParent();f=function(a){return!a.equals(n)}}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)}}};q=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 b(a,c){var d=new CKEDITOR.dom.range(a);d.setStartAfter(c.startNode);d.setEndBefore(c.endNode);return d}return{list:{detectMerge:function(a,c){var d=b(c,a.bookmark), -g=d.startPath(),e=d.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)d=d.clone(),d.setStartBefore(a.bookmark.startNode),d.setEndAfter(a.bookmark.endNode),a.mergeListBookmark=d.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),n=f.contains(CKEDITOR.dtd.$list);h.equals(n)||(n.moveChildren(h),n.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(b){var g=[],e,f=new CKEDITOR.dom.walker(b),h=b.startPath().contains(d),n=b.endPath().contains(d),m={};f.guard=function(a, -f){if(a.type==CKEDITOR.NODE_ELEMENT){var k="visited_"+(f?"out":"in");if(a.getCustomData(k))return;CKEDITOR.dom.element.setMarker(m,a,k,1)}if(f&&h&&a.equals(h))e=b.clone(),e.setEndAt(h,CKEDITOR.POSITION_BEFORE_END),g.push(e);else if(!f&&n&&a.equals(n))e=b.clone(),e.setStartAt(n,CKEDITOR.POSITION_AFTER_START),g.push(e);else{if(k=!f)k=a.type==CKEDITOR.NODE_ELEMENT&&a.is(d)&&(!h||c(a,h))&&(!n||c(a,n));if(!k&&(k=f))if(a.is(d))var k=h&&h.getAscendant("table",!0),l=n&&n.getAscendant("table",!0),r=a.getAscendant("table", -!0),k=k&&k.contains(r)||l&&l.contains(r);else k=void 0;k&&(e=b.clone(),e.selectNodeContents(a),g.push(e))}};f.lastForward();CKEDITOR.dom.element.clearAllMarkers(m);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 d={td:1,th:1,caption:1};return{detectPurge:function(a){var c=a.range,b=c.clone();b.enlarge(CKEDITOR.ENLARGE_ELEMENT);var b=new CKEDITOR.dom.walker(b),g=0;b.evaluator=function(a){a.type== -CKEDITOR.NODE_ELEMENT&&a.is(d)&&++g};b.checkForward();if(1b?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&&l(a,c=new CKEDITOR.htmlParser.text);c.value=a.attributes["data-cke-title"]||""},input:c,textarea:c},attributes:{"class":function(a){return CKEDITOR.tools.ltrim(a.replace(/(?:^|\s+)cke_[^\s]*/g, +""))||!1}}};CKEDITOR.env.ie&&(E.attributes.style=function(a){return a.replace(/(^|;)([^\:]+)/g,function(a){return a.toLowerCase()})});var F=/<(a|area|img|input|source)\b([^>]*)>/gi,K=/([\w-:]+)\s*=\s*(?:(?:"[^"]*")|(?:'[^']*')|(?:[^ "'>]+))/gi,M=/^(href|src|name)$/i,D=/(?:])[^>]*>[\s\S]*?<\/style>)|(?:<(:?link|meta|base)[^>]*>)/gi,N=/(])[^>]*>)([\s\S]*?)(?:<\/textarea>)/gi,I=/([^<]*)<\/cke:encoded>/gi,L=/(<\/?)((?:object|embed|param|html|body|head|title)([\s][^>]*)?>)/gi, +R=/(<\/?)cke:((?:html|body|head|title)[^>]*>)/gi,H=/]*?)\/?>(?!\s*<\/cke:\1)/gi;r=function(){function a(c,d){for(var b=0;b/g];return function(c){for(;a(b,c);)for(var d=b,g=0;ga?1:0},f=CKEDITOR.htmlParser.fragment.prototype;CKEDITOR.htmlParser.element.prototype=CKEDITOR.tools.extend(new CKEDITOR.htmlParser.node,{type:CKEDITOR.NODE_ELEMENT,add:f.add,clone:function(){return new CKEDITOR.htmlParser.element(this.name,this.attributes)},filter:function(b,a){var f=this,h,m;a=f.getFilterContext(a);if(!f.parent)b.onRoot(a,f);for(;;){h=f.name;if(!(m=b.onElementName(a,h)))return this.remove(),!1;f.name=m;if(!(f=b.onElement(a,f)))return this.remove(), +!1;if(f!==this)return this.replaceWith(f),!1;if(f.name==h)break;if(f.type!=CKEDITOR.NODE_ELEMENT)return this.replaceWith(f),!1;if(!f.name)return this.replaceWithChildren(),!1}h=f.attributes;var c,d;for(c in h){for(m=h[c];;)if(d=b.onAttributeName(a,c))if(d!=c)delete h[c],c=d;else break;else{delete h[c];break}d&&(!1===(m=b.onAttribute(a,f,d,m))?delete h[d]:h[d]=m)}f.isEmpty||this.filterChildren(b,!1,a);return!0},filterChildren:f.filterChildren,writeHtml:function(b,a){a&&this.filter(a);var f=this.name, +l=[],m=this.attributes,c,d;b.openTag(f,m);for(c in m)l.push([c,m[c]]);b.sortAttributes&&l.sort(h);c=0;for(d=l.length;cCKEDITOR.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()};z.eol.detect(a,this);z.bogus.exclude(a);z.cell.shrink(a);a.fragment=a.range.cloneContents(); +z.tree.rebuild(a,this);z.eol.fix(a,this);return new CKEDITOR.dom.documentFragment(a.fragment.$)},extractHtmlFromRange:function(a,c){var b=u,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(!y(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),v(a.startContainer)&&a.startContainer.appendBogus();a.startContainer.mergeSiblings();return g},setup:function(){var a=this.editor;this.attachListener(a,"beforeGetData",function(){var c=this.getData();this.is("textarea")||!1!==a.config.ignoreEmptyParagraph&&(c=c.replace(q,function(a,c){return c}));a.setData(c,null,1)}, +this);this.attachListener(a,"getSnapshot",function(a){a.data=this.getData(1)},this);this.attachListener(a,"afterSetData",function(){this.setData(a.getData(1))},this);this.attachListener(a,"loadSnapshot",function(a){this.setData(a.data,1)},this);this.attachListener(a,"beforeFocus",function(){var c=a.getSelection();(c=c&&c.getNative())&&"Control"==c.type||this.focus()},this);this.attachListener(a,"insertHtml",function(a){this.insertHtml(a.data.dataValue,a.data.mode,a.data.range)},this);this.attachListener(a, +"insertElement",function(a){this.insertElement(a.data)},this);this.attachListener(a,"insertText",function(a){this.insertText(a.data)},this);this.setReadOnly(a.readOnly);this.attachClass("cke_editable");a.elementMode==CKEDITOR.ELEMENT_MODE_INLINE?this.attachClass("cke_editable_inline"):a.elementMode!=CKEDITOR.ELEMENT_MODE_REPLACE&&a.elementMode!=CKEDITOR.ELEMENT_MODE_APPENDTO||this.attachClass("cke_editable_themed");this.attachClass("cke_contents_"+a.config.contentsLangDirection);a.keystrokeHandler.blockedKeystrokes[8]= ++a.readOnly;a.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(){a._.previousScrollTop=a.editable().$.scrollTop},null,null,-1);if(CKEDITOR.env.edge&&14CKEDITOR.env.version?l.$.styleSheet.cssText=h:l.setText(h)):(h=b.appendStyleText(h),h=new CKEDITOR.dom.element(h.ownerNode||h.owningElement),d.setCustomData("stylesheet",h),h.data("cke-temp",1))}d=b.getCustomData("stylesheet_ref")||0;b.setCustomData("stylesheet_ref",d+1);this.setCustomData("cke_includeReadonly",!a.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(a,"key",function(c){if(a.readOnly)return!0;var b=c.data.domEvent.getKey(),d;c=a.getSelection();if(0!==c.getRanges().length){if(b in m){var g,e=c.getRanges()[0],f=e.startPath(),h,l,q,b=8==b;CKEDITOR.env.ie&&11>CKEDITOR.env.version&&(g=c.getSelectedElement())||(g=k(c))?(a.fire("saveSnapshot"),e.moveToPosition(g,CKEDITOR.POSITION_BEFORE_START),g.remove(), +e.select(),a.fire("saveSnapshot"),d=1):e.collapsed&&((h=f.block)&&(q=h[b?"getPrevious":"getNext"](n))&&q.type==CKEDITOR.NODE_ELEMENT&&q.is("table")&&e[b?"checkStartOfBlock":"checkEndOfBlock"]()?(a.fire("saveSnapshot"),e[b?"checkEndOfBlock":"checkStartOfBlock"]()&&h.remove(),e["moveToElementEdit"+(b?"End":"Start")](q),e.select(),a.fire("saveSnapshot"),d=1):f.blockLimit&&f.blockLimit.is("td")&&(l=f.blockLimit.getAscendant("table"))&&e.checkBoundaryOfElement(l,b?CKEDITOR.START:CKEDITOR.END)&&(q=l[b? +"getPrevious":"getNext"](n))?(a.fire("saveSnapshot"),e["moveToElementEdit"+(b?"End":"Start")](q),e.checkStartOfBlock()&&e.checkEndOfBlock()?q.remove():e.select(),a.fire("saveSnapshot"),d=1):(l=f.contains(["td","th","caption"]))&&e.checkBoundaryOfElement(l,b?CKEDITOR.START:CKEDITOR.END)&&(d=1))}return!d}});a.blockless&&CKEDITOR.env.ie&&CKEDITOR.env.needsBrFiller&&this.attachListener(this,"keyup",function(c){c.data.getKeystroke()in m&&!this.getFirst(e)&&(this.appendBogus(),c=a.createRange(),c.moveToPosition(this, +CKEDITOR.POSITION_AFTER_START),c.select())});this.attachListener(this,"dblclick",function(c){if(a.readOnly)return!1;c={element:c.data.getTarget()};a.fire("doubleclick",c)});CKEDITOR.env.ie&&this.attachListener(this,"click",f);CKEDITOR.env.ie&&!CKEDITOR.env.edge||this.attachListener(this,"mousedown",function(c){var b=c.data.getTarget();b.is("img","hr","input","textarea","select")&&!b.isReadOnly()&&(a.getSelection().selectElement(b),b.is("input","textarea","select")&&c.data.preventDefault())});CKEDITOR.env.edge&& +this.attachListener(this,"mouseup",function(c){(c=c.data.getTarget())&&c.is("img")&&!c.isReadOnly()&&a.getSelection().selectElement(c)});CKEDITOR.env.gecko&&this.attachListener(this,"mouseup",function(c){if(2==c.data.$.button&&(c=c.data.getTarget(),!c.getAscendant("table")&&!c.getOuterHtml().replace(q,""))){var b=a.createRange();b.moveToElementEditStart(c);b.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(a,"key",function(c){if(a.readOnly)return!0;var b=c.data.domEvent.getKey();if(b in m&&(c=a.getSelection(),0!==c.getRanges().length)){var b=8==b,d=c.getRanges()[0];c=d.startPath();if(d.collapsed)a:{var e=c.block;if(e&&d[b?"checkStartOfBlock":"checkEndOfBlock"](!0)&&d.moveToClosestEditablePosition(e,!b)&&d.collapsed){if(d.startContainer.type==CKEDITOR.NODE_ELEMENT){var f= +d.startContainer.getChild(d.startOffset-(b?1:0));if(f&&f.type==CKEDITOR.NODE_ELEMENT&&f.is("hr")){a.fire("saveSnapshot");f.remove();c=!0;break a}}d=d.startPath().block;if(!d||d&&d.contains(e))c=void 0;else{a.fire("saveSnapshot");var h;(h=(b?d:e).getBogus())&&h.remove();h=a.getSelection();f=h.createBookmarks();(b?e:d).moveChildren(b?d:e,!1);c.lastElement.mergeSiblings();g(e,d,!b);h.selectBookmarks(f);c=!0}}else c=!1}else b=d,h=c.block,d=b.endPath().block,h&&d&&!h.equals(d)?(a.fire("saveSnapshot"), +(e=h.getBogus())&&e.remove(),b.enlarge(CKEDITOR.ENLARGE_INLINE),b.deleteContents(),d.getParent()&&(d.moveChildren(h,!1),c.lastElement.mergeSiblings(),g(h,d,!0)),b=a.getSelection().getRanges()[0],b.collapse(1),b.optimize(),""===b.startContainer.getHtml()&&b.startContainer.appendBogus(),b.select(),c=!0):c=!1;if(!c)return;a.getSelection().scrollIntoView();a.fire("saveSnapshot");return!1}},this,null,100)}},getUniqueId:function(){var a;try{this._.expandoNumber=a=CKEDITOR.dom.domObject.prototype.getUniqueId.call(this)}catch(c){a= +this._&&this._.expandoNumber}return a}},_:{cleanCustomData:function(){this.removeClass("cke_editable");this.restoreAttrs();for(var a=this.removeCustomData("classes");a&&a.length;)this.removeClass(a.pop());if(!this.is("textarea")){var a=this.getDocument(),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())}}}}});CKEDITOR.editor.prototype.editable= +function(a){var c=this._.editable;if(c&&a)return 0;if(!arguments.length)return c;a?c=a instanceof CKEDITOR.editable?a:new CKEDITOR.editable(this,a):(c&&c.detach(),c=null);return this._.editable=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 d=c.getSelection();d&&!d.isLocked&&(d=c.checkDirty(),c.fire("lockSnapshot"),b(a),c.fire("unlockSnapshot"),!d&&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}");n=CKEDITOR.dom.walker.whitespaces(!0);y=CKEDITOR.dom.walker.bookmark(!1,!0);v=CKEDITOR.dom.walker.empty(); +p=CKEDITOR.dom.walker.bogus();q=/(^|]*>)\s*<(p|div|address|h\d|center|pre)[^>]*>\s*(?:]*>| |\u00A0| )?\s*(:?<\/\2>)?\s*(?=$|<\/body>)/gi;r=function(){function a(c){return c.type==CKEDITOR.NODE_ELEMENT}function b(c,d){var g,e,f,h,k=[],l=d.range.startContainer;g=d.range.startPath();for(var l=n[l.getName()],m=0,q=c.getChildren(),r=q.count(),y=-1,t=-1,u=0,F=g.contains(n.$list);mCKEDITOR.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))}}();t=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())}}();z={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||!p(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)}}};u=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;v(b)&&b.remove()}function b(a,c){var d=new CKEDITOR.dom.range(a);d.setStartAfter(c.startNode);d.setEndBefore(c.endNode);return d}return{list:{detectMerge:function(a,c){var d=b(c,a.bookmark),g=d.startPath(),e=d.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)d=d.clone(),d.setStartBefore(a.bookmark.startNode),d.setEndAfter(a.bookmark.endNode),a.mergeListBookmark=d.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(b){var g=[],e,f=new CKEDITOR.dom.walker(b),h=b.startPath().contains(d),k=b.endPath().contains(d),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=b.clone(),e.setEndAt(h,CKEDITOR.POSITION_BEFORE_END),g.push(e);else if(!f&&k&&a.equals(k))e=b.clone(),e.setStartAt(k,CKEDITOR.POSITION_AFTER_START),g.push(e);else{if(l=!f)l=a.type==CKEDITOR.NODE_ELEMENT&&a.is(d)&&(!h||c(a,h))&&(!k||c(a,k));if(!l&&(l=f))if(a.is(d))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=b.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 d={td:1,th:1,caption:1};return{detectPurge:function(a){var c=a.range,b=c.clone();b.enlarge(CKEDITOR.ENLARGE_ELEMENT);var b=new CKEDITOR.dom.walker(b),g=0;b.evaluator=function(a){a.type==CKEDITOR.NODE_ELEMENT&& +a.is(d)&&++g};b.checkForward();if(1e&&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(y(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 y(a,c){return c?a.replace(z,function(a,c){return c?" ":""}):a.replace(u,"")}function w(a,c){var b= +g&&(d=a[g].getAscendant("tr")),b.push(a[g].getText());return c+=b.join("\t")}function a(a){var c=this.root.editor,b=c.getSelection(1);this.reset();u=!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=e(a);b.nativeSel=null;this.isFake=1;this.rev=x++;c._.fakeSelection=this;u=!1;this.root.fire("selectionchange")}function k(){var a= +this._.fakeSelection,c;if(a){c=this.getSelection(1);var d;if(!(d=!c)&&(d=!c.isHidden())){d=a;var g=c.getRanges(),e=d.getRanges(),f=g.length&&g[0]._getTableElement()&&g[0]._getTableElement().getAscendant("table",!0),k=e.length&&e[0]._getTableElement()&&e[0]._getTableElement().getAscendant("table",!0),n=1===g.length&&g[0]._getTableElement()&&g[0]._getTableElement().is("table"),l=1===e.length&&e[0]._getTableElement()&&e[0]._getTableElement().is("table");if(b(d.getSelectedElement()))d=!1;else{var m=1=== +g.length&&g[0].collapsed,e=h(g,!!CKEDITOR.env.webkit)&&h(e);f=f&&k?f.equals(k)||k.contains(f):!1;f&&(m||e)?(n&&!l&&d.selectRanges(g),d=!0):d=!1}d=!d}d&&(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)||(d=this._.selectionPreviousPath&&this._.selectionPreviousPath.blockLimit.equals(c.blockLimit),!CKEDITOR.env.webkit&&!CKEDITOR.env.gecko||d||(this._.previousActive= +this.document.getActive()),this._.selectionPreviousPath=c,this.fire("selectionChange",{selection:a,path:c}))}function l(){B=!0;w||(m.call(this),w=CKEDITOR.tools.setTimeout(m,200,this))}function m(){w=null;B&&(CKEDITOR.tools.setTimeout(k,0,this),B=!1)}function c(a){return C(a)||a.type==CKEDITOR.NODE_ELEMENT&&!a.is(CKEDITOR.dtd.$empty)?!0:!1}function d(a){function b(c,d){return c&&c.type!=CKEDITOR.NODE_TEXT?a.clone()["moveToElementEdit"+(d?"End":"Start")](c):!1}if(!(a.root instanceof CKEDITOR.editable))return!1; +var d=a.startContainer,g=a.getPreviousNode(c,null,d),e=a.getNextNode(c,null,d);return b(g)||b(e,1)||!(g||e||d.type==CKEDITOR.NODE_ELEMENT&&d.isBlockBoundary()&&d.getBogus())?!0:!1}function g(a){n(a,!1);var c=a.getDocument().createText(t);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=t.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(y(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 y(a,c){return c?a.replace(z,function(a,c){return c?" ":""}):a.replace(t,"")}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;width:0;height:0;overflow:hidden;")+'"\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 p(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(),e=g.getRanges()[0];g.isCollapsed()&&(e=e[38>d?"getPreviousEditableNode":"getNextEditableNode"]())&&e.type==CKEDITOR.NODE_ELEMENT&&"false"==e.getAttribute("contenteditable")&&(g=g.getStartElement(),!g.isBlockBoundary()||""!==(void 0===g.$.textContent? -g.$.innerText:g.$.textContent)||8!==d&&46!==d||(g.remove(),a.fire("saveSnapshot")),a.getSelection().fake(e),b.data.preventDefault(),b.cancel())}}}function t(a){for(var c=0;c=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 r="function"!=typeof window.getSelection,x=1,u=CKEDITOR.tools.repeat("​",7),z=new RegExp(u+"( )?","g"),q,v,B,D=CKEDITOR.dom.walker.invisible(1),A=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(){u=new CKEDITOR.dom.selection(b.getSelection());u.lock()}function c(){f.removeListener("mouseup", -c);t.removeListener("mouseup",c);var a=CKEDITOR.document.$.selection,b=a.createRange();"None"!=a.type&&b.parentElement()&&b.parentElement().ownerDocument==e.$&&b.select()}function d(a){var c,b;c=(c=this.document.getActive())?"input"===c.getName()||"textarea"===c.getName():!1;c||(c=this.getSelection(1),(b=g(c))&&!b.equals(h)&&(c.selectElement(b),a.data.preventDefault()))}function g(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 e=b.document,f=CKEDITOR.document,h=b.editable(),l=e.getBody(),t=e.getDocumentElement(),y=h.isInline(),q,u;CKEDITOR.env.gecko&&h.attachListener(h,"focus",function(a){a.removeListener();0!==q&&(a=b.getSelection().getNative())&&a.isCollapsed&&a.anchorNode==h.$&&(a=b.createRange(),a.moveToElementEditStart(h),a.select())},null,null,-2);h.attachListener(h,CKEDITOR.env.webkit||CKEDITOR.env.gecko?"focusin":"focus",function(){if(q&&(CKEDITOR.env.webkit|| -CKEDITOR.env.gecko)){q=b._.previousActive&&b._.previousActive.equals(e.getActive());var a=null!=b._.previousScrollTop&&b._.previousScrollTop!=h.$.scrollTop;CKEDITOR.env.webkit&&q&&a&&(h.$.scrollTop=b._.previousScrollTop)}b.unlockSelection(q);q=0},null,null,-1);h.attachListener(h,"mousedown",function(){q=0});if(CKEDITOR.env.ie||CKEDITOR.env.gecko||y)r?h.attachListener(h,"beforedeactivate",a,null,null,-1):h.attachListener(b,"selectionCheck",a,null,null,-1),h.attachListener(h,CKEDITOR.env.webkit||CKEDITOR.env.gecko? -"focusout":"blur",function(){var a=u&&(u.isFake||2>u.getRanges().length);CKEDITOR.env.gecko&&!y&&a||(b.lockSelection(u),q=1)},null,null,-1),h.attachListener(h,"mousedown",function(){q=0});if(CKEDITOR.env.ie&&!y){var x;h.attachListener(h,"mousedown",function(a){2==a.data.$.button&&((a=b.document.getSelection())&&a.getType()!=CKEDITOR.SELECTION_NONE||(x=b.window.getScrollPosition()))});h.attachListener(h,"mouseup",function(a){2==a.data.$.button&&x&&(b.document.$.documentElement.scrollLeft=x.x,b.document.$.documentElement.scrollTop= -x.y);x=null});if("BackCompat"!=e.$.compatMode){if(CKEDITOR.env.ie7Compat||CKEDITOR.env.ie6Compat){var v,w;t.on("mousedown",function(a){function c(a){a=a.data.$;if(v){var b=l.$.createTextRange();try{b.moveToPoint(a.clientX,a.clientY)}catch(d){}v.setEndPoint(0>w.compareEndPoints("StartToStart",b)?"EndToEnd":"StartToStart",b);v.select()}}function b(){t.removeListener("mousemove",c);f.removeListener("mouseup",b);t.removeListener("mouseup",b);v.select()}a=a.data;if(a.getTarget().is("html")&&a.$.yCKEDITOR.env.version)t.on("mousedown",function(a){a.data.getTarget().is("html")&&(f.on("mouseup",c),t.on("mouseup",c))})}}h.attachListener(h,"selectionchange",m,b);h.attachListener(h,"keyup",k,b);h.attachListener(h,"touchstart",k,b);h.attachListener(h,"touchend",k,b);CKEDITOR.env.ie&&h.attachListener(h, -"keydown",d,b);h.attachListener(h,CKEDITOR.env.webkit||CKEDITOR.env.gecko?"focusin":"focus",function(){b.forceNextSelectionCheck();b.selectionChange(1)});if(y&&(CKEDITOR.env.webkit||CKEDITOR.env.gecko)){var z;h.attachListener(h,"mousedown",function(){z=1});h.attachListener(e.getDocumentElement(),"mouseup",function(){z&&k.call(b);z=0})}else h.attachListener(CKEDITOR.env.ie?h:e.getDocumentElement(),"mouseup",k,b);CKEDITOR.env.webkit&&h.attachListener(e,"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:h.hasFocus&& +d.next()}}return a}var r="function"!=typeof window.getSelection,x=1,t=CKEDITOR.tools.repeat("​",7),z=new RegExp(t+"( )?","g"),u,w,B,C=CKEDITOR.dom.walker.invisible(1),A=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(){t=new CKEDITOR.dom.selection(b.getSelection());t.lock()}function c(){f.removeListener("mouseup", +c);q.removeListener("mouseup",c);var a=CKEDITOR.document.$.selection,b=a.createRange();"None"!=a.type&&b.parentElement()&&b.parentElement().ownerDocument==e.$&&b.select()}function d(a){var c,b;c=(c=this.document.getActive())?"input"===c.getName()||"textarea"===c.getName():!1;c||(c=this.getSelection(1),(b=g(c))&&!b.equals(h)&&(c.selectElement(b),a.data.preventDefault()))}function g(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 e=b.document,f=CKEDITOR.document,h=b.editable(),m=e.getBody(),q=e.getDocumentElement(),y=h.isInline(),u,t;CKEDITOR.env.gecko&&h.attachListener(h,"focus",function(a){a.removeListener();0!==u&&(a=b.getSelection().getNative())&&a.isCollapsed&&a.anchorNode==h.$&&(a=b.createRange(),a.moveToElementEditStart(h),a.select())},null,null,-2);h.attachListener(h,CKEDITOR.env.webkit||CKEDITOR.env.gecko?"focusin":"focus",function(){if(u&&(CKEDITOR.env.webkit|| +CKEDITOR.env.gecko)){u=b._.previousActive&&b._.previousActive.equals(e.getActive());var a=null!=b._.previousScrollTop&&b._.previousScrollTop!=h.$.scrollTop;CKEDITOR.env.webkit&&u&&a&&(h.$.scrollTop=b._.previousScrollTop)}b.unlockSelection(u);u=0},null,null,-1);h.attachListener(h,"mousedown",function(){u=0});if(CKEDITOR.env.ie||CKEDITOR.env.gecko||y)r?h.attachListener(h,"beforedeactivate",a,null,null,-1):h.attachListener(b,"selectionCheck",a,null,null,-1),h.attachListener(h,CKEDITOR.env.webkit||CKEDITOR.env.gecko? +"focusout":"blur",function(){var a=t&&(t.isFake||2>t.getRanges().length);CKEDITOR.env.gecko&&!y&&a||(b.lockSelection(t),u=1)},null,null,-1),h.attachListener(h,"mousedown",function(){u=0});if(CKEDITOR.env.ie&&!y){var w;h.attachListener(h,"mousedown",function(a){2==a.data.$.button&&((a=b.document.getSelection())&&a.getType()!=CKEDITOR.SELECTION_NONE||(w=b.window.getScrollPosition()))});h.attachListener(h,"mouseup",function(a){2==a.data.$.button&&w&&(b.document.$.documentElement.scrollLeft=w.x,b.document.$.documentElement.scrollTop= +w.y);w=null});if("BackCompat"!=e.$.compatMode){if(CKEDITOR.env.ie7Compat||CKEDITOR.env.ie6Compat){var x,v;q.on("mousedown",function(a){function c(a){a=a.data.$;if(x){var b=m.$.createTextRange();try{b.moveToPoint(a.clientX,a.clientY)}catch(d){}x.setEndPoint(0>v.compareEndPoints("StartToStart",b)?"EndToEnd":"StartToStart",b);x.select()}}function b(){q.removeListener("mousemove",c);f.removeListener("mouseup",b);q.removeListener("mouseup",b);x.select()}a=a.data;if(a.getTarget().is("html")&&a.$.yCKEDITOR.env.version)q.on("mousedown",function(a){a.data.getTarget().is("html")&&(f.on("mouseup",c),q.on("mouseup",c))})}}h.attachListener(h,"selectionchange",k,b);h.attachListener(h,"keyup",l,b);h.attachListener(h,"touchstart",l,b);h.attachListener(h,"touchend",l,b);CKEDITOR.env.ie&&h.attachListener(h, +"keydown",d,b);h.attachListener(h,CKEDITOR.env.webkit||CKEDITOR.env.gecko?"focusin":"focus",function(){b.forceNextSelectionCheck();b.selectionChange(1)});if(y&&(CKEDITOR.env.webkit||CKEDITOR.env.gecko)){var z;h.attachListener(h,"mousedown",function(){z=1});h.attachListener(e.getDocumentElement(),"mouseup",function(){z&&l.call(b);z=0})}else h.attachListener(CKEDITOR.env.ie?h:e.getDocumentElement(),"mouseup",l,b);CKEDITOR.env.webkit&&h.attachListener(e,"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:h.hasFocus&& n(h)}},null,null,-1);h.attachListener(h,"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 d=A[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=y(a.data))},c,null,20);c.on("toDataFormat",function(a){a.data.dataValue=y(a.data.dataValue)},null,null,0)});CKEDITOR.editor.prototype.selectionChange=function(a){(a?m:k).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.getSelectedRanges=function(a){var c=this.getSelection();return c&&c.getRanges(a)||[]};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:x++;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 E={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:y,_createFillingCharSequenceNode:g,FILLING_CHAR_SEQUENCE:u});CKEDITOR.dom.selection.prototype={getNative:function(){return void 0!==this._.cache.nativeSel?this._.cache.nativeSel:this._.cache.nativeSel=r?this.document.$.selection:this.document.getWindow().$.getSelection()},getType:r?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&&E[d.childNodes[b.startOffset].nodeName.toLowerCase()]&& -(c=CKEDITOR.SELECTION_ELEMENT)}return a.type=c},getRanges:function(){var a=r?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(),n=0,m=g.length-1,k=-1,l,r;n<=m;)if(k=Math.floor((n+m)/2),e=g[k],h.moveToElementText(e),l=h.compareEndPoints("StartToStart",c),0l)n=k+1;else return{container:d,offset:a(e)}; -if(-1==k||k==g.length-1&&0>l){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;0d.length?this.selectElement(b):this.selectRanges(d))}},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=x++},selectElement:function(a){var c=new CKEDITOR.dom.range(this.root);c.setStartBefore(a);c.setEndAfter(a);this.selectRanges([c])},selectRanges:function(c){var b=this.root.editor,e=b&&b._.hiddenSelectionContainer;this.reset();if(e)for(var e=this.root,f,m=0;m]*>)[ \t\r\n]*/gi,"$1");f=f.replace(/([ \t\n\r]+| )/g, -" ");f=f.replace(/]*>/gi,"\n");if(CKEDITOR.env.ie){var h=a.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);c=e}else f?c=y(b?[a.getHtml()]:g(a),c):a.moveChildren(c);c.replace(a);if(d){var b=c,k;(k=b.getPrevious(C))&&k.type==CKEDITOR.NODE_ELEMENT&&k.is("pre")&&(d=n(k.getHtml(),/\n$/,"")+"\n\n"+n(b.getHtml(),/^\n/,""),CKEDITOR.env.ie?b.$.outerHTML="\x3cpre\x3e"+d+"\x3c/pre\x3e": +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=y(a.data))},c,null,20);c.on("toDataFormat",function(a){a.data.dataValue=y(a.data.dataValue)},null,null,0)});CKEDITOR.editor.prototype.selectionChange=function(a){(a?k:l).call(this)};CKEDITOR.editor.prototype.getSelection=function(a){return!this._.savedSelection&&!this._.fakeSelection|| +a?(a=this.editable())&&"wysiwyg"==this.mode&&"recreating"!==this.status?new CKEDITOR.dom.selection(a):null:this._.savedSelection||this._.fakeSelection};CKEDITOR.editor.prototype.getSelectedRanges=function(a){var c=this.getSelection();return c&&c.getRanges(a)||[]};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:x++;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 E={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:y,_createFillingCharSequenceNode:g,FILLING_CHAR_SEQUENCE:t});CKEDITOR.dom.selection.prototype={getNative:function(){return void 0!==this._.cache.nativeSel?this._.cache.nativeSel:this._.cache.nativeSel=r?this.document.$.selection:this.document.getWindow().$.getSelection()},getType:r?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&&E[d.childNodes[b.startOffset].nodeName.toLowerCase()]&&(c=CKEDITOR.SELECTION_ELEMENT)}return a.type=c},getRanges:function(){var a=r?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),0m)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;0d.length?this.selectElement(b):this.selectRanges(d))}},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=x++},selectElement:function(a){var c=new CKEDITOR.dom.range(this.root);c.setStartBefore(a);c.setEndAfter(a);this.selectRanges([c])},selectRanges:function(c){var b=this.root.editor,e=b&&b._.hiddenSelectionContainer;this.reset(); +if(e)for(var e=this.root,f,k=0;k]*>)[ \t\r\n]*/gi,"$1");f=f.replace(/([ \t\n\r]+| )/g, +" ");f=f.replace(/]*>/gi,"\n");if(CKEDITOR.env.ie){var h=a.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);c=e}else f?c=y(b?[a.getHtml()]:g(a),c):a.moveChildren(c);c.replace(a);if(d){var b=c,k;(k=b.getPrevious(D))&&k.type==CKEDITOR.NODE_ELEMENT&&k.is("pre")&&(d=n(k.getHtml(),/\n$/,"")+"\n\n"+n(b.getHtml(),/^\n/,""),CKEDITOR.env.ie?b.$.outerHTML="\x3cpre\x3e"+d+"\x3c/pre\x3e": b.setHtml(d),k.remove())}else b&&r(c)}function g(a){var c=[];n(a.getOuterHtml(),/(\S\s*)\n(?:\s|(]+data-cke-bookmark.*?\/span>))*\n(?!$)/gi,function(a,c,b){return c+"\x3c/pre\x3e"+b+"\x3cpre\x3e"}).replace(/([\s\S]*?)<\/pre>/gi,function(a,b){c.push(b)});return c}function n(a,c,b){var d="",g="";a=a.replace(/(^]+data-cke-bookmark.*?\/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 y(a,c){var b; 1=b&&a<=e}function a(a){a=a.toString(16);return 1==a.length?"0"+a:a}CKEDITOR.tools.color=CKEDITOR.tools.createClass({$:function(a,b){this._.initialColorCode=a;this._.defaultValue=b;this._.parseInput(a)},proto:{getHex:function(){if(!this._.isValidColor)return this._.defaultValue;var a=this._.blendAlphaColor(this._.red,this._.green,this._.blue,this._.alpha);return this._.formatHexString(a[0],a[1],a[2])},getHexWithAlpha:function(){if(!this._.isValidColor)return this._.defaultValue; -var a=Math.round(this._.alpha*CKEDITOR.tools.color.MAX_RGB_CHANNEL_VALUE);return this._.formatHexString(this._.red,this._.green,this._.blue,a)},getRgb:function(){if(!this._.isValidColor)return this._.defaultValue;var a=this._.blendAlphaColor(this._.red,this._.green,this._.blue,this._.alpha);return this._.formatRgbString("rgb",a[0],a[1],a[2])},getRgba:function(){return this._.isValidColor?this._.formatRgbString("rgba",this._.red,this._.green,this._.blue,this._.alpha):this._.defaultValue},getHsl:function(){if(!this._.isValidColor)return this._.defaultValue; -var a=this._.blendAlphaColor(this._.red,this._.green,this._.blue,this._.alpha),a=this._.rgbToHsl(a[0],a[1],a[2]);return this._.formatHslString("hsl",a[0],a[1],a[2])},getHsla:function(){if(!this._.isValidColor)return this._.defaultValue;var a=this._.rgbToHsl(this._.red,this._.green,this._.blue);return this._.formatHslString("hsla",a[0],a[1],a[2],this._.alpha)},getInitialValue:function(){return this._.initialColorCode}},_:{initialColorCode:"",isValidColor:!0,red:0,green:0,blue:0,alpha:1,blendAlphaColor:function(a, -b,e,c){return CKEDITOR.tools.array.map([a,b,e],function(a){return Math.round(CKEDITOR.tools.color.MAX_RGB_CHANNEL_VALUE-c*(CKEDITOR.tools.color.MAX_RGB_CHANNEL_VALUE-a))})},formatHexString:function(b,e,f,c){b="#"+a(b)+a(e)+a(f);void 0!==c&&(b+=a(c));return b.toUpperCase()},formatRgbString:function(a,b,e,c,d){b=[b,e,c];void 0!==d&&b.push(d);return a+"("+b.join(",")+")"},formatHslString:function(a,b,e,c,d){return a+"("+b+","+e+"%,"+c+"%"+(void 0!==d?","+d:"")+")"},parseInput:function(a){if("string"!== -typeof a)this._.isValidColor=!1;else{a=CKEDITOR.tools.trim(a);var b=this._.matchStringToNamedColor(a);b&&(a=b);var b=this._.extractColorChannelsFromHex(a),e=this._.extractColorChannelsFromRgba(a);a=this._.extractColorChannelsFromHsla(a);(a=b||e||a)?(this._.red=a[0],this._.green=a[1],this._.blue=a[2],this._.alpha=a[3]):this._.isValidColor=!1}},matchStringToNamedColor:function(a){return CKEDITOR.tools.color.namedColors[a.toLowerCase()]||null},extractColorChannelsFromHex:function(a){a.match(CKEDITOR.tools.color.hex3CharsRegExp)&& -(a=this._.hex3ToHex6(a));if(!a.match(CKEDITOR.tools.color.hex6CharsRegExp)&&!a.match(CKEDITOR.tools.color.hex8CharsRegExp))return null;a=a.split("");var b=1;a[7]&&a[8]&&(b=parseInt(a[7]+a[8],16),b/=CKEDITOR.tools.color.MAX_RGB_CHANNEL_VALUE,b=Number(b.toFixed(1)));return[parseInt(a[1]+a[2],16),parseInt(a[3]+a[4],16),parseInt(a[5]+a[6],16),b]},extractColorChannelsFromRgba:function(a){var e=this._.extractColorChannelsByPattern(a,CKEDITOR.tools.color.rgbRegExp);if(!e||(a=0===a.indexOf("rgba"))&&4!== -e.length||!a&&3!==e.length)return null;var f=b(e[0],CKEDITOR.tools.color.MAX_RGB_CHANNEL_VALUE),c=b(e[1],CKEDITOR.tools.color.MAX_RGB_CHANNEL_VALUE),d=b(e[2],CKEDITOR.tools.color.MAX_RGB_CHANNEL_VALUE),g=1;a&&(g=h(e[3],CKEDITOR.tools.color.MAX_ALPHA_CHANNEL_VALUE));return this._.areColorChannelsValid(f,c,d,g)?[f,c,d,g]:null},extractColorChannelsFromHsla:function(a){var e=this._.extractColorChannelsByPattern(a,CKEDITOR.tools.color.hslRegExp);if(!e||(a=0===a.indexOf("hsla"))&&4!==e.length||!a&&3!== -e.length)return null;var f=b(e[0],CKEDITOR.tools.color.MAX_HUE_CHANNEL_VALUE),c=h(e[1],CKEDITOR.tools.color.MAX_SATURATION_LIGHTNESS_CHANNEL_VALUE),d=h(e[2],CKEDITOR.tools.color.MAX_SATURATION_LIGHTNESS_CHANNEL_VALUE),g=1,f=this._.hslToRgb(f,c,d);a&&(g=h(e[3],CKEDITOR.tools.color.MAX_ALPHA_CHANNEL_VALUE));f.push(g);return this._.areColorChannelsValid(f[0],f[1],f[2],f[3])?f:null},hex3ToHex6:function(a){a=a.split("");return"#"+a[1]+a[1]+a[2]+a[2]+a[3]+a[3]},extractColorChannelsByPattern:function(a, -b){var e=a.match(b);if(!e)return null;e=e[2].split(",");return e=CKEDITOR.tools.array.map(e,function(a){return CKEDITOR.tools.trim(a)})},areColorChannelsValid:function(a,b,f,c){return e(a,0,CKEDITOR.tools.color.MAX_RGB_CHANNEL_VALUE)&&e(b,0,CKEDITOR.tools.color.MAX_RGB_CHANNEL_VALUE)&&e(f,0,CKEDITOR.tools.color.MAX_RGB_CHANNEL_VALUE)&&e(c,0,CKEDITOR.tools.color.MAX_ALPHA_CHANNEL_VALUE)},hslToRgb:function(a,b,e){var c=function(c){var g=(c+a/30)%12;c=b*Math.min(e,1-e);g=Math.min(g-3,9-g,1);g=Math.max(-1, -g);return Math.round((e-c*g)*CKEDITOR.tools.color.MAX_RGB_CHANNEL_VALUE)};return[c(0),c(8),c(4)]},rgbToHsl:function(a,b,e){a/=CKEDITOR.tools.color.MAX_RGB_CHANNEL_VALUE;b/=CKEDITOR.tools.color.MAX_RGB_CHANNEL_VALUE;var c=e/CKEDITOR.tools.color.MAX_RGB_CHANNEL_VALUE,d=Math.max(a,b,c),g=Math.min(a,b,c);e=d-g;var f=0;switch(d){case a:f=(b-c)/e%6;break;case b:f=(c-a)/e+2;break;case c:f=(a-b)/e+4}a=0===e?0:60*f;b=(d+g)/2;d=0;1!==b&&0!==b&&(d=e/(1-Math.abs(2*b-1)));a=Math.round(a);d=100*Math.round(d);return[a, -d,100*b]}},statics:{MAX_RGB_CHANNEL_VALUE:255,MAX_ALPHA_CHANNEL_VALUE:1,MAX_HUE_CHANNEL_VALUE:360,MAX_SATURATION_LIGHTNESS_CHANNEL_VALUE:1,hex3CharsRegExp:/#([0-9a-f]{3}$)/gim,hex6CharsRegExp:/#([0-9a-f]{6}$)/gim,hex8CharsRegExp:/#([0-9a-f]{8}$)/gim,rgbRegExp:/(rgb[a]?)\(([.,\d\s%]*)\)/i,hslRegExp:/(hsl[a]?)\(([.,\d\s%]*)\)/i,namedColors:{aliceblue:"#F0F8FF",antiquewhite:"#FAEBD7",aqua:"#00FFFF",aquamarine:"#7FFFD4",azure:"#F0FFFF",beige:"#F5F5DC",bisque:"#FFE4C4",black:"#000000",blanchedalmond:"#FFEBCD", -blue:"#0000FF",blueviolet:"#8A2BE2",brown:"#A52A2A",burlywood:"#DEB887",cadetblue:"#5F9EA0",chartreuse:"#7FFF00",chocolate:"#D2691E",coral:"#FF7F50",cornflowerblue:"#6495ED",cornsilk:"#FFF8DC",crimson:"#DC143C",cyan:"#00FFFF",darkblue:"#00008B",darkcyan:"#008B8B",darkgoldenrod:"#B8860B",darkgray:"#A9A9A9",darkgreen:"#006400",darkgrey:"#A9A9A9",darkkhaki:"#BDB76B",darkmagenta:"#8B008B",darkolivegreen:"#556B2F",darkorange:"#FF8C00",darkorchid:"#9932CC",darkred:"#8B0000",darksalmon:"#E9967A",darkseagreen:"#8FBC8F", -darkslateblue:"#483D8B",darkslategray:"#2F4F4F",darkslategrey:"#2F4F4F",darkturquoise:"#00CED1",darkviolet:"#9400D3",deeppink:"#FF1493",deepskyblue:"#00BFFF",dimgray:"#696969",dimgrey:"#696969",dodgerblue:"#1E90FF",firebrick:"#B22222",floralwhite:"#FFFAF0",forestgreen:"#228B22",fuchsia:"#FF00FF",gainsboro:"#DCDCDC",ghostwhite:"#F8F8FF",gold:"#FFD700",goldenrod:"#DAA520",gray:"#808080",green:"#008000",greenyellow:"#ADFF2F",grey:"#808080",honeydew:"#F0FFF0",hotpink:"#FF69B4",indianred:"#CD5C5C",indigo:"#4B0082", -ivory:"#FFFFF0",khaki:"#F0E68C",lavender:"#E6E6FA",lavenderblush:"#FFF0F5",lawngreen:"#7CFC00",lemonchiffon:"#FFFACD",lightblue:"#ADD8E6",lightcoral:"#F08080",lightcyan:"#E0FFFF",lightgoldenrodyellow:"#FAFAD2",lightgray:"#D3D3D3",lightgreen:"#90EE90",lightgrey:"#D3D3D3",lightpink:"#FFB6C1",lightsalmon:"#FFA07A",lightseagreen:"#20B2AA",lightskyblue:"#87CEFA",lightslategray:"#778899",lightslategrey:"#778899",lightsteelblue:"#B0C4DE",lightyellow:"#FFFFE0",lime:"#00FF00",limegreen:"#32CD32",linen:"#FAF0E6", -magenta:"#FF00FF",maroon:"#800000",mediumaquamarine:"#66CDAA",mediumblue:"#0000CD",mediumorchid:"#BA55D3",mediumpurple:"#9370DB",mediumseagreen:"#3CB371",mediumslateblue:"#7B68EE",mediumspringgreen:"#00FA9A",mediumturquoise:"#48D1CC",mediumvioletred:"#C71585",midnightblue:"#191970",mintcream:"#F5FFFA",mistyrose:"#FFE4E1",moccasin:"#FFE4B5",navajowhite:"#FFDEAD",navy:"#000080",oldlace:"#FDF5E6",olive:"#808000",olivedrab:"#6B8E23",orange:"#FFA500",orangered:"#FF4500",orchid:"#DA70D6",palegoldenrod:"#EEE8AA", -palegreen:"#98FB98",paleturquoise:"#AFEEEE",palevioletred:"#DB7093",papayawhip:"#FFEFD5",peachpuff:"#FFDAB9",peru:"#CD853F",pink:"#FFC0CB",plum:"#DDA0DD",powderblue:"#B0E0E6",purple:"#800080",rebeccapurple:"#663399",red:"#FF0000",rosybrown:"#BC8F8F",royalblue:"#4169E1",saddlebrown:"#8B4513",salmon:"#FA8072",sandybrown:"#F4A460",seagreen:"#2E8B57",seashell:"#FFF5EE",sienna:"#A0522D",silver:"#C0C0C0",skyblue:"#87CEEB",slateblue:"#6A5ACD",slategray:"#708090",slategrey:"#708090",snow:"#FFFAFA",springgreen:"#00FF7F", -steelblue:"#4682B4",tan:"#D2B48C",teal:"#008080",thistle:"#D8BFD8",tomato:"#FF6347",turquoise:"#40E0D0",violet:"#EE82EE",windowtext:"windowtext",wheat:"#F5DEB3",white:"#FFFFFF",whitesmoke:"#F5F5F5",yellow:"#FFFF00",yellowgreen:"#9ACD32"}}});CKEDITOR.tools.style.parse._colors=CKEDITOR.tools.color.namedColors}(),CKEDITOR.dom.comment=function(b,h){"string"==typeof b&&(b=(h?h.$:document).createComment(b));CKEDITOR.dom.domObject.call(this,b)},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 b={},h={},f;for(f in CKEDITOR.dtd.$blockLimit)f in CKEDITOR.dtd.$list||(b[f]=1);for(f in CKEDITOR.dtd.$block)f in CKEDITOR.dtd.$blockLimit||f in CKEDITOR.dtd.$empty||(h[f]=1);CKEDITOR.dom.elementPath=function(e,a){var f=null,k=null,l=[],c=e,d;a=a||e.getDocument().getBody();c||(c=a);do if(c.type==CKEDITOR.NODE_ELEMENT){l.push(c);if(!this.lastElement&&(this.lastElement=c,c.is(CKEDITOR.dtd.$object)|| -"false"==c.getAttribute("contenteditable")))continue;if(c.equals(a))break;if(!k&&(d=c.getName(),"true"==c.getAttribute("contenteditable")?k=c:!f&&h[d]&&(f=c),b[d])){if(d=!f&&"div"==d){a:{d=c.getChildren();for(var g=0,n=d.count();g=e?(m=a.createText(""),m.insertAfter(this)):(b=a.createText(""),b.insertAfter(m),b.remove()));return m},substring:function(b,h){return"number"!=typeof h?this.$.nodeValue.substr(b):this.$.nodeValue.substring(b,h)}}),function(){function b(b,e,a){var h=b.serializable,k=e[a?"endContainer":"startContainer"],l=a?"endOffset":"startOffset",c=h?e.document.getById(b.startNode):b.startNode;b=h?e.document.getById(b.endNode):b.endNode;k.equals(c.getPrevious())?(e.startOffset=e.startOffset- -k.getLength()-b.getPrevious().getLength(),k=b.getNext()):k.equals(b.getPrevious())&&(e.startOffset-=k.getLength(),k=b.getNext());k.equals(c.getParent())&&e[l]++;k.equals(b.getParent())&&e[l]++;e[a?"endContainer":"startContainer"]=k;return e}CKEDITOR.dom.rangeList=function(b){if(b instanceof CKEDITOR.dom.rangeList)return b;b?b instanceof CKEDITOR.dom.range&&(b=[b]):b=[];return CKEDITOR.tools.extend(b,h)};var h={createIterator:function(){var b=this,e=CKEDITOR.dom.walker.bookmark(),a=[],h;return{getNextRange:function(k){h= -void 0===h?0:h+1;var l=b[h];if(l&&1c?-1:1}),f=0,h;fCKEDITOR.env.version?a[k].$.styleSheet.cssText+=h:a[k].$.innerHTML+=h}}var m={};CKEDITOR.skin={path:b,loadPart:function(a,c){CKEDITOR.skin.name!=CKEDITOR.skinName.split(",")[0]? -CKEDITOR.scriptLoader.load(CKEDITOR.getUrl(b()+"skin.js"),function(){f(a,c)}):f(a,c)},getPath:function(a){return CKEDITOR.getUrl(h(a))},icons:{},addIcon:function(a,c,b,e){a=a.toLowerCase();this.icons[a]||(this.icons[a]={path:c,offset:b||0,bgsize:e||"16px"})},getIconStyle:function(a,c,b,e,f){var h;a&&(a=a.toLowerCase(),c&&(h=this.icons[a+"-rtl"]),h||(h=this.icons[a]));a=b||h&&h.path||"";e=e||h&&h.offset;f=f||h&&h.bgsize||"16px";a&&(a=a.replace(/'/g,"\\'"));return a&&"background-image:url('"+CKEDITOR.getUrl(a)+ -"');background-position:0 "+e+"px;background-size:"+f+";"}};CKEDITOR.tools.extend(CKEDITOR.editor.prototype,{getUiColor:function(){return this.uiColor},setUiColor:function(b){var g=e(CKEDITOR.document);return(this.setUiColor=function(b){this.uiColor=b;var d=CKEDITOR.skin.chameleon,e="",f="";"function"==typeof d&&(e=d(this,"editor"),f=d(this,"panel"));b=[[c,b]];a([g],e,b);a(l,f,b)}).call(this,b)}});var k="cke_ui_color",l=[],c=/\$color/g;CKEDITOR.on("instanceLoaded",function(b){if(!CKEDITOR.env.ie|| -!CKEDITOR.env.quirks){var g=b.editor;b=function(b){b=(b.data[0]||b.data).element.getElementsByTag("iframe").getItem(0).getFrameDocument();if(!b.getById("cke_ui_color")){var d=e(b);l.push(d);g.on("destroy",function(){l=CKEDITOR.tools.array.filter(l,function(a){return d!==a})});(b=g.getUiColor())&&a([d],CKEDITOR.skin.chameleon(g,"panel"),[[c,b]])}};g.on("panelShow",b);g.on("menuShow",b);g.config.uiColor&&g.setUiColor(g.config.uiColor)}})}(),function(){var b=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);b.appendTo(CKEDITOR.document.getHead());try{var h=b.getComputedStyle("border-top-color"),f=b.getComputedStyle("border-right-color");CKEDITOR.env.hc=!(!h||h!=f)}catch(e){CKEDITOR.env.hc=!1}b.remove();CKEDITOR.env.hc&&(CKEDITOR.env.cssClass+=" cke_hc");CKEDITOR.document.appendStyleText(".cke{visibility:hidden;}");CKEDITOR.status="loaded";CKEDITOR.fireOnce("loaded");if(b=CKEDITOR._.pending)for(delete CKEDITOR._.pending,h=0;hh;h++){var k=h,l;l=parseInt(a[h],16);l=("0"+(0>e?0|l*(1+e):0|l+(255-l)*e).toString(16)).slice(-2);a[k]=l}return"#"+a.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};] "), +function(h){if(!h)return CKEDITOR.error("no-vendor-lib",{path:b});if("undefined"!==typeof window.ES6Promise)return CKEDITOR.tools.promise=ES6Promise})}}(),function(){function b(b,a,k){b.once("selectionCheck",function(b){if(!h){var e=b.data.getRanges()[0];k.equals(e)?b.cancel():a.equals(e)&&(f=!0)}},null,null,-1)}var h=!0,f=!1;CKEDITOR.dom.selection.setupEditorOptimization=function(b){b.on("selectionCheck",function(a){a.data&&!f&&a.data.optimizeInElementEnds();f=!1});b.on("contentDom",function(){var a= +b.editable();a&&(a.attachListener(a,"keydown",function(a){this._.shiftPressed=a.data.$.shiftKey},this),a.attachListener(a,"keyup",function(a){this._.shiftPressed=a.data.$.shiftKey},this))})};CKEDITOR.dom.selection.prototype.optimizeInElementEnds=function(){var e=this.getRanges()[0],a=this.root.editor,f;if(this.root.editor._.shiftPressed||this.isFake||e.isCollapsed||e.startContainer.equals(e.endContainer))f=!1;else if(0===e.endOffset)f=!0;else{f=e.startContainer.type===CKEDITOR.NODE_TEXT;var l=e.endContainer.type=== +CKEDITOR.NODE_TEXT,m=f?e.startContainer.getLength():e.startContainer.getChildCount();f=e.startOffset===m||f^l}f&&(f=e.clone(),e.shrink(CKEDITOR.SHRINK_TEXT,!1,{skipBogus:!CKEDITOR.env.webkit}),h=!1,b(a,e,f),e.select(),h=!0)}}(),function(){function b(a,b){if(f(a))a=Math.round(b*(parseFloat(a)/100));else if("string"===typeof a&&a.match(/^\d+$/gm)||"string"===typeof a&&a.match(/^\d+(?:deg)?$/gm))a=parseInt(a,10);return a}function h(a,b){f(a)?a=b*(parseFloat(a)/100):"string"===typeof a&&a.match(/^\d?\.\d+/gm)&& +(a=parseFloat(a));return a}function f(a){return"string"===typeof a&&a.match(/^((\d*\.\d+)|(\d+))%{1}$/gm)}function e(a,b,e){return!isNaN(a)&&a>=b&&a<=e}function a(a){a=a.toString(16);return 1==a.length?"0"+a:a}CKEDITOR.tools.color=CKEDITOR.tools.createClass({$:function(a,b){this._.initialColorCode=a;this._.defaultValue=b;this._.parseInput(a)},proto:{getHex:function(){if(!this._.isValidColor)return this._.defaultValue;var a=this._.blendAlphaColor(this._.red,this._.green,this._.blue,this._.alpha);return this._.formatHexString(a[0], +a[1],a[2])},getHexWithAlpha:function(){if(!this._.isValidColor)return this._.defaultValue;var a=Math.round(this._.alpha*CKEDITOR.tools.color.MAX_RGB_CHANNEL_VALUE);return this._.formatHexString(this._.red,this._.green,this._.blue,a)},getRgb:function(){if(!this._.isValidColor)return this._.defaultValue;var a=this._.blendAlphaColor(this._.red,this._.green,this._.blue,this._.alpha);return this._.formatRgbString("rgb",a[0],a[1],a[2])},getRgba:function(){return this._.isValidColor?this._.formatRgbString("rgba", +this._.red,this._.green,this._.blue,this._.alpha):this._.defaultValue},getHsl:function(){var a=0===this._.alpha||1===this._.alpha;if(!this._.isValidColor)return this._.defaultValue;this._.type===CKEDITOR.tools.color.TYPE_HSL&&a?a=[this._.hue,this._.saturation,this._.lightness]:(a=this._.blendAlphaColor(this._.red,this._.green,this._.blue,this._.alpha),a=this._.rgbToHsl(a[0],a[1],a[2]));return this._.formatHslString("hsl",a[0],a[1],a[2])},getHsla:function(){var a;if(!this._.isValidColor)return this._.defaultValue; +a=this._.type===CKEDITOR.tools.color.TYPE_HSL?[this._.hue,this._.saturation,this._.lightness]:this._.rgbToHsl(this._.red,this._.green,this._.blue);return this._.formatHslString("hsla",a[0],a[1],a[2],this._.alpha)},getInitialValue:function(){return this._.initialColorCode}},_:{initialColorCode:"",isValidColor:!0,type:0,hue:0,saturation:0,lightness:0,red:0,green:0,blue:0,alpha:1,blendAlphaColor:function(a,b,e,c){return CKEDITOR.tools.array.map([a,b,e],function(a){return Math.round(CKEDITOR.tools.color.MAX_RGB_CHANNEL_VALUE- +c*(CKEDITOR.tools.color.MAX_RGB_CHANNEL_VALUE-a))})},formatHexString:function(b,e,f,c){b="#"+a(b)+a(e)+a(f);void 0!==c&&(b+=a(c));return b.toUpperCase()},formatRgbString:function(a,b,e,c,d){b=[b,e,c];void 0!==d&&b.push(d);return a+"("+b.join(",")+")"},formatHslString:function(a,b,e,c,d){return a+"("+b+","+e+"%,"+c+"%"+(void 0!==d?","+d:"")+")"},parseInput:function(a){if("string"!==typeof a)this._.isValidColor=!1;else{a=CKEDITOR.tools.trim(a);var b=this._.matchStringToNamedColor(a);b&&(a=b);var b= +this._.extractColorChannelsFromHex(a),e=this._.extractColorChannelsFromRgba(a);a=this._.extractColorChannelsFromHsla(a);(a=b||e||a)?(this._.type=a.type,this._.red=a.red,this._.green=a.green,this._.blue=a.blue,this._.alpha=a.alpha,a.type===CKEDITOR.tools.color.TYPE_HSL&&(this._.hue=a.hue,this._.saturation=a.saturation,this._.lightness=a.lightness)):this._.isValidColor=!1}},matchStringToNamedColor:function(a){return CKEDITOR.tools.color.namedColors[a.toLowerCase()]||null},extractColorChannelsFromHex:function(a){-1=== +a.indexOf("#")&&(a="#"+a);a.match(CKEDITOR.tools.color.hex3CharsRegExp)&&(a=this._.hex3ToHex6(a));a.match(CKEDITOR.tools.color.hex4CharsRegExp)&&(a=this._.hex4ToHex8(a));if(!a.match(CKEDITOR.tools.color.hex6CharsRegExp)&&!a.match(CKEDITOR.tools.color.hex8CharsRegExp))return null;a=a.split("");var b=1;a[7]&&a[8]&&(b=parseInt(a[7]+a[8],16),b/=CKEDITOR.tools.color.MAX_RGB_CHANNEL_VALUE,b=Number(b.toFixed(1)));return{type:CKEDITOR.tools.color.TYPE_RGB,red:parseInt(a[1]+a[2],16),green:parseInt(a[3]+a[4], +16),blue:parseInt(a[5]+a[6],16),alpha:b}},extractColorChannelsFromRgba:function(a){var e=this._.extractColorChannelsByPattern(a,CKEDITOR.tools.color.rgbRegExp);if(!e||3>e.length||4e.length||4=e?(k=a.createText(""),k.insertAfter(this)):(b=a.createText(""),b.insertAfter(k),b.remove()));return k},substring:function(b,h){return"number"!=typeof h?this.$.nodeValue.substr(b):this.$.nodeValue.substring(b,h)}}),function(){function b(b, +e,a){var h=b.serializable,l=e[a?"endContainer":"startContainer"],m=a?"endOffset":"startOffset",c=h?e.document.getById(b.startNode):b.startNode;b=h?e.document.getById(b.endNode):b.endNode;l.equals(c.getPrevious())?(e.startOffset=e.startOffset-l.getLength()-b.getPrevious().getLength(),l=b.getNext()):l.equals(b.getPrevious())&&(e.startOffset-=l.getLength(),l=b.getNext());l.equals(c.getParent())&&e[m]++;l.equals(b.getParent())&&e[m]++;e[a?"endContainer":"startContainer"]=l;return e}CKEDITOR.dom.rangeList= +function(b){if(b instanceof CKEDITOR.dom.rangeList)return b;b?b instanceof CKEDITOR.dom.range&&(b=[b]):b=[];return CKEDITOR.tools.extend(b,h)};var h={createIterator:function(){var b=this,e=CKEDITOR.dom.walker.bookmark(),a=[],h;return{getNextRange:function(l){h=void 0===h?0:h+1;var m=b[h];if(m&&1c?-1:1}),f=0,h;fCKEDITOR.env.version?a[k].$.styleSheet.cssText+=h:a[k].$.innerHTML+=h}}var k={};CKEDITOR.skin={path:b,loadPart:function(a,c){CKEDITOR.skin.name!=CKEDITOR.skinName.split(",")[0]?CKEDITOR.scriptLoader.load(CKEDITOR.getUrl(b()+"skin.js"),function(){f(a,c)}):f(a,c)},getPath:function(a){return CKEDITOR.getUrl(h(a))},icons:{},addIcon:function(a,c,b,e){a=a.toLowerCase();this.icons[a]||(this.icons[a]={path:c,offset:b||0,bgsize:e|| +"16px"})},getIconStyle:function(a,c,b,e,f){var h;a&&(a=a.toLowerCase(),c&&(h=this.icons[a+"-rtl"]),h||(h=this.icons[a]));a=b||h&&h.path||"";e=e||h&&h.offset;f=f||h&&h.bgsize||"16px";a&&(a=a.replace(/'/g,"\\'"));return a&&"background-image:url('"+CKEDITOR.getUrl(a)+"');background-position:0 "+e+"px;background-size:"+f+";"}};CKEDITOR.tools.extend(CKEDITOR.editor.prototype,{getUiColor:function(){return this.uiColor},setUiColor:function(b){var g=e(CKEDITOR.document);return(this.setUiColor=function(b){this.uiColor= +b;var d=CKEDITOR.skin.chameleon,e="",f="";"function"==typeof d&&(e=d(this,"editor"),f=d(this,"panel"));b=[[c,b]];a([g],e,b);a(m,f,b)}).call(this,b)}});var l="cke_ui_color",m=[],c=/\$color/g;CKEDITOR.on("instanceLoaded",function(b){if(!CKEDITOR.env.ie||!CKEDITOR.env.quirks){var g=b.editor;b=function(b){b=(b.data[0]||b.data).element.getElementsByTag("iframe").getItem(0).getFrameDocument();if(!b.getById("cke_ui_color")){var d=e(b);m.push(d);g.on("destroy",function(){m=CKEDITOR.tools.array.filter(m,function(a){return d!== +a})});(b=g.getUiColor())&&a([d],CKEDITOR.skin.chameleon(g,"panel"),[[c,b]])}};g.on("panelShow",b);g.on("menuShow",b);g.config.uiColor&&g.setUiColor(g.config.uiColor)}})}(),function(){var b=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);b.appendTo(CKEDITOR.document.getHead());try{var h=b.getComputedStyle("border-top-color"),f=b.getComputedStyle("border-right-color"); +CKEDITOR.env.hc=!(!h||h!=f)}catch(e){CKEDITOR.env.hc=!1}b.remove();CKEDITOR.env.hc&&(CKEDITOR.env.cssClass+=" cke_hc");CKEDITOR.document.appendStyleText(".cke{visibility:hidden;}");CKEDITOR.status="loaded";CKEDITOR.fireOnce("loaded");if(b=CKEDITOR._.pending)for(delete CKEDITOR._.pending,h=0;hh;h++){var l=h,m;m=parseInt(a[h],16);m=("0"+(0>e?0|m*(1+e):0|m+(255-m)*e).toString(16)).slice(-2);a[l]=m}return"#"+a.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(f,e){var a=b(f.uiColor,.4),a={id:"."+f.id,defaultBorder:b(a,-.2),toolbarElementsBorder:b(a,-.25),defaultBackground:a,lightBackground:b(a,.8),darkBackground:b(a,-.15),ckeButtonOn:b(a,.4),ckeResizer:b(a,-.4),ckeColorauto:b(a,.8),dialogBody:b(a,.7),dialogTab:b(a,.65),dialogTabSelected:"#FFF",dialogTabSelectedBorder:"#FFF",elementsPathColor:b(a,-.6),menubuttonHover:b(a,.1),menubuttonIcon:b(a,.5),menubuttonIconHover:b(a,.3)};return h[e].output(a).replace(/\[/g,"{").replace(/\]/g,"}")}}(), CKEDITOR.plugins.add("dialogui",{onLoad:function(){var b=function(a){this._||(this._={});this._["default"]=this._.initValue=a["default"]||"";this._.required=a.required||!1;for(var b=[this._],g=1;garguments.length)){var f=b.call(this,d);f.labelId=CKEDITOR.tools.getNextId()+ -"_label";this._.children=[];var h={role:d.role||"presentation"};d.includeLabel&&(h["aria-labelledby"]=f.labelId);CKEDITOR.ui.dialog.uiElement.call(this,a,d,g,"div",null,h,function(){var b=[],g=d.required?" cke_required":"";"horizontal"!=d.labelLayout?b.push('\x3clabel class\x3d"cke_dialog_ui_labeled_label'+g+'" ',' id\x3d"'+f.labelId+'"',f.inputId?' for\x3d"'+f.inputId+'"':"",(d.labelStyle?' style\x3d"'+d.labelStyle+'"':"")+"\x3e",d.label,"\x3c/label\x3e",'\x3cdiv class\x3d"cke_dialog_ui_labeled_content"', -d.controlStyle?' style\x3d"'+d.controlStyle+'"':"",' role\x3d"presentation"\x3e',e.call(this,a,d),"\x3c/div\x3e"):(g={type:"hbox",widths:d.widths,padding:0,children:[{type:"html",html:'\x3clabel class\x3d"cke_dialog_ui_labeled_label'+g+'" id\x3d"'+f.labelId+'" for\x3d"'+f.inputId+'"'+(d.labelStyle?' style\x3d"'+d.labelStyle+'"':"")+"\x3e"+CKEDITOR.tools.htmlEncode(d.label)+"\x3c/label\x3e"},{type:"html",html:'\x3cspan class\x3d"cke_dialog_ui_labeled_content"'+(d.controlStyle?' style\x3d"'+d.controlStyle+ -'"':"")+"\x3e"+e.call(this,a,d)+"\x3c/span\x3e"}]},CKEDITOR.dialog._.uiElementBuilders.hbox.build(a,g,b));return b.join("")})}},textInput:function(a,d,g){if(!(3>arguments.length)){b.call(this,d);var e=this._.inputId=CKEDITOR.tools.getNextId()+"_textInput",f={"class":"cke_dialog_ui_input_"+d.type,id:e,type:d.type};d.validate&&(this.validate=d.validate);d.maxLength&&(f.maxlength=d.maxLength);d.size&&(f.size=d.size);d.inputStyle&&(f.style=d.inputStyle);var h=this,k=!1;a.on("load",function(){h.getInputElement().on("keydown", -function(a){13==a.data.getKeystroke()&&(k=!0)});h.getInputElement().on("keyup",function(b){13==b.data.getKeystroke()&&k&&(a.getButton("ok")&&setTimeout(function(){a.getButton("ok").click()},0),k=!1);h.bidi&&l.call(h,b)},null,null,1E3)});CKEDITOR.ui.dialog.labeledElement.call(this,a,d,g,function(){var a=['\x3cdiv class\x3d"cke_dialog_ui_input_',d.type,'" role\x3d"presentation"'];d.width&&a.push('style\x3d"width:'+d.width+'" ');a.push("\x3e\x3cinput ");f["aria-labelledby"]=this._.labelId;this._.required&& -(f["aria-required"]=this._.required);for(var c in f)a.push(c+'\x3d"'+f[c]+'" ');a.push(" /\x3e\x3c/div\x3e");return a.join("")})}},textarea:function(a,d,g){if(!(3>arguments.length)){b.call(this,d);var e=this,f=this._.inputId=CKEDITOR.tools.getNextId()+"_textarea",h={};d.validate&&(this.validate=d.validate);h.rows=d.rows||5;h.cols=d.cols||20;h["class"]="cke_dialog_ui_input_textarea "+(d["class"]||"");"undefined"!=typeof d.inputStyle&&(h.style=d.inputStyle);d.dir&&(h.dir=d.dir);if(e.bidi)a.on("load", -function(){e.getInputElement().on("keyup",l)},e);CKEDITOR.ui.dialog.labeledElement.call(this,a,d,g,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"',f,'" '],c;for(c in h)a.push(c+'\x3d"'+CKEDITOR.tools.htmlEncode(h[c])+'" ');a.push("\x3e",CKEDITOR.tools.htmlEncode(e._["default"]),"\x3c/textarea\x3e\x3c/div\x3e");return a.join("")})}},checkbox:function(a, -d,g){if(!(3>arguments.length)){var e=b.call(this,d,{"default":!!d["default"]});d.validate&&(this.validate=d.validate);CKEDITOR.ui.dialog.uiElement.call(this,a,d,g,"span",null,null,function(){var b=CKEDITOR.tools.extend({},d,{id:d.id?d.id+"_checkbox":CKEDITOR.tools.getNextId()+"_checkbox"},!0),g=[],f=CKEDITOR.tools.getNextId()+"_label",h={"class":"cke_dialog_ui_checkbox_input",type:"checkbox","aria-labelledby":f};k(b);d["default"]&&(h.checked="checked");"undefined"!=typeof b.inputStyle&&(b.style=b.inputStyle); -e.checkbox=new CKEDITOR.ui.dialog.uiElement(a,b,g,"input",null,h);g.push(' \x3clabel id\x3d"',f,'" for\x3d"',h.id,'"'+(d.labelStyle?' style\x3d"'+d.labelStyle+'"':"")+"\x3e",CKEDITOR.tools.htmlEncode(d.label),"\x3c/label\x3e");return g.join("")})}},radio:function(a,d,g){if(!(3>arguments.length)){b.call(this,d);this._["default"]||(this._["default"]=this._.initValue=d.items[0][1]);d.validate&&(this.validate=d.validate);var e=[],f=this;d.role="radiogroup";d.includeLabel=!0;CKEDITOR.ui.dialog.labeledElement.call(this, -a,d,g,function(){for(var b=[],g=[],h=(d.id?d.id:CKEDITOR.tools.getNextId())+"_radio",l=0;larguments.length)){var e=b.call(this,d);d.validate&&(this.validate=d.validate);e.inputId=CKEDITOR.tools.getNextId()+"_select";CKEDITOR.ui.dialog.labeledElement.call(this,a,d,g,function(){var b=CKEDITOR.tools.extend({},d,{id:d.id?d.id+"_select":CKEDITOR.tools.getNextId()+"_select"},!0),g=[],f=[],h={id:e.inputId,"class":"cke_dialog_ui_input_select","aria-labelledby":this._.labelId};g.push('\x3cdiv class\x3d"cke_dialog_ui_input_', -d.type,'" role\x3d"presentation"');d.width&&g.push('style\x3d"width:'+d.width+'" ');g.push("\x3e");void 0!==d.size&&(h.size=d.size);void 0!==d.multiple&&(h.multiple=d.multiple);k(b);for(var l=0,m;larguments.length)){void 0===d["default"]&&(d["default"]="");var e=CKEDITOR.tools.extend(b.call(this,d),{definition:d,buttons:[]});d.validate&&(this.validate=d.validate);a.on("load",function(){CKEDITOR.document.getById(e.frameId).getParent().addClass("cke_dialog_ui_input_file")});CKEDITOR.ui.dialog.labeledElement.call(this,a,d,g,function(){e.frameId=CKEDITOR.tools.getNextId()+"_fileInput";var a=['\x3ciframe frameborder\x3d"0" allowtransparency\x3d"0" class\x3d"cke_dialog_ui_input_file" role\x3d"presentation" id\x3d"', -e.frameId,'" title\x3d"',d.label,'" src\x3d"javascript:void('];a.push(CKEDITOR.env.ie?"(function(){"+encodeURIComponent("document.open();("+CKEDITOR.tools.fixDomain+")();document.close();")+"})()":"0");a.push(')"\x3e\x3c/iframe\x3e');return a.join("")})}},fileButton:function(a,d,g){var e=this;if(!(3>arguments.length)){b.call(this,d);d.validate&&(this.validate=d.validate);var f=CKEDITOR.tools.extend({},d),h=f.onClick;f.className=(f.className?f.className+" ":"")+"cke_dialog_ui_button";f.onClick=function(b){var g= -d["for"];b=h?h.call(this,b):!1;!1!==b&&("xhr"!==b&&a.getContentElement(g[0],g[1]).submit(),this.disable())};a.on("load",function(){a.getContentElement(d["for"][0],d["for"][1])._.buttons.push(e)});CKEDITOR.ui.dialog.button.call(this,a,f,g)}},html:function(){var a=/^\s*<[\w:]+\s+([^>]*)?>/,b=/^(\s*<[\w:]+(?:\s+[^>]*)?)((?:.|\r|\n)+)$/,g=/\/$/;return function(e,f,h){if(!(3>arguments.length)){var k=[],l=f.html;"\x3c"!=l.charAt(0)&&(l="\x3cspan\x3e"+l+"\x3c/span\x3e");var m=f.focus;if(m){var x=this.focus; -this.focus=function(){("function"==typeof m?m:x).call(this);this.fire("focus")};f.isFocusable&&(this.isFocusable=this.isFocusable);this.keyboardFocusable=!0}CKEDITOR.ui.dialog.uiElement.call(this,e,f,k,"span",null,null,"");k=k.join("").match(a);l=l.match(b)||["","",""];g.test(l[1])&&(l[1]=l[1].slice(0,-1),l[2]="/"+l[2]);h.push([l[1]," ",k[1]||"",l[2]].join(""))}}}(),fieldset:function(a,b,g,e,f){var h=f.label;this._={children:b};CKEDITOR.ui.dialog.uiElement.call(this,a,f,e,"fieldset",null,null,function(){var a= -[];h&&a.push("\x3clegend"+(f.labelStyle?' style\x3d"'+f.labelStyle+'"':"")+"\x3e"+h+"\x3c/legend\x3e");for(var c=0;cb.getChildCount()?(new CKEDITOR.dom.text(a,CKEDITOR.document)).appendTo(b):b.getChild(0).$.nodeValue= -a;return this},getLabel:function(){var a=CKEDITOR.document.getById(this._.labelId);return!a||1>a.getChildCount()?"":a.getChild(0).getText()},eventProcessors:a},!0);CKEDITOR.ui.dialog.button.prototype=CKEDITOR.tools.extend(new CKEDITOR.ui.dialog.uiElement,{click:function(){return this._.disabled?!1:this.fire("click",{dialog:this._.dialog})},enable:function(){this._.disabled=!1;var a=this.getElement();a&&a.removeClass("cke_disabled")},disable:function(){this._.disabled=!0;this.getElement().addClass("cke_disabled")}, -isVisible:function(){return this.getElement().getFirst().isVisible()},isEnabled:function(){return!this._.disabled},eventProcessors:CKEDITOR.tools.extend({},CKEDITOR.ui.dialog.uiElement.prototype.eventProcessors,{onClick:function(a,b){this.on("click",function(){b.apply(this,arguments)})}},!0),accessKeyUp:function(){this.click()},accessKeyDown:function(){this.focus()},keyboardFocusable:!0},!0);CKEDITOR.ui.dialog.textInput.prototype=CKEDITOR.tools.extend(new CKEDITOR.ui.dialog.labeledElement,{getInputElement:function(){return CKEDITOR.document.getById(this._.inputId)}, -focus:function(){var a=this.selectParentTab();setTimeout(function(){var b=a.getInputElement();b&&b.$.focus()},0)},select:function(){var a=this.selectParentTab();setTimeout(function(){var b=a.getInputElement();b&&(b.$.focus(),b.$.select())},0)},accessKeyUp:function(){this.select()},setValue:function(a){if(this.bidi){var b=a&&a.charAt(0);(b="‪"==b?"ltr":"‫"==b?"rtl":null)&&(a=a.slice(1));this.setDirectionMarker(b)}a||(a="");return CKEDITOR.ui.dialog.uiElement.prototype.setValue.apply(this,arguments)}, -getValue:function(){var a=CKEDITOR.ui.dialog.uiElement.prototype.getValue.call(this);if(this.bidi&&a){var b=this.getDirectionMarker();b&&(a=("ltr"==b?"‪":"‫")+a)}return a},setDirectionMarker:function(a){var b=this.getInputElement();a?b.setAttributes({dir:a,"data-cke-dir-marker":a}):this.getDirectionMarker()&&b.removeAttributes(["dir","data-cke-dir-marker"])},getDirectionMarker:function(){return this.getInputElement().data("cke-dir-marker")},keyboardFocusable:!0},e,!0);CKEDITOR.ui.dialog.textarea.prototype= -new CKEDITOR.ui.dialog.textInput;CKEDITOR.ui.dialog.select.prototype=CKEDITOR.tools.extend(new CKEDITOR.ui.dialog.labeledElement,{getInputElement:function(){return this._.select.getElement()},add:function(a,b,g){var e=new CKEDITOR.dom.element("option",this.getDialog().getParentEditor().document),f=this.getInputElement().$;e.$.text=a;e.$.value=void 0===b||null===b?a:b;void 0===g||null===g?CKEDITOR.env.ie?f.add(e.$):f.add(e.$,null):f.add(e.$,g);return this},remove:function(a){this.getInputElement().$.remove(a); -return this},clear:function(){for(var a=this.getInputElement().$;0b-a;c--)if(this._.tabs[this._.tabIdList[c%a]][0].$.offsetHeight)return this._.tabIdList[c%a];return null}function f(){for(var a=this._.tabIdList.length,b=CKEDITOR.tools.indexOf(this._.tabIdList,this._.currentTabId),c=b+1;ck.width-n.width-f?k.width-n.width+("rtl"==e.lang.dir?0:h[1]):g.x;n=g.y+h[0]k.height-n.height-f?k.height-n.height+h[2]:g.y;l=Math.floor(l);n=Math.floor(n);a.move(l,n,1);c.data.preventDefault()}function c(){CKEDITOR.document.removeListener("mousemove",b);CKEDITOR.document.removeListener("mouseup",c);if(CKEDITOR.env.ie6Compat){var a=E.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){if(!a._.moved){var f=a._.element;f.getFirst().setStyle("position","absolute");f.removeStyle("display");a._.moved=!0;a.layout()}d={x:e.data.$.screenX,y:e.data.$.screenY};CKEDITOR.document.on("mousemove",b);CKEDITOR.document.on("mouseup",c);g=a.getPosition();CKEDITOR.env.ie6Compat&&(f=E.getChild(0).getFrameDocument(),f.on("mousemove",b),f.on("mouseup",c));e.data.preventDefault()}, -a)}function y(a){function b(c){var m="rtl"==e.lang.dir,r=l.width,t=l.height,q=r+(c.data.$.screenX-k.x)*(m?-1:1)*(a._.moved?1:2),R=t+(c.data.$.screenY-k.y)*(a._.moved?1:2),u=a._.element.getFirst(),u=m&&parseInt(u.getComputedStyle("right"),10),v=a.getPosition();v.x=v.x||0;v.y=v.y||0;v.y+R>n.height&&(R=n.height-v.y);(m?u:v.x)+q>n.width&&(q=n.width-(m?u:v.x));R=Math.floor(R);q=Math.floor(q);if(g==CKEDITOR.DIALOG_RESIZE_WIDTH||g==CKEDITOR.DIALOG_RESIZE_BOTH)r=Math.max(d.minWidth||0,q-f);if(g==CKEDITOR.DIALOG_RESIZE_HEIGHT|| -g==CKEDITOR.DIALOG_RESIZE_BOTH)t=Math.max(d.minHeight||0,R-h);a.resize(r,t);a._.moved&&w(a,a._.position.x,a._.position.y);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=E.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,n,k,l,m,r=CKEDITOR.tools.addFunction(function(d){function g(a){return a.isVisible()}l=a.getSize();var e=a.parts.contents,r=e.$.getElementsByTagName("iframe").length,t=!(CKEDITOR.env.gecko||CKEDITOR.env.ie&&CKEDITOR.env.quirks);r&&(m=CKEDITOR.dom.element.createFromHtml('\x3cdiv class\x3d"cke_dialog_resize_cover" style\x3d"height: 100%; position: absolute; width: 100%; left:0; top:0;"\x3e\x3c/div\x3e'),e.append(m));h=l.height-a.parts.contents.getFirst(g).getSize("height",t); -f=l.width-a.parts.contents.getFirst(g).getSize("width",1);k={x:d.screenX,y:d.screenY};n=CKEDITOR.document.getWindow().getViewPaneSize();CKEDITOR.document.on("mousemove",b);CKEDITOR.document.on("mouseup",c);CKEDITOR.env.ie6Compat&&(e=E.getChild(0).getFrameDocument(),e.on("mousemove",b),e.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('+r+', event )"\x3e'+("ltr"==e.lang.dir?"â—¢":"â—£")+"\x3c/div\x3e");a.parts.footer.append(b,1)});e.on("destroy",function(){CKEDITOR.tools.removeFunction(r)})}}function w(a,b,c){var d=a.parts.dialog.getParent().getClientSize(),g=a.getSize(),e=a._.viewportRatio,f=Math.max(d.width-g.width,0),d=Math.max(d.height-g.height,0);e.width=f?b/f:e.width;e.height=d?c/d:e.height; -a._.viewportRatio=e}function p(a){a.data.preventDefault(1)}function t(a){var b=a.config,c=CKEDITOR.skinName||a.config.skin,d=b.dialog_backgroundCoverColor||("moono-lisa"==c?"black":"white"),c=b.dialog_backgroundCoverOpacity,g=b.baseFloatZIndex,b=CKEDITOR.tools.genKey(d,c,g),e=M[b];CKEDITOR.document.getBody().addClass("cke_dialog_open");e?e.show():(g=['\x3cdiv tabIndex\x3d"-1" style\x3d"position: ',CKEDITOR.env.ie6Compat?"absolute":"fixed","; z-index: ",g,"; top: 0px; left: 0px; ","; width: 100%; height: 100%;", -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",g.push('\x3ciframe hidefocus\x3d"true" frameborder\x3d"0" id\x3d"cke_dialog_background_iframe" src\x3d"javascript:'),g.push("void((function(){"+encodeURIComponent("document.open();("+CKEDITOR.tools.fixDomain+")();document.write( '"+d+"' );document.close();")+"})())"),g.push('" style\x3d"position:absolute;left:0;top:0;width:100%;height: 100%;filter: progid:DXImageTransform.Microsoft.Alpha(opacity\x3d0)"\x3e\x3c/iframe\x3e')), -g.push("\x3c/div\x3e"),e=CKEDITOR.dom.element.createFromHtml(g.join("")),e.setOpacity(void 0!==c?c:.5),e.on("keydown",p),e.on("keypress",p),e.on("keyup",p),e.appendTo(CKEDITOR.document.getBody()),M[b]=e);a.focusManager.add(e);E=e;CKEDITOR.env.mac&&CKEDITOR.env.webkit||e.focus()}function r(a){CKEDITOR.document.getBody().removeClass("cke_dialog_open");E&&(a.focusManager.remove(E),E.hide())}function x(a){var b=a.data.$.ctrlKey||a.data.$.metaKey,c=a.data.$.altKey,d=a.data.$.shiftKey,g=String.fromCharCode(a.data.$.keyCode); -(b=Q[(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())}function u(a){var b=a.data.$.ctrlKey||a.data.$.metaKey,c=a.data.$.altKey,d=a.data.$.shiftKey,g=String.fromCharCode(a.data.$.keyCode);(b=Q[(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()))}function z(a,b,c,d,g){(Q[c]||(Q[c]=[])).push({uiElement:a, -dialog:b,key:c,keyup:g||a.accessKeyUp,keydown:d||a.accessKeyDown})}function q(a){for(var b in Q){for(var c=Q[b],d=c.length-1;0<=d;d--)c[d].dialog!=a&&c[d].uiElement!=a||c.splice(d,1);0===c.length&&delete Q[b]}}function v(a,b){a._.accessKeyMap[b]&&a.selectPage(a._.accessKeyMap[b])}function B(){}var D=CKEDITOR.tools.cssLength,A,E,F=!1,K=!CKEDITOR.env.ie||CKEDITOR.env.edge,L='\x3cdiv class\x3d"cke_reset_all cke_dialog_container {editorId} {editorDialogClass} {hidpi}" dir\x3d"{langDir}" style\x3d"'+(K? -"display:flex":"")+'" 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"'+(K?"margin:auto":"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(c,g){function e(){var a=E._.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;cb.length)){var c=E._.currentFocusIndex;E._.tabBarMode&&0>a&&(c=0);try{b[c].getInputElement().$.blur()}catch(d){}var g=c,e=1arguments.length)){var f=b.call(this,d);f.labelId=CKEDITOR.tools.getNextId()+ +"_label";this._.children=[];var h={role:d.role||"presentation"};d.includeLabel&&(h["aria-labelledby"]=f.labelId);CKEDITOR.ui.dialog.uiElement.call(this,a,d,g,"div",null,h,function(){var b=[],g=d.required?" cke_required":"";"horizontal"!=d.labelLayout?b.push('\x3clabel class\x3d"cke_dialog_ui_labeled_label'+g+'" ',' id\x3d"'+f.labelId+'"',f.inputId?' for\x3d"'+f.inputId+'"':"",(d.labelStyle?' style\x3d"'+d.labelStyle+'"':"")+"\x3e",d.required?d.label+'\x3cspan class\x3d"cke_dialog_ui_labeled_required" aria-hidden\x3d"true"\x3e*\x3c/span\x3e': +d.label,"\x3c/label\x3e",'\x3cdiv class\x3d"cke_dialog_ui_labeled_content"',d.controlStyle?' style\x3d"'+d.controlStyle+'"':"",' role\x3d"presentation"\x3e',e.call(this,a,d),"\x3c/div\x3e"):(g={type:"hbox",widths:d.widths,padding:0,children:[{type:"html",html:'\x3clabel class\x3d"cke_dialog_ui_labeled_label'+g+'" id\x3d"'+f.labelId+'" for\x3d"'+f.inputId+'"'+(d.labelStyle?' style\x3d"'+d.labelStyle+'"':"")+"\x3e"+CKEDITOR.tools.htmlEncode(d.label)+"\x3c/label\x3e"},{type:"html",html:'\x3cspan class\x3d"cke_dialog_ui_labeled_content"'+ +(d.controlStyle?' style\x3d"'+d.controlStyle+'"':"")+"\x3e"+e.call(this,a,d)+"\x3c/span\x3e"}]},CKEDITOR.dialog._.uiElementBuilders.hbox.build(a,g,b));return b.join("")})}},textInput:function(a,d,g){if(!(3>arguments.length)){b.call(this,d);var e=this._.inputId=CKEDITOR.tools.getNextId()+"_textInput",f={"class":"cke_dialog_ui_input_"+d.type,id:e,type:d.type};d.validate&&(this.validate=d.validate);d.maxLength&&(f.maxlength=d.maxLength);d.size&&(f.size=d.size);d.inputStyle&&(f.style=d.inputStyle);var h= +this,k=!1;a.on("load",function(){h.getInputElement().on("keydown",function(a){13==a.data.getKeystroke()&&(k=!0)});h.getInputElement().on("keyup",function(b){13==b.data.getKeystroke()&&k&&(a.getButton("ok")&&setTimeout(function(){a.getButton("ok").click()},0),k=!1);h.bidi&&m.call(h,b)},null,null,1E3)});CKEDITOR.ui.dialog.labeledElement.call(this,a,d,g,function(){var a=['\x3cdiv class\x3d"cke_dialog_ui_input_',d.type,'" role\x3d"presentation"'];d.width&&a.push('style\x3d"width:'+d.width+'" ');a.push("\x3e\x3cinput "); +f["aria-labelledby"]=this._.labelId;this._.required&&(f["aria-required"]=this._.required);for(var c in f)a.push(c+'\x3d"'+f[c]+'" ');a.push(" /\x3e\x3c/div\x3e");return a.join("")})}},textarea:function(a,d,g){if(!(3>arguments.length)){b.call(this,d);var e=this,f=this._.inputId=CKEDITOR.tools.getNextId()+"_textarea",h={};d.validate&&(this.validate=d.validate);h.rows=d.rows||5;h.cols=d.cols||20;h["class"]="cke_dialog_ui_input_textarea "+(d["class"]||"");"undefined"!=typeof d.inputStyle&&(h.style=d.inputStyle); +d.dir&&(h.dir=d.dir);if(e.bidi)a.on("load",function(){e.getInputElement().on("keyup",m)},e);CKEDITOR.ui.dialog.labeledElement.call(this,a,d,g,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"',f,'" '],c;for(c in h)a.push(c+'\x3d"'+CKEDITOR.tools.htmlEncode(h[c])+'" ');a.push("\x3e",CKEDITOR.tools.htmlEncode(e._["default"]),"\x3c/textarea\x3e\x3c/div\x3e"); +return a.join("")})}},checkbox:function(a,d,g){if(!(3>arguments.length)){var e=b.call(this,d,{"default":!!d["default"]});d.validate&&(this.validate=d.validate);CKEDITOR.ui.dialog.uiElement.call(this,a,d,g,"span",null,null,function(){var b=CKEDITOR.tools.extend({},d,{id:d.id?d.id+"_checkbox":CKEDITOR.tools.getNextId()+"_checkbox"},!0),g=[],f=CKEDITOR.tools.getNextId()+"_label",h={"class":"cke_dialog_ui_checkbox_input",type:"checkbox","aria-labelledby":f};l(b);d["default"]&&(h.checked="checked");"undefined"!= +typeof b.inputStyle&&(b.style=b.inputStyle);e.checkbox=new CKEDITOR.ui.dialog.uiElement(a,b,g,"input",null,h);g.push(' \x3clabel id\x3d"',f,'" for\x3d"',h.id,'"'+(d.labelStyle?' style\x3d"'+d.labelStyle+'"':"")+"\x3e",CKEDITOR.tools.htmlEncode(d.label),"\x3c/label\x3e");return g.join("")})}},radio:function(a,d,g){if(!(3>arguments.length)){b.call(this,d);this._["default"]||(this._["default"]=this._.initValue=d.items[0][1]);d.validate&&(this.validate=d.validate);var e=[],f=this;d.role="radiogroup"; +d.includeLabel=!0;CKEDITOR.ui.dialog.labeledElement.call(this,a,d,g,function(){for(var b=[],g=[],h=(d.id?d.id:CKEDITOR.tools.getNextId())+"_radio",k=0;karguments.length)){var e=b.call(this,d);d.validate&&(this.validate=d.validate);e.inputId=CKEDITOR.tools.getNextId()+"_select";CKEDITOR.ui.dialog.labeledElement.call(this,a,d,g,function(){var b=CKEDITOR.tools.extend({},d,{id:d.id?d.id+"_select":CKEDITOR.tools.getNextId()+"_select"},!0),g=[],f=[],h={id:e.inputId,"class":"cke_dialog_ui_input_select", +"aria-labelledby":this._.labelId};g.push('\x3cdiv class\x3d"cke_dialog_ui_input_',d.type,'" role\x3d"presentation"');d.width&&g.push('style\x3d"width:'+d.width+'" ');g.push("\x3e");void 0!==d.size&&(h.size=d.size);void 0!==d.multiple&&(h.multiple=d.multiple);l(b);for(var k=0,m;karguments.length)){void 0===d["default"]&&(d["default"]="");var e=CKEDITOR.tools.extend(b.call(this,d),{definition:d,buttons:[]});d.validate&&(this.validate=d.validate);a.on("load",function(){CKEDITOR.document.getById(e.frameId).getParent().addClass("cke_dialog_ui_input_file")});CKEDITOR.ui.dialog.labeledElement.call(this,a,d,g, +function(){e.frameId=CKEDITOR.tools.getNextId()+"_fileInput";var a=['\x3ciframe frameborder\x3d"0" allowtransparency\x3d"0" class\x3d"cke_dialog_ui_input_file" role\x3d"presentation" id\x3d"',e.frameId,'" title\x3d"',d.label,'" src\x3d"javascript:void('];a.push(CKEDITOR.env.ie?"(function(){"+encodeURIComponent("document.open();("+CKEDITOR.tools.fixDomain+")();document.close();")+"})()":"0");a.push(')"\x3e\x3c/iframe\x3e');return a.join("")})}},fileButton:function(a,d,g){var e=this;if(!(3>arguments.length)){b.call(this, +d);d.validate&&(this.validate=d.validate);var f=CKEDITOR.tools.extend({},d),h=f.onClick;f.className=(f.className?f.className+" ":"")+"cke_dialog_ui_button";f.onClick=function(b){var g=d["for"];b=h?h.call(this,b):!1;!1!==b&&("xhr"!==b&&a.getContentElement(g[0],g[1]).submit(),this.disable())};a.on("load",function(){a.getContentElement(d["for"][0],d["for"][1])._.buttons.push(e)});CKEDITOR.ui.dialog.button.call(this,a,f,g)}},html:function(){var a=/^\s*<[\w:]+\s+([^>]*)?>/,b=/^(\s*<[\w:]+(?:\s+[^>]*)?)((?:.|\r|\n)+)$/, +g=/\/$/;return function(e,f,h){if(!(3>arguments.length)){var k=[],l=f.html;"\x3c"!=l.charAt(0)&&(l="\x3cspan\x3e"+l+"\x3c/span\x3e");var m=f.focus;if(m){var x=this.focus;this.focus=function(){("function"==typeof m?m:x).call(this);this.fire("focus")};f.isFocusable&&(this.isFocusable=this.isFocusable);this.keyboardFocusable=!0}CKEDITOR.ui.dialog.uiElement.call(this,e,f,k,"span",null,null,"");k=k.join("").match(a);l=l.match(b)||["","",""];g.test(l[1])&&(l[1]=l[1].slice(0,-1),l[2]="/"+l[2]);h.push([l[1], +" ",k[1]||"",l[2]].join(""))}}}(),fieldset:function(a,b,g,e,f){var h=f.label;this._={children:b};CKEDITOR.ui.dialog.uiElement.call(this,a,f,e,"fieldset",null,null,function(){var a=[];h&&a.push("\x3clegend"+(f.labelStyle?' style\x3d"'+f.labelStyle+'"':"")+"\x3e"+h+"\x3c/legend\x3e");for(var c=0;cb.getChildCount()?(new CKEDITOR.dom.text(a,CKEDITOR.document)).appendTo(b):b.getChild(0).$.nodeValue=a;return this},getLabel:function(){var a=CKEDITOR.document.getById(this._.labelId);return!a||1>a.getChildCount()?"":a.getChild(0).getText()},eventProcessors:a},!0);CKEDITOR.ui.dialog.button.prototype=CKEDITOR.tools.extend(new CKEDITOR.ui.dialog.uiElement,{click:function(){return this._.disabled?!1:this.fire("click",{dialog:this._.dialog})}, +enable:function(){this._.disabled=!1;var a=this.getElement();a&&a.removeClass("cke_disabled")},disable:function(){this._.disabled=!0;this.getElement().addClass("cke_disabled")},isVisible:function(){return this.getElement().getFirst().isVisible()},isEnabled:function(){return!this._.disabled},eventProcessors:CKEDITOR.tools.extend({},CKEDITOR.ui.dialog.uiElement.prototype.eventProcessors,{onClick:function(a,b){this.on("click",function(){b.apply(this,arguments)})}},!0),accessKeyUp:function(){this.click()}, +accessKeyDown:function(){this.focus()},keyboardFocusable:!0},!0);CKEDITOR.ui.dialog.textInput.prototype=CKEDITOR.tools.extend(new CKEDITOR.ui.dialog.labeledElement,{getInputElement:function(){return CKEDITOR.document.getById(this._.inputId)},focus:function(){var a=this.selectParentTab();setTimeout(function(){var b=a.getInputElement();b&&b.$.focus()},0)},select:function(){var a=this.selectParentTab();setTimeout(function(){var b=a.getInputElement();b&&(b.$.focus(),b.$.select())},0)},accessKeyUp:function(){this.select()}, +setValue:function(a){if(this.bidi){var b=a&&a.charAt(0);(b="‪"==b?"ltr":"‫"==b?"rtl":null)&&(a=a.slice(1));this.setDirectionMarker(b)}a||(a="");return CKEDITOR.ui.dialog.uiElement.prototype.setValue.apply(this,arguments)},getValue:function(){var a=CKEDITOR.ui.dialog.uiElement.prototype.getValue.call(this);if(this.bidi&&a){var b=this.getDirectionMarker();b&&(a=("ltr"==b?"‪":"‫")+a)}return a},setDirectionMarker:function(a){var b=this.getInputElement();a?b.setAttributes({dir:a,"data-cke-dir-marker":a}): +this.getDirectionMarker()&&b.removeAttributes(["dir","data-cke-dir-marker"])},getDirectionMarker:function(){return this.getInputElement().data("cke-dir-marker")},keyboardFocusable:!0},e,!0);CKEDITOR.ui.dialog.textarea.prototype=new CKEDITOR.ui.dialog.textInput;CKEDITOR.ui.dialog.select.prototype=CKEDITOR.tools.extend(new CKEDITOR.ui.dialog.labeledElement,{getInputElement:function(){return this._.select.getElement()},add:function(a,b,g){var e=new CKEDITOR.dom.element("option",this.getDialog().getParentEditor().document), +f=this.getInputElement().$;e.$.text=a;e.$.value=void 0===b||null===b?a:b;void 0===g||null===g?CKEDITOR.env.ie?f.add(e.$):f.add(e.$,null):f.add(e.$,g);return this},remove:function(a){this.getInputElement().$.remove(a);return this},clear:function(){for(var a=this.getInputElement().$;0c-a;b--)if(this._.tabs[this._.tabIdList[b% +a]][0].$.offsetHeight)return this._.tabIdList[b%a];return null}function f(){for(var a=this._.tabIdList.length,c=CKEDITOR.tools.indexOf(this._.tabIdList,this._.currentTabId),b=c+1;bk.width-n.width-f?k.width-n.width+("rtl"==e.lang.dir?0:h[1]):g.x;n=g.y+h[0]k.height-n.height-f?k.height-n.height+h[2]:g.y;l=Math.floor(l);n=Math.floor(n);a.move(l,n,1);b.data.preventDefault()} +function b(){CKEDITOR.document.removeListener("mousemove",c);CKEDITOR.document.removeListener("mouseup",b);if(CKEDITOR.env.ie6Compat){var a=E.getChild(0).getFrameDocument();a.removeListener("mousemove",c);a.removeListener("mouseup",b)}}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){if(!a._.moved){var f=a._.element;f.getFirst().setStyle("position","absolute");f.removeStyle("display"); +a._.moved=!0;a.layout()}d={x:e.data.$.screenX,y:e.data.$.screenY};CKEDITOR.document.on("mousemove",c);CKEDITOR.document.on("mouseup",b);g=a.getPosition();CKEDITOR.env.ie6Compat&&(f=E.getChild(0).getFrameDocument(),f.on("mousemove",c),f.on("mouseup",b));e.data.preventDefault()},a)}function y(a){function c(b){var m="rtl"==e.lang.dir,q=l.width,t=l.height,r=q+(b.data.$.screenX-k.x)*(m?-1:1)*(a._.moved?1:2),Q=t+(b.data.$.screenY-k.y)*(a._.moved?1:2),u=a._.element.getFirst(),u=m&&parseInt(u.getComputedStyle("right"), +10),w=a.getPosition();w.x=w.x||0;w.y=w.y||0;w.y+Q>n.height&&(Q=n.height-w.y);(m?u:w.x)+r>n.width&&(r=n.width-(m?u:w.x));Q=Math.floor(Q);r=Math.floor(r);if(g==CKEDITOR.DIALOG_RESIZE_WIDTH||g==CKEDITOR.DIALOG_RESIZE_BOTH)q=Math.max(d.minWidth||0,r-f);if(g==CKEDITOR.DIALOG_RESIZE_HEIGHT||g==CKEDITOR.DIALOG_RESIZE_BOTH)t=Math.max(d.minHeight||0,Q-h);a.resize(q,t);a._.moved&&v(a,a._.position.x,a._.position.y);a._.moved||a.layout();b.data.preventDefault()}function b(){CKEDITOR.document.removeListener("mouseup", +b);CKEDITOR.document.removeListener("mousemove",c);m&&(m.remove(),m=null);if(CKEDITOR.env.ie6Compat){var a=E.getChild(0).getFrameDocument();a.removeListener("mouseup",b);a.removeListener("mousemove",c)}}var d=a.definition,g=d.resizable;if(g!=CKEDITOR.DIALOG_RESIZE_NONE){var e=a.getParentEditor(),f,h,n,k,l,m,q=CKEDITOR.tools.addFunction(function(d){function g(a){return a.isVisible()}l=a.getSize();var e=a.parts.contents,q=e.$.getElementsByTagName("iframe").length,t=!(CKEDITOR.env.gecko||CKEDITOR.env.ie&& +CKEDITOR.env.quirks);q&&(m=CKEDITOR.dom.element.createFromHtml('\x3cdiv class\x3d"cke_dialog_resize_cover" style\x3d"height: 100%; position: absolute; width: 100%; left:0; top:0;"\x3e\x3c/div\x3e'),e.append(m));h=l.height-a.parts.contents.getFirst(g).getSize("height",t);f=l.width-a.parts.contents.getFirst(g).getSize("width",1);k={x:d.screenX,y:d.screenY};n=CKEDITOR.document.getWindow().getViewPaneSize();CKEDITOR.document.on("mousemove",c);CKEDITOR.document.on("mouseup",b);CKEDITOR.env.ie6Compat&& +(e=E.getChild(0).getFrameDocument(),e.on("mousemove",c),e.on("mouseup",b));d.preventDefault&&d.preventDefault()});a.on("load",function(){var c="";g==CKEDITOR.DIALOG_RESIZE_WIDTH?c=" cke_resizer_horizontal":g==CKEDITOR.DIALOG_RESIZE_HEIGHT&&(c=" cke_resizer_vertical");c=CKEDITOR.dom.element.createFromHtml('\x3cdiv class\x3d"cke_resizer'+c+" 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(c,1)});e.on("destroy",function(){CKEDITOR.tools.removeFunction(q)})}}function v(a,c,b){var d=a.parts.dialog.getParent().getClientSize(),g=a.getSize(),e=a._.viewportRatio,f=Math.max(d.width-g.width,0),d=Math.max(d.height-g.height,0);e.width=f?c/f:e.width;e.height=d?b/d:e.height;a._.viewportRatio=e}function p(a){a.data.preventDefault(1)}function q(a){var c=a.config,b=CKEDITOR.skinName||a.config.skin,d=c.dialog_backgroundCoverColor||("moono-lisa"== +b?"black":"white"),b=c.dialog_backgroundCoverOpacity,g=c.baseFloatZIndex,c=CKEDITOR.tools.genKey(d,b,g),e=L[c];CKEDITOR.document.getBody().addClass("cke_dialog_open");e?e.show():(g=['\x3cdiv tabIndex\x3d"-1" style\x3d"position: ',CKEDITOR.env.ie6Compat?"absolute":"fixed","; z-index: ",g,"; top: 0px; left: 0px; ","; width: 100%; height: 100%;",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",g.push('\x3ciframe hidefocus\x3d"true" frameborder\x3d"0" id\x3d"cke_dialog_background_iframe" src\x3d"javascript:'),g.push("void((function(){"+encodeURIComponent("document.open();("+CKEDITOR.tools.fixDomain+")();document.write( '"+d+"' );document.close();")+"})())"),g.push('" style\x3d"position:absolute;left:0;top:0;width:100%;height: 100%;filter: progid:DXImageTransform.Microsoft.Alpha(opacity\x3d0)"\x3e\x3c/iframe\x3e')),g.push("\x3c/div\x3e"),e=CKEDITOR.dom.element.createFromHtml(g.join("")), +e.setOpacity(void 0!==b?b:.5),e.on("keydown",p),e.on("keypress",p),e.on("keyup",p),e.appendTo(CKEDITOR.document.getBody()),L[c]=e);a.focusManager.add(e);E=e;CKEDITOR.env.mac&&CKEDITOR.env.webkit||e.focus()}function r(a){CKEDITOR.document.getBody().removeClass("cke_dialog_open");E&&(a.focusManager.remove(E),E.hide())}function x(a){var c=a.data.$.ctrlKey||a.data.$.metaKey,b=a.data.$.altKey,d=a.data.$.shiftKey,g=String.fromCharCode(a.data.$.keyCode);(c=R[(c?"CTRL+":"")+(b?"ALT+":"")+(d?"SHIFT+":"")+ +g])&&c.length&&(c=c[c.length-1],c.keydown&&c.keydown.call(c.uiElement,c.dialog,c.key),a.data.preventDefault())}function t(a){var c=a.data.$.ctrlKey||a.data.$.metaKey,b=a.data.$.altKey,d=a.data.$.shiftKey,g=String.fromCharCode(a.data.$.keyCode);(c=R[(c?"CTRL+":"")+(b?"ALT+":"")+(d?"SHIFT+":"")+g])&&c.length&&(c=c[c.length-1],c.keyup&&(c.keyup.call(c.uiElement,c.dialog,c.key),a.data.preventDefault()))}function z(a,c,b,d,g){(R[b]||(R[b]=[])).push({uiElement:a,dialog:c,key:b,keyup:g||a.accessKeyUp,keydown:d|| +a.accessKeyDown})}function u(a){for(var c in R){for(var b=R[c],d=b.length-1;0<=d;d--)b[d].dialog!=a&&b[d].uiElement!=a||b.splice(d,1);0===b.length&&delete R[c]}}function w(a,c){a._.accessKeyMap[c]&&a.selectPage(a._.accessKeyMap[c])}function B(){}var C=CKEDITOR.tools.cssLength,A,E,F=!1,K=!CKEDITOR.env.ie||CKEDITOR.env.edge,M='\x3cdiv class\x3d"cke_reset_all cke_dialog_container {editorId} {editorDialogClass} {hidpi}" dir\x3d"{langDir}" style\x3d"'+(K?"display:flex":"")+'" 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"'+(K?"margin:auto":"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(c,g){function e(){var a=E._.focusList;a.sort(function(a,c){return a.tabIndex!=c.tabIndex?c.tabIndex-a.tabIndex:a.focusIndex-c.focusIndex});for(var c=a.length,b=0;bc.length)){var b=E._.currentFocusIndex;E._.tabBarMode&&0>a&&(b=0);try{c[b].getInputElement().$.blur()}catch(d){}var g=b,e=1arguments.length)){var h=(d.call?d(b):d)||"div",n=["\x3c",h," "],k=(g&&g.call?g(b):g)||{},l=(e&&e.call?e(b):e)||{},m=(f&&f.call?f.call(this,a,b):f)||"",r=this.domId=l.id||CKEDITOR.tools.getNextId()+"_uiElement";b.requiredContent&&!a.getParentEditor().filter.check(b.requiredContent)&&(k.display="none",this.notAllowed=!0);l.id=r;var q={};b.type&&(q["cke_dialog_ui_"+b.type]=1);b.className&&(q[b.className]= -1);b.disabled&&(q.cke_disabled=1);for(var t=l["class"]&&l["class"].split?l["class"].split(" "):[],r=0;rCKEDITOR.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,n,k={role:"presentation"};g&&g.align&&(k.align=g.align);CKEDITOR.ui.dialog.uiElement.call(this,a,g||{type:"hbox"},d,"table",{},k,function(){var a= -['\x3ctbody\x3e\x3ctr class\x3d"cke_dialog_ui_hbox"\x3e'];for(n=0;narguments.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:"+D(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;darguments.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;hl.$.clientHeight?l.setStyle("overflow-y","hidden"):l.removeStyle("overflow-y"))}var a,m,k,l,c,d=b.config.autoGrow_bottomSpace||0,g=void 0!==b.config.autoGrow_minHeight?b.config.autoGrow_minHeight:200,n=b.config.autoGrow_maxHeight||Infinity,y=!b.config.autoGrow_maxHeight; -b.addCommand("autogrow",{exec:e,modes:{wysiwyg:1},readOnly:1,canUndo:!1,editorFocus:!1});var w={contentDom:1,key:1,selectionChange:1,insertElement:1,mode:1},p;for(p in w)b.on(p,function(c){"wysiwyg"==c.editor.mode&&setTimeout(function(){var c=b.getCommand("maximize");!b.window||c&&c.state==CKEDITOR.TRISTATE_ON?a=null:(e(),y||e())},100)});b.on("afterCommandExec",function(a){"maximize"==a.data.name&&"wysiwyg"==a.editor.mode&&(a.data.command.state==CKEDITOR.TRISTATE_ON?l.removeStyle("overflow-y"):e())}); +this.parts.dialog;if(this._.moved||!K){var c=this.getSize(),b=CKEDITOR.document.getWindow().getViewPaneSize(),d;this._.moved&&this._.position?(d=this._.position.x,c=this._.position.y):(d=(b.width-c.width)/2,c=(b.height-c.height)/2);CKEDITOR.env.ie6Compat||(a.setStyle("position","absolute"),a.removeStyle("margin"));d=Math.floor(d);c=Math.floor(c);this.move(d,c)}},foreach:function(a){for(var c in this._.contents)for(var b in this._.contents[c])a.call(this,this._.contents[c][b]);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(c){c.setup&&c.setup.apply(c,a)})},commitContent:function(){var a=arguments;this.foreach(function(c){CKEDITOR.env.ie&&this._.currentFocusIndex==c.focusIndex&&c.getInputElement().$.blur();c.commit&&c.commit.apply(c,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(u(this);CKEDITOR.dialog._.currentTop!=this;)CKEDITOR.dialog._.currentTop.hide();if(this._.parentDialog){var c=this._.parentDialog.getElement().getFirst();this._.parentDialog.getElement().removeStyle("z-index");c.setStyle("z-index",parseInt(c.$.style.zIndex,10)+Math.floor(this._.editor.config.baseFloatZIndex/2))}else r(this._.editor);if(CKEDITOR.dialog._.currentTop=this._.parentDialog)CKEDITOR.dialog._.currentZIndex-= +10;else{CKEDITOR.dialog._.currentZIndex=null;a.removeListener("keydown",x);a.removeListener("keyup",t);var b=this._.editor;b.focus();setTimeout(function(){b.focusManager.unlock();CKEDITOR.env.iOS&&b.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 c=[],b=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%;"},c),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);c=CKEDITOR.dom.element.createFromHtml(c.join(""));c.setAttribute("role","tabpanel");c.setStyle("min-height", +"100%");d=CKEDITOR.env;g="cke_"+a.id+"_"+CKEDITOR.tools.getNextNumber();b=CKEDITOR.dom.element.createFromHtml(['\x3ca class\x3d"cke_dialog_tab"',0arguments.length)){var h=(d.call?d(c):d)||"div",n=["\x3c",h," "],k=(g&&g.call?g(c):g)||{},l=(e&&e.call?e(c):e)||{},m=(f&&f.call?f.call(this,a,c):f)||"",r=this.domId=l.id||CKEDITOR.tools.getNextId()+"_uiElement";c.requiredContent&&!a.getParentEditor().filter.check(c.requiredContent)&&(k.display="none",this.notAllowed= +!0);l.id=r;var q={};c.type&&(q["cke_dialog_ui_"+c.type]=1);c.className&&(q[c.className]=1);c.disabled&&(q.cke_disabled=1);for(var t=l["class"]&&l["class"].split?l["class"].split(" "):[],r=0;rCKEDITOR.env.version?"cke_dialog_ui_focused":"";c.on("focus", +function(){a._.tabBarMode=!1;a._.hasFocus=!0;u.fire("focus");b&&this.addClass(b)});c.on("blur",function(){u.fire("blur");b&&this.removeClass(b)})}});CKEDITOR.tools.extend(this,c);this.keyboardFocusable&&(this.tabIndex=c.tabIndex||0,this.focusIndex=a._.focusList.push(this)-1,this.on("focus",function(){a._.currentFocusIndex=u.focusIndex}))}},hbox:function(a,c,b,d,g){if(!(4>arguments.length)){this._||(this._={});var e=this._.children=c,f=g&&g.widths||null,h=g&&g.height||null,n,k={role:"presentation"}; +g&&g.align&&(k.align=g.align);CKEDITOR.ui.dialog.uiElement.call(this,a,g||{type:"hbox"},d,"table",{},k,function(){var a=['\x3ctbody\x3e\x3ctr class\x3d"cke_dialog_ui_hbox"\x3e'];for(n=0;narguments.length)){this._||(this._={});var e=this._.children=c,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 c= +['\x3ctable role\x3d"presentation" cellspacing\x3d"0" border\x3d"0" '];c.push('style\x3d"');g&&g.expand&&c.push("height:100%;");c.push("width:"+C(f||"100%"),";");CKEDITOR.env.webkit&&c.push("float:none;");c.push('"');c.push('align\x3d"',CKEDITOR.tools.htmlEncode(g&&g.align||("ltr"==a.getParentEditor().lang.dir?"left":"right")),'" ');c.push("\x3e\x3ctbody\x3e");for(var d=0;darguments.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, +c,b){for(var d=c.children,g,e=[],f=[],h=0;hm.$.clientHeight?m.setStyle("overflow-y","hidden"):m.removeStyle("overflow-y"))}var a,k,l,m,c,d=b.config.autoGrow_bottomSpace||0,g=void 0!==b.config.autoGrow_minHeight?b.config.autoGrow_minHeight:200,n=b.config.autoGrow_maxHeight||Infinity,y=!b.config.autoGrow_maxHeight; +b.addCommand("autogrow",{exec:e,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)b.on(p,function(c){"wysiwyg"==c.editor.mode&&setTimeout(function(){var c=b.getCommand("maximize");!b.window||c&&c.state==CKEDITOR.TRISTATE_ON?a=null:(e(),y||e())},100)});b.on("afterCommandExec",function(a){"maximize"==a.data.name&&"wysiwyg"==a.editor.mode&&(a.data.command.state==CKEDITOR.TRISTATE_ON?m.removeStyle("overflow-y"):e())}); b.on("contentDom",f);f();b.config.autoGrow_onStartup&&b.editable().isVisible()&&b.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"):b(h)})}})}(),CKEDITOR.plugins.add("basicstyles",{init:function(b){var h=0,f=function(a,f,c,d){if(d){d=new CKEDITOR.style(d);var g=e[c];g.unshift(d);b.attachStyleStateChange(d,function(a){!b.readOnly&& b.getCommand(c).setState(a)});b.addCommand(c,new CKEDITOR.styleCommand(d,{contentForms:g}));b.ui.addButton&&b.ui.addButton(a,{label:f,command:c,toolbar:"basicstyles,"+(h+=10)})}},e={bold:["strong","b",["span",function(a){a=a.styles["font-weight"];return"bold"==a||700<=+a}]],italic:["em","i",["span",function(a){return"italic"==a.styles["font-style"]}]],underline:["u",["span",function(a){return"underline"==a.styles["text-decoration"]}]],strike:["s","strike",["span",function(a){return"line-through"== -a.styles["text-decoration"]}]],subscript:["sub"],superscript:["sup"]},a=b.config,m=b.lang.basicstyles;f("Bold",m.bold,"bold",a.coreStyles_bold);f("Italic",m.italic,"italic",a.coreStyles_italic);f("Underline",m.underline,"underline",a.coreStyles_underline);f("Strike",m.strike,"strike",a.coreStyles_strike);f("Subscript",m.subscript,"subscript",a.coreStyles_subscript);f("Superscript",m.superscript,"superscript",a.coreStyles_superscript);b.setKeystroke([[CKEDITOR.CTRL+66,"bold"],[CKEDITOR.CTRL+73,"italic"], +a.styles["text-decoration"]}]],subscript:["sub"],superscript:["sup"]},a=b.config,k=b.lang.basicstyles;f("Bold",k.bold,"bold",a.coreStyles_bold);f("Italic",k.italic,"italic",a.coreStyles_italic);f("Underline",k.underline,"underline",a.coreStyles_underline);f("Strike",k.strike,"strike",a.coreStyles_strike);f("Subscript",k.subscript,"subscript",a.coreStyles_subscript);f("Superscript",k.superscript,"superscript",a.coreStyles_superscript);b.setKeystroke([[CKEDITOR.CTRL+66,"bold"],[CKEDITOR.CTRL+73,"italic"], [CKEDITOR.CTRL+85,"underline"]])}}),CKEDITOR.config.coreStyles_bold={element:"strong",overrides:"b"},CKEDITOR.config.coreStyles_italic={element:"em",overrides:"i"},CKEDITOR.config.coreStyles_underline={element:"u"},CKEDITOR.config.coreStyles_strike={element:"s",overrides:"strike"},CKEDITOR.config.coreStyles_subscript={element:"sub"},CKEDITOR.config.coreStyles_superscript={element:"sup"},function(){var b={exec:function(b){var f=b.getCommand("blockquote").state,e=b.getSelection(),a=e&&e.getRanges()[0]; -if(a){var m=e.createBookmarks();if(CKEDITOR.env.ie){var k=m[0].startNode,l=m[0].endNode,c;if(k&&"blockquote"==k.getParent().getName())for(c=k;c=c.getNext();)if(c.type==CKEDITOR.NODE_ELEMENT&&c.isBlockBoundary()){k.move(c,!0);break}if(l&&"blockquote"==l.getParent().getName())for(c=l;c=c.getPrevious();)if(c.type==CKEDITOR.NODE_ELEMENT&&c.isBlockBoundary()){l.move(c);break}}var d=a.createIterator();d.enlargeBr=b.config.enterMode!=CKEDITOR.ENTER_BR;if(f==CKEDITOR.TRISTATE_OFF){for(k=[];f=d.getNextParagraph();)k.push(f); -1>k.length&&(f=b.document.createElement(b.config.enterMode==CKEDITOR.ENTER_P?"p":"div"),l=m.shift(),a.insertNode(f),f.append(new CKEDITOR.dom.text("",b.document)),a.moveToBookmark(l),a.selectNodeContents(f),a.collapse(!0),l=a.createBookmark(),k.push(f),m.unshift(l));c=k[0].getParent();a=[];for(l=0;ll.length&&(f=b.document.createElement(b.config.enterMode==CKEDITOR.ENTER_P?"p":"div"),m=k.shift(),a.insertNode(f),f.append(new CKEDITOR.dom.text("",b.document)),a.moveToBookmark(m),a.selectNodeContents(f),a.collapse(!0),m=a.createBookmark(),l.push(f),k.unshift(m));c=l[0].getParent();a=[];for(m=0;me||(this.notifications.splice(e,1),b.element.remove(),this.element.getChildCount()||(this._removeListeners(),this.element.remove()))},_createElement:function(){var b=this.editor,e=b.config,a=new CKEDITOR.dom.element("div");a.addClass("cke_notifications_area");a.setAttribute("id","cke_notifications_area_"+b.name);a.setStyle("z-index",e.baseFloatZIndex- 2);return a},_attachListeners:function(){var b=CKEDITOR.document.getWindow(),e=this.editor;b.on("scroll",this._uiBuffer.input);b.on("resize",this._uiBuffer.input);e.on("change",this._changeBuffer.input);e.on("floatingSpaceLayout",this._layout,this,null,20);e.on("blur",this._layout,this,null,20)},_removeListeners:function(){var b=CKEDITOR.document.getWindow(),e=this.editor;b.removeListener("scroll",this._uiBuffer.input);b.removeListener("resize",this._uiBuffer.input);e.removeListener("change",this._changeBuffer.input); -e.removeListener("floatingSpaceLayout",this._layout);e.removeListener("blur",this._layout)},_layout:function(){function b(){e.setStyle("left",x(u+h.width-n-y))}var e=this.element,a=this.editor,h=a.ui.contentsElement.getClientRect(),k=a.ui.contentsElement.getDocumentPosition(),l,c,d=e.getClientRect(),g,n=this._notificationWidth,y=this._notificationMargin;g=CKEDITOR.document.getWindow();var w=g.getScrollPosition(),p=g.getViewPaneSize(),t=CKEDITOR.document.getBody(),r=t.getDocumentPosition(),x=CKEDITOR.tools.cssLength; -n&&y||(g=this.element.getChild(0),n=this._notificationWidth=g.getClientRect().width,y=this._notificationMargin=parseInt(g.getComputedStyle("margin-left"),10)+parseInt(g.getComputedStyle("margin-right"),10));a.toolbar&&(l=a.ui.space(a.config.toolbarLocation),c=l.getClientRect());l&&l.isVisible()&&c.bottom>h.top&&c.bottomw.y?e.setStyles({position:"fixed",top:0}): -e.setStyles({position:"absolute",top:x(k.y+h.height-d.height)});var u="fixed"==e.getStyle("position")?h.left:"static"!=t.getComputedStyle("position")?k.x-r.x:k.x;h.widthw.x+p.width?b():e.setStyle("left",x(u)):k.x+n+y>w.x+p.width?e.setStyle("left",x(u)):k.x+h.width/2+n/2+y>w.x+p.width?e.setStyle("left",x(u-k.x+w.x+p.width-n-y)):0>h.left+h.width-n-y?b():0>h.left+h.width/2-n/2?e.setStyle("left",x(u-k.x+w.x)):e.setStyle("left",x(u+h.width/2-n/2-y/2))}};CKEDITOR.plugins.notification=b}(), +e.removeListener("floatingSpaceLayout",this._layout);e.removeListener("blur",this._layout)},_layout:function(){function b(){e.setStyle("left",x(t+h.width-n-y))}var e=this.element,a=this.editor,h=a.ui.contentsElement.getClientRect(),l=a.ui.contentsElement.getDocumentPosition(),m,c,d=e.getClientRect(),g,n=this._notificationWidth,y=this._notificationMargin;g=CKEDITOR.document.getWindow();var v=g.getScrollPosition(),p=g.getViewPaneSize(),q=CKEDITOR.document.getBody(),r=q.getDocumentPosition(),x=CKEDITOR.tools.cssLength; +n&&y||(g=this.element.getChild(0),n=this._notificationWidth=g.getClientRect().width,y=this._notificationMargin=parseInt(g.getComputedStyle("margin-left"),10)+parseInt(g.getComputedStyle("margin-right"),10));a.toolbar&&(m=a.ui.space(a.config.toolbarLocation),c=m.getClientRect());m&&m.isVisible()&&c.bottom>h.top&&c.bottomv.y?e.setStyles({position:"fixed",top:0}): +e.setStyles({position:"absolute",top:x(l.y+h.height-d.height)});var t="fixed"==e.getStyle("position")?h.left:"static"!=q.getComputedStyle("position")?l.x-r.x:l.x;h.widthv.x+p.width?b():e.setStyle("left",x(t)):l.x+n+y>v.x+p.width?e.setStyle("left",x(t)):l.x+h.width/2+n/2+y>v.x+p.width?e.setStyle("left",x(t-l.x+v.x+p.width-n-y)):0>h.left+h.width-n-y?b():0>h.left+h.width/2-n/2?e.setStyle("left",x(t-l.x+v.x)):e.setStyle("left",x(t+h.width/2-n/2-y/2))}};CKEDITOR.plugins.notification=b}(), function(){var b='\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&&(b+=' onkeypress\x3d"return false;"');CKEDITOR.env.gecko&&(b+= ' onblur\x3d"this.style.cssText \x3d this.style.cssText;"');var h="";CKEDITOR.env.ie&&(h='return false;" onmouseup\x3d"CKEDITOR.tools.getMouseButton(event)\x3d\x3dCKEDITOR.MOUSE_BUTTON_LEFT\x26\x26');var b=b+(' onkeydown\x3d"return CKEDITOR.tools.callFunction({keydownFn},event);" onfocus\x3d"return CKEDITOR.tools.callFunction({focusFn},event);" onclick\x3d"'+h+'CKEDITOR.tools.callFunction({clickFn},this);return false;"\x3e\x3cspan class\x3d"cke_button_icon cke_button__{iconName}_icon" style\x3d"{style}"')+ '\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{ariaShortcutSpace}{ariaShortcut}\x3c/span\x3e{arrowHtml}\x3c/a\x3e',f=CKEDITOR.addTemplate("buttonArrow",'\x3cspan class\x3d"cke_button_arrow"\x3e'+(CKEDITOR.env.hc?"\x26#9660;":"")+"\x3c/span\x3e"),e=CKEDITOR.addTemplate("button",b);CKEDITOR.plugins.add("button", -{beforeInit:function(a){a.ui.addHandler(CKEDITOR.UI_BUTTON,CKEDITOR.ui.button.handler)}});CKEDITOR.UI_BUTTON="button";CKEDITOR.ui.button=function(a){CKEDITOR.tools.extend(this,a,{title:a.label,click:a.click||function(b){b.execCommand(a.command)}});this._={}};CKEDITOR.ui.button.handler={create:function(a){return new CKEDITOR.ui.button(a)}};CKEDITOR.ui.button.prototype={render:function(a,b){function h(){var b=a.mode;b&&(b=this.modes[b]?void 0!==l[b]?l[b]:CKEDITOR.TRISTATE_OFF:CKEDITOR.TRISTATE_DISABLED, -b=a.readOnly&&!this.readOnly?CKEDITOR.TRISTATE_DISABLED:b,this.setState(b),this.refresh&&this.refresh())}var l=null,c=CKEDITOR.env,d=this._.id=CKEDITOR.tools.getNextId(),g="",n=this.command,y,w,p;this._.editor=a;var t={id:d,button:this,editor:a,focus:function(){CKEDITOR.document.getById(d).focus()},execute:function(){this.button.click(a)},attach:function(a){this.button.attach(a)}},r=CKEDITOR.tools.addFunction(function(a){if(t.onkey)return a=new CKEDITOR.dom.event(a),!1!==t.onkey(t,a.getKeystroke())}), -x=CKEDITOR.tools.addFunction(function(a){var b;t.onfocus&&(b=!1!==t.onfocus(t,new CKEDITOR.dom.event(a)));return b}),u=0;t.clickFn=y=CKEDITOR.tools.addFunction(function(){u&&(a.unlockSelection(1),u=0);t.execute();c.iOS&&a.focus()});this.modes?(l={},a.on("beforeModeUnload",function(){a.mode&&this._.state!=CKEDITOR.TRISTATE_DISABLED&&(l[a.mode]=this._.state)},this),a.on("activeFilterChange",h,this),a.on("mode",h,this),!this.readOnly&&a.on("readOnly",h,this)):n&&(n=a.getCommand(n))&&(n.on("state",function(){this.setState(n.state)}, -this),g+=n.state==CKEDITOR.TRISTATE_ON?"on":n.state==CKEDITOR.TRISTATE_DISABLED?"disabled":"off");var z;if(this.directional)a.on("contentDirChanged",function(b){var c=CKEDITOR.document.getById(this._.id),d=c.getFirst();b=b.data;b!=a.lang.dir?c.addClass("cke_"+b):c.removeClass("cke_ltr").removeClass("cke_rtl");d.setAttribute("style",CKEDITOR.skin.getIconStyle(z,"rtl"==b,this.icon,this.iconOffset))},this);n?(w=a.getCommandKeystroke(n))&&(p=CKEDITOR.tools.keystrokeToString(a.lang.common.keyboard,w)): -g+="off";w=this.name||this.command;var q=null,v=this.icon;z=w;this.icon&&!/\./.test(this.icon)?(z=this.icon,v=null):(this.icon&&(q=this.icon),CKEDITOR.env.hidpi&&this.iconHiDpi&&(q=this.iconHiDpi));q?(CKEDITOR.skin.addIcon(q,q),v=null):q=z;g={id:d,name:w,iconName:z,label:this.label,cls:(this.hasArrow?"cke_button_expandable ":"")+(this.className||""),state:g,ariaDisabled:"disabled"==g?"true":"false",title:this.title+(p?" ("+p.display+")":""),ariaShortcutSpace:p?"\x26nbsp;":"",ariaShortcut:p?a.lang.common.keyboardShortcut+ -" "+p.aria:"",titleJs:c.gecko&&!c.hc?"":(this.title||"").replace("'",""),hasArrow:"string"===typeof this.hasArrow&&this.hasArrow||(this.hasArrow?"true":"false"),keydownFn:r,focusFn:x,clickFn:y,style:CKEDITOR.skin.getIconStyle(q,"rtl"==a.lang.dir,v,this.iconOffset),arrowHtml:this.hasArrow?f.output():""};e.output(g,b);if(this.onRender)this.onRender();return t},setState:function(a){if(this._.state==a)return!1;this._.state=a;var b=CKEDITOR.document.getById(this._.id);return b?(b.setState(a,"cke_button"), +{beforeInit:function(a){a.ui.addHandler(CKEDITOR.UI_BUTTON,CKEDITOR.ui.button.handler)}});CKEDITOR.UI_BUTTON="button";CKEDITOR.ui.button=function(a){CKEDITOR.tools.extend(this,a,{title:a.label,click:a.click||function(b){b.execCommand(a.command)}});this._={}};CKEDITOR.ui.button.handler={create:function(a){return new CKEDITOR.ui.button(a)}};CKEDITOR.ui.button.prototype={render:function(a,b){function h(){var c=a.mode;c&&(c=this.modes[c]?void 0!==m[c]?m[c]:CKEDITOR.TRISTATE_OFF:CKEDITOR.TRISTATE_DISABLED, +c=a.readOnly&&!this.readOnly?CKEDITOR.TRISTATE_DISABLED:c,this.setState(c),this.refresh&&this.refresh())}var m=null,c=CKEDITOR.env,d=this._.id=CKEDITOR.tools.getNextId(),g="",n=this.command,y,v,p;this._.editor=a;var q={id:d,button:this,editor:a,focus:function(){CKEDITOR.document.getById(d).focus()},execute:function(){this.button.click(a)},attach:function(a){this.button.attach(a)}},r=CKEDITOR.tools.addFunction(function(a){if(q.onkey)return a=new CKEDITOR.dom.event(a),!1!==q.onkey(q,a.getKeystroke())}), +x=CKEDITOR.tools.addFunction(function(a){var c;q.onfocus&&(c=!1!==q.onfocus(q,new CKEDITOR.dom.event(a)));return c}),t=0;q.clickFn=y=CKEDITOR.tools.addFunction(function(){t&&(a.unlockSelection(1),t=0);q.execute();c.iOS&&a.focus()});this.modes?(m={},a.on("beforeModeUnload",function(){a.mode&&this._.state!=CKEDITOR.TRISTATE_DISABLED&&(m[a.mode]=this._.state)},this),a.on("activeFilterChange",h,this),a.on("mode",h,this),!this.readOnly&&a.on("readOnly",h,this)):n&&(n=a.getCommand(n))&&(n.on("state",function(){this.setState(n.state)}, +this),g+=n.state==CKEDITOR.TRISTATE_ON?"on":n.state==CKEDITOR.TRISTATE_DISABLED?"disabled":"off");var z;if(this.directional)a.on("contentDirChanged",function(c){var b=CKEDITOR.document.getById(this._.id),d=b.getFirst();c=c.data;c!=a.lang.dir?b.addClass("cke_"+c):b.removeClass("cke_ltr").removeClass("cke_rtl");d.setAttribute("style",CKEDITOR.skin.getIconStyle(z,"rtl"==c,this.icon,this.iconOffset))},this);n?(v=a.getCommandKeystroke(n))&&(p=CKEDITOR.tools.keystrokeToString(a.lang.common.keyboard,v)): +g+="off";v=this.name||this.command;var u=null,w=this.icon;z=v;this.icon&&!/\./.test(this.icon)?(z=this.icon,w=null):(this.icon&&(u=this.icon),CKEDITOR.env.hidpi&&this.iconHiDpi&&(u=this.iconHiDpi));u?(CKEDITOR.skin.addIcon(u,u),w=null):u=z;g={id:d,name:v,iconName:z,label:this.label,cls:(this.hasArrow?"cke_button_expandable ":"")+(this.className||""),state:g,ariaDisabled:"disabled"==g?"true":"false",title:this.title+(p?" ("+p.display+")":""),ariaShortcutSpace:p?"\x26nbsp;":"",ariaShortcut:p?a.lang.common.keyboardShortcut+ +" "+p.aria:"",titleJs:c.gecko&&!c.hc?"":(this.title||"").replace("'",""),hasArrow:"string"===typeof this.hasArrow&&this.hasArrow||(this.hasArrow?"true":"false"),keydownFn:r,focusFn:x,clickFn:y,style:CKEDITOR.skin.getIconStyle(u,"rtl"==a.lang.dir,w,this.iconOffset),arrowHtml:this.hasArrow?f.output():""};e.output(g,b);if(this.onRender)this.onRender();return q},setState:function(a){if(this._.state==a)return!1;this._.state=a;var b=CKEDITOR.document.getById(this._.id);return b?(b.setState(a,"cke_button"), b.setAttribute("aria-disabled",a==CKEDITOR.TRISTATE_DISABLED),this.hasArrow?b.setAttribute("aria-expanded",a==CKEDITOR.TRISTATE_ON):a===CKEDITOR.TRISTATE_ON?b.setAttribute("aria-pressed",!0):b.removeAttribute("aria-pressed"),!0):!1},getState:function(){return this._.state},toFeature:function(a){if(this._.feature)return this._.feature;var b=this;this.allowedContent||this.requiredContent||!this.command||(b=a.getCommand(this.command)||b);return this._.feature=b}};CKEDITOR.ui.prototype.addButton=function(a, -b){this.add(a,CKEDITOR.UI_BUTTON,b)}}(),function(){function b(a){function b(){for(var c=e(),d=CKEDITOR.tools.clone(a.config.toolbarGroups)||h(a),g=0;gb.order?-1:0>a.order?1:a.orderc.order?-1:0>a.order?1:a.order]+data-cke-bookmark[^<]*?<\/span>/ig,"");e&&b(a,d)})}function B(){if("wysiwyg"==a.mode){var b=D("paste");a.getCommand("cut").setState(D("cut")); -a.getCommand("copy").setState(D("copy"));a.getCommand("paste").setState(b);a.fire("pasteState",b)}}function D(b){var c=a.getSelection(),c=c&&c.getRanges()[0];if((a.readOnly||c&&c.checkReadOnly())&&b in{paste:1,cut:1})return CKEDITOR.TRISTATE_DISABLED;if("paste"==b)return CKEDITOR.TRISTATE_OFF;b=a.getSelection();c=b.getRanges();return b.getType()==CKEDITOR.SELECTION_NONE||1==c.length&&c[0].collapsed?CKEDITOR.TRISTATE_DISABLED:CKEDITOR.TRISTATE_OFF}var A=CKEDITOR.plugins.clipboard,E=0,F=0;(function(){a.on("key", -q);a.on("contentDom",c);a.on("selectionChange",B);if(a.contextMenu){a.contextMenu.addListener(function(){return{cut:D("cut"),copy:D("copy"),paste:D("paste")}});var b=null;a.on("menuShow",function(){b&&(b.removeListener(),b=null);var c=a.contextMenu.findItemByCommandName("paste");c&&c.element&&(b=c.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,e,f,h){var n=a.lang.clipboard[d];a.addCommand(d,e);a.ui.addButton&&a.ui.addButton(c,{label:n,command:d,toolbar:"clipboard,"+f});a.addMenuItems&&a.addMenuItem(d,{label:n,command:d,group:"clipboard",order:h})}b("Cut","cut",d("cut"),10,1);b("Copy","copy",d("copy"),20,4);b("Paste","paste",e(),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 e(a){a.removeListener();a.cancel();c({type:h,dataValue:a.data.dataValue,dataTransfer:a.data.dataTransfer,method:"paste"})}var f=!1,h="auto";c||(c=b,b=null);a.on("beforePaste",function(a){a.removeListener();f=!0;h=a.data.type},null,null,1E3);a.on("paste",d,null,null,0);!1===z()&&(a.removeListener("paste",d),a._.forcePasteDialog&&f&&a.fire("pasteDialog")?(a.on("pasteDialogCommit",e),a.on("dialogHide",function(a){a.removeListener(); -a.data.removeListener("pasteDialogCommit",e);a.data._.committed||c(null)})):c(null))}}function f(a){if(CKEDITOR.env.webkit){if(!a.match(/^[^<]*$/g)&&!a.match(/^(
<\/div>|
[^<]*<\/div>)*$/gi))return"html"}else if(CKEDITOR.env.ie){if(!a.match(/^([^<]|)*$/gi)&&!a.match(/^(

([^<]|)*<\/p>|(\r\n))*$/gi))return"html"}else if(CKEDITOR.env.gecko){if(!a.match(/^([^<]|)*$/gi))return"html"}else return"html";return"htmlifiedtext"}function e(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(/> +/gi,"\x3cbr\x3e");b=b.replace(/<\/?[A-Z]+>/g,function(a){return a.toLowerCase()});if(b.match(/^[^<]$/))return b;CKEDITOR.env.webkit&&-1(
|)<\/div>)(?!$|(

(
|)<\/div>))/g,"\x3cbr\x3e").replace(/^(
(
|)<\/div>){2}(?!$)/g,"\x3cdiv\x3e\x3c/div\x3e"),b.match(/
(
|)<\/div>/)&&(b="\x3cp\x3e"+b.replace(/(
(
|)<\/div>)+/g, -function(a){return c(a.split("\x3c/div\x3e\x3cdiv\x3e").length+1)})+"\x3c/p\x3e"),b=b.replace(/<\/div>
/g,"\x3cbr\x3e"),b=b.replace(/<\/?div>/g,""));CKEDITOR.env.gecko&&a.enterMode!=CKEDITOR.ENTER_BR&&(CKEDITOR.env.gecko&&(b=b.replace(/^

$/,"\x3cbr\x3e")),-1){2,}/g,function(a){return c(a.length/4)})+"\x3c/p\x3e"));return k(a,b)}function a(a){function b(){var a={},c;for(c in CKEDITOR.dtd)"$"!=c.charAt(0)&&"div"!=c&&"span"!= -c&&(a[c]=1);return a}var c={};return{get:function(d){return"plain-text"==d?c.plainText||(c.plainText=new CKEDITOR.filter(a,"br")):"semantic-content"==d?((d=c.semanticContent)||(d=new CKEDITOR.filter(a,{}),d.allow({$1:{elements:b(),attributes:!0,styles:!1,classes:!1}}),d=c.semanticContent=d),d):d?new CKEDITOR.filter(a,d):null}}}function m(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 k(a,b){a.enterMode==CKEDITOR.ENTER_BR?b=b.replace(/(<\/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 l(a){a.data.preventDefault();a.data.$.dataTransfer.dropEffect="none"}function c(a){var c=CKEDITOR.plugins.clipboard;a.on("contentDom",function(){function d(c,e,f){e.select();b(a,{dataTransfer:f,method:"drop"},1);f.sourceEditor.fire("saveSnapshot"); -f.sourceEditor.editable().extractHtmlFromRange(c);f.sourceEditor.getSelection().selectRanges([c]);f.sourceEditor.fire("saveSnapshot")}function e(d,f){d.select();b(a,{dataTransfer:f,method:"drop"},1);c.resetDragDataTransfer()}function f(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 h(a){a.type!=CKEDITOR.NODE_ELEMENT&&(a=a.getParent());return a.getChildCount()}var k=a.editable(),l=CKEDITOR.plugins.clipboard.getDropTarget(a), -m=a.ui.space("top"),z=a.ui.space("bottom");c.preventDefaultDropOnElement(m);c.preventDefaultDropOnElement(z);k.attachListener(l,"dragstart",f);k.attachListener(a,"dragstart",c.resetDragDataTransfer,c,null,1);k.attachListener(a,"dragstart",function(b){c.initDragDataTransfer(b,a)},null,null,2);k.attachListener(a,"dragstart",function(){var b=c.dragRange=a.getSelection().getRanges()[0];CKEDITOR.env.ie&&10>CKEDITOR.env.version&&(c.dragStartContainerChildCount=b?h(b.startContainer):null,c.dragEndContainerChildCount= -b?h(b.endContainer):null)},null,null,100);k.attachListener(l,"dragend",f);k.attachListener(a,"dragend",c.initDragDataTransfer,c,null,1);k.attachListener(a,"dragend",c.resetDragDataTransfer,c,null,100);k.attachListener(l,"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()}}); -k.attachListener(l,"drop",function(b){if(!b.data.$.defaultPrevented&&(b.data.preventDefault(),!a.readOnly)){var d=b.data.getTarget();if(!d.isReadOnly()||d.type==CKEDITOR.NODE_ELEMENT&&d.is("html")){var d=c.getRangeAtDropPosition(b,a),e=c.dragRange;d&&f(b,e,d)}}},null,null,9999);k.attachListener(a,"drop",c.initDragDataTransfer,c,null,1);k.attachListener(a,"drop",function(b){if(b=b.data){var f=b.dropRange,h=b.dragRange,k=b.dataTransfer;k.getTransferType(a)==CKEDITOR.DATA_TRANSFER_INTERNAL?setTimeout(function(){c.internalDrop(h, -f,k,a)},0):k.getTransferType(a)==CKEDITOR.DATA_TRANSFER_CROSS_EDITORS?d(h,f,k):e(f,k)}},null,null,9999)})}var d;CKEDITOR.plugins.add("clipboard",{requires:"dialog,notification,toolbar",init:function(b){function d(a){if(!a||t===a.id)return!1;var b=a.getTypes(),b=1===b.length&&"Files"===b[0];a=1===a.getFilesCount();return b&&a}var k,l=a(b);b.config.forcePasteAsPlainText?k="plain-text":b.config.pasteFilter?k=b.config.pasteFilter:!CKEDITOR.env.webkit||"pasteFilter"in b.config||(k="semantic-content"); -b.pasteFilter=l.get(k);h(b);c(b);CKEDITOR.dialog.add("paste",CKEDITOR.getUrl(this.path+"dialogs/paste.js"));if(CKEDITOR.env.gecko){var p=["image/png","image/jpeg","image/gif"],t;b.on("paste",function(a){var c=a.data,e=c.dataTransfer;if(!c.dataValue&&"paste"==c.method&&d(e)&&(e=e.getFile(0),-1!=CKEDITOR.tools.indexOf(p,e.type))){var f=new FileReader;f.addEventListener("load",function(){a.data.dataValue='\x3cimg src\x3d"'+f.result+'" /\x3e';b.fire("paste",a.data)},!1);f.addEventListener("abort",function(){b.fire("paste", -a.data)},!1);f.addEventListener("error",function(){b.fire("paste",a.data)},!1);f.readAsDataURL(e);t=c.dataTransfer.id;a.stop()}},null,null,1)}b.on("paste",function(a){a.data.dataTransfer||(a.data.dataTransfer=new CKEDITOR.plugins.clipboard.dataTransfer);if(!a.data.dataValue){var c=a.data.dataTransfer,d=c.getData("text/html");if(d)a.data.dataValue=d,a.data.type="html";else if(d=c.getData("text/plain"))a.data.dataValue=b.editable().transformPlainTextToHtml(d),a.data.type="text"}},null,null,1);b.on("paste", -function(a){var b=a.data.dataValue,c=CKEDITOR.dtd.$block;-1 <\/span>/gi," "),"html"!=a.data.type&&(b=b.replace(/]*>([^<]*)<\/span>/gi,function(a,b){return b.replace(/\t/g,"\x26nbsp;\x26nbsp; \x26nbsp;")})),-1/,"")),b=b.replace(/(<[^>]+) class="Apple-[^"]*"/gi, -"$1"));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(/
$/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>$/,function(b,d){return d in -c?(a.data.endsWithEOL=1,"\x3c/"+d+"\x3e"):b}):CKEDITOR.env.gecko&&(b=b.replace(/(\s)
$/,"$1"));a.data.dataValue=b},null,null,3);b.on("paste",function(a){a=a.data;var c=b._.nextPasteType||a.type,d=a.dataValue,h,k=b.config.clipboard_defaultContentType||"html",n=a.dataTransfer.getTransferType(b)==CKEDITOR.DATA_TRANSFER_EXTERNAL,t=!0===b.config.forcePasteAsPlainText;h="html"==c||"html"==a.preSniffing?"html":f(d);delete b._.nextPasteType;"htmlifiedtext"==h&&(d=e(b.config,d));if("text"==c&&"html"==h)d= -m(b,d,l.get("plain-text"));else if(n&&b.pasteFilter&&!a.dontFilter||t)d=m(b,d,b.pasteFilter);a.startsWithEOL&&(d='\x3cbr data-cke-eol\x3d"1"\x3e'+d);a.endsWithEOL&&(d+='\x3cbr data-cke-eol\x3d"1"\x3e');"auto"==c&&(c="html"==h||"html"==k?"html":"text");a.type=c;a.dataValue=d;delete a.preSniffing;delete a.startsWithEOL;delete a.endsWithEOL},null,null,6);b.on("paste",function(a){a=a.data;a.dataValue&&(b.insertHtml(a.dataValue,a.type,a.range),setTimeout(function(){b.fire("afterPaste")},0))},null,null, -1E3);b.on("pasteDialog",function(a){setTimeout(function(){b.openDialog("paste",a.data)},0)})}});CKEDITOR.plugins.clipboard={isCustomCopyCutSupported:CKEDITOR.env.ie&&16>CKEDITOR.env.version||CKEDITOR.env.iOS&&605>CKEDITOR.env.version?!1:!0,isCustomDataTypesSupported:!CKEDITOR.env.ie||16<=CKEDITOR.env.version,isFileApiSupported:!CKEDITOR.env.ie||9CKEDITOR.env.version||b.isInline()?b:a.document},fixSplitNodesAfterDrop:function(a,b,c,d){function e(a,c,d){var g=a;g.type==CKEDITOR.NODE_TEXT&&(g=a.getParent());if(g.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 f=b.startContainer;"number"==typeof d&&"number"== -typeof c&&f.type==CKEDITOR.NODE_ELEMENT&&(e(a.startContainer,f,c)||e(a.endContainer,f,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()CKEDITOR.env.version&&this.fixSplitNodesAfterDrop(a,c,f.dragStartContainerChildCount,f.dragEndContainerChildCount);(l=this.isDropRangeAffectedByDragRange(a,c))||(k=a.createBookmark(!1));f=c.clone().createBookmark(!1);l&&(k=a.createBookmark(!1));a=k.startNode;c=k.endNode;l=f.startNode;c&&a.getPosition(l)&CKEDITOR.POSITION_PRECEDING&&c.getPosition(l)&CKEDITOR.POSITION_FOLLOWING&&l.insertBefore(a);a=e.createRange();a.moveToBookmark(k);h.extractHtmlFromRange(a,1);c=e.createRange(); -f.startNode.getCommonAncestor(h)||(f=e.getSelection().createBookmarks()[0]);c.moveToBookmark(f);b(e,{dataTransfer:d,method:"drop",range:c},1);e.fire("unlockSnapshot")},getRangeAtDropPosition:function(a,b){var c=a.data.$,d=c.clientX,e=c.clientY,f=b.getSelection(!0).getRanges()[0],h=b.createRange();if(a.data.testRange)return a.data.testRange;if(document.caretRangeFromPoint&&b.document.$.caretRangeFromPoint(d,e))c=b.document.$.caretRangeFromPoint(d,e),h.setStart(CKEDITOR.dom.node(c.startContainer),c.startOffset), -h.collapse(!0);else if(c.rangeParent)h.setStart(CKEDITOR.dom.node(c.rangeParent),c.rangeOffset),h.collapse(!0);else{if(CKEDITOR.env.ie&&8l&&!k;l++){if(!k)try{c.moveToPoint(d,e-l),k=!0}catch(m){}if(!k)try{c.moveToPoint(d,e+l),k=!0}catch(q){}}if(k){var v="cke-temp-"+(new Date).getTime();c.pasteHTML('\x3cspan id\x3d"'+v+'"\x3e​\x3c/span\x3e'); -var B=b.document.getById(v);h.moveToPosition(B,CKEDITOR.POSITION_BEFORE_START);B.remove()}else{var D=b.document.$.elementFromPoint(d,e),A=new CKEDITOR.dom.element(D),E;if(A.equals(b.editable())||"html"==A.getName())return f&&f.startContainer&&!f.startContainer.equals(b.editable())?f:null;E=A.getClientRect();d/i,fragmentRegExp:/\s*\x3c!--StartFragment--\x3e|\x3c!--EndFragment--\x3e\s*/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(d);this.id||(this.id="Text"==d?"":"cke-"+CKEDITOR.tools.getUniqueId());b&&(this.sourceEditor=b,this.setData("text/html",b.getSelectedHtml(1)),"Text"==d||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(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 e=c.indexOf("\x3c/html\x3e"),c=-1!==e?c.substring(0,e+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"==d&&"Text"==a&&(this.id=b),this._.fallbackDataTransfer.isRequired())this._.fallbackDataTransfer.setData(a,b);else try{this.$.setData(a,b)}catch(c){}},storeId:function(){"Text"!== -d&&this.setData(d,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(c){c=b._.normalizeType(c);var d=b.getData(c);"text/html"==c&&(b._.nativeHtmlCache=b.getData(c,!0),d=b._stripHtml(d));d&&(b._.data[c]=d)}if(this.$){var b=this,c,d;if(CKEDITOR.plugins.clipboard.isCustomDataTypesSupported){if(this.$.types)for(c=0;c$/gi,"")}a&&a.length&& -(a=b(a),a=a.replace(this._.metaRegExp,""),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;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,e=this._dataTransfer.$;try{e.setData(a,d),c&&(this._dataTransfer._.nativeHtmlCache=d)}catch(f){if(this._isUnsupportedMimeTypeError(f)){c=CKEDITOR.plugins.clipboard.fallbackDataTransfer;-1===CKEDITOR.tools.indexOf(c._customTypes,a)&&c._customTypes.push(a);var c=this._getFallbackTypeContent(), -h=this._getFallbackTypeData();h[a]=d;try{d=this._applyDataComment(c,h),e.setData(this._customDataFallbackType,d),this._dataTransfer._.nativeHtmlCache=d}catch(k){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]+data-cke-bookmark[^<]*?<\/span>/ig,"");e&&b(a,d)})}function B(){if("wysiwyg"==a.mode){var c=C("paste");a.getCommand("cut").setState(C("cut")); +a.getCommand("copy").setState(C("copy"));a.getCommand("paste").setState(c);a.fire("pasteState",c)}}function C(c){var b=a.getSelection(),b=b&&b.getRanges()[0];if((a.readOnly||b&&b.checkReadOnly())&&c in{paste:1,cut:1})return CKEDITOR.TRISTATE_DISABLED;if("paste"==c)return CKEDITOR.TRISTATE_OFF;c=a.getSelection();b=c.getRanges();return c.getType()==CKEDITOR.SELECTION_NONE||1==b.length&&b[0].collapsed?CKEDITOR.TRISTATE_DISABLED:CKEDITOR.TRISTATE_OFF}var A=CKEDITOR.plugins.clipboard,E=0,F=0;(function(){a.on("key", +u);a.on("contentDom",c);a.on("selectionChange",B);if(a.contextMenu){a.contextMenu.addListener(function(){return{cut:C("cut"),copy:C("copy"),paste:C("paste")}});var b=null;a.on("menuShow",function(){b&&(b.removeListener(),b=null);var c=a.contextMenu.findItemByCommandName("paste");c&&c.element&&(b=c.element.on("touchend",function(){a._.forcePasteDialog=!0}))})}if(a.ui.addButton)a.once("instanceReady",function(){a._.pasteButtons&&CKEDITOR.tools.array.forEach(a._.pasteButtons,function(c){if(c=a.ui.get(c))if(c= +CKEDITOR.document.getById(c._.id))c.on("touchend",function(){a._.forcePasteDialog=!0})})})})();(function(){function c(b,d,e,f,h){var n=a.lang.clipboard[d];a.addCommand(d,e);a.ui.addButton&&a.ui.addButton(b,{label:n,command:d,toolbar:"clipboard,"+f});a.addMenuItems&&a.addMenuItem(d,{label:n,command:d,group:"clipboard",order:h})}c("Cut","cut",d("cut"),10,1);c("Copy","copy",d("copy"),20,4);c("Paste","paste",e(),30,8);a._.pasteButtons||(a._.pasteButtons=[]);a._.pasteButtons.push("Paste")})();a.getClipboardData= +function(c,b){function d(a){a.removeListener();a.cancel();b(a.data)}function e(a){a.removeListener();a.cancel();b({type:h,dataValue:a.data.dataValue,dataTransfer:a.data.dataTransfer,method:"paste"})}var f=!1,h="auto";b||(b=c,c=null);a.on("beforePaste",function(a){a.removeListener();f=!0;h=a.data.type},null,null,1E3);a.on("paste",d,null,null,0);!1===z()&&(a.removeListener("paste",d),a._.forcePasteDialog&&f&&a.fire("pasteDialog")?(a.on("pasteDialogCommit",e),a.on("dialogHide",function(a){a.removeListener(); +a.data.removeListener("pasteDialogCommit",e);a.data._.committed||b(null)})):b(null))}}function f(a){if(CKEDITOR.env.webkit){if(!a.match(/^[^<]*$/g)&&!a.match(/^(
<\/div>|
[^<]*<\/div>)*$/gi))return"html"}else if(CKEDITOR.env.ie){if(!a.match(/^([^<]|)*$/gi)&&!a.match(/^(

([^<]|)*<\/p>|(\r\n))*$/gi))return"html"}else if(CKEDITOR.env.gecko){if(!a.match(/^([^<]|)*$/gi))return"html"}else return"html";return"htmlifiedtext"}function e(a,c){function b(a){return CKEDITOR.tools.repeat("\x3c/p\x3e\x3cp\x3e", +~~(a/2))+(1==a%2?"\x3cbr\x3e":"")}c=c.replace(/(?!\u3000)\s+/g," ").replace(/> +/gi,"\x3cbr\x3e");c=c.replace(/<\/?[A-Z]+>/g,function(a){return a.toLowerCase()});if(c.match(/^[^<]$/))return c;CKEDITOR.env.webkit&&-1(
|)<\/div>)(?!$|(

(
|)<\/div>))/g,"\x3cbr\x3e").replace(/^(
(
|)<\/div>){2}(?!$)/g,"\x3cdiv\x3e\x3c/div\x3e"),c.match(/
(
|)<\/div>/)&&(c="\x3cp\x3e"+c.replace(/(
(
|)<\/div>)+/g, +function(a){return b(a.split("\x3c/div\x3e\x3cdiv\x3e").length+1)})+"\x3c/p\x3e"),c=c.replace(/<\/div>
/g,"\x3cbr\x3e"),c=c.replace(/<\/?div>/g,""));CKEDITOR.env.gecko&&a.enterMode!=CKEDITOR.ENTER_BR&&(CKEDITOR.env.gecko&&(c=c.replace(/^

$/,"\x3cbr\x3e")),-1){2,}/g,function(a){return b(a.length/4)})+"\x3c/p\x3e"));return l(a,c)}function a(a){function c(){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(d){return"plain-text"==d?b.plainText||(b.plainText=new CKEDITOR.filter(a,"br")):"semantic-content"==d?((d=b.semanticContent)||(d=new CKEDITOR.filter(a,{}),d.allow({$1:{elements:c(),attributes:!0,styles:!1,classes:!1}}),d=b.semanticContent=d),d):d?new CKEDITOR.filter(a,d):null}}}function k(a,c,b){c=CKEDITOR.htmlParser.fragment.fromHtml(c);var d=new CKEDITOR.htmlParser.basicWriter;b.applyTo(c,!0,!1,a.activeEnterMode);c.writeHtml(d);return d.getHtml()} +function l(a,c){a.enterMode==CKEDITOR.ENTER_BR?c=c.replace(/(<\/p>

)+/g,function(a){return CKEDITOR.tools.repeat("\x3cbr\x3e",a.length/7*2)}).replace(/<\/?p>/g,""):a.enterMode==CKEDITOR.ENTER_DIV&&(c=c.replace(/<(\/)?p>/g,"\x3c$1div\x3e"));return c}function m(a){a.data.preventDefault();a.data.$.dataTransfer.dropEffect="none"}function c(a){var c=CKEDITOR.plugins.clipboard;a.on("contentDom",function(){function d(c,e,f){e.select();b(a,{dataTransfer:f,method:"drop"},1);f.sourceEditor.fire("saveSnapshot"); +f.sourceEditor.editable().extractHtmlFromRange(c);f.sourceEditor.getSelection().selectRanges([c]);f.sourceEditor.fire("saveSnapshot")}function e(d,f){d.select();b(a,{dataTransfer:f,method:"drop"},1);c.resetDragDataTransfer()}function f(c,b,d){var e={$:c.data.$,target:c.data.getTarget()};b&&(e.dragRange=b);d&&(e.dropRange=d);!1===a.fire(c.name,e)&&c.data.preventDefault()}function h(a){a.type!=CKEDITOR.NODE_ELEMENT&&(a=a.getParent());return a.getChildCount()}var l=a.editable(),k=CKEDITOR.plugins.clipboard.getDropTarget(a), +m=a.ui.space("top"),z=a.ui.space("bottom");c.preventDefaultDropOnElement(m);c.preventDefaultDropOnElement(z);l.attachListener(k,"dragstart",f);l.attachListener(a,"dragstart",c.resetDragDataTransfer,c,null,1);l.attachListener(a,"dragstart",function(b){c.initDragDataTransfer(b,a)},null,null,2);l.attachListener(a,"dragstart",function(){var b=c.dragRange=a.getSelection().getRanges()[0];CKEDITOR.env.ie&&10>CKEDITOR.env.version&&(c.dragStartContainerChildCount=b?h(b.startContainer):null,c.dragEndContainerChildCount= +b?h(b.endContainer):null)},null,null,100);l.attachListener(k,"dragend",f);l.attachListener(a,"dragend",c.initDragDataTransfer,c,null,1);l.attachListener(a,"dragend",c.resetDragDataTransfer,c,null,100);l.attachListener(k,"dragover",function(a){if(CKEDITOR.env.edge)a.data.preventDefault();else{var c=a.data.getTarget();c&&c.is&&c.is("html")?a.data.preventDefault():CKEDITOR.env.ie&&CKEDITOR.plugins.clipboard.isFileApiSupported&&a.data.$.dataTransfer.types.contains("Files")&&a.data.preventDefault()}}); +l.attachListener(k,"drop",function(b){if(!b.data.$.defaultPrevented&&(b.data.preventDefault(),!a.readOnly)){var d=b.data.getTarget();if(!d.isReadOnly()||d.type==CKEDITOR.NODE_ELEMENT&&d.is("html")){var d=c.getRangeAtDropPosition(b,a),e=c.dragRange;d&&f(b,e,d)}}},null,null,9999);l.attachListener(a,"drop",c.initDragDataTransfer,c,null,1);l.attachListener(a,"drop",function(b){if(b=b.data){var f=b.dropRange,h=b.dragRange,l=b.dataTransfer;l.getTransferType(a)==CKEDITOR.DATA_TRANSFER_INTERNAL?setTimeout(function(){c.internalDrop(h, +f,l,a)},0):l.getTransferType(a)==CKEDITOR.DATA_TRANSFER_CROSS_EDITORS?d(h,f,l):e(f,l)}},null,null,9999)})}var d;CKEDITOR.plugins.add("clipboard",{requires:"dialog,notification,toolbar",init:function(b){function d(a){a=CKEDITOR.tools.array.map(a,function(a){return a.split("/")[1].toUpperCase()}).join(", ");return b.lang.clipboard.fileFormatNotSupportedNotification.replace(/\${formats\}/g,a)}function l(a,c){return CKEDITOR.env.ie&&a.data.fileTransferCancel||!(CKEDITOR.env.ie||c&&x!==c.id)?!1:c.isFileTransfer()&& +1===c.getFilesCount()}var m,p=a(b);b.config.forcePasteAsPlainText?m="plain-text":b.config.pasteFilter?m=b.config.pasteFilter:!CKEDITOR.env.webkit||"pasteFilter"in b.config||(m="semantic-content");b.pasteFilter=p.get(m);h(b);c(b);CKEDITOR.dialog.add("paste",CKEDITOR.getUrl(this.path+"dialogs/paste.js"));if((CKEDITOR.plugins.clipboard.isCustomDataTypesSupported||CKEDITOR.plugins.clipboard.isFileApiSupported)&&b.config.clipboard_handleImages){var q=["image/png","image/jpeg","image/gif"],r=d(q),x;b.on("paste", +function(a){var c=a.data,d=c.dataTransfer;if(!c.dataValue&&l(a,d))if(d=d.getFile(0),-1===CKEDITOR.tools.indexOf(q,d.type))b.showNotification(r,"info",b.config.clipboard_notificationDuration);else{var e=new FileReader;e.addEventListener("load",function(){a.data.dataValue='\x3cimg src\x3d"'+e.result+'" /\x3e';b.fire("paste",a.data)},!1);e.addEventListener("abort",function(){CKEDITOR.env.ie&&(a.data.fileTransferCancel=!0);b.fire("paste",a.data)},!1);e.addEventListener("error",function(){CKEDITOR.env.ie&& +(a.data.fileTransferCancel=!0);b.fire("paste",a.data)},!1);e.readAsDataURL(d);x=c.dataTransfer.id;a.stop()}},null,null,1)}b.on("paste",function(a){a.data.dataTransfer||(a.data.dataTransfer=new CKEDITOR.plugins.clipboard.dataTransfer);if(!a.data.dataValue){var c=a.data.dataTransfer,d=c.getData("text/html");if(d)a.data.dataValue=d,a.data.type="html";else if(d=c.getData("text/plain"))a.data.dataValue=b.editable().transformPlainTextToHtml(d),a.data.type="text"}},null,null,1);b.on("paste",function(a){var c= +a.data.dataValue,b=CKEDITOR.dtd.$block;-1 <\/span>/gi," "),"html"!=a.data.type&&(c=c.replace(/]*>([^<]*)<\/span>/gi,function(a,c){return c.replace(/\t/g,"\x26nbsp;\x26nbsp; \x26nbsp;")})),-1/,"")),c=c.replace(/(<[^>]+) class="Apple-[^"]*"/gi, +"$1"));if(c.match(/^<[^<]+cke_(editable|contents)/i)){var d,g,e=new CKEDITOR.dom.element("div");for(e.setHtml(c);1==e.getChildCount()&&(d=e.getFirst())&&d.type==CKEDITOR.NODE_ELEMENT&&(d.hasClass("cke_editable")||d.hasClass("cke_contents"));)e=g=d;g&&(c=g.getHtml().replace(/
$/i,""))}CKEDITOR.env.ie?c=c.replace(/^ (?: |\r\n)?<(\w+)/g,function(c,d){return d.toLowerCase()in b?(a.data.preSniffing="html","\x3c"+d):c}):CKEDITOR.env.webkit?c=c.replace(/<\/(\w+)>


<\/div>$/,function(c,d){return d in +b?(a.data.endsWithEOL=1,"\x3c/"+d+"\x3e"):c}):CKEDITOR.env.gecko&&(c=c.replace(/(\s)
$/,"$1"));a.data.dataValue=c},null,null,3);b.on("paste",function(a){a=a.data;var c=b._.nextPasteType||a.type,d=a.dataValue,h,l=b.config.clipboard_defaultContentType||"html",n=a.dataTransfer.getTransferType(b)==CKEDITOR.DATA_TRANSFER_EXTERNAL,m=!0===b.config.forcePasteAsPlainText;h="html"==c||"html"==a.preSniffing?"html":f(d);delete b._.nextPasteType;"htmlifiedtext"==h&&(d=e(b.config,d));if("text"==c&&"html"==h)d= +k(b,d,p.get("plain-text"));else if(n&&b.pasteFilter&&!a.dontFilter||m)d=k(b,d,b.pasteFilter);a.startsWithEOL&&(d='\x3cbr data-cke-eol\x3d"1"\x3e'+d);a.endsWithEOL&&(d+='\x3cbr data-cke-eol\x3d"1"\x3e');"auto"==c&&(c="html"==h||"html"==l?"html":"text");a.type=c;a.dataValue=d;delete a.preSniffing;delete a.startsWithEOL;delete a.endsWithEOL},null,null,6);b.on("paste",function(a){a=a.data;a.dataValue&&(b.insertHtml(a.dataValue,a.type,a.range),setTimeout(function(){b.fire("afterPaste")},0))},null,null, +1E3);b.on("pasteDialog",function(a){setTimeout(function(){b.openDialog("paste",a.data)},0)})}});CKEDITOR.plugins.clipboard={isCustomCopyCutSupported:CKEDITOR.env.ie&&16>CKEDITOR.env.version||CKEDITOR.env.iOS&&605>CKEDITOR.env.version?!1:!0,isCustomDataTypesSupported:!CKEDITOR.env.ie||16<=CKEDITOR.env.version,isFileApiSupported:!CKEDITOR.env.ie||9CKEDITOR.env.version||c.isInline()?c:a.document},fixSplitNodesAfterDrop:function(a,c,b,d){function e(a,b,d){var g=a;g.type==CKEDITOR.NODE_TEXT&&(g=a.getParent());if(g.equals(b)&&d!=b.getChildCount())return a=c.startContainer.getChild(c.startOffset-1),b=c.startContainer.getChild(c.startOffset),a&&a.type==CKEDITOR.NODE_TEXT&&b&&b.type==CKEDITOR.NODE_TEXT&&(d=a.getLength(),a.setText(a.getText()+b.getText()),b.remove(),c.setStart(a,d),c.collapse(!0)),!0}var f=c.startContainer;"number"==typeof d&&"number"== +typeof b&&f.type==CKEDITOR.NODE_ELEMENT&&(e(a.startContainer,f,b)||e(a.endContainer,f,d))},isDropRangeAffectedByDragRange:function(a,c){var b=c.startContainer,d=c.endOffset;return a.endContainer.equals(b)&&a.endOffset<=d||a.startContainer.getParent().equals(b)&&a.startContainer.getIndex()CKEDITOR.env.version&&this.fixSplitNodesAfterDrop(a,c,f.dragStartContainerChildCount,f.dragEndContainerChildCount);(k=this.isDropRangeAffectedByDragRange(a,c))||(l=a.createBookmark(!1));f=c.clone().createBookmark(!1);k&&(l=a.createBookmark(!1));a=l.startNode;c=l.endNode;k=f.startNode;c&&a.getPosition(k)&CKEDITOR.POSITION_PRECEDING&&c.getPosition(k)&CKEDITOR.POSITION_FOLLOWING&&k.insertBefore(a);a=e.createRange();a.moveToBookmark(l);h.extractHtmlFromRange(a,1);c=e.createRange(); +f.startNode.getCommonAncestor(h)||(f=e.getSelection().createBookmarks()[0]);c.moveToBookmark(f);b(e,{dataTransfer:d,method:"drop",range:c},1);e.fire("unlockSnapshot")},getRangeAtDropPosition:function(a,c){var b=a.data.$,d=b.clientX,e=b.clientY,f=c.getSelection(!0).getRanges()[0],h=c.createRange();if(a.data.testRange)return a.data.testRange;if(document.caretRangeFromPoint&&c.document.$.caretRangeFromPoint(d,e))b=c.document.$.caretRangeFromPoint(d,e),h.setStart(CKEDITOR.dom.node(b.startContainer),b.startOffset), +h.collapse(!0);else if(b.rangeParent)h.setStart(CKEDITOR.dom.node(b.rangeParent),b.rangeOffset),h.collapse(!0);else{if(CKEDITOR.env.ie&&8k&&!l;k++){if(!l)try{b.moveToPoint(d,e-k),l=!0}catch(m){}if(!l)try{b.moveToPoint(d,e+k),l=!0}catch(u){}}if(l){var w="cke-temp-"+(new Date).getTime();b.pasteHTML('\x3cspan id\x3d"'+w+'"\x3e​\x3c/span\x3e'); +var B=c.document.getById(w);h.moveToPosition(B,CKEDITOR.POSITION_BEFORE_START);B.remove()}else{var C=c.document.$.elementFromPoint(d,e),A=new CKEDITOR.dom.element(C),E;if(A.equals(c.editable())||"html"==A.getName())return f&&f.startContainer&&!f.startContainer.equals(c.editable())?f:null;E=A.getClientRect();d/i,fragmentRegExp:/\s*\x3c!--StartFragment--\x3e|\x3c!--EndFragment--\x3e\s*/g, +types:[],data:{},files:[],nativeHtmlCache:"",normalizeType:function(a){a=a.toLowerCase();return"text"==a||"text/plain"==a?"Text":"url"==a?"URL":"files"===a?"Files":a}};this._.fallbackDataTransfer=new CKEDITOR.plugins.clipboard.fallbackDataTransfer(this);this.id=this.getData(d);this.id||(this.id="Text"==d?"":"cke-"+CKEDITOR.tools.getUniqueId());c&&(this.sourceEditor=c,this.setData("text/html",c.getSelectedHtml(1)),"Text"==d||this.getData("text/plain")||this.setData("text/plain",c.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,c){a=this._.normalizeType(a);var b="text/html"==a&&c?this._.nativeHtmlCache:this._.data[a];if(void 0===b||null===b||""===b){if(this._.fallbackDataTransfer.isRequired())b=this._.fallbackDataTransfer.getData(a,c);else try{b=this.$.getData(a)||""}catch(d){b=""}"text/html"!=a||c||(b=this._stripHtml(b))}"Text"==a&&CKEDITOR.env.gecko&& +this.getFilesCount()&&"file://"==b.substring(0,7)&&(b="");if("string"===typeof b)var e=b.indexOf("\x3c/html\x3e"),b=-1!==e?b.substring(0,e+7):b;return b},setData:function(a,c){a=this._.normalizeType(a);"text/html"==a?(this._.data[a]=this._stripHtml(c),this._.nativeHtmlCache=c):this._.data[a]=c;if(CKEDITOR.plugins.clipboard.isCustomDataTypesSupported||"URL"==a||"Text"==a)if("Text"==d&&"Text"==a&&(this.id=c),this._.fallbackDataTransfer.isRequired())this._.fallbackDataTransfer.setData(a,c);else try{this.$.setData(a, +c)}catch(b){}},storeId:function(){"Text"!==d&&this.setData(d,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(b){b=c._.normalizeType(b);var d=c.getData(b);"text/html"==b&&(c._.nativeHtmlCache=c.getData(b,!0),d=c._stripHtml(d));d&&(c._.data[b]=d);c._.types.push(b)}if(this.$){var c=this,b,d,e;if(CKEDITOR.plugins.clipboard.isCustomDataTypesSupported){if(this.$.types)for(b= +0;b$/gi,"")}a&&a.length&&(a=c(a),a=a.replace(this._.metaRegExp,""),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,c=this._dataTransfer.$;if(null===a._isCustomMimeTypeSupported)if(c){a._isCustomMimeTypeSupported=!1;if(CKEDITOR.env.edge&&17<=CKEDITOR.env.version)return!0;try{c.setData("cke/mimetypetest","cke test value"),a._isCustomMimeTypeSupported="cke test value"===c.getData("cke/mimetypetest"),c.clearData("cke/mimetypetest")}catch(b){}}else return!1; +return!a._isCustomMimeTypeSupported},getData:function(a,c){var b=this._getData(this._customDataFallbackType,!0);if(c)return b;var b=this._extractDataComment(b),d=null,d=a===this._customDataFallbackType?b.content:b.data&&b.data[a]?b.data[a]:this._getData(a,!0);return null!==d?d:""},setData:function(a,c){var b=a===this._customDataFallbackType;b&&(c=this._applyDataComment(c,this._getFallbackTypeData()));var d=c,e=this._dataTransfer.$;try{e.setData(a,d),b&&(this._dataTransfer._.nativeHtmlCache=d)}catch(f){if(this._isUnsupportedMimeTypeError(f)){b= +CKEDITOR.plugins.clipboard.fallbackDataTransfer;-1===CKEDITOR.tools.indexOf(b._customTypes,a)&&b._customTypes.push(a);var b=this._getFallbackTypeContent(),h=this._getFallbackTypeData();h[a]=d;try{d=this._applyDataComment(b,h),e.setData(this._customDataFallbackType,d),this._dataTransfer._.nativeHtmlCache=d}catch(l){d=""}}}return d},_getData:function(a,c){var b=this._dataTransfer._.data;if(!c&&b[a])return b[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,c=this._extractDataComment(this._getData(this._customDataFallbackType,!0)).data||{},b=this._dataTransfer._.data;CKEDITOR.tools.array.forEach(a,function(a){void 0!==b[a]?c[a]=b[a]:void 0!==c[a]&&(c[a]=c[a])},this);return c},_isUnsupportedMimeTypeError:function(a){return a.message&& +-1!==a.message.search(/element not found/gi)},_extractDataComment:function(a){var c={data:null,content:a||""};if(a&&16g?r+g:b.width>g?r-a.left:r-a.right+b.width):fg?r-g:b.width>g?r-a.right+b.width:r-a.left);g=a.top;b.height-a.tope?x-e:b.height>e?x-a.bottom+b.height:x-a.top);CKEDITOR.env.ie&&!CKEDITOR.env.edge&&((b=a=n.$.offsetParent&&new CKEDITOR.dom.element(n.$.offsetParent))&&"html"==b.getName()&&(b=b.getDocument().getBody()),b&&"rtl"==b.getComputedStyle("direction")&& -(r=CKEDITOR.env.ie8Compat?r-2*n.getDocument().getDocumentElement().$.scrollLeft:r-(a.$.scrollWidth-a.$.clientWidth)));var a=n.getFirst(),k;(k=a.getCustomData("activePanel"))&&k.onHide&&k.onHide.call(this,1);a.setCustomData("activePanel",this);n.setStyles({top:x+"px",left:r+"px"});n.setOpacity(1);l&&l()},this);c.isLoaded?a():c.onLoad=a;CKEDITOR.tools.setTimeout(function(){var a=CKEDITOR.env.webkit&&CKEDITOR.document.getWindow().getScrollPosition().y;this.focus();d.element.focus();CKEDITOR.env.webkit&& +d.element:b.getBody()).$.scrollWidth;CKEDITOR.env.ie&&CKEDITOR.env.quirks&&0g?r+g:b.width>g?r-a.left:r-a.right+b.width):fg?r-g:b.width>g?r-a.right+b.width:r-a.left);g=a.top;b.height-a.tope?x-e:b.height>e?x-a.bottom+b.height:x-a.top);CKEDITOR.env.ie&&!CKEDITOR.env.edge&&((b=a=n.$.offsetParent&&new CKEDITOR.dom.element(n.$.offsetParent))&&"html"==b.getName()&&(b=b.getDocument().getBody()),b&&"rtl"==b.getComputedStyle("direction")&& +(r=CKEDITOR.env.ie8Compat?r-2*n.getDocument().getDocumentElement().$.scrollLeft:r-(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:x+"px",left:r+"px"});n.setOpacity(1);m&&m()},this);c.isLoaded?a():c.onLoad=a;CKEDITOR.tools.setTimeout(function(){var a=CKEDITOR.env.webkit&&CKEDITOR.document.getWindow().getScrollPosition().y;this.focus();d.element.focus();CKEDITOR.env.webkit&& (CKEDITOR.document.getBody().$.scrollTop=a);this.allowBlur(!0);this._.markFirst&&(CKEDITOR.env.ie?CKEDITOR.tools.setTimeout(function(){d.markFirstDisplayed?d.markFirstDisplayed():d._.markFirstDisplayed()},0):d.markFirstDisplayed?d.markFirstDisplayed():d._.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 b=this._.showBlockParams;this.visible&&this._.showBlockParams&&(this.hide(), this.showBlock.apply(this,b))},focus:function(){if(CKEDITOR.env.webkit){var b=CKEDITOR.document.getActive();b&&!b.equals(this._.iframe)&&b.$.blur()}(this._.lastFocused||this._.iframe.getFrameDocument().getWindow()).focus()},blur:function(){var b=this._.iframe.getFrameDocument().getActive();b&&b.is("a")&&(this._.lastFocused=b)},hide:function(b){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(b=b&&this._.returnFocus)CKEDITOR.env.webkit&&b.type&&b.getWindow().$.focus(),b.focus();delete this._.lastFocused;this._.showBlockParams=null;this._.editor.fire("panelHide",this)}},allowBlur:function(b){var e=this._.panel;void 0!==b&&(e.allowBlur=b);return e.allowBlur},showAsChild:function(b,e,a,h,k,l){if(this._.activeChild!=b||b._.panel._.offsetParentId!=a.getId())this.hideChild(),b.onHide= -CKEDITOR.tools.bind(function(){CKEDITOR.tools.setTimeout(function(){this._.focused||this.hide()},0,this)},this),this._.activeChild=b,this._.focused=!1,b.showBlock(e,a,h,k,l),this.blur(),(CKEDITOR.env.ie7Compat||CKEDITOR.env.ie6Compat)&&setTimeout(function(){b.element.getChild(0).$.style.cssText+=""},100)},hideChild:function(b){var e=this._.activeChild;e&&(delete e.onHide,delete this._.activeChild,e.hide(),b&&this.focus())}}});CKEDITOR.on("instanceDestroyed",function(){var b=CKEDITOR.tools.isEmpty(CKEDITOR.instances), +this.element.setStyle("display","none");this.visible=0;this.element.getFirst().removeCustomData("activePanel");if(b=b&&this._.returnFocus)CKEDITOR.env.webkit&&b.type&&b.getWindow().$.focus(),b.focus();delete this._.lastFocused;this._.showBlockParams=null;this._.editor.fire("panelHide",this)}},allowBlur:function(b){var e=this._.panel;void 0!==b&&(e.allowBlur=b);return e.allowBlur},showAsChild:function(b,e,a,h,l,m){if(this._.activeChild!=b||b._.panel._.offsetParentId!=a.getId())this.hideChild(),b.onHide= +CKEDITOR.tools.bind(function(){CKEDITOR.tools.setTimeout(function(){this._.focused||this.hide()},0,this)},this),this._.activeChild=b,this._.focused=!1,b.showBlock(e,a,h,l,m),this.blur(),(CKEDITOR.env.ie7Compat||CKEDITOR.env.ie6Compat)&&setTimeout(function(){b.element.getChild(0).$.style.cssText+=""},100)},hideChild:function(b){var e=this._.activeChild;e&&(delete e.onHide,delete this._.activeChild,e.hide(),b&&this.focus())}}});CKEDITOR.on("instanceDestroyed",function(){var b=CKEDITOR.tools.isEmpty(CKEDITOR.instances), e;for(e in h){var a=h[e];b?a.destroy():a.element.hide()}b&&(h={})})}(),CKEDITOR.plugins.add("menu",{requires:"floatpanel",beforeInit:function(b){for(var h=b.config.menu_groups.split(","),f=b._.menuGroups={},e=b._.menuItems={},a=0;ab.group?1:a.orderb.order?1:0})}var h='\x3cspan class\x3d"cke_menuitem"\x3e\x3ca id\x3d"{id}" class\x3d"cke_menubutton cke_menubutton__{name} cke_menubutton_{state} {cls}" href\x3d"{href}" title\x3d"{title}" tabindex\x3d"-1" _cke_focus\x3d1 hidefocus\x3d"true" role\x3d"{role}" aria-label\x3d"{attrLabel}" aria-describedby\x3d"{id}_description" aria-haspopup\x3d"{hasPopup}" aria-disabled\x3d"{disabled}" {ariaChecked} draggable\x3d"false"', +function(a){delete e[a]}}}),function(){function b(a){a.sort(function(a,c){return a.groupc.group?1:a.orderc.order?1:0})}var h='\x3cspan class\x3d"cke_menuitem"\x3e\x3ca id\x3d"{id}" class\x3d"cke_menubutton cke_menubutton__{name} cke_menubutton_{state} {cls}" href\x3d"{href}" title\x3d"{title}" tabindex\x3d"-1" _cke_focus\x3d1 hidefocus\x3d"true" role\x3d"{role}" aria-label\x3d"{attrLabel}" aria-describedby\x3d"{id}_description" aria-haspopup\x3d"{hasPopup}" aria-disabled\x3d"{disabled}" {ariaChecked} draggable\x3d"false"', f="";CKEDITOR.env.gecko&&CKEDITOR.env.mac&&(h+=' onkeypress\x3d"return false;"');CKEDITOR.env.gecko&&(h+=' onblur\x3d"this.style.cssText \x3d this.style.cssText;" ondragstart\x3d"return false;"');CKEDITOR.env.ie&&(f='return false;" onmouseup\x3d"CKEDITOR.tools.getMouseButton(event)\x3d\x3d\x3dCKEDITOR.MOUSE_BUTTON_LEFT\x26\x26');var h=h+(' onmouseover\x3d"CKEDITOR.tools.callFunction({hoverFn},{index});" onmouseout\x3d"CKEDITOR.tools.callFunction({moveOutFn},{index});" onclick\x3d"'+f+'CKEDITOR.tools.callFunction({clickFn},{index}); return false;"\x3e')+ '\x3cspan class\x3d"cke_menubutton_inner"\x3e\x3cspan class\x3d"cke_menubutton_icon"\x3e\x3cspan class\x3d"cke_button_icon cke_button__{iconName}_icon" style\x3d"{iconStyle}"\x3e\x3c/span\x3e\x3c/span\x3e\x3cspan class\x3d"cke_menubutton_label"\x3e{label}\x3c/span\x3e{shortcutHtml}{arrowHtml}\x3c/span\x3e\x3c/a\x3e\x3cspan id\x3d"{id}_description" class\x3d"cke_voice_label" aria-hidden\x3d"false"\x3e{ariaShortcut}\x3c/span\x3e\x3c/span\x3e',e=CKEDITOR.addTemplate("menuItem",h),a=CKEDITOR.addTemplate("menuArrow", -'\x3cspan class\x3d"cke_menuarrow"\x3e\x3cspan\x3e{label}\x3c/span\x3e\x3c/span\x3e'),m=CKEDITOR.addTemplate("menuShortcut",'\x3cspan class\x3d"cke_menubutton_label cke_menubutton_shortcut"\x3e{shortcut}\x3c/span\x3e');CKEDITOR.menu=CKEDITOR.tools.createClass({$:function(a,b){b=this._.definition=b||{};this.id=CKEDITOR.tools.getNextId();this.editor=a;this.items=[];this._.listeners=[];this._.level=b.level||1;var c=CKEDITOR.tools.extend({},b.panel,{css:[CKEDITOR.skin.getPath("editor")],level:this._.level- +'\x3cspan class\x3d"cke_menuarrow"\x3e\x3cspan\x3e{label}\x3c/span\x3e\x3c/span\x3e'),k=CKEDITOR.addTemplate("menuShortcut",'\x3cspan class\x3d"cke_menubutton_label cke_menubutton_shortcut"\x3e{shortcut}\x3c/span\x3e');CKEDITOR.menu=CKEDITOR.tools.createClass({$:function(a,b){b=this._.definition=b||{};this.id=CKEDITOR.tools.getNextId();this.editor=a;this.items=[];this._.listeners=[];this._.level=b.level||1;var c=CKEDITOR.tools.extend({},b.panel,{css:[CKEDITOR.skin.getPath("editor")],level:this._.level- 1,block:{}}),d=c.block.attributes=c.attributes||{};!d.role&&(d.role="menu");this._.panelDefinition=c},_:{onShow:function(){var a=this.editor.getSelection(),b=a&&a.getStartElement(),c=this.editor.elementPath(),d=this._.listeners;this.removeAll();for(var g=0;gCKEDITOR.env.version?k.createText("\r"):k.createElement("br"),e.deleteContents(),e.insertNode(a),CKEDITOR.env.needsBrFiller?(k.createText("").insertAfter(a),m&&(r||t.blockLimit).appendBogus(),a.getNext().$.nodeValue="",e.setStartAt(a.getNext(),CKEDITOR.POSITION_AFTER_START)):e.setStartAt(a,CKEDITOR.POSITION_AFTER_END)),e.collapse(!0),e.select(),e.scrollIntoView()):l(a,b,e,f)}}};m=CKEDITOR.plugins.enterkey;k=m.enterBr;l=m.enterBlock;c=/^h[1-6]$/}(),function(){function b(b,f){var e={},a=[],m={nbsp:" ", -shy:"­",gt:"\x3e",lt:"\x3c",amp:"\x26",apos:"'",quot:'"'};b=b.replace(/\b(nbsp|shy|gt|lt|amp|apos|quot)(?:,|$)/g,function(b,c){var h=f?"\x26"+c+";":m[c];e[h]=f?m[c]:"\x26"+c+";";a.push(h);return""});b=b.replace(/,$/,"");if(!f&&b){b=b.split(",");var k=document.createElement("div"),l;k.innerHTML="\x26"+b.join(";\x26")+";";l=k.innerHTML;k=null;for(k=0;kh&&(h=640);420>f&&(f=420);var a=parseInt((window.screen.height-f)/2,10),m=parseInt((window.screen.width- -h)/2,10);e=(e||"location\x3dno,menubar\x3dno,toolbar\x3dno,dependent\x3dyes,minimizable\x3dno,modal\x3dyes,alwaysRaised\x3dyes,resizable\x3dyes,scrollbars\x3dyes")+",width\x3d"+h+",height\x3d"+f+",top\x3d"+a+",left\x3d"+m;var k=window.open("",null,e,!0);if(!k)return!1;try{-1==navigator.userAgent.toLowerCase().indexOf(" chrome/")&&(k.moveTo(m,a),k.resizeTo(h,f)),k.focus(),k.location.href=b}catch(l){window.open(b,null,e,!0)}return!0}}),"use strict",function(){function b(a){this.editor=a;this.loaders= +exec:function(a){b(a,a.activeShiftEnterMode,1)}});a.setKeystroke([[13,"enter"],[CKEDITOR.SHIFT+13,"shiftEnter"]])}});var e=CKEDITOR.dom.walker.whitespaces(),a=CKEDITOR.dom.walker.bookmark(),k,l,m,c;CKEDITOR.plugins.enterkey={enterBlock:function(b,g,k,m){function v(a){var b;if(a===CKEDITOR.ENTER_BR||-1===CKEDITOR.tools.indexOf(["td","th"],x.lastElement.getName())||1!==x.lastElement.getChildCount())return!1;a=x.lastElement.getChild(0).clone(!0);(b=a.getBogus())&&b.remove();return a.getText().length? +!1:!0}if(k=k||h(b)){k=f(k);var p=k.document,q=k.checkStartOfBlock(),r=k.checkEndOfBlock(),x=b.elementPath(k.startContainer),t=x.block,z=g==CKEDITOR.ENTER_DIV?"div":"p",u;if(t&&q&&r){q=t.getParent();if(q.is("li")&&1CKEDITOR.env.version?k.createText("\r"):k.createElement("br"),e.deleteContents(),e.insertNode(a),CKEDITOR.env.needsBrFiller?(k.createText("").insertAfter(a),l&&(r||q.blockLimit).appendBogus(),a.getNext().$.nodeValue="",e.setStartAt(a.getNext(),CKEDITOR.POSITION_AFTER_START)):e.setStartAt(a,CKEDITOR.POSITION_AFTER_END)),e.collapse(!0),e.select(),e.scrollIntoView()):m(a,b,e,f)}}};k=CKEDITOR.plugins.enterkey;l=k.enterBr;m=k.enterBlock;c=/^h[1-6]$/}(),function(){function b(b,f){var e={},a=[],k={nbsp:" ", +shy:"­",gt:"\x3e",lt:"\x3c",amp:"\x26",apos:"'",quot:'"'};b=b.replace(/\b(nbsp|shy|gt|lt|amp|apos|quot)(?:,|$)/g,function(b,c){var h=f?"\x26"+c+";":k[c];e[h]=f?k[c]:"\x26"+c+";";a.push(h);return""});b=b.replace(/,$/,"");if(!f&&b){b=b.split(",");var l=document.createElement("div"),m;l.innerHTML="\x26"+b.join(";\x26")+";";m=l.innerHTML;l=null;for(l=0;lh&&(h=640);420>f&&(f=420);var a=parseInt((window.screen.height-f)/2,10),k=parseInt((window.screen.width- +h)/2,10);e=(e||"location\x3dno,menubar\x3dno,toolbar\x3dno,dependent\x3dyes,minimizable\x3dno,modal\x3dyes,alwaysRaised\x3dyes,resizable\x3dyes,scrollbars\x3dyes")+",width\x3d"+h+",height\x3d"+f+",top\x3d"+a+",left\x3d"+k;var l=window.open("",null,e,!0);if(!l)return!1;try{-1==navigator.userAgent.toLowerCase().indexOf(" chrome/")&&(l.moveTo(k,a),l.resizeTo(h,f)),l.focus(),l.location.href=b}catch(m){window.open(b,null,e,!0)}return!0}}),"use strict",function(){function b(a){this.editor=a;this.loaders= []}function h(a,b,e){var h=a.config.fileTools_defaultFileName;this.editor=a;this.lang=a.lang;"string"===typeof b?(this.data=b,this.file=f(this.data),this.loaded=this.total=this.file.size):(this.data=null,this.file=b,this.total=this.file.size,this.loaded=0);e?this.fileName=e:this.file.name?this.fileName=this.file.name:(a=this.file.type.split("/"),h&&(a[0]=h),this.fileName=a.join("."));this.uploaded=0;this.responseData=this.uploadTotal=null;this.status="created";this.abort=function(){this.changeStatus("abort")}} function f(a){var b=a.match(e)[1];a=a.replace(e,"");a=atob(a);var f=[],h,c,d,g;for(h=0;hf.status||299x.height-r.bottom?g("pin"):g("bottom"),d=x.width/2,d=a.floatSpacePreferRight?"right":0t.width?"rtl"==a.contentsLangDirection?"right":"left":d-r.left>r.right-d?"left":"right",t.width>x.width?(d="left",n=0):(n="left"==d?0x.width&&(d="left"==d?"right":"left",n=0)),c.setStyle(d,f(("pin"==l?B:q)+n+("pin"==l?0:"left"==d?z:-z)))):(l="pin",g("pin"),k(d))}}}();if(m){var l=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}"'+(b.title?' aria-labelledby\x3d"cke_{name}_arialbl"':" ")+"\x3e"+(b.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'),c=CKEDITOR.document.getBody().append(CKEDITOR.dom.element.createFromHtml(l.output({content:m, -id:b.id,langDir:b.lang.dir,langCode:b.langCode,name:b.name,style:"display:none;z-index:"+(a.baseFloatZIndex-1),topId:b.ui.spaceId("top"),voiceLabel:b.title}))),d=CKEDITOR.tools.eventsBuffer(500,k),g=CKEDITOR.tools.eventsBuffer(100,k);c.unselectable();c.on("mousedown",function(a){a=a.data;a.getTarget().hasAscendant("a",1)||a.preventDefault()});b.on("focus",function(a){k(a);b.on("change",d.input);h.on("scroll",g.input);h.on("resize",g.input)});b.on("blur",function(){c.hide();b.removeListener("change", +function(a){if(a.editor.plugins.filebrowser)for(var b=a.data.definition,c,e=0;ex.height-r.bottom?g("pin"):g("bottom"),d=x.width/2,d=a.floatSpacePreferRight?"right":0q.width?"rtl"==a.contentsLangDirection?"right":"left":d-r.left>r.right-d?"left":"right",q.width>x.width?(d="left",n=0):(n="left"==d?0x.width&&(d="left"==d?"right":"left",n=0)),c.setStyle(d,f(("pin"==k?B:u)+n+("pin"==k?0:"left"==d?z:-z)))):(k="pin",g("pin"),l(d))}}}();if(k){var m=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}"'+(b.title?' aria-labelledby\x3d"cke_{name}_arialbl"':" ")+"\x3e"+(b.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'),c=CKEDITOR.document.getBody().append(CKEDITOR.dom.element.createFromHtml(m.output({content:k, +id:b.id,langDir:b.lang.dir,langCode:b.langCode,name:b.name,style:"display:none;z-index:"+(a.baseFloatZIndex-1),topId:b.ui.spaceId("top"),voiceLabel:b.title}))),d=CKEDITOR.tools.eventsBuffer(500,l),g=CKEDITOR.tools.eventsBuffer(100,l);c.unselectable();c.on("mousedown",function(a){a=a.data;a.getTarget().hasAscendant("a",1)||a.preventDefault()});b.on("focus",function(a){l(a);b.on("change",d.input);h.on("scroll",g.input);h.on("resize",g.input)});b.on("blur",function(){c.hide();b.removeListener("change", d.input);h.removeListener("scroll",g.input);h.removeListener("resize",g.input)});b.on("destroy",function(){h.removeListener("scroll",g.input);h.removeListener("resize",g.input);c.clearCustomData();c.remove()});b.focusManager.hasFocus&&c.show();b.focusManager.add(c,1)}}var h=CKEDITOR.document.getWindow(),f=CKEDITOR.tools.cssLength;CKEDITOR.plugins.add("floatingspace",{init:function(e){e.on("loaded",function(){b(this)},null,null,20)}})}(),CKEDITOR.plugins.add("listblock",{requires:"panel",onLoad:function(){var b= CKEDITOR.addTemplate("panel-list",'\x3cul role\x3d"presentation" class\x3d"cke_panel_list"\x3e{items}\x3c/ul\x3e'),h=CKEDITOR.addTemplate("panel-list-item",'\x3cli id\x3d"{id}" class\x3d"cke_panel_listItem" role\x3dpresentation\x3e\x3ca id\x3d"{id}_option" _cke_focus\x3d1 hidefocus\x3dtrue title\x3d"{title}" draggable\x3d"false" ondragstart\x3d"return false;" href\x3d"javascript:void(\'{val}\')" onclick\x3d"{onclick}CKEDITOR.tools.callFunction({clickFn},\'{val}\'); return false;" role\x3d"option"\x3e{text}\x3c/a\x3e\x3c/li\x3e'), f=CKEDITOR.addTemplate("panel-list-group",'\x3ch1 id\x3d"{id}" draggable\x3d"false" ondragstart\x3d"return false;" class\x3d"cke_panel_grouptitle" role\x3d"presentation" \x3e{label}\x3c/h1\x3e'),e=/\'/g;CKEDITOR.ui.panel.prototype.addListBlock=function(a,b){return this.addBlock(a,new CKEDITOR.ui.listBlock(this.getHolderElement(),b))};CKEDITOR.ui.listBlock=CKEDITOR.tools.createClass({base:CKEDITOR.ui.panel.block,$:function(a,b){b=b||{};var e=b.attributes||(b.attributes={});(this.multiSelect=!!b.multiSelect)&& (e["aria-multiselectable"]=!0);!e.role&&(e.role="listbox");this.base.apply(this,arguments);this.element.setAttribute("role",e.role);e=this.keys;e[40]="next";e[9]="next";e[38]="prev";e[CKEDITOR.SHIFT+9]="prev";e[32]=CKEDITOR.env.ie?"mouseup":"click";CKEDITOR.env.ie&&(e[13]="mouseup");this._.pendingHtml=[];this._.pendingList=[];this._.items={};this._.groups={}},_:{close:function(){if(this._.started){var a=b.output({items:this._.pendingList.join("")});this._.pendingList=[];this._.pendingHtml.push(a); -delete this._.started}},getClick:function(){this._.click||(this._.click=CKEDITOR.tools.addFunction(function(a){var b=this.toggle(a);if(this.onClick)this.onClick(a,b)},this));return this._.click}},proto:{add:function(a,b,f){var l=CKEDITOR.tools.getNextId();this._.started||(this._.started=1,this._.size=this._.size||0);this._.items[a]=l;var c;c=CKEDITOR.tools.htmlEncodeAttr(a).replace(e,"\\'");a={id:l,val:c,onclick:CKEDITOR.env.ie?'return false;" onmouseup\x3d"CKEDITOR.tools.getMouseButton(event)\x3d\x3d\x3dCKEDITOR.MOUSE_BUTTON_LEFT\x26\x26': +delete this._.started}},getClick:function(){this._.click||(this._.click=CKEDITOR.tools.addFunction(function(a){var b=this.toggle(a);if(this.onClick)this.onClick(a,b)},this));return this._.click}},proto:{add:function(a,b,f){var m=CKEDITOR.tools.getNextId();this._.started||(this._.started=1,this._.size=this._.size||0);this._.items[a]=m;var c;c=CKEDITOR.tools.htmlEncodeAttr(a).replace(e,"\\'");a={id:m,val:c,onclick:CKEDITOR.env.ie?'return false;" onmouseup\x3d"CKEDITOR.tools.getMouseButton(event)\x3d\x3d\x3dCKEDITOR.MOUSE_BUTTON_LEFT\x26\x26': "",clickFn:this._.getClick(),title:CKEDITOR.tools.htmlEncodeAttr(f||a),text:b||a};this._.pendingList.push(h.output(a))},startGroup:function(a){this._.close();var b=CKEDITOR.tools.getNextId();this._.groups[a]=b;this._.pendingHtml.push(f.output({id:b,label:a}))},commit:function(){this._.close();this.element.appendHtml(this._.pendingHtml.join(""));delete this._.size;this._.pendingHtml=[]},toggle:function(a){var b=this.isMarked(a);b?this.unmark(a):this.mark(a);return!b},hideGroup:function(a){var b=(a= this.element.getDocument().getById(this._.groups[a]))&&a.getNext();a&&(a.setStyle("display","none"),b&&"ul"==b.getName()&&b.setStyle("display","none"))},hideItem:function(a){this.element.getDocument().getById(this._.items[a]).setStyle("display","none")},showAll:function(){var a=this._.items,b=this._.groups,e=this.element.getDocument(),f;for(f in a)e.getById(a[f]).setStyle("display","");for(var c in b)a=e.getById(b[c]),f=a.getNext(),a.setStyle("display",""),f&&"ul"==f.getName()&&f.setStyle("display", "")},mark:function(a){this.multiSelect||this.unmarkAll();a=this._.items[a];var b=this.element.getDocument().getById(a);b.addClass("cke_selected");this.element.getDocument().getById(a+"_option").setAttribute("aria-selected",!0);this.onMark&&this.onMark(b)},markFirstDisplayed:function(){var a=this;this._.markFirstDisplayed(function(){a.multiSelect||a.unmarkAll()})},unmark:function(a){var b=this.element.getDocument();a=this._.items[a];var e=b.getById(a);e.removeClass("cke_selected");b.getById(a+"_option").removeAttribute("aria-selected"); @@ -854,15 +863,15 @@ b.getItem(++f);){if(a.equals(e)){this._.focusIndex=f;break}}else this.element.fo (CKEDITOR.env.gecko&&!CKEDITOR.env.hc?"":" href\x3d\"javascript:void('{titleJs}')\"")+' hidefocus\x3d"true" role\x3d"button" aria-labelledby\x3d"{id}_label" aria-haspopup\x3d"listbox"',h="";CKEDITOR.env.gecko&&CKEDITOR.env.mac&&(b+=' onkeypress\x3d"return false;"');CKEDITOR.env.gecko&&(b+=' onblur\x3d"this.style.cssText \x3d this.style.cssText;"');CKEDITOR.env.ie&&(h='return false;" onmouseup\x3d"CKEDITOR.tools.getMouseButton(event)\x3d\x3dCKEDITOR.MOUSE_BUTTON_LEFT\x26\x26');var b=b+(' onkeydown\x3d"return CKEDITOR.tools.callFunction({keydownFn},event,this);" onfocus\x3d"return CKEDITOR.tools.callFunction({focusFn},event);" onclick\x3d"'+ h+'CKEDITOR.tools.callFunction({clickFn},this);return false;"\x3e\x3cspan id\x3d"{id}_text" class\x3d"cke_combo_text cke_combo_inlinelabel"\x3e{label}\x3c/span\x3e\x3cspan class\x3d"cke_combo_open"\x3e\x3cspan class\x3d"cke_combo_arrow"\x3e'+(CKEDITOR.env.hc?"\x26#9660;":CKEDITOR.env.air?"\x26nbsp;":"")+"\x3c/span\x3e\x3c/span\x3e\x3c/a\x3e\x3c/span\x3e"),f=CKEDITOR.addTemplate("combo",b);CKEDITOR.UI_RICHCOMBO="richcombo";CKEDITOR.ui.richCombo=CKEDITOR.tools.createClass({$:function(b){CKEDITOR.tools.extend(this, b,{canGroup:!1,title:b.label,modes:{wysiwyg:1},editorFocus:1});b=this.panel||{};delete this.panel;this.id=CKEDITOR.tools.getNextNumber();this.document=b.parent&&b.parent.getDocument()||CKEDITOR.document;b.className="cke_combopanel";b.block={multiSelect:b.multiSelect,attributes:b.attributes};b.toolbarRelated=!0;this._={panelDefinition:b,items:{},listeners:[]}},proto:{renderHtml:function(b){var a=[];this.render(b,a);return a.join("")},render:function(b,a){function h(){if(this.getState()!=CKEDITOR.TRISTATE_ON){var a= -this.modes[b.mode]?CKEDITOR.TRISTATE_OFF:CKEDITOR.TRISTATE_DISABLED;b.readOnly&&!this.readOnly&&(a=CKEDITOR.TRISTATE_DISABLED);this.setState(a);this.setValue("");a!=CKEDITOR.TRISTATE_DISABLED&&this.refresh&&this.refresh()}}var k=CKEDITOR.env,l,c,d="cke_"+this.id,g=CKEDITOR.tools.addFunction(function(a){c&&(b.unlockSelection(1),c=0);l.execute(a)},this),n=this;l={id:d,combo:this,focus:function(){CKEDITOR.document.getById(d).getChild(1).focus()},execute:function(a){var c=n._;if(c.state!=CKEDITOR.TRISTATE_DISABLED)if(n.createPanel(b), +this.modes[b.mode]?CKEDITOR.TRISTATE_OFF:CKEDITOR.TRISTATE_DISABLED;b.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,c,d="cke_"+this.id,g=CKEDITOR.tools.addFunction(function(a){c&&(b.unlockSelection(1),c=0);m.execute(a)},this),n=this;m={id:d,combo:this,focus:function(){CKEDITOR.document.getById(d).getChild(1).focus()},execute:function(a){var c=n._;if(c.state!=CKEDITOR.TRISTATE_DISABLED)if(n.createPanel(b), c.on)c.panel.hide();else{n.commit();var d=n.getValue();d?c.list.mark(d):c.list.unmarkAll();c.panel.showBlock(n.id,new CKEDITOR.dom.element(a),4)}},clickFn:g};this._.listeners.push(b.on("activeFilterChange",h,this));this._.listeners.push(b.on("mode",h,this));this._.listeners.push(b.on("selectionChange",h,this));!this.readOnly&&this._.listeners.push(b.on("readOnly",h,this));var y=CKEDITOR.tools.addFunction(function(a,b){a=new CKEDITOR.dom.event(a);var c=a.getKeystroke();switch(c){case 13:case 32:case 40:CKEDITOR.tools.callFunction(g, -b);break;default:l.onkey(l,c)}a.preventDefault()}),w=CKEDITOR.tools.addFunction(function(){l.onfocus&&l.onfocus()});c=0;l.keyDownFn=y;k={id:d,name:this.name||this.command,label:this.label,title:this.title,cls:this.className||"",titleJs:k.gecko&&!k.hc?"":(this.title||"").replace("'",""),keydownFn:y,focusFn:w,clickFn:g};f.output(k,a);if(this.onRender)this.onRender();return l},createPanel:function(b){if(!this._.panel){var a=this._.panelDefinition,f=this._.panelDefinition.block,h=a.parent||CKEDITOR.document.getBody(), -l="cke_combopanel__"+this.name,c=new CKEDITOR.ui.floatPanel(b,h,a),a=c.addListBlock(this.id,f),d=this;c.onShow=function(){this.element.addClass(l);d.setState(CKEDITOR.TRISTATE_ON);d._.on=1;d.editorFocus&&!b.focusManager.hasFocus&&b.focus();if(d.onOpen)d.onOpen()};c.onHide=function(a){this.element.removeClass(l);d.setState(d.modes&&d.modes[b.mode]?CKEDITOR.TRISTATE_OFF:CKEDITOR.TRISTATE_DISABLED);d._.on=0;if(!a&&d.onClose)d.onClose()};c.onEscape=function(){c.hide(1)};a.onClick=function(a,b){d.onClick&& +b);break;default:m.onkey(m,c)}a.preventDefault()}),v=CKEDITOR.tools.addFunction(function(){m.onfocus&&m.onfocus()});c=0;m.keyDownFn=y;l={id:d,name:this.name||this.command,label:this.label,title:this.title,cls:this.className||"",titleJs:l.gecko&&!l.hc?"":(this.title||"").replace("'",""),keydownFn:y,focusFn:v,clickFn:g};f.output(l,a);if(this.onRender)this.onRender();return m},createPanel:function(b){if(!this._.panel){var a=this._.panelDefinition,f=this._.panelDefinition.block,h=a.parent||CKEDITOR.document.getBody(), +m="cke_combopanel__"+this.name,c=new CKEDITOR.ui.floatPanel(b,h,a),a=c.addListBlock(this.id,f),d=this;c.onShow=function(){this.element.addClass(m);d.setState(CKEDITOR.TRISTATE_ON);d._.on=1;d.editorFocus&&!b.focusManager.hasFocus&&b.focus();if(d.onOpen)d.onOpen()};c.onHide=function(a){this.element.removeClass(m);d.setState(d.modes&&d.modes[b.mode]?CKEDITOR.TRISTATE_OFF:CKEDITOR.TRISTATE_DISABLED);d._.on=0;if(!a&&d.onClose)d.onClose()};c.onEscape=function(){c.hide(1)};a.onClick=function(a,b){d.onClick&& d.onClick.call(d,a,b);c.hide()};this._.panel=c;this._.list=a;c.getBlock(this.id).onHide=function(){d._.on=0;d.setState(CKEDITOR.TRISTATE_OFF)};this.init&&this.init()}},setValue:function(b,a){this._.value=b;var f=this.document.getById("cke_"+this.id+"_text");f&&(b||a?f.removeClass("cke_combo_inlinelabel"):(a=this.label,f.addClass("cke_combo_inlinelabel")),f.setText("undefined"!=typeof a?a:b));var f="undefined"!=typeof a?a:b,h=this.label,f=f===h?f:f+", "+h;(h=this.document.getById("cke_"+this.id+"_label"))&& h.setText(f)},getValue:function(){return this._.value||""},unmarkAll:function(){this._.list.unmarkAll()},mark:function(b){this._.list.mark(b)},hideItem:function(b){this._.list.hideItem(b)},hideGroup:function(b){this._.list.hideGroup(b)},showAll:function(){this._.list.showAll()},add:function(b,a,f){this._.items[b]=f||b;this._.list.add(b,a,f)},startGroup:function(b){this._.list.startGroup(b)},commit:function(){this._.committed||(this._.list.commit(),this._.committed=1,CKEDITOR.ui.fire("ready",this)); this._.committed=1},setState:function(b){if(this._.state!=b){var a=this.document.getById("cke_"+this.id),f=a.getElementsByTag("a").getItem(0);a.setState(b,"cke_combo");b==CKEDITOR.TRISTATE_DISABLED?a.setAttribute("aria-disabled",!0):a.removeAttribute("aria-disabled");f&&f.setAttribute("aria-expanded",b==CKEDITOR.TRISTATE_ON);this._.state=b}},getState:function(){return this._.state},enable:function(){this._.state==CKEDITOR.TRISTATE_DISABLED&&this.setState(this._.lastState)},disable:function(){this._.state!= CKEDITOR.TRISTATE_DISABLED&&(this._.lastState=this._.state,this.setState(CKEDITOR.TRISTATE_DISABLED))},destroy:function(){CKEDITOR.tools.array.forEach(this._.listeners,function(b){b.removeListener()});this._.listeners=[]},select:function(b){if(!CKEDITOR.tools.isEmpty(this._.items))for(var a in this._.items)if(b({value:a,text:this._.items[a]})){this.setValue(a);break}}},statics:{handler:{create:function(b){return new CKEDITOR.ui.richCombo(b)}}}});CKEDITOR.ui.prototype.addRichCombo=function(b,a){this.add(b, -CKEDITOR.UI_RICHCOMBO,a)}}(),CKEDITOR.plugins.add("format",{requires:"richcombo",init:function(b){if(!b.blockless){for(var h=b.config,f=b.lang.format,e=h.format_tags.split(";"),a={},m=0,k=[],l=0;l=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);e.attachListener(b,"resize",f);e.attachListener(b,"mode",k);b.on("destroy",k);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({}, -m,this.lineStyle,!0)),tipLeftStyle:CKEDITOR.tools.writeCssText(CKEDITOR.tools.extend({},a,{left:"0px","border-left-color":"red","border-width":"6px 0 6px 6px"},this.tipCss,this.tipLeftStyle,!0)),tipRightStyle:CKEDITOR.tools.writeCssText(CKEDITOR.tools.extend({},a,{right:"0px","border-right-color":"red","border-width":"6px 6px 6px 0"},this.tipCss,this.tipRightStyle,!0))})}function e(a){var b;if(b=a&&a.type==CKEDITOR.NODE_ELEMENT)b=!(k[a.getComputedStyle("float")]||k[a.getAttribute("align")]);return b&& -!l[a.getComputedStyle("position")]}CKEDITOR.plugins.add("lineutils");CKEDITOR.LINEUTILS_BEFORE=1;CKEDITOR.LINEUTILS_AFTER=2;CKEDITOR.LINEUTILS_INSIDE=4;b.prototype={start:function(a){var b=this,e=this.editor,f=this.doc,h,k,l,m,r=CKEDITOR.tools.eventsBuffer(50,function(){e.readOnly||"wysiwyg"!=e.mode||(b.relations={},(k=f.$.elementFromPoint(l,m))&&k.nodeType&&(h=new CKEDITOR.dom.element(k),b.traverseSearch(h),isNaN(l+m)||b.pixelSearch(h,l,m),a&&a(b.relations,l,m)))});this.listener=this.editable.attachListener(this.target, +this.queryViewport();var f=CKEDITOR.tools.bind(this.queryViewport,this),h=CKEDITOR.tools.bind(this.hideVisible,this),l=CKEDITOR.tools.bind(this.removeAll,this);e.attachListener(this.winTop,"resize",f);e.attachListener(this.winTop,"scroll",f);e.attachListener(this.winTop,"resize",h);e.attachListener(this.win,"scroll",h);e.attachListener(this.inline?e: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);e.attachListener(b,"resize",f);e.attachListener(b,"mode",l);b.on("destroy",l);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({}, +k,this.lineStyle,!0)),tipLeftStyle:CKEDITOR.tools.writeCssText(CKEDITOR.tools.extend({},a,{left:"0px","border-left-color":"red","border-width":"6px 0 6px 6px"},this.tipCss,this.tipLeftStyle,!0)),tipRightStyle:CKEDITOR.tools.writeCssText(CKEDITOR.tools.extend({},a,{right:"0px","border-right-color":"red","border-width":"6px 6px 6px 0"},this.tipCss,this.tipRightStyle,!0))})}function e(a){var b;if(b=a&&a.type==CKEDITOR.NODE_ELEMENT)b=!(l[a.getComputedStyle("float")]||l[a.getAttribute("align")]);return b&& +!m[a.getComputedStyle("position")]}CKEDITOR.plugins.add("lineutils");CKEDITOR.LINEUTILS_BEFORE=1;CKEDITOR.LINEUTILS_AFTER=2;CKEDITOR.LINEUTILS_INSIDE=4;b.prototype={start:function(a){var b=this,e=this.editor,f=this.doc,h,k,l,m,r=CKEDITOR.tools.eventsBuffer(50,function(){e.readOnly||"wysiwyg"!=e.mode||(b.relations={},(k=f.$.elementFromPoint(l,m))&&k.nodeType&&(h=new CKEDITOR.dom.element(k),b.traverseSearch(h),isNaN(l+m)||b.pixelSearch(h,l,m),a&&a(b.relations,l,m)))});this.listener=this.editable.attachListener(this.target, "mousemove",function(a){l=a.data.$.clientX;m=a.data.$.clientY;r.input()});this.editable.attachListener(this.inline?this.editable:this.frame,"mouseout",function(){r.reset()})},stop:function(){this.listener&&this.listener.removeListener()},getRange:function(){var a={};a[CKEDITOR.LINEUTILS_BEFORE]=CKEDITOR.POSITION_BEFORE_START;a[CKEDITOR.LINEUTILS_AFTER]=CKEDITOR.POSITION_AFTER_END;a[CKEDITOR.LINEUTILS_INSIDE]=CKEDITOR.POSITION_AFTER_START;return function(b){var e=this.editor.createRange();e.moveToPosition(this.relations[b.uid].element, a[b.type]);return e}}(),store:function(){function a(b,c,e){var f=b.getUniqueId();f in e?e[f].type|=c:e[f]={element:b,type:c}}return function(b,g){var f;g&CKEDITOR.LINEUTILS_AFTER&&e(f=b.getNext())&&f.isVisible()&&(a(f,CKEDITOR.LINEUTILS_BEFORE,this.relations),g^=CKEDITOR.LINEUTILS_AFTER);g&CKEDITOR.LINEUTILS_INSIDE&&e(f=b.getFirst())&&f.isVisible()&&(a(f,CKEDITOR.LINEUTILS_BEFORE,this.relations),g^=CKEDITOR.LINEUTILS_INSIDE);a(b,g,this.relations)}}(),traverseSearch:function(a){var b,g,f;do if(f=a.$["data-cke-expando"], !(f&&f in this.relations)){if(a.equals(this.editable))break;if(e(a))for(b in this.lookups)(g=this.lookups[b](a))&&this.store(a,g)}while((!a||a.type!=CKEDITOR.NODE_ELEMENT||"true"!=a.getAttribute("contenteditable"))&&(a=a.getParent()))},pixelSearch:function(){function a(c,f,h,k,l){for(var m=0,r;l(h);){h+=k;if(25==++m)break;if(r=this.doc.$.elementFromPoint(f,h))if(r==c)m=0;else if(b(c,r)&&(m=0,e(r=new CKEDITOR.dom.element(r))))return r}}var b=CKEDITOR.env.ie||CKEDITOR.env.webkit?function(a,b){return a.contains(b)}: @@ -884,230 +893,233 @@ function(a,b){return!!(a.compareDocumentPosition(b)&16)};return function(b,d,f){ greedySearch:function(){this.relations={};for(var a=this.editable.getElementsByTag("*"),b=0,g,f,h;g=a.getItem(b++);)if(!g.equals(this.editable)&&g.type==CKEDITOR.NODE_ELEMENT&&(g.hasAttribute("contenteditable")||!g.isReadOnly())&&e(g)&&g.isVisible())for(h in this.lookups)(f=this.lookups[h](g))&&this.store(g,f);return this.relations}};h.prototype={locate:function(){function a(b,c){var f=b.element[c===CKEDITOR.LINEUTILS_BEFORE?"getPrevious":"getNext"]();return f&&e(f)?(b.siblingRect=f.getClientRect(), c==CKEDITOR.LINEUTILS_BEFORE?(b.siblingRect.bottom+b.elementRect.top)/2:(b.elementRect.bottom+b.siblingRect.top)/2):c==CKEDITOR.LINEUTILS_BEFORE?b.elementRect.top:b.elementRect.bottom}return function(b){var e;this.locations={};for(var f in b)e=b[f],e.elementRect=e.element.getClientRect(),e.type&CKEDITOR.LINEUTILS_BEFORE&&this.store(f,CKEDITOR.LINEUTILS_BEFORE,a(e,CKEDITOR.LINEUTILS_BEFORE)),e.type&CKEDITOR.LINEUTILS_AFTER&&this.store(f,CKEDITOR.LINEUTILS_AFTER,a(e,CKEDITOR.LINEUTILS_AFTER)),e.type& CKEDITOR.LINEUTILS_INSIDE&&this.store(f,CKEDITOR.LINEUTILS_INSIDE,(e.elementRect.top+e.elementRect.bottom)/2);return this.locations}}(),sort:function(){var a,b,e,f;return function(h,k){a=this.locations;b=[];for(var l in a)for(var m in a[l])if(e=Math.abs(h-a[l][m]),b.length){for(f=0;fthis.rect.bottom)return!1;this.inline? h.left=e.elementRect.left-this.rect.relativeX:(0[^<]*[^<]*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 m(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 k(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();de});0>g&&(g=a._.upcasts.length);a._.upcasts.splice(g,0,[CKEDITOR.tools.bind(b,c),c.name,e])}var e=b.upcast,g=b.upcastPriority||10;e&&("string"==typeof e?d(c, +b,g):d(e,b,g))}function k(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 l(a){a=a.data;if("wysiwyg"==this.editor.mode){var b=this.editor.editable(),c=this.instances,d,e,g,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(e=k.count();d -a.selected.length||O(c,"cut"===d.name)}var c=a.editor;c.on("contentDom",function(){var a=c.editable();a.attachListener(a,"copy",b);a.attachListener(a,"cut",b)})}function D(a){function b(){var a=e.getSelection();if(a&&(a=a.getRanges()[0])&&!a.collapsed){var d=c(a.startContainer),f=c(a.endContainer);!d&&f?(a.setEndBefore(f.wrapper),a.select()):d&&!f&&(a.setStartAfter(d.wrapper),a.select())}}function c(a){return a?a.type==CKEDITOR.NODE_TEXT?c(a.getParent()):e.widgets.getByElement(a):null}function d(){a.fire("checkSelection")} +a.selected.length||I(c,"cut"===d.name)}var c=a.editor;c.on("contentDom",function(){var a=c.editable();a.attachListener(a,"copy",b);a.attachListener(a,"cut",b)})}function C(a){function b(){var a=e.getSelection();if(a&&(a=a.getRanges()[0])&&!a.collapsed){var d=c(a.startContainer),g=c(a.endContainer);!d&&g?(a.setEndBefore(g.wrapper),a.select()):d&&!g&&(a.setStartAfter(d.wrapper),a.select())}}function c(a){return a?a.type==CKEDITOR.NODE_TEXT?c(a.getParent()):e.widgets.getByElement(a):null}function d(){a.fire("checkSelection")} var e=a.editor;e.on("selectionCheck",d);e.on("contentDom",function(){e.editable().attachListener(e,"key",function(){setTimeout(d,10)})});if(!CKEDITOR.env.ie)a.on("checkSelection",b);a.on("checkSelection",a.checkSelection,a);e.on("selectionChange",function(b){var c=(b=h.getNestedEditable(e.editable(),b.data.selection.getStartElement()))&&a.getByElement(b),d=a.widgetHoldingFocusedEditable;d?d===c&&d.focusedEditable.equals(b)||(r(a,d,null),c&&b&&r(a,c,b)):c&&b&&r(a,c,b)});e.on("dataReady",function(){F(a).commit()}); -e.on("blur",function(){var b;(b=a.focused)&&m(a,b);(b=a.widgetHoldingFocusedEditable)&&r(a,b,null)})}function A(a){var b=a.editor,e={};b.on("toDataFormat",function(b){var f=CKEDITOR.tools.getNextNumber(),g=[];b.data.downcastingSessionId=f;e[f]=g;b.data.dataValue.forEach(function(b){var e=b.attributes,f;if("data-cke-widget-white-space"in e){f=c(b);var k=d(b);f.parent.attributes["data-cke-white-space-first"]&&(f.value=f.value.replace(/^ /g," "));k.parent.attributes["data-cke-white-space-last"]&& -(k.value=k.value.replace(/ $/g," "))}if("data-cke-widget-id"in e){if(e=a.instances[e["data-cke-widget-id"]])f=b.getFirst(h.isParserWidgetElement),g.push({wrapper:b,element:f,widget:e,editables:{}}),"1"!=f.attributes["data-cke-widget-keep-attr"]&&delete f.attributes["data-widget"]}else if("data-cke-widget-editable"in e)return 0CKEDITOR.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)&&m(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 K(a){a&&a.addFilterRule(function(a){return a.replace(/\s*cke_widget_selected/g,"").replace(/\s*cke_widget_focused/g,"")})}function L(a, -b,c){var d=0;b=I(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 C(a){a.cancel()}function O(a,b){var c=a.widgets.focused,d,e,f;ga.hasCopyBin(a)||(e=new ga(a,{beforeDestroy:function(){!b&&c&&c.focus();f&&a.getSelection().selectBookmarks(f);d&&CKEDITOR.plugins.widgetselection.addFillers(a.editable())},afterDestroy:function(){b&&!a.readOnly&&(c?a.widgets.del(c):a.extractSelectedHtml(),a.fire("saveSnapshot"))}}), -c||(d=CKEDITOR.env.webkit&&CKEDITOR.plugins.widgetselection.isWholeContentSelected(a.editable()),f=a.getSelection().createBookmarks(!0)),e.handle(H(a)))}function I(a){return(a=(a=a.getDefinition().attributes)&&a["class"])?a.split(/\s+/):null}function M(){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 Q(){CKEDITOR.env.gecko&&this.editor.unlockSelection();CKEDITOR.env.webkit||(this.editor.forceNextSelectionCheck(), -this.editor.selectionChange(1))}function H(a){var b=a.getSelectedHtml(!0);if(a.widgets.focused)return a.widgets.focused.getClipboardHtml();a.once("toDataFormat",function(a){a.data.widgetsCopy=!0},null,null,-1);return a.dataProcessor.toDataFormat(b)}function G(a,b){P(a);Y(a);T(a);X(a);S(a);aa(a);ba(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){O(a.editor,b==CKEDITOR.CTRL+88);return}if(b in V||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 P(a){(a.wrapper=a.element.getParent()).setAttribute("data-cke-widget-id",a.id)}function Y(a,b){a.partSelectors||(a.partSelectors= -a.parts);if(a.parts){var c={},d,e;for(e in a.partSelectors)b||!a.parts[e]||"string"==typeof a.parts[e]?(d=a.wrapper.findOne(a.partSelectors[e]),c[e]=d):c[e]=a.parts[e];a.parts=c}}function T(a){var b=a.editables,c,d;a.editables={};if(a.editables)for(c in b)d=b[c],a.initEditable(c,"string"==typeof d?{selector:d}:d)}function X(a){if(!0===a.mask)da(a);else if(a.mask){var b=new CKEDITOR.tools.buffers.throttle(250,J,a),c=CKEDITOR.env.gecko?300:0,d,e;a.on("focus",function(){b.input();d=a.editor.on("change", -b.input);e=a.on("blur",function(){d.removeListener();e.removeListener()})});a.editor.on("instanceReady",function(){setTimeout(function(){b.input()},c)});a.editor.on("mode",function(){setTimeout(function(){b.input()},c)});if(CKEDITOR.env.gecko){var f=a.element.find("img");CKEDITOR.tools.array.forEach(f.toArray(),function(a){a.on("load",function(){b.input()})})}for(var g in a.editables)a.editables[g].on("focus",function(){a.editor.on("change",b.input);e&&e.removeListener()}),a.editables[g].on("blur", -function(){a.editor.removeListener("change",b.input)});b.input()}}function da(a){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 J(){if(this.wrapper){this.maskPart=this.maskPart||this.mask;var a=this.parts[this.maskPart],b;if(a&&"string"!=typeof a){b=this.wrapper.findOne(".cke_widget_partial_mask");b||(b=new CKEDITOR.dom.element("img", -this.editor.document),b.setAttributes({src:CKEDITOR.tools.transparentImageData,"class":"cke_reset cke_widget_partial_mask"}),this.wrapper.append(b));this.mask=b;var c=b.$,d=a.$,e=!(c.offsetTop==d.offsetTop&&c.offsetLeft==d.offsetLeft);if(c.offsetWidth!=d.offsetWidth||c.offsetHeight!=d.offsetHeight||e)c=a.getParent(),d=CKEDITOR.plugins.widget.isDomWidget(c),b.setStyles({top:a.$.offsetTop+(d?0:c.$.offsetTop)+"px",left:a.$.offsetLeft+(d?0:c.$.offsetLeft)+"px",width:a.$.offsetWidth+"px",height:a.$.offsetHeight+ -"px"})}}}function S(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);display:none;"}),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",W,a),CKEDITOR.env.ie&&9>CKEDITOR.env.version))d.on("dragstart",function(a){a.data.preventDefault(!0)}); -a.dragHandlerContainer=c}}function W(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 n=c.greedySearch(),r=CKEDITOR.tools.eventsBuffer(50,function(){l=d.locate(n);k=d.sort(m,1);k.length&&(e.prepare(n,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 aa(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 ba(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 ca(a){a.element.data("cke-widget-data",encodeURIComponent(JSON.stringify(a.data)))} -function Z(){function a(){}function b(a,c,d){return d&&this.checkElement(a)?(a=d.widgets.getByElement(a,!0))&&a.checkStyleActive(this):!1}function c(a){function b(a,c,d){for(var e=a.length,f=0;fCKEDITOR.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 g=a.focused!==e,f,h;a.editor.fire("lockSnapshot");for(g&& +(f=a.focused)&&k(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());g&&e&&(h=a.editor.checkDirty(),a.focused=e,a.fire("widgetFocused",{widget:e}),e.setFocused(!0),!h&&a.editor.resetDirty());for(;f=c.pop();)b.push(f),f.setSelected(!0);a.editor.fire("unlockSnapshot")}}}function K(a){a&&a.addFilterRule(function(a){return a.replace(/\s*cke_widget_selected/g,"").replace(/\s*cke_widget_focused/g,"")})}function M(a, +b,c){var d=0;b=L(b);var e=a.data.classes||{},g;if(b){for(e=CKEDITOR.tools.clone(e);g=b.pop();)c?e[g]||(d=e[g]=1):e[g]&&(delete e[g],d=1);d&&a.setData("classes",e)}}function D(a){a.cancel()}function N(a,b){var c=function(a){return a==CKEDITOR.ENTER_BR?"br":a==CKEDITOR.ENTER_DIV?"div":"p"}(a.editor.config.enterMode),d=new CKEDITOR.dom.element(c);"br"!==c&&d.appendBogus();"after"===b?d.insertAfter(a.wrapper):d.insertBefore(a.wrapper);(function(b){var c=a.editor.createRange();c.setStart(b,0);a.editor.getSelection().selectRanges([c])})(d)} +function I(a,b){var c=a.widgets.focused,d,e,g;P.hasCopyBin(a)||(e=new P(a,{beforeDestroy:function(){!b&&c&&c.focus();g&&a.getSelection().selectBookmarks(g);d&&CKEDITOR.plugins.widgetselection.addFillers(a.editable())},afterDestroy:function(){b&&!a.readOnly&&(c?a.widgets.del(c):a.extractSelectedHtml(),a.fire("saveSnapshot"))}}),c||(d=CKEDITOR.env.webkit&&CKEDITOR.plugins.widgetselection.isWholeContentSelected(a.editable()),g=a.getSelection().createBookmarks(!0)),e.handle(G(a)))}function L(a){return(a= +(a=a.getDefinition().attributes)&&a["class"])?a.split(/\s+/):null}function R(){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 H(){CKEDITOR.env.gecko&&this.editor.unlockSelection();CKEDITOR.env.webkit||(this.editor.forceNextSelectionCheck(),this.editor.selectionChange(1))}function G(a){var b=a.getSelectedHtml(!0);if(a.widgets.focused)return a.widgets.focused.getClipboardHtml();a.once("toDataFormat", +function(a){a.data.widgetsCopy=!0},null,null,-1);return a.dataProcessor.toDataFormat(b)}function O(a,b){var c=a.editor.config.widget_keystrokeInsertLineBefore,d=a.editor.config.widget_keystrokeInsertLineAfter;Y(a);S(a);X(a);ca(a);W(a);ba(a);da(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(b==c)N(a,"before"),a.editor.fire("saveSnapshot");else if(b==d)N(a,"after"),a.editor.fire("saveSnapshot");else if(13==b)a.edit();else{if(b==CKEDITOR.CTRL+67||b==CKEDITOR.CTRL+88){I(a.editor,b==CKEDITOR.CTRL+88);return}if(b in ha||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 Y(a){(a.wrapper=a.element.getParent()).setAttribute("data-cke-widget-id", +a.id)}function S(a,b){a.partSelectors||(a.partSelectors=a.parts);if(a.parts){var c={},d,e;for(e in a.partSelectors)b||!a.parts[e]||"string"==typeof a.parts[e]?(d=a.wrapper.findOne(a.partSelectors[e]),c[e]=d):c[e]=a.parts[e];a.parts=c}}function X(a){var b=a.editables,c,d;a.editables={};if(a.editables)for(c in b)d=b[c],a.initEditable(c,"string"==typeof d?{selector:d}:d)}function ca(a){if(!0===a.mask)J(a);else if(a.mask){var b=new CKEDITOR.tools.buffers.throttle(250,T,a),c=CKEDITOR.env.gecko?300:0,d, +e;a.on("focus",function(){b.input();d=a.editor.on("change",b.input);e=a.on("blur",function(){d.removeListener();e.removeListener()})});a.editor.on("instanceReady",function(){setTimeout(function(){b.input()},c)});a.editor.on("mode",function(){setTimeout(function(){b.input()},c)});if(CKEDITOR.env.gecko){var g=a.element.find("img");CKEDITOR.tools.array.forEach(g.toArray(),function(a){a.on("load",function(){b.input()})})}for(var f in a.editables)a.editables[f].on("focus",function(){a.editor.on("change", +b.input);e&&e.removeListener()}),a.editables[f].on("blur",function(){a.editor.removeListener("change",b.input)});b.input()}}function J(a){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 T(){if(this.wrapper){this.maskPart=this.maskPart||this.mask;var a=this.parts[this.maskPart],b;if(a&&"string"!=typeof a){b=this.wrapper.findOne(".cke_widget_partial_mask"); +b||(b=new CKEDITOR.dom.element("img",this.editor.document),b.setAttributes({src:CKEDITOR.tools.transparentImageData,"class":"cke_reset cke_widget_partial_mask"}),this.wrapper.append(b));this.mask=b;var c=b.$,d=a.$,e=!(c.offsetTop==d.offsetTop&&c.offsetLeft==d.offsetLeft);if(c.offsetWidth!=d.offsetWidth||c.offsetHeight!=d.offsetHeight||e)c=a.getParent(),d=CKEDITOR.plugins.widget.isDomWidget(c),b.setStyles({top:a.$.offsetTop+(d?0:c.$.offsetTop)+"px",left:a.$.offsetLeft+(d?0:c.$.offsetLeft)+"px",width:a.$.offsetWidth+ +"px",height:a.$.offsetHeight+"px"})}}}function W(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);display:none;"}),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",aa,a),CKEDITOR.env.ie&&9>CKEDITOR.env.version))d.on("dragstart", +function(a){a.data.preventDefault(!0)});a.dragHandlerContainer=c}}function aa(a){function b(){var c;for(r.reset();c=h.pop();)c.removeListener();var d=k;c=a.sender;var e=this.repository.finder,g=this.repository.liner,f=this.editor,l=this.editor.editable();CKEDITOR.tools.isEmpty(g.visible)||(d=e.getRange(d[0]),this.focus(),f.fire("drop",{dropRange:d,target:d.startContainer}));l.removeClass("cke_widget_dragging");g.hideVisible();f.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,g=this.editor,f=g.editable(),h=[],k=[],l,m;this.repository._.draggedWidget=this;var n=c.greedySearch(),r=CKEDITOR.tools.eventsBuffer(50,function(){l=d.locate(n);k=d.sort(m,1);k.length&&(e.prepare(n,l),e.placeLine(k[0]),e.cleanup())});f.addClass("cke_widget_dragging");h.push(f.on("mousemove",function(a){m=a.data.$.clientY;r.input()}));g.fire("dragstart",{target:a.sender});h.push(g.document.once("mouseup",b,this));f.isInline()|| +h.push(CKEDITOR.document.once("mouseup",b,this))}}function ba(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 da(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 Z(a){a.element.data("cke-widget-data", +encodeURIComponent(JSON.stringify(a.data)))}function U(){function a(){}function b(a,c,d){return d&&this.checkElement(a)?(a=d.widgets.getByElement(a,!0))&&a.checkStyleActive(this):!1}function c(a){function b(a,c,d){for(var e=a.length,g=0;g)?(?:<(?:div|span)(?: style="[^"]+")?>)?]*data-cke-copybin-start="1"[^>]*>.?<\/span>([\s\S]+)]*data-cke-copybin-end="1"[^>]*>.?<\/span>(?:<\/(?:div|span)>)?(?:<\/(?:div|span)>)?$/i, -V={37:1,38:1,39:1,40:1,8:1,46:1};V[CKEDITOR.SHIFT+121]=1;var ga=CKEDITOR.tools.createClass({$:function(a,b){this._.createCopyBin(a,b);this._.createListeners(b)},_:{createCopyBin:function(a){var b=a.document,c=CKEDITOR.env.edge&&16<=CKEDITOR.env.version,d=!a.blockless&&!CKEDITOR.env.ie||c?"div":"span",c=b.createElement(d),b=b.createElement(d);b.setAttributes({id:"cke_copybin","data-cke-temp":"1"});c.setStyles({position:"absolute",width:"1px",height:"1px",overflow:"hidden"});c.setStyle("ltr"==a.config.contentsLangDirection? -"left":"right","-5000px");this.editor=a;this.copyBin=c;this.container=b},createListeners:function(a){a&&(a.beforeDestroy&&(this.beforeDestroy=a.beforeDestroy),a.afterDestroy&&(this.afterDestroy=a.afterDestroy))}},proto:{handle:function(a){var b=this.copyBin,c=this.editor,d=this.container,e=CKEDITOR.env.ie&&9>CKEDITOR.env.version,f=c.document.getDocumentElement().$,g=c.createRange(),h=this,k=CKEDITOR.env.mac&&CKEDITOR.env.webkit,l=k?100:0,m=window.requestAnimationFrame&&!k?requestAnimationFrame:setTimeout, -n,r,q;b.setHtml('\x3cspan data-cke-copybin-start\x3d"1"\x3e​\x3c/span\x3e'+a+'\x3cspan data-cke-copybin-end\x3d"1"\x3e​\x3c/span\x3e');c.fire("lockSnapshot");d.append(b);c.editable().append(d);n=c.on("selectionChange",C,null,null,0);r=c.widgets.on("checkSelection",C,null,null,0);e&&(q=f.scrollTop);g.selectNodeContents(b);g.select();e&&(f.scrollTop=q);return new CKEDITOR.tools.promise(function(a){m(function(){h.beforeDestroy&&h.beforeDestroy();d.remove();n.removeListener();r.removeListener();c.fire("unlockSnapshot"); -h.afterDestroy&&h.afterDestroy();a()},l)})}},statics:{hasCopyBin:function(a){return!!ga.getCopyBin(a)},getCopyBin:function(a){return a.document.getById("cke_copybin")}}});CKEDITOR.plugins.widget=h;h.repository=b;h.nestedEditable=f}(),"use strict",function(){function b(a){function b(){this.deflated||(a.widgets.focused==this.widget&&(this.focused=!0),a.widgets.destroy(this.widget),this.deflated=!0)}function c(){var b=a.editable(),d=a.document;if(this.deflated)this.widget=a.widgets.initOn(this.element, -"image",this.widget.data),this.widget.inline&&!(new CKEDITOR.dom.elementPath(this.widget.wrapper,b)).block&&(b=d.createElement(a.activeEnterMode==CKEDITOR.ENTER_P?"p":"div"),b.replace(this.widget.wrapper),this.widget.wrapper.move(b)),this.focused&&(this.widget.focus(),delete this.focused),delete this.deflated;else{var f=this.widget,b=e,d=f.wrapper,g=f.data.align,f=f.data.hasCaption;if(b){for(var h=3;h--;)d.removeClass(b[h]);"center"==g?f&&d.addClass(b[1]):"none"!=g&&d.addClass(b[w[g]])}else"center"== -g?(f?d.setStyle("text-align","center"):d.removeStyle("text-align"),d.removeStyle("float")):("none"==g?d.removeStyle("float"):d.setStyle("float",g),d.removeStyle("text-align"))}}var e=a.config.image2_alignClasses,k=a.config.image2_captionedClass;return{allowedContent:d(a),requiredContent:"img[src,alt]",features:g(a),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 d=this.features;this.data.hasCaption&&!a.filter.checkFeature(d.caption)&&(this.data.hasCaption=!1);"none"==this.data.align||a.filter.checkFeature(d.align)||(this.data.align="none");this.shiftState({widget:this,element:this.element,oldData:this.oldData,newData:this.data,deflate:b,inflate:c});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 e in this.data.classes)this.parts.image.removeClass(e);if(a.filter.checkFeature(d.dimension)){d=this.data;d={width:d.width,height:d.height};e=this.parts.image;for(var f in d)d[f]?e.setAttribute(f,d[f]):e.removeAttribute(f)}this.oldData=CKEDITOR.tools.extend({},this.data)},init:function(){var b=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?b.checkHasNaturalRatio(c):!0},f=c.getAscendant("a");f&&this.wrapper.contains(f)&&(this.parts.link=f);d.align||(c=d.hasCaption?this.element:c,e?(c.hasClass(e[0])?d.align="left":c.hasClass(e[2])&&(d.align="right"),d.align?c.removeClass(e[w[d.align]]):d.align="none"):(d.align=c.getStyle("float")||"none",c.removeStyle("float"))); -a.plugins.link&&this.parts.link&&(d.link=b.getLinkAttributesParser()(a,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);a.filter.checkFeature(this.features.dimension)&&!0!==a.config.image2_disableResizer&&m(this);this.shiftState=b.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})},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,e).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(a),downcast:f(a),getLabel:function(){return this.editor.lang.widget.label.replace(/%1/, -(this.data.alt||"")+" "+this.pathName)}}}function h(b){var c=e(b),d=b.config.image2_captionedClass;return function(b,e){var f={width:1,height:1},g=b.name,h;if(!b.attributes["data-cke-realelement"]&&(c(b)?("div"==g&&(h=b.getFirst("figure"))&&(b.replaceWith(h),b=h),e.align="center",h=b.getFirst("img")||b.getFirst("a").getFirst("img")):"figure"==g&&b.hasClass(d)?h=b.find(function(a){return"img"===a.name&&-1!==CKEDITOR.tools.array.indexOf(["figure","a"],a.parent.name)},!0)[0]:a(b)&&(h="a"==b.name?b.children[0]: -b),h)){for(var k in f)(f=h.attributes[k])&&f.match(p)&&delete h.attributes[k];return b}}}function f(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[w[e]]):f["float"]=e),b||CKEDITOR.tools.isEmpty(f)||(d.style=CKEDITOR.tools.writeCssText(f)));return a}}function e(b){var c=b.config.image2_captionedClass,d=b.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(!a(g))return!1}else if("figure"==g.name){if(!g.hasClass(c))return!1}else if(b.enterMode==CKEDITOR.ENTER_P||!a(g))return!1; -return(d?f.hasClass(d[1]):"center"==CKEDITOR.tools.parseCssText(f.attributes.style||"",!0)["text-align"])?!0:!1}}function a(a){return"img"==a.name?!0:"a"==a.name?1==a.children.length&&a.getFirst("img"):!1}function m(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(){T=p+n*J;X=Math.round(T/B)}function k(){X=y-S;T=Math.round(X*B)}var l=a.parts.image,m=function(){var a=b.config.image2_maxSize,c;if(!a)return null;a=CKEDITOR.tools.copy(a);c=CKEDITOR.plugins.image2.getNatural(l); -a.width=Math.max("natural"===a.width?c.width:a.width,15);a.height=Math.max("natural"===a.height?c.height:a.height,15);return a}(),n="right"==a.data.align?-1:1,q=f.data.$.screenX,v=f.data.$.screenY,p=l.$.clientWidth,y=l.$.clientHeight,B=p/y,w=[],P="cke_image_s"+(~n?"e":"w"),Y,T,X,da,J,S,W;b.fire("saveSnapshot");g("mousemove",function(a){Y=a.data.$;J=Y.screenX-q;S=v-Y.screenY;W=Math.abs(J/S);1==n?0>=J?0>=S?h():W>=B?h():k():0>=S?W>=B?k():h():k():0>=J?0>=S?W>=B?k():h():k():0>=S?h():W>=B?h():k();a=m&& -(T>m.width||X>m.height);15>T||15>X||a||(da={width:T,height:X},l.setAttributes(da))},w);g("mouseup",function(){for(var d;d=w.pop();)d.removeListener();c.removeClass(P);e.removeClass("cke_image_resizing");da&&(a.setData(da),b.fire("saveSnapshot"));da=!1},w);c.addClass(P);e.addClass("cke_image_resizing")});a.on("data",function(){e["right"==a.data.align?"addClass":"removeClass"]("cke_image_resizer_left")})}function k(a){var b=[],d;return function(e){var f=a.getCommand("justify"+e);if(f){b.push(function(){f.refresh(a, -a.elementPath())});if(e in{right:1,left:1,center:1})f.on("exec",function(d){var f=c(a);if(f){f.setData("align",e);for(f=b.length;f--;)b[f]();d.cancel()}});f.on("refresh",function(b){var f=c(a),g={right:1,left:1,center:1};f&&(void 0===d&&(d=a.filter.checkFeature(a.widgets.registered.image.features.align)),d?this.setState(f.data.align==e?CKEDITOR.TRISTATE_ON:e in g?CKEDITOR.TRISTATE_OFF:CKEDITOR.TRISTATE_DISABLED):this.setState(CKEDITOR.TRISTATE_DISABLED),b.cancel())})}}}function l(a){if(a.plugins.link){var b= -CKEDITOR.on("dialogDefinition",function(b){b=b.data;if("link"==b.name){b=b.definition;var d=b.onShow,e=b.onOk;b.onShow=function(){var b=c(a),e=this.getContentElement("info","linkDisplayText").getElement().getParent().getParent();b&&(b.inline?!b.wrapper.getAscendant("a"):1)?(this.setupContent(b.data.link||{}),e.hide()):(e.show(),d.apply(this,arguments))};b.onOk=function(){var b=c(a);if(b&&(b.inline?!b.wrapper.getAscendant("a"):1)){var d={};this.commitContent(d);b.setData("link",d)}else e.apply(this, -arguments)}}});a.on("destroy",function(){b.removeListener()});a.getCommand("unlink").on("exec",function(b){var d=c(a);d&&d.parts.link&&(d.setData("link",null),this.refresh(a,a.elementPath()),b.cancel())});a.getCommand("unlink").on("refresh",function(b){var d=c(a);d&&(this.setState(d.data.link||d.wrapper.getAscendant("a")?CKEDITOR.TRISTATE_OFF:CKEDITOR.TRISTATE_DISABLED),b.cancel())})}}function c(a){return(a=a.widgets.focused)&&"image"==a.name?a:null}function d(a){var b=a.config.image2_alignClasses; -a={div:{match:e(a)},p:{match:e(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 g(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 y=new CKEDITOR.template('\x3cfigure class\x3d"{captionedClass}"\x3e\x3cimg alt\x3d"" src\x3d"" /\x3e\x3cfigcaption\x3e{captionPlaceholder}\x3c/figcaption\x3e\x3c/figure\x3e'),w={left:0,center:1,right:2},p=/^\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_editable[contenteditable\x3d"false"] .cke_image_resizer{display:none;}.cke_widget_wrapper\x3ea{display:inline-block}')}, +this.editor.widgets.destroyAll(!1,this);this._.initialSetData=!1;a=this.editor.dataProcessor.unprotectRealComments(a);a=this.editor.dataProcessor.unprotectSource(a);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="[^"]+")?>)?]*data-cke-copybin-start="1"[^>]*>.?<\/span>([\s\S]+)]*data-cke-copybin-end="1"[^>]*>.?<\/span>(?:<\/(?:div|span)>)?(?:<\/(?:div|span)>)?$/i, +ha={37:1,38:1,39:1,40:1,8:1,46:1};ha[CKEDITOR.SHIFT+121]=1;var P=CKEDITOR.tools.createClass({$:function(a,b){this._.createCopyBin(a,b);this._.createListeners(b)},_:{createCopyBin:function(a){var b=a.document,c=CKEDITOR.env.edge&&16<=CKEDITOR.env.version,d=!a.blockless&&!CKEDITOR.env.ie||c?"div":"span",c=b.createElement(d),b=b.createElement(d);b.setAttributes({id:"cke_copybin","data-cke-temp":"1"});c.setStyles({position:"absolute",width:"1px",height:"1px",overflow:"hidden"});c.setStyle("ltr"==a.config.contentsLangDirection? +"left":"right","-5000px");this.editor=a;this.copyBin=c;this.container=b},createListeners:function(a){a&&(a.beforeDestroy&&(this.beforeDestroy=a.beforeDestroy),a.afterDestroy&&(this.afterDestroy=a.afterDestroy))}},proto:{handle:function(a){var b=this.copyBin,c=this.editor,d=this.container,e=CKEDITOR.env.ie&&9>CKEDITOR.env.version,g=c.document.getDocumentElement().$,f=c.createRange(),h=this,k=CKEDITOR.env.mac&&CKEDITOR.env.webkit,l=k?100:0,m=window.requestAnimationFrame&&!k?requestAnimationFrame:setTimeout, +n,r,t;b.setHtml('\x3cspan data-cke-copybin-start\x3d"1"\x3e​\x3c/span\x3e'+a+'\x3cspan data-cke-copybin-end\x3d"1"\x3e​\x3c/span\x3e');c.fire("lockSnapshot");d.append(b);c.editable().append(d);n=c.on("selectionChange",D,null,null,0);r=c.widgets.on("checkSelection",D,null,null,0);e&&(t=g.scrollTop);f.selectNodeContents(b);f.select();e&&(g.scrollTop=t);return new CKEDITOR.tools.promise(function(a){m(function(){h.beforeDestroy&&h.beforeDestroy();d.remove();n.removeListener();r.removeListener();c.fire("unlockSnapshot"); +h.afterDestroy&&h.afterDestroy();a()},l)})}},statics:{hasCopyBin:function(a){return!!P.getCopyBin(a)},getCopyBin:function(a){return a.document.getById("cke_copybin")}}});CKEDITOR.plugins.widget=h;h.repository=b;h.nestedEditable=f}(),CKEDITOR.config.widget_keystrokeInsertLineBefore=CKEDITOR.SHIFT+CKEDITOR.ALT+13,CKEDITOR.config.widget_keystrokeInsertLineAfter=CKEDITOR.SHIFT+13,"use strict",function(){function b(a){function b(){this.deflated||(a.widgets.focused==this.widget&&(this.focused=!0),a.widgets.destroy(this.widget), +this.deflated=!0)}function c(){var b=a.editable(),d=a.document;if(this.deflated)this.widget=a.widgets.initOn(this.element,"image",this.widget.data),this.widget.inline&&!(new CKEDITOR.dom.elementPath(this.widget.wrapper,b)).block&&(b=d.createElement(a.activeEnterMode==CKEDITOR.ENTER_P?"p":"div"),b.replace(this.widget.wrapper),this.widget.wrapper.move(b)),this.focused&&(this.widget.focus(),delete this.focused),delete this.deflated;else{var g=this.widget,b=e,d=g.wrapper,f=g.data.align,g=g.data.hasCaption; +if(b){for(var h=3;h--;)d.removeClass(b[h]);"center"==f?g&&d.addClass(b[1]):"none"!=f&&d.addClass(b[v[f]])}else"center"==f?(g?d.setStyle("text-align","center"):d.removeStyle("text-align"),d.removeStyle("float")):("none"==f?d.removeStyle("float"):d.setStyle("float",f),d.removeStyle("text-align"))}}var e=a.config.image2_alignClasses,l=a.config.image2_captionedClass;return{allowedContent:d(a),requiredContent:"img[src,alt]",features:g(a),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 d=this.features;this.data.hasCaption&&!a.filter.checkFeature(d.caption)&&(this.data.hasCaption=!1);"none"==this.data.align||a.filter.checkFeature(d.align)||(this.data.align="none");this.shiftState({widget:this,element:this.element,oldData:this.oldData,newData:this.data,deflate:b, +inflate:c});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 e in this.data.classes)this.parts.image.removeClass(e);if(a.filter.checkFeature(d.dimension)){d=this.data;d={width:d.width,height:d.height};e=this.parts.image;for(var g in d)d[g]?e.setAttribute(g, +d[g]):e.removeAttribute(g)}this.oldData=CKEDITOR.tools.extend({},this.data)},init:function(){var b=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?b.checkHasNaturalRatio(c):!0},g=c.getAscendant("a");g&&this.wrapper.contains(g)&&(this.parts.link=g);d.align||(c=d.hasCaption?this.element:c,e?(c.hasClass(e[0])?d.align="left":c.hasClass(e[2])&& +(d.align="right"),d.align?c.removeClass(e[v[d.align]]):d.align="none"):(d.align=c.getStyle("float")||"none",c.removeStyle("float")));a.plugins.link&&this.parts.link&&(d.link=b.getLinkAttributesParser()(a,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);a.filter.checkFeature(this.features.dimension)&&!0!==a.config.image2_disableResizer&& +k(this);this.shiftState=b.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})},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(l,e).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(a),downcast:f(a),getLabel:function(){return this.editor.lang.widget.label.replace(/%1/,(this.data.alt||"")+" "+this.pathName)}}}function h(b){var c=e(b),d=b.config.image2_captionedClass;return function(b,e){var g={width:1,height:1},f=b.name,h;if(!b.attributes["data-cke-realelement"]&&(c(b)?("div"==f&&(h=b.getFirst("figure"))&&(b.replaceWith(h),b=h),e.align="center",h=b.getFirst("img")||b.getFirst("a").getFirst("img")):"figure"==f&&b.hasClass(d)? +h=b.find(function(a){return"img"===a.name&&-1!==CKEDITOR.tools.array.indexOf(["figure","a"],a.parent.name)},!0)[0]:a(b)&&(h="a"==b.name?b.children[0]:b),h)){for(var k in g)(g=h.attributes[k])&&g.match(p)&&delete h.attributes[k];return b}}}function f(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 g=a.getFirst("span");g&&g.replaceWith(g.getFirst({img:1,a:1}))}e&&"none"!=e&&(g=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]]):g["float"]=e),b||CKEDITOR.tools.isEmpty(g)||(d.style=CKEDITOR.tools.writeCssText(g)));return a}}function e(b){var c=b.config.image2_captionedClass,d=b.config.image2_alignClasses,e={figure:1,a:1,img:1};return function(g){if(!(g.name in{div:1,p:1}))return!1;var f=g.children;if(1!==f.length)return!1;f=f[0];if(!(f.name in e))return!1; +if("p"==g.name){if(!a(f))return!1}else if("figure"==f.name){if(!f.hasClass(c))return!1}else if(b.enterMode==CKEDITOR.ENTER_P||!a(f))return!1;return(d?g.hasClass(d[1]):"center"==CKEDITOR.tools.parseCssText(g.attributes.style||"",!0)["text-align"])?!0:!1}}function a(a){return"img"==a.name?!0:"a"==a.name?1==a.children.length&&a.getFirst("img"):!1}function k(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 g=a.parts.link||a.parts.image,f=g.getParent(),h=d.createElement("span");h.addClass("cke_image_resizer_wrapper");h.append(g);h.append(e);a.element.append(h,!0);f.is("span")&&f.remove()}e.on("mousedown",function(g){function f(a,b,c){var e=CKEDITOR.document,g=[];d.equals(e)||g.push(e.on(a,b));g.push(d.on(a,b));if(c)for(a=g.length;a--;)c.push(g.pop())}function h(){S=B+n*J;X=Math.round(S/y)}function k(){X=p-T;S=Math.round(X* +y)}var l=a.parts.image,m=function(){var a=b.config.image2_maxSize,c;if(!a)return null;a=CKEDITOR.tools.copy(a);c=CKEDITOR.plugins.image2.getNatural(l);a.width=Math.max("natural"===a.width?c.width:a.width,15);a.height=Math.max("natural"===a.height?c.height:a.height,15);return a}(),n="right"==a.data.align?-1:1,u=g.data.$.screenX,w=g.data.$.screenY,B=l.$.clientWidth,p=l.$.clientHeight,y=B/p,v=[],O="cke_image_s"+(~n?"e":"w"),Y,S,X,ca,J,T,W;b.fire("saveSnapshot");f("mousemove",function(a){Y=a.data.$;J= +Y.screenX-u;T=w-Y.screenY;W=Math.abs(J/T);1==n?0>=J?0>=T?h():W>=y?h():k():0>=T?W>=y?k():h():k():0>=J?0>=T?W>=y?k():h():k():0>=T?h():W>=y?h():k();a=m&&(S>m.width||X>m.height);15>S||15>X||a||(ca={width:S,height:X},l.setAttributes(ca))},v);f("mouseup",function(){for(var d;d=v.pop();)d.removeListener();c.removeClass(O);e.removeClass("cke_image_resizing");ca&&(a.setData(ca),b.fire("saveSnapshot"));ca=!1},v);c.addClass(O);e.addClass("cke_image_resizing")});a.on("data",function(){e["right"==a.data.align? +"addClass":"removeClass"]("cke_image_resizer_left")})}function l(a){var b=[],d;return function(e){var g=a.getCommand("justify"+e);if(g){b.push(function(){g.refresh(a,a.elementPath())});if(e in{right:1,left:1,center:1})g.on("exec",function(d){var g=c(a);if(g){g.setData("align",e);for(g=b.length;g--;)b[g]();d.cancel()}});g.on("refresh",function(b){var g=c(a),f={right:1,left:1,center:1};g&&(void 0===d&&(d=a.filter.checkFeature(a.widgets.registered.image.features.align)),d?this.setState(g.data.align== +e?CKEDITOR.TRISTATE_ON:e in f?CKEDITOR.TRISTATE_OFF:CKEDITOR.TRISTATE_DISABLED):this.setState(CKEDITOR.TRISTATE_DISABLED),b.cancel())})}}}function m(a){if(a.plugins.link){var b=CKEDITOR.on("dialogDefinition",function(b){b=b.data;if("link"==b.name){b=b.definition;var d=b.onShow,e=b.onOk;b.onShow=function(){var b=c(a),e=this.getContentElement("info","linkDisplayText").getElement().getParent().getParent();b&&(b.inline?!b.wrapper.getAscendant("a"):1)?(this.setupContent(b.data.link||{}),e.hide()):(e.show(), +d.apply(this,arguments))};b.onOk=function(){var b=c(a);if(b&&(b.inline?!b.wrapper.getAscendant("a"):1)){var d={};this.commitContent(d);b.setData("link",d)}else e.apply(this,arguments)}}});a.on("destroy",function(){b.removeListener()});a.getCommand("unlink").on("exec",function(b){var d=c(a);d&&d.parts.link&&(d.setData("link",null),this.refresh(a,a.elementPath()),b.cancel())});a.getCommand("unlink").on("refresh",function(b){var d=c(a);d&&(this.setState(d.data.link||d.wrapper.getAscendant("a")?CKEDITOR.TRISTATE_OFF: +CKEDITOR.TRISTATE_DISABLED),b.cancel())})}}function c(a){return(a=a.widgets.focused)&&"image"==a.name?a:null}function d(a){var b=a.config.image2_alignClasses;a={div:{match:e(a)},p:{match:e(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 g(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 y=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",{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_editable[contenteditable\x3d"false"] .cke_image_resizer{display:none;}.cke_widget_wrapper\x3ea{display:inline-block}')}, init:function(a){if(!a.plugins.detectConflict("image2",["easyimage"])){var c=a.config,d=a.lang.image2,e=b(a);c.filebrowserImage2BrowseUrl=c.filebrowserImageBrowseUrl;c.filebrowserImage2UploadUrl=c.filebrowserImageUploadUrl;e.pathName=d.pathName;e.editables.caption.pathName=d.pathNameCaption;a.widgets.add("image",e);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:d.menu,command:"image", -group:"image"}));CKEDITOR.dialog.add("image2",this.path+"dialogs/image2.js")}},afterInit:function(a){var b={left:1,right:1,center:1,block:1},c=k(a),d;for(d in b)c(d);l(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(y.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; +group:"image"}));CKEDITOR.dialog.add("image2",this.path+"dialogs/image2.js")}},afterInit:function(a){var b={left:1,right:1,center:1,block:1},c=l(a),d;for(d in b)c(d);m(a)}});CKEDITOR.plugins.image2={stateShifter:function(a){function b(a,g){var f={};e?f.attributes={"class":e[1]}:f.styles={"text-align":"center"};f=d.createElement(a.activeEnterMode==CKEDITOR.ENTER_P?"p":"div",f);c(f,g);g.move(f);return f}function c(b,d){if(d.getParent()){var e=a.createRange();e.moveToPosition(d,CKEDITOR.POSITION_BEFORE_START); +d.remove();f.insertElementIntoRange(b,e)}else b.replace(d)}var d=a.document,e=a.config.image2_alignClasses,g=a.config.image2_captionedClass,f=a.editable(),h=["hasCaption","align","link"],k={align:function(c,d,g){var f=c.element;c.changed.align?c.newData.hasCaption||("center"==g&&(c.deflate(),c.element=b(a,f)),c.changed.hasCaption||"center"!=d||"center"==g||(c.deflate(),d=f.findOne("a,img"),d.replace(f),c.element=d)):"center"==g&&c.changed.hasCaption&&!c.newData.hasCaption&&(c.deflate(),c.element= +b(a,f));!e&&f.is("figure")&&("center"==g?f.setStyle("display","inline-block"):f.removeStyle("display"))},hasCaption:function(b,e,f){b.changed.hasCaption&&(e=b.element.is({img:1,a:1})?b.element:b.element.findOne("a,img"),b.deflate(),f?(f=CKEDITOR.dom.element.createFromHtml(y.output({captionedClass:g,captionPlaceholder:a.lang.image2.captionPlaceholder}),d),c(f,b.element),e.replace(f.findOne("img")),b.element=f):(e.replace(b.element),b.element=e))},link:function(b,c,e){if(b.changed.link){var g=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")&&!e||b.element.is("img")&&e,k;h&&b.deflate();e?(c||(k=d.createElement("a",{attributes:{href:b.newData.link.url}}),k.replace(g),g.move(k)),e=CKEDITOR.plugins.image2.getLinkAttributesGetter()(a,e),CKEDITOR.tools.isEmpty(e.set)||(k||f).setAttributes(e.set),e.removed.length&&(k||f).removeAttributes(e.removed)):(e=f.findOne("img"),e.replace(f),k=e);h&&(b.element=k)}}};return function(a){var b,c; a.changed={};for(c=0;ct.length)return!1;h=c.getParents(!0);for(u=0;uv;u++)q[u].indent+=h;h=CKEDITOR.plugins.list.arrayToList(q,e,null,a.config.enterMode,c.getDirection());if(!d.isIndent){var A;if((A=c.getParent())&&A.is("li"))for(var t=h.listNode.getChildren(),E=[],w,u=t.count()-1;0<=u;u--)(w=t.getItem(u))&& -w.is&&w.is("li")&&E.push(w)}h&&h.listNode.replace(c);if(E&&E.length)for(u=0;uq.length)return!1;h=c.getParents(!0);for(t=0;tw;t++)u[t].indent+=h;h=CKEDITOR.plugins.list.arrayToList(u,e,null,a.config.enterMode,c.getDirection());if(!d.isIndent){var A;if((A=c.getParent())&&A.is("li"))for(var q=h.listNode.getChildren(),E=[],v,t=q.count()-1;0<=t;t--)(v=q.getItem(t))&& +v.is&&v.is("li")&&E.push(v)}h&&h.listNode.replace(c);if(E&&E.length)for(t=0;tf.length)){d=f[f.length-1].getNext();g=e.createElement(this.type);for(c.push(g);f.length;)c=f.shift(),a=e.createElement("li"),l=c,l.is("pre")||p.test(l.getName())||"false"==l.getAttribute("contenteditable")?c.appendTo(a):(c.copyAttributes(a),h&&c.getDirection()&&(a.removeStyle("direction"),a.removeAttribute("dir")),c.moveChildren(a), -c.remove()),a.appendTo(g);h&&k&&g.setAttribute("dir",h);d?g.insertBefore(d):g.appendTo(b)}}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;ge[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 e(a,b){this.name= -a;this.context=this.type=b;this.allowedContent=b+" li";this.requiredContent=b}function a(a,b,c,d){for(var e,f;e=a[d?"getLast":"getFirst"](t);)(f=e.getDirection(1))!==b.getDirection(1)&&e.setAttribute("dir",f),e.remove(),c?e[d?"insertBefore":"insertAfter"](c):b.append(e,d),c=e}function m(b){function c(d){var e=b[d?"getPrevious":"getNext"](y);e&&e.type==CKEDITOR.NODE_ELEMENT&&e.is(b.getName())&&(a(b,e,null,!d),b.remove(),b=e)}c();c(1)}function k(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,d,e){b.fire("saveSnapshot");e.enlarge(CKEDITOR.ENLARGE_LIST_ITEM_CONTENTS);var f=e.extractContents();d.trim(!1,!0);var g=d.createBookmark(),h=new CKEDITOR.dom.elementPath(d.startContainer),k=h.block,h=h.lastElement.getAscendant("li",1)||k,l=new CKEDITOR.dom.elementPath(e.startContainer),n=l.contains(CKEDITOR.dtd.$listItem),l=l.contains(CKEDITOR.dtd.$list);k?(k=k.getBogus())&&k.remove():l&&(k=l.getPrevious(y))&& -w(k)&&k.remove();(k=f.getLast())&&k.type==CKEDITOR.NODE_ELEMENT&&k.is("br")&&k.remove();(k=d.startContainer.getChild(d.startOffset))?f.insertBefore(k):d.startContainer.append(f);n&&(f=c(n))&&(h.contains(n)?(a(f,n.getParent(),n),f.remove()):h.append(f));for(;e.checkStartOfBlock()&&e.checkEndOfBlock();){l=e.startPath();f=l.block;if(!f)break;f.is("li")&&(h=f.getParent(),f.equals(h.getLast(y))&&f.equals(h.getFirst(y))&&(f=h));e.moveToPosition(f,CKEDITOR.POSITION_BEFORE_START);f.remove()}e=e.clone();f= -b.editable();e.setEndAt(f,CKEDITOR.POSITION_BEFORE_END);e=new CKEDITOR.dom.walker(e);e.evaluator=function(a){return y(a)&&!w(a)};(e=e.next())&&e.type==CKEDITOR.NODE_ELEMENT&&e.getName()in CKEDITOR.dtd.$list&&m(e);d.moveToBookmark(g);d.select();b.fire("saveSnapshot")}function c(a){return(a=a.getLast(y))&&a.type==CKEDITOR.NODE_ELEMENT&&a.getName()in d?a:null}var d={ol:1,ul:1},g=CKEDITOR.dom.walker.whitespaces(),n=CKEDITOR.dom.walker.bookmark(),y=function(a){return!(g(a)||n(a))},w=CKEDITOR.dom.walker.bogus(); -CKEDITOR.plugins.list={listToArray:function(a,b,c,e,f){if(!d[a.getName()])return[];e||(e=0);c||(c=[]);for(var g=0,h=a.getChildCount();g= -h.$.documentMode&&p.append(h.createText(" ")),p.append(m.listNode),m=m.nextIndex;else if(-1==I.indent&&!c&&g){d[g.getName()]?(p=I.element.clone(!1,!0),w!=g.getDirection(1)&&p.setAttribute("dir",w)):p=new CKEDITOR.dom.documentFragment(h);var l=g.getDirection(1)!=w,M=I.element,Q=M.getAttribute("class"),H=M.getAttribute("style"),G=p.type==CKEDITOR.NODE_DOCUMENT_FRAGMENT&&(e!=CKEDITOR.ENTER_BR||l||H||Q),P,Y=I.contents.length,T;for(g=0;gg.length)){d=g[g.length-1].getNext();f=e.createElement(this.type);for(c.push(f);g.length;)c=g.shift(),a=e.createElement("li"),l=c,l.is("pre")||p.test(l.getName())||"false"==l.getAttribute("contenteditable")?c.appendTo(a):(c.copyAttributes(a),h&&c.getDirection()&&(a.removeStyle("direction"),a.removeAttribute("dir")),c.moveChildren(a), +c.remove()),a.appendTo(f);h&&k&&f.setAttribute("dir",h);d?f.insertBefore(d):f.appendTo(b)}}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),g=[],f=0;fe[f-1].indent+1){g=e[f-1].indent+1-e[f].indent;for(h=e[f].indent;e[f]&&e[f].indent>=h;)e[f].indent+=g,f++;f--}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 e(a,b){this.name= +a;this.context=this.type=b;this.allowedContent=b+" li";this.requiredContent=b}function a(a,b,c,d){for(var e,g;e=a[d?"getLast":"getFirst"](q);)(g=e.getDirection(1))!==b.getDirection(1)&&e.setAttribute("dir",g),e.remove(),c?e[d?"insertBefore":"insertAfter"](c):b.append(e,d),c=e}function k(b){function c(d){var e=b[d?"getPrevious":"getNext"](y);e&&e.type==CKEDITOR.NODE_ELEMENT&&e.is(b.getName())&&(a(b,e,null,!d),b.remove(),b=e)}c();c(1)}function l(a){return a.type==CKEDITOR.NODE_ELEMENT&&(a.getName()in +CKEDITOR.dtd.$block||a.getName()in CKEDITOR.dtd.$listItem)&&CKEDITOR.dtd[a.getName()]["#"]}function m(b,d,e){b.fire("saveSnapshot");e.enlarge(CKEDITOR.ENLARGE_LIST_ITEM_CONTENTS);var g=e.extractContents();d.trim(!1,!0);var f=d.createBookmark(),h=new CKEDITOR.dom.elementPath(d.startContainer),l=h.block,h=h.lastElement.getAscendant("li",1)||l,m=new CKEDITOR.dom.elementPath(e.startContainer),n=m.contains(CKEDITOR.dtd.$listItem),m=m.contains(CKEDITOR.dtd.$list);l?(l=l.getBogus())&&l.remove():m&&(l=m.getPrevious(y))&& +v(l)&&l.remove();(l=g.getLast())&&l.type==CKEDITOR.NODE_ELEMENT&&l.is("br")&&l.remove();(l=d.startContainer.getChild(d.startOffset))?g.insertBefore(l):d.startContainer.append(g);n&&(g=c(n))&&(h.contains(n)?(a(g,n.getParent(),n),g.remove()):h.append(g));for(;e.checkStartOfBlock()&&e.checkEndOfBlock();){m=e.startPath();g=m.block;if(!g)break;g.is("li")&&(h=g.getParent(),g.equals(h.getLast(y))&&g.equals(h.getFirst(y))&&(g=h));e.moveToPosition(g,CKEDITOR.POSITION_BEFORE_START);g.remove()}e=e.clone();g= +b.editable();e.setEndAt(g,CKEDITOR.POSITION_BEFORE_END);e=new CKEDITOR.dom.walker(e);e.evaluator=function(a){return y(a)&&!v(a)};(e=e.next())&&e.type==CKEDITOR.NODE_ELEMENT&&e.getName()in CKEDITOR.dtd.$list&&k(e);d.moveToBookmark(f);d.select();b.fire("saveSnapshot")}function c(a){return(a=a.getLast(y))&&a.type==CKEDITOR.NODE_ELEMENT&&a.getName()in d?a:null}var d={ol:1,ul:1},g=CKEDITOR.dom.walker.whitespaces(),n=CKEDITOR.dom.walker.bookmark(),y=function(a){return!(g(a)||n(a))},v=CKEDITOR.dom.walker.bogus(); +CKEDITOR.plugins.list={listToArray:function(a,b,c,e,g){if(!d[a.getName()])return[];e||(e=0);c||(c=[]);for(var f=0,h=a.getChildCount();f= +h.$.documentMode&&p.append(h.createText(" ")),p.append(m.listNode),m=m.nextIndex;else if(-1==I.indent&&!c&&f){d[f.getName()]?(p=I.element.clone(!1,!0),v!=f.getDirection(1)&&p.setAttribute("dir",v)):p=new CKEDITOR.dom.documentFragment(h);var l=f.getDirection(1)!=v,L=I.element,R=L.getAttribute("class"),H=L.getAttribute("style"),G=p.type==CKEDITOR.NODE_DOCUMENT_FRAGMENT&&(e!=CKEDITOR.ENTER_BR||l||H||R),O,Y=I.contents.length,S;for(f=0;fb&&aK.version?" ":T,g=b.hotNode&&b.hotNode.getText()==f&&b.element.equals(b.hotNode)&&b.lastCmdDirection===!!d;c(b,function(c){g&& -b.hotNode&&b.hotNode.remove();c[d?"insertAfter":"insertBefore"](a);c.setAttributes({"data-cke-magicline-hot":1,"data-cke-magicline-dir":!!d});b.lastCmdDirection=!!d});K.ie||b.enterMode==CKEDITOR.ENTER_BR||b.hotNode.scrollIntoView();b.line.detach()}return function(c){c=c.getSelection().getStartElement();var g;c=c.getAscendant(S,1);if(!t(b,c)&&c&&!c.equals(b.editable)&&!c.contains(b.editable)){(g=k(c))&&"false"==g.getAttribute("contenteditable")&&(c=g);b.element=c;g=a(b,c,!d);var h;n(g)&&g.is(b.triggers)&& -g.is(J)&&(!a(b,g,!d)||(h=a(b,g,!d))&&n(h)&&h.is(b.triggers))?e(g):(h=f(b,c),n(h)&&(a(b,h,!d)?(c=a(b,h,!d))&&n(c)&&c.is(b.triggers)&&e(h):e(h)))}}}()}}function g(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 y(a){if(!n(a))return!1;var b;(b=w(a))||(n(a)?(b={left:1,right:1,center:1},b=!(!b[a.getComputedStyle("float")]&&!b[a.getAttribute("align")])):b=!1);return b}function w(a){return!!{absolute:1, -fixed:1}[a.getComputedStyle("position")]}function p(a,b){return n(b)?b.is(a.triggers):null}function t(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 r(a,b,c){b=b[c?"getLast":"getFirst"](function(b){return a.isRelevant(b)&&!b.is(da)});if(!b)return!1;q(a,b);return c?b.size.top>a.mouse.y:b.size.bottom -(a.inInlineMode?d.editable.top+d.editable.height/2:Math.min(d.editable.height,d.pane.height)/2),b=b[f?"getLast":"getFirst"](function(a){return!(U(a)||V(a))});if(!b)return null;g(a,b)&&(b=a.line.wrap[f?"getPrevious":"getNext"](function(a){return!(U(a)||V(a))}));if(!n(b)||y(b)||!p(a,b))return null;q(a,b);return!f&&0<=b.size.top&&m(c.y,0,b.size.top+e)?(a=a.inInlineMode||0===d.scroll.y?G:Y,new h([null,b,I,H,a])):f&&b.size.bottom<=d.pane.height&&m(c.y,b.size.bottom-e,d.pane.height)?(a=a.inInlineMode|| -m(b.size.bottom,d.pane.height-e,d.pane.height)?P:Y,new h([b,null,M,H,a])):null}function u(b){var c=b.mouse,d=b.view,e=b.triggerOffset,g=f(b);if(!g)return null;q(b,g);var e=Math.min(e,0|g.size.outerHeight/2),k=[],l,t;if(m(c.y,g.size.top-1,g.size.top+e))t=!1;else if(m(c.y,g.size.bottom-e,g.size.bottom+1))t=!0;else return null;if(y(g)||r(b,g,t)||g.getParent().is(X))return null;var u=a(b,g,!t);if(u){if(u&&u.type==CKEDITOR.NODE_TEXT)return null;if(n(u)){if(y(u)||!p(b,u)||u.getParent().is(X))return null; -k=[u,g][t?"reverse":"concat"]().concat([Q,H])}}else g.equals(b.editable[t?"getLast":"getFirst"](b.isRelevant))?(v(b),t&&m(c.y,g.size.bottom-e,d.pane.height)&&m(g.size.bottom,d.pane.height-e,d.pane.height)?l=P:m(c.y,0,g.size.top+e)&&(l=G)):l=Y,k=[null,g][t?"reverse":"concat"]().concat([t?M:I,H,l,g.equals(b.editable[t?"getLast":"getFirst"](b.isRelevant))?t?P:G:Y]);return 0 in k?new h(k):null}function z(a,b,c,d){for(var e=b.getDocumentPosition(),f={},g={},h={},k={},l=N.length;l--;)f[N[l]]=parseInt(b.getComputedStyle.call(b, -"border-"+N[l]+"-width"),10)||0,h[N[l]]=parseInt(b.getComputedStyle.call(b,"padding-"+N[l]),10)||0,g[N[l]]=parseInt(b.getComputedStyle.call(b,"margin-"+N[l]),10)||0;c&&!d||B(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 A({border:f,padding:h,margin:g,ignoreScroll:c},k,!0)}function q(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-W)return null;return A(b.size,z(a,b,c),{date:+new Date},!0)}function v(a,b){a.view.editable=z(a,a.editable,b,!0)}function B(a,b){a.view||(a.view={});var c=a.view;if(!(!b&&c&&c.date>new Date-W)){var d=a.win,c=d.getScrollPosition(),d=d.getViewPaneSize();A(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 D(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+gd.left-e.x&&cd.top-e.y&&aCKEDITOR.env.version, -C=CKEDITOR.dtd,O={},I=128,M=64,Q=32,H=16,G=4,P=2,Y=1,T=" ",X=C.$listItem,da=C.$tableContent,J=A({},C.$nonEditable,C.$empty),S=C.$block,W=100,aa="width:0px;height:0px;padding:0px;margin:0px;display:block;z-index:9999;color:#fff;position:absolute;font-size: 0px;line-height:0px;",ba=aa+"border-color:transparent;display:block;border-style:solid;",ca="\x3cspan\x3e"+T+"\x3c/span\x3e";O[CKEDITOR.ENTER_BR]="br";O[CKEDITOR.ENTER_P]="p";O[CKEDITOR.ENTER_DIV]="div";h.prototype={set:function(a,b,c){this.properties= +{label:a.lang.list.bulletedlist,command:"bulletedlist",directional:!0,toolbar:"list,20"})),a.on("key",function(b){var e=b.data.domEvent.getKey(),g;if("wysiwyg"==a.mode&&e in{8:1,46:1}){var f=a.getSelection().getRanges()[0],h=f&&f.startPath();if(f&&f.collapsed){var k=8==e,n=a.editable(),q=new CKEDITOR.dom.walker(f.clone());q.evaluator=function(a){return y(a)&&!v(a)};q.guard=function(a,b){return!(b&&a.type==CKEDITOR.NODE_ELEMENT&&a.is("table"))};e=f.clone();if(k){var p;(p=h.contains(d))&&f.checkBoundaryOfElement(p, +CKEDITOR.START)&&(p=p.getParent())&&p.is("li")&&(p=c(p))?(g=p,p=p.getPrevious(y),e.moveToPosition(p&&v(p)?p:g,CKEDITOR.POSITION_BEFORE_START)):(q.range.setStartAt(n,CKEDITOR.POSITION_AFTER_START),q.range.setEnd(f.startContainer,f.startOffset),(p=q.previous())&&p.type==CKEDITOR.NODE_ELEMENT&&(p.getName()in d||p.is("li"))&&(p.is("li")||(q.range.selectNodeContents(p),q.reset(),q.evaluator=l,p=q.previous()),g=p,e.moveToElementEditEnd(g),e.moveToPosition(e.endPath().block,CKEDITOR.POSITION_BEFORE_END))); +if(g)m(a,e,f),b.cancel();else{var F=h.contains(d);F&&f.checkBoundaryOfElement(F,CKEDITOR.START)&&(g=F.getFirst(y),f.checkBoundaryOfElement(g,CKEDITOR.START)&&(p=F.getPrevious(y),c(g)?p&&(f.moveToElementEditEnd(p),f.select()):a.execCommand("outdent"),b.cancel()))}}else if(g=h.contains("li")){if(q.range.setEndAt(n,CKEDITOR.POSITION_BEFORE_END),k=(n=g.getLast(y))&&l(n)?n:g,h=0,(p=q.next())&&p.type==CKEDITOR.NODE_ELEMENT&&p.getName()in d&&p.equals(n)?(h=1,p=q.next()):f.checkBoundaryOfElement(k,CKEDITOR.END)&& +(h=2),h&&p){f=f.clone();f.moveToElementEditStart(p);if(1==h&&(e.optimize(),!e.startContainer.equals(g))){for(g=e.startContainer;g.is(CKEDITOR.dtd.$inline);)F=g,g=g.getParent();F&&e.moveToPosition(F,CKEDITOR.POSITION_AFTER_END)}2==h&&(e.moveToPosition(e.endPath().block,CKEDITOR.POSITION_BEFORE_END),f.endPath().block&&f.moveToPosition(f.endPath().block,CKEDITOR.POSITION_AFTER_START));m(a,e,f);b.cancel()}}else q.range.setEndAt(n,CKEDITOR.POSITION_BEFORE_END),(p=q.next())&&p.type==CKEDITOR.NODE_ELEMENT&& +p.is(d)&&(p=p.getFirst(y),h.block&&f.checkStartOfBlock()&&f.checkEndOfBlock()?(h.block.remove(),f.moveToElementEditStart(p),f.select()):c(p)?(f.moveToElementEditStart(p),f.select()):(f=f.clone(),f.moveToElementEditStart(p),m(a,e,f)),b.cancel());setTimeout(function(){a.selectionChange(1)})}}}))}})}(),"use strict",function(){function b(a,b,c){return n(b)&&n(c)&&c.equals(b.getNext(function(a){return!(U(a)||V(a)||y(a))}))}function h(a){this.upper=a[0];this.lower=a[1];this.set.apply(this,a.slice(2))}function f(a){var b= +a.element;if(b&&n(b)&&(b=b.getAscendant(a.triggers,!0))&&a.editable.contains(b)){var c=l(b);if("true"==c.getAttribute("contenteditable"))return b;if(c.is(a.triggers))return c}return null}function e(a,b,c){u(a,b);u(a,c);a=b.size.bottom;c=c.size.top;return a&&c?0|(a+c)/2:a||c}function a(a,b,c){return b=b[c?"getPrevious":"getNext"](function(b){return b&&b.type==CKEDITOR.NODE_TEXT&&!U(b)||n(b)&&!y(b)&&!g(a,b)})}function k(a,b,c){return a>b&&aK.version?" ":S,f=b.hotNode&&b.hotNode.getText()==g&&b.element.equals(b.hotNode)&&b.lastCmdDirection===!!d;c(b,function(c){f&& +b.hotNode&&b.hotNode.remove();c[d?"insertAfter":"insertBefore"](a);c.setAttributes({"data-cke-magicline-hot":1,"data-cke-magicline-dir":!!d});b.lastCmdDirection=!!d});K.ie||b.enterMode==CKEDITOR.ENTER_BR||b.hotNode.scrollIntoView();b.line.detach()}return function(c){c=c.getSelection().getStartElement();var g;c=c.getAscendant(T,1);if(!q(b,c)&&c&&!c.equals(b.editable)&&!c.contains(b.editable)){(g=l(c))&&"false"==g.getAttribute("contenteditable")&&(c=g);b.element=c;g=a(b,c,!d);var h;n(g)&&g.is(b.triggers)&& +g.is(J)&&(!a(b,g,!d)||(h=a(b,g,!d))&&n(h)&&h.is(b.triggers))?e(g):(h=f(b,c),n(h)&&(a(b,h,!d)?(c=a(b,h,!d))&&n(c)&&c.is(b.triggers)&&e(h):e(h)))}}}()}}function g(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 y(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 q(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 r(a,b,c){b=b[c?"getLast":"getFirst"](function(b){return a.isRelevant(b)&&!b.is(ca)});if(!b)return!1;u(a,b);return c?b.size.top>a.mouse.y:b.size.bottom +(a.inInlineMode?d.editable.top+d.editable.height/2:Math.min(d.editable.height,d.pane.height)/2),b=b[f?"getLast":"getFirst"](function(a){return!(U(a)||V(a))});if(!b)return null;g(a,b)&&(b=a.line.wrap[f?"getPrevious":"getNext"](function(a){return!(U(a)||V(a))}));if(!n(b)||y(b)||!p(a,b))return null;u(a,b);return!f&&0<=b.size.top&&k(c.y,0,b.size.top+e)?(a=a.inInlineMode||0===d.scroll.y?G:Y,new h([null,b,I,H,a])):f&&b.size.bottom<=d.pane.height&&k(c.y,b.size.bottom-e,d.pane.height)?(a=a.inInlineMode|| +k(b.size.bottom,d.pane.height-e,d.pane.height)?O:Y,new h([b,null,L,H,a])):null}function t(b){var c=b.mouse,d=b.view,e=b.triggerOffset,g=f(b);if(!g)return null;u(b,g);var e=Math.min(e,0|g.size.outerHeight/2),l=[],m,q;if(k(c.y,g.size.top-1,g.size.top+e))q=!1;else if(k(c.y,g.size.bottom-e,g.size.bottom+1))q=!0;else return null;if(y(g)||r(b,g,q)||g.getParent().is(X))return null;var t=a(b,g,!q);if(t){if(t&&t.type==CKEDITOR.NODE_TEXT)return null;if(n(t)){if(y(t)||!p(b,t)||t.getParent().is(X))return null; +l=[t,g][q?"reverse":"concat"]().concat([R,H])}}else g.equals(b.editable[q?"getLast":"getFirst"](b.isRelevant))?(w(b),q&&k(c.y,g.size.bottom-e,d.pane.height)&&k(g.size.bottom,d.pane.height-e,d.pane.height)?m=O:k(c.y,0,g.size.top+e)&&(m=G)):m=Y,l=[null,g][q?"reverse":"concat"]().concat([q?L:I,H,m,g.equals(b.editable[q?"getLast":"getFirst"](b.isRelevant))?q?O:G:Y]);return 0 in l?new h(l):null}function z(a,b,c,d){for(var e=b.getDocumentPosition(),g={},f={},h={},l={},k=P.length;k--;)g[P[k]]=parseInt(b.getComputedStyle.call(b, +"border-"+P[k]+"-width"),10)||0,h[P[k]]=parseInt(b.getComputedStyle.call(b,"padding-"+P[k]),10)||0,f[P[k]]=parseInt(b.getComputedStyle.call(b,"margin-"+P[k]),10)||0;c&&!d||B(a,d);l.top=e.y-(c?0:a.view.scroll.y);l.left=e.x-(c?0:a.view.scroll.x);l.outerWidth=b.$.offsetWidth;l.outerHeight=b.$.offsetHeight;l.height=l.outerHeight-(h.top+h.bottom+g.top+g.bottom);l.width=l.outerWidth-(h.left+h.right+g.left+g.right);l.bottom=l.top+l.outerHeight;l.right=l.left+l.outerWidth;a.inInlineMode&&(l.scroll={top:b.$.scrollTop, +left:b.$.scrollLeft});return A({border:g,padding:h,margin:f,ignoreScroll:c},l,!0)}function u(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-W)return null;return A(b.size,z(a,b,c),{date:+new Date},!0)}function w(a,b){a.view.editable=z(a,a.editable,b,!0)}function B(a,b){a.view||(a.view={});var c=a.view;if(!(!b&&c&&c.date>new Date-W)){var d=a.win,c=d.getScrollPosition(),d=d.getViewPaneSize();A(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 C(a,b,c,d){for(var e=d,g=d,f=0,l=!1,k=!1,m=a.view.pane.height,n=a.mouse;n.y+fd.left-e.x&&cd.top-e.y&&aCKEDITOR.env.version, +D=CKEDITOR.dtd,N={},I=128,L=64,R=32,H=16,G=4,O=2,Y=1,S=" ",X=D.$listItem,ca=D.$tableContent,J=A({},D.$nonEditable,D.$empty),T=D.$block,W=100,aa="width:0px;height:0px;padding:0px;margin:0px;display:block;z-index:9999;color:#fff;position:absolute;font-size: 0px;line-height:0px;",ba=aa+"border-color:transparent;display:block;border-style:solid;",da="\x3cspan\x3e"+S+"\x3c/span\x3e";N[CKEDITOR.ENTER_BR]="br";N[CKEDITOR.ENTER_P]="p";N[CKEDITOR.ENTER_DIV]="div";h.prototype={set:function(a,b,c){this.properties= a+b+(c||Y);return this},is:function(a){return(this.properties&a)==a}};var Z=function(){function a(b,c){var d=b.$.elementFromPoint(c.x,c.y);return d&&d.nodeType?new CKEDITOR.dom.element(d):null}return function(b,c,d){if(!b.mouse)return null;var e=b.doc,f=b.line.wrap;d=d||b.mouse;var h=a(e,d);c&&g(b,h)&&(f.hide(),h=a(e,d),f.show());return!h||h.type!=CKEDITOR.NODE_ELEMENT||!h.$||K.ie&&9>K.version&&!b.boundary.equals(h)&&!b.boundary.contains(h)?null:h}}(),U=CKEDITOR.dom.walker.whitespaces(),V=CKEDITOR.dom.walker.nodeType(CKEDITOR.NODE_COMMENT), -ga=function(){function a(d){var f=d.element,g,h,k;if(!n(f)||f.contains(d.editable)||f.isReadOnly())return null;k=D(d,function(a,b){return!b.equals(a)},function(a,b){return Z(a,!0,b)},f);g=k.upper;h=k.lower;if(b(d,g,h))return k.set(Q,8);if(g&&f.contains(g))for(;!g.getParent().equals(f);)g=g.getParent();else g=f.getFirst(function(a){return c(d,a)});if(h&&f.contains(h))for(;!h.getParent().equals(f);)h=h.getParent();else h=f.getLast(function(a){return c(d,a)});if(!g||!h)return null;q(d,g);q(d,h);if(!m(d.mouse.y, -g.size.top,h.size.bottom))return null;for(var f=Number.MAX_VALUE,l,r,t,u;h&&!h.equals(g)&&(r=g.getNext(d.isRelevant));)l=Math.abs(e(d,g,r)-d.mouse.y),la.status||304==a.status||0===a.status||1223==a.status))return null;switch(b){case "text":return a.responseText;case "xml":var e=a.responseXML;return new CKEDITOR.xml(e&&e.firstChild?e:a.responseText);case "arraybuffer":return a.response;default:return null}} -function f(a,e,f){var l=!!e,c=b();if(!c)return null;l&&"text"!==f&&"xml"!==f&&(c.responseType=f);c.open("GET",a,l);l&&(c.onreadystatechange=function(){4==c.readyState&&(e(h(c,f)),c=null)});c.send(null);return l?"":h(c,f)}function e(a,e,f,l,c){var d=b();if(!d)return null;d.open("POST",a,!0);d.onreadystatechange=function(){4==d.readyState&&(l&&l(h(d,c)),d=null)};d.setRequestHeader("Content-type",f||"application/x-www-form-urlencoded; charset\x3dUTF-8");d.send(e)}return{load:function(a,b,e){return f(a, -b,e||"text")},post:function(a,b,f,h){return e(a,b,f,h,"text")},loadXml:function(a,b){return f(a,b,"xml")},loadText:function(a,b){return f(a,b,"text")},loadBinary:function(a,b){return f(a,b,"arraybuffer")}}}()}(),function(){function b(a,b){return CKEDITOR.tools.array.filter(a,function(a){return a.canHandle(b)}).sort(function(a,b){return a.priority===b.priority?0:a.priority-b.priority})}function h(a,b){var c=a.shift();c&&c.handle(b,function(){h(a,b)})}function f(a){var b=CKEDITOR.tools.array.reduce(a, -function(a,b){return CKEDITOR.tools.array.isArray(b.filters)?a.concat(b.filters):a},[]);return CKEDITOR.tools.array.filter(b,function(a,d){return CKEDITOR.tools.array.indexOf(b,a)===d})}function e(b,e){var c=0,d,f;if(!CKEDITOR.tools.array.isArray(b)||0===b.length)return!0;d=CKEDITOR.tools.array.filter(b,function(b){return-1===CKEDITOR.tools.array.indexOf(a,b)});if(0=CKEDITOR.env.version;return!(CKEDITOR.env.webkit&&!CKEDITOR.env.chrome)&&!b},init:function(b){if(this.isSupportedEnvironment()){var h=CKEDITOR.plugins.getPath("pastetools"), -f=this.path;b.pasteTools.register({priority:100,filters:[CKEDITOR.getUrl(h+"filter/common.js"),CKEDITOR.getUrl(h+"filter/image.js"),CKEDITOR.getUrl(f+"filter/default.js")],canHandle:function(b){b=b.data;return(b=b.dataTransfer.getData("text/html",!0)||b.dataValue)?"libreoffice"===CKEDITOR.plugins.pastetools.getContentGeneratorName(b):!1},handle:function(e,a){var f=e.data,h=f.dataValue||CKEDITOR.plugins.pastetools.getClipboardData(f,"text/html");f.dontFilter=!0;h=CKEDITOR.pasteFilters.image(h,b,CKEDITOR.plugins.pastetools.getClipboardData(f, -"text/rtf"));f.dataValue=CKEDITOR.pasteFilters.libreoffice(h,b);!0===b.config.forcePasteAsPlainText&&(f.type="text");a()}})}}})}(),function(){CKEDITOR.plugins.add("pastefromword",{requires:"pastetools",init:function(b){var h=0,f=CKEDITOR.plugins.getPath("pastetools"),e=this.path,a=void 0===b.config.pasteFromWord_inlineImages?!0:b.config.pasteFromWord_inlineImages,f=[CKEDITOR.getUrl(f+"filter/common.js"),CKEDITOR.getUrl(f+"filter/image.js"),CKEDITOR.getUrl(e+"filter/default.js")];b.addCommand("pastefromword", -{canUndo:!1,async:!0,exec:function(a,b){h=1;a.execCommand("paste",{type:"html",notification:b&&"undefined"!==typeof b.notification?b.notification:!0})}});CKEDITOR.plugins.clipboard.addPasteButton(b,"PasteFromWord",{label:b.lang.pastefromword.toolbar,command:"pastefromword",toolbar:"clipboard,50"});b.pasteTools.register({filters:b.config.pasteFromWordCleanupFile?[b.config.pasteFromWordCleanupFile]:f,canHandle:function(a){a=CKEDITOR.plugins.pastetools.getClipboardData(a.data,"text/html");var b=CKEDITOR.plugins.pastetools.getContentGeneratorName(a), -e=/(class="?Mso|style=["'][^"]*?\bmso\-|w:WordDocument||<\/font>)/,b=b?"microsoft"===b:e.test(a);return a&&(h||b)},handle:function(e,f){var l=e.data,c=CKEDITOR.plugins.pastetools.getClipboardData(l,"text/html"),d=CKEDITOR.plugins.pastetools.getClipboardData(l,"text/rtf"),c={dataValue:c,dataTransfer:{"text/rtf":d}};if(!1!==b.fire("pasteFromWord",c)||h){l.dontFilter=!0;if(h||!b.config.pasteFromWordPromptCleanup||confirm(b.lang.pastefromword.confirmCleanup))c.dataValue=CKEDITOR.cleanWord(c.dataValue, -b),CKEDITOR.plugins.clipboard.isCustomDataTypesSupported&&a&&CKEDITOR.pasteFilters.image&&(c.dataValue=CKEDITOR.pasteFilters.image(c.dataValue,b,d)),b.fire("afterPasteFromWord",c),l.dataValue=c.dataValue,!0===b.config.forcePasteAsPlainText?l.type="text":CKEDITOR.plugins.clipboard.isCustomCopyCutSupported||"allow-word"!==b.config.forcePasteAsPlainText||(l.type="html");h=0;f()}}})}})}(),function(){var b={canUndo:!1,async:!0,exec:function(b,f){var e=b.lang,a=CKEDITOR.tools.keystrokeToString(e.common.keyboard, -b.getCommandKeystroke(CKEDITOR.env.ie?b.commands.paste:this)),m=f&&"undefined"!==typeof f.notification?f.notification:!f||!f.from||"keystrokeHandler"===f.from&&CKEDITOR.env.ie,e=m&&"string"===typeof m?m:e.pastetext.pasteNotification.replace(/%1/,'\x3ckbd aria-label\x3d"'+a.aria+'"\x3e'+a.display+"\x3c/kbd\x3e");b.execCommand("paste",{type:"text",notification:m?e:!1})}};CKEDITOR.plugins.add("pastetext",{requires:"clipboard",init:function(h){var f=CKEDITOR.env.safari?CKEDITOR.CTRL+CKEDITOR.ALT+CKEDITOR.SHIFT+ -86:CKEDITOR.CTRL+CKEDITOR.SHIFT+86;h.addCommand("pastetext",b);h.setKeystroke(f,"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(b){"html"!=b.data.type&&(b.data.type="text")});h.on("pasteState",function(b){h.getCommand("pastetext").setState(b.data)})}})}(),CKEDITOR.plugins.add("removeformat",{init:function(b){b.addCommand("removeFormat",CKEDITOR.plugins.removeformat.commands.removeformat); -b.ui.addButton&&b.ui.addButton("RemoveFormat",{label:b.lang.removeformat.toolbar,command:"removeFormat",toolbar:"cleanup,10"})}}),CKEDITOR.plugins.removeformat={commands:{removeformat:{exec:function(b){for(var h=b._.removeFormatRegex||(b._.removeFormatRegex=new RegExp("^(?:"+b.config.removeFormatTags.replace(/,/g,"|")+")$","i")),f=b._.removeAttributes||(b._.removeAttributes=b.config.removeFormatAttributes.split(",")),e=CKEDITOR.plugins.removeformat.filter,a=b.getSelection().getRanges(),m=a.createIterator(), -k=function(a){return a.type==CKEDITOR.NODE_ELEMENT},l;l=m.getNextRange();){l.enlarge(CKEDITOR.ENLARGE_INLINE);var c=l.createBookmark(),d=c.startNode,g=c.endNode,n=function(a){for(var c=b.elementPath(a),d=c.elements,f=1,g;(g=d[f])&&!g.equals(c.block)&&!g.equals(c.blockLimit);f++)h.test(g.getName())&&e(b,g)&&a.breakParent(g)};n(d);if(g)for(n(g),d=d.getNextSourceNode(!0,CKEDITOR.NODE_ELEMENT);d&&!d.equals(g);)if(d.isReadOnly()){if(d.getPosition(g)&CKEDITOR.POSITION_CONTAINS)break;d=d.getNext(k)}else n= -d.getNextSourceNode(!1,CKEDITOR.NODE_ELEMENT),"img"==d.getName()&&d.data("cke-realelement")||!e(b,d)||(h.test(d.getName())?d.remove(1):(d.removeAttributes(f),b.fire("removeFormatCleanup",d))),d=n;l.moveToBookmark(c)}b.forceNextSelectionCheck();b.getSelection().selectRanges(a)}}},filter:function(b,h){for(var f=b._.removeFormatFilters||[],e=0;eCKEDITOR.env.version),c=l?":not([contenteditable\x3dfalse]):not(.cke_show_blocks_off)":"",d,g;for(f=e=a=m="";d=b.pop();)g=b.length?",":"",f+=".cke_show_blocks "+d+c+g,a+=".cke_show_blocks.cke_contents_ltr "+d+c+g,m+=".cke_show_blocks.cke_contents_rtl "+d+c+g,e+=".cke_show_blocks "+d+c+"{background-image:url("+CKEDITOR.getUrl(k+"images/block_"+d+".png")+")}";CKEDITOR.addCss((f+"{background-repeat:no-repeat;border:1px dotted gray;padding-top:8px}").concat(e, -a+"{background-position:top left;padding-left:8px}",m+"{background-position:top right;padding-right:8px}"));l||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}")}, +e.inline);h(f)}function a(a){if(!a.editable().isInline()){var b=CKEDITOR.instances,e;for(e in b){var c=b[e];"wysiwyg"!=c.mode||c.readOnly||(c=c.document.getBody(),c.setAttribute("contentEditable",!1),c.setAttribute("contentEditable",!0))}a.editable().hasFocus&&(a.toolbox.focus(),a.focus())}}CKEDITOR.plugins.add("maximize",{init:function(b){function h(){var a=d.getViewPaneSize();b.resize(a.width,a.height,null,!0)}if(b.elementMode!=CKEDITOR.ELEMENT_MODE_INLINE){var m=b.lang,c=CKEDITOR.document,d=c.getWindow(), +g,n,y,v=CKEDITOR.TRISTATE_OFF;b.addCommand("maximize",{modes:{wysiwyg:!CKEDITOR.env.iOS,source:!CKEDITOR.env.iOS},readOnly:1,editorFocus:!1,exec:function(){var p=b.container.getFirst(function(a){return a.type==CKEDITOR.NODE_ELEMENT&&a.hasClass("cke_inner")}),q=b.ui.space("contents");if("wysiwyg"==b.mode){var r=b.getSelection();g=r&&r.getRanges();n=d.getScrollPosition()}else{var x=b.editable().$;g=!CKEDITOR.env.ie&&[x.selectionStart,x.selectionEnd];n=[x.scrollLeft,x.scrollTop]}if(this.state==CKEDITOR.TRISTATE_OFF){d.on("resize", +h);y=d.getScrollPosition();for(r=b.container;r=r.getParent();)r.setCustomData("maximize_saved_styles",f(r)),r.setStyle("z-index",b.config.baseFloatZIndex-5);q.setCustomData("maximize_saved_styles",f(q,!0));p.setCustomData("maximize_saved_styles",f(p,!0));q={overflow:CKEDITOR.env.webkit?"":"hidden",width:0,height:0};c.getDocumentElement().setStyles(q);!CKEDITOR.env.gecko&&c.getDocumentElement().setStyle("position","fixed");CKEDITOR.env.gecko&&CKEDITOR.env.quirks||c.getBody().setStyles(q);CKEDITOR.env.ie? +setTimeout(function(){d.$.scrollTo(0,0)},0):d.$.scrollTo(0,0);p.setStyle("position",CKEDITOR.env.gecko&&CKEDITOR.env.quirks?"fixed":"absolute");p.$.offsetLeft;p.setStyles({"z-index":b.config.baseFloatZIndex-5,left:"0px",top:"0px"});p.addClass("cke_maximized");h();q=p.getDocumentPosition();p.setStyles({left:-1*q.x+"px",top:-1*q.y+"px"});CKEDITOR.env.gecko&&a(b)}else if(this.state==CKEDITOR.TRISTATE_ON){d.removeListener("resize",h);for(var r=[q,p],t=0;ta.status||304==a.status||0===a.status||1223==a.status))return null;switch(b){case "text":return a.responseText;case "xml":var e=a.responseXML;return new CKEDITOR.xml(e&&e.firstChild?e:a.responseText);case "arraybuffer":return a.response;default:return null}}function f(a,e,f){var m=!!e,c=b();if(!c)return null;m&&"text"!==f&&"xml"!==f&&(c.responseType=f);c.open("GET",a,m);m&&(c.onreadystatechange=function(){4==c.readyState&&(e(h(c,f)),c=null)});c.send(null); +return m?"":h(c,f)}function e(a,e,f,m,c){var d=b();if(!d)return null;d.open("POST",a,!0);d.onreadystatechange=function(){4==d.readyState&&(m&&m(h(d,c)),d=null)};d.setRequestHeader("Content-type",f||"application/x-www-form-urlencoded; charset\x3dUTF-8");d.send(e)}return{load:function(a,b,e){return f(a,b,e||"text")},post:function(a,b,f,h){return e(a,b,f,h,"text")},loadXml:function(a,b){return f(a,b,"xml")},loadText:function(a,b){return f(a,b,"text")},loadBinary:function(a,b){return f(a,b,"arraybuffer")}}}()}(), +function(){function b(a,b){return CKEDITOR.tools.array.filter(a,function(a){return a.canHandle(b)}).sort(function(a,b){return a.priority===b.priority?0:a.priority-b.priority})}function h(a,b){var c=a.shift();c&&c.handle(b,function(){h(a,b)})}function f(a){var b=CKEDITOR.tools.array.reduce(a,function(a,b){return CKEDITOR.tools.array.isArray(b.filters)?a.concat(b.filters):a},[]);return CKEDITOR.tools.array.filter(b,function(a,d){return CKEDITOR.tools.array.indexOf(b,a)===d})}function e(b,e){var c=0, +d,g;if(!CKEDITOR.tools.array.isArray(b)||0===b.length)return!0;d=CKEDITOR.tools.array.filter(b,function(b){return-1===CKEDITOR.tools.array.indexOf(a,b)});if(0=CKEDITOR.env.version;return!(CKEDITOR.env.webkit&&!CKEDITOR.env.chrome)&&!b},init:function(b){if(this.isSupportedEnvironment()){var h=CKEDITOR.plugins.getPath("pastetools"),f=this.path;b.pasteTools.register({priority:100,filters:[CKEDITOR.getUrl(h+"filter/common.js"),CKEDITOR.getUrl(h+"filter/image.js"),CKEDITOR.getUrl(f+"filter/default.js")],canHandle:function(b){b=b.data;return(b=b.dataTransfer.getData("text/html", +!0)||b.dataValue)?"libreoffice"===CKEDITOR.plugins.pastetools.getContentGeneratorName(b):!1},handle:function(e,a){var f=e.data,h=f.dataValue||CKEDITOR.plugins.pastetools.getClipboardData(f,"text/html");f.dontFilter=!0;h=CKEDITOR.pasteFilters.image(h,b,CKEDITOR.plugins.pastetools.getClipboardData(f,"text/rtf"));f.dataValue=CKEDITOR.pasteFilters.libreoffice(h,b);!0===b.config.forcePasteAsPlainText&&(f.type="text");a()}})}}})}(),function(){CKEDITOR.plugins.add("pastefromword",{requires:"pastetools", +init:function(b){var h=0,f=CKEDITOR.plugins.getPath("pastetools"),e=this.path,a=void 0===b.config.pasteFromWord_inlineImages?!0:b.config.pasteFromWord_inlineImages,f=[CKEDITOR.getUrl(f+"filter/common.js"),CKEDITOR.getUrl(f+"filter/image.js"),CKEDITOR.getUrl(e+"filter/default.js")];b.addCommand("pastefromword",{canUndo:!1,async:!0,exec:function(a,b){h=1;a.execCommand("paste",{type:"html",notification:b&&"undefined"!==typeof b.notification?b.notification:!0})}});CKEDITOR.plugins.clipboard.addPasteButton(b, +"PasteFromWord",{label:b.lang.pastefromword.toolbar,command:"pastefromword",toolbar:"clipboard,50"});b.pasteTools.register({filters:b.config.pasteFromWordCleanupFile?[b.config.pasteFromWordCleanupFile]:f,canHandle:function(a){a=CKEDITOR.plugins.pastetools.getClipboardData(a.data,"text/html");var b=CKEDITOR.plugins.pastetools.getContentGeneratorName(a),e=/(class="?Mso|style=["'][^"]*?\bmso\-|w:WordDocument||<\/font>)/,b=b?"microsoft"===b:e.test(a);return a&&(h||b)},handle:function(e,f){var m= +e.data,c=CKEDITOR.plugins.pastetools.getClipboardData(m,"text/html"),d=CKEDITOR.plugins.pastetools.getClipboardData(m,"text/rtf"),c={dataValue:c,dataTransfer:{"text/rtf":d}};if(!1!==b.fire("pasteFromWord",c)||h){m.dontFilter=!0;if(h||!b.config.pasteFromWordPromptCleanup||confirm(b.lang.pastefromword.confirmCleanup))c.dataValue=CKEDITOR.cleanWord(c.dataValue,b),CKEDITOR.plugins.clipboard.isCustomDataTypesSupported&&a&&CKEDITOR.pasteFilters.image&&(c.dataValue=CKEDITOR.pasteFilters.image(c.dataValue, +b,d)),b.fire("afterPasteFromWord",c),m.dataValue=c.dataValue,!0===b.config.forcePasteAsPlainText?m.type="text":CKEDITOR.plugins.clipboard.isCustomCopyCutSupported||"allow-word"!==b.config.forcePasteAsPlainText||(m.type="html");h=0;f()}}})}})}(),function(){var b={canUndo:!1,async:!0,exec:function(b,f){var e=b.lang,a=CKEDITOR.tools.keystrokeToString(e.common.keyboard,b.getCommandKeystroke(CKEDITOR.env.ie?b.commands.paste:this)),k=f&&"undefined"!==typeof f.notification?f.notification:!f||!f.from||"keystrokeHandler"=== +f.from&&CKEDITOR.env.ie,e=k&&"string"===typeof k?k:e.pastetext.pasteNotification.replace(/%1/,'\x3ckbd aria-label\x3d"'+a.aria+'"\x3e'+a.display+"\x3c/kbd\x3e");b.execCommand("paste",{type:"text",notification:k?e:!1})}};CKEDITOR.plugins.add("pastetext",{requires:"clipboard",init:function(h){var f=CKEDITOR.env.safari?CKEDITOR.CTRL+CKEDITOR.ALT+CKEDITOR.SHIFT+86:CKEDITOR.CTRL+CKEDITOR.SHIFT+86;h.addCommand("pastetext",b);h.setKeystroke(f,"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(b){"html"!=b.data.type&&(b.data.type="text")});h.on("pasteState",function(b){h.getCommand("pastetext").setState(b.data)})}})}(),CKEDITOR.plugins.add("removeformat",{init:function(b){b.addCommand("removeFormat",CKEDITOR.plugins.removeformat.commands.removeformat);b.ui.addButton&&b.ui.addButton("RemoveFormat",{label:b.lang.removeformat.toolbar,command:"removeFormat", +toolbar:"cleanup,10"})}}),CKEDITOR.plugins.removeformat={commands:{removeformat:{exec:function(b){for(var h=b._.removeFormatRegex||(b._.removeFormatRegex=new RegExp("^(?:"+b.config.removeFormatTags.replace(/,/g,"|")+")$","i")),f=b._.removeAttributes||(b._.removeAttributes=b.config.removeFormatAttributes.split(",")),e=CKEDITOR.plugins.removeformat.filter,a=b.getSelection().getRanges(),k=a.createIterator(),l=function(a){return a.type==CKEDITOR.NODE_ELEMENT},m;m=k.getNextRange();){m.enlarge(CKEDITOR.ENLARGE_INLINE); +var c=m.createBookmark(),d=c.startNode,g=c.endNode,n=function(a){for(var c=b.elementPath(a),d=c.elements,g=1,f;(f=d[g])&&!f.equals(c.block)&&!f.equals(c.blockLimit);g++)h.test(f.getName())&&e(b,f)&&a.breakParent(f)};n(d);if(g)for(n(g),d=d.getNextSourceNode(!0,CKEDITOR.NODE_ELEMENT);d&&!d.equals(g);)if(d.isReadOnly()){if(d.getPosition(g)&CKEDITOR.POSITION_CONTAINS)break;d=d.getNext(l)}else n=d.getNextSourceNode(!1,CKEDITOR.NODE_ELEMENT),"img"==d.getName()&&d.data("cke-realelement")||!e(b,d)||(h.test(d.getName())? +d.remove(1):(d.removeAttributes(f),b.fire("removeFormatCleanup",d))),d=n;m.moveToBookmark(c)}b.forceNextSelectionCheck();b.getSelection().selectRanges(a)}}},filter:function(b,h){for(var f=b._.removeFormatFilters||[],e=0;eCKEDITOR.env.version),c=m?":not([contenteditable\x3dfalse]):not(.cke_show_blocks_off)": +"",d,g;for(f=e=a=k="";d=b.pop();)g=b.length?",":"",f+=".cke_show_blocks "+d+c+g,a+=".cke_show_blocks.cke_contents_ltr "+d+c+g,k+=".cke_show_blocks.cke_contents_rtl "+d+c+g,e+=".cke_show_blocks "+d+c+"{background-image:url("+CKEDITOR.getUrl(l+"images/block_"+d+".png")+")}";CKEDITOR.addCss((f+"{background-repeat:no-repeat;border:1px dotted gray;padding-top:8px}").concat(e,a+"{background-position:top left;padding-left:8px}",k+"{background-position:top right;padding-right:8px}"));m||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 f(){e.refresh(h)}if(!h.blockless){var e=h.addCommand("showblocks",b);e.canUndo=!1;h.config.startupOutlineBlocks&&e.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(){e.state!=CKEDITOR.TRISTATE_DISABLED&&e.refresh(h)});h.elementMode==CKEDITOR.ELEMENT_MODE_INLINE&&(h.on("focus",f),h.on("blur",f));h.on("contentDom",function(){e.state!=CKEDITOR.TRISTATE_DISABLED&& e.refresh(h)})}}})}(),function(){var b={preserveState:!0,editorFocus:!1,readOnly:1,exec:function(b){this.toggleState();this.refresh(b)},refresh:function(b){if(b.document){var f=this.state==CKEDITOR.TRISTATE_ON?"attachClass":"removeClass";b.editable()[f]("cke_show_borders")}}};CKEDITOR.plugins.add("showborders",{modes:{wysiwyg:1},onLoad:function(){var b;b=(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(b)},init:function(h){var f=h.addCommand("showborders",b);f.canUndo=!1;!1!==h.config.startupShowBorders&&f.setState(CKEDITOR.TRISTATE_ON);h.on("mode",function(){f.state!=CKEDITOR.TRISTATE_DISABLED&&f.refresh(h)},null,null,100);h.on("contentDom",function(){f.state!=CKEDITOR.TRISTATE_DISABLED&&f.refresh(h)});h.on("removeFormatCleanup",function(b){b=b.data;h.getCommand("showborders").state==CKEDITOR.TRISTATE_ON&&b.is("table")&&(!b.hasAttribute("border")|| @@ -1121,95 +1133,97 @@ this.remove()}}})}(),CKEDITOR.plugins.sourcearea={commands:{source:{modes:{wysiw b.ui.addButton&&b.ui.addButton("Sourcedialog",{label:b.lang.sourcedialog.toolbar,command:"sourcedialog",toolbar:"mode,10"})}}),CKEDITOR.plugins.add("specialchar",{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-ca":1,"en-gb":1,eo:1,es:1,"es-mx":1,et:1,eu:1,fa:1,fi:1,fr:1,"fr-ca":1,gl:1,he:1,hr:1,hu:1,id:1,it:1,ja:1,km:1,ko:1,ku:1,lt:1,lv: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},requires:"dialog",init:function(b){var h=this;CKEDITOR.dialog.add("specialchar",this.path+"dialogs/specialchar.js");b.addCommand("specialchar",{exec:function(){var f=b.langCode,f=h.availableLangs[f]?f:h.availableLangs[f.replace(/-.*/,"")]?f.replace(/-.*/,""):"en";CKEDITOR.scriptLoader.load(CKEDITOR.getUrl(h.path+"dialogs/lang/"+f+".js"),function(){CKEDITOR.tools.extend(b.lang.specialchar,h.langEntries[f]);b.openDialog("specialchar")})},modes:{wysiwyg:1},canUndo:!1});b.ui.addButton&& b.ui.addButton("SpecialChar",{label:b.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(b){var h=b.config,f=b.lang.stylescombo,e={},a=[],m=[];b.on("stylesSet",function(f){if(f=f.data.styles){for(var l,c,d,g=0,n=f.length;g=f)for(l=this.getNextSourceNode(b,CKEDITOR.NODE_ELEMENT);l;){if(l.isVisible()&&0===l.getTabIndex()){m=l;break}l=l.getNextSourceNode(!1,CKEDITOR.NODE_ELEMENT)}else for(l=this.getDocument().getBody().getFirst();l=l.getNextSourceNode(!1,CKEDITOR.NODE_ELEMENT);){if(!e)if(!a&&l.equals(this)){if(a=!0,b){if(!(l=l.getNextSourceNode(!0,CKEDITOR.NODE_ELEMENT)))break;e=1}}else a&&!this.contains(l)&&(e=1);if(l.isVisible()&&!(0>(c=l.getTabIndex()))){if(e&& -c==f){m=l;break}c>f&&(!m||!k||c(l=c.getTabIndex())))if(0>=f){if(e&&0===l){m=c;break}l> -k&&(m=c,k=l)}else{if(e&&l==f){m=c;break}lk)&&(m=c,k=l)}}m&&m.focus()},CKEDITOR.plugins.add("table",{requires:"dialog",init:function(b){function h(b){return CKEDITOR.tools.extend(b||{},{contextSensitive:1,refresh:function(a,b){this.setState(b.contains("table",1)?CKEDITOR.TRISTATE_OFF:CKEDITOR.TRISTATE_DISABLED)}})}if(!b.blockless){var f=b.lang.table;b.addCommand("table",new CKEDITOR.dialogCommand("table",{context:"table",allowedContent:"table{width,height,border-collapse}[align,border,cellpadding,cellspacing,summary];caption tbody thead tfoot;th td tr[scope];td{border*,background-color,vertical-align,width,height}[colspan,rowspan];"+ +else return!0;else{for(var d=f.getAscendant("table").$,c=f.getParent().$.cells,d=new CKEDITOR.dom.element(d.insertRow(-1),b.document),g=0,h=c.length;g=f)for(m=this.getNextSourceNode(b,CKEDITOR.NODE_ELEMENT);m;){if(m.isVisible()&&0===m.getTabIndex()){k=m;break}m=m.getNextSourceNode(!1,CKEDITOR.NODE_ELEMENT)}else for(m=this.getDocument().getBody().getFirst();m=m.getNextSourceNode(!1,CKEDITOR.NODE_ELEMENT);){if(!e)if(!a&&m.equals(this)){if(a=!0,b){if(!(m=m.getNextSourceNode(!0,CKEDITOR.NODE_ELEMENT)))break;e=1}}else a&&!this.contains(m)&&(e=1);if(m.isVisible()&&!(0>(c=m.getTabIndex()))){if(e&& +c==f){k=m;break}c>f&&(!k||!l||c(m=c.getTabIndex())))if(0>=f){if(e&&0===m){k=c;break}m> +l&&(k=c,l=m)}else{if(e&&m==f){k=c;break}ml)&&(k=c,l=m)}}k&&k.focus()},CKEDITOR.plugins.add("table",{requires:"dialog",init:function(b){function h(b){return CKEDITOR.tools.extend(b||{},{contextSensitive:1,refresh:function(a,b){this.setState(b.contains("table",1)?CKEDITOR.TRISTATE_OFF:CKEDITOR.TRISTATE_DISABLED)}})}if(!b.blockless){var f=b.lang.table;b.addCommand("table",new CKEDITOR.dialogCommand("table",{context:"table",allowedContent:"table{width,height,border-collapse}[align,border,cellpadding,cellspacing,summary];caption tbody thead tfoot;th td tr[scope];td{border*,background-color,vertical-align,width,height}[colspan,rowspan];"+ (b.plugins.dialogadvtab?"table"+b.plugins.dialogadvtab.allowedContent():""),requiredContent:"table",contentTransformations:[["table{width}: sizeToStyle","table[width]: sizeToAttribute"],["td: splitBorderShorthand"],[{element:"table",right:function(b){if(b.styles){var a;if(b.styles.border)a=CKEDITOR.tools.style.parse.border(b.styles.border);else if(CKEDITOR.env.ie&&8===CKEDITOR.env.version){var f=b.styles;f["border-left"]&&f["border-left"]===f["border-right"]&&f["border-right"]===f["border-top"]&& f["border-top"]===f["border-bottom"]&&(a=CKEDITOR.tools.style.parse.border(f["border-top"]))}a&&a.style&&"solid"===a.style&&a.width&&0!==parseFloat(a.width)&&(b.attributes.border=1);"collapse"==b.styles["border-collapse"]&&(b.attributes.cellspacing=0)}}}]]}));b.addCommand("tableProperties",new CKEDITOR.dialogCommand("tableProperties",h()));b.addCommand("tableDelete",h({exec:function(b){var a=b.elementPath().contains("table",1);if(a){var f=a.getParent(),h=b.editable();1!=f.getChildCount()||f.is("td", "th")||f.equals(h)||(a=f);b=b.createRange();b.moveToPosition(a,CKEDITOR.POSITION_BEFORE_START);a.remove();b.select()}}}));b.ui.addButton&&b.ui.addButton("Table",{label:f.toolbar,command:"table",toolbar:"insert,30"});CKEDITOR.dialog.add("table",this.path+"dialogs/table.js");CKEDITOR.dialog.add("tableProperties",this.path+"dialogs/table.js");b.addMenuItems&&b.addMenuItems({table:{label:f.menu,command:"tableProperties",group:"table",order:5},tabledelete:{label:f.deleteTable,command:"tableDelete",group:"table", -order:1}});b.on("doubleclick",function(b){b.data.element.is("table")&&(b.data.dialog="tableProperties")});b.contextMenu&&b.contextMenu.addListener(function(){return{tabledelete:CKEDITOR.TRISTATE_OFF,table:CKEDITOR.TRISTATE_OFF}})}}}),function(){function b(a,b){function c(a){return b?b.contains(a)&&a.getAscendant("table",!0).equals(b):!0}function d(a){var b=/^(?:td|th)$/;0c)c=f}return c}function m(c,d){for(var e=p(c)?c:b(c),f=e[0].getAscendant("table"),g=a(e,1),e=a(e),h=d?g:e,k=CKEDITOR.tools.buildTableMap(f),f=[],g=[],e=[],l=k.length,m=0;ml?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(e.$.parentNode);m.length==a&&(d[0].moveToPosition(e,CKEDITOR.POSITION_AFTER_END),d[0].select(),e.remove());return k}function l(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 c(a){if(a instanceof CKEDITOR.dom.selection){var e= -a.getRanges(),f=b(a),g=f[0]&&f[0].getAscendant("table"),h;a:{var k=0;h=f.length-1;for(var l={},m,n;m=f[k++];)CKEDITOR.dom.element.setMarker(l,m,"delete_cell",!0);for(k=0;m=f[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=f[0].getParent();(k=k.getPrevious())?h=k.getLast():(k=f[h].getParent(),h=(k=k.getNext())?k.getChild(0):null)}a.reset();for(a= -f.length-1;0<=a;a--)c(f[a]);h?d(h,!0):g&&(e[0].moveToPosition(g,CKEDITOR.POSITION_BEFORE_START),e[0].select(),g.remove())}else a instanceof CKEDITOR.dom.element&&(e=a.getParent(),1==e.getChildCount()?e.remove():a.remove())}function d(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 g(a,b,c){a=a[b]; -if("undefined"==typeof c)return a;for(b=0;a&&be.length)||(f=a.getCommonAncestor())&&f.type==CKEDITOR.NODE_ELEMENT&&f.is("table"))return!1;a=e[0];f=a.getAscendant("table");var h=CKEDITOR.tools.buildTableMap(f),k=h.length,l=h[0].length,m=a.getParent().$.rowIndex,n=g(h,m,a),p;if(c){var w;try{var y=parseInt(a.getAttribute("rowspan"),10)||1;p=parseInt(a.getAttribute("colspan"), -10)||1;w=h["up"==c?m-y:"down"==c?m+y:m]["left"==c?n-p:"right"==c?n+p:n]}catch(L){return!1}if(!w||a.$==w)return!1;e["up"==c||"left"==c?"unshift":"push"](new CKEDITOR.dom.element(w))}c=a.getDocument();var C=m,y=w=0,O=!d&&new CKEDITOR.dom.documentFragment(c),I=0;for(c=0;c=l?a.removeAttribute("rowSpan"):a.$.rowSpan=w;w>=k?a.removeAttribute("colSpan"):a.$.colSpan=y;d=new CKEDITOR.dom.nodeList(f.$.rows);e=d.count();for(c=e-1;0<=c;c--)f=d.getItem(c),f.$.cells.length||(f.remove(),e++);return a}function y(a,c){var d=b(a);if(1< +order:1}});b.on("doubleclick",function(b){b.data.element.is("table")&&(b.data.dialog="tableProperties")});b.contextMenu&&b.contextMenu.addListener(function(){return{tabledelete:CKEDITOR.TRISTATE_OFF,table:CKEDITOR.TRISTATE_OFF}})}}}),function(){function b(a,b){function c(a){return b?b.contains(a)&&a.getAscendant("table",!0).equals(b):!0}function d(a){var b=/^(?:td|th)$/;0c)c=g}return c}function k(c,d){for(var e=p(c)?c:b(c),g=e[0].getAscendant("table"),f=a(e,1),e=a(e),h=d?f:e,k=CKEDITOR.tools.buildTableMap(g),g=[],f=[],e=[],l=k.length,m=0;ml?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(e.$.parentNode);m.length==a&&(d[0].moveToPosition(e,CKEDITOR.POSITION_AFTER_END),d[0].select(),e.remove());return k}function m(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 c(a){if(a instanceof CKEDITOR.dom.selection){var e= +a.getRanges(),g=b(a),f=g[0]&&g[0].getAscendant("table"),h;a:{var k=0;h=g.length-1;for(var l={},m,n;m=g[k++];)CKEDITOR.dom.element.setMarker(l,m,"delete_cell",!0);for(k=0;m=g[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=g[0].getParent();(k=k.getPrevious())?h=k.getLast():(k=g[h].getParent(),h=(k=k.getNext())?k.getChild(0):null)}a.reset();for(a= +g.length-1;0<=a;a--)c(g[a]);h?d(h,!0):f&&(e[0].moveToPosition(f,CKEDITOR.POSITION_BEFORE_START),e[0].select(),f.remove())}else a instanceof CKEDITOR.dom.element&&(e=a.getParent(),1==e.getChildCount()?e.remove():a.remove())}function d(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 g(a,b,c){a=a[b]; +if("undefined"==typeof c)return a;for(b=0;a&&be.length)||(f=a.getCommonAncestor())&&f.type==CKEDITOR.NODE_ELEMENT&&f.is("table"))return!1;a=e[0];f=a.getAscendant("table");var h=CKEDITOR.tools.buildTableMap(f),k=h.length,l=h[0].length,m=a.getParent().$.rowIndex,n=g(h,m,a),p;if(c){var v;try{var y=parseInt(a.getAttribute("rowspan"),10)||1;p=parseInt(a.getAttribute("colspan"), +10)||1;v=h["up"==c?m-y:"down"==c?m+y:m]["left"==c?n-p:"right"==c?n+p:n]}catch(M){return!1}if(!v||a.$==v)return!1;e["up"==c||"left"==c?"unshift":"push"](new CKEDITOR.dom.element(v))}c=a.getDocument();var D=m,y=v=0,N=!d&&new CKEDITOR.dom.documentFragment(c),I=0;for(c=0;c=l?a.removeAttribute("rowSpan"):a.$.rowSpan=v;v>=k?a.removeAttribute("colSpan"):a.$.colSpan=y;d=new CKEDITOR.dom.nodeList(f.$.rows);e=d.count();for(c=e-1;0<=c;c--)f=d.getItem(c),f.$.cells.length||(f.remove(),e++);return a}function y(a,c){var d=b(a);if(1< d.length)return!1;if(c)return!0;var d=d[0],e=d.getParent(),f=e.getAscendant("table"),h=CKEDITOR.tools.buildTableMap(f),k=e.$.rowIndex,l=g(h,k,d),m=d.$.rowSpan,n;if(1l){e.insertBefore(new CKEDITOR.dom.element(p));break}else p=null;p||f.append(e)}else for(m=n=1,f=e.clone(),f.insertAfter(e),f.append(e=d.clone()),p=g(h,k),l=0;le);n++){k[m+n]||(k[m+n]=[]);for(var y=0;y=a)break}}return k},function(){function b(a){return CKEDITOR.env.ie?a.$.clientWidth:parseInt(a.getComputedStyle("width"),10)}function h(a,b){var e=a.getComputedStyle("border-"+ +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:e,insertRow:h,insertColumn:k,getSelectedCells:b};CKEDITOR.plugins.add("tabletools",CKEDITOR.plugins.tabletools)}(),CKEDITOR.tools.buildTableMap=function(b,h,f,e,a){b=b.$.rows;f=f||0;e="number"===typeof e?e:b.length-1;a="number"===typeof a? +a:-1;var k=-1,l=[];for(h=h||0;h<=e;h++){k++;!l[k]&&(l[k]=[]);for(var m=-1,c=f;c<=(-1===a?b[h].cells.length-1:a);c++){var d=b[h].cells[c];if(!d)break;for(m++;l[k][m];)m++;for(var g=isNaN(d.colSpan)?1:d.colSpan,d=isNaN(d.rowSpan)?1:d.rowSpan,n=0;ne);n++){l[k+n]||(l[k+n]=[]);for(var y=0;y=a)break}}return l},function(){function b(a){return CKEDITOR.env.ie?a.$.clientWidth:parseInt(a.getComputedStyle("width"),10)}function h(a,b){var e=a.getComputedStyle("border-"+ b+"-width"),f={thin:"0px",medium:"1px",thick:"2px"};0>e.indexOf("px")&&(e=e in f&&"none"!=a.getComputedStyle("border-style")?f[e]:0);return parseFloat(e)}function f(a){var b=[],e={},f="rtl"===a.getComputedStyle("direction"),k=CKEDITOR.tools.array.zip((new CKEDITOR.dom.nodeList(a.$.rows)).toArray(),CKEDITOR.tools.buildTableMap(a));CKEDITOR.tools.array.forEach(k,function(k){var l=k[0].$;k=k[1];var m=-1,r=0,y=null;l?(r=new CKEDITOR.dom.element(l),y={height:r.$.offsetHeight,position:r.getDocumentPosition()}): -y=void 0;for(var l=CKEDITOR.env.ie&&!CKEDITOR.env.edge,u="collapse"===a.getComputedStyle("border-collapse"),r=y.height,y=y.position,z=0;z=p.x&&a<=p.x+p.width&&b>=p.y&&b<=p.y+p.height))return p= -null,x=z=0,t.removeListener("mouseup",y),r.removeListener("mousedown",m),r.removeListener("mousemove",w),t.getBody().setStyle("cursor","auto"),l?r.remove():r.hide(),0;var c=a-Math.round(r.$.offsetWidth/2);if(x){if(c==D||c==A)return 1;c=Math.max(c,D);c=Math.min(c,A);z=c-u}r.setStyle("left",k(c));return 1}}function m(a){var b=a.data.getTarget();if("mouseout"==a.name){if(!b.is("table"))return;for(var e=new CKEDITOR.dom.element(a.data.$.relatedTarget||a.data.$.toElement);e&&e.$&&!e.equals(b)&&!e.is("body");)e= -e.getParent();if(!e||e.equals(b))return}b.getAscendant("table",1).removeCustomData("_cke_table_pillars");a.removeListener()}var k=CKEDITOR.tools.cssLength,l=CKEDITOR.env.ie&&(CKEDITOR.env.ie7Compat||CKEDITOR.env.quirks);CKEDITOR.plugins.add("tableresize",{requires:"tabletools",init:function(b){b.on("contentDom",function(){var d,g=b.editable();g.attachListener(g.isInline()?g:b.document,"mousemove",function(g){g=g.data;var h=g.getTarget();if(h.type==CKEDITOR.NODE_ELEMENT){var k=g.getPageOffset().x, -l=g.getPageOffset().y;if(d&&d.move(k,l))e(g);else if(h.is("table")||h.getAscendant({thead:1,tbody:1,tfoot:1},1))if(g=h.getAscendant("table",1),b.editable().contains(g)){(h=g.getCustomData("_cke_table_pillars"))||(g.setCustomData("_cke_table_pillars",h=f(g)),g.on("mouseout",m),g.on("mousedown",m));a:{g=h;for(var h=0,t=g.length;h=r.x&&k<=r.x+r.width&&l>=r.y&&l<=r.y+r.height){k=r;break a}}k=null}k&&(!d&&(d=new a(b)),d.attachTo(k))}}})})}})}(),"use strict",function(){function b(a, -b){return CKEDITOR.tools.array.reduce(b,function(a,b){return b(a)},a)}var h=[CKEDITOR.CTRL+90,CKEDITOR.CTRL+89,CKEDITOR.CTRL+CKEDITOR.SHIFT+90],f={8:1,46:1};CKEDITOR.plugins.add("undo",{init:function(a){function b(a){l.enabled&&!1!==a.data.command.canUndo&&l.save()}function f(){l.enabled=a.readOnly?!1:"wysiwyg"==a.mode;l.onChange()}var l=a.undoManager=new e(a),m=l.editingHandler=new k(l),w=a.addCommand("undo",{exec:function(){l.undo()&&(a.selectionChange(),this.fire("afterUndo"))},startDisabled:!0, -canUndo:!1}),p=a.addCommand("redo",{exec:function(){l.redo()&&(a.selectionChange(),this.fire("afterRedo"))},startDisabled:!0,canUndo:!1});a.setKeystroke([[h[0],"undo"],[h[1],"redo"],[h[2],"redo"]]);l.onChange=function(){w.setState(l.undoable()?CKEDITOR.TRISTATE_OFF:CKEDITOR.TRISTATE_DISABLED);p.setState(l.redoable()?CKEDITOR.TRISTATE_OFF:CKEDITOR.TRISTATE_DISABLED)};a.on("beforeCommandExec",b);a.on("afterCommandExec",b);a.on("saveSnapshot",function(a){l.save(a.data&&a.data.contentOnly)});a.on("contentDom", -m.attachListeners,m);a.on("instanceReady",function(){a.fire("saveSnapshot")});a.on("beforeModeUnload",function(){"wysiwyg"==a.mode&&l.save(!0)});a.on("mode",f);a.on("readOnly",f);a.ui.addButton&&(a.ui.addButton("Undo",{label:a.lang.undo.undo,command:"undo",toolbar:"undo,10"}),a.ui.addButton("Redo",{label:a.lang.undo.redo,command:"redo",toolbar:"undo,20"}));a.resetUndo=function(){l.reset();a.fire("saveSnapshot")};a.on("updateSnapshot",function(){l.currentImage&&l.update()});a.on("lockSnapshot",function(a){a= -a.data;l.lock(a&&a.dontUpdate,a&&a.forceUpdate)});a.on("unlockSnapshot",l.unlock,l)}});CKEDITOR.plugins.undo={};var e=CKEDITOR.plugins.undo.UndoManager=function(a){this.strokesRecorded=[0,0];this.locked=null;this.previousKeyGroup=-1;this.limit=a.config.undoStackSize||20;this.strokesLimit=25;this._filterRules=[];this.editor=a;this.reset();CKEDITOR.env.ie&&this.addFilterRule(function(a){return a.replace(/\s+data-cke-expando=".*?"/g,"")})};e.prototype={type:function(a,b){var f=e.getKeyGroup(a),h=this.strokesRecorded[f]+ -1;b=b||h>=this.strokesLimit;this.typing||(this.hasUndo=this.typing=!0,this.hasRedo=!1,this.onChange());b?(h=0,this.editor.fire("saveSnapshot")):this.editor.fire("change");this.strokesRecorded[f]=h;this.previousKeyGroup=f},keyGroupChanged:function(a){return e.getKeyGroup(a)!=this.previousKeyGroup},reset:function(){this.snapshots=[];this.index=-1;this.currentImage=null;this.hasRedo=this.hasUndo=!1;this.locked=null;this.resetType()},resetType:function(){this.strokesRecorded=[0,0];this.typing=!1;this.previousKeyGroup= +y=void 0;for(var l=CKEDITOR.env.ie&&!CKEDITOR.env.edge,t="collapse"===a.getComputedStyle("border-collapse"),r=y.height,y=y.position,z=0;z=p.x&&a<=p.x+p.width&&b>=p.y&&b<=p.y+p.height))return p= +null,x=z=0,q.removeListener("mouseup",k),r.removeListener("mousedown",f),r.removeListener("mousemove",v),q.getBody().setStyle("cursor","auto"),m?r.remove():r.hide(),0;var c=a-Math.round(r.$.offsetWidth/2);if(x){if(c==C||c==A)return 1;c=Math.max(c,C);c=Math.min(c,A);z=c-t}r.setStyle("left",l(c));return 1}}function k(a){var b=a.data.getTarget();if("mouseout"==a.name){if(!b.is("table"))return;for(var e=new CKEDITOR.dom.element(a.data.$.relatedTarget||a.data.$.toElement);e&&e.$&&!e.equals(b)&&!e.is("body");)e= +e.getParent();if(!e||e.equals(b))return}b.getAscendant("table",1).removeCustomData("_cke_table_pillars");a.removeListener()}var l=CKEDITOR.tools.cssLength,m=CKEDITOR.env.ie&&(CKEDITOR.env.ie7Compat||CKEDITOR.env.quirks);CKEDITOR.plugins.add("tableresize",{requires:"tabletools",init:function(b){b.on("contentDom",function(){var d,g=b.editable();g.attachListener(g.isInline()?g:b.document,"mousemove",function(g){g=g.data;var h=g.getTarget();if(h.type==CKEDITOR.NODE_ELEMENT){var l=g.getPageOffset().x, +m=g.getPageOffset().y;if(d&&d.move(l,m))e(g);else if(h.is("table")||h.getAscendant({thead:1,tbody:1,tfoot:1},1))if(g=h.getAscendant("table",1),b.editable().contains(g)){(h=g.getCustomData("_cke_table_pillars"))||(g.setCustomData("_cke_table_pillars",h=f(g)),g.on("mouseout",k),g.on("mousedown",k));a:{g=h;for(var h=0,q=g.length;h=r.x&&l<=r.x+r.width&&m>=r.y&&m<=r.y+r.height){l=r;break a}}l=null}l&&(!d&&(d=new a(b)),d.attachTo(l))}}})})}})}(),"use strict",function(){function b(a, +b){return CKEDITOR.tools.array.reduce(b,function(a,b){return b(a)},a)}var h=[CKEDITOR.CTRL+90,CKEDITOR.CTRL+89,CKEDITOR.CTRL+CKEDITOR.SHIFT+90],f={8:1,46:1};CKEDITOR.plugins.add("undo",{init:function(a){function b(a){f.enabled&&!1!==a.data.command.canUndo&&f.save()}function g(){f.enabled=a.readOnly?!1:"wysiwyg"==a.mode;f.onChange()}var f=a.undoManager=new e(a),k=f.editingHandler=new l(f),m=a.addCommand("undo",{exec:function(){f.undo()&&(a.selectionChange(),this.fire("afterUndo"))},startDisabled:!0, +canUndo:!1}),p=a.addCommand("redo",{exec:function(){f.redo()&&(a.selectionChange(),this.fire("afterRedo"))},startDisabled:!0,canUndo:!1});a.setKeystroke([[h[0],"undo"],[h[1],"redo"],[h[2],"redo"]]);f.onChange=function(){m.setState(f.undoable()?CKEDITOR.TRISTATE_OFF:CKEDITOR.TRISTATE_DISABLED);p.setState(f.redoable()?CKEDITOR.TRISTATE_OFF:CKEDITOR.TRISTATE_DISABLED)};a.on("beforeCommandExec",b);a.on("afterCommandExec",b);a.on("saveSnapshot",function(a){f.save(a.data&&a.data.contentOnly)});a.on("contentDom", +k.attachListeners,k);a.on("instanceReady",function(){a.fire("saveSnapshot")});a.on("beforeModeUnload",function(){"wysiwyg"==a.mode&&f.save(!0)});a.on("mode",g);a.on("readOnly",g);a.ui.addButton&&(a.ui.addButton("Undo",{label:a.lang.undo.undo,command:"undo",toolbar:"undo,10"}),a.ui.addButton("Redo",{label:a.lang.undo.redo,command:"redo",toolbar:"undo,20"}));a.resetUndo=function(){f.reset();a.fire("saveSnapshot")};a.on("updateSnapshot",function(){f.currentImage&&f.update()});a.on("lockSnapshot",function(a){a= +a.data;f.lock(a&&a.dontUpdate,a&&a.forceUpdate)});a.on("unlockSnapshot",f.unlock,f)}});CKEDITOR.plugins.undo={};var e=CKEDITOR.plugins.undo.UndoManager=function(a){this.strokesRecorded=[0,0];this.locked=null;this.previousKeyGroup=-1;this.limit=a.config.undoStackSize||20;this.strokesLimit=25;this._filterRules=[];this.editor=a;this.reset();CKEDITOR.env.ie&&this.addFilterRule(function(a){return a.replace(/\s+data-cke-expando=".*?"/g,"")})};e.prototype={type:function(a,b){var g=e.getKeyGroup(a),f=this.strokesRecorded[g]+ +1;b=b||f>=this.strokesLimit;this.typing||(this.hasUndo=this.typing=!0,this.hasRedo=!1,this.onChange());b?(f=0,this.editor.fire("saveSnapshot")):this.editor.fire("change");this.strokesRecorded[g]=f;this.previousKeyGroup=g},keyGroupChanged:function(a){return e.getKeyGroup(a)!=this.previousKeyGroup},reset:function(){this.snapshots=[];this.index=-1;this.currentImage=null;this.hasRedo=this.hasUndo=!1;this.locked=null;this.resetType()},resetType:function(){this.strokesRecorded=[0,0];this.typing=!1;this.previousKeyGroup= -1},refreshState:function(){this.hasUndo=!!this.getNextImage(!0);this.hasRedo=!!this.getNextImage(!1);this.resetType();this.onChange()},save:function(b,d,e){var f=this.editor;if(this.locked||"ready"!=f.status||"wysiwyg"!=f.mode)return!1;var h=f.editable();if(!h||"ready"!=h.status)return!1;h=this.snapshots;d||(d=new a(f));if(!1===d.contents)return!1;if(this.currentImage)if(d.equalsContent(this.currentImage)){if(b||d.equalsSelection(this.currentImage))return!1}else!1!==e&&f.fire("change");h.splice(this.index+ 1,h.length-this.index-1);h.length==this.limit&&h.shift();this.index=h.push(d)-1;this.currentImage=d;!1!==e&&this.refreshState();return!0},restoreImage:function(a){var b=this.editor,e;a.bookmarks&&(b.focus(),e=b.getSelection());this.locked={level:999};this.editor.loadSnapshot(a.contents);a.bookmarks?e.selectBookmarks(a.bookmarks):CKEDITOR.env.ie&&(e=this.editor.document.getBody().$.createTextRange(),e.collapse(!0),e.select());this.locked=null;this.index=a.index;this.currentImage=this.snapshots[this.index]; this.update();this.refreshState();b.fire("change")},getNextImage:function(a){var b=this.snapshots,e=this.currentImage,f;if(e)if(a)for(f=this.index-1;0<=f;f--){if(a=b[f],!e.equalsContent(a))return a.index=f,a}else for(f=this.index+1;f=this.undoManager.strokesLimit&&(this.undoManager.type(a.keyCode,!0),this.keyEventsStack.resetInputs())}},onKeyup:function(b){var d=this.undoManager;b=b.data.getKey();var f=this.keyEventsStack.getTotalInputs();this.keyEventsStack.remove(b);if(!(e.ieFunctionalKeysBug(b)&&this.lastKeydownImage&&this.lastKeydownImage.equalsContent(new a(d.editor,!0))))if(0CKEDITOR.env.version&&e.enterMode!=CKEDITOR.ENTER_DIV&&b("div");if(CKEDITOR.env.webkit||CKEDITOR.env.ie&& 10this.$.offsetHeight){var c= e.createRange();c[33==b?"moveToElementEditStart":"moveToElementEditEnd"](this);c.select();a.data.preventDefault()}});CKEDITOR.env.ie&&this.attachListener(f,"blur",function(){try{f.$.selection.empty()}catch(a){}});CKEDITOR.env.iOS&&this.attachListener(f,"touchend",function(){a.focus()});c=e.document.getElementsByTag("title").getItem(0);c.data("cke-title",c.getText());CKEDITOR.env.ie&&(e.document.$.title=this._.docTitle);CKEDITOR.tools.setTimeout(function(){"unloaded"==this.status&&(this.status="ready"); e.fire("contentDom");this._.isPendingFocus&&(e.focus(),this._.isPendingFocus=!1);setTimeout(function(){e.fire("dataReady")},0)},0,this)}}function h(a){function b(){var c;a.editable().attachListener(a,"selectionChange",function(){var b=a.getSelection().getSelectedElement();b&&(c&&(c.detachEvent("onresizestart",e),c=null),b.$.attachEvent("onresizestart",e),c=b.$)})}function e(a){a.returnValue=!1}if(CKEDITOR.env.gecko)try{var f=a.document.$;f.execCommand("enableObjectResizing",!1,!a.config.disableObjectResizing); -f.execCommand("enableInlineTableEditing",!1,!a.config.disableNativeTableHandles)}catch(c){}else CKEDITOR.env.ie&&11>CKEDITOR.env.version&&a.config.disableObjectResizing&&b(a)}function f(){var a=[];if(8<=CKEDITOR.document.$.documentMode){a.push("html.CSS1Compat [contenteditable\x3dfalse]{min-height:0 !important}");var b=[],e;for(e in CKEDITOR.dtd.$removeEmpty)b.push("html.CSS1Compat "+e+"[contenteditable\x3dfalse]");a.push(b.join(",")+"{display:inline-block}")}else CKEDITOR.env.gecko&&(a.push("html{height:100% !important}"), -a.push("img:-moz-broken{-moz-force-broken-image-icon:1;min-width:24px;min-height:24px}"));a.push("html{cursor:text;*cursor:auto}");a.push("img,input,textarea{cursor:default}");return a.join("\n")}var e;CKEDITOR.plugins.add("wysiwygarea",{init:function(a){a.config.fullPage&&a.addFeature({allowedContent:"html head title; style [media,type]; body (*)[id]; meta link [*]",requiredContent:"body"});a.addMode("wysiwyg",function(b){function f(d){d&&d.removeListener();a.isDestroyed()||a.isDetached()||(a.editable(new e(a, -c.$.contentWindow.document.body)),a.setData(a.getData(1),b))}var h="document.open();"+(CKEDITOR.env.ie?"("+CKEDITOR.tools.fixDomain+")();":"")+"document.close();",h=CKEDITOR.env.air?"javascript:void(0)":CKEDITOR.env.ie&&!CKEDITOR.env.edge?"javascript:void(function(){"+encodeURIComponent(h)+"}())":"",c=CKEDITOR.dom.element.createFromHtml('\x3ciframe src\x3d"'+h+'" frameBorder\x3d"0"\x3e\x3c/iframe\x3e');c.setStyles({width:"100%",height:"100%"});c.addClass("cke_wysiwyg_frame").addClass("cke_reset"); -h=a.ui.space("contents");h.append(c);var d=CKEDITOR.env.ie&&!CKEDITOR.env.edge||CKEDITOR.env.gecko;if(d)c.on("load",f);var g=a.title,n=a.fire("ariaEditorHelpLabel",{}).label;g&&(CKEDITOR.env.ie&&n&&(g+=", "+n),c.setAttribute("title",g));if(n){var g=CKEDITOR.tools.getNextId(),y=CKEDITOR.dom.element.createFromHtml('\x3cspan id\x3d"'+g+'" class\x3d"cke_voice_label"\x3e'+n+"\x3c/span\x3e");h.append(y,1);c.setAttribute("aria-describedby",g)}a.on("beforeModeUnload",function(a){a.removeListener();y&&y.remove()}); -c.setAttributes({tabIndex:a.tabIndex,allowTransparency:"true"});!d&&f();a.fire("ariaWidget",c)})}});CKEDITOR.editor.prototype.addContentsCss=function(a){var b=this.config,e=b.contentsCss;CKEDITOR.tools.isArray(e)||(b.contentsCss=e?[e]:[]);b.contentsCss.push(a)};e=CKEDITOR.tools.createClass({$:function(){this.base.apply(this,arguments);this._.frameLoadedHandler=CKEDITOR.tools.addFunction(function(a){CKEDITOR.tools.setTimeout(b,0,this,a)},this);this._.docTitle=this.getWindow().getFrame().getAttribute("title")}, -base:CKEDITOR.editable,proto:{setData:function(a,b){var e=this.editor;if(b)this.setHtml(a),this.fixInitialSelection(),e.fire("dataReady");else{this._.isLoadingData=!0;e._.dataStore={id:1};var h=e.config,c=h.fullPage,d=h.docType,g=CKEDITOR.tools.buildStyleHtml(f()).replace(/ + + + + + + +

Colorbox Demonstration

+

Elastic Transition

+

Grouped Photo 1

+

Grouped Photo 2

+

Grouped Photo 3

+ +

Fade Transition

+

Grouped Photo 1

+

Grouped Photo 2

+

Grouped Photo 3

+ +

No Transition + fixed width and height (75% of screen size)

+

Grouped Photo 1

+

Grouped Photo 2

+

Grouped Photo 3

+ +

Slideshow

+

Grouped Photo 1

+

Grouped Photo 2

+

Grouped Photo 3

+ +

Other Content Types

+

Outside HTML (Ajax)

+

Flash / Video (Iframe/Direct Link To YouTube)

+

Flash / Video (Iframe/Direct Link To Vimeo)

+

Outside Webpage (Iframe)

+

Inline HTML

+ +

Demonstration of using callbacks

+

Example with alerts. Callbacks and event-hooks allow users to extend functionality without having to rewrite parts of the plugin.

+ + +

Retina Images

+

Retina

+

Non-Retina

+ + +
+
+

This content comes from a hidden element on this page.

+

The inline option preserves bound JavaScript events and changes, and it puts the content back where it came from when it is closed.

+

Click me, it will be preserved!

+ +

If you try to open a new Colorbox while it is already open, it will update itself with the new content.

+

Updating Content Example:
+ Click here to load new content

+
+
+ + \ No newline at end of file diff --git a/web/libraries/colorbox/example2/colorbox.css b/web/libraries/colorbox/example2/colorbox.css new file mode 100644 index 00000000..208b8ee6 --- /dev/null +++ b/web/libraries/colorbox/example2/colorbox.css @@ -0,0 +1,50 @@ +/* + Colorbox Core Style: + The following CSS is consistent between example themes and should not be altered. +*/ +#colorbox, #cboxOverlay, #cboxWrapper{position:absolute; top:0; left:0; z-index:9999; overflow:hidden; -webkit-transform: translate3d(0,0,0);} +#cboxWrapper {max-width:none;} +#cboxOverlay{position:fixed; width:100%; height:100%;} +#cboxMiddleLeft, #cboxBottomLeft{clear:left;} +#cboxContent{position:relative;} +#cboxLoadedContent{overflow:auto; -webkit-overflow-scrolling: touch;} +#cboxTitle{margin:0;} +#cboxLoadingOverlay, #cboxLoadingGraphic{position:absolute; top:0; left:0; width:100%; height:100%;} +#cboxPrevious, #cboxNext, #cboxClose, #cboxSlideshow{cursor:pointer;} +.cboxPhoto{float:left; margin:auto; border:0; display:block; max-width:none; -ms-interpolation-mode:bicubic;} +.cboxIframe{width:100%; height:100%; display:block; border:0; padding:0; margin:0;} +#colorbox, #cboxContent, #cboxLoadedContent{box-sizing:content-box; -moz-box-sizing:content-box; -webkit-box-sizing:content-box;} + +/* + User Style: + Change the following styles to modify the appearance of Colorbox. They are + ordered & tabbed in a way that represents the nesting of the generated HTML. +*/ +#cboxOverlay{background:#fff; opacity: 0.9; filter: alpha(opacity = 90);} +#colorbox{outline:0;} + #cboxContent{margin-top:32px; overflow:visible; background:#000;} + .cboxIframe{background:#fff;} + #cboxError{padding:50px; border:1px solid #ccc;} + #cboxLoadedContent{background:#000; padding:1px;} + #cboxLoadingGraphic{background:url(images/loading.gif) no-repeat center center;} + #cboxLoadingOverlay{background:#000;} + #cboxTitle{position:absolute; top:-22px; left:0; color:#000;} + #cboxCurrent{position:absolute; top:-22px; right:205px; text-indent:-9999px;} + + /* these elements are buttons, and may need to have additional styles reset to avoid unwanted base styles */ + #cboxPrevious, #cboxNext, #cboxSlideshow, #cboxClose {border:0; padding:0; margin:0; overflow:visible; text-indent:-9999px; width:20px; height:20px; position:absolute; top:-20px; background:url(images/controls.png) no-repeat 0 0;} + + /* avoid outlines on :active (mouseclick), but preserve outlines on :focus (tabbed navigating) */ + #cboxPrevious:active, #cboxNext:active, #cboxSlideshow:active, #cboxClose:active {outline:0;} + + #cboxPrevious{background-position:0px 0px; right:44px;} + #cboxPrevious:hover{background-position:0px -25px;} + #cboxNext{background-position:-25px 0px; right:22px;} + #cboxNext:hover{background-position:-25px -25px;} + #cboxClose{background-position:-50px 0px; right:0;} + #cboxClose:hover{background-position:-50px -25px;} + .cboxSlideshow_on #cboxPrevious, .cboxSlideshow_off #cboxPrevious{right:66px;} + .cboxSlideshow_on #cboxSlideshow{background-position:-75px -25px; right:44px;} + .cboxSlideshow_on #cboxSlideshow:hover{background-position:-100px -25px;} + .cboxSlideshow_off #cboxSlideshow{background-position:-100px 0px; right:44px;} + .cboxSlideshow_off #cboxSlideshow:hover{background-position:-75px -25px;} diff --git a/web/libraries/colorbox/example2/images/controls.png b/web/libraries/colorbox/example2/images/controls.png new file mode 100644 index 00000000..36f52699 Binary files /dev/null and b/web/libraries/colorbox/example2/images/controls.png differ diff --git a/web/libraries/colorbox/example2/images/loading.gif b/web/libraries/colorbox/example2/images/loading.gif new file mode 100644 index 00000000..a32df5c0 Binary files /dev/null and b/web/libraries/colorbox/example2/images/loading.gif differ diff --git a/web/libraries/colorbox/example2/index.html b/web/libraries/colorbox/example2/index.html new file mode 100644 index 00000000..8f10b930 --- /dev/null +++ b/web/libraries/colorbox/example2/index.html @@ -0,0 +1,95 @@ + + + + + Colorbox Examples + + + + + + + +

Colorbox Demonstration

+

Elastic Transition

+

Grouped Photo 1

+

Grouped Photo 2

+

Grouped Photo 3

+ +

Fade Transition

+

Grouped Photo 1

+

Grouped Photo 2

+

Grouped Photo 3

+ +

No Transition + fixed width and height (75% of screen size)

+

Grouped Photo 1

+

Grouped Photo 2

+

Grouped Photo 3

+ +

Slideshow

+

Grouped Photo 1

+

Grouped Photo 2

+

Grouped Photo 3

+ +

Other Content Types

+

Outside HTML (Ajax)

+

Flash / Video (Iframe/Direct Link To YouTube)

+

Flash / Video (Iframe/Direct Link To Vimeo)

+

Outside Webpage (Iframe)

+

Inline HTML

+ +

Demonstration of using callbacks

+

Example with alerts. Callbacks and event-hooks allow users to extend functionality without having to rewrite parts of the plugin.

+ + +

Retina Images

+

Retina

+

Non-Retina

+ + +
+
+

This content comes from a hidden element on this page.

+

The inline option preserves bound JavaScript events and changes, and it puts the content back where it came from when it is closed.

+

Click me, it will be preserved!

+ +

If you try to open a new Colorbox while it is already open, it will update itself with the new content.

+

Updating Content Example:
+ Click here to load new content

+
+
+ + \ No newline at end of file diff --git a/web/libraries/colorbox/example3/colorbox.css b/web/libraries/colorbox/example3/colorbox.css new file mode 100644 index 00000000..0bf753f0 --- /dev/null +++ b/web/libraries/colorbox/example3/colorbox.css @@ -0,0 +1,45 @@ +/* + Colorbox Core Style: + The following CSS is consistent between example themes and should not be altered. +*/ +#colorbox, #cboxOverlay, #cboxWrapper{position:absolute; top:0; left:0; z-index:9999; overflow:hidden; -webkit-transform: translate3d(0,0,0);} +#cboxWrapper {max-width:none;} +#cboxOverlay{position:fixed; width:100%; height:100%;} +#cboxMiddleLeft, #cboxBottomLeft{clear:left;} +#cboxContent{position:relative;} +#cboxLoadedContent{overflow:auto; -webkit-overflow-scrolling: touch;} +#cboxTitle{margin:0;} +#cboxLoadingOverlay, #cboxLoadingGraphic{position:absolute; top:0; left:0; width:100%; height:100%;} +#cboxPrevious, #cboxNext, #cboxClose, #cboxSlideshow{cursor:pointer;} +.cboxPhoto{float:left; margin:auto; border:0; display:block; max-width:none; -ms-interpolation-mode:bicubic;} +.cboxIframe{width:100%; height:100%; display:block; border:0; padding:0; margin:0;} +#colorbox, #cboxContent, #cboxLoadedContent{box-sizing:content-box; -moz-box-sizing:content-box; -webkit-box-sizing:content-box;} + +/* + User Style: + Change the following styles to modify the appearance of Colorbox. They are + ordered & tabbed in a way that represents the nesting of the generated HTML. +*/ +#cboxOverlay{background:#000; opacity: 0.9; filter: alpha(opacity = 90);} +#colorbox{outline:0;} + #cboxContent{margin-top:20px;background:#000;} + .cboxIframe{background:#fff;} + #cboxError{padding:50px; border:1px solid #ccc;} + #cboxLoadedContent{border:5px solid #000; background:#fff;} + #cboxTitle{position:absolute; top:-20px; left:0; color:#ccc;} + #cboxCurrent{position:absolute; top:-20px; right:0px; color:#ccc;} + #cboxLoadingGraphic{background:url(images/loading.gif) no-repeat center center;} + + /* these elements are buttons, and may need to have additional styles reset to avoid unwanted base styles */ + #cboxPrevious, #cboxNext, #cboxSlideshow, #cboxClose {border:0; padding:0; margin:0; overflow:visible; width:auto; background:none; } + + /* avoid outlines on :active (mouseclick), but preserve outlines on :focus (tabbed navigating) */ + #cboxPrevious:active, #cboxNext:active, #cboxSlideshow:active, #cboxClose:active {outline:0;} + + #cboxSlideshow{position:absolute; top:-20px; right:90px; color:#fff;} + #cboxPrevious{position:absolute; top:50%; left:5px; margin-top:-32px; background:url(images/controls.png) no-repeat top left; width:28px; height:65px; text-indent:-9999px;} + #cboxPrevious:hover{background-position:bottom left;} + #cboxNext{position:absolute; top:50%; right:5px; margin-top:-32px; background:url(images/controls.png) no-repeat top right; width:28px; height:65px; text-indent:-9999px;} + #cboxNext:hover{background-position:bottom right;} + #cboxClose{position:absolute; top:5px; right:5px; display:block; background:url(images/controls.png) no-repeat top center; width:38px; height:19px; text-indent:-9999px;} + #cboxClose:hover{background-position:bottom center;} diff --git a/web/libraries/colorbox/example3/images/controls.png b/web/libraries/colorbox/example3/images/controls.png new file mode 100644 index 00000000..e1e97982 Binary files /dev/null and b/web/libraries/colorbox/example3/images/controls.png differ diff --git a/web/libraries/colorbox/example3/images/loading.gif b/web/libraries/colorbox/example3/images/loading.gif new file mode 100644 index 00000000..a32df5c0 Binary files /dev/null and b/web/libraries/colorbox/example3/images/loading.gif differ diff --git a/web/libraries/colorbox/example3/index.html b/web/libraries/colorbox/example3/index.html new file mode 100644 index 00000000..8f10b930 --- /dev/null +++ b/web/libraries/colorbox/example3/index.html @@ -0,0 +1,95 @@ + + + + + Colorbox Examples + + + + + + + +

Colorbox Demonstration

+

Elastic Transition

+

Grouped Photo 1

+

Grouped Photo 2

+

Grouped Photo 3

+ +

Fade Transition

+

Grouped Photo 1

+

Grouped Photo 2

+

Grouped Photo 3

+ +

No Transition + fixed width and height (75% of screen size)

+

Grouped Photo 1

+

Grouped Photo 2

+

Grouped Photo 3

+ +

Slideshow

+

Grouped Photo 1

+

Grouped Photo 2

+

Grouped Photo 3

+ +

Other Content Types

+

Outside HTML (Ajax)

+

Flash / Video (Iframe/Direct Link To YouTube)

+

Flash / Video (Iframe/Direct Link To Vimeo)

+

Outside Webpage (Iframe)

+

Inline HTML

+ +

Demonstration of using callbacks

+

Example with alerts. Callbacks and event-hooks allow users to extend functionality without having to rewrite parts of the plugin.

+ + +

Retina Images

+

Retina

+

Non-Retina

+ + +
+
+

This content comes from a hidden element on this page.

+

The inline option preserves bound JavaScript events and changes, and it puts the content back where it came from when it is closed.

+

Click me, it will be preserved!

+ +

If you try to open a new Colorbox while it is already open, it will update itself with the new content.

+

Updating Content Example:
+ Click here to load new content

+
+
+ + \ No newline at end of file diff --git a/web/libraries/colorbox/example4/colorbox.css b/web/libraries/colorbox/example4/colorbox.css new file mode 100644 index 00000000..523896a5 --- /dev/null +++ b/web/libraries/colorbox/example4/colorbox.css @@ -0,0 +1,66 @@ +/* + Colorbox Core Style: + The following CSS is consistent between example themes and should not be altered. +*/ +#colorbox, #cboxOverlay, #cboxWrapper{position:absolute; top:0; left:0; z-index:9999; overflow:hidden; -webkit-transform: translate3d(0,0,0);} +#cboxWrapper {max-width:none;} +#cboxOverlay{position:fixed; width:100%; height:100%;} +#cboxMiddleLeft, #cboxBottomLeft{clear:left;} +#cboxContent{position:relative;} +#cboxLoadedContent{overflow:auto; -webkit-overflow-scrolling: touch;} +#cboxTitle{margin:0;} +#cboxLoadingOverlay, #cboxLoadingGraphic{position:absolute; top:0; left:0; width:100%; height:100%;} +#cboxPrevious, #cboxNext, #cboxClose, #cboxSlideshow{cursor:pointer;} +.cboxPhoto{float:left; margin:auto; border:0; display:block; max-width:none; -ms-interpolation-mode:bicubic;} +.cboxIframe{width:100%; height:100%; display:block; border:0; padding:0; margin:0;} +#colorbox, #cboxContent, #cboxLoadedContent{box-sizing:content-box; -moz-box-sizing:content-box; -webkit-box-sizing:content-box;} + +/* + User Style: + Change the following styles to modify the appearance of Colorbox. They are + ordered & tabbed in a way that represents the nesting of the generated HTML. +*/ +#cboxOverlay{background:#fff; opacity: 0.9; filter: alpha(opacity = 90);} +#colorbox{outline:0;} + #cboxTopLeft{width:25px; height:25px; background:url(images/border1.png) no-repeat 0 0;} + #cboxTopCenter{height:25px; background:url(images/border1.png) repeat-x 0 -50px;} + #cboxTopRight{width:25px; height:25px; background:url(images/border1.png) no-repeat -25px 0;} + #cboxBottomLeft{width:25px; height:25px; background:url(images/border1.png) no-repeat 0 -25px;} + #cboxBottomCenter{height:25px; background:url(images/border1.png) repeat-x 0 -75px;} + #cboxBottomRight{width:25px; height:25px; background:url(images/border1.png) no-repeat -25px -25px;} + #cboxMiddleLeft{width:25px; background:url(images/border2.png) repeat-y 0 0;} + #cboxMiddleRight{width:25px; background:url(images/border2.png) repeat-y -25px 0;} + #cboxContent{background:#fff; overflow:hidden;} + .cboxIframe{background:#fff;} + #cboxError{padding:50px; border:1px solid #ccc;} + #cboxLoadedContent{margin-bottom:20px;} + #cboxTitle{position:absolute; bottom:0px; left:0; text-align:center; width:100%; color:#999;} + #cboxCurrent{position:absolute; bottom:0px; left:100px; color:#999;} + #cboxLoadingOverlay{background:#fff url(images/loading.gif) no-repeat 5px 5px;} + + /* these elements are buttons, and may need to have additional styles reset to avoid unwanted base styles */ + #cboxPrevious, #cboxNext, #cboxSlideshow, #cboxClose {border:0; padding:0; margin:0; overflow:visible; width:auto; background:none; } + + /* avoid outlines on :active (mouseclick), but preserve outlines on :focus (tabbed navigating) */ + #cboxPrevious:active, #cboxNext:active, #cboxSlideshow:active, #cboxClose:active {outline:0;} + + #cboxSlideshow{position:absolute; bottom:0px; right:42px; color:#444;} + #cboxPrevious{position:absolute; bottom:0px; left:0; color:#444;} + #cboxNext{position:absolute; bottom:0px; left:63px; color:#444;} + #cboxClose{position:absolute; bottom:0; right:0; display:block; color:#444;} + +/* + The following fixes a problem where IE7 and IE8 replace a PNG's alpha transparency with a black fill + when an alpha filter (opacity change) is set on the element or ancestor element. This style is not applied to or needed in IE9. + See: http://jacklmoore.com/notes/ie-transparency-problems/ +*/ +.cboxIE #cboxTopLeft, +.cboxIE #cboxTopCenter, +.cboxIE #cboxTopRight, +.cboxIE #cboxBottomLeft, +.cboxIE #cboxBottomCenter, +.cboxIE #cboxBottomRight, +.cboxIE #cboxMiddleLeft, +.cboxIE #cboxMiddleRight { + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr=#00FFFFFF,endColorstr=#00FFFFFF); +} \ No newline at end of file diff --git a/web/libraries/colorbox/example4/images/border1.png b/web/libraries/colorbox/example4/images/border1.png new file mode 100644 index 00000000..ea73e159 Binary files /dev/null and b/web/libraries/colorbox/example4/images/border1.png differ diff --git a/web/libraries/colorbox/example4/images/border2.png b/web/libraries/colorbox/example4/images/border2.png new file mode 100644 index 00000000..72cad44c Binary files /dev/null and b/web/libraries/colorbox/example4/images/border2.png differ diff --git a/web/libraries/colorbox/example4/images/loading.gif b/web/libraries/colorbox/example4/images/loading.gif new file mode 100644 index 00000000..1f3a2c0a Binary files /dev/null and b/web/libraries/colorbox/example4/images/loading.gif differ diff --git a/web/libraries/colorbox/example4/index.html b/web/libraries/colorbox/example4/index.html new file mode 100644 index 00000000..8f10b930 --- /dev/null +++ b/web/libraries/colorbox/example4/index.html @@ -0,0 +1,95 @@ + + + + + Colorbox Examples + + + + + + + +

Colorbox Demonstration

+

Elastic Transition

+

Grouped Photo 1

+

Grouped Photo 2

+

Grouped Photo 3

+ +

Fade Transition

+

Grouped Photo 1

+

Grouped Photo 2

+

Grouped Photo 3

+ +

No Transition + fixed width and height (75% of screen size)

+

Grouped Photo 1

+

Grouped Photo 2

+

Grouped Photo 3

+ +

Slideshow

+

Grouped Photo 1

+

Grouped Photo 2

+

Grouped Photo 3

+ +

Other Content Types

+

Outside HTML (Ajax)

+

Flash / Video (Iframe/Direct Link To YouTube)

+

Flash / Video (Iframe/Direct Link To Vimeo)

+

Outside Webpage (Iframe)

+

Inline HTML

+ +

Demonstration of using callbacks

+

Example with alerts. Callbacks and event-hooks allow users to extend functionality without having to rewrite parts of the plugin.

+ + +

Retina Images

+

Retina

+

Non-Retina

+ + +
+
+

This content comes from a hidden element on this page.

+

The inline option preserves bound JavaScript events and changes, and it puts the content back where it came from when it is closed.

+

Click me, it will be preserved!

+ +

If you try to open a new Colorbox while it is already open, it will update itself with the new content.

+

Updating Content Example:
+ Click here to load new content

+
+
+ + \ No newline at end of file diff --git a/web/libraries/colorbox/example5/colorbox.css b/web/libraries/colorbox/example5/colorbox.css new file mode 100644 index 00000000..5e9d4b7a --- /dev/null +++ b/web/libraries/colorbox/example5/colorbox.css @@ -0,0 +1,58 @@ +/* + Colorbox Core Style: + The following CSS is consistent between example themes and should not be altered. +*/ +#colorbox, #cboxOverlay, #cboxWrapper{position:absolute; top:0; left:0; z-index:9999; overflow:hidden; -webkit-transform: translate3d(0,0,0);} +#cboxWrapper {max-width:none;} +#cboxOverlay{position:fixed; width:100%; height:100%;} +#cboxMiddleLeft, #cboxBottomLeft{clear:left;} +#cboxContent{position:relative;} +#cboxLoadedContent{overflow:auto; -webkit-overflow-scrolling: touch;} +#cboxTitle{margin:0;} +#cboxLoadingOverlay, #cboxLoadingGraphic{position:absolute; top:0; left:0; width:100%; height:100%;} +#cboxPrevious, #cboxNext, #cboxClose, #cboxSlideshow{cursor:pointer;} +.cboxPhoto{float:left; margin:auto; border:0; display:block; max-width:none; -ms-interpolation-mode:bicubic;} +.cboxIframe{width:100%; height:100%; display:block; border:0; padding:0; margin:0;} +#colorbox, #cboxContent, #cboxLoadedContent{box-sizing:content-box; -moz-box-sizing:content-box; -webkit-box-sizing:content-box;} + +/* + User Style: + Change the following styles to modify the appearance of Colorbox. They are + ordered & tabbed in a way that represents the nesting of the generated HTML. +*/ +#cboxOverlay{background:#000; opacity: 0.9; filter: alpha(opacity = 90);} +#colorbox{outline:0;} + #cboxTopLeft{width:14px; height:14px; background:url(images/controls.png) no-repeat 0 0;} + #cboxTopCenter{height:14px; background:url(images/border.png) repeat-x top left;} + #cboxTopRight{width:14px; height:14px; background:url(images/controls.png) no-repeat -36px 0;} + #cboxBottomLeft{width:14px; height:43px; background:url(images/controls.png) no-repeat 0 -32px;} + #cboxBottomCenter{height:43px; background:url(images/border.png) repeat-x bottom left;} + #cboxBottomRight{width:14px; height:43px; background:url(images/controls.png) no-repeat -36px -32px;} + #cboxMiddleLeft{width:14px; background:url(images/controls.png) repeat-y -175px 0;} + #cboxMiddleRight{width:14px; background:url(images/controls.png) repeat-y -211px 0;} + #cboxContent{background:#fff; overflow:visible;} + .cboxIframe{background:#fff;} + #cboxError{padding:50px; border:1px solid #ccc;} + #cboxLoadedContent{margin-bottom:5px;} + #cboxLoadingOverlay{background:url(images/loading_background.png) no-repeat center center;} + #cboxLoadingGraphic{background:url(images/loading.gif) no-repeat center center;} + #cboxTitle{position:absolute; bottom:-25px; left:0; text-align:center; width:100%; font-weight:bold; color:#7C7C7C;} + #cboxCurrent{position:absolute; bottom:-25px; left:58px; font-weight:bold; color:#7C7C7C;} + + /* these elements are buttons, and may need to have additional styles reset to avoid unwanted base styles */ + #cboxPrevious, #cboxNext, #cboxSlideshow, #cboxClose {border:0; padding:0; margin:0; overflow:visible; position:absolute; bottom:-29px; background:url(images/controls.png) no-repeat 0px 0px; width:23px; height:23px; text-indent:-9999px;} + + /* avoid outlines on :active (mouseclick), but preserve outlines on :focus (tabbed navigating) */ + #cboxPrevious:active, #cboxNext:active, #cboxSlideshow:active, #cboxClose:active {outline:0;} + + #cboxPrevious{left:0px; background-position: -51px -25px;} + #cboxPrevious:hover{background-position:-51px 0px;} + #cboxNext{left:27px; background-position:-75px -25px;} + #cboxNext:hover{background-position:-75px 0px;} + #cboxClose{right:0; background-position:-100px -25px;} + #cboxClose:hover{background-position:-100px 0px;} + + .cboxSlideshow_on #cboxSlideshow{background-position:-125px 0px; right:27px;} + .cboxSlideshow_on #cboxSlideshow:hover{background-position:-150px 0px;} + .cboxSlideshow_off #cboxSlideshow{background-position:-150px -25px; right:27px;} + .cboxSlideshow_off #cboxSlideshow:hover{background-position:-125px 0px;} \ No newline at end of file diff --git a/web/libraries/colorbox/example5/images/border.png b/web/libraries/colorbox/example5/images/border.png new file mode 100644 index 00000000..c1cd1a2a Binary files /dev/null and b/web/libraries/colorbox/example5/images/border.png differ diff --git a/web/libraries/colorbox/example5/images/controls.png b/web/libraries/colorbox/example5/images/controls.png new file mode 100644 index 00000000..259130cd Binary files /dev/null and b/web/libraries/colorbox/example5/images/controls.png differ diff --git a/web/libraries/colorbox/example5/images/loading.gif b/web/libraries/colorbox/example5/images/loading.gif new file mode 100644 index 00000000..dba33c81 Binary files /dev/null and b/web/libraries/colorbox/example5/images/loading.gif differ diff --git a/web/libraries/colorbox/example5/images/loading_background.png b/web/libraries/colorbox/example5/images/loading_background.png new file mode 100644 index 00000000..23a336b3 Binary files /dev/null and b/web/libraries/colorbox/example5/images/loading_background.png differ diff --git a/web/libraries/colorbox/example5/index.html b/web/libraries/colorbox/example5/index.html new file mode 100644 index 00000000..8f10b930 --- /dev/null +++ b/web/libraries/colorbox/example5/index.html @@ -0,0 +1,95 @@ + + + + + Colorbox Examples + + + + + + + +

Colorbox Demonstration

+

Elastic Transition

+

Grouped Photo 1

+

Grouped Photo 2

+

Grouped Photo 3

+ +

Fade Transition

+

Grouped Photo 1

+

Grouped Photo 2

+

Grouped Photo 3

+ +

No Transition + fixed width and height (75% of screen size)

+

Grouped Photo 1

+

Grouped Photo 2

+

Grouped Photo 3

+ +

Slideshow

+

Grouped Photo 1

+

Grouped Photo 2

+

Grouped Photo 3

+ +

Other Content Types

+

Outside HTML (Ajax)

+

Flash / Video (Iframe/Direct Link To YouTube)

+

Flash / Video (Iframe/Direct Link To Vimeo)

+

Outside Webpage (Iframe)

+

Inline HTML

+ +

Demonstration of using callbacks

+

Example with alerts. Callbacks and event-hooks allow users to extend functionality without having to rewrite parts of the plugin.

+ + +

Retina Images

+

Retina

+

Non-Retina

+ + +
+
+

This content comes from a hidden element on this page.

+

The inline option preserves bound JavaScript events and changes, and it puts the content back where it came from when it is closed.

+

Click me, it will be preserved!

+ +

If you try to open a new Colorbox while it is already open, it will update itself with the new content.

+

Updating Content Example:
+ Click here to load new content

+
+
+ + \ No newline at end of file diff --git a/web/libraries/colorbox/i18n/jquery.colorbox-ar.js b/web/libraries/colorbox/i18n/jquery.colorbox-ar.js new file mode 100644 index 00000000..6c4228cd --- /dev/null +++ b/web/libraries/colorbox/i18n/jquery.colorbox-ar.js @@ -0,0 +1,15 @@ +/* + jQuery Colorbox language configuration + language: Arabic (ar) + translated by: A.Rhman Sayes +*/ +jQuery.extend(jQuery.colorbox.settings, { + current: "الصورة {current} من {total}", + previous: "السابق", + next: "التالي", + close: "إغلاق", + xhrError: "حدث خطأ أثناء تحميل المحتوى.", + imgError: "حدث خطأ أثناء تحميل الصورة.", + slideshowStart: "تشغيل العرض", + slideshowStop: "إيقا٠العرض" +}); diff --git a/web/libraries/colorbox/i18n/jquery.colorbox-bg.js b/web/libraries/colorbox/i18n/jquery.colorbox-bg.js new file mode 100644 index 00000000..de7e4a1d --- /dev/null +++ b/web/libraries/colorbox/i18n/jquery.colorbox-bg.js @@ -0,0 +1,16 @@ +/* + jQuery Colorbox language configuration + language: Bulgarian (bg) + translated by: Marian M.Bida + site: webmax.bg +*/ +jQuery.extend(jQuery.colorbox.settings, { + current: "изображение {current} от {total}", + previous: "предишна", + next: "Ñледваща", + close: "затвори", + xhrError: "ÐеуÑпешно зареждане на Ñъдържанието.", + imgError: "ÐеуÑпешно зареждане на изображението.", + slideshowStart: "пуÑни Ñлайд-шоу", + slideshowStop: "Ñпри Ñлайд-шоу" +}); diff --git a/web/libraries/colorbox/i18n/jquery.colorbox-bn.js b/web/libraries/colorbox/i18n/jquery.colorbox-bn.js new file mode 100644 index 00000000..946229d4 --- /dev/null +++ b/web/libraries/colorbox/i18n/jquery.colorbox-bn.js @@ -0,0 +1,16 @@ +/* +jQuery Colorbox language configuration +language: Bengali (bn) +translated by: Arkaprava Majumder +http://github.com/arkaindas +*/ +jQuery.extend(jQuery.colorbox.settings, { +current: "ছবি {current} à¦à¦° {total}", +previous: "আগে", +next: "পরে", +close: "বনà§à¦§", +xhrError: "à¦à¦‡ কনà§à¦Ÿà§‡à¦¨à§à¦Ÿ লোড করা যায়নি.", +imgError: "à¦à¦‡ ছবিটি লোড করা যায়নি.", +slideshowStart: "সà§à¦²à¦¾à¦‡à¦¡à¦¶à§‹ শà§à¦°à§", +slideshowStop: "সà§à¦²à¦¾à¦‡à¦¡à¦¶à§‹ বনà§à¦§" +}); diff --git a/web/libraries/colorbox/i18n/jquery.colorbox-ca.js b/web/libraries/colorbox/i18n/jquery.colorbox-ca.js new file mode 100644 index 00000000..173c05fd --- /dev/null +++ b/web/libraries/colorbox/i18n/jquery.colorbox-ca.js @@ -0,0 +1,13 @@ +/* + jQuery Colorbox language configuration + language: Catala (ca) + translated by: eduard salla +*/ +jQuery.extend(jQuery.colorbox.settings, { + current: "Imatge {current} de {total}", + previous: "Anterior", + next: "Següent", + close: "Tancar", + xhrError: "Error en la càrrega del contingut.", + imgError: "Error en la càrrega de la imatge." +}); diff --git a/web/libraries/colorbox/i18n/jquery.colorbox-cs.js b/web/libraries/colorbox/i18n/jquery.colorbox-cs.js new file mode 100644 index 00000000..9649fd45 --- /dev/null +++ b/web/libraries/colorbox/i18n/jquery.colorbox-cs.js @@ -0,0 +1,16 @@ +/* + jQuery Colorbox language configuration + language: Czech (cs) + translated by: Filip Novak + site: mame.napilno.cz/filip-novak +*/ +jQuery.extend(jQuery.colorbox.settings, { + current: "{current}. obrázek z {total}", + previous: "PÅ™edchozí", + next: "Následující", + close: "Zavřít", + xhrError: "Obsah se nepodaÅ™ilo naÄíst.", + imgError: "Obrázek se nepodaÅ™ilo naÄíst.", + slideshowStart: "Spustit slideshow", + slideshowStop: "Zastavit slideshow" +}); \ No newline at end of file diff --git a/web/libraries/colorbox/i18n/jquery.colorbox-da.js b/web/libraries/colorbox/i18n/jquery.colorbox-da.js new file mode 100644 index 00000000..676fffed --- /dev/null +++ b/web/libraries/colorbox/i18n/jquery.colorbox-da.js @@ -0,0 +1,16 @@ +/* + jQuery Colorbox language configuration + language: Danish (da) + translated by: danieljuhl + site: danieljuhl.dk +*/ +jQuery.extend(jQuery.colorbox.settings, { + current: "Billede {current} af {total}", + previous: "Forrige", + next: "Næste", + close: "Luk", + xhrError: "Indholdet fejlede i indlæsningen.", + imgError: "Billedet fejlede i indlæsningen.", + slideshowStart: "Start slideshow", + slideshowStop: "Stop slideshow" +}); diff --git a/web/libraries/colorbox/i18n/jquery.colorbox-de.js b/web/libraries/colorbox/i18n/jquery.colorbox-de.js new file mode 100644 index 00000000..d489379b --- /dev/null +++ b/web/libraries/colorbox/i18n/jquery.colorbox-de.js @@ -0,0 +1,15 @@ +/* + jQuery Colorbox language configuration + language: German (de) + translated by: wallenium +*/ +jQuery.extend(jQuery.colorbox.settings, { + current: "Bild {current} von {total}", + previous: "Zurück", + next: "Vor", + close: "Schließen", + xhrError: "Dieser Inhalt konnte nicht geladen werden.", + imgError: "Dieses Bild konnte nicht geladen werden.", + slideshowStart: "Slideshow starten", + slideshowStop: "Slideshow anhalten" +}); \ No newline at end of file diff --git a/web/libraries/colorbox/i18n/jquery.colorbox-es.js b/web/libraries/colorbox/i18n/jquery.colorbox-es.js new file mode 100644 index 00000000..11296fc9 --- /dev/null +++ b/web/libraries/colorbox/i18n/jquery.colorbox-es.js @@ -0,0 +1,13 @@ +/* + jQuery Colorbox language configuration + language: Spanish (es) + translated by: migolo +*/ +jQuery.extend(jQuery.colorbox.settings, { + current: "Imagen {current} de {total}", + previous: "Anterior", + next: "Siguiente", + close: "Cerrar", + xhrError: "Error en la carga del contenido.", + imgError: "Error en la carga de la imagen." +}); diff --git a/web/libraries/colorbox/i18n/jquery.colorbox-et.js b/web/libraries/colorbox/i18n/jquery.colorbox-et.js new file mode 100644 index 00000000..60a4e888 --- /dev/null +++ b/web/libraries/colorbox/i18n/jquery.colorbox-et.js @@ -0,0 +1,15 @@ +/* + jQuery Colorbox language configuration + language: Estonian (et) + translated by: keevitaja +*/ +jQuery.extend(jQuery.colorbox.settings, { + current: "{current}/{total}", + previous: "eelmine", + next: "järgmine", + close: "sulge", + xhrError: "Sisu ei õnnestunud laadida.", + imgError: "Pilti ei õnnestunud laadida.", + slideshowStart: "Käivita slaidid", + slideshowStop: "Peata slaidid" +}); \ No newline at end of file diff --git a/web/libraries/colorbox/i18n/jquery.colorbox-fa.js b/web/libraries/colorbox/i18n/jquery.colorbox-fa.js new file mode 100644 index 00000000..dbe70e1a --- /dev/null +++ b/web/libraries/colorbox/i18n/jquery.colorbox-fa.js @@ -0,0 +1,18 @@ +/* + jQuery Colorbox language configuration + language: Persian (Farsi) + translated by: Mahdi Jaberzadeh Ansari (MJZSoft) + site: www.mjzsoft.ir + email: mahdijaberzadehansari (at) yahoo.co.uk + Please note : Persian language is right to left like arabic. +*/ +jQuery.extend(jQuery.colorbox.settings, { + current: "تصویر {current} از {total}", + previous: "قبلی", + next: "بعدی", + close: "بستن", + xhrError: "متاسÙانه محتویات مورد نظر قابل نمایش نیست.", + imgError: "متاسÙانه بارگذاری این عکس با مشکل مواجه شده است.", + slideshowStart: "آغاز نمایش خودکار", + slideshowStop: "توق٠نمایش خودکار" +}); diff --git a/web/libraries/colorbox/i18n/jquery.colorbox-fi.js b/web/libraries/colorbox/i18n/jquery.colorbox-fi.js new file mode 100644 index 00000000..ac03fe02 --- /dev/null +++ b/web/libraries/colorbox/i18n/jquery.colorbox-fi.js @@ -0,0 +1,15 @@ +/* + jQuery Colorbox language configuration + language: Finnish (fi) + translated by: Mikko +*/ +jQuery.extend(jQuery.colorbox.settings, { + current: "Kuva {current} / {total}", + previous: "Edellinen", + next: "Seuraava", + close: "Sulje", + xhrError: "Sisällön lataaminen epäonnistui.", + imgError: "Kuvan lataaminen epäonnistui.", + slideshowStart: "Aloita kuvaesitys.", + slideshowStop: "Lopeta kuvaesitys." +}); diff --git a/web/libraries/colorbox/i18n/jquery.colorbox-fr.js b/web/libraries/colorbox/i18n/jquery.colorbox-fr.js new file mode 100644 index 00000000..f76352bd --- /dev/null +++ b/web/libraries/colorbox/i18n/jquery.colorbox-fr.js @@ -0,0 +1,15 @@ +/* + jQuery Colorbox language configuration + language: French (fr) + translated by: oaubert +*/ +jQuery.extend(jQuery.colorbox.settings, { + current: "image {current} sur {total}", + previous: "précédente", + next: "suivante", + close: "fermer", + xhrError: "Impossible de charger ce contenu.", + imgError: "Impossible de charger cette image.", + slideshowStart: "démarrer la présentation", + slideshowStop: "arrêter la présentation" +}); diff --git a/web/libraries/colorbox/i18n/jquery.colorbox-gl.js b/web/libraries/colorbox/i18n/jquery.colorbox-gl.js new file mode 100644 index 00000000..3641b51b --- /dev/null +++ b/web/libraries/colorbox/i18n/jquery.colorbox-gl.js @@ -0,0 +1,13 @@ +/* + jQuery Colorbox language configuration + language: Galician (gl) + translated by: donatorouco +*/ +jQuery.extend(jQuery.colorbox.settings, { + current: "Imaxe {current} de {total}", + previous: "Anterior", + next: "Seguinte", + close: "Pechar", + xhrError: "Erro na carga do contido.", + imgError: "Erro na carga da imaxe." +}); diff --git a/web/libraries/colorbox/i18n/jquery.colorbox-gr.js b/web/libraries/colorbox/i18n/jquery.colorbox-gr.js new file mode 100644 index 00000000..0d2c1bb7 --- /dev/null +++ b/web/libraries/colorbox/i18n/jquery.colorbox-gr.js @@ -0,0 +1,16 @@ +/* + jQuery Colorbox language configuration + language: Greek (gr) + translated by: S.Demirtzoglou + site: webiq.gr +*/ +jQuery.extend(jQuery.colorbox.settings, { + current: "Εικόνα {current} από {total}", + previous: "ΠÏοηγοÏμενη", + next: "Επόμενη", + close: "ΑπόκÏυψη", + xhrError: "Το πεÏιεχόμενο δεν μπόÏεσε να φοÏτωθεί.", + imgError: "Απέτυχε η φόÏτωση της εικόνας.", + slideshowStart: "ΈναÏξη παÏουσίασης", + slideshowStop: "ΠαÏση παÏουσίασης" +}); diff --git a/web/libraries/colorbox/i18n/jquery.colorbox-he.js b/web/libraries/colorbox/i18n/jquery.colorbox-he.js new file mode 100644 index 00000000..05e84607 --- /dev/null +++ b/web/libraries/colorbox/i18n/jquery.colorbox-he.js @@ -0,0 +1,16 @@ +/* + jQuery Colorbox language configuration + language: Hebrew (he) + translated by: David Cohen + site: dav.co.il +*/ +jQuery.extend(jQuery.colorbox.settings, { + current: "תמונה {current} מתוך {total}", + previous: "הקוד×", + next: "הב×", + close: "סגור", + xhrError: "שגי××” בטעינת התוכן.", + imgError: "שגי××” בטעינת התמונה.", + slideshowStart: "התחל מצגת", + slideshowStop: "עצור מצגת" +}); diff --git a/web/libraries/colorbox/i18n/jquery.colorbox-hr.js b/web/libraries/colorbox/i18n/jquery.colorbox-hr.js new file mode 100644 index 00000000..9e0d0f48 --- /dev/null +++ b/web/libraries/colorbox/i18n/jquery.colorbox-hr.js @@ -0,0 +1,15 @@ +/* + jQuery Colorbox language configuration + language: Croatian (hr) + translated by: Mladen Bicanic (base.hr) +*/ +jQuery.extend(jQuery.colorbox.settings, { + current: "Slika {current} od {total}", + previous: "Prethodna", + next: "Sljedeća", + close: "Zatvori", + xhrError: "NeuspjeÅ¡no uÄitavanje sadržaja.", + imgError: "NeuspjeÅ¡no uÄitavanje slike.", + slideshowStart: "Pokreni slideshow", + slideshowStop: "Zaustavi slideshow" +}); \ No newline at end of file diff --git a/web/libraries/colorbox/i18n/jquery.colorbox-hu.js b/web/libraries/colorbox/i18n/jquery.colorbox-hu.js new file mode 100644 index 00000000..72e9d36b --- /dev/null +++ b/web/libraries/colorbox/i18n/jquery.colorbox-hu.js @@ -0,0 +1,15 @@ +/* + jQuery Colorbox language configuration + language: Hungarian (hu) + translated by: kovadani +*/ +jQuery.extend(jQuery.colorbox.settings, { + current: "{current}/{total} kép", + previous: "ElÅ‘zÅ‘", + next: "KövetkezÅ‘", + close: "Bezár", + xhrError: "A tartalmat nem sikerült betölteni.", + imgError: "A képet nem sikerült betölteni.", + slideshowStart: "Diavetítés indítása", + slideshowStop: "Diavetítés leállítása" +}); \ No newline at end of file diff --git a/web/libraries/colorbox/i18n/jquery.colorbox-id.js b/web/libraries/colorbox/i18n/jquery.colorbox-id.js new file mode 100644 index 00000000..81a62df3 --- /dev/null +++ b/web/libraries/colorbox/i18n/jquery.colorbox-id.js @@ -0,0 +1,15 @@ +/* + jQuery Colorbox language configuration + language: Indonesian (id) + translated by: sarwasunda +*/ +jQuery.extend(jQuery.colorbox.settings, { + current: "ke {current} dari {total}", + previous: "Sebelumnya", + next: "Berikutnya", + close: "Tutup", + xhrError: "Konten ini tidak dapat dimuat.", + imgError: "Gambar ini tidak dapat dimuat.", + slideshowStart: "Putar", + slideshowStop: "Berhenti" +}); diff --git a/web/libraries/colorbox/i18n/jquery.colorbox-it.js b/web/libraries/colorbox/i18n/jquery.colorbox-it.js new file mode 100644 index 00000000..2a4af645 --- /dev/null +++ b/web/libraries/colorbox/i18n/jquery.colorbox-it.js @@ -0,0 +1,15 @@ +/* + jQuery Colorbox language configuration + language: Italian (it) + translated by: maur8ino +*/ +jQuery.extend(jQuery.colorbox.settings, { + current: "Immagine {current} di {total}", + previous: "Precedente", + next: "Successiva", + close: "Chiudi", + xhrError: "Errore nel caricamento del contenuto.", + imgError: "Errore nel caricamento dell'immagine.", + slideshowStart: "Inizia la presentazione", + slideshowStop: "Termina la presentazione" +}); diff --git a/web/libraries/colorbox/i18n/jquery.colorbox-ja.js b/web/libraries/colorbox/i18n/jquery.colorbox-ja.js new file mode 100644 index 00000000..067612c0 --- /dev/null +++ b/web/libraries/colorbox/i18n/jquery.colorbox-ja.js @@ -0,0 +1,15 @@ +/* + jQuery Colorbox language configuration + language: Japanaese (ja) + translated by: Hajime Fujimoto +*/ +jQuery.extend(jQuery.colorbox.settings, { + current: "{total}枚中{current}æžšç›®", + previous: "å‰", + next: "次", + close: "é–‰ã˜ã‚‹", + xhrError: "コンテンツã®èª­ã¿è¾¼ã¿ã«å¤±æ•—ã—ã¾ã—ãŸ", + imgError: "ç”»åƒã®èª­ã¿è¾¼ã¿ã«å¤±æ•—ã—ã¾ã—ãŸ", + slideshowStart: "スライドショー開始", + slideshowStop: "スライドショー終了" +}); diff --git a/web/libraries/colorbox/i18n/jquery.colorbox-kr.js b/web/libraries/colorbox/i18n/jquery.colorbox-kr.js new file mode 100644 index 00000000..b95702bc --- /dev/null +++ b/web/libraries/colorbox/i18n/jquery.colorbox-kr.js @@ -0,0 +1,15 @@ +/* + jQuery Colorbox language configuration + language: Korean (kr) + translated by: lunareffect +*/ +jQuery.extend(jQuery.colorbox.settings, { + current: "ì´ {total} 중 {current}", + previous: "ì´ì „", + next: "다ìŒ", + close: "닫기", + xhrError: "컨í…츠를 불러오는 ë° ì‹¤íŒ¨í–ˆìŠµë‹ˆë‹¤.", + imgError: "ì´ë¯¸ì§€ë¥¼ 불러오는 ë° ì‹¤íŒ¨í–ˆìŠµë‹ˆë‹¤.", + slideshowStart: "슬ë¼ì´ë“œì‡¼ 시작", + slideshowStop: "슬ë¼ì´ë“œì‡¼ 중지" +}); diff --git a/web/libraries/colorbox/i18n/jquery.colorbox-lt.js b/web/libraries/colorbox/i18n/jquery.colorbox-lt.js new file mode 100644 index 00000000..a513fcf6 --- /dev/null +++ b/web/libraries/colorbox/i18n/jquery.colorbox-lt.js @@ -0,0 +1,15 @@ +/* + jQuery Colorbox language configuration + language: Lithuanian (lt) + translated by: Tomas NorkÅ«nas +*/ +jQuery.extend(jQuery.colorbox.settings, { + current: "Nuotrauka {current} iÅ¡ {total}", + previous: "Atgal", + next: "Pirmyn", + close: "Uždaryti", + xhrError: "Nepavyko užkrauti turinio.", + imgError: "Nepavyko užkrauti nuotraukos.", + slideshowStart: "PradÄ—ti automatinÄ™ peržiÅ«rÄ…", + slideshowStop: "Sustabdyti automatinÄ™ peržiÅ«rÄ…" +}); \ No newline at end of file diff --git a/web/libraries/colorbox/i18n/jquery.colorbox-lv.js b/web/libraries/colorbox/i18n/jquery.colorbox-lv.js new file mode 100644 index 00000000..e376366b --- /dev/null +++ b/web/libraries/colorbox/i18n/jquery.colorbox-lv.js @@ -0,0 +1,16 @@ +/* + jQuery Colorbox language configuration + language: Latvian (lv) + translated by: Matiss Roberts Treinis + site: x0.lv +*/ +jQuery.extend(jQuery.colorbox.settings, { + current: "attÄ“ls {current} no {total}", + previous: "iepriekÅ¡Ä“jais", + next: "nÄkamais", + close: "aizvÄ“rt", + xhrError: "NeizdevÄs ielÄdÄ“t saturu.", + imgError: "NeizdevÄs ielÄdÄ“t attÄ“lu.", + slideshowStart: "sÄkt slaidrÄdi", + slideshowStop: "apturÄ“t slaidrÄdi" +}); diff --git a/web/libraries/colorbox/i18n/jquery.colorbox-my.js b/web/libraries/colorbox/i18n/jquery.colorbox-my.js new file mode 100644 index 00000000..216e252c --- /dev/null +++ b/web/libraries/colorbox/i18n/jquery.colorbox-my.js @@ -0,0 +1,15 @@ +/* + jQuery Colorbox language configuration + language: Myanmar (my) + translated by: Yan Naing +*/ +jQuery.extend(jQuery.colorbox.settings, { + current: "ပုံ {total} မှာ {current} မြောက်ပုံ", + previous: "ရှေ့သို့", + next: "နောက်သို့", + close: "ပိá€á€ºá€™á€Šá€º", + xhrError: "ပါá€á€„်သော အကြောင်းအရာများ ဖော်ပြရာá€á€½á€„် အနည်းငယ် á€á€»á€­á€¯á€·á€šá€½á€„်းမှုရှိနေပါသည်", + imgError: "ပုံပြသရာá€á€½á€„် အနည်းငယ် á€á€»á€­á€¯á€·á€šá€½á€„်းá€á€»á€€á€º ရှိနေပါသည်", + slideshowStart: "ပုံများ စá€á€„်ပြသမည်", + slideshowStop: "ပုံပြသá€á€¼á€„်း ရပ်ဆိုင်မည်" +}); diff --git a/web/libraries/colorbox/i18n/jquery.colorbox-nl.js b/web/libraries/colorbox/i18n/jquery.colorbox-nl.js new file mode 100644 index 00000000..dfc658ec --- /dev/null +++ b/web/libraries/colorbox/i18n/jquery.colorbox-nl.js @@ -0,0 +1,15 @@ +/* + jQuery Colorbox language configuration + language: Dutch (nl) + translated by: barryvdh +*/ +jQuery.extend(jQuery.colorbox.settings, { + current: "Afbeelding {current} van {total}", + previous: "Vorige", + next: "Volgende", + close: "Sluiten", + xhrError: "Deze inhoud kan niet geladen worden.", + imgError: "Deze afbeelding kan niet geladen worden.", + slideshowStart: "Diashow starten", + slideshowStop: "Diashow stoppen" +}); \ No newline at end of file diff --git a/web/libraries/colorbox/i18n/jquery.colorbox-no.js b/web/libraries/colorbox/i18n/jquery.colorbox-no.js new file mode 100644 index 00000000..277c5d3f --- /dev/null +++ b/web/libraries/colorbox/i18n/jquery.colorbox-no.js @@ -0,0 +1,16 @@ +/* + jQuery Colorbox language configuration + language: Norwegian (no) + translated by: lars-erik + site: markedspartner.no +*/ +jQuery.extend(jQuery.colorbox.settings, { + current: "Bilde {current} av {total}", + previous: "Forrige", + next: "Neste", + close: "Lukk", + xhrError: "Feil ved lasting av innhold.", + imgError: "Feil ved lasting av bilde.", + slideshowStart: "Start lysbildefremvisning", + slideshowStop: "Stopp lysbildefremvisning" +}); diff --git a/web/libraries/colorbox/i18n/jquery.colorbox-pl.js b/web/libraries/colorbox/i18n/jquery.colorbox-pl.js new file mode 100644 index 00000000..8cbdcab2 --- /dev/null +++ b/web/libraries/colorbox/i18n/jquery.colorbox-pl.js @@ -0,0 +1,16 @@ +/* + jQuery Colorbox language configuration + language: Polski (pl) + translated by: Tomasz WasiÅ„ski + site: 2bevisible.pl +*/ +jQuery.extend(jQuery.colorbox.settings, { + current: "{current}. obrazek z {total}", + previous: "Poprzedni", + next: "NastÄ™pny", + close: "Zamknij", + xhrError: "Nie udaÅ‚o siÄ™ zaÅ‚adować treÅ›ci.", + imgError: "Nie udaÅ‚o siÄ™ zaÅ‚adować obrazka.", + slideshowStart: "rozpocznij pokaz slajdów", + slideshowStop: "zatrzymaj pokaz slajdów" +}); \ No newline at end of file diff --git a/web/libraries/colorbox/i18n/jquery.colorbox-pt-BR.js b/web/libraries/colorbox/i18n/jquery.colorbox-pt-BR.js new file mode 100644 index 00000000..a405d93d --- /dev/null +++ b/web/libraries/colorbox/i18n/jquery.colorbox-pt-BR.js @@ -0,0 +1,15 @@ +/* + jQuery Colorbox language configuration + language: Brazilian Portuguese (pt-BR) + translated by: ReinaldoMT +*/ +jQuery.extend(jQuery.colorbox.settings, { + current: "Imagem {current} de {total}", + previous: "Anterior", + next: "Próxima", + close: "Fechar", + slideshowStart: "iniciar apresentação de slides", + slideshowStop: "parar apresentação de slides", + xhrError: "Erro ao carregar o conteúdo.", + imgError: "Erro ao carregar a imagem." +}); \ No newline at end of file diff --git a/web/libraries/colorbox/i18n/jquery.colorbox-ro.js b/web/libraries/colorbox/i18n/jquery.colorbox-ro.js new file mode 100644 index 00000000..0a461e28 --- /dev/null +++ b/web/libraries/colorbox/i18n/jquery.colorbox-ro.js @@ -0,0 +1,15 @@ +/* + jQuery Colorbox language configuration + language: Romanian (ro) + translated by: shurub3l +*/ +jQuery.extend(jQuery.colorbox.settings, { + current: "imagine {current} din {total}", + previous: "precedenta", + next: "următoarea", + close: "închideÈ›i", + xhrError: "Acest conÈ›inut nu poate fi încărcat.", + imgError: "Această imagine nu poate fi încărcată", + slideshowStart: "începeÈ›i prezentarea (slideshow)", + slideshowStop: "opriÈ›i prezentarea (slideshow)" +}); \ No newline at end of file diff --git a/web/libraries/colorbox/i18n/jquery.colorbox-ru.js b/web/libraries/colorbox/i18n/jquery.colorbox-ru.js new file mode 100644 index 00000000..81b688f2 --- /dev/null +++ b/web/libraries/colorbox/i18n/jquery.colorbox-ru.js @@ -0,0 +1,16 @@ +/* + jQuery Colorbox language configuration + language: Russian (ru) + translated by: Marfa + site: themarfa.name +*/ +jQuery.extend(jQuery.colorbox.settings, { + current: "изображение {current} из {total}", + previous: "назад", + next: "вперёд", + close: "закрыть", + xhrError: "Ðе удалоÑÑŒ загрузить Ñодержимое.", + imgError: "Ðе удалоÑÑŒ загрузить изображение.", + slideshowStart: "начать Ñлайд-шоу", + slideshowStop: "оÑтановить Ñлайд-шоу" +}); \ No newline at end of file diff --git a/web/libraries/colorbox/i18n/jquery.colorbox-si.js b/web/libraries/colorbox/i18n/jquery.colorbox-si.js new file mode 100644 index 00000000..8fac6800 --- /dev/null +++ b/web/libraries/colorbox/i18n/jquery.colorbox-si.js @@ -0,0 +1,15 @@ +/* + jQuery Colorbox language configuration + language: Slovenian (si) + translated by: BoÅ¡tjan PiÅ¡ler (pisler.si) +*/ +jQuery.extend(jQuery.colorbox.settings, { + current: "Slika {current} od {total}", + previous: "PrejÅ¡nja", + next: "Naslednja", + close: "Zapri", + xhrError: "Vsebine ni bilo mogoÄe naložiti.", + imgError: "Slike ni bilo mogoÄe naložiti.", + slideshowStart: "Zaženi prezentacijo", + slideshowStop: "Zaustavi prezentacijo" +}); \ No newline at end of file diff --git a/web/libraries/colorbox/i18n/jquery.colorbox-sk.js b/web/libraries/colorbox/i18n/jquery.colorbox-sk.js new file mode 100644 index 00000000..faa9291c --- /dev/null +++ b/web/libraries/colorbox/i18n/jquery.colorbox-sk.js @@ -0,0 +1,15 @@ +/* + jQuery Colorbox language configuration + language: Slovak (sk) + translated by: Jaroslav Kostal +*/ +jQuery.extend(jQuery.colorbox.settings, { + current: "{current}. obrázok z {total}", + previous: "Predchádzajúci", + next: "Následujúci", + close: "ZatvoriÅ¥", + xhrError: "Obsah sa nepodarilo naÄítaÅ¥.", + imgError: "Obrázok sa nepodarilo naÄítaÅ¥.", + slideshowStart: "SpustiÅ¥ slideshow", + slideshowStop: "zastaviÅ¥ slideshow" +}); \ No newline at end of file diff --git a/web/libraries/colorbox/i18n/jquery.colorbox-sr.js b/web/libraries/colorbox/i18n/jquery.colorbox-sr.js new file mode 100644 index 00000000..618e73c4 --- /dev/null +++ b/web/libraries/colorbox/i18n/jquery.colorbox-sr.js @@ -0,0 +1,15 @@ +/* + jQuery Colorbox language configuration + language: Serbian (sr) + translated by: Sasa Stefanovic (baguje.com) +*/ +jQuery.extend(jQuery.colorbox.settings, { + current: "Slika {current} od {total}", + previous: "Prethodna", + next: "Sledeća", + close: "Zatvori", + xhrError: "NeuspeÅ¡no uÄitavanje sadržaja.", + imgError: "NeuspeÅ¡no uÄitavanje slike.", + slideshowStart: "Pokreni slideshow", + slideshowStop: "Zaustavi slideshow" +}); diff --git a/web/libraries/colorbox/i18n/jquery.colorbox-sv.js b/web/libraries/colorbox/i18n/jquery.colorbox-sv.js new file mode 100644 index 00000000..01bb1d8c --- /dev/null +++ b/web/libraries/colorbox/i18n/jquery.colorbox-sv.js @@ -0,0 +1,15 @@ +/* + jQuery Colorbox language configuration + language: Swedish (sv) + translated by: Mattias Reichel +*/ +jQuery.extend(jQuery.colorbox.settings, { + current: "Bild {current} av {total}", + previous: "FöregÃ¥ende", + next: "Nästa", + close: "Stäng", + xhrError: "InnehÃ¥llet kunde inte laddas.", + imgError: "Den här bilden kunde inte laddas.", + slideshowStart: "Starta bildspel", + slideshowStop: "Stoppa bildspel" +}); \ No newline at end of file diff --git a/web/libraries/colorbox/i18n/jquery.colorbox-tk.js b/web/libraries/colorbox/i18n/jquery.colorbox-tk.js new file mode 100644 index 00000000..ddb0a23c --- /dev/null +++ b/web/libraries/colorbox/i18n/jquery.colorbox-tk.js @@ -0,0 +1,16 @@ +/* + jQuery Colorbox language configuration + language: Turkmen (tk) + translated by: N'Bayramberdiyev + site: nbayramberdiyev.com +*/ +jQuery.extend(jQuery.colorbox.settings, { + current: "Surat {current} / {total}", + previous: "Öňki", + next: "Soňky", + close: "Ãap", + xhrError: "Ãüklenýärkä näsazlyk ýüze çykdy.", + imgError: "Ãüklenýärkä näsazlyk ýüze çykdy.", + slideshowStart: "Slaýdy BaÅŸlat", + slideshowStop: "Slaýdy Duruz" +}); diff --git a/web/libraries/colorbox/i18n/jquery.colorbox-tr.js b/web/libraries/colorbox/i18n/jquery.colorbox-tr.js new file mode 100644 index 00000000..d467c2ef --- /dev/null +++ b/web/libraries/colorbox/i18n/jquery.colorbox-tr.js @@ -0,0 +1,19 @@ +/* + jQuery Colorbox language configuration + language: Turkish (tr) + translated by: Caner ÖNCEL + site: egonomik.com + + edited by: Sinan Eldem + www.sinaneldem.com.tr +*/ +jQuery.extend(jQuery.colorbox.settings, { + current: "Görsel {current} / {total}", + previous: "Önceki", + next: "Sonraki", + close: "Kapat", + xhrError: "İçerik yüklenirken hata meydana geldi.", + imgError: "Resim yüklenirken hata meydana geldi.", + slideshowStart: "Slaytı BaÅŸlat", + slideshowStop: "Slaytı Durdur" +}); diff --git a/web/libraries/colorbox/i18n/jquery.colorbox-uk.js b/web/libraries/colorbox/i18n/jquery.colorbox-uk.js new file mode 100644 index 00000000..3f786d3f --- /dev/null +++ b/web/libraries/colorbox/i18n/jquery.colorbox-uk.js @@ -0,0 +1,16 @@ +/* + jQuery ColorBox language configuration + language: Ukrainian (uk) + translated by: Andrew + http://acisoftware.com.ua +*/ +jQuery.extend(jQuery.colorbox.settings, { + current: "Ð·Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð½Ñ {current} з {total}", + previous: "попереднє", + next: "наÑтупне", + close: "закрити", + xhrError: "Ðе вдалоÑÑ Ð·Ð°Ð²Ð°Ð½Ñ‚Ð°Ð¶Ð¸Ñ‚Ð¸ вміÑÑ‚.", + imgError: "Ðе вдалоÑÑ Ð·Ð°Ð²Ð°Ð½Ñ‚Ð°Ð¶Ð¸Ñ‚Ð¸ зображеннÑ.", + slideshowStart: "почати Ñлайд-шоу", + slideshowStop: "зупинити Ñлайд-шоу" +}); \ No newline at end of file diff --git a/web/libraries/colorbox/i18n/jquery.colorbox-vi.js b/web/libraries/colorbox/i18n/jquery.colorbox-vi.js new file mode 100644 index 00000000..72c29188 --- /dev/null +++ b/web/libraries/colorbox/i18n/jquery.colorbox-vi.js @@ -0,0 +1,16 @@ +/* + jQuery Colorbox language configuration + language: Vietnamese (vi) + translated by: ngtrian + site: nopviet.com +*/ +jQuery.extend(jQuery.colorbox.settings, { + current: "ảnh {current} trên {total}", + previous: "trÆ°á»›c đó", + next: "tiếp theo", + close: "đóng", + xhrError: "Thất bại tải vá» ná»™i dung này.", + imgError: "Thất bại tải vỠảnh này.", + slideshowStart: "Bắt đầu trình chiếu", + slideshowStop: "Kết thúc trình chiếu" +}); diff --git a/web/libraries/colorbox/i18n/jquery.colorbox-zh-CN.js b/web/libraries/colorbox/i18n/jquery.colorbox-zh-CN.js new file mode 100644 index 00000000..5b6ec042 --- /dev/null +++ b/web/libraries/colorbox/i18n/jquery.colorbox-zh-CN.js @@ -0,0 +1,15 @@ +/* + jQuery Colorbox language configuration + language: Chinese Simplified (zh-CN) + translated by: zhao weiming +*/ +jQuery.extend(jQuery.colorbox.settings, { + current: "当å‰å›¾åƒ {current} 总共 {total}", + previous: "å‰ä¸€é¡µ", + next: "åŽä¸€é¡µ", + close: "关闭", + xhrError: "此内容无法加载", + imgError: "此图片无法加载", + slideshowStart: "开始播放幻ç¯ç‰‡", + slideshowStop: "åœæ­¢æ’­æ”¾å¹»ç¯ç‰‡" +}); \ No newline at end of file diff --git a/web/libraries/colorbox/i18n/jquery.colorbox-zh-TW.js b/web/libraries/colorbox/i18n/jquery.colorbox-zh-TW.js new file mode 100644 index 00000000..d72b7429 --- /dev/null +++ b/web/libraries/colorbox/i18n/jquery.colorbox-zh-TW.js @@ -0,0 +1,15 @@ +/* + jQuery Colorbox language configuration + language: Chinese Traditional (zh-TW) + translated by: Atans Chiu +*/ +jQuery.extend(jQuery.colorbox.settings, { + current: "圖片 {current} 總共 {total}", + previous: "上一é ", + next: "下一é ", + close: "關閉", + xhrError: "此內容載入失敗.", + imgError: "此圖片加入失敗.", + slideshowStart: "開始幻燈片", + slideshowStop: "çµæŸå¹»ç‡ˆç‰‡" +}); diff --git a/web/libraries/colorbox/jquery.colorbox-min.js b/web/libraries/colorbox/jquery.colorbox-min.js new file mode 100644 index 00000000..b5109a26 --- /dev/null +++ b/web/libraries/colorbox/jquery.colorbox-min.js @@ -0,0 +1,6 @@ +/*! + Colorbox 1.6.4 + license: MIT + http://www.jacklmoore.com/colorbox +*/ +(function(t,e,i){function n(i,n,o){var r=e.createElement(i);return n&&(r.id=Z+n),o&&(r.style.cssText=o),t(r)}function o(){return i.innerHeight?i.innerHeight:t(i).height()}function r(e,i){i!==Object(i)&&(i={}),this.cache={},this.el=e,this.value=function(e){var n;return void 0===this.cache[e]&&(n=t(this.el).attr("data-cbox-"+e),void 0!==n?this.cache[e]=n:void 0!==i[e]?this.cache[e]=i[e]:void 0!==X[e]&&(this.cache[e]=X[e])),this.cache[e]},this.get=function(e){var i=this.value(e);return t.isFunction(i)?i.call(this.el,this):i}}function h(t){var e=W.length,i=(A+t)%e;return 0>i?e+i:i}function a(t,e){return Math.round((/%/.test(t)?("x"===e?E.width():o())/100:1)*parseInt(t,10))}function s(t,e){return t.get("photo")||t.get("photoRegex").test(e)}function l(t,e){return t.get("retinaUrl")&&i.devicePixelRatio>1?e.replace(t.get("photoRegex"),t.get("retinaSuffix")):e}function d(t){"contains"in x[0]&&!x[0].contains(t.target)&&t.target!==v[0]&&(t.stopPropagation(),x.focus())}function c(t){c.str!==t&&(x.add(v).removeClass(c.str).addClass(t),c.str=t)}function g(e){A=0,e&&e!==!1&&"nofollow"!==e?(W=t("."+te).filter(function(){var i=t.data(this,Y),n=new r(this,i);return n.get("rel")===e}),A=W.index(_.el),-1===A&&(W=W.add(_.el),A=W.length-1)):W=t(_.el)}function u(i){t(e).trigger(i),ae.triggerHandler(i)}function f(i){var o;if(!G){if(o=t(i).data(Y),_=new r(i,o),g(_.get("rel")),!U){U=$=!0,c(_.get("className")),x.css({visibility:"hidden",display:"block",opacity:""}),I=n(se,"LoadedContent","width:0; height:0; overflow:hidden; visibility:hidden"),b.css({width:"",height:""}).append(I),j=T.height()+k.height()+b.outerHeight(!0)-b.height(),D=C.width()+H.width()+b.outerWidth(!0)-b.width(),N=I.outerHeight(!0),z=I.outerWidth(!0);var h=a(_.get("initialWidth"),"x"),s=a(_.get("initialHeight"),"y"),l=_.get("maxWidth"),f=_.get("maxHeight");_.w=Math.max((l!==!1?Math.min(h,a(l,"x")):h)-z-D,0),_.h=Math.max((f!==!1?Math.min(s,a(f,"y")):s)-N-j,0),I.css({width:"",height:_.h}),J.position(),u(ee),_.get("onOpen"),O.add(F).hide(),x.focus(),_.get("trapFocus")&&e.addEventListener&&(e.addEventListener("focus",d,!0),ae.one(re,function(){e.removeEventListener("focus",d,!0)})),_.get("returnFocus")&&ae.one(re,function(){t(_.el).focus()})}var p=parseFloat(_.get("opacity"));v.css({opacity:p===p?p:"",cursor:_.get("overlayClose")?"pointer":"",visibility:"visible"}).show(),_.get("closeButton")?B.html(_.get("close")).appendTo(b):B.appendTo("
"),w()}}function p(){x||(V=!1,E=t(i),x=n(se).attr({id:Y,"class":t.support.opacity===!1?Z+"IE":"",role:"dialog",tabindex:"-1"}).hide(),v=n(se,"Overlay").hide(),L=t([n(se,"LoadingOverlay")[0],n(se,"LoadingGraphic")[0]]),y=n(se,"Wrapper"),b=n(se,"Content").append(F=n(se,"Title"),R=n(se,"Current"),P=t(' + + + +
+ + +
+ +
+
+ + +
+
+
diff --git a/web/modules/contrib/audiofield/templates/audioplayer--jplayer--default-single.html.twig b/web/modules/contrib/audiofield/templates/audioplayer--jplayer--default-single.html.twig new file mode 100644 index 00000000..c4d4b272 --- /dev/null +++ b/web/modules/contrib/audiofield/templates/audioplayer--jplayer--default-single.html.twig @@ -0,0 +1,53 @@ +{# +/** + * @file + * Single file default theme implementation for jPlayer audio player. + * + * Available variables: + * - plugin_id: the name of the plugin being used for templating. + * - plugin_theme: the name of the specific plugin theme, if it exists. + * - files: array of render info for each file. + * - settings: array of settings for thie player. + * + * @ingroup themeable + */ +#} +
+ + +
diff --git a/web/modules/contrib/audiofield/templates/audioplayer--jplayer--jplayer-circle.html.twig b/web/modules/contrib/audiofield/templates/audioplayer--jplayer--jplayer-circle.html.twig new file mode 100644 index 00000000..cab28df5 --- /dev/null +++ b/web/modules/contrib/audiofield/templates/audioplayer--jplayer--jplayer-circle.html.twig @@ -0,0 +1,43 @@ +{# +/** + * @file + * Default theme implementation for jPlayer audio player. + * + * Available variables: + * - plugin_id: the name of the plugin being used for templating. + * - plugin_theme: the name of the specific plugin theme, if it exists. + * - files: array of render info for each file. + * - settings: array of settings for thie player. + * + * @ingroup themeable + */ +#} +
+ + {% if settings.audio_player_jplayer_theme == 'audiofield.jplayer.theme_jplayer_circle' %} + {% for file in files %} +
+
+
+
+
+
+
+
+
+
+
+
+
+ +
+ +
+
+ {% endfor %} + {% endif %} + +
diff --git a/web/modules/contrib/audiofield/templates/audioplayer--jplayer.html.twig b/web/modules/contrib/audiofield/templates/audioplayer--jplayer.html.twig new file mode 100644 index 00000000..91de5a9a --- /dev/null +++ b/web/modules/contrib/audiofield/templates/audioplayer--jplayer.html.twig @@ -0,0 +1,39 @@ +{# +/** + * @file + * Circle theme implementation for jPlayer audio player. + * + * Available variables: + * - plugin_id: the name of the plugin being used for templating. + * - plugin_theme: the name of the specific plugin theme, if it exists. + * - files: array of render info for each file. + * - settings: array of settings for thie player. + * + * @ingroup themeable + */ +#} +
+ {% for file in files %} +
+
+
+
+
+
+
+
+
+
+
+
+
+ +
+ +
+
+ {% endfor %} +
diff --git a/web/modules/contrib/audiofield/templates/audioplayer--mediaelement.html.twig b/web/modules/contrib/audiofield/templates/audioplayer--mediaelement.html.twig new file mode 100644 index 00000000..1e784485 --- /dev/null +++ b/web/modules/contrib/audiofield/templates/audioplayer--mediaelement.html.twig @@ -0,0 +1,27 @@ +{# +/** + * @file + * Default theme implementation for Media Element audio player. + * + * Available variables: + * - plugin_id: the name of the plugin being used for templating. + * - plugin_theme: the name of the specific plugin theme, if it exists. + * - files: array of render info for each file. + * - settings: array of settings for thie player. + * + * @ingroup themeable + */ +#} +
+ {% for file in files %} +
+
+ +
+ +
+ {% endfor %} +
diff --git a/web/modules/contrib/audiofield/templates/audioplayer--projekktor.html.twig b/web/modules/contrib/audiofield/templates/audioplayer--projekktor.html.twig new file mode 100644 index 00000000..b179de5f --- /dev/null +++ b/web/modules/contrib/audiofield/templates/audioplayer--projekktor.html.twig @@ -0,0 +1,25 @@ +{# +/** + * @file + * Default theme implementation for Projekktor audio player. + * + * Available variables: + * - plugin_id: the name of the plugin being used for templating. + * - plugin_theme: the name of the specific plugin theme, if it exists. + * - files: array of render info for each file. + * - settings: array of settings for thie player. + * + * @ingroup themeable + */ +#} +
+ {% for file in files %} +
+ + +
+ {% endfor %} +
diff --git a/web/modules/contrib/audiofield/templates/audioplayer--soundmanager--barui.html.twig b/web/modules/contrib/audiofield/templates/audioplayer--soundmanager--barui.html.twig new file mode 100644 index 00000000..8365f2ea --- /dev/null +++ b/web/modules/contrib/audiofield/templates/audioplayer--soundmanager--barui.html.twig @@ -0,0 +1,76 @@ +{# +/** + * @file + * Bar UI theme implementation for SoundManager audio player. + * + * Available variables: + * - plugin_id: the name of the plugin being used for templating. + * - plugin_theme: the name of the specific plugin theme, if it exists. + * - files: array of render info for each file. + * - settings: array of settings for thie player. + * + * @ingroup themeable + */ +#} +
+
+
+
+
+
+ +
+
+
+
+
+
+
+
0:00
+
+
+
+
+
+
+
0:00
+
+
+
+
+
+ + volume +
+
+
+
+ menu +
+
+
+
+
+ +
+
+
+ +
+ +
+
+
+
+
+
diff --git a/web/modules/contrib/audiofield/templates/audioplayer--soundmanager--inlineplayer.html.twig b/web/modules/contrib/audiofield/templates/audioplayer--soundmanager--inlineplayer.html.twig new file mode 100644 index 00000000..a3bce4bf --- /dev/null +++ b/web/modules/contrib/audiofield/templates/audioplayer--soundmanager--inlineplayer.html.twig @@ -0,0 +1,23 @@ +{# +/** + * @file + * Inline player theme implementation for SoundManager audio player. + * + * Available variables: + * - plugin_id: the name of the plugin being used for templating. + * - plugin_theme: the name of the specific plugin theme, if it exists. + * - files: array of render info for each file. + * - settings: array of settings for thie player. + * + * @ingroup themeable + */ +#} +
+ {% for file in files %} + + {% endfor %} +
diff --git a/web/modules/contrib/audiofield/templates/audioplayer--soundmanager--player360.html.twig b/web/modules/contrib/audiofield/templates/audioplayer--soundmanager--player360.html.twig new file mode 100644 index 00000000..3a3775a5 --- /dev/null +++ b/web/modules/contrib/audiofield/templates/audioplayer--soundmanager--player360.html.twig @@ -0,0 +1,21 @@ +{# +/** + * @file + * Player 360 theme implementation for SoundManager audio player. + * + * Available variables: + * - plugin_id: the name of the plugin being used for templating. + * - plugin_theme: the name of the specific plugin theme, if it exists. + * - files: array of render info for each file. + * - settings: array of settings for thie player. + * + * @ingroup themeable + */ +#} +
+ {% for file in files %} + + {% endfor %} +
diff --git a/web/modules/contrib/audiofield/templates/audioplayer--soundmanager.html.twig b/web/modules/contrib/audiofield/templates/audioplayer--soundmanager.html.twig new file mode 100644 index 00000000..94df89b6 --- /dev/null +++ b/web/modules/contrib/audiofield/templates/audioplayer--soundmanager.html.twig @@ -0,0 +1,24 @@ +{# +/** + * @file + * Default theme implementation for SoundManager audio player. + * + * Available variables: + * - plugin_id: the name of the plugin being used for templating. + * - plugin_theme: the name of the specific plugin theme, if it exists. + * - files: array of render info for each file. + * - settings: array of settings for thie player. + * + * @see template_preprocess_audioplayer__soundmanager() + * + * @ingroup themeable + */ +#} +
+ {% for file in files %} +
+ {{ file.description }} + +
+ {% endfor %} +
diff --git a/web/modules/contrib/audiofield/templates/audioplayer--wavesurfer--playlist.html.twig b/web/modules/contrib/audiofield/templates/audioplayer--wavesurfer--playlist.html.twig new file mode 100644 index 00000000..bf76fd84 --- /dev/null +++ b/web/modules/contrib/audiofield/templates/audioplayer--wavesurfer--playlist.html.twig @@ -0,0 +1,29 @@ +{# +/** + * @file + * Playlist theme implementation for Wavesurfer audio player. + * + * Available variables: + * - plugin_id: the name of the plugin being used for templating. + * - plugin_theme: the name of the specific plugin theme, if it exists. + * - files: array of render info for each file. + * - settings: array of settings for thie player. + * + * @ingroup themeable + */ +#} +
+
+
+ +
Play
+ + + +
    + {% for file in files %} +
  1. {{ file.description }}
  2. + {% endfor %} +
+
+
diff --git a/web/modules/contrib/audiofield/templates/audioplayer--wavesurfer.html.twig b/web/modules/contrib/audiofield/templates/audioplayer--wavesurfer.html.twig new file mode 100644 index 00000000..a505dfc2 --- /dev/null +++ b/web/modules/contrib/audiofield/templates/audioplayer--wavesurfer.html.twig @@ -0,0 +1,24 @@ +{# +/** + * @file + * Default theme implementation for Wavesurfer audio player. + * + * Available variables: + * - plugin_id: the name of the plugin being used for templating. + * - plugin_theme: the name of the specific plugin theme, if it exists. + * - files: array of render info for each file. + * - settings: array of settings for thie player. + * + * @ingroup themeable + */ +#} +
+ {% for file in files %} +
+
+
Play
+ + +
+ {% endfor %} +
diff --git a/web/modules/contrib/audiofield/templates/audioplayer--wordpress.html.twig b/web/modules/contrib/audiofield/templates/audioplayer--wordpress.html.twig new file mode 100644 index 00000000..132fa69f --- /dev/null +++ b/web/modules/contrib/audiofield/templates/audioplayer--wordpress.html.twig @@ -0,0 +1,21 @@ +{# +/** + * @file + * Default theme implementation for Wordpress audio player. + * + * Available variables: + * - plugin_id: the name of the plugin being used for templating. + * - plugin_theme: the name of the specific plugin theme, if it exists. + * - files: array of render info for each file. + * - settings: array of settings for thie player. + * + * @ingroup themeable + */ +#} +
+ {% for file in files %} +
+
{{ file.description }}
+
+ {% endfor %} +
diff --git a/web/modules/contrib/audiofield/templates/audioplayer.html.twig b/web/modules/contrib/audiofield/templates/audioplayer.html.twig new file mode 100644 index 00000000..a1ec4006 --- /dev/null +++ b/web/modules/contrib/audiofield/templates/audioplayer.html.twig @@ -0,0 +1,25 @@ +{# +/** + * @file + * Default implementation for Audiofield audio players. + * + * Available variables: + * - plugin_id: the name of the plugin being used for templating. + * - plugin_theme: the name of the specific plugin theme, if it exists. + * - files: array of render info for each file. + * - settings: array of settings for thie player. + * + * @ingroup themeable + */ +#} +
+ {% for file in files %} +
+ + +
+ {% endfor %} +
diff --git a/web/modules/contrib/colorbox/LICENSE.txt b/web/modules/contrib/colorbox/LICENSE.txt new file mode 100644 index 00000000..d159169d --- /dev/null +++ b/web/modules/contrib/colorbox/LICENSE.txt @@ -0,0 +1,339 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Lesser General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. diff --git a/web/modules/contrib/colorbox/README.txt b/web/modules/contrib/colorbox/README.txt new file mode 100644 index 00000000..70aeb0d2 --- /dev/null +++ b/web/modules/contrib/colorbox/README.txt @@ -0,0 +1,122 @@ +CONTENTS OF THIS FILE +--------------------- + + * Introduction + * Features + * Requirements + * Installation + * Configuration + * Maintainers + + +INTRODUCTION +------------ + +Colorbox is a light-weight, customizable lightbox plugin for jQuery 1.4.3+. +This module allows for integration of Colorbox into Drupal. +The jQuery library is a part of Drupal since version 5+. + +* jQuery - http://jquery.com/ +* Colorbox - http://www.jacklmoore.com/colorbox/ + + +FEATURES: +--------- + +The Colorbox module: + +* Works as a Formatter in entities and in views. +* Excellent integration with core image field and image styles and the Insert + module +* Choose between a default style and a number of other styles that are included. +* Style the Colorbox with a custom Colorbox style in your theme. +* Drush command, drush colorbox-plugin, to download and install the Colorbox + plugin in "libraries/". + +The Colorbox plugin: + +* Compatible with: jQuery 1.3.2+ in Firefox, Safari, Chrome, Opera, Internet + Explorer 7+ +* Supports photos, grouping, slideshow, ajax, inline, and iframed content. +* Lightweight: 10KB of JavaScript (less than 5KBs gzipped). +* Appearance is controlled through CSS so it can be restyled. +* Can be extended with callbacks & event-hooks without altering the source + files. +* Completely unobtrusive, options are set in the JS and require no changes to + existing HTML. +* Preloads upcoming images in a photo group. +* Currently used on more than 2 million websites. +* Released under the MIT License. + + +REQUIREMENTS +------------ + +Just Colorbox plugin in "libraries". + + +INSTALLATION +------------ + +1. Install the module as normal, see link for instructions. + Link: https://www.drupal.org/documentation/install/modules-themes/modules-8 + +2. Download and unpack the Colorbox plugin in "libraries" inside root folder. + Make sure the path to the plugin file becomes: + "libraries/colorbox/jquery.colorbox-min.js" + Link: https://github.com/jackmoore/colorbox/archive/master.zip + Drush users can use the command "drush colorbox-plugin". + +3. Change the permission of colorbox plugin inside 'libraries' folder. + Right click on 'libraries' folder -> properties -> "permissions" + and change to full permission. + +4. Go to "Administer" -> "Extend" and enable the Colorbox module. + + +CONFIGURATION +------------- + + * Go to "Configuration" -> "Media" -> "Colorbox" to find all the configuration + options. + +Add a custom Colorbox style to your theme: +---------------------------------------- +The easiest way is to start with either the default style or one of the example +styles included in the Colorbox JS library download. Simply copy the entire +style folder to your theme and rename it to something logical like "mycolorbox". +Inside that folder are both a .css and .js file, rename both of those as well to +match your folder name: i.e. "colorbox_mycolorbox.css" and +"colorbox_mycolorbox.js" + +Add entries in your theme's .info file for the Colorbox CSS/JS files: + +stylesheets[all][] = mycolorbox/colorbox_mycolorbox.css +scripts[] = mycolorbox/colorbox_mycolorbox.js + +Go to "Configuration" -> "Media" -> "Colorbox" and select "None" under +"Styles and Options". This will leave the styling of Colorbox up to your theme. +Make any CSS adjustments to your "colorbox_mycolorbox.css" file. + + +Drush: +------ +A Drush command is provides for easy installation of the Colorbox plugin itself. + +% drush colorbox-plugin + +The command will download the plugin and unpack it in "libraries/". +It is possible to add another path as an option to the command, but not +recommended unless you know what you are doing. + + +MAINTAINERS +----------- + +Current maintainers: + + * Neslee Canil Pinto - https://www.drupal.org/u/neslee-canil-pinto + * Fredrik Jonsson (frjo) - https://www.drupal.org/user/5546 + +Requires - Drupal 8 +License - GPL (see LICENSE) diff --git a/web/modules/contrib/colorbox/colorbox.api.php b/web/modules/contrib/colorbox/colorbox.api.php new file mode 100644 index 00000000..1a0d52fa --- /dev/null +++ b/web/modules/contrib/colorbox/colorbox.api.php @@ -0,0 +1,35 @@ +addMessage(t('Thanks for installing Colorbox')); +} + +/** + * Implements hook_requirements(). + */ +function colorbox_requirements($phase) { + if ($phase != 'runtime') { + return []; + } + + $library = \Drupal::service('library.discovery')->getLibraryByName('colorbox', 'colorbox'); + $library_exists = file_exists(DRUPAL_ROOT . '/' . $library['js'][0]['data']); + + return [ + 'colorbox_library_downloaded' => [ + 'title' => t('Colorbox library'), + 'value' => $library_exists ? t('Installed') : t('Not installed'), + 'description' => $library_exists ? '' : t('The Colorbox library needs to be downloaded and extracted into the /libraries/colorbox folder in your Drupal installation directory.', ['@url' => 'https://github.com/jackmoore/colorbox/archive/master.zip']), + 'severity' => $library_exists ? REQUIREMENT_OK : REQUIREMENT_ERROR, + ], + ]; +} diff --git a/web/modules/contrib/colorbox/colorbox.libraries.yml b/web/modules/contrib/colorbox/colorbox.libraries.yml new file mode 100644 index 00000000..80f24387 --- /dev/null +++ b/web/modules/contrib/colorbox/colorbox.libraries.yml @@ -0,0 +1,101 @@ +colorbox: + remote: http://github.com/jackmoore/colorbox + version: VERSION + license: + name: MIT + gpl-compatible: false + js: + /libraries/colorbox/jquery.colorbox-min.js: { minified: true } + dependencies: + - core/jquery + - core/jquery.once + +colorbox-dev: + remote: http://github.com/jackmoore/colorbox + version: VERSION + license: + name: MIT + gpl-compatible: false + js: + /libraries/colorbox/jquery.colorbox.js: { } + dependencies: + - core/jquery + - core/jquery.once + +init: + version: VERSION + js: + js/colorbox.js: {} + dependencies: + - core/jquery + - core/drupal + +plain: + version: VERSION + js: + styles/plain/colorbox_style.js: {} + css: + theme: + styles/plain/colorbox_style.css: {} + dependencies: + - colorbox/init + +stockholmsyndrome: + version: VERSION + js: + styles/stockholmsyndrome/colorbox_style.js: {} + css: + theme: + styles/stockholmsyndrome/colorbox_style.css: {} + dependencies: + - colorbox/init + +default: + version: VERSION + js: + styles/default/colorbox_style.js: {} + css: + theme: + styles/default/colorbox_style.css: {} + dependencies: + - colorbox/init + +example1: + version: VERSION + css: + theme: + /libraries/colorbox/example1/colorbox.css: {} + dependencies: + - colorbox/init + +example2: + version: VERSION + css: + theme: + /libraries/colorbox/example2/colorbox.css: {} + dependencies: + - colorbox/init + +example3: + version: VERSION + css: + theme: + /libraries/colorbox/example3/colorbox.css: {} + dependencies: + - colorbox/init + +example4: + version: VERSION + css: + theme: + /libraries/colorbox/example4/colorbox.css: {} + dependencies: + - colorbox/init + +example5: + version: VERSION + css: + theme: + /libraries/colorbox/example5/colorbox.css: {} + dependencies: + - colorbox/init diff --git a/web/modules/contrib/colorbox/colorbox.links.menu.yml b/web/modules/contrib/colorbox/colorbox.links.menu.yml new file mode 100644 index 00000000..e03938c8 --- /dev/null +++ b/web/modules/contrib/colorbox/colorbox.links.menu.yml @@ -0,0 +1,5 @@ +colorbox.admin_settings: + title: 'Colorbox settings' + description: 'Configure the Colorbox settings.' + parent: system.admin_config_media + route_name: colorbox.admin_settings diff --git a/web/modules/contrib/colorbox/colorbox.module b/web/modules/contrib/colorbox/colorbox.module new file mode 100644 index 00000000..9a9a2935 --- /dev/null +++ b/web/modules/contrib/colorbox/colorbox.module @@ -0,0 +1,46 @@ +' . t('About') . ''; + $output .= '

' . t('Colorbox is a light-weight, customizable lightbox plugin for jQuery 1.4.3+. This module allows for integration of Colorbox into Drupal.
The jQuery library is a part of Drupal since version 5+.') . '

'; + $output .= '

' . t('Configuration') . '

'; + $output .= '

' . t('Go to "Configuration" -> "Media" -> "Colorbox" to find all the configuration options.') . '

'; + $output .= '

' . t('Add a custom Colorbox style to your theme') . '

'; + $output .= '

' . t('The easiest way is to start with either the default style or one of the example styles included in the Colorbox JS library download. Simply copy the entire style folder to your theme and rename it to something logical like "mycolorbox". Inside that folder are both a .css and .js file, rename both of those as well to match +your folder name: i.e. "colorbox_mycolorbox.css" and "colorbox_mycolorbox.js"') . '

'; + $output .= '

' . t("Add entries in your theme's .info file for the Colorbox CSS/JS files:") . '

'; + $output .= '

' . t('stylesheets[all][] = mycolorbox/colorbox_mycolorbox.css
scripts[] = mycolorbox/colorbox_mycolorbox.js') . '

'; + $output .= '

' . t('Go to "Configuration" -> "Media" -> "Colorbox" and select "None" under "Styles and Options". This will leave the styling of Colorbox up to your theme.
Make any CSS adjustments to your "colorbox_mycolorbox.css" file.') . '

'; + return $output; + } +} + +/** + * Implements hook_theme(). + */ +function colorbox_theme() { + return [ + 'colorbox_formatter' => [ + 'variables' => [ + 'item' => NULL, + 'item_attributes' => NULL, + 'entity' => NULL, + 'settings' => NULL, + ], + 'file' => 'colorbox.theme.inc', + ], + ]; +} diff --git a/web/modules/contrib/colorbox/colorbox.post_update.php b/web/modules/contrib/colorbox/colorbox.post_update.php new file mode 100644 index 00000000..a4815432 --- /dev/null +++ b/web/modules/contrib/colorbox/colorbox.post_update.php @@ -0,0 +1,22 @@ +save(); + } +} diff --git a/web/modules/contrib/colorbox/colorbox.routing.yml b/web/modules/contrib/colorbox/colorbox.routing.yml new file mode 100644 index 00000000..4932b48c --- /dev/null +++ b/web/modules/contrib/colorbox/colorbox.routing.yml @@ -0,0 +1,7 @@ +colorbox.admin_settings: + path: '/admin/config/media/colorbox' + defaults: + _form: '\Drupal\colorbox\Form\ColorboxSettingsForm' + _title: 'Colorbox settings' + requirements: + _permission: 'administer site configuration' diff --git a/web/modules/contrib/colorbox/colorbox.services.yml b/web/modules/contrib/colorbox/colorbox.services.yml new file mode 100644 index 00000000..d7ffa363 --- /dev/null +++ b/web/modules/contrib/colorbox/colorbox.services.yml @@ -0,0 +1,10 @@ +services: + colorbox.activation_check: + class: Drupal\colorbox\ActivationCheck + arguments: ['@config.factory', '@request_stack'] + colorbox.attachment: + class: Drupal\colorbox\ColorboxAttachment + arguments: ['@colorbox.activation_check', '@module_handler', '@config.factory'] + colorbox.gallery_id_generator: + class: Drupal\colorbox\GalleryIdHelper + arguments: ['@config.factory', '@token'] diff --git a/web/modules/contrib/colorbox/colorbox.theme.inc b/web/modules/contrib/colorbox/colorbox.theme.inc new file mode 100644 index 00000000..07f17757 --- /dev/null +++ b/web/modules/contrib/colorbox/colorbox.theme.inc @@ -0,0 +1,161 @@ +entity->getFileUri(); + $classes_array = ['colorbox']; + $data_cbox_img_attrs = []; + + // Build the caption. + $entity_title = $entity->label(); + $entity_type = $entity->getEntityTypeId(); + + switch ($settings['colorbox_caption']) { + case 'auto': + // If the title is empty use alt or the entity title in that order. + if (!empty($item->title)) { + $caption = $item->title; + } + elseif (!empty($item->alt)) { + $caption = $item->alt; + } + elseif (!empty($entity_title)) { + $caption = $entity_title; + } + else { + $caption = ''; + } + break; + + case 'title': + $caption = $item->title; + break; + + case 'alt': + $caption = $item->alt; + break; + + case 'entity_title': + $caption = $entity_title; + break; + + case 'custom': + $token_service = \Drupal::token(); + $caption = $token_service->replace( + $settings['colorbox_caption_custom'], + [$entity_type => $entity, 'file' => $item], + ['clear' => TRUE] + ); + break; + + default: + $caption = ''; + } + + // Shorten the caption for the example styles or when caption + // shortening is active. + $config = \Drupal::config('colorbox.settings'); + $colorbox_style = $config->get('colorbox_style'); + $trim_length = $config->get('colorbox_caption_trim_length'); + if (((strpos($colorbox_style, 'colorbox/example') !== FALSE) || $config->get('colorbox_caption_trim')) && (strlen($caption) > $trim_length)) { + $caption = substr($caption, 0, $trim_length - 5) . '...'; + } + + $gallery_id = \Drupal::service('colorbox.gallery_id_generator')->generateId($entity, $item, $settings); + + // Set up the $variables['image'] parameter. + if ($settings['style_name'] == 'hide') { + $variables['image'] = []; + $classes_array[] = 'js-hide'; + } + elseif (!empty($settings['style_name'])) { + $variables['image'] = [ + '#theme' => 'image_style', + '#style_name' => $settings['style_name'], + ]; + } + else { + $variables['image'] = [ + '#theme' => 'image', + ]; + } + + if (!empty($variables['image'])) { + $variables['image']['#attributes'] = $item_attributes; + + // Do not output an empty 'title' attribute. + if (strlen($item->title) != 0) { + $variables['image']['#title'] = $item->title; + $data_cbox_img_attrs['title'] = '"title":"' . $item->title . '"'; + } + + foreach (['width', 'height', 'alt'] as $key) { + $variables['image']["#$key"] = $item->$key; + if ($key == 'alt') { + $data_cbox_img_attrs['alt'] = '"alt":"' . $item->alt . '"'; + } + } + + $variables['image']['#uri'] = empty($item->uri) ? $image_uri : $item->uri; + } + + if (!empty($settings['colorbox_image_style'])) { + $style = ImageStyle::load($settings['colorbox_image_style']); + $variables['url'] = $style->buildUrl($image_uri); + } + else { + $variables['url'] = file_create_url($image_uri); + } + + // If File Entity module is enabled, load attribute values from file entity. + if (\Drupal::moduleHandler()->moduleExists('file_entity')) { + // File id of the save file. + $fid = $item->target_id; + // Load file object. + $file_obj = File::load($fid); + $file_array = $file_obj->toArray(); + // Populate the image title. + if (!empty($file_array['field_image_title_text'][0]['value']) && empty($item->title) && $settings['colorbox_caption'] == 'title') { + $caption = $file_array['field_image_title_text'][0]['value']; + } + // Populate the image alt text. + if (!empty($file_array['field_image_alt_text'][0]['value']) && empty($item->alt) && $settings['colorbox_caption'] == 'alt') { + $caption = $file_array['field_image_alt_text'][0]['value']; + } + } + + $variables['attributes']['title'] = $caption; + $variables['attributes']['data-colorbox-gallery'] = $gallery_id; + $variables['attributes']['class'] = $classes_array; + if (!empty($data_cbox_img_attrs)) { + $variables['attributes']['data-cbox-img-attrs'] = '{' . implode(',', $data_cbox_img_attrs) . '}'; + } +} diff --git a/web/modules/contrib/colorbox/composer.json b/web/modules/contrib/colorbox/composer.json new file mode 100644 index 00000000..5ce7f1fe --- /dev/null +++ b/web/modules/contrib/colorbox/composer.json @@ -0,0 +1,51 @@ +{ + "name": "drupal/colorbox", + "description": "A light-weight, customizable lightbox plugin for jQuery.", + "type": "drupal-module", + "homepage": "https://www.drupal.org/project/colorbox", + "support": { + "issues": "https://www.drupal.org/project/issues/colorbox", + "source": "https://git.drupalcode.org/project/colorbox" + }, + "license": "GPL-2.0-or-later", + "minimum-stability": "dev", + "authors": [ + { + "name": "Neslee Canil Pinto", + "homepage": "https://www.drupal.org/u/neslee-canil-pinto", + "role": "Maintainer" + }, + { + "name": "Fredrik Jonsson", + "homepage": "https://www.drupal.org/u/frjo", + "role": "Maintainer" + } + ], + "repositories": [ + { + "type": "package", + "package": { + "name": "jackmoore/colorbox", + "version": "1.6.4", + "type": "drupal-library", + "dist": { + "url": "https://github.com/jackmoore/colorbox/archive/1.6.4.zip", + "type": "zip" + } + } + } + ], + "require": { + "drupal/core": "^8.8 || ^9" + }, + "suggest": { + "jackmoore/colorbox": "The Colorbox library is required to use the drupal/colorbox module." + }, + "extra": { + "drush": { + "services": { + "drush.services.yml": "^9" + } + } + } +} diff --git a/web/modules/contrib/colorbox/config/install/colorbox.settings.yml b/web/modules/contrib/colorbox/config/install/colorbox.settings.yml new file mode 100644 index 00000000..c25fff31 --- /dev/null +++ b/web/modules/contrib/colorbox/config/install/colorbox.settings.yml @@ -0,0 +1,31 @@ +custom: + style: 'default' + activate: 0 + transition_type: 'elastic' + transition_speed: 350 + opacity: 0.85 + text_current: '{current} of {total}' + text_previous: '« Prev' + text_next: 'Next »' + text_close: 'Close' + maxwidth: '98%' + maxheight: '98%' + initialwidth: '300' + initialheight: '250' + overlayclose: TRUE + returnfocus: TRUE + fixed: TRUE + scrolling: TRUE + slideshow: + slideshow: 0 + auto: TRUE + speed: 2500 + text_start: 'start slideshow' + text_stop: 'stop slideshow' +advanced: + unique_token: 1 + mobile_detect: 1 + mobile_device_width: '480px' + caption_trim: 0 + caption_trim_length: 75 + compression_type: 'minified' diff --git a/web/modules/contrib/colorbox/config/schema/colorbox.schema.yml b/web/modules/contrib/colorbox/config/schema/colorbox.schema.yml new file mode 100644 index 00000000..e5ae990b --- /dev/null +++ b/web/modules/contrib/colorbox/config/schema/colorbox.schema.yml @@ -0,0 +1,126 @@ +field.formatter.settings.colorbox: + type: mapping + label: 'Entity reference field formatter settings.' + mapping: + colorbox_node_style: + type: string + label: 'Node Style' + colorbox_node_style_first: + type: string + label: 'Node style first' + colorbox_image_style: + type: string + label: 'Image style' + colorbox_gallery: + type: string + label: 'Gallery' + colorbox_gallery_custom: + type: string + label: 'Gallery custom' + colorbox_caption: + type: string + label: 'Caption' + colorbox_caption_custom: + type: string + label: 'Caption custom' + +colorbox.settings: + type: config_object + label: 'Colorbox settings' + mapping: + custom: + type: mapping + label: Custom Settings + mapping: + style: + type: string + label: 'Style' + activate: + type: integer + label: 'Options' + transition_type: + type: string + label: 'Transition type' + transition_speed: + type: integer + label: 'Transition speed' + opacity: + type: float + label: 'Opacity' + text_current: + type: text + label: 'Current' + text_previous: + type: text + label: 'Previous' + text_next: + type: text + label: 'Next' + text_close: + type: text + label: 'Close' + maxwidth: + type: text + label: 'Max width' + maxheight: + type: text + label: 'Max height' + initialwidth: + type: text + label: 'Initial width' + initialheight: + type: text + label: 'Initial height' + overlayclose: + type: boolean + label: 'Overlay close' + returnfocus: + type: boolean + label: 'Return focus' + fixed: + type: boolean + label: 'Fixed' + scrolling: + type: boolean + label: 'Scrollbars' + slideshow: + type: mapping + label: 'Slideshow' + mapping: + slideshow: + type: integer + label: 'Slideshow' + auto: + type: boolean + label: 'Slideshow autostart' + speed: + type: integer + label: 'Slideshow speed' + text_start: + type: text + label: 'Start slideshow' + text_stop: + type: text + label: 'Stop slideshow' + advanced: + type: mapping + label: 'Advanced settings' + mapping: + unique_token: + type: integer + label: 'Unique per-request gallery token' + mobile_detect: + type: integer + label: 'Mobile detection' + mobile_device_width: + type: string + label: 'Device width' + caption_trim: + type: integer + label: 'Caption shortening' + caption_trim_length: + type: integer + label: 'Caption max length' + compression_type: + type: string + label: 'Colorbox compression level' diff --git a/web/modules/contrib/colorbox/drush.services.yml b/web/modules/contrib/colorbox/drush.services.yml new file mode 100644 index 00000000..e1dbbcf8 --- /dev/null +++ b/web/modules/contrib/colorbox/drush.services.yml @@ -0,0 +1,7 @@ +services: + colorbox.commands: + class: \Drupal\colorbox\Commands\ColorboxCommands + arguments: + - '@library.discovery' + tags: + - { name: drush.command } diff --git a/web/modules/contrib/colorbox/drush/colorbox.drush.inc b/web/modules/contrib/colorbox/drush/colorbox.drush.inc new file mode 100644 index 00000000..d98aa0e9 --- /dev/null +++ b/web/modules/contrib/colorbox/drush/colorbox.drush.inc @@ -0,0 +1,103 @@ + 'drush_colorbox_plugin', + 'description' => dt('Download and install the Colorbox plugin.'), + // No bootstrap. + 'bootstrap' => DRUSH_BOOTSTRAP_DRUSH, + 'arguments' => [ + 'path' => dt('Optional. A path where to install the Colorbox plugin. If omitted Drush will use the default location.'), + ], + 'aliases' => ['colorboxplugin'], + ]; + + return $items; +} + +/** + * Implements hook_drush_help(). + * + * This function is called whenever a drush user calls + * 'drush help ' + */ +function colorbox_drush_help($section) { + switch ($section) { + case 'drush:colorbox-plugin': + return dt('Download and install the Colorbox plugin from jacklmoore.com/colorbox, default location is the libraries directory.'); + } +} + +/** + * Command to download the Colorbox plugin. + */ +function drush_colorbox_plugin() { + $args = func_get_args(); + if (!empty($args[0])) { + $path = $args[0]; + } + else { + $path = 'libraries'; + } + + // Create the path if it does not exist. + if (!is_dir($path)) { + drush_op('mkdir', $path); + \Drupal::logger(dt('Directory @path was created', ['@path' => $path]))->notice('notice'); + } + + // Set the directory to the download location. + $olddir = getcwd(); + chdir($path); + + // Download the zip archive. + if ($filepath = drush_download_file(COLORBOX_DOWNLOAD_URI)) { + $filename = basename($filepath); + $dirname = COLORBOX_DOWNLOAD_PREFIX . basename($filepath, '.zip'); + + // Remove any existing Colorbox plugin directory. + if (is_dir($dirname) || is_dir('colorbox')) { + Filesystem::remove($dirname, TRUE); + Filesystem::remove('colorbox', TRUE); + \Drupal::logger(dt('A existing Colorbox plugin was deleted from @path', ['@path' => $path]))->notice('notice'); + } + + // Decompress the zip archive. + drush_tarball_extract($filename); + + // Change the directory name to "colorbox" if needed. + if ($dirname != 'colorbox') { + drush_move_dir($dirname, 'colorbox', TRUE); + $dirname = 'colorbox'; + } + } + + if (is_dir($dirname)) { + \Drupal::logger(dt('Colorbox plugin has been installed in @path', ['@path' => $path]))->success('success'); + } + else { + \Drupal::logger(dt('Drush was unable to install the Colorbox plugin to @path', ['@path' => $path]))->error('error'); + } + + // Set working directory back to the previous working directory. + chdir($olddir); +} diff --git a/web/modules/contrib/colorbox/images/admin/colorbox_example_1.png b/web/modules/contrib/colorbox/images/admin/colorbox_example_1.png new file mode 100644 index 00000000..7ed90d6a Binary files /dev/null and b/web/modules/contrib/colorbox/images/admin/colorbox_example_1.png differ diff --git a/web/modules/contrib/colorbox/images/admin/colorbox_example_2.png b/web/modules/contrib/colorbox/images/admin/colorbox_example_2.png new file mode 100644 index 00000000..927dfa38 Binary files /dev/null and b/web/modules/contrib/colorbox/images/admin/colorbox_example_2.png differ diff --git a/web/modules/contrib/colorbox/images/admin/colorbox_example_3.png b/web/modules/contrib/colorbox/images/admin/colorbox_example_3.png new file mode 100644 index 00000000..6533b7db Binary files /dev/null and b/web/modules/contrib/colorbox/images/admin/colorbox_example_3.png differ diff --git a/web/modules/contrib/colorbox/images/admin/colorbox_example_4.png b/web/modules/contrib/colorbox/images/admin/colorbox_example_4.png new file mode 100644 index 00000000..14a05d93 Binary files /dev/null and b/web/modules/contrib/colorbox/images/admin/colorbox_example_4.png differ diff --git a/web/modules/contrib/colorbox/images/admin/example_default.png b/web/modules/contrib/colorbox/images/admin/example_default.png new file mode 100644 index 00000000..439ebe6b Binary files /dev/null and b/web/modules/contrib/colorbox/images/admin/example_default.png differ diff --git a/web/modules/contrib/colorbox/images/admin/example_none.png b/web/modules/contrib/colorbox/images/admin/example_none.png new file mode 100644 index 00000000..7f8d4137 Binary files /dev/null and b/web/modules/contrib/colorbox/images/admin/example_none.png differ diff --git a/web/modules/contrib/colorbox/images/admin/example_plain.png b/web/modules/contrib/colorbox/images/admin/example_plain.png new file mode 100644 index 00000000..20bf6188 Binary files /dev/null and b/web/modules/contrib/colorbox/images/admin/example_plain.png differ diff --git a/web/modules/contrib/colorbox/images/admin/example_stockholm_syndrome.png b/web/modules/contrib/colorbox/images/admin/example_stockholm_syndrome.png new file mode 100644 index 00000000..e84f4439 Binary files /dev/null and b/web/modules/contrib/colorbox/images/admin/example_stockholm_syndrome.png differ diff --git a/web/modules/contrib/colorbox/images/controls.png b/web/modules/contrib/colorbox/images/controls.png new file mode 100644 index 00000000..22389727 Binary files /dev/null and b/web/modules/contrib/colorbox/images/controls.png differ diff --git a/web/modules/contrib/colorbox/images/loading_animation.gif b/web/modules/contrib/colorbox/images/loading_animation.gif new file mode 100644 index 00000000..f864d5fd Binary files /dev/null and b/web/modules/contrib/colorbox/images/loading_animation.gif differ diff --git a/web/modules/contrib/colorbox/images/loading_background.png b/web/modules/contrib/colorbox/images/loading_background.png new file mode 100644 index 00000000..9de11f46 Binary files /dev/null and b/web/modules/contrib/colorbox/images/loading_background.png differ diff --git a/web/modules/contrib/colorbox/js/colorbox.js b/web/modules/contrib/colorbox/js/colorbox.js new file mode 100644 index 00000000..6824c91b --- /dev/null +++ b/web/modules/contrib/colorbox/js/colorbox.js @@ -0,0 +1,35 @@ +/** + * @file + * Colorbox JS. + */ + +(function ($, Drupal) { + + 'use strict'; + + Drupal.behaviors.initColorbox = { + attach: function (context, settings) { + if (!$.isFunction($.colorbox) || typeof settings.colorbox === 'undefined') { + return; + } + + if (settings.colorbox.mobiledetect && window.matchMedia) { + // Disable Colorbox for small screens. + var mq = window.matchMedia('(max-device-width: ' + settings.colorbox.mobiledevicewidth + ')'); + if (mq.matches) { + $.colorbox.remove(); + return; + } + } + + settings.colorbox.rel = function () { + return $(this).data('colorbox-gallery') + }; + + $('.colorbox', context) + .once('init-colorbox') + .colorbox(settings.colorbox); + } + }; + +})(jQuery, Drupal); diff --git a/web/modules/contrib/colorbox/src/ActivationCheck.php b/web/modules/contrib/colorbox/src/ActivationCheck.php new file mode 100644 index 00000000..15ae847a --- /dev/null +++ b/web/modules/contrib/colorbox/src/ActivationCheck.php @@ -0,0 +1,42 @@ +settings = $config->get('colorbox.settings'); + $this->request = $request->getCurrentRequest(); + } + + /** + * {@inheritdoc} + */ + public function isActive() { + return $this->request->get('colorbox') !== 'no'; + } + +} diff --git a/web/modules/contrib/colorbox/src/ActivationCheckInterface.php b/web/modules/contrib/colorbox/src/ActivationCheckInterface.php new file mode 100644 index 00000000..9a9e773d --- /dev/null +++ b/web/modules/contrib/colorbox/src/ActivationCheckInterface.php @@ -0,0 +1,18 @@ +activation = $activation; + $this->moduleHandler = $module_handler; + $this->settings = $config->get('colorbox.settings'); + } + + /** + * {@inheritdoc} + */ + public function isApplicable() { + return !InstallerKernel::installationAttempted() && $this->activation->isActive(); + } + + /** + * {@inheritdoc} + */ + public function attach(array &$page) { + if ($this->settings->get('custom.activate')) { + $js_settings = [ + 'transition' => $this->settings->get('custom.transition_type'), + 'speed' => $this->settings->get('custom.transition_speed'), + 'opacity' => $this->settings->get('custom.opacity'), + 'slideshow' => $this->settings->get('custom.slideshow.slideshow') ? TRUE : FALSE, + 'slideshowAuto' => $this->settings->get('custom.slideshow.auto') ? TRUE : FALSE, + 'slideshowSpeed' => $this->settings->get('custom.slideshow.speed'), + 'slideshowStart' => $this->settings->get('custom.slideshow.text_start'), + 'slideshowStop' => $this->settings->get('custom.slideshow.text_stop'), + 'current' => $this->settings->get('custom.text_current'), + 'previous' => $this->settings->get('custom.text_previous'), + 'next' => $this->settings->get('custom.text_next'), + 'close' => $this->settings->get('custom.text_close'), + 'overlayClose' => $this->settings->get('custom.overlayclose') ? TRUE : FALSE, + 'returnFocus' => $this->settings->get('custom.returnfocus') ? TRUE : FALSE, + 'maxWidth' => $this->settings->get('custom.maxwidth'), + 'maxHeight' => $this->settings->get('custom.maxheight'), + 'initialWidth' => $this->settings->get('custom.initialwidth'), + 'initialHeight' => $this->settings->get('custom.initialheight'), + 'fixed' => $this->settings->get('custom.fixed') ? TRUE : FALSE, + 'scrolling' => $this->settings->get('custom.scrolling') ? TRUE : FALSE, + 'mobiledetect' => $this->settings->get('advanced.mobile_detect') ? TRUE : FALSE, + 'mobiledevicewidth' => $this->settings->get('advanced.mobile_device_width'), + ]; + } + else { + $js_settings = [ + 'opacity' => '0.85', + 'current' => $this->t('{current} of {total}'), + 'previous' => $this->t('« Prev'), + 'next' => $this->t('Next »'), + 'close' => $this->t('Close'), + 'maxWidth' => '98%', + 'maxHeight' => '98%', + 'fixed' => TRUE, + 'mobiledetect' => $this->settings->get('advanced.mobile_detect') ? TRUE : FALSE, + 'mobiledevicewidth' => $this->settings->get('advanced.mobile_device_width'), + ]; + } + + $style = $this->settings->get('custom.style'); + + // Give other modules the possibility to override Colorbox + // settings and style. + $this->moduleHandler->alter('colorbox_settings', $js_settings, $style); + + // Add colorbox js settings. + $page['#attached']['drupalSettings']['colorbox'] = $js_settings; + + // Add and initialise the Colorbox plugin. + if ($this->settings->get('advanced.compression_type') == 'minified') { + $page['#attached']['library'][] = 'colorbox/colorbox'; + } + else { + $page['#attached']['library'][] = 'colorbox/colorbox-dev'; + } + + // Add JS and CSS based on selected style. + if ($style != 'none') { + $page['#attached']['library'][] = "colorbox/$style"; + } + else { + $page['#attached']['library'][] = "colorbox/init"; + } + } + +} diff --git a/web/modules/contrib/colorbox/src/Commands/ColorboxCommands.php b/web/modules/contrib/colorbox/src/Commands/ColorboxCommands.php new file mode 100644 index 00000000..9b5f8168 --- /dev/null +++ b/web/modules/contrib/colorbox/src/Commands/ColorboxCommands.php @@ -0,0 +1,118 @@ +libraryDiscovery = $library_discovery; + } + + /** + * Download and install the Colorbox plugin. + * + * @param mixed $path + * Optional. A path where to install the Colorbox plugin. + * If omitted Drush will use the default location. + * + * @command colorbox:plugin + * @aliases colorboxplugin,colorbox-plugin + */ + public function download($path = '') { + + $fs = new Filesystem(); + + if (empty($path)) { + $path = DRUPAL_ROOT . '/libraries/colorbox'; + } + + // Create path if it doesn't exist + // Exit with a message otherwise. + if (!$fs->exists($path)) { + $fs->mkdir($path); + } + else { + $this->logger()->notice(dt('Colorbox is already present at @path. No download required.', ['@path' => $path])); + return; + } + + // Load the colorbox defined library. + if ($colorbox_library = $this->libraryDiscovery->getLibraryByName('colorbox', 'colorbox')) { + // Download the file. + $client = new Client(); + $destination = tempnam(sys_get_temp_dir(), 'colorbox-tmp'); + try { + $client->get($colorbox_library['remote'] . '/archive/master.zip', ['save_to' => $destination]); + } + catch (RequestException $e) { + // Remove the directory. + $fs->remove($path); + $this->logger()->error(dt('Drush was unable to download the colorbox library from @remote. @exception', [ + '@remote' => $colorbox_library['remote'] . '/archive/master.zip', + '@exception' => $e->getMessage(), + ], 'error')); + return; + } + + // Move downloaded file. + $fs->rename($destination, $path . '/colorbox.zip'); + + // Unzip the file. + $zip = new \ZipArchive(); + $res = $zip->open($path . '/colorbox.zip'); + if ($res === TRUE) { + $zip->extractTo($path); + $zip->close(); + } + else { + // Remove the directory if unzip fails and exit. + $fs->remove($path); + $this->logger()->error(dt('Error: unable to unzip colorbox file.', [], 'error')); + return; + } + + // Remove the downloaded zip file. + $fs->remove($path . '/colorbox.zip'); + + // Move the file. + $fs->mirror($path . '/colorbox-master', $path, NULL, ['override' => TRUE]); + $fs->remove($path . '/colorbox-master'); + + // Success. + $this->logger()->notice(dt('The colorbox library has been successfully downloaded to @path.', [ + '@path' => $path, + ], 'success')); + } + else { + $this->logger()->error(dt('Drush was unable to load the colorbox library')); + } + } + +} diff --git a/web/modules/contrib/colorbox/src/ElementAttachmentInterface.php b/web/modules/contrib/colorbox/src/ElementAttachmentInterface.php new file mode 100644 index 00000000..56cfabb9 --- /dev/null +++ b/web/modules/contrib/colorbox/src/ElementAttachmentInterface.php @@ -0,0 +1,26 @@ +moduleHandler = $moduleHandler; + } + + /** + * {@inheritdoc} + */ + public static function create(ContainerInterface $container) { + return new static( + $container->get('config.factory'), + $container->get('module_handler') + ); + } + + /** + * {@inheritdoc} + */ + public function getFormId() { + return 'colorbox_admin_settings_form'; + } + + /** + * {@inheritdoc} + */ + protected function getEditableConfigNames() { + return ['colorbox.settings']; + } + + /** + * {@inheritdoc} + */ + public function buildForm(array $form, FormStateInterface $form_state) { + global $base_url; + $module_path = \Drupal::service('extension.list.module')->getPath('colorbox'); + $img_folder_path = $base_url . '/' . $module_path . '/images/admin'; + + $config = $this->configFactory->get('colorbox.settings'); + + $form['colorbox_custom_settings'] = [ + '#type' => 'details', + '#title' => $this->t('Styles and options'), + '#open' => TRUE, + ]; + $colorbox_styles = [ + 'default' => $this->t('Default'), + 'plain' => $this->t('Plain (mainly for images)'), + 'stockholmsyndrome' => $this->t('Stockholm Syndrome'), + 'example1' => $this->t('Example 1'), + 'example2' => $this->t('Example 2'), + 'example3' => $this->t('Example 3'), + 'example4' => $this->t('Example 4'), + 'example5' => $this->t('Example 5'), + 'none' => $this->t('None'), + ]; + $form['colorbox_custom_settings']['colorbox_style'] = [ + '#type' => 'select', + '#title' => $this->t('Style'), + '#options' => $colorbox_styles, + '#default_value' => $config->get('custom.style'), + '#description' => $this->t('Select the style to use for the Colorbox. The example styles are the ones that come with the Colorbox plugin. Select "None" if you have added Colorbox styles to your theme.
Examples: ', ['@img_folder_path' => $img_folder_path]), + ]; + $form['colorbox_custom_settings']['colorbox_custom_settings_activate'] = [ + '#type' => 'radios', + '#title' => $this->t('Options'), + '#options' => [0 => $this->t('Default'), 1 => $this->t('Custom')], + '#default_value' => $config->get('custom.activate'), + '#description' => $this->t('Use the default or custom options for Colorbox.'), + ]; + $form['colorbox_custom_settings']['colorbox_transition_type'] = [ + '#type' => 'radios', + '#title' => $this->t('Transition type'), + '#options' => [ + 'elastic' => $this->t('Elastic'), + 'fade' => $this->t('Fade'), + 'none' => $this->t('None'), + ], + '#default_value' => $config->get('custom.transition_type'), + '#description' => $this->t('The transition type.'), + '#states' => $this->getState(static::STATE_CUSTOM_SETTINGS), + ]; + $form['colorbox_custom_settings']['colorbox_transition_speed'] = [ + '#type' => 'select', + '#title' => $this->t('Transition speed'), + '#options' => $this->optionsRange(100, 600, 50), + '#default_value' => $config->get('custom.transition_speed'), + '#description' => $this->t('Sets the speed of the fade and elastic transitions, in milliseconds.'), + '#states' => $this->getState(static::STATE_CUSTOM_SETTINGS), + ]; + $form['colorbox_custom_settings']['colorbox_opacity'] = [ + '#type' => 'select', + '#title' => $this->t('Opacity'), + '#options' => $this->optionsRange(0, 1, 0.05), + '#default_value' => $config->get('custom.opacity'), + '#description' => $this->t('The overlay opacity level. Range: 0 to 1.'), + '#states' => $this->getState(static::STATE_CUSTOM_SETTINGS), + ]; + $form['colorbox_custom_settings']['colorbox_text_current'] = [ + '#type' => 'textfield', + '#title' => $this->t('Current'), + '#default_value' => $config->get('custom.text_current'), + '#size' => 30, + '#description' => $this->t('Text format for the content group / gallery count. {current} and {total} are detected and replaced with actual numbers while Colorbox runs.'), + '#states' => $this->getState(static::STATE_CUSTOM_SETTINGS), + ]; + $form['colorbox_custom_settings']['colorbox_text_previous'] = [ + '#type' => 'textfield', + '#title' => $this->t('Previous'), + '#default_value' => $config->get('custom.text_previous'), + '#size' => 30, + '#description' => $this->t('Text for the previous button in a shared relation group.'), + '#states' => $this->getState(static::STATE_CUSTOM_SETTINGS), + ]; + $form['colorbox_custom_settings']['colorbox_text_next'] = [ + '#type' => 'textfield', + '#title' => $this->t('Next'), + '#default_value' => $config->get('custom.text_next'), + '#size' => 30, + '#description' => $this->t('Text for the next button in a shared relation group.'), + '#states' => $this->getState(static::STATE_CUSTOM_SETTINGS), + ]; + $form['colorbox_custom_settings']['colorbox_text_close'] = [ + '#type' => 'textfield', + '#title' => $this->t('Close'), + '#default_value' => $config->get('custom.text_close'), + '#size' => 30, + '#description' => $this->t('Text for the close button. The "Esc" key will also close Colorbox.'), + '#states' => $this->getState(static::STATE_CUSTOM_SETTINGS), + ]; + $form['colorbox_custom_settings']['colorbox_maxwidth'] = [ + '#type' => 'textfield', + '#title' => $this->t('Max width'), + '#default_value' => $config->get('custom.maxwidth'), + '#size' => 30, + '#description' => $this->t('Set a maximum width for loaded content. Example: "100%", 500, "500px".'), + '#states' => $this->getState(static::STATE_CUSTOM_SETTINGS), + ]; + $form['colorbox_custom_settings']['colorbox_maxheight'] = [ + '#type' => 'textfield', + '#title' => $this->t('Max height'), + '#default_value' => $config->get('custom.maxheight'), + '#size' => 30, + '#description' => $this->t('Set a maximum height for loaded content. Example: "100%", 500, "500px".'), + '#states' => $this->getState(static::STATE_CUSTOM_SETTINGS), + ]; + $form['colorbox_custom_settings']['colorbox_initialwidth'] = [ + '#type' => 'textfield', + '#title' => $this->t('Initial width'), + '#default_value' => $config->get('custom.initialwidth'), + '#size' => 30, + '#description' => $this->t('Set the initial width, prior to any content being loaded. Example: "100%", 500, "500px".'), + '#states' => $this->getState(static::STATE_CUSTOM_SETTINGS), + ]; + $form['colorbox_custom_settings']['colorbox_initialheight'] = [ + '#type' => 'textfield', + '#title' => $this->t('Initial height'), + '#default_value' => $config->get('custom.initialheight'), + '#size' => 30, + '#description' => $this->t('Set the initial height, prior to any content being loaded. Example: "100%", 500, "500px".'), + '#states' => $this->getState(static::STATE_CUSTOM_SETTINGS), + ]; + $form['colorbox_custom_settings']['colorbox_overlayclose'] = [ + '#type' => 'checkbox', + '#title' => $this->t('Overlay close'), + '#default_value' => $config->get('custom.overlayclose'), + '#description' => $this->t('Enable closing Colorbox by clicking on the background overlay.'), + '#states' => $this->getState(static::STATE_CUSTOM_SETTINGS), + ]; + $form['colorbox_custom_settings']['colorbox_returnfocus'] = [ + '#type' => 'checkbox', + '#title' => $this->t('Return focus'), + '#default_value' => $config->get('custom.returnfocus'), + '#description' => $this->t('Return focus when Colorbox exits to the element it was launched from.'), + '#states' => $this->getState(static::STATE_CUSTOM_SETTINGS), + ]; + $form['colorbox_custom_settings']['colorbox_fixed'] = [ + '#type' => 'checkbox', + '#title' => $this->t('Fixed'), + '#default_value' => $config->get('custom.fixed'), + '#description' => $this->t("If the Colorbox should be displayed in a fixed position within the visitor's viewport or relative to the document."), + '#states' => $this->getState(static::STATE_CUSTOM_SETTINGS), + ]; + $form['colorbox_custom_settings']['colorbox_scrolling'] = [ + '#type' => 'checkbox', + '#title' => $this->t('Scrollbars'), + '#default_value' => $config->get('custom.scrolling'), + '#description' => $this->t('If unchecked, Colorbox will hide scrollbars for overflowing content. This could be used on conjunction with the resize method for a smoother transition if you are appending content to an already open instance of Colorbox.'), + '#states' => $this->getState(static::STATE_CUSTOM_SETTINGS), + ]; + + $form['colorbox_custom_settings']['colorbox_slideshow_settings'] = [ + '#type' => 'details', + '#title' => $this->t('Slideshow settings'), + '#collapsible' => TRUE, + '#collapsed' => TRUE, + '#states' => $this->getState(static::STATE_CUSTOM_SETTINGS), + ]; + $form['colorbox_custom_settings']['colorbox_slideshow_settings']['colorbox_slideshow'] = [ + '#type' => 'radios', + '#title' => $this->t('Slideshow'), + '#options' => [0 => $this->t('Off'), 1 => $this->t('On')], + '#default_value' => $config->get('custom.slideshow.slideshow'), + '#description' => $this->t('An automatic slideshow to a content group / gallery.'), + ]; + $form['colorbox_custom_settings']['colorbox_slideshow_settings']['colorbox_slideshowauto'] = [ + '#type' => 'checkbox', + '#title' => $this->t('Slideshow autostart'), + '#default_value' => $config->get('custom.slideshow.auto'), + '#description' => $this->t('If the slideshow should automatically start to play.'), + '#states' => $this->getState(static::STATE_SLIDESHOW_ENABLED), + ]; + $form['colorbox_custom_settings']['colorbox_slideshow_settings']['colorbox_slideshowspeed'] = [ + '#type' => 'select', + '#title' => $this->t('Slideshow speed'), + '#options' => $this->optionsRange(1000, 6000, 500), + '#default_value' => $config->get('custom.slideshow.speed'), + '#description' => $this->t('Sets the speed of the slideshow, in milliseconds.'), + '#states' => $this->getState(static::STATE_SLIDESHOW_ENABLED), + ]; + $form['colorbox_custom_settings']['colorbox_slideshow_settings']['colorbox_text_start'] = [ + '#type' => 'textfield', + '#title' => $this->t('Start slideshow'), + '#default_value' => $config->get('custom.slideshow.text_start'), + '#size' => 30, + '#description' => $this->t('Text for the slideshow start button.'), + '#states' => $this->getState(static::STATE_SLIDESHOW_ENABLED), + ]; + $form['colorbox_custom_settings']['colorbox_slideshow_settings']['colorbox_text_stop'] = [ + '#type' => 'textfield', + '#title' => $this->t('Stop slideshow'), + '#default_value' => $config->get('custom.slideshow.text_stop'), + '#size' => 30, + '#description' => $this->t('Text for the slideshow stop button.'), + '#states' => $this->getState(static::STATE_SLIDESHOW_ENABLED), + ]; + + $form['colorbox_advanced_settings'] = [ + '#type' => 'details', + '#title' => $this->t('Advanced settings'), + ]; + $form['colorbox_advanced_settings']['colorbox_unique_token'] = [ + '#type' => 'radios', + '#title' => $this->t('Unique per-request gallery token'), + '#options' => [1 => $this->t('On'), 0 => $this->t('Off')], + '#default_value' => $config->get('advanced.unique_token'), + '#description' => $this->t('If On (default), Colorbox will add a unique per-request token to the gallery id to avoid images being added manually to galleries. The token was added as a security fix but some see the old behavoiur as an feature and this settings makes it possible to remove the token.'), + ]; + $form['colorbox_advanced_settings']['colorbox_mobile_detect'] = [ + '#type' => 'radios', + '#title' => $this->t('Mobile detection'), + '#options' => [1 => $this->t('On'), 0 => $this->t('Off')], + '#default_value' => $config->get('advanced.mobile_detect'), + '#description' => $this->t('If on (default) Colorbox will not be active for devices with the max width set below.'), + ]; + $form['colorbox_advanced_settings']['colorbox_mobile_device_width'] = [ + '#type' => 'textfield', + '#title' => $this->t('Device width'), + '#default_value' => $config->get('advanced.mobile_device_width'), + '#size' => 30, + '#description' => $this->t('Set the mobile device max width. Default: 480px.'), + '#states' => [ + 'visible' => [ + ':input[name="colorbox_mobile_detect"]' => ['value' => '1'], + ], + ], + ]; + $form['colorbox_advanced_settings']['colorbox_caption_trim'] = [ + '#type' => 'radios', + '#title' => $this->t('Caption shortening'), + '#options' => [0 => $this->t('Default'), 1 => $this->t('Yes')], + '#default_value' => $config->get('advanced.caption_trim'), + '#description' => $this->t('If the caption should be made shorter in the Colorbox to avoid layout problems. The default is to shorten for the example styles, they need it, but not for other styles.'), + ]; + $form['colorbox_advanced_settings']['colorbox_caption_trim_length'] = [ + '#type' => 'select', + '#title' => $this->t('Caption max length'), + '#options' => $this->optionsRange(40, 120, 5), + '#default_value' => $config->get('advanced.caption_trim_length'), + '#states' => [ + 'visible' => [ + ':input[name="colorbox_caption_trim"]' => ['value' => '1'], + ], + ], + ]; + $form['colorbox_advanced_settings']['colorbox_compression_type'] = [ + '#type' => 'radios', + '#title' => $this->t('Choose Colorbox compression level'), + '#options' => [ + 'minified' => $this->t('Production (Minified)'), + 'source' => $this->t('Development (Uncompressed Code)'), + ], + '#default_value' => $config->get('advanced.compression_type'), + ]; + + if (!$this->moduleHandler->moduleExists('colorbox_load') || !$this->moduleHandler->moduleExists('colorbox_inline')) { + + $form['colorbox_extras'] = [ + '#type' => 'details', + '#title' => $this->t('Extras'), + ]; + + $form['colorbox_extras']['colorbox_additional_tips'] = [ + '#markup' => $this->t('You can find new features in the Colorbox Load and Colorbox Inline', [ + '@url_colorbox_load' => 'https://www.drupal.org/project/colorbox_load', + '@url_colorbox_inline' => 'https://www.drupal.org/project/colorbox_inline', + ]), + ]; + } + + return parent::buildForm($form, $form_state); + } + + /** + * {@inheritdoc} + */ + public function submitForm(array &$form, FormStateInterface $form_state) { + + $config = $this->configFactory->getEditable('colorbox.settings'); + + $config + ->set('custom.style', $form_state->getValue('colorbox_style')) + ->set('custom.activate', $form_state->getValue('colorbox_custom_settings_activate')) + ->set('custom.transition_type', $form_state->getValue('colorbox_transition_type')) + ->set('custom.transition_speed', $form_state->getValue('colorbox_transition_speed')) + ->set('custom.opacity', $form_state->getValue('colorbox_opacity')) + ->set('custom.text_current', $form_state->getValue('colorbox_text_current')) + ->set('custom.text_previous', $form_state->getValue('colorbox_text_previous')) + ->set('custom.text_next', $form_state->getValue('colorbox_text_next')) + ->set('custom.text_close', $form_state->getValue('colorbox_text_close')) + ->set('custom.overlayclose', $form_state->getValue('colorbox_overlayclose')) + ->set('custom.returnfocus', $form_state->getValue('colorbox_returnfocus')) + ->set('custom.maxwidth', $form_state->getValue('colorbox_maxwidth')) + ->set('custom.maxheight', $form_state->getValue('colorbox_maxheight')) + ->set('custom.initialwidth', $form_state->getValue('colorbox_initialwidth')) + ->set('custom.initialheight', $form_state->getValue('colorbox_initialheight')) + ->set('custom.fixed', $form_state->getValue('colorbox_fixed')) + ->set('custom.scrolling', $form_state->getValue('colorbox_scrolling')) + ->set('custom.slideshow.slideshow', $form_state->getValue('colorbox_slideshow')) + ->set('custom.slideshow.auto', $form_state->getValue('colorbox_slideshowauto')) + ->set('custom.slideshow.speed', $form_state->getValue('colorbox_slideshowspeed')) + ->set('custom.slideshow.text_start', $form_state->getValue('colorbox_text_start')) + ->set('custom.slideshow.text_stop', $form_state->getValue('colorbox_text_stop')) + ->set('advanced.unique_token', $form_state->getValue('colorbox_unique_token')) + ->set('advanced.mobile_detect', $form_state->getValue('colorbox_mobile_detect')) + ->set('advanced.mobile_device_width', $form_state->getValue('colorbox_mobile_device_width')) + ->set('advanced.caption_trim', $form_state->getValue('colorbox_caption_trim')) + ->set('advanced.caption_trim_length', $form_state->getValue('colorbox_caption_trim_length')) + ->set('advanced.compression_type', $form_state->getValue('colorbox_compression_type')); + + if ($form_state->getValue('colorbox_image_style')) { + $config->set('insert.image_style', $form_state->getValue('colorbox_image_style')); + } + + if ($form_state->getValue('colorbox_insert_gallery')) { + $config->set('insert.insert_gallery', $form_state->getValue('colorbox_insert_gallery')); + } + + $config->save(); + + parent::submitForm($form, $form_state); + } + + /** + * Get one of the pre-defined states used in this form. + * + * @param string $state + * The state to get that matches one of the state class constants. + * + * @return array + * A corresponding form API state. + */ + protected function getState($state) { + $states = [ + static::STATE_CUSTOM_SETTINGS => [ + 'visible' => [ + ':input[name="colorbox_custom_settings_activate"]' => ['value' => '1'], + ], + ], + static::STATE_SLIDESHOW_ENABLED => [ + 'visible' => [ + ':input[name="colorbox_slideshow"]' => ['value' => '1'], + ], + ], + ]; + return $states[$state]; + } + + /** + * Create a range for a series of options. + * + * @param int $start + * The start of the range. + * @param int $end + * The end of the range. + * @param int $step + * The interval between elements. + * + * @return array + * An options array for the given range. + */ + protected function optionsRange($start, $end, $step) { + $range = range($start, $end, $step); + return array_combine($range, $range); + } + +} diff --git a/web/modules/contrib/colorbox/src/GalleryIdHelper.php b/web/modules/contrib/colorbox/src/GalleryIdHelper.php new file mode 100644 index 00000000..df900e80 --- /dev/null +++ b/web/modules/contrib/colorbox/src/GalleryIdHelper.php @@ -0,0 +1,118 @@ +configFactory = $configFactory; + $this->token = $token; + } + + /** + * Generate ID. + * + * @param \Drupal\Core\Entity\ContentEntityInterface $entity + * The Entity. + * @param \Drupal\Core\Field\FieldItemInterface $item + * The Item. + * @param array $settings + * The Settings. + * + * @return string + * Return string. + */ + public function generateId(ContentEntityInterface $entity, FieldItemInterface $item, array $settings) { + $entity_bundle = $entity->bundle(); + $entity_type = $entity->getEntityTypeId(); + $config = $this->configFactory->get('colorbox.settings'); + + // Build the gallery id. + $id = $entity->id(); + $entity_id = !empty($id) ? $entity_bundle . '-' . $id : 'entity-id'; + $field_name = $item->getParent()->getName(); + + switch ($settings['colorbox_gallery']) { + case 'post': + $gallery_id = 'gallery-' . $entity_id; + break; + + case 'page': + $gallery_id = 'gallery-all'; + break; + + case 'field_post': + $gallery_id = 'gallery-' . $entity_id . '-' . $field_name; + break; + + case 'field_page': + $gallery_id = 'gallery-' . $field_name; + break; + + case 'custom': + $gallery_id = $this->token->replace( + $settings['colorbox_gallery_custom'], + [$entity_type => $entity, 'file' => $item], + ['clear' => TRUE] + ); + break; + + default: + $gallery_id = ''; + } + + // If gallery id is not empty add unique per-request token to avoid. + // images being added manually to galleries. + if (!empty($gallery_id) && $config->get('advanced.unique_token')) { + // Check if gallery token has already been set, we need to reuse. + // the token for the whole request. + if (is_null($this->galleryToken)) { + // We use a short token since randomness is not critical. + $this->galleryToken = Crypt::randomBytesBase64(8); + } + $gallery_id = $gallery_id . '-' . $this->galleryToken; + } + return $gallery_id; + } + +} diff --git a/web/modules/contrib/colorbox/src/Plugin/Field/FieldFormatter/ColorboxFormatter.php b/web/modules/contrib/colorbox/src/Plugin/Field/FieldFormatter/ColorboxFormatter.php new file mode 100644 index 00000000..6987973d --- /dev/null +++ b/web/modules/contrib/colorbox/src/Plugin/Field/FieldFormatter/ColorboxFormatter.php @@ -0,0 +1,463 @@ +currentUser = $current_user; + $this->imageStyleStorage = $image_style_storage; + $this->attachment = $attachment; + $this->moduleHandler = $moduleHandler; + } + + /** + * {@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('current_user'), + $container->get('entity_type.manager')->getStorage('image_style'), + $container->get('colorbox.attachment'), + $container->get('module_handler') + ); + } + + /** + * {@inheritdoc} + */ + public static function defaultSettings() { + return [ + 'colorbox_node_style' => '', + 'colorbox_node_style_first' => '', + 'colorbox_image_style' => '', + 'colorbox_gallery' => 'post', + 'colorbox_gallery_custom' => '', + 'colorbox_caption' => 'auto', + 'colorbox_caption_custom' => '', + ] + parent::defaultSettings(); + } + + /** + * {@inheritdoc} + */ + public function settingsForm(array $form, FormStateInterface $form_state) { + $image_styles = image_style_options(FALSE); + $image_styles_hide = $image_styles; + $image_styles_hide['hide'] = $this->t('Hide (do not display image)'); + $description_link = Link::fromTextAndUrl( + $this->t('Configure Image Styles'), + Url::fromRoute('entity.image_style.collection') + ); + + $element['colorbox_node_style'] = [ + '#title' => $this->t('Image style for content'), + '#type' => 'select', + '#default_value' => $this->getSetting('colorbox_node_style'), + '#empty_option' => $this->t('None (original image)'), + '#options' => $image_styles_hide, + '#description' => $description_link->toRenderable() + [ + '#access' => $this->currentUser->hasPermission('administer image styles'), + ], + ]; + $element['colorbox_node_style_first'] = [ + '#title' => $this->t('Image style for first image in content'), + '#type' => 'select', + '#default_value' => $this->getSetting('colorbox_node_style_first'), + '#empty_option' => $this->t('No special style.'), + '#options' => $image_styles, + '#description' => $description_link->toRenderable() + [ + '#access' => $this->currentUser->hasPermission('administer image styles'), + ], + ]; + $element['colorbox_image_style'] = [ + '#title' => $this->t('Image style for Colorbox'), + '#type' => 'select', + '#default_value' => $this->getSetting('colorbox_image_style'), + '#empty_option' => $this->t('None (original image)'), + '#options' => $image_styles, + '#description' => $description_link->toRenderable() + [ + '#access' => $this->currentUser->hasPermission('administer image styles'), + ], + ]; + + $gallery = [ + 'post' => $this->t('Per post gallery'), + 'page' => $this->t('Per page gallery'), + 'field_post' => $this->t('Per field in post gallery'), + 'field_page' => $this->t('Per field in page gallery'), + 'custom' => $this->t('Custom (with tokens)'), + 'none' => $this->t('No gallery'), + ]; + $element['colorbox_gallery'] = [ + '#title' => $this->t('Gallery (image grouping)'), + '#type' => 'select', + '#default_value' => $this->getSetting('colorbox_gallery'), + '#options' => $gallery, + '#description' => $this->t('How Colorbox should group the image galleries.'), + ]; + $element['colorbox_gallery_custom'] = [ + '#title' => $this->t('Custom gallery'), + '#type' => 'textfield', + '#default_value' => $this->getSetting('colorbox_gallery_custom'), + '#description' => $this->t('All images on a page with the same gallery value (rel attribute) will be grouped together. It must only contain lowercase letters, numbers, and underscores.'), + '#required' => FALSE, + '#states' => [ + 'visible' => [ + ':input[name$="[settings_edit_form][settings][colorbox_gallery]"]' => ['value' => 'custom'], + ], + ], + ]; + if ($this->moduleHandler->moduleExists('token')) { + + $entity_type = ''; + + if (isset($form['#entity_type']) && !empty($form['#entity_type'])) { + $entity_type = $form['#entity_type']; + } + + $element['colorbox_token_gallery'] = [ + '#type' => 'fieldset', + '#title' => $this->t('Replacement patterns'), + '#theme' => 'token_tree_link', + '#token_types' => [$entity_type, 'file'], + '#states' => [ + 'visible' => [ + ':input[name$="[settings_edit_form][settings][colorbox_gallery]"]' => ['value' => 'custom'], + ], + ], + ]; + } + else { + $element['colorbox_token_gallery'] = [ + '#type' => 'fieldset', + '#title' => $this->t('Replacement patterns'), + '#description' => '' . $this->t('For token support the token module must be installed.', ['@token_url' => 'http://drupal.org/project/token']) . '', + '#states' => [ + 'visible' => [ + ':input[name$="[settings_edit_form][settings][colorbox_gallery]"]' => ['value' => 'custom'], + ], + ], + ]; + } + + $caption = [ + 'auto' => $this->t('Automatic'), + 'title' => $this->t('Title text'), + 'alt' => $this->t('Alt text'), + 'entity_title' => $this->t('Content title'), + 'custom' => $this->t('Custom (with tokens)'), + 'none' => $this->t('None'), + ]; + $element['colorbox_caption'] = [ + '#title' => $this->t('Caption'), + '#type' => 'select', + '#default_value' => $this->getSetting('colorbox_caption'), + '#options' => $caption, + '#description' => $this->t('Automatic will use the first non-empty value out of the title, the alt text and the content title.'), + ]; + $element['colorbox_caption_custom'] = [ + '#title' => $this->t('Custom caption'), + '#type' => 'textfield', + '#default_value' => $this->getSetting('colorbox_caption_custom'), + '#states' => [ + 'visible' => [ + ':input[name$="[settings_edit_form][settings][colorbox_caption]"]' => ['value' => 'custom'], + ], + ], + ]; + if ($this->moduleHandler->moduleExists('token')) { + + $entity_type = ''; + + if (isset($form['#entity_type']) && !empty($form['#entity_type'])) { + $entity_type = $form['#entity_type']; + } + + $element['colorbox_token_caption'] = [ + '#type' => 'fieldset', + '#title' => $this->t('Replacement patterns'), + '#theme' => 'token_tree_link', + '#token_types' => [$entity_type, 'file'], + '#states' => [ + 'visible' => [ + ':input[name$="[settings_edit_form][settings][colorbox_caption]"]' => ['value' => 'custom'], + ], + ], + ]; + } + else { + $element['colorbox_token_caption'] = [ + '#type' => 'fieldset', + '#title' => $this->t('Replacement patterns'), + '#description' => '' . $this->t('For token support the token module must be installed.', ['@token_url' => 'http://drupal.org/project/token']) . '', + '#states' => [ + 'visible' => [ + ':input[name$="[settings_edit_form][settings][colorbox_caption]"]' => ['value' => 'custom'], + ], + ], + ]; + } + + return $element; + } + + /** + * {@inheritdoc} + */ + public function settingsSummary() { + $summary = []; + + $image_styles = image_style_options(FALSE); + // Unset possible 'No defined styles' option. + unset($image_styles['']); + // Styles could be lost because of enabled/disabled modules that defines + // their styles in code. + if (isset($image_styles[$this->getSetting('colorbox_node_style')])) { + $summary[] = $this->t('Content image style: @style', ['@style' => $image_styles[$this->getSetting('colorbox_node_style')]]); + } + elseif ($this->getSetting('colorbox_node_style') == 'hide') { + $summary[] = $this->t('Content image style: Hide'); + } + else { + $summary[] = $this->t('Content image style: Original image'); + } + + if (isset($image_styles[$this->getSetting('colorbox_node_style_first')])) { + $summary[] = $this->t('Content image style of first image: @style', ['@style' => $image_styles[$this->getSetting('colorbox_node_style_first')]]); + } + + if (isset($image_styles[$this->getSetting('colorbox_image_style')])) { + $summary[] = $this->t('Colorbox image style: @style', ['@style' => $image_styles[$this->getSetting('colorbox_image_style')]]); + } + else { + $summary[] = $this->t('Colorbox image style: Original image'); + } + + $gallery = [ + 'post' => $this->t('Per post gallery'), + 'page' => $this->t('Per page gallery'), + 'field_post' => $this->t('Per field in post gallery'), + 'field_page' => $this->t('Per field in page gallery'), + 'custom' => $this->t('Custom (with tokens)'), + 'none' => $this->t('No gallery'), + ]; + if ($this->getSetting('colorbox_gallery')) { + $summary[] = $this->t('Colorbox gallery type: @type', ['@type' => $gallery[$this->getSetting('colorbox_gallery')]]) . ($this->getSetting('colorbox_gallery') == 'custom' ? ' (' . $this->getSetting('colorbox_gallery_custom') . ')' : ''); + } + + $caption = [ + 'auto' => $this->t('Automatic'), + 'title' => $this->t('Title text'), + 'alt' => $this->t('Alt text'), + 'entity_title' => $this->t('Content title'), + 'custom' => $this->t('Custom (with tokens)'), + 'none' => $this->t('None'), + ]; + + if ($this->getSetting('colorbox_caption')) { + $summary[] = $this->t('Colorbox caption: @type', ['@type' => $caption[$this->getSetting('colorbox_caption')]]); + } + + return $summary; + } + + /** + * {@inheritdoc} + */ + public function viewElements(FieldItemListInterface $items, $langcode) { + $elements = []; + $settings = $this->getSettings(); + $files = $this->getEntitiesToView($items, $langcode); + + // Early opt-out if the field is empty. + if (empty($files)) { + return $elements; + } + + // Collect cache tags to be added for each item in the field. + $cache_tags = []; + if (!empty($settings['colorbox_node_style']) && $settings['colorbox_node_style'] != 'hide') { + $image_style = $this->imageStyleStorage->load($settings['colorbox_node_style']); + $cache_tags = $image_style->getCacheTags(); + } + $cache_tags_first = []; + if (!empty($settings['colorbox_node_style_first'])) { + $image_style_first = $this->imageStyleStorage->load($settings['colorbox_node_style_first']); + $cache_tags_first = $image_style_first->getCacheTags(); + } + + foreach ($files as $delta => $file) { + // Check if first image should have separate image style. + if ($delta == 0 && !empty($settings['colorbox_node_style_first'])) { + $settings['style_first'] = TRUE; + $settings['style_name'] = $settings['colorbox_node_style_first']; + $cache_tags = Cache::mergeTags($cache_tags_first, $file->getCacheTags()); + } + else { + $settings['style_first'] = FALSE; + $settings['style_name'] = $settings['colorbox_node_style']; + $cache_tags = Cache::mergeTags($cache_tags, $file->getCacheTags()); + } + + // Extract field item attributes for the theme function, and unset them + // from the $item so that the field template does not re-render them. + $item = $file->_referringItem; + $item_attributes = $item->_attributes; + unset($item->_attributes); + + $elements[$delta] = [ + '#theme' => 'colorbox_formatter', + '#item' => $item, + '#item_attributes' => $item_attributes, + '#entity' => $items->getEntity(), + '#settings' => $settings, + '#cache' => [ + 'tags' => $cache_tags, + ], + ]; + } + + // Attach the Colorbox JS and CSS. + if ($this->attachment->isApplicable()) { + $this->attachment->attach($elements); + } + + return $elements; + } + + /** + * {@inheritdoc} + */ + public function calculateDependencies() { + $dependencies = parent::calculateDependencies(); + $style_ids = []; + $style_ids[] = $this->getSetting('colorbox_node_style'); + if (!empty($this->getSetting('colorbox_node_style_first'))) { + $style_ids[] = $this->getSetting('colorbox_node_style_first'); + } + $style_ids[] = $this->getSetting('colorbox_image_style'); + /** @var \Drupal\image\ImageStyleInterface $style */ + foreach ($style_ids as $style_id) { + if ($style_id && $style = ImageStyle::load($style_id)) { + // If this formatter uses a valid image style to display the image, add + // the image style configuration entity as dependency of this formatter. + $dependencies[$style->getConfigDependencyKey()][] = $style->getConfigDependencyName(); + } + } + return $dependencies; + } + + /** + * {@inheritdoc} + */ + public function onDependencyRemoval(array $dependencies) { + $changed = parent::onDependencyRemoval($dependencies); + $style_ids = []; + $style_ids['colorbox_node_style'] = $this->getSetting('colorbox_node_style'); + if (!empty($this->getSetting('colorbox_node_style_first'))) { + $style_ids['colorbox_node_style_first'] = $this->getSetting('colorbox_node_style_first'); + } + $style_ids['colorbox_image_style'] = $this->getSetting('colorbox_image_style'); + /** @var \Drupal\image\ImageStyleInterface $style */ + foreach ($style_ids as $name => $style_id) { + if ($style_id && $style = ImageStyle::load($style_id)) { + if (!empty($dependencies[$style->getConfigDependencyKey()][$style->getConfigDependencyName()])) { + $replacement_id = $this->imageStyleStorage->getReplacementId($style_id); + // If a valid replacement has been provided in the storage, + // replace the image style with the replacement and signal + // that the formatter plugin. + // Settings were updated. + if ($replacement_id && ImageStyle::load($replacement_id)) { + $this->setSetting($name, $replacement_id); + $changed = TRUE; + } + } + } + } + return $changed; + } + +} diff --git a/web/modules/contrib/colorbox/styles/default/colorbox_style.css b/web/modules/contrib/colorbox/styles/default/colorbox_style.css new file mode 100644 index 00000000..c33b3796 --- /dev/null +++ b/web/modules/contrib/colorbox/styles/default/colorbox_style.css @@ -0,0 +1,228 @@ +/** + * Colorbox Core Style: + * The following CSS is consistent between example themes and should not be altered. + */ +#colorbox, +#cboxOverlay, +#cboxWrapper { + position: absolute; + top: 0; + left: 0; + z-index: 9999; + overflow: hidden; +} +#cboxOverlay { + position: fixed; + width: 100%; + height: 100%; +} +#cboxMiddleLeft, +#cboxBottomLeft { + clear: left; +} +#cboxContent { + position: relative; +} +#cboxLoadedContent { + overflow: auto; + -webkit-overflow-scrolling: touch; +} +#cboxTitle { + margin: 0; +} +#cboxLoadingOverlay, +#cboxLoadingGraphic { + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; +} +/** + * These elements are buttons, and may need to have additional + * styles reset to avoid unwanted base styles. + */ +#cboxPrevious, +#cboxNext, +#cboxClose, +#cboxSlideshow { + border: 0; + padding: 0; + margin: 0; + overflow: visible; + width: auto; + background: none; + cursor: pointer; +} +/** + * Avoid outlines on :active (mouseclick), + * but preserve outlines on :focus (tabbed navigating) + */ +#cboxPrevious:active, +#cboxNext:active, +#cboxClose:active, +#cboxSlideshow:active { + outline: 0; +} +.cboxPhoto { + float: left; + margin: auto; + border: 0; + display: block; + max-width: none; +} +.cboxIframe { + width: 100%; + height: 100%; + display: block; + border: 0; +} +/* Reset box sizing to content-box if theme is using border-box. */ +#colorbox, +#cboxContent, +#cboxLoadedContent { + -moz-box-sizing: content-box; + -webkit-box-sizing: content-box; + box-sizing: content-box; +} + +/** + * Colorbox module default style: + * The styles are ordered & tabbed in a way that represents + * the nesting of the generated HTML. + */ +#cboxOverlay { + background: #000; +} +#colorbox { + outline: 0; +} +#cboxWrapper { + background: #fff; + -moz-border-radius: 5px; + -webkit-border-radius: 5px; + border-radius: 5px; +} +#cboxTopLeft { + width: 15px; + height: 15px; +} +#cboxTopCenter { + height: 15px; +} +#cboxTopRight { + width: 15px; + height: 15px; +} +#cboxBottomLeft { + width: 15px; + height: 10px; +} +#cboxBottomCenter { + height: 10px; +} +#cboxBottomRight { + width: 15px; + height: 10px; +} +#cboxMiddleLeft { + width: 15px; +} +#cboxMiddleRight { + width: 15px; +} +#cboxContent { + background: #fff; + overflow: hidden; +} +#cboxError { + padding: 50px; + border: 1px solid #ccc; +} +#cboxLoadedContent { + margin-bottom: 28px; +} +#cboxTitle { + position: absolute; + background: rgba(255, 255, 255, 0.7); + bottom: 28px; + left: 0; + color: #535353; + width: 100%; + padding: 4px 6px; + -moz-box-sizing: border-box; + -webkit-box-sizing: border-box; + box-sizing: border-box; +} +#cboxCurrent { + position: absolute; + bottom: 4px; + left: 60px; + color: #949494; +} +.cboxSlideshow_on #cboxSlideshow { + position: absolute; + bottom: 0px; + right: 30px; + background: url(images/controls.png) no-repeat -75px -50px; + width: 25px; + height: 25px; + text-indent: -9999px; +} +.cboxSlideshow_on #cboxSlideshow:hover { + background-position: -101px -50px; +} +.cboxSlideshow_off #cboxSlideshow { + position: absolute; + bottom: 0px; + right: 30px; + background: url(images/controls.png) no-repeat -25px -50px; + width: 25px; + height: 25px; + text-indent: -9999px; +} +.cboxSlideshow_off #cboxSlideshow:hover { + background-position: -49px -50px; +} +#cboxPrevious { + position: absolute; + bottom: 0; + left: 0; + background: url(images/controls.png) no-repeat -75px 0px; + width: 25px; + height: 25px; + text-indent: -9999px; +} +#cboxPrevious:hover { + background-position: -75px -25px; +} +#cboxNext { + position: absolute; + bottom: 0; + left: 27px; + background: url(images/controls.png) no-repeat -50px 0px; + width: 25px; + height: 25px; + text-indent: -9999px; +} +#cboxNext:hover { + background-position: -50px -25px; +} +#cboxLoadingOverlay { + background: #fff; +} +#cboxLoadingGraphic { + background: url(images/loading_animation.gif) no-repeat center center; +} +#cboxClose { + position: absolute; + bottom: 0; + right: 0; + background: url(images/controls.png) no-repeat -25px 0px; + width: 25px; + height: 25px; + text-indent: -9999px; +} +#cboxClose:hover { + background-position: -25px -25px; +} diff --git a/web/modules/contrib/colorbox/styles/default/colorbox_style.js b/web/modules/contrib/colorbox/styles/default/colorbox_style.js new file mode 100644 index 00000000..d885be81 --- /dev/null +++ b/web/modules/contrib/colorbox/styles/default/colorbox_style.js @@ -0,0 +1,27 @@ +/** + * @file + * Colorbox Style JS. + */ + +(function ($) { + +Drupal.behaviors.initColorboxDefaultStyle = { + attach: function (context, settings) { + $(context).bind('cbox_complete', function () { + // Only run if there is a title. + if ($('#cboxTitle:empty', context).length == false) { + $('#cboxLoadedContent img', context).bind('mouseover', function () { + $('#cboxTitle', context).slideDown(); + }); + $('#cboxOverlay', context).bind('mouseover', function () { + $('#cboxTitle', context).slideUp(); + }); + } + else { + $('#cboxTitle', context).hide(); + } + }); + } +}; + +})(jQuery); diff --git a/web/modules/contrib/colorbox/styles/default/images/controls.png b/web/modules/contrib/colorbox/styles/default/images/controls.png new file mode 100644 index 00000000..22389727 Binary files /dev/null and b/web/modules/contrib/colorbox/styles/default/images/controls.png differ diff --git a/web/modules/contrib/colorbox/styles/default/images/loading_animation.gif b/web/modules/contrib/colorbox/styles/default/images/loading_animation.gif new file mode 100644 index 00000000..f864d5fd Binary files /dev/null and b/web/modules/contrib/colorbox/styles/default/images/loading_animation.gif differ diff --git a/web/modules/contrib/colorbox/styles/default/images/loading_background.png b/web/modules/contrib/colorbox/styles/default/images/loading_background.png new file mode 100644 index 00000000..9de11f46 Binary files /dev/null and b/web/modules/contrib/colorbox/styles/default/images/loading_background.png differ diff --git a/web/modules/contrib/colorbox/styles/plain/colorbox_style.css b/web/modules/contrib/colorbox/styles/plain/colorbox_style.css new file mode 100644 index 00000000..8500975b --- /dev/null +++ b/web/modules/contrib/colorbox/styles/plain/colorbox_style.css @@ -0,0 +1,159 @@ +/** + * Colorbox Core Style: + * The following CSS is consistent between example themes and should not be altered. + */ +#colorbox, +#cboxOverlay, +#cboxWrapper { + position: absolute; + top: 0; + left: 0; + z-index: 9999; + overflow: hidden; +} +#cboxOverlay { + position: fixed; + width: 100%; + height: 100%; +} +#cboxMiddleLeft, +#cboxBottomLeft { + clear: left; +} +#cboxContent { + position: relative; +} +#cboxLoadedContent { + overflow: auto; + -webkit-overflow-scrolling: touch; +} +#cboxTitle { + margin: 0; +} +#cboxLoadingOverlay, +#cboxLoadingGraphic { + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; +} +/** + * These elements are buttons, and may need to have additional + * styles reset to avoid unwanted base styles. + */ +#cboxPrevious, +#cboxNext, +#cboxClose, +#cboxSlideshow { + border: 0; + padding: 0; + margin: 0; + overflow: visible; + width: auto; + background: none; + cursor: pointer; +} +/** + * Avoid outlines on :active (mouseclick), + * but preserve outlines on :focus (tabbed navigating) + */ +#cboxPrevious:active, +#cboxNext:active, +#cboxClose:active, +#cboxSlideshow:active { + outline: 0; +} +.cboxPhoto { + float: left; + margin: auto; + border: 0; + display: block; + max-width: none; +} +.cboxIframe { + width: 100%; + height: 100%; + display: block; + border: 0; +} +/* Reset box sizing to content-box if theme is using border-box. */ +#colorbox, +#cboxContent, +#cboxLoadedContent { + -moz-box-sizing: content-box; + -webkit-box-sizing: content-box; + box-sizing: content-box; +} + +/** + * Colorbox module plain style: + * The styles are ordered & tabbed in a way that represents + * the nesting of the generated HTML. + */ +#cboxOverlay { + background: #000; +} +#colorbox { + outline: 0; +} +/* @codingStandardsIgnoreLine */ +#cboxWrapper { +} +#cboxContent { + overflow: hidden; +} +#cboxContent, +.cboxPhoto { + -webkit-border-radius: 5px; + -moz-border-radius: 5px; + border-radius: 5px; +} +#cboxError { + padding: 50px; + border: 1px solid #ccc; +} +#cboxTitle { + position: absolute; + background: rgba(255, 255, 255, 0.7); + bottom: 0; + left: 0; + color: #535353; + width: 100%; + padding: 4px 6px; + -moz-box-sizing: border-box; + -webkit-box-sizing: border-box; + box-sizing: border-box; + -webkit-border-bottom-right-radius: 5px; + -webkit-border-bottom-left-radius: 5px; + -moz-border-radius-bottomright: 5px; + -moz-border-radius-bottomleft: 5px; + border-bottom-right-radius: 5px; + border-bottom-left-radius: 5px; +} + +#cboxLoadingOverlay { + background: #fff; +} +#cboxLoadingGraphic { + background: url(images/loading_animation.gif) no-repeat center center; +} +#cboxClose.cbox-close-plain { + position: absolute; + font-size: 20px; + line-height: 18px; + text-align: center; + color: rgba(255, 255, 255, 0.7); + background: rgba(0, 0, 0, 0.5); + top: 4px; + right: 4px; + width: 20px; + height: 20px; + -webkit-border-radius: 10px; + -moz-border-radius: 10px; + border-radius: 10px; +} +.cbox-close-plain:hover { + color: rgba(255, 255, 255, 0.9); + background: rgba(0, 0, 0, 0.8); +} diff --git a/web/modules/contrib/colorbox/styles/plain/colorbox_style.js b/web/modules/contrib/colorbox/styles/plain/colorbox_style.js new file mode 100644 index 00000000..a53b7685 --- /dev/null +++ b/web/modules/contrib/colorbox/styles/plain/colorbox_style.js @@ -0,0 +1,39 @@ +/** + * @file + */ + +(function ($, Drupal) { + + "use strict"; + + Drupal.behaviors.initColorboxPlainStyle = { + attach: function (context, settings) { + $(context).bind('cbox_complete', function () { + // Make all the controls invisible. + $('#cboxCurrent, #cboxSlideshow, #cboxPrevious, #cboxNext', context).addClass('element-invisible'); + // Replace "Close" with "×" and show. + $('#cboxClose', context).html('\u00d7').addClass('cbox-close-plain'); + // Hide empty title. + if ($('#cboxTitle:empty', context).length == true) { + $('#cboxTitle', context).hide(); + } + $('#cboxLoadedContent', context).bind('mouseover', function () { + $('#cboxClose', context).animate({opacity: 1}, {queue: false, duration: "fast"}); + if ($('#cboxTitle:empty', context).length == false) { + $('#cboxTitle', context).slideDown(); + } + }); + $('#cboxOverlay', context).bind('mouseover', function () { + $('#cboxClose', context).animate({opacity: 0}, {queue: false, duration: "fast"}); + if ($('#cboxTitle:empty', context).length == false) { + $('#cboxTitle', context).slideUp(); + } + }); + }); + $(context).bind('cbox_closed', function () { + $('#cboxClose', context).removeClass('cbox-close-plain'); + }); + } + }; + +})(jQuery, Drupal); diff --git a/web/modules/contrib/colorbox/styles/plain/images/controls.png b/web/modules/contrib/colorbox/styles/plain/images/controls.png new file mode 100644 index 00000000..22389727 Binary files /dev/null and b/web/modules/contrib/colorbox/styles/plain/images/controls.png differ diff --git a/web/modules/contrib/colorbox/styles/plain/images/loading_animation.gif b/web/modules/contrib/colorbox/styles/plain/images/loading_animation.gif new file mode 100644 index 00000000..f864d5fd Binary files /dev/null and b/web/modules/contrib/colorbox/styles/plain/images/loading_animation.gif differ diff --git a/web/modules/contrib/colorbox/styles/plain/images/loading_background.png b/web/modules/contrib/colorbox/styles/plain/images/loading_background.png new file mode 100644 index 00000000..9de11f46 Binary files /dev/null and b/web/modules/contrib/colorbox/styles/plain/images/loading_background.png differ diff --git a/web/modules/contrib/colorbox/styles/stockholmsyndrome/colorbox_stockholmsyndrome_screen.png b/web/modules/contrib/colorbox/styles/stockholmsyndrome/colorbox_stockholmsyndrome_screen.png new file mode 100644 index 00000000..3ff1269b Binary files /dev/null and b/web/modules/contrib/colorbox/styles/stockholmsyndrome/colorbox_stockholmsyndrome_screen.png differ diff --git a/web/modules/contrib/colorbox/styles/stockholmsyndrome/colorbox_style.css b/web/modules/contrib/colorbox/styles/stockholmsyndrome/colorbox_style.css new file mode 100644 index 00000000..3ac08717 --- /dev/null +++ b/web/modules/contrib/colorbox/styles/stockholmsyndrome/colorbox_style.css @@ -0,0 +1,235 @@ +/** + * Colorbox Core Style: + * The following CSS is consistent between example themes and should not be altered. + */ +#colorbox, +#cboxOverlay, +#cboxWrapper { + position: absolute; + top: 0; + left: 0; + z-index: 9999; + overflow: hidden; +} +#cboxOverlay { + position: fixed; + width: 100%; + height: 100%; +} +#cboxMiddleLeft, +#cboxBottomLeft { + clear: left; +} +#cboxContent { + position: relative; +} +#cboxLoadedContent { + overflow: auto; + -webkit-overflow-scrolling: touch; +} +#cboxTitle { + margin: 0; +} +#cboxLoadingOverlay, +#cboxLoadingGraphic { + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; +} +/** + * These elements are buttons, and may need to have additional + * styles reset to avoid unwanted base styles. + */ +#cboxPrevious, +#cboxNext, +#cboxClose, +#cboxSlideshow { + border: 0; + padding: 0; + margin: 0; + overflow: visible; + width: auto; + background: none; + cursor: pointer; +} +/** + * Avoid outlines on :active (mouseclick), + * but preserve outlines on :focus (tabbed navigating) + */ +#cboxPrevious:active, +#cboxNext:active, +#cboxClose:active, +#cboxSlideshow:active { + outline: 0; +} +.cboxPhoto { + float: left; + margin: auto; + border: 0; + display: block; + max-width: none; +} +.cboxIframe { + width: 100%; + height: 100%; + display: block; + border: 0; +} +/* Reset box sizing to content-box if theme is using border-box. */ +#colorbox, +#cboxContent, +#cboxLoadedContent { + -moz-box-sizing: content-box; + -webkit-box-sizing: content-box; + box-sizing: content-box; +} + +/** + * Colorbox module Stockholm syndrome style: + * The styles are ordered & tabbed in a way that represents + * the nesting of the generated HTML. + */ +#cboxOverlay { + background: #000; +} + +#colorbox { + background: #fff url(images/bg_tab.png) center bottom repeat-x; + -moz-box-shadow: 3px 3px 16px #333; + -webkit-box-shadow: 3px 3px 16px #333; + box-shadow: 3px 3px 16px #333; + -moz-border-radius-bottomleft: 9px; + -moz-border-radius-bottomright: 9px; + -webkit-border-bottom-left-radius: 9px; + -webkit-border-bottom-right-radius: 9px; + border-bottom-left-radius: 9px; + border-bottom-right-radius: 9px; + outline: 0; +} +#colorbox, +#colorbox div { + overflow: visible; /* Required by the close button. */ +} +#cboxWrapper { + -moz-border-radius-bottomleft: 9px; + -moz-border-radius-bottomright: 9px; + -webkit-border-bottom-left-radius: 9px; + -webkit-border-bottom-right-radius: 9px; + border-bottom-left-radius: 9px; + border-bottom-right-radius: 9px; +} +#cboxTopLeft { + width: 0; + height: 0; +} +#cboxTopCenter { + height: 0; +} +#cboxTopRight { + width: 0; + height: 0; +} +#cboxBottomLeft { + width: 15px; + height: 10px; +} +#cboxBottomCenter { + height: 10px; +} +#cboxBottomRight { + width: 15px; + height: 10px; +} +#cboxMiddleLeft { + width: 0; +} +#cboxMiddleRight { + width: 0; +} +#cboxContent { + background: #fff; + overflow: hidden; + margin-bottom: 28px; +} +#cboxError { + padding: 50px; + border: 1px solid #ccc; +} +/* @codingStandardsIgnoreLine */ +#cboxLoadedContent { +} +#cboxTitle { + left: 0; + height: 38px; + color: #313131; + padding: 0 140px 0 15px; + display: table-cell !important; + vertical-align: middle; + float: none !important; +} +#cboxCurrent { + position: absolute; + bottom: -26px; + right: 80px; + color: #313131; + border-left: 1px solid #313131; + padding: 0 0 0 15px; +} +/* Slideshow not implemented. */ +.cboxSlideshow_on #cboxSlideshow { + display: none; +} +/* @codingStandardsIgnoreLine */ +.cboxSlideshow_on #cboxSlideshow:hover { +} +.cboxSlideshow_off #cboxSlideshow { + display: none; +} +/* @codingStandardsIgnoreLine */ +.cboxSlideshow_off #cboxSlideshow:hover { +} +#cboxPrevious { + position: absolute; + bottom: -26px; + right: 45px; + background: url(images/controls.png) no-repeat 0 -48px; + width: 21px; + height: 15px; + text-indent: -9999px; +} +#cboxPrevious:hover { + background-position: 0 -111px; +} +#cboxNext { + position: absolute; + bottom: -26px; + right: 15px; + background: url(images/controls.png) no-repeat 0 -29px; + width: 21px; + height: 15px; + text-indent: -9999px; +} +#cboxNext:hover { + background-position: 0 -92px; +} +#cboxLoadingOverlay { + background: #e6e6e6; +} +#cboxLoadingGraphic { + background: url(images/loading_animation.gif) no-repeat center center; +} +#cboxClose { + position: absolute; + top: -10px; + right: -10px; + background: url(images/controls.png) no-repeat 0px 0px; + width: 25px; + height: 25px; + text-indent: -9999px; + opacity: 0; +} +#cboxClose:hover { + background-position: 0 -63px; +} diff --git a/web/modules/contrib/colorbox/styles/stockholmsyndrome/colorbox_style.js b/web/modules/contrib/colorbox/styles/stockholmsyndrome/colorbox_style.js new file mode 100644 index 00000000..b8adb77f --- /dev/null +++ b/web/modules/contrib/colorbox/styles/stockholmsyndrome/colorbox_style.js @@ -0,0 +1,25 @@ +/** + * @file + * Colorbox Style JS. + */ + +(function ($) { + +Drupal.behaviors.initColorboxStockholmsyndromeStyle = { + attach: function (context, settings) { + $(context).bind('cbox_open', function () { + // Hide close button initially. + $('#cboxClose', context).css('opacity', 0); + }); + $(context).bind('cbox_load', function () { + // Hide close button. (It doesn't handle the load animation well.) + $('#cboxClose', context).css('opacity', 0); + }); + $(context).bind('cbox_complete', function () { + // Show close button with a delay. + $('#cboxClose', context).fadeTo('fast', 0, function () {$(this).css('opacity', 1)}); + }); + } +}; + +})(jQuery); diff --git a/web/modules/contrib/colorbox/styles/stockholmsyndrome/images/bg_tab.png b/web/modules/contrib/colorbox/styles/stockholmsyndrome/images/bg_tab.png new file mode 100644 index 00000000..03064d92 Binary files /dev/null and b/web/modules/contrib/colorbox/styles/stockholmsyndrome/images/bg_tab.png differ diff --git a/web/modules/contrib/colorbox/styles/stockholmsyndrome/images/controls.png b/web/modules/contrib/colorbox/styles/stockholmsyndrome/images/controls.png new file mode 100644 index 00000000..6745faa2 Binary files /dev/null and b/web/modules/contrib/colorbox/styles/stockholmsyndrome/images/controls.png differ diff --git a/web/modules/contrib/colorbox/styles/stockholmsyndrome/images/loading_animation.gif b/web/modules/contrib/colorbox/styles/stockholmsyndrome/images/loading_animation.gif new file mode 100644 index 00000000..f864d5fd Binary files /dev/null and b/web/modules/contrib/colorbox/styles/stockholmsyndrome/images/loading_animation.gif differ diff --git a/web/modules/contrib/colorbox/templates/colorbox-formatter.html.twig b/web/modules/contrib/colorbox/templates/colorbox-formatter.html.twig new file mode 100644 index 00000000..a5c86188 --- /dev/null +++ b/web/modules/contrib/colorbox/templates/colorbox-formatter.html.twig @@ -0,0 +1,17 @@ +{# +/** + * @file + * Default theme implementation to display a formatted colorbox image field. + * + * Available variables: + * - image: A collection of image data. + * - url: An URL the image can be linked to. + * - attributes: Link attributes. + * + * @see template_preprocess_colorbox_formatter() + * + * @ingroup themeable + */ +#} + +{{ image }} diff --git a/web/modules/contrib/colorbox/tests/modules/colorbox_library_test/colorbox_library_test.info.yml b/web/modules/contrib/colorbox/tests/modules/colorbox_library_test/colorbox_library_test.info.yml new file mode 100644 index 00000000..4cae3dd7 --- /dev/null +++ b/web/modules/contrib/colorbox/tests/modules/colorbox_library_test/colorbox_library_test.info.yml @@ -0,0 +1,11 @@ +name: 'Colorbox Library Test' +description: 'Ensure colorbox can be tested properly with the downloaded library.' +type: module +hidden: true +package: Testing +core_version_requirement: ^8.8 || ^9 + +# Information added by Drupal.org packaging script on 2021-03-05 +version: '8.x-1.7' +project: 'colorbox' +datestamp: 1614960643 diff --git a/web/modules/contrib/colorbox/tests/modules/colorbox_library_test/colorbox_library_test.install b/web/modules/contrib/colorbox/tests/modules/colorbox_library_test/colorbox_library_test.install new file mode 100644 index 00000000..d4dd0d1d --- /dev/null +++ b/web/modules/contrib/colorbox/tests/modules/colorbox_library_test/colorbox_library_test.install @@ -0,0 +1,27 @@ +prepareDirectory($library_folder, FileSystemInterface::MODIFY_PERMISSIONS | FileSystemInterface::CREATE_DIRECTORY); + copy('https://github.com/jackmoore/colorbox/archive/master.zip', $zip_file); + $zip = new \ZipArchive(); + $zip->open($zip_file); + $zip->extractTo($library_folder); + rename($library_folder . '/colorbox-master', $colorbox_folder); +} diff --git a/web/modules/contrib/colorbox/tests/modules/colorbox_library_test/colorbox_library_test.module b/web/modules/contrib/colorbox/tests/modules/colorbox_library_test/colorbox_library_test.module new file mode 100644 index 00000000..f62de99d --- /dev/null +++ b/web/modules/contrib/colorbox/tests/modules/colorbox_library_test/colorbox_library_test.module @@ -0,0 +1,21 @@ + $library) { + $libraries['colorbox']['js']['/' . Settings::get('file_public_path') . $key] = $library; + unset($libraries['colorbox']['js'][$key]); + } +} diff --git a/web/modules/contrib/colorbox/tests/src/FunctionalJavascript/ColorboxJavascriptTest.php b/web/modules/contrib/colorbox/tests/src/FunctionalJavascript/ColorboxJavascriptTest.php new file mode 100644 index 00000000..fcb09ab9 --- /dev/null +++ b/web/modules/contrib/colorbox/tests/src/FunctionalJavascript/ColorboxJavascriptTest.php @@ -0,0 +1,196 @@ +drupalGet('node/' . $this->node->id()); + $this->getSession()->getPage()->find('css', 'img')->click(); + $this->getSession()->wait(static::COLORBOX_WAIT_TIMEOUT); + $this->assertSession()->elementContains('css', '#colorbox', 'test.png'); + } + + /** + * Test the gallery works. + */ + public function testColorboxGallery() { + $this->drupalGet('node/' . $this->node->id()); + + // Click and launch the gallery. + $this->getSession()->getPage()->find('css', 'img')->click(); + $this->getSession()->wait(static::COLORBOX_WAIT_TIMEOUT); + $this->assertSession()->elementContains('css', '#cboxTitle', 'Image title 1'); + $this->assertSession()->elementContains('css', '#colorbox', 'test.png'); + + // Click on the next image and assert the second image is visible. + $this->assertSession()->elementExists('css', '#cboxNext')->click(); + $this->getSession()->wait(static::COLORBOX_WAIT_TIMEOUT); + $this->assertSession()->elementContains('css', '#cboxTitle', 'Image title 2'); + $this->assertSession()->elementContains('css', '#colorbox', 'test.png'); + + // Use alt captions. + \Drupal::entityTypeManager() + ->getStorage('entity_view_display') + ->load('node.page.default') + ->setComponent('field_test_image', [ + 'type' => 'colorbox', + 'settings' => ['colorbox_caption' => 'alt'], + ]) + ->save(); + drupal_flush_all_caches(); + + // Ensure the caption being used is the alt text. + $this->drupalGet('node/' . $this->node->id()); + $this->getSession()->getPage()->find('css', 'img')->click(); + $this->getSession()->wait(static::COLORBOX_WAIT_TIMEOUT); + $this->assertSession()->elementContains('css', '#cboxTitle', 'Image alt 1'); + } + + /** + * Test the mobile detection. + */ + public function testMobileDetection() { + $this->changeSetting('advanced.mobile_detect', TRUE); + $this->changeSetting('advanced.mobile_device_width', '1200px'); + $this->getSession()->resizeWindow(200, 200); + $this->drupalGet('node/' . $this->node->id()); + $this->assertSession()->elementAttributeContains('css', '#colorbox', 'style', 'display: none;'); + } + + /** + * Test the admin form. + */ + public function testAdminForm() { + $this->drupalLogin($this->drupalCreateUser([ + 'administer site configuration', + ])); + $this->drupalGet('admin/config/media/colorbox'); + $this->assertFalse($this->getSession()->getPage()->find('css', '.form-item-colorbox-transition-speed')->isVisible()); + $this->assertSession()->fieldExists('colorbox_custom_settings_activate')->setValue(TRUE); + $this->assertTrue($this->getSession()->getPage()->find('css', '.form-item-colorbox-transition-speed')->isVisible()); + $this->assertSession()->fieldExists('colorbox_overlayclose')->setValue(FALSE); + $this->getSession()->getPage()->find('css', '.form-submit')->click(); + $this->assertSession()->pageTextContains('The configuration options have been saved.'); + } + + /** + * Change a colorbox setting. + * + * @param string $setting + * The name of the setting. + * @param string $value + * The value. + */ + protected function changeSetting($setting, $value) { + \Drupal::configFactory() + ->getEditable('colorbox.settings') + ->set($setting, $value) + ->save(); + } + + /** + * {@inheritdoc} + */ + protected function setUp() { + parent::setUp(); + $this->createContentType(['type' => 'page']); + FieldStorageConfig::create([ + 'field_name' => 'field_test_image', + 'entity_type' => 'node', + 'type' => 'image', + 'settings' => [], + 'cardinality' => 3, + ])->save(); + $field_config = FieldConfig::create([ + 'field_name' => 'field_test_image', + 'label' => 'Colorbox Field', + 'entity_type' => 'node', + 'bundle' => 'page', + 'required' => TRUE, + 'settings' => [], + ]); + $field_config->save(); + \Drupal::entityTypeManager() + ->getStorage('entity_view_display') + ->load('node.page.default') + ->setComponent('field_test_image', [ + 'type' => 'colorbox', + 'settings' => [], + ]) + ->save(); + \Drupal::service('file_system')->copy(__DIR__ . '/../../../images/admin/colorbox_example_1.png', 'public://test.png'); + $file_a = File::create([ + 'uri' => 'public://test.png', + 'filename' => 'test.png', + ]); + $file_a->save(); + $file_b = File::create([ + 'uri' => 'public://test.png', + 'filename' => 'test.png', + ]); + $file_b->save(); + $this->node = $this->createNode([ + 'type' => 'page', + 'field_test_image' => [ + [ + 'target_id' => $file_a->id(), + 'alt' => 'Image alt 1', + 'title' => 'Image title 1', + ], + [ + 'target_id' => $file_b->id(), + 'alt' => 'Image alt 2', + 'title' => 'Image title 2', + ], + ], + ]); + } + +} diff --git a/web/modules/contrib/devel/.docker/zz-php.ini b/web/modules/contrib/devel/.docker/zz-php.ini new file mode 100644 index 00000000..582337f2 --- /dev/null +++ b/web/modules/contrib/devel/.docker/zz-php.ini @@ -0,0 +1,5 @@ +[PHP] +variables_order = GPCS +error_reporting = E_ALL +date.timezone = "UTC" +sendmail_path = "true" diff --git a/web/modules/contrib/devel/.gitignore b/web/modules/contrib/devel/.gitignore new file mode 100644 index 00000000..4a5c9bed --- /dev/null +++ b/web/modules/contrib/devel/.gitignore @@ -0,0 +1,33 @@ +/vendor/ +vendor +/web/ +web +/node_modules/ +.env +composer.lock +yarn.lock +/.editorconfig +/.gitattributes + +#PHPUnit output +junit.xml +.phpunit.result.cache + +# Ignore local overrides. +docker-compose.override.yml +/.csslintrc +/.eslintignore +/.eslintrc.json +/.ht.router.php +/.htaccess +/INSTALL.txt +/README.txt +/autoload.php +/example.gitignore +/index.php +/robots.txt +/update.php +/web.config +/composer.spoons.json +/composer.spoons.lock +/.env diff --git a/web/modules/contrib/devel/.gitlab-ci.yml b/web/modules/contrib/devel/.gitlab-ci.yml new file mode 100644 index 00000000..ea269d55 --- /dev/null +++ b/web/modules/contrib/devel/.gitlab-ci.yml @@ -0,0 +1,29 @@ +include: + - project: 'drupalspoons/composer-plugin' + # Best practice is to pin to a tag or a SHA1. https://docs.gitlab.com/ee/ci/yaml/#includefile + ref: "2.1.0" + # The template below may be inspected at https://gitlab.com/drupalspoons/composer-plugin/-/blob/master/templates/.gitlab-ci.yml + file: 'templates/.gitlab-ci.yml' + +# +# Projects may override anything in the template above. +# The code below is specific to devel project. Comment it out or delete it when +# copying this file to your new project. +# + +# Run tests on Drupal 9.1 by default, including a phpspec/prophecy-phpunit requirement. +composer_node: + variables: + # https://getcomposer.org/doc/articles/versions.md#next-significant-release-operators + DRUPAL_CORE_CONSTRAINT: ~9.1.0 + after_script: + # See https://www.drupal.org/project/drupal/issues/3182653 + # This will fail on PHPUnit 8-, that is OK as its not needed there. + - vendor/bin/spoon require --no-progress phpspec/prophecy-phpunit:^2 || true + + +# Add /webprofiler to ignored paths. +phpcs: + script: + - PWD=$(pwd) && vendor/bin/phpcs --runtime-set ignore_warnings_on_exit 1 --runtime-set ignore_errors_on_exit 1 --ignore=$PWD/web/,$PWD/vendor/,$PWD/webprofiler/ --report-junit=junit.xml --report-full --report-summary + diff --git a/web/modules/contrib/devel/.travis.yml b/web/modules/contrib/devel/.travis.yml new file mode 100644 index 00000000..b1d1ab88 --- /dev/null +++ b/web/modules/contrib/devel/.travis.yml @@ -0,0 +1,109 @@ +language: php + +# The Travis CI container mode has random functional test fails, so we must use +# sudo here. +sudo: true + +php: + - 7.1 + - 7.3 + +services: + - mysql + +env: + global: + - MODULE=devel + matrix: + - DRUPAL_CORE=8.8.x + - DRUPAL_CORE=8.9.x + - DRUPAL_CORE=9.0.x + +matrix: + fast_finish: true + # PHP7.1 is not supported from Core 9.0 onwards. + exclude: + - php: 7.1 + env: DRUPAL_CORE=9.0.x + +# Be sure to cache composer downloads. +cache: + directories: + - $HOME/.composer + +before_script: + - echo $MODULE + + # Remove Xdebug as we don't need it and it causes + # PHP Fatal error: Maximum function nesting level of '256' reached. + # We also don't care if that file exists or not on PHP 7. + - phpenv config-rm xdebug.ini || true + + # Navigate out of module directory to prevent blown stack by recursive module + # lookup. + - cd .. + + # Create database. + - mysql -e "create database $MODULE" + # Export database variable for kernel tests. + - export SIMPLETEST_DB=mysql://root:@127.0.0.1/$MODULE + + # Download Drupal core from the Github mirror because it is faster. + - travis_retry git clone --branch $DRUPAL_CORE --depth 1 https://github.com/drupal/drupal.git + - cd drupal + # Store the path to Drupal root. + - DRUPAL_ROOT=$(pwd) + - echo $DRUPAL_ROOT + + # Make a directory for our module and copy the built source into it. + - mkdir $DRUPAL_ROOT/modules/$MODULE + - cp -R $TRAVIS_BUILD_DIR/* $DRUPAL_ROOT/modules/$MODULE/ + + # Apply patch to reverse the addition of doctrine/debug in composer.json so that tests can run again. + - cd $DRUPAL_ROOT/modules/$MODULE; + - wget -q -O - https://www.drupal.org/files/issues/2020-04-17/3125678-9.remove-doctrine-common.patch | patch -p1 --verbose; + - cd $DRUPAL_ROOT; + + # Run composer self-update and install. + - travis_retry composer self-update && travis_retry composer install + + # Run composer update in the module directory in order to fetch dependencies. + - travis_retry composer update -d $DRUPAL_ROOT/modules/$MODULE + + # Install drush + - travis_retry composer require drush/drush:"^9.0 || ^10.0" + + # Coder is already installed as part of composer install. We just need to set + # the installed_paths to pick up the Drupal standards. + - $DRUPAL_ROOT/vendor/bin/phpcs --config-set installed_paths $DRUPAL_ROOT/vendor/drupal/coder/coder_sniffer + + # Start a web server on port 8888, run in the background. + - php -S localhost:8888 & + + # Export web server URL for browser tests. + - export SIMPLETEST_BASE_URL=http://localhost:8888 + + # Interim patch for 9.0 only to avoid the Webprofiler toolbar halting the test run with 'class not found'. + - if [ $DRUPAL_CORE == "9.0.x" ]; then + cd $DRUPAL_ROOT/modules/$MODULE; + wget -q -O - https://www.drupal.org/files/issues/2020-04-07/3097125-33.replace-JavascriptTestBase.patch | patch -p1 --verbose; + fi + +script: + # Run the PHPUnit tests. + - cd $DRUPAL_ROOT + - ./vendor/bin/phpunit -c ./core/phpunit.xml.dist --verbose --group=devel,devel_generate,webprofiler ./modules/$MODULE + + # Check for coding standards. First change directory to our module. + - cd $DRUPAL_ROOT/modules/$MODULE + + # List all the sniffs that were used. + - $DRUPAL_ROOT/vendor/bin/phpcs --version + - $DRUPAL_ROOT/vendor/bin/phpcs -i + - $DRUPAL_ROOT/vendor/bin/phpcs -e + + # Show the violations in detail and do not fail for any errors or warnings. + - $DRUPAL_ROOT/vendor/bin/phpcs -s --report-width=130 --colors --runtime-set ignore_warnings_on_exit 1 --runtime-set ignore_errors_on_exit 1 . + + # Run again to give a summary and total count. + - $DRUPAL_ROOT/vendor/bin/phpcs --report-width=130 --colors --runtime-set ignore_warnings_on_exit 1 --runtime-set ignore_errors_on_exit 1 --report=summary . diff --git a/web/modules/contrib/devel/CODEOWNERS b/web/modules/contrib/devel/CODEOWNERS new file mode 100644 index 00000000..00636043 --- /dev/null +++ b/web/modules/contrib/devel/CODEOWNERS @@ -0,0 +1,3 @@ +/webprofiler/ @lussoluca +/src/Commands/ @weitzman + diff --git a/web/modules/contrib/devel/LICENSE.txt b/web/modules/contrib/devel/LICENSE.txt new file mode 100644 index 00000000..d159169d --- /dev/null +++ b/web/modules/contrib/devel/LICENSE.txt @@ -0,0 +1,339 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Lesser General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. diff --git a/web/modules/contrib/devel/README.md b/web/modules/contrib/devel/README.md new file mode 100644 index 00000000..47ab28cf --- /dev/null +++ b/web/modules/contrib/devel/README.md @@ -0,0 +1,55 @@ +[[_TOC_]] + +#### Introduction + +Devel module contains helper functions and pages for Drupal developers and +inquisitive admins: + + - A block and toolbar for quickly accessing devel pages + - Debug functions for inspecting a variable such as `dpm($variable)` + - Debug a SQL query `dpq($query` or print a backtrace `ddebug_backtrace()` + - A block for masquerading as other users (useful for testing) + - A mail-system class which redirects outbound email to files + - Drush commands such as `fn-hook`, `fn-event`, `token`, `uuid`, and `devel-services` + - *Webprofiler*. Adds a debug bar at bottom of all pages with tons of useful + information like a query list, cache hit/miss data, memory profiling, page + speed, php info, session info, etc. + - *Devel Generate*. Bulk creates nodes, users, comment, taxonomy, media, menus for development. Has + Drush integration. + +This module is safe to use on a production site. Just be sure to only grant +_access development information_ permission to developers. + +#### Collaboration +- https://gitlab.com/drupalspoons/devel is our workplace for code, MRs, and CI. See +[DrupalSpoons](https://gitlab.com/drupalcontrib/webmasters/-/blob/master/README.md) +for more info. +- We push back to git.drupalcode.org in order to keep +[Security Team](https://www.drupal.org/security) coverage and packages.drupal.org integration. +- Chat with us at [#devel](https://drupal.slack.com/archives/C012WAW1MH6) on Drupal Slack. + +#### Local Development +1. Clone devel `git clone https://gitlab.com/drupalforks/devel.git` +1. `cd devel` +1. Install the composer plugin from https://gitlab.com/drupalspoons/composer-plugin. Your source tree now looks like: +![Folder tree](/icons/folder.png) +1. Configure a web server to serve devel's `/web` directory as docroot. __Either__ of these works fine: + 1. `vendor/bin/spoon runserver` + 1. Setup Apache/Nginx/Other. A virtual host will work fine. Any domain name works. +1. Configure a database server and a database. +1. Install a testing site `vendor/bin/spoon si -- --db-url=mysql://user:pass@localhost/db`. Adjust as needed. + +#### Testing +- [CI docs](https://gitlab.com/drupalspoons/webmasters/-/blob/master/docs/ci.md) gives info on running tests. +- See [develCommandsTest.php](tests/src/Functional/DevelCommandsTest.php) for an example of Drush command testing. This uses [Drush Test Traits](https://www.drush.org/contribute/#drush-test-traits). + +#### Version Compatibility +| Devel version | Drupal core | PHP | Drush | +| ------ | ------ | ----- | ----- | +| 4.x |8.8+ | 7.2+ | 9+ +| 8.x-2.x | 8.x |7.0+ | 8+ + + +#### Maintainers + +See https://gitlab.com/groups/drupaladmins/devel/-/group_members. diff --git a/web/modules/contrib/devel/composer.json b/web/modules/contrib/devel/composer.json new file mode 100644 index 00000000..3b60a26d --- /dev/null +++ b/web/modules/contrib/devel/composer.json @@ -0,0 +1,33 @@ +{ + "name": "drupal/devel", + "description": "Various blocks, pages, and functions for developers.", + "type": "drupal-module", + "support": { + "issues": "https://gitlab.com/drupalspoons/devel/-/issues", + "slack": "https://drupal.slack.com/archives/C012WAW1MH6", + "source": "https://gitlab.com/drupalspoons/devel" + }, + "license": "GPL-2.0-or-later", + "minimum-stability": "dev", + "prefer-stable": true, + "require": { + "symfony/var-dumper": "^4 || ^5", + "doctrine/common": "^2.7" + }, + "require-dev": { + "drush/drush": "^10" + }, + "suggest": { + "kint-php/kint": "Kint provides an informative display of arrays/objects. Useful for debugging and developing." + }, + "conflict": { + "kint-php/kint": "<3" + }, + "extra": { + "drush": { + "services": { + "drush.services.yml": "^9 || ^10" + } + } + } +} diff --git a/web/modules/contrib/devel/config/install/devel.settings.yml b/web/modules/contrib/devel/config/install/devel.settings.yml new file mode 100644 index 00000000..bd0c269c --- /dev/null +++ b/web/modules/contrib/devel/config/install/devel.settings.yml @@ -0,0 +1,10 @@ +page_alter: FALSE +raw_names: FALSE +error_handlers: + 1: 1 +rebuild_theme: FALSE +debug_mail_file_format: '%to-%subject-%datetime.mail.txt' +debug_mail_directory: 'temporary://devel-mails' +devel_dumper: 'default' +debug_logfile: 'temporary://drupal_debug.txt' +debug_pre: TRUE diff --git a/web/modules/contrib/devel/config/install/devel.toolbar.settings.yml b/web/modules/contrib/devel/config/install/devel.toolbar.settings.yml new file mode 100644 index 00000000..b12c5bdc --- /dev/null +++ b/web/modules/contrib/devel/config/install/devel.toolbar.settings.yml @@ -0,0 +1,8 @@ +toolbar_items: + - 'devel.admin_settings_link' + - 'devel.cache_clear' + - 'devel.container_info.service' + - 'devel.menu_rebuild' + - 'devel.reinstall' + - 'devel.route_info' + - 'devel.run_cron' diff --git a/web/modules/contrib/devel/config/install/system.menu.devel.yml b/web/modules/contrib/devel/config/install/system.menu.devel.yml new file mode 100644 index 00000000..36de4c40 --- /dev/null +++ b/web/modules/contrib/devel/config/install/system.menu.devel.yml @@ -0,0 +1,10 @@ +langcode: en +status: true +dependencies: + enforced: + module: + - devel +id: devel +label: Development +description: 'Links related to Devel module.' +locked: true diff --git a/web/modules/contrib/devel/config/schema/devel.schema.yml b/web/modules/contrib/devel/config/schema/devel.schema.yml new file mode 100644 index 00000000..dd6ae1cb --- /dev/null +++ b/web/modules/contrib/devel/config/schema/devel.schema.yml @@ -0,0 +1,59 @@ +# Schema for the configuration files of the Devel module. + +devel.settings: + type: config_object + label: 'Devel settings' + mapping: + page_alter: + type: boolean + label: 'Page alter' + raw_names: + type: boolean + label: 'Raw names' + error_handlers: + label: 'Error handlers' + type: sequence + sequence: + type: integer + rebuild_theme: + type: boolean + label: 'Rebuild theme information' + debug_mail_file_format: + type: string + label: 'Mail debug file format' + debug_mail_directory: + type: string + label: 'Mail debug directory' + devel_dumper: + type: string + label: 'Devel variable dumper' + debug_logfile: + type: string + label: 'Devel debug log file' + debug_pre: + type: boolean + label: 'Wrap debug output in pre tags' + +devel.toolbar.settings: + type: config_object + label: 'Devel Toolbar settings' + mapping: + toolbar_items: + type: sequence + label: 'Toolbar items' + sequence: + type: string + +block.settings.devel_switch_user: + type: block_settings + label: 'Switch user block' + mapping: + list_size: + type: integer + label: 'List size' + include_anon: + type: boolean + label: 'Include Anonymous user' + show_form: + type: boolean + label: 'Show search form' diff --git a/web/modules/contrib/devel/css/devel.css b/web/modules/contrib/devel/css/devel.css new file mode 100644 index 00000000..f50eb15b --- /dev/null +++ b/web/modules/contrib/devel/css/devel.css @@ -0,0 +1,28 @@ +/** + * Dumpers + */ +.devel-dumper .details-wrapper { + max-height: 450px; + margin-right: 3px; + overflow: auto; +} + +/** + * Switch User block + */ +.region-content .block-devel-switch-user ul, +.site-footer .block-devel-switch-user ul { + display: flex; + flex-flow: row wrap; + padding: 0; +} + +.region-content .block-devel-switch-user ul li, +.site-footer .block-devel-switch-user ul li { + display: block; + padding-right: 2em; +} + +.devel-switchuser-form { + margin-top: 0.5em; +} diff --git a/web/modules/contrib/devel/css/devel.toolbar.css b/web/modules/contrib/devel/css/devel.toolbar.css new file mode 100644 index 00000000..8a8b791b --- /dev/null +++ b/web/modules/contrib/devel/css/devel.toolbar.css @@ -0,0 +1,42 @@ +/** + * @file + * Styling for devel toolbar module. + */ + +.toolbar .toolbar-tray-vertical .edit-devel-toolbar { + text-align: right; /* LTR */ + padding: 1em; +} + +[dir="rtl"] .toolbar .toolbar-tray-vertical .edit-devel-toolbar { + text-align: left; +} + +.toolbar .toolbar-tray-horizontal .edit-devel-toolbar { + float: right; /* LTR */ +} + +[dir="rtl"] .toolbar .toolbar-tray-horizontal .edit-devel-toolbar { + float: left; +} + +.toolbar .toolbar-tray-horizontal .toolbar-menu { + float: left; /* LTR */ +} + +[dir="rtl"] .toolbar .toolbar-tray-horizontal .toolbar-menu { + float: right; +} + +.toolbar .toolbar-bar .toolbar-icon-devel:before { + background-image: url(../icons/bebebe/cog.svg); +} + +.toolbar-bar .toolbar-icon-devel:active:before, +.toolbar-bar .toolbar-icon-devel.is-active:before { + background-image: url(../icons/ffffff/cog.svg); +} + +.toolbar-horizontal .toolbar-horizontal-item-hidden { + display: none; +} diff --git a/web/modules/contrib/devel/devel.api.php b/web/modules/contrib/devel/devel.api.php new file mode 100644 index 00000000..e8c4b49b --- /dev/null +++ b/web/modules/contrib/devel/devel.api.php @@ -0,0 +1,25 @@ + t('Devel module enabled'), + 'description' => t("The Devel module provides access to internal debugging information; therefore it's recommended to disable this module on sites in production."), + 'severity' => REQUIREMENT_INFO, + ]; + } + + return $requirements; +} + +/** + * Set the default devel dumper plugin. + */ +function devel_update_8001() { + $kint_enabled = \Drupal::moduleHandler()->moduleExists('kint'); + + $default_dumper = $kint_enabled ? 'kint' : 'default'; + + // Set the default dumper plugin to kint if kint module is available. + \Drupal::configFactory()->getEditable('devel.settings') + ->set('devel_dumper', $default_dumper) + ->save(TRUE); +} + +/** + * Add enforced dependencies to system.menu.devel. + */ +function devel_update_8002() { + $config = \Drupal::configFactory()->getEditable('system.menu.devel'); + $dependencies = $config->get('dependencies'); + $dependencies['enforced']['module'][] = 'devel'; + $config->set('dependencies', $dependencies)->save(TRUE); +} diff --git a/web/modules/contrib/devel/devel.libraries.yml b/web/modules/contrib/devel/devel.libraries.yml new file mode 100644 index 00000000..ee32ae99 --- /dev/null +++ b/web/modules/contrib/devel/devel.libraries.yml @@ -0,0 +1,17 @@ +devel: + version: 0 + css: + theme: + css/devel.css: {} + +devel-toolbar: + version: VERSION + css: + component: + css/devel.toolbar.css: {} + +devel-table-filter: + version: VERSION + js: {} + dependencies: + - system/drupal.system.modules diff --git a/web/modules/contrib/devel/devel.links.menu.yml b/web/modules/contrib/devel/devel.links.menu.yml new file mode 100644 index 00000000..4becee6f --- /dev/null +++ b/web/modules/contrib/devel/devel.links.menu.yml @@ -0,0 +1,89 @@ +devel.admin_settings: + title: 'Devel settings' + description: 'Helper functions, pages, and blocks to assist Drupal developers. The devel blocks can be managed via the block administration page.' + route_name: devel.admin_settings + parent: 'system.admin_config_development' +devel.admin_settings_link: + title: 'Devel settings' + description: 'Helper functions, pages, and blocks to assist Drupal developers. The devel blocks can be managed via the block administration page.' + route_name: devel.admin_settings + menu_name: devel +devel.configs_list: + title: 'Config editor' + description: 'Edit configuration.' + route_name: devel.configs_list + menu_name: devel +devel.reinstall: + title: 'Reinstall Modules' + route_name: devel.reinstall + menu_name: devel + class: \Drupal\devel\Plugin\Menu\DestinationMenuLink +devel.menu_rebuild: + title: 'Rebuild Menu' + route_name: devel.menu_rebuild + menu_name: devel + class: \Drupal\devel\Plugin\Menu\DestinationMenuLink +devel.state_system_page: + title: 'State editor' + description: 'Edit state system values.' + route_name: devel.state_system_page + menu_name: devel +devel.theme_registry: + title: 'Theme registry' + route_name: devel.theme_registry + menu_name: devel +devel.entity_info_page: + title: 'Entity Info' + route_name: devel.entity_info_page +# parent: 'system.admin_config_development' + menu_name: devel +devel.field_info_page: + title: 'Field Info' + route_name: devel.field_info_page +# parent: 'system.admin_config_development' + menu_name: devel +devel.phpinfo: + title: 'PHPinfo()' + route_name: system.php + menu_name: devel +devel.session: + title: 'View Session' + route_name: devel.session + menu_name: devel +devel.elements_page: + title: 'Element Info' + route_name: devel.elements_page + menu_name: devel +devel.cache_clear: + title: 'Cache clear' + route_name: devel.cache_clear + menu_name: devel + class: \Drupal\devel\Plugin\Menu\DestinationMenuLink +devel.run_cron: + title: 'Run cron' + route_name: devel.run_cron + menu_name: devel + class: \Drupal\devel\Plugin\Menu\DestinationMenuLink + +# Container info +devel.container_info.service: + title: 'Container Info' + route_name: devel.container_info.service + menu_name: devel + +# Routes info +devel.route_info: + title: 'Routes Info' + route_name: devel.route_info + menu_name: devel +devel.route_info.item: + title: 'Current route info' + route_name: devel.route_info.item + menu_name: devel + class: \Drupal\devel\Plugin\Menu\RouteDetailMenuLink + +# Event info +devel.event_info: + title: 'Events Info' + route_name: devel.event_info + menu_name: devel diff --git a/web/modules/contrib/devel/devel.links.task.yml b/web/modules/contrib/devel/devel.links.task.yml new file mode 100644 index 00000000..9c7d349e --- /dev/null +++ b/web/modules/contrib/devel/devel.links.task.yml @@ -0,0 +1,18 @@ +devel.entities: + class: \Drupal\Core\Menu\LocalTaskDefault + deriver: \Drupal\devel\Plugin\Derivative\DevelLocalTask +devel.admin_settings: + title: 'Settings' + route_name: devel.admin_settings + base_route: devel.admin_settings + weight: 0 + +# Container info +devel.container_info.service: + title: 'Services' + route_name: devel.container_info.service + base_route: devel.container_info.service +devel.container_info.parameter: + title: 'Parameters' + route_name: devel.container_info.parameter + base_route: devel.container_info.service diff --git a/web/modules/contrib/devel/devel.module b/web/modules/contrib/devel/devel.module new file mode 100644 index 00000000..21c23fbb --- /dev/null +++ b/web/modules/contrib/devel/devel.module @@ -0,0 +1,758 @@ +' . t('About') . ''; + $output .= '

' . t('The Devel module provides a suite of modules containing fun for module developers and themers. For more information, see the online documentation for the Devel module.', [':url' => 'https://www.drupal.org/docs/8/modules/devel']) . '

'; + $output .= '

' . t('Uses') . '

'; + $output .= '
'; + $output .= '
' . t('Inspecting Service Container') . '
'; + $output .= '
' . t('The module allows you to inspect Services and Parameters registered in the Service Container. You can see those informations on Container info page.', [':url' => Url::fromRoute('devel.container_info.service')->toString()]) . '
'; + $output .= '
' . t('Inspecting Routes') . '
'; + $output .= '
' . t('The module allows you to inspect routes information, gathering all routing data from .routing.yml files and from classes which subscribe to the route build/alter events. You can see those informations on Routes info page.', [':url' => Url::fromRoute('devel.route_info')->toString()]) . '
'; + $output .= '
' . t('Inspecting Events') . '
'; + $output .= '
' . t('The module allow you to inspect listeners registered in the event dispatcher. You can see those informations on Events info page.', [':url' => Url::fromRoute('devel.event_info')->toString()]) . '
'; + $output .= '
'; + return $output; + + case 'devel.container_info.service': + case 'devel.container_info.parameter': + $output = ''; + $output .= '

' . t('Displays Services and Parameters registered in the Service Container. For more informations on the Service Container, see the Symfony online documentation.', [':url' => 'http://symfony.com/doc/current/service_container.html']) . '

'; + return $output; + + case 'devel.route_info': + $output = ''; + $output .= '

' . t('Displays registered routes for the site. For a complete overview of the routing system, see the online documentation.', [':url' => 'https://www.drupal.org/docs/8/api/routing-system']) . '

'; + return $output; + + case 'devel.event_info': + $output = ''; + $output .= '

' . t('Displays events and listeners registered in the event dispatcher. For a complete overview of the event system, see the Symfony online documentation.', [':url' => 'http://symfony.com/doc/current/components/event_dispatcher.html']) . '

'; + return $output; + + case 'devel.reinstall': + $output = '

' . t('Warning - will delete your module tables and configuration.') . '

'; + $output .= '

' . t('Uninstall and then install the selected modules. hook_uninstall() and hook_install() will be executed and the schema version number will be set to the most recent update number.') . '

'; + return $output; + + case 'devel/session': + return '

' . t('Here are the contents of your $_SESSION variable.') . '

'; + + case 'devel.state_system_page': + return '

' . t('This is a list of state variables and their values. For more information read online documentation of State API in Drupal 8.', [':documentation' => "https://www.drupal.org/developing/api/8/state"]) . '

'; + + case 'devel.layout_info': + $output = ''; + $output .= '

' . t('Displays layouts available to the site. For a complete overview of the layout system, see the Layout API documentation.', [':url' => 'https://www.drupal.org/docs/8/api/layout-api']) . '

'; + return $output; + + } +} + +/** + * Implements hook_entity_type_alter(). + */ +function devel_entity_type_alter(array &$entity_types) { + return \Drupal::service('class_resolver') + ->getInstanceFromDefinition(EntityTypeInfo::class) + ->entityTypeAlter($entity_types); +} + +/** + * Implements hook_entity_operation(). + */ +function devel_entity_operation(EntityInterface $entity) { + return \Drupal::service('class_resolver') + ->getInstanceFromDefinition(EntityTypeInfo::class) + ->entityOperation($entity); +} + +/** + * Implements hook_toolbar(). + */ +function devel_toolbar() { + return \Drupal::service('class_resolver') + ->getInstanceFromDefinition(ToolbarHandler::class) + ->toolbar(); +} + +/** + * Implements hook_menu_links_discovered_alter(). + */ +function devel_menu_links_discovered_alter(&$links) { + // Conditionally add the Layouts info menu link. + if (\Drupal::moduleHandler()->moduleExists('layout_discovery')) { + $links['devel.layout_info'] = [ + 'title' => new TranslatableMarkup('Layouts Info'), + 'route_name' => 'devel.layout_info', + 'description' => new TranslatableMarkup('Overview of layouts available to the site.'), + 'menu_name' => 'devel', + ]; + } +} + +/** + * Implements hook_local_tasks_alter(). + */ +function devel_local_tasks_alter(&$local_tasks) { + if (\Drupal::moduleHandler()->moduleExists('toolbar')) { + $local_tasks['devel.toolbar.settings_form'] = [ + 'title' => 'Toolbar Settings', + 'base_route' => 'devel.admin_settings', + 'route_name' => 'devel.toolbar.settings_form', + 'class' => LocalTaskDefault::class, + 'options' => [], + ]; + } +} + +/** + * Sets message. + */ +function devel_set_message($msg, $type = NULL) { + if (function_exists('drush_log')) { + drush_log($msg, $type); + } + else { + \Drupal::messenger()->addMessage($msg, $type, TRUE); + } +} + +/** + * Gets error handlers. + */ +function devel_get_handlers() { + $error_handlers = \Drupal::config('devel.settings')->get('error_handlers'); + if (!empty($error_handlers)) { + unset($error_handlers[DEVEL_ERROR_HANDLER_NONE]); + } + return $error_handlers; +} + +/** + * Sets a new error handler or restores the prior one. + */ +function devel_set_handler($handlers) { + if (empty($handlers)) { + restore_error_handler(); + } + elseif (count($handlers) == 1 && isset($handlers[DEVEL_ERROR_HANDLER_STANDARD])) { + // Do nothing. + } + else { + set_error_handler('backtrace_error_handler'); + } +} + +/** + * Displays backtrace showing the route of calls to the current error. + * + * @param int $error_level + * The level of the error raised. + * @param string $message + * The error message. + * @param string $filename + * (optional) The filename that the error was raised in. + * @param int $line + * (optional) The line number the error was raised at. + * @param array $context + * (optional) An array that points to the active symbol table at the point the error + * occurred. + */ +function backtrace_error_handler($error_level, $message, $filename = NULL, $line = NULL, $context = NULL) { + // Hide stack trace and parameters from unqualified users. + if (!\Drupal::currentUser()->hasPermission('access devel information')) { + // Do what core does in bootstrap.inc and errors.inc. + // (We need to duplicate the core code here rather than calling it + // to avoid having the backtrace_error_handler() on top of the call stack.) + if ($error_level & error_reporting()) { + $types = drupal_error_levels(); + list($severity_msg, $severity_level) = $types[$error_level]; + $backtrace = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS); + $caller = Error::getLastCaller($backtrace); + + // We treat recoverable errors as fatal. + _drupal_log_error([ + '%type' => isset($types[$error_level]) ? $severity_msg : 'Unknown error', + '@message' => $message, + '%function' => $caller['function'], + '%file' => $caller['file'], + '%line' => $caller['line'], + 'severity_level' => $severity_level, + 'backtrace' => $backtrace, + ], $error_level == E_RECOVERABLE_ERROR); + } + + return; + } + + // Don't respond to the error if it was suppressed with a '@'. + if (error_reporting() == 0) { + return; + } + + // Don't respond to warning caused by ourselves. + if (preg_match('#Cannot modify header information - headers already sent by \\([^\\)]*[/\\\\]devel[/\\\\]#', $message)) { + return; + } + + if ($error_level & error_reporting()) { + // Only write each distinct NOTICE message once, as repeats do not give any + // further information and can choke the page output. + if ($error_level == E_NOTICE) { + static $written = []; + if (!empty($written[$line][$filename][$message])) { + return; + } + $written[$line][$filename][$message] = TRUE; + } + + $types = drupal_error_levels(); + list($severity_msg, $severity_level) = $types[$error_level]; + + $backtrace = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS); + $caller = Error::getLastCaller($backtrace); + $variables = [ + '%type' => isset($types[$error_level]) ? $severity_msg : 'Unknown error', + '@message' => $message, + '%function' => $caller['function'], + '%file' => $caller['file'], + '%line' => $caller['line'], + ]; + $msg = t('%type: @message in %function (line %line of %file).', $variables); + + // Show message if error_level is ERROR_REPORTING_DISPLAY_SOME or higher. + // (This is Drupal's error_level, which is different from $error_level, + // and we purposely ignore the difference between _SOME and _ALL, + // see #970688!) + if (\Drupal::config('system.logging')->get('error_level') != 'hide') { + $error_handlers = devel_get_handlers(); + if (!empty($error_handlers[DEVEL_ERROR_HANDLER_STANDARD])) { + \Drupal::messenger()->addMessage($msg, ($severity_level <= RfcLogLevel::NOTICE ? MessengerInterface::TYPE_ERROR : MessengerInterface::TYPE_WARNING), TRUE); + } + if (!empty($error_handlers[DEVEL_ERROR_HANDLER_BACKTRACE_KINT])) { + print kpr(ddebug_backtrace(TRUE, 1), TRUE, $msg); + } + if (!empty($error_handlers[DEVEL_ERROR_HANDLER_BACKTRACE_DPM])) { + dpm(ddebug_backtrace(TRUE, 1), $msg, 'warning'); + } + } + + \Drupal::logger('php')->log($severity_level, $msg); + } +} + +/** + * Implements hook_page_attachments_alter(). + */ +function devel_page_attachments_alter(&$page) { + if (\Drupal::currentUser()->hasPermission('access devel information') && \Drupal::config('devel.settings')->get('page_alter')) { + dpm($page, 'page'); + } +} + +/** + * Dumps information about a variable. + * + * Wrapper for DevelDumperManager::dump(). + * + * @param mixed $input + * The variable to dump. + * @param string $name + * (optional) The label to output before variable, defaults to NULL. + * @param string $plugin_id + * (optional) The plugin ID, defaults to NULL. + * + * @see \Drupal\devel\DevelDumperManager::dump() + */ +function devel_dump($input, $name = NULL, $plugin_id = NULL) { + \Drupal::service('devel.dumper')->dump($input, $name, $plugin_id); +} + +/** + * Returns a string representation of a variable. + * + * Wrapper for DevelDumperManager::export(). + * + * @param mixed $input + * The variable to dump. + * @param string $name + * (optional) The label to output before variable, defaults to NULL. + * @param string $plugin_id + * (optional) The plugin ID, defaults to NULL. + * + * @return string + * String representation of a variable. + * + * @see \Drupal\devel\DevelDumperManager::export() + */ +function devel_export($input, $name = NULL, $plugin_id = NULL) { + return \Drupal::service('devel.dumper')->export($input, $name, $plugin_id); +} + +/** + * Sets a message with a string representation of a variable. + * + * Wrapper for DevelDumperManager::message(). + * + * @param mixed $input + * The variable to dump. + * @param string $name + * (optional) The label to output before variable, defaults to NULL. + * @param string $type + * (optional) The message's type. Defaults to 'status'. + * @param string $plugin_id + * (optional) The plugin ID, defaults to NULL. + * + * @see \Drupal\devel\DevelDumperManager::message() + */ +function devel_message($input, $name = NULL, $type = 'status', $plugin_id = NULL) { + \Drupal::service('devel.dumper')->message($input, $name, $type, $plugin_id); +} + +/** + * Logs a variable to a drupal_debug.txt in the site's temp directory. + * + * Wrapper for DevelDumperManager::debug(). + * + * @param mixed $input + * The variable to log to the drupal_debug.txt log file. + * @param string $name + * (optional) If set, a label to output before $data in the log file. + * @param string $plugin_id + * (optional) The plugin ID, defaults to NULL. + * + * @return null|false + * Empty if successful, FALSE if the log file could not be written. + * + * @see \Drupal\devel\DevelDumperManager::debug() + */ +function devel_debug($input, $name = NULL, $plugin_id = NULL) { + return \Drupal::service('devel.dumper')->debug($input, $name, $plugin_id); +} + +/** + * Wrapper for DevelDumperManager::dump(). + * + * Calls the http://www.firephp.org/ fb() function if it is found. + * + * @see \Drupal\devel\DevelDumperManager::dump() + */ +function dfb() { + $args = func_get_args(); + \Drupal::service('devel.dumper')->dump($args, NULL, 'firephp'); +} + +/** + * Wrapper for DevelDumperManager::dump(). + * + * Calls dfb() to output a backtrace. + * + * @see \Drupal\devel\DevelDumperManager::dump() + */ +function dfbt($label) { + \Drupal::service('devel.dumper')->dump(FirePHP::TRACE, $label, 'firephp'); +} + +if (!function_exists('dd')) { + + /** + * Wrapper for DevelDumperManager::debug(). + * + * @deprecated since Drupal 8.6.0 because symfony now has dd() as a function. + * Use the ddm() function instead. + * + * @see \Drupal\devel\DevelDumperManager::debug() + */ + function dd($data, $label = NULL) { + return \Drupal::service('devel.dumper')->debug($data, $label, 'default'); + } + +} + +if (!function_exists('ddm')) { + + /** + * Wrapper for DevelDumperManager::debug() to replace previous dd function. + * + * @see \Drupal\devel\DevelDumperManager::debug() + */ + function ddm($data, $label = NULL) { + return \Drupal::service('devel.dumper')->debug($data, $label, 'default'); + } + +} + +if (!function_exists('kint')) { + + /** + * Prints passed argument(s) using Kint debug tool. + * + * Wrapper for DevelDumperManager::dump(). + * + * @see \Drupal\devel\DevelDumperManager::dump() + */ + function kint() { + $args = func_get_args(); + if (count($args) == 1) { + // Pass a single argument directly, which works for any plug-in. + $args = $args[0]; + $name = NULL; + } + else { + // Pass an array marked with a special name. The kint plug-in expands the + // arguments and prints each separately. + $name = '__ARGS__'; + } + + return \Drupal::service('devel.dumper')->dump($args, $name, 'kint'); + } + +} + +if (!function_exists('ksm')) { + + /** + * Prints passed argument(s) to the 'message' area of the page. + * + * Wrapper for DevelDumperManager::message(). + * + * @see \Drupal\devel\DevelDumperManager::message() + */ + function ksm() { + $args = func_get_args(); + if (count($args) == 1) { + // Pass a single argument directly, which works for any plug-in. + $args = $args[0]; + $name = NULL; + } + else { + // Pass an array marked with a special name. The kint plug-in expands the + // arguments and prints each separately. + $name = '__ARGS__'; + } + + return \Drupal::service('devel.dumper')->message($args, $name, MessengerInterface::TYPE_STATUS, 'kint'); + } + +} + +/** + * Wrapper for DevelDumperManager::message(). + * + * Prints a variable to the 'message' area of the page. + * + * Uses Drupal\Core\Messenger\MessengerInterface::addMessage() + * + * @param mixed $input + * An arbitrary value to output. + * @param string $name + * Optional name for identifying the output. + * @param string $type + * Optional message type see MessengerInterface, defaults to TYPE_STATUS. + * + * @return input + * The unaltered input value. + * + * @see \Drupal\devel\DevelDumperManager::message() + */ +function dpm($input, $name = NULL, $type = MessengerInterface::TYPE_STATUS) { + \Drupal::service('devel.dumper')->message($input, $name, $type); + return $input; +} + +/** + * Wrapper for DevelDumperManager::message(). + * + * Displays a Variable::export() variable to the 'message' area of the page. + * + * Uses Drupal\Core\Messenger\MessengerInterface::addMessage() + * + * @param $input + * An arbitrary value to output. + * @param string $name + * Optional name for identifying the output. + * + * @return input + * The unaltered input value. + * + * @see \Drupal\devel\DevelDumperManager::message() + */ +function dvm($input, $name = NULL) { + \Drupal::service('devel.dumper')->message($input, $name, MessengerInterface::TYPE_STATUS, 'drupal_variable'); + return $input; +} + +/** + * An alias for dpm(), for historic reasons. + */ +function dsm($input, $name = NULL) { + return dpm($input, $name); +} + +/** + * Wrapper for DevelDumperManager::dumpOrExport(). + * + * An alias for the devel.dumper service. Saves carpal tunnel syndrome. + * + * @see \Drupal\devel\DevelDumperManager::dumpOrExport() + */ +function dpr($input, $export = FALSE, $name = NULL) { + return \Drupal::service('devel.dumper')->dumpOrExport($input, $name, $export, 'default'); +} + +/** + * Wrapper for DevelDumperManager::dumpOrExport(). + * + * An alias for devel_dump(). Saves carpal tunnel syndrome. + * + * @see \Drupal\devel\DevelDumperManager::dumpOrExport() + */ +function kpr($input, $export = FALSE, $name = NULL) { + return \Drupal::service('devel.dumper')->dumpOrExport($input, $name, $export); +} + +/** + * Wrapper for DevelDumperManager::dumpOrExport(). + * + * Like dpr(), but uses Variable::export() instead. + * + * @see \Drupal\devel\DevelDumperManager::dumpOrExport() + */ +function dvr($input, $export = FALSE, $name = NULL) { + return \Drupal::service('devel.dumper')->dumpOrExport($input, $name, $export, 'drupal_variable'); +} + +/** + * Prints the arguments passed into the current function. + */ +function dargs($always = TRUE) { + static $printed; + if ($always || !$printed) { + $bt = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS); + print kpr($bt[1]['args'], TRUE); + $printed = TRUE; + } +} + +/** + * Prints a SQL string from a DBTNG Select object. Includes quoted arguments. + * + * @param object $query + * An object that implements the SelectInterface interface. + * @param bool $return + * Whether to return the string. Default is FALSE, meaning to print it + * and return $query instead. + * @param string $name + * Optional name for identifying the output. + * + * @return object|string + * The $query object, or the query string if $return was TRUE. + */ +function dpq($query, $return = FALSE, $name = NULL) { + if (\Drupal::currentUser()->hasPermission('access devel information')) { + if (method_exists($query, 'preExecute')) { + $query->preExecute(); + } + $sql = (string) $query; + $quoted = []; + $database = \Drupal::database(); + foreach ((array) $query->arguments() as $key => $val) { + $quoted[$key] = is_null($val) ? 'NULL' : $database->quote($val); + } + $sql = strtr($sql, $quoted); + if ($return) { + return $sql; + } + dpm($sql, $name); + } + return ($return ? NULL : $query); +} + +/** + * Prints a renderable array element to the screen using kprint_r(). + * + * #pre_render and/or #post_render pass-through callback for kprint_r(). + * + * @todo Investigate appending to #suffix. + * @todo Investigate label derived from #id, #title, #name, and #theme. + */ +function devel_render() { + $args = func_get_args(); + // #pre_render and #post_render pass the rendered $element as last argument. + kpr(end($args)); + // #pre_render and #post_render expect the first argument to be returned. + return reset($args); +} + +/** + * Prints the function call stack. + * + * @param $return + * Pass TRUE to return the formatted backtrace rather than displaying it in + * the browser via kprint_r(). + * @param $pop + * How many items to pop from the top of the stack; useful when calling from + * an error handler. + * @param $options + * Options to pass on to PHP's debug_backtrace(). + * + * @return string|null + * The formatted backtrace, if requested, or NULL. + * + * @see http://php.net/manual/en/function.debug-backtrace.php + */ +function ddebug_backtrace($return = FALSE, $pop = 0, $options = DEBUG_BACKTRACE_PROVIDE_OBJECT) { + if (\Drupal::currentUser()->hasPermission('access devel information')) { + $backtrace = debug_backtrace($options); + while ($pop-- > 0) { + array_shift($backtrace); + } + $counter = count($backtrace); + $path = $backtrace[$counter - 1]['file']; + $path = substr($path, 0, strlen($path) - 10); + $paths[$path] = strlen($path) + 1; + $paths[DRUPAL_ROOT] = strlen(DRUPAL_ROOT) + 1; + $nbsp = "\xC2\xA0"; + + // Show message if error_level is ERROR_REPORTING_DISPLAY_SOME or higher. + // (This is Drupal's error_level, which is different from $error_level, + // and we purposely ignore the difference between _SOME and _ALL, + // see #970688!) + if (\Drupal::config('system.logging')->get('error_level') != 'hide') { + while (!empty($backtrace)) { + $call = []; + if (isset($backtrace[0]['file'])) { + $call['file'] = $backtrace[0]['file']; + foreach ($paths as $path => $len) { + if (strpos($backtrace[0]['file'], $path) === 0) { + $call['file'] = substr($backtrace[0]['file'], $len); + } + } + $call['file'] .= ':' . $backtrace[0]['line']; + } + if (isset($backtrace[1])) { + if (isset($backtrace[1]['class'])) { + $function = $backtrace[1]['class'] . $backtrace[1]['type'] . $backtrace[1]['function'] . '()'; + } + else { + $function = $backtrace[1]['function'] . '()'; + } + $backtrace[1] += ['args' => []]; + foreach ($backtrace[1]['args'] as $key => $value) { + $call['args'][$key] = $value; + } + } + else { + $function = 'main()'; + $call['args'] = $_GET; + } + $nicetrace[($counter <= 10 ? $nbsp : '') . --$counter . ': ' . $function] = $call; + array_shift($backtrace); + } + if ($return) { + return $nicetrace; + } + kpr($nicetrace); + } + } +} + +/** + * Implements hook_form_FORM_ID_alter(). + * + * Adds mouse-over hints on the Permissions page to display + * language-independent machine names and module base names. + * + * @see \Drupal\user\Form\UserPermissionsForm::buildForm() + */ +function devel_form_user_admin_permissions_alter(&$form, FormStateInterface $form_state) { + if (\Drupal::currentUser()->hasPermission('access devel information') && \Drupal::config('devel.settings')->get('raw_names')) { + foreach (Element::children($form['permissions']) as $key) { + if (isset($form['permissions'][$key][0])) { + $form['permissions'][$key][0]['#wrapper_attributes']['title'] = $key; + } + elseif (isset($form['permissions'][$key]['description'])) { + $form['permissions'][$key]['description']['#wrapper_attributes']['title'] = $key; + } + } + } +} + +/** + * Implements hook_form_FORM_ID_alter(). + * + * Adds mouse-over hints on the Modules page to display module base names. + * + * @see \Drupal\system\Form\ModulesListForm::buildForm() + * @see theme_system_modules_details() + */ +function devel_form_system_modules_alter(&$form, FormStateInterface $form_state) { + if (\Drupal::currentUser()->hasPermission('access devel information') && \Drupal::config('devel.settings')->get('raw_names', FALSE) && isset($form['modules']) && is_array($form['modules'])) { + foreach (Element::children($form['modules']) as $group) { + if (is_array($form['modules'][$group])) { + foreach (Element::children($form['modules'][$group]) as $key) { + if (isset($form['modules'][$group][$key]['name']['#markup'])) { + $form['modules'][$group][$key]['name']['#markup'] = '' . $form['modules'][$group][$key]['name']['#markup'] . ''; + } + } + } + } + } +} + +/** + * Implements hook_query_TAG_alter(). + * + * Makes debugging entity query much easier. + * + * Example usage: + * @code + * $query = \Drupal::entityQuery('node'); + * $query->condition('status', NODE_PUBLISHED); + * $query->addTag('debug'); + * $query->execute(); + * @endcode + */ +function devel_query_debug_alter(AlterableInterface $query) { + if (!$query->hasTag('debug-semaphore')) { + $query->addTag('debug-semaphore'); + dpq($query); + } +} diff --git a/web/modules/contrib/devel/devel.permissions.yml b/web/modules/contrib/devel/devel.permissions.yml new file mode 100644 index 00000000..e32ad8c1 --- /dev/null +++ b/web/modules/contrib/devel/devel.permissions.yml @@ -0,0 +1,9 @@ +access devel information: + description: 'View developer output like variable printouts, query log, etc.' + title: 'Access developer information' + restrict access: TRUE + +switch users: + title: 'Switch users' + description: 'Become any user on the site with just a click.' + restrict access: TRUE diff --git a/web/modules/contrib/devel/devel.routing.yml b/web/modules/contrib/devel/devel.routing.yml new file mode 100644 index 00000000..80be9c54 --- /dev/null +++ b/web/modules/contrib/devel/devel.routing.yml @@ -0,0 +1,288 @@ +devel.admin_settings: + path: '/admin/config/development/devel' + defaults: + _form: '\Drupal\devel\Form\SettingsForm' + _title: 'Devel settings' + requirements: + _permission: 'administer site configuration' + +devel.toolbar.settings_form: + path: '/admin/config/development/devel/toolbar' + defaults: + _form: '\Drupal\devel\Form\ToolbarSettingsForm' + _title: 'Devel Toolbar Settings' + requirements: + _permission: 'administer site configuration' + _module_dependencies: 'toolbar' + +devel.reinstall: + path: '/devel/reinstall' + defaults: + _form: '\Drupal\devel\Form\DevelReinstall' + _title: 'Reinstall modules' + options: + _admin_route: TRUE + requirements: + _permission: 'administer site configuration' + +devel.menu_rebuild: + path: '/devel/menu/reset' + defaults: + _form: '\Drupal\devel\Form\RouterRebuildConfirmForm' + _title: 'Rebuild router' + options: + _admin_route: TRUE + requirements: + _permission: 'administer site configuration' + +devel.configs_list: + path: '/devel/config/{filter}' + options: + _admin_route: TRUE + defaults: + _form: '\Drupal\devel\Form\ConfigsList' + _title: 'Config editor' + filter: '' + requirements: + _permission: 'administer site configuration' + +devel.config_edit: + path: '/devel/config/edit/{config_name}' + defaults: + _form: '\Drupal\devel\Form\ConfigEditor' + _title: 'Edit configuration object: @config_name' + options: + _admin_route: TRUE + requirements: + _permission: 'administer site configuration' + +devel.config_delete: + path: '/devel/config/delete/{config_name}' + defaults: + _form: '\Drupal\devel\Form\ConfigDeleteForm' + _title: 'Delete configuration object: @config_name' + options: + _admin_route: TRUE + requirements: + _permission: 'administer site configuration' + +devel.state_system_page: + path: '/devel/state' + defaults: + _controller: '\Drupal\devel\Controller\DevelController::stateSystemPage' + _title: 'State editor' + options: + _admin_route: TRUE + requirements: + _permission: 'access devel information' + +devel.system_state_edit: + path: '/devel/state/edit/{state_name}' + defaults: + _form: '\Drupal\devel\Form\SystemStateEdit' + _title: 'Edit state variable: @state_name' + options: + _admin_route: TRUE + requirements: + _permission: 'administer site configuration' + +devel.theme_registry: + path: '/devel/theme/registry' + defaults: + _controller: '\Drupal\devel\Controller\DevelController::themeRegistry' + _title: 'Theme registry' + options: + _admin_route: TRUE + requirements: + _permission: 'access devel information' + +devel.field_info_page: + path: '/devel/field/info' + defaults: + _controller: '\Drupal\devel\Controller\DevelController::fieldInfoPage' + _title: 'Field info' + options: + _admin_route: TRUE + requirements: + _permission: 'access devel information' + +devel.session: + path: '/devel/session' + defaults: + _controller: '\Drupal\devel\Controller\DevelController::session' + _title: 'Session viewer' + options: + _admin_route: TRUE + requirements: + _permission: 'access devel information' + +devel.switch: + path: '/devel/switch/{name}' + defaults: + _controller: '\Drupal\devel\Controller\SwitchUserController::switchUser' + _title: 'Switch user' + name: '' + options: + _admin_route: TRUE + requirements: + _permission: 'switch users' + _csrf_token: 'TRUE' + +devel.cache_clear: + path: '/devel/cache/clear' + defaults: + _controller: '\Drupal\devel\Controller\DevelController::cacheClear' + _title: 'Clear cache' + options: + _admin_route: TRUE + requirements: + _permission: 'access devel information' + _csrf_token: 'TRUE' + +devel.run_cron: + path: '/devel/run-cron' + defaults: + _controller: '\Drupal\system\CronController::runManually' + _title: 'Run cron' + options: + _admin_route: TRUE + requirements: + _permission: 'administer site configuration' + _csrf_token: 'TRUE' + +# Container info +devel.container_info.service: + path: '/devel/container/service' + defaults: + _controller: '\Drupal\devel\Controller\ContainerInfoController::serviceList' + _title: 'Container services' + options: + _admin_route: TRUE + requirements: + _permission: 'access devel information' + +devel.container_info.service.detail: + path: '/devel/container/service/{service_id}' + defaults: + _controller: '\Drupal\devel\Controller\ContainerInfoController::serviceDetail' + _title: 'Service @service_id detail' + options: + _admin_route: TRUE + requirements: + _permission: 'access devel information' + +devel.container_info.parameter: + path: '/devel/container/parameter' + defaults: + _controller: '\Drupal\devel\Controller\ContainerInfoController::parameterList' + _title: 'Container parameters' + options: + _admin_route: TRUE + requirements: + _permission: 'access devel information' + +devel.container_info.parameter.detail: + path: '/devel/container/parameter/{parameter_name}' + defaults: + _controller: '\Drupal\devel\Controller\ContainerInfoController::parameterDetail' + _title: 'Parameter @parameter_name value' + options: + _admin_route: TRUE + requirements: + _permission: 'access devel information' + +# Route info +devel.route_info: + path: '/devel/routes' + defaults: + _controller: '\Drupal\devel\Controller\RouteInfoController::routeList' + _title: 'Routes' + options: + _admin_route: TRUE + requirements: + _permission: 'access devel information' + +devel.route_info.item: + path: '/devel/routes/item' + defaults: + _controller: '\Drupal\devel\Controller\RouteInfoController::routeDetail' + _title: 'Route detail' + options: + _admin_route: TRUE + requirements: + _permission: 'access devel information' + +# Event info +devel.event_info: + path: '/devel/events' + defaults: + _controller: '\Drupal\devel\Controller\EventInfoController::eventList' + _title: 'Events' + options: + _admin_route: TRUE + requirements: + _permission: 'access devel information' + +# Layouts info +devel.layout_info: + path: '/devel/layouts' + defaults: + _controller: '\Drupal\devel\Controller\LayoutInfoController::layoutInfoPage' + _title: 'Layouts' + options: + _admin_route: TRUE + requirements: + _permission: 'access devel information' + _module_dependencies: 'layout_discovery' + +# Element info +devel.elements_page: + path: '/devel/elements' + defaults: + _controller: '\Drupal\devel\Controller\ElementInfoController::elementList' + _title: 'Element Info' + options: + _admin_route: TRUE + requirements: + _permission: 'access devel information' + +devel.elements_page.detail: + path: '/devel/elements/{element_name}' + defaults: + _controller: '\Drupal\devel\Controller\ElementInfoController::elementDetail' + _title: 'Element @element_name' + options: + _admin_route: TRUE + requirements: + _permission: 'access devel information' + +# Entity type info +devel.entity_info_page: + path: '/devel/entity/info' + defaults: + _controller: '\Drupal\devel\Controller\EntityTypeInfoController::entityTypeList' + _title: 'Entity info' + options: + _admin_route: TRUE + requirements: + _permission: 'access devel information' + +devel.entity_info_page.detail: + path: '/devel/entity/info/{entity_type_id}' + defaults: + _controller: '\Drupal\devel\Controller\EntityTypeInfoController::entityTypeDetail' + _title: 'Entity type @entity_type_id' + options: + _admin_route: TRUE + requirements: + _permission: 'access devel information' + +devel.entity_info_page.fields: + path: '/devel/entity/fields/{entity_type_id}' + defaults: + _controller: '\Drupal\devel\Controller\EntityTypeInfoController::entityTypeFields' + _title: 'Entity fields @entity_type_id' + options: + _admin_route: TRUE + requirements: + _permission: 'access devel information' diff --git a/web/modules/contrib/devel/devel.services.yml b/web/modules/contrib/devel/devel.services.yml new file mode 100644 index 00000000..2e74e1ad --- /dev/null +++ b/web/modules/contrib/devel/devel.services.yml @@ -0,0 +1,32 @@ +services: + devel.error_subscriber: + class: Drupal\devel\EventSubscriber\ErrorHandlerSubscriber + arguments: ['@current_user'] + tags: + - { name: event_subscriber } + + devel.theme_rebuild_subscriber: + class: Drupal\devel\EventSubscriber\ThemeInfoRebuildSubscriber + arguments: ['@config.factory', '@current_user', '@theme_handler'] + tags: + - { name: event_subscriber } + + devel.route_subscriber: + class: Drupal\devel\Routing\RouteSubscriber + arguments: ['@entity_type.manager'] + tags: + - { name: event_subscriber } + + plugin.manager.devel_dumper: + class: Drupal\devel\DevelDumperPluginManager + parent: default_plugin_manager + + devel.dumper: + class: Drupal\devel\DevelDumperManager + arguments: ['@config.factory', '@current_user', '@plugin.manager.devel_dumper'] + + devel.twig.debug_extension: + class: Drupal\devel\Twig\Extension\Debug + arguments: ['@devel.dumper'] + tags: + - { name: twig.extension } diff --git a/web/modules/contrib/devel/devel_generate/README.md b/web/modules/contrib/devel/devel_generate/README.md new file mode 100644 index 00000000..8ed10c12 --- /dev/null +++ b/web/modules/contrib/devel/devel_generate/README.md @@ -0,0 +1,57 @@ +[[_TOC_]] + +This module may be used to create entities that contain sample content. This is +useful when showing off your site to a client, for example. Even if the content +is not yet available, the site can show its look and feel and behavior. + +The sample entities may be created via the Web or via the included Drush commands. + +#### Recommended Modules + +- [Devel Images Provider](http://drupal.org/project/devel_image_provider) allows to configure external providers for images. + +#### Custom plugins + +This module creates the _DevelGenerate_ plugin type. + +All you need to do to provide a new instance for DevelGenerate plugin type +is to create your class extending `DevelGenerateBase` and following these steps: + +1. Declare your plugin with annotations: + ```` + /** + * Provides a ExampleDevelGenerate plugin. + * + * @DevelGenerate( + * id = "example", + * label = @Translation("example"), + * description = @Translation("Generate a given number of example elements."), + * url = "example", + * permission = "administer example", + * settings = { + * "num" = 50, + * "kill" = FALSE, + * "another_property" = "default_value" + * } + * ) + */ + ```` +1. Implement the `settingsForm` method to create a form using the properties +from the annotations. +1. Implement the `handleDrushParams` method. It should return an array of +values. +1. Implement the `generateElements` method. You can write here your business +logic using the array of values. + +#### Notes + +- You can alter existing properties for every plugin by implementing +`hook_devel_generate_info_alter`. +- DevelGenerateBaseInterface details base wrapping methods that most +DevelGenerate implementations will want to directly inherit from +`Drupal\devel_generate\DevelGenerateBase`. +- To give support for a new field type the field type base class should properly +implement `\Drupal\Core\Field\FieldItemInterface::generateSampleValue()`. +Devel Generate automatically uses the values returned by this method during the +generate process for generating placeholder field values. For more information +see: https://api.drupal.org/api/drupal/core!lib!Drupal!Core!Field!FieldItemInterface.php/function/FieldItemInterface::generateSampleValue diff --git a/web/modules/contrib/devel/devel_generate/composer.json b/web/modules/contrib/devel/devel_generate/composer.json new file mode 100644 index 00000000..4c32c156 --- /dev/null +++ b/web/modules/contrib/devel/devel_generate/composer.json @@ -0,0 +1,52 @@ +{ + "name": "drupal/devel_generate", + "description": "Generate dummy users, nodes, menus, taxonomy terms...", + "type": "drupal-module", + "homepage": "http://drupal.org/project/devel", + "authors": [ + { + "name": "Moshe Weitzman", + "email": "weitzman@tejasa.com", + "homepage": "https://github.com/weitzman", + "role": "Maintainer" + }, + { + "name": "Hans Salvisberg", + "email": "drupal@salvisberg.com", + "homepage": "https://www.drupal.org/u/salvis", + "role": "Maintainer" + }, + { + "name": "Luca Lusso", + "homepage": "https://www.drupal.org/u/lussoluca", + "role": "Maintainer" + }, + { + "name": "Marco (willzyx)", + "homepage": "https://www.drupal.org/u/willzyx", + "role": "Maintainer" + }, + { + "name": "See contributors", + "homepage": "https://www.drupal.org/node/3236/committers" + } + ], + "support": { + "issues": "http://drupal.org/project/devel", + "irc": "irc://irc.freenode.org/drupal-contribute", + "source": "http://cgit.drupalcode.org/devel" + }, + "license": "GPL-2.0-or-later", + "minimum-stability": "dev", + "require": {}, + "suggest": { + "drupal/realistic_dummy_content": "Generate realistic demo content with Devel's devel_generate module." + }, + "extra": { + "drush": { + "services": { + "drush.services.yml": "^9 || ^10" + } + } + } +} diff --git a/web/modules/contrib/devel/devel_generate/devel_generate.batch.inc b/web/modules/contrib/devel/devel_generate/devel_generate.batch.inc new file mode 100644 index 00000000..09b74c15 --- /dev/null +++ b/web/modules/contrib/devel/devel_generate/devel_generate.batch.inc @@ -0,0 +1,34 @@ +$method($vars, $context); +} + +/** + * Standard finish batch function. + */ +function devel_generate_batch_finished($success, $results, $operations) { + + if ($success) { + if (!empty($results['num_translations'])) { + $message = t('Finished @num elements and @num_translations translations created successfully.', ['@num' => $results['num'], '@num_translations' => $results['num_translations']]); + } + else { + $message = t('Finished @num elements created successfully.', ['@num' => $results['num']]); + } + } + else { + $message = t('Finished with an error.'); + } + \Drupal::messenger()->addMessage($message); +} diff --git a/web/modules/contrib/devel/devel_generate/devel_generate.info.yml b/web/modules/contrib/devel/devel_generate/devel_generate.info.yml new file mode 100644 index 00000000..1286f376 --- /dev/null +++ b/web/modules/contrib/devel/devel_generate/devel_generate.info.yml @@ -0,0 +1,13 @@ +type: module +name: 'Devel Generate' +description: 'Generate dummy users, nodes, menus, taxonomy terms...' +package: Development +core_version_requirement: ^8.8 || ^9 +php: 7.2 +tags: + - developer + +# Information added by Drupal.org packaging script on 2020-12-31 +version: '4.1.1' +project: 'devel' +datestamp: 1609419530 diff --git a/web/modules/contrib/devel/devel_generate/devel_generate.module b/web/modules/contrib/devel/devel_generate/devel_generate.module new file mode 100644 index 00000000..d825ec92 --- /dev/null +++ b/web/modules/contrib/devel/devel_generate/devel_generate.module @@ -0,0 +1,177 @@ +getDefinitions(); + foreach ($devel_generate_plugins as $id => $plugin) { + $label = $plugin['label']; + $links["devel_generate.$id"] = [ + 'title' => new TranslatableMarkup("Generate @label", ['@label' => $label]), + 'parent' => 'devel_generate.admin_config_generate', + 'description' => $plugin['description'], + 'route_name' => "devel_generate.$id", + 'provider' => 'devel_generate', + ]; + } + + // Store the basic link info for repeated use. Each of the three actual links + // require subtle variations on this. + $basics = [ + 'title' => new TranslatableMarkup('Generate'), + 'description' => new TranslatableMarkup('Generate realistic items (content, users, menus, etc) to assist your site development and testing.'), + 'route_name' => 'devel_generate.admin_config_generate', + 'provider' => 'devel_generate', + ]; + + // Define a separate group on admin/config page, so that 'Generate' has its + // own block with all the generate links. + $links['devel_generate.admin_config_generate'] = [ + 'parent' => 'system.admin_config', + // The main development group has weight -10 in system.links.menu.yml so use + // -9 here as this block should be near but just after it on the page. + 'weight' => -9, + ] + $basics; + + // Add a link in the main development group, to allow direct access to the + // the Generate page and to make the back breadcrumb more useful. + $links['devel_generate.generate'] = [ + 'title' => new TranslatableMarkup('Devel generate'), + 'parent' => 'system.admin_config_development', + ] + $basics; + + // Define a top-level link (with no parent) in the 'devel' menu. This also + // means that it will be available in the devel admin toolbar. + $links['devel_generate.generate2'] = ['menu_name' => 'devel'] + $basics; + +} + +/** + * Implements hook_entity_insert(). + * + * Inserts nodes properly based on generation options. + * + * @param \Drupal\Core\Entity\EntityInterface $entity + * The base node created on submit. Inspects $node->devel_generate. + * + * @todo Can more of this processing move into develGenerateContentAddNode() ? + * Adding url alias is now moved. + */ +function devel_generate_entity_insert(EntityInterface $entity) { + if ($entity->getEntityTypeId() != 'node' || !isset($entity->devel_generate)) { + return; + } + /* @var \Drupal\node\NodeInterface $entity */ + $results = $entity->devel_generate; + + if (!empty($results['max_comments'])) { + foreach ($entity->getFieldDefinitions() as $field_name => $field_definition) { + if ($field_definition->getType() == 'comment' && $entity->get($field_name)->status == CommentItemInterface::OPEN) { + // Add comments for each comment field on entity. + devel_generate_add_comments($entity, $field_definition, $results['users'], $results['max_comments'], $results['title_length']); + } + } + } + + // Add node statistics. + if (!empty($results['add_statistics']) && \Drupal::moduleHandler()->moduleExists('statistics')) { + devel_generate_add_statistics($entity); + } +} + +/** + * Create comments and add them to a node. + * + * @param \Drupal\node\NodeInterface $node + * Node to add comments to. + * @param \Drupal\Core\Field\FieldDefinitionInterface $field_definition + * The field storage definition. + * @param array $users + * Array of users to assign comment authors. + * @param int $max_comments + * Max number of comments to generate per node. + * @param int $title_length + * Max length of the title of the comments. + */ +function devel_generate_add_comments(NodeInterface $node, FieldDefinitionInterface $field_definition, $users, $max_comments, $title_length = 8) { + $parents = []; + $field_name = $field_definition->getName(); + $num_comments = mt_rand(0, $max_comments); + for ($i = 1; $i <= $num_comments; $i++) { + switch ($i % 3) { + case 0: + // No parent. + case 1: + // Top level parent. + $parents = \Drupal::entityQuery('comment') + ->condition('pid', 0) + ->condition('entity_id', $node->id()) + ->condition('entity_type', 'node') + ->condition('field_name', $field_name) + ->range(0, 1) + ->execute(); + break; + + case 2: + // Non top level parent. + $parents = \Drupal::entityQuery('comment') + ->condition('pid', 0, '>') + ->condition('entity_id', $node->id()) + ->condition('entity_type', 'node') + ->condition('field_name', $field_name) + ->range(0, 1) + ->execute(); + break; + } + $random = new Random(); + $stub = [ + 'entity_type' => $node->getEntityTypeId(), + 'entity_id' => $node->id(), + 'field_name' => $field_name, + 'name' => 'devel generate', + 'mail' => 'devel_generate@example.com', + 'timestamp' => mt_rand($node->getCreatedTime(), \Drupal::time()->getRequestTime()), + 'subject' => substr($random->sentences(mt_rand(1, $title_length), TRUE), 0, 63), + 'uid' => $users[array_rand($users)], + 'langcode' => $node->language()->getId(), + ]; + if ($parents) { + $stub['pid'] = current($parents); + } + $comment = \Drupal::entityTypeManager()->getStorage('comment')->create($stub); + + // Populate all core fields on behalf of field.module. + DevelGenerateBase::populateFields($comment); + $comment->save(); + } +} + +/** + * Generate statistics information for a node. + * + * @param \Drupal\node\NodeInterface $node + * A node object. + */ +function devel_generate_add_statistics(NodeInterface $node) { + $statistic = [ + 'nid' => $node->id(), + 'totalcount' => mt_rand(0, 500), + 'timestamp' => \Drupal::time()->getRequestTime() - mt_rand(0, $node->getCreatedTime()), + ]; + $statistic['daycount'] = mt_rand(0, $statistic['totalcount']); + $database = \Drupal::database(); + $database->insert('node_counter')->fields($statistic)->execute(); +} diff --git a/web/modules/contrib/devel/devel_generate/devel_generate.permissions.yml b/web/modules/contrib/devel/devel_generate/devel_generate.permissions.yml new file mode 100644 index 00000000..10f9479e --- /dev/null +++ b/web/modules/contrib/devel/devel_generate/devel_generate.permissions.yml @@ -0,0 +1,5 @@ +administer devel_generate: + title: 'Administer devel_generate' + +permission_callbacks: + - \Drupal\devel_generate\DevelGeneratePermissions::permissions diff --git a/web/modules/contrib/devel/devel_generate/devel_generate.routing.yml b/web/modules/contrib/devel/devel_generate/devel_generate.routing.yml new file mode 100644 index 00000000..fe3199f1 --- /dev/null +++ b/web/modules/contrib/devel/devel_generate/devel_generate.routing.yml @@ -0,0 +1,2 @@ +route_callbacks: + - '\Drupal\devel_generate\Routing\DevelGenerateRoutes::routes' diff --git a/web/modules/contrib/devel/devel_generate/devel_generate.services.yml b/web/modules/contrib/devel/devel_generate/devel_generate.services.yml new file mode 100644 index 00000000..16025e1d --- /dev/null +++ b/web/modules/contrib/devel/devel_generate/devel_generate.services.yml @@ -0,0 +1,4 @@ +services: + plugin.manager.develgenerate: + class: Drupal\devel_generate\DevelGeneratePluginManager + parent: default_plugin_manager diff --git a/web/modules/contrib/devel/devel_generate/drush.services.yml b/web/modules/contrib/devel/devel_generate/drush.services.yml new file mode 100644 index 00000000..11c8e9ca --- /dev/null +++ b/web/modules/contrib/devel/devel_generate/drush.services.yml @@ -0,0 +1,6 @@ +services: + develgenerate.commands: + class: Drupal\devel_generate\Commands\DevelGenerateCommands + arguments: ['@plugin.manager.develgenerate'] + tags: + - { name: drush.command } diff --git a/web/modules/contrib/devel/devel_generate/src/Annotation/DevelGenerate.php b/web/modules/contrib/devel/devel_generate/src/Annotation/DevelGenerate.php new file mode 100644 index 00000000..ddc5ff27 --- /dev/null +++ b/web/modules/contrib/devel/devel_generate/src/Annotation/DevelGenerate.php @@ -0,0 +1,85 @@ +setManager($manager); + } + + /** + * Get the DevelGenerate plugin manager. + * + * @return \Drupal\devel_generate\DevelGeneratePluginManager + * The DevelGenerate plugin manager. + */ + public function getManager() { + return $this->manager; + } + + /** + * Set the DevelGenerate plugin manager. + * + * @param \Drupal\devel_generate\DevelGeneratePluginManager $manager + * The DevelGenerate plugin manager. + */ + public function setManager(DevelGeneratePluginManager $manager) { + $this->manager = $manager; + } + + /** + * Get the DevelGenerate plugin instance. + * + * @return mixed + * The DevelGenerate plugin instance. + */ + public function getPluginInstance() { + return $this->pluginInstance; + } + + /** + * Set the DevelGenerate plugin instance. + * + * @param mixed $pluginInstance + * The DevelGenerate plugin instance. + */ + public function setPluginInstance($pluginInstance) { + $this->pluginInstance = $pluginInstance; + } + + /** + * Get the DevelGenerate plugin parameters. + * + * @return array + * The plugin parameters. + */ + public function getParameters() { + return $this->parameters; + } + + /** + * Set the DevelGenerate plugin parameters. + * + * @param array $parameters + * The plugin parameters. + */ + public function setParameters(array $parameters) { + $this->parameters = $parameters; + } + + /** + * Create users. + * + * @command devel-generate:users + * @aliases genu, devel-generate-users + * @pluginId user + * + * @param int $num + * Number of users to generate. + * @param array $options + * Array of options as described below. + * + * @option kill Delete all users before generating new ones. + * @option roles A comma delimited list of role IDs for new users. Don't specify 'authenticated'. + * @option pass Specify a password to be set for all generated users. + */ + public function users($num = 50, array $options = ['kill' => FALSE, 'roles' => '']) { + // @todo pass $options to the plugins. + $this->generate(); + } + + /** + * Create terms in specified vocabulary. + * + * @command devel-generate:terms + * @aliases gent, devel-generate-terms + * @pluginId term + * + * @param int $num + * Number of terms to generate. + * @param array $options + * Array of options as described below. + * + * @option kill Delete all terms in these vocabularies before generating new ones. + * @option bundles A comma-delimited list of machine names for the vocabularies where terms will be created. + * @option feedback An integer representing interval for insertion rate logging. + * @option languages A comma-separated list of language codes + * @option translations A comma-separated list of language codes for translations. + * @option min-depth The minimum depth of hierarchy for the new terms. + * @option max-depth The maximum depth of hierarchy for the new terms. + */ + public function terms($num = 50, array $options = ['kill' => FALSE, 'bundles' => NULL, 'feedback' => '1000', 'languages' => NULL, 'translations' => NULL, 'min-depth' => '1', 'max-depth' => '4']) { + $this->generate(); + } + + /** + * Create vocabularies. + * + * @command devel-generate:vocabs + * @aliases genv, devel-generate-vocabs + * @pluginId vocabulary + * @validate-module-enabled taxonomy + * + * @param int $num + * Number of vocabularies to generate. + * @param array $options + * Array of options as described below. + * + * @option kill Delete all vocabs before generating new ones. + */ + public function vocabs($num = 1, array $options = ['kill' => FALSE]) { + $this->generate(); + } + + /** + * Create menus. + * + * @command devel-generate:menus + * @aliases genm, devel-generate-menus + * @pluginId menu + * @validate-module-enabled menu_link_content + * + * @param int $number_menus + * Number of menus to generate. + * @param int $number_links + * Number of links to generate. + * @param int $max_depth + * Max link depth. + * @param int $max_width + * Max width of first level of links. + * @param array $options + * Array of options as described below. + * + * @option kill Delete any menus and menu links previously created by devel_generate before generating new ones. + */ + public function menus($number_menus = 2, $number_links = 50, $max_depth = 3, $max_width = 8, array $options = ['kill' => FALSE]) { + $this->generate(); + } + + /** + * Create content. + * + * @command devel-generate:content + * @aliases genc, devel-generate-content + * @pluginId content + * @validate-module-enabled node + * + * @param int $num + * Number of nodes to generate. + * @param int $max_comments + * Maximum number of comments to generate. + * @param array $options + * Array of options as described below. + * + * @option kill Delete all content before generating new content. + * @option bundles A comma-delimited list of content types to create. + * @option authors A comma delimited list of authors ids. Defaults to all users. + * @option feedback An integer representing interval for insertion rate logging. + * @option skip-fields A comma delimited list of fields to omit when generating random values + * @option languages A comma-separated list of language codes + * @option translations A comma-separated list of language codes for translations. + * @option add-type-label Add the content type label to the front of the node title + */ + public function content($num = 50, $max_comments = 0, array $options = ['kill' => FALSE, 'bundles' => 'page,article', 'authors' => NULL, 'feedback' => 1000, 'languages' => NULL, 'translations' => NULL, 'add-type-label' => FALSE]) { + $this->generate(); + } + + /** + * Create media items. + * + * @command devel-generate:media + * @aliases genmd, devel-generate-media + * @pluginId media + * @validate-module-enabled media + * + * @param int $num + * Number of media items to generate. + * @param array $options + * Array of options as described below. + * + * @option kill Delete all media items before generating new media. + * @option media-types A comma-delimited list of media types to create. + * @option feedback An integer representing interval for insertion rate logging. + * @option skip-fields A comma delimited list of fields to omit when generating random values. + * @option languages A comma-separated list of language codes + */ + public function media($num = 50, array $options = ['kill' => FALSE, 'media-types' => NULL, 'feedback' => 1000]) { + $this->generate(); + } + + /** + * The standard drush validate hook. + * + * @hook validate + * + * @param \Consolidation\AnnotatedCommand\CommandData $commandData + * The data sent from the drush command. + */ + public function validate(CommandData $commandData) { + $manager = $this->getManager(); + $args = $commandData->input()->getArguments(); + // The command name is the first argument but we do not need this. + array_shift($args); + /* @var DevelGenerateBaseInterface $instance */ + $instance = $manager->createInstance($commandData->annotationData()->get('pluginId'), []); + $this->setPluginInstance($instance); + $parameters = $instance->validateDrushParams($args, $commandData->input()->getOptions()); + $this->setParameters($parameters); + } + + /** + * Wrapper for calling the plugin instance generate function. + */ + public function generate() { + $instance = $this->getPluginInstance(); + $instance->generate($this->getParameters()); + } + +} diff --git a/web/modules/contrib/devel/devel_generate/src/DevelGenerateBase.php b/web/modules/contrib/devel/devel_generate/src/DevelGenerateBase.php new file mode 100644 index 00000000..30087bc2 --- /dev/null +++ b/web/modules/contrib/devel/devel_generate/src/DevelGenerateBase.php @@ -0,0 +1,307 @@ +settings)) { + $this->settings = $this->getDefaultSettings(); + } + return isset($this->settings[$key]) ? $this->settings[$key] : NULL; + } + + /** + * {@inheritdoc} + */ + public function getDefaultSettings() { + $definition = $this->getPluginDefinition(); + return $definition['settings']; + } + + /** + * {@inheritdoc} + */ + public function getSettings() { + return $this->settings; + } + + /** + * {@inheritdoc} + */ + public function settingsForm(array $form, FormStateInterface $form_state) { + return []; + } + + /** + * {@inheritdoc} + */ + public function settingsFormValidate(array $form, FormStateInterface $form_state) { + // Validation is optional. + } + + /** + * {@inheritdoc} + */ + public function generate(array $values) { + $this->generateElements($values); + $this->setMessage('Generate process complete.'); + } + + /** + * Business logic relating with each DevelGenerate plugin. + * + * @param array $values + * The input values from the settings form. + */ + protected function generateElements(array $values) { + + } + + /** + * Populate the fields on a given entity with sample values. + * + * @param \Drupal\Core\Entity\EntityInterface $entity + * The entity to be enriched with sample field values. + * + * @throws \Drupal\Component\Plugin\Exception\InvalidPluginDefinitionException + * @throws \Drupal\Component\Plugin\Exception\PluginNotFoundException + */ + public static function populateFields(EntityInterface $entity) { + $properties = [ + 'entity_type' => $entity->getEntityType()->id(), + 'bundle' => $entity->bundle(), + ]; + $field_config_storage = \Drupal::entityTypeManager()->getStorage('field_config'); + /* @var \Drupal\field\FieldConfigInterface[] $instances */ + $instances = $field_config_storage->loadByProperties($properties); + + // @todo not implemented for Drush9+. Possibly remove. + if ($skips = @$_REQUEST['skip-fields']) { + foreach (explode(',', $skips) as $skip) { + unset($instances[$skip]); + } + } + + foreach ($instances as $instance) { + $field_storage = $instance->getFieldStorageDefinition(); + $max = $cardinality = $field_storage->getCardinality(); + if ($cardinality == FieldStorageDefinitionInterface::CARDINALITY_UNLIMITED) { + // Just an arbitrary number for 'unlimited'. + $max = rand(1, 3); + } + $field_name = $field_storage->getName(); + $entity->$field_name->generateSampleItems($max); + } + } + + /** + * {@inheritdoc} + */ + public function handleDrushParams($args) { + + } + + /** + * Set a message for either drush or the web interface. + * + * @param string $msg + * The message to display. + * @param string $type + * (optional) The message type, as defined in MessengerInterface. Defaults + * to MessengerInterface::TYPE_STATUS. + */ + protected function setMessage($msg, $type = MessengerInterface::TYPE_STATUS) { + if (function_exists('drush_log')) { + $msg = strip_tags($msg); + drush_log($msg); + } + else { + \Drupal::messenger()->addMessage($msg, $type); + } + } + + /** + * Check if a given param is a number. + * + * @param mixed $number + * The parameter to check. + * + * @return bool + * TRUE if the parameter is a number, FALSE otherwise. + */ + public static function isNumber($number) { + if ($number == NULL) { + return FALSE; + } + if (!is_numeric($number)) { + return FALSE; + } + return TRUE; + } + + /** + * Gets the entity type manager service. + * + * @return \Drupal\Core\Entity\EntityTypeManagerInterface + * The entity type manager service. + */ + protected function getEntityTypeManager() { + if (!$this->entityTypeManager) { + $this->entityTypeManager = \Drupal::entityTypeManager(); + } + return $this->entityTypeManager; + } + + /** + * Returns the random data generator. + * + * @return \Drupal\Component\Utility\Random + * The random data generator. + */ + protected function getRandom() { + if (!$this->random) { + $this->random = new Random(); + } + return $this->random; + } + + /** + * Generates a random sentence of specific length. + * + * Words are randomly selected with length from 2 up to the optional parameter + * $max_word_length. The first word is capitalised. No ending period is added. + * + * @param int $sentence_length + * The total length of the sentence, including the word-separating spaces. + * @param int $max_word_length + * (optional) Maximum length of each word. Defaults to 8. + * + * @return string + * A sentence of the required length. + */ + protected function randomSentenceOfLength($sentence_length, $max_word_length = 8) { + // Maximum word length cannot be longer than the sentence length. + $max_word_length = min($sentence_length, $max_word_length); + $words = []; + $remainder = $sentence_length; + do { + if ($remainder <= $max_word_length) { + // If near enough to the end then generate the exact length word to fit. + $next_word = $remainder; + } + else { + // Cannot fill the remaining space with one word, so choose a random + // length, short enough for a following word of at least minimum length. + $next_word = mt_rand(2, min($max_word_length, $remainder - 3)); + } + $words[] = $this->getRandom()->word($next_word); + $remainder = $remainder - $next_word - 1; + } while ($remainder > 0); + $sentence = ucfirst(implode(' ', $words)); + return $sentence; + } + + /** + * Creates the language and translation section of the form. + * + * This is used by both Content and Term generation. + * + * @param string $items + * The name of the things that are being generated - 'nodes' or 'terms'. + * + * @return array + * The language details section of the form. + */ + protected function getLanguageForm($items) { + // We always need a language, even if the language module is not installed. + $options = []; + $languages = $this->languageManager->getLanguages(LanguageInterface::STATE_CONFIGURABLE); + foreach ($languages as $langcode => $language) { + $options[$langcode] = $language->getName(); + } + + $language_module_exists = $this->moduleHandler->moduleExists('language'); + $translation_module_exists = $this->moduleHandler->moduleExists('content_translation'); + + $form['language'] = [ + '#type' => 'details', + '#title' => $this->t('Language'), + '#open' => $language_module_exists, + ]; + $form['language']['add_language'] = [ + '#type' => 'select', + '#title' => $this->t('Select the primary language(s) for @items', ['@items' => $items]), + '#multiple' => TRUE, + '#description' => $language_module_exists ? '' : $this->t('Disabled - requires Language module'), + '#options' => $options, + '#default_value' => [ + $this->languageManager->getDefaultLanguage()->getId(), + ], + '#disabled' => !$language_module_exists, + ]; + $form['language']['translate_language'] = [ + '#type' => 'select', + '#title' => $this->t('Select the language(s) for translated @items', ['@items' => $items]), + '#multiple' => TRUE, + '#description' => $translation_module_exists ? $this->t('Translated @items will be created for each language selected.', ['@items' => $items]) : $this->t('Disabled - requires Content Translation module.'), + '#options' => $options, + '#disabled' => !$translation_module_exists, + ]; + return $form; + } + + /** + * Return a language code. + * + * @param array $add_language + * Optional array of language codes from which to select one at random. + * If empty then return the site's default language. + * + * @return string + * The language code to use. + */ + protected function getLangcode(array $add_language) { + if (empty($add_language)) { + return $this->languageManager->getDefaultLanguage()->getId(); + } + return $add_language[array_rand($add_language)]; + } + +} diff --git a/web/modules/contrib/devel/devel_generate/src/DevelGenerateBaseInterface.php b/web/modules/contrib/devel/devel_generate/src/DevelGenerateBaseInterface.php new file mode 100644 index 00000000..2cd54e73 --- /dev/null +++ b/web/modules/contrib/devel/devel_generate/src/DevelGenerateBaseInterface.php @@ -0,0 +1,83 @@ +develGeneratePluginManager = $develGeneratePluginManager; + } + + /** + * {@inheritdoc} + */ + public static function create(ContainerInterface $container) { + return new static($container->get('plugin.manager.develgenerate')); + } + + /** + * A permissions callback. + * + * @see devel_generate.permissions.yml + * + * @return array + * An array of permissions for all plugins. + */ + public function permissions() { + $devel_generate_plugins = $this->develGeneratePluginManager->getDefinitions(); + foreach ($devel_generate_plugins as $plugin) { + + $permission = $plugin['permission']; + $permissions[$permission] = [ + 'title' => $this->t('@permission', ['@permission' => $permission]), + ]; + } + + return $permissions; + } + +} diff --git a/web/modules/contrib/devel/devel_generate/src/DevelGeneratePluginManager.php b/web/modules/contrib/devel/devel_generate/src/DevelGeneratePluginManager.php new file mode 100644 index 00000000..a068f09d --- /dev/null +++ b/web/modules/contrib/devel/devel_generate/src/DevelGeneratePluginManager.php @@ -0,0 +1,53 @@ +alterInfo('devel_generate_info'); + $this->setCacheBackend($cache_backend, 'devel_generate_plugins'); + } + + /** + * {@inheritdoc} + */ + protected function findDefinitions() { + $definitions = []; + foreach (parent::findDefinitions() as $plugin_id => $plugin_definition) { + $plugin_available = TRUE; + foreach ($plugin_definition['dependencies'] as $module_name) { + // If a plugin defines module dependencies and at least one module is + // not installed don't make this plugin available. + if (!$this->moduleHandler->moduleExists($module_name)) { + $plugin_available = FALSE; + break; + } + } + if ($plugin_available) { + $definitions[$plugin_id] = $plugin_definition; + } + } + return $definitions; + } + +} diff --git a/web/modules/contrib/devel/devel_generate/src/Form/DevelGenerateForm.php b/web/modules/contrib/devel/devel_generate/src/Form/DevelGenerateForm.php new file mode 100644 index 00000000..0a16fff6 --- /dev/null +++ b/web/modules/contrib/devel/devel_generate/src/Form/DevelGenerateForm.php @@ -0,0 +1,113 @@ +develGenerateManager = $devel_generate_manager; + } + + /** + * {@inheritdoc} + */ + public static function create(ContainerInterface $container) { + return new static( + $container->get('plugin.manager.develgenerate') + ); + } + + /** + * {@inheritdoc} + */ + public function getFormId() { + return 'devel_generate_form_' . $this->getPluginIdFromRequest(); + } + + /** + * Returns the value of the param _plugin_id for the current request. + * + * @see \Drupal\devel_generate\Routing\DevelGenerateRouteSubscriber + */ + protected function getPluginIdFromRequest() { + $request = $this->getRequest(); + return $request->get('_plugin_id'); + } + + /** + * Returns a DevelGenerate plugin instance for a given plugin id. + * + * @param string $plugin_id + * The plugin_id for the plugin instance. + * + * @return \Drupal\devel_generate\DevelGenerateBaseInterface + * A DevelGenerate plugin instance. + */ + public function getPluginInstance($plugin_id) { + $instance = $this->develGenerateManager->createInstance($plugin_id, []); + return $instance; + } + + /** + * {@inheritdoc} + */ + public function buildForm(array $form, FormStateInterface $form_state) { + $plugin_id = $this->getPluginIdFromRequest(); + $instance = $this->getPluginInstance($plugin_id); + $form = $instance->settingsForm($form, $form_state); + $form['actions'] = ['#type' => 'actions']; + $form['actions']['submit'] = [ + '#type' => 'submit', + '#value' => $this->t('Generate'), + '#button_type' => 'primary', + ]; + + return $form; + } + + /** + * {@inheritdoc} + */ + public function validateForm(array &$form, FormStateInterface $form_state) { + $plugin_id = $this->getPluginIdFromRequest(); + $instance = $this->getPluginInstance($plugin_id); + $instance->settingsFormValidate($form, $form_state); + } + + /** + * {@inheritdoc} + */ + public function submitForm(array &$form, FormStateInterface $form_state) { + try { + $plugin_id = $this->getPluginIdFromRequest(); + $instance = $this->getPluginInstance($plugin_id); + $instance->generate($form_state->getValues()); + } + catch (\Exception $e) { + $this->logger('DevelGenerate', $this->t('Failed to generate elements due to "%error".', ['%error' => $e->getMessage()])); + $this->messenger()->addMessage($this->t('Failed to generate elements due to "%error".', ['%error' => $e->getMessage()])); + } + } + +} diff --git a/web/modules/contrib/devel/devel_generate/src/Plugin/DevelGenerate/ContentDevelGenerate.php b/web/modules/contrib/devel/devel_generate/src/Plugin/DevelGenerate/ContentDevelGenerate.php new file mode 100644 index 00000000..d22d70f6 --- /dev/null +++ b/web/modules/contrib/devel/devel_generate/src/Plugin/DevelGenerate/ContentDevelGenerate.php @@ -0,0 +1,728 @@ +moduleHandler = $module_handler; + $this->nodeStorage = $node_storage; + $this->nodeTypeStorage = $node_type_storage; + $this->userStorage = $user_storage; + $this->commentManager = $comment_manager; + $this->languageManager = $language_manager; + $this->contentTranslationManager = $content_translation_manager; + $this->urlGenerator = $url_generator; + $this->aliasStorage = $alias_storage; + $this->dateFormatter = $date_formatter; + $this->time = $time; + $this->database = $database; + } + + /** + * {@inheritdoc} + */ + public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) { + $entity_type_manager = $container->get('entity_type.manager'); + return new static( + $configuration, $plugin_id, $plugin_definition, + $entity_type_manager->getStorage('node'), + $entity_type_manager->getStorage('node_type'), + $entity_type_manager->getStorage('user'), + $container->get('module_handler'), + $container->has('comment.manager') ? $container->get('comment.manager') : NULL, + $container->get('language_manager'), + $container->has('content_translation.manager') ? $container->get('content_translation.manager') : NULL, + $container->get('url_generator'), + $entity_type_manager->getStorage('path_alias'), + $container->get('date.formatter'), + $container->get('datetime.time'), + $container->get('database') + ); + } + + /** + * {@inheritdoc} + */ + public function settingsForm(array $form, FormStateInterface $form_state) { + $types = $this->nodeTypeStorage->loadMultiple(); + + if (empty($types)) { + $create_url = $this->urlGenerator->generateFromRoute('node.type_add'); + $this->setMessage($this->t('You do not have any content types that can be generated. Go create a new content type', [':create-type' => $create_url]), 'error', FALSE); + return; + } + + $options = []; + + foreach ($types as $type) { + $options[$type->id()] = [ + 'type' => ['#markup' => $type->label()], + ]; + if ($this->commentManager) { + $comment_fields = $this->commentManager->getFields('node'); + $map = [$this->t('Hidden'), $this->t('Closed'), $this->t('Open')]; + + $fields = []; + foreach ($comment_fields as $field_name => $info) { + // Find all comment fields for the bundle. + if (in_array($type->id(), $info['bundles'])) { + $instance = FieldConfig::loadByName('node', $type->id(), $field_name); + $default_value = $instance->getDefaultValueLiteral(); + $default_mode = reset($default_value); + $fields[] = new FormattableMarkup('@field: @state', [ + '@field' => $instance->label(), + '@state' => $map[$default_mode['status']], + ]); + } + } + // @todo Refactor display of comment fields. + if (!empty($fields)) { + $options[$type->id()]['comments'] = [ + 'data' => [ + '#theme' => 'item_list', + '#items' => $fields, + ], + ]; + } + else { + $options[$type->id()]['comments'] = $this->t('No comment fields'); + } + } + } + + $header = [ + 'type' => $this->t('Content type'), + ]; + if ($this->commentManager) { + $header['comments'] = [ + 'data' => $this->t('Comments'), + 'class' => [RESPONSIVE_PRIORITY_MEDIUM], + ]; + } + + $form['node_types'] = [ + '#type' => 'tableselect', + '#header' => $header, + '#options' => $options, + ]; + + $form['kill'] = [ + '#type' => 'checkbox', + '#title' => $this->t('Delete all content in these content types before generating new content.'), + '#default_value' => $this->getSetting('kill'), + ]; + $form['num'] = [ + '#type' => 'number', + '#title' => $this->t('How many nodes would you like to generate?'), + '#default_value' => $this->getSetting('num'), + '#required' => TRUE, + '#min' => 0, + ]; + + $options = [1 => $this->t('Now')]; + foreach ([3600, 86400, 604800, 2592000, 31536000] as $interval) { + $options[$interval] = $this->dateFormatter->formatInterval($interval, 1) . ' ' . $this->t('ago'); + } + $form['time_range'] = [ + '#type' => 'select', + '#title' => $this->t('How far back in time should the nodes be dated?'), + '#description' => $this->t('Node creation dates will be distributed randomly from the current time, back to the selected time.'), + '#options' => $options, + '#default_value' => 604800, + ]; + + $form['max_comments'] = [ + '#type' => $this->moduleHandler->moduleExists('comment') ? 'number' : 'value', + '#title' => $this->t('Maximum number of comments per node.'), + '#description' => $this->t('You must also enable comments for the content types you are generating. Note that some nodes will randomly receive zero comments. Some will receive the max.'), + '#default_value' => $this->getSetting('max_comments'), + '#min' => 0, + '#access' => $this->moduleHandler->moduleExists('comment'), + ]; + $form['title_length'] = [ + '#type' => 'number', + '#title' => $this->t('Maximum number of words in titles'), + '#default_value' => $this->getSetting('title_length'), + '#required' => TRUE, + '#min' => 1, + '#max' => 255, + ]; + $form['add_type_label'] = [ + '#type' => 'checkbox', + '#title' => $this->t('Prefix the title with the content type label.'), + '#description' => $this->t('This will not count against the maximum number of title words specified above.'), + '#default_value' => $this->getSetting('add_type_label'), + ]; + $form['add_alias'] = [ + '#type' => 'checkbox', + '#disabled' => !$this->moduleHandler->moduleExists('path'), + '#description' => $this->t('Requires path.module'), + '#title' => $this->t('Add an url alias for each node.'), + '#default_value' => FALSE, + ]; + $form['add_statistics'] = [ + '#type' => 'checkbox', + '#title' => $this->t('Add statistics for each node (node_counter table).'), + '#default_value' => TRUE, + '#access' => $this->moduleHandler->moduleExists('statistics'), + ]; + + // Add the language and translation options. + $form += $this->getLanguageForm('nodes'); + + // Add the user selection checkboxes. + $author_header = [ + 'id' => $this->t('User ID'), + 'user' => $this->t('Name'), + 'role' => $this->t('Role(s)'), + ]; + + $author_rows = []; + /** @var \Drupal\user\UserInterface $user */ + foreach ($this->userStorage->loadMultiple() as $user) { + $author_rows[$user->id()] = [ + 'id' => ['#markup' => $user->id()], + 'user' => ['#markup' => $user->getAccountName()], + 'role' => ['#markup' => implode(", ", $user->getRoles())], + ]; + } + + $form['authors-wrap'] = [ + '#type' => 'details', + '#title' => $this->t('Users'), + '#open' => FALSE, + '#description' => $this->t('Select users for randomly assigning as authors of the generated content. Leave all unchecked to use a random selection of up to 50 users.'), + ]; + + $form['authors-wrap']['authors'] = [ + '#type' => 'tableselect', + '#header' => $author_header, + '#options' => $author_rows, + ]; + + $form['#redirect'] = FALSE; + + return $form; + } + + /** + * {@inheritdoc} + */ + public function settingsFormValidate(array $form, FormStateInterface $form_state) { + if (!array_filter($form_state->getValue('node_types'))) { + $form_state->setErrorByName('node_types', $this->t('Please select at least one content type')); + } + } + + /** + * {@inheritdoc} + */ + protected function generateElements(array $values) { + if ($this->isBatch($values['num'], $values['max_comments'])) { + $this->generateBatchContent($values); + } + else { + $this->generateContent($values); + } + } + + /** + * Generate content when not in batch mode. + * + * This method is used when the number of elements is under 50. + */ + private function generateContent($values) { + $values['node_types'] = array_filter($values['node_types']); + if (!empty($values['kill']) && $values['node_types']) { + $this->contentKill($values); + } + + if (!empty($values['node_types'])) { + // Generate nodes. + $this->develGenerateContentPreNode($values); + $start = time(); + $values['num_translations'] = 0; + for ($i = 1; $i <= $values['num']; $i++) { + $this->develGenerateContentAddNode($values); + if (isset($values['feedback']) && $i % $values['feedback'] == 0) { + $now = time(); + $options = [ + '@feedback' => $values['feedback'], + '@rate' => ($values['feedback'] * 60) / ($now - $start), + ]; + $this->messenger()->addStatus(dt('Completed @feedback nodes (@rate nodes/min)', $options)); + $start = $now; + } + } + } + $this->setMessage($this->formatPlural($values['num'], 'Created 1 node', 'Created @count nodes')); + if ($values['num_translations'] > 0) { + $this->setMessage($this->formatPlural($values['num_translations'], 'Created 1 node translation', 'Created @count node translations')); + } + } + + /** + * Generate content in batch mode. + * + * This method is used when the number of elements is 50 or more. + */ + private function generateBatchContent($values) { + // Remove unselected node types. + $values['node_types'] = array_filter($values['node_types']); + // If it is drushBatch then this operation is already run in the + // self::validateDrushParams(). + if (!$this->drushBatch) { + // Setup the batch operations and save the variables. + $operations[] = ['devel_generate_operation', + [$this, 'batchContentPreNode', $values], + ]; + } + + // Add the kill operation. + if ($values['kill']) { + $operations[] = ['devel_generate_operation', + [$this, 'batchContentKill', $values], + ]; + } + + // Add the operations to create the nodes. + for ($num = 0; $num < $values['num']; $num++) { + $operations[] = ['devel_generate_operation', + [$this, 'batchContentAddNode', $values], + ]; + } + + // Set the batch. + $batch = [ + 'title' => $this->t('Generating Content'), + 'operations' => $operations, + 'finished' => 'devel_generate_batch_finished', + 'file' => drupal_get_path('module', 'devel_generate') . '/devel_generate.batch.inc', + ]; + + batch_set($batch); + if ($this->drushBatch) { + drush_backend_batch_process(); + } + } + + /** + * Batch wrapper for calling ContentPreNode. + */ + public function batchContentPreNode($vars, &$context) { + $context['results'] = $vars; + $context['results']['num'] = 0; + $context['results']['num_translations'] = 0; + $this->develGenerateContentPreNode($context['results']); + } + + /** + * Batch wrapper for calling ContentAddNode. + */ + public function batchContentAddNode($vars, &$context) { + if ($this->drushBatch) { + $this->develGenerateContentAddNode($vars); + } + else { + $this->develGenerateContentAddNode($context['results']); + } + $context['results']['num']++; + if (!empty($vars['num_translations'])) { + $context['results']['num_translations'] += $vars['num_translations']; + } + } + + /** + * Batch wrapper for calling ContentKill. + */ + public function batchContentKill($vars, &$context) { + if ($this->drushBatch) { + $this->contentKill($vars); + } + else { + $this->contentKill($context['results']); + } + } + + /** + * {@inheritdoc} + */ + public function validateDrushParams(array $args, array $options = []) { + $add_language = StringUtils::csvToArray($options['languages']); + // Intersect with the enabled languages to make sure the language args + // passed are actually enabled. + $valid_languages = array_keys($this->languageManager->getLanguages(LanguageInterface::STATE_ALL)); + $values['add_language'] = array_intersect($add_language, $valid_languages); + + $translate_language = StringUtils::csvToArray($options['translations']); + $values['translate_language'] = array_intersect($translate_language, $valid_languages); + + $values['add_type_label'] = $options['add-type-label']; + $values['kill'] = $options['kill']; + $values['feedback'] = $options['feedback']; + $values['title_length'] = 6; + $values['num'] = array_shift($args); + $values['max_comments'] = array_shift($args); + $all_types = array_keys(node_type_get_names()); + $default_types = array_intersect(['page', 'article'], $all_types); + $selected_types = StringUtils::csvToArray($options['bundles'] ?: $default_types); + + if (empty($selected_types)) { + throw new \Exception(dt('No content types available')); + } + + $values['node_types'] = array_combine($selected_types, $selected_types); + $node_types = array_filter($values['node_types']); + + if (!empty($values['kill']) && empty($node_types)) { + throw new \Exception(dt('To delete content, please provide the content types (--bundles)')); + } + + // Checks for any missing content types before generating nodes. + if (array_diff($node_types, $all_types)) { + throw new \Exception(dt('One or more content types have been entered that don\'t exist on this site')); + } + + $values['authors'] = is_null($options['authors']) ? [] : explode(',', + $options['authors']); + + if ($this->isBatch($values['num'], $values['max_comments'])) { + $this->drushBatch = TRUE; + $this->develGenerateContentPreNode($values); + } + + return $values; + } + + /** + * Determines if the content should be generated in batch mode. + */ + protected function isBatch($content_count, $comment_count) { + return $content_count >= 50 || $comment_count >= 10; + } + + /** + * Deletes all nodes of given node types. + * + * @param array $values + * The input values from the settings form. + */ + protected function contentKill(array $values) { + $nids = $this->nodeStorage->getQuery() + ->condition('type', $values['node_types'], 'IN') + ->execute(); + + if (!empty($nids)) { + $nodes = $this->nodeStorage->loadMultiple($nids); + $this->nodeStorage->delete($nodes); + $this->setMessage($this->t('Deleted %count nodes.', ['%count' => count($nids)])); + } + } + + /** + * Preprocesses $results before adding content. + * + * @param array $results + * Results information. + */ + protected function develGenerateContentPreNode(array &$results) { + $authors = $results['authors']; + // Remove non-selected users. !== 0 will leave the Anonymous user in if it + // was selected on the form or entered in the drush parameters. + $authors = array_filter($authors, function ($k) { + return $k !== 0; + }); + // If no users are specified then get a random set up to a maximum of 50. + // There is no direct way randomise the selection using entity queries, so + // we use a database query instead. + if (empty($authors)) { + $query = $this->database->select('users', 'u') + ->fields('u', ['uid']) + ->range(0, 50) + ->orderRandom(); + $authors = $query->execute()->fetchCol(); + } + $results['users'] = $authors; + } + + /** + * Create one node. Used by both batch and non-batch code branches. + * + * @param array $results + * Results information. + */ + protected function develGenerateContentAddNode(array &$results) { + if (!isset($results['time_range'])) { + $results['time_range'] = 0; + } + $users = $results['users']; + + $node_type = array_rand($results['node_types']); + $uid = $users[array_rand($users)]; + + // Add the content type label if required. + $title_prefix = $results['add_type_label'] ? $this->nodeTypeStorage->load($node_type)->label() . ' - ' : ''; + + $values = [ + 'nid' => NULL, + 'type' => $node_type, + 'title' => $title_prefix . $this->getRandom()->sentences(mt_rand(1, $results['title_length']), TRUE), + 'uid' => $uid, + 'revision' => mt_rand(0, 1), + 'status' => TRUE, + 'promote' => mt_rand(0, 1), + 'created' => $this->time->getRequestTime() - mt_rand(0, $results['time_range']), + ]; + + if (isset($results['add_language'])) { + $values['langcode'] = $this->getLangcode($results['add_language']); + } + + $node = $this->nodeStorage->create($values); + + // A flag to let hook_node_insert() implementations know that this is a + // generated node. + $node->devel_generate = $results; + + // Populate all fields with sample values. + $this->populateFields($node); + + // See devel_generate_entity_insert() for actions that happen before and + // after this save. + $node->save(); + + // Add url alias if required. + if (!empty($results['add_alias'])) { + $path_alias = $this->aliasStorage->create([ + 'path' => '/node/' . $node->id(), + 'alias' => '/node-' . $node->id() . '-' . $node->bundle(), + 'langcode' => $values['langcode'] ?? LanguageInterface::LANGCODE_NOT_SPECIFIED, + ]); + $path_alias->save(); + } + + // Add translations. + if (isset($results['translate_language']) && !empty($results['translate_language'])) { + $this->develGenerateContentAddNodeTranslation($results, $node); + } + } + + /** + * Create translation for the given node. + * + * @param array $results + * Results array. + * @param \Drupal\node\NodeInterface $node + * Node to add translations to. + * + * @throws \Drupal\Core\Entity\EntityStorageException + */ + protected function develGenerateContentAddNodeTranslation(array &$results, NodeInterface $node) { + if (is_null($this->contentTranslationManager)) { + return; + } + if (!$this->contentTranslationManager->isEnabled('node', $node->getType())) { + return; + } + if ($node->langcode == LanguageInterface::LANGCODE_NOT_SPECIFIED || $node->langcode == LanguageInterface::LANGCODE_NOT_APPLICABLE) { + return; + } + + if (!isset($results['num_translations'])) { + $results['num_translations'] = 0; + } + // Translate node to each target language. + $skip_languages = [ + LanguageInterface::LANGCODE_NOT_SPECIFIED, + LanguageInterface::LANGCODE_NOT_APPLICABLE, + $node->langcode->value, + ]; + foreach ($results['translate_language'] as $langcode) { + if (in_array($langcode, $skip_languages)) { + continue; + } + $translation_node = $node->addTranslation($langcode); + $translation_node->devel_generate = $results; + $translation_node->setTitle($node->getTitle() . ' (' . $langcode . ')'); + $this->populateFields($translation_node); + $translation_node->save(); + if ($translation_node->id() > 0 && !empty($results['add_alias'])) { + $path_alias = $this->aliasStorage->create([ + 'path' => '/node/' . $translation_node->id(), + 'alias' => '/node-' . $translation_node->id() . '-' . $translation_node->bundle() . '-' . $langcode, + 'langcode' => $langcode, + ]); + $path_alias->save(); + } + $results['num_translations']++; + } + } + +} diff --git a/web/modules/contrib/devel/devel_generate/src/Plugin/DevelGenerate/MediaDevelGenerate.php b/web/modules/contrib/devel/devel_generate/src/Plugin/DevelGenerate/MediaDevelGenerate.php new file mode 100644 index 00000000..f4801daa --- /dev/null +++ b/web/modules/contrib/devel/devel_generate/src/Plugin/DevelGenerate/MediaDevelGenerate.php @@ -0,0 +1,547 @@ +mediaStorage = $entity_type_manager->getStorage('media'); + $this->mediaTypeStorage = $entity_type_manager->getStorage('media_type'); + $this->userStorage = $entity_type_manager->getStorage('user');; + $this->languageManager = $language_manager; + $this->urlGenerator = $url_generator; + $this->dateFormatter = $date_formatter; + $this->time = $time; + } + + /** + * {@inheritdoc} + */ + public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) { + return new static( + $configuration, $plugin_id, $plugin_definition, + $container->get('entity_type.manager'), + $container->get('language_manager'), + $container->get('url_generator'), + $container->get('date.formatter'), + $container->get('datetime.time') + ); + } + + /** + * {@inheritdoc} + */ + public function settingsForm(array $form, FormStateInterface $form_state) { + $types = $this->mediaTypeStorage->loadMultiple(); + + if (empty($types)) { + $create_url = $this->urlGenerator->generateFromRoute('entity.media_type.add_form'); + $this->setMessage($this->t('You do not have any media types that can be generated. Go create a new media type', [ + ':url' => $create_url, + ]), MessengerInterface::TYPE_ERROR); + return []; + } + + $options = []; + foreach ($types as $type) { + $options[$type->id()] = ['type' => ['#markup' => $type->label()]]; + } + + $form['media_types'] = [ + '#type' => 'tableselect', + '#header' => ['type' => $this->t('Media type')], + '#options' => $options, + ]; + + $form['kill'] = [ + '#type' => 'checkbox', + '#title' => $this->t('Delete all media in these types before generating new media.'), + '#default_value' => $this->getSetting('kill'), + ]; + $form['num'] = [ + '#type' => 'number', + '#title' => $this->t('How many media items would you like to generate?'), + '#default_value' => $this->getSetting('num'), + '#required' => TRUE, + '#min' => 0, + ]; + + $options = [1 => $this->t('Now')]; + foreach ([3600, 86400, 604800, 2592000, 31536000] as $interval) { + $options[$interval] = $this->dateFormatter->formatInterval($interval, 1) . ' ' . $this->t('ago'); + } + $form['time_range'] = [ + '#type' => 'select', + '#title' => $this->t('How far back in time should the media be dated?'), + '#description' => $this->t('Media creation dates will be distributed randomly from the current time, back to the selected time.'), + '#options' => $options, + '#default_value' => 604800, + ]; + + $form['name_length'] = [ + '#type' => 'number', + '#title' => $this->t('Maximum number of words in names'), + '#default_value' => $this->getSetting('name_length'), + '#required' => TRUE, + '#min' => 1, + '#max' => 255, + ]; + + $options = []; + // We always need a language. + $languages = $this->languageManager->getLanguages(LanguageInterface::STATE_ALL); + foreach ($languages as $langcode => $language) { + $options[$langcode] = $language->getName(); + } + + $form['add_language'] = [ + '#type' => 'select', + '#title' => $this->t('Set language on media'), + '#multiple' => TRUE, + '#description' => $this->t('Requires locale.module'), + '#options' => $options, + '#default_value' => [ + $this->languageManager->getDefaultLanguage()->getId(), + ], + ]; + + $form['#redirect'] = FALSE; + + return $form; + } + + /** + * {@inheritdoc} + */ + public function settingsFormValidate(array $form, FormStateInterface $form_state) { + // Remove the media types not selected. + $media_types = array_filter($form_state->getValue('media_types')); + if (!$media_types) { + $form_state->setErrorByName('media_types', $this->t('Please select at least one media type')); + } + // Store the normalized value back, in form state. + $form_state->setValue('media_types', array_combine($media_types, $media_types)); + } + + /** + * {@inheritdoc} + */ + protected function generateElements(array $values) { + if ($this->isBatch($values['num'])) { + $this->generateBatchMedia($values); + } + else { + $this->generateMedia($values); + } + } + + /** + * Method for creating media when number of elements is less than 50. + * + * @param array $values + * Array of values submitted through a form. + * + * @throws \Drupal\Component\Plugin\Exception\InvalidPluginDefinitionException + * Thrown if the storage handler couldn't be loaded. + * @throws \Drupal\Component\Plugin\Exception\PluginNotFoundException + * Thrown if the entity type doesn't exist. + * @throws \Drupal\Core\Entity\EntityStorageException + * Thrown if the bundle does not exist or was needed but not specified. + */ + protected function generateMedia(array $values) { + if (!empty($values['kill']) && $values['media_types']) { + $this->mediaKill($values); + } + + if (!empty($values['media_types'])) { + // Generate media items. + $this->preGenerate($values); + $start = time(); + for ($i = 1; $i <= $values['num']; $i++) { + $this->createMediaItem($values); + if (isset($values['feedback']) && $i % $values['feedback'] == 0) { + $now = time(); + $this->messenger()->addStatus(dt('Completed !feedback media items (!rate media/min)', [ + '!feedback' => $values['feedback'], + '!rate' => ($values['feedback'] * 60) / ($now - $start), + ])); + $start = $now; + } + } + } + $this->setMessage($this->formatPlural($values['num'], '1 media item created.', 'Finished creating @count media items.')); + } + + /** + * Method for creating media when number of elements is greater than 50. + * + * @param array $values + * The input values from the settings form. + */ + protected function generateBatchMedia(array $values) { + $operations = []; + + // Setup the batch operations and save the variables. + $operations[] = [ + 'devel_generate_operation', + [$this, 'batchPreGenerate', $values], + ]; + + // Add the kill operation. + if ($values['kill']) { + $operations[] = [ + 'devel_generate_operation', + [$this, 'batchMediaKill', $values], + ]; + } + + // Add the operations to create the media. + for ($num = 0; $num < $values['num']; $num++) { + $operations[] = [ + 'devel_generate_operation', + [$this, 'batchCreateMediaItem', $values], + ]; + } + + // Start the batch. + $batch = [ + 'title' => $this->t('Generating media items'), + 'operations' => $operations, + 'finished' => 'devel_generate_batch_finished', + 'file' => drupal_get_path('module', 'devel_generate') . '/devel_generate.batch.inc', + ]; + batch_set($batch); + + if ($this->drushBatch) { + drush_backend_batch_process(); + } + } + + /** + * Provides a batch version of preGenerate(). + * + * @param array $vars + * The input values from the settings form. + * @param iterable $context + * Batch job context. + * + * @see self::preGenerate() + */ + public function batchPreGenerate(array $vars, iterable &$context) { + $context['results'] = $vars; + $context['results']['num'] = 0; + $this->preGenerate($context['results']); + } + + /** + * Provides a batch version of createMediaItem(). + * + * @param array $vars + * The input values from the settings form. + * @param array $context + * Batch job context. + * + * @throws \Drupal\Component\Plugin\Exception\InvalidPluginDefinitionException + * Thrown if the storage handler couldn't be loaded. + * @throws \Drupal\Component\Plugin\Exception\PluginNotFoundException + * Thrown if the entity type doesn't exist. + * @throws \Drupal\Core\Entity\EntityStorageException + * Thrown if the bundle does not exist or was needed but not specified. + * + * @see self::createMediaItem() + */ + public function batchCreateMediaItem(array $vars, &$context) { + if ($this->drushBatch) { + $this->createMediaItem($vars); + } + else { + $this->createMediaItem($context['results']); + } + $context['results']['num']++; + } + + /** + * Provides a batch version of mediaKill(). + * + * @param array $vars + * The input values from the settings form. + * @param array $context + * Batch job context. + * + * @see self::mediaKill() + */ + public function batchMediaKill($vars, &$context) { + if ($this->drushBatch) { + $this->mediaKill($vars); + } + else { + $this->mediaKill($context['results']); + } + } + + /** + * {@inheritdoc} + */ + public function validateDrushParams(array $args, array $options = []) { + $add_language = $options['languages']; + if (!empty($add_language)) { + $add_language = explode(',', str_replace(' ', '', $add_language)); + // Intersect with the enabled languages to make sure the language args + // passed are actually enabled. + $values['values']['add_language'] = array_intersect($add_language, array_keys($this->languageManager->getLanguages(LanguageInterface::STATE_ALL))); + } + + $values['kill'] = $options['kill']; + $values['feedback'] = $options['feedback']; + $values['name_length'] = 6; + $values['num'] = array_shift($args); + + $all_media_types = array_values($this->mediaTypeStorage->getQuery()->execute()); + $requested_media_types = StringUtils::csvToArray($options['media-types'] ?: $all_media_types); + + if (empty($requested_media_types)) { + throw new \Exception(dt('No media types available')); + } + // Check for any missing media type. + if ($invalid_media_types = array_diff($requested_media_types, $all_media_types)) { + throw new \Exception("Requested media types don't exists: " . implode(', ', $invalid_media_types)); + } + + $values['media_types'] = array_combine($requested_media_types, $requested_media_types); + + if ($this->isBatch($values['num'])) { + $this->drushBatch = TRUE; + $this->preGenerate($values); + } + + return $values; + } + + /** + * Deletes all media of given media media types. + * + * @param array $values + * The input values from the settings form. + * + * @throws \Drupal\Core\Entity\EntityStorageException + * Thrown if the media type does not exist. + */ + protected function mediaKill(array $values) { + $mids = $this->mediaStorage->getQuery() + ->condition('bundle', $values['media_types'], 'IN') + ->execute(); + + if (!empty($mids)) { + $media = $this->mediaStorage->loadMultiple($mids); + $this->mediaStorage->delete($media); + $this->setMessage($this->t('Deleted %count media items.', ['%count' => count($mids)])); + } + } + + /** + * Code to be run before generating items. + * + * Returns the same array passed in as parameter, but with an array of uids + * for the key 'users'. + * + * @param array $results + * The input values from the settings form. + */ + protected function preGenerate(array &$results) { + // Get user id. + $users = array_values($this->userStorage->getQuery() + ->range(0, 50) + ->execute()); + $users = array_merge($users, ['0']); + $results['users'] = $users; + } + + /** + * Create one media item. Used by both batch and non-batch code branches. + * + * @param array $results + * The input values from the settings form. + * + * @throws \Drupal\Component\Plugin\Exception\InvalidPluginDefinitionException + * Thrown if the storage handler couldn't be loaded. + * @throws \Drupal\Component\Plugin\Exception\PluginNotFoundException + * Thrown if the entity type doesn't exist. + * @throws \Drupal\Core\Entity\EntityStorageException + * Thrown if the bundle does not exist or was needed but not specified. + */ + protected function createMediaItem(array &$results) { + if (!isset($results['time_range'])) { + $results['time_range'] = 0; + } + + $media_type = array_rand($results['media_types']); + $uid = $results['users'][array_rand($results['users'])]; + + $media = $this->mediaStorage->create([ + 'bundle' => $media_type, + 'name' => $this->getRandom()->sentences(mt_rand(1, $results['name_length']), TRUE), + 'uid' => $uid, + 'revision' => mt_rand(0, 1), + 'status' => TRUE, + 'created' => $this->time->getRequestTime() - mt_rand(0, $results['time_range']), + 'langcode' => $this->getLangcode($results), + ]); + + // A flag to let hook implementations know that this is a generated item. + $media->devel_generate = $results; + + // Populate all fields with sample values. + $this->populateFields($media); + + $media->save(); + } + + /** + * Determine language based on $results. + * + * @param array $results + * The input values from the settings form. + * + * @return string + * The language code. + */ + protected function getLangcode(array $results) { + if (isset($results['add_language'])) { + $langcodes = $results['add_language']; + $langcode = $langcodes[array_rand($langcodes)]; + } + else { + $langcode = $this->languageManager->getDefaultLanguage()->getId(); + } + return $langcode; + } + + /** + * Finds out if the media item generation will run in batch process. + * + * @param int $media_items_count + * Number of media items to be generated. + * + * @return bool + * If the process should be a batch process. + */ + protected function isBatch($media_items_count) { + return $media_items_count >= 50; + } + +} diff --git a/web/modules/contrib/devel/devel_generate/src/Plugin/DevelGenerate/MenuDevelGenerate.php b/web/modules/contrib/devel/devel_generate/src/Plugin/DevelGenerate/MenuDevelGenerate.php new file mode 100644 index 00000000..79a173a4 --- /dev/null +++ b/web/modules/contrib/devel/devel_generate/src/Plugin/DevelGenerate/MenuDevelGenerate.php @@ -0,0 +1,426 @@ +menuLinkTree = $menu_tree; + $this->menuStorage = $menu_storage; + $this->menuLinkContentStorage = $menu_link_storage; + $this->moduleHandler = $module_handler; + $this->database = $database; + } + + /** + * {@inheritdoc} + */ + public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) { + $entity_type_manager = $container->get('entity_type.manager'); + return new static( + $configuration, $plugin_id, $plugin_definition, + $container->get('menu.link_tree'), + $entity_type_manager->getStorage('menu'), + $entity_type_manager->getStorage('menu_link_content'), + $container->get('module_handler'), + $container->get('database') + ); + } + + /** + * {@inheritdoc} + */ + public function settingsForm(array $form, FormStateInterface $form_state) { + $menu_enabled = $this->moduleHandler->moduleExists('menu_ui'); + if ($menu_enabled) { + $menus = ['__new-menu__' => $this->t('Create new menu(s)')] + menu_ui_get_menus(); + } + else { + $menus = menu_list_system_menus(); + } + $form['existing_menus'] = [ + '#type' => 'checkboxes', + '#title' => $this->t('Generate links for these menus'), + '#options' => $menus, + '#default_value' => ['__new-menu__'], + '#required' => TRUE, + ]; + if ($menu_enabled) { + $form['num_menus'] = [ + '#type' => 'number', + '#title' => $this->t('Number of new menus to create'), + '#default_value' => $this->getSetting('num_menus'), + '#min' => 0, + '#states' => [ + 'visible' => [ + ':input[name="existing_menus[__new-menu__]"]' => ['checked' => TRUE], + ], + ], + ]; + } + $form['num_links'] = [ + '#type' => 'number', + '#title' => $this->t('Number of links to generate'), + '#default_value' => $this->getSetting('num_links'), + '#required' => TRUE, + '#min' => 0, + ]; + $form['title_length'] = [ + '#type' => 'number', + '#title' => $this->t('Maximum length for menu titles and menu links'), + '#description' => $this->t('Text will be generated at random lengths up to this value. Enter a number between 2 and 128.'), + '#default_value' => $this->getSetting('title_length'), + '#required' => TRUE, + '#min' => 2, + '#max' => 128, + ]; + $form['link_types'] = [ + '#type' => 'checkboxes', + '#title' => $this->t('Types of links to generate'), + '#options' => [ + 'node' => $this->t('Nodes'), + 'front' => $this->t('Front page'), + 'external' => $this->t('External'), + ], + '#default_value' => ['node', 'front', 'external'], + '#required' => TRUE, + ]; + $form['max_depth'] = [ + '#type' => 'select', + '#title' => $this->t('Maximum link depth'), + '#options' => range(0, $this->menuLinkTree->maxDepth()), + '#default_value' => floor($this->menuLinkTree->maxDepth() / 2), + '#required' => TRUE, + ]; + unset($form['max_depth']['#options'][0]); + $form['max_width'] = [ + '#type' => 'number', + '#title' => $this->t('Maximum menu width'), + '#default_value' => $this->getSetting('max_width'), + '#description' => $this->t("Limit the width of the generated menu's first level of links to a certain number of items."), + '#required' => TRUE, + '#min' => 0, + ]; + $form['kill'] = [ + '#type' => 'checkbox', + '#title' => $this->t('Delete existing custom generated menus and menu links before generating new ones.'), + '#default_value' => $this->getSetting('kill'), + ]; + + return $form; + } + + /** + * {@inheritdoc} + */ + public function generateElements(array $values) { + // If the create new menus checkbox is off, set the number of menus to 0. + if (!isset($values['existing_menus']['__new-menu__']) || !$values['existing_menus']['__new-menu__']) { + $values['num_menus'] = 0; + } + else { + // Unset the aux menu to avoid attach menu new items. + unset($values['existing_menus']['__new-menu__']); + } + + // Delete custom menus. + if ($values['kill']) { + list($menus_deleted, $links_deleted) = $this->deleteMenus(); + $this->setMessage($this->t('Deleted @menus_deleted menu(s) and @links_deleted other link(s).', + ['@menus_deleted' => $menus_deleted, '@links_deleted' => $links_deleted])); + } + + // Generate new menus. + $new_menus = $this->generateMenus($values['num_menus'], $values['title_length']); + if (!empty($new_menus)) { + $this->setMessage($this->formatPlural(count($new_menus), 'Created the following 1 new menu: @menus', 'Created the following @count new menus: @menus', + ['@menus' => implode(', ', $new_menus)])); + } + + // Generate new menu links. + $menus = $new_menus; + if (isset($values['existing_menus'])) { + $menus = $menus + $values['existing_menus']; + } + $new_links = $this->generateLinks($values['num_links'], $menus, $values['title_length'], $values['link_types'], $values['max_depth'], $values['max_width']); + $this->setMessage($this->formatPlural(count($new_links), 'Created 1 new menu link.', 'Created @count new menu links.')); + } + + /** + * {@inheritdoc} + */ + public function validateDrushParams(array $args, array $options = []) { + + $link_types = ['node', 'front', 'external']; + $values = [ + 'num_menus' => array_shift($args), + 'num_links' => array_shift($args), + 'kill' => $options['kill'], + 'pipe' => $options['pipe'], + 'link_types' => array_combine($link_types, $link_types), + ]; + + $max_depth = array_shift($args); + $max_width = array_shift($args); + $values['max_depth'] = $max_depth ? $max_depth : 3; + $values['max_width'] = $max_width ? $max_width : 8; + $values['title_length'] = $this->getSetting('title_length'); + $values['existing_menus']['__new-menu__'] = TRUE; + + if ($this->isNumber($values['num_menus']) == FALSE) { + throw new \Exception(dt('Invalid number of menus')); + } + if ($this->isNumber($values['num_links']) == FALSE) { + throw new \Exception(dt('Invalid number of links')); + } + if ($this->isNumber($values['max_depth']) == FALSE || $values['max_depth'] > 9 || $values['max_depth'] < 1) { + throw new \Exception(dt('Invalid maximum link depth. Use a value between 1 and 9')); + } + if ($this->isNumber($values['max_width']) == FALSE || $values['max_width'] < 1) { + throw new \Exception(dt('Invalid maximum menu width. Use a positive numeric value.')); + } + + return $values; + } + + /** + * Deletes custom generated menus. + */ + protected function deleteMenus() { + if ($this->moduleHandler->moduleExists('menu_ui')) { + $menu_ids = []; + foreach (menu_ui_get_menus(FALSE) as $menu => $menu_title) { + if (strpos($menu, 'devel-') === 0) { + $menu_ids[] = $menu; + } + } + + if ($menu_ids) { + $menus = $this->menuStorage->loadMultiple($menu_ids); + $this->menuStorage->delete($menus); + } + } + + // Delete menu links in other menus, but generated by devel. + $link_ids = $this->menuLinkContentStorage->getQuery() + ->condition('menu_name', 'devel', '<>') + ->condition('link__options', '%' . $this->database->escapeLike('s:5:"devel";b:1') . '%', 'LIKE') + ->execute(); + + if ($link_ids) { + $links = $this->menuLinkContentStorage->loadMultiple($link_ids); + $this->menuLinkContentStorage->delete($links); + } + + return [count($menu_ids), count($link_ids)]; + + } + + /** + * Generates new menus. + * + * @param int $num_menus + * Number of menus to create. + * @param int $title_length + * (optional) Maximum length of menu name. + * + * @return array + * Array containing the generated menus. + */ + protected function generateMenus($num_menus, $title_length = 12) { + $menus = []; + + for ($i = 1; $i <= $num_menus; $i++) { + $name = $this->randomSentenceOfLength(mt_rand(2, $title_length)); + // Create a random string of random length for the menu id. The maximum + // machine-name length is 32, so allowing for prefix 'devel-' we can have + // up to 26 here. For safety avoid accidentally reusing the same id. + do { + $id = 'devel-' . $this->getRandom()->name(mt_rand(2, 26)); + } while (array_key_exists($id, $menus)); + + $menu = $this->menuStorage->create([ + 'label' => $name, + 'id' => $id, + 'description' => $this->t('Description of @name', ['@name' => $name]), + ]); + + $menu->save(); + $menus[$menu->id()] = $menu->label(); + } + + return $menus; + } + + /** + * Generates menu links in a tree structure. + */ + protected function generateLinks($num_links, $menus, $title_length, $link_types, $max_depth, $max_width) { + $links = []; + $menus = array_keys(array_filter($menus)); + $link_types = array_keys(array_filter($link_types)); + + $nids = []; + for ($i = 1; $i <= $num_links; $i++) { + // Pick a random menu. + $menu_name = $menus[array_rand($menus)]; + // Build up our link. + $link_title = $this->getRandom()->word(mt_rand(2, max(2, $title_length))); + $link = $this->menuLinkContentStorage->create([ + 'menu_name' => $menu_name, + 'weight' => mt_rand(-50, 50), + 'title' => $link_title, + 'bundle' => 'menu_link_content', + 'description' => $this->t('Description of @title.', ['@title' => $link_title]), + ]); + $link->link->options = ['devel' => TRUE]; + + // For the first $max_width items, make first level links. + if ($i <= $max_width) { + $depth = 0; + } + else { + // Otherwise, get a random parent menu depth. + $depth = mt_rand(1, max(1, $max_depth - 1)); + } + // Get a random parent link from the proper depth. + do { + $parameters = new MenuTreeParameters(); + $parameters->setMinDepth($depth); + $parameters->setMaxDepth($depth); + $tree = $this->menuLinkTree->load($menu_name, $parameters); + + if ($tree) { + $link->parent = array_rand($tree); + } + $depth--; + } while (!$link->parent && $depth > 0); + + $link_type = array_rand($link_types); + switch ($link_types[$link_type]) { + case 'node': + // Grab a random node ID. + $select = $this->database->select('node_field_data', 'n') + ->fields('n', ['nid', 'title']) + ->condition('n.status', 1) + ->range(0, 1) + ->orderRandom(); + // Don't put a node into the menu twice. + if (!empty($nids[$menu_name])) { + $select->condition('n.nid', $nids[$menu_name], 'NOT IN'); + } + $node = $select->execute()->fetchAssoc(); + if (isset($node['nid'])) { + $nids[$menu_name][] = $node['nid']; + $link->link->uri = 'entity:node/' . $node['nid']; + $link->title = $node['title']; + break; + } + + case 'external': + $link->link->uri = 'http://www.example.com/'; + break; + + case 'front': + $link->link->uri = 'internal:/'; + break; + + default: + $link->devel_link_type = $link_type; + break; + } + + $link->save(); + + $links[$link->id()] = $link->link_title; + } + + return $links; + } + +} diff --git a/web/modules/contrib/devel/devel_generate/src/Plugin/DevelGenerate/TermDevelGenerate.php b/web/modules/contrib/devel/devel_generate/src/Plugin/DevelGenerate/TermDevelGenerate.php new file mode 100644 index 00000000..44b300e6 --- /dev/null +++ b/web/modules/contrib/devel/devel_generate/src/Plugin/DevelGenerate/TermDevelGenerate.php @@ -0,0 +1,477 @@ +vocabularyStorage = $vocabulary_storage; + $this->termStorage = $term_storage; + $this->database = $database; + $this->moduleHandler = $module_handler; + $this->languageManager = $language_manager; + $this->contentTranslationManager = $content_translation_manager; + } + + /** + * {@inheritdoc} + */ + public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) { + $entity_type_manager = $container->get('entity_type.manager'); + return new static( + $configuration, $plugin_id, $plugin_definition, + $entity_type_manager->getStorage('taxonomy_vocabulary'), + $entity_type_manager->getStorage('taxonomy_term'), + $container->get('database'), + $container->get('module_handler'), + $container->get('language_manager'), + $container->has('content_translation.manager') ? $container->get('content_translation.manager') : NULL + ); + } + + /** + * {@inheritdoc} + */ + public function settingsForm(array $form, FormStateInterface $form_state) { + $options = []; + foreach ($this->vocabularyStorage->loadMultiple() as $vocabulary) { + $options[$vocabulary->id()] = $vocabulary->label(); + } + // Sort by vocabulary label. + asort($options); + // Set default to 'tags' only if it exists as a vocabulary. + $default_vids = array_key_exists('tags', $options) ? 'tags' : ''; + $form['vids'] = [ + '#type' => 'select', + '#multiple' => TRUE, + '#title' => $this->t('Vocabularies'), + '#required' => TRUE, + '#default_value' => $default_vids, + '#options' => $options, + '#description' => $this->t('Restrict terms to these vocabularies.'), + ]; + $form['num'] = [ + '#type' => 'number', + '#title' => $this->t('Number of terms'), + '#default_value' => $this->getSetting('num'), + '#required' => TRUE, + '#min' => 0, + ]; + $form['title_length'] = [ + '#type' => 'number', + '#title' => $this->t('Maximum number of characters in term names'), + '#default_value' => $this->getSetting('title_length'), + '#required' => TRUE, + '#min' => 2, + '#max' => 255, + ]; + $form['minimum_depth'] = [ + '#type' => 'number', + '#title' => $this->t('Minimum depth for new terms in the vocabulary hierarchy'), + '#description' => $this->t('Enter a value from 1 to 20.'), + '#default_value' => $this->getSetting('minimum_depth'), + '#min' => 1, + '#max' => 20, + ]; + $form['maximum_depth'] = [ + '#type' => 'number', + '#title' => $this->t('Maximum depth for new terms in the vocabulary hierarchy'), + '#description' => $this->t('Enter a value from 1 to 20.'), + '#default_value' => $this->getSetting('maximum_depth'), + '#min' => 1, + '#max' => 20, + ]; + $form['kill'] = [ + '#type' => 'checkbox', + '#title' => $this->t('Delete existing terms in specified vocabularies before generating new terms.'), + '#default_value' => $this->getSetting('kill'), + ]; + + // Add the language and translation options. + $form += $this->getLanguageForm('terms'); + + return $form; + } + + /** + * {@inheritdoc} + */ + public function generateElements(array $values) { + $new_terms = $this->generateTerms($values); + if (!empty($new_terms['terms'])) { + $this->setMessage($this->formatPlural($new_terms['terms'], 'Created 1 new term', 'Created @count new terms')); + + // Helper function to format the number of terms and the list of terms. + $format_terms_func = function ($data, $level) { + if ($data['total'] > 10) { + $data['terms'][] = '...'; + } + return $this->formatPlural($data['total'], + '1 new term at level @level (@terms)', + '@count new terms at level @level (@terms)', + ['@level' => $level, '@terms' => implode(',', $data['terms'])]); + }; + + foreach ($new_terms['vocabs'] as $vid => $vlabel) { + if (array_key_exists($vid, $new_terms)) { + ksort($new_terms[$vid]); + $termlist = implode(', ', array_map($format_terms_func, $new_terms[$vid], array_keys($new_terms[$vid]))); + $this->setMessage($this->t('In vocabulary @vlabel: @termlist', ['@vlabel' => $vlabel, '@termlist' => $termlist])); + } + else { + $this->setMessage($this->t('In vocabulary @vlabel: No terms created', ['@vlabel' => $vlabel])); + } + } + + } + if ($new_terms['terms_translations'] > 0) { + $this->setMessage($this->formatPlural($new_terms['terms_translations'], 'Created 1 term translation', 'Created @count term translations')); + } + } + + /** + * Deletes all terms of given vocabularies. + * + * @param array $vids + * Array of vocabulary ids. + * + * @return int + * The number of terms deleted. + */ + protected function deleteVocabularyTerms(array $vids) { + $tids = $this->vocabularyStorage->getToplevelTids($vids); + $terms = $this->termStorage->loadMultiple($tids); + $total_deleted = 0; + foreach ($vids as $vid) { + $total_deleted += count($this->termStorage->loadTree($vid)); + } + $this->termStorage->delete($terms); + return $total_deleted; + } + + /** + * Generates taxonomy terms for a list of given vocabularies. + * + * @param array $parameters + * The input parameters from the settings form or drush command. + * + * @return array + * Information about the created terms. + */ + protected function generateTerms(array $parameters) { + $info = [ + 'terms' => 0, + 'terms_translations' => 0, + ]; + $min_depth = $parameters['minimum_depth']; + $max_depth = $parameters['maximum_depth']; + + // $parameters['vids'] from the UI has keys of the vocab ids. From drush + // the array is keyed 0,1,2. Therefore create $vocabs which has keys of the + // vocab ids, so it can be used with array_rand(). + $vocabs = array_combine($parameters['vids'], $parameters['vids']); + + // Build an array of potential parents for the new terms. These will be + // terms in the vocabularies we are creating in, which have a depth of one + // less than the minimum for new terms up to one less than the maximum. + $all_parents = []; + foreach ($parameters['vids'] as $vid) { + $info['vocabs'][$vid] = $this->vocabularyStorage->load($vid)->label(); + // Initialise the nested array for this vocabulary. + $all_parents[$vid] = ['top_level' => [], 'lower_levels' => []]; + for ($depth = 1; $depth < $max_depth; $depth++) { + $query = \Drupal::entityQuery('taxonomy_term')->condition('vid', $vid); + if ($depth == 1) { + // For the top level the parent id must be zero. + $query->condition('parent', 0); + } + else { + // For lower levels use the $ids array obtained in the previous loop. + // phpcs:ignore DrupalPractice.CodeAnalysis.VariableAnalysis.UndefinedVariable + $query->condition('parent', $ids, 'IN'); + } + $ids = $query->execute(); + + if (empty($ids)) { + // Reached the end, no more parents to be found. + break; + } + + // Store these terms as parents if they are within the depth range for + // new terms. + if ($depth == $min_depth - 1) { + $all_parents[$vid]['top_level'] = array_fill_keys($ids, $depth); + } + elseif ($depth >= $min_depth) { + $all_parents[$vid]['lower_levels'] += array_fill_keys($ids, $depth); + } + } + // No top-level parents will have been found above when the minimum depth + // is 1 so add a record for that data here. + if ($min_depth == 1) { + $all_parents[$vid]['top_level'] = [0 => 0]; + } + elseif (empty($all_parents[$vid]['top_level'])) { + // No parents for required minimum level so cannot use this vocabulary. + unset($vocabs[$vid]); + } + } + + if (empty($vocabs)) { + // There are no available parents at the required depth in any vocabulary + // so we cannot create any new terms. + throw new \Exception(sprintf('Invalid minimum depth %s because there are no terms in any vocabulary at depth %s', $min_depth, $min_depth - 1)); + } + + // Only delete terms from the vocabularies we can create new terms in. + if ($parameters['kill']) { + $deleted = $this->deleteVocabularyTerms($vocabs); + $this->setMessage($this->formatPlural($deleted, 'Deleted 1 existing term', 'Deleted @count existing terms')); + } + + // Insert new data: + for ($i = 1; $i <= $parameters['num']; $i++) { + // Select a vocabulary at random. + $vid = array_rand($vocabs); + + // Set the group to use to select a random parent from. Using < 50 means + // on average half of the new terms will be top_level. Also if no terms + // exist yet in 'lower_levels' then we have to use 'top_level'. + $group = (mt_rand(0, 100) < 50 || empty($all_parents[$vid]['lower_levels'])) ? 'top_level' : 'lower_levels'; + $parent = array_rand($all_parents[$vid][$group]); + $depth = $all_parents[$vid][$group][$parent] + 1; + $name = $this->getRandom()->word(mt_rand(2, $parameters['title_length'])); + + $values = [ + 'name' => $name, + 'description' => 'Description of ' . $name . ' (depth ' . $depth . ')', + 'format' => filter_fallback_format(), + 'weight' => mt_rand(0, 10), + 'vid' => $vid, + 'parent' => [$parent], + ]; + if (isset($parameters['add_language'])) { + $values['langcode'] = $this->getLangcode($parameters['add_language']); + } + $term = $this->termStorage->create($values); + + // A flag to let hook implementations know that this is a generated term. + $term->devel_generate = TRUE; + + // Populate all fields with sample values. + $this->populateFields($term); + $term->save(); + + // Add translations. + if (isset($parameters['translate_language']) && !empty($parameters['translate_language'])) { + $info['terms_translations'] += $this->generateTermTranslation($parameters['translate_language'], $term); + } + + // If the depth of the new term is less than the maximum depth then it can + // also be saved as a potential parent for the subsequent new terms. + if ($depth < $max_depth) { + $all_parents[$vid]['lower_levels'] += [$term->id() => $depth]; + } + + // Store data about the newly generated term. + $info['terms']++; + @$info[$vid][$depth]['total']++; + // List only the first 10 new terms at each vocab/level. + if (!isset($info[$vid][$depth]['terms']) || count($info[$vid][$depth]['terms']) < 10) { + $info[$vid][$depth]['terms'][] = $term->label(); + } + + unset($term); + } + + return $info; + } + + /** + * Create translation for the given term. + * + * @param array $translate_language + * Potential translate languages array. + * @param \Drupal\taxonomy\TermInterface $term + * Term to add translations to. + * + * @return int + * Number of translations added. + */ + protected function generateTermTranslation(array $translate_language, TermInterface $term) { + if (is_null($this->contentTranslationManager)) { + return 0; + } + if (!$this->contentTranslationManager->isEnabled('taxonomy_term', $term->bundle())) { + return 0; + } + if ($term->langcode == LanguageInterface::LANGCODE_NOT_SPECIFIED || $term->langcode == LanguageInterface::LANGCODE_NOT_APPLICABLE) { + return 0; + } + + $num_translations = 0; + // Translate term to each target language. + $skip_languages = [ + LanguageInterface::LANGCODE_NOT_SPECIFIED, + LanguageInterface::LANGCODE_NOT_APPLICABLE, + $term->langcode->value, + ]; + foreach ($translate_language as $langcode) { + if (in_array($langcode, $skip_languages)) { + continue; + } + $translation_term = $term->addTranslation($langcode); + $translation_term->setName($term->getName() . ' (' . $langcode . ')'); + $this->populateFields($translation_term); + $translation_term->save(); + $num_translations++; + } + return $num_translations; + } + + /** + * {@inheritdoc} + */ + public function validateDrushParams(array $args, array $options = []) { + // Get default settings from the annotated command definition. + $defaultSettings = $this->getDefaultSettings(); + + $bundles = StringUtils::csvToarray($options['bundles']); + if (count($bundles) < 1) { + throw new \Exception(dt('Please provide a vocabulary machine name (--bundles).')); + } + foreach ($bundles as $bundle) { + // Verify that each bundle is a valid vocabulary id. + if (!$this->vocabularyStorage->load($bundle)) { + throw new \Exception(dt('Invalid vocabulary machine name: @name', ['@name' => $bundle])); + } + } + + $number = array_shift($args) ?: $defaultSettings['num']; + if (!$this->isNumber($number)) { + throw new \Exception(dt('Invalid number of terms: @num', ['@num' => $number])); + } + + $minimum_depth = $options['min-depth'] ?? $defaultSettings['minimum_depth']; + $maximum_depth = $options['max-depth'] ?? $defaultSettings['maximum_depth']; + if ($minimum_depth < 1 || $minimum_depth > 20 || $maximum_depth < 1 || $maximum_depth > 20 || $minimum_depth > $maximum_depth) { + throw new \Exception(dt('The depth values must be in the range 1 to 20 and min-depth cannot be larger than max-depth (values given: min-depth @min, max-depth @max)', ['@min' => $minimum_depth, '@max' => $maximum_depth])); + } + + $values = [ + 'num' => $number, + 'kill' => $options['kill'], + 'title_length' => 12, + 'vids' => $bundles, + 'minimum_depth' => $minimum_depth, + 'maximum_depth' => $maximum_depth, + ]; + $add_language = StringUtils::csvToArray($options['languages']); + // Intersect with the enabled languages to make sure the language args + // passed are actually enabled. + $valid_languages = array_keys($this->languageManager->getLanguages(LanguageInterface::STATE_ALL)); + $values['add_language'] = array_intersect($add_language, $valid_languages); + + $translate_language = StringUtils::csvToArray($options['translations']); + $values['translate_language'] = array_intersect($translate_language, $valid_languages); + return $values; + } + +} diff --git a/web/modules/contrib/devel/devel_generate/src/Plugin/DevelGenerate/UserDevelGenerate.php b/web/modules/contrib/devel/devel_generate/src/Plugin/DevelGenerate/UserDevelGenerate.php new file mode 100644 index 00000000..69d0b15e --- /dev/null +++ b/web/modules/contrib/devel/devel_generate/src/Plugin/DevelGenerate/UserDevelGenerate.php @@ -0,0 +1,206 @@ +userStorage = $entity_storage; + $this->dateFormatter = $date_formatter; + $this->time = $time; + } + + /** + * {@inheritdoc} + */ + public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) { + return new static( + $configuration, $plugin_id, $plugin_definition, + $container->get('entity_type.manager')->getStorage('user'), + $container->get('date.formatter'), + $container->get('datetime.time') + ); + } + + /** + * {@inheritdoc} + */ + public function settingsForm(array $form, FormStateInterface $form_state) { + $form['num'] = [ + '#type' => 'number', + '#title' => $this->t('How many users would you like to generate?'), + '#default_value' => $this->getSetting('num'), + '#required' => TRUE, + '#min' => 0, + ]; + + $form['kill'] = [ + '#type' => 'checkbox', + '#title' => $this->t('Delete all users (except user id 1) before generating new users.'), + '#default_value' => $this->getSetting('kill'), + ]; + + $options = user_role_names(TRUE); + unset($options[AccountInterface::AUTHENTICATED_ROLE]); + $form['roles'] = [ + '#type' => 'checkboxes', + '#title' => $this->t('Which roles should the users receive?'), + '#description' => $this->t('Users always receive the authenticated user role.'), + '#options' => $options, + ]; + + $form['pass'] = [ + '#type' => 'textfield', + '#title' => $this->t('Password to be set'), + '#default_value' => $this->getSetting('pass'), + '#size' => 32, + '#description' => $this->t('Leave this field empty if you do not need to set a password'), + ]; + + $options = [1 => $this->t('Now')]; + foreach ([3600, 86400, 604800, 2592000, 31536000] as $interval) { + $options[$interval] = $this->dateFormatter->formatInterval($interval, 1) . ' ' . $this->t('ago'); + } + $form['time_range'] = [ + '#type' => 'select', + '#title' => $this->t('How old should user accounts be?'), + '#description' => $this->t('User ages will be distributed randomly from the current time, back to the selected time.'), + '#options' => $options, + '#default_value' => 604800, + ]; + + return $form; + } + + /** + * {@inheritdoc} + */ + protected function generateElements(array $values) { + $num = $values['num']; + $kill = $values['kill']; + $pass = $values['pass']; + $age = $values['time_range']; + $roles = array_filter($values['roles']); + + if ($kill) { + $uids = $this->userStorage->getQuery() + ->condition('uid', 1, '>') + ->execute(); + $users = $this->userStorage->loadMultiple($uids); + $this->userStorage->delete($users); + + $this->setMessage($this->formatPlural(count($uids), '1 user deleted', '@count users deleted.')); + } + + if ($num > 0) { + $names = []; + while (count($names) < $num) { + $name = $this->getRandom()->word(mt_rand(6, 12)); + $names[$name] = ''; + } + + if (empty($roles)) { + $roles = [AccountInterface::AUTHENTICATED_ROLE]; + } + foreach ($names as $name => $value) { + $account = $this->userStorage->create([ + 'uid' => NULL, + 'name' => $name, + 'pass' => $pass, + 'mail' => $name . '@example.com', + 'status' => 1, + 'created' => $this->time->getRequestTime() - mt_rand(0, $age), + 'roles' => array_values($roles), + // A flag to let hook_user_* know that this is a generated user. + 'devel_generate' => TRUE, + ]); + + // Populate all fields with sample values. + $this->populateFields($account); + $account->save(); + } + } + $this->setMessage($this->t('@num_users created.', + ['@num_users' => $this->formatPlural($num, '1 user', '@count users')])); + } + + /** + * {@inheritdoc} + */ + public function validateDrushParams(array $args, array $options = []) { + $values = [ + 'num' => array_shift($args), + 'time_range' => 0, + 'roles' => StringUtils::csvToArray($options['roles']), + 'kill' => $options['kill'], + 'pass' => $options['pass'], + ]; + return $values; + } + +} diff --git a/web/modules/contrib/devel/devel_generate/src/Plugin/DevelGenerate/VocabularyDevelGenerate.php b/web/modules/contrib/devel/devel_generate/src/Plugin/DevelGenerate/VocabularyDevelGenerate.php new file mode 100644 index 00000000..a8c1a592 --- /dev/null +++ b/web/modules/contrib/devel/devel_generate/src/Plugin/DevelGenerate/VocabularyDevelGenerate.php @@ -0,0 +1,174 @@ +vocabularyStorage = $entity_storage; + } + + /** + * {@inheritdoc} + */ + public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) { + return new static( + $configuration, $plugin_id, $plugin_definition, + $container->get('entity_type.manager')->getStorage('taxonomy_vocabulary') + ); + } + + /** + * {@inheritdoc} + */ + public function settingsForm(array $form, FormStateInterface $form_state) { + $form['num'] = [ + '#type' => 'number', + '#title' => $this->t('Number of vocabularies?'), + '#default_value' => $this->getSetting('num'), + '#required' => TRUE, + '#min' => 0, + ]; + $form['title_length'] = [ + '#type' => 'number', + '#title' => $this->t('Maximum number of characters in vocabulary names'), + '#default_value' => $this->getSetting('title_length'), + '#required' => TRUE, + '#min' => 2, + '#max' => 255, + ]; + $form['kill'] = [ + '#type' => 'checkbox', + '#title' => $this->t('Delete existing vocabularies before generating new ones.'), + '#default_value' => $this->getSetting('kill'), + ]; + + return $form; + } + + /** + * {@inheritdoc} + */ + public function generateElements(array $values) { + if ($values['kill']) { + $this->deleteVocabularies(); + $this->setMessage($this->t('Deleted existing vocabularies.')); + } + + $new_vocs = $this->generateVocabularies($values['num'], $values['title_length']); + if (!empty($new_vocs)) { + $this->setMessage($this->t('Created the following new vocabularies: @vocs', ['@vocs' => implode(', ', $new_vocs)])); + } + } + + /** + * Deletes all vocabularies. + */ + protected function deleteVocabularies() { + $vocabularies = $this->vocabularyStorage->loadMultiple(); + $this->vocabularyStorage->delete($vocabularies); + } + + /** + * Generates vocabularies. + * + * @param int $records + * Number of vocabularies to create. + * @param int $maxlength + * (optional) Maximum length for vocabulary name. + * + * @return array + * Array containing the generated vocabularies id. + */ + protected function generateVocabularies($records, $maxlength = 12) { + $vocabularies = []; + + // Insert new data: + for ($i = 1; $i <= $records; $i++) { + $name = $this->getRandom()->word(mt_rand(2, $maxlength)); + + $vocabulary = $this->vocabularyStorage->create([ + 'name' => $name, + 'vid' => mb_strtolower($name), + 'langcode' => Language::LANGCODE_NOT_SPECIFIED, + 'description' => "Description of $name", + 'hierarchy' => 1, + 'weight' => mt_rand(0, 10), + 'multiple' => 1, + 'required' => 0, + 'relations' => 1, + ]); + + // Populate all fields with sample values. + $this->populateFields($vocabulary); + $vocabulary->save(); + + $vocabularies[] = $vocabulary->id(); + unset($vocabulary); + } + + return $vocabularies; + } + + /** + * {@inheritdoc} + */ + public function validateDrushParams(array $args, array $options = []) { + $values = [ + 'num' => array_shift($args), + 'kill' => $options['kill'], + 'title_length' => 12, + ]; + + if ($this->isNumber($values['num']) == FALSE) { + throw new \Exception(dt('Invalid number of vocabularies: @num.', ['@num' => $values['num']])); + } + + return $values; + } + +} diff --git a/web/modules/contrib/devel/devel_generate/src/Routing/DevelGenerateRoutes.php b/web/modules/contrib/devel/devel_generate/src/Routing/DevelGenerateRoutes.php new file mode 100644 index 00000000..eb302b00 --- /dev/null +++ b/web/modules/contrib/devel/devel_generate/src/Routing/DevelGenerateRoutes.php @@ -0,0 +1,73 @@ +DevelGenerateManager = $devel_generate_manager; + } + + /** + * {@inheritdoc} + */ + public static function create(ContainerInterface $container) { + return new static( + $container->get('plugin.manager.develgenerate') + ); + } + + /** + * Define routes for all devel_generate plugins. + */ + public function routes() { + $devel_generate_plugins = $this->DevelGenerateManager->getDefinitions(); + + $routes = []; + foreach ($devel_generate_plugins as $id => $plugin) { + $label = $plugin['label']; + $type_url_str = str_replace('_', '-', $plugin['url']); + $routes["devel_generate.$id"] = new Route( + "admin/config/development/generate/$type_url_str", + [ + '_form' => '\Drupal\devel_generate\Form\DevelGenerateForm', + '_title' => "Generate $label", + '_plugin_id' => $id, + ], + [ + '_permission' => $plugin['permission'], + ] + ); + } + + // Add the route for the 'Generate' admin group on the admin/config page. + // This also provides the page for all devel_generate links. + $routes['devel_generate.admin_config_generate'] = new Route( + '/admin/config/development/generate', + [ + '_controller' => '\Drupal\system\Controller\SystemController::systemAdminMenuBlockPage', + '_title' => 'Generate', + ], + [ + '_permission' => 'administer devel_generate', + ] + ); + + return $routes; + } + +} diff --git a/web/modules/contrib/devel/devel_generate/tests/modules/devel_generate_example/devel_generate_example.info.yml b/web/modules/contrib/devel/devel_generate/tests/modules/devel_generate_example/devel_generate_example.info.yml new file mode 100644 index 00000000..b0c5fb95 --- /dev/null +++ b/web/modules/contrib/devel/devel_generate/tests/modules/devel_generate_example/devel_generate_example.info.yml @@ -0,0 +1,13 @@ +name: 'Devel Generate Example' +type: module +description: 'Create an example of a Devel Generate plugin type for testing purposes.' +package: Development +core_version_requirement: ^8.8 || ^9 +configure: admin/config/development/generate +tags: + - developer + +# Information added by Drupal.org packaging script on 2020-12-31 +version: '4.1.1' +project: 'devel' +datestamp: 1609419530 diff --git a/web/modules/contrib/devel/devel_generate/tests/modules/devel_generate_example/src/Plugin/DevelGenerate/ExampleDevelGenerate.php b/web/modules/contrib/devel/devel_generate/tests/modules/devel_generate_example/src/Plugin/DevelGenerate/ExampleDevelGenerate.php new file mode 100644 index 00000000..eff39752 --- /dev/null +++ b/web/modules/contrib/devel/devel_generate/tests/modules/devel_generate_example/src/Plugin/DevelGenerate/ExampleDevelGenerate.php @@ -0,0 +1,97 @@ + 'textfield', + '#title' => $this->t('How many examples would you like to generate?'), + '#default_value' => $this->getSetting('num'), + '#size' => 10, + ]; + + $form['kill'] = [ + '#type' => 'checkbox', + '#title' => $this->t('Delete all examples before generating new examples.'), + '#default_value' => $this->getSetting('kill'), + ]; + + return $form; + } + + /** + * {@inheritdoc} + */ + protected function generateElements(array $values) { + $num = $values['num']; + $kill = $values['kill']; + + if ($kill) { + $this->setMessage($this->t('Old examples have been deleted.')); + } + + // Creating user in order to demonstrate + // how to override default business login generation. + $edit = [ + 'uid' => NULL, + 'name' => 'example_devel_generate', + 'pass' => '', + 'mail' => 'example_devel_generate@example.com', + 'status' => 1, + 'created' => \Drupal::time()->getRequestTime(), + 'roles' => '', + // A flag to let hook_user_* know that this is a generated user. + 'devel_generate' => TRUE, + ]; + + $account = user_load_by_name('example_devel_generate'); + if (!$account) { + $account = $this->getEntityTypeManager()->getStorage('user')->create($edit); + } + + // Populate all fields with sample values. + $this->populateFields($account); + + $account->save(); + + $this->setMessage($this->t('@num_examples created.', [ + '@num_examples' => $this->formatPlural($num, '1 example', '@count examples'), + ])); + } + + /** + * + */ + public function validateDrushParams(array $args, array $options = []) { + $values = [ + 'num' => $options['num'], + 'kill' => $options['kill'], + ]; + return $values; + } + +} diff --git a/web/modules/contrib/devel/devel_generate/tests/src/Functional/DevelGenerateBrowserTest.php b/web/modules/contrib/devel/devel_generate/tests/src/Functional/DevelGenerateBrowserTest.php new file mode 100644 index 00000000..f54e02cb --- /dev/null +++ b/web/modules/contrib/devel/devel_generate/tests/src/Functional/DevelGenerateBrowserTest.php @@ -0,0 +1,412 @@ + 4, + ]; + $this->drupalPostForm('admin/config/development/generate/user', $edit, 'Generate'); + $this->assertText('4 users created.'); + $this->assertText('Generate process complete.'); + + } + + /** + * Tests generating content. + */ + public function testDevelGenerateContent() { + // Tests that if no content types are selected an error message is shown. + $edit = [ + 'num' => 4, + 'title_length' => 4, + ]; + $this->drupalPostForm('admin/config/development/generate/content', $edit, 'Generate'); + $this->assertText('Please select at least one content type'); + + // Create a node in order to test the Delete content checkbox. + $this->drupalCreateNode(['type' => 'article']); + + // Generate articles with comments and aliases. + $edit = [ + 'num' => 4, + 'kill' => TRUE, + 'node_types[article]' => TRUE, + 'time_range' => 604800, + 'max_comments' => 3, + 'title_length' => 4, + 'add_alias' => 1, + ]; + $this->drupalPostForm('admin/config/development/generate/content', $edit, 'Generate'); + $this->assertSession()->pageTextContains('Deleted 1 node'); + $this->assertSession()->pageTextContains('Created 4 nodes'); + $this->assertSession()->pageTextContains('Generate process complete.'); + $this->assertSession()->pageTextNotContains('translations'); + + // Tests that nodes have been created in the generation process. + $nodes = Node::loadMultiple(); + $this->assert(count($nodes) == 4, 'Nodes generated successfully.'); + + // Tests url alias for the generated nodes. + foreach ($nodes as $node) { + $alias = 'node-' . $node->id() . '-' . $node->bundle(); + $this->drupalGet($alias); + $this->assertSession()->statusCodeEquals('200'); + $this->assertSession()->pageTextContains($node->getTitle(), 'Generated url alias for the node works.'); + } + + // Generate articles with translations. + $edit = [ + 'num' => 3, + 'kill' => TRUE, + 'node_types[article]' => TRUE, + 'add_language[]' => ['en'], + 'translate_language[]' => ['de', 'ca'], + 'add_alias' => TRUE, + ]; + $this->drupalPostForm('admin/config/development/generate/content', $edit, 'Generate'); + $this->assertSession()->pageTextContains('Deleted 4 nodes'); + $this->assertSession()->pageTextContains('Created 3 nodes'); + // Two translations for each node makes six. + $this->assertSession()->pageTextContains('Created 6 node translations'); + $articles = \Drupal::entityQuery('node')->execute(); + $this->assertCount(3, $articles); + $node = Node::load(end($articles)); + $this->assertTrue($node->hasTranslation('de')); + $this->assertTrue($node->hasTranslation('ca')); + $this->assertFalse($node->hasTranslation('fr')); + + // Check url alias for each of the translations. + foreach (Node::loadMultiple($articles) as $node) { + foreach (['de', 'ca'] as $langcode) { + $translation_node = $node->getTranslation($langcode); + $alias = 'node-' . $translation_node->id() . '-' . $translation_node->bundle() . '-' . $langcode; + $this->drupalGet($langcode . '/' . $alias); + $this->assertSession()->statusCodeEquals('200'); + $this->assertSession()->pageTextContains($translation_node->getTitle()); + } + } + + // Create article to make sure it is not deleted when only killing pages. + $article = $this->drupalCreateNode(['type' => 'article', 'title' => 'Alive']); + // The 'page' content type is not enabled for translation. + $edit = [ + 'num' => 2, + 'kill' => TRUE, + 'node_types[page]' => TRUE, + 'add_language[]' => ['en'], + 'translate_language[]' => ['fr'], + ]; + $this->drupalPostForm('admin/config/development/generate/content', $edit, 'Generate'); + $this->assertSession()->pageTextNotContains('Deleted'); + $this->assertSession()->pageTextContains('Created 2 nodes'); + $this->assertSession()->pageTextNotContains('node translations'); + // Check that 'kill' has not deleted the article. + $this->assertNotEmpty(Node::load($article->id())); + $pages = \Drupal::entityQuery('node')->condition('type', 'page')->execute(); + $this->assertCount(2, $pages); + $node = Node::load(end($pages)); + $this->assertFalse($node->hasTranslation('fr')); + + // Create articles with add-type-label option. + $edit = [ + 'num' => 5, + 'kill' => TRUE, + 'node_types[article]' => TRUE, + 'add_type_label' => TRUE, + ]; + $this->drupalPostForm('admin/config/development/generate/content', $edit, 'Generate'); + $this->assertSession()->pageTextContains('Created 5 nodes'); + $this->assertSession()->pageTextContains('Generate process complete'); + + // Count the articles created in the generation process. + $nodes = \Drupal::entityQuery('node')->condition('type', 'article')->execute(); + $this->assertCount(5, $nodes); + + // Load the final node and verify that the title starts with the label. + $node = Node::load(end($nodes)); + $this->assertEquals('Article - ', substr($node->title->value, 0, 10)); + + // Test creating content with specified authors. First create 15 more users + // making 18 in total, to make the test much stronger. + for ($i = 0; $i < 15; $i++) { + $this->drupalCreateUser(); + } + $edit = [ + 'num' => 10, + 'kill' => TRUE, + 'node_types[article]' => TRUE, + 'authors[3]' => TRUE, + 'authors[4]' => TRUE, + ]; + $this->drupalPostForm('admin/config/development/generate/content', $edit, 'Generate'); + + // Display the full content list for information and debug only. + $this->drupalGet('admin/content'); + + // Count all the articles by user 3 and 4 and by others. We count the two + // users nodes separately to ensure that there are some by each user. + $nodes_by_user_3 = \Drupal::entityQuery('node')->condition('type', 'article')->condition('uid', ['3'], 'IN')->execute(); + $nodes_by_user_4 = \Drupal::entityQuery('node')->condition('type', 'article')->condition('uid', ['4'], 'IN')->execute(); + $nodes_by_others = \Drupal::entityQuery('node')->condition('type', 'article')->condition('uid', ['3', '4'], 'NOT IN')->execute(); + + // If the user option was not working correctly and users were assigned at + // random, then the chance that these assertions will correctly detect the + // error is 1 - (2/18 ** 10) = 99.99%. + $this->assertEquals(10, count($nodes_by_user_3) + count($nodes_by_user_4)); + $this->assertCount(0, $nodes_by_others); + + // If the user option is coded correctly the chance of either of these + // assertions giving a false failure is 1/2 ** 10 = 0.097%. + $this->assertGreaterThan(0, count($nodes_by_user_3)); + $this->assertGreaterThan(0, count($nodes_by_user_4)); + } + + /** + * Tests generating terms. + */ + public function testDevelGenerateTerms() { + // Generate terms. + $edit = [ + 'vids[]' => $this->vocabulary->id(), + 'num' => 5, + 'title_length' => 12, + ]; + $this->drupalPostForm('admin/config/development/generate/term', $edit, 'Generate'); + $this->assertSession()->pageTextContains('Created 5 new terms'); + $this->assertSession()->pageTextContains('In vocabulary ' . $this->vocabulary->label()); + $this->assertSession()->pageTextNotContains('translations'); + $this->assertSession()->pageTextContains('Generate process complete.'); + $this->assertCount(5, \Drupal::entityQuery('taxonomy_term')->execute()); + + // Generate terms with translations. + $edit = [ + 'vids[]' => $this->vocabulary->id(), + 'num' => 3, + 'add_language[]' => ['en'], + 'translate_language[]' => ['ca'], + ]; + $this->drupalPostForm('admin/config/development/generate/term', $edit, 'Generate'); + $this->assertSession()->pageTextNotContains('Deleted'); + $this->assertSession()->pageTextContains('Created 3 new terms'); + $this->assertSession()->pageTextContains('Created 3 term translations'); + // Not using 'kill' so there should be 8 terms. + $terms = \Drupal::entityQuery('taxonomy_term')->execute(); + $this->assertCount(8, $terms); + // Check the translations created (and not created). + $term = Term::load(end($terms)); + $this->assertTrue($term->hasTranslation('ca')); + $this->assertFalse($term->hasTranslation('de')); + $this->assertFalse($term->hasTranslation('fr')); + + // Generate terms in vocabulary 2 only. + $edit = [ + 'vids[]' => $this->vocabulary2->id(), + 'num' => 4, + ]; + $this->drupalPostForm('admin/config/development/generate/term', $edit, 'Generate'); + $this->assertSession()->pageTextContains('Created 4 new terms'); + $this->assertSession()->pageTextNotContains('In vocabulary ' . $this->vocabulary->label()); + $this->assertSession()->pageTextContains('In vocabulary ' . $this->vocabulary2->label()); + // Check the term count in each vocabulary. + $terms1 = \Drupal::entityQuery('taxonomy_term')->condition('vid', $this->vocabulary->id())->execute(); + $this->assertCount(8, $terms1); + $terms2 = \Drupal::entityQuery('taxonomy_term')->condition('vid', $this->vocabulary2->id())->execute(); + $this->assertCount(4, $terms2); + + // Generate in vocabulary 2 with 'kill' to remove the existing vocab2 terms. + $edit = [ + 'vids[]' => $this->vocabulary2->id(), + 'num' => 6, + 'kill' => TRUE, + ]; + $this->drupalPostForm('admin/config/development/generate/term', $edit, 'Generate'); + $this->assertSession()->pageTextContains('Deleted 4 existing terms'); + $this->assertSession()->pageTextContains('Created 6 new terms'); + // Check the term count in vocabulary 1 has not changed. + $terms1 = \Drupal::entityQuery('taxonomy_term')->condition('vid', $this->vocabulary->id())->execute(); + $this->assertCount(8, $terms1); + // Check the term count in vocabulary 2 is just from the second call. + $terms2 = \Drupal::entityQuery('taxonomy_term')->condition('vid', $this->vocabulary2->id())->execute(); + $this->assertCount(6, $terms2); + + // Generate in both vocabularies and specify minimum and maximum depth. + $edit = [ + 'vids[]' => [$this->vocabulary->id(), $this->vocabulary2->id()], + 'num' => 9, + 'minimum_depth' => 2, + 'maximum_depth' => 6, + ]; + $this->drupalPostForm('admin/config/development/generate/term', $edit, 'Generate'); + $this->assertSession()->pageTextContains('Created 9 new terms'); + // Check the total term count is 8 + 6 + 9 = 23. + $terms1 = \Drupal::entityQuery('taxonomy_term')->condition('vid', $this->vocabulary->id())->execute(); + $terms2 = \Drupal::entityQuery('taxonomy_term')->condition('vid', $this->vocabulary2->id())->execute(); + $this->assertCount(23, $terms1 + $terms2); + + } + + /** + * Tests generating vocabularies. + */ + public function testDevelGenerateVocabs() { + $edit = [ + 'num' => 5, + 'title_length' => 12, + 'kill' => TRUE, + ]; + $this->drupalPostForm('admin/config/development/generate/vocabs', $edit, 'Generate'); + $this->assertSession()->pageTextContains('Created the following new vocabularies: '); + $this->assertSession()->pageTextContains('Generate process complete.'); + } + + /** + * Tests generating menus. + * + * @todo Add test coverage to check: + * - title_length is not exceeded. + * - max_depth and max_width work as designed. + * - generating links in existing menus, and then deleting them with kill. + * - using specific link_types settings only create those links. + */ + public function testDevelGenerateMenus() { + $edit = [ + 'num_menus' => 5, + 'num_links' => 7, + ]; + $this->drupalPostForm('admin/config/development/generate/menu', $edit, 'Generate'); + $this->assertSession()->pageTextContains('Created the following 5 new menus: '); + $this->assertSession()->pageTextContains('Created 7 new menu links'); + $this->assertSession()->pageTextContains('Generate process complete.'); + + // Use big numbers for menus and links, but short text, to test for clashes. + // Also verify the kill option. + $edit = [ + 'num_menus' => 160, + 'num_links' => 380, + 'title_length' => 3, + 'kill' => 1, + ]; + $this->drupalPostForm('admin/config/development/generate/menu', $edit, 'Generate'); + $this->assertSession()->pageTextContains('Deleted 5 menu(s) and 0 other link(s).'); + $this->assertSession()->pageTextContains('Created the following 160 new menus: '); + $this->assertSession()->pageTextContains('Created 380 new menu links'); + $this->assertSession()->pageTextContains('Generate process complete.'); + } + + /** + * Tests generating media. + */ + public function testDevelGenerateMedia() { + // As the 'media' plugin has a dependency on 'media' module, the plugin is + // not generating a route to the plugin form. + $this->drupalGet('admin/config/development/generate/media'); + $this->assertSession()->statusCodeEquals(404); + // Enable the module and retry. + \Drupal::service('module_installer')->install(['media']); + $this->getSession()->reload(); + $this->assertSession()->statusCodeEquals(200); + $this->assertSession()->pageTextContains('Generate media'); + + // Create two media types. + $media_type1 = $this->createMediaType('image'); + $media_type2 = $this->createMediaType('audio_file'); + + // Creating media items (non-batch mode). + $edit = [ + 'num' => 5, + 'name_length' => 12, + "media_types[{$media_type1->id()}]" => 1, + "media_types[{$media_type2->id()}]" => 1, + 'kill' => 1, + ]; + $this->drupalPostForm('admin/config/development/generate/media', $edit, 'Generate'); + $this->assertSession()->pageTextContains('Finished creating 5 media items.'); + $this->assertSession()->pageTextContains('Generate process complete.'); + $this->assertCount(5, \Drupal::entityQuery('media')->execute()); + + // Creating media items (batch mode). + $edit = [ + 'num' => 56, + 'name_length' => 6, + "media_types[{$media_type1->id()}]" => 1, + "media_types[{$media_type2->id()}]" => 1, + 'kill' => 1, + ]; + $this->drupalPostForm('admin/config/development/generate/media', $edit, 'Generate'); + $this->assertSession()->pageTextContains('Finished 56 elements created successfully.'); + $this->assertSession()->pageTextContains('Generate process complete.'); + $this->assertCount(56, \Drupal::entityQuery('media')->execute()); + } + + /** + * Tests generating content in batch mode. + */ + public function testDevelGenerateBatchContent() { + // For 50 or more nodes, the processing will be done via batch. + $edit = [ + 'num' => 55, + 'kill' => TRUE, + 'node_types[article]' => TRUE, + 'node_types[page]' => TRUE, + ]; + $this->drupalPostForm('admin/config/development/generate/content', $edit, 'Generate'); + $this->assertSession()->pageTextContains('Finished 55 elements created successfully.'); + $this->assertSession()->pageTextContains('Generate process complete.'); + + // Tests that the expected number of nodes have been created. + $count = count(Node::loadMultiple()); + $this->assertEquals(55, $count, sprintf('The expected total number of nodes is %s, found %s', 55, $count)); + + // Create nodes with translations via batch. + $edit = [ + 'num' => 52, + 'kill' => TRUE, + 'node_types[article]' => TRUE, + 'node_types[page]' => TRUE, + 'add_language[]' => ['en'], + 'translate_language[]' => ['de', 'ca'], + ]; + $this->drupalPostForm('admin/config/development/generate/content', $edit, 'Generate'); + $this->assertCount(52, \Drupal::entityQuery('node')->execute()); + // Only aticles will have translations so get that number. + $articles = \Drupal::entityQuery('node')->condition('type', 'article')->execute(); + $this->assertSession()->pageTextContains(sprintf('Finished 52 elements and %s translations created successfully.', 2 * count($articles))); + + // Generate only articles. + $edit = [ + 'num' => 60, + 'kill' => TRUE, + 'node_types[article]' => TRUE, + 'node_types[page]' => FALSE, + ]; + $this->drupalPostForm('admin/config/development/generate/content', $edit, 'Generate'); + + // Tests that all the created nodes were of the node type selected. + $nodeStorage = $this->container->get('entity_type.manager')->getStorage('node'); + $type = 'article'; + $count = $nodeStorage->getQuery() + ->condition('type', $type) + ->count() + ->execute(); + $this->assertEquals(60, $count, sprintf('The expected number of %s is %s, found %s', $type, 60, $count)); + + } + +} diff --git a/web/modules/contrib/devel/devel_generate/tests/src/Functional/DevelGenerateBrowserTestBase.php b/web/modules/contrib/devel/devel_generate/tests/src/Functional/DevelGenerateBrowserTestBase.php new file mode 100644 index 00000000..6efcbf94 --- /dev/null +++ b/web/modules/contrib/devel/devel_generate/tests/src/Functional/DevelGenerateBrowserTestBase.php @@ -0,0 +1,52 @@ +setUpData(); + } + +} diff --git a/web/modules/contrib/devel/devel_generate/tests/src/Functional/DevelGenerateCommandsTest.php b/web/modules/contrib/devel/devel_generate/tests/src/Functional/DevelGenerateCommandsTest.php new file mode 100644 index 00000000..c68853d4 --- /dev/null +++ b/web/modules/contrib/devel/devel_generate/tests/src/Functional/DevelGenerateCommandsTest.php @@ -0,0 +1,229 @@ +setUpData(); + } + + /** + * Tests generating users. + */ + public function testDrushGenerateUsers() { + // Make sure users get created, and with correct roles. + $this->drush('devel-generate-users', [55], ['kill' => NULL, 'roles' => 'administrator']); + $user = User::load(55); + $this->assertTrue($user->hasRole('administrator')); + } + + /** + * Tests generating terms. + */ + public function testDrushGenerateTerms() { + // Make sure terms get created, and with correct vocab. + $this->drush('devel-generate-terms', [55], ['kill' => NULL, 'bundles' => $this->vocabulary->id()]); + $term = Term::load(55); + $this->assertEquals($this->vocabulary->id(), $term->bundle()); + + // Make sure terms get created, with proper language. + $this->drush('devel-generate-terms', [10], [ + 'kill' => NULL, + 'bundles' => $this->vocabulary->id(), + 'languages' => 'fr', + ]); + $term = Term::load(60); + $this->assertEquals($term->language()->getId(), 'fr'); + + // Make sure terms gets created, with proper translation. + $this->drush('devel-generate-terms', [10], [ + 'kill' => NULL, + 'bundles' => $this->vocabulary->id(), + 'languages' => 'fr', + 'translations' => 'de', + ]); + $term = Term::load(70); + $this->assertTrue($term->hasTranslation('de')); + $this->assertTrue($term->hasTranslation('fr')); + } + + /** + * Tests generating vocabularies. + */ + public function testDrushGenerateVocabs() { + // Make sure vocabs get created. + $this->drush('devel-generate-vocabs', [5], ['kill' => NULL]); + $vocabs = Vocabulary::loadMultiple(); + $this->assertGreaterThan(4, count($vocabs)); + $vocab = array_pop($vocabs); + $this->assertNotEmpty($vocab); + } + + /** + * Tests generating menus. + */ + public function testDrushGenerateMenus() { + // Make sure menus, and with correct properties. + $this->drush('devel-generate-menus', [1, 5], ['kill' => NULL]); + $menus = Menu::loadMultiple(); + foreach ($menus as $menu) { + if (strstr($menu->id(), 'devel-') !== FALSE) { + // We have a menu that we created. + break; + } + } + $link = MenuLinkContent::load(5); + $this->assertEquals($menu->id(), $link->getMenuName()); + } + + /** + * Tests generating content. + */ + public function testDrushGenerateContent() { + // Generate content using the minimum parameters. + $this->drush('devel-generate-content', [21]); + $node = Node::load(21); + $this->assertNotEmpty($node); + + // Make sure articles get comments. Only one third of articles will have + // comment status 'open' and therefore the ability to receive a comment. + // However generating 30 articles will give the likelyhood of test failure + // (i.e. no article gets a comment) as 2/3 ^ 30 = 0.00052% or 1 in 191751. + $this->drush('devel-generate-content', [30, 9], ['kill' => NULL, 'bundles' => 'article']); + $comment = Comment::load(1); + $this->assertNotEmpty($comment); + + // Generate content with a higher number that triggers batch running. + $this->drush('devel-generate-content', [55], ['kill' => NULL]); + $nodes = \Drupal::entityQuery('node')->execute(); + $this->assertCount(55, $nodes); + $messages = $this->getErrorOutput(); + $this->assertStringContainsStringIgnoringCase('Finished 55 elements created successfully.', $messages, 'devel-generate-content batch ending message not found'); + + // Generate content with specified language. + $this->drush('devel-generate-content', [10], ['kill' => NULL, 'languages' => 'fr']); + $nodes = \Drupal::entityQuery('node')->execute(); + $node = Node::load(end($nodes)); + $this->assertEquals($node->language()->getId(), 'fr'); + + // Generate content with translations. + $this->drush('devel-generate-content', [18], [ + 'kill' => NULL, + 'languages' => 'fr', + 'translations' => 'de', + ]); + // Only articles are enabled for translations. + $articles = \Drupal::entityQuery('node')->condition('type', 'article')->execute(); + $pages = \Drupal::entityQuery('node')->condition('type', 'page')->execute(); + $this->assertCount(18, $articles + $pages); + // Check that the last article has 'de' and 'fr' but no 'ca' translation. + $node = Node::load(end($articles)); + $this->assertTrue($node->hasTranslation('de')); + $this->assertTrue($node->hasTranslation('fr')); + $this->assertFalse($node->hasTranslation('ca')); + + // Generate just page content with option --add-type-label. + // Note: Use the -v verbose option to get the ending message shown when not + // generating enough to trigger batch mode. + // @todo Remove -v when the messages are shown for both run types. + $this->drush('devel-generate-content -v', [9], [ + 'kill' => NULL, + 'bundles' => 'page', + 'add-type-label' => NULL, + ]); + // Count the page nodes. + $nodes = \Drupal::entityQuery('node')->condition('type', 'page')->execute(); + $this->assertCount(9, $nodes); + $messages = $this->getErrorOutput(); + $this->assertStringContainsStringIgnoringCase('Created 9 nodes', $messages, 'batch end message not found'); + // Load the final node and verify that the title starts with the label. + $node = Node::load(end($nodes)); + $this->assertEquals('Basic Page - ', substr($node->title->value, 0, 13)); + + // Generate articles with a specified users. + $this->drush('devel-generate-content -v', [10], [ + 'kill' => NULL, + 'bundles' => 'article', + 'authors' => '2', + ]); + // Count the nodes assigned to user 2. We have two other users (0 and 1) so + // if the code was broken and users were assigned randomly the chance that + // this fauly would be detected is 1 - (1/3 ** 10) = 99.998%. + $nodes = \Drupal::entityQuery('node')->condition('type', 'article')->condition('uid', ['2'], 'IN')->execute(); + $this->assertCount(10, $nodes); + + } + + /** + * Tests generating media. + */ + public function testDrushGenerateMedia() { + // Create two media types. + $media_type1 = $this->createMediaType('image'); + $media_type2 = $this->createMediaType('audio_file'); + // Make sure media items gets created with batch process. + $this->drush('devel-generate-media', [53], ['kill' => NULL]); + $this->assertCount(53, \Drupal::entityQuery('media')->execute()); + $messages = $this->getErrorOutput(); + $this->assertStringContainsStringIgnoringCase('Finished 53 elements created successfully.', $messages, 'devel-generate-media batch ending message not found'); + + // Test also with a non-batch process. We're testing also --kill here. + $this->drush('devel-generate-media', [7], [ + 'media-types' => $media_type1->id() . ',' . $media_type2->id(), + 'kill' => NULL, + ]); + $this->assertCount(7, \Drupal::entityQuery('media')->execute()); + } + +} diff --git a/web/modules/contrib/devel/devel_generate/tests/src/Traits/DevelGenerateSetupTrait.php b/web/modules/contrib/devel/devel_generate/tests/src/Traits/DevelGenerateSetupTrait.php new file mode 100644 index 00000000..d388011a --- /dev/null +++ b/web/modules/contrib/devel/devel_generate/tests/src/Traits/DevelGenerateSetupTrait.php @@ -0,0 +1,109 @@ +drupalCreateUser([ + 'administer devel_generate', + 'access devel information', + 'access content overview', + ]); + $this->drupalLogin($admin_user); + + $entity_type_manager = $this->container->get('entity_type.manager'); + // Create Basic page and Article node types. + if ($this->profile != 'standard') { + $this->drupalCreateContentType(['type' => 'page', 'name' => 'Basic Page']); + $this->drupalCreateContentType(['type' => 'article', 'name' => 'Article']); + $this->addDefaultCommentField('node', 'article'); + } + + // Enable translation for article content type (but not for page). + \Drupal::service('content_translation.manager')->setEnabled('node', 'article', TRUE); + // Create languages for generated translations. + ConfigurableLanguage::createFromLangcode('ca')->save(); + ConfigurableLanguage::createFromLangcode('de')->save(); + ConfigurableLanguage::createFromLangcode('fr')->save(); + + // Creating a vocabulary to associate taxonomy terms generated. + $this->vocabulary = Vocabulary::create([ + 'name' => 'Vocab 1 ' . $this->randomString(15), + 'description' => $this->randomMachineName(), + 'vid' => 'vocab_1_' . mb_strtolower($this->randomMachineName()), + 'langcode' => Language::LANGCODE_NOT_SPECIFIED, + ]); + $this->vocabulary->save(); + // Enable translation for terms in this vocabulary. + \Drupal::service('content_translation.manager')->setEnabled('taxonomy_term', $this->vocabulary->id(), TRUE); + + // Creates a field of an entity reference field storage on article. + $field_name = 'taxonomy_' . $this->vocabulary->id(); + + $handler_settings = [ + 'target_bundles' => [ + $this->vocabulary->id() => $this->vocabulary->id(), + ], + 'auto_create' => TRUE, + ]; + $this->createEntityReferenceField('node', 'article', $field_name, NULL, 'taxonomy_term', 'default', $handler_settings, FieldStorageDefinitionInterface::CARDINALITY_UNLIMITED); + + $entity_type_manager->getStorage('entity_form_display') + ->load('node.article.default') + ->setComponent($field_name, [ + 'type' => 'options_select', + ]) + ->save(); + + $entity_type_manager->getStorage('entity_view_display') + ->load('node.article.default') + ->setComponent($field_name, [ + 'type' => 'entity_reference_label', + ]) + ->save(); + + // Create the second vocabulary. + $this->vocabulary2 = Vocabulary::create([ + 'name' => 'Vocab 2 ' . $this->randomString(15), + 'vid' => 'vocab_2_' . mb_strtolower($this->randomMachineName()), + 'langcode' => Language::LANGCODE_NOT_SPECIFIED, + ]); + $this->vocabulary2->save(); + + } + +} diff --git a/web/modules/contrib/devel/devel_generate/tests/src/Unit/DevelGenerateManagerTest.php b/web/modules/contrib/devel/devel_generate/tests/src/Unit/DevelGenerateManagerTest.php new file mode 100644 index 00000000..ca9bcd30 --- /dev/null +++ b/web/modules/contrib/devel/devel_generate/tests/src/Unit/DevelGenerateManagerTest.php @@ -0,0 +1,86 @@ + [ + 'id' => 'devel_generate_example', + 'class' => 'Drupal\devel_generate_example\Plugin\DevelGenerate\ExampleDevelGenerate', + 'url' => 'devel_generate_example', + 'dependencies' => [], + ], + ]; + + /** + * {@inheritdoc} + */ + protected function setUp() { + parent::setUp(); + // Mock a Discovery object to replace AnnotationClassDiscovery. + $this->discovery = $this->createMock('Drupal\Component\Plugin\Discovery\DiscoveryInterface'); + $this->discovery->expects($this->any()) + ->method('getDefinitions') + ->will($this->returnValue($this->definitions)); + + } + + /** + * Test creating an instance of the DevelGenerateManager. + */ + public function testCreateInstance() { + $namespaces = new \ArrayObject(['Drupal\devel_generate_example' => realpath(dirname(__FILE__) . '/../../../modules/devel_generate_example/lib')]); + $cache_backend = $this->createMock('Drupal\Core\Cache\CacheBackendInterface'); + + $module_handler = $this->createMock('Drupal\Core\Extension\ModuleHandlerInterface'); + $manager = new TestDevelGeneratePluginManager($namespaces, $cache_backend, $module_handler); + $manager->setDiscovery($this->discovery); + + $example_instance = $manager->createInstance('devel_generate_example'); + $plugin_def = $example_instance->getPluginDefinition(); + + $this->assertInstanceOf('Drupal\devel_generate_example\Plugin\DevelGenerate\ExampleDevelGenerate', $example_instance); + $this->assertArrayHasKey('url', $plugin_def); + $this->assertTrue($plugin_def['url'] == 'devel_generate_example'); + } + +} + +/** + * Provides a testing version of DevelGeneratePluginManager with an empty + * constructor. + */ +class TestDevelGeneratePluginManager extends DevelGeneratePluginManager { + + /** + * Sets the discovery for the manager. + * + * @param \Drupal\Component\Plugin\Discovery\DiscoveryInterface $discovery + * The discovery object. + */ + public function setDiscovery(DiscoveryInterface $discovery) { + $this->discovery = $discovery; + } + +} diff --git a/web/modules/contrib/devel/drush.services.yml b/web/modules/contrib/devel/drush.services.yml new file mode 100644 index 00000000..4b442628 --- /dev/null +++ b/web/modules/contrib/devel/drush.services.yml @@ -0,0 +1,6 @@ +services: + devel.commands: + class: Drupal\devel\Commands\DevelCommands + arguments: ['@token', '@service_container', '@event_dispatcher', '@module_handler'] + tags: + - { name: drush.command } diff --git a/web/modules/contrib/devel/icons/bebebe/cog.svg b/web/modules/contrib/devel/icons/bebebe/cog.svg new file mode 100644 index 00000000..5f57a392 --- /dev/null +++ b/web/modules/contrib/devel/icons/bebebe/cog.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/web/modules/contrib/devel/icons/ffffff/cog.svg b/web/modules/contrib/devel/icons/ffffff/cog.svg new file mode 100644 index 00000000..63b300e3 --- /dev/null +++ b/web/modules/contrib/devel/icons/ffffff/cog.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/web/modules/contrib/devel/icons/folder.png b/web/modules/contrib/devel/icons/folder.png new file mode 100644 index 00000000..ba8e7a80 Binary files /dev/null and b/web/modules/contrib/devel/icons/folder.png differ diff --git a/web/modules/contrib/devel/phpcs.xml.dist b/web/modules/contrib/devel/phpcs.xml.dist new file mode 100644 index 00000000..f88da0b6 --- /dev/null +++ b/web/modules/contrib/devel/phpcs.xml.dist @@ -0,0 +1,41 @@ + + + . + + + + + + + + + + + + + + + + + _ignore + \.patch + interdif + + + + + + \.md + + + + Commands\.php + + + + + + 0 + + + diff --git a/web/modules/contrib/devel/src/Annotation/DevelDumper.php b/web/modules/contrib/devel/src/Annotation/DevelDumper.php new file mode 100644 index 00000000..40fe0279 --- /dev/null +++ b/web/modules/contrib/devel/src/Annotation/DevelDumper.php @@ -0,0 +1,37 @@ +token = $token; + $this->container = $container; + $this->eventDispatcher = $eventDispatcher; + $this->moduleHandler = $moduleHandler; + } + + /** + * @return \Drupal\Core\Extension\ModuleHandlerInterface + * The moduleHandler. + */ + public function getModuleHandler() { + return $this->moduleHandler; + } + + /** + * @return mixed + * The eventDispatcher. + */ + public function getEventDispatcher() { + return $this->eventDispatcher; + } + + /** + * @return mixed + * The container. + */ + public function getContainer() { + return $this->container; + } + + /** + * @return \Drupal\Core\Utility\Token + * The token. + */ + public function getToken() { + return $this->token; + } + + /** + * Uninstall, and Install modules. + * + * @command devel:reinstall + * @aliases dre,devel-reinstall + * @allow-additional-options pm-uninstall,pm-enable + * + * @param string $modules + * A comma-separated list of module names. + */ + public function reinstall($modules) { + $modules = StringUtils::csvToArray($modules); + + $modules_str = implode(',', $modules); + $process = $this->processManager()->drush($this->siteAliasManager()->getSelf(), 'pm:uninstall', [$modules_str]); + $process->mustRun(); + $process = $this->processManager()->drush($this->siteAliasManager()->getSelf(), 'pm:enable', [$modules_str]); + $process->mustRun(); + } + + /** + * List implementations of a given hook and optionally edit one. + * + * @command devel:hook + * + * @param string $hook + * The name of the hook to explore. + * @param string $implementation + * The name of the implementation to edit. Usually omitted. + * + * @usage devel-hook cron + * List implementations of hook_cron(). + * @aliases fnh,fn-hook,hook,devel-hook + * @optionset_get_editor + */ + public function hook($hook, $implementation) { + // Get implementations in the .install files as well. + include_once './core/includes/install.inc'; + drupal_load_updates(); + $info = $this->codeLocate($implementation . "_$hook"); + $exec = self::getEditor(); + $cmd = sprintf($exec, Escape::shellArg($info['file'])); + $process = $this->processManager()->shell($cmd); + $process->setTty(TRUE); + $process->mustRun(); + } + + /** + * @hook interact hook + */ + public function hookInteract(Input $input, Output $output) { + if (!$input->getArgument('implementation')) { + if ($hook_implementations = $this->getModuleHandler()->getImplementations($input->getArgument('hook'))) { + if (!$choice = $this->io()->choice('Enter the number of the hook implementation you wish to view.', array_combine($hook_implementations, $hook_implementations))) { + throw new UserAbortException(); + } + $input->setArgument('implementation', $choice); + } + else { + throw new \Exception(dt('No implementations')); + } + } + } + + /** + * List implementations of a given event and optionally edit one. + * + * @command devel:event + * + * @param string $event + * The name of the event to explore. If omitted, a list of events is shown. + * @param string $implementation + * The name of the implementation to show. Usually omitted. + * + * @usage devel-event + * Pick a Kernel event, then pick an implementation, and then view its + * source code. + * @usage devel-event kernel.terminate + * Pick a terminate subscribers implementation and view its source code. + * @aliases fne,fn-event,event + */ + public function event($event, $implementation) { + $info = $this->codeLocate($implementation); + $exec = self::getEditor(); + $cmd = sprintf($exec, Escape::shellArg($info['file'])); + $process = $this->processManager()->shell($cmd); + $process->setTty(TRUE); + $process->mustRun(); + } + + /** + * @hook interact devel:event + */ + public function interactEvent(Input $input, Output $output) { + $dispatcher = $this->getEventDispatcher(); + $event = $input->getArgument('event'); + if (!$event) { + // @todo Expand this list. + $events = [ + 'kernel.controller', + 'kernel.exception', + 'kernel.request', + 'kernel.response', + 'kernel.terminate', + 'kernel.view', + ]; + $events = array_combine($events, $events); + if (!$event = $this->io()->choice('Enter the event you wish to explore.', $events)) { + throw new UserAbortException(); + } + $input->setArgument('event', $event); + } + if ($implementations = $dispatcher->getListeners($event)) { + foreach ($implementations as $implementation) { + $callable = get_class($implementation[0]) . '::' . $implementation[1]; + $choices[$callable] = $callable; + } + if (!$choice = $this->io()->choice('Enter the number of the implementation you wish to view.', $choices)) { + throw new UserAbortException(); + } + $input->setArgument('implementation', $choice); + } + else { + throw new \Exception(dt('No implementations.')); + } + } + + /** + * List available tokens. + * + * @command devel:token + * @aliases token,devel-token + * @field-labels + * group: Group + * token: Token + * name: Name + * @default-fields group,token,name + * + * @return \Consolidation\OutputFormatters\StructuredData\RowsOfFields + * The tokens structured in a RowsOfFields object. + */ + public function token($options = ['format' => 'table']) { + $all = $this->getToken()->getInfo(); + foreach ($all['tokens'] as $group => $tokens) { + foreach ($tokens as $key => $token) { + $rows[] = [ + 'group' => $group, + 'token' => $key, + 'name' => $token['name'], + ]; + } + } + return new RowsOfFields($rows); + } + + /** + * Generate a Universally Unique Identifier (UUID). + * + * @command devel:uuid + * @aliases uuid,devel-uuid + * @usage drush devel-uuid + * + * @return string + * The generated uuid. + */ + public function uuid() { + $uuid = new Php(); + return $uuid->generate(); + } + + /** + * Get source code line for specified function or method. + */ + public function codeLocate($function_name) { + // Get implementations in the .install files as well. + include_once './core/includes/install.inc'; + drupal_load_updates(); + + if (strpos($function_name, '::') === FALSE) { + if (!function_exists($function_name)) { + throw new \Exception(dt('Function not found')); + } + $reflect = new \ReflectionFunction($function_name); + } + else { + list($class, $method) = explode('::', $function_name); + if (!method_exists($class, $method)) { + throw new \Exception(dt('Method not found')); + } + $reflect = new \ReflectionMethod($class, $method); + } + return [ + 'file' => $reflect->getFileName(), + 'startline' => $reflect->getStartLine(), + 'endline' => $reflect->getEndLine(), + ]; + + } + + /** + * Get a list of available container services. + * + * @command devel:services + * + * @param string $prefix + * Optional prefix to filter the service list by. + * @param array $options + * An array of options (is this used?) + * + * @aliases devel-container-services,dcs,devel-services + * @usage drush devel-services + * Gets a list of all available container services + * @usage drush dcs plugin.manager + * Get all services containing "plugin.manager" + * + * @return array + * The container service ids. + */ + public function services($prefix = NULL, array $options = ['format' => 'yaml']) { + $container = $this->getContainer(); + + // Get a list of all available service IDs. + $services = $container->getServiceIds(); + + // If there is a prefix, try to find matches. + if (isset($prefix)) { + $services = preg_grep("/$prefix/", $services); + } + + if (empty($services)) { + throw new \Exception(dt('No container services found.')); + } + + sort($services); + return $services; + } + +} diff --git a/web/modules/contrib/devel/src/Controller/ContainerInfoController.php b/web/modules/contrib/devel/src/Controller/ContainerInfoController.php new file mode 100644 index 00000000..9aac792d --- /dev/null +++ b/web/modules/contrib/devel/src/Controller/ContainerInfoController.php @@ -0,0 +1,257 @@ +kernel = $drupalKernel; + $this->dumper = $dumper; + } + + /** + * {@inheritdoc} + */ + public static function create(ContainerInterface $container) { + return new static( + $container->get('kernel'), + $container->get('devel.dumper') + ); + } + + /** + * Builds the services overview page. + * + * @return array + * A render array as expected by the renderer. + */ + public function serviceList() { + $headers = [ + $this->t('ID'), + $this->t('Class'), + $this->t('Alias'), + $this->t('Operations'), + ]; + + $rows = []; + + if ($container = $this->kernel->getCachedContainerDefinition()) { + foreach ($container['services'] as $service_id => $definition) { + $service = unserialize($definition); + + $row['id'] = [ + 'data' => $service_id, + 'filter' => TRUE, + ]; + $row['class'] = [ + 'data' => isset($service['class']) ? $service['class'] : '', + 'filter' => TRUE, + ]; + $row['alias'] = [ + 'data' => array_search($service_id, $container['aliases']) ?: '', + 'filter' => TRUE, + ]; + $row['operations']['data'] = [ + '#type' => 'operations', + '#links' => [ + 'devel' => [ + 'title' => $this->t('Devel'), + 'url' => Url::fromRoute('devel.container_info.service.detail', ['service_id' => $service_id]), + 'attributes' => [ + 'class' => ['use-ajax'], + 'data-dialog-type' => 'modal', + 'data-dialog-options' => Json::encode([ + 'width' => 700, + 'minHeight' => 500, + ]), + ], + ], + ], + ]; + + $rows[$service_id] = $row; + } + + ksort($rows); + } + + $output['services'] = [ + '#type' => 'devel_table_filter', + '#filter_label' => $this->t('Search'), + '#filter_placeholder' => $this->t('Enter service id, alias or class'), + '#filter_description' => $this->t('Enter a part of the service id, service alias or class to filter by.'), + '#header' => $headers, + '#rows' => $rows, + '#empty' => $this->t('No services found.'), + '#sticky' => TRUE, + '#attributes' => [ + 'class' => ['devel-service-list'], + ], + ]; + + return $output; + } + + /** + * Returns a render array representation of the service. + * + * @param string $service_id + * The ID of the service to retrieve. + * + * @return array + * A render array containing the service detail. + * + * @throws \Symfony\Component\HttpKernel\Exception\NotFoundHttpException + * If the requested service is not defined. + */ + public function serviceDetail($service_id) { + $instance = $this->container->get($service_id, ContainerInterface::NULL_ON_INVALID_REFERENCE); + if ($instance === NULL) { + throw new NotFoundHttpException(); + } + + $output = []; + + if ($cached_definitions = $this->kernel->getCachedContainerDefinition()) { + // Tries to retrieve the service definition from the kernel's cached + // container definition. + if (isset($cached_definitions['services'][$service_id])) { + $definition = unserialize($cached_definitions['services'][$service_id]); + + // If the service has an alias add it to the definition. + if ($alias = array_search($service_id, $cached_definitions['aliases'])) { + $definition['alias'] = $alias; + } + + $output['definition'] = $this->dumper->exportAsRenderable($definition, $this->t('Computed Definition')); + } + } + + $output['instance'] = $this->dumper->exportAsRenderable($instance, $this->t('Instance')); + + return $output; + } + + /** + * Builds the parameters overview page. + * + * @return array + * A render array as expected by the renderer. + */ + public function parameterList() { + $headers = [ + $this->t('Name'), + $this->t('Operations'), + ]; + + $rows = []; + + if ($container = $this->kernel->getCachedContainerDefinition()) { + foreach ($container['parameters'] as $parameter_name => $definition) { + $row['name'] = [ + 'data' => $parameter_name, + 'filter' => TRUE, + ]; + $row['operations']['data'] = [ + '#type' => 'operations', + '#links' => [ + 'devel' => [ + 'title' => $this->t('Devel'), + 'url' => Url::fromRoute('devel.container_info.parameter.detail', ['parameter_name' => $parameter_name]), + 'attributes' => [ + 'class' => ['use-ajax'], + 'data-dialog-type' => 'modal', + 'data-dialog-options' => Json::encode([ + 'width' => 700, + 'minHeight' => 500, + ]), + ], + ], + ], + ]; + + $rows[$parameter_name] = $row; + } + + ksort($rows); + } + + $output['parameters'] = [ + '#type' => 'devel_table_filter', + '#filter_label' => $this->t('Search'), + '#filter_placeholder' => $this->t('Enter parameter name'), + '#filter_description' => $this->t('Enter a part of the parameter name to filter by.'), + '#header' => $headers, + '#rows' => $rows, + '#empty' => $this->t('No parameters found.'), + '#sticky' => TRUE, + '#attributes' => [ + 'class' => ['devel-parameter-list'], + ], + ]; + + return $output; + } + + /** + * Returns a render array representation of the parameter value. + * + * @param string $parameter_name + * The name of the parameter to retrieve. + * + * @return array + * A render array containing the parameter value. + * + * @throws \Symfony\Component\HttpKernel\Exception\NotFoundHttpException + * If the requested parameter is not defined. + */ + public function parameterDetail($parameter_name) { + try { + $parameter = $this->container->getParameter($parameter_name); + } + catch (ParameterNotFoundException $e) { + throw new NotFoundHttpException(); + } + + return $this->dumper->exportAsRenderable($parameter); + } + +} diff --git a/web/modules/contrib/devel/src/Controller/DevelController.php b/web/modules/contrib/devel/src/Controller/DevelController.php new file mode 100644 index 00000000..d57a07f4 --- /dev/null +++ b/web/modules/contrib/devel/src/Controller/DevelController.php @@ -0,0 +1,226 @@ +dumper = $dumper; + $this->entityTypeBundleInfo = $entity_type_bundle_info; + $this->fieldTypeManager = $field_type_manager; + $this->formatterPluginManager = $formatter_plugin_manager; + $this->widgetPluginManager = $widget_plugin_manager; + } + + /** + * {@inheritdoc} + */ + public static function create(ContainerInterface $container) { + return new static( + $container->get('devel.dumper'), + $container->get('entity_type.bundle.info'), + $container->get('plugin.manager.field.field_type'), + $container->get('plugin.manager.field.formatter'), + $container->get('plugin.manager.field.widget') + ); + } + + /** + * Clears all caches, then redirects to the previous page. + */ + public function cacheClear() { + drupal_flush_all_caches(); + $this->messenger()->addMessage($this->t('Cache cleared.')); + return $this->redirect(''); + } + + /** + * Theme registry. + * + * @return array + * The complete theme registry as renderable. + */ + public function themeRegistry() { + $hooks = theme_get_registry(); + ksort($hooks); + return $this->dumper->exportAsRenderable($hooks); + } + + /** + * Builds the fields info overview page. + * + * @return array + * Array of page elements to render. + */ + public function fieldInfoPage() { + $fields = FieldStorageConfig::loadMultiple(); + ksort($fields); + $output['fields'] = $this->dumper->exportAsRenderable($fields, $this->t('Fields')); + + $field_instances = FieldConfig::loadMultiple(); + ksort($field_instances); + $output['instances'] = $this->dumper->exportAsRenderable($field_instances, $this->t('Instances')); + + $bundles = $this->entityTypeBundleInfo->getAllBundleInfo(); + ksort($bundles); + $output['bundles'] = $this->dumper->exportAsRenderable($bundles, $this->t('Bundles')); + + $field_types = $this->fieldTypeManager->getUiDefinitions(); + ksort($field_types); + $output['field_types'] = $this->dumper->exportAsRenderable($field_types, $this->t('Field types')); + + $formatter_types = $this->formatterPluginManager->getDefinitions(); + ksort($formatter_types); + $output['formatter_types'] = $this->dumper->exportAsRenderable($formatter_types, $this->t('Formatter types')); + + $widget_types = $this->widgetPluginManager->getDefinitions(); + ksort($widget_types); + $output['widget_types'] = $this->dumper->exportAsRenderable($widget_types, $this->t('Widget types')); + + return $output; + } + + /** + * Builds the state variable overview page. + * + * @return array + * Array of page elements to render. + */ + public function stateSystemPage() { + $can_edit = $this->currentUser()->hasPermission('administer site configuration'); + + $header = [ + 'name' => $this->t('Name'), + 'value' => $this->t('Value'), + ]; + + if ($can_edit) { + $header['edit'] = $this->t('Operations'); + } + + $rows = []; + // State class doesn't have getAll method so we get all states from the + // KeyValueStorage. + foreach ($this->keyValue('state')->getAll() as $state_name => $state) { + $rows[$state_name] = [ + 'name' => [ + 'data' => $state_name, + 'class' => 'table-filter-text-source', + ], + 'value' => [ + 'data' => $this->dumper->export($state), + ], + ]; + + if ($can_edit) { + $operations['edit'] = [ + 'title' => $this->t('Edit'), + 'url' => Url::fromRoute('devel.system_state_edit', ['state_name' => $state_name]), + ]; + $rows[$state_name]['edit'] = [ + 'data' => ['#type' => 'operations', '#links' => $operations], + ]; + } + } + + $output['states'] = [ + '#type' => 'devel_table_filter', + '#filter_label' => $this->t('Search'), + '#filter_placeholder' => $this->t('Enter state name'), + '#filter_title' => $this->t('Enter a part of the state name to filter by.'), + '#header' => $header, + '#rows' => $rows, + '#empty' => $this->t('No state variables found.'), + '#attributes' => [ + 'class' => ['devel-state-list'], + ], + ]; + + return $output; + } + + /** + * Builds the session overview page. + * + * @return array + * Array of page elements to render. + */ + public function session() { + $output['description'] = [ + '#markup' => '

' . $this->t('Here are the contents of your $_SESSION variable.') . '

', + ]; + $output['session'] = [ + '#type' => 'table', + '#header' => [$this->t('Session name'), $this->t('Session ID')], + '#rows' => [[session_name(), session_id()]], + '#empty' => $this->t('No session available.'), + ]; + $output['data'] = $this->dumper->exportAsRenderable($_SESSION); + + return $output; + } + +} diff --git a/web/modules/contrib/devel/src/Controller/ElementInfoController.php b/web/modules/contrib/devel/src/Controller/ElementInfoController.php new file mode 100644 index 00000000..14ae3058 --- /dev/null +++ b/web/modules/contrib/devel/src/Controller/ElementInfoController.php @@ -0,0 +1,145 @@ +elementInfo = $element_info; + $this->dumper = $dumper; + } + + /** + * {@inheritdoc} + */ + public static function create(ContainerInterface $container) { + return new static( + $container->get('element_info'), + $container->get('devel.dumper') + ); + } + + /** + * Builds the element overview page. + * + * @return array + * A render array as expected by the renderer. + */ + public function elementList() { + $headers = [ + $this->t('Name'), + $this->t('Provider'), + $this->t('Class'), + $this->t('Operations'), + ]; + + $rows = []; + + foreach ($this->elementInfo->getDefinitions() as $element_type => $definition) { + $row['name'] = [ + 'data' => $element_type, + 'filter' => TRUE, + ]; + $row['provider'] = [ + 'data' => $definition['provider'], + 'filter' => TRUE, + ]; + $row['class'] = [ + 'data' => $definition['class'], + 'filter' => TRUE, + ]; + $row['operations']['data'] = [ + '#type' => 'operations', + '#links' => [ + 'devel' => [ + 'title' => $this->t('Devel'), + 'url' => Url::fromRoute('devel.elements_page.detail', ['element_name' => $element_type]), + 'attributes' => [ + 'class' => ['use-ajax'], + 'data-dialog-type' => 'modal', + 'data-dialog-options' => Json::encode([ + 'width' => 700, + 'minHeight' => 500, + ]), + ], + ], + ], + ]; + + $rows[$element_type] = $row; + } + + ksort($rows); + + $output['elements'] = [ + '#type' => 'devel_table_filter', + '#filter_label' => $this->t('Search'), + '#filter_placeholder' => $this->t('Enter element id, provider or class'), + '#filter_description' => $this->t('Enter a part of the element id, provider or class to filter by.'), + '#header' => $headers, + '#rows' => $rows, + '#empty' => $this->t('No elements found.'), + '#sticky' => TRUE, + '#attributes' => [ + 'class' => ['devel-element-list'], + ], + ]; + + return $output; + } + + /** + * Returns a render array representation of the element. + * + * @param string $element_name + * The name of the element to retrieve. + * + * @return array + * A render array containing the element. + * + * @throws \Symfony\Component\HttpKernel\Exception\NotFoundHttpException + * If the requested element is not defined. + */ + public function elementDetail($element_name) { + if (!$element = $this->elementInfo->getDefinition($element_name, FALSE)) { + throw new NotFoundHttpException(); + } + + $element += $this->elementInfo->getInfo($element_name); + return $this->dumper->exportAsRenderable($element, $element_name); + } + +} diff --git a/web/modules/contrib/devel/src/Controller/EntityDebugController.php b/web/modules/contrib/devel/src/Controller/EntityDebugController.php new file mode 100644 index 00000000..f999e458 --- /dev/null +++ b/web/modules/contrib/devel/src/Controller/EntityDebugController.php @@ -0,0 +1,142 @@ +dumper = $dumper; + } + + /** + * {@inheritdoc} + */ + public static function create(ContainerInterface $container) { + return new static($container->get('devel.dumper')); + } + + /** + * Returns the entity type definition of the current entity. + * + * @param \Drupal\Core\Routing\RouteMatchInterface $route_match + * A RouteMatch object. + * + * @return array + * Array of page elements to render. + */ + public function entityTypeDefinition(RouteMatchInterface $route_match) { + $output = []; + + $entity = $this->getEntityFromRouteMatch($route_match); + + if ($entity instanceof EntityInterface) { + $output = $this->dumper->exportAsRenderable($entity->getEntityType()); + } + + return $output; + } + + /** + * Returns the loaded structure of the current entity. + * + * @param \Drupal\Core\Routing\RouteMatchInterface $route_match + * A RouteMatch object. + * + * @return array + * Array of page elements to render. + */ + public function entityLoad(RouteMatchInterface $route_match) { + $output = []; + + $entity = $this->getEntityFromRouteMatch($route_match); + + if ($entity instanceof EntityInterface) { + // Field definitions are lazy loaded and are populated only when needed. + // By calling ::getFieldDefinitions() we are sure that field definitions + // are populated and available in the dump output. + // @see https://www.drupal.org/node/2311557 + if ($entity instanceof FieldableEntityInterface) { + $entity->getFieldDefinitions(); + } + + $output = $this->dumper->exportAsRenderable($entity); + } + + return $output; + } + + /** + * Returns the render structure of the current entity. + * + * @param \Drupal\Core\Routing\RouteMatchInterface $route_match + * A RouteMatch object. + * + * @return array + * Array of page elements to render. + */ + public function entityRender(RouteMatchInterface $route_match) { + $output = []; + + $entity = $this->getEntityFromRouteMatch($route_match); + + if ($entity instanceof EntityInterface) { + $entity_type_id = $entity->getEntityTypeId(); + $view_hook = $entity_type_id . '_view'; + + $build = []; + // If module implements own {entity_type}_view() hook use it, otherwise + // fallback to the entity view builder if available. + if (function_exists($view_hook)) { + $build = $view_hook($entity); + } + elseif ($this->entityTypeManager()->hasHandler($entity_type_id, 'view_builder')) { + $build = $this->entityTypeManager()->getViewBuilder($entity_type_id)->view($entity); + } + + $output = $this->dumper->exportAsRenderable($build); + } + + return $output; + } + + /** + * Retrieves entity from route match. + * + * @param \Drupal\Core\Routing\RouteMatchInterface $route_match + * The route match. + * + * @return \Drupal\Core\Entity\EntityInterface|null + * The entity object as determined from the passed-in route match. + */ + protected function getEntityFromRouteMatch(RouteMatchInterface $route_match) { + $parameter_name = $route_match->getRouteObject()->getOption('_devel_entity_type_id'); + return $route_match->getParameter($parameter_name); + } + +} diff --git a/web/modules/contrib/devel/src/Controller/EntityTypeInfoController.php b/web/modules/contrib/devel/src/Controller/EntityTypeInfoController.php new file mode 100644 index 00000000..42cbee6f --- /dev/null +++ b/web/modules/contrib/devel/src/Controller/EntityTypeInfoController.php @@ -0,0 +1,180 @@ +dumper = $dumper; + $this->entityLastInstalledSchemaRepository = $entityLastInstalledSchemaRepository; + } + + /** + * {@inheritdoc} + */ + public static function create(ContainerInterface $container) { + return new static( + $container->get('devel.dumper'), + $container->get('entity.last_installed_schema.repository') + ); + } + + /** + * Builds the entity types overview page. + * + * @return array + * A render array as expected by the renderer. + */ + public function entityTypeList() { + $headers = [ + $this->t('ID'), + $this->t('Name'), + $this->t('Provider'), + $this->t('Class'), + $this->t('Operations'), + ]; + + $rows = []; + + foreach ($this->entityTypeManager()->getDefinitions() as $entity_type_id => $entity_type) { + $row['id'] = [ + 'data' => $entity_type->id(), + 'filter' => TRUE, + ]; + $row['name'] = [ + 'data' => $entity_type->getLabel(), + 'filter' => TRUE, + ]; + $row['provider'] = [ + 'data' => $entity_type->getProvider(), + 'filter' => TRUE, + ]; + $row['class'] = [ + 'data' => $entity_type->getClass(), + 'filter' => TRUE, + ]; + $row['operations']['data'] = [ + '#type' => 'operations', + '#links' => [ + 'devel' => [ + 'title' => $this->t('Devel'), + 'url' => Url::fromRoute('devel.entity_info_page.detail', ['entity_type_id' => $entity_type_id]), + 'attributes' => [ + 'class' => ['use-ajax'], + 'data-dialog-type' => 'modal', + 'data-dialog-options' => Json::encode([ + 'width' => 700, + 'minHeight' => 500, + ]), + ], + ], + 'fields' => [ + 'title' => $this->t('Fields'), + 'url' => Url::fromRoute('devel.entity_info_page.fields', ['entity_type_id' => $entity_type_id]), + 'attributes' => [ + 'class' => ['use-ajax'], + 'data-dialog-type' => 'modal', + 'data-dialog-options' => Json::encode([ + 'width' => 700, + 'minHeight' => 500, + ]), + ], + ], + ], + ]; + + $rows[$entity_type_id] = $row; + } + + ksort($rows); + + $output['entities'] = [ + '#type' => 'devel_table_filter', + '#filter_label' => $this->t('Search'), + '#filter_placeholder' => $this->t('Enter entity type id, provider or class'), + '#filter_description' => $this->t('Enter a part of the entity type id, provider or class to filter by.'), + '#header' => $headers, + '#rows' => $rows, + '#empty' => $this->t('No entity types found.'), + '#sticky' => TRUE, + '#attributes' => [ + 'class' => ['devel-entity-type-list'], + ], + ]; + + return $output; + } + + /** + * Returns a render array representation of the entity type. + * + * @param string $entity_type_id + * The name of the entity type to retrieve. + * + * @return array + * A render array containing the entity type. + * + * @throws \Symfony\Component\HttpKernel\Exception\NotFoundHttpException + * If the requested entity type is not defined. + */ + public function entityTypeDetail($entity_type_id) { + if (!$entity_type = $this->entityTypeManager()->getDefinition($entity_type_id, FALSE)) { + throw new NotFoundHttpException(); + } + + return $this->dumper->exportAsRenderable($entity_type, $entity_type_id); + } + + /** + * Returns a render array representation of the entity type field definitions. + * + * @param string $entity_type_id + * The name of the entity type to retrieve. + * + * @return array + * A render array containing the entity type field definitions. + * + * @throws \Symfony\Component\HttpKernel\Exception\NotFoundHttpException + * If the requested entity type is not defined. + */ + public function entityTypeFields($entity_type_id) { + if (!$this->entityTypeManager()->getDefinition($entity_type_id, FALSE)) { + throw new NotFoundHttpException(); + } + + $field_storage_definitions = $this->entityLastInstalledSchemaRepository->getLastInstalledFieldStorageDefinitions($entity_type_id); + return $this->dumper->exportAsRenderable($field_storage_definitions, $entity_type_id); + } + +} diff --git a/web/modules/contrib/devel/src/Controller/EventInfoController.php b/web/modules/contrib/devel/src/Controller/EventInfoController.php new file mode 100644 index 00000000..3f6a251a --- /dev/null +++ b/web/modules/contrib/devel/src/Controller/EventInfoController.php @@ -0,0 +1,121 @@ +eventDispatcher = $event_dispatcher; + } + + /** + * {@inheritdoc} + */ + public static function create(ContainerInterface $container) { + return new static( + $container->get('event_dispatcher') + ); + } + + /** + * Builds the events overview page. + * + * @return array + * A render array as expected by the renderer. + */ + public function eventList() { + $headers = [ + 'name' => [ + 'data' => $this->t('Event Name'), + 'class' => 'visually-hidden', + ], + 'callable' => $this->t('Callable'), + 'priority' => $this->t('Priority'), + ]; + + $event_listeners = $this->eventDispatcher->getListeners(); + ksort($event_listeners); + + $rows = []; + + foreach ($event_listeners as $event_name => $listeners) { + + $rows[][] = [ + 'data' => $event_name, + 'class' => ['devel-event-name-header'], + 'filter' => TRUE, + 'colspan' => '3', + 'header' => TRUE, + ]; + + foreach ($listeners as $listener) { + $row['name'] = [ + 'data' => $event_name, + 'class' => ['visually-hidden'], + 'filter' => TRUE, + ]; + $row['class'] = [ + 'data' => $this->resolveCallableName($listener), + ]; + $row['priority'] = [ + 'data' => $this->eventDispatcher->getListenerPriority($event_name, $listener), + ]; + $rows[] = $row; + } + } + + $output['events'] = [ + '#type' => 'devel_table_filter', + '#filter_label' => $this->t('Search'), + '#filter_placeholder' => $this->t('Enter event name'), + '#filter_description' => $this->t('Enter a part of the event name to filter by.'), + '#header' => $headers, + '#rows' => $rows, + '#empty' => $this->t('No events found.'), + '#attributes' => [ + 'class' => ['devel-event-list'], + ], + ]; + + return $output; + } + + /** + * Helper function for resolve callable name. + * + * @param mixed $callable + * The for which resolve the name. Can be either the name of a function + * stored in a string variable, or an object and the name of a method + * within the object. + * + * @return string + * The resolved callable name or an empty string. + */ + protected function resolveCallableName($callable) { + if (is_callable($callable, TRUE, $callable_name)) { + return $callable_name; + } + return ''; + } + +} diff --git a/web/modules/contrib/devel/src/Controller/LayoutInfoController.php b/web/modules/contrib/devel/src/Controller/LayoutInfoController.php new file mode 100644 index 00000000..4fdb3f41 --- /dev/null +++ b/web/modules/contrib/devel/src/Controller/LayoutInfoController.php @@ -0,0 +1,82 @@ +layoutPluginManager = $pluginManagerLayout; + } + + /** + * {@inheritdoc} + */ + public static function create(ContainerInterface $container) { + return new static( + $container->get('plugin.manager.core.layout') + ); + } + + /** + * Builds the Layout Info page. + * + * @return array + * Array of page elements to render. + */ + public function layoutInfoPage() { + $headers = [ + $this->t('Icon'), + $this->t('Label'), + $this->t('Description'), + $this->t('Category'), + $this->t('Regions'), + $this->t('Provider'), + ]; + + $rows = []; + + foreach ($this->layoutPluginManager->getDefinitions() as $layout) { + $rows[] = [ + 'icon' => ['data' => $layout->getIcon()], + 'label' => $layout->getLabel(), + 'description' => $layout->getDescription(), + 'category' => $layout->getCategory(), + 'regions' => implode(', ', $layout->getRegionLabels()), + 'provider' => $layout->getProvider(), + ]; + } + + $output['layouts'] = [ + '#type' => 'table', + '#header' => $headers, + '#rows' => $rows, + '#empty' => $this->t('No layouts available.'), + '#attributes' => [ + 'class' => ['devel-layout-list'], + ], + ]; + + return $output; + } + +} diff --git a/web/modules/contrib/devel/src/Controller/RouteInfoController.php b/web/modules/contrib/devel/src/Controller/RouteInfoController.php new file mode 100644 index 00000000..a87aa5c9 --- /dev/null +++ b/web/modules/contrib/devel/src/Controller/RouteInfoController.php @@ -0,0 +1,195 @@ +routeProvider = $provider; + $this->router = $router; + $this->dumper = $dumper; + } + + /** + * {@inheritdoc} + */ + public static function create(ContainerInterface $container) { + return new static( + $container->get('router.route_provider'), + $container->get('router.no_access_checks'), + $container->get('devel.dumper') + ); + } + + /** + * Builds the routes overview page. + * + * @return array + * A render array as expected by the renderer. + */ + public function routeList() { + $headers = [ + $this->t('Route Name'), + $this->t('Path'), + $this->t('Allowed Methods'), + $this->t('Operations'), + ]; + + $rows = []; + + foreach ($this->routeProvider->getAllRoutes() as $route_name => $route) { + $row['name'] = [ + 'data' => $route_name, + 'filter' => TRUE, + ]; + $row['path'] = [ + 'data' => $route->getPath(), + 'filter' => TRUE, + ]; + $row['methods']['data'] = [ + '#theme' => 'item_list', + '#items' => $route->getMethods(), + '#empty' => $this->t('ANY'), + '#context' => ['list_style' => 'comma-list'], + ]; + + // We cannot resolve routes with dynamic parameters from route path. For + // these routes we pass the route name. + // @see ::routeItem() + if (strpos($route->getPath(), '{') !== FALSE) { + $parameters = ['query' => ['route_name' => $route_name]]; + } + else { + $parameters = ['query' => ['path' => $route->getPath()]]; + } + + $row['operations']['data'] = [ + '#type' => 'operations', + '#links' => [ + 'devel' => [ + 'title' => $this->t('Devel'), + 'url' => Url::fromRoute('devel.route_info.item', [], $parameters), + 'attributes' => [ + 'class' => ['use-ajax'], + 'data-dialog-type' => 'modal', + 'data-dialog-options' => Json::encode([ + 'width' => 700, + 'minHeight' => 500, + ]), + ], + ], + ], + ]; + + $rows[] = $row; + } + + $output['routes'] = [ + '#type' => 'devel_table_filter', + '#filter_label' => $this->t('Search'), + '#filter_placeholder' => $this->t('Enter route name or path'), + '#filter_description' => $this->t('Enter a part of the route name or path to filter by.'), + '#header' => $headers, + '#rows' => $rows, + '#empty' => $this->t('No routes found.'), + '#sticky' => TRUE, + '#attributes' => [ + 'class' => ['devel-route-list'], + ], + ]; + + return $output; + } + + /** + * Returns a render array representation of the route object. + * + * The method tries to resolve the route from the 'path' or the 'route_name' + * query string value if available. If no route is retrieved from the query + * string parameters it fallbacks to the current route. + * + * @param \Symfony\Component\HttpFoundation\Request $request + * The request object. + * @param \Drupal\Core\Routing\RouteMatchInterface $route_match + * The route match. + * + * @return array + * A render array as expected by the renderer. + */ + public function routeDetail(Request $request, RouteMatchInterface $route_match) { + $route = NULL; + + // Get the route object from the path query string if available. + if ($path = $request->query->get('path')) { + try { + $route = $this->router->match($path); + } + catch (\Exception $e) { + $this->messenger()->addWarning($this->t("Unable to load route for url '%url'", ['%url' => $path])); + } + } + + // Get the route object from the route name query string if available and + // the route is not retrieved by path. + if ($route === NULL && $route_name = $request->query->get('route_name')) { + try { + $route = $this->routeProvider->getRouteByName($route_name); + } + catch (\Exception $e) { + $this->messenger()->addWarning($this->t("Unable to load route '%name'", ['%name' => $route_name])); + } + } + + // No route retrieved from path or name specified, get the current route. + if ($route === NULL) { + $route = $route_match->getRouteObject(); + } + + return $this->dumper->exportAsRenderable($route); + } + +} diff --git a/web/modules/contrib/devel/src/Controller/SwitchUserController.php b/web/modules/contrib/devel/src/Controller/SwitchUserController.php new file mode 100644 index 00000000..8f9542ae --- /dev/null +++ b/web/modules/contrib/devel/src/Controller/SwitchUserController.php @@ -0,0 +1,120 @@ +account = $account; + $this->userStorage = $user_storage; + $this->moduleHandler = $module_handler; + $this->sessionManager = $session_manager; + $this->session = $session; + } + + /** + * {@inheritdoc} + */ + public static function create(ContainerInterface $container) { + return new static( + $container->get('current_user'), + $container->get('entity_type.manager')->getStorage('user'), + $container->get('module_handler'), + $container->get('session_manager'), + $container->get('session') + ); + } + + /** + * Switches to a different user. + * + * We don't call session_save_session() because we really want to change + * users. Usually unsafe! + * + * @param string $name + * The username to switch to, or NULL to log out. + * + * @return \Symfony\Component\HttpFoundation\RedirectResponse + * A redirect response object. + * + * @throws \Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException + */ + public function switchUser($name = NULL) { + if (empty($name) || !($account = $this->userStorage->loadByProperties(['name' => $name]))) { + throw new AccessDeniedHttpException(); + } + $account = reset($account); + + // Call logout hooks when switching from original user. + $this->moduleHandler->invokeAll('user_logout', [$this->account]); + + // Regenerate the session ID to prevent against session fixation attacks. + $this->sessionManager->regenerate(); + + // Based off masquarade module as: + // https://www.drupal.org/node/218104 doesn't stick and instead only + // keeps context until redirect. + $this->account->setAccount($account); + $this->session->set('uid', $account->id()); + + // Call all login hooks when switching to masquerading user. + $this->moduleHandler->invokeAll('user_login', [$account]); + + return $this->redirect(''); + } + +} diff --git a/web/modules/contrib/devel/src/DevelDumperBase.php b/web/modules/contrib/devel/src/DevelDumperBase.php new file mode 100644 index 00000000..68458dd5 --- /dev/null +++ b/web/modules/contrib/devel/src/DevelDumperBase.php @@ -0,0 +1,87 @@ +export($input, $name); + } + + /** + * {@inheritdoc} + */ + public function exportAsRenderable($input, $name = NULL) { + return ['#markup' => $this->export($input, $name)]; + } + + /** + * Wrapper for \Drupal\Core\Render\Markup::create(). + * + * @param string $input + * The input string to mark as safe. + * + * @return string + * The unaltered input value. + */ + protected function setSafeMarkup($input) { + return FilteredMarkup::create($input); + } + + /** + * Returns a list of internal functions. + * + * The list returned from this method can be used to exclude internal + * functions from the backtrace output. + * + * @return array + * An array of internal functions. + */ + protected function getInternalFunctions() { + $class_name = get_class($this); + $manager_class_name = DevelDumperManager::class; + + $aliases = [ + [$class_name, 'dump'], + [$class_name, 'export'], + [$manager_class_name, 'dump'], + [$manager_class_name, 'export'], + [$manager_class_name, 'exportAsRenderable'], + [$manager_class_name, 'message'], + [\Drupal\devel\Twig\Extension\Debug::class, 'dump'], + 'dpm', + 'dvm', + 'dsm', + 'dpr', + 'dvr', + 'kpr', + 'dargs', + 'dcp', + 'dfb', + 'dfbt', + 'dpq', + 'kint', + 'ksm', + 'ddebug_backtrace', + 'kdevel_print_object', + 'backtrace_error_handler', + ]; + + return $aliases; + } + +} diff --git a/web/modules/contrib/devel/src/DevelDumperInterface.php b/web/modules/contrib/devel/src/DevelDumperInterface.php new file mode 100644 index 00000000..1236dd0b --- /dev/null +++ b/web/modules/contrib/devel/src/DevelDumperInterface.php @@ -0,0 +1,59 @@ +config = $config_factory->get('devel.settings'); + $this->account = $account; + $this->dumperManager = $dumper_manager; + } + + /** + * Instances a new dumper plugin. + * + * @param string $plugin_id + * (optional) The plugin ID, defaults to NULL. + * + * @return \Drupal\devel\DevelDumperInterface + * Returns the devel dumper plugin instance. + */ + protected function createInstance($plugin_id = NULL) { + if (!$plugin_id || !$this->dumperManager->isPluginSupported($plugin_id)) { + $plugin_id = $this->config->get('devel_dumper'); + } + return $this->dumperManager->createInstance($plugin_id); + } + + /** + * {@inheritdoc} + */ + public function dump($input, $name = NULL, $plugin_id = NULL) { + if ($this->hasAccessToDevelInformation()) { + $this->createInstance($plugin_id)->dump($input, $name); + } + } + + /** + * {@inheritdoc} + */ + public function export($input, $name = NULL, $plugin_id = NULL) { + if ($this->hasAccessToDevelInformation()) { + return $this->createInstance($plugin_id)->export($input, $name); + } + return NULL; + } + + /** + * {@inheritdoc} + */ + public function message($input, $name = NULL, $type = MessengerInterface::TYPE_STATUS, $plugin_id = NULL) { + if ($this->hasAccessToDevelInformation()) { + $output = $this->export($input, $name, $plugin_id); + $this->messenger()->addMessage($output, $type, TRUE); + } + } + + /** + * {@inheritdoc} + */ + public function debug($input, $name = NULL, $plugin_id = NULL) { + $output = $this->createInstance($plugin_id)->export($input, $name) . "\n"; + // The temp directory does vary across multiple simpletest instances. + $file = $this->config->get('debug_logfile'); + if (file_put_contents($file, $output, FILE_APPEND) === FALSE && $this->hasAccessToDevelInformation()) { + $this->messenger()->addError($this->t('Devel was unable to write to %file.', ['%file' => $file])); + return FALSE; + } + } + + /** + * {@inheritdoc} + */ + public function dumpOrExport($input, $name = NULL, $export = TRUE, $plugin_id = NULL) { + if ($this->hasAccessToDevelInformation()) { + $dumper = $this->createInstance($plugin_id); + if ($export) { + return $dumper->export($input, $name); + } + $dumper->dump($input, $name); + } + return NULL; + } + + /** + * {@inheritdoc} + */ + public function exportAsRenderable($input, $name = NULL, $plugin_id = NULL) { + if ($this->hasAccessToDevelInformation()) { + return $this->createInstance($plugin_id)->exportAsRenderable($input, $name); + } + return []; + } + + /** + * Checks whether a user has access to devel information. + * + * @return bool + * TRUE if the user has the permission, FALSE otherwise. + */ + protected function hasAccessToDevelInformation() { + return $this->account && $this->account->hasPermission('access devel information'); + } + +} diff --git a/web/modules/contrib/devel/src/DevelDumperManagerInterface.php b/web/modules/contrib/devel/src/DevelDumperManagerInterface.php new file mode 100644 index 00000000..13259a9f --- /dev/null +++ b/web/modules/contrib/devel/src/DevelDumperManagerInterface.php @@ -0,0 +1,104 @@ +setCacheBackend($cache_backend, 'devel_dumper_plugins'); + $this->alterInfo('devel_dumper_info'); + } + + /** + * {@inheritdoc} + */ + public function processDefinition(&$definition, $plugin_id) { + parent::processDefinition($definition, $plugin_id); + + $definition['supported'] = (bool) call_user_func([$definition['class'], 'checkRequirements']); + } + + /** + * {@inheritdoc} + */ + public function isPluginSupported($plugin_id) { + $definition = $this->getDefinition($plugin_id, FALSE); + return $definition && $definition['supported']; + } + + /** + * {@inheritdoc} + */ + public function createInstance($plugin_id, array $configuration = []) { + if (!$this->isPluginSupported($plugin_id)) { + $plugin_id = $this->getFallbackPluginId($plugin_id); + } + return parent::createInstance($plugin_id, $configuration); + } + + /** + * {@inheritdoc} + */ + public function getFallbackPluginId($plugin_id, array $configuration = []) { + return 'default'; + } + +} diff --git a/web/modules/contrib/devel/src/DevelDumperPluginManagerInterface.php b/web/modules/contrib/devel/src/DevelDumperPluginManagerInterface.php new file mode 100644 index 00000000..8f42ed2a --- /dev/null +++ b/web/modules/contrib/devel/src/DevelDumperPluginManagerInterface.php @@ -0,0 +1,24 @@ + 'devel_table_filter', + * '#filter_label' => $this->t('Search'), + * '#filter_placeholder' => $this->t('Enter element name.'), + * '#filter_description' => $this->t('Enter a part of name to filter by.'), + * '#header' => $headers, + * '#rows' => $rows, + * '#empty' => $this->t('No element found.'), + * ]; + * @endcode + * + * @RenderElement("devel_table_filter") + */ +class ClientSideFilterTable extends RenderElement { + + /** + * {@inheritdoc} + */ + public function getInfo() { + $class = get_class($this); + return [ + '#filter_label' => $this->t('Search'), + '#filter_placeholder' => $this->t('Search'), + '#filter_description' => $this->t('Search'), + '#header' => [], + '#rows' => [], + '#empty' => '', + '#sticky' => FALSE, + '#responsive' => TRUE, + '#attributes' => [], + '#pre_render' => [ + [$class, 'preRenderTable'], + ], + ]; + } + + /** + * Pre-render callback: Assemble render array for the filterable table. + * + * @param array $element + * An associative array containing the properties of the element. + * + * @return array + * The $element with prepared render array ready for rendering. + */ + public static function preRenderTable(array $element) { + $build['#attached']['library'][] = 'devel/devel-table-filter'; + $identifier = Html::getUniqueId('js-devel-table-filter'); + + $build['filters'] = [ + '#type' => 'container', + '#weight' => -1, + '#attributes' => [ + 'class' => ['table-filter', 'js-show'], + ], + ]; + + $build['filters']['name'] = [ + '#type' => 'search', + '#size' => 30, + '#title' => $element['#filter_label'], + '#placeholder' => $element['#filter_placeholder'], + '#attributes' => [ + 'class' => ['table-filter-text'], + 'data-table' => ".$identifier", + 'autocomplete' => 'off', + 'title' => $element['#filter_description'], + ], + ]; + + foreach ($element['#rows'] as &$row) { + foreach ($row as &$cell) { + if (isset($cell['data']) && !empty($cell['filter'])) { + $cell['class'][] = 'table-filter-text-source'; + } + } + } + + $build['table'] = [ + '#type' => 'table', + '#header' => $element['#header'], + '#rows' => $element['#rows'], + '#empty' => $element['#empty'], + '#sticky' => $element['#sticky'], + '#responsive' => $element['#responsive'], + '#attributes' => $element['#attributes'], + ]; + + $build['table']['#attributes']['class'][] = $identifier; + $build['table']['#attributes']['class'][] = 'devel-table-filter'; + + return $build; + } + +} diff --git a/web/modules/contrib/devel/src/EntityTypeInfo.php b/web/modules/contrib/devel/src/EntityTypeInfo.php new file mode 100644 index 00000000..a72417a4 --- /dev/null +++ b/web/modules/contrib/devel/src/EntityTypeInfo.php @@ -0,0 +1,103 @@ +currentUser = $current_user; + } + + /** + * {@inheritdoc} + */ + public static function create(ContainerInterface $container) { + return new static( + $container->get('current_user') + ); + } + + /** + * Adds devel links to appropriate entity types. + * + * This is an alter hook bridge. + * + * @param \Drupal\Core\Entity\EntityTypeInterface[] $entity_types + * The master entity type list to alter. + * + * @see hook_entity_type_alter() + */ + public function entityTypeAlter(array &$entity_types) { + foreach ($entity_types as $entity_type_id => $entity_type) { + if (($entity_type->getFormClass('default') || $entity_type->getFormClass('edit')) && $entity_type->hasLinkTemplate('edit-form')) { + $entity_type->setLinkTemplate('devel-load', "/devel/$entity_type_id/{{$entity_type_id}}"); + } + if ($entity_type->hasViewBuilderClass() && $entity_type->hasLinkTemplate('canonical')) { + $entity_type->setLinkTemplate('devel-render', "/devel/$entity_type_id/{{$entity_type_id}}/render"); + } + if ($entity_type->hasLinkTemplate('devel-render') || $entity_type->hasLinkTemplate('devel-load')) { + $entity_type->setLinkTemplate('devel-definition', "/devel/$entity_type_id/{{$entity_type_id}}/definition"); + } + } + } + + /** + * Adds devel operations on entity that supports it. + * + * @param \Drupal\Core\Entity\EntityInterface $entity + * The entity on which to define an operation. + * + * @return array + * An array of operation definitions. + * + * @see hook_entity_operation() + */ + public function entityOperation(EntityInterface $entity) { + $operations = []; + if ($this->currentUser->hasPermission('access devel information')) { + if ($entity->hasLinkTemplate('devel-load')) { + $operations['devel'] = [ + 'title' => $this->t('Devel'), + 'weight' => 100, + 'url' => $entity->toUrl('devel-load'), + ]; + } + elseif ($entity->hasLinkTemplate('devel-render')) { + $operations['devel'] = [ + 'title' => $this->t('Devel'), + 'weight' => 100, + 'url' => $entity->toUrl('devel-render'), + ]; + } + } + return $operations; + } + +} diff --git a/web/modules/contrib/devel/src/EventSubscriber/ErrorHandlerSubscriber.php b/web/modules/contrib/devel/src/EventSubscriber/ErrorHandlerSubscriber.php new file mode 100644 index 00000000..ee5ad21b --- /dev/null +++ b/web/modules/contrib/devel/src/EventSubscriber/ErrorHandlerSubscriber.php @@ -0,0 +1,57 @@ +account = $account; + } + + /** + * Register devel error handler. + * + * @param \Symfony\Component\EventDispatcher\Event $event + * The event to process. + */ + public function registerErrorHandler(Event $event = NULL) { + if ($this->account && $this->account->hasPermission('access devel information')) { + devel_set_handler(devel_get_handlers()); + } + } + + /** + * {@inheritdoc} + */ + public static function getSubscribedEvents() { + // Runs as soon as possible in the request but after + // AuthenticationSubscriber (priority 300) because you need to access to + // the current user for determine whether register the devel error handler + // or not. + $events[KernelEvents::REQUEST][] = ['registerErrorHandler', 256]; + + return $events; + } + +} diff --git a/web/modules/contrib/devel/src/EventSubscriber/ThemeInfoRebuildSubscriber.php b/web/modules/contrib/devel/src/EventSubscriber/ThemeInfoRebuildSubscriber.php new file mode 100644 index 00000000..9b833ecc --- /dev/null +++ b/web/modules/contrib/devel/src/EventSubscriber/ThemeInfoRebuildSubscriber.php @@ -0,0 +1,119 @@ +config = $config->get('devel.settings'); + $this->account = $account; + $this->themeHandler = $theme_handler; + } + + /** + * Forces the system to rebuild the theme registry. + * + * @param \Symfony\Component\HttpKernel\Event\GetResponseEvent $event + * The event to process. + */ + public function rebuildThemeInfo(GetResponseEvent $event) { + if ($this->config->get('rebuild_theme')) { + // Update the theme registry. + drupal_theme_rebuild(); + // Refresh theme data. + $this->themeHandler->refreshInfo(); + // Resets the internal state of the theme handler and clear the 'system + // list' cache; this allow to properly register, if needed, PSR-4 + // namespaces for theme extensions after refreshing the info data. + $this->themeHandler->reset(); + // Notify the user that the theme info are rebuilt on every request. + $this->triggerWarningIfNeeded($event->getRequest()); + } + } + + /** + * Notifies the user that the theme info are rebuilt on every request. + * + * The warning message is shown only to users with adequate permissions and + * only once per session. + * + * @param \Symfony\Component\HttpFoundation\Request $request + * The request. + */ + protected function triggerWarningIfNeeded(Request $request) { + if ($this->account && $this->account->hasPermission('access devel information')) { + $session = $request->getSession(); + if ($session && !$session->has($this->notificationFlag)) { + $session->set($this->notificationFlag, TRUE); + $message = $this->t('The theme information is being rebuilt on every request. Remember to turn off this feature on production websites.', [':url' => Url::fromRoute('devel.admin_settings')->toString()]); + $this->messenger()->addWarning($message); + + } + } + } + + /** + * {@inheritdoc} + */ + public static function getSubscribedEvents() { + // Set high priority value to start as early as possible. + $events[KernelEvents::REQUEST][] = ['rebuildThemeInfo', 256]; + return $events; + } + +} diff --git a/web/modules/contrib/devel/src/Form/ConfigEditor.php b/web/modules/contrib/devel/src/Form/ConfigEditor.php new file mode 100644 index 00000000..efefe6b2 --- /dev/null +++ b/web/modules/contrib/devel/src/Form/ConfigEditor.php @@ -0,0 +1,155 @@ +config($config_name); + + if ($config === FALSE || $config->isNew()) { + $this->messenger()->addError($this->t('Config @name does not exist in the system.', ['@name' => $config_name])); + return; + } + + $data = $config->getOriginal(); + + if (empty($data)) { + $this->messenger()->addWarning($this->t('Config @name exists but has no data.', ['@name' => $config_name])); + return; + } + + try { + $output = Yaml::encode($data); + } + catch (InvalidDataTypeException $e) { + $this->messenger()->addError($this->t('Invalid data detected for @name : %error', ['@name' => $config_name, '%error' => $e->getMessage()])); + return; + } + + $form['current'] = [ + '#type' => 'details', + '#title' => $this->t('Current value for %variable', ['%variable' => $config_name]), + '#attributes' => ['class' => ['container-inline']], + ]; + $form['current']['value'] = [ + '#type' => 'item', + // phpcs:ignore Drupal.Functions.DiscouragedFunctions + '#markup' => dpr($output, TRUE), + ]; + + $form['name'] = [ + '#type' => 'value', + '#value' => $config_name, + ]; + $form['new'] = [ + '#type' => 'textarea', + '#title' => $this->t('New value'), + '#default_value' => $output, + '#rows' => 24, + '#required' => TRUE, + ]; + + $form['actions'] = ['#type' => 'actions']; + $form['actions']['submit'] = [ + '#type' => 'submit', + '#value' => $this->t('Save'), + ]; + $form['actions']['cancel'] = [ + '#type' => 'link', + '#title' => $this->t('Cancel'), + '#url' => $this->buildCancelLinkUrl(), + ]; + $form['actions']['delete'] = [ + '#type' => 'link', + '#title' => $this->t('Delete'), + '#url' => Url::fromRoute('devel.config_delete', ['config_name' => $config_name]), + '#attributes' => [ + 'class' => ['button', 'button--danger'], + ], + ]; + + return $form; + } + + /** + * {@inheritdoc} + */ + public function validateForm(array &$form, FormStateInterface $form_state) { + $value = $form_state->getValue('new'); + // Try to parse the new provided value. + try { + $parsed_value = Yaml::decode($value); + // Config::setData needs array for the new configuration and + // a simple string is valid YAML for any reason. + if (is_array($parsed_value)) { + $form_state->setValue('parsed_value', $parsed_value); + } + else { + $form_state->setErrorByName('new', $this->t('Invalid input')); + } + } + catch (InvalidDataTypeException $e) { + $form_state->setErrorByName('new', $this->t('Invalid input: %error', ['%error' => $e->getMessage()])); + } + } + + /** + * {@inheritdoc} + */ + public function submitForm(array &$form, FormStateInterface $form_state) { + $values = $form_state->getValues(); + try { + $this->configFactory()->getEditable($values['name'])->setData($values['parsed_value'])->save(); + $this->messenger()->addMessage($this->t('Configuration variable %variable was successfully saved.', ['%variable' => $values['name']])); + $this->logger('devel')->info('Configuration variable %variable was successfully saved.', ['%variable' => $values['name']]); + + $form_state->setRedirectUrl(Url::fromRoute('devel.configs_list')); + } + catch (\Exception $e) { + $this->messenger()->addError($e->getMessage()); + $this->logger('devel')->error('Error saving configuration variable %variable : %error.', ['%variable' => $values['name'], '%error' => $e->getMessage()]); + } + } + + /** + * Builds the cancel link url for the form. + * + * @return \Drupal\Core\Url + * Cancel url + */ + private function buildCancelLinkUrl() { + $query = $this->getRequest()->query; + + if ($query->has('destination')) { + $options = UrlHelper::parse($query->get('destination')); + $url = Url::fromUserInput('/' . ltrim($options['path'], '/'), $options); + } + else { + $url = Url::fromRoute('devel.configs_list'); + } + + return $url; + } + +} diff --git a/web/modules/contrib/devel/src/Form/ConfigsList.php b/web/modules/contrib/devel/src/Form/ConfigsList.php new file mode 100644 index 00000000..e460c464 --- /dev/null +++ b/web/modules/contrib/devel/src/Form/ConfigsList.php @@ -0,0 +1,86 @@ + 'details', + '#title' => $this->t('Filter variables'), + '#attributes' => ['class' => ['container-inline']], + '#open' => isset($filter) && trim($filter) != '', + ]; + $form['filter']['name'] = [ + '#type' => 'textfield', + '#title' => $this->t('Variable name'), + '#title_display' => 'invisible', + '#default_value' => $filter, + ]; + $form['filter']['actions'] = ['#type' => 'actions']; + $form['filter']['actions']['show'] = [ + '#type' => 'submit', + '#value' => $this->t('Filter'), + ]; + + $header = [ + 'name' => ['data' => $this->t('Name')], + 'edit' => ['data' => $this->t('Operations')], + ]; + + $rows = []; + + $destination = $this->getDestinationArray(); + + // List all the variables filtered if any filter was provided. + $names = $this->configFactory()->listAll($filter); + + foreach ($names as $config_name) { + $operations['edit'] = [ + 'title' => $this->t('Edit'), + 'url' => Url::fromRoute('devel.config_edit', ['config_name' => $config_name]), + 'query' => $destination, + ]; + $rows[] = [ + 'name' => $config_name, + 'operation' => ['data' => ['#type' => 'operations', '#links' => $operations]], + ]; + } + + $form['variables'] = [ + '#type' => 'table', + '#header' => $header, + '#rows' => $rows, + '#empty' => $this->t('No variables found'), + ]; + + return $form; + } + + /** + * {@inheritdoc} + */ + public function submitForm(array &$form, FormStateInterface $form_state) { + $filter = $form_state->getValue('name'); + $form_state->setRedirectUrl(Url::FromRoute('devel.configs_list', ['filter' => Html::escape($filter)])); + } + +} diff --git a/web/modules/contrib/devel/src/Form/DevelReinstall.php b/web/modules/contrib/devel/src/Form/DevelReinstall.php new file mode 100644 index 00000000..32f89b46 --- /dev/null +++ b/web/modules/contrib/devel/src/Form/DevelReinstall.php @@ -0,0 +1,166 @@ +moduleInstaller = $module_installer; + $this->moduleExtensionList = $extension_list_module; + } + + /** + * {@inheritdoc} + */ + public static function create(ContainerInterface $container) { + return new static( + $container->get('module_installer'), + $container->get('extension.list.module') + ); + } + + /** + * {@inheritdoc} + */ + public function getFormId() { + return 'devel_reinstall_form'; + } + + /** + * {@inheritdoc} + */ + public function buildForm(array $form, FormStateInterface $form_state) { + // Get a list of all available modules. + $modules = $this->moduleExtensionList->reset()->getList(); + + $uninstallable = array_filter($modules, function ($module) use ($modules) { + return empty($modules[$module->getName()]->info['required']) && drupal_get_installed_schema_version($module->getName()) > SCHEMA_UNINSTALLED && $module->getName() !== 'devel'; + }); + + $form['filters'] = [ + '#type' => 'container', + '#attributes' => [ + 'class' => ['table-filter', 'js-show'], + ], + ]; + $form['filters']['text'] = [ + '#type' => 'search', + '#title' => $this->t('Search'), + '#size' => 30, + '#placeholder' => $this->t('Enter module name'), + '#attributes' => [ + 'class' => ['table-filter-text'], + 'data-table' => '#devel-reinstall-form', + 'autocomplete' => 'off', + 'title' => $this->t('Enter a part of the module name or description to filter by.'), + ], + ]; + + // Only build the rest of the form if there are any modules available to + // uninstall. + if (empty($uninstallable)) { + return $form; + } + + $header = [ + 'name' => $this->t('Name'), + 'description' => $this->t('Description'), + ]; + + $rows = []; + + foreach ($uninstallable as $module) { + $name = $module->info['name'] ?: $module->getName(); + + $rows[$module->getName()] = [ + 'name' => [ + 'data' => [ + '#type' => 'inline_template', + '#template' => '', + '#context' => ['module_name' => $name], + ], + ], + 'description' => [ + 'data' => $module->info['description'], + 'class' => ['description'], + ], + ]; + } + + $form['reinstall'] = [ + '#type' => 'tableselect', + '#header' => $header, + '#options' => $rows, + '#js_select' => FALSE, + '#empty' => $this->t('No modules are available to uninstall.'), + ]; + + $form['#attached']['library'][] = 'system/drupal.system.modules'; + + $form['actions'] = ['#type' => 'actions']; + $form['actions']['submit'] = [ + '#type' => 'submit', + '#value' => $this->t('Reinstall'), + ]; + + return $form; + } + + /** + * {@inheritdoc} + */ + public function validateForm(array &$form, FormStateInterface $form_state) { + // Form submitted, but no modules selected. + if (!array_filter($form_state->getValue('reinstall'))) { + $form_state->setErrorByName('reinstall', $this->t('No modules selected.')); + } + } + + /** + * {@inheritdoc} + */ + public function submitForm(array &$form, FormStateInterface $form_state) { + try { + $modules = $form_state->getValue('reinstall'); + $reinstall = array_keys(array_filter($modules)); + $this->moduleInstaller->uninstall($reinstall, FALSE); + $this->moduleInstaller->install($reinstall, FALSE); + $this->messenger()->addMessage($this->t('Uninstalled and installed: %names.', ['%names' => implode(', ', $reinstall)])); + } + catch (\Exception $e) { + $this->messenger()->addError($this->t('Unable to reinstall modules. Error: %error.', ['%error' => $e->getMessage()])); + } + } + +} diff --git a/web/modules/contrib/devel/src/Form/RouterRebuildConfirmForm.php b/web/modules/contrib/devel/src/Form/RouterRebuildConfirmForm.php new file mode 100644 index 00000000..c6e7383e --- /dev/null +++ b/web/modules/contrib/devel/src/Form/RouterRebuildConfirmForm.php @@ -0,0 +1,86 @@ +routeBuilder = $route_builder; + } + + /** + * {@inheritdoc} + */ + public static function create(ContainerInterface $container) { + return new static( + $container->get('router.builder') + ); + } + + /** + * {@inheritdoc} + */ + public function getFormId() { + return 'devel_menu_rebuild'; + } + + /** + * {@inheritdoc} + */ + public function getQuestion() { + return $this->t('Are you sure you want to rebuild the router?'); + } + + /** + * {@inheritdoc} + */ + public function getCancelUrl() { + return new Url(''); + } + + /** + * {@inheritdoc} + */ + public function getDescription() { + return $this->t('Rebuilds the routes information gathering all routing data from .routing.yml files and from classes which subscribe to the route build events. This action cannot be undone.'); + } + + /** + * {@inheritdoc} + */ + public function getConfirmText() { + return $this->t('Rebuild'); + } + + /** + * {@inheritdoc} + */ + public function submitForm(array &$form, FormStateInterface $form_state) { + $this->routeBuilder->rebuild(); + $this->messenger()->addMessage($this->t('The router has been rebuilt.')); + $form_state->setRedirect(''); + } + +} diff --git a/web/modules/contrib/devel/src/Form/SettingsForm.php b/web/modules/contrib/devel/src/Form/SettingsForm.php new file mode 100644 index 00000000..3c44427e --- /dev/null +++ b/web/modules/contrib/devel/src/Form/SettingsForm.php @@ -0,0 +1,225 @@ +dumperManager = $devel_dumper_manager; + } + + /** + * {@inheritdoc} + */ + public static function create(ContainerInterface $container) { + return new static( + $container->get('plugin.manager.devel_dumper') + ); + } + + /** + * {@inheritdoc} + */ + public function getFormId() { + return 'devel_admin_settings_form'; + } + + /** + * {@inheritdoc} + */ + protected function getEditableConfigNames() { + return [ + 'devel.settings', + ]; + } + + /** + * {@inheritdoc} + */ + public function buildForm(array $form, FormStateInterface $form_state, Request $request = NULL) { + $current_url = Url::createFromRequest($request); + $devel_config = $this->config('devel.settings'); + + $form['page_alter'] = [ + '#type' => 'checkbox', + '#title' => $this->t('Display $page array'), + '#default_value' => $devel_config->get('page_alter'), + '#description' => $this->t('Display $page array from hook_page_attachments_alter() in the messages area of each page.'), + ]; + $form['raw_names'] = [ + '#type' => 'checkbox', + '#title' => $this->t('Display machine names of permissions and modules'), + '#default_value' => $devel_config->get('raw_names'), + '#description' => $this->t('Display the language-independent machine names of the permissions in mouse-over hints on the Permissions page and the module base file names on the Permissions and Modules pages.', [ + ':permissions_url' => Url::fromRoute('user.admin_permissions')->toString(), + ':modules_url' => Url::fromRoute('system.modules_list')->toString(), + ]), + ]; + $form['rebuild_theme'] = [ + '#type' => 'checkbox', + '#title' => $this->t('Rebuild the theme registry on every page load'), + '#description' => $this->t('New templates, theme overrides, and changes to the theme.info.yml need the theme registry to be rebuilt in order to appear on the site.'), + '#default_value' => $devel_config->get('rebuild_theme'), + ]; + + $error_handlers = devel_get_handlers(); + $form['error_handlers'] = [ + '#type' => 'select', + '#title' => $this->t('Error handlers'), + '#options' => [ + DEVEL_ERROR_HANDLER_NONE => $this->t('None'), + DEVEL_ERROR_HANDLER_STANDARD => $this->t('Standard Drupal'), + DEVEL_ERROR_HANDLER_BACKTRACE_DPM => $this->t('Backtrace in the message area'), + DEVEL_ERROR_HANDLER_BACKTRACE_KINT => $this->t('Backtrace above the rendered page'), + ], + '#multiple' => TRUE, + '#default_value' => empty($error_handlers) ? DEVEL_ERROR_HANDLER_NONE : $error_handlers, + '#description' => [ + [ + '#markup' => $this->t('Select the error handler(s) to use, in case you choose to show errors on screen.', [':choose' => Url::fromRoute('system.logging_settings')->toString()]), + ], + [ + '#theme' => 'item_list', + '#items' => [ + $this->t('None is a good option when stepping through the site in your debugger.'), + $this->t('Standard Drupal does not display all the information that is often needed to resolve an issue.'), + $this->t('Backtrace displays nice debug information when any type of error is noticed, but only to users with the %perm permission.', ['%perm' => $this->t('Access developer information')]), + ], + ], + [ + '#markup' => $this->t('Depending on the situation, the theme, the size of the call stack and the arguments, etc., some handlers may not display their messages, or display them on the subsequent page. Select Standard Drupal and Backtrace above the rendered page to maximize your chances of not missing any messages.') . '
' . + $this->t('Demonstrate the current error handler(s):') . ' ' . + Link::fromTextAndUrl('notice', $current_url->setOption('query', ['demo' => 'notice']))->toString() . ', ' . + Link::fromTextAndUrl('notice+warning', $current_url->setOption('query', ['demo' => 'warning']))->toString() . ', ' . + Link::fromTextAndUrl('notice+warning+error', $current_url->setOption('query', ['demo' => 'error']))->toString() . ' (' . + $this->t('The presentation of the @error is determined by PHP.', ['@error' => 'error']) . ')', + ], + ], + ]; + + $form['error_handlers']['#size'] = count($form['error_handlers']['#options']); + if ($request->query->has('demo')) { + if ($request->getMethod() == 'GET') { + $this->demonstrateErrorHandlers($request->query->get('demo')); + } + $request->query->remove('demo'); + } + + $dumper = $devel_config->get('devel_dumper'); + $default = $this->dumperManager->isPluginSupported($dumper) ? $dumper : $this->dumperManager->getFallbackPluginId(NULL); + + $form['dumper'] = [ + '#type' => 'radios', + '#title' => $this->t('Variables Dumper'), + '#options' => [], + '#default_value' => $default, + '#description' => $this->t('Select the debugging tool used for formatting and displaying the variables inspected through the debug functions of Devel. NOTE: Some of these plugins require external libraries for to be enabled. Learn how install external libraries with Composer.', [ + ':url' => 'https://www.drupal.org/node/2404989', + ]), + ]; + + foreach ($this->dumperManager->getDefinitions() as $id => $definition) { + $form['dumper']['#options'][$id] = $definition['label']; + + $supported = $this->dumperManager->isPluginSupported($id); + $form['dumper'][$id]['#disabled'] = !$supported; + + $form['dumper'][$id]['#description'] = [ + '#type' => 'inline_template', + '#template' => '{{ description }}{% if not supported %}
{% trans %}Not available. You may need to install external dependencies for use this plugin.{% endtrans %}
{% endif %}', + '#context' => [ + 'description' => $definition['description'], + 'supported' => $supported, + ], + ]; + } + + // Allow custom debug filename for use in DevelDumperManager::debug() + $default_file = $devel_config->get('debug_logfile') ?: 'temporary://drupal_debug.txt'; + $form['debug_logfile'] = [ + '#type' => 'textfield', + '#title' => $this->t('Debug Log File'), + '#description' => $this->t('This is the log file that Devel functions such as ddm() write to. Use temporary:// to represent your systems temporary directory. Save with a blank filename to revert to the default.'), + '#default_value' => $default_file, + ]; + + // Specify whether debug file should have
 tags around each $dump,
+    // for use in Plugin\Devel\Dumper\DoctrineDebug::export()
+    $form['debug_pre'] = [
+      '#type' => 'checkbox',
+      '#title' => $this->t('Wrap debug in <pre> tags'),
+      '#default_value' => $devel_config->get('debug_pre'),
+      '#description' => $this->t('You may want the debug output wrapped in <pre> tags, depending on your debug file format and how it is displayed.'),
+    ];
+
+    return parent::buildForm($form, $form_state);
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function submitForm(array &$form, FormStateInterface $form_state) {
+    $values = $form_state->getValues();
+    $this->config('devel.settings')
+      ->set('page_alter', $values['page_alter'])
+      ->set('raw_names', $values['raw_names'])
+      ->set('error_handlers', $values['error_handlers'])
+      ->set('rebuild_theme', $values['rebuild_theme'])
+      ->set('devel_dumper', $values['dumper'])
+      ->set('debug_logfile', $values['debug_logfile'] ?: 'temporary://drupal_debug.txt')
+      ->set('debug_pre', $values['debug_pre'])
+      ->save();
+
+    parent::submitForm($form, $form_state);
+  }
+
+  /**
+   * Demonstrates the capabilities of the error handler.
+   *
+   * @param string $severity
+   *   The severity level for which demonstrate the error handler capabilities.
+   */
+  protected function demonstrateErrorHandlers($severity) {
+    switch ($severity) {
+      case 'notice':
+        trigger_error('This is an example notice', E_USER_NOTICE);
+        break;
+
+      case 'warning':
+        trigger_error('This is an example notice', E_USER_NOTICE);
+        trigger_error('This is an example warning', E_USER_WARNING);
+        break;
+
+      case 'error':
+        trigger_error('This is an example notice', E_USER_NOTICE);
+        trigger_error('This is an example warning', E_USER_WARNING);
+        trigger_error('This is an example error', E_USER_ERROR);
+        break;
+    }
+  }
+
+}
diff --git a/web/modules/contrib/devel/src/Form/SwitchUserForm.php b/web/modules/contrib/devel/src/Form/SwitchUserForm.php
new file mode 100644
index 00000000..7b9c44d7
--- /dev/null
+++ b/web/modules/contrib/devel/src/Form/SwitchUserForm.php
@@ -0,0 +1,110 @@
+csrfToken = $csrf_token_generator;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function create(ContainerInterface $container) {
+    return new static(
+      $container->get('csrf_token')
+    );
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getFormId() {
+    return 'devel_switchuser_form';
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function buildForm(array $form, FormStateInterface $form_state) {
+    $form['autocomplete'] = [
+      '#type' => 'container',
+      '#attributes' => [
+        'class' => ['container-inline'],
+      ],
+    ];
+    $form['autocomplete']['userid'] = [
+      '#type' => 'entity_autocomplete',
+      '#title' => $this->t('Username'),
+      '#placeholder' => $this->t('Enter username'),
+      '#target_type' => 'user',
+      '#selection_settings' => [
+        'include_anonymous' => FALSE,
+      ],
+      '#process_default_value' => FALSE,
+      '#maxlength' => UserInterface::USERNAME_MAX_LENGTH,
+      '#title_display' => 'invisible',
+      '#required' => TRUE,
+      '#size' => '28',
+    ];
+
+    $form['autocomplete']['actions'] = ['#type' => 'actions'];
+    $form['autocomplete']['actions']['submit'] = [
+      '#type' => 'submit',
+      '#value' => $this->t('Switch'),
+    ];
+
+    return $form;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function validateForm(array &$form, FormStateInterface $form_state) {
+    if (!$account = User::load($form_state->getValue('userid'))) {
+      $form_state->setErrorByName('userid', $this->t('Username not found'));
+    }
+    else {
+      $form_state->setValue('username', $account->getAccountName());
+    }
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function submitForm(array &$form, FormStateInterface $form_state) {
+    // We cannot rely on automatic token creation, since the csrf seed changes
+    // after the redirect and the generated token is not more valid.
+    // TODO find another way to do this.
+    $url = Url::fromRoute('devel.switch', ['name' => $form_state->getValue('username')]);
+    $url->setOption('query', ['token' => $this->csrfToken->get($url->getInternalPath())]);
+
+    $form_state->setRedirectUrl($url);
+  }
+
+}
diff --git a/web/modules/contrib/devel/src/Form/SystemStateEdit.php b/web/modules/contrib/devel/src/Form/SystemStateEdit.php
new file mode 100644
index 00000000..8899885c
--- /dev/null
+++ b/web/modules/contrib/devel/src/Form/SystemStateEdit.php
@@ -0,0 +1,190 @@
+state = $state;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function create(ContainerInterface $container) {
+    return new static(
+      $container->get('state')
+    );
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getFormId() {
+    return 'devel_state_system_edit_form';
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function buildForm(array $form, FormStateInterface $form_state, $state_name = '') {
+    // Get the old value.
+    $old_value = $this->state->get($state_name);
+
+    if (!isset($old_value)) {
+      $this->messenger()->addWarning($this->t('State @name does not exist in the system.', ['@name' => $state_name]));
+      return;
+    }
+
+    // Only simple structures are allowed to be edited.
+    $disabled = !$this->checkObject($old_value);
+
+    if ($disabled) {
+      $this->messenger()->addWarning($this->t('Only simple structures are allowed to be edited. State @name contains objects.', ['@name' => $state_name]));
+
+    }
+
+    // First we will show the user the content of the variable about to be edited.
+    $form['value'] = [
+      '#type' => 'item',
+      '#title' => $this->t('Current value for %name', ['%name' => $state_name]),
+      // phpcs:ignore Drupal.Functions.DiscouragedFunctions
+      '#markup' => kpr($old_value, TRUE),
+    ];
+
+    $transport = 'plain';
+
+    if (!$disabled && is_array($old_value)) {
+      try {
+        $old_value = Yaml::encode($old_value);
+        $transport = 'yaml';
+      }
+      catch (InvalidDataTypeException $e) {
+        $this->messenger()->addError($this->t('Invalid data detected for @name : %error', ['@name' => $state_name, '%error' => $e->getMessage()]));
+        return;
+      }
+    }
+
+    // Store in the form the name of the state variable.
+    $form['state_name'] = [
+      '#type' => 'value',
+      '#value' => $state_name,
+    ];
+    // Set the transport format for the new value. Values:
+    //  - plain
+    //  - yaml.
+    $form['transport'] = [
+      '#type' => 'value',
+      '#value' => $transport,
+    ];
+
+    $form['new_value'] = [
+      '#type' => 'textarea',
+      '#title' => $this->t('New value'),
+      '#default_value' => $disabled ? '' : $old_value,
+      '#disabled' => $disabled,
+      '#rows' => 15,
+    ];
+
+    $form['actions'] = ['#type' => 'actions'];
+    $form['actions']['submit'] = [
+      '#type' => 'submit',
+      '#value' => $this->t('Save'),
+      '#disabled' => $disabled,
+    ];
+    $form['actions']['cancel'] = [
+      '#type' => 'link',
+      '#title' => $this->t('Cancel'),
+      '#url' => Url::fromRoute('devel.state_system_page'),
+    ];
+
+    return $form;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function validateForm(array &$form, FormStateInterface $form_state) {
+    $values = $form_state->getValues();
+
+    if ($values['transport'] == 'yaml') {
+      // Try to parse the new provided value.
+      try {
+        $parsed_value = Yaml::decode($values['new_value']);
+        $form_state->setValue('parsed_value', $parsed_value);
+      }
+      catch (InvalidDataTypeException $e) {
+        $form_state->setErrorByName('new_value', $this->t('Invalid input: %error', ['%error' => $e->getMessage()]));
+      }
+    }
+    else {
+      $form_state->setValue('parsed_value', $values['new_value']);
+    }
+
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function submitForm(array &$form, FormStateInterface $form_state) {
+    // Save the state.
+    $values = $form_state->getValues();
+    $this->state->set($values['state_name'], $values['parsed_value']);
+
+    $form_state->setRedirectUrl(Url::fromRoute('devel.state_system_page'));
+    $this->messenger()->addMessage($this->t('Variable %variable was successfully edited.', ['%variable' => $values['state_name']]));
+    $this->logger('devel')->info('Variable %variable was successfully edited.', ['%variable' => $values['state_name']]);
+  }
+
+  /**
+   * Helper function to determine if a variable is or contains an object.
+   *
+   * @param $data
+   *   Input data to check
+   *
+   * @return bool
+   *   TRUE if the variable is not an object and does not contain one.
+   */
+  protected function checkObject($data) {
+    if (is_object($data)) {
+      return FALSE;
+    }
+    if (is_array($data)) {
+      // If the current object is an array, then check recursively.
+      foreach ($data as $value) {
+        // If there is an object the whole container is "contaminated".
+        if (!$this->checkObject($value)) {
+          return FALSE;
+        }
+      }
+    }
+
+    // All checks pass.
+    return TRUE;
+  }
+
+}
diff --git a/web/modules/contrib/devel/src/Form/ToolbarSettingsForm.php b/web/modules/contrib/devel/src/Form/ToolbarSettingsForm.php
new file mode 100644
index 00000000..d0e09fc7
--- /dev/null
+++ b/web/modules/contrib/devel/src/Form/ToolbarSettingsForm.php
@@ -0,0 +1,118 @@
+menuLinkTree = $menu_link_tree;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function create(ContainerInterface $container) {
+    return new static(
+      $container->get('config.factory'),
+      $container->get('menu.link_tree')
+    );
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getFormId() {
+    return 'devel_toolbar_settings_form';
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function getEditableConfigNames() {
+    return [
+      'devel.toolbar.settings',
+    ];
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function buildForm(array $form, FormStateInterface $form_state) {
+    $config = $this->config('devel.toolbar.settings');
+
+    $form['toolbar_items'] = [
+      '#type' => 'checkboxes',
+      '#title' => $this->t('Menu items always visible'),
+      '#options' => $this->getLinkLabels(),
+      '#default_value' => $config->get('toolbar_items') ?: [],
+      '#required' => TRUE,
+      '#description' => $this->t('Select the menu items always visible in devel toolbar tray. All the items not selected in this list will be visible only when the toolbar orientation is vertical.'),
+    ];
+
+    return parent::buildForm($form, $form_state);
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function submitForm(array &$form, FormStateInterface $form_state) {
+    $values = $form_state->getValues();
+    $toolbar_items = array_keys(array_filter($values['toolbar_items']));
+
+    $this->config('devel.toolbar.settings')
+      ->set('toolbar_items', $toolbar_items)
+      ->save();
+
+    parent::submitForm($form, $form_state);
+  }
+
+  /**
+   * Provides an array of available menu items.
+   *
+   * @return array
+   *   Associative array of devel menu item labels keyed by plugin ID.
+   */
+  protected function getLinkLabels() {
+    $options = [];
+
+    $parameters = new MenuTreeParameters();
+    $parameters->onlyEnabledLinks()->setTopLevelOnly();
+    $tree = $this->menuLinkTree->load('devel', $parameters);
+
+    foreach ($tree as $element) {
+      $link = $element->link;
+      $options[$link->getPluginId()] = $link->getTitle();
+    }
+
+    asort($options);
+
+    return $options;
+  }
+
+}
diff --git a/web/modules/contrib/devel/src/Plugin/Block/SwitchUserBlock.php b/web/modules/contrib/devel/src/Plugin/Block/SwitchUserBlock.php
new file mode 100644
index 00000000..d85222ce
--- /dev/null
+++ b/web/modules/contrib/devel/src/Plugin/Block/SwitchUserBlock.php
@@ -0,0 +1,298 @@
+formBuilder = $form_builder;
+    $this->currentUser = $current_user;
+    $this->userStorage = $user_storage;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
+    return new static(
+      $configuration,
+      $plugin_id,
+      $plugin_definition,
+      $container->get('current_user'),
+      $container->get('entity_type.manager')->getStorage('user'),
+      $container->get('form_builder')
+    );
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function defaultConfiguration() {
+    return [
+      'list_size' => 12,
+      'include_anon' => FALSE,
+      'show_form' => TRUE,
+    ];
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function blockAccess(AccountInterface $account) {
+    return AccessResult::allowedIfHasPermission($account, 'switch users');
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function blockForm($form, FormStateInterface $form_state) {
+    $anonymous = new AnonymousUserSession();
+    $form['list_size'] = [
+      '#type' => 'number',
+      '#title' => $this->t('Number of users to display in the list'),
+      '#default_value' => $this->configuration['list_size'],
+      '#min' => 1,
+      '#max' => 50,
+    ];
+    $form['include_anon'] = [
+      '#type' => 'checkbox',
+      '#title' => $this->t('Include %anonymous', ['%anonymous' => $anonymous->getDisplayName()]),
+      '#default_value' => $this->configuration['include_anon'],
+    ];
+    $form['show_form'] = [
+      '#type' => 'checkbox',
+      '#title' => $this->t('Allow entering any user name'),
+      '#default_value' => $this->configuration['show_form'],
+    ];
+
+    return $form;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function blockSubmit($form, FormStateInterface $form_state) {
+    $this->configuration['list_size'] = $form_state->getValue('list_size');
+    $this->configuration['include_anon'] = $form_state->getValue('include_anon');
+    $this->configuration['show_form'] = $form_state->getValue('show_form');
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getCacheMaxAge() {
+    return 0;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function build() {
+    $build = [];
+    if ($accounts = $this->getUsers()) {
+      $build['devel_links'] = $this->buildUserList($accounts);
+
+      if ($this->configuration['show_form']) {
+        $build['devel_form'] = $this->formBuilder->getForm('\Drupal\devel\Form\SwitchUserForm');
+      }
+    }
+
+    return $build;
+  }
+
+  /**
+   * Provides the list of accounts that can be used for the user switch.
+   *
+   * Inactive users are omitted from all of the following db selects. Users
+   * with 'switch users' permission and anonymous user if include_anon property
+   * is set to TRUE, are prioritized.
+   *
+   * @return \Drupal\Core\Session\AccountInterface[]
+   *   List of accounts to be used for the switch.
+   */
+  protected function getUsers() {
+    $list_size = $this->configuration['list_size'];
+    $include_anonymous = $this->configuration['include_anon'];
+
+    $list_size = $include_anonymous ? $list_size - 1 : $list_size;
+
+    // Users with 'switch users' permission are prioritized so
+    // we try to load first users with this permission.
+    $query = $this->userStorage->getQuery()
+      ->condition('uid', 0, '>')
+      ->condition('status', 0, '>')
+      ->sort('access', 'DESC')
+      ->range(0, $list_size);
+
+    $roles = user_roles(TRUE, 'switch users');
+
+    if (!empty($roles) && !isset($roles[Role::AUTHENTICATED_ID])) {
+      $query->condition('roles', array_keys($roles), 'IN');
+    }
+
+    $user_ids = $query->execute();
+
+    // If we don't have enough users with 'switch users' permission, add
+    // uids until we hit $list_size.
+    if (count($user_ids) < $list_size) {
+      $query = $this->userStorage->getQuery()
+        ->condition('uid', 0, '>')
+        ->condition('status', 0, '>')
+        ->sort('access', 'DESC')
+        ->range(0, $list_size);
+
+      // Excludes the prioritized user ids only if the previous query return
+      // some records.
+      if (!empty($user_ids)) {
+        $query->condition('uid', array_keys($user_ids), 'NOT IN');
+        $query->range(0, $list_size - count($user_ids));
+      }
+
+      $user_ids += $query->execute();
+    }
+
+    /** @var \Drupal\Core\Session\AccountInterface[] $accounts */
+    $accounts = $this->userStorage->loadMultiple($user_ids);
+
+    if ($include_anonymous) {
+      $anonymous = new AnonymousUserSession();
+      $accounts[$anonymous->id()] = $anonymous;
+    }
+
+    uasort($accounts, 'static::sortUserList');
+
+    return $accounts;
+  }
+
+  /**
+   * Builds the user listing as renderable array.
+   *
+   * @param \Drupal\core\Session\AccountInterface[] $accounts
+   *   The accounts to be rendered in the list.
+   *
+   * @return array
+   *   A renderable array.
+   */
+  protected function buildUserList(array $accounts) {
+    $links = [];
+
+    foreach ($accounts as $account) {
+      $links[$account->id()] = [
+        'title' => $account->getDisplayName(),
+        'url' => Url::fromRoute('devel.switch', ['name' => $account->getAccountName()]),
+        'query' => $this->getDestinationArray(),
+        'attributes' => [
+          'title' => $account->hasPermission('switch users') ? $this->t('This user can switch back.') : $this->t('Caution: this user will be unable to switch back.'),
+        ],
+      ];
+
+      if ($account->isAnonymous()) {
+        $links[$account->id()]['url'] = Url::fromRoute('user.logout');
+      }
+
+      if ($this->currentUser->id() === $account->id()) {
+        $links[$account->id()]['title'] = new FormattableMarkup('%user', ['%user' => $account->getDisplayName()]);
+      }
+    }
+
+    return [
+      '#theme' => 'links',
+      '#links' => $links,
+      '#attached' => ['library' => ['devel/devel']],
+    ];
+  }
+
+  /**
+   * Helper callback for uasort() to sort accounts by last access.
+   *
+   * @param \Drupal\Core\Session\AccountInterface $a
+   *   First account.
+   * @param \Drupal\Core\Session\AccountInterface $b
+   *   Second account.
+   *
+   * @return int
+   *   Result of comparing the last access times:
+   *   - -1 if $a was more recently accessed
+   *   -  0 if last access times compare equal
+   *   -  1 if $b was more recently accessed
+   */
+  public static function sortUserList(AccountInterface $a, AccountInterface $b) {
+    $a_access = (int) $a->getLastAccessedTime();
+    $b_access = (int) $b->getLastAccessedTime();
+
+    if ($a_access === $b_access) {
+      return 0;
+    }
+
+    // User never access to site.
+    if ($a_access === 0) {
+      return 1;
+    }
+
+    return ($a_access > $b_access) ? -1 : 1;
+  }
+
+}
diff --git a/web/modules/contrib/devel/src/Plugin/Derivative/DevelLocalTask.php b/web/modules/contrib/devel/src/Plugin/Derivative/DevelLocalTask.php
new file mode 100644
index 00000000..4dedb38d
--- /dev/null
+++ b/web/modules/contrib/devel/src/Plugin/Derivative/DevelLocalTask.php
@@ -0,0 +1,106 @@
+entityTypeManager = $entity_type_manager;
+    $this->stringTranslation = $string_translation;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function create(ContainerInterface $container, $base_plugin_id) {
+    return new static(
+      $container->get('entity_type.manager'),
+      $container->get('string_translation')
+    );
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getDerivativeDefinitions($base_plugin_definition) {
+    $this->derivatives = [];
+
+    foreach ($this->entityTypeManager->getDefinitions() as $entity_type_id => $entity_type) {
+
+      $has_edit_path = $entity_type->hasLinkTemplate('devel-load');
+      $has_canonical_path = $entity_type->hasLinkTemplate('devel-render');
+
+      if ($has_edit_path || $has_canonical_path) {
+
+        $this->derivatives["$entity_type_id.devel_tab"] = [
+          'route_name' => "entity.$entity_type_id." . ($has_edit_path ? 'devel_load' : 'devel_render'),
+          'title' => $this->t('Devel'),
+          'base_route' => "entity.$entity_type_id." . ($has_canonical_path ? "canonical" : "edit_form"),
+          'weight' => 100,
+        ];
+
+        $this->derivatives["$entity_type_id.devel_definition_tab"] = [
+          'route_name' => "entity.$entity_type_id.devel_definition",
+          'title' => $this->t('Definition'),
+          'parent_id' => "devel.entities:$entity_type_id.devel_tab",
+          'weight' => 100,
+        ];
+
+        if ($has_canonical_path) {
+          $this->derivatives["$entity_type_id.devel_render_tab"] = [
+            'route_name' => "entity.$entity_type_id.devel_render",
+            'weight' => 100,
+            'title' => $this->t('Render'),
+            'parent_id' => "devel.entities:$entity_type_id.devel_tab",
+          ];
+        }
+
+        if ($has_edit_path) {
+          $this->derivatives["$entity_type_id.devel_load_tab"] = [
+            'route_name' => "entity.$entity_type_id.devel_load",
+            'weight' => 100,
+            'title' => $this->t('Load'),
+            'parent_id' => "devel.entities:$entity_type_id.devel_tab",
+          ];
+        }
+      }
+    }
+
+    foreach ($this->derivatives as &$entry) {
+      $entry += $base_plugin_definition;
+    }
+
+    return $this->derivatives;
+  }
+
+}
diff --git a/web/modules/contrib/devel/src/Plugin/Devel/Dumper/DoctrineDebug.php b/web/modules/contrib/devel/src/Plugin/Devel/Dumper/DoctrineDebug.php
new file mode 100644
index 00000000..b827d450
--- /dev/null
+++ b/web/modules/contrib/devel/src/Plugin/Devel/Dumper/DoctrineDebug.php
@@ -0,0 +1,71 @@
+Doctrine debugging tool.")
+ * )
+ */
+class DoctrineDebug extends DevelDumperBase {
+
+  /**
+   * {@inheritdoc}
+   */
+  public function export($input, $name = NULL) {
+    $name = $name ? $name . ' => ' : '';
+    $variable = Debug::export($input, 6);
+
+    ob_start();
+    print_r($variable);
+    $dump = ob_get_contents();
+    ob_end_clean();
+
+    // Run Xss::filterAdmin on the resulting string to prevent
+    // cross-site-scripting (XSS) vulnerabilities.
+    $dump = Xss::filterAdmin($dump);
+
+    $config = \Drupal::config('devel.settings');
+    $debug_pre = $config->get('debug_pre');
+    $dump = ($debug_pre ? '
' : '') . $name . $dump . ($debug_pre ? '
' : ''); + + return $this->setSafeMarkup($dump); + } + + /** + * {@inheritdoc} + */ + public function exportAsRenderable($input, $name = NULL) { + $output['container'] = [ + '#type' => 'details', + '#title' => $name ?: $this->t('Variable'), + '#attached' => [ + 'library' => ['devel/devel'], + ], + '#attributes' => [ + 'class' => ['container-inline', 'devel-dumper', 'devel-selectable'], + ], + 'export' => [ + '#markup' => $this->export($input), + ], + ]; + + return $output; + } + + /** + * {@inheritdoc} + */ + public static function checkRequirements() { + return TRUE; + } + +} diff --git a/web/modules/contrib/devel/src/Plugin/Devel/Dumper/Kint.php b/web/modules/contrib/devel/src/Plugin/Devel/Dumper/Kint.php new file mode 100644 index 00000000..4998f9e5 --- /dev/null +++ b/web/modules/contrib/devel/src/Plugin/Devel/Dumper/Kint.php @@ -0,0 +1,100 @@ +Kint debugging tool."), + * ) + */ +class Kint extends DevelDumperBase { + + /** + * {@inheritdoc} + */ + public function __construct(array $configuration, $plugin_id, $plugin_definition) { + parent::__construct($configuration, $plugin_id, $plugin_definition); + $this->configure(); + } + + /** + * Configures kint with more sane values. + */ + protected function configure() { + // Remove resource-hungry plugins. + \Kint::$plugins = array_diff(\Kint::$plugins, [ + 'Kint\\Parser\\ClassMethodsPlugin', + 'Kint\\Parser\\ClassStaticsPlugin', + 'Kint\\Parser\\IteratorPlugin', + ]); + \Kint::$aliases = $this->getInternalFunctions(); + + RichRenderer::$folder = FALSE; + BlacklistPlugin::$shallow_blacklist[] = ContainerInterface::class; + } + + /** + * {@inheritdoc} + */ + public function export($input, $name = NULL) { + ob_start(); + if ($name == '__ARGS__') { + call_user_func_array(['Kint', 'dump'], $input); + $name = NULL; + } + elseif ($name !== NULL) { + // In order to get the correct access path information returned from Kint + // we have to give a second parameter here. This is due to a fault in + // Kint::getSingleCall which returns no info when the number of arguments + // passed to Kint::dump does not match the number in the original call + // that invoked the export (such as dsm). However, this second parameter + // is just treated as the next variable to dump, it is not used as the + // label. So we give a dummy value that we can remove below. + // @see https://gitlab.com/drupalspoons/devel/-/issues/252 + \Kint::dump($input, '---temporary-fix-see-issue-252---'); + } + else { + \Kint::dump($input); + } + $dump = ob_get_clean(); + if ($name) { + // Kint no longer treats an additional parameter as a custom title, but we + // can add the required $name as a label at the top of the output. + $dump = str_replace('
', '
' . $name . ': ', $dump); + + // Remove the output from the second dummy parameter. The pattern in [ ] + // matches the minimum to ensure we get just the string to be removed. + $pattern = '/(
[\w\d\s<>\/()]*"---temporary-fix-see-issue-252---"<\/dt><\/dl>)/'; + preg_match($pattern, $dump, $matches); + if (!preg_last_error() && isset($matches[1])) { + $dump = str_replace($matches[1], '', $dump); + } + } + + return $this->setSafeMarkup($dump); + } + + /** + * {@inheritdoc} + */ + public function getInternalFunctions() { + return array_merge(parent::getInternalFunctions(), \Kint\Kint::$aliases); + } + + /** + * {@inheritdoc} + */ + public static function checkRequirements() { + return class_exists('Kint', TRUE); + } + +} diff --git a/web/modules/contrib/devel/src/Plugin/Devel/Dumper/VarDumper.php b/web/modules/contrib/devel/src/Plugin/Devel/Dumper/VarDumper.php new file mode 100644 index 00000000..d51ae9cf --- /dev/null +++ b/web/modules/contrib/devel/src/Plugin/Devel/Dumper/VarDumper.php @@ -0,0 +1,46 @@ +Symfony var-dumper debugging tool."), + * ) + */ +class VarDumper extends DevelDumperBase { + + /** + * {@inheritdoc} + */ + public function export($input, $name = NULL) { + $cloner = new VarCloner(); + $dumper = 'cli' === PHP_SAPI ? new CliDumper() : new HtmlDumper(); + + $output = fopen('php://memory', 'r+b'); + $dumper->dump($cloner->cloneVar($input), $output); + $output = stream_get_contents($output, -1, 0); + + if ($name) { + $output = $name . ' => ' . $output; + } + + return $this->setSafeMarkup($output); + } + + /** + * {@inheritdoc} + */ + public static function checkRequirements() { + return class_exists('Symfony\Component\VarDumper\Cloner\VarCloner', TRUE); + } + +} diff --git a/web/modules/contrib/devel/src/Plugin/Mail/DevelMailLog.php b/web/modules/contrib/devel/src/Plugin/Mail/DevelMailLog.php new file mode 100644 index 00000000..354fcb2a --- /dev/null +++ b/web/modules/contrib/devel/src/Plugin/Mail/DevelMailLog.php @@ -0,0 +1,203 @@ +config = $config_factory->get('devel.settings'); + $this->fileSystem = $file_system; + } + + /** + * {@inheritdoc} + */ + public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) { + return new static( + $configuration, + $plugin_id, + $plugin_definition, + $container->get('config.factory'), + $container->get('file_system') + ); + } + + /** + * {@inheritdoc} + */ + public function mail(array $message) { + $directory = $this->config->get('debug_mail_directory'); + + if (!$this->prepareDirectory($directory)) { + return FALSE; + } + + $pattern = $this->config->get('debug_mail_file_format'); + $filename = $this->replacePlaceholders($pattern, $message); + $output = $this->composeMessage($message); + + return (bool) file_put_contents($directory . '/' . $filename, $output); + } + + /** + * {@inheritdoc} + */ + public function format(array $message) { + // Join the body array into one string. + $message['body'] = implode("\n\n", $message['body']); + + // Convert any HTML to plain-text. + $message['body'] = MailFormatHelper::htmlToText($message['body']); + // Wrap the mail body for sending. + $message['body'] = MailFormatHelper::wrapMail($message['body']); + + return $message; + } + + /** + * Compose the output message. + * + * @param array $message + * A message array, as described in hook_mail_alter(). + * + * @return string + * The output message. + */ + protected function composeMessage(array $message) { + $mimeheaders = []; + $message['headers']['To'] = $message['to']; + foreach ($message['headers'] as $name => $value) { + $mimeheaders[] = $name . ': ' . Unicode::mimeHeaderEncode($value); + } + + $line_endings = Settings::get('mail_line_endings', PHP_EOL); + $output = implode($line_endings, $mimeheaders) . $line_endings; + // 'Subject:' is a mail header and should not be translated. + $output .= 'Subject: ' . $message['subject'] . $line_endings; + // Blank line to separate headers from body. + $output .= $line_endings; + $output .= preg_replace('@\r?\n@', $line_endings, $message['body']); + return $output; + } + + /** + * Replaces placeholders with sanitized values in a string. + * + * @param string $filename + * The string that contains the placeholders. The following placeholders + * are considered in the replacement: + * - %to: replaced by the email recipient value. + * - %subject: replaced by the email subject value. + * - %datetime: replaced by the current datetime in 'y-m-d_his' format. + * @param array $message + * A message array, as described in hook_mail_alter(). + * + * @return string + * The formatted string. + */ + protected function replacePlaceholders($filename, array $message) { + $tokens = [ + '%to' => $message['to'], + '%subject' => $message['subject'], + '%datetime' => date('y-m-d_his'), + ]; + $filename = str_replace(array_keys($tokens), array_values($tokens), $filename); + return preg_replace('/[^a-zA-Z0-9_\-\.@]/', '_', $filename); + } + + /** + * Checks that the directory exists and is writable. + * + * Public directories will be protected by adding an .htaccess which + * indicates that the directory is private. + * + * @param string $directory + * A string reference containing the name of a directory path or URI. + * + * @return bool + * TRUE if the directory exists (or was created), is writable and is + * protected (if it is public). FALSE otherwise. + */ + protected function prepareDirectory($directory) { + if (!$this->fileSystem->prepareDirectory($directory, FileSystemInterface::CREATE_DIRECTORY)) { + return FALSE; + } + if (0 === strpos($directory, 'public://')) { + return FileSecurity::writeHtaccess($directory); + } + + return TRUE; + } + +} diff --git a/web/modules/contrib/devel/src/Plugin/Menu/DestinationMenuLink.php b/web/modules/contrib/devel/src/Plugin/Menu/DestinationMenuLink.php new file mode 100644 index 00000000..4edf1c32 --- /dev/null +++ b/web/modules/contrib/devel/src/Plugin/Menu/DestinationMenuLink.php @@ -0,0 +1,32 @@ +')->toString(); + return $options; + } + + /** + * {@inheritdoc} + * + * @todo Make cacheable once https://www.drupal.org/node/2582797 lands. + */ + public function getCacheMaxAge() { + return 0; + } + +} diff --git a/web/modules/contrib/devel/src/Plugin/Menu/RouteDetailMenuLink.php b/web/modules/contrib/devel/src/Plugin/Menu/RouteDetailMenuLink.php new file mode 100644 index 00000000..92299180 --- /dev/null +++ b/web/modules/contrib/devel/src/Plugin/Menu/RouteDetailMenuLink.php @@ -0,0 +1,29 @@ +')->getInternalPath(); + return $options; + } + + /** + * {@inheritdoc} + */ + public function getCacheMaxAge() { + return 0; + } + +} diff --git a/web/modules/contrib/devel/src/Render/FilteredMarkup.php b/web/modules/contrib/devel/src/Render/FilteredMarkup.php new file mode 100644 index 00000000..2d144a0f --- /dev/null +++ b/web/modules/contrib/devel/src/Render/FilteredMarkup.php @@ -0,0 +1,23 @@ +entityTypeManager = $entity_manager; + } + + /** + * {@inheritdoc} + */ + protected function alterRoutes(RouteCollection $collection) { + foreach ($this->entityTypeManager->getDefinitions() as $entity_type_id => $entity_type) { + if ($route = $this->getEntityLoadRoute($entity_type)) { + $collection->add("entity.$entity_type_id.devel_load", $route); + } + if ($route = $this->getEntityRenderRoute($entity_type)) { + $collection->add("entity.$entity_type_id.devel_render", $route); + } + if ($route = $this->getEntityTypeDefinitionRoute($entity_type)) { + $collection->add("entity.$entity_type_id.devel_definition", $route); + } + } + } + + /** + * Gets the entity load route. + * + * @param \Drupal\Core\Entity\EntityTypeInterface $entity_type + * The entity type. + * + * @return \Symfony\Component\Routing\Route|null + * The generated route, if available. + */ + protected function getEntityLoadRoute(EntityTypeInterface $entity_type) { + if ($devel_load = $entity_type->getLinkTemplate('devel-load')) { + $entity_type_id = $entity_type->id(); + $route = new Route($devel_load); + $route + ->addDefaults([ + '_controller' => '\Drupal\devel\Controller\EntityDebugController::entityLoad', + '_title' => 'Devel Load', + ]) + ->addRequirements([ + '_permission' => 'access devel information', + ]) + ->setOption('_admin_route', TRUE) + ->setOption('_devel_entity_type_id', $entity_type_id) + ->setOption('parameters', [ + $entity_type_id => ['type' => 'entity:' . $entity_type_id], + ]); + + return $route; + } + } + + /** + * Gets the entity render route. + * + * @param \Drupal\Core\Entity\EntityTypeInterface $entity_type + * The entity type. + * + * @return \Symfony\Component\Routing\Route|null + * The generated route, if available. + */ + protected function getEntityRenderRoute(EntityTypeInterface $entity_type) { + if ($devel_render = $entity_type->getLinkTemplate('devel-render')) { + $entity_type_id = $entity_type->id(); + $route = new Route($devel_render); + $route + ->addDefaults([ + '_controller' => '\Drupal\devel\Controller\EntityDebugController::entityRender', + '_title' => 'Devel Render', + ]) + ->addRequirements([ + '_permission' => 'access devel information', + ]) + ->setOption('_admin_route', TRUE) + ->setOption('_devel_entity_type_id', $entity_type_id) + ->setOption('parameters', [ + $entity_type_id => ['type' => 'entity:' . $entity_type_id], + ]); + + return $route; + } + } + + /** + * Gets the entity type definition route. + * + * @param \Drupal\Core\Entity\EntityTypeInterface $entity_type + * The entity type. + * + * @return \Symfony\Component\Routing\Route|null + * The generated route, if available. + */ + protected function getEntityTypeDefinitionRoute(EntityTypeInterface $entity_type) { + if ($devel_definition = $entity_type->getLinkTemplate('devel-definition')) { + $entity_type_id = $entity_type->id(); + $route = new Route($devel_definition); + $route + ->addDefaults([ + '_controller' => '\Drupal\devel\Controller\EntityDebugController::entityTypeDefinition', + '_title' => 'Entity type definition', + ]) + ->addRequirements([ + '_permission' => 'access devel information', + ]) + ->setOption('_admin_route', TRUE) + ->setOption('_devel_entity_type_id', $entity_type_id) + ->setOption('parameters', [ + $entity_type_id => ['type' => 'entity:' . $entity_type_id], + ]); + + return $route; + } + } + + /** + * {@inheritdoc} + */ + public static function getSubscribedEvents() { + $events = parent::getSubscribedEvents(); + $events[RoutingEvents::ALTER] = ['onAlterRoutes', 100]; + return $events; + } + +} diff --git a/web/modules/contrib/devel/src/ToolbarHandler.php b/web/modules/contrib/devel/src/ToolbarHandler.php new file mode 100644 index 00000000..cfdb955d --- /dev/null +++ b/web/modules/contrib/devel/src/ToolbarHandler.php @@ -0,0 +1,189 @@ +menuLinkTree = $menu_link_tree; + $this->config = $config_factory->get('devel.toolbar.settings'); + $this->account = $account; + } + + /** + * {@inheritdoc} + */ + public static function create(ContainerInterface $container) { + return new static( + $container->get('toolbar.menu_tree'), + $container->get('config.factory'), + $container->get('current_user') + ); + } + + /** + * {@inheritdoc} + */ + public static function trustedCallbacks() { + return ['lazyBuilder']; + } + + /** + * Hook bridge. + * + * @return array + * The devel toolbar items render array. + * + * @see hook_toolbar() + */ + public function toolbar() { + $items['devel'] = [ + '#cache' => [ + 'contexts' => ['user.permissions'], + ], + ]; + + if ($this->account->hasPermission('access devel information')) { + $items['devel'] += [ + '#type' => 'toolbar_item', + '#weight' => 999, + 'tab' => [ + '#type' => 'link', + '#title' => $this->t('Devel'), + '#url' => Url::fromRoute('devel.admin_settings'), + '#attributes' => [ + 'title' => $this->t('Development menu'), + 'class' => ['toolbar-icon', 'toolbar-icon-devel'], + ], + ], + 'tray' => [ + '#heading' => $this->t('Development menu'), + 'devel_menu' => [ + // Currently devel menu is uncacheable, so instead of poisoning the + // entire page cache we use a lazy builder. + // @see \Drupal\devel\Plugin\Menu\DestinationMenuLink + // @see \Drupal\devel\Plugin\Menu\RouteDetailMenuItem + '#lazy_builder' => [ToolbarHandler::class . ':lazyBuilder', []], + // Force the creation of the placeholder instead of rely on the + // automatical placeholdering or otherwise the page results + // uncacheable when max-age 0 is bubbled up. + '#create_placeholder' => TRUE, + ], + 'configuration' => [ + '#type' => 'link', + '#title' => $this->t('Configure'), + '#url' => Url::fromRoute('devel.toolbar.settings_form'), + '#options' => [ + 'attributes' => ['class' => ['edit-devel-toolbar']], + ], + ], + ], + '#attached' => [ + 'library' => 'devel/devel-toolbar', + ], + ]; + } + + return $items; + } + + /** + * Lazy builder callback for the devel menu toolbar. + * + * @return array + * The renderable array rapresentation of the devel menu. + */ + public function lazyBuilder() { + $parameters = new MenuTreeParameters(); + $parameters->onlyEnabledLinks()->setTopLevelOnly(); + + $tree = $this->menuLinkTree->load('devel', $parameters); + + $manipulators = [ + ['callable' => 'menu.default_tree_manipulators:checkAccess'], + ['callable' => 'menu.default_tree_manipulators:generateIndexAndSort'], + ['callable' => ToolbarHandler::class . ':processTree'], + ]; + $tree = $this->menuLinkTree->transform($tree, $manipulators); + + $build = $this->menuLinkTree->build($tree); + + CacheableMetadata::createFromRenderArray($build) + ->addCacheableDependency($this->config) + ->applyTo($build); + + return $build; + } + + /** + * Adds toolbar-specific attributes to the menu link tree. + * + * @param \Drupal\Core\Menu\MenuLinkTreeElement[] $tree + * The menu link tree to manipulate. + * + * @return \Drupal\Core\Menu\MenuLinkTreeElement[] + * The manipulated menu link tree. + */ + public function processTree(array $tree) { + $visible_items = $this->config->get('toolbar_items') ?: []; + + foreach ($tree as $element) { + $plugin_id = $element->link->getPluginId(); + if (!in_array($plugin_id, $visible_items)) { + // Add a class that allow to hide the non prioritized menu items when + // the toolbar has horizontal orientation. + $element->options['attributes']['class'][] = 'toolbar-horizontal-item-hidden'; + } + } + + return $tree; + } + +} diff --git a/web/modules/contrib/devel/src/Twig/Extension/Debug.php b/web/modules/contrib/devel/src/Twig/Extension/Debug.php new file mode 100644 index 00000000..e9f7e168 --- /dev/null +++ b/web/modules/contrib/devel/src/Twig/Extension/Debug.php @@ -0,0 +1,243 @@ +dumper = $dumper; + } + + /** + * {@inheritdoc} + */ + public function getName() { + return 'devel_debug'; + } + + /** + * {@inheritdoc} + */ + public function getFunctions() { + $options = [ + 'is_safe' => ['html'], + 'needs_environment' => TRUE, + 'needs_context' => TRUE, + 'is_variadic' => TRUE, + ]; + + return [ + new \Twig_SimpleFunction('devel_dump', [$this, 'dump'], $options), + new \Twig_SimpleFunction('kpr', [$this, 'dump'], $options), + // Preserve familiar kint() function for dumping + new \Twig_SimpleFunction('kint', [$this, 'dump'], $options), + new \Twig_SimpleFunction('devel_message', [$this, 'message'], $options), + new \Twig_SimpleFunction('dpm', [$this, 'message'], $options), + new \Twig_SimpleFunction('dsm', [$this, 'message'], $options), + new \Twig_SimpleFunction('devel_breakpoint', [$this, 'breakpoint'], [ + 'needs_environment' => TRUE, + 'needs_context' => TRUE, + 'is_variadic' => TRUE, + ]), + ]; + } + + /** + * Provides debug function to Twig templates. + * + * Handles 0, 1, or multiple arguments. + * + * @param \Twig_Environment $env + * The twig environment instance. + * @param array $context + * An array of parameters passed to the template. + * @param array $args + * An array of parameters passed the function. + * + * @return string + * String representation of the input variables. + * + * @see \Drupal\devel\DevelDumperManager::dump() + */ + public function dump(\Twig_Environment $env, array $context, array $args = []) { + if (!$env->isDebug()) { + return NULL; + } + + ob_start(); + + // No arguments passed, display full Twig context. + if (empty($args)) { + $context_variables = $this->getContextVariables($context); + $this->dumper->dump($context_variables, 'Twig context'); + } + else { + $parameters = $this->guessTwigFunctionParameters(); + + foreach ($args as $index => $variable) { + $name = !empty($parameters[$index]) ? $parameters[$index] : NULL; + $this->dumper->dump($variable, $name); + } + } + + return ob_get_clean(); + } + + /** + * Provides debug function to Twig templates. + * + * Handles 0, 1, or multiple arguments. + * + * @param \Twig_Environment $env + * The twig environment instance. + * @param array $context + * An array of parameters passed to the template. + * @param array $args + * An array of parameters passed the function. + * + * @see \Drupal\devel\DevelDumperManager::message() + */ + public function message(\Twig_Environment $env, array $context, array $args = []) { + if (!$env->isDebug()) { + return; + } + + // No arguments passed, display full Twig context. + if (empty($args)) { + $context_variables = $this->getContextVariables($context); + $this->dumper->message($context_variables, 'Twig context'); + } + else { + $parameters = $this->guessTwigFunctionParameters(); + + foreach ($args as $index => $variable) { + $name = !empty($parameters[$index]) ? $parameters[$index] : NULL; + $this->dumper->message($variable, $name); + } + } + + } + + /** + * Provides XDebug integration for Twig templates. + * + * To use this features simply put the following statement in the template + * of interest: + * + * @code + * {{ devel_breakpoint() }} + * @endcode + * + * When the template is evaluated is made a call to a dedicated method in + * devel twig debug extension in which is used xdebug_break(), that emits a + * breakpoint to the debug client (the debugger break on the specific line as + * if a normal file/line breakpoint was set on this line). + * In this way you'll be able to inspect any variables available in the + * template (environment, context, specific variables etc..) in your IDE. + * + * @param \Twig_Environment $env + * The twig environment instance. + * @param array $context + * An array of parameters passed to the template. + * @param array $args + * An array of parameters passed the function. + */ + public function breakpoint(\Twig_Environment $env, array $context, array $args = []) { + if (!$env->isDebug()) { + return; + } + + if (function_exists('xdebug_break')) { + xdebug_break(); + } + } + + /** + * Filters the Twig context variable. + * + * @param array $context + * The Twig context. + * + * @return array + * An array Twig context variables. + */ + protected function getContextVariables(array $context) { + $context_variables = []; + foreach ($context as $key => $value) { + if (!$value instanceof \Twig_Template) { + $context_variables[$key] = $value; + } + } + return $context_variables; + } + + /** + * Gets the twig function parameters for the current invocation. + * + * @return array + * The detected twig function parameters. + */ + protected function guessTwigFunctionParameters() { + $callee = NULL; + $template = NULL; + + $backtrace = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS | DEBUG_BACKTRACE_PROVIDE_OBJECT); + + foreach ($backtrace as $index => $trace) { + if (isset($trace['object']) && $trace['object'] instanceof \Twig_Template && 'Twig_Template' !== get_class($trace['object'])) { + $template = $trace['object']; + $callee = $backtrace[$index - 1]; + break; + } + } + + $parameters = []; + + /** @var \Twig_Template $template */ + if (NULL !== $template && NULL !== $callee) { + $line_number = $callee['line']; + $debug_infos = $template->getDebugInfo(); + + if (isset($debug_infos[$line_number])) { + $source_line = $debug_infos[$line_number]; + $source_file_name = $template->getTemplateName(); + + if (is_readable($source_file_name)) { + $source = file($source_file_name, FILE_IGNORE_NEW_LINES); + $line = $source[$source_line - 1]; + + preg_match('/\((.+)\)/', $line, $matches); + if (isset($matches[1])) { + $parameters = array_map('trim', explode(',', $matches[1])); + } + } + } + } + + return $parameters; + } + +} diff --git a/web/modules/contrib/devel/tests/modules/devel_dumper_test/css/devel_dumper_test.css b/web/modules/contrib/devel/tests/modules/devel_dumper_test/css/devel_dumper_test.css new file mode 100644 index 00000000..62a91dbc --- /dev/null +++ b/web/modules/contrib/devel/tests/modules/devel_dumper_test/css/devel_dumper_test.css @@ -0,0 +1,3 @@ +.some-rule { + display: block; +} diff --git a/web/modules/contrib/devel/tests/modules/devel_dumper_test/devel_dumper_test.info.yml b/web/modules/contrib/devel/tests/modules/devel_dumper_test/devel_dumper_test.info.yml new file mode 100644 index 00000000..da40934e --- /dev/null +++ b/web/modules/contrib/devel/tests/modules/devel_dumper_test/devel_dumper_test.info.yml @@ -0,0 +1,10 @@ +name: 'Devel dumper test module' +type: module +description: 'Test pluggable dumpers.' +package: Testing +core_version_requirement: ^8.8 || ^9 + +# Information added by Drupal.org packaging script on 2020-12-31 +version: '4.1.1' +project: 'devel' +datestamp: 1609419530 diff --git a/web/modules/contrib/devel/tests/modules/devel_dumper_test/devel_dumper_test.libraries.yml b/web/modules/contrib/devel/tests/modules/devel_dumper_test/devel_dumper_test.libraries.yml new file mode 100644 index 00000000..8e8c2ad8 --- /dev/null +++ b/web/modules/contrib/devel/tests/modules/devel_dumper_test/devel_dumper_test.libraries.yml @@ -0,0 +1,7 @@ +devel_dumper_test: + version: 0 + css: + theme: + css/devel_dumper_test.css: {} + js: + js/devel_dumper_test.js: {} diff --git a/web/modules/contrib/devel/tests/modules/devel_dumper_test/devel_dumper_test.routing.yml b/web/modules/contrib/devel/tests/modules/devel_dumper_test/devel_dumper_test.routing.yml new file mode 100644 index 00000000..589193b8 --- /dev/null +++ b/web/modules/contrib/devel/tests/modules/devel_dumper_test/devel_dumper_test.routing.yml @@ -0,0 +1,40 @@ +devel_dumper_test.dump: + path: '/devel_dumper_test/dump' + defaults: + _controller: '\Drupal\devel_dumper_test\Controller\DumperTestController::dump' + _title: 'Devel Dumper Test' + requirements: + _permission: 'access devel information' + +devel_dumper_test.message: + path: '/devel_dumper_test/message' + defaults: + _controller: '\Drupal\devel_dumper_test\Controller\DumperTestController::message' + _title: 'Devel Dumper Test' + requirements: + _permission: 'access devel information' + +devel_dumper_test.export: + path: '/devel_dumper_test/export' + defaults: + _controller: '\Drupal\devel_dumper_test\Controller\DumperTestController::export' + _title: 'Devel Dumper Test' + requirements: + _permission: 'access devel information' + +devel_dumper_test.export_renderable: + path: '/devel_dumper_test/export_renderable' + defaults: + _controller: '\Drupal\devel_dumper_test\Controller\DumperTestController::exportRenderable' + _title: 'Devel Dumper Test' + requirements: + _permission: 'access devel information' + +devel_dumper_test.debug: + path: '/devel_dumper_test/debug' + defaults: + _controller: '\Drupal\devel_dumper_test\Controller\DumperTestController::debug' + _title: 'Devel Dumper Test' + requirements: + # Specifically give access to all users for testing in testDumpersOutput(). + _access: 'TRUE' diff --git a/web/modules/contrib/devel/tests/modules/devel_dumper_test/js/devel_dumper_test.js b/web/modules/contrib/devel/tests/modules/devel_dumper_test/js/devel_dumper_test.js new file mode 100644 index 00000000..e69de29b diff --git a/web/modules/contrib/devel/tests/modules/devel_dumper_test/src/Controller/DumperTestController.php b/web/modules/contrib/devel/tests/modules/devel_dumper_test/src/Controller/DumperTestController.php new file mode 100644 index 00000000..71e4c424 --- /dev/null +++ b/web/modules/contrib/devel/tests/modules/devel_dumper_test/src/Controller/DumperTestController.php @@ -0,0 +1,106 @@ +dumper = $devel_dumper_manager; + } + + /** + * {@inheritdoc} + */ + public static function create(ContainerInterface $container) { + return new static( + $container->get('devel.dumper') + ); + } + + /** + * Returns the dump output to test. + * + * @return array + * The render array output. + */ + public function dump() { + $this->dumper->dump('Test output'); + + return [ + '#markup' => 'test', + ]; + } + + /** + * Returns the message output to test. + * + * @return array + * The render array output. + */ + public function message() { + $this->dumper->message('Test output'); + + return [ + '#markup' => 'test', + ]; + } + + /** + * Returns the debug output to test. + * + * @return array + * The render array output. + */ + public function debug() { + $this->dumper->debug('Test output'); + + return [ + '#markup' => 'test', + ]; + } + + /** + * Returns the export output to test. + * + * @return array + * The render array output. + */ + public function export() { + return [ + '#markup' => $this->dumper->export('Test output'), + ]; + } + + /** + * Returns the renderable export output to test. + * + * @return array + * The render array output. + */ + public function exportRenderable() { + return $this->dumper->exportAsRenderable('Test output'); + } + +} diff --git a/web/modules/contrib/devel/tests/modules/devel_dumper_test/src/Plugin/Devel/Dumper/AvailableTestDumper.php b/web/modules/contrib/devel/tests/modules/devel_dumper_test/src/Plugin/Devel/Dumper/AvailableTestDumper.php new file mode 100644 index 00000000..526c8d40 --- /dev/null +++ b/web/modules/contrib/devel/tests/modules/devel_dumper_test/src/Plugin/Devel/Dumper/AvailableTestDumper.php @@ -0,0 +1,61 @@ +' . 'AvailableTestDumper::dump() ' . $input . '
'; + echo $input; + } + + /** + * {@inheritdoc} + */ + public function export($input, $name = NULL) { + // Add a predetermined string to $input to check if this dumper has been + // selected successfully. + $input = '
' . 'AvailableTestDumper::export() ' . $input . '
'; + return $this->setSafeMarkup($input); + } + + /** + * {@inheritdoc} + */ + public function exportAsRenderable($input, $name = NULL) { + // Add a predetermined string to $input to check if this dumper has been + // selected successfully. + $input = '
' . 'AvailableTestDumper::exportAsRenderable() ' . $input . '
'; + + return [ + '#attached' => [ + 'library' => ['devel_dumper_test/devel_dumper_test'], + ], + '#markup' => $this->setSafeMarkup($input), + ]; + } + + /** + * {@inheritdoc} + */ + public static function checkRequirements() { + return TRUE; + } + +} diff --git a/web/modules/contrib/devel/tests/modules/devel_dumper_test/src/Plugin/Devel/Dumper/NotAvailableTestDumper.php b/web/modules/contrib/devel/tests/modules/devel_dumper_test/src/Plugin/Devel/Dumper/NotAvailableTestDumper.php new file mode 100644 index 00000000..2b0d886e --- /dev/null +++ b/web/modules/contrib/devel/tests/modules/devel_dumper_test/src/Plugin/Devel/Dumper/NotAvailableTestDumper.php @@ -0,0 +1,41 @@ +' . $input . '
'; + echo $input; + } + + /** + * {@inheritdoc} + */ + public function export($input, $name = NULL) { + $input = '
' . $input . '
'; + return $this->setSafeMarkup($input); + } + + /** + * {@inheritdoc} + */ + public static function checkRequirements() { + return FALSE; + } + +} diff --git a/web/modules/contrib/devel/tests/modules/devel_entity_test/devel_entity_test.info.yml b/web/modules/contrib/devel/tests/modules/devel_entity_test/devel_entity_test.info.yml new file mode 100644 index 00000000..157eca0b --- /dev/null +++ b/web/modules/contrib/devel/tests/modules/devel_entity_test/devel_entity_test.info.yml @@ -0,0 +1,14 @@ +name: 'Devel entity test module' +type: module +description: 'Provides entity types for Devel tests.' +package: Testing +core_version_requirement: ^8.8 || ^9 +dependencies: + - drupal:field + - drupal:text + - drupal:entity_test + +# Information added by Drupal.org packaging script on 2020-12-31 +version: '4.1.1' +project: 'devel' +datestamp: 1609419530 diff --git a/web/modules/contrib/devel/tests/modules/devel_entity_test/devel_entity_test.links.task.yml b/web/modules/contrib/devel/tests/modules/devel_entity_test/devel_entity_test.links.task.yml new file mode 100644 index 00000000..052baa9c --- /dev/null +++ b/web/modules/contrib/devel/tests/modules/devel_entity_test/devel_entity_test.links.task.yml @@ -0,0 +1,2 @@ +devel_entity_test.local_tasks: + deriver: 'Drupal\devel_entity_test\Plugin\Derivative\DevelEntityTestLocalTasks' diff --git a/web/modules/contrib/devel/tests/modules/devel_entity_test/devel_entity_test.module b/web/modules/contrib/devel/tests/modules/devel_entity_test/devel_entity_test.module new file mode 100644 index 00000000..dd88c492 --- /dev/null +++ b/web/modules/contrib/devel/tests/modules/devel_entity_test/devel_entity_test.module @@ -0,0 +1,29 @@ +getDefinitions(); + foreach ($entity_info as $entity_type => $info) { + if ($entity_info[$entity_type]->getProvider() == 'devel_entity_test_canonical' && !isset($view_modes[$entity_type])) { + $view_modes[$entity_type] = [ + 'full' => [ + 'label' => t('Full object'), + 'status' => TRUE, + 'cache' => TRUE, + ], + 'teaser' => [ + 'label' => t('Teaser'), + 'status' => TRUE, + 'cache' => TRUE, + ], + ]; + } + } +} diff --git a/web/modules/contrib/devel/tests/modules/devel_entity_test/src/Entity/DevelEntityTestCanonical.php b/web/modules/contrib/devel/tests/modules/devel_entity_test/src/Entity/DevelEntityTestCanonical.php new file mode 100644 index 00000000..e7ed04f3 --- /dev/null +++ b/web/modules/contrib/devel/tests/modules/devel_entity_test/src/Entity/DevelEntityTestCanonical.php @@ -0,0 +1,44 @@ +derivatives = []; + + $this->derivatives['devel_entity_test_canonical.canonical'] = []; + $this->derivatives['devel_entity_test_canonical.canonical']['base_route'] = "entity.devel_entity_test_canonical.canonical"; + $this->derivatives['devel_entity_test_canonical.canonical']['route_name'] = "entity.devel_entity_test_canonical.canonical"; + $this->derivatives['devel_entity_test_canonical.canonical']['title'] = 'View'; + + $this->derivatives['devel_entity_test_edit.edit'] = []; + $this->derivatives['devel_entity_test_edit.edit']['base_route'] = "entity.devel_entity_test_edit.edit_form"; + $this->derivatives['devel_entity_test_edit.edit']['route_name'] = "entity.devel_entity_test_edit.edit_form"; + $this->derivatives['devel_entity_test_edit.edit']['title'] = 'Edit'; + + return parent::getDerivativeDefinitions($base_plugin_definition); + } + +} diff --git a/web/modules/contrib/devel/tests/modules/devel_test/devel_test.info.yml b/web/modules/contrib/devel/tests/modules/devel_test/devel_test.info.yml new file mode 100644 index 00000000..c1d52022 --- /dev/null +++ b/web/modules/contrib/devel/tests/modules/devel_test/devel_test.info.yml @@ -0,0 +1,10 @@ +name: 'Devel test module' +type: module +description: 'Support module for Devel testing.' +package: Testing +core_version_requirement: ^8.8 || ^9 + +# Information added by Drupal.org packaging script on 2020-12-31 +version: '4.1.1' +project: 'devel' +datestamp: 1609419530 diff --git a/web/modules/contrib/devel/tests/modules/devel_test/devel_test.module b/web/modules/contrib/devel/tests/modules/devel_test/devel_test.module new file mode 100644 index 00000000..e94fb715 --- /dev/null +++ b/web/modules/contrib/devel/tests/modules/devel_test/devel_test.module @@ -0,0 +1,20 @@ + $this->t('Simple page'), + ]; + } + +} diff --git a/web/modules/contrib/devel/tests/modules/devel_test/src/Routing/TestRouteSubscriber.php b/web/modules/contrib/devel/tests/modules/devel_test/src/Routing/TestRouteSubscriber.php new file mode 100644 index 00000000..636a38fb --- /dev/null +++ b/web/modules/contrib/devel/tests/modules/devel_test/src/Routing/TestRouteSubscriber.php @@ -0,0 +1,38 @@ +state = $state; + } + + /** + * {@inheritdoc} + */ + protected function alterRoutes(RouteCollection $collection) { + $this->state->set('devel_test_route_rebuild', 'Router rebuild fired'); + } + +} diff --git a/web/modules/contrib/devel/tests/src/Functional/DevelBrowserTestBase.php b/web/modules/contrib/devel/tests/src/Functional/DevelBrowserTestBase.php new file mode 100644 index 00000000..38571f85 --- /dev/null +++ b/web/modules/contrib/devel/tests/src/Functional/DevelBrowserTestBase.php @@ -0,0 +1,55 @@ +adminUser = $this->drupalCreateUser([ + 'access devel information', + 'administer site configuration', + ]); + + $this->develUser = $this->drupalCreateUser([ + 'access devel information', + ]); + } + +} diff --git a/web/modules/contrib/devel/tests/src/Functional/DevelCommandsTest.php b/web/modules/contrib/devel/tests/src/Functional/DevelCommandsTest.php new file mode 100644 index 00000000..0361dd74 --- /dev/null +++ b/web/modules/contrib/devel/tests/src/Functional/DevelCommandsTest.php @@ -0,0 +1,44 @@ +drush('devel:token', [], ['format' => 'json']); + $output = $this->getOutputFromJSON(); + $tokens = array_column($output, 'token'); + $this->assertContains('account-name', $tokens); + + $this->drush('devel:services', [], ['format' => 'json']); + $output = $this->getOutputFromJSON(); + $this->assertContains('current_user', $output); + } + +} diff --git a/web/modules/contrib/devel/tests/src/Functional/DevelContainerInfoTest.php b/web/modules/contrib/devel/tests/src/Functional/DevelContainerInfoTest.php new file mode 100644 index 00000000..938d71bb --- /dev/null +++ b/web/modules/contrib/devel/tests/src/Functional/DevelContainerInfoTest.php @@ -0,0 +1,245 @@ +drupalPlaceBlock('local_tasks_block'); + $this->drupalPlaceBlock('page_title_block'); + $this->drupalLogin($this->develUser); + } + + /** + * Tests container info menu link. + */ + public function testContainerInfoMenuLink() { + $this->drupalPlaceBlock('system_menu_block:devel'); + // Ensures that the events info link is present on the devel menu and that + // it points to the correct page. + $this->drupalGet(''); + $this->clickLink('Container Info'); + $this->assertSession()->statusCodeEquals(200); + $this->assertSession()->addressEquals('/devel/container/service'); + $this->assertSession()->pageTextContains('Container services'); + } + + /** + * Tests service list page. + */ + public function testServiceList() { + $this->drupalGet('/devel/container/service'); + $this->assertSession()->statusCodeEquals(200); + $this->assertSession()->pageTextContains('Container services'); + $this->assertContainerInfoLocalTasks(); + + $page = $this->getSession()->getPage(); + + // Ensures that the services table is found. + $table = $page->find('css', 'table.devel-service-list'); + $this->assertNotNull($table); + + // Ensures that the expected table headers are found. + /* @var $headers \Behat\Mink\Element\NodeElement[] */ + $headers = $table->findAll('css', 'thead th'); + $this->assertEquals(4, count($headers)); + + $expected_headers = ['ID', 'Class', 'Alias', 'Operations']; + $actual_headers = array_map(function ($element) { + return $element->getText(); + }, $headers); + $this->assertSame($expected_headers, $actual_headers); + + // Ensures that all the serivices are listed in the table. + $cached_definition = \Drupal::service('kernel')->getCachedContainerDefinition(); + $this->assertNotNull($cached_definition); + $rows = $table->findAll('css', 'tbody tr'); + $this->assertEquals(count($cached_definition['services']), count($rows)); + + // Tests the presence of some (arbitrarily chosen) services in the table. + $expected_services = [ + 'config.factory' => [ + 'class' => 'Drupal\Core\Config\ConfigFactory', + 'alias' => '', + ], + 'devel.route_subscriber' => [ + 'class' => 'Drupal\devel\Routing\RouteSubscriber', + 'alias' => '', + ], + 'plugin.manager.element_info' => [ + 'class' => 'Drupal\Core\Render\ElementInfoManager', + 'alias' => 'element_info', + ], + ]; + + foreach ($expected_services as $service_id => $expected) { + $row = $table->find('css', sprintf('tbody tr:contains("%s")', $service_id)); + $this->assertNotNull($row); + + /* @var $cells \Behat\Mink\Element\NodeElement[] */ + $cells = $row->findAll('css', 'td'); + $this->assertEquals(4, count($cells)); + + $cell_service_id = $cells[0]; + $this->assertEquals($service_id, $cell_service_id->getText()); + $this->assertTrue($cell_service_id->hasClass('table-filter-text-source')); + + $cell_class = $cells[1]; + $this->assertEquals($expected['class'], $cell_class->getText()); + $this->assertTrue($cell_class->hasClass('table-filter-text-source')); + + $cell_alias = $cells[2]; + $this->assertEquals($expected['alias'], $cell_alias->getText()); + $this->assertTrue($cell_class->hasClass('table-filter-text-source')); + + $cell_operations = $cells[3]; + $actual_href = $cell_operations->findLink('Devel')->getAttribute('href'); + $expected_href = Url::fromRoute('devel.container_info.service.detail', ['service_id' => $service_id])->toString(); + $this->assertEquals($expected_href, $actual_href); + } + + // Ensures that the page is accessible ony to users with the adequate + // permissions. + $this->drupalLogout(); + $this->drupalGet('devel/container/service'); + $this->assertSession()->statusCodeEquals(403); + } + + /** + * Tests service detail page. + */ + public function testServiceDetail() { + $service_id = 'devel.dumper'; + + // Ensures that the page works as expected. + $this->drupalGet("/devel/container/service/$service_id"); + $this->assertSession()->statusCodeEquals(200); + $this->assertSession()->pageTextContains("Service $service_id detail"); + + // Ensures that the page returns a 404 error if the requested service is + // not defined. + $this->drupalGet('/devel/container/service/not.exists'); + $this->assertSession()->statusCodeEquals(404); + + // Ensures that the page is accessible ony to users with the adequate + // permissions. + $this->drupalLogout(); + $this->drupalGet("devel/container/service/$service_id"); + $this->assertSession()->statusCodeEquals(403); + } + + /** + * Tests parameter list page. + */ + public function testParameterList() { + // Ensures that the page works as expected. + $this->drupalGet('/devel/container/parameter'); + $this->assertSession()->statusCodeEquals(200); + $this->assertSession()->pageTextContains('Container parameters'); + $this->assertContainerInfoLocalTasks(); + + $page = $this->getSession()->getPage(); + + // Ensures that the parameters table is found. + $table = $page->find('css', 'table.devel-parameter-list'); + $this->assertNotNull($table); + + // Ensures that the expected table headers are found. + /* @var $headers \Behat\Mink\Element\NodeElement[] */ + $headers = $table->findAll('css', 'thead th'); + $this->assertEquals(2, count($headers)); + + $expected_headers = ['Name', 'Operations']; + $actual_headers = array_map(function ($element) { + return $element->getText(); + }, $headers); + $this->assertSame($expected_headers, $actual_headers); + + // Ensures that all the parameters are listed in the table. + $cached_definition = \Drupal::service('kernel')->getCachedContainerDefinition(); + $this->assertNotNull($cached_definition); + $rows = $table->findAll('css', 'tbody tr'); + $this->assertEquals(count($cached_definition['parameters']), count($rows)); + + // Tests the presence of some parameters in the table. + $expected_parameters = [ + 'container.modules', + 'cache_bins', + 'factory.keyvalue', + 'twig.config', + ]; + + foreach ($expected_parameters as $parameter_name) { + $row = $table->find('css', sprintf('tbody tr:contains("%s")', $parameter_name)); + $this->assertNotNull($row); + + /* @var $cells \Behat\Mink\Element\NodeElement[] */ + $cells = $row->findAll('css', 'td'); + $this->assertEquals(2, count($cells)); + + $cell_parameter_name = $cells[0]; + $this->assertEquals($parameter_name, $cell_parameter_name->getText()); + $this->assertTrue($cell_parameter_name->hasClass('table-filter-text-source')); + + $cell_operations = $cells[1]; + $actual_href = $cell_operations->findLink('Devel')->getAttribute('href'); + $expected_href = Url::fromRoute('devel.container_info.parameter.detail', ['parameter_name' => $parameter_name])->toString(); + $this->assertEquals($expected_href, $actual_href); + } + + // Ensures that the page is accessible ony to users with the adequate + // permissions. + $this->drupalLogout(); + $this->drupalGet('devel/container/service'); + $this->assertSession()->statusCodeEquals(403); + } + + /** + * Tests parameter detail page. + */ + public function testParameterDetail() { + $parameter_name = 'cache_bins'; + + // Ensures that the page works as expected. + $this->drupalGet("/devel/container/parameter/$parameter_name"); + $this->assertSession()->statusCodeEquals(200); + $this->assertSession()->pageTextContains("Parameter $parameter_name value"); + + // Ensures that the page returns a 404 error if the requested parameter is + // not defined. + $this->drupalGet('/devel/container/parameter/not_exists'); + $this->assertSession()->statusCodeEquals(404); + + // Ensures that the page is accessible ony to users with the adequate + // permissions. + $this->drupalLogout(); + $this->drupalGet("devel/container/service/$parameter_name"); + $this->assertSession()->statusCodeEquals(403); + } + + /** + * Asserts that container info local tasks are present. + */ + protected function assertContainerInfoLocalTasks() { + $expected_local_tasks = [ + ['devel.container_info.service', []], + ['devel.container_info.parameter', []], + ]; + + $this->assertLocalTasks($expected_local_tasks); + } + +} diff --git a/web/modules/contrib/devel/tests/src/Functional/DevelControllerTest.php b/web/modules/contrib/devel/tests/src/Functional/DevelControllerTest.php new file mode 100644 index 00000000..389e4a8a --- /dev/null +++ b/web/modules/contrib/devel/tests/src/Functional/DevelControllerTest.php @@ -0,0 +1,145 @@ +container->get('entity_type.manager'); + + // Create a test entity. + $random_label = $this->randomMachineName(); + $data = ['type' => 'entity_test', 'name' => $random_label]; + $this->entity = $entity_type_manager->getStorage('entity_test')->create($data); + $this->entity->save(); + + // Create a test entity with only canonical route. + $random_label = $this->randomMachineName(); + $data = ['type' => 'devel_entity_test_canonical', 'name' => $random_label]; + $this->entity_canonical = $entity_type_manager->getStorage('devel_entity_test_canonical')->create($data); + $this->entity_canonical->save(); + + // Create a test entity with only edit route. + $random_label = $this->randomMachineName(); + $data = ['type' => 'devel_entity_test_edit', 'name' => $random_label]; + $this->entity_edit = $entity_type_manager->getStorage('devel_entity_test_edit')->create($data); + $this->entity_edit->save(); + + // Create a test entity with no routes. + $random_label = $this->randomMachineName(); + $data = ['type' => 'devel_entity_test_no_links', 'name' => $random_label]; + $this->entity_no_links = $entity_type_manager->getStorage('devel_entity_test_no_links')->create($data); + $this->entity_no_links->save(); + + $this->drupalPlaceBlock('local_tasks_block'); + + $web_user = $this->drupalCreateUser([ + 'view test entity', + 'administer entity_test content', + 'access devel information', + ]); + $this->drupalLogin($web_user); + } + + /** + * Tests route generation. + */ + public function testRouteGeneration() { + // Test Devel load and render routes for entities with both route + // definitions. + $this->drupalGet('entity_test/' . $this->entity->id()); + $this->assertSession()->statusCodeEquals(200); + $this->assertSession()->LinkExists('View'); + $this->assertSession()->LinkExists('Edit'); + $this->assertSession()->LinkExists('Devel'); + $this->drupalGet('devel/entity_test/' . $this->entity->id()); + $this->assertSession()->statusCodeEquals(200); + $this->assertSession()->LinkExists('Definition'); + $this->assertSession()->LinkExists('Render'); + $this->assertSession()->LinkExists('Load'); + $this->assertSession()->linkByHrefExists('devel/entity_test/' . $this->entity->id() . '/render'); + $this->drupalGet('devel/entity_test/' . $this->entity->id() . '/render'); + $this->assertSession()->statusCodeEquals(200); + $this->assertSession()->linkByHrefExists('devel/entity_test/' . $this->entity->id() . '/definition'); + $this->drupalGet('devel/entity_test/' . $this->entity->id() . '/definition'); + $this->assertSession()->statusCodeEquals(200); + + // Test Devel load and render routes for entities with only canonical route + // definitions. + $this->drupalGet('devel_entity_test_canonical/' . $this->entity_canonical->id()); + $this->assertSession()->statusCodeEquals(200); + $this->assertSession()->LinkExists('View'); + $this->assertSession()->LinkNotExists('Edit'); + $this->assertSession()->LinkExists('Devel'); + // Use xpath with equality check on @data-drupal-link-system-path because + // assertNoLinkByHref matches on partial values and finds the other link. + $this->assertSession()->elementNotExists('xpath', + '//a[@data-drupal-link-system-path = "devel/devel_entity_test_canonical/' . $this->entity_canonical->id() . '"]'); + $this->assertSession()->elementExists('xpath', + '//a[@data-drupal-link-system-path = "devel/devel_entity_test_canonical/' . $this->entity_canonical->id() . '/render"]'); + $this->drupalGet('devel/devel_entity_test_canonical/' . $this->entity_canonical->id()); + $this->assertSession()->statusCodeEquals(404); + $this->drupalGet('devel/devel_entity_test_canonical/' . $this->entity_canonical->id() . '/render'); + $this->assertSession()->statusCodeEquals(200); + $this->assertSession()->LinkExists('Definition'); + $this->assertSession()->LinkExists('Render'); + $this->assertSession()->LinkNotExists('Load'); + $this->assertSession()->linkByHrefExists('devel/devel_entity_test_canonical/' . $this->entity_canonical->id() . '/definition'); + $this->drupalGet('devel/devel_entity_test_canonical/' . $this->entity_canonical->id() . '/definition'); + $this->assertSession()->statusCodeEquals(200); + + // Test Devel load and render routes for entities with only edit route + // definitions. + $this->drupalGet('devel_entity_test_edit/manage/' . $this->entity_edit->id()); + $this->assertSession()->statusCodeEquals(200); + $this->assertSession()->LinkNotExists('View'); + $this->assertSession()->LinkExists('Edit'); + $this->assertSession()->LinkExists('Devel'); + $this->assertSession()->linkByHrefExists('devel/devel_entity_test_edit/' . $this->entity_edit->id()); + $this->drupalGet('devel/devel_entity_test_edit/' . $this->entity_edit->id()); + $this->assertSession()->statusCodeEquals(200); + $this->assertSession()->LinkExists('Definition'); + $this->assertSession()->LinkNotExists('Render'); + $this->assertSession()->LinkExists('Load'); + $this->assertSession()->linkByHrefExists('devel/devel_entity_test_edit/' . $this->entity_edit->id() . '/definition'); + $this->assertSession()->linkByHrefNotExists('devel/devel_entity_test_edit/' . $this->entity_edit->id() . '/render'); + $this->drupalGet('devel/devel_entity_test_edit/' . $this->entity_edit->id() . '/definition'); + $this->assertSession()->statusCodeEquals(200); + $this->drupalGet('devel/devel_entity_test_edit/' . $this->entity_edit->id() . '/render'); + $this->assertSession()->statusCodeEquals(404); + + // Test Devel load and render routes for entities with no route + // definitions. + $this->drupalGet('devel_entity_test_no_links/' . $this->entity_edit->id()); + $this->assertSession()->statusCodeEquals(404); + $this->drupalGet('devel/devel_entity_test_no_links/' . $this->entity_no_links->id()); + $this->assertSession()->statusCodeEquals(404); + $this->drupalGet('devel/devel_entity_test_no_links/' . $this->entity_no_links->id() . '/render'); + $this->assertSession()->statusCodeEquals(404); + $this->drupalGet('devel/devel_entity_test_no_links/' . $this->entity_no_links->id() . '/definition'); + $this->assertSession()->statusCodeEquals(404); + } + +} diff --git a/web/modules/contrib/devel/tests/src/Functional/DevelDumperTest.php b/web/modules/contrib/devel/tests/src/Functional/DevelDumperTest.php new file mode 100644 index 00000000..812919b1 --- /dev/null +++ b/web/modules/contrib/devel/tests/src/Functional/DevelDumperTest.php @@ -0,0 +1,145 @@ +drupalLogin($this->adminUser); + } + + /** + * Test dumpers configuration page. + */ + public function testDumpersConfiguration() { + $this->drupalGet('admin/config/development/devel'); + + // Ensures that the dumper input is present on the config page. + $this->assertSession()->fieldExists('dumper'); + + // Ensures that the 'default' dumper is enabled by default. + $this->assertSession()->checkboxChecked('edit-dumper-default'); + + // Ensures that all dumpers declared by devel are present on the config page + // and that only the available dumpers are selectable. + $dumpers = [ + 'default', + 'var_dumper', + ]; + $available_dumpers = ['default', 'var_dumper']; + + foreach ($dumpers as $dumper) { + $this->assertFieldsByValue($this->xpath('//input[@type="radio" and @name="dumper"]'), $dumper); + if (in_array($dumper, $available_dumpers)) { + $this->assertFieldsByValue($this->xpath('//input[@name="dumper" and not(@disabled="disabled")]'), $dumper); + } + else { + $this->assertFieldsByValue($this->xpath('//input[@name="dumper" and @disabled="disabled"]'), $dumper); + } + } + + // Ensures that dumper plugins declared by other modules are present on the + // config page and that only the available dumpers are selectable. + $this->assertFieldsByValue($this->xpath('//input[@name="dumper"]'), 'available_test_dumper'); + $this->assertSession()->pageTextContains('Available test dumper.'); + $this->assertSession()->pageTextContains('Drupal dumper for testing purposes (available).'); + $this->assertFieldsByValue($this->xpath('//input[@name="dumper" and not(@disabled="disabled")]'), 'available_test_dumper', 'Available dumper input not is disabled.'); + + $this->assertFieldsByValue($this->xpath('//input[@name="dumper"]'), 'not_available_test_dumper'); + $this->assertSession()->pageTextContains('Not available test dumper.'); + $this->assertSession()->pageTextContains('Drupal dumper for testing purposes (not available).Not available. You may need to install external dependencies for use this plugin.'); + $this->assertFieldsByValue($this->xpath('//input[@name="dumper" and @disabled="disabled"]'), 'not_available_test_dumper', 'Non available dumper input is disabled.'); + + // Ensures that saving of the dumpers configuration works as expected. + $edit = [ + 'dumper' => 'var_dumper', + ]; + $this->drupalPostForm('admin/config/development/devel', $edit, 'Save configuration'); + $this->assertSession()->pageTextContains('The configuration options have been saved.'); + $this->assertSession()->checkboxChecked('Symfony var-dumper'); + + $config = \Drupal::config('devel.settings')->get('devel_dumper'); + $this->assertEquals('var_dumper', $config, 'The configuration options have been properly saved'); + } + + /** + * Test variable is dumped in page. + */ + public function testDumpersOutput() { + $edit = [ + 'dumper' => 'available_test_dumper', + ]; + $this->drupalPostForm('admin/config/development/devel', $edit, 'Save configuration'); + $this->assertSession()->pageTextContains('The configuration options have been saved.'); + + $this->drupalGet('devel_dumper_test/dump'); + $elements = $this->xpath('//body/pre[contains(text(), :message)]', [':message' => 'AvailableTestDumper::dump() Test output']); + $this->assertNotEmpty($elements, 'Dumped message is present.'); + + $this->drupalGet('devel_dumper_test/message'); + $elements = $this->xpath('//div[@aria-label="Status message"]/pre[contains(text(), :message)]', [':message' => 'AvailableTestDumper::export() Test output']); + $this->assertNotEmpty($elements, 'Dumped message is present.'); + + $this->drupalGet('devel_dumper_test/export'); + $elements = $this->xpath('//div[@class="layout-content"]//pre[contains(text(), :message)]', [':message' => 'AvailableTestDumper::export() Test output']); + $this->assertNotEmpty($elements, 'Dumped message is present.'); + + $this->drupalGet('devel_dumper_test/export_renderable'); + $elements = $this->xpath('//div[@class="layout-content"]//pre[contains(text(), :message)]', [':message' => 'AvailableTestDumper::exportAsRenderable() Test output']); + $this->assertNotEmpty($elements, 'Dumped message is present.'); + // Ensures that plugins can add libraries to the page when the + // ::exportAsRenderable() method is used. + $this->assertSession()->responseContains('devel_dumper_test/css/devel_dumper_test.css'); + $this->assertSession()->responseContains('devel_dumper_test/js/devel_dumper_test.js'); + + // @todo Cater for deprecated code where the replacement has not been + // backported. Remove this when support for core 8.7 is no longer required. + // @see https://www.drupal.org/project/devel/issues/3118851 + if (version_compare(\Drupal::VERSION, 8.8, '>=')) { + // For 8.8+. + $debug_filename = \Drupal::service('file_system')->getTempDirectory() . '/' . 'drupal_debug.txt'; + } + else { + // Up to 8.7. + $debug_filename = file_directory_temp() . '/drupal_debug.txt'; + } + + $this->drupalGet('devel_dumper_test/debug'); + $file_content = file_get_contents($debug_filename); + $expected = <<AvailableTestDumper::export() Test output
+ +EOF; + $this->assertEquals($file_content, $expected, 'Dumped message is present.'); + + // Ensures that the DevelDumperManager::debug() is not access checked and + // that the dump is written in the debug file even if the user has not the + // 'access devel information' permission. + file_put_contents($debug_filename, ''); + $this->drupalLogout(); + $this->drupalGet('devel_dumper_test/debug'); + $file_content = file_get_contents($debug_filename); + $expected = <<AvailableTestDumper::export() Test output + +EOF; + $this->assertEquals($file_content, $expected, 'Dumped message is present.'); + } + +} diff --git a/web/modules/contrib/devel/tests/src/Functional/DevelElementInfoTest.php b/web/modules/contrib/devel/tests/src/Functional/DevelElementInfoTest.php new file mode 100644 index 00000000..57e66045 --- /dev/null +++ b/web/modules/contrib/devel/tests/src/Functional/DevelElementInfoTest.php @@ -0,0 +1,135 @@ +drupalPlaceBlock('system_menu_block:devel'); + $this->drupalPlaceBlock('page_title_block'); + $this->drupalLogin($this->develUser); + } + + /** + * Tests element info menu link. + */ + public function testElementInfoMenuLink() { + $this->drupalPlaceBlock('system_menu_block:devel'); + // Ensures that the element info link is present on the devel menu and that + // it points to the correct page. + $this->drupalGet(''); + $this->clickLink('Element Info'); + $this->assertSession()->statusCodeEquals(200); + $this->assertSession()->addressEquals('/devel/elements'); + $this->assertSession()->pageTextContains('Element Info'); + } + + /** + * Tests element list page. + */ + public function testElementList() { + $this->drupalGet('/devel/elements'); + $this->assertSession()->statusCodeEquals(200); + $this->assertSession()->pageTextContains('Element Info'); + + $page = $this->getSession()->getPage(); + + // Ensures that the element list table is found. + $table = $page->find('css', 'table.devel-element-list'); + $this->assertNotNull($table); + + // Ensures that the expected table headers are found. + $headers = $table->findAll('css', 'thead th'); + $this->assertEquals(4, count($headers)); + + $expected_headers = ['Name', 'Provider', 'Class', 'Operations']; + $actual_headers = array_map(function (NodeElement $element) { + return $element->getText(); + }, $headers); + $this->assertSame($expected_headers, $actual_headers); + + // Tests the presence of some (arbitrarily chosen) elements in the table. + $expected_elements = [ + 'button' => [ + 'class' => 'Drupal\Core\Render\Element\Button', + 'provider' => 'core', + ], + 'form' => [ + 'class' => 'Drupal\Core\Render\Element\Form', + 'provider' => 'core', + ], + 'html' => [ + 'class' => 'Drupal\Core\Render\Element\Html', + 'provider' => 'core', + ], + ]; + + foreach ($expected_elements as $element_name => $element) { + $row = $table->find('css', sprintf('tbody tr:contains("%s")', $element_name)); + $this->assertNotNull($row); + + /* @var $cells \Behat\Mink\Element\NodeElement[] */ + $cells = $row->findAll('css', 'td'); + $this->assertEquals(4, count($cells)); + + $cell = $cells[0]; + $this->assertEquals($element_name, $cell->getText()); + $this->assertTrue($cell->hasClass('table-filter-text-source')); + + $cell = $cells[1]; + $this->assertEquals($element['provider'], $cell->getText()); + $this->assertTrue($cell->hasClass('table-filter-text-source')); + + $cell = $cells[2]; + $this->assertEquals($element['class'], $cell->getText()); + $this->assertTrue($cell->hasClass('table-filter-text-source')); + + $cell = $cells[3]; + $actual_href = $cell->findLink('Devel')->getAttribute('href'); + $expected_href = Url::fromRoute('devel.elements_page.detail', ['element_name' => $element_name])->toString(); + $this->assertEquals($expected_href, $actual_href); + } + + // Ensures that the page is accessible only to the users with the adequate + // permissions. + $this->drupalLogout(); + $this->drupalGet('devel/elements'); + $this->assertSession()->statusCodeEquals(403); + } + + /** + * Tests element detail page. + */ + public function testElementDetail() { + $element_name = 'button'; + + // Ensures that the page works as expected. + $this->drupalGet("/devel/elements/$element_name"); + $this->assertSession()->statusCodeEquals(200); + $this->assertSession()->pageTextContains("Element $element_name"); + + // Ensures that the page returns a 404 error if the requested element is + // not defined. + $this->drupalGet('/devel/elements/not_exists'); + $this->assertSession()->statusCodeEquals(404); + + // Ensures that the page is accessible ony to users with the adequate + // permissions. + $this->drupalLogout(); + $this->drupalGet("/devel/elements/$element_name"); + $this->assertSession()->statusCodeEquals(403); + } + +} diff --git a/web/modules/contrib/devel/tests/src/Functional/DevelEntityTypeInfoTest.php b/web/modules/contrib/devel/tests/src/Functional/DevelEntityTypeInfoTest.php new file mode 100644 index 00000000..98bdea21 --- /dev/null +++ b/web/modules/contrib/devel/tests/src/Functional/DevelEntityTypeInfoTest.php @@ -0,0 +1,170 @@ +drupalPlaceBlock('system_menu_block:devel'); + $this->drupalPlaceBlock('page_title_block'); + $this->drupalLogin($this->develUser); + } + + /** + * Tests entity info menu link. + */ + public function testEntityInfoMenuLink() { + $this->drupalPlaceBlock('system_menu_block:devel'); + // Ensures that the entity type info link is present on the devel menu and + // that it points to the correct page. + $this->drupalGet(''); + $this->clickLink('Entity Info'); + $this->assertSession()->statusCodeEquals(200); + $this->assertSession()->addressEquals('/devel/entity/info'); + $this->assertSession()->pageTextContains('Entity Info'); + } + + /** + * Tests entity type list page. + */ + public function testEntityTypeList() { + $this->drupalGet('/devel/entity/info'); + $this->assertSession()->statusCodeEquals(200); + $this->assertSession()->pageTextContains('Entity Info'); + + $page = $this->getSession()->getPage(); + + // Ensures that the entity type list table is found. + $table = $page->find('css', 'table.devel-entity-type-list'); + $this->assertNotNull($table); + + // Ensures that the expected table headers are found. + $headers = $table->findAll('css', 'thead th'); + $this->assertEquals(5, count($headers)); + + $expected_headers = ['ID', 'Name', 'Provider', 'Class', 'Operations']; + $actual_headers = array_map(function (NodeElement $element) { + return $element->getText(); + }, $headers); + $this->assertSame($expected_headers, $actual_headers); + + // Tests the presence of some (arbitrarily chosen) entity types in the + // table. + $expected_types = [ + 'date_format' => [ + 'name' => 'Date format', + 'class' => 'Drupal\Core\Datetime\Entity\DateFormat', + 'provider' => 'core', + ], + 'block' => [ + 'name' => 'Block', + 'class' => 'Drupal\block\Entity\Block', + 'provider' => 'block', + ], + 'entity_view_mode' => [ + 'name' => 'View mode', + 'class' => 'Drupal\Core\Entity\Entity\EntityViewMode', + 'provider' => 'core', + ], + ]; + + foreach ($expected_types as $entity_type_id => $entity_type) { + $row = $table->find('css', sprintf('tbody tr:contains("%s")', $entity_type_id)); + $this->assertNotNull($row); + + /* @var $cells \Behat\Mink\Element\NodeElement[] */ + $cells = $row->findAll('css', 'td'); + $this->assertEquals(5, count($cells)); + + $cell = $cells[0]; + $this->assertEquals($entity_type_id, $cell->getText()); + $this->assertTrue($cell->hasClass('table-filter-text-source')); + + $cell = $cells[1]; + $this->assertEquals($entity_type['name'], $cell->getText()); + $this->assertTrue($cell->hasClass('table-filter-text-source')); + + $cell = $cells[2]; + $this->assertEquals($entity_type['provider'], $cell->getText()); + $this->assertTrue($cell->hasClass('table-filter-text-source')); + + $cell = $cells[3]; + $this->assertEquals($entity_type['class'], $cell->getText()); + $this->assertTrue($cell->hasClass('table-filter-text-source')); + + $cell = $cells[4]; + $actual_href = $cell->findLink('Devel')->getAttribute('href'); + $expected_href = Url::fromRoute('devel.entity_info_page.detail', ['entity_type_id' => $entity_type_id])->toString(); + $this->assertEquals($expected_href, $actual_href); + + $actual_href = $cell->findLink('Fields')->getAttribute('href'); + $expected_href = Url::fromRoute('devel.entity_info_page.fields', ['entity_type_id' => $entity_type_id])->toString(); + $this->assertEquals($expected_href, $actual_href); + } + + // Ensures that the page is accessible only to the users with the adequate + // permissions. + $this->drupalLogout(); + $this->drupalGet('devel/entity/info'); + $this->assertSession()->statusCodeEquals(403); + } + + /** + * Tests entity type detail page. + */ + public function testEntityTypeDetail() { + $entity_type_id = 'date_format'; + + // Ensures that the page works as expected. + $this->drupalGet("/devel/entity/info/$entity_type_id"); + $this->assertSession()->statusCodeEquals(200); + $this->assertSession()->pageTextContains("Entity type $entity_type_id"); + + // Ensures that the page returns a 404 error if the requested entity type is + // not defined. + $this->drupalGet('/devel/entity/info/not_exists'); + $this->assertSession()->statusCodeEquals(404); + + // Ensures that the page is accessible ony to users with the adequate + // permissions. + $this->drupalLogout(); + $this->drupalGet("/devel/entity/info/$entity_type_id"); + $this->assertSession()->statusCodeEquals(403); + } + + /** + * Tests entity type fields page. + */ + public function testEntityTypeFields() { + $entity_type_id = 'date_format'; + + // Ensures that the page works as expected. + $this->drupalGet("/devel/entity/fields/$entity_type_id"); + $this->assertSession()->statusCodeEquals(200); + $this->assertSession()->pageTextContains("Entity fields $entity_type_id"); + + // Ensures that the page returns a 404 error if the requested entity type is + // not defined. + $this->drupalGet('/devel/entity/fields/not_exists'); + $this->assertSession()->statusCodeEquals(404); + + // Ensures that the page is accessible ony to users with the adequate + // permissions. + $this->drupalLogout(); + $this->drupalGet("/devel/entity/fields/$entity_type_id"); + $this->assertSession()->statusCodeEquals(403); + } + +} diff --git a/web/modules/contrib/devel/tests/src/Functional/DevelErrorHandlerTest.php b/web/modules/contrib/devel/tests/src/Functional/DevelErrorHandlerTest.php new file mode 100644 index 00000000..0d6a3e57 --- /dev/null +++ b/web/modules/contrib/devel/tests/src/Functional/DevelErrorHandlerTest.php @@ -0,0 +1,139 @@ +config('system.logging'); + $config->set('error_level', ERROR_REPORTING_DISPLAY_VERBOSE)->save(); + + $this->drupalLogin($this->adminUser); + + // Ensures that the error handler config is present on the config page and + // by default the standard error handler is selected. + $error_handlers = \Drupal::config('devel.settings')->get('error_handlers'); + $this->assertEquals($error_handlers, [DEVEL_ERROR_HANDLER_STANDARD => DEVEL_ERROR_HANDLER_STANDARD]); + $this->drupalGet('admin/config/development/devel'); + $this->assertTrue($this->assertSession()->optionExists('edit-error-handlers', DEVEL_ERROR_HANDLER_STANDARD)->hasAttribute('selected')); + + // Ensures that selecting the DEVEL_ERROR_HANDLER_NONE option no error + // (raw or message) is shown on the site in case of php errors. + $edit = [ + 'error_handlers[]' => DEVEL_ERROR_HANDLER_NONE, + ]; + $this->drupalPostForm('admin/config/development/devel', $edit, 'Save configuration'); + $this->assertSession()->pageTextContains('The configuration options have been saved.'); + + $error_handlers = \Drupal::config('devel.settings')->get('error_handlers'); + $this->assertEquals($error_handlers, [DEVEL_ERROR_HANDLER_NONE => DEVEL_ERROR_HANDLER_NONE]); + $this->assertTrue($this->assertSession()->optionExists('edit-error-handlers', DEVEL_ERROR_HANDLER_NONE)->hasAttribute('selected')); + + $this->markTestSkipped('Unclear to me what this Error Handler feature does.'); + + $this->clickLink('notice+warning'); + $this->assertSession()->statusCodeEquals(200); + $this->assertSession()->pageTextNotContains($expected_notice); + $this->assertSession()->pageTextNotContains($expected_warning); + $this->assertSession()->elementNotExists('css', $messages_selector); + + // Ensures that selecting the DEVEL_ERROR_HANDLER_BACKTRACE_KINT option a + // backtrace above the rendered page is shown on the site in case of php + // errors. + $edit = [ + 'error_handlers[]' => DEVEL_ERROR_HANDLER_BACKTRACE_KINT, + ]; + $this->drupalPostForm('admin/config/development/devel', $edit, 'Save configuration'); + $this->assertSession()->pageTextContains('The configuration options have been saved.'); + + $error_handlers = \Drupal::config('devel.settings')->get('error_handlers'); + $this->assertEquals($error_handlers, [DEVEL_ERROR_HANDLER_BACKTRACE_KINT => DEVEL_ERROR_HANDLER_BACKTRACE_KINT]); + $this->assertTrue($this->assertSession()->optionExists('edit-error-handlers', DEVEL_ERROR_HANDLER_BACKTRACE_KINT)->hasAttribute('selected')); + + $this->clickLink('notice+warning'); + $this->assertSession()->statusCodeEquals(200); + $this->assertSession()->elementNotExists('css', $messages_selector); + + // Ensures that selecting the DEVEL_ERROR_HANDLER_BACKTRACE_DPM option a + // backtrace in the message area is shown on the site in case of php errors. + $edit = [ + 'error_handlers[]' => DEVEL_ERROR_HANDLER_BACKTRACE_DPM, + ]; + $this->drupalPostForm('admin/config/development/devel', $edit, 'Save configuration'); + $this->assertSession()->pageTextContains('The configuration options have been saved.'); + + $error_handlers = \Drupal::config('devel.settings')->get('error_handlers'); + $this->assertEquals($error_handlers, [DEVEL_ERROR_HANDLER_BACKTRACE_DPM => DEVEL_ERROR_HANDLER_BACKTRACE_DPM]); + $this->assertTrue($this->assertSession()->optionExists('edit-error-handlers', DEVEL_ERROR_HANDLER_BACKTRACE_DPM)->hasAttribute('selected')); + + $this->clickLink('notice+warning'); + $this->assertSession()->statusCodeEquals(200); + $this->assertSession()->elementContains('css', $messages_selector, $expected_notice); + $this->assertSession()->elementContains('css', $messages_selector, $expected_warning); + + // Ensures that when multiple handlers are selected, the output produced by + // every handler is shown on the site in case of php errors. + $edit = [ + 'error_handlers[]' => [ + DEVEL_ERROR_HANDLER_BACKTRACE_KINT => DEVEL_ERROR_HANDLER_BACKTRACE_KINT, + DEVEL_ERROR_HANDLER_BACKTRACE_DPM => DEVEL_ERROR_HANDLER_BACKTRACE_DPM, + ], + ]; + $this->drupalPostForm('admin/config/development/devel', $edit, 'Save configuration'); + $this->assertSession()->pageTextContains('The configuration options have been saved.'); + + $error_handlers = \Drupal::config('devel.settings')->get('error_handlers'); + $this->assertEquals($error_handlers, [ + DEVEL_ERROR_HANDLER_BACKTRACE_KINT => DEVEL_ERROR_HANDLER_BACKTRACE_KINT, + DEVEL_ERROR_HANDLER_BACKTRACE_DPM => DEVEL_ERROR_HANDLER_BACKTRACE_DPM, + ]); + $this->assertTrue($this->assertSession()->optionExists('edit-error-handlers', DEVEL_ERROR_HANDLER_BACKTRACE_KINT)->hasAttribute('selected')); + $this->assertTrue($this->assertSession()->optionExists('edit-error-handlers', DEVEL_ERROR_HANDLER_BACKTRACE_DPM)->hasAttribute('selected')); + + $this->clickLink('notice+warning'); + $this->assertSession()->statusCodeEquals(200); + $this->assertSession()->elementContains('css', $messages_selector, $expected_notice); + $this->assertSession()->elementContains('css', $messages_selector, $expected_warning); + + // Ensures that setting the error reporting to all the output produced by + // handlers is shown on the site in case of php errors. + $config->set('error_level', ERROR_REPORTING_DISPLAY_ALL)->save(); + $this->clickLink('notice+warning'); + $this->assertSession()->statusCodeEquals(200); + $this->assertSession()->elementContains('css', $messages_selector, $expected_notice); + $this->assertSession()->elementContains('css', $messages_selector, $expected_warning); + + // Ensures that setting the error reporting to some the output produced by + // handlers is shown on the site in case of php errors. + $config->set('error_level', ERROR_REPORTING_DISPLAY_SOME)->save(); + $this->clickLink('notice+warning'); + $this->assertSession()->statusCodeEquals(200); + $this->assertSession()->elementContains('css', $messages_selector, $expected_notice); + $this->assertSession()->elementContains('css', $messages_selector, $expected_warning); + + // Ensures that setting the error reporting to none the output produced by + // handlers is not shown on the site in case of php errors. + $config->set('error_level', ERROR_REPORTING_HIDE)->save(); + $this->clickLink('notice+warning'); + $this->assertSession()->statusCodeEquals(200); + $this->assertSession()->pageTextNotContains($expected_notice); + $this->assertSession()->pageTextNotContains($expected_warning); + $this->assertSession()->elementNotExists('css', $messages_selector); + } + +} diff --git a/web/modules/contrib/devel/tests/src/Functional/DevelEventInfoTest.php b/web/modules/contrib/devel/tests/src/Functional/DevelEventInfoTest.php new file mode 100644 index 00000000..1d895985 --- /dev/null +++ b/web/modules/contrib/devel/tests/src/Functional/DevelEventInfoTest.php @@ -0,0 +1,119 @@ +drupalPlaceBlock('page_title_block'); + $this->drupalLogin($this->develUser); + } + + /** + * Tests event info menu link. + */ + public function testEventsInfoMenuLink() { + $this->drupalPlaceBlock('system_menu_block:devel'); + // Ensures that the events info link is present on the devel menu and that + // it points to the correct page. + $this->drupalGet(''); + $this->clickLink('Events Info'); + $this->assertSession()->statusCodeEquals(200); + $this->assertSession()->addressEquals('/devel/events'); + $this->assertSession()->pageTextContains('Events'); + } + + /** + * Tests event info page. + */ + public function testEventList() { + /** @var \Symfony\Component\EventDispatcher\EventDispatcherInterface $event_dispatcher */ + $event_dispatcher = \Drupal::service('event_dispatcher'); + + $this->drupalGet('/devel/events'); + $this->assertSession()->statusCodeEquals(200); + $this->assertSession()->pageTextContains('Events'); + + $page = $this->getSession()->getPage(); + + // Ensures that the event table is found. + $table = $page->find('css', 'table.devel-event-list'); + $this->assertNotNull($table); + + // Ensures that the expected table headers are found. + /* @var $headers \Behat\Mink\Element\NodeElement[] */ + $headers = $table->findAll('css', 'thead th'); + $this->assertEquals(3, count($headers)); + + $expected_headers = ['Event Name', 'Callable', 'Priority']; + $actual_headers = array_map(function ($element) { + return $element->getText(); + }, $headers); + $this->assertSame($expected_headers, $actual_headers); + + // Ensures that all the events are listed in the table. + $events = $event_dispatcher->getListeners(); + $event_header_row = $table->findAll('css', 'tbody tr th.devel-event-name-header'); + $this->assertEquals(count($events), count($event_header_row)); + + // Tests the presence of some (arbitrarily chosen) events and related + // listeners in the table. The event items are tested dynamically so no + // test failures are expected if listeners change. + $expected_events = [ + 'config.delete', + 'kernel.request', + 'routing.route_alter', + ]; + + foreach ($expected_events as $event_name) { + $listeners = $event_dispatcher->getListeners($event_name); + + // Ensures that the event header is present in the table. + $event_header_row = $table->findAll('css', sprintf('tbody tr th:contains("%s")', $event_name)); + $this->assertNotNull($event_header_row); + $this->assertEquals(1, count($event_header_row)); + + // Ensures that all the event listener are listed in the table. + /* @var $event_rows \Behat\Mink\Element\NodeElement[] */ + $event_rows = $table->findAll('css', sprintf('tbody tr:contains("%s")', $event_name)); + // Remove the header row. + array_shift($event_rows); + $this->assertEquals(count($listeners), count($event_rows)); + + foreach ($listeners as $index => $listener) { + /* @var $cells \Behat\Mink\Element\NodeElement[] */ + $cells = $event_rows[$index]->findAll('css', 'td'); + $this->assertEquals(3, count($cells)); + + $cell_event_name = $cells[0]; + $this->assertEquals($event_name, $cell_event_name->getText()); + $this->assertTrue($cell_event_name->hasClass('table-filter-text-source')); + $this->assertTrue($cell_event_name->hasClass('visually-hidden')); + + $cell_callable = $cells[1]; + is_callable($listener, TRUE, $callable_name); + $this->assertEquals($callable_name, $cell_callable->getText()); + + $cell_methods = $cells[2]; + $priority = $event_dispatcher->getListenerPriority($event_name, $listener); + $this->assertEquals($priority, $cell_methods->getText()); + } + } + + // Ensures that the page is accessible only to the users with the adequate + // permissions. + $this->drupalLogout(); + $this->drupalGet('devel/events'); + $this->assertSession()->statusCodeEquals(403); + } + +} diff --git a/web/modules/contrib/devel/tests/src/Functional/DevelLayoutInfoTest.php b/web/modules/contrib/devel/tests/src/Functional/DevelLayoutInfoTest.php new file mode 100644 index 00000000..49332f31 --- /dev/null +++ b/web/modules/contrib/devel/tests/src/Functional/DevelLayoutInfoTest.php @@ -0,0 +1,140 @@ +drupalPlaceBlock('page_title_block'); + $this->drupalLogin($this->develUser); + } + + /** + * Tests layout info menu link. + */ + public function testLayoutsInfoMenuLink() { + $this->drupalPlaceBlock('system_menu_block:devel'); + // Ensures that the layout info link is present on the devel menu and that + // it points to the correct page. + $this->drupalGet(''); + $this->clickLink('Layouts Info'); + $this->assertSession()->statusCodeEquals(200); + $this->assertSession()->addressEquals('/devel/layouts'); + $this->assertSession()->pageTextContains('Layout'); + } + + /** + * Tests layout info page. + */ + public function testLayoutList() { + $this->drupalGet('/devel/layouts'); + $this->assertSession()->statusCodeEquals(200); + $this->assertSession()->pageTextContains('Layouts'); + + $page = $this->getSession()->getPage(); + + // Ensures that the layout table is found. + $table = $page->find('css', 'table.devel-layout-list'); + $this->assertNotNull($table); + + // Ensures that the expected table headers are found. + /* @var $headers \Behat\Mink\Element\NodeElement[] */ + $headers = $table->findAll('css', 'thead th'); + $this->assertEquals(6, count($headers)); + + $expected_headers = [ + 'Icon', + 'Label', + 'Description', + 'Category', + 'Regions', + 'Provider', + ]; + $actual_headers = array_map(function ($element) { + return $element->getText(); + }, $headers); + $this->assertSame($expected_headers, $actual_headers); + + // Ensures that all the layouts are listed in the table. + $layout_manager = \Drupal::service('plugin.manager.core.layout'); + $layouts = $layout_manager->getDefinitions(); + $table_rows = $table->findAll('css', 'tbody tr'); + $this->assertEquals(count($layouts), count($table_rows)); + + $index = 0; + foreach ($layouts as $layout) { + $cells = $table_rows[$index]->findAll('css', 'td'); + $this->assertEquals(6, count($cells)); + + $cell_layout_icon = $cells[0]; + if (empty($layout->getIconPath())) { + // @todo test that the icon path image is set correctly + } + else { + $this->assertNull($cell_layout_icon->getText()); + } + + $cell_layout_label = $cells[1]; + $this->assertEquals($cell_layout_label->getText(), $layout->getLabel()); + + $cell_layout_description = $cells[2]; + $this->assertEquals($cell_layout_description->getText(), $layout->getDescription()); + + $cell_layout_category = $cells[3]; + $this->assertEquals($cell_layout_category->getText(), $layout->getCategory()); + + $cell_layout_regions = $cells[4]; + $this->assertEquals($cell_layout_regions->getText(), implode(', ', $layout->getRegionLabels())); + + $cell_layout_provider = $cells[5]; + $this->assertEquals($cell_layout_provider->getText(), $layout->getProvider()); + + $index++; + } + + // Ensures that the page is accessible only to the users with the adequate + // permissions. + $this->drupalLogout(); + $this->drupalGet('devel/layouts'); + $this->assertSession()->statusCodeEquals(403); + } + + /** + * Tests the dependency with layout_discovery module. + */ + public function testLayoutDiscoveryDependency() { + $this->container->get('module_installer')->uninstall(['layout_discovery']); + $this->drupalPlaceBlock('system_menu_block:devel'); + + // Ensures that the layout info link is not present on the devel menu. + $this->drupalGet(''); + $this->assertSession()->linkNotExists('Layouts Info'); + + // Ensures that the layouts info page is not available. + $this->drupalGet('/devel/layouts'); + $this->assertSession()->statusCodeEquals(404); + + // Check a few other devel pages to verify devel module stil works. + $this->drupalGet('/devel/events'); + $this->assertSession()->statusCodeEquals(200); + $this->drupalGet('devel/routes'); + $this->assertSession()->statusCodeEquals(200); + $this->drupalGet('/devel/container/service'); + $this->assertSession()->statusCodeEquals(200); + } + +} diff --git a/web/modules/contrib/devel/tests/src/Functional/DevelMenuLinksTest.php b/web/modules/contrib/devel/tests/src/Functional/DevelMenuLinksTest.php new file mode 100644 index 00000000..b2de463c --- /dev/null +++ b/web/modules/contrib/devel/tests/src/Functional/DevelMenuLinksTest.php @@ -0,0 +1,93 @@ +drupalPlaceBlock('system_menu_block:devel'); + $this->drupalPlaceBlock('page_title_block'); + $this->drupalLogin($this->adminUser); + } + + /** + * Tests CSFR protected links. + */ + public function testCsrfProtectedLinks() { + // Ensure CSRF link are not accessible directly. + $this->drupalGet('devel/run-cron'); + $this->assertSession()->statusCodeEquals(403); + $this->drupalGet('devel/cache/clear'); + $this->assertSession()->statusCodeEquals(403); + + // Ensure clear cache link works properly. + $this->assertSession()->linkExists('Cache clear'); + $this->clickLink('Cache clear'); + $this->assertSession()->pageTextContains('Cache cleared.'); + + // Ensure run cron link works properly. + $this->assertSession()->linkExists('Run cron'); + $this->clickLink('Run cron'); + $this->assertSession()->pageTextContains('Cron ran successfully.'); + + // Ensure CSRF protected links work properly after change session. + $this->drupalLogout(); + $this->drupalLogin($this->adminUser); + + $this->assertSession()->linkExists('Cache clear'); + $this->clickLink('Cache clear'); + $this->assertSession()->pageTextContains('Cache cleared.'); + + $this->assertSession()->linkExists('Run cron'); + $this->clickLink('Run cron'); + $this->assertSession()->pageTextContains('Cron ran successfully.'); + } + + /** + * Tests redirect destination links. + */ + public function testRedirectDestinationLinks() { + // By default, in the testing profile, front page is the user canonical URI. + // For better testing do not use the default frontpage. + $url = Url::fromRoute('devel.simple_page'); + $destination = Url::fromRoute('devel.simple_page', [], ['absolute' => FALSE]); + + $this->drupalGet($url); + $this->assertSession()->linkExists('Reinstall Modules'); + $this->clickLink('Reinstall Modules'); + $this->assertSession()->addressEquals('devel/reinstall', ['query' => ['destination' => $destination->toString()]]); + + $this->drupalGet($url); + $this->assertSession()->linkExists('Rebuild Menu'); + $this->clickLink('Rebuild Menu'); + $this->assertSession()->addressEquals('devel/menu/reset', ['query' => ['destination' => $destination->toString()]]); + + $this->drupalGet($url); + $this->assertSession()->linkExists('Cache clear'); + $this->clickLink('Cache clear'); + $this->assertSession()->pageTextContains('Cache cleared.'); + $this->assertSession()->addressEquals($url); + + $this->drupalGet($url); + $this->assertSession()->linkExists('Run cron'); + $this->clickLink('Run cron'); + $this->assertSession()->pageTextContains('Cron ran successfully.'); + $this->assertSession()->addressEquals($url); + + } + +} diff --git a/web/modules/contrib/devel/tests/src/Functional/DevelModulesReinstallTest.php b/web/modules/contrib/devel/tests/src/Functional/DevelModulesReinstallTest.php new file mode 100644 index 00000000..9a9a12cf --- /dev/null +++ b/web/modules/contrib/devel/tests/src/Functional/DevelModulesReinstallTest.php @@ -0,0 +1,50 @@ +drupalLogin($this->adminUser); + } + + /** + * Reinstall modules. + */ + public function testDevelReinstallModules() { + // Minimal profile enables only dblog, block and node. + $modules = ['dblog', 'block']; + + // Needed for compare correctly the message. + sort($modules); + + $this->drupalGet('devel/reinstall'); + + // Prepare field data in an associative array. + $edit = []; + foreach ($modules as $module) { + $edit["reinstall[$module]"] = TRUE; + } + + $this->drupalPostForm('devel/reinstall', $edit, 'Reinstall'); + $this->assertSession()->pageTextContains('Uninstalled and installed: ' . implode(', ', $modules) . '.'); + + } + +} diff --git a/web/modules/contrib/devel/tests/src/Functional/DevelRequirementsTest.php b/web/modules/contrib/devel/tests/src/Functional/DevelRequirementsTest.php new file mode 100644 index 00000000..dc185222 --- /dev/null +++ b/web/modules/contrib/devel/tests/src/Functional/DevelRequirementsTest.php @@ -0,0 +1,25 @@ +drupalLogin($this->adminUser); + + $this->drupalGet('admin/reports/status'); + $this->assertSession()->statusCodeEquals(200); + + $this->assertSession()->pageTextContains('Devel module enabled'); + $this->assertSession()->pageTextContains('The Devel module provides access to internal debugging information; therefore it\'s recommended to disable this module on sites in production.'); + } + +} diff --git a/web/modules/contrib/devel/tests/src/Functional/DevelRouteInfoTest.php b/web/modules/contrib/devel/tests/src/Functional/DevelRouteInfoTest.php new file mode 100644 index 00000000..15c35e3d --- /dev/null +++ b/web/modules/contrib/devel/tests/src/Functional/DevelRouteInfoTest.php @@ -0,0 +1,181 @@ +drupalPlaceBlock('system_menu_block:devel'); + $this->drupalPlaceBlock('page_title_block'); + $this->drupalLogin($this->develUser); + } + + /** + * Tests routes info. + */ + public function testRouteList() { + // Ensures that the routes info link is present on the devel menu and that + // it points to the correct page. + $this->drupalGet(''); + $this->clickLink('Routes Info'); + $this->assertSession()->statusCodeEquals(200); + $this->assertSession()->addressEquals('/devel/routes'); + $this->assertSession()->pageTextContains('Routes'); + + $page = $this->getSession()->getPage(); + + // Ensures that the expected table headers are found. + /* @var $headers \Behat\Mink\Element\NodeElement[] */ + $headers = $page->findAll('css', 'table.devel-route-list thead th'); + $this->assertEquals(4, count($headers)); + + $expected_items = ['Route Name', 'Path', 'Allowed Methods', 'Operations']; + foreach ($headers as $key => $element) { + $this->assertSame($element->getText(), $expected_items[$key]); + } + + // Ensures that all the routes are listed in the table. + $routes = \Drupal::service('router.route_provider')->getAllRoutes(); + $rows = $page->findAll('css', 'table.devel-route-list tbody tr'); + $this->assertEquals(count($routes), count($rows)); + + // Tests the presence of some (arbitrarily chosen) routes in the table. + $expected_routes = [ + '' => [ + 'path' => '/', + 'methods' => ['GET', 'POST'], + 'dynamic' => FALSE, + ], + 'user.login' => [ + 'path' => '/user/login', + 'methods' => ['GET', 'POST'], + 'dynamic' => FALSE, + ], + 'entity.user.canonical' => [ + 'path' => '/user/{user}', + 'methods' => ['GET', 'POST'], + 'dynamic' => TRUE, + ], + 'entity.user.devel_load' => [ + 'path' => '/devel/user/{user}', + 'methods' => ['ANY'], + 'dynamic' => TRUE, + ], + ]; + + foreach ($expected_routes as $route_name => $expected) { + $row = $page->find('css', sprintf('table.devel-route-list tbody tr:contains("%s")', $route_name)); + $this->assertNotNull($row); + + /* @var $cells \Behat\Mink\Element\NodeElement[] */ + $cells = $row->findAll('css', 'td'); + $this->assertEquals(4, count($cells)); + + $cell_route_name = $cells[0]; + $this->assertEquals($route_name, $cell_route_name->getText()); + $this->assertTrue($cell_route_name->hasClass('table-filter-text-source')); + + $cell_path = $cells[1]; + $this->assertEquals($expected['path'], $cell_path->getText()); + $this->assertTrue($cell_path->hasClass('table-filter-text-source')); + + $cell_methods = $cells[2]; + $this->assertEquals(implode('', $expected['methods']), $cell_methods->getText()); + + $cell_operations = $cells[3]; + $actual_href = $cell_operations->findLink('Devel')->getAttribute('href'); + if ($expected['dynamic']) { + $parameters = ['query' => ['route_name' => $route_name]]; + } + else { + $parameters = ['query' => ['path' => $expected['path']]]; + } + $expected_href = Url::fromRoute('devel.route_info.item', [], $parameters)->toString(); + $this->assertEquals($expected_href, $actual_href); + } + + // Ensures that the page is accessible only to the users with the adequate + // permissions. + $this->drupalLogout(); + $this->drupalGet('devel/routes'); + $this->assertSession()->statusCodeEquals(403); + } + + /** + * Tests route detail page. + */ + public function testRouteDetail() { + $expected_title = 'Route detail'; + $xpath_warning_messages = '//div[@aria-label="Warning message"]'; + + // Ensures that devel route detail link in the menu works properly. + $url = $this->develUser->toUrl(); + $path = '/' . $url->getInternalPath(); + + $this->drupalGet($url); + $this->clickLink('Current route info'); + $this->assertSession()->statusCodeEquals(200); + $this->assertSession()->pageTextContains($expected_title); + $expected_url = Url::fromRoute('devel.route_info.item', [], ['query' => ['path' => $path]]); + $this->assertSession()->addressEquals($expected_url); + $this->assertSession()->elementNotExists('xpath', $xpath_warning_messages); + + // Ensures that devel route detail works properly even when dynamic cache + // is enabled. + $url = Url::fromRoute('devel.simple_page'); + $path = '/' . $url->getInternalPath(); + + $this->drupalGet($url); + $this->clickLink('Current route info'); + $this->assertSession()->statusCodeEquals(200); + $this->assertSession()->pageTextContains($expected_title); + $expected_url = Url::fromRoute('devel.route_info.item', [], ['query' => ['path' => $path]]); + $this->assertSession()->addressEquals($expected_url); + $this->assertSession()->elementNotExists('xpath', $xpath_warning_messages); + + // Ensures that if a non existent path is passed as input, a warning + // message is shown. + $this->drupalGet('devel/routes/item', ['query' => ['path' => '/undefined']]); + $this->assertSession()->statusCodeEquals(200); + $this->assertSession()->pageTextContains($expected_title); + $this->assertSession()->elementExists('xpath', $xpath_warning_messages); + + // Ensures that the route detail page works properly when a valid route + // name input is passed. + $this->drupalGet('devel/routes/item', ['query' => ['route_name' => 'devel.simple_page']]); + $this->assertSession()->statusCodeEquals(200); + $this->assertSession()->pageTextContains($expected_title); + $this->assertSession()->elementNotExists('xpath', $xpath_warning_messages); + + // Ensures that if a non existent route name is passed as input a warning + // message is shown. + $this->drupalGet('devel/routes/item', ['query' => ['route_name' => 'not.exists']]); + $this->assertSession()->statusCodeEquals(200); + $this->assertSession()->pageTextContains($expected_title); + $this->assertSession()->elementExists('xpath', $xpath_warning_messages); + + // Ensures that if no 'path' nor 'name' query string is passed as input, + // devel route detail page does not return errors. + $this->drupalGet('devel/routes/item'); + $this->assertSession()->statusCodeEquals(200); + $this->assertSession()->pageTextContains($expected_title); + + // Ensures that the page is accessible ony to the users with the adequate + // permissions. + $this->drupalLogout(); + $this->drupalGet('devel/routes/item'); + $this->assertSession()->statusCodeEquals(403); + } + +} diff --git a/web/modules/contrib/devel/tests/src/Functional/DevelRouterRebuildTest.php b/web/modules/contrib/devel/tests/src/Functional/DevelRouterRebuildTest.php new file mode 100644 index 00000000..90916291 --- /dev/null +++ b/web/modules/contrib/devel/tests/src/Functional/DevelRouterRebuildTest.php @@ -0,0 +1,36 @@ +set('devel_test_route_rebuild', NULL); + + $this->drupalGet('devel/menu/reset'); + $this->assertSession()->statusCodeEquals(403); + + $this->drupalLogin($this->adminUser); + + $this->drupalGet('devel/menu/reset'); + $this->assertSession()->statusCodeEquals(200); + $this->assertSession()->pageTextContains('Are you sure you want to rebuild the router?'); + $route_rebuild_state = \Drupal::state()->get('devel_test_route_rebuild'); + $this->assertEmpty($route_rebuild_state); + + $this->drupalPostForm('devel/menu/reset', [], 'Rebuild'); + $this->assertSession()->pageTextContains('The router has been rebuilt.'); + $route_rebuild_state = \Drupal::state()->get('devel_test_route_rebuild'); + $this->assertEquals('Router rebuild fired', $route_rebuild_state); + } + +} diff --git a/web/modules/contrib/devel/tests/src/Functional/DevelStateEditorTest.php b/web/modules/contrib/devel/tests/src/Functional/DevelStateEditorTest.php new file mode 100644 index 00000000..1ca79969 --- /dev/null +++ b/web/modules/contrib/devel/tests/src/Functional/DevelStateEditorTest.php @@ -0,0 +1,184 @@ +state = $this->container->get('state'); + $this->drupalPlaceBlock('page_title_block'); + } + + /** + * Tests state editor menu link. + */ + public function testStateEditMenuLink() { + $this->drupalPlaceBlock('system_menu_block:devel'); + $this->drupalLogin($this->develUser); + // Ensures that the state editor link is present on the devel menu and that + // it points to the correct page. + $this->drupalGet(''); + $this->clickLink('State editor'); + $this->assertSession()->statusCodeEquals(200); + $this->assertSession()->addressEquals('/devel/state'); + $this->assertSession()->pageTextContains('State editor'); + } + + /** + * Tests state listing. + */ + public function testStateListing() { + $table_selector = 'table.devel-state-list'; + + // Ensure that state listing page is accessible only by users with the + // adequate permissions. + $this->drupalGet('devel/state'); + $this->assertSession()->statusCodeEquals(403); + + $this->drupalLogin($this->develUser); + $this->drupalGet('devel/state'); + $this->assertSession()->statusCodeEquals(200); + $this->assertSession()->pageTextContains('State editor'); + + // Ensure that the state variables table is visible. + $table = $this->assertSession()->elementExists('css', $table_selector); + + // Ensure that all state variables are listed in the table. + $states = \Drupal::keyValue('state')->getAll(); + $rows = $table->findAll('css', 'tbody tr'); + $this->assertEquals(count($rows), count($states), 'All states are listed in the table.'); + + // Ensure that the added state variables are listed in the table. + $this->state->set('devel.simple', 'Hello!'); + $this->drupalGet('devel/state'); + $table = $this->assertSession()->elementExists('css', $table_selector); + $this->assertSession()->elementExists('css', sprintf('tbody td:contains("%s")', 'devel.simple'), $table); + + // Ensure that the operations column and the actions buttons are not + // available for user without 'administer site configuration' permission. + $headers = $table->findAll('css', 'thead th'); + $this->assertEquals(count($headers), 2, 'Correct number of table header cells found.'); + $this->assertElementsTextEquals($headers, ['Name', 'Value']); + $this->assertSession()->elementNotExists('css', 'ul.dropbutton li a', $table); + + // Ensure that the operations column and the actions buttons are + // available for user with 'administer site configuration' permission. + $this->drupalLogin($this->adminUser); + $this->drupalGet('devel/state'); + + $table = $this->assertSession()->elementExists('css', $table_selector); + $headers = $table->findAll('css', 'thead th'); + $this->assertEquals(count($headers), 3, 'Correct number of table header cells found.'); + $this->assertElementsTextEquals($headers, ['Name', 'Value', 'Operations']); + $this->assertSession()->elementExists('css', 'ul.dropbutton li a', $table); + + // Test that the edit button works properly. + $this->clickLink('Edit'); + $this->assertSession()->statusCodeEquals(200); + } + + /** + * Tests state edit. + */ + public function testStateEdit() { + // Create some state variables for the test. + $this->state->set('devel.simple', 0); + $this->state->set('devel.array', ['devel' => 'value']); + $this->state->set('devel.object', $this->randomObject()); + + // Ensure that state edit form is accessible only by users with the + // adequate permissions. + $this->drupalLogin($this->develUser); + $this->drupalGet('devel/state/edit/devel.simple'); + $this->assertSession()->statusCodeEquals(403); + + $this->drupalLogin($this->adminUser); + + // Ensure that accessing an un-existent state variable cause a warning + // message. + $this->drupalGet('devel/state/edit/devel.unknown'); + $this->assertSession()->pageTextContains(strtr('State @name does not exist in the system.', ['@name' => 'devel.unknown'])); + + // Ensure that state variables that contain simple type can be edited and + // saved. + $this->drupalGet('devel/state/edit/devel.simple'); + $this->assertSession()->statusCodeEquals(200); + $this->assertSession()->pageTextContains(strtr('Edit state variable: @name', ['@name' => 'devel.simple'])); + $input = $this->assertSession()->fieldExists('edit-new-value'); + $this->assertFalse($input->hasAttribute('disabled')); + $button = $this->assertSession()->buttonExists('edit-submit'); + $this->assertFalse($button->hasAttribute('disabled')); + + $edit = ['new_value' => 1]; + $this->drupalPostForm('devel/state/edit/devel.simple', $edit, 'Save'); + $this->assertSession()->pageTextContains(strtr('Variable @name was successfully edited.', ['@name' => 'devel.simple'])); + $this->assertEquals(1, $this->state->get('devel.simple')); + + // Ensure that state variables that contain array can be edited and saved + // and the new value is properly validated. + $this->drupalGet('devel/state/edit/devel.array'); + $this->assertSession()->statusCodeEquals(200); + $this->assertSession()->pageTextContains(strtr('Edit state variable: @name', ['@name' => 'devel.array'])); + $input = $this->assertSession()->fieldExists('edit-new-value'); + $this->assertFalse($input->hasAttribute('disabled')); + $button = $this->assertSession()->buttonExists('edit-submit'); + $this->assertFalse($button->hasAttribute('disabled')); + + // Try to save an invalid yaml input. + $edit = ['new_value' => 'devel: \'value updated']; + $this->drupalPostForm('devel/state/edit/devel.array', $edit, 'Save'); + $this->assertSession()->pageTextContains('Invalid input:'); + + $edit = ['new_value' => 'devel: \'value updated\'']; + $this->drupalPostForm('devel/state/edit/devel.array', $edit, 'Save'); + $this->assertSession()->pageTextContains(strtr('Variable @name was successfully edited.', ['@name' => 'devel.array'])); + $this->assertEquals(['devel' => 'value updated'], $this->state->get('devel.array')); + + // Ensure that state variables that contain objects cannot be edited. + $this->drupalGet('devel/state/edit/devel.object'); + $this->assertSession()->statusCodeEquals(200); + $this->assertSession()->pageTextContains(strtr('Edit state variable: @name', ['@name' => 'devel.object'])); + $this->assertSession()->pageTextContains(strtr('Only simple structures are allowed to be edited. State @name contains objects.', ['@name' => 'devel.object'])); + $this->assertSession()->fieldDisabled('edit-new-value'); + $button = $this->assertSession()->buttonExists('edit-submit'); + $this->assertTrue($button->hasAttribute('disabled')); + + // Ensure that the cancel link works as expected. + $this->clickLink('Cancel'); + $this->assertSession()->addressEquals('devel/state'); + } + + /** + * Checks that the passed in elements have the expected text. + * + * @param \Behat\Mink\Element\NodeElement[] $elements + * The elements for which check the text. + * @param array $expected_elements_text + * The expected text for the passed in elements. + */ + protected function assertElementsTextEquals(array $elements, array $expected_elements_text) { + $actual_text = array_map(function (NodeElement $element) { + return $element->getText(); + }, $elements); + $this->assertSame($expected_elements_text, $actual_text); + } + +} diff --git a/web/modules/contrib/devel/tests/src/Functional/DevelSwitchUserTest.php b/web/modules/contrib/devel/tests/src/Functional/DevelSwitchUserTest.php new file mode 100644 index 00000000..f62cb270 --- /dev/null +++ b/web/modules/contrib/devel/tests/src/Functional/DevelSwitchUserTest.php @@ -0,0 +1,305 @@ +block = $this->drupalPlaceBlock('devel_switch_user', ['id' => 'switch-user', 'label' => 'Switch Hit']); + + $this->develUser = $this->drupalCreateUser(['access devel information', 'switch users'], 'Devel User Four'); + $this->switchUser = $this->drupalCreateUser(['switch users'], 'Switch User Five'); + $this->webUser = $this->drupalCreateUser([], 'Web User Six'); + } + + /** + * Tests switch user basic functionality. + */ + public function testSwitchUserFunctionality() { + $this->drupalLogin($this->webUser); + + $this->drupalGet(''); + $this->assertSession()->pageTextNotContains($this->block->label()); + + // Ensure that a token is required to switch user. + $this->drupalGet('/devel/switch/' . $this->webUser->getDisplayName()); + $this->assertSession()->statusCodeEquals(403); + + $this->drupalLogin($this->develUser); + + $this->drupalGet(''); + $this->assertSession()->pageTextContains($this->block->label(), 'Block title was found.'); + + // Ensure that if name in not passed the controller returns access denied. + $this->drupalGet('/devel/switch'); + $this->assertSession()->statusCodeEquals(403); + + // Ensure that a token is required to switch user. + $this->drupalGet('/devel/switch/' . $this->switchUser->getDisplayName()); + $this->assertSession()->statusCodeEquals(403); + + // Switch to another user account. + $this->drupalGet('/user/' . $this->switchUser->id()); + $this->clickLink($this->switchUser->getDisplayName()); + $this->assertSessionByUid($this->switchUser->id()); + $this->assertNoSessionByUid($this->develUser->id()); + + // Switch back to initial account. + $this->clickLink($this->develUser->getDisplayName()); + $this->assertNoSessionByUid($this->switchUser->id()); + $this->assertSessionByUid($this->develUser->id()); + + // Use the search form to switch to another account. + $edit = ['userid' => $this->switchUser->getDisplayName()]; + $this->drupalPostForm(NULL, $edit, 'Switch'); + $this->assertSessionByUid($this->switchUser->id()); + $this->assertNoSessionByUid($this->develUser->id()); + } + + /** + * Tests the switch user block configuration. + */ + public function testSwitchUserBlockConfiguration() { + $anonymous = \Drupal::config('user.settings')->get('anonymous'); + + // Create some users for the test. + for ($i = 0; $i < 12; $i++) { + $this->drupalCreateUser(); + } + + $this->drupalLogin($this->develUser); + + $this->drupalGet(''); + $this->assertSession()->pageTextContains($this->block->label(), 'Block title was found.'); + + // Ensure that block default configuration is effectively used. The block + // default configuration is the following: + // - list_size : 12. + // - include_anon : FALSE. + // - show_form : TRUE. + $this->assertSwitchUserSearchForm(); + $this->assertSwitchUserListCount(12); + $this->assertSwitchUserListNoContainsUser($anonymous); + + // Ensure that changing the list_size configuration property the number of + // user displayed in the list change. + $this->setBlockConfiguration('list_size', 4); + $this->drupalGet(''); + $this->assertSwitchUserListCount(4); + + // Ensure that changing the include_anon configuration property the + // anonymous user is displayed in the list. + $this->setBlockConfiguration('include_anon', TRUE); + $this->drupalGet(''); + $this->assertSwitchUserListContainsUser($anonymous); + + // Ensure that changing the show_form configuration property the + // form is not displayed. + $this->setBlockConfiguration('show_form', FALSE); + $this->drupalGet(''); + $this->assertSwitchUserNoSearchForm(); + } + + /** + * Test the user list items. + */ + public function testSwitchUserListItems() { + $anonymous = \Drupal::config('user.settings')->get('anonymous'); + + $this->setBlockConfiguration('list_size', 2); + + // Login as web user so we are sure that this account is prioritized + // in the list if not enough users with 'switch users' permission are + // present. + $this->drupalLogin($this->webUser); + + $this->drupalLogin($this->develUser); + $this->drupalGet(''); + + // Ensure that users with 'switch users' permission are prioritized. + $this->assertSwitchUserListCount(2); + $this->assertSwitchUserListContainsUser($this->develUser->getDisplayName()); + $this->assertSwitchUserListContainsUser($this->switchUser->getDisplayName()); + + // Ensure that blocked users are not shown in the list. + $this->switchUser->set('status', 0)->save(); + $this->drupalGet(''); + $this->assertSwitchUserListCount(2); + $this->assertSwitchUserListContainsUser($this->develUser->getDisplayName()); + $this->assertSwitchUserListContainsUser($this->webUser->getDisplayName()); + $this->assertSwitchUserListNoContainsUser($this->switchUser->getDisplayName()); + + // Ensure that anonymous user are prioritized if include_anon is set to + // true. + $this->setBlockConfiguration('include_anon', TRUE); + $this->drupalGet(''); + $this->assertSwitchUserListCount(2); + $this->assertSwitchUserListContainsUser($this->develUser->getDisplayName()); + $this->assertSwitchUserListContainsUser($anonymous); + + // Ensure that the switch user block works properly even if no prioritized + // users are found (special handling for user 1). + $this->drupalLogout(); + $this->develUser->delete(); + + $this->drupalLogin($this->rootUser); + $this->drupalGet(''); + $this->assertSwitchUserListCount(2); + // Removed assertion on rootUser which causes random test failures. + // @todo Adjust the tests when user 1 option is completed. + // @see https://www.drupal.org/project/devel/issues/3097047 + // @see https://www.drupal.org/project/devel/issues/3114264 + $this->assertSwitchUserListContainsUser($anonymous); + + // Ensure that the switch user block works properly even if no roles have + // the 'switch users' permission associated (special handling for user 1). + $roles = user_roles(TRUE, 'switch users'); + \Drupal::entityTypeManager()->getStorage('user_role')->delete($roles); + + $this->drupalGet(''); + $this->assertSwitchUserListCount(2); + // Removed assertion on rootUser which causes random test failures. + // @todo Adjust the tests when user 1 option is completed. + // @see https://www.drupal.org/project/devel/issues/3097047 + // @see https://www.drupal.org/project/devel/issues/3114264 + $this->assertSwitchUserListContainsUser($anonymous); + } + + /** + * Helper function for verify the number of items shown in the user list. + * + * @param int $number + * The expected numer of items. + */ + public function assertSwitchUserListCount($number) { + $result = $this->xpath('//div[@id=:block]//ul/li/a', [':block' => 'block-switch-user']); + $this->assertTrue(count($result) == $number, 'The number of users shown in switch user is correct.'); + } + + /** + * Helper function for verify if the user list contains a username. + * + * @param string $username + * The username to check. + */ + public function assertSwitchUserListContainsUser($username) { + $result = $this->xpath('//div[@id=:block]//ul/li/a[normalize-space()=:user]', [':block' => 'block-switch-user', ':user' => $username]); + $this->assertTrue(count($result) > 0, new FormattableMarkup('User "%user" is included in the switch user list.', ['%user' => $username])); + } + + /** + * Helper function for verify if the user list not contains a username. + * + * @param string $username + * The username to check. + */ + public function assertSwitchUserListNoContainsUser($username) { + $result = $this->xpath('//div[@id=:block]//ul/li/a[normalize-space()=:user]', [':block' => 'block-switch-user', ':user' => $username]); + $this->assertTrue(count($result) == 0, new FormattableMarkup('User "%user" is not included in the switch user list.', ['%user' => $username])); + } + + /** + * Helper function for verify if the search form is shown. + */ + public function assertSwitchUserSearchForm() { + $result = $this->xpath('//div[@id=:block]//form[contains(@class, :form)]', [':block' => 'block-switch-user', ':form' => 'devel-switchuser-form']); + $this->assertTrue(count($result) > 0, 'The search form is shown.'); + } + + /** + * Helper function for verify if the search form is not shown. + */ + public function assertSwitchUserNoSearchForm() { + $result = $this->xpath('//div[@id=:block]//form[contains(@class, :form)]', [':block' => 'block-switch-user', ':form' => 'devel-switchuser-form']); + $this->assertTrue(count($result) == 0, 'The search form is not shown.'); + } + + /** + * Protected helper method to set the test block's configuration. + */ + protected function setBlockConfiguration($key, $value) { + $block = $this->block->getPlugin(); + $block->setConfigurationValue($key, $value); + $this->block->save(); + } + + /** + * Asserts that there is a session for a given user ID. + * + * Based off masquarade module. + * + * @param int $uid + * The user ID for which to find a session record. + * + * @TODO find a cleaner way to do this check. + */ + protected function assertSessionByUid($uid) { + $query = \Drupal::database()->select('sessions'); + $query->fields('sessions', ['uid']); + $query->condition('uid', $uid); + $result = $query->execute()->fetchAll(); + // Check that we have some results. + $this->assertNotEmpty($result, sprintf('No session found for uid %s', $uid)); + // If there is more than one session, then that must be unexpected. + $this->assertTrue(count($result) == 1, sprintf('Found more than one session for uid %s', $uid)); + } + + /** + * Asserts that no session exists for a given uid. + * + * Based off masquarade module. + * + * @param int $uid + * The user ID to assert. + * + * @TODO find a cleaner way to do this check. + */ + protected function assertNoSessionByUid($uid) { + $query = \Drupal::database()->select('sessions'); + $query->fields('sessions', ['uid']); + $query->condition('uid', $uid); + $result = $query->execute()->fetchAll(); + $this->assertTrue(empty($result), "No session for uid $uid found."); + } + +} diff --git a/web/modules/contrib/devel/tests/src/Functional/DevelToolbarTest.php b/web/modules/contrib/devel/tests/src/Functional/DevelToolbarTest.php new file mode 100644 index 00000000..0860cb74 --- /dev/null +++ b/web/modules/contrib/devel/tests/src/Functional/DevelToolbarTest.php @@ -0,0 +1,268 @@ +drupalPlaceBlock('local_tasks_block'); + $this->drupalPlaceBlock('page_title_block'); + + $this->develUser = $this->drupalCreateUser([ + 'administer site configuration', + 'access devel information', + 'access toolbar', + ]); + $this->toolbarUser = $this->drupalCreateUser([ + 'access toolbar', + ]); + } + + /** + * Tests configuration form. + */ + public function testConfigurationForm() { + // Ensures that the page is accessible only to users with the adequate + // permissions. + $this->drupalGet('admin/config/development/devel/toolbar'); + $this->assertSession()->statusCodeEquals(403); + + // Ensures that the config page is accessible for users with the adequate + // permissions and the Devel toolbar local task and content are shown. + $this->drupalLogin($this->develUser); + $this->drupalGet('admin/config/development/devel/toolbar'); + $this->assertSession()->statusCodeEquals(200); + $this->assertSession() + ->elementExists('xpath', '//h2[text()="Primary tabs"]/following-sibling::ul//a[contains(text(), "Toolbar Settings")]'); + $this->assertSession()->elementExists('xpath', '//fieldset[@id="edit-toolbar-items--wrapper"]'); + $this->assertSession()->pageTextContains('Devel Toolbar Settings'); + + // Ensures and that all devel menu links are listed in the configuration + // page. + foreach ($this->getMenuLinkInfos() as $link) { + $this->assertSession()->fieldExists(sprintf('toolbar_items[%s]', $link['id'])); + } + + // Ensures and that the default configuration items are selected by + // default. + foreach ($this->defaultToolbarItems as $item) { + $this->assertSession()->checkboxChecked(sprintf('toolbar_items[%s]', $item)); + } + + // Ensures that the configuration save works as expected. + $edit = [ + 'toolbar_items[devel.event_info]' => 'devel.event_info', + 'toolbar_items[devel.theme_registry]' => 'devel.theme_registry', + ]; + $this->drupalPostForm('admin/config/development/devel/toolbar', $edit, 'Save configuration'); + $this->assertSession()->pageTextContains('The configuration options have been saved.'); + + $expected_items = array_merge($this->defaultToolbarItems, ['devel.event_info', 'devel.theme_registry']); + sort($expected_items); + $config_items = \Drupal::config('devel.toolbar.settings')->get('toolbar_items'); + sort($config_items); + + $this->assertEquals($expected_items, $config_items); + } + + /** + * Tests cache metadata headers. + */ + public function testCacheHeaders() { + // Disable user toolbar tab so we can test properly if the devel toolbar + // implementation interferes with the page cacheability. + \Drupal::service('module_installer')->install(['toolbar_disable_user_toolbar']); + + // The menu is not loaded for users without the adequate permission, + // so no cache tags for configuration are added. + $this->drupalLogin($this->toolbarUser); + $this->assertSession()->responseHeaderNotContains('X-Drupal-Cache-Tags', 'config:devel.toolbar.settings'); + $this->assertSession()->responseHeaderNotContains('X-Drupal-Cache-Tags', 'config:system.menu.devel'); + + // Make sure that the configuration cache tags are present for users with + // the adequate permission. + $this->drupalLogin($this->develUser); + $this->assertSession()->responseHeaderContains('X-Drupal-Cache-Tags', 'config:devel.toolbar.settings'); + $this->assertSession()->responseHeaderContains('X-Drupal-Cache-Tags', 'config:system.menu.devel'); + + // The Devel toolbar implementation should not interfere with the page + // cacheability, so you expect a MISS value in the X-Drupal-Dynamic-Cache + // header the first time. + $this->assertSession()->responseHeaderContains('X-Drupal-Dynamic-Cache', 'MISS'); + + // Triggers a page reload and verify that the page is served from the + // cache. + $this->drupalGet(''); + $this->assertSession()->responseHeaderContains('X-Drupal-Dynamic-Cache', 'HIT'); + } + + /** + * Tests toolbar integration. + */ + public function testToolbarIntegration() { + $library_css_url = 'css/devel.toolbar.css'; + $toolbar_selector = '#toolbar-bar .toolbar-tab'; + $toolbar_tab_selector = '#toolbar-bar .toolbar-tab a.toolbar-icon-devel'; + $toolbar_tray_selector = '#toolbar-bar .toolbar-tab #toolbar-item-devel-tray'; + + // Ensures that devel toolbar item is accessible only for user with the + // adequate permissions. + $this->drupalGet(''); + $this->assertSession()->responseNotContains($library_css_url); + $this->assertSession()->elementNotExists('css', $toolbar_selector); + $this->assertSession()->elementNotExists('css', $toolbar_tab_selector); + + $this->drupalLogin($this->toolbarUser); + $this->assertSession()->responseNotContains($library_css_url); + $this->assertSession()->elementExists('css', $toolbar_selector); + $this->assertSession()->elementNotExists('css', $toolbar_tab_selector); + + $this->drupalLogin($this->develUser); + $this->assertSession()->responseContains($library_css_url); + $this->assertSession()->elementExists('css', $toolbar_selector); + $this->assertSession()->elementExists('css', $toolbar_tab_selector); + $this->assertSession()->elementTextContains('css', $toolbar_tab_selector, 'Devel'); + + // Ensures that the configure link in the toolbar is present and point to + // the correct page. + $this->clickLink('Configure'); + $this->assertSession()->addressEquals('admin/config/development/devel/toolbar'); + + // Ensures that the toolbar tray contains the all the menu links. To the + // links not marked as always visible will be assigned a css class that + // allow to hide they when the toolbar has horizontal orientation. + $this->drupalGet(''); + $toolbar_tray = $this->assertSession()->elementExists('css', $toolbar_tray_selector); + + $devel_menu_items = $this->getMenuLinkInfos(); + $toolbar_items = $toolbar_tray->findAll('css', 'ul.toolbar-menu a'); + $this->assertCount(count($devel_menu_items), $toolbar_items); + + foreach ($devel_menu_items as $link) { + $item_selector = sprintf('ul.toolbar-menu a:contains("%s")', $link['title']); + $item = $this->assertSession()->elementExists('css', $item_selector, $toolbar_tray); + // Only test the url up to the ? as the destination and token parameters + // will vary and are not checkable. + $this->assertEquals(strtok($link['url'], '?'), strtok($item->getAttribute('href'), '?')); + + $not_visible = !in_array($link['id'], $this->defaultToolbarItems); + $this->assertTrue($not_visible === $item->hasClass('toolbar-horizontal-item-hidden')); + } + + // Ensures that changing the toolbar settings configuration the changes are + // immediately visible. + $saved_items = $this->config('devel.toolbar.settings')->get('toolbar_items'); + $saved_items[] = 'devel.event_info'; + + $this->config('devel.toolbar.settings') + ->set('toolbar_items', $saved_items) + ->save(); + + $this->drupalGet(''); + $toolbar_tray = $this->assertSession()->elementExists('css', $toolbar_tray_selector); + $item = $this->assertSession()->elementExists('css', sprintf('ul.toolbar-menu a:contains("%s")', 'Events Info'), $toolbar_tray); + $this->assertFalse($item->hasClass('toolbar-horizontal-item-hidden')); + + // Ensures that disabling a menu link it will not more shown in the toolbar + // and that the changes are immediately visible. + $menu_link_manager = \Drupal::service('plugin.manager.menu.link'); + $menu_link_manager->updateDefinition('devel.event_info', ['enabled' => FALSE]); + + $this->drupalGet(''); + $toolbar_tray = $this->assertSession()->elementExists('css', $toolbar_tray_selector); + $this->assertSession()->elementNotExists('css', sprintf('ul.toolbar-menu a:contains("%s")', 'Events Info'), $toolbar_tray); + } + + /** + * Tests devel when toolbar module is not installed. + */ + public function testToolbarModuleNotInstalled() { + // Ensures that when toolbar module is not installed all works properly. + \Drupal::service('module_installer')->uninstall(['toolbar']); + + $this->drupalLogin($this->develUser); + + // Toolbar settings page should respond with 404. + $this->drupalGet('admin/config/development/devel/toolbar'); + $this->assertSession()->statusCodeEquals(404); + + // Primary local task should not contain toolbar tab. + $this->drupalGet('admin/config/development/devel'); + $this->assertSession()->statusCodeEquals(200); + $this->assertSession()->elementNotExists('xpath', '//a[contains(text(), "Toolbar Settings")]'); + + // Toolbar setting config and devel menu cache tags sholud not present. + $this->drupalGet(''); + $this->assertSession()->responseHeaderNotContains('X-Drupal-Cache-Tags', 'config:devel.toolbar.settings'); + $this->assertSession()->responseHeaderNotContains('X-Drupal-Cache-Tags', 'config:system.menu.devel'); + } + + /** + * Helper function for retrieve the menu link informations. + * + * @return array + * An array containing the menu link informations. + */ + protected function getMenuLinkInfos() { + $parameters = new MenuTreeParameters(); + $parameters->onlyEnabledLinks()->setTopLevelOnly(); + $tree = \Drupal::menuTree()->load('devel', $parameters); + + $links = []; + foreach ($tree as $element) { + $links[] = [ + 'id' => $element->link->getPluginId(), + 'title' => $element->link->getTitle(), + 'url' => $element->link->getUrlObject()->toString(), + ]; + } + return $links; + } + +} diff --git a/web/modules/contrib/devel/tests/src/Functional/DevelWebAssertHelper.php b/web/modules/contrib/devel/tests/src/Functional/DevelWebAssertHelper.php new file mode 100644 index 00000000..86607463 --- /dev/null +++ b/web/modules/contrib/devel/tests/src/Functional/DevelWebAssertHelper.php @@ -0,0 +1,34 @@ +xpath('//h2[text()="' . $tab_label . '"]/following-sibling::ul//a'); + $this->assertNotEmpty($elements, 'Local tasks not found.'); + foreach ($routes as $index => $route_info) { + list($route_name, $route_parameters) = $route_info; + $expected = Url::fromRoute($route_name, $route_parameters)->toString(); + $this->assertEquals($expected, $elements[$index]->getAttribute('href')); + } + } + +} diff --git a/web/modules/contrib/devel/tests/src/Kernel/DevelDumperTestTrait.php b/web/modules/contrib/devel/tests/src/Kernel/DevelDumperTestTrait.php new file mode 100644 index 00000000..56026da7 --- /dev/null +++ b/web/modules/contrib/devel/tests/src/Kernel/DevelDumperTestTrait.php @@ -0,0 +1,133 @@ +getDumperExportDump($data, $name); + $this->assertEquals(rtrim($dump), $output, $message); + } + + /** + * Asserts that a haystack contains the dump export output. + * + * Use \Drupal\devel\DevelDumperManager::export(). + * + * @param string $haystack + * The string that contains the dump output to test. + * @param mixed $data + * The variable to dump. + * @param string $name + * (optional) The label to output before variable, defaults to NULL. + * @param string $message + * (optional) A message to display with the assertion. + */ + public function assertContainsDumpExport($haystack, $data, $name = NULL, $message = '') { + // As at 18.04.2020 assertContainsDumpExport() is not actually used in any + // devel tests in any current code branch. + $output = $this->getDumperExportDump($data, $name); + $this->assertStringContainsString($output, (string) $haystack, $message); + } + + /** + * Assertion for ensure dump content. + * + * Asserts that the string passed in input is equals to the string + * representation of a variable obtained dumping the data. + * + * Use \Drupal\devel\DevelDumperManager::dump(). + * + * @param string $dump + * The string that contains the dump output to test. + * @param mixed $data + * The variable to dump. + * @param string $name + * (optional) The label to output before variable, defaults to NULL. + * @param string $message + * (optional) A message to display with the assertion. + */ + public function assertDumpEquals($dump, $data, $name = NULL, $message = '') { + $output = $this->getDumperDump($data, $name); + $this->assertEquals(rtrim($dump), $output, $message); + } + + /** + * Asserts that a haystack contains the dump output. + * + * Use \Drupal\devel\DevelDumperManager::dump(). + * + * @param string $haystack + * The string that contains the dump output to test. + * @param mixed $data + * The variable to dump. + * @param string $name + * (optional) The label to output before variable, defaults to NULL. + * @param string $message + * (optional) A message to display with the assertion. + */ + public function assertContainsDump($haystack, $data, $name = NULL, $message = '') { + $output = $this->getDumperDump($data, $name); + $this->assertStringContainsString($output, (string) $haystack, $message); + } + + /** + * Returns a string representation of a variable. + * + * @param mixed $input + * The variable to dump. + * @param string $name + * (optional) The label to output before variable, defaults to NULL. + * + * @return string + * String representation of a variable. + * + * @see \Drupal\devel\DevelDumperManager::export() + */ + private function getDumperExportDump($input, $name = NULL) { + $output = \Drupal::service('devel.dumper')->export($input, $name); + return rtrim($output); + } + + /** + * Returns a string representation of a variable. + * + * @param mixed $input + * The variable to dump. + * @param string $name + * (optional) The label to output before variable, defaults to NULL. + * + * @return string + * String representation of a variable. + * + * @see \Drupal\devel\DevelDumperManager::dump() + */ + private function getDumperDump($input, $name = NULL) { + ob_start(); + \Drupal::service('devel.dumper')->dump($input, $name); + $output = ob_get_contents(); + ob_end_clean(); + return rtrim($output); + } + +} diff --git a/web/modules/contrib/devel/tests/src/Kernel/DevelEnforcedDependenciesTest.php b/web/modules/contrib/devel/tests/src/Kernel/DevelEnforcedDependenciesTest.php new file mode 100644 index 00000000..4a73e7bc --- /dev/null +++ b/web/modules/contrib/devel/tests/src/Kernel/DevelEnforcedDependenciesTest.php @@ -0,0 +1,80 @@ +installEntitySchema('user'); + $this->installConfig('devel'); + // For uninstall to work. + $this->installSchema('user', ['users_data']); + } + + /** + * Tests devel menu enforced dependencies. + */ + public function testMenuEnforcedDependencies() { + /* @var \Drupal\Core\Config\ConfigManagerInterface $config_manager */ + $config_manager = $this->container->get('config.manager'); + + // Ensure that the Devel menu has explicit enforced dependencies on devel + // module. + $menu = Menu::load('devel'); + $this->assertEquals(['enforced' => ['module' => ['devel']]], $menu->get('dependencies')); + + // Creates an instance of devel menu block so you can test if enforced + // dependencies work properly with it. + $block_id = strtolower($this->randomMachineName(8)); + + $block = Block::create([ + 'plugin' => 'system_menu_block:devel', + 'region' => 'sidebar_first', + 'id' => $block_id, + 'theme' => $this->config('system.theme')->get('default'), + 'label' => $this->randomMachineName(8), + 'visibility' => [], + 'weight' => 0, + ]); + $block->save(); + + // Ensure that the menu and block instance depend on devel module. + $dependents = $config_manager->findConfigEntityDependents('module', ['devel']); + $this->assertArrayHasKey('system.menu.devel', $dependents); + $this->assertArrayHasKey('block.block.' . $block_id, $dependents); + + $this->container->get('module_installer')->uninstall(['devel']); + + // Ensure that the menu and block instance are deleted when the dependency + // is uninstalled. + $this->assertNull(Menu::load('devel')); + $this->assertNull(Block::load($block_id)); + + // Ensure that no config entities depend on devel once uninstalled. + $dependents = $config_manager->findConfigEntityDependents('module', ['devel']); + $this->assertArrayNotHasKey('system.menu.devel', $dependents); + $this->assertArrayNotHasKey('block.block.' . $block_id, $dependents); + } + +} diff --git a/web/modules/contrib/devel/tests/src/Kernel/DevelMailLogTest.php b/web/modules/contrib/devel/tests/src/Kernel/DevelMailLogTest.php new file mode 100644 index 00000000..26a4d577 --- /dev/null +++ b/web/modules/contrib/devel/tests/src/Kernel/DevelMailLogTest.php @@ -0,0 +1,201 @@ +installConfig(['system', 'devel']); + + // Configure system.site mail settings. + $this->config('system.site')->set('mail', 'devel-test@example.com')->save(); + + $this->mailManager = $this->container->get('plugin.manager.mail'); + } + + /** + * Tests devel_mail_log plugin as default mail backend. + */ + public function testDevelMailLogDefaultBackend() { + // Configure devel_mail_log as default mail backends. + $this->setDevelMailLogAsDefaultBackend(); + + // Ensures that devel_mail_log is the default mail plugin . + $mail_backend = $this->mailManager->getInstance(['module' => 'default', 'key' => 'default']); + $this->assertInstanceOf(DevelMailLog::class, $mail_backend); + + $mail_backend = $this->mailManager->getInstance(['module' => 'somemodule', 'key' => 'default']); + $this->assertInstanceOf(DevelMailLog::class, $mail_backend); + } + + /** + * Tests devel_mail_log plugin with multiple mail backend. + */ + public function testDevelMailLogMultipleBackend() { + // Configure test_mail_collector as default mail backend. + $this->config('system.mail') + ->set('interface.default', 'test_mail_collector') + ->save(); + + // Configure devel_mail_log as a module-specific mail backend. + $this->config('system.mail') + ->set('interface.somemodule', 'devel_mail_log') + ->save(); + + // Ensures that devel_mail_log is not the default mail plugin. + $mail_backend = $this->mailManager->getInstance(['module' => 'default', 'key' => 'default']); + $this->assertInstanceOf(TestMailCollector::class, $mail_backend); + + // Ensures that devel_mail_log is used as mail backend only for the + // specified module. + $mail_backend = $this->mailManager->getInstance(['module' => 'somemodule', 'key' => 'default']); + $this->assertInstanceOf(DevelMailLog::class, $mail_backend); + } + + /** + * Tests devel_mail_log default settings. + */ + public function testDevelMailDefaultSettings() { + $config = \Drupal::config('devel.settings'); + $this->assertEquals('temporary://devel-mails', $config->get('debug_mail_directory')); + $this->assertEquals('%to-%subject-%datetime.mail.txt', $config->get('debug_mail_file_format')); + } + + /** + * Tests devel mail log output. + */ + public function testDevelMailLogOutput() { + $config = \Drupal::config('devel.settings'); + + // Parameters used for send the email. + $mail = [ + 'module' => 'devel_test', + 'key' => 'devel_mail_log', + 'to' => 'drupal@example.com', + 'reply' => 'replyto@example.com', + 'lang' => \Drupal::languageManager()->getCurrentLanguage(), + ]; + + // Parameters used for compose the email in devel_test module. + // @see devel_test_mail() + $params = [ + 'subject' => 'Devel mail log subject', + 'body' => 'Devel mail log body', + 'headers' => [ + 'from' => 'postmaster@example.com', + 'additional' => [ + 'X-stupid' => 'dumb', + ], + ], + ]; + + // Configure devel_mail_log as default mail backends. + $this->setDevelMailLogAsDefaultBackend(); + + // Changes the default filename pattern removing the dynamic date + // placeholder for a more predictable filename output. + $random = $this->randomMachineName(); + $filename_pattern = '%to-%subject-' . $random . '.mail.txt'; + $this->config('devel.settings') + ->set('debug_mail_file_format', $filename_pattern) + ->save(); + + $expected_filename = 'drupal@example.com-Devel_mail_log_subject-' . $random . '.mail.txt'; + $expected_output = <<get('debug_mail_directory'); + $expected_file_path = $default_output_directory . '/' . $expected_filename; + + $this->mailManager->mail($mail['module'], $mail['key'], $mail['to'], $mail['lang'], $params, $mail['reply']); + $this->assertFileExists($expected_file_path); + $this->assertStringEqualsFile($expected_file_path, $expected_output); + + // Ensures that even changing the default output directory devel_mail_log + // works as expected. + $changed_output_directory = 'temporary://my-folder'; + $expected_file_path = $changed_output_directory . '/' . $expected_filename; + $this->config('devel.settings') + ->set('debug_mail_directory', $changed_output_directory) + ->save(); + + $result = $this->mailManager->mail($mail['module'], $mail['key'], $mail['to'], $mail['lang'], $params, $mail['reply']); + $this->assertSame(TRUE, $result['result']); + $this->assertFileExists($expected_file_path); + $this->assertStringEqualsFile($expected_file_path, $expected_output); + + // Ensures that if the default output directory is a public directory it + // will be protected by adding an .htaccess. + $public_output_directory = 'public://my-folder'; + $expected_file_path = $public_output_directory . '/' . $expected_filename; + $this->config('devel.settings') + ->set('debug_mail_directory', $public_output_directory) + ->save(); + + $this->mailManager->mail($mail['module'], $mail['key'], $mail['to'], $mail['lang'], $params, $mail['reply']); + $this->assertFileExists($expected_file_path); + $this->assertStringEqualsFile($expected_file_path, $expected_output); + $this->assertFileExists($public_output_directory . '/.htaccess'); + } + + /** + * Configure devel_mail_log as default mail backend. + */ + private function setDevelMailLogAsDefaultBackend() { + // TODO can this be avoided? + // KernelTestBase enforce the usage of 'test_mail_collector' plugin for + // collect the mails. Since we need to test devel mail plugin we manually + // configure the mail implementation to use 'devel_mail_log'. + $GLOBALS['config']['system.mail']['interface']['default'] = 'devel_mail_log'; + + // Configure devel_mail_log as default mail backend. + $this->config('system.mail') + ->set('interface.default', 'devel_mail_log') + ->save(); + } + +} diff --git a/web/modules/contrib/devel/tests/src/Kernel/DevelQueryDebugTest.php b/web/modules/contrib/devel/tests/src/Kernel/DevelQueryDebugTest.php new file mode 100644 index 00000000..5b6ee18d --- /dev/null +++ b/web/modules/contrib/devel/tests/src/Kernel/DevelQueryDebugTest.php @@ -0,0 +1,136 @@ +installSchema('system', 'sequences'); + $this->installConfig(['system', 'devel']); + $this->installEntitySchema('user'); + + $devel_role = Role::create([ + 'id' => 'admin', + 'permissions' => ['access devel information'], + ]); + $devel_role->save(); + + $this->develUser = User::create([ + 'name' => $this->randomMachineName(), + 'roles' => [$devel_role->id()], + ]); + $this->develUser->save(); + } + + /** + * Tests devel_query_debug_alter() for select queries. + */ + public function testSelectQueryDebugTag() { + // Clear the messages stack. + $this->getDrupalMessages(); + + // Ensures that no debug message is shown to user without the adequate + // permissions. + $query = \Drupal::database()->select('users', 'u'); + $query->fields('u', ['uid']); + $query->addTag('debug'); + $query->execute(); + + $messages = $this->getDrupalMessages(); + $this->assertEmpty($messages); + + // Ensures that the SQL debug message is shown to user with the adequate + // permissions. We expect only one status message containing the SQL for + // the debugged query. + \Drupal::currentUser()->setAccount($this->develUser); + $expected_message = "SELECT u.uid AS uid\nFROM\n{users} u"; + + $query = \Drupal::database()->select('users', 'u'); + $query->fields('u', ['uid']); + $query->addTag('debug'); + $query->execute(); + + $messages = $this->getDrupalMessages(); + $this->assertNotEmpty($messages['status']); + $this->assertCount(1, $messages['status']); + $actual_message = strip_tags($messages['status'][0]); + // In Drupal 9 the literals are quoted, but not in Drupal 8. We only need + // the actual content, so remove all quotes from the actual message found. + $actual_message = str_replace(['"', "'"], ['', ''], $actual_message); + $this->assertEquals($expected_message, $actual_message); + } + + /** + * Tests devel_query_debug_alter() for entity queries. + */ + public function testEntityQueryDebugTag() { + // Clear the messages stack. + $this->getDrupalMessages(); + + // Ensures that no debug message is shown to user without the adequate + // permissions. + $query = \Drupal::entityQuery('user'); + $query->addTag('debug'); + $query->execute(); + + $messages = $this->getDrupalMessages(); + $this->assertEmpty($messages); + + // Ensures that the SQL debug message is shown to user with the adequate + // permissions. We expect only one status message containing the SQL for + // the debugged entity query. + \Drupal::currentUser()->setAccount($this->develUser); + $expected_message = "SELECT base_table.uid AS uid, base_table.uid AS base_table_uid\nFROM\n{users} base_table"; + + $query = \Drupal::entityQuery('user'); + $query->addTag('debug'); + $query->execute(); + + $messages = $this->getDrupalMessages(); + $this->assertNotEmpty($messages['status']); + $this->assertCount(1, $messages['status']); + $actual_message = strip_tags($messages['status'][0]); + $actual_message = str_replace(['"', "'"], ['', ''], $actual_message); + $this->assertEquals($expected_message, $actual_message); + } + + /** + * Retrieves and removes the drupal messages. + * + * @return array + * The messages + */ + protected function getDrupalMessages() { + return $this->messenger()->deleteAll(); + } + +} diff --git a/web/modules/contrib/devel/tests/src/Kernel/DevelTwigExtensionTest.php b/web/modules/contrib/devel/tests/src/Kernel/DevelTwigExtensionTest.php new file mode 100644 index 00000000..e7d21eca --- /dev/null +++ b/web/modules/contrib/devel/tests/src/Kernel/DevelTwigExtensionTest.php @@ -0,0 +1,204 @@ +installEntitySchema('user'); + $this->installSchema('system', 'sequences'); + + $devel_role = Role::create([ + 'id' => 'admin', + 'permissions' => ['access devel information'], + ]); + $devel_role->save(); + + $this->develUser = User::create([ + 'name' => $this->randomMachineName(), + 'roles' => [$devel_role->id()], + ]); + $this->develUser->save(); + } + + /** + * {@inheritdoc} + */ + public function register(ContainerBuilder $container) { + parent::register($container); + + $parameters = $container->getParameter('twig.config'); + $parameters['debug'] = TRUE; + $container->setParameter('twig.config', $parameters); + } + + /** + * Tests that Twig extension loads appropriately. + */ + public function testTwigExtensionLoaded() { + $twig_service = \Drupal::service('twig'); + $extension = $twig_service->getExtension(Debug::class); + $this->assertEquals(get_class($extension), Debug::class, 'Debug Extension loaded successfully.'); + } + + /** + * Tests that the Twig dump functions are registered properly. + */ + public function testDumpFunctionsRegistered() { + /* @var \Twig_SimpleFunction[] $functions */ + $functions = \Drupal::service('twig')->getFunctions(); + + $dump_functions = ['devel_dump', 'kpr']; + $message_functions = ['devel_message', 'dpm', 'dsm']; + $registered_functions = $dump_functions + $message_functions; + + foreach ($registered_functions as $name) { + $function = $functions[$name]; + $this->assertTrue($function instanceof \Twig_SimpleFunction); + $this->assertEquals($function->getName(), $name); + $this->assertTrue($function->needsContext()); + $this->assertTrue($function->needsEnvironment()); + $this->assertTrue($function->isVariadic()); + + is_callable($function->getCallable(), TRUE, $callable); + if (in_array($name, $dump_functions)) { + $this->assertEquals($callable, 'Drupal\devel\Twig\Extension\Debug::dump'); + } + else { + $this->assertEquals($callable, 'Drupal\devel\Twig\Extension\Debug::message'); + } + } + } + + /** + * Tests that the Twig function for XDebug integration is registered properly. + */ + public function testXdebugIntegrationFunctionsRegistered() { + /* @var \Twig_SimpleFunction $function */ + $function = \Drupal::service('twig')->getFunction('devel_breakpoint'); + $this->assertTrue($function instanceof \Twig_SimpleFunction); + $this->assertEquals($function->getName(), 'devel_breakpoint'); + $this->assertTrue($function->needsContext()); + $this->assertTrue($function->needsEnvironment()); + $this->assertTrue($function->isVariadic()); + is_callable($function->getCallable(), TRUE, $callable); + $this->assertEquals($callable, 'Drupal\devel\Twig\Extension\Debug::breakpoint'); + } + + /** + * Tests that the Twig extension's dump functions produce the expected output. + */ + public function testDumpFunctions() { + $template = 'test-with-context {{ twig_string }} {{ twig_array.first }} {{ twig_array.second }}{{ devel_dump() }}'; + $expected_template_output = 'test-with-context context! first value second value'; + + $context = [ + 'twig_string' => 'context!', + 'twig_array' => [ + 'first' => 'first value', + 'second' => 'second value', + ], + 'twig_object' => new \stdClass(), + ]; + + /* @var \Drupal\Core\Template\TwigEnvironment $environment */ + $environment = \Drupal::service('twig'); + + // Ensures that the twig extension does nothing if the current + // user has not the adequate permission. + $this->assertTrue($environment->isDebug()); + $this->assertEquals($environment->renderInline($template, $context), $expected_template_output); + + \Drupal::currentUser()->setAccount($this->develUser); + + // Ensures that if no argument is passed to the function the twig context is + // dumped. + $output = (string) $environment->renderInline($template, $context); + $this->assertStringContainsString($expected_template_output, $output, 'When no argument passed'); + $this->assertContainsDump($output, $context, 'Twig context'); + + // Ensures that if an argument is passed to the function it is dumped. + $template = 'test-with-context {{ twig_string }} {{ twig_array.first }} {{ twig_array.second }}{{ devel_dump(twig_array) }}'; + $output = (string) $environment->renderInline($template, $context); + $this->assertStringContainsString($expected_template_output, $output, 'When one argument is passed'); + $this->assertContainsDump($output, $context['twig_array']); + + // Ensures that if more than one argument is passed the function works + // properly and every argument is dumped separately. + $template = 'test-with-context {{ twig_string }} {{ twig_array.first }} {{ twig_array.second }}{{ devel_dump(twig_string, twig_array.first, twig_array, twig_object) }}'; + $output = (string) $environment->renderInline($template, $context); + $this->assertStringContainsString($expected_template_output, $output, 'When multiple arguments are passed'); + $this->assertContainsDump($output, $context['twig_string']); + $this->assertContainsDump($output, $context['twig_array']['first']); + $this->assertContainsDump($output, $context['twig_array']); + $this->assertContainsDump($output, $context['twig_object']); + + // Clear messages. + $this->messenger()->deleteAll(); + + $retrieve_message = function ($messages, $index) { + return isset($messages['status'][$index]) ? (string) $messages['status'][$index] : NULL; + }; + + // Ensures that if no argument is passed to the function the twig context is + // dumped. + $template = 'test-with-context {{ twig_string }} {{ twig_array.first }} {{ twig_array.second }}{{ devel_message() }}'; + $output = (string) $environment->renderInline($template, $context); + $this->assertStringContainsString($expected_template_output, $output, 'When no argument passed'); + $messages = \Drupal::messenger()->deleteAll(); + $this->assertDumpExportEquals($retrieve_message($messages, 0), $context, 'Twig context'); + + // Ensures that if an argument is passed to the function it is dumped. + $template = 'test-with-context {{ twig_string }} {{ twig_array.first }} {{ twig_array.second }}{{ devel_message(twig_array) }}'; + $output = (string) $environment->renderInline($template, $context); + $this->assertStringContainsString($expected_template_output, $output, 'When one argument is passed'); + $messages = $this->messenger()->deleteAll(); + $this->assertDumpExportEquals($retrieve_message($messages, 0), $context['twig_array']); + + // Ensures that if more than one argument is passed to the function works + // properly and every argument is dumped separately. + $template = 'test-with-context {{ twig_string }} {{ twig_array.first }} {{ twig_array.second }}{{ devel_message(twig_string, twig_array.first, twig_array, twig_object) }}'; + $output = (string) $environment->renderInline($template, $context); + $this->assertStringContainsString($expected_template_output, $output, 'When multiple arguments are passed'); + $messages = $this->messenger()->deleteAll(); + $this->assertDumpExportEquals($retrieve_message($messages, 0), $context['twig_string']); + $this->assertDumpExportEquals($retrieve_message($messages, 1), $context['twig_array']['first']); + $this->assertDumpExportEquals($retrieve_message($messages, 2), $context['twig_array']); + $this->assertDumpExportEquals($retrieve_message($messages, 3), $context['twig_object']); + } + +} diff --git a/web/modules/contrib/devel/tests/src/Unit/DevelClientSideFilterTableTest.php b/web/modules/contrib/devel/tests/src/Unit/DevelClientSideFilterTableTest.php new file mode 100644 index 00000000..b2f6b94c --- /dev/null +++ b/web/modules/contrib/devel/tests/src/Unit/DevelClientSideFilterTableTest.php @@ -0,0 +1,204 @@ +getStringTranslationStub(); + + $expected_info = [ + '#filter_label' => $translation->translate('Search'), + '#filter_placeholder' => $translation->translate('Search'), + '#filter_description' => $translation->translate('Search'), + '#header' => [], + '#rows' => [], + '#empty' => '', + '#sticky' => FALSE, + '#responsive' => TRUE, + '#attributes' => [], + '#pre_render' => [ + [ClientSideFilterTable::class, 'preRenderTable'], + ], + ]; + + $table = new ClientSideFilterTable([], 'test', 'test'); + $table->setStringTranslation($translation); + $this->assertEquals($expected_info, $table->getInfo()); + } + + /** + * @covers ::preRenderTable + * @dataProvider providerPreRenderTable + */ + public function testPreRenderTable($element, $expected) { + $result = ClientSideFilterTable::preRenderTable($element); + $this->assertEquals($expected, $result); + } + + /** + * Data provider for preRenderHtmlTag test. + */ + public function providerPreRenderTable() { + $data = []; + + $t = $this->getStringTranslationStub(); + + $actual = [ + '#type' => 'devel_table_filter', + '#filter_label' => $t->translate('Label 1'), + '#filter_placeholder' => $t->translate('Placeholder 1'), + '#filter_description' => $t->translate('Description 1'), + '#header' => [], + '#rows' => [], + '#empty' => $t->translate('Empty 1'), + '#responsive' => TRUE, + '#sticky' => TRUE, + '#attributes' => [ + 'class' => ['devel-a-list'], + ], + ]; + + $expected = []; + $expected['#attached']['library'][] = 'devel/devel-table-filter'; + $expected['filters'] = [ + '#type' => 'container', + '#weight' => -1, + '#attributes' => ['class' => ['table-filter', 'js-show']], + 'name' => [ + '#type' => 'search', + '#size' => 30, + '#title' => $t->translate('Label 1'), + '#placeholder' => $t->translate('Placeholder 1'), + '#attributes' => [ + 'class' => ['table-filter-text'], + 'data-table' => ".js-devel-table-filter", + 'autocomplete' => 'off', + 'title' => $t->translate('Description 1'), + ], + ], + ]; + $expected['table'] = [ + '#type' => 'table', + '#header' => [], + '#rows' => [], + '#empty' => $t->translate('Empty 1'), + '#responsive' => TRUE, + '#sticky' => TRUE, + '#attributes' => [ + 'class' => [ + 'devel-a-list', + 'js-devel-table-filter', + 'devel-table-filter', + ], + ], + ]; + + $data[] = [$actual, $expected]; + + $headers = ['Test1', 'Test2', 'Test3', 'Test4', 'Test5']; + + $actual = [ + '#type' => 'devel_table_filter', + '#filter_label' => $t->translate('Label 2'), + '#filter_placeholder' => $t->translate('Placeholder 2'), + '#filter_description' => $t->translate('Description 2'), + '#header' => $headers, + '#rows' => [ + [ + ['data' => 'test1', 'filter' => TRUE], + ['data' => 'test2', 'filter' => TRUE, 'class' => ['test2']], + ['data' => 'test3', 'class' => ['test3']], + ['test4'], + [ + 'data' => 'test5', + 'filter' => TRUE, + 'class' => ['devel-event-name-header'], + 'colspan' => '3', + 'header' => TRUE, + ], + ], + ], + '#empty' => $t->translate('Empty 2'), + '#responsive' => FALSE, + '#sticky' => FALSE, + '#attributes' => [ + 'class' => ['devel-some-list'], + ], + ]; + + $expected = []; + $expected['#attached']['library'][] = 'devel/devel-table-filter'; + $expected['filters'] = [ + '#type' => 'container', + '#weight' => -1, + '#attributes' => ['class' => ['table-filter', 'js-show']], + 'name' => [ + '#type' => 'search', + '#size' => 30, + '#title' => $t->translate('Label 2'), + '#placeholder' => $t->translate('Placeholder 2'), + '#attributes' => [ + 'class' => ['table-filter-text'], + 'data-table' => ".js-devel-table-filter--2", + 'autocomplete' => 'off', + 'title' => $t->translate('Description 2'), + ], + ], + ]; + $expected['table'] = [ + '#type' => 'table', + '#header' => $headers, + '#rows' => [ + [ + [ + 'data' => 'test1', + 'filter' => TRUE, + 'class' => ['table-filter-text-source'], + ], + [ + 'data' => 'test2', + 'filter' => TRUE, + 'class' => ['test2', 'table-filter-text-source'], + ], + ['data' => 'test3', 'class' => ['test3']], + ['test4'], + [ + 'data' => 'test5', + 'filter' => TRUE, + 'class' => ['devel-event-name-header', 'table-filter-text-source'], + 'colspan' => '3', + 'header' => TRUE, + ], + ], + ], + '#empty' => $t->translate('Empty 2'), + '#responsive' => FALSE, + '#sticky' => FALSE, + '#attributes' => [ + 'class' => [ + 'devel-some-list', + 'js-devel-table-filter--2', + 'devel-table-filter', + ], + ], + ]; + + $data[] = [$actual, $expected]; + + return $data; + } + +} diff --git a/web/modules/contrib/devel/webprofiler/README.md b/web/modules/contrib/devel/webprofiler/README.md new file mode 100644 index 00000000..69ae48db --- /dev/null +++ b/web/modules/contrib/devel/webprofiler/README.md @@ -0,0 +1,86 @@ +[[_TOC_]] + +#### Dependencies +- d3.js: Webprofiler module requires D3 library 3.x (not 4.x) to render data. +- highlight.js: Webprofiler module requires highlight 9.7.x library to syntax highlight collected queries. + +#### Install using Composer (recommended) +If you use Composer to manage dependencies, edit [composer.json](composer.json) as follows: + +1. Run `composer require composer/installers` to ensure that you have the `composer/installers` package installed. This package facilitates the installation of packages into directories other than `/vendor` (e.g. `/libraries`) using Composer. +1. Add the following to the `installer-paths` section of `composer.json`: + ``` + "libraries/{$name}": ["type:drupal-library"], + ``` + When you are using the drupal-composer/drupal-project template add the following instead: + ``` + "web/libraries/{$name}": ["type:drupal-library"], + ``` +1. Add the following to the "repositories" section of `composer.json`: + ``` + { + "type": "package", + "package": { + "name": "d3/d3", + "version": "v3.5.17", + "type": "drupal-library", + "source": { + "url": "https://github.com/d3/d3.git", + "type": "git", + "reference": "tags/v3.5.17" + } + } + }, + { + "type": "package", + "package": { + "name": "highlightjs/highlightjs", + "version": "9.7.0", + "type": "drupal-library", + "source": { + "url": "https://github.com/highlightjs/highlight.js.git", + "type": "git", + "reference": "tags/9.7.0" + } + } + } + ``` +1. Run `composer require d3/d3 highlightjs/highlightjs` - you should find that new directories have been created +under `libraries` + +#### Install manually + +- d3.js: + + - Create a `/libraries/d3/` directory below your Drupal root directory + - Download https://d3js.org/d3.v3.min.js + - Rename it to `/libraries/d3/d3.min.js` + + For further details on how to obtain D3.js, see https://github.com/d3/d3/ + +- highlight.js: + + - Create `/libraries/highlightjs/` directory below your Drupal root directory + - Download the library and CSS from http://highlightjs.org into it + +#### IDE link + +Each class name discovered while profiling (controller class, event class) is specially linked to open the class in +an IDE. You can configure the URLs for these links to work for your IDE. + +- [Sublime text (2 and 3) - macOS](https://github.com/dhoulb/subl) +- Textmate. Use `txmt://open?url=file://@file&line=@line` +- PhpStorm. Use `phpstorm://open?file=@file&line=@line` + +#### Timeline + +It is also possible to collect the time needed to instantiate every single service used in a request. + +Add the following two lines to `settings.php` (or, even better, to `settings.local.php`): + + ``` + $class_loader->addPsr4('Drupal\\webprofiler\\', [ __DIR__ . '/../../modules/contrib/devel/webprofiler/src']); + $settings['container_base_class'] = '\Drupal\webprofiler\DependencyInjection\TraceableContainer'; + ``` + +Check if the path from the Webprofiler module in your `settings.php` file matches the location of the installed Webprofiler module in your project. diff --git a/web/modules/contrib/devel/webprofiler/composer.json b/web/modules/contrib/devel/webprofiler/composer.json new file mode 100644 index 00000000..3c133f9c --- /dev/null +++ b/web/modules/contrib/devel/webprofiler/composer.json @@ -0,0 +1,15 @@ +{ + "name": "drupal/webprofiler", + "description": "Drupal Web Profiler.", + "type": "drupal-module", + "authors": [ + { + "name": "Luca Lusso", + "email": "lussoluca@gmail.com", + "homepage": "https://github.com/lussoluca", + "role": "Maintainer" + } + ], + "license": "GPL-2.0-or-later", + "require": {} +} diff --git a/web/modules/contrib/devel/webprofiler/config/install/webprofiler.config.yml b/web/modules/contrib/devel/webprofiler/config/install/webprofiler.config.yml new file mode 100644 index 00000000..5e812743 --- /dev/null +++ b/web/modules/contrib/devel/webprofiler/config/install/webprofiler.config.yml @@ -0,0 +1,28 @@ +purge_on_cache_clear: true +storage: profiler.database_storage +exclude: "/contextual/*\r\n/toolbar/*\r\n/edit/*\r\n*.js\r\n*.css" +ide_link: "txmt://open?url=file://@file&line=@line" +ide_link_remote: "" +ide_link_local: "" +active_toolbar_items: + devel: devel + assets: assets + blocks: blocks + cache: cache + database: database + drupal_extension: drupal_extension + forms: forms + performance_timing: performance_timing + php_config: php_config + request: request + time: time + user: user + views: views + config: '0' + events: '0' + http: '0' + routing: '0' + services: '0' + state: '0' +query_sort: source +query_highlight: 5 diff --git a/web/modules/contrib/devel/webprofiler/config/schema/webprofiler.schema.yml b/web/modules/contrib/devel/webprofiler/config/schema/webprofiler.schema.yml new file mode 100644 index 00000000..1adc2f16 --- /dev/null +++ b/web/modules/contrib/devel/webprofiler/config/schema/webprofiler.schema.yml @@ -0,0 +1,35 @@ +# Schema for the configuration files of the Webprofiler module. +webprofiler.config: + type: config_object + label: 'Webprofiler configuration' + mapping: + purge_on_cache_clear: + type: boolean + label: 'Purge profiles on cache clear' + storage: + type: string + label: 'Storage implementation' + exclude: + type: string + label: 'Paths to exclude' + active_toolbar_items: + type: sequence + label: 'Active toolbar items' + sequence: + - type: string + label: 'Toolbar item' + ide_link: + type: string + label: 'IDE link' + ide_link_remote: + type: string + label: 'IDE link remote path' + ide_link_local: + type: string + label: 'IDE link local path' + query_sort: + type: string + label: 'Sort query log' + query_highlight: + type: integer + label: 'Slow query highlighting' diff --git a/web/modules/contrib/devel/webprofiler/console.services.yml b/web/modules/contrib/devel/webprofiler/console.services.yml new file mode 100644 index 00000000..fc662e47 --- /dev/null +++ b/web/modules/contrib/devel/webprofiler/console.services.yml @@ -0,0 +1,14 @@ +services: + webprofiler.list: + class: Drupal\webprofiler\Command\ListCommand + tags: + - { name: drupal.command } + lazy: true + webprofiler.export: + class: Drupal\webprofiler\Command\ExportCommand + tags: + - { name: drupal.command } + webprofiler.benchmark: + class: Drupal\webprofiler\Command\BenchmarkCommand + tags: + - { name: drupal.command } diff --git a/web/modules/contrib/devel/webprofiler/console/translations/en/webprofiler.benchmark.yml b/web/modules/contrib/devel/webprofiler/console/translations/en/webprofiler.benchmark.yml new file mode 100644 index 00000000..3f6da362 --- /dev/null +++ b/web/modules/contrib/devel/webprofiler/console/translations/en/webprofiler.benchmark.yml @@ -0,0 +1,20 @@ +description: Benchmark an url. +arguments: + url: Url to benchmark. +options: + runs: Number of runs. + file: Save results as file. + cache-rebuild: Rebuild cache before start benchmark. +messages: + not_git: Not in a git repository. + error_login: Impossibile to login in the user. +progress: + cache_rebuild: Rebuilding cache... + login: Login user... + get: Http request... + compute_avg: Compute average... + compute_median: Compute median... + compute_95percentile: Compute 95 percentile... + git_hash: Compute GIT hash... + yaml: Generate output... + done: Done. diff --git a/web/modules/contrib/devel/webprofiler/console/translations/en/webprofiler.export.yml b/web/modules/contrib/devel/webprofiler/console/translations/en/webprofiler.export.yml new file mode 100644 index 00000000..e11c8d7d --- /dev/null +++ b/web/modules/contrib/devel/webprofiler/console/translations/en/webprofiler.export.yml @@ -0,0 +1,15 @@ +description: Exports Webprofiler profile/s to file. +arguments: + id: Profile id. +options: + directory: Destination directory to store exported file/s. +messages: + success: Succesfully exported to %s + exported_count: Exported %s profiles + error_writing: Error writing file %s + error_no_profile: No profile with id %s +progress: + exporting: Exporting profiles... + archive: Create archive... + delete_tmp: Delete temp files... + done: Done. diff --git a/web/modules/contrib/devel/webprofiler/console/translations/en/webprofiler.list.yml b/web/modules/contrib/devel/webprofiler/console/translations/en/webprofiler.list.yml new file mode 100644 index 00000000..c8cb699a --- /dev/null +++ b/web/modules/contrib/devel/webprofiler/console/translations/en/webprofiler.list.yml @@ -0,0 +1,14 @@ +description: Lists Webprofiler profiles. +options: + ip: Filter by IP. + url: Filter by URL. + method: Filter by HTTP method. + limit: Limit printed profiles. +rows: + time: D, m/d/Y - H:i:s +header: + token: Token + ip: IP + method: Method + url: URL + time: Time diff --git a/web/modules/contrib/devel/webprofiler/console/translations/es/webprofiler.benchmark.yml b/web/modules/contrib/devel/webprofiler/console/translations/es/webprofiler.benchmark.yml new file mode 100644 index 00000000..8ed902eb --- /dev/null +++ b/web/modules/contrib/devel/webprofiler/console/translations/es/webprofiler.benchmark.yml @@ -0,0 +1,20 @@ +description: Benchmark una URL. +arguments: + url: Url para efectuar un benchmark. +options: + runs: Número de ejecuciones. + file: Guardar los resultados en un archivo. + cache-rebuild: Reconstruir cache antes de iniciar el benchmark. +messages: + not_git: No en un repositorio git. + error_login: Error ingresando al sistema. +progress: + cache_rebuild: Reconstruyendo cache... + login: Ingresando al sistema... + get: Solicitud Http... + compute_avg: Calculando promedio... + compute_median: Calculando media... + compute_95percentile: Calculando percentile 95... + git_hash: Calculando GIT hash... + yaml: Generando salida... + done: Terminado. diff --git a/web/modules/contrib/devel/webprofiler/console/translations/es/webprofiler.export.yml b/web/modules/contrib/devel/webprofiler/console/translations/es/webprofiler.export.yml new file mode 100644 index 00000000..d7ca9201 --- /dev/null +++ b/web/modules/contrib/devel/webprofiler/console/translations/es/webprofiler.export.yml @@ -0,0 +1,15 @@ +description: Exportar Webprofiler perfil(es) a un archivo. +arguments: + id: Profile id. +options: + directory: Directorio de destiono para almacenar archivo(s) exportados. +messages: + success: Satisfactoriamente exportado en %s + exported_count: Exportados %s perfiles + error_writing: Error escribiendo el archivo %s + error_no_profile: No fue encontrado un perfil con id %s +progress: + exporting: Exportando perfiles... + archive: Creando archivos... + delete_tmp: Borrando archivos temporales... + done: Terminado. diff --git a/web/modules/contrib/devel/webprofiler/console/translations/es/webprofiler.list.yml b/web/modules/contrib/devel/webprofiler/console/translations/es/webprofiler.list.yml new file mode 100644 index 00000000..e4635aef --- /dev/null +++ b/web/modules/contrib/devel/webprofiler/console/translations/es/webprofiler.list.yml @@ -0,0 +1,14 @@ +description: Listar perfiles Webprofiler. +options: + ip: Filtrar por IP. + url: Filtrar por URL. + method: Filtrar por método HTTP. + limit: Limitar perfiles a mostrar. +rows: + time: D, d/m/Y - H:i:s +header: + token: Token + ip: IP + method: Método + url: URL + time: Fecha diff --git a/web/modules/contrib/devel/webprofiler/css/app/dashboard.css b/web/modules/contrib/devel/webprofiler/css/app/dashboard.css new file mode 100644 index 00000000..ce74d7d6 --- /dev/null +++ b/web/modules/contrib/devel/webprofiler/css/app/dashboard.css @@ -0,0 +1,852 @@ +/* base themes */ +#webrofiler { + overflow: hidden; + font-size: 1em; + line-height: 1.2; + color: rgba(0, 0, 0, 0.7); + background-color: #ffffff; +} +#webrofiler * { + box-sizing: border-box; +} + +#webprofiler { + /* + + overview example + +