diff --git a/CHANGELOG-v3.md b/CHANGELOG-v3.md index 81319587cd4..5ebb1d3148c 100644 --- a/CHANGELOG-v3.md +++ b/CHANGELOG-v3.md @@ -1,5 +1,22 @@ # Release Notes for Craft CMS 3.x +## 3.2.6 - 2019-07-23 + +### Changed +- When enabling a new site for a Single section, Craft now uses the primary site’s content as the starting point for the new site’s content, if the section was already enabled for it. +- Swapped the position of the “Save as a Draft” and “Save Entry” buttons. ([#4622](https://github.com/craftcms/cms/issues/4622)) +- `craft\helpers\DateTimeHelper::toDateTime()` now supports arrays created from `DateTime` objects. ([#4627](https://github.com/craftcms/cms/issues/4627)) +- Plugin license key inputs are no longer limited to 29 characters, to make room for long environment variable names. ([#4393](https://github.com/craftcms/cms/issues/4393)) +- Updated Imagine to 1.2.2.1. + +### Fixed +- Fixed a bug where Craft could load the same JavaScript and CSS files multiple times when opening element editor HUDs. ([#4620](https://github.com/craftcms/cms/issues/4620)) +- Fixed a bug where each animated GIF frame would still be parsed when generating a thumbnail, even if the `transformGifs` setting was set to `false`. ([#4588](https://github.com/craftcms/cms/issues/4588)) +- Fixed a bug where back-end slug validation wasn’t working correctly for slugs with unicode characters. ([#4628](https://github.com/craftcms/cms/issues/4628)) +- Fixed a bug where it wasn’t possible to create new entries if the section handle matched the `pageTrigger` config setting, and the `pageTrigger` config setting had a trailing slash. ([#4631](https://github.com/craftcms/cms/issues/4631)) +- Fixed a bug where the `sections.previewTargets` database column was getting created as a `varchar` instead of `text` column for new Craft installs. ([#4638](https://github.com/craftcms/cms/issues/4638)) +- Fixed a bug where the `preserveExifData` config setting wasn’t being respected on image upload. + ## 3.2.5.1 - 2019-07-19 ### Fixed @@ -108,10 +125,12 @@ ## 3.2.0 - 2019-07-09 -> {warning} If you’ve ever run the `project-config/rebuild` command, it’s highly recommended that you run it again with Craft 3.1.34, before updating to Craft 3.2. +> {warning} If you’ve ever run the `project-config/rebuild` command, it’s highly recommended that you run it again with Craft 3.1.34.2, before updating to Craft 3.2. > {warning} Custom login controllers must now explicitly set their `$allowAnonymous` values to include `self::ALLOW_ANONYMOUS_OFFLINE` if they wish to be available when the system is offline. +> {tip} If you have Super Table or Neo installed, you should update those **at the same time** as Craft, to avoid unnecessary search index jobs from being added to the queue. + ### Added - All element types now have the option to support drafts and revisions. - Drafts are now autocreated when content is modified, and autosaved whenever the content changes. ([#1034](https://github.com/craftcms/cms/issues/1034)) @@ -291,6 +310,16 @@ - Fixed a bug where `craft\helpers\UrlHelper` methods could add duplicate query params on generated URLs. - Fixed a bug where Matrix blocks weren’t getting duplicated for other sites when creating a new element. ([#4449](https://github.com/craftcms/cms/issues/4449)) +## 3.1.34.2 - 2019-07-23 + +### Fixed +- Fixed a bug where the `project-config/rebuild` command was discarding email and user settings. + +## 3.1.34.1 - 2019-07-22 + +### Fixed +- Fixed a bug where the `project-config/rebuild` command was ignoring entry types that didn’t have a field layout. ([#4600](https://github.com/craftcms/cms/issues/4600)) + ## 3.1.34 - 2019-07-09 ### Changed diff --git a/composer.json b/composer.json index 207ce574fee..64bc57ef7fd 100644 --- a/composer.json +++ b/composer.json @@ -1,7 +1,7 @@ { "name": "craftcms/cms", "description": "Craft CMS", - "version": "3.2.5.1", + "version": "3.2.6", "keywords": [ "cms", "craftcms", @@ -39,7 +39,7 @@ "league/flysystem": "^1.0.35", "league/oauth2-client": "^2.2.1", "mikehaertl/php-shellcommand": "^1.2.5", - "pixelandtonic/imagine": "~0.7.1.2", + "pixelandtonic/imagine": "~1.2.2.1", "seld/cli-prompt": "^1.0.3", "symfony/yaml": "^3.2|^4.0", "true/punycode": "^2.1.0", diff --git a/composer.lock b/composer.lock index 63ff9c774ec..27930b299aa 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": "3d4e63404c0cb4cb129905209ba2bc40", + "content-hash": "3b0e833ae0db47e5581928c60d50b631", "packages": [ { "name": "cebe/markdown", @@ -605,16 +605,16 @@ }, { "name": "egulias/email-validator", - "version": "2.1.8", + "version": "2.1.10", "source": { "type": "git", "url": "https://github.com/egulias/EmailValidator.git", - "reference": "c26463ff9241f27907112fbcd0c86fa670cfef98" + "reference": "a6c8d7101b19a451c1707b1b79bbbc56e4bdb7ec" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/egulias/EmailValidator/zipball/c26463ff9241f27907112fbcd0c86fa670cfef98", - "reference": "c26463ff9241f27907112fbcd0c86fa670cfef98", + "url": "https://api.github.com/repos/egulias/EmailValidator/zipball/a6c8d7101b19a451c1707b1b79bbbc56e4bdb7ec", + "reference": "a6c8d7101b19a451c1707b1b79bbbc56e4bdb7ec", "shasum": "" }, "require": { @@ -624,7 +624,8 @@ "require-dev": { "dominicsayers/isemail": "dev-master", "phpunit/phpunit": "^4.8.35||^5.7||^6.0", - "satooshi/php-coveralls": "^1.0.1" + "satooshi/php-coveralls": "^1.0.1", + "symfony/phpunit-bridge": "^4.4@dev" }, "suggest": { "ext-intl": "PHP Internationalization Libraries are required to use the SpoofChecking validation" @@ -658,7 +659,7 @@ "validation", "validator" ], - "time": "2019-05-16T22:02:54+00:00" + "time": "2019-07-19T20:52:08+00:00" }, { "name": "elvanto/litemoji", @@ -737,23 +738,23 @@ }, { "name": "ezyang/htmlpurifier", - "version": "v4.10.0", + "version": "v4.11.0", "source": { "type": "git", "url": "https://github.com/ezyang/htmlpurifier.git", - "reference": "d85d39da4576a6934b72480be6978fb10c860021" + "reference": "83ab08bc1af7d808a9e0fbf024f1c24bfd73c0a7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/ezyang/htmlpurifier/zipball/d85d39da4576a6934b72480be6978fb10c860021", - "reference": "d85d39da4576a6934b72480be6978fb10c860021", + "url": "https://api.github.com/repos/ezyang/htmlpurifier/zipball/83ab08bc1af7d808a9e0fbf024f1c24bfd73c0a7", + "reference": "83ab08bc1af7d808a9e0fbf024f1c24bfd73c0a7", "shasum": "" }, "require": { "php": ">=5.2" }, "require-dev": { - "simpletest/simpletest": "^1.1" + "simpletest/simpletest": "dev-master#72de02a7b80c6bb8864ef9bf66d41d2f58f826bd" }, "type": "library", "autoload": { @@ -766,7 +767,7 @@ }, "notification-url": "https://packagist.org/downloads/", "license": [ - "LGPL" + "LGPL-2.1-or-later" ], "authors": [ { @@ -780,7 +781,7 @@ "keywords": [ "html" ], - "time": "2018-02-23T01:58:20+00:00" + "time": "2019-07-14T18:58:38+00:00" }, { "name": "guzzlehttp/guzzle", @@ -900,33 +901,37 @@ }, { "name": "guzzlehttp/psr7", - "version": "1.5.2", + "version": "1.6.1", "source": { "type": "git", "url": "https://github.com/guzzle/psr7.git", - "reference": "9f83dded91781a01c63574e387eaa769be769115" + "reference": "239400de7a173fe9901b9ac7c06497751f00727a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/guzzle/psr7/zipball/9f83dded91781a01c63574e387eaa769be769115", - "reference": "9f83dded91781a01c63574e387eaa769be769115", + "url": "https://api.github.com/repos/guzzle/psr7/zipball/239400de7a173fe9901b9ac7c06497751f00727a", + "reference": "239400de7a173fe9901b9ac7c06497751f00727a", "shasum": "" }, "require": { "php": ">=5.4.0", "psr/http-message": "~1.0", - "ralouphie/getallheaders": "^2.0.5" + "ralouphie/getallheaders": "^2.0.5 || ^3.0.0" }, "provide": { "psr/http-message-implementation": "1.0" }, "require-dev": { + "ext-zlib": "*", "phpunit/phpunit": "~4.8.36 || ^5.7.27 || ^6.5.8" }, + "suggest": { + "zendframework/zend-httphandlerrunner": "Emit PSR-7 responses" + }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.5-dev" + "dev-master": "1.6-dev" } }, "autoload": { @@ -963,7 +968,7 @@ "uri", "url" ], - "time": "2018-12-04T20:46:45+00:00" + "time": "2019-07-01T23:21:34+00:00" }, { "name": "justinrainbow/json-schema", @@ -1182,171 +1187,6 @@ ], "time": "2018-11-22T18:33:57+00:00" }, - { - "name": "markbaker/complex", - "version": "1.4.7", - "source": { - "type": "git", - "url": "https://github.com/MarkBaker/PHPComplex.git", - "reference": "1ea674a8308baf547cbcbd30c5fcd6d301b7c000" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/MarkBaker/PHPComplex/zipball/1ea674a8308baf547cbcbd30c5fcd6d301b7c000", - "reference": "1ea674a8308baf547cbcbd30c5fcd6d301b7c000", - "shasum": "" - }, - "require": { - "php": "^5.6.0|^7.0.0" - }, - "require-dev": { - "dealerdirect/phpcodesniffer-composer-installer": "^0.4.3", - "phpcompatibility/php-compatibility": "^8.0", - "phpdocumentor/phpdocumentor": "2.*", - "phploc/phploc": "2.*", - "phpmd/phpmd": "2.*", - "phpunit/phpunit": "^4.8.35|^5.4.0", - "sebastian/phpcpd": "2.*", - "squizlabs/php_codesniffer": "^3.3.0" - }, - "type": "library", - "autoload": { - "psr-4": { - "Complex\\": "classes/src/" - }, - "files": [ - "classes/src/functions/abs.php", - "classes/src/functions/acos.php", - "classes/src/functions/acosh.php", - "classes/src/functions/acot.php", - "classes/src/functions/acoth.php", - "classes/src/functions/acsc.php", - "classes/src/functions/acsch.php", - "classes/src/functions/argument.php", - "classes/src/functions/asec.php", - "classes/src/functions/asech.php", - "classes/src/functions/asin.php", - "classes/src/functions/asinh.php", - "classes/src/functions/atan.php", - "classes/src/functions/atanh.php", - "classes/src/functions/conjugate.php", - "classes/src/functions/cos.php", - "classes/src/functions/cosh.php", - "classes/src/functions/cot.php", - "classes/src/functions/coth.php", - "classes/src/functions/csc.php", - "classes/src/functions/csch.php", - "classes/src/functions/exp.php", - "classes/src/functions/inverse.php", - "classes/src/functions/ln.php", - "classes/src/functions/log2.php", - "classes/src/functions/log10.php", - "classes/src/functions/negative.php", - "classes/src/functions/pow.php", - "classes/src/functions/rho.php", - "classes/src/functions/sec.php", - "classes/src/functions/sech.php", - "classes/src/functions/sin.php", - "classes/src/functions/sinh.php", - "classes/src/functions/sqrt.php", - "classes/src/functions/tan.php", - "classes/src/functions/tanh.php", - "classes/src/functions/theta.php", - "classes/src/operations/add.php", - "classes/src/operations/subtract.php", - "classes/src/operations/multiply.php", - "classes/src/operations/divideby.php", - "classes/src/operations/divideinto.php" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Mark Baker", - "email": "mark@lange.demon.co.uk" - } - ], - "description": "PHP Class for working with complex numbers", - "homepage": "https://github.com/MarkBaker/PHPComplex", - "keywords": [ - "complex", - "mathematics" - ], - "time": "2018-10-13T23:28:42+00:00" - }, - { - "name": "markbaker/matrix", - "version": "1.1.4", - "source": { - "type": "git", - "url": "https://github.com/MarkBaker/PHPMatrix.git", - "reference": "6ea97472b5baf12119b4f31f802835b820dd6d64" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/MarkBaker/PHPMatrix/zipball/6ea97472b5baf12119b4f31f802835b820dd6d64", - "reference": "6ea97472b5baf12119b4f31f802835b820dd6d64", - "shasum": "" - }, - "require": { - "php": "^5.6.0|^7.0.0" - }, - "require-dev": { - "dealerdirect/phpcodesniffer-composer-installer": "^0.4.3", - "phpcompatibility/php-compatibility": "^8.0", - "phpdocumentor/phpdocumentor": "2.*", - "phploc/phploc": "2.*", - "phpmd/phpmd": "2.*", - "phpunit/phpunit": "^4.8.35|^5.4.0", - "sebastian/phpcpd": "2.*", - "squizlabs/php_codesniffer": "^3.3.0" - }, - "type": "library", - "autoload": { - "psr-4": { - "Matrix\\": "classes/src/" - }, - "files": [ - "classes/src/functions/adjoint.php", - "classes/src/functions/antidiagonal.php", - "classes/src/functions/cofactors.php", - "classes/src/functions/determinant.php", - "classes/src/functions/diagonal.php", - "classes/src/functions/identity.php", - "classes/src/functions/inverse.php", - "classes/src/functions/minors.php", - "classes/src/functions/trace.php", - "classes/src/functions/transpose.php", - "classes/src/operations/add.php", - "classes/src/operations/directsum.php", - "classes/src/operations/subtract.php", - "classes/src/operations/multiply.php", - "classes/src/operations/divideby.php", - "classes/src/operations/divideinto.php" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Mark Baker", - "email": "mark@lange.demon.co.uk" - } - ], - "description": "PHP Class for working with matrices", - "homepage": "https://github.com/MarkBaker/PHPMatrix", - "keywords": [ - "mathematics", - "matrix", - "vector" - ], - "time": "2018-11-04T22:12:12+00:00" - }, { "name": "mikehaertl/php-shellcommand", "version": "1.4.1", @@ -1432,134 +1272,89 @@ "time": "2018-07-02T15:55:56+00:00" }, { - "name": "phpoffice/phpspreadsheet", - "version": "1.7.0", + "name": "pixelandtonic/imagine", + "version": "1.2.2.1", "source": { "type": "git", - "url": "https://github.com/PHPOffice/PhpSpreadsheet.git", - "reference": "84e09df79855ed3da84e2eab6850eb7741d8cbda" + "url": "https://github.com/pixelandtonic/Imagine.git", + "reference": "c70db7d7f6bd6fb0abc7562bdabe51265af2518b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/PHPOffice/PhpSpreadsheet/zipball/84e09df79855ed3da84e2eab6850eb7741d8cbda", - "reference": "84e09df79855ed3da84e2eab6850eb7741d8cbda", + "url": "https://api.github.com/repos/pixelandtonic/Imagine/zipball/c70db7d7f6bd6fb0abc7562bdabe51265af2518b", + "reference": "c70db7d7f6bd6fb0abc7562bdabe51265af2518b", "shasum": "" }, "require": { - "ext-ctype": "*", - "ext-dom": "*", - "ext-fileinfo": "*", - "ext-gd": "*", - "ext-iconv": "*", - "ext-libxml": "*", - "ext-mbstring": "*", - "ext-simplexml": "*", - "ext-xml": "*", - "ext-xmlreader": "*", - "ext-xmlwriter": "*", - "ext-zip": "*", - "ext-zlib": "*", - "markbaker/complex": "^1.4", - "markbaker/matrix": "^1.1", - "php": "^5.6|^7.0", - "psr/simple-cache": "^1.0" + "php": ">=5.3.2" }, "require-dev": { - "doctrine/instantiator": "^1.0.0", - "dompdf/dompdf": "^0.8.0", - "friendsofphp/php-cs-fixer": "@stable", - "jpgraph/jpgraph": "^4.0", - "mpdf/mpdf": "^7.0.0", - "phpcompatibility/php-compatibility": "^8.0", - "phpunit/phpunit": "^5.7", - "squizlabs/php_codesniffer": "^3.3", - "tecnickcom/tcpdf": "^6.2" + "friendsofphp/php-cs-fixer": "2.2.*", + "phpunit/phpunit": "^4.8 || ^5.7 || ^6.5 || ^7.4 || ^8.2" }, "suggest": { - "dompdf/dompdf": "Option for rendering PDF with PDF Writer", - "jpgraph/jpgraph": "Option for rendering charts, or including charts with PDF or HTML Writers", - "mpdf/mpdf": "Option for rendering PDF with PDF Writer", - "tecnickcom/tcpdf": "Option for rendering PDF with PDF Writer" + "ext-gd": "to use the GD implementation", + "ext-gmagick": "to use the Gmagick implementation", + "ext-imagick": "to use the Imagick implementation" }, "type": "library", + "extra": { + "branch-alias": { + "dev-develop": "0.7-dev" + } + }, "autoload": { "psr-4": { - "PhpOffice\\PhpSpreadsheet\\": "src/PhpSpreadsheet" + "Imagine\\": "src/" } }, "notification-url": "https://packagist.org/downloads/", "license": [ - "LGPL-2.1-or-later" + "MIT" ], "authors": [ { - "name": "Erik Tilt" - }, - { - "name": "Adrien Crivelli" - }, - { - "name": "Maarten Balliauw", - "homepage": "https://blog.maartenballiauw.be" - }, - { - "name": "Mark Baker", - "homepage": "https://markbakeruk.net" - }, - { - "name": "Franck Lefevre", - "homepage": "https://rootslabs.net" + "name": "Bulat Shakirzyanov", + "email": "mallluhuct@gmail.com", + "homepage": "http://avalanche123.com" } ], - "description": "PHPSpreadsheet - Read, Create and Write Spreadsheet documents in PHP - Spreadsheet engine", - "homepage": "https://github.com/PHPOffice/PhpSpreadsheet", + "description": "Image processing for PHP 5.3", + "homepage": "http://imagine.readthedocs.org/", "keywords": [ - "OpenXML", - "excel", - "gnumeric", - "ods", - "php", - "spreadsheet", - "xls", - "xlsx" + "drawing", + "graphics", + "image manipulation", + "image processing" ], - "time": "2019-05-26T02:50:36+00:00" + "time": "2019-07-19T12:55:50+00:00" }, { - "name": "pixelandtonic/imagine", - "version": "v0.7.1.3", + "name": "psr/container", + "version": "1.0.0", "source": { "type": "git", - "url": "https://github.com/pixelandtonic/Imagine.git", - "reference": "989656b05410446fde623540bbf83af15087e4ea" + "url": "https://github.com/php-fig/container.git", + "reference": "b7ce3b176482dbbc1245ebf52b181af44c2cf55f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/pixelandtonic/Imagine/zipball/989656b05410446fde623540bbf83af15087e4ea", - "reference": "989656b05410446fde623540bbf83af15087e4ea", + "url": "https://api.github.com/repos/php-fig/container/zipball/b7ce3b176482dbbc1245ebf52b181af44c2cf55f", + "reference": "b7ce3b176482dbbc1245ebf52b181af44c2cf55f", "shasum": "" }, "require": { - "php": ">=5.3.2" - }, - "require-dev": { - "sami/sami": "^3.3", - "symfony/phpunit-bridge": "^3.2" - }, - "suggest": { - "ext-gd": "to use the GD implementation", - "ext-gmagick": "to use the Gmagick implementation", - "ext-imagick": "to use the Imagick implementation" + "php": ">=5.3.0" }, "type": "library", "extra": { "branch-alias": { - "dev-develop": "0.7-dev" + "dev-master": "1.0.x-dev" } }, "autoload": { - "psr-0": { - "Imagine": "lib/" + "psr-4": { + "Psr\\Container\\": "src/" } }, "notification-url": "https://packagist.org/downloads/", @@ -1568,20 +1363,20 @@ ], "authors": [ { - "name": "Bulat Shakirzyanov", - "email": "mallluhuct@gmail.com", - "homepage": "http://avalanche123.com" + "name": "PHP-FIG", + "homepage": "http://www.php-fig.org/" } ], - "description": "Image processing for PHP 5.3", - "homepage": "http://imagine.readthedocs.org/", + "description": "Common Container Interface (PHP FIG PSR-11)", + "homepage": "https://github.com/php-fig/container", "keywords": [ - "drawing", - "graphics", - "image manipulation", - "image processing" + "PSR-11", + "container", + "container-interface", + "container-interop", + "psr" ], - "time": "2017-10-26T13:18:33+00:00" + "time": "2017-02-14T16:28:37+00:00" }, { "name": "psr/http-message", @@ -1680,74 +1475,26 @@ ], "time": "2018-11-20T15:27:04+00:00" }, - { - "name": "psr/simple-cache", - "version": "1.0.1", - "source": { - "type": "git", - "url": "https://github.com/php-fig/simple-cache.git", - "reference": "408d5eafb83c57f6365a3ca330ff23aa4a5fa39b" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/php-fig/simple-cache/zipball/408d5eafb83c57f6365a3ca330ff23aa4a5fa39b", - "reference": "408d5eafb83c57f6365a3ca330ff23aa4a5fa39b", - "shasum": "" - }, - "require": { - "php": ">=5.3.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.0.x-dev" - } - }, - "autoload": { - "psr-4": { - "Psr\\SimpleCache\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "PHP-FIG", - "homepage": "http://www.php-fig.org/" - } - ], - "description": "Common interfaces for simple caching", - "keywords": [ - "cache", - "caching", - "psr", - "psr-16", - "simple-cache" - ], - "time": "2017-10-23T01:57:42+00:00" - }, { "name": "ralouphie/getallheaders", - "version": "2.0.5", + "version": "3.0.3", "source": { "type": "git", "url": "https://github.com/ralouphie/getallheaders.git", - "reference": "5601c8a83fbba7ef674a7369456d12f1e0d0eafa" + "reference": "120b605dfeb996808c31b6477290a714d356e822" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/ralouphie/getallheaders/zipball/5601c8a83fbba7ef674a7369456d12f1e0d0eafa", - "reference": "5601c8a83fbba7ef674a7369456d12f1e0d0eafa", + "url": "https://api.github.com/repos/ralouphie/getallheaders/zipball/120b605dfeb996808c31b6477290a714d356e822", + "reference": "120b605dfeb996808c31b6477290a714d356e822", "shasum": "" }, "require": { - "php": ">=5.3" + "php": ">=5.6" }, "require-dev": { - "phpunit/phpunit": "~3.7.0", - "satooshi/php-coveralls": ">=1.0" + "php-coveralls/php-coveralls": "^2.1", + "phpunit/phpunit": "^5 || ^6.5" }, "type": "library", "autoload": { @@ -1766,7 +1513,7 @@ } ], "description": "A polyfill for getallheaders.", - "time": "2016-02-11T07:05:27+00:00" + "time": "2019-03-08T08:55:37+00:00" }, { "name": "seld/cli-prompt", @@ -1973,16 +1720,16 @@ }, { "name": "symfony/console", - "version": "v4.3.1", + "version": "v4.3.2", "source": { "type": "git", "url": "https://github.com/symfony/console.git", - "reference": "d50bbeeb0e17e6dd4124ea391eff235e932cbf64" + "reference": "b592b26a24265a35172d8a2094d8b10f22b7cc39" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/console/zipball/d50bbeeb0e17e6dd4124ea391eff235e932cbf64", - "reference": "d50bbeeb0e17e6dd4124ea391eff235e932cbf64", + "url": "https://api.github.com/repos/symfony/console/zipball/b592b26a24265a35172d8a2094d8b10f22b7cc39", + "reference": "b592b26a24265a35172d8a2094d8b10f22b7cc39", "shasum": "" }, "require": { @@ -2044,20 +1791,20 @@ ], "description": "Symfony Console Component", "homepage": "https://symfony.com", - "time": "2019-06-05T13:25:51+00:00" + "time": "2019-06-13T11:03:18+00:00" }, { "name": "symfony/filesystem", - "version": "v4.3.1", + "version": "v4.3.2", "source": { "type": "git", "url": "https://github.com/symfony/filesystem.git", - "reference": "bf2af40d738dec5e433faea7b00daa4431d0a4cf" + "reference": "b9896d034463ad6fd2bf17e2bf9418caecd6313d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/filesystem/zipball/bf2af40d738dec5e433faea7b00daa4431d0a4cf", - "reference": "bf2af40d738dec5e433faea7b00daa4431d0a4cf", + "url": "https://api.github.com/repos/symfony/filesystem/zipball/b9896d034463ad6fd2bf17e2bf9418caecd6313d", + "reference": "b9896d034463ad6fd2bf17e2bf9418caecd6313d", "shasum": "" }, "require": { @@ -2094,20 +1841,20 @@ ], "description": "Symfony Filesystem Component", "homepage": "https://symfony.com", - "time": "2019-06-03T20:27:40+00:00" + "time": "2019-06-23T08:51:25+00:00" }, { "name": "symfony/finder", - "version": "v4.3.1", + "version": "v4.3.2", "source": { "type": "git", "url": "https://github.com/symfony/finder.git", - "reference": "b3d4f4c0e4eadfdd8b296af9ca637cfbf51d8176" + "reference": "33c21f7d5d3dc8a140c282854a7e13aeb5d0f91a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/finder/zipball/b3d4f4c0e4eadfdd8b296af9ca637cfbf51d8176", - "reference": "b3d4f4c0e4eadfdd8b296af9ca637cfbf51d8176", + "url": "https://api.github.com/repos/symfony/finder/zipball/33c21f7d5d3dc8a140c282854a7e13aeb5d0f91a", + "reference": "33c21f7d5d3dc8a140c282854a7e13aeb5d0f91a", "shasum": "" }, "require": { @@ -2143,7 +1890,7 @@ ], "description": "Symfony Finder Component", "homepage": "https://symfony.com", - "time": "2019-05-26T20:47:49+00:00" + "time": "2019-06-13T11:03:18+00:00" }, { "name": "symfony/polyfill-ctype", @@ -2498,7 +2245,7 @@ }, { "name": "symfony/process", - "version": "v4.3.1", + "version": "v4.3.2", "source": { "type": "git", "url": "https://github.com/symfony/process.git", @@ -2547,23 +2294,23 @@ }, { "name": "symfony/service-contracts", - "version": "v1.1.2", + "version": "v1.1.5", "source": { "type": "git", "url": "https://github.com/symfony/service-contracts.git", - "reference": "191afdcb5804db960d26d8566b7e9a2843cab3a0" + "reference": "f391a00de78ec7ec8cf5cdcdae59ec7b883edb8d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/service-contracts/zipball/191afdcb5804db960d26d8566b7e9a2843cab3a0", - "reference": "191afdcb5804db960d26d8566b7e9a2843cab3a0", + "url": "https://api.github.com/repos/symfony/service-contracts/zipball/f391a00de78ec7ec8cf5cdcdae59ec7b883edb8d", + "reference": "f391a00de78ec7ec8cf5cdcdae59ec7b883edb8d", "shasum": "" }, "require": { - "php": "^7.1.3" + "php": "^7.1.3", + "psr/container": "^1.0" }, "suggest": { - "psr/container": "", "symfony/service-implementation": "" }, "type": "library", @@ -2601,11 +2348,11 @@ "interoperability", "standards" ], - "time": "2019-05-28T07:50:59+00:00" + "time": "2019-06-13T11:15:36+00:00" }, { "name": "symfony/yaml", - "version": "v4.3.1", + "version": "v4.3.2", "source": { "type": "git", "url": "https://github.com/symfony/yaml.git", @@ -2927,23 +2674,24 @@ }, { "name": "yiisoft/yii2-composer", - "version": "2.0.7", + "version": "2.0.8", "source": { "type": "git", "url": "https://github.com/yiisoft/yii2-composer.git", - "reference": "1439e78be1218c492e6cde251ed87d3f128b9534" + "reference": "5c7ca9836cf80b34db265332a7f2f8438eb469b9" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/yiisoft/yii2-composer/zipball/1439e78be1218c492e6cde251ed87d3f128b9534", - "reference": "1439e78be1218c492e6cde251ed87d3f128b9534", + "url": "https://api.github.com/repos/yiisoft/yii2-composer/zipball/5c7ca9836cf80b34db265332a7f2f8438eb469b9", + "reference": "5c7ca9836cf80b34db265332a7f2f8438eb469b9", "shasum": "" }, "require": { "composer-plugin-api": "^1.0" }, "require-dev": { - "composer/composer": "^1.0" + "composer/composer": "^1.0", + "phpunit/phpunit": "<7" }, "type": "composer-plugin", "extra": { @@ -2977,7 +2725,7 @@ "extension installer", "yii2" ], - "time": "2018-07-05T15:44:47+00:00" + "time": "2019-07-16T13:22:30+00:00" }, { "name": "yiisoft/yii2-debug", @@ -3387,16 +3135,16 @@ }, { "name": "codeception/codeception", - "version": "3.0.1", + "version": "3.0.3", "source": { "type": "git", "url": "https://github.com/Codeception/Codeception.git", - "reference": "52dfbb5f31b74d042100a8836bbde792326ebb64" + "reference": "feb566a9dc26993611602011ae3834d8e3c1dd7f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Codeception/Codeception/zipball/52dfbb5f31b74d042100a8836bbde792326ebb64", - "reference": "52dfbb5f31b74d042100a8836bbde792326ebb64", + "url": "https://api.github.com/repos/Codeception/Codeception/zipball/feb566a9dc26993611602011ae3834d8e3c1dd7f", + "reference": "feb566a9dc26993611602011ae3834d8e3c1dd7f", "shasum": "" }, "require": { @@ -3421,6 +3169,8 @@ }, "require-dev": { "codeception/specify": "~0.3", + "doctrine/annotations": "^1", + "doctrine/orm": "^2", "flow/jsonpath": "~0.2", "monolog/monolog": "~1.8", "pda/pheanstalk": "~3.0", @@ -3475,7 +3225,7 @@ "functional testing", "unit testing" ], - "time": "2019-05-20T17:02:37+00:00" + "time": "2019-07-18T16:21:08+00:00" }, { "name": "codeception/mockery-module", @@ -3520,21 +3270,22 @@ }, { "name": "codeception/phpunit-wrapper", - "version": "7.7.1", + "version": "8.0.4", "source": { "type": "git", "url": "https://github.com/Codeception/phpunit-wrapper.git", - "reference": "ab04a956264291505ea84998f43cf91639b4575d" + "reference": "7090736f36b4398cae6ef838b9a2bdfe8d8d104b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Codeception/phpunit-wrapper/zipball/ab04a956264291505ea84998f43cf91639b4575d", - "reference": "ab04a956264291505ea84998f43cf91639b4575d", + "url": "https://api.github.com/repos/Codeception/phpunit-wrapper/zipball/7090736f36b4398cae6ef838b9a2bdfe8d8d104b", + "reference": "7090736f36b4398cae6ef838b9a2bdfe8d8d104b", "shasum": "" }, "require": { - "phpunit/php-code-coverage": "^6.0", - "phpunit/phpunit": "7.5.*", + "php": ">=7.2", + "phpunit/php-code-coverage": "^7.0", + "phpunit/phpunit": "^8.0", "sebastian/comparator": "^3.0", "sebastian/diff": "^3.0" }, @@ -3559,7 +3310,7 @@ } ], "description": "PHPUnit classes used by Codeception", - "time": "2019-02-26T20:35:32+00:00" + "time": "2019-02-27T12:58:57+00:00" }, { "name": "codeception/specify", @@ -4980,40 +4731,40 @@ }, { "name": "phpunit/php-code-coverage", - "version": "6.1.4", + "version": "7.0.6", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-code-coverage.git", - "reference": "807e6013b00af69b6c5d9ceb4282d0393dbb9d8d" + "reference": "d471d0d2b529a67c6a722dd446c4ec90881ac315" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/807e6013b00af69b6c5d9ceb4282d0393dbb9d8d", - "reference": "807e6013b00af69b6c5d9ceb4282d0393dbb9d8d", + "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/d471d0d2b529a67c6a722dd446c4ec90881ac315", + "reference": "d471d0d2b529a67c6a722dd446c4ec90881ac315", "shasum": "" }, "require": { "ext-dom": "*", "ext-xmlwriter": "*", - "php": "^7.1", - "phpunit/php-file-iterator": "^2.0", + "php": "^7.2", + "phpunit/php-file-iterator": "^2.0.2", "phpunit/php-text-template": "^1.2.1", - "phpunit/php-token-stream": "^3.0", + "phpunit/php-token-stream": "^3.0.2", "sebastian/code-unit-reverse-lookup": "^1.0.1", - "sebastian/environment": "^3.1 || ^4.0", + "sebastian/environment": "^4.2.2", "sebastian/version": "^2.0.1", - "theseer/tokenizer": "^1.1" + "theseer/tokenizer": "^1.1.3" }, "require-dev": { - "phpunit/phpunit": "^7.0" + "phpunit/phpunit": "^8.2.2" }, "suggest": { - "ext-xdebug": "^2.6.0" + "ext-xdebug": "^2.7.2" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "6.1-dev" + "dev-master": "7.0-dev" } }, "autoload": { @@ -5039,7 +4790,7 @@ "testing", "xunit" ], - "time": "2018-10-31T16:06:48+00:00" + "time": "2019-07-08T05:29:42+00:00" }, { "name": "phpunit/php-file-iterator", @@ -5183,16 +4934,16 @@ }, { "name": "phpunit/php-token-stream", - "version": "3.0.1", + "version": "3.0.2", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-token-stream.git", - "reference": "c99e3be9d3e85f60646f152f9002d46ed7770d18" + "reference": "c4a66b97f040e3e20b3aa2a243230a1c3a9f7c8c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-token-stream/zipball/c99e3be9d3e85f60646f152f9002d46ed7770d18", - "reference": "c99e3be9d3e85f60646f152f9002d46ed7770d18", + "url": "https://api.github.com/repos/sebastianbergmann/php-token-stream/zipball/c4a66b97f040e3e20b3aa2a243230a1c3a9f7c8c", + "reference": "c4a66b97f040e3e20b3aa2a243230a1c3a9f7c8c", "shasum": "" }, "require": { @@ -5228,57 +4979,56 @@ "keywords": [ "tokenizer" ], - "time": "2018-10-30T05:52:18+00:00" + "time": "2019-07-08T05:24:54+00:00" }, { "name": "phpunit/phpunit", - "version": "7.5.13", + "version": "8.2.5", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/phpunit.git", - "reference": "b9278591caa8630127f96c63b598712b699e671c" + "reference": "c1b8534b3730f20f58600124129197bf1183dc92" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/b9278591caa8630127f96c63b598712b699e671c", - "reference": "b9278591caa8630127f96c63b598712b699e671c", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/c1b8534b3730f20f58600124129197bf1183dc92", + "reference": "c1b8534b3730f20f58600124129197bf1183dc92", "shasum": "" }, "require": { - "doctrine/instantiator": "^1.1", + "doctrine/instantiator": "^1.2.0", "ext-dom": "*", "ext-json": "*", "ext-libxml": "*", "ext-mbstring": "*", "ext-xml": "*", - "myclabs/deep-copy": "^1.7", - "phar-io/manifest": "^1.0.2", - "phar-io/version": "^2.0", - "php": "^7.1", - "phpspec/prophecy": "^1.7", - "phpunit/php-code-coverage": "^6.0.7", - "phpunit/php-file-iterator": "^2.0.1", + "ext-xmlwriter": "*", + "myclabs/deep-copy": "^1.9.1", + "phar-io/manifest": "^1.0.3", + "phar-io/version": "^2.0.1", + "php": "^7.2", + "phpspec/prophecy": "^1.8.1", + "phpunit/php-code-coverage": "^7.0.5", + "phpunit/php-file-iterator": "^2.0.2", "phpunit/php-text-template": "^1.2.1", - "phpunit/php-timer": "^2.1", - "sebastian/comparator": "^3.0", - "sebastian/diff": "^3.0", - "sebastian/environment": "^4.0", - "sebastian/exporter": "^3.1", - "sebastian/global-state": "^2.0", + "phpunit/php-timer": "^2.1.2", + "sebastian/comparator": "^3.0.2", + "sebastian/diff": "^3.0.2", + "sebastian/environment": "^4.2.2", + "sebastian/exporter": "^3.1.0", + "sebastian/global-state": "^3.0.0", "sebastian/object-enumerator": "^3.0.3", - "sebastian/resource-operations": "^2.0", + "sebastian/resource-operations": "^2.0.1", + "sebastian/type": "^1.1.3", "sebastian/version": "^2.0.1" }, - "conflict": { - "phpunit/phpunit-mock-objects": "*" - }, "require-dev": { "ext-pdo": "*" }, "suggest": { "ext-soap": "*", "ext-xdebug": "*", - "phpunit/php-invoker": "^2.0" + "phpunit/php-invoker": "^2.0.0" }, "bin": [ "phpunit" @@ -5286,7 +5036,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "7.5-dev" + "dev-master": "8.2-dev" } }, "autoload": { @@ -5301,8 +5051,8 @@ "authors": [ { "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" + "role": "lead", + "email": "sebastian@phpunit.de" } ], "description": "The PHP Unit Testing framework.", @@ -5312,7 +5062,7 @@ "testing", "xunit" ], - "time": "2019-06-19T12:01:51+00:00" + "time": "2019-07-15T06:26:24+00:00" }, { "name": "sebastian/code-unit-reverse-lookup", @@ -5601,23 +5351,26 @@ }, { "name": "sebastian/global-state", - "version": "2.0.0", + "version": "3.0.0", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/global-state.git", - "reference": "e8ba02eed7bbbb9e59e43dedd3dddeff4a56b0c4" + "reference": "edf8a461cf1d4005f19fb0b6b8b95a9f7fa0adc4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/e8ba02eed7bbbb9e59e43dedd3dddeff4a56b0c4", - "reference": "e8ba02eed7bbbb9e59e43dedd3dddeff4a56b0c4", + "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/edf8a461cf1d4005f19fb0b6b8b95a9f7fa0adc4", + "reference": "edf8a461cf1d4005f19fb0b6b8b95a9f7fa0adc4", "shasum": "" }, "require": { - "php": "^7.0" + "php": "^7.2", + "sebastian/object-reflector": "^1.1.1", + "sebastian/recursion-context": "^3.0" }, "require-dev": { - "phpunit/phpunit": "^6.0" + "ext-dom": "*", + "phpunit/phpunit": "^8.0" }, "suggest": { "ext-uopz": "*" @@ -5625,7 +5378,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "2.0-dev" + "dev-master": "3.0-dev" } }, "autoload": { @@ -5648,7 +5401,7 @@ "keywords": [ "global state" ], - "time": "2017-04-27T15:39:26+00:00" + "time": "2019-02-01T05:30:01+00:00" }, { "name": "sebastian/object-enumerator", @@ -5837,6 +5590,52 @@ "homepage": "https://www.github.com/sebastianbergmann/resource-operations", "time": "2018-10-04T04:07:39+00:00" }, + { + "name": "sebastian/type", + "version": "1.1.3", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/type.git", + "reference": "3aaaa15fa71d27650d62a948be022fe3b48541a3" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/type/zipball/3aaaa15fa71d27650d62a948be022fe3b48541a3", + "reference": "3aaaa15fa71d27650d62a948be022fe3b48541a3", + "shasum": "" + }, + "require": { + "php": "^7.2" + }, + "require-dev": { + "phpunit/phpunit": "^8.2" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.1-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Collection of value objects that represent the types of the PHP type system", + "homepage": "https://github.com/sebastianbergmann/type", + "time": "2019-07-02T08:10:15+00:00" + }, { "name": "sebastian/version", "version": "2.0.1", @@ -5882,16 +5681,16 @@ }, { "name": "symfony/browser-kit", - "version": "v4.3.1", + "version": "v4.3.2", "source": { "type": "git", "url": "https://github.com/symfony/browser-kit.git", - "reference": "e07d50e84b8cf489590f22244f4f609579b4a2c4" + "reference": "a29dd02a1f3f81b9a15c7730cc3226718ddb55ca" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/browser-kit/zipball/e07d50e84b8cf489590f22244f4f609579b4a2c4", - "reference": "e07d50e84b8cf489590f22244f4f609579b4a2c4", + "url": "https://api.github.com/repos/symfony/browser-kit/zipball/a29dd02a1f3f81b9a15c7730cc3226718ddb55ca", + "reference": "a29dd02a1f3f81b9a15c7730cc3226718ddb55ca", "shasum": "" }, "require": { @@ -5937,11 +5736,11 @@ ], "description": "Symfony BrowserKit Component", "homepage": "https://symfony.com", - "time": "2019-05-30T16:10:05+00:00" + "time": "2019-06-11T15:41:59+00:00" }, { "name": "symfony/css-selector", - "version": "v4.3.1", + "version": "v4.3.2", "source": { "type": "git", "url": "https://github.com/symfony/css-selector.git", @@ -5994,16 +5793,16 @@ }, { "name": "symfony/dom-crawler", - "version": "v4.3.1", + "version": "v4.3.2", "source": { "type": "git", "url": "https://github.com/symfony/dom-crawler.git", - "reference": "06ee58fbc9a8130f1d35b5280e15235a0515d457" + "reference": "291397232a2eefb3347eaab9170409981eaad0e2" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/dom-crawler/zipball/06ee58fbc9a8130f1d35b5280e15235a0515d457", - "reference": "06ee58fbc9a8130f1d35b5280e15235a0515d457", + "url": "https://api.github.com/repos/symfony/dom-crawler/zipball/291397232a2eefb3347eaab9170409981eaad0e2", + "reference": "291397232a2eefb3347eaab9170409981eaad0e2", "shasum": "" }, "require": { @@ -6051,20 +5850,20 @@ ], "description": "Symfony DomCrawler Component", "homepage": "https://symfony.com", - "time": "2019-05-31T18:55:30+00:00" + "time": "2019-06-13T11:03:18+00:00" }, { "name": "symfony/event-dispatcher", - "version": "v4.3.1", + "version": "v4.3.2", "source": { "type": "git", "url": "https://github.com/symfony/event-dispatcher.git", - "reference": "4e6c670af81c4fb0b6c08b035530a9915d0b691f" + "reference": "d257021c1ab28d48d24a16de79dfab445ce93398" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/4e6c670af81c4fb0b6c08b035530a9915d0b691f", - "reference": "4e6c670af81c4fb0b6c08b035530a9915d0b691f", + "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/d257021c1ab28d48d24a16de79dfab445ce93398", + "reference": "d257021c1ab28d48d24a16de79dfab445ce93398", "shasum": "" }, "require": { @@ -6121,20 +5920,20 @@ ], "description": "Symfony EventDispatcher Component", "homepage": "https://symfony.com", - "time": "2019-05-30T16:10:05+00:00" + "time": "2019-06-13T11:03:18+00:00" }, { "name": "symfony/event-dispatcher-contracts", - "version": "v1.1.1", + "version": "v1.1.5", "source": { "type": "git", "url": "https://github.com/symfony/event-dispatcher-contracts.git", - "reference": "8fa2cf2177083dd59cf8e44ea4b6541764fbda69" + "reference": "c61766f4440ca687de1084a5c00b08e167a2575c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/event-dispatcher-contracts/zipball/8fa2cf2177083dd59cf8e44ea4b6541764fbda69", - "reference": "8fa2cf2177083dd59cf8e44ea4b6541764fbda69", + "url": "https://api.github.com/repos/symfony/event-dispatcher-contracts/zipball/c61766f4440ca687de1084a5c00b08e167a2575c", + "reference": "c61766f4440ca687de1084a5c00b08e167a2575c", "shasum": "" }, "require": { @@ -6179,7 +5978,7 @@ "interoperability", "standards" ], - "time": "2019-05-22T12:23:29+00:00" + "time": "2019-06-20T06:46:26+00:00" }, { "name": "theseer/tokenizer", diff --git a/crowdin.yml b/crowdin.yml new file mode 100644 index 00000000000..ff3556761d9 --- /dev/null +++ b/crowdin.yml @@ -0,0 +1,3 @@ +files: + - source: /src/translations/**/*.php + translation: /src/translations/%two_letters_code%/app.php diff --git a/src/config/GeneralConfig.php b/src/config/GeneralConfig.php index d574213e3e7..17a55a38a3f 100644 --- a/src/config/GeneralConfig.php +++ b/src/config/GeneralConfig.php @@ -534,7 +534,7 @@ class GeneralConfig extends BaseObject */ public $preserveCmykColorspace = false; /** - * @var bool Whether the EXIF data should be preserved when manipulating images. + * @var bool Whether the EXIF data should be preserved when manipulating and uploading images. * * Setting this to `true` will result in larger image file sizes. * diff --git a/src/config/app.php b/src/config/app.php index 645f7a600a3..8cfd39cadbb 100644 --- a/src/config/app.php +++ b/src/config/app.php @@ -3,8 +3,8 @@ return [ 'id' => 'CraftCMS', 'name' => 'Craft CMS', - 'version' => '3.2.5.1', - 'schemaVersion' => '3.2.15', + 'version' => '3.2.6', + 'schemaVersion' => '3.2.16', 'minVersionRequired' => '2.6.2788', 'basePath' => dirname(__DIR__), // Defines the @app alias 'runtimePath' => '@storage/runtime', // Defines the @runtime alias diff --git a/src/controllers/AssetsController.php b/src/controllers/AssetsController.php index ced6081dd61..0388cff52ee 100644 --- a/src/controllers/AssetsController.php +++ b/src/controllers/AssetsController.php @@ -950,10 +950,10 @@ public function actionPreviewFile(): Response /** * Handles an error when generating a thumb/transform. * - * @param \Throwable $e The exception that was thrown + * @param \Exception $e The exception that was thrown * @return Response */ - private function _handleImageException(\Throwable $e): Response + private function _handleImageException(\Exception $e): Response { Craft::$app->getErrorHandler()->logException($e); $statusCode = $e instanceof HttpException && $e->statusCode ? $e->statusCode : 500; diff --git a/src/elements/db/ElementQuery.php b/src/elements/db/ElementQuery.php index 29107bfbd5e..84e4736505f 100644 --- a/src/elements/db/ElementQuery.php +++ b/src/elements/db/ElementQuery.php @@ -2683,6 +2683,11 @@ private function _createElement(array $row): ElementInterface } if ($class::hasContent() && $this->contentTable !== null) { + if ($class::hasTitles()) { + // Ensure the title is a string + $row['title'] = (string)($row['title'] ?? ''); + } + // Separate the content values from the main element attributes $fieldValues = []; diff --git a/src/helpers/DateTimeHelper.php b/src/helpers/DateTimeHelper.php index 5880df59f0b..46226a5f4ba 100644 --- a/src/helpers/DateTimeHelper.php +++ b/src/helpers/DateTimeHelper.php @@ -85,7 +85,7 @@ class DateTimeHelper * - Relaxed versions of W3C and MySQL formats (single-digit months, days, and hours) * - Unix timestamps * - An array with at least one of these keys defined: `datetime`, `date`, or `time`. Supported keys include: - * - `date` – a date string in `YYYY-MM-DD` format or the current locale’s short date format + * - `date` – a date string in `YYYY-MM-DD` or `YYYY-MM-DD HH:MM:SS.MU` formats or the current locale’s short date format * - `time` – a time string in `HH:MM` (24-hour) format or the current locale’s short time format * - `datetime` – A timestamp in any of the non-array formats supported by this method * - `timezone` – A [valid PHP timezone](http://php.net/manual/en/timezones.php). If set, this will override @@ -597,9 +597,13 @@ private static function _parseDate(string $value): array { $value = trim($value); - // First see if it's in YYYY-MM-DD format - if (preg_match('/^\d{4}-\d{2}-\d{2}$/', $value)) { - return [$value, 'Y-m-d']; + // First see if it's in YYYY-MM-DD or YYYY-MM-DD HH:MM:SS.MU formats + if (preg_match('/^\d{4}-\d{2}-\d{2}( \d{2}:\d{2}:\d{2}\.\d+)?$/', $value, $match)) { + $format = 'Y-m-d'; + if (!empty($match[1])) { + $format .= ' H:i:s.u'; + } + return [$value, $format]; } // Get the locale's short date format diff --git a/src/helpers/ElementHelper.php b/src/helpers/ElementHelper.php index 252b958dd91..e11ff194a76 100644 --- a/src/helpers/ElementHelper.php +++ b/src/helpers/ElementHelper.php @@ -76,7 +76,7 @@ public static function createSlug(string $str): string // Get the "words". Split on anything that is not alphanumeric or allowed punctuation // Reference: http://www.regular-expressions.info/unicode.html - $words = array_filter(preg_split('/[^\p{L}\p{N}\p{M}\._\-]+/', $str)); + $words = array_filter(preg_split('/[^\p{L}\p{N}\p{M}\._\-]+/u', $str)); return implode($generalConfig->slugWordSeparator, $words); } diff --git a/src/helpers/Image.php b/src/helpers/Image.php index 7e0ec5b5344..1bd16d7b6d4 100644 --- a/src/helpers/Image.php +++ b/src/helpers/Image.php @@ -328,6 +328,32 @@ public static function parseSvgSize(string $svg): array return [$width, $height]; } + /** + * Clean EXIF data from an image loaded inside an Imagick instance, taking + * care not to wipe the ICC profile. + * + * @param \Imagick $imagick + */ + public static function cleanExifDataFromImagickImage(\Imagick $imagick) + { + $config = Craft::$app->getConfig()->getGeneral(); + + if (!$config->preserveExifData) { + $iccProfiles = null; + $supportsImageProfiles = method_exists($imagick, 'getimageprofiles'); + + if ($config->preserveImageColorProfiles && $supportsImageProfiles) { + $iccProfiles = $imagick->getImageProfiles("icc", true); + } + + $imagick->stripImage(); + + if (!empty($iccProfiles)) { + $imagick->profileImage("icc", $iccProfiles['icc'] ?? []); + } + } + } + // Private Methods // ========================================================================= diff --git a/src/image/Raster.php b/src/image/Raster.php index e9b08abe500..a8160512378 100644 --- a/src/image/Raster.php +++ b/src/image/Raster.php @@ -371,11 +371,9 @@ public function resize(int $targetWidth = null, int $targetHeight = null) $this->_image = $gif; } else { if (Craft::$app->getImages()->getIsImagick() && Craft::$app->getConfig()->getGeneral()->optimizeImageFilesize) { - $config = Craft::$app->getConfig()->getGeneral(); - $keepImageProfiles = $config->preserveImageColorProfiles; - $keepExifData = $config->preserveExifData; + $keepImageProfiles = Craft::$app->getConfig()->getGeneral()->preserveImageColorProfiles; - $this->_image->smartResize(new Box($targetWidth, $targetHeight), $keepImageProfiles, $keepExifData, $this->_quality); + $this->_image->smartResize(new Box($targetWidth, $targetHeight), $keepImageProfiles, true, $this->_quality); } else { $this->_image->resize(new Box($targetWidth, $targetHeight), $this->_getResizeFilter()); } @@ -478,6 +476,9 @@ public function saveAs(string $targetPath, bool $autoQuality = false): bool Craft::warning("Unable to rename \"{$tempFile}\" to \"{$targetPath}\": " . $e->getMessage(), __METHOD__); } } else { + if (Craft::$app->getImages()->getIsImagick()) { + ImageHelper::cleanExifDataFromImagickImage($this->_image->getImagick()); + } $this->_image->save($targetPath, $options); } } catch (RuntimeException $e) { @@ -608,6 +609,14 @@ public function writeText(string $text, int $x, int $y, int $angle = 0) public function disableAnimation() { $this->_isAnimatedGif = false; + + if ($this->_image->layers()->count() > 1) { + // Fetching the first layer returns the built-in Imagick object + // So cycle that through the loading phase to get one that sports the + // `smartResize` functionality. + $this->_image = $this->_instance->load((string) $this->_image->layers()->get(0)); + } + return $this; } @@ -647,6 +656,10 @@ private function _autoGuessImageQuality(string $tempFileName, int $originalSize, clearstatcache(); // Generate one last time. + if (Craft::$app->getImages()->getIsImagick()) { + ImageHelper::cleanExifDataFromImagickImage($this->_image->getImagick()); + } + $this->_image->save($tempFileName, $this->_getSaveOptions($midQuality)); return $tempFileName; diff --git a/src/migrations/Install.php b/src/migrations/Install.php index 909c0643b8e..805092f46c3 100644 --- a/src/migrations/Install.php +++ b/src/migrations/Install.php @@ -459,7 +459,7 @@ public function createTables() 'type' => $this->enum('type', [Section::TYPE_SINGLE, Section::TYPE_CHANNEL, Section::TYPE_STRUCTURE])->notNull()->defaultValue('channel'), 'enableVersioning' => $this->boolean()->defaultValue(false)->notNull(), 'propagationMethod' => $this->string()->defaultValue(Section::PROPAGATION_METHOD_ALL)->notNull(), - 'previewTargets' => $this->string(), + 'previewTargets' => $this->text(), 'dateCreated' => $this->dateTime()->notNull(), 'dateUpdated' => $this->dateTime()->notNull(), 'dateDeleted' => $this->dateTime()->null(), diff --git a/src/migrations/m180521_173000_initial_yml_and_snapshot.php b/src/migrations/m180521_173000_initial_yml_and_snapshot.php index fc7ec253f4a..ef309ce1b0b 100644 --- a/src/migrations/m180521_173000_initial_yml_and_snapshot.php +++ b/src/migrations/m180521_173000_initial_yml_and_snapshot.php @@ -240,22 +240,23 @@ private function _getSectionData(): array ->innerJoin('{{%sections}} sections', '[[sections.id]] = [[entrytypes.sectionId]]') ->all(); - $layoutIds = ArrayHelper::getColumn($entryTypeRows, 'fieldLayoutId'); + $layoutIds = array_filter(ArrayHelper::getColumn($entryTypeRows, 'fieldLayoutId')); $fieldLayouts = $this->_generateFieldLayoutArray($layoutIds); foreach ($entryTypeRows as $entryType) { - $layout = $fieldLayouts[$entryType['fieldLayoutId']]; - - $layoutUid = $layout['uid']; - $sectionUid = $entryType['sectionUid']; - $uid = $entryType['uid']; - - unset($entryType['fieldLayoutId'], $entryType['sectionUid'], $entryType['uid'], $layout['uid']); + $uid = ArrayHelper::remove($entryType, 'uid'); + $sectionUid = ArrayHelper::remove($entryType, 'sectionUid'); + $fieldLayoutId = ArrayHelper::remove($entryType, 'fieldLayoutId'); $entryType['hasTitleField'] = (bool)$entryType['hasTitleField']; $entryType['sortOrder'] = (int)$entryType['sortOrder']; - $entryType['fieldLayouts'] = [$layoutUid => $layout]; + if ($fieldLayoutId) { + $layout = array_merge($fieldLayouts[$fieldLayoutId]); + $layoutUid = ArrayHelper::remove($layout, 'uid'); + $entryType['fieldLayouts'] = [$layoutUid => $layout]; + } + $sectionData[$sectionUid]['entryTypes'][$uid] = $entryType; } diff --git a/src/migrations/m190723_140314_fix_preview_targets_column.php b/src/migrations/m190723_140314_fix_preview_targets_column.php new file mode 100644 index 00000000000..6c1096d55e5 --- /dev/null +++ b/src/migrations/m190723_140314_fix_preview_targets_column.php @@ -0,0 +1,30 @@ +alterColumn(Table::SECTIONS, 'previewTargets', $this->text()); + } + + /** + * @inheritdoc + */ + public function safeDown() + { + echo "m190723_140314_fix_preview_targets_column cannot be reverted.\n"; + return false; + } +} diff --git a/src/services/Images.php b/src/services/Images.php index ee2592ad743..943b3d0af97 100644 --- a/src/services/Images.php +++ b/src/services/Images.php @@ -386,6 +386,7 @@ public function stripOrientationFromExifData(string $filePath): bool $image = new \Imagick($filePath); $image->setImageOrientation(\Imagick::ORIENTATION_UNDEFINED); + ImageHelper::cleanExifDataFromImagickImage($image); $image->writeImages($filePath, true); return true; diff --git a/src/services/ProjectConfig.php b/src/services/ProjectConfig.php index 8c95950f13e..2e5e7355abf 100644 --- a/src/services/ProjectConfig.php +++ b/src/services/ProjectConfig.php @@ -894,7 +894,9 @@ public function rebuild() $configData = array_replace_recursive([ 'system' => $currentConfig['system'], 'routes' => $currentConfig['routes'] ?? [], - 'plugins' => $currentConfig['plugins'] ?? [] + 'plugins' => $currentConfig['plugins'] ?? [], + 'users' => $currentConfig['users'] ?? [], + 'email' => $currentConfig['email'] ?? [], ], $event->config); $this->muteEvents = true; @@ -1571,25 +1573,23 @@ private function _getSectionData(): array ->andWhere(['entrytypes.dateDeleted' => null]) ->all(); - $layoutIds = ArrayHelper::getColumn($entryTypeRows, 'fieldLayoutId'); + $layoutIds = array_filter(ArrayHelper::getColumn($entryTypeRows, 'fieldLayoutId')); $fieldLayouts = $this->_generateFieldLayoutArray($layoutIds); foreach ($entryTypeRows as $entryType) { - if (empty($entryType['fieldLayoutId'])) { - continue; - } - - $layout = $fieldLayouts[$entryType['fieldLayoutId']]; - $layoutUid = $layout['uid']; - $sectionUid = $entryType['sectionUid']; - $uid = $entryType['uid']; - - unset($entryType['fieldLayoutId'], $entryType['sectionUid'], $entryType['uid'], $layout['uid']); + $uid = ArrayHelper::remove($entryType, 'uid'); + $sectionUid = ArrayHelper::remove($entryType, 'sectionUid'); + $fieldLayoutId = ArrayHelper::remove($entryType, 'fieldLayoutId'); $entryType['hasTitleField'] = (bool)$entryType['hasTitleField']; $entryType['sortOrder'] = (int)$entryType['sortOrder']; - $entryType['fieldLayouts'] = [$layoutUid => $layout]; + if ($fieldLayoutId) { + $layout = array_merge($fieldLayouts[$fieldLayoutId]); + $layoutUid = ArrayHelper::remove($layout, 'uid'); + $entryType['fieldLayouts'] = [$layoutUid => $layout]; + } + $sectionData[$sectionUid]['entryTypes'][$uid] = $entryType; } diff --git a/src/services/Sections.php b/src/services/Sections.php index 5f018da0bed..2c5f9f4882e 100644 --- a/src/services/Sections.php +++ b/src/services/Sections.php @@ -29,6 +29,7 @@ use craft\models\FieldLayout; use craft\models\Section; use craft\models\Section_SiteSettings; +use craft\models\Site; use craft\models\Structure; use craft\queue\jobs\ResaveElements; use craft\records\EntryType as EntryTypeRecord; @@ -1479,12 +1480,12 @@ private function _createSectionQuery(): Query * @param Section $section * @param array|null $siteSettings * @return Entry The - * @see saveSection() * @throws Exception if reasons + * @see saveSection() */ private function _ensureSingleEntry(Section $section, array $siteSettings = null): Entry { - // Get all the entries that currently exist for this section + // Get the section's supported sites // --------------------------------------------------------------------- if ($siteSettings === null) { @@ -1495,63 +1496,40 @@ private function _ensureSingleEntry(Section $section, array $siteSettings = null throw new Exception('No site settings exist for section ' . $section->id); } - $allSiteUids = array_keys($siteSettings); + $sites = ArrayHelper::where(Craft::$app->getSites()->getAllSites(), function(Site $site) use ($siteSettings) { + // Only include it if it's one of this section's sites + return isset($siteSettings[$site->uid]); + }); - $entryData = (new Query()) - ->select([ - 'e.id', - 'typeId', - 'siteId' => (new Query()) - ->select('es.siteId') - ->from('{{%elements_sites}} es') - ->innerJoin('{{%sites}} s', '[[s.id]] = [[es.siteId]]') - ->where('[[es.elementId]] = [[e.id]]') - ->andWhere(['in', 's.uid', $allSiteUids]) - ->limit(1) - ]) - ->from(['{{%entries}} e']) - ->where(['e.sectionId' => $section->id]) - ->orderBy(['e.id' => SORT_ASC]) - ->all(); + $siteIds = ArrayHelper::getColumn($sites, 'id', false); // Get the section's entry types // --------------------------------------------------------------------- - /** @var EntryType[] $entryTypes */ - $entryTypes = ArrayHelper::index($this->getEntryTypesBySectionId($section->id), 'id'); + $entryTypeIds = ArrayHelper::getColumn($this->getEntryTypesBySectionId($section->id), 'id', false); // There should always be at least one entry type by the time this is called - if (empty($entryTypes)) { + if (empty($entryTypeIds)) { throw new Exception('No entry types exist for section ' . $section->id); } // Get/save the entry // --------------------------------------------------------------------- - $entry = null; - // If there are any existing entries, find the first one with a valid typeId - foreach ($entryData as $data) { - if (isset($entryTypes[$data['typeId']])) { - $entry = Entry::find() - ->id($data['id']) - ->siteId($data['siteId']) - ->anyStatus() - ->one(); - break; - } - } + $entry = Entry::find() + ->typeId($entryTypeIds) + ->siteId($siteIds) + ->anyStatus() + ->one(); // Otherwise create a new one if ($entry === null) { // Create one - $firstSiteUid = reset($allSiteUids); - $firstEntryType = reset($entryTypes); - $entry = new Entry(); - $entry->siteId = Db::idByUid(Table::SITES, $firstSiteUid); + $entry->siteId = $siteIds[0]; $entry->sectionId = $section->id; - $entry->typeId = $firstEntryType->id; + $entry->typeId = $entryTypeIds[0]; $entry->title = $section->name; } @@ -1564,10 +1542,16 @@ private function _ensureSingleEntry(Section $section, array $siteSettings = null // Delete any other entries in the section // --------------------------------------------------------------------- - foreach ($entryData as $data) { - if ($data['id'] != $entry->id) { - Craft::$app->getElements()->deleteElementById($data['id'], Entry::class, $data['siteId']); - } + $elementsService = Craft::$app->getElements(); + $otherEntriesQuery = Entry::find() + ->sectionId($section->id) + ->siteId('*') + ->unique() + ->id(['not', $entry->id]) + ->anyStatus(); + + foreach ($otherEntriesQuery->each() as $entry) { + $elementsService->deleteElement($entry, true); } return $entry; @@ -1577,8 +1561,8 @@ private function _ensureSingleEntry(Section $section, array $siteSettings = null * Adds existing entries to a newly-created structure, if the section type was just converted to Structure. * * @param SectionRecord $sectionRecord - * @see saveSection() * @throws Exception if reasons + * @see saveSection() */ private function _populateNewStructure(SectionRecord $sectionRecord) { diff --git a/src/templates/_layouts/element.html b/src/templates/_layouts/element.html index 02c6750ad90..42b2de36535 100644 --- a/src/templates/_layouts/element.html +++ b/src/templates/_layouts/element.html @@ -30,6 +30,7 @@ {% set isDraft = element.getIsDraft() %} {% set isUnsavedDraft = element.getIsUnsavedDraft() %} {% set isRevision = element.getIsRevision() %} +{% set isCurrent = not isDraft and not isRevision %} {% set previewTargets = CraftEdition == CraftPro ? (element.previewTargets ?? []) : [] %} {% if element.uri %} @@ -74,7 +75,7 @@ {% if not isDraft and not canUpdateSource %} {% set saveShortcut = false %} -{% elseif isUnsavedDraft or (not (isDraft or isRevision) and canUpdateSource) %} +{% elseif isUnsavedDraft or (isCurrent and canUpdateSource) %} {% set saveShortcutRedirect = '{cpEditUrl}' %} {% endif %} @@ -94,17 +95,10 @@ {% endif %} - {% if actionButton %} + {% if isCurrent %} {% if previewTargets %}
{% endif %} - {{ actionButton|raw }} - {% endif %} - - {% if not isDraft and not isRevision %} - {% if previewTargets or actionButton %} -
- {% endif %}
{% if canUpdateSource and saveSourceAction %}
{{ 'Save as a Draft'|t('app') }}
@@ -113,6 +107,13 @@ {% endif %}
{% endif %} + + {% if actionButton %} + {% if previewTargets or isCurrent %} +
+ {% endif %} + {{ actionButton|raw }} + {% endif %} {% endblock %} {% block contextMenu %} @@ -120,7 +121,7 @@ {% endblock %} {% block actionButton %} - {% if isUnsavedDraft or not (isDraft or isRevision) %} + {% if isUnsavedDraft or isCurrent %} {# Can they save the source element, and do we know how to save it? #} {% if isUnsavedDraft or (canUpdateSource and saveSourceAction) %}
@@ -271,7 +272,7 @@
{{ "Notes"|t('app') }}
sourceId: element.getSourceId(), siteId: element.siteId, isUnsavedDraft: isUnsavedDraft, - isLive: not isDraft and not isRevision and element.enabled and element.enabledForSite and element.getRoute(), + isLive: isCurrent and element.enabled and element.enabledForSite and element.getRoute(), cpEditUrl: element.cpEditUrl, hashedRedirectUrl: (isUnsavedDraft ? redirectUrl : '{cpEditUrl}')|hash, draftId: element.draftId, diff --git a/src/templates/settings/plugins/index.html b/src/templates/settings/plugins/index.html index 0e0f9916391..f045e2cae6b 100644 --- a/src/templates/settings/plugins/index.html +++ b/src/templates/settings/plugins/index.html @@ -62,7 +62,7 @@

{{ config.name }}

{% set showLicenseKey = config.licenseKey or config.licenseKeyStatus != 'unknown' %}
- +
{{ "Buy now"|t('app') }} diff --git a/src/web/Request.php b/src/web/Request.php index d34506363c0..b3a64ed3565 100644 --- a/src/web/Request.php +++ b/src/web/Request.php @@ -219,6 +219,10 @@ public function init() if ($this->_isCpRequest) { // Chop the CP trigger segment off of the path & segments array array_shift($this->_segments); + + // Force 'p' pageTrigger + // (all that really matters is that it doesn't have a trailing slash, but whatever.) + $generalConfig->pageTrigger = 'p'; } // Is this a paginated request? diff --git a/src/web/assets/cp/dist/js/Craft.js b/src/web/assets/cp/dist/js/Craft.js index da725caf2f6..e0e6ee075be 100644 --- a/src/web/assets/cp/dist/js/Craft.js +++ b/src/web/assets/cp/dist/js/Craft.js @@ -1,4 +1,4 @@ -/*! - 2019-07-19 */ +/*! - 2019-07-22 */ (function($){ /** global: Craft */ @@ -215,7 +215,7 @@ $.extend(Craft, // Does baseUrl already contain a path? var pathMatch = url.match(new RegExp('[&\?]' + Craft.escapeRegex(Craft.pathParam) + '=[^&]+')); if (pathMatch) { - url = url.replace(pathMatch[0], pathMatch[0] + '/' + path); + url = url.replace(pathMatch[0], Craft.rtrim(pathMatch[0], '/') + '/' + path); path = ''; } } @@ -918,10 +918,11 @@ $.extend(Craft, if ($existingCss.length) { var existingCss = []; + var href; for (var i = 0; i < $existingCss.length; i++) { - var href = $existingCss.eq(i).attr('href'); - existingCss.push(href.replace(/[.?*+^$[\]\\(){}|-]/g, "\\$&")); + href = $existingCss.eq(i).attr('href').replace(/&/g, '&'); + existingCss.push(Craft.escapeRegex(href)); } var regexp = new RegExp(']*href="(?:' + existingCss.join('|') + ')".*?>', 'g'); @@ -942,10 +943,11 @@ $.extend(Craft, if ($existingJs.length) { var existingJs = []; + var src; for (var i = 0; i < $existingJs.length; i++) { - var src = $existingJs.eq(i).attr('src'); - existingJs.push(src.replace(/[.?*+^$[\]\\(){}|-]/g, "\\$&")); + src = $existingJs.eq(i).attr('src').replace(/&/g, '&'); + existingJs.push(Craft.escapeRegex(src)); } var regexp = new RegExp(']*src="(?:' + existingJs.join('|') + ')".*?>', 'g'); diff --git a/src/web/assets/cp/dist/js/Craft.min.js b/src/web/assets/cp/dist/js/Craft.min.js index 835eb0197c7..41bd920c3a8 100644 --- a/src/web/assets/cp/dist/js/Craft.min.js +++ b/src/web/assets/cp/dist/js/Craft.min.js @@ -1,2 +1,2 @@ -!function($){$.extend(Craft,{navHeight:48,t:function(t,e,i){if(void 0!==Craft.translations[t]&&void 0!==Craft.translations[t][e]&&(e=Craft.translations[t][e]),i)for(var s in i)i.hasOwnProperty(s)&&(e=e.replace("{"+s+"}",i[s]));return e},formatDate:function(t){return"object"!=typeof t&&(t=new Date(t)),$.datepicker.formatDate(Craft.datepickerOptions.dateFormat,t)},formatNumber:function(t,e){return void 0===e&&(e=",.0f"),d3.formatLocale(d3FormatLocaleDefinition).format(e)(t)},escapeHtml:function(t){return $("
").text(t).html()},escapeRegex:function(t){return t.replace(/[-[\]{}()*+?.,\\^$|#\s]/g,"\\$&")},getText:function(t){return $("
").html(t).text()},encodeUriComponent:function(t){t=encodeURIComponent(t);var e={"!":"%21","*":"%2A","'":"%27","(":"%28",")":"%29"};for(var i in e){var s=new RegExp("\\"+i,"g");t=t.replace(s,e[i])}return t},selectFullValue:function(t){var e=$(t),i=e.val();if(void 0!==e[0].setSelectionRange){var s=2*i.length;e[0].setSelectionRange(0,s)}else e.val(i)},formatInputId:function(t){return this.rtrim(t.replace(/[\[\]\\]+/g,"-"),"-")},getUrl:function(t,e,i){"string"!=typeof t&&(t="");var s="";if($.isPlainObject(e)){var n=[];for(var a in e)if(e.hasOwnProperty(a)){var r=e[a];"#"===a?s=r:null!==r&&""!==r&&n.push(a+"="+r)}e=n}e=Garnish.isArray(e)?e.join("&"):Craft.trim(e,"&?");var o,l=t.indexOf("?");if(-1!==l&&(e=t.substr(l+1)+(e?"&"+e:""),t=t.substr(0,l)),-1!==t.search("://")||"/"===t[0])return t+(e?"?"+e:"");if(t=Craft.trim(t,"/"),i){if(o=i,t){var h=o.match(new RegExp("[&?]"+Craft.escapeRegex(Craft.pathParam)+"=[^&]+"));h&&(o=o.replace(h[0],h[0]+"/"+t),t="")}}else o=Craft.baseUrl;if(-1!==(l=o.indexOf("?"))&&(e=o.substr(l+1)+(e?"&"+e:""),o=o.substr(0,l)),!Craft.omitScriptNameInUrls&&t)if(Craft.usePathInfo)-1===o.search(Craft.scriptName)&&(o=Craft.rtrim(o,"/")+"/"+Craft.scriptName);else{if(e&&e.substr(0,Craft.pathParam.length+1)===Craft.pathParam+"="){var d,c=e.indexOf("&");e=-1!==c?(d=e.substring(2,c),e.substr(c+1)):(d=e.substr(2),null),t=(d=Craft.rtrim(d))+(t?"/"+t:"")}e=Craft.pathParam+"="+t+(e?"&"+e:""),t=null}return t&&(o=Craft.rtrim(o,"/")+"/"+t),e&&(o+="?"+e),s&&(o+="#"+s),o},getCpUrl:function(t,e){return this.getUrl(t,e,Craft.baseCpUrl)},getSiteUrl:function(t,e){return this.getUrl(t,e,Craft.baseSiteUrl)},getActionUrl:function(t,e){return Craft.getUrl(t,e,Craft.actionUrl)},redirectTo:function(t){document.location.href=this.getUrl(t)},getCsrfInput:function(){return Craft.csrfTokenName?'':""},postActionRequest:function(t,e,i,s){"function"==typeof e&&(s=i,i=e,e={});var n={"X-Registered-Asset-Bundles":Object.keys(Craft.registeredAssetBundles).join(","),"X-Registered-Js-Files":Object.keys(Craft.registeredJsFiles).join(",")};Craft.csrfTokenValue&&Craft.csrfTokenName&&(n["X-CSRF-Token"]=Craft.csrfTokenValue);var a=$.ajax($.extend({url:Craft.getActionUrl(t),type:"POST",dataType:"json",headers:n,data:e,success:i,error:function(t,e){i&&i(null,e,t)},complete:function(t,e){"success"!==e&&(void 0!==Craft.cp?Craft.cp.displayError():alert(Craft.t("app","An unknown error occurred.")))}},s));return s&&"function"==typeof s.send&&s.send(a),a},_waitingOnAjax:!1,_ajaxQueue:[],queueActionRequest:function(t,e,i,s){"function"==typeof e&&(s=i,i=e,e=void 0),Craft._ajaxQueue.push([t,e,i,s]),Craft._waitingOnAjax||Craft._postNextActionRequestInQueue()},_postNextActionRequestInQueue:function(){Craft._waitingOnAjax=!0;var s=Craft._ajaxQueue.shift();Craft.postActionRequest(s[0],s[1],function(t,e,i){s[2]&&"function"==typeof s[2]&&s[2](t,e,i),Craft._ajaxQueue.length?Craft._postNextActionRequestInQueue():Craft._waitingOnAjax=!1},s[3])},stringToArray:function(t){if("string"!=typeof t)return t;for(var e=t.split(","),i=0;i]*href="(?:'+i.join("|")+')".*?><\/script>',"g");t=t.replace(a,"")}$("head").append(t)}},appendFootHtml:function(t){if(t){var e=$("script[src]");if(e.length){for(var i=[],s=0;s]*src="(?:'+i.join("|")+')".*?><\/script>',"g");t=t.replace(a,"")}Garnish.$bod.append(t)}},initUiElements:function(t){$(".grid",t).grid(),$(".info",t).infoicon(),$(".checkbox-select",t).checkboxselect(),$(".fieldtoggle",t).fieldtoggle(),$(".lightswitch",t).lightswitch(),$(".nicetext",t).nicetext(),$(".pill",t).pill(),$(".formsubmit",t).formsubmit(),$(".menubtn",t).menubtn()},_elementIndexClasses:{},_elementSelectorModalClasses:{},_elementEditorClasses:{},registerElementIndexClass:function(t,e){if(void 0!==this._elementIndexClasses[t])throw"An element index class has already been registered for the element type “"+t+"”.";this._elementIndexClasses[t]=e},registerElementSelectorModalClass:function(t,e){if(void 0!==this._elementSelectorModalClasses[t])throw"An element selector modal class has already been registered for the element type “"+t+"”.";this._elementSelectorModalClasses[t]=e},registerElementEditorClass:function(t,e){if(void 0!==this._elementEditorClasses[t])throw"An element editor class has already been registered for the element type “"+t+"”.";this._elementEditorClasses[t]=e},createElementIndex:function(t,e,i){return new(void 0!==this._elementIndexClasses[t]?this._elementIndexClasses[t]:Craft.BaseElementIndex)(t,e,i)},createElementSelectorModal:function(t,e){return new(void 0!==this._elementSelectorModalClasses[t]?this._elementSelectorModalClasses[t]:Craft.BaseElementSelectorModal)(t,e)},createElementEditor:function(t,e,i){return new(void 0!==this._elementEditorClasses[t]?this._elementEditorClasses[t]:Craft.BaseElementEditor)(e,i)},getLocalStorage:function(t,e){return t="Craft-"+Craft.systemUid+"."+t,"undefined"!=typeof localStorage&&void 0!==localStorage[t]?JSON.parse(localStorage[t]):e},setLocalStorage:function(t,e){if("undefined"!=typeof localStorage){t="Craft-"+Craft.systemUid+"."+t;try{localStorage[t]=JSON.stringify(e)}catch(t){}}},getElementInfo:function(t){var e=$(t);return e.hasClass("element")||(e=e.find(".element:first")),{id:e.data("id"),siteId:e.data("site-id"),label:e.data("label"),status:e.data("status"),url:e.data("url"),hasThumb:e.hasClass("hasthumb"),$element:e}},setElementSize:function(t,e){var i=$(t);if("small"!==e&&"large"!==e&&(e="small"),!i.hasClass(e)){var s="small"===e?"large":"small";if(i.addClass(e).removeClass(s),i.hasClass("hasthumb")){var n=i.find("> .elementthumb > img"),a=$("",{sizes:("small"===e?"30":"100")+"px",srcset:n.attr("srcset")||n.attr("data-pfsrcset")});n.replaceWith(a),picturefill({elements:[a[0]]})}}}}),$.extend($.fn,{animateLeft:function(t,e,i,s){return"ltr"===Craft.orientation?this.velocity({left:t},e,i,s):this.velocity({right:t},e,i,s)},animateRight:function(t,e,i,s){return"ltr"===Craft.orientation?this.velocity({right:t},e,i,s):this.velocity({left:t},e,i,s)},disable:function(){return this.each(function(){var t=$(this);t.addClass("disabled"),t.data("activatable")&&t.removeAttr("tabindex")})},enable:function(){return this.each(function(){var t=$(this);t.removeClass("disabled"),t.data("activatable")&&t.attr("tabindex","0")})},grid:function(){return this.each(function(){var t=$(this),e={};t.data("item-selector")&&(e.itemSelector=t.data("item-selector")),t.data("cols")&&(e.cols=parseInt(t.data("cols"))),t.data("max-cols")&&(e.maxCols=parseInt(t.data("max-cols"))),t.data("min-col-width")&&(e.minColWidth=parseInt(t.data("min-col-width"))),t.data("mode")&&(e.mode=t.data("mode")),t.data("fill-mode")&&(e.fillMode=t.data("fill-mode")),t.data("col-class")&&(e.colClass=t.data("col-class")),t.data("snap-to-grid")&&(e.snapToGrid=!!t.data("snap-to-grid")),new Craft.Grid(this,e)})},infoicon:function(){return this.each(function(){new Craft.InfoIcon(this)})},checkboxselect:function(){return this.each(function(){$.data(this,"checkboxselect")||new Garnish.CheckboxSelect(this)})},fieldtoggle:function(){return this.each(function(){$.data(this,"fieldtoggle")||new Craft.FieldToggle(this)})},lightswitch:function(e,t,i){return"settings"===e?("string"==typeof t?(e={})[t]=i:e=t,this.each(function(){var t=$.data(this,"lightswitch");t&&t.setSettings(e)})):($.isPlainObject(e)||(e={}),this.each(function(){var t=$.extend({},e);Garnish.hasAttr(this,"data-value")&&(t.value=$(this).attr("data-value")),$.data(this,"lightswitch")||new Craft.LightSwitch(this,t)}))},nicetext:function(){return this.each(function(){$.data(this,"nicetext")||new Garnish.NiceText(this)})},pill:function(){return this.each(function(){$.data(this,"pill")||new Garnish.Pill(this)})},formsubmit:function(){this.on("click",function(t){var e=$(t.currentTarget);if(!e.attr("data-confirm")||confirm(e.attr("data-confirm"))){var i=e.data("menu")?e.data("menu").$anchor:e,s=i.attr("data-form")?$("#"+i.attr("data-form")):i.closest("form");e.data("action")&&$('').val(e.data("action")).appendTo(s),e.data("redirect")&&$('').val(e.data("redirect")).appendTo(s),e.data("param")&&$('').attr({name:e.data("param"),value:e.data("value")}).appendTo(s),s.trigger({type:"submit",customTrigger:e})}})},menubtn:function(){return this.each(function(){var t=$(this);if(!t.data("menubtn")&&t.next().hasClass("menu")){var e={};t.data("menu-anchor")&&(e.menuAnchor=t.data("menu-anchor")),new Garnish.MenuBtn(t,e)}})}}),Garnish.$doc.ready(function(){Craft.initUiElements()}),Craft.BaseElementEditor=Garnish.Base.extend({$element:null,elementId:null,siteId:null,$form:null,$fieldsContainer:null,$cancelBtn:null,$saveBtn:null,$spinner:null,$siteSelect:null,$siteSpinner:null,hud:null,init:function(t,e){void 0===e&&$.isPlainObject(t)&&(e=t,t=null),this.$element=$(t),this.setSettings(e,Craft.BaseElementEditor.defaults),this.loadHud()},setElementAttribute:function(t,e){this.settings.attributes||(this.settings.attributes={}),null===e?delete this.settings.attributes[t]:this.settings.attributes[t]=e},getBaseData:function(){var t=$.extend({},this.settings.params);return this.settings.siteId?t.siteId=this.settings.siteId:this.$element&&this.$element.data("site-id")&&(t.siteId=this.$element.data("site-id")),this.settings.elementId?t.elementId=this.settings.elementId:this.$element&&this.$element.data("id")&&(t.elementId=this.$element.data("id")),this.settings.elementType&&(t.elementType=this.settings.elementType),this.settings.attributes&&(t.attributes=this.settings.attributes),this.settings.prevalidate&&(t.prevalidate=1),t},loadHud:function(){this.onBeginLoading();var t=this.getBaseData();t.includeSites=this.settings.showSiteSwitcher,Craft.postActionRequest("elements/get-editor-html",t,$.proxy(this,"showHud"))},showHud:function(t,e){if(this.onEndLoading(),"success"===e){var i=$();if(t.sites){var s=$('
'),n=$('
').appendTo(s);this.$siteSelect=$("').appendTo(l),this.$spinner=$('