# HG changeset patch # User Chris Cannam # Date 1531231679 -3600 # Node ID c2387f1178081127ad2d43dd1078b73b37d06f9d # Parent e200cb7efeb335a32cf3253cf1e5ad3b3987bf1e Routine composer update diff -r e200cb7efeb3 -r c2387f117808 composer.lock --- a/composer.lock Thu Apr 26 11:26:54 2018 +0100 +++ b/composer.lock Tue Jul 10 15:07:59 2018 +0100 @@ -1,7 +1,7 @@ { "_readme": [ "This file locks the dependencies of your project to a known state", - "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", + "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], "content-hash": "673d6450e7592482b377d82d279d6f25", @@ -242,16 +242,16 @@ }, { "name": "consolidation/annotated-command", - "version": "2.8.3", + "version": "2.8.4", "source": { "type": "git", "url": "https://github.com/consolidation/annotated-command.git", - "reference": "8f8f5da2ca06fbd3a85f7d551c49f844b7c59437" + "reference": "651541a0b68318a2a202bda558a676e5ad92223c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/consolidation/annotated-command/zipball/8f8f5da2ca06fbd3a85f7d551c49f844b7c59437", - "reference": "8f8f5da2ca06fbd3a85f7d551c49f844b7c59437", + "url": "https://api.github.com/repos/consolidation/annotated-command/zipball/651541a0b68318a2a202bda558a676e5ad92223c", + "reference": "651541a0b68318a2a202bda558a676e5ad92223c", "shasum": "" }, "require": { @@ -263,9 +263,9 @@ "symfony/finder": "^2.5|^3|^4" }, "require-dev": { - "greg-1-anderson/composer-test-scenarios": "^1", - "phpunit/phpunit": "^4.8", - "satooshi/php-coveralls": "^1.0.2 | dev-master", + "g1a/composer-test-scenarios": "^2", + "phpunit/phpunit": "^6", + "satooshi/php-coveralls": "^2", "squizlabs/php_codesniffer": "^2.7" }, "type": "library", @@ -290,20 +290,20 @@ } ], "description": "Initialize Symfony Console commands from annotated command class methods.", - "time": "2018-02-23T16:32:04+00:00" + "time": "2018-05-25T18:04:25+00:00" }, { "name": "consolidation/output-formatters", - "version": "3.2.0", + "version": "3.2.1", "source": { "type": "git", "url": "https://github.com/consolidation/output-formatters.git", - "reference": "da889e4bce19f145ca4ec5b1725a946f4eb625a9" + "reference": "d78ef59aea19d3e2e5a23f90a055155ee78a0ad5" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/consolidation/output-formatters/zipball/da889e4bce19f145ca4ec5b1725a946f4eb625a9", - "reference": "da889e4bce19f145ca4ec5b1725a946f4eb625a9", + "url": "https://api.github.com/repos/consolidation/output-formatters/zipball/d78ef59aea19d3e2e5a23f90a055155ee78a0ad5", + "reference": "d78ef59aea19d3e2e5a23f90a055155ee78a0ad5", "shasum": "" }, "require": { @@ -312,7 +312,7 @@ "symfony/finder": "^2.5|^3|^4" }, "require-dev": { - "g-1-a/composer-test-scenarios": "^2", + "g1a/composer-test-scenarios": "^2", "phpunit/phpunit": "^5.7.27", "satooshi/php-coveralls": "^2", "squizlabs/php_codesniffer": "^2.7", @@ -345,7 +345,7 @@ } ], "description": "Format text by applying transformations provided by plug-in formatters.", - "time": "2018-03-20T15:18:32+00:00" + "time": "2018-05-25T18:02:34+00:00" }, { "name": "dnoegel/php-xdg-base-dir", @@ -781,16 +781,16 @@ }, { "name": "drupal/core", - "version": "8.5.3", + "version": "8.5.5", "source": { "type": "git", "url": "https://github.com/drupal/core.git", - "reference": "b012f0ae51504880e920f2c6efdbdf03b6fe2129" + "reference": "900c28f19d4b5643f43c1cf046684046402eaac4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/drupal/core/zipball/b012f0ae51504880e920f2c6efdbdf03b6fe2129", - "reference": "b012f0ae51504880e920f2c6efdbdf03b6fe2129", + "url": "https://api.github.com/repos/drupal/core/zipball/900c28f19d4b5643f43c1cf046684046402eaac4", + "reference": "900c28f19d4b5643f43c1cf046684046402eaac4", "shasum": "" }, "require": { @@ -1012,20 +1012,20 @@ "GPL-2.0-or-later" ], "description": "Drupal is an open source content management platform powering millions of websites and applications.", - "time": "2018-04-25T15:39:01+00:00" + "time": "2018-07-04T21:08:11+00:00" }, { "name": "drush/drush", - "version": "8.1.16", + "version": "8.1.17", "source": { "type": "git", "url": "https://github.com/drush-ops/drush.git", - "reference": "bbaff2dc725a5f3eb22006c5de3dc92a2de54b08" + "reference": "7ea681dc7e639f6ddab906e78611d3558f88d9b0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/drush-ops/drush/zipball/bbaff2dc725a5f3eb22006c5de3dc92a2de54b08", - "reference": "bbaff2dc725a5f3eb22006c5de3dc92a2de54b08", + "url": "https://api.github.com/repos/drush-ops/drush/zipball/7ea681dc7e639f6ddab906e78611d3558f88d9b0", + "reference": "7ea681dc7e639f6ddab906e78611d3558f88d9b0", "shasum": "" }, "require": { @@ -1121,7 +1121,7 @@ ], "description": "Drush is a command line shell and scripting interface for Drupal, a veritable Swiss Army knife designed to make life easier for those of us who spend some of our working hours hacking away at the command prompt.", "homepage": "http://www.drush.org", - "time": "2018-02-06T21:18:48+00:00" + "time": "2018-05-23T16:58:54+00:00" }, { "name": "easyrdf/easyrdf", @@ -1572,16 +1572,16 @@ }, { "name": "nikic/php-parser", - "version": "v4.0.1", + "version": "v4.0.2", "source": { "type": "git", "url": "https://github.com/nikic/PHP-Parser.git", - "reference": "e4a54fa90a5cd8e8dd3fb4099942681731c5cdd3" + "reference": "35b8caf75e791ba1b2d24fec1552168d72692b12" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/e4a54fa90a5cd8e8dd3fb4099942681731c5cdd3", - "reference": "e4a54fa90a5cd8e8dd3fb4099942681731c5cdd3", + "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/35b8caf75e791ba1b2d24fec1552168d72692b12", + "reference": "35b8caf75e791ba1b2d24fec1552168d72692b12", "shasum": "" }, "require": { @@ -1619,20 +1619,20 @@ "parser", "php" ], - "time": "2018-03-25T17:35:16+00:00" + "time": "2018-06-03T11:33:10+00:00" }, { "name": "paragonie/random_compat", - "version": "v2.0.12", + "version": "v2.0.17", "source": { "type": "git", "url": "https://github.com/paragonie/random_compat.git", - "reference": "258c89a6b97de7dfaf5b8c7607d0478e236b04fb" + "reference": "29af24f25bab834fcbb38ad2a69fa93b867e070d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/paragonie/random_compat/zipball/258c89a6b97de7dfaf5b8c7607d0478e236b04fb", - "reference": "258c89a6b97de7dfaf5b8c7607d0478e236b04fb", + "url": "https://api.github.com/repos/paragonie/random_compat/zipball/29af24f25bab834fcbb38ad2a69fa93b867e070d", + "reference": "29af24f25bab834fcbb38ad2a69fa93b867e070d", "shasum": "" }, "require": { @@ -1664,10 +1664,11 @@ "description": "PHP 5.x polyfill for random_bytes() and random_int() from PHP 7", "keywords": [ "csprng", + "polyfill", "pseudorandom", "random" ], - "time": "2018-04-04T21:24:14+00:00" + "time": "2018-07-04T16:31:37+00:00" }, { "name": "pear/console_table", @@ -1872,16 +1873,16 @@ }, { "name": "psy/psysh", - "version": "v0.9.3", + "version": "v0.9.6", "source": { "type": "git", "url": "https://github.com/bobthecow/psysh.git", - "reference": "79c280013cf0b30fa23f3ba8bd3649218075adf4" + "reference": "4a2ce86f199d51b6e2524214dc06835e872f4fce" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/bobthecow/psysh/zipball/79c280013cf0b30fa23f3ba8bd3649218075adf4", - "reference": "79c280013cf0b30fa23f3ba8bd3649218075adf4", + "url": "https://api.github.com/repos/bobthecow/psysh/zipball/4a2ce86f199d51b6e2524214dc06835e872f4fce", + "reference": "4a2ce86f199d51b6e2524214dc06835e872f4fce", "shasum": "" }, "require": { @@ -1893,9 +1894,9 @@ "symfony/var-dumper": "~2.7|~3.0|~4.0" }, "require-dev": { + "bamarni/composer-bin-plugin": "^1.2", "hoa/console": "~2.15|~3.16", - "phpunit/phpunit": "~4.8.35|~5.0|~6.0|~7.0", - "symfony/finder": "~2.1|~3.0|~4.0" + "phpunit/phpunit": "~4.8.35|~5.0|~6.0|~7.0" }, "suggest": { "ext-pcntl": "Enabling the PCNTL extension makes PsySH a lot happier :)", @@ -1940,7 +1941,7 @@ "interactive", "shell" ], - "time": "2018-04-18T12:32:50+00:00" + "time": "2018-06-10T17:57:20+00:00" }, { "name": "stack/builder", @@ -2052,7 +2053,7 @@ }, { "name": "symfony/class-loader", - "version": "v3.4.8", + "version": "v3.4.12", "source": { "type": "git", "url": "https://github.com/symfony/class-loader.git", @@ -2108,16 +2109,16 @@ }, { "name": "symfony/console", - "version": "v3.4.8", + "version": "v3.4.12", "source": { "type": "git", "url": "https://github.com/symfony/console.git", - "reference": "d4bb70fa24d540c309d88a9d6e43fb2d339b1fbf" + "reference": "1b97071a26d028c9bd4588264e101e14f6e7cd00" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/console/zipball/d4bb70fa24d540c309d88a9d6e43fb2d339b1fbf", - "reference": "d4bb70fa24d540c309d88a9d6e43fb2d339b1fbf", + "url": "https://api.github.com/repos/symfony/console/zipball/1b97071a26d028c9bd4588264e101e14f6e7cd00", + "reference": "1b97071a26d028c9bd4588264e101e14f6e7cd00", "shasum": "" }, "require": { @@ -2138,7 +2139,7 @@ "symfony/process": "~3.3|~4.0" }, "suggest": { - "psr/log": "For using the console logger", + "psr/log-implementation": "For using the console logger", "symfony/event-dispatcher": "", "symfony/lock": "", "symfony/process": "" @@ -2173,20 +2174,20 @@ ], "description": "Symfony Console Component", "homepage": "https://symfony.com", - "time": "2018-04-03T05:22:50+00:00" + "time": "2018-05-23T05:02:55+00:00" }, { "name": "symfony/debug", - "version": "v3.4.8", + "version": "v3.4.12", "source": { "type": "git", "url": "https://github.com/symfony/debug.git", - "reference": "9cf7c2271cfb89ef9727db1b740ca77be57bf9d7" + "reference": "47e6788c5b151cf0cfdf3329116bf33800632d75" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/debug/zipball/9cf7c2271cfb89ef9727db1b740ca77be57bf9d7", - "reference": "9cf7c2271cfb89ef9727db1b740ca77be57bf9d7", + "url": "https://api.github.com/repos/symfony/debug/zipball/47e6788c5b151cf0cfdf3329116bf33800632d75", + "reference": "47e6788c5b151cf0cfdf3329116bf33800632d75", "shasum": "" }, "require": { @@ -2229,20 +2230,20 @@ ], "description": "Symfony Debug Component", "homepage": "https://symfony.com", - "time": "2018-04-03T05:22:50+00:00" + "time": "2018-06-25T11:10:40+00:00" }, { "name": "symfony/dependency-injection", - "version": "v3.4.8", + "version": "v3.4.12", "source": { "type": "git", "url": "https://github.com/symfony/dependency-injection.git", - "reference": "24a68710c6ddc1e3d159a110cef94cedfcf3c611" + "reference": "a0be80e3f8c11aca506e250c00bb100c04c35d10" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/dependency-injection/zipball/24a68710c6ddc1e3d159a110cef94cedfcf3c611", - "reference": "24a68710c6ddc1e3d159a110cef94cedfcf3c611", + "url": "https://api.github.com/repos/symfony/dependency-injection/zipball/a0be80e3f8c11aca506e250c00bb100c04c35d10", + "reference": "a0be80e3f8c11aca506e250c00bb100c04c35d10", "shasum": "" }, "require": { @@ -2300,11 +2301,11 @@ ], "description": "Symfony DependencyInjection Component", "homepage": "https://symfony.com", - "time": "2018-03-29T11:25:31+00:00" + "time": "2018-06-25T08:36:56+00:00" }, { "name": "symfony/event-dispatcher", - "version": "v3.4.8", + "version": "v3.4.12", "source": { "type": "git", "url": "https://github.com/symfony/event-dispatcher.git", @@ -2367,16 +2368,16 @@ }, { "name": "symfony/finder", - "version": "v3.4.8", + "version": "v3.4.12", "source": { "type": "git", "url": "https://github.com/symfony/finder.git", - "reference": "bd14efe8b1fabc4de82bf50dce62f05f9a102433" + "reference": "3a8c3de91d2b2c68cd2d665cf9d00f7ef9eaa394" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/finder/zipball/bd14efe8b1fabc4de82bf50dce62f05f9a102433", - "reference": "bd14efe8b1fabc4de82bf50dce62f05f9a102433", + "url": "https://api.github.com/repos/symfony/finder/zipball/3a8c3de91d2b2c68cd2d665cf9d00f7ef9eaa394", + "reference": "3a8c3de91d2b2c68cd2d665cf9d00f7ef9eaa394", "shasum": "" }, "require": { @@ -2412,20 +2413,20 @@ ], "description": "Symfony Finder Component", "homepage": "https://symfony.com", - "time": "2018-04-04T05:07:11+00:00" + "time": "2018-06-19T20:52:10+00:00" }, { "name": "symfony/http-foundation", - "version": "v3.4.8", + "version": "v3.4.12", "source": { "type": "git", "url": "https://github.com/symfony/http-foundation.git", - "reference": "b11e6d165ff4cbf5685d185ab19a90f2f3bb7d1e" + "reference": "1c28679fcbb0d9b35e4fd49fbb74d2ca4ea17bce" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/http-foundation/zipball/b11e6d165ff4cbf5685d185ab19a90f2f3bb7d1e", - "reference": "b11e6d165ff4cbf5685d185ab19a90f2f3bb7d1e", + "url": "https://api.github.com/repos/symfony/http-foundation/zipball/1c28679fcbb0d9b35e4fd49fbb74d2ca4ea17bce", + "reference": "1c28679fcbb0d9b35e4fd49fbb74d2ca4ea17bce", "shasum": "" }, "require": { @@ -2466,20 +2467,20 @@ ], "description": "Symfony HttpFoundation Component", "homepage": "https://symfony.com", - "time": "2018-04-03T05:22:50+00:00" + "time": "2018-06-21T11:10:19+00:00" }, { "name": "symfony/http-kernel", - "version": "v3.4.8", + "version": "v3.4.12", "source": { "type": "git", "url": "https://github.com/symfony/http-kernel.git", - "reference": "3cc2d4374aa9590c09277ad68657671cf49dbbf4" + "reference": "cb7edcdc47cab3c61c891e6e55337f8dd470d820" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/http-kernel/zipball/3cc2d4374aa9590c09277ad68657671cf49dbbf4", - "reference": "3cc2d4374aa9590c09277ad68657671cf49dbbf4", + "url": "https://api.github.com/repos/symfony/http-kernel/zipball/cb7edcdc47cab3c61c891e6e55337f8dd470d820", + "reference": "cb7edcdc47cab3c61c891e6e55337f8dd470d820", "shasum": "" }, "require": { @@ -2487,7 +2488,8 @@ "psr/log": "~1.0", "symfony/debug": "~2.8|~3.0|~4.0", "symfony/event-dispatcher": "~2.8|~3.0|~4.0", - "symfony/http-foundation": "^3.4.4|^4.0.4" + "symfony/http-foundation": "~3.4.12|~4.0.12|^4.1.1", + "symfony/polyfill-ctype": "~1.8" }, "conflict": { "symfony/config": "<2.8", @@ -2554,20 +2556,75 @@ ], "description": "Symfony HttpKernel Component", "homepage": "https://symfony.com", - "time": "2018-04-06T15:19:48+00:00" + "time": "2018-06-25T12:29:19+00:00" + }, + { + "name": "symfony/polyfill-ctype", + "version": "v1.8.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-ctype.git", + "reference": "7cc359f1b7b80fc25ed7796be7d96adc9b354bae" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/7cc359f1b7b80fc25ed7796be7d96adc9b354bae", + "reference": "7cc359f1b7b80fc25ed7796be7d96adc9b354bae", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.8-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Polyfill\\Ctype\\": "" + }, + "files": [ + "bootstrap.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + }, + { + "name": "Gert de Pagter", + "email": "BackEndTea@gmail.com" + } + ], + "description": "Symfony polyfill for ctype functions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "ctype", + "polyfill", + "portable" + ], + "time": "2018-04-30T19:57:29+00:00" }, { "name": "symfony/polyfill-iconv", - "version": "v1.7.0", + "version": "v1.8.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-iconv.git", - "reference": "bd515d8f392730c833bc1ba993a4f598da64fa5b" + "reference": "7cb8436a814d5b0fcf292810ee26f8b0cb47584d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-iconv/zipball/bd515d8f392730c833bc1ba993a4f598da64fa5b", - "reference": "bd515d8f392730c833bc1ba993a4f598da64fa5b", + "url": "https://api.github.com/repos/symfony/polyfill-iconv/zipball/7cb8436a814d5b0fcf292810ee26f8b0cb47584d", + "reference": "7cb8436a814d5b0fcf292810ee26f8b0cb47584d", "shasum": "" }, "require": { @@ -2579,7 +2636,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "1.7-dev" + "dev-master": "1.8-dev" } }, "autoload": { @@ -2613,20 +2670,20 @@ "portable", "shim" ], - "time": "2018-01-30T19:27:44+00:00" + "time": "2018-04-26T10:06:28+00:00" }, { "name": "symfony/polyfill-mbstring", - "version": "v1.7.0", + "version": "v1.8.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-mbstring.git", - "reference": "78be803ce01e55d3491c1397cf1c64beb9c1b63b" + "reference": "3296adf6a6454a050679cde90f95350ad604b171" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/78be803ce01e55d3491c1397cf1c64beb9c1b63b", - "reference": "78be803ce01e55d3491c1397cf1c64beb9c1b63b", + "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/3296adf6a6454a050679cde90f95350ad604b171", + "reference": "3296adf6a6454a050679cde90f95350ad604b171", "shasum": "" }, "require": { @@ -2638,7 +2695,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "1.7-dev" + "dev-master": "1.8-dev" } }, "autoload": { @@ -2672,20 +2729,20 @@ "portable", "shim" ], - "time": "2018-01-30T19:27:44+00:00" + "time": "2018-04-26T10:06:28+00:00" }, { "name": "symfony/polyfill-php70", - "version": "v1.7.0", + "version": "v1.8.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-php70.git", - "reference": "3532bfcd8f933a7816f3a0a59682fc404776600f" + "reference": "77454693d8f10dd23bb24955cffd2d82db1007a6" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php70/zipball/3532bfcd8f933a7816f3a0a59682fc404776600f", - "reference": "3532bfcd8f933a7816f3a0a59682fc404776600f", + "url": "https://api.github.com/repos/symfony/polyfill-php70/zipball/77454693d8f10dd23bb24955cffd2d82db1007a6", + "reference": "77454693d8f10dd23bb24955cffd2d82db1007a6", "shasum": "" }, "require": { @@ -2695,7 +2752,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "1.7-dev" + "dev-master": "1.8-dev" } }, "autoload": { @@ -2731,20 +2788,20 @@ "portable", "shim" ], - "time": "2018-01-30T19:27:44+00:00" + "time": "2018-04-26T10:06:28+00:00" }, { "name": "symfony/process", - "version": "v3.4.8", + "version": "v3.4.12", "source": { "type": "git", "url": "https://github.com/symfony/process.git", - "reference": "4b7d64e852886319e93ddfdecff0d744ab87658b" + "reference": "acc5a37c706ace827962851b69705b24e71ca17c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/process/zipball/4b7d64e852886319e93ddfdecff0d744ab87658b", - "reference": "4b7d64e852886319e93ddfdecff0d744ab87658b", + "url": "https://api.github.com/repos/symfony/process/zipball/acc5a37c706ace827962851b69705b24e71ca17c", + "reference": "acc5a37c706ace827962851b69705b24e71ca17c", "shasum": "" }, "require": { @@ -2780,7 +2837,7 @@ ], "description": "Symfony Process Component", "homepage": "https://symfony.com", - "time": "2018-04-03T05:22:50+00:00" + "time": "2018-05-30T04:24:30+00:00" }, { "name": "symfony/psr-http-message-bridge", @@ -2844,16 +2901,16 @@ }, { "name": "symfony/routing", - "version": "v3.4.8", + "version": "v3.4.12", "source": { "type": "git", "url": "https://github.com/symfony/routing.git", - "reference": "50f333b707bef9f6972ad04e6df3ec8875c9a67c" + "reference": "6b9fef5343828e542db17e2519722ef08992f2c1" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/routing/zipball/50f333b707bef9f6972ad04e6df3ec8875c9a67c", - "reference": "50f333b707bef9f6972ad04e6df3ec8875c9a67c", + "url": "https://api.github.com/repos/symfony/routing/zipball/6b9fef5343828e542db17e2519722ef08992f2c1", + "reference": "6b9fef5343828e542db17e2519722ef08992f2c1", "shasum": "" }, "require": { @@ -2866,7 +2923,6 @@ }, "require-dev": { "doctrine/annotations": "~1.0", - "doctrine/common": "~2.2", "psr/log": "~1.0", "symfony/config": "^3.3.1|~4.0", "symfony/dependency-injection": "~3.3|~4.0", @@ -2918,24 +2974,25 @@ "uri", "url" ], - "time": "2018-04-04T13:22:16+00:00" + "time": "2018-06-19T20:52:10+00:00" }, { "name": "symfony/serializer", - "version": "v3.4.8", + "version": "v3.4.12", "source": { "type": "git", "url": "https://github.com/symfony/serializer.git", - "reference": "d4dc1551da627273230fe16511f4bb4844c02399" + "reference": "2e6d57dbbb37691f1480393440aff3a4b69dd9f7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/serializer/zipball/d4dc1551da627273230fe16511f4bb4844c02399", - "reference": "d4dc1551da627273230fe16511f4bb4844c02399", + "url": "https://api.github.com/repos/symfony/serializer/zipball/2e6d57dbbb37691f1480393440aff3a4b69dd9f7", + "reference": "2e6d57dbbb37691f1480393440aff3a4b69dd9f7", "shasum": "" }, "require": { - "php": "^5.5.9|>=7.0.8" + "php": "^5.5.9|>=7.0.8", + "symfony/polyfill-ctype": "~1.8" }, "conflict": { "phpdocumentor/type-resolver": "<0.2.1", @@ -2996,20 +3053,20 @@ ], "description": "Symfony Serializer Component", "homepage": "https://symfony.com", - "time": "2018-03-15T19:08:29+00:00" + "time": "2018-06-22T08:58:39+00:00" }, { "name": "symfony/translation", - "version": "v3.4.8", + "version": "v3.4.12", "source": { "type": "git", "url": "https://github.com/symfony/translation.git", - "reference": "80e19eaf12cbb546ac40384e5c55c36306823e57" + "reference": "7047f725e35eab768137c677f8c38e4a2a8e38fb" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/translation/zipball/80e19eaf12cbb546ac40384e5c55c36306823e57", - "reference": "80e19eaf12cbb546ac40384e5c55c36306823e57", + "url": "https://api.github.com/repos/symfony/translation/zipball/7047f725e35eab768137c677f8c38e4a2a8e38fb", + "reference": "7047f725e35eab768137c677f8c38e4a2a8e38fb", "shasum": "" }, "require": { @@ -3030,7 +3087,7 @@ "symfony/yaml": "~3.4|~4.0" }, "suggest": { - "psr/log": "To use logging capability in translator", + "psr/log-implementation": "To use logging capability in translator", "symfony/config": "", "symfony/yaml": "" }, @@ -3064,24 +3121,25 @@ ], "description": "Symfony Translation Component", "homepage": "https://symfony.com", - "time": "2018-02-22T06:28:18+00:00" + "time": "2018-05-21T10:06:52+00:00" }, { "name": "symfony/validator", - "version": "v3.4.8", + "version": "v3.4.12", "source": { "type": "git", "url": "https://github.com/symfony/validator.git", - "reference": "6fa41262dcbd50eedb1e841cfd97f5a1956cf2e7" + "reference": "fca490df65008eb680c5ee9c2d521191c9e54ed5" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/validator/zipball/6fa41262dcbd50eedb1e841cfd97f5a1956cf2e7", - "reference": "6fa41262dcbd50eedb1e841cfd97f5a1956cf2e7", + "url": "https://api.github.com/repos/symfony/validator/zipball/fca490df65008eb680c5ee9c2d521191c9e54ed5", + "reference": "fca490df65008eb680c5ee9c2d521191c9e54ed5", "shasum": "" }, "require": { "php": "^5.5.9|>=7.0.8", + "symfony/polyfill-ctype": "~1.8", "symfony/polyfill-mbstring": "~1.0", "symfony/translation": "~2.8|~3.0|~4.0" }, @@ -3148,20 +3206,20 @@ ], "description": "Symfony Validator Component", "homepage": "https://symfony.com", - "time": "2018-04-06T07:35:25+00:00" + "time": "2018-06-19T20:52:10+00:00" }, { "name": "symfony/var-dumper", - "version": "v3.4.8", + "version": "v3.4.12", "source": { "type": "git", "url": "https://github.com/symfony/var-dumper.git", - "reference": "951643091b39a6fd40fce56cd16e21e12bef3feb" + "reference": "e173954a28a44a32c690815fbe4d0f2eac43accb" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/var-dumper/zipball/951643091b39a6fd40fce56cd16e21e12bef3feb", - "reference": "951643091b39a6fd40fce56cd16e21e12bef3feb", + "url": "https://api.github.com/repos/symfony/var-dumper/zipball/e173954a28a44a32c690815fbe4d0f2eac43accb", + "reference": "e173954a28a44a32c690815fbe4d0f2eac43accb", "shasum": "" }, "require": { @@ -3217,24 +3275,25 @@ "debug", "dump" ], - "time": "2018-04-03T20:34:11+00:00" + "time": "2018-06-15T07:47:49+00:00" }, { "name": "symfony/yaml", - "version": "v3.4.8", + "version": "v3.4.12", "source": { "type": "git", "url": "https://github.com/symfony/yaml.git", - "reference": "a42f9da85c7c38d59f5e53f076fe81a091f894d0" + "reference": "c5010cc1692ce1fa328b1fb666961eb3d4a85bb0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/yaml/zipball/a42f9da85c7c38d59f5e53f076fe81a091f894d0", - "reference": "a42f9da85c7c38d59f5e53f076fe81a091f894d0", + "url": "https://api.github.com/repos/symfony/yaml/zipball/c5010cc1692ce1fa328b1fb666961eb3d4a85bb0", + "reference": "c5010cc1692ce1fa328b1fb666961eb3d4a85bb0", "shasum": "" }, "require": { - "php": "^5.5.9|>=7.0.8" + "php": "^5.5.9|>=7.0.8", + "symfony/polyfill-ctype": "~1.8" }, "conflict": { "symfony/console": "<3.4" @@ -3275,7 +3334,7 @@ ], "description": "Symfony Yaml Component", "homepage": "https://symfony.com", - "time": "2018-04-03T05:14:20+00:00" + "time": "2018-05-03T23:18:14+00:00" }, { "name": "twig/twig", @@ -3489,16 +3548,16 @@ }, { "name": "zendframework/zend-diactoros", - "version": "1.7.1", + "version": "1.8.1", "source": { "type": "git", "url": "https://github.com/zendframework/zend-diactoros.git", - "reference": "bf26aff803a11c5cc8eb7c4878a702c403ec67f1" + "reference": "63d920d1c9ebc009d860c3666593a66298727dd6" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/zendframework/zend-diactoros/zipball/bf26aff803a11c5cc8eb7c4878a702c403ec67f1", - "reference": "bf26aff803a11c5cc8eb7c4878a702c403ec67f1", + "url": "https://api.github.com/repos/zendframework/zend-diactoros/zipball/63d920d1c9ebc009d860c3666593a66298727dd6", + "reference": "63d920d1c9ebc009d860c3666593a66298727dd6", "shasum": "" }, "require": { @@ -3517,11 +3576,22 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "1.7.x-dev", - "dev-develop": "1.8.x-dev" + "dev-master": "1.8.x-dev", + "dev-develop": "1.9.x-dev", + "dev-release-2.0": "2.0.x-dev" } }, "autoload": { + "files": [ + "src/functions/create_uploaded_file.php", + "src/functions/marshal_headers_from_sapi.php", + "src/functions/marshal_method_from_sapi.php", + "src/functions/marshal_protocol_version_from_sapi.php", + "src/functions/marshal_uri_from_sapi.php", + "src/functions/normalize_server.php", + "src/functions/normalize_uploaded_files.php", + "src/functions/parse_cookie_header.php" + ], "psr-4": { "Zend\\Diactoros\\": "src/" } @@ -3537,7 +3607,7 @@ "psr", "psr-7" ], - "time": "2018-02-26T15:44:50+00:00" + "time": "2018-07-09T21:17:27+00:00" }, { "name": "zendframework/zend-escaper", @@ -3586,16 +3656,16 @@ }, { "name": "zendframework/zend-feed", - "version": "2.9.0", + "version": "2.10.2", "source": { "type": "git", "url": "https://github.com/zendframework/zend-feed.git", - "reference": "abe88686124d492e0a2a84656f15e5482bfbe030" + "reference": "5253f949f4ad999086ab9b408908b6c6776f24db" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/zendframework/zend-feed/zipball/abe88686124d492e0a2a84656f15e5482bfbe030", - "reference": "abe88686124d492e0a2a84656f15e5482bfbe030", + "url": "https://api.github.com/repos/zendframework/zend-feed/zipball/5253f949f4ad999086ab9b408908b6c6776f24db", + "reference": "5253f949f4ad999086ab9b408908b6c6776f24db", "shasum": "" }, "require": { @@ -3624,8 +3694,8 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "2.9-dev", - "dev-develop": "2.10-dev" + "dev-master": "2.10.x-dev", + "dev-develop": "2.11.x-dev" } }, "autoload": { @@ -3643,35 +3713,35 @@ "feed", "zf" ], - "time": "2017-12-04T17:59:38+00:00" + "time": "2018-06-18T20:14:01+00:00" }, { "name": "zendframework/zend-stdlib", - "version": "3.1.1", + "version": "3.2.0", "source": { "type": "git", "url": "https://github.com/zendframework/zend-stdlib.git", - "reference": "10ef03144902d1955f935fff5346ed52f7d99bcc" + "reference": "cd164b4a18b5d1aeb69be2c26db035b5ed6925ae" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/zendframework/zend-stdlib/zipball/10ef03144902d1955f935fff5346ed52f7d99bcc", - "reference": "10ef03144902d1955f935fff5346ed52f7d99bcc", + "url": "https://api.github.com/repos/zendframework/zend-stdlib/zipball/cd164b4a18b5d1aeb69be2c26db035b5ed6925ae", + "reference": "cd164b4a18b5d1aeb69be2c26db035b5ed6925ae", "shasum": "" }, "require": { "php": "^5.6 || ^7.0" }, "require-dev": { - "athletic/athletic": "~0.1", - "phpunit/phpunit": "~4.0", + "phpbench/phpbench": "^0.13", + "phpunit/phpunit": "^5.7.27 || ^6.5.8 || ^7.1.2", "zendframework/zend-coding-standard": "~1.0.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "3.1-dev", - "dev-develop": "3.2-dev" + "dev-master": "3.2.x-dev", + "dev-develop": "3.3.x-dev" } }, "autoload": { @@ -3683,12 +3753,13 @@ "license": [ "BSD-3-Clause" ], - "homepage": "https://github.com/zendframework/zend-stdlib", + "description": "SPL extensions, array utilities, error handlers, and more", "keywords": [ + "ZendFramework", "stdlib", - "zf2" - ], - "time": "2018-04-12T16:05:42+00:00" + "zf" + ], + "time": "2018-04-30T13:50:40+00:00" } ], "packages-dev": [ @@ -3698,12 +3769,12 @@ "source": { "type": "git", "url": "https://github.com/minkphp/Mink.git", - "reference": "04ab7af68536ac2c80fd6c08a6fd3620d3409891" + "reference": "d5ee350c40baff5f331a05ebdbe1927345c9ac8b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/minkphp/Mink/zipball/04ab7af68536ac2c80fd6c08a6fd3620d3409891", - "reference": "04ab7af68536ac2c80fd6c08a6fd3620d3409891", + "url": "https://api.github.com/repos/minkphp/Mink/zipball/d5ee350c40baff5f331a05ebdbe1927345c9ac8b", + "reference": "d5ee350c40baff5f331a05ebdbe1927345c9ac8b", "shasum": "" }, "require": { @@ -3717,7 +3788,8 @@ "behat/mink-browserkit-driver": "extremely fast headless driver for Symfony\\Kernel-based apps (Sf2, Silex)", "behat/mink-goutte-driver": "fast headless driver for any app without JS emulation", "behat/mink-selenium2-driver": "slow, but JS-enabled driver for any app (requires Selenium2)", - "behat/mink-zombie-driver": "fast and JS-enabled headless driver for any app (requires node.js)" + "behat/mink-zombie-driver": "fast and JS-enabled headless driver for any app (requires node.js)", + "dmore/chrome-mink-driver": "fast and JS-enabled driver for any app (requires chromium or google chrome)" }, "type": "library", "extra": { @@ -3748,31 +3820,31 @@ "testing", "web" ], - "time": "2018-01-07T17:25:05+00:00" + "time": "2018-06-24T20:08:51+00:00" }, { "name": "behat/mink-browserkit-driver", - "version": "v1.3.2", + "version": "1.3.3", "source": { "type": "git", "url": "https://github.com/minkphp/MinkBrowserKitDriver.git", - "reference": "10e67fb4a295efcd62ea0bf16025a85ea19534fb" + "reference": "1b9a7ce903cfdaaec5fb32bfdbb26118343662eb" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/minkphp/MinkBrowserKitDriver/zipball/10e67fb4a295efcd62ea0bf16025a85ea19534fb", - "reference": "10e67fb4a295efcd62ea0bf16025a85ea19534fb", + "url": "https://api.github.com/repos/minkphp/MinkBrowserKitDriver/zipball/1b9a7ce903cfdaaec5fb32bfdbb26118343662eb", + "reference": "1b9a7ce903cfdaaec5fb32bfdbb26118343662eb", "shasum": "" }, "require": { "behat/mink": "^1.7.1@dev", "php": ">=5.3.6", - "symfony/browser-kit": "~2.3|~3.0", - "symfony/dom-crawler": "~2.3|~3.0" + "symfony/browser-kit": "~2.3|~3.0|~4.0", + "symfony/dom-crawler": "~2.3|~3.0|~4.0" }, "require-dev": { - "silex/silex": "~1.2", - "symfony/phpunit-bridge": "~2.7|~3.0" + "mink/driver-testsuite": "dev-master", + "symfony/http-kernel": "~2.3|~3.0|~4.0" }, "type": "mink-driver", "extra": { @@ -3804,7 +3876,7 @@ "browser", "testing" ], - "time": "2016-03-05T08:59:47+00:00" + "time": "2018-05-02T09:25:31+00:00" }, { "name": "behat/mink-goutte-driver", @@ -3867,12 +3939,12 @@ "source": { "type": "git", "url": "https://github.com/minkphp/MinkSelenium2Driver.git", - "reference": "93474c65a2a7bf959200ab5f7a14cc450645c185" + "reference": "d8adafd0ba04fcd5a3865400e2bd0500c683f981" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/minkphp/MinkSelenium2Driver/zipball/93474c65a2a7bf959200ab5f7a14cc450645c185", - "reference": "93474c65a2a7bf959200ab5f7a14cc450645c185", + "url": "https://api.github.com/repos/minkphp/MinkSelenium2Driver/zipball/d8adafd0ba04fcd5a3865400e2bd0500c683f981", + "reference": "d8adafd0ba04fcd5a3865400e2bd0500c683f981", "shasum": "" }, "require": { @@ -3920,7 +3992,7 @@ "testing", "webdriver" ], - "time": "2018-01-07T19:17:08+00:00" + "time": "2018-06-25T17:38:20+00:00" }, { "name": "doctrine/instantiator", @@ -4009,16 +4081,16 @@ }, { "name": "fabpot/goutte", - "version": "v3.2.2", + "version": "v3.2.3", "source": { "type": "git", "url": "https://github.com/FriendsOfPHP/Goutte.git", - "reference": "395f61d7c2e15a813839769553a4de16fa3b3c96" + "reference": "3f0eaf0a40181359470651f1565b3e07e3dd31b8" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/FriendsOfPHP/Goutte/zipball/395f61d7c2e15a813839769553a4de16fa3b3c96", - "reference": "395f61d7c2e15a813839769553a4de16fa3b3c96", + "url": "https://api.github.com/repos/FriendsOfPHP/Goutte/zipball/3f0eaf0a40181359470651f1565b3e07e3dd31b8", + "reference": "3f0eaf0a40181359470651f1565b3e07e3dd31b8", "shasum": "" }, "require": { @@ -4060,7 +4132,7 @@ "keywords": [ "scraper" ], - "time": "2017-11-19T08:45:40+00:00" + "time": "2018-06-29T15:13:57+00:00" }, { "name": "instaclick/php-webdriver", @@ -4895,16 +4967,16 @@ }, { "name": "phpunit/phpunit", - "version": "6.5.8", + "version": "6.5.9", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/phpunit.git", - "reference": "4f21a3c6b97c42952fd5c2837bb354ec0199b97b" + "reference": "093ca5508174cd8ab8efe44fd1dde447adfdec8f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/4f21a3c6b97c42952fd5c2837bb354ec0199b97b", - "reference": "4f21a3c6b97c42952fd5c2837bb354ec0199b97b", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/093ca5508174cd8ab8efe44fd1dde447adfdec8f", + "reference": "093ca5508174cd8ab8efe44fd1dde447adfdec8f", "shasum": "" }, "require": { @@ -4975,20 +5047,20 @@ "testing", "xunit" ], - "time": "2018-04-10T11:38:34+00:00" + "time": "2018-07-03T06:40:40+00:00" }, { "name": "phpunit/phpunit-mock-objects", - "version": "5.0.6", + "version": "5.0.7", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/phpunit-mock-objects.git", - "reference": "33fd41a76e746b8fa96d00b49a23dadfa8334cdf" + "reference": "3eaf040f20154d27d6da59ca2c6e28ac8fd56dce" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit-mock-objects/zipball/33fd41a76e746b8fa96d00b49a23dadfa8334cdf", - "reference": "33fd41a76e746b8fa96d00b49a23dadfa8334cdf", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit-mock-objects/zipball/3eaf040f20154d27d6da59ca2c6e28ac8fd56dce", + "reference": "3eaf040f20154d27d6da59ca2c6e28ac8fd56dce", "shasum": "" }, "require": { @@ -5034,7 +5106,7 @@ "mock", "xunit" ], - "time": "2018-01-06T05:45:45+00:00" + "time": "2018-05-29T13:50:43+00:00" }, { "name": "sebastian/code-unit-reverse-lookup", @@ -5675,7 +5747,7 @@ }, { "name": "symfony/browser-kit", - "version": "v3.4.8", + "version": "v3.4.12", "source": { "type": "git", "url": "https://github.com/symfony/browser-kit.git", @@ -5732,16 +5804,16 @@ }, { "name": "symfony/css-selector", - "version": "v3.4.8", + "version": "v3.4.12", "source": { "type": "git", "url": "https://github.com/symfony/css-selector.git", - "reference": "519a80d7c1d95c6cc0b67f686d15fe27c6910de0" + "reference": "d2ce52290b648ae33b5301d09bc14ee378612914" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/css-selector/zipball/519a80d7c1d95c6cc0b67f686d15fe27c6910de0", - "reference": "519a80d7c1d95c6cc0b67f686d15fe27c6910de0", + "url": "https://api.github.com/repos/symfony/css-selector/zipball/d2ce52290b648ae33b5301d09bc14ee378612914", + "reference": "d2ce52290b648ae33b5301d09bc14ee378612914", "shasum": "" }, "require": { @@ -5781,24 +5853,25 @@ ], "description": "Symfony CssSelector Component", "homepage": "https://symfony.com", - "time": "2018-03-19T22:32:39+00:00" + "time": "2018-05-16T12:49:49+00:00" }, { "name": "symfony/dom-crawler", - "version": "v3.4.8", + "version": "v3.4.12", "source": { "type": "git", "url": "https://github.com/symfony/dom-crawler.git", - "reference": "1a4cffeb059226ff6bee9f48acb388faf674afff" + "reference": "201b210fafcdd193c1e45b2994bf7133fb6263e8" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/dom-crawler/zipball/1a4cffeb059226ff6bee9f48acb388faf674afff", - "reference": "1a4cffeb059226ff6bee9f48acb388faf674afff", + "url": "https://api.github.com/repos/symfony/dom-crawler/zipball/201b210fafcdd193c1e45b2994bf7133fb6263e8", + "reference": "201b210fafcdd193c1e45b2994bf7133fb6263e8", "shasum": "" }, "require": { "php": "^5.5.9|>=7.0.8", + "symfony/polyfill-ctype": "~1.8", "symfony/polyfill-mbstring": "~1.0" }, "require-dev": { @@ -5837,20 +5910,20 @@ ], "description": "Symfony DomCrawler Component", "homepage": "https://symfony.com", - "time": "2018-03-19T22:32:39+00:00" + "time": "2018-05-01T22:53:27+00:00" }, { "name": "symfony/phpunit-bridge", - "version": "v3.4.8", + "version": "v3.4.12", "source": { "type": "git", "url": "https://github.com/symfony/phpunit-bridge.git", - "reference": "48c669ec1a2b0425d4a82c7ad4bce2f5b947b95e" + "reference": "8a21eb6bedad38bf1f15d529c65eb9e17d0242fd" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/phpunit-bridge/zipball/48c669ec1a2b0425d4a82c7ad4bce2f5b947b95e", - "reference": "48c669ec1a2b0425d4a82c7ad4bce2f5b947b95e", + "url": "https://api.github.com/repos/symfony/phpunit-bridge/zipball/8a21eb6bedad38bf1f15d529c65eb9e17d0242fd", + "reference": "8a21eb6bedad38bf1f15d529c65eb9e17d0242fd", "shasum": "" }, "require": { @@ -5903,7 +5976,7 @@ ], "description": "Symfony PHPUnit Bridge", "homepage": "https://symfony.com", - "time": "2018-04-04T15:02:59+00:00" + "time": "2018-06-10T07:25:02+00:00" }, { "name": "theseer/tokenizer", diff -r e200cb7efeb3 -r c2387f117808 core/INSTALL.txt --- a/core/INSTALL.txt Thu Apr 26 11:26:54 2018 +0100 +++ b/core/INSTALL.txt Tue Jul 10 15:07:59 2018 +0100 @@ -266,7 +266,7 @@ this optional security measure, from a Unix/Linux command line you can use the following command: - chmod a-r CHANGELOG.txt + chmod a-r core/CHANGELOG.txt Note that the example only affects CHANGELOG.txt. To completely hide all documentation files from public view, repeat this command for each of the diff -r e200cb7efeb3 -r c2387f117808 core/MAINTAINERS.txt --- a/core/MAINTAINERS.txt Thu Apr 26 11:26:54 2018 +0100 +++ b/core/MAINTAINERS.txt Tue Jul 10 15:07:59 2018 +0100 @@ -33,7 +33,6 @@ Frontend - Lauri Eskola 'lauriii' https://www.drupal.org/u/lauriii - - Scott Reeves 'Cottser' https://www.drupal.org/u/cottser Release managers - Nathaniel Catchpole 'catch' https://www.drupal.org/u/catch @@ -49,7 +48,6 @@ information on their responsibilities, and to find out how to become a subsystem maintainer. Current subsystem maintainers for Drupal 8: - Actions - ? @@ -109,6 +107,7 @@ - Nathaniel Catchpole 'catch' https://www.drupal.org/u/catch CKEditor +- Henrik Danielsson 'TwoD' https://www.drupal.org/u/TwoD - Wim Leers 'Wim Leers' https://www.drupal.org/u/wim-leers - Marek 'mlewand' Lewandowski https://www.drupal.org/u/mlewand @@ -190,6 +189,7 @@ - Wim Leers 'Wim Leers' https://www.drupal.org/u/wim-leers Editor +- Henrik Danielsson 'TwoD' https://www.drupal.org/u/TwoD - Wim Leers 'Wim Leers' https://www.drupal.org/u/wim-leers Entity API @@ -354,7 +354,7 @@ - Jibran Ijaz 'jibran' https://www.drupal.org/u/jibran Stable -- Scott Reeves 'Cottser' https://www.drupal.org/u/cottser +- ? Stark - John Albin Wilkins 'JohnAlbin' https://www.drupal.org/u/johnalbin @@ -423,6 +423,7 @@ Workflows - Sam Becker 'Sam152' https://www.drupal.org/u/sam152 + Topic maintainers ----------------- @@ -445,8 +446,9 @@ Provisional membership: None at this time. + Security team ------------------ +------------- To report a security issue, see: https://www.drupal.org/security-team/report-issue @@ -458,6 +460,7 @@ - Michael Hess 'mlhess' https://www.drupal.org/u/mlhess + Initiative coordinators ----------------------- @@ -482,20 +485,25 @@ Media Initiative - Janez Urevc 'slashrsm' https://www.drupal.org/u/slashrsm +Out-of-the-Box Initiative +- Mark Conroy 'markconroy' https://www.drupal.org/u/markconroy +- Gareth Goodwin 'smaz' https://www.drupal.org/u/smaz +- Keith Jay 'kjay' https://www.drupal.org/u/kjay +- Elliot Ward 'eli-t' https://www.drupal.org/u/eli-t + PHPUnit Initiative - Daniel Wehner 'dawehner' https://www.drupal.org/u/dawehner - - (provisional) Michiel Nugter 'michielnugter' https://www.drupal.org/u/michielnugter - - (provisional) Len Swaneveld 'Lendude' https://www.drupal.org/u/lendude +- (provisional) Michiel Nugter 'michielnugter' https://www.drupal.org/u/michielnugter +- (provisional) Len Swaneveld 'Lendude' https://www.drupal.org/u/lendude Workflow Initiative - Dick Olsson 'dixon_' https://www.drupal.org/u/dixon_ - Provisional membership: None at this time. Core mentoring coordinators ---------------------- +--------------------------- The Drupal Core mentors inspire, enable, and encourage new core contributors. See https://www.drupal.org/core-mentoring for more information about mentoring. diff -r e200cb7efeb3 -r c2387f117808 core/assets/vendor/jquery-form/jquery.form.min.js.map --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/core/assets/vendor/jquery-form/jquery.form.min.js.map Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,1 @@ +{"version":3,"sources":["../src/jquery.form.js"],"names":["factory","define","amd","module","exports","root","jQuery","window","require","$","doAjaxSubmit","e","options","data","isDefaultPrevented","preventDefault","target","closest","ajaxSubmit","captureSubmittingElement","$el","is","t","length","form","clk","type","offsetX","clk_x","clk_y","offsetY","fn","offset","pageX","left","pageY","top","offsetLeft","offsetTop","setTimeout","log","debug","msg","Array","prototype","join","call","arguments","console","opera","postError","rCRLF","feature","fileapi","undefined","get","files","formdata","FormData","hasProp","prop","attr2","this","attr","apply","val","jquery","dataType","onSuccess","deepSerialize","extraData","i","part","serialized","param","traditional","split","len","result","replace","push","decodeURIComponent","fileUploadIframe","a","getDoc","frame","doc","contentWindow","document","err","contentDocument","doSubmit","checkState","state","io","readyState","toLowerCase","name","cb","SERVER_ABORT","timeoutHandle","clearTimeout","$form","et","setAttribute","id","method","test","s","url","skipEncodingOverride","encoding","enctype","timeout","timedOut","CLIENT_TIMEOUT_ABORT","extraInputs","n","hasOwnProperty","isPlainObject","ownerDocument","value","appendTo","iframeTarget","$io","$body","attachEvent","addEventListener","submit","createElement","removeAttr","remove","xhr","aborted","callbackProcessed","abort","deferred","reject","location","href","iframeSrc","detachEvent","removeEventListener","errMsg","status","isXml","XMLDocument","isXMLDoc","body","innerHTML","domCheckCount","docRoot","documentElement","responseText","responseXML","getResponseHeader","header","content-type","Number","getAttribute","statusText","dt","scr","textarea","ta","getElementsByTagName","pre","b","textContent","innerText","toXml","httpData","error","success","context","resolve","g","event","trigger","active","complete","el","sub","Deferred","elements","extend","ajaxSettings","Date","getTime","css","position","getAllResponseHeaders","setRequestHeader","execCommand","ignore","global","beforeSend","disabled","csrf_token","csrf_param","forceSync","parseXML","ActiveXObject","async","loadXML","DOMParser","parseFromString","nodeName","parseJSON","ct","xml","indexOf","dataFilter","globalEval","action","trim","match","veto","beforeSerialize","qx","formToArray","semantic","filtering","optionsData","isFunction","beforeSubmit","q","toUpperCase","callbacks","resetForm","clearForm","includeHidden","oldSuccess","textStatus","jqXHR","successArguments","replaceTarget","each","isArray","merge","max","oldError","oldComplete","hasFileInputs","filter","mp","multipart","fileAPI","jqxhr","shouldUseFrame","iframe","closeKeepAlive","append","serializedData","contentType","processData","cache","uploadProgress","upload","percent","loaded","total","lengthComputable","Math","ceil","o","formData","ajax","removeData","k","ajaxForm","delegation","on","selector","c","isReady","off","ajaxFormUnbind","els2","formId","els","makeArray","navigator","userAgent","concat","map","j","v","jmax","fieldValue","constructor","required","$input","input","formSerialize","fieldSerialize","successful","tag","tagName","checked","selectedIndex","index","ops","one","op","selected","attributes","text","clearFields","clearInputs","re","replaceWith","clone","defaultChecked","defaultValue","select","parents","multiple","defaultSelected","find","forEl","list","unshift","reset","nodeType","enable","$sel","parent"],"mappings":";;;;;;;;;;;;;;;;;;;;;CAwBC,SAAUA,GACY,mBAAXC,QAAyBA,OAAOC,IAE1CD,QAAQ,UAAWD,GACS,iBAAXG,QAAuBA,OAAOC,QAE/CD,OAAOC,QAAU,SAAUC,EAAMC,GAYhC,YAXsB,IAAXA,IAITA,EADqB,oBAAXC,OACDC,QAAQ,UAGRA,QAAQ,UAAUH,IAG7BL,EAAQM,GACDA,GAIRN,EAAQM,SAGR,SAAUG,GAEX,aAw8BA,SAASC,EAAaC,GAErB,IAAIC,EAAUD,EAAEE,KAEXF,EAAEG,uBACNH,EAAEI,iBACFN,EAAEE,EAAEK,QAAQC,QAAQ,QAAQC,WAAWN,IAIzC,SAASO,EAAyBR,GAEjC,IAAIK,EAASL,EAAEK,OACXI,EAAMX,EAAEO,GAEZ,IAAKI,EAAIC,GAAG,8BAA+B,CAE1C,IAAIC,EAAIF,EAAIH,QAAQ,iBAEpB,GAAiB,IAAbK,EAAEC,OACL,OAEDP,EAASM,EAAE,GAGZ,IAAIE,EAAOR,EAAOQ,KAIlB,GAFAA,EAAKC,IAAMT,EAES,UAAhBA,EAAOU,KACV,QAAyB,IAAdf,EAAEgB,QACZH,EAAKI,MAAQjB,EAAEgB,QACfH,EAAKK,MAAQlB,EAAEmB,aAET,GAA2B,mBAAhBrB,EAAEsB,GAAGC,OAAuB,CAC7C,IAAIA,EAASZ,EAAIY,SAEjBR,EAAKI,MAAQjB,EAAEsB,MAAQD,EAAOE,KAC9BV,EAAKK,MAAQlB,EAAEwB,MAAQH,EAAOI,SAG9BZ,EAAKI,MAAQjB,EAAEsB,MAAQjB,EAAOqB,WAC9Bb,EAAKK,MAAQlB,EAAEwB,MAAQnB,EAAOsB,UAIhCC,WAAW,WACVf,EAAKC,IAAMD,EAAKI,MAAQJ,EAAKK,MAAQ,MACnC,KAicJ,SAASW,IACR,GAAK/B,EAAEsB,GAAGb,WAAWuB,MAArB,CAIA,IAAIC,EAAM,iBAAmBC,MAAMC,UAAUC,KAAKC,KAAKC,UAAW,IAE9DxC,OAAOyC,SAAWzC,OAAOyC,QAAQR,IACpCjC,OAAOyC,QAAQR,IAAIE,GAETnC,OAAO0C,OAAS1C,OAAO0C,MAAMC,WACvC3C,OAAO0C,MAAMC,UAAUR,IA75CzB,IAAIS,EAAQ,SAKRC,KAEJA,EAAQC,aAAoDC,IAA1C7C,EAAE,uBAAuB8C,IAAI,GAAGC,MAClDJ,EAAQK,cAAuC,IAApBlD,OAAOmD,SAElC,IAAIC,IAAYlD,EAAEsB,GAAG6B,KAMrBnD,EAAEsB,GAAG8B,MAAQ,WACZ,IAAKF,EACJ,OAAOG,KAAKC,KAAKC,MAAMF,KAAMf,WAG9B,IAAIkB,EAAMH,KAAKF,KAAKI,MAAMF,KAAMf,WAEhC,OAAKkB,GAAOA,EAAIC,QAA0B,iBAARD,EAC1BA,EAGDH,KAAKC,KAAKC,MAAMF,KAAMf,YAY9BtC,EAAEsB,GAAGb,WAAa,SAASN,EAASC,EAAMsD,EAAUC,GA+NnD,SAASC,EAAcC,GACtB,IAGIC,EAAGC,EAHHC,EAAahE,EAAEiE,MAAMJ,EAAW1D,EAAQ+D,aAAaC,MAAM,KAC3DC,EAAMJ,EAAWlD,OACjBuD,KAGJ,IAAKP,EAAI,EAAGA,EAAIM,EAAKN,IAEpBE,EAAWF,GAAKE,EAAWF,GAAGQ,QAAQ,MAAO,KAC7CP,EAAOC,EAAWF,GAAGK,MAAM,KAE3BE,EAAOE,MAAMC,mBAAmBT,EAAK,IAAKS,mBAAmBT,EAAK,MAGnE,OAAOM,EA0ER,SAASI,EAAiBC,GAyHzB,SAASC,EAAOC,GAQf,IAAIC,EAAM,KAGV,IACKD,EAAME,gBACTD,EAAMD,EAAME,cAAcC,UAE1B,MAAOC,GAERjD,EAAI,6CAA+CiD,GAGpD,GAAIH,EACH,OAAOA,EAGR,IACCA,EAAMD,EAAMK,gBAAkBL,EAAMK,gBAAkBL,EAAMG,SAC3D,MAAOC,GAERjD,EAAI,sCAAwCiD,GAC5CH,EAAMD,EAAMG,SAGb,OAAOF,EAaR,SAASK,IAgCR,SAASC,IACR,IACC,IAAIC,EAAQT,EAAOU,GAAIC,WAEvBvD,EAAI,WAAaqD,GACbA,GAAiC,kBAAxBA,EAAMG,eAClBzD,WAAWqD,EAAY,IAGvB,MAAOjF,GACR6B,EAAI,iBAAkB7B,EAAG,KAAMA,EAAEsF,KAAM,KACvCC,EAAGC,GACCC,GACHC,aAAaD,GAEdA,OAAgB9C,GA7ClB,IAAIhC,EAAIgF,EAAMzC,MAAM,UACnBsB,EAAImB,EAAMzC,MAAM,UAEhB0C,EAAKD,EAAMvC,KAAK,YAAcuC,EAAMvC,KAAK,aADpC,sBAINvC,EAAKgF,aAAa,SAAUC,GACvBC,IAAU,QAAQC,KAAKD,IAC3BlF,EAAKgF,aAAa,SAAU,QAEzBrB,IAAMyB,EAAEC,KACXrF,EAAKgF,aAAa,SAAUI,EAAEC,KAI1BD,EAAEE,sBAA0BJ,IAAU,QAAQC,KAAKD,IACvDJ,EAAMvC,MACLgD,SAAW,sBACXC,QAAW,wBAKTJ,EAAEK,UACLb,EAAgB7D,WAAW,WAC1B2E,GAAW,EAAMhB,EAAGiB,IAClBP,EAAEK,UAwBN,IAAIG,KAEJ,IACC,GAAIR,EAAEtC,UACL,IAAK,IAAI+C,KAAKT,EAAEtC,UACXsC,EAAEtC,UAAUgD,eAAeD,KAE1B5G,EAAE8G,cAAcX,EAAEtC,UAAU+C,KAAOT,EAAEtC,UAAU+C,GAAGC,eAAe,SAAWV,EAAEtC,UAAU+C,GAAGC,eAAe,SAC7GF,EAAYpC,KACZvE,EAAE,8BAAgCmG,EAAEtC,UAAU+C,GAAGpB,KAAO,KAAMuB,GAAevD,IAAI2C,EAAEtC,UAAU+C,GAAGI,OAC9FC,SAASlG,GAAM,IAEjB4F,EAAYpC,KACZvE,EAAE,8BAAgC4G,EAAI,KAAMG,GAAevD,IAAI2C,EAAEtC,UAAU+C,IACzEK,SAASlG,GAAM,KAMhBoF,EAAEe,cAENC,EAAIF,SAASG,GAGV/B,EAAGgC,YACNhC,EAAGgC,YAAY,SAAU5B,GAEzBJ,EAAGiC,iBAAiB,OAAQ7B,GAAI,GAGjC3D,WAAWqD,EAAY,IAEvB,IACCpE,EAAKwG,SAEJ,MAAOvC,GAEOD,SAASyC,cAAc,QAAQD,OAErChE,MAAMxC,IAGf,QAEDA,EAAKgF,aAAa,SAAUrB,GAC5B3D,EAAKgF,aAAa,UAAWD,GACzBjF,EACHE,EAAKgF,aAAa,SAAUlF,GAE5BgF,EAAM4B,WAAW,UAElBzH,EAAE2G,GAAae,UAYjB,SAASjC,EAAGvF,GACX,IAAIyH,EAAIC,UAAWC,EAAnB,CASA,IALAhD,EAAMF,EAAOU,MAEZtD,EAAI,mCACJ7B,EAAIwF,GAEDxF,IAAMwG,GAAwBiB,EAIjC,OAHAA,EAAIG,MAAM,gBACVC,EAASC,OAAOL,EAAK,WAIf,GAAIzH,IAAMwF,GAAgBiC,EAIhC,OAHAA,EAAIG,MAAM,qBACVC,EAASC,OAAOL,EAAK,QAAS,gBAK/B,GAAK9C,GAAOA,EAAIoD,SAASC,OAAS/B,EAAEgC,WAE9B1B,EAFN,CAOIpB,EAAG+C,YACN/C,EAAG+C,YAAY,SAAU3C,GAEzBJ,EAAGgD,oBAAoB,OAAQ5C,GAAI,GAGpC,IAAwB6C,EAApBC,EAAS,UAEb,IACC,GAAI9B,EACH,KAAM,UAGP,IAAI+B,EAAuB,QAAfrC,EAAEzC,UAAsBmB,EAAI4D,aAAezI,EAAE0I,SAAS7D,GAIlE,GAFA9C,EAAI,SAAWyG,IAEVA,GAAS1I,OAAO0C,QAAuB,OAAbqC,EAAI8D,OAAkB9D,EAAI8D,KAAKC,cACvDC,EAML,OAHA9G,EAAI,oDACJD,WAAW2D,EAAI,KAUjB,IAAIqD,EAAUjE,EAAI8D,KAAO9D,EAAI8D,KAAO9D,EAAIkE,gBAExCpB,EAAIqB,aAAeF,EAAUA,EAAQF,UAAY,KACjDjB,EAAIsB,YAAcpE,EAAI4D,YAAc5D,EAAI4D,YAAc5D,EAClD2D,IACHrC,EAAEzC,SAAW,OAEdiE,EAAIuB,kBAAoB,SAASC,GAGhC,OAFeC,eAAgBjD,EAAEzC,UAElByF,EAAO5D,gBAGnBuD,IACHnB,EAAIY,OAASc,OAAOP,EAAQQ,aAAa,YAAc3B,EAAIY,OAC3DZ,EAAI4B,WAAaT,EAAQQ,aAAa,eAAiB3B,EAAI4B,YAG5D,IAAIC,GAAMrD,EAAEzC,UAAY,IAAI6B,cACxBkE,EAAM,qBAAqBvD,KAAKsD,GAEpC,GAAIC,GAAOtD,EAAEuD,SAAU,CAEtB,IAAIC,EAAK9E,EAAI+E,qBAAqB,YAAY,GAE9C,GAAID,EACHhC,EAAIqB,aAAeW,EAAG3C,MAEtBW,EAAIY,OAASc,OAAOM,EAAGL,aAAa,YAAc3B,EAAIY,OACtDZ,EAAI4B,WAAaI,EAAGL,aAAa,eAAiB3B,EAAI4B,gBAEhD,GAAIE,EAAK,CAEf,IAAII,EAAMhF,EAAI+E,qBAAqB,OAAO,GACtCE,EAAIjF,EAAI+E,qBAAqB,QAAQ,GAErCC,EACHlC,EAAIqB,aAAea,EAAIE,YAAcF,EAAIE,YAAcF,EAAIG,UACjDF,IACVnC,EAAIqB,aAAec,EAAEC,YAAcD,EAAEC,YAAcD,EAAEE,gBAItC,QAAPR,IAAiB7B,EAAIsB,aAAetB,EAAIqB,eAClDrB,EAAIsB,YAAcgB,EAAMtC,EAAIqB,eAG7B,IACC5I,EAAO8J,EAASvC,EAAK6B,EAAIrD,GAExB,MAAOnB,GACRuD,EAAS,cACTZ,EAAIwC,MAAQ7B,EAAUtD,GAAOuD,GAG7B,MAAOvD,GACRjD,EAAI,iBAAkBiD,GACtBuD,EAAS,QACTZ,EAAIwC,MAAQ7B,EAAUtD,GAAOuD,EAG1BZ,EAAIC,UACP7F,EAAI,kBACJwG,EAAS,MAGNZ,EAAIY,SACPA,EAAWZ,EAAIY,QAAU,KAAOZ,EAAIY,OAAS,KAAuB,MAAfZ,EAAIY,OAAkB,UAAY,SAIzE,YAAXA,GACCpC,EAAEiE,SACLjE,EAAEiE,QAAQ/H,KAAK8D,EAAEkE,QAASjK,EAAM,UAAWuH,GAG5CI,EAASuC,QAAQ3C,EAAIqB,aAAc,UAAWrB,GAE1C4C,GACHvK,EAAEwK,MAAMC,QAAQ,eAAgB9C,EAAKxB,KAG5BoC,SACY,IAAXD,IACVA,EAASX,EAAI4B,YAEVpD,EAAEgE,OACLhE,EAAEgE,MAAM9H,KAAK8D,EAAEkE,QAAS1C,EAAKY,EAAQD,GAEtCP,EAASC,OAAOL,EAAK,QAASW,GAC1BiC,GACHvK,EAAEwK,MAAMC,QAAQ,aAAc9C,EAAKxB,EAAGmC,KAIpCiC,GACHvK,EAAEwK,MAAMC,QAAQ,gBAAiB9C,EAAKxB,IAGnCoE,MAAQvK,EAAE0K,QACb1K,EAAEwK,MAAMC,QAAQ,YAGbtE,EAAEwE,UACLxE,EAAEwE,SAAStI,KAAK8D,EAAEkE,QAAS1C,EAAKY,GAGjCV,GAAoB,EAChB1B,EAAEK,SACLZ,aAAaD,GAId7D,WAAW,WACLqE,EAAEe,aAGNC,EAAI7D,KAAK,MAAO6C,EAAEgC,WAFlBhB,EAAIO,SAILC,EAAIsB,YAAc,MAChB,OA/cJ,IAAqB2B,EAAI9G,EAAGqC,EAAGoE,EAAGvE,EAAImB,EAAK9B,EAAIsC,EAAKkD,EAAKjE,EAAGH,EAAUd,EAAlE5E,EAAO8E,EAAM,GACbkC,EAAW/H,EAAE8K,WAOjB,GAJA/C,EAASD,MAAQ,SAASS,GACzBZ,EAAIG,MAAMS,IAGP7D,EAEH,IAAKZ,EAAI,EAAGA,EAAIiH,EAASjK,OAAQgD,IAChC8G,EAAK5K,EAAE+K,EAASjH,IACZZ,EACH0H,EAAGzH,KAAK,YAAY,GAEpByH,EAAGnD,WAAW,aAKjBtB,EAAInG,EAAEgL,QAAO,KAAUhL,EAAEiL,aAAc9K,IACrCkK,QAAUlE,EAAEkE,SAAWlE,EACzBH,EAAK,YAAa,IAAIkF,MAAOC,UAC7B,IAAIpE,EAAgBhG,EAAKgG,cACrBK,EAAQvB,EAAMrF,QAAQ,QAgE1B,GA9DI2F,EAAEe,cAELN,GADAO,EAAMnH,EAAEmG,EAAEe,aAAcH,IAChB3D,MAAM,SAIb4C,EAAKY,EAFLO,EAAI/D,MAAM,OAAQ4C,IAMnBmB,EAAMnH,EAAE,iBAAmBgG,EAAK,UAAYG,EAAEgC,UAAY,OAAQpB,IAC9DqE,KAAKC,SAAU,WAAY1J,IAAK,UAAWF,KAAM,YAEtD4D,EAAK8B,EAAI,GAGTQ,GACCC,QAAwB,EACxBoB,aAAwB,KACxBC,YAAwB,KACxBV,OAAwB,EACxBgB,WAAwB,MACxB+B,sBAAwB,aACxBpC,kBAAwB,aACxBqC,iBAAwB,aACxBzD,MAAwB,SAASS,GAChC,IAAIrI,EAAgB,YAAXqI,EAAuB,UAAY,UAE5CxG,EAAI,sBAAwB7B,GAC5BmD,KAAKuE,QAAU,EAEf,IACKvC,EAAGP,cAAcC,SAASyG,aAC7BnG,EAAGP,cAAcC,SAASyG,YAAY,QAEtC,MAAOC,IAETtE,EAAI7D,KAAK,MAAO6C,EAAEgC,WAClBR,EAAIwC,MAAQjK,EACRiG,EAAEgE,OACLhE,EAAEgE,MAAM9H,KAAK8D,EAAEkE,QAAS1C,EAAKzH,EAAGqI,GAG7BgC,GACHvK,EAAEwK,MAAMC,QAAQ,aAAc9C,EAAKxB,EAAGjG,IAGnCiG,EAAEwE,UACLxE,EAAEwE,SAAStI,KAAK8D,EAAEkE,QAAS1C,EAAKzH,MAKnCqK,EAAIpE,EAAEuF,SAEkB,GAAf1L,EAAE0K,UACV1K,EAAEwK,MAAMC,QAAQ,aAEbF,GACHvK,EAAEwK,MAAMC,QAAQ,YAAa9C,EAAKxB,IAG/BA,EAAEwF,aAAuD,IAAzCxF,EAAEwF,WAAWtJ,KAAK8D,EAAEkE,QAAS1C,EAAKxB,GAMrD,OALIA,EAAEuF,QACL1L,EAAE0K,SAEH3C,EAASC,SAEFD,EAGR,GAAIJ,EAAIC,QAGP,OAFAG,EAASC,SAEFD,GAIR8C,EAAM9J,EAAKC,OAEV4F,EAAIiE,EAAIrF,QACEqF,EAAIe,WACbzF,EAAEtC,UAAYsC,EAAEtC,cAChBsC,EAAEtC,UAAU+C,GAAKiE,EAAI7D,MACJ,UAAb6D,EAAI5J,OACPkF,EAAEtC,UAAU+C,EAAI,MAAQ7F,EAAKI,MAC7BgF,EAAEtC,UAAU+C,EAAI,MAAQ7F,EAAKK,QAKhC,IAAIsF,EAAuB,EACvBhB,EAAe,EAsCfmG,EAAa7L,EAAE,yBAAyBsD,KAAK,WAC7CwI,EAAa9L,EAAE,yBAAyBsD,KAAK,WAE7CwI,GAAcD,IACjB1F,EAAEtC,UAAYsC,EAAEtC,cAChBsC,EAAEtC,UAAUiI,GAAcD,GAgHvB1F,EAAE4F,UACL7G,IAEApD,WAAWoD,EAAU,IAGtB,IAAI9E,EAAMyE,EAAyBgD,EAApBgB,EAAgB,GA2L3BoB,EAAQjK,EAAEgM,UAAY,SAAS7F,EAAGtB,GAUrC,OATI/E,OAAOmM,gBACVpH,EAAM,IAAIoH,cAAc,qBACpBC,MAAQ,QACZrH,EAAIsH,QAAQhG,IAGZtB,GAAM,IAAKuH,WAAaC,gBAAgBlG,EAAG,YAGpCtB,GAAOA,EAAIkE,iBAAoD,gBAAjClE,EAAIkE,gBAAgBuD,SAA8BzH,EAAM,MAE3F0H,EAAYvM,EAAEuM,WAAa,SAASpG,GAEvC,OAAOrG,OAAa,KAAE,IAAMqG,EAAI,MAG7B+D,EAAW,SAASvC,EAAK1G,EAAMkF,GAElC,IAAIqG,EAAK7E,EAAIuB,kBAAkB,iBAAmB,GACjDuD,GAAiB,QAATxL,IAAmBA,IAASuL,EAAGE,QAAQ,QAAU,EACzDtM,EAAOqM,EAAM9E,EAAIsB,YAActB,EAAIqB,aAkBpC,OAhBIyD,GAAyC,gBAAlCrM,EAAK2I,gBAAgBuD,UAC3BtM,EAAEmK,OACLnK,EAAEmK,MAAM,eAGNhE,GAAKA,EAAEwG,aACVvM,EAAO+F,EAAEwG,WAAWvM,EAAMa,IAEP,iBAATb,KACI,SAATa,IAAoBA,IAASuL,EAAGE,QAAQ,SAAW,EACvDtM,EAAOmM,EAAUnM,IACG,WAATa,IAAsBA,IAASuL,EAAGE,QAAQ,eAAiB,GACtE1M,EAAE4M,WAAWxM,IAIRA,GAGR,OAAO2H,EAlzBR,IAAK1E,KAAKvC,OAGT,OAFAiB,EAAI,6DAEGsB,KAIR,IAAI4C,EAAQ4G,EAAQzG,EAAKP,EAAQxC,KAEV,mBAAZlD,EACVA,GAAWiK,QAASjK,GAES,iBAAZA,IAAqC,IAAZA,GAAqBmC,UAAUxB,OAAS,GAClFX,GACCiG,IAAajG,EACbC,KAAaA,EACbsD,SAAaA,GAGW,mBAAdC,IACVxD,EAAQiK,QAAUzG,SAGU,IAAZxD,IACjBA,MAGD8F,EAAS9F,EAAQ8F,QAAU9F,EAAQc,MAAQoC,KAAKD,MAAM,WAItDgD,GADAA,EAAyB,iBAFzByG,EAAS1M,EAAQiG,KAAO/C,KAAKD,MAAM,WAEEpD,EAAE8M,KAAKD,GAAU,KACzC/M,OAAOmI,SAASC,MAAQ,MAGpC9B,GAAOA,EAAI2G,MAAM,iBAAmB,IAGrC5M,EAAUH,EAAEgL,QAAO,GAClB5E,IAAYA,EACZgE,QAAYpK,EAAEiL,aAAab,QAC3BnJ,KAAYgF,GAAUjG,EAAEiL,aAAahK,KACrCkH,UAAY,UAAUjC,KAAKpG,OAAOmI,SAASC,MAAQ,IAAM,mBAAqB,eAC5E/H,GAIH,IAAI6M,KAIJ,GAFA3J,KAAKoH,QAAQ,sBAAuBpH,KAAMlD,EAAS6M,IAE/CA,EAAKA,KAGR,OAFAjL,EAAI,4DAEGsB,KAIR,GAAIlD,EAAQ8M,kBAA8D,IAA3C9M,EAAQ8M,gBAAgB5J,KAAMlD,GAG5D,OAFA4B,EAAI,2DAEGsB,KAGR,IAAIa,EAAc/D,EAAQ+D,iBAEC,IAAhBA,IACVA,EAAclE,EAAEiL,aAAa/G,aAG9B,IACIgJ,EADAnC,KACIrG,EAAIrB,KAAK8J,YAAYhN,EAAQiN,SAAUrC,EAAU5K,EAAQkN,WAEjE,GAAIlN,EAAQC,KAAM,CACjB,IAAIkN,EAActN,EAAEuN,WAAWpN,EAAQC,MAAQD,EAAQC,KAAKsE,GAAKvE,EAAQC,KAEzED,EAAQ0D,UAAYyJ,EACpBJ,EAAKlN,EAAEiE,MAAMqJ,EAAapJ,GAI3B,GAAI/D,EAAQqN,eAA2D,IAA3CrN,EAAQqN,aAAa9I,EAAGrB,KAAMlD,GAGzD,OAFA4B,EAAI,wDAEGsB,KAKR,GADAA,KAAKoH,QAAQ,wBAAyB/F,EAAGrB,KAAMlD,EAAS6M,IACpDA,EAAKA,KAGR,OAFAjL,EAAI,8DAEGsB,KAGR,IAAIoK,EAAIzN,EAAEiE,MAAMS,EAAGR,GAEfgJ,IACHO,EAAKA,EAAKA,EAAI,IAAMP,EAAMA,GAGQ,QAA/B/M,EAAQc,KAAKyM,eAChBvN,EAAQiG,MAAQjG,EAAQiG,IAAIsG,QAAQ,MAAQ,EAAI,IAAM,KAAOe,EAC7DtN,EAAQC,KAAO,MAEfD,EAAQC,KAAOqN,EAGhB,IAAIE,KAeJ,GAbIxN,EAAQyN,WACXD,EAAUpJ,KAAK,WACdsB,EAAM+H,cAIJzN,EAAQ0N,WACXF,EAAUpJ,KAAK,WACdsB,EAAMgI,UAAU1N,EAAQ2N,kBAKrB3N,EAAQuD,UAAYvD,EAAQI,OAAQ,CACxC,IAAIwN,EAAa5N,EAAQiK,SAAW,aAEpCuD,EAAUpJ,KAAK,SAASnE,EAAM4N,EAAYC,GACzC,IAAIC,EAAmB5L,UACtBhB,EAAKnB,EAAQgO,cAAgB,cAAgB,OAE9CnO,EAAEG,EAAQI,QAAQe,GAAIlB,GAAMgO,KAAK,WAChCL,EAAWxK,MAAMF,KAAM6K,YAIf/N,EAAQiK,UACdpK,EAAEqO,QAAQlO,EAAQiK,SACrBpK,EAAEsO,MAAMX,EAAWxN,EAAQiK,SAE3BuD,EAAUpJ,KAAKpE,EAAQiK,UAYzB,GARAjK,EAAQiK,QAAU,SAAShK,EAAMmI,EAAQZ,GAGxC,IAAK,IAFD0C,EAAUlK,EAAQkK,SAAWhH,KAExBS,EAAI,EAAGyK,EAAMZ,EAAU7M,OAAQgD,EAAIyK,EAAKzK,IAChD6J,EAAU7J,GAAGP,MAAM8G,GAAUjK,EAAMmI,EAAQZ,GAAO9B,EAAOA,KAIvD1F,EAAQgK,MAAO,CAClB,IAAIqE,EAAWrO,EAAQgK,MAEvBhK,EAAQgK,MAAQ,SAASxC,EAAKY,EAAQ4B,GACrC,IAAIE,EAAUlK,EAAQkK,SAAWhH,KAEjCmL,EAASjL,MAAM8G,GAAU1C,EAAKY,EAAQ4B,EAAOtE,KAI/C,GAAI1F,EAAQwK,SAAU,CACrB,IAAI8D,EAActO,EAAQwK,SAE1BxK,EAAQwK,SAAW,SAAShD,EAAKY,GAChC,IAAI8B,EAAUlK,EAAQkK,SAAWhH,KAEjCoL,EAAYlL,MAAM8G,GAAU1C,EAAKY,EAAQ1C,KAQ3C,IAGI6I,EAHa1O,EAAE,2BAA4BqD,MAAMsL,OAAO,WAC3D,MAAyB,KAAlB3O,EAAEqD,MAAMG,QAEe1C,OAAS,EACpC8N,EAAK,sBACLC,EAAahJ,EAAMvC,KAAK,aAAesL,GAAM/I,EAAMvC,KAAK,cAAgBsL,EACxEE,EAAUnM,EAAQC,SAAWD,EAAQK,SAEzCjB,EAAI,YAAc+M,GAElB,IACIC,EADAC,GAAkBN,GAAiBG,KAAeC,GAK/B,IAAnB3O,EAAQ8O,SAAqB9O,EAAQ8O,QAAUD,GAG9C7O,EAAQ+O,eACXlP,EAAE8C,IAAI3C,EAAQ+O,eAAgB,WAC7BH,EAAQtK,EAAiBC,KAI1BqK,EAAQtK,EAAiBC,GAI1BqK,GADWL,GAAiBG,IAAcC,EAsC3C,SAAuBpK,GAGtB,IAAK,IAFD1B,EAAW,IAAIC,SAEVa,EAAI,EAAGA,EAAIY,EAAE5D,OAAQgD,IAC7Bd,EAASmM,OAAOzK,EAAEZ,GAAG0B,KAAMd,EAAEZ,GAAGkD,OAGjC,GAAI7G,EAAQ0D,UAAW,CACtB,IAAIuL,EAAiBxL,EAAczD,EAAQ0D,WAE3C,IAAKC,EAAI,EAAGA,EAAIsL,EAAetO,OAAQgD,IAClCsL,EAAetL,IAClBd,EAASmM,OAAOC,EAAetL,GAAG,GAAIsL,EAAetL,GAAG,IAK3D3D,EAAQC,KAAO,KAEf,IAAI+F,EAAInG,EAAEgL,QAAO,KAAUhL,EAAEiL,aAAc9K,GAC1CkP,aAAc,EACdC,aAAc,EACdC,OAAc,EACdtO,KAAcgF,GAAU,SAGrB9F,EAAQqP,iBAEXrJ,EAAEwB,IAAM,WACP,IAAIA,EAAM3H,EAAEiL,aAAatD,MAgBzB,OAdIA,EAAI8H,QACP9H,EAAI8H,OAAOnI,iBAAiB,WAAY,SAASkD,GAChD,IAAIkF,EAAU,EACVrE,EAAWb,EAAMmF,QAAUnF,EAAMa,SACjCuE,EAAQpF,EAAMoF,MAEdpF,EAAMqF,mBACTH,EAAUI,KAAKC,KAAK1E,EAAWuE,EAAQ,MAGxCzP,EAAQqP,eAAehF,EAAOa,EAAUuE,EAAOF,KAC7C,GAGG/H,IAITxB,EAAE/F,KAAO,KAET,IAAIuL,EAAaxF,EAAEwF,WAenB,OAbAxF,EAAEwF,WAAa,SAAShE,EAAKqI,GAExB7P,EAAQ8P,SACXD,EAAE5P,KAAOD,EAAQ8P,SAEjBD,EAAE5P,KAAO4C,EAGN2I,GACHA,EAAWtJ,KAAKgB,KAAMsE,EAAKqI,IAItBhQ,EAAEkQ,KAAK/J,IAvGQzB,GAGd1E,EAAEkQ,KAAK/P,GAGhB0F,EAAMsK,WAAW,SAAS/P,KAAK,QAAS2O,GAGxC,IAAK,IAAIqB,EAAI,EAAGA,EAAIrF,EAASjK,OAAQsP,IACpCrF,EAASqF,GAAK,KAMf,OAFA/M,KAAKoH,QAAQ,sBAAuBpH,KAAMlD,IAEnCkD,MA2mBRrD,EAAEsB,GAAG+O,SAAW,SAASlQ,EAASC,EAAMsD,EAAUC,GAiBjD,IAhBuB,iBAAZxD,IAAqC,IAAZA,GAAqBmC,UAAUxB,OAAS,KAC3EX,GACCiG,IAAajG,EACbC,KAAaA,EACbsD,SAAaA,GAGW,mBAAdC,IACVxD,EAAQiK,QAAUzG,IAIpBxD,EAAUA,MACVA,EAAQmQ,WAAanQ,EAAQmQ,YAActQ,EAAEuN,WAAWvN,EAAEsB,GAAGiP,KAGxDpQ,EAAQmQ,YAA8B,IAAhBjN,KAAKvC,OAAc,CAC7C,IAAIkP,GAAK7J,EAAG9C,KAAKmN,SAAUC,EAAGpN,KAAKgH,SAEnC,OAAKrK,EAAE0Q,SAAWV,EAAE7J,GACnBpE,EAAI,mCACJ/B,EAAE,WACDA,EAAEgQ,EAAE7J,EAAG6J,EAAES,GAAGJ,SAASlQ,KAGfkD,OAIRtB,EAAI,gDAAkD/B,EAAE0Q,QAAU,GAAK,qBAEhErN,MAGR,OAAIlD,EAAQmQ,YACXtQ,EAAE+E,UACA4L,IAAI,qBAAsBtN,KAAKmN,SAAUvQ,GACzC0Q,IAAI,oBAAqBtN,KAAKmN,SAAU9P,GACxC6P,GAAG,qBAAsBlN,KAAKmN,SAAUrQ,EAASF,GACjDsQ,GAAG,oBAAqBlN,KAAKmN,SAAUrQ,EAASO,GAE3C2C,MAGDA,KAAKuN,iBACVL,GAAG,qBAAsBpQ,EAASF,GAClCsQ,GAAG,oBAAqBpQ,EAASO,IAyDpCV,EAAEsB,GAAGsP,eAAiB,WACrB,OAAOvN,KAAKsN,IAAI,yCAcjB3Q,EAAEsB,GAAG6L,YAAc,SAASC,EAAUrC,EAAUsC,GAC/C,IAAI3I,KAEJ,GAAoB,IAAhBrB,KAAKvC,OACR,OAAO4D,EAGR,IAGImM,EAHA9P,EAAOsC,KAAK,GACZyN,EAASzN,KAAKC,KAAK,MACnByN,EAAO3D,QAAqC,IAAlBrM,EAAKgK,SAA4BhK,EAAK6I,qBAAqB,KAAO7I,EAAKgK,SAgBrG,GAbIgG,IACHA,EAAM/Q,EAAEgR,UAAUD,IAKfD,IAAW1D,GAAY,mBAAmBlH,KAAK+K,UAAUC,cAC5DL,EAAO7Q,EAAE,gBAAkB8Q,EAAS,MAAMhO,OACjChC,SACRiQ,GAAOA,OAAWI,OAAON,KAItBE,IAAQA,EAAIjQ,OAChB,OAAO4D,EAGJ1E,EAAEuN,WAAWF,KAChB0D,EAAM/Q,EAAEoR,IAAIL,EAAK1D,IAGlB,IAAIvJ,EAAGuN,EAAGzK,EAAG0K,EAAG1G,EAAI2D,EAAKgD,EAEzB,IAAKzN,EAAI,EAAGyK,EAAMwC,EAAIjQ,OAAQgD,EAAIyK,EAAKzK,IAGtC,GAFA8G,EAAKmG,EAAIjN,IACT8C,EAAIgE,EAAGpF,QACGoF,EAAGgB,SAIb,GAAIwB,GAAYrM,EAAKC,KAAmB,UAAZ4J,EAAG3J,KAE1BF,EAAKC,MAAQ4J,IAChBlG,EAAEH,MAAMiB,KAAMoB,EAAGI,MAAOhH,EAAE4K,GAAIpH,MAAOvC,KAAM2J,EAAG3J,OAC9CyD,EAAEH,MAAMiB,KAAMoB,EAAI,KAAMI,MAAOjG,EAAKI,QAASqE,KAAMoB,EAAI,KAAMI,MAAOjG,EAAKK,cAM3E,IADAkQ,EAAItR,EAAEwR,WAAW5G,GAAI,KACZ0G,EAAEG,cAAgBvP,MAI1B,IAHI6I,GACHA,EAASxG,KAAKqG,GAEVyG,EAAI,EAAGE,EAAOD,EAAExQ,OAAQuQ,EAAIE,EAAMF,IACtC3M,EAAEH,MAAMiB,KAAMoB,EAAGI,MAAOsK,EAAED,UAGrB,GAAI1O,EAAQC,SAAuB,SAAZgI,EAAG3J,KAAiB,CAC7C8J,GACHA,EAASxG,KAAKqG,GAGf,IAAI7H,EAAQ6H,EAAG7H,MAEf,GAAIA,EAAMjC,OACT,IAAKuQ,EAAI,EAAGA,EAAItO,EAAMjC,OAAQuQ,IAC7B3M,EAAEH,MAAMiB,KAAMoB,EAAGI,MAAOjE,EAAMsO,GAAIpQ,KAAM2J,EAAG3J,YAI5CyD,EAAEH,MAAMiB,KAAMoB,EAAGI,MAAO,GAAI/F,KAAM2J,EAAG3J,YAGtB,OAANqQ,QAA2B,IAANA,IAC3BvG,GACHA,EAASxG,KAAKqG,GAEflG,EAAEH,MAAMiB,KAAMoB,EAAGI,MAAOsK,EAAGrQ,KAAM2J,EAAG3J,KAAMyQ,SAAU9G,EAAG8G,YAIzD,IAAKtE,GAAYrM,EAAKC,IAAK,CAE1B,IAAI2Q,EAAS3R,EAAEe,EAAKC,KAAM4Q,EAAQD,EAAO,IAEzC/K,EAAIgL,EAAMpM,QAEAoM,EAAMhG,UAA2B,UAAfgG,EAAM3Q,OACjCyD,EAAEH,MAAMiB,KAAMoB,EAAGI,MAAO2K,EAAOnO,QAC/BkB,EAAEH,MAAMiB,KAAMoB,EAAI,KAAMI,MAAOjG,EAAKI,QAASqE,KAAMoB,EAAI,KAAMI,MAAOjG,EAAKK,SAI3E,OAAOsD,GAOR1E,EAAEsB,GAAGuQ,cAAgB,SAASzE,GAE7B,OAAOpN,EAAEiE,MAAMZ,KAAK8J,YAAYC,KAOjCpN,EAAEsB,GAAGwQ,eAAiB,SAASC,GAC9B,IAAIrN,KAsBJ,OApBArB,KAAK+K,KAAK,WACT,IAAIxH,EAAIvD,KAAKmC,KAEb,GAAKoB,EAAL,CAIA,IAAI0K,EAAItR,EAAEwR,WAAWnO,KAAM0O,GAE3B,GAAIT,GAAKA,EAAEG,cAAgBvP,MAC1B,IAAK,IAAI4B,EAAI,EAAGyK,EAAM+C,EAAExQ,OAAQgD,EAAIyK,EAAKzK,IACxCY,EAAEH,MAAMiB,KAAMoB,EAAGI,MAAOsK,EAAExN,UAGX,OAANwN,QAA2B,IAANA,GAC/B5M,EAAEH,MAAMiB,KAAMnC,KAAKmC,KAAMwB,MAAOsK,OAK3BtR,EAAEiE,MAAMS,IAyChB1E,EAAEsB,GAAGkQ,WAAa,SAASO,GAC1B,IAAK,IAAIvO,KAAUM,EAAI,EAAGyK,EAAMlL,KAAKvC,OAAQgD,EAAIyK,EAAKzK,IAAK,CAC1D,IAAI8G,EAAKvH,KAAKS,GACVwN,EAAItR,EAAEwR,WAAW5G,EAAImH,GAEf,OAANT,QAA2B,IAANA,GAAsBA,EAAEG,cAAgBvP,QAAUoP,EAAExQ,SAIzEwQ,EAAEG,cAAgBvP,MACrBlC,EAAEsO,MAAM9K,EAAK8N,GAEb9N,EAAIe,KAAK+M,IAIX,OAAO9N,GAMRxD,EAAEwR,WAAa,SAAS5G,EAAImH,GAC3B,IAAInL,EAAIgE,EAAGpF,KAAM3E,EAAI+J,EAAG3J,KAAM+Q,EAAMpH,EAAGqH,QAAQ1M,cAO/C,QAL0B,IAAfwM,IACVA,GAAa,GAIVA,KAAgBnL,GAAKgE,EAAGgB,UAAkB,UAAN/K,GAAuB,WAANA,IACjD,aAANA,GAA0B,UAANA,KAAmB+J,EAAGsH,UACpC,WAANrR,GAAwB,UAANA,IAAkB+J,EAAG7J,MAAQ6J,EAAG7J,KAAKC,MAAQ4J,GACxD,WAARoH,IAA0C,IAAtBpH,EAAGuH,eAEvB,OAAO,KAGR,GAAY,WAARH,EAAkB,CACrB,IAAII,EAAQxH,EAAGuH,cAEf,GAAIC,EAAQ,EACX,OAAO,KAOR,IAAK,IAJD1N,KAAQ2N,EAAMzH,EAAGzK,QACjBmS,EAAa,eAANzR,EACP0N,EAAO+D,EAAMF,EAAQ,EAAIC,EAAIvR,OAExBgD,EAAKwO,EAAMF,EAAQ,EAAItO,EAAIyK,EAAKzK,IAAK,CAC7C,IAAIyO,EAAKF,EAAIvO,GAEb,GAAIyO,EAAGC,WAAaD,EAAG3G,SAAU,CAChC,IAAI0F,EAAIiB,EAAGvL,MAMX,GAJKsK,IACJA,EAAKiB,EAAGE,YAAcF,EAAGE,WAAWzL,QAAWuL,EAAGE,WAAWzL,MAAe,UAAKuL,EAAGG,KAAOH,EAAGvL,OAG3FsL,EACH,OAAOhB,EAGR5M,EAAEH,KAAK+M,IAIT,OAAO5M,EAGR,OAAO1E,EAAE4K,GAAIpH,MAAMc,QAAQ5B,EAAO,SAWnC1C,EAAEsB,GAAGuM,UAAY,SAASC,GACzB,OAAOzK,KAAK+K,KAAK,WAChBpO,EAAE,wBAAyBqD,MAAMsP,YAAY7E,MAO/C9N,EAAEsB,GAAGqR,YAAc3S,EAAEsB,GAAGsR,YAAc,SAAS9E,GAC9C,IAAI+E,EAAK,6FAET,OAAOxP,KAAK+K,KAAK,WAChB,IAAIvN,EAAIwC,KAAKpC,KAAM+Q,EAAM3O,KAAK4O,QAAQ1M,cAElCsN,EAAG3M,KAAKrF,IAAc,aAARmR,EACjB3O,KAAK2D,MAAQ,GAEG,aAANnG,GAA0B,UAANA,EAC9BwC,KAAK6O,SAAU,EAEG,WAARF,EACV3O,KAAK8O,eAAiB,EAEN,SAANtR,EACN,OAAOqF,KAAK+K,UAAUC,WACzBlR,EAAEqD,MAAMyP,YAAY9S,EAAEqD,MAAM0P,OAAM,IAElC/S,EAAEqD,MAAMG,IAAI,IAGHsK,KAKa,IAAlBA,GAA0B,SAAS5H,KAAKrF,IAClB,iBAAlBiN,GAA8B9N,EAAEqD,MAAMzC,GAAGkN,MACjDzK,KAAK2D,MAAQ,OAiBjBhH,EAAEsB,GAAGsM,UAAY,WAChB,OAAOvK,KAAK+K,KAAK,WAChB,IAAIxD,EAAK5K,EAAEqD,MACP2O,EAAM3O,KAAK4O,QAAQ1M,cAEvB,OAAQyM,GACR,IAAK,QACJ3O,KAAK6O,QAAU7O,KAAK2P,eAGrB,IAAK,WAGJ,OAFA3P,KAAK2D,MAAQ3D,KAAK4P,cAEX,EAER,IAAK,SACL,IAAK,WACJ,IAAIC,EAAStI,EAAGuI,QAAQ,UAYxB,OAVID,EAAOpS,QAAUoS,EAAO,GAAGE,SAClB,WAARpB,EACH3O,KAAKmP,SAAWnP,KAAKgQ,gBAErBzI,EAAG0I,KAAK,UAAU1F,YAGnBsF,EAAOtF,aAGD,EAER,IAAK,SAUJ,OATAhD,EAAG0I,KAAK,UAAUlF,KAAK,SAAStK,GAE/B,GADAT,KAAKmP,SAAWnP,KAAKgQ,gBACjBhQ,KAAKgQ,kBAAoBzI,EAAG,GAAGwI,SAGlC,OAFAxI,EAAG,GAAGuH,cAAgBrO,GAEf,KAIF,EAER,IAAK,QACJ,IAAIyP,EAAQvT,EAAE4K,EAAGtH,KAAK,QAClBkQ,EAAO5I,EAAG0I,KAAK,yBAQnB,OANIC,EAAM,IACTC,EAAKC,QAAQF,EAAM,IAGpBC,EAAK5F,aAEE,EAER,IAAK,OAOJ,OAJ0B,mBAAfvK,KAAKqQ,OAA+C,iBAAfrQ,KAAKqQ,QAAuBrQ,KAAKqQ,MAAMC,WACtFtQ,KAAKqQ,SAGC,EAER,QAGC,OAFA9I,EAAG0I,KAAK,oCAAoC1F,aAErC,MAQV5N,EAAEsB,GAAGsS,OAAS,SAAS9J,GAKtB,YAJiB,IAANA,IACVA,GAAI,GAGEzG,KAAK+K,KAAK,WAChB/K,KAAKuI,UAAY9B,KAQnB9J,EAAEsB,GAAGkR,SAAW,SAASU,GAKxB,YAJsB,IAAXA,IACVA,GAAS,GAGH7P,KAAK+K,KAAK,WAChB,IAAIvN,EAAIwC,KAAKpC,KAEb,GAAU,aAANJ,GAA0B,UAANA,EACvBwC,KAAK6O,QAAUgB,OAET,GAAmC,WAA/B7P,KAAK4O,QAAQ1M,cAA4B,CACnD,IAAIsO,EAAO7T,EAAEqD,MAAMyQ,OAAO,UAEtBZ,GAAUW,EAAK,IAAuB,eAAjBA,EAAK,GAAG5S,MAEhC4S,EAAKP,KAAK,UAAUd,UAAS,GAG9BnP,KAAKmP,SAAWU,MAMnBlT,EAAEsB,GAAGb,WAAWuB,OAAQ","file":"jquery.form.min.js"} \ No newline at end of file diff -r e200cb7efeb3 -r c2387f117808 core/core.api.php --- a/core/core.api.php Thu Apr 26 11:26:54 2018 +0100 +++ b/core/core.api.php Tue Jul 10 15:07:59 2018 +0100 @@ -413,7 +413,7 @@ * \Drupal\Core\Cache\CacheBackendInterface. * * The Cache API is used to store data that takes a long time to compute. - * Caching can either be permanent or valid only for a certain timespan, and + * Caching can either be permanent or valid only for a certain time span, and * the cache can contain any type of data. * * To use the Cache API: @@ -558,7 +558,7 @@ * This also is the case when you define your own entity types: you'll get the * exact same cache tag invalidation as any of the built-in entity types, with * the ability to override any of the default behavior if needed. - * See \Drupal\Core\Cache\CacheableDepenencyInterface::getCacheTags(), + * See \Drupal\Core\Cache\CacheableDependencyInterface::getCacheTags(), * \Drupal\Core\Entity\EntityTypeInterface::getListCacheTags(), * \Drupal\Core\Entity\Entity::invalidateTagsOnSave() and * \Drupal\Core\Entity\Entity::invalidateTagsOnDelete(). @@ -569,7 +569,7 @@ * logged-in user who is viewing a page, the language the page is being rendered * in, the theme being used, etc. When caching the output of such a calculation, * you must cache each variation separately, along with information about which - * variation of the contextual data was used in the calculatation. The next time + * variation of the contextual data was used in the calculation. The next time * the computed data is needed, if the context matches that for an existing * cached data set, the cached data can be reused; if no context matches, a new * data set can be calculated and cached for later use. @@ -1226,7 +1226,7 @@ * under development. While PHP type hinting does this for objects and arrays, * runtime assertions do this for scalars (strings, integers, floats, etc.) and * complex data structures such as cache and render arrays. They ensure that - * methods' return values are the documented datatypes. They also verify that + * methods' return values are the documented data types. They also verify that * objects have been properly configured and set up by the service container. * They supplement unit tests by checking scenarios that do not have unit tests * written for them. @@ -1252,9 +1252,11 @@ * using @link entity_api Entities @endlink. * - Session: Information about individual users' interactions with the site, * such as whether they are logged in. This is really "state" information, but - * it is not stored the same way so it's a separate type here. Session - * information is available from the Request object. The session implements + * it is not stored the same way so it's a separate type here. Session data is + * accessed via \Symfony\Component\HttpFoundation\Request::getSession(), which + * returns an instance of * \Symfony\Component\HttpFoundation\Session\SessionInterface. + * See the @link session Sessions topic @endlink for more information. * - State: Information of a temporary nature, generally machine-generated and * not human-edited, about the current state of your site. Examples: the time * when Cron was last run, whether node access permissions need rebuilding, @@ -2001,12 +2003,12 @@ * Alter cron queue information before cron runs. * * Called by \Drupal\Core\Cron to allow modules to alter cron queue settings - * before any jobs are processesed. + * before any jobs are processed. * * @param array $queues * An array of cron queue information. * - * @see \Drupal\Core\QueueWorker\QueueWorkerInterface + * @see \Drupal\Core\Queue\QueueWorkerInterface * @see \Drupal\Core\Annotation\QueueWorker * @see \Drupal\Core\Cron */ @@ -2257,12 +2259,12 @@ * they will be processed. Each callable item defined in $sync_steps should * either be a global function or a public static method. The callable should * accept a $context array by reference. For example: - * + * @code * function _additional_configuration_step(&$context) { * // Do stuff. * // If finished set $context['finished'] = 1. * } - * + * @endcode * For more information on creating batches, see the * @link batch Batch operations @endlink documentation. * @@ -2585,3 +2587,64 @@ * minor release. * @} */ + +/** + * @defgroup session Sessions + * @{ + * Store and retrieve data associated with a user's browsing session. + * + * @section sec_intro Overview + * The Drupal session management subsystem is built on top of the Symfony + * session component. It is optimized in order to minimize the impact of + * anonymous sessions on caching proxies. A session is only started if necessary + * and the session cookie is removed from the browser as soon as the session + * has no data. For this reason it is important for contributed and custom + * code to remove session data if it is not used anymore. + * + * @section sec_usage Usage + * Session data is accessed via the + * \Symfony\Component\HttpFoundation\Request::getSession() + * method, which returns an instance of + * \Symfony\Component\HttpFoundation\Session\SessionInterface. The most + * important methods on SessionInterface are set(), get(), and remove(). + * + * The following code fragment shows the implementation of a counter controller + * relying on the session: + * @code + * public function counter(Request $request) { + * $session = $request->getSession(); + * $count = $session->get('mymodule.counter', 0) + 1; + * $session->set('mymodule.counter', $count); + * + * return [ + * '#markup' => $this->t('Page Views: @count', ['@count' => $count]), + * '#cache' => [ + * 'max-age' => 0, + * ], + * ]; + * } + * + * public function reset(Request $request) { + * $session = $request->getSession(); + * $session->remove('mymodule.counter'); + * } + * @endcode + * + * It is important to keep the amount of data stored inside the session to a + * minimum, as the complete session is loaded on every request. Also third + * party session storage backends do not necessarily allow objects of unlimited + * size. If it is necessary to collect a non-trivial amount of data specific to + * a user's session, use the Key/Value store to save the serialized data and + * only store the key to the entry in the session. + * + * @section sec_reserved Reserved attributes and namespacing + * Contributed modules relying on the session are encouraged to namespace + * session attributes by prefixing them with their project name or an + * abbreviation thereof. + * + * Some attributes are reserved for Drupal core and must not be accessed from + * within contributed and custom code. Reserved attributes include: + * - uid: The user ID for an authenticated user. The value of this attribute + * cannot be modified. + * @} + */ diff -r e200cb7efeb3 -r c2387f117808 core/includes/common.inc --- a/core/includes/common.inc Thu Apr 26 11:26:54 2018 +0100 +++ b/core/includes/common.inc Tue Jul 10 15:07:59 2018 +0100 @@ -608,7 +608,7 @@ * 'id' => 'my-module-table', * ), * ); - * return drupal_render($table); + * return \Drupal::service('renderer')->render($table); * @endcode * * In the theme function for the form, a special class must be added to each @@ -899,7 +899,7 @@ * rendering when possible or loop through the elements and render them as * they are available. * - * @see drupal_render() + * @see \Drupal\Core\Render\RendererInterface::render() * @see https://www.drupal.org/node/2912757 */ function drupal_render_children(&$element, $children_keys = NULL) { diff -r e200cb7efeb3 -r c2387f117808 core/includes/file.inc --- a/core/includes/file.inc Thu Apr 26 11:26:54 2018 +0100 +++ b/core/includes/file.inc Tue Jul 10 15:07:59 2018 +0100 @@ -270,7 +270,7 @@ $http_host = $host . ':' . $port; } - return preg_replace('|^https?://' . $http_host . '|', '', $file_url); + return preg_replace('|^https?://' . preg_quote($http_host, '|') . '|', '', $file_url); } /** diff -r e200cb7efeb3 -r c2387f117808 core/includes/install.core.inc --- a/core/includes/install.core.inc Thu Apr 26 11:26:54 2018 +0100 +++ b/core/includes/install.core.inc Tue Jul 10 15:07:59 2018 +0100 @@ -1425,7 +1425,7 @@ * * @param string $version * Version info string (e.g., 8.0.0, 8.1.0, 8.0.0-dev, 8.0.0-unstable1, - * 8.0.0-alpha2, 8.0.0-beta3, and 8.0.0-rc4). + * 8.0.0-alpha2, 8.0.0-beta3, 8.6.x, and 8.0.0-rc4). * * @return array * Associative array of version info: @@ -1443,7 +1443,7 @@ \. # . (?P[0-9]+) # Minor release number. \. # . - (?P[0-9]+) # Patch release number. + (?P[0-9]+|x) # Patch release number. ) # ( # - # - separator for "extra" version information. @@ -1715,6 +1715,9 @@ ]; \Drupal::service('locale.project')->set($data['name'], $data); module_load_include('compare.inc', 'locale'); + // Reset project information static cache so that it uses the data + // set above. + locale_translation_clear_cache_projects(); locale_translation_check_projects_local(['drupal'], [$langcode]); } } @@ -1850,10 +1853,19 @@ return; } + $version = \Drupal::VERSION; + // For dev releases, remove the '-dev' part and trust the translation server + // to fall back to the latest stable release for that branch. + // @see locale_translation_build_projects() + if (preg_match("/^(\d+\.\d+\.).*-dev$/", $version, $matches)) { + // Example match: 8.0.0-dev => 8.0.x (Drupal core) + $version = $matches[1] . 'x'; + } + // Build URL for the translation file and the translation server. $variables = [ '%project' => 'drupal', - '%version' => \Drupal::VERSION, + '%version' => $version, '%core' => \Drupal::CORE_COMPATIBILITY, '%language' => $langcode, ]; diff -r e200cb7efeb3 -r c2387f117808 core/includes/schema.inc --- a/core/includes/schema.inc Thu Apr 26 11:26:54 2018 +0100 +++ b/core/includes/schema.inc Tue Jul 10 15:07:59 2018 +0100 @@ -202,7 +202,7 @@ } /** - * Typecasts values to proper datatypes. + * Typecasts values to proper data types. * * MySQL PDO silently casts, e.g. FALSE and '' to 0, when inserting the value * into an integer column, but PostgreSQL PDO does not. Look up the schema diff -r e200cb7efeb3 -r c2387f117808 core/lib/Drupal.php --- a/core/lib/Drupal.php Thu Apr 26 11:26:54 2018 +0100 +++ b/core/lib/Drupal.php Tue Jul 10 15:07:59 2018 +0100 @@ -82,7 +82,7 @@ /** * The current system version. */ - const VERSION = '8.5.3'; + const VERSION = '8.5.5'; /** * Core API compatibility. diff -r e200cb7efeb3 -r c2387f117808 core/lib/Drupal/Component/Datetime/DateTimePlus.php --- a/core/lib/Drupal/Component/Datetime/DateTimePlus.php Thu Apr 26 11:26:54 2018 +0100 +++ b/core/lib/Drupal/Component/Datetime/DateTimePlus.php Tue Jul 10 15:07:59 2018 +0100 @@ -671,7 +671,7 @@ * Formats the date for display. * * @param string $format - * A format string using either PHP's date(). + * Format accepted by date(). * @param array $settings * - timezone: (optional) String timezone name. Defaults to the timezone * of the date object. diff -r e200cb7efeb3 -r c2387f117808 core/lib/Drupal/Component/Transliteration/data/x04.php --- a/core/lib/Drupal/Component/Transliteration/data/x04.php Thu Apr 26 11:26:54 2018 +0100 +++ b/core/lib/Drupal/Component/Transliteration/data/x04.php Tue Jul 10 15:07:59 2018 +0100 @@ -6,12 +6,12 @@ */ $base = [ - 0x00 => 'E', 'E', 'D', 'G', 'E', 'Z', 'I', 'I', 'J', 'L', 'N', 'C', 'K', 'I', 'U', 'D', - 0x10 => 'A', 'B', 'V', 'G', 'D', 'E', 'Z', 'Z', 'I', 'I', 'K', 'L', 'M', 'N', 'O', 'P', - 0x20 => 'R', 'S', 'T', 'U', 'F', 'H', 'C', 'C', 'S', 'S', '', 'Y', '', 'E', 'U', 'A', - 0x30 => 'a', 'b', 'v', 'g', 'd', 'e', 'z', 'z', 'i', 'i', 'k', 'l', 'm', 'n', 'o', 'p', - 0x40 => 'r', 's', 't', 'u', 'f', 'h', 'c', 'c', 's', 's', '', 'y', '', 'e', 'u', 'a', - 0x50 => 'e', 'e', 'd', 'g', 'e', 'z', 'i', 'i', 'j', 'l', 'n', 'c', 'k', 'i', 'u', 'd', + 0x00 => 'E', 'YO', 'D', 'G', 'E', 'Z', 'I', 'I', 'J', 'L', 'N', 'C', 'K', 'I', 'U', 'D', + 0x10 => 'A', 'B', 'V', 'G', 'D', 'E', 'ZH', 'Z', 'I', 'Y', 'K', 'L', 'M', 'N', 'O', 'P', + 0x20 => 'R', 'S', 'T', 'U', 'F', 'KH', 'C', 'CH', 'SH', 'SCH', '', 'Y', '', 'E', 'YU', 'YA', + 0x30 => 'a', 'b', 'v', 'g', 'd', 'e', 'zh', 'z', 'i', 'y', 'k', 'l', 'm', 'n', 'o', 'p', + 0x40 => 'r', 's', 't', 'u', 'f', 'kh', 'c', 'ch', 'sh', 'sch', '', 'y', '', 'e', 'yu', 'ya', + 0x50 => 'e', 'yo', 'd', 'g', 'e', 'z', 'i', 'i', 'j', 'l', 'n', 'c', 'k', 'i', 'u', 'd', 0x60 => 'O', 'o', 'E', 'e', 'Ie', 'ie', 'E', 'e', 'Ie', 'ie', 'O', 'o', 'Io', 'io', 'Ks', 'ks', 0x70 => 'Ps', 'ps', 'F', 'f', 'Y', 'y', 'Y', 'y', 'u', 'u', 'O', 'o', 'O', 'o', 'Ot', 'ot', 0x80 => 'Q', 'q', '*1000*', '', '', '', '', NULL, '*100.000*', '*1.000.000*', NULL, NULL, '"', '"', 'R\'', 'r\'', diff -r e200cb7efeb3 -r c2387f117808 core/lib/Drupal/Component/Uuid/composer.json --- a/core/lib/Drupal/Component/Uuid/composer.json Thu Apr 26 11:26:54 2018 +0100 +++ b/core/lib/Drupal/Component/Uuid/composer.json Tue Jul 10 15:07:59 2018 +0100 @@ -1,6 +1,6 @@ { "name": "drupal/core-uuid", - "description": "PHP library for reading PO files.", + "description": "UUID generation and validation.", "type": "library", "license": "GPL-2.0-or-later", "support": { diff -r e200cb7efeb3 -r c2387f117808 core/lib/Drupal/Core/Access/AccessResult.php --- a/core/lib/Drupal/Core/Access/AccessResult.php Thu Apr 26 11:26:54 2018 +0100 +++ b/core/lib/Drupal/Core/Access/AccessResult.php Tue Jul 10 15:07:59 2018 +0100 @@ -336,10 +336,10 @@ $merge_other = TRUE; } - if ($this->isForbidden() && $this instanceof AccessResultReasonInterface) { + if ($this->isForbidden() && $this instanceof AccessResultReasonInterface && !is_null($this->getReason())) { $result->setReason($this->getReason()); } - elseif ($other->isForbidden() && $other instanceof AccessResultReasonInterface) { + elseif ($other->isForbidden() && $other instanceof AccessResultReasonInterface && !is_null($other->getReason())) { $result->setReason($other->getReason()); } } @@ -353,14 +353,13 @@ $result = static::neutral(); if (!$this->isNeutral() || ($this->getCacheMaxAge() === 0 && $other->isNeutral()) || ($this->getCacheMaxAge() !== 0 && $other instanceof CacheableDependencyInterface && $other->getCacheMaxAge() !== 0)) { $merge_other = TRUE; - if ($other instanceof AccessResultReasonInterface) { - $result->setReason($other->getReason()); - } } - else { - if ($this instanceof AccessResultReasonInterface) { - $result->setReason($this->getReason()); - } + + if ($this instanceof AccessResultReasonInterface && !is_null($this->getReason())) { + $result->setReason($this->getReason()); + } + elseif ($other instanceof AccessResultReasonInterface && !is_null($other->getReason())) { + $result->setReason($other->getReason()); } } $result->inheritCacheability($this); diff -r e200cb7efeb3 -r c2387f117808 core/lib/Drupal/Core/Cache/Context/SiteCacheContext.php --- a/core/lib/Drupal/Core/Cache/Context/SiteCacheContext.php Thu Apr 26 11:26:54 2018 +0100 +++ b/core/lib/Drupal/Core/Cache/Context/SiteCacheContext.php Tue Jul 10 15:07:59 2018 +0100 @@ -7,7 +7,7 @@ /** * Defines the SiteCacheContext service, for "per site" caching. * - * Cache context ID: 'site'. + * Cache context ID: 'url.site'. * * A "site" is defined as the combination of URI scheme, domain name, port and * base path. It allows for varying between the *same* site being accessed via diff -r e200cb7efeb3 -r c2387f117808 core/lib/Drupal/Core/Config/Config.php --- a/core/lib/Drupal/Core/Config/Config.php Thu Apr 26 11:26:54 2018 +0100 +++ b/core/lib/Drupal/Core/Config/Config.php Tue Jul 10 15:07:59 2018 +0100 @@ -219,6 +219,10 @@ } } + // Potentially configuration schema could have changed the underlying data's + // types. + $this->resetOverriddenData(); + $this->storage->write($this->name, $this->data); if (!$this->isNew) { Cache::invalidateTags($this->getCacheTags()); @@ -226,9 +230,6 @@ $this->isNew = FALSE; $this->eventDispatcher->dispatch(ConfigEvents::SAVE, new ConfigCrudEvent($this)); $this->originalData = $this->data; - // Potentially configuration schema could have changed the underlying data's - // types. - $this->resetOverriddenData(); return $this; } diff -r e200cb7efeb3 -r c2387f117808 core/lib/Drupal/Core/Controller/ControllerBase.php --- a/core/lib/Drupal/Core/Controller/ControllerBase.php Thu Apr 26 11:26:54 2018 +0100 +++ b/core/lib/Drupal/Core/Controller/ControllerBase.php Tue Jul 10 15:07:59 2018 +0100 @@ -93,7 +93,7 @@ /** * The state service. * - * @var \Drupal\Core\KeyValueStore\KeyValueStoreInterface + * @var \Drupal\Core\State\StateInterface */ protected $stateService; @@ -222,7 +222,7 @@ * needs to be the same across development, production, etc. environments * (for example, the system maintenance message) should use config() instead. * - * @return \Drupal\Core\KeyValueStore\KeyValueStoreInterface + * @return \Drupal\Core\State\StateInterface */ protected function state() { if (!$this->stateService) { diff -r e200cb7efeb3 -r c2387f117808 core/lib/Drupal/Core/Database/Driver/mysql/Schema.php --- a/core/lib/Drupal/Core/Database/Driver/mysql/Schema.php Thu Apr 26 11:26:54 2018 +0100 +++ b/core/lib/Drupal/Core/Database/Driver/mysql/Schema.php Tue Jul 10 15:07:59 2018 +0100 @@ -434,8 +434,16 @@ ->execute(); } if (isset($spec['initial_from_field'])) { + if (isset($spec['initial'])) { + $expression = 'COALESCE(' . $spec['initial_from_field'] . ', :default_initial_value)'; + $arguments = [':default_initial_value' => $spec['initial']]; + } + else { + $expression = $spec['initial_from_field']; + $arguments = []; + } $this->connection->update($table) - ->expression($field, $spec['initial_from_field']) + ->expression($field, $expression, $arguments) ->execute(); } if ($fixnull) { diff -r e200cb7efeb3 -r c2387f117808 core/lib/Drupal/Core/Database/Driver/pgsql/Schema.php --- a/core/lib/Drupal/Core/Database/Driver/pgsql/Schema.php Thu Apr 26 11:26:54 2018 +0100 +++ b/core/lib/Drupal/Core/Database/Driver/pgsql/Schema.php Tue Jul 10 15:07:59 2018 +0100 @@ -358,7 +358,7 @@ } if (!empty($field['unsigned'])) { - // Unsigned datatypes are not supported in PostgreSQL 9.1. In MySQL, + // Unsigned data types are not supported in PostgreSQL 9.1. In MySQL, // they are used to ensure a positive number is inserted and it also // doubles the maximum integer size that can be stored in a field. // The PostgreSQL schema in Drupal creates a check constraint @@ -568,8 +568,16 @@ ->execute(); } if (isset($spec['initial_from_field'])) { + if (isset($spec['initial'])) { + $expression = 'COALESCE(' . $spec['initial_from_field'] . ', :default_initial_value)'; + $arguments = [':default_initial_value' => $spec['initial']]; + } + else { + $expression = $spec['initial_from_field']; + $arguments = []; + } $this->connection->update($table) - ->expression($field, $spec['initial_from_field']) + ->expression($field, $expression, $arguments) ->execute(); } if ($fixnull) { diff -r e200cb7efeb3 -r c2387f117808 core/lib/Drupal/Core/Database/Driver/sqlite/Schema.php --- a/core/lib/Drupal/Core/Database/Driver/sqlite/Schema.php Thu Apr 26 11:26:54 2018 +0100 +++ b/core/lib/Drupal/Core/Database/Driver/sqlite/Schema.php Tue Jul 10 15:07:59 2018 +0100 @@ -333,8 +333,16 @@ ->execute(); } if (isset($specification['initial_from_field'])) { + if (isset($specification['initial'])) { + $expression = 'COALESCE(' . $specification['initial_from_field'] . ', :default_initial_value)'; + $arguments = [':default_initial_value' => $specification['initial']]; + } + else { + $expression = $specification['initial_from_field']; + $arguments = []; + } $this->connection->update($table) - ->expression($field, $specification['initial_from_field']) + ->expression($field, $expression, $arguments) ->execute(); } } @@ -358,9 +366,17 @@ } elseif (isset($specification['initial_from_field'])) { // If we have a initial value, copy it over. + if (isset($specification['initial'])) { + $expression = 'COALESCE(' . $specification['initial_from_field'] . ', :default_initial_value)'; + $arguments = [':default_initial_value' => $specification['initial']]; + } + else { + $expression = $specification['initial_from_field']; + $arguments = []; + } $mapping[$field] = [ - 'expression' => $specification['initial_from_field'], - 'arguments' => [], + 'expression' => $expression, + 'arguments' => $arguments, ]; } else { diff -r e200cb7efeb3 -r c2387f117808 core/lib/Drupal/Core/Database/Driver/sqlite/Statement.php --- a/core/lib/Drupal/Core/Database/Driver/sqlite/Statement.php Thu Apr 26 11:26:54 2018 +0100 +++ b/core/lib/Drupal/Core/Database/Driver/sqlite/Statement.php Tue Jul 10 15:07:59 2018 +0100 @@ -27,7 +27,7 @@ * See http://bugs.php.net/bug.php?id=45259 for more details. */ protected function getStatement($query, &$args = []) { - if (count($args)) { + if (is_array($args) && !empty($args)) { // Check if $args is a simple numeric array. if (range(0, count($args) - 1) === array_keys($args)) { // In that case, we have unnamed placeholders. diff -r e200cb7efeb3 -r c2387f117808 core/lib/Drupal/Core/Database/Query/SelectInterface.php --- a/core/lib/Drupal/Core/Database/Query/SelectInterface.php Thu Apr 26 11:26:54 2018 +0100 +++ b/core/lib/Drupal/Core/Database/Query/SelectInterface.php Tue Jul 10 15:07:59 2018 +0100 @@ -404,10 +404,10 @@ * on. * * Example: - * + * @code * $query->addExpression('SUBSTRING(thread, 1, (LENGTH(thread) - 1))', 'order_field'); * $query->orderBy('order_field', 'ASC'); - * + * @endcode * @param $direction * The direction to sort. Legal values are "ASC" and "DESC". Any other value * will be converted to "ASC". diff -r e200cb7efeb3 -r c2387f117808 core/lib/Drupal/Core/Database/StatementInterface.php --- a/core/lib/Drupal/Core/Database/StatementInterface.php Thu Apr 26 11:26:54 2018 +0100 +++ b/core/lib/Drupal/Core/Database/StatementInterface.php Tue Jul 10 15:07:59 2018 +0100 @@ -44,7 +44,7 @@ * * @param $args * An array of values with as many elements as there are bound parameters in - * the SQL statement being executed. + * the SQL statement being executed. This can be NULL. * @param $options * An array of options for this query. * diff -r e200cb7efeb3 -r c2387f117808 core/lib/Drupal/Core/Database/StatementPrefetch.php --- a/core/lib/Drupal/Core/Database/StatementPrefetch.php Thu Apr 26 11:26:54 2018 +0100 +++ b/core/lib/Drupal/Core/Database/StatementPrefetch.php Tue Jul 10 15:07:59 2018 +0100 @@ -214,8 +214,8 @@ * * @param $query * The query. - * @param array $args - * An array of arguments. + * @param array|null $args + * An array of arguments. This can be NULL. * @return \PDOStatement * A PDOStatement object. */ diff -r e200cb7efeb3 -r c2387f117808 core/lib/Drupal/Core/Database/database.api.php --- a/core/lib/Drupal/Core/Database/database.api.php Thu Apr 26 11:26:54 2018 +0100 +++ b/core/lib/Drupal/Core/Database/database.api.php Tue Jul 10 15:07:59 2018 +0100 @@ -256,7 +256,7 @@ * recent) {node_field_revision}.vid value for this nid." * - 'type': The generic datatype: 'char', 'varchar', 'text', 'blob', 'int', * 'float', 'numeric', or 'serial'. Most types just map to the according - * database engine specific datatypes. Use 'serial' for auto incrementing + * database engine specific data types. Use 'serial' for auto incrementing * fields. This will expand to 'INT auto_increment' on MySQL. * A special 'varchar_ascii' type is also available for limiting machine * name field to US ASCII characters. @@ -272,7 +272,7 @@ * - 'size': The data size: 'tiny', 'small', 'medium', 'normal', * 'big'. This is a hint about the largest value the field will * store and determines which of the database engine specific - * datatypes will be used (e.g. on MySQL, TINYINT vs. INT vs. BIGINT). + * data types will be used (e.g. on MySQL, TINYINT vs. INT vs. BIGINT). * 'normal', the default, selects the base type (e.g. on MySQL, * INT, VARCHAR, BLOB, etc.). * Not all sizes are available for all data types. See diff -r e200cb7efeb3 -r c2387f117808 core/lib/Drupal/Core/Datetime/Element/Datetime.php --- a/core/lib/Drupal/Core/Datetime/Element/Datetime.php Thu Apr 26 11:26:54 2018 +0100 +++ b/core/lib/Drupal/Core/Datetime/Element/Datetime.php Tue Jul 10 15:07:59 2018 +0100 @@ -181,9 +181,13 @@ * dynamic value that is that many years earlier or later than the current * year at the time the form is displayed. Used in jQueryUI datepicker year * range and HTML5 min/max date settings. Defaults to '1900:2050'. - * - #date_increment: The increment to use for minutes and seconds, i.e. - * '15' would show only :00, :15, :30 and :45. Used for HTML5 step values and - * jQueryUI datepicker settings. Defaults to 1 to show every minute. + * - #date_increment: The interval (step) to use when incrementing or + * decrementing time, in seconds. For example, if this value is set to 30, + * time increases (or decreases) in steps of 30 seconds (00:00:00, + * 00:00:30, 00:01:00, and so on.) If this value is a multiple of 60, the + * "seconds"-component will not be shown in the input. Used for HTML5 step + * values and jQueryUI datepicker settings. Defaults to 1 to show every + * second. * - #date_timezone: The local timezone to use when creating dates. Generally * this should be left empty and it will be set correctly for the user using * the form. Useful if the default value is empty to designate a desired diff -r e200cb7efeb3 -r c2387f117808 core/lib/Drupal/Core/DependencyInjection/DependencySerializationTrait.php --- a/core/lib/Drupal/Core/DependencyInjection/DependencySerializationTrait.php Thu Apr 26 11:26:54 2018 +0100 +++ b/core/lib/Drupal/Core/DependencyInjection/DependencySerializationTrait.php Tue Jul 10 15:07:59 2018 +0100 @@ -2,6 +2,7 @@ namespace Drupal\Core\DependencyInjection; +use Drupal\Core\Entity\EntityStorageInterface; use Symfony\Component\DependencyInjection\ContainerInterface; /** @@ -17,6 +18,13 @@ protected $_serviceIds = []; /** + * An array of entity type IDs keyed by the property name of their storages. + * + * @var array + */ + protected $_entityStorages = []; + + /** * {@inheritdoc} */ public function __sleep() { @@ -35,6 +43,17 @@ $this->_serviceIds[$key] = 'service_container'; unset($vars[$key]); } + elseif ($value instanceof EntityStorageInterface) { + // If a class member is an entity storage, only store the entity type ID + // the storage is for so it can be used to get a fresh object on + // unserialization. By doing this we prevent possible memory leaks when + // the storage is serialized when it contains a static cache of entity + // objects and additionally we ensure that we'll not have multiple + // storage objects for the same entity type and therefore prevent + // returning different references for the same entity. + $this->_entityStorages[$key] = $value->getEntityTypeId(); + unset($vars[$key]); + } } return array_keys($vars); @@ -61,6 +80,19 @@ $this->$key = $container->get($service_id); } $this->_serviceIds = []; + + // In rare cases, when test data is serialized in the parent process, there + // is a service container but it doesn't contain all expected services. To + // avoid fatal errors during the wrap-up of failing tests, we check for this + // case, too. + if ($this->_entityStorages && (!$phpunit_bootstrap || $container->has('entity_type.manager'))) { + /** @var \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager */ + $entity_type_manager = $container->get('entity_type.manager'); + foreach ($this->_entityStorages as $key => $entity_type_id) { + $this->$key = $entity_type_manager->getStorage($entity_type_id); + } + } + $this->_entityStorages = []; } } diff -r e200cb7efeb3 -r c2387f117808 core/lib/Drupal/Core/DrupalKernel.php --- a/core/lib/Drupal/Core/DrupalKernel.php Thu Apr 26 11:26:54 2018 +0100 +++ b/core/lib/Drupal/Core/DrupalKernel.php Tue Jul 10 15:07:59 2018 +0100 @@ -318,6 +318,9 @@ * for bootstrap level configuration, file configuration stores, public file * storage and site specific modules and themes. * + * A file named sites.php must be present in the sites directory for + * multisite. If it doesn't exist, then 'sites/default' will be used. + * * Finds a matching site directory file by stripping the website's hostname * from left to right and pathname from right to left. By default, the * directory must contain a 'settings.php' file for it to match. If the @@ -328,9 +331,8 @@ * default.settings.php for examples on how the URL is converted to a * directory. * - * If a file named sites.php is present in the sites directory, it will be - * loaded prior to scanning for directories. That file can define aliases in - * an associative array named $sites. The array is written in the format + * The sites.php file in the sites directory can define aliases in an + * associative array named $sites. The array is written in the format * '..' => 'directory'. As an example, to create a * directory alias for https://www.drupal.org:8080/mysite/test whose * configuration file is in sites/example.com, the array should be defined as: @@ -981,16 +983,18 @@ // sites/default/default.settings.php contains more runtime settings. // The .htaccess file contains settings that cannot be changed at runtime. - // Use session cookies, not transparent sessions that puts the session id in - // the query string. - ini_set('session.use_cookies', '1'); - ini_set('session.use_only_cookies', '1'); - ini_set('session.use_trans_sid', '0'); - // Don't send HTTP headers using PHP's session handler. - // Send an empty string to disable the cache limiter. - ini_set('session.cache_limiter', ''); - // Use httponly session cookies. - ini_set('session.cookie_httponly', '1'); + if (PHP_SAPI !== 'cli') { + // Use session cookies, not transparent sessions that puts the session id + // in the query string. + ini_set('session.use_cookies', '1'); + ini_set('session.use_only_cookies', '1'); + ini_set('session.use_trans_sid', '0'); + // Don't send HTTP headers using PHP's session handler. + // Send an empty string to disable the cache limiter. + ini_set('session.cache_limiter', ''); + // Use httponly session cookies. + ini_set('session.cookie_httponly', '1'); + } // Set sane locale settings, to ensure consistent string, dates, times and // numbers handling. diff -r e200cb7efeb3 -r c2387f117808 core/lib/Drupal/Core/Entity/ContentEntityBase.php --- a/core/lib/Drupal/Core/Entity/ContentEntityBase.php Thu Apr 26 11:26:54 2018 +0100 +++ b/core/lib/Drupal/Core/Entity/ContentEntityBase.php Tue Jul 10 15:07:59 2018 +0100 @@ -772,11 +772,11 @@ * {@inheritdoc} */ public function onChange($name) { - // Check if the changed name is the value of an entity key and if the value - // of that is currently cached, if so, reset it. Exclude the bundle from - // that check, as it ready only and must not change, unsetting it could + // Check if the changed name is the value of any entity keys and if any of + // those values are currently cached, if so, reset it. Exclude the bundle + // from that check, as it ready only and must not change, unsetting it could // lead to recursions. - if ($key = array_search($name, $this->getEntityType()->getKeys())) { + foreach (array_keys($this->getEntityType()->getKeys(), $name, TRUE) as $key) { if ($key != 'bundle') { if (isset($this->entityKeys[$key])) { unset($this->entityKeys[$key]); diff -r e200cb7efeb3 -r c2387f117808 core/lib/Drupal/Core/Entity/ContentEntityInterface.php --- a/core/lib/Drupal/Core/Entity/ContentEntityInterface.php Thu Apr 26 11:26:54 2018 +0100 +++ b/core/lib/Drupal/Core/Entity/ContentEntityInterface.php Tue Jul 10 15:07:59 2018 +0100 @@ -5,16 +5,19 @@ /** * Defines a common interface for all content entity objects. * - * Content entities use fields for all their entity properties and are - * translatable and revisionable, while translations and revisions can be - * enabled per entity type. It's best practice to always implement - * ContentEntityInterface for content-like entities that should be stored in - * some database, and enable/disable revisions and translations as desired. + * Content entities use fields for all their entity properties and can be + * translatable and revisionable. Translations and revisions can be + * enabled per entity type through annotation and using entity type hooks. + * + * It's best practice to always implement ContentEntityInterface for + * content-like entities that should be stored in some database, and + * enable/disable revisions and translations as desired. * * When implementing this interface which extends Traversable, make sure to list * IteratorAggregate or Iterator before this interface in the implements clause. * * @see \Drupal\Core\Entity\ContentEntityBase + * @see \Drupal\Core\Entity\EntityTypeInterface * * @ingroup entity_api */ diff -r e200cb7efeb3 -r c2387f117808 core/lib/Drupal/Core/Entity/Controller/EntityListController.php --- a/core/lib/Drupal/Core/Entity/Controller/EntityListController.php Thu Apr 26 11:26:54 2018 +0100 +++ b/core/lib/Drupal/Core/Entity/Controller/EntityListController.php Tue Jul 10 15:07:59 2018 +0100 @@ -16,7 +16,8 @@ * The entity type to render. * * @return array - * A render array as expected by drupal_render(). + * A render array as expected by + * \Drupal\Core\Render\RendererInterface::render(). */ public function listing($entity_type) { return $this->entityManager()->getListBuilder($entity_type)->render(); diff -r e200cb7efeb3 -r c2387f117808 core/lib/Drupal/Core/Entity/Controller/EntityViewController.php --- a/core/lib/Drupal/Core/Entity/Controller/EntityViewController.php Thu Apr 26 11:26:54 2018 +0100 +++ b/core/lib/Drupal/Core/Entity/Controller/EntityViewController.php Tue Jul 10 15:07:59 2018 +0100 @@ -88,7 +88,8 @@ * Defaults to 'full'. * * @return array - * A render array as expected by drupal_render(). + * A render array as expected by + * \Drupal\Core\Render\RendererInterface::render(). */ public function view(EntityInterface $_entity, $view_mode = 'full') { $page = $this->entityManager diff -r e200cb7efeb3 -r c2387f117808 core/lib/Drupal/Core/Entity/Entity.php --- a/core/lib/Drupal/Core/Entity/Entity.php Thu Apr 26 11:26:54 2018 +0100 +++ b/core/lib/Drupal/Core/Entity/Entity.php Tue Jul 10 15:07:59 2018 +0100 @@ -13,6 +13,7 @@ use Drupal\Core\Link; use Drupal\Core\Session\AccountInterface; use Drupal\Core\Url; +use Symfony\Component\Routing\Exception\MissingMandatoryParametersException; use Symfony\Component\Routing\Exception\RouteNotFoundException; /** @@ -344,6 +345,9 @@ catch (RouteNotFoundException $e) { return FALSE; } + catch (MissingMandatoryParametersException $e) { + return FALSE; + } return TRUE; }); } diff -r e200cb7efeb3 -r c2387f117808 core/lib/Drupal/Core/Entity/EntityForm.php --- a/core/lib/Drupal/Core/Entity/EntityForm.php Thu Apr 26 11:26:54 2018 +0100 +++ b/core/lib/Drupal/Core/Entity/EntityForm.php Tue Jul 10 15:07:59 2018 +0100 @@ -221,6 +221,17 @@ /** * Returns an array of supported actions for the current entity form. * + * This function generates a list of Form API elements which represent + * actions supported by the current entity form. + * + * @param array $form + * An associative array containing the structure of the form. + * @param \Drupal\Core\Form\FormStateInterface $form_state + * The current state of the form. + * + * @return array + * An array of supported Form API action elements keyed by name. + * * @todo Consider introducing a 'preview' action here, since it is used by * many entity types. */ diff -r e200cb7efeb3 -r c2387f117808 core/lib/Drupal/Core/Entity/EntityListBuilderInterface.php --- a/core/lib/Drupal/Core/Entity/EntityListBuilderInterface.php Thu Apr 26 11:26:54 2018 +0100 +++ b/core/lib/Drupal/Core/Entity/EntityListBuilderInterface.php Tue Jul 10 15:07:59 2018 +0100 @@ -47,7 +47,8 @@ * Builds a listing of entities for the given entity type. * * @return array - * A render array as expected by drupal_render(). + * A render array as expected by + * \Drupal\Core\Render\RendererInterface::render(). */ public function render(); diff -r e200cb7efeb3 -r c2387f117808 core/lib/Drupal/Core/Entity/EntityManager.php --- a/core/lib/Drupal/Core/Entity/EntityManager.php Thu Apr 26 11:26:54 2018 +0100 +++ b/core/lib/Drupal/Core/Entity/EntityManager.php Tue Jul 10 15:07:59 2018 +0100 @@ -303,7 +303,7 @@ * {@inheritdoc} * * @deprecated in Drupal 8.0.0, will be removed before Drupal 9.0.0. - * Use \Drupal\Core\Entity\EntityTypeBundleManagerInterface::clearCachedBundles() + * Use \Drupal\Core\Entity\EntityTypeBundleInfoInterface::clearCachedBundles() * instead. * * @see https://www.drupal.org/node/2549139 @@ -316,7 +316,7 @@ * {@inheritdoc} * * @deprecated in Drupal 8.0.0, will be removed before Drupal 9.0.0. - * Use \Drupal\Core\Entity\EntityTypeBundleManagerInterface::getBundleInfo() + * Use \Drupal\Core\Entity\EntityTypeBundleInfoInterface::getBundleInfo() * instead. * * @see https://www.drupal.org/node/2549139 @@ -329,7 +329,7 @@ * {@inheritdoc} * * @deprecated in Drupal 8.0.0, will be removed before Drupal 9.0.0. - * Use \Drupal\Core\Entity\EntityTypeBundleManagerInterface::getAllBundleInfo() + * Use \Drupal\Core\Entity\EntityTypeBundleInfoInterface::getAllBundleInfo() * instead. * * @see https://www.drupal.org/node/2549139 diff -r e200cb7efeb3 -r c2387f117808 core/lib/Drupal/Core/Entity/EntityStorageBase.php --- a/core/lib/Drupal/Core/Entity/EntityStorageBase.php Thu Apr 26 11:26:54 2018 +0100 +++ b/core/lib/Drupal/Core/Entity/EntityStorageBase.php Tue Jul 10 15:07:59 2018 +0100 @@ -541,4 +541,16 @@ */ abstract protected function getQueryServiceName(); + /** + * {@inheritdoc} + */ + public function __sleep() { + // In case the storage is being serialized then we prevent from serializing + // the static cache of entities together with it, as this could lead to a + // memory leak. + $vars = parent::__sleep(); + unset($vars['entities']); + return $vars; + } + } diff -r e200cb7efeb3 -r c2387f117808 core/lib/Drupal/Core/Entity/EntityTypeInterface.php --- a/core/lib/Drupal/Core/Entity/EntityTypeInterface.php Thu Apr 26 11:26:54 2018 +0100 +++ b/core/lib/Drupal/Core/Entity/EntityTypeInterface.php Tue Jul 10 15:07:59 2018 +0100 @@ -7,10 +7,19 @@ /** * Provides an interface for an entity type and its metadata. * - * Additional information can be provided by modules: hook_entity_type_build() can be - * implemented to define new properties, while hook_entity_type_alter() can be - * implemented to alter existing data and fill-in defaults. Module-specific - * properties should be documented in the hook implementations defining them. + * Entity type classes can provide docblock annotations. The entity type manager + * will use these annotations to populate the entity type object with + * properties. + * + * Additional properties can be defined by module implementations of + * hook_entity_type_build(). Existing data can be altered in implementations of + * hook_entity_type_alter(), which can also be used to fill in defaults. + * Module-specific properties should be documented in the hook implementations + * defining them. + * + * @see \Drupal\Core\Entity\EntityTypeManagerInterface + * @see hook_entity_type_build() + * @see hook_entity_type_alter() */ interface EntityTypeInterface extends PluginDefinitionInterface { @@ -326,10 +335,10 @@ public function getAccessControlClass(); /** - * Gets the access class. + * Sets the access control handler class. * * @param string $class - * The class for this entity type's access. + * The class for this entity type's access control handler. * * @return $this */ diff -r e200cb7efeb3 -r c2387f117808 core/lib/Drupal/Core/Entity/EntityTypeManagerInterface.php --- a/core/lib/Drupal/Core/Entity/EntityTypeManagerInterface.php Thu Apr 26 11:26:54 2018 +0100 +++ b/core/lib/Drupal/Core/Entity/EntityTypeManagerInterface.php Tue Jul 10 15:07:59 2018 +0100 @@ -30,7 +30,10 @@ * @return \Drupal\Core\Entity\EntityStorageInterface * A storage instance. * + * @throws \Drupal\Component\Plugin\Exception\PluginNotFoundException + * Thrown if the entity type doesn't exist. * @throws \Drupal\Component\Plugin\Exception\InvalidPluginDefinitionException + * Thrown if the storage handler couldn't be loaded. */ public function getStorage($entity_type); diff -r e200cb7efeb3 -r c2387f117808 core/lib/Drupal/Core/Entity/EntityViewBuilder.php --- a/core/lib/Drupal/Core/Entity/EntityViewBuilder.php Thu Apr 26 11:26:54 2018 +0100 +++ b/core/lib/Drupal/Core/Entity/EntityViewBuilder.php Tue Jul 10 15:07:59 2018 +0100 @@ -213,7 +213,7 @@ * @return array * The updated renderable array. * - * @see drupal_render() + * @see \Drupal\Core\Render\RendererInterface::render() */ public function build(array $build) { $build_list = [$build]; @@ -237,7 +237,7 @@ * @return array * The updated renderable array. * - * @see drupal_render() + * @see \Drupal\Core\Render\RendererInterface::render() */ public function buildMultiple(array $build_list) { // Build the view modes and display objects. diff -r e200cb7efeb3 -r c2387f117808 core/lib/Drupal/Core/Entity/Query/Sql/Condition.php --- a/core/lib/Drupal/Core/Entity/Query/Sql/Condition.php Thu Apr 26 11:26:54 2018 +0100 +++ b/core/lib/Drupal/Core/Entity/Query/Sql/Condition.php Tue Jul 10 15:07:59 2018 +0100 @@ -13,6 +13,13 @@ class Condition extends ConditionBase { /** + * Whether this condition is nested inside an OR condition. + * + * @var bool + */ + protected $nestedInsideOrCondition = FALSE; + + /** * The SQL entity query object this condition belongs to. * * @var \Drupal\Core\Entity\Query\Sql\Query @@ -36,11 +43,12 @@ $sql_condition = new SqlCondition($condition['field']->getConjunction()); // Add the SQL query to the object before calling this method again. $sql_condition->sqlQuery = $sql_query; + $condition['field']->nestedInsideOrCondition = $this->nestedInsideOrCondition || strtoupper($this->conjunction) === 'OR'; $condition['field']->compile($sql_condition); $conditionContainer->condition($sql_condition); } else { - $type = strtoupper($this->conjunction) == 'OR' || $condition['operator'] == 'IS NULL' ? 'LEFT' : 'INNER'; + $type = $this->nestedInsideOrCondition || strtoupper($this->conjunction) === 'OR' || $condition['operator'] === 'IS NULL' ? 'LEFT' : 'INNER'; $field = $tables->addField($condition['field'], $type, $condition['langcode']); $condition['real_field'] = $field; static::translateCondition($condition, $sql_query, $tables->isFieldCaseSensitive($condition['field'])); diff -r e200cb7efeb3 -r c2387f117808 core/lib/Drupal/Core/Entity/Query/Sql/Tables.php --- a/core/lib/Drupal/Core/Entity/Query/Sql/Tables.php Thu Apr 26 11:26:54 2018 +0100 +++ b/core/lib/Drupal/Core/Entity/Query/Sql/Tables.php Tue Jul 10 15:07:59 2018 +0100 @@ -414,8 +414,10 @@ * @param string $table * The table name. * - * @return array|bool - * The table field mapping for the given table or FALSE if not available. + * @return array|false + * An associative array of table field mapping for the given table, keyed by + * columns name and values are just incrementing integers. If the table + * mapping is not available, FALSE is returned. */ protected function getTableMapping($table, $entity_type_id) { $storage = $this->entityManager->getStorage($entity_type_id); diff -r e200cb7efeb3 -r c2387f117808 core/lib/Drupal/Core/Entity/RevisionableInterface.php --- a/core/lib/Drupal/Core/Entity/RevisionableInterface.php Thu Apr 26 11:26:54 2018 +0100 +++ b/core/lib/Drupal/Core/Entity/RevisionableInterface.php Tue Jul 10 15:07:59 2018 +0100 @@ -4,6 +4,21 @@ /** * Provides methods for an entity to support revisions. + * + * Classes implementing this interface do not necessarily support revisions. + * + * To detect whether an entity type supports revisions, call + * EntityTypeInterface::isRevisionable(). + * + * Many entity interfaces are composed of numerous other interfaces such as this + * one, which allow implementations to pick and choose which features to. + * support through stub implementations of various interface methods. This means + * that even if an entity class implements RevisionableInterface, it might only + * have a stub implementation and not a functional one. + * + * @see \Drupal\Core\Entity\EntityTypeInterface::isRevisionable() + * @see https://www.drupal.org/docs/8/api/entity-api/structure-of-an-entity-annotation + * @see https://www.drupal.org/docs/8/api/entity-api/making-an-entity-revisionable */ interface RevisionableInterface { diff -r e200cb7efeb3 -r c2387f117808 core/lib/Drupal/Core/Entity/Sql/DefaultTableMapping.php --- a/core/lib/Drupal/Core/Entity/Sql/DefaultTableMapping.php Thu Apr 26 11:26:54 2018 +0100 +++ b/core/lib/Drupal/Core/Entity/Sql/DefaultTableMapping.php Tue Jul 10 15:07:59 2018 +0100 @@ -269,7 +269,7 @@ * The field storage definition. * * @return bool - * TRUE if the field can be stored in a dedicated table, FALSE otherwise. + * TRUE if the field can be stored in a shared table, FALSE otherwise. */ public function allowsSharedTableStorage(FieldStorageDefinitionInterface $storage_definition) { return !$storage_definition->hasCustomStorage() && $storage_definition->isBaseField() && !$storage_definition->isMultiple() && !$storage_definition->isDeleted(); @@ -282,7 +282,7 @@ * The field storage definition. * * @return bool - * TRUE if the field can be stored in a dedicated table, FALSE otherwise. + * TRUE if the field has to be stored in a dedicated table, FALSE otherwise. */ public function requiresDedicatedTableStorage(FieldStorageDefinitionInterface $storage_definition) { return !$storage_definition->hasCustomStorage() && !$this->allowsSharedTableStorage($storage_definition); diff -r e200cb7efeb3 -r c2387f117808 core/lib/Drupal/Core/Entity/Sql/SqlContentEntityStorageSchema.php --- a/core/lib/Drupal/Core/Entity/Sql/SqlContentEntityStorageSchema.php Thu Apr 26 11:26:54 2018 +0100 +++ b/core/lib/Drupal/Core/Entity/Sql/SqlContentEntityStorageSchema.php Tue Jul 10 15:07:59 2018 +0100 @@ -1621,7 +1621,7 @@ } $column_schema = $original_schema[$table_name]['fields'][$column_name]; $column_schema['not null'] = $not_null; - $schema_handler->changeField($table_name, $field_name, $field_name, $column_schema); + $schema_handler->changeField($table_name, $column_name, $column_name, $column_schema); } } @@ -1881,7 +1881,7 @@ if ($initial_value && isset($initial_value[$field_column_name])) { $schema['fields'][$schema_field_name]['initial'] = drupal_schema_get_field_value($column_schema, $initial_value[$field_column_name]); } - elseif (!empty($initial_value_from_field)) { + if (!empty($initial_value_from_field)) { $schema['fields'][$schema_field_name]['initial_from_field'] = $initial_value_from_field[$field_column_name]; } } diff -r e200cb7efeb3 -r c2387f117808 core/lib/Drupal/Core/Entity/Sql/SqlContentEntityStorageSchemaConverter.php --- a/core/lib/Drupal/Core/Entity/Sql/SqlContentEntityStorageSchemaConverter.php Thu Apr 26 11:26:54 2018 +0100 +++ b/core/lib/Drupal/Core/Entity/Sql/SqlContentEntityStorageSchemaConverter.php Tue Jul 10 15:07:59 2018 +0100 @@ -296,7 +296,9 @@ // Set the 'revision_translation_affected' flag to TRUE to match the // previous API return value: if the field was not defined the value // returned was always TRUE. - $entity->set($revision_translation_affected_key, TRUE); + if ($temporary_entity_type->isTranslatable()) { + $entity->set($revision_translation_affected_key, TRUE); + } // Treat the entity as new in order to make the storage do an INSERT // rather than an UPDATE. diff -r e200cb7efeb3 -r c2387f117808 core/lib/Drupal/Core/Entity/entity.api.php --- a/core/lib/Drupal/Core/Entity/entity.api.php Thu Apr 26 11:26:54 2018 +0100 +++ b/core/lib/Drupal/Core/Entity/entity.api.php Tue Jul 10 15:07:59 2018 +0100 @@ -590,7 +590,7 @@ * // rules will be used. * $build = $view_builder->view($entity, 'view_mode_name', $language->getId()); * // $build is a render array. - * $rendered = drupal_render($build); + * $rendered = \Drupal::service('renderer')->render($build); * @endcode * * @section sec_access Access checking on entities @@ -1359,7 +1359,8 @@ * @param &$build * A renderable array representing the entity content. The module may add * elements to $build prior to rendering. The structure of $build is a - * renderable array as expected by drupal_render(). + * renderable array as expected by + * \Drupal\Core\Render\RendererInterface::render(). * @param \Drupal\Core\Entity\EntityInterface $entity * The entity object. * @param \Drupal\Core\Entity\Display\EntityViewDisplayInterface $display @@ -1391,7 +1392,8 @@ * @param &$build * A renderable array representing the entity content. The module may add * elements to $build prior to rendering. The structure of $build is a - * renderable array as expected by drupal_render(). + * renderable array as expected by + * \Drupal\Core\Render\RendererInterface::render(). * @param \Drupal\Core\Entity\EntityInterface $entity * The entity object. * @param \Drupal\Core\Entity\Display\EntityViewDisplayInterface $display @@ -1569,7 +1571,7 @@ * @param string $view_mode * The view_mode that is to be used to display the entity. * - * @see drupal_render() + * @see \Drupal\Core\Render\RendererInterface::render() * @see \Drupal\Core\Entity\EntityViewBuilder * @see hook_entity_build_defaults_alter() * @@ -1593,7 +1595,7 @@ * @param string $view_mode * The view_mode that is to be used to display the entity. * - * @see drupal_render() + * @see \Drupal\Core\Render\RendererInterface::render() * @see \Drupal\Core\Entity\EntityViewBuilder * @see hook_ENTITY_TYPE_build_defaults_alter() * @@ -1953,8 +1955,9 @@ * @param \Drupal\Core\Session\AccountInterface $account * The user account to check. * @param \Drupal\Core\Field\FieldItemListInterface $items - * (optional) The entity field object on which the operation is to be - * performed. + * (optional) The entity field object for which to check access, or NULL if + * access is checked for the field definition, without any specific value + * available. Defaults to NULL. * * @return \Drupal\Core\Access\AccessResultInterface * The access result. diff -r e200cb7efeb3 -r c2387f117808 core/lib/Drupal/Core/EventSubscriber/ActiveLinkResponseFilter.php --- a/core/lib/Drupal/Core/EventSubscriber/ActiveLinkResponseFilter.php Thu Apr 26 11:26:54 2018 +0100 +++ b/core/lib/Drupal/Core/EventSubscriber/ActiveLinkResponseFilter.php Tue Jul 10 15:07:59 2018 +0100 @@ -127,6 +127,9 @@ $search_key_current_path = 'data-drupal-link-system-path="' . $current_path . '"'; $search_key_front = 'data-drupal-link-system-path="<front>"'; + // Receive the query in a standardized manner. + ksort($query); + $offset = 0; // There are two distinct conditions that can make a link be marked active: // 1. A link has the current path in its 'data-drupal-link-system-path' diff -r e200cb7efeb3 -r c2387f117808 core/lib/Drupal/Core/Field/BaseFieldDefinition.php --- a/core/lib/Drupal/Core/Field/BaseFieldDefinition.php Thu Apr 26 11:26:54 2018 +0100 +++ b/core/lib/Drupal/Core/Field/BaseFieldDefinition.php Tue Jul 10 15:07:59 2018 +0100 @@ -232,7 +232,9 @@ * {@inheritdoc} */ public function isRevisionable() { - return !empty($this->definition['revisionable']); + // Multi-valued base fields are always considered revisionable, just like + // configurable fields. + return !empty($this->definition['revisionable']) || $this->isMultiple(); } /** @@ -263,6 +265,10 @@ * Possible values are positive integers or * FieldStorageDefinitionInterface::CARDINALITY_UNLIMITED. * + * Note that if the entity type that this base field is attached to is + * revisionable and the field has a cardinality higher than 1, the field is + * considered revisionable by default. + * * @param int $cardinality * The field cardinality. * @@ -582,12 +588,24 @@ * * @param string $field_name * The name of the field that will be used for getting initial values. + * @param mixed $default_value + * (optional) The default value for the field, in case the inherited value + * is NULL. This can be either: + * - a literal, in which case it will be assigned to the first property of + * the first item; + * - a numerically indexed array of items, each item being a property/value + * array; + * - a non-numerically indexed array, in which case the array is assumed to + * be a property/value array and used as the first item; + * - an empty array for no initial value. + * If the field being added is required or an entity key, it is recommended + * to provide a default value. * * @return $this */ - public function setInitialValueFromField($field_name) { + public function setInitialValueFromField($field_name, $default_value = NULL) { $this->definition['initial_value_from_field'] = $field_name; - + $this->setInitialValue($default_value); return $this; } diff -r e200cb7efeb3 -r c2387f117808 core/lib/Drupal/Core/Field/EntityReferenceFieldItemList.php --- a/core/lib/Drupal/Core/Field/EntityReferenceFieldItemList.php Thu Apr 26 11:26:54 2018 +0100 +++ b/core/lib/Drupal/Core/Field/EntityReferenceFieldItemList.php Tue Jul 10 15:07:59 2018 +0100 @@ -24,7 +24,7 @@ * {@inheritdoc} */ public function referencedEntities() { - if (empty($this->list)) { + if ($this->isEmpty()) { return []; } diff -r e200cb7efeb3 -r c2387f117808 core/lib/Drupal/Core/Field/FieldItemInterface.php --- a/core/lib/Drupal/Core/Field/FieldItemInterface.php Thu Apr 26 11:26:54 2018 +0100 +++ b/core/lib/Drupal/Core/Field/FieldItemInterface.php Tue Jul 10 15:07:59 2018 +0100 @@ -38,8 +38,8 @@ * Returns the name of the main property, if any. * * Some field items consist mainly of one main property, e.g. the value of a - * text field or the @code target_id @endcode of an entity reference. If the - * field item has no main property, the method returns NULL. + * text field or the target_id of an entity reference. If the field item has + * no main property, the method returns NULL. * * @return string|null * The name of the value property, or NULL if there is none. diff -r e200cb7efeb3 -r c2387f117808 core/lib/Drupal/Core/Field/FieldItemListInterface.php --- a/core/lib/Drupal/Core/Field/FieldItemListInterface.php Thu Apr 26 11:26:54 2018 +0100 +++ b/core/lib/Drupal/Core/Field/FieldItemListInterface.php Tue Jul 10 15:07:59 2018 +0100 @@ -30,7 +30,7 @@ /** * Gets the entity that field belongs to. * - * @return \Drupal\Core\Entity\EntityInterface + * @return \Drupal\Core\Entity\FieldableEntityInterface * The entity object. */ public function getEntity(); diff -r e200cb7efeb3 -r c2387f117808 core/lib/Drupal/Core/Field/FieldStorageDefinitionInterface.php --- a/core/lib/Drupal/Core/Field/FieldStorageDefinitionInterface.php Thu Apr 26 11:26:54 2018 +0100 +++ b/core/lib/Drupal/Core/Field/FieldStorageDefinitionInterface.php Tue Jul 10 15:07:59 2018 +0100 @@ -97,7 +97,11 @@ public function setTranslatable($translatable); /** - * Returns whether the field is revisionable. + * Returns whether the field storage is revisionable. + * + * Note that if the entity type is revisionable and the field storage has a + * cardinality higher than 1, the field storage is considered revisionable + * by default. * * @return bool * TRUE if the field is revisionable. diff -r e200cb7efeb3 -r c2387f117808 core/lib/Drupal/Core/Field/Plugin/Field/FieldFormatter/EntityReferenceEntityFormatter.php --- a/core/lib/Drupal/Core/Field/Plugin/Field/FieldFormatter/EntityReferenceEntityFormatter.php Thu Apr 26 11:26:54 2018 +0100 +++ b/core/lib/Drupal/Core/Field/Plugin/Field/FieldFormatter/EntityReferenceEntityFormatter.php Tue Jul 10 15:07:59 2018 +0100 @@ -47,7 +47,7 @@ protected $entityTypeManager; /** - * The entity type manager. + * The entity display repository. * * @var \Drupal\Core\Entity\EntityDisplayRepositoryInterface */ diff -r e200cb7efeb3 -r c2387f117808 core/lib/Drupal/Core/Field/Plugin/Field/FieldType/EntityReferenceItem.php --- a/core/lib/Drupal/Core/Field/Plugin/Field/FieldType/EntityReferenceItem.php Thu Apr 26 11:26:54 2018 +0100 +++ b/core/lib/Drupal/Core/Field/Plugin/Field/FieldType/EntityReferenceItem.php Tue Jul 10 15:07:59 2018 +0100 @@ -272,6 +272,10 @@ * {@inheritdoc} */ public static function generateSampleValue(FieldDefinitionInterface $field_definition) { + // An associative array keyed by the reference type, target type, and + // bundle. + static $recursion_tracker = []; + $manager = \Drupal::service('plugin.manager.entity_reference_selection'); // Instead of calling $manager->getSelectionHandler($field_definition) @@ -300,9 +304,25 @@ // Attempt to create a sample entity, avoiding recursion. $entity_storage = \Drupal::entityTypeManager()->getStorage($options['target_type']); - if ($options['target_type'] !== $field_definition->getTargetEntityTypeId() && $entity_storage instanceof ContentEntityStorageInterface) { + if ($entity_storage instanceof ContentEntityStorageInterface) { $bundle = static::getRandomBundle($entity_type, $options['handler_settings']); - $values['entity'] = $entity_storage->createWithSampleValues($bundle); + + // Track the generated entity by reference type, target type, and bundle. + $key = $field_definition->getTargetEntityTypeId() . ':' . $options['target_type'] . ':' . $bundle; + + // If entity generation was attempted but did not finish, do not continue. + if (isset($recursion_tracker[$key])) { + return []; + } + + // Mark this as an attempt at generation. + $recursion_tracker[$key] = TRUE; + + // Mark the sample entity as being a preview. + $values['entity'] = $entity_storage->createWithSampleValues($bundle, ['in_preview' => TRUE]); + + // Remove the indicator once the entity is successfully generated. + unset($recursion_tracker[$key]); return $values; } } diff -r e200cb7efeb3 -r c2387f117808 core/lib/Drupal/Core/Field/Plugin/Field/FieldType/TimestampItem.php --- a/core/lib/Drupal/Core/Field/Plugin/Field/FieldType/TimestampItem.php Thu Apr 26 11:26:54 2018 +0100 +++ b/core/lib/Drupal/Core/Field/Plugin/Field/FieldType/TimestampItem.php Tue Jul 10 15:07:59 2018 +0100 @@ -27,7 +27,6 @@ * } * } * ) - * ) */ class TimestampItem extends FieldItemBase { diff -r e200cb7efeb3 -r c2387f117808 core/lib/Drupal/Core/Form/FormBuilder.php --- a/core/lib/Drupal/Core/Form/FormBuilder.php Thu Apr 26 11:26:54 2018 +0100 +++ b/core/lib/Drupal/Core/Form/FormBuilder.php Tue Jul 10 15:07:59 2018 +0100 @@ -84,11 +84,15 @@ protected $themeManager; /** + * The form validator. + * * @var \Drupal\Core\Form\FormValidatorInterface */ protected $formValidator; /** + * The form submitter. + * * @var \Drupal\Core\Form\FormSubmitterInterface */ protected $formSubmitter; diff -r e200cb7efeb3 -r c2387f117808 core/lib/Drupal/Core/Form/FormInterface.php --- a/core/lib/Drupal/Core/Form/FormInterface.php Thu Apr 26 11:26:54 2018 +0100 +++ b/core/lib/Drupal/Core/Form/FormInterface.php Tue Jul 10 15:07:59 2018 +0100 @@ -12,6 +12,10 @@ /** * Returns a unique string identifying the form. * + * The returned ID should be a unique string that can be a valid PHP function + * name, since it's used in hook implementation names such as + * hook_form_FORM_ID_alter(). + * * @return string * The unique string identifying the form. */ diff -r e200cb7efeb3 -r c2387f117808 core/lib/Drupal/Core/Form/FormStateInterface.php --- a/core/lib/Drupal/Core/Form/FormStateInterface.php Thu Apr 26 11:26:54 2018 +0100 +++ b/core/lib/Drupal/Core/Form/FormStateInterface.php Tue Jul 10 15:07:59 2018 +0100 @@ -12,9 +12,8 @@ * examine what in the form changed when the form submission process is * complete. Furthermore, it may be used to store information related to the * processed data in the form, which will persist across page requests when the - * 'cache' or 'rebuild' flag is set. See - * \Drupal\Core\Form\FormState::$internalStorage for documentation of the - * available flags. + * 'cache' or 'rebuild' flag is set. See \Drupal\Core\Form\FormState for + * documentation of the available flags. * * @see \Drupal\Core\Form\FormBuilderInterface * @see \Drupal\Core\Form\FormValidatorInterface diff -r e200cb7efeb3 -r c2387f117808 core/lib/Drupal/Core/Installer/Form/SiteConfigureForm.php --- a/core/lib/Drupal/Core/Installer/Form/SiteConfigureForm.php Thu Apr 26 11:26:54 2018 +0100 +++ b/core/lib/Drupal/Core/Installer/Form/SiteConfigureForm.php Tue Jul 10 15:07:59 2018 +0100 @@ -6,6 +6,7 @@ use Drupal\Core\Form\ConfigFormBase; use Drupal\Core\Form\FormStateInterface; use Drupal\Core\Locale\CountryManagerInterface; +use Drupal\Core\Site\Settings; use Drupal\Core\State\StateInterface; use Drupal\user\UserStorageInterface; use Symfony\Component\DependencyInjection\ContainerInterface; @@ -133,7 +134,7 @@ // distract from the message that the Drupal installation has completed // successfully.) $post_params = $this->getRequest()->request->all(); - if (empty($post_params) && (!drupal_verify_install_file($this->root . '/' . $settings_file, FILE_EXIST | FILE_READABLE | FILE_NOT_WRITABLE) || !drupal_verify_install_file($this->root . '/' . $settings_dir, FILE_NOT_WRITABLE, 'dir'))) { + if (empty($post_params) && (Settings::get('skip_permissions_hardening') || !drupal_verify_install_file($this->root . '/' . $settings_file, FILE_EXIST | FILE_READABLE | FILE_NOT_WRITABLE) || !drupal_verify_install_file($this->root . '/' . $settings_dir, FILE_NOT_WRITABLE, 'dir'))) { drupal_set_message(t('All necessary changes to %dir and %file have been made, so you should remove write permissions to them now in order to avoid security risks. If you are unsure how to do so, consult the online handbook.', ['%dir' => $settings_dir, '%file' => $settings_file, ':handbook_url' => 'https://www.drupal.org/server-permissions']), 'warning'); } diff -r e200cb7efeb3 -r c2387f117808 core/lib/Drupal/Core/Menu/menu.api.php --- a/core/lib/Drupal/Core/Menu/menu.api.php Thu Apr 26 11:26:54 2018 +0100 +++ b/core/lib/Drupal/Core/Menu/menu.api.php Tue Jul 10 15:07:59 2018 +0100 @@ -201,7 +201,7 @@ * // Finally, build a renderable array from the transformed tree. * $menu = $menu_tree->build($tree); * - * $menu_html = drupal_render($menu); + * $menu_html = \Drupal::service('renderer')->render($menu); * @endcode * * @} @@ -302,10 +302,12 @@ * as described above. * @param string $route_name * The route name of the page. + * @param \Drupal\Core\Cache\RefinableCacheableDependencyInterface $cacheability + * The cacheability metadata for the current route's local tasks. * * @ingroup menu */ -function hook_menu_local_tasks_alter(&$data, $route_name) { +function hook_menu_local_tasks_alter(&$data, $route_name, \Drupal\Core\Cache\RefinableCacheableDependencyInterface &$cacheability) { // Add a tab linking to node/add to all pages. $data['tabs'][0]['node.add_page'] = [ @@ -320,6 +322,8 @@ ], ], ]; + // The tab we're adding is dependent on a user's access to add content. + $cacheability->addCacheTags(['user.permissions']); } /** diff -r e200cb7efeb3 -r c2387f117808 core/lib/Drupal/Core/Plugin/Context/ContextDefinition.php --- a/core/lib/Drupal/Core/Plugin/Context/ContextDefinition.php Thu Apr 26 11:26:54 2018 +0100 +++ b/core/lib/Drupal/Core/Plugin/Context/ContextDefinition.php Tue Jul 10 15:07:59 2018 +0100 @@ -273,7 +273,7 @@ if ($context->hasContextValue()) { $values = [$context->getContextData()]; } - elseif ($definition instanceof static) { + elseif ($definition instanceof self) { $values = $definition->getSampleValues(); } else { @@ -282,7 +282,14 @@ $validator = $this->getTypedDataManager()->getValidator(); foreach ($values as $value) { - $violations = $validator->validate($value, array_values($this->getConstraintObjects())); + $constraints = array_values($this->getConstraintObjects()); + $violations = $validator->validate($value, $constraints); + foreach ($violations as $delta => $violation) { + // Remove any violation that does not correspond to the constraints. + if (!in_array($violation->getConstraint(), $constraints)) { + $violations->remove($delta); + } + } // If a value has no violations then the requirement is satisfied. if (!$violations->count()) { return TRUE; diff -r e200cb7efeb3 -r c2387f117808 core/lib/Drupal/Core/Plugin/Discovery/ContainerDerivativeDiscoveryDecorator.php --- a/core/lib/Drupal/Core/Plugin/Discovery/ContainerDerivativeDiscoveryDecorator.php Thu Apr 26 11:26:54 2018 +0100 +++ b/core/lib/Drupal/Core/Plugin/Discovery/ContainerDerivativeDiscoveryDecorator.php Tue Jul 10 15:07:59 2018 +0100 @@ -4,6 +4,11 @@ use Drupal\Component\Plugin\Discovery\DerivativeDiscoveryDecorator; +/** + * Injects dependencies into derivers if they use ContainerDeriverInterface. + * + * @see \Drupal\Core\Plugin\Discovery\ContainerDeriverInterface + */ class ContainerDerivativeDiscoveryDecorator extends DerivativeDiscoveryDecorator { /** diff -r e200cb7efeb3 -r c2387f117808 core/lib/Drupal/Core/Render/Element/Link.php --- a/core/lib/Drupal/Core/Render/Element/Link.php Thu Apr 26 11:26:54 2018 +0100 +++ b/core/lib/Drupal/Core/Render/Element/Link.php Tue Jul 10 15:07:59 2018 +0100 @@ -12,15 +12,15 @@ * * Properties: * - #title: The link text. - * - #url: \Drupal\Url object containing URL information pointing to a internal - * or external link . See \Drupal\Core\Utility\LinkGeneratorInterface. + * - #url: \Drupal\Core\Url object containing URL information pointing to a + * internal or external link. See \Drupal\Core\Utility\LinkGeneratorInterface. * * Usage example: * @code * $build['examples_link'] = [ * '#title' => $this->t('Examples'), * '#type' => 'link', - * '#url' => Url::fromRoute('examples.description') + * '#url' => \Drupal\Core\Url::fromRoute('examples.description') * ]; * @endcode * diff -r e200cb7efeb3 -r c2387f117808 core/lib/Drupal/Core/Render/Element/Weight.php --- a/core/lib/Drupal/Core/Render/Element/Weight.php Thu Apr 26 11:26:54 2018 +0100 +++ b/core/lib/Drupal/Core/Render/Element/Weight.php Tue Jul 10 15:07:59 2018 +0100 @@ -59,6 +59,11 @@ for ($n = (-1 * $element['#delta']); $n <= $element['#delta']; $n++) { $weights[$n] = $n; } + $default_value = (int) $element['#default_value']; + if (!isset($weights[$default_value])) { + $weights[$default_value] = $default_value; + ksort($weights); + } $element['#options'] = $weights; $element += $element_info_manager->getInfo('select'); } diff -r e200cb7efeb3 -r c2387f117808 core/lib/Drupal/Core/Render/Renderer.php --- a/core/lib/Drupal/Core/Render/Renderer.php Thu Apr 26 11:26:54 2018 +0100 +++ b/core/lib/Drupal/Core/Render/Renderer.php Tue Jul 10 15:07:59 2018 +0100 @@ -380,7 +380,7 @@ } // All render elements support #markup and #plain_text. - if (!empty($elements['#markup']) || !empty($elements['#plain_text'])) { + if (isset($elements['#markup']) || isset($elements['#plain_text'])) { $elements = $this->ensureMarkupIsSafe($elements); } @@ -744,11 +744,7 @@ * @see \Drupal\Component\Utility\Xss::filterAdmin() */ protected function ensureMarkupIsSafe(array $elements) { - if (empty($elements['#markup']) && empty($elements['#plain_text'])) { - return $elements; - } - - if (!empty($elements['#plain_text'])) { + if (isset($elements['#plain_text'])) { $elements['#markup'] = Markup::create(Html::escape($elements['#plain_text'])); } elseif (!($elements['#markup'] instanceof MarkupInterface)) { diff -r e200cb7efeb3 -r c2387f117808 core/lib/Drupal/Core/Render/theme.api.php --- a/core/lib/Drupal/Core/Render/theme.api.php Thu Apr 26 11:26:54 2018 +0100 +++ b/core/lib/Drupal/Core/Render/theme.api.php Tue Jul 10 15:07:59 2018 +0100 @@ -765,6 +765,12 @@ /** * Render a template using the theme engine. * + * It is the theme engine's responsibility to escape variables. The only + * exception is if a variable implements + * \Drupal\Component\Render\MarkupInterface. Drupal is inherently unsafe if + * other variables are not escaped. The helper function + * theme_render_and_autoescape() may be used for this. + * * @param string $template_file * The path (relative to the Drupal root directory) to the template to be * rendered including its extension in the format 'path/to/TEMPLATE_NAME.EXT'. diff -r e200cb7efeb3 -r c2387f117808 core/lib/Drupal/Core/Routing/ContentTypeHeaderMatcher.php --- a/core/lib/Drupal/Core/Routing/ContentTypeHeaderMatcher.php Thu Apr 26 11:26:54 2018 +0100 +++ b/core/lib/Drupal/Core/Routing/ContentTypeHeaderMatcher.php Tue Jul 10 15:07:59 2018 +0100 @@ -15,10 +15,10 @@ * {@inheritdoc} */ public function filter(RouteCollection $collection, Request $request) { - // The Content-type header does not make sense on GET requests, because GET - // requests do not carry any content. Nothing to filter in this case. Same - // for all other safe methods. - if ($request->isMethodSafe(FALSE)) { + // The Content-type header does not make sense on GET or DELETE requests, + // because they do not carry any content. Nothing to filter in this case. + // Same for all other safe methods. + if ($request->isMethodSafe(FALSE) || $request->isMethod('DELETE')) { return $collection; } diff -r e200cb7efeb3 -r c2387f117808 core/lib/Drupal/Core/Routing/RequestFormatRouteFilter.php --- a/core/lib/Drupal/Core/Routing/RequestFormatRouteFilter.php Thu Apr 26 11:26:54 2018 +0100 +++ b/core/lib/Drupal/Core/Routing/RequestFormatRouteFilter.php Tue Jul 10 15:07:59 2018 +0100 @@ -4,6 +4,7 @@ use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpKernel\Exception\NotAcceptableHttpException; +use Symfony\Component\Routing\Route; use Symfony\Component\Routing\RouteCollection; /** @@ -17,7 +18,14 @@ public function filter(RouteCollection $collection, Request $request) { // Determine the request format. $default_format = static::getDefaultFormat($collection); - $format = $request->getRequestFormat($default_format); + // If the request does not specify a format then use the default. + if (is_null($request->getRequestFormat(NULL))) { + $format = $default_format; + $request->setRequestFormat($default_format); + } + else { + $format = $request->getRequestFormat($default_format); + } $routes_with_requirement = []; $routes_without_requirement = []; @@ -60,7 +68,9 @@ * * By default, use 'html' as the default format. But when there's only a * single route match, and that route specifies a '_format' requirement - * listing a single format, then use that as the default format. + * listing a single format, then use that as the default format. Also, if + * there are multiple routes which all require the same single format then + * use it. * * @param \Symfony\Component\Routing\RouteCollection $collection * The route collection to filter. @@ -69,15 +79,20 @@ * The default format. */ protected static function getDefaultFormat(RouteCollection $collection) { - $default_format = 'html'; - if ($collection->count() === 1) { - $only_route = $collection->getIterator()->current(); - $required_format = $only_route->getRequirement('_format'); - if (strpos($required_format, '|') === FALSE) { - $default_format = $required_format; - } - } - return $default_format; + // Get the set of formats across all routes in the collection. + $all_formats = array_reduce($collection->all(), function (array $carry, Route $route) { + // Routes without a '_format' requirement are assumed to require HTML. + $route_formats = !$route->hasRequirement('_format') + ? ['html'] + : explode('|', $route->getRequirement('_format')); + return array_merge($carry, $route_formats); + }, []); + $formats = array_unique(array_filter($all_formats)); + + // The default format is 'html' unless ALL routes require the same format. + return count($formats) === 1 + ? reset($formats) + : 'html'; } } diff -r e200cb7efeb3 -r c2387f117808 core/lib/Drupal/Core/Routing/RouteFilterInterface.php --- a/core/lib/Drupal/Core/Routing/RouteFilterInterface.php Thu Apr 26 11:26:54 2018 +0100 +++ b/core/lib/Drupal/Core/Routing/RouteFilterInterface.php Tue Jul 10 15:07:59 2018 +0100 @@ -4,7 +4,7 @@ use Symfony\Component\Routing\Route; -@trigger_error('\Drupal\Core\Routing\Enhancer\RouteFilterInterface is deprecated in Drupal 8.5.0 and will be removed before Drupal 9.0.0. Instead, you should use \Drupal\Core\Routing\FilterInterface. See https://www.drupal.org/node/2894934', E_USER_DEPRECATED); +@trigger_error('\Drupal\Core\Routing\RouteFilterInterface is deprecated in Drupal 8.5.0 and will be removed before Drupal 9.0.0. Instead, you should use \Drupal\Core\Routing\FilterInterface. See https://www.drupal.org/node/2894934', E_USER_DEPRECATED); /** * A route filter service to filter down the collection of route instances. diff -r e200cb7efeb3 -r c2387f117808 core/lib/Drupal/Core/Security/RequestSanitizer.php --- a/core/lib/Drupal/Core/Security/RequestSanitizer.php Thu Apr 26 11:26:54 2018 +0100 +++ b/core/lib/Drupal/Core/Security/RequestSanitizer.php Tue Jul 10 15:07:59 2018 +0100 @@ -34,7 +34,7 @@ * @param string[] $whitelist * An array of keys to whitelist as safe. See default.settings.php. * @param bool $log_sanitized_keys - * (optional) Set to TRUE to log an keys that are sanitized. + * (optional) Set to TRUE to log keys that are sanitized. * * @return \Symfony\Component\HttpFoundation\Request * The sanitized request. diff -r e200cb7efeb3 -r c2387f117808 core/lib/Drupal/Core/StackMiddleware/NegotiationMiddleware.php --- a/core/lib/Drupal/Core/StackMiddleware/NegotiationMiddleware.php Thu Apr 26 11:26:54 2018 +0100 +++ b/core/lib/Drupal/Core/StackMiddleware/NegotiationMiddleware.php Tue Jul 10 15:07:59 2018 +0100 @@ -46,7 +46,9 @@ } // Determine the request format using the negotiator. - $request->setRequestFormat($this->getContentType($request)); + if ($requested_format = $this->getContentType($request)) { + $request->setRequestFormat($requested_format); + } return $this->app->handle($request, $type, $catch); } @@ -88,8 +90,8 @@ return $request->query->get('_format'); } - // Do HTML last so that it always wins. - return 'html'; + // No format was specified in the request. + return NULL; } } diff -r e200cb7efeb3 -r c2387f117808 core/lib/Drupal/Core/TempStore/PrivateTempStore.php --- a/core/lib/Drupal/Core/TempStore/PrivateTempStore.php Thu Apr 26 11:26:54 2018 +0100 +++ b/core/lib/Drupal/Core/TempStore/PrivateTempStore.php Tue Jul 10 15:07:59 2018 +0100 @@ -117,6 +117,18 @@ * Thrown when a lock for the backend storage could not be acquired. */ public function set($key, $value) { + // Ensure that an anonymous user has a session created for them, as + // otherwise subsequent page loads will not be able to retrieve their + // tempstore data. + if ($this->currentUser->isAnonymous()) { + // @todo when https://www.drupal.org/node/2865991 is resolved, use force + // start session API rather than setting an arbitrary value directly. + $this->requestStack + ->getCurrentRequest() + ->getSession() + ->set('core.tempstore.private', TRUE); + } + $key = $this->createkey($key); if (!$this->lockBackend->acquire($key)) { $this->lockBackend->wait($key); diff -r e200cb7efeb3 -r c2387f117808 core/lib/Drupal/Core/Template/Loader/ThemeRegistryLoader.php --- a/core/lib/Drupal/Core/Template/Loader/ThemeRegistryLoader.php Thu Apr 26 11:26:54 2018 +0100 +++ b/core/lib/Drupal/Core/Template/Loader/ThemeRegistryLoader.php Tue Jul 10 15:07:59 2018 +0100 @@ -36,8 +36,8 @@ * @param bool $throw * Whether to throw an exception when an error occurs. * - * @return string - * The path to the template. + * @return string|false + * The path to the template, or false if the template is not found. * * @throws \Twig_Error_Loader * Thrown if a template matching $name cannot be found. @@ -63,6 +63,8 @@ if ($throw) { throw new \Twig_Error_Loader(sprintf('Unable to find template "%s" in the Drupal theme registry.', $name)); } + + return FALSE; } } diff -r e200cb7efeb3 -r c2387f117808 core/lib/Drupal/Core/Template/TwigSandboxPolicy.php --- a/core/lib/Drupal/Core/Template/TwigSandboxPolicy.php Thu Apr 26 11:26:54 2018 +0100 +++ b/core/lib/Drupal/Core/Template/TwigSandboxPolicy.php Tue Jul 10 15:07:59 2018 +0100 @@ -17,19 +17,25 @@ /** * An array of whitelisted methods in the form of methodName => TRUE. + * + * @var array */ - protected $whitelisted_methods = NULL; + protected $whitelisted_methods; /** * An array of whitelisted method prefixes -- any method starting with one of * these prefixes will be allowed. + * + * @var array */ - protected $whitelisted_prefixes = NULL; + protected $whitelisted_prefixes; /** * An array of class names for which any method calls are allowed. + * + * @var array */ - protected $whitelisted_classes = NULL; + protected $whitelisted_classes; /** * Constructs a new TwigSandboxPolicy object. diff -r e200cb7efeb3 -r c2387f117808 core/lib/Drupal/Core/TypedData/DataDefinition.php --- a/core/lib/Drupal/Core/TypedData/DataDefinition.php Thu Apr 26 11:26:54 2018 +0100 +++ b/core/lib/Drupal/Core/TypedData/DataDefinition.php Tue Jul 10 15:07:59 2018 +0100 @@ -273,7 +273,14 @@ } /** - * {@inheritdoc} + * Sets an array of validation constraints. + * + * @param array $constraints + * An array of validation constraint definitions, keyed by constraint name. + * Each constraint definition can be used for instantiating + * \Symfony\Component\Validator\Constraint objects. + * + * @return $this */ public function setConstraints(array $constraints) { $this->definition['constraints'] = $constraints; diff -r e200cb7efeb3 -r c2387f117808 core/lib/Drupal/Core/TypedData/TranslatableInterface.php --- a/core/lib/Drupal/Core/TypedData/TranslatableInterface.php Thu Apr 26 11:26:54 2018 +0100 +++ b/core/lib/Drupal/Core/TypedData/TranslatableInterface.php Tue Jul 10 15:07:59 2018 +0100 @@ -4,6 +4,21 @@ /** * Interface for translatable data. + * + * Classes implementing this interface do not necessarily support translations. + * + * To detect whether an entity type supports translation, call + * EntityTypeInterface::isTranslatable(). + * + * Many entity interfaces are composed of numerous other interfaces such as this + * one, which allow implementations to pick and choose which features to support + * through stub implementations of various interface methods. This means that + * even if an entity class implements TranslatableInterface, it might only have + * a stub implementation and not a functional one. + * + * @see \Drupal\Core\Entity\EntityTypeInterface::isTranslatable() + * @see https://www.drupal.org/docs/8/api/entity-api/structure-of-an-entity-annotation + * @see https://www.drupal.org/docs/8/api/entity-api/entity-translation-api */ interface TranslatableInterface { diff -r e200cb7efeb3 -r c2387f117808 core/lib/Drupal/Core/Update/UpdateKernel.php --- a/core/lib/Drupal/Core/Update/UpdateKernel.php Thu Apr 26 11:26:54 2018 +0100 +++ b/core/lib/Drupal/Core/Update/UpdateKernel.php Tue Jul 10 15:07:59 2018 +0100 @@ -182,7 +182,7 @@ $db_update_access = $this->getContainer()->get('access_check.db_update'); if (!Settings::get('update_free_access', FALSE) && !$db_update_access->access($account)->isAllowed()) { - throw new AccessDeniedHttpException('In order to run update.php you need to either be logged in as admin or have set $settings[\'update_free_access\'] in your settings.php.'); + throw new AccessDeniedHttpException('In order to run update.php you need to either have "Administer software updates" permission or have set $settings[\'update_free_access\'] in your settings.php.'); } } diff -r e200cb7efeb3 -r c2387f117808 core/lib/Drupal/Core/Utility/UnroutedUrlAssembler.php --- a/core/lib/Drupal/Core/Utility/UnroutedUrlAssembler.php Thu Apr 26 11:26:54 2018 +0100 +++ b/core/lib/Drupal/Core/Utility/UnroutedUrlAssembler.php Tue Jul 10 15:07:59 2018 +0100 @@ -2,6 +2,7 @@ namespace Drupal\Core\Utility; +use Drupal\Component\Utility\NestedArray; use Drupal\Component\Utility\UrlHelper; use Drupal\Core\GeneratedUrl; use Drupal\Core\PathProcessor\OutboundPathProcessorInterface; @@ -69,13 +70,18 @@ */ protected function buildExternalUrl($uri, array $options = [], $collect_bubbleable_metadata = FALSE) { $this->addOptionDefaults($options); - // Split off the fragment. - if (strpos($uri, '#') !== FALSE) { - list($uri, $old_fragment) = explode('#', $uri, 2); - // If $options contains no fragment, take it over from the path. - if (isset($old_fragment) && !$options['fragment']) { - $options['fragment'] = '#' . $old_fragment; - } + // Split off the query & fragment. + $parsed = UrlHelper::parse($uri); + $uri = $parsed['path']; + + $parsed += ['query' => []]; + $options += ['query' => []]; + + $options['query'] = NestedArray::mergeDeep($parsed['query'], $options['query']); + ksort($options['query']); + + if ($parsed['fragment'] && !$options['fragment']) { + $options['fragment'] = '#' . $parsed['fragment']; } if (isset($options['https'])) { @@ -88,7 +94,7 @@ } // Append the query. if ($options['query']) { - $uri .= (strpos($uri, '?') !== FALSE ? '&' : '?') . UrlHelper::buildQuery($options['query']); + $uri .= '?' . UrlHelper::buildQuery($options['query']); } // Reassemble. $url = $uri . $options['fragment']; diff -r e200cb7efeb3 -r c2387f117808 core/misc/dropbutton/dropbutton.es6.js --- a/core/misc/dropbutton/dropbutton.es6.js Thu Apr 26 11:26:54 2018 +0100 +++ b/core/misc/dropbutton/dropbutton.es6.js Tue Jul 10 15:07:59 2018 +0100 @@ -214,7 +214,7 @@ * @param {object} options * Options object. * @param {string} [options.title] - * The HTML anchor title attribute and text for the inner span element. + * The button text. * * @return {string} * A string representing a DOM fragment. diff -r e200cb7efeb3 -r c2387f117808 core/modules/action/src/Plugin/Action/EmailAction.php --- a/core/modules/action/src/Plugin/Action/EmailAction.php Thu Apr 26 11:26:54 2018 +0100 +++ b/core/modules/action/src/Plugin/Action/EmailAction.php Tue Jul 10 15:07:59 2018 +0100 @@ -139,12 +139,11 @@ } $params = ['context' => $this->configuration]; - if ($this->mailManager->mail('system', 'action_send_email', $recipient, $langcode, $params)) { + $message = $this->mailManager->mail('system', 'action_send_email', $recipient, $langcode, $params); + // Error logging is handled by \Drupal\Core\Mail\MailManager::mail(). + if ($message['result']) { $this->logger->notice('Sent email to %recipient', ['%recipient' => $recipient]); } - else { - $this->logger->error('Unable to send email to %recipient', ['%recipient' => $recipient]); - } } /** diff -r e200cb7efeb3 -r c2387f117808 core/modules/action/tests/src/Kernel/Plugin/Action/EmailActionTest.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/core/modules/action/tests/src/Kernel/Plugin/Action/EmailActionTest.php Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,65 @@ +installEntitySchema('user'); + $this->installSchema('dblog', ['watchdog']); + } + + /** + * Test the email action plugin. + */ + public function testEmailAction() { + /** @var \Drupal\Core\Action\ActionManager $plugin_manager */ + $plugin_manager = $this->container->get('plugin.manager.action'); + $configuration = [ + 'recipient' => 'test@example.com', + 'subject' => 'Test subject', + 'message' => 'Test message' + ]; + $plugin_manager + ->createInstance('action_send_email_action', $configuration) + ->execute(); + + $mails = $this->getMails(); + $this->assertCount(1, $this->getMails()); + $this->assertEquals('test@example.com', $mails[0]['to']); + $this->assertEquals('Test subject', $mails[0]['subject']); + $this->assertEquals("Test message\n", $mails[0]['body']); + + // Ensure that the email sending is logged. + $log = \Drupal::database() + ->select('watchdog', 'w') + ->fields('w', ['message', 'variables']) + ->orderBy('wid', 'DESC') + ->range(0, 1) + ->execute() + ->fetch(); + + $this->assertEquals($log->message, 'Sent email to %recipient'); + $variables = unserialize($log->variables); + $this->assertEquals($variables['%recipient'], 'test@example.com'); + } + +} diff -r e200cb7efeb3 -r c2387f117808 core/modules/aggregator/src/Controller/AggregatorController.php --- a/core/modules/aggregator/src/Controller/AggregatorController.php Thu Apr 26 11:26:54 2018 +0100 +++ b/core/modules/aggregator/src/Controller/AggregatorController.php Tue Jul 10 15:07:59 2018 +0100 @@ -44,7 +44,8 @@ * Presents the aggregator feed creation form. * * @return array - * A form array as expected by drupal_render(). + * A form array as expected by + * \Drupal\Core\Render\RendererInterface::render(). */ public function feedAdd() { $feed = $this->entityManager()->getStorage('aggregator_feed')->create(); @@ -101,7 +102,8 @@ * Displays the aggregator administration page. * * @return array - * A render array as expected by drupal_render(). + * A render array as expected by + * \Drupal\Core\Render\RendererInterface::render(). */ public function adminOverview() { $entity_manager = $this->entityManager(); diff -r e200cb7efeb3 -r c2387f117808 core/modules/aggregator/tests/src/Functional/Hal/FeedHalJsonAnonTest.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/core/modules/aggregator/tests/src/Functional/Hal/FeedHalJsonAnonTest.php Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,19 @@ +applyHalFieldNormalization($default_normalization); + + return $normalization + [ + '_links' => [ + 'self' => [ + 'href' => $this->baseUrl . '/aggregator/sources/1?_format=hal_json' + ], + 'type' => [ + 'href' => $this->baseUrl . '/rest/type/aggregator_feed/aggregator_feed' + ], + ], + ]; + } + + /** + * {@inheritdoc} + */ + protected function getNormalizedPostEntity() { + return parent::getNormalizedPostEntity() + [ + '_links' => [ + 'type' => [ + 'href' => $this->baseUrl . '/rest/type/aggregator_feed/aggregator_feed' + ], + ], + ]; + } + +} diff -r e200cb7efeb3 -r c2387f117808 core/modules/aggregator/tests/src/Functional/Hal/ItemHalJsonAnonTest.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/core/modules/aggregator/tests/src/Functional/Hal/ItemHalJsonAnonTest.php Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,29 @@ +applyHalFieldNormalization($default_normalization); + $feed = Feed::load($this->entity->getFeedId()); + + return $normalization + [ + '_embedded' => [ + $this->baseUrl . '/rest/relation/aggregator_item/aggregator_item/fid' => [ + [ + '_links' => [ + 'self' => [ + 'href' => $this->baseUrl . '/aggregator/sources/1?_format=hal_json', + ], + 'type' => [ + 'href' => $this->baseUrl . '/rest/type/aggregator_feed/aggregator_feed', + ], + ], + 'uuid' => [ + [ + 'value' => $feed->uuid(), + ], + ], + ], + ], + ], + '_links' => [ + 'self' => [ + 'href' => '', + ], + 'type' => [ + 'href' => $this->baseUrl . '/rest/type/aggregator_item/aggregator_item', + ], + $this->baseUrl . '/rest/relation/aggregator_item/aggregator_item/fid' => [ + [ + 'href' => $this->baseUrl . '/aggregator/sources/' . $feed->id() . '?_format=hal_json', + ], + ], + ], + ]; + } + + /** + * {@inheritdoc} + */ + protected function getNormalizedPostEntity() { + return parent::getNormalizedPostEntity() + [ + '_links' => [ + 'type' => [ + 'href' => $this->baseUrl . '/rest/type/aggregator_item/aggregator_item', + ], + ], + ]; + } + + /** + * {@inheritdoc} + */ + protected function getExpectedCacheContexts() { + return [ + 'url.site', + 'user.permissions', + ]; + } + +} diff -r e200cb7efeb3 -r c2387f117808 core/modules/aggregator/tests/src/Functional/Rest/FeedJsonAnonTest.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/core/modules/aggregator/tests/src/Functional/Rest/FeedJsonAnonTest.php Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,24 @@ +grantPermissionsToTestedRole(['access news feeds']); + break; + case 'POST': + case 'PATCH': + case 'DELETE': + $this->grantPermissionsToTestedRole(['administer news feeds']); + break; + } + } + + /** + * {@inheritdoc} + */ + public function createEntity() { + $feed = Feed::create(); + $feed->set('fid', 1) + ->set('uuid', 'abcdefg') + ->setTitle('Feed') + ->setUrl('http://example.com/rss.xml') + ->setDescription('Feed Resource Test 1') + ->setRefreshRate(900) + ->setLastCheckedTime(123456789) + ->setQueuedTime(123456789) + ->setWebsiteUrl('http://example.com') + ->setImage('http://example.com/feed_logo') + ->setHash('abcdefg') + ->setEtag('hijklmn') + ->setLastModified(123456789) + ->save(); + + return $feed; + } + + /** + * {@inheritdoc} + */ + protected function getExpectedNormalizedEntity() { + return [ + 'uuid' => [ + [ + 'value' => 'abcdefg' + ] + ], + 'fid' => [ + [ + 'value' => 1 + ] + ], + 'langcode' => [ + [ + 'value' => 'en' + ] + ], + 'url' => [ + [ + 'value' => 'http://example.com/rss.xml' + ] + ], + 'title' => [ + [ + 'value' => 'Feed' + ] + ], + 'refresh' => [ + [ + 'value' => 900 + ] + ], + 'checked' => [ + $this->formatExpectedTimestampItemValues(123456789), + ], + 'queued' => [ + $this->formatExpectedTimestampItemValues(123456789), + ], + 'link' => [ + [ + 'value' => 'http://example.com' + ] + ], + 'description' => [ + [ + 'value' => 'Feed Resource Test 1' + ] + ], + 'image' => [ + [ + 'value' => 'http://example.com/feed_logo' + ] + ], + 'hash' => [ + [ + 'value' => 'abcdefg' + ] + ], + 'etag' => [ + [ + 'value' => 'hijklmn' + ] + ], + 'modified' => [ + $this->formatExpectedTimestampItemValues(123456789), + ], + ]; + } + + /** + * {@inheritdoc} + */ + protected function getNormalizedPostEntity() { + return [ + 'title' => [ + [ + 'value' => 'Feed Resource Post Test' + ] + ], + 'url' => [ + [ + 'value' => 'http://example.com/feed' + ] + ], + 'refresh' => [ + [ + 'value' => 900 + ] + ], + 'description' => [ + [ + 'value' => 'Feed Resource Post Test Description' + ] + ], + ]; + } + + /** + * {@inheritdoc} + */ + protected function getExpectedUnauthorizedAccessMessage($method) { + if ($this->config('rest.settings')->get('bc_entity_resource_permissions')) { + return parent::getExpectedUnauthorizedAccessMessage($method); + } + + switch ($method) { + case 'GET': + return "The 'access news feeds' permission is required."; + case 'POST': + case 'PATCH': + case 'DELETE': + return "The 'administer news feeds' permission is required."; + default: + return parent::getExpectedUnauthorizedAccessMessage($method); + } + } + +} diff -r e200cb7efeb3 -r c2387f117808 core/modules/aggregator/tests/src/Functional/Rest/FeedXmlAnonTest.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/core/modules/aggregator/tests/src/Functional/Rest/FeedXmlAnonTest.php Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,26 @@ +grantPermissionsToTestedRole(['access news feeds']); + break; + + case 'POST': + case 'PATCH': + case 'DELETE': + $this->grantPermissionsToTestedRole(['administer news feeds']); + break; + } + } + + /** + * {@inheritdoc} + */ + protected function createEntity() { + // Create a "Camelids" feed. + $feed = Feed::create([ + 'title' => 'Camelids', + 'url' => 'https://groups.drupal.org/not_used/167169', + 'refresh' => 900, + 'checked' => 1389919932, + 'description' => 'Drupal Core Group feed', + ]); + $feed->save(); + + // Create a "Llama" item. + $item = Item::create(); + $item->setTitle('Llama') + ->setFeedId($feed->id()) + ->setLink('https://www.drupal.org/') + ->setPostedTime(123456789) + ->save(); + + return $item; + } + + /** + * {@inheritdoc} + */ + protected function createAnotherEntity() { + $entity = $this->entity->createDuplicate(); + $entity->setLink('https://www.example.org/'); + $label_key = $entity->getEntityType()->getKey('label'); + if ($label_key) { + $entity->set($label_key, $entity->label() . '_dupe'); + } + $entity->save(); + return $entity; + } + + /** + * {@inheritdoc} + */ + protected function getExpectedNormalizedEntity() { + $feed = Feed::load($this->entity->getFeedId()); + + return [ + 'iid' => [ + [ + 'value' => 1, + ], + ], + 'langcode' => [ + [ + 'value' => 'en', + ], + ], + 'fid' => [ + [ + 'target_id' => 1, + 'target_type' => 'aggregator_feed', + 'target_uuid' => $feed->uuid(), + 'url' => base_path() . 'aggregator/sources/1', + ], + ], + 'title' => [ + [ + 'value' => 'Llama', + ], + ], + 'link' => [ + [ + 'value' => 'https://www.drupal.org/', + ], + ], + 'author' => [], + 'description' => [], + 'timestamp' => [ + $this->formatExpectedTimestampItemValues(123456789), + ], + 'guid' => [], + ]; + } + + /** + * {@inheritdoc} + */ + protected function getNormalizedPostEntity() { + return [ + 'fid' => [ + [ + 'target_id' => 1, + ], + ], + 'title' => [ + [ + 'value' => 'Llama', + ], + ], + 'link' => [ + [ + 'value' => 'https://www.drupal.org/', + ], + ], + ]; + } + + /** + * {@inheritdoc} + */ + protected function getExpectedCacheContexts() { + // @see ::createEntity() + return ['user.permissions']; + } + + /** + * {@inheritdoc} + */ + protected function getExpectedUnauthorizedAccessMessage($method) { + if ($this->config('rest.settings')->get('bc_entity_resource_permissions')) { + return parent::getExpectedUnauthorizedAccessMessage($method); + } + + switch ($method) { + case 'GET': + return "The 'access news feeds' permission is required."; + + case 'POST': + case 'PATCH': + case 'DELETE': + return "The 'administer news feeds' permission is required."; + + default: + return parent::getExpectedUnauthorizedAccessMessage($method); + } + } + +} diff -r e200cb7efeb3 -r c2387f117808 core/modules/aggregator/tests/src/Functional/Rest/ItemXmlAnonTest.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/core/modules/aggregator/tests/src/Functional/Rest/ItemXmlAnonTest.php Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,26 @@ +label() === 'some condition') { $build['#cache']['contexts'][] = 'user'; } } diff -r e200cb7efeb3 -r c2387f117808 core/modules/block/src/Controller/BlockListController.php --- a/core/modules/block/src/Controller/BlockListController.php Thu Apr 26 11:26:54 2018 +0100 +++ b/core/modules/block/src/Controller/BlockListController.php Tue Jul 10 15:07:59 2018 +0100 @@ -48,7 +48,8 @@ * The current request. * * @return array - * A render array as expected by drupal_render(). + * A render array as expected by + * \Drupal\Core\Render\RendererInterface::render(). */ public function listing($theme = NULL, Request $request = NULL) { $theme = $theme ?: $this->config('system.theme')->get('default'); diff -r e200cb7efeb3 -r c2387f117808 core/modules/block/tests/src/Functional/Hal/BlockHalJsonAnonTest.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/core/modules/block/tests/src/Functional/Hal/BlockHalJsonAnonTest.php Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,30 @@ +entity->setVisibilityConfig('user_role', [])->save(); + break; + case 'POST': + $this->grantPermissionsToTestedRole(['administer blocks']); + break; + case 'PATCH': + $this->grantPermissionsToTestedRole(['administer blocks']); + break; + } + } + + /** + * {@inheritdoc} + */ + protected function createEntity() { + $block = Block::create([ + 'plugin' => 'llama_block', + 'region' => 'header', + 'id' => 'llama', + 'theme' => 'classy', + ]); + // All blocks can be viewed by the anonymous user by default. An interesting + // side effect of this is that any anonymous user is also able to read the + // corresponding block config entity via REST, even if an authentication + // provider is configured for the block config entity REST resource! In + // other words: Block entities do not distinguish between 'view' as in + // "render on a page" and 'view' as in "read the configuration". + // This prevents that. + // @todo Fix this in https://www.drupal.org/node/2820315. + $block->setVisibilityConfig('user_role', [ + 'id' => 'user_role', + 'roles' => ['non-existing-role' => 'non-existing-role'], + 'negate' => FALSE, + 'context_mapping' => [ + 'user' => '@user.current_user_context:current_user', + ], + ]); + $block->save(); + + return $block; + } + + /** + * {@inheritdoc} + */ + protected function getExpectedNormalizedEntity() { + $normalization = [ + 'uuid' => $this->entity->uuid(), + 'id' => 'llama', + 'weight' => NULL, + 'langcode' => 'en', + 'status' => TRUE, + 'dependencies' => [ + 'theme' => [ + 'classy', + ], + ], + 'theme' => 'classy', + 'region' => 'header', + 'provider' => NULL, + 'plugin' => 'llama_block', + 'settings' => [ + 'id' => 'broken', + 'label' => '', + 'provider' => 'core', + 'label_display' => 'visible', + ], + 'visibility' => [], + ]; + + return $normalization; + } + + /** + * {@inheritdoc} + */ + protected function getNormalizedPostEntity() { + // @todo Update in https://www.drupal.org/node/2300677. + } + + /** + * {@inheritdoc} + */ + protected function getExpectedCacheContexts() { + // @see ::createEntity() + return ['url.site']; + } + + /** + * {@inheritdoc} + */ + protected function getExpectedCacheTags() { + // Because the 'user.permissions' cache context is missing, the cache tag + // for the anonymous user role is never added automatically. + return array_values(array_diff(parent::getExpectedCacheTags(), ['config:user.role.anonymous'])); + } + + /** + * {@inheritdoc} + */ + protected function getExpectedUnauthorizedAccessMessage($method) { + if ($this->config('rest.settings')->get('bc_entity_resource_permissions')) { + return parent::getExpectedUnauthorizedAccessMessage($method); + } + + switch ($method) { + case 'GET': + return "You are not authorized to view this block entity."; + default: + return parent::getExpectedUnauthorizedAccessMessage($method); + } + } + + /** + * {@inheritdoc} + */ + protected function getExpectedUnauthorizedAccessCacheability() { + // @see \Drupal\block\BlockAccessControlHandler::checkAccess() + return parent::getExpectedUnauthorizedAccessCacheability() + ->setCacheTags([ + '4xx-response', + 'config:block.block.llama', + 'http_response', + static::$auth ? 'user:2' : 'user:0', + ]) + ->setCacheContexts(['user.roles']); + } + +} diff -r e200cb7efeb3 -r c2387f117808 core/modules/block/tests/src/Functional/Rest/BlockXmlAnonTest.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/core/modules/block/tests/src/Functional/Rest/BlockXmlAnonTest.php Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,26 @@ +moduleExists('content_translation') && $definition_update_manager->getFieldStorageDefinition('content_translation_status', 'block_content'); if ($has_content_translation_status_field) { - $status->setInitialValueFromField('content_translation_status'); + $status->setInitialValueFromField('content_translation_status', TRUE); } else { $status->setInitialValue(TRUE); diff -r e200cb7efeb3 -r c2387f117808 core/modules/block_content/src/Controller/BlockContentController.php --- a/core/modules/block_content/src/Controller/BlockContentController.php Thu Apr 26 11:26:54 2018 +0100 +++ b/core/modules/block_content/src/Controller/BlockContentController.php Tue Jul 10 15:07:59 2018 +0100 @@ -98,7 +98,8 @@ * The current request object. * * @return array - * A form array as expected by drupal_render(). + * A form array as expected by + * \Drupal\Core\Render\RendererInterface::render(). */ public function addForm(BlockContentTypeInterface $block_content_type, Request $request) { $block = $this->blockContentStorage->create([ diff -r e200cb7efeb3 -r c2387f117808 core/modules/block_content/tests/src/Functional/BlockContentTranslationUITest.php --- a/core/modules/block_content/tests/src/Functional/BlockContentTranslationUITest.php Thu Apr 26 11:26:54 2018 +0100 +++ b/core/modules/block_content/tests/src/Functional/BlockContentTranslationUITest.php Tue Jul 10 15:07:59 2018 +0100 @@ -5,7 +5,7 @@ use Drupal\block_content\Entity\BlockContent; use Drupal\block_content\Entity\BlockContentType; use Drupal\Component\Utility\Unicode; -use Drupal\content_translation\Tests\ContentTranslationUITestBase; +use Drupal\Tests\content_translation\Functional\ContentTranslationUITestBase; /** * Tests the block content translation UI. diff -r e200cb7efeb3 -r c2387f117808 core/modules/block_content/tests/src/Functional/Hal/BlockContentHalJsonAnonTest.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/core/modules/block_content/tests/src/Functional/Hal/BlockContentHalJsonAnonTest.php Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,74 @@ +applyHalFieldNormalization($default_normalization); + + return $normalization + [ + '_links' => [ + 'self' => [ + 'href' => $this->baseUrl . '/block/1?_format=hal_json', + ], + 'type' => [ + 'href' => $this->baseUrl . '/rest/type/block_content/basic', + ], + ], + ]; + } + + /** + * {@inheritdoc} + */ + protected function getNormalizedPostEntity() { + return parent::getNormalizedPostEntity() + [ + '_links' => [ + 'type' => [ + 'href' => $this->baseUrl . '/rest/type/block_content/basic', + ], + ], + ]; + } + + /** + * {@inheritdoc} + */ + protected function getExpectedCacheContexts() { + // The 'url.site' cache context is added for '_links' in the response. + return Cache::mergeTags(parent::getExpectedCacheContexts(), ['url.site']); + } + +} diff -r e200cb7efeb3 -r c2387f117808 core/modules/block_content/tests/src/Functional/Hal/BlockContentHalJsonBasicAuthTest.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/core/modules/block_content/tests/src/Functional/Hal/BlockContentHalJsonBasicAuthTest.php Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,24 @@ +grantPermissionsToTestedRole(['administer blocks']); + } + + /** + * {@inheritdoc} + */ + protected function createEntity() { + if (!BlockContentType::load('basic')) { + $block_content_type = BlockContentType::create([ + 'id' => 'basic', + 'label' => 'basic', + 'revision' => TRUE, + ]); + $block_content_type->save(); + block_content_add_body_field($block_content_type->id()); + } + + // Create a "Llama" custom block. + $block_content = BlockContent::create([ + 'info' => 'Llama', + 'type' => 'basic', + 'body' => [ + 'value' => 'The name "llama" was adopted by European settlers from native Peruvians.', + 'format' => 'plain_text', + ], + ]) + ->setPublished(FALSE); + $block_content->save(); + return $block_content; + } + + /** + * {@inheritdoc} + */ + protected function getExpectedNormalizedEntity() { + return [ + 'id' => [ + [ + 'value' => 1, + ], + ], + 'uuid' => [ + [ + 'value' => $this->entity->uuid(), + ], + ], + 'langcode' => [ + [ + 'value' => 'en', + ], + ], + 'type' => [ + [ + 'target_id' => 'basic', + 'target_type' => 'block_content_type', + 'target_uuid' => BlockContentType::load('basic')->uuid(), + ], + ], + 'info' => [ + [ + 'value' => 'Llama', + ], + ], + 'revision_log' => [], + 'changed' => [ + $this->formatExpectedTimestampItemValues($this->entity->getChangedTime()), + ], + 'revision_id' => [ + [ + 'value' => 1, + ], + ], + 'revision_created' => [ + $this->formatExpectedTimestampItemValues((int) $this->entity->getRevisionCreationTime()), + ], + 'revision_user' => [], + 'revision_translation_affected' => [ + [ + 'value' => TRUE, + ], + ], + 'default_langcode' => [ + [ + 'value' => TRUE, + ], + ], + 'body' => [ + [ + 'value' => 'The name "llama" was adopted by European settlers from native Peruvians.', + 'format' => 'plain_text', + 'summary' => NULL, + 'processed' => "

The name "llama" was adopted by European settlers from native Peruvians.

\n", + ], + ], + 'status' => [ + [ + 'value' => FALSE, + ], + ], + ]; + } + + /** + * {@inheritdoc} + */ + protected function getNormalizedPostEntity() { + return [ + 'type' => [ + [ + 'target_id' => 'basic', + ], + ], + 'info' => [ + [ + 'value' => 'Dramallama', + ], + ], + ]; + } + + + /** + * {@inheritdoc} + */ + protected function getExpectedUnauthorizedAccessMessage($method) { + if ($this->config('rest.settings')->get('bc_entity_resource_permissions')) { + return parent::getExpectedUnauthorizedAccessMessage($method); + } + + return parent::getExpectedUnauthorizedAccessMessage($method); + } + + /** + * {@inheritdoc} + */ + protected function getExpectedUnauthorizedAccessCacheability() { + // @see \Drupal\block_content\BlockContentAccessControlHandler() + return parent::getExpectedUnauthorizedAccessCacheability() + ->addCacheTags(['block_content:1']); + } + + /** + * {@inheritdoc} + */ + protected function getExpectedCacheTags() { + return Cache::mergeTags(parent::getExpectedCacheTags(), ['config:filter.format.plain_text']); + } + + /** + * {@inheritdoc} + */ + protected function getExpectedCacheContexts() { + return Cache::mergeContexts(['url.site'], $this->container->getParameter('renderer.config')['required_cache_contexts']); + } + +} diff -r e200cb7efeb3 -r c2387f117808 core/modules/block_content/tests/src/Functional/Rest/BlockContentTypeJsonAnonTest.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/core/modules/block_content/tests/src/Functional/Rest/BlockContentTypeJsonAnonTest.php Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,24 @@ +grantPermissionsToTestedRole(['administer blocks']); + } + + /** + * {@inheritdoc} + */ + protected function createEntity() { + $block_content_type = BlockContentType::create([ + 'id' => 'pascal', + 'label' => 'Pascal', + 'revision' => FALSE, + 'description' => 'Provides a competitive alternative to the "basic" type', + ]); + + $block_content_type->save(); + + return $block_content_type; + } + + /** + * {@inheritdoc} + */ + protected function getExpectedNormalizedEntity() { + return [ + 'dependencies' => [], + 'description' => 'Provides a competitive alternative to the "basic" type', + 'id' => 'pascal', + 'label' => 'Pascal', + 'langcode' => 'en', + 'revision' => 0, + 'status' => TRUE, + 'uuid' => $this->entity->uuid(), + ]; + } + + /** + * {@inheritdoc} + */ + protected function getNormalizedPostEntity() { + // @todo Update in https://www.drupal.org/node/2300677. + } + +} diff -r e200cb7efeb3 -r c2387f117808 core/modules/block_content/tests/src/Functional/Rest/BlockContentTypeXmlAnonTest.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/core/modules/block_content/tests/src/Functional/Rest/BlockContentTypeXmlAnonTest.php Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,26 @@ +save(); } } + +/** + * Implements hook_migration_plugins_alter(). + */ +function book_migration_plugins_alter(array &$migrations) { + // Book settings are migrated identically for Drupal 6 and Drupal 7. However, + // a d6_book_settings migration already existed before the consolidated + // book_settings migration existed, so to maintain backwards compatibility, + // ensure that d6_book_settings is an alias of book_settings. + if (isset($migrations['book_settings'])) { + $migrations['d6_book_settings'] = &$migrations['book_settings']; + } +} diff -r e200cb7efeb3 -r c2387f117808 core/modules/book/migrations/book_settings.yml --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/core/modules/book/migrations/book_settings.yml Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,20 @@ +id: book_settings +label: Book configuration +migration_tags: + - Drupal 6 + - Drupal 7 + - Configuration +source: + plugin: variable + variables: + - book_child_type + - book_block_mode + - book_allowed_types + source_module: book +process: + child_type: book_child_type + 'block/navigation/mode': book_block_mode + allowed_types: book_allowed_types +destination: + plugin: config + config_name: book.settings diff -r e200cb7efeb3 -r c2387f117808 core/modules/book/migrations/d6_book.yml --- a/core/modules/book/migrations/d6_book.yml Thu Apr 26 11:26:54 2018 +0100 +++ b/core/modules/book/migrations/d6_book.yml Tue Jul 10 15:07:59 2018 +0100 @@ -4,7 +4,7 @@ - Drupal 6 - Content source: - plugin: d6_book + plugin: book process: nid: nid 'book/bid': bid diff -r e200cb7efeb3 -r c2387f117808 core/modules/book/migrations/d6_book_settings.yml --- a/core/modules/book/migrations/d6_book_settings.yml Thu Apr 26 11:26:54 2018 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,19 +0,0 @@ -id: d6_book_settings -label: Book configuration -migration_tags: - - Drupal 6 - - Configuration -source: - plugin: variable - variables: - - book_child_type - - book_block_mode - - book_allowed_types - source_module: book -process: - child_type: book_child_type - 'block/navigation/mode': book_block_mode - allowed_types: book_allowed_types -destination: - plugin: config - config_name: book.settings diff -r e200cb7efeb3 -r c2387f117808 core/modules/book/migrations/d7_book.yml --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/core/modules/book/migrations/d7_book.yml Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,24 @@ +id: d7_book +label: Books +migration_tags: + - Drupal 7 + - Content +source: + plugin: book +process: + nid: nid + 'book/bid': bid + 'book/weight': weight + 'book/pid': + - + plugin: skip_on_empty + method: process + source: plid + - + plugin: migration_lookup + migration: d7_book +destination: + plugin: book +migration_dependencies: + required: + - d7_node diff -r e200cb7efeb3 -r c2387f117808 core/modules/book/src/BookManagerInterface.php --- a/core/modules/book/src/BookManagerInterface.php Thu Apr 26 11:26:54 2018 +0100 +++ b/core/modules/book/src/BookManagerInterface.php Tue Jul 10 15:07:59 2018 +0100 @@ -246,7 +246,8 @@ * A data structure representing the tree as returned from buildBookOutlineData. * * @return array - * A structured array to be rendered by drupal_render(). + * A structured array to be rendered by + * \Drupal\Core\Render\RendererInterface::render(). * * @see \Drupal\Core\Menu\MenuLinkTree::build */ diff -r e200cb7efeb3 -r c2387f117808 core/modules/book/src/Plugin/migrate/source/Book.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/core/modules/book/src/Plugin/migrate/source/Book.php Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,63 @@ +select('book', 'b')->fields('b', ['nid', 'bid']); + $query->join('menu_links', 'ml', 'b.mlid = ml.mlid'); + $ml_fields = ['mlid', 'plid', 'weight', 'has_children', 'depth']; + foreach (range(1, 9) as $i) { + $field = "p$i"; + $ml_fields[] = $field; + $query->orderBy('ml.' . $field); + } + return $query->fields('ml', $ml_fields); + } + + /** + * {@inheritdoc} + */ + public function getIds() { + $ids['mlid']['type'] = 'integer'; + $ids['mlid']['alias'] = 'ml'; + return $ids; + } + + /** + * {@inheritdoc} + */ + public function fields() { + return [ + 'nid' => $this->t('Node ID'), + 'bid' => $this->t('Book ID'), + 'mlid' => $this->t('Menu link ID'), + 'plid' => $this->t('Parent link ID'), + 'weight' => $this->t('Weight'), + 'p1' => $this->t('The first mlid in the materialized path. If N = depth, then pN must equal the mlid. If depth > 1 then p(N-1) must equal the parent link mlid. All pX where X > depth must equal zero. The columns p1 .. p9 are also called the parents.'), + 'p2' => $this->t('The second mlid in the materialized path. See p1.'), + 'p3' => $this->t('The third mlid in the materialized path. See p1.'), + 'p4' => $this->t('The fourth mlid in the materialized path. See p1.'), + 'p5' => $this->t('The fifth mlid in the materialized path. See p1.'), + 'p6' => $this->t('The sixth mlid in the materialized path. See p1.'), + 'p7' => $this->t('The seventh mlid in the materialized path. See p1.'), + 'p8' => $this->t('The eighth mlid in the materialized path. See p1.'), + 'p9' => $this->t('The ninth mlid in the materialized path. See p1.'), + ]; + } + +} diff -r e200cb7efeb3 -r c2387f117808 core/modules/book/src/Plugin/migrate/source/d6/Book.php --- a/core/modules/book/src/Plugin/migrate/source/d6/Book.php Thu Apr 26 11:26:54 2018 +0100 +++ b/core/modules/book/src/Plugin/migrate/source/d6/Book.php Tue Jul 10 15:07:59 2018 +0100 @@ -2,7 +2,9 @@ namespace Drupal\book\Plugin\migrate\source\d6; -use Drupal\migrate_drupal\Plugin\migrate\source\DrupalSqlBase; +use Drupal\book\Plugin\migrate\source\Book as BookGeneral; + +@trigger_error('Book is deprecated in Drupal 8.6.x and will be removed before Drupal 9.0.x. Use \Drupal\book\Plugin\migrate\source\Book instead. See https://www.drupal.org/node/2947487 for more information.', E_USER_DEPRECATED); /** * Drupal 6 book source. @@ -11,54 +13,9 @@ * id = "d6_book", * source_module = "book" * ) + * + * @deprecated in Drupal 8.6.x, to be removed before Drupal 9.0.x. Use + * \Drupal\book\Plugin\migrate\source\Book instead. See + * https://www.drupal.org/node/2947487 for more information. */ -class Book extends DrupalSqlBase { - - /** - * {@inheritdoc} - */ - public function query() { - $query = $this->select('book', 'b')->fields('b', ['nid', 'bid']); - $query->join('menu_links', 'ml', 'b.mlid = ml.mlid'); - $ml_fields = ['mlid', 'plid', 'weight', 'has_children', 'depth']; - for ($i = 1; $i <= 9; $i++) { - $field = "p$i"; - $ml_fields[] = $field; - $query->orderBy('ml.' . $field); - } - $query->fields('ml', $ml_fields); - return $query; - } - - /** - * {@inheritdoc} - */ - public function getIds() { - $ids['mlid']['type'] = 'integer'; - $ids['mlid']['alias'] = 'ml'; - return $ids; - } - - /** - * {@inheritdoc} - */ - public function fields() { - return [ - 'nid' => $this->t('Node ID'), - 'bid' => $this->t('Book ID'), - 'mlid' => $this->t('Menu link ID'), - 'plid' => $this->t('Parent link ID'), - 'weight' => $this->t('Weight'), - 'p1' => $this->t('The first mlid in the materialized path. If N = depth, then pN must equal the mlid. If depth > 1 then p(N-1) must equal the parent link mlid. All pX where X > depth must equal zero. The columns p1 .. p9 are also called the parents.'), - 'p2' => $this->t('The second mlid in the materialized path. See p1.'), - 'p3' => $this->t('The third mlid in the materialized path. See p1.'), - 'p4' => $this->t('The fourth mlid in the materialized path. See p1.'), - 'p5' => $this->t('The fifth mlid in the materialized path. See p1.'), - 'p6' => $this->t('The sixth mlid in the materialized path. See p1.'), - 'p7' => $this->t('The seventh mlid in the materialized path. See p1.'), - 'p8' => $this->t('The eighth mlid in the materialized path. See p1.'), - 'p9' => $this->t('The ninth mlid in the materialized path. See p1.'), - ]; - } - -} +class Book extends BookGeneral {} diff -r e200cb7efeb3 -r c2387f117808 core/modules/book/tests/src/Kernel/Migrate/d6/MigrateBookConfigsTest.php --- a/core/modules/book/tests/src/Kernel/Migrate/d6/MigrateBookConfigsTest.php Thu Apr 26 11:26:54 2018 +0100 +++ b/core/modules/book/tests/src/Kernel/Migrate/d6/MigrateBookConfigsTest.php Tue Jul 10 15:07:59 2018 +0100 @@ -20,17 +20,29 @@ public static $modules = ['book']; /** - * {@inheritdoc} + * Data provider for testBookSettings(). + * + * @return array + * The data for each test scenario. */ - protected function setUp() { - parent::setUp(); - $this->executeMigration('d6_book_settings'); + public function providerBookSettings() { + return [ + // d6_book_settings was renamed to book_settings, but use the old alias to + // prove that it works. + // @see book_migration_plugins_alter() + ['d6_book_settings'], + ['book_settings'], + ]; } /** * Tests migration of book variables to book.settings.yml. + * + * @dataProvider providerBookSettings */ - public function testBookSettings() { + public function testBookSettings($migration_id) { + $this->executeMigration($migration_id); + $config = $this->config('book.settings'); $this->assertIdentical('book', $config->get('child_type')); $this->assertSame('book pages', $config->get('block.navigation.mode')); diff -r e200cb7efeb3 -r c2387f117808 core/modules/book/tests/src/Kernel/Migrate/d7/MigrateBookConfigsTest.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/core/modules/book/tests/src/Kernel/Migrate/d7/MigrateBookConfigsTest.php Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,41 @@ +executeMigration('book_settings'); + } + + /** + * Tests migration of book variables to book.settings.yml. + */ + public function testBookSettings() { + $config = $this->config('book.settings'); + $this->assertSame('book', $config->get('child_type')); + $this->assertSame('all pages', $config->get('block.navigation.mode')); + $this->assertSame(['book'], $config->get('allowed_types')); + $this->assertConfigSchema(\Drupal::service('config.typed'), 'book.settings', $config->get()); + } + +} diff -r e200cb7efeb3 -r c2387f117808 core/modules/book/tests/src/Kernel/Migrate/d7/MigrateBookTest.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/core/modules/book/tests/src/Kernel/Migrate/d7/MigrateBookTest.php Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,69 @@ +installEntitySchema('node'); + $this->installEntitySchema('taxonomy_term'); + $this->installConfig(['node']); + $this->installSchema('book', ['book']); + $this->installSchema('node', ['node_access']); + $this->executeMigrations([ + 'd7_user_role', + 'd7_user', + 'd7_node_type', + 'd7_node', + 'd7_book' + ]); + } + + /** + * Tests the Drupal 7 book structure to Drupal 8 migration. + */ + public function testBook() { + $nodes = Node::loadMultiple([1, 2, 4, 6]); + $this->assertSame('8', $nodes[1]->book['bid']); + $this->assertSame('6', $nodes[1]->book['pid']); + + $this->assertSame('4', $nodes[2]->book['bid']); + $this->assertSame('6', $nodes[2]->book['pid']); + + $this->assertSame('4', $nodes[4]->book['bid']); + $this->assertSame('0', $nodes[4]->book['pid']); + + $this->assertSame('4', $nodes[6]->book['bid']); + $this->assertSame('4', $nodes[6]->book['pid']); + + $tree = \Drupal::service('book.manager')->bookTreeAllData(4); + $this->assertSame('4', $tree['49990 is - The thing about Firefly 4']['link']['nid']); + $this->assertSame('6', $tree['49990 is - The thing about Firefly 4']['below']['50000 Comments are closed :-( 6']['link']['nid']); + $this->assertSame('2', $tree['49990 is - The thing about Firefly 4']['below']['50000 Comments are closed :-( 6']['below']['50000 The thing about Deep Space 9 2']['link']['nid']); + $this->assertSame([], $tree['49990 is - The thing about Firefly 4']['below']['50000 Comments are closed :-( 6']['below']['50000 The thing about Deep Space 9 2']['below']); + } + +} diff -r e200cb7efeb3 -r c2387f117808 core/modules/book/tests/src/Kernel/Plugin/migrate/source/BookTest.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/core/modules/book/tests/src/Kernel/Plugin/migrate/source/BookTest.php Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,100 @@ + '1', + 'nid' => '4', + 'bid' => '4', + ], + ]; + $tests[0]['source_data']['menu_links'] = [ + [ + 'menu_name' => 'book-toc-1', + 'mlid' => '1', + 'plid' => '0', + 'link_path' => 'node/4', + 'router_path' => 'node/%', + 'link_title' => 'Test top book title', + 'options' => 'a:0:{}', + 'module' => 'book', + 'hidden' => '0', + 'external' => '0', + 'has_children' => '1', + 'expanded' => '0', + 'weight' => '-10', + 'depth' => '1', + 'customized' => '0', + 'p1' => '1', + 'p2' => '0', + 'p3' => '0', + 'p4' => '0', + 'p5' => '0', + 'p6' => '0', + 'p7' => '0', + 'p8' => '0', + 'p9' => '0', + 'updated' => '0', + ], + ]; + + // The expected results. + $tests[0]['expected_data'] = [ + [ + 'nid' => '4', + 'bid' => '4', + 'mlid' => '1', + 'plid' => '0', + 'weight' => '-10', + 'p1' => '1', + 'p2' => '0', + 'p3' => '0', + 'p4' => '0', + 'p5' => '0', + 'p6' => '0', + 'p7' => '0', + 'p8' => '0', + 'p9' => '0', + ], + ]; + return $tests; + } + + /** + * @expectedDeprecation Book is deprecated in Drupal 8.6.x and will be removed before Drupal 9.0.x. Use \Drupal\book\Plugin\migrate\source\Book instead. See https://www.drupal.org/node/2947487 for more information. + */ + public function testDeprecatedPlugin() { + new D6Book( + [], + 'd6_book', + [], + $this->prophesize('Drupal\migrate\Plugin\MigrationInterface')->reveal(), + $this->prophesize('Drupal\Core\State\StateInterface')->reveal(), + $this->prophesize('Drupal\Core\Entity\EntityManagerInterface')->reveal() + ); + } + +} diff -r e200cb7efeb3 -r c2387f117808 core/modules/book/tests/src/Kernel/Plugin/migrate/source/d6/BookTest.php --- a/core/modules/book/tests/src/Kernel/Plugin/migrate/source/d6/BookTest.php Thu Apr 26 11:26:54 2018 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,84 +0,0 @@ - '1', - 'nid' => '4', - 'bid' => '4', - ], - ]; - $tests[0]['source_data']['menu_links'] = [ - [ - 'menu_name' => 'book-toc-1', - 'mlid' => '1', - 'plid' => '0', - 'link_path' => 'node/4', - 'router_path' => 'node/%', - 'link_title' => 'Test top book title', - 'options' => 'a:0:{}', - 'module' => 'book', - 'hidden' => '0', - 'external' => '0', - 'has_children' => '1', - 'expanded' => '0', - 'weight' => '-10', - 'depth' => '1', - 'customized' => '0', - 'p1' => '1', - 'p2' => '0', - 'p3' => '0', - 'p4' => '0', - 'p5' => '0', - 'p6' => '0', - 'p7' => '0', - 'p8' => '0', - 'p9' => '0', - 'updated' => '0', - ], - ]; - - // The expected results. - $tests[0]['expected_data'] = [ - [ - 'nid' => '4', - 'bid' => '4', - 'mlid' => '1', - 'plid' => '0', - 'weight' => '-10', - 'p1' => '1', - 'p2' => '0', - 'p3' => '0', - 'p4' => '0', - 'p5' => '0', - 'p6' => '0', - 'p7' => '0', - 'p8' => '0', - 'p9' => '0', - ], - ]; - return $tests; - } - -} diff -r e200cb7efeb3 -r c2387f117808 core/modules/color/migrations/d7_color.yml --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/core/modules/color/migrations/d7_color.yml Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,54 @@ +id: d7_color +label: Color +migration_tags: + - Drupal 7 + - Configuration +source: + plugin: d7_color + constants: + config_prefix: 'color.theme.' +process: + # Skip if theme not installed on destination. + theme_installed: + plugin: skip_on_empty + source: theme_installed + method: row + element_name: + - + plugin: explode + source: name + delimiter: _ + - + plugin: extract + index: + - 2 + # Skip if the variable name ends in 'screenshot'. + screenshot: + - + plugin: static_map + source: '@element_name' + bypass: true + map: + screenshot: false + - + plugin: skip_on_empty + method: row + # Build the configuration name from the variable name, i.e. + # 'color_themename_element' becomes 'color.theme.themename' + theme_name: + - + plugin: explode + source: name + delimiter: _ + - + plugin: extract + index: + - 1 + configuration_name: + plugin: concat + source: + - constants/config_prefix + - '@theme_name' + value: value +destination: + plugin: color diff -r e200cb7efeb3 -r c2387f117808 core/modules/color/src/Plugin/migrate/destination/Color.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/core/modules/color/src/Plugin/migrate/destination/Color.php Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,90 @@ +configFactory = $config_factory; + } + + /** + * {@inheritdoc} + */ + public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition, MigrationInterface $migration = NULL) { + return new static( + $configuration, + $plugin_id, + $plugin_definition, + $migration, + $container->get('config.factory') + ); + } + + /** + * {@inheritdoc} + */ + public function import(Row $row, array $old_destination_id_values = []) { + $imported = FALSE; + $value = $row->getDestinationProperty('value'); + if (isset($value)) { + $this->configFactory->getEditable($row->getDestinationProperty('configuration_name')) + ->set($row->getDestinationProperty('element_name'), $row->getDestinationProperty('value')) + ->save(); + $imported = TRUE; + } + return $imported; + } + + /** + * {@inheritdoc} + */ + public function getIds() { + $ids['name']['type'] = 'string'; + return $ids; + } + + /** + * {@inheritdoc} + */ + public function fields(MigrationInterface $migration = NULL) { + return []; + } + +} diff -r e200cb7efeb3 -r c2387f117808 core/modules/color/src/Plugin/migrate/source/d7/Color.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/core/modules/color/src/Plugin/migrate/source/d7/Color.php Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,98 @@ +themeHandler = $theme_handler; + } + + /** + * {@inheritdoc} + */ + public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition, MigrationInterface $migration = NULL) { + return new static( + $configuration, + $plugin_id, + $plugin_definition, + $migration, + $container->get('state'), + $container->get('entity.manager'), + $container->get('theme_handler') + ); + } + + /** + * {@inheritdoc} + */ + public function query() { + // Get color data for all themes. + $query = $this->select('variable', 'v') + ->fields('v', ['name', 'value']) + ->condition('name', 'color_%', 'LIKE'); + return $query; + } + + /** + * {@inheritdoc} + */ + public function prepareRow(Row $row) { + $themes = $this->themeHandler->listInfo(); + $themes_installed = []; + /** @var \Drupal\Core\Extension\Extension $theme */ + foreach ($themes as $theme) { + if ($theme->status) { + $themes_installed[] = $theme->getName(); + } + } + + // The name is of the form 'color_theme_variable'. + $name = explode('_', $row->getSourceProperty('name')); + + // Set theme_installed if this source theme is installed. + if (in_array($name[1], $themes_installed)) { + $row->setSourceProperty('theme_installed', TRUE); + } + + return parent::prepareRow($row); + } + + /** + * {@inheritdoc} + */ + public function fields() { + return [ + 'name' => $this->t('A color variable for a theme.'), + 'value' => $this->t('The value of a color variable.'), + ]; + } + +} diff -r e200cb7efeb3 -r c2387f117808 core/modules/color/tests/src/Kernel/Migrate/d7/MigrateColorTest.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/core/modules/color/tests/src/Kernel/Migrate/d7/MigrateColorTest.php Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,61 @@ +container->get('theme_installer')->install(['bartik']); + $this->executeMigration('d7_color'); + } + + /** + * Tests migration of color's variables to configuration. + */ + public function testMigrateColor() { + // Test Bartik migration. + $config = $this->config('color.theme.bartik'); + $files = [ + 'public://color/bartik-e0e23ad7/logo.png', + 'public://color/bartik-e0e23ad7/colors.css', + ]; + $this->assertSame($files, $config->get('files')); + $this->assertSame('public://color/bartik-e0e23ad7/logo.png', $config->get('logo')); + $palette = [ + 'top' => '#d0d0d0', + 'bottom' => '#c2c4c5', + 'bg' => '#ffffff', + 'sidebar' => '#ffffff', + 'sidebarborders' => '#cccccc', + 'footer' => '#24272c', + 'titleslogan' => '#000000', + 'text' => '#4a4a4a', + 'link' => '#019dbf', + ]; + $this->assertSame($palette, $config->get('palette')); + $this->assertSame(['public://color/bartik-e0e23ad7/colors.css'], $config->get('stylesheets')); + // Test that the screenshot was not migrated. + $this->assertNull($config->get('screenshot')); + + // Test that garland was not migrated. + $this->assertEmpty(\Drupal::config('color.theme.garland')->get()); + } + +} diff -r e200cb7efeb3 -r c2387f117808 core/modules/color/tests/src/Kernel/Plugin/migrate/source/d7/ColorTest.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/core/modules/color/tests/src/Kernel/Plugin/migrate/source/d7/ColorTest.php Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,129 @@ + 'color_bartik_palette', + 'value' => [ + 'top' => '#cd2d2d', + 'bottom' => '#d64e4e', + 'bg' => '#ffffff', + 'sidebar' => '#f1f4f0', + 'sidebarborders' => '#ededed', + 'footer' => '#1f1d1c', + 'titleslogan' => '#fffeff', + 'text' => '#888888', + 'link' => '#d6121f', + ], + ], + [ + 'name' => 'color_bartik_logo', + 'value' => 'public://color/bartik-e0e23ad7/logo.png', + ], + [ + 'name' => 'color_bartik_stylesheets', + 'value' => ['public://color/bartik-1d249313/colors.css'], + ], + [ + 'name' => 'color_bartik_files', + 'value' => [ + 'public://color/bartik-e0e23ad7/logo.png', + 'public://color/bartik-e0e23ad7/colors.css', + ], + ], + [ + 'name' => 'color_bartik_screenshot', + 'value' => ['public:://color/bartik-b69cfcec/screenshot.png'], + ], + [ + 'name' => 'color_custom_stylesheets', + 'value' => ['public:://color/custom-beadedff/colors.css'], + ], + ]; + + foreach ($tests[0]['database']['variable'] as $key => $expected) { + $tests[0]['database']['variable'][$key]['value'] = serialize($expected['value']); + } + + $tests[0]['database']['system'] = [ + [ + 'name' => 'bartik', + 'type' => 'theme', + 'status' => '1', + ], + [ + 'name' => 'custom', + 'type' => 'theme', + 'status' => '0', + ], + ]; + + // Expected results are the same as the source. + $tests[0]['expected_results'] = [ + [ + 'name' => 'color_bartik_palette', + 'value' => [ + 'top' => '#cd2d2d', + 'bottom' => '#d64e4e', + 'bg' => '#ffffff', + 'sidebar' => '#f1f4f0', + 'sidebarborders' => '#ededed', + 'footer' => '#1f1d1c', + 'titleslogan' => '#fffeff', + 'text' => '#888888', + 'link' => '#d6121f', + ], + ], + [ + 'name' => 'color_bartik_logo', + 'value' => 'public://color/bartik-e0e23ad7/logo.png', + ], + [ + 'name' => 'color_bartik_stylesheets', + 'value' => ['public://color/bartik-1d249313/colors.css'], + ], + [ + 'name' => 'color_bartik_files', + 'value' => [ + 'public://color/bartik-e0e23ad7/logo.png', + 'public://color/bartik-e0e23ad7/colors.css', + ], + ], + [ + 'name' => 'color_bartik_screenshot', + 'value' => ['public:://color/bartik-b69cfcec/screenshot.png'], + ], + [ + 'name' => 'color_custom_stylesheets', + 'value' => ['public:://color/custom-beadedff/colors.css'], + ], + ]; + + return $tests; + } + +} diff -r e200cb7efeb3 -r c2387f117808 core/modules/comment/comment.module --- a/core/modules/comment/comment.module Thu Apr 26 11:26:54 2018 +0100 +++ b/core/modules/comment/comment.module Tue Jul 10 15:07:59 2018 +0100 @@ -268,7 +268,7 @@ * content language of the current request. * * @return array - * An array as expected by drupal_render(). + * An array as expected by \Drupal\Core\Render\RendererInterface::render(). * * @deprecated in Drupal 8.x and will be removed before Drupal 9.0. * Use \Drupal::entityManager()->getViewBuilder('comment')->view(). @@ -291,12 +291,13 @@ * Defaults to NULL. * * @return array - * An array in the format expected by drupal_render(). + * An array in the format expected by + * \Drupal\Core\Render\RendererInterface::render(). * * @deprecated in Drupal 8.x and will be removed before Drupal 9.0. * Use \Drupal::entityManager()->getViewBuilder('comment')->viewMultiple(). * - * @see drupal_render() + * @see \Drupal\Core\Render\RendererInterface::render() */ function comment_view_multiple($comments, $view_mode = 'full', $langcode = NULL) { return entity_view_multiple($comments, $view_mode, $langcode); @@ -558,7 +559,7 @@ * The current state of the form. * * @return array - * An array as expected by drupal_render(). + * An array as expected by \Drupal\Core\Render\RendererInterface::render(). */ function comment_preview(CommentInterface $comment, FormStateInterface $form_state) { $preview_build = []; diff -r e200cb7efeb3 -r c2387f117808 core/modules/comment/src/CommentViewBuilder.php --- a/core/modules/comment/src/CommentViewBuilder.php Thu Apr 26 11:26:54 2018 +0100 +++ b/core/modules/comment/src/CommentViewBuilder.php Tue Jul 10 15:07:59 2018 +0100 @@ -98,6 +98,7 @@ // A counter to track the indentation level. $current_indent = 0; + $attach_history = $this->moduleHandler->moduleExists('history') && $this->currentUser->isAuthenticated(); foreach ($entities as $id => $entity) { if ($build[$id]['#comment_threaded']) { @@ -143,7 +144,7 @@ $build[$id]['#attached'] = []; } $build[$id]['#attached']['library'][] = 'comment/drupal.comment-by-viewer'; - if ($this->moduleHandler->moduleExists('history') && $this->currentUser->isAuthenticated()) { + if ($attach_history && $commented_entity->getEntityTypeId() === 'node') { $build[$id]['#attached']['library'][] = 'comment/drupal.comment-new-indicator'; // Embed the metadata for the comment "new" indicators on this node. diff -r e200cb7efeb3 -r c2387f117808 core/modules/comment/src/Entity/CommentType.php --- a/core/modules/comment/src/Entity/CommentType.php Thu Apr 26 11:26:54 2018 +0100 +++ b/core/modules/comment/src/Entity/CommentType.php Tue Jul 10 15:07:59 2018 +0100 @@ -37,7 +37,7 @@ * "delete-form" = "/admin/structure/comment/manage/{comment_type}/delete", * "edit-form" = "/admin/structure/comment/manage/{comment_type}", * "add-form" = "/admin/structure/comment/types/add", - * "collection" = "/admin/structure/comment/types", + * "collection" = "/admin/structure/comment", * }, * config_export = { * "id", diff -r e200cb7efeb3 -r c2387f117808 core/modules/comment/tests/src/Functional/CommentEntityTest.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/core/modules/comment/tests/src/Functional/CommentEntityTest.php Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,80 @@ +vocab = $this->createVocabulary(); + $this->commentType = CommentType::create([ + 'id' => 'taxonomy_comment', + 'label' => 'Taxonomy comment', + 'description' => '', + 'target_entity_type_id' => 'taxonomy_term', + ]); + $this->commentType->save(); + $this->addDefaultCommentField( + 'taxonomy_term', + $this->vocab->id(), + 'field_comment', + CommentItemInterface::OPEN, + $this->commentType->id() + ); + } + + /** + * Tests CSS classes on comments. + */ + public function testEntityChanges() { + $this->drupalLogin($this->webUser); + // Create a new node. + $term = $this->createTerm($this->vocab, ['uid' => $this->webUser->id()]); + + // Add a comment. + /** @var \Drupal\comment\CommentInterface $comment */ + $comment = Comment::create([ + 'entity_id' => $term->id(), + 'entity_type' => 'taxonomy_term', + 'field_name' => 'field_comment', + 'uid' => $this->webUser->id(), + 'status' => CommentInterface::PUBLISHED, + 'subject' => $this->randomMachineName(), + 'language' => LanguageInterface::LANGCODE_NOT_SPECIFIED, + 'comment_body' => [LanguageInterface::LANGCODE_NOT_SPECIFIED => [$this->randomMachineName()]], + ]); + $comment->save(); + + // Request the node with the comment. + $this->drupalGet('taxonomy/term/' . $term->id()); + $settings = $this->getDrupalSettings(); + $this->assertFalse(isset($settings['ajaxPageState']['libraries']) && in_array('comment/drupal.comment-new-indicator', explode(',', $settings['ajaxPageState']['libraries'])), 'drupal.comment-new-indicator library is present.'); + $this->assertFalse(isset($settings['history']['lastReadTimestamps']) && in_array($term->id(), array_keys($settings['history']['lastReadTimestamps'])), 'history.lastReadTimestamps is present.'); + } + +} diff -r e200cb7efeb3 -r c2387f117808 core/modules/comment/tests/src/Functional/Hal/CommentHalJsonAnonTest.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/core/modules/comment/tests/src/Functional/Hal/CommentHalJsonAnonTest.php Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,35 @@ +applyHalFieldNormalization($default_normalization); + + // Because \Drupal\comment\Entity\Comment::getOwner() generates an in-memory + // User entity without a UUID, we cannot use it. + $author = User::load($this->entity->getOwnerId()); + $commented_entity = EntityTest::load(1); + return $normalization + [ + '_links' => [ + 'self' => [ + 'href' => $this->baseUrl . '/comment/1?_format=hal_json', + ], + 'type' => [ + 'href' => $this->baseUrl . '/rest/type/comment/comment', + ], + $this->baseUrl . '/rest/relation/comment/comment/entity_id' => [ + [ + 'href' => $this->baseUrl . '/entity_test/1?_format=hal_json', + ], + ], + $this->baseUrl . '/rest/relation/comment/comment/uid' => [ + [ + 'href' => $this->baseUrl . '/user/' . $author->id() . '?_format=hal_json', + 'lang' => 'en', + ], + ], + ], + '_embedded' => [ + $this->baseUrl . '/rest/relation/comment/comment/entity_id' => [ + [ + '_links' => [ + 'self' => [ + 'href' => $this->baseUrl . '/entity_test/1?_format=hal_json', + ], + 'type' => [ + 'href' => $this->baseUrl . '/rest/type/entity_test/bar', + ], + ], + 'uuid' => [ + ['value' => $commented_entity->uuid()] + ], + ], + ], + $this->baseUrl . '/rest/relation/comment/comment/uid' => [ + [ + '_links' => [ + 'self' => [ + 'href' => $this->baseUrl . '/user/' . $author->id() . '?_format=hal_json', + ], + 'type' => [ + 'href' => $this->baseUrl . '/rest/type/user/user', + ], + ], + 'uuid' => [ + ['value' => $author->uuid()] + ], + 'lang' => 'en', + ], + ], + ], + ]; + } + + /** + * {@inheritdoc} + */ + protected function getNormalizedPostEntity() { + return parent::getNormalizedPostEntity() + [ + '_links' => [ + 'type' => [ + 'href' => $this->baseUrl . '/rest/type/comment/comment', + ], + ], + ]; + } + +} diff -r e200cb7efeb3 -r c2387f117808 core/modules/comment/tests/src/Functional/Hal/CommentTypeHalJsonAnonTest.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/core/modules/comment/tests/src/Functional/Hal/CommentTypeHalJsonAnonTest.php Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,30 @@ +grantPermissionsToTestedRole(['access comments', 'view test entity']); + break; + case 'POST': + $this->grantPermissionsToTestedRole(['post comments']); + break; + case 'PATCH': + // Anononymous users are not ever allowed to edit their own comments. To + // be able to test PATCHing comments as the anonymous user, the more + // permissive 'administer comments' permission must be granted. + // @see \Drupal\comment\CommentAccessControlHandler::checkAccess + if (static::$auth) { + $this->grantPermissionsToTestedRole(['edit own comments']); + } + else { + $this->grantPermissionsToTestedRole(['administer comments']); + } + break; + case 'DELETE': + $this->grantPermissionsToTestedRole(['administer comments']); + break; + } + } + + /** + * {@inheritdoc} + */ + protected function createEntity() { + // Create a "bar" bundle for the "entity_test" entity type and create. + $bundle = 'bar'; + entity_test_create_bundle($bundle, NULL, 'entity_test'); + + // Create a comment field on this bundle. + $this->addDefaultCommentField('entity_test', 'bar', 'comment'); + + // Create a "Camelids" test entity that the comment will be assigned to. + $commented_entity = EntityTest::create([ + 'name' => 'Camelids', + 'type' => 'bar', + ]); + $commented_entity->save(); + + // Create a "Llama" comment. + $comment = Comment::create([ + 'comment_body' => [ + 'value' => 'The name "llama" was adopted by European settlers from native Peruvians.', + 'format' => 'plain_text', + ], + 'entity_id' => $commented_entity->id(), + 'entity_type' => 'entity_test', + 'field_name' => 'comment', + ]); + $comment->setSubject('Llama') + ->setOwnerId(static::$auth ? $this->account->id() : 0) + ->setPublished(TRUE) + ->setCreatedTime(123456789) + ->setChangedTime(123456789); + $comment->save(); + + return $comment; + } + + /** + * {@inheritdoc} + */ + protected function getExpectedNormalizedEntity() { + $author = User::load($this->entity->getOwnerId()); + return [ + 'cid' => [ + ['value' => 1], + ], + 'uuid' => [ + ['value' => $this->entity->uuid()], + ], + 'langcode' => [ + [ + 'value' => 'en', + ], + ], + 'comment_type' => [ + [ + 'target_id' => 'comment', + 'target_type' => 'comment_type', + 'target_uuid' => CommentType::load('comment')->uuid(), + ], + ], + 'subject' => [ + [ + 'value' => 'Llama', + ], + ], + 'status' => [ + [ + 'value' => TRUE, + ], + ], + 'created' => [ + $this->formatExpectedTimestampItemValues(123456789), + ], + 'changed' => [ + $this->formatExpectedTimestampItemValues($this->entity->getChangedTime()), + ], + 'default_langcode' => [ + [ + 'value' => TRUE, + ], + ], + 'uid' => [ + [ + 'target_id' => (int) $author->id(), + 'target_type' => 'user', + 'target_uuid' => $author->uuid(), + 'url' => base_path() . 'user/' . $author->id(), + ], + ], + 'pid' => [], + 'entity_type' => [ + [ + 'value' => 'entity_test', + ], + ], + 'entity_id' => [ + [ + 'target_id' => 1, + 'target_type' => 'entity_test', + 'target_uuid' => EntityTest::load(1)->uuid(), + 'url' => base_path() . 'entity_test/1', + ], + ], + 'field_name' => [ + [ + 'value' => 'comment', + ], + ], + 'name' => [], + 'homepage' => [], + 'thread' => [ + [ + 'value' => '01/', + ], + ], + 'comment_body' => [ + [ + 'value' => 'The name "llama" was adopted by European settlers from native Peruvians.', + 'format' => 'plain_text', + 'processed' => '

The name "llama" was adopted by European settlers from native Peruvians.

' . "\n", + ], + ], + ]; + } + + /** + * {@inheritdoc} + */ + protected function getNormalizedPostEntity() { + return [ + 'comment_type' => [ + [ + 'target_id' => 'comment', + ], + ], + 'entity_type' => [ + [ + 'value' => 'entity_test', + ], + ], + 'entity_id' => [ + [ + 'target_id' => (int) EntityTest::load(1)->id(), + ], + ], + 'field_name' => [ + [ + 'value' => 'comment', + ], + ], + 'subject' => [ + [ + 'value' => 'Dramallama', + ], + ], + 'comment_body' => [ + [ + 'value' => 'Llamas are awesome.', + 'format' => 'plain_text', + ], + ], + ]; + } + + /** + * {@inheritdoc} + */ + protected function getNormalizedPatchEntity() { + return array_diff_key($this->getNormalizedPostEntity(), ['entity_type' => TRUE, 'entity_id' => TRUE, 'field_name' => TRUE]); + } + + /** + * {@inheritdoc} + */ + protected function getExpectedCacheTags() { + return Cache::mergeTags(parent::getExpectedCacheTags(), ['config:filter.format.plain_text']); + } + + /** + * {@inheritdoc} + */ + protected function getExpectedCacheContexts() { + return Cache::mergeContexts(['languages:language_interface', 'theme'], parent::getExpectedCacheContexts()); + } + + /** + * Tests POSTing a comment without critical base fields. + * + * testPost() is testing with the most minimal normalization possible: the one + * returned by ::getNormalizedPostEntity(). + * + * But Comment entities have some very special edge cases: + * - base fields that are not marked as required in + * \Drupal\comment\Entity\Comment::baseFieldDefinitions() yet in fact are + * required. + * - base fields that are marked as required, but yet can still result in + * validation errors other than "missing required field". + */ + public function testPostDxWithoutCriticalBaseFields() { + $this->initAuthentication(); + $this->provisionEntityResource(); + $this->setUpAuthorization('POST'); + + $url = $this->getEntityResourcePostUrl()->setOption('query', ['_format' => static::$format]); + $request_options = []; + $request_options[RequestOptions::HEADERS]['Accept'] = static::$mimeType; + $request_options[RequestOptions::HEADERS]['Content-Type'] = static::$mimeType; + $request_options = array_merge_recursive($request_options, $this->getAuthenticationRequestOptions('POST')); + + // DX: 422 when missing 'entity_type' field. + $request_options[RequestOptions::BODY] = $this->serializer->encode(array_diff_key($this->getNormalizedPostEntity(), ['entity_type' => TRUE]), static::$format); + $response = $this->request('POST', $url, $request_options); + // @todo Uncomment, remove next 3 lines in https://www.drupal.org/node/2820364. + $this->assertSame(500, $response->getStatusCode()); + $this->assertSame(['text/plain; charset=UTF-8'], $response->getHeader('Content-Type')); + $this->assertStringStartsWith('The website encountered an unexpected error. Please try again later.

Symfony\Component\HttpKernel\Exception\HttpException: Internal Server Error in Drupal\rest\Plugin\rest\resource\EntityResource->post()', (string) $response->getBody()); + // $this->assertResourceErrorResponse(422, "Unprocessable Entity: validation failed.\nentity_type: This value should not be null.\n", $response); + + // DX: 422 when missing 'entity_id' field. + $request_options[RequestOptions::BODY] = $this->serializer->encode(array_diff_key($this->getNormalizedPostEntity(), ['entity_id' => TRUE]), static::$format); + // @todo Remove the try/catch in favor of the two commented lines in + // https://www.drupal.org/node/2820364. + try { + $response = $this->request('POST', $url, $request_options); + // This happens on DrupalCI. + // $this->assertSame(500, $response->getStatusCode()); + } + catch (\Exception $e) { + // This happens on Wim's local machine. + // $this->assertSame("Error: Call to a member function get() on null\nDrupal\\comment\\Plugin\\Validation\\Constraint\\CommentNameConstraintValidator->getAnonymousContactDetailsSetting()() (Line: 96)\n", $e->getMessage()); + } + // $response = $this->request('POST', $url, $request_options); + // $this->assertResourceErrorResponse(422, "Unprocessable Entity: validation failed.\nentity_type: This value should not be null.\n", $response); + + // DX: 422 when missing 'entity_type' field. + $request_options[RequestOptions::BODY] = $this->serializer->encode(array_diff_key($this->getNormalizedPostEntity(), ['field_name' => TRUE]), static::$format); + $response = $this->request('POST', $url, $request_options); + // @todo Uncomment, remove next 2 lines in https://www.drupal.org/node/2820364. + $this->assertSame(500, $response->getStatusCode()); + $this->assertSame(['text/plain; charset=UTF-8'], $response->getHeader('Content-Type')); + // $this->assertResourceErrorResponse(422, "Unprocessable Entity: validation failed.\nfield_name: This value should not be null.\n", $response); + } + + /** + * {@inheritdoc} + */ + protected function getExpectedUnauthorizedAccessMessage($method) { + if ($this->config('rest.settings')->get('bc_entity_resource_permissions')) { + return parent::getExpectedUnauthorizedAccessMessage($method); + } + + switch ($method) { + case 'GET'; + return "The 'access comments' permission is required and the comment must be published."; + case 'POST'; + return "The 'post comments' permission is required."; + default: + return parent::getExpectedUnauthorizedAccessMessage($method); + } + } + + /** + * Tests POSTing a comment with and without 'skip comment approval' + */ + public function testPostSkipCommentApproval() { + $this->initAuthentication(); + $this->provisionEntityResource(); + $this->setUpAuthorization('POST'); + + // Create request. + $request_options = []; + $request_options[RequestOptions::HEADERS]['Accept'] = static::$mimeType; + $request_options[RequestOptions::HEADERS]['Content-Type'] = static::$mimeType; + $request_options = array_merge_recursive($request_options, $this->getAuthenticationRequestOptions('POST')); + $request_options[RequestOptions::BODY] = $this->serializer->encode($this->getNormalizedPostEntity(), static::$format); + + $url = $this->getEntityResourcePostUrl()->setOption('query', ['_format' => static::$format]); + + // Status should be FALSE when posting as anonymous. + $response = $this->request('POST', $url, $request_options); + $unserialized = $this->serializer->deserialize((string) $response->getBody(), get_class($this->entity), static::$format); + $this->assertResourceResponse(201, FALSE, $response); + $this->assertFalse($unserialized->getStatus()); + + // Grant anonymous permission to skip comment approval. + $this->grantPermissionsToTestedRole(['skip comment approval']); + + // Status should be TRUE when posting as anonymous and skip comment approval. + $response = $this->request('POST', $url, $request_options); + $unserialized = $this->serializer->deserialize((string) $response->getBody(), get_class($this->entity), static::$format); + $this->assertResourceResponse(201, FALSE, $response); + $this->assertTrue($unserialized->getStatus()); + } + + /** + * {@inheritdoc} + */ + protected function getExpectedUnauthorizedAccessCacheability() { + // @see \Drupal\comment\CommentAccessControlHandler::checkAccess() + return parent::getExpectedUnauthorizedAccessCacheability() + ->addCacheTags(['comment:1']); + } + +} diff -r e200cb7efeb3 -r c2387f117808 core/modules/comment/tests/src/Functional/Rest/CommentTypeJsonAnonTest.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/core/modules/comment/tests/src/Functional/Rest/CommentTypeJsonAnonTest.php Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,24 @@ +grantPermissionsToTestedRole(['administer comment types']); + } + + /** + * {@inheritdoc} + */ + protected function createEntity() { + // Create a "Camelids" comment type. + $camelids = CommentType::create([ + 'id' => 'camelids', + 'label' => 'Camelids', + 'description' => 'Camelids are large, strictly herbivorous animals with slender necks and long legs.', + 'target_entity_type_id' => 'node', + ]); + + $camelids->save(); + + return $camelids; + } + + /** + * {@inheritdoc} + */ + protected function getExpectedNormalizedEntity() { + return [ + 'dependencies' => [], + 'description' => 'Camelids are large, strictly herbivorous animals with slender necks and long legs.', + 'id' => 'camelids', + 'label' => 'Camelids', + 'langcode' => 'en', + 'status' => TRUE, + 'target_entity_type_id' => 'node', + 'uuid' => $this->entity->uuid(), + ]; + } + + /** + * {@inheritdoc} + */ + protected function getNormalizedPostEntity() { + // @todo Update in https://www.drupal.org/node/2300677. + } + +} diff -r e200cb7efeb3 -r c2387f117808 core/modules/comment/tests/src/Functional/Rest/CommentTypeXmlAnonTest.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/core/modules/comment/tests/src/Functional/Rest/CommentTypeXmlAnonTest.php Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,26 @@ +markTestSkipped(); + } + + /** + * {@inheritdoc} + */ + public function testPostSkipCommentApproval() { + // Deserialization of the XML format is not supported. + $this->markTestSkipped(); + } + +} diff -r e200cb7efeb3 -r c2387f117808 core/modules/comment/tests/src/Functional/Rest/CommentXmlBasicAuthTest.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/core/modules/comment/tests/src/Functional/Rest/CommentXmlBasicAuthTest.php Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,52 @@ +markTestSkipped(); + } + + /** + * {@inheritdoc} + */ + public function testPostSkipCommentApproval() { + // Deserialization of the XML format is not supported. + $this->markTestSkipped(); + } + +} diff -r e200cb7efeb3 -r c2387f117808 core/modules/comment/tests/src/Functional/Rest/CommentXmlCookieTest.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/core/modules/comment/tests/src/Functional/Rest/CommentXmlCookieTest.php Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,47 @@ +markTestSkipped(); + } + + /** + * {@inheritdoc} + */ + public function testPostSkipCommentApproval() { + // Deserialization of the XML format is not supported. + $this->markTestSkipped(); + } + +} diff -r e200cb7efeb3 -r c2387f117808 core/modules/config/src/ConfigSubscriber.php --- a/core/modules/config/src/ConfigSubscriber.php Thu Apr 26 11:26:54 2018 +0100 +++ b/core/modules/config/src/ConfigSubscriber.php Tue Jul 10 15:07:59 2018 +0100 @@ -18,6 +18,11 @@ * The config import event. */ public function onConfigImporterValidate(ConfigImporterEvent $event) { + // Make sure config syncs performed via the Config UI don't break, but + // don't worry about syncs initiated via the command line. + if (PHP_SAPI === 'cli') { + return; + } $importer = $event->getConfigImporter(); $core_extension = $importer->getStorageComparer()->getSourceStorage()->read('core.extension'); if (!isset($core_extension['module']['config'])) { diff -r e200cb7efeb3 -r c2387f117808 core/modules/config/src/Form/ConfigSync.php --- a/core/modules/config/src/Form/ConfigSync.php Thu Apr 26 11:26:54 2018 +0100 +++ b/core/modules/config/src/Form/ConfigSync.php Tue Jul 10 15:07:59 2018 +0100 @@ -342,7 +342,6 @@ 'init_message' => t('Starting configuration synchronization.'), 'progress_message' => t('Completed step @current of @total.'), 'error_message' => t('Configuration synchronization has encountered an error.'), - 'file' => __DIR__ . '/../../config.admin.inc', ]; foreach ($sync_steps as $sync_step) { $batch['operations'][] = [[get_class($this), 'processBatch'], [$config_importer, $sync_step]]; diff -r e200cb7efeb3 -r c2387f117808 core/modules/config/tests/config_override_test/src/PirateDayCacheabilityMetadataConfigOverride.php --- a/core/modules/config/tests/config_override_test/src/PirateDayCacheabilityMetadataConfigOverride.php Thu Apr 26 11:26:54 2018 +0100 +++ b/core/modules/config/tests/config_override_test/src/PirateDayCacheabilityMetadataConfigOverride.php Tue Jul 10 15:07:59 2018 +0100 @@ -61,17 +61,4 @@ return $metadata; } - /** - * Returns whether or not our overrides are potentially applicable. - * - * @param string $name - * The name of the config object that is being constructed. - * - * @return bool - * TRUE if the merchant ship will be boarded. FALSE if we drink rum instead. - */ - protected function isCacheabilityMetadataApplicable($name) { - return in_array($name, ['system.theme', 'block.block.call_to_action']); - } - } diff -r e200cb7efeb3 -r c2387f117808 core/modules/config/tests/config_test/src/ConfigValidation.php --- a/core/modules/config/tests/config_test/src/ConfigValidation.php Thu Apr 26 11:26:54 2018 +0100 +++ b/core/modules/config/tests/config_test/src/ConfigValidation.php Tue Jul 10 15:07:59 2018 +0100 @@ -74,8 +74,11 @@ * The validation execution context. */ public static function validateMapping($mapping, ExecutionContextInterface $context) { - if ($diff = array_diff(array_keys($mapping), ['llama', 'cat', 'giraffe', 'uuid', '_core'])) { - $context->addViolation('Missing giraffe.'); + // Ensure we are validating the entire mapping by diffing against all the + // keys. + $mapping_schema = \Drupal::service('config.typed')->get('config_test.validation')->getValue(); + if ($diff = array_diff_key($mapping, $mapping_schema)) { + $context->addViolation('Unexpected keys: ' . implode(', ', array_keys($diff))); } } diff -r e200cb7efeb3 -r c2387f117808 core/modules/config/tests/config_test/tests/src/Functional/Hal/ConfigTestHalJsonAnonTest.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/core/modules/config/tests/config_test/tests/src/Functional/Hal/ConfigTestHalJsonAnonTest.php Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,30 @@ +grantPermissionsToTestedRole(['view config_test']); + } + + /** + * {@inheritdoc} + */ + protected function createEntity() { + $config_test = ConfigTest::create([ + 'id' => 'llama', + 'label' => 'Llama', + ]); + $config_test->save(); + + return $config_test; + } + + /** + * {@inheritdoc} + */ + protected function getExpectedNormalizedEntity() { + $normalization = [ + 'uuid' => $this->entity->uuid(), + 'id' => 'llama', + 'weight' => 0, + 'langcode' => 'en', + 'status' => TRUE, + 'dependencies' => [], + 'label' => 'Llama', + 'style' => NULL, + 'size' => NULL, + 'size_value' => NULL, + 'protected_property' => NULL, + ]; + + return $normalization; + } + + /** + * {@inheritdoc} + */ + protected function getNormalizedPostEntity() { + // @todo Update in https://www.drupal.org/node/2300677. + } + +} diff -r e200cb7efeb3 -r c2387f117808 core/modules/config/tests/config_test/tests/src/Functional/Rest/ConfigTestXmlAnonTest.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/core/modules/config/tests/config_test/tests/src/Functional/Rest/ConfigTestXmlAnonTest.php Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,26 @@ +markTestSkipped('This test has to be run from the CLI'); + } + + $this->copyConfig($this->container->get('config.storage'), $this->container->get('config.storage.sync')); + + // Set up the ConfigImporter object for testing. + $storage_comparer = new StorageComparer( + $this->container->get('config.storage.sync'), + $this->container->get('config.storage'), + $this->container->get('config.manager') + ); + $this->configImporter = new ConfigImporter( + $storage_comparer->createChangelist(), + $this->container->get('event_dispatcher'), + $this->container->get('config.manager'), + $this->container->get('lock'), + $this->container->get('config.typed'), + $this->container->get('module_handler'), + $this->container->get('module_installer'), + $this->container->get('theme_handler'), + $this->container->get('string_translation') + ); + } + + /** + * Tests that the config mopdule can be uninstalled via CLI config import. + * + * @see \Drupal\config\ConfigSubscriber + */ + public function testConfigUninstallViaCli() { + $this->assertTrue($this->container->get('module_handler')->moduleExists('config')); + $sync = $this->container->get('config.storage.sync'); + $extensions = $sync->read('core.extension'); + unset($extensions['module']['config']); + $sync->write('core.extension', $extensions); + $this->configImporter->reset()->import(); + $this->assertFalse($this->container->get('module_handler')->moduleExists('config')); + } + +} diff -r e200cb7efeb3 -r c2387f117808 core/modules/config_translation/migrations/d6_user_profile_field_instance_translation.yml --- a/core/modules/config_translation/migrations/d6_user_profile_field_instance_translation.yml Thu Apr 26 11:26:54 2018 +0100 +++ b/core/modules/config_translation/migrations/d6_user_profile_field_instance_translation.yml Tue Jul 10 15:07:59 2018 +0100 @@ -12,7 +12,18 @@ langcode: language entity_type: 'constants/entity_type' bundle: 'constants/bundle' - field_name: name + field_name: + - + plugin: migration_lookup + migration: user_profile_field + source: fid + - + plugin: skip_on_empty + method: row + - + plugin: extract + index: + - 1 property: plugin: static_map source: property diff -r e200cb7efeb3 -r c2387f117808 core/modules/config_translation/src/Controller/ConfigTranslationListController.php --- a/core/modules/config_translation/src/Controller/ConfigTranslationListController.php Thu Apr 26 11:26:54 2018 +0100 +++ b/core/modules/config_translation/src/Controller/ConfigTranslationListController.php Tue Jul 10 15:07:59 2018 +0100 @@ -45,7 +45,8 @@ * The name of the mapper. * * @return array - * A render array as expected by drupal_render(). + * A render array as expected by + * \Drupal\Core\Render\RendererInterface::render(). * * @throws \Symfony\Component\HttpKernel\Exception\NotFoundHttpException * Throws an exception if a mapper plugin could not be instantiated from the diff -r e200cb7efeb3 -r c2387f117808 core/modules/config_translation/tests/src/Functional/ConfigTranslationListUiTest.php --- a/core/modules/config_translation/tests/src/Functional/ConfigTranslationListUiTest.php Thu Apr 26 11:26:54 2018 +0100 +++ b/core/modules/config_translation/tests/src/Functional/ConfigTranslationListUiTest.php Tue Jul 10 15:07:59 2018 +0100 @@ -80,6 +80,7 @@ // tests. $this->config('locale.settings') ->set('translation.import_enabled', TRUE) + ->set('translation.use_source', LOCALE_TRANSLATION_USE_SOURCE_LOCAL) ->save(); $this->drupalPlaceBlock('local_tasks_block'); } diff -r e200cb7efeb3 -r c2387f117808 core/modules/config_translation/tests/src/Functional/ConfigTranslationUiTest.php --- a/core/modules/config_translation/tests/src/Functional/ConfigTranslationUiTest.php Thu Apr 26 11:26:54 2018 +0100 +++ b/core/modules/config_translation/tests/src/Functional/ConfigTranslationUiTest.php Tue Jul 10 15:07:59 2018 +0100 @@ -808,6 +808,7 @@ // tests. $this->config('locale.settings') ->set('translation.import_enabled', TRUE) + ->set('translation.use_source', LOCALE_TRANSLATION_USE_SOURCE_LOCAL) ->save(); $this->drupalLogin($this->adminUser); diff -r e200cb7efeb3 -r c2387f117808 core/modules/config_translation/tests/src/Kernel/Migrate/d6/MigrateUserProfileFieldInstanceTranslationTest.php --- a/core/modules/config_translation/tests/src/Kernel/Migrate/d6/MigrateUserProfileFieldInstanceTranslationTest.php Thu Apr 26 11:26:54 2018 +0100 +++ b/core/modules/config_translation/tests/src/Kernel/Migrate/d6/MigrateUserProfileFieldInstanceTranslationTest.php Tue Jul 10 15:07:59 2018 +0100 @@ -28,7 +28,7 @@ ]); $language_manager = $this->container->get('language_manager'); - $config_translation = $language_manager->getLanguageConfigOverride('fr', 'field.field.user.user.profile_love_migrations'); + $config_translation = $language_manager->getLanguageConfigOverride('fr', 'field.field.user.user.profile_really_really_love_mig'); $this->assertSame("J'aime les migrations", $config_translation->get('label')); $this->assertSame("Si vous cochez cette case, vous aimez les migrations.", $config_translation->get('description')); diff -r e200cb7efeb3 -r c2387f117808 core/modules/contact/src/Controller/ContactController.php --- a/core/modules/contact/src/Controller/ContactController.php Thu Apr 26 11:26:54 2018 +0100 +++ b/core/modules/contact/src/Controller/ContactController.php Tue Jul 10 15:07:59 2018 +0100 @@ -47,7 +47,8 @@ * The contact form to use. * * @return array - * The form as render array as expected by drupal_render(). + * The form as render array as expected by + * \Drupal\Core\Render\RendererInterface::render(). * * @throws \Symfony\Component\HttpKernel\Exception\NotFoundHttpException * Exception is thrown when user tries to access non existing default @@ -95,7 +96,8 @@ * The account for which a personal contact form should be generated. * * @return array - * The personal contact form as render array as expected by drupal_render(). + * The personal contact form as render array as expected by + * \Drupal\Core\Render\RendererInterface::render(). * * @throws \Symfony\Component\HttpKernel\Exception\NotFoundHttpException * Exception is thrown when user tries to access a contact form for a diff -r e200cb7efeb3 -r c2387f117808 core/modules/contact/tests/src/Functional/Hal/ContactFormHalJsonAnonTest.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/core/modules/contact/tests/src/Functional/Hal/ContactFormHalJsonAnonTest.php Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,30 @@ + [ + 'type' => [ + 'href' => $this->baseUrl . '/rest/type/contact_message/camelids', + ], + ], + ]; + } + +} diff -r e200cb7efeb3 -r c2387f117808 core/modules/contact/tests/src/Functional/Hal/MessageHalJsonBasicAuthTest.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/core/modules/contact/tests/src/Functional/Hal/MessageHalJsonBasicAuthTest.php Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,24 @@ +grantPermissionsToTestedRole(['access site-wide contact form']); + default: + $this->grantPermissionsToTestedRole(['administer contact forms']); + } + } + + /** + * {@inheritdoc} + */ + protected function createEntity() { + $contact_form = ContactForm::create([ + 'id' => 'llama', + 'label' => 'Llama', + 'message' => 'Let us know what you think about llamas', + 'reply' => 'Llamas are indeed awesome!', + 'recipients' => [ + 'llama@example.com', + 'contact@example.com', + ], + ]); + $contact_form->save(); + + return $contact_form; + } + + /** + * {@inheritdoc} + */ + protected function getExpectedNormalizedEntity() { + return [ + 'dependencies' => [], + 'id' => 'llama', + 'label' => 'Llama', + 'langcode' => 'en', + 'message' => 'Let us know what you think about llamas', + 'recipients' => [ + 'llama@example.com', + 'contact@example.com', + ], + 'redirect' => NULL, + 'reply' => 'Llamas are indeed awesome!', + 'status' => TRUE, + 'uuid' => $this->entity->uuid(), + 'weight' => 0, + ]; + } + + /** + * {@inheritdoc} + */ + protected function getNormalizedPostEntity() { + // @todo Update in https://www.drupal.org/node/2300677. + } + + /** + * {@inheritdoc} + */ + protected function getExpectedUnauthorizedAccessMessage($method) { + if ($this->config('rest.settings')->get('bc_entity_resource_permissions')) { + return parent::getExpectedUnauthorizedAccessMessage($method); + } + + return "The 'access site-wide contact form' permission is required."; + } + +} diff -r e200cb7efeb3 -r c2387f117808 core/modules/contact/tests/src/Functional/Rest/ContactFormXmlAnonTest.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/core/modules/contact/tests/src/Functional/Rest/ContactFormXmlAnonTest.php Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,26 @@ +grantPermissionsToTestedRole(['access site-wide contact form']); + } + + /** + * {@inheritdoc} + */ + protected function createEntity() { + if (!ContactForm::load('camelids')) { + // Create a "Camelids" contact form. + ContactForm::create([ + 'id' => 'camelids', + 'label' => 'Llama', + 'message' => 'Let us know what you think about llamas', + 'reply' => 'Llamas are indeed awesome!', + 'recipients' => [ + 'llama@example.com', + 'contact@example.com', + ], + ])->save(); + } + + $message = Message::create([ + 'contact_form' => 'camelids', + 'subject' => 'Llama Gabilondo', + 'message' => 'Llamas are awesome!', + ]); + $message->save(); + + return $message; + } + + /** + * {@inheritdoc} + */ + protected function getNormalizedPostEntity() { + return [ + 'subject' => [ + [ + 'value' => 'Dramallama', + ], + ], + 'contact_form' => [ + [ + 'target_id' => 'camelids', + ], + ], + 'message' => [ + [ + 'value' => 'http://www.urbandictionary.com/define.php?term=drama%20llama', + ], + ], + ]; + } + + /** + * {@inheritdoc} + */ + protected function getExpectedNormalizedEntity() { + throw new \Exception('Not yet supported.'); + } + + /** + * {@inheritdoc} + */ + protected function getExpectedUnauthorizedAccessMessage($method) { + if ($this->config('rest.settings')->get('bc_entity_resource_permissions')) { + return parent::getExpectedUnauthorizedAccessMessage($method); + } + + if ($method === 'POST') { + return "The 'access site-wide contact form' permission is required."; + } + return parent::getExpectedUnauthorizedAccessMessage($method); + } + + /** + * {@inheritdoc} + */ + public function testGet() { + // Contact Message entities are not stored, so they cannot be retrieved. + $this->setExpectedException(RouteNotFoundException::class, 'Route "rest.entity.contact_message.GET" does not exist.'); + + $this->provisionEntityResource(); + Url::fromRoute('rest.entity.contact_message.GET')->toString(TRUE); + } + + /** + * {@inheritdoc} + */ + public function testPatch() { + // Contact Message entities are not stored, so they cannot be modified. + $this->setExpectedException(RouteNotFoundException::class, 'Route "rest.entity.contact_message.PATCH" does not exist.'); + + $this->provisionEntityResource(); + Url::fromRoute('rest.entity.contact_message.PATCH')->toString(TRUE); + } + + /** + * {@inheritdoc} + */ + public function testDelete() { + // Contact Message entities are not stored, so they cannot be deleted. + $this->setExpectedException(RouteNotFoundException::class, 'Route "rest.entity.contact_message.DELETE" does not exist.'); + + $this->provisionEntityResource(); + Url::fromRoute('rest.entity.contact_message.DELETE')->toString(TRUE); + } + +} diff -r e200cb7efeb3 -r c2387f117808 core/modules/contact/tests/src/Functional/Rest/MessageXmlAnonTest.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/core/modules/contact/tests/src/Functional/Rest/MessageXmlAnonTest.php Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,26 @@ +entityTypeManager()->getDefinition('node'); diff -r e200cb7efeb3 -r c2387f117808 core/modules/content_moderation/src/Entity/Handler/NodeModerationHandler.php --- a/core/modules/content_moderation/src/Entity/Handler/NodeModerationHandler.php Thu Apr 26 11:26:54 2018 +0100 +++ b/core/modules/content_moderation/src/Entity/Handler/NodeModerationHandler.php Tue Jul 10 15:07:59 2018 +0100 @@ -54,7 +54,7 @@ */ public function enforceRevisionsBundleFormAlter(array &$form, FormStateInterface $form_state, $form_id) { // Force the revision checkbox on. - $form['workflow']['options']['#default_value']['revision'] = 'revision'; + $form['workflow']['options']['#value']['revision'] = 'revision'; $form['workflow']['options']['revision']['#disabled'] = TRUE; } diff -r e200cb7efeb3 -r c2387f117808 core/modules/content_moderation/src/EntityOperations.php --- a/core/modules/content_moderation/src/EntityOperations.php Thu Apr 26 11:26:54 2018 +0100 +++ b/core/modules/content_moderation/src/EntityOperations.php Tue Jul 10 15:07:59 2018 +0100 @@ -203,7 +203,6 @@ $moderation_state = $workflow->getTypePlugin()->getInitialState($entity)->id(); } - // @todo what if $entity->moderation_state is null at this point? $content_moderation_state->set('content_entity_revision_id', $entity_revision_id); $content_moderation_state->set('moderation_state', $moderation_state); ContentModerationStateEntity::updateOrCreateFromEntity($content_moderation_state); diff -r e200cb7efeb3 -r c2387f117808 core/modules/content_moderation/src/EntityTypeInfo.php --- a/core/modules/content_moderation/src/EntityTypeInfo.php Thu Apr 26 11:26:54 2018 +0100 +++ b/core/modules/content_moderation/src/EntityTypeInfo.php Tue Jul 10 15:07:59 2018 +0100 @@ -131,7 +131,7 @@ public function entityTypeAlter(array &$entity_types) { foreach ($entity_types as $entity_type_id => $entity_type) { // The ContentModerationState entity type should never be moderated. - if ($entity_type->isRevisionable() && $entity_type_id != 'content_moderation_state') { + if ($entity_type->isRevisionable() && !$entity_type->isInternal()) { $entity_types[$entity_type_id] = $this->addModerationToEntityType($entity_type); } } diff -r e200cb7efeb3 -r c2387f117808 core/modules/content_moderation/src/Form/EntityModerationForm.php --- a/core/modules/content_moderation/src/Form/EntityModerationForm.php Thu Apr 26 11:26:54 2018 +0100 +++ b/core/modules/content_moderation/src/Form/EntityModerationForm.php Tue Jul 10 15:07:59 2018 +0100 @@ -128,6 +128,7 @@ ]; $form['#theme'] = ['entity_moderation_form']; + $form['#attached']['library'][] = 'content_moderation/content_moderation'; return $form; } diff -r e200cb7efeb3 -r c2387f117808 core/modules/content_moderation/src/Plugin/Field/FieldWidget/ModerationStateWidget.php --- a/core/modules/content_moderation/src/Plugin/Field/FieldWidget/ModerationStateWidget.php Thu Apr 26 11:26:54 2018 +0100 +++ b/core/modules/content_moderation/src/Plugin/Field/FieldWidget/ModerationStateWidget.php Tue Jul 10 15:07:59 2018 +0100 @@ -131,6 +131,9 @@ foreach ($transitions as $transition) { $transition_to_state = $transition->to(); $transition_labels[$transition_to_state->id()] = $transition_to_state->label(); + if ($default->id() === $transition_to_state->id()) { + $default_value = $default->id(); + } } $element += [ diff -r e200cb7efeb3 -r c2387f117808 core/modules/content_moderation/src/Plugin/Field/ModerationStateFieldItemList.php --- a/core/modules/content_moderation/src/Plugin/Field/ModerationStateFieldItemList.php Thu Apr 26 11:26:54 2018 +0100 +++ b/core/modules/content_moderation/src/Plugin/Field/ModerationStateFieldItemList.php Tue Jul 10 15:07:59 2018 +0100 @@ -141,11 +141,13 @@ public function setValue($values, $notify = TRUE) { parent::setValue($values, $notify); + if (isset($this->list[0])) { + $this->valueComputed = TRUE; + } // If the parent created a field item and if the parent should be notified // about the change (e.g. this is not initialized with the current value), // update the moderated entity. if (isset($this->list[0]) && $notify) { - $this->valueComputed = TRUE; $this->updateModeratedEntity($this->list[0]->value); } } diff -r e200cb7efeb3 -r c2387f117808 core/modules/content_moderation/templates/entity-moderation-form.html.twig --- a/core/modules/content_moderation/templates/entity-moderation-form.html.twig Thu Apr 26 11:26:54 2018 +0100 +++ b/core/modules/content_moderation/templates/entity-moderation-form.html.twig Tue Jul 10 15:07:59 2018 +0100 @@ -1,4 +1,3 @@ -{{ attach_library('content_moderation/content_moderation') }}
  • {{ form.current }}
  • {{ form.new_state }}
  • diff -r e200cb7efeb3 -r c2387f117808 core/modules/content_moderation/tests/src/Functional/DefaultContentModerationStateRevisionUpdateTest.php --- a/core/modules/content_moderation/tests/src/Functional/DefaultContentModerationStateRevisionUpdateTest.php Thu Apr 26 11:26:54 2018 +0100 +++ b/core/modules/content_moderation/tests/src/Functional/DefaultContentModerationStateRevisionUpdateTest.php Tue Jul 10 15:07:59 2018 +0100 @@ -20,7 +20,6 @@ $this->databaseDumpFiles = [ __DIR__ . '/../../../../system/tests/fixtures/update/drupal-8.4.0.bare.standard.php.gz', __DIR__ . '/../../fixtures/update/drupal-8.4.0-content_moderation_installed.php', - __DIR__ . '/../../fixtures/update/drupal-8.default-cms-entity-id-2941736.php', ]; } @@ -28,6 +27,11 @@ * Test updating the default revision. */ public function testUpdateDefaultRevision() { + // Include the database fixture required to test updating the default + // revision. This is excluded from ::setDatabaseDumpFiles so that we can + // test the same post_update hook with no test content enabled. + require __DIR__ . '/../../fixtures/update/drupal-8.default-cms-entity-id-2941736.php'; + $this->runUpdates(); foreach (['node', 'block_content'] as $entity_type_id) { @@ -46,6 +50,14 @@ } /** + * Test the post_update hook when no entity types are being moderated. + */ + public function testNoEntitiesUnderModeration() { + // If any errors occur during the post_update hook, the test case will fail. + $this->runUpdates(); + } + + /** * Assert for the given entity, the default revision ID matches. * * @param \Drupal\Core\Entity\ContentEntityInterface $entity diff -r e200cb7efeb3 -r c2387f117808 core/modules/content_moderation/tests/src/Functional/ModerationFormTest.php --- a/core/modules/content_moderation/tests/src/Functional/ModerationFormTest.php Thu Apr 26 11:26:54 2018 +0100 +++ b/core/modules/content_moderation/tests/src/Functional/ModerationFormTest.php Tue Jul 10 15:07:59 2018 +0100 @@ -107,6 +107,10 @@ 'moderation_state[0][state]' => 'published', ], t('Save')); + // Check widget default value. + $this->drupalGet($edit_path); + $this->assertFieldByName('moderation_state[0][state]', 'published', 'The moderation default value is set correctly.'); + // The published view should not have a moderation form, because it is the // live revision. $this->drupalGet($canonical_path); diff -r e200cb7efeb3 -r c2387f117808 core/modules/content_moderation/tests/src/Functional/ModerationStateTestBase.php --- a/core/modules/content_moderation/tests/src/Functional/ModerationStateTestBase.php Thu Apr 26 11:26:54 2018 +0100 +++ b/core/modules/content_moderation/tests/src/Functional/ModerationStateTestBase.php Tue Jul 10 15:07:59 2018 +0100 @@ -3,6 +3,7 @@ namespace Drupal\Tests\content_moderation\Functional; use Drupal\Core\Session\AccountInterface; +use Drupal\node\Entity\NodeType; use Drupal\Tests\BrowserTestBase; use Drupal\user\Entity\Role; @@ -110,6 +111,9 @@ ]; $this->drupalPostForm(NULL, $edit, t('Save content type')); + // Check the content type has been set to create new revisions. + $this->assertTrue(NodeType::load($content_type_id)->isNewRevision()); + if ($moderated) { $this->enableModerationThroughUi($content_type_id, $workflow_id); } diff -r e200cb7efeb3 -r c2387f117808 core/modules/content_moderation/tests/src/Kernel/EntityTypeInfoTest.php --- a/core/modules/content_moderation/tests/src/Kernel/EntityTypeInfoTest.php Thu Apr 26 11:26:54 2018 +0100 +++ b/core/modules/content_moderation/tests/src/Kernel/EntityTypeInfoTest.php Tue Jul 10 15:07:59 2018 +0100 @@ -61,4 +61,34 @@ $this->assertTrue($base_fields['moderation_state']->isTranslatable()); } + /** + * Test the correct entity types have moderation added. + * + * @covers ::entityTypeAlter + * + * @dataProvider providerTestEntityTypeAlter + */ + public function testEntityTypeAlter($entity_type_id, $moderatable) { + $entity_types = $this->entityTypeManager->getDefinitions(); + $this->assertSame($moderatable, $entity_types[$entity_type_id]->hasHandlerClass('moderation')); + } + + /** + * Provides test data for testEntityTypeAlter(). + * + * @return array + * An array of test cases, where each test case is an array with the + * following values: + * - An entity type ID. + * - Whether the entity type is moderatable or not. + */ + public function providerTestEntityTypeAlter() { + $tests = []; + $tests['non_internal_non_revisionable'] = ['entity_test', FALSE]; + $tests['non_internal_revisionable'] = ['entity_test_rev', TRUE]; + $tests['internal_non_revisionable'] = ['entity_test_no_label', FALSE]; + $tests['internal_revisionable'] = ['content_moderation_state', FALSE]; + return $tests; + } + } diff -r e200cb7efeb3 -r c2387f117808 core/modules/content_moderation/tests/src/Kernel/ModerationInformationTest.php --- a/core/modules/content_moderation/tests/src/Kernel/ModerationInformationTest.php Thu Apr 26 11:26:54 2018 +0100 +++ b/core/modules/content_moderation/tests/src/Kernel/ModerationInformationTest.php Tue Jul 10 15:07:59 2018 +0100 @@ -2,8 +2,10 @@ namespace Drupal\Tests\content_moderation\Kernel; +use Drupal\entity_test\Entity\EntityTestMulRevPub; use Drupal\entity_test\Entity\EntityTestRev; use Drupal\KernelTests\KernelTestBase; +use Drupal\language\Entity\ConfigurableLanguage; use Drupal\workflows\Entity\Workflow; /** @@ -15,7 +17,21 @@ /** * {@inheritdoc} */ - public static $modules = ['content_moderation', 'entity_test', 'user', 'workflows']; + public static $modules = [ + 'content_moderation', + 'entity_test', + 'user', + 'workflows', + 'language', + 'content_translation', + ]; + + /** + * The moderation information service. + * + * @var \Drupal\content_moderation\ModerationInformationInterface + */ + protected $moderationInformation; /** * {@inheritdoc} @@ -24,8 +40,20 @@ parent::setUp(); $this->installEntitySchema('entity_test_rev'); + $this->installEntitySchema('entity_test_mulrevpub'); $this->installEntitySchema('content_moderation_state'); $this->installConfig(['content_moderation']); + + $this->moderationInformation = $this->container->get('content_moderation.moderation_information'); + + ConfigurableLanguage::createFromLangcode('de')->save(); + + $workflow = Workflow::load('editorial'); + $workflow->getTypePlugin()->addEntityTypeAndBundle('entity_test_mulrevpub', 'entity_test_mulrevpub'); + $workflow->getTypePlugin()->addEntityTypeAndBundle('entity_test_rev', 'entity_test_rev'); + $workflow->save(); + + $this->container->get('content_translation.manager')->setEnabled('entity_test_mulrevpub', 'entity_test_mulrevpub', TRUE); } /** @@ -33,10 +61,6 @@ * @covers ::getLatestRevisionId */ public function testDefaultAndLatestRevisionId() { - $workflow = Workflow::load('editorial'); - $workflow->getTypePlugin()->addEntityTypeAndBundle('entity_test_rev', 'entity_test_rev'); - $workflow->save(); - $entity_test_rev = EntityTestRev::create([ 'name' => 'Default Revision', 'moderation_state' => 'published', @@ -47,18 +71,85 @@ $entity_test_rev->moderation_state = 'draft'; $entity_test_rev->save(); - /** @var \Drupal\content_moderation\ModerationInformationInterface $moderation_info */ - $moderation_info = \Drupal::service('content_moderation.moderation_information'); - // Check that moderation information service returns the correct default // revision ID. - $default_revision_id = $moderation_info->getDefaultRevisionId('entity_test_rev', $entity_test_rev->id()); + $default_revision_id = $this->moderationInformation->getDefaultRevisionId('entity_test_rev', $entity_test_rev->id()); $this->assertSame(1, $default_revision_id); // Check that moderation information service returns the correct latest // revision ID. - $latest_revision_id = $moderation_info->getLatestRevisionId('entity_test_rev', $entity_test_rev->id()); + $latest_revision_id = $this->moderationInformation->getLatestRevisionId('entity_test_rev', $entity_test_rev->id()); $this->assertSame(2, $latest_revision_id); } + /** + * @covers ::isDefaultRevisionPublished + * @dataProvider isDefaultRevisionPublishedTestCases + */ + public function testIsDefaultRevisionPublished($initial_state, $final_state, $initial_is_default_published, $final_is_default_published) { + $entity = EntityTestMulRevPub::create([ + 'moderation_state' => $initial_state, + ]); + $entity->save(); + $this->assertEquals($initial_is_default_published, $this->moderationInformation->isDefaultRevisionPublished($entity)); + + $entity->moderation_state = $final_state; + $entity->save(); + $this->assertEquals($final_is_default_published, $this->moderationInformation->isDefaultRevisionPublished($entity)); + } + + /** + * Test cases for ::testIsDefaultRevisionPublished. + */ + public function isDefaultRevisionPublishedTestCases() { + return [ + 'Draft to draft' => [ + 'draft', + 'draft', + FALSE, + FALSE, + ], + 'Draft to published' => [ + 'draft', + 'published', + FALSE, + TRUE, + ], + 'Published to published' => [ + 'published', + 'published', + TRUE, + TRUE, + ], + 'Published to draft' => [ + 'published', + 'draft', + TRUE, + TRUE, + ], + ]; + } + + /** + * @covers ::isDefaultRevisionPublished + */ + public function testIsDefaultRevisionPublishedMultilingual() { + $entity = EntityTestMulRevPub::create([ + 'moderation_state' => 'draft', + ]); + $entity->save(); + $this->assertEquals('draft', $entity->moderation_state->value); + + $translated = $entity->addTranslation('de'); + $translated->moderation_state = 'published'; + $translated->save(); + $this->assertEquals('published', $translated->moderation_state->value); + + // Test a scenario where the default revision exists with the default + // language in a draft state and a non-default language in a published + // state. The method returns TRUE if any of the languages for the default + // revision are in a published state. + $this->assertEquals(TRUE, $this->moderationInformation->isDefaultRevisionPublished($entity)); + } + } diff -r e200cb7efeb3 -r c2387f117808 core/modules/content_moderation/tests/src/Kernel/ModerationStateFieldItemListTest.php --- a/core/modules/content_moderation/tests/src/Kernel/ModerationStateFieldItemListTest.php Thu Apr 26 11:26:54 2018 +0100 +++ b/core/modules/content_moderation/tests/src/Kernel/ModerationStateFieldItemListTest.php Tue Jul 10 15:07:59 2018 +0100 @@ -111,6 +111,9 @@ unset($this->testNode->moderation_state); $this->assertEquals('draft', $this->testNode->moderation_state->value); + + $this->testNode->moderation_state = NULL; + $this->assertEquals('draft', $this->testNode->moderation_state->value); } /** @@ -130,22 +133,58 @@ /** * Tests that moderation state changes also change the related entity state. + * + * @dataProvider moderationStateChangesTestCases */ - public function testModerationStateChanges() { - // Change the moderation state and check that the entity's - // 'isDefaultRevision' flag and the publishing status have also been - // updated. - $this->testNode->moderation_state->value = 'published'; - - $this->assertTrue($this->testNode->isPublished()); - $this->assertTrue($this->testNode->isDefaultRevision()); - + public function testModerationStateChanges($initial_state, $final_state, $first_published, $first_is_default, $second_published, $second_is_default) { + $this->testNode->moderation_state->value = $initial_state; + $this->assertEquals($first_published, $this->testNode->isPublished()); + $this->assertEquals($first_is_default, $this->testNode->isDefaultRevision()); $this->testNode->save(); - // Repeat the checks using an 'unpublished' state. - $this->testNode->moderation_state->value = 'draft'; - $this->assertFalse($this->testNode->isPublished()); - $this->assertFalse($this->testNode->isDefaultRevision()); + $this->testNode->moderation_state->value = $final_state; + $this->assertEquals($second_published, $this->testNode->isPublished()); + $this->assertEquals($second_is_default, $this->testNode->isDefaultRevision()); + } + + /** + * Data provider for ::testModerationStateChanges + */ + public function moderationStateChangesTestCases() { + return [ + 'Draft to draft' => [ + 'draft', + 'draft', + FALSE, + TRUE, + FALSE, + TRUE, + ], + 'Draft to published' => [ + 'draft', + 'published', + FALSE, + TRUE, + TRUE, + TRUE, + ], + 'Published to published' => [ + 'published', + 'published', + TRUE, + TRUE, + TRUE, + TRUE, + ], + 'Published to draft' => [ + 'published', + 'draft', + TRUE, + TRUE, + FALSE, + FALSE, + ], + ]; } /** @@ -175,13 +214,39 @@ /** * Test the moderation_state field after an entity has been serialized. + * + * @dataProvider entityUnserializeTestCases */ - public function testEntityUnserialize() { - $this->testNode->moderation_state->value = 'draft'; + public function testEntityUnserialize($state, $default, $published) { + $this->testNode->moderation_state->value = $state; + + $this->assertEquals($state, $this->testNode->moderation_state->value); + $this->assertEquals($default, $this->testNode->isDefaultRevision()); + $this->assertEquals($published, $this->testNode->isPublished()); + $unserialized = unserialize(serialize($this->testNode)); - $this->assertEquals('Test title', $unserialized->title->value); - $this->assertEquals('draft', $unserialized->moderation_state->value); + $this->assertEquals($state, $unserialized->moderation_state->value); + $this->assertEquals($default, $unserialized->isDefaultRevision()); + $this->assertEquals($published, $unserialized->isPublished()); + } + + /** + * Test cases for ::testEntityUnserialize. + */ + public function entityUnserializeTestCases() { + return [ + 'Default draft state' => [ + 'draft', + TRUE, + FALSE, + ], + 'Non-default published state' => [ + 'published', + TRUE, + TRUE, + ], + ]; } } diff -r e200cb7efeb3 -r c2387f117808 core/modules/content_translation/migrations/d7_entity_translation_settings.yml --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/core/modules/content_translation/migrations/d7_entity_translation_settings.yml Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,36 @@ +id: d7_entity_translation_settings +label: Drupal 7 Entity Translation settings +migration_tags: + - Drupal 7 + - Configuration +source: + plugin: d7_entity_translation_settings +process: + id: id + target_entity_type_id: target_entity_type_id + target_bundle: target_bundle + default_langcode: + plugin: static_map + source: default_langcode + bypass: true + map: + xx-et-default: site_default + xx-et-current: current_interface + xx-et-author: authors_default + language_alterable: language_alterable + third_party_settings/content_translation/enabled: + plugin: default_value + default_value: true + third_party_settings/content_translation/bundle_settings/untranslatable_fields_hide: untranslatable_fields_hide +destination: + plugin: entity:language_content_settings + content_translation_update_definitions: + - comment + - node + - taxonomy_term + - user +migration_dependencies: + optional: + - d7_comment_type + - d7_node_type + - d7_taxonomy_vocabulary diff -r e200cb7efeb3 -r c2387f117808 core/modules/content_translation/src/ContentTranslationHandler.php --- a/core/modules/content_translation/src/ContentTranslationHandler.php Thu Apr 26 11:26:54 2018 +0100 +++ b/core/modules/content_translation/src/ContentTranslationHandler.php Tue Jul 10 15:07:59 2018 +0100 @@ -743,7 +743,7 @@ * Takes care of entity deletion. */ public function entityFormDelete($form, FormStateInterface $form_state) { - $form_object = $form_state->getFormObject()->getEntity(); + $form_object = $form_state->getFormObject(); $entity = $form_object->getEntity(); if (count($entity->getTranslationLanguages()) > 1) { drupal_set_message(t('This will delete all the translations of %label.', ['%label' => $entity->label()]), 'warning'); diff -r e200cb7efeb3 -r c2387f117808 core/modules/content_translation/src/Plugin/migrate/source/d7/EntityTranslationSettings.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/core/modules/content_translation/src/Plugin/migrate/source/d7/EntityTranslationSettings.php Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,195 @@ +select('variable', 'v') + ->fields('v', ['name', 'value']); + $condition = $query->orConditionGroup() + // The 'entity_translation_entity_types' variable tells us which entity + // type uses entity translation. + ->condition('name', 'entity_translation_entity_types') + // The 'entity_translation_taxonomy' variable tells us which taxonomy + // vocabulary uses entity_translation. + ->condition('name', 'entity_translation_taxonomy') + // The 'entity_translation_settings_%' variables give us the entity + // translation settings for each entity type and each bundle. + ->condition('name', 'entity_translation_settings_%', 'LIKE') + // The 'language_content_type_%' variables tells us which node type and + // which comment type uses entity translation. + ->condition('name', 'language_content_type_%', 'LIKE'); + $query->condition($condition); + return $query; + } + + /** + * {@inheritdoc} + */ + protected function initializeIterator() { + $results = array_map('unserialize', $this->prepareQuery()->execute()->fetchAllKeyed()); + $rows = []; + + // Find out which entity type uses entity translation by looking at the + // 'entity_translation_entity_types' variable. + $entity_types = array_filter($results['entity_translation_entity_types']); + + // If no entity type uses entity translation, there's nothing to do. + if (empty($entity_types)) { + return new \ArrayIterator($rows); + } + + // Find out which node type uses entity translation by looking at the + // 'language_content_type_%' variables. + $node_types = []; + foreach ($results as $name => $value) { + if (preg_match('/^language_content_type_(.+)$/', $name, $matches) && (int) $value === 4) { + $node_types[] = $matches[1]; + } + } + + // Find out which vocabulary uses entity translation by looking at the + // 'entity_translation_taxonomy' variable. + $vocabularies = array_keys(array_filter($results['entity_translation_taxonomy'])); + + if (in_array('node', $entity_types, TRUE) && !empty($node_types)) { + // For each node type that uses entity translation, check if a + // settings variable exists for that node type, otherwise use default + // values. + foreach ($node_types as $node_type) { + $settings = isset($results['entity_translation_settings_node__' . $node_type]) ? $results['entity_translation_settings_node__' . $node_type] : []; + $rows[] = [ + 'id' => 'node.' . $node_type, + 'target_entity_type_id' => 'node', + 'target_bundle' => $node_type, + 'default_langcode' => isset($settings['default_language']) ? $settings['default_language'] : 'und', + // The Drupal 7 'hide_language_selector' configuration has become + // 'language_alterable' in Drupal 8 so we need to negate the value we + // receive from the source. The Drupal 7 'hide_language_selector' + // default value for the node entity type was FALSE so in Drupal 8 it + // should be set to TRUE, unlike the other entity types for which + // it's the opposite. + 'language_alterable' => isset($settings['hide_language_selector']) ? (bool) !$settings['hide_language_selector'] : TRUE, + 'untranslatable_fields_hide' => isset($settings['shared_fields_original_only']) ? (bool) $settings['shared_fields_original_only'] : FALSE, + ]; + } + } + + if (in_array('comment', $entity_types, TRUE) && !empty($node_types)) { + // A comment type uses entity translation if the associated node type + // uses it. So, for each node type that uses entity translation, check + // if a settings variable exists for that comment type, otherwise use + // default values. + foreach ($node_types as $node_type) { + $settings = isset($results['entity_translation_settings_comment__comment_node_' . $node_type]) ? $results['entity_translation_settings_comment__comment_node_' . $node_type] : []; + // Forum uses a hardcoded comment type name, so make sure we use it + // when we're dealing with forum comment type. + $bundle = $node_type == 'forum' ? 'comment_forum' : 'comment_node_' . $node_type; + $rows[] = [ + 'id' => 'comment.' . $bundle, + 'target_entity_type_id' => 'comment', + 'target_bundle' => $bundle, + 'default_langcode' => isset($settings['default_language']) ? $settings['default_language'] : 'xx-et-current', + // The Drupal 7 'hide_language_selector' configuration has become + // 'language_alterable' in Drupal 8 so we need to negate the value we + // receive from the source. The Drupal 7 'hide_language_selector' + // default value for the comment entity type was TRUE so in Drupal 8 + // it should be set to FALSE. + 'language_alterable' => isset($settings['hide_language_selector']) ? (bool) !$settings['hide_language_selector'] : FALSE, + 'untranslatable_fields_hide' => isset($settings['shared_fields_original_only']) ? (bool) $settings['shared_fields_original_only'] : FALSE, + ]; + } + } + + if (in_array('taxonomy_term', $entity_types, TRUE) && !empty($vocabularies)) { + // For each vocabulary that uses entity translation, check if a + // settings variable exists for that vocabulary, otherwise use default + // values. + foreach ($vocabularies as $vocabulary) { + $settings = isset($results['entity_translation_settings_taxonomy_term__' . $vocabulary]) ? $results['entity_translation_settings_taxonomy_term__' . $vocabulary] : []; + $rows[] = [ + 'id' => 'taxonomy_term.' . $vocabulary, + 'target_entity_type_id' => 'taxonomy_term', + 'target_bundle' => $vocabulary, + 'default_langcode' => isset($settings['default_language']) ? $settings['default_language'] : 'xx-et-default', + // The Drupal 7 'hide_language_selector' configuration has become + // 'language_alterable' in Drupal 8 so we need to negate the value we + // receive from the source. The Drupal 7 'hide_language_selector' + // default value for the taxonomy_term entity type was TRUE so in + // Drupal 8 it should be set to FALSE. + 'language_alterable' => isset($settings['hide_language_selector']) ? (bool) !$settings['hide_language_selector'] : FALSE, + 'untranslatable_fields_hide' => isset($settings['shared_fields_original_only']) ? (bool) $settings['shared_fields_original_only'] : FALSE, + ]; + } + } + + if (in_array('user', $entity_types, TRUE)) { + // User entity type is not bundleable. Check if a settings variable + // exists, otherwise use default values. + $settings = isset($results['entity_translation_settings_user__user']) ? $results['entity_translation_settings_user__user'] : []; + $rows[] = [ + 'id' => 'user.user', + 'target_entity_type_id' => 'user', + 'target_bundle' => 'user', + 'default_langcode' => isset($settings['default_language']) ? $settings['default_language'] : 'xx-et-default', + // The Drupal 7 'hide_language_selector' configuration has become + // 'language_alterable' in Drupal 8 so we need to negate the value we + // receive from the source. The Drupal 7 'hide_language_selector' + // default value for the user entity type was TRUE so in Drupal 8 it + // should be set to FALSE. + 'language_alterable' => isset($settings['hide_language_selector']) ? (bool) !$settings['hide_language_selector'] : FALSE, + 'untranslatable_fields_hide' => isset($settings['shared_fields_original_only']) ? (bool) $settings['shared_fields_original_only'] : FALSE, + ]; + } + + return new \ArrayIterator($rows); + } + + /** + * {@inheritdoc} + */ + public function fields() { + return [ + 'id' => $this->t('The configuration ID'), + 'target_entity_type_id' => $this->t('The target entity type ID'), + 'target_bundle' => $this->t('The target bundle'), + 'default_langcode' => $this->t('The default language'), + 'language_alterable' => $this->t('Whether to show language selector on create and edit pages'), + 'untranslatable_fields_hide' => $this->t('Whether to hide non translatable fields on translation forms'), + ]; + } + + /** + * {@inheritdoc} + */ + public function getIds() { + $ids['id']['type'] = 'string'; + return $ids; + } + + /** + * {@inheritdoc} + */ + public function count($refresh = FALSE) { + // Since the number of variables we fetch with query() does not match the + // actual number of rows generated by initializeIterator(), we need to + // override count() to return the correct count. + return (int) $this->initializeIterator()->count(); + } + +} diff -r e200cb7efeb3 -r c2387f117808 core/modules/content_translation/tests/src/Kernel/Migrate/d6/MigrateTaxonomyTermTranslationTest.php --- a/core/modules/content_translation/tests/src/Kernel/Migrate/d6/MigrateTaxonomyTermTranslationTest.php Thu Apr 26 11:26:54 2018 +0100 +++ b/core/modules/content_translation/tests/src/Kernel/Migrate/d6/MigrateTaxonomyTermTranslationTest.php Tue Jul 10 15:07:59 2018 +0100 @@ -78,7 +78,7 @@ $this->assertInstanceOf(TermInterface::class, $entity); $this->assertSame($expected_language, $entity->language()->getId()); $this->assertSame($expected_label, $entity->label()); - $this->assertSame($expected_vid, $entity->getVocabularyId()); + $this->assertSame($expected_vid, $entity->bundle()); $this->assertSame($expected_description, $entity->getDescription()); $this->assertSame($expected_format, $entity->getFormat()); $this->assertSame($expected_weight, $entity->getWeight()); diff -r e200cb7efeb3 -r c2387f117808 core/modules/content_translation/tests/src/Kernel/Migrate/d7/MigrateEntityTranslationSettingsTest.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/core/modules/content_translation/tests/src/Kernel/Migrate/d7/MigrateEntityTranslationSettingsTest.php Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,97 @@ +installConfig([ + 'comment', + 'content_translation', + 'node', + 'taxonomy', + 'user', + ]); + + $this->installEntitySchema('comment'); + $this->installEntitySchema('node'); + $this->installEntitySchema('taxonomy_term'); + $this->installEntitySchema('user'); + + $this->executeMigrations([ + 'd7_comment_type', + 'd7_node_type', + 'd7_taxonomy_vocabulary', + 'd7_entity_translation_settings', + ]); + } + + /** + * Tests entity translation settings migration. + */ + public function testEntityTranslationSettingsMigration() { + // Tests 'comment_node_test_content_type' entity translation settings. + $config = $this->config('language.content_settings.comment.comment_node_test_content_type'); + $this->assertSame($config->get('target_entity_type_id'), 'comment'); + $this->assertSame($config->get('target_bundle'), 'comment_node_test_content_type'); + $this->assertSame($config->get('default_langcode'), 'current_interface'); + $this->assertFalse((bool) $config->get('language_alterable')); + $this->assertTrue((bool) $config->get('third_party_settings.content_translation.enabled')); + $this->assertFalse((bool) $config->get('third_party_settings.content_translation.bundle_settings.untranslatable_fields_hide')); + + // Tests 'test_content_type' entity translation settings. + $config = $this->config('language.content_settings.node.test_content_type'); + $this->assertSame($config->get('target_entity_type_id'), 'node'); + $this->assertSame($config->get('target_bundle'), 'test_content_type'); + $this->assertSame($config->get('default_langcode'), LanguageInterface::LANGCODE_NOT_SPECIFIED); + $this->assertTrue((bool) $config->get('language_alterable')); + $this->assertTrue((bool) $config->get('third_party_settings.content_translation.enabled')); + $this->assertFalse((bool) $config->get('third_party_settings.content_translation.bundle_settings.untranslatable_fields_hide')); + + // Tests 'test_vocabulary' entity translation settings. + $config = $this->config('language.content_settings.taxonomy_term.test_vocabulary'); + $this->assertSame($config->get('target_entity_type_id'), 'taxonomy_term'); + $this->assertSame($config->get('target_bundle'), 'test_vocabulary'); + $this->assertSame($config->get('default_langcode'), LanguageInterface::LANGCODE_SITE_DEFAULT); + $this->assertFalse((bool) $config->get('language_alterable')); + $this->assertTrue((bool) $config->get('third_party_settings.content_translation.enabled')); + $this->assertFalse((bool) $config->get('third_party_settings.content_translation.bundle_settings.untranslatable_fields_hide')); + + // Tests 'user' entity translation settings. + $config = $this->config('language.content_settings.user.user'); + $this->assertSame($config->get('target_entity_type_id'), 'user'); + $this->assertSame($config->get('target_bundle'), 'user'); + $this->assertSame($config->get('default_langcode'), LanguageInterface::LANGCODE_SITE_DEFAULT); + $this->assertFalse((bool) $config->get('language_alterable')); + $this->assertTrue((bool) $config->get('third_party_settings.content_translation.enabled')); + $this->assertFalse((bool) $config->get('third_party_settings.content_translation.bundle_settings.untranslatable_fields_hide')); + } + +} diff -r e200cb7efeb3 -r c2387f117808 core/modules/content_translation/tests/src/Kernel/Plugin/migrate/source/d7/EntityTranslationSettingsTest.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/core/modules/content_translation/tests/src/Kernel/Plugin/migrate/source/d7/EntityTranslationSettingsTest.php Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,241 @@ + 'entity_translation_entity_types', + 'value' => 'a:4:{s:7:"comment";i:0;s:4:"node";i:0;s:13:"taxonomy_term";i:0;s:4:"user";i:0;}', + ], + ]; + + // Source data when there's no bundle settings variables. + $tests[1]['source_data']['variable'] = [ + [ + 'name' => 'entity_translation_entity_types', + 'value' => 'a:4:{s:7:"comment";s:7:"comment";s:4:"node";s:4:"node";s:13:"taxonomy_term";s:13:"taxonomy_term";s:4:"user";s:4:"user";}', + ], + [ + 'name' => 'entity_translation_taxonomy', + 'value' => 'a:3:{s:6:"forums";b:1;s:4:"tags";b:1;s:4:"test";b:0;}', + ], + [ + 'name' => 'language_content_type_article', + 'value' => 's:1:"2";', + ], + [ + 'name' => 'language_content_type_forum', + 'value' => 's:1:"4";', + ], + [ + 'name' => 'language_content_type_page', + 'value' => 's:1:"4";', + ], + ]; + + // Source data when there's bundle settings variables. + $tests[2]['source_data']['variable'] = [ + [ + 'name' => 'entity_translation_entity_types', + 'value' => 'a:4:{s:7:"comment";s:7:"comment";s:4:"node";s:4:"node";s:13:"taxonomy_term";s:13:"taxonomy_term";s:4:"user";s:4:"user";}', + ], + [ + 'name' => 'entity_translation_settings_comment__comment_node_forum', + 'value' => 'a:5:{s:16:"default_language";s:12:"xx-et-author";s:22:"hide_language_selector";i:1;s:21:"exclude_language_none";i:0;s:13:"lock_language";i:0;s:27:"shared_fields_original_only";i:0;}', + ], + [ + 'name' => 'entity_translation_settings_comment__comment_node_page', + 'value' => 'a:5:{s:16:"default_language";s:12:"xx-et-author";s:22:"hide_language_selector";i:0;s:21:"exclude_language_none";i:0;s:13:"lock_language";i:0;s:27:"shared_fields_original_only";i:1;}', + ], + [ + 'name' => 'entity_translation_settings_node__forum', + 'value' => 'a:5:{s:16:"default_language";s:12:"xx-et-author";s:22:"hide_language_selector";i:0;s:21:"exclude_language_none";i:0;s:13:"lock_language";i:0;s:27:"shared_fields_original_only";i:0;}', + ], + [ + 'name' => 'entity_translation_settings_node__page', + 'value' => 'a:5:{s:16:"default_language";s:13:"xx-et-default";s:22:"hide_language_selector";i:1;s:21:"exclude_language_none";i:0;s:13:"lock_language";i:0;s:27:"shared_fields_original_only";i:1;}', + ], + [ + 'name' => 'entity_translation_settings_taxonomy_term__forums', + 'value' => 'a:5:{s:16:"default_language";s:13:"xx-et-current";s:22:"hide_language_selector";i:0;s:21:"exclude_language_none";i:0;s:13:"lock_language";i:0;s:27:"shared_fields_original_only";i:1;}', + ], + [ + 'name' => 'entity_translation_settings_taxonomy_term__tags', + 'value' => 'a:5:{s:16:"default_language";s:13:"xx-et-current";s:22:"hide_language_selector";i:1;s:21:"exclude_language_none";i:0;s:13:"lock_language";i:0;s:27:"shared_fields_original_only";i:0;}', + ], + [ + 'name' => 'entity_translation_settings_user__user', + 'value' => 'a:5:{s:16:"default_language";s:12:"xx-et-author";s:22:"hide_language_selector";i:1;s:21:"exclude_language_none";i:0;s:13:"lock_language";i:0;s:27:"shared_fields_original_only";i:1;}', + ], + [ + 'name' => 'entity_translation_taxonomy', + 'value' => 'a:3:{s:6:"forums";b:1;s:4:"tags";b:1;s:4:"test";b:0;}', + ], + [ + 'name' => 'language_content_type_article', + 'value' => 's:1:"2";', + ], + [ + 'name' => 'language_content_type_forum', + 'value' => 's:1:"4";', + ], + [ + 'name' => 'language_content_type_page', + 'value' => 's:1:"4";', + ], + ]; + + // Expected data when there's no entity type that uses entity translation. + $tests[0]['expected_data'] = []; + + // Expected data when there's no bundle settings variables. + $tests[1]['expected_data'] = [ + [ + 'id' => 'node.forum', + 'target_entity_type_id' => 'node', + 'target_bundle' => 'forum', + 'default_langcode' => 'und', + 'language_alterable' => TRUE, + 'untranslatable_fields_hide' => FALSE, + ], + [ + 'id' => 'node.page', + 'target_entity_type_id' => 'node', + 'target_bundle' => 'page', + 'default_langcode' => 'und', + 'language_alterable' => TRUE, + 'untranslatable_fields_hide' => FALSE, + ], + [ + 'id' => 'comment.comment_forum', + 'target_entity_type_id' => 'comment', + 'target_bundle' => 'comment_forum', + 'default_langcode' => 'xx-et-current', + 'language_alterable' => FALSE, + 'untranslatable_fields_hide' => FALSE, + ], + [ + 'id' => 'comment.comment_node_page', + 'target_entity_type_id' => 'comment', + 'target_bundle' => 'comment_node_page', + 'default_langcode' => 'xx-et-current', + 'language_alterable' => FALSE, + 'untranslatable_fields_hide' => FALSE, + ], + [ + 'id' => 'taxonomy_term.forums', + 'target_entity_type_id' => 'taxonomy_term', + 'target_bundle' => 'forums', + 'default_langcode' => 'xx-et-default', + 'language_alterable' => FALSE, + 'untranslatable_fields_hide' => FALSE, + ], + [ + 'id' => 'taxonomy_term.tags', + 'target_entity_type_id' => 'taxonomy_term', + 'target_bundle' => 'tags', + 'default_langcode' => 'xx-et-default', + 'language_alterable' => FALSE, + 'untranslatable_fields_hide' => FALSE, + ], + [ + 'id' => 'user.user', + 'target_entity_type_id' => 'user', + 'target_bundle' => 'user', + 'default_langcode' => 'xx-et-default', + 'language_alterable' => FALSE, + 'untranslatable_fields_hide' => FALSE, + ], + ]; + + // Expected data when there's bundle settings variables. + $tests[2]['expected_data'] = [ + [ + 'id' => 'node.forum', + 'target_entity_type_id' => 'node', + 'target_bundle' => 'forum', + 'default_langcode' => 'xx-et-author', + 'language_alterable' => TRUE, + 'untranslatable_fields_hide' => FALSE, + ], + [ + 'id' => 'node.page', + 'target_entity_type_id' => 'node', + 'target_bundle' => 'page', + 'default_langcode' => 'xx-et-default', + 'language_alterable' => FALSE, + 'untranslatable_fields_hide' => TRUE, + ], + [ + 'id' => 'comment.comment_forum', + 'target_entity_type_id' => 'comment', + 'target_bundle' => 'comment_forum', + 'default_langcode' => 'xx-et-author', + 'language_alterable' => FALSE, + 'untranslatable_fields_hide' => FALSE, + ], + [ + 'id' => 'comment.comment_node_page', + 'target_entity_type_id' => 'comment', + 'target_bundle' => 'comment_node_page', + 'default_langcode' => 'xx-et-author', + 'language_alterable' => TRUE, + 'untranslatable_fields_hide' => TRUE, + ], + [ + 'id' => 'taxonomy_term.forums', + 'target_entity_type_id' => 'taxonomy_term', + 'target_bundle' => 'forums', + 'default_langcode' => 'xx-et-current', + 'language_alterable' => TRUE, + 'untranslatable_fields_hide' => TRUE, + ], + [ + 'id' => 'taxonomy_term.tags', + 'target_entity_type_id' => 'taxonomy_term', + 'target_bundle' => 'tags', + 'default_langcode' => 'xx-et-current', + 'language_alterable' => FALSE, + 'untranslatable_fields_hide' => FALSE, + ], + [ + 'id' => 'user.user', + 'target_entity_type_id' => 'user', + 'target_bundle' => 'user', + 'default_langcode' => 'xx-et-author', + 'language_alterable' => FALSE, + 'untranslatable_fields_hide' => TRUE, + ], + ]; + + return $tests; + } + +} diff -r e200cb7efeb3 -r c2387f117808 core/modules/contextual/tests/src/FunctionalJavascript/ContextualLinkClickTrait.php --- a/core/modules/contextual/tests/src/FunctionalJavascript/ContextualLinkClickTrait.php Thu Apr 26 11:26:54 2018 +0100 +++ b/core/modules/contextual/tests/src/FunctionalJavascript/ContextualLinkClickTrait.php Tue Jul 10 15:07:59 2018 +0100 @@ -18,6 +18,11 @@ * If true then the button will be forced to visible so it can be clicked. */ protected function clickContextualLink($selector, $link_locator, $force_visible = TRUE) { + $page = $this->getSession()->getPage(); + $page->waitFor(10, function () use ($page, $selector) { + return $page->find('css', "$selector .contextual-links"); + }); + if ($force_visible) { $this->toggleContextualTriggerVisibility($selector); } diff -r e200cb7efeb3 -r c2387f117808 core/modules/datetime/tests/src/Functional/EntityResource/EntityTest/EntityTestDateonlyTest.php --- a/core/modules/datetime/tests/src/Functional/EntityResource/EntityTest/EntityTestDateonlyTest.php Thu Apr 26 11:26:54 2018 +0100 +++ b/core/modules/datetime/tests/src/Functional/EntityResource/EntityTest/EntityTestDateonlyTest.php Tue Jul 10 15:07:59 2018 +0100 @@ -7,8 +7,8 @@ use Drupal\datetime\Plugin\Field\FieldType\DateTimeItem; use Drupal\field\Entity\FieldConfig; use Drupal\field\Entity\FieldStorageConfig; +use Drupal\Tests\entity_test\Functional\Rest\EntityTestResourceTestBase; use Drupal\Tests\rest\Functional\AnonResourceTestTrait; -use Drupal\Tests\rest\Functional\EntityResource\EntityTest\EntityTestResourceTestBase; use GuzzleHttp\RequestOptions; /** diff -r e200cb7efeb3 -r c2387f117808 core/modules/datetime/tests/src/Functional/EntityResource/EntityTest/EntityTestDatetimeTest.php --- a/core/modules/datetime/tests/src/Functional/EntityResource/EntityTest/EntityTestDatetimeTest.php Thu Apr 26 11:26:54 2018 +0100 +++ b/core/modules/datetime/tests/src/Functional/EntityResource/EntityTest/EntityTestDatetimeTest.php Tue Jul 10 15:07:59 2018 +0100 @@ -7,8 +7,8 @@ use Drupal\datetime\Plugin\Field\FieldType\DateTimeItem; use Drupal\field\Entity\FieldConfig; use Drupal\field\Entity\FieldStorageConfig; +use Drupal\Tests\entity_test\Functional\Rest\EntityTestResourceTestBase; use Drupal\Tests\rest\Functional\AnonResourceTestTrait; -use Drupal\Tests\rest\Functional\EntityResource\EntityTest\EntityTestResourceTestBase; use GuzzleHttp\RequestOptions; /** diff -r e200cb7efeb3 -r c2387f117808 core/modules/datetime/tests/src/Unit/Plugin/migrate/field/d6/DateFieldTest.php --- a/core/modules/datetime/tests/src/Unit/Plugin/migrate/field/d6/DateFieldTest.php Thu Apr 26 11:26:54 2018 +0100 +++ b/core/modules/datetime/tests/src/Unit/Plugin/migrate/field/d6/DateFieldTest.php Tue Jul 10 15:07:59 2018 +0100 @@ -24,6 +24,8 @@ /** * Tests an Exception is thrown when the field type is not a known date type. + * + * @expectedDeprecation DateField is deprecated in Drupal 8.4.x and will be removed before Drupal 9.0.x. Use \Drupal\datetime\Plugin\migrate\field\DateField instead. */ public function testUnknownDateType() { $this->migration = $this->prophesize('Drupal\migrate\Plugin\MigrationInterface')->reveal(); diff -r e200cb7efeb3 -r c2387f117808 core/modules/dblog/src/Controller/DbLogController.php --- a/core/modules/dblog/src/Controller/DbLogController.php Thu Apr 26 11:26:54 2018 +0100 +++ b/core/modules/dblog/src/Controller/DbLogController.php Tue Jul 10 15:07:59 2018 +0100 @@ -113,7 +113,8 @@ * Full-length messages can be viewed on the message details page. * * @return array - * A render array as expected by drupal_render(). + * A render array as expected by + * \Drupal\Core\Render\RendererInterface::render(). * * @see Drupal\dblog\Form\DblogClearLogConfirmForm * @see Drupal\dblog\Controller\DbLogController::eventDetails() @@ -237,7 +238,7 @@ * * @return array * If the ID is located in the Database Logging table, a build array in the - * format expected by drupal_render(); + * format expected by \Drupal\Core\Render\RendererInterface::render(). */ public function eventDetails($event_id) { $build = []; @@ -378,7 +379,8 @@ * Type of database log events to display (e.g., 'search'). * * @return array - * A build array in the format expected by drupal_render(). + * A build array in the format expected by + * \Drupal\Core\Render\RendererInterface::render(). */ public function topLogMessages($type) { $header = [ diff -r e200cb7efeb3 -r c2387f117808 core/modules/editor/tests/src/Functional/Hal/EditorHalJsonAnonTest.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/core/modules/editor/tests/src/Functional/Hal/EditorHalJsonAnonTest.php Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,30 @@ +grantPermissionsToTestedRole(['administer filters']); + } + + /** + * {@inheritdoc} + */ + protected function createEntity() { + // Create a "Llama" filter format. + $llama_format = FilterFormat::create([ + 'name' => 'Llama', + 'format' => 'llama', + 'langcode' => 'es', + 'filters' => [ + 'filter_html' => [ + 'status' => TRUE, + 'settings' => [ + 'allowed_html' => '

    ', + ], + ], + ], + ]); + + $llama_format->save(); + + // Create a "Camelids" editor. + $camelids = Editor::create([ + 'format' => 'llama', + 'editor' => 'ckeditor', + ]); + $camelids + ->setImageUploadSettings([ + 'status' => FALSE, + 'scheme' => file_default_scheme(), + 'directory' => 'inline-images', + 'max_size' => '', + 'max_dimensions' => [ + 'width' => '', + 'height' => '', + ], + ]) + ->save(); + + return $camelids; + } + + /** + * {@inheritdoc} + */ + protected function getExpectedNormalizedEntity() { + return [ + 'dependencies' => [ + 'config' => [ + 'filter.format.llama', + ], + 'module' => [ + 'ckeditor', + ], + ], + 'editor' => 'ckeditor', + 'format' => 'llama', + 'image_upload' => [ + 'status' => FALSE, + 'scheme' => 'public', + 'directory' => 'inline-images', + 'max_size' => '', + 'max_dimensions' => [ + 'width' => NULL, + 'height' => NULL, + ], + ], + 'langcode' => 'en', + 'settings' => [ + 'toolbar' => [ + 'rows' => [ + [ + [ + 'name' => 'Formatting', + 'items' => [ + 'Bold', + 'Italic', + ], + ], + [ + 'name' => 'Links', + 'items' => [ + 'DrupalLink', + 'DrupalUnlink', + ], + ], + [ + 'name' => 'Lists', + 'items' => [ + 'BulletedList', + 'NumberedList', + ], + ], + [ + 'name' => 'Media', + 'items' => [ + 'Blockquote', + 'DrupalImage', + ], + ], + [ + 'name' => 'Tools', + 'items' => [ + 'Source', + ], + ], + ], + ], + ], + 'plugins' => [ + 'language' => [ + 'language_list' => 'un', + ], + ], + ], + 'status' => TRUE, + 'uuid' => $this->entity->uuid(), + ]; + } + + /** + * {@inheritdoc} + */ + protected function getNormalizedPostEntity() { + // @todo Update in https://www.drupal.org/node/2300677. + } + + /** + * {@inheritdoc} + */ + protected function getExpectedCacheContexts() { + // @see ::createEntity() + return ['user.permissions']; + } + + /** + * {@inheritdoc} + */ + protected function getExpectedUnauthorizedAccessMessage($method) { + if ($this->config('rest.settings')->get('bc_entity_resource_permissions')) { + return parent::getExpectedUnauthorizedAccessMessage($method); + } + + return "The 'administer filters' permission is required."; + } + +} diff -r e200cb7efeb3 -r c2387f117808 core/modules/editor/tests/src/Functional/Rest/EditorXmlAnonTest.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/core/modules/editor/tests/src/Functional/Rest/EditorXmlAnonTest.php Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,26 @@ +select('field_config_instance', 'fci') ->fields('fci') - ->fields('fc', ['type']) + ->fields('fc', ['type', 'translatable']) ->condition('fc.active', 1) ->condition('fc.storage_active', 1) ->condition('fc.deleted', 0) @@ -102,12 +102,13 @@ $translatable = FALSE; if ($row->getSourceProperty('entity_type') == 'node') { + $language_content_type_bundle = (int) $this->variableGet('language_content_type_' . $row->getSourceProperty('bundle'), 0); // language_content_type_[bundle] may be // - 0: no language support // - 1: language assignment support // - 2: node translation support // - 4: entity translation support - if ($this->variableGet('language_content_type_' . $row->getSourceProperty('bundle'), 0) == 2) { + if ($language_content_type_bundle === 2 || ($language_content_type_bundle === 4 && $row->getSourceProperty('translatable'))) { $translatable = TRUE; } } diff -r e200cb7efeb3 -r c2387f117808 core/modules/field/tests/src/Functional/Hal/FieldConfigHalJsonAnonTest.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/core/modules/field/tests/src/Functional/Hal/FieldConfigHalJsonAnonTest.php Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,30 @@ +grantPermissionsToTestedRole(['administer node fields']); + } + + /** + * {@inheritdoc} + */ + protected function createEntity() { + $camelids = NodeType::create([ + 'name' => 'Camelids', + 'type' => 'camelids', + ]); + $camelids->save(); + + $field_storage = FieldStorageConfig::create([ + 'field_name' => 'field_llama', + 'entity_type' => 'node', + 'type' => 'text', + ]); + $field_storage->save(); + + $entity = FieldConfig::create([ + 'field_storage' => $field_storage, + 'bundle' => 'camelids', + ]); + $entity->save(); + + return $entity; + } + + /** + * {@inheritdoc} + */ + protected function getExpectedNormalizedEntity() { + return [ + 'bundle' => 'camelids', + 'default_value' => [], + 'default_value_callback' => '', + 'dependencies' => [ + 'config' => [ + 'field.storage.node.field_llama', + 'node.type.camelids', + ], + 'module' => [ + 'text', + ], + ], + 'description' => '', + 'entity_type' => 'node', + 'field_name' => 'field_llama', + 'field_type' => 'text', + 'id' => 'node.camelids.field_llama', + 'label' => 'field_llama', + 'langcode' => 'en', + 'required' => FALSE, + 'settings' => [], + 'status' => TRUE, + 'translatable' => TRUE, + 'uuid' => $this->entity->uuid(), + ]; + } + + /** + * {@inheritdoc} + */ + protected function getNormalizedPostEntity() { + // @todo Update in https://www.drupal.org/node/2300677. + } + + /** + * {@inheritdoc} + */ + protected function getExpectedCacheContexts() { + return [ + 'user.permissions', + ]; + } + + /** + * {@inheritdoc} + */ + protected function getExpectedUnauthorizedAccessMessage($method) { + if ($this->config('rest.settings')->get('bc_entity_resource_permissions')) { + return parent::getExpectedUnauthorizedAccessMessage($method); + } + + return "The 'administer node fields' permission is required."; + } + +} diff -r e200cb7efeb3 -r c2387f117808 core/modules/field/tests/src/Functional/Rest/FieldConfigXmlAnonTest.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/core/modules/field/tests/src/Functional/Rest/FieldConfigXmlAnonTest.php Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,26 @@ +grantPermissionsToTestedRole(['administer node fields']); + } + + /** + * {@inheritdoc} + */ + protected function createEntity() { + $field_storage = FieldStorageConfig::create([ + 'field_name' => 'true_llama', + 'entity_type' => 'node', + 'type' => 'boolean', + ]); + $field_storage->save(); + return $field_storage; + } + + /** + * {@inheritdoc} + */ + protected function getExpectedNormalizedEntity() { + return [ + 'cardinality' => 1, + 'custom_storage' => FALSE, + 'dependencies' => [ + 'module' => ['node'], + ], + 'entity_type' => 'node', + 'field_name' => 'true_llama', + 'id' => 'node.true_llama', + 'indexes' => [], + 'langcode' => 'en', + 'locked' => FALSE, + 'module' => 'core', + 'persist_with_no_fields' => FALSE, + 'settings' => [], + 'status' => TRUE, + 'translatable' => TRUE, + 'type' => 'boolean', + 'uuid' => $this->entity->uuid(), + ]; + } + + /** + * {@inheritdoc} + */ + protected function getNormalizedPostEntity() { + // @todo Update in https://www.drupal.org/node/2300677. + } + + /** + * {@inheritdoc} + */ + protected function getExpectedUnauthorizedAccessMessage($method) { + if ($this->config('rest.settings')->get('bc_entity_resource_permissions')) { + return parent::getExpectedUnauthorizedAccessMessage($method); + } + + switch ($method) { + case 'GET': + return "The 'administer node fields' permission is required."; + + default: + return parent::getExpectedUnauthorizedAccessMessage($method); + } + } + + /** + * {@inheritdoc} + */ + protected function getExpectedCacheContexts() { + return [ + 'user.permissions', + ]; + } + +} diff -r e200cb7efeb3 -r c2387f117808 core/modules/field/tests/src/Functional/Rest/FieldStorageConfigXmlAnonTest.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/core/modules/field/tests/src/Functional/Rest/FieldStorageConfigXmlAnonTest.php Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,26 @@ +term->save(); + NodeType::create([ + 'type' => $this->randomMachineName(), + ])->save(); + CommentType::create([ + 'id' => $this->randomMachineName(), + 'target_entity_type_id' => 'node', + ])->save(); + $this->entityStringId = EntityTestStringId::create([ 'id' => $this->randomMachineName(), ]); @@ -103,6 +113,7 @@ $this->createEntityReferenceField('entity_test', 'entity_test', 'field_test_user', 'Test user entity reference', 'user'); $this->createEntityReferenceField('entity_test', 'entity_test', 'field_test_comment', 'Test comment entity reference', 'comment'); $this->createEntityReferenceField('entity_test', 'entity_test', 'field_test_file', 'Test file entity reference', 'file'); + $this->createEntityReferenceField('entity_test_string_id', 'entity_test_string_id', 'field_test_entity_test', 'Test content entity reference with string ID', 'entity_test'); } /** @@ -213,6 +224,19 @@ } /** + * Tests the ::generateSampleValue() method when it has a circular reference. + */ + public function testGenerateSampleValueCircularReference() { + // Delete the existing entity. + $this->entityStringId->delete(); + + $entity_storage = \Drupal::entityTypeManager()->getStorage('entity_test'); + $entity = $entity_storage->createWithSampleValues('entity_test'); + $this->assertInstanceOf(EntityTestStringId::class, $entity->field_test_entity_test_string_id->entity); + $this->assertInstanceOf(EntityTest::class, $entity->field_test_entity_test_string_id->entity->field_test_entity_test->entity); + } + + /** * Tests referencing content entities with string IDs. */ public function testContentEntityReferenceItemWithStringId() { diff -r e200cb7efeb3 -r c2387f117808 core/modules/field/tests/src/Kernel/Migrate/d6/MigrateFieldFormatterSettingsTest.php --- a/core/modules/field/tests/src/Kernel/Migrate/d6/MigrateFieldFormatterSettingsTest.php Thu Apr 26 11:26:54 2018 +0100 +++ b/core/modules/field/tests/src/Kernel/Migrate/d6/MigrateFieldFormatterSettingsTest.php Tue Jul 10 15:07:59 2018 +0100 @@ -197,7 +197,7 @@ $component = $display->getComponent('field_test_datetime'); $this->assertIdentical($expected, $component); // Test that our Id map has the correct data. - $this->assertIdentical(['node', 'story', 'teaser', 'field_test'], $this->getMigration('d6_field_formatter_settings')->getIdMap()->lookupDestinationID(['story', 'teaser', 'node', 'field_test'])); + $this->assertIdentical(['node', 'story', 'teaser', 'field_test'], $this->getMigration('d6_field_formatter_settings')->getIdMap()->lookupDestinationId(['story', 'teaser', 'node', 'field_test'])); // Test hidden field. $this->assertComponentNotExists('node.test_planet.teaser', 'field_test_text_single_checkbox'); diff -r e200cb7efeb3 -r c2387f117808 core/modules/field/tests/src/Kernel/Migrate/d6/MigrateFieldWidgetSettingsTest.php --- a/core/modules/field/tests/src/Kernel/Migrate/d6/MigrateFieldWidgetSettingsTest.php Thu Apr 26 11:26:54 2018 +0100 +++ b/core/modules/field/tests/src/Kernel/Migrate/d6/MigrateFieldWidgetSettingsTest.php Tue Jul 10 15:07:59 2018 +0100 @@ -108,6 +108,16 @@ $this->assertSame('options_select', $component['type']); $component = entity_get_form_display('node', 'employee', 'default') + ->getComponent('field_company_2'); + $this->assertInternalType('array', $component); + $this->assertSame('options_buttons', $component['type']); + + $component = entity_get_form_display('node', 'employee', 'default') + ->getComponent('field_company_3'); + $this->assertInternalType('array', $component); + $this->assertSame('entity_reference_autocomplete_tags', $component['type']); + + $component = entity_get_form_display('node', 'employee', 'default') ->getComponent('field_commander'); $this->assertInternalType('array', $component); $this->assertSame('options_select', $component['type']); diff -r e200cb7efeb3 -r c2387f117808 core/modules/field/tests/src/Kernel/Migrate/d7/MigrateFieldFormatterSettingsTest.php --- a/core/modules/field/tests/src/Kernel/Migrate/d7/MigrateFieldFormatterSettingsTest.php Thu Apr 26 11:26:54 2018 +0100 +++ b/core/modules/field/tests/src/Kernel/Migrate/d7/MigrateFieldFormatterSettingsTest.php Tue Jul 10 15:07:59 2018 +0100 @@ -283,6 +283,7 @@ $this->assertComponent('node.test_content_type.default', 'field_link', 'link', 'above', 9); $this->assertComponent('node.test_content_type.default', 'field_text_list', 'list_default', 'above', 10); $this->assertComponent('node.test_content_type.default', 'field_integer_list', 'list_default', 'above', 11); + $this->assertComponent('node.test_content_type.default', 'field_float_list', 'list_default', 'above', 19); $this->assertComponent('node.test_content_type.default', 'field_long_text', 'text_default', 'above', 12); $this->assertComponent('node.test_content_type.default', 'field_node_entityreference', 'entity_reference_label', 'above', 15); $this->assertComponent('node.test_content_type.default', 'field_user_entityreference', 'entity_reference_label', 'above', 16); diff -r e200cb7efeb3 -r c2387f117808 core/modules/field/tests/src/Kernel/Migrate/d7/MigrateFieldInstanceTest.php --- a/core/modules/field/tests/src/Kernel/Migrate/d7/MigrateFieldInstanceTest.php Thu Apr 26 11:26:54 2018 +0100 +++ b/core/modules/field/tests/src/Kernel/Migrate/d7/MigrateFieldInstanceTest.php Tue Jul 10 15:07:59 2018 +0100 @@ -118,14 +118,15 @@ $this->assertEntity('node.test_content_type.field_file', 'File', 'file', FALSE, FALSE); $this->assertEntity('node.test_content_type.field_float', 'Float', 'float', FALSE, FALSE); $this->assertEntity('node.test_content_type.field_images', 'Images', 'image', TRUE, FALSE); - $this->assertEntity('node.test_content_type.field_integer', 'Integer', 'integer', TRUE, FALSE); + $this->assertEntity('node.test_content_type.field_integer', 'Integer', 'integer', TRUE, TRUE); $this->assertEntity('node.test_content_type.field_link', 'Link', 'link', FALSE, FALSE); $this->assertEntity('node.test_content_type.field_text_list', 'Text List', 'list_string', FALSE, FALSE); $this->assertEntity('node.test_content_type.field_integer_list', 'Integer List', 'list_integer', FALSE, FALSE); + $this->assertEntity('node.test_content_type.field_float_list', 'Float List', 'list_float', FALSE, FALSE); $this->assertEntity('node.test_content_type.field_long_text', 'Long text', 'text_with_summary', FALSE, FALSE); $this->assertEntity('node.test_content_type.field_term_reference', 'Term Reference', 'entity_reference', FALSE, FALSE); $this->assertEntity('node.test_content_type.field_text', 'Text', 'string', FALSE, FALSE); - $this->assertEntity('comment.comment_node_test_content_type.field_integer', 'Integer', 'integer', FALSE, FALSE); + $this->assertEntity('comment.comment_node_test_content_type.field_integer', 'Integer', 'integer', FALSE, TRUE); $this->assertEntity('user.user.field_file', 'File', 'file', FALSE, FALSE); $this->assertLinkFields('node.test_content_type.field_link', DRUPAL_OPTIONAL); diff -r e200cb7efeb3 -r c2387f117808 core/modules/field/tests/src/Kernel/Migrate/d7/MigrateFieldInstanceWidgetSettingsTest.php --- a/core/modules/field/tests/src/Kernel/Migrate/d7/MigrateFieldInstanceWidgetSettingsTest.php Thu Apr 26 11:26:54 2018 +0100 +++ b/core/modules/field/tests/src/Kernel/Migrate/d7/MigrateFieldInstanceWidgetSettingsTest.php Tue Jul 10 15:07:59 2018 +0100 @@ -141,6 +141,7 @@ $this->assertComponent('node.test_content_type.default', 'field_term_entityreference', 'entity_reference_autocomplete_tags', 18); $this->assertComponent('node.test_content_type.default', 'field_text', 'string_textfield', 15); $this->assertComponent('node.test_content_type.default', 'field_text_list', 'options_select', 11); + $this->assertComponent('node.test_content_type.default', 'field_float_list', 'options_select', 20); $this->assertEntity('user.user.default', 'user', 'user'); $this->assertComponent('user.user.default', 'field_file', 'file_generic', 8); diff -r e200cb7efeb3 -r c2387f117808 core/modules/field/tests/src/Kernel/Migrate/d7/MigrateFieldTest.php --- a/core/modules/field/tests/src/Kernel/Migrate/d7/MigrateFieldTest.php Thu Apr 26 11:26:54 2018 +0100 +++ b/core/modules/field/tests/src/Kernel/Migrate/d7/MigrateFieldTest.php Tue Jul 10 15:07:59 2018 +0100 @@ -93,6 +93,7 @@ $this->assertEntity('node.taxonomy_forums', 'entity_reference', TRUE, 1); $this->assertEntity('node.field_text', 'string', TRUE, 1); $this->assertEntity('node.field_text_list', 'list_string', TRUE, 3); + $this->assertEntity('node.field_float_list', 'list_float', TRUE, 1); $this->assertEntity('node.field_boolean', 'boolean', TRUE, 1); $this->assertEntity('node.field_email', 'email', TRUE, -1); $this->assertEntity('node.field_phone', 'telephone', TRUE, 1); diff -r e200cb7efeb3 -r c2387f117808 core/modules/field/tests/src/Kernel/Plugin/migrate/source/d7/FieldInstancePerFormDisplayTest.php --- a/core/modules/field/tests/src/Kernel/Plugin/migrate/source/d7/FieldInstancePerFormDisplayTest.php Thu Apr 26 11:26:54 2018 +0100 +++ b/core/modules/field/tests/src/Kernel/Plugin/migrate/source/d7/FieldInstancePerFormDisplayTest.php Tue Jul 10 15:07:59 2018 +0100 @@ -95,7 +95,7 @@ 'locked' => '0', 'data' => 'a:7:{s:12:"translatable";s:1:"0";s:12:"entity_types";a:0:{}s:8:"settings";a:3:{s:13:"display_field";i:0;s:15:"display_default";i:0;s:10:"uri_scheme";s:6:"public";}s:7:"storage";a:5:{s:4:"type";s:17:"field_sql_storage";s:8:"settings";a:0:{}s:6:"module";s:17:"field_sql_storage";s:6:"active";s:1:"1";s:7:"details";a:1:{s:3:"sql";a:2:{s:18:"FIELD_LOAD_CURRENT";a:1:{s:21:"field_data_field_file";a:3:{s:3:"fid";s:14:"field_file_fid";s:7:"display";s:18:"field_file_display";s:11:"description";s:22:"field_file_description";}}s:19:"FIELD_LOAD_REVISION";a:1:{s:25:"field_revision_field_file";a:3:{s:3:"fid";s:14:"field_file_fid";s:7:"display";s:18:"field_file_display";s:11:"description";s:22:"field_file_description";}}}}}s:12:"foreign keys";a:1:{s:3:"fid";a:2:{s:5:"table";s:12:"file_managed";s:7:"columns";a:1:{s:3:"fid";s:3:"fid";}}}s:7:"indexes";a:1:{s:3:"fid";a:1:{i:0;s:3:"fid";}}s:2:"id";s:2:"11";}', 'cardinality' => '1', - 'translatable' => '0', + 'translatable' => '1', 'deleted' => '0', ], [ @@ -125,7 +125,7 @@ 'locked' => '0', 'data' => 'a:7:{s:12:"translatable";s:1:"0";s:12:"entity_types";a:0:{}s:8:"settings";a:7:{s:10:"attributes";a:3:{s:6:"target";s:7:"default";s:5:"class";s:0:"";s:3:"rel";s:0:"";}s:3:"url";i:0;s:5:"title";s:8:"optional";s:11:"title_value";s:0:"";s:15:"title_maxlength";i:128;s:13:"enable_tokens";i:1;s:7:"display";a:1:{s:10:"url_cutoff";i:80;}}s:7:"storage";a:5:{s:4:"type";s:17:"field_sql_storage";s:8:"settings";a:0:{}s:6:"module";s:17:"field_sql_storage";s:6:"active";s:1:"1";s:7:"details";a:1:{s:3:"sql";a:2:{s:18:"FIELD_LOAD_CURRENT";a:1:{s:21:"field_data_field_link";a:3:{s:3:"url";s:14:"field_link_url";s:5:"title";s:16:"field_link_title";s:10:"attributes";s:21:"field_link_attributes";}}s:19:"FIELD_LOAD_REVISION";a:1:{s:25:"field_revision_field_link";a:3:{s:3:"url";s:14:"field_link_url";s:5:"title";s:16:"field_link_title";s:10:"attributes";s:21:"field_link_attributes";}}}}}s:12:"foreign keys";a:0:{}s:7:"indexes";a:0:{}s:2:"id";s:2:"15";}', 'cardinality' => '1', - 'translatable' => '0', + 'translatable' => '1', 'deleted' => '0', ], ]; @@ -175,6 +175,7 @@ 'data' => 'a:6:{s:5:"label";s:4:"Body";s:6:"widget";a:4:{s:4:"type";s:26:"text_textarea_with_summary";s:8:"settings";a:2:{s:4:"rows";i:20;s:12:"summary_rows";i:5;}s:6:"weight";i:-4;s:6:"module";s:4:"text";}s:8:"settings";a:3:{s:15:"display_summary";b:1;s:15:"text_processing";i:1;s:18:"user_register_form";b:0;}s:7:"display";a:2:{s:7:"default";a:5:{s:5:"label";s:6:"hidden";s:4:"type";s:12:"text_default";s:8:"settings";a:0:{}s:6:"module";s:4:"text";s:6:"weight";i:0;}s:6:"teaser";a:5:{s:5:"label";s:6:"hidden";s:4:"type";s:23:"text_summary_or_trimmed";s:8:"settings";a:1:{s:11:"trim_length";i:600;}s:6:"module";s:4:"text";s:6:"weight";i:0;}}s:8:"required";b:0;s:11:"description";s:0:"";}', 'deleted' => '0', 'type' => 'text_with_summary', + 'translatable' => '0', ], ], ], @@ -208,7 +209,7 @@ 'locked' => '0', 'data' => 'a:7:{s:12:"translatable";s:1:"0";s:12:"entity_types";a:0:{}s:8:"settings";a:3:{s:13:"display_field";i:0;s:15:"display_default";i:0;s:10:"uri_scheme";s:6:"public";}s:7:"storage";a:5:{s:4:"type";s:17:"field_sql_storage";s:8:"settings";a:0:{}s:6:"module";s:17:"field_sql_storage";s:6:"active";s:1:"1";s:7:"details";a:1:{s:3:"sql";a:2:{s:18:"FIELD_LOAD_CURRENT";a:1:{s:21:"field_data_field_file";a:3:{s:3:"fid";s:14:"field_file_fid";s:7:"display";s:18:"field_file_display";s:11:"description";s:22:"field_file_description";}}s:19:"FIELD_LOAD_REVISION";a:1:{s:25:"field_revision_field_file";a:3:{s:3:"fid";s:14:"field_file_fid";s:7:"display";s:18:"field_file_display";s:11:"description";s:22:"field_file_description";}}}}}s:12:"foreign keys";a:1:{s:3:"fid";a:2:{s:5:"table";s:12:"file_managed";s:7:"columns";a:1:{s:3:"fid";s:3:"fid";}}}s:7:"indexes";a:1:{s:3:"fid";a:1:{i:0;s:3:"fid";}}s:2:"id";s:2:"11";}', 'cardinality' => '1', - 'translatable' => '0', + 'translatable' => '1', 'deleted' => '0', ], 'instances' => [ @@ -221,6 +222,7 @@ 'data' => 'a:6:{s:5:"label";s:4:"File";s:6:"widget";a:5:{s:6:"weight";s:1:"8";s:4:"type";s:12:"file_generic";s:6:"module";s:4:"file";s:6:"active";i:1;s:8:"settings";a:1:{s:18:"progress_indicator";s:8:"throbber";}}s:8:"settings";a:5:{s:14:"file_directory";s:0:"";s:15:"file_extensions";s:3:"txt";s:12:"max_filesize";s:0:"";s:17:"description_field";i:0;s:18:"user_register_form";i:0;}s:7:"display";a:1:{s:7:"default";a:5:{s:5:"label";s:5:"above";s:4:"type";s:12:"file_default";s:8:"settings";a:0:{}s:6:"module";s:4:"file";s:6:"weight";i:0;}}s:8:"required";i:0;s:11:"description";s:0:"";}', 'deleted' => '0', 'type' => 'file', + 'translatable' => '1', ], ], ], @@ -265,6 +267,7 @@ 'data' => 'a:7:{s:5:"label";s:7:"Integer";s:6:"widget";a:5:{s:6:"weight";s:1:"2";s:4:"type";s:6:"number";s:6:"module";s:6:"number";s:6:"active";i:0;s:8:"settings";a:0:{}}s:8:"settings";a:5:{s:3:"min";s:0:"";s:3:"max";s:0:"";s:6:"prefix";s:0:"";s:6:"suffix";s:0:"";s:18:"user_register_form";b:0;}s:7:"display";a:1:{s:7:"default";a:5:{s:5:"label";s:5:"above";s:4:"type";s:14:"number_integer";s:8:"settings";a:4:{s:18:"thousand_separator";s:1:" ";s:17:"decimal_separator";s:1:".";s:5:"scale";i:0;s:13:"prefix_suffix";b:1;}s:6:"module";s:6:"number";s:6:"weight";i:1;}}s:8:"required";i:0;s:11:"description";s:0:"";s:13:"default_value";N;}', 'deleted' => '0', 'type' => 'number_integer', + 'translatable' => '0', ] ], ], @@ -296,7 +299,7 @@ 'locked' => '0', 'data' => 'a:7:{s:12:"translatable";s:1:"0";s:12:"entity_types";a:0:{}s:8:"settings";a:7:{s:10:"attributes";a:3:{s:6:"target";s:7:"default";s:5:"class";s:0:"";s:3:"rel";s:0:"";}s:3:"url";i:0;s:5:"title";s:8:"optional";s:11:"title_value";s:0:"";s:15:"title_maxlength";i:128;s:13:"enable_tokens";i:1;s:7:"display";a:1:{s:10:"url_cutoff";i:80;}}s:7:"storage";a:5:{s:4:"type";s:17:"field_sql_storage";s:8:"settings";a:0:{}s:6:"module";s:17:"field_sql_storage";s:6:"active";s:1:"1";s:7:"details";a:1:{s:3:"sql";a:2:{s:18:"FIELD_LOAD_CURRENT";a:1:{s:21:"field_data_field_link";a:3:{s:3:"url";s:14:"field_link_url";s:5:"title";s:16:"field_link_title";s:10:"attributes";s:21:"field_link_attributes";}}s:19:"FIELD_LOAD_REVISION";a:1:{s:25:"field_revision_field_link";a:3:{s:3:"url";s:14:"field_link_url";s:5:"title";s:16:"field_link_title";s:10:"attributes";s:21:"field_link_attributes";}}}}}s:12:"foreign keys";a:0:{}s:7:"indexes";a:0:{}s:2:"id";s:2:"15";}', 'cardinality' => '1', - 'translatable' => '0', + 'translatable' => '1', 'deleted' => '0', ], 'instances' => [ @@ -309,6 +312,7 @@ 'data' => 'a:7:{s:5:"label";s:4:"Link";s:6:"widget";a:5:{s:6:"weight";s:2:"10";s:4:"type";s:10:"link_field";s:6:"module";s:4:"link";s:6:"active";i:0;s:8:"settings";a:0:{}}s:8:"settings";a:12:{s:12:"absolute_url";i:1;s:12:"validate_url";i:1;s:3:"url";i:0;s:5:"title";s:8:"optional";s:11:"title_value";s:19:"Unused Static Title";s:27:"title_label_use_field_label";i:0;s:15:"title_maxlength";s:3:"128";s:7:"display";a:1:{s:10:"url_cutoff";s:2:"81";}s:10:"attributes";a:6:{s:6:"target";s:6:"_blank";s:3:"rel";s:8:"nofollow";s:18:"configurable_class";i:0;s:5:"class";s:7:"classes";s:18:"configurable_title";i:1;s:5:"title";s:0:"";}s:10:"rel_remove";s:19:"rel_remove_external";s:13:"enable_tokens";i:1;s:18:"user_register_form";b:0;}s:7:"display";a:1:{s:7:"default";a:5:{s:5:"label";s:5:"above";s:4:"type";s:12:"link_default";s:6:"weight";s:1:"9";s:8:"settings";a:0:{}s:6:"module";s:4:"link";}}s:8:"required";i:0;s:11:"description";s:0:"";s:13:"default_value";N;}', 'deleted' => '0', 'type' => 'link_field', + 'translatable' => '1', ], ], ], diff -r e200cb7efeb3 -r c2387f117808 core/modules/field/tests/src/Kernel/Plugin/migrate/source/d7/FieldInstancePerViewModeTest.php --- a/core/modules/field/tests/src/Kernel/Plugin/migrate/source/d7/FieldInstancePerViewModeTest.php Thu Apr 26 11:26:54 2018 +0100 +++ b/core/modules/field/tests/src/Kernel/Plugin/migrate/source/d7/FieldInstancePerViewModeTest.php Tue Jul 10 15:07:59 2018 +0100 @@ -103,6 +103,7 @@ 'data' => 'a:6:{s:5:"label";s:4:"Body";s:6:"widget";a:4:{s:4:"type";s:26:"text_textarea_with_summary";s:8:"settings";a:2:{s:4:"rows";i:20;s:12:"summary_rows";i:5;}s:6:"weight";i:-4;s:6:"module";s:4:"text";}s:8:"settings";a:3:{s:15:"display_summary";b:1;s:15:"text_processing";i:1;s:18:"user_register_form";b:0;}s:7:"display";a:2:{s:7:"default";a:5:{s:5:"label";s:6:"hidden";s:4:"type";s:12:"text_default";s:8:"settings";a:0:{}s:6:"module";s:4:"text";s:6:"weight";i:0;}s:6:"teaser";a:5:{s:5:"label";s:6:"hidden";s:4:"type";s:23:"text_summary_or_trimmed";s:8:"settings";a:1:{s:11:"trim_length";i:600;}s:6:"module";s:4:"text";s:6:"weight";i:0;}}s:8:"required";b:0;s:11:"description";s:0:"";}', 'deleted' => '0', 'type' => 'text_with_summary', + 'translatable' => '0', ], ], ], @@ -150,6 +151,7 @@ 'data' => 'a:6:{s:5:"label";s:4:"Body";s:6:"widget";a:4:{s:4:"type";s:26:"text_textarea_with_summary";s:8:"settings";a:2:{s:4:"rows";i:20;s:12:"summary_rows";i:5;}s:6:"weight";i:-4;s:6:"module";s:4:"text";}s:8:"settings";a:3:{s:15:"display_summary";b:1;s:15:"text_processing";i:1;s:18:"user_register_form";b:0;}s:7:"display";a:2:{s:7:"default";a:5:{s:5:"label";s:6:"hidden";s:4:"type";s:12:"text_default";s:8:"settings";a:0:{}s:6:"module";s:4:"text";s:6:"weight";i:0;}s:6:"teaser";a:5:{s:5:"label";s:6:"hidden";s:4:"type";s:23:"text_summary_or_trimmed";s:8:"settings";a:1:{s:11:"trim_length";i:600;}s:6:"module";s:4:"text";s:6:"weight";i:0;}}s:8:"required";b:0;s:11:"description";s:0:"";}', 'deleted' => '0', 'type' => 'text_with_summary', + 'translatable' => '0', ], ], ], diff -r e200cb7efeb3 -r c2387f117808 core/modules/field/tests/src/Kernel/Plugin/migrate/source/d7/FieldInstanceTest.php --- a/core/modules/field/tests/src/Kernel/Plugin/migrate/source/d7/FieldInstanceTest.php Thu Apr 26 11:26:54 2018 +0100 +++ b/core/modules/field/tests/src/Kernel/Plugin/migrate/source/d7/FieldInstanceTest.php Tue Jul 10 15:07:59 2018 +0100 @@ -129,6 +129,7 @@ 'data' => 'a:6:{s:5:"label";s:4:"Body";s:6:"widget";a:4:{s:4:"type";s:26:"text_textarea_with_summary";s:8:"settings";a:2:{s:4:"rows";i:20;s:12:"summary_rows";i:5;}s:6:"weight";i:-4;s:6:"module";s:4:"text";}s:8:"settings";a:3:{s:15:"display_summary";b:1;s:15:"text_processing";i:1;s:18:"user_register_form";b:0;}s:7:"display";a:2:{s:7:"default";a:5:{s:5:"label";s:6:"hidden";s:4:"type";s:12:"text_default";s:8:"settings";a:0:{}s:6:"module";s:4:"text";s:6:"weight";i:0;}s:6:"teaser";a:5:{s:5:"label";s:6:"hidden";s:4:"type";s:23:"text_summary_or_trimmed";s:8:"settings";a:1:{s:11:"trim_length";i:600;}s:6:"module";s:4:"text";s:6:"weight";i:0;}}s:8:"required";b:0;s:11:"description";s:0:"";}', 'deleted' => '0', 'type' => 'text_with_summary', + 'translatable' => '0', ], ], ], diff -r e200cb7efeb3 -r c2387f117808 core/modules/field_ui/src/Controller/FieldConfigListController.php --- a/core/modules/field_ui/src/Controller/FieldConfigListController.php Thu Apr 26 11:26:54 2018 +0100 +++ b/core/modules/field_ui/src/Controller/FieldConfigListController.php Tue Jul 10 15:07:59 2018 +0100 @@ -21,7 +21,8 @@ * The current route match. * * @return array - * A render array as expected by drupal_render(). + * A render array as expected by + * \Drupal\Core\Render\RendererInterface::render(). */ public function listing($entity_type_id = NULL, $bundle = NULL, RouteMatchInterface $route_match = NULL) { return $this->entityManager()->getListBuilder('field_config')->render($entity_type_id, $bundle); diff -r e200cb7efeb3 -r c2387f117808 core/modules/field_ui/src/Element/FieldUiTable.php --- a/core/modules/field_ui/src/Element/FieldUiTable.php Thu Apr 26 11:26:54 2018 +0100 +++ b/core/modules/field_ui/src/Element/FieldUiTable.php Tue Jul 10 15:07:59 2018 +0100 @@ -38,7 +38,7 @@ * @return array * The $element with prepared variables ready for field-ui-table.html.twig. * - * @see drupal_render() + * @see \Drupal\Core\Render\RendererInterface::render() * @see \Drupal\Core\Render\Element\Table::preRenderTable() */ public static function tablePreRender($elements) { diff -r e200cb7efeb3 -r c2387f117808 core/modules/field_ui/src/EntityDisplayModeListBuilder.php --- a/core/modules/field_ui/src/EntityDisplayModeListBuilder.php Thu Apr 26 11:26:54 2018 +0100 +++ b/core/modules/field_ui/src/EntityDisplayModeListBuilder.php Tue Jul 10 15:07:59 2018 +0100 @@ -36,6 +36,8 @@ public function __construct(EntityTypeInterface $entity_type, EntityStorageInterface $storage, array $entity_types) { parent::__construct($entity_type, $storage); + // Override the default limit (50) in order to display all view modes. + $this->limit = FALSE; $this->entityTypes = $entity_types; } diff -r e200cb7efeb3 -r c2387f117808 core/modules/field_ui/src/Form/EntityDisplayFormBase.php --- a/core/modules/field_ui/src/Form/EntityDisplayFormBase.php Thu Apr 26 11:26:54 2018 +0100 +++ b/core/modules/field_ui/src/Form/EntityDisplayFormBase.php Tue Jul 10 15:07:59 2018 +0100 @@ -210,6 +210,7 @@ if ($enabled_displays = array_filter($this->getDisplayStatuses())) { $default = array_keys(array_intersect_key($display_mode_options, $enabled_displays)); } + natcasesort($display_mode_options); $form['modes']['display_modes_custom'] = [ '#type' => 'checkboxes', '#title' => $this->t('Use custom display settings for the following @display_context modes', ['@display_context' => $this->displayContext]), @@ -702,7 +703,7 @@ * * @return array * - * @see drupal_render() + * @see \Drupal\Core\Render\RendererInterface::render() * @see \Drupal\Core\Render\Element\Table::preRenderTable() * * @deprecated in Drupal 8.0.0, will be removed before Drupal 9.0.0. diff -r e200cb7efeb3 -r c2387f117808 core/modules/field_ui/tests/src/Functional/EntityDisplayModeTest.php --- a/core/modules/field_ui/tests/src/Functional/EntityDisplayModeTest.php Thu Apr 26 11:26:54 2018 +0100 +++ b/core/modules/field_ui/tests/src/Functional/EntityDisplayModeTest.php Tue Jul 10 15:07:59 2018 +0100 @@ -19,7 +19,7 @@ * * @var string[] */ - public static $modules = ['block', 'entity_test', 'field_ui']; + public static $modules = ['block', 'entity_test', 'field_ui', 'node']; /** * {@inheritdoc} @@ -27,6 +27,12 @@ protected function setUp() { parent::setUp(); + // Create a node type. + $this->drupalCreateContentType([ + 'type' => 'article', + 'name' => 'Article', + ]); + $this->drupalPlaceBlock('local_actions_block'); $this->drupalPlaceBlock('page_title_block'); } @@ -140,4 +146,62 @@ $this->assertRaw(t('The form mode %label has been deleted.', ['%label' => $edit['label']])); } + /** + * Tests if view modes appear in alphabetical order by visible name. + * + * The machine name should not be used for sorting. + * + * @see https://www.drupal.org/node/2858569 + */ + public function testAlphabeticalDisplaySettings() { + $this->drupalLogin($this->drupalCreateUser([ + 'access administration pages', + 'administer content types', + 'administer display modes', + 'administer nodes', + 'administer node fields', + 'administer node display', + 'administer node form display', + 'view the administration theme', + ])); + $this->drupalGet('admin/structure/types/manage/article/display'); + // Verify that the order of view modes is alphabetical by visible label. + // Since the default view modes all have machine names which coincide with + // the English labels, they should appear in alphabetical order, by default + // if viewing the site in English and if no changes have been made. We will + // verify this first. + $page_text = $this->getTextContent(); + $start = strpos($page_text, 'view modes'); + $pos = $start; + $list = ['Full content', 'RSS', 'Search index', 'Search result', 'Teaser']; + foreach ($list as $name) { + $new_pos = strpos($page_text, $name, $start); + $this->assertTrue($new_pos > $pos, 'Order of ' . $name . ' is correct on page'); + $pos = $new_pos; + } + // Now that we have verified the original display order, we can change the + // label for one of the view modes. If we rename "Teaser" to "Breezer", it + // should appear as the first of the listed view modes: + // Set new values and enable test plugins. + $edit = [ + 'label' => 'Breezer', + ]; + $this->drupalPostForm('admin/structure/display-modes/view/manage/node.teaser', $edit, 'Save'); + $this->assertSession()->pageTextContains('Saved the Breezer view mode.'); + + // Re-open the display settings for the article content type and verify + // that changing "Teaser" to "Breezer" makes it appear before "Full + // content". + $this->drupalGet('admin/structure/types/manage/article/display'); + $page_text = $this->getTextContent(); + $start = strpos($page_text, 'view modes'); + $pos = $start; + $list = ['Breezer', 'Full content']; + foreach ($list as $name) { + $new_pos = strpos($page_text, $name, $start); + $this->assertTrue($new_pos > $pos, 'Order of ' . $name . ' is correct on page'); + $pos = $new_pos; + } + } + } diff -r e200cb7efeb3 -r c2387f117808 core/modules/file/file.es6.js --- a/core/modules/file/file.es6.js Thu Apr 26 11:26:54 2018 +0100 +++ b/core/modules/file/file.es6.js Tue Jul 10 15:07:59 2018 +0100 @@ -179,12 +179,7 @@ * The event triggered, most likely a `mousedown` event. */ disableFields(event) { - const $clickedButton = $(this).findOnce('ajax'); - - // Only disable upload fields for Ajax buttons. - if (!$clickedButton.length) { - return; - } + const $clickedButton = $(this); // Check if we're working with an "Upload" button. let $enabledFields = []; diff -r e200cb7efeb3 -r c2387f117808 core/modules/file/file.js --- a/core/modules/file/file.js Thu Apr 26 11:26:54 2018 +0100 +++ b/core/modules/file/file.js Tue Jul 10 15:07:59 2018 +0100 @@ -93,11 +93,7 @@ $(event.target).closest('.js-form-managed-file').find('.js-form-submit').trigger('mousedown'); }, disableFields: function disableFields(event) { - var $clickedButton = $(this).findOnce('ajax'); - - if (!$clickedButton.length) { - return; - } + var $clickedButton = $(this); var $enabledFields = []; if ($clickedButton.closest('div.js-form-managed-file').length > 0) { diff -r e200cb7efeb3 -r c2387f117808 core/modules/file/file.module --- a/core/modules/file/file.module Thu Apr 26 11:26:54 2018 +0100 +++ b/core/modules/file/file.module Tue Jul 10 15:07:59 2018 +0100 @@ -1017,9 +1017,6 @@ continue; } - // Move uploaded files from PHP's upload_tmp_dir to Drupal's temporary - // directory. This overcomes open_basedir restrictions for future file - // operations. $file->setFileUri($file->destination); if (!drupal_move_uploaded_file($file_info->getRealPath(), $file->getFileUri())) { drupal_set_message(t('File upload error. Could not move uploaded file.'), 'error'); diff -r e200cb7efeb3 -r c2387f117808 core/modules/file/src/FileAccessControlHandler.php --- a/core/modules/file/src/FileAccessControlHandler.php Thu Apr 26 11:26:54 2018 +0100 +++ b/core/modules/file/src/FileAccessControlHandler.php Tue Jul 10 15:07:59 2018 +0100 @@ -52,11 +52,11 @@ // services can be more properly injected. $allowed_fids = \Drupal::service('session')->get('anonymous_allowed_file_ids', []); if (!empty($allowed_fids[$entity->id()])) { - return AccessResult::allowed(); + return AccessResult::allowed()->addCacheContexts(['session', 'user']); } } else { - return AccessResult::allowed(); + return AccessResult::allowed()->addCacheContexts(['user']); } } } diff -r e200cb7efeb3 -r c2387f117808 core/modules/file/src/Plugin/Validation/Constraint/FileValidationConstraintValidator.php --- a/core/modules/file/src/Plugin/Validation/Constraint/FileValidationConstraintValidator.php Thu Apr 26 11:26:54 2018 +0100 +++ b/core/modules/file/src/Plugin/Validation/Constraint/FileValidationConstraintValidator.php Tue Jul 10 15:07:59 2018 +0100 @@ -15,7 +15,12 @@ */ public function validate($value, Constraint $constraint) { // Get the file to execute validators. - $file = $value->get('entity')->getTarget()->getValue(); + $target = $value->get('entity')->getTarget(); + if (!$target) { + return; + } + + $file = $target->getValue(); // Get the validators. $validators = $value->getUploadValidators(); // Checks that a file meets the criteria specified by the validators. diff -r e200cb7efeb3 -r c2387f117808 core/modules/file/tests/src/Functional/FileFieldTestBase.php --- a/core/modules/file/tests/src/Functional/FileFieldTestBase.php Thu Apr 26 11:26:54 2018 +0100 +++ b/core/modules/file/tests/src/Functional/FileFieldTestBase.php Tue Jul 10 15:07:59 2018 +0100 @@ -7,6 +7,7 @@ use Drupal\file\FileInterface; use Drupal\Tests\BrowserTestBase; use Drupal\file\Entity\File; +use Drupal\Tests\TestFileCreationTrait; /** * Provides methods specifically for testing File module's field handling. @@ -14,6 +15,9 @@ abstract class FileFieldTestBase extends BrowserTestBase { use FileFieldCreationTrait; + use TestFileCreationTrait { + getTestFiles as drupalGetTestFiles; + } /** * Modules to enable. @@ -156,7 +160,7 @@ $edit[$name][] = $file_path; } } - $this->drupalPostForm("node/$nid/edit", $edit, t('Save and keep published')); + $this->drupalPostForm("node/$nid/edit", $edit, t('Save')); return $nid; } @@ -172,7 +176,7 @@ ]; $this->drupalPostForm('node/' . $nid . '/edit', [], t('Remove')); - $this->drupalPostForm(NULL, $edit, t('Save and keep published')); + $this->drupalPostForm(NULL, $edit, t('Save')); } /** @@ -185,7 +189,7 @@ ]; $this->drupalPostForm('node/' . $nid . '/edit', [], t('Remove')); - $this->drupalPostForm(NULL, $edit, t('Save and keep published')); + $this->drupalPostForm(NULL, $edit, t('Save')); } /** diff -r e200cb7efeb3 -r c2387f117808 core/modules/file/tests/src/Functional/Hal/FileHalJsonAnonTest.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/core/modules/file/tests/src/Functional/Hal/FileHalJsonAnonTest.php Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,147 @@ +applyHalFieldNormalization($default_normalization); + + $url = file_create_url($this->entity->getFileUri()); + // @see \Drupal\Tests\hal\Functional\EntityResource\File\FileHalJsonAnonTest::testGetBcUriField() + if ($this->config('hal.settings')->get('bc_file_uri_as_url_normalizer')) { + $normalization['uri'][0]['value'] = $url; + } + + $uid = $this->author->id(); + + return $normalization + [ + '_embedded' => [ + $this->baseUrl . '/rest/relation/file/file/uid' => [ + [ + '_links' => [ + 'self' => [ + 'href' => $this->baseUrl . "/user/$uid?_format=hal_json", + ], + 'type' => [ + 'href' => $this->baseUrl . '/rest/type/user/user', + ], + ], + 'uuid' => [ + [ + 'value' => $this->author->uuid(), + ], + ], + ], + ], + ], + '_links' => [ + 'self' => [ + 'href' => $url, + ], + 'type' => [ + 'href' => $this->baseUrl . '/rest/type/file/file', + ], + $this->baseUrl . '/rest/relation/file/file/uid' => [ + [ + 'href' => $this->baseUrl . "/user/$uid?_format=hal_json", + ], + ], + ], + ]; + } + + /** + * {@inheritdoc} + */ + protected function getNormalizedPostEntity() { + return parent::getNormalizedPostEntity() + [ + '_links' => [ + 'type' => [ + 'href' => $this->baseUrl . '/rest/type/file/file', + ], + ], + ]; + } + + /** + * {@inheritdoc} + */ + protected function getExpectedCacheTags() { + return Cache::mergeTags(parent::getExpectedCacheTags(), ['config:hal.settings']); + } + + /** + * {@inheritdoc} + */ + protected function getExpectedCacheContexts() { + return [ + 'url.site', + 'user.permissions', + ]; + } + + /** + * @see hal_update_8501() + */ + public function testGetBcUriField() { + $this->config('hal.settings')->set('bc_file_uri_as_url_normalizer', TRUE)->save(TRUE); + + $this->initAuthentication(); + $url = $this->getEntityResourceUrl(); + $url->setOption('query', ['_format' => static::$format]); + $request_options = $this->getAuthenticationRequestOptions('GET'); + $this->provisionEntityResource(); + $this->setUpAuthorization('GET'); + $response = $this->request('GET', $url, $request_options); + $expected = $this->getExpectedNormalizedEntity(); + static::recursiveKSort($expected); + $actual = $this->serializer->decode((string) $response->getBody(), static::$format); + static::recursiveKSort($actual); + $this->assertSame($expected, $actual); + + // Explicitly assert that $file->uri->value is an absolute file URL, unlike + // the default normalization. + $this->assertSame($this->baseUrl . '/' . $this->siteDirectory . '/files/drupal.txt', $actual['uri'][0]['value']); + } + + /** + * {@inheritdoc} + */ + public function testPatch() { + // @todo https://www.drupal.org/node/1927648 + $this->markTestSkipped(); + } + +} diff -r e200cb7efeb3 -r c2387f117808 core/modules/file/tests/src/Functional/Hal/FileHalJsonBasicAuthTest.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/core/modules/file/tests/src/Functional/Hal/FileHalJsonBasicAuthTest.php Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,24 @@ +grantPermissionsToTestedRole(['access content']); + break; + + case 'PATCH': + case 'DELETE': + // \Drupal\file\FileAccessControlHandler::checkAccess() grants 'update' + // and 'delete' access only to the user that owns the file. So there is + // no permission to grant: instead, the file owner must be changed from + // its default (user 1) to the current user. + $this->makeCurrentUserFileOwner(); + break; + } + } + + /** + * {@inheritdoc} + */ + protected function grantPermissionsToTestedRole(array $permissions) { + // testPatch() and testDelete() test the 'bc_entity_resource_permissions' BC + // layer; also call makeCurrentUserFileOwner() then. + if ($permissions === ['restful patch entity:file'] || $permissions === ['restful delete entity:file']) { + $this->makeCurrentUserFileOwner(); + } + parent::grantPermissionsToTestedRole($permissions); + } + + /** + * Makes the current user the file owner. + */ + protected function makeCurrentUserFileOwner() { + $account = static::$auth ? User::load(2) : User::load(0); + $this->entity->setOwnerId($account->id()); + $this->entity->setOwner($account); + $this->entity->save(); + } + + /** + * {@inheritdoc} + */ + protected function createEntity() { + $this->author = User::load(1); + + $file = File::create(); + $file->setOwnerId($this->author->id()); + $file->setFilename('drupal.txt'); + $file->setMimeType('text/plain'); + $file->setFileUri('public://drupal.txt'); + $file->set('status', FILE_STATUS_PERMANENT); + $file->save(); + + file_put_contents($file->getFileUri(), 'Drupal'); + + return $file; + } + + /** + * {@inheritdoc} + */ + protected function getExpectedNormalizedEntity() { + return [ + 'changed' => [ + $this->formatExpectedTimestampItemValues($this->entity->getChangedTime()), + ], + 'created' => [ + $this->formatExpectedTimestampItemValues((int) $this->entity->getCreatedTime()), + ], + 'fid' => [ + [ + 'value' => 1, + ], + ], + 'filemime' => [ + [ + 'value' => 'text/plain', + ], + ], + 'filename' => [ + [ + 'value' => 'drupal.txt', + ], + ], + 'filesize' => [ + [ + 'value' => (int) $this->entity->getSize(), + ], + ], + 'langcode' => [ + [ + 'value' => 'en', + ], + ], + 'status' => [ + [ + 'value' => TRUE, + ], + ], + 'uid' => [ + [ + 'target_id' => (int) $this->author->id(), + 'target_type' => 'user', + 'target_uuid' => $this->author->uuid(), + 'url' => base_path() . 'user/' . $this->author->id(), + ], + ], + 'uri' => [ + [ + 'url' => base_path() . $this->siteDirectory . '/files/drupal.txt', + 'value' => 'public://drupal.txt', + ], + ], + 'uuid' => [ + [ + 'value' => $this->entity->uuid(), + ], + ], + ]; + } + + /** + * {@inheritdoc} + */ + protected function getNormalizedPostEntity() { + return [ + 'uid' => [ + [ + 'target_id' => $this->author->id(), + ], + ], + 'filename' => [ + [ + 'value' => 'drupal.txt', + ], + ], + ]; + } + + /** + * {@inheritdoc} + */ + protected function getNormalizedPatchEntity() { + return array_diff_key($this->getNormalizedPostEntity(), ['uid' => TRUE]); + } + + /** + * {@inheritdoc} + */ + protected function getExpectedCacheContexts() { + return [ + 'user.permissions', + ]; + } + + /** + * {@inheritdoc} + */ + public function testPost() { + // @todo https://www.drupal.org/node/1927648 + $this->markTestSkipped(); + } + + /** + * {@inheritdoc} + */ + protected function getExpectedUnauthorizedAccessMessage($method) { + if ($this->config('rest.settings')->get('bc_entity_resource_permissions')) { + return parent::getExpectedUnauthorizedAccessMessage($method); + } + + if ($method === 'GET') { + return "The 'access content' permission is required."; + } + if ($method === 'PATCH') { + return 'You are not authorized to update this file entity.'; + } + return parent::getExpectedUnauthorizedAccessMessage($method); + } + +} diff -r e200cb7efeb3 -r c2387f117808 core/modules/file/tests/src/Functional/Rest/FileXmlAnonTest.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/core/modules/file/tests/src/Functional/Rest/FileXmlAnonTest.php Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,26 @@ +assertFalse($this->file->access('create')); } + /** + * Tests cacheability metadata. + */ + public function testFileCacheability() { + $file = File::create([ + 'filename' => 'green-scarf', + 'uri' => 'private://green-scarf', + 'filemime' => 'text/plain', + 'status' => FILE_STATUS_PERMANENT, + ]); + $file->save(); + \Drupal::service('session')->set('anonymous_allowed_file_ids', [$file->id() => $file->id()]); + + $account = User::getAnonymousUser(); + $file->setOwnerId($account->id())->save(); + $this->assertSame(['session', 'user'], $file->access('view', $account, TRUE)->getCacheContexts()); + $this->assertSame(['session', 'user'], $file->access('download', $account, TRUE)->getCacheContexts()); + + $account = $this->user1; + $file->setOwnerId($account->id())->save(); + $this->assertSame(['user'], $file->access('view', $account, TRUE)->getCacheContexts()); + $this->assertSame(['user'], $file->access('download', $account, TRUE)->getCacheContexts()); + } + } diff -r e200cb7efeb3 -r c2387f117808 core/modules/file/tests/src/Kernel/FileItemValidationTest.php --- a/core/modules/file/tests/src/Kernel/FileItemValidationTest.php Thu Apr 26 11:26:54 2018 +0100 +++ b/core/modules/file/tests/src/Kernel/FileItemValidationTest.php Tue Jul 10 15:07:59 2018 +0100 @@ -104,6 +104,18 @@ $this->assertEquals('The file is 2.93 KB exceeding the maximum file size of 2 KB.', (string) $result->get(0)->getMessage()); $this->assertEquals('field_test_file.0', $result->get(1)->getPropertyPath()); $this->assertEquals('Only files with the following extensions are allowed: jpg|png.', (string) $result->get(1)->getMessage()); + + // Refer to a file that does not exist. + $entity_test = EntityTest::create([ + 'uid' => $this->user->id(), + 'field_test_file' => [ + 'target_id' => 2, + ], + ]); + $result = $entity_test->validate(); + $this->assertCount(1, $result); + $this->assertEquals('field_test_file.0.target_id', $result->get(0)->getPropertyPath()); + $this->assertEquals('The referenced entity (file: 2) does not exist.', (string) $result->get(0)->getMessage()); } /** diff -r e200cb7efeb3 -r c2387f117808 core/modules/file/tests/src/Kernel/Migrate/d6/MigrateUploadEntityDisplayTest.php --- a/core/modules/file/tests/src/Kernel/Migrate/d6/MigrateUploadEntityDisplayTest.php Thu Apr 26 11:26:54 2018 +0100 +++ b/core/modules/file/tests/src/Kernel/Migrate/d6/MigrateUploadEntityDisplayTest.php Tue Jul 10 15:07:59 2018 +0100 @@ -44,7 +44,7 @@ $component = $display->getComponent('upload'); $this->assertTrue(is_null($component)); - $this->assertIdentical(['node', 'page', 'default', 'upload'], $this->getMigration('d6_upload_entity_display')->getIdMap()->lookupDestinationID(['page'])); + $this->assertIdentical(['node', 'page', 'default', 'upload'], $this->getMigration('d6_upload_entity_display')->getIdMap()->lookupDestinationId(['page'])); } /** diff -r e200cb7efeb3 -r c2387f117808 core/modules/file/tests/src/Kernel/Migrate/d6/MigrateUploadEntityFormDisplayTest.php --- a/core/modules/file/tests/src/Kernel/Migrate/d6/MigrateUploadEntityFormDisplayTest.php Thu Apr 26 11:26:54 2018 +0100 +++ b/core/modules/file/tests/src/Kernel/Migrate/d6/MigrateUploadEntityFormDisplayTest.php Tue Jul 10 15:07:59 2018 +0100 @@ -44,7 +44,7 @@ $component = $display->getComponent('upload'); $this->assertTrue(is_null($component)); - $this->assertIdentical(['node', 'page', 'default', 'upload'], $this->getMigration('d6_upload_entity_form_display')->getIdMap()->lookupDestinationID(['page'])); + $this->assertIdentical(['node', 'page', 'default', 'upload'], $this->getMigration('d6_upload_entity_form_display')->getIdMap()->lookupDestinationId(['page'])); } /** diff -r e200cb7efeb3 -r c2387f117808 core/modules/file/tests/src/Kernel/Migrate/d6/MigrateUploadFieldTest.php --- a/core/modules/file/tests/src/Kernel/Migrate/d6/MigrateUploadFieldTest.php Thu Apr 26 11:26:54 2018 +0100 +++ b/core/modules/file/tests/src/Kernel/Migrate/d6/MigrateUploadFieldTest.php Tue Jul 10 15:07:59 2018 +0100 @@ -31,7 +31,7 @@ public function testUpload() { $field_storage = FieldStorageConfig::load('node.upload'); $this->assertIdentical('node.upload', $field_storage->id()); - $this->assertIdentical(['node', 'upload'], $this->getMigration('d6_upload_field')->getIdMap()->lookupDestinationID([''])); + $this->assertIdentical(['node', 'upload'], $this->getMigration('d6_upload_field')->getIdMap()->lookupDestinationId([''])); } } diff -r e200cb7efeb3 -r c2387f117808 core/modules/file/tests/src/Kernel/Migrate/d6/MigrateUploadInstanceTest.php --- a/core/modules/file/tests/src/Kernel/Migrate/d6/MigrateUploadInstanceTest.php Thu Apr 26 11:26:54 2018 +0100 +++ b/core/modules/file/tests/src/Kernel/Migrate/d6/MigrateUploadInstanceTest.php Tue Jul 10 15:07:59 2018 +0100 @@ -43,7 +43,7 @@ $field = FieldConfig::load('node.article.upload'); $this->assertTrue(is_null($field)); - $this->assertIdentical(['node', 'page', 'upload'], $this->getMigration('d6_upload_field_instance')->getIdMap()->lookupDestinationID(['page'])); + $this->assertIdentical(['node', 'page', 'upload'], $this->getMigration('d6_upload_field_instance')->getIdMap()->lookupDestinationId(['page'])); } } diff -r e200cb7efeb3 -r c2387f117808 core/modules/file/tests/src/Kernel/Migrate/d7/FileMigrationSetupTrait.php --- a/core/modules/file/tests/src/Kernel/Migrate/d7/FileMigrationSetupTrait.php Thu Apr 26 11:26:54 2018 +0100 +++ b/core/modules/file/tests/src/Kernel/Migrate/d7/FileMigrationSetupTrait.php Tue Jul 10 15:07:59 2018 +0100 @@ -2,8 +2,8 @@ namespace Drupal\Tests\file\Kernel\Migrate\d7; -use Drupal\Core\StreamWrapper\PublicStream; -use Drupal\Core\StreamWrapper\StreamWrapperInterface; +use Drupal\file\Entity\File; +use Drupal\file\FileInterface; /** * A trait to setup the file migration. @@ -11,27 +11,71 @@ trait FileMigrationSetupTrait { /** + * Returns information about the file to be migrated. + * + * @return array + * Array with keys 'path', 'size', 'base_path', and 'plugin_id'. + */ + abstract protected function getFileMigrationInfo(); + + /** * Prepare the file migration for running. */ protected function fileMigrationSetup() { + $this->installEntitySchema('file'); $this->installSchema('file', ['file_usage']); - $this->installEntitySchema('file'); - $this->container->get('stream_wrapper_manager')->registerWrapper('public', PublicStream::class, StreamWrapperInterface::NORMAL); - $fs = \Drupal::service('file_system'); - // The public file directory active during the test will serve as the - // root of the fictional Drupal 7 site we're migrating. - $fs->mkdir('public://sites/default/files', NULL, TRUE); - file_put_contents('public://sites/default/files/cube.jpeg', str_repeat('*', 3620)); + $info = $this->getFileMigrationInfo(); + $fs = $this->container->get('file_system'); + // Ensure that the files directory exists. + $fs->mkdir(dirname($info['path']), NULL, TRUE); + // Put test file in the source directory. + file_put_contents($info['path'], str_repeat('*', $info['size'])); /** @var \Drupal\migrate\Plugin\Migration $migration */ - $migration = $this->getMigration('d7_file'); + $migration = $this->getMigration($info['plugin_id']); // Set the source plugin's source_base_path configuration value, which // would normally be set by the user running the migration. $source = $migration->getSourceConfiguration(); - $source['constants']['source_base_path'] = $fs->realpath('public://'); + $source['constants']['source_base_path'] = $fs->realpath($info['base_path']); $migration->set('source', $source); $this->executeMigration($migration); } + /** + * Tests a single file entity. + * + * @param int $id + * The file ID. + * @param string $name + * The expected file name. + * @param string $uri + * The expected URI. + * @param string $mime + * The expected MIME type. + * @param string $size + * The expected file size. + * @param string $created + * The expected creation time. + * @param string $changed + * The expected modification time. + * @param string $uid + * The expected owner ID. + */ + protected function assertEntity($id, $name, $uri, $mime, $size, $created, $changed, $uid) { + /** @var \Drupal\file\FileInterface $file */ + $file = File::load($id); + $this->assertInstanceOf(FileInterface::class, $file); + $this->assertSame($name, $file->getFilename()); + $this->assertSame($uri, $file->getFileUri()); + $this->assertFileExists($uri); + $this->assertSame($mime, $file->getMimeType()); + $this->assertSame($size, $file->getSize()); + // isPermanent(), isTemporary(), etc. are determined by the status column. + $this->assertTrue($file->isPermanent()); + $this->assertSame($created, $file->getCreatedTime()); + $this->assertSame($changed, $file->getChangedTime()); + $this->assertSame($uid, $file->getOwnerId()); + } + } diff -r e200cb7efeb3 -r c2387f117808 core/modules/file/tests/src/Kernel/Migrate/d7/MigrateFileTest.php --- a/core/modules/file/tests/src/Kernel/Migrate/d7/MigrateFileTest.php Thu Apr 26 11:26:54 2018 +0100 +++ b/core/modules/file/tests/src/Kernel/Migrate/d7/MigrateFileTest.php Tue Jul 10 15:07:59 2018 +0100 @@ -2,8 +2,6 @@ namespace Drupal\Tests\file\Kernel\Migrate\d7; -use Drupal\file\Entity\File; -use Drupal\file\FileInterface; use Drupal\Tests\migrate_drupal\Kernel\d7\MigrateDrupal7TestBase; /** @@ -15,6 +13,9 @@ use FileMigrationSetupTrait; + /** + * {@inheritdoc} + */ public static $modules = ['file']; /** @@ -22,44 +23,19 @@ */ protected function setUp() { parent::setUp(); - $this->fileMigrationSetup(); } /** - * Tests a single file entity. - * - * @param int $id - * The file ID. - * @param string $name - * The expected file name. - * @param string $uri - * The expected URI. - * @param string $mime - * The expected MIME type. - * @param int $size - * The expected file size. - * @param int $created - * The expected creation time. - * @param int $changed - * The expected modification time. - * @param int $uid - * The expected owner ID. + * {@inheritdoc} */ - protected function assertEntity($id, $name, $uri, $mime, $size, $created, $changed, $uid) { - /** @var \Drupal\file\FileInterface $file */ - $file = File::load($id); - $this->assertTrue($file instanceof FileInterface); - $this->assertIdentical($name, $file->getFilename()); - $this->assertIdentical($uri, $file->getFileUri()); - $this->assertTrue(file_exists($uri)); - $this->assertIdentical($mime, $file->getMimeType()); - $this->assertIdentical($size, $file->getSize()); - // isPermanent(), isTemporary(), etc. are determined by the status column. - $this->assertTrue($file->isPermanent()); - $this->assertIdentical($created, $file->getCreatedTime()); - $this->assertIdentical($changed, $file->getChangedTime()); - $this->assertIdentical($uid, $file->getOwnerId()); + protected function getFileMigrationInfo() { + return [ + 'path' => 'public://sites/default/files/cube.jpeg', + 'size' => '3620', + 'base_path' => 'public://', + 'plugin_id' => 'd7_file', + ]; } /** diff -r e200cb7efeb3 -r c2387f117808 core/modules/file/tests/src/Kernel/Migrate/d7/MigratePrivateFileTest.php --- a/core/modules/file/tests/src/Kernel/Migrate/d7/MigratePrivateFileTest.php Thu Apr 26 11:26:54 2018 +0100 +++ b/core/modules/file/tests/src/Kernel/Migrate/d7/MigratePrivateFileTest.php Tue Jul 10 15:07:59 2018 +0100 @@ -3,8 +3,6 @@ namespace Drupal\Tests\file\Kernel\Migrate\d7; use Drupal\Core\DependencyInjection\ContainerBuilder; -use Drupal\file\Entity\File; -use Drupal\file\FileInterface; use Drupal\Tests\migrate_drupal\Kernel\d7\MigrateDrupal7TestBase; /** @@ -14,6 +12,8 @@ */ class MigratePrivateFileTest extends MigrateDrupal7TestBase { + use FileMigrationSetupTrait; + /** * {@inheritdoc} */ @@ -25,22 +25,19 @@ protected function setUp() { parent::setUp(); $this->setSetting('file_private_path', $this->container->get('site.path') . '/private'); - $this->installEntitySchema('file'); - $fs = $this->container->get('file_system'); + $this->fileMigrationSetup(); + } - // Ensure that the private files directory exists. - $fs->mkdir('private://sites/default/private/', NULL, TRUE); - // Put test file in the source directory. - file_put_contents('private://sites/default/private/Babylon5.txt', str_repeat('*', 3)); - - /** @var \Drupal\migrate\Plugin\Migration $migration */ - $migration = $this->getMigration('d7_file_private'); - // Set the source plugin's source_file_private_path configuration value, - // which would normally be set by the user running the migration. - $source = $migration->getSourceConfiguration(); - $source['constants']['source_base_path'] = $fs->realpath('private://'); - $migration->set('source', $source); - $this->executeMigration($migration); + /** + * {@inheritdoc} + */ + protected function getFileMigrationInfo() { + return [ + 'path' => 'private://sites/default/private/Babylon5.txt', + 'size' => '3', + 'base_path' => 'private://', + 'plugin_id' => 'd7_file_private', + ]; } /** @@ -53,42 +50,6 @@ } /** - * Tests a single file entity. - * - * @param int $id - * The file ID. - * @param string $name - * The expected file name. - * @param string $uri - * The expected URI. - * @param string $mime - * The expected MIME type. - * @param int $size - * The expected file size. - * @param int $created - * The expected creation time. - * @param int $changed - * The expected modification time. - * @param int $uid - * The expected owner ID. - */ - protected function assertEntity($id, $name, $uri, $mime, $size, $created, $changed, $uid) { - /** @var \Drupal\file\FileInterface $file */ - $file = File::load($id); - $this->assertInstanceOf(FileInterface::class, $file); - $this->assertSame($name, $file->getFilename()); - $this->assertSame($uri, $file->getFileUri()); - $this->assertFileExists($uri); - $this->assertSame($mime, $file->getMimeType()); - $this->assertSame($size, $file->getSize()); - // isPermanent(), isTemporary(), etc. are determined by the status column. - $this->assertTrue($file->isPermanent()); - $this->assertSame($created, $file->getCreatedTime()); - $this->assertSame($changed, $file->getChangedTime()); - $this->assertSame($uid, $file->getOwnerId()); - } - - /** * Tests that all expected files are migrated. */ public function testFileMigration() { diff -r e200cb7efeb3 -r c2387f117808 core/modules/filter/tests/src/Functional/Hal/FilterFormatHalJsonAnonTest.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/core/modules/filter/tests/src/Functional/Hal/FilterFormatHalJsonAnonTest.php Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,30 @@ +grantPermissionsToTestedRole(['administer filters']); + } + + /** + * {@inheritdoc} + */ + protected function createEntity() { + $pablo_format = FilterFormat::create([ + 'name' => 'Pablo Piccasso', + 'format' => 'pablo', + 'langcode' => 'es', + 'filters' => [ + 'filter_html' => [ + 'status' => TRUE, + 'settings' => [ + 'allowed_html' => '

    ', + ], + ], + ], + ]); + $pablo_format->save(); + return $pablo_format; + } + + /** + * {@inheritdoc} + */ + protected function getExpectedNormalizedEntity() { + return [ + 'dependencies' => [], + 'filters' => [ + 'filter_html' => [ + 'id' => 'filter_html', + 'provider' => 'filter', + 'status' => TRUE, + 'weight' => -10, + 'settings' => [ + 'allowed_html' => '

    ', + 'filter_html_help' => TRUE, + 'filter_html_nofollow' => FALSE, + ], + ], + ], + 'format' => 'pablo', + 'langcode' => 'es', + 'name' => 'Pablo Piccasso', + 'status' => TRUE, + 'uuid' => $this->entity->uuid(), + 'weight' => 0, + ]; + } + + /** + * {@inheritdoc} + */ + protected function getNormalizedPostEntity() { + // @todo Update in https://www.drupal.org/node/2300677. + } + +} diff -r e200cb7efeb3 -r c2387f117808 core/modules/filter/tests/src/Functional/Rest/FilterFormatXmlAnonTest.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/core/modules/filter/tests/src/Functional/Rest/FilterFormatXmlAnonTest.php Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,26 @@ + TRUE, 'map' => [ @@ -78,11 +78,14 @@ } /** - * The test data provider. + * Provides filter ids for testing transformations. * * @return array + * Formatted as $source_id, $tranformed_id, $invalid_id. + * When $invalid_id is provided the transformation should fail with the + * supplied id. */ - public function testProvider() { + public function provideFilters() { return [ // The filter ID is mapped, and the plugin exists. [ diff -r e200cb7efeb3 -r c2387f117808 core/modules/hal/tests/src/Functional/EntityResource/Action/ActionHalJsonAnonTest.php --- a/core/modules/hal/tests/src/Functional/EntityResource/Action/ActionHalJsonAnonTest.php Thu Apr 26 11:26:54 2018 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,30 +0,0 @@ -applyHalFieldNormalization($default_normalization); - - return $normalization + [ - '_links' => [ - 'self' => [ - 'href' => $this->baseUrl . '/block/1?_format=hal_json', - ], - 'type' => [ - 'href' => $this->baseUrl . '/rest/type/block_content/basic', - ], - ], - ]; - } - - /** - * {@inheritdoc} - */ - protected function getNormalizedPostEntity() { - return parent::getNormalizedPostEntity() + [ - '_links' => [ - 'type' => [ - 'href' => $this->baseUrl . '/rest/type/block_content/basic', - ], - ], - ]; - } - - /** - * {@inheritdoc} - */ - protected function getExpectedCacheContexts() { - // The 'url.site' cache context is added for '_links' in the response. - return Cache::mergeTags(parent::getExpectedCacheContexts(), ['url.site']); - } - -} diff -r e200cb7efeb3 -r c2387f117808 core/modules/hal/tests/src/Functional/EntityResource/BlockContent/BlockContentHalJsonBasicAuthTest.php --- a/core/modules/hal/tests/src/Functional/EntityResource/BlockContent/BlockContentHalJsonBasicAuthTest.php Thu Apr 26 11:26:54 2018 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,24 +0,0 @@ -applyHalFieldNormalization($default_normalization); - - // Because \Drupal\comment\Entity\Comment::getOwner() generates an in-memory - // User entity without a UUID, we cannot use it. - $author = User::load($this->entity->getOwnerId()); - $commented_entity = EntityTest::load(1); - return $normalization + [ - '_links' => [ - 'self' => [ - 'href' => $this->baseUrl . '/comment/1?_format=hal_json', - ], - 'type' => [ - 'href' => $this->baseUrl . '/rest/type/comment/comment', - ], - $this->baseUrl . '/rest/relation/comment/comment/entity_id' => [ - [ - 'href' => $this->baseUrl . '/entity_test/1?_format=hal_json', - ], - ], - $this->baseUrl . '/rest/relation/comment/comment/uid' => [ - [ - 'href' => $this->baseUrl . '/user/' . $author->id() . '?_format=hal_json', - 'lang' => 'en', - ], - ], - ], - '_embedded' => [ - $this->baseUrl . '/rest/relation/comment/comment/entity_id' => [ - [ - '_links' => [ - 'self' => [ - 'href' => $this->baseUrl . '/entity_test/1?_format=hal_json', - ], - 'type' => [ - 'href' => $this->baseUrl . '/rest/type/entity_test/bar', - ], - ], - 'uuid' => [ - ['value' => $commented_entity->uuid()] - ], - ], - ], - $this->baseUrl . '/rest/relation/comment/comment/uid' => [ - [ - '_links' => [ - 'self' => [ - 'href' => $this->baseUrl . '/user/' . $author->id() . '?_format=hal_json', - ], - 'type' => [ - 'href' => $this->baseUrl . '/rest/type/user/user', - ], - ], - 'uuid' => [ - ['value' => $author->uuid()] - ], - 'lang' => 'en', - ], - ], - ], - ]; - } - - /** - * {@inheritdoc} - */ - protected function getNormalizedPostEntity() { - return parent::getNormalizedPostEntity() + [ - '_links' => [ - 'type' => [ - 'href' => $this->baseUrl . '/rest/type/comment/comment', - ], - ], - ]; - } - +/** + * Class for backward compatibility. It is deprecated in Drupal 8.6.x. + * + * @see https://www.drupal.org/node/2971931 + */ +abstract class CommentHalJsonTestBase extends CommentHalJsonTestBaseReal { } diff -r e200cb7efeb3 -r c2387f117808 core/modules/hal/tests/src/Functional/EntityResource/CommentType/CommentTypeHalJsonAnonTest.php --- a/core/modules/hal/tests/src/Functional/EntityResource/CommentType/CommentTypeHalJsonAnonTest.php Thu Apr 26 11:26:54 2018 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,30 +0,0 @@ -applyHalFieldNormalization($default_normalization); - - $author = User::load(0); - return $normalization + [ - '_links' => [ - 'self' => [ - 'href' => $this->baseUrl . '/entity_test/1?_format=hal_json', - ], - 'type' => [ - 'href' => $this->baseUrl . '/rest/type/entity_test/entity_test', - ], - $this->baseUrl . '/rest/relation/entity_test/entity_test/user_id' => [ - [ - 'href' => $this->baseUrl . '/user/0?_format=hal_json', - 'lang' => 'en', - ], - ], - ], - '_embedded' => [ - $this->baseUrl . '/rest/relation/entity_test/entity_test/user_id' => [ - [ - '_links' => [ - 'self' => [ - 'href' => $this->baseUrl . '/user/0?_format=hal_json', - ], - 'type' => [ - 'href' => $this->baseUrl . '/rest/type/user/user', - ], - ], - 'uuid' => [ - ['value' => $author->uuid()] - ], - 'lang' => 'en', - ], - ], - ], - ]; - } - - /** - * {@inheritdoc} - */ - protected function getNormalizedPostEntity() { - return parent::getNormalizedPostEntity() + [ - '_links' => [ - 'type' => [ - 'href' => $this->baseUrl . '/rest/type/entity_test/entity_test', - ], - ], - ]; - } - -} diff -r e200cb7efeb3 -r c2387f117808 core/modules/hal/tests/src/Functional/EntityResource/EntityTest/EntityTestHalJsonBasicAuthTest.php --- a/core/modules/hal/tests/src/Functional/EntityResource/EntityTest/EntityTestHalJsonBasicAuthTest.php Thu Apr 26 11:26:54 2018 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,24 +0,0 @@ -applyHalFieldNormalization($default_normalization); - // The 'internal_value' property in test field type will not be returned in - // normalization because setInternal(FALSE) was not called for this - // property. - // @see \Drupal\entity_test\Plugin\Field\FieldType\InternalPropertyTestFieldItem::propertyDefinitions - $normalization['field_test_internal'] = [ - [ - 'value' => 'This value shall not be internal!', - 'non_internal_value' => 'Computed! This value shall not be internal!', - ], - ]; - return $normalization; - } - - /** - * {@inheritdoc} - */ - protected function createEntity() { - if (!FieldStorageConfig::loadByName('entity_test', 'field_test_internal')) { - FieldStorageConfig::create([ - 'entity_type' => 'entity_test', - 'field_name' => 'field_test_internal', - 'type' => 'internal_property_test', - 'cardinality' => 1, - 'translatable' => FALSE, - ])->save(); - FieldConfig::create([ - 'entity_type' => 'entity_test', - 'field_name' => 'field_test_internal', - 'bundle' => 'entity_test', - 'label' => 'Test field with internal and non-internal properties', - ])->save(); - } - - $entity = parent::createEntity(); - $entity->field_test_internal = [ - 'value' => 'This value shall not be internal!', - ]; - $entity->save(); - return $entity; - } - - /** - * {@inheritdoc} - */ - protected function getNormalizedPostEntity() { - return parent::getNormalizedPostEntity() + [ - 'field_test_internal' => [ - [ - 'value' => 'This value shall not be internal!', - ], - ], - ]; - } - - /** - * {@inheritdoc} - */ - protected function getExpectedCacheContexts() { - return Cache::mergeContexts(parent::getExpectedCacheContexts(), ['request_format']); - } - - /** - * {@inheritdoc} - */ - protected function getExpectedCacheTags() { - return Cache::mergeTags(parent::getExpectedCacheTags(), ['you_are_it', 'no_tag_backs']); - } - -} diff -r e200cb7efeb3 -r c2387f117808 core/modules/hal/tests/src/Functional/EntityResource/EntityTestBundle/EntityTestBundleHalJsonAnonTest.php --- a/core/modules/hal/tests/src/Functional/EntityResource/EntityTestBundle/EntityTestBundleHalJsonAnonTest.php Thu Apr 26 11:26:54 2018 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,32 +0,0 @@ -applyHalFieldNormalization($default_normalization); - - $author = User::load(0); - return $normalization + [ - '_links' => [ - 'self' => [ - 'href' => '', - ], - 'type' => [ - 'href' => $this->baseUrl . '/rest/type/entity_test_label/entity_test_label', - ], - $this->baseUrl . '/rest/relation/entity_test_label/entity_test_label/user_id' => [ - [ - 'href' => $this->baseUrl . '/user/0?_format=hal_json', - 'lang' => 'en', - ], - ], - ], - '_embedded' => [ - $this->baseUrl . '/rest/relation/entity_test_label/entity_test_label/user_id' => [ - [ - '_links' => [ - 'self' => [ - 'href' => $this->baseUrl . '/user/0?_format=hal_json', - ], - 'type' => [ - 'href' => $this->baseUrl . '/rest/type/user/user', - ], - ], - 'uuid' => [ - [ - 'value' => $author->uuid(), - ], - ], - 'lang' => 'en', - ], - ], - ], - ]; - } - - /** - * {@inheritdoc} - */ - protected function getNormalizedPostEntity() { - return parent::getNormalizedPostEntity() + [ - '_links' => [ - 'type' => [ - 'href' => $this->baseUrl . '/rest/type/entity_test_label/entity_test_label', - ], - ], - ]; - } - - /** - * {@inheritdoc} - */ - protected function getExpectedCacheContexts() { - return [ - 'url.site', - 'user.permissions', - ]; - } - -} diff -r e200cb7efeb3 -r c2387f117808 core/modules/hal/tests/src/Functional/EntityResource/EntityTestLabel/EntityTestLabelHalJsonBasicAuthTest.php --- a/core/modules/hal/tests/src/Functional/EntityResource/EntityTestLabel/EntityTestLabelHalJsonBasicAuthTest.php Thu Apr 26 11:26:54 2018 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,24 +0,0 @@ -applyHalFieldNormalization($default_normalization); - - return $normalization + [ - '_links' => [ - 'self' => [ - 'href' => $this->baseUrl . '/aggregator/sources/1?_format=hal_json' - ], - 'type' => [ - 'href' => $this->baseUrl . '/rest/type/aggregator_feed/aggregator_feed' - ], - ], - ]; - } - - /** - * {@inheritdoc} - */ - protected function getNormalizedPostEntity() { - return parent::getNormalizedPostEntity() + [ - '_links' => [ - 'type' => [ - 'href' => $this->baseUrl . '/rest/type/aggregator_feed/aggregator_feed' - ], - ], - ]; - } - +/** + * Class for backward compatibility. It is deprecated in Drupal 8.6.x. + * + * @see https://www.drupal.org/node/2971931 + */ +abstract class FeedHalJsonTestBase extends FeedHalJsonTestBaseReal { } diff -r e200cb7efeb3 -r c2387f117808 core/modules/hal/tests/src/Functional/EntityResource/FieldConfig/FieldConfigHalJsonAnonTest.php --- a/core/modules/hal/tests/src/Functional/EntityResource/FieldConfig/FieldConfigHalJsonAnonTest.php Thu Apr 26 11:26:54 2018 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,30 +0,0 @@ -applyHalFieldNormalization($default_normalization); - - $url = file_create_url($this->entity->getFileUri()); - // @see \Drupal\Tests\hal\Functional\EntityResource\File\FileHalJsonAnonTest::testGetBcUriField() - if ($this->config('hal.settings')->get('bc_file_uri_as_url_normalizer')) { - $normalization['uri'][0]['value'] = $url; - } - - $uid = $this->author->id(); - - return $normalization + [ - '_embedded' => [ - $this->baseUrl . '/rest/relation/file/file/uid' => [ - [ - '_links' => [ - 'self' => [ - 'href' => $this->baseUrl . "/user/$uid?_format=hal_json", - ], - 'type' => [ - 'href' => $this->baseUrl . '/rest/type/user/user', - ], - ], - 'uuid' => [ - [ - 'value' => $this->author->uuid(), - ], - ], - ], - ], - ], - '_links' => [ - 'self' => [ - 'href' => $url, - ], - 'type' => [ - 'href' => $this->baseUrl . '/rest/type/file/file', - ], - $this->baseUrl . '/rest/relation/file/file/uid' => [ - [ - 'href' => $this->baseUrl . "/user/$uid?_format=hal_json", - ], - ], - ], - ]; - } - - /** - * {@inheritdoc} - */ - protected function getNormalizedPostEntity() { - return parent::getNormalizedPostEntity() + [ - '_links' => [ - 'type' => [ - 'href' => $this->baseUrl . '/rest/type/file/file', - ], - ], - ]; - } - - /** - * {@inheritdoc} - */ - protected function getExpectedCacheTags() { - return Cache::mergeTags(parent::getExpectedCacheTags(), ['config:hal.settings']); - } - - /** - * {@inheritdoc} - */ - protected function getExpectedCacheContexts() { - return [ - 'url.site', - 'user.permissions', - ]; - } - - /** - * @see hal_update_8501() - */ - public function testGetBcUriField() { - $this->config('hal.settings')->set('bc_file_uri_as_url_normalizer', TRUE)->save(TRUE); - - $this->initAuthentication(); - $url = $this->getEntityResourceUrl(); - $url->setOption('query', ['_format' => static::$format]); - $request_options = $this->getAuthenticationRequestOptions('GET'); - $this->provisionEntityResource(); - $this->setUpAuthorization('GET'); - $response = $this->request('GET', $url, $request_options); - $expected = $this->getExpectedNormalizedEntity(); - static::recursiveKSort($expected); - $actual = $this->serializer->decode((string) $response->getBody(), static::$format); - static::recursiveKSort($actual); - $this->assertSame($expected, $actual); - - // Explicitly assert that $file->uri->value is an absolute file URL, unlike - // the default normalization. - $this->assertSame($this->baseUrl . '/' . $this->siteDirectory . '/files/drupal.txt', $actual['uri'][0]['value']); - } - - /** - * {@inheritdoc} - */ - public function testPatch() { - // @todo https://www.drupal.org/node/1927648 - $this->markTestSkipped(); - } - -} diff -r e200cb7efeb3 -r c2387f117808 core/modules/hal/tests/src/Functional/EntityResource/File/FileHalJsonBasicAuthTest.php --- a/core/modules/hal/tests/src/Functional/EntityResource/File/FileHalJsonBasicAuthTest.php Thu Apr 26 11:26:54 2018 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,24 +0,0 @@ -applyHalFieldNormalization($default_normalization); - $feed = Feed::load($this->entity->getFeedId()); - - return $normalization + [ - '_embedded' => [ - $this->baseUrl . '/rest/relation/aggregator_item/aggregator_item/fid' => [ - [ - '_links' => [ - 'self' => [ - 'href' => $this->baseUrl . '/aggregator/sources/1?_format=hal_json', - ], - 'type' => [ - 'href' => $this->baseUrl . '/rest/type/aggregator_feed/aggregator_feed', - ], - ], - 'uuid' => [ - [ - 'value' => $feed->uuid(), - ], - ], - ], - ], - ], - '_links' => [ - 'self' => [ - 'href' => '', - ], - 'type' => [ - 'href' => $this->baseUrl . '/rest/type/aggregator_item/aggregator_item', - ], - $this->baseUrl . '/rest/relation/aggregator_item/aggregator_item/fid' => [ - [ - 'href' => $this->baseUrl . '/aggregator/sources/' . $feed->id() . '?_format=hal_json', - ], - ], - ], - ]; - } - - /** - * {@inheritdoc} - */ - protected function getNormalizedPostEntity() { - return parent::getNormalizedPostEntity() + [ - '_links' => [ - 'type' => [ - 'href' => $this->baseUrl . '/rest/type/aggregator_item/aggregator_item', - ], - ], - ]; - } - - /** - * {@inheritdoc} - */ - protected function getExpectedCacheContexts() { - return [ - 'url.site', - 'user.permissions', - ]; - } - +abstract class ItemHalJsonTestBase extends ItemHalJsonTestBaseReal { } diff -r e200cb7efeb3 -r c2387f117808 core/modules/hal/tests/src/Functional/EntityResource/Media/MediaHalJsonAnonTest.php --- a/core/modules/hal/tests/src/Functional/EntityResource/Media/MediaHalJsonAnonTest.php Thu Apr 26 11:26:54 2018 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,174 +0,0 @@ -applyHalFieldNormalization($default_normalization); - - $file = File::load(1); - $thumbnail = File::load(2); - $author = User::load($this->entity->getOwnerId()); - return $normalization + [ - '_links' => [ - 'self' => [ - 'href' => $this->baseUrl . '/media/1?_format=hal_json', - ], - 'type' => [ - 'href' => $this->baseUrl . '/rest/type/media/camelids', - ], - $this->baseUrl . '/rest/relation/media/camelids/field_media_file' => [ - [ - 'href' => $file->url(), - 'lang' => 'en', - ], - ], - $this->baseUrl . '/rest/relation/media/camelids/revision_user' => [ - [ - 'href' => $this->baseUrl . '/user/' . $author->id() . '?_format=hal_json', - ], - ], - $this->baseUrl . '/rest/relation/media/camelids/thumbnail' => [ - [ - 'href' => $thumbnail->url(), - 'lang' => 'en', - ], - ], - $this->baseUrl . '/rest/relation/media/camelids/uid' => [ - [ - 'href' => $this->baseUrl . '/user/' . $author->id() . '?_format=hal_json', - 'lang' => 'en', - ], - ], - ], - '_embedded' => [ - $this->baseUrl . '/rest/relation/media/camelids/field_media_file' => [ - [ - '_links' => [ - 'self' => [ - 'href' => $file->url(), - ], - 'type' => [ - 'href' => $this->baseUrl . '/rest/type/file/file', - ], - ], - 'lang' => 'en', - 'uuid' => [ - [ - 'value' => $file->uuid(), - ], - ], - ], - ], - $this->baseUrl . '/rest/relation/media/camelids/revision_user' => [ - [ - '_links' => [ - 'self' => [ - 'href' => $this->baseUrl . '/user/' . $author->id() . '?_format=hal_json', - ], - 'type' => [ - 'href' => $this->baseUrl . '/rest/type/user/user', - ], - ], - 'uuid' => [ - [ - 'value' => $author->uuid(), - ], - ], - ], - ], - $this->baseUrl . '/rest/relation/media/camelids/thumbnail' => [ - [ - '_links' => [ - 'self' => [ - 'href' => $thumbnail->url(), - ], - 'type' => [ - 'href' => $this->baseUrl . '/rest/type/file/file', - ], - ], - 'lang' => 'en', - 'uuid' => [ - [ - 'value' => $thumbnail->uuid(), - ], - ], - ], - ], - $this->baseUrl . '/rest/relation/media/camelids/uid' => [ - [ - '_links' => [ - 'self' => [ - 'href' => $this->baseUrl . '/user/' . $author->id() . '?_format=hal_json', - ], - 'type' => [ - 'href' => $this->baseUrl . '/rest/type/user/user', - ], - ], - 'uuid' => [ - [ - 'value' => $author->uuid(), - ], - ], - 'lang' => 'en', - ], - ], - ], - ]; - } - - /** - * {@inheritdoc} - */ - protected function getNormalizedPostEntity() { - return parent::getNormalizedPostEntity() + [ - '_links' => [ - 'type' => [ - 'href' => $this->baseUrl . '/rest/type/media/camelids', - ], - ], - ]; - } - - /** - * {@inheritdoc} - */ - protected function getExpectedCacheTags() { - return Cache::mergeTags(parent::getExpectedCacheTags(), ['config:hal.settings']); - } - -} diff -r e200cb7efeb3 -r c2387f117808 core/modules/hal/tests/src/Functional/EntityResource/Media/MediaHalJsonBasicAuthTest.php --- a/core/modules/hal/tests/src/Functional/EntityResource/Media/MediaHalJsonBasicAuthTest.php Thu Apr 26 11:26:54 2018 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,24 +0,0 @@ -applyHalFieldNormalization($default_normalization); - - return $normalization + [ - '_links' => [ - 'self' => [ - 'href' => $this->baseUrl . '/admin/structure/menu/item/1/edit?_format=hal_json', - ], - 'type' => [ - 'href' => $this->baseUrl . '/rest/type/menu_link_content/menu_link_content', - ], - ], - ]; - } - - /** - * {@inheritdoc} - */ - protected function getNormalizedPostEntity() { - return parent::getNormalizedPostEntity() + [ - '_links' => [ - 'type' => [ - 'href' => $this->baseUrl . '/rest/type/menu_link_content/menu_link_content', - ], - ], - ]; - } - - /** - * {@inheritdoc} - */ - protected function getExpectedCacheContexts() { - // The 'url.site' cache context is added for '_links' in the response. - return Cache::mergeTags(parent::getExpectedCacheContexts(), ['url.site']); - } - -} diff -r e200cb7efeb3 -r c2387f117808 core/modules/hal/tests/src/Functional/EntityResource/MenuLinkContent/MenuLinkContentHalJsonBasicAuthTest.php --- a/core/modules/hal/tests/src/Functional/EntityResource/MenuLinkContent/MenuLinkContentHalJsonBasicAuthTest.php Thu Apr 26 11:26:54 2018 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,24 +0,0 @@ - [ - 'type' => [ - 'href' => $this->baseUrl . '/rest/type/contact_message/camelids', - ], - ], - ]; - } - -} diff -r e200cb7efeb3 -r c2387f117808 core/modules/hal/tests/src/Functional/EntityResource/Message/MessageHalJsonBasicAuthTest.php --- a/core/modules/hal/tests/src/Functional/EntityResource/Message/MessageHalJsonBasicAuthTest.php Thu Apr 26 11:26:54 2018 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,24 +0,0 @@ -applyHalFieldNormalization($default_normalization); - - $author = User::load($this->entity->getOwnerId()); - return $normalization + [ - '_links' => [ - 'self' => [ - 'href' => $this->baseUrl . '/llama?_format=hal_json', - ], - 'type' => [ - 'href' => $this->baseUrl . '/rest/type/node/camelids', - ], - $this->baseUrl . '/rest/relation/node/camelids/revision_uid' => [ - [ - 'href' => $this->baseUrl . '/user/' . $author->id() . '?_format=hal_json', - ], - ], - $this->baseUrl . '/rest/relation/node/camelids/uid' => [ - [ - 'href' => $this->baseUrl . '/user/' . $author->id() . '?_format=hal_json', - 'lang' => 'en', - ], - ], - ], - '_embedded' => [ - $this->baseUrl . '/rest/relation/node/camelids/revision_uid' => [ - [ - '_links' => [ - 'self' => [ - 'href' => $this->baseUrl . '/user/' . $author->id() . '?_format=hal_json', - ], - 'type' => [ - 'href' => $this->baseUrl . '/rest/type/user/user', - ], - ], - 'uuid' => [ - ['value' => $author->uuid()] - ], - ], - ], - $this->baseUrl . '/rest/relation/node/camelids/uid' => [ - [ - '_links' => [ - 'self' => [ - 'href' => $this->baseUrl . '/user/' . $author->id() . '?_format=hal_json', - ], - 'type' => [ - 'href' => $this->baseUrl . '/rest/type/user/user', - ], - ], - 'uuid' => [ - ['value' => $author->uuid()] - ], - 'lang' => 'en', - ], - ], - ], - ]; - } - - /** - * {@inheritdoc} - */ - protected function getNormalizedPostEntity() { - return parent::getNormalizedPostEntity() + [ - '_links' => [ - 'type' => [ - 'href' => $this->baseUrl . '/rest/type/node/camelids', - ], - ], - ]; - } - -} diff -r e200cb7efeb3 -r c2387f117808 core/modules/hal/tests/src/Functional/EntityResource/Node/NodeHalJsonBasicAuthTest.php --- a/core/modules/hal/tests/src/Functional/EntityResource/Node/NodeHalJsonBasicAuthTest.php Thu Apr 26 11:26:54 2018 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,24 +0,0 @@ -applyHalFieldNormalization($default_normalization); - - return $normalization + [ - '_links' => [ - 'self' => [ - 'href' => $this->baseUrl . '/admin/config/user-interface/shortcut/link/1?_format=hal_json', - ], - 'type' => [ - 'href' => $this->baseUrl . '/rest/type/shortcut/default', - ], - ], - ]; - } - - /** - * {@inheritdoc} - */ - protected function getNormalizedPostEntity() { - return parent::getNormalizedPostEntity() + [ - '_links' => [ - 'type' => [ - 'href' => $this->baseUrl . '/rest/type/shortcut/default', - ], - ], - ]; - } - - /** - * {@inheritdoc} - */ - protected function getExpectedCacheContexts() { - // The 'url.site' cache context is added for '_links' in the response. - return Cache::mergeContexts(parent::getExpectedCacheContexts(), ['url.site']); - } - -} diff -r e200cb7efeb3 -r c2387f117808 core/modules/hal/tests/src/Functional/EntityResource/Shortcut/ShortcutHalJsonBasicAuthTest.php --- a/core/modules/hal/tests/src/Functional/EntityResource/Shortcut/ShortcutHalJsonBasicAuthTest.php Thu Apr 26 11:26:54 2018 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,24 +0,0 @@ -applyHalFieldNormalization($default_normalization); - - return $normalization + [ - '_links' => [ - 'self' => [ - 'href' => $this->baseUrl . '/llama?_format=hal_json', - ], - 'type' => [ - 'href' => $this->baseUrl . '/rest/type/taxonomy_term/camelids', - ], - ], - ]; - } - - /** - * {@inheritdoc} - */ - protected function getNormalizedPostEntity() { - return parent::getNormalizedPostEntity() + [ - '_links' => [ - 'type' => [ - 'href' => $this->baseUrl . '/rest/type/taxonomy_term/camelids', - ], - ], - ]; - } - -} diff -r e200cb7efeb3 -r c2387f117808 core/modules/hal/tests/src/Functional/EntityResource/Term/TermHalJsonBasicAuthTest.php --- a/core/modules/hal/tests/src/Functional/EntityResource/Term/TermHalJsonBasicAuthTest.php Thu Apr 26 11:26:54 2018 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,24 +0,0 @@ -applyHalFieldNormalization($default_normalization); - - return $normalization + [ - '_links' => [ - 'self' => [ - 'href' => $this->baseUrl . '/user/3?_format=hal_json', - ], - 'type' => [ - 'href' => $this->baseUrl . '/rest/type/user/user', - ], - ], - ]; - } - - /** - * {@inheritdoc} - */ - protected function getNormalizedPostEntity() { - return parent::getNormalizedPostEntity() + [ - '_links' => [ - 'type' => [ - 'href' => $this->baseUrl . '/rest/type/user/user', - ], - ], - ]; - } - -} diff -r e200cb7efeb3 -r c2387f117808 core/modules/hal/tests/src/Functional/EntityResource/User/UserHalJsonBasicAuthTest.php --- a/core/modules/hal/tests/src/Functional/EntityResource/User/UserHalJsonBasicAuthTest.php Thu Apr 26 11:26:54 2018 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,24 +0,0 @@ -markTestSkipped(); - } - -} diff -r e200cb7efeb3 -r c2387f117808 core/modules/hal/tests/src/Functional/EntityResource/Vocabulary/VocabularyHalJsonBasicAuthTest.php --- a/core/modules/hal/tests/src/Functional/EntityResource/Vocabulary/VocabularyHalJsonBasicAuthTest.php Thu Apr 26 11:26:54 2018 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,35 +0,0 @@ -moduleExists('comment')) { @@ -61,6 +67,9 @@ } } + /** + * {@inheritdoc} + */ public function query() { // Only add ourselves to the query if logged in. if (\Drupal::currentUser()->isAnonymous()) { diff -r e200cb7efeb3 -r c2387f117808 core/modules/history/src/Plugin/views/filter/HistoryUserTimestamp.php --- a/core/modules/history/src/Plugin/views/filter/HistoryUserTimestamp.php Thu Apr 26 11:26:54 2018 +0100 +++ b/core/modules/history/src/Plugin/views/filter/HistoryUserTimestamp.php Tue Jul 10 15:07:59 2018 +0100 @@ -20,7 +20,9 @@ use UncacheableDependencyTrait; - // Don't display empty space where the operator would be. + /** + * {@inheritdoc} + */ public $no_operator = TRUE; /** @@ -30,6 +32,9 @@ return FALSE; } + /** + * {@inheritdoc} + */ public function buildExposeForm(&$form, FormStateInterface $form_state) { parent::buildExposeForm($form, $form_state); // @todo There are better ways of excluding required and multiple (object flags) @@ -38,6 +43,9 @@ unset($form['expose']['remember']); } + /** + * {@inheritdoc} + */ protected function valueForm(&$form, FormStateInterface $form_state) { // Only present a checkbox for the exposed filter itself. There's no way // to tell the difference between not checked and the default value, so @@ -57,6 +65,9 @@ } } + /** + * {@inheritdoc} + */ public function query() { // This can only work if we're authenticated in. if (!\Drupal::currentUser()->isAuthenticated()) { @@ -70,7 +81,6 @@ // Hey, Drupal kills old history, so nodes that haven't been updated // since HISTORY_READ_LIMIT are bzzzzzzzt outta here! - $limit = REQUEST_TIME - HISTORY_READ_LIMIT; $this->ensureMyTable(); @@ -79,9 +89,9 @@ $clause = ''; $clause2 = ''; - if ($ces = $this->query->ensureTable('comment_entity_statistics', $this->relationship)) { - $clause = ("OR $ces.last_comment_timestamp > (***CURRENT_TIME*** - $limit)"); - $clause2 = "OR $field < $ces.last_comment_timestamp"; + if ($alias = $this->query->ensureTable('comment_entity_statistics', $this->relationship)) { + $clause = "OR $alias.last_comment_timestamp > (***CURRENT_TIME*** - $limit)"; + $clause2 = "OR $field < $alias.last_comment_timestamp"; } // NULL means a history record doesn't exist. That's clearly new content. @@ -90,6 +100,9 @@ $this->query->addWhereExpression($this->options['group'], "($field IS NULL AND ($node.changed > (***CURRENT_TIME*** - $limit) $clause)) OR $field < $node.changed $clause2"); } + /** + * {@inheritdoc} + */ public function adminSummary() { if (!empty($this->options['exposed'])) { return $this->t('exposed'); diff -r e200cb7efeb3 -r c2387f117808 core/modules/image/src/Controller/ImageStyleDownloadController.php --- a/core/modules/image/src/Controller/ImageStyleDownloadController.php Thu Apr 26 11:26:54 2018 +0100 +++ b/core/modules/image/src/Controller/ImageStyleDownloadController.php Tue Jul 10 15:07:59 2018 +0100 @@ -11,6 +11,7 @@ use Symfony\Component\HttpFoundation\BinaryFileResponse; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; +use Symfony\Component\HttpKernel\Exception\NotFoundHttpException; use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException; use Symfony\Component\HttpKernel\Exception\ServiceUnavailableHttpException; @@ -79,6 +80,8 @@ * @return \Symfony\Component\HttpFoundation\BinaryFileResponse|\Symfony\Component\HttpFoundation\Response * The transferred file as response or some error response. * + * @throws \Symfony\Component\HttpKernel\Exception\NotFoundHttpException + * Thrown when the file request is invalid. * @throws \Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException * Thrown when the user does not have access to the file. * @throws \Symfony\Component\HttpKernel\Exception\ServiceUnavailableHttpException @@ -104,7 +107,11 @@ $valid &= $request->query->get(IMAGE_DERIVATIVE_TOKEN) === $image_style->getPathToken($image_uri); } if (!$valid) { - throw new AccessDeniedHttpException(); + // Return a 404 (Page Not Found) rather than a 403 (Access Denied) as the + // image token is for DDoS protection rather than access checking. 404s + // are more likely to be cached (e.g. at a proxy) which enhances + // protection from DDoS. + throw new NotFoundHttpException(); } $derivative_uri = $image_style->buildUri($image_uri); diff -r e200cb7efeb3 -r c2387f117808 core/modules/image/src/Routing/ImageStyleRoutes.php --- a/core/modules/image/src/Routing/ImageStyleRoutes.php Thu Apr 26 11:26:54 2018 +0100 +++ b/core/modules/image/src/Routing/ImageStyleRoutes.php Tue Jul 10 15:07:59 2018 +0100 @@ -20,7 +20,7 @@ protected $streamWrapperManager; /** - * Constructs a new PathProcessorImageStyles object. + * Constructs a new ImageStyleRoutes object. * * @param \Drupal\Core\StreamWrapper\StreamWrapperManagerInterface $stream_wrapper_manager * The stream wrapper manager service. diff -r e200cb7efeb3 -r c2387f117808 core/modules/image/src/Tests/FileMoveTest.php --- a/core/modules/image/src/Tests/FileMoveTest.php Thu Apr 26 11:26:54 2018 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,52 +0,0 @@ -drupalGetTestFiles('image'))); - - // Create derivative image. - $styles = ImageStyle::loadMultiple(); - $style = reset($styles); - $original_uri = $file->getFileUri(); - $derivative_uri = $style->buildUri($original_uri); - $style->createDerivative($original_uri, $derivative_uri); - - // Check if derivative image exists. - $this->assertTrue(file_exists($derivative_uri), 'Make sure derivative image is generated successfully.'); - - // Clone the object so we don't have to worry about the function changing - // our reference copy. - $desired_filepath = 'public://' . $this->randomMachineName(); - $result = file_move(clone $file, $desired_filepath, FILE_EXISTS_ERROR); - - // Check if image has been moved. - $this->assertTrue(file_exists($result->getFileUri()), 'Make sure image is moved successfully.'); - - // Check if derivative image has been flushed. - $this->assertFalse(file_exists($derivative_uri), 'Make sure derivative image has been flushed.'); - } - -} diff -r e200cb7efeb3 -r c2387f117808 core/modules/image/src/Tests/ImageAdminStylesTest.php --- a/core/modules/image/src/Tests/ImageAdminStylesTest.php Thu Apr 26 11:26:54 2018 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,541 +0,0 @@ -drupalGetTestFiles('image'); - $file = reset($files); - $file_path = file_unmanaged_copy($file->uri); - } - - return $style->buildUrl($file_path) ? $file_path : FALSE; - } - - /** - * Count the number of images currently create for a style. - */ - public function getImageCount(ImageStyleInterface $style) { - return count(file_scan_directory('public://styles/' . $style->id(), '/.*/')); - } - - /** - * Test creating an image style with a numeric name and ensuring it can be - * applied to an image. - */ - public function testNumericStyleName() { - $style_name = rand(); - $style_label = $this->randomString(); - $edit = [ - 'name' => $style_name, - 'label' => $style_label, - ]; - $this->drupalPostForm('admin/config/media/image-styles/add', $edit, t('Create new style')); - $this->assertRaw(t('Style %name was created.', ['%name' => $style_label])); - $options = image_style_options(); - $this->assertTrue(array_key_exists($style_name, $options), format_string('Array key %key exists.', ['%key' => $style_name])); - } - - /** - * General test to add a style, add/remove/edit effects to it, then delete it. - */ - public function testStyle() { - $admin_path = 'admin/config/media/image-styles'; - - // Setup a style to be created and effects to add to it. - $style_name = strtolower($this->randomMachineName(10)); - $style_label = $this->randomString(); - $style_path = $admin_path . '/manage/' . $style_name; - $effect_edits = [ - 'image_resize' => [ - 'width' => 100, - 'height' => 101, - ], - 'image_scale' => [ - 'width' => 110, - 'height' => 111, - 'upscale' => 1, - ], - 'image_scale_and_crop' => [ - 'width' => 120, - 'height' => 121, - ], - 'image_crop' => [ - 'width' => 130, - 'height' => 131, - 'anchor' => 'left-top', - ], - 'image_desaturate' => [ - // No options for desaturate. - ], - 'image_rotate' => [ - 'degrees' => 5, - 'random' => 1, - 'bgcolor' => '#FFFF00', - ], - ]; - - // Add style form. - - $edit = [ - 'name' => $style_name, - 'label' => $style_label, - ]; - $this->drupalPostForm($admin_path . '/add', $edit, t('Create new style')); - $this->assertRaw(t('Style %name was created.', ['%name' => $style_label])); - - // Ensure that the expected entity operations are there. - $this->drupalGet($admin_path); - $this->assertLinkByHref($style_path); - $this->assertLinkByHref($style_path . '/flush'); - $this->assertLinkByHref($style_path . '/delete'); - - // Add effect form. - - // Add each sample effect to the style. - foreach ($effect_edits as $effect => $edit) { - $edit_data = []; - foreach ($edit as $field => $value) { - $edit_data['data[' . $field . ']'] = $value; - } - // Add the effect. - $this->drupalPostForm($style_path, ['new' => $effect], t('Add')); - if (!empty($edit)) { - $this->drupalPostForm(NULL, $edit_data, t('Add effect')); - } - } - - // Load the saved image style. - $style = ImageStyle::load($style_name); - - // Ensure that third party settings were added to the config entity. - // These are added by a hook_image_style_presave() implemented in - // image_module_test module. - $this->assertEqual('bar', $style->getThirdPartySetting('image_module_test', 'foo'), 'Third party settings were added to the image style.'); - - // Ensure that the image style URI matches our expected path. - $style_uri_path = $style->url(); - $this->assertTrue(strpos($style_uri_path, $style_path) !== FALSE, 'The image style URI is correct.'); - - // Confirm that all effects on the image style have settings that match - // what was saved. - $uuids = []; - foreach ($style->getEffects() as $uuid => $effect) { - // Store the uuid for later use. - $uuids[$effect->getPluginId()] = $uuid; - $effect_configuration = $effect->getConfiguration(); - foreach ($effect_edits[$effect->getPluginId()] as $field => $value) { - $this->assertEqual($value, $effect_configuration['data'][$field], SafeMarkup::format('The %field field in the %effect effect has the correct value of %value.', ['%field' => $field, '%effect' => $effect->getPluginId(), '%value' => $value])); - } - } - - // Assert that every effect was saved. - foreach (array_keys($effect_edits) as $effect_name) { - $this->assertTrue(isset($uuids[$effect_name]), format_string( - 'A %effect_name effect was saved with ID %uuid', - [ - '%effect_name' => $effect_name, - '%uuid' => $uuids[$effect_name], - ])); - } - - // Image style overview form (ordering and renaming). - - // Confirm the order of effects is maintained according to the order we - // added the fields. - $effect_edits_order = array_keys($effect_edits); - $order_correct = TRUE; - $index = 0; - foreach ($style->getEffects() as $effect) { - if ($effect_edits_order[$index] != $effect->getPluginId()) { - $order_correct = FALSE; - } - $index++; - } - $this->assertTrue($order_correct, 'The order of the effects is correctly set by default.'); - - // Test the style overview form. - // Change the name of the style and adjust the weights of effects. - $style_name = strtolower($this->randomMachineName(10)); - $style_label = $this->randomMachineName(); - $weight = count($effect_edits); - $edit = [ - 'name' => $style_name, - 'label' => $style_label, - ]; - foreach ($style->getEffects() as $uuid => $effect) { - $edit['effects[' . $uuid . '][weight]'] = $weight; - $weight--; - } - - // Create an image to make sure it gets flushed after saving. - $image_path = $this->createSampleImage($style); - $this->assertEqual($this->getImageCount($style), 1, format_string('Image style %style image %file successfully generated.', ['%style' => $style->label(), '%file' => $image_path])); - - $this->drupalPostForm($style_path, $edit, t('Update style')); - - // Note that after changing the style name, the style path is changed. - $style_path = 'admin/config/media/image-styles/manage/' . $style_name; - - // Check that the URL was updated. - $this->drupalGet($style_path); - $this->assertTitle(t('Edit style @name | Drupal', ['@name' => $style_label])); - $this->assertResponse(200, format_string('Image style %original renamed to %new', ['%original' => $style->id(), '%new' => $style_name])); - - // Check that the available image effects are properly sorted. - $option = $this->xpath('//select[@id=:id]//option', [':id' => 'edit-new--2']); - $this->assertTrue($option[1] == 'Ajax test', '"Ajax test" is the first selectable effect.'); - - // Check that the image was flushed after updating the style. - // This is especially important when renaming the style. Make sure that - // the old image directory has been deleted. - $this->assertEqual($this->getImageCount($style), 0, format_string('Image style %style was flushed after renaming the style and updating the order of effects.', ['%style' => $style->label()])); - - // Load the style by the new name with the new weights. - $style = ImageStyle::load($style_name); - - // Confirm the new style order was saved. - $effect_edits_order = array_reverse($effect_edits_order); - $order_correct = TRUE; - $index = 0; - foreach ($style->getEffects() as $effect) { - if ($effect_edits_order[$index] != $effect->getPluginId()) { - $order_correct = FALSE; - } - $index++; - } - $this->assertTrue($order_correct, 'The order of the effects is correctly set by default.'); - - // Image effect deletion form. - - // Create an image to make sure it gets flushed after deleting an effect. - $image_path = $this->createSampleImage($style); - $this->assertEqual($this->getImageCount($style), 1, format_string('Image style %style image %file successfully generated.', ['%style' => $style->label(), '%file' => $image_path])); - - // Delete the 'image_crop' effect from the style. - $this->drupalPostForm($style_path . '/effects/' . $uuids['image_crop'] . '/delete', [], t('Delete')); - // Confirm that the form submission was successful. - $this->assertResponse(200); - $image_crop_effect = $style->getEffect($uuids['image_crop']); - $this->assertRaw(t('The image effect %name has been deleted.', ['%name' => $image_crop_effect->label()])); - // Confirm that there is no longer a link to the effect. - $this->assertNoLinkByHref($style_path . '/effects/' . $uuids['image_crop'] . '/delete'); - // Refresh the image style information and verify that the effect was - // actually deleted. - $entity_type_manager = $this->container->get('entity_type.manager'); - $style = $entity_type_manager->getStorage('image_style')->loadUnchanged($style->id()); - $this->assertFalse($style->getEffects()->has($uuids['image_crop']), format_string( - 'Effect with ID %uuid no longer found on image style %style', - [ - '%uuid' => $uuids['image_crop'], - '%style' => $style->label(), - ])); - - // Additional test on Rotate effect, for transparent background. - $edit = [ - 'data[degrees]' => 5, - 'data[random]' => 0, - 'data[bgcolor]' => '', - ]; - $this->drupalPostForm($style_path, ['new' => 'image_rotate'], t('Add')); - $this->drupalPostForm(NULL, $edit, t('Add effect')); - $entity_type_manager = $this->container->get('entity_type.manager'); - $style = $entity_type_manager->getStorage('image_style')->loadUnchanged($style_name); - $this->assertEqual(count($style->getEffects()), 6, 'Rotate effect with transparent background was added.'); - - // Style deletion form. - - // Delete the style. - $this->drupalPostForm($style_path . '/delete', [], t('Delete')); - - // Confirm the style directory has been removed. - $directory = file_default_scheme() . '://styles/' . $style_name; - $this->assertFalse(is_dir($directory), format_string('Image style %style directory removed on style deletion.', ['%style' => $style->label()])); - - $this->assertFalse(ImageStyle::load($style_name), format_string('Image style %style successfully deleted.', ['%style' => $style->label()])); - - // Test empty text when there are no image styles. - - // Delete all image styles. - foreach (ImageStyle::loadMultiple() as $image_style) { - $image_style->delete(); - } - - // Confirm that the empty text is correct on the image styles page. - $this->drupalGet($admin_path); - $this->assertRaw(t('There are currently no styles. Add a new one.', [ - ':url' => \Drupal::url('image.style_add'), - ])); - - } - - /** - * Tests editing Ajax-enabled image effect forms. - */ - public function testAjaxEnabledEffectForm() { - $admin_path = 'admin/config/media/image-styles'; - - // Setup a style to be created and effects to add to it. - $style_name = strtolower($this->randomMachineName(10)); - $style_label = $this->randomString(); - $style_path = $admin_path . '/manage/' . $style_name; - $effect_edit = [ - 'data[test_parameter]' => 100, - ]; - - // Add style form. - $edit = [ - 'name' => $style_name, - 'label' => $style_label, - ]; - $this->drupalPostForm($admin_path . '/add', $edit, t('Create new style')); - $this->assertRaw(t('Style %name was created.', ['%name' => $style_label])); - - // Add two Ajax-enabled test effects. - $this->drupalPostForm($style_path, ['new' => 'image_module_test_ajax'], t('Add')); - $this->drupalPostForm(NULL, $effect_edit, t('Add effect')); - $this->drupalPostForm($style_path, ['new' => 'image_module_test_ajax'], t('Add')); - $this->drupalPostForm(NULL, $effect_edit, t('Add effect')); - - // Load the saved image style. - $style = ImageStyle::load($style_name); - - // Edit back the effects. - foreach ($style->getEffects() as $uuid => $effect) { - $effect_path = $admin_path . '/manage/' . $style_name . '/effects/' . $uuid; - $this->drupalGet($effect_path); - $this->drupalPostAjaxForm(NULL, $effect_edit, ['op' => t('Ajax refresh')]); - $this->drupalPostForm(NULL, $effect_edit, t('Update effect')); - } - - } - - /** - * Test deleting a style and choosing a replacement style. - */ - public function testStyleReplacement() { - // Create a new style. - $style_name = strtolower($this->randomMachineName(10)); - $style_label = $this->randomString(); - $style = ImageStyle::create(['name' => $style_name, 'label' => $style_label]); - $style->save(); - $style_path = 'admin/config/media/image-styles/manage/'; - - // Create an image field that uses the new style. - $field_name = strtolower($this->randomMachineName(10)); - $this->createImageField($field_name, 'article'); - entity_get_display('node', 'article', 'default') - ->setComponent($field_name, [ - 'type' => 'image', - 'settings' => ['image_style' => $style_name], - ]) - ->save(); - - // Create a new node with an image attached. - $test_image = current($this->drupalGetTestFiles('image')); - $nid = $this->uploadNodeImage($test_image, $field_name, 'article', $this->randomMachineName()); - $node = Node::load($nid); - - // Get node field original image URI. - $fid = $node->get($field_name)->target_id; - $original_uri = File::load($fid)->getFileUri(); - - // Test that image is displayed using newly created style. - $this->drupalGet('node/' . $nid); - $this->assertRaw(file_url_transform_relative($style->buildUrl($original_uri)), format_string('Image displayed using style @style.', ['@style' => $style_name])); - - // Rename the style and make sure the image field is updated. - $new_style_name = strtolower($this->randomMachineName(10)); - $new_style_label = $this->randomString(); - $edit = [ - 'name' => $new_style_name, - 'label' => $new_style_label, - ]; - $this->drupalPostForm($style_path . $style_name, $edit, t('Update style')); - $this->assertText(t('Changes to the style have been saved.'), format_string('Style %name was renamed to %new_name.', ['%name' => $style_name, '%new_name' => $new_style_name])); - $this->drupalGet('node/' . $nid); - - // Reload the image style using the new name. - $style = ImageStyle::load($new_style_name); - $this->assertRaw(file_url_transform_relative($style->buildUrl($original_uri)), 'Image displayed using style replacement style.'); - - // Delete the style and choose a replacement style. - $edit = [ - 'replacement' => 'thumbnail', - ]; - $this->drupalPostForm($style_path . $new_style_name . '/delete', $edit, t('Delete')); - $message = t('The image style %name has been deleted.', ['%name' => $new_style_label]); - $this->assertRaw($message); - - $replacement_style = ImageStyle::load('thumbnail'); - $this->drupalGet('node/' . $nid); - $this->assertRaw(file_url_transform_relative($replacement_style->buildUrl($original_uri)), 'Image displayed using style replacement style.'); - } - - /** - * Verifies that editing an image effect does not cause it to be duplicated. - */ - public function testEditEffect() { - // Add a scale effect. - $style_name = 'test_style_effect_edit'; - $this->drupalGet('admin/config/media/image-styles/add'); - $this->drupalPostForm(NULL, ['label' => 'Test style effect edit', 'name' => $style_name], t('Create new style')); - $this->drupalPostForm(NULL, ['new' => 'image_scale_and_crop'], t('Add')); - $this->drupalPostForm(NULL, ['data[width]' => '300', 'data[height]' => '200'], t('Add effect')); - $this->assertText(t('Scale and crop 300×200')); - - // There should normally be only one edit link on this page initially. - $this->clickLink(t('Edit')); - $this->drupalPostForm(NULL, ['data[width]' => '360', 'data[height]' => '240'], t('Update effect')); - $this->assertText(t('Scale and crop 360×240')); - - // Check that the previous effect is replaced. - $this->assertNoText(t('Scale and crop 300×200')); - - // Add another scale effect. - $this->drupalGet('admin/config/media/image-styles/add'); - $this->drupalPostForm(NULL, ['label' => 'Test style scale edit scale', 'name' => 'test_style_scale_edit_scale'], t('Create new style')); - $this->drupalPostForm(NULL, ['new' => 'image_scale'], t('Add')); - $this->drupalPostForm(NULL, ['data[width]' => '12', 'data[height]' => '19'], t('Add effect')); - - // Edit the scale effect that was just added. - $this->clickLink(t('Edit')); - $this->drupalPostForm(NULL, ['data[width]' => '24', 'data[height]' => '19'], t('Update effect')); - - // Add another scale effect and make sure both exist. Click through from - // the overview to make sure that it is possible to add new effect then. - $this->drupalGet('admin/config/media/image-styles'); - $rows = $this->xpath('//table/tbody/tr'); - $i = 0; - foreach ($rows as $row) { - if (((string) $row->td[0]) === 'Test style scale edit scale') { - $this->clickLink('Edit', $i); - break; - } - $i++; - } - $this->drupalPostForm(NULL, ['new' => 'image_scale'], t('Add')); - $this->drupalPostForm(NULL, ['data[width]' => '12', 'data[height]' => '19'], t('Add effect')); - $this->assertText(t('Scale 24×19')); - $this->assertText(t('Scale 12×19')); - - // Try to edit a nonexistent effect. - $uuid = $this->container->get('uuid'); - $this->drupalGet('admin/config/media/image-styles/manage/' . $style_name . '/effects/' . $uuid->generate()); - $this->assertResponse(404); - } - - /** - * Test flush user interface. - */ - public function testFlushUserInterface() { - $admin_path = 'admin/config/media/image-styles'; - - // Create a new style. - $style_name = strtolower($this->randomMachineName(10)); - $style = ImageStyle::create(['name' => $style_name, 'label' => $this->randomString()]); - $style->save(); - - // Create an image to make sure it gets flushed. - $files = $this->drupalGetTestFiles('image'); - $image_uri = $files[0]->uri; - $derivative_uri = $style->buildUri($image_uri); - $this->assertTrue($style->createDerivative($image_uri, $derivative_uri)); - $this->assertEqual($this->getImageCount($style), 1); - - // Go to image styles list page and check if the flush operation link - // exists. - $this->drupalGet($admin_path); - $flush_path = $admin_path . '/manage/' . $style_name . '/flush'; - $this->assertLinkByHref($flush_path); - - // Flush the image style derivatives using the user interface. - $this->drupalPostForm($flush_path, [], t('Flush')); - - // The derivative image file should have been deleted. - $this->assertEqual($this->getImageCount($style), 0); - } - - /** - * Tests image style configuration import that does a delete. - */ - public function testConfigImport() { - // Create a new style. - $style_name = strtolower($this->randomMachineName(10)); - $style_label = $this->randomString(); - $style = ImageStyle::create(['name' => $style_name, 'label' => $style_label]); - $style->save(); - - // Create an image field that uses the new style. - $field_name = strtolower($this->randomMachineName(10)); - $this->createImageField($field_name, 'article'); - entity_get_display('node', 'article', 'default') - ->setComponent($field_name, [ - 'type' => 'image', - 'settings' => ['image_style' => $style_name], - ]) - ->save(); - - // Create a new node with an image attached. - $test_image = current($this->drupalGetTestFiles('image')); - $nid = $this->uploadNodeImage($test_image, $field_name, 'article', $this->randomMachineName()); - $node = Node::load($nid); - - // Get node field original image URI. - $fid = $node->get($field_name)->target_id; - $original_uri = File::load($fid)->getFileUri(); - - // Test that image is displayed using newly created style. - $this->drupalGet('node/' . $nid); - $this->assertRaw(file_url_transform_relative($style->buildUrl($original_uri)), format_string('Image displayed using style @style.', ['@style' => $style_name])); - - // Copy config to sync, and delete the image style. - $sync = $this->container->get('config.storage.sync'); - $active = $this->container->get('config.storage'); - // Remove the image field from the display, to avoid a dependency error - // during import. - EntityViewDisplay::load('node.article.default') - ->removeComponent($field_name) - ->save(); - $this->copyConfig($active, $sync); - $sync->delete('image.style.' . $style_name); - $this->configImporter()->import(); - - $this->assertFalse(ImageStyle::load($style_name), 'Style deleted after config import.'); - $this->assertEqual($this->getImageCount($style), 0, 'Image style was flushed after being deleted by config import.'); - } - - /** - * Tests access for the image style listing. - */ - public function testImageStyleAccess() { - $style = ImageStyle::create(['name' => 'style_foo', 'label' => $this->randomString()]); - $style->save(); - - $this->drupalGet('admin/config/media/image-styles'); - $this->clickLink(t('Edit')); - $this->assertRaw(t('Select a new effect')); - } - -} diff -r e200cb7efeb3 -r c2387f117808 core/modules/image/src/Tests/ImageDimensionsTest.php --- a/core/modules/image/src/Tests/ImageDimensionsTest.php Thu Apr 26 11:26:54 2018 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,293 +0,0 @@ -container->get('image.factory'); - // Create a working copy of the file. - $files = $this->drupalGetTestFiles('image'); - $file = reset($files); - $original_uri = file_unmanaged_copy($file->uri, 'public://', FILE_EXISTS_RENAME); - - // Create a style. - /** @var $style \Drupal\image\ImageStyleInterface */ - $style = ImageStyle::create(['name' => 'test', 'label' => 'Test']); - $style->save(); - $generated_uri = 'public://styles/test/public/' . \Drupal::service('file_system')->basename($original_uri); - $url = file_url_transform_relative($style->buildUrl($original_uri)); - - $variables = [ - '#theme' => 'image_style', - '#style_name' => 'test', - '#uri' => $original_uri, - '#width' => 40, - '#height' => 20, - ]; - // Verify that the original image matches the hard-coded values. - $image_file = $image_factory->get($original_uri); - $this->assertEqual($image_file->getWidth(), $variables['#width']); - $this->assertEqual($image_file->getHeight(), $variables['#height']); - - // Scale an image that is wider than it is high. - $effect = [ - 'id' => 'image_scale', - 'data' => [ - 'width' => 120, - 'height' => 90, - 'upscale' => TRUE, - ], - 'weight' => 0, - ]; - - $style->addImageEffect($effect); - $style->save(); - $this->assertEqual($this->getImageTag($variables), ''); - $this->assertFalse(file_exists($generated_uri), 'Generated file does not exist.'); - $this->drupalGet($this->getAbsoluteUrl($url)); - $this->assertResponse(200, 'Image was generated at the URL.'); - $this->assertTrue(file_exists($generated_uri), 'Generated file does exist after we accessed it.'); - $image_file = $image_factory->get($generated_uri); - $this->assertEqual($image_file->getWidth(), 120); - $this->assertEqual($image_file->getHeight(), 60); - - // Rotate 90 degrees anticlockwise. - $effect = [ - 'id' => 'image_rotate', - 'data' => [ - 'degrees' => -90, - 'random' => FALSE, - ], - 'weight' => 1, - ]; - - $style->addImageEffect($effect); - $style->save(); - $this->assertEqual($this->getImageTag($variables), ''); - $this->assertFalse(file_exists($generated_uri), 'Generated file does not exist.'); - $this->drupalGet($this->getAbsoluteUrl($url)); - $this->assertResponse(200, 'Image was generated at the URL.'); - $this->assertTrue(file_exists($generated_uri), 'Generated file does exist after we accessed it.'); - $image_file = $image_factory->get($generated_uri); - $this->assertEqual($image_file->getWidth(), 60); - $this->assertEqual($image_file->getHeight(), 120); - - // Scale an image that is higher than it is wide (rotated by previous effect). - $effect = [ - 'id' => 'image_scale', - 'data' => [ - 'width' => 120, - 'height' => 90, - 'upscale' => TRUE, - ], - 'weight' => 2, - ]; - - $style->addImageEffect($effect); - $style->save(); - $this->assertEqual($this->getImageTag($variables), ''); - $this->assertFalse(file_exists($generated_uri), 'Generated file does not exist.'); - $this->drupalGet($this->getAbsoluteUrl($url)); - $this->assertResponse(200, 'Image was generated at the URL.'); - $this->assertTrue(file_exists($generated_uri), 'Generated file does exist after we accessed it.'); - $image_file = $image_factory->get($generated_uri); - $this->assertEqual($image_file->getWidth(), 45); - $this->assertEqual($image_file->getHeight(), 90); - - // Test upscale disabled. - $effect = [ - 'id' => 'image_scale', - 'data' => [ - 'width' => 400, - 'height' => 200, - 'upscale' => FALSE, - ], - 'weight' => 3, - ]; - - $style->addImageEffect($effect); - $style->save(); - $this->assertEqual($this->getImageTag($variables), ''); - $this->assertFalse(file_exists($generated_uri), 'Generated file does not exist.'); - $this->drupalGet($this->getAbsoluteUrl($url)); - $this->assertResponse(200, 'Image was generated at the URL.'); - $this->assertTrue(file_exists($generated_uri), 'Generated file does exist after we accessed it.'); - $image_file = $image_factory->get($generated_uri); - $this->assertEqual($image_file->getWidth(), 45); - $this->assertEqual($image_file->getHeight(), 90); - - // Add a desaturate effect. - $effect = [ - 'id' => 'image_desaturate', - 'data' => [], - 'weight' => 4, - ]; - - $style->addImageEffect($effect); - $style->save(); - $this->assertEqual($this->getImageTag($variables), ''); - $this->assertFalse(file_exists($generated_uri), 'Generated file does not exist.'); - $this->drupalGet($this->getAbsoluteUrl($url)); - $this->assertResponse(200, 'Image was generated at the URL.'); - $this->assertTrue(file_exists($generated_uri), 'Generated file does exist after we accessed it.'); - $image_file = $image_factory->get($generated_uri); - $this->assertEqual($image_file->getWidth(), 45); - $this->assertEqual($image_file->getHeight(), 90); - - // Add a random rotate effect. - $effect = [ - 'id' => 'image_rotate', - 'data' => [ - 'degrees' => 180, - 'random' => TRUE, - ], - 'weight' => 5, - ]; - - $style->addImageEffect($effect); - $style->save(); - $this->assertEqual($this->getImageTag($variables), ''); - $this->assertFalse(file_exists($generated_uri), 'Generated file does not exist.'); - $this->drupalGet($this->getAbsoluteUrl($url)); - $this->assertResponse(200, 'Image was generated at the URL.'); - $this->assertTrue(file_exists($generated_uri), 'Generated file does exist after we accessed it.'); - - // Add a crop effect. - $effect = [ - 'id' => 'image_crop', - 'data' => [ - 'width' => 30, - 'height' => 30, - 'anchor' => 'center-center', - ], - 'weight' => 6, - ]; - - $style->addImageEffect($effect); - $style->save(); - $this->assertEqual($this->getImageTag($variables), ''); - $this->assertFalse(file_exists($generated_uri), 'Generated file does not exist.'); - $this->drupalGet($this->getAbsoluteUrl($url)); - $this->assertResponse(200, 'Image was generated at the URL.'); - $this->assertTrue(file_exists($generated_uri), 'Generated file does exist after we accessed it.'); - $image_file = $image_factory->get($generated_uri); - $this->assertEqual($image_file->getWidth(), 30); - $this->assertEqual($image_file->getHeight(), 30); - - // Rotate to a non-multiple of 90 degrees. - $effect = [ - 'id' => 'image_rotate', - 'data' => [ - 'degrees' => 57, - 'random' => FALSE, - ], - 'weight' => 7, - ]; - - $effect_id = $style->addImageEffect($effect); - $style->save(); - // @todo Uncomment this once - // https://www.drupal.org/project/drupal/issues/2670966 is resolved. - // $this->assertEqual($this->getImageTag($variables), ''); - $this->assertFalse(file_exists($generated_uri), 'Generated file does not exist.'); - $this->drupalGet($this->getAbsoluteUrl($url)); - $this->assertResponse(200, 'Image was generated at the URL.'); - $this->assertTrue(file_exists($generated_uri), 'Generated file does exist after we accessed it.'); - $image_file = $image_factory->get($generated_uri); - // @todo Uncomment this once - // https://www.drupal.org/project/drupal/issues/2670966 is resolved. - // $this->assertEqual($image_file->getWidth(), 41); - // $this->assertEqual($image_file->getHeight(), 41); - - $effect_plugin = $style->getEffect($effect_id); - $style->deleteImageEffect($effect_plugin); - - // Ensure that an effect can unset dimensions. - $effect = [ - 'id' => 'image_module_test_null', - 'data' => [], - 'weight' => 8, - ]; - - $style->addImageEffect($effect); - $style->save(); - $this->assertEqual($this->getImageTag($variables), ''); - - // Test URI dependent image effect. - $style = ImageStyle::create(['name' => 'test_uri', 'label' => 'Test URI']); - $effect = [ - 'id' => 'image_module_test_uri_dependent', - 'data' => [], - 'weight' => 0, - ]; - $style->addImageEffect($effect); - $style->save(); - $variables = [ - '#theme' => 'image_style', - '#style_name' => 'test_uri', - '#uri' => $original_uri, - '#width' => 40, - '#height' => 20, - ]; - // PNG original image. Should be resized to 100x100. - $generated_uri = 'public://styles/test_uri/public/' . \Drupal::service('file_system')->basename($original_uri); - $url = file_url_transform_relative($style->buildUrl($original_uri)); - $this->assertEqual($this->getImageTag($variables), ''); - $this->assertFalse(file_exists($generated_uri), 'Generated file does not exist.'); - $this->drupalGet($this->getAbsoluteUrl($url)); - $this->assertResponse(200, 'Image was generated at the URL.'); - $this->assertTrue(file_exists($generated_uri), 'Generated file does exist after we accessed it.'); - $image_file = $image_factory->get($generated_uri); - $this->assertEqual($image_file->getWidth(), 100); - $this->assertEqual($image_file->getHeight(), 100); - // GIF original image. Should be resized to 50x50. - $file = $files[1]; - $original_uri = file_unmanaged_copy($file->uri, 'public://', FILE_EXISTS_RENAME); - $generated_uri = 'public://styles/test_uri/public/' . \Drupal::service('file_system')->basename($original_uri); - $url = file_url_transform_relative($style->buildUrl($original_uri)); - $variables['#uri'] = $original_uri; - $this->assertEqual($this->getImageTag($variables), ''); - $this->assertFalse(file_exists($generated_uri), 'Generated file does not exist.'); - $this->drupalGet($this->getAbsoluteUrl($url)); - $this->assertResponse(200, 'Image was generated at the URL.'); - $this->assertTrue(file_exists($generated_uri), 'Generated file does exist after we accessed it.'); - $image_file = $image_factory->get($generated_uri); - $this->assertEqual($image_file->getWidth(), 50); - $this->assertEqual($image_file->getHeight(), 50); - } - - /** - * Render an image style element. - * - * drupal_render() alters the passed $variables array by adding a new key - * '#printed' => TRUE. This prevents next call to re-render the element. We - * wrap drupal_render() in a helper protected method and pass each time a - * fresh array so that $variables won't get altered and the element is - * re-rendered each time. - */ - protected function getImageTag($variables) { - return str_replace("\n", NULL, \Drupal::service('renderer')->renderRoot($variables)); - } - -} diff -r e200cb7efeb3 -r c2387f117808 core/modules/image/src/Tests/ImageFieldDefaultImagesTest.php --- a/core/modules/image/src/Tests/ImageFieldDefaultImagesTest.php Thu Apr 26 11:26:54 2018 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,392 +0,0 @@ -container->get('entity.manager')->getStorage('node'); - // Create files to use as the default images. - $files = $this->drupalGetTestFiles('image'); - // Create 10 files so the default image fids are not a single value. - for ($i = 1; $i <= 10; $i++) { - $filename = $this->randomMachineName() . "$i"; - $desired_filepath = 'public://' . $filename; - file_unmanaged_copy($files[0]->uri, $desired_filepath, FILE_EXISTS_ERROR); - $file = File::create(['uri' => $desired_filepath, 'filename' => $filename, 'name' => $filename]); - $file->save(); - } - $default_images = []; - foreach (['field_storage', 'field', 'field2', 'field_storage_new', 'field_new', 'field_storage_private', 'field_private'] as $image_target) { - $file = File::create((array) array_pop($files)); - $file->save(); - $default_images[$image_target] = $file; - } - - // Create an image field storage and add a field to the article content - // type. - $field_name = strtolower($this->randomMachineName()); - $storage_settings['default_image'] = [ - 'uuid' => $default_images['field_storage']->uuid(), - 'alt' => '', - 'title' => '', - 'width' => 0, - 'height' => 0, - ]; - $field_settings['default_image'] = [ - 'uuid' => $default_images['field']->uuid(), - 'alt' => '', - 'title' => '', - 'width' => 0, - 'height' => 0, - ]; - $widget_settings = [ - 'preview_image_style' => 'medium', - ]; - $field = $this->createImageField($field_name, 'article', $storage_settings, $field_settings, $widget_settings); - - // The field default image id should be 2. - $this->assertEqual($field->getSetting('default_image')['uuid'], $default_images['field']->uuid()); - - // Also test \Drupal\field\Entity\FieldConfig::getSettings(). - $this->assertEqual($field->getSettings()['default_image']['uuid'], $default_images['field']->uuid()); - - $field_storage = $field->getFieldStorageDefinition(); - - // The field storage default image id should be 1. - $this->assertEqual($field_storage->getSetting('default_image')['uuid'], $default_images['field_storage']->uuid()); - - // Also test \Drupal\field\Entity\FieldStorageConfig::getSettings(). - $this->assertEqual($field_storage->getSettings()['default_image']['uuid'], $default_images['field_storage']->uuid()); - - // Add another field with another default image to the page content type. - $field2 = FieldConfig::create([ - 'field_storage' => $field_storage, - 'bundle' => 'page', - 'label' => $field->label(), - 'required' => $field->isRequired(), - 'settings' => [ - 'default_image' => [ - 'uuid' => $default_images['field2']->uuid(), - 'alt' => '', - 'title' => '', - 'width' => 0, - 'height' => 0, - ], - ], - ]); - $field2->save(); - - $widget_settings = entity_get_form_display('node', $field->getTargetBundle(), 'default')->getComponent($field_name); - entity_get_form_display('node', 'page', 'default') - ->setComponent($field_name, $widget_settings) - ->save(); - entity_get_display('node', 'page', 'default') - ->setComponent($field_name) - ->save(); - - // Confirm the defaults are present on the article field storage settings - // form. - $field_id = $field->id(); - $this->drupalGet("admin/structure/types/manage/article/fields/$field_id/storage"); - $this->assertFieldByXpath( - '//input[@name="settings[default_image][uuid][fids]"]', - $default_images['field_storage']->id(), - format_string( - 'Article image field storage default equals expected file ID of @fid.', - ['@fid' => $default_images['field_storage']->id()] - ) - ); - // Confirm the defaults are present on the article field edit form. - $this->drupalGet("admin/structure/types/manage/article/fields/$field_id"); - $this->assertFieldByXpath( - '//input[@name="settings[default_image][uuid][fids]"]', - $default_images['field']->id(), - format_string( - 'Article image field default equals expected file ID of @fid.', - ['@fid' => $default_images['field']->id()] - ) - ); - - // Confirm the defaults are present on the page field storage settings form. - $this->drupalGet("admin/structure/types/manage/page/fields/$field_id/storage"); - $this->assertFieldByXpath( - '//input[@name="settings[default_image][uuid][fids]"]', - $default_images['field_storage']->id(), - format_string( - 'Page image field storage default equals expected file ID of @fid.', - ['@fid' => $default_images['field_storage']->id()] - ) - ); - // Confirm the defaults are present on the page field edit form. - $field2_id = $field2->id(); - $this->drupalGet("admin/structure/types/manage/page/fields/$field2_id"); - $this->assertFieldByXpath( - '//input[@name="settings[default_image][uuid][fids]"]', - $default_images['field2']->id(), - format_string( - 'Page image field default equals expected file ID of @fid.', - ['@fid' => $default_images['field2']->id()] - ) - ); - - // Confirm that the image default is shown for a new article node. - $article = $this->drupalCreateNode(['type' => 'article']); - $article_built = $this->drupalBuildEntityView($article); - $this->assertEqual( - $article_built[$field_name][0]['#item']->target_id, - $default_images['field']->id(), - format_string( - 'A new article node without an image has the expected default image file ID of @fid.', - ['@fid' => $default_images['field']->id()] - ) - ); - - // Also check that the field renders without warnings when the label is - // hidden. - EntityViewDisplay::load('node.article.default') - ->setComponent($field_name, ['label' => 'hidden', 'type' => 'image']) - ->save(); - $this->drupalGet('node/' . $article->id()); - - // Confirm that the image default is shown for a new page node. - $page = $this->drupalCreateNode(['type' => 'page']); - $page_built = $this->drupalBuildEntityView($page); - $this->assertEqual( - $page_built[$field_name][0]['#item']->target_id, - $default_images['field2']->id(), - format_string( - 'A new page node without an image has the expected default image file ID of @fid.', - ['@fid' => $default_images['field2']->id()] - ) - ); - - // Upload a new default for the field storage. - $default_image_settings = $field_storage->getSetting('default_image'); - $default_image_settings['uuid'] = $default_images['field_storage_new']->uuid(); - $field_storage->setSetting('default_image', $default_image_settings); - $field_storage->save(); - - // Confirm that the new default is used on the article field storage - // settings form. - $this->drupalGet("admin/structure/types/manage/article/fields/$field_id/storage"); - $this->assertFieldByXpath( - '//input[@name="settings[default_image][uuid][fids]"]', - $default_images['field_storage_new']->id(), - format_string( - 'Updated image field storage default equals expected file ID of @fid.', - ['@fid' => $default_images['field_storage_new']->id()] - ) - ); - - // Reload the nodes and confirm the field defaults are used. - $node_storage->resetCache([$article->id(), $page->id()]); - $article_built = $this->drupalBuildEntityView($article = $node_storage->load($article->id())); - $page_built = $this->drupalBuildEntityView($page = $node_storage->load($page->id())); - $this->assertEqual( - $article_built[$field_name][0]['#item']->target_id, - $default_images['field']->id(), - format_string( - 'An existing article node without an image has the expected default image file ID of @fid.', - ['@fid' => $default_images['field']->id()] - ) - ); - $this->assertEqual( - $page_built[$field_name][0]['#item']->target_id, - $default_images['field2']->id(), - format_string( - 'An existing page node without an image has the expected default image file ID of @fid.', - ['@fid' => $default_images['field2']->id()] - ) - ); - - // Upload a new default for the article's field. - $default_image_settings = $field->getSetting('default_image'); - $default_image_settings['uuid'] = $default_images['field_new']->uuid(); - $field->setSetting('default_image', $default_image_settings); - $field->save(); - - // Confirm the new field default is used on the article field admin form. - $this->drupalGet("admin/structure/types/manage/article/fields/$field_id"); - $this->assertFieldByXpath( - '//input[@name="settings[default_image][uuid][fids]"]', - $default_images['field_new']->id(), - format_string( - 'Updated article image field default equals expected file ID of @fid.', - ['@fid' => $default_images['field_new']->id()] - ) - ); - - // Reload the nodes. - $node_storage->resetCache([$article->id(), $page->id()]); - $article_built = $this->drupalBuildEntityView($article = $node_storage->load($article->id())); - $page_built = $this->drupalBuildEntityView($page = $node_storage->load($page->id())); - - // Confirm the article uses the new default. - $this->assertEqual( - $article_built[$field_name][0]['#item']->target_id, - $default_images['field_new']->id(), - format_string( - 'An existing article node without an image has the expected default image file ID of @fid.', - ['@fid' => $default_images['field_new']->id()] - ) - ); - // Confirm the page remains unchanged. - $this->assertEqual( - $page_built[$field_name][0]['#item']->target_id, - $default_images['field2']->id(), - format_string( - 'An existing page node without an image has the expected default image file ID of @fid.', - ['@fid' => $default_images['field2']->id()] - ) - ); - - // Confirm the default image is shown on the node form. - $file = File::load($default_images['field_new']->id()); - $this->drupalGet('node/add/article'); - $this->assertRaw($file->getFilename()); - - // Remove the field default from articles. - $default_image_settings = $field->getSetting('default_image'); - $default_image_settings['uuid'] = 0; - $field->setSetting('default_image', $default_image_settings); - $field->save(); - - // Confirm the article field default has been removed. - $this->drupalGet("admin/structure/types/manage/article/fields/$field_id"); - $this->assertFieldByXpath( - '//input[@name="settings[default_image][uuid][fids]"]', - '', - 'Updated article image field default has been successfully removed.' - ); - - // Reload the nodes. - $node_storage->resetCache([$article->id(), $page->id()]); - $article_built = $this->drupalBuildEntityView($article = $node_storage->load($article->id())); - $page_built = $this->drupalBuildEntityView($page = $node_storage->load($page->id())); - // Confirm the article uses the new field storage (not field) default. - $this->assertEqual( - $article_built[$field_name][0]['#item']->target_id, - $default_images['field_storage_new']->id(), - format_string( - 'An existing article node without an image has the expected default image file ID of @fid.', - ['@fid' => $default_images['field_storage_new']->id()] - ) - ); - // Confirm the page remains unchanged. - $this->assertEqual( - $page_built[$field_name][0]['#item']->target_id, - $default_images['field2']->id(), - format_string( - 'An existing page node without an image has the expected default image file ID of @fid.', - ['@fid' => $default_images['field2']->id()] - ) - ); - - $non_image = $this->drupalGetTestFiles('text'); - $this->drupalPostForm(NULL, ['files[settings_default_image_uuid]' => \Drupal::service('file_system')->realpath($non_image[0]->uri)], t("Upload")); - $this->assertText('The specified file text-0.txt could not be uploaded.'); - $this->assertText('Only files with the following extensions are allowed: png gif jpg jpeg.'); - - // Confirm the default image is shown on the node form. - $file = File::load($default_images['field_storage_new']->id()); - $this->drupalGet('node/add/article'); - $this->assertRaw($file->getFilename()); - - // Change the default image for the field storage and also change the upload - // destination to the private filesystem at the same time. - $default_image_settings = $field_storage->getSetting('default_image'); - $default_image_settings['uuid'] = $default_images['field_storage_private']->uuid(); - $field_storage->setSetting('default_image', $default_image_settings); - $field_storage->setSetting('uri_scheme', 'private'); - $field_storage->save(); - - // Confirm that the new default is used on the article field storage - // settings form. - $this->drupalGet("admin/structure/types/manage/article/fields/$field_id/storage"); - $this->assertFieldByXpath( - '//input[@name="settings[default_image][uuid][fids]"]', - $default_images['field_storage_private']->id(), - format_string( - 'Updated image field storage default equals expected file ID of @fid.', - ['@fid' => $default_images['field_storage_private']->id()] - ) - ); - - // Upload a new default for the article's field after setting the field - // storage upload destination to 'private'. - $default_image_settings = $field->getSetting('default_image'); - $default_image_settings['uuid'] = $default_images['field_private']->uuid(); - $field->setSetting('default_image', $default_image_settings); - $field->save(); - - // Confirm the new field field default is used on the article field - // admin form. - $this->drupalGet("admin/structure/types/manage/article/fields/$field_id"); - $this->assertFieldByXpath( - '//input[@name="settings[default_image][uuid][fids]"]', - $default_images['field_private']->id(), - format_string( - 'Updated article image field default equals expected file ID of @fid.', - ['@fid' => $default_images['field_private']->id()] - ) - ); - } - - /** - * Tests image field and field storage having an invalid default image. - */ - public function testInvalidDefaultImage() { - $field_storage = FieldStorageConfig::create([ - 'field_name' => Unicode::strtolower($this->randomMachineName()), - 'entity_type' => 'node', - 'type' => 'image', - 'settings' => [ - 'default_image' => [ - 'uuid' => 100000, - ] - ], - ]); - $field_storage->save(); - $settings = $field_storage->getSettings(); - // The non-existent default image should not be saved. - $this->assertNull($settings['default_image']['uuid']); - - $field = FieldConfig::create([ - 'field_storage' => $field_storage, - 'bundle' => 'page', - 'label' => $this->randomMachineName(), - 'settings' => [ - 'default_image' => [ - 'uuid' => 100000, - ] - ], - ]); - $field->save(); - $settings = $field->getSettings(); - // The non-existent default image should not be saved. - $this->assertNull($settings['default_image']['uuid']); - } - -} diff -r e200cb7efeb3 -r c2387f117808 core/modules/image/src/Tests/ImageFieldDisplayTest.php --- a/core/modules/image/src/Tests/ImageFieldDisplayTest.php Thu Apr 26 11:26:54 2018 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,461 +0,0 @@ -_testImageFieldFormatters('public'); - } - - /** - * Test image formatters on node display for private files. - */ - public function testImageFieldFormattersPrivate() { - // Remove access content permission from anonymous users. - user_role_change_permissions(RoleInterface::ANONYMOUS_ID, ['access content' => FALSE]); - $this->_testImageFieldFormatters('private'); - } - - /** - * Test image formatters on node display. - */ - public function _testImageFieldFormatters($scheme) { - /** @var \Drupal\Core\Render\RendererInterface $renderer */ - $renderer = $this->container->get('renderer'); - $node_storage = $this->container->get('entity.manager')->getStorage('node'); - $field_name = strtolower($this->randomMachineName()); - $field_settings = ['alt_field_required' => 0]; - $instance = $this->createImageField($field_name, 'article', ['uri_scheme' => $scheme], $field_settings); - - // Go to manage display page. - $this->drupalGet("admin/structure/types/manage/article/display"); - - // Test for existence of link to image styles configuration. - $this->drupalPostAjaxForm(NULL, [], "{$field_name}_settings_edit"); - $this->assertLinkByHref(\Drupal::url('entity.image_style.collection'), 0, 'Link to image styles configuration is found'); - - // Remove 'administer image styles' permission from testing admin user. - $admin_user_roles = $this->adminUser->getRoles(TRUE); - user_role_change_permissions(reset($admin_user_roles), ['administer image styles' => FALSE]); - - // Go to manage display page again. - $this->drupalGet("admin/structure/types/manage/article/display"); - - // Test for absence of link to image styles configuration. - $this->drupalPostAjaxForm(NULL, [], "{$field_name}_settings_edit"); - $this->assertNoLinkByHref(\Drupal::url('entity.image_style.collection'), 'Link to image styles configuration is absent when permissions are insufficient'); - - // Restore 'administer image styles' permission to testing admin user - user_role_change_permissions(reset($admin_user_roles), ['administer image styles' => TRUE]); - - // Create a new node with an image attached. - $test_image = current($this->drupalGetTestFiles('image')); - - // Ensure that preview works. - $this->previewNodeImage($test_image, $field_name, 'article'); - - // After previewing, make the alt field required. It cannot be required - // during preview because the form validation will fail. - $instance->setSetting('alt_field_required', 1); - $instance->save(); - - // Create alt text for the image. - $alt = $this->randomMachineName(); - - // Save node. - $nid = $this->uploadNodeImage($test_image, $field_name, 'article', $alt); - $node_storage->resetCache([$nid]); - $node = $node_storage->load($nid); - - // Test that the default formatter is being used. - $file = $node->{$field_name}->entity; - $image_uri = $file->getFileUri(); - $image = [ - '#theme' => 'image', - '#uri' => $image_uri, - '#width' => 40, - '#height' => 20, - '#alt' => $alt, - ]; - $default_output = str_replace("\n", NULL, $renderer->renderRoot($image)); - $this->assertRaw($default_output, 'Default formatter displaying correctly on full node view.'); - - // Test the image linked to file formatter. - $display_options = [ - 'type' => 'image', - 'settings' => ['image_link' => 'file'], - ]; - $display = entity_get_display('node', $node->getType(), 'default'); - $display->setComponent($field_name, $display_options) - ->save(); - - $image = [ - '#theme' => 'image', - '#uri' => $image_uri, - '#width' => 40, - '#height' => 20, - '#alt' => $alt, - ]; - $default_output = '' . $renderer->renderRoot($image) . ''; - $this->drupalGet('node/' . $nid); - $this->assertCacheTag($file->getCacheTags()[0]); - // @todo Remove in https://www.drupal.org/node/2646744. - $this->assertCacheContext('url.site'); - $cache_tags_header = $this->drupalGetHeader('X-Drupal-Cache-Tags'); - $this->assertTrue(!preg_match('/ image_style\:/', $cache_tags_header), 'No image style cache tag found.'); - $this->assertRaw($default_output, 'Image linked to file formatter displaying correctly on full node view.'); - // Verify that the image can be downloaded. - $this->assertEqual(file_get_contents($test_image->uri), $this->drupalGet(file_create_url($image_uri)), 'File was downloaded successfully.'); - if ($scheme == 'private') { - // Only verify HTTP headers when using private scheme and the headers are - // sent by Drupal. - $this->assertEqual($this->drupalGetHeader('Content-Type'), 'image/png', 'Content-Type header was sent.'); - $this->assertTrue(strstr($this->drupalGetHeader('Cache-Control'), 'private') !== FALSE, 'Cache-Control header was sent.'); - - // Log out and try to access the file. - $this->drupalLogout(); - $this->drupalGet(file_create_url($image_uri)); - $this->assertResponse('403', 'Access denied to original image as anonymous user.'); - - // Log in again. - $this->drupalLogin($this->adminUser); - } - - // Test the image linked to content formatter. - $display_options['settings']['image_link'] = 'content'; - $display->setComponent($field_name, $display_options) - ->save(); - $image = [ - '#theme' => 'image', - '#uri' => $image_uri, - '#width' => 40, - '#height' => 20, - ]; - $this->drupalGet('node/' . $nid); - $this->assertCacheTag($file->getCacheTags()[0]); - $cache_tags_header = $this->drupalGetHeader('X-Drupal-Cache-Tags'); - $this->assertTrue(!preg_match('/ image_style\:/', $cache_tags_header), 'No image style cache tag found.'); - $elements = $this->xpath( - '//a[@href=:path]/img[@src=:url and @alt=:alt and @width=:width and @height=:height]', - [ - ':path' => $node->url(), - ':url' => file_url_transform_relative(file_create_url($image['#uri'])), - ':width' => $image['#width'], - ':height' => $image['#height'], - ':alt' => $alt, - ] - ); - $this->assertEqual(count($elements), 1, 'Image linked to content formatter displaying correctly on full node view.'); - - // Test the image style 'thumbnail' formatter. - $display_options['settings']['image_link'] = ''; - $display_options['settings']['image_style'] = 'thumbnail'; - $display->setComponent($field_name, $display_options) - ->save(); - - // Ensure the derivative image is generated so we do not have to deal with - // image style callback paths. - $this->drupalGet(ImageStyle::load('thumbnail')->buildUrl($image_uri)); - $image_style = [ - '#theme' => 'image_style', - '#uri' => $image_uri, - '#width' => 40, - '#height' => 20, - '#style_name' => 'thumbnail', - '#alt' => $alt, - ]; - $default_output = $renderer->renderRoot($image_style); - $this->drupalGet('node/' . $nid); - $image_style = ImageStyle::load('thumbnail'); - $this->assertCacheTag($image_style->getCacheTags()[0]); - $this->assertRaw($default_output, 'Image style thumbnail formatter displaying correctly on full node view.'); - - if ($scheme == 'private') { - // Log out and try to access the file. - $this->drupalLogout(); - $this->drupalGet(ImageStyle::load('thumbnail')->buildUrl($image_uri)); - $this->assertResponse('403', 'Access denied to image style thumbnail as anonymous user.'); - } - - // Test the image URL formatter without an image style. - $display_options = [ - 'type' => 'image_url', - 'settings' => ['image_style' => ''], - ]; - $expected_url = file_url_transform_relative(file_create_url($image_uri)); - $this->assertEqual($expected_url, $node->{$field_name}->view($display_options)[0]['#markup']); - - // Test the image URL formatter with an image style. - $display_options['settings']['image_style'] = 'thumbnail'; - $expected_url = file_url_transform_relative(ImageStyle::load('thumbnail')->buildUrl($image_uri)); - $this->assertEqual($expected_url, $node->{$field_name}->view($display_options)[0]['#markup']); - } - - /** - * Tests for image field settings. - */ - public function testImageFieldSettings() { - /** @var \Drupal\Core\Render\RendererInterface $renderer */ - $renderer = $this->container->get('renderer'); - $node_storage = $this->container->get('entity.manager')->getStorage('node'); - $test_image = current($this->drupalGetTestFiles('image')); - list(, $test_image_extension) = explode('.', $test_image->filename); - $field_name = strtolower($this->randomMachineName()); - $field_settings = [ - 'alt_field' => 1, - 'file_extensions' => $test_image_extension, - 'max_filesize' => '50 KB', - 'max_resolution' => '100x100', - 'min_resolution' => '10x10', - 'title_field' => 1, - ]; - $widget_settings = [ - 'preview_image_style' => 'medium', - ]; - $field = $this->createImageField($field_name, 'article', [], $field_settings, $widget_settings); - - // Verify that the min/max resolution set on the field are properly - // extracted, and displayed, on the image field's configuration form. - $this->drupalGet('admin/structure/types/manage/article/fields/' . $field->id()); - $this->assertFieldByName('settings[max_resolution][x]', '100', 'Expected max resolution X value of 100.'); - $this->assertFieldByName('settings[max_resolution][y]', '100', 'Expected max resolution Y value of 100.'); - $this->assertFieldByName('settings[min_resolution][x]', '10', 'Expected min resolution X value of 10.'); - $this->assertFieldByName('settings[min_resolution][y]', '10', 'Expected min resolution Y value of 10.'); - - $this->drupalGet('node/add/article'); - $this->assertText(t('50 KB limit.'), 'Image widget max file size is displayed on article form.'); - $this->assertText(t('Allowed types: @extensions.', ['@extensions' => $test_image_extension]), 'Image widget allowed file types displayed on article form.'); - $this->assertText(t('Images must be larger than 10x10 pixels. Images larger than 100x100 pixels will be resized.'), 'Image widget allowed resolution displayed on article form.'); - - // We have to create the article first and then edit it because the alt - // and title fields do not display until the image has been attached. - - // Create alt text for the image. - $alt = $this->randomMachineName(); - - $nid = $this->uploadNodeImage($test_image, $field_name, 'article', $alt); - $this->drupalGet('node/' . $nid . '/edit'); - $this->assertFieldByName($field_name . '[0][alt]', '', 'Alt field displayed on article form.'); - $this->assertFieldByName($field_name . '[0][title]', '', 'Title field displayed on article form.'); - // Verify that the attached image is being previewed using the 'medium' - // style. - $node_storage->resetCache([$nid]); - $node = $node_storage->load($nid); - $file = $node->{$field_name}->entity; - - $url = file_url_transform_relative(file_create_url(ImageStyle::load('medium')->buildUrl($file->getFileUri()))); - $this->assertTrue($this->cssSelect('img[width=40][height=20][class=image-style-medium][src="' . $url . '"]')); - - // Add alt/title fields to the image and verify that they are displayed. - $image = [ - '#theme' => 'image', - '#uri' => $file->getFileUri(), - '#alt' => $alt, - '#title' => $this->randomMachineName(), - '#width' => 40, - '#height' => 20, - ]; - $edit = [ - $field_name . '[0][alt]' => $image['#alt'], - $field_name . '[0][title]' => $image['#title'], - ]; - $this->drupalPostForm('node/' . $nid . '/edit', $edit, t('Save')); - $default_output = str_replace("\n", NULL, $renderer->renderRoot($image)); - $this->assertRaw($default_output, 'Image displayed using user supplied alt and title attributes.'); - - // Verify that alt/title longer than allowed results in a validation error. - $test_size = 2000; - $edit = [ - $field_name . '[0][alt]' => $this->randomMachineName($test_size), - $field_name . '[0][title]' => $this->randomMachineName($test_size), - ]; - $this->drupalPostForm('node/' . $nid . '/edit', $edit, t('Save')); - $schema = $field->getFieldStorageDefinition()->getSchema(); - $this->assertRaw(t('Alternative text cannot be longer than %max characters but is currently %length characters long.', [ - '%max' => $schema['columns']['alt']['length'], - '%length' => $test_size, - ])); - $this->assertRaw(t('Title cannot be longer than %max characters but is currently %length characters long.', [ - '%max' => $schema['columns']['title']['length'], - '%length' => $test_size, - ])); - - // Set cardinality to unlimited and add upload a second image. - // The image widget is extending on the file widget, but the image field - // type does not have the 'display_field' setting which is expected by - // the file widget. This resulted in notices before when cardinality is not - // 1, so we need to make sure the file widget prevents these notices by - // providing all settings, even if they are not used. - // @see FileWidget::formMultipleElements(). - $this->drupalPostForm('admin/structure/types/manage/article/fields/node.article.' . $field_name . '/storage', ['cardinality' => FieldStorageDefinitionInterface::CARDINALITY_UNLIMITED], t('Save field settings')); - $edit = [ - 'files[' . $field_name . '_1][]' => \Drupal::service('file_system')->realpath($test_image->uri), - ]; - $this->drupalPostForm('node/' . $node->id() . '/edit', $edit, t('Save')); - // Add the required alt text. - $this->drupalPostForm(NULL, [$field_name . '[1][alt]' => $alt], t('Save')); - $this->assertText(format_string('Article @title has been updated.', ['@title' => $node->getTitle()])); - - // Assert ImageWidget::process() calls FieldWidget::process(). - $this->drupalGet('node/' . $node->id() . '/edit'); - $edit = [ - 'files[' . $field_name . '_2][]' => \Drupal::service('file_system')->realpath($test_image->uri), - ]; - $this->drupalPostAjaxForm(NULL, $edit, $field_name . '_2_upload_button'); - $this->assertNoRaw(''); - $this->assertRaw(''); - } - - /** - * Test use of a default image with an image field. - */ - public function testImageFieldDefaultImage() { - /** @var \Drupal\Core\Render\RendererInterface $renderer */ - $renderer = $this->container->get('renderer'); - - $node_storage = $this->container->get('entity.manager')->getStorage('node'); - // Create a new image field. - $field_name = strtolower($this->randomMachineName()); - $this->createImageField($field_name, 'article'); - - // Create a new node, with no images and verify that no images are - // displayed. - $node = $this->drupalCreateNode(['type' => 'article']); - $this->drupalGet('node/' . $node->id()); - // Verify that no image is displayed on the page by checking for the class - // that would be used on the image field. - $this->assertNoPattern('

    ', 'No image displayed when no image is attached and no default image specified.'); - $cache_tags_header = $this->drupalGetHeader('X-Drupal-Cache-Tags'); - $this->assertTrue(!preg_match('/ image_style\:/', $cache_tags_header), 'No image style cache tag found.'); - - // Add a default image to the public image field. - $images = $this->drupalGetTestFiles('image'); - $alt = $this->randomString(512); - $title = $this->randomString(1024); - $edit = [ - // Get the path of the 'image-test.png' file. - 'files[settings_default_image_uuid]' => \Drupal::service('file_system')->realpath($images[0]->uri), - 'settings[default_image][alt]' => $alt, - 'settings[default_image][title]' => $title, - ]; - $this->drupalPostForm("admin/structure/types/manage/article/fields/node.article.$field_name/storage", $edit, t('Save field settings')); - // Clear field definition cache so the new default image is detected. - \Drupal::entityManager()->clearCachedFieldDefinitions(); - $field_storage = FieldStorageConfig::loadByName('node', $field_name); - $default_image = $field_storage->getSetting('default_image'); - $file = \Drupal::entityManager()->loadEntityByUuid('file', $default_image['uuid']); - $this->assertTrue($file->isPermanent(), 'The default image status is permanent.'); - $image = [ - '#theme' => 'image', - '#uri' => $file->getFileUri(), - '#alt' => $alt, - '#title' => $title, - '#width' => 40, - '#height' => 20, - ]; - $default_output = str_replace("\n", NULL, $renderer->renderRoot($image)); - $this->drupalGet('node/' . $node->id()); - $this->assertCacheTag($file->getCacheTags()[0]); - $cache_tags_header = $this->drupalGetHeader('X-Drupal-Cache-Tags'); - $this->assertTrue(!preg_match('/ image_style\:/', $cache_tags_header), 'No image style cache tag found.'); - $this->assertRaw($default_output, 'Default image displayed when no user supplied image is present.'); - - // Create a node with an image attached and ensure that the default image - // is not displayed. - - // Create alt text for the image. - $alt = $this->randomMachineName(); - - // Upload the 'image-test.gif' file. - $nid = $this->uploadNodeImage($images[2], $field_name, 'article', $alt); - $node_storage->resetCache([$nid]); - $node = $node_storage->load($nid); - $file = $node->{$field_name}->entity; - $image = [ - '#theme' => 'image', - '#uri' => $file->getFileUri(), - '#width' => 40, - '#height' => 20, - '#alt' => $alt, - ]; - $image_output = str_replace("\n", NULL, $renderer->renderRoot($image)); - $this->drupalGet('node/' . $nid); - $this->assertCacheTag($file->getCacheTags()[0]); - $cache_tags_header = $this->drupalGetHeader('X-Drupal-Cache-Tags'); - $this->assertTrue(!preg_match('/ image_style\:/', $cache_tags_header), 'No image style cache tag found.'); - $this->assertNoRaw($default_output, 'Default image is not displayed when user supplied image is present.'); - $this->assertRaw($image_output, 'User supplied image is displayed.'); - - // Remove default image from the field and make sure it is no longer used. - $edit = [ - 'settings[default_image][uuid][fids]' => 0, - ]; - $this->drupalPostForm("admin/structure/types/manage/article/fields/node.article.$field_name/storage", $edit, t('Save field settings')); - // Clear field definition cache so the new default image is detected. - \Drupal::entityManager()->clearCachedFieldDefinitions(); - $field_storage = FieldStorageConfig::loadByName('node', $field_name); - $default_image = $field_storage->getSetting('default_image'); - $this->assertFalse($default_image['uuid'], 'Default image removed from field.'); - // Create an image field that uses the private:// scheme and test that the - // default image works as expected. - $private_field_name = strtolower($this->randomMachineName()); - $this->createImageField($private_field_name, 'article', ['uri_scheme' => 'private']); - // Add a default image to the new field. - $edit = [ - // Get the path of the 'image-test.gif' file. - 'files[settings_default_image_uuid]' => \Drupal::service('file_system')->realpath($images[2]->uri), - 'settings[default_image][alt]' => $alt, - 'settings[default_image][title]' => $title, - ]; - $this->drupalPostForm('admin/structure/types/manage/article/fields/node.article.' . $private_field_name . '/storage', $edit, t('Save field settings')); - // Clear field definition cache so the new default image is detected. - \Drupal::entityManager()->clearCachedFieldDefinitions(); - - $private_field_storage = FieldStorageConfig::loadByName('node', $private_field_name); - $default_image = $private_field_storage->getSetting('default_image'); - $file = \Drupal::entityManager()->loadEntityByUuid('file', $default_image['uuid']); - $this->assertEqual('private', file_uri_scheme($file->getFileUri()), 'Default image uses private:// scheme.'); - $this->assertTrue($file->isPermanent(), 'The default image status is permanent.'); - // Create a new node with no image attached and ensure that default private - // image is displayed. - $node = $this->drupalCreateNode(['type' => 'article']); - $image = [ - '#theme' => 'image', - '#uri' => $file->getFileUri(), - '#alt' => $alt, - '#title' => $title, - '#width' => 40, - '#height' => 20, - ]; - $default_output = str_replace("\n", NULL, $renderer->renderRoot($image)); - $this->drupalGet('node/' . $node->id()); - $this->assertCacheTag($file->getCacheTags()[0]); - $cache_tags_header = $this->drupalGetHeader('X-Drupal-Cache-Tags'); - $this->assertTrue(!preg_match('/ image_style\:/', $cache_tags_header), 'No image style cache tag found.'); - $this->assertRaw($default_output, 'Default private image displayed when no user supplied image is present.'); - } - -} diff -r e200cb7efeb3 -r c2387f117808 core/modules/image/src/Tests/ImageFieldTestBase.php --- a/core/modules/image/src/Tests/ImageFieldTestBase.php Thu Apr 26 11:26:54 2018 +0100 +++ b/core/modules/image/src/Tests/ImageFieldTestBase.php Tue Jul 10 15:07:59 2018 +0100 @@ -2,6 +2,8 @@ namespace Drupal\image\Tests; +@trigger_error('The ' . __NAMESPACE__ . '\ImageFieldTestBase class is deprecated in Drupal 8.5.x and will be removed before Drupal 9.0.0. Use \Drupal\Tests\image\Functional\ImageFieldTestBase instead. See https://www.drupal.org/node/2863626.', E_USER_DEPRECATED); + use Drupal\Tests\image\Kernel\ImageFieldCreationTrait; use Drupal\simpletest\WebTestBase; diff -r e200cb7efeb3 -r c2387f117808 core/modules/image/src/Tests/ImageFieldValidateTest.php --- a/core/modules/image/src/Tests/ImageFieldValidateTest.php Thu Apr 26 11:26:54 2018 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,288 +0,0 @@ -container->get('file_system'); - $image_files = $this->drupalGetTestFiles('image'); - - $field_name = strtolower($this->randomMachineName()); - $this->createImageField($field_name, 'article', [], ['file_directory' => 'test-upload']); - $expected_path = 'public://test-upload'; - - // Create alt text for the image. - $alt = $this->randomMachineName(); - - // Create a node with a valid image. - $node = $this->uploadNodeImage($image_files[0], $field_name, 'article', $alt); - $this->assertTrue(file_exists($expected_path . '/' . $image_files[0]->filename)); - - // Remove the image. - $this->drupalPostForm('node/' . $node . '/edit', [], t('Remove')); - $this->drupalPostForm(NULL, [], t('Save')); - - // Get invalid image test files from simpletest. - $files = file_scan_directory(drupal_get_path('module', 'simpletest') . '/files', '/invalid-img-.*/'); - $invalid_image_files = []; - foreach ($files as $file) { - $invalid_image_files[$file->filename] = $file; - } - - // Try uploading a zero-byte image. - $zero_size_image = $invalid_image_files['invalid-img-zero-size.png']; - $edit = [ - 'files[' . $field_name . '_0]' => $file_system->realpath($zero_size_image->uri), - ]; - $this->drupalPostForm('node/' . $node . '/edit', $edit, t('Upload')); - $this->assertFalse(file_exists($expected_path . '/' . $zero_size_image->filename)); - - // Try uploading an invalid image. - $invalid_image = $invalid_image_files['invalid-img-test.png']; - $edit = [ - 'files[' . $field_name . '_0]' => $file_system->realpath($invalid_image->uri), - ]; - $this->drupalPostForm('node/' . $node . '/edit', $edit, t('Upload')); - $this->assertFalse(file_exists($expected_path . '/' . $invalid_image->filename)); - - // Upload a valid image again. - $valid_image = $image_files[0]; - $edit = [ - 'files[' . $field_name . '_0]' => $file_system->realpath($valid_image->uri), - ]; - $this->drupalPostForm('node/' . $node . '/edit', $edit, t('Upload')); - $this->assertTrue(file_exists($expected_path . '/' . $valid_image->filename)); - } - - /** - * Test min/max resolution settings. - */ - public function testResolution() { - $field_names = [ - 0 => strtolower($this->randomMachineName()), - 1 => strtolower($this->randomMachineName()), - 2 => strtolower($this->randomMachineName()), - ]; - $min_resolution = [ - 'width' => 50, - 'height' => 50 - ]; - $max_resolution = [ - 'width' => 100, - 'height' => 100 - ]; - $no_height_min_resolution = [ - 'width' => 50, - 'height' => NULL - ]; - $no_height_max_resolution = [ - 'width' => 100, - 'height' => NULL - ]; - $no_width_min_resolution = [ - 'width' => NULL, - 'height' => 50 - ]; - $no_width_max_resolution = [ - 'width' => NULL, - 'height' => 100 - ]; - $field_settings = [ - 0 => $this->getFieldSettings($min_resolution, $max_resolution), - 1 => $this->getFieldSettings($no_height_min_resolution, $no_height_max_resolution), - 2 => $this->getFieldSettings($no_width_min_resolution, $no_width_max_resolution), - ]; - $this->createImageField($field_names[0], 'article', [], $field_settings[0]); - $this->createImageField($field_names[1], 'article', [], $field_settings[1]); - $this->createImageField($field_names[2], 'article', [], $field_settings[2]); - - // We want a test image that is too small, and a test image that is too - // big, so cycle through test image files until we have what we need. - $image_that_is_too_big = FALSE; - $image_that_is_too_small = FALSE; - $image_factory = $this->container->get('image.factory'); - foreach ($this->drupalGetTestFiles('image') as $image) { - $image_file = $image_factory->get($image->uri); - if ($image_file->getWidth() > $max_resolution['width']) { - $image_that_is_too_big = $image; - } - if ($image_file->getWidth() < $min_resolution['width']) { - $image_that_is_too_small = $image; - $image_that_is_too_small_file = $image_file; - } - if ($image_that_is_too_small && $image_that_is_too_big) { - break; - } - } - $this->uploadNodeImage($image_that_is_too_small, $field_names[0], 'article'); - $this->assertRaw(t('The specified file %name could not be uploaded.', ['%name' => $image_that_is_too_small->filename])); - $this->assertRaw(t('The image is too small. The minimum dimensions are %dimensions pixels and the image size is %widthx%height pixels.', [ - '%dimensions' => '50x50', - '%width' => $image_that_is_too_small_file->getWidth(), - '%height' => $image_that_is_too_small_file->getHeight(), - ])); - $this->uploadNodeImage($image_that_is_too_big, $field_names[0], 'article'); - $this->assertText(t('The image was resized to fit within the maximum allowed dimensions of 100x100 pixels.')); - $this->uploadNodeImage($image_that_is_too_small, $field_names[1], 'article'); - $this->assertRaw(t('The specified file %name could not be uploaded.', ['%name' => $image_that_is_too_small->filename])); - $this->uploadNodeImage($image_that_is_too_big, $field_names[1], 'article'); - $this->assertText(t('The image was resized to fit within the maximum allowed width of 100 pixels.')); - $this->uploadNodeImage($image_that_is_too_small, $field_names[2], 'article'); - $this->assertRaw(t('The specified file %name could not be uploaded.', ['%name' => $image_that_is_too_small->filename])); - $this->uploadNodeImage($image_that_is_too_big, $field_names[2], 'article'); - $this->assertText(t('The image was resized to fit within the maximum allowed height of 100 pixels.')); - } - - /** - * Test that required alt/title fields gets validated right. - */ - public function testRequiredAttributes() { - $field_name = strtolower($this->randomMachineName()); - $field_settings = [ - 'alt_field' => 1, - 'alt_field_required' => 1, - 'title_field' => 1, - 'title_field_required' => 1, - 'required' => 1, - ]; - $instance = $this->createImageField($field_name, 'article', [], $field_settings); - $images = $this->drupalGetTestFiles('image'); - // Let's just use the first image. - $image = $images[0]; - $this->uploadNodeImage($image, $field_name, 'article'); - - // Look for form-required for the alt text. - $elements = $this->xpath('//label[@for="edit-' . $field_name . '-0-alt" and @class="js-form-required form-required"]/following-sibling::input[@id="edit-' . $field_name . '-0-alt"]'); - - $this->assertTrue(isset($elements[0]), 'Required marker is shown for the required alt text.'); - - $elements = $this->xpath('//label[@for="edit-' . $field_name . '-0-title" and @class="js-form-required form-required"]/following-sibling::input[@id="edit-' . $field_name . '-0-title"]'); - - $this->assertTrue(isset($elements[0]), 'Required marker is shown for the required title text.'); - - $this->assertText(t('Alternative text field is required.')); - $this->assertText(t('Title field is required.')); - - $instance->setSetting('alt_field_required', 0); - $instance->setSetting('title_field_required', 0); - $instance->save(); - - $edit = [ - 'title[0][value]' => $this->randomMachineName(), - ]; - $this->drupalPostForm('node/add/article', $edit, t('Save')); - - $this->assertNoText(t('Alternative text field is required.')); - $this->assertNoText(t('Title field is required.')); - - $instance->setSetting('required', 0); - $instance->setSetting('alt_field_required', 1); - $instance->setSetting('title_field_required', 1); - $instance->save(); - - $edit = [ - 'title[0][value]' => $this->randomMachineName(), - ]; - $this->drupalPostForm('node/add/article', $edit, t('Save')); - - $this->assertNoText(t('Alternative text field is required.')); - $this->assertNoText(t('Title field is required.')); - } - - /** - * Returns field settings. - * - * @param int[] $min_resolution - * The minimum width and height resolution setting. - * @param int[] $max_resolution - * The maximum width and height resolution setting. - * - * @return array - */ - protected function getFieldSettings($min_resolution, $max_resolution) { - return [ - 'max_resolution' => $max_resolution['width'] . 'x' . $max_resolution['height'], - 'min_resolution' => $min_resolution['width'] . 'x' . $min_resolution['height'], - 'alt_field' => 0, - ]; - } - - /** - * Test the validation message is displayed only once for ajax uploads. - */ - public function testAJAXValidationMessage() { - $field_name = strtolower($this->randomMachineName()); - $this->createImageField($field_name, 'article', ['cardinality' => -1]); - - $this->drupalGet('node/add/article'); - /** @var \Drupal\file\FileInterface[] $text_files */ - $text_files = $this->drupalGetTestFiles('text'); - $text_file = reset($text_files); - $edit = [ - 'files[' . $field_name . '_0][]' => $this->container->get('file_system')->realpath($text_file->uri), - 'title[0][value]' => $this->randomMachineName(), - ]; - $this->drupalPostAjaxForm(NULL, $edit, $field_name . '_0_upload_button'); - $elements = $this->xpath('//div[contains(@class, :class)]', [ - ':class' => 'messages--error', - ]); - $this->assertEqual(count($elements), 1, 'Ajax validation messages are displayed once.'); - } - - /** - * Tests that image field validation works with other form submit handlers. - */ - public function testFriendlyAjaxValidation() { - // Add a custom field to the Article content type that contains an AJAX - // handler on a select field. - $field_storage = FieldStorageConfig::create([ - 'field_name' => 'field_dummy_select', - 'type' => 'image_module_test_dummy_ajax', - 'entity_type' => 'node', - 'cardinality' => 1, - ]); - $field_storage->save(); - - $field = FieldConfig::create([ - 'field_storage' => $field_storage, - 'entity_type' => 'node', - 'bundle' => 'article', - 'field_name' => 'field_dummy_select', - 'label' => t('Dummy select'), - ])->save(); - - \Drupal::entityTypeManager() - ->getStorage('entity_form_display') - ->load('node.article.default') - ->setComponent( - 'field_dummy_select', - [ - 'type' => 'image_module_test_dummy_ajax_widget', - 'weight' => 1, - ]) - ->save(); - - // Then, add an image field. - $this->createImageField('field_dummy_image', 'article'); - - // Open an article and trigger the AJAX handler. - $this->drupalGet('node/add/article'); - $edit = [ - 'field_dummy_select[select_widget]' => 'bam', - ]; - $this->drupalPostAjaxForm(NULL, $edit, 'field_dummy_select[select_widget]'); - } - -} diff -r e200cb7efeb3 -r c2387f117808 core/modules/image/src/Tests/ImageOnTranslatedEntityTest.php --- a/core/modules/image/src/Tests/ImageOnTranslatedEntityTest.php Thu Apr 26 11:26:54 2018 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,228 +0,0 @@ -config('file.settings')->set('make_unused_managed_files_temporary', TRUE)->save(); - - // Create the "Basic page" node type. - // @todo Remove the disabling of new revision creation in - // https://www.drupal.org/node/1239558. - $this->drupalCreateContentType(['type' => 'basicpage', 'name' => 'Basic page', 'new_revision' => FALSE]); - - // Create a image field on the "Basic page" node type. - $this->fieldName = strtolower($this->randomMachineName()); - $this->createImageField($this->fieldName, 'basicpage', [], ['title_field' => 1]); - - // Create and log in user. - $permissions = [ - 'access administration pages', - 'administer content translation', - 'administer content types', - 'administer languages', - 'administer node fields', - 'create content translations', - 'create basicpage content', - 'edit any basicpage content', - 'translate any entity', - 'delete any basicpage content', - ]; - $admin_user = $this->drupalCreateUser($permissions); - $this->drupalLogin($admin_user); - - // Add a second and third language. - $edit = []; - $edit['predefined_langcode'] = 'fr'; - $this->drupalPostForm('admin/config/regional/language/add', $edit, t('Add language')); - - $edit = []; - $edit['predefined_langcode'] = 'nl'; - $this->drupalPostForm('admin/config/regional/language/add', $edit, t('Add language')); - } - - /** - * Tests synced file fields on translated nodes. - */ - public function testSyncedImages() { - // Enable translation for "Basic page" nodes. - $edit = [ - 'entity_types[node]' => 1, - 'settings[node][basicpage][translatable]' => 1, - "settings[node][basicpage][fields][$this->fieldName]" => 1, - "settings[node][basicpage][columns][$this->fieldName][file]" => 1, - // Explicitly disable alt and title since the javascript disables the - // checkboxes on the form. - "settings[node][basicpage][columns][$this->fieldName][alt]" => FALSE, - "settings[node][basicpage][columns][$this->fieldName][title]" => FALSE, - ]; - $this->drupalPostForm('admin/config/regional/content-language', $edit, 'Save configuration'); - - // Verify that the image field on the "Basic basic" node type is - // translatable. - $definitions = \Drupal::entityManager()->getFieldDefinitions('node', 'basicpage'); - $this->assertTrue($definitions[$this->fieldName]->isTranslatable(), 'Node image field is translatable.'); - - // Create a default language node. - $default_language_node = $this->drupalCreateNode(['type' => 'basicpage', 'title' => 'Lost in translation']); - - // Edit the node to upload a file. - $edit = []; - $name = 'files[' . $this->fieldName . '_0]'; - $edit[$name] = \Drupal::service('file_system')->realpath($this->drupalGetTestFiles('image')[0]->uri); - $this->drupalPostForm('node/' . $default_language_node->id() . '/edit', $edit, t('Save')); - $edit = [$this->fieldName . '[0][alt]' => 'Lost in translation image', $this->fieldName . '[0][title]' => 'Lost in translation image title']; - $this->drupalPostForm(NULL, $edit, t('Save')); - $first_fid = $this->getLastFileId(); - - // Translate the node into French: remove the existing file. - $this->drupalPostForm('node/' . $default_language_node->id() . '/translations/add/en/fr', [], t('Remove')); - - // Upload a different file. - $edit = []; - $edit['title[0][value]'] = 'Scarlett Johansson'; - $name = 'files[' . $this->fieldName . '_0]'; - $edit[$name] = \Drupal::service('file_system')->realpath($this->drupalGetTestFiles('image')[1]->uri); - $this->drupalPostForm(NULL, $edit, t('Save (this translation)')); - $edit = [$this->fieldName . '[0][alt]' => 'Scarlett Johansson image', $this->fieldName . '[0][title]' => 'Scarlett Johansson image title']; - $this->drupalPostForm(NULL, $edit, t('Save (this translation)')); - // This inspects the HTML after the post of the translation, the image - // should be displayed on the original node. - $this->assertRaw('alt="Lost in translation image"'); - $this->assertRaw('title="Lost in translation image title"'); - $second_fid = $this->getLastFileId(); - // View the translated node. - $this->drupalGet('fr/node/' . $default_language_node->id()); - $this->assertRaw('alt="Scarlett Johansson image"'); - - \Drupal::entityTypeManager()->getStorage('file')->resetCache(); - - /* @var $file \Drupal\file\FileInterface */ - - // Ensure the file status of the first file permanent. - $file = File::load($first_fid); - $this->assertTrue($file->isPermanent()); - - // Ensure the file status of the second file is permanent. - $file = File::load($second_fid); - $this->assertTrue($file->isPermanent()); - - // Translate the node into dutch: remove the existing file. - $this->drupalPostForm('node/' . $default_language_node->id() . '/translations/add/en/nl', [], t('Remove')); - - // Upload a different file. - $edit = []; - $edit['title[0][value]'] = 'Akiko Takeshita'; - $name = 'files[' . $this->fieldName . '_0]'; - $edit[$name] = \Drupal::service('file_system')->realpath($this->drupalGetTestFiles('image')[2]->uri); - $this->drupalPostForm(NULL, $edit, t('Save (this translation)')); - $edit = [$this->fieldName . '[0][alt]' => 'Akiko Takeshita image', $this->fieldName . '[0][title]' => 'Akiko Takeshita image title']; - $this->drupalPostForm(NULL, $edit, t('Save (this translation)')); - $third_fid = $this->getLastFileId(); - - \Drupal::entityTypeManager()->getStorage('file')->resetCache(); - - // Ensure the first file is untouched. - $file = File::load($first_fid); - $this->assertTrue($file->isPermanent(), 'First file still exists and is permanent.'); - // This inspects the HTML after the post of the translation, the image - // should be displayed on the original node. - $this->assertRaw('alt="Lost in translation image"'); - $this->assertRaw('title="Lost in translation image title"'); - // View the translated node. - $this->drupalGet('nl/node/' . $default_language_node->id()); - $this->assertRaw('alt="Akiko Takeshita image"'); - $this->assertRaw('title="Akiko Takeshita image title"'); - - // Ensure the file status of the second file is permanent. - $file = File::load($second_fid); - $this->assertTrue($file->isPermanent()); - - // Ensure the file status of the third file is permanent. - $file = File::load($third_fid); - $this->assertTrue($file->isPermanent()); - - // Edit the second translation: remove the existing file. - $this->drupalPostForm('fr/node/' . $default_language_node->id() . '/edit', [], t('Remove')); - - // Upload a different file. - $edit = []; - $edit['title[0][value]'] = 'Giovanni Ribisi'; - $name = 'files[' . $this->fieldName . '_0]'; - $edit[$name] = \Drupal::service('file_system')->realpath($this->drupalGetTestFiles('image')[3]->uri); - $this->drupalPostForm(NULL, $edit, t('Save (this translation)')); - $name = $this->fieldName . '[0][alt]'; - - $edit = [$name => 'Giovanni Ribisi image']; - $this->drupalPostForm(NULL, $edit, t('Save (this translation)')); - $replaced_second_fid = $this->getLastFileId(); - - \Drupal::entityTypeManager()->getStorage('file')->resetCache(); - - // Ensure the first and third files are untouched. - $file = File::load($first_fid); - $this->assertTrue($file->isPermanent(), 'First file still exists and is permanent.'); - - $file = File::load($third_fid); - $this->assertTrue($file->isPermanent()); - - // Ensure the file status of the replaced second file is permanent. - $file = File::load($replaced_second_fid); - $this->assertTrue($file->isPermanent()); - - // Delete the third translation. - $this->drupalPostForm('nl/node/' . $default_language_node->id() . '/delete', [], t('Delete Dutch translation')); - - \Drupal::entityTypeManager()->getStorage('file')->resetCache(); - - // Ensure the first and replaced second files are untouched. - $file = File::load($first_fid); - $this->assertTrue($file->isPermanent(), 'First file still exists and is permanent.'); - - $file = File::load($replaced_second_fid); - $this->assertTrue($file->isPermanent()); - - // Ensure the file status of the third file is now temporary. - $file = File::load($third_fid); - $this->assertTrue($file->isTemporary()); - - // Delete the all translations. - $this->drupalPostForm('node/' . $default_language_node->id() . '/delete', [], t('Delete all translations')); - - \Drupal::entityTypeManager()->getStorage('file')->resetCache(); - - // Ensure the file status of the all files are now temporary. - $file = File::load($first_fid); - $this->assertTrue($file->isTemporary(), 'First file still exists and is temporary.'); - - $file = File::load($replaced_second_fid); - $this->assertTrue($file->isTemporary()); - } - -} diff -r e200cb7efeb3 -r c2387f117808 core/modules/image/src/Tests/ImageStyleFlushTest.php --- a/core/modules/image/src/Tests/ImageStyleFlushTest.php Thu Apr 26 11:26:54 2018 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,110 +0,0 @@ -drupalGetTestFiles('image'); - $file = reset($files); - } - - // Make sure we have an image in our wrapper testing file directory. - $source_uri = file_unmanaged_copy($file->uri, $wrapper . '://'); - // Build the derivative image. - $derivative_uri = $style->buildUri($source_uri); - $derivative = $style->createDerivative($source_uri, $derivative_uri); - - return $derivative ? $derivative_uri : FALSE; - } - - /** - * Count the number of images currently created for a style in a wrapper. - */ - public function getImageCount($style, $wrapper) { - return count(file_scan_directory($wrapper . '://styles/' . $style->id(), '/.*/')); - } - - /** - * General test to flush a style. - */ - public function testFlush() { - - // Setup a style to be created and effects to add to it. - $style_name = strtolower($this->randomMachineName(10)); - $style_label = $this->randomString(); - $style_path = 'admin/config/media/image-styles/manage/' . $style_name; - $effect_edits = [ - 'image_resize' => [ - 'data[width]' => 100, - 'data[height]' => 101, - ], - 'image_scale' => [ - 'data[width]' => 110, - 'data[height]' => 111, - 'data[upscale]' => 1, - ], - ]; - - // Add style form. - $edit = [ - 'name' => $style_name, - 'label' => $style_label, - ]; - $this->drupalPostForm('admin/config/media/image-styles/add', $edit, t('Create new style')); - - // Add each sample effect to the style. - foreach ($effect_edits as $effect => $edit) { - // Add the effect. - $this->drupalPostForm($style_path, ['new' => $effect], t('Add')); - if (!empty($edit)) { - $this->drupalPostForm(NULL, $edit, t('Add effect')); - } - } - - // Load the saved image style. - $style = ImageStyle::load($style_name); - - // Create an image for the 'public' wrapper. - $image_path = $this->createSampleImage($style, 'public'); - // Expecting to find 2 images, one is the sample.png image shown in - // image style preview. - $this->assertEqual($this->getImageCount($style, 'public'), 2, format_string('Image style %style image %file successfully generated.', ['%style' => $style->label(), '%file' => $image_path])); - - // Create an image for the 'private' wrapper. - $image_path = $this->createSampleImage($style, 'private'); - $this->assertEqual($this->getImageCount($style, 'private'), 1, format_string('Image style %style image %file successfully generated.', ['%style' => $style->label(), '%file' => $image_path])); - - // Remove the 'image_scale' effect and updates the style, which in turn - // forces an image style flush. - $style_path = 'admin/config/media/image-styles/manage/' . $style->id(); - $uuids = []; - foreach ($style->getEffects() as $uuid => $effect) { - $uuids[$effect->getPluginId()] = $uuid; - } - $this->drupalPostForm($style_path . '/effects/' . $uuids['image_scale'] . '/delete', [], t('Delete')); - $this->assertResponse(200); - $this->drupalPostForm($style_path, [], t('Update style')); - $this->assertResponse(200); - - // Post flush, expected 1 image in the 'public' wrapper (sample.png). - $this->assertEqual($this->getImageCount($style, 'public'), 1, format_string('Image style %style flushed correctly for %wrapper wrapper.', ['%style' => $style->label(), '%wrapper' => 'public'])); - - // Post flush, expected no image in the 'private' wrapper. - $this->assertEqual($this->getImageCount($style, 'private'), 0, format_string('Image style %style flushed correctly for %wrapper wrapper.', ['%style' => $style->label(), '%wrapper' => 'private'])); - } - -} diff -r e200cb7efeb3 -r c2387f117808 core/modules/image/src/Tests/ImageStylesPathAndUrlTest.php --- a/core/modules/image/src/Tests/ImageStylesPathAndUrlTest.php Thu Apr 26 11:26:54 2018 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,312 +0,0 @@ -style = ImageStyle::create([ - 'name' => 'style_foo', - 'label' => $this->randomString(), - ]); - $this->style->save(); - - // Create a new language. - ConfigurableLanguage::createFromLangcode('fr')->save(); - } - - /** - * Tests \Drupal\image\ImageStyleInterface::buildUri(). - */ - public function testImageStylePath() { - $scheme = 'public'; - $actual = $this->style->buildUri("$scheme://foo/bar.gif"); - $expected = "$scheme://styles/" . $this->style->id() . "/$scheme/foo/bar.gif"; - $this->assertEqual($actual, $expected, 'Got the path for a file URI.'); - - $actual = $this->style->buildUri('foo/bar.gif'); - $expected = "$scheme://styles/" . $this->style->id() . "/$scheme/foo/bar.gif"; - $this->assertEqual($actual, $expected, 'Got the path for a relative file path.'); - } - - /** - * Tests an image style URL using the "public://" scheme. - */ - public function testImageStyleUrlAndPathPublic() { - $this->doImageStyleUrlAndPathTests('public'); - } - - /** - * Tests an image style URL using the "private://" scheme. - */ - public function testImageStyleUrlAndPathPrivate() { - $this->doImageStyleUrlAndPathTests('private'); - } - - /** - * Tests an image style URL with the "public://" scheme and unclean URLs. - */ - public function testImageStyleUrlAndPathPublicUnclean() { - $this->doImageStyleUrlAndPathTests('public', FALSE); - } - - /** - * Tests an image style URL with the "private://" schema and unclean URLs. - */ - public function testImageStyleUrlAndPathPrivateUnclean() { - $this->doImageStyleUrlAndPathTests('private', FALSE); - } - - /** - * Tests an image style URL with the "public://" schema and language prefix. - */ - public function testImageStyleUrlAndPathPublicLanguage() { - $this->doImageStyleUrlAndPathTests('public', TRUE, TRUE, 'fr'); - } - - /** - * Tests an image style URL with the "private://" schema and language prefix. - */ - public function testImageStyleUrlAndPathPrivateLanguage() { - $this->doImageStyleUrlAndPathTests('private', TRUE, TRUE, 'fr'); - } - - /** - * Tests an image style URL with a file URL that has an extra slash in it. - */ - public function testImageStyleUrlExtraSlash() { - $this->doImageStyleUrlAndPathTests('public', TRUE, TRUE); - } - - /** - * Tests that an invalid source image returns a 404. - */ - public function testImageStyleUrlForMissingSourceImage() { - $non_existent_uri = 'public://foo.png'; - $generated_url = $this->style->buildUrl($non_existent_uri); - $this->drupalGet($generated_url); - $this->assertResponse(404, 'Accessing an image style URL with a source image that does not exist provides a 404 error response.'); - } - - /** - * Tests building an image style URL. - */ - public function doImageStyleUrlAndPathTests($scheme, $clean_url = TRUE, $extra_slash = FALSE, $langcode = FALSE) { - $this->prepareRequestForGenerator($clean_url); - - // Make the default scheme neither "public" nor "private" to verify the - // functions work for other than the default scheme. - $this->config('system.file')->set('default_scheme', 'temporary')->save(); - - // Create the directories for the styles. - $directory = $scheme . '://styles/' . $this->style->id(); - $status = file_prepare_directory($directory, FILE_CREATE_DIRECTORY); - $this->assertNotIdentical(FALSE, $status, 'Created the directory for the generated images for the test style.'); - - // Override the language to build the URL for the correct language. - if ($langcode) { - $language_manager = \Drupal::service('language_manager'); - $language = $language_manager->getLanguage($langcode); - $language_manager->setConfigOverrideLanguage($language); - } - - // Create a working copy of the file. - $files = $this->drupalGetTestFiles('image'); - $file = array_shift($files); - $original_uri = file_unmanaged_copy($file->uri, $scheme . '://', FILE_EXISTS_RENAME); - // Let the image_module_test module know about this file, so it can claim - // ownership in hook_file_download(). - \Drupal::state()->set('image.test_file_download', $original_uri); - $this->assertNotIdentical(FALSE, $original_uri, 'Created the generated image file.'); - - // Get the URL of a file that has not been generated and try to create it. - $generated_uri = $this->style->buildUri($original_uri); - $this->assertFalse(file_exists($generated_uri), 'Generated file does not exist.'); - $generate_url = $this->style->buildUrl($original_uri, $clean_url); - - // Make sure that language prefix is never added to the image style URL. - if ($langcode) { - $this->assertTrue(strpos($generate_url, "/$langcode/") === FALSE, 'Langcode was not found in the image style URL.'); - } - - // Ensure that the tests still pass when the file is generated by accessing - // a poorly constructed (but still valid) file URL that has an extra slash - // in it. - if ($extra_slash) { - $modified_uri = str_replace('://', ':///', $original_uri); - $this->assertNotEqual($original_uri, $modified_uri, 'An extra slash was added to the generated file URI.'); - $generate_url = $this->style->buildUrl($modified_uri, $clean_url); - } - if (!$clean_url) { - $this->assertTrue(strpos($generate_url, 'index.php/') !== FALSE, 'When using non-clean URLS, the system path contains the script name.'); - } - // Add some extra chars to the token. - $this->drupalGet(str_replace(IMAGE_DERIVATIVE_TOKEN . '=', IMAGE_DERIVATIVE_TOKEN . '=Zo', $generate_url)); - $this->assertResponse(403, 'Image was inaccessible at the URL with an invalid token.'); - // Change the parameter name so the token is missing. - $this->drupalGet(str_replace(IMAGE_DERIVATIVE_TOKEN . '=', 'wrongparam=', $generate_url)); - $this->assertResponse(403, 'Image was inaccessible at the URL with a missing token.'); - - // Check that the generated URL is the same when we pass in a relative path - // rather than a URI. We need to temporarily switch the default scheme to - // match the desired scheme before testing this, then switch it back to the - // "temporary" scheme used throughout this test afterwards. - $this->config('system.file')->set('default_scheme', $scheme)->save(); - $relative_path = file_uri_target($original_uri); - $generate_url_from_relative_path = $this->style->buildUrl($relative_path, $clean_url); - $this->assertEqual($generate_url, $generate_url_from_relative_path); - $this->config('system.file')->set('default_scheme', 'temporary')->save(); - - // Fetch the URL that generates the file. - $this->drupalGet($generate_url); - $this->assertResponse(200, 'Image was generated at the URL.'); - $this->assertTrue(file_exists($generated_uri), 'Generated file does exist after we accessed it.'); - $this->assertRaw(file_get_contents($generated_uri), 'URL returns expected file.'); - $image = $this->container->get('image.factory')->get($generated_uri); - $this->assertEqual($this->drupalGetHeader('Content-Type'), $image->getMimeType(), 'Expected Content-Type was reported.'); - $this->assertEqual($this->drupalGetHeader('Content-Length'), $image->getFileSize(), 'Expected Content-Length was reported.'); - - // Check that we did not download the original file. - $original_image = $this->container->get('image.factory') - ->get($original_uri); - $this->assertNotEqual($this->drupalGetHeader('Content-Length'), $original_image->getFileSize()); - - if ($scheme == 'private') { - $this->assertEqual($this->drupalGetHeader('Expires'), 'Sun, 19 Nov 1978 05:00:00 GMT', 'Expires header was sent.'); - $this->assertNotEqual(strpos($this->drupalGetHeader('Cache-Control'), 'no-cache'), FALSE, 'Cache-Control header contains \'no-cache\' to prevent caching.'); - $this->assertEqual($this->drupalGetHeader('X-Image-Owned-By'), 'image_module_test', 'Expected custom header has been added.'); - - // Make sure that a second request to the already existing derivative - // works too. - $this->drupalGet($generate_url); - $this->assertResponse(200, 'Image was generated at the URL.'); - - // Check that the second request also returned the generated image. - $this->assertEqual($this->drupalGetHeader('Content-Length'), $image->getFileSize()); - - // Check that we did not download the original file. - $this->assertNotEqual($this->drupalGetHeader('Content-Length'), $original_image->getFileSize()); - - // Make sure that access is denied for existing style files if we do not - // have access. - \Drupal::state()->delete('image.test_file_download'); - $this->drupalGet($generate_url); - $this->assertResponse(403, 'Confirmed that access is denied for the private image style.'); - - // Repeat this with a different file that we do not have access to and - // make sure that access is denied. - $file_noaccess = array_shift($files); - $original_uri_noaccess = file_unmanaged_copy($file_noaccess->uri, $scheme . '://', FILE_EXISTS_RENAME); - $generated_uri_noaccess = $scheme . '://styles/' . $this->style->id() . '/' . $scheme . '/' . drupal_basename($original_uri_noaccess); - $this->assertFalse(file_exists($generated_uri_noaccess), 'Generated file does not exist.'); - $generate_url_noaccess = $this->style->buildUrl($original_uri_noaccess); - - $this->drupalGet($generate_url_noaccess); - $this->assertResponse(403, 'Confirmed that access is denied for the private image style.'); - // Verify that images are not appended to the response. - // Currently this test only uses PNG images. - if (strpos($generate_url, '.png') === FALSE) { - $this->fail('Confirming that private image styles are not appended require PNG file.'); - } - else { - // Check for PNG-Signature - // (cf. http://www.libpng.org/pub/png/book/chapter08.html#png.ch08.div.2) - // in the response body. - $this->assertNoRaw(chr(137) . chr(80) . chr(78) . chr(71) . chr(13) . chr(10) . chr(26) . chr(10), 'No PNG signature found in the response body.'); - } - } - else { - $this->assertEqual($this->drupalGetHeader('Expires'), 'Sun, 19 Nov 1978 05:00:00 GMT', 'Expires header was sent.'); - $this->assertEqual(strpos($this->drupalGetHeader('Cache-Control'), 'no-cache'), FALSE, 'Cache-Control header contains \'no-cache\' to prevent caching.'); - - if ($clean_url) { - // Add some extra chars to the token. - $this->drupalGet(str_replace(IMAGE_DERIVATIVE_TOKEN . '=', IMAGE_DERIVATIVE_TOKEN . '=Zo', $generate_url)); - $this->assertResponse(200, 'Existing image was accessible at the URL with an invalid token.'); - } - } - - // Allow insecure image derivatives to be created for the remainder of this - // test. - $this->config('image.settings') - ->set('allow_insecure_derivatives', TRUE) - ->save(); - - // Create another working copy of the file. - $files = $this->drupalGetTestFiles('image'); - $file = array_shift($files); - $original_uri = file_unmanaged_copy($file->uri, $scheme . '://', FILE_EXISTS_RENAME); - // Let the image_module_test module know about this file, so it can claim - // ownership in hook_file_download(). - \Drupal::state()->set('image.test_file_download', $original_uri); - - // Suppress the security token in the URL, then get the URL of a file that - // has not been created and try to create it. Check that the security token - // is not present in the URL but that the image is still accessible. - $this->config('image.settings')->set('suppress_itok_output', TRUE)->save(); - $generated_uri = $this->style->buildUri($original_uri); - $this->assertFalse(file_exists($generated_uri), 'Generated file does not exist.'); - $generate_url = $this->style->buildUrl($original_uri, $clean_url); - $this->assertIdentical(strpos($generate_url, IMAGE_DERIVATIVE_TOKEN . '='), FALSE, 'The security token does not appear in the image style URL.'); - $this->drupalGet($generate_url); - $this->assertResponse(200, 'Image was accessible at the URL with a missing token.'); - - // Stop supressing the security token in the URL. - $this->config('image.settings')->set('suppress_itok_output', FALSE)->save(); - // Ensure allow_insecure_derivatives is enabled. - $this->assertEqual($this->config('image.settings') - ->get('allow_insecure_derivatives'), TRUE); - // Check that a security token is still required when generating a second - // image derivative using the first one as a source. - $nested_url = $this->style->buildUrl($generated_uri, $clean_url); - $matches_expected_url_format = (boolean) preg_match('/styles\/' . $this->style->id() . '\/' . $scheme . '\/styles\/' . $this->style->id() . '\/' . $scheme . '/', $nested_url); - $this->assertTrue($matches_expected_url_format, "URL for a derivative of an image style matches expected format."); - $nested_url_with_wrong_token = str_replace(IMAGE_DERIVATIVE_TOKEN . '=', 'wrongparam=', $nested_url); - $this->drupalGet($nested_url_with_wrong_token); - $this->assertResponse(403, 'Image generated from an earlier derivative was inaccessible at the URL with a missing token.'); - // Check that this restriction cannot be bypassed by adding extra slashes - // to the URL. - $this->drupalGet(substr_replace($nested_url_with_wrong_token, '//styles/', strrpos($nested_url_with_wrong_token, '/styles/'), strlen('/styles/'))); - $this->assertResponse(403, 'Image generated from an earlier derivative was inaccessible at the URL with a missing token, even with an extra forward slash in the URL.'); - $this->drupalGet(substr_replace($nested_url_with_wrong_token, '////styles/', strrpos($nested_url_with_wrong_token, '/styles/'), strlen('/styles/'))); - $this->assertResponse(403, 'Image generated from an earlier derivative was inaccessible at the URL with a missing token, even with multiple forward slashes in the URL.'); - // Make sure the image can still be generated if a correct token is used. - $this->drupalGet($nested_url); - $this->assertResponse(200, 'Image was accessible when a correct token was provided in the URL.'); - - // Check that requesting a nonexistent image does not create any new - // directories in the file system. - $directory = $scheme . '://styles/' . $this->style->id() . '/' . $scheme . '/' . $this->randomMachineName(); - $this->drupalGet(file_create_url($directory . '/' . $this->randomString())); - $this->assertFalse(file_exists($directory), 'New directory was not created in the filesystem when requesting an unauthorized image.'); - } - -} diff -r e200cb7efeb3 -r c2387f117808 core/modules/image/src/Tests/ImageThemeFunctionTest.php --- a/core/modules/image/src/Tests/ImageThemeFunctionTest.php Thu Apr 26 11:26:54 2018 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,221 +0,0 @@ - 'entity_test', - 'field_name' => 'image_test', - 'type' => 'image', - 'cardinality' => FieldStorageDefinitionInterface::CARDINALITY_UNLIMITED, - ])->save(); - FieldConfig::create([ - 'entity_type' => 'entity_test', - 'field_name' => 'image_test', - 'bundle' => 'entity_test', - ])->save(); - file_unmanaged_copy(\Drupal::root() . '/core/misc/druplicon.png', 'public://example.jpg'); - $this->image = File::create([ - 'uri' => 'public://example.jpg', - ]); - $this->image->save(); - $this->imageFactory = $this->container->get('image.factory'); - } - - /** - * Tests usage of the image field formatters. - */ - public function testImageFormatterTheme() { - /** @var \Drupal\Core\Render\RendererInterface $renderer */ - $renderer = $this->container->get('renderer'); - - // Create an image. - $files = $this->drupalGetTestFiles('image'); - $file = reset($files); - $original_uri = file_unmanaged_copy($file->uri, 'public://', FILE_EXISTS_RENAME); - - // Create a style. - $style = ImageStyle::create(['name' => 'test', 'label' => 'Test']); - $style->save(); - $url = file_url_transform_relative($style->buildUrl($original_uri)); - - // Create a test entity with the image field set. - $entity = EntityTest::create(); - $entity->image_test->target_id = $this->image->id(); - $entity->image_test->alt = NULL; - $entity->image_test->uri = $original_uri; - $image = $this->imageFactory->get('public://example.jpg'); - $entity->save(); - - // Create the base element that we'll use in the tests below. - $path = $this->randomMachineName(); - $base_element = [ - '#theme' => 'image_formatter', - '#image_style' => 'test', - '#item' => $entity->image_test, - '#url' => Url::fromUri('base:' . $path), - ]; - - // Test using theme_image_formatter() with a NULL value for the alt option. - $element = $base_element; - $this->setRawContent($renderer->renderRoot($element)); - $elements = $this->xpath('//a[@href=:path]/img[@class="image-style-test" and @src=:url and @width=:width and @height=:height]', [':path' => base_path() . $path, ':url' => $url, ':width' => $image->getWidth(), ':height' => $image->getHeight()]); - $this->assertEqual(count($elements), 1, 'theme_image_formatter() correctly renders with a NULL value for the alt option.'); - - // Test using theme_image_formatter() without an image title, alt text, or - // link options. - $element = $base_element; - $element['#item']->alt = ''; - $this->setRawContent($renderer->renderRoot($element)); - $elements = $this->xpath('//a[@href=:path]/img[@class="image-style-test" and @src=:url and @width=:width and @height=:height and @alt=""]', [':path' => base_path() . $path, ':url' => $url, ':width' => $image->getWidth(), ':height' => $image->getHeight()]); - $this->assertEqual(count($elements), 1, 'theme_image_formatter() correctly renders without title, alt, or path options.'); - - // Link the image to a fragment on the page, and not a full URL. - $fragment = $this->randomMachineName(); - $element = $base_element; - $element['#url'] = Url::fromRoute('', [], ['fragment' => $fragment]); - $this->setRawContent($renderer->renderRoot($element)); - $elements = $this->xpath('//a[@href=:fragment]/img[@class="image-style-test" and @src=:url and @width=:width and @height=:height and @alt=""]', [ - ':fragment' => '#' . $fragment, - ':url' => $url, - ':width' => $image->getWidth(), - ':height' => $image->getHeight() - ]); - $this->assertEqual(count($elements), 1, 'theme_image_formatter() correctly renders a link fragment.'); - } - - /** - * Tests usage of the image style theme function. - */ - public function testImageStyleTheme() { - /** @var \Drupal\Core\Render\RendererInterface $renderer */ - $renderer = $this->container->get('renderer'); - - // Create an image. - $files = $this->drupalGetTestFiles('image'); - $file = reset($files); - $original_uri = file_unmanaged_copy($file->uri, 'public://', FILE_EXISTS_RENAME); - - // Create a style. - $style = ImageStyle::create(['name' => 'image_test', 'label' => 'Test']); - $style->save(); - $url = file_url_transform_relative($style->buildUrl($original_uri)); - - // Create the base element that we'll use in the tests below. - $base_element = [ - '#theme' => 'image_style', - '#style_name' => 'image_test', - '#uri' => $original_uri, - ]; - - $element = $base_element; - $this->setRawContent($renderer->renderRoot($element)); - $elements = $this->xpath('//img[@class="image-style-image-test" and @src=:url and @alt=""]', [':url' => $url]); - $this->assertEqual(count($elements), 1, 'theme_image_style() renders an image correctly.'); - - // Test using theme_image_style() with a NULL value for the alt option. - $element = $base_element; - $element['#alt'] = NULL; - $this->setRawContent($renderer->renderRoot($element)); - $elements = $this->xpath('//img[@class="image-style-image-test" and @src=:url]', [':url' => $url]); - $this->assertEqual(count($elements), 1, 'theme_image_style() renders an image correctly with a NULL value for the alt option.'); - } - - /** - * Tests image alt attribute functionality. - */ - public function testImageAltFunctionality() { - /** @var \Drupal\Core\Render\RendererInterface $renderer */ - $renderer = $this->container->get('renderer'); - - // Test using alt directly with alt attribute. - $image_with_alt_property = [ - '#theme' => 'image', - '#uri' => '/core/themes/bartik/logo.svg', - '#alt' => 'Regular alt', - '#title' => 'Test title', - '#width' => '50%', - '#height' => '50%', - '#attributes' => ['class' => 'image-with-regular-alt', 'id' => 'my-img'], - ]; - - $this->setRawContent($renderer->renderRoot($image_with_alt_property)); - $elements = $this->xpath('//img[contains(@class, class) and contains(@alt, :alt)]', [":class" => "image-with-regular-alt", ":alt" => "Regular alt"]); - $this->assertEqual(count($elements), 1, 'Regular alt displays correctly'); - - // Test using alt attribute inside attributes. - $image_with_alt_attribute_alt_attribute = [ - '#theme' => 'image', - '#uri' => '/core/themes/bartik/logo.svg', - '#width' => '50%', - '#height' => '50%', - '#attributes' => [ - 'class' => 'image-with-attribute-alt', - 'id' => 'my-img', - 'title' => 'New test title', - 'alt' => 'Attribute alt', - ], - ]; - - $this->setRawContent($renderer->renderRoot($image_with_alt_attribute_alt_attribute)); - $elements = $this->xpath('//img[contains(@class, class) and contains(@alt, :alt)]', [":class" => "image-with-attribute-alt", ":alt" => "Attribute alt"]); - $this->assertEqual(count($elements), 1, 'Attribute alt displays correctly'); - - // Test using alt attribute as property and inside attributes. - $image_with_alt_attribute_both = [ - '#theme' => 'image', - '#uri' => '/core/themes/bartik/logo.svg', - '#width' => '50%', - '#height' => '50%', - '#alt' => 'Kitten sustainable', - '#attributes' => [ - 'class' => 'image-with-attribute-alt', - 'id' => 'my-img', - 'title' => 'New test title', - 'alt' => 'Attribute alt', - ], - ]; - - $this->setRawContent($renderer->renderRoot($image_with_alt_attribute_both)); - $elements = $this->xpath('//img[contains(@class, class) and contains(@alt, :alt)]', [":class" => "image-with-attribute-alt", ":alt" => "Attribute alt"]); - $this->assertEqual(count($elements), 1, 'Attribute alt overrides alt property if both set.'); - } - -} diff -r e200cb7efeb3 -r c2387f117808 core/modules/image/src/Tests/QuickEditImageControllerTest.php --- a/core/modules/image/src/Tests/QuickEditImageControllerTest.php Thu Apr 26 11:26:54 2018 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,186 +0,0 @@ -drupalCreateContentType(['type' => 'article', 'name' => 'Article']); - - // Log in as a content author who can use Quick Edit and edit Articles. - $this->contentAuthorUser = $this->drupalCreateUser([ - 'access contextual links', - 'access in-place editing', - 'access content', - 'create article content', - 'edit any article content', - 'delete any article content', - ]); - $this->drupalLogin($this->contentAuthorUser); - - // Create a field with basic resolution validators. - $this->fieldName = strtolower($this->randomMachineName()); - $field_settings = [ - 'max_resolution' => '100x', - 'min_resolution' => '50x', - ]; - $this->createImageField($this->fieldName, 'article', [], $field_settings); - } - - /** - * Tests that routes restrict access for un-privileged users. - */ - public function testAccess() { - // Create an anonymous user. - $user = $this->createUser(); - $this->drupalLogin($user); - - // Create a test Node. - $node = $this->drupalCreateNode([ - 'type' => 'article', - 'title' => t('Test Node'), - ]); - $this->drupalGet('quickedit/image/info/node/' . $node->id() . '/' . $this->fieldName . '/' . $node->language()->getId() . '/default'); - $this->assertResponse('403'); - $this->drupalPost('quickedit/image/upload/node/' . $node->id() . '/' . $this->fieldName . '/' . $node->language()->getId() . '/default', 'application/json', []); - $this->assertResponse('403'); - } - - /** - * Tests that the field info route returns expected data. - */ - public function testFieldInfo() { - // Create a test Node. - $node = $this->drupalCreateNode([ - 'type' => 'article', - 'title' => t('Test Node'), - ]); - $info = $this->drupalGetJSON('quickedit/image/info/node/' . $node->id() . '/' . $this->fieldName . '/' . $node->language()->getId() . '/default'); - // Assert that the default settings for our field are respected by our JSON - // endpoint. - $this->assertTrue($info['alt_field']); - $this->assertFalse($info['title_field']); - } - - /** - * Tests that uploading a valid image works. - */ - public function testValidImageUpload() { - // Create a test Node. - $node = $this->drupalCreateNode([ - 'type' => 'article', - 'title' => t('Test Node'), - ]); - - // We want a test image that is a valid size. - $valid_image = FALSE; - $image_factory = $this->container->get('image.factory'); - foreach ($this->drupalGetTestFiles('image') as $image) { - $image_file = $image_factory->get($image->uri); - if ($image_file->getWidth() > 50 && $image_file->getWidth() < 100) { - $valid_image = $image; - break; - } - } - $this->assertTrue($valid_image); - $this->uploadImage($valid_image, $node->id(), $this->fieldName, $node->language()->getId()); - $this->assertText('fid', t('Valid upload completed successfully.')); - } - - /** - * Tests that uploading a invalid image does not work. - */ - public function testInvalidUpload() { - // Create a test Node. - $node = $this->drupalCreateNode([ - 'type' => 'article', - 'title' => t('Test Node'), - ]); - - // We want a test image that will fail validation. - $invalid_image = FALSE; - /** @var \Drupal\Core\Image\ImageFactory $image_factory */ - $image_factory = $this->container->get('image.factory'); - foreach ($this->drupalGetTestFiles('image') as $image) { - /** @var \Drupal\Core\Image\ImageInterface $image_file */ - $image_file = $image_factory->get($image->uri); - if ($image_file->getWidth() < 50 || $image_file->getWidth() > 100) { - $invalid_image = $image; - break; - } - } - $this->assertTrue($invalid_image); - $this->uploadImage($invalid_image, $node->id(), $this->fieldName, $node->language()->getId()); - $this->assertText('main_error', t('Invalid upload returned errors.')); - } - - /** - * Uploads an image using the image module's Quick Edit route. - * - * @param object $image - * The image to upload. - * @param int $nid - * The target node ID. - * @param string $field_name - * The target field machine name. - * @param string $langcode - * The langcode to use when setting the field's value. - * - * @return mixed - * The content returned from the call to $this->curlExec(). - */ - public function uploadImage($image, $nid, $field_name, $langcode) { - $filepath = $this->container->get('file_system')->realpath($image->uri); - $data = [ - 'files[image]' => curl_file_create($filepath), - ]; - $path = 'quickedit/image/upload/node/' . $nid . '/' . $field_name . '/' . $langcode . '/default'; - // We assemble the curl request ourselves as drupalPost cannot process file - // uploads, and drupalPostForm only works with typical Drupal forms. - return $this->curlExec([ - CURLOPT_URL => $this->buildUrl($path, []), - CURLOPT_POST => TRUE, - CURLOPT_POSTFIELDS => $data, - CURLOPT_HTTPHEADER => [ - 'Accept: application/json', - 'Content-Type: multipart/form-data', - ], - ]); - } - -} diff -r e200cb7efeb3 -r c2387f117808 core/modules/image/src/Tests/Views/RelationshipUserImageDataTest.php --- a/core/modules/image/src/Tests/Views/RelationshipUserImageDataTest.php Thu Apr 26 11:26:54 2018 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,96 +0,0 @@ - 'user', - 'field_name' => 'user_picture', - 'type' => 'image', - 'translatable' => '0', - ])->save(); - FieldConfig::create([ - 'label' => 'User Picture', - 'description' => '', - 'field_name' => 'user_picture', - 'entity_type' => 'user', - 'bundle' => 'user', - 'required' => 0, - ])->save(); - - ViewTestData::createTestViews(get_class($this), ['image_test_views']); - } - - /** - * Tests using the views image relationship. - */ - public function testViewsHandlerRelationshipUserImageData() { - $file = File::create([ - 'fid' => 2, - 'uid' => 2, - 'filename' => 'image-test.jpg', - 'uri' => "public://image-test.jpg", - 'filemime' => 'image/jpeg', - 'created' => 1, - 'changed' => 1, - 'status' => FILE_STATUS_PERMANENT, - ]); - $file->enforceIsNew(); - file_put_contents($file->getFileUri(), file_get_contents('core/modules/simpletest/files/image-1.png')); - $file->save(); - - $account = $this->drupalCreateUser(); - $account->user_picture->target_id = 2; - $account->save(); - - $view = Views::getView('test_image_user_image_data'); - // Tests \Drupal\taxonomy\Plugin\views\relationship\NodeTermData::calculateDependencies(). - $expected = [ - 'module' => [ - 'file', - 'user', - ], - ]; - $this->assertIdentical($expected, $view->getDependencies()); - $this->executeView($view); - $expected_result = [ - [ - 'file_managed_user__user_picture_fid' => '2', - ], - ]; - $column_map = ['file_managed_user__user_picture_fid' => 'file_managed_user__user_picture_fid']; - $this->assertIdenticalResultset($view, $expected_result, $column_map); - } - -} diff -r e200cb7efeb3 -r c2387f117808 core/modules/image/tests/src/Functional/FileMoveTest.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/core/modules/image/tests/src/Functional/FileMoveTest.php Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,58 @@ +drupalGetTestFiles('image'))); + + // Create derivative image. + $styles = ImageStyle::loadMultiple(); + $style = reset($styles); + $original_uri = $file->getFileUri(); + $derivative_uri = $style->buildUri($original_uri); + $style->createDerivative($original_uri, $derivative_uri); + + // Check if derivative image exists. + $this->assertTrue(file_exists($derivative_uri), 'Make sure derivative image is generated successfully.'); + + // Clone the object so we don't have to worry about the function changing + // our reference copy. + $desired_filepath = 'public://' . $this->randomMachineName(); + $result = file_move(clone $file, $desired_filepath, FILE_EXISTS_ERROR); + + // Check if image has been moved. + $this->assertTrue(file_exists($result->getFileUri()), 'Make sure image is moved successfully.'); + + // Check if derivative image has been flushed. + $this->assertFalse(file_exists($derivative_uri), 'Make sure derivative image has been flushed.'); + } + +} diff -r e200cb7efeb3 -r c2387f117808 core/modules/image/tests/src/Functional/Hal/ImageStyleHalJsonAnonTest.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/core/modules/image/tests/src/Functional/Hal/ImageStyleHalJsonAnonTest.php Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,30 @@ +drupalGetTestFiles('image'); + $file = reset($files); + $file_path = file_unmanaged_copy($file->uri); + } + + return $style->buildUrl($file_path) ? $file_path : FALSE; + } + + /** + * Count the number of images currently create for a style. + */ + public function getImageCount(ImageStyleInterface $style) { + return count(file_scan_directory('public://styles/' . $style->id(), '/.*/')); + } + + /** + * Test creating an image style with a numeric name and ensuring it can be + * applied to an image. + */ + public function testNumericStyleName() { + $style_name = rand(); + $style_label = $this->randomString(); + $edit = [ + 'name' => $style_name, + 'label' => $style_label, + ]; + $this->drupalPostForm('admin/config/media/image-styles/add', $edit, t('Create new style')); + $this->assertRaw(t('Style %name was created.', ['%name' => $style_label])); + $options = image_style_options(); + $this->assertTrue(array_key_exists($style_name, $options), format_string('Array key %key exists.', ['%key' => $style_name])); + } + + /** + * General test to add a style, add/remove/edit effects to it, then delete it. + */ + public function testStyle() { + $admin_path = 'admin/config/media/image-styles'; + + // Setup a style to be created and effects to add to it. + $style_name = strtolower($this->randomMachineName(10)); + $style_label = $this->randomString(); + $style_path = $admin_path . '/manage/' . $style_name; + $effect_edits = [ + 'image_resize' => [ + 'width' => 100, + 'height' => 101, + ], + 'image_scale' => [ + 'width' => 110, + 'height' => 111, + 'upscale' => 1, + ], + 'image_scale_and_crop' => [ + 'width' => 120, + 'height' => 121, + ], + 'image_crop' => [ + 'width' => 130, + 'height' => 131, + 'anchor' => 'left-top', + ], + 'image_desaturate' => [ + // No options for desaturate. + ], + 'image_rotate' => [ + 'degrees' => 5, + 'random' => 1, + 'bgcolor' => '#FFFF00', + ], + ]; + + // Add style form. + + $edit = [ + 'name' => $style_name, + 'label' => $style_label, + ]; + $this->drupalPostForm($admin_path . '/add', $edit, t('Create new style')); + $this->assertRaw(t('Style %name was created.', ['%name' => $style_label])); + + // Ensure that the expected entity operations are there. + $this->drupalGet($admin_path); + $this->assertLinkByHref($style_path); + $this->assertLinkByHref($style_path . '/flush'); + $this->assertLinkByHref($style_path . '/delete'); + + // Add effect form. + + // Add each sample effect to the style. + foreach ($effect_edits as $effect => $edit) { + $edit_data = []; + foreach ($edit as $field => $value) { + $edit_data['data[' . $field . ']'] = $value; + } + // Add the effect. + $this->drupalPostForm($style_path, ['new' => $effect], t('Add')); + if (!empty($edit)) { + $this->drupalPostForm(NULL, $edit_data, t('Add effect')); + } + } + + // Load the saved image style. + $style = ImageStyle::load($style_name); + + // Ensure that third party settings were added to the config entity. + // These are added by a hook_image_style_presave() implemented in + // image_module_test module. + $this->assertEqual('bar', $style->getThirdPartySetting('image_module_test', 'foo'), 'Third party settings were added to the image style.'); + + // Ensure that the image style URI matches our expected path. + $style_uri_path = $style->url(); + $this->assertTrue(strpos($style_uri_path, $style_path) !== FALSE, 'The image style URI is correct.'); + + // Confirm that all effects on the image style have settings that match + // what was saved. + $uuids = []; + foreach ($style->getEffects() as $uuid => $effect) { + // Store the uuid for later use. + $uuids[$effect->getPluginId()] = $uuid; + $effect_configuration = $effect->getConfiguration(); + foreach ($effect_edits[$effect->getPluginId()] as $field => $value) { + $this->assertEqual($value, $effect_configuration['data'][$field], SafeMarkup::format('The %field field in the %effect effect has the correct value of %value.', ['%field' => $field, '%effect' => $effect->getPluginId(), '%value' => $value])); + } + } + + // Assert that every effect was saved. + foreach (array_keys($effect_edits) as $effect_name) { + $this->assertTrue(isset($uuids[$effect_name]), format_string( + 'A %effect_name effect was saved with ID %uuid', + [ + '%effect_name' => $effect_name, + '%uuid' => $uuids[$effect_name], + ])); + } + + // Image style overview form (ordering and renaming). + + // Confirm the order of effects is maintained according to the order we + // added the fields. + $effect_edits_order = array_keys($effect_edits); + $order_correct = TRUE; + $index = 0; + foreach ($style->getEffects() as $effect) { + if ($effect_edits_order[$index] != $effect->getPluginId()) { + $order_correct = FALSE; + } + $index++; + } + $this->assertTrue($order_correct, 'The order of the effects is correctly set by default.'); + + // Test the style overview form. + // Change the name of the style and adjust the weights of effects. + $style_name = strtolower($this->randomMachineName(10)); + $style_label = $this->randomMachineName(); + $weight = count($effect_edits); + $edit = [ + 'name' => $style_name, + 'label' => $style_label, + ]; + foreach ($style->getEffects() as $uuid => $effect) { + $edit['effects[' . $uuid . '][weight]'] = $weight; + $weight--; + } + + // Create an image to make sure it gets flushed after saving. + $image_path = $this->createSampleImage($style); + $this->assertEqual($this->getImageCount($style), 1, format_string('Image style %style image %file successfully generated.', ['%style' => $style->label(), '%file' => $image_path])); + + $this->drupalPostForm($style_path, $edit, t('Update style')); + + // Note that after changing the style name, the style path is changed. + $style_path = 'admin/config/media/image-styles/manage/' . $style_name; + + // Check that the URL was updated. + $this->drupalGet($style_path); + $this->assertTitle(t('Edit style @name | Drupal', ['@name' => $style_label])); + $this->assertResponse(200, format_string('Image style %original renamed to %new', ['%original' => $style->id(), '%new' => $style_name])); + + // Check that the available image effects are properly sorted. + $option = $this->xpath('//select[@id=:id]//option', [':id' => 'edit-new--2']); + $this->assertEquals('Ajax test', $option[1]->getText(), '"Ajax test" is the first selectable effect.'); + + // Check that the image was flushed after updating the style. + // This is especially important when renaming the style. Make sure that + // the old image directory has been deleted. + $this->assertEqual($this->getImageCount($style), 0, format_string('Image style %style was flushed after renaming the style and updating the order of effects.', ['%style' => $style->label()])); + + // Load the style by the new name with the new weights. + $style = ImageStyle::load($style_name); + + // Confirm the new style order was saved. + $effect_edits_order = array_reverse($effect_edits_order); + $order_correct = TRUE; + $index = 0; + foreach ($style->getEffects() as $effect) { + if ($effect_edits_order[$index] != $effect->getPluginId()) { + $order_correct = FALSE; + } + $index++; + } + $this->assertTrue($order_correct, 'The order of the effects is correctly set by default.'); + + // Image effect deletion form. + + // Create an image to make sure it gets flushed after deleting an effect. + $image_path = $this->createSampleImage($style); + $this->assertEqual($this->getImageCount($style), 1, format_string('Image style %style image %file successfully generated.', ['%style' => $style->label(), '%file' => $image_path])); + + // Delete the 'image_crop' effect from the style. + $this->drupalPostForm($style_path . '/effects/' . $uuids['image_crop'] . '/delete', [], t('Delete')); + // Confirm that the form submission was successful. + $this->assertResponse(200); + $image_crop_effect = $style->getEffect($uuids['image_crop']); + $this->assertRaw(t('The image effect %name has been deleted.', ['%name' => $image_crop_effect->label()])); + // Confirm that there is no longer a link to the effect. + $this->assertNoLinkByHref($style_path . '/effects/' . $uuids['image_crop'] . '/delete'); + // Refresh the image style information and verify that the effect was + // actually deleted. + $entity_type_manager = $this->container->get('entity_type.manager'); + $style = $entity_type_manager->getStorage('image_style')->loadUnchanged($style->id()); + $this->assertFalse($style->getEffects()->has($uuids['image_crop']), format_string( + 'Effect with ID %uuid no longer found on image style %style', + [ + '%uuid' => $uuids['image_crop'], + '%style' => $style->label(), + ])); + + // Additional test on Rotate effect, for transparent background. + $edit = [ + 'data[degrees]' => 5, + 'data[random]' => 0, + 'data[bgcolor]' => '', + ]; + $this->drupalPostForm($style_path, ['new' => 'image_rotate'], t('Add')); + $this->drupalPostForm(NULL, $edit, t('Add effect')); + $entity_type_manager = $this->container->get('entity_type.manager'); + $style = $entity_type_manager->getStorage('image_style')->loadUnchanged($style_name); + $this->assertEqual(count($style->getEffects()), 6, 'Rotate effect with transparent background was added.'); + + // Style deletion form. + + // Delete the style. + $this->drupalPostForm($style_path . '/delete', [], t('Delete')); + + // Confirm the style directory has been removed. + $directory = file_default_scheme() . '://styles/' . $style_name; + $this->assertFalse(is_dir($directory), format_string('Image style %style directory removed on style deletion.', ['%style' => $style->label()])); + + $this->assertFalse(ImageStyle::load($style_name), format_string('Image style %style successfully deleted.', ['%style' => $style->label()])); + + // Test empty text when there are no image styles. + + // Delete all image styles. + foreach (ImageStyle::loadMultiple() as $image_style) { + $image_style->delete(); + } + + // Confirm that the empty text is correct on the image styles page. + $this->drupalGet($admin_path); + $this->assertRaw(t('There are currently no styles. Add a new one.', [ + ':url' => \Drupal::url('image.style_add'), + ])); + + } + + /** + * Test deleting a style and choosing a replacement style. + */ + public function testStyleReplacement() { + // Create a new style. + $style_name = strtolower($this->randomMachineName(10)); + $style_label = $this->randomString(); + $style = ImageStyle::create(['name' => $style_name, 'label' => $style_label]); + $style->save(); + $style_path = 'admin/config/media/image-styles/manage/'; + + // Create an image field that uses the new style. + $field_name = strtolower($this->randomMachineName(10)); + $this->createImageField($field_name, 'article'); + entity_get_display('node', 'article', 'default') + ->setComponent($field_name, [ + 'type' => 'image', + 'settings' => ['image_style' => $style_name], + ]) + ->save(); + + // Create a new node with an image attached. + $test_image = current($this->drupalGetTestFiles('image')); + $nid = $this->uploadNodeImage($test_image, $field_name, 'article', $this->randomMachineName()); + $node = Node::load($nid); + + // Get node field original image URI. + $fid = $node->get($field_name)->target_id; + $original_uri = File::load($fid)->getFileUri(); + + // Test that image is displayed using newly created style. + $this->drupalGet('node/' . $nid); + $this->assertRaw(file_url_transform_relative($style->buildUrl($original_uri)), format_string('Image displayed using style @style.', ['@style' => $style_name])); + + // Rename the style and make sure the image field is updated. + $new_style_name = strtolower($this->randomMachineName(10)); + $new_style_label = $this->randomString(); + $edit = [ + 'name' => $new_style_name, + 'label' => $new_style_label, + ]; + $this->drupalPostForm($style_path . $style_name, $edit, t('Update style')); + $this->assertText(t('Changes to the style have been saved.'), format_string('Style %name was renamed to %new_name.', ['%name' => $style_name, '%new_name' => $new_style_name])); + $this->drupalGet('node/' . $nid); + + // Reload the image style using the new name. + $style = ImageStyle::load($new_style_name); + $this->assertRaw(file_url_transform_relative($style->buildUrl($original_uri)), 'Image displayed using style replacement style.'); + + // Delete the style and choose a replacement style. + $edit = [ + 'replacement' => 'thumbnail', + ]; + $this->drupalPostForm($style_path . $new_style_name . '/delete', $edit, t('Delete')); + $message = t('The image style %name has been deleted.', ['%name' => $new_style_label]); + $this->assertRaw($message); + + $replacement_style = ImageStyle::load('thumbnail'); + $this->drupalGet('node/' . $nid); + $this->assertRaw(file_url_transform_relative($replacement_style->buildUrl($original_uri)), 'Image displayed using style replacement style.'); + } + + /** + * Verifies that editing an image effect does not cause it to be duplicated. + */ + public function testEditEffect() { + // Add a scale effect. + $style_name = 'test_style_effect_edit'; + $this->drupalGet('admin/config/media/image-styles/add'); + $this->drupalPostForm(NULL, ['label' => 'Test style effect edit', 'name' => $style_name], t('Create new style')); + $this->drupalPostForm(NULL, ['new' => 'image_scale_and_crop'], t('Add')); + $this->drupalPostForm(NULL, ['data[width]' => '300', 'data[height]' => '200'], t('Add effect')); + $this->assertText(t('Scale and crop 300×200')); + + // There should normally be only one edit link on this page initially. + $this->clickLink(t('Edit')); + $this->drupalPostForm(NULL, ['data[width]' => '360', 'data[height]' => '240'], t('Update effect')); + $this->assertText(t('Scale and crop 360×240')); + + // Check that the previous effect is replaced. + $this->assertNoText(t('Scale and crop 300×200')); + + // Add another scale effect. + $this->drupalGet('admin/config/media/image-styles/add'); + $this->drupalPostForm(NULL, ['label' => 'Test style scale edit scale', 'name' => 'test_style_scale_edit_scale'], t('Create new style')); + $this->drupalPostForm(NULL, ['new' => 'image_scale'], t('Add')); + $this->drupalPostForm(NULL, ['data[width]' => '12', 'data[height]' => '19'], t('Add effect')); + + // Edit the scale effect that was just added. + $this->clickLink(t('Edit')); + $this->drupalPostForm(NULL, ['data[width]' => '24', 'data[height]' => '19'], t('Update effect')); + + // Add another scale effect and make sure both exist. Click through from + // the overview to make sure that it is possible to add new effect then. + $this->drupalGet('admin/config/media/image-styles'); + $rows = $this->xpath('//table/tbody/tr'); + $i = 0; + foreach ($rows as $row) { + if ($row->find('css', 'td')->getText() === 'Test style scale edit scale') { + $this->clickLink('Edit', $i); + break; + } + $i++; + } + $this->drupalPostForm(NULL, ['new' => 'image_scale'], t('Add')); + $this->drupalPostForm(NULL, ['data[width]' => '12', 'data[height]' => '19'], t('Add effect')); + $this->assertText(t('Scale 24×19')); + $this->assertText(t('Scale 12×19')); + + // Try to edit a nonexistent effect. + $uuid = $this->container->get('uuid'); + $this->drupalGet('admin/config/media/image-styles/manage/' . $style_name . '/effects/' . $uuid->generate()); + $this->assertResponse(404); + } + + /** + * Test flush user interface. + */ + public function testFlushUserInterface() { + $admin_path = 'admin/config/media/image-styles'; + + // Create a new style. + $style_name = strtolower($this->randomMachineName(10)); + $style = ImageStyle::create(['name' => $style_name, 'label' => $this->randomString()]); + $style->save(); + + // Create an image to make sure it gets flushed. + $files = $this->drupalGetTestFiles('image'); + $image_uri = $files[0]->uri; + $derivative_uri = $style->buildUri($image_uri); + $this->assertTrue($style->createDerivative($image_uri, $derivative_uri)); + $this->assertEqual($this->getImageCount($style), 1); + + // Go to image styles list page and check if the flush operation link + // exists. + $this->drupalGet($admin_path); + $flush_path = $admin_path . '/manage/' . $style_name . '/flush'; + $this->assertLinkByHref($flush_path); + + // Flush the image style derivatives using the user interface. + $this->drupalPostForm($flush_path, [], t('Flush')); + + // The derivative image file should have been deleted. + $this->assertEqual($this->getImageCount($style), 0); + } + + /** + * Tests image style configuration import that does a delete. + */ + public function testConfigImport() { + // Create a new style. + $style_name = strtolower($this->randomMachineName(10)); + $style_label = $this->randomString(); + $style = ImageStyle::create(['name' => $style_name, 'label' => $style_label]); + $style->save(); + + // Create an image field that uses the new style. + $field_name = strtolower($this->randomMachineName(10)); + $this->createImageField($field_name, 'article'); + entity_get_display('node', 'article', 'default') + ->setComponent($field_name, [ + 'type' => 'image', + 'settings' => ['image_style' => $style_name], + ]) + ->save(); + + // Create a new node with an image attached. + $test_image = current($this->drupalGetTestFiles('image')); + $nid = $this->uploadNodeImage($test_image, $field_name, 'article', $this->randomMachineName()); + $node = Node::load($nid); + + // Get node field original image URI. + $fid = $node->get($field_name)->target_id; + $original_uri = File::load($fid)->getFileUri(); + + // Test that image is displayed using newly created style. + $this->drupalGet('node/' . $nid); + $this->assertRaw(file_url_transform_relative($style->buildUrl($original_uri)), format_string('Image displayed using style @style.', ['@style' => $style_name])); + + // Copy config to sync, and delete the image style. + $sync = $this->container->get('config.storage.sync'); + $active = $this->container->get('config.storage'); + // Remove the image field from the display, to avoid a dependency error + // during import. + EntityViewDisplay::load('node.article.default') + ->removeComponent($field_name) + ->save(); + $this->copyConfig($active, $sync); + $sync->delete('image.style.' . $style_name); + $this->configImporter()->import(); + + $this->assertFalse(ImageStyle::load($style_name), 'Style deleted after config import.'); + $this->assertEqual($this->getImageCount($style), 0, 'Image style was flushed after being deleted by config import.'); + } + + /** + * Tests access for the image style listing. + */ + public function testImageStyleAccess() { + $style = ImageStyle::create(['name' => 'style_foo', 'label' => $this->randomString()]); + $style->save(); + + $this->drupalGet('admin/config/media/image-styles'); + $this->clickLink(t('Edit')); + $this->assertRaw(t('Select a new effect')); + } + +} diff -r e200cb7efeb3 -r c2387f117808 core/modules/image/tests/src/Functional/ImageDimensionsTest.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/core/modules/image/tests/src/Functional/ImageDimensionsTest.php Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,299 @@ +container->get('image.factory'); + // Create a working copy of the file. + $files = $this->drupalGetTestFiles('image'); + $file = reset($files); + $original_uri = file_unmanaged_copy($file->uri, 'public://', FILE_EXISTS_RENAME); + + // Create a style. + /** @var $style \Drupal\image\ImageStyleInterface */ + $style = ImageStyle::create(['name' => 'test', 'label' => 'Test']); + $style->save(); + $generated_uri = 'public://styles/test/public/' . \Drupal::service('file_system')->basename($original_uri); + $url = file_url_transform_relative($style->buildUrl($original_uri)); + + $variables = [ + '#theme' => 'image_style', + '#style_name' => 'test', + '#uri' => $original_uri, + '#width' => 40, + '#height' => 20, + ]; + // Verify that the original image matches the hard-coded values. + $image_file = $image_factory->get($original_uri); + $this->assertEqual($image_file->getWidth(), $variables['#width']); + $this->assertEqual($image_file->getHeight(), $variables['#height']); + + // Scale an image that is wider than it is high. + $effect = [ + 'id' => 'image_scale', + 'data' => [ + 'width' => 120, + 'height' => 90, + 'upscale' => TRUE, + ], + 'weight' => 0, + ]; + + $style->addImageEffect($effect); + $style->save(); + $this->assertEqual($this->getImageTag($variables), ''); + $this->assertFalse(file_exists($generated_uri), 'Generated file does not exist.'); + $this->drupalGet($this->getAbsoluteUrl($url)); + $this->assertResponse(200, 'Image was generated at the URL.'); + $this->assertTrue(file_exists($generated_uri), 'Generated file does exist after we accessed it.'); + $image_file = $image_factory->get($generated_uri); + $this->assertEqual($image_file->getWidth(), 120); + $this->assertEqual($image_file->getHeight(), 60); + + // Rotate 90 degrees anticlockwise. + $effect = [ + 'id' => 'image_rotate', + 'data' => [ + 'degrees' => -90, + 'random' => FALSE, + ], + 'weight' => 1, + ]; + + $style->addImageEffect($effect); + $style->save(); + $this->assertEqual($this->getImageTag($variables), ''); + $this->assertFalse(file_exists($generated_uri), 'Generated file does not exist.'); + $this->drupalGet($this->getAbsoluteUrl($url)); + $this->assertResponse(200, 'Image was generated at the URL.'); + $this->assertTrue(file_exists($generated_uri), 'Generated file does exist after we accessed it.'); + $image_file = $image_factory->get($generated_uri); + $this->assertEqual($image_file->getWidth(), 60); + $this->assertEqual($image_file->getHeight(), 120); + + // Scale an image that is higher than it is wide (rotated by previous effect). + $effect = [ + 'id' => 'image_scale', + 'data' => [ + 'width' => 120, + 'height' => 90, + 'upscale' => TRUE, + ], + 'weight' => 2, + ]; + + $style->addImageEffect($effect); + $style->save(); + $this->assertEqual($this->getImageTag($variables), ''); + $this->assertFalse(file_exists($generated_uri), 'Generated file does not exist.'); + $this->drupalGet($this->getAbsoluteUrl($url)); + $this->assertResponse(200, 'Image was generated at the URL.'); + $this->assertTrue(file_exists($generated_uri), 'Generated file does exist after we accessed it.'); + $image_file = $image_factory->get($generated_uri); + $this->assertEqual($image_file->getWidth(), 45); + $this->assertEqual($image_file->getHeight(), 90); + + // Test upscale disabled. + $effect = [ + 'id' => 'image_scale', + 'data' => [ + 'width' => 400, + 'height' => 200, + 'upscale' => FALSE, + ], + 'weight' => 3, + ]; + + $style->addImageEffect($effect); + $style->save(); + $this->assertEqual($this->getImageTag($variables), ''); + $this->assertFalse(file_exists($generated_uri), 'Generated file does not exist.'); + $this->drupalGet($this->getAbsoluteUrl($url)); + $this->assertResponse(200, 'Image was generated at the URL.'); + $this->assertTrue(file_exists($generated_uri), 'Generated file does exist after we accessed it.'); + $image_file = $image_factory->get($generated_uri); + $this->assertEqual($image_file->getWidth(), 45); + $this->assertEqual($image_file->getHeight(), 90); + + // Add a desaturate effect. + $effect = [ + 'id' => 'image_desaturate', + 'data' => [], + 'weight' => 4, + ]; + + $style->addImageEffect($effect); + $style->save(); + $this->assertEqual($this->getImageTag($variables), ''); + $this->assertFalse(file_exists($generated_uri), 'Generated file does not exist.'); + $this->drupalGet($this->getAbsoluteUrl($url)); + $this->assertResponse(200, 'Image was generated at the URL.'); + $this->assertTrue(file_exists($generated_uri), 'Generated file does exist after we accessed it.'); + $image_file = $image_factory->get($generated_uri); + $this->assertEqual($image_file->getWidth(), 45); + $this->assertEqual($image_file->getHeight(), 90); + + // Add a random rotate effect. + $effect = [ + 'id' => 'image_rotate', + 'data' => [ + 'degrees' => 180, + 'random' => TRUE, + ], + 'weight' => 5, + ]; + + $style->addImageEffect($effect); + $style->save(); + $this->assertEqual($this->getImageTag($variables), ''); + $this->assertFalse(file_exists($generated_uri), 'Generated file does not exist.'); + $this->drupalGet($this->getAbsoluteUrl($url)); + $this->assertResponse(200, 'Image was generated at the URL.'); + $this->assertTrue(file_exists($generated_uri), 'Generated file does exist after we accessed it.'); + + // Add a crop effect. + $effect = [ + 'id' => 'image_crop', + 'data' => [ + 'width' => 30, + 'height' => 30, + 'anchor' => 'center-center', + ], + 'weight' => 6, + ]; + + $style->addImageEffect($effect); + $style->save(); + $this->assertEqual($this->getImageTag($variables), ''); + $this->assertFalse(file_exists($generated_uri), 'Generated file does not exist.'); + $this->drupalGet($this->getAbsoluteUrl($url)); + $this->assertResponse(200, 'Image was generated at the URL.'); + $this->assertTrue(file_exists($generated_uri), 'Generated file does exist after we accessed it.'); + $image_file = $image_factory->get($generated_uri); + $this->assertEqual($image_file->getWidth(), 30); + $this->assertEqual($image_file->getHeight(), 30); + + // Rotate to a non-multiple of 90 degrees. + $effect = [ + 'id' => 'image_rotate', + 'data' => [ + 'degrees' => 57, + 'random' => FALSE, + ], + 'weight' => 7, + ]; + + $effect_id = $style->addImageEffect($effect); + $style->save(); + // @todo Uncomment this once + // https://www.drupal.org/project/drupal/issues/2670966 is resolved. + // $this->assertEqual($this->getImageTag($variables), ''); + $this->assertFalse(file_exists($generated_uri), 'Generated file does not exist.'); + $this->drupalGet($this->getAbsoluteUrl($url)); + $this->assertResponse(200, 'Image was generated at the URL.'); + $this->assertTrue(file_exists($generated_uri), 'Generated file does exist after we accessed it.'); + $image_file = $image_factory->get($generated_uri); + // @todo Uncomment this once + // https://www.drupal.org/project/drupal/issues/2670966 is resolved. + // $this->assertEqual($image_file->getWidth(), 41); + // $this->assertEqual($image_file->getHeight(), 41); + + $effect_plugin = $style->getEffect($effect_id); + $style->deleteImageEffect($effect_plugin); + + // Ensure that an effect can unset dimensions. + $effect = [ + 'id' => 'image_module_test_null', + 'data' => [], + 'weight' => 8, + ]; + + $style->addImageEffect($effect); + $style->save(); + $this->assertEqual($this->getImageTag($variables), ''); + + // Test URI dependent image effect. + $style = ImageStyle::create(['name' => 'test_uri', 'label' => 'Test URI']); + $effect = [ + 'id' => 'image_module_test_uri_dependent', + 'data' => [], + 'weight' => 0, + ]; + $style->addImageEffect($effect); + $style->save(); + $variables = [ + '#theme' => 'image_style', + '#style_name' => 'test_uri', + '#uri' => $original_uri, + '#width' => 40, + '#height' => 20, + ]; + // PNG original image. Should be resized to 100x100. + $generated_uri = 'public://styles/test_uri/public/' . \Drupal::service('file_system')->basename($original_uri); + $url = file_url_transform_relative($style->buildUrl($original_uri)); + $this->assertEqual($this->getImageTag($variables), ''); + $this->assertFalse(file_exists($generated_uri), 'Generated file does not exist.'); + $this->drupalGet($this->getAbsoluteUrl($url)); + $this->assertResponse(200, 'Image was generated at the URL.'); + $this->assertTrue(file_exists($generated_uri), 'Generated file does exist after we accessed it.'); + $image_file = $image_factory->get($generated_uri); + $this->assertEqual($image_file->getWidth(), 100); + $this->assertEqual($image_file->getHeight(), 100); + // GIF original image. Should be resized to 50x50. + $file = $files[1]; + $original_uri = file_unmanaged_copy($file->uri, 'public://', FILE_EXISTS_RENAME); + $generated_uri = 'public://styles/test_uri/public/' . \Drupal::service('file_system')->basename($original_uri); + $url = file_url_transform_relative($style->buildUrl($original_uri)); + $variables['#uri'] = $original_uri; + $this->assertEqual($this->getImageTag($variables), ''); + $this->assertFalse(file_exists($generated_uri), 'Generated file does not exist.'); + $this->drupalGet($this->getAbsoluteUrl($url)); + $this->assertResponse(200, 'Image was generated at the URL.'); + $this->assertTrue(file_exists($generated_uri), 'Generated file does exist after we accessed it.'); + $image_file = $image_factory->get($generated_uri); + $this->assertEqual($image_file->getWidth(), 50); + $this->assertEqual($image_file->getHeight(), 50); + } + + /** + * Render an image style element. + * + * drupal_render() alters the passed $variables array by adding a new key + * '#printed' => TRUE. This prevents next call to re-render the element. We + * wrap drupal_render() in a helper protected method and pass each time a + * fresh array so that $variables won't get altered and the element is + * re-rendered each time. + */ + protected function getImageTag($variables) { + return str_replace("\n", NULL, \Drupal::service('renderer')->renderRoot($variables)); + } + +} diff -r e200cb7efeb3 -r c2387f117808 core/modules/image/tests/src/Functional/ImageFieldDefaultImagesTest.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/core/modules/image/tests/src/Functional/ImageFieldDefaultImagesTest.php Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,402 @@ +container->get('entity.manager')->getStorage('node'); + // Create files to use as the default images. + $files = $this->drupalGetTestFiles('image'); + // Create 10 files so the default image fids are not a single value. + for ($i = 1; $i <= 10; $i++) { + $filename = $this->randomMachineName() . "$i"; + $desired_filepath = 'public://' . $filename; + file_unmanaged_copy($files[0]->uri, $desired_filepath, FILE_EXISTS_ERROR); + $file = File::create(['uri' => $desired_filepath, 'filename' => $filename, 'name' => $filename]); + $file->save(); + } + $default_images = []; + foreach (['field_storage', 'field', 'field2', 'field_storage_new', 'field_new', 'field_storage_private', 'field_private'] as $image_target) { + $file = File::create((array) array_pop($files)); + $file->save(); + $default_images[$image_target] = $file; + } + + // Create an image field storage and add a field to the article content + // type. + $field_name = strtolower($this->randomMachineName()); + $storage_settings['default_image'] = [ + 'uuid' => $default_images['field_storage']->uuid(), + 'alt' => '', + 'title' => '', + 'width' => 0, + 'height' => 0, + ]; + $field_settings['default_image'] = [ + 'uuid' => $default_images['field']->uuid(), + 'alt' => '', + 'title' => '', + 'width' => 0, + 'height' => 0, + ]; + $widget_settings = [ + 'preview_image_style' => 'medium', + ]; + $field = $this->createImageField($field_name, 'article', $storage_settings, $field_settings, $widget_settings); + + // The field default image id should be 2. + $this->assertEqual($field->getSetting('default_image')['uuid'], $default_images['field']->uuid()); + + // Also test \Drupal\field\Entity\FieldConfig::getSettings(). + $this->assertEqual($field->getSettings()['default_image']['uuid'], $default_images['field']->uuid()); + + $field_storage = $field->getFieldStorageDefinition(); + + // The field storage default image id should be 1. + $this->assertEqual($field_storage->getSetting('default_image')['uuid'], $default_images['field_storage']->uuid()); + + // Also test \Drupal\field\Entity\FieldStorageConfig::getSettings(). + $this->assertEqual($field_storage->getSettings()['default_image']['uuid'], $default_images['field_storage']->uuid()); + + // Add another field with another default image to the page content type. + $field2 = FieldConfig::create([ + 'field_storage' => $field_storage, + 'bundle' => 'page', + 'label' => $field->label(), + 'required' => $field->isRequired(), + 'settings' => [ + 'default_image' => [ + 'uuid' => $default_images['field2']->uuid(), + 'alt' => '', + 'title' => '', + 'width' => 0, + 'height' => 0, + ], + ], + ]); + $field2->save(); + + $widget_settings = entity_get_form_display('node', $field->getTargetBundle(), 'default')->getComponent($field_name); + entity_get_form_display('node', 'page', 'default') + ->setComponent($field_name, $widget_settings) + ->save(); + entity_get_display('node', 'page', 'default') + ->setComponent($field_name) + ->save(); + + // Confirm the defaults are present on the article field storage settings + // form. + $field_id = $field->id(); + $this->drupalGet("admin/structure/types/manage/article/fields/$field_id/storage"); + $this->assertFieldByXpath( + '//input[@name="settings[default_image][uuid][fids]"]', + $default_images['field_storage']->id(), + format_string( + 'Article image field storage default equals expected file ID of @fid.', + ['@fid' => $default_images['field_storage']->id()] + ) + ); + // Confirm the defaults are present on the article field edit form. + $this->drupalGet("admin/structure/types/manage/article/fields/$field_id"); + $this->assertFieldByXpath( + '//input[@name="settings[default_image][uuid][fids]"]', + $default_images['field']->id(), + format_string( + 'Article image field default equals expected file ID of @fid.', + ['@fid' => $default_images['field']->id()] + ) + ); + + // Confirm the defaults are present on the page field storage settings form. + $this->drupalGet("admin/structure/types/manage/page/fields/$field_id/storage"); + $this->assertFieldByXpath( + '//input[@name="settings[default_image][uuid][fids]"]', + $default_images['field_storage']->id(), + format_string( + 'Page image field storage default equals expected file ID of @fid.', + ['@fid' => $default_images['field_storage']->id()] + ) + ); + // Confirm the defaults are present on the page field edit form. + $field2_id = $field2->id(); + $this->drupalGet("admin/structure/types/manage/page/fields/$field2_id"); + $this->assertFieldByXpath( + '//input[@name="settings[default_image][uuid][fids]"]', + $default_images['field2']->id(), + format_string( + 'Page image field default equals expected file ID of @fid.', + ['@fid' => $default_images['field2']->id()] + ) + ); + + // Confirm that the image default is shown for a new article node. + $article = $this->drupalCreateNode(['type' => 'article']); + $article_built = $this->drupalBuildEntityView($article); + $this->assertEqual( + $article_built[$field_name][0]['#item']->target_id, + $default_images['field']->id(), + format_string( + 'A new article node without an image has the expected default image file ID of @fid.', + ['@fid' => $default_images['field']->id()] + ) + ); + + // Also check that the field renders without warnings when the label is + // hidden. + EntityViewDisplay::load('node.article.default') + ->setComponent($field_name, ['label' => 'hidden', 'type' => 'image']) + ->save(); + $this->drupalGet('node/' . $article->id()); + + // Confirm that the image default is shown for a new page node. + $page = $this->drupalCreateNode(['type' => 'page']); + $page_built = $this->drupalBuildEntityView($page); + $this->assertEqual( + $page_built[$field_name][0]['#item']->target_id, + $default_images['field2']->id(), + format_string( + 'A new page node without an image has the expected default image file ID of @fid.', + ['@fid' => $default_images['field2']->id()] + ) + ); + + // Upload a new default for the field storage. + $default_image_settings = $field_storage->getSetting('default_image'); + $default_image_settings['uuid'] = $default_images['field_storage_new']->uuid(); + $field_storage->setSetting('default_image', $default_image_settings); + $field_storage->save(); + + // Confirm that the new default is used on the article field storage + // settings form. + $this->drupalGet("admin/structure/types/manage/article/fields/$field_id/storage"); + $this->assertFieldByXpath( + '//input[@name="settings[default_image][uuid][fids]"]', + $default_images['field_storage_new']->id(), + format_string( + 'Updated image field storage default equals expected file ID of @fid.', + ['@fid' => $default_images['field_storage_new']->id()] + ) + ); + + // Reload the nodes and confirm the field defaults are used. + $node_storage->resetCache([$article->id(), $page->id()]); + $article_built = $this->drupalBuildEntityView($article = $node_storage->load($article->id())); + $page_built = $this->drupalBuildEntityView($page = $node_storage->load($page->id())); + $this->assertEqual( + $article_built[$field_name][0]['#item']->target_id, + $default_images['field']->id(), + format_string( + 'An existing article node without an image has the expected default image file ID of @fid.', + ['@fid' => $default_images['field']->id()] + ) + ); + $this->assertEqual( + $page_built[$field_name][0]['#item']->target_id, + $default_images['field2']->id(), + format_string( + 'An existing page node without an image has the expected default image file ID of @fid.', + ['@fid' => $default_images['field2']->id()] + ) + ); + + // Upload a new default for the article's field. + $default_image_settings = $field->getSetting('default_image'); + $default_image_settings['uuid'] = $default_images['field_new']->uuid(); + $field->setSetting('default_image', $default_image_settings); + $field->save(); + + // Confirm the new field default is used on the article field admin form. + $this->drupalGet("admin/structure/types/manage/article/fields/$field_id"); + $this->assertFieldByXpath( + '//input[@name="settings[default_image][uuid][fids]"]', + $default_images['field_new']->id(), + format_string( + 'Updated article image field default equals expected file ID of @fid.', + ['@fid' => $default_images['field_new']->id()] + ) + ); + + // Reload the nodes. + $node_storage->resetCache([$article->id(), $page->id()]); + $article_built = $this->drupalBuildEntityView($article = $node_storage->load($article->id())); + $page_built = $this->drupalBuildEntityView($page = $node_storage->load($page->id())); + + // Confirm the article uses the new default. + $this->assertEqual( + $article_built[$field_name][0]['#item']->target_id, + $default_images['field_new']->id(), + format_string( + 'An existing article node without an image has the expected default image file ID of @fid.', + ['@fid' => $default_images['field_new']->id()] + ) + ); + // Confirm the page remains unchanged. + $this->assertEqual( + $page_built[$field_name][0]['#item']->target_id, + $default_images['field2']->id(), + format_string( + 'An existing page node without an image has the expected default image file ID of @fid.', + ['@fid' => $default_images['field2']->id()] + ) + ); + + // Confirm the default image is shown on the node form. + $file = File::load($default_images['field_new']->id()); + $this->drupalGet('node/add/article'); + $this->assertRaw($file->getFilename()); + + // Remove the field default from articles. + $default_image_settings = $field->getSetting('default_image'); + $default_image_settings['uuid'] = 0; + $field->setSetting('default_image', $default_image_settings); + $field->save(); + + // Confirm the article field default has been removed. + $this->drupalGet("admin/structure/types/manage/article/fields/$field_id"); + $this->assertFieldByXpath( + '//input[@name="settings[default_image][uuid][fids]"]', + '', + 'Updated article image field default has been successfully removed.' + ); + + // Reload the nodes. + $node_storage->resetCache([$article->id(), $page->id()]); + $article_built = $this->drupalBuildEntityView($article = $node_storage->load($article->id())); + $page_built = $this->drupalBuildEntityView($page = $node_storage->load($page->id())); + // Confirm the article uses the new field storage (not field) default. + $this->assertEqual( + $article_built[$field_name][0]['#item']->target_id, + $default_images['field_storage_new']->id(), + format_string( + 'An existing article node without an image has the expected default image file ID of @fid.', + ['@fid' => $default_images['field_storage_new']->id()] + ) + ); + // Confirm the page remains unchanged. + $this->assertEqual( + $page_built[$field_name][0]['#item']->target_id, + $default_images['field2']->id(), + format_string( + 'An existing page node without an image has the expected default image file ID of @fid.', + ['@fid' => $default_images['field2']->id()] + ) + ); + + $non_image = $this->drupalGetTestFiles('text'); + $this->drupalPostForm(NULL, ['files[settings_default_image_uuid]' => \Drupal::service('file_system')->realpath($non_image[0]->uri)], t("Upload")); + $this->assertText('The specified file text-0.txt could not be uploaded.'); + $this->assertText('Only files with the following extensions are allowed: png gif jpg jpeg.'); + + // Confirm the default image is shown on the node form. + $file = File::load($default_images['field_storage_new']->id()); + $this->drupalGet('node/add/article'); + $this->assertRaw($file->getFilename()); + + // Change the default image for the field storage and also change the upload + // destination to the private filesystem at the same time. + $default_image_settings = $field_storage->getSetting('default_image'); + $default_image_settings['uuid'] = $default_images['field_storage_private']->uuid(); + $field_storage->setSetting('default_image', $default_image_settings); + $field_storage->setSetting('uri_scheme', 'private'); + $field_storage->save(); + + // Confirm that the new default is used on the article field storage + // settings form. + $this->drupalGet("admin/structure/types/manage/article/fields/$field_id/storage"); + $this->assertFieldByXpath( + '//input[@name="settings[default_image][uuid][fids]"]', + $default_images['field_storage_private']->id(), + format_string( + 'Updated image field storage default equals expected file ID of @fid.', + ['@fid' => $default_images['field_storage_private']->id()] + ) + ); + + // Upload a new default for the article's field after setting the field + // storage upload destination to 'private'. + $default_image_settings = $field->getSetting('default_image'); + $default_image_settings['uuid'] = $default_images['field_private']->uuid(); + $field->setSetting('default_image', $default_image_settings); + $field->save(); + + // Confirm the new field field default is used on the article field + // admin form. + $this->drupalGet("admin/structure/types/manage/article/fields/$field_id"); + $this->assertFieldByXpath( + '//input[@name="settings[default_image][uuid][fids]"]', + $default_images['field_private']->id(), + format_string( + 'Updated article image field default equals expected file ID of @fid.', + ['@fid' => $default_images['field_private']->id()] + ) + ); + } + + /** + * Tests image field and field storage having an invalid default image. + */ + public function testInvalidDefaultImage() { + $field_storage = FieldStorageConfig::create([ + 'field_name' => Unicode::strtolower($this->randomMachineName()), + 'entity_type' => 'node', + 'type' => 'image', + 'settings' => [ + 'default_image' => [ + 'uuid' => 100000, + ] + ], + ]); + $field_storage->save(); + $settings = $field_storage->getSettings(); + // The non-existent default image should not be saved. + $this->assertNull($settings['default_image']['uuid']); + + $field = FieldConfig::create([ + 'field_storage' => $field_storage, + 'bundle' => 'page', + 'label' => $this->randomMachineName(), + 'settings' => [ + 'default_image' => [ + 'uuid' => 100000, + ] + ], + ]); + $field->save(); + $settings = $field->getSettings(); + // The non-existent default image should not be saved. + $this->assertNull($settings['default_image']['uuid']); + } + +} diff -r e200cb7efeb3 -r c2387f117808 core/modules/image/tests/src/Functional/ImageFieldDisplayTest.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/core/modules/image/tests/src/Functional/ImageFieldDisplayTest.php Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,473 @@ +_testImageFieldFormatters('public'); + } + + /** + * Test image formatters on node display for private files. + */ + public function testImageFieldFormattersPrivate() { + // Remove access content permission from anonymous users. + user_role_change_permissions(RoleInterface::ANONYMOUS_ID, ['access content' => FALSE]); + $this->_testImageFieldFormatters('private'); + } + + /** + * Test image formatters on node display. + */ + public function _testImageFieldFormatters($scheme) { + /** @var \Drupal\Core\Render\RendererInterface $renderer */ + $renderer = $this->container->get('renderer'); + $node_storage = $this->container->get('entity.manager')->getStorage('node'); + $field_name = strtolower($this->randomMachineName()); + $field_settings = ['alt_field_required' => 0]; + $instance = $this->createImageField($field_name, 'article', ['uri_scheme' => $scheme], $field_settings); + + // Go to manage display page. + $this->drupalGet("admin/structure/types/manage/article/display"); + + // Test for existence of link to image styles configuration. + $this->drupalPostForm(NULL, [], "{$field_name}_settings_edit"); + $this->assertLinkByHref(\Drupal::url('entity.image_style.collection'), 0, 'Link to image styles configuration is found'); + + // Remove 'administer image styles' permission from testing admin user. + $admin_user_roles = $this->adminUser->getRoles(TRUE); + user_role_change_permissions(reset($admin_user_roles), ['administer image styles' => FALSE]); + + // Go to manage display page again. + $this->drupalGet("admin/structure/types/manage/article/display"); + + // Test for absence of link to image styles configuration. + $this->drupalPostForm(NULL, [], "{$field_name}_settings_edit"); + $this->assertNoLinkByHref(\Drupal::url('entity.image_style.collection'), 'Link to image styles configuration is absent when permissions are insufficient'); + + // Restore 'administer image styles' permission to testing admin user + user_role_change_permissions(reset($admin_user_roles), ['administer image styles' => TRUE]); + + // Create a new node with an image attached. + $test_image = current($this->drupalGetTestFiles('image')); + + // Ensure that preview works. + $this->previewNodeImage($test_image, $field_name, 'article'); + + // After previewing, make the alt field required. It cannot be required + // during preview because the form validation will fail. + $instance->setSetting('alt_field_required', 1); + $instance->save(); + + // Create alt text for the image. + $alt = $this->randomMachineName(); + + // Save node. + $nid = $this->uploadNodeImage($test_image, $field_name, 'article', $alt); + $node_storage->resetCache([$nid]); + $node = $node_storage->load($nid); + + // Test that the default formatter is being used. + $file = $node->{$field_name}->entity; + $image_uri = $file->getFileUri(); + $image = [ + '#theme' => 'image', + '#uri' => $image_uri, + '#width' => 40, + '#height' => 20, + '#alt' => $alt, + ]; + $default_output = str_replace("\n", NULL, $renderer->renderRoot($image)); + $this->assertRaw($default_output, 'Default formatter displaying correctly on full node view.'); + + // Test the image linked to file formatter. + $display_options = [ + 'type' => 'image', + 'settings' => ['image_link' => 'file'], + ]; + $display = entity_get_display('node', $node->getType(), 'default'); + $display->setComponent($field_name, $display_options) + ->save(); + + $image = [ + '#theme' => 'image', + '#uri' => $image_uri, + '#width' => 40, + '#height' => 20, + '#alt' => $alt, + ]; + $default_output = '' . $renderer->renderRoot($image) . ''; + $this->drupalGet('node/' . $nid); + $this->assertCacheTag($file->getCacheTags()[0]); + // @todo Remove in https://www.drupal.org/node/2646744. + $this->assertCacheContext('url.site'); + $cache_tags_header = $this->drupalGetHeader('X-Drupal-Cache-Tags'); + $this->assertTrue(!preg_match('/ image_style\:/', $cache_tags_header), 'No image style cache tag found.'); + $this->assertRaw($default_output, 'Image linked to file formatter displaying correctly on full node view.'); + // Verify that the image can be downloaded. + $this->assertEqual(file_get_contents($test_image->uri), $this->drupalGet(file_create_url($image_uri)), 'File was downloaded successfully.'); + if ($scheme == 'private') { + // Only verify HTTP headers when using private scheme and the headers are + // sent by Drupal. + $this->assertEqual($this->drupalGetHeader('Content-Type'), 'image/png', 'Content-Type header was sent.'); + $this->assertTrue(strstr($this->drupalGetHeader('Cache-Control'), 'private') !== FALSE, 'Cache-Control header was sent.'); + + // Log out and try to access the file. + $this->drupalLogout(); + $this->drupalGet(file_create_url($image_uri)); + $this->assertResponse('403', 'Access denied to original image as anonymous user.'); + + // Log in again. + $this->drupalLogin($this->adminUser); + } + + // Test the image linked to content formatter. + $display_options['settings']['image_link'] = 'content'; + $display->setComponent($field_name, $display_options) + ->save(); + $image = [ + '#theme' => 'image', + '#uri' => $image_uri, + '#width' => 40, + '#height' => 20, + ]; + $this->drupalGet('node/' . $nid); + $this->assertCacheTag($file->getCacheTags()[0]); + $cache_tags_header = $this->drupalGetHeader('X-Drupal-Cache-Tags'); + $this->assertTrue(!preg_match('/ image_style\:/', $cache_tags_header), 'No image style cache tag found.'); + $elements = $this->xpath( + '//a[@href=:path]/img[@src=:url and @alt=:alt and @width=:width and @height=:height]', + [ + ':path' => $node->url(), + ':url' => file_url_transform_relative(file_create_url($image['#uri'])), + ':width' => $image['#width'], + ':height' => $image['#height'], + ':alt' => $alt, + ] + ); + $this->assertEqual(count($elements), 1, 'Image linked to content formatter displaying correctly on full node view.'); + + // Test the image style 'thumbnail' formatter. + $display_options['settings']['image_link'] = ''; + $display_options['settings']['image_style'] = 'thumbnail'; + $display->setComponent($field_name, $display_options) + ->save(); + + // Ensure the derivative image is generated so we do not have to deal with + // image style callback paths. + $this->drupalGet(ImageStyle::load('thumbnail')->buildUrl($image_uri)); + $image_style = [ + '#theme' => 'image_style', + '#uri' => $image_uri, + '#width' => 40, + '#height' => 20, + '#style_name' => 'thumbnail', + '#alt' => $alt, + ]; + $default_output = $renderer->renderRoot($image_style); + $this->drupalGet('node/' . $nid); + $image_style = ImageStyle::load('thumbnail'); + $this->assertCacheTag($image_style->getCacheTags()[0]); + $this->assertRaw($default_output, 'Image style thumbnail formatter displaying correctly on full node view.'); + + if ($scheme == 'private') { + // Log out and try to access the file. + $this->drupalLogout(); + $this->drupalGet(ImageStyle::load('thumbnail')->buildUrl($image_uri)); + $this->assertResponse('403', 'Access denied to image style thumbnail as anonymous user.'); + } + + // Test the image URL formatter without an image style. + $display_options = [ + 'type' => 'image_url', + 'settings' => ['image_style' => ''], + ]; + $expected_url = file_url_transform_relative(file_create_url($image_uri)); + $this->assertEqual($expected_url, $node->{$field_name}->view($display_options)[0]['#markup']); + + // Test the image URL formatter with an image style. + $display_options['settings']['image_style'] = 'thumbnail'; + $expected_url = file_url_transform_relative(ImageStyle::load('thumbnail')->buildUrl($image_uri)); + $this->assertEqual($expected_url, $node->{$field_name}->view($display_options)[0]['#markup']); + } + + /** + * Tests for image field settings. + */ + public function testImageFieldSettings() { + /** @var \Drupal\Core\Render\RendererInterface $renderer */ + $renderer = $this->container->get('renderer'); + $node_storage = $this->container->get('entity.manager')->getStorage('node'); + $test_image = current($this->drupalGetTestFiles('image')); + list(, $test_image_extension) = explode('.', $test_image->filename); + $field_name = strtolower($this->randomMachineName()); + $field_settings = [ + 'alt_field' => 1, + 'file_extensions' => $test_image_extension, + 'max_filesize' => '50 KB', + 'max_resolution' => '100x100', + 'min_resolution' => '10x10', + 'title_field' => 1, + ]; + $widget_settings = [ + 'preview_image_style' => 'medium', + ]; + $field = $this->createImageField($field_name, 'article', [], $field_settings, $widget_settings); + + // Verify that the min/max resolution set on the field are properly + // extracted, and displayed, on the image field's configuration form. + $this->drupalGet('admin/structure/types/manage/article/fields/' . $field->id()); + $this->assertFieldByName('settings[max_resolution][x]', '100', 'Expected max resolution X value of 100.'); + $this->assertFieldByName('settings[max_resolution][y]', '100', 'Expected max resolution Y value of 100.'); + $this->assertFieldByName('settings[min_resolution][x]', '10', 'Expected min resolution X value of 10.'); + $this->assertFieldByName('settings[min_resolution][y]', '10', 'Expected min resolution Y value of 10.'); + + $this->drupalGet('node/add/article'); + $this->assertText(t('50 KB limit.'), 'Image widget max file size is displayed on article form.'); + $this->assertText(t('Allowed types: @extensions.', ['@extensions' => $test_image_extension]), 'Image widget allowed file types displayed on article form.'); + $this->assertText(t('Images must be larger than 10x10 pixels. Images larger than 100x100 pixels will be resized.'), 'Image widget allowed resolution displayed on article form.'); + + // We have to create the article first and then edit it because the alt + // and title fields do not display until the image has been attached. + + // Create alt text for the image. + $alt = $this->randomMachineName(); + + $nid = $this->uploadNodeImage($test_image, $field_name, 'article', $alt); + $this->drupalGet('node/' . $nid . '/edit'); + + // Verify that the optional fields alt & title are saved & filled. + $this->assertFieldByName($field_name . '[0][alt]', $alt, 'Alt field displayed on article form.'); + $this->assertFieldByName($field_name . '[0][title]', '', 'Title field displayed on article form.'); + + // Verify that the attached image is being previewed using the 'medium' + // style. + $node_storage->resetCache([$nid]); + $node = $node_storage->load($nid); + $file = $node->{$field_name}->entity; + + $url = file_url_transform_relative(file_create_url(ImageStyle::load('medium')->buildUrl($file->getFileUri()))); + $this->assertTrue($this->cssSelect('img[width=40][height=20][class=image-style-medium][src="' . $url . '"]')); + + // Add alt/title fields to the image and verify that they are displayed. + $image = [ + '#theme' => 'image', + '#uri' => $file->getFileUri(), + '#alt' => $alt, + '#title' => $this->randomMachineName(), + '#width' => 40, + '#height' => 20, + ]; + $edit = [ + $field_name . '[0][alt]' => $image['#alt'], + $field_name . '[0][title]' => $image['#title'], + ]; + $this->drupalPostForm('node/' . $nid . '/edit', $edit, t('Save')); + $default_output = str_replace("\n", NULL, $renderer->renderRoot($image)); + $this->assertRaw($default_output, 'Image displayed using user supplied alt and title attributes.'); + + // Verify that alt/title longer than allowed results in a validation error. + $test_size = 2000; + $edit = [ + $field_name . '[0][alt]' => $this->randomMachineName($test_size), + $field_name . '[0][title]' => $this->randomMachineName($test_size), + ]; + $this->drupalPostForm('node/' . $nid . '/edit', $edit, t('Save')); + $schema = $field->getFieldStorageDefinition()->getSchema(); + $this->assertRaw(t('Alternative text cannot be longer than %max characters but is currently %length characters long.', [ + '%max' => $schema['columns']['alt']['length'], + '%length' => $test_size, + ])); + $this->assertRaw(t('Title cannot be longer than %max characters but is currently %length characters long.', [ + '%max' => $schema['columns']['title']['length'], + '%length' => $test_size, + ])); + + // Set cardinality to unlimited and add upload a second image. + // The image widget is extending on the file widget, but the image field + // type does not have the 'display_field' setting which is expected by + // the file widget. This resulted in notices before when cardinality is not + // 1, so we need to make sure the file widget prevents these notices by + // providing all settings, even if they are not used. + // @see FileWidget::formMultipleElements(). + $this->drupalPostForm('admin/structure/types/manage/article/fields/node.article.' . $field_name . '/storage', ['cardinality' => FieldStorageDefinitionInterface::CARDINALITY_UNLIMITED], t('Save field settings')); + $edit = [ + 'files[' . $field_name . '_1][]' => \Drupal::service('file_system')->realpath($test_image->uri), + ]; + $this->drupalPostForm('node/' . $node->id() . '/edit', $edit, t('Save')); + // Add the required alt text. + $this->drupalPostForm(NULL, [$field_name . '[1][alt]' => $alt], t('Save')); + $this->assertText(format_string('Article @title has been updated.', ['@title' => $node->getTitle()])); + + // Assert ImageWidget::process() calls FieldWidget::process(). + $this->drupalGet('node/' . $node->id() . '/edit'); + $edit = [ + 'files[' . $field_name . '_2][]' => \Drupal::service('file_system')->realpath($test_image->uri), + ]; + $this->drupalPostForm(NULL, $edit, $field_name . '_2_upload_button'); + $this->assertSession()->elementNotExists('css', 'input[name="files[' . $field_name . '_2][]"]'); + $this->assertSession()->elementExists('css', 'input[name="files[' . $field_name . '_3][]"]'); + } + + /** + * Test use of a default image with an image field. + */ + public function testImageFieldDefaultImage() { + /** @var \Drupal\Core\Render\RendererInterface $renderer */ + $renderer = $this->container->get('renderer'); + + $node_storage = $this->container->get('entity.manager')->getStorage('node'); + // Create a new image field. + $field_name = strtolower($this->randomMachineName()); + $this->createImageField($field_name, 'article'); + + // Create a new node, with no images and verify that no images are + // displayed. + $node = $this->drupalCreateNode(['type' => 'article']); + $this->drupalGet('node/' . $node->id()); + // Verify that no image is displayed on the page by checking for the class + // that would be used on the image field. + $this->assertNoPattern('
    ', 'No image displayed when no image is attached and no default image specified.'); + $cache_tags_header = $this->drupalGetHeader('X-Drupal-Cache-Tags'); + $this->assertTrue(!preg_match('/ image_style\:/', $cache_tags_header), 'No image style cache tag found.'); + + // Add a default image to the public image field. + $images = $this->drupalGetTestFiles('image'); + $alt = $this->randomString(512); + $title = $this->randomString(1024); + $edit = [ + // Get the path of the 'image-test.png' file. + 'files[settings_default_image_uuid]' => \Drupal::service('file_system')->realpath($images[0]->uri), + 'settings[default_image][alt]' => $alt, + 'settings[default_image][title]' => $title, + ]; + $this->drupalPostForm("admin/structure/types/manage/article/fields/node.article.$field_name/storage", $edit, t('Save field settings')); + // Clear field definition cache so the new default image is detected. + \Drupal::entityManager()->clearCachedFieldDefinitions(); + $field_storage = FieldStorageConfig::loadByName('node', $field_name); + $default_image = $field_storage->getSetting('default_image'); + $file = \Drupal::entityManager()->loadEntityByUuid('file', $default_image['uuid']); + $this->assertTrue($file->isPermanent(), 'The default image status is permanent.'); + $image = [ + '#theme' => 'image', + '#uri' => $file->getFileUri(), + '#alt' => $alt, + '#title' => $title, + '#width' => 40, + '#height' => 20, + ]; + $default_output = str_replace("\n", NULL, $renderer->renderRoot($image)); + $this->drupalGet('node/' . $node->id()); + $this->assertCacheTag($file->getCacheTags()[0]); + $cache_tags_header = $this->drupalGetHeader('X-Drupal-Cache-Tags'); + $this->assertTrue(!preg_match('/ image_style\:/', $cache_tags_header), 'No image style cache tag found.'); + $this->assertRaw($default_output, 'Default image displayed when no user supplied image is present.'); + + // Create a node with an image attached and ensure that the default image + // is not displayed. + + // Create alt text for the image. + $alt = $this->randomMachineName(); + + // Upload the 'image-test.gif' file. + $nid = $this->uploadNodeImage($images[2], $field_name, 'article', $alt); + $node_storage->resetCache([$nid]); + $node = $node_storage->load($nid); + $file = $node->{$field_name}->entity; + $image = [ + '#theme' => 'image', + '#uri' => $file->getFileUri(), + '#width' => 40, + '#height' => 20, + '#alt' => $alt, + ]; + $image_output = str_replace("\n", NULL, $renderer->renderRoot($image)); + $this->drupalGet('node/' . $nid); + $this->assertCacheTag($file->getCacheTags()[0]); + $cache_tags_header = $this->drupalGetHeader('X-Drupal-Cache-Tags'); + $this->assertTrue(!preg_match('/ image_style\:/', $cache_tags_header), 'No image style cache tag found.'); + $this->assertNoRaw($default_output, 'Default image is not displayed when user supplied image is present.'); + $this->assertRaw($image_output, 'User supplied image is displayed.'); + + // Remove default image from the field and make sure it is no longer used. + // Can't use fillField cause Mink can't fill hidden fields. + $this->drupalGet("admin/structure/types/manage/article/fields/node.article.$field_name/storage"); + $this->getSession()->getPage()->find('css', 'input[name="settings[default_image][uuid][fids]"]')->setValue(0); + $this->getSession()->getPage()->pressButton(t('Save field settings')); + + // Clear field definition cache so the new default image is detected. + \Drupal::entityManager()->clearCachedFieldDefinitions(); + $field_storage = FieldStorageConfig::loadByName('node', $field_name); + $default_image = $field_storage->getSetting('default_image'); + $this->assertFalse($default_image['uuid'], 'Default image removed from field.'); + // Create an image field that uses the private:// scheme and test that the + // default image works as expected. + $private_field_name = strtolower($this->randomMachineName()); + $this->createImageField($private_field_name, 'article', ['uri_scheme' => 'private']); + // Add a default image to the new field. + $edit = [ + // Get the path of the 'image-test.gif' file. + 'files[settings_default_image_uuid]' => \Drupal::service('file_system')->realpath($images[2]->uri), + 'settings[default_image][alt]' => $alt, + 'settings[default_image][title]' => $title, + ]; + $this->drupalPostForm('admin/structure/types/manage/article/fields/node.article.' . $private_field_name . '/storage', $edit, t('Save field settings')); + // Clear field definition cache so the new default image is detected. + \Drupal::entityManager()->clearCachedFieldDefinitions(); + + $private_field_storage = FieldStorageConfig::loadByName('node', $private_field_name); + $default_image = $private_field_storage->getSetting('default_image'); + $file = \Drupal::entityManager()->loadEntityByUuid('file', $default_image['uuid']); + $this->assertEqual('private', file_uri_scheme($file->getFileUri()), 'Default image uses private:// scheme.'); + $this->assertTrue($file->isPermanent(), 'The default image status is permanent.'); + // Create a new node with no image attached and ensure that default private + // image is displayed. + $node = $this->drupalCreateNode(['type' => 'article']); + $image = [ + '#theme' => 'image', + '#uri' => $file->getFileUri(), + '#alt' => $alt, + '#title' => $title, + '#width' => 40, + '#height' => 20, + ]; + $default_output = str_replace("\n", NULL, $renderer->renderRoot($image)); + $this->drupalGet('node/' . $node->id()); + $this->assertCacheTag($file->getCacheTags()[0]); + $cache_tags_header = $this->drupalGetHeader('X-Drupal-Cache-Tags'); + $this->assertTrue(!preg_match('/ image_style\:/', $cache_tags_header), 'No image style cache tag found.'); + $this->assertRaw($default_output, 'Default private image displayed when no user supplied image is present.'); + } + +} diff -r e200cb7efeb3 -r c2387f117808 core/modules/image/tests/src/Functional/ImageFieldTestBase.php --- a/core/modules/image/tests/src/Functional/ImageFieldTestBase.php Thu Apr 26 11:26:54 2018 +0100 +++ b/core/modules/image/tests/src/Functional/ImageFieldTestBase.php Tue Jul 10 15:07:59 2018 +0100 @@ -87,10 +87,10 @@ 'title[0][value]' => $this->randomMachineName(), ]; $edit['files[' . $field_name . '_0]'] = \Drupal::service('file_system')->realpath($image->uri); - $this->drupalPostForm('node/add/' . $type, $edit, t('Save and publish')); + $this->drupalPostForm('node/add/' . $type, $edit, t('Save')); if ($alt) { // Add alt text. - $this->drupalPostForm(NULL, [$field_name . '[0][alt]' => $alt], t('Save and publish')); + $this->drupalPostForm(NULL, [$field_name . '[0][alt]' => $alt], t('Save')); } // Retrieve ID of the newly created node from the current URL. diff -r e200cb7efeb3 -r c2387f117808 core/modules/image/tests/src/Functional/ImageFieldValidateTest.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/core/modules/image/tests/src/Functional/ImageFieldValidateTest.php Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,226 @@ +container->get('file_system'); + $image_files = $this->drupalGetTestFiles('image'); + + $field_name = strtolower($this->randomMachineName()); + $this->createImageField($field_name, 'article', [], ['file_directory' => 'test-upload']); + $expected_path = 'public://test-upload'; + + // Create alt text for the image. + $alt = $this->randomMachineName(); + + // Create a node with a valid image. + $node = $this->uploadNodeImage($image_files[0], $field_name, 'article', $alt); + $this->assertTrue(file_exists($expected_path . '/' . $image_files[0]->filename)); + + // Remove the image. + $this->drupalPostForm('node/' . $node . '/edit', [], t('Remove')); + $this->drupalPostForm(NULL, [], t('Save')); + + // Get invalid image test files from simpletest. + $files = file_scan_directory(drupal_get_path('module', 'simpletest') . '/files', '/invalid-img-.*/'); + $invalid_image_files = []; + foreach ($files as $file) { + $invalid_image_files[$file->filename] = $file; + } + + // Try uploading a zero-byte image. + $zero_size_image = $invalid_image_files['invalid-img-zero-size.png']; + $edit = [ + 'files[' . $field_name . '_0]' => $file_system->realpath($zero_size_image->uri), + ]; + $this->drupalPostForm('node/' . $node . '/edit', $edit, t('Upload')); + $this->assertFalse(file_exists($expected_path . '/' . $zero_size_image->filename)); + + // Try uploading an invalid image. + $invalid_image = $invalid_image_files['invalid-img-test.png']; + $edit = [ + 'files[' . $field_name . '_0]' => $file_system->realpath($invalid_image->uri), + ]; + $this->drupalPostForm('node/' . $node . '/edit', $edit, t('Upload')); + $this->assertFalse(file_exists($expected_path . '/' . $invalid_image->filename)); + + // Upload a valid image again. + $valid_image = $image_files[0]; + $edit = [ + 'files[' . $field_name . '_0]' => $file_system->realpath($valid_image->uri), + ]; + $this->drupalPostForm('node/' . $node . '/edit', $edit, t('Upload')); + $this->assertTrue(file_exists($expected_path . '/' . $valid_image->filename)); + } + + /** + * Test min/max resolution settings. + */ + public function testResolution() { + $field_names = [ + 0 => strtolower($this->randomMachineName()), + 1 => strtolower($this->randomMachineName()), + 2 => strtolower($this->randomMachineName()), + ]; + $min_resolution = [ + 'width' => 50, + 'height' => 50 + ]; + $max_resolution = [ + 'width' => 100, + 'height' => 100 + ]; + $no_height_min_resolution = [ + 'width' => 50, + 'height' => NULL + ]; + $no_height_max_resolution = [ + 'width' => 100, + 'height' => NULL + ]; + $no_width_min_resolution = [ + 'width' => NULL, + 'height' => 50 + ]; + $no_width_max_resolution = [ + 'width' => NULL, + 'height' => 100 + ]; + $field_settings = [ + 0 => $this->getFieldSettings($min_resolution, $max_resolution), + 1 => $this->getFieldSettings($no_height_min_resolution, $no_height_max_resolution), + 2 => $this->getFieldSettings($no_width_min_resolution, $no_width_max_resolution), + ]; + $this->createImageField($field_names[0], 'article', [], $field_settings[0]); + $this->createImageField($field_names[1], 'article', [], $field_settings[1]); + $this->createImageField($field_names[2], 'article', [], $field_settings[2]); + + // We want a test image that is too small, and a test image that is too + // big, so cycle through test image files until we have what we need. + $image_that_is_too_big = FALSE; + $image_that_is_too_small = FALSE; + $image_factory = $this->container->get('image.factory'); + foreach ($this->drupalGetTestFiles('image') as $image) { + $image_file = $image_factory->get($image->uri); + if ($image_file->getWidth() > $max_resolution['width']) { + $image_that_is_too_big = $image; + } + if ($image_file->getWidth() < $min_resolution['width']) { + $image_that_is_too_small = $image; + $image_that_is_too_small_file = $image_file; + } + if ($image_that_is_too_small && $image_that_is_too_big) { + break; + } + } + $this->uploadNodeImage($image_that_is_too_small, $field_names[0], 'article'); + $this->assertRaw(t('The specified file %name could not be uploaded.', ['%name' => $image_that_is_too_small->filename])); + $this->assertRaw(t('The image is too small. The minimum dimensions are %dimensions pixels and the image size is %widthx%height pixels.', [ + '%dimensions' => '50x50', + '%width' => $image_that_is_too_small_file->getWidth(), + '%height' => $image_that_is_too_small_file->getHeight(), + ])); + $this->uploadNodeImage($image_that_is_too_big, $field_names[0], 'article'); + $this->assertText(t('The image was resized to fit within the maximum allowed dimensions of 100x100 pixels.')); + $this->uploadNodeImage($image_that_is_too_small, $field_names[1], 'article'); + $this->assertRaw(t('The specified file %name could not be uploaded.', ['%name' => $image_that_is_too_small->filename])); + $this->uploadNodeImage($image_that_is_too_big, $field_names[1], 'article'); + $this->assertText(t('The image was resized to fit within the maximum allowed width of 100 pixels.')); + $this->uploadNodeImage($image_that_is_too_small, $field_names[2], 'article'); + $this->assertRaw(t('The specified file %name could not be uploaded.', ['%name' => $image_that_is_too_small->filename])); + $this->uploadNodeImage($image_that_is_too_big, $field_names[2], 'article'); + $this->assertText(t('The image was resized to fit within the maximum allowed height of 100 pixels.')); + } + + /** + * Test that required alt/title fields gets validated right. + */ + public function testRequiredAttributes() { + $field_name = strtolower($this->randomMachineName()); + $field_settings = [ + 'alt_field' => 1, + 'alt_field_required' => 1, + 'title_field' => 1, + 'title_field_required' => 1, + 'required' => 1, + ]; + $instance = $this->createImageField($field_name, 'article', [], $field_settings); + $images = $this->drupalGetTestFiles('image'); + // Let's just use the first image. + $image = $images[0]; + $this->uploadNodeImage($image, $field_name, 'article'); + + // Look for form-required for the alt text. + $elements = $this->xpath('//label[@for="edit-' . $field_name . '-0-alt" and @class="js-form-required form-required"]/following-sibling::input[@id="edit-' . $field_name . '-0-alt"]'); + + $this->assertTrue(isset($elements[0]), 'Required marker is shown for the required alt text.'); + + $elements = $this->xpath('//label[@for="edit-' . $field_name . '-0-title" and @class="js-form-required form-required"]/following-sibling::input[@id="edit-' . $field_name . '-0-title"]'); + + $this->assertTrue(isset($elements[0]), 'Required marker is shown for the required title text.'); + + $this->assertText(t('Alternative text field is required.')); + $this->assertText(t('Title field is required.')); + + $instance->setSetting('alt_field_required', 0); + $instance->setSetting('title_field_required', 0); + $instance->save(); + + $edit = [ + 'title[0][value]' => $this->randomMachineName(), + ]; + $this->drupalPostForm('node/add/article', $edit, t('Save')); + + $this->assertNoText(t('Alternative text field is required.')); + $this->assertNoText(t('Title field is required.')); + + $instance->setSetting('required', 0); + $instance->setSetting('alt_field_required', 1); + $instance->setSetting('title_field_required', 1); + $instance->save(); + + $edit = [ + 'title[0][value]' => $this->randomMachineName(), + ]; + $this->drupalPostForm('node/add/article', $edit, t('Save')); + + $this->assertNoText(t('Alternative text field is required.')); + $this->assertNoText(t('Title field is required.')); + } + + /** + * Returns field settings. + * + * @param int[] $min_resolution + * The minimum width and height resolution setting. + * @param int[] $max_resolution + * The maximum width and height resolution setting. + * + * @return array + */ + protected function getFieldSettings($min_resolution, $max_resolution) { + return [ + 'max_resolution' => $max_resolution['width'] . 'x' . $max_resolution['height'], + 'min_resolution' => $min_resolution['width'] . 'x' . $min_resolution['height'], + 'alt_field' => 0, + ]; + } + +} diff -r e200cb7efeb3 -r c2387f117808 core/modules/image/tests/src/Functional/ImageOnTranslatedEntityTest.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/core/modules/image/tests/src/Functional/ImageOnTranslatedEntityTest.php Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,234 @@ +config('file.settings')->set('make_unused_managed_files_temporary', TRUE)->save(); + + // Create the "Basic page" node type. + // @todo Remove the disabling of new revision creation in + // https://www.drupal.org/node/1239558. + $this->drupalCreateContentType(['type' => 'basicpage', 'name' => 'Basic page', 'new_revision' => FALSE]); + + // Create a image field on the "Basic page" node type. + $this->fieldName = strtolower($this->randomMachineName()); + $this->createImageField($this->fieldName, 'basicpage', [], ['title_field' => 1]); + + // Create and log in user. + $permissions = [ + 'access administration pages', + 'administer content translation', + 'administer content types', + 'administer languages', + 'administer node fields', + 'create content translations', + 'create basicpage content', + 'edit any basicpage content', + 'translate any entity', + 'delete any basicpage content', + ]; + $admin_user = $this->drupalCreateUser($permissions); + $this->drupalLogin($admin_user); + + // Add a second and third language. + $edit = []; + $edit['predefined_langcode'] = 'fr'; + $this->drupalPostForm('admin/config/regional/language/add', $edit, t('Add language')); + + $edit = []; + $edit['predefined_langcode'] = 'nl'; + $this->drupalPostForm('admin/config/regional/language/add', $edit, t('Add language')); + } + + /** + * Tests synced file fields on translated nodes. + */ + public function testSyncedImages() { + // Enable translation for "Basic page" nodes. + $edit = [ + 'entity_types[node]' => 1, + 'settings[node][basicpage][translatable]' => 1, + "settings[node][basicpage][fields][$this->fieldName]" => 1, + "settings[node][basicpage][columns][$this->fieldName][file]" => 1, + // Explicitly disable alt and title since the javascript disables the + // checkboxes on the form. + "settings[node][basicpage][columns][$this->fieldName][alt]" => FALSE, + "settings[node][basicpage][columns][$this->fieldName][title]" => FALSE, + ]; + $this->drupalPostForm('admin/config/regional/content-language', $edit, 'Save configuration'); + + // Verify that the image field on the "Basic basic" node type is + // translatable. + $definitions = \Drupal::entityManager()->getFieldDefinitions('node', 'basicpage'); + $this->assertTrue($definitions[$this->fieldName]->isTranslatable(), 'Node image field is translatable.'); + + // Create a default language node. + $default_language_node = $this->drupalCreateNode(['type' => 'basicpage', 'title' => 'Lost in translation']); + + // Edit the node to upload a file. + $edit = []; + $name = 'files[' . $this->fieldName . '_0]'; + $edit[$name] = \Drupal::service('file_system')->realpath($this->drupalGetTestFiles('image')[0]->uri); + $this->drupalPostForm('node/' . $default_language_node->id() . '/edit', $edit, t('Save')); + $edit = [$this->fieldName . '[0][alt]' => 'Lost in translation image', $this->fieldName . '[0][title]' => 'Lost in translation image title']; + $this->drupalPostForm(NULL, $edit, t('Save')); + $first_fid = $this->getLastFileId(); + + // Translate the node into French: remove the existing file. + $this->drupalPostForm('node/' . $default_language_node->id() . '/translations/add/en/fr', [], t('Remove')); + + // Upload a different file. + $edit = []; + $edit['title[0][value]'] = 'Scarlett Johansson'; + $name = 'files[' . $this->fieldName . '_0]'; + $edit[$name] = \Drupal::service('file_system')->realpath($this->drupalGetTestFiles('image')[1]->uri); + $this->drupalPostForm(NULL, $edit, t('Save (this translation)')); + $edit = [$this->fieldName . '[0][alt]' => 'Scarlett Johansson image', $this->fieldName . '[0][title]' => 'Scarlett Johansson image title']; + $this->drupalPostForm(NULL, $edit, t('Save (this translation)')); + // This inspects the HTML after the post of the translation, the image + // should be displayed on the original node. + $this->assertRaw('alt="Lost in translation image"'); + $this->assertRaw('title="Lost in translation image title"'); + $second_fid = $this->getLastFileId(); + // View the translated node. + $this->drupalGet('fr/node/' . $default_language_node->id()); + $this->assertRaw('alt="Scarlett Johansson image"'); + + \Drupal::entityTypeManager()->getStorage('file')->resetCache(); + + /* @var $file \Drupal\file\FileInterface */ + + // Ensure the file status of the first file permanent. + $file = File::load($first_fid); + $this->assertTrue($file->isPermanent()); + + // Ensure the file status of the second file is permanent. + $file = File::load($second_fid); + $this->assertTrue($file->isPermanent()); + + // Translate the node into dutch: remove the existing file. + $this->drupalPostForm('node/' . $default_language_node->id() . '/translations/add/en/nl', [], t('Remove')); + + // Upload a different file. + $edit = []; + $edit['title[0][value]'] = 'Akiko Takeshita'; + $name = 'files[' . $this->fieldName . '_0]'; + $edit[$name] = \Drupal::service('file_system')->realpath($this->drupalGetTestFiles('image')[2]->uri); + $this->drupalPostForm(NULL, $edit, t('Save (this translation)')); + $edit = [$this->fieldName . '[0][alt]' => 'Akiko Takeshita image', $this->fieldName . '[0][title]' => 'Akiko Takeshita image title']; + $this->drupalPostForm(NULL, $edit, t('Save (this translation)')); + $third_fid = $this->getLastFileId(); + + \Drupal::entityTypeManager()->getStorage('file')->resetCache(); + + // Ensure the first file is untouched. + $file = File::load($first_fid); + $this->assertTrue($file->isPermanent(), 'First file still exists and is permanent.'); + // This inspects the HTML after the post of the translation, the image + // should be displayed on the original node. + $this->assertRaw('alt="Lost in translation image"'); + $this->assertRaw('title="Lost in translation image title"'); + // View the translated node. + $this->drupalGet('nl/node/' . $default_language_node->id()); + $this->assertRaw('alt="Akiko Takeshita image"'); + $this->assertRaw('title="Akiko Takeshita image title"'); + + // Ensure the file status of the second file is permanent. + $file = File::load($second_fid); + $this->assertTrue($file->isPermanent()); + + // Ensure the file status of the third file is permanent. + $file = File::load($third_fid); + $this->assertTrue($file->isPermanent()); + + // Edit the second translation: remove the existing file. + $this->drupalPostForm('fr/node/' . $default_language_node->id() . '/edit', [], t('Remove')); + + // Upload a different file. + $edit = []; + $edit['title[0][value]'] = 'Giovanni Ribisi'; + $name = 'files[' . $this->fieldName . '_0]'; + $edit[$name] = \Drupal::service('file_system')->realpath($this->drupalGetTestFiles('image')[3]->uri); + $this->drupalPostForm(NULL, $edit, t('Save (this translation)')); + $name = $this->fieldName . '[0][alt]'; + + $edit = [$name => 'Giovanni Ribisi image']; + $this->drupalPostForm(NULL, $edit, t('Save (this translation)')); + $replaced_second_fid = $this->getLastFileId(); + + \Drupal::entityTypeManager()->getStorage('file')->resetCache(); + + // Ensure the first and third files are untouched. + $file = File::load($first_fid); + $this->assertTrue($file->isPermanent(), 'First file still exists and is permanent.'); + + $file = File::load($third_fid); + $this->assertTrue($file->isPermanent()); + + // Ensure the file status of the replaced second file is permanent. + $file = File::load($replaced_second_fid); + $this->assertTrue($file->isPermanent()); + + // Delete the third translation. + $this->drupalPostForm('nl/node/' . $default_language_node->id() . '/delete', [], t('Delete Dutch translation')); + + \Drupal::entityTypeManager()->getStorage('file')->resetCache(); + + // Ensure the first and replaced second files are untouched. + $file = File::load($first_fid); + $this->assertTrue($file->isPermanent(), 'First file still exists and is permanent.'); + + $file = File::load($replaced_second_fid); + $this->assertTrue($file->isPermanent()); + + // Ensure the file status of the third file is now temporary. + $file = File::load($third_fid); + $this->assertTrue($file->isTemporary()); + + // Delete the all translations. + $this->drupalPostForm('node/' . $default_language_node->id() . '/delete', [], t('Delete all translations')); + + \Drupal::entityTypeManager()->getStorage('file')->resetCache(); + + // Ensure the file status of the all files are now temporary. + $file = File::load($first_fid); + $this->assertTrue($file->isTemporary(), 'First file still exists and is temporary.'); + + $file = File::load($replaced_second_fid); + $this->assertTrue($file->isTemporary()); + } + +} diff -r e200cb7efeb3 -r c2387f117808 core/modules/image/tests/src/Functional/ImageStyleFlushTest.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/core/modules/image/tests/src/Functional/ImageStyleFlushTest.php Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,116 @@ +drupalGetTestFiles('image'); + $file = reset($files); + } + + // Make sure we have an image in our wrapper testing file directory. + $source_uri = file_unmanaged_copy($file->uri, $wrapper . '://'); + // Build the derivative image. + $derivative_uri = $style->buildUri($source_uri); + $derivative = $style->createDerivative($source_uri, $derivative_uri); + + return $derivative ? $derivative_uri : FALSE; + } + + /** + * Count the number of images currently created for a style in a wrapper. + */ + public function getImageCount($style, $wrapper) { + return count(file_scan_directory($wrapper . '://styles/' . $style->id(), '/.*/')); + } + + /** + * General test to flush a style. + */ + public function testFlush() { + + // Setup a style to be created and effects to add to it. + $style_name = strtolower($this->randomMachineName(10)); + $style_label = $this->randomString(); + $style_path = 'admin/config/media/image-styles/manage/' . $style_name; + $effect_edits = [ + 'image_resize' => [ + 'data[width]' => 100, + 'data[height]' => 101, + ], + 'image_scale' => [ + 'data[width]' => 110, + 'data[height]' => 111, + 'data[upscale]' => 1, + ], + ]; + + // Add style form. + $edit = [ + 'name' => $style_name, + 'label' => $style_label, + ]; + $this->drupalPostForm('admin/config/media/image-styles/add', $edit, t('Create new style')); + + // Add each sample effect to the style. + foreach ($effect_edits as $effect => $edit) { + // Add the effect. + $this->drupalPostForm($style_path, ['new' => $effect], t('Add')); + if (!empty($edit)) { + $this->drupalPostForm(NULL, $edit, t('Add effect')); + } + } + + // Load the saved image style. + $style = ImageStyle::load($style_name); + + // Create an image for the 'public' wrapper. + $image_path = $this->createSampleImage($style, 'public'); + // Expecting to find 2 images, one is the sample.png image shown in + // image style preview. + $this->assertEqual($this->getImageCount($style, 'public'), 2, format_string('Image style %style image %file successfully generated.', ['%style' => $style->label(), '%file' => $image_path])); + + // Create an image for the 'private' wrapper. + $image_path = $this->createSampleImage($style, 'private'); + $this->assertEqual($this->getImageCount($style, 'private'), 1, format_string('Image style %style image %file successfully generated.', ['%style' => $style->label(), '%file' => $image_path])); + + // Remove the 'image_scale' effect and updates the style, which in turn + // forces an image style flush. + $style_path = 'admin/config/media/image-styles/manage/' . $style->id(); + $uuids = []; + foreach ($style->getEffects() as $uuid => $effect) { + $uuids[$effect->getPluginId()] = $uuid; + } + $this->drupalPostForm($style_path . '/effects/' . $uuids['image_scale'] . '/delete', [], t('Delete')); + $this->assertResponse(200); + $this->drupalPostForm($style_path, [], t('Update style')); + $this->assertResponse(200); + + // Post flush, expected 1 image in the 'public' wrapper (sample.png). + $this->assertEqual($this->getImageCount($style, 'public'), 1, format_string('Image style %style flushed correctly for %wrapper wrapper.', ['%style' => $style->label(), '%wrapper' => 'public'])); + + // Post flush, expected no image in the 'private' wrapper. + $this->assertEqual($this->getImageCount($style, 'private'), 0, format_string('Image style %style flushed correctly for %wrapper wrapper.', ['%style' => $style->label(), '%wrapper' => 'private'])); + } + +} diff -r e200cb7efeb3 -r c2387f117808 core/modules/image/tests/src/Functional/ImageStylesPathAndUrlTest.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/core/modules/image/tests/src/Functional/ImageStylesPathAndUrlTest.php Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,320 @@ +style = ImageStyle::create([ + 'name' => 'style_foo', + 'label' => $this->randomString(), + ]); + $this->style->save(); + + // Create a new language. + ConfigurableLanguage::createFromLangcode('fr')->save(); + } + + /** + * Tests \Drupal\image\ImageStyleInterface::buildUri(). + */ + public function testImageStylePath() { + $scheme = 'public'; + $actual = $this->style->buildUri("$scheme://foo/bar.gif"); + $expected = "$scheme://styles/" . $this->style->id() . "/$scheme/foo/bar.gif"; + $this->assertEqual($actual, $expected, 'Got the path for a file URI.'); + + $actual = $this->style->buildUri('foo/bar.gif'); + $expected = "$scheme://styles/" . $this->style->id() . "/$scheme/foo/bar.gif"; + $this->assertEqual($actual, $expected, 'Got the path for a relative file path.'); + } + + /** + * Tests an image style URL using the "public://" scheme. + */ + public function testImageStyleUrlAndPathPublic() { + $this->doImageStyleUrlAndPathTests('public'); + } + + /** + * Tests an image style URL using the "private://" scheme. + */ + public function testImageStyleUrlAndPathPrivate() { + $this->doImageStyleUrlAndPathTests('private'); + } + + /** + * Tests an image style URL with the "public://" scheme and unclean URLs. + */ + public function testImageStyleUrlAndPathPublicUnclean() { + $this->doImageStyleUrlAndPathTests('public', FALSE); + } + + /** + * Tests an image style URL with the "private://" schema and unclean URLs. + */ + public function testImageStyleUrlAndPathPrivateUnclean() { + $this->doImageStyleUrlAndPathTests('private', FALSE); + } + + /** + * Tests an image style URL with the "public://" schema and language prefix. + */ + public function testImageStyleUrlAndPathPublicLanguage() { + $this->doImageStyleUrlAndPathTests('public', TRUE, TRUE, 'fr'); + } + + /** + * Tests an image style URL with the "private://" schema and language prefix. + */ + public function testImageStyleUrlAndPathPrivateLanguage() { + $this->doImageStyleUrlAndPathTests('private', TRUE, TRUE, 'fr'); + } + + /** + * Tests an image style URL with a file URL that has an extra slash in it. + */ + public function testImageStyleUrlExtraSlash() { + $this->doImageStyleUrlAndPathTests('public', TRUE, TRUE); + } + + /** + * Tests that an invalid source image returns a 404. + */ + public function testImageStyleUrlForMissingSourceImage() { + $non_existent_uri = 'public://foo.png'; + $generated_url = $this->style->buildUrl($non_existent_uri); + $this->drupalGet($generated_url); + $this->assertResponse(404, 'Accessing an image style URL with a source image that does not exist provides a 404 error response.'); + } + + /** + * Tests building an image style URL. + */ + public function doImageStyleUrlAndPathTests($scheme, $clean_url = TRUE, $extra_slash = FALSE, $langcode = FALSE) { + $this->prepareRequestForGenerator($clean_url); + + // Make the default scheme neither "public" nor "private" to verify the + // functions work for other than the default scheme. + $this->config('system.file')->set('default_scheme', 'temporary')->save(); + + // Create the directories for the styles. + $directory = $scheme . '://styles/' . $this->style->id(); + $status = file_prepare_directory($directory, FILE_CREATE_DIRECTORY); + $this->assertNotIdentical(FALSE, $status, 'Created the directory for the generated images for the test style.'); + + // Override the language to build the URL for the correct language. + if ($langcode) { + $language_manager = \Drupal::service('language_manager'); + $language = $language_manager->getLanguage($langcode); + $language_manager->setConfigOverrideLanguage($language); + } + + // Create a working copy of the file. + $files = $this->drupalGetTestFiles('image'); + $file = array_shift($files); + $original_uri = file_unmanaged_copy($file->uri, $scheme . '://', FILE_EXISTS_RENAME); + // Let the image_module_test module know about this file, so it can claim + // ownership in hook_file_download(). + \Drupal::state()->set('image.test_file_download', $original_uri); + $this->assertNotIdentical(FALSE, $original_uri, 'Created the generated image file.'); + + // Get the URL of a file that has not been generated and try to create it. + $generated_uri = $this->style->buildUri($original_uri); + $this->assertFalse(file_exists($generated_uri), 'Generated file does not exist.'); + $generate_url = $this->style->buildUrl($original_uri, $clean_url); + + // Make sure that language prefix is never added to the image style URL. + if ($langcode) { + $this->assertTrue(strpos($generate_url, "/$langcode/") === FALSE, 'Langcode was not found in the image style URL.'); + } + + // Ensure that the tests still pass when the file is generated by accessing + // a poorly constructed (but still valid) file URL that has an extra slash + // in it. + if ($extra_slash) { + $modified_uri = str_replace('://', ':///', $original_uri); + $this->assertNotEqual($original_uri, $modified_uri, 'An extra slash was added to the generated file URI.'); + $generate_url = $this->style->buildUrl($modified_uri, $clean_url); + } + if (!$clean_url) { + $this->assertTrue(strpos($generate_url, 'index.php/') !== FALSE, 'When using non-clean URLS, the system path contains the script name.'); + } + // Add some extra chars to the token. + $this->drupalGet(str_replace(IMAGE_DERIVATIVE_TOKEN . '=', IMAGE_DERIVATIVE_TOKEN . '=Zo', $generate_url)); + $this->assertResponse(404, 'Image was inaccessible at the URL with an invalid token.'); + // Change the parameter name so the token is missing. + $this->drupalGet(str_replace(IMAGE_DERIVATIVE_TOKEN . '=', 'wrongparam=', $generate_url)); + $this->assertResponse(404, 'Image was inaccessible at the URL with a missing token.'); + + // Check that the generated URL is the same when we pass in a relative path + // rather than a URI. We need to temporarily switch the default scheme to + // match the desired scheme before testing this, then switch it back to the + // "temporary" scheme used throughout this test afterwards. + $this->config('system.file')->set('default_scheme', $scheme)->save(); + $relative_path = file_uri_target($original_uri); + $generate_url_from_relative_path = $this->style->buildUrl($relative_path, $clean_url); + $this->assertEqual($generate_url, $generate_url_from_relative_path); + $this->config('system.file')->set('default_scheme', 'temporary')->save(); + + // Fetch the URL that generates the file. + $this->drupalGet($generate_url); + $this->assertResponse(200, 'Image was generated at the URL.'); + $this->assertTrue(file_exists($generated_uri), 'Generated file does exist after we accessed it.'); + // assertRaw can't be used with string containing non UTF-8 chars. + $this->assertNotEmpty(file_get_contents($generated_uri), 'URL returns expected file.'); + $image = $this->container->get('image.factory')->get($generated_uri); + $this->assertEqual($this->drupalGetHeader('Content-Type'), $image->getMimeType(), 'Expected Content-Type was reported.'); + $this->assertEqual($this->drupalGetHeader('Content-Length'), $image->getFileSize(), 'Expected Content-Length was reported.'); + + // Check that we did not download the original file. + $original_image = $this->container->get('image.factory') + ->get($original_uri); + $this->assertNotEqual($this->drupalGetHeader('Content-Length'), $original_image->getFileSize()); + + if ($scheme == 'private') { + $this->assertEqual($this->drupalGetHeader('Expires'), 'Sun, 19 Nov 1978 05:00:00 GMT', 'Expires header was sent.'); + $this->assertNotEqual(strpos($this->drupalGetHeader('Cache-Control'), 'no-cache'), FALSE, 'Cache-Control header contains \'no-cache\' to prevent caching.'); + $this->assertEqual($this->drupalGetHeader('X-Image-Owned-By'), 'image_module_test', 'Expected custom header has been added.'); + + // Make sure that a second request to the already existing derivative + // works too. + $this->drupalGet($generate_url); + $this->assertResponse(200, 'Image was generated at the URL.'); + + // Check that the second request also returned the generated image. + $this->assertEqual($this->drupalGetHeader('Content-Length'), $image->getFileSize()); + + // Check that we did not download the original file. + $this->assertNotEqual($this->drupalGetHeader('Content-Length'), $original_image->getFileSize()); + + // Make sure that access is denied for existing style files if we do not + // have access. + \Drupal::state()->delete('image.test_file_download'); + $this->drupalGet($generate_url); + $this->assertResponse(403, 'Confirmed that access is denied for the private image style.'); + + // Repeat this with a different file that we do not have access to and + // make sure that access is denied. + $file_noaccess = array_shift($files); + $original_uri_noaccess = file_unmanaged_copy($file_noaccess->uri, $scheme . '://', FILE_EXISTS_RENAME); + $generated_uri_noaccess = $scheme . '://styles/' . $this->style->id() . '/' . $scheme . '/' . drupal_basename($original_uri_noaccess); + $this->assertFalse(file_exists($generated_uri_noaccess), 'Generated file does not exist.'); + $generate_url_noaccess = $this->style->buildUrl($original_uri_noaccess); + + $this->drupalGet($generate_url_noaccess); + $this->assertResponse(403, 'Confirmed that access is denied for the private image style.'); + // Verify that images are not appended to the response. + // Currently this test only uses PNG images. + if (strpos($generate_url, '.png') === FALSE) { + $this->fail('Confirming that private image styles are not appended require PNG file.'); + } + else { + // Check for PNG-Signature + // (cf. http://www.libpng.org/pub/png/book/chapter08.html#png.ch08.div.2) + // in the response body. + $raw = $this->getSession()->getPage()->getContent(); + $this->assertFalse(strpos($raw, chr(137) . chr(80) . chr(78) . chr(71) . chr(13) . chr(10) . chr(26) . chr(10))); + } + } + else { + $this->assertEqual($this->drupalGetHeader('Expires'), 'Sun, 19 Nov 1978 05:00:00 GMT', 'Expires header was sent.'); + $this->assertEqual(strpos($this->drupalGetHeader('Cache-Control'), 'no-cache'), FALSE, 'Cache-Control header contains \'no-cache\' to prevent caching.'); + + if ($clean_url) { + // Add some extra chars to the token. + $this->drupalGet(str_replace(IMAGE_DERIVATIVE_TOKEN . '=', IMAGE_DERIVATIVE_TOKEN . '=Zo', $generate_url)); + $this->assertResponse(200, 'Existing image was accessible at the URL with an invalid token.'); + } + } + + // Allow insecure image derivatives to be created for the remainder of this + // test. + $this->config('image.settings') + ->set('allow_insecure_derivatives', TRUE) + ->save(); + + // Create another working copy of the file. + $files = $this->drupalGetTestFiles('image'); + $file = array_shift($files); + $original_uri = file_unmanaged_copy($file->uri, $scheme . '://', FILE_EXISTS_RENAME); + // Let the image_module_test module know about this file, so it can claim + // ownership in hook_file_download(). + \Drupal::state()->set('image.test_file_download', $original_uri); + + // Suppress the security token in the URL, then get the URL of a file that + // has not been created and try to create it. Check that the security token + // is not present in the URL but that the image is still accessible. + $this->config('image.settings')->set('suppress_itok_output', TRUE)->save(); + $generated_uri = $this->style->buildUri($original_uri); + $this->assertFalse(file_exists($generated_uri), 'Generated file does not exist.'); + $generate_url = $this->style->buildUrl($original_uri, $clean_url); + $this->assertIdentical(strpos($generate_url, IMAGE_DERIVATIVE_TOKEN . '='), FALSE, 'The security token does not appear in the image style URL.'); + $this->drupalGet($generate_url); + $this->assertResponse(200, 'Image was accessible at the URL with a missing token.'); + + // Stop supressing the security token in the URL. + $this->config('image.settings')->set('suppress_itok_output', FALSE)->save(); + // Ensure allow_insecure_derivatives is enabled. + $this->assertEqual($this->config('image.settings') + ->get('allow_insecure_derivatives'), TRUE); + // Check that a security token is still required when generating a second + // image derivative using the first one as a source. + $nested_url = $this->style->buildUrl($generated_uri, $clean_url); + $matches_expected_url_format = (boolean) preg_match('/styles\/' . $this->style->id() . '\/' . $scheme . '\/styles\/' . $this->style->id() . '\/' . $scheme . '/', $nested_url); + $this->assertTrue($matches_expected_url_format, "URL for a derivative of an image style matches expected format."); + $nested_url_with_wrong_token = str_replace(IMAGE_DERIVATIVE_TOKEN . '=', 'wrongparam=', $nested_url); + $this->drupalGet($nested_url_with_wrong_token); + $this->assertResponse(404, 'Image generated from an earlier derivative was inaccessible at the URL with a missing token.'); + // Check that this restriction cannot be bypassed by adding extra slashes + // to the URL. + $this->drupalGet(substr_replace($nested_url_with_wrong_token, '//styles/', strrpos($nested_url_with_wrong_token, '/styles/'), strlen('/styles/'))); + $this->assertResponse(404, 'Image generated from an earlier derivative was inaccessible at the URL with a missing token, even with an extra forward slash in the URL.'); + $this->drupalGet(substr_replace($nested_url_with_wrong_token, '////styles/', strrpos($nested_url_with_wrong_token, '/styles/'), strlen('/styles/'))); + $this->assertResponse(404, 'Image generated from an earlier derivative was inaccessible at the URL with a missing token, even with multiple forward slashes in the URL.'); + // Make sure the image can still be generated if a correct token is used. + $this->drupalGet($nested_url); + $this->assertResponse(200, 'Image was accessible when a correct token was provided in the URL.'); + + // Check that requesting a nonexistent image does not create any new + // directories in the file system. + $directory = $scheme . '://styles/' . $this->style->id() . '/' . $scheme . '/' . $this->randomMachineName(); + $this->drupalGet(file_create_url($directory . '/' . $this->randomString())); + $this->assertFalse(file_exists($directory), 'New directory was not created in the filesystem when requesting an unauthorized image.'); + } + +} diff -r e200cb7efeb3 -r c2387f117808 core/modules/image/tests/src/Functional/QuickEditImageControllerTest.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/core/modules/image/tests/src/Functional/QuickEditImageControllerTest.php Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,186 @@ +drupalCreateContentType(['type' => 'article', 'name' => 'Article']); + + // Log in as a content author who can use Quick Edit and edit Articles. + $this->contentAuthorUser = $this->drupalCreateUser([ + 'access contextual links', + 'access in-place editing', + 'access content', + 'create article content', + 'edit any article content', + 'delete any article content', + ]); + $this->drupalLogin($this->contentAuthorUser); + + // Create a field with basic resolution validators. + $this->fieldName = strtolower($this->randomMachineName()); + $field_settings = [ + 'max_resolution' => '100x', + 'min_resolution' => '50x', + ]; + $this->createImageField($this->fieldName, 'article', [], $field_settings); + } + + /** + * Tests that routes restrict access for un-privileged users. + */ + public function testAccess() { + // Create an anonymous user. + $user = $this->createUser(); + $this->drupalLogin($user); + + // Create a test Node. + $node = $this->drupalCreateNode([ + 'type' => 'article', + 'title' => t('Test Node'), + ]); + $this->drupalGet('quickedit/image/info/node/' . $node->id() . '/' . $this->fieldName . '/' . $node->language()->getId() . '/default'); + $this->assertResponse('403'); + + /** @var \Symfony\Component\BrowserKit\Client $client */ + $client = $this->getSession()->getDriver()->getClient(); + $client->request('POST', '/quickedit/image/upload/node/' . $node->id() . '/' . $this->fieldName . '/' . $node->language()->getId() . '/default'); + $this->assertEquals('403', $client->getResponse()->getStatus()); + } + + /** + * Tests that the field info route returns expected data. + */ + public function testFieldInfo() { + // Create a test Node. + $node = $this->drupalCreateNode([ + 'type' => 'article', + 'title' => t('Test Node'), + ]); + $json = $this->drupalGet('quickedit/image/info/node/' . $node->id() . '/' . $this->fieldName . '/' . $node->language()->getId() . '/default', ['query' => ['_format' => 'json']]); + $info = Json::decode($json); + // Assert that the default settings for our field are respected by our JSON + // endpoint. + $this->assertTrue($info['alt_field']); + $this->assertFalse($info['title_field']); + } + + /** + * Tests that uploading a valid image works. + */ + public function testValidImageUpload() { + // Create a test Node. + $node = $this->drupalCreateNode([ + 'type' => 'article', + 'title' => t('Test Node'), + ]); + + // We want a test image that is a valid size. + $valid_image = FALSE; + $image_factory = $this->container->get('image.factory'); + foreach ($this->drupalGetTestFiles('image') as $image) { + $image_file = $image_factory->get($image->uri); + if ($image_file->getWidth() > 50 && $image_file->getWidth() < 100) { + $valid_image = $image; + break; + } + } + $this->assertTrue($valid_image); + + $this->drupalLogin($this->contentAuthorUser); + $this->uploadImage($valid_image, $node->id(), $this->fieldName, $node->language()->getId()); + $this->assertContains('"fid":"1"', $this->getSession()->getPage()->getContent(), 'Valid upload completed successfully.'); + } + + /** + * Tests that uploading a invalid image does not work. + */ + public function testInvalidUpload() { + // Create a test Node. + $node = $this->drupalCreateNode([ + 'type' => 'article', + 'title' => t('Test Node'), + ]); + + // We want a test image that will fail validation. + $invalid_image = FALSE; + /** @var \Drupal\Core\Image\ImageFactory $image_factory */ + $image_factory = $this->container->get('image.factory'); + foreach ($this->drupalGetTestFiles('image') as $image) { + /** @var \Drupal\Core\Image\ImageInterface $image_file */ + $image_file = $image_factory->get($image->uri); + if ($image_file->getWidth() < 50 || $image_file->getWidth() > 100) { + $invalid_image = $image; + break; + } + } + $this->assertTrue($invalid_image); + + $this->drupalLogin($this->contentAuthorUser); + $this->uploadImage($invalid_image, $node->id(), $this->fieldName, $node->language()->getId()); + $this->assertContains('"main_error":"The image failed validation."', $this->getSession()->getPage()->getContent(), 'Invalid upload returned errors.'); + } + + /** + * Uploads an image using the image module's Quick Edit route. + * + * @param object $image + * The image to upload. + * @param int $nid + * The target node ID. + * @param string $field_name + * The target field machine name. + * @param string $langcode + * The langcode to use when setting the field's value. + */ + public function uploadImage($image, $nid, $field_name, $langcode) { + $filepath = $this->container->get('file_system')->realpath($image->uri); + $path = 'quickedit/image/upload/node/' . $nid . '/' . $field_name . '/' . $langcode . '/default'; + + $this->prepareRequest(); + $client = $this->getSession()->getDriver()->getClient(); + $client->request('POST', $this->buildUrl($path, []), [], ['files[image]' => $filepath]); + } + +} diff -r e200cb7efeb3 -r c2387f117808 core/modules/image/tests/src/Functional/Rest/ImageStyleJsonAnonTest.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/core/modules/image/tests/src/Functional/Rest/ImageStyleJsonAnonTest.php Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,24 @@ +grantPermissionsToTestedRole(['administer image styles']); + } + + /** + * {@inheritdoc} + */ + protected function createEntity() { + // Create a "Camelids" image style. + $camelids = ImageStyle::create([ + 'name' => 'camelids', + 'label' => 'Camelids', + ]); + + // Add an image effect. + $effect = [ + 'id' => 'image_scale_and_crop', + 'data' => [ + 'width' => 120, + 'height' => 121, + ], + 'weight' => 0, + ]; + $this->effectUuid = $camelids->addImageEffect($effect); + + $camelids->save(); + + return $camelids; + } + + /** + * {@inheritdoc} + */ + protected function getExpectedNormalizedEntity() { + return [ + 'dependencies' => [], + 'effects' => [ + $this->effectUuid => [ + 'uuid' => $this->effectUuid, + 'id' => 'image_scale_and_crop', + 'weight' => 0, + 'data' => [ + 'width' => 120, + 'height' => 121, + ], + ], + ], + 'label' => 'Camelids', + 'langcode' => 'en', + 'name' => 'camelids', + 'status' => TRUE, + 'uuid' => $this->entity->uuid(), + ]; + } + + /** + * {@inheritdoc} + */ + protected function getNormalizedPostEntity() { + // @todo Update in https://www.drupal.org/node/2300677. + } + + /** + * {@inheritdoc} + */ + protected function getExpectedUnauthorizedAccessMessage($method) { + if ($this->config('rest.settings')->get('bc_entity_resource_permissions')) { + return parent::getExpectedUnauthorizedAccessMessage($method); + } + + return "The 'administer image styles' permission is required."; + } + +} diff -r e200cb7efeb3 -r c2387f117808 core/modules/image/tests/src/Functional/Rest/ImageStyleXmlAnonTest.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/core/modules/image/tests/src/Functional/Rest/ImageStyleXmlAnonTest.php Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,34 @@ +markTestSkipped(); + } + +} diff -r e200cb7efeb3 -r c2387f117808 core/modules/image/tests/src/Functional/Rest/ImageStyleXmlBasicAuthTest.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/core/modules/image/tests/src/Functional/Rest/ImageStyleXmlBasicAuthTest.php Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,44 @@ +markTestSkipped(); + } + +} diff -r e200cb7efeb3 -r c2387f117808 core/modules/image/tests/src/Functional/Rest/ImageStyleXmlCookieTest.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/core/modules/image/tests/src/Functional/Rest/ImageStyleXmlCookieTest.php Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,39 @@ +markTestSkipped(); + } + +} diff -r e200cb7efeb3 -r c2387f117808 core/modules/image/tests/src/FunctionalJavascript/ImageAdminStylesTest.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/core/modules/image/tests/src/FunctionalJavascript/ImageAdminStylesTest.php Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,64 @@ +randomMachineName(10)); + $style_label = $this->randomString(); + $style_path = $admin_path . '/manage/' . $style_name; + $effect_edit = [ + 'data[test_parameter]' => 100, + ]; + + // Add style form. + $page = $this->getSession()->getPage(); + $assert = $this->assertSession(); + $this->drupalGet($admin_path . '/add'); + $page->findField('label')->setValue($style_label); + $assert->waitForElementVisible('named', ['button', 'Edit'])->press(); + $assert->waitForElementVisible('named', ['id_or_name', 'name'])->setValue($style_name); + $page->pressButton('Create new style'); + $assert->pageTextContains("Style $style_label was created."); + + // Add two Ajax-enabled test effects. + $this->drupalPostForm($style_path, ['new' => 'image_module_test_ajax'], t('Add')); + $this->drupalPostForm(NULL, $effect_edit, t('Add effect')); + $this->drupalPostForm($style_path, ['new' => 'image_module_test_ajax'], t('Add')); + $this->drupalPostForm(NULL, $effect_edit, t('Add effect')); + + // Load the saved image style. + $style = ImageStyle::load($style_name); + + // Edit back the effects. + foreach ($style->getEffects() as $uuid => $effect) { + $effect_path = $admin_path . '/manage/' . $style_name . '/effects/' . $uuid; + $this->drupalGet($effect_path); + $page->findField('data[test_parameter]')->setValue(111); + $ajax_value = $page->find('css', '#ajax-value')->getText(); + $this->assertSame('Ajax value bar', $ajax_value); + $this->getSession()->getPage()->pressButton('Ajax refresh'); + $this->assertTrue($page->waitFor(10, function ($page) { + $ajax_value = $page->find('css', '#ajax-value')->getText(); + return preg_match('/^Ajax value [0-9.]+ [0-9.]+$/', $ajax_value); + })); + $page->pressButton('Update effect'); + $assert->pageTextContains('The image effect was successfully applied.'); + } + } + +} diff -r e200cb7efeb3 -r c2387f117808 core/modules/image/tests/src/FunctionalJavascript/ImageFieldTestBase.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/core/modules/image/tests/src/FunctionalJavascript/ImageFieldTestBase.php Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,72 @@ +profile !== 'standard') { + $this->drupalCreateContentType(['type' => 'page', 'name' => 'Basic page']); + $this->drupalCreateContentType(['type' => 'article', 'name' => 'Article']); + } + + $this->adminUser = $this->drupalCreateUser([ + 'access content', + 'access administration pages', + 'administer site configuration', + 'administer content types', + 'administer node fields', + 'administer nodes', + 'create article content', + 'edit any article content', + 'delete any article content', + 'administer image styles', + 'administer node display', + ]); + $this->drupalLogin($this->adminUser); + } + +} diff -r e200cb7efeb3 -r c2387f117808 core/modules/image/tests/src/FunctionalJavascript/ImageFieldValidateTest.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/core/modules/image/tests/src/FunctionalJavascript/ImageFieldValidateTest.php Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,82 @@ +randomMachineName()); + $this->createImageField($field_name, 'article', ['cardinality' => -1]); + + $this->drupalGet('node/add/article'); + /** @var \Drupal\file\FileInterface[] $text_files */ + $text_files = $this->drupalGetTestFiles('text'); + $text_file = reset($text_files); + + $field = $this->getSession()->getPage()->findField('files[' . $field_name . '_0][]'); + $field->attachFile($this->container->get('file_system')->realpath($text_file->uri)); + $this->assertSession()->waitForElement('css', '.messages--error'); + + $elements = $this->xpath('//div[contains(@class, :class)]', [ + ':class' => 'messages--error', + ]); + $this->assertEqual(count($elements), 1, 'Ajax validation messages are displayed once.'); + } + + /** + * Tests that image field validation works with other form submit handlers. + */ + public function testFriendlyAjaxValidation() { + // Add a custom field to the Article content type that contains an AJAX + // handler on a select field. + $field_storage = FieldStorageConfig::create([ + 'field_name' => 'field_dummy_select', + 'type' => 'image_module_test_dummy_ajax', + 'entity_type' => 'node', + 'cardinality' => 1, + ]); + $field_storage->save(); + + $field = FieldConfig::create([ + 'field_storage' => $field_storage, + 'entity_type' => 'node', + 'bundle' => 'article', + 'field_name' => 'field_dummy_select', + 'label' => t('Dummy select'), + ])->save(); + + \Drupal::entityTypeManager() + ->getStorage('entity_form_display') + ->load('node.article.default') + ->setComponent( + 'field_dummy_select', + [ + 'type' => 'image_module_test_dummy_ajax_widget', + 'weight' => 1, + ]) + ->save(); + + // Then, add an image field. + $this->createImageField('field_dummy_image', 'article'); + + // Open an article and trigger the AJAX handler. + $this->drupalGet('node/add/article'); + $id = $this->getSession()->getPage()->find('css', '[name="form_build_id"]')->getValue(); + $field = $this->getSession()->getPage()->findField('field_dummy_select[select_widget]'); + $field->setValue('bam'); + // Make sure that the operation did not end with an exception. + $this->assertSession()->waitForElement('css', "[name='form_build_id']:not([value='$id'])"); + } + +} diff -r e200cb7efeb3 -r c2387f117808 core/modules/image/tests/src/Kernel/ImageThemeFunctionTest.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/core/modules/image/tests/src/Kernel/ImageThemeFunctionTest.php Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,232 @@ +installEntitySchema('entity_test'); + $this->installEntitySchema('file'); + $this->installSchema('file', ['file_usage']); + $this->installEntitySchema('user'); + + FieldStorageConfig::create([ + 'entity_type' => 'entity_test', + 'field_name' => 'image_test', + 'type' => 'image', + 'cardinality' => FieldStorageDefinitionInterface::CARDINALITY_UNLIMITED, + ])->save(); + FieldConfig::create([ + 'entity_type' => 'entity_test', + 'field_name' => 'image_test', + 'bundle' => 'entity_test', + ])->save(); + file_unmanaged_copy(\Drupal::root() . '/core/misc/druplicon.png', 'public://example.jpg'); + $this->image = File::create([ + 'uri' => 'public://example.jpg', + ]); + $this->image->save(); + $this->imageFactory = $this->container->get('image.factory'); + } + + /** + * Tests usage of the image field formatters. + */ + public function testImageFormatterTheme() { + /** @var \Drupal\Core\Render\RendererInterface $renderer */ + $renderer = $this->container->get('renderer'); + + // Create an image. + $files = $this->drupalGetTestFiles('image'); + $file = reset($files); + $original_uri = file_unmanaged_copy($file->uri, 'public://', FILE_EXISTS_RENAME); + + // Create a style. + $style = ImageStyle::create(['name' => 'test', 'label' => 'Test']); + $style->save(); + $url = file_url_transform_relative($style->buildUrl($original_uri)); + + // Create a test entity with the image field set. + $entity = EntityTest::create(); + $entity->image_test->target_id = $this->image->id(); + $entity->image_test->alt = NULL; + $entity->image_test->uri = $original_uri; + $image = $this->imageFactory->get('public://example.jpg'); + $entity->save(); + + // Create the base element that we'll use in the tests below. + $path = $this->randomMachineName(); + $base_element = [ + '#theme' => 'image_formatter', + '#image_style' => 'test', + '#item' => $entity->image_test, + '#url' => Url::fromUri('base:' . $path), + ]; + + // Test using theme_image_formatter() with a NULL value for the alt option. + $element = $base_element; + $this->setRawContent($renderer->renderRoot($element)); + $elements = $this->xpath('//a[@href=:path]/img[@src=:url and @width=:width and @height=:height]', [':path' => base_path() . $path, ':url' => $url, ':width' => $image->getWidth(), ':height' => $image->getHeight()]); + $this->assertEqual(count($elements), 1, 'theme_image_formatter() correctly renders with a NULL value for the alt option.'); + + // Test using theme_image_formatter() without an image title, alt text, or + // link options. + $element = $base_element; + $element['#item']->alt = ''; + $this->setRawContent($renderer->renderRoot($element)); + $elements = $this->xpath('//a[@href=:path]/img[@src=:url and @width=:width and @height=:height and @alt=""]', [':path' => base_path() . $path, ':url' => $url, ':width' => $image->getWidth(), ':height' => $image->getHeight()]); + $this->assertEqual(count($elements), 1, 'theme_image_formatter() correctly renders without title, alt, or path options.'); + + // Link the image to a fragment on the page, and not a full URL. + $fragment = $this->randomMachineName(); + $element = $base_element; + $element['#url'] = Url::fromRoute('', [], ['fragment' => $fragment]); + $this->setRawContent($renderer->renderRoot($element)); + $elements = $this->xpath('//a[@href=:fragment]/img[@src=:url and @width=:width and @height=:height and @alt=""]', [ + ':fragment' => '#' . $fragment, + ':url' => $url, + ':width' => $image->getWidth(), + ':height' => $image->getHeight() + ]); + $this->assertEqual(count($elements), 1, 'theme_image_formatter() correctly renders a link fragment.'); + } + + /** + * Tests usage of the image style theme function. + */ + public function testImageStyleTheme() { + /** @var \Drupal\Core\Render\RendererInterface $renderer */ + $renderer = $this->container->get('renderer'); + + // Create an image. + $files = $this->drupalGetTestFiles('image'); + $file = reset($files); + $original_uri = file_unmanaged_copy($file->uri, 'public://', FILE_EXISTS_RENAME); + + // Create a style. + $style = ImageStyle::create(['name' => 'image_test', 'label' => 'Test']); + $style->save(); + $url = file_url_transform_relative($style->buildUrl($original_uri)); + + // Create the base element that we'll use in the tests below. + $base_element = [ + '#theme' => 'image_style', + '#style_name' => 'image_test', + '#uri' => $original_uri, + ]; + + $element = $base_element; + $this->setRawContent($renderer->renderRoot($element)); + $elements = $this->xpath('//img[@src=:url and @alt=""]', [':url' => $url]); + $this->assertEqual(count($elements), 1, 'theme_image_style() renders an image correctly.'); + + // Test using theme_image_style() with a NULL value for the alt option. + $element = $base_element; + $element['#alt'] = NULL; + $this->setRawContent($renderer->renderRoot($element)); + $elements = $this->xpath('//img[@src=:url]', [':url' => $url]); + $this->assertEqual(count($elements), 1, 'theme_image_style() renders an image correctly with a NULL value for the alt option.'); + } + + /** + * Tests image alt attribute functionality. + */ + public function testImageAltFunctionality() { + /** @var \Drupal\Core\Render\RendererInterface $renderer */ + $renderer = $this->container->get('renderer'); + + // Test using alt directly with alt attribute. + $image_with_alt_property = [ + '#theme' => 'image', + '#uri' => '/core/themes/bartik/logo.svg', + '#alt' => 'Regular alt', + '#title' => 'Test title', + '#width' => '50%', + '#height' => '50%', + '#attributes' => ['class' => 'image-with-regular-alt', 'id' => 'my-img'], + ]; + + $this->setRawContent($renderer->renderRoot($image_with_alt_property)); + $elements = $this->xpath('//img[contains(@class, class) and contains(@alt, :alt)]', [":class" => "image-with-regular-alt", ":alt" => "Regular alt"]); + $this->assertEqual(count($elements), 1, 'Regular alt displays correctly'); + + // Test using alt attribute inside attributes. + $image_with_alt_attribute_alt_attribute = [ + '#theme' => 'image', + '#uri' => '/core/themes/bartik/logo.svg', + '#width' => '50%', + '#height' => '50%', + '#attributes' => [ + 'class' => 'image-with-attribute-alt', + 'id' => 'my-img', + 'title' => 'New test title', + 'alt' => 'Attribute alt', + ], + ]; + + $this->setRawContent($renderer->renderRoot($image_with_alt_attribute_alt_attribute)); + $elements = $this->xpath('//img[contains(@class, class) and contains(@alt, :alt)]', [":class" => "image-with-attribute-alt", ":alt" => "Attribute alt"]); + $this->assertEqual(count($elements), 1, 'Attribute alt displays correctly'); + + // Test using alt attribute as property and inside attributes. + $image_with_alt_attribute_both = [ + '#theme' => 'image', + '#uri' => '/core/themes/bartik/logo.svg', + '#width' => '50%', + '#height' => '50%', + '#alt' => 'Kitten sustainable', + '#attributes' => [ + 'class' => 'image-with-attribute-alt', + 'id' => 'my-img', + 'title' => 'New test title', + 'alt' => 'Attribute alt', + ], + ]; + + $this->setRawContent($renderer->renderRoot($image_with_alt_attribute_both)); + $elements = $this->xpath('//img[contains(@class, class) and contains(@alt, :alt)]', [":class" => "image-with-attribute-alt", ":alt" => "Attribute alt"]); + $this->assertEqual(count($elements), 1, 'Attribute alt overrides alt property if both set.'); + } + +} diff -r e200cb7efeb3 -r c2387f117808 core/modules/image/tests/src/Kernel/Views/RelationshipUserImageDataTest.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/core/modules/image/tests/src/Kernel/Views/RelationshipUserImageDataTest.php Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,103 @@ +installEntitySchema('file'); + $this->installSchema('file', ['file_usage']); + $this->installEntitySchema('user'); + + // Create the user profile field and instance. + FieldStorageConfig::create([ + 'entity_type' => 'user', + 'field_name' => 'user_picture', + 'type' => 'image', + 'translatable' => '0', + ])->save(); + FieldConfig::create([ + 'label' => 'User Picture', + 'description' => '', + 'field_name' => 'user_picture', + 'entity_type' => 'user', + 'bundle' => 'user', + 'required' => 0, + ])->save(); + + ViewTestData::createTestViews(get_class($this), ['image_test_views']); + } + + /** + * Tests using the views image relationship. + */ + public function testViewsHandlerRelationshipUserImageData() { + $file = File::create([ + 'fid' => 2, + 'uid' => 2, + 'filename' => 'image-test.jpg', + 'uri' => "public://image-test.jpg", + 'filemime' => 'image/jpeg', + 'created' => 1, + 'changed' => 1, + 'status' => FILE_STATUS_PERMANENT, + ]); + $file->enforceIsNew(); + file_put_contents($file->getFileUri(), file_get_contents('core/modules/simpletest/files/image-1.png')); + $file->save(); + + $account = User::create([ + 'name' => 'foo', + ]); + $account->user_picture->target_id = 2; + $account->save(); + + $view = Views::getView('test_image_user_image_data'); + // Tests \Drupal\taxonomy\Plugin\views\relationship\NodeTermData::calculateDependencies(). + $expected = [ + 'module' => [ + 'file', + 'user', + ], + ]; + $this->assertIdentical($expected, $view->getDependencies()); + $this->executeView($view); + $expected_result = [ + [ + 'file_managed_user__user_picture_fid' => '2', + ], + ]; + $column_map = ['file_managed_user__user_picture_fid' => 'file_managed_user__user_picture_fid']; + $this->assertIdenticalResultset($view, $expected_result, $column_map); + } + +} diff -r e200cb7efeb3 -r c2387f117808 core/modules/language/migrations/d6_language_content_menu_settings.yml --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/core/modules/language/migrations/d6_language_content_menu_settings.yml Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,21 @@ +id: d6_language_content_menu_settings +label: Drupal 6 language content menu settings +migration_tags: + - Drupal 6 + - Configuration +source: + plugin: extension + name: i18nmenu + constants: + target_type: 'menu_link_content' + langcode: 'site_default' +process: + target_entity_type_id: 'constants/target_type' + # menu_link_content has a bundle key but no bundle support so use the entity + # type as the bundle. + target_bundle: 'constants/target_type' + default_langcode: 'constants/langcode' + # Drupal 6 menus are translated when the i18nmenu module is enabled. + language_alterable: status +destination: + plugin: entity:language_content_settings diff -r e200cb7efeb3 -r c2387f117808 core/modules/language/tests/src/Functional/Hal/ConfigurableLanguageHalJsonAnonTest.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/core/modules/language/tests/src/Functional/Hal/ConfigurableLanguageHalJsonAnonTest.php Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,30 @@ +grantPermissionsToTestedRole(['administer languages']); + } + + /** + * {@inheritdoc} + */ + protected function createEntity() { + $configurable_language = ConfigurableLanguage::create([ + 'id' => 'll', + 'label' => 'Llama Language', + ]); + $configurable_language->save(); + + return $configurable_language; + } + + /** + * {@inheritdoc} + */ + protected function getExpectedNormalizedEntity() { + return [ + 'dependencies' => [], + 'direction' => 'ltr', + 'id' => 'll', + 'label' => 'Llama Language', + 'langcode' => 'en', + 'locked' => FALSE, + 'status' => TRUE, + 'uuid' => $this->entity->uuid(), + 'weight' => 0, + ]; + } + + /** + * {@inheritdoc} + */ + protected function getExpectedCacheContexts() { + return Cache::mergeContexts(parent::getExpectedCacheContexts(), ['languages:language_interface']); + } + + /** + * {@inheritdoc} + */ + protected function getNormalizedPostEntity() { + // @todo Update in https://www.drupal.org/node/2300677. + } + + /** + * Test a GET request for a default config entity, which has a _core key. + * + * @see https://www.drupal.org/node/2915414 + */ + public function testGetDefaultConfig() { + $this->initAuthentication(); + $url = Url::fromUri('base:/entity/configurable_language/en')->setOption('query', ['_format' => static::$format]);; + $request_options = $this->getAuthenticationRequestOptions('GET'); + $this->provisionEntityResource(); + $this->setUpAuthorization('GET'); + $response = $this->request('GET', $url, $request_options); + + $normalization = $this->serializer->decode((string) $response->getBody(), static::$format); + $this->assertArrayNotHasKey('_core', $normalization); + } + +} diff -r e200cb7efeb3 -r c2387f117808 core/modules/language/tests/src/Functional/Rest/ConfigurableLanguageXmlAnonTest.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/core/modules/language/tests/src/Functional/Rest/ConfigurableLanguageXmlAnonTest.php Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,26 @@ +grantPermissionsToTestedRole(['administer languages']); + } + + /** + * {@inheritdoc} + */ + protected function createEntity() { + // Create a "Camelids" node type. + $camelids = NodeType::create([ + 'name' => 'Camelids', + 'type' => 'camelids', + ]); + $camelids->save(); + + $entity = ContentLanguageSettings::create([ + 'target_entity_type_id' => 'node', + 'target_bundle' => 'camelids', + ]); + $entity->setDefaultLangcode('site_default') + ->save(); + + return $entity; + } + + /** + * {@inheritdoc} + */ + protected function getExpectedNormalizedEntity() { + return [ + 'default_langcode' => 'site_default', + 'dependencies' => [ + 'config' => [ + 'node.type.camelids', + ], + ], + 'id' => 'node.camelids', + 'langcode' => 'en', + 'language_alterable' => FALSE, + 'status' => TRUE, + 'target_bundle' => 'camelids', + 'target_entity_type_id' => 'node', + 'uuid' => $this->entity->uuid(), + ]; + } + + /** + * {@inheritdoc} + */ + protected function getNormalizedPostEntity() { + // @todo Update in https://www.drupal.org/node/2300677. + } + + /** + * {@inheritdoc} + */ + protected function getExpectedCacheContexts() { + return [ + 'languages:language_interface', + 'user.permissions', + ]; + } + +} diff -r e200cb7efeb3 -r c2387f117808 core/modules/language/tests/src/Functional/Rest/ContentLanguageSettingsXmlAnonTest.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/core/modules/language/tests/src/Functional/Rest/ContentLanguageSettingsXmlAnonTest.php Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,26 @@ +save(); + ConfigurableLanguage::createFromLangcode('fr')->save(); + $this->executeMigrations(['d6_language_content_menu_settings']); + } + + /** + * Tests migration of menu translation ability. + */ + public function testLanguageMenuContent() { + $config = ContentLanguageSettings::load('menu_link_content.menu_link_content'); + $this->assertInstanceOf(ContentLanguageSettings::class, $config); + $this->assertSame('menu_link_content', $config->getTargetEntityTypeId()); + $this->assertSame('menu_link_content', $config->getTargetBundle()); + $this->assertSame(LanguageInterface::LANGCODE_SITE_DEFAULT, $config->getDefaultLangcode()); + $this->assertTrue($config->isLanguageAlterable()); + + // Test that menus are not alterable when the i18nmenu is not enabled. + $this->sourceDatabase->update('system') + ->fields(['status' => 0]) + ->condition('name', 'i18nmenu') + ->execute(); + + /** @var \Drupal\migrate\Plugin\MigrationInterface $migration */ + $migration = $this->getMigration('d6_language_content_menu_settings'); + // Indicate we're rerunning a migration that's already run. + $migration->getIdMap()->prepareUpdate(); + $this->executeMigration($migration); + + $config = ContentLanguageSettings::load('menu_link_content.menu_link_content'); + $this->assertInstanceOf(ContentLanguageSettings::class, $config); + $this->assertSame('menu_link_content', $config->getTargetEntityTypeId()); + $this->assertSame('menu_link_content', $config->getTargetBundle()); + $this->assertSame(LanguageInterface::LANGCODE_SITE_DEFAULT, $config->getDefaultLangcode()); + $this->assertFalse($config->isLanguageAlterable()); + } + +} diff -r e200cb7efeb3 -r c2387f117808 core/modules/layout_builder/css/layout-builder.css --- a/core/modules/layout_builder/css/layout-builder.css Thu Apr 26 11:26:54 2018 +0100 +++ b/core/modules/layout_builder/css/layout-builder.css Tue Jul 10 15:07:59 2018 +0100 @@ -1,4 +1,5 @@ .add-section { + background-color: #f7f7f7; width: 100%; outline: 2px dashed #979797; padding: 1.5em 0; @@ -7,19 +8,54 @@ transition: visually-hidden 2s ease-out, height 2s ease-in; } +.add-section__link, +.add-block__link { + color: #787878; + border-bottom: none; + padding-left: 24px; + background: url(../../../misc/icons/787878/plus.svg) transparent top left / 16px 16px no-repeat; +} + +.add-section__link:hover, +.add-section__link:active, +.add-section__link:focus, +.add-block__link:hover, +.add-block__link:active, +.add-block__link:focus { + border-bottom-style: none; + color: #000; +} + .layout-section { margin-bottom: 1.5em; } +.layout-section .ui-sortable-helper { + background-color: #fff; + outline: 2px solid #f7f7f7; +} + +.layout-section .ui-state-drop { + background-color: #ffd; + outline: 2px dashed #fedb60; + margin: 20px; + padding: 30px; +} + .layout-section .layout-builder--layout__region { outline: 2px dashed #2f91da; - padding: 1.5em 0; } .layout-section .layout-builder--layout__region .add-block { + background-color: #eff6fc; + padding: 1.5em 0; text-align: center; } +.layout-section .layout-builder--layout__region .block { + padding: 1.5em; +} + .layout-section .remove-section { position: relative; background: url(../../../misc/icons/bebebe/ex.svg) #fff center center / 16px 16px no-repeat; diff -r e200cb7efeb3 -r c2387f117808 core/modules/layout_builder/js/layout-builder.es6.js --- a/core/modules/layout_builder/js/layout-builder.es6.js Thu Apr 26 11:26:54 2018 +0100 +++ b/core/modules/layout_builder/js/layout-builder.es6.js Tue Jul 10 15:07:59 2018 +0100 @@ -4,6 +4,7 @@ $(context).find('.layout-builder--layout__region').sortable({ items: '> .draggable', connectWith: '.layout-builder--layout__region', + placeholder: 'ui-state-drop', /** * Updates the layout with the new position of the block. diff -r e200cb7efeb3 -r c2387f117808 core/modules/layout_builder/js/layout-builder.js --- a/core/modules/layout_builder/js/layout-builder.js Thu Apr 26 11:26:54 2018 +0100 +++ b/core/modules/layout_builder/js/layout-builder.js Tue Jul 10 15:07:59 2018 +0100 @@ -14,6 +14,7 @@ $(context).find('.layout-builder--layout__region').sortable({ items: '> .draggable', connectWith: '.layout-builder--layout__region', + placeholder: 'ui-state-drop', update: function update(event, ui) { var itemRegion = ui.item.closest('.layout-builder--layout__region'); diff -r e200cb7efeb3 -r c2387f117808 core/modules/layout_builder/layout_builder.services.yml --- a/core/modules/layout_builder/layout_builder.services.yml Thu Apr 26 11:26:54 2018 +0100 +++ b/core/modules/layout_builder/layout_builder.services.yml Tue Jul 10 15:07:59 2018 +0100 @@ -36,3 +36,6 @@ arguments: ['@current_user'] tags: - { name: event_subscriber } + logger.channel.layout_builder: + parent: logger.channel_base + arguments: ['layout_builder'] diff -r e200cb7efeb3 -r c2387f117808 core/modules/layout_builder/src/Controller/LayoutBuilderController.php --- a/core/modules/layout_builder/src/Controller/LayoutBuilderController.php Thu Apr 26 11:26:54 2018 +0100 +++ b/core/modules/layout_builder/src/Controller/LayoutBuilderController.php Tue Jul 10 15:07:59 2018 +0100 @@ -161,7 +161,7 @@ ], [ 'attributes' => [ - 'class' => ['use-ajax'], + 'class' => ['use-ajax', 'add-section__link'], 'data-dialog-type' => 'dialog', 'data-dialog-renderer' => 'off_canvas', ], @@ -226,7 +226,7 @@ ], [ 'attributes' => [ - 'class' => ['use-ajax'], + 'class' => ['use-ajax', 'add-block__link'], 'data-dialog-type' => 'dialog', 'data-dialog-renderer' => 'off_canvas', ], diff -r e200cb7efeb3 -r c2387f117808 core/modules/layout_builder/src/DefaultsSectionStorageInterface.php --- a/core/modules/layout_builder/src/DefaultsSectionStorageInterface.php Thu Apr 26 11:26:54 2018 +0100 +++ b/core/modules/layout_builder/src/DefaultsSectionStorageInterface.php Tue Jul 10 15:07:59 2018 +0100 @@ -2,6 +2,8 @@ namespace Drupal\layout_builder; +use Drupal\Core\Config\Entity\ThirdPartySettingsInterface; + /** * Defines an interface for an object that stores layout sections for defaults. * @@ -10,7 +12,7 @@ * experimental modules and development releases of contributed modules. * See https://www.drupal.org/core/experimental for more information. */ -interface DefaultsSectionStorageInterface extends SectionStorageInterface { +interface DefaultsSectionStorageInterface extends SectionStorageInterface, ThirdPartySettingsInterface { /** * Determines if the defaults allow custom overrides. diff -r e200cb7efeb3 -r c2387f117808 core/modules/layout_builder/src/Entity/LayoutBuilderEntityViewDisplayStorage.php --- a/core/modules/layout_builder/src/Entity/LayoutBuilderEntityViewDisplayStorage.php Thu Apr 26 11:26:54 2018 +0100 +++ b/core/modules/layout_builder/src/Entity/LayoutBuilderEntityViewDisplayStorage.php Tue Jul 10 15:07:59 2018 +0100 @@ -5,7 +5,6 @@ use Drupal\Core\Config\Entity\ConfigEntityStorage; use Drupal\Core\Entity\EntityInterface; use Drupal\layout_builder\Section; -use Drupal\layout_builder\SectionComponent; /** * Provides storage for entity view display entities that have layouts. @@ -38,20 +37,7 @@ foreach ($records as $id => &$record) { if (!empty($record['third_party_settings']['layout_builder']['sections'])) { $sections = &$record['third_party_settings']['layout_builder']['sections']; - foreach ($sections as $section_delta => $section) { - $sections[$section_delta] = new Section( - $section['layout_id'], - $section['layout_settings'], - array_map(function (array $component) { - return (new SectionComponent( - $component['uuid'], - $component['region'], - $component['configuration'], - $component['additional'] - ))->setWeight($component['weight']); - }, $section['components']) - ); - } + $sections = array_map([Section::class, 'fromArray'], $sections); } } return parent::mapFromStorageRecords($records); diff -r e200cb7efeb3 -r c2387f117808 core/modules/layout_builder/src/OverridesSectionStorageInterface.php --- a/core/modules/layout_builder/src/OverridesSectionStorageInterface.php Thu Apr 26 11:26:54 2018 +0100 +++ b/core/modules/layout_builder/src/OverridesSectionStorageInterface.php Tue Jul 10 15:07:59 2018 +0100 @@ -15,7 +15,7 @@ /** * Returns the corresponding defaults section storage for this override. * - * @return \Drupal\layout_builder\SectionStorageInterface + * @return \Drupal\layout_builder\DefaultsSectionStorageInterface * The defaults section storage. * * @todo Determine if this method needs a parameter in diff -r e200cb7efeb3 -r c2387f117808 core/modules/layout_builder/src/Plugin/Block/FieldBlock.php --- a/core/modules/layout_builder/src/Plugin/Block/FieldBlock.php Thu Apr 26 11:26:54 2018 +0100 +++ b/core/modules/layout_builder/src/Plugin/Block/FieldBlock.php Tue Jul 10 15:07:59 2018 +0100 @@ -20,6 +20,7 @@ use Drupal\Core\Render\Element; use Drupal\Core\Session\AccountInterface; use Drupal\Core\StringTranslation\TranslatableMarkup; +use Psr\Log\LoggerInterface; use Symfony\Component\DependencyInjection\ContainerInterface; /** @@ -82,6 +83,13 @@ protected $moduleHandler; /** + * The logger. + * + * @var \Psr\Log\LoggerInterface + */ + protected $logger; + + /** * Constructs a new FieldBlock. * * @param array $configuration @@ -96,11 +104,14 @@ * The formatter manager. * @param \Drupal\Core\Extension\ModuleHandlerInterface $module_handler * The module handler. + * @param \Psr\Log\LoggerInterface $logger + * The logger. */ - public function __construct(array $configuration, $plugin_id, $plugin_definition, EntityFieldManagerInterface $entity_field_manager, FormatterPluginManager $formatter_manager, ModuleHandlerInterface $module_handler) { + public function __construct(array $configuration, $plugin_id, $plugin_definition, EntityFieldManagerInterface $entity_field_manager, FormatterPluginManager $formatter_manager, ModuleHandlerInterface $module_handler, LoggerInterface $logger) { $this->entityFieldManager = $entity_field_manager; $this->formatterManager = $formatter_manager; $this->moduleHandler = $module_handler; + $this->logger = $logger; // Get the entity type and field name from the plugin ID. list (, $entity_type_id, $bundle, $field_name) = explode(static::DERIVATIVE_SEPARATOR, $plugin_id, 4); @@ -121,7 +132,8 @@ $plugin_definition, $container->get('entity_field.manager'), $container->get('plugin.manager.field.formatter'), - $container->get('module_handler') + $container->get('module_handler'), + $container->get('logger.channel.layout_builder') ); } @@ -141,7 +153,13 @@ public function build() { $display_settings = $this->getConfiguration()['formatter']; $entity = $this->getEntity(); - $build = $entity->get($this->fieldName)->view($display_settings); + try { + $build = $entity->get($this->fieldName)->view($display_settings); + } + catch (\Exception $e) { + $build = []; + $this->logger->warning('The field "%field" failed to render with the error of "%error".', ['%field' => $this->fieldName, '%error' => $e->getMessage()]); + } if (!empty($entity->in_preview) && !Element::getVisibleChildren($build)) { $build['content']['#markup'] = new TranslatableMarkup('Placeholder for the "@field" field', ['@field' => $this->getFieldDefinition()->getLabel()]); } diff -r e200cb7efeb3 -r c2387f117808 core/modules/layout_builder/src/Plugin/SectionStorage/DefaultsSectionStorage.php --- a/core/modules/layout_builder/src/Plugin/SectionStorage/DefaultsSectionStorage.php Thu Apr 26 11:26:54 2018 +0100 +++ b/core/modules/layout_builder/src/Plugin/SectionStorage/DefaultsSectionStorage.php Tue Jul 10 15:07:59 2018 +0100 @@ -293,4 +293,41 @@ return $this; } + /** + * {@inheritdoc} + */ + public function setThirdPartySetting($module, $key, $value) { + $this->getDisplay()->setThirdPartySetting($module, $key, $value); + return $this; + } + + /** + * {@inheritdoc} + */ + public function getThirdPartySetting($module, $key, $default = NULL) { + return $this->getDisplay()->getThirdPartySetting($module, $key, $default); + } + + /** + * {@inheritdoc} + */ + public function getThirdPartySettings($module) { + return $this->getDisplay()->getThirdPartySettings($module); + } + + /** + * {@inheritdoc} + */ + public function unsetThirdPartySetting($module, $key) { + $this->getDisplay()->unsetThirdPartySetting($module, $key); + return $this; + } + + /** + * {@inheritdoc} + */ + public function getThirdPartyProviders() { + return $this->getDisplay()->getThirdPartyProviders(); + } + } diff -r e200cb7efeb3 -r c2387f117808 core/modules/layout_builder/src/Plugin/SectionStorage/OverridesSectionStorage.php --- a/core/modules/layout_builder/src/Plugin/SectionStorage/OverridesSectionStorage.php Thu Apr 26 11:26:54 2018 +0100 +++ b/core/modules/layout_builder/src/Plugin/SectionStorage/OverridesSectionStorage.php Tue Jul 10 15:07:59 2018 +0100 @@ -187,7 +187,9 @@ * {@inheritdoc} */ public function getDefaultSectionStorage() { - return LayoutBuilderEntityViewDisplay::collectRenderDisplay($this->getEntity(), 'default'); + // @todo Expand to work for all view modes in + // https://www.drupal.org/node/2907413. + return LayoutBuilderEntityViewDisplay::collectRenderDisplay($this->getEntity(), 'full'); } /** diff -r e200cb7efeb3 -r c2387f117808 core/modules/layout_builder/src/Section.php --- a/core/modules/layout_builder/src/Section.php Thu Apr 26 11:26:54 2018 +0100 +++ b/core/modules/layout_builder/src/Section.php Tue Jul 10 15:07:59 2018 +0100 @@ -322,8 +322,7 @@ /** * Returns an array representation of the section. * - * @internal - * This is intended for use by a storage mechanism for sections. + * Only use this method if you are implementing custom storage for sections. * * @return array * An array representation of the section component. @@ -338,4 +337,23 @@ ]; } + /** + * Creates an object from an array representation of the section. + * + * Only use this method if you are implementing custom storage for sections. + * + * @param array $section + * An array of section data in the format returned by ::toArray(). + * + * @return static + * The section object. + */ + public static function fromArray(array $section) { + return new static( + $section['layout_id'], + $section['layout_settings'], + array_map([SectionComponent::class, 'fromArray'], $section['components']) + ); + } + } diff -r e200cb7efeb3 -r c2387f117808 core/modules/layout_builder/src/SectionComponent.php --- a/core/modules/layout_builder/src/SectionComponent.php Thu Apr 26 11:26:54 2018 +0100 +++ b/core/modules/layout_builder/src/SectionComponent.php Tue Jul 10 15:07:59 2018 +0100 @@ -292,8 +292,7 @@ /** * Returns an array representation of the section component. * - * @internal - * This is intended for use by a storage mechanism for section components. + * Only use this method if you are implementing custom storage for sections. * * @return array * An array representation of the section component. @@ -308,4 +307,24 @@ ]; } + /** + * Creates an object from an array representation of the section component. + * + * Only use this method if you are implementing custom storage for sections. + * + * @param array $component + * An array of section component data in the format returned by ::toArray(). + * + * @return static + * The section component object. + */ + public static function fromArray(array $component) { + return (new static( + $component['uuid'], + $component['region'], + $component['configuration'], + $component['additional'] + ))->setWeight($component['weight']); + } + } diff -r e200cb7efeb3 -r c2387f117808 core/modules/layout_builder/tests/src/Functional/LayoutBuilderTest.php --- a/core/modules/layout_builder/tests/src/Functional/LayoutBuilderTest.php Thu Apr 26 11:26:54 2018 +0100 +++ b/core/modules/layout_builder/tests/src/Functional/LayoutBuilderTest.php Tue Jul 10 15:07:59 2018 +0100 @@ -256,4 +256,67 @@ $assert_session->elementNotExists('css', '.block.menu--mymenu'); } + /** + * Tests the interaction between full and default view modes. + * + * @see \Drupal\layout_builder\Plugin\SectionStorage\OverridesSectionStorage::getDefaultSectionStorage() + */ + public function testLayoutBuilderUiFullViewMode() { + $assert_session = $this->assertSession(); + $page = $this->getSession()->getPage(); + + $this->drupalLogin($this->drupalCreateUser([ + 'configure any layout', + 'administer node display', + 'administer node fields', + ])); + + $field_ui_prefix = 'admin/structure/types/manage/bundle_with_section_field'; + // Allow overrides for the layout. + $this->drupalPostForm("$field_ui_prefix/display/default", ['layout[allow_custom]' => TRUE], 'Save'); + + // Customize the default view mode. + $this->drupalGet("$field_ui_prefix/display-layout/default"); + $this->clickLink('Add Block'); + $this->clickLink('Powered by Drupal'); + $page->fillField('settings[label]', 'This is the default view mode'); + $page->checkField('settings[label_display]'); + $page->pressButton('Add Block'); + $assert_session->pageTextContains('This is the default view mode'); + $this->clickLink('Save Layout'); + + // The default view mode is used for both the node display and layout UI. + $this->drupalGet('node/1'); + $assert_session->pageTextContains('This is the default view mode'); + $this->drupalGet('node/1/layout'); + $assert_session->pageTextContains('This is the default view mode'); + $this->clickLink('Cancel Layout'); + + // Enable the full view mode and customize it. + $this->drupalPostForm("$field_ui_prefix/display/default", ['display_modes_custom[full]' => TRUE], 'Save'); + $this->drupalGet("$field_ui_prefix/display-layout/full"); + $this->clickLink('Add Block'); + $this->clickLink('Powered by Drupal'); + $page->fillField('settings[label]', 'This is the full view mode'); + $page->checkField('settings[label_display]'); + $page->pressButton('Add Block'); + $assert_session->pageTextContains('This is the full view mode'); + $this->clickLink('Save Layout'); + + // The full view mode is now used for both the node display and layout UI. + $this->drupalGet('node/1'); + $assert_session->pageTextContains('This is the full view mode'); + $this->drupalGet('node/1/layout'); + $assert_session->pageTextContains('This is the full view mode'); + $this->clickLink('Cancel Layout'); + + // Disable the full view mode, the default should be used again. + $this->drupalPostForm("$field_ui_prefix/display/default", ['display_modes_custom[full]' => FALSE], 'Save'); + $this->drupalGet('node/1'); + $assert_session->pageTextContains('This is the default view mode'); + $this->drupalGet('node/1/layout'); + $assert_session->pageTextContains('This is the default view mode'); + $this->clickLink('Cancel Layout'); + } + } diff -r e200cb7efeb3 -r c2387f117808 core/modules/layout_builder/tests/src/Kernel/FieldBlockTest.php --- a/core/modules/layout_builder/tests/src/Kernel/FieldBlockTest.php Thu Apr 26 11:26:54 2018 +0100 +++ b/core/modules/layout_builder/tests/src/Kernel/FieldBlockTest.php Tue Jul 10 15:07:59 2018 +0100 @@ -7,13 +7,19 @@ use Drupal\Core\Entity\EntityInterface; use Drupal\Core\Entity\FieldableEntityInterface; use Drupal\Core\Extension\ModuleHandlerInterface; +use Drupal\Core\Field\FieldDefinitionInterface; use Drupal\Core\Field\FieldItemListInterface; use Drupal\Core\Field\FormatterPluginManager; use Drupal\Core\Plugin\Context\ContextDefinition; use Drupal\Core\Session\AccountInterface; use Drupal\KernelTests\Core\Entity\EntityKernelTestBase; use Drupal\layout_builder\Plugin\Block\FieldBlock; +use Prophecy\Argument; +use Prophecy\Promise\PromiseInterface; +use Prophecy\Promise\ReturnPromise; +use Prophecy\Promise\ThrowPromise; use Prophecy\Prophecy\ProphecyInterface; +use Psr\Log\LoggerInterface; /** * @coversDefaultClass \Drupal\layout_builder\Plugin\Block\FieldBlock @@ -22,6 +28,30 @@ class FieldBlockTest extends EntityKernelTestBase { /** + * The entity field manager. + * + * @var \Drupal\Core\Entity\EntityFieldManagerInterface + */ + protected $entityFieldManager; + + /** + * The logger. + * + * @var \Psr\Log\LoggerInterface + */ + protected $logger; + + /** + * {@inheritdoc} + */ + protected function setUp() { + parent::setUp(); + + $this->entityFieldManager = $this->prophesize(EntityFieldManagerInterface::class); + $this->logger = $this->prophesize(LoggerInterface::class); + } + + /** * Tests entity access. * * @covers ::blockAccess @@ -180,7 +210,6 @@ 'entity' => new ContextDefinition('entity:entity_test', 'Test', TRUE), ], ]; - $entity_field_manager = $this->prophesize(EntityFieldManagerInterface::class); $formatter_manager = $this->prophesize(FormatterPluginManager::class); $module_handler = $this->prophesize(ModuleHandlerInterface::class); @@ -188,12 +217,93 @@ $configuration, 'field_block:entity_test:entity_test:the_field_name', $plugin_definition, - $entity_field_manager->reveal(), + $this->entityFieldManager->reveal(), $formatter_manager->reveal(), - $module_handler->reveal() + $module_handler->reveal(), + $this->logger->reveal() ); $block->setContextValue('entity', $entity_prophecy->reveal()); return $block; } + /** + * @covers ::build + * @dataProvider providerTestBuild + */ + public function testBuild(PromiseInterface $promise, $in_preview, $expected_markup, $log_message = '', $log_arguments = []) { + $entity = $this->prophesize(FieldableEntityInterface::class); + $field = $this->prophesize(FieldItemListInterface::class); + $entity->get('the_field_name')->willReturn($field->reveal()); + $entity->in_preview = $in_preview; + $field->view(Argument::type('array'))->will($promise); + + $field_definition = $this->prophesize(FieldDefinitionInterface::class); + $field_definition->getLabel()->willReturn('The Field Label'); + $this->entityFieldManager->getFieldDefinitions('entity_test', 'entity_test')->willReturn(['the_field_name' => $field_definition]); + + if ($log_message) { + $this->logger->warning($log_message, $log_arguments)->shouldBeCalled(); + } + else { + $this->logger->warning(Argument::cetera())->shouldNotBeCalled(); + } + + $block = $this->getTestBlock($entity); + $expected = [ + '#cache' => [ + 'contexts' => [], + 'tags' => [], + 'max-age' => 0, + ], + ]; + if ($expected_markup) { + $expected['content']['#markup'] = $expected_markup; + } + + $actual = $block->build(); + $this->assertEquals($expected, $actual); + } + + /** + * Provides test data for ::testBuild(). + */ + public function providerTestBuild() { + $data = []; + $data['array, no preview'] = [ + new ReturnPromise([['content' => ['#markup' => 'The field value']]]), + FALSE, + 'The field value', + ]; + $data['array, preview'] = [ + new ReturnPromise([['content' => ['#markup' => 'The field value']]]), + TRUE, + 'The field value', + ]; + $data['empty array, no preview'] = [ + new ReturnPromise([[]]), + FALSE, + '', + ]; + $data['empty array, preview'] = [ + new ReturnPromise([[]]), + TRUE, + 'Placeholder for the "The Field Label" field', + ]; + $data['exception, no preview'] = [ + new ThrowPromise(new \Exception('The exception message')), + FALSE, + '', + 'The field "%field" failed to render with the error of "%error".', + ['%field' => 'the_field_name', '%error' => 'The exception message'], + ]; + $data['exception, preview'] = [ + new ThrowPromise(new \Exception('The exception message')), + TRUE, + 'Placeholder for the "The Field Label" field', + 'The field "%field" failed to render with the error of "%error".', + ['%field' => 'the_field_name', '%error' => 'The exception message'], + ]; + return $data; + } + } diff -r e200cb7efeb3 -r c2387f117808 core/modules/layout_builder/tests/src/Unit/DefaultsSectionStorageTest.php --- a/core/modules/layout_builder/tests/src/Unit/DefaultsSectionStorageTest.php Thu Apr 26 11:26:54 2018 +0100 +++ b/core/modules/layout_builder/tests/src/Unit/DefaultsSectionStorageTest.php Tue Jul 10 15:07:59 2018 +0100 @@ -9,6 +9,7 @@ use Drupal\Core\Entity\EntityTypeManagerInterface; use Drupal\Core\Entity\FieldableEntityInterface; use Drupal\layout_builder\Entity\LayoutBuilderSampleEntityGenerator; +use Drupal\layout_builder\Entity\LayoutEntityDisplayInterface; use Drupal\layout_builder\Plugin\SectionStorage\DefaultsSectionStorage; use Drupal\layout_builder\SectionStorage\SectionStorageDefinition; use Drupal\Tests\UnitTestCase; @@ -54,6 +55,30 @@ } /** + * @covers ::getThirdPartySetting + * @covers ::setThirdPartySetting + */ + public function testThirdPartySettings() { + // Set an initial value on the section list. + $section_list = $this->prophesize(LayoutEntityDisplayInterface::class); + $section_list->getThirdPartySetting('the_module', 'the_key', NULL)->willReturn('value 1'); + $this->plugin->setSectionList($section_list->reveal()); + + // The plugin returns the initial value. + $this->assertSame('value 1', $this->plugin->getThirdPartySetting('the_module', 'the_key')); + + // When the section list is updated, also update the result returned. + $section_list->setThirdPartySetting('the_module', 'the_key', 'value 2')->shouldBeCalled()->will(function ($args) { + $this->getThirdPartySetting('the_module', 'the_key', NULL)->willReturn($args[2]); + }); + + // Update the plugin value. + $this->plugin->setThirdPartySetting('the_module', 'the_key', 'value 2'); + // Assert that the returned value matches. + $this->assertSame('value 2', $this->plugin->getThirdPartySetting('the_module', 'the_key')); + } + + /** * @covers ::extractIdFromRoute * * @dataProvider providerTestExtractIdFromRoute diff -r e200cb7efeb3 -r c2387f117808 core/modules/link/src/Plugin/Field/FieldWidget/LinkWidget.php --- a/core/modules/link/src/Plugin/Field/FieldWidget/LinkWidget.php Thu Apr 26 11:26:54 2018 +0100 +++ b/core/modules/link/src/Plugin/Field/FieldWidget/LinkWidget.php Tue Jul 10 15:07:59 2018 +0100 @@ -101,7 +101,7 @@ */ protected static function getUserEnteredStringAsUri($string) { // By default, assume the entered string is an URI. - $uri = $string; + $uri = trim($string); // Detect entity autocomplete string, map to 'entity:' URI. $entity_id = EntityAutocomplete::extractEntityIdFromAutocompleteInput($string); @@ -158,6 +158,17 @@ } /** + * Form element validation handler for the 'title' element. + * + * Requires the URL value if a link title was filled in. + */ + public static function validateTitleNoLink(&$element, FormStateInterface $form_state, $form) { + if ($element['uri']['#value'] === '' && $element['title']['#value'] !== '') { + $form_state->setError($element['uri'], t('The @uri field is required when the @title field is specified.', ['@title' => $element['title']['#title'], '@uri' => $element['uri']['#title']])); + } + } + + /** * {@inheritdoc} */ public function formElement(FieldItemListInterface $items, $delta, array $element, array &$form, FormStateInterface $form_state) { @@ -222,8 +233,12 @@ // Post-process the title field to make it conditionally required if URL is // non-empty. Omit the validation on the field edit form, since the field // settings cannot be saved otherwise. + // + // Validate that title field is filled out (regardless of uri) when it is a + // required field. if (!$this->isDefaultValueWidget($form_state) && $this->getFieldSetting('title') === DRUPAL_REQUIRED) { $element['#element_validate'][] = [get_called_class(), 'validateTitleElement']; + $element['#element_validate'][] = [get_called_class(), 'validateTitleNoLink']; if (!$element['title']['#required']) { // Make title required on the front-end when URI filled-in. @@ -242,6 +257,12 @@ } } + // Ensure that a URI is always entered when an optional title field is + // submitted. + if (!$this->isDefaultValueWidget($form_state) && $this->getFieldSetting('title') == DRUPAL_OPTIONAL) { + $element['#element_validate'][] = [get_called_class(), 'validateTitleNoLink']; + } + // Exposing the attributes array in the widget is left for alternate and more // advanced field widgets. $element['attributes'] = [ diff -r e200cb7efeb3 -r c2387f117808 core/modules/link/tests/src/Functional/LinkFieldTest.php --- a/core/modules/link/tests/src/Functional/LinkFieldTest.php Thu Apr 26 11:26:54 2018 +0100 +++ b/core/modules/link/tests/src/Functional/LinkFieldTest.php Tue Jul 10 15:07:59 2018 +0100 @@ -121,6 +121,10 @@ '/?example=llama' => '<front>?example=llama', '/#example' => '<front>#example', + // Trailing spaces should be ignored. + '/ ' => '<front>', + '/path with spaces ' => '/path with spaces', + // @todo '' is valid input for BC reasons, may be removed by // https://www.drupal.org/node/2421941 '' => '<front>', @@ -200,7 +204,7 @@ preg_match('|entity_test/manage/(\d+)|', $this->getUrl(), $match); $id = $match[1]; $this->assertText(t('entity_test @id has been created.', ['@id' => $id])); - $this->assertRaw($string); + $this->assertRaw('"' . $string . '"'); } } @@ -281,6 +285,14 @@ $this->assertRaw('placeholder="Enter the text for this link"'); $this->assertFieldByName("{$field_name}[0][title]", '', 'Link text field found.'); + if ($title_setting === DRUPAL_OPTIONAL) { + // Verify that the URL is required, if the link text is non-empty. + $edit = [ + "{$field_name}[0][title]" => 'Example', + ]; + $this->drupalPostForm(NULL, $edit, t('Save')); + $this->assertText(t('The URL field is required when the @title field is specified.', ['@title' => t('Link text')])); + } if ($title_setting === DRUPAL_REQUIRED) { // Verify that the link text is required, if the URL is non-empty. $edit = [ diff -r e200cb7efeb3 -r c2387f117808 core/modules/locale/locale.batch.inc --- a/core/modules/locale/locale.batch.inc Thu Apr 26 11:26:54 2018 +0100 +++ b/core/modules/locale/locale.batch.inc Tue Jul 10 15:07:59 2018 +0100 @@ -292,7 +292,7 @@ * File object if download was successful. FALSE on failure. */ function locale_translation_download_source($source_file, $directory = 'temporary://') { - if ($uri = system_retrieve_file($source_file->uri, $directory)) { + if ($uri = system_retrieve_file($source_file->uri, $directory, FALSE, FILE_EXISTS_REPLACE)) { $file = clone($source_file); $file->type = LOCALE_TRANSLATION_LOCAL; $file->uri = $uri; diff -r e200cb7efeb3 -r c2387f117808 core/modules/locale/locale.module --- a/core/modules/locale/locale.module Thu Apr 26 11:26:54 2018 +0100 +++ b/core/modules/locale/locale.module Tue Jul 10 15:07:59 2018 +0100 @@ -261,13 +261,13 @@ * * The index is computed from the formula of this language. * - * @param $count + * @param int $count * Number to return plural for. - * @param $langcode - * Optional language code to translate to a language other than - * what is used to display the page. + * @param string|null $langcode + * (optional) Language code to translate to a language other than what is used + * to display the page, or NULL for current language. Defaults to NULL. * - * @return + * @return int * The numeric index of the plural variant to use for this $langcode and * $count combination or -1 if the language was not found or does not have a * plural formula. @@ -1113,9 +1113,6 @@ * @param string $filepath * File name to parse. * - * @return array - * Array of string objects to update indexed by context and source. - * * @throws Exception * If a non-local file is attempted to be parsed. */ @@ -1217,10 +1214,11 @@ * files are rebuilt (with locale_update_js_files()) the next time a * request is served in that language. * - * @param $langcode - * The language code for which the file needs to be refreshed. + * @param string|null $langcode + * (optional) The language code for which the file needs to be refreshed, or + * NULL to refresh all languages. Defaults to NULL. * - * @return + * @return array * New content of the 'system.javascript_parsed' variable. */ function _locale_invalidate_js($langcode = NULL) { @@ -1245,8 +1243,9 @@ /** * (Re-)Creates the JavaScript translation file for a language. * - * @param $langcode - * The language, the translation file should be (re)created for. + * @param string|null $langcode + * (optional) The language that the translation file should be (re)created + * for, or NULL for the current language. Defaults to NULL. * * @return bool * TRUE if translation file exists, FALSE otherwise. diff -r e200cb7efeb3 -r c2387f117808 core/modules/locale/src/PoDatabaseWriter.php --- a/core/modules/locale/src/PoDatabaseWriter.php Thu Apr 26 11:26:54 2018 +0100 +++ b/core/modules/locale/src/PoDatabaseWriter.php Tue Jul 10 15:07:59 2018 +0100 @@ -16,7 +16,7 @@ * An associative array indicating what data should be overwritten, if any. * * Elements of the array: - * - override_options + * - overwrite_options * - not_customized: boolean indicating that not customized strings should * be overwritten. * - customized: boolean indicating that customized strings should be @@ -109,6 +109,16 @@ /** * Set the options for the current writer. + * + * @param array $options + * An associative array containing: + * - overwrite_options: An array of options. Each option contains: + * - not_customized: Boolean indicating that not customized strings should + * be overwritten. + * - customized: Boolean indicating that customized strings should be + * overwritten. + * - customized: The strings being imported should be saved as customized. + * One of LOCALE_CUSTOMIZED or LOCALE_NOT_CUSTOMIZED. */ public function setOptions(array $options) { if (!isset($options['overwrite_options'])) { diff -r e200cb7efeb3 -r c2387f117808 core/modules/locale/tests/src/Functional/LocaleConfigTranslationImportTest.php --- a/core/modules/locale/tests/src/Functional/LocaleConfigTranslationImportTest.php Thu Apr 26 11:26:54 2018 +0100 +++ b/core/modules/locale/tests/src/Functional/LocaleConfigTranslationImportTest.php Tue Jul 10 15:07:59 2018 +0100 @@ -25,11 +25,6 @@ */ protected function setUp() { parent::setUp(); - - // @todo Re-enable the test and only skip it when the translation cannot be - // downloaded, or provide a translation as a fixture instead. See - // https://www.drupal.org/project/drupal/issues/2828143. - $this->markTestSkipped(); } /** @@ -51,6 +46,7 @@ // tests. $this->config('locale.settings') ->set('translation.import_enabled', TRUE) + ->set('translation.use_source', LOCALE_TRANSLATION_USE_SOURCE_LOCAL) ->save(); // Add translation permissions now that the locale module has been enabled. @@ -96,6 +92,7 @@ // tests. $this->config('locale.settings') ->set('translation.import_enabled', TRUE) + ->set('translation.use_source', LOCALE_TRANSLATION_USE_SOURCE_LOCAL) ->save(); // Add predefined language. @@ -154,6 +151,7 @@ // tests. $this->config('locale.settings') ->set('translation.import_enabled', TRUE) + ->set('translation.use_source', LOCALE_TRANSLATION_USE_SOURCE_LOCAL) ->save(); // Add predefined language. @@ -191,6 +189,7 @@ // tests. $this->config('locale.settings') ->set('translation.import_enabled', TRUE) + ->set('translation.use_source', LOCALE_TRANSLATION_USE_SOURCE_LOCAL) ->save(); // Add predefined language. diff -r e200cb7efeb3 -r c2387f117808 core/modules/locale/tests/src/Functional/LocaleConfigTranslationTest.php --- a/core/modules/locale/tests/src/Functional/LocaleConfigTranslationTest.php Thu Apr 26 11:26:54 2018 +0100 +++ b/core/modules/locale/tests/src/Functional/LocaleConfigTranslationTest.php Tue Jul 10 15:07:59 2018 +0100 @@ -38,6 +38,7 @@ // tests. $this->config('locale.settings') ->set('translation.import_enabled', TRUE) + ->set('translation.use_source', LOCALE_TRANSLATION_USE_SOURCE_LOCAL) ->save(); // Add custom language. diff -r e200cb7efeb3 -r c2387f117808 core/modules/locale/tests/src/Functional/LocaleImportFunctionalTest.php --- a/core/modules/locale/tests/src/Functional/LocaleImportFunctionalTest.php Thu Apr 26 11:26:54 2018 +0100 +++ b/core/modules/locale/tests/src/Functional/LocaleImportFunctionalTest.php Tue Jul 10 15:07:59 2018 +0100 @@ -52,6 +52,7 @@ // tests. $this->config('locale.settings') ->set('translation.import_enabled', TRUE) + ->set('translation.use_source', LOCALE_TRANSLATION_USE_SOURCE_LOCAL) ->save(); } diff -r e200cb7efeb3 -r c2387f117808 core/modules/locale/tests/src/Functional/LocaleNonInteractiveDevInstallTest.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/core/modules/locale/tests/src/Functional/LocaleNonInteractiveDevInstallTest.php Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,21 @@ +root . '/core/includes/install.core.inc'; + $version = _install_get_version_info(\Drupal::VERSION); + return $version['major'] . '.' . $version['minor'] . '.x'; + } + +} diff -r e200cb7efeb3 -r c2387f117808 core/modules/locale/tests/src/Functional/LocaleNonInteractiveInstallTest.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/core/modules/locale/tests/src/Functional/LocaleNonInteractiveInstallTest.php Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,57 @@ +root . '/core/includes/install.core.inc'; + $version = _install_get_version_info(\Drupal::VERSION); + return $version['major'] . '.0.0'; + } + + /** + * {@inheritdoc} + */ + protected function installParameters() { + $parameters = parent::installParameters(); + // Install Drupal in German. + $parameters['parameters']['langcode'] = 'de'; + // Create a po file so we don't attempt to download one from + // localize.drupal.org and to have a test translation that will not change. + \Drupal::service('file_system')->mkdir($this->publicFilesDirectory . '/translations', NULL, TRUE); + $contents = <<getVersionStringToTest(); + file_put_contents($this->publicFilesDirectory . "/translations/drupal-{$version}.de.po", $contents); + return $parameters; + } + + /** + * Tests that the expected translated text appears on the login screen. + */ + public function testInstallerTranslations() { + $this->drupalGet('user/login'); + $this->assertSession()->responseContains('Geben sie das Passwort für ihren Benutzernamen ein.'); + } + +} diff -r e200cb7efeb3 -r c2387f117808 core/modules/locale/tests/src/Functional/LocaleTranslationDownloadTest.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/core/modules/locale/tests/src/Functional/LocaleTranslationDownloadTest.php Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,65 @@ +container->get('module_handler'); + $moduleHandler->loadInclude('locale', 'inc', 'locale.batch'); + ConfigurableLanguage::createFromLangcode('de')->save(); + + // Let the translations:// stream wrapper point to a virtual file system to + // make it independent from the test environment. + $this->translationsStream = vfsStream::setup('translations'); + \Drupal::configFactory()->getEditable('locale.settings') + ->set('translation.path', $this->translationsStream->url()) + ->save(); + } + + /** + * Tests translation download from remote sources. + */ + public function testUpdateImportSourceRemote() { + + // Provide remote and 'previously' downloaded translation file. + $this->setTranslationFiles(); + vfsStream::create([ + 'contrib_module_one-8.x-1.1.de._po' => '__old_content__', + ], $this->translationsStream); + + $url = \Drupal::service('url_generator')->generateFromRoute('', [], ['absolute' => TRUE]); + $uri = $url . PublicStream::basePath() . '/remote/8.x/contrib_module_one/contrib_module_one-8.x-1.1.de._po'; + $source_file = (object) [ + 'uri' => $uri, + ]; + + $result = locale_translation_download_source($source_file, 'translations://'); + + $this->assertEquals('translations://contrib_module_one-8.x-1.1.de._po', $result->uri); + $this->assertFalse(file_exists('translations://contrib_module_one-8.x-1.1.de_0._po')); + $this->assertTrue(file_exists('translations://contrib_module_one-8.x-1.1.de._po')); + $this->assertNotContains('__old_content__', file_get_contents('translations://contrib_module_one-8.x-1.1.de._po')); + } + +} diff -r e200cb7efeb3 -r c2387f117808 core/modules/locale/tests/src/Functional/LocaleUpdateBase.php --- a/core/modules/locale/tests/src/Functional/LocaleUpdateBase.php Thu Apr 26 11:26:54 2018 +0100 +++ b/core/modules/locale/tests/src/Functional/LocaleUpdateBase.php Tue Jul 10 15:07:59 2018 +0100 @@ -63,6 +63,7 @@ // tests. $this->config('locale.settings') ->set('translation.import_enabled', TRUE) + ->set('translation.use_source', LOCALE_TRANSLATION_USE_SOURCE_LOCAL) ->save(); } diff -r e200cb7efeb3 -r c2387f117808 core/modules/locale/tests/src/Functional/LocaleUpdateCronTest.php --- a/core/modules/locale/tests/src/Functional/LocaleUpdateCronTest.php Thu Apr 26 11:26:54 2018 +0100 +++ b/core/modules/locale/tests/src/Functional/LocaleUpdateCronTest.php Tue Jul 10 15:07:59 2018 +0100 @@ -84,7 +84,7 @@ // Check whether tasks are added to the queue. $queue = \Drupal::queue('locale_translation', TRUE); - $this->assertEqual($queue->numberOfItems(), 3, 'Queue holds tasks for one project.'); + $this->assertEqual($queue->numberOfItems(), 2, 'Queue holds tasks for one project.'); $item = $queue->claimItem(); $queue->releaseItem($item); $this->assertEqual($item->data[1][0], 'contrib_module_two', 'Queue holds tasks for contrib module one.'); @@ -95,7 +95,7 @@ // Check whether no more tasks are added to the queue. $queue = \Drupal::queue('locale_translation', TRUE); - $this->assertEqual($queue->numberOfItems(), 3, 'Queue holds tasks for one project.'); + $this->assertEqual($queue->numberOfItems(), 2, 'Queue holds tasks for one project.'); // Ensure last checked is updated to a greater time than the initial value. sleep(1); diff -r e200cb7efeb3 -r c2387f117808 core/modules/media/tests/src/Functional/Hal/MediaHalJsonAnonTest.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/core/modules/media/tests/src/Functional/Hal/MediaHalJsonAnonTest.php Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,174 @@ +applyHalFieldNormalization($default_normalization); + + $file = File::load(1); + $thumbnail = File::load(2); + $author = User::load($this->entity->getOwnerId()); + return $normalization + [ + '_links' => [ + 'self' => [ + 'href' => $this->baseUrl . '/media/1?_format=hal_json', + ], + 'type' => [ + 'href' => $this->baseUrl . '/rest/type/media/camelids', + ], + $this->baseUrl . '/rest/relation/media/camelids/field_media_file' => [ + [ + 'href' => $file->url(), + 'lang' => 'en', + ], + ], + $this->baseUrl . '/rest/relation/media/camelids/revision_user' => [ + [ + 'href' => $this->baseUrl . '/user/' . $author->id() . '?_format=hal_json', + ], + ], + $this->baseUrl . '/rest/relation/media/camelids/thumbnail' => [ + [ + 'href' => $thumbnail->url(), + 'lang' => 'en', + ], + ], + $this->baseUrl . '/rest/relation/media/camelids/uid' => [ + [ + 'href' => $this->baseUrl . '/user/' . $author->id() . '?_format=hal_json', + 'lang' => 'en', + ], + ], + ], + '_embedded' => [ + $this->baseUrl . '/rest/relation/media/camelids/field_media_file' => [ + [ + '_links' => [ + 'self' => [ + 'href' => $file->url(), + ], + 'type' => [ + 'href' => $this->baseUrl . '/rest/type/file/file', + ], + ], + 'lang' => 'en', + 'uuid' => [ + [ + 'value' => $file->uuid(), + ], + ], + ], + ], + $this->baseUrl . '/rest/relation/media/camelids/revision_user' => [ + [ + '_links' => [ + 'self' => [ + 'href' => $this->baseUrl . '/user/' . $author->id() . '?_format=hal_json', + ], + 'type' => [ + 'href' => $this->baseUrl . '/rest/type/user/user', + ], + ], + 'uuid' => [ + [ + 'value' => $author->uuid(), + ], + ], + ], + ], + $this->baseUrl . '/rest/relation/media/camelids/thumbnail' => [ + [ + '_links' => [ + 'self' => [ + 'href' => $thumbnail->url(), + ], + 'type' => [ + 'href' => $this->baseUrl . '/rest/type/file/file', + ], + ], + 'lang' => 'en', + 'uuid' => [ + [ + 'value' => $thumbnail->uuid(), + ], + ], + ], + ], + $this->baseUrl . '/rest/relation/media/camelids/uid' => [ + [ + '_links' => [ + 'self' => [ + 'href' => $this->baseUrl . '/user/' . $author->id() . '?_format=hal_json', + ], + 'type' => [ + 'href' => $this->baseUrl . '/rest/type/user/user', + ], + ], + 'uuid' => [ + [ + 'value' => $author->uuid(), + ], + ], + 'lang' => 'en', + ], + ], + ], + ]; + } + + /** + * {@inheritdoc} + */ + protected function getNormalizedPostEntity() { + return parent::getNormalizedPostEntity() + [ + '_links' => [ + 'type' => [ + 'href' => $this->baseUrl . '/rest/type/media/camelids', + ], + ], + ]; + } + + /** + * {@inheritdoc} + */ + protected function getExpectedCacheTags() { + return Cache::mergeTags(parent::getExpectedCacheTags(), ['config:hal.settings']); + } + +} diff -r e200cb7efeb3 -r c2387f117808 core/modules/media/tests/src/Functional/Hal/MediaHalJsonBasicAuthTest.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/core/modules/media/tests/src/Functional/Hal/MediaHalJsonBasicAuthTest.php Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,24 @@ +drupalGet('media/' . $first_media_item->id()); $assert_session->statusCodeEquals(200); $assert_session->pageTextContains($first_media_item->getName()); + $assert_session->elementsCount('css', '.media--view-mode-full', 1); // Go to second media item. $this->drupalGet('media/' . $second_media_item->id()); diff -r e200cb7efeb3 -r c2387f117808 core/modules/media/tests/src/Functional/Rest/MediaJsonAnonTest.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/core/modules/media/tests/src/Functional/Rest/MediaJsonAnonTest.php Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,24 @@ +grantPermissionsToTestedRole(['view media']); + break; + + case 'POST': + $this->grantPermissionsToTestedRole(['create camelids media']); + break; + + case 'PATCH': + $this->grantPermissionsToTestedRole(['edit any camelids media']); + // @todo Remove this in https://www.drupal.org/node/2824851. + $this->grantPermissionsToTestedRole(['access content']); + break; + + case 'DELETE': + $this->grantPermissionsToTestedRole(['delete any camelids media']); + break; + } + } + + /** + * {@inheritdoc} + */ + protected function createEntity() { + if (!MediaType::load('camelids')) { + // Create a "Camelids" media type. + $media_type = MediaType::create([ + 'name' => 'Camelids', + 'id' => 'camelids', + 'description' => 'Camelids are large, strictly herbivorous animals with slender necks and long legs.', + 'source' => 'file', + ]); + $media_type->save(); + // Create the source field. + $source_field = $media_type->getSource()->createSourceField($media_type); + $source_field->getFieldStorageDefinition()->save(); + $source_field->save(); + $media_type + ->set('source_configuration', [ + 'source_field' => $source_field->getName(), + ]) + ->save(); + } + + // Create a file to upload. + $file = File::create([ + 'uri' => 'public://llama.txt', + ]); + $file->setPermanent(); + $file->save(); + + // Create a "Llama" media item. + $media = Media::create([ + 'bundle' => 'camelids', + 'field_media_file' => [ + 'target_id' => $file->id(), + ], + ]); + $media + ->setName('Llama') + ->setPublished(TRUE) + ->setCreatedTime(123456789) + ->setOwnerId(static::$auth ? $this->account->id() : 0) + ->setRevisionUserId(static::$auth ? $this->account->id() : 0) + ->save(); + + return $media; + } + + /** + * {@inheritdoc} + */ + protected function getExpectedNormalizedEntity() { + $file = File::load(1); + $thumbnail = File::load(2); + $author = User::load($this->entity->getOwnerId()); + return [ + 'mid' => [ + [ + 'value' => 1, + ], + ], + 'uuid' => [ + [ + 'value' => $this->entity->uuid(), + ], + ], + 'vid' => [ + [ + 'value' => 1, + ], + ], + 'langcode' => [ + [ + 'value' => 'en', + ], + ], + 'bundle' => [ + [ + 'target_id' => 'camelids', + 'target_type' => 'media_type', + 'target_uuid' => MediaType::load('camelids')->uuid(), + ], + ], + 'name' => [ + [ + 'value' => 'Llama', + ], + ], + 'field_media_file' => [ + [ + 'description' => NULL, + 'display' => NULL, + 'target_id' => (int) $file->id(), + 'target_type' => 'file', + 'target_uuid' => $file->uuid(), + 'url' => $file->url(), + ], + ], + 'thumbnail' => [ + [ + 'alt' => 'Thumbnail', + 'width' => 180, + 'height' => 180, + 'target_id' => (int) $thumbnail->id(), + 'target_type' => 'file', + 'target_uuid' => $thumbnail->uuid(), + 'title' => 'Llama', + 'url' => $thumbnail->url(), + ], + ], + 'status' => [ + [ + 'value' => TRUE, + ], + ], + 'created' => [ + $this->formatExpectedTimestampItemValues(123456789), + ], + 'changed' => [ + $this->formatExpectedTimestampItemValues($this->entity->getChangedTime()), + ], + 'revision_created' => [ + $this->formatExpectedTimestampItemValues((int) $this->entity->getRevisionCreationTime()), + ], + 'default_langcode' => [ + [ + 'value' => TRUE, + ], + ], + 'uid' => [ + [ + 'target_id' => (int) $author->id(), + 'target_type' => 'user', + 'target_uuid' => $author->uuid(), + 'url' => base_path() . 'user/' . $author->id(), + ], + ], + 'revision_user' => [ + [ + 'target_id' => (int) $author->id(), + 'target_type' => 'user', + 'target_uuid' => $author->uuid(), + 'url' => base_path() . 'user/' . $author->id(), + ], + ], + 'revision_log_message' => [], + 'revision_translation_affected' => [ + [ + 'value' => TRUE, + ], + ], + ]; + } + + /** + * {@inheritdoc} + */ + protected function getNormalizedPostEntity() { + return [ + 'bundle' => [ + [ + 'target_id' => 'camelids', + ], + ], + 'name' => [ + [ + 'value' => 'Dramallama', + ], + ], + ]; + } + + /** + * {@inheritdoc} + */ + protected function getExpectedUnauthorizedAccessMessage($method) { + if ($this->config('rest.settings')->get('bc_entity_resource_permissions')) { + return parent::getExpectedUnauthorizedAccessMessage($method); + } + + switch ($method) { + case 'GET'; + return "The 'view media' permission is required and the media item must be published."; + + case 'PATCH': + return 'You are not authorized to update this media entity of bundle camelids.'; + + case 'DELETE': + return 'You are not authorized to delete this media entity of bundle camelids.'; + + default: + return parent::getExpectedUnauthorizedAccessMessage($method); + } + } + + /** + * {@inheritdoc} + */ + public function testPost() { + $this->markTestSkipped('POSTing File Media items is not supported until https://www.drupal.org/node/1927648 is solved.'); + } + + /** + * {@inheritdoc} + */ + protected function getExpectedUnauthorizedAccessCacheability() { + // @see \Drupal\media\MediaAccessControlHandler::checkAccess() + return parent::getExpectedUnauthorizedAccessCacheability() + ->addCacheTags(['media:1']); + } + +} diff -r e200cb7efeb3 -r c2387f117808 core/modules/media/tests/src/Functional/Rest/MediaTypeJsonAnonTest.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/core/modules/media/tests/src/Functional/Rest/MediaTypeJsonAnonTest.php Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,24 @@ +grantPermissionsToTestedRole(['administer media types']); + } + + /** + * {@inheritdoc} + */ + protected function createEntity() { + // Create a "Camelids" media type. + $camelids = MediaType::create([ + 'name' => 'Camelids', + 'id' => 'camelids', + 'description' => 'Camelids are large, strictly herbivorous animals with slender necks and long legs.', + 'source' => 'file', + ]); + + $camelids->save(); + + return $camelids; + } + + /** + * {@inheritdoc} + */ + protected function getExpectedNormalizedEntity() { + return [ + 'dependencies' => [], + 'description' => 'Camelids are large, strictly herbivorous animals with slender necks and long legs.', + 'field_map' => [], + 'id' => 'camelids', + 'label' => NULL, + 'langcode' => 'en', + 'new_revision' => FALSE, + 'queue_thumbnail_downloads' => FALSE, + 'source' => 'file', + 'source_configuration' => [ + 'source_field' => '', + ], + 'status' => TRUE, + 'uuid' => $this->entity->uuid(), + ]; + } + + /** + * {@inheritdoc} + */ + protected function getNormalizedPostEntity() { + // @todo Update in https://www.drupal.org/node/2300677. + } + +} diff -r e200cb7efeb3 -r c2387f117808 core/modules/media/tests/src/Functional/Rest/MediaTypeXmlAnonTest.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/core/modules/media/tests/src/Functional/Rest/MediaTypeXmlAnonTest.php Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,26 @@ +" and is not routed, we will get + # back an URI of the form "base:node/". + plugin: link_uri + source: + - link_path + validate_route: false + - + # Isolate the node ID. + plugin: explode + delimiter: 'base:node/' + - + # Extract the node ID. + plugin: extract + default: false + index: + - 1 + - + # Skip row if node ID is empty. + plugin: skip_on_empty + method: row + - + # With the old node ID in hand, lookup in the d6_node_translation or + # d7_node_translation mapping tables to find the new node ID. + plugin: migration_lookup + migration: + - d6_node_translation + - d7_node_translation + no_stub: true + - + # Skip row if the new node ID is empty. + plugin: skip_on_empty + method: row + - + # Extract the node ID. The migration lookup will return an array with two + # items, the new node ID and the translation langcode. We need the node ID + # which is at index 0. + plugin: extract + index: + - 0 + # This will be used in the "link/uri" and "route" processes below. + link_path: + plugin: concat + source: + - 'constants/node_prefix' + - '@new_nid' + link/uri: + plugin: concat + source: + - 'constants/entity_prefix' + - '@link_path' + link/options: options + route: + plugin: route + source: + - '@link_path' + - options + route_name: '@route/route_name' + route_parameters: '@route/route_parameters' + url: '@route/url' + options: '@route/options' + external: external + weight: weight + expanded: expanded + enabled: enabled + parent: + plugin: menu_link_parent + source: + - plid + - '@menu_name' + - parent_link_path + changed: updated +destination: + plugin: entity:menu_link_content + default_bundle: menu_link_content + no_stub: true +migration_dependencies: + optional: + - d6_menu_links + - d6_node_translation + - d7_menu_links + - d7_node_translation diff -r e200cb7efeb3 -r c2387f117808 core/modules/menu_link_content/src/Entity/MenuLinkContent.php --- a/core/modules/menu_link_content/src/Entity/MenuLinkContent.php Thu Apr 26 11:26:54 2018 +0100 +++ b/core/modules/menu_link_content/src/Entity/MenuLinkContent.php Tue Jul 10 15:07:59 2018 +0100 @@ -228,6 +228,14 @@ foreach ($entities as $menu_link) { /** @var \Drupal\menu_link_content\Entity\MenuLinkContent $menu_link */ $menu_link_manager->removeDefinition($menu_link->getPluginId(), FALSE); + + // Children get re-attached to the menu link's parent. + $parent_plugin_id = $menu_link->getParentId(); + $children = $storage->loadByProperties(['parent' => $menu_link->getPluginId()]); + foreach ($children as $child) { + /** @var \Drupal\menu_link_content\Entity\MenuLinkContent $child */ + $child->set('parent', $parent_plugin_id)->save(); + } } } diff -r e200cb7efeb3 -r c2387f117808 core/modules/menu_link_content/src/Plugin/migrate/process/LinkUri.php --- a/core/modules/menu_link_content/src/Plugin/migrate/process/LinkUri.php Thu Apr 26 11:26:54 2018 +0100 +++ b/core/modules/menu_link_content/src/Plugin/migrate/process/LinkUri.php Tue Jul 10 15:07:59 2018 +0100 @@ -14,6 +14,8 @@ /** * Processes a link path into an 'internal:' or 'entity:' URI. * + * @todo: Add documentation in https://www.drupal.org/node/2954908 + * * @MigrateProcessPlugin( * id = "link_uri" * ) @@ -40,6 +42,9 @@ * The entity type manager, used to fetch entity link templates. */ public function __construct(array $configuration, $plugin_id, $plugin_definition, EntityTypeManagerInterface $entity_type_manager) { + $configuration += [ + 'validate_route' => TRUE, + ]; parent::__construct($configuration, $plugin_id, $plugin_definition); $this->entityTypeManager = $entity_type_manager; } @@ -82,7 +87,15 @@ } } else { - throw new MigrateException(sprintf('The path "%s" failed validation.', $path)); + // If the URL is not routed, we might want to get something back to do + // other processing. If this is the case, the "validate_route" + // configuration option can be set to FALSE to return the URI. + if (!$this->configuration['validate_route']) { + return $url->getUri(); + } + else { + throw new MigrateException(sprintf('The path "%s" failed validation.', $path)); + } } } return $path; diff -r e200cb7efeb3 -r c2387f117808 core/modules/menu_link_content/src/Plugin/migrate/source/d6/MenuLinkTranslation.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/core/modules/menu_link_content/src/Plugin/migrate/source/d6/MenuLinkTranslation.php Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,98 @@ +leftJoin('i18n_strings', 'i18n', 'CAST(ml.mlid as CHAR(255)) = i18n.objectid'); + $query->isNotNull('i18n.lid'); + $query->addField('i18n', 'lid'); + $query->addField('i18n', 'property'); + + // Add in the translation for the property. + $query->innerJoin('locales_target', 'lt', 'i18n.lid = lt.lid'); + $query->addField('lt', 'language'); + $query->addField('lt', 'translation'); + return $query; + } + + /** + * {@inheritdoc} + */ + public function prepareRow(Row $row) { + $language = $row->getSourceProperty('language'); + $mlid = $row->getSourceProperty('mlid'); + + // If this row has been migrated it is a duplicate then skip it. + if ($this->idMap->lookupDestinationIds(['mlid' => $mlid, 'language' => $language])) { + return FALSE; + } + + // Save the translation for this property. + $property = $row->getSourceProperty('property'); + $row->setSourceProperty($property . '_translated', $row->getSourceProperty('translation')); + + // Get the translation, if one exists, for the property not already in the + // row. + $other_property = ($property == 'title') ? 'description' : 'title'; + $query = $this->select('i18n_strings', 'i18n') + ->fields('i18n', ['lid']) + ->condition('i18n.property', $other_property) + ->condition('i18n.objectid', $mlid); + $query->leftJoin('locales_target', 'lt', 'i18n.lid = lt.lid'); + $query->condition('lt.language', $language); + $query->addField('lt', 'translation'); + $results = $query->execute()->fetchAssoc(); + $row->setSourceProperty($other_property . '_translated', $results['translation']); + parent::prepareRow($row); + } + + /** + * {@inheritdoc} + */ + public function fields() { + $fields = [ + 'language' => $this->t('Language for this menu.'), + 'title_translated' => $this->t('Menu link title translation.'), + 'description_translated' => $this->t('Menu link description translation.'), + ]; + return parent::fields() + $fields; + } + + /** + * {@inheritdoc} + */ + public function getIds() { + $ids['language']['type'] = 'string'; + return parent::getIds() + $ids; + } + +} diff -r e200cb7efeb3 -r c2387f117808 core/modules/menu_link_content/tests/src/Functional/Hal/MenuLinkContentHalJsonAnonTest.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/core/modules/menu_link_content/tests/src/Functional/Hal/MenuLinkContentHalJsonAnonTest.php Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,74 @@ +applyHalFieldNormalization($default_normalization); + + return $normalization + [ + '_links' => [ + 'self' => [ + 'href' => $this->baseUrl . '/admin/structure/menu/item/1/edit?_format=hal_json', + ], + 'type' => [ + 'href' => $this->baseUrl . '/rest/type/menu_link_content/menu_link_content', + ], + ], + ]; + } + + /** + * {@inheritdoc} + */ + protected function getNormalizedPostEntity() { + return parent::getNormalizedPostEntity() + [ + '_links' => [ + 'type' => [ + 'href' => $this->baseUrl . '/rest/type/menu_link_content/menu_link_content', + ], + ], + ]; + } + + /** + * {@inheritdoc} + */ + protected function getExpectedCacheContexts() { + // The 'url.site' cache context is added for '_links' in the response. + return Cache::mergeTags(parent::getExpectedCacheContexts(), ['url.site']); + } + +} diff -r e200cb7efeb3 -r c2387f117808 core/modules/menu_link_content/tests/src/Functional/Hal/MenuLinkContentHalJsonBasicAuthTest.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/core/modules/menu_link_content/tests/src/Functional/Hal/MenuLinkContentHalJsonBasicAuthTest.php Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,24 @@ +grantPermissionsToTestedRole(['administer menu']); + break; + } + } + + /** + * {@inheritdoc} + */ + protected function createEntity() { + $menu_link = MenuLinkContent::create([ + 'id' => 'llama', + 'title' => 'Llama Gabilondo', + 'description' => 'Llama Gabilondo', + 'link' => 'https://nl.wikipedia.org/wiki/Llama', + 'weight' => 0, + 'menu_name' => 'main', + ]); + $menu_link->save(); + + return $menu_link; + } + + /** + * {@inheritdoc} + */ + protected function getNormalizedPostEntity() { + return [ + 'title' => [ + [ + 'value' => 'Dramallama', + ], + ], + 'link' => [ + [ + 'uri' => 'http://www.urbandictionary.com/define.php?term=drama%20llama', + ], + ], + 'bundle' => [ + [ + 'value' => 'menu_link_content', + ], + ], + ]; + } + + /** + * {@inheritdoc} + */ + protected function getExpectedNormalizedEntity() { + return [ + 'uuid' => [ + [ + 'value' => $this->entity->uuid(), + ], + ], + 'id' => [ + [ + 'value' => 1, + ], + ], + 'title' => [ + [ + 'value' => 'Llama Gabilondo', + ], + ], + 'link' => [ + [ + 'uri' => 'https://nl.wikipedia.org/wiki/Llama', + 'title' => NULL, + 'options' => [], + ], + ], + 'weight' => [ + [ + 'value' => 0, + ], + ], + 'menu_name' => [ + [ + 'value' => 'main', + ], + ], + 'langcode' => [ + [ + 'value' => 'en', + ], + ], + 'bundle' => [ + [ + 'value' => 'menu_link_content', + ], + ], + 'description' => [ + [ + 'value' => 'Llama Gabilondo', + ], + ], + 'external' => [ + [ + 'value' => FALSE, + ], + ], + 'rediscover' => [ + [ + 'value' => FALSE, + ], + ], + 'expanded' => [ + [ + 'value' => FALSE, + ], + ], + 'enabled' => [ + [ + 'value' => TRUE, + ], + ], + 'changed' => [ + $this->formatExpectedTimestampItemValues($this->entity->getChangedTime()), + ], + 'default_langcode' => [ + [ + 'value' => TRUE, + ], + ], + 'parent' => [], + ]; + } + + /** + * {@inheritdoc} + */ + protected function getExpectedUnauthorizedAccessMessage($method) { + if ($this->config('rest.settings')->get('bc_entity_resource_permissions')) { + return parent::getExpectedUnauthorizedAccessMessage($method); + } + + switch ($method) { + case 'DELETE': + return "You are not authorized to delete this menu_link_content entity."; + default: + return parent::getExpectedUnauthorizedAccessMessage($method); + } + } + +} diff -r e200cb7efeb3 -r c2387f117808 core/modules/menu_link_content/tests/src/Functional/Rest/MenuLinkContentXmlAnonTest.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/core/modules/menu_link_content/tests/src/Functional/Rest/MenuLinkContentXmlAnonTest.php Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,26 @@ +installEntitySchema('menu_link_content'); + } + + /** + * Tests the MenuLinkContent::preDelete function. + */ + public function testMenuLinkContentDelete() { + // Add new menu items in a hierarchy. + $parent = MenuLinkContent::create([ + 'title' => $this->randomMachineName(8), + 'link' => [['uri' => 'internal:/']], + 'menu_name' => 'main', + ]); + $parent->save(); + $child1 = MenuLinkContent::create([ + 'title' => $this->randomMachineName(8), + 'link' => [['uri' => 'internal:/']], + 'menu_name' => 'main', + 'parent' => 'menu_link_content:' . $parent->uuid(), + ]); + $child1->save(); + $child2 = MenuLinkContent::create([ + 'title' => $this->randomMachineName(8), + 'link' => [['uri' => 'internal:/']], + 'menu_name' => 'main', + 'parent' => 'menu_link_content:' . $child1->uuid(), + ]); + $child2->save(); + + // Delete the middle child. + $child1->delete(); + // Refresh $child2. + $child2 = MenuLinkContent::load($child2->id()); + // Test the reference in the child. + $this->assertSame('menu_link_content:' . $parent->uuid(), $child2->getParentId()); + } + +} diff -r e200cb7efeb3 -r c2387f117808 core/modules/menu_link_content/tests/src/Kernel/Migrate/d6/MigrateMenuLinkTest.php --- a/core/modules/menu_link_content/tests/src/Kernel/Migrate/d6/MigrateMenuLinkTest.php Thu Apr 26 11:26:54 2018 +0100 +++ b/core/modules/menu_link_content/tests/src/Kernel/Migrate/d6/MigrateMenuLinkTest.php Tue Jul 10 15:07:59 2018 +0100 @@ -3,19 +3,25 @@ namespace Drupal\Tests\menu_link_content\Kernel\Migrate\d6; use Drupal\menu_link_content\Entity\MenuLinkContent; -use Drupal\Tests\migrate_drupal\Kernel\d6\MigrateDrupal6TestBase; +use Drupal\menu_link_content\MenuLinkContentInterface; +use Drupal\Tests\node\Kernel\Migrate\d6\MigrateNodeTestBase; /** * Menu link migration. * * @group migrate_drupal_6 */ -class MigrateMenuLinkTest extends MigrateDrupal6TestBase { +class MigrateMenuLinkTest extends MigrateNodeTestBase { /** * {@inheritdoc} */ - public static $modules = ['menu_ui', 'menu_link_content']; + public static $modules = [ + 'content_translation', + 'language', + 'menu_link_content', + 'menu_ui', + ]; /** * {@inheritdoc} @@ -23,53 +29,76 @@ protected function setUp() { parent::setUp(); $this->installEntitySchema('menu_link_content'); - $this->executeMigrations(['d6_menu', 'd6_menu_links']); + $this->executeMigrations([ + 'language', + 'd6_language_content_settings', + 'd6_node', + 'd6_node_translation', + 'd6_menu', + 'd6_menu_links', + 'node_translation_menu_links', + ]); + } + + /** + * Asserts various aspects of a menu link entity. + * + * @param string $id + * The link ID. + * @param string $title + * The expected title of the link. + * @param string $menu + * The expected ID of the menu to which the link will belong. + * @param string $description + * The link's expected description. + * @param bool $enabled + * Whether the link is enabled. + * @param bool $expanded + * Whether the link is expanded. + * @param array $attributes + * Additional attributes the link is expected to have. + * @param string $uri + * The expected URI of the link. + * @param int $weight + * The expected weight of the link. + * + * @return \Drupal\menu_link_content\MenuLinkContentInterface + * The menu link content. + */ + protected function assertEntity($id, $title, $menu, $description, $enabled, $expanded, array $attributes, $uri, $weight) { + /** @var \Drupal\menu_link_content\MenuLinkContentInterface $menu_link */ + $menu_link = MenuLinkContent::load($id); + $this->assertInstanceOf(MenuLinkContentInterface::class, $menu_link); + $this->assertSame($title, $menu_link->getTitle()); + $this->assertSame($menu, $menu_link->getMenuName()); + $this->assertSame($description, $menu_link->getDescription()); + $this->assertSame($enabled, $menu_link->isEnabled()); + $this->assertSame($expanded, $menu_link->isExpanded()); + $this->assertSame($attributes, $menu_link->link->options); + $this->assertSame($uri, $menu_link->link->uri); + $this->assertSame($weight, $menu_link->getWeight()); + return $menu_link; } /** * Tests migration of menu links. */ public function testMenuLinks() { - $menu_link = MenuLinkContent::load(138); - $this->assertIdentical('Test 1', $menu_link->getTitle()); - $this->assertIdentical('secondary-links', $menu_link->getMenuName()); - $this->assertIdentical('Test menu link 1', $menu_link->getDescription()); - $this->assertIdentical(TRUE, $menu_link->isEnabled()); - $this->assertIdentical(FALSE, $menu_link->isExpanded()); - $this->assertIdentical(['attributes' => ['title' => 'Test menu link 1']], $menu_link->link->options); - $this->assertIdentical('internal:/user/login', $menu_link->link->uri); - $this->assertIdentical(-50, $menu_link->getWeight()); + $this->assertEntity('138', 'Test 1', 'secondary-links', 'Test menu link 1', TRUE, FALSE, ['attributes' => ['title' => 'Test menu link 1'], 'langcode' => 'en'], 'internal:/user/login', -50); + $this->assertEntity('139', 'Test 2', 'secondary-links', 'Test menu link 2', TRUE, TRUE, ['query' => 'foo=bar', 'attributes' => ['title' => 'Test menu link 2']], 'internal:/admin', -49); + $this->assertEntity('140', 'Drupal.org', 'secondary-links', NULL, TRUE, FALSE, ['attributes' => ['title' => '']], 'https://www.drupal.org', -50); - $menu_link = MenuLinkContent::load(139); - $this->assertIdentical('Test 2', $menu_link->getTitle()); - $this->assertIdentical('secondary-links', $menu_link->getMenuName()); - $this->assertIdentical('Test menu link 2', $menu_link->getDescription()); - $this->assertIdentical(TRUE, $menu_link->isEnabled()); - $this->assertIdentical(TRUE, $menu_link->isExpanded()); - $this->assertIdentical(['query' => 'foo=bar', 'attributes' => ['title' => 'Test menu link 2']], $menu_link->link->options); - $this->assertIdentical('internal:/admin', $menu_link->link->uri); - $this->assertIdentical(-49, $menu_link->getWeight()); + // Assert that missing title attributes don't stop or break migration. + $this->assertEntity('393', 'Test 3', 'secondary-links', NULL, TRUE, FALSE, [], 'internal:/user/login', -47); - $menu_link = MenuLinkContent::load(140); - $this->assertIdentical('Drupal.org', $menu_link->getTitle()); - $this->assertIdentical('secondary-links', $menu_link->getMenuName()); - $this->assertIdentical(NULL, $menu_link->getDescription()); - $this->assertIdentical(TRUE, $menu_link->isEnabled()); - $this->assertIdentical(FALSE, $menu_link->isExpanded()); - $this->assertIdentical(['attributes' => ['title' => '']], $menu_link->link->options); - $this->assertIdentical('https://www.drupal.org', $menu_link->link->uri); - $this->assertIdentical(-50, $menu_link->getWeight()); + // Test the migration of menu links for translated nodes. + $this->assertEntity('459', 'The Real McCoy', 'primary-links', NULL, TRUE, FALSE, ['attributes' => ['title' => ''], 'alter' => TRUE], 'entity:node/10', 0); + $this->assertEntity('460', 'Le Vrai McCoy', 'primary-links', NULL, TRUE, FALSE, ['attributes' => ['title' => ''], 'alter' => TRUE], 'entity:node/10', 0); + $this->assertEntity('461', 'Abantu zulu', 'primary-links', NULL, TRUE, FALSE, ['attributes' => ['title' => ''], 'alter' => TRUE], 'entity:node/12', 0); + $this->assertEntity('462', 'The Zulu People', 'primary-links', NULL, TRUE, FALSE, ['attributes' => ['title' => ''], 'alter' => TRUE], 'entity:node/12', 0); - // assert that missing title attributes don't stop or break migration. - $menu_link = MenuLinkContent::load(393); - $this->assertIdentical('Test 3', $menu_link->getTitle()); - $this->assertIdentical('secondary-links', $menu_link->getMenuName()); - $this->assertIdentical(NULL, $menu_link->getDescription()); - $this->assertIdentical(TRUE, $menu_link->isEnabled()); - $this->assertIdentical(FALSE, $menu_link->isExpanded()); - $this->assertIdentical([], $menu_link->link->options); - $this->assertIdentical('internal:/user/login', $menu_link->link->uri); - $this->assertIdentical(-47, $menu_link->getWeight()); + // Test the migration of menu links translation. + $this->assertEntity('463', 'fr - Test 1', 'secondary-links', 'fr - Test menu link 1', TRUE, FALSE, ['attributes' => ['title' => 'fr - Test menu link 1'], 'langcode' => 'fr', 'alter' => TRUE], 'internal:/user/login', -49); } } diff -r e200cb7efeb3 -r c2387f117808 core/modules/menu_link_content/tests/src/Kernel/Migrate/d6/MigrateMenuLinkTranslationTest.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/core/modules/menu_link_content/tests/src/Kernel/Migrate/d6/MigrateMenuLinkTranslationTest.php Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,93 @@ +migrateContent(); + $this->installSchema('system', ['router']); + $this->installEntitySchema('menu_link_content'); + $this->executeMigrations([ + 'language', + 'd6_menu', + 'd6_menu_links', + 'd6_menu_links_translation', + ]); + } + + /** + * Tests migration of menu links. + */ + public function testMenuLinks() { + /** @var \Drupal\menu_link_content\Entity\MenuLinkContent $menu_link */ + $menu_link = MenuLinkContent::load(139)->getTranslation('fr'); + $this->assertInstanceOf(MenuLinkContent::class, $menu_link); + $this->assertSame('fr - Test 2', $menu_link->getTitle()); + $this->assertSame('fr - Test menu link 2', $menu_link->getDescription()); + $this->assertSame('secondary-links', $menu_link->getMenuName()); + $this->assertTrue($menu_link->isEnabled()); + $this->assertTrue($menu_link->isExpanded()); + $this->assertSame(['query' => 'foo=bar', 'attributes' => ['title' => 'Test menu link 2']], $menu_link->link->options); + $this->assertSame('internal:/admin', $menu_link->link->uri); + $this->assertSame(-49, $menu_link->getWeight()); + + $menu_link = MenuLinkContent::load(139)->getTranslation('zu'); + $this->assertInstanceOf(MenuLinkContent::class, $menu_link); + $this->assertSame('Test 2', $menu_link->getTitle()); + $this->assertSame('zu - Test menu link 2', $menu_link->getDescription()); + $this->assertSame('secondary-links', $menu_link->getMenuName()); + $this->assertTrue($menu_link->isEnabled()); + $this->assertTrue($menu_link->isExpanded()); + $this->assertSame(['query' => 'foo=bar', 'attributes' => ['title' => 'Test menu link 2']], $menu_link->link->options); + $this->assertSame('internal:/admin', $menu_link->link->uri); + $this->assertSame(-49, $menu_link->getWeight()); + + $menu_link = MenuLinkContent::load(140)->getTranslation('fr'); + $this->assertInstanceOf(MenuLinkContent::class, $menu_link); + $this->assertSame('fr - Drupal.org', $menu_link->getTitle()); + $this->assertSame('', $menu_link->getDescription()); + $this->assertSame('secondary-links', $menu_link->getMenuName()); + $this->assertTrue($menu_link->isEnabled()); + $this->assertFalse($menu_link->isExpanded()); + $this->assertSame(['attributes' => ['title' => '']], $menu_link->link->options); + $this->assertSame('https://www.drupal.org', $menu_link->link->uri); + $this->assertSame(-50, $menu_link->getWeight()); + + $menu_link = MenuLinkContent::load(463); + $this->assertInstanceOf(MenuLinkContent::class, $menu_link); + $this->assertSame('fr - Test 1', $menu_link->getTitle()); + $this->assertSame('fr - Test menu link 1', $menu_link->getDescription()); + $this->assertSame('secondary-links', $menu_link->getMenuName()); + $this->assertTrue($menu_link->isEnabled()); + $this->assertFalse($menu_link->isExpanded()); + $attributes = [ + 'attributes' => [ + 'title' => 'fr - Test menu link 1', + ], + 'langcode' => 'fr', + 'alter' => TRUE, + ]; + $this->assertSame($attributes, $menu_link->link->options); + $this->assertSame('internal:/user/login', $menu_link->link->uri); + $this->assertSame(-49, $menu_link->getWeight()); + } + +} diff -r e200cb7efeb3 -r c2387f117808 core/modules/menu_link_content/tests/src/Kernel/Migrate/d7/MigrateMenuLinkTest.php --- a/core/modules/menu_link_content/tests/src/Kernel/Migrate/d7/MigrateMenuLinkTest.php Thu Apr 26 11:26:54 2018 +0100 +++ b/core/modules/menu_link_content/tests/src/Kernel/Migrate/d7/MigrateMenuLinkTest.php Tue Jul 10 15:07:59 2018 +0100 @@ -5,7 +5,6 @@ use Drupal\Core\Menu\MenuTreeParameters; use Drupal\menu_link_content\Entity\MenuLinkContent; use Drupal\menu_link_content\MenuLinkContentInterface; -use Drupal\node\Entity\Node; use Drupal\Tests\migrate_drupal\Kernel\d7\MigrateDrupal7TestBase; /** @@ -19,7 +18,15 @@ /** * {@inheritdoc} */ - public static $modules = ['link', 'menu_ui', 'menu_link_content', 'node']; + public static $modules = [ + 'content_translation', + 'language', + 'link', + 'menu_ui', + 'menu_link_content', + 'node', + 'text', + ]; /** * {@inheritdoc} @@ -28,13 +35,20 @@ parent::setUp(); $this->installEntitySchema('menu_link_content'); $this->installEntitySchema('node'); - $node = Node::create([ - 'nid' => 2, - 'title' => 'node link test', - 'type' => 'article', + $this->installSchema('node', ['node_access']); + $this->installConfig(static::$modules); + $this->executeMigrations([ + 'language', + 'd7_user_role', + 'd7_user', + 'd7_node_type', + 'd7_language_content_settings', + 'd7_node', + 'd7_node_translation', + 'd7_menu', + 'd7_menu_links', + 'node_translation_menu_links', ]); - $node->save(); - $this->executeMigrations(['d7_menu', 'd7_menu_links']); \Drupal::service('router.builder')->rebuild(); } @@ -52,7 +66,7 @@ * @param bool $enabled * Whether the link is enabled. * @param bool $expanded - * Whether the link is expanded + * Whether the link is expanded. * @param array $attributes * Additional attributes the link is expected to have. * @param string $uri @@ -66,11 +80,9 @@ protected function assertEntity($id, $title, $menu, $description, $enabled, $expanded, array $attributes, $uri, $weight) { /** @var \Drupal\menu_link_content\MenuLinkContentInterface $menu_link */ $menu_link = MenuLinkContent::load($id); - $this->assertTrue($menu_link instanceof MenuLinkContentInterface); + $this->assertInstanceOf(MenuLinkContentInterface::class, $menu_link); $this->assertSame($title, $menu_link->getTitle()); $this->assertSame($menu, $menu_link->getMenuName()); - // The migration sets the description of the link to the value of the - // 'title' attribute. Bit strange, but there you go. $this->assertSame($description, $menu_link->getDescription()); $this->assertSame($enabled, $menu_link->isEnabled()); $this->assertSame($expanded, $menu_link->isExpanded()); @@ -120,6 +132,12 @@ } } $this->assertTrue($found); + + // Test the migration of menu links for translated nodes. + $this->assertEntity(484, 'The thing about Deep Space 9', 'tools', NULL, TRUE, FALSE, ['attributes' => ['title' => '']], 'entity:node/2', 9); + $this->assertEntity(485, 'is - The thing about Deep Space 9', 'tools', NULL, TRUE, FALSE, ['attributes' => ['title' => '']], 'entity:node/2', 10); + $this->assertEntity(486, 'is - The thing about Firefly', 'tools', NULL, TRUE, FALSE, ['attributes' => ['title' => '']], 'entity:node/4', 11); + $this->assertEntity(487, 'en - The thing about Firefly', 'tools', NULL, TRUE, FALSE, ['attributes' => ['title' => '']], 'entity:node/4', 12); } } diff -r e200cb7efeb3 -r c2387f117808 core/modules/menu_link_content/tests/src/Kernel/Plugin/migrate/process/LinkUriTest.php --- a/core/modules/menu_link_content/tests/src/Kernel/Plugin/migrate/process/LinkUriTest.php Thu Apr 26 11:26:54 2018 +0100 +++ b/core/modules/menu_link_content/tests/src/Kernel/Plugin/migrate/process/LinkUriTest.php Tue Jul 10 15:07:59 2018 +0100 @@ -6,6 +6,7 @@ use Drupal\migrate\MigrateException; use Drupal\migrate\MigrateExecutableInterface; use Drupal\migrate\Row; +use Drupal\node\Entity\Node; use Drupal\KernelTests\KernelTestBase; /** @@ -18,6 +19,22 @@ class LinkUriTest extends KernelTestBase { /** + * Modules to enable. + * + * @var array + */ + public static $modules = ['node', 'user']; + + /** + * {@inheritdoc} + */ + public function setUp() { + parent::setUp(); + $this->installEntitySchema('node'); + $this->installEntitySchema('user'); + } + + /** * Tests LinkUri::transform(). * * @param array $value @@ -99,21 +116,69 @@ } /** + * Tests disabling route validation in LinkUri::transform(). + * + * @param array $value + * The value to pass to LinkUri::transform(). + * @param string $expected + * The expected return value of LinkUri::transform(). + * + * @dataProvider providerTestDisablingRouteValidation + * + * @covers ::transform + */ + public function testDisablingRouteValidation(array $value, $expected) { + // Create a node so we have a valid route. + Node::create([ + 'nid' => 1, + 'title' => 'test', + 'type' => 'page', + ])->save(); + + $actual = $this->doTransform($value, ['validate_route' => FALSE]); + $this->assertSame($expected, $actual); + } + + /** + * Provides test cases for LinkUriTest::testDisablingRouteValidation(). + * + * @return array + * An array of test cases, each which the following values: + * - The value array to pass to LinkUri::transform(). + * - The expected path returned by LinkUri::transform(). + */ + public function providerTestDisablingRouteValidation() { + $tests = []; + + $value = ['node/1']; + $expected = 'entity:node/1'; + $tests['routed'] = [$value, $expected]; + + $value = ['node/2']; + $expected = 'base:node/2'; + $tests['unrouted'] = [$value, $expected]; + + return $tests; + } + + /** * Transforms a link path into an 'internal:' or 'entity:' URI. * * @param array $value * The value to pass to LinkUri::transform(). + * @param array $configuration + * The plugin configuration. * * @return string * The transformed link. */ - public function doTransform(array $value) { + public function doTransform(array $value, $configuration = []) { $entityTypeManager = $this->container->get('entity_type.manager'); $routeBuilder = $this->container->get('router.builder'); $row = new Row(); $executable = $this->prophesize(MigrateExecutableInterface::class)->reveal(); - $plugin = new LinkUri([], 'link_uri', [], $entityTypeManager, $routeBuilder); + $plugin = new LinkUri($configuration, 'link_uri', [], $entityTypeManager, $routeBuilder); $actual = $plugin->transform($value, $executable, $row, 'destinationproperty'); return $actual; diff -r e200cb7efeb3 -r c2387f117808 core/modules/menu_link_content/tests/src/Kernel/Plugin/migrate/source/d6/MenuLinkTranslationTest.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/core/modules/menu_link_content/tests/src/Kernel/Plugin/migrate/source/d6/MenuLinkTranslationTest.php Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,250 @@ + 'menu-test-menu', + 'mlid' => 138, + 'plid' => 0, + 'link_path' => 'admin', + 'router_path' => 'admin', + 'link_title' => 'Test 1', + 'options' => 'a:1:{s:10:"attributes";a:1:{s:5:"title";s:16:"Test menu link 1";}}', + 'module' => 'menu', + 'hidden' => 0, + 'external' => 0, + 'has_children' => 1, + 'expanded' => 0, + 'weight' => 15, + 'depth' => 1, + 'customized' => 1, + 'p1' => '138', + 'p2' => '0', + 'p3' => '0', + 'p4' => '0', + 'p5' => '0', + 'p6' => '0', + 'p7' => '0', + 'p8' => '0', + 'p9' => '0', + 'updated' => '0', + ], + [ + 'menu_name' => 'menu-test-menu', + 'mlid' => 139, + 'plid' => 138, + 'link_path' => 'admin/modules', + 'router_path' => 'admin/modules', + 'link_title' => 'Test 2', + 'options' => 'a:1:{s:10:"attributes";a:1:{s:5:"title";s:16:"Test menu link 2";}}', + 'module' => 'menu', + 'hidden' => 0, + 'external' => 0, + 'has_children' => 0, + 'expanded' => 0, + 'weight' => 12, + 'depth' => 2, + 'customized' => 1, + 'p1' => '138', + 'p2' => '139', + 'p3' => '0', + 'p4' => '0', + 'p5' => '0', + 'p6' => '0', + 'p7' => '0', + 'p8' => '0', + 'p9' => '0', + 'updated' => '0', + ], + [ + 'menu_name' => 'menu-test-menu', + 'mlid' => 140, + 'plid' => 0, + 'link_path' => 'https://www.drupal.org', + 'router_path' => 'admin/modules', + 'link_title' => 'Test 2', + 'options' => 'a:1:{s:10:"attributes";a:1:{s:5:"title";s:16:"Test menu link 2";}}', + 'module' => 'menu', + 'hidden' => 0, + 'external' => 0, + 'has_children' => 0, + 'expanded' => 0, + 'weight' => 12, + 'depth' => 2, + 'customized' => 1, + 'p1' => '0', + 'p2' => '0', + 'p3' => '0', + 'p4' => '0', + 'p5' => '0', + 'p6' => '0', + 'p7' => '0', + 'p8' => '0', + 'p9' => '0', + 'updated' => '0', + ], + [ + 'menu_name' => 'menu-test-menu', + 'mlid' => 141, + 'plid' => 0, + 'link_path' => 'https://api.drupal.org/api/drupal/8.3.x', + 'router_path' => 'admin/modules', + 'link_title' => 'Test 3', + 'options' => 'a:1:{s:10:"attributes";a:1:{s:5:"title";s:16:"Test menu link 3";}}', + 'module' => 'menu', + 'hidden' => 0, + 'external' => 0, + 'has_children' => 0, + 'expanded' => 0, + 'weight' => 12, + 'depth' => 2, + 'customized' => 1, + 'p1' => '0', + 'p2' => '0', + 'p3' => '0', + 'p4' => '0', + 'p5' => '0', + 'p6' => '0', + 'p7' => '0', + 'p8' => '0', + 'p9' => '0', + 'updated' => '0', + ], + ]; + $test[0]['source_data']['i18n_strings'] = [ + [ + 'lid' => 1, + 'objectid' => 139, + 'type' => 'item', + 'property' => 'title', + 'objectindex' => 0, + 'format' => 0, + ], + [ + 'lid' => 2, + 'objectid' => 139, + 'type' => 'item', + 'property' => 'description', + 'objectindex' => 0, + 'format' => 0, + ], + [ + 'lid' => 3, + 'objectid' => 140, + 'type' => 'item', + 'property' => 'description', + 'objectindex' => 0, + 'format' => 0, + ], + [ + 'lid' => 4, + 'objectid' => 141, + 'type' => 'item', + 'property' => 'title', + 'objectindex' => 0, + 'format' => 0, + ], + ]; + $test[0]['source_data']['locales_target'] = [ + [ + 'lid' => 1, + 'language' => 'fr', + 'translation' => 'fr - title translation', + 'plid' => 0, + 'plural' => 0, + 'i18n_status' => 0, + ], + [ + 'lid' => 2, + 'language' => 'fr', + 'translation' => 'fr - description translation', + 'plid' => 0, + 'plural' => 0, + 'i18n_status' => 0, + ], + [ + 'lid' => 3, + 'language' => 'zu', + 'translation' => 'zu - description translation', + 'plid' => 0, + 'plural' => 0, + 'i18n_status' => 0, + ], + [ + 'lid' => 4, + 'language' => 'zu', + 'translation' => 'zu - title translation', + 'plid' => 0, + 'plural' => 0, + 'i18n_status' => 0, + ], + ]; + + $test[0]['expected_results'] = [ + [ + 'menu_name' => 'menu-test-menu', + 'mlid' => 139, + 'property' => 'title', + 'language' => 'fr', + 'link_title' => 'Test 2', + 'description' => 'Test menu link 2', + 'title_translated' => 'fr - title translation', + 'description_translated' => 'fr - description translation', + ], + [ + 'menu_name' => 'menu-test-menu', + 'mlid' => 139, + 'property' => 'description', + 'language' => 'fr', + 'link_title' => 'Test 2', + 'description' => 'Test menu link 2', + 'title_translated' => 'fr - title translation', + 'description_translated' => 'fr - description translation', + ], + [ + 'menu_name' => 'menu-test-menu', + 'mlid' => 140, + 'property' => 'description', + 'language' => 'zu', + 'link_title' => 'Test 2', + 'description' => 'Test menu link 2', + 'title_translated' => NULL, + 'description_translated' => 'zu - description translation', + ], + [ + 'menu_name' => 'menu-test-menu', + 'mlid' => 141, + 'property' => 'title', + 'language' => 'zu', + 'link_title' => 'Test 3', + 'description' => 'Test menu link 3', + 'title_translated' => 'zu - title translation', + 'description_translated' => NULL, + ], + ]; + + return $test; + } + +} diff -r e200cb7efeb3 -r c2387f117808 core/modules/menu_ui/src/Tests/MenuLanguageTest.php --- a/core/modules/menu_ui/src/Tests/MenuLanguageTest.php Thu Apr 26 11:26:54 2018 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,133 +0,0 @@ -drupalLogin($this->drupalCreateUser(['access administration pages', 'administer menu'])); - - // Add some custom languages. - foreach (['aa', 'bb', 'cc', 'cs'] as $language_code) { - ConfigurableLanguage::create([ - 'id' => $language_code, - 'label' => $this->randomMachineName(), - ])->save(); - } - } - - /** - * Tests menu language settings and the defaults for menu link items. - */ - public function testMenuLanguage() { - // Create a test menu to test the various language-related settings. - // Machine name has to be lowercase. - $menu_name = Unicode::strtolower($this->randomMachineName(16)); - $label = $this->randomString(); - $edit = [ - 'id' => $menu_name, - 'description' => '', - 'label' => $label, - 'langcode' => 'aa', - ]; - $this->drupalPostForm('admin/structure/menu/add', $edit, t('Save')); - ContentLanguageSettings::loadByEntityTypeBundle('menu_link_content', 'menu_link_content') - ->setDefaultLangcode('bb') - ->setLanguageAlterable(TRUE) - ->save(); - - // Check menu language. - $this->assertOptionSelected('edit-langcode', $edit['langcode'], 'The menu language was correctly selected.'); - - // Test menu link language. - $link_path = '/'; - - // Add a menu link. - $link_title = $this->randomString(); - $edit = [ - 'title[0][value]' => $link_title, - 'link[0][uri]' => $link_path, - ]; - $this->drupalPostForm("admin/structure/menu/manage/$menu_name/add", $edit, t('Save')); - // Check the link was added with the correct menu link default language. - $menu_links = entity_load_multiple_by_properties('menu_link_content', ['title' => $link_title]); - $menu_link = reset($menu_links); - $this->assertMenuLink($menu_link->getPluginId(), [ - 'menu_name' => $menu_name, - 'route_name' => '', - 'langcode' => 'bb', - ]); - - // Edit menu link default, changing it to cc. - ContentLanguageSettings::loadByEntityTypeBundle('menu_link_content', 'menu_link_content') - ->setDefaultLangcode('cc') - ->setLanguageAlterable(TRUE) - ->save(); - - // Add a menu link. - $link_title = $this->randomString(); - $edit = [ - 'title[0][value]' => $link_title, - 'link[0][uri]' => $link_path, - ]; - $this->drupalPostForm("admin/structure/menu/manage/$menu_name/add", $edit, t('Save')); - // Check the link was added with the correct new menu link default language. - $menu_links = entity_load_multiple_by_properties('menu_link_content', ['title' => $link_title]); - $menu_link = reset($menu_links); - $this->assertMenuLink($menu_link->getPluginId(), [ - 'menu_name' => $menu_name, - 'route_name' => '', - 'langcode' => 'cc', - ]); - - // Now change the language of the new link to 'bb'. - $edit = [ - 'langcode[0][value]' => 'bb', - ]; - $this->drupalPostForm('admin/structure/menu/item/' . $menu_link->id() . '/edit', $edit, t('Save')); - $this->assertMenuLink($menu_link->getPluginId(), [ - 'menu_name' => $menu_name, - 'route_name' => '', - 'langcode' => 'bb', - ]); - - // Saving menu link items ends up on the edit menu page. To check the menu - // link has the correct language default on edit, go to the menu link edit - // page first. - $this->drupalGet('admin/structure/menu/item/' . $menu_link->id() . '/edit'); - // Check that the language selector has the correct default value. - $this->assertOptionSelected('edit-langcode-0-value', 'bb', 'The menu link language was correctly selected.'); - - // Edit menu to hide the language select on menu link item add. - ContentLanguageSettings::loadByEntityTypeBundle('menu_link_content', 'menu_link_content') - ->setDefaultLangcode('cc') - ->setLanguageAlterable(FALSE) - ->save(); - - // Check that the language selector is not available on menu link add page. - $this->drupalGet("admin/structure/menu/manage/$menu_name/add"); - $this->assertNoField('edit-langcode-0-value', 'The language selector field was hidden the page'); - } - -} diff -r e200cb7efeb3 -r c2387f117808 core/modules/menu_ui/src/Tests/MenuNodeTest.php --- a/core/modules/menu_ui/src/Tests/MenuNodeTest.php Thu Apr 26 11:26:54 2018 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,339 +0,0 @@ -drupalPlaceBlock('system_menu_block:main'); - $this->drupalPlaceBlock('page_title_block'); - - $this->drupalCreateContentType(['type' => 'page', 'name' => 'Basic page']); - - $this->editor = $this->drupalCreateUser([ - 'access administration pages', - 'administer content types', - 'administer menu', - 'create page content', - 'edit any page content', - 'delete any page content', - 'create content translations', - 'update content translations', - 'delete content translations', - 'translate any entity', - ]); - $this->drupalLogin($this->editor); - } - - /** - * Test creating, editing, deleting menu links via node form widget. - */ - public function testMenuNodeFormWidget() { - // Verify that cacheability metadata is bubbled from the menu link tree - // access checking that is performed when determining the "default parent - // item" options in menu_ui_form_node_type_form_alter(). The "log out" link - // adds the "user.roles:authenticated" cache context. - $this->drupalGet('admin/structure/types/manage/page'); - $this->assertCacheContext('user.roles:authenticated'); - - // Verify that the menu link title has the correct maxlength. - $max_length = \Drupal::entityManager()->getBaseFieldDefinitions('menu_link_content')['title']->getSetting('max_length'); - $this->drupalGet('node/add/page'); - $this->assertPattern('//', 'Menu link title field has correct maxlength in node add form.'); - - // Disable the default main menu, so that no menus are enabled. - $edit = [ - 'menu_options[main]' => FALSE, - ]; - $this->drupalPostForm('admin/structure/types/manage/page', $edit, t('Save content type')); - - // Verify that no menu settings are displayed and nodes can be created. - $this->drupalGet('node/add/page'); - $this->assertText(t('Create Basic page')); - $this->assertNoText(t('Menu settings')); - $node_title = $this->randomMachineName(); - $edit = [ - 'title[0][value]' => $node_title, - 'body[0][value]' => $this->randomString(), - ]; - $this->drupalPostForm(NULL, $edit, t('Save')); - $node = $this->drupalGetNodeByTitle($node_title); - $this->assertEqual($node->getTitle(), $edit['title[0][value]']); - - // Test that we cannot set a menu item from a menu that is not set as - // available. - $edit = [ - 'menu_options[tools]' => 1, - 'menu_parent' => 'main:', - ]; - $this->drupalPostForm('admin/structure/types/manage/page', $edit, t('Save content type')); - $this->assertText(t('The selected menu item is not under one of the selected menus.')); - $this->assertNoRaw(t('The content type %name has been updated.', ['%name' => 'Basic page'])); - - // Enable Tools menu as available menu. - $edit = [ - 'menu_options[main]' => 1, - 'menu_options[tools]' => 1, - 'menu_parent' => 'main:', - ]; - $this->drupalPostForm('admin/structure/types/manage/page', $edit, t('Save content type')); - $this->assertRaw(t('The content type %name has been updated.', ['%name' => 'Basic page'])); - - // Test that we can preview a node that will create a menu item. - $edit = [ - 'title[0][value]' => $node_title, - 'menu[enabled]' => 1, - 'menu[title]' => 'Test preview', - ]; - $this->drupalPostForm('node/add/page', $edit, t('Preview')); - - // Create a node. - $node_title = $this->randomMachineName(); - $edit = [ - 'title[0][value]' => $node_title, - 'body[0][value]' => $this->randomString(), - ]; - $this->drupalPostForm('node/add/page', $edit, t('Save')); - $node = $this->drupalGetNodeByTitle($node_title); - // Assert that there is no link for the node. - $this->drupalGet('test-page'); - $this->assertNoLink($node_title); - - // Edit the node, enable the menu link setting, but skip the link title. - $edit = [ - 'menu[enabled]' => 1, - ]; - $this->drupalPostForm('node/' . $node->id() . '/edit', $edit, t('Save')); - // Assert that there is no link for the node. - $this->drupalGet('test-page'); - $this->assertNoLink($node_title); - - // Make sure the menu links only appear when the node is published. - // These buttons just appear for 'administer nodes' users. - $admin_user = $this->drupalCreateUser([ - 'access administration pages', - 'administer content types', - 'administer nodes', - 'administer menu', - 'create page content', - 'edit any page content', - ]); - $this->drupalLogin($admin_user); - // Assert that the link does not exist if unpublished. - $edit = [ - 'menu[enabled]' => 1, - 'menu[title]' => $node_title, - 'status[value]' => FALSE, - ]; - $this->drupalPostForm('node/' . $node->id() . '/edit', $edit, 'Save'); - $this->drupalGet('test-page'); - $this->assertNoLink($node_title, 'Found no menu link with the node unpublished'); - // Assert that the link exists if published. - $edit['status[value]'] = TRUE; - $this->drupalPostForm('node/' . $node->id() . '/edit', $edit, 'Save'); - $this->drupalGet('test-page'); - $this->assertLink($node_title, 0, 'Found a menu link with the node published'); - - // Log back in as normal user. - $this->drupalLogin($this->editor); - // Edit the node and create a menu link. - $edit = [ - 'menu[enabled]' => 1, - 'menu[title]' => $node_title, - 'menu[weight]' => 17, - ]; - $this->drupalPostForm('node/' . $node->id() . '/edit', $edit, t('Save')); - // Assert that the link exists. - $this->drupalGet('test-page'); - $this->assertLink($node_title); - - $this->drupalGet('node/' . $node->id() . '/edit'); - $this->assertFieldById('edit-menu-weight', 17, 'Menu weight correct in edit form'); - $this->assertPattern('//', 'Menu link title field has correct maxlength in node edit form.'); - - // Disable the menu link, then edit the node--the link should stay disabled. - $link_id = menu_ui_get_menu_link_defaults($node)['entity_id']; - /** @var \Drupal\menu_link_content\Entity\MenuLinkContent $link */ - $link = MenuLinkContent::load($link_id); - $link->set('enabled', FALSE); - $link->save(); - $this->drupalPostForm($node->urlInfo('edit-form'), $edit, t('Save')); - $link = MenuLinkContent::load($link_id); - $this->assertFalse($link->isEnabled(), 'Saving a node with a disabled menu link keeps the menu link disabled.'); - - // Edit the node and remove the menu link. - $edit = [ - 'menu[enabled]' => FALSE, - ]; - $this->drupalPostForm('node/' . $node->id() . '/edit', $edit, t('Save')); - // Assert that there is no link for the node. - $this->drupalGet('test-page'); - $this->assertNoLink($node_title); - - // Add a menu link to the Administration menu. - $item = MenuLinkContent::create([ - 'link' => [['uri' => 'entity:node/' . $node->id()]], - 'title' => $this->randomMachineName(16), - 'menu_name' => 'admin', - ]); - $item->save(); - - // Assert that disabled Administration menu is not shown on the - // node/$nid/edit page. - $this->drupalGet('node/' . $node->id() . '/edit'); - $this->assertText('Provide a menu link', 'Link in not allowed menu not shown in node edit form'); - // Assert that the link is still in the Administration menu after save. - $this->drupalPostForm('node/' . $node->id() . '/edit', $edit, t('Save')); - $link = MenuLinkContent::load($item->id()); - $this->assertTrue($link, 'Link in not allowed menu still exists after saving node'); - - // Move the menu link back to the Tools menu. - $item->menu_name->value = 'tools'; - $item->save(); - // Create a second node. - $child_node = $this->drupalCreateNode(['type' => 'article']); - // Assign a menu link to the second node, being a child of the first one. - $child_item = MenuLinkContent::create([ - 'link' => [['uri' => 'entity:node/' . $child_node->id()]], - 'title' => $this->randomMachineName(16), - 'parent' => $item->getPluginId(), - 'menu_name' => $item->getMenuName(), - ]); - $child_item->save(); - // Edit the first node. - $this->drupalGet('node/' . $node->id() . '/edit'); - // Assert that it is not possible to set the parent of the first node to itself or the second node. - $this->assertNoOption('edit-menu-menu-parent', 'tools:' . $item->getPluginId()); - $this->assertNoOption('edit-menu-menu-parent', 'tools:' . $child_item->getPluginId()); - // Assert that unallowed Administration menu is not available in options. - $this->assertNoOption('edit-menu-menu-parent', 'admin:'); - } - - /** - * Testing correct loading and saving of menu links via node form widget in a multilingual environment. - */ - public function testMultilingualMenuNodeFormWidget() { - // Setup languages. - $langcodes = ['de']; - foreach ($langcodes as $langcode) { - ConfigurableLanguage::createFromLangcode($langcode)->save(); - } - array_unshift($langcodes, \Drupal::languageManager()->getDefaultLanguage()->getId()); - - $config = \Drupal::service('config.factory')->getEditable('language.negotiation'); - // Ensure path prefix is used to determine the language. - $config->set('url.source', 'path_prefix'); - // Ensure that there's a path prefix set for english as well. - $config->set('url.prefixes.' . $langcodes[0], $langcodes[0]); - $config->save(); - - $this->rebuildContainer(); - - $languages = []; - foreach ($langcodes as $langcode) { - $languages[$langcode] = ConfigurableLanguage::load($langcode); - } - - // Use a UI form submission to make the node type and menu link content entity translatable. - $this->drupalLogout(); - $this->drupalLogin($this->rootUser); - $edit = [ - 'entity_types[node]' => TRUE, - 'entity_types[menu_link_content]' => TRUE, - 'settings[node][page][settings][language][language_alterable]' => TRUE, - 'settings[node][page][translatable]' => TRUE, - 'settings[node][page][fields][title]' => TRUE, - 'settings[menu_link_content][menu_link_content][translatable]' => TRUE, - ]; - $this->drupalPostForm('admin/config/regional/content-language', $edit, t('Save configuration')); - - // Log out and back in as normal user. - $this->drupalLogout(); - $this->drupalLogin($this->editor); - - // Create a node. - $node_title = $this->randomMachineName(8); - $node = Node::create([ - 'type' => 'page', - 'title' => $node_title, - 'body' => $this->randomMachineName(16), - 'uid' => $this->editor->id(), - 'status' => 1, - 'langcode' => $langcodes[0], - ]); - $node->save(); - - // Create translation. - $translated_node_title = $this->randomMachineName(8); - $node->addTranslation($langcodes[1], ['title' => $translated_node_title, 'body' => $this->randomMachineName(16), 'status' => 1]); - $node->save(); - - // Edit the node and create a menu link. - $edit = [ - 'menu[enabled]' => 1, - 'menu[title]' => $node_title, - 'menu[weight]' => 17, - ]; - $options = ['language' => $languages[$langcodes[0]]]; - $url = $node->toUrl('edit-form', $options); - $this->drupalPostForm($url, $edit, t('Save') . ' ' . t('(this translation)')); - - // Edit the node in a different language and translate the menu link. - $edit = [ - 'menu[enabled]' => 1, - 'menu[title]' => $translated_node_title, - 'menu[weight]' => 17, - ]; - $options = ['language' => $languages[$langcodes[1]]]; - $url = $node->toUrl('edit-form', $options); - $this->drupalPostForm($url, $edit, t('Save') . ' ' . t('(this translation)')); - - // Assert that the original link exists in the frontend. - $this->drupalGet('node/' . $node->id(), ['language' => $languages[$langcodes[0]]]); - $this->assertLink($node_title); - - // Assert that the translated link exists in the frontend. - $this->drupalGet('node/' . $node->id(), ['language' => $languages[$langcodes[1]]]); - $this->assertLink($translated_node_title); - - // Revisit the edit page in original language, check the loaded menu item title and save. - $options = ['language' => $languages[$langcodes[0]]]; - $url = $node->toUrl('edit-form', $options); - $this->drupalGet($url); - $this->assertFieldById('edit-menu-title', $node_title); - $this->drupalPostForm(NULL, [], t('Save') . ' ' . t('(this translation)')); - - // Revisit the edit page of the translation and check the loaded menu item title. - $options = ['language' => $languages[$langcodes[1]]]; - $url = $node->toUrl('edit-form', $options); - $this->drupalGet($url); - $this->assertFieldById('edit-menu-title', $translated_node_title); - } - -} diff -r e200cb7efeb3 -r c2387f117808 core/modules/menu_ui/src/Tests/MenuTest.php --- a/core/modules/menu_ui/src/Tests/MenuTest.php Thu Apr 26 11:26:54 2018 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,962 +0,0 @@ -drupalPlaceBlock('page_title_block'); - - $this->drupalCreateContentType(['type' => 'article', 'name' => 'Article']); - - // Create users. - $this->adminUser = $this->drupalCreateUser(['access administration pages', 'administer blocks', 'administer menu', 'create article content']); - $this->authenticatedUser = $this->drupalCreateUser([]); - } - - /** - * Tests menu functionality using the admin and user interfaces. - */ - public function testMenu() { - // Log in the user. - $this->drupalLogin($this->adminUser); - $this->items = []; - - $this->menu = $this->addCustomMenu(); - $this->doMenuTests(); - $this->doTestMenuBlock(); - $this->addInvalidMenuLink(); - $this->addCustomMenuCRUD(); - - // Verify that the menu links rebuild is idempotent and leaves the same - // number of links in the table. - /** @var \Drupal\Core\Menu\MenuLinkManagerInterface $menu_link_manager */ - $menu_link_manager = \Drupal::service('plugin.manager.menu.link'); - $before_count = $menu_link_manager->countMenuLinks(NULL); - $menu_link_manager->rebuild(); - $after_count = $menu_link_manager->countMenuLinks(NULL); - $this->assertIdentical($before_count, $after_count, 'MenuLinkManager::rebuild() does not add more links'); - // Do standard user tests. - // Log in the user. - $this->drupalLogin($this->authenticatedUser); - $this->verifyAccess(403); - - foreach ($this->items as $item) { - // Menu link URIs are stored as 'internal:/node/$nid'. - $node = Node::load(str_replace('internal:/node/', '', $item->link->uri)); - $this->verifyMenuLink($item, $node); - } - - // Log in the administrator. - $this->drupalLogin($this->adminUser); - - // Verify delete link exists and reset link does not exist. - $this->drupalGet('admin/structure/menu/manage/' . $this->menu->id()); - $this->assertLinkByHref(Url::fromRoute('entity.menu_link_content.delete_form', ['menu_link_content' => $this->items[0]->id()])->toString()); - $this->assertNoLinkByHref(Url::fromRoute('menu_ui.link_reset', ['menu_link_plugin' => $this->items[0]->getPluginId()])->toString()); - // Check delete and reset access. - $this->drupalGet('admin/structure/menu/item/' . $this->items[0]->id() . '/delete'); - $this->assertResponse(200); - $this->drupalGet('admin/structure/menu/link/' . $this->items[0]->getPluginId() . '/reset'); - $this->assertResponse(403); - - // Delete menu links. - foreach ($this->items as $item) { - $this->deleteMenuLink($item); - } - - // Delete custom menu. - $this->deleteCustomMenu(); - - // Modify and reset a standard menu link. - $instance = $this->getStandardMenuLink(); - $old_weight = $instance->getWeight(); - // Edit the static menu link. - $edit = []; - $edit['weight'] = 10; - $id = $instance->getPluginId(); - $this->drupalPostForm("admin/structure/menu/link/$id/edit", $edit, t('Save')); - $this->assertResponse(200); - $this->assertText('The menu link has been saved.'); - $menu_link_manager->resetDefinitions(); - - $instance = $menu_link_manager->createInstance($instance->getPluginId()); - $this->assertEqual($edit['weight'], $instance->getWeight(), 'Saving an existing link updates the weight.'); - $this->resetMenuLink($instance, $old_weight); - } - - /** - * Adds a custom menu using CRUD functions. - */ - public function addCustomMenuCRUD() { - // Add a new custom menu. - $menu_name = substr(hash('sha256', $this->randomMachineName(16)), 0, MENU_MAX_MENU_NAME_LENGTH_UI); - $label = $this->randomMachineName(16); - - $menu = Menu::create([ - 'id' => $menu_name, - 'label' => $label, - 'description' => 'Description text', - ]); - $menu->save(); - - // Assert the new menu. - $this->drupalGet('admin/structure/menu/manage/' . $menu_name); - $this->assertRaw($label, 'Custom menu was added.'); - - // Edit the menu. - $new_label = $this->randomMachineName(16); - $menu->set('label', $new_label); - $menu->save(); - $this->drupalGet('admin/structure/menu/manage/' . $menu_name); - $this->assertRaw($new_label, 'Custom menu was edited.'); - } - - /** - * Creates a custom menu. - * - * @return \Drupal\system\Entity\Menu - * The custom menu that has been created. - */ - public function addCustomMenu() { - // Try adding a menu using a menu_name that is too long. - $this->drupalGet('admin/structure/menu/add'); - $menu_name = substr(hash('sha256', $this->randomMachineName(16)), 0, MENU_MAX_MENU_NAME_LENGTH_UI + 1); - $label = $this->randomMachineName(16); - $edit = [ - 'id' => $menu_name, - 'description' => '', - 'label' => $label, - ]; - $this->drupalPostForm('admin/structure/menu/add', $edit, t('Save')); - - // Verify that using a menu_name that is too long results in a validation - // message. - $this->assertRaw(t('@name cannot be longer than %max characters but is currently %length characters long.', [ - '@name' => t('Menu name'), - '%max' => MENU_MAX_MENU_NAME_LENGTH_UI, - '%length' => Unicode::strlen($menu_name), - ])); - - // Change the menu_name so it no longer exceeds the maximum length. - $menu_name = substr(hash('sha256', $this->randomMachineName(16)), 0, MENU_MAX_MENU_NAME_LENGTH_UI); - $edit['id'] = $menu_name; - $this->drupalPostForm('admin/structure/menu/add', $edit, t('Save')); - - // Verify that no validation error is given for menu_name length. - $this->assertNoRaw(t('@name cannot be longer than %max characters but is currently %length characters long.', [ - '@name' => t('Menu name'), - '%max' => MENU_MAX_MENU_NAME_LENGTH_UI, - '%length' => Unicode::strlen($menu_name), - ])); - // Verify that the confirmation message is displayed. - $this->assertRaw(t('Menu %label has been added.', ['%label' => $label])); - $this->drupalGet('admin/structure/menu'); - $this->assertText($label, 'Menu created'); - - // Confirm that the custom menu block is available. - $this->drupalGet('admin/structure/block/list/' . $this->config('system.theme')->get('default')); - $this->clickLinkPartialName('Place block'); - $this->assertText($label); - - // Enable the block. - $block = $this->drupalPlaceBlock('system_menu_block:' . $menu_name); - $this->blockPlacements[$menu_name] = $block->id(); - return Menu::load($menu_name); - } - - /** - * Deletes the locally stored custom menu. - * - * This deletes the custom menu that is stored in $this->menu and performs - * tests on the menu delete user interface. - */ - public function deleteCustomMenu() { - $menu_name = $this->menu->id(); - $label = $this->menu->label(); - - // Delete custom menu. - $this->drupalPostForm("admin/structure/menu/manage/$menu_name/delete", [], t('Delete')); - $this->assertResponse(200); - $this->assertRaw(t('The menu %title has been deleted.', ['%title' => $label]), 'Custom menu was deleted'); - $this->assertNull(Menu::load($menu_name), 'Custom menu was deleted'); - // Test if all menu links associated with the menu were removed from - // database. - $result = entity_load_multiple_by_properties('menu_link_content', ['menu_name' => $menu_name]); - $this->assertFalse($result, 'All menu links associated with the custom menu were deleted.'); - - // Make sure there's no delete button on system menus. - $this->drupalGet('admin/structure/menu/manage/main'); - $this->assertNoRaw('edit-delete', 'The delete button was not found'); - - // Try to delete the main menu. - $this->drupalGet('admin/structure/menu/manage/main/delete'); - $this->assertText(t('You are not authorized to access this page.')); - } - - /** - * Tests menu functionality. - */ - public function doMenuTests() { - $menu_name = $this->menu->id(); - - // Test the 'Add link' local action. - $this->drupalGet(Url::fromRoute('entity.menu.edit_form', ['menu' => $menu_name])); - - $this->clickLink(t('Add link')); - $link_title = $this->randomString(); - $this->drupalPostForm(NULL, ['link[0][uri]' => '/', 'title[0][value]' => $link_title], t('Save')); - $this->assertUrl(Url::fromRoute('entity.menu.edit_form', ['menu' => $menu_name])); - // Test the 'Edit' operation. - $this->clickLink(t('Edit')); - $this->assertFieldByName('title[0][value]', $link_title); - $link_title = $this->randomString(); - $this->drupalPostForm(NULL, ['title[0][value]' => $link_title], t('Save')); - $this->assertUrl(Url::fromRoute('entity.menu.edit_form', ['menu' => $menu_name])); - // Test the 'Delete' operation. - $this->clickLink(t('Delete')); - $this->assertRaw(t('Are you sure you want to delete the custom menu link %item?', ['%item' => $link_title])); - $this->drupalPostForm(NULL, [], t('Delete')); - $this->assertUrl(Url::fromRoute('entity.menu.edit_form', ['menu' => $menu_name])); - - // Add nodes to use as links for menu links. - $node1 = $this->drupalCreateNode(['type' => 'article']); - $node2 = $this->drupalCreateNode(['type' => 'article']); - $node3 = $this->drupalCreateNode(['type' => 'article']); - $node4 = $this->drupalCreateNode(['type' => 'article']); - // Create a node with an alias. - $node5 = $this->drupalCreateNode([ - 'type' => 'article', - 'path' => [ - 'alias' => '/node5', - ], - ]); - - // Verify add link button. - $this->drupalGet('admin/structure/menu'); - $this->assertLinkByHref('admin/structure/menu/manage/' . $menu_name . '/add', 0, "The add menu link button URL is correct"); - - // Verify form defaults. - $this->doMenuLinkFormDefaultsTest(); - - // Add menu links. - $item1 = $this->addMenuLink('', '/node/' . $node1->id(), $menu_name, TRUE); - $item2 = $this->addMenuLink($item1->getPluginId(), '/node/' . $node2->id(), $menu_name, FALSE); - $item3 = $this->addMenuLink($item2->getPluginId(), '/node/' . $node3->id(), $menu_name); - - // Hierarchy - // <$menu_name> - // - item1 - // -- item2 - // --- item3 - - $this->assertMenuLink($item1->getPluginId(), [ - 'children' => [$item2->getPluginId(), $item3->getPluginId()], - 'parents' => [$item1->getPluginId()], - // We assert the language code here to make sure that the language - // selection element degrades gracefully without the Language module. - 'langcode' => 'en', - ]); - $this->assertMenuLink($item2->getPluginId(), [ - 'children' => [$item3->getPluginId()], - 'parents' => [$item2->getPluginId(), $item1->getPluginId()], - // See above. - 'langcode' => 'en', - ]); - $this->assertMenuLink($item3->getPluginId(), [ - 'children' => [], - 'parents' => [$item3->getPluginId(), $item2->getPluginId(), $item1->getPluginId()], - // See above. - 'langcode' => 'en', - ]); - - // Verify menu links. - $this->verifyMenuLink($item1, $node1); - $this->verifyMenuLink($item2, $node2, $item1, $node1); - $this->verifyMenuLink($item3, $node3, $item2, $node2); - - // Add more menu links. - $item4 = $this->addMenuLink('', '/node/' . $node4->id(), $menu_name); - $item5 = $this->addMenuLink($item4->getPluginId(), '/node/' . $node5->id(), $menu_name); - // Create a menu link pointing to an alias. - $item6 = $this->addMenuLink($item4->getPluginId(), '/node5', $menu_name, TRUE, '0'); - - // Hierarchy - // <$menu_name> - // - item1 - // -- item2 - // --- item3 - // - item4 - // -- item5 - // -- item6 - - $this->assertMenuLink($item4->getPluginId(), [ - 'children' => [$item5->getPluginId(), $item6->getPluginId()], - 'parents' => [$item4->getPluginId()], - // See above. - 'langcode' => 'en', - ]); - $this->assertMenuLink($item5->getPluginId(), [ - 'children' => [], - 'parents' => [$item5->getPluginId(), $item4->getPluginId()], - 'langcode' => 'en', - ]); - $this->assertMenuLink($item6->getPluginId(), [ - 'children' => [], - 'parents' => [$item6->getPluginId(), $item4->getPluginId()], - 'route_name' => 'entity.node.canonical', - 'route_parameters' => ['node' => $node5->id()], - 'url' => '', - // See above. - 'langcode' => 'en', - ]); - - // Modify menu links. - $this->modifyMenuLink($item1); - $this->modifyMenuLink($item2); - - // Toggle menu links. - $this->toggleMenuLink($item1); - $this->toggleMenuLink($item2); - - // Move link and verify that descendants are updated. - $this->moveMenuLink($item2, $item5->getPluginId(), $menu_name); - // Hierarchy - // <$menu_name> - // - item1 - // - item4 - // -- item5 - // --- item2 - // ---- item3 - // -- item6 - - $this->assertMenuLink($item1->getPluginId(), [ - 'children' => [], - 'parents' => [$item1->getPluginId()], - // See above. - 'langcode' => 'en', - ]); - $this->assertMenuLink($item4->getPluginId(), [ - 'children' => [$item5->getPluginId(), $item6->getPluginId(), $item2->getPluginId(), $item3->getPluginId()], - 'parents' => [$item4->getPluginId()], - // See above. - 'langcode' => 'en', - ]); - - $this->assertMenuLink($item5->getPluginId(), [ - 'children' => [$item2->getPluginId(), $item3->getPluginId()], - 'parents' => [$item5->getPluginId(), $item4->getPluginId()], - // See above. - 'langcode' => 'en', - ]); - $this->assertMenuLink($item2->getPluginId(), [ - 'children' => [$item3->getPluginId()], - 'parents' => [$item2->getPluginId(), $item5->getPluginId(), $item4->getPluginId()], - // See above. - 'langcode' => 'en', - ]); - $this->assertMenuLink($item3->getPluginId(), [ - 'children' => [], - 'parents' => [$item3->getPluginId(), $item2->getPluginId(), $item5->getPluginId(), $item4->getPluginId()], - // See above. - 'langcode' => 'en', - ]); - - // Add 102 menu links with increasing weights, then make sure the last-added - // item's weight doesn't get changed because of the old hardcoded delta=50. - $items = []; - for ($i = -50; $i <= 51; $i++) { - $items[$i] = $this->addMenuLink('', '/node/' . $node1->id(), $menu_name, TRUE, strval($i)); - } - $this->assertMenuLink($items[51]->getPluginId(), ['weight' => '51']); - - // Disable a link and then re-enable the link via the overview form. - $this->disableMenuLink($item1); - $edit = []; - $edit['links[menu_plugin_id:' . $item1->getPluginId() . '][enabled]'] = TRUE; - $this->drupalPostForm('admin/structure/menu/manage/' . $item1->getMenuName(), $edit, t('Save')); - - // Mark item2, item4 and item5 as expanded. - // This is done in order to show them on the frontpage. - $item2->expanded->value = 1; - $item2->save(); - $item4->expanded->value = 1; - $item4->save(); - $item5->expanded->value = 1; - $item5->save(); - - // Verify in the database. - $this->assertMenuLink($item1->getPluginId(), ['enabled' => 1]); - - // Add an external link. - $item7 = $this->addMenuLink('', 'https://www.drupal.org', $menu_name); - $this->assertMenuLink($item7->getPluginId(), ['url' => 'https://www.drupal.org']); - - // Add menu item. - $item8 = $this->addMenuLink('', '/', $menu_name); - $this->assertMenuLink($item8->getPluginId(), ['route_name' => '']); - $this->drupalGet(''); - $this->assertResponse(200); - // Make sure we get routed correctly. - $this->clickLink($item8->getTitle()); - $this->assertResponse(200); - - // Check invalid menu link parents. - $this->checkInvalidParentMenuLinks(); - - // Save menu links for later tests. - $this->items[] = $item1; - $this->items[] = $item2; - } - - /** - * Ensures that the proper default values are set when adding a menu link - */ - protected function doMenuLinkFormDefaultsTest() { - $this->drupalGet("admin/structure/menu/manage/tools/add"); - $this->assertResponse(200); - - $this->assertFieldByName('title[0][value]', ''); - $this->assertFieldByName('link[0][uri]', ''); - - $this->assertNoFieldChecked('edit-expanded-value'); - $this->assertFieldChecked('edit-enabled-value'); - - $this->assertFieldByName('description[0][value]', ''); - $this->assertFieldByName('weight[0][value]', 0); - } - - /** - * Adds and removes a menu link with a query string and fragment. - */ - public function testMenuQueryAndFragment() { - $this->drupalLogin($this->adminUser); - - // Make a path with query and fragment on. - $path = '/test-page?arg1=value1&arg2=value2'; - $item = $this->addMenuLink('', $path); - - $this->drupalGet('admin/structure/menu/item/' . $item->id() . '/edit'); - $this->assertFieldByName('link[0][uri]', $path, 'Path is found with both query and fragment.'); - - // Now change the path to something without query and fragment. - $path = '/test-page'; - $this->drupalPostForm('admin/structure/menu/item/' . $item->id() . '/edit', ['link[0][uri]' => $path], t('Save')); - $this->drupalGet('admin/structure/menu/item/' . $item->id() . '/edit'); - $this->assertFieldByName('link[0][uri]', $path, 'Path no longer has query or fragment.'); - - // Use #fragment and ensure that saving it does not lose its content. - $path = '?arg1=value#fragment'; - $item = $this->addMenuLink('', $path); - - $this->drupalGet('admin/structure/menu/item/' . $item->id() . '/edit'); - $this->assertFieldByName('link[0][uri]', $path, 'Path is found with both query and fragment.'); - - $this->drupalPostForm('admin/structure/menu/item/' . $item->id() . '/edit', [], t('Save')); - - $this->drupalGet('admin/structure/menu/item/' . $item->id() . '/edit'); - $this->assertFieldByName('link[0][uri]', $path, 'Path is found with both query and fragment.'); - } - - /** - * Tests renaming the built-in menu. - */ - public function testSystemMenuRename() { - $this->drupalLogin($this->adminUser); - $edit = [ - 'label' => $this->randomMachineName(16), - ]; - $this->drupalPostForm('admin/structure/menu/manage/main', $edit, t('Save')); - - // Make sure menu shows up with new name in block addition. - $default_theme = $this->config('system.theme')->get('default'); - $this->drupalget('admin/structure/block/list/' . $default_theme); - $this->clickLinkPartialName('Place block'); - $this->assertText($edit['label']); - } - - /** - * Tests that menu items pointing to unpublished nodes are editable. - */ - public function testUnpublishedNodeMenuItem() { - $this->drupalLogin($this->drupalCreateUser(['access administration pages', 'administer blocks', 'administer menu', 'create article content', 'bypass node access'])); - // Create an unpublished node. - $node = $this->drupalCreateNode([ - 'type' => 'article', - 'status' => NodeInterface::NOT_PUBLISHED, - ]); - - $item = $this->addMenuLink('', '/node/' . $node->id()); - $this->modifyMenuLink($item); - - // Test that a user with 'administer menu' but without 'bypass node access' - // cannot see the menu item. - $this->drupalLogout(); - $this->drupalLogin($this->adminUser); - $this->drupalGet('admin/structure/menu/manage/' . $item->getMenuName()); - $this->assertNoText($item->getTitle(), "Menu link pointing to unpublished node is only visible to users with 'bypass node access' permission"); - // The cache contexts associated with the (in)accessible menu links are - // bubbled. See DefaultMenuLinkTreeManipulators::menuLinkCheckAccess(). - $this->assertCacheContext('user.permissions'); - } - - /** - * Tests the contextual links on a menu block. - */ - public function testBlockContextualLinks() { - $this->drupalLogin($this->drupalCreateUser(['administer menu', 'access contextual links', 'administer blocks'])); - $custom_menu = $this->addCustomMenu(); - $this->addMenuLink('', '/', $custom_menu->id()); - $block = $this->drupalPlaceBlock('system_menu_block:' . $custom_menu->id(), ['label' => 'Custom menu', 'provider' => 'system']); - $this->drupalGet('test-page'); - - $id = 'block:block=' . $block->id() . ':langcode=en|menu:menu=' . $custom_menu->id() . ':langcode=en'; - // @see \Drupal\contextual\Tests\ContextualDynamicContextTest:assertContextualLinkPlaceHolder() - $this->assertRaw('
    ', format_string('Contextual link placeholder with id @id exists.', ['@id' => $id])); - - // Get server-rendered contextual links. - // @see \Drupal\contextual\Tests\ContextualDynamicContextTest:renderContextualLinks() - $post = ['ids[0]' => $id]; - $response = $this->drupalPost('contextual/render', 'application/json', $post, ['query' => ['destination' => 'test-page']]); - $this->assertResponse(200); - $json = Json::decode($response); - $this->assertIdentical($json[$id], ''); - } - - /** - * Adds a menu link using the UI. - * - * @param string $parent - * Optional parent menu link id. - * @param string $path - * The path to enter on the form. Defaults to the front page. - * @param string $menu_name - * Menu name. Defaults to 'tools'. - * @param bool $expanded - * Whether or not this menu link is expanded. Setting this to TRUE should - * test whether it works when we do the authenticatedUser tests. Defaults - * to FALSE. - * @param string $weight - * Menu weight. Defaults to 0. - * - * @return \Drupal\menu_link_content\Entity\MenuLinkContent - * A menu link entity. - */ - public function addMenuLink($parent = '', $path = '/', $menu_name = 'tools', $expanded = FALSE, $weight = '0') { - // View add menu link page. - $this->drupalGet("admin/structure/menu/manage/$menu_name/add"); - $this->assertResponse(200); - - $title = '!link_' . $this->randomMachineName(16); - $edit = [ - 'link[0][uri]' => $path, - 'title[0][value]' => $title, - 'description[0][value]' => '', - 'enabled[value]' => 1, - 'expanded[value]' => $expanded, - 'menu_parent' => $menu_name . ':' . $parent, - 'weight[0][value]' => $weight, - ]; - - // Add menu link. - $this->drupalPostForm(NULL, $edit, t('Save')); - $this->assertResponse(200); - $this->assertText('The menu link has been saved.'); - - $menu_links = entity_load_multiple_by_properties('menu_link_content', ['title' => $title]); - - $menu_link = reset($menu_links); - $this->assertTrue($menu_link, 'Menu link was found in database.'); - $this->assertMenuLink($menu_link->getPluginId(), ['menu_name' => $menu_name, 'children' => [], 'parent' => $parent]); - - return $menu_link; - } - - /** - * Attempts to add menu link with invalid path or no access permission. - */ - public function addInvalidMenuLink() { - foreach (['access' => '/admin/people/permissions'] as $type => $link_path) { - $edit = [ - 'link[0][uri]' => $link_path, - 'title[0][value]' => 'title', - ]; - $this->drupalPostForm("admin/structure/menu/manage/{$this->menu->id()}/add", $edit, t('Save')); - $this->assertRaw(t("The path '@link_path' is inaccessible.", ['@link_path' => $link_path]), 'Menu link was not created'); - } - } - - /** - * Tests that parent options are limited by depth when adding menu links. - */ - public function checkInvalidParentMenuLinks() { - $last_link = NULL; - $created_links = []; - - // Get the max depth of the tree. - $menu_link_tree = \Drupal::service('menu.link_tree'); - $max_depth = $menu_link_tree->maxDepth(); - - // Create a maximum number of menu links, each a child of the previous. - for ($i = 0; $i <= $max_depth - 1; $i++) { - $parent = $last_link ? 'tools:' . $last_link->getPluginId() : 'tools:'; - $title = 'title' . $i; - $edit = [ - 'link[0][uri]' => '/', - 'title[0][value]' => $title, - 'menu_parent' => $parent, - 'description[0][value]' => '', - 'enabled[value]' => 1, - 'expanded[value]' => FALSE, - 'weight[0][value]' => '0', - ]; - $this->drupalPostForm("admin/structure/menu/manage/{$this->menu->id()}/add", $edit, t('Save')); - $menu_links = entity_load_multiple_by_properties('menu_link_content', ['title' => $title]); - $last_link = reset($menu_links); - $created_links[] = 'tools:' . $last_link->getPluginId(); - } - - // The last link cannot be a parent in the new menu link form. - $this->drupalGet('admin/structure/menu/manage/admin/add'); - $value = 'tools:' . $last_link->getPluginId(); - $this->assertNoOption('edit-menu-parent', $value, 'The invalid option is not there.'); - - // All but the last link can be parents in the new menu link form. - array_pop($created_links); - foreach ($created_links as $key => $link) { - $this->assertOption('edit-menu-parent', $link, 'The valid option number ' . ($key + 1) . ' is there.'); - } - } - - /** - * Verifies a menu link using the UI. - * - * @param \Drupal\menu_link_content\Entity\MenuLinkContent $item - * Menu link. - * @param object $item_node - * Menu link content node. - * @param \Drupal\menu_link_content\Entity\MenuLinkContent $parent - * Parent menu link. - * @param object $parent_node - * Parent menu link content node. - */ - public function verifyMenuLink(MenuLinkContent $item, $item_node, MenuLinkContent $parent = NULL, $parent_node = NULL) { - // View home page. - $this->drupalGet(''); - $this->assertResponse(200); - - // Verify parent menu link. - if (isset($parent)) { - // Verify menu link. - $title = $parent->getTitle(); - $this->assertLink($title, 0, 'Parent menu link was displayed'); - - // Verify menu link link. - $this->clickLink($title); - $title = $parent_node->label(); - $this->assertTitle(t("@title | Drupal", ['@title' => $title]), 'Parent menu link link target was correct'); - } - - // Verify menu link. - $title = $item->getTitle(); - $this->assertLink($title, 0, 'Menu link was displayed'); - - // Verify menu link link. - $this->clickLink($title); - $title = $item_node->label(); - $this->assertTitle(t("@title | Drupal", ['@title' => $title]), 'Menu link link target was correct'); - } - - /** - * Changes the parent of a menu link using the UI. - * - * @param \Drupal\menu_link_content\MenuLinkContentInterface $item - * The menu link item to move. - * @param int $parent - * The id of the new parent. - * @param string $menu_name - * The menu the menu link will be moved to. - */ - public function moveMenuLink(MenuLinkContent $item, $parent, $menu_name) { - $mlid = $item->id(); - - $edit = [ - 'menu_parent' => $menu_name . ':' . $parent, - ]; - $this->drupalPostForm("admin/structure/menu/item/$mlid/edit", $edit, t('Save')); - $this->assertResponse(200); - } - - /** - * Modifies a menu link using the UI. - * - * @param \Drupal\menu_link_content\Entity\MenuLinkContent $item - * Menu link entity. - */ - public function modifyMenuLink(MenuLinkContent $item) { - $item->title->value = $this->randomMachineName(16); - - $mlid = $item->id(); - $title = $item->getTitle(); - - // Edit menu link. - $edit = []; - $edit['title[0][value]'] = $title; - $this->drupalPostForm("admin/structure/menu/item/$mlid/edit", $edit, t('Save')); - $this->assertResponse(200); - $this->assertText('The menu link has been saved.'); - // Verify menu link. - $this->drupalGet('admin/structure/menu/manage/' . $item->getMenuName()); - $this->assertText($title, 'Menu link was edited'); - } - - /** - * Resets a standard menu link using the UI. - * - * @param \Drupal\Core\Menu\MenuLinkInterface $menu_link - * The Menu link. - * @param int $old_weight - * Original title for menu link. - */ - public function resetMenuLink(MenuLinkInterface $menu_link, $old_weight) { - // Reset menu link. - $this->drupalPostForm("admin/structure/menu/link/{$menu_link->getPluginId()}/reset", [], t('Reset')); - $this->assertResponse(200); - $this->assertRaw(t('The menu link was reset to its default settings.'), 'Menu link was reset'); - - // Verify menu link. - $instance = \Drupal::service('plugin.manager.menu.link')->createInstance($menu_link->getPluginId()); - $this->assertEqual($old_weight, $instance->getWeight(), 'Resets to the old weight.'); - } - - /** - * Deletes a menu link using the UI. - * - * @param \Drupal\menu_link_content\Entity\MenuLinkContent $item - * Menu link. - */ - public function deleteMenuLink(MenuLinkContent $item) { - $mlid = $item->id(); - $title = $item->getTitle(); - - // Delete menu link. - $this->drupalPostForm("admin/structure/menu/item/$mlid/delete", [], t('Delete')); - $this->assertResponse(200); - $this->assertRaw(t('The menu link %title has been deleted.', ['%title' => $title]), 'Menu link was deleted'); - - // Verify deletion. - $this->drupalGet(''); - $this->assertNoText($title, 'Menu link was deleted'); - } - - /** - * Alternately disables and enables a menu link. - * - * @param \Drupal\menu_link_content\Entity\MenuLinkContent $item - * Menu link. - */ - public function toggleMenuLink(MenuLinkContent $item) { - $this->disableMenuLink($item); - - // Verify menu link is absent. - $this->drupalGet(''); - $this->assertNoText($item->getTitle(), 'Menu link was not displayed'); - $this->enableMenuLink($item); - - // Verify menu link is displayed. - $this->drupalGet(''); - $this->assertText($item->getTitle(), 'Menu link was displayed'); - } - - /** - * Disables a menu link. - * - * @param \Drupal\menu_link_content\Entity\MenuLinkContent $item - * Menu link. - */ - public function disableMenuLink(MenuLinkContent $item) { - $mlid = $item->id(); - $edit['enabled[value]'] = FALSE; - $this->drupalPostForm("admin/structure/menu/item/$mlid/edit", $edit, t('Save')); - - // Unlike most other modules, there is no confirmation message displayed. - // Verify in the database. - $this->assertMenuLink($item->getPluginId(), ['enabled' => 0]); - } - - /** - * Enables a menu link. - * - * @param \Drupal\menu_link_content\Entity\MenuLinkContent $item - * Menu link. - */ - public function enableMenuLink(MenuLinkContent $item) { - $mlid = $item->id(); - $edit['enabled[value]'] = TRUE; - $this->drupalPostForm("admin/structure/menu/item/$mlid/edit", $edit, t('Save')); - - // Verify in the database. - $this->assertMenuLink($item->getPluginId(), ['enabled' => 1]); - } - - /** - * Tests if administrative users other than user 1 can access the menu parents - * AJAX callback. - */ - public function testMenuParentsJsAccess() { - $admin = $this->drupalCreateUser(['administer menu']); - $this->drupalLogin($admin); - // Just check access to the callback overall, the POST data is irrelevant. - $this->drupalGetAjax('admin/structure/menu/parents'); - $this->assertResponse(200); - - // Do standard user tests. - // Log in the user. - $this->drupalLogin($this->authenticatedUser); - $this->drupalGetAjax('admin/structure/menu/parents'); - $this->assertResponse(403); - } - - /** - * Returns standard menu link. - * - * @return \Drupal\Core\Menu\MenuLinkInterface - * A menu link plugin. - */ - private function getStandardMenuLink() { - // Retrieve menu link id of the Log out menu link, which will always be on - // the front page. - /** @var \Drupal\Core\Menu\MenuLinkManagerInterface $menu_link_manager */ - $menu_link_manager = \Drupal::service('plugin.manager.menu.link'); - $instance = $menu_link_manager->getInstance(['id' => 'user.logout']); - - $this->assertTrue((bool) $instance, 'Standard menu link was loaded'); - return $instance; - } - - /** - * Verifies the logged in user has the desired access to various menu pages. - * - * @param int $response - * (optional) The expected HTTP response code. Defaults to 200. - */ - private function verifyAccess($response = 200) { - // View menu help page. - $this->drupalGet('admin/help/menu'); - $this->assertResponse($response); - if ($response == 200) { - $this->assertText(t('Menu'), 'Menu help was displayed'); - } - - // View menu build overview page. - $this->drupalGet('admin/structure/menu'); - $this->assertResponse($response); - if ($response == 200) { - $this->assertText(t('Menus'), 'Menu build overview page was displayed'); - } - - // View tools menu customization page. - $this->drupalGet('admin/structure/menu/manage/' . $this->menu->id()); - $this->assertResponse($response); - if ($response == 200) { - $this->assertText(t('Tools'), 'Tools menu page was displayed'); - } - - // View menu edit page for a static link. - $item = $this->getStandardMenuLink(); - $this->drupalGet('admin/structure/menu/link/' . $item->getPluginId() . '/edit'); - $this->assertResponse($response); - if ($response == 200) { - $this->assertText(t('Edit menu item'), 'Menu edit page was displayed'); - } - - // View add menu page. - $this->drupalGet('admin/structure/menu/add'); - $this->assertResponse($response); - if ($response == 200) { - $this->assertText(t('Menus'), 'Add menu page was displayed'); - } - } - - /** - * Tests menu block settings. - */ - protected function doTestMenuBlock() { - $menu_id = $this->menu->id(); - $block_id = $this->blockPlacements[$menu_id]; - $this->drupalGet('admin/structure/block/manage/' . $block_id); - $this->drupalPostForm(NULL, [ - 'settings[depth]' => 3, - 'settings[level]' => 2, - ], t('Save block')); - $block = Block::load($block_id); - $settings = $block->getPlugin()->getConfiguration(); - $this->assertEqual($settings['depth'], 3); - $this->assertEqual($settings['level'], 2); - // Reset settings. - $block->getPlugin()->setConfigurationValue('depth', 0); - $block->getPlugin()->setConfigurationValue('level', 1); - $block->save(); - } - -} diff -r e200cb7efeb3 -r c2387f117808 core/modules/menu_ui/src/Tests/MenuWebTestBase.php --- a/core/modules/menu_ui/src/Tests/MenuWebTestBase.php Thu Apr 26 11:26:54 2018 +0100 +++ b/core/modules/menu_ui/src/Tests/MenuWebTestBase.php Tue Jul 10 15:07:59 2018 +0100 @@ -2,10 +2,17 @@ namespace Drupal\menu_ui\Tests; +@trigger_error(__NAMESPACE__ . '\MenuWebTestBase is deprecated in Drupal 8.5.x and will be removed before Drupal 9.0.0. Use the \Drupal\Tests\BrowserTestBase base class and the \Drupal\Tests\menu_ui\Traits\MenuUiTrait trait instead. See https://www.drupal.org/node/2917910.', E_USER_DEPRECATED); + use Drupal\simpletest\WebTestBase; /** * Base class for menu web tests. + * + * @deprecated in Drupal 8.5.x, will be removed before Drupal 9.0.x. Use + * \Drupal\Tests\menu_ui\Traits\MenuUiTrait methods, instead. + * + * @see https://www.drupal.org/node/2917910 */ abstract class MenuWebTestBase extends WebTestBase { diff -r e200cb7efeb3 -r c2387f117808 core/modules/menu_ui/tests/src/Functional/MenuUiLanguageTest.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/core/modules/menu_ui/tests/src/Functional/MenuUiLanguageTest.php Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,141 @@ +drupalLogin($this->drupalCreateUser(['access administration pages', 'administer menu'])); + + // Add some custom languages. + foreach (['aa', 'bb', 'cc', 'cs'] as $language_code) { + ConfigurableLanguage::create([ + 'id' => $language_code, + 'label' => $this->randomMachineName(), + ])->save(); + } + } + + /** + * Tests menu language settings and the defaults for menu link items. + */ + public function testMenuLanguage() { + // Create a test menu to test the various language-related settings. + // Machine name has to be lowercase. + $menu_name = Unicode::strtolower($this->randomMachineName(16)); + $label = $this->randomString(); + $edit = [ + 'id' => $menu_name, + 'description' => '', + 'label' => $label, + 'langcode' => 'aa', + ]; + $this->drupalPostForm('admin/structure/menu/add', $edit, t('Save')); + ContentLanguageSettings::loadByEntityTypeBundle('menu_link_content', 'menu_link_content') + ->setDefaultLangcode('bb') + ->setLanguageAlterable(TRUE) + ->save(); + + // Check menu language. + $this->assertOptionSelected('edit-langcode', $edit['langcode'], 'The menu language was correctly selected.'); + + // Test menu link language. + $link_path = '/'; + + // Add a menu link. + $link_title = $this->randomString(); + $edit = [ + 'title[0][value]' => $link_title, + 'link[0][uri]' => $link_path, + ]; + $this->drupalPostForm("admin/structure/menu/manage/$menu_name/add", $edit, t('Save')); + // Check the link was added with the correct menu link default language. + $menu_links = entity_load_multiple_by_properties('menu_link_content', ['title' => $link_title]); + $menu_link = reset($menu_links); + $this->assertMenuLink([ + 'menu_name' => $menu_name, + 'route_name' => '', + 'langcode' => 'bb', + ], $menu_link->getPluginId()); + + // Edit menu link default, changing it to cc. + ContentLanguageSettings::loadByEntityTypeBundle('menu_link_content', 'menu_link_content') + ->setDefaultLangcode('cc') + ->setLanguageAlterable(TRUE) + ->save(); + + // Add a menu link. + $link_title = $this->randomString(); + $edit = [ + 'title[0][value]' => $link_title, + 'link[0][uri]' => $link_path, + ]; + $this->drupalPostForm("admin/structure/menu/manage/$menu_name/add", $edit, t('Save')); + // Check the link was added with the correct new menu link default language. + $menu_links = entity_load_multiple_by_properties('menu_link_content', ['title' => $link_title]); + $menu_link = reset($menu_links); + $this->assertMenuLink([ + 'menu_name' => $menu_name, + 'route_name' => '', + 'langcode' => 'cc', + ], $menu_link->getPluginId()); + + // Now change the language of the new link to 'bb'. + $edit = [ + 'langcode[0][value]' => 'bb', + ]; + $this->drupalPostForm('admin/structure/menu/item/' . $menu_link->id() . '/edit', $edit, t('Save')); + $this->assertMenuLink([ + 'menu_name' => $menu_name, + 'route_name' => '', + 'langcode' => 'bb', + ], $menu_link->getPluginId()); + + // Saving menu link items ends up on the edit menu page. To check the menu + // link has the correct language default on edit, go to the menu link edit + // page first. + $this->drupalGet('admin/structure/menu/item/' . $menu_link->id() . '/edit'); + // Check that the language selector has the correct default value. + $this->assertOptionSelected('edit-langcode-0-value', 'bb', 'The menu link language was correctly selected.'); + + // Edit menu to hide the language select on menu link item add. + ContentLanguageSettings::loadByEntityTypeBundle('menu_link_content', 'menu_link_content') + ->setDefaultLangcode('cc') + ->setLanguageAlterable(FALSE) + ->save(); + + // Check that the language selector is not available on menu link add page. + $this->drupalGet("admin/structure/menu/manage/$menu_name/add"); + $this->assertNoField('edit-langcode-0-value', 'The language selector field was hidden the page'); + } + +} diff -r e200cb7efeb3 -r c2387f117808 core/modules/menu_ui/tests/src/Functional/MenuUiNodeTest.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/core/modules/menu_ui/tests/src/Functional/MenuUiNodeTest.php Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,339 @@ +drupalPlaceBlock('system_menu_block:main'); + $this->drupalPlaceBlock('page_title_block'); + + $this->drupalCreateContentType(['type' => 'page', 'name' => 'Basic page']); + + $this->editor = $this->drupalCreateUser([ + 'access administration pages', + 'administer content types', + 'administer menu', + 'create page content', + 'edit any page content', + 'delete any page content', + 'create content translations', + 'update content translations', + 'delete content translations', + 'translate any entity', + ]); + $this->drupalLogin($this->editor); + } + + /** + * Test creating, editing, deleting menu links via node form widget. + */ + public function testMenuNodeFormWidget() { + // Verify that cacheability metadata is bubbled from the menu link tree + // access checking that is performed when determining the "default parent + // item" options in menu_ui_form_node_type_form_alter(). The "log out" link + // adds the "user.roles:authenticated" cache context. + $this->drupalGet('admin/structure/types/manage/page'); + $this->assertSession()->responseHeaderContains('X-Drupal-Cache-Contexts', 'user.roles:authenticated'); + + // Verify that the menu link title has the correct maxlength. + $max_length = \Drupal::entityManager()->getBaseFieldDefinitions('menu_link_content')['title']->getSetting('max_length'); + $this->drupalGet('node/add/page'); + $this->assertPattern('//', 'Menu link title field has correct maxlength in node add form.'); + + // Disable the default main menu, so that no menus are enabled. + $edit = [ + 'menu_options[main]' => FALSE, + ]; + $this->drupalPostForm('admin/structure/types/manage/page', $edit, t('Save content type')); + + // Verify that no menu settings are displayed and nodes can be created. + $this->drupalGet('node/add/page'); + $this->assertText(t('Create Basic page')); + $this->assertNoText(t('Menu settings')); + $node_title = $this->randomMachineName(); + $edit = [ + 'title[0][value]' => $node_title, + 'body[0][value]' => $this->randomString(), + ]; + $this->drupalPostForm(NULL, $edit, t('Save')); + $node = $this->drupalGetNodeByTitle($node_title); + $this->assertEqual($node->getTitle(), $edit['title[0][value]']); + + // Test that we cannot set a menu item from a menu that is not set as + // available. + $edit = [ + 'menu_options[tools]' => 1, + 'menu_parent' => 'main:', + ]; + $this->drupalPostForm('admin/structure/types/manage/page', $edit, t('Save content type')); + $this->assertText(t('The selected menu item is not under one of the selected menus.')); + $this->assertNoRaw(t('The content type %name has been updated.', ['%name' => 'Basic page'])); + + // Enable Tools menu as available menu. + $edit = [ + 'menu_options[main]' => 1, + 'menu_options[tools]' => 1, + 'menu_parent' => 'main:', + ]; + $this->drupalPostForm('admin/structure/types/manage/page', $edit, t('Save content type')); + $this->assertRaw(t('The content type %name has been updated.', ['%name' => 'Basic page'])); + + // Test that we can preview a node that will create a menu item. + $edit = [ + 'title[0][value]' => $node_title, + 'menu[enabled]' => 1, + 'menu[title]' => 'Test preview', + ]; + $this->drupalPostForm('node/add/page', $edit, t('Preview')); + + // Create a node. + $node_title = $this->randomMachineName(); + $edit = [ + 'title[0][value]' => $node_title, + 'body[0][value]' => $this->randomString(), + ]; + $this->drupalPostForm('node/add/page', $edit, t('Save')); + $node = $this->drupalGetNodeByTitle($node_title); + // Assert that there is no link for the node. + $this->drupalGet('test-page'); + $this->assertNoLink($node_title); + + // Edit the node, enable the menu link setting, but skip the link title. + $edit = [ + 'menu[enabled]' => 1, + ]; + $this->drupalPostForm('node/' . $node->id() . '/edit', $edit, t('Save')); + // Assert that there is no link for the node. + $this->drupalGet('test-page'); + $this->assertNoLink($node_title); + + // Make sure the menu links only appear when the node is published. + // These buttons just appear for 'administer nodes' users. + $admin_user = $this->drupalCreateUser([ + 'access administration pages', + 'administer content types', + 'administer nodes', + 'administer menu', + 'create page content', + 'edit any page content', + ]); + $this->drupalLogin($admin_user); + // Assert that the link does not exist if unpublished. + $edit = [ + 'menu[enabled]' => 1, + 'menu[title]' => $node_title, + 'status[value]' => FALSE, + ]; + $this->drupalPostForm('node/' . $node->id() . '/edit', $edit, 'Save'); + $this->drupalGet('test-page'); + $this->assertNoLink($node_title, 'Found no menu link with the node unpublished'); + // Assert that the link exists if published. + $edit['status[value]'] = TRUE; + $this->drupalPostForm('node/' . $node->id() . '/edit', $edit, 'Save'); + $this->drupalGet('test-page'); + $this->assertLink($node_title, 0, 'Found a menu link with the node published'); + + // Log back in as normal user. + $this->drupalLogin($this->editor); + // Edit the node and create a menu link. + $edit = [ + 'menu[enabled]' => 1, + 'menu[title]' => $node_title, + 'menu[weight]' => 17, + ]; + $this->drupalPostForm('node/' . $node->id() . '/edit', $edit, t('Save')); + // Assert that the link exists. + $this->drupalGet('test-page'); + $this->assertLink($node_title); + + $this->drupalGet('node/' . $node->id() . '/edit'); + $this->assertFieldById('edit-menu-weight', 17, 'Menu weight correct in edit form'); + $this->assertPattern('//', 'Menu link title field has correct maxlength in node edit form.'); + + // Disable the menu link, then edit the node--the link should stay disabled. + $link_id = menu_ui_get_menu_link_defaults($node)['entity_id']; + /** @var \Drupal\menu_link_content\Entity\MenuLinkContent $link */ + $link = MenuLinkContent::load($link_id); + $link->set('enabled', FALSE); + $link->save(); + $this->drupalPostForm($node->urlInfo('edit-form'), $edit, t('Save')); + $link = MenuLinkContent::load($link_id); + $this->assertFalse($link->isEnabled(), 'Saving a node with a disabled menu link keeps the menu link disabled.'); + + // Edit the node and remove the menu link. + $edit = [ + 'menu[enabled]' => FALSE, + ]; + $this->drupalPostForm('node/' . $node->id() . '/edit', $edit, t('Save')); + // Assert that there is no link for the node. + $this->drupalGet('test-page'); + $this->assertNoLink($node_title); + + // Add a menu link to the Administration menu. + $item = MenuLinkContent::create([ + 'link' => [['uri' => 'entity:node/' . $node->id()]], + 'title' => $this->randomMachineName(16), + 'menu_name' => 'admin', + ]); + $item->save(); + + // Assert that disabled Administration menu is not shown on the + // node/$nid/edit page. + $this->drupalGet('node/' . $node->id() . '/edit'); + $this->assertText('Provide a menu link', 'Link in not allowed menu not shown in node edit form'); + // Assert that the link is still in the Administration menu after save. + $this->drupalPostForm('node/' . $node->id() . '/edit', $edit, t('Save')); + $link = MenuLinkContent::load($item->id()); + $this->assertTrue($link, 'Link in not allowed menu still exists after saving node'); + + // Move the menu link back to the Tools menu. + $item->menu_name->value = 'tools'; + $item->save(); + // Create a second node. + $child_node = $this->drupalCreateNode(['type' => 'article']); + // Assign a menu link to the second node, being a child of the first one. + $child_item = MenuLinkContent::create([ + 'link' => [['uri' => 'entity:node/' . $child_node->id()]], + 'title' => $this->randomMachineName(16), + 'parent' => $item->getPluginId(), + 'menu_name' => $item->getMenuName(), + ]); + $child_item->save(); + // Edit the first node. + $this->drupalGet('node/' . $node->id() . '/edit'); + // Assert that it is not possible to set the parent of the first node to itself or the second node. + $this->assertNoOption('edit-menu-menu-parent', 'tools:' . $item->getPluginId()); + $this->assertNoOption('edit-menu-menu-parent', 'tools:' . $child_item->getPluginId()); + // Assert that unallowed Administration menu is not available in options. + $this->assertNoOption('edit-menu-menu-parent', 'admin:'); + } + + /** + * Testing correct loading and saving of menu links via node form widget in a multilingual environment. + */ + public function testMultilingualMenuNodeFormWidget() { + // Setup languages. + $langcodes = ['de']; + foreach ($langcodes as $langcode) { + ConfigurableLanguage::createFromLangcode($langcode)->save(); + } + array_unshift($langcodes, \Drupal::languageManager()->getDefaultLanguage()->getId()); + + $config = \Drupal::service('config.factory')->getEditable('language.negotiation'); + // Ensure path prefix is used to determine the language. + $config->set('url.source', 'path_prefix'); + // Ensure that there's a path prefix set for english as well. + $config->set('url.prefixes.' . $langcodes[0], $langcodes[0]); + $config->save(); + + $this->rebuildContainer(); + + $languages = []; + foreach ($langcodes as $langcode) { + $languages[$langcode] = ConfigurableLanguage::load($langcode); + } + + // Use a UI form submission to make the node type and menu link content entity translatable. + $this->drupalLogout(); + $this->drupalLogin($this->rootUser); + $edit = [ + 'entity_types[node]' => TRUE, + 'entity_types[menu_link_content]' => TRUE, + 'settings[node][page][settings][language][language_alterable]' => TRUE, + 'settings[node][page][translatable]' => TRUE, + 'settings[node][page][fields][title]' => TRUE, + 'settings[menu_link_content][menu_link_content][translatable]' => TRUE, + ]; + $this->drupalPostForm('admin/config/regional/content-language', $edit, t('Save configuration')); + + // Log out and back in as normal user. + $this->drupalLogout(); + $this->drupalLogin($this->editor); + + // Create a node. + $node_title = $this->randomMachineName(8); + $node = Node::create([ + 'type' => 'page', + 'title' => $node_title, + 'body' => $this->randomMachineName(16), + 'uid' => $this->editor->id(), + 'status' => 1, + 'langcode' => $langcodes[0], + ]); + $node->save(); + + // Create translation. + $translated_node_title = $this->randomMachineName(8); + $node->addTranslation($langcodes[1], ['title' => $translated_node_title, 'body' => $this->randomMachineName(16), 'status' => 1]); + $node->save(); + + // Edit the node and create a menu link. + $edit = [ + 'menu[enabled]' => 1, + 'menu[title]' => $node_title, + 'menu[weight]' => 17, + ]; + $options = ['language' => $languages[$langcodes[0]]]; + $url = $node->toUrl('edit-form', $options); + $this->drupalPostForm($url, $edit, t('Save') . ' ' . t('(this translation)')); + + // Edit the node in a different language and translate the menu link. + $edit = [ + 'menu[enabled]' => 1, + 'menu[title]' => $translated_node_title, + 'menu[weight]' => 17, + ]; + $options = ['language' => $languages[$langcodes[1]]]; + $url = $node->toUrl('edit-form', $options); + $this->drupalPostForm($url, $edit, t('Save') . ' ' . t('(this translation)')); + + // Assert that the original link exists in the frontend. + $this->drupalGet('node/' . $node->id(), ['language' => $languages[$langcodes[0]]]); + $this->assertLink($node_title); + + // Assert that the translated link exists in the frontend. + $this->drupalGet('node/' . $node->id(), ['language' => $languages[$langcodes[1]]]); + $this->assertLink($translated_node_title); + + // Revisit the edit page in original language, check the loaded menu item title and save. + $options = ['language' => $languages[$langcodes[0]]]; + $url = $node->toUrl('edit-form', $options); + $this->drupalGet($url); + $this->assertFieldById('edit-menu-title', $node_title); + $this->drupalPostForm(NULL, [], t('Save') . ' ' . t('(this translation)')); + + // Revisit the edit page of the translation and check the loaded menu item title. + $options = ['language' => $languages[$langcodes[1]]]; + $url = $node->toUrl('edit-form', $options); + $this->drupalGet($url); + $this->assertFieldById('edit-menu-title', $translated_node_title); + } + +} diff -r e200cb7efeb3 -r c2387f117808 core/modules/menu_ui/tests/src/Functional/MenuUiTest.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/core/modules/menu_ui/tests/src/Functional/MenuUiTest.php Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,950 @@ +drupalPlaceBlock('page_title_block'); + + $this->drupalCreateContentType(['type' => 'article', 'name' => 'Article']); + + // Create users. + $this->adminUser = $this->drupalCreateUser(['access administration pages', 'administer blocks', 'administer menu', 'create article content']); + $this->authenticatedUser = $this->drupalCreateUser([]); + } + + /** + * Tests menu functionality using the admin and user interfaces. + */ + public function testMenu() { + // Log in the user. + $this->drupalLogin($this->adminUser); + $this->items = []; + + $this->menu = $this->addCustomMenu(); + $this->doMenuTests(); + $this->doTestMenuBlock(); + $this->addInvalidMenuLink(); + $this->addCustomMenuCRUD(); + + // Verify that the menu links rebuild is idempotent and leaves the same + // number of links in the table. + /** @var \Drupal\Core\Menu\MenuLinkManagerInterface $menu_link_manager */ + $menu_link_manager = \Drupal::service('plugin.manager.menu.link'); + $before_count = $menu_link_manager->countMenuLinks(NULL); + $menu_link_manager->rebuild(); + $after_count = $menu_link_manager->countMenuLinks(NULL); + $this->assertIdentical($before_count, $after_count, 'MenuLinkManager::rebuild() does not add more links'); + // Do standard user tests. + // Log in the user. + $this->drupalLogin($this->authenticatedUser); + $this->verifyAccess(403); + + foreach ($this->items as $item) { + // Menu link URIs are stored as 'internal:/node/$nid'. + $node = Node::load(str_replace('internal:/node/', '', $item->link->uri)); + $this->verifyMenuLink($item, $node); + } + + // Log in the administrator. + $this->drupalLogin($this->adminUser); + + // Verify delete link exists and reset link does not exist. + $this->drupalGet('admin/structure/menu/manage/' . $this->menu->id()); + $this->assertLinkByHref(Url::fromRoute('entity.menu_link_content.delete_form', ['menu_link_content' => $this->items[0]->id()])->toString()); + $this->assertNoLinkByHref(Url::fromRoute('menu_ui.link_reset', ['menu_link_plugin' => $this->items[0]->getPluginId()])->toString()); + // Check delete and reset access. + $this->drupalGet('admin/structure/menu/item/' . $this->items[0]->id() . '/delete'); + $this->assertResponse(200); + $this->drupalGet('admin/structure/menu/link/' . $this->items[0]->getPluginId() . '/reset'); + $this->assertResponse(403); + + // Delete menu links. + foreach ($this->items as $item) { + $this->deleteMenuLink($item); + } + + // Delete custom menu. + $this->deleteCustomMenu(); + + // Modify and reset a standard menu link. + $instance = $this->getStandardMenuLink(); + $old_weight = $instance->getWeight(); + // Edit the static menu link. + $edit = []; + $edit['weight'] = 10; + $id = $instance->getPluginId(); + $this->drupalPostForm("admin/structure/menu/link/$id/edit", $edit, t('Save')); + $this->assertResponse(200); + $this->assertText('The menu link has been saved.'); + $menu_link_manager->resetDefinitions(); + + $instance = $menu_link_manager->createInstance($instance->getPluginId()); + $this->assertEqual($edit['weight'], $instance->getWeight(), 'Saving an existing link updates the weight.'); + $this->resetMenuLink($instance, $old_weight); + } + + /** + * Adds a custom menu using CRUD functions. + */ + public function addCustomMenuCRUD() { + // Add a new custom menu. + $menu_name = substr(hash('sha256', $this->randomMachineName(16)), 0, MENU_MAX_MENU_NAME_LENGTH_UI); + $label = $this->randomMachineName(16); + + $menu = Menu::create([ + 'id' => $menu_name, + 'label' => $label, + 'description' => 'Description text', + ]); + $menu->save(); + + // Assert the new menu. + $this->drupalGet('admin/structure/menu/manage/' . $menu_name); + $this->assertRaw($label, 'Custom menu was added.'); + + // Edit the menu. + $new_label = $this->randomMachineName(16); + $menu->set('label', $new_label); + $menu->save(); + $this->drupalGet('admin/structure/menu/manage/' . $menu_name); + $this->assertRaw($new_label, 'Custom menu was edited.'); + } + + /** + * Creates a custom menu. + * + * @return \Drupal\system\Entity\Menu + * The custom menu that has been created. + */ + public function addCustomMenu() { + // Try adding a menu using a menu_name that is too long. + $this->drupalGet('admin/structure/menu/add'); + $menu_name = substr(hash('sha256', $this->randomMachineName(16)), 0, MENU_MAX_MENU_NAME_LENGTH_UI + 1); + $label = $this->randomMachineName(16); + $edit = [ + 'id' => $menu_name, + 'description' => '', + 'label' => $label, + ]; + $this->drupalPostForm('admin/structure/menu/add', $edit, t('Save')); + + // Verify that using a menu_name that is too long results in a validation + // message. + $this->assertRaw(t('@name cannot be longer than %max characters but is currently %length characters long.', [ + '@name' => t('Menu name'), + '%max' => MENU_MAX_MENU_NAME_LENGTH_UI, + '%length' => Unicode::strlen($menu_name), + ])); + + // Change the menu_name so it no longer exceeds the maximum length. + $menu_name = substr(hash('sha256', $this->randomMachineName(16)), 0, MENU_MAX_MENU_NAME_LENGTH_UI); + $edit['id'] = $menu_name; + $this->drupalPostForm('admin/structure/menu/add', $edit, t('Save')); + + // Verify that no validation error is given for menu_name length. + $this->assertNoRaw(t('@name cannot be longer than %max characters but is currently %length characters long.', [ + '@name' => t('Menu name'), + '%max' => MENU_MAX_MENU_NAME_LENGTH_UI, + '%length' => Unicode::strlen($menu_name), + ])); + // Verify that the confirmation message is displayed. + $this->assertRaw(t('Menu %label has been added.', ['%label' => $label])); + $this->drupalGet('admin/structure/menu'); + $this->assertText($label, 'Menu created'); + + // Confirm that the custom menu block is available. + $this->drupalGet('admin/structure/block/list/' . $this->config('system.theme')->get('default')); + $this->clickLink('Place block'); + $this->assertText($label); + + // Enable the block. + $block = $this->drupalPlaceBlock('system_menu_block:' . $menu_name); + $this->blockPlacements[$menu_name] = $block->id(); + return Menu::load($menu_name); + } + + /** + * Deletes the locally stored custom menu. + * + * This deletes the custom menu that is stored in $this->menu and performs + * tests on the menu delete user interface. + */ + public function deleteCustomMenu() { + $menu_name = $this->menu->id(); + $label = $this->menu->label(); + + // Delete custom menu. + $this->drupalPostForm("admin/structure/menu/manage/$menu_name/delete", [], t('Delete')); + $this->assertResponse(200); + $this->assertRaw(t('The menu %title has been deleted.', ['%title' => $label]), 'Custom menu was deleted'); + $this->assertNull(Menu::load($menu_name), 'Custom menu was deleted'); + // Test if all menu links associated with the menu were removed from + // database. + $result = entity_load_multiple_by_properties('menu_link_content', ['menu_name' => $menu_name]); + $this->assertFalse($result, 'All menu links associated with the custom menu were deleted.'); + + // Make sure there's no delete button on system menus. + $this->drupalGet('admin/structure/menu/manage/main'); + $this->assertNoRaw('edit-delete', 'The delete button was not found'); + + // Try to delete the main menu. + $this->drupalGet('admin/structure/menu/manage/main/delete'); + $this->assertText(t('You are not authorized to access this page.')); + } + + /** + * Tests menu functionality. + */ + public function doMenuTests() { + $menu_name = $this->menu->id(); + + // Test the 'Add link' local action. + $this->drupalGet(Url::fromRoute('entity.menu.edit_form', ['menu' => $menu_name])); + + $this->clickLink(t('Add link')); + $link_title = $this->randomString(); + $this->drupalPostForm(NULL, ['link[0][uri]' => '/', 'title[0][value]' => $link_title], t('Save')); + $this->assertUrl(Url::fromRoute('entity.menu.edit_form', ['menu' => $menu_name])); + // Test the 'Edit' operation. + $this->clickLink(t('Edit')); + $this->assertFieldByName('title[0][value]', $link_title); + $link_title = $this->randomString(); + $this->drupalPostForm(NULL, ['title[0][value]' => $link_title], t('Save')); + $this->assertUrl(Url::fromRoute('entity.menu.edit_form', ['menu' => $menu_name])); + // Test the 'Delete' operation. + $this->clickLink(t('Delete')); + $this->assertRaw(t('Are you sure you want to delete the custom menu link %item?', ['%item' => $link_title])); + $this->drupalPostForm(NULL, [], t('Delete')); + $this->assertUrl(Url::fromRoute('entity.menu.edit_form', ['menu' => $menu_name])); + + // Add nodes to use as links for menu links. + $node1 = $this->drupalCreateNode(['type' => 'article']); + $node2 = $this->drupalCreateNode(['type' => 'article']); + $node3 = $this->drupalCreateNode(['type' => 'article']); + $node4 = $this->drupalCreateNode(['type' => 'article']); + // Create a node with an alias. + $node5 = $this->drupalCreateNode([ + 'type' => 'article', + 'path' => [ + 'alias' => '/node5', + ], + ]); + + // Verify add link button. + $this->drupalGet('admin/structure/menu'); + $this->assertLinkByHref('admin/structure/menu/manage/' . $menu_name . '/add', 0, "The add menu link button URL is correct"); + + // Verify form defaults. + $this->doMenuLinkFormDefaultsTest(); + + // Add menu links. + $item1 = $this->addMenuLink('', '/node/' . $node1->id(), $menu_name, TRUE); + $item2 = $this->addMenuLink($item1->getPluginId(), '/node/' . $node2->id(), $menu_name, FALSE); + $item3 = $this->addMenuLink($item2->getPluginId(), '/node/' . $node3->id(), $menu_name); + + // Hierarchy + // <$menu_name> + // - item1 + // -- item2 + // --- item3 + + $this->assertMenuLink([ + 'children' => [$item2->getPluginId(), $item3->getPluginId()], + 'parents' => [$item1->getPluginId()], + // We assert the language code here to make sure that the language + // selection element degrades gracefully without the Language module. + 'langcode' => 'en', + ], $item1->getPluginId()); + $this->assertMenuLink([ + 'children' => [$item3->getPluginId()], + 'parents' => [$item2->getPluginId(), $item1->getPluginId()], + // See above. + 'langcode' => 'en', + ], $item2->getPluginId()); + $this->assertMenuLink([ + 'children' => [], + 'parents' => [$item3->getPluginId(), $item2->getPluginId(), $item1->getPluginId()], + // See above. + 'langcode' => 'en', + ], $item3->getPluginId()); + + // Verify menu links. + $this->verifyMenuLink($item1, $node1); + $this->verifyMenuLink($item2, $node2, $item1, $node1); + $this->verifyMenuLink($item3, $node3, $item2, $node2); + + // Add more menu links. + $item4 = $this->addMenuLink('', '/node/' . $node4->id(), $menu_name); + $item5 = $this->addMenuLink($item4->getPluginId(), '/node/' . $node5->id(), $menu_name); + // Create a menu link pointing to an alias. + $item6 = $this->addMenuLink($item4->getPluginId(), '/node5', $menu_name, TRUE, '0'); + + // Hierarchy + // <$menu_name> + // - item1 + // -- item2 + // --- item3 + // - item4 + // -- item5 + // -- item6 + + $this->assertMenuLink([ + 'children' => [$item5->getPluginId(), $item6->getPluginId()], + 'parents' => [$item4->getPluginId()], + // See above. + 'langcode' => 'en', + ], $item4->getPluginId()); + $this->assertMenuLink([ + 'children' => [], + 'parents' => [$item5->getPluginId(), $item4->getPluginId()], + 'langcode' => 'en', + ], $item5->getPluginId()); + $this->assertMenuLink([ + 'children' => [], + 'parents' => [$item6->getPluginId(), $item4->getPluginId()], + 'route_name' => 'entity.node.canonical', + 'route_parameters' => ['node' => $node5->id()], + 'url' => '', + // See above. + 'langcode' => 'en', + ], $item6->getPluginId()); + + // Modify menu links. + $this->modifyMenuLink($item1); + $this->modifyMenuLink($item2); + + // Toggle menu links. + $this->toggleMenuLink($item1); + $this->toggleMenuLink($item2); + + // Move link and verify that descendants are updated. + $this->moveMenuLink($item2, $item5->getPluginId(), $menu_name); + // Hierarchy + // <$menu_name> + // - item1 + // - item4 + // -- item5 + // --- item2 + // ---- item3 + // -- item6 + + $this->assertMenuLink([ + 'children' => [], + 'parents' => [$item1->getPluginId()], + // See above. + 'langcode' => 'en', + ], $item1->getPluginId()); + $this->assertMenuLink([ + 'children' => [$item5->getPluginId(), $item6->getPluginId(), $item2->getPluginId(), $item3->getPluginId()], + 'parents' => [$item4->getPluginId()], + // See above. + 'langcode' => 'en', + ], $item4->getPluginId()); + + $this->assertMenuLink([ + 'children' => [$item2->getPluginId(), $item3->getPluginId()], + 'parents' => [$item5->getPluginId(), $item4->getPluginId()], + // See above. + 'langcode' => 'en', + ], $item5->getPluginId()); + $this->assertMenuLink([ + 'children' => [$item3->getPluginId()], + 'parents' => [$item2->getPluginId(), $item5->getPluginId(), $item4->getPluginId()], + // See above. + 'langcode' => 'en', + ], $item2->getPluginId()); + $this->assertMenuLink([ + 'children' => [], + 'parents' => [$item3->getPluginId(), $item2->getPluginId(), $item5->getPluginId(), $item4->getPluginId()], + // See above. + 'langcode' => 'en', + ], $item3->getPluginId()); + + // Add 102 menu links with increasing weights, then make sure the last-added + // item's weight doesn't get changed because of the old hardcoded delta=50. + $items = []; + for ($i = -50; $i <= 51; $i++) { + $items[$i] = $this->addMenuLink('', '/node/' . $node1->id(), $menu_name, TRUE, strval($i)); + } + $this->assertMenuLink(['weight' => '51'], $items[51]->getPluginId()); + + // Disable a link and then re-enable the link via the overview form. + $this->disableMenuLink($item1); + $edit = []; + $edit['links[menu_plugin_id:' . $item1->getPluginId() . '][enabled]'] = TRUE; + $this->drupalPostForm('admin/structure/menu/manage/' . $item1->getMenuName(), $edit, t('Save')); + + // Mark item2, item4 and item5 as expanded. + // This is done in order to show them on the frontpage. + $item2->expanded->value = 1; + $item2->save(); + $item4->expanded->value = 1; + $item4->save(); + $item5->expanded->value = 1; + $item5->save(); + + // Verify in the database. + $this->assertMenuLink(['enabled' => 1], $item1->getPluginId()); + + // Add an external link. + $item7 = $this->addMenuLink('', 'https://www.drupal.org', $menu_name); + $this->assertMenuLink(['url' => 'https://www.drupal.org'], $item7->getPluginId()); + + // Add menu item. + $item8 = $this->addMenuLink('', '/', $menu_name); + $this->assertMenuLink(['route_name' => ''], $item8->getPluginId()); + $this->drupalGet(''); + $this->assertResponse(200); + // Make sure we get routed correctly. + $this->clickLink($item8->getTitle()); + $this->assertResponse(200); + + // Check invalid menu link parents. + $this->checkInvalidParentMenuLinks(); + + // Save menu links for later tests. + $this->items[] = $item1; + $this->items[] = $item2; + } + + /** + * Ensures that the proper default values are set when adding a menu link + */ + protected function doMenuLinkFormDefaultsTest() { + $this->drupalGet("admin/structure/menu/manage/tools/add"); + $this->assertResponse(200); + + $this->assertFieldByName('title[0][value]', ''); + $this->assertFieldByName('link[0][uri]', ''); + + $this->assertNoFieldChecked('edit-expanded-value'); + $this->assertFieldChecked('edit-enabled-value'); + + $this->assertFieldByName('description[0][value]', ''); + $this->assertFieldByName('weight[0][value]', 0); + } + + /** + * Adds and removes a menu link with a query string and fragment. + */ + public function testMenuQueryAndFragment() { + $this->drupalLogin($this->adminUser); + + // Make a path with query and fragment on. + $path = '/test-page?arg1=value1&arg2=value2'; + $item = $this->addMenuLink('', $path); + + $this->drupalGet('admin/structure/menu/item/' . $item->id() . '/edit'); + $this->assertFieldByName('link[0][uri]', $path, 'Path is found with both query and fragment.'); + + // Now change the path to something without query and fragment. + $path = '/test-page'; + $this->drupalPostForm('admin/structure/menu/item/' . $item->id() . '/edit', ['link[0][uri]' => $path], t('Save')); + $this->drupalGet('admin/structure/menu/item/' . $item->id() . '/edit'); + $this->assertFieldByName('link[0][uri]', $path, 'Path no longer has query or fragment.'); + + // Use #fragment and ensure that saving it does not lose its content. + $path = '?arg1=value#fragment'; + $item = $this->addMenuLink('', $path); + + $this->drupalGet('admin/structure/menu/item/' . $item->id() . '/edit'); + $this->assertFieldByName('link[0][uri]', $path, 'Path is found with both query and fragment.'); + + $this->drupalPostForm('admin/structure/menu/item/' . $item->id() . '/edit', [], t('Save')); + + $this->drupalGet('admin/structure/menu/item/' . $item->id() . '/edit'); + $this->assertFieldByName('link[0][uri]', $path, 'Path is found with both query and fragment.'); + } + + /** + * Tests renaming the built-in menu. + */ + public function testSystemMenuRename() { + $this->drupalLogin($this->adminUser); + $edit = [ + 'label' => $this->randomMachineName(16), + ]; + $this->drupalPostForm('admin/structure/menu/manage/main', $edit, t('Save')); + + // Make sure menu shows up with new name in block addition. + $default_theme = $this->config('system.theme')->get('default'); + $this->drupalget('admin/structure/block/list/' . $default_theme); + $this->clickLink('Place block'); + $this->assertText($edit['label']); + } + + /** + * Tests that menu items pointing to unpublished nodes are editable. + */ + public function testUnpublishedNodeMenuItem() { + $this->drupalLogin($this->drupalCreateUser(['access administration pages', 'administer blocks', 'administer menu', 'create article content', 'bypass node access'])); + // Create an unpublished node. + $node = $this->drupalCreateNode([ + 'type' => 'article', + 'status' => NodeInterface::NOT_PUBLISHED, + ]); + + $item = $this->addMenuLink('', '/node/' . $node->id()); + $this->modifyMenuLink($item); + + // Test that a user with 'administer menu' but without 'bypass node access' + // cannot see the menu item. + $this->drupalLogout(); + $this->drupalLogin($this->adminUser); + $this->drupalGet('admin/structure/menu/manage/' . $item->getMenuName()); + $this->assertNoText($item->getTitle(), "Menu link pointing to unpublished node is only visible to users with 'bypass node access' permission"); + // The cache contexts associated with the (in)accessible menu links are + // bubbled. See DefaultMenuLinkTreeManipulators::menuLinkCheckAccess(). + $this->assertSession()->responseHeaderContains('X-Drupal-Cache-Contexts', 'user.permissions'); + } + + /** + * Adds a menu link using the UI. + * + * @param string $parent + * Optional parent menu link id. + * @param string $path + * The path to enter on the form. Defaults to the front page. + * @param string $menu_name + * Menu name. Defaults to 'tools'. + * @param bool $expanded + * Whether or not this menu link is expanded. Setting this to TRUE should + * test whether it works when we do the authenticatedUser tests. Defaults + * to FALSE. + * @param string $weight + * Menu weight. Defaults to 0. + * + * @return \Drupal\menu_link_content\Entity\MenuLinkContent + * A menu link entity. + */ + public function addMenuLink($parent = '', $path = '/', $menu_name = 'tools', $expanded = FALSE, $weight = '0') { + // View add menu link page. + $this->drupalGet("admin/structure/menu/manage/$menu_name/add"); + $this->assertResponse(200); + + $title = '!link_' . $this->randomMachineName(16); + $edit = [ + 'link[0][uri]' => $path, + 'title[0][value]' => $title, + 'description[0][value]' => '', + 'enabled[value]' => 1, + 'expanded[value]' => $expanded, + 'menu_parent' => $menu_name . ':' . $parent, + 'weight[0][value]' => $weight, + ]; + + // Add menu link. + $this->drupalPostForm(NULL, $edit, t('Save')); + $this->assertResponse(200); + $this->assertText('The menu link has been saved.'); + + $menu_links = entity_load_multiple_by_properties('menu_link_content', ['title' => $title]); + + $menu_link = reset($menu_links); + $this->assertTrue($menu_link, 'Menu link was found in database.'); + $this->assertMenuLink(['menu_name' => $menu_name, 'children' => [], 'parent' => $parent], $menu_link->getPluginId()); + + return $menu_link; + } + + /** + * Attempts to add menu link with invalid path or no access permission. + */ + public function addInvalidMenuLink() { + foreach (['access' => '/admin/people/permissions'] as $type => $link_path) { + $edit = [ + 'link[0][uri]' => $link_path, + 'title[0][value]' => 'title', + ]; + $this->drupalPostForm("admin/structure/menu/manage/{$this->menu->id()}/add", $edit, t('Save')); + $this->assertRaw(t("The path '@link_path' is inaccessible.", ['@link_path' => $link_path]), 'Menu link was not created'); + } + } + + /** + * Tests that parent options are limited by depth when adding menu links. + */ + public function checkInvalidParentMenuLinks() { + $last_link = NULL; + $created_links = []; + + // Get the max depth of the tree. + $menu_link_tree = \Drupal::service('menu.link_tree'); + $max_depth = $menu_link_tree->maxDepth(); + + // Create a maximum number of menu links, each a child of the previous. + for ($i = 0; $i <= $max_depth - 1; $i++) { + $parent = $last_link ? 'tools:' . $last_link->getPluginId() : 'tools:'; + $title = 'title' . $i; + $edit = [ + 'link[0][uri]' => '/', + 'title[0][value]' => $title, + 'menu_parent' => $parent, + 'description[0][value]' => '', + 'enabled[value]' => 1, + 'expanded[value]' => FALSE, + 'weight[0][value]' => '0', + ]; + $this->drupalPostForm("admin/structure/menu/manage/{$this->menu->id()}/add", $edit, t('Save')); + $menu_links = entity_load_multiple_by_properties('menu_link_content', ['title' => $title]); + $last_link = reset($menu_links); + $created_links[] = 'tools:' . $last_link->getPluginId(); + } + + // The last link cannot be a parent in the new menu link form. + $this->drupalGet('admin/structure/menu/manage/admin/add'); + $value = 'tools:' . $last_link->getPluginId(); + $this->assertNoOption('edit-menu-parent', $value, 'The invalid option is not there.'); + + // All but the last link can be parents in the new menu link form. + array_pop($created_links); + foreach ($created_links as $key => $link) { + $this->assertOption('edit-menu-parent', $link, 'The valid option number ' . ($key + 1) . ' is there.'); + } + } + + /** + * Verifies a menu link using the UI. + * + * @param \Drupal\menu_link_content\Entity\MenuLinkContent $item + * Menu link. + * @param object $item_node + * Menu link content node. + * @param \Drupal\menu_link_content\Entity\MenuLinkContent $parent + * Parent menu link. + * @param object $parent_node + * Parent menu link content node. + */ + public function verifyMenuLink(MenuLinkContent $item, $item_node, MenuLinkContent $parent = NULL, $parent_node = NULL) { + // View home page. + $this->drupalGet(''); + $this->assertResponse(200); + + // Verify parent menu link. + if (isset($parent)) { + // Verify menu link. + $title = $parent->getTitle(); + $this->assertLink($title, 0, 'Parent menu link was displayed'); + + // Verify menu link link. + $this->clickLink($title); + $title = $parent_node->label(); + $this->assertTitle(t("@title | Drupal", ['@title' => $title]), 'Parent menu link link target was correct'); + } + + // Verify menu link. + $title = $item->getTitle(); + $this->assertLink($title, 0, 'Menu link was displayed'); + + // Verify menu link link. + $this->clickLink($title); + $title = $item_node->label(); + $this->assertTitle(t("@title | Drupal", ['@title' => $title]), 'Menu link link target was correct'); + } + + /** + * Changes the parent of a menu link using the UI. + * + * @param \Drupal\menu_link_content\MenuLinkContentInterface $item + * The menu link item to move. + * @param int $parent + * The id of the new parent. + * @param string $menu_name + * The menu the menu link will be moved to. + */ + public function moveMenuLink(MenuLinkContent $item, $parent, $menu_name) { + $mlid = $item->id(); + + $edit = [ + 'menu_parent' => $menu_name . ':' . $parent, + ]; + $this->drupalPostForm("admin/structure/menu/item/$mlid/edit", $edit, t('Save')); + $this->assertResponse(200); + } + + /** + * Modifies a menu link using the UI. + * + * @param \Drupal\menu_link_content\Entity\MenuLinkContent $item + * Menu link entity. + */ + public function modifyMenuLink(MenuLinkContent $item) { + $item->title->value = $this->randomMachineName(16); + + $mlid = $item->id(); + $title = $item->getTitle(); + + // Edit menu link. + $edit = []; + $edit['title[0][value]'] = $title; + $this->drupalPostForm("admin/structure/menu/item/$mlid/edit", $edit, t('Save')); + $this->assertResponse(200); + $this->assertText('The menu link has been saved.'); + // Verify menu link. + $this->drupalGet('admin/structure/menu/manage/' . $item->getMenuName()); + $this->assertText($title, 'Menu link was edited'); + } + + /** + * Resets a standard menu link using the UI. + * + * @param \Drupal\Core\Menu\MenuLinkInterface $menu_link + * The Menu link. + * @param int $old_weight + * Original title for menu link. + */ + public function resetMenuLink(MenuLinkInterface $menu_link, $old_weight) { + // Reset menu link. + $this->drupalPostForm("admin/structure/menu/link/{$menu_link->getPluginId()}/reset", [], t('Reset')); + $this->assertResponse(200); + $this->assertRaw(t('The menu link was reset to its default settings.'), 'Menu link was reset'); + + // Verify menu link. + $instance = \Drupal::service('plugin.manager.menu.link')->createInstance($menu_link->getPluginId()); + $this->assertEqual($old_weight, $instance->getWeight(), 'Resets to the old weight.'); + } + + /** + * Deletes a menu link using the UI. + * + * @param \Drupal\menu_link_content\Entity\MenuLinkContent $item + * Menu link. + */ + public function deleteMenuLink(MenuLinkContent $item) { + $mlid = $item->id(); + $title = $item->getTitle(); + + // Delete menu link. + $this->drupalPostForm("admin/structure/menu/item/$mlid/delete", [], t('Delete')); + $this->assertResponse(200); + $this->assertRaw(t('The menu link %title has been deleted.', ['%title' => $title]), 'Menu link was deleted'); + + // Verify deletion. + $this->drupalGet(''); + $this->assertNoText($title, 'Menu link was deleted'); + } + + /** + * Alternately disables and enables a menu link. + * + * @param \Drupal\menu_link_content\Entity\MenuLinkContent $item + * Menu link. + */ + public function toggleMenuLink(MenuLinkContent $item) { + $this->disableMenuLink($item); + + // Verify menu link is absent. + $this->drupalGet(''); + $this->assertNoText($item->getTitle(), 'Menu link was not displayed'); + $this->enableMenuLink($item); + + // Verify menu link is displayed. + $this->drupalGet(''); + $this->assertText($item->getTitle(), 'Menu link was displayed'); + } + + /** + * Disables a menu link. + * + * @param \Drupal\menu_link_content\Entity\MenuLinkContent $item + * Menu link. + */ + public function disableMenuLink(MenuLinkContent $item) { + $mlid = $item->id(); + $edit['enabled[value]'] = FALSE; + $this->drupalPostForm("admin/structure/menu/item/$mlid/edit", $edit, t('Save')); + + // Unlike most other modules, there is no confirmation message displayed. + // Verify in the database. + $this->assertMenuLink(['enabled' => 0], $item->getPluginId()); + } + + /** + * Enables a menu link. + * + * @param \Drupal\menu_link_content\Entity\MenuLinkContent $item + * Menu link. + */ + public function enableMenuLink(MenuLinkContent $item) { + $mlid = $item->id(); + $edit['enabled[value]'] = TRUE; + $this->drupalPostForm("admin/structure/menu/item/$mlid/edit", $edit, t('Save')); + + // Verify in the database. + $this->assertMenuLink(['enabled' => 1], $item->getPluginId()); + } + + /** + * Tests if admin users, other than UID1, can access parents AJAX callback. + */ + public function testMenuParentsJsAccess() { + $this->drupalLogin($this->drupalCreateUser(['administer menu'])); + // Just check access to the callback overall, the POST data is irrelevant. + $this->drupalGet('admin/structure/menu/parents', ['query' => [MainContentViewSubscriber::WRAPPER_FORMAT => 'drupal_ajax']], ['X-Requested-With: XMLHttpRequest']); + $this->assertSession()->statusCodeEquals(200); + + // Log in as authenticated user. + $this->drupalLogin($this->drupalCreateUser()); + // Check that a simple user is not able to access the menu. + $this->drupalGet('admin/structure/menu/parents', ['query' => [MainContentViewSubscriber::WRAPPER_FORMAT => 'drupal_ajax']], ['X-Requested-With: XMLHttpRequest']); + $this->assertSession()->statusCodeEquals(403); + } + + /** + * Returns standard menu link. + * + * @return \Drupal\Core\Menu\MenuLinkInterface + * A menu link plugin. + */ + private function getStandardMenuLink() { + // Retrieve menu link id of the Log out menu link, which will always be on + // the front page. + /** @var \Drupal\Core\Menu\MenuLinkManagerInterface $menu_link_manager */ + $menu_link_manager = \Drupal::service('plugin.manager.menu.link'); + $instance = $menu_link_manager->getInstance(['id' => 'user.logout']); + + $this->assertTrue((bool) $instance, 'Standard menu link was loaded'); + return $instance; + } + + /** + * Verifies the logged in user has the desired access to various menu pages. + * + * @param int $response + * (optional) The expected HTTP response code. Defaults to 200. + */ + private function verifyAccess($response = 200) { + // View menu help page. + $this->drupalGet('admin/help/menu'); + $this->assertResponse($response); + if ($response == 200) { + $this->assertText(t('Menu'), 'Menu help was displayed'); + } + + // View menu build overview page. + $this->drupalGet('admin/structure/menu'); + $this->assertResponse($response); + if ($response == 200) { + $this->assertText(t('Menus'), 'Menu build overview page was displayed'); + } + + // View tools menu customization page. + $this->drupalGet('admin/structure/menu/manage/' . $this->menu->id()); + $this->assertResponse($response); + if ($response == 200) { + $this->assertText(t('Tools'), 'Tools menu page was displayed'); + } + + // View menu edit page for a static link. + $item = $this->getStandardMenuLink(); + $this->drupalGet('admin/structure/menu/link/' . $item->getPluginId() . '/edit'); + $this->assertResponse($response); + if ($response == 200) { + $this->assertText(t('Edit menu item'), 'Menu edit page was displayed'); + } + + // View add menu page. + $this->drupalGet('admin/structure/menu/add'); + $this->assertResponse($response); + if ($response == 200) { + $this->assertText(t('Menus'), 'Add menu page was displayed'); + } + } + + /** + * Tests menu block settings. + */ + protected function doTestMenuBlock() { + $menu_id = $this->menu->id(); + $block_id = $this->blockPlacements[$menu_id]; + $this->drupalGet('admin/structure/block/manage/' . $block_id); + $this->drupalPostForm(NULL, [ + 'settings[depth]' => 3, + 'settings[level]' => 2, + ], t('Save block')); + $block = Block::load($block_id); + $settings = $block->getPlugin()->getConfiguration(); + $this->assertEqual($settings['depth'], 3); + $this->assertEqual($settings['level'], 2); + // Reset settings. + $block->getPlugin()->setConfigurationValue('depth', 0); + $block->getPlugin()->setConfigurationValue('level', 1); + $block->save(); + } + +} diff -r e200cb7efeb3 -r c2387f117808 core/modules/menu_ui/tests/src/FunctionalJavascript/MenuUiJavascriptTest.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/core/modules/menu_ui/tests/src/FunctionalJavascript/MenuUiJavascriptTest.php Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,159 @@ +drupalLogin($this->drupalCreateUser([ + 'administer menu', + 'access contextual links', + 'administer blocks', + ])); + $menu = $this->addCustomMenu(); + + $block = $this->drupalPlaceBlock('system_menu_block:' . $menu->id(), [ + 'label' => 'Custom menu', + 'provider' => 'system' + ]); + $this->addMenuLink('', '/', $menu->id()); + + $this->drupalGet('test-page'); + + // Click on 'Configure block' contextual link. + $this->clickContextualLink("#block-{$block->id()}", 'Configure block'); + // Check that we're on block configuration form. + $this->assertNotEmpty($this->getSession()->getPage()->findLink('Remove block')); + + $this->drupalGet('test-page'); + + // Click on 'Edit menu' contextual link. + $this->clickContextualLink("#block-{$block->id()}", 'Edit menu'); + // Check that we're on block configuration form. + $this->assertSession()->pageTextContains("Machine name: {$menu->id()}"); + } + + /** + * Creates a custom menu. + * + * @return \Drupal\system\Entity\Menu + * The custom menu that has been created. + */ + protected function addCustomMenu() { + // Try adding a menu using a menu_name that is too long. + $label = $this->randomMachineName(16); + $menu_id = strtolower($this->randomMachineName(MENU_MAX_MENU_NAME_LENGTH_UI + 1)); + + $this->drupalGet('admin/structure/menu/add'); + $page = $this->getSession()->getPage(); + // Type the label to activate the machine name field and the edit button. + $page->fillField('Title', $label); + // Wait for the machine name widget to be activated. + $this->assertSession()->waitForElementVisible('css', 'button[type=button].link:contains(Edit)'); + // Activate the machine name text field. + $page->pressButton('Edit'); + // Try to fill a text longer than the allowed limit. + $page->fillField('Menu name', $menu_id); + $page->pressButton('Save'); + // Check that the menu was saved with the ID truncated to the max length. + $menu = Menu::load(substr($menu_id, 0, MENU_MAX_MENU_NAME_LENGTH_UI)); + $this->assertEquals($label, $menu->label()); + + // Check that the menu was added. + $this->drupalGet('admin/structure/menu'); + $this->assertSession()->pageTextContains($label); + + // Confirm that the custom menu block is available. + $this->drupalGet('admin/structure/block/list/' . $this->config('system.theme')->get('default')); + $this->clickLink('Place block'); + // Wait for the modal dialog to be loaded. + $this->assertSession()->waitForElement('css', "div[aria-describedby=drupal-modal]"); + // Check that the block is available to be placed. + $this->assertSession()->pageTextContains($label); + + return $menu; + } + + /** + * Adds a menu link using the UI. + * + * @param string $parent + * Optional parent menu link id. + * @param string $path + * The path to enter on the form. Defaults to the front page. + * @param string $menu_id + * Menu ID. Defaults to 'tools'. + * @param bool $expanded + * Whether or not this menu link is expanded. Setting this to TRUE should + * test whether it works when we do the authenticatedUser tests. Defaults + * to FALSE. + * @param string $weight + * Menu weight. Defaults to 0. + * + * @return \Drupal\menu_link_content\Entity\MenuLinkContent + * A menu link entity. + */ + protected function addMenuLink($parent = '', $path = '/', $menu_id = 'tools', $expanded = FALSE, $weight = '0') { + // View add menu link page. + $this->drupalGet("admin/structure/menu/manage/$menu_id/add"); + $this->assertSession()->statusCodeEquals(200); + + $title = '!link_' . $this->randomMachineName(16); + $edit = [ + 'link[0][uri]' => $path, + 'title[0][value]' => $title, + 'description[0][value]' => '', + 'enabled[value]' => 1, + 'expanded[value]' => $expanded, + 'menu_parent' => $menu_id . ':' . $parent, + 'weight[0][value]' => $weight, + ]; + + // Add menu link. + $this->drupalPostForm(NULL, $edit, 'Save'); + $this->assertSession()->statusCodeEquals(200); + $this->assertSession()->pageTextContains('The menu link has been saved.'); + + $storage = $this->container->get('entity_type.manager')->getStorage('menu_link_content'); + $menu_links = $storage->loadByProperties(['title' => $title]); + $menu_link = reset($menu_links); + + // Check that the stored menu link meeting the expectations. + $this->assertNotNull($menu_link); + $this->assertMenuLink([ + 'menu_name' => $menu_id, + 'children' => [], + 'parent' => $parent + ], $menu_link->getPluginId()); + + return $menu_link; + } + +} diff -r e200cb7efeb3 -r c2387f117808 core/modules/menu_ui/tests/src/Traits/MenuUiTrait.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/core/modules/menu_ui/tests/src/Traits/MenuUiTrait.php Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,69 @@ +resetDefinitions(); + // Reset the static load cache. + \Drupal::entityTypeManager()->getStorage('menu_link_content')->resetCache(); + $definition = $menu_link_manager->getDefinition($menu_plugin_id); + + $entity = NULL; + + // Pull the path from the menu link content. + if (strpos($menu_plugin_id, 'menu_link_content') === 0) { + list(, $uuid) = explode(':', $menu_plugin_id, 2); + /** @var \Drupal\menu_link_content\Entity\MenuLinkContent $entity */ + $entity = \Drupal::service('entity.repository') + ->loadEntityByUuid('menu_link_content', $uuid); + } + + if (isset($expected_item['children'])) { + $child_ids = array_values($menu_link_manager->getChildIds($menu_plugin_id)); + sort($expected_item['children']); + if ($child_ids) { + sort($child_ids); + } + $this->assertSame($expected_item['children'], $child_ids); + unset($expected_item['children']); + } + + if (isset($expected_item['parents'])) { + $parent_ids = array_values($menu_link_manager->getParentIds($menu_plugin_id)); + $this->assertSame($expected_item['parents'], $parent_ids); + unset($expected_item['parents']); + } + + if (isset($expected_item['langcode']) && $entity) { + $this->assertEquals($expected_item['langcode'], $entity->langcode->value); + unset($expected_item['langcode']); + } + + if (isset($expected_item['enabled']) && $entity) { + $this->assertEquals($expected_item['enabled'], $entity->enabled->value); + unset($expected_item['enabled']); + } + + foreach ($expected_item as $key => $value) { + $this->assertNotNull($definition[$key]); + $this->assertSame($value, $definition[$key]); + } + } + +} diff -r e200cb7efeb3 -r c2387f117808 core/modules/migrate/src/Annotation/MigrateDestination.php --- a/core/modules/migrate/src/Annotation/MigrateDestination.php Thu Apr 26 11:26:54 2018 +0100 +++ b/core/modules/migrate/src/Annotation/MigrateDestination.php Tue Jul 10 15:07:59 2018 +0100 @@ -13,7 +13,7 @@ * \Drupal\migrate\Plugin\migrate\destination\UrlAlias * * @see \Drupal\migrate\Plugin\MigrateDestinationInterface - * @see \Drupal\migrate\Plugin\destination\DestinationBase + * @see \Drupal\migrate\Plugin\migrate\destination\DestinationBase * @see \Drupal\migrate\Plugin\MigrateDestinationPluginManager * @see \Drupal\migrate\Annotation\MigrateSource * @see \Drupal\migrate\Annotation\MigrateProcessPlugin diff -r e200cb7efeb3 -r c2387f117808 core/modules/migrate/src/MigrateExecutableInterface.php --- a/core/modules/migrate/src/MigrateExecutableInterface.php Thu Apr 26 11:26:54 2018 +0100 +++ b/core/modules/migrate/src/MigrateExecutableInterface.php Tue Jul 10 15:07:59 2018 +0100 @@ -29,7 +29,7 @@ * Usually setting this is not necessary as $process typically starts with * a 'get'. This is useful only when the $process contains a single * destination and needs to access a value outside of the source. See - * \Drupal\migrate\Plugin\migrate\process\Iterator::transformKey for an + * \Drupal\migrate\Plugin\migrate\process\SubProcess::transformKey for an * example. * * @throws \Drupal\migrate\MigrateException diff -r e200cb7efeb3 -r c2387f117808 core/modules/migrate/src/Plugin/MigrateDestinationInterface.php --- a/core/modules/migrate/src/Plugin/MigrateDestinationInterface.php Thu Apr 26 11:26:54 2018 +0100 +++ b/core/modules/migrate/src/Plugin/MigrateDestinationInterface.php Tue Jul 10 15:07:59 2018 +0100 @@ -11,7 +11,7 @@ * Destinations are responsible for persisting source data into the destination * Drupal. * - * @see \Drupal\migrate\Plugin\destination\DestinationBase + * @see \Drupal\migrate\Plugin\migrate\destination\DestinationBase * @see \Drupal\migrate\Plugin\MigrateDestinationPluginManager * @see \Drupal\migrate\Annotation\MigrateDestination * @see plugin_api diff -r e200cb7efeb3 -r c2387f117808 core/modules/migrate/src/Plugin/MigrateDestinationPluginManager.php --- a/core/modules/migrate/src/Plugin/MigrateDestinationPluginManager.php Thu Apr 26 11:26:54 2018 +0100 +++ b/core/modules/migrate/src/Plugin/MigrateDestinationPluginManager.php Tue Jul 10 15:07:59 2018 +0100 @@ -10,7 +10,7 @@ * Plugin manager for migrate destination plugins. * * @see \Drupal\migrate\Plugin\MigrateDestinationInterface - * @see \Drupal\migrate\Plugin\destination\DestinationBase + * @see \Drupal\migrate\Plugin\migrate\destination\DestinationBase * @see \Drupal\migrate\Annotation\MigrateDestination * @see plugin_api * diff -r e200cb7efeb3 -r c2387f117808 core/modules/migrate/src/Plugin/MigrateIdMapInterface.php --- a/core/modules/migrate/src/Plugin/MigrateIdMapInterface.php Thu Apr 26 11:26:54 2018 +0100 +++ b/core/modules/migrate/src/Plugin/MigrateIdMapInterface.php Tue Jul 10 15:07:59 2018 +0100 @@ -197,7 +197,7 @@ * The source identifier keyed values of the record, e.g. ['nid' => 5], or * an empty array on failure. */ - public function lookupSourceID(array $destination_id_values); + public function lookupSourceId(array $destination_id_values); /** * Looks up the destination identifier corresponding to a source key. diff -r e200cb7efeb3 -r c2387f117808 core/modules/migrate/src/Plugin/MigrateProcessInterface.php --- a/core/modules/migrate/src/Plugin/MigrateProcessInterface.php Thu Apr 26 11:26:54 2018 +0100 +++ b/core/modules/migrate/src/Plugin/MigrateProcessInterface.php Tue Jul 10 15:07:59 2018 +0100 @@ -9,11 +9,16 @@ /** * An interface for migrate process plugins. * - * A process plugin can use any number of methods instead of (but not in - * addition to) transform with the same arguments and then the plugin - * configuration needs to provide the name of the method to be called via the - * "method" key. See \Drupal\migrate\Plugin\migrate\process\SkipOnEmpty and - * migrate.migration.d6_field_instance_widget_settings.yml for examples. + * A process plugin will typically implement the transform() method to perform + * its work. However, it is possible instead for a process plugin to use any + * number of methods, thus offering different alternatives ways of processing. + * In this case, the transform() method should not be implemented, and the + * plugin configuration must provide the name of the method to be called via the + * "method" key. Each method must have the same signature as transform(). + * The base class \Drupal\migrate\ProcessPluginBase takes care of implementing + * transform() and calling the configured method. See + * \Drupal\migrate\Plugin\migrate\process\SkipOnEmpty and + * d6_field_instance_widget_settings.yml for examples. * * @see \Drupal\migrate\Plugin\MigratePluginManager * @see \Drupal\migrate\ProcessPluginBase diff -r e200cb7efeb3 -r c2387f117808 core/modules/migrate/src/Plugin/Migration.php --- a/core/modules/migrate/src/Plugin/Migration.php Thu Apr 26 11:26:54 2018 +0100 +++ b/core/modules/migrate/src/Plugin/Migration.php Tue Jul 10 15:07:59 2018 +0100 @@ -620,19 +620,22 @@ } /** - * Find migration dependencies from the migration and the iterator plugins. + * Find migration dependencies from migration_lookup and sub_process plugins. * - * @param $process + * @param array $process + * A process configuration array. + * * @return array + * The migration dependencies. */ protected function findMigrationDependencies($process) { $return = []; foreach ($this->getProcessNormalized($process) as $process_pipeline) { foreach ($process_pipeline as $plugin_configuration) { - if ($plugin_configuration['plugin'] == 'migration') { + if (in_array($plugin_configuration['plugin'], ['migration', 'migration_lookup'], TRUE)) { $return = array_merge($return, (array) $plugin_configuration['migration']); } - if ($plugin_configuration['plugin'] == 'sub_process') { + if (in_array($plugin_configuration['plugin'], ['iterator', 'sub_process'], TRUE)) { $return = array_merge($return, $this->findMigrationDependencies($plugin_configuration['process'])); } } diff -r e200cb7efeb3 -r c2387f117808 core/modules/migrate/src/Plugin/migrate/destination/DestinationBase.php --- a/core/modules/migrate/src/Plugin/migrate/destination/DestinationBase.php Thu Apr 26 11:26:54 2018 +0100 +++ b/core/modules/migrate/src/Plugin/migrate/destination/DestinationBase.php Tue Jul 10 15:07:59 2018 +0100 @@ -12,7 +12,7 @@ /** * Base class for migrate destination classes. * - * Migrate destination plugins perfom the import operation of the migration. + * Migrate destination plugins perform the import operation of the migration. * Destination plugins extend this abstract base class. A destination plugin * must implement at least fields(), getIds() and import() methods. Destination * plugins can also support rollback operations. For more diff -r e200cb7efeb3 -r c2387f117808 core/modules/migrate/src/Plugin/migrate/destination/EntityContentBase.php --- a/core/modules/migrate/src/Plugin/migrate/destination/EntityContentBase.php Thu Apr 26 11:26:54 2018 +0100 +++ b/core/modules/migrate/src/Plugin/migrate/destination/EntityContentBase.php Tue Jul 10 15:07:59 2018 +0100 @@ -148,7 +148,7 @@ } $ids = $this->save($entity, $old_destination_id_values); - if (!empty($this->configuration['translations'])) { + if ($this->isTranslationDestination()) { $ids[] = $entity->language()->getId(); } return $ids; @@ -181,12 +181,15 @@ * {@inheritdoc} */ public function getIds() { + $ids = []; + $id_key = $this->getKey('id'); $ids[$id_key] = $this->getDefinitionFromEntity($id_key); if ($this->isTranslationDestination()) { - if (!$langcode_key = $this->getKey('langcode')) { - throw new MigrateException('This entity type does not support translation.'); + $langcode_key = $this->getKey('langcode'); + if (!$langcode_key) { + throw new MigrateException(sprintf('The "%s" entity type does not support translations.', $this->storage->getEntityTypeId())); } $ids[$langcode_key] = $this->getDefinitionFromEntity($langcode_key); } @@ -202,8 +205,8 @@ * @param \Drupal\migrate\Row $row * The row object to update from. * - * @return \Drupal\Core\Entity\EntityInterface|null - * An updated entity, or NULL if it's the same as the one passed in. + * @return \Drupal\Core\Entity\EntityInterface + * An updated entity from row values. */ protected function updateEntity(EntityInterface $entity, Row $row) { $empty_destinations = $row->getEmptyDestinationProperties(); diff -r e200cb7efeb3 -r c2387f117808 core/modules/migrate/src/Plugin/migrate/destination/EntityRevision.php --- a/core/modules/migrate/src/Plugin/migrate/destination/EntityRevision.php Thu Apr 26 11:26:54 2018 +0100 +++ b/core/modules/migrate/src/Plugin/migrate/destination/EntityRevision.php Tue Jul 10 15:07:59 2018 +0100 @@ -160,7 +160,9 @@ $entity->enforceIsNew(FALSE); $entity->setNewRevision(TRUE); } - $this->updateEntity($entity, $row); + // We need to update the entity, so that the destination row IDs are + // correct. + $entity = $this->updateEntity($entity, $row); $entity->isDefaultRevision(FALSE); return $entity; } @@ -177,10 +179,23 @@ * {@inheritdoc} */ public function getIds() { - if ($key = $this->getKey('revision')) { - return [$key => $this->getDefinitionFromEntity($key)]; + $ids = []; + + $revision_key = $this->getKey('revision'); + if (!$revision_key) { + throw new MigrateException(sprintf('The "%s" entity type does not support revisions.', $this->storage->getEntityTypeId())); } - throw new MigrateException('This entity type does not support revisions.'); + $ids[$revision_key] = $this->getDefinitionFromEntity($revision_key); + + if ($this->isTranslationDestination()) { + $langcode_key = $this->getKey('langcode'); + if (!$langcode_key) { + throw new MigrateException(sprintf('The "%s" entity type does not support translations.', $this->storage->getEntityTypeId())); + } + $ids[$langcode_key] = $this->getDefinitionFromEntity($langcode_key); + } + + return $ids; } /** diff -r e200cb7efeb3 -r c2387f117808 core/modules/migrate/src/Plugin/migrate/id_map/NullIdMap.php --- a/core/modules/migrate/src/Plugin/migrate/id_map/NullIdMap.php Thu Apr 26 11:26:54 2018 +0100 +++ b/core/modules/migrate/src/Plugin/migrate/id_map/NullIdMap.php Tue Jul 10 15:07:59 2018 +0100 @@ -48,7 +48,7 @@ /** * {@inheritdoc} */ - public function lookupSourceID(array $destination_id_values) { + public function lookupSourceId(array $destination_id_values) { return []; } diff -r e200cb7efeb3 -r c2387f117808 core/modules/migrate/src/Plugin/migrate/id_map/Sql.php --- a/core/modules/migrate/src/Plugin/migrate/id_map/Sql.php Thu Apr 26 11:26:54 2018 +0100 +++ b/core/modules/migrate/src/Plugin/migrate/id_map/Sql.php Tue Jul 10 15:07:59 2018 +0100 @@ -187,7 +187,7 @@ * @return string * An hash containing the hashed values of the source identifiers. */ - public function getSourceIDsHash(array $source_id_values) { + public function getSourceIdsHash(array $source_id_values) { // When looking up the destination ID we require an array with both the // source key and value, e.g. ['nid' => 41]. In this case, $source_id_values // need to be ordered the same order as $this->sourceIdFields(). @@ -491,7 +491,7 @@ public function getRowBySource(array $source_id_values) { $query = $this->getDatabase()->select($this->mapTableName(), 'map') ->fields('map'); - $query->condition(static::SOURCE_IDS_HASH, $this->getSourceIDsHash($source_id_values)); + $query->condition(static::SOURCE_IDS_HASH, $this->getSourceIdsHash($source_id_values)); $result = $query->execute(); return $result->fetchAssoc(); } @@ -528,7 +528,7 @@ /** * {@inheritdoc} */ - public function lookupSourceID(array $destination_id_values) { + public function lookupSourceId(array $destination_id_values) { $source_id_fields = $this->sourceIdFields(); $query = $this->getDatabase()->select($this->mapTableName(), 'map'); foreach ($source_id_fields as $source_field_name => $idmap_field_name) { @@ -562,9 +562,13 @@ $conditions = []; foreach ($this->sourceIdFields() as $field_name => $db_field) { if ($is_associative) { - // Associative $source_id_values can have fields out of order. - if (isset($source_id_values[$field_name])) { - $conditions[$db_field] = $source_id_values[$field_name]; + // Ensure to handle array elements with a NULL value. + if (array_key_exists($field_name, $source_id_values)) { + // Associative $source_id_values can have fields out of order. + if (isset($source_id_values[$field_name])) { + // Only add a condition if the value is not NULL. + $conditions[$db_field] = $source_id_values[$field_name]; + } unset($source_id_values[$field_name]); } } @@ -579,14 +583,15 @@ } if (!empty($source_id_values)) { - throw new MigrateException("Extra unknown items in source IDs"); + $var_dump = var_export($source_id_values, TRUE); + throw new MigrateException(sprintf("Extra unknown items in source IDs: %s", $var_dump)); } $query = $this->getDatabase()->select($this->mapTableName(), 'map') ->fields('map', $this->destinationIdFields()); if (count($this->sourceIdFields()) === count($conditions)) { // Optimization: Use the primary key. - $query->condition(self::SOURCE_IDS_HASH, $this->getSourceIDsHash(array_values($conditions))); + $query->condition(self::SOURCE_IDS_HASH, $this->getSourceIdsHash(array_values($conditions))); } else { foreach ($conditions as $db_field => $value) { @@ -636,7 +641,7 @@ if ($this->migration->getTrackLastImported()) { $fields['last_imported'] = time(); } - $keys = [static::SOURCE_IDS_HASH => $this->getSourceIDsHash($source_id_values)]; + $keys = [static::SOURCE_IDS_HASH => $this->getSourceIdsHash($source_id_values)]; // Notify anyone listening of the map row we're about to save. $this->eventDispatcher->dispatch(MigrateEvents::MAP_SAVE, new MigrateMapSaveEvent($this, $fields)); $this->getDatabase()->merge($this->mapTableName()) @@ -655,7 +660,7 @@ return; } } - $fields[static::SOURCE_IDS_HASH] = $this->getSourceIDsHash($source_id_values); + $fields[static::SOURCE_IDS_HASH] = $this->getSourceIdsHash($source_id_values); $fields['level'] = $level; $fields['message'] = $message; $this->getDatabase()->insert($this->messageTableName()) @@ -674,7 +679,7 @@ $query = $this->getDatabase()->select($this->messageTableName(), 'msg') ->fields('msg'); if ($source_id_values) { - $query->condition(static::SOURCE_IDS_HASH, $this->getSourceIDsHash($source_id_values)); + $query->condition(static::SOURCE_IDS_HASH, $this->getSourceIdsHash($source_id_values)); } if ($level) { @@ -763,13 +768,13 @@ if (!$messages_only) { $map_query = $this->getDatabase()->delete($this->mapTableName()); - $map_query->condition(static::SOURCE_IDS_HASH, $this->getSourceIDsHash($source_id_values)); + $map_query->condition(static::SOURCE_IDS_HASH, $this->getSourceIdsHash($source_id_values)); // Notify anyone listening of the map row we're about to delete. $this->eventDispatcher->dispatch(MigrateEvents::MAP_DELETE, new MigrateMapDeleteEvent($this, $source_id_values)); $map_query->execute(); } $message_query = $this->getDatabase()->delete($this->messageTableName()); - $message_query->condition(static::SOURCE_IDS_HASH, $this->getSourceIDsHash($source_id_values)); + $message_query->condition(static::SOURCE_IDS_HASH, $this->getSourceIdsHash($source_id_values)); $message_query->execute(); } @@ -779,7 +784,7 @@ public function deleteDestination(array $destination_id_values) { $map_query = $this->getDatabase()->delete($this->mapTableName()); $message_query = $this->getDatabase()->delete($this->messageTableName()); - $source_id_values = $this->lookupSourceID($destination_id_values); + $source_id_values = $this->lookupSourceId($destination_id_values); if (!empty($source_id_values)) { foreach ($this->destinationIdFields() as $field_name => $destination_id) { $map_query->condition($destination_id, $destination_id_values[$field_name]); @@ -788,7 +793,7 @@ $this->eventDispatcher->dispatch(MigrateEvents::MAP_DELETE, new MigrateMapDeleteEvent($this, $source_id_values)); $map_query->execute(); - $message_query->condition(static::SOURCE_IDS_HASH, $this->getSourceIDsHash($source_id_values)); + $message_query->condition(static::SOURCE_IDS_HASH, $this->getSourceIdsHash($source_id_values)); $message_query->execute(); } } diff -r e200cb7efeb3 -r c2387f117808 core/modules/migrate/src/Plugin/migrate/process/MakeUniqueEntityField.php --- a/core/modules/migrate/src/Plugin/migrate/process/MakeUniqueEntityField.php Thu Apr 26 11:26:54 2018 +0100 +++ b/core/modules/migrate/src/Plugin/migrate/process/MakeUniqueEntityField.php Tue Jul 10 15:07:59 2018 +0100 @@ -134,7 +134,7 @@ $idMap = $this->migration->getIdMap(); foreach ($query->execute() as $id) { $dest_id_values[$this->configuration['field']] = $id; - if ($idMap->lookupSourceID($dest_id_values)) { + if ($idMap->lookupSourceId($dest_id_values)) { return TRUE; } } diff -r e200cb7efeb3 -r c2387f117808 core/modules/migrate/src/Plugin/migrate/process/StaticMap.php --- a/core/modules/migrate/src/Plugin/migrate/process/StaticMap.php Thu Apr 26 11:26:54 2018 +0100 +++ b/core/modules/migrate/src/Plugin/migrate/process/StaticMap.php Tue Jul 10 15:07:59 2018 +0100 @@ -3,6 +3,7 @@ namespace Drupal\migrate\Plugin\migrate\process; use Drupal\Component\Utility\NestedArray; +use Drupal\Component\Utility\Variable; use Drupal\migrate\ProcessPluginBase; use Drupal\migrate\MigrateException; use Drupal\migrate\MigrateExecutableInterface; @@ -140,7 +141,7 @@ return $this->configuration['default_value']; } if (empty($this->configuration['bypass'])) { - throw new MigrateSkipRowException(); + throw new MigrateSkipRowException(sprintf("No static mapping found for '%s' and no default value provided for destination '%s'.", Variable::export($value), $destination_property)); } else { return $value; diff -r e200cb7efeb3 -r c2387f117808 core/modules/migrate/src/Plugin/migrate/source/EmptySource.php --- a/core/modules/migrate/src/Plugin/migrate/source/EmptySource.php Thu Apr 26 11:26:54 2018 +0100 +++ b/core/modules/migrate/src/Plugin/migrate/source/EmptySource.php Tue Jul 10 15:07:59 2018 +0100 @@ -19,7 +19,8 @@ * elements, with values of 'user' and 'image', respectively. * * @MigrateSource( - * id = "empty" + * id = "empty", + * source_module = "migrate" * ) */ class EmptySource extends SourcePluginBase { diff -r e200cb7efeb3 -r c2387f117808 core/modules/migrate/src/Plugin/migrate/source/SqlBase.php --- a/core/modules/migrate/src/Plugin/migrate/source/SqlBase.php Thu Apr 26 11:26:54 2018 +0100 +++ b/core/modules/migrate/src/Plugin/migrate/source/SqlBase.php Tue Jul 10 15:07:59 2018 +0100 @@ -24,8 +24,11 @@ * - target: (optional) The database target name. Defaults to 'default'. * - batch_size: (optional) Number of records to fetch from the database during * each batch. If omitted, all records are fetched in a single query. - * - ignore_map: (optional) Source data is joined to the map table by default. - * If set to TRUE, the map table will not be joined. + * - ignore_map: (optional) Source data is joined to the map table by default to + * improve migration performance. If set to TRUE, the map table will not be + * joined. Using expressions in the query may result in column aliases in the + * JOIN clause which would be invalid SQL. If you run into this, set + * ignore_map to TRUE. * * For other optional configuration keys inherited from the parent class, refer * to \Drupal\migrate\Plugin\migrate\source\SourcePluginBase. diff -r e200cb7efeb3 -r c2387f117808 core/modules/migrate/tests/src/Kernel/Plugin/EntityRevisionTest.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/core/modules/migrate/tests/src/Kernel/Plugin/EntityRevisionTest.php Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,131 @@ +installConfig('node'); + $this->installSchema('node', ['node_access']); + $this->installEntitySchema('node'); + $this->installEntitySchema('user'); + } + + /** + * Tests that EntityRevision correctly handles revision translations. + */ + public function testRevisionTranslation() { + ConfigurableLanguage::createFromLangcode('fr')->save(); + + /** @var \Drupal\node\NodeInterface $node */ + $node = Node::create([ + 'type' => $this->createContentType()->id(), + 'title' => 'Default 1', + ]); + $node->addTranslation('fr', [ + 'title' => 'French 1', + ]); + $node->save(); + $node->setNewRevision(); + $node->setTitle('Default 2'); + $node->getTranslation('fr')->setTitle('French 2'); + $node->save(); + + $migration = [ + 'source' => [ + 'plugin' => 'embedded_data', + 'data_rows' => [ + [ + 'nid' => $node->id(), + 'vid' => $node->getRevisionId(), + 'langcode' => 'fr', + 'title' => 'Titre nouveau, tabarnak!', + ], + ], + 'ids' => [ + 'nid' => [ + 'type' => 'integer', + ], + 'vid' => [ + 'type' => 'integer', + ], + 'langcode' => [ + 'type' => 'string', + ], + ], + ], + 'process' => [ + 'nid' => 'nid', + 'vid' => 'vid', + 'langcode' => 'langcode', + 'title' => 'title', + ], + 'destination' => [ + 'plugin' => 'entity_revision:node', + 'translations' => TRUE, + ], + ]; + + /** @var \Drupal\migrate\Plugin\MigrationInterface $migration */ + $migration = $this->container + ->get('plugin.manager.migration') + ->createStubMigration($migration); + + $this->executeMigration($migration); + + // The entity_revision destination uses the revision ID and langcode as its + // keys (the langcode is only used if the destination is configured for + // translation), so we should be able to look up the source IDs by revision + // ID and langcode. + $source_ids = $migration->getIdMap()->lookupSourceID([ + 'vid' => $node->getRevisionId(), + 'langcode' => 'fr', + ]); + $this->assertNotEmpty($source_ids); + $this->assertSame($node->id(), $source_ids['nid']); + $this->assertSame($node->getRevisionId(), $source_ids['vid']); + $this->assertSame('fr', $source_ids['langcode']); + + // Confirm the french revision was used in the migration, instead of the + // default revision. + /** @var \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager */ + $entity_type_manager = \Drupal::entityTypeManager(); + $revision = $entity_type_manager->getStorage('node')->loadRevision(1); + $this->assertSame('Default 1', $revision->label()); + $this->assertSame('French 1', $revision->getTranslation('fr')->label()); + $revision = $entity_type_manager->getStorage('node')->loadRevision(2); + $this->assertSame('Default 2', $revision->label()); + $this->assertSame('Titre nouveau, tabarnak!', $revision->getTranslation('fr')->label()); + } + +} diff -r e200cb7efeb3 -r c2387f117808 core/modules/migrate/tests/src/Kernel/Plugin/MigrationPluginListTest.php --- a/core/modules/migrate/tests/src/Kernel/Plugin/MigrationPluginListTest.php Thu Apr 26 11:26:54 2018 +0100 +++ b/core/modules/migrate/tests/src/Kernel/Plugin/MigrationPluginListTest.php Tue Jul 10 15:07:59 2018 +0100 @@ -41,6 +41,7 @@ 'menu_link_content', 'menu_ui', 'node', + 'options', 'path', 'search', 'shortcut', diff -r e200cb7efeb3 -r c2387f117808 core/modules/migrate/tests/src/Kernel/Plugin/MigrationProvidersExistTest.php --- a/core/modules/migrate/tests/src/Kernel/Plugin/MigrationProvidersExistTest.php Thu Apr 26 11:26:54 2018 +0100 +++ b/core/modules/migrate/tests/src/Kernel/Plugin/MigrationProvidersExistTest.php Tue Jul 10 15:07:59 2018 +0100 @@ -31,16 +31,12 @@ public function testProvidersExist() { $this->enableAllModules(); - /** @var \Drupal\migrate\Plugin\MigrationPluginManager $plugin_manager */ - $plugin_manager = $this->container->get('plugin.manager.migration'); + /** @var \Drupal\migrate\Plugin\MigrateSourcePluginManager $plugin_manager */ + $plugin_manager = $this->container->get('plugin.manager.migrate.source'); - // Instantiate all migrations. - $migrations = array_keys($plugin_manager->getDefinitions()); - $migrations = $plugin_manager->createInstances($migrations); - - /** @var \Drupal\migrate\Plugin\MigrationInterface $migration */ - foreach ($migrations as $migration) { - $this->assertInternalType('string', $migration->getSourcePlugin()->getSourceModule()); + foreach ($plugin_manager->getDefinitions() as $definition) { + $id = $definition['id']; + $this->assertArrayHasKey('source_module', $definition, "No source_module property in '$id'"); } } diff -r e200cb7efeb3 -r c2387f117808 core/modules/migrate/tests/src/Kernel/Plugin/MigrationTest.php --- a/core/modules/migrate/tests/src/Kernel/Plugin/MigrationTest.php Thu Apr 26 11:26:54 2018 +0100 +++ b/core/modules/migrate/tests/src/Kernel/Plugin/MigrationTest.php Tue Jul 10 15:07:59 2018 +0100 @@ -50,10 +50,32 @@ ], ], ], + 'f4' => [ + 'plugin' => 'migration_lookup', + 'migration' => 'm3' + ], + 'f5' => [ + 'plugin' => 'sub_process', + 'process' => [ + 'target_id' => [ + 'plugin' => 'migration_lookup', + 'migration' => 'm4', + ], + ], + ], + 'f6' => [ + 'plugin' => 'iterator', + 'process' => [ + 'target_id' => [ + 'plugin' => 'migration_lookup', + 'migration' => 'm5', + ], + ], + ], ], ]; $migration = $plugin_manager->createStubMigration($plugin_definition); - $this->assertSame(['required' => [], 'optional' => ['m1', 'm2']], $migration->getMigrationDependencies()); + $this->assertSame(['required' => [], 'optional' => ['m1', 'm2', 'm3', 'm4', 'm5']], $migration->getMigrationDependencies()); } /** diff -r e200cb7efeb3 -r c2387f117808 core/modules/migrate/tests/src/Unit/MigrateSqlIdMapTest.php --- a/core/modules/migrate/tests/src/Unit/MigrateSqlIdMapTest.php Thu Apr 26 11:26:54 2018 +0100 +++ b/core/modules/migrate/tests/src/Unit/MigrateSqlIdMapTest.php Tue Jul 10 15:07:59 2018 +0100 @@ -166,7 +166,7 @@ $expected_result = [ [ 'sourceid1' => 'source_value', - 'source_ids_hash' => $this->getIdMap()->getSourceIDsHash($source), + 'source_ids_hash' => $this->getIdMap()->getSourceIdsHash($source), 'destid1' => 2, ] + $this->idMapDefaults(), ]; @@ -178,7 +178,7 @@ $id_map->saveIdMapping($row, ['destination_id_property' => 3]); $expected_result[] = [ 'sourceid1' => 'source_value_1', - 'source_ids_hash' => $this->getIdMap()->getSourceIDsHash($source), + 'source_ids_hash' => $this->getIdMap()->getSourceIdsHash($source), 'destid1' => 3, ] + $this->idMapDefaults(); $this->queryResultTest($this->getIdMapContents(), $expected_result); @@ -236,7 +236,7 @@ $id_map->saveIdMapping($row, $destination, $status); $expected_results[] = [ 'sourceid1' => 'source_value_' . $status, - 'source_ids_hash' => $this->getIdMap()->getSourceIDsHash($source), + 'source_ids_hash' => $this->getIdMap()->getSourceIdsHash($source), 'destid1' => 'destination_value_' . $status, 'source_row_status' => $status, 'rollback_action' => MigrateIdMapInterface::ROLLBACK_DELETE, @@ -348,14 +348,14 @@ $row = [ 'sourceid1' => 'source_id_value_1', 'sourceid2' => 'source_id_value_2', - 'source_ids_hash' => $this->getIdMap()->getSourceIDsHash(['source_id_property' => 'source_id_value_1']), + 'source_ids_hash' => $this->getIdMap()->getSourceIdsHash(['source_id_property' => 'source_id_value_1']), 'destid1' => 'destination_id_value_1', ] + $this->idMapDefaults(); $this->saveMap($row); $row = [ 'sourceid1' => 'source_id_value_3', 'sourceid2' => 'source_id_value_4', - 'source_ids_hash' => $this->getIdMap()->getSourceIDsHash(['source_id_property' => 'source_id_value_3', 'sourceid2' => 'source_id_value_4']), + 'source_ids_hash' => $this->getIdMap()->getSourceIdsHash(['source_id_property' => 'source_id_value_3', 'sourceid2' => 'source_id_value_4']), 'destid1' => 'destination_id_value_2', ] + $this->idMapDefaults(); $this->saveMap($row); @@ -419,7 +419,7 @@ $expected_result[] = "destination_id_value_$i"; $this->destinationIds["destination_id_property_$i"] = []; } - $row['source_ids_hash'] = $this->getIdMap()->getSourceIDsHash($source_id_values); + $row['source_ids_hash'] = $this->getIdMap()->getSourceIdsHash($source_id_values); $this->saveMap($row); $id_map = $this->getIdMap(); // Test for a valid hit. @@ -458,7 +458,7 @@ foreach ($rows as $row) { $values = array_combine($db_keys, $row); $source_values = array_slice($row, 0, count($source_keys)); - $values['source_ids_hash'] = $this->getIdMap()->getSourceIDsHash($source_values); + $values['source_ids_hash'] = $this->getIdMap()->getSourceIdsHash($source_values); $this->saveMap($values); } @@ -517,6 +517,8 @@ $this->assertEquals([[101, 'en'], [101, 'fr'], [101, 'de']], $id_map->lookupDestinationIds(['nid' => 1])); $this->assertEquals([[102, 'en']], $id_map->lookupDestinationIds(['nid' => 2])); $this->assertEquals([], $id_map->lookupDestinationIds(['nid' => 99])); + $this->assertEquals([[101, 'en'], [101, 'fr'], [101, 'de']], $id_map->lookupDestinationIds(['nid' => 1, 'language' => NULL])); + $this->assertEquals([[102, 'en']], $id_map->lookupDestinationIds(['nid' => 2, 'language' => NULL])); // Out-of-order partial associative list. $this->assertEquals([[101, 'en'], [102, 'en']], $id_map->lookupDestinationIds(['language' => 'en'])); $this->assertEquals([[101, 'fr']], $id_map->lookupDestinationIds(['language' => 'fr'])); @@ -527,14 +529,14 @@ $this->fail('Too many source IDs should throw'); } catch (MigrateException $e) { - $this->assertEquals("Extra unknown items in source IDs", $e->getMessage()); + $this->assertEquals("Extra unknown items in source IDs: array (\n 0 => 3,\n)", $e->getMessage()); } try { $id_map->lookupDestinationIds(['nid' => 1, 'aaa' => '2']); $this->fail('Unknown source ID key should throw'); } catch (MigrateException $e) { - $this->assertEquals("Extra unknown items in source IDs", $e->getMessage()); + $this->assertEquals("Extra unknown items in source IDs: array (\n 'aaa' => '2',\n)", $e->getMessage()); } // Verify that we are looking up by source_id_hash when all source IDs are @@ -554,14 +556,14 @@ $row = [ 'sourceid1' => 'source_id_value_1', 'sourceid2' => 'source_id_value_2', - 'source_ids_hash' => $this->getIdMap()->getSourceIDsHash(['source_id_property' => 'source_id_value_1']), + 'source_ids_hash' => $this->getIdMap()->getSourceIdsHash(['source_id_property' => 'source_id_value_1']), 'destid1' => 'destination_id_value_1', ] + $this->idMapDefaults(); $this->saveMap($row); $row = [ 'sourceid1' => 'source_id_value_3', 'sourceid2' => 'source_id_value_4', - 'source_ids_hash' => $this->getIdMap()->getSourceIDsHash(['source_id_property' => 'source_id_value_3']), + 'source_ids_hash' => $this->getIdMap()->getSourceIdsHash(['source_id_property' => 'source_id_value_3']), 'destid1' => 'destination_id_value_2', ] + $this->idMapDefaults(); $this->saveMap($row); @@ -577,7 +579,7 @@ } /** - * Data provider for testLookupSourceIDMapping(). + * Data provider for testLookupSourceIdMapping(). * * Scenarios to test (for both hits and misses) are: * - Single-value destination ID to single-value source ID. @@ -588,7 +590,7 @@ * @return array * An array of data values. */ - public function lookupSourceIDMappingDataProvider() { + public function lookupSourceIdMappingDataProvider() { return [ [1, 1], [2, 2], @@ -605,9 +607,9 @@ * @param int $num_destination_fields * Number of destination fields to test. * - * @dataProvider lookupSourceIDMappingDataProvider + * @dataProvider lookupSourceIdMappingDataProvider */ - public function testLookupSourceIDMapping($num_source_fields, $num_destination_fields) { + public function testLookupSourceIdMapping($num_source_fields, $num_destination_fields) { // Adjust the migration configuration according to the number of source and // destination fields. $this->sourceIds = []; @@ -629,14 +631,14 @@ $nonexistent_id_values["destination_id_property_$i"] = "nonexistent_destination_id_value_$i"; $this->destinationIds["destination_id_property_$i"] = []; } - $row['source_ids_hash'] = $this->getIdMap()->getSourceIDsHash($source_ids_values); + $row['source_ids_hash'] = $this->getIdMap()->getSourceIdsHash($source_ids_values); $this->saveMap($row); $id_map = $this->getIdMap(); // Test for a valid hit. - $source_id = $id_map->lookupSourceID($destination_id_values); + $source_id = $id_map->lookupSourceId($destination_id_values); $this->assertSame($expected_result, $source_id); // Test for a miss. - $source_id = $id_map->lookupSourceID($nonexistent_id_values); + $source_id = $id_map->lookupSourceId($nonexistent_id_values); $this->assertSame(0, count($source_id)); } @@ -765,7 +767,7 @@ for ($i = 0; $i < 5; $i++) { $row = $this->idMapDefaults(); $row['sourceid1'] = "source_id_value_$i"; - $row['source_ids_hash'] = $this->getIdMap()->getSourceIDsHash(['source_id_property' => $row['sourceid1']]); + $row['source_ids_hash'] = $this->getIdMap()->getSourceIdsHash(['source_id_property' => $row['sourceid1']]); $row['destid1'] = "destination_id_value_$i"; $row['source_row_status'] = MigrateIdMapInterface::STATUS_IMPORTED; $this->saveMap($row); @@ -773,7 +775,7 @@ for (; $i < 5 + $num_update_rows; $i++) { $row = $this->idMapDefaults(); $row['sourceid1'] = "source_id_value_$i"; - $row['source_ids_hash'] = $this->getIdMap()->getSourceIDsHash(['source_id_property' => $row['sourceid1']]); + $row['source_ids_hash'] = $this->getIdMap()->getSourceIdsHash(['source_id_property' => $row['sourceid1']]); $row['destid1'] = "destination_id_value_$i"; $row['source_row_status'] = MigrateIdMapInterface::STATUS_NEEDS_UPDATE; $this->saveMap($row); @@ -813,7 +815,7 @@ for ($i = 0; $i < 5; $i++) { $row = $this->idMapDefaults(); $row['sourceid1'] = "source_id_value_$i"; - $row['source_ids_hash'] = $this->getIdMap()->getSourceIDsHash(['source_id_property' => $row['sourceid1']]); + $row['source_ids_hash'] = $this->getIdMap()->getSourceIdsHash(['source_id_property' => $row['sourceid1']]); $row['destid1'] = "destination_id_value_$i"; $row['source_row_status'] = MigrateIdMapInterface::STATUS_IMPORTED; $this->saveMap($row); @@ -821,7 +823,7 @@ for (; $i < 5 + $num_error_rows; $i++) { $row = $this->idMapDefaults(); $row['sourceid1'] = "source_id_value_$i"; - $row['source_ids_hash'] = $this->getIdMap()->getSourceIDsHash(['source_id_property' => $row['sourceid1']]); + $row['source_ids_hash'] = $this->getIdMap()->getSourceIdsHash(['source_id_property' => $row['sourceid1']]); $row['destid1'] = "destination_id_value_$i"; $row['source_row_status'] = MigrateIdMapInterface::STATUS_FAILED; $this->saveMap($row); @@ -849,7 +851,7 @@ $id_map->saveIdMapping($row, $destination, $status); $expected_results[] = [ 'sourceid1' => 'source_value_' . $status, - 'source_ids_hash' => $this->getIdMap()->getSourceIDsHash($source), + 'source_ids_hash' => $this->getIdMap()->getSourceIdsHash($source), 'destid1' => 'destination_value_' . $status, 'source_row_status' => $status, 'rollback_action' => MigrateIdMapInterface::ROLLBACK_DELETE, @@ -978,7 +980,7 @@ for ($i = 0; $i < 3; $i++) { $row = $this->idMapDefaults(); $row['sourceid1'] = "source_id_value_$i"; - $row['source_ids_hash'] = $this->getIdMap()->getSourceIDsHash(['source_id_property' => $row['sourceid1']]); + $row['source_ids_hash'] = $this->getIdMap()->getSourceIdsHash(['source_id_property' => $row['sourceid1']]); $row['destid1'] = "destination_id_value_$i"; $row['source_row_status'] = MigrateIdMapInterface::STATUS_IMPORTED; $expected_results[serialize(['sourceid1' => $row['sourceid1']])] = ['destid1' => $row['destid1']]; diff -r e200cb7efeb3 -r c2387f117808 core/modules/migrate/tests/src/Unit/Plugin/migrate/destination/EntityContentBaseTest.php --- a/core/modules/migrate/tests/src/Unit/Plugin/migrate/destination/EntityContentBaseTest.php Thu Apr 26 11:26:54 2018 +0100 +++ b/core/modules/migrate/tests/src/Unit/Plugin/migrate/destination/EntityContentBaseTest.php Tue Jul 10 15:07:59 2018 +0100 @@ -60,6 +60,7 @@ $this->entityType = $this->prophesize(EntityTypeInterface::class); $this->entityType->getPluralLabel()->willReturn('wonkiness'); $this->storage->getEntityType()->willReturn($this->entityType->reveal()); + $this->storage->getEntityTypeId()->willReturn('foo'); $this->entityManager = $this->prophesize(EntityManagerInterface::class); } @@ -129,7 +130,7 @@ $this->entityManager->reveal(), $this->prophesize(FieldTypePluginManagerInterface::class)->reveal() ); - $this->setExpectedException(MigrateException::class, 'This entity type does not support translation'); + $this->setExpectedException(MigrateException::class, 'The "foo" entity type does not support translations.'); $destination->getIds(); } diff -r e200cb7efeb3 -r c2387f117808 core/modules/migrate/tests/src/Unit/Plugin/migrate/destination/EntityRevisionTest.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/core/modules/migrate/tests/src/Unit/Plugin/migrate/destination/EntityRevisionTest.php Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,162 @@ +migration = $this->prophesize(MigrationInterface::class); + $this->storage = $this->prophesize(EntityStorageInterface::class); + + $this->entityType = $this->prophesize(EntityTypeInterface::class); + $this->entityType->getSingularLabel()->willReturn('foo'); + $this->entityType->getPluralLabel()->willReturn('bar'); + $this->storage->getEntityType()->willReturn($this->entityType->reveal()); + $this->storage->getEntityTypeId()->willReturn('foo'); + + $this->entityManager = $this->prophesize(EntityManagerInterface::class); + } + + /** + * Tests that revision destination fails for unrevisionable entities. + */ + public function testUnrevisionable() { + $this->entityType->getKey('id')->willReturn('id'); + $this->entityType->getKey('revision')->willReturn(''); + $this->entityManager->getBaseFieldDefinitions('foo') + ->willReturn([ + 'id' => BaseFieldDefinitionTest::create('integer'), + ]); + + $destination = new EntityRevisionTestDestination( + [], + '', + [], + $this->migration->reveal(), + $this->storage->reveal(), + [], + $this->entityManager->reveal(), + $this->prophesize(FieldTypePluginManagerInterface::class)->reveal() + ); + $this->setExpectedException(MigrateException::class, 'The "foo" entity type does not support revisions.'); + $destination->getIds(); + } + + /** + * Tests that translation destination fails for untranslatable entities. + */ + public function testUntranslatable() { + $this->entityType->getKey('id')->willReturn('id'); + $this->entityType->getKey('revision')->willReturn('vid'); + $this->entityType->getKey('langcode')->willReturn(''); + $this->entityManager->getBaseFieldDefinitions('foo') + ->willReturn([ + 'id' => BaseFieldDefinitionTest::create('integer'), + 'vid' => BaseFieldDefinitionTest::create('integer'), + ]); + + $destination = new EntityRevisionTestDestination( + ['translations' => TRUE], + '', + [], + $this->migration->reveal(), + $this->storage->reveal(), + [], + $this->entityManager->reveal(), + $this->prophesize(FieldTypePluginManagerInterface::class)->reveal() + ); + $this->setExpectedException(MigrateException::class, 'The "foo" entity type does not support translations.'); + $destination->getIds(); + } + +} + +/** + * Stub class for testing EntityRevision methods. + */ +class EntityRevisionTestDestination extends EntityRevision { + + private $entity = NULL; + + public function setEntity($entity) { + $this->entity = $entity; + } + + protected function getEntity(Row $row, array $old_destination_id_values) { + return $this->entity; + } + + public static function getEntityTypeId($plugin_id) { + return 'foo'; + } + +} + +/** + * Stub class for BaseFieldDefinition. + */ +class BaseFieldDefinitionTest extends BaseFieldDefinition { + + public static function create($type) { + return new static([]); + } + + public function getSettings() { + return []; + } + + public function getType() { + return 'integer'; + } + +} diff -r e200cb7efeb3 -r c2387f117808 core/modules/migrate/tests/src/Unit/destination/EntityRevisionTest.php --- a/core/modules/migrate/tests/src/Unit/destination/EntityRevisionTest.php Thu Apr 26 11:26:54 2018 +0100 +++ b/core/modules/migrate/tests/src/Unit/destination/EntityRevisionTest.php Tue Jul 10 15:07:59 2018 +0100 @@ -230,6 +230,8 @@ * workings of its implementation which would trickle into mock assertions. An * empty implementation avoids this. */ - protected function updateEntity(EntityInterface $entity, Row $row) {} + protected function updateEntity(EntityInterface $entity, Row $row) { + return $entity; + } } diff -r e200cb7efeb3 -r c2387f117808 core/modules/migrate/tests/src/Unit/process/DedupeEntityTest.php --- a/core/modules/migrate/tests/src/Unit/process/DedupeEntityTest.php Thu Apr 26 11:26:54 2018 +0100 +++ b/core/modules/migrate/tests/src/Unit/process/DedupeEntityTest.php Tue Jul 10 15:07:59 2018 +0100 @@ -198,7 +198,7 @@ // Entity 'forums' is pre-existing, entity 'test_vocab' was migrated. $this->idMap - ->method('lookupSourceID') + ->method('lookupSourceId') ->will($this->returnValueMap([ [['test_field' => 'forums'], FALSE], [['test_field' => 'test_vocab'], ['source_id' => 42]], diff -r e200cb7efeb3 -r c2387f117808 core/modules/migrate/tests/src/Unit/process/IteratorTest.php --- a/core/modules/migrate/tests/src/Unit/process/IteratorTest.php Thu Apr 26 11:26:54 2018 +0100 +++ b/core/modules/migrate/tests/src/Unit/process/IteratorTest.php Tue Jul 10 15:07:59 2018 +0100 @@ -18,7 +18,7 @@ /** * The iterator plugin being tested. * - * @var \Drupal\migrate\Plugin\migrate\process\TestIterator + * @var \Drupal\migrate\Plugin\migrate\process\Iterator */ protected $plugin; @@ -33,6 +33,7 @@ * Tests the iterator process plugin. * * @group legacy + * @expectedDeprecation The Drupal\migrate\Plugin\migrate\process\Iterator is deprecated in Drupal 8.4.x and will be removed before Drupal 9.0.0. Instead, use Drupal\migrate\Plugin\migrate\process\SubProcess */ public function testIterator() { $migration = $this->getMigration(); diff -r e200cb7efeb3 -r c2387f117808 core/modules/migrate/tests/src/Unit/process/MakeUniqueEntityFieldTest.php --- a/core/modules/migrate/tests/src/Unit/process/MakeUniqueEntityFieldTest.php Thu Apr 26 11:26:54 2018 +0100 +++ b/core/modules/migrate/tests/src/Unit/process/MakeUniqueEntityFieldTest.php Tue Jul 10 15:07:59 2018 +0100 @@ -197,7 +197,7 @@ // Entity 'forums' is pre-existing, entity 'test_vocab' was migrated. $this->idMap - ->method('lookupSourceID') + ->method('lookupSourceId') ->will($this->returnValueMap([ [['test_field' => 'forums'], FALSE], [['test_field' => 'test_vocab'], ['source_id' => 42]], diff -r e200cb7efeb3 -r c2387f117808 core/modules/migrate/tests/src/Unit/process/StaticMapTest.php --- a/core/modules/migrate/tests/src/Unit/process/StaticMapTest.php Thu Apr 26 11:26:54 2018 +0100 +++ b/core/modules/migrate/tests/src/Unit/process/StaticMapTest.php Tue Jul 10 15:07:59 2018 +0100 @@ -2,6 +2,7 @@ namespace Drupal\Tests\migrate\Unit\process; +use Drupal\Component\Utility\Variable; use Drupal\migrate\MigrateException; use Drupal\migrate\MigrateSkipRowException; use Drupal\migrate\Plugin\migrate\process\StaticMap; @@ -50,7 +51,7 @@ * Tests when the source is invalid. */ public function testMapwithInvalidSource() { - $this->setExpectedException(MigrateSkipRowException::class); + $this->setExpectedException(MigrateSkipRowException::class, sprintf("No static mapping found for '%s' and no default value provided for destination '%s'.", Variable::export(['bar']), 'destinationproperty')); $this->plugin->transform(['bar'], $this->migrateExecutable, $this->row, 'destinationproperty'); } diff -r e200cb7efeb3 -r c2387f117808 core/modules/migrate_drupal/config/install/migrate_drupal.settings.yml --- a/core/modules/migrate_drupal/config/install/migrate_drupal.settings.yml Thu Apr 26 11:26:54 2018 +0100 +++ b/core/modules/migrate_drupal/config/install/migrate_drupal.settings.yml Tue Jul 10 15:07:59 2018 +0100 @@ -3,3 +3,8 @@ enforce_source_module_tags: - Drupal 6 - Drupal 7 +# Migrations with any of these tags will not be derived and executed with the +# other migrations. They will be derived and executed after the migrations on +# which they depend have been successfully executed. +follow_up_migration_tags: + - Follow-up migration diff -r e200cb7efeb3 -r c2387f117808 core/modules/migrate_drupal/config/schema/migrate_drupal.schema.yml --- a/core/modules/migrate_drupal/config/schema/migrate_drupal.schema.yml Thu Apr 26 11:26:54 2018 +0100 +++ b/core/modules/migrate_drupal/config/schema/migrate_drupal.schema.yml Tue Jul 10 15:07:59 2018 +0100 @@ -8,3 +8,9 @@ sequence: type: string label: 'Tag' + follow_up_migration_tags: + type: sequence + label: 'Follow-up migration tags' + sequence: + type: string + label: 'Tag' diff -r e200cb7efeb3 -r c2387f117808 core/modules/migrate_drupal/migrate_drupal.install --- a/core/modules/migrate_drupal/migrate_drupal.install Thu Apr 26 11:26:54 2018 +0100 +++ b/core/modules/migrate_drupal/migrate_drupal.install Tue Jul 10 15:07:59 2018 +0100 @@ -14,3 +14,13 @@ ->set('enforce_source_module_tags', ['Drupal 6', 'Drupal 7']) ->save(); } + +/** + * Sets the follow-up migration tags. + */ +function migrate_drupal_update_8502() { + \Drupal::configFactory() + ->getEditable('migrate_drupal.settings') + ->set('follow_up_migration_tags', ['Follow-up migration']) + ->save(); +} diff -r e200cb7efeb3 -r c2387f117808 core/modules/migrate_drupal/migrations/d6_entity_reference_translation.yml --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/core/modules/migrate_drupal/migrations/d6_entity_reference_translation.yml Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,22 @@ +id: d6_entity_reference_translation +label: Entity reference translations +migration_tags: + - Drupal 6 + - Follow-up migration +deriver: Drupal\migrate_drupal\Plugin\migrate\EntityReferenceTranslationDeriver +# Supported target types for entity reference translation migrations. The array +# keys are the supported target types and the values are arrays of migrations +# to lookup for the translated entity IDs. +target_types: + node: + - d6_node_translation +# The source plugin will be set by the deriver. +source: + plugin: empty + key: default + target: default +# The process pipeline will be set by the deriver. +process: [] +# The destination plugin will be set by the deriver. +destination: + plugin: null diff -r e200cb7efeb3 -r c2387f117808 core/modules/migrate_drupal/migrations/d7_entity_reference_translation.yml --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/core/modules/migrate_drupal/migrations/d7_entity_reference_translation.yml Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,22 @@ +id: d7_entity_reference_translation +label: Entity reference translations +migration_tags: + - Drupal 7 + - Follow-up migration +deriver: Drupal\migrate_drupal\Plugin\migrate\EntityReferenceTranslationDeriver +# Supported target types for entity reference translation migrations. The array +# keys are the supported target types and the values are arrays of migrations +# to lookup for the translated entity IDs. +target_types: + node: + - d7_node_translation +# The source plugin will be set by the deriver. +source: + plugin: empty + key: default + target: default +# The process pipeline will be set by the deriver. +process: [] +# The destination plugin will be set by the deriver. +destination: + plugin: null diff -r e200cb7efeb3 -r c2387f117808 core/modules/migrate_drupal/src/Annotation/MigrateField.php --- a/core/modules/migrate_drupal/src/Annotation/MigrateField.php Thu Apr 26 11:26:54 2018 +0100 +++ b/core/modules/migrate_drupal/src/Annotation/MigrateField.php Tue Jul 10 15:07:59 2018 +0100 @@ -55,7 +55,7 @@ * Identifies the system providing the data the field plugin will read. * * The source_module is expected to be the name of a Drupal module that must - * must be installed in the source database. + * be installed in the source database. * * @var string */ diff -r e200cb7efeb3 -r c2387f117808 core/modules/migrate_drupal/src/MigrationConfigurationTrait.php --- a/core/modules/migrate_drupal/src/MigrationConfigurationTrait.php Thu Apr 26 11:26:54 2018 +0100 +++ b/core/modules/migrate_drupal/src/MigrationConfigurationTrait.php Tue Jul 10 15:07:59 2018 +0100 @@ -13,6 +13,13 @@ trait MigrationConfigurationTrait { /** + * The follow-up migration tags. + * + * @var string[] + */ + protected $followUpMigrationTags; + + /** * Gets the database connection for the source Drupal database. * * @param array $database @@ -96,6 +103,13 @@ $all_migrations = $plugin_manager->createInstancesByTag($version_tag); $migrations = []; foreach ($all_migrations as $migration) { + // Skip migrations tagged with any of the follow-up migration tags. They + // will be derived and executed after the migrations on which they depend + // have been successfully executed. + // @see Drupal\migrate_drupal\Plugin\MigrationWithFollowUpInterface + if (!empty(array_intersect($migration->getMigrationTags(), $this->getFollowUpMigrationTags()))) { + continue; + } try { // @todo https://drupal.org/node/2681867 We should be able to validate // the entire migration at this point. @@ -120,6 +134,20 @@ } /** + * Returns the follow-up migration tags. + * + * @return string[] + */ + protected function getFollowUpMigrationTags() { + if ($this->followUpMigrationTags === NULL) { + $this->followUpMigrationTags = \Drupal::configFactory() + ->get('migrate_drupal.settings') + ->get('follow_up_migration_tags') ?: []; + } + return $this->followUpMigrationTags; + } + + /** * Determines what version of Drupal the source database contains. * * @param \Drupal\Core\Database\Connection $connection diff -r e200cb7efeb3 -r c2387f117808 core/modules/migrate_drupal/src/Plugin/MigrationWithFollowUpInterface.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/core/modules/migrate_drupal/src/Plugin/MigrationWithFollowUpInterface.php Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,40 @@ +entityFieldManager = $entity_field_manager; + $this->entityTypeManager = $entity_type_manager; + } + + /** + * {@inheritdoc} + */ + public static function create(ContainerInterface $container, $base_plugin_id) { + return new static( + $base_plugin_id, + $container->get('entity_field.manager'), + $container->get('entity_type.manager') + ); + } + + /** + * {@inheritdoc} + */ + public function getDerivativeDefinitions($base_plugin_definition) { + // Get all entity reference fields. + $field_map = $this->entityFieldManager->getFieldMapByFieldType('entity_reference'); + + foreach ($field_map as $entity_type => $fields) { + foreach ($fields as $field_name => $field) { + foreach ($field['bundles'] as $bundle) { + $field_definitions = $this->entityFieldManager->getFieldDefinitions($entity_type, $bundle); + $target_type = $field_definitions[$field_name]->getSetting('target_type'); + + // If the field's target type is not supported, skip it. + if (!array_key_exists($target_type, $base_plugin_definition['target_types'])) { + continue; + } + + // Key derivatives by entity types and bundles. + $derivative_key = $entity_type . '__' . $bundle; + + $derivative = $base_plugin_definition; + + // Set the migration label. + $derivative['label'] = $this->t('@label (@derivative)', [ + '@label' => $base_plugin_definition['label'], + '@derivative' => $derivative_key, + ]); + + // Set the source plugin. + $derivative['source']['plugin'] = 'content_entity' . PluginBase::DERIVATIVE_SEPARATOR . $entity_type; + $derivative['source']['bundle'] = $bundle; + + // Set the process pipeline. + $entity_type_definition = $this->entityTypeManager->getDefinition($entity_type); + $id_key = $entity_type_definition->getKey('id'); + $derivative['process'][$id_key] = $id_key; + if ($entity_type_definition->isRevisionable()) { + $revision_key = $entity_type_definition->getKey('revision'); + $derivative['process'][$revision_key] = $revision_key; + } + if ($entity_type_definition->isTranslatable()) { + $langcode_key = $entity_type_definition->getKey('langcode'); + $derivative['process'][$langcode_key] = $langcode_key; + } + + // Set the destination plugin. + $derivative['destination']['plugin'] = 'entity' . PluginBase::DERIVATIVE_SEPARATOR . $entity_type; + $derivative['destination']['default_bundle'] = $bundle; + if ($entity_type_definition->isTranslatable()) { + $derivative['destination']['translations'] = TRUE; + } + + // Allow overwriting the entity reference field so we can update its + // values with the ones found in the mapping table. + $derivative['destination']['overwrite_properties'][$field_name] = $field_name; + + // Add the entity reference field to the process pipeline. + $derivative['process'][$field_name] = [ + 'plugin' => 'sub_process', + 'source' => $field_name, + 'process' => [ + 'target_id' => [ + [ + 'plugin' => 'migration_lookup', + 'source' => 'target_id', + 'migration' => $base_plugin_definition['target_types'][$target_type], + 'no_stub' => TRUE, + ], + [ + 'plugin' => 'skip_on_empty', + 'method' => 'row', + ], + [ + 'plugin' => 'extract', + 'index' => [0], + ], + ], + ], + ]; + + if (!isset($this->derivatives[$derivative_key])) { + // If this is a new derivative, add it to the returned derivatives. + $this->derivatives[$derivative_key] = $derivative; + } + else { + // If this is an existing derivative, it means this bundle has more + // than one entity reference field. In that case, we only want to add + // the field to the process pipeline and make it overwritable. + $this->derivatives[$derivative_key]['process'] += $derivative['process']; + $this->derivatives[$derivative_key]['destination']['overwrite_properties'] += $derivative['destination']['overwrite_properties']; + } + } + } + } + + return $this->derivatives; + } + +} diff -r e200cb7efeb3 -r c2387f117808 core/modules/migrate_drupal/src/Plugin/migrate/field/NodeReference.php --- a/core/modules/migrate_drupal/src/Plugin/migrate/field/NodeReference.php Thu Apr 26 11:26:54 2018 +0100 +++ b/core/modules/migrate_drupal/src/Plugin/migrate/field/NodeReference.php Tue Jul 10 15:07:59 2018 +0100 @@ -26,8 +26,7 @@ 'source' => $field_name, 'process' => [ 'target_id' => [ - 'plugin' => 'migration_lookup', - 'migration' => 'd6_node', + 'plugin' => 'get', 'source' => 'nid', ], ], diff -r e200cb7efeb3 -r c2387f117808 core/modules/migrate_drupal/tests/fixtures/drupal6.php --- a/core/modules/migrate_drupal/tests/fixtures/drupal6.php Thu Apr 26 11:26:54 2018 +0100 +++ b/core/modules/migrate_drupal/tests/fixtures/drupal6.php Tue Jul 10 15:07:59 2018 +0100 @@ -2717,6 +2717,30 @@ 'locked' => '0', )) ->values(array( + 'field_name' => 'field_company_2', + 'type' => 'nodereference', + 'global_settings' => 'a:1:{s:19:"referenceable_types";a:10:{s:7:"company";s:7:"company";s:7:"article";i:0;s:8:"employee";i:0;s:5:"forum";i:0;s:10:"test_event";i:0;s:9:"test_page";i:0;s:11:"test_planet";i:0;s:10:"test_story";i:0;s:7:"sponsor";i:0;s:5:"story";i:0;}}', + 'required' => '0', + 'multiple' => '0', + 'db_storage' => '1', + 'module' => 'nodereference', + 'db_columns' => 'a:1:{s:3:"nid";a:4:{s:4:"type";s:3:"int";s:8:"unsigned";b:1;s:8:"not null";b:0;s:5:"index";b:1;}}', + 'active' => '1', + 'locked' => '0', +)) +->values(array( + 'field_name' => 'field_company_3', + 'type' => 'nodereference', + 'global_settings' => 'a:1:{s:19:"referenceable_types";a:10:{s:7:"company";s:7:"company";s:7:"article";i:0;s:8:"employee";i:0;s:5:"forum";i:0;s:10:"test_event";i:0;s:9:"test_page";i:0;s:11:"test_planet";i:0;s:10:"test_story";i:0;s:7:"sponsor";i:0;s:5:"story";i:0;}}', + 'required' => '0', + 'multiple' => '0', + 'db_storage' => '1', + 'module' => 'nodereference', + 'db_columns' => 'a:1:{s:3:"nid";a:4:{s:4:"type";s:3:"int";s:8:"unsigned";b:1;s:8:"not null";b:0;s:5:"index";b:1;}}', + 'active' => '1', + 'locked' => '0', +)) +->values(array( 'field_name' => 'field_multivalue', 'type' => 'number_decimal', 'global_settings' => 'a:9:{s:6:"prefix";s:0:"";s:6:"suffix";s:0:"";s:3:"min";s:0:"";s:3:"max";s:0:"";s:14:"allowed_values";s:0:"";s:18:"allowed_values_php";s:0:"";s:9:"precision";s:2:"10";s:5:"scale";s:1:"2";s:7:"decimal";s:1:".";}', @@ -2729,6 +2753,30 @@ 'locked' => '0', )) ->values(array( + 'field_name' => 'field_reference', + 'type' => 'nodereference', + 'global_settings' => 'a:1:{s:19:"referenceable_types";a:11:{s:4:"page";s:4:"page";s:7:"article";i:0;s:7:"company";i:0;s:8:"employee";i:0;s:5:"forum";i:0;s:10:"test_event";i:0;s:9:"test_page";i:0;s:11:"test_planet";i:0;s:10:"test_story";i:0;s:7:"sponsor";i:0;s:5:"story";i:0;}}', + 'required' => '0', + 'multiple' => '0', + 'db_storage' => '1', + 'module' => 'nodereference', + 'db_columns' => 'a:1:{s:3:"nid";a:4:{s:4:"type";s:3:"int";s:8:"unsigned";b:1;s:8:"not null";b:0;s:5:"index";b:1;}}', + 'active' => '1', + 'locked' => '0', +)) +->values(array( + 'field_name' => 'field_reference_2', + 'type' => 'nodereference', + 'global_settings' => 'a:1:{s:19:"referenceable_types";a:11:{s:4:"page";s:4:"page";s:7:"article";i:0;s:7:"company";i:0;s:8:"employee";i:0;s:5:"forum";i:0;s:10:"test_event";i:0;s:9:"test_page";i:0;s:11:"test_planet";i:0;s:10:"test_story";i:0;s:7:"sponsor";i:0;s:5:"story";i:0;}}', + 'required' => '0', + 'multiple' => '0', + 'db_storage' => '1', + 'module' => 'nodereference', + 'db_columns' => 'a:1:{s:3:"nid";a:4:{s:4:"type";s:3:"int";s:8:"unsigned";b:1;s:8:"not null";b:0;s:5:"index";b:1;}}', + 'active' => '1', + 'locked' => '0', +)) +->values(array( 'field_name' => 'field_test', 'type' => 'text', 'global_settings' => 'a:4:{s:15:"text_processing";s:1:"1";s:10:"max_length";s:0:"";s:14:"allowed_values";s:0:"";s:18:"allowed_values_php";s:0:"";}', @@ -3075,6 +3123,30 @@ 'widget_active' => '1', )) ->values(array( + 'field_name' => 'field_company_2', + 'type_name' => 'employee', + 'weight' => '33', + 'label' => 'Company 2', + 'widget_type' => 'nodereference_buttons', + 'widget_settings' => 'a:4:{s:18:"autocomplete_match";s:8:"contains";s:4:"size";i:60;s:13:"default_value";a:1:{i:0;a:1:{s:3:"nid";s:0:"";}}s:17:"default_value_php";N;}', + 'display_settings' => 'a:5:{s:5:"label";a:2:{s:6:"format";s:5:"above";s:7:"exclude";i:0;}i:5;a:2:{s:6:"format";s:7:"default";s:7:"exclude";i:0;}s:6:"teaser";a:2:{s:6:"format";s:7:"default";s:7:"exclude";i:0;}s:4:"full";a:2:{s:6:"format";s:7:"default";s:7:"exclude";i:0;}i:4;a:2:{s:6:"format";s:7:"default";s:7:"exclude";i:0;}}', + 'description' => '', + 'widget_module' => 'nodereference', + 'widget_active' => '1', +)) +->values(array( + 'field_name' => 'field_company_3', + 'type_name' => 'employee', + 'weight' => '34', + 'label' => 'Company 3', + 'widget_type' => 'nodereference_autocomplete', + 'widget_settings' => 'a:4:{s:18:"autocomplete_match";s:8:"contains";s:4:"size";s:2:"60";s:13:"default_value";a:1:{i:0;a:2:{s:3:"nid";N;s:14:"_error_element";s:50:"default_value_widget][field_company_3][0][nid][nid";}}s:17:"default_value_php";N;}', + 'display_settings' => 'a:5:{s:5:"label";a:2:{s:6:"format";s:5:"above";s:7:"exclude";i:0;}i:5;a:2:{s:6:"format";s:7:"default";s:7:"exclude";i:0;}s:6:"teaser";a:2:{s:6:"format";s:7:"default";s:7:"exclude";i:0;}s:4:"full";a:2:{s:6:"format";s:7:"default";s:7:"exclude";i:0;}i:4;a:2:{s:6:"format";s:7:"default";s:7:"exclude";i:0;}}', + 'description' => '', + 'widget_module' => 'nodereference', + 'widget_active' => '1', +)) +->values(array( 'field_name' => 'field_multivalue', 'type_name' => 'test_planet', 'weight' => '2', @@ -3087,6 +3159,30 @@ 'widget_active' => '1', )) ->values(array( + 'field_name' => 'field_reference', + 'type_name' => 'page', + 'weight' => '31', + 'label' => 'Reference', + 'widget_type' => 'nodereference_select', + 'widget_settings' => 'a:4:{s:18:"autocomplete_match";s:8:"contains";s:4:"size";i:60;s:13:"default_value";a:1:{i:0;a:1:{s:3:"nid";s:0:"";}}s:17:"default_value_php";N;}', + 'display_settings' => 'a:5:{s:5:"label";a:2:{s:6:"format";s:5:"above";s:7:"exclude";i:0;}i:5;a:2:{s:6:"format";s:7:"default";s:7:"exclude";i:0;}s:6:"teaser";a:2:{s:6:"format";s:7:"default";s:7:"exclude";i:0;}s:4:"full";a:2:{s:6:"format";s:7:"default";s:7:"exclude";i:0;}i:4;a:2:{s:6:"format";s:7:"default";s:7:"exclude";i:0;}}', + 'description' => '', + 'widget_module' => 'nodereference', + 'widget_active' => '1', +)) +->values(array( + 'field_name' => 'field_reference_2', + 'type_name' => 'page', + 'weight' => '32', + 'label' => 'Reference', + 'widget_type' => 'nodereference_select', + 'widget_settings' => 'a:4:{s:18:"autocomplete_match";s:8:"contains";s:4:"size";i:60;s:13:"default_value";a:1:{i:0;a:1:{s:3:"nid";s:0:"";}}s:17:"default_value_php";N;}', + 'display_settings' => 'a:5:{s:5:"label";a:2:{s:6:"format";s:5:"above";s:7:"exclude";i:0;}i:5;a:2:{s:6:"format";s:7:"default";s:7:"exclude";i:0;}s:6:"teaser";a:2:{s:6:"format";s:7:"default";s:7:"exclude";i:0;}s:4:"full";a:2:{s:6:"format";s:7:"default";s:7:"exclude";i:0;}i:4;a:2:{s:6:"format";s:7:"default";s:7:"exclude";i:0;}}', + 'description' => '', + 'widget_module' => 'nodereference', + 'widget_active' => '1', +)) +->values(array( 'field_name' => 'field_test', 'type_name' => 'story', 'weight' => '1', @@ -3374,6 +3470,18 @@ 'size' => 'normal', 'unsigned' => TRUE, ), + 'field_company_2_nid' => array( + 'type' => 'int', + 'not null' => FALSE, + 'size' => 'normal', + 'unsigned' => TRUE, + ), + 'field_company_3_nid' => array( + 'type' => 'int', + 'not null' => FALSE, + 'size' => 'normal', + 'unsigned' => TRUE, + ), ), 'primary key' => array( 'vid', @@ -3385,6 +3493,12 @@ 'field_commander_uid' => array( 'field_commander_uid', ), + 'field_company_2_nid' => array( + 'field_company_2_nid', + ), + 'field_company_3_nid' => array( + 'field_company_3_nid', + ), ), 'mysql_character_set' => 'utf8', )); @@ -3394,11 +3508,15 @@ 'vid', 'nid', 'field_commander_uid', + 'field_company_2_nid', + 'field_company_3_nid', )) ->values(array( 'vid' => '21', 'nid' => '18', 'field_commander_uid' => '8', + 'field_company_2_nid' => '15', + 'field_company_3_nid' => '16', )) ->execute(); @@ -3423,12 +3541,70 @@ 'not null' => FALSE, 'size' => 'normal', ), + 'field_reference_nid' => array( + 'type' => 'int', + 'not null' => FALSE, + 'size' => 'normal', + 'unsigned' => TRUE, + ), + 'field_reference_2_nid' => array( + 'type' => 'int', + 'not null' => FALSE, + 'size' => 'normal', + 'unsigned' => TRUE, + ), ), 'primary key' => array( 'vid', ), - 'mysql_character_set' => 'utf8', -)); + 'indexes' => array( + 'field_reference_nid' => array( + 'field_reference_nid', + ), + 'field_reference_2_nid' => array( + 'field_reference_2_nid', + ), + ), + 'mysql_character_set' => 'utf8', +)); + +$connection->insert('content_type_page') +->fields(array( + 'vid', + 'nid', + 'field_text_field_value', + 'field_reference_nid', + 'field_reference_2_nid', +)) +->values(array( + 'vid' => '13', + 'nid' => '10', + 'field_text_field_value' => NULL, + 'field_reference_nid' => '13', + 'field_reference_2_nid' => '13', +)) +->values(array( + 'vid' => '14', + 'nid' => '11', + 'field_text_field_value' => NULL, + 'field_reference_nid' => '20', + 'field_reference_2_nid' => '20', +)) +->values(array( + 'vid' => '16', + 'nid' => '13', + 'field_text_field_value' => NULL, + 'field_reference_nid' => '10', + 'field_reference_2_nid' => '10', +)) +->values(array( + 'vid' => '23', + 'nid' => '20', + 'field_text_field_value' => NULL, + 'field_reference_nid' => '11', + 'field_reference_2_nid' => '11', +)) +->execute(); $connection->schema()->createTable('content_type_story', array( 'fields' => array( @@ -8626,7 +8802,7 @@ )) ->values(array( 'lid' => '509', - 'objectid' => 'profile_sell_address', + 'objectid' => 'profile_sell_Address', 'type' => 'field', 'property' => 'title', 'objectindex' => '0', @@ -8634,7 +8810,7 @@ )) ->values(array( 'lid' => '510', - 'objectid' => 'profile_sell_address', + 'objectid' => 'profile_sell_Address', 'type' => 'field', 'property' => 'explanation', 'objectindex' => '0', @@ -8714,7 +8890,7 @@ )) ->values(array( 'lid' => '520', - 'objectid' => 'profile_love_migrations', + 'objectid' => 'profile_really_really_love_migrations', 'type' => 'field', 'property' => 'title', 'objectindex' => '0', @@ -8722,7 +8898,7 @@ )) ->values(array( 'lid' => '521', - 'objectid' => 'profile_love_migrations', + 'objectid' => 'profile_really_really_love_migrations', 'type' => 'field', 'property' => 'explanation', 'objectindex' => '0', @@ -9640,6 +9816,46 @@ 'objectindex' => '7', 'format' => '0', )) +->values(array( + 'lid' => '1674', + 'objectid' => '463', + 'type' => 'item', + 'property' => 'title', + 'objectindex' => '463', + 'format' => '0', +)) +->values(array( + 'lid' => '1675', + 'objectid' => '463', + 'type' => 'item', + 'property' => 'description', + 'objectindex' => '463', + 'format' => '0', +)) +->values(array( + 'lid' => '1676', + 'objectid' => '138', + 'type' => 'item', + 'property' => 'title', + 'objectindex' => '138', + 'format' => '0', +)) +->values(array( + 'lid' => '1677', + 'objectid' => '138', + 'type' => 'item', + 'property' => 'description', + 'objectindex' => '138', + 'format' => '0', +)) +->values(array( + 'lid' => '1678', + 'objectid' => 'profile_really_really_love_migrating', + 'type' => 'field', + 'property' => 'title', + 'objectindex' => '0', + 'format' => '0', +)) ->execute(); $connection->schema()->createTable('i18n_variable', array( @@ -13960,14 +14176,14 @@ )) ->values(array( 'lid' => '509', - 'location' => 'field:profile_sell_address:title', + 'location' => 'field:profile_sell_Address:title', 'textgroup' => 'profile', 'source' => 'Sell your email address?', 'version' => '1', )) ->values(array( 'lid' => '510', - 'location' => 'field:profile_sell_address:explanation', + 'location' => 'field:profile_sell_Address:explanation', 'textgroup' => 'profile', 'source' => "If you check this box, we'll sell your address to spammers to help line the pockets of our shareholders. Thanks!", 'version' => '1', @@ -14037,14 +14253,14 @@ )) ->values(array( 'lid' => '520', - 'location' => 'field:profile_love_migrations:title', + 'location' => 'field:profile_really_really_love_migrations:title', 'textgroup' => 'profile', - 'source' => 'I love migrations', + 'source' => 'I really, really, really love migrations', 'version' => '1', )) ->values(array( 'lid' => '521', - 'location' => 'field:profile_love_migrations:explanation', + 'location' => 'field:profile_really_really_love_migrations:explanation', 'textgroup' => 'profile', 'source' => 'If you check this box, you love migrations.', 'version' => '1', @@ -22106,6 +22322,41 @@ 'source' => 'Forums', 'version' => '1', )) +->values(array( + 'lid' => '1674', + 'location' => 'item:463:title', + 'textgroup' => 'menu', + 'source' => 'fr - Test 1', + 'version' => '1', +)) +->values(array( + 'lid' => '1675', + 'location' => 'item:463:description', + 'textgroup' => 'menu', + 'source' => 'fr - Test menu link 1', + 'version' => '1', +)) +->values(array( + 'lid' => '1676', + 'location' => 'item:138:title', + 'textgroup' => 'menu', + 'source' => 'Test 1', + 'version' => '1', +)) +->values(array( + 'lid' => '1677', + 'location' => 'item:138:description', + 'textgroup' => 'menu', + 'source' => 'Test menu link 1', + 'version' => '1', +)) +->values(array( + 'lid' => '1678', + 'location' => 'field:profile_really_really_love_migrating:title', + 'textgroup' => 'profile', + 'source' => 'I really, really, really love migrating', + 'version' => '1', +)) ->execute(); $connection->schema()->createTable('locales_target', array( @@ -26284,7 +26535,7 @@ 'language' => 'fr', 'plid' => '0', 'plural' => '0', - 'i18n_status' => '0', + 'i18n_status' => '1', )) ->values(array( 'lid' => '521', @@ -27151,6 +27402,14 @@ 'i18n_status' => '0', )) ->values(array( + 'lid' => '1678', + 'translation' => 'fr - I really, really, really love migrating ', + 'language' => 'fr', + 'plid' => '0', + 'plural' => '0', + 'i18n_status' => '0', +)) +->values(array( 'lid' => '66', 'translation' => 'zu - CCK - Aucune Intégration aux Vues', 'language' => 'zu', @@ -27635,7 +27894,7 @@ 'link_path' => 'user/login', 'router_path' => 'user/login', 'link_title' => 'Test 1', - 'options' => 'a:1:{s:10:"attributes";a:1:{s:5:"title";s:16:"Test menu link 1";}}', + 'options' => 'a:2:{s:10:"attributes";a:1:{s:5:"title";s:16:"Test menu link 1";}s:8:"langcode";s:2:"en";}', 'module' => 'menu', 'hidden' => '0', 'external' => '0', @@ -33649,6 +33908,141 @@ 'p9' => '0', 'updated' => '0', )) +->values(array( + 'menu_name' => 'primary-links', + 'mlid' => '459', + 'plid' => '0', + 'link_path' => 'node/10', + 'router_path' => 'node/%', + 'link_title' => 'The Real McCoy', + 'options' => 'a:2:{s:10:"attributes";a:1:{s:5:"title";s:0:"";}s:5:"alter";b:1;}', + 'module' => 'menu', + 'hidden' => '0', + 'external' => '0', + 'has_children' => '0', + 'expanded' => '0', + 'weight' => '0', + 'depth' => '1', + 'customized' => '1', + 'p1' => '459', + 'p2' => '0', + 'p3' => '0', + 'p4' => '0', + 'p5' => '0', + 'p6' => '0', + 'p7' => '0', + 'p8' => '0', + 'p9' => '0', + 'updated' => '0', +)) +->values(array( + 'menu_name' => 'primary-links', + 'mlid' => '460', + 'plid' => '0', + 'link_path' => 'node/11', + 'router_path' => 'node/%', + 'link_title' => 'Le Vrai McCoy', + 'options' => 'a:2:{s:10:"attributes";a:1:{s:5:"title";s:0:"";}s:5:"alter";b:1;}', + 'module' => 'menu', + 'hidden' => '0', + 'external' => '0', + 'has_children' => '0', + 'expanded' => '0', + 'weight' => '0', + 'depth' => '1', + 'customized' => '1', + 'p1' => '460', + 'p2' => '0', + 'p3' => '0', + 'p4' => '0', + 'p5' => '0', + 'p6' => '0', + 'p7' => '0', + 'p8' => '0', + 'p9' => '0', + 'updated' => '0', +)) +->values(array( + 'menu_name' => 'primary-links', + 'mlid' => '461', + 'plid' => '0', + 'link_path' => 'node/12', + 'router_path' => 'node/%', + 'link_title' => 'Abantu zulu', + 'options' => 'a:2:{s:10:"attributes";a:1:{s:5:"title";s:0:"";}s:5:"alter";b:1;}', + 'module' => 'menu', + 'hidden' => '0', + 'external' => '0', + 'has_children' => '0', + 'expanded' => '0', + 'weight' => '0', + 'depth' => '1', + 'customized' => '1', + 'p1' => '461', + 'p2' => '0', + 'p3' => '0', + 'p4' => '0', + 'p5' => '0', + 'p6' => '0', + 'p7' => '0', + 'p8' => '0', + 'p9' => '0', + 'updated' => '0', +)) +->values(array( + 'menu_name' => 'primary-links', + 'mlid' => '462', + 'plid' => '0', + 'link_path' => 'node/13', + 'router_path' => 'node/%', + 'link_title' => 'The Zulu People', + 'options' => 'a:2:{s:10:"attributes";a:1:{s:5:"title";s:0:"";}s:5:"alter";b:1;}', + 'module' => 'menu', + 'hidden' => '0', + 'external' => '0', + 'has_children' => '0', + 'expanded' => '0', + 'weight' => '0', + 'depth' => '1', + 'customized' => '1', + 'p1' => '462', + 'p2' => '0', + 'p3' => '0', + 'p4' => '0', + 'p5' => '0', + 'p6' => '0', + 'p7' => '0', + 'p8' => '0', + 'p9' => '0', + 'updated' => '0', +)) +->values(array( + 'menu_name' => 'secondary-links', + 'mlid' => '463', + 'plid' => '139', + 'link_path' => 'user/login', + 'router_path' => 'user/login', + 'link_title' => 'fr - Test 1', + 'options' => 'a:3:{s:10:"attributes";a:1:{s:5:"title";s:21:"fr - Test menu link 1";}s:8:"langcode";s:2:"fr";s:5:"alter";b:1;}', + 'module' => 'menu', + 'hidden' => '0', + 'external' => '0', + 'has_children' => '0', + 'expanded' => '0', + 'weight' => '-49', + 'depth' => '2', + 'customized' => '1', + 'p1' => '139', + 'p2' => '459', + 'p3' => '0', + 'p4' => '0', + 'p5' => '0', + 'p6' => '0', + 'p7' => '0', + 'p8' => '0', + 'p9' => '0', + 'updated' => '0', +)) ->execute(); $connection->schema()->createTable('menu_router', array( @@ -43283,6 +43677,23 @@ 'tnid' => '0', 'translate' => '0', )) +->values(array( + 'nid' => '20', + 'vid' => '23', + 'type' => 'page', + 'language' => 'fr', + 'title' => 'Le peuple zoulou', + 'uid' => '1', + 'status' => '1', + 'created' => '1520613038', + 'changed' => '1520613305', + 'comment' => '0', + 'promote' => '1', + 'moderate' => '0', + 'sticky' => '0', + 'tnid' => '12', + 'translate' => '0', +)) ->execute(); $connection->schema()->createTable('node_access', array( @@ -43565,6 +43976,30 @@ 'timestamp' => '1478755314', )) ->values(array( + 'nid' => '10', + 'totalcount' => '5', + 'daycount' => '1', + 'timestamp' => '1521137459', +)) +->values(array( + 'nid' => '11', + 'totalcount' => '3', + 'daycount' => '1', + 'timestamp' => '1521137463', +)) +->values(array( + 'nid' => '12', + 'totalcount' => '3', + 'daycount' => '0', + 'timestamp' => '1521137469', +)) +->values(array( + 'nid' => '13', + 'totalcount' => '2', + 'daycount' => '1', + 'timestamp' => '1521137470', +)) +->values(array( 'nid' => '14', 'totalcount' => '1', 'daycount' => '1', @@ -43917,6 +44352,17 @@ 'timestamp' => '1501955771', 'format' => '1', )) +->values(array( + 'nid' => '20', + 'vid' => '23', + 'uid' => '1', + 'title' => 'Le peuple zoulou', + 'body' => 'Le peuple zoulou.', + 'teaser' => 'Le peuple zoulou.', + 'log' => '', + 'timestamp' => '1520613305', + 'format' => '1', +)) ->execute(); $connection->schema()->createTable('node_type', array( @@ -44183,7 +44629,7 @@ 'custom' => '1', 'modified' => '1', 'locked' => '0', - 'orig_type' => 'page', + 'orig_type' => 'test_page', )) ->values(array( 'type' => 'test_planet', @@ -44414,7 +44860,7 @@ ->values(array( 'fid' => '10', 'title' => 'Sell your email address?', - 'name' => 'profile_sell_address', + 'name' => 'profile_sell_Address', 'explanation' => "If you check this box, we'll sell your address to spammers to help line the pockets of our shareholders. Thanks!", 'category' => 'Communication preferences', 'page' => 'People who want us to sell their address', @@ -44488,8 +44934,8 @@ )) ->values(array( 'fid' => '15', - 'title' => 'I love migrations', - 'name' => 'profile_love_migrations', + 'title' => 'I really, really, really love migrations', + 'name' => 'profile_really_really_love_migrations', 'explanation' => 'If you check this box, you love migrations.', 'category' => 'Personal information', 'page' => 'People who love migrations', @@ -44501,6 +44947,21 @@ 'autocomplete' => '0', 'options' => '', )) +->values(array( + 'fid' => '16', + 'title' => 'I really, really, really love migrating', + 'name' => 'profile_really_really_love_migrating', + 'explanation' => '', + 'category' => 'Personal information', + 'page' => '', + 'type' => 'checkbox', + 'weight' => '0', + 'required' => '0', + 'register' => '0', + 'visibility' => '2', + 'autocomplete' => '0', + 'options' => '', +)) ->execute(); $connection->schema()->createTable('profile_values', array( @@ -44713,6 +45174,11 @@ 'uid' => '17', 'value' => 'a:3:{s:5:"month";s:2:"12";s:3:"day";s:2:"18";s:4:"year";s:4:"1942";}', )) +->values(array( + 'fid' => '15', + 'uid' => '2', + 'value' => '1', +)) ->execute(); $connection->schema()->createTable('role', array( diff -r e200cb7efeb3 -r c2387f117808 core/modules/migrate_drupal/tests/fixtures/drupal7.php --- a/core/modules/migrate_drupal/tests/fixtures/drupal7.php Thu Apr 26 11:26:54 2018 +0100 +++ b/core/modules/migrate_drupal/tests/fixtures/drupal7.php Tue Jul 10 15:07:59 2018 +0100 @@ -1906,6 +1906,34 @@ 'mysql_character_set' => 'utf8', )); +$connection->insert('book') + ->fields(array( + 'mlid', + 'nid', + 'bid', + )) + ->values(array( + 'mlid' => '480', + 'nid' => '4', + 'bid' => '4', + )) + ->values(array( + 'mlid' => '481', + 'nid' => '6', + 'bid' => '4', + )) + ->values(array( + 'mlid' => '482', + 'nid' => '2', + 'bid' => '4', + )) + ->values(array( + 'mlid' => '483', + 'nid' => '1', + 'bid' => '8', + )) + ->execute(); + $connection->schema()->createTable('cache', array( 'fields' => array( 'cid' => array( @@ -2983,6 +3011,180 @@ )) ->execute(); +$connection->schema()->createTable('entity_translation', array( + 'fields' => array( + 'entity_type' => array( + 'type' => 'varchar', + 'not null' => TRUE, + 'length' => '128', + 'default' => '', + ), + 'entity_id' => array( + 'type' => 'int', + 'not null' => TRUE, + 'size' => 'normal', + 'unsigned' => TRUE, + ), + 'revision_id' => array( + 'type' => 'int', + 'not null' => TRUE, + 'size' => 'normal', + 'unsigned' => TRUE, + ), + 'language' => array( + 'type' => 'varchar', + 'not null' => TRUE, + 'length' => '32', + 'default' => '', + ), + 'source' => array( + 'type' => 'varchar', + 'not null' => TRUE, + 'length' => '32', + 'default' => '', + ), + 'uid' => array( + 'type' => 'int', + 'not null' => TRUE, + 'size' => 'normal', + 'default' => '0', + ), + 'status' => array( + 'type' => 'int', + 'not null' => TRUE, + 'size' => 'normal', + 'default' => '1', + ), + 'translate' => array( + 'type' => 'int', + 'not null' => TRUE, + 'size' => 'normal', + 'default' => '0', + ), + 'created' => array( + 'type' => 'int', + 'not null' => TRUE, + 'size' => 'normal', + 'default' => '0', + ), + 'changed' => array( + 'type' => 'int', + 'not null' => TRUE, + 'size' => 'normal', + 'default' => '0', + ), + ), + 'primary key' => array( + 'entity_type', + 'entity_id', + 'language', + ), + 'mysql_character_set' => 'utf8', +)); + +$connection->insert('entity_translation') +->fields(array( + 'entity_type', + 'entity_id', + 'revision_id', + 'language', + 'source', + 'uid', + 'status', + 'translate', + 'created', + 'changed', +)) +->values(array( + 'entity_type' => 'user', + 'entity_id' => '2', + 'revision_id' => '2', + 'language' => 'en', + 'source' => '', + 'uid' => '1', + 'status' => '1', + 'translate' => '0', + 'created' => '1527594929', + 'changed' => '1527594929', +)) +->execute(); + +$connection->schema()->createTable('entity_translation_revision', array( + 'fields' => array( + 'entity_type' => array( + 'type' => 'varchar', + 'not null' => TRUE, + 'length' => '128', + 'default' => '', + ), + 'entity_id' => array( + 'type' => 'int', + 'not null' => TRUE, + 'size' => 'normal', + 'unsigned' => TRUE, + ), + 'revision_id' => array( + 'type' => 'int', + 'not null' => TRUE, + 'size' => 'normal', + 'unsigned' => TRUE, + ), + 'language' => array( + 'type' => 'varchar', + 'not null' => TRUE, + 'length' => '32', + 'default' => '', + ), + 'source' => array( + 'type' => 'varchar', + 'not null' => TRUE, + 'length' => '32', + 'default' => '', + ), + 'uid' => array( + 'type' => 'int', + 'not null' => TRUE, + 'size' => 'normal', + 'default' => '0', + ), + 'status' => array( + 'type' => 'int', + 'not null' => TRUE, + 'size' => 'normal', + 'default' => '1', + ), + 'translate' => array( + 'type' => 'int', + 'not null' => TRUE, + 'size' => 'normal', + 'default' => '0', + ), + 'created' => array( + 'type' => 'int', + 'not null' => TRUE, + 'size' => 'normal', + 'default' => '0', + ), + 'changed' => array( + 'type' => 'int', + 'not null' => TRUE, + 'size' => 'normal', + 'default' => '0', + ), + ), + 'primary key' => array( + 'entity_type', + 'revision_id', + 'language', + ), + 'indexes' => array( + 'revision_id' => array( + 'revision_id', + ), + ), + 'mysql_character_set' => 'utf8', +)); + $connection->schema()->createTable('field_config', array( 'fields' => array( 'id' => array( @@ -3286,9 +3488,9 @@ 'storage_module' => 'field_sql_storage', 'storage_active' => '1', 'locked' => '0', - 'data' => 'a:7:{s:12:"translatable";s:1:"0";s:12:"entity_types";a:0:{}s:8:"settings";a:0:{}s:7:"storage";a:5:{s:4:"type";s:17:"field_sql_storage";s:8:"settings";a:0:{}s:6:"module";s:17:"field_sql_storage";s:6:"active";s:1:"1";s:7:"details";a:1:{s:3:"sql";a:2:{s:18:"FIELD_LOAD_CURRENT";a:1:{s:24:"field_data_field_integer";a:1:{s:5:"value";s:19:"field_integer_value";}}s:19:"FIELD_LOAD_REVISION";a:1:{s:28:"field_revision_field_integer";a:1:{s:5:"value";s:19:"field_integer_value";}}}}}s:12:"foreign keys";a:0:{}s:7:"indexes";a:0:{}s:2:"id";s:2:"14";}', + 'data' => 'a:7:{s:12:"translatable";b:1;s:12:"entity_types";a:0:{}s:8:"settings";a:1:{s:23:"entity_translation_sync";b:0;}s:7:"storage";a:5:{s:4:"type";s:17:"field_sql_storage";s:8:"settings";a:0:{}s:6:"module";s:17:"field_sql_storage";s:6:"active";s:1:"1";s:7:"details";a:1:{s:3:"sql";a:2:{s:18:"FIELD_LOAD_CURRENT";a:1:{s:24:"field_data_field_integer";a:1:{s:5:"value";s:19:"field_integer_value";}}s:19:"FIELD_LOAD_REVISION";a:1:{s:28:"field_revision_field_integer";a:1:{s:5:"value";s:19:"field_integer_value";}}}}}s:12:"foreign keys";a:0:{}s:7:"indexes";a:0:{}s:2:"id";s:2:"14";}', 'cardinality' => '1', - 'translatable' => '0', + 'translatable' => '1', 'deleted' => '0', )) ->values(array( @@ -3606,6 +3808,51 @@ 'translatable' => '0', 'deleted' => '0', )) +->values(array( + 'id' => '37', + 'field_name' => 'field_float_list', + 'type' => 'list_float', + 'module' => 'list', + 'active' => '1', + 'storage_type' => 'field_sql_storage', + 'storage_module' => 'field_sql_storage', + 'storage_active' => '1', + 'locked' => '0', + 'data' => 'a:7:{s:12:"translatable";s:1:"0";s:12:"entity_types";a:0:{}s:8:"settings";a:2:{s:14:"allowed_values";a:2:{s:6:"3.1416";s:2:"Pi";s:6:"6.2832";s:3:"Tau";}s:23:"allowed_values_function";s:0:"";}s:7:"storage";a:5:{s:4:"type";s:17:"field_sql_storage";s:8:"settings";a:0:{}s:6:"module";s:17:"field_sql_storage";s:6:"active";s:1:"1";s:7:"details";a:1:{s:3:"sql";a:2:{s:18:"FIELD_LOAD_CURRENT";a:1:{s:27:"field_data_field_float_list";a:1:{s:5:"value";s:22:"field_float_list_value";}}s:19:"FIELD_LOAD_REVISION";a:1:{s:31:"field_revision_field_float_list";a:1:{s:5:"value";s:22:"field_float_list_value";}}}}}s:12:"foreign keys";a:0:{}s:7:"indexes";a:1:{s:5:"value";a:1:{i:0;s:5:"value";}}s:2:"id";s:2:"37";}', + 'cardinality' => '1', + 'translatable' => '0', + 'deleted' => '0', +)) +->values(array( + 'id' => '38', + 'field_name' => 'field_reference', + 'type' => 'entityreference', + 'module' => 'entityreference', + 'active' => '1', + 'storage_type' => 'field_sql_storage', + 'storage_module' => 'field_sql_storage', + 'storage_active' => '1', + 'locked' => '0', + 'data' => 'a:7:{s:12:"translatable";s:1:"0";s:12:"entity_types";a:0:{}s:8:"settings";a:3:{s:11:"target_type";s:4:"node";s:7:"handler";s:4:"base";s:16:"handler_settings";a:2:{s:14:"target_bundles";a:1:{s:7:"article";s:7:"article";}s:4:"sort";a:1:{s:4:"type";s:4:"none";}}}s:7:"storage";a:5:{s:4:"type";s:17:"field_sql_storage";s:8:"settings";a:0:{}s:6:"module";s:17:"field_sql_storage";s:6:"active";s:1:"1";s:7:"details";a:1:{s:3:"sql";a:2:{s:18:"FIELD_LOAD_CURRENT";a:1:{s:26:"field_data_field_reference";a:1:{s:9:"target_id";s:25:"field_reference_target_id";}}s:19:"FIELD_LOAD_REVISION";a:1:{s:30:"field_revision_field_reference";a:1:{s:9:"target_id";s:25:"field_reference_target_id";}}}}}s:12:"foreign keys";a:1:{s:4:"node";a:2:{s:5:"table";s:4:"node";s:7:"columns";a:1:{s:9:"target_id";s:3:"nid";}}}s:7:"indexes";a:1:{s:9:"target_id";a:1:{i:0;s:9:"target_id";}}s:2:"id";s:2:"37";}', + 'cardinality' => '1', + 'translatable' => '0', + 'deleted' => '0', +)) +->values(array( + 'id' => '39', + 'field_name' => 'field_reference_2', + 'type' => 'entityreference', + 'module' => 'entityreference', + 'active' => '1', + 'storage_type' => 'field_sql_storage', + 'storage_module' => 'field_sql_storage', + 'storage_active' => '1', + 'locked' => '0', + 'data' => 'a:7:{s:12:"translatable";s:1:"0";s:12:"entity_types";a:0:{}s:8:"settings";a:3:{s:11:"target_type";s:4:"node";s:7:"handler";s:4:"base";s:16:"handler_settings";a:2:{s:14:"target_bundles";a:1:{s:7:"article";s:7:"article";}s:4:"sort";a:1:{s:4:"type";s:4:"none";}}}s:7:"storage";a:5:{s:4:"type";s:17:"field_sql_storage";s:8:"settings";a:0:{}s:6:"module";s:17:"field_sql_storage";s:6:"active";s:1:"1";s:7:"details";a:1:{s:3:"sql";a:2:{s:18:"FIELD_LOAD_CURRENT";a:1:{s:28:"field_data_field_reference_2";a:1:{s:9:"target_id";s:27:"field_reference_2_target_id";}}s:19:"FIELD_LOAD_REVISION";a:1:{s:32:"field_revision_field_reference_2";a:1:{s:9:"target_id";s:27:"field_reference_2_target_id";}}}}}s:12:"foreign keys";a:1:{s:4:"node";a:2:{s:5:"table";s:4:"node";s:7:"columns";a:1:{s:9:"target_id";s:3:"nid";}}}s:7:"indexes";a:1:{s:9:"target_id";a:1:{i:0;s:9:"target_id";}}s:2:"id";s:2:"39";}', + 'cardinality' => '1', + 'translatable' => '0', + 'deleted' => '0', +)) ->execute(); $connection->schema()->createTable('field_config_instance', array( @@ -4206,6 +4453,33 @@ 'data' => 'a:6:{s:5:"label";s:17:"Date without time";s:6:"widget";a:5:{s:6:"weight";s:1:"2";s:4:"type";s:11:"date_select";s:6:"module";s:4:"date";s:6:"active";i:1;s:8:"settings";a:6:{s:12:"input_format";s:13:"m/d/Y - H:i:s";s:19:"input_format_custom";s:0:"";s:10:"year_range";s:5:"-3:+3";s:9:"increment";s:2:"15";s:14:"label_position";s:5:"above";s:10:"text_parts";a:0:{}}}s:8:"settings";a:5:{s:13:"default_value";s:3:"now";s:18:"default_value_code";s:0:"";s:14:"default_value2";s:4:"same";s:19:"default_value_code2";s:0:"";s:18:"user_register_form";b:0;}s:7:"display";a:1:{s:7:"default";a:5:{s:5:"label";s:5:"above";s:4:"type";s:12:"date_default";s:6:"weight";s:1:"3";s:8:"settings";a:5:{s:11:"format_type";s:4:"long";s:15:"multiple_number";s:0:"";s:13:"multiple_from";s:0:"";s:11:"multiple_to";s:0:"";s:6:"fromto";s:4:"both";}s:6:"module";s:4:"date";}}s:8:"required";i:0;s:11:"description";s:0:"";}', 'deleted' => '0', )) +->values(array( + 'id' => '63', + 'field_id' => '37', + 'field_name' => 'field_float_list', + 'entity_type' => 'node', + 'bundle' => 'test_content_type', + 'data' => 'a:7:{s:5:"label";s:10:"Float List";s:6:"widget";a:5:{s:6:"weight";s:2:"20";s:4:"type";s:14:"options_select";s:6:"module";s:7:"options";s:6:"active";i:1;s:8:"settings";a:0:{}}s:8:"settings";a:1:{s:18:"user_register_form";b:0;}s:7:"display";a:1:{s:7:"default";a:5:{s:5:"label";s:5:"above";s:4:"type";s:12:"list_default";s:8:"settings";a:0:{}s:6:"module";s:4:"list";s:6:"weight";i:19;}}s:8:"required";i:0;s:11:"description";s:0:"";s:13:"default_value";N;}', + 'deleted' => '0', +)) +->values(array( + 'id' => '64', + 'field_id' => '38', + 'field_name' => 'field_reference', + 'entity_type' => 'node', + 'bundle' => 'article', + 'data' => 'a:7:{s:5:"label";s:9:"Reference";s:6:"widget";a:5:{s:6:"weight";s:2:"20";s:4:"type";s:14:"options_select";s:6:"module";s:7:"options";s:6:"active";i:1;s:8:"settings";a:0:{}}s:8:"settings";a:1:{s:18:"user_register_form";b:0;}s:7:"display";a:1:{s:7:"default";a:5:{s:5:"label";s:5:"above";s:4:"type";s:21:"entityreference_label";s:6:"weight";s:2:"20";s:8:"settings";a:2:{s:13:"bypass_access";i:0;s:4:"link";i:1;}s:6:"module";s:15:"entityreference";}}s:8:"required";i:0;s:11:"description";s:0:"";s:13:"default_value";N;}', + 'deleted' => '0', +)) +->values(array( + 'id' => '65', + 'field_id' => '39', + 'field_name' => 'field_reference_2', + 'entity_type' => 'node', + 'bundle' => 'article', + 'data' => 'a:6:{s:5:"label";s:11:"Reference 2";s:6:"widget";a:4:{s:4:"type";s:14:"options_select";s:6:"weight";s:2:"21";s:8:"settings";a:0:{}s:6:"module";s:7:"options";}s:8:"settings";a:1:{s:18:"user_register_form";b:0;}s:7:"display";a:1:{s:7:"default";a:5:{s:5:"label";s:5:"above";s:4:"type";s:21:"entityreference_label";s:8:"settings";a:2:{s:4:"link";b:0;s:13:"bypass_access";b:0;}s:6:"module";s:15:"entityreference";s:6:"weight";i:21;}}s:8:"required";b:0;s:11:"description";s:0:"";}', + 'deleted' => '0', +)) ->execute(); $connection->schema()->createTable('field_data_body', array( @@ -5120,6 +5394,112 @@ )) ->execute(); +$connection->schema()->createTable('field_data_field_float_list', array( + 'fields' => array( + 'entity_type' => array( + 'type' => 'varchar', + 'not null' => TRUE, + 'length' => '128', + 'default' => '', + ), + 'bundle' => array( + 'type' => 'varchar', + 'not null' => TRUE, + 'length' => '128', + 'default' => '', + ), + 'deleted' => array( + 'type' => 'int', + 'not null' => TRUE, + 'size' => 'tiny', + 'default' => '0', + ), + 'entity_id' => array( + 'type' => 'int', + 'not null' => TRUE, + 'size' => 'normal', + 'unsigned' => TRUE, + ), + 'revision_id' => array( + 'type' => 'int', + 'not null' => FALSE, + 'size' => 'normal', + 'unsigned' => TRUE, + ), + 'language' => array( + 'type' => 'varchar', + 'not null' => TRUE, + 'length' => '32', + 'default' => '', + ), + 'delta' => array( + 'type' => 'int', + 'not null' => TRUE, + 'size' => 'normal', + 'unsigned' => TRUE, + ), + 'field_float_list_value' => array( + 'type' => 'float', + 'not null' => FALSE, + 'size' => 'normal', + ), + ), + 'primary key' => array( + 'entity_type', + 'entity_id', + 'deleted', + 'delta', + 'language', + ), + 'indexes' => array( + 'entity_type' => array( + 'entity_type', + ), + 'bundle' => array( + 'bundle', + ), + 'deleted' => array( + 'deleted', + ), + 'entity_id' => array( + 'entity_id', + ), + 'revision_id' => array( + 'revision_id', + ), + 'language' => array( + 'language', + ), + 'field_float_list_value' => array( + 'field_float_list_value', + ), + ), + 'mysql_character_set' => 'utf8', +)); + +$connection->insert('field_data_field_float_list') +->fields(array( + 'entity_type', + 'bundle', + 'deleted', + 'entity_id', + 'revision_id', + 'language', + 'delta', + 'field_float_list_value', +)) +->values(array( + 'entity_type' => 'node', + 'bundle' => 'test_content_type', + 'deleted' => '0', + 'entity_id' => '1', + 'revision_id' => '1', + 'language' => 'und', + 'delta' => '0', + 'field_float_list_value' => '3.1416', +)) +->execute(); + $connection->schema()->createTable('field_data_field_image', array( 'fields' => array( 'entity_type' => array( @@ -5394,7 +5774,7 @@ 'deleted' => '0', 'entity_id' => '1', 'revision_id' => '1', - 'language' => 'und', + 'language' => 'en', 'delta' => '0', 'field_integer_value' => '5', )) @@ -5404,7 +5784,7 @@ 'deleted' => '0', 'entity_id' => '2', 'revision_id' => '2', - 'language' => 'und', + 'language' => 'en', 'delta' => '0', 'field_integer_value' => '99', )) @@ -5414,7 +5794,7 @@ 'deleted' => '0', 'entity_id' => '4', 'revision_id' => '4', - 'language' => 'und', + 'language' => 'en', 'delta' => '0', 'field_integer_value' => '6', )) @@ -6007,6 +6387,280 @@ )) ->execute(); +$connection->schema()->createTable('field_data_field_reference', array( + 'fields' => array( + 'entity_type' => array( + 'type' => 'varchar', + 'not null' => TRUE, + 'length' => '128', + 'default' => '', + ), + 'bundle' => array( + 'type' => 'varchar', + 'not null' => TRUE, + 'length' => '128', + 'default' => '', + ), + 'deleted' => array( + 'type' => 'int', + 'not null' => TRUE, + 'size' => 'tiny', + 'default' => '0', + ), + 'entity_id' => array( + 'type' => 'int', + 'not null' => TRUE, + 'size' => 'normal', + 'unsigned' => TRUE, + ), + 'revision_id' => array( + 'type' => 'int', + 'not null' => FALSE, + 'size' => 'normal', + 'unsigned' => TRUE, + ), + 'language' => array( + 'type' => 'varchar', + 'not null' => TRUE, + 'length' => '32', + 'default' => '', + ), + 'delta' => array( + 'type' => 'int', + 'not null' => TRUE, + 'size' => 'normal', + 'unsigned' => TRUE, + ), + 'field_reference_target_id' => array( + 'type' => 'int', + 'not null' => TRUE, + 'size' => 'normal', + 'unsigned' => TRUE, + ), + ), + 'primary key' => array( + 'entity_type', + 'entity_id', + 'deleted', + 'delta', + 'language', + ), + 'indexes' => array( + 'entity_type' => array( + 'entity_type', + ), + 'bundle' => array( + 'bundle', + ), + 'deleted' => array( + 'deleted', + ), + 'entity_id' => array( + 'entity_id', + ), + 'revision_id' => array( + 'revision_id', + ), + 'language' => array( + 'language', + ), + 'field_reference_target_id' => array( + 'field_reference_target_id', + ), + ), + 'mysql_character_set' => 'utf8', +)); + +$connection->insert('field_data_field_reference') +->fields(array( + 'entity_type', + 'bundle', + 'deleted', + 'entity_id', + 'revision_id', + 'language', + 'delta', + 'field_reference_target_id', +)) +->values(array( + 'entity_type' => 'node', + 'bundle' => 'article', + 'deleted' => '0', + 'entity_id' => '2', + 'revision_id' => '2', + 'language' => 'und', + 'delta' => '0', + 'field_reference_target_id' => '5', +)) +->values(array( + 'entity_type' => 'node', + 'bundle' => 'article', + 'deleted' => '0', + 'entity_id' => '3', + 'revision_id' => '3', + 'language' => 'und', + 'delta' => '0', + 'field_reference_target_id' => '4', +)) +->values(array( + 'entity_type' => 'node', + 'bundle' => 'article', + 'deleted' => '0', + 'entity_id' => '4', + 'revision_id' => '4', + 'language' => 'und', + 'delta' => '0', + 'field_reference_target_id' => '3', +)) +->values(array( + 'entity_type' => 'node', + 'bundle' => 'article', + 'deleted' => '0', + 'entity_id' => '5', + 'revision_id' => '5', + 'language' => 'und', + 'delta' => '0', + 'field_reference_target_id' => '2', +)) +->execute(); + +$connection->schema()->createTable('field_data_field_reference_2', array( + 'fields' => array( + 'entity_type' => array( + 'type' => 'varchar', + 'not null' => TRUE, + 'length' => '128', + 'default' => '', + ), + 'bundle' => array( + 'type' => 'varchar', + 'not null' => TRUE, + 'length' => '128', + 'default' => '', + ), + 'deleted' => array( + 'type' => 'int', + 'not null' => TRUE, + 'size' => 'tiny', + 'default' => '0', + ), + 'entity_id' => array( + 'type' => 'int', + 'not null' => TRUE, + 'size' => 'normal', + 'unsigned' => TRUE, + ), + 'revision_id' => array( + 'type' => 'int', + 'not null' => FALSE, + 'size' => 'normal', + 'unsigned' => TRUE, + ), + 'language' => array( + 'type' => 'varchar', + 'not null' => TRUE, + 'length' => '32', + 'default' => '', + ), + 'delta' => array( + 'type' => 'int', + 'not null' => TRUE, + 'size' => 'normal', + 'unsigned' => TRUE, + ), + 'field_reference_2_target_id' => array( + 'type' => 'int', + 'not null' => TRUE, + 'size' => 'normal', + 'unsigned' => TRUE, + ), + ), + 'primary key' => array( + 'entity_type', + 'entity_id', + 'deleted', + 'delta', + 'language', + ), + 'indexes' => array( + 'entity_type' => array( + 'entity_type', + ), + 'bundle' => array( + 'bundle', + ), + 'deleted' => array( + 'deleted', + ), + 'entity_id' => array( + 'entity_id', + ), + 'revision_id' => array( + 'revision_id', + ), + 'language' => array( + 'language', + ), + 'field_reference_2_target_id' => array( + 'field_reference_2_target_id', + ), + ), + 'mysql_character_set' => 'utf8', +)); + +$connection->insert('field_data_field_reference_2') +->fields(array( + 'entity_type', + 'bundle', + 'deleted', + 'entity_id', + 'revision_id', + 'language', + 'delta', + 'field_reference_2_target_id', +)) +->values(array( + 'entity_type' => 'node', + 'bundle' => 'article', + 'deleted' => '0', + 'entity_id' => '2', + 'revision_id' => '2', + 'language' => 'und', + 'delta' => '0', + 'field_reference_2_target_id' => '5', +)) +->values(array( + 'entity_type' => 'node', + 'bundle' => 'article', + 'deleted' => '0', + 'entity_id' => '3', + 'revision_id' => '3', + 'language' => 'und', + 'delta' => '0', + 'field_reference_2_target_id' => '4', +)) +->values(array( + 'entity_type' => 'node', + 'bundle' => 'article', + 'deleted' => '0', + 'entity_id' => '4', + 'revision_id' => '4', + 'language' => 'und', + 'delta' => '0', + 'field_reference_2_target_id' => '3', +)) +->values(array( + 'entity_type' => 'node', + 'bundle' => 'article', + 'deleted' => '0', + 'entity_id' => '5', + 'revision_id' => '5', + 'language' => 'und', + 'delta' => '0', + 'field_reference_2_target_id' => '2', +)) +->execute(); + $connection->schema()->createTable('field_data_field_tags', array( 'fields' => array( 'entity_type' => array( @@ -8479,6 +9133,113 @@ )) ->execute(); +$connection->schema()->createTable('field_revision_field_float_list', array( + 'fields' => array( + 'entity_type' => array( + 'type' => 'varchar', + 'not null' => TRUE, + 'length' => '128', + 'default' => '', + ), + 'bundle' => array( + 'type' => 'varchar', + 'not null' => TRUE, + 'length' => '128', + 'default' => '', + ), + 'deleted' => array( + 'type' => 'int', + 'not null' => TRUE, + 'size' => 'tiny', + 'default' => '0', + ), + 'entity_id' => array( + 'type' => 'int', + 'not null' => TRUE, + 'size' => 'normal', + 'unsigned' => TRUE, + ), + 'revision_id' => array( + 'type' => 'int', + 'not null' => TRUE, + 'size' => 'normal', + 'unsigned' => TRUE, + ), + 'language' => array( + 'type' => 'varchar', + 'not null' => TRUE, + 'length' => '32', + 'default' => '', + ), + 'delta' => array( + 'type' => 'int', + 'not null' => TRUE, + 'size' => 'normal', + 'unsigned' => TRUE, + ), + 'field_float_list_value' => array( + 'type' => 'float', + 'not null' => FALSE, + 'size' => 'normal', + ), + ), + 'primary key' => array( + 'entity_type', + 'entity_id', + 'revision_id', + 'deleted', + 'delta', + 'language', + ), + 'indexes' => array( + 'entity_type' => array( + 'entity_type', + ), + 'bundle' => array( + 'bundle', + ), + 'deleted' => array( + 'deleted', + ), + 'entity_id' => array( + 'entity_id', + ), + 'revision_id' => array( + 'revision_id', + ), + 'language' => array( + 'language', + ), + 'field_float_list_value' => array( + 'field_float_list_value', + ), + ), + 'mysql_character_set' => 'utf8', +)); + +$connection->insert('field_revision_field_float_list') +->fields(array( + 'entity_type', + 'bundle', + 'deleted', + 'entity_id', + 'revision_id', + 'language', + 'delta', + 'field_float_list_value', +)) +->values(array( + 'entity_type' => 'node', + 'bundle' => 'test_content_type', + 'deleted' => '0', + 'entity_id' => '1', + 'revision_id' => '1', + 'language' => 'und', + 'delta' => '0', + 'field_float_list_value' => '3.1416', +)) +->execute(); + $connection->schema()->createTable('field_revision_field_image', array( 'fields' => array( 'entity_type' => array( @@ -8756,7 +9517,7 @@ 'deleted' => '0', 'entity_id' => '1', 'revision_id' => '1', - 'language' => 'und', + 'language' => 'en', 'delta' => '0', 'field_integer_value' => '5', )) @@ -8766,7 +9527,7 @@ 'deleted' => '0', 'entity_id' => '2', 'revision_id' => '2', - 'language' => 'und', + 'language' => 'en', 'delta' => '0', 'field_integer_value' => '99', )) @@ -8776,7 +9537,7 @@ 'deleted' => '0', 'entity_id' => '4', 'revision_id' => '4', - 'language' => 'und', + 'language' => 'en', 'delta' => '0', 'field_integer_value' => '6', )) @@ -9385,6 +10146,282 @@ )) ->execute(); +$connection->schema()->createTable('field_revision_field_reference', array( + 'fields' => array( + 'entity_type' => array( + 'type' => 'varchar', + 'not null' => TRUE, + 'length' => '128', + 'default' => '', + ), + 'bundle' => array( + 'type' => 'varchar', + 'not null' => TRUE, + 'length' => '128', + 'default' => '', + ), + 'deleted' => array( + 'type' => 'int', + 'not null' => TRUE, + 'size' => 'tiny', + 'default' => '0', + ), + 'entity_id' => array( + 'type' => 'int', + 'not null' => TRUE, + 'size' => 'normal', + 'unsigned' => TRUE, + ), + 'revision_id' => array( + 'type' => 'int', + 'not null' => TRUE, + 'size' => 'normal', + 'unsigned' => TRUE, + ), + 'language' => array( + 'type' => 'varchar', + 'not null' => TRUE, + 'length' => '32', + 'default' => '', + ), + 'delta' => array( + 'type' => 'int', + 'not null' => TRUE, + 'size' => 'normal', + 'unsigned' => TRUE, + ), + 'field_reference_target_id' => array( + 'type' => 'int', + 'not null' => TRUE, + 'size' => 'normal', + 'unsigned' => TRUE, + ), + ), + 'primary key' => array( + 'entity_type', + 'entity_id', + 'revision_id', + 'deleted', + 'delta', + 'language', + ), + 'indexes' => array( + 'entity_type' => array( + 'entity_type', + ), + 'bundle' => array( + 'bundle', + ), + 'deleted' => array( + 'deleted', + ), + 'entity_id' => array( + 'entity_id', + ), + 'revision_id' => array( + 'revision_id', + ), + 'language' => array( + 'language', + ), + 'field_reference_target_id' => array( + 'field_reference_target_id', + ), + ), + 'mysql_character_set' => 'utf8', +)); + +$connection->insert('field_revision_field_reference') +->fields(array( + 'entity_type', + 'bundle', + 'deleted', + 'entity_id', + 'revision_id', + 'language', + 'delta', + 'field_reference_target_id', +)) +->values(array( + 'entity_type' => 'node', + 'bundle' => 'article', + 'deleted' => '0', + 'entity_id' => '2', + 'revision_id' => '2', + 'language' => 'und', + 'delta' => '0', + 'field_reference_target_id' => '5', +)) +->values(array( + 'entity_type' => 'node', + 'bundle' => 'article', + 'deleted' => '0', + 'entity_id' => '3', + 'revision_id' => '3', + 'language' => 'und', + 'delta' => '0', + 'field_reference_target_id' => '4', +)) +->values(array( + 'entity_type' => 'node', + 'bundle' => 'article', + 'deleted' => '0', + 'entity_id' => '4', + 'revision_id' => '4', + 'language' => 'und', + 'delta' => '0', + 'field_reference_target_id' => '3', +)) +->values(array( + 'entity_type' => 'node', + 'bundle' => 'article', + 'deleted' => '0', + 'entity_id' => '5', + 'revision_id' => '5', + 'language' => 'und', + 'delta' => '0', + 'field_reference_target_id' => '2', +)) +->execute(); + +$connection->schema()->createTable('field_revision_field_reference_2', array( + 'fields' => array( + 'entity_type' => array( + 'type' => 'varchar', + 'not null' => TRUE, + 'length' => '128', + 'default' => '', + ), + 'bundle' => array( + 'type' => 'varchar', + 'not null' => TRUE, + 'length' => '128', + 'default' => '', + ), + 'deleted' => array( + 'type' => 'int', + 'not null' => TRUE, + 'size' => 'tiny', + 'default' => '0', + ), + 'entity_id' => array( + 'type' => 'int', + 'not null' => TRUE, + 'size' => 'normal', + 'unsigned' => TRUE, + ), + 'revision_id' => array( + 'type' => 'int', + 'not null' => TRUE, + 'size' => 'normal', + 'unsigned' => TRUE, + ), + 'language' => array( + 'type' => 'varchar', + 'not null' => TRUE, + 'length' => '32', + 'default' => '', + ), + 'delta' => array( + 'type' => 'int', + 'not null' => TRUE, + 'size' => 'normal', + 'unsigned' => TRUE, + ), + 'field_reference_2_target_id' => array( + 'type' => 'int', + 'not null' => TRUE, + 'size' => 'normal', + 'unsigned' => TRUE, + ), + ), + 'primary key' => array( + 'entity_type', + 'entity_id', + 'revision_id', + 'deleted', + 'delta', + 'language', + ), + 'indexes' => array( + 'entity_type' => array( + 'entity_type', + ), + 'bundle' => array( + 'bundle', + ), + 'deleted' => array( + 'deleted', + ), + 'entity_id' => array( + 'entity_id', + ), + 'revision_id' => array( + 'revision_id', + ), + 'language' => array( + 'language', + ), + 'field_reference_2_target_id' => array( + 'field_reference_2_target_id', + ), + ), + 'mysql_character_set' => 'utf8', +)); + +$connection->insert('field_revision_field_reference_2') +->fields(array( + 'entity_type', + 'bundle', + 'deleted', + 'entity_id', + 'revision_id', + 'language', + 'delta', + 'field_reference_2_target_id', +)) +->values(array( + 'entity_type' => 'node', + 'bundle' => 'article', + 'deleted' => '0', + 'entity_id' => '2', + 'revision_id' => '2', + 'language' => 'und', + 'delta' => '0', + 'field_reference_2_target_id' => '5', +)) +->values(array( + 'entity_type' => 'node', + 'bundle' => 'article', + 'deleted' => '0', + 'entity_id' => '3', + 'revision_id' => '3', + 'language' => 'und', + 'delta' => '0', + 'field_reference_2_target_id' => '4', +)) +->values(array( + 'entity_type' => 'node', + 'bundle' => 'article', + 'deleted' => '0', + 'entity_id' => '4', + 'revision_id' => '4', + 'language' => 'und', + 'delta' => '0', + 'field_reference_2_target_id' => '3', +)) +->values(array( + 'entity_type' => 'node', + 'bundle' => 'article', + 'deleted' => '0', + 'entity_id' => '5', + 'revision_id' => '5', + 'language' => 'und', + 'delta' => '0', + 'field_reference_2_target_id' => '2', +)) +->execute(); + $connection->schema()->createTable('field_revision_field_tags', array( 'fields' => array( 'entity_type' => array( @@ -22957,6 +23994,249 @@ 'p9' => '0', 'updated' => '0', )) + ->values(array( + 'menu_name' => 'book-toc-1', + 'mlid' => '480', + 'plid' => '0', + 'link_path' => 'node/4', + 'router_path' => 'node/%', + 'link_title' => 'Test top book title', + 'options' => 'a:0:{}', + 'module' => 'book', + 'hidden' => '0', + 'external' => '0', + 'has_children' => '1', + 'expanded' => '0', + 'weight' => '-10', + 'depth' => '1', + 'customized' => '0', + 'p1' => '480', + 'p2' => '0', + 'p3' => '0', + 'p4' => '0', + 'p5' => '0', + 'p6' => '0', + 'p7' => '0', + 'p8' => '0', + 'p9' => '0', + 'updated' => '0', + )) + ->values(array( + 'menu_name' => 'book-toc-1', + 'mlid' => '481', + 'plid' => '480', + 'link_path' => 'node/6', + 'router_path' => 'node/%', + 'link_title' => 'Test book title child 1', + 'options' => 'a:0:{}', + 'module' => 'book', + 'hidden' => '0', + 'external' => '0', + 'has_children' => '1', + 'expanded' => '0', + 'weight' => '0', + 'depth' => '2', + 'customized' => '0', + 'p1' => '480', + 'p2' => '481', + 'p3' => '0', + 'p4' => '0', + 'p5' => '0', + 'p6' => '0', + 'p7' => '0', + 'p8' => '0', + 'p9' => '0', + 'updated' => '0', + )) + ->values(array( + 'menu_name' => 'book-toc-1', + 'mlid' => '482', + 'plid' => '481', + 'link_path' => 'node/2', + 'router_path' => 'node/%', + 'link_title' => 'Test book title child 1.1', + 'options' => 'a:0:{}', + 'module' => 'book', + 'hidden' => '0', + 'external' => '0', + 'has_children' => '0', + 'expanded' => '0', + 'weight' => '0', + 'depth' => '3', + 'customized' => '0', + 'p1' => '480', + 'p2' => '481', + 'p3' => '482', + 'p4' => '0', + 'p5' => '0', + 'p6' => '0', + 'p7' => '0', + 'p8' => '0', + 'p9' => '0', + 'updated' => '0', + )) + ->values(array( + 'menu_name' => 'book-toc-2', + 'mlid' => '483', + 'plid' => '481', + 'link_path' => 'node/1', + 'router_path' => 'node/%', + 'link_title' => 'Test book title 2', + 'options' => 'a:0:{}', + 'module' => 'book', + 'hidden' => '0', + 'external' => '0', + 'has_children' => '0', + 'expanded' => '0', + 'weight' => '0', + 'depth' => '3', + 'customized' => '0', + 'p1' => '480', + 'p2' => '481', + 'p3' => '483', + 'p4' => '0', + 'p5' => '0', + 'p6' => '0', + 'p7' => '0', + 'p8' => '0', + 'p9' => '0', + 'updated' => '0', + )) +->values(array( + 'menu_name' => 'navigation', + 'mlid' => '484', + 'plid' => '0', + 'link_path' => 'node/2', + 'router_path' => 'node/%', + 'link_title' => 'The thing about Deep Space 9', + 'options' => 'a:1:{s:10:"attributes";a:1:{s:5:"title";s:0:"";}}', + 'module' => 'menu', + 'hidden' => '0', + 'external' => '0', + 'has_children' => '0', + 'expanded' => '0', + 'weight' => '9', + 'depth' => '1', + 'customized' => '1', + 'p1' => '484', + 'p2' => '0', + 'p3' => '0', + 'p4' => '0', + 'p5' => '0', + 'p6' => '0', + 'p7' => '0', + 'p8' => '0', + 'p9' => '0', + 'updated' => '0', +)) +->values(array( + 'menu_name' => 'navigation', + 'mlid' => '485', + 'plid' => '0', + 'link_path' => 'node/3', + 'router_path' => 'node/%', + 'link_title' => 'is - The thing about Deep Space 9', + 'options' => 'a:1:{s:10:"attributes";a:1:{s:5:"title";s:0:"";}}', + 'module' => 'menu', + 'hidden' => '0', + 'external' => '0', + 'has_children' => '0', + 'expanded' => '0', + 'weight' => '10', + 'depth' => '1', + 'customized' => '1', + 'p1' => '485', + 'p2' => '0', + 'p3' => '0', + 'p4' => '0', + 'p5' => '0', + 'p6' => '0', + 'p7' => '0', + 'p8' => '0', + 'p9' => '0', + 'updated' => '0', +)) +->values(array( + 'menu_name' => 'navigation', + 'mlid' => '486', + 'plid' => '0', + 'link_path' => 'node/4', + 'router_path' => 'node/%', + 'link_title' => 'is - The thing about Firefly', + 'options' => 'a:1:{s:10:"attributes";a:1:{s:5:"title";s:0:"";}}', + 'module' => 'menu', + 'hidden' => '0', + 'external' => '0', + 'has_children' => '0', + 'expanded' => '0', + 'weight' => '11', + 'depth' => '1', + 'customized' => '1', + 'p1' => '486', + 'p2' => '0', + 'p3' => '0', + 'p4' => '0', + 'p5' => '0', + 'p6' => '0', + 'p7' => '0', + 'p8' => '0', + 'p9' => '0', + 'updated' => '0', +)) +->values(array( + 'menu_name' => 'navigation', + 'mlid' => '487', + 'plid' => '0', + 'link_path' => 'node/5', + 'router_path' => 'node/%', + 'link_title' => 'en - The thing about Firefly', + 'options' => 'a:1:{s:10:"attributes";a:1:{s:5:"title";s:0:"";}}', + 'module' => 'menu', + 'hidden' => '0', + 'external' => '0', + 'has_children' => '0', + 'expanded' => '0', + 'weight' => '12', + 'depth' => '1', + 'customized' => '1', + 'p1' => '487', + 'p2' => '0', + 'p3' => '0', + 'p4' => '0', + 'p5' => '0', + 'p6' => '0', + 'p7' => '0', + 'p8' => '0', + 'p9' => '0', + 'updated' => '0', +)) +->values(array( + 'menu_name' => 'management', + 'mlid' => '491', + 'plid' => '48', + 'link_path' => 'admin/config/regional/entity_translation', + 'router_path' => 'admin/config/regional/entity_translation', + 'link_title' => 'Entity translation', + 'options' => 'a:1:{s:10:"attributes";a:1:{s:5:"title";s:83:"Configure which entities can be translated and enable or disable language fallback.";}}', + 'module' => 'system', + 'hidden' => '0', + 'external' => '0', + 'has_children' => '1', + 'expanded' => '0', + 'weight' => '0', + 'depth' => '4', + 'customized' => '0', + 'p1' => '1', + 'p2' => '8', + 'p3' => '48', + 'p4' => '491', + 'p5' => '0', + 'p6' => '0', + 'p7' => '0', + 'p8' => '0', + 'p9' => '0', + 'updated' => '0', +)) ->execute(); $connection->schema()->createTable('menu_router', array( @@ -24902,6 +26182,31 @@ 'include_file' => 'modules/system/system.admin.inc', )) ->values(array( + 'path' => 'admin/config/regional/entity_translation', + 'load_functions' => '', + 'to_arg_functions' => '', + 'access_callback' => 'user_access', + 'access_arguments' => 'a:1:{i:0;s:29:"administer entity translation";}', + 'page_callback' => 'drupal_get_form', + 'page_arguments' => 'a:1:{i:0;s:29:"entity_translation_admin_form";}', + 'delivery_callback' => '', + 'fit' => '15', + 'number_parts' => '4', + 'context' => '0', + 'tab_parent' => '', + 'tab_root' => 'admin/config/regional/entity_translation', + 'title' => 'Entity translation', + 'title_callback' => 't', + 'title_arguments' => '', + 'theme_callback' => '', + 'theme_arguments' => 'a:0:{}', + 'type' => '6', + 'description' => 'Configure which entities can be translated and enable or disable language fallback.', + 'position' => '', + 'weight' => '0', + 'include_file' => 'sites/all/modules/entity_translation/entity_translation.admin.inc', +)) +->values(array( 'path' => 'admin/config/regional/language', 'load_functions' => '', 'to_arg_functions' => '', @@ -36619,6 +37924,55 @@ 'weight' => '0', )) ->values(array( + 'name' => 'EntityTranslationCommentHandler', + 'type' => 'class', + 'filename' => 'sites/all/modules/entity_translation/includes/translation.handler.comment.inc', + 'module' => 'entity_translation', + 'weight' => '11', +)) +->values(array( + 'name' => 'EntityTranslationDefaultHandler', + 'type' => 'class', + 'filename' => 'sites/all/modules/entity_translation/includes/translation.handler.inc', + 'module' => 'entity_translation', + 'weight' => '11', +)) +->values(array( + 'name' => 'EntityTranslationHandlerFactory', + 'type' => 'class', + 'filename' => 'sites/all/modules/entity_translation/includes/translation.handler_factory.inc', + 'module' => 'entity_translation', + 'weight' => '11', +)) +->values(array( + 'name' => 'EntityTranslationHandlerInterface', + 'type' => 'interface', + 'filename' => 'sites/all/modules/entity_translation/includes/translation.handler.inc', + 'module' => 'entity_translation', + 'weight' => '11', +)) +->values(array( + 'name' => 'EntityTranslationNodeHandler', + 'type' => 'class', + 'filename' => 'sites/all/modules/entity_translation/includes/translation.handler.node.inc', + 'module' => 'entity_translation', + 'weight' => '11', +)) +->values(array( + 'name' => 'EntityTranslationTaxonomyTermHandler', + 'type' => 'class', + 'filename' => 'sites/all/modules/entity_translation/includes/translation.handler.taxonomy_term.inc', + 'module' => 'entity_translation', + 'weight' => '11', +)) +->values(array( + 'name' => 'EntityTranslationUserHandler', + 'type' => 'class', + 'filename' => 'sites/all/modules/entity_translation/includes/translation.handler.user.inc', + 'module' => 'entity_translation', + 'weight' => '11', +)) +->values(array( 'name' => 'EntityValueWrapper', 'type' => 'class', 'filename' => 'sites/all/modules/entity/includes/entity.wrapper.inc', @@ -36633,6 +37987,55 @@ 'weight' => '0', )) ->values(array( + 'name' => 'entity_translation_handler_field_field', + 'type' => 'class', + 'filename' => 'sites/all/modules/entity_translation/views/entity_translation_handler_field_field.inc', + 'module' => 'entity_translation', + 'weight' => '11', +)) +->values(array( + 'name' => 'entity_translation_handler_field_label', + 'type' => 'class', + 'filename' => 'sites/all/modules/entity_translation/views/entity_translation_handler_field_label.inc', + 'module' => 'entity_translation', + 'weight' => '11', +)) +->values(array( + 'name' => 'entity_translation_handler_field_translate_link', + 'type' => 'class', + 'filename' => 'sites/all/modules/entity_translation/views/entity_translation_handler_field_translate_link.inc', + 'module' => 'entity_translation', + 'weight' => '11', +)) +->values(array( + 'name' => 'entity_translation_handler_filter_entity_type', + 'type' => 'class', + 'filename' => 'sites/all/modules/entity_translation/views/entity_translation_handler_filter_entity_type.inc', + 'module' => 'entity_translation', + 'weight' => '11', +)) +->values(array( + 'name' => 'entity_translation_handler_filter_language', + 'type' => 'class', + 'filename' => 'sites/all/modules/entity_translation/views/entity_translation_handler_filter_language.inc', + 'module' => 'entity_translation', + 'weight' => '11', +)) +->values(array( + 'name' => 'entity_translation_handler_filter_translation_exists', + 'type' => 'class', + 'filename' => 'sites/all/modules/entity_translation/views/entity_translation_handler_filter_translation_exists.inc', + 'module' => 'entity_translation', + 'weight' => '11', +)) +->values(array( + 'name' => 'entity_translation_handler_relationship', + 'type' => 'class', + 'filename' => 'sites/all/modules/entity_translation/views/entity_translation_handler_relationship.inc', + 'module' => 'entity_translation', + 'weight' => '11', +)) +->values(array( 'name' => 'entity_views_handler_area_entity', 'type' => 'class', 'filename' => 'sites/all/modules/entity/views/handlers/entity_views_handler_area_entity.inc', @@ -44838,7 +46241,7 @@ 'name' => 'ctools', 'type' => 'module', 'owner' => '', - 'status' => '0', + 'status' => '1', 'bootstrap' => '0', 'schema_version' => '6008', 'weight' => '0', @@ -45175,6 +46578,17 @@ 'info' => 'a:13:{s:4:"name";s:41:"Entityreference - Feeds integration tests";s:11:"description";s:65:"Support module for the Entityreference - Feeds integration tests.";s:7:"package";s:7:"Testing";s:4:"core";s:3:"7.x";s:6:"hidden";b:1;s:12:"dependencies";a:3:{i:0;s:5:"feeds";i:1;s:8:"feeds_ui";i:2;s:15:"entityreference";}s:7:"version";s:7:"7.x-1.1";s:7:"project";s:15:"entityreference";s:9:"datestamp";s:10:"1384973110";s:5:"mtime";i:1384973110;s:3:"php";s:5:"5.2.4";s:5:"files";a:0:{}s:9:"bootstrap";i:0;}', )) ->values(array( + 'filename' => 'sites/all/modules/entity_translation/entity_translation.module', + 'name' => 'entity_translation', + 'type' => 'module', + 'owner' => '', + 'status' => '1', + 'bootstrap' => '0', + 'schema_version' => '7009', + 'weight' => '11', + 'info' => 'a:14:{s:4:"name";s:18:"Entity Translation";s:11:"description";s:58:"Allows entities to be translated into different languages.";s:7:"package";s:33:"Multilingual - Entity Translation";s:4:"core";s:3:"7.x";s:9:"configure";s:40:"admin/config/regional/entity_translation";s:12:"dependencies";a:1:{i:0;s:14:"locale (>7.14)";}s:17:"test_dependencies";a:2:{i:0;s:17:"pathauto:pathauto";i:1;s:5:"title";}s:5:"files";a:15:{i:0;s:40:"includes/translation.handler_factory.inc";i:1;s:32:"includes/translation.handler.inc";i:2;s:40:"includes/translation.handler.comment.inc";i:3;s:37:"includes/translation.handler.node.inc";i:4;s:46:"includes/translation.handler.taxonomy_term.inc";i:5;s:37:"includes/translation.handler.user.inc";i:6;s:32:"includes/translation.migrate.inc";i:7;s:29:"tests/entity_translation.test";i:8;s:49:"views/entity_translation_handler_relationship.inc";i:9;s:57:"views/entity_translation_handler_field_translate_link.inc";i:10;s:48:"views/entity_translation_handler_field_label.inc";i:11;s:55:"views/entity_translation_handler_filter_entity_type.inc";i:12;s:52:"views/entity_translation_handler_filter_language.inc";i:13;s:62:"views/entity_translation_handler_filter_translation_exists.inc";i:14;s:48:"views/entity_translation_handler_field_field.inc";}s:7:"version";s:7:"7.x-1.0";s:7:"project";s:18:"entity_translation";s:9:"datestamp";s:10:"1522600694";s:5:"mtime";i:1522600694;s:3:"php";s:5:"5.2.4";s:9:"bootstrap";i:0;}', +)) +->values(array( 'filename' => 'sites/all/modules/link/link.module', 'name' => 'link', 'type' => 'module', @@ -46325,6 +47739,10 @@ 'value' => 'a:1:{i:0;s:4:"book";}', )) ->values(array( + 'name' => 'book_block_mode', + 'value' => 's:9:"all pages";', +)) +->values(array( 'name' => 'book_child_type', 'value' => 's:4:"book";', )) @@ -46377,6 +47795,46 @@ 'value' => 's:1:"1";', )) ->values(array( + 'name' => 'color_bartik_files', + 'value' => 'a:2:{i:0;s:39:"public://color/bartik-e0e23ad7/logo.png";i:1;s:41:"public://color/bartik-e0e23ad7/colors.css";}', +)) +->values(array( + 'name' => 'color_bartik_logo', + 'value' => 's:39:"public://color/bartik-e0e23ad7/logo.png";', +)) +->values(array( + 'name' => 'color_bartik_palette', + 'value' => 'a:9:{s:3:"top";s:7:"#d0d0d0";s:6:"bottom";s:7:"#c2c4c5";s:2:"bg";s:7:"#ffffff";s:7:"sidebar";s:7:"#ffffff";s:14:"sidebarborders";s:7:"#cccccc";s:6:"footer";s:7:"#24272c";s:11:"titleslogan";s:7:"#000000";s:4:"text";s:7:"#4a4a4a";s:4:"link";s:7:"#019dbf";}', +)) +->values(array( + 'name' => 'color_bartik_stylesheets', + 'value' => 'a:1:{i:0;s:41:"public://color/bartik-e0e23ad7/colors.css";}', +)) +->values(array( + 'name' => 'color_bartik_screenshot', + 'value' => 's:72:"/var/www/drupal/sites/default/files/color/bartik-b69cfcec/screenshot.png";' +)) +->values(array( + 'name' => 'color_garland_files', + 'value' => 'a:19:{i:0;s:50:"public://color/garland-b69cfcec/menu-collapsed.gif";i:1;s:54:"public://color/garland-b69cfcec/menu-collapsed-rtl.gif";i:2;s:49:"public://color/garland-b69cfcec/menu-expanded.gif";i:3;s:45:"public://color/garland-b69cfcec/menu-leaf.gif";i:4;s:67:"/var/www/drupal/sites/default/files/color/garland-b69cfcec/body.png";i:5;s:69:"/var/www/drupal/sites/default/files/color/garland-b69cfcec/bg-bar.png";i:6;s:75:"/var/www/drupal/sites/default/files/color/garland-b69cfcec/bg-bar-white.png";i:7;s:69:"/var/www/drupal/sites/default/files/color/garland-b69cfcec/bg-tab.png";i:8;s:76:"/var/www/drupal/sites/default/files/color/garland-b69cfcec/bg-navigation.png";i:9;s:78:"/var/www/drupal/sites/default/files/color/garland-b69cfcec/bg-content-left.png";i:10;s:79:"/var/www/drupal/sites/default/files/color/garland-b69cfcec/bg-content-right.png";i:11;s:73:"/var/www/drupal/sites/default/files/color/garland-b69cfcec/bg-content.png";i:12;s:81:"/var/www/drupal/sites/default/files/color/garland-b69cfcec/bg-navigation-item.png";i:13;s:87:"/var/www/drupal/sites/default/files/color/garland-b69cfcec/bg-navigation-item-hover.png";i:14;s:77:"/var/www/drupal/sites/default/files/color/garland-b69cfcec/gradient-inner.png";i:15;s:67:"/var/www/drupal/sites/default/files/color/garland-b69cfcec/logo.png";i:16;s:73:"/var/www/drupal/sites/default/files/color/garland-b69cfcec/screenshot.png";i:17;s:41:"public://color/garland-b69cfcec/style.css";i:18;s:45:"public://color/garland-b69cfcec/style-rtl.css";}', +)) +->values(array( + 'name' => 'color_garland_logo', + 'value' => 's:40:"public://color/garland-b69cfcec/logo.png";' +)) +->values(array( + 'name' => 'color_garland_palette', + 'value' => 'a:5:{s:4:"base";s:7:"#d0cb9a";s:4:"link";s:7:"#917803";s:3:"top";s:7:"#efde01";s:6:"bottom";s:7:"#e6fb2d";s:4:"text";s:7:"#494949";}', +)) +->values(array( + 'name' => 'color_garland_screenshot', + 'value' => 's:73:"/var/www/drupal/sites/default/files/color/garland-b69cfcec/screenshot.png";' +)) +->values(array( + 'name' => 'color_garland_stylesheets', + 'value' => 'a:2:{i:0;s:41:"public://color/garland-b69cfcec/style.css";i:1;s:45:"public://color/garland-b69cfcec/style-rtl.css";}', +)) +->values(array( 'name' => 'comment_anonymous_article', 'value' => 'i:0;', )) @@ -46633,6 +48091,30 @@ 'value' => 'b:1;', )) ->values(array( + 'name' => 'entity_translation_entity_types', + 'value' => 'a:4:{s:7:"comment";s:7:"comment";s:4:"node";s:4:"node";s:13:"taxonomy_term";s:13:"taxonomy_term";s:4:"user";s:4:"user";}', +)) +->values(array( + 'name' => 'entity_translation_settings_comment__comment_node_test_content_type', + 'value' => 'a:5:{s:16:"default_language";s:13:"xx-et-current";s:22:"hide_language_selector";i:1;s:21:"exclude_language_none";i:0;s:13:"lock_language";i:0;s:27:"shared_fields_original_only";i:0;}', +)) +->values(array( + 'name' => 'entity_translation_settings_node__test_content_type', + 'value' => 'a:5:{s:16:"default_language";s:3:"und";s:22:"hide_language_selector";i:0;s:21:"exclude_language_none";i:0;s:13:"lock_language";i:0;s:27:"shared_fields_original_only";i:0;}', +)) +->values(array( + 'name' => 'entity_translation_settings_taxonomy_term__test_vocabulary', + 'value' => 'a:5:{s:16:"default_language";s:13:"xx-et-default";s:22:"hide_language_selector";i:1;s:21:"exclude_language_none";i:0;s:13:"lock_language";i:0;s:27:"shared_fields_original_only";i:0;}', +)) +->values(array( + 'name' => 'entity_translation_settings_user__user', + 'value' => 'a:5:{s:16:"default_language";s:13:"xx-et-default";s:22:"hide_language_selector";i:1;s:21:"exclude_language_none";i:0;s:13:"lock_language";i:0;s:27:"shared_fields_original_only";i:0;}', +)) +->values(array( + 'name' => 'entity_translation_taxonomy', + 'value' => 'a:1:{s:15:"test_vocabulary";b:1;}', +)) +->values(array( 'name' => 'error_level', 'value' => 'i:1;', )) @@ -46774,7 +48256,7 @@ )) ->values(array( 'name' => 'language_content_type_test_content_type', - 'value' => 's:1:"0";', + 'value' => 's:1:"4";', )) ->values(array( 'name' => 'i18n_node_options_blog', diff -r e200cb7efeb3 -r c2387f117808 core/modules/migrate_drupal/tests/src/Kernel/CckFieldBackwardsCompatibilityTest.php --- a/core/modules/migrate_drupal/tests/src/Kernel/CckFieldBackwardsCompatibilityTest.php Thu Apr 26 11:26:54 2018 +0100 +++ b/core/modules/migrate_drupal/tests/src/Kernel/CckFieldBackwardsCompatibilityTest.php Tue Jul 10 15:07:59 2018 +0100 @@ -7,6 +7,7 @@ /** * @group migrate_drupal + * @group legacy */ class CckFieldBackwardsCompatibilityTest extends MigrateDrupal6TestBase { @@ -17,6 +18,8 @@ /** * Ensures that the cckfield backwards compatibility layer is invoked. + * + * @expectedDeprecation MigrateCckFieldInterface is deprecated in Drupal 8.3.x and will be removed before Drupal 9.0.x. Use \Drupal\migrate_drupal\Annotation\MigrateField instead. */ public function testBackwardsCompatibility() { $migration = $this->container diff -r e200cb7efeb3 -r c2387f117808 core/modules/migrate_drupal/tests/src/Kernel/Plugin/migrate/DestinationCategoryTest.php --- a/core/modules/migrate_drupal/tests/src/Kernel/Plugin/migrate/DestinationCategoryTest.php Thu Apr 26 11:26:54 2018 +0100 +++ b/core/modules/migrate_drupal/tests/src/Kernel/Plugin/migrate/DestinationCategoryTest.php Tue Jul 10 15:07:59 2018 +0100 @@ -3,6 +3,7 @@ namespace Drupal\Tests\migrate_drupal\Kernel\Plugin\migrate; use Drupal\ban\Plugin\migrate\destination\BlockedIP; +use Drupal\color\Plugin\migrate\destination\Color; use Drupal\KernelTests\FileSystemModuleDiscoveryDataProviderTrait; use Drupal\migrate\Plugin\migrate\destination\ComponentEntityDisplayBase; use Drupal\migrate\Plugin\migrate\destination\Config; @@ -98,6 +99,7 @@ */ protected function getConfigurationClasses() { return [ + Color::class, Config::class, EntityConfigBase::class, ThemeSettings::class, diff -r e200cb7efeb3 -r c2387f117808 core/modules/migrate_drupal/tests/src/Kernel/d6/EntityContentBaseTest.php --- a/core/modules/migrate_drupal/tests/src/Kernel/d6/EntityContentBaseTest.php Thu Apr 26 11:26:54 2018 +0100 +++ b/core/modules/migrate_drupal/tests/src/Kernel/d6/EntityContentBaseTest.php Tue Jul 10 15:07:59 2018 +0100 @@ -115,7 +115,7 @@ // Match the expected message. Can't use default argument types, because // we need to convert to string from TranslatableMarkup. $argument = Argument::that(function ($msg) { - return strpos((string) $msg, "This entity type does not support translation") !== FALSE; + return strpos((string) $msg, htmlentities('The "no_language_entity_test" entity type does not support translations.')) !== FALSE; }); $message->display($argument, Argument::any()) ->shouldBeCalled(); diff -r e200cb7efeb3 -r c2387f117808 core/modules/migrate_drupal/tests/src/Kernel/d6/FollowUpMigrationsTest.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/core/modules/migrate_drupal/tests/src/Kernel/d6/FollowUpMigrationsTest.php Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,78 @@ +executeMigrations([ + 'language', + 'd6_language_content_settings', + 'd6_node', + 'd6_node_translation', + ]); + } + + /** + * Test entity reference translations. + */ + public function testEntityReferenceTranslations() { + // Test the entity reference field before the follow-up migrations. + $node = Node::load(10); + $this->assertSame('13', $node->get('field_reference')->target_id); + $this->assertSame('13', $node->get('field_reference_2')->target_id); + $translation = $node->getTranslation('fr'); + $this->assertSame('20', $translation->get('field_reference')->target_id); + $this->assertSame('20', $translation->get('field_reference_2')->target_id); + + $node = Node::load(12)->getTranslation('en'); + $this->assertSame('10', $node->get('field_reference')->target_id); + $this->assertSame('10', $node->get('field_reference_2')->target_id); + $translation = $node->getTranslation('fr'); + $this->assertSame('11', $translation->get('field_reference')->target_id); + $this->assertSame('11', $translation->get('field_reference_2')->target_id); + + // Run the follow-up migrations. + $migration_plugin_manager = $this->container->get('plugin.manager.migration'); + $migration_plugin_manager->clearCachedDefinitions(); + $follow_up_migrations = $migration_plugin_manager->createInstances('d6_entity_reference_translation'); + $this->executeMigrations(array_keys($follow_up_migrations)); + + // Test the entity reference field after the follow-up migrations. + $node = Node::load(10); + $this->assertSame('12', $node->get('field_reference')->target_id); + $this->assertSame('12', $node->get('field_reference_2')->target_id); + $translation = $node->getTranslation('fr'); + $this->assertSame('12', $translation->get('field_reference')->target_id); + $this->assertSame('12', $translation->get('field_reference_2')->target_id); + + $node = Node::load(12)->getTranslation('en'); + $this->assertSame('10', $node->get('field_reference')->target_id); + $this->assertSame('10', $node->get('field_reference_2')->target_id); + $translation = $node->getTranslation('fr'); + $this->assertSame('10', $translation->get('field_reference')->target_id); + $this->assertSame('10', $translation->get('field_reference_2')->target_id); + } + +} diff -r e200cb7efeb3 -r c2387f117808 core/modules/migrate_drupal/tests/src/Kernel/d6/MigrateDrupal6AuditIdsTest.php --- a/core/modules/migrate_drupal/tests/src/Kernel/d6/MigrateDrupal6AuditIdsTest.php Thu Apr 26 11:26:54 2018 +0100 +++ b/core/modules/migrate_drupal/tests/src/Kernel/d6/MigrateDrupal6AuditIdsTest.php Tue Jul 10 15:07:59 2018 +0100 @@ -137,6 +137,7 @@ 'd6_taxonomy_term', 'd6_term_node_revision', 'd6_user', + 'node_translation_menu_links', ]; $this->assertEmpty(array_diff(array_filter($conflicts), $expected)); } diff -r e200cb7efeb3 -r c2387f117808 core/modules/migrate_drupal/tests/src/Kernel/d7/FollowUpMigrationsTest.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/core/modules/migrate_drupal/tests/src/Kernel/d7/FollowUpMigrationsTest.php Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,117 @@ +fileMigrationSetup(); + + $this->installEntitySchema('node'); + $this->installEntitySchema('comment'); + $this->installEntitySchema('taxonomy_term'); + $this->installConfig(static::$modules); + $this->installSchema('node', ['node_access']); + + $this->executeMigrations([ + 'language', + 'd7_user_role', + 'd7_user', + 'd7_node_type', + 'd7_language_content_settings', + 'd7_comment_type', + 'd7_taxonomy_vocabulary', + 'd7_field', + 'd7_field_instance', + 'd7_node', + 'd7_node_translation', + ]); + } + + /** + * {@inheritdoc} + */ + protected function getFileMigrationInfo() { + return [ + 'path' => 'public://sites/default/files/cube.jpeg', + 'size' => '3620', + 'base_path' => 'public://', + 'plugin_id' => 'd7_file', + ]; + } + + /** + * Test entity reference translations. + */ + public function testEntityReferenceTranslations() { + // Test the entity reference field before the follow-up migrations. + $node = Node::load(2); + $this->assertSame('5', $node->get('field_reference')->target_id); + $this->assertSame('5', $node->get('field_reference_2')->target_id); + $translation = $node->getTranslation('is'); + $this->assertSame('4', $translation->get('field_reference')->target_id); + $this->assertSame('4', $translation->get('field_reference_2')->target_id); + + $node = Node::load(4); + $this->assertSame('3', $node->get('field_reference')->target_id); + $this->assertSame('3', $node->get('field_reference_2')->target_id); + $translation = $node->getTranslation('en'); + $this->assertSame('2', $translation->get('field_reference')->target_id); + $this->assertSame('2', $translation->get('field_reference_2')->target_id); + + // Run the follow-up migrations. + $migration_plugin_manager = $this->container->get('plugin.manager.migration'); + $migration_plugin_manager->clearCachedDefinitions(); + $follow_up_migrations = $migration_plugin_manager->createInstances('d7_entity_reference_translation'); + $this->executeMigrations(array_keys($follow_up_migrations)); + + // Test the entity reference field after the follow-up migrations. + $node = Node::load(2); + $this->assertSame('4', $node->get('field_reference')->target_id); + $this->assertSame('4', $node->get('field_reference_2')->target_id); + $translation = $node->getTranslation('is'); + $this->assertSame('4', $translation->get('field_reference')->target_id); + $this->assertSame('4', $translation->get('field_reference_2')->target_id); + + $node = Node::load(4); + $this->assertSame('2', $node->get('field_reference')->target_id); + $this->assertSame('2', $node->get('field_reference_2')->target_id); + $translation = $node->getTranslation('en'); + $this->assertSame('2', $translation->get('field_reference')->target_id); + $this->assertSame('2', $translation->get('field_reference_2')->target_id); + } + +} diff -r e200cb7efeb3 -r c2387f117808 core/modules/migrate_drupal/tests/src/Kernel/d7/MigrateDrupal7AuditIdsTest.php --- a/core/modules/migrate_drupal/tests/src/Kernel/d7/MigrateDrupal7AuditIdsTest.php Thu Apr 26 11:26:54 2018 +0100 +++ b/core/modules/migrate_drupal/tests/src/Kernel/d7/MigrateDrupal7AuditIdsTest.php Tue Jul 10 15:07:59 2018 +0100 @@ -136,6 +136,7 @@ 'd7_node_revision', 'd7_taxonomy_term', 'd7_user', + 'node_translation_menu_links', ]; $this->assertEmpty(array_diff(array_filter($conflicts), $expected)); } diff -r e200cb7efeb3 -r c2387f117808 core/modules/migrate_drupal_ui/src/Batch/MigrateUpgradeImportBatch.php --- a/core/modules/migrate_drupal_ui/src/Batch/MigrateUpgradeImportBatch.php Thu Apr 26 11:26:54 2018 +0100 +++ b/core/modules/migrate_drupal_ui/src/Batch/MigrateUpgradeImportBatch.php Tue Jul 10 15:07:59 2018 +0100 @@ -9,11 +9,13 @@ use Drupal\migrate\Plugin\MigrationInterface; use Drupal\migrate\Event\MigrateEvents; use Drupal\migrate\Event\MigrateIdMapMessageEvent; +use Drupal\migrate\Event\MigrateImportEvent; use Drupal\migrate\Event\MigrateMapDeleteEvent; use Drupal\migrate\Event\MigrateMapSaveEvent; use Drupal\migrate\Event\MigratePostRowSaveEvent; use Drupal\migrate\Event\MigrateRowDeleteEvent; use Drupal\migrate\MigrateExecutable; +use Drupal\migrate_drupal\Plugin\MigrationWithFollowUpInterface; /** * Runs a single migration batch. @@ -56,6 +58,13 @@ protected static $messages; /** + * The follow-up migrations. + * + * @var \Drupal\migrate\Plugin\MigrationInterface[]; + */ + protected static $followUpMigrations; + + /** * Runs a single migrate batch import. * * @param int[] $initial_ids @@ -69,6 +78,7 @@ if (!static::$listenersAdded) { $event_dispatcher = \Drupal::service('event_dispatcher'); $event_dispatcher->addListener(MigrateEvents::POST_ROW_SAVE, [static::class, 'onPostRowSave']); + $event_dispatcher->addListener(MigrateEvents::POST_IMPORT, [static::class, 'onPostImport']); $event_dispatcher->addListener(MigrateEvents::MAP_SAVE, [static::class, 'onMapSave']); $event_dispatcher->addListener(MigrateEvents::IDMAP_MESSAGE, [static::class, 'onIdMapMessage']); @@ -138,6 +148,25 @@ \Drupal::logger('migrate_drupal_ui')->notice($message); $context['sandbox']['num_processed'] = 0; $context['results']['successes']++; + + // If the completed migration has any follow-up migrations, add them + // to the batch migrations. + // @see onPostImport() + if (!empty(static::$followUpMigrations)) { + foreach (static::$followUpMigrations as $migration_id => $migration) { + if (!in_array($migration_id, $context['sandbox']['migration_ids'], TRUE)) { + // Add the follow-up migration ID to the batch migration IDs for + // later execution. + $context['sandbox']['migration_ids'][] = $migration_id; + // Increase the number of migrations in the batch to update the + // progress bar and keep it accurate. + $context['sandbox']['max']++; + // Unset the follow-up migration to make sure it won't get added + // to the batch twice. + unset(static::$followUpMigrations[$migration_id]); + } + } + } break; case MigrationInterface::RESULT_INCOMPLETE: @@ -263,6 +292,24 @@ } /** + * Adds follow-up migrations. + * + * @param \Drupal\migrate\Event\MigrateImportEvent $event + * The import event. + */ + public static function onPostImport(MigrateImportEvent $event) { + $migration = $event->getMigration(); + if ($migration instanceof MigrationWithFollowUpInterface) { + // After the migration on which they depend has been successfully + // executed, the follow-up migrations are immediately added to the batch + // and removed from the $followUpMigrations property. This means that the + // $followUpMigrations property is always empty at this point and it's OK + // to override it with the next follow-up migrations. + static::$followUpMigrations = $migration->generateFollowUpMigrations(); + } + } + + /** * Reacts to item deletion. * * @param \Drupal\migrate\Event\MigrateRowDeleteEvent $event diff -r e200cb7efeb3 -r c2387f117808 core/modules/migrate_drupal_ui/src/Form/CredentialForm.php --- a/core/modules/migrate_drupal_ui/src/Form/CredentialForm.php Thu Apr 26 11:26:54 2018 +0100 +++ b/core/modules/migrate_drupal_ui/src/Form/CredentialForm.php Tue Jul 10 15:07:59 2018 +0100 @@ -2,9 +2,12 @@ namespace Drupal\migrate_drupal_ui\Form; +use Drupal\Component\Utility\UrlHelper; use Drupal\Core\Form\FormStateInterface; use Drupal\Core\Render\RendererInterface; use Drupal\Core\TempStore\PrivateTempStoreFactory; +use GuzzleHttp\ClientInterface; +use GuzzleHttp\Exception\TransferException; use Symfony\Component\DependencyInjection\ContainerInterface; /** @@ -22,16 +25,33 @@ protected $renderer; /** + * The HTTP client to fetch the files with. + * + * @var \GuzzleHttp\ClientInterface + */ + protected $httpClient; + + /** + * An array of error information. + * + * @var array + */ + protected $errors = []; + + /** * CredentialForm constructor. * * @param \Drupal\Core\Render\RendererInterface $renderer * The renderer service. * @param \Drupal\Core\TempStore\PrivateTempStoreFactory $tempstore_private * The private tempstore factory. + * @param \GuzzleHttp\ClientInterface $http_client + * A Guzzle client object. */ - public function __construct(RendererInterface $renderer, PrivateTempStoreFactory $tempstore_private) { + public function __construct(RendererInterface $renderer, PrivateTempStoreFactory $tempstore_private, ClientInterface $http_client) { parent::__construct($tempstore_private); $this->renderer = $renderer; + $this->httpClient = $http_client; } /** @@ -40,7 +60,8 @@ public static function create(ContainerInterface $container) { return new static( $container->get('renderer'), - $container->get('tempstore.private') + $container->get('tempstore.private'), + $container->get('http_client') ); } @@ -75,6 +96,11 @@ $default_options = []; + $form['help'] = [ + '#type' => 'item', + '#description' => $this->t('Provide the information to access the Drupal site you want to upgrade. Files can be imported into the upgraded site as well. See the Upgrade documentation for more detailed instructions.', [':url' => 'https://www.drupal.org/upgrade/migrate']), + ]; + $form['version'] = [ '#type' => 'radios', '#default_value' => 7, @@ -145,6 +171,7 @@ ':input[name="version"]' => ['value' => '6'], ], ], + '#element_validate' => ['::validatePaths'], ]; $form['source']['source_base_path'] = [ @@ -156,6 +183,7 @@ ':input[name="version"]' => ['value' => '7'], ], ], + '#element_validate' => ['::validatePaths'], ]; $form['source']['source_private_file_path'] = [ @@ -168,6 +196,7 @@ ':input[name="version"]' => ['value' => '7'], ], ], + '#element_validate' => ['::validatePaths'], ]; return $form; @@ -177,7 +206,6 @@ * {@inheritdoc} */ public function validateForm(array &$form, FormStateInterface $form_state) { - // Retrieve the database driver from the form, use reflection to get the // namespace, and then construct a valid database array the same as in // settings.php. @@ -194,35 +222,61 @@ // Validate the driver settings and just end here if we have any issues. if ($errors = $drivers[$driver]->validateDatabaseSettings($database)) { foreach ($errors as $name => $message) { + $this->errors[$name] = $message; + } + } + else { + try { + $connection = $this->getConnection($database); + $version = (string) $this->getLegacyDrupalVersion($connection); + if (!$version) { + $this->errors[$database['driver'] . '][database'] = $this->t('Source database does not contain a recognizable Drupal version.'); + } + elseif ($version !== (string) $form_state->getValue('version')) { + $this->errors['version'] = $this->t('Source database is Drupal version @version but version @selected was selected.', + [ + '@version' => $version, + '@selected' => $form_state->getValue('version'), + ]); + } + else { + // Setup migrations and save form data to private store. + $this->setupMigrations($database, $form_state); + } + } + catch (\Exception $e) { + $this->errors[$database['driver'] . '][database'] = $e->getMessage(); + } + } + + // Display all errors as a list of items. + if ($this->errors) { + $form_state->setError($form, $this->t('

    Resolve all issues below to continue the upgrade.

    ')); + foreach ($this->errors as $name => $message) { $form_state->setErrorByName($name, $message); } - return; } + } - try { - $connection = $this->getConnection($database); - $version = (string) $this->getLegacyDrupalVersion($connection); - if (!$version) { - $form_state->setErrorByName($database['driver'] . '][0', $this->t('Source database does not contain a recognizable Drupal version.')); + /** + * The #element_validate handler for the source path elements. + * + * Ensures that entered path can be read. + */ + public function validatePaths($element, FormStateInterface $form_state) { + if ($source = $element['#value']) { + $msg = $this->t('Unable to read from @title.', ['@title' => $element['#title']]); + if (UrlHelper::isExternal($source)) { + try { + $this->httpClient->head($source); + } + catch (TransferException $e) { + $this->errors[$element['#name']] = $msg . ' ' . $e->getMessage(); + } } - elseif ($version !== (string) $form_state->getValue('version')) { - $form_state->setErrorByName($database['driver'] . '][0', $this->t('Source database is Drupal version @version but version @selected was selected.', [ - '@version' => $version, - '@selected' => $form_state->getValue('version'), - ])); + elseif (!file_exists($source) || (!is_dir($source)) || (!is_readable($source))) { + $this->errors[$element['#name']] = $msg; } - else { - // Setup migrations and save form data to private store. - $this->setupMigrations($database, $form_state); - } - } - catch (\Exception $e) { - $error_message = [ - '#title' => $this->t('Resolve the issue below to continue the upgrade.'), - '#theme' => 'item_list', - '#items' => [$e->getMessage()], - ]; - $form_state->setErrorByName($database['driver'] . '][0', $this->renderer->renderPlain($error_message)); } } diff -r e200cb7efeb3 -r c2387f117808 core/modules/migrate_drupal_ui/src/Form/ReviewForm.php --- a/core/modules/migrate_drupal_ui/src/Form/ReviewForm.php Thu Apr 26 11:26:54 2018 +0100 +++ b/core/modules/migrate_drupal_ui/src/Form/ReviewForm.php Tue Jul 10 15:07:59 2018 +0100 @@ -237,7 +237,7 @@ // Add source_module and destination_module for modules that do not need an // upgrade path and are enabled on the source site. foreach ($this->noUpgradePaths[$version] as $extension) { - if ($system_data['module'][$extension]['status']) { + if (isset($system_data['module'][$extension]) && $system_data['module'][$extension]['status']) { $table_data[$extension]['core'][$extension] = $extension; } } diff -r e200cb7efeb3 -r c2387f117808 core/modules/migrate_drupal_ui/src/Tests/MigrateUpgradeTestBase.php --- a/core/modules/migrate_drupal_ui/src/Tests/MigrateUpgradeTestBase.php Thu Apr 26 11:26:54 2018 +0100 +++ b/core/modules/migrate_drupal_ui/src/Tests/MigrateUpgradeTestBase.php Tue Jul 10 15:07:59 2018 +0100 @@ -179,8 +179,8 @@ $this->drupalPostForm(NULL, [], t('Perform upgrade')); $this->assertText(t('Congratulations, you upgraded Drupal!')); - // Have to reset all the statics after migration to ensure entities are - // loadable. + // Have to reset all the static caches after migration to ensure entities + // are loadable. $this->resetAll(); $expected_counts = $this->getEntityCounts(); diff -r e200cb7efeb3 -r c2387f117808 core/modules/migrate_drupal_ui/tests/src/Functional/MigrateUpgradeExecuteTestBase.php --- a/core/modules/migrate_drupal_ui/tests/src/Functional/MigrateUpgradeExecuteTestBase.php Thu Apr 26 11:26:54 2018 +0100 +++ b/core/modules/migrate_drupal_ui/tests/src/Functional/MigrateUpgradeExecuteTestBase.php Tue Jul 10 15:07:59 2018 +0100 @@ -2,7 +2,6 @@ namespace Drupal\Tests\migrate_drupal_ui\Functional; -use Drupal\migrate_drupal\MigrationConfigurationTrait; use Drupal\Tests\migrate_drupal\Traits\CreateTestContentEntitiesTrait; /** @@ -10,7 +9,6 @@ */ abstract class MigrateUpgradeExecuteTestBase extends MigrateUpgradeTestBase { - use MigrationConfigurationTrait; use CreateTestContentEntitiesTrait; /** @@ -70,16 +68,35 @@ // Ensure submitting the form with invalid database credentials gives us a // nice warning. $this->drupalPostForm(NULL, [$driver . '[database]' => 'wrong'] + $edits, t('Review upgrade')); - $session->pageTextContains('Resolve the issue below to continue the upgrade.'); + $session->pageTextContains('Resolve all issues below to continue the upgrade.'); $this->drupalPostForm(NULL, $edits, t('Review upgrade')); // Ensure we get errors about missing modules. - $session->pageTextContains(t('Resolve the issue below to continue the upgrade')); + $session->pageTextContains(t('Resolve all issues below to continue the upgrade.')); $session->pageTextContains(t('The no_source_module plugin must define the source_module property.')); // Uninstall the module causing the missing module error messages. $this->container->get('module_installer')->uninstall(['migration_provider_test'], TRUE); + // Test the file sources. + $this->drupalGet('/upgrade'); + $this->drupalPostForm(NULL, [], t('Continue')); + if ($version == 6) { + $paths['d6_source_base_path'] = DRUPAL_ROOT . '/wrong-path'; + } + else { + $paths['source_base_path'] = 'https://example.com/wrong-path'; + $paths['source_private_file_path'] = DRUPAL_ROOT . '/wrong-path'; + } + $this->drupalPostForm(NULL, $paths + $edits, t('Review upgrade')); + if ($version == 6) { + $session->responseContains('Unable to read from Files directory.'); + } + else { + $session->responseContains('Unable to read from Public files directory.'); + $session->responseContains('Unable to read from Private file directory.'); + } + // Restart the upgrade process. $this->drupalGet('/upgrade'); $session->responseContains('Upgrade a site by importing its files and the data from its database into a clean and empty new install of Drupal 8.'); diff -r e200cb7efeb3 -r c2387f117808 core/modules/migrate_drupal_ui/tests/src/Functional/MigrateUpgradeReviewPageTestBase.php --- a/core/modules/migrate_drupal_ui/tests/src/Functional/MigrateUpgradeReviewPageTestBase.php Thu Apr 26 11:26:54 2018 +0100 +++ b/core/modules/migrate_drupal_ui/tests/src/Functional/MigrateUpgradeReviewPageTestBase.php Tue Jul 10 15:07:59 2018 +0100 @@ -2,7 +2,6 @@ namespace Drupal\Tests\migrate_drupal_ui\Functional; -use Drupal\migrate_drupal\MigrationConfigurationTrait; use Drupal\Tests\migrate_drupal\Traits\CreateTestContentEntitiesTrait; /** @@ -10,7 +9,6 @@ */ abstract class MigrateUpgradeReviewPageTestBase extends MigrateUpgradeTestBase { - use MigrationConfigurationTrait; use CreateTestContentEntitiesTrait; /** @@ -112,6 +110,28 @@ $available_paths = $this->getAvailablePaths(); $missing_paths = $this->getMissingPaths(); $this->assertUpgradePaths($session, $available_paths, $missing_paths); + + // Check there are no errors when a module in noUpgradePaths is not in the + // source system tables. Test with a module that is listed in noUpgradePaths + // for both Drupal 6 and Drupal 7. + // @see \Drupal\migrate_drupal_ui\Form\ReviewForm::$noUpgradePaths + $module = 'help'; + $query = $this->sourceDatabase->delete('system'); + $query->condition('type', 'module'); + $query->condition('name', $module); + $query->execute(); + + // Start the upgrade process. + $this->drupalGet('/upgrade'); + $this->drupalPostForm(NULL, [], t('Continue')); + $this->drupalPostForm(NULL, $edits, t('Review upgrade')); + $this->drupalPostForm(NULL, [], t('I acknowledge I may lose data. Continue anyway.')); + + // Test the upgrade paths. + $available_paths = $this->getAvailablePaths(); + $available_paths = array_diff($available_paths, [$module]); + $missing_paths = $this->getMissingPaths(); + $this->assertUpgradePaths($session, $available_paths, $missing_paths); } /** diff -r e200cb7efeb3 -r c2387f117808 core/modules/migrate_drupal_ui/tests/src/Functional/MigrateUpgradeTestBase.php --- a/core/modules/migrate_drupal_ui/tests/src/Functional/MigrateUpgradeTestBase.php Thu Apr 26 11:26:54 2018 +0100 +++ b/core/modules/migrate_drupal_ui/tests/src/Functional/MigrateUpgradeTestBase.php Tue Jul 10 15:07:59 2018 +0100 @@ -98,28 +98,6 @@ } /** - * Transforms a nested array into a flat array suitable for BrowserTestBase::drupalPostForm(). - * - * @param array $values - * A multi-dimensional form values array to convert. - * - * @return array - * The flattened $edit array suitable for BrowserTestBase::drupalPostForm(). - */ - protected function translatePostValues(array $values) { - $edit = []; - // The easiest and most straightforward way to translate values suitable for - // BrowserTestBase::drupalPostForm() is to actually build the POST data string - // and convert the resulting key/value pairs back into a flat array. - $query = http_build_query($values); - foreach (explode('&', $query) as $item) { - list($key, $value) = explode('=', $item); - $edit[urldecode($key)] = urldecode($value); - } - return $edit; - } - - /** * Tests the displayed upgrade paths. * * @param \Drupal\Tests\WebAssert $session diff -r e200cb7efeb3 -r c2387f117808 core/modules/migrate_drupal_ui/tests/src/Functional/d6/MigrateUpgrade6ReviewPageTest.php --- a/core/modules/migrate_drupal_ui/tests/src/Functional/d6/MigrateUpgrade6ReviewPageTest.php Thu Apr 26 11:26:54 2018 +0100 +++ b/core/modules/migrate_drupal_ui/tests/src/Functional/d6/MigrateUpgrade6ReviewPageTest.php Tue Jul 10 15:07:59 2018 +0100 @@ -89,6 +89,7 @@ 'filefield_meta', 'help', 'i18n', + 'i18nmenu', 'i18nstrings', 'imageapi', 'imageapi_gd', @@ -123,7 +124,6 @@ 'i18nblocks', 'i18ncck', 'i18ncontent', - 'i18nmenu', 'i18npoll', 'i18nprofile', 'i18nsync', diff -r e200cb7efeb3 -r c2387f117808 core/modules/migrate_drupal_ui/tests/src/Functional/d6/MigrateUpgrade6Test.php --- a/core/modules/migrate_drupal_ui/tests/src/Functional/d6/MigrateUpgrade6Test.php Thu Apr 26 11:26:54 2018 +0100 +++ b/core/modules/migrate_drupal_ui/tests/src/Functional/d6/MigrateUpgrade6Test.php Tue Jul 10 15:07:59 2018 +0100 @@ -2,6 +2,7 @@ namespace Drupal\Tests\migrate_drupal_ui\Functional\d6; +use Drupal\node\Entity\Node; use Drupal\Tests\migrate_drupal_ui\Functional\MigrateUpgradeExecuteTestBase; use Drupal\user\Entity\User; @@ -63,12 +64,12 @@ 'contact_form' => 5, 'configurable_language' => 5, 'editor' => 2, - 'field_config' => 84, - 'field_storage_config' => 58, + 'field_config' => 89, + 'field_storage_config' => 63, 'file' => 8, 'filter_format' => 7, 'image_style' => 5, - 'language_content_settings' => 2, + 'language_content_settings' => 3, 'migration' => 105, 'node' => 17, // The 'book' module provides the 'book' node type, and the migration @@ -85,12 +86,12 @@ 'tour' => 4, 'user' => 7, 'user_role' => 6, - 'menu_link_content' => 5, + 'menu_link_content' => 10, 'view' => 16, 'date_format' => 11, 'entity_form_display' => 29, 'entity_form_mode' => 1, - 'entity_view_display' => 53, + 'entity_view_display' => 55, 'entity_view_mode' => 14, 'base_field_override' => 38, ]; @@ -103,10 +104,10 @@ $counts = $this->getEntityCounts(); $counts['block_content'] = 3; $counts['comment'] = 7; - $counts['entity_view_display'] = 53; + $counts['entity_view_display'] = 55; $counts['entity_view_mode'] = 14; $counts['file'] = 9; - $counts['menu_link_content'] = 6; + $counts['menu_link_content'] = 11; $counts['node'] = 18; $counts['taxonomy_term'] = 9; $counts['user'] = 8; @@ -131,6 +132,7 @@ 'filefield', 'filter', 'forum', + 'i18nmenu', 'i18ntaxonomy', 'imagecache', 'imagefield', @@ -175,7 +177,6 @@ 'i18nblocks', 'i18ncck', 'i18ncontent', - 'i18nmenu', // This module is in the missing path list because it is installed on the // source site but it is not installed on the destination site. 'i18nprofile', @@ -192,6 +193,26 @@ $user = User::load(2); $user->passRaw = 'john.doe_pass'; $this->drupalLogin($user); + $this->assertFollowUpMigrationResults(); + } + + /** + * Tests that follow-up migrations have been run successfully. + */ + protected function assertFollowUpMigrationResults() { + $node = Node::load(10); + $this->assertSame('12', $node->get('field_reference')->target_id); + $this->assertSame('12', $node->get('field_reference_2')->target_id); + $translation = $node->getTranslation('fr'); + $this->assertSame('12', $translation->get('field_reference')->target_id); + $this->assertSame('12', $translation->get('field_reference_2')->target_id); + + $node = Node::load(12)->getTranslation('en'); + $this->assertSame('10', $node->get('field_reference')->target_id); + $this->assertSame('10', $node->get('field_reference_2')->target_id); + $translation = $node->getTranslation('fr'); + $this->assertSame('10', $translation->get('field_reference')->target_id); + $this->assertSame('10', $translation->get('field_reference_2')->target_id); } } diff -r e200cb7efeb3 -r c2387f117808 core/modules/migrate_drupal_ui/tests/src/Functional/d7/MigrateUpgrade7ReviewPageTest.php --- a/core/modules/migrate_drupal_ui/tests/src/Functional/d7/MigrateUpgrade7ReviewPageTest.php Thu Apr 26 11:26:54 2018 +0100 +++ b/core/modules/migrate_drupal_ui/tests/src/Functional/d7/MigrateUpgrade7ReviewPageTest.php Tue Jul 10 15:07:59 2018 +0100 @@ -34,11 +34,14 @@ return [ 'aggregator', 'block', + 'book', + 'color', 'comment', 'contact', 'date', 'dblog', 'email', + 'entity_translation', 'field', 'field_sql_storage', 'file', @@ -115,8 +118,6 @@ */ protected function getMissingPaths() { return [ - 'book', - 'color', 'rdf', 'views', ]; diff -r e200cb7efeb3 -r c2387f117808 core/modules/migrate_drupal_ui/tests/src/Functional/d7/MigrateUpgrade7Test.php --- a/core/modules/migrate_drupal_ui/tests/src/Functional/d7/MigrateUpgrade7Test.php Thu Apr 26 11:26:54 2018 +0100 +++ b/core/modules/migrate_drupal_ui/tests/src/Functional/d7/MigrateUpgrade7Test.php Tue Jul 10 15:07:59 2018 +0100 @@ -2,6 +2,7 @@ namespace Drupal\Tests\migrate_drupal_ui\Functional\d7; +use Drupal\node\Entity\Node; use Drupal\Tests\migrate_drupal_ui\Functional\MigrateUpgradeExecuteTestBase; use Drupal\user\Entity\User; @@ -65,12 +66,12 @@ 'configurable_language' => 4, 'contact_form' => 3, 'editor' => 2, - 'field_config' => 63, - 'field_storage_config' => 46, + 'field_config' => 66, + 'field_storage_config' => 49, 'file' => 3, 'filter_format' => 7, 'image_style' => 6, - 'language_content_settings' => 2, + 'language_content_settings' => 6, 'migration' => 73, 'node' => 5, 'node_type' => 6, @@ -85,7 +86,7 @@ 'tour' => 4, 'user' => 4, 'user_role' => 3, - 'menu_link_content' => 8, + 'menu_link_content' => 12, 'view' => 16, 'date_format' => 11, 'entity_form_display' => 17, @@ -104,7 +105,7 @@ $counts['block_content'] = 2; $counts['comment'] = 2; $counts['file'] = 4; - $counts['menu_link_content'] = 9; + $counts['menu_link_content'] = 13; $counts['node'] = 6; $counts['taxonomy_term'] = 19; $counts['user'] = 5; @@ -118,12 +119,15 @@ return [ 'aggregator', 'block', + 'book', + 'color', 'comment', 'contact', 'date', 'dblog', 'email', 'entityreference', + 'entity_translation', 'field', 'field_sql_storage', 'file', @@ -169,8 +173,6 @@ */ protected function getMissingPaths() { return [ - 'book', - 'color', 'rdf', // These modules are in the missing path list because they are installed // on the source site but they are not installed on the destination site. @@ -190,6 +192,27 @@ $user = User::load(2); $user->passRaw = 'a password'; $this->drupalLogin($user); + $this->assertFollowUpMigrationResults(); + } + + /** + * Tests that follow-up migrations have been run successfully. + */ + protected function assertFollowUpMigrationResults() { + $node = Node::load(2); + $this->assertSame('4', $node->get('field_reference')->target_id); + $this->assertSame('4', $node->get('field_reference_2')->target_id); + $translation = $node->getTranslation('is'); + $this->assertSame('4', $translation->get('field_reference')->target_id); + $this->assertSame('4', $translation->get('field_reference_2')->target_id); + + $node = Node::load(4); + $this->assertSame('2', $node->get('field_reference')->target_id); + $this->assertSame('2', $node->get('field_reference_2')->target_id); + $translation = $node->getTranslation('en'); + $this->assertSame('2', $translation->get('field_reference')->target_id); + $this->assertSame('2', $translation->get('field_reference_2')->target_id); + } } diff -r e200cb7efeb3 -r c2387f117808 core/modules/node/migrations/d6_node_translation.yml --- a/core/modules/node/migrations/d6_node_translation.yml Thu Apr 26 11:26:54 2018 +0100 +++ b/core/modules/node/migrations/d6_node_translation.yml Tue Jul 10 15:07:59 2018 +0100 @@ -2,7 +2,9 @@ label: Node translations migration_tags: - Drupal 6 + - translation - Content +class: Drupal\node\Plugin\migrate\D6NodeTranslation deriver: Drupal\node\Plugin\migrate\D6NodeDeriver source: plugin: d6_node diff -r e200cb7efeb3 -r c2387f117808 core/modules/node/migrations/d7_node_translation.yml --- a/core/modules/node/migrations/d7_node_translation.yml Thu Apr 26 11:26:54 2018 +0100 +++ b/core/modules/node/migrations/d7_node_translation.yml Tue Jul 10 15:07:59 2018 +0100 @@ -4,6 +4,7 @@ - Drupal 7 - translation - Content +class: Drupal\node\Plugin\migrate\D7NodeTranslation deriver: Drupal\node\Plugin\migrate\D7NodeDeriver source: plugin: d7_node diff -r e200cb7efeb3 -r c2387f117808 core/modules/node/node.module --- a/core/modules/node/node.module Thu Apr 26 11:26:54 2018 +0100 +++ b/core/modules/node/node.module Tue Jul 10 15:07:59 2018 +0100 @@ -806,7 +806,7 @@ * the global content language of the current request. * * @return array - * An array as expected by drupal_render(). + * An array as expected by \Drupal\Core\Render\RendererInterface::render(). */ function node_view(NodeInterface $node, $view_mode = 'full', $langcode = NULL) { return entity_view($node, $view_mode, $langcode); @@ -824,7 +824,8 @@ * content language of the current request. * * @return array - * An array in the format expected by drupal_render(). + * An array in the format expected by + * \Drupal\Core\Render\RendererInterface::render(). */ function node_view_multiple($nodes, $view_mode = 'teaser', $langcode = NULL) { return entity_view_multiple($nodes, $view_mode, $langcode); diff -r e200cb7efeb3 -r c2387f117808 core/modules/node/src/Controller/NodeController.php --- a/core/modules/node/src/Controller/NodeController.php Thu Apr 26 11:26:54 2018 +0100 +++ b/core/modules/node/src/Controller/NodeController.php Tue Jul 10 15:07:59 2018 +0100 @@ -122,7 +122,7 @@ * The node revision ID. * * @return array - * An array suitable for drupal_render(). + * An array suitable for \Drupal\Core\Render\RendererInterface::render(). */ public function revisionShow($node_revision) { $node = $this->entityManager()->getStorage('node')->loadRevision($node_revision); @@ -154,7 +154,7 @@ * A node object. * * @return array - * An array as expected by drupal_render(). + * An array as expected by \Drupal\Core\Render\RendererInterface::render(). */ public function revisionOverview(NodeInterface $node) { $account = $this->currentUser(); diff -r e200cb7efeb3 -r c2387f117808 core/modules/node/src/Form/NodeRevisionRevertForm.php --- a/core/modules/node/src/Form/NodeRevisionRevertForm.php Thu Apr 26 11:26:54 2018 +0100 +++ b/core/modules/node/src/Form/NodeRevisionRevertForm.php Tue Jul 10 15:07:59 2018 +0100 @@ -128,6 +128,7 @@ $this->revision = $this->prepareRevertedRevision($this->revision, $form_state); $this->revision->revision_log = t('Copy of the revision from %date.', ['%date' => $this->dateFormatter->format($original_revision_timestamp)]); + $this->revision->setRevisionUserId($this->currentUser()->id()); $this->revision->setRevisionCreationTime($this->time->getRequestTime()); $this->revision->setChangedTime($this->time->getRequestTime()); $this->revision->save(); diff -r e200cb7efeb3 -r c2387f117808 core/modules/node/src/Plugin/migrate/D6NodeTranslation.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/core/modules/node/src/Plugin/migrate/D6NodeTranslation.php Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,21 @@ +migrationPluginManager->clearCachedDefinitions(); + return $this->migrationPluginManager->createInstances('d6_entity_reference_translation'); + } + +} diff -r e200cb7efeb3 -r c2387f117808 core/modules/node/src/Plugin/migrate/D7NodeTranslation.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/core/modules/node/src/Plugin/migrate/D7NodeTranslation.php Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,21 @@ +migrationPluginManager->clearCachedDefinitions(); + return $this->migrationPluginManager->createInstances('d7_entity_reference_translation'); + } + +} diff -r e200cb7efeb3 -r c2387f117808 core/modules/node/src/Tests/NodeRevisionsTest.php --- a/core/modules/node/src/Tests/NodeRevisionsTest.php Thu Apr 26 11:26:54 2018 +0100 +++ b/core/modules/node/src/Tests/NodeRevisionsTest.php Tue Jul 10 15:07:59 2018 +0100 @@ -109,8 +109,8 @@ $node->untranslatable_string_field->value = $this->randomString(); $node->setNewRevision(); - // Edit the 2nd revision with a different user. - if ($i == 1) { + // Edit the 1st and 2nd revision with a different user. + if ($i < 2) { $editor = $this->drupalCreateUser(); $node->setRevisionUserId($editor->id()); } @@ -179,6 +179,10 @@ $node_storage->resetCache([$node->id()]); $reverted_node = $node_storage->load($node->id()); $this->assertTrue(($nodes[1]->body->value == $reverted_node->body->value), 'Node reverted correctly.'); + // Confirm the revision author is the user performing the revert. + $this->assertTrue($reverted_node->getRevisionUserId() == $this->loggedInUser->id(), 'Node revision author is user performing revert.'); + // And that its not the revision author. + $this->assertTrue($reverted_node->getRevisionUserId() != $nodes[1]->getRevisionUserId(), 'Node revision author is not original revision author.'); // Confirm that this is not the default version. $node = node_revision_load($node->getRevisionId()); diff -r e200cb7efeb3 -r c2387f117808 core/modules/node/tests/modules/node_test_views/test_views/views.view.test_node_revision_links.yml --- a/core/modules/node/tests/modules/node_test_views/test_views/views.view.test_node_revision_links.yml Thu Apr 26 11:26:54 2018 +0100 +++ b/core/modules/node/tests/modules/node_test_views/test_views/views.view.test_node_revision_links.yml Tue Jul 10 15:07:59 2018 +0100 @@ -202,7 +202,7 @@ hide_empty: false empty_zero: false hide_alter_empty: true - text: 'Link to delete revision' + text: 'Link to revert revision' entity_type: node plugin_id: node_revision_link_revert filters: { } diff -r e200cb7efeb3 -r c2387f117808 core/modules/node/tests/src/Functional/Hal/NodeHalJsonAnonTest.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/core/modules/node/tests/src/Functional/Hal/NodeHalJsonAnonTest.php Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,111 @@ +applyHalFieldNormalization($default_normalization); + + $author = User::load($this->entity->getOwnerId()); + return $normalization + [ + '_links' => [ + 'self' => [ + 'href' => $this->baseUrl . '/llama?_format=hal_json', + ], + 'type' => [ + 'href' => $this->baseUrl . '/rest/type/node/camelids', + ], + $this->baseUrl . '/rest/relation/node/camelids/revision_uid' => [ + [ + 'href' => $this->baseUrl . '/user/' . $author->id() . '?_format=hal_json', + ], + ], + $this->baseUrl . '/rest/relation/node/camelids/uid' => [ + [ + 'href' => $this->baseUrl . '/user/' . $author->id() . '?_format=hal_json', + 'lang' => 'en', + ], + ], + ], + '_embedded' => [ + $this->baseUrl . '/rest/relation/node/camelids/revision_uid' => [ + [ + '_links' => [ + 'self' => [ + 'href' => $this->baseUrl . '/user/' . $author->id() . '?_format=hal_json', + ], + 'type' => [ + 'href' => $this->baseUrl . '/rest/type/user/user', + ], + ], + 'uuid' => [ + ['value' => $author->uuid()] + ], + ], + ], + $this->baseUrl . '/rest/relation/node/camelids/uid' => [ + [ + '_links' => [ + 'self' => [ + 'href' => $this->baseUrl . '/user/' . $author->id() . '?_format=hal_json', + ], + 'type' => [ + 'href' => $this->baseUrl . '/rest/type/user/user', + ], + ], + 'uuid' => [ + ['value' => $author->uuid()] + ], + 'lang' => 'en', + ], + ], + ], + ]; + } + + /** + * {@inheritdoc} + */ + protected function getNormalizedPostEntity() { + return parent::getNormalizedPostEntity() + [ + '_links' => [ + 'type' => [ + 'href' => $this->baseUrl . '/rest/type/node/camelids', + ], + ], + ]; + } + +} diff -r e200cb7efeb3 -r c2387f117808 core/modules/node/tests/src/Functional/Hal/NodeHalJsonBasicAuthTest.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/core/modules/node/tests/src/Functional/Hal/NodeHalJsonBasicAuthTest.php Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,24 @@ +drupalCreateContentType([ + 'type' => 'page', + 'name' => 'Basic page', + 'display_submitted' => FALSE, + ]); + + // Grant create and editing permissions to anonymous user: + $anonymous_role = Role::load(AccountInterface::ANONYMOUS_ROLE); + $anonymous_role->grantPermission('create page content'); + $anonymous_role->save(); + } + + /** + * Checks the node preview functionality for anonymous users. + */ + public function testAnonymousPagePreview() { + + $title_key = 'title[0][value]'; + $body_key = 'body[0][value]'; + + // Fill in node creation form and preview node. + $edit = [ + $title_key => $this->randomMachineName(), + $body_key => $this->randomMachineName() + ]; + $this->drupalPostForm('node/add/page', $edit, t('Preview')); + + // Check that the preview is displaying the title, body and term. + $this->assertSession()->linkExists(t('Back to content editing')); + $this->assertSession()->responseContains($edit[$body_key]); + $this->assertSession()->titleEquals($edit[$title_key] . ' | Drupal'); + } + +} diff -r e200cb7efeb3 -r c2387f117808 core/modules/node/tests/src/Functional/NodeRevisionsAllTest.php --- a/core/modules/node/tests/src/Functional/NodeRevisionsAllTest.php Thu Apr 26 11:26:54 2018 +0100 +++ b/core/modules/node/tests/src/Functional/NodeRevisionsAllTest.php Tue Jul 10 15:07:59 2018 +0100 @@ -27,6 +27,13 @@ protected $revisionLogs; /** + * An arbitrary user for revision authoring. + * + * @var \Drupal\user\UserInterface + */ + protected $revisionUser; + + /** * {@inheritdoc} */ protected function setUp() { @@ -47,6 +54,10 @@ // Create an initial node. $node = $this->drupalCreateNode(); + // Create a user for revision authoring. + // This must be different from user performing revert. + $this->revisionUser = $this->drupalCreateUser(); + $settings = get_object_vars($node); $settings['revision'] = 1; @@ -86,6 +97,8 @@ 'format' => filter_default_format(), ]; $node->setNewRevision(); + // Ensure the revision author is a different user. + $node->setRevisionUserId($this->revisionUser->id()); $node->save(); return $node; @@ -141,6 +154,11 @@ $reverted_node = $node_storage->load($node->id()); $this->assertTrue(($nodes[1]->body->value == $reverted_node->body->value), 'Node reverted correctly.'); + // Confirm the revision author is the user performing the revert. + $this->assertTrue($reverted_node->getRevisionUserId() == $this->loggedInUser->id(), 'Node revision author is user performing revert.'); + // And that its not the revision author. + $this->assertTrue($reverted_node->getRevisionUserId() != $this->revisionUser->id(), 'Node revision author is not original revision author.'); + // Confirm that this is not the current version. $node = node_revision_load($node->getRevisionId()); $this->assertFalse($node->isDefaultRevision(), 'Third node revision is not the current one.'); diff -r e200cb7efeb3 -r c2387f117808 core/modules/node/tests/src/Functional/NodeTypeTranslationTest.php --- a/core/modules/node/tests/src/Functional/NodeTypeTranslationTest.php Thu Apr 26 11:26:54 2018 +0100 +++ b/core/modules/node/tests/src/Functional/NodeTypeTranslationTest.php Tue Jul 10 15:07:59 2018 +0100 @@ -83,6 +83,11 @@ protected function installParameters() { $parameters = parent::installParameters(); $parameters['parameters']['langcode'] = $this->defaultLangcode; + // Create an empty po file so we don't attempt to download one from + // localize.drupal.org. It does not need to match the version exactly as the + // multi-lingual system will fallback. + \Drupal::service('file_system')->mkdir($this->publicFilesDirectory . '/translations', NULL, TRUE); + file_put_contents($this->publicFilesDirectory . "/translations/drupal-8.0.0.{$this->defaultLangcode}.po", ''); return $parameters; } diff -r e200cb7efeb3 -r c2387f117808 core/modules/node/tests/src/Functional/Rest/NodeJsonAnonTest.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/core/modules/node/tests/src/Functional/Rest/NodeJsonAnonTest.php Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,24 @@ +grantPermissionsToTestedRole(['access content']); + break; + case 'POST': + $this->grantPermissionsToTestedRole(['access content', 'create camelids content']); + break; + case 'PATCH': + // Do not grant the 'create url aliases' permission to test the case + // when the path field is protected/not accessible, see + // \Drupal\Tests\rest\Functional\EntityResource\Term\TermResourceTestBase + // for a positive test. + $this->grantPermissionsToTestedRole(['access content', 'edit any camelids content']); + break; + case 'DELETE': + $this->grantPermissionsToTestedRole(['access content', 'delete any camelids content']); + break; + } + } + + /** + * {@inheritdoc} + */ + protected function createEntity() { + if (!NodeType::load('camelids')) { + // Create a "Camelids" node type. + NodeType::create([ + 'name' => 'Camelids', + 'type' => 'camelids', + ])->save(); + } + + // Create a "Llama" node. + $node = Node::create(['type' => 'camelids']); + $node->setTitle('Llama') + ->setOwnerId(static::$auth ? $this->account->id() : 0) + ->setPublished(TRUE) + ->setCreatedTime(123456789) + ->setChangedTime(123456789) + ->setRevisionCreationTime(123456789) + ->set('path', '/llama') + ->save(); + + return $node; + } + + /** + * {@inheritdoc} + */ + protected function getExpectedNormalizedEntity() { + $author = User::load($this->entity->getOwnerId()); + return [ + 'nid' => [ + ['value' => 1], + ], + 'uuid' => [ + ['value' => $this->entity->uuid()], + ], + 'vid' => [ + ['value' => 1], + ], + 'langcode' => [ + [ + 'value' => 'en', + ], + ], + 'type' => [ + [ + 'target_id' => 'camelids', + 'target_type' => 'node_type', + 'target_uuid' => NodeType::load('camelids')->uuid(), + ], + ], + 'title' => [ + [ + 'value' => 'Llama', + ], + ], + 'status' => [ + [ + 'value' => TRUE, + ], + ], + 'created' => [ + $this->formatExpectedTimestampItemValues(123456789), + ], + 'changed' => [ + $this->formatExpectedTimestampItemValues($this->entity->getChangedTime()), + ], + 'promote' => [ + [ + 'value' => TRUE, + ], + ], + 'sticky' => [ + [ + 'value' => FALSE, + ], + ], + 'revision_timestamp' => [ + $this->formatExpectedTimestampItemValues(123456789), + ], + 'revision_translation_affected' => [ + [ + 'value' => TRUE, + ], + ], + 'default_langcode' => [ + [ + 'value' => TRUE, + ], + ], + 'uid' => [ + [ + 'target_id' => (int) $author->id(), + 'target_type' => 'user', + 'target_uuid' => $author->uuid(), + 'url' => base_path() . 'user/' . $author->id(), + ], + ], + 'revision_uid' => [ + [ + 'target_id' => (int) $author->id(), + 'target_type' => 'user', + 'target_uuid' => $author->uuid(), + 'url' => base_path() . 'user/' . $author->id(), + ], + ], + 'revision_log' => [], + 'path' => [ + [ + 'alias' => '/llama', + 'pid' => 1, + 'langcode' => 'en', + ], + ], + ]; + } + + /** + * {@inheritdoc} + */ + protected function getNormalizedPostEntity() { + return [ + 'type' => [ + [ + 'target_id' => 'camelids', + ], + ], + 'title' => [ + [ + 'value' => 'Dramallama', + ], + ], + ]; + } + + /** + * {@inheritdoc} + */ + protected function getExpectedUnauthorizedAccessMessage($method) { + if ($this->config('rest.settings')->get('bc_entity_resource_permissions')) { + return parent::getExpectedUnauthorizedAccessMessage($method); + } + + if ($method === 'GET' || $method == 'PATCH' || $method == 'DELETE') { + return "The 'access content' permission is required."; + } + return parent::getExpectedUnauthorizedAccessMessage($method); + } + + /** + * Tests PATCHing a node's path with and without 'create url aliases'. + * + * For a positive test, see the similar test coverage for Term. + * + * @see \Drupal\Tests\rest\Functional\EntityResource\Term\TermResourceTestBase::testPatchPath() + */ + public function testPatchPath() { + $this->initAuthentication(); + $this->provisionEntityResource(); + $this->setUpAuthorization('GET'); + $this->setUpAuthorization('PATCH'); + + $url = $this->getEntityResourceUrl()->setOption('query', ['_format' => static::$format]); + + // GET node's current normalization. + $response = $this->request('GET', $url, $this->getAuthenticationRequestOptions('GET')); + $normalization = $this->serializer->decode((string) $response->getBody(), static::$format); + + // Change node's path alias. + $normalization['path'][0]['alias'] .= 's-rule-the-world'; + + // Create node PATCH request. + $request_options = []; + $request_options[RequestOptions::HEADERS]['Content-Type'] = static::$mimeType; + $request_options = array_merge_recursive($request_options, $this->getAuthenticationRequestOptions('PATCH')); + $request_options[RequestOptions::BODY] = $this->serializer->encode($normalization, static::$format); + + // PATCH request: 403 when creating URL aliases unauthorized. Before + // asserting the 403 response, assert that the stored path alias remains + // unchanged. + $response = $this->request('PATCH', $url, $request_options); + $this->assertSame('/llama', $this->entityStorage->loadUnchanged($this->entity->id())->get('path')->alias); + $this->assertResourceErrorResponse(403, "Access denied on updating field 'path'.", $response); + + // Grant permission to create URL aliases. + $this->grantPermissionsToTestedRole(['create url aliases']); + + // Repeat PATCH request: 200. + $response = $this->request('PATCH', $url, $request_options); + $this->assertResourceResponse(200, FALSE, $response); + $updated_normalization = $this->serializer->decode((string) $response->getBody(), static::$format); + $this->assertSame($normalization['path'], $updated_normalization['path']); + } + +} diff -r e200cb7efeb3 -r c2387f117808 core/modules/node/tests/src/Functional/Rest/NodeTypeJsonAnonTest.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/core/modules/node/tests/src/Functional/Rest/NodeTypeJsonAnonTest.php Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,24 @@ +grantPermissionsToTestedRole(['administer content types', 'access content']); + } + + /** + * {@inheritdoc} + */ + protected function createEntity() { + // Create a "Camelids" node type. + $camelids = NodeType::create([ + 'name' => 'Camelids', + 'type' => 'camelids', + 'description' => 'Camelids are large, strictly herbivorous animals with slender necks and long legs.', + ]); + + $camelids->save(); + + return $camelids; + } + + /** + * {@inheritdoc} + */ + protected function getExpectedNormalizedEntity() { + return [ + 'dependencies' => [], + 'description' => 'Camelids are large, strictly herbivorous animals with slender necks and long legs.', + 'display_submitted' => TRUE, + 'help' => NULL, + 'langcode' => 'en', + 'name' => 'Camelids', + 'new_revision' => TRUE, + 'preview_mode' => 1, + 'status' => TRUE, + 'type' => 'camelids', + 'uuid' => $this->entity->uuid(), + ]; + } + + /** + * {@inheritdoc} + */ + protected function getNormalizedPostEntity() { + // @todo Update in https://www.drupal.org/node/2300677. + } + + /** + * {@inheritdoc} + */ + protected function getExpectedUnauthorizedAccessMessage($method) { + if ($this->config('rest.settings')->get('bc_entity_resource_permissions')) { + return parent::getExpectedUnauthorizedAccessMessage($method); + } + + return "The 'access content' permission is required."; + } + +} diff -r e200cb7efeb3 -r c2387f117808 core/modules/node/tests/src/Functional/Rest/NodeTypeXmlAnonTest.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/core/modules/node/tests/src/Functional/Rest/NodeTypeXmlAnonTest.php Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,26 @@ +markTestSkipped(); + } + +} diff -r e200cb7efeb3 -r c2387f117808 core/modules/node/tests/src/Functional/Rest/NodeXmlBasicAuthTest.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/core/modules/node/tests/src/Functional/Rest/NodeXmlBasicAuthTest.php Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,44 @@ +markTestSkipped(); + } + +} diff -r e200cb7efeb3 -r c2387f117808 core/modules/node/tests/src/Functional/Rest/NodeXmlCookieTest.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/core/modules/node/tests/src/Functional/Rest/NodeXmlCookieTest.php Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,39 @@ +markTestSkipped(); + } + +} diff -r e200cb7efeb3 -r c2387f117808 core/modules/node/tests/src/Kernel/Migrate/d6/MigrateNodeTest.php --- a/core/modules/node/tests/src/Kernel/Migrate/d6/MigrateNodeTest.php Thu Apr 26 11:26:54 2018 +0100 +++ b/core/modules/node/tests/src/Kernel/Migrate/d6/MigrateNodeTest.php Tue Jul 10 15:07:59 2018 +0100 @@ -94,6 +94,10 @@ $this->assertCount(2, $node->field_company); $this->assertSame('Klingon Empire', $node->field_company[0]->entity->label()); $this->assertSame('Romulan Empire', $node->field_company[1]->entity->label()); + $this->assertCount(1, $node->field_company_2); + $this->assertSame('Klingon Empire', $node->field_company_2[0]->entity->label()); + $this->assertCount(1, $node->field_company_3); + $this->assertSame('Romulan Empire', $node->field_company_3[0]->entity->label()); // Test that user reference field values were migrated. $this->assertCount(1, $node->field_commander); @@ -223,7 +227,7 @@ $default_connection = \Drupal::database(); $default_connection->truncate($table_name)->execute(); if ($new_row) { - $hash = $migration->getIdMap()->getSourceIDsHash(['nid' => $new_row['sourceid1']]); + $hash = $migration->getIdMap()->getSourceIdsHash(['nid' => $new_row['sourceid1']]); $new_row['source_ids_hash'] = $hash; $default_connection->insert($table_name) ->fields($new_row) diff -r e200cb7efeb3 -r c2387f117808 core/modules/node/tests/src/Kernel/Migrate/d6/MigrateNodeTypeTest.php --- a/core/modules/node/tests/src/Kernel/Migrate/d6/MigrateNodeTypeTest.php Thu Apr 26 11:26:54 2018 +0100 +++ b/core/modules/node/tests/src/Kernel/Migrate/d6/MigrateNodeTypeTest.php Tue Jul 10 15:07:59 2018 +0100 @@ -38,7 +38,7 @@ $this->assertIdentical(TRUE, $node_type_page->displaySubmitted()); $this->assertIdentical(FALSE, $node_type_page->isNewRevision()); $this->assertIdentical(DRUPAL_OPTIONAL, $node_type_page->getPreviewMode()); - $this->assertIdentical($id_map->lookupDestinationID(['test_page']), ['test_page']); + $this->assertIdentical($id_map->lookupDestinationId(['test_page']), ['test_page']); // Test we have a body field. $field = FieldConfig::loadByName('node', 'test_page', 'body'); @@ -57,7 +57,7 @@ $this->assertIdentical(TRUE, $node_type_story->displaySubmitted()); $this->assertIdentical(FALSE, $node_type_story->isNewRevision()); $this->assertIdentical(DRUPAL_OPTIONAL, $node_type_story->getPreviewMode()); - $this->assertIdentical($id_map->lookupDestinationID(['test_story']), ['test_story']); + $this->assertIdentical($id_map->lookupDestinationId(['test_story']), ['test_story']); // Test we don't have a body field. $field = FieldConfig::loadByName('node', 'test_story', 'body'); @@ -76,7 +76,7 @@ $this->assertIdentical(TRUE, $node_type_event->displaySubmitted()); $this->assertIdentical(TRUE, $node_type_event->isNewRevision()); $this->assertIdentical(DRUPAL_OPTIONAL, $node_type_event->getPreviewMode()); - $this->assertIdentical($id_map->lookupDestinationID(['test_event']), ['test_event']); + $this->assertIdentical($id_map->lookupDestinationId(['test_event']), ['test_event']); // Test we have a body field. $field = FieldConfig::loadByName('node', 'test_event', 'body'); diff -r e200cb7efeb3 -r c2387f117808 core/modules/node/tests/src/Kernel/Migrate/d6/MigrateViewModesTest.php --- a/core/modules/node/tests/src/Kernel/Migrate/d6/MigrateViewModesTest.php Thu Apr 26 11:26:54 2018 +0100 +++ b/core/modules/node/tests/src/Kernel/Migrate/d6/MigrateViewModesTest.php Tue Jul 10 15:07:59 2018 +0100 @@ -29,7 +29,7 @@ $this->assertIdentical(FALSE, is_null($view_mode), 'Preview view mode loaded.'); $this->assertIdentical('Preview', $view_mode->label(), 'View mode has correct label.'); // Test the ID map. - $this->assertIdentical(['node', 'preview'], $this->getMigration('d6_view_modes')->getIdMap()->lookupDestinationID([1])); + $this->assertIdentical(['node', 'preview'], $this->getMigration('d6_view_modes')->getIdMap()->lookupDestinationId([1])); } } diff -r e200cb7efeb3 -r c2387f117808 core/modules/node/tests/src/Kernel/Migrate/d7/MigrateNodeTest.php --- a/core/modules/node/tests/src/Kernel/Migrate/d7/MigrateNodeTest.php Thu Apr 26 11:26:54 2018 +0100 +++ b/core/modules/node/tests/src/Kernel/Migrate/d7/MigrateNodeTest.php Tue Jul 10 15:07:59 2018 +0100 @@ -72,6 +72,18 @@ } /** + * {@inheritdoc} + */ + protected function getFileMigrationInfo() { + return [ + 'path' => 'public://sites/default/files/cube.jpeg', + 'size' => '3620', + 'base_path' => 'public://', + 'plugin_id' => 'd7_file', + ]; + } + + /** * Asserts various aspects of a node. * * @param string $id @@ -164,6 +176,7 @@ $this->assertEquals('default@example.com', $node->field_email->value); $this->assertEquals('another@example.com', $node->field_email[1]->value); $this->assertEquals(CommentItemInterface::OPEN, $node->comment_node_test_content_type->status); + $this->assertEquals('3.1416', $node->field_float_list[0]->value); $node = Node::load(2); $this->assertEquals('en', $node->langcode->value); diff -r e200cb7efeb3 -r c2387f117808 core/modules/options/src/Plugin/migrate/field/d7/ListField.php --- a/core/modules/options/src/Plugin/migrate/field/d7/ListField.php Thu Apr 26 11:26:54 2018 +0100 +++ b/core/modules/options/src/Plugin/migrate/field/d7/ListField.php Tue Jul 10 15:07:59 2018 +0100 @@ -11,6 +11,7 @@ * "list_boolean" = "boolean", * "list_integer" = "list_integer", * "list_text" = "list_string", + * "list_float" = "list_float", * }, * core = {7}, * source_module = "list", diff -r e200cb7efeb3 -r c2387f117808 core/modules/path/src/Controller/PathController.php --- a/core/modules/path/src/Controller/PathController.php Thu Apr 26 11:26:54 2018 +0100 +++ b/core/modules/path/src/Controller/PathController.php Tue Jul 10 15:07:59 2018 +0100 @@ -59,7 +59,8 @@ * The request object. * * @return array - * A render array as expected by drupal_render(). + * A render array as expected by + * \Drupal\Core\Render\RendererInterface::render(). */ public function adminOverview(Request $request) { $keys = $request->query->get('search'); diff -r e200cb7efeb3 -r c2387f117808 core/modules/path/tests/src/Kernel/Migrate/d6/MigrateUrlAliasTest.php --- a/core/modules/path/tests/src/Kernel/Migrate/d6/MigrateUrlAliasTest.php Thu Apr 26 11:26:54 2018 +0100 +++ b/core/modules/path/tests/src/Kernel/Migrate/d6/MigrateUrlAliasTest.php Tue Jul 10 15:07:59 2018 +0100 @@ -68,7 +68,7 @@ ]; $path = \Drupal::service('path.alias_storage')->load($conditions); $this->assertPath('1', $conditions, $path); - $this->assertIdentical($id_map->lookupDestinationID([$path['pid']]), ['1'], "Test IdMap"); + $this->assertIdentical($id_map->lookupDestinationId([$path['pid']]), ['1'], "Test IdMap"); $conditions = [ 'source' => '/node/2', diff -r e200cb7efeb3 -r c2387f117808 core/modules/rdf/src/Tests/CommentAttributesTest.php --- a/core/modules/rdf/src/Tests/CommentAttributesTest.php Thu Apr 26 11:26:54 2018 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,376 +0,0 @@ - TRUE, - 'post comments' => TRUE, - 'skip comment approval' => TRUE, - ]); - // Allows anonymous to leave their contact information. - $this->setCommentAnonymous(COMMENT_ANONYMOUS_MAY_CONTACT); - $this->setCommentPreview(DRUPAL_OPTIONAL); - $this->setCommentForm(TRUE); - $this->setCommentSubject(TRUE); - $this->setCommentSettings('comment_default_mode', CommentManagerInterface::COMMENT_MODE_THREADED, 'Comment paging changed.'); - - // Prepares commonly used URIs. - $this->baseUri = \Drupal::url('', [], ['absolute' => TRUE]); - $this->nodeUri = $this->node->url('canonical', ['absolute' => TRUE]); - - // Set relation between node and comment. - $article_mapping = rdf_get_mapping('node', 'article'); - $comment_count_mapping = [ - 'properties' => ['sioc:num_replies'], - 'datatype' => 'xsd:integer', - 'datatype_callback' => ['callable' => 'Drupal\rdf\CommonDataConverter::rawValue'], - ]; - $article_mapping->setFieldMapping('comment_count', $comment_count_mapping)->save(); - - // Save user mapping. - $user_mapping = rdf_get_mapping('user', 'user'); - $username_mapping = [ - 'properties' => ['foaf:name'], - ]; - $user_mapping->setFieldMapping('name', $username_mapping)->save(); - $user_mapping->setFieldMapping('homepage', ['properties' => ['foaf:page'], 'mapping_type' => 'rel'])->save(); - - // Save comment mapping. - $mapping = rdf_get_mapping('comment', 'comment'); - $mapping->setBundleMapping(['types' => ['sioc:Post', 'sioct:Comment']])->save(); - $field_mappings = [ - 'subject' => [ - 'properties' => ['dc:title'], - ], - 'created' => [ - 'properties' => ['dc:date', 'dc:created'], - 'datatype' => 'xsd:dateTime', - 'datatype_callback' => ['callable' => 'Drupal\rdf\CommonDataConverter::dateIso8601Value'], - ], - 'changed' => [ - 'properties' => ['dc:modified'], - 'datatype' => 'xsd:dateTime', - 'datatype_callback' => ['callable' => 'Drupal\rdf\CommonDataConverter::dateIso8601Value'], - ], - 'comment_body' => [ - 'properties' => ['content:encoded'], - ], - 'pid' => [ - 'properties' => ['sioc:reply_of'], - 'mapping_type' => 'rel', - ], - 'uid' => [ - 'properties' => ['sioc:has_creator'], - 'mapping_type' => 'rel', - ], - 'name' => [ - 'properties' => ['foaf:name'], - ], - ]; - // Iterate over shared field mappings and save. - foreach ($field_mappings as $field_name => $field_mapping) { - $mapping->setFieldMapping($field_name, $field_mapping)->save(); - } - } - - /** - * Tests the presence of the RDFa markup for the number of comments. - */ - public function testNumberOfCommentsRdfaMarkup() { - // Posts 2 comments on behalf of registered user. - $this->saveComment($this->node->id(), $this->webUser->id()); - $this->saveComment($this->node->id(), $this->webUser->id()); - - // Tests number of comments in teaser view. - $this->drupalLogin($this->webUser); - $parser = new \EasyRdf_Parser_Rdfa(); - $graph = new \EasyRdf_Graph(); - $parser->parse($graph, $this->drupalGet('node'), 'rdfa', $this->baseUri); - - // Number of comments. - $expected_value = [ - 'type' => 'literal', - 'value' => 2, - 'datatype' => 'http://www.w3.org/2001/XMLSchema#integer', - ]; - $this->assertTrue($graph->hasProperty($this->nodeUri, 'http://rdfs.org/sioc/ns#num_replies', $expected_value), 'Number of comments found in RDF output of teaser view (sioc:num_replies).'); - - // Tests number of comments in full node view, expected value is the same. - $parser = new \EasyRdf_Parser_Rdfa(); - $graph = new \EasyRdf_Graph(); - $parser->parse($graph, $this->drupalGet('node/' . $this->node->id()), 'rdfa', $this->baseUri); - $this->assertTrue($graph->hasProperty($this->nodeUri, 'http://rdfs.org/sioc/ns#num_replies', $expected_value), 'Number of comments found in RDF output of full node view mode (sioc:num_replies).'); - } - - /** - * Tests comment author link markup has not been broken by RDF. - */ - public function testCommentRdfAuthorMarkup() { - // Post a comment as a registered user. - $this->saveComment($this->node->id(), $this->webUser->id()); - - // Give the user access to view user profiles so the profile link shows up. - user_role_grant_permissions(RoleInterface::AUTHENTICATED_ID, ['access user profiles']); - $this->drupalLogin($this->webUser); - - // Ensure that the author link still works properly after the author output - // is modified by the RDF module. - $this->drupalGet('node/' . $this->node->id()); - $this->assertLink($this->webUser->getUsername()); - $this->assertLinkByHref('user/' . $this->webUser->id()); - } - - /** - * Tests if RDFa markup for meta information is present in comments. - * - * Tests presence of RDFa markup for the title, date and author and homepage - * on comments from registered and anonymous users. - */ - public function testCommentRdfaMarkup() { - // Posts comment #1 on behalf of registered user. - $comment1 = $this->saveComment($this->node->id(), $this->webUser->id()); - - // Tests comment #1 with access to the user profile. - $this->drupalLogin($this->webUser); - $parser = new \EasyRdf_Parser_Rdfa(); - $graph = new \EasyRdf_Graph(); - $parser->parse($graph, $this->drupalGet('node/' . $this->node->id()), 'rdfa', $this->baseUri); - $this->_testBasicCommentRdfaMarkup($graph, $comment1); - - // Tests comment #1 with no access to the user profile (as anonymous user). - $this->drupalLogout(); - $parser = new \EasyRdf_Parser_Rdfa(); - $graph = new \EasyRdf_Graph(); - $parser->parse($graph, $this->drupalGet('node/' . $this->node->id()), 'rdfa', $this->baseUri); - $this->_testBasicCommentRdfaMarkup($graph, $comment1); - - // Posts comment #2 as anonymous user. - $anonymous_user = []; - $anonymous_user['name'] = $this->randomMachineName(); - $anonymous_user['mail'] = 'tester@simpletest.org'; - $anonymous_user['homepage'] = 'http://example.org/'; - $comment2 = $this->saveComment($this->node->id(), 0, $anonymous_user); - - // Tests comment #2 as anonymous user. - $parser = new \EasyRdf_Parser_Rdfa(); - $graph = new \EasyRdf_Graph(); - $parser->parse($graph, $this->drupalGet('node/' . $this->node->id()), 'rdfa', $this->baseUri); - $this->_testBasicCommentRdfaMarkup($graph, $comment2, $anonymous_user); - - // Tests comment #2 as logged in user. - $this->drupalLogin($this->webUser); - $parser = new \EasyRdf_Parser_Rdfa(); - $graph = new \EasyRdf_Graph(); - $parser->parse($graph, $this->drupalGet('node/' . $this->node->id()), 'rdfa', $this->baseUri); - $this->_testBasicCommentRdfaMarkup($graph, $comment2, $anonymous_user); - } - - /** - * Tests RDF comment replies. - */ - public function testCommentReplyOfRdfaMarkup() { - // Posts comment #1 on behalf of registered user. - $this->drupalLogin($this->webUser); - $comment_1 = $this->saveComment($this->node->id(), $this->webUser->id()); - - $comment_1_uri = $comment_1->url('canonical', ['absolute' => TRUE]); - - // Posts a reply to the first comment. - $comment_2 = $this->saveComment($this->node->id(), $this->webUser->id(), NULL, $comment_1->id()); - $comment_2_uri = $comment_2->url('canonical', ['absolute' => TRUE]); - - $parser = new \EasyRdf_Parser_Rdfa(); - $graph = new \EasyRdf_Graph(); - $parser->parse($graph, $this->drupalGet('node/' . $this->node->id()), 'rdfa', $this->baseUri); - - // Tests the reply_of relationship of a first level comment. - $expected_value = [ - 'type' => 'uri', - 'value' => $this->nodeUri, - ]; - $this->assertTrue($graph->hasProperty($comment_1_uri, 'http://rdfs.org/sioc/ns#reply_of', $expected_value), 'Comment relation to its node found in RDF output (sioc:reply_of).'); - - // Tests the reply_of relationship of a second level comment. - $expected_value = [ - 'type' => 'uri', - 'value' => $this->nodeUri, - ]; - $this->assertTrue($graph->hasProperty($comment_2_uri, 'http://rdfs.org/sioc/ns#reply_of', $expected_value), 'Comment relation to its node found in RDF output (sioc:reply_of).'); - $expected_value = [ - 'type' => 'uri', - 'value' => $comment_1_uri, - ]; - $this->assertTrue($graph->hasProperty($comment_2_uri, 'http://rdfs.org/sioc/ns#reply_of', $expected_value), 'Comment relation to its parent comment found in RDF output (sioc:reply_of).'); - } - - /** - * Helper function for testCommentRdfaMarkup(). - * - * Tests the current page for basic comment RDFa markup. - * - * @param $comment - * Comment object. - * @param $account - * An array containing information about an anonymous user. - */ - public function _testBasicCommentRdfaMarkup($graph, CommentInterface $comment, $account = []) { - $comment_uri = $comment->url('canonical', ['absolute' => TRUE]); - - // Comment type. - $expected_value = [ - 'type' => 'uri', - 'value' => 'http://rdfs.org/sioc/types#Comment', - ]; - $this->assertTrue($graph->hasProperty($comment_uri, 'http://www.w3.org/1999/02/22-rdf-syntax-ns#type', $expected_value), 'Comment type found in RDF output (sioct:Comment).'); - // Comment type. - $expected_value = [ - 'type' => 'uri', - 'value' => 'http://rdfs.org/sioc/ns#Post', - ]; - $this->assertTrue($graph->hasProperty($comment_uri, 'http://www.w3.org/1999/02/22-rdf-syntax-ns#type', $expected_value), 'Comment type found in RDF output (sioc:Post).'); - - // Comment title. - $expected_value = [ - 'type' => 'literal', - 'value' => $comment->getSubject(), - 'lang' => 'en', - ]; - $this->assertTrue($graph->hasProperty($comment_uri, 'http://purl.org/dc/terms/title', $expected_value), 'Comment subject found in RDF output (dc:title).'); - - // Comment date. - $expected_value = [ - 'type' => 'literal', - 'value' => format_date($comment->getCreatedTime(), 'custom', 'c', 'UTC'), - 'datatype' => 'http://www.w3.org/2001/XMLSchema#dateTime', - ]; - $this->assertTrue($graph->hasProperty($comment_uri, 'http://purl.org/dc/terms/date', $expected_value), 'Comment date found in RDF output (dc:date).'); - // Comment date. - $expected_value = [ - 'type' => 'literal', - 'value' => format_date($comment->getCreatedTime(), 'custom', 'c', 'UTC'), - 'datatype' => 'http://www.w3.org/2001/XMLSchema#dateTime', - ]; - $this->assertTrue($graph->hasProperty($comment_uri, 'http://purl.org/dc/terms/created', $expected_value), 'Comment date found in RDF output (dc:created).'); - - // Comment body. - $expected_value = [ - 'type' => 'literal', - 'value' => $comment->comment_body->value . "\n", - 'lang' => 'en', - ]; - $this->assertTrue($graph->hasProperty($comment_uri, 'http://purl.org/rss/1.0/modules/content/encoded', $expected_value), 'Comment body found in RDF output (content:encoded).'); - - // The comment author can be a registered user or an anonymous user. - if ($comment->getOwnerId() > 0) { - $author_uri = \Drupal::url('entity.user.canonical', ['user' => $comment->getOwnerId()], ['absolute' => TRUE]); - // Comment relation to author. - $expected_value = [ - 'type' => 'uri', - 'value' => $author_uri, - ]; - $this->assertTrue($graph->hasProperty($comment_uri, 'http://rdfs.org/sioc/ns#has_creator', $expected_value), 'Comment relation to author found in RDF output (sioc:has_creator).'); - } - else { - // The author is expected to be a blank node. - $author_uri = $graph->get($comment_uri, ''); - if ($author_uri instanceof \EasyRdf_Resource) { - $this->assertTrue($author_uri->isBnode(), 'Comment relation to author found in RDF output (sioc:has_creator) and author is blank node.'); - } - else { - $this->fail('Comment relation to author found in RDF output (sioc:has_creator).'); - } - } - - // Author name. - $name = empty($account["name"]) ? $this->webUser->getUsername() : $account["name"] . " (not verified)"; - $expected_value = [ - 'type' => 'literal', - 'value' => $name, - ]; - $this->assertTrue($graph->hasProperty($author_uri, 'http://xmlns.com/foaf/0.1/name', $expected_value), 'Comment author name found in RDF output (foaf:name).'); - - // Comment author homepage (only for anonymous authors). - if ($comment->getOwnerId() == 0) { - $expected_value = [ - 'type' => 'uri', - 'value' => 'http://example.org/', - ]; - $this->assertTrue($graph->hasProperty($author_uri, 'http://xmlns.com/foaf/0.1/page', $expected_value), 'Comment author link found in RDF output (foaf:page).'); - } - } - - /** - * Creates a comment entity. - * - * @param $nid - * Node id which will hold the comment. - * @param $uid - * User id of the author of the comment. Can be NULL if $contact provided. - * @param $contact - * Set to NULL for no contact info, TRUE to ignore success checking, and - * array of values to set contact info. - * @param $pid - * Comment id of the parent comment in a thread. - * - * @return \Drupal\comment\Entity\Comment - * The saved comment. - */ - public function saveComment($nid, $uid, $contact = NULL, $pid = 0) { - $values = [ - 'entity_id' => $nid, - 'entity_type' => 'node', - 'field_name' => 'comment', - 'uid' => $uid, - 'pid' => $pid, - 'subject' => $this->randomMachineName(), - 'comment_body' => $this->randomMachineName(), - 'status' => 1, - ]; - if ($contact) { - $values += $contact; - } - - $comment = Comment::create($values); - $comment->save(); - return $comment; - } - -} diff -r e200cb7efeb3 -r c2387f117808 core/modules/rdf/src/Tests/Field/TestDataConverter.php --- a/core/modules/rdf/src/Tests/Field/TestDataConverter.php Thu Apr 26 11:26:54 2018 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,23 +0,0 @@ -drupalGet(''); - - $element = $this->xpath('//html[contains(@prefix, :prefix_binding)]', [ - ':prefix_binding' => 'rdfs: http://www.w3.org/2000/01/rdf-schema#', - ]); - $this->assertTrue(!empty($element), 'A prefix declared once is displayed.'); - - $element = $this->xpath('//html[contains(@prefix, :prefix_binding)]', [ - ':prefix_binding' => 'foaf: http://xmlns.com/foaf/0.1/', - ]); - $this->assertTrue(!empty($element), 'The same prefix declared in several implementations of hook_rdf_namespaces() is valid as long as all the namespaces are the same.'); - - $element = $this->xpath('//html[contains(@prefix, :prefix_binding)]', [ - ':prefix_binding' => 'foaf1: http://xmlns.com/foaf/0.1/', - ]); - $this->assertTrue(!empty($element), 'Two prefixes can be assigned the same namespace.'); - - $element = $this->xpath('//html[contains(@prefix, :prefix_binding)]', [ - ':prefix_binding' => 'dc: http://purl.org/dc/terms/', - ]); - $this->assertTrue(!empty($element), 'When a prefix has conflicting namespaces, the first declared one is used.'); - } - -} diff -r e200cb7efeb3 -r c2387f117808 core/modules/rdf/src/Tests/ImageFieldAttributesTest.php --- a/core/modules/rdf/src/Tests/ImageFieldAttributesTest.php Thu Apr 26 11:26:54 2018 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,113 +0,0 @@ -fieldName = 'field_image'; - - // Create the image field. - $this->createImageField($this->fieldName, 'article'); - - // Set the RDF mapping for the new field. - rdf_get_mapping('node', 'article') - ->setFieldMapping($this->fieldName, [ - 'properties' => ['og:image'], - 'mapping_type' => 'rel', - ]) - ->setBundleMapping(['types' => []]) - ->save(); - - // Get the test image that simpletest provides. - $image = current($this->drupalGetTestFiles('image')); - - // Save a node with the image. - $nid = $this->uploadNodeImage($image, $this->fieldName, 'article', $this->randomMachineName()); - $this->node = Node::load($nid); - $this->file = File::load($this->node->{$this->fieldName}->target_id); - } - - /** - * Tests that image fields in teasers have correct resources. - */ - public function testNodeTeaser() { - // Set the display options for the teaser. - $display_options = [ - 'type' => 'image', - 'settings' => ['image_style' => 'medium', 'image_link' => 'content'], - ]; - $display = entity_get_display('node', 'article', 'teaser'); - $display->setComponent($this->fieldName, $display_options) - ->save(); - - // Render the teaser. - $node_render_array = node_view($this->node, 'teaser'); - $html = \Drupal::service('renderer')->renderRoot($node_render_array); - - // Parse the teaser. - $parser = new \EasyRdf_Parser_Rdfa(); - $graph = new \EasyRdf_Graph(); - $base_uri = \Drupal::url('', [], ['absolute' => TRUE]); - $parser->parse($graph, $html, 'rdfa', $base_uri); - - // Construct the node and image URIs for testing. - $node_uri = $this->node->url('canonical', ['absolute' => TRUE]); - $image_uri = ImageStyle::load('medium')->buildUrl($this->file->getFileUri()); - - // Test relations from node to image. - $expected_value = [ - 'type' => 'uri', - 'value' => $image_uri, - ]; - $this->assertTrue($graph->hasProperty($node_uri, 'http://ogp.me/ns#image', $expected_value), 'Node to file relation found in RDF output (og:image).'); - - // Test image type. - $expected_value = [ - 'type' => 'uri', - 'value' => 'http://xmlns.com/foaf/0.1/Image', - ]; - $this->assertTrue($graph->hasProperty($image_uri, 'http://www.w3.org/1999/02/22-rdf-syntax-ns#type', $expected_value), 'Image type found in RDF output (foaf:Image).'); - } - -} diff -r e200cb7efeb3 -r c2387f117808 core/modules/rdf/tests/rdf_test/rdf_test.info.yml --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/core/modules/rdf/tests/rdf_test/rdf_test.info.yml Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,8 @@ +name: 'RDF test module' +type: module +description: 'Test functionality for the RDF module.' +package: Testing +version: VERSION +core: 8.x +dependencies: + - rdf diff -r e200cb7efeb3 -r c2387f117808 core/modules/rdf/tests/rdf_test/src/TestDataConverter.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/core/modules/rdf/tests/rdf_test/src/TestDataConverter.php Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,23 @@ + TRUE, + 'post comments' => TRUE, + 'skip comment approval' => TRUE, + ]); + // Allows anonymous to leave their contact information. + $this->setCommentAnonymous(COMMENT_ANONYMOUS_MAY_CONTACT); + $this->setCommentPreview(DRUPAL_OPTIONAL); + $this->setCommentForm(TRUE); + $this->setCommentSubject(TRUE); + $this->setCommentSettings('comment_default_mode', CommentManagerInterface::COMMENT_MODE_THREADED, 'Comment paging changed.'); + + // Prepares commonly used URIs. + $this->baseUri = \Drupal::url('', [], ['absolute' => TRUE]); + $this->nodeUri = $this->node->url('canonical', ['absolute' => TRUE]); + + // Set relation between node and comment. + $article_mapping = rdf_get_mapping('node', 'article'); + $comment_count_mapping = [ + 'properties' => ['sioc:num_replies'], + 'datatype' => 'xsd:integer', + 'datatype_callback' => ['callable' => 'Drupal\rdf\CommonDataConverter::rawValue'], + ]; + $article_mapping->setFieldMapping('comment_count', $comment_count_mapping)->save(); + + // Save user mapping. + $user_mapping = rdf_get_mapping('user', 'user'); + $username_mapping = [ + 'properties' => ['foaf:name'], + ]; + $user_mapping->setFieldMapping('name', $username_mapping)->save(); + $user_mapping->setFieldMapping('homepage', ['properties' => ['foaf:page'], 'mapping_type' => 'rel'])->save(); + + // Save comment mapping. + $mapping = rdf_get_mapping('comment', 'comment'); + $mapping->setBundleMapping(['types' => ['sioc:Post', 'sioct:Comment']])->save(); + $field_mappings = [ + 'subject' => [ + 'properties' => ['dc:title'], + ], + 'created' => [ + 'properties' => ['dc:date', 'dc:created'], + 'datatype' => 'xsd:dateTime', + 'datatype_callback' => ['callable' => 'Drupal\rdf\CommonDataConverter::dateIso8601Value'], + ], + 'changed' => [ + 'properties' => ['dc:modified'], + 'datatype' => 'xsd:dateTime', + 'datatype_callback' => ['callable' => 'Drupal\rdf\CommonDataConverter::dateIso8601Value'], + ], + 'comment_body' => [ + 'properties' => ['content:encoded'], + ], + 'pid' => [ + 'properties' => ['sioc:reply_of'], + 'mapping_type' => 'rel', + ], + 'uid' => [ + 'properties' => ['sioc:has_creator'], + 'mapping_type' => 'rel', + ], + 'name' => [ + 'properties' => ['foaf:name'], + ], + ]; + // Iterate over shared field mappings and save. + foreach ($field_mappings as $field_name => $field_mapping) { + $mapping->setFieldMapping($field_name, $field_mapping)->save(); + } + } + + /** + * Tests the presence of the RDFa markup for the number of comments. + */ + public function testNumberOfCommentsRdfaMarkup() { + // Posts 2 comments on behalf of registered user. + $this->saveComment($this->node->id(), $this->webUser->id()); + $this->saveComment($this->node->id(), $this->webUser->id()); + + // Tests number of comments in teaser view. + $this->drupalLogin($this->webUser); + $parser = new \EasyRdf_Parser_Rdfa(); + $graph = new \EasyRdf_Graph(); + $parser->parse($graph, $this->drupalGet('node'), 'rdfa', $this->baseUri); + + // Number of comments. + $expected_value = [ + 'type' => 'literal', + 'value' => 2, + 'datatype' => 'http://www.w3.org/2001/XMLSchema#integer', + ]; + $this->assertTrue($graph->hasProperty($this->nodeUri, 'http://rdfs.org/sioc/ns#num_replies', $expected_value), 'Number of comments found in RDF output of teaser view (sioc:num_replies).'); + + // Tests number of comments in full node view, expected value is the same. + $parser = new \EasyRdf_Parser_Rdfa(); + $graph = new \EasyRdf_Graph(); + $parser->parse($graph, $this->drupalGet('node/' . $this->node->id()), 'rdfa', $this->baseUri); + $this->assertTrue($graph->hasProperty($this->nodeUri, 'http://rdfs.org/sioc/ns#num_replies', $expected_value), 'Number of comments found in RDF output of full node view mode (sioc:num_replies).'); + } + + /** + * Tests comment author link markup has not been broken by RDF. + */ + public function testCommentRdfAuthorMarkup() { + // Post a comment as a registered user. + $this->saveComment($this->node->id(), $this->webUser->id()); + + // Give the user access to view user profiles so the profile link shows up. + user_role_grant_permissions(RoleInterface::AUTHENTICATED_ID, ['access user profiles']); + $this->drupalLogin($this->webUser); + + // Ensure that the author link still works properly after the author output + // is modified by the RDF module. + $this->drupalGet('node/' . $this->node->id()); + $this->assertLink($this->webUser->getUsername()); + $this->assertLinkByHref('user/' . $this->webUser->id()); + } + + /** + * Tests if RDFa markup for meta information is present in comments. + * + * Tests presence of RDFa markup for the title, date and author and homepage + * on comments from registered and anonymous users. + */ + public function testCommentRdfaMarkup() { + // Posts comment #1 on behalf of registered user. + $comment1 = $this->saveComment($this->node->id(), $this->webUser->id()); + + // Tests comment #1 with access to the user profile. + $this->drupalLogin($this->webUser); + $parser = new \EasyRdf_Parser_Rdfa(); + $graph = new \EasyRdf_Graph(); + $parser->parse($graph, $this->drupalGet('node/' . $this->node->id()), 'rdfa', $this->baseUri); + $this->_testBasicCommentRdfaMarkup($graph, $comment1); + + // Tests comment #1 with no access to the user profile (as anonymous user). + $this->drupalLogout(); + $parser = new \EasyRdf_Parser_Rdfa(); + $graph = new \EasyRdf_Graph(); + $parser->parse($graph, $this->drupalGet('node/' . $this->node->id()), 'rdfa', $this->baseUri); + $this->_testBasicCommentRdfaMarkup($graph, $comment1); + + // Posts comment #2 as anonymous user. + $anonymous_user = []; + $anonymous_user['name'] = $this->randomMachineName(); + $anonymous_user['mail'] = 'tester@simpletest.org'; + $anonymous_user['homepage'] = 'http://example.org/'; + $comment2 = $this->saveComment($this->node->id(), 0, $anonymous_user); + + // Tests comment #2 as anonymous user. + $parser = new \EasyRdf_Parser_Rdfa(); + $graph = new \EasyRdf_Graph(); + $parser->parse($graph, $this->drupalGet('node/' . $this->node->id()), 'rdfa', $this->baseUri); + $this->_testBasicCommentRdfaMarkup($graph, $comment2, $anonymous_user); + + // Tests comment #2 as logged in user. + $this->drupalLogin($this->webUser); + $parser = new \EasyRdf_Parser_Rdfa(); + $graph = new \EasyRdf_Graph(); + $parser->parse($graph, $this->drupalGet('node/' . $this->node->id()), 'rdfa', $this->baseUri); + $this->_testBasicCommentRdfaMarkup($graph, $comment2, $anonymous_user); + } + + /** + * Tests RDF comment replies. + */ + public function testCommentReplyOfRdfaMarkup() { + // Posts comment #1 on behalf of registered user. + $this->drupalLogin($this->webUser); + $comment_1 = $this->saveComment($this->node->id(), $this->webUser->id()); + + $comment_1_uri = $comment_1->url('canonical', ['absolute' => TRUE]); + + // Posts a reply to the first comment. + $comment_2 = $this->saveComment($this->node->id(), $this->webUser->id(), NULL, $comment_1->id()); + $comment_2_uri = $comment_2->url('canonical', ['absolute' => TRUE]); + + $parser = new \EasyRdf_Parser_Rdfa(); + $graph = new \EasyRdf_Graph(); + $parser->parse($graph, $this->drupalGet('node/' . $this->node->id()), 'rdfa', $this->baseUri); + + // Tests the reply_of relationship of a first level comment. + $expected_value = [ + 'type' => 'uri', + 'value' => $this->nodeUri, + ]; + $this->assertTrue($graph->hasProperty($comment_1_uri, 'http://rdfs.org/sioc/ns#reply_of', $expected_value), 'Comment relation to its node found in RDF output (sioc:reply_of).'); + + // Tests the reply_of relationship of a second level comment. + $expected_value = [ + 'type' => 'uri', + 'value' => $this->nodeUri, + ]; + $this->assertTrue($graph->hasProperty($comment_2_uri, 'http://rdfs.org/sioc/ns#reply_of', $expected_value), 'Comment relation to its node found in RDF output (sioc:reply_of).'); + $expected_value = [ + 'type' => 'uri', + 'value' => $comment_1_uri, + ]; + $this->assertTrue($graph->hasProperty($comment_2_uri, 'http://rdfs.org/sioc/ns#reply_of', $expected_value), 'Comment relation to its parent comment found in RDF output (sioc:reply_of).'); + } + + /** + * Helper function for testCommentRdfaMarkup(). + * + * Tests the current page for basic comment RDFa markup. + * + * @param $comment + * Comment object. + * @param $account + * An array containing information about an anonymous user. + */ + public function _testBasicCommentRdfaMarkup($graph, CommentInterface $comment, $account = []) { + $comment_uri = $comment->url('canonical', ['absolute' => TRUE]); + + // Comment type. + $expected_value = [ + 'type' => 'uri', + 'value' => 'http://rdfs.org/sioc/types#Comment', + ]; + $this->assertTrue($graph->hasProperty($comment_uri, 'http://www.w3.org/1999/02/22-rdf-syntax-ns#type', $expected_value), 'Comment type found in RDF output (sioct:Comment).'); + // Comment type. + $expected_value = [ + 'type' => 'uri', + 'value' => 'http://rdfs.org/sioc/ns#Post', + ]; + $this->assertTrue($graph->hasProperty($comment_uri, 'http://www.w3.org/1999/02/22-rdf-syntax-ns#type', $expected_value), 'Comment type found in RDF output (sioc:Post).'); + + // Comment title. + $expected_value = [ + 'type' => 'literal', + 'value' => $comment->getSubject(), + 'lang' => 'en', + ]; + $this->assertTrue($graph->hasProperty($comment_uri, 'http://purl.org/dc/terms/title', $expected_value), 'Comment subject found in RDF output (dc:title).'); + + // Comment date. + $expected_value = [ + 'type' => 'literal', + 'value' => format_date($comment->getCreatedTime(), 'custom', 'c', 'UTC'), + 'datatype' => 'http://www.w3.org/2001/XMLSchema#dateTime', + ]; + $this->assertTrue($graph->hasProperty($comment_uri, 'http://purl.org/dc/terms/date', $expected_value), 'Comment date found in RDF output (dc:date).'); + // Comment date. + $expected_value = [ + 'type' => 'literal', + 'value' => format_date($comment->getCreatedTime(), 'custom', 'c', 'UTC'), + 'datatype' => 'http://www.w3.org/2001/XMLSchema#dateTime', + ]; + $this->assertTrue($graph->hasProperty($comment_uri, 'http://purl.org/dc/terms/created', $expected_value), 'Comment date found in RDF output (dc:created).'); + + // Comment body. + $expected_value = [ + 'type' => 'literal', + 'value' => $comment->comment_body->value . "\n", + 'lang' => 'en', + ]; + $this->assertTrue($graph->hasProperty($comment_uri, 'http://purl.org/rss/1.0/modules/content/encoded', $expected_value), 'Comment body found in RDF output (content:encoded).'); + + // The comment author can be a registered user or an anonymous user. + if ($comment->getOwnerId() > 0) { + $author_uri = \Drupal::url('entity.user.canonical', ['user' => $comment->getOwnerId()], ['absolute' => TRUE]); + // Comment relation to author. + $expected_value = [ + 'type' => 'uri', + 'value' => $author_uri, + ]; + $this->assertTrue($graph->hasProperty($comment_uri, 'http://rdfs.org/sioc/ns#has_creator', $expected_value), 'Comment relation to author found in RDF output (sioc:has_creator).'); + } + else { + // The author is expected to be a blank node. + $author_uri = $graph->get($comment_uri, ''); + if ($author_uri instanceof \EasyRdf_Resource) { + $this->assertTrue($author_uri->isBnode(), 'Comment relation to author found in RDF output (sioc:has_creator) and author is blank node.'); + } + else { + $this->fail('Comment relation to author found in RDF output (sioc:has_creator).'); + } + } + + // Author name. + $name = empty($account["name"]) ? $this->webUser->getUsername() : $account["name"] . " (not verified)"; + $expected_value = [ + 'type' => 'literal', + 'value' => $name, + ]; + $this->assertTrue($graph->hasProperty($author_uri, 'http://xmlns.com/foaf/0.1/name', $expected_value), 'Comment author name found in RDF output (foaf:name).'); + + // Comment author homepage (only for anonymous authors). + if ($comment->getOwnerId() == 0) { + $expected_value = [ + 'type' => 'uri', + 'value' => 'http://example.org/', + ]; + $this->assertTrue($graph->hasProperty($author_uri, 'http://xmlns.com/foaf/0.1/page', $expected_value), 'Comment author link found in RDF output (foaf:page).'); + } + } + + /** + * Creates a comment entity. + * + * @param $nid + * Node id which will hold the comment. + * @param $uid + * User id of the author of the comment. Can be NULL if $contact provided. + * @param $contact + * Set to NULL for no contact info, TRUE to ignore success checking, and + * array of values to set contact info. + * @param $pid + * Comment id of the parent comment in a thread. + * + * @return \Drupal\comment\Entity\Comment + * The saved comment. + */ + public function saveComment($nid, $uid, $contact = NULL, $pid = 0) { + $values = [ + 'entity_id' => $nid, + 'entity_type' => 'node', + 'field_name' => 'comment', + 'uid' => $uid, + 'pid' => $pid, + 'subject' => $this->randomMachineName(), + 'comment_body' => $this->randomMachineName(), + 'status' => 1, + ]; + if ($contact) { + $values += $contact; + } + + $comment = Comment::create($values); + $comment->save(); + return $comment; + } + +} diff -r e200cb7efeb3 -r c2387f117808 core/modules/rdf/tests/src/Functional/FileFieldAttributesTest.php --- a/core/modules/rdf/tests/src/Functional/FileFieldAttributesTest.php Thu Apr 26 11:26:54 2018 +0100 +++ b/core/modules/rdf/tests/src/Functional/FileFieldAttributesTest.php Tue Jul 10 15:07:59 2018 +0100 @@ -2,7 +2,7 @@ namespace Drupal\Tests\rdf\Functional; -use Drupal\file\Tests\FileFieldTestBase; +use Drupal\Tests\file\Functional\FileFieldTestBase; use Drupal\file\Entity\File; /** diff -r e200cb7efeb3 -r c2387f117808 core/modules/rdf/tests/src/Functional/GetRdfNamespacesTest.php --- a/core/modules/rdf/tests/src/Functional/GetRdfNamespacesTest.php Thu Apr 26 11:26:54 2018 +0100 +++ b/core/modules/rdf/tests/src/Functional/GetRdfNamespacesTest.php Tue Jul 10 15:07:59 2018 +0100 @@ -22,6 +22,25 @@ * Tests getting RDF namespaces. */ public function testGetRdfNamespaces() { + // Fetches the front page and extracts RDFa 1.1 prefixes. + $this->drupalGet(''); + + // We have to use the find() method on the driver directly because //html is + // prepended to all xpath queries otherwise. + $driver = $this->getSession()->getDriver(); + + $element = $driver->find('//html[contains(@prefix, "rdfs: http://www.w3.org/2000/01/rdf-schema#")]'); + $this->assertCount(1, $element, 'A prefix declared once is displayed.'); + + $element = $driver->find('//html[contains(@prefix, "foaf: http://xmlns.com/foaf/0.1/")]'); + $this->assertCount(1, $element, 'The same prefix declared in several implementations of hook_rdf_namespaces() is valid as long as all the namespaces are the same.'); + + $element = $driver->find('//html[contains(@prefix, "foaf1: http://xmlns.com/foaf/0.1/")]'); + $this->assertCount(1, $element, 'Two prefixes can be assigned the same namespace.'); + + $element = $driver->find('//html[contains(@prefix, "dc: http://purl.org/dc/terms/")]'); + $this->assertCount(1, $element, 'When a prefix has conflicting namespaces, the first declared one is used.'); + // Get all RDF namespaces. $ns = rdf_get_namespaces(); diff -r e200cb7efeb3 -r c2387f117808 core/modules/rdf/tests/src/Functional/Hal/RdfMappingHalJsonAnonTest.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/core/modules/rdf/tests/src/Functional/Hal/RdfMappingHalJsonAnonTest.php Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,30 @@ +fieldName = 'field_image'; + + // Create the image field. + $this->createImageField($this->fieldName, 'article'); + + // Set the RDF mapping for the new field. + rdf_get_mapping('node', 'article') + ->setFieldMapping($this->fieldName, [ + 'properties' => ['og:image'], + 'mapping_type' => 'rel', + ]) + ->setBundleMapping(['types' => []]) + ->save(); + + // Get the test image that simpletest provides. + $image = current($this->drupalGetTestFiles('image')); + + // Save a node with the image. + $nid = $this->uploadNodeImage($image, $this->fieldName, 'article', $this->randomMachineName()); + $this->node = Node::load($nid); + $this->file = File::load($this->node->{$this->fieldName}->target_id); + } + + /** + * Tests that image fields in teasers have correct resources. + */ + public function testNodeTeaser() { + // Set the display options for the teaser. + $display_options = [ + 'type' => 'image', + 'settings' => ['image_style' => 'medium', 'image_link' => 'content'], + ]; + $display = entity_get_display('node', 'article', 'teaser'); + $display->setComponent($this->fieldName, $display_options) + ->save(); + + // Render the teaser. + $node_render_array = node_view($this->node, 'teaser'); + $html = \Drupal::service('renderer')->renderRoot($node_render_array); + + // Parse the teaser. + $parser = new \EasyRdf_Parser_Rdfa(); + $graph = new \EasyRdf_Graph(); + $base_uri = \Drupal::url('', [], ['absolute' => TRUE]); + $parser->parse($graph, $html, 'rdfa', $base_uri); + + // Construct the node and image URIs for testing. + $node_uri = $this->node->url('canonical', ['absolute' => TRUE]); + $image_uri = ImageStyle::load('medium')->buildUrl($this->file->getFileUri()); + + // Test relations from node to image. + $expected_value = [ + 'type' => 'uri', + 'value' => $image_uri, + ]; + $this->assertTrue($graph->hasProperty($node_uri, 'http://ogp.me/ns#image', $expected_value), 'Node to file relation found in RDF output (og:image).'); + + // Test image type. + $expected_value = [ + 'type' => 'uri', + 'value' => 'http://xmlns.com/foaf/0.1/Image', + ]; + $this->assertTrue($graph->hasProperty($image_uri, 'http://www.w3.org/1999/02/22-rdf-syntax-ns#type', $expected_value), 'Image type found in RDF output (foaf:Image).'); + } + +} diff -r e200cb7efeb3 -r c2387f117808 core/modules/rdf/tests/src/Functional/NodeAttributesTest.php --- a/core/modules/rdf/tests/src/Functional/NodeAttributesTest.php Thu Apr 26 11:26:54 2018 +0100 +++ b/core/modules/rdf/tests/src/Functional/NodeAttributesTest.php Tue Jul 10 15:07:59 2018 +0100 @@ -2,7 +2,7 @@ namespace Drupal\Tests\rdf\Functional; -use Drupal\node\Tests\NodeTestBase; +use Drupal\Tests\node\Functional\NodeTestBase; /** * Tests the RDFa markup of Nodes. diff -r e200cb7efeb3 -r c2387f117808 core/modules/rdf/tests/src/Functional/Rest/RdfMappingJsonAnonTest.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/core/modules/rdf/tests/src/Functional/Rest/RdfMappingJsonAnonTest.php Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,24 @@ +grantPermissionsToTestedRole(['administer site configuration']); + } + + /** + * {@inheritdoc} + */ + protected function createEntity() { + // Create a "Camelids" node type. + $camelids = NodeType::create([ + 'name' => 'Camelids', + 'type' => 'camelids', + ]); + + $camelids->save(); + + // Create the RDF mapping. + $llama = RdfMapping::create([ + 'targetEntityType' => 'node', + 'bundle' => 'camelids', + ]); + $llama->setBundleMapping([ + 'types' => ['sioc:Item', 'foaf:Document'], + ]) + ->setFieldMapping('title', [ + 'properties' => ['dc:title'], + ]) + ->setFieldMapping('created', [ + 'properties' => ['dc:date', 'dc:created'], + 'datatype' => 'xsd:dateTime', + 'datatype_callback' => ['callable' => 'Drupal\rdf\CommonDataConverter::dateIso8601Value'], + ]) + ->save(); + + return $llama; + } + + /** + * {@inheritdoc} + */ + protected function getExpectedNormalizedEntity() { + return [ + 'bundle' => 'camelids', + 'dependencies' => [ + 'config' => [ + 'node.type.camelids', + ], + 'module' => [ + 'node', + ], + ], + 'fieldMappings' => [ + 'title' => [ + 'properties' => [ + 'dc:title', + ], + ], + 'created' => [ + 'properties' => [ + 'dc:date', + 'dc:created', + ], + 'datatype' => 'xsd:dateTime', + 'datatype_callback' => [ + 'callable' => 'Drupal\rdf\CommonDataConverter::dateIso8601Value', + ], + ], + ], + 'id' => 'node.camelids', + 'langcode' => 'en', + 'status' => TRUE, + 'targetEntityType' => 'node', + 'types' => [ + 'sioc:Item', + 'foaf:Document', + ], + 'uuid' => $this->entity->uuid(), + ]; + } + + /** + * {@inheritdoc} + */ + protected function getNormalizedPostEntity() { + // @todo Update in https://www.drupal.org/node/2300677. + } + + /** + * {@inheritdoc} + */ + protected function getExpectedCacheContexts() { + return [ + 'user.permissions', + ]; + } + +} diff -r e200cb7efeb3 -r c2387f117808 core/modules/rdf/tests/src/Functional/Rest/RdfMappingXmlAnonTest.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/core/modules/rdf/tests/src/Functional/Rest/RdfMappingXmlAnonTest.php Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,26 @@ +setFieldMapping($this->fieldName, [ 'properties' => ['schema:interactionCount'], 'datatype_callback' => [ - 'callable' => 'Drupal\rdf\Tests\Field\TestDataConverter::convertFoo', + 'callable' => 'Drupal\rdf_test\TestDataConverter::convertFoo', ], ])->save(); diff -r e200cb7efeb3 -r c2387f117808 core/modules/rdf/tests/src/Kernel/Field/LinkFieldRdfaTest.php --- a/core/modules/rdf/tests/src/Kernel/Field/LinkFieldRdfaTest.php Thu Apr 26 11:26:54 2018 +0100 +++ b/core/modules/rdf/tests/src/Kernel/Field/LinkFieldRdfaTest.php Tue Jul 10 15:07:59 2018 +0100 @@ -42,7 +42,7 @@ */ public function testAllFormattersExternal() { // Set up test values. - $this->testValue = 'http://test.me/foo/bar/neque/porro/quisquam/est/qui-dolorem?foo/bar/neque/porro/quisquam/est/qui-dolorem'; + $this->testValue = 'http://test.me/foo/bar/neque/porro/quisquam/est/qui-dolorem?path=foo/bar/neque/porro/quisquam/est/qui-dolorem'; $this->entity = EntityTest::create([]); $this->entity->{$this->fieldName}->uri = $this->testValue; diff -r e200cb7efeb3 -r c2387f117808 core/modules/responsive_image/src/Plugin/Field/FieldFormatter/ResponsiveImageFormatter.php --- a/core/modules/responsive_image/src/Plugin/Field/FieldFormatter/ResponsiveImageFormatter.php Thu Apr 26 11:26:54 2018 +0100 +++ b/core/modules/responsive_image/src/Plugin/Field/FieldFormatter/ResponsiveImageFormatter.php Tue Jul 10 15:07:59 2018 +0100 @@ -138,7 +138,7 @@ $elements['responsive_image_style'] = [ '#title' => t('Responsive image style'), '#type' => 'select', - '#default_value' => $this->getSetting('responsive_image_style'), + '#default_value' => $this->getSetting('responsive_image_style') ?: NULL, '#required' => TRUE, '#options' => $responsive_image_options, '#description' => [ diff -r e200cb7efeb3 -r c2387f117808 core/modules/responsive_image/tests/src/Functional/Hal/ResponsiveImageStyleHalJsonAnonTest.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/core/modules/responsive_image/tests/src/Functional/Hal/ResponsiveImageStyleHalJsonAnonTest.php Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,30 @@ +grantPermissionsToTestedRole(['administer responsive images']); + } + + /** + * {@inheritdoc} + */ + protected function createEntity() { + // Create a "Camelids" responsive image style. + $camelids = ResponsiveImageStyle::create([ + 'id' => 'camelids', + 'label' => 'Camelids', + ]); + $camelids->setBreakpointGroup('test_group'); + $camelids->setFallbackImageStyle('fallback'); + $camelids->addImageStyleMapping('test_breakpoint', '1x', [ + 'image_mapping_type' => 'image_style', + 'image_mapping' => 'small', + ]); + $camelids->addImageStyleMapping('test_breakpoint', '2x', [ + 'image_mapping_type' => 'sizes', + 'image_mapping' => [ + 'sizes' => '(min-width:700px) 700px, 100vw', + 'sizes_image_styles' => [ + 'medium' => 'medium', + 'large' => 'large', + ], + ], + ]); + $camelids->save(); + + return $camelids; + } + + /** + * {@inheritdoc} + */ + protected function getExpectedNormalizedEntity() { + return [ + 'breakpoint_group' => 'test_group', + 'dependencies' => [ + 'config' => [ + 'image.style.large', + 'image.style.medium', + ], + ], + 'fallback_image_style' => 'fallback', + 'id' => 'camelids', + 'image_style_mappings' => [ + 0 => [ + 'breakpoint_id' => 'test_breakpoint', + 'image_mapping' => 'small', + 'image_mapping_type' => 'image_style', + 'multiplier' => '1x', + ], + 1 => [ + 'breakpoint_id' => 'test_breakpoint', + 'image_mapping' => [ + 'sizes' => '(min-width:700px) 700px, 100vw', + 'sizes_image_styles' => [ + 'large' => 'large', + 'medium' => 'medium', + ], + ], + 'image_mapping_type' => 'sizes', + 'multiplier' => '2x', + ], + ], + 'label' => 'Camelids', + 'langcode' => 'en', + 'status' => TRUE, + 'uuid' => $this->entity->uuid(), + ]; + } + + /** + * {@inheritdoc} + */ + protected function getNormalizedPostEntity() { + // @todo Update in https://www.drupal.org/node/2300677. + } + + /** + * {@inheritdoc} + */ + protected function getExpectedUnauthorizedAccessMessage($method) { + if ($this->config('rest.settings')->get('bc_entity_resource_permissions')) { + return parent::getExpectedUnauthorizedAccessMessage($method); + } + + return "The 'administer responsive images' permission is required."; + } + +} diff -r e200cb7efeb3 -r c2387f117808 core/modules/responsive_image/tests/src/Functional/Rest/ResponsiveImageStyleXmlAnonTest.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/core/modules/responsive_image/tests/src/Functional/Rest/ResponsiveImageStyleXmlAnonTest.php Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,26 @@ +enableViewsTestModule(); + + // Create a responsive image style. + $responsive_image_style = ResponsiveImageStyle::create([ + 'id' => self::RESPONSIVE_IMAGE_STYLE_ID, + 'label' => 'Foo', + 'breakpoint_group' => 'responsive_image_test_module', + ]); + // Create an image field to be used with a responsive image formatter. + FieldStorageConfig::create([ + 'type' => 'image', + 'entity_type' => 'entity_test', + 'field_name' => 'bar', + ])->save(); + FieldConfig::create([ + 'entity_type' => 'entity_test', + 'bundle' => 'entity_test', + 'field_name' => 'bar', + ])->save(); + + $responsive_image_style + ->addImageStyleMapping('responsive_image_test_module.mobile', '1x', [ + 'image_mapping_type' => 'image_style', + 'image_mapping' => 'thumbnail', + ]) + ->addImageStyleMapping('responsive_image_test_module.narrow', '1x', [ + 'image_mapping_type' => 'image_style', + 'image_mapping' => 'medium', + ]) + // Test the normal output of mapping to an image style. + ->addImageStyleMapping('responsive_image_test_module.wide', '1x', [ + 'image_mapping_type' => 'image_style', + 'image_mapping' => 'large', + ]) + ->save(); + + $admin_user = $this->drupalCreateUser(['administer views']); + $this->drupalLogin($admin_user); + } + + /** + * Tests integration with Views. + */ + public function testViewsAddResponsiveImageField() { + // Add the image field to the View. + $this->drupalGet('admin/structure/views/nojs/add-handler/entity_test_row/default/field'); + $this->drupalPostForm('admin/structure/views/nojs/add-handler/entity_test_row/default/field', ['name[entity_test__bar.bar]' => TRUE], 'Add and configure field'); + // Set the formatter to 'Responsive image'. + $this->drupalPostForm(NULL, ['options[type]' => 'responsive_image'], 'Apply'); + $this->assertSession() + ->responseContains('Responsive image style field is required.'); + $this->drupalPostForm(NULL, ['options[settings][responsive_image_style]' => self::RESPONSIVE_IMAGE_STYLE_ID], 'Apply'); + $this->drupalGet('admin/structure/views/nojs/handler/entity_test_row/default/field/bar'); + // Make sure the selected value is set. + $this->assertSession() + ->fieldValueEquals('options[settings][responsive_image_style]', self::RESPONSIVE_IMAGE_STYLE_ID); + } + +} diff -r e200cb7efeb3 -r c2387f117808 core/modules/rest/tests/modules/rest_test/rest_test.info.yml --- a/core/modules/rest/tests/modules/rest_test/rest_test.info.yml Thu Apr 26 11:26:54 2018 +0100 +++ b/core/modules/rest/tests/modules/rest_test/rest_test.info.yml Tue Jul 10 15:07:59 2018 +0100 @@ -4,5 +4,3 @@ package: Testing version: VERSION core: 8.x -dependencies: - - rest diff -r e200cb7efeb3 -r c2387f117808 core/modules/rest/tests/modules/rest_test/rest_test.services.yml --- a/core/modules/rest/tests/modules/rest_test/rest_test.services.yml Thu Apr 26 11:26:54 2018 +0100 +++ b/core/modules/rest/tests/modules/rest_test/rest_test.services.yml Tue Jul 10 15:07:59 2018 +0100 @@ -12,3 +12,7 @@ public: false tags: - { name: page_cache_request_policy } + rest_test.encoder.foobar: + class: Drupal\serialization\Encoder\JsonEncoder + tags: + - { name: encoder, format: foobar } diff -r e200cb7efeb3 -r c2387f117808 core/modules/rest/tests/src/Functional/EntityResource/Action/ActionJsonAnonTest.php --- a/core/modules/rest/tests/src/Functional/EntityResource/Action/ActionJsonAnonTest.php Thu Apr 26 11:26:54 2018 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,24 +0,0 @@ -grantPermissionsToTestedRole(['administer actions']); - } - - /** - * {@inheritdoc} - */ - protected function createEntity() { - $action = Action::create([ - 'id' => 'user_add_role_action.' . RoleInterface::ANONYMOUS_ID, - 'type' => 'user', - 'label' => t('Add the anonymous role to the selected users'), - 'configuration' => [ - 'rid' => RoleInterface::ANONYMOUS_ID, - ], - 'plugin' => 'user_add_role_action', - ]); - $action->save(); - - return $action; - } - - /** - * {@inheritdoc} - */ - protected function getExpectedNormalizedEntity() { - return [ - 'configuration' => [ - 'rid' => 'anonymous', - ], - 'dependencies' => [ - 'config' => ['user.role.anonymous'], - 'module' => ['user'], - ], - 'id' => 'user_add_role_action.anonymous', - 'label' => 'Add the anonymous role to the selected users', - 'langcode' => 'en', - 'plugin' => 'user_add_role_action', - 'status' => TRUE, - 'type' => 'user', - 'uuid' => $this->entity->uuid(), - ]; - } - - /** - * {@inheritdoc} - */ - protected function getExpectedCacheContexts() { - return [ - 'user.permissions', - ]; - } - - /** - * {@inheritdoc} - */ - protected function getNormalizedPostEntity() { - // @todo Update in https://www.drupal.org/node/2300677. - } - +/** + * Class for backward compatibility. It is deprecated in Drupal 8.6.x. + * + * @see https://www.drupal.org/node/2971931 + */ +abstract class ActionResourceTestBase extends ActionResourceTestBaseReal { } diff -r e200cb7efeb3 -r c2387f117808 core/modules/rest/tests/src/Functional/EntityResource/Action/ActionXmlAnonTest.php --- a/core/modules/rest/tests/src/Functional/EntityResource/Action/ActionXmlAnonTest.php Thu Apr 26 11:26:54 2018 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,26 +0,0 @@ -grantPermissionsToTestedRole(['administer node fields']); - } - - /** - * {@inheritdoc} - */ - protected function createEntity() { - $camelids = NodeType::create([ - 'name' => 'Camelids', - 'type' => 'camelids', - ]); - $camelids->save(); - - $entity = BaseFieldOverride::create([ - 'field_name' => 'promote', - 'entity_type' => 'node', - 'bundle' => 'camelids', - ]); - $entity->save(); - - return $entity; - } - - /** - * {@inheritdoc} - */ - protected function getExpectedNormalizedEntity() { - return [ - 'bundle' => 'camelids', - 'default_value' => [], - 'default_value_callback' => '', - 'dependencies' => [ - 'config' => [ - 'node.type.camelids', - ], - ], - 'description' => '', - 'entity_type' => 'node', - 'field_name' => 'promote', - 'field_type' => 'boolean', - 'id' => 'node.camelids.promote', - 'label' => NULL, - 'langcode' => 'en', - 'required' => FALSE, - 'settings' => [ - 'on_label' => 'On', - 'off_label' => 'Off', - ], - 'status' => TRUE, - 'translatable' => TRUE, - 'uuid' => $this->entity->uuid(), - ]; - } - - /** - * {@inheritdoc} - */ - protected function getNormalizedPostEntity() { - // @todo Update in https://www.drupal.org/node/2300677. - } - - /** - * {@inheritdoc} - */ - protected function getExpectedCacheContexts() { - return [ - 'user.permissions', - ]; - } - - /** - * {@inheritdoc} - */ - protected function getExpectedUnauthorizedAccessMessage($method) { - if ($this->config('rest.settings')->get('bc_entity_resource_permissions')) { - return parent::getExpectedUnauthorizedAccessMessage($method); - } - - return "The 'administer node fields' permission is required."; - } - +/** + * Class for backward compatibility. It is deprecated in Drupal 8.6.x. + * + * @see https://www.drupal.org/node/2971931 + */ +abstract class BaseFieldOverrideResourceTestBase extends BaseFieldOverrideResourceTestBaseReal { } diff -r e200cb7efeb3 -r c2387f117808 core/modules/rest/tests/src/Functional/EntityResource/BaseFieldOverride/BaseFieldOverrideXmlAnonTest.php --- a/core/modules/rest/tests/src/Functional/EntityResource/BaseFieldOverride/BaseFieldOverrideXmlAnonTest.php Thu Apr 26 11:26:54 2018 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,26 +0,0 @@ -entity->setVisibilityConfig('user_role', [])->save(); - break; - case 'POST': - $this->grantPermissionsToTestedRole(['administer blocks']); - break; - case 'PATCH': - $this->grantPermissionsToTestedRole(['administer blocks']); - break; - } - } - - /** - * {@inheritdoc} - */ - protected function createEntity() { - $block = Block::create([ - 'plugin' => 'llama_block', - 'region' => 'header', - 'id' => 'llama', - 'theme' => 'classy', - ]); - // All blocks can be viewed by the anonymous user by default. An interesting - // side effect of this is that any anonymous user is also able to read the - // corresponding block config entity via REST, even if an authentication - // provider is configured for the block config entity REST resource! In - // other words: Block entities do not distinguish between 'view' as in - // "render on a page" and 'view' as in "read the configuration". - // This prevents that. - // @todo Fix this in https://www.drupal.org/node/2820315. - $block->setVisibilityConfig('user_role', [ - 'id' => 'user_role', - 'roles' => ['non-existing-role' => 'non-existing-role'], - 'negate' => FALSE, - 'context_mapping' => [ - 'user' => '@user.current_user_context:current_user', - ], - ]); - $block->save(); - - return $block; - } - - /** - * {@inheritdoc} - */ - protected function getExpectedNormalizedEntity() { - $normalization = [ - 'uuid' => $this->entity->uuid(), - 'id' => 'llama', - 'weight' => NULL, - 'langcode' => 'en', - 'status' => TRUE, - 'dependencies' => [ - 'theme' => [ - 'classy', - ], - ], - 'theme' => 'classy', - 'region' => 'header', - 'provider' => NULL, - 'plugin' => 'llama_block', - 'settings' => [ - 'id' => 'broken', - 'label' => '', - 'provider' => 'core', - 'label_display' => 'visible', - ], - 'visibility' => [], - ]; - - return $normalization; - } - - /** - * {@inheritdoc} - */ - protected function getNormalizedPostEntity() { - // @todo Update in https://www.drupal.org/node/2300677. - } - - /** - * {@inheritdoc} - */ - protected function getExpectedCacheContexts() { - // @see ::createEntity() - return ['url.site']; - } - - /** - * {@inheritdoc} - */ - protected function getExpectedCacheTags() { - // Because the 'user.permissions' cache context is missing, the cache tag - // for the anonymous user role is never added automatically. - return array_values(array_diff(parent::getExpectedCacheTags(), ['config:user.role.anonymous'])); - } - - /** - * {@inheritdoc} - */ - protected function getExpectedUnauthorizedAccessMessage($method) { - if ($this->config('rest.settings')->get('bc_entity_resource_permissions')) { - return parent::getExpectedUnauthorizedAccessMessage($method); - } - - switch ($method) { - case 'GET': - return "You are not authorized to view this block entity."; - default: - return parent::getExpectedUnauthorizedAccessMessage($method); - } - } - - /** - * {@inheritdoc} - */ - protected function getExpectedUnauthorizedAccessCacheability() { - // @see \Drupal\block\BlockAccessControlHandler::checkAccess() - return parent::getExpectedUnauthorizedAccessCacheability() - ->setCacheTags([ - '4xx-response', - 'config:block.block.llama', - 'http_response', - static::$auth ? 'user:2' : 'user:0', - ]) - ->setCacheContexts(['user.roles']); - } - +/** + * Class for backward compatibility. It is deprecated in Drupal 8.6.x. + * + * @see https://www.drupal.org/node/2971931 + */ +abstract class BlockResourceTestBase extends BlockResourceTestBaseReal { } diff -r e200cb7efeb3 -r c2387f117808 core/modules/rest/tests/src/Functional/EntityResource/Block/BlockXmlAnonTest.php --- a/core/modules/rest/tests/src/Functional/EntityResource/Block/BlockXmlAnonTest.php Thu Apr 26 11:26:54 2018 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,26 +0,0 @@ -grantPermissionsToTestedRole(['administer blocks']); - } - - /** - * {@inheritdoc} - */ - protected function createEntity() { - if (!BlockContentType::load('basic')) { - $block_content_type = BlockContentType::create([ - 'id' => 'basic', - 'label' => 'basic', - 'revision' => TRUE, - ]); - $block_content_type->save(); - block_content_add_body_field($block_content_type->id()); - } - - // Create a "Llama" custom block. - $block_content = BlockContent::create([ - 'info' => 'Llama', - 'type' => 'basic', - 'body' => [ - 'value' => 'The name "llama" was adopted by European settlers from native Peruvians.', - 'format' => 'plain_text', - ], - ]) - ->setPublished(FALSE); - $block_content->save(); - return $block_content; - } - - /** - * {@inheritdoc} - */ - protected function getExpectedNormalizedEntity() { - return [ - 'id' => [ - [ - 'value' => 1, - ], - ], - 'uuid' => [ - [ - 'value' => $this->entity->uuid(), - ], - ], - 'langcode' => [ - [ - 'value' => 'en', - ], - ], - 'type' => [ - [ - 'target_id' => 'basic', - 'target_type' => 'block_content_type', - 'target_uuid' => BlockContentType::load('basic')->uuid(), - ], - ], - 'info' => [ - [ - 'value' => 'Llama', - ], - ], - 'revision_log' => [], - 'changed' => [ - $this->formatExpectedTimestampItemValues($this->entity->getChangedTime()), - ], - 'revision_id' => [ - [ - 'value' => 1, - ], - ], - 'revision_created' => [ - $this->formatExpectedTimestampItemValues((int) $this->entity->getRevisionCreationTime()), - ], - 'revision_user' => [], - 'revision_translation_affected' => [ - [ - 'value' => TRUE, - ], - ], - 'default_langcode' => [ - [ - 'value' => TRUE, - ], - ], - 'body' => [ - [ - 'value' => 'The name "llama" was adopted by European settlers from native Peruvians.', - 'format' => 'plain_text', - 'summary' => NULL, - 'processed' => "

    The name "llama" was adopted by European settlers from native Peruvians.

    \n", - ], - ], - 'status' => [ - [ - 'value' => FALSE, - ], - ], - ]; - } - - /** - * {@inheritdoc} - */ - protected function getNormalizedPostEntity() { - return [ - 'type' => [ - [ - 'target_id' => 'basic', - ], - ], - 'info' => [ - [ - 'value' => 'Dramallama', - ], - ], - ]; - } - - - /** - * {@inheritdoc} - */ - protected function getExpectedUnauthorizedAccessMessage($method) { - if ($this->config('rest.settings')->get('bc_entity_resource_permissions')) { - return parent::getExpectedUnauthorizedAccessMessage($method); - } - - return parent::getExpectedUnauthorizedAccessMessage($method); - } - - /** - * {@inheritdoc} - */ - protected function getExpectedUnauthorizedAccessCacheability() { - // @see \Drupal\block_content\BlockContentAccessControlHandler() - return parent::getExpectedUnauthorizedAccessCacheability() - ->addCacheTags(['block_content:1']); - } - - /** - * {@inheritdoc} - */ - protected function getExpectedCacheTags() { - return Cache::mergeTags(parent::getExpectedCacheTags(), ['config:filter.format.plain_text']); - } - - /** - * {@inheritdoc} - */ - protected function getExpectedCacheContexts() { - return Cache::mergeContexts(['url.site'], $this->container->getParameter('renderer.config')['required_cache_contexts']); - } - +abstract class BlockContentResourceTestBase extends BlockContentResourceTestBaseReal { } diff -r e200cb7efeb3 -r c2387f117808 core/modules/rest/tests/src/Functional/EntityResource/BlockContent/BlockContentXmlAnonTest.php --- a/core/modules/rest/tests/src/Functional/EntityResource/BlockContent/BlockContentXmlAnonTest.php Thu Apr 26 11:26:54 2018 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,26 +0,0 @@ -grantPermissionsToTestedRole(['administer blocks']); - } - - /** - * {@inheritdoc} - */ - protected function createEntity() { - $block_content_type = BlockContentType::create([ - 'id' => 'pascal', - 'label' => 'Pascal', - 'revision' => FALSE, - 'description' => 'Provides a competitive alternative to the "basic" type', - ]); - - $block_content_type->save(); - - return $block_content_type; - } - - /** - * {@inheritdoc} - */ - protected function getExpectedNormalizedEntity() { - return [ - 'dependencies' => [], - 'description' => 'Provides a competitive alternative to the "basic" type', - 'id' => 'pascal', - 'label' => 'Pascal', - 'langcode' => 'en', - 'revision' => 0, - 'status' => TRUE, - 'uuid' => $this->entity->uuid(), - ]; - } - - /** - * {@inheritdoc} - */ - protected function getNormalizedPostEntity() { - // @todo Update in https://www.drupal.org/node/2300677. - } - +/** + * Class for backward compatibility. It is deprecated in Drupal 8.6.x. + * + * @see https://www.drupal.org/node/2971931 + */ +abstract class BlockContentTypeResourceTestBase extends BlockContentTypeResourceTestBaseReal { } diff -r e200cb7efeb3 -r c2387f117808 core/modules/rest/tests/src/Functional/EntityResource/BlockContentType/BlockContentTypeXmlAnonTest.php --- a/core/modules/rest/tests/src/Functional/EntityResource/BlockContentType/BlockContentTypeXmlAnonTest.php Thu Apr 26 11:26:54 2018 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,26 +0,0 @@ -grantPermissionsToTestedRole(['access comments', 'view test entity']); - break; - case 'POST': - $this->grantPermissionsToTestedRole(['post comments']); - break; - case 'PATCH': - // Anononymous users are not ever allowed to edit their own comments. To - // be able to test PATCHing comments as the anonymous user, the more - // permissive 'administer comments' permission must be granted. - // @see \Drupal\comment\CommentAccessControlHandler::checkAccess - if (static::$auth) { - $this->grantPermissionsToTestedRole(['edit own comments']); - } - else { - $this->grantPermissionsToTestedRole(['administer comments']); - } - break; - case 'DELETE': - $this->grantPermissionsToTestedRole(['administer comments']); - break; - } - } - - /** - * {@inheritdoc} - */ - protected function createEntity() { - // Create a "bar" bundle for the "entity_test" entity type and create. - $bundle = 'bar'; - entity_test_create_bundle($bundle, NULL, 'entity_test'); - - // Create a comment field on this bundle. - $this->addDefaultCommentField('entity_test', 'bar', 'comment'); - - // Create a "Camelids" test entity that the comment will be assigned to. - $commented_entity = EntityTest::create([ - 'name' => 'Camelids', - 'type' => 'bar', - ]); - $commented_entity->save(); - - // Create a "Llama" comment. - $comment = Comment::create([ - 'comment_body' => [ - 'value' => 'The name "llama" was adopted by European settlers from native Peruvians.', - 'format' => 'plain_text', - ], - 'entity_id' => $commented_entity->id(), - 'entity_type' => 'entity_test', - 'field_name' => 'comment', - ]); - $comment->setSubject('Llama') - ->setOwnerId(static::$auth ? $this->account->id() : 0) - ->setPublished(TRUE) - ->setCreatedTime(123456789) - ->setChangedTime(123456789); - $comment->save(); - - return $comment; - } - - /** - * {@inheritdoc} - */ - protected function getExpectedNormalizedEntity() { - $author = User::load($this->entity->getOwnerId()); - return [ - 'cid' => [ - ['value' => 1], - ], - 'uuid' => [ - ['value' => $this->entity->uuid()], - ], - 'langcode' => [ - [ - 'value' => 'en', - ], - ], - 'comment_type' => [ - [ - 'target_id' => 'comment', - 'target_type' => 'comment_type', - 'target_uuid' => CommentType::load('comment')->uuid(), - ], - ], - 'subject' => [ - [ - 'value' => 'Llama', - ], - ], - 'status' => [ - [ - 'value' => TRUE, - ], - ], - 'created' => [ - $this->formatExpectedTimestampItemValues(123456789), - ], - 'changed' => [ - $this->formatExpectedTimestampItemValues($this->entity->getChangedTime()), - ], - 'default_langcode' => [ - [ - 'value' => TRUE, - ], - ], - 'uid' => [ - [ - 'target_id' => (int) $author->id(), - 'target_type' => 'user', - 'target_uuid' => $author->uuid(), - 'url' => base_path() . 'user/' . $author->id(), - ], - ], - 'pid' => [], - 'entity_type' => [ - [ - 'value' => 'entity_test', - ], - ], - 'entity_id' => [ - [ - 'target_id' => 1, - 'target_type' => 'entity_test', - 'target_uuid' => EntityTest::load(1)->uuid(), - 'url' => base_path() . 'entity_test/1', - ], - ], - 'field_name' => [ - [ - 'value' => 'comment', - ], - ], - 'name' => [], - 'homepage' => [], - 'thread' => [ - [ - 'value' => '01/', - ], - ], - 'comment_body' => [ - [ - 'value' => 'The name "llama" was adopted by European settlers from native Peruvians.', - 'format' => 'plain_text', - 'processed' => '

    The name "llama" was adopted by European settlers from native Peruvians.

    ' . "\n", - ], - ], - ]; - } - - /** - * {@inheritdoc} - */ - protected function getNormalizedPostEntity() { - return [ - 'comment_type' => [ - [ - 'target_id' => 'comment', - ], - ], - 'entity_type' => [ - [ - 'value' => 'entity_test', - ], - ], - 'entity_id' => [ - [ - 'target_id' => (int) EntityTest::load(1)->id(), - ], - ], - 'field_name' => [ - [ - 'value' => 'comment', - ], - ], - 'subject' => [ - [ - 'value' => 'Dramallama', - ], - ], - 'comment_body' => [ - [ - 'value' => 'Llamas are awesome.', - 'format' => 'plain_text', - ], - ], - ]; - } - - /** - * {@inheritdoc} - */ - protected function getNormalizedPatchEntity() { - return array_diff_key($this->getNormalizedPostEntity(), ['entity_type' => TRUE, 'entity_id' => TRUE, 'field_name' => TRUE]); - } - - /** - * {@inheritdoc} - */ - protected function getExpectedCacheTags() { - return Cache::mergeTags(parent::getExpectedCacheTags(), ['config:filter.format.plain_text']); - } - - /** - * {@inheritdoc} - */ - protected function getExpectedCacheContexts() { - return Cache::mergeContexts(['languages:language_interface', 'theme'], parent::getExpectedCacheContexts()); - } - - /** - * Tests POSTing a comment without critical base fields. - * - * testPost() is testing with the most minimal normalization possible: the one - * returned by ::getNormalizedPostEntity(). - * - * But Comment entities have some very special edge cases: - * - base fields that are not marked as required in - * \Drupal\comment\Entity\Comment::baseFieldDefinitions() yet in fact are - * required. - * - base fields that are marked as required, but yet can still result in - * validation errors other than "missing required field". - */ - public function testPostDxWithoutCriticalBaseFields() { - $this->initAuthentication(); - $this->provisionEntityResource(); - $this->setUpAuthorization('POST'); - - $url = $this->getEntityResourcePostUrl()->setOption('query', ['_format' => static::$format]); - $request_options = []; - $request_options[RequestOptions::HEADERS]['Accept'] = static::$mimeType; - $request_options[RequestOptions::HEADERS]['Content-Type'] = static::$mimeType; - $request_options = array_merge_recursive($request_options, $this->getAuthenticationRequestOptions('POST')); - - // DX: 422 when missing 'entity_type' field. - $request_options[RequestOptions::BODY] = $this->serializer->encode(array_diff_key($this->getNormalizedPostEntity(), ['entity_type' => TRUE]), static::$format); - $response = $this->request('POST', $url, $request_options); - // @todo Uncomment, remove next 3 lines in https://www.drupal.org/node/2820364. - $this->assertSame(500, $response->getStatusCode()); - $this->assertSame(['text/plain; charset=UTF-8'], $response->getHeader('Content-Type')); - $this->assertStringStartsWith('The website encountered an unexpected error. Please try again later.

    Symfony\Component\HttpKernel\Exception\HttpException: Internal Server Error in Drupal\rest\Plugin\rest\resource\EntityResource->post()', (string) $response->getBody()); - // $this->assertResourceErrorResponse(422, "Unprocessable Entity: validation failed.\nentity_type: This value should not be null.\n", $response); - - // DX: 422 when missing 'entity_id' field. - $request_options[RequestOptions::BODY] = $this->serializer->encode(array_diff_key($this->getNormalizedPostEntity(), ['entity_id' => TRUE]), static::$format); - // @todo Remove the try/catch in favor of the two commented lines in - // https://www.drupal.org/node/2820364. - try { - $response = $this->request('POST', $url, $request_options); - // This happens on DrupalCI. - // $this->assertSame(500, $response->getStatusCode()); - } - catch (\Exception $e) { - // This happens on Wim's local machine. - // $this->assertSame("Error: Call to a member function get() on null\nDrupal\\comment\\Plugin\\Validation\\Constraint\\CommentNameConstraintValidator->getAnonymousContactDetailsSetting()() (Line: 96)\n", $e->getMessage()); - } - // $response = $this->request('POST', $url, $request_options); - // $this->assertResourceErrorResponse(422, "Unprocessable Entity: validation failed.\nentity_type: This value should not be null.\n", $response); - - // DX: 422 when missing 'entity_type' field. - $request_options[RequestOptions::BODY] = $this->serializer->encode(array_diff_key($this->getNormalizedPostEntity(), ['field_name' => TRUE]), static::$format); - $response = $this->request('POST', $url, $request_options); - // @todo Uncomment, remove next 2 lines in https://www.drupal.org/node/2820364. - $this->assertSame(500, $response->getStatusCode()); - $this->assertSame(['text/plain; charset=UTF-8'], $response->getHeader('Content-Type')); - // $this->assertResourceErrorResponse(422, "Unprocessable Entity: validation failed.\nfield_name: This value should not be null.\n", $response); - } - - /** - * {@inheritdoc} - */ - protected function getExpectedUnauthorizedAccessMessage($method) { - if ($this->config('rest.settings')->get('bc_entity_resource_permissions')) { - return parent::getExpectedUnauthorizedAccessMessage($method); - } - - switch ($method) { - case 'GET'; - return "The 'access comments' permission is required and the comment must be published."; - case 'POST'; - return "The 'post comments' permission is required."; - default: - return parent::getExpectedUnauthorizedAccessMessage($method); - } - } - - /** - * Tests POSTing a comment with and without 'skip comment approval' - */ - public function testPostSkipCommentApproval() { - $this->initAuthentication(); - $this->provisionEntityResource(); - $this->setUpAuthorization('POST'); - - // Create request. - $request_options = []; - $request_options[RequestOptions::HEADERS]['Accept'] = static::$mimeType; - $request_options[RequestOptions::HEADERS]['Content-Type'] = static::$mimeType; - $request_options = array_merge_recursive($request_options, $this->getAuthenticationRequestOptions('POST')); - $request_options[RequestOptions::BODY] = $this->serializer->encode($this->getNormalizedPostEntity(), static::$format); - - $url = $this->getEntityResourcePostUrl()->setOption('query', ['_format' => static::$format]); - - // Status should be FALSE when posting as anonymous. - $response = $this->request('POST', $url, $request_options); - $unserialized = $this->serializer->deserialize((string) $response->getBody(), get_class($this->entity), static::$format); - $this->assertResourceResponse(201, FALSE, $response); - $this->assertFalse($unserialized->getStatus()); - - // Grant anonymous permission to skip comment approval. - $this->grantPermissionsToTestedRole(['skip comment approval']); - - // Status should be TRUE when posting as anonymous and skip comment approval. - $response = $this->request('POST', $url, $request_options); - $unserialized = $this->serializer->deserialize((string) $response->getBody(), get_class($this->entity), static::$format); - $this->assertResourceResponse(201, FALSE, $response); - $this->assertTrue($unserialized->getStatus()); - } - - /** - * {@inheritdoc} - */ - protected function getExpectedUnauthorizedAccessCacheability() { - // @see \Drupal\comment\CommentAccessControlHandler::checkAccess() - return parent::getExpectedUnauthorizedAccessCacheability() - ->addCacheTags(['comment:1']); - } - +/** + * Class for backward compatibility. It is deprecated in Drupal 8.6.x. + * + * @see https://www.drupal.org/node/2971931 + */ +abstract class CommentResourceTestBase extends CommentResourceTestBaseReal { } diff -r e200cb7efeb3 -r c2387f117808 core/modules/rest/tests/src/Functional/EntityResource/Comment/CommentXmlAnonTest.php --- a/core/modules/rest/tests/src/Functional/EntityResource/Comment/CommentXmlAnonTest.php Thu Apr 26 11:26:54 2018 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,63 +0,0 @@ -markTestSkipped(); - } - - /** - * {@inheritdoc} - */ - public function testPostSkipCommentApproval() { - // Deserialization of the XML format is not supported. - $this->markTestSkipped(); - } - -} diff -r e200cb7efeb3 -r c2387f117808 core/modules/rest/tests/src/Functional/EntityResource/Comment/CommentXmlBasicAuthTest.php --- a/core/modules/rest/tests/src/Functional/EntityResource/Comment/CommentXmlBasicAuthTest.php Thu Apr 26 11:26:54 2018 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,52 +0,0 @@ -markTestSkipped(); - } - - /** - * {@inheritdoc} - */ - public function testPostSkipCommentApproval() { - // Deserialization of the XML format is not supported. - $this->markTestSkipped(); - } - -} diff -r e200cb7efeb3 -r c2387f117808 core/modules/rest/tests/src/Functional/EntityResource/Comment/CommentXmlCookieTest.php --- a/core/modules/rest/tests/src/Functional/EntityResource/Comment/CommentXmlCookieTest.php Thu Apr 26 11:26:54 2018 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,47 +0,0 @@ -markTestSkipped(); - } - - /** - * {@inheritdoc} - */ - public function testPostSkipCommentApproval() { - // Deserialization of the XML format is not supported. - $this->markTestSkipped(); - } - -} diff -r e200cb7efeb3 -r c2387f117808 core/modules/rest/tests/src/Functional/EntityResource/CommentType/CommentTypeJsonAnonTest.php --- a/core/modules/rest/tests/src/Functional/EntityResource/CommentType/CommentTypeJsonAnonTest.php Thu Apr 26 11:26:54 2018 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,24 +0,0 @@ -grantPermissionsToTestedRole(['administer comment types']); - } - - /** - * {@inheritdoc} - */ - protected function createEntity() { - // Create a "Camelids" comment type. - $camelids = CommentType::create([ - 'id' => 'camelids', - 'label' => 'Camelids', - 'description' => 'Camelids are large, strictly herbivorous animals with slender necks and long legs.', - 'target_entity_type_id' => 'node', - ]); - - $camelids->save(); - - return $camelids; - } - - /** - * {@inheritdoc} - */ - protected function getExpectedNormalizedEntity() { - return [ - 'dependencies' => [], - 'description' => 'Camelids are large, strictly herbivorous animals with slender necks and long legs.', - 'id' => 'camelids', - 'label' => 'Camelids', - 'langcode' => 'en', - 'status' => TRUE, - 'target_entity_type_id' => 'node', - 'uuid' => $this->entity->uuid(), - ]; - } - - /** - * {@inheritdoc} - */ - protected function getNormalizedPostEntity() { - // @todo Update in https://www.drupal.org/node/2300677. - } - +abstract class CommentTypeResourceTestBase extends CommentTypeResourceTestBaseReal { } diff -r e200cb7efeb3 -r c2387f117808 core/modules/rest/tests/src/Functional/EntityResource/CommentType/CommentTypeXmlAnonTest.php --- a/core/modules/rest/tests/src/Functional/EntityResource/CommentType/CommentTypeXmlAnonTest.php Thu Apr 26 11:26:54 2018 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,26 +0,0 @@ -grantPermissionsToTestedRole(['view config_test']); - } - - /** - * {@inheritdoc} - */ - protected function createEntity() { - $config_test = ConfigTest::create([ - 'id' => 'llama', - 'label' => 'Llama', - ]); - $config_test->save(); - - return $config_test; - } - - /** - * {@inheritdoc} - */ - protected function getExpectedNormalizedEntity() { - $normalization = [ - 'uuid' => $this->entity->uuid(), - 'id' => 'llama', - 'weight' => 0, - 'langcode' => 'en', - 'status' => TRUE, - 'dependencies' => [], - 'label' => 'Llama', - 'style' => NULL, - 'size' => NULL, - 'size_value' => NULL, - 'protected_property' => NULL, - ]; - - return $normalization; - } - - /** - * {@inheritdoc} - */ - protected function getNormalizedPostEntity() { - // @todo Update in https://www.drupal.org/node/2300677. - } - +/** + * Class for backward compatibility. It is deprecated in Drupal 8.6.x. + * + * @see https://www.drupal.org/node/2971931 + */ +abstract class ConfigTestResourceTestBase extends ConfigTestResourceTestBaseReal { } diff -r e200cb7efeb3 -r c2387f117808 core/modules/rest/tests/src/Functional/EntityResource/ConfigTest/ConfigTestXmlAnonTest.php --- a/core/modules/rest/tests/src/Functional/EntityResource/ConfigTest/ConfigTestXmlAnonTest.php Thu Apr 26 11:26:54 2018 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,26 +0,0 @@ -grantPermissionsToTestedRole(['administer languages']); - } - - /** - * {@inheritdoc} - */ - protected function createEntity() { - $configurable_language = ConfigurableLanguage::create([ - 'id' => 'll', - 'label' => 'Llama Language', - ]); - $configurable_language->save(); - - return $configurable_language; - } - - /** - * {@inheritdoc} - */ - protected function getExpectedNormalizedEntity() { - return [ - 'dependencies' => [], - 'direction' => 'ltr', - 'id' => 'll', - 'label' => 'Llama Language', - 'langcode' => 'en', - 'locked' => FALSE, - 'status' => TRUE, - 'uuid' => $this->entity->uuid(), - 'weight' => 0, - ]; - } - - /** - * {@inheritdoc} - */ - protected function getExpectedCacheContexts() { - return Cache::mergeContexts(parent::getExpectedCacheContexts(), ['languages:language_interface']); - } - - /** - * {@inheritdoc} - */ - protected function getNormalizedPostEntity() { - // @todo Update in https://www.drupal.org/node/2300677. - } - - /** - * Test a GET request for a default config entity, which has a _core key. - * - * @see https://www.drupal.org/node/2915414 - */ - public function testGetDefaultConfig() { - $this->initAuthentication(); - $url = Url::fromUri('base:/entity/configurable_language/en')->setOption('query', ['_format' => static::$format]);; - $request_options = $this->getAuthenticationRequestOptions('GET'); - $this->provisionEntityResource(); - $this->setUpAuthorization('GET'); - $response = $this->request('GET', $url, $request_options); - - $normalization = $this->serializer->decode((string) $response->getBody(), static::$format); - $this->assertArrayNotHasKey('_core', $normalization); - } - +/** + * Class for backward compatibility. It is deprecated in Drupal 8.6.x. + * + * @see https://www.drupal.org/node/2971931 + */ +abstract class ConfigurableLanguageResourceTestBase extends ConfigurableLanguageResourceTestBaseReal { } diff -r e200cb7efeb3 -r c2387f117808 core/modules/rest/tests/src/Functional/EntityResource/ConfigurableLanguage/ConfigurableLanguageXmlAnonTest.php --- a/core/modules/rest/tests/src/Functional/EntityResource/ConfigurableLanguage/ConfigurableLanguageXmlAnonTest.php Thu Apr 26 11:26:54 2018 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,26 +0,0 @@ -grantPermissionsToTestedRole(['access site-wide contact form']); - default: - $this->grantPermissionsToTestedRole(['administer contact forms']); - } - } - - /** - * {@inheritdoc} - */ - protected function createEntity() { - $contact_form = ContactForm::create([ - 'id' => 'llama', - 'label' => 'Llama', - 'message' => 'Let us know what you think about llamas', - 'reply' => 'Llamas are indeed awesome!', - 'recipients' => [ - 'llama@example.com', - 'contact@example.com', - ], - ]); - $contact_form->save(); - - return $contact_form; - } - - /** - * {@inheritdoc} - */ - protected function getExpectedNormalizedEntity() { - return [ - 'dependencies' => [], - 'id' => 'llama', - 'label' => 'Llama', - 'langcode' => 'en', - 'message' => 'Let us know what you think about llamas', - 'recipients' => [ - 'llama@example.com', - 'contact@example.com', - ], - 'redirect' => NULL, - 'reply' => 'Llamas are indeed awesome!', - 'status' => TRUE, - 'uuid' => $this->entity->uuid(), - 'weight' => 0, - ]; - } - - /** - * {@inheritdoc} - */ - protected function getNormalizedPostEntity() { - // @todo Update in https://www.drupal.org/node/2300677. - } - - /** - * {@inheritdoc} - */ - protected function getExpectedUnauthorizedAccessMessage($method) { - if ($this->config('rest.settings')->get('bc_entity_resource_permissions')) { - return parent::getExpectedUnauthorizedAccessMessage($method); - } - - return "The 'access site-wide contact form' permission is required."; - } - +/** + * Class for backward compatibility. It is deprecated in Drupal 8.6.x. + * + * @see https://www.drupal.org/node/2971931 + */ +abstract class ContactFormResourceTestBase extends ContactFormResourceTestBaseReal { } diff -r e200cb7efeb3 -r c2387f117808 core/modules/rest/tests/src/Functional/EntityResource/ContactForm/ContactFormXmlAnonTest.php --- a/core/modules/rest/tests/src/Functional/EntityResource/ContactForm/ContactFormXmlAnonTest.php Thu Apr 26 11:26:54 2018 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,26 +0,0 @@ -grantPermissionsToTestedRole(['administer languages']); - } - - /** - * {@inheritdoc} - */ - protected function createEntity() { - // Create a "Camelids" node type. - $camelids = NodeType::create([ - 'name' => 'Camelids', - 'type' => 'camelids', - ]); - $camelids->save(); - - $entity = ContentLanguageSettings::create([ - 'target_entity_type_id' => 'node', - 'target_bundle' => 'camelids', - ]); - $entity->setDefaultLangcode('site_default') - ->save(); - - return $entity; - } - - /** - * {@inheritdoc} - */ - protected function getExpectedNormalizedEntity() { - return [ - 'default_langcode' => 'site_default', - 'dependencies' => [ - 'config' => [ - 'node.type.camelids', - ], - ], - 'id' => 'node.camelids', - 'langcode' => 'en', - 'language_alterable' => FALSE, - 'status' => TRUE, - 'target_bundle' => 'camelids', - 'target_entity_type_id' => 'node', - 'uuid' => $this->entity->uuid(), - ]; - } - - /** - * {@inheritdoc} - */ - protected function getNormalizedPostEntity() { - // @todo Update in https://www.drupal.org/node/2300677. - } - - /** - * {@inheritdoc} - */ - protected function getExpectedCacheContexts() { - return [ - 'languages:language_interface', - 'user.permissions', - ]; - } - +/** + * Class for backward compatibility. It is deprecated in Drupal 8.6.x. + * + * @see https://www.drupal.org/node/2971931 + */ +abstract class ContentLanguageSettingsResourceTestBase extends ContentLanguageSettingsResourceTestBaseReal { } diff -r e200cb7efeb3 -r c2387f117808 core/modules/rest/tests/src/Functional/EntityResource/ContentLanguageSettings/ContentLanguageSettingsXmlAnonTest.php --- a/core/modules/rest/tests/src/Functional/EntityResource/ContentLanguageSettings/ContentLanguageSettingsXmlAnonTest.php Thu Apr 26 11:26:54 2018 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,26 +0,0 @@ -grantPermissionsToTestedRole(['administer site configuration']); - } - - /** - * {@inheritdoc} - */ - protected function createEntity() { - // Create a date format. - $date_format = DateFormat::create([ - 'id' => 'llama', - 'label' => 'Llama', - 'pattern' => 'F d, Y', - ]); - - $date_format->save(); - - return $date_format; - } - - /** - * {@inheritdoc} - */ - protected function getExpectedNormalizedEntity() { - return [ - 'dependencies' => [], - 'id' => 'llama', - 'label' => 'Llama', - 'langcode' => 'en', - 'locked' => FALSE, - 'pattern' => 'F d, Y', - 'status' => TRUE, - 'uuid' => $this->entity->uuid(), - ]; - } - - /** - * {@inheritdoc} - */ - protected function getNormalizedPostEntity() { - // @todo Update in https://www.drupal.org/node/2300677. - } - +abstract class DateFormatResourceTestBase extends DateFormatResourceTestBaseReal { } diff -r e200cb7efeb3 -r c2387f117808 core/modules/rest/tests/src/Functional/EntityResource/DateFormat/DateFormatXmlAnonTest.php --- a/core/modules/rest/tests/src/Functional/EntityResource/DateFormat/DateFormatXmlAnonTest.php Thu Apr 26 11:26:54 2018 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,26 +0,0 @@ -grantPermissionsToTestedRole(['administer filters']); - } - - /** - * {@inheritdoc} - */ - protected function createEntity() { - // Create a "Llama" filter format. - $llama_format = FilterFormat::create([ - 'name' => 'Llama', - 'format' => 'llama', - 'langcode' => 'es', - 'filters' => [ - 'filter_html' => [ - 'status' => TRUE, - 'settings' => [ - 'allowed_html' => '

    ', - ], - ], - ], - ]); - - $llama_format->save(); - - // Create a "Camelids" editor. - $camelids = Editor::create([ - 'format' => 'llama', - 'editor' => 'ckeditor', - ]); - $camelids - ->setImageUploadSettings([ - 'status' => FALSE, - 'scheme' => file_default_scheme(), - 'directory' => 'inline-images', - 'max_size' => '', - 'max_dimensions' => [ - 'width' => '', - 'height' => '', - ], - ]) - ->save(); - - return $camelids; - } - - /** - * {@inheritdoc} - */ - protected function getExpectedNormalizedEntity() { - return [ - 'dependencies' => [ - 'config' => [ - 'filter.format.llama', - ], - 'module' => [ - 'ckeditor', - ], - ], - 'editor' => 'ckeditor', - 'format' => 'llama', - 'image_upload' => [ - 'status' => FALSE, - 'scheme' => 'public', - 'directory' => 'inline-images', - 'max_size' => '', - 'max_dimensions' => [ - 'width' => NULL, - 'height' => NULL, - ], - ], - 'langcode' => 'en', - 'settings' => [ - 'toolbar' => [ - 'rows' => [ - [ - [ - 'name' => 'Formatting', - 'items' => [ - 'Bold', - 'Italic', - ], - ], - [ - 'name' => 'Links', - 'items' => [ - 'DrupalLink', - 'DrupalUnlink', - ], - ], - [ - 'name' => 'Lists', - 'items' => [ - 'BulletedList', - 'NumberedList', - ], - ], - [ - 'name' => 'Media', - 'items' => [ - 'Blockquote', - 'DrupalImage', - ], - ], - [ - 'name' => 'Tools', - 'items' => [ - 'Source', - ], - ], - ], - ], - ], - 'plugins' => [ - 'language' => [ - 'language_list' => 'un', - ], - ], - ], - 'status' => TRUE, - 'uuid' => $this->entity->uuid(), - ]; - } - - /** - * {@inheritdoc} - */ - protected function getNormalizedPostEntity() { - // @todo Update in https://www.drupal.org/node/2300677. - } - - /** - * {@inheritdoc} - */ - protected function getExpectedCacheContexts() { - // @see ::createEntity() - return ['user.permissions']; - } - - /** - * {@inheritdoc} - */ - protected function getExpectedUnauthorizedAccessMessage($method) { - if ($this->config('rest.settings')->get('bc_entity_resource_permissions')) { - return parent::getExpectedUnauthorizedAccessMessage($method); - } - - return "The 'administer filters' permission is required."; - } - +abstract class EditorResourceTestBase extends EditorResourceTestBaseReal { } diff -r e200cb7efeb3 -r c2387f117808 core/modules/rest/tests/src/Functional/EntityResource/Editor/EditorXmlAnonTest.php --- a/core/modules/rest/tests/src/Functional/EntityResource/Editor/EditorXmlAnonTest.php Thu Apr 26 11:26:54 2018 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,26 +0,0 @@ -grantPermissionsToTestedRole(['administer node form display']); - } - - /** - * {@inheritdoc} - */ - protected function createEntity() { - // Create a "Camelids" node type. - $camelids = NodeType::create([ - 'name' => 'Camelids', - 'type' => 'camelids', - ]); - - $camelids->save(); - - // Create a form display. - $form_display = EntityFormDisplay::create([ - 'targetEntityType' => 'node', - 'bundle' => 'camelids', - 'mode' => 'default', - ]); - $form_display->save(); - - return $form_display; - } - - /** - * {@inheritdoc} - */ - protected function getExpectedNormalizedEntity() { - return [ - 'bundle' => 'camelids', - 'content' => [ - 'created' => [ - 'type' => 'datetime_timestamp', - 'weight' => 10, - 'region' => 'content', - 'settings' => [], - 'third_party_settings' => [], - ], - 'promote' => [ - 'type' => 'boolean_checkbox', - 'settings' => [ - 'display_label' => TRUE, - ], - 'weight' => 15, - 'region' => 'content', - 'third_party_settings' => [], - ], - 'status' => [ - 'type' => 'boolean_checkbox', - 'weight' => 120, - 'region' => 'content', - 'settings' => [ - 'display_label' => TRUE, - ], - 'third_party_settings' => [], - ], - 'sticky' => [ - 'type' => 'boolean_checkbox', - 'settings' => [ - 'display_label' => TRUE, - ], - 'weight' => 16, - 'region' => 'content', - 'third_party_settings' => [], - ], - 'title' => [ - 'type' => 'string_textfield', - 'weight' => -5, - 'region' => 'content', - 'settings' => [ - 'size' => 60, - 'placeholder' => '', - ], - 'third_party_settings' => [], - ], - 'uid' => [ - 'type' => 'entity_reference_autocomplete', - 'weight' => 5, - 'settings' => [ - 'match_operator' => 'CONTAINS', - 'size' => 60, - 'placeholder' => '', - ], - 'region' => 'content', - 'third_party_settings' => [], - ], - ], - 'dependencies' => [ - 'config' => [ - 'node.type.camelids', - ], - ], - 'hidden' => [], - 'id' => 'node.camelids.default', - 'langcode' => 'en', - 'mode' => 'default', - 'status' => NULL, - 'targetEntityType' => 'node', - 'uuid' => $this->entity->uuid(), - ]; - } - - /** - * {@inheritdoc} - */ - protected function getNormalizedPostEntity() { - // @todo Update in https://www.drupal.org/node/2300677. - } - - /** - * {@inheritdoc} - */ - protected function getExpectedCacheContexts() { - return [ - 'user.permissions', - ]; - } - - /** - * {@inheritdoc} - */ - protected function getExpectedUnauthorizedAccessMessage($method) { - if ($this->config('rest.settings')->get('bc_entity_resource_permissions')) { - return parent::getExpectedUnauthorizedAccessMessage($method); - } - - return "The 'administer node form display' permission is required."; - } - +/** + * Class for backward compatibility. It is deprecated in Drupal 8.6.x. + * + * @see https://www.drupal.org/node/2971931 + */ +abstract class EntityFormDisplayResourceTestBase extends EntityFormDisplayResourceTestBaseReal { } diff -r e200cb7efeb3 -r c2387f117808 core/modules/rest/tests/src/Functional/EntityResource/EntityFormDisplay/EntityFormDisplayXmlAnonTest.php --- a/core/modules/rest/tests/src/Functional/EntityResource/EntityFormDisplay/EntityFormDisplayXmlAnonTest.php Thu Apr 26 11:26:54 2018 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,26 +0,0 @@ -grantPermissionsToTestedRole(['administer display modes']); - } - - /** - * {@inheritdoc} - */ - protected function createEntity() { - $entity_form_mode = EntityFormMode::create([ - 'id' => 'user.test', - 'label' => 'Test', - 'targetEntityType' => 'user', - ]); - $entity_form_mode->save(); - return $entity_form_mode; - } - - /** - * {@inheritdoc} - */ - protected function getExpectedNormalizedEntity() { - return [ - 'cache' => TRUE, - 'dependencies' => [ - 'module' => [ - 'user', - ], - ], - 'id' => 'user.test', - 'label' => 'Test', - 'langcode' => 'en', - 'status' => TRUE, - 'targetEntityType' => 'user', - 'uuid' => $this->entity->uuid(), - ]; - } - - /** - * {@inheritdoc} - */ - protected function getNormalizedPostEntity() { - // @todo Update in https://www.drupal.org/node/2300677. - } - +/** + * Class for backward compatibility. It is deprecated in Drupal 8.6.x. + * + * @see https://www.drupal.org/node/2971931 + */ +abstract class EntityFormModeResourceTestBase extends EntityFormModeResourceTestBaseReal { } diff -r e200cb7efeb3 -r c2387f117808 core/modules/rest/tests/src/Functional/EntityResource/EntityFormMode/EntityFormModeXmlAnonTest.php --- a/core/modules/rest/tests/src/Functional/EntityResource/EntityFormMode/EntityFormModeXmlAnonTest.php Thu Apr 26 11:26:54 2018 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,26 +0,0 @@ - [ - 'possible paths' => [ - '\Drupal\Tests\rest\Functional\EntityResource\CLASS\CLASS', - ], + 'path' => '\Drupal\Tests\PROVIDER\Functional\Rest\CLASS', 'class suffix' => [ 'JsonAnonTest', 'JsonBasicAuthTest', @@ -74,9 +72,7 @@ ], // Test coverage for formats provided by the 'hal' module. 'hal' => [ - 'possible paths' => [ - '\Drupal\Tests\hal\Functional\EntityResource\CLASS\CLASS', - ], + 'path' => '\Drupal\Tests\PROVIDER\Functional\Hal\CLASS', 'class suffix' => [ 'HalJsonAnonTest', 'HalJsonBasicAuthTest', @@ -92,21 +88,14 @@ $class_name = end($parts); $module_name = $parts[1]; - // The test class can live either in the REST/HAL module, or in the module - // providing the entity type. - $tests = $default_test_locations; - $tests['serialization']['possible paths'][] = '\Drupal\Tests\\' . $module_name . '\Functional\Rest\CLASS'; - $tests['hal']['possible paths'][] = '\Drupal\Tests\\' . $module_name . '\Functional\Hal\CLASS'; - foreach ($tests as $module => $info) { - $possible_paths = $info['possible paths']; + $path = $info['path']; $missing_tests = []; foreach ($info['class suffix'] as $postfix) { - foreach ($possible_paths as $path) { - $class = str_replace('CLASS', $class_name, $path . $postfix); - if (class_exists($class)) { - continue 2; - } + $class = str_replace(['PROVIDER', 'CLASS'], [$module_name, $class_name], $path . $postfix); + $class_alternative = str_replace("\\Drupal\\Tests\\$module_name\\Functional", '\Drupal\FunctionalTests', $class); + if (class_exists($class) || class_exists($class_alternative)) { + continue; } $missing_tests[] = $postfix; } diff -r e200cb7efeb3 -r c2387f117808 core/modules/rest/tests/src/Functional/EntityResource/EntityResourceTestBase.php --- a/core/modules/rest/tests/src/Functional/EntityResource/EntityResourceTestBase.php Thu Apr 26 11:26:54 2018 +0100 +++ b/core/modules/rest/tests/src/Functional/EntityResource/EntityResourceTestBase.php Tue Jul 10 15:07:59 2018 +0100 @@ -156,12 +156,22 @@ /** * Provides an entity resource. + * + * @param bool $single_format + * Provisions a single-format entity REST resource. Defaults to FALSE. */ - protected function provisionEntityResource() { + protected function provisionEntityResource($single_format = FALSE) { + if ($existing = $this->resourceConfigStorage->load(static::$resourceConfigId)) { + $existing->delete(); + } + + $format = $single_format + ? [static::$format] + : [static::$format, 'foobar']; // It's possible to not have any authentication providers enabled, when // testing public (anonymous) usage of a REST resource. $auth = isset(static::$auth) ? [static::$auth] : []; - $this->provisionResource([static::$format], $auth); + $this->provisionResource($format, $auth); } /** @@ -434,20 +444,6 @@ } $this->provisionEntityResource(); - // Simulate the developer again forgetting the ?_format query string. - $url->setOption('query', []); - - // DX: 406 when ?_format is missing, except when requesting a canonical HTML - // route. - $response = $this->request('GET', $url, $request_options); - if ($has_canonical_url && (!static::$auth || static::$auth === 'cookie')) { - $this->assertSame(403, $response->getStatusCode()); - } - else { - $this->assert406Response($response); - } - - $url->setOption('query', ['_format' => static::$format]); // DX: forgetting authentication: authentication provider-specific error // response. @@ -472,10 +468,44 @@ unset($request_options[RequestOptions::HEADERS]['REST-test-auth-global']); $request_options = NestedArray::mergeDeep($request_options, $this->getAuthenticationRequestOptions('GET')); - // DX: 403 when unauthorized. + // First: single format. Drupal will automatically pick the only format. + $this->provisionEntityResource(TRUE); + $expected_403_cacheability = $this->getExpectedUnauthorizedAccessCacheability(); + // DX: 403 because unauthorized single-format route, ?_format is omittable. + $url->setOption('query', []); $response = $this->request('GET', $url, $request_options); - $expected_403_cacheability = $this->getExpectedUnauthorizedAccessCacheability(); - $this->assertResourceErrorResponse(403, $this->getExpectedUnauthorizedAccessMessage('GET'), $response, $expected_403_cacheability->getCacheTags(), $expected_403_cacheability->getCacheContexts(), static::$auth ? FALSE : 'MISS', 'MISS'); + if ($has_canonical_url) { + $this->assertSame(403, $response->getStatusCode()); + $this->assertSame(['text/html; charset=UTF-8'], $response->getHeader('Content-Type')); + } + else { + $this->assertResourceErrorResponse(403, FALSE, $response, $expected_403_cacheability->getCacheTags(), $expected_403_cacheability->getCacheContexts(), static::$auth ? FALSE : 'MISS', 'MISS'); + } + $this->assertSame(static::$auth ? [] : ['MISS'], $response->getHeader('X-Drupal-Cache')); + // DX: 403 because unauthorized. + $url->setOption('query', ['_format' => static::$format]); + $response = $this->request('GET', $url, $request_options); + $this->assertResourceErrorResponse(403, FALSE, $response, $expected_403_cacheability->getCacheTags(), $expected_403_cacheability->getCacheContexts(), static::$auth ? FALSE : 'MISS', $has_canonical_url ? 'MISS' : 'HIT'); + + // Then, what we'll use for the remainder of the test: multiple formats. + $this->provisionEntityResource(); + // DX: 406 because despite unauthorized, ?_format is not omittable. + $url->setOption('query', []); + $response = $this->request('GET', $url, $request_options); + if ($has_canonical_url) { + $this->assertSame(403, $response->getStatusCode()); + $this->assertSame(['HIT'], $response->getHeader('X-Drupal-Dynamic-Cache')); + } + else { + $this->assertSame(406, $response->getStatusCode()); + $this->assertSame(['UNCACHEABLE'], $response->getHeader('X-Drupal-Dynamic-Cache')); + } + $this->assertSame(['text/html; charset=UTF-8'], $response->getHeader('Content-Type')); + $this->assertSame(static::$auth ? [] : ['MISS'], $response->getHeader('X-Drupal-Cache')); + // DX: 403 because unauthorized. + $url->setOption('query', ['_format' => static::$format]); + $response = $this->request('GET', $url, $request_options); + $this->assertResourceErrorResponse(403, $this->getExpectedUnauthorizedAccessMessage('GET'), $response, $expected_403_cacheability->getCacheTags(), $expected_403_cacheability->getCacheContexts(), static::$auth ? FALSE : 'MISS', 'HIT'); $this->assertArrayNotHasKey('Link', $response->getHeaders()); $this->setUpAuthorization('GET'); diff -r e200cb7efeb3 -r c2387f117808 core/modules/rest/tests/src/Functional/EntityResource/EntityTest/EntityTestJsonAnonTest.php --- a/core/modules/rest/tests/src/Functional/EntityResource/EntityTest/EntityTestJsonAnonTest.php Thu Apr 26 11:26:54 2018 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,26 +0,0 @@ - 'This value shall not be internal!', - 'non_internal_value' => 'Computed! This value shall not be internal!', - ], - ]; - return $expected; - } - - /** - * {@inheritdoc} - */ - protected function createEntity() { - if (!FieldStorageConfig::loadByName('entity_test', 'field_test_internal')) { - FieldStorageConfig::create([ - 'entity_type' => 'entity_test', - 'field_name' => 'field_test_internal', - 'type' => 'internal_property_test', - 'cardinality' => 1, - 'translatable' => FALSE, - ])->save(); - FieldConfig::create([ - 'entity_type' => 'entity_test', - 'field_name' => 'field_test_internal', - 'bundle' => 'entity_test', - 'label' => 'Test field with internal and non-internal properties', - ])->save(); - } - - $entity = parent::createEntity(); - $entity->field_test_internal = [ - 'value' => 'This value shall not be internal!', - ]; - $entity->save(); - return $entity; - } - - /** - * {@inheritdoc} - */ - protected function getNormalizedPostEntity() { - return parent::getNormalizedPostEntity() + [ - 'field_test_internal' => [ - [ - 'value' => 'This value shall not be internal!', - ], - ], - ]; - } - - /** - * {@inheritdoc} - */ - protected function getExpectedCacheContexts() { - return Cache::mergeContexts(parent::getExpectedCacheContexts(), ['request_format']); - } - - /** - * {@inheritdoc} - */ - protected function getExpectedCacheTags() { - return Cache::mergeTags(parent::getExpectedCacheTags(), ['you_are_it', 'no_tag_backs']); - } - -} diff -r e200cb7efeb3 -r c2387f117808 core/modules/rest/tests/src/Functional/EntityResource/EntityTest/EntityTestResourceTestBase.php --- a/core/modules/rest/tests/src/Functional/EntityResource/EntityTest/EntityTestResourceTestBase.php Thu Apr 26 11:26:54 2018 +0100 +++ b/core/modules/rest/tests/src/Functional/EntityResource/EntityTest/EntityTestResourceTestBase.php Tue Jul 10 15:07:59 2018 +0100 @@ -2,162 +2,12 @@ namespace Drupal\Tests\rest\Functional\EntityResource\EntityTest; -use Drupal\entity_test\Entity\EntityTest; -use Drupal\Tests\rest\Functional\BcTimestampNormalizerUnixTestTrait; -use Drupal\Tests\rest\Functional\EntityResource\EntityResourceTestBase; -use Drupal\Tests\Traits\ExpectDeprecationTrait; -use Drupal\user\Entity\User; +use Drupal\Tests\entity_test\Functional\Rest\EntityTestResourceTestBase as EntityTestResourceTestBaseReal; -abstract class EntityTestResourceTestBase extends EntityResourceTestBase { - - use BcTimestampNormalizerUnixTestTrait; - use ExpectDeprecationTrait; - - /** - * {@inheritdoc} - */ - public static $modules = ['entity_test']; - - /** - * {@inheritdoc} - */ - protected static $entityTypeId = 'entity_test'; - - /** - * {@inheritdoc} - */ - protected static $patchProtectedFieldNames = []; - - /** - * @var \Drupal\entity_test\Entity\EntityTest - */ - protected $entity; - - /** - * {@inheritdoc} - */ - protected function setUpAuthorization($method) { - switch ($method) { - case 'GET': - $this->grantPermissionsToTestedRole(['view test entity']); - break; - case 'POST': - $this->grantPermissionsToTestedRole(['create entity_test entity_test_with_bundle entities']); - break; - case 'PATCH': - case 'DELETE': - $this->grantPermissionsToTestedRole(['administer entity_test content']); - break; - } - } - - /** - * {@inheritdoc} - */ - protected function createEntity() { - // Set flag so that internal field 'internal_string_field' is created. - // @see entity_test_entity_base_field_info() - $this->container->get('state')->set('entity_test.internal_field', TRUE); - \Drupal::entityDefinitionUpdateManager()->applyUpdates(); - - $entity_test = EntityTest::create([ - 'name' => 'Llama', - 'type' => 'entity_test', - // Set a value for the internal field to confirm that it will not be - // returned in normalization. - // @see entity_test_entity_base_field_info(). - 'internal_string_field' => [ - 'value' => 'This value shall not be internal!', - ], - ]); - $entity_test->setOwnerId(0); - $entity_test->save(); - - return $entity_test; - } - - /** - * {@inheritdoc} - */ - protected function getExpectedNormalizedEntity() { - $author = User::load(0); - $normalization = [ - 'uuid' => [ - [ - 'value' => $this->entity->uuid() - ] - ], - 'id' => [ - [ - 'value' => 1, - ], - ], - 'langcode' => [ - [ - 'value' => 'en', - ], - ], - 'type' => [ - [ - 'value' => 'entity_test', - ] - ], - 'name' => [ - [ - 'value' => 'Llama', - ] - ], - 'created' => [ - $this->formatExpectedTimestampItemValues((int) $this->entity->get('created')->value) - ], - 'user_id' => [ - [ - 'target_id' => (int) $author->id(), - 'target_type' => 'user', - 'target_uuid' => $author->uuid(), - 'url' => $author->toUrl()->toString(), - ] - ], - 'field_test_text' => [], - ]; - - return $normalization; - } - - /** - * {@inheritdoc} - */ - protected function getNormalizedPostEntity() { - return [ - 'type' => [ - [ - 'value' => 'entity_test', - ], - ], - 'name' => [ - [ - 'value' => 'Dramallama', - ], - ], - ]; - } - - /** - * {@inheritdoc} - */ - protected function getExpectedUnauthorizedAccessMessage($method) { - if ($this->config('rest.settings')->get('bc_entity_resource_permissions')) { - return parent::getExpectedUnauthorizedAccessMessage($method); - } - - switch ($method) { - case 'GET': - return "The 'view test entity' permission is required."; - case 'POST': - return "The following permissions are required: 'administer entity_test content' OR 'administer entity_test_with_bundle content' OR 'create entity_test entity_test_with_bundle entities'."; - default: - return parent::getExpectedUnauthorizedAccessMessage($method); - } - } - +/** + * Class for backward compatibility. It is deprecated in Drupal 8.6.x. + * + * @see https://www.drupal.org/node/2971931 + */ +abstract class EntityTestResourceTestBase extends EntityTestResourceTestBaseReal { } diff -r e200cb7efeb3 -r c2387f117808 core/modules/rest/tests/src/Functional/EntityResource/EntityTest/EntityTestTextItemNormalizerTest.php --- a/core/modules/rest/tests/src/Functional/EntityResource/EntityTest/EntityTestTextItemNormalizerTest.php Thu Apr 26 11:26:54 2018 +0100 +++ b/core/modules/rest/tests/src/Functional/EntityResource/EntityTest/EntityTestTextItemNormalizerTest.php Tue Jul 10 15:07:59 2018 +0100 @@ -5,6 +5,7 @@ use Drupal\Core\Cache\Cache; use Drupal\Core\Language\LanguageInterface; use Drupal\filter\Entity\FilterFormat; +use Drupal\Tests\entity_test\Functional\Rest\EntityTestResourceTestBase; use Drupal\Tests\rest\Functional\AnonResourceTestTrait; /** diff -r e200cb7efeb3 -r c2387f117808 core/modules/rest/tests/src/Functional/EntityResource/EntityTest/EntityTestXmlAnonTest.php --- a/core/modules/rest/tests/src/Functional/EntityResource/EntityTest/EntityTestXmlAnonTest.php Thu Apr 26 11:26:54 2018 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,28 +0,0 @@ -grantPermissionsToTestedRole(['administer entity_test_bundle content']); - } - - /** - * {@inheritdoc} - */ - protected function createEntity() { - $entity_test_bundle = EntityTestBundle::create([ - 'id' => 'camelids', - 'label' => 'Camelids', - 'description' => 'Camelids are large, strictly herbivorous animals with slender necks and long legs.', - ]); - $entity_test_bundle->save(); - - return $entity_test_bundle; - } - - /** - * {@inheritdoc} - */ - protected function getExpectedNormalizedEntity() { - return [ - 'dependencies' => [], - 'description' => 'Camelids are large, strictly herbivorous animals with slender necks and long legs.', - 'id' => 'camelids', - 'label' => 'Camelids', - 'langcode' => 'en', - 'status' => TRUE, - 'uuid' => $this->entity->uuid(), - ]; - } - - /** - * {@inheritdoc} - */ - protected function getNormalizedPostEntity() { - // @todo Update in https://www.drupal.org/node/2300677. - } - +/** + * Class for backward compatibility. It is deprecated in Drupal 8.6.x. + * + * @see https://www.drupal.org/node/2971931 + */ +abstract class EntityTestBundleResourceTestBase extends EntityTestBundleResourceTestBaseReal { } diff -r e200cb7efeb3 -r c2387f117808 core/modules/rest/tests/src/Functional/EntityResource/EntityTestBundle/EntityTestBundleXmlAnonTest.php --- a/core/modules/rest/tests/src/Functional/EntityResource/EntityTestBundle/EntityTestBundleXmlAnonTest.php Thu Apr 26 11:26:54 2018 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,26 +0,0 @@ -grantPermissionsToTestedRole(['view test entity']); - break; - case 'POST': - $this->grantPermissionsToTestedRole([ - 'administer entity_test content', - 'administer entity_test_with_bundle content', - 'create entity_test entity_test_with_bundle entities', - ]); - break; - case 'PATCH': - case 'DELETE': - $this->grantPermissionsToTestedRole(['administer entity_test content']); - break; - } - } - - /** - * {@inheritdoc} - */ - protected function createEntity() { - $entity_test_label = EntityTestLabel::create([ - 'name' => 'label_llama', - ]); - $entity_test_label->setOwnerId(0); - $entity_test_label->save(); - return $entity_test_label; - } - - /** - * {@inheritdoc} - */ - protected function getExpectedNormalizedEntity() { - $author = User::load(0); - $normalization = [ - 'uuid' => [ - [ - 'value' => $this->entity->uuid(), - ], - ], - 'id' => [ - [ - 'value' => (int) $this->entity->id(), - ], - ], - 'langcode' => [ - [ - 'value' => 'en', - ], - ], - 'type' => [ - [ - 'value' => 'entity_test_label', - ], - ], - 'name' => [ - [ - 'value' => 'label_llama', - ], - ], - 'created' => [ - $this->formatExpectedTimestampItemValues((int) $this->entity->get('created')->value), - ], - 'user_id' => [ - [ - 'target_id' => (int) $author->id(), - 'target_type' => 'user', - 'target_uuid' => $author->uuid(), - 'url' => $author->toUrl()->toString(), - ], - ], - ]; - - return $normalization; - } - - /** - * {@inheritdoc} - */ - protected function getNormalizedPostEntity() { - return [ - 'type' => [ - [ - 'value' => 'entity_test_label', - ], - ], - 'name' => [ - [ - 'value' => 'label_llama', - ], - ], - ]; - } - - /** - * {@inheritdoc} - */ - protected function getExpectedCacheContexts() { - return ['user.permissions']; - } - - /** - * {@inheritdoc} - */ - protected function getExpectedUnauthorizedAccessMessage($method) { - if ($this->config('rest.settings')->get('bc_entity_resource_permissions')) { - return parent::getExpectedUnauthorizedAccessMessage($method); - } - - switch ($method) { - case 'GET': - return "The 'view test entity' permission is required."; - case 'POST': - return "The following permissions are required: 'administer entity_test content' OR 'administer entity_test_with_bundle content' OR 'create entity_test_label entity_test_with_bundle entities'."; - case 'PATCH': - case 'DELETE': - return "The 'administer entity_test content' permission is required."; - default: - return parent::getExpectedUnauthorizedAccessMessage($method); - } - } - +/** + * Class for backward compatibility. It is deprecated in Drupal 8.6.x. + * + * @see https://www.drupal.org/node/2971931 + */ +abstract class EntityTestLabelResourceTestBase extends EntityTestLabelResourceTestBaseReal { } diff -r e200cb7efeb3 -r c2387f117808 core/modules/rest/tests/src/Functional/EntityResource/EntityTestLabel/EntityTestLabelXmlAnonTest.php --- a/core/modules/rest/tests/src/Functional/EntityResource/EntityTestLabel/EntityTestLabelXmlAnonTest.php Thu Apr 26 11:26:54 2018 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,26 +0,0 @@ -grantPermissionsToTestedRole(['administer node display']); - } - - /** - * {@inheritdoc} - */ - protected function createEntity() { - // Create a "Camelids" node type. - $camelids = NodeType::create([ - 'name' => 'Camelids', - 'type' => 'camelids', - ]); - $camelids->save(); - - // Create a view display. - $view_display = EntityViewDisplay::create([ - 'targetEntityType' => 'node', - 'bundle' => 'camelids', - 'mode' => 'default', - 'status' => TRUE, - ]); - $view_display->save(); - - return $view_display; - } - - /** - * {@inheritdoc} - */ - protected function getExpectedNormalizedEntity() { - return [ - 'bundle' => 'camelids', - 'content' => [ - 'links' => [ - 'region' => 'content', - 'weight' => 100, - ], - ], - 'dependencies' => [ - 'config' => [ - 'node.type.camelids', - ], - 'module' => [ - 'user', - ], - ], - 'hidden' => [], - 'id' => 'node.camelids.default', - 'langcode' => 'en', - 'mode' => 'default', - 'status' => TRUE, - 'targetEntityType' => 'node', - 'uuid' => $this->entity->uuid(), - ]; - } - - /** - * {@inheritdoc} - */ - protected function getNormalizedPostEntity() { - // @todo Update in https://www.drupal.org/node/2300677. - } - - /** - * {@inheritdoc} - */ - protected function getExpectedCacheContexts() { - return [ - 'user.permissions', - ]; - } - - /** - * {@inheritdoc} - */ - protected function getExpectedUnauthorizedAccessMessage($method) { - if ($this->config('rest.settings')->get('bc_entity_resource_permissions')) { - return parent::getExpectedUnauthorizedAccessMessage($method); - } - - return "The 'administer node display' permission is required."; - } - +/** + * Class for backward compatibility. It is deprecated in Drupal 8.6.x. + * + * @see https://www.drupal.org/node/2971931 + */ +abstract class EntityViewDisplayResourceTestBase extends EntityViewDisplayResourceTestBaseReal { } diff -r e200cb7efeb3 -r c2387f117808 core/modules/rest/tests/src/Functional/EntityResource/EntityViewDisplay/EntityViewDisplayXmlAnonTest.php --- a/core/modules/rest/tests/src/Functional/EntityResource/EntityViewDisplay/EntityViewDisplayXmlAnonTest.php Thu Apr 26 11:26:54 2018 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,26 +0,0 @@ -grantPermissionsToTestedRole(['administer display modes']); - } - - /** - * {@inheritdoc} - */ - protected function createEntity() { - $entity_view_mode = EntityViewMode::create([ - 'id' => 'user.test', - 'label' => 'Test', - 'targetEntityType' => 'user', - ]); - $entity_view_mode->save(); - return $entity_view_mode; - } - - /** - * {@inheritdoc} - */ - protected function getExpectedNormalizedEntity() { - return [ - 'cache' => TRUE, - 'dependencies' => [ - 'module' => [ - 'user', - ], - ], - 'id' => 'user.test', - 'label' => 'Test', - 'langcode' => 'en', - 'status' => TRUE, - 'targetEntityType' => 'user', - 'uuid' => $this->entity->uuid(), - ]; - } - - /** - * {@inheritdoc} - */ - protected function getNormalizedPostEntity() { - // @todo Update in https://www.drupal.org/node/2300677. - } - +/** + * Class for backward compatibility. It is deprecated in Drupal 8.6.x. + * + * @see https://www.drupal.org/node/2971931 + */ +abstract class EntityViewModeResourceTestBase extends EntityViewModeResourceTestBaseReal { } diff -r e200cb7efeb3 -r c2387f117808 core/modules/rest/tests/src/Functional/EntityResource/EntityViewMode/EntityViewModeXmlAnonTest.php --- a/core/modules/rest/tests/src/Functional/EntityResource/EntityViewMode/EntityViewModeXmlAnonTest.php Thu Apr 26 11:26:54 2018 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,26 +0,0 @@ -grantPermissionsToTestedRole(['access news feeds']); - break; - case 'POST': - case 'PATCH': - case 'DELETE': - $this->grantPermissionsToTestedRole(['administer news feeds']); - break; - } - } - - /** - * {@inheritdoc} - */ - public function createEntity() { - $feed = Feed::create(); - $feed->set('fid', 1) - ->set('uuid', 'abcdefg') - ->setTitle('Feed') - ->setUrl('http://example.com/rss.xml') - ->setDescription('Feed Resource Test 1') - ->setRefreshRate(900) - ->setLastCheckedTime(123456789) - ->setQueuedTime(123456789) - ->setWebsiteUrl('http://example.com') - ->setImage('http://example.com/feed_logo') - ->setHash('abcdefg') - ->setEtag('hijklmn') - ->setLastModified(123456789) - ->save(); - - return $feed; - } - - /** - * {@inheritdoc} - */ - protected function getExpectedNormalizedEntity() { - return [ - 'uuid' => [ - [ - 'value' => 'abcdefg' - ] - ], - 'fid' => [ - [ - 'value' => 1 - ] - ], - 'langcode' => [ - [ - 'value' => 'en' - ] - ], - 'url' => [ - [ - 'value' => 'http://example.com/rss.xml' - ] - ], - 'title' => [ - [ - 'value' => 'Feed' - ] - ], - 'refresh' => [ - [ - 'value' => 900 - ] - ], - 'checked' => [ - $this->formatExpectedTimestampItemValues(123456789), - ], - 'queued' => [ - $this->formatExpectedTimestampItemValues(123456789), - ], - 'link' => [ - [ - 'value' => 'http://example.com' - ] - ], - 'description' => [ - [ - 'value' => 'Feed Resource Test 1' - ] - ], - 'image' => [ - [ - 'value' => 'http://example.com/feed_logo' - ] - ], - 'hash' => [ - [ - 'value' => 'abcdefg' - ] - ], - 'etag' => [ - [ - 'value' => 'hijklmn' - ] - ], - 'modified' => [ - $this->formatExpectedTimestampItemValues(123456789), - ], - ]; - } - - /** - * {@inheritdoc} - */ - protected function getNormalizedPostEntity() { - return [ - 'title' => [ - [ - 'value' => 'Feed Resource Post Test' - ] - ], - 'url' => [ - [ - 'value' => 'http://example.com/feed' - ] - ], - 'refresh' => [ - [ - 'value' => 900 - ] - ], - 'description' => [ - [ - 'value' => 'Feed Resource Post Test Description' - ] - ], - ]; - } - - /** - * {@inheritdoc} - */ - protected function getExpectedUnauthorizedAccessMessage($method) { - if ($this->config('rest.settings')->get('bc_entity_resource_permissions')) { - return parent::getExpectedUnauthorizedAccessMessage($method); - } - - switch ($method) { - case 'GET': - return "The 'access news feeds' permission is required."; - case 'POST': - case 'PATCH': - case 'DELETE': - return "The 'administer news feeds' permission is required."; - default: - return parent::getExpectedUnauthorizedAccessMessage($method); - } - } - +/** + * Class for backward compatibility. It is deprecated in Drupal 8.6.x. + * + * @see https://www.drupal.org/node/2971931 + */ +abstract class FeedResourceTestBase extends FeedResourceTestBaseReal { } diff -r e200cb7efeb3 -r c2387f117808 core/modules/rest/tests/src/Functional/EntityResource/Feed/FeedXmlAnonTest.php --- a/core/modules/rest/tests/src/Functional/EntityResource/Feed/FeedXmlAnonTest.php Thu Apr 26 11:26:54 2018 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,26 +0,0 @@ -grantPermissionsToTestedRole(['administer node fields']); - } - - /** - * {@inheritdoc} - */ - protected function createEntity() { - $camelids = NodeType::create([ - 'name' => 'Camelids', - 'type' => 'camelids', - ]); - $camelids->save(); - - $field_storage = FieldStorageConfig::create([ - 'field_name' => 'field_llama', - 'entity_type' => 'node', - 'type' => 'text', - ]); - $field_storage->save(); - - $entity = FieldConfig::create([ - 'field_storage' => $field_storage, - 'bundle' => 'camelids', - ]); - $entity->save(); - - return $entity; - } - - /** - * {@inheritdoc} - */ - protected function getExpectedNormalizedEntity() { - return [ - 'bundle' => 'camelids', - 'default_value' => [], - 'default_value_callback' => '', - 'dependencies' => [ - 'config' => [ - 'field.storage.node.field_llama', - 'node.type.camelids', - ], - 'module' => [ - 'text', - ], - ], - 'description' => '', - 'entity_type' => 'node', - 'field_name' => 'field_llama', - 'field_type' => 'text', - 'id' => 'node.camelids.field_llama', - 'label' => 'field_llama', - 'langcode' => 'en', - 'required' => FALSE, - 'settings' => [], - 'status' => TRUE, - 'translatable' => TRUE, - 'uuid' => $this->entity->uuid(), - ]; - } - - /** - * {@inheritdoc} - */ - protected function getNormalizedPostEntity() { - // @todo Update in https://www.drupal.org/node/2300677. - } - - /** - * {@inheritdoc} - */ - protected function getExpectedCacheContexts() { - return [ - 'user.permissions', - ]; - } - - /** - * {@inheritdoc} - */ - protected function getExpectedUnauthorizedAccessMessage($method) { - if ($this->config('rest.settings')->get('bc_entity_resource_permissions')) { - return parent::getExpectedUnauthorizedAccessMessage($method); - } - - return "The 'administer node fields' permission is required."; - } - +/** + * Class for backward compatibility. It is deprecated in Drupal 8.6.x. + * + * @see https://www.drupal.org/node/2971931 + */ +abstract class FieldConfigResourceTestBase extends FieldConfigResourceTestBaseReal { } diff -r e200cb7efeb3 -r c2387f117808 core/modules/rest/tests/src/Functional/EntityResource/FieldConfig/FieldConfigXmlAnonTest.php --- a/core/modules/rest/tests/src/Functional/EntityResource/FieldConfig/FieldConfigXmlAnonTest.php Thu Apr 26 11:26:54 2018 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,26 +0,0 @@ -grantPermissionsToTestedRole(['administer node fields']); - } - - /** - * {@inheritdoc} - */ - protected function createEntity() { - $field_storage = FieldStorageConfig::create([ - 'field_name' => 'true_llama', - 'entity_type' => 'node', - 'type' => 'boolean', - ]); - $field_storage->save(); - return $field_storage; - } - - /** - * {@inheritdoc} - */ - protected function getExpectedNormalizedEntity() { - return [ - 'cardinality' => 1, - 'custom_storage' => FALSE, - 'dependencies' => [ - 'module' => ['node'], - ], - 'entity_type' => 'node', - 'field_name' => 'true_llama', - 'id' => 'node.true_llama', - 'indexes' => [], - 'langcode' => 'en', - 'locked' => FALSE, - 'module' => 'core', - 'persist_with_no_fields' => FALSE, - 'settings' => [], - 'status' => TRUE, - 'translatable' => TRUE, - 'type' => 'boolean', - 'uuid' => $this->entity->uuid(), - ]; - } - - /** - * {@inheritdoc} - */ - protected function getNormalizedPostEntity() { - // @todo Update in https://www.drupal.org/node/2300677. - } - - /** - * {@inheritdoc} - */ - protected function getExpectedUnauthorizedAccessMessage($method) { - if ($this->config('rest.settings')->get('bc_entity_resource_permissions')) { - return parent::getExpectedUnauthorizedAccessMessage($method); - } - - switch ($method) { - case 'GET': - return "The 'administer node fields' permission is required."; - - default: - return parent::getExpectedUnauthorizedAccessMessage($method); - } - } - - /** - * {@inheritdoc} - */ - protected function getExpectedCacheContexts() { - return [ - 'user.permissions', - ]; - } - +/** + * Class for backward compatibility. It is deprecated in Drupal 8.6.x. + * + * @see https://www.drupal.org/node/2971931 + */ +abstract class FieldStorageConfigResourceTestBase extends FieldStorageConfigResourceTestBaseReal { } diff -r e200cb7efeb3 -r c2387f117808 core/modules/rest/tests/src/Functional/EntityResource/FieldStorageConfig/FieldStorageConfigXmlAnonTest.php --- a/core/modules/rest/tests/src/Functional/EntityResource/FieldStorageConfig/FieldStorageConfigXmlAnonTest.php Thu Apr 26 11:26:54 2018 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,26 +0,0 @@ -grantPermissionsToTestedRole(['access content']); - break; - - case 'PATCH': - case 'DELETE': - // \Drupal\file\FileAccessControlHandler::checkAccess() grants 'update' - // and 'delete' access only to the user that owns the file. So there is - // no permission to grant: instead, the file owner must be changed from - // its default (user 1) to the current user. - $this->makeCurrentUserFileOwner(); - break; - } - } - - /** - * {@inheritdoc} - */ - protected function grantPermissionsToTestedRole(array $permissions) { - // testPatch() and testDelete() test the 'bc_entity_resource_permissions' BC - // layer; also call makeCurrentUserFileOwner() then. - if ($permissions === ['restful patch entity:file'] || $permissions === ['restful delete entity:file']) { - $this->makeCurrentUserFileOwner(); - } - parent::grantPermissionsToTestedRole($permissions); - } - - /** - * Makes the current user the file owner. - */ - protected function makeCurrentUserFileOwner() { - $account = static::$auth ? User::load(2) : User::load(0); - $this->entity->setOwnerId($account->id()); - $this->entity->setOwner($account); - $this->entity->save(); - } - - /** - * {@inheritdoc} - */ - protected function createEntity() { - $this->author = User::load(1); - - $file = File::create(); - $file->setOwnerId($this->author->id()); - $file->setFilename('drupal.txt'); - $file->setMimeType('text/plain'); - $file->setFileUri('public://drupal.txt'); - $file->set('status', FILE_STATUS_PERMANENT); - $file->save(); - - file_put_contents($file->getFileUri(), 'Drupal'); - - return $file; - } - - /** - * {@inheritdoc} - */ - protected function getExpectedNormalizedEntity() { - return [ - 'changed' => [ - $this->formatExpectedTimestampItemValues($this->entity->getChangedTime()), - ], - 'created' => [ - $this->formatExpectedTimestampItemValues((int) $this->entity->getCreatedTime()), - ], - 'fid' => [ - [ - 'value' => 1, - ], - ], - 'filemime' => [ - [ - 'value' => 'text/plain', - ], - ], - 'filename' => [ - [ - 'value' => 'drupal.txt', - ], - ], - 'filesize' => [ - [ - 'value' => (int) $this->entity->getSize(), - ], - ], - 'langcode' => [ - [ - 'value' => 'en', - ], - ], - 'status' => [ - [ - 'value' => TRUE, - ], - ], - 'uid' => [ - [ - 'target_id' => (int) $this->author->id(), - 'target_type' => 'user', - 'target_uuid' => $this->author->uuid(), - 'url' => base_path() . 'user/' . $this->author->id(), - ], - ], - 'uri' => [ - [ - 'url' => base_path() . $this->siteDirectory . '/files/drupal.txt', - 'value' => 'public://drupal.txt', - ], - ], - 'uuid' => [ - [ - 'value' => $this->entity->uuid(), - ], - ], - ]; - } - - /** - * {@inheritdoc} - */ - protected function getNormalizedPostEntity() { - return [ - 'uid' => [ - [ - 'target_id' => $this->author->id(), - ], - ], - 'filename' => [ - [ - 'value' => 'drupal.txt', - ], - ], - ]; - } - - /** - * {@inheritdoc} - */ - protected function getNormalizedPatchEntity() { - return array_diff_key($this->getNormalizedPostEntity(), ['uid' => TRUE]); - } - - /** - * {@inheritdoc} - */ - protected function getExpectedCacheContexts() { - return [ - 'user.permissions', - ]; - } - - /** - * {@inheritdoc} - */ - public function testPost() { - // @todo https://www.drupal.org/node/1927648 - $this->markTestSkipped(); - } - - /** - * {@inheritdoc} - */ - protected function getExpectedUnauthorizedAccessMessage($method) { - if ($this->config('rest.settings')->get('bc_entity_resource_permissions')) { - return parent::getExpectedUnauthorizedAccessMessage($method); - } - - if ($method === 'GET') { - return "The 'access content' permission is required."; - } - if ($method === 'PATCH') { - return 'You are not authorized to update this file entity.'; - } - return parent::getExpectedUnauthorizedAccessMessage($method); - } - +/** + * Class for backward compatibility. It is deprecated in Drupal 8.6.x. + * + * @see https://www.drupal.org/node/2971931 + */ +abstract class FileResourceTestBase extends FileResourceTestBaseReal { } diff -r e200cb7efeb3 -r c2387f117808 core/modules/rest/tests/src/Functional/EntityResource/File/FileXmlAnonTest.php --- a/core/modules/rest/tests/src/Functional/EntityResource/File/FileXmlAnonTest.php Thu Apr 26 11:26:54 2018 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,26 +0,0 @@ -grantPermissionsToTestedRole(['administer filters']); - } - - /** - * {@inheritdoc} - */ - protected function createEntity() { - $pablo_format = FilterFormat::create([ - 'name' => 'Pablo Piccasso', - 'format' => 'pablo', - 'langcode' => 'es', - 'filters' => [ - 'filter_html' => [ - 'status' => TRUE, - 'settings' => [ - 'allowed_html' => '

    ', - ], - ], - ], - ]); - $pablo_format->save(); - return $pablo_format; - } - - /** - * {@inheritdoc} - */ - protected function getExpectedNormalizedEntity() { - return [ - 'dependencies' => [], - 'filters' => [ - 'filter_html' => [ - 'id' => 'filter_html', - 'provider' => 'filter', - 'status' => TRUE, - 'weight' => -10, - 'settings' => [ - 'allowed_html' => '

    ', - 'filter_html_help' => TRUE, - 'filter_html_nofollow' => FALSE, - ], - ], - ], - 'format' => 'pablo', - 'langcode' => 'es', - 'name' => 'Pablo Piccasso', - 'status' => TRUE, - 'uuid' => $this->entity->uuid(), - 'weight' => 0, - ]; - } - - /** - * {@inheritdoc} - */ - protected function getNormalizedPostEntity() { - // @todo Update in https://www.drupal.org/node/2300677. - } - +/** + * Class for backward compatibility. It is deprecated in Drupal 8.6.x. + * + * @see https://www.drupal.org/node/2971931 + */ +abstract class FilterFormatResourceTestBase extends FilterFormatResourceTestBaseReal { } diff -r e200cb7efeb3 -r c2387f117808 core/modules/rest/tests/src/Functional/EntityResource/FilterFormat/FilterFormatXmlAnonTest.php --- a/core/modules/rest/tests/src/Functional/EntityResource/FilterFormat/FilterFormatXmlAnonTest.php Thu Apr 26 11:26:54 2018 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,26 +0,0 @@ -grantPermissionsToTestedRole(['administer image styles']); - } - - /** - * {@inheritdoc} - */ - protected function createEntity() { - // Create a "Camelids" image style. - $camelids = ImageStyle::create([ - 'name' => 'camelids', - 'label' => 'Camelids', - ]); - - // Add an image effect. - $effect = [ - 'id' => 'image_scale_and_crop', - 'data' => [ - 'width' => 120, - 'height' => 121, - ], - 'weight' => 0, - ]; - $this->effectUuid = $camelids->addImageEffect($effect); - - $camelids->save(); - - return $camelids; - } - - /** - * {@inheritdoc} - */ - protected function getExpectedNormalizedEntity() { - return [ - 'dependencies' => [], - 'effects' => [ - $this->effectUuid => [ - 'uuid' => $this->effectUuid, - 'id' => 'image_scale_and_crop', - 'weight' => 0, - 'data' => [ - 'width' => 120, - 'height' => 121, - ], - ], - ], - 'label' => 'Camelids', - 'langcode' => 'en', - 'name' => 'camelids', - 'status' => TRUE, - 'uuid' => $this->entity->uuid(), - ]; - } - - /** - * {@inheritdoc} - */ - protected function getNormalizedPostEntity() { - // @todo Update in https://www.drupal.org/node/2300677. - } - - /** - * {@inheritdoc} - */ - protected function getExpectedUnauthorizedAccessMessage($method) { - if ($this->config('rest.settings')->get('bc_entity_resource_permissions')) { - return parent::getExpectedUnauthorizedAccessMessage($method); - } - - return "The 'administer image styles' permission is required."; - } - +abstract class ImageStyleResourceTestBase extends ImageStyleResourceTestBaseReal { } diff -r e200cb7efeb3 -r c2387f117808 core/modules/rest/tests/src/Functional/EntityResource/ImageStyle/ImageStyleXmlAnonTest.php --- a/core/modules/rest/tests/src/Functional/EntityResource/ImageStyle/ImageStyleXmlAnonTest.php Thu Apr 26 11:26:54 2018 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,34 +0,0 @@ -markTestSkipped(); - } - -} diff -r e200cb7efeb3 -r c2387f117808 core/modules/rest/tests/src/Functional/EntityResource/ImageStyle/ImageStyleXmlBasicAuthTest.php --- a/core/modules/rest/tests/src/Functional/EntityResource/ImageStyle/ImageStyleXmlBasicAuthTest.php Thu Apr 26 11:26:54 2018 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,44 +0,0 @@ -markTestSkipped(); - } - -} diff -r e200cb7efeb3 -r c2387f117808 core/modules/rest/tests/src/Functional/EntityResource/ImageStyle/ImageStyleXmlCookieTest.php --- a/core/modules/rest/tests/src/Functional/EntityResource/ImageStyle/ImageStyleXmlCookieTest.php Thu Apr 26 11:26:54 2018 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,39 +0,0 @@ -markTestSkipped(); - } - -} diff -r e200cb7efeb3 -r c2387f117808 core/modules/rest/tests/src/Functional/EntityResource/Item/ItemJsonAnonTest.php --- a/core/modules/rest/tests/src/Functional/EntityResource/Item/ItemJsonAnonTest.php Thu Apr 26 11:26:54 2018 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,24 +0,0 @@ -grantPermissionsToTestedRole(['access news feeds']); - break; - - case 'POST': - case 'PATCH': - case 'DELETE': - $this->grantPermissionsToTestedRole(['administer news feeds']); - break; - } - } - - /** - * {@inheritdoc} - */ - protected function createEntity() { - // Create a "Camelids" feed. - $feed = Feed::create([ - 'title' => 'Camelids', - 'url' => 'https://groups.drupal.org/not_used/167169', - 'refresh' => 900, - 'checked' => 1389919932, - 'description' => 'Drupal Core Group feed', - ]); - $feed->save(); - - // Create a "Llama" item. - $item = Item::create(); - $item->setTitle('Llama') - ->setFeedId($feed->id()) - ->setLink('https://www.drupal.org/') - ->setPostedTime(123456789) - ->save(); - - return $item; - } - - /** - * {@inheritdoc} - */ - protected function createAnotherEntity() { - $entity = $this->entity->createDuplicate(); - $entity->setLink('https://www.example.org/'); - $label_key = $entity->getEntityType()->getKey('label'); - if ($label_key) { - $entity->set($label_key, $entity->label() . '_dupe'); - } - $entity->save(); - return $entity; - } - - /** - * {@inheritdoc} - */ - protected function getExpectedNormalizedEntity() { - $feed = Feed::load($this->entity->getFeedId()); - - return [ - 'iid' => [ - [ - 'value' => 1, - ], - ], - 'langcode' => [ - [ - 'value' => 'en', - ], - ], - 'fid' => [ - [ - 'target_id' => 1, - 'target_type' => 'aggregator_feed', - 'target_uuid' => $feed->uuid(), - 'url' => base_path() . 'aggregator/sources/1', - ], - ], - 'title' => [ - [ - 'value' => 'Llama', - ], - ], - 'link' => [ - [ - 'value' => 'https://www.drupal.org/', - ], - ], - 'author' => [], - 'description' => [], - 'timestamp' => [ - $this->formatExpectedTimestampItemValues(123456789), - ], - 'guid' => [], - ]; - } - - /** - * {@inheritdoc} - */ - protected function getNormalizedPostEntity() { - return [ - 'fid' => [ - [ - 'target_id' => 1, - ], - ], - 'title' => [ - [ - 'value' => 'Llama', - ], - ], - 'link' => [ - [ - 'value' => 'https://www.drupal.org/', - ], - ], - ]; - } - - /** - * {@inheritdoc} - */ - protected function getExpectedCacheContexts() { - // @see ::createEntity() - return ['user.permissions']; - } - - /** - * {@inheritdoc} - */ - protected function getExpectedUnauthorizedAccessMessage($method) { - if ($this->config('rest.settings')->get('bc_entity_resource_permissions')) { - return parent::getExpectedUnauthorizedAccessMessage($method); - } - - switch ($method) { - case 'GET': - return "The 'access news feeds' permission is required."; - - case 'POST': - case 'PATCH': - case 'DELETE': - return "The 'administer news feeds' permission is required."; - - default: - return parent::getExpectedUnauthorizedAccessMessage($method); - } - } - +abstract class ItemResourceTestBase extends ItemResourceTestBaseReal { } diff -r e200cb7efeb3 -r c2387f117808 core/modules/rest/tests/src/Functional/EntityResource/Item/ItemXmlAnonTest.php --- a/core/modules/rest/tests/src/Functional/EntityResource/Item/ItemXmlAnonTest.php Thu Apr 26 11:26:54 2018 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,26 +0,0 @@ -grantPermissionsToTestedRole(['view media']); - break; - - case 'POST': - $this->grantPermissionsToTestedRole(['create camelids media']); - break; - - case 'PATCH': - $this->grantPermissionsToTestedRole(['edit any camelids media']); - // @todo Remove this in https://www.drupal.org/node/2824851. - $this->grantPermissionsToTestedRole(['access content']); - break; - - case 'DELETE': - $this->grantPermissionsToTestedRole(['delete any camelids media']); - break; - } - } - - /** - * {@inheritdoc} - */ - protected function createEntity() { - if (!MediaType::load('camelids')) { - // Create a "Camelids" media type. - $media_type = MediaType::create([ - 'name' => 'Camelids', - 'id' => 'camelids', - 'description' => 'Camelids are large, strictly herbivorous animals with slender necks and long legs.', - 'source' => 'file', - ]); - $media_type->save(); - // Create the source field. - $source_field = $media_type->getSource()->createSourceField($media_type); - $source_field->getFieldStorageDefinition()->save(); - $source_field->save(); - $media_type - ->set('source_configuration', [ - 'source_field' => $source_field->getName(), - ]) - ->save(); - } - - // Create a file to upload. - $file = File::create([ - 'uri' => 'public://llama.txt', - ]); - $file->setPermanent(); - $file->save(); - - // Create a "Llama" media item. - $media = Media::create([ - 'bundle' => 'camelids', - 'field_media_file' => [ - 'target_id' => $file->id(), - ], - ]); - $media - ->setName('Llama') - ->setPublished(TRUE) - ->setCreatedTime(123456789) - ->setOwnerId(static::$auth ? $this->account->id() : 0) - ->setRevisionUserId(static::$auth ? $this->account->id() : 0) - ->save(); - - return $media; - } - - /** - * {@inheritdoc} - */ - protected function getExpectedNormalizedEntity() { - $file = File::load(1); - $thumbnail = File::load(2); - $author = User::load($this->entity->getOwnerId()); - return [ - 'mid' => [ - [ - 'value' => 1, - ], - ], - 'uuid' => [ - [ - 'value' => $this->entity->uuid(), - ], - ], - 'vid' => [ - [ - 'value' => 1, - ], - ], - 'langcode' => [ - [ - 'value' => 'en', - ], - ], - 'bundle' => [ - [ - 'target_id' => 'camelids', - 'target_type' => 'media_type', - 'target_uuid' => MediaType::load('camelids')->uuid(), - ], - ], - 'name' => [ - [ - 'value' => 'Llama', - ], - ], - 'field_media_file' => [ - [ - 'description' => NULL, - 'display' => NULL, - 'target_id' => (int) $file->id(), - 'target_type' => 'file', - 'target_uuid' => $file->uuid(), - 'url' => $file->url(), - ], - ], - 'thumbnail' => [ - [ - 'alt' => 'Thumbnail', - 'width' => 180, - 'height' => 180, - 'target_id' => (int) $thumbnail->id(), - 'target_type' => 'file', - 'target_uuid' => $thumbnail->uuid(), - 'title' => 'Llama', - 'url' => $thumbnail->url(), - ], - ], - 'status' => [ - [ - 'value' => TRUE, - ], - ], - 'created' => [ - $this->formatExpectedTimestampItemValues(123456789), - ], - 'changed' => [ - $this->formatExpectedTimestampItemValues($this->entity->getChangedTime()), - ], - 'revision_created' => [ - $this->formatExpectedTimestampItemValues((int) $this->entity->getRevisionCreationTime()), - ], - 'default_langcode' => [ - [ - 'value' => TRUE, - ], - ], - 'uid' => [ - [ - 'target_id' => (int) $author->id(), - 'target_type' => 'user', - 'target_uuid' => $author->uuid(), - 'url' => base_path() . 'user/' . $author->id(), - ], - ], - 'revision_user' => [ - [ - 'target_id' => (int) $author->id(), - 'target_type' => 'user', - 'target_uuid' => $author->uuid(), - 'url' => base_path() . 'user/' . $author->id(), - ], - ], - 'revision_log_message' => [], - 'revision_translation_affected' => [ - [ - 'value' => TRUE, - ], - ], - ]; - } - - /** - * {@inheritdoc} - */ - protected function getNormalizedPostEntity() { - return [ - 'bundle' => [ - [ - 'target_id' => 'camelids', - ], - ], - 'name' => [ - [ - 'value' => 'Dramallama', - ], - ], - ]; - } - - /** - * {@inheritdoc} - */ - protected function getExpectedUnauthorizedAccessMessage($method) { - if ($this->config('rest.settings')->get('bc_entity_resource_permissions')) { - return parent::getExpectedUnauthorizedAccessMessage($method); - } - - switch ($method) { - case 'GET'; - return "The 'view media' permission is required and the media item must be published."; - - case 'PATCH': - return 'You are not authorized to update this media entity of bundle camelids.'; - - case 'DELETE': - return 'You are not authorized to delete this media entity of bundle camelids.'; - - default: - return parent::getExpectedUnauthorizedAccessMessage($method); - } - } - - /** - * {@inheritdoc} - */ - public function testPost() { - $this->markTestSkipped('POSTing File Media items is not supported until https://www.drupal.org/node/1927648 is solved.'); - } - - /** - * {@inheritdoc} - */ - protected function getExpectedUnauthorizedAccessCacheability() { - // @see \Drupal\media\MediaAccessControlHandler::checkAccess() - return parent::getExpectedUnauthorizedAccessCacheability() - ->addCacheTags(['media:1']); - } - +/** + * Class for backward compatibility. It is deprecated in Drupal 8.6.x. + * + * @see https://www.drupal.org/node/2971931 + */ +abstract class MediaResourceTestBase extends MediaResourceTestBaseReal { } diff -r e200cb7efeb3 -r c2387f117808 core/modules/rest/tests/src/Functional/EntityResource/Media/MediaXmlAnonTest.php --- a/core/modules/rest/tests/src/Functional/EntityResource/Media/MediaXmlAnonTest.php Thu Apr 26 11:26:54 2018 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,26 +0,0 @@ -grantPermissionsToTestedRole(['administer media types']); - } - - /** - * {@inheritdoc} - */ - protected function createEntity() { - // Create a "Camelids" media type. - $camelids = MediaType::create([ - 'name' => 'Camelids', - 'id' => 'camelids', - 'description' => 'Camelids are large, strictly herbivorous animals with slender necks and long legs.', - 'source' => 'file', - ]); - - $camelids->save(); - - return $camelids; - } - - /** - * {@inheritdoc} - */ - protected function getExpectedNormalizedEntity() { - return [ - 'dependencies' => [], - 'description' => 'Camelids are large, strictly herbivorous animals with slender necks and long legs.', - 'field_map' => [], - 'id' => 'camelids', - 'label' => NULL, - 'langcode' => 'en', - 'new_revision' => FALSE, - 'queue_thumbnail_downloads' => FALSE, - 'source' => 'file', - 'source_configuration' => [ - 'source_field' => '', - ], - 'status' => TRUE, - 'uuid' => $this->entity->uuid(), - ]; - } - - /** - * {@inheritdoc} - */ - protected function getNormalizedPostEntity() { - // @todo Update in https://www.drupal.org/node/2300677. - } - +/** + * Class for backward compatibility. It is deprecated in Drupal 8.6.x. + * + * @see https://www.drupal.org/node/2971931 + */ +abstract class MediaTypeResourceTestBase extends MediaTypeResourceTestBaseReal { } diff -r e200cb7efeb3 -r c2387f117808 core/modules/rest/tests/src/Functional/EntityResource/MediaType/MediaTypeXmlAnonTest.php --- a/core/modules/rest/tests/src/Functional/EntityResource/MediaType/MediaTypeXmlAnonTest.php Thu Apr 26 11:26:54 2018 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,26 +0,0 @@ -grantPermissionsToTestedRole(['administer menu']); - } - - /** - * {@inheritdoc} - */ - protected function createEntity() { - $menu = Menu::create([ - 'id' => 'menu', - 'label' => 'Menu', - 'description' => 'Menu', - ]); - $menu->save(); - - return $menu; - } - - /** - * {@inheritdoc} - */ - protected function getExpectedNormalizedEntity() { - return [ - 'dependencies' => [], - 'description' => 'Menu', - 'id' => 'menu', - 'label' => 'Menu', - 'langcode' => 'en', - 'locked' => FALSE, - 'status' => TRUE, - 'uuid' => $this->entity->uuid(), - ]; - } - - /** - * {@inheritdoc} - */ - protected function getNormalizedPostEntity() { - // @todo Update in https://www.drupal.org/node/2300677. - } - - /** - * {@inheritdoc} - */ - protected function getExpectedCacheContexts() { - return [ - 'user.permissions', - ]; - } - +/** + * Class for backward compatibility. It is deprecated in Drupal 8.6.x. + * + * @see https://www.drupal.org/node/2971931 + */ +abstract class MenuResourceTestBase extends MenuResourceTestBaseReal { } diff -r e200cb7efeb3 -r c2387f117808 core/modules/rest/tests/src/Functional/EntityResource/Menu/MenuXmlAnonTest.php --- a/core/modules/rest/tests/src/Functional/EntityResource/Menu/MenuXmlAnonTest.php Thu Apr 26 11:26:54 2018 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,26 +0,0 @@ -grantPermissionsToTestedRole(['administer menu']); - break; - } - } - - /** - * {@inheritdoc} - */ - protected function createEntity() { - $menu_link = MenuLinkContent::create([ - 'id' => 'llama', - 'title' => 'Llama Gabilondo', - 'description' => 'Llama Gabilondo', - 'link' => 'https://nl.wikipedia.org/wiki/Llama', - 'weight' => 0, - 'menu_name' => 'main', - ]); - $menu_link->save(); - - return $menu_link; - } - - /** - * {@inheritdoc} - */ - protected function getNormalizedPostEntity() { - return [ - 'title' => [ - [ - 'value' => 'Dramallama', - ], - ], - 'link' => [ - [ - 'uri' => 'http://www.urbandictionary.com/define.php?term=drama%20llama', - ], - ], - 'bundle' => [ - [ - 'value' => 'menu_link_content', - ], - ], - ]; - } - - /** - * {@inheritdoc} - */ - protected function getExpectedNormalizedEntity() { - return [ - 'uuid' => [ - [ - 'value' => $this->entity->uuid(), - ], - ], - 'id' => [ - [ - 'value' => 1, - ], - ], - 'title' => [ - [ - 'value' => 'Llama Gabilondo', - ], - ], - 'link' => [ - [ - 'uri' => 'https://nl.wikipedia.org/wiki/Llama', - 'title' => NULL, - 'options' => [], - ], - ], - 'weight' => [ - [ - 'value' => 0, - ], - ], - 'menu_name' => [ - [ - 'value' => 'main', - ], - ], - 'langcode' => [ - [ - 'value' => 'en', - ], - ], - 'bundle' => [ - [ - 'value' => 'menu_link_content', - ], - ], - 'description' => [ - [ - 'value' => 'Llama Gabilondo', - ], - ], - 'external' => [ - [ - 'value' => FALSE, - ], - ], - 'rediscover' => [ - [ - 'value' => FALSE, - ], - ], - 'expanded' => [ - [ - 'value' => FALSE, - ], - ], - 'enabled' => [ - [ - 'value' => TRUE, - ], - ], - 'changed' => [ - $this->formatExpectedTimestampItemValues($this->entity->getChangedTime()), - ], - 'default_langcode' => [ - [ - 'value' => TRUE, - ], - ], - 'parent' => [], - ]; - } - - /** - * {@inheritdoc} - */ - protected function getExpectedUnauthorizedAccessMessage($method) { - if ($this->config('rest.settings')->get('bc_entity_resource_permissions')) { - return parent::getExpectedUnauthorizedAccessMessage($method); - } - - switch ($method) { - case 'DELETE': - return "You are not authorized to delete this menu_link_content entity."; - default: - return parent::getExpectedUnauthorizedAccessMessage($method); - } - } - +abstract class MenuLinkContentResourceTestBase extends MenuLinkContentResourceTestBaseReal { } diff -r e200cb7efeb3 -r c2387f117808 core/modules/rest/tests/src/Functional/EntityResource/MenuLinkContent/MenuLinkContentXmlAnonTest.php --- a/core/modules/rest/tests/src/Functional/EntityResource/MenuLinkContent/MenuLinkContentXmlAnonTest.php Thu Apr 26 11:26:54 2018 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,26 +0,0 @@ -grantPermissionsToTestedRole(['access site-wide contact form']); - } - - /** - * {@inheritdoc} - */ - protected function createEntity() { - if (!ContactForm::load('camelids')) { - // Create a "Camelids" contact form. - ContactForm::create([ - 'id' => 'camelids', - 'label' => 'Llama', - 'message' => 'Let us know what you think about llamas', - 'reply' => 'Llamas are indeed awesome!', - 'recipients' => [ - 'llama@example.com', - 'contact@example.com', - ], - ])->save(); - } - - $message = Message::create([ - 'contact_form' => 'camelids', - 'subject' => 'Llama Gabilondo', - 'message' => 'Llamas are awesome!', - ]); - $message->save(); - - return $message; - } - - /** - * {@inheritdoc} - */ - protected function getNormalizedPostEntity() { - return [ - 'subject' => [ - [ - 'value' => 'Dramallama', - ], - ], - 'contact_form' => [ - [ - 'target_id' => 'camelids', - ], - ], - 'message' => [ - [ - 'value' => 'http://www.urbandictionary.com/define.php?term=drama%20llama', - ], - ], - ]; - } - - /** - * {@inheritdoc} - */ - protected function getExpectedNormalizedEntity() { - throw new \Exception('Not yet supported.'); - } - - /** - * {@inheritdoc} - */ - protected function getExpectedUnauthorizedAccessMessage($method) { - if ($this->config('rest.settings')->get('bc_entity_resource_permissions')) { - return parent::getExpectedUnauthorizedAccessMessage($method); - } - - if ($method === 'POST') { - return "The 'access site-wide contact form' permission is required."; - } - return parent::getExpectedUnauthorizedAccessMessage($method); - } - - /** - * {@inheritdoc} - */ - public function testGet() { - // Contact Message entities are not stored, so they cannot be retrieved. - $this->setExpectedException(RouteNotFoundException::class, 'Route "rest.entity.contact_message.GET" does not exist.'); - - $this->provisionEntityResource(); - Url::fromRoute('rest.entity.contact_message.GET')->toString(TRUE); - } - - /** - * {@inheritdoc} - */ - public function testPatch() { - // Contact Message entities are not stored, so they cannot be modified. - $this->setExpectedException(RouteNotFoundException::class, 'Route "rest.entity.contact_message.PATCH" does not exist.'); - - $this->provisionEntityResource(); - Url::fromRoute('rest.entity.contact_message.PATCH')->toString(TRUE); - } - - /** - * {@inheritdoc} - */ - public function testDelete() { - // Contact Message entities are not stored, so they cannot be deleted. - $this->setExpectedException(RouteNotFoundException::class, 'Route "rest.entity.contact_message.DELETE" does not exist.'); - - $this->provisionEntityResource(); - Url::fromRoute('rest.entity.contact_message.DELETE')->toString(TRUE); - } - +/** + * Class for backward compatibility. It is deprecated in Drupal 8.6.x. + * + * @see https://www.drupal.org/node/2971931 + */ +abstract class MessageResourceTestBase extends MessageResourceTestBaseReal { } diff -r e200cb7efeb3 -r c2387f117808 core/modules/rest/tests/src/Functional/EntityResource/Message/MessageXmlAnonTest.php --- a/core/modules/rest/tests/src/Functional/EntityResource/Message/MessageXmlAnonTest.php Thu Apr 26 11:26:54 2018 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,26 +0,0 @@ -grantPermissionsToTestedRole(['access content']); - break; - case 'POST': - $this->grantPermissionsToTestedRole(['access content', 'create camelids content']); - break; - case 'PATCH': - // Do not grant the 'create url aliases' permission to test the case - // when the path field is protected/not accessible, see - // \Drupal\Tests\rest\Functional\EntityResource\Term\TermResourceTestBase - // for a positive test. - $this->grantPermissionsToTestedRole(['access content', 'edit any camelids content']); - break; - case 'DELETE': - $this->grantPermissionsToTestedRole(['access content', 'delete any camelids content']); - break; - } - } - - /** - * {@inheritdoc} - */ - protected function createEntity() { - if (!NodeType::load('camelids')) { - // Create a "Camelids" node type. - NodeType::create([ - 'name' => 'Camelids', - 'type' => 'camelids', - ])->save(); - } - - // Create a "Llama" node. - $node = Node::create(['type' => 'camelids']); - $node->setTitle('Llama') - ->setOwnerId(static::$auth ? $this->account->id() : 0) - ->setPublished(TRUE) - ->setCreatedTime(123456789) - ->setChangedTime(123456789) - ->setRevisionCreationTime(123456789) - ->set('path', '/llama') - ->save(); - - return $node; - } - - /** - * {@inheritdoc} - */ - protected function getExpectedNormalizedEntity() { - $author = User::load($this->entity->getOwnerId()); - return [ - 'nid' => [ - ['value' => 1], - ], - 'uuid' => [ - ['value' => $this->entity->uuid()], - ], - 'vid' => [ - ['value' => 1], - ], - 'langcode' => [ - [ - 'value' => 'en', - ], - ], - 'type' => [ - [ - 'target_id' => 'camelids', - 'target_type' => 'node_type', - 'target_uuid' => NodeType::load('camelids')->uuid(), - ], - ], - 'title' => [ - [ - 'value' => 'Llama', - ], - ], - 'status' => [ - [ - 'value' => TRUE, - ], - ], - 'created' => [ - $this->formatExpectedTimestampItemValues(123456789), - ], - 'changed' => [ - $this->formatExpectedTimestampItemValues($this->entity->getChangedTime()), - ], - 'promote' => [ - [ - 'value' => TRUE, - ], - ], - 'sticky' => [ - [ - 'value' => FALSE, - ], - ], - 'revision_timestamp' => [ - $this->formatExpectedTimestampItemValues(123456789), - ], - 'revision_translation_affected' => [ - [ - 'value' => TRUE, - ], - ], - 'default_langcode' => [ - [ - 'value' => TRUE, - ], - ], - 'uid' => [ - [ - 'target_id' => (int) $author->id(), - 'target_type' => 'user', - 'target_uuid' => $author->uuid(), - 'url' => base_path() . 'user/' . $author->id(), - ], - ], - 'revision_uid' => [ - [ - 'target_id' => (int) $author->id(), - 'target_type' => 'user', - 'target_uuid' => $author->uuid(), - 'url' => base_path() . 'user/' . $author->id(), - ], - ], - 'revision_log' => [], - 'path' => [ - [ - 'alias' => '/llama', - 'pid' => 1, - 'langcode' => 'en', - ], - ], - ]; - } - - /** - * {@inheritdoc} - */ - protected function getNormalizedPostEntity() { - return [ - 'type' => [ - [ - 'target_id' => 'camelids', - ], - ], - 'title' => [ - [ - 'value' => 'Dramallama', - ], - ], - ]; - } - - /** - * {@inheritdoc} - */ - protected function getExpectedUnauthorizedAccessMessage($method) { - if ($this->config('rest.settings')->get('bc_entity_resource_permissions')) { - return parent::getExpectedUnauthorizedAccessMessage($method); - } - - if ($method === 'GET' || $method == 'PATCH' || $method == 'DELETE') { - return "The 'access content' permission is required."; - } - return parent::getExpectedUnauthorizedAccessMessage($method); - } - - /** - * Tests PATCHing a node's path with and without 'create url aliases'. - * - * For a positive test, see the similar test coverage for Term. - * - * @see \Drupal\Tests\rest\Functional\EntityResource\Term\TermResourceTestBase::testPatchPath() - */ - public function testPatchPath() { - $this->initAuthentication(); - $this->provisionEntityResource(); - $this->setUpAuthorization('GET'); - $this->setUpAuthorization('PATCH'); - - $url = $this->getEntityResourceUrl()->setOption('query', ['_format' => static::$format]); - - // GET node's current normalization. - $response = $this->request('GET', $url, $this->getAuthenticationRequestOptions('GET')); - $normalization = $this->serializer->decode((string) $response->getBody(), static::$format); - - // Change node's path alias. - $normalization['path'][0]['alias'] .= 's-rule-the-world'; - - // Create node PATCH request. - $request_options = []; - $request_options[RequestOptions::HEADERS]['Content-Type'] = static::$mimeType; - $request_options = array_merge_recursive($request_options, $this->getAuthenticationRequestOptions('PATCH')); - $request_options[RequestOptions::BODY] = $this->serializer->encode($normalization, static::$format); - - // PATCH request: 403 when creating URL aliases unauthorized. Before - // asserting the 403 response, assert that the stored path alias remains - // unchanged. - $response = $this->request('PATCH', $url, $request_options); - $this->assertSame('/llama', $this->entityStorage->loadUnchanged($this->entity->id())->get('path')->alias); - $this->assertResourceErrorResponse(403, "Access denied on updating field 'path'.", $response); - - // Grant permission to create URL aliases. - $this->grantPermissionsToTestedRole(['create url aliases']); - - // Repeat PATCH request: 200. - $response = $this->request('PATCH', $url, $request_options); - $this->assertResourceResponse(200, FALSE, $response); - $updated_normalization = $this->serializer->decode((string) $response->getBody(), static::$format); - $this->assertSame($normalization['path'], $updated_normalization['path']); - } - +/** + * Class for backward compatibility. It is deprecated in Drupal 8.6.x. + * + * @see https://www.drupal.org/node/2971931 + */ +abstract class NodeResourceTestBase extends NodeResourceTestBaseReal { } diff -r e200cb7efeb3 -r c2387f117808 core/modules/rest/tests/src/Functional/EntityResource/Node/NodeXmlAnonTest.php --- a/core/modules/rest/tests/src/Functional/EntityResource/Node/NodeXmlAnonTest.php Thu Apr 26 11:26:54 2018 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,34 +0,0 @@ -markTestSkipped(); - } - -} diff -r e200cb7efeb3 -r c2387f117808 core/modules/rest/tests/src/Functional/EntityResource/Node/NodeXmlBasicAuthTest.php --- a/core/modules/rest/tests/src/Functional/EntityResource/Node/NodeXmlBasicAuthTest.php Thu Apr 26 11:26:54 2018 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,44 +0,0 @@ -markTestSkipped(); - } - -} diff -r e200cb7efeb3 -r c2387f117808 core/modules/rest/tests/src/Functional/EntityResource/Node/NodeXmlCookieTest.php --- a/core/modules/rest/tests/src/Functional/EntityResource/Node/NodeXmlCookieTest.php Thu Apr 26 11:26:54 2018 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,39 +0,0 @@ -markTestSkipped(); - } - -} diff -r e200cb7efeb3 -r c2387f117808 core/modules/rest/tests/src/Functional/EntityResource/NodeType/NodeTypeJsonAnonTest.php --- a/core/modules/rest/tests/src/Functional/EntityResource/NodeType/NodeTypeJsonAnonTest.php Thu Apr 26 11:26:54 2018 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,24 +0,0 @@ -grantPermissionsToTestedRole(['administer content types', 'access content']); - } - - /** - * {@inheritdoc} - */ - protected function createEntity() { - // Create a "Camelids" node type. - $camelids = NodeType::create([ - 'name' => 'Camelids', - 'type' => 'camelids', - 'description' => 'Camelids are large, strictly herbivorous animals with slender necks and long legs.', - ]); - - $camelids->save(); - - return $camelids; - } - - /** - * {@inheritdoc} - */ - protected function getExpectedNormalizedEntity() { - return [ - 'dependencies' => [], - 'description' => 'Camelids are large, strictly herbivorous animals with slender necks and long legs.', - 'display_submitted' => TRUE, - 'help' => NULL, - 'langcode' => 'en', - 'name' => 'Camelids', - 'new_revision' => TRUE, - 'preview_mode' => 1, - 'status' => TRUE, - 'type' => 'camelids', - 'uuid' => $this->entity->uuid(), - ]; - } - - /** - * {@inheritdoc} - */ - protected function getNormalizedPostEntity() { - // @todo Update in https://www.drupal.org/node/2300677. - } - - /** - * {@inheritdoc} - */ - protected function getExpectedUnauthorizedAccessMessage($method) { - if ($this->config('rest.settings')->get('bc_entity_resource_permissions')) { - return parent::getExpectedUnauthorizedAccessMessage($method); - } - - return "The 'access content' permission is required."; - } - +abstract class NodeTypeResourceTestBase extends NodeTypeResourceTestBaseReal { } diff -r e200cb7efeb3 -r c2387f117808 core/modules/rest/tests/src/Functional/EntityResource/NodeType/NodeTypeXmlAnonTest.php --- a/core/modules/rest/tests/src/Functional/EntityResource/NodeType/NodeTypeXmlAnonTest.php Thu Apr 26 11:26:54 2018 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,26 +0,0 @@ -grantPermissionsToTestedRole(['administer site configuration']); - } - - /** - * {@inheritdoc} - */ - protected function createEntity() { - // Create a "Camelids" node type. - $camelids = NodeType::create([ - 'name' => 'Camelids', - 'type' => 'camelids', - ]); - - $camelids->save(); - - // Create the RDF mapping. - $llama = RdfMapping::create([ - 'targetEntityType' => 'node', - 'bundle' => 'camelids', - ]); - $llama->setBundleMapping([ - 'types' => ['sioc:Item', 'foaf:Document'], - ]) - ->setFieldMapping('title', [ - 'properties' => ['dc:title'], - ]) - ->setFieldMapping('created', [ - 'properties' => ['dc:date', 'dc:created'], - 'datatype' => 'xsd:dateTime', - 'datatype_callback' => ['callable' => 'Drupal\rdf\CommonDataConverter::dateIso8601Value'], - ]) - ->save(); - - return $llama; - } - - /** - * {@inheritdoc} - */ - protected function getExpectedNormalizedEntity() { - return [ - 'bundle' => 'camelids', - 'dependencies' => [ - 'config' => [ - 'node.type.camelids', - ], - 'module' => [ - 'node', - ], - ], - 'fieldMappings' => [ - 'title' => [ - 'properties' => [ - 'dc:title', - ], - ], - 'created' => [ - 'properties' => [ - 'dc:date', - 'dc:created', - ], - 'datatype' => 'xsd:dateTime', - 'datatype_callback' => [ - 'callable' => 'Drupal\rdf\CommonDataConverter::dateIso8601Value', - ], - ], - ], - 'id' => 'node.camelids', - 'langcode' => 'en', - 'status' => TRUE, - 'targetEntityType' => 'node', - 'types' => [ - 'sioc:Item', - 'foaf:Document', - ], - 'uuid' => $this->entity->uuid(), - ]; - } - - /** - * {@inheritdoc} - */ - protected function getNormalizedPostEntity() { - // @todo Update in https://www.drupal.org/node/2300677. - } - - /** - * {@inheritdoc} - */ - protected function getExpectedCacheContexts() { - return [ - 'user.permissions', - ]; - } - +/** + * Class for backward compatibility. It is deprecated in Drupal 8.6.x. + * + * @see https://www.drupal.org/node/2971931 + */ +abstract class RdfMappingResourceTestBase extends RdfMappingResourceTestBaseReal { } diff -r e200cb7efeb3 -r c2387f117808 core/modules/rest/tests/src/Functional/EntityResource/RdfMapping/RdfMappingXmlAnonTest.php --- a/core/modules/rest/tests/src/Functional/EntityResource/RdfMapping/RdfMappingXmlAnonTest.php Thu Apr 26 11:26:54 2018 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,26 +0,0 @@ -grantPermissionsToTestedRole(['administer responsive images']); - } - - /** - * {@inheritdoc} - */ - protected function createEntity() { - // Create a "Camelids" responsive image style. - $camelids = ResponsiveImageStyle::create([ - 'id' => 'camelids', - 'label' => 'Camelids', - ]); - $camelids->setBreakpointGroup('test_group'); - $camelids->setFallbackImageStyle('fallback'); - $camelids->addImageStyleMapping('test_breakpoint', '1x', [ - 'image_mapping_type' => 'image_style', - 'image_mapping' => 'small', - ]); - $camelids->addImageStyleMapping('test_breakpoint', '2x', [ - 'image_mapping_type' => 'sizes', - 'image_mapping' => [ - 'sizes' => '(min-width:700px) 700px, 100vw', - 'sizes_image_styles' => [ - 'medium' => 'medium', - 'large' => 'large', - ], - ], - ]); - $camelids->save(); - - return $camelids; - } - - /** - * {@inheritdoc} - */ - protected function getExpectedNormalizedEntity() { - return [ - 'breakpoint_group' => 'test_group', - 'dependencies' => [ - 'config' => [ - 'image.style.large', - 'image.style.medium', - ], - ], - 'fallback_image_style' => 'fallback', - 'id' => 'camelids', - 'image_style_mappings' => [ - 0 => [ - 'breakpoint_id' => 'test_breakpoint', - 'image_mapping' => 'small', - 'image_mapping_type' => 'image_style', - 'multiplier' => '1x', - ], - 1 => [ - 'breakpoint_id' => 'test_breakpoint', - 'image_mapping' => [ - 'sizes' => '(min-width:700px) 700px, 100vw', - 'sizes_image_styles' => [ - 'large' => 'large', - 'medium' => 'medium', - ], - ], - 'image_mapping_type' => 'sizes', - 'multiplier' => '2x', - ], - ], - 'label' => 'Camelids', - 'langcode' => 'en', - 'status' => TRUE, - 'uuid' => $this->entity->uuid(), - ]; - } - - /** - * {@inheritdoc} - */ - protected function getNormalizedPostEntity() { - // @todo Update in https://www.drupal.org/node/2300677. - } - - /** - * {@inheritdoc} - */ - protected function getExpectedUnauthorizedAccessMessage($method) { - if ($this->config('rest.settings')->get('bc_entity_resource_permissions')) { - return parent::getExpectedUnauthorizedAccessMessage($method); - } - - return "The 'administer responsive images' permission is required."; - } - +abstract class ResponsiveImageStyleResourceTestBase extends ResponsiveImageStyleResourceTestBaseReal { } diff -r e200cb7efeb3 -r c2387f117808 core/modules/rest/tests/src/Functional/EntityResource/ResponsiveImageStyle/ResponsiveImageStyleXmlAnonTest.php --- a/core/modules/rest/tests/src/Functional/EntityResource/ResponsiveImageStyle/ResponsiveImageStyleXmlAnonTest.php Thu Apr 26 11:26:54 2018 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,26 +0,0 @@ -grantPermissionsToTestedRole(['administer rest resources']); - } - - /** - * {@inheritdoc} - */ - protected function createEntity() { - $rest_resource_config = RestResourceConfig::create([ - 'id' => 'llama', - 'plugin_id' => 'dblog', - 'granularity' => 'method', - 'configuration' => [ - 'GET' => [ - 'supported_formats' => [ - 'json', - ], - 'supported_auth' => [ - 'cookie', - ], - ], - ], - ]); - $rest_resource_config->save(); - - return $rest_resource_config; - } - - /** - * {@inheritdoc} - */ - protected function getExpectedNormalizedEntity() { - return [ - 'uuid' => $this->entity->uuid(), - 'langcode' => 'en', - 'status' => TRUE, - 'dependencies' => [ - 'module' => [ - 'dblog', - 'serialization', - 'user', - ], - ], - 'id' => 'llama', - 'plugin_id' => 'dblog', - 'granularity' => 'method', - 'configuration' => [ - 'GET' => [ - 'supported_formats' => [ - 'json', - ], - 'supported_auth' => [ - 'cookie', - ], - ], - ], - ]; - } - - /** - * {@inheritdoc} - */ - protected function getNormalizedPostEntity() { - // @todo Update in https://www.drupal.org/node/2300677. - } - - /** - * {@inheritdoc} - */ - protected function getExpectedCacheContexts() { - return [ - 'user.permissions', - ]; - } - +/** + * Class for backward compatibility. It is deprecated in Drupal 8.6.x. + * + * @see https://www.drupal.org/node/2971931 + */ +abstract class RestResourceConfigResourceTestBase extends RestResourceConfigResourceTestBaseReal { } diff -r e200cb7efeb3 -r c2387f117808 core/modules/rest/tests/src/Functional/EntityResource/RestResourceConfig/RestResourceConfigXmlAnonTest.php --- a/core/modules/rest/tests/src/Functional/EntityResource/RestResourceConfig/RestResourceConfigXmlAnonTest.php Thu Apr 26 11:26:54 2018 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,26 +0,0 @@ -grantPermissionsToTestedRole(['administer permissions']); - } - - /** - * {@inheritdoc} - */ - protected function createEntity() { - $role = Role::create([ - 'id' => 'llama', - 'name' => $this->randomString(), - ]); - $role->save(); - - return $role; - } - - /** - * {@inheritdoc} - */ - protected function getExpectedNormalizedEntity() { - return [ - 'uuid' => $this->entity->uuid(), - 'weight' => 2, - 'langcode' => 'en', - 'status' => TRUE, - 'dependencies' => [], - 'id' => 'llama', - 'label' => NULL, - 'is_admin' => NULL, - 'permissions' => [], - ]; - } - - /** - * {@inheritdoc} - */ - protected function getNormalizedPostEntity() { - // @todo Update in https://www.drupal.org/node/2300677. - } - +/** + * Class for backward compatibility. It is deprecated in Drupal 8.6.x. + * + * @see https://www.drupal.org/node/2971931 + */ +abstract class RoleResourceTestBase extends RoleResourceTestBaseReal { } diff -r e200cb7efeb3 -r c2387f117808 core/modules/rest/tests/src/Functional/EntityResource/Role/RoleXmlAnonTest.php --- a/core/modules/rest/tests/src/Functional/EntityResource/Role/RoleXmlAnonTest.php Thu Apr 26 11:26:54 2018 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,26 +0,0 @@ -grantPermissionsToTestedRole(['access content']); - break; - - case 'POST': - case 'PATCH': - case 'DELETE': - $this->grantPermissionsToTestedRole(['administer search']); - break; - } - } - - /** - * {@inheritdoc} - */ - protected function createEntity() { - $search_page = SearchPage::create([ - 'id' => 'hinode_search', - 'plugin' => 'node_search', - 'label' => 'Search of magnetic activity of the Sun', - 'path' => 'sun', - ]); - $search_page->save(); - return $search_page; - } - - /** - * {@inheritdoc} - */ - protected function getExpectedNormalizedEntity() { - return [ - 'configuration' => [ - 'rankings' => [], - ], - 'dependencies' => [ - 'module' => ['node'], - ], - 'id' => 'hinode_search', - 'label' => 'Search of magnetic activity of the Sun', - 'langcode' => 'en', - 'path' => 'sun', - 'plugin' => 'node_search', - 'status' => TRUE, - 'uuid' => $this->entity->uuid(), - 'weight' => 0, - ]; - } - - /** - * {@inheritdoc} - */ - protected function getNormalizedPostEntity() { - // @todo Update in https://www.drupal.org/node/2300677. - } - - /** - * {@inheritdoc} - */ - protected function getExpectedUnauthorizedAccessMessage($method) { - if ($this->config('rest.settings')->get('bc_entity_resource_permissions')) { - return parent::getExpectedUnauthorizedAccessMessage($method); - } - - switch ($method) { - case 'GET': - return "The 'access content' permission is required."; - - default: - return parent::getExpectedUnauthorizedAccessMessage($method); - } - } - - /** - * {@inheritdoc} - */ - protected function getExpectedUnauthorizedAccessCacheability() { - // @see \Drupal\search\SearchPageAccessControlHandler::checkAccess() - return parent::getExpectedUnauthorizedAccessCacheability() - ->addCacheTags(['config:search.page.hinode_search']); - } - +/** + * Class for backward compatibility. It is deprecated in Drupal 8.6.x. + * + * @see https://www.drupal.org/node/2971931 + */ +abstract class SearchPageResourceTestBase extends SearchPageResourceTestBaseReal { } diff -r e200cb7efeb3 -r c2387f117808 core/modules/rest/tests/src/Functional/EntityResource/SearchPage/SearchPageXmlAnonTest.php --- a/core/modules/rest/tests/src/Functional/EntityResource/SearchPage/SearchPageXmlAnonTest.php Thu Apr 26 11:26:54 2018 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,26 +0,0 @@ -grantPermissionsToTestedRole(['access shortcuts', 'customize shortcut links']); - break; - } - } - - /** - * {@inheritdoc} - */ - protected function createEntity() { - // Create shortcut. - $shortcut = Shortcut::create([ - 'shortcut_set' => 'default', - 'title' => t('Comments'), - 'weight' => -20, - 'link' => [ - 'uri' => 'internal:/admin/content/comment', - ], - ]); - $shortcut->save(); - - return $shortcut; - } - - /** - * {@inheritdoc} - */ - protected function getExpectedNormalizedEntity() { - return [ - 'uuid' => [ - [ - 'value' => $this->entity->uuid(), - ], - ], - 'id' => [ - [ - 'value' => (int) $this->entity->id(), - ], - ], - 'title' => [ - [ - 'value' => 'Comments', - ], - ], - 'shortcut_set' => [ - [ - 'target_id' => 'default', - 'target_type' => 'shortcut_set', - 'target_uuid' => ShortcutSet::load('default')->uuid(), - ], - ], - 'link' => [ - [ - 'uri' => 'internal:/admin/content/comment', - 'title' => NULL, - 'options' => [], - ], - ], - 'weight' => [ - [ - 'value' => -20, - ], - ], - 'langcode' => [ - [ - 'value' => 'en', - ], - ], - 'default_langcode' => [ - [ - 'value' => TRUE, - ], - ], - ]; - } - - /** - * {@inheritdoc} - */ - protected function getNormalizedPostEntity() { - return [ - 'title' => [ - [ - 'value' => 'Comments', - ], - ], - 'link' => [ - [ - 'uri' => 'internal:/', - ], - ], - 'shortcut_set' => [ - [ - 'target_id' => 'default', - ], - ], - ]; - } - - /** - * {@inheritdoc} - */ - protected function getExpectedUnauthorizedAccessMessage($method) { - if ($this->config('rest.settings')->get('bc_entity_resource_permissions')) { - return parent::getExpectedUnauthorizedAccessMessage($method); - } - - switch ($method) { - case 'GET': - case 'POST': - case 'PATCH': - case 'DELETE': - return "The shortcut set must be the currently displayed set for the user and the user must have 'access shortcuts' AND 'customize shortcut links' permissions."; - - default: - return parent::getExpectedUnauthorizedAccessMessage($method); - } - } - +abstract class ShortcutResourceTestBase extends ShortcutResourceTestBaseReal { } diff -r e200cb7efeb3 -r c2387f117808 core/modules/rest/tests/src/Functional/EntityResource/Shortcut/ShortcutXmlAnonTest.php --- a/core/modules/rest/tests/src/Functional/EntityResource/Shortcut/ShortcutXmlAnonTest.php Thu Apr 26 11:26:54 2018 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,26 +0,0 @@ -grantPermissionsToTestedRole(['access shortcuts']); - break; - - case 'POST': - case 'PATCH': - $this->grantPermissionsToTestedRole(['access shortcuts', 'customize shortcut links']); - break; - - case 'DELETE': - $this->grantPermissionsToTestedRole(['administer shortcuts']); - break; - } - } - - /** - * {@inheritdoc} - */ - protected function createEntity() { - $set = ShortcutSet::create([ - 'id' => 'llama_set', - 'label' => 'Llama Set', - ]); - $set->save(); - return $set; - } - - /** - * {@inheritdoc} - */ - protected function getExpectedNormalizedEntity() { - return [ - 'id' => 'llama_set', - 'uuid' => $this->entity->uuid(), - 'label' => 'Llama Set', - 'status' => TRUE, - 'langcode' => 'en', - 'dependencies' => [], - ]; - } - - /** - * {@inheritdoc} - */ - protected function getNormalizedPostEntity() { - // @todo Update in https://www.drupal.org/node/2300677. - } - +abstract class ShortcutSetResourceTestBase extends ShortcutSetResourceTestBaseReal { } diff -r e200cb7efeb3 -r c2387f117808 core/modules/rest/tests/src/Functional/EntityResource/ShortcutSet/ShortcutSetXmlAnonTest.php --- a/core/modules/rest/tests/src/Functional/EntityResource/ShortcutSet/ShortcutSetXmlAnonTest.php Thu Apr 26 11:26:54 2018 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,26 +0,0 @@ -grantPermissionsToTestedRole(['access content']); - break; - - case 'POST': - $this->grantPermissionsToTestedRole(['create terms in camelids']); - break; - - case 'PATCH': - // Grant the 'create url aliases' permission to test the case when - // the path field is accessible, see - // \Drupal\Tests\rest\Functional\EntityResource\Node\NodeResourceTestBase - // for a negative test. - $this->grantPermissionsToTestedRole(['edit terms in camelids', 'create url aliases']); - break; - - case 'DELETE': - $this->grantPermissionsToTestedRole(['delete terms in camelids']); - break; - - } - } - - /** - * {@inheritdoc} - */ - protected function createEntity() { - $vocabulary = Vocabulary::load('camelids'); - if (!$vocabulary) { - // Create a "Camelids" vocabulary. - $vocabulary = Vocabulary::create([ - 'name' => 'Camelids', - 'vid' => 'camelids', - ]); - $vocabulary->save(); - } - - // Create a "Llama" taxonomy term. - $term = Term::create(['vid' => $vocabulary->id()]) - ->setName('Llama') - ->setDescription("It is a little known fact that llamas cannot count higher than seven.") - ->setChangedTime(123456789) - ->set('path', '/llama'); - $term->save(); - - return $term; - } - - /** - * {@inheritdoc} - */ - protected function getExpectedNormalizedEntity() { - return [ - 'tid' => [ - ['value' => 1], - ], - 'uuid' => [ - ['value' => $this->entity->uuid()], - ], - 'vid' => [ - [ - 'target_id' => 'camelids', - 'target_type' => 'taxonomy_vocabulary', - 'target_uuid' => Vocabulary::load('camelids')->uuid(), - ], - ], - 'name' => [ - ['value' => 'Llama'], - ], - 'description' => [ - [ - 'value' => 'It is a little known fact that llamas cannot count higher than seven.', - 'format' => NULL, - 'processed' => "

    It is a little known fact that llamas cannot count higher than seven.

    \n", - ], - ], - 'parent' => [], - 'weight' => [ - ['value' => 0], - ], - 'langcode' => [ - [ - 'value' => 'en', - ], - ], - 'changed' => [ - $this->formatExpectedTimestampItemValues($this->entity->getChangedTime()), - ], - 'default_langcode' => [ - [ - 'value' => TRUE, - ], - ], - 'path' => [ - [ - 'alias' => '/llama', - 'pid' => 1, - 'langcode' => 'en', - ], - ], - ]; - } - - /** - * {@inheritdoc} - */ - protected function getNormalizedPostEntity() { - return [ - 'vid' => [ - [ - 'target_id' => 'camelids', - ], - ], - 'name' => [ - [ - 'value' => 'Dramallama', - ], - ], - 'description' => [ - [ - 'value' => 'Dramallamas are the coolest camelids.', - 'format' => NULL, - ], - ], - ]; - } - - /** - * {@inheritdoc} - */ - protected function getExpectedUnauthorizedAccessMessage($method) { - if ($this->config('rest.settings')->get('bc_entity_resource_permissions')) { - return parent::getExpectedUnauthorizedAccessMessage($method); - } - - switch ($method) { - case 'GET': - return "The 'access content' permission is required."; - case 'POST': - return "The following permissions are required: 'create terms in camelids' OR 'administer taxonomy'."; - case 'PATCH': - return "The following permissions are required: 'edit terms in camelids' OR 'administer taxonomy'."; - case 'DELETE': - return "The following permissions are required: 'delete terms in camelids' OR 'administer taxonomy'."; - default: - return parent::getExpectedUnauthorizedAccessMessage($method); - } - } - - /** - * Tests PATCHing a term's path. - * - * For a negative test, see the similar test coverage for Node. - * - * @see \Drupal\Tests\rest\Functional\EntityResource\Node\NodeResourceTestBase::testPatchPath() - */ - public function testPatchPath() { - $this->initAuthentication(); - $this->provisionEntityResource(); - $this->setUpAuthorization('GET'); - $this->setUpAuthorization('PATCH'); - - $url = $this->getEntityResourceUrl()->setOption('query', ['_format' => static::$format]); - - // GET term's current normalization. - $response = $this->request('GET', $url, $this->getAuthenticationRequestOptions('GET')); - $normalization = $this->serializer->decode((string) $response->getBody(), static::$format); - - // Change term's path alias. - $normalization['path'][0]['alias'] .= 's-rule-the-world'; - - // Create term PATCH request. - $request_options = []; - $request_options[RequestOptions::HEADERS]['Content-Type'] = static::$mimeType; - $request_options = array_merge_recursive($request_options, $this->getAuthenticationRequestOptions('PATCH')); - $request_options[RequestOptions::BODY] = $this->serializer->encode($normalization, static::$format); - - // PATCH request: 200. - $response = $this->request('PATCH', $url, $request_options); - $this->assertResourceResponse(200, FALSE, $response); - $updated_normalization = $this->serializer->decode((string) $response->getBody(), static::$format); - $this->assertSame($normalization['path'], $updated_normalization['path']); - } - - /** - * {@inheritdoc} - */ - protected function getExpectedCacheTags() { - return Cache::mergeTags(parent::getExpectedCacheTags(), ['config:filter.format.plain_text', 'config:filter.settings']); - } - - /** - * {@inheritdoc} - */ - protected function getExpectedCacheContexts() { - return Cache::mergeContexts(['url.site'], $this->container->getParameter('renderer.config')['required_cache_contexts']); - } - +/** + * Class for backward compatibility. It is deprecated in Drupal 8.6.x. + * + * @see https://www.drupal.org/node/2971931 + */ +abstract class TermResourceTestBase extends TermResourceTestBaseReal { } diff -r e200cb7efeb3 -r c2387f117808 core/modules/rest/tests/src/Functional/EntityResource/Term/TermXmlAnonTest.php --- a/core/modules/rest/tests/src/Functional/EntityResource/Term/TermXmlAnonTest.php Thu Apr 26 11:26:54 2018 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,34 +0,0 @@ -markTestSkipped(); - } - -} diff -r e200cb7efeb3 -r c2387f117808 core/modules/rest/tests/src/Functional/EntityResource/Term/TermXmlBasicAuthTest.php --- a/core/modules/rest/tests/src/Functional/EntityResource/Term/TermXmlBasicAuthTest.php Thu Apr 26 11:26:54 2018 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,44 +0,0 @@ -markTestSkipped(); - } - -} diff -r e200cb7efeb3 -r c2387f117808 core/modules/rest/tests/src/Functional/EntityResource/Term/TermXmlCookieTest.php --- a/core/modules/rest/tests/src/Functional/EntityResource/Term/TermXmlCookieTest.php Thu Apr 26 11:26:54 2018 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,39 +0,0 @@ -markTestSkipped(); - } - -} diff -r e200cb7efeb3 -r c2387f117808 core/modules/rest/tests/src/Functional/EntityResource/Tour/TourJsonAnonTest.php --- a/core/modules/rest/tests/src/Functional/EntityResource/Tour/TourJsonAnonTest.php Thu Apr 26 11:26:54 2018 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,24 +0,0 @@ -grantPermissionsToTestedRole(['access tour']); - } - - /** - * {@inheritdoc} - */ - protected function createEntity() { - $tour = Tour::create([ - 'id' => 'tour-llama', - 'label' => 'Llama tour', - 'langcode' => 'en', - 'module' => 'tour', - 'routes' => [ - [ - 'route_name' => '', - ], - ], - 'tips' => [ - 'tour-llama-1' => [ - 'id' => 'tour-llama-1', - 'plugin' => 'text', - 'label' => 'Llama', - 'body' => 'Who handle the awesomeness of llamas?', - 'weight' => 100, - 'attributes' => [ - 'data-id' => 'tour-llama-1', - ], - ], - ], - ]); - $tour->save(); - - return $tour; - } - - /** - * {@inheritdoc} - */ - protected function getExpectedNormalizedEntity() { - return [ - 'dependencies' => [], - 'id' => 'tour-llama', - 'label' => 'Llama tour', - 'langcode' => 'en', - 'module' => 'tour', - 'routes' => [ - [ - 'route_name' => '', - ], - ], - 'status' => TRUE, - 'tips' => [ - 'tour-llama-1' => [ - 'id' => 'tour-llama-1', - 'plugin' => 'text', - 'label' => 'Llama', - 'body' => 'Who handle the awesomeness of llamas?', - 'weight' => 100, - 'attributes' => [ - 'data-id' => 'tour-llama-1', - ], - ], - ], - 'uuid' => $this->entity->uuid(), - ]; - } - - /** - * {@inheritdoc} - */ - protected function getNormalizedPostEntity() { - // @todo Update in https://www.drupal.org/node/2300677. - } - - /** - * {@inheritdoc} - */ - protected function getExpectedCacheContexts() { - return [ - 'user.permissions', - ]; - } - - /** - * {@inheritdoc} - */ - protected function getExpectedUnauthorizedAccessMessage($method) { - if ($this->config('rest.settings')->get('bc_entity_resource_permissions')) { - return parent::getExpectedUnauthorizedAccessMessage($method); - } - - return "The following permissions are required: 'access tour' OR 'administer site configuration'."; - } - +/** + * Class for backward compatibility. It is deprecated in Drupal 8.6.x. + * + * @see https://www.drupal.org/node/2971931 + */ +abstract class TourResourceTestBase extends TourResourceTestBaseReal { } diff -r e200cb7efeb3 -r c2387f117808 core/modules/rest/tests/src/Functional/EntityResource/Tour/TourXmlAnonTest.php --- a/core/modules/rest/tests/src/Functional/EntityResource/Tour/TourXmlAnonTest.php Thu Apr 26 11:26:54 2018 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,26 +0,0 @@ -grantPermissionsToTestedRole(['access user profiles']); - break; - case 'POST': - case 'PATCH': - case 'DELETE': - $this->grantPermissionsToTestedRole(['administer users']); - break; - } - } - - /** - * {@inheritdoc} - */ - protected function createEntity() { - // Create a "Llama" user. - $user = User::create(['created' => 123456789]); - $user->setUsername('Llama') - ->setChangedTime(123456789) - ->activate() - ->save(); - - return $user; - } - - /** - * {@inheritdoc} - */ - protected function createAnotherEntity() { - /** @var \Drupal\user\UserInterface $user */ - $user = $this->entity->createDuplicate(); - $user->setUsername($user->label() . '_dupe'); - $user->save(); - return $user; - } - - /** - * {@inheritdoc} - */ - protected function getExpectedNormalizedEntity() { - return [ - 'uid' => [ - ['value' => 3], - ], - 'uuid' => [ - ['value' => $this->entity->uuid()], - ], - 'langcode' => [ - [ - 'value' => 'en', - ], - ], - 'name' => [ - [ - 'value' => 'Llama', - ], - ], - 'created' => [ - $this->formatExpectedTimestampItemValues(123456789), - ], - 'changed' => [ - $this->formatExpectedTimestampItemValues($this->entity->getChangedTime()), - ], - 'default_langcode' => [ - [ - 'value' => TRUE, - ], - ], - ]; - } - - /** - * {@inheritdoc} - */ - protected function getNormalizedPostEntity() { - return [ - 'name' => [ - [ - 'value' => 'Dramallama', - ], - ], - ]; - } - - /** - * Tests PATCHing security-sensitive base fields of the logged in account. - */ - public function testPatchDxForSecuritySensitiveBaseFields() { - // The anonymous user is never allowed to modify itself. - if (!static::$auth) { - $this->markTestSkipped(); - } - - $this->initAuthentication(); - $this->provisionEntityResource(); - - /** @var \Drupal\user\UserInterface $user */ - $user = static::$auth ? $this->account : User::load(0); - // @todo Remove the array_diff_key() call in https://www.drupal.org/node/2821077. - $original_normalization = array_diff_key($this->serializer->normalize($user, static::$format), ['created' => TRUE, 'changed' => TRUE, 'name' => TRUE]); - - // Since this test must be performed by the user that is being modified, - // we cannot use $this->getUrl(). - $url = $user->toUrl()->setOption('query', ['_format' => static::$format]); - $request_options = [ - RequestOptions::HEADERS => ['Content-Type' => static::$mimeType], - ]; - $request_options = array_merge_recursive($request_options, $this->getAuthenticationRequestOptions('PATCH')); - - // Test case 1: changing email. - $normalization = $original_normalization; - $normalization['mail'] = [['value' => 'new-email@example.com']]; - $request_options[RequestOptions::BODY] = $this->serializer->encode($normalization, static::$format); - - // DX: 422 when changing email without providing the password. - $response = $this->request('PATCH', $url, $request_options); - $this->assertResourceErrorResponse(422, "Unprocessable Entity: validation failed.\nmail: Your current password is missing or incorrect; it's required to change the Email.\n", $response, FALSE, FALSE, FALSE, FALSE); - - $normalization['pass'] = [['existing' => 'wrong']]; - $request_options[RequestOptions::BODY] = $this->serializer->encode($normalization, static::$format); - - // DX: 422 when changing email while providing a wrong password. - $response = $this->request('PATCH', $url, $request_options); - $this->assertResourceErrorResponse(422, "Unprocessable Entity: validation failed.\nmail: Your current password is missing or incorrect; it's required to change the Email.\n", $response, FALSE, FALSE, FALSE, FALSE); - - $normalization['pass'] = [['existing' => $this->account->passRaw]]; - $request_options[RequestOptions::BODY] = $this->serializer->encode($normalization, static::$format); - - // 200 for well-formed request. - $response = $this->request('PATCH', $url, $request_options); - $this->assertResourceResponse(200, FALSE, $response); - - // Test case 2: changing password. - $normalization = $original_normalization; - $new_password = $this->randomString(); - $normalization['pass'] = [['value' => $new_password]]; - $request_options[RequestOptions::BODY] = $this->serializer->encode($normalization, static::$format); - - // DX: 422 when changing password without providing the current password. - $response = $this->request('PATCH', $url, $request_options); - $this->assertResourceErrorResponse(422, "Unprocessable Entity: validation failed.\npass: Your current password is missing or incorrect; it's required to change the Password.\n", $response, FALSE, FALSE, FALSE, FALSE); - - $normalization['pass'][0]['existing'] = $this->account->pass_raw; - $request_options[RequestOptions::BODY] = $this->serializer->encode($normalization, static::$format); - - // 200 for well-formed request. - $response = $this->request('PATCH', $url, $request_options); - $this->assertResourceResponse(200, FALSE, $response); - - // Verify that we can log in with the new password. - $this->assertRpcLogin($user->getAccountName(), $new_password); - - // Update password in $this->account, prepare for future requests. - $this->account->passRaw = $new_password; - $this->initAuthentication(); - $request_options = [ - RequestOptions::HEADERS => ['Content-Type' => static::$mimeType], - ]; - $request_options = array_merge_recursive($request_options, $this->getAuthenticationRequestOptions('PATCH')); - - // Test case 3: changing name. - $normalization = $original_normalization; - $normalization['name'] = [['value' => 'Cooler Llama']]; - $request_options[RequestOptions::BODY] = $this->serializer->encode($normalization, static::$format); - - // DX: 403 when modifying username without required permission. - $response = $this->request('PATCH', $url, $request_options); - $this->assertResourceErrorResponse(403, "Access denied on updating field 'name'.", $response); - - $this->grantPermissionsToTestedRole(['change own username']); - - // 200 for well-formed request. - $response = $this->request('PATCH', $url, $request_options); - $this->assertResourceResponse(200, FALSE, $response); - - // Verify that we can log in with the new username. - $this->assertRpcLogin('Cooler Llama', $new_password); - } - - /** - * Verifies that logging in with the given username and password works. - * - * @param string $username - * The username to log in with. - * @param string $password - * The password to log in with. - */ - protected function assertRpcLogin($username, $password) { - $request_body = [ - 'name' => $username, - 'pass' => $password, - ]; - $request_options = [ - RequestOptions::HEADERS => [], - RequestOptions::BODY => $this->serializer->encode($request_body, 'json'), - ]; - $response = $this->request('POST', Url::fromRoute('user.login.http')->setRouteParameter('_format', 'json'), $request_options); - $this->assertSame(200, $response->getStatusCode()); - } - - /** - * Tests PATCHing security-sensitive base fields to change other users. - */ - public function testPatchSecurityOtherUser() { - // The anonymous user is never allowed to modify other users. - if (!static::$auth) { - $this->markTestSkipped(); - } - - $this->initAuthentication(); - $this->provisionEntityResource(); - - /** @var \Drupal\user\UserInterface $user */ - $user = $this->account; - $original_normalization = array_diff_key($this->serializer->normalize($user, static::$format), ['changed' => TRUE]); - - // Since this test must be performed by the user that is being modified, - // we cannot use $this->getUrl(). - $url = $user->toUrl()->setOption('query', ['_format' => static::$format]); - $request_options = [ - RequestOptions::HEADERS => ['Content-Type' => static::$mimeType], - ]; - $request_options = array_merge_recursive($request_options, $this->getAuthenticationRequestOptions('PATCH')); - - $normalization = $original_normalization; - $normalization['mail'] = [['value' => 'new-email@example.com']]; - $request_options[RequestOptions::BODY] = $this->serializer->encode($normalization, static::$format); - - // Try changing user 1's email. - $user1 = [ - 'mail' => [['value' => 'another_email_address@example.com']], - 'uid' => [['value' => 1]], - 'name' => [['value' => 'another_user_name']], - 'pass' => [['existing' => $this->account->passRaw]], - 'uuid' => [['value' => '2e9403a4-d8af-4096-a116-624710140be0']], - ] + $original_normalization; - $request_options[RequestOptions::BODY] = $this->serializer->encode($user1, static::$format); - $response = $this->request('PATCH', $url, $request_options); - // Ensure the email address has not changed. - $this->assertEquals('admin@example.com', $this->entityStorage->loadUnchanged(1)->getEmail()); - $this->assertResourceErrorResponse(403, "Access denied on updating field 'uid'.", $response); - } - - /** - * {@inheritdoc} - */ - protected function getExpectedUnauthorizedAccessMessage($method) { - if ($this->config('rest.settings')->get('bc_entity_resource_permissions')) { - return parent::getExpectedUnauthorizedAccessMessage($method); - } - - switch ($method) { - case 'GET': - return "The 'access user profiles' permission is required and the user must be active."; - case 'PATCH': - return "You are not authorized to update this user entity."; - case 'DELETE': - return 'You are not authorized to delete this user entity.'; - default: - return parent::getExpectedUnauthorizedAccessMessage($method); - } - } - - /** - * {@inheritdoc} - */ - protected function getExpectedUnauthorizedAccessCacheability() { - // @see \Drupal\user\UserAccessControlHandler::checkAccess() - return parent::getExpectedUnauthorizedAccessCacheability() - ->addCacheTags(['user:3']); - } - +/** + * Class for backward compatibility. It is deprecated in Drupal 8.6.x. + * + * @see https://www.drupal.org/node/2971931 + */ +abstract class UserResourceTestBase extends UserResourceTestBaseReal { } diff -r e200cb7efeb3 -r c2387f117808 core/modules/rest/tests/src/Functional/EntityResource/User/UserXmlAnonTest.php --- a/core/modules/rest/tests/src/Functional/EntityResource/User/UserXmlAnonTest.php Thu Apr 26 11:26:54 2018 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,34 +0,0 @@ -markTestSkipped(); - } - -} diff -r e200cb7efeb3 -r c2387f117808 core/modules/rest/tests/src/Functional/EntityResource/User/UserXmlBasicAuthTest.php --- a/core/modules/rest/tests/src/Functional/EntityResource/User/UserXmlBasicAuthTest.php Thu Apr 26 11:26:54 2018 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,52 +0,0 @@ -markTestSkipped(); - } - - /** - * {@inheritdoc} - */ - public function testPatchSecurityOtherUser() { - // Deserialization of the XML format is not supported. - $this->markTestSkipped(); - } - -} diff -r e200cb7efeb3 -r c2387f117808 core/modules/rest/tests/src/Functional/EntityResource/User/UserXmlCookieTest.php --- a/core/modules/rest/tests/src/Functional/EntityResource/User/UserXmlCookieTest.php Thu Apr 26 11:26:54 2018 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,47 +0,0 @@ -markTestSkipped(); - } - - /** - * {@inheritdoc} - */ - public function testPatchSecurityOtherUser() { - // Deserialization of the XML format is not supported. - $this->markTestSkipped(); - } - -} diff -r e200cb7efeb3 -r c2387f117808 core/modules/rest/tests/src/Functional/EntityResource/View/ViewJsonAnonTest.php --- a/core/modules/rest/tests/src/Functional/EntityResource/View/ViewJsonAnonTest.php Thu Apr 26 11:26:54 2018 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,24 +0,0 @@ -grantPermissionsToTestedRole(['administer views']); - } - - /** - * {@inheritdoc} - */ - protected function createEntity() { - $view = View::create([ - 'id' => 'test_rest', - 'label' => 'Test REST', - ]); - $view->save(); - return $view; - } - - /** - * {@inheritdoc} - */ - protected function getExpectedNormalizedEntity() { - return [ - 'base_field' => 'nid', - 'base_table' => 'node', - 'core' => '8.x', - 'dependencies' => [], - 'description' => '', - 'display' => [ - 'default' => [ - 'display_plugin' => 'default', - 'id' => 'default', - 'display_title' => 'Master', - 'position' => 0, - 'display_options' => [ - 'display_extenders' => [], - ], - 'cache_metadata' => [ - 'max-age' => -1, - 'contexts' => [ - 'languages:language_interface', - 'url.query_args', - ], - 'tags' => [], - ], - ], - ], - 'id' => 'test_rest', - 'label' => 'Test REST', - 'langcode' => 'en', - 'module' => 'views', - 'status' => TRUE, - 'tag' => '', - 'uuid' => $this->entity->uuid(), - ]; - } - - /** - * {@inheritdoc} - */ - protected function getNormalizedPostEntity() { - // @todo Update in https://www.drupal.org/node/2300677. - } - - /** - * {@inheritdoc} - */ - protected function getExpectedCacheContexts() { - return [ - 'user.permissions', - ]; - } - +/** + * Class for backward compatibility. It is deprecated in Drupal 8.6.x. + * + * @see https://www.drupal.org/node/2971931 + */ +abstract class ViewResourceTestBase extends ViewResourceTestBaseReal { } diff -r e200cb7efeb3 -r c2387f117808 core/modules/rest/tests/src/Functional/EntityResource/View/ViewXmlAnonTest.php --- a/core/modules/rest/tests/src/Functional/EntityResource/View/ViewXmlAnonTest.php Thu Apr 26 11:26:54 2018 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,26 +0,0 @@ -markTestSkipped(); - } - -} diff -r e200cb7efeb3 -r c2387f117808 core/modules/rest/tests/src/Functional/EntityResource/Vocabulary/VocabularyJsonBasicAuthTest.php --- a/core/modules/rest/tests/src/Functional/EntityResource/Vocabulary/VocabularyJsonBasicAuthTest.php Thu Apr 26 11:26:54 2018 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,34 +0,0 @@ -grantPermissionsToTestedRole(['administer taxonomy']); - } - - /** - * {@inheritdoc} - */ - protected function createEntity() { - $vocabulary = Vocabulary::create([ - 'name' => 'Llama', - 'vid' => 'llama', - ]); - $vocabulary->save(); - - return $vocabulary; - } - - /** - * {@inheritdoc} - */ - protected function getExpectedNormalizedEntity() { - return [ - 'uuid' => $this->entity->uuid(), - 'vid' => 'llama', - 'langcode' => 'en', - 'status' => TRUE, - 'dependencies' => [], - 'name' => 'Llama', - 'description' => NULL, - 'hierarchy' => 0, - 'weight' => 0, - ]; - } - - /** - * {@inheritdoc} - */ - protected function getNormalizedPostEntity() { - // @todo Update in https://www.drupal.org/node/2300677. - } - - /** - * {@inheritdoc} - */ - protected function getExpectedUnauthorizedAccessMessage($method) { - if ($this->config('rest.settings')->get('bc_entity_resource_permissions')) { - return parent::getExpectedUnauthorizedAccessMessage($method); - } - - if ($method === 'GET') { - return "The following permissions are required: 'access taxonomy overview' OR 'administer taxonomy'."; - } - return parent::getExpectedUnauthorizedAccessMessage($method); - } - +/** + * Class for backward compatibility. It is deprecated in Drupal 8.6.x. + * + * @see https://www.drupal.org/node/2971931 + */ +abstract class VocabularyResourceTestBase extends VocabularyResourceTestBaseReal { } diff -r e200cb7efeb3 -r c2387f117808 core/modules/rest/tests/src/Functional/EntityResource/Vocabulary/VocabularyXmlAnonTest.php --- a/core/modules/rest/tests/src/Functional/EntityResource/Vocabulary/VocabularyXmlAnonTest.php Thu Apr 26 11:26:54 2018 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,26 +0,0 @@ -decorateWithXdebugCookie($request_options); - $client = $this->getSession()->getDriver()->getClient()->getClient(); + $client = $this->getHttpClient(); return $client->request($method, $url->setAbsolute(TRUE)->toString(), $request_options); } diff -r e200cb7efeb3 -r c2387f117808 core/modules/rest/tests/src/Functional/Rest/RestResourceConfigJsonAnonTest.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/core/modules/rest/tests/src/Functional/Rest/RestResourceConfigJsonAnonTest.php Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,24 @@ +grantPermissionsToTestedRole(['administer rest resources']); + } + + /** + * {@inheritdoc} + */ + protected function createEntity() { + $rest_resource_config = RestResourceConfig::create([ + 'id' => 'llama', + 'plugin_id' => 'dblog', + 'granularity' => 'method', + 'configuration' => [ + 'GET' => [ + 'supported_formats' => [ + 'json', + ], + 'supported_auth' => [ + 'cookie', + ], + ], + ], + ]); + $rest_resource_config->save(); + + return $rest_resource_config; + } + + /** + * {@inheritdoc} + */ + protected function getExpectedNormalizedEntity() { + return [ + 'uuid' => $this->entity->uuid(), + 'langcode' => 'en', + 'status' => TRUE, + 'dependencies' => [ + 'module' => [ + 'dblog', + 'serialization', + 'user', + ], + ], + 'id' => 'llama', + 'plugin_id' => 'dblog', + 'granularity' => 'method', + 'configuration' => [ + 'GET' => [ + 'supported_formats' => [ + 'json', + ], + 'supported_auth' => [ + 'cookie', + ], + ], + ], + ]; + } + + /** + * {@inheritdoc} + */ + protected function getNormalizedPostEntity() { + // @todo Update in https://www.drupal.org/node/2300677. + } + + /** + * {@inheritdoc} + */ + protected function getExpectedCacheContexts() { + return [ + 'user.permissions', + ]; + } + +} diff -r e200cb7efeb3 -r c2387f117808 core/modules/rest/tests/src/Functional/Rest/RestResourceConfigXmlAnonTest.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/core/modules/rest/tests/src/Functional/Rest/RestResourceConfigXmlAnonTest.php Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,26 @@ +grantPermissionsToTestedRole(['access content']); + break; + + case 'POST': + case 'PATCH': + case 'DELETE': + $this->grantPermissionsToTestedRole(['administer search']); + break; + } + } + + /** + * {@inheritdoc} + */ + protected function createEntity() { + $search_page = SearchPage::create([ + 'id' => 'hinode_search', + 'plugin' => 'node_search', + 'label' => 'Search of magnetic activity of the Sun', + 'path' => 'sun', + ]); + $search_page->save(); + return $search_page; + } + + /** + * {@inheritdoc} + */ + protected function getExpectedNormalizedEntity() { + return [ + 'configuration' => [ + 'rankings' => [], + ], + 'dependencies' => [ + 'module' => ['node'], + ], + 'id' => 'hinode_search', + 'label' => 'Search of magnetic activity of the Sun', + 'langcode' => 'en', + 'path' => 'sun', + 'plugin' => 'node_search', + 'status' => TRUE, + 'uuid' => $this->entity->uuid(), + 'weight' => 0, + ]; + } + + /** + * {@inheritdoc} + */ + protected function getNormalizedPostEntity() { + // @todo Update in https://www.drupal.org/node/2300677. + } + + /** + * {@inheritdoc} + */ + protected function getExpectedUnauthorizedAccessMessage($method) { + if ($this->config('rest.settings')->get('bc_entity_resource_permissions')) { + return parent::getExpectedUnauthorizedAccessMessage($method); + } + + switch ($method) { + case 'GET': + return "The 'access content' permission is required."; + + default: + return parent::getExpectedUnauthorizedAccessMessage($method); + } + } + + /** + * {@inheritdoc} + */ + protected function getExpectedUnauthorizedAccessCacheability() { + // @see \Drupal\search\SearchPageAccessControlHandler::checkAccess() + return parent::getExpectedUnauthorizedAccessCacheability() + ->addCacheTags(['config:search.page.hinode_search']); + } + +} diff -r e200cb7efeb3 -r c2387f117808 core/modules/search/tests/src/Functional/Rest/SearchPageXmlAnonTest.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/core/modules/search/tests/src/Functional/Rest/SearchPageXmlAnonTest.php Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,26 @@ +createUser([ + 'administer blocks', + 'access contextual links', + 'access toolbar', + ]); + $this->drupalLogin($user); + } + + /** + * Tests access to block forms with related configuration is correct. + */ + public function testBlockConfigAccess() { + $page = $this->getSession()->getPage(); + $web_assert = $this->assertSession(); + + // Confirm that System Branding block does not expose Site Name field + // without permission. + $block = $this->placeBlock('system_branding_block'); + $this->drupalGet('user'); + $this->enableEditMode(); + $this->openBlockForm($this->getBlockSelector($block)); + // The site name field should not appear because the user doesn't have + // permission. + $web_assert->fieldNotExists('settings[site_information][site_name]'); + $page->pressButton('Save Site branding'); + $this->assertElementVisibleAfterWait('css', 'div:contains(The block configuration has been saved)'); + $web_assert->assertWaitOnAjaxRequest(); + // Confirm we did not save changes to the configuration. + $this->assertEquals('Drupal', \Drupal::configFactory()->getEditable('system.site')->get('name')); + + $this->grantPermissions(Role::load(Role::AUTHENTICATED_ID), ['administer site configuration']); + $this->drupalGet('user'); + $this->openBlockForm($this->getBlockSelector($block)); + // The site name field should appear because the user does have permission. + $web_assert->fieldExists('settings[site_information][site_name]'); + + // Confirm that the Menu block does not expose menu configuration without + // permission. + // Add a link or the menu will not render. + $menu_link_content = MenuLinkContent::create([ + 'title' => 'This is on the menu', + 'menu_name' => 'main', + 'link' => ['uri' => 'route:'], + ]); + $menu_link_content->save(); + $this->assertNotEmpty($menu_link_content->isEnabled()); + $menu_without_overrides = \Drupal::configFactory()->getEditable('system.menu.main')->get(); + $block = $this->placeBlock('system_menu_block:main'); + $this->drupalGet('user'); + $web_assert->pageTextContains('This is on the menu'); + $this->openBlockForm($this->getBlockSelector($block)); + // Edit menu form should not appear because the user doesn't have + // permission. + $web_assert->pageTextNotContains('Edit menu'); + $page->pressButton('Save Main navigation'); + $this->assertElementVisibleAfterWait('css', 'div:contains(The block configuration has been saved)'); + $web_assert->assertWaitOnAjaxRequest(); + // Confirm we did not save changes to the menu or the menu link. + $this->assertEquals($menu_without_overrides, \Drupal::configFactory()->getEditable('system.menu.main')->get()); + $menu_link_content = MenuLinkContent::load($menu_link_content->id()); + $this->assertNotEmpty($menu_link_content->isEnabled()); + // Confirm menu is still on the page. + $this->drupalGet('user'); + $web_assert->pageTextContains('This is on the menu'); + + $this->grantPermissions(Role::load(Role::AUTHENTICATED_ID), ['administer menu']); + $this->drupalGet('user'); + $web_assert->pageTextContains('This is on the menu'); + $this->openBlockForm($this->getBlockSelector($block)); + // Edit menu form should appear because the user does have permission. + $web_assert->pageTextContains('Edit menu'); + } + +} diff -r e200cb7efeb3 -r c2387f117808 core/modules/settings_tray/tests/src/FunctionalJavascript/OverriddenConfigurationTest.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/core/modules/settings_tray/tests/src/FunctionalJavascript/OverriddenConfigurationTest.php Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,174 @@ +createUser([ + 'administer blocks', + 'access contextual links', + 'access toolbar', + ]); + $this->drupalLogin($user); + } + + /** + * Test blocks with overridden related configuration removed when overridden. + */ + public function testOverriddenConfigurationRemoved() { + $web_assert = $this->assertSession(); + $page = $this->getSession()->getPage(); + $this->grantPermissions(Role::load(Role::AUTHENTICATED_ID), ['administer site configuration', 'administer menu']); + + // Confirm the branding block does include 'site_information' section when + // the site name is not overridden. + $branding_block = $this->placeBlock('system_branding_block'); + $this->drupalGet('user'); + $this->enableEditMode(); + $this->openBlockForm($this->getBlockSelector($branding_block)); + $web_assert->fieldExists('settings[site_information][site_name]'); + // Confirm the branding block does not include 'site_information' section + // when the site name is overridden. + $this->container->get('state')->set('settings_tray_override_test.site_name', TRUE); + $this->drupalGet('user'); + $this->openBlockForm($this->getBlockSelector($branding_block)); + $web_assert->fieldNotExists('settings[site_information][site_name]'); + $page->pressButton('Save Site branding'); + $this->assertElementVisibleAfterWait('css', 'div:contains(The block configuration has been saved)'); + $web_assert->assertWaitOnAjaxRequest(); + // Confirm we did not save changes to the configuration. + $this->assertEquals('Llama Fan Club', \Drupal::configFactory()->get('system.site')->get('name')); + $this->assertEquals('Drupal', \Drupal::configFactory()->getEditable('system.site')->get('name')); + + // Add a link or the menu will not render. + $menu_link_content = MenuLinkContent::create([ + 'title' => 'This is on the menu', + 'menu_name' => 'main', + 'link' => ['uri' => 'route:'], + ]); + $menu_link_content->save(); + // Confirm the menu block does include menu section when the menu is not + // overridden. + $menu_block = $this->placeBlock('system_menu_block:main'); + $web_assert->assertWaitOnAjaxRequest(); + $this->drupalGet('user'); + $web_assert->pageTextContains('This is on the menu'); + $this->openBlockForm($this->getBlockSelector($menu_block)); + $web_assert->elementExists('css', '#menu-overview'); + + // Confirm the menu block does not include menu section when the menu is + // overridden. + $this->container->get('state')->set('settings_tray_override_test.menu', TRUE); + $this->drupalGet('user'); + $web_assert->pageTextContains('This is on the menu'); + $menu_with_overrides = \Drupal::configFactory()->get('system.menu.main')->get(); + $menu_without_overrides = \Drupal::configFactory()->getEditable('system.menu.main')->get(); + $this->openBlockForm($this->getBlockSelector($menu_block)); + $web_assert->elementNotExists('css', '#menu-overview'); + $page->pressButton('Save Main navigation'); + $this->assertElementVisibleAfterWait('css', 'div:contains(The block configuration has been saved)'); + $web_assert->assertWaitOnAjaxRequest(); + // Confirm we did not save changes to the configuration. + $this->assertEquals('Labely label', \Drupal::configFactory()->get('system.menu.main')->get('label')); + $this->assertEquals('Main navigation', \Drupal::configFactory()->getEditable('system.menu.main')->get('label')); + $this->assertEquals($menu_with_overrides, \Drupal::configFactory()->get('system.menu.main')->get()); + $this->assertEquals($menu_without_overrides, \Drupal::configFactory()->getEditable('system.menu.main')->get()); + $web_assert->pageTextContains('This is on the menu'); + } + + /** + * Tests that blocks with configuration overrides are disabled. + */ + public function testOverriddenBlock() { + $web_assert = $this->assertSession(); + $page = $this->getSession()->getPage(); + $overridden_block = $this->placeBlock('system_powered_by_block', [ + 'id' => 'overridden_block', + 'label_display' => 1, + 'label' => 'This will be overridden.', + ]); + $this->drupalGet('user'); + $block_selector = $this->getBlockSelector($overridden_block); + // Confirm the block is marked as Settings Tray editable. + $this->assertEquals('editable', $page->find('css', $block_selector)->getAttribute('data-drupal-settingstray')); + // Confirm the label is not overridden. + $web_assert->elementContains('css', $block_selector, 'This will be overridden.'); + $this->enableEditMode(); + $this->openBlockForm($block_selector); + + // Confirm the block Settings Tray functionality is disabled when block is + // overridden. + $this->container->get('state')->set('settings_tray_override_test.block', TRUE); + $overridden_block->save(); + $block_config = \Drupal::configFactory()->getEditable('block.block.overridden_block'); + $block_config->set('settings', $block_config->get('settings'))->save(); + + $this->drupalGet('user'); + $this->assertOverriddenBlockDisabled($overridden_block, 'Now this will be the label.'); + + // Test a non-overridden block does show the form in the off-canvas dialog. + $block = $this->placeBlock('system_powered_by_block', [ + 'label_display' => 1, + 'label' => 'Labely label', + ]); + $this->drupalGet('user'); + $block_selector = $this->getBlockSelector($block); + // Confirm the block is marked as Settings Tray editable. + $this->assertEquals('editable', $page->find('css', $block_selector)->getAttribute('data-drupal-settingstray')); + // Confirm the label is not overridden. + $web_assert->elementContains('css', $block_selector, 'Labely label'); + $this->openBlockForm($block_selector); + } + + /** + * Asserts that an overridden block has Settings Tray disabled. + * + * @param \Drupal\block\Entity\Block $overridden_block + * The overridden block. + * @param string $override_text + * The override text that should appear in the block. + */ + protected function assertOverriddenBlockDisabled(Block $overridden_block, $override_text) { + $web_assert = $this->assertSession(); + $page = $this->getSession()->getPage(); + $block_selector = $this->getBlockSelector($overridden_block); + $block_id = $overridden_block->id(); + // Confirm the block does not have a quick edit link. + $contextual_links = $page->findAll('css', "$block_selector .contextual-links li a"); + $this->assertNotEmpty($contextual_links); + foreach ($contextual_links as $link) { + $this->assertNotContains("/admin/structure/block/manage/$block_id/off-canvas", $link->getAttribute('href')); + } + // Confirm the block is not marked as Settings Tray editable. + $this->assertFalse($page->find('css', $block_selector) + ->hasAttribute('data-drupal-settingstray')); + + // Confirm the text is actually overridden. + $web_assert->elementContains('css', $this->getBlockSelector($overridden_block), $override_text); + } + +} diff -r e200cb7efeb3 -r c2387f117808 core/modules/settings_tray/tests/src/FunctionalJavascript/QuickEditIntegrationTest.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/core/modules/settings_tray/tests/src/FunctionalJavascript/QuickEditIntegrationTest.php Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,204 @@ +createUser([ + 'administer blocks', + 'access contextual links', + 'access toolbar', + 'administer nodes', + 'access in-place editing', + ]); + $this->drupalLogin($user); + + } + + /** + * Tests QuickEdit links behavior. + */ + public function testQuickEditLinks() { + $quick_edit_selector = '#quickedit-entity-toolbar'; + $node_selector = '[data-quickedit-entity-id="node/1"]'; + $body_selector = '[data-quickedit-field-id="node/1/body/en/full"]'; + $web_assert = $this->assertSession(); + // Create a Content type and two test nodes. + $this->createContentType(['type' => 'page']); + $auth_role = Role::load(Role::AUTHENTICATED_ID); + $this->grantPermissions($auth_role, [ + 'edit any page content', + 'access content', + ]); + $node = $this->createNode( + [ + 'title' => 'Page One', + 'type' => 'page', + 'body' => [ + [ + 'value' => 'Regular NODE body for the test.', + 'format' => 'plain_text', + ], + ], + ] + ); + $page = $this->getSession()->getPage(); + $block_plugin = 'system_powered_by_block'; + + foreach ($this->getTestThemes() as $theme) { + + $this->enableTheme($theme); + + $block = $this->placeBlock($block_plugin); + $block_selector = $this->getBlockSelector($block); + // Load the same page twice. + foreach ([1, 2] as $page_load_times) { + $this->drupalGet('node/' . $node->id()); + // The 2nd page load we should already be in edit mode. + if ($page_load_times == 1) { + $this->enableEditMode(); + } + // In Edit mode clicking field should open QuickEdit toolbar. + $page->find('css', $body_selector)->click(); + $this->assertElementVisibleAfterWait('css', $quick_edit_selector); + + $this->disableEditMode(); + // Exiting Edit mode should close QuickEdit toolbar. + $web_assert->elementNotExists('css', $quick_edit_selector); + // When not in Edit mode QuickEdit toolbar should not open. + $page->find('css', $body_selector)->click(); + $web_assert->elementNotExists('css', $quick_edit_selector); + $this->enableEditMode(); + $this->openBlockForm($block_selector); + $page->find('css', $body_selector)->click(); + $this->assertElementVisibleAfterWait('css', $quick_edit_selector); + // Off-canvas dialog should be closed when opening QuickEdit toolbar. + $this->waitForOffCanvasToClose(); + + $this->openBlockForm($block_selector); + // QuickEdit toolbar should be closed when opening Off-canvas dialog. + $web_assert->elementNotExists('css', $quick_edit_selector); + } + // Check using contextual links to invoke QuickEdit and open the tray. + $this->drupalGet('node/' . $node->id()); + $web_assert->assertWaitOnAjaxRequest(); + $this->disableEditMode(); + // Open QuickEdit toolbar before going into Edit mode. + $this->clickContextualLink($node_selector, "Quick edit"); + $this->assertElementVisibleAfterWait('css', $quick_edit_selector); + // Open off-canvas and enter Edit mode via contextual link. + $this->clickContextualLink($block_selector, "Quick edit"); + $this->waitForOffCanvasToOpen(); + // QuickEdit toolbar should be closed when opening off-canvas dialog. + $web_assert->elementNotExists('css', $quick_edit_selector); + // Open QuickEdit toolbar via contextual link while in Edit mode. + $this->clickContextualLink($node_selector, "Quick edit", FALSE); + $this->waitForOffCanvasToClose(); + $this->assertElementVisibleAfterWait('css', $quick_edit_selector); + $this->disableEditMode(); + } + } + + /** + * Tests that contextual links in custom blocks are changed. + * + * "Quick edit" is quickedit.module link. + * "Quick edit settings" is settings_tray.module link. + */ + public function testCustomBlockLinks() { + $this->createBlockContentType('basic', TRUE); + $block_content = $this->createBlockContent('Custom Block', 'basic', TRUE); + $this->placeBlock('block_content:' . $block_content->uuid(), ['id' => 'custom']); + $this->drupalGet('user'); + $page = $this->getSession()->getPage(); + $links = $page->findAll('css', "#block-custom .contextual-links li a"); + $link_labels = []; + /** @var \Behat\Mink\Element\NodeElement $link */ + foreach ($links as $link) { + $link_labels[$link->getAttribute('href')] = $link->getText(); + } + $href = array_search('Quick edit', $link_labels); + $this->assertEquals('', $href); + $href = array_search('Quick edit settings', $link_labels); + $this->assertTrue(strstr($href, '/admin/structure/block/manage/custom/settings-tray?destination=user/2') !== FALSE); + } + + /** + * Creates a custom block. + * + * @param bool|string $title + * (optional) Title of block. When no value is given uses a random name. + * Defaults to FALSE. + * @param string $bundle + * (optional) Bundle name. Defaults to 'basic'. + * @param bool $save + * (optional) Whether to save the block. Defaults to TRUE. + * + * @return \Drupal\block_content\Entity\BlockContent + * Created custom block. + */ + protected function createBlockContent($title = FALSE, $bundle = 'basic', $save = TRUE) { + $title = $title ?: $this->randomName(); + $block_content = BlockContent::create([ + 'info' => $title, + 'type' => $bundle, + 'langcode' => 'en', + 'body' => [ + 'value' => 'The name "llama" was adopted by European settlers from native Peruvians.', + 'format' => 'plain_text', + ], + ]); + if ($block_content && $save === TRUE) { + $block_content->save(); + } + return $block_content; + } + + /** + * Creates a custom block type (bundle). + * + * @param string $label + * The block type label. + * @param bool $create_body + * Whether or not to create the body field. + * + * @return \Drupal\block_content\Entity\BlockContentType + * Created custom block type. + */ + protected function createBlockContentType($label, $create_body = FALSE) { + $bundle = BlockContentType::create([ + 'id' => $label, + 'label' => $label, + 'revision' => FALSE, + ]); + $bundle->save(); + if ($create_body) { + block_content_add_body_field($bundle->id()); + } + return $bundle; + } + +} diff -r e200cb7efeb3 -r c2387f117808 core/modules/settings_tray/tests/src/FunctionalJavascript/SettingsTrayBlockFormTest.php --- a/core/modules/settings_tray/tests/src/FunctionalJavascript/SettingsTrayBlockFormTest.php Thu Apr 26 11:26:54 2018 +0100 +++ b/core/modules/settings_tray/tests/src/FunctionalJavascript/SettingsTrayBlockFormTest.php Tue Jul 10 15:07:59 2018 +0100 @@ -2,51 +2,24 @@ namespace Drupal\Tests\settings_tray\FunctionalJavascript; -use Drupal\block\Entity\Block; -use Drupal\block_content\Entity\BlockContent; -use Drupal\block_content\Entity\BlockContentType; -use Drupal\menu_link_content\Entity\MenuLinkContent; use Drupal\settings_tray_test\Plugin\Block\SettingsTrayFormAnnotationIsClassBlock; use Drupal\settings_tray_test\Plugin\Block\SettingsTrayFormAnnotationNoneBlock; -use Drupal\Tests\contextual\FunctionalJavascript\ContextualLinkClickTrait; -use Drupal\Tests\system\FunctionalJavascript\OffCanvasTestBase; use Drupal\user\Entity\Role; -use Drupal\user\RoleInterface; /** * Testing opening and saving block forms in the off-canvas dialog. * * @group settings_tray */ -class SettingsTrayBlockFormTest extends OffCanvasTestBase { - - use ContextualLinkClickTrait; - - const TOOLBAR_EDIT_LINK_SELECTOR = '#toolbar-bar div.contextual-toolbar-tab button'; - - const LABEL_INPUT_SELECTOR = 'input[data-drupal-selector="edit-settings-label"]'; +class SettingsTrayBlockFormTest extends SettingsTrayTestBase { /** * {@inheritdoc} */ public static $modules = [ 'node', - 'block', - 'system', - 'breakpoint', - 'toolbar', - 'contextual', - 'settings_tray', 'search', - 'block_content', 'settings_tray_test', - // Add test module to override CSS pointer-events properties because they - // cause test failures. - 'settings_tray_test_css', - 'settings_tray_test', - 'settings_tray_override_test', - 'menu_ui', - 'menu_link_content', ]; /** @@ -55,8 +28,6 @@ protected function setUp() { parent::setUp(); - $this->createBlockContentType('basic', TRUE); - $block_content = $this->createBlockContent('Custom Block', 'basic', TRUE); $user = $this->createUser([ 'administer blocks', 'access contextual links', @@ -65,7 +36,6 @@ 'search content', ]); $this->drupalLogin($user); - $this->placeBlock('block_content:' . $block_content->uuid(), ['id' => 'custom']); } /** @@ -231,160 +201,6 @@ } /** - * Enables edit mode by pressing edit button in the toolbar. - */ - protected function enableEditMode() { - $this->pressToolbarEditButton(); - $this->assertEditModeEnabled(); - } - - /** - * Disables edit mode by pressing edit button in the toolbar. - */ - protected function disableEditMode() { - $this->assertSession()->assertWaitOnAjaxRequest(); - $this->pressToolbarEditButton(); - $this->assertEditModeDisabled(); - } - - /** - * Asserts that Off-Canvas block form is valid. - */ - protected function assertOffCanvasBlockFormIsValid() { - $web_assert = $this->assertSession(); - // Confirm that Block title display label has been changed. - $web_assert->elementTextContains('css', '.form-item-settings-label-display label', 'Display block title'); - // Confirm Block title label is shown if checkbox is checked. - if ($this->getSession()->getPage()->find('css', 'input[name="settings[label_display]"]')->isChecked()) { - $this->assertEquals($this->isLabelInputVisible(), TRUE, 'Label is visible'); - $web_assert->elementTextContains('css', '.form-item-settings-label label', 'Block title'); - } - else { - $this->assertEquals($this->isLabelInputVisible(), FALSE, 'Label is not visible'); - } - - // Check that common block form elements exist. - $web_assert->elementExists('css', static::LABEL_INPUT_SELECTOR); - $web_assert->elementExists('css', 'input[data-drupal-selector="edit-settings-label-display"]'); - // Check that advanced block form elements do not exist. - $web_assert->elementNotExists('css', 'input[data-drupal-selector="edit-visibility-request-path-pages"]'); - $web_assert->elementNotExists('css', 'select[data-drupal-selector="edit-region"]'); - } - - /** - * Open block form by clicking the element found with a css selector. - * - * @param string $block_selector - * A css selector selects the block or an element within it. - * @param string $contextual_link_container - * The element that contains the contextual links. If none provide the - * $block_selector will be used. - */ - protected function openBlockForm($block_selector, $contextual_link_container = '') { - if (!$contextual_link_container) { - $contextual_link_container = $block_selector; - } - // Ensure that contextual link element is present because this is required - // to open the off-canvas dialog in edit mode. - $contextual_link = $this->assertSession()->waitForElement('css', "$contextual_link_container .contextual-links a"); - $this->assertNotEmpty($contextual_link); - // When page first loads Edit Mode is not triggered until first contextual - // link is added. - $this->assertElementVisibleAfterWait('css', '.dialog-off-canvas-main-canvas.js-settings-tray-edit-mode'); - // Ensure that all other Ajax activity is completed. - $this->assertSession()->assertWaitOnAjaxRequest(); - $this->click($block_selector); - $this->waitForOffCanvasToOpen(); - $this->assertOffCanvasBlockFormIsValid(); - } - - /** - * Tests QuickEdit links behavior. - */ - public function testQuickEditLinks() { - $this->container->get('module_installer')->install(['quickedit']); - $this->grantPermissions(Role::load(RoleInterface::AUTHENTICATED_ID), ['access in-place editing']); - $quick_edit_selector = '#quickedit-entity-toolbar'; - $node_selector = '[data-quickedit-entity-id="node/1"]'; - $body_selector = '[data-quickedit-field-id="node/1/body/en/full"]'; - $web_assert = $this->assertSession(); - // Create a Content type and two test nodes. - $this->createContentType(['type' => 'page']); - $auth_role = Role::load(Role::AUTHENTICATED_ID); - $this->grantPermissions($auth_role, [ - 'edit any page content', - 'access content', - ]); - $node = $this->createNode( - [ - 'title' => 'Page One', - 'type' => 'page', - 'body' => [ - [ - 'value' => 'Regular NODE body for the test.', - 'format' => 'plain_text', - ], - ], - ] - ); - $page = $this->getSession()->getPage(); - $block_plugin = 'system_powered_by_block'; - - foreach ($this->getTestThemes() as $theme) { - - $this->enableTheme($theme); - - $block = $this->placeBlock($block_plugin); - $block_selector = $this->getBlockSelector($block); - // Load the same page twice. - foreach ([1, 2] as $page_load_times) { - $this->drupalGet('node/' . $node->id()); - // The 2nd page load we should already be in edit mode. - if ($page_load_times == 1) { - $this->enableEditMode(); - } - // In Edit mode clicking field should open QuickEdit toolbar. - $page->find('css', $body_selector)->click(); - $this->assertElementVisibleAfterWait('css', $quick_edit_selector); - - $this->disableEditMode(); - // Exiting Edit mode should close QuickEdit toolbar. - $web_assert->elementNotExists('css', $quick_edit_selector); - // When not in Edit mode QuickEdit toolbar should not open. - $page->find('css', $body_selector)->click(); - $web_assert->elementNotExists('css', $quick_edit_selector); - $this->enableEditMode(); - $this->openBlockForm($block_selector); - $page->find('css', $body_selector)->click(); - $this->assertElementVisibleAfterWait('css', $quick_edit_selector); - // Off-canvas dialog should be closed when opening QuickEdit toolbar. - $this->waitForOffCanvasToClose(); - - $this->openBlockForm($block_selector); - // QuickEdit toolbar should be closed when opening Off-canvas dialog. - $web_assert->elementNotExists('css', $quick_edit_selector); - } - // Check using contextual links to invoke QuickEdit and open the tray. - $this->drupalGet('node/' . $node->id()); - $web_assert->assertWaitOnAjaxRequest(); - $this->disableEditMode(); - // Open QuickEdit toolbar before going into Edit mode. - $this->clickContextualLink($node_selector, "Quick edit"); - $this->assertElementVisibleAfterWait('css', $quick_edit_selector); - // Open off-canvas and enter Edit mode via contextual link. - $this->clickContextualLink($block_selector, "Quick edit"); - $this->waitForOffCanvasToOpen(); - // QuickEdit toolbar should be closed when opening off-canvas dialog. - $web_assert->elementNotExists('css', $quick_edit_selector); - // Open QuickEdit toolbar via contextual link while in Edit mode. - $this->clickContextualLink($node_selector, "Quick edit", FALSE); - $this->waitForOffCanvasToClose(); - $this->assertElementVisibleAfterWait('css', $quick_edit_selector); - $this->disableEditMode(); - } - } - - /** * Tests enabling and disabling Edit Mode. */ public function testEditModeEnableDisable() { @@ -420,212 +236,6 @@ } /** - * Assert that edit mode has been properly enabled. - */ - protected function assertEditModeEnabled() { - $web_assert = $this->assertSession(); - // No contextual triggers should be hidden. - $web_assert->elementNotExists('css', '.contextual .trigger.visually-hidden'); - // The toolbar edit button should read "Editing". - $web_assert->elementContains('css', static::TOOLBAR_EDIT_LINK_SELECTOR, 'Editing'); - // The main canvas element should have the "js-settings-tray-edit-mode" class. - $web_assert->elementExists('css', '.dialog-off-canvas-main-canvas.js-settings-tray-edit-mode'); - } - - /** - * Assert that edit mode has been properly disabled. - */ - protected function assertEditModeDisabled() { - $web_assert = $this->assertSession(); - // Contextual triggers should be hidden. - $web_assert->elementExists('css', '.contextual .trigger.visually-hidden'); - // No contextual triggers should be not hidden. - $web_assert->elementNotExists('css', '.contextual .trigger:not(.visually-hidden)'); - // The toolbar edit button should read "Edit". - $web_assert->elementContains('css', static::TOOLBAR_EDIT_LINK_SELECTOR, 'Edit'); - // The main canvas element should NOT have the "js-settings-tray-edit-mode" - // class. - $web_assert->elementNotExists('css', '.dialog-off-canvas-main-canvas.js-settings-tray-edit-mode'); - } - - /** - * Press the toolbar Edit button provided by the contextual module. - */ - protected function pressToolbarEditButton() { - $this->assertSession()->waitForElement('css', '[data-contextual-id] .contextual-links a'); - $edit_button = $this->getSession() - ->getPage() - ->find('css', static::TOOLBAR_EDIT_LINK_SELECTOR); - $edit_button->press(); - } - - /** - * Creates a custom block. - * - * @param bool|string $title - * (optional) Title of block. When no value is given uses a random name. - * Defaults to FALSE. - * @param string $bundle - * (optional) Bundle name. Defaults to 'basic'. - * @param bool $save - * (optional) Whether to save the block. Defaults to TRUE. - * - * @return \Drupal\block_content\Entity\BlockContent - * Created custom block. - */ - protected function createBlockContent($title = FALSE, $bundle = 'basic', $save = TRUE) { - $title = $title ?: $this->randomName(); - $block_content = BlockContent::create([ - 'info' => $title, - 'type' => $bundle, - 'langcode' => 'en', - 'body' => [ - 'value' => 'The name "llama" was adopted by European settlers from native Peruvians.', - 'format' => 'plain_text', - ], - ]); - if ($block_content && $save === TRUE) { - $block_content->save(); - } - return $block_content; - } - - /** - * Creates a custom block type (bundle). - * - * @param string $label - * The block type label. - * @param bool $create_body - * Whether or not to create the body field. - * - * @return \Drupal\block_content\Entity\BlockContentType - * Created custom block type. - */ - protected function createBlockContentType($label, $create_body = FALSE) { - $bundle = BlockContentType::create([ - 'id' => $label, - 'label' => $label, - 'revision' => FALSE, - ]); - $bundle->save(); - if ($create_body) { - block_content_add_body_field($bundle->id()); - } - return $bundle; - } - - /** - * Tests that contextual links in custom blocks are changed. - * - * "Quick edit" is quickedit.module link. - * "Quick edit settings" is settings_tray.module link. - */ - public function testCustomBlockLinks() { - $this->container->get('module_installer')->install(['quickedit']); - $this->grantPermissions(Role::load(RoleInterface::AUTHENTICATED_ID), ['access in-place editing']); - $this->drupalGet('user'); - $page = $this->getSession()->getPage(); - $links = $page->findAll('css', "#block-custom .contextual-links li a"); - $link_labels = []; - /** @var \Behat\Mink\Element\NodeElement $link */ - foreach ($links as $link) { - $link_labels[$link->getAttribute('href')] = $link->getText(); - } - $href = array_search('Quick edit', $link_labels); - $this->assertEquals('', $href); - $href = array_search('Quick edit settings', $link_labels); - $this->assertTrue(strstr($href, '/admin/structure/block/manage/custom/settings-tray?destination=user/2') !== FALSE); - } - - /** - * Gets the block CSS selector. - * - * @param \Drupal\block\Entity\Block $block - * The block. - * - * @return string - * The CSS selector. - */ - public function getBlockSelector(Block $block) { - return '#block-' . str_replace('_', '-', $block->id()); - } - - /** - * Determines if the label input is visible. - * - * @return bool - * TRUE if the label is visible, FALSE if it is not. - */ - protected function isLabelInputVisible() { - return $this->getSession()->getPage()->find('css', static::LABEL_INPUT_SELECTOR)->isVisible(); - } - - /** - * Tests access to block forms with related configuration is correct. - */ - public function testBlockConfigAccess() { - $page = $this->getSession()->getPage(); - $web_assert = $this->assertSession(); - - // Confirm that System Branding block does not expose Site Name field - // without permission. - $block = $this->placeBlock('system_branding_block'); - $this->drupalGet('user'); - $this->enableEditMode(); - $this->openBlockForm($this->getBlockSelector($block)); - // The site name field should not appear because the user doesn't have - // permission. - $web_assert->fieldNotExists('settings[site_information][site_name]'); - $page->pressButton('Save Site branding'); - $this->assertElementVisibleAfterWait('css', 'div:contains(The block configuration has been saved)'); - $web_assert->assertWaitOnAjaxRequest(); - // Confirm we did not save changes to the configuration. - $this->assertEquals('Drupal', \Drupal::configFactory()->getEditable('system.site')->get('name')); - - $this->grantPermissions(Role::load(Role::AUTHENTICATED_ID), ['administer site configuration']); - $this->drupalGet('user'); - $this->openBlockForm($this->getBlockSelector($block)); - // The site name field should appear because the user does have permission. - $web_assert->fieldExists('settings[site_information][site_name]'); - - // Confirm that the Menu block does not expose menu configuration without - // permission. - // Add a link or the menu will not render. - $menu_link_content = MenuLinkContent::create([ - 'title' => 'This is on the menu', - 'menu_name' => 'main', - 'link' => ['uri' => 'route:'], - ]); - $menu_link_content->save(); - $this->assertNotEmpty($menu_link_content->isEnabled()); - $menu_without_overrides = \Drupal::configFactory()->getEditable('system.menu.main')->get(); - $block = $this->placeBlock('system_menu_block:main'); - $this->drupalGet('user'); - $web_assert->pageTextContains('This is on the menu'); - $this->openBlockForm($this->getBlockSelector($block)); - // Edit menu form should not appear because the user doesn't have - // permission. - $web_assert->pageTextNotContains('Edit menu'); - $page->pressButton('Save Main navigation'); - $this->assertElementVisibleAfterWait('css', 'div:contains(The block configuration has been saved)'); - $web_assert->assertWaitOnAjaxRequest(); - // Confirm we did not save changes to the menu or the menu link. - $this->assertEquals($menu_without_overrides, \Drupal::configFactory()->getEditable('system.menu.main')->get()); - $menu_link_content = MenuLinkContent::load($menu_link_content->id()); - $this->assertNotEmpty($menu_link_content->isEnabled()); - // Confirm menu is still on the page. - $this->drupalGet('user'); - $web_assert->pageTextContains('This is on the menu'); - - $this->grantPermissions(Role::load(Role::AUTHENTICATED_ID), ['administer menu']); - $this->drupalGet('user'); - $web_assert->pageTextContains('This is on the menu'); - $this->openBlockForm($this->getBlockSelector($block)); - // Edit menu form should appear because the user does have permission. - $web_assert->pageTextContains('Edit menu'); - } - - /** * Test that validation errors appear in the off-canvas dialog. */ public function testValidationMessages() { @@ -658,138 +268,4 @@ }); } - /** - * Tests that blocks with configuration overrides are disabled. - */ - public function testOverriddenBlock() { - $web_assert = $this->assertSession(); - $page = $this->getSession()->getPage(); - $overridden_block = $this->placeBlock('system_powered_by_block', [ - 'id' => 'overridden_block', - 'label_display' => 1, - 'label' => 'This will be overridden.', - ]); - $this->drupalGet('user'); - $block_selector = $this->getBlockSelector($overridden_block); - // Confirm the block is marked as Settings Tray editable. - $this->assertEquals('editable', $page->find('css', $block_selector)->getAttribute('data-drupal-settingstray')); - // Confirm the label is not overridden. - $web_assert->elementContains('css', $block_selector, 'This will be overridden.'); - $this->enableEditMode(); - $this->openBlockForm($block_selector); - - // Confirm the block Settings Tray functionality is disabled when block is - // overridden. - $this->container->get('state')->set('settings_tray_override_test.block', TRUE); - $overridden_block->save(); - $block_config = \Drupal::configFactory()->getEditable('block.block.overridden_block'); - $block_config->set('settings', $block_config->get('settings'))->save(); - - $this->drupalGet('user'); - $this->assertOverriddenBlockDisabled($overridden_block, 'Now this will be the label.'); - - // Test a non-overridden block does show the form in the off-canvas dialog. - $block = $this->placeBlock('system_powered_by_block', [ - 'label_display' => 1, - 'label' => 'Labely label', - ]); - $this->drupalGet('user'); - $block_selector = $this->getBlockSelector($block); - // Confirm the block is marked as Settings Tray editable. - $this->assertEquals('editable', $page->find('css', $block_selector)->getAttribute('data-drupal-settingstray')); - // Confirm the label is not overridden. - $web_assert->elementContains('css', $block_selector, 'Labely label'); - $this->openBlockForm($block_selector); - } - - /** - * Test blocks with overridden related configuration removed when overridden. - */ - public function testOverriddenConfigurationRemoved() { - $web_assert = $this->assertSession(); - $page = $this->getSession()->getPage(); - $this->grantPermissions(Role::load(Role::AUTHENTICATED_ID), ['administer site configuration', 'administer menu']); - - // Confirm the branding block does include 'site_information' section when - // the site name is not overridden. - $branding_block = $this->placeBlock('system_branding_block'); - $this->drupalGet('user'); - $this->enableEditMode(); - $this->openBlockForm($this->getBlockSelector($branding_block)); - $web_assert->fieldExists('settings[site_information][site_name]'); - // Confirm the branding block does not include 'site_information' section - // when the site name is overridden. - $this->container->get('state')->set('settings_tray_override_test.site_name', TRUE); - $this->drupalGet('user'); - $this->openBlockForm($this->getBlockSelector($branding_block)); - $web_assert->fieldNotExists('settings[site_information][site_name]'); - $page->pressButton('Save Site branding'); - $this->assertElementVisibleAfterWait('css', 'div:contains(The block configuration has been saved)'); - $web_assert->assertWaitOnAjaxRequest(); - // Confirm we did not save changes to the configuration. - $this->assertEquals('Llama Fan Club', \Drupal::configFactory()->get('system.site')->get('name')); - $this->assertEquals('Drupal', \Drupal::configFactory()->getEditable('system.site')->get('name')); - - // Add a link or the menu will not render. - $menu_link_content = MenuLinkContent::create([ - 'title' => 'This is on the menu', - 'menu_name' => 'main', - 'link' => ['uri' => 'route:'], - ]); - $menu_link_content->save(); - // Confirm the menu block does include menu section when the menu is not - // overridden. - $menu_block = $this->placeBlock('system_menu_block:main'); - $web_assert->assertWaitOnAjaxRequest(); - $this->drupalGet('user'); - $web_assert->pageTextContains('This is on the menu'); - $this->openBlockForm($this->getBlockSelector($menu_block)); - $web_assert->elementExists('css', '#menu-overview'); - - // Confirm the menu block does not include menu section when the menu is - // overridden. - $this->container->get('state')->set('settings_tray_override_test.menu', TRUE); - $this->drupalGet('user'); - $web_assert->pageTextContains('This is on the menu'); - $menu_with_overrides = \Drupal::configFactory()->get('system.menu.main')->get(); - $menu_without_overrides = \Drupal::configFactory()->getEditable('system.menu.main')->get(); - $this->openBlockForm($this->getBlockSelector($menu_block)); - $web_assert->elementNotExists('css', '#menu-overview'); - $page->pressButton('Save Main navigation'); - $this->assertElementVisibleAfterWait('css', 'div:contains(The block configuration has been saved)'); - $web_assert->assertWaitOnAjaxRequest(); - // Confirm we did not save changes to the configuration. - $this->assertEquals('Labely label', \Drupal::configFactory()->get('system.menu.main')->get('label')); - $this->assertEquals('Main navigation', \Drupal::configFactory()->getEditable('system.menu.main')->get('label')); - $this->assertEquals($menu_with_overrides, \Drupal::configFactory()->get('system.menu.main')->get()); - $this->assertEquals($menu_without_overrides, \Drupal::configFactory()->getEditable('system.menu.main')->get()); - $web_assert->pageTextContains('This is on the menu'); - } - /** - * Asserts that an overridden block has Settings Tray disabled. - * - * @param \Drupal\block\Entity\Block $overridden_block - * The overridden block. - * @param string $override_text - * The override text that should appear in the block. - */ - protected function assertOverriddenBlockDisabled(Block $overridden_block, $override_text) { - $web_assert = $this->assertSession(); - $page = $this->getSession()->getPage(); - $block_selector = $this->getBlockSelector($overridden_block); - $block_id = $overridden_block->id(); - // Confirm the block does not have a quick edit link. - $contextual_links = $page->findAll('css', "$block_selector .contextual-links li a"); - $this->assertNotEmpty($contextual_links); - foreach ($contextual_links as $link) { - $this->assertNotContains("/admin/structure/block/manage/$block_id/off-canvas", $link->getAttribute('href')); - } - // Confirm the block is not marked as Settings Tray editable. - $this->assertFalse($page->find('css', $block_selector) - ->hasAttribute('data-drupal-settingstray')); - - // Confirm the text is actually overridden. - $web_assert->elementContains('css', $this->getBlockSelector($overridden_block), $override_text); - } - } diff -r e200cb7efeb3 -r c2387f117808 core/modules/settings_tray/tests/src/FunctionalJavascript/SettingsTrayTestBase.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/core/modules/settings_tray/tests/src/FunctionalJavascript/SettingsTrayTestBase.php Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,172 @@ +assertSession()->waitForElement('css', "$contextual_link_container .contextual-links a"); + $this->assertNotEmpty($contextual_link); + // When page first loads Edit Mode is not triggered until first contextual + // link is added. + $this->assertElementVisibleAfterWait('css', '.dialog-off-canvas-main-canvas.js-settings-tray-edit-mode'); + // Ensure that all other Ajax activity is completed. + $this->assertSession()->assertWaitOnAjaxRequest(); + $this->click($block_selector); + $this->waitForOffCanvasToOpen(); + $this->assertOffCanvasBlockFormIsValid(); + } + + /** + * Enables edit mode by pressing edit button in the toolbar. + */ + protected function enableEditMode() { + $this->pressToolbarEditButton(); + $this->assertEditModeEnabled(); + } + + /** + * Disables edit mode by pressing edit button in the toolbar. + */ + protected function disableEditMode() { + $this->assertSession()->assertWaitOnAjaxRequest(); + $this->pressToolbarEditButton(); + $this->assertEditModeDisabled(); + } + + /** + * Press the toolbar Edit button provided by the contextual module. + */ + protected function pressToolbarEditButton() { + $this->assertSession()->waitForElement('css', '[data-contextual-id] .contextual-links a'); + $edit_button = $this->getSession() + ->getPage() + ->find('css', static::TOOLBAR_EDIT_LINK_SELECTOR); + $edit_button->press(); + } + + /** + * Assert that edit mode has been properly disabled. + */ + protected function assertEditModeDisabled() { + $web_assert = $this->assertSession(); + // Contextual triggers should be hidden. + $web_assert->elementExists('css', '.contextual .trigger.visually-hidden'); + // No contextual triggers should be not hidden. + $web_assert->elementNotExists('css', '.contextual .trigger:not(.visually-hidden)'); + // The toolbar edit button should read "Edit". + $web_assert->elementContains('css', static::TOOLBAR_EDIT_LINK_SELECTOR, 'Edit'); + // The main canvas element should NOT have the "js-settings-tray-edit-mode" + // class. + $web_assert->elementNotExists('css', '.dialog-off-canvas-main-canvas.js-settings-tray-edit-mode'); + } + + /** + * Assert that edit mode has been properly enabled. + */ + protected function assertEditModeEnabled() { + $web_assert = $this->assertSession(); + // No contextual triggers should be hidden. + $web_assert->elementNotExists('css', '.contextual .trigger.visually-hidden'); + // The toolbar edit button should read "Editing". + $web_assert->elementContains('css', static::TOOLBAR_EDIT_LINK_SELECTOR, 'Editing'); + // The main canvas element should have the "js-settings-tray-edit-mode" class. + $web_assert->elementExists('css', '.dialog-off-canvas-main-canvas.js-settings-tray-edit-mode'); + } + + /** + * Asserts that Off-Canvas block form is valid. + */ + protected function assertOffCanvasBlockFormIsValid() { + $web_assert = $this->assertSession(); + // Confirm that Block title display label has been changed. + $web_assert->elementTextContains('css', '.form-item-settings-label-display label', 'Display block title'); + // Confirm Block title label is shown if checkbox is checked. + if ($this->getSession()->getPage()->find('css', 'input[name="settings[label_display]"]')->isChecked()) { + $this->assertEquals($this->isLabelInputVisible(), TRUE, 'Label is visible'); + $web_assert->elementTextContains('css', '.form-item-settings-label label', 'Block title'); + } + else { + $this->assertEquals($this->isLabelInputVisible(), FALSE, 'Label is not visible'); + } + + // Check that common block form elements exist. + $web_assert->elementExists('css', static::LABEL_INPUT_SELECTOR); + $web_assert->elementExists('css', 'input[data-drupal-selector="edit-settings-label-display"]'); + // Check that advanced block form elements do not exist. + $web_assert->elementNotExists('css', 'input[data-drupal-selector="edit-visibility-request-path-pages"]'); + $web_assert->elementNotExists('css', 'select[data-drupal-selector="edit-region"]'); + } + + /** + * {@inheritdoc} + */ + protected function getTestThemes() { + // Remove 'seven' theme. Settings Tray "Edit Mode" will not work with + // 'seven' because it removes all contextual links. + return array_filter(parent::getTestThemes(), function ($theme) { + return $theme !== 'seven'; + }); + } + + /** + * Gets the block CSS selector. + * + * @param \Drupal\block\Entity\Block $block + * The block. + * + * @return string + * The CSS selector. + */ + public function getBlockSelector(Block $block) { + return '#block-' . str_replace('_', '-', $block->id()); + } + + /** + * Determines if the label input is visible. + * + * @return bool + * TRUE if the label is visible, FALSE if it is not. + */ + protected function isLabelInputVisible() { + return $this->getSession()->getPage()->find('css', static::LABEL_INPUT_SELECTOR)->isVisible(); + } + +} diff -r e200cb7efeb3 -r c2387f117808 core/modules/shortcut/tests/src/Functional/Hal/ShortcutHalJsonAnonTest.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/core/modules/shortcut/tests/src/Functional/Hal/ShortcutHalJsonAnonTest.php Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,74 @@ +applyHalFieldNormalization($default_normalization); + + return $normalization + [ + '_links' => [ + 'self' => [ + 'href' => $this->baseUrl . '/admin/config/user-interface/shortcut/link/1?_format=hal_json', + ], + 'type' => [ + 'href' => $this->baseUrl . '/rest/type/shortcut/default', + ], + ], + ]; + } + + /** + * {@inheritdoc} + */ + protected function getNormalizedPostEntity() { + return parent::getNormalizedPostEntity() + [ + '_links' => [ + 'type' => [ + 'href' => $this->baseUrl . '/rest/type/shortcut/default', + ], + ], + ]; + } + + /** + * {@inheritdoc} + */ + protected function getExpectedCacheContexts() { + // The 'url.site' cache context is added for '_links' in the response. + return Cache::mergeContexts(parent::getExpectedCacheContexts(), ['url.site']); + } + +} diff -r e200cb7efeb3 -r c2387f117808 core/modules/shortcut/tests/src/Functional/Hal/ShortcutHalJsonBasicAuthTest.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/core/modules/shortcut/tests/src/Functional/Hal/ShortcutHalJsonBasicAuthTest.php Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,24 @@ +grantPermissionsToTestedRole(['access shortcuts', 'customize shortcut links']); + break; + } + } + + /** + * {@inheritdoc} + */ + protected function createEntity() { + // Create shortcut. + $shortcut = Shortcut::create([ + 'shortcut_set' => 'default', + 'title' => t('Comments'), + 'weight' => -20, + 'link' => [ + 'uri' => 'internal:/admin/content/comment', + ], + ]); + $shortcut->save(); + + return $shortcut; + } + + /** + * {@inheritdoc} + */ + protected function getExpectedNormalizedEntity() { + return [ + 'uuid' => [ + [ + 'value' => $this->entity->uuid(), + ], + ], + 'id' => [ + [ + 'value' => (int) $this->entity->id(), + ], + ], + 'title' => [ + [ + 'value' => 'Comments', + ], + ], + 'shortcut_set' => [ + [ + 'target_id' => 'default', + 'target_type' => 'shortcut_set', + 'target_uuid' => ShortcutSet::load('default')->uuid(), + ], + ], + 'link' => [ + [ + 'uri' => 'internal:/admin/content/comment', + 'title' => NULL, + 'options' => [], + ], + ], + 'weight' => [ + [ + 'value' => -20, + ], + ], + 'langcode' => [ + [ + 'value' => 'en', + ], + ], + 'default_langcode' => [ + [ + 'value' => TRUE, + ], + ], + ]; + } + + /** + * {@inheritdoc} + */ + protected function getNormalizedPostEntity() { + return [ + 'title' => [ + [ + 'value' => 'Comments', + ], + ], + 'link' => [ + [ + 'uri' => 'internal:/', + ], + ], + 'shortcut_set' => [ + [ + 'target_id' => 'default', + ], + ], + ]; + } + + /** + * {@inheritdoc} + */ + protected function getExpectedUnauthorizedAccessMessage($method) { + if ($this->config('rest.settings')->get('bc_entity_resource_permissions')) { + return parent::getExpectedUnauthorizedAccessMessage($method); + } + + switch ($method) { + case 'GET': + case 'POST': + case 'PATCH': + case 'DELETE': + return "The shortcut set must be the currently displayed set for the user and the user must have 'access shortcuts' AND 'customize shortcut links' permissions."; + + default: + return parent::getExpectedUnauthorizedAccessMessage($method); + } + } + +} diff -r e200cb7efeb3 -r c2387f117808 core/modules/shortcut/tests/src/Functional/Rest/ShortcutSetJsonAnonTest.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/core/modules/shortcut/tests/src/Functional/Rest/ShortcutSetJsonAnonTest.php Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,24 @@ +grantPermissionsToTestedRole(['access shortcuts']); + break; + + case 'POST': + case 'PATCH': + $this->grantPermissionsToTestedRole(['access shortcuts', 'customize shortcut links']); + break; + + case 'DELETE': + $this->grantPermissionsToTestedRole(['administer shortcuts']); + break; + } + } + + /** + * {@inheritdoc} + */ + protected function createEntity() { + $set = ShortcutSet::create([ + 'id' => 'llama_set', + 'label' => 'Llama Set', + ]); + $set->save(); + return $set; + } + + /** + * {@inheritdoc} + */ + protected function getExpectedNormalizedEntity() { + return [ + 'id' => 'llama_set', + 'uuid' => $this->entity->uuid(), + 'label' => 'Llama Set', + 'status' => TRUE, + 'langcode' => 'en', + 'dependencies' => [], + ]; + } + + /** + * {@inheritdoc} + */ + protected function getNormalizedPostEntity() { + // @todo Update in https://www.drupal.org/node/2300677. + } + +} diff -r e200cb7efeb3 -r c2387f117808 core/modules/shortcut/tests/src/Functional/Rest/ShortcutSetXmlAnonTest.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/core/modules/shortcut/tests/src/Functional/Rest/ShortcutSetXmlAnonTest.php Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,26 @@ +find(); - $command = $php . ' -f ' . escapeshellarg($command) . ' --'; + $command = $php . ' -f ' . $command . ' --'; } return $command; } diff -r e200cb7efeb3 -r c2387f117808 core/modules/simpletest/src/TestDiscovery.php --- a/core/modules/simpletest/src/TestDiscovery.php Thu Apr 26 11:26:54 2018 +0100 +++ b/core/modules/simpletest/src/TestDiscovery.php Tue Jul 10 15:07:59 2018 +0100 @@ -331,7 +331,7 @@ * If the class does not have a @group annotation. */ public static function getTestInfo($classname, $doc_comment = NULL) { - if (!$doc_comment) { + if ($doc_comment === NULL) { $reflection = new \ReflectionClass($classname); $doc_comment = $reflection->getDocComment(); } diff -r e200cb7efeb3 -r c2387f117808 core/modules/simpletest/src/WebTestBase.php --- a/core/modules/simpletest/src/WebTestBase.php Thu Apr 26 11:26:54 2018 +0100 +++ b/core/modules/simpletest/src/WebTestBase.php Tue Jul 10 15:07:59 2018 +0100 @@ -19,11 +19,11 @@ use Drupal\Tests\EntityViewTrait; use Drupal\Tests\block\Traits\BlockCreationTrait as BaseBlockCreationTrait; use Drupal\Tests\Listeners\DeprecationListenerTrait; -use Drupal\Tests\node\Traits\ContentTypeCreationTrait; -use Drupal\Tests\node\Traits\NodeCreationTrait; +use Drupal\Tests\node\Traits\ContentTypeCreationTrait as BaseContentTypeCreationTrait; +use Drupal\Tests\node\Traits\NodeCreationTrait as BaseNodeCreationTrait; use Drupal\Tests\Traits\Core\CronRunTrait; use Drupal\Tests\TestFileCreationTrait; -use Drupal\Tests\user\Traits\UserCreationTrait; +use Drupal\Tests\user\Traits\UserCreationTrait as BaseUserCreationTrait; use Drupal\Tests\XdebugRequestTrait; use Zend\Diactoros\Uri; @@ -44,18 +44,18 @@ use BaseBlockCreationTrait { placeBlock as drupalPlaceBlock; } - use ContentTypeCreationTrait { + use BaseContentTypeCreationTrait { createContentType as drupalCreateContentType; } use CronRunTrait; use AssertMailTrait { getMails as drupalGetMails; } - use NodeCreationTrait { + use BaseNodeCreationTrait { getNodeByTitle as drupalGetNodeByTitle; createNode as drupalCreateNode; } - use UserCreationTrait { + use BaseUserCreationTrait { createUser as drupalCreateUser; createRole as drupalCreateRole; createAdminRole as drupalCreateAdminRole; diff -r e200cb7efeb3 -r c2387f117808 core/modules/simpletest/tests/src/Unit/TestDiscoveryTest.php --- a/core/modules/simpletest/tests/src/Unit/TestDiscoveryTest.php Thu Apr 26 11:26:54 2018 +0100 +++ b/core/modules/simpletest/tests/src/Unit/TestDiscoveryTest.php Tue Jul 10 15:07:59 2018 +0100 @@ -385,6 +385,21 @@ return $data; } + /** + * Ensure that classes are not reflected when the docblock is empty. + * + * @covers ::getTestInfo + */ + public function testGetTestInfoEmptyDocblock() { + // If getTestInfo() performed reflection, it won't be able to find the + // class we asked it to analyze, so it will throw a ReflectionException. + // We want to make sure it didn't do that, because we already did some + // analysis and already have an empty docblock. getTestInfo() will throw + // MissingGroupException because the annotation is empty. + $this->setExpectedException(MissingGroupException::class); + TestDiscovery::getTestInfo('Drupal\Tests\simpletest\ThisTestDoesNotExistTest', ''); + } + } class TestTestDiscovery extends TestDiscovery { diff -r e200cb7efeb3 -r c2387f117808 core/modules/statistics/migrations/statistics_node_translation_counter.yml --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/core/modules/statistics/migrations/statistics_node_translation_counter.yml Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,34 @@ +id: statistics_node_translation_counter +label: Node translation counter +migration_tags: + - Drupal 6 + - Drupal 7 + - Content +source: + plugin: node_counter +process: + nid: + - + plugin: migration_lookup + migration: + - d6_node_translation + - d7_node_translation + source: nid + - + plugin: skip_on_empty + method: row + - + plugin: extract + index: + - 0 + totalcount: totalcount + daycount: daycount + timestamp: timestamp +destination: + plugin: node_counter +migration_dependencies: + required: + - statistics_node_counter + optional: + - d6_node_translation + - d7_node_translation diff -r e200cb7efeb3 -r c2387f117808 core/modules/statistics/src/Plugin/migrate/destination/NodeCounter.php --- a/core/modules/statistics/src/Plugin/migrate/destination/NodeCounter.php Thu Apr 26 11:26:54 2018 +0100 +++ b/core/modules/statistics/src/Plugin/migrate/destination/NodeCounter.php Tue Jul 10 15:07:59 2018 +0100 @@ -81,15 +81,24 @@ * {@inheritdoc} */ public function import(Row $row, array $old_destination_id_values = []) { + $nid = $row->getDestinationProperty('nid'); + $daycount = $row->getDestinationProperty('daycount'); + $totalcount = $row->getDestinationProperty('totalcount'); + $timestamp = $row->getDestinationProperty('timestamp'); + $this->connection - ->insert('node_counter') + ->merge('node_counter') + ->key('nid', $nid) ->fields([ - 'nid' => $row->getDestinationProperty('nid'), - 'daycount' => $row->getDestinationProperty('daycount'), - 'totalcount' => $row->getDestinationProperty('totalcount'), - 'timestamp' => $row->getDestinationProperty('timestamp'), + 'daycount' => $daycount, + 'totalcount' => $totalcount, + 'timestamp' => $timestamp, ]) + ->expression('daycount', 'daycount + :daycount', [':daycount' => $daycount]) + ->expression('totalcount', 'totalcount + :totalcount', [':totalcount' => $totalcount]) + ->expression('timestamp', 'CASE WHEN timestamp > :timestamp THEN timestamp ELSE :timestamp END', [':timestamp' => $timestamp]) ->execute(); + return [$row->getDestinationProperty('nid')]; } diff -r e200cb7efeb3 -r c2387f117808 core/modules/statistics/src/StatisticsViewsResult.php --- a/core/modules/statistics/src/StatisticsViewsResult.php Thu Apr 26 11:26:54 2018 +0100 +++ b/core/modules/statistics/src/StatisticsViewsResult.php Tue Jul 10 15:07:59 2018 +0100 @@ -23,9 +23,9 @@ protected $timestamp; public function __construct($total_count, $day_count, $timestamp) { - $this->totalCount = $total_count; - $this->dayCount = $day_count; - $this->timestamp = $timestamp; + $this->totalCount = (int) $total_count; + $this->dayCount = (int) $day_count; + $this->timestamp = (int) $timestamp; } /** diff -r e200cb7efeb3 -r c2387f117808 core/modules/statistics/statistics.module --- a/core/modules/statistics/statistics.module Thu Apr 26 11:26:54 2018 +0100 +++ b/core/modules/statistics/statistics.module Tue Jul 10 15:07:59 2018 +0100 @@ -41,7 +41,7 @@ function statistics_node_view(array &$build, EntityInterface $node, EntityViewDisplayInterface $display, $view_mode) { if (!$node->isNew() && $view_mode == 'full' && node_is_page($node) && empty($node->in_preview)) { $build['#attached']['library'][] = 'statistics/drupal.statistics'; - $settings = ['data' => ['nid' => $node->id()], 'url' => Url::fromUri('base:' . drupal_get_path('module', 'statistics') . '/statistics.php')->toString()]; + $settings = ['data' => ['nid' => $node->id()], 'url' => \Drupal::request()->getBasePath() . '/' . drupal_get_path('module', 'statistics') . '/statistics.php']; $build['#attached']['drupalSettings']['statistics'] = $settings; } } diff -r e200cb7efeb3 -r c2387f117808 core/modules/statistics/tests/src/Functional/StatisticsLoggingTest.php --- a/core/modules/statistics/tests/src/Functional/StatisticsLoggingTest.php Thu Apr 26 11:26:54 2018 +0100 +++ b/core/modules/statistics/tests/src/Functional/StatisticsLoggingTest.php Tue Jul 10 15:07:59 2018 +0100 @@ -125,7 +125,7 @@ $post = ['nid' => $this->node->id()]; $this->client->post($base_root . $stats_path, ['form_params' => $post]); $node_counter = statistics_get($this->node->id()); - $this->assertIdentical($node_counter['totalcount'], '1'); + $this->assertIdentical($node_counter['totalcount'], 1); // Try fetching statistics for an invalid node ID and verify it returns // FALSE. diff -r e200cb7efeb3 -r c2387f117808 core/modules/statistics/tests/src/FunctionalJavascript/StatisticsLoggingTest.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/core/modules/statistics/tests/src/FunctionalJavascript/StatisticsLoggingTest.php Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,87 @@ +config('statistics.settings') + ->set('count_content_views', 1) + ->save(); + + Role::load(AccountInterface::ANONYMOUS_ROLE) + ->grantPermission('view post access counter') + ->save(); + + // Add another language to enable multilingual path processor. + ConfigurableLanguage::create(['id' => 'xx'])->save(); + $this->config('language.negotiation')->set('url.prefixes.en', 'en')->save(); + + $this->drupalCreateContentType(['type' => 'page', 'name' => 'Basic page']); + $this->node = $this->drupalCreateNode(); + } + + /** + * Tests that statistics works with different addressing variants. + */ + public function testLoggingPage() { + // At the first request, the page does not contain statistics counter. + $this->assertNull($this->getStatisticsCounter('node/1')); + $this->assertSame(1, $this->getStatisticsCounter('node/1')); + $this->assertSame(2, $this->getStatisticsCounter('en/node/1')); + $this->assertSame(3, $this->getStatisticsCounter('en/node/1')); + $this->assertSame(4, $this->getStatisticsCounter('index.php/node/1')); + $this->assertSame(5, $this->getStatisticsCounter('index.php/node/1')); + $this->assertSame(6, $this->getStatisticsCounter('index.php/en/node/1')); + $this->assertSame(7, $this->getStatisticsCounter('index.php/en/node/1')); + } + + /** + * Gets counter of views by path. + * + * @param string $path + * A path to node. + * + * @return int|null + * A counter of views. Returns NULL if the page does not contain statistics. + */ + protected function getStatisticsCounter($path) { + $this->drupalGet($path); + // Wait while statistics module send ajax request. + $this->assertSession()->assertWaitOnAjaxRequest(); + // Resaving the node to call the hook_node_links_alter(), which is used to + // update information on the page. See statistics_node_links_alter(). + $this->node->save(); + + $field_counter = $this->getSession()->getPage()->find('css', '.statistics-counter'); + return $field_counter ? (int) explode(' ', $field_counter->getText())[0] : NULL; + } + +} diff -r e200cb7efeb3 -r c2387f117808 core/modules/statistics/tests/src/Kernel/Migrate/d6/MigrateNodeCounterTest.php --- a/core/modules/statistics/tests/src/Kernel/Migrate/d6/MigrateNodeCounterTest.php Thu Apr 26 11:26:54 2018 +0100 +++ b/core/modules/statistics/tests/src/Kernel/Migrate/d6/MigrateNodeCounterTest.php Tue Jul 10 15:07:59 2018 +0100 @@ -15,6 +15,8 @@ * {@inheritdoc} */ public static $modules = [ + 'content_translation', + 'language', 'menu_ui', 'node', 'statistics', @@ -29,16 +31,20 @@ $this->installEntitySchema('node'); $this->installConfig('node'); + $this->installSchema('node', ['node_access']); $this->installSchema('statistics', ['node_counter']); $this->executeMigrations([ + 'language', 'd6_filter_format', 'd6_user_role', 'd6_node_settings', 'd6_user', 'd6_node_type', + 'd6_language_content_settings', 'd6_node', - 'statistics_node_counter' + 'd6_node_translation', + 'statistics_node_counter', ]); } @@ -51,6 +57,13 @@ $this->assertNodeCounter(3, 1, 0, 1471428153); $this->assertNodeCounter(4, 1, 1, 1478755275); $this->assertNodeCounter(5, 1, 1, 1478755314); + $this->assertNodeCounter(10, 5, 1, 1521137459); + $this->assertNodeCounter(12, 3, 0, 1521137469); + + // Tests that translated node counts include all translation counts. + $this->executeMigration('statistics_node_translation_counter'); + $this->assertNodeCounter(10, 8, 2, 1521137463); + $this->assertNodeCounter(12, 5, 1, 1521137470); } /** diff -r e200cb7efeb3 -r c2387f117808 core/modules/statistics/tests/src/Kernel/Migrate/d7/MigrateNodeCounterTest.php --- a/core/modules/statistics/tests/src/Kernel/Migrate/d7/MigrateNodeCounterTest.php Thu Apr 26 11:26:54 2018 +0100 +++ b/core/modules/statistics/tests/src/Kernel/Migrate/d7/MigrateNodeCounterTest.php Tue Jul 10 15:07:59 2018 +0100 @@ -15,6 +15,8 @@ * {@inheritdoc} */ public static $modules = [ + 'content_translation', + 'language', 'menu_ui', 'node', 'statistics', @@ -29,14 +31,18 @@ $this->installEntitySchema('node'); $this->installConfig('node'); + $this->installSchema('node', ['node_access']); $this->installSchema('statistics', ['node_counter']); $this->executeMigrations([ + 'language', 'd7_user_role', 'd7_user', 'd7_node_type', + 'd7_language_content_settings', 'd7_node', - 'statistics_node_counter' + 'd7_node_translation', + 'statistics_node_counter', ]); } @@ -47,6 +53,11 @@ $this->assertNodeCounter(1, 2, 0, 1421727536); $this->assertNodeCounter(2, 1, 0, 1471428059); $this->assertNodeCounter(4, 1, 1, 1478755275); + + // Tests that translated node counts include all translation counts. + $this->executeMigration('statistics_node_translation_counter'); + $this->assertNodeCounter(2, 2, 0, 1471428153); + $this->assertNodeCounter(4, 2, 2, 1478755314); } /** diff -r e200cb7efeb3 -r c2387f117808 core/modules/statistics/tests/src/Unit/StatisticsViewsResultTest.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/core/modules/statistics/tests/src/Unit/StatisticsViewsResultTest.php Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,37 @@ +assertSame((int) $total_count, $statistics->getTotalCount()); + $this->assertSame((int) $day_count, $statistics->getDayCount()); + $this->assertSame((int) $timestamp, $statistics->getTimestamp()); + } + + public function providerTestStatisticsCount() { + return [ + [2, 0, 1421727536], + [1, 0, 1471428059], + [1, 1, 1478755275], + ['1', '1', '1478755275'], + ]; + } + +} diff -r e200cb7efeb3 -r c2387f117808 core/modules/system/src/Form/ThemeSettingsForm.php --- a/core/modules/system/src/Form/ThemeSettingsForm.php Thu Apr 26 11:26:54 2018 +0100 +++ b/core/modules/system/src/Form/ThemeSettingsForm.php Tue Jul 10 15:07:59 2018 +0100 @@ -377,22 +377,23 @@ parent::validateForm($form, $form_state); if ($this->moduleHandler->moduleExists('file')) { - $validators = ['file_validate_is_image' => []]; // Check for a new uploaded logo. - $file = _file_save_upload_from_form($form['logo']['settings']['logo_upload'], $form_state, 0); - if ($file) { - // Put the temporary file in form_values so we can save it on submit. - $form_state->setValue('logo_upload', $file); + if (isset($form['logo'])) { + $file = _file_save_upload_from_form($form['logo']['settings']['logo_upload'], $form_state, 0); + if ($file) { + // Put the temporary file in form_values so we can save it on submit. + $form_state->setValue('logo_upload', $file); + } } - $validators = ['file_validate_extensions' => ['ico png gif jpg jpeg apng svg']]; - // Check for a new uploaded favicon. - $file = _file_save_upload_from_form($form['favicon']['settings']['favicon_upload'], $form_state, 0); - if ($file) { - // Put the temporary file in form_values so we can save it on submit. - $form_state->setValue('favicon_upload', $file); + if (isset($form['favicon'])) { + $file = _file_save_upload_from_form($form['favicon']['settings']['favicon_upload'], $form_state, 0); + if ($file) { + // Put the temporary file in form_values so we can save it on submit. + $form_state->setValue('favicon_upload', $file); + } } // When intending to use the default logo, unset the logo_path. diff -r e200cb7efeb3 -r c2387f117808 core/modules/system/src/Plugin/migrate/source/Extension.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/core/modules/system/src/Plugin/migrate/source/Extension.php Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,66 @@ +select('system', 's') + ->fields('s'); + + if (isset($this->configuration['name'])) { + $query->condition('name', (array) $this->configuration['name'], 'IN'); + } + return $query; + } + + /** + * {@inheritdoc} + */ + public function fields() { + $fields = [ + 'filename' => $this->t('Filename'), + 'name' => $this->t('Name'), + 'type' => $this->t('Type'), + 'owner' => $this->t('Owner'), + 'status' => $this->t('Status'), + 'throttle' => $this->t('Throttle'), + 'bootstrap' => $this->t('Bootstrap'), + 'schema_version' => $this->t('Schema version'), + 'weight' => $this->t('Weight'), + 'info' => $this->t('Information array'), + ]; + return $fields; + } + + /** + * {@inheritdoc} + */ + public function prepareRow(Row $row) { + $row->setSourceProperty('info', unserialize($row->getSourceProperty('info'))); + return parent::prepareRow($row); + } + + /** + * {@inheritdoc} + */ + public function getIds() { + $ids['name']['type'] = 'string'; + return $ids; + } + +} diff -r e200cb7efeb3 -r c2387f117808 core/modules/system/src/SystemManager.php --- a/core/modules/system/src/SystemManager.php Thu Apr 26 11:26:54 2018 +0100 +++ b/core/modules/system/src/SystemManager.php Tue Jul 10 15:07:59 2018 +0100 @@ -152,7 +152,8 @@ * hidden, so we supply the contents of the block. * * @return array - * A render array suitable for drupal_render. + * A render array suitable for + * \Drupal\Core\Render\RendererInterface::render(). */ public function getBlockContents() { // We hard-code the menu name here since otherwise a link in the tools menu diff -r e200cb7efeb3 -r c2387f117808 core/modules/system/src/Tests/Common/AlterTest.php --- a/core/modules/system/src/Tests/Common/AlterTest.php Thu Apr 26 11:26:54 2018 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,72 +0,0 @@ -alter(). - * - * @group Common - */ -class AlterTest extends WebTestBase { - - /** - * Modules to enable. - * - * @var array - */ - public static $modules = ['block', 'common_test']; - - /** - * Tests if the theme has been altered. - */ - public function testDrupalAlter() { - // This test depends on Bartik, so make sure that it is always the current - // active theme. - \Drupal::service('theme_handler')->install(['bartik']); - \Drupal::theme()->setActiveTheme(\Drupal::service('theme.initialization')->initTheme('bartik')); - - $array = ['foo' => 'bar']; - $entity = new \stdClass(); - $entity->foo = 'bar'; - - // Verify alteration of a single argument. - $array_copy = $array; - $array_expected = ['foo' => 'Drupal theme']; - \Drupal::moduleHandler()->alter('drupal_alter', $array_copy); - \Drupal::theme()->alter('drupal_alter', $array_copy); - $this->assertEqual($array_copy, $array_expected, 'Single array was altered.'); - - $entity_copy = clone $entity; - $entity_expected = clone $entity; - $entity_expected->foo = 'Drupal theme'; - \Drupal::moduleHandler()->alter('drupal_alter', $entity_copy); - \Drupal::theme()->alter('drupal_alter', $entity_copy); - $this->assertEqual($entity_copy, $entity_expected, 'Single object was altered.'); - - // Verify alteration of multiple arguments. - $array_copy = $array; - $array_expected = ['foo' => 'Drupal theme']; - $entity_copy = clone $entity; - $entity_expected = clone $entity; - $entity_expected->foo = 'Drupal theme'; - $array2_copy = $array; - $array2_expected = ['foo' => 'Drupal theme']; - \Drupal::moduleHandler()->alter('drupal_alter', $array_copy, $entity_copy, $array2_copy); - \Drupal::theme()->alter('drupal_alter', $array_copy, $entity_copy, $array2_copy); - $this->assertEqual($array_copy, $array_expected, 'First argument to \Drupal::moduleHandler->alter() was altered.'); - $this->assertEqual($entity_copy, $entity_expected, 'Second argument to \Drupal::moduleHandler->alter() was altered.'); - $this->assertEqual($array2_copy, $array2_expected, 'Third argument to \Drupal::moduleHandler->alter() was altered.'); - - // Verify alteration order when passing an array of types to \Drupal::moduleHandler->alter(). - // common_test_module_implements_alter() places 'block' implementation after - // other modules. - $array_copy = $array; - $array_expected = ['foo' => 'Drupal block theme']; - \Drupal::moduleHandler()->alter(['drupal_alter', 'drupal_alter_foo'], $array_copy); - \Drupal::theme()->alter(['drupal_alter', 'drupal_alter_foo'], $array_copy); - $this->assertEqual($array_copy, $array_expected, 'hook_TYPE_alter() implementations ran in correct order.'); - } - -} diff -r e200cb7efeb3 -r c2387f117808 core/modules/system/src/Tests/Common/EarlyRenderingControllerTest.php --- a/core/modules/system/src/Tests/Common/EarlyRenderingControllerTest.php Thu Apr 26 11:26:54 2018 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,110 +0,0 @@ -drupalGet(Url::fromRoute('early_rendering_controller_test.render_array')); - $this->assertResponse(200); - $this->assertRaw('Hello world!'); - $this->assertCacheTag('foo'); - $this->drupalGet(Url::fromRoute('early_rendering_controller_test.render_array.early')); - $this->assertResponse(200); - $this->assertRaw('Hello world!'); - $this->assertCacheTag('foo'); - - // AjaxResponse: non-early & early. - // @todo Add cache tags assertion when AjaxResponse is made cacheable in - // https://www.drupal.org/node/956186. - $this->drupalGet(Url::fromRoute('early_rendering_controller_test.ajax_response')); - $this->assertResponse(200); - $this->assertRaw('Hello world!'); - $this->drupalGet(Url::fromRoute('early_rendering_controller_test.ajax_response.early')); - $this->assertResponse(200); - $this->assertRaw('Hello world!'); - - // Basic Response object: non-early & early. - $this->drupalGet(Url::fromRoute('early_rendering_controller_test.response')); - $this->assertResponse(200); - $this->assertRaw('Hello world!'); - $this->assertNoCacheTag('foo'); - $this->drupalGet(Url::fromRoute('early_rendering_controller_test.response.early')); - $this->assertResponse(200); - $this->assertRaw('Hello world!'); - $this->assertNoCacheTag('foo'); - - // Response object with attachments: non-early & early. - $this->drupalGet(Url::fromRoute('early_rendering_controller_test.response-with-attachments')); - $this->assertResponse(200); - $this->assertRaw('Hello world!'); - $this->assertNoCacheTag('foo'); - $this->drupalGet(Url::fromRoute('early_rendering_controller_test.response-with-attachments.early')); - $this->assertResponse(500); - $this->assertRaw('The controller result claims to be providing relevant cache metadata, but leaked metadata was detected. Please ensure you are not rendering content too early. Returned object class: Drupal\early_rendering_controller_test\AttachmentsTestResponse.'); - - // Cacheable Response object: non-early & early. - $this->drupalGet(Url::fromRoute('early_rendering_controller_test.cacheable-response')); - $this->assertResponse(200); - $this->assertRaw('Hello world!'); - $this->assertNoCacheTag('foo'); - $this->drupalGet(Url::fromRoute('early_rendering_controller_test.cacheable-response.early')); - $this->assertResponse(500); - $this->assertRaw('The controller result claims to be providing relevant cache metadata, but leaked metadata was detected. Please ensure you are not rendering content too early. Returned object class: Drupal\early_rendering_controller_test\CacheableTestResponse.'); - - // Basic domain object: non-early & early. - $this->drupalGet(Url::fromRoute('early_rendering_controller_test.domain-object')); - $this->assertResponse(200); - $this->assertRaw('TestDomainObject'); - $this->assertNoCacheTag('foo'); - $this->drupalGet(Url::fromRoute('early_rendering_controller_test.domain-object.early')); - $this->assertResponse(200); - $this->assertRaw('TestDomainObject'); - $this->assertNoCacheTag('foo'); - - // Basic domain object with attachments: non-early & early. - $this->drupalGet(Url::fromRoute('early_rendering_controller_test.domain-object-with-attachments')); - $this->assertResponse(200); - $this->assertRaw('AttachmentsTestDomainObject'); - $this->assertNoCacheTag('foo'); - $this->drupalGet(Url::fromRoute('early_rendering_controller_test.domain-object-with-attachments.early')); - $this->assertResponse(500); - $this->assertRaw('The controller result claims to be providing relevant cache metadata, but leaked metadata was detected. Please ensure you are not rendering content too early. Returned object class: Drupal\early_rendering_controller_test\AttachmentsTestDomainObject.'); - - // Cacheable Response object: non-early & early. - $this->drupalGet(Url::fromRoute('early_rendering_controller_test.cacheable-domain-object')); - $this->assertResponse(200); - $this->assertRaw('CacheableTestDomainObject'); - $this->assertNoCacheTag('foo'); - $this->drupalGet(Url::fromRoute('early_rendering_controller_test.cacheable-domain-object.early')); - $this->assertResponse(500); - $this->assertRaw('The controller result claims to be providing relevant cache metadata, but leaked metadata was detected. Please ensure you are not rendering content too early. Returned object class: Drupal\early_rendering_controller_test\CacheableTestDomainObject.'); - - // The exceptions are expected. Do not interpret them as a test failure. - // Not using File API; a potential error must trigger a PHP warning. - unlink(\Drupal::root() . '/' . $this->siteDirectory . '/error.log'); - } - -} diff -r e200cb7efeb3 -r c2387f117808 core/modules/system/src/Tests/Common/NoJavaScriptAnonymousTest.php --- a/core/modules/system/src/Tests/Common/NoJavaScriptAnonymousTest.php Thu Apr 26 11:26:54 2018 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,67 +0,0 @@ -drupalCreateNode([ - 'promote' => NodeInterface::PROMOTED, - ]); - $user = $this->drupalCreateUser(); - - // Test frontpage. - $this->drupalGet(''); - $this->assertNoJavaScriptExceptHtml5Shiv(); - - // Test node page. - $this->drupalGet('node/1'); - $this->assertNoJavaScriptExceptHtml5Shiv(); - - // Test user profile page. - $this->drupalGet('user/' . $user->id()); - $this->assertNoJavaScriptExceptHtml5Shiv(); - } - - /** - * Passes if no JavaScript is found on the page except the HTML5 shiv. - * - * The HTML5 shiv is necessary for e.g. the
    tag which Drupal 8 uses - * to work in older browsers like Internet Explorer 8. - */ - protected function assertNoJavaScriptExceptHtml5Shiv() { - // Ensure drupalSettings is not set. - $settings = $this->getDrupalSettings(); - $this->assertTrue(empty($settings), 'drupalSettings is not set.'); - - // Ensure the HTML5 shiv exists. - $this->assertRaw('html5shiv/html5shiv.min.js', 'HTML5 shiv JavaScript exists.'); - - // Ensure no other JavaScript file exists on the page, while ignoring the - // HTML5 shiv. - $this->assertNoPattern('/(?randomMachineName(); - $path = ""; - $encoded_path = "3CSCRIPT%3Ealert%28%27XSS%27%29%3C/SCRIPT%3E"; - - $link = \Drupal::l($text, Url::fromUserInput('/' . $path)); - $this->assertTrue(strpos($link, $encoded_path) !== FALSE && strpos($link, $path) === FALSE, format_string('XSS attack @path was filtered by \Drupal\Core\Utility\LinkGeneratorInterface::generate().', ['@path' => $path])); - - // Test \Drupal\Core\Url. - $link = Url::fromUri('base:' . $path)->toString(); - $this->assertTrue(strpos($link, $encoded_path) !== FALSE && strpos($link, $path) === FALSE, format_string('XSS attack @path was filtered by #theme', ['@path' => $path])); - } - - /** - * Tests that #type=link bubbles outbound route/path processors' metadata. - */ - public function testLinkBubbleableMetadata() { - $cases = [ - ['Regular link', 'internal:/user', [], ['contexts' => [], 'tags' => [], 'max-age' => Cache::PERMANENT], []], - ['Regular link, absolute', 'internal:/user', ['absolute' => TRUE], ['contexts' => ['url.site'], 'tags' => [], 'max-age' => Cache::PERMANENT], []], - ['Route processor link', 'route:system.run_cron', [], ['contexts' => ['session'], 'tags' => [], 'max-age' => Cache::PERMANENT], ['placeholders' => []]], - ['Route processor link, absolute', 'route:system.run_cron', ['absolute' => TRUE], ['contexts' => ['url.site', 'session'], 'tags' => [], 'max-age' => Cache::PERMANENT], ['placeholders' => []]], - ['Path processor link', 'internal:/user/1', [], ['contexts' => [], 'tags' => ['user:1'], 'max-age' => Cache::PERMANENT], []], - ['Path processor link, absolute', 'internal:/user/1', ['absolute' => TRUE], ['contexts' => ['url.site'], 'tags' => ['user:1'], 'max-age' => Cache::PERMANENT], []], - ]; - - foreach ($cases as $case) { - list($title, $uri, $options, $expected_cacheability, $expected_attachments) = $case; - $expected_cacheability['contexts'] = Cache::mergeContexts($expected_cacheability['contexts'], ['languages:language_interface', 'theme', 'user.permissions']); - $link = [ - '#type' => 'link', - '#title' => $title, - '#options' => $options, - '#url' => Url::fromUri($uri), - ]; - \Drupal::service('renderer')->renderRoot($link); - $this->pass($title); - $this->assertEqual($expected_cacheability, $link['#cache']); - $this->assertEqual($expected_attachments, $link['#attached']); - } - } - - /** - * Tests that default and custom attributes are handled correctly on links. - */ - public function testLinkAttributes() { - /** @var \Drupal\Core\Render\RendererInterface $renderer */ - $renderer = $this->container->get('renderer'); - - // Test that hreflang is added when a link has a known language. - $language = new Language(['id' => 'fr', 'name' => 'French']); - $hreflang_link = [ - '#type' => 'link', - '#options' => [ - 'language' => $language, - ], - '#url' => Url::fromUri('https://www.drupal.org'), - '#title' => 'bar', - ]; - $langcode = $language->getId(); - - // Test that the default hreflang handling for links does not override a - // hreflang attribute explicitly set in the render array. - $hreflang_override_link = $hreflang_link; - $hreflang_override_link['#options']['attributes']['hreflang'] = 'foo'; - - $rendered = $renderer->renderRoot($hreflang_link); - $this->assertTrue($this->hasAttribute('hreflang', $rendered, $langcode), format_string('hreflang attribute with value @langcode is present on a rendered link when langcode is provided in the render array.', ['@langcode' => $langcode])); - - $rendered = $renderer->renderRoot($hreflang_override_link); - $this->assertTrue($this->hasAttribute('hreflang', $rendered, 'foo'), format_string('hreflang attribute with value @hreflang is present on a rendered link when @hreflang is provided in the render array.', ['@hreflang' => 'foo'])); - - // Test the active class in links produced by - // \Drupal\Core\Utility\LinkGeneratorInterface::generate() and #type 'link'. - $options_no_query = []; - $options_query = [ - 'query' => [ - 'foo' => 'bar', - 'one' => 'two', - ], - ]; - $options_query_reverse = [ - 'query' => [ - 'one' => 'two', - 'foo' => 'bar', - ], - ]; - - // Test #type link. - $path = 'common-test/type-link-active-class'; - - $this->drupalGet($path, $options_no_query); - $links = $this->xpath('//a[@href = :href and contains(@class, :class)]', [':href' => Url::fromRoute('common_test.l_active_class', [], $options_no_query)->toString(), ':class' => 'is-active']); - $this->assertTrue(isset($links[0]), 'A link generated by the link generator to the current page is marked active.'); - - $links = $this->xpath('//a[@href = :href and not(contains(@class, :class))]', [':href' => Url::fromRoute('common_test.l_active_class', [], $options_query)->toString(), ':class' => 'is-active']); - $this->assertTrue(isset($links[0]), 'A link generated by the link generator to the current page with a query string when the current page has no query string is not marked active.'); - - $this->drupalGet($path, $options_query); - $links = $this->xpath('//a[@href = :href and contains(@class, :class)]', [':href' => Url::fromRoute('common_test.l_active_class', [], $options_query)->toString(), ':class' => 'is-active']); - $this->assertTrue(isset($links[0]), 'A link generated by the link generator to the current page with a query string that matches the current query string is marked active.'); - - $links = $this->xpath('//a[@href = :href and contains(@class, :class)]', [':href' => Url::fromRoute('common_test.l_active_class', [], $options_query_reverse)->toString(), ':class' => 'is-active']); - $this->assertTrue(isset($links[0]), 'A link generated by the link generator to the current page with a query string that has matching parameters to the current query string but in a different order is marked active.'); - - $links = $this->xpath('//a[@href = :href and not(contains(@class, :class))]', [':href' => Url::fromRoute('common_test.l_active_class', [], $options_no_query)->toString(), ':class' => 'is-active']); - $this->assertTrue(isset($links[0]), 'A link generated by the link generator to the current page without a query string when the current page has a query string is not marked active.'); - - // Test adding a custom class in links produced by - // \Drupal\Core\Utility\LinkGeneratorInterface::generate() and #type 'link'. - // Test the link generator. - $class_l = $this->randomMachineName(); - $link_l = \Drupal::l($this->randomMachineName(), new Url('', [], ['attributes' => ['class' => [$class_l]]])); - $this->assertTrue($this->hasAttribute('class', $link_l, $class_l), format_string('Custom class @class is present on link when requested by l()', ['@class' => $class_l])); - - // Test #type. - $class_theme = $this->randomMachineName(); - $type_link = [ - '#type' => 'link', - '#title' => $this->randomMachineName(), - '#url' => Url::fromRoute(''), - '#options' => [ - 'attributes' => [ - 'class' => [$class_theme], - ], - ], - ]; - $link_theme = $renderer->renderRoot($type_link); - $this->assertTrue($this->hasAttribute('class', $link_theme, $class_theme), format_string('Custom class @class is present on link when requested by #type', ['@class' => $class_theme])); - } - - /** - * Tests that link functions support render arrays as 'text'. - */ - public function testLinkRenderArrayText() { - /** @var \Drupal\Core\Render\RendererInterface $renderer */ - $renderer = $this->container->get('renderer'); - - // Build a link with the link generator for reference. - $l = \Drupal::l('foo', Url::fromUri('https://www.drupal.org')); - - // Test a renderable array passed to the link generator. - $renderer->executeInRenderContext(new RenderContext(), function () use ($renderer, $l) { - $renderable_text = ['#markup' => 'foo']; - $l_renderable_text = \Drupal::l($renderable_text, Url::fromUri('https://www.drupal.org')); - $this->assertEqual($l_renderable_text, $l); - }); - - // Test a themed link with plain text 'text'. - $type_link_plain_array = [ - '#type' => 'link', - '#title' => 'foo', - '#url' => Url::fromUri('https://www.drupal.org'), - ]; - $type_link_plain = $renderer->renderRoot($type_link_plain_array); - $this->assertEqual($type_link_plain, $l); - - // Build a themed link with renderable 'text'. - $type_link_nested_array = [ - '#type' => 'link', - '#title' => ['#markup' => 'foo'], - '#url' => Url::fromUri('https://www.drupal.org'), - ]; - $type_link_nested = $renderer->renderRoot($type_link_nested_array); - $this->assertEqual($type_link_nested, $l); - } - - /** - * Checks for class existence in link. - * - * @param $link - * URL to search. - * @param $class - * Element class to search for. - * - * @return bool - * TRUE if the class is found, FALSE otherwise. - */ - private function hasAttribute($attribute, $link, $class) { - return preg_match('|' . $attribute . '="([^\"\s]+\s+)*' . $class . '|', $link); - } - - /** - * Tests UrlHelper::filterQueryParameters(). - */ - public function testDrupalGetQueryParameters() { - $original = [ - 'a' => 1, - 'b' => [ - 'd' => 4, - 'e' => [ - 'f' => 5, - ], - ], - 'c' => 3, - ]; - - // First-level exclusion. - $result = $original; - unset($result['b']); - $this->assertEqual(UrlHelper::filterQueryParameters($original, ['b']), $result, "'b' was removed."); - - // Second-level exclusion. - $result = $original; - unset($result['b']['d']); - $this->assertEqual(UrlHelper::filterQueryParameters($original, ['b[d]']), $result, "'b[d]' was removed."); - - // Third-level exclusion. - $result = $original; - unset($result['b']['e']['f']); - $this->assertEqual(UrlHelper::filterQueryParameters($original, ['b[e][f]']), $result, "'b[e][f]' was removed."); - - // Multiple exclusions. - $result = $original; - unset($result['a'], $result['b']['e'], $result['c']); - $this->assertEqual(UrlHelper::filterQueryParameters($original, ['a', 'b[e]', 'c']), $result, "'a', 'b[e]', 'c' were removed."); - } - - /** - * Tests UrlHelper::parse(). - */ - public function testDrupalParseUrl() { - // Relative, absolute, and external URLs, without/with explicit script path, - // without/with Drupal path. - foreach (['', '/', 'https://www.drupal.org/'] as $absolute) { - foreach (['', 'index.php/'] as $script) { - foreach (['', 'foo/bar'] as $path) { - $url = $absolute . $script . $path . '?foo=bar&bar=baz&baz#foo'; - $expected = [ - 'path' => $absolute . $script . $path, - 'query' => ['foo' => 'bar', 'bar' => 'baz', 'baz' => ''], - 'fragment' => 'foo', - ]; - $this->assertEqual(UrlHelper::parse($url), $expected, 'URL parsed correctly.'); - } - } - } - - // Relative URL that is known to confuse parse_url(). - $url = 'foo/bar:1'; - $result = [ - 'path' => 'foo/bar:1', - 'query' => [], - 'fragment' => '', - ]; - $this->assertEqual(UrlHelper::parse($url), $result, 'Relative URL parsed correctly.'); - - // Test that drupal can recognize an absolute URL. Used to prevent attack vectors. - $url = 'https://www.drupal.org/foo/bar?foo=bar&bar=baz&baz#foo'; - $this->assertTrue(UrlHelper::isExternal($url), 'Correctly identified an external URL.'); - - // Test that UrlHelper::parse() does not allow spoofing a URL to force a malicious redirect. - $parts = UrlHelper::parse('forged:http://cwe.mitre.org/data/definitions/601.html'); - $this->assertFalse(UrlHelper::isValid($parts['path'], TRUE), '\Drupal\Component\Utility\UrlHelper::isValid() correctly parsed a forged URL.'); - } - - /** - * Tests external URL handling. - */ - public function testExternalUrls() { - $test_url = 'https://www.drupal.org/'; - - // Verify external URL can contain a fragment. - $url = $test_url . '#drupal'; - $result = Url::fromUri($url)->toString(); - $this->assertEqual($url, $result, 'External URL with fragment works without a fragment in $options.'); - - // Verify fragment can be overridden in an external URL. - $url = $test_url . '#drupal'; - $fragment = $this->randomMachineName(10); - $result = Url::fromUri($url, ['fragment' => $fragment])->toString(); - $this->assertEqual($test_url . '#' . $fragment, $result, 'External URL fragment is overridden with a custom fragment in $options.'); - - // Verify external URL can contain a query string. - $url = $test_url . '?drupal=awesome'; - $result = Url::fromUri($url)->toString(); - $this->assertEqual($url, $result); - - // Verify external URL can be extended with a query string. - $url = $test_url; - $query = [$this->randomMachineName(5) => $this->randomMachineName(5)]; - $result = Url::fromUri($url, ['query' => $query])->toString(); - $this->assertEqual($url . '?' . http_build_query($query, '', '&'), $result, 'External URL can be extended with a query string in $options.'); - - // Verify query string can be extended in an external URL. - $url = $test_url . '?drupal=awesome'; - $query = [$this->randomMachineName(5) => $this->randomMachineName(5)]; - $result = Url::fromUri($url, ['query' => $query])->toString(); - $this->assertEqual($url . '&' . http_build_query($query, '', '&'), $result); - } - -} diff -r e200cb7efeb3 -r c2387f117808 core/modules/system/src/Tests/Entity/EntityUnitTestBase.php --- a/core/modules/system/src/Tests/Entity/EntityUnitTestBase.php Thu Apr 26 11:26:54 2018 +0100 +++ b/core/modules/system/src/Tests/Entity/EntityUnitTestBase.php Tue Jul 10 15:07:59 2018 +0100 @@ -2,6 +2,8 @@ namespace Drupal\system\Tests\Entity; +@trigger_error(__FILE__ . ' is deprecated in Drupal 8.1.0 and will be removed before Drupal 9.0.0. Use \Drupal\KernelTests\Core\Entity\EntityKernelTestBase instead.', E_USER_DEPRECATED); + use Drupal\simpletest\KernelTestBase; use Drupal\Core\Entity\EntityInterface; use Drupal\user\Entity\Role; @@ -10,7 +12,7 @@ /** * Defines an abstract test base for entity unit tests. * - * @deprecated in Drupal 8.1.x, will be removed before Drupal 8.2.x. Use + * @deprecated in Drupal 8.1.0, will be removed before Drupal 9.0.0. Use * \Drupal\KernelTests\Core\Entity\EntityKernelTestBase instead. */ abstract class EntityUnitTestBase extends KernelTestBase { diff -r e200cb7efeb3 -r c2387f117808 core/modules/system/src/Tests/Installer/DistributionProfileExistingSettingsTest.php --- a/core/modules/system/src/Tests/Installer/DistributionProfileExistingSettingsTest.php Thu Apr 26 11:26:54 2018 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,131 +0,0 @@ -info = [ - 'type' => 'profile', - 'core' => \Drupal::CORE_COMPATIBILITY, - 'name' => 'Distribution profile', - 'distribution' => [ - 'name' => 'My Distribution', - 'install' => [ - 'theme' => 'bartik', - ], - ], - ]; - // File API functions are not available yet. - $path = $this->siteDirectory . '/profiles/mydistro'; - mkdir($path, 0777, TRUE); - file_put_contents("$path/mydistro.info.yml", Yaml::encode($this->info)); - - // Pre-configure hash salt. - // Any string is valid, so simply use the class name of this test. - $this->settings['settings']['hash_salt'] = (object) [ - 'value' => __CLASS__, - 'required' => TRUE, - ]; - - // Pre-configure database credentials. - $connection_info = Database::getConnectionInfo(); - unset($connection_info['default']['pdo']); - unset($connection_info['default']['init_commands']); - - $this->settings['databases']['default'] = (object) [ - 'value' => $connection_info, - 'required' => TRUE, - ]; - - // Use the kernel to find the site path because the site.path service should - // not be available at this point in the install process. - $site_path = DrupalKernel::findSitePath(Request::createFromGlobals()); - // Pre-configure config directories. - $this->settings['config_directories'] = [ - CONFIG_SYNC_DIRECTORY => (object) [ - 'value' => $site_path . '/files/config_staging', - 'required' => TRUE, - ], - ]; - mkdir($this->settings['config_directories'][CONFIG_SYNC_DIRECTORY]->value, 0777, TRUE); - parent::setUp(); - } - - /** - * {@inheritdoc} - */ - protected function setUpLanguage() { - // Make settings file not writable. - $filename = $this->siteDirectory . '/settings.php'; - // Make the settings file read-only. - // Not using File API; a potential error must trigger a PHP warning. - chmod($filename, 0444); - - // Verify that the distribution name appears. - $this->assertRaw($this->info['distribution']['name']); - // Verify that the requested theme is used. - $this->assertRaw($this->info['distribution']['install']['theme']); - // Verify that the "Choose profile" step does not appear. - $this->assertNoText('profile'); - - parent::setUpLanguage(); - } - - /** - * {@inheritdoc} - */ - protected function setUpProfile() { - // This step is skipped, because there is a distribution profile. - } - - /** - * {@inheritdoc} - */ - protected function setUpSettings() { - // This step should not appear, since settings.php is fully configured - // already. - } - - /** - * Confirms that the installation succeeded. - */ - public function testInstalled() { - $this->assertUrl('user/1'); - $this->assertResponse(200); - // Confirm that we are logged-in after installation. - $this->assertText($this->rootUser->getUsername()); - - // Confirm that Drupal recognizes this distribution as the current profile. - $this->assertEqual(\Drupal::installProfile(), 'mydistro'); - $this->assertNull(Settings::get('install_profile'), 'The install profile has not been written to settings.php.'); - $this->assertEqual($this->config('core.extension')->get('profile'), 'mydistro', 'The install profile has been written to core.extension configuration.'); - - $this->rebuildContainer(); - $this->pass('Container can be rebuilt even though distribution is not written to settings.php.'); - $this->assertEqual(\Drupal::installProfile(), 'mydistro'); - } - -} diff -r e200cb7efeb3 -r c2387f117808 core/modules/system/src/Tests/Installer/DistributionProfileTest.php --- a/core/modules/system/src/Tests/Installer/DistributionProfileTest.php Thu Apr 26 11:26:54 2018 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,81 +0,0 @@ -info = [ - 'type' => 'profile', - 'core' => \Drupal::CORE_COMPATIBILITY, - 'name' => 'Distribution profile', - 'distribution' => [ - 'name' => 'My Distribution', - 'install' => [ - 'theme' => 'bartik', - ], - ], - ]; - // File API functions are not available yet. - $path = $this->siteDirectory . '/profiles/mydistro'; - mkdir($path, 0777, TRUE); - file_put_contents("$path/mydistro.info.yml", Yaml::encode($this->info)); - - parent::setUp(); - } - - /** - * {@inheritdoc} - */ - protected function setUpLanguage() { - // Verify that the distribution name appears. - $this->assertRaw($this->info['distribution']['name']); - // Verify that the distribution name is used in the site title. - $this->assertTitle('Choose language | ' . $this->info['distribution']['name']); - // Verify that the requested theme is used. - $this->assertRaw($this->info['distribution']['install']['theme']); - // Verify that the "Choose profile" step does not appear. - $this->assertNoText('profile'); - - parent::setUpLanguage(); - } - - /** - * {@inheritdoc} - */ - protected function setUpProfile() { - // This step is skipped, because there is a distribution profile. - } - - /** - * Confirms that the installation succeeded. - */ - public function testInstalled() { - $this->assertUrl('user/1'); - $this->assertResponse(200); - // Confirm that we are logged-in after installation. - $this->assertText($this->rootUser->getUsername()); - - // Confirm that Drupal recognizes this distribution as the current profile. - $this->assertEqual(\Drupal::installProfile(), 'mydistro'); - $this->assertEqual(Settings::get('install_profile'), 'mydistro', 'The install profile has been written to settings.php.'); - $this->assertEqual($this->config('core.extension')->get('profile'), 'mydistro', 'The install profile has been written to core.extension configuration.'); - } - -} diff -r e200cb7efeb3 -r c2387f117808 core/modules/system/src/Tests/Installer/DistributionProfileTranslationQueryTest.php --- a/core/modules/system/src/Tests/Installer/DistributionProfileTranslationQueryTest.php Thu Apr 26 11:26:54 2018 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,142 +0,0 @@ -info = [ - 'type' => 'profile', - 'core' => \Drupal::CORE_COMPATIBILITY, - 'name' => 'Distribution profile', - 'distribution' => [ - 'name' => 'My Distribution', - 'langcode' => $this->langcode, - 'install' => [ - 'theme' => 'bartik', - ], - ], - ]; - // File API functions are not available yet. - $path = $this->siteDirectory . '/profiles/mydistro'; - mkdir($path, 0777, TRUE); - file_put_contents("$path/mydistro.info.yml", Yaml::encode($this->info)); - - parent::setUp(); - } - - /** - * {@inheritdoc} - */ - protected function visitInstaller() { - // Place a custom local translation in the translations directory. - mkdir(\Drupal::root() . '/' . $this->siteDirectory . '/files/translations', 0777, TRUE); - file_put_contents(\Drupal::root() . '/' . $this->siteDirectory . '/files/translations/drupal-8.0.0.de.po', $this->getPo('de')); - file_put_contents(\Drupal::root() . '/' . $this->siteDirectory . '/files/translations/drupal-8.0.0.fr.po', $this->getPo('fr')); - - // Pass a different language code than the one set in the distribution - // profile. This distribution language should still be used. - // The unrouted URL assembler does not exist at this point, so we build the - // URL ourselves. - $this->drupalGet($GLOBALS['base_url'] . '/core/install.php' . '?langcode=fr'); - } - - /** - * {@inheritdoc} - */ - protected function setUpLanguage() { - // This step is skipped, because the distribution profile uses a fixed - // language. - } - - /** - * {@inheritdoc} - */ - protected function setUpProfile() { - // This step is skipped, because there is a distribution profile. - } - - /** - * {@inheritdoc} - */ - protected function setUpSettings() { - // The language should have been automatically detected, all following - // screens should be translated already. - $elements = $this->xpath('//input[@type="submit"]/@value'); - $this->assertEqual((string) current($elements), 'Save and continue de'); - $this->translations['Save and continue'] = 'Save and continue de'; - - // Check the language direction. - $direction = (string) current($this->xpath('/html/@dir')); - $this->assertEqual($direction, 'ltr'); - - // Verify that the distribution name appears. - $this->assertRaw($this->info['distribution']['name']); - // Verify that the requested theme is used. - $this->assertRaw($this->info['distribution']['install']['theme']); - // Verify that the "Choose profile" step does not appear. - $this->assertNoText('profile'); - - parent::setUpSettings(); - } - - /** - * Confirms that the installation succeeded. - */ - public function testInstalled() { - $this->assertUrl('user/1'); - $this->assertResponse(200); - - // Confirm that we are logged-in after installation. - $this->assertText($this->rootUser->getDisplayName()); - - // Verify German was configured but not English. - $this->drupalGet('admin/config/regional/language'); - $this->assertText('German'); - $this->assertNoText('English'); - } - - /** - * Returns the string for the test .po file. - * - * @param string $langcode - * The language code. - * @return string - * Contents for the test .po file. - */ - protected function getPo($langcode) { - return <<info = [ - 'type' => 'profile', - 'core' => \Drupal::CORE_COMPATIBILITY, - 'name' => 'Distribution profile', - 'distribution' => [ - 'name' => 'My Distribution', - 'langcode' => $this->langcode, - 'install' => [ - 'theme' => 'bartik', - ], - ], - ]; - // File API functions are not available yet. - $path = $this->siteDirectory . '/profiles/mydistro'; - mkdir($path, 0777, TRUE); - file_put_contents("$path/mydistro.info.yml", Yaml::encode($this->info)); - - parent::setUp(); - } - - /** - * {@inheritdoc} - */ - protected function visitInstaller() { - // Place a custom local translation in the translations directory. - mkdir(\Drupal::root() . '/' . $this->siteDirectory . '/files/translations', 0777, TRUE); - file_put_contents(\Drupal::root() . '/' . $this->siteDirectory . '/files/translations/drupal-8.0.0.de.po', $this->getPo('de')); - - parent::visitInstaller(); - } - - /** - * {@inheritdoc} - */ - protected function setUpLanguage() { - // This step is skipped, because the distribution profile uses a fixed - // language. - } - - /** - * {@inheritdoc} - */ - protected function setUpProfile() { - // This step is skipped, because there is a distribution profile. - } - - /** - * {@inheritdoc} - */ - protected function setUpSettings() { - // The language should have been automatically detected, all following - // screens should be translated already. - $elements = $this->xpath('//input[@type="submit"]/@value'); - $this->assertEqual((string) current($elements), 'Save and continue de'); - $this->translations['Save and continue'] = 'Save and continue de'; - - // Check the language direction. - $direction = (string) current($this->xpath('/html/@dir')); - $this->assertEqual($direction, 'ltr'); - - // Verify that the distribution name appears. - $this->assertRaw($this->info['distribution']['name']); - // Verify that the requested theme is used. - $this->assertRaw($this->info['distribution']['install']['theme']); - // Verify that the "Choose profile" step does not appear. - $this->assertNoText('profile'); - - parent::setUpSettings(); - } - - - /** - * Confirms that the installation succeeded. - */ - public function testInstalled() { - $this->assertUrl('user/1'); - $this->assertResponse(200); - - // Confirm that we are logged-in after installation. - $this->assertText($this->rootUser->getDisplayName()); - - // Verify German was configured but not English. - $this->drupalGet('admin/config/regional/language'); - $this->assertText('German'); - $this->assertNoText('English'); - } - - /** - * Returns the string for the test .po file. - * - * @param string $langcode - * The language code. - * @return string - * Contents for the test .po file. - */ - protected function getPo($langcode) { - return <<configDirectory = $this->publicFilesDirectory . '/config_' . Crypt::randomBytesBase64(); - $this->settings['config_directories'][CONFIG_SYNC_DIRECTORY] = (object) [ - 'value' => $this->configDirectory . '/sync', - 'required' => TRUE, - ]; - // Create the files directory early so we can test the error case. - mkdir($this->publicFilesDirectory); - // Create a file so the directory can not be created. - file_put_contents($this->configDirectory, 'Test'); - parent::setUp(); - } - - /** - * Installer step: Configure settings. - */ - protected function setUpSettings() { - // This step should not appear as we had a failure prior to the settings - // screen. - } - - /** - * {@inheritdoc} - */ - protected function setUpSite() { - // This step should not appear as we had a failure prior to the settings - // screen. - } - - /** - * Verifies that installation failed. - */ - public function testError() { - $this->assertText("An automated attempt to create the directory {$this->configDirectory}/sync failed, possibly due to a permissions problem."); - $this->assertFalse(file_exists($this->configDirectory . '/sync') && is_dir($this->configDirectory . '/sync'), "The directory {$this->configDirectory}/sync does not exist."); - } - -} diff -r e200cb7efeb3 -r c2387f117808 core/modules/system/src/Tests/Installer/InstallerConfigDirectorySetNoDirectoryTest.php --- a/core/modules/system/src/Tests/Installer/InstallerConfigDirectorySetNoDirectoryTest.php Thu Apr 26 11:26:54 2018 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,49 +0,0 @@ -syncDirectory = $this->publicFilesDirectory . '/config_' . Crypt::randomBytesBase64() . '/sync'; - $this->settings['config_directories'][CONFIG_SYNC_DIRECTORY] = (object) [ - 'value' => $this->syncDirectory, - 'required' => TRUE, - ]; - // Other directories will be created too. - $this->settings['config_directories']['custom'] = (object) [ - 'value' => $this->publicFilesDirectory . '/config_custom', - 'required' => TRUE, - ]; - parent::setUp(); - } - - /** - * Verifies that installation succeeded. - */ - public function testInstaller() { - $this->assertUrl('user/1'); - $this->assertResponse(200); - $this->assertTrue(file_exists($this->syncDirectory) && is_dir($this->syncDirectory), "The directory {$this->syncDirectory} exists."); - $this->assertTrue(file_exists($this->publicFilesDirectory . '/config_custom') && is_dir($this->publicFilesDirectory . '/config_custom'), "The directory {$this->publicFilesDirectory}/custom_config exists."); - } - -} diff -r e200cb7efeb3 -r c2387f117808 core/modules/system/src/Tests/Installer/InstallerDatabaseErrorMessagesTest.php --- a/core/modules/system/src/Tests/Installer/InstallerDatabaseErrorMessagesTest.php Thu Apr 26 11:26:54 2018 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,41 +0,0 @@ -query('CREATE TABLE {drupal_install_test} (id int NULL)'); - parent::setUpSettings(); - } - - /** - * {@inheritdoc} - */ - protected function setUpSite() { - // This step should not appear as we had a failure on the settings screen. - } - - /** - * Verifies that the error message in the settings step is correct. - */ - public function testSetUpSettingsErrorMessage() { - $this->assertRaw('
    • Failed to CREATE a test table'); - } - -} diff -r e200cb7efeb3 -r c2387f117808 core/modules/system/src/Tests/Installer/InstallerEmptySettingsTest.php --- a/core/modules/system/src/Tests/Installer/InstallerEmptySettingsTest.php Thu Apr 26 11:26:54 2018 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,31 +0,0 @@ -siteDirectory . '/settings.php'); - parent::setUp(); - } - - /** - * Verifies that installation succeeded. - */ - public function testInstaller() { - $this->assertUrl('user/1'); - $this->assertResponse(200); - } - -} diff -r e200cb7efeb3 -r c2387f117808 core/modules/system/src/Tests/Installer/InstallerExistingConfigDirectoryTest.php --- a/core/modules/system/src/Tests/Installer/InstallerExistingConfigDirectoryTest.php Thu Apr 26 11:26:54 2018 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,44 +0,0 @@ -siteDirectory . '/config_read_only', 0444); - $this->expectedFilePerms = fileperms($this->siteDirectory . '/config_read_only'); - $this->settings['config_directories'][CONFIG_SYNC_DIRECTORY] = (object) [ - 'value' => $this->siteDirectory . '/config_read_only', - 'required' => TRUE, - ]; - parent::setUp(); - } - - /** - * Verifies that installation succeeded. - */ - public function testInstaller() { - $this->assertUrl('user/1'); - $this->assertResponse(200); - $this->assertEqual($this->expectedFilePerms, fileperms($this->siteDirectory . '/config_read_only')); - $this->assertEqual([], glob($this->siteDirectory . '/config_read_only/*'), 'The sync directory is empty after install because it is read-only.'); - } - -} diff -r e200cb7efeb3 -r c2387f117808 core/modules/system/src/Tests/Installer/InstallerExistingDatabaseSettingsTest.php --- a/core/modules/system/src/Tests/Installer/InstallerExistingDatabaseSettingsTest.php Thu Apr 26 11:26:54 2018 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,62 +0,0 @@ -settings['databases']['default'] = (object) [ - 'value' => $connection_info, - 'required' => TRUE, - ]; - parent::setUp(); - } - - /** - * {@inheritdoc} - * - * @todo The database settings form is not supposed to appear if settings.php - * contains a valid database connection already (but e.g. no config - * directories yet). - */ - protected function setUpSettings() { - // All database settings should be pre-configured, except password. - $values = $this->parameters['forms']['install_settings_form']; - $driver = $values['driver']; - $edit = []; - if (isset($values[$driver]['password']) && $values[$driver]['password'] !== '') { - $edit = $this->translatePostValues([ - $driver => [ - 'password' => $values[$driver]['password'], - ], - ]); - } - $this->drupalPostForm(NULL, $edit, $this->translations['Save and continue']); - } - - /** - * Verifies that installation succeeded. - */ - public function testInstaller() { - $this->assertUrl('user/1'); - $this->assertResponse(200); - } - -} diff -r e200cb7efeb3 -r c2387f117808 core/modules/system/src/Tests/Installer/InstallerExistingInstallationTest.php --- a/core/modules/system/src/Tests/Installer/InstallerExistingInstallationTest.php Thu Apr 26 11:26:54 2018 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,40 +0,0 @@ -visitInstaller(); - $this->assertRaw('Drupal already installed'); - - // Delete settings.php and attempt to reinstall again. - unlink($this->siteDirectory . '/settings.php'); - $this->visitInstaller(); - $this->setUpLanguage(); - $this->setUpProfile(); - $this->setUpRequirementsProblem(); - $this->setUpSettings(); - $this->assertRaw('Drupal already installed'); - } - -} diff -r e200cb7efeb3 -r c2387f117808 core/modules/system/src/Tests/Installer/InstallerExistingSettingsMismatchProfileBrokenTest.php --- a/core/modules/system/src/Tests/Installer/InstallerExistingSettingsMismatchProfileBrokenTest.php Thu Apr 26 11:26:54 2018 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,108 +0,0 @@ -settings['settings']['hash_salt'] = (object) [ - 'value' => __CLASS__, - 'required' => TRUE, - ]; - - // Pre-configure database credentials. - $connection_info = Database::getConnectionInfo(); - unset($connection_info['default']['pdo']); - unset($connection_info['default']['init_commands']); - - $this->settings['databases']['default'] = (object) [ - 'value' => $connection_info, - 'required' => TRUE, - ]; - - // During interactive install we'll change this to a different profile and - // this test will ensure that the new value is written to settings.php. - $this->settings['settings']['install_profile'] = (object) [ - 'value' => 'minimal', - 'required' => TRUE, - ]; - - // Pre-configure config directories. - $site_path = DrupalKernel::findSitePath(Request::createFromGlobals()); - $this->settings['config_directories'] = [ - CONFIG_SYNC_DIRECTORY => (object) [ - 'value' => $site_path . '/files/config_staging', - 'required' => TRUE, - ], - ]; - mkdir($this->settings['config_directories'][CONFIG_SYNC_DIRECTORY]->value, 0777, TRUE); - - parent::setUp(); - } - - /** - * {@inheritdoc} - */ - protected function visitInstaller() { - // Make settings file not writable. This will break the installer. - $filename = $this->siteDirectory . '/settings.php'; - // Make the settings file read-only. - // Not using File API; a potential error must trigger a PHP warning. - chmod($filename, 0444); - - $this->drupalGet($GLOBALS['base_url'] . '/core/install.php?langcode=en&profile=testing'); - } - - /** - * {@inheritdoc} - */ - protected function setUpLanguage() { - // This step is skipped, because there is a lagcode as a query param. - } - - /** - * {@inheritdoc} - */ - protected function setUpProfile() { - // This step is skipped, because there is a profile as a query param. - } - - /** - * {@inheritdoc} - */ - protected function setUpSettings() { - // This step should not appear, since settings.php is fully configured - // already. - } - - protected function setUpSite() { - // This step should not appear, since settings.php could not be written. - } - - /** - * Verifies that installation did not succeed. - */ - public function testBrokenInstaller() { - $this->assertTitle('Install profile mismatch | Drupal'); - $this->assertText("The selected profile testing does not match the install_profile setting, which is minimal. Cannot write updated setting to {$this->siteDirectory}/settings.php."); - } - -} diff -r e200cb7efeb3 -r c2387f117808 core/modules/system/src/Tests/Installer/InstallerExistingSettingsMismatchProfileTest.php --- a/core/modules/system/src/Tests/Installer/InstallerExistingSettingsMismatchProfileTest.php Thu Apr 26 11:26:54 2018 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,101 +0,0 @@ -settings['settings']['hash_salt'] = (object) [ - 'value' => __CLASS__, - 'required' => TRUE, - ]; - - // Pre-configure database credentials. - $connection_info = Database::getConnectionInfo(); - unset($connection_info['default']['pdo']); - unset($connection_info['default']['init_commands']); - - $this->settings['databases']['default'] = (object) [ - 'value' => $connection_info, - 'required' => TRUE, - ]; - - // During interactive install we'll change this to a different profile and - // this test will ensure that the new value is written to settings.php. - $this->settings['settings']['install_profile'] = (object) [ - 'value' => 'minimal', - 'required' => TRUE, - ]; - - // Pre-configure config directories. - $this->settings['config_directories'] = [ - CONFIG_SYNC_DIRECTORY => (object) [ - 'value' => DrupalKernel::findSitePath(Request::createFromGlobals()) . '/files/config_sync', - 'required' => TRUE, - ], - ]; - mkdir($this->settings['config_directories'][CONFIG_SYNC_DIRECTORY]->value, 0777, TRUE); - - parent::setUp(); - } - - /** - * {@inheritdoc} - */ - protected function visitInstaller() { - // Provide profile and language in query string to skip these pages. - $this->drupalGet($GLOBALS['base_url'] . '/core/install.php?langcode=en&profile=testing'); - } - - /** - * {@inheritdoc} - */ - protected function setUpLanguage() { - // This step is skipped, because there is a lagcode as a query param. - } - - /** - * {@inheritdoc} - */ - protected function setUpProfile() { - // This step is skipped, because there is a profile as a query param. - } - - /** - * {@inheritdoc} - */ - protected function setUpSettings() { - // This step should not appear, since settings.php is fully configured - // already. - } - - /** - * Verifies that installation succeeded. - */ - public function testInstaller() { - $this->assertUrl('user/1'); - $this->assertResponse(200); - $this->assertEqual('testing', \Drupal::installProfile()); - $this->assertEqual('testing', Settings::get('install_profile'), 'Profile was correctly changed to testing in Settings.php'); - } - -} diff -r e200cb7efeb3 -r c2387f117808 core/modules/system/src/Tests/Installer/InstallerExistingSettingsNoProfileTest.php --- a/core/modules/system/src/Tests/Installer/InstallerExistingSettingsNoProfileTest.php Thu Apr 26 11:26:54 2018 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,70 +0,0 @@ -settings['settings']['hash_salt'] = (object) [ - 'value' => __CLASS__, - 'required' => TRUE, - ]; - - // Pre-configure database credentials. - $connection_info = Database::getConnectionInfo(); - unset($connection_info['default']['pdo']); - unset($connection_info['default']['init_commands']); - - $this->settings['databases']['default'] = (object) [ - 'value' => $connection_info, - 'required' => TRUE, - ]; - - // Pre-configure config directories. - $this->settings['config_directories'] = [ - CONFIG_SYNC_DIRECTORY => (object) [ - 'value' => DrupalKernel::findSitePath(Request::createFromGlobals()) . '/files/config_sync', - 'required' => TRUE, - ], - ]; - mkdir($this->settings['config_directories'][CONFIG_SYNC_DIRECTORY]->value, 0777, TRUE); - - parent::setUp(); - } - - /** - * {@inheritdoc} - */ - protected function setUpSettings() { - // This step should not appear, since settings.php is fully configured - // already. - } - - /** - * Verifies that installation succeeded. - */ - public function testInstaller() { - $this->assertUrl('user/1'); - $this->assertResponse(200); - $this->assertEqual('testing', \Drupal::installProfile()); - } - -} diff -r e200cb7efeb3 -r c2387f117808 core/modules/system/src/Tests/Installer/InstallerExistingSettingsTest.php --- a/core/modules/system/src/Tests/Installer/InstallerExistingSettingsTest.php Thu Apr 26 11:26:54 2018 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,82 +0,0 @@ -settings['settings']['hash_salt'] = (object) [ - 'value' => __CLASS__, - 'required' => TRUE, - ]; - - // During interactive install we'll change this to a different profile and - // this test will ensure that the new value is written to settings.php. - $this->settings['settings']['install_profile'] = (object) [ - 'value' => 'minimal', - 'required' => TRUE, - ]; - - // Pre-configure database credentials. - $connection_info = Database::getConnectionInfo(); - unset($connection_info['default']['pdo']); - unset($connection_info['default']['init_commands']); - - $this->settings['databases']['default'] = (object) [ - 'value' => $connection_info, - 'required' => TRUE, - ]; - - // Use the kernel to find the site path because the site.path service should - // not be available at this point in the install process. - $site_path = DrupalKernel::findSitePath(Request::createFromGlobals()); - // Pre-configure config directories. - $this->settings['config_directories'] = [ - CONFIG_SYNC_DIRECTORY => (object) [ - 'value' => $site_path . '/files/config_sync', - 'required' => TRUE, - ], - ]; - mkdir($this->settings['config_directories'][CONFIG_SYNC_DIRECTORY]->value, 0777, TRUE); - - parent::setUp(); - } - - /** - * {@inheritdoc} - */ - protected function setUpSettings() { - // This step should not appear, since settings.php is fully configured - // already. - } - - /** - * Verifies that installation succeeded. - */ - public function testInstaller() { - $this->assertUrl('user/1'); - $this->assertResponse(200); - $this->assertEqual('testing', \Drupal::installProfile(), 'Profile was changed from minimal to testing during interactive install.'); - $this->assertEqual('testing', Settings::get('install_profile'), 'Profile was correctly changed to testing in Settings.php'); - } - -} diff -r e200cb7efeb3 -r c2387f117808 core/modules/system/src/Tests/Installer/InstallerLanguageDirectionTest.php --- a/core/modules/system/src/Tests/Installer/InstallerLanguageDirectionTest.php Thu Apr 26 11:26:54 2018 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,49 +0,0 @@ -siteDirectory . '/files/translations', 0777, TRUE); - file_put_contents(\Drupal::root() . '/' . $this->siteDirectory . '/files/translations/drupal-8.0.0.ar.po', "msgid \"\"\nmsgstr \"\"\nmsgid \"Save and continue\"\nmsgstr \"Save and continue Arabic\""); - - parent::setUpLanguage(); - // After selecting a different language than English, all following screens - // should be translated already. - $elements = $this->xpath('//input[@type="submit"]/@value'); - $this->assertEqual((string) current($elements), 'Save and continue Arabic'); - $this->translations['Save and continue'] = 'Save and continue Arabic'; - - // Verify that language direction is right-to-left. - $direction = (string) current($this->xpath('/html/@dir')); - $this->assertEqual($direction, 'rtl'); - } - - /** - * Confirms that the installation succeeded. - */ - public function testInstalled() { - $this->assertUrl('user/1'); - $this->assertResponse(200); - } - -} diff -r e200cb7efeb3 -r c2387f117808 core/modules/system/src/Tests/Installer/InstallerLanguagePageTest.php --- a/core/modules/system/src/Tests/Installer/InstallerLanguagePageTest.php Thu Apr 26 11:26:54 2018 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,45 +0,0 @@ -siteDirectory . '/files/translations', 0777, TRUE); - touch(\Drupal::root() . '/' . $this->siteDirectory . '/files/translations/drupal-8.0.0.xoxo.po'); - - // Check that all predefined languages show up with their native names. - $this->visitInstaller(); - foreach (LanguageManager::getStandardLanguageList() as $langcode => $names) { - $this->assertOption('edit-langcode', $langcode); - $this->assertRaw('>' . $names[1] . '<'); - } - - // Check that our custom one shows up with the file name indicated language. - $this->assertOption('edit-langcode', 'xoxo'); - $this->assertRaw('>xoxo<'); - - parent::setUpLanguage(); - } - - /** - * Confirms that the installation succeeded. - */ - public function testInstalled() { - $this->assertUrl('user/1'); - $this->assertResponse(200); - } - -} diff -r e200cb7efeb3 -r c2387f117808 core/modules/system/src/Tests/Installer/InstallerTest.php --- a/core/modules/system/src/Tests/Installer/InstallerTest.php Thu Apr 26 11:26:54 2018 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,91 +0,0 @@ -assertUrl('user/1'); - $this->assertResponse(200); - // Confirm that we are logged-in after installation. - $this->assertText($this->rootUser->getUsername()); - - // Verify that the confirmation message appears. - require_once \Drupal::root() . '/core/includes/install.inc'; - $this->assertRaw(t('Congratulations, you installed @drupal!', [ - '@drupal' => drupal_install_profile_distribution_name(), - ])); - - // Ensure that the timezone is correct for sites under test after installing - // interactively. - $this->assertEqual($this->config('system.date')->get('timezone.default'), 'Australia/Sydney'); - } - - /** - * Installer step: Select language. - */ - protected function setUpLanguage() { - // Test that \Drupal\Core\Render\BareHtmlPageRenderer adds assets and - // metatags as expected to the first page of the installer. - $this->assertRaw('core/themes/seven/css/components/buttons.css'); - $this->assertRaw(''); - - // Assert that the expected title is present. - $this->assertEqual('Choose language', $this->cssSelect('main h2')[0]); - - parent::setUpLanguage(); - } - - /** - * {@inheritdoc} - */ - protected function setUpProfile() { - // Assert that the expected title is present. - $this->assertEqual('Select an installation profile', $this->cssSelect('main h2')[0]); - $result = $this->xpath('//span[contains(@class, :class) and contains(text(), :text)]', [':class' => 'visually-hidden', ':text' => 'Select an installation profile']); - $this->assertEqual(count($result), 1, "Title/Label not displayed when '#title_display' => 'invisible' attribute is set"); - - parent::setUpProfile(); - } - - /** - * {@inheritdoc} - */ - protected function setUpSettings() { - // Assert that the expected title is present. - $this->assertEqual('Database configuration', $this->cssSelect('main h2')[0]); - - parent::setUpSettings(); - } - - /** - * {@inheritdoc} - */ - protected function setUpSite() { - // Assert that the expected title is present. - $this->assertEqual('Configure site', $this->cssSelect('main h2')[0]); - - parent::setUpSite(); - } - - /** - * {@inheritdoc} - */ - protected function visitInstaller() { - parent::visitInstaller(); - - // Assert the title is correct and has the title suffix. - $this->assertTitle('Choose language | Drupal'); - } - -} diff -r e200cb7efeb3 -r c2387f117808 core/modules/system/src/Tests/Installer/InstallerTranslationMultipleLanguageForeignTest.php --- a/core/modules/system/src/Tests/Installer/InstallerTranslationMultipleLanguageForeignTest.php Thu Apr 26 11:26:54 2018 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,27 +0,0 @@ -translations['Save and continue'] = 'Save and continue de'; - } - -} diff -r e200cb7efeb3 -r c2387f117808 core/modules/system/src/Tests/Installer/InstallerTranslationMultipleLanguageKeepEnglishTest.php --- a/core/modules/system/src/Tests/Installer/InstallerTranslationMultipleLanguageKeepEnglishTest.php Thu Apr 26 11:26:54 2018 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,19 +0,0 @@ -siteDirectory . '/files/translations', 0777, TRUE); - file_put_contents(DRUPAL_ROOT . '/' . $this->siteDirectory . '/files/translations/drupal-8.0.0.de.po', $this->getPo('de')); - file_put_contents(DRUPAL_ROOT . '/' . $this->siteDirectory . '/files/translations/drupal-8.0.0.es.po', $this->getPo('es')); - - parent::setUpLanguage(); - } - - /** - * Returns the string for the test .po file. - * - * @param string $langcode - * The language code. - * @return string - * Contents for the test .po file. - */ - protected function getPo($langcode) { - return <<langcode; - return $params; - } - - /** - * Tests that translations ended up at the expected places. - */ - public function testTranslationsLoaded() { - // Ensure the title is correct. - $this->assertEqual('SITE_NAME_' . $this->langcode, \Drupal::config('system.site')->get('name')); - - // Verify German and Spanish were configured. - $this->drupalGet('admin/config/regional/language'); - $this->assertText('German'); - $this->assertText('Spanish'); - // If the installer was English or we used a profile that keeps English, we - // expect that configured also. Otherwise English should not be configured - // on the site. - if ($this->langcode == 'en' || $this->profile == 'testing_multilingual_with_english') { - $this->assertText('English'); - } - else { - $this->assertNoText('English'); - } - - // Verify the strings from the translation files were imported. - $this->verifyImportedStringsTranslated(); - - /** @var \Drupal\language\ConfigurableLanguageManager $language_manager */ - $language_manager = \Drupal::languageManager(); - - // If the site was installed in a foreign language (only tested with German - // in subclasses), then the active configuration should be updated and no - // override should exist in German. Otherwise the German translation should - // end up in overrides the same way as Spanish (which is not used as a site - // installation language). English should be available based on profile - // information and should be possible to add if not yet added, making - // English overrides available. - - $config = \Drupal::config('user.settings'); - $override_de = $language_manager->getLanguageConfigOverride('de', 'user.settings'); - $override_en = $language_manager->getLanguageConfigOverride('en', 'user.settings'); - $override_es = $language_manager->getLanguageConfigOverride('es', 'user.settings'); - - if ($this->langcode == 'de') { - // Active configuration should be in German and no German override should - // exist. - $this->assertEqual($config->get('anonymous'), 'Anonymous de'); - $this->assertEqual($config->get('langcode'), 'de'); - $this->assertTrue($override_de->isNew()); - - if ($this->profile == 'testing_multilingual_with_english') { - // English is already added in this profile. Should make the override - // available. - $this->assertEqual($override_en->get('anonymous'), 'Anonymous'); - } - else { - // English is not yet available. - $this->assertTrue($override_en->isNew()); - - // Adding English should make the English override available. - $edit = ['predefined_langcode' => 'en']; - $this->drupalPostForm('admin/config/regional/language/add', $edit, t('Add language')); - $override_en = $language_manager->getLanguageConfigOverride('en', 'user.settings'); - $this->assertEqual($override_en->get('anonymous'), 'Anonymous'); - } - - // Activate a module, to make sure that config is not overridden by module - // installation. - $edit = [ - 'modules[views][enable]' => TRUE, - 'modules[filter][enable]' => TRUE, - ]; - $this->drupalPostForm('admin/modules', $edit, t('Install')); - - // Verify the strings from the translation are still as expected. - $this->verifyImportedStringsTranslated(); - } - else { - // Active configuration should be English. - $this->assertEqual($config->get('anonymous'), 'Anonymous'); - $this->assertEqual($config->get('langcode'), 'en'); - // There should not be an English override. - $this->assertTrue($override_en->isNew()); - // German should be an override. - $this->assertEqual($override_de->get('anonymous'), 'Anonymous de'); - } - - // Spanish is always an override (never used as installation language). - $this->assertEqual($override_es->get('anonymous'), 'Anonymous es'); - - } - - /** - * Helper function to verify that the expected strings are translated. - */ - protected function verifyImportedStringsTranslated() { - $test_samples = ['Save and continue', 'Anonymous', 'Language']; - $langcodes = ['de', 'es']; - - foreach ($test_samples as $sample) { - foreach ($langcodes as $langcode) { - $edit = []; - $edit['langcode'] = $langcode; - $edit['translation'] = 'translated'; - $edit['string'] = $sample; - $this->drupalPostForm('admin/config/regional/translate', $edit, t('Filter')); - $this->assertText($sample . ' ' . $langcode); - } - } - } - -} diff -r e200cb7efeb3 -r c2387f117808 core/modules/system/src/Tests/Installer/InstallerTranslationQueryTest.php --- a/core/modules/system/src/Tests/Installer/InstallerTranslationQueryTest.php Thu Apr 26 11:26:54 2018 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,85 +0,0 @@ -siteDirectory . '/files/translations', 0777, TRUE); - file_put_contents(\Drupal::root() . '/' . $this->siteDirectory . '/files/translations/drupal-8.0.0.de.po', $this->getPo('de')); - - // The unrouted URL assembler does not exist at this point, so we build the - // URL ourselves. - $this->drupalGet($GLOBALS['base_url'] . '/core/install.php' . '?langcode=' . $this->langcode); - - // The language should have been automatically detected, all following - // screens should be translated already. - $elements = $this->xpath('//input[@type="submit"]/@value'); - $this->assertEqual((string) current($elements), 'Save and continue de'); - $this->translations['Save and continue'] = 'Save and continue de'; - - // Check the language direction. - $direction = (string) current($this->xpath('/html/@dir')); - $this->assertEqual($direction, 'ltr'); - } - - /** - * {@inheritdoc} - */ - protected function setUpLanguage() { - // The language was was preset by passing a query parameter in the URL, so - // no explicit language selection is necessary. - } - - /** - * Verifies the expected behaviors of the installation result. - */ - public function testInstaller() { - $this->assertUrl('user/1'); - $this->assertResponse(200); - - // Verify German was configured but not English. - $this->drupalGet('admin/config/regional/language'); - $this->assertText('German'); - $this->assertNoText('English'); - } - - /** - * Returns the string for the test .po file. - * - * @param string $langcode - * The language code. - * @return string - * Contents for the test .po file. - */ - protected function getPo($langcode) { - return <<siteDirectory . '/files/translations', 0777, TRUE); - file_put_contents(\Drupal::root() . '/' . $this->siteDirectory . '/files/translations/drupal-8.0.0.de.po', $this->getPo('de')); - - parent::setUpLanguage(); - - // After selecting a different language than English, all following screens - // should be translated already. - $elements = $this->xpath('//input[@type="submit"]/@value'); - $this->assertEqual((string) current($elements), 'Save and continue de'); - $this->translations['Save and continue'] = 'Save and continue de'; - - // Check the language direction. - $direction = (string) current($this->xpath('/html/@dir')); - $this->assertEqual($direction, 'ltr'); - } - - /** - * {@inheritdoc} - */ - protected function setUpSettings() { - // We are creating a table here to force an error in the installer because - // it will try and create the drupal_install_test table as this is part of - // the standard database tests performed by the installer in - // Drupal\Core\Database\Install\Tasks. - Database::getConnection('default')->query('CREATE TABLE {drupal_install_test} (id int NULL)'); - parent::setUpSettings(); - - // Ensure that the error message translation is working. - $this->assertRaw('Beheben Sie alle Probleme unten, um die Installation fortzusetzen. Informationen zur Konfiguration der Datenbankserver finden Sie in der Installationshandbuch, oder kontaktieren Sie Ihren Hosting-Anbieter.'); - $this->assertRaw('CREATE ein Test-Tabelle auf Ihrem Datenbankserver mit dem Befehl CREATE TABLE {drupal_install_test} (id int NULL) fehlgeschlagen.'); - - // Now do it successfully. - Database::getConnection('default')->query('DROP TABLE {drupal_install_test}'); - parent::setUpSettings(); - } - - /** - * Verifies the expected behaviors of the installation result. - */ - public function testInstaller() { - $this->assertUrl('user/1'); - $this->assertResponse(200); - - // Verify German was configured but not English. - $this->drupalGet('admin/config/regional/language'); - $this->assertText('German'); - $this->assertNoText('English'); - - // The current container still has the english as current language, rebuild. - $this->rebuildContainer(); - /** @var \Drupal\user\Entity\User $account */ - $account = User::load(0); - $this->assertEqual($account->language()->getId(), 'en', 'Anonymous user is English.'); - $account = User::load(1); - $this->assertEqual($account->language()->getId(), 'en', 'Administrator user is English.'); - $account = $this->drupalCreateUser(); - $this->assertEqual($account->language()->getId(), 'de', 'New user is German.'); - - // Ensure that we can enable basic_auth on a non-english site. - $this->drupalPostForm('admin/modules', ['modules[basic_auth][enable]' => TRUE], t('Install')); - $this->assertResponse(200); - - // Assert that the theme CSS was added to the page. - $edit = ['preprocess_css' => FALSE]; - $this->drupalPostForm('admin/config/development/performance', $edit, t('Save configuration')); - $this->drupalGet(''); - $this->assertRaw('classy/css/components/action-links.css'); - - // Verify the strings from the translation files were imported. - $test_samples = ['Save and continue', 'Anonymous']; - foreach ($test_samples as $sample) { - $edit = []; - $edit['langcode'] = 'de'; - $edit['translation'] = 'translated'; - $edit['string'] = $sample; - $this->drupalPostForm('admin/config/regional/translate', $edit, t('Filter')); - $this->assertText($sample . ' de'); - } - - /** @var \Drupal\language\ConfigurableLanguageManager $language_manager */ - $language_manager = \Drupal::languageManager(); - - // Installed in German, configuration should be in German. No German or - // English overrides should be present. - $config = \Drupal::config('user.settings'); - $override_de = $language_manager->getLanguageConfigOverride('de', 'user.settings'); - $override_en = $language_manager->getLanguageConfigOverride('en', 'user.settings'); - $this->assertEqual($config->get('anonymous'), 'Anonymous de'); - $this->assertEqual($config->get('langcode'), 'de'); - $this->assertTrue($override_de->isNew()); - $this->assertTrue($override_en->isNew()); - - // Assert that adding English makes the English override available. - $edit = ['predefined_langcode' => 'en']; - $this->drupalPostForm('admin/config/regional/language/add', $edit, t('Add language')); - $override_en = $language_manager->getLanguageConfigOverride('en', 'user.settings'); - $this->assertFalse($override_en->isNew()); - $this->assertEqual($override_en->get('anonymous'), 'Anonymous'); - } - - /** - * Returns the string for the test .po file. - * - * @param string $langcode - * The language code. - * @return string - * Contents for the test .po file. - */ - protected function getPo($langcode) { - return <<installation handbook, or contact your hosting provider." -msgstr "Beheben Sie alle Probleme unten, um die Installation fortzusetzen. Informationen zur Konfiguration der Datenbankserver finden Sie in der Installationshandbuch, oder kontaktieren Sie Ihren Hosting-Anbieter." - -msgid "Failed to CREATE a test table on your database server with the command %query. The server reports the following message: %error.

      Are you sure the configured username has the necessary permissions to create tables in the database?

      " -msgstr "CREATE ein Test-Tabelle auf Ihrem Datenbankserver mit dem Befehl %query fehlgeschlagen." -ENDPO; - } - -} diff -r e200cb7efeb3 -r c2387f117808 core/modules/system/src/Tests/Installer/MinimalInstallerTest.php --- a/core/modules/system/src/Tests/Installer/MinimalInstallerTest.php Thu Apr 26 11:26:54 2018 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,28 +0,0 @@ -assertInstalledConfig([]); - } - -} diff -r e200cb7efeb3 -r c2387f117808 core/modules/system/src/Tests/Installer/MultipleDistributionsProfileTest.php --- a/core/modules/system/src/Tests/Installer/MultipleDistributionsProfileTest.php Thu Apr 26 11:26:54 2018 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,91 +0,0 @@ - 'profile', - 'core' => \Drupal::CORE_COMPATIBILITY, - 'name' => $name . ' profile', - 'distribution' => [ - 'name' => $name, - 'install' => [ - 'theme' => 'bartik', - ], - ], - ]; - // File API functions are not available yet. - $path = $this->siteDirectory . '/profiles/' . $name; - mkdir($path, 0777, TRUE); - file_put_contents("$path/$name.info.yml", Yaml::encode($info)); - } - // Install the first distribution. - $this->profile = 'distribution_one'; - - parent::setUp(); - } - - /** - * {@inheritdoc} - */ - protected function setUpLanguage() { - // Verify that the distribution name appears. - $this->assertRaw('distribution_one'); - // Verify that the requested theme is used. - $this->assertRaw('bartik'); - // Verify that the "Choose profile" step does not appear. - $this->assertNoText('profile'); - - parent::setUpLanguage(); - } - - /** - * {@inheritdoc} - */ - protected function setUpProfile() { - // This step is skipped, because there is a distribution profile. - } - - /** - * Confirms that the installation succeeded. - */ - public function testInstalled() { - $this->assertUrl('user/1'); - $this->assertResponse(200); - // Confirm that we are logged-in after installation. - $this->assertText($this->rootUser->getUsername()); - - // Confirm that Drupal recognizes this distribution as the current profile. - $this->assertEqual(\Drupal::installProfile(), 'distribution_one'); - $this->assertEqual(Settings::get('install_profile'), 'distribution_one', 'The install profile has been written to settings.php.'); - $this->assertEqual($this->config('core.extension')->get('profile'), 'distribution_one', 'The install profile has been written to core.extension configuration.'); - - $this->rebuildContainer(); - $this->pass('Container can be rebuilt as distribution is written to configuration.'); - $this->assertEqual(\Drupal::installProfile(), 'distribution_one'); - } - -} diff -r e200cb7efeb3 -r c2387f117808 core/modules/system/src/Tests/Installer/SingleVisibleProfileTest.php --- a/core/modules/system/src/Tests/Installer/SingleVisibleProfileTest.php Thu Apr 26 11:26:54 2018 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,60 +0,0 @@ - 'profile', - 'core' => \Drupal::CORE_COMPATIBILITY, - 'name' => 'Override ' . $profile, - 'hidden' => TRUE, - ]; - // File API functions are not available yet. - $path = $this->siteDirectory . '/profiles/' . $profile; - mkdir($path, 0777, TRUE); - file_put_contents("$path/$profile.info.yml", Yaml::encode($info)); - } - parent::setUp(); - } - - /** - * {@inheritdoc} - */ - protected function setUpProfile() { - // This step is skipped, because there is only one visible profile. - } - - /** - * Confirms that the installation succeeded. - */ - public function testInstalled() { - $this->assertUrl('user/1'); - $this->assertResponse(200); - // Confirm that we are logged-in after installation. - $this->assertText($this->rootUser->getUsername()); - // Confirm that the minimal profile was installed. - $this->assertEqual(drupal_get_profile(), 'minimal'); - } - -} diff -r e200cb7efeb3 -r c2387f117808 core/modules/system/src/Tests/Installer/SiteNameTest.php --- a/core/modules/system/src/Tests/Installer/SiteNameTest.php Thu Apr 26 11:26:54 2018 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,39 +0,0 @@ -siteName = $this->randomMachineName(); - $parameters = parent::installParameters(); - $parameters['forms']['install_configure_form']['site_name'] = $this->siteName; - return $parameters; - } - - /** - * Tests that the desired site name appears on the page after installation. - */ - public function testSiteName() { - $this->drupalGet(''); - $this->assertRaw($this->siteName, 'The site name that was set during the installation appears on the front page after installation.'); - } - -} diff -r e200cb7efeb3 -r c2387f117808 core/modules/system/src/Tests/Installer/StandardInstallerTest.php --- a/core/modules/system/src/Tests/Installer/StandardInstallerTest.php Thu Apr 26 11:26:54 2018 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,68 +0,0 @@ -assertRaw('No front page content has been created yet.'); - } - - /** - * {@inheritdoc} - */ - protected function setUpSite() { - // Test that the correct theme is being used. - $this->assertNoRaw('bartik'); - $this->assertRaw('themes/seven/css/theme/install-page.css'); - parent::setUpSite(); - } - - /** - * {@inheritdoc} - */ - protected function curlExec($curl_options, $redirect = FALSE) { - // Ensure that we see the classy progress CSS on the batch page. - // Batch processing happens as part of HTTP redirects, so we can access the - // HTML of the batch page. - if (strpos($curl_options[CURLOPT_URL], '&id=1&op=do_nojs') !== FALSE) { - $this->assertRaw('themes/classy/css/components/progress.css'); - } - return parent::curlExec($curl_options, $redirect); - } - - /** - * Ensures that the exported standard configuration is up to date. - */ - public function testStandardConfig() { - $skipped_config = []; - // \Drupal\simpletest\WebTestBase::installParameters() uses - // simpletest@example.com as mail address. - $skipped_config['contact.form.feedback'][] = '- simpletest@example.com'; - // \Drupal\filter\Entity\FilterFormat::toArray() drops the roles of filter - // formats. - $skipped_config['filter.format.basic_html'][] = 'roles:'; - $skipped_config['filter.format.basic_html'][] = '- authenticated'; - $skipped_config['filter.format.full_html'][] = 'roles:'; - $skipped_config['filter.format.full_html'][] = '- administrator'; - $skipped_config['filter.format.restricted_html'][] = 'roles:'; - $skipped_config['filter.format.restricted_html'][] = '- anonymous'; - - $this->assertInstalledConfig($skipped_config); - } - -} diff -r e200cb7efeb3 -r c2387f117808 core/modules/system/src/Tests/System/ThemeTest.php --- a/core/modules/system/src/Tests/System/ThemeTest.php Thu Apr 26 11:26:54 2018 +0100 +++ b/core/modules/system/src/Tests/System/ThemeTest.php Tue Jul 10 15:07:59 2018 +0100 @@ -428,4 +428,17 @@ $this->assertTextPattern('/Bartik ' . preg_quote($version) . '\s{2,}\(default theme\)/'); } + /** + * Test the theme settings form when logo and favicon features are disabled. + */ + public function testThemeSettingsNoLogoNoFavicon() { + // Install theme with no logo and no favicon feature. + $this->container->get('theme_handler')->install(['test_theme_settings_features']); + // Visit this theme's settings page. + $this->drupalGet('admin/appearance/settings/test_theme_settings_features'); + $edit = []; + $this->drupalPostForm('admin/appearance/settings/test_theme_settings_features', $edit, t('Save configuration')); + $this->assertText('The configuration options have been saved.'); + } + } diff -r e200cb7efeb3 -r c2387f117808 core/modules/system/templates/status-messages.html.twig --- a/core/modules/system/templates/status-messages.html.twig Thu Apr 26 11:26:54 2018 +0100 +++ b/core/modules/system/templates/status-messages.html.twig Tue Jul 10 15:07:59 2018 +0100 @@ -15,8 +15,6 @@ * Available variables: * - message_list: List of messages to be displayed, grouped by type. * - status_headings: List of all status types. - * - display: (optional) May have a value of 'status' or 'error' when only - * displaying messages of that specific type. * - attributes: HTML attributes for the element, including: * - class: HTML classes. * diff -r e200cb7efeb3 -r c2387f117808 core/modules/system/tests/modules/default_format_test/default_format_test.info.yml --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/core/modules/system/tests/modules/default_format_test/default_format_test.info.yml Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,6 @@ +name: 'Default format test' +type: module +description: 'Support module for testing default route format.' +package: Testing +version: VERSION +core: 8.x diff -r e200cb7efeb3 -r c2387f117808 core/modules/system/tests/modules/default_format_test/default_format_test.routing.yml --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/core/modules/system/tests/modules/default_format_test/default_format_test.routing.yml Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,28 @@ +default_format_test.machine: + path: '/default_format_test/machine' + defaults: + # Same controller + method! + _controller: '\Drupal\default_format_test\DefaultFormatTestController::content' + requirements: + _access: 'TRUE' + _format: 'json' + +default_format_test.human: + path: '/default_format_test/human' + defaults: + # Same controller + method! + _controller: '\Drupal\default_format_test\DefaultFormatTestController::content' + requirements: + _access: 'TRUE' + _format: 'html' + +# Route definition identical to default_format_test.machine, only different name. +# @see \Drupal\FunctionalTests\Routing\DefaultFormatTest::testMultiple +default_format_test.machine.alias: + path: '/default_format_test/machine' + defaults: + # Same controller + method! + _controller: '\Drupal\default_format_test\DefaultFormatTestController::content' + requirements: + _access: 'TRUE' + _format: 'json' diff -r e200cb7efeb3 -r c2387f117808 core/modules/system/tests/modules/default_format_test/src/DefaultFormatTestController.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/core/modules/system/tests/modules/default_format_test/src/DefaultFormatTestController.php Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,15 @@ +getRequestFormat(); + return new CacheableResponse('format:' . $format, 200, ['Content-Type' => $request->getMimeType($format)]); + } + +} diff -r e200cb7efeb3 -r c2387f117808 core/modules/system/tests/modules/entity_test/entity_test.module --- a/core/modules/system/tests/modules/entity_test/entity_test.module Thu Apr 26 11:26:54 2018 +0100 +++ b/core/modules/system/tests/modules/entity_test/entity_test.module Tue Jul 10 15:07:59 2018 +0100 @@ -101,6 +101,9 @@ if (!$state->get('entity_test_new')) { unset($entity_types['entity_test_new']); } + + $entity_test_definition = $entity_types['entity_test']; + $entity_test_definition->set('entity_keys', $state->get('entity_test.entity_keys', []) + $entity_test_definition->getKeys()); } /** diff -r e200cb7efeb3 -r c2387f117808 core/modules/system/tests/modules/entity_test/src/Entity/EntityTest.php --- a/core/modules/system/tests/modules/entity_test/src/Entity/EntityTest.php Thu Apr 26 11:26:54 2018 +0100 +++ b/core/modules/system/tests/modules/entity_test/src/Entity/EntityTest.php Tue Jul 10 15:07:59 2018 +0100 @@ -109,7 +109,7 @@ ], ]); - return $fields; + return $fields + \Drupal::state()->get($entity_type->id() . '.additional_base_field_definitions', []); } /** @@ -164,4 +164,15 @@ return $this->get('name')->value; } + /** + * {@inheritdoc} + */ + public function getEntityKey($key) { + // Typically this protected method is used internally by entity classes and + // exposed publicly through more specific getter methods. So that test cases + // are able to set and access entity keys dynamically, update the visibility + // of this method to public. + return parent::getEntityKey($key); + } + } diff -r e200cb7efeb3 -r c2387f117808 core/modules/system/tests/modules/entity_test/src/Entity/EntityTestComputedField.php --- a/core/modules/system/tests/modules/entity_test/src/Entity/EntityTestComputedField.php Thu Apr 26 11:26:54 2018 +0100 +++ b/core/modules/system/tests/modules/entity_test/src/Entity/EntityTestComputedField.php Tue Jul 10 15:07:59 2018 +0100 @@ -4,6 +4,7 @@ use Drupal\Core\Entity\EntityTypeInterface; use Drupal\Core\Field\BaseFieldDefinition; +use Drupal\entity_test\Plugin\Field\ComputedReferenceTestFieldItemList; use Drupal\entity_test\Plugin\Field\ComputedTestFieldItemList; /** @@ -39,6 +40,12 @@ ->setComputed(TRUE) ->setClass(ComputedTestFieldItemList::class); + $fields['computed_reference_field'] = BaseFieldDefinition::create('entity_reference') + ->setLabel('Computed Reference Field Test') + ->setComputed(TRUE) + ->setSetting('target_type', 'entity_test') + ->setClass(ComputedReferenceTestFieldItemList::class); + return $fields; } diff -r e200cb7efeb3 -r c2387f117808 core/modules/system/tests/modules/entity_test/src/Plugin/Field/ComputedReferenceTestFieldItemList.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/core/modules/system/tests/modules/entity_test/src/Plugin/Field/ComputedReferenceTestFieldItemList.php Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,24 @@ +get('entity_test_reference_computed_target_ids', []) as $delta => $id) { + $this->list[$delta] = $this->createItem($delta, $id); + } + } + +} diff -r e200cb7efeb3 -r c2387f117808 core/modules/system/tests/modules/entity_test/tests/src/Functional/Hal/EntityTestBundleHalJsonAnonTest.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/core/modules/system/tests/modules/entity_test/tests/src/Functional/Hal/EntityTestBundleHalJsonAnonTest.php Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,32 @@ +applyHalFieldNormalization($default_normalization); + + $author = User::load(0); + return $normalization + [ + '_links' => [ + 'self' => [ + 'href' => $this->baseUrl . '/entity_test/1?_format=hal_json', + ], + 'type' => [ + 'href' => $this->baseUrl . '/rest/type/entity_test/entity_test', + ], + $this->baseUrl . '/rest/relation/entity_test/entity_test/user_id' => [ + [ + 'href' => $this->baseUrl . '/user/0?_format=hal_json', + 'lang' => 'en', + ], + ], + ], + '_embedded' => [ + $this->baseUrl . '/rest/relation/entity_test/entity_test/user_id' => [ + [ + '_links' => [ + 'self' => [ + 'href' => $this->baseUrl . '/user/0?_format=hal_json', + ], + 'type' => [ + 'href' => $this->baseUrl . '/rest/type/user/user', + ], + ], + 'uuid' => [ + ['value' => $author->uuid()] + ], + 'lang' => 'en', + ], + ], + ], + ]; + } + + /** + * {@inheritdoc} + */ + protected function getNormalizedPostEntity() { + return parent::getNormalizedPostEntity() + [ + '_links' => [ + 'type' => [ + 'href' => $this->baseUrl . '/rest/type/entity_test/entity_test', + ], + ], + ]; + } + +} diff -r e200cb7efeb3 -r c2387f117808 core/modules/system/tests/modules/entity_test/tests/src/Functional/Hal/EntityTestHalJsonBasicAuthTest.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/core/modules/system/tests/modules/entity_test/tests/src/Functional/Hal/EntityTestHalJsonBasicAuthTest.php Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,24 @@ +applyHalFieldNormalization($default_normalization); + // The 'internal_value' property in test field type will not be returned in + // normalization because setInternal(FALSE) was not called for this + // property. + // @see \Drupal\entity_test\Plugin\Field\FieldType\InternalPropertyTestFieldItem::propertyDefinitions + $normalization['field_test_internal'] = [ + [ + 'value' => 'This value shall not be internal!', + 'non_internal_value' => 'Computed! This value shall not be internal!', + ], + ]; + return $normalization; + } + + /** + * {@inheritdoc} + */ + protected function createEntity() { + if (!FieldStorageConfig::loadByName('entity_test', 'field_test_internal')) { + FieldStorageConfig::create([ + 'entity_type' => 'entity_test', + 'field_name' => 'field_test_internal', + 'type' => 'internal_property_test', + 'cardinality' => 1, + 'translatable' => FALSE, + ])->save(); + FieldConfig::create([ + 'entity_type' => 'entity_test', + 'field_name' => 'field_test_internal', + 'bundle' => 'entity_test', + 'label' => 'Test field with internal and non-internal properties', + ])->save(); + } + + $entity = parent::createEntity(); + $entity->field_test_internal = [ + 'value' => 'This value shall not be internal!', + ]; + $entity->save(); + return $entity; + } + + /** + * {@inheritdoc} + */ + protected function getNormalizedPostEntity() { + return parent::getNormalizedPostEntity() + [ + 'field_test_internal' => [ + [ + 'value' => 'This value shall not be internal!', + ], + ], + ]; + } + + /** + * {@inheritdoc} + */ + protected function getExpectedCacheContexts() { + return Cache::mergeContexts(parent::getExpectedCacheContexts(), ['request_format']); + } + + /** + * {@inheritdoc} + */ + protected function getExpectedCacheTags() { + return Cache::mergeTags(parent::getExpectedCacheTags(), ['you_are_it', 'no_tag_backs']); + } + +} diff -r e200cb7efeb3 -r c2387f117808 core/modules/system/tests/modules/entity_test/tests/src/Functional/Hal/EntityTestLabelHalJsonAnonTest.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/core/modules/system/tests/modules/entity_test/tests/src/Functional/Hal/EntityTestLabelHalJsonAnonTest.php Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,103 @@ +applyHalFieldNormalization($default_normalization); + + $author = User::load(0); + return $normalization + [ + '_links' => [ + 'self' => [ + 'href' => '', + ], + 'type' => [ + 'href' => $this->baseUrl . '/rest/type/entity_test_label/entity_test_label', + ], + $this->baseUrl . '/rest/relation/entity_test_label/entity_test_label/user_id' => [ + [ + 'href' => $this->baseUrl . '/user/0?_format=hal_json', + 'lang' => 'en', + ], + ], + ], + '_embedded' => [ + $this->baseUrl . '/rest/relation/entity_test_label/entity_test_label/user_id' => [ + [ + '_links' => [ + 'self' => [ + 'href' => $this->baseUrl . '/user/0?_format=hal_json', + ], + 'type' => [ + 'href' => $this->baseUrl . '/rest/type/user/user', + ], + ], + 'uuid' => [ + [ + 'value' => $author->uuid(), + ], + ], + 'lang' => 'en', + ], + ], + ], + ]; + } + + /** + * {@inheritdoc} + */ + protected function getNormalizedPostEntity() { + return parent::getNormalizedPostEntity() + [ + '_links' => [ + 'type' => [ + 'href' => $this->baseUrl . '/rest/type/entity_test_label/entity_test_label', + ], + ], + ]; + } + + /** + * {@inheritdoc} + */ + protected function getExpectedCacheContexts() { + return [ + 'url.site', + 'user.permissions', + ]; + } + +} diff -r e200cb7efeb3 -r c2387f117808 core/modules/system/tests/modules/entity_test/tests/src/Functional/Hal/EntityTestLabelHalJsonBasicAuthTest.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/core/modules/system/tests/modules/entity_test/tests/src/Functional/Hal/EntityTestLabelHalJsonBasicAuthTest.php Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,24 @@ +grantPermissionsToTestedRole(['administer entity_test_bundle content']); + } + + /** + * {@inheritdoc} + */ + protected function createEntity() { + $entity_test_bundle = EntityTestBundle::create([ + 'id' => 'camelids', + 'label' => 'Camelids', + 'description' => 'Camelids are large, strictly herbivorous animals with slender necks and long legs.', + ]); + $entity_test_bundle->save(); + + return $entity_test_bundle; + } + + /** + * {@inheritdoc} + */ + protected function getExpectedNormalizedEntity() { + return [ + 'dependencies' => [], + 'description' => 'Camelids are large, strictly herbivorous animals with slender necks and long legs.', + 'id' => 'camelids', + 'label' => 'Camelids', + 'langcode' => 'en', + 'status' => TRUE, + 'uuid' => $this->entity->uuid(), + ]; + } + + /** + * {@inheritdoc} + */ + protected function getNormalizedPostEntity() { + // @todo Update in https://www.drupal.org/node/2300677. + } + +} diff -r e200cb7efeb3 -r c2387f117808 core/modules/system/tests/modules/entity_test/tests/src/Functional/Rest/EntityTestBundleXmlAnonTest.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/core/modules/system/tests/modules/entity_test/tests/src/Functional/Rest/EntityTestBundleXmlAnonTest.php Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,26 @@ + 'This value shall not be internal!', + 'non_internal_value' => 'Computed! This value shall not be internal!', + ], + ]; + return $expected; + } + + /** + * {@inheritdoc} + */ + protected function createEntity() { + if (!FieldStorageConfig::loadByName('entity_test', 'field_test_internal')) { + FieldStorageConfig::create([ + 'entity_type' => 'entity_test', + 'field_name' => 'field_test_internal', + 'type' => 'internal_property_test', + 'cardinality' => 1, + 'translatable' => FALSE, + ])->save(); + FieldConfig::create([ + 'entity_type' => 'entity_test', + 'field_name' => 'field_test_internal', + 'bundle' => 'entity_test', + 'label' => 'Test field with internal and non-internal properties', + ])->save(); + } + + $entity = parent::createEntity(); + $entity->field_test_internal = [ + 'value' => 'This value shall not be internal!', + ]; + $entity->save(); + return $entity; + } + + /** + * {@inheritdoc} + */ + protected function getNormalizedPostEntity() { + return parent::getNormalizedPostEntity() + [ + 'field_test_internal' => [ + [ + 'value' => 'This value shall not be internal!', + ], + ], + ]; + } + + /** + * {@inheritdoc} + */ + protected function getExpectedCacheContexts() { + return Cache::mergeContexts(parent::getExpectedCacheContexts(), ['request_format']); + } + + /** + * {@inheritdoc} + */ + protected function getExpectedCacheTags() { + return Cache::mergeTags(parent::getExpectedCacheTags(), ['you_are_it', 'no_tag_backs']); + } + +} diff -r e200cb7efeb3 -r c2387f117808 core/modules/system/tests/modules/entity_test/tests/src/Functional/Rest/EntityTestLabelJsonAnonTest.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/core/modules/system/tests/modules/entity_test/tests/src/Functional/Rest/EntityTestLabelJsonAnonTest.php Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,24 @@ +grantPermissionsToTestedRole(['view test entity']); + break; + case 'POST': + $this->grantPermissionsToTestedRole([ + 'administer entity_test content', + 'administer entity_test_with_bundle content', + 'create entity_test entity_test_with_bundle entities', + ]); + break; + case 'PATCH': + case 'DELETE': + $this->grantPermissionsToTestedRole(['administer entity_test content']); + break; + } + } + + /** + * {@inheritdoc} + */ + protected function createEntity() { + $entity_test_label = EntityTestLabel::create([ + 'name' => 'label_llama', + ]); + $entity_test_label->setOwnerId(0); + $entity_test_label->save(); + return $entity_test_label; + } + + /** + * {@inheritdoc} + */ + protected function getExpectedNormalizedEntity() { + $author = User::load(0); + $normalization = [ + 'uuid' => [ + [ + 'value' => $this->entity->uuid(), + ], + ], + 'id' => [ + [ + 'value' => (int) $this->entity->id(), + ], + ], + 'langcode' => [ + [ + 'value' => 'en', + ], + ], + 'type' => [ + [ + 'value' => 'entity_test_label', + ], + ], + 'name' => [ + [ + 'value' => 'label_llama', + ], + ], + 'created' => [ + $this->formatExpectedTimestampItemValues((int) $this->entity->get('created')->value), + ], + 'user_id' => [ + [ + 'target_id' => (int) $author->id(), + 'target_type' => 'user', + 'target_uuid' => $author->uuid(), + 'url' => $author->toUrl()->toString(), + ], + ], + ]; + + return $normalization; + } + + /** + * {@inheritdoc} + */ + protected function getNormalizedPostEntity() { + return [ + 'type' => [ + [ + 'value' => 'entity_test_label', + ], + ], + 'name' => [ + [ + 'value' => 'label_llama', + ], + ], + ]; + } + + /** + * {@inheritdoc} + */ + protected function getExpectedCacheContexts() { + return ['user.permissions']; + } + + /** + * {@inheritdoc} + */ + protected function getExpectedUnauthorizedAccessMessage($method) { + if ($this->config('rest.settings')->get('bc_entity_resource_permissions')) { + return parent::getExpectedUnauthorizedAccessMessage($method); + } + + switch ($method) { + case 'GET': + return "The 'view test entity' permission is required."; + case 'POST': + return "The following permissions are required: 'administer entity_test content' OR 'administer entity_test_with_bundle content' OR 'create entity_test_label entity_test_with_bundle entities'."; + case 'PATCH': + case 'DELETE': + return "The 'administer entity_test content' permission is required."; + default: + return parent::getExpectedUnauthorizedAccessMessage($method); + } + } + +} diff -r e200cb7efeb3 -r c2387f117808 core/modules/system/tests/modules/entity_test/tests/src/Functional/Rest/EntityTestLabelXmlAnonTest.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/core/modules/system/tests/modules/entity_test/tests/src/Functional/Rest/EntityTestLabelXmlAnonTest.php Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,26 @@ +grantPermissionsToTestedRole(['view test entity']); + break; + case 'POST': + $this->grantPermissionsToTestedRole(['create entity_test entity_test_with_bundle entities']); + break; + case 'PATCH': + case 'DELETE': + $this->grantPermissionsToTestedRole(['administer entity_test content']); + break; + } + } + + /** + * {@inheritdoc} + */ + protected function createEntity() { + // Set flag so that internal field 'internal_string_field' is created. + // @see entity_test_entity_base_field_info() + $this->container->get('state')->set('entity_test.internal_field', TRUE); + \Drupal::entityDefinitionUpdateManager()->applyUpdates(); + + $entity_test = EntityTest::create([ + 'name' => 'Llama', + 'type' => 'entity_test', + // Set a value for the internal field to confirm that it will not be + // returned in normalization. + // @see entity_test_entity_base_field_info(). + 'internal_string_field' => [ + 'value' => 'This value shall not be internal!', + ], + ]); + $entity_test->setOwnerId(0); + $entity_test->save(); + + return $entity_test; + } + + /** + * {@inheritdoc} + */ + protected function getExpectedNormalizedEntity() { + $author = User::load(0); + $normalization = [ + 'uuid' => [ + [ + 'value' => $this->entity->uuid() + ] + ], + 'id' => [ + [ + 'value' => 1, + ], + ], + 'langcode' => [ + [ + 'value' => 'en', + ], + ], + 'type' => [ + [ + 'value' => 'entity_test', + ] + ], + 'name' => [ + [ + 'value' => 'Llama', + ] + ], + 'created' => [ + $this->formatExpectedTimestampItemValues((int) $this->entity->get('created')->value) + ], + 'user_id' => [ + [ + 'target_id' => (int) $author->id(), + 'target_type' => 'user', + 'target_uuid' => $author->uuid(), + 'url' => $author->toUrl()->toString(), + ] + ], + 'field_test_text' => [], + ]; + + return $normalization; + } + + /** + * {@inheritdoc} + */ + protected function getNormalizedPostEntity() { + return [ + 'type' => [ + [ + 'value' => 'entity_test', + ], + ], + 'name' => [ + [ + 'value' => 'Dramallama', + ], + ], + ]; + } + + /** + * {@inheritdoc} + */ + protected function getExpectedUnauthorizedAccessMessage($method) { + if ($this->config('rest.settings')->get('bc_entity_resource_permissions')) { + return parent::getExpectedUnauthorizedAccessMessage($method); + } + + switch ($method) { + case 'GET': + return "The 'view test entity' permission is required."; + case 'POST': + return "The following permissions are required: 'administer entity_test content' OR 'administer entity_test_with_bundle content' OR 'create entity_test entity_test_with_bundle entities'."; + default: + return parent::getExpectedUnauthorizedAccessMessage($method); + } + } + +} diff -r e200cb7efeb3 -r c2387f117808 core/modules/system/tests/modules/entity_test/tests/src/Functional/Rest/EntityTestTextItemNormalizerTest.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/core/modules/system/tests/modules/entity_test/tests/src/Functional/Rest/EntityTestTextItemNormalizerTest.php Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,195 @@ +grantPermissionsToTestedRole(['use text format my_text_format']); + } + } + + /** + * {@inheritdoc} + */ + protected function getExpectedNormalizedEntity() { + $expected = parent::getExpectedNormalizedEntity(); + $expected['field_test_text'] = [ + [ + 'value' => 'Cádiz is the oldest continuously inhabited city in Spain and a nice place to spend a Sunday with friends.', + 'format' => 'my_text_format', + 'processed' => '

      Cádiz is the oldest continuously inhabited city in Spain and a nice place to spend a Sunday with friends.

      ' . "\n" . '

      This is a dynamic llama.

      ', + ], + ]; + return $expected; + } + + /** + * {@inheritdoc} + */ + protected function createEntity() { + $entity = parent::createEntity(); + if (!FilterFormat::load('my_text_format')) { + FilterFormat::create([ + 'format' => 'my_text_format', + 'name' => 'My Text Format', + 'filters' => [ + 'filter_test_assets' => [ + 'weight' => -1, + 'status' => TRUE, + ], + 'filter_test_cache_tags' => [ + 'weight' => 0, + 'status' => TRUE, + ], + 'filter_test_cache_contexts' => [ + 'weight' => 0, + 'status' => TRUE, + ], + 'filter_test_cache_merge' => [ + 'weight' => 0, + 'status' => TRUE, + ], + 'filter_test_placeholders' => [ + 'weight' => 1, + 'status' => TRUE, + ], + 'filter_autop' => [ + 'status' => TRUE, + ], + ], + ])->save(); + } + $entity->field_test_text = [ + 'value' => 'Cádiz is the oldest continuously inhabited city in Spain and a nice place to spend a Sunday with friends.', + 'format' => 'my_text_format', + ]; + $entity->save(); + return $entity; + } + + /** + * {@inheritdoc} + */ + protected function getNormalizedPostEntity() { + $post_entity = parent::getNormalizedPostEntity(); + $post_entity['field_test_text'] = [ + [ + 'value' => 'Llamas are awesome.', + 'format' => 'my_text_format', + ], + ]; + return $post_entity; + } + + /** + * {@inheritdoc} + */ + protected function getExpectedCacheTags() { + return Cache::mergeTags([ + // The cache tag set by the processed_text element itself. + 'config:filter.format.my_text_format', + // The cache tags set by the filter_test_cache_tags filter. + 'foo:bar', + 'foo:baz', + // The cache tags set by the filter_test_cache_merge filter. + 'merge:tag' + ], parent::getExpectedCacheTags()); + } + + /** + * {@inheritdoc} + */ + protected function getExpectedCacheContexts() { + return Cache::mergeContexts([ + // The cache context set by the filter_test_cache_contexts filter. + 'languages:' . LanguageInterface::TYPE_CONTENT, + // The default cache contexts for Renderer. + 'languages:' . LanguageInterface::TYPE_INTERFACE, + 'theme', + // The cache tags set by the filter_test_cache_merge filter. + 'user.permissions', + ], parent::getExpectedCacheContexts()); + } + + /** + * Tests GETting an entity with the test text field set to a specific format. + * + * @dataProvider providerTestGetWithFormat + */ + public function testGetWithFormat($text_format_id, array $expected_cache_tags) { + FilterFormat::create([ + 'name' => 'Pablo Piccasso', + 'format' => 'pablo', + 'langcode' => 'es', + 'filters' => [], + ])->save(); + + // Set TextItemBase field's value for testing, using the given text format. + $value = [ + 'value' => $this->randomString(), + ]; + if ($text_format_id !== FALSE) { + $value['format'] = $text_format_id; + } + $this->entity->set('field_test_text', $value)->save(); + + $this->initAuthentication(); + $url = $this->getEntityResourceUrl(); + $url->setOption('query', ['_format' => static::$format]); + $request_options = $this->getAuthenticationRequestOptions('GET'); + $this->provisionEntityResource(); + $this->setUpAuthorization('GET'); + $response = $this->request('GET', $url, $request_options); + $expected_cache_tags = Cache::mergeTags($expected_cache_tags, parent::getExpectedCacheTags()); + $this->assertSame($expected_cache_tags, explode(' ', $response->getHeader('X-Drupal-Cache-Tags')[0])); + } + + public function providerTestGetWithFormat() { + return [ + 'format specified (different from fallback format)' => [ + 'pablo', + ['config:filter.format.pablo'], + ], + 'format specified (happens to be the same as fallback format)' => [ + 'plain_text', + ['config:filter.format.plain_text'], + ], + 'no format specified: fallback format used automatically' => [ + FALSE, + ['config:filter.format.plain_text', 'config:filter.settings'], + ], + ]; + } + +} diff -r e200cb7efeb3 -r c2387f117808 core/modules/system/tests/modules/entity_test/tests/src/Functional/Rest/EntityTestXmlAnonTest.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/core/modules/system/tests/modules/entity_test/tests/src/Functional/Rest/EntityTestXmlAnonTest.php Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,28 @@ + 'Bad html ']; @@ -105,7 +109,8 @@ * Renders a page with pipe character in link test. * * @return array - * A render array as expected by drupal_render() + * A render array as expected by + * \Drupal\Core\Render\RendererInterface::render(). */ public function renderPipeInLink() { return ['#markup' => 'foo|bar|baz']; diff -r e200cb7efeb3 -r c2387f117808 core/modules/system/tests/src/Functional/Common/AlterTest.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/core/modules/system/tests/src/Functional/Common/AlterTest.php Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,72 @@ +alter(). + * + * @group Common + */ +class AlterTest extends BrowserTestBase { + + /** + * Modules to enable. + * + * @var array + */ + public static $modules = ['block', 'common_test']; + + /** + * Tests if the theme has been altered. + */ + public function testDrupalAlter() { + // This test depends on Bartik, so make sure that it is always the current + // active theme. + \Drupal::service('theme_handler')->install(['bartik']); + \Drupal::theme()->setActiveTheme(\Drupal::service('theme.initialization')->initTheme('bartik')); + + $array = ['foo' => 'bar']; + $entity = new \stdClass(); + $entity->foo = 'bar'; + + // Verify alteration of a single argument. + $array_copy = $array; + $array_expected = ['foo' => 'Drupal theme']; + \Drupal::moduleHandler()->alter('drupal_alter', $array_copy); + \Drupal::theme()->alter('drupal_alter', $array_copy); + $this->assertEqual($array_copy, $array_expected, 'Single array was altered.'); + + $entity_copy = clone $entity; + $entity_expected = clone $entity; + $entity_expected->foo = 'Drupal theme'; + \Drupal::moduleHandler()->alter('drupal_alter', $entity_copy); + \Drupal::theme()->alter('drupal_alter', $entity_copy); + $this->assertEqual($entity_copy, $entity_expected, 'Single object was altered.'); + + // Verify alteration of multiple arguments. + $array_copy = $array; + $array_expected = ['foo' => 'Drupal theme']; + $entity_copy = clone $entity; + $entity_expected = clone $entity; + $entity_expected->foo = 'Drupal theme'; + $array2_copy = $array; + $array2_expected = ['foo' => 'Drupal theme']; + \Drupal::moduleHandler()->alter('drupal_alter', $array_copy, $entity_copy, $array2_copy); + \Drupal::theme()->alter('drupal_alter', $array_copy, $entity_copy, $array2_copy); + $this->assertEqual($array_copy, $array_expected, 'First argument to \Drupal::moduleHandler->alter() was altered.'); + $this->assertEqual($entity_copy, $entity_expected, 'Second argument to \Drupal::moduleHandler->alter() was altered.'); + $this->assertEqual($array2_copy, $array2_expected, 'Third argument to \Drupal::moduleHandler->alter() was altered.'); + + // Verify alteration order when passing an array of types to \Drupal::moduleHandler->alter(). + // common_test_module_implements_alter() places 'block' implementation after + // other modules. + $array_copy = $array; + $array_expected = ['foo' => 'Drupal block theme']; + \Drupal::moduleHandler()->alter(['drupal_alter', 'drupal_alter_foo'], $array_copy); + \Drupal::theme()->alter(['drupal_alter', 'drupal_alter_foo'], $array_copy); + $this->assertEqual($array_copy, $array_expected, 'hook_TYPE_alter() implementations ran in correct order.'); + } + +} diff -r e200cb7efeb3 -r c2387f117808 core/modules/system/tests/src/Functional/Common/EarlyRenderingControllerTest.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/core/modules/system/tests/src/Functional/Common/EarlyRenderingControllerTest.php Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,110 @@ +drupalGet(Url::fromRoute('early_rendering_controller_test.render_array')); + $this->assertResponse(200); + $this->assertRaw('Hello world!'); + $this->assertCacheTag('foo'); + $this->drupalGet(Url::fromRoute('early_rendering_controller_test.render_array.early')); + $this->assertResponse(200); + $this->assertRaw('Hello world!'); + $this->assertCacheTag('foo'); + + // AjaxResponse: non-early & early. + // @todo Add cache tags assertion when AjaxResponse is made cacheable in + // https://www.drupal.org/node/956186. + $this->drupalGet(Url::fromRoute('early_rendering_controller_test.ajax_response')); + $this->assertResponse(200); + $this->assertRaw('Hello world!'); + $this->drupalGet(Url::fromRoute('early_rendering_controller_test.ajax_response.early')); + $this->assertResponse(200); + $this->assertRaw('Hello world!'); + + // Basic Response object: non-early & early. + $this->drupalGet(Url::fromRoute('early_rendering_controller_test.response')); + $this->assertResponse(200); + $this->assertRaw('Hello world!'); + $this->assertNoCacheTag('foo'); + $this->drupalGet(Url::fromRoute('early_rendering_controller_test.response.early')); + $this->assertResponse(200); + $this->assertRaw('Hello world!'); + $this->assertNoCacheTag('foo'); + + // Response object with attachments: non-early & early. + $this->drupalGet(Url::fromRoute('early_rendering_controller_test.response-with-attachments')); + $this->assertResponse(200); + $this->assertRaw('Hello world!'); + $this->assertNoCacheTag('foo'); + $this->drupalGet(Url::fromRoute('early_rendering_controller_test.response-with-attachments.early')); + $this->assertResponse(500); + $this->assertRaw('The controller result claims to be providing relevant cache metadata, but leaked metadata was detected. Please ensure you are not rendering content too early. Returned object class: Drupal\early_rendering_controller_test\AttachmentsTestResponse.'); + + // Cacheable Response object: non-early & early. + $this->drupalGet(Url::fromRoute('early_rendering_controller_test.cacheable-response')); + $this->assertResponse(200); + $this->assertRaw('Hello world!'); + $this->assertNoCacheTag('foo'); + $this->drupalGet(Url::fromRoute('early_rendering_controller_test.cacheable-response.early')); + $this->assertResponse(500); + $this->assertRaw('The controller result claims to be providing relevant cache metadata, but leaked metadata was detected. Please ensure you are not rendering content too early. Returned object class: Drupal\early_rendering_controller_test\CacheableTestResponse.'); + + // Basic domain object: non-early & early. + $this->drupalGet(Url::fromRoute('early_rendering_controller_test.domain-object')); + $this->assertResponse(200); + $this->assertRaw('TestDomainObject'); + $this->assertNoCacheTag('foo'); + $this->drupalGet(Url::fromRoute('early_rendering_controller_test.domain-object.early')); + $this->assertResponse(200); + $this->assertRaw('TestDomainObject'); + $this->assertNoCacheTag('foo'); + + // Basic domain object with attachments: non-early & early. + $this->drupalGet(Url::fromRoute('early_rendering_controller_test.domain-object-with-attachments')); + $this->assertResponse(200); + $this->assertRaw('AttachmentsTestDomainObject'); + $this->assertNoCacheTag('foo'); + $this->drupalGet(Url::fromRoute('early_rendering_controller_test.domain-object-with-attachments.early')); + $this->assertResponse(500); + $this->assertRaw('The controller result claims to be providing relevant cache metadata, but leaked metadata was detected. Please ensure you are not rendering content too early. Returned object class: Drupal\early_rendering_controller_test\AttachmentsTestDomainObject.'); + + // Cacheable Response object: non-early & early. + $this->drupalGet(Url::fromRoute('early_rendering_controller_test.cacheable-domain-object')); + $this->assertResponse(200); + $this->assertRaw('CacheableTestDomainObject'); + $this->assertNoCacheTag('foo'); + $this->drupalGet(Url::fromRoute('early_rendering_controller_test.cacheable-domain-object.early')); + $this->assertResponse(500); + $this->assertRaw('The controller result claims to be providing relevant cache metadata, but leaked metadata was detected. Please ensure you are not rendering content too early. Returned object class: Drupal\early_rendering_controller_test\CacheableTestDomainObject.'); + + // The exceptions are expected. Do not interpret them as a test failure. + // Not using File API; a potential error must trigger a PHP warning. + unlink(\Drupal::root() . '/' . $this->siteDirectory . '/error.log'); + } + +} diff -r e200cb7efeb3 -r c2387f117808 core/modules/system/tests/src/Functional/Common/NoJavaScriptAnonymousTest.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/core/modules/system/tests/src/Functional/Common/NoJavaScriptAnonymousTest.php Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,67 @@ +drupalCreateNode([ + 'promote' => NodeInterface::PROMOTED, + ]); + $user = $this->drupalCreateUser(); + + // Test frontpage. + $this->drupalGet(''); + $this->assertNoJavaScriptExceptHtml5Shiv(); + + // Test node page. + $this->drupalGet('node/1'); + $this->assertNoJavaScriptExceptHtml5Shiv(); + + // Test user profile page. + $this->drupalGet('user/' . $user->id()); + $this->assertNoJavaScriptExceptHtml5Shiv(); + } + + /** + * Passes if no JavaScript is found on the page except the HTML5 shiv. + * + * The HTML5 shiv is necessary for e.g. the
      tag which Drupal 8 uses + * to work in older browsers like Internet Explorer 8. + */ + protected function assertNoJavaScriptExceptHtml5Shiv() { + // Ensure drupalSettings is not set. + $settings = $this->getDrupalSettings(); + $this->assertTrue(empty($settings), 'drupalSettings is not set.'); + + // Ensure the HTML5 shiv exists. + $this->assertRaw('html5shiv/html5shiv.min.js', 'HTML5 shiv JavaScript exists.'); + + // Ensure no other JavaScript file exists on the page, while ignoring the + // HTML5 shiv. + $this->assertNoPattern('/(?randomMachineName(); + $path = ""; + $encoded_path = "3CSCRIPT%3Ealert%28%27XSS%27%29%3C/SCRIPT%3E"; + + $link = \Drupal::l($text, Url::fromUserInput('/' . $path)); + $this->assertTrue(strpos($link, $encoded_path) !== FALSE && strpos($link, $path) === FALSE, format_string('XSS attack @path was filtered by \Drupal\Core\Utility\LinkGeneratorInterface::generate().', ['@path' => $path])); + + // Test \Drupal\Core\Url. + $link = Url::fromUri('base:' . $path)->toString(); + $this->assertTrue(strpos($link, $encoded_path) !== FALSE && strpos($link, $path) === FALSE, format_string('XSS attack @path was filtered by #theme', ['@path' => $path])); + } + + /** + * Tests that #type=link bubbles outbound route/path processors' metadata. + */ + public function testLinkBubbleableMetadata() { + $cases = [ + ['Regular link', 'internal:/user', [], ['contexts' => [], 'tags' => [], 'max-age' => Cache::PERMANENT], []], + ['Regular link, absolute', 'internal:/user', ['absolute' => TRUE], ['contexts' => ['url.site'], 'tags' => [], 'max-age' => Cache::PERMANENT], []], + ['Route processor link', 'route:system.run_cron', [], ['contexts' => ['session'], 'tags' => [], 'max-age' => Cache::PERMANENT], ['placeholders' => []]], + ['Route processor link, absolute', 'route:system.run_cron', ['absolute' => TRUE], ['contexts' => ['url.site', 'session'], 'tags' => [], 'max-age' => Cache::PERMANENT], ['placeholders' => []]], + ['Path processor link', 'internal:/user/1', [], ['contexts' => [], 'tags' => ['user:1'], 'max-age' => Cache::PERMANENT], []], + ['Path processor link, absolute', 'internal:/user/1', ['absolute' => TRUE], ['contexts' => ['url.site'], 'tags' => ['user:1'], 'max-age' => Cache::PERMANENT], []], + ]; + + foreach ($cases as $case) { + list($title, $uri, $options, $expected_cacheability, $expected_attachments) = $case; + $expected_cacheability['contexts'] = Cache::mergeContexts($expected_cacheability['contexts'], ['languages:language_interface', 'theme', 'user.permissions']); + $link = [ + '#type' => 'link', + '#title' => $title, + '#options' => $options, + '#url' => Url::fromUri($uri), + ]; + \Drupal::service('renderer')->renderRoot($link); + $this->pass($title); + $this->assertEqual($expected_cacheability, $link['#cache']); + $this->assertEqual($expected_attachments, $link['#attached']); + } + } + + /** + * Tests that default and custom attributes are handled correctly on links. + */ + public function testLinkAttributes() { + /** @var \Drupal\Core\Render\RendererInterface $renderer */ + $renderer = $this->container->get('renderer'); + + // Test that hreflang is added when a link has a known language. + $language = new Language(['id' => 'fr', 'name' => 'French']); + $hreflang_link = [ + '#type' => 'link', + '#options' => [ + 'language' => $language, + ], + '#url' => Url::fromUri('https://www.drupal.org'), + '#title' => 'bar', + ]; + $langcode = $language->getId(); + + // Test that the default hreflang handling for links does not override a + // hreflang attribute explicitly set in the render array. + $hreflang_override_link = $hreflang_link; + $hreflang_override_link['#options']['attributes']['hreflang'] = 'foo'; + + $rendered = $renderer->renderRoot($hreflang_link); + $this->assertTrue($this->hasAttribute('hreflang', $rendered, $langcode), format_string('hreflang attribute with value @langcode is present on a rendered link when langcode is provided in the render array.', ['@langcode' => $langcode])); + + $rendered = $renderer->renderRoot($hreflang_override_link); + $this->assertTrue($this->hasAttribute('hreflang', $rendered, 'foo'), format_string('hreflang attribute with value @hreflang is present on a rendered link when @hreflang is provided in the render array.', ['@hreflang' => 'foo'])); + + // Test the active class in links produced by + // \Drupal\Core\Utility\LinkGeneratorInterface::generate() and #type 'link'. + $options_no_query = []; + $options_query = [ + 'query' => [ + 'foo' => 'bar', + 'one' => 'two', + ], + ]; + $options_query_reverse = [ + 'query' => [ + 'one' => 'two', + 'foo' => 'bar', + ], + ]; + + // Test #type link. + $path = 'common-test/type-link-active-class'; + + $this->drupalGet($path, $options_no_query); + $links = $this->xpath('//a[@href = :href and contains(@class, :class)]', [':href' => Url::fromRoute('common_test.l_active_class', [], $options_no_query)->toString(), ':class' => 'is-active']); + $this->assertTrue(isset($links[0]), 'A link generated by the link generator to the current page is marked active.'); + + $links = $this->xpath('//a[@href = :href and not(contains(@class, :class))]', [':href' => Url::fromRoute('common_test.l_active_class', [], $options_query)->toString(), ':class' => 'is-active']); + $this->assertTrue(isset($links[0]), 'A link generated by the link generator to the current page with a query string when the current page has no query string is not marked active.'); + + $this->drupalGet($path, $options_query); + $links = $this->xpath('//a[@href = :href and contains(@class, :class)]', [':href' => Url::fromRoute('common_test.l_active_class', [], $options_query)->toString(), ':class' => 'is-active']); + $this->assertTrue(isset($links[0]), 'A link generated by the link generator to the current page with a query string that matches the current query string is marked active.'); + + $links = $this->xpath('//a[@href = :href and contains(@class, :class)]', [':href' => Url::fromRoute('common_test.l_active_class', [], $options_query_reverse)->toString(), ':class' => 'is-active']); + $this->assertTrue(isset($links[0]), 'A link generated by the link generator to the current page with a query string that has matching parameters to the current query string but in a different order is marked active.'); + + $links = $this->xpath('//a[@href = :href and not(contains(@class, :class))]', [':href' => Url::fromRoute('common_test.l_active_class', [], $options_no_query)->toString(), ':class' => 'is-active']); + $this->assertTrue(isset($links[0]), 'A link generated by the link generator to the current page without a query string when the current page has a query string is not marked active.'); + + // Test adding a custom class in links produced by + // \Drupal\Core\Utility\LinkGeneratorInterface::generate() and #type 'link'. + // Test the link generator. + $class_l = $this->randomMachineName(); + $link_l = \Drupal::l($this->randomMachineName(), new Url('', [], ['attributes' => ['class' => [$class_l]]])); + $this->assertTrue($this->hasAttribute('class', $link_l, $class_l), format_string('Custom class @class is present on link when requested by l()', ['@class' => $class_l])); + + // Test #type. + $class_theme = $this->randomMachineName(); + $type_link = [ + '#type' => 'link', + '#title' => $this->randomMachineName(), + '#url' => Url::fromRoute(''), + '#options' => [ + 'attributes' => [ + 'class' => [$class_theme], + ], + ], + ]; + $link_theme = $renderer->renderRoot($type_link); + $this->assertTrue($this->hasAttribute('class', $link_theme, $class_theme), format_string('Custom class @class is present on link when requested by #type', ['@class' => $class_theme])); + } + + /** + * Tests that link functions support render arrays as 'text'. + */ + public function testLinkRenderArrayText() { + /** @var \Drupal\Core\Render\RendererInterface $renderer */ + $renderer = $this->container->get('renderer'); + + // Build a link with the link generator for reference. + $l = \Drupal::l('foo', Url::fromUri('https://www.drupal.org')); + + // Test a renderable array passed to the link generator. + $renderer->executeInRenderContext(new RenderContext(), function () use ($renderer, $l) { + $renderable_text = ['#markup' => 'foo']; + $l_renderable_text = \Drupal::l($renderable_text, Url::fromUri('https://www.drupal.org')); + $this->assertEqual($l_renderable_text, $l); + }); + + // Test a themed link with plain text 'text'. + $type_link_plain_array = [ + '#type' => 'link', + '#title' => 'foo', + '#url' => Url::fromUri('https://www.drupal.org'), + ]; + $type_link_plain = $renderer->renderRoot($type_link_plain_array); + $this->assertEqual($type_link_plain, $l); + + // Build a themed link with renderable 'text'. + $type_link_nested_array = [ + '#type' => 'link', + '#title' => ['#markup' => 'foo'], + '#url' => Url::fromUri('https://www.drupal.org'), + ]; + $type_link_nested = $renderer->renderRoot($type_link_nested_array); + $this->assertEqual($type_link_nested, $l); + } + + /** + * Checks for class existence in link. + * + * @param $link + * URL to search. + * @param $class + * Element class to search for. + * + * @return bool + * TRUE if the class is found, FALSE otherwise. + */ + private function hasAttribute($attribute, $link, $class) { + return preg_match('|' . $attribute . '="([^\"\s]+\s+)*' . $class . '|', $link); + } + + /** + * Tests UrlHelper::filterQueryParameters(). + */ + public function testDrupalGetQueryParameters() { + $original = [ + 'a' => 1, + 'b' => [ + 'd' => 4, + 'e' => [ + 'f' => 5, + ], + ], + 'c' => 3, + ]; + + // First-level exclusion. + $result = $original; + unset($result['b']); + $this->assertEqual(UrlHelper::filterQueryParameters($original, ['b']), $result, "'b' was removed."); + + // Second-level exclusion. + $result = $original; + unset($result['b']['d']); + $this->assertEqual(UrlHelper::filterQueryParameters($original, ['b[d]']), $result, "'b[d]' was removed."); + + // Third-level exclusion. + $result = $original; + unset($result['b']['e']['f']); + $this->assertEqual(UrlHelper::filterQueryParameters($original, ['b[e][f]']), $result, "'b[e][f]' was removed."); + + // Multiple exclusions. + $result = $original; + unset($result['a'], $result['b']['e'], $result['c']); + $this->assertEqual(UrlHelper::filterQueryParameters($original, ['a', 'b[e]', 'c']), $result, "'a', 'b[e]', 'c' were removed."); + } + + /** + * Tests UrlHelper::parse(). + */ + public function testDrupalParseUrl() { + // Relative, absolute, and external URLs, without/with explicit script path, + // without/with Drupal path. + foreach (['', '/', 'https://www.drupal.org/'] as $absolute) { + foreach (['', 'index.php/'] as $script) { + foreach (['', 'foo/bar'] as $path) { + $url = $absolute . $script . $path . '?foo=bar&bar=baz&baz#foo'; + $expected = [ + 'path' => $absolute . $script . $path, + 'query' => ['foo' => 'bar', 'bar' => 'baz', 'baz' => ''], + 'fragment' => 'foo', + ]; + $this->assertEqual(UrlHelper::parse($url), $expected, 'URL parsed correctly.'); + } + } + } + + // Relative URL that is known to confuse parse_url(). + $url = 'foo/bar:1'; + $result = [ + 'path' => 'foo/bar:1', + 'query' => [], + 'fragment' => '', + ]; + $this->assertEqual(UrlHelper::parse($url), $result, 'Relative URL parsed correctly.'); + + // Test that drupal can recognize an absolute URL. Used to prevent attack vectors. + $url = 'https://www.drupal.org/foo/bar?foo=bar&bar=baz&baz#foo'; + $this->assertTrue(UrlHelper::isExternal($url), 'Correctly identified an external URL.'); + + // Test that UrlHelper::parse() does not allow spoofing a URL to force a malicious redirect. + $parts = UrlHelper::parse('forged:http://cwe.mitre.org/data/definitions/601.html'); + $this->assertFalse(UrlHelper::isValid($parts['path'], TRUE), '\Drupal\Component\Utility\UrlHelper::isValid() correctly parsed a forged URL.'); + } + + /** + * Tests external URL handling. + */ + public function testExternalUrls() { + $test_url = 'https://www.drupal.org/'; + + // Verify external URL can contain a fragment. + $url = $test_url . '#drupal'; + $result = Url::fromUri($url)->toString(); + $this->assertEqual($url, $result, 'External URL with fragment works without a fragment in $options.'); + + // Verify fragment can be overridden in an external URL. + $url = $test_url . '#drupal'; + $fragment = $this->randomMachineName(10); + $result = Url::fromUri($url, ['fragment' => $fragment])->toString(); + $this->assertEqual($test_url . '#' . $fragment, $result, 'External URL fragment is overridden with a custom fragment in $options.'); + + // Verify external URL can contain a query string. + $url = $test_url . '?drupal=awesome'; + $result = Url::fromUri($url)->toString(); + $this->assertEqual($url, $result); + + // Verify external URL can be extended with a query string. + $url = $test_url; + $query = ['awesome' => 'drupal']; + $result = Url::fromUri($url, ['query' => $query])->toString(); + $this->assertSame('https://www.drupal.org/?awesome=drupal', $result); + + // Verify query string can be extended in an external URL. + $url = $test_url . '?drupal=awesome'; + $query = ['awesome' => 'drupal']; + $result = Url::fromUri($url, ['query' => $query])->toString(); + $this->assertEqual('https://www.drupal.org/?awesome=drupal&drupal=awesome', $result); + } + +} diff -r e200cb7efeb3 -r c2387f117808 core/modules/system/tests/src/Functional/Entity/Update/SqlContentEntityStorageSchemaConverterNonTranslatableTest.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/core/modules/system/tests/src/Functional/Entity/Update/SqlContentEntityStorageSchemaConverterNonTranslatableTest.php Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,23 @@ +databaseDumpFiles = [ + __DIR__ . '/../../../../fixtures/update/drupal-8.0.0-rc1-filled.standard.entity_test_update.php.gz', + __DIR__ . '/../../../../fixtures/update/drupal-8.entity-test-schema-converter-enabled.php', + ]; + } + +} diff -r e200cb7efeb3 -r c2387f117808 core/modules/system/tests/src/Functional/Entity/Update/SqlContentEntityStorageSchemaConverterTest.php --- a/core/modules/system/tests/src/Functional/Entity/Update/SqlContentEntityStorageSchemaConverterTest.php Thu Apr 26 11:26:54 2018 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,269 +0,0 @@ -entityManager = \Drupal::entityManager(); - $this->entityDefinitionUpdateManager = \Drupal::entityDefinitionUpdateManager(); - $this->lastInstalledSchemaRepository = \Drupal::service('entity.last_installed_schema.repository'); - $this->installedStorageSchema = \Drupal::keyValue('entity.storage_schema.sql'); - $this->state = \Drupal::state(); - } - - /** - * {@inheritdoc} - */ - protected function setDatabaseDumpFiles() { - $this->databaseDumpFiles = [ - __DIR__ . '/../../../../fixtures/update/drupal-8.0.0-rc1-filled.standard.entity_test_update_mul.php.gz', - __DIR__ . '/../../../../fixtures/update/drupal-8.entity-test-schema-converter-enabled.php', - ]; - } - - /** - * Tests the conversion of an entity type to revisionable. - */ - public function testMakeRevisionable() { - // Check that entity type is not revisionable prior to running the update - // process. - $entity_test_update = $this->lastInstalledSchemaRepository->getLastInstalledDefinition('entity_test_update'); - $this->assertFalse($entity_test_update->isRevisionable()); - - // Make the entity type revisionable and translatable and run the updates. - $this->updateEntityTypeToRevisionableAndTranslatable(); - - $this->runUpdates(); - - /** @var \Drupal\Core\Entity\EntityTypeInterface $entity_test_update */ - $entity_test_update = $this->lastInstalledSchemaRepository->getLastInstalledDefinition('entity_test_update'); - $this->assertTrue($entity_test_update->isRevisionable()); - - $field_storage_definitions = $this->lastInstalledSchemaRepository->getLastInstalledFieldStorageDefinitions('entity_test_update'); - $this->assertTrue(isset($field_storage_definitions['revision_translation_affected'])); - - /** @var \Drupal\Core\Entity\Sql\SqlEntityStorageInterface $storage */ - $storage = \Drupal::entityTypeManager()->getStorage('entity_test_update'); - $this->assertEqual(count($storage->loadMultiple()), 102, 'All test entities were found.'); - - // Check that each field value was copied correctly to the revision tables. - for ($i = 1; $i <= 102; $i++) { - /** @var \Drupal\Core\Entity\ContentEntityInterface $revision */ - $revision = $storage->loadRevision($i); - - $this->assertEqual($i, $revision->id()); - $this->assertEqual($i, $revision->getRevisionId()); - - // Check that the correct initial value was provided for the - // 'revision_translation_affected' field. - $this->assertTrue($revision->revision_translation_affected->value); - - $this->assertEqual($i . ' - test single property', $revision->test_single_property->value); - - $this->assertEqual($i . ' - test multiple properties - value1', $revision->test_multiple_properties->value1); - $this->assertEqual($i . ' - test multiple properties - value2', $revision->test_multiple_properties->value2); - - $this->assertEqual($i . ' - test single property multiple values 0', $revision->test_single_property_multiple_values->value); - $this->assertEqual($i . ' - test single property multiple values 1', $revision->test_single_property_multiple_values[1]->value); - - $this->assertEqual($i . ' - test multiple properties multiple values - value1 0', $revision->test_multiple_properties_multiple_values[0]->value1); - $this->assertEqual($i . ' - test multiple properties multiple values - value2 0', $revision->test_multiple_properties_multiple_values[0]->value2); - $this->assertEqual($i . ' - test multiple properties multiple values - value1 1', $revision->test_multiple_properties_multiple_values[1]->value1); - $this->assertEqual($i . ' - test multiple properties multiple values - value2 1', $revision->test_multiple_properties_multiple_values[1]->value2); - - $this->assertEqual($i . ' - field test configurable field - value1 0', $revision->field_test_configurable_field[0]->value1); - $this->assertEqual($i . ' - field test configurable field - value2 0', $revision->field_test_configurable_field[0]->value2); - $this->assertEqual($i . ' - field test configurable field - value1 1', $revision->field_test_configurable_field[1]->value1); - $this->assertEqual($i . ' - field test configurable field - value2 1', $revision->field_test_configurable_field[1]->value2); - - $this->assertEqual($i . ' - test entity base field info', $revision->test_entity_base_field_info->value); - - // Do the same checks for translated field values. - $translation = $revision->getTranslation('ro'); - - $this->assertEqual($i . ' - test single property - ro', $translation->test_single_property->value); - - $this->assertEqual($i . ' - test multiple properties - value1 - ro', $translation->test_multiple_properties->value1); - $this->assertEqual($i . ' - test multiple properties - value2 - ro', $translation->test_multiple_properties->value2); - - $this->assertEqual($i . ' - test single property multiple values 0 - ro', $translation->test_single_property_multiple_values[0]->value); - $this->assertEqual($i . ' - test single property multiple values 1 - ro', $translation->test_single_property_multiple_values[1]->value); - - $this->assertEqual($i . ' - test multiple properties multiple values - value1 0 - ro', $translation->test_multiple_properties_multiple_values[0]->value1); - $this->assertEqual($i . ' - test multiple properties multiple values - value2 0 - ro', $translation->test_multiple_properties_multiple_values[0]->value2); - $this->assertEqual($i . ' - test multiple properties multiple values - value1 1 - ro', $translation->test_multiple_properties_multiple_values[1]->value1); - $this->assertEqual($i . ' - test multiple properties multiple values - value2 1 - ro', $translation->test_multiple_properties_multiple_values[1]->value2); - - $this->assertEqual($i . ' - field test configurable field - value1 0 - ro', $translation->field_test_configurable_field[0]->value1); - $this->assertEqual($i . ' - field test configurable field - value2 0 - ro', $translation->field_test_configurable_field[0]->value2); - $this->assertEqual($i . ' - field test configurable field - value1 1 - ro', $translation->field_test_configurable_field[1]->value1); - $this->assertEqual($i . ' - field test configurable field - value2 1 - ro', $translation->field_test_configurable_field[1]->value2); - - $this->assertEqual($i . ' - test entity base field info - ro', $translation->test_entity_base_field_info->value); - } - - // Check that temporary tables have been removed at the end of the process. - $schema = \Drupal::database()->schema(); - foreach ($storage->getTableMapping()->getTableNames() as $table_name) { - $this->assertFalse($schema->tableExists(TemporaryTableMapping::getTempTableName($table_name))); - } - - // Check that backup tables have been removed at the end of the process. - $schema = \Drupal::database()->schema(); - foreach ($storage->getTableMapping()->getTableNames() as $table_name) { - $this->assertFalse($schema->tableExists(TemporaryTableMapping::getTempTableName($table_name, 'old_'))); - } - } - - /** - * Tests that a failed "make revisionable" update preserves the existing data. - */ - public function testMakeRevisionableErrorHandling() { - $original_entity_type = $this->lastInstalledSchemaRepository->getLastInstalledDefinition('entity_test_update'); - $original_storage_definitions = $this->lastInstalledSchemaRepository->getLastInstalledFieldStorageDefinitions('entity_test_update'); - - $original_entity_schema_data = $this->installedStorageSchema->get('entity_test_update.entity_schema_data', []); - foreach ($original_storage_definitions as $storage_definition) { - $original_field_schema_data[$storage_definition->getName()] = $this->installedStorageSchema->get('entity_test_update.field_schema_data.' . $storage_definition->getName(), []); - } - - // Check that entity type is not revisionable prior to running the update - // process. - $this->assertFalse($original_entity_type->isRevisionable()); - - // Make the update throw an exception during the entity save process. - \Drupal::state()->set('entity_test_update.throw_exception', TRUE); - - // Since the update process is interrupted by the exception thrown above, - // we can not do the full post update testing offered by UpdatePathTestBase. - $this->checkFailedUpdates = FALSE; - - // Make the entity type revisionable and run the updates. - $this->updateEntityTypeToRevisionableAndTranslatable(); - - $this->runUpdates(); - - // Check that the update failed. - $this->assertRaw('' . t('Failed:') . ''); - - // Check that the last installed entity type definition is kept as - // non-revisionable. - $new_entity_type = $this->lastInstalledSchemaRepository->getLastInstalledDefinition('entity_test_update'); - $this->assertFalse($new_entity_type->isRevisionable(), 'The entity type is kept unchanged.'); - - // Check that the last installed field storage definitions did not change by - // looking at the 'langcode' field, which is updated automatically. - $new_storage_definitions = $this->lastInstalledSchemaRepository->getLastInstalledFieldStorageDefinitions('entity_test_update'); - $langcode_key = $original_entity_type->getKey('langcode'); - $this->assertEqual($original_storage_definitions[$langcode_key]->isRevisionable(), $new_storage_definitions[$langcode_key]->isRevisionable(), "The 'langcode' field is kept unchanged."); - - /** @var \Drupal\Core\Entity\Sql\SqlEntityStorageInterface $storage */ - $storage = \Drupal::entityTypeManager()->getStorage('entity_test_update'); - - // Check that installed storage schema did not change. - $new_entity_schema_data = $this->installedStorageSchema->get('entity_test_update.entity_schema_data', []); - $this->assertEqual($original_entity_schema_data, $new_entity_schema_data); - - foreach ($new_storage_definitions as $storage_definition) { - $new_field_schema_data[$storage_definition->getName()] = $this->installedStorageSchema->get('entity_test_update.field_schema_data.' . $storage_definition->getName(), []); - } - $this->assertEqual($original_field_schema_data, $new_field_schema_data); - - // Check that temporary tables have been removed. - $schema = \Drupal::database()->schema(); - foreach ($storage->getTableMapping()->getTableNames() as $table_name) { - $this->assertFalse($schema->tableExists(TemporaryTableMapping::getTempTableName($table_name))); - } - - // Check that the original tables still exist and their data is intact. - $this->assertTrue($schema->tableExists('entity_test_update')); - $this->assertTrue($schema->tableExists('entity_test_update_data')); - - $base_table_count = \Drupal::database()->select('entity_test_update') - ->countQuery() - ->execute() - ->fetchField(); - $this->assertEqual($base_table_count, 102); - - $data_table_count = \Drupal::database()->select('entity_test_update_data') - ->countQuery() - ->execute() - ->fetchField(); - // There are two records for each entity, one for English and one for - // Romanian. - $this->assertEqual($data_table_count, 204); - - $base_table_row = \Drupal::database()->select('entity_test_update') - ->fields('entity_test_update') - ->condition('id', 1, '=') - ->condition('langcode', 'en', '=') - ->execute() - ->fetchAllAssoc('id'); - $this->assertEqual('843e9ac7-3351-4cc1-a202-2dbffffae21c', $base_table_row[1]->uuid); - - $data_table_row = \Drupal::database()->select('entity_test_update_data') - ->fields('entity_test_update_data') - ->condition('id', 1, '=') - ->condition('langcode', 'en', '=') - ->execute() - ->fetchAllAssoc('id'); - $this->assertEqual('1 - test single property', $data_table_row[1]->test_single_property); - $this->assertEqual('1 - test multiple properties - value1', $data_table_row[1]->test_multiple_properties__value1); - $this->assertEqual('1 - test multiple properties - value2', $data_table_row[1]->test_multiple_properties__value2); - $this->assertEqual('1 - test entity base field info', $data_table_row[1]->test_entity_base_field_info); - } - -} diff -r e200cb7efeb3 -r c2387f117808 core/modules/system/tests/src/Functional/Entity/Update/SqlContentEntityStorageSchemaConverterTestBase.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/core/modules/system/tests/src/Functional/Entity/Update/SqlContentEntityStorageSchemaConverterTestBase.php Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,170 @@ +entityManager = \Drupal::entityManager(); + $this->entityDefinitionUpdateManager = \Drupal::entityDefinitionUpdateManager(); + $this->lastInstalledSchemaRepository = \Drupal::service('entity.last_installed_schema.repository'); + $this->installedStorageSchema = \Drupal::keyValue('entity.storage_schema.sql'); + $this->state = \Drupal::state(); + } + + /** + * Tests the conversion of an entity type to revisionable. + */ + public function testMakeRevisionable() { + // Check that entity type is not revisionable prior to running the update + // process. + $entity_test_update = $this->lastInstalledSchemaRepository->getLastInstalledDefinition('entity_test_update'); + $this->assertFalse($entity_test_update->isRevisionable()); + + $translatable = $entity_test_update->isTranslatable(); + + // Make the entity type revisionable and run the updates. + if ($translatable) { + $this->updateEntityTypeToRevisionableAndTranslatable(); + } + else { + $this->updateEntityTypeToRevisionable(); + } + + $this->runUpdates(); + + /** @var \Drupal\Core\Entity\EntityTypeInterface $entity_test_update */ + $entity_test_update = $this->lastInstalledSchemaRepository->getLastInstalledDefinition('entity_test_update'); + $field_storage_definitions = $this->lastInstalledSchemaRepository->getLastInstalledFieldStorageDefinitions('entity_test_update'); + + $this->assertTrue($entity_test_update->isRevisionable()); + $this->assertEquals($translatable, isset($field_storage_definitions['revision_translation_affected'])); + + /** @var \Drupal\Core\Entity\Sql\SqlEntityStorageInterface $storage */ + $storage = \Drupal::entityTypeManager()->getStorage('entity_test_update'); + $this->assertEqual(count($storage->loadMultiple()), 102, 'All test entities were found.'); + + // Check that each field value was copied correctly to the revision tables. + for ($i = 1; $i <= 102; $i++) { + /** @var \Drupal\Core\Entity\ContentEntityInterface $revision */ + $revision = $storage->loadRevision($i); + + $this->assertEqual($i, $revision->id()); + $this->assertEqual($i, $revision->getRevisionId()); + + $this->assertEqual($i . ' - test single property', $revision->test_single_property->value); + + $this->assertEqual($i . ' - test multiple properties - value1', $revision->test_multiple_properties->value1); + $this->assertEqual($i . ' - test multiple properties - value2', $revision->test_multiple_properties->value2); + + $this->assertEqual($i . ' - test single property multiple values 0', $revision->test_single_property_multiple_values->value); + $this->assertEqual($i . ' - test single property multiple values 1', $revision->test_single_property_multiple_values[1]->value); + + $this->assertEqual($i . ' - test multiple properties multiple values - value1 0', $revision->test_multiple_properties_multiple_values[0]->value1); + $this->assertEqual($i . ' - test multiple properties multiple values - value2 0', $revision->test_multiple_properties_multiple_values[0]->value2); + $this->assertEqual($i . ' - test multiple properties multiple values - value1 1', $revision->test_multiple_properties_multiple_values[1]->value1); + $this->assertEqual($i . ' - test multiple properties multiple values - value2 1', $revision->test_multiple_properties_multiple_values[1]->value2); + + $this->assertEqual($i . ' - field test configurable field - value1 0', $revision->field_test_configurable_field[0]->value1); + $this->assertEqual($i . ' - field test configurable field - value2 0', $revision->field_test_configurable_field[0]->value2); + $this->assertEqual($i . ' - field test configurable field - value1 1', $revision->field_test_configurable_field[1]->value1); + $this->assertEqual($i . ' - field test configurable field - value2 1', $revision->field_test_configurable_field[1]->value2); + + $this->assertEqual($i . ' - test entity base field info', $revision->test_entity_base_field_info->value); + + // Do the same checks for translated field values if the entity type is + // translatable. + if (!$translatable) { + continue; + } + + // Check that the correct initial value was provided for the + // 'revision_translation_affected' field. + $this->assertTrue($revision->revision_translation_affected->value); + + $translation = $revision->getTranslation('ro'); + + $this->assertEqual($i . ' - test single property - ro', $translation->test_single_property->value); + + $this->assertEqual($i . ' - test multiple properties - value1 - ro', $translation->test_multiple_properties->value1); + $this->assertEqual($i . ' - test multiple properties - value2 - ro', $translation->test_multiple_properties->value2); + + $this->assertEqual($i . ' - test single property multiple values 0 - ro', $translation->test_single_property_multiple_values[0]->value); + $this->assertEqual($i . ' - test single property multiple values 1 - ro', $translation->test_single_property_multiple_values[1]->value); + + $this->assertEqual($i . ' - test multiple properties multiple values - value1 0 - ro', $translation->test_multiple_properties_multiple_values[0]->value1); + $this->assertEqual($i . ' - test multiple properties multiple values - value2 0 - ro', $translation->test_multiple_properties_multiple_values[0]->value2); + $this->assertEqual($i . ' - test multiple properties multiple values - value1 1 - ro', $translation->test_multiple_properties_multiple_values[1]->value1); + $this->assertEqual($i . ' - test multiple properties multiple values - value2 1 - ro', $translation->test_multiple_properties_multiple_values[1]->value2); + + $this->assertEqual($i . ' - field test configurable field - value1 0 - ro', $translation->field_test_configurable_field[0]->value1); + $this->assertEqual($i . ' - field test configurable field - value2 0 - ro', $translation->field_test_configurable_field[0]->value2); + $this->assertEqual($i . ' - field test configurable field - value1 1 - ro', $translation->field_test_configurable_field[1]->value1); + $this->assertEqual($i . ' - field test configurable field - value2 1 - ro', $translation->field_test_configurable_field[1]->value2); + + $this->assertEqual($i . ' - test entity base field info - ro', $translation->test_entity_base_field_info->value); + } + + // Check that temporary tables have been removed at the end of the process. + $schema = \Drupal::database()->schema(); + foreach ($storage->getTableMapping()->getTableNames() as $table_name) { + $this->assertFalse($schema->tableExists(TemporaryTableMapping::getTempTableName($table_name))); + } + + // Check that backup tables have been removed at the end of the process. + $schema = \Drupal::database()->schema(); + foreach ($storage->getTableMapping()->getTableNames() as $table_name) { + $this->assertFalse($schema->tableExists(TemporaryTableMapping::getTempTableName($table_name, 'old_'))); + } + } + +} diff -r e200cb7efeb3 -r c2387f117808 core/modules/system/tests/src/Functional/Entity/Update/SqlContentEntityStorageSchemaConverterTranslatableTest.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/core/modules/system/tests/src/Functional/Entity/Update/SqlContentEntityStorageSchemaConverterTranslatableTest.php Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,123 @@ +databaseDumpFiles = [ + __DIR__ . '/../../../../fixtures/update/drupal-8.0.0-rc1-filled.standard.entity_test_update_mul.php.gz', + __DIR__ . '/../../../../fixtures/update/drupal-8.entity-test-schema-converter-enabled.php', + ]; + } + + /** + * Tests that a failed "make revisionable" update preserves the existing data. + */ + public function testMakeRevisionableErrorHandling() { + $original_entity_type = $this->lastInstalledSchemaRepository->getLastInstalledDefinition('entity_test_update'); + $original_storage_definitions = $this->lastInstalledSchemaRepository->getLastInstalledFieldStorageDefinitions('entity_test_update'); + + $original_entity_schema_data = $this->installedStorageSchema->get('entity_test_update.entity_schema_data', []); + foreach ($original_storage_definitions as $storage_definition) { + $original_field_schema_data[$storage_definition->getName()] = $this->installedStorageSchema->get('entity_test_update.field_schema_data.' . $storage_definition->getName(), []); + } + + // Check that entity type is not revisionable prior to running the update + // process. + $this->assertFalse($original_entity_type->isRevisionable()); + + // Make the update throw an exception during the entity save process. + \Drupal::state()->set('entity_test_update.throw_exception', TRUE); + + // Since the update process is interrupted by the exception thrown above, + // we can not do the full post update testing offered by UpdatePathTestBase. + $this->checkFailedUpdates = FALSE; + + // Make the entity type revisionable and run the updates. + $this->updateEntityTypeToRevisionableAndTranslatable(); + + $this->runUpdates(); + + // Check that the update failed. + $this->assertRaw('' . t('Failed:') . ''); + + // Check that the last installed entity type definition is kept as + // non-revisionable. + $new_entity_type = $this->lastInstalledSchemaRepository->getLastInstalledDefinition('entity_test_update'); + $this->assertFalse($new_entity_type->isRevisionable(), 'The entity type is kept unchanged.'); + + // Check that the last installed field storage definitions did not change by + // looking at the 'langcode' field, which is updated automatically. + $new_storage_definitions = $this->lastInstalledSchemaRepository->getLastInstalledFieldStorageDefinitions('entity_test_update'); + $langcode_key = $original_entity_type->getKey('langcode'); + $this->assertEqual($original_storage_definitions[$langcode_key]->isRevisionable(), $new_storage_definitions[$langcode_key]->isRevisionable(), "The 'langcode' field is kept unchanged."); + + /** @var \Drupal\Core\Entity\Sql\SqlEntityStorageInterface $storage */ + $storage = \Drupal::entityTypeManager()->getStorage('entity_test_update'); + + // Check that installed storage schema did not change. + $new_entity_schema_data = $this->installedStorageSchema->get('entity_test_update.entity_schema_data', []); + $this->assertEqual($original_entity_schema_data, $new_entity_schema_data); + + foreach ($new_storage_definitions as $storage_definition) { + $new_field_schema_data[$storage_definition->getName()] = $this->installedStorageSchema->get('entity_test_update.field_schema_data.' . $storage_definition->getName(), []); + } + $this->assertEqual($original_field_schema_data, $new_field_schema_data); + + // Check that temporary tables have been removed. + $schema = \Drupal::database()->schema(); + foreach ($storage->getTableMapping()->getTableNames() as $table_name) { + $this->assertFalse($schema->tableExists(TemporaryTableMapping::getTempTableName($table_name))); + } + + // Check that the original tables still exist and their data is intact. + $this->assertTrue($schema->tableExists('entity_test_update')); + $this->assertTrue($schema->tableExists('entity_test_update_data')); + + $base_table_count = \Drupal::database()->select('entity_test_update') + ->countQuery() + ->execute() + ->fetchField(); + $this->assertEqual($base_table_count, 102); + + $data_table_count = \Drupal::database()->select('entity_test_update_data') + ->countQuery() + ->execute() + ->fetchField(); + // There are two records for each entity, one for English and one for + // Romanian. + $this->assertEqual($data_table_count, 204); + + $base_table_row = \Drupal::database()->select('entity_test_update') + ->fields('entity_test_update') + ->condition('id', 1, '=') + ->condition('langcode', 'en', '=') + ->execute() + ->fetchAllAssoc('id'); + $this->assertEqual('843e9ac7-3351-4cc1-a202-2dbffffae21c', $base_table_row[1]->uuid); + + $data_table_row = \Drupal::database()->select('entity_test_update_data') + ->fields('entity_test_update_data') + ->condition('id', 1, '=') + ->condition('langcode', 'en', '=') + ->execute() + ->fetchAllAssoc('id'); + $this->assertEqual('1 - test single property', $data_table_row[1]->test_single_property); + $this->assertEqual('1 - test multiple properties - value1', $data_table_row[1]->test_multiple_properties__value1); + $this->assertEqual('1 - test multiple properties - value2', $data_table_row[1]->test_multiple_properties__value2); + $this->assertEqual('1 - test entity base field info', $data_table_row[1]->test_entity_base_field_info); + } + +} diff -r e200cb7efeb3 -r c2387f117808 core/modules/system/tests/src/Functional/Form/FormObjectTest.php --- a/core/modules/system/tests/src/Functional/Form/FormObjectTest.php Thu Apr 26 11:26:54 2018 +0100 +++ b/core/modules/system/tests/src/Functional/Form/FormObjectTest.php Tue Jul 10 15:07:59 2018 +0100 @@ -2,15 +2,14 @@ namespace Drupal\Tests\system\Functional\Form; -use Drupal\system\Tests\System\SystemConfigFormTestBase; -use Drupal\form_test\FormTestObject; +use Drupal\Tests\BrowserTestBase; /** * Tests building a form from an object. * * @group Form */ -class FormObjectTest extends SystemConfigFormTestBase { +class FormObjectTest extends BrowserTestBase { /** * Modules to enable. @@ -19,19 +18,6 @@ */ public static $modules = ['form_test']; - protected function setUp() { - parent::setUp(); - - $this->form = new FormTestObject($this->container->get('config.factory')); - $this->values = [ - 'bananas' => [ - '#value' => $this->randomString(10), - '#config_name' => 'form_test.object', - '#config_key' => 'bananas', - ], - ]; - } - /** * Tests using an object as the form callback. * diff -r e200cb7efeb3 -r c2387f117808 core/modules/system/tests/src/Functional/Hal/ActionHalJsonAnonTest.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/core/modules/system/tests/src/Functional/Hal/ActionHalJsonAnonTest.php Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,30 @@ +grantPermissionsToTestedRole(['administer actions']); + } + + /** + * {@inheritdoc} + */ + protected function createEntity() { + $action = Action::create([ + 'id' => 'user_add_role_action.' . RoleInterface::ANONYMOUS_ID, + 'type' => 'user', + 'label' => t('Add the anonymous role to the selected users'), + 'configuration' => [ + 'rid' => RoleInterface::ANONYMOUS_ID, + ], + 'plugin' => 'user_add_role_action', + ]); + $action->save(); + + return $action; + } + + /** + * {@inheritdoc} + */ + protected function getExpectedNormalizedEntity() { + return [ + 'configuration' => [ + 'rid' => 'anonymous', + ], + 'dependencies' => [ + 'config' => ['user.role.anonymous'], + 'module' => ['user'], + ], + 'id' => 'user_add_role_action.anonymous', + 'label' => 'Add the anonymous role to the selected users', + 'langcode' => 'en', + 'plugin' => 'user_add_role_action', + 'status' => TRUE, + 'type' => 'user', + 'uuid' => $this->entity->uuid(), + ]; + } + + /** + * {@inheritdoc} + */ + protected function getExpectedCacheContexts() { + return [ + 'user.permissions', + ]; + } + + /** + * {@inheritdoc} + */ + protected function getNormalizedPostEntity() { + // @todo Update in https://www.drupal.org/node/2300677. + } + +} diff -r e200cb7efeb3 -r c2387f117808 core/modules/system/tests/src/Functional/Rest/ActionXmlAnonTest.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/core/modules/system/tests/src/Functional/Rest/ActionXmlAnonTest.php Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,26 @@ +grantPermissionsToTestedRole(['administer menu']); + } + + /** + * {@inheritdoc} + */ + protected function createEntity() { + $menu = Menu::create([ + 'id' => 'menu', + 'label' => 'Menu', + 'description' => 'Menu', + ]); + $menu->save(); + + return $menu; + } + + /** + * {@inheritdoc} + */ + protected function getExpectedNormalizedEntity() { + return [ + 'dependencies' => [], + 'description' => 'Menu', + 'id' => 'menu', + 'label' => 'Menu', + 'langcode' => 'en', + 'locked' => FALSE, + 'status' => TRUE, + 'uuid' => $this->entity->uuid(), + ]; + } + + /** + * {@inheritdoc} + */ + protected function getNormalizedPostEntity() { + // @todo Update in https://www.drupal.org/node/2300677. + } + + /** + * {@inheritdoc} + */ + protected function getExpectedCacheContexts() { + return [ + 'user.permissions', + ]; + } + +} diff -r e200cb7efeb3 -r c2387f117808 core/modules/system/tests/src/Functional/Rest/MenuXmlAnonTest.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/core/modules/system/tests/src/Functional/Rest/MenuXmlAnonTest.php Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,26 @@ +form = new FormTestObject($this->container->get('config.factory')); + $this->values = [ + 'bananas' => [ + '#value' => $this->randomString(10), + '#config_name' => 'form_test.object', + '#config_key' => 'bananas', + ], + ]; + } + +} diff -r e200cb7efeb3 -r c2387f117808 core/modules/system/tests/src/Kernel/Plugin/migrate/source/ExtensionTest.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/core/modules/system/tests/src/Kernel/Plugin/migrate/source/ExtensionTest.php Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,77 @@ + 'sites/all/modules/i18n/i18nmenu/i18nmenu.module', + 'name' => 'i18nmenu', + 'type' => 'module', + 'owner' => '', + 'status' => '1', + 'throttle' => '0', + 'bootstrap' => '0', + 'schema_version' => '0', + 'weight' => '0', + 'info' => 'a:10:{s:4:"name";s:16:"Menu translation";s:11:"description";s:40:"Supports translatable custom menu items.";s:12:"dependencies";a:4:{i:0;s:4:"i18n";i:1;s:4:"menu";i:2;s:10:"i18nblocks";i:3;s:11:"i18nstrings";}s:7:"package";s:13:"Multilanguage";s:4:"core";s:3:"6.x";s:7:"version";s:8:"6.x-1.10";s:7:"project";s:4:"i18n";s:9:"datestamp";s:10:"1318336004";s:10:"dependents";a:0:{}s:3:"php";s:5:"4.3.5";},', + ], + [ + 'filename' => 'sites/all/modules/variable/variable.module ', + 'name' => 'variable', + 'type' => 'module', + 'owner' => '', + 'status' => '1', + 'throttle' => '0', + 'bootstrap' => '0', + 'schema_version' => '-1', + 'weight' => '0', + 'info' => 'a:9:{s:4:"name";s:12:"Variable API";s:11:"description";s:12:"Variable API";s:4:"core";s:3:"6.x";s:7:"version";s:14:"6.x-1.0-alpha1";s:7:"project";s:8:"variable";s:9:"datestamp";s:10:"1414059742";s:12:"dependencies";a:0:{}s:10:"dependents";a:0:{}s:3:"php";s:5:"4.3.5";}', + ], + ]; + + $info = unserialize('a:9:{s:4:"name";s:12:"Variable API";s:11:"description";s:12:"Variable API";s:4:"core";s:3:"6.x";s:7:"version";s:14:"6.x-1.0-alpha1";s:7:"project";s:8:"variable";s:9:"datestamp";s:10:"1414059742";s:12:"dependencies";a:0:{}s:10:"dependents";a:0:{}s:3:"php";s:5:"4.3.5";}'); + $test[0]['expected_results'] = [ + [ + 'filename' => 'sites/all/modules/variable/variable.module ', + 'name' => 'variable', + 'type' => 'module', + 'owner' => '', + 'status' => '1', + 'throttle' => '0', + 'bootstrap' => '0', + 'schema_version' => '-1', + 'weight' => '0', + 'info' => $info, + ], + ]; + + $test[0]['expected_count'] = NULL; + $test[0]['configuration'] = [ + 'name' => 'variable', + ]; + + return $test; + } + +} diff -r e200cb7efeb3 -r c2387f117808 core/modules/system/tests/themes/test_theme_settings_features/config/schema/test_theme_settings_features.schema.yml --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/core/modules/system/tests/themes/test_theme_settings_features/config/schema/test_theme_settings_features.schema.yml Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,3 @@ +test_theme_settings_features.settings: + type: theme_settings + label: 'Test theme settings' diff -r e200cb7efeb3 -r c2387f117808 core/modules/system/tests/themes/test_theme_settings_features/test_theme_settings_features.info.yml --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/core/modules/system/tests/themes/test_theme_settings_features/test_theme_settings_features.info.yml Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,8 @@ +name: Test features +type: theme +core: 8.x +description: 'Test theme to test theme settings with limited features.' +features: + - node_user_picture + - comment_user_picture + - comment_user_verification diff -r e200cb7efeb3 -r c2387f117808 core/modules/taxonomy/src/Form/OverviewTerms.php --- a/core/modules/taxonomy/src/Form/OverviewTerms.php Thu Apr 26 11:26:54 2018 +0100 +++ b/core/modules/taxonomy/src/Form/OverviewTerms.php Tue Jul 10 15:07:59 2018 +0100 @@ -241,6 +241,11 @@ $form['terms'] = [ '#type' => 'table', '#empty' => $empty, + '#header' => [ + 'term' => $this->t('Name'), + 'operations' => $this->t('Operations'), + 'weight' => $this->t('Weight'), + ], '#attributes' => [ 'id' => 'taxonomy', ], @@ -251,6 +256,11 @@ // all terms. $change_weight_access = AccessResult::allowed(); foreach ($current_page as $key => $term) { + $form['terms'][$key] = [ + 'term' => [], + 'operations' => [], + 'weight' => [], + ]; /** @var $term \Drupal\Core\Entity\EntityInterface */ $term = $this->entityManager->getTranslationFromContext($term); $form['terms'][$key]['#term'] = $term; @@ -344,11 +354,8 @@ $row_position++; } - $form['terms']['#header'] = [$this->t('Name')]; - $this->renderer->addCacheableDependency($form['terms'], $change_weight_access); if ($change_weight_access->isAllowed()) { - $form['terms']['#header'][] = $this->t('Weight'); if ($parent_fields) { $form['terms']['#tabledrag'][] = [ 'action' => 'match', @@ -377,8 +384,6 @@ ]; } - $form['terms']['#header'][] = $this->t('Operations'); - if (($taxonomy_vocabulary->getHierarchy() !== VocabularyInterface::HIERARCHY_MULTIPLE && count($tree) > 1) && $change_weight_access->isAllowed()) { $form['actions'] = ['#type' => 'actions', '#tree' => FALSE]; $form['actions']['submit'] = [ diff -r e200cb7efeb3 -r c2387f117808 core/modules/taxonomy/src/TermInterface.php --- a/core/modules/taxonomy/src/TermInterface.php Thu Apr 26 11:26:54 2018 +0100 +++ b/core/modules/taxonomy/src/TermInterface.php Tue Jul 10 15:07:59 2018 +0100 @@ -57,7 +57,7 @@ /** * Sets the name of the term. * - * @param int $name + * @param string $name * The term's name. * * @return $this diff -r e200cb7efeb3 -r c2387f117808 core/modules/taxonomy/src/VocabularyListBuilder.php --- a/core/modules/taxonomy/src/VocabularyListBuilder.php Thu Apr 26 11:26:54 2018 +0100 +++ b/core/modules/taxonomy/src/VocabularyListBuilder.php Tue Jul 10 15:07:59 2018 +0100 @@ -123,7 +123,7 @@ $header['label'] = t('Vocabulary name'); $header['description'] = t('Description'); - if ($this->currentUser->hasPermission('administer vocabularies')) { + if ($this->currentUser->hasPermission('administer vocabularies') && !empty($this->weightKey)) { $header['weight'] = t('Weight'); } diff -r e200cb7efeb3 -r c2387f117808 core/modules/taxonomy/taxonomy.module --- a/core/modules/taxonomy/taxonomy.module Thu Apr 26 11:26:54 2018 +0100 +++ b/core/modules/taxonomy/taxonomy.module Tue Jul 10 15:07:59 2018 +0100 @@ -213,7 +213,8 @@ * content language of the current request. * * @return array - * A $page element suitable for use by drupal_render(). + * A $page element suitable for use by + * \Drupal\Core\Render\RendererInterface::render(). */ function taxonomy_term_view(Term $term, $view_mode = 'full', $langcode = NULL) { return entity_view($term, $view_mode, $langcode); @@ -231,7 +232,8 @@ * content language of the current request. * * @return array - * An array in the format expected by drupal_render(). + * An array in the format expected by + * \Drupal\Core\Render\RendererInterface::render(). */ function taxonomy_term_view_multiple(array $terms, $view_mode = 'full', $langcode = NULL) { return entity_view_multiple($terms, $view_mode, $langcode); diff -r e200cb7efeb3 -r c2387f117808 core/modules/taxonomy/tests/src/Functional/Hal/TermHalJsonAnonTest.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/core/modules/taxonomy/tests/src/Functional/Hal/TermHalJsonAnonTest.php Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,65 @@ +applyHalFieldNormalization($default_normalization); + + return $normalization + [ + '_links' => [ + 'self' => [ + 'href' => $this->baseUrl . '/llama?_format=hal_json', + ], + 'type' => [ + 'href' => $this->baseUrl . '/rest/type/taxonomy_term/camelids', + ], + ], + ]; + } + + /** + * {@inheritdoc} + */ + protected function getNormalizedPostEntity() { + return parent::getNormalizedPostEntity() + [ + '_links' => [ + 'type' => [ + 'href' => $this->baseUrl . '/rest/type/taxonomy_term/camelids', + ], + ], + ]; + } + +} diff -r e200cb7efeb3 -r c2387f117808 core/modules/taxonomy/tests/src/Functional/Hal/TermHalJsonBasicAuthTest.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/core/modules/taxonomy/tests/src/Functional/Hal/TermHalJsonBasicAuthTest.php Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,24 @@ +markTestSkipped(); + } + +} diff -r e200cb7efeb3 -r c2387f117808 core/modules/taxonomy/tests/src/Functional/Hal/VocabularyHalJsonBasicAuthTest.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/core/modules/taxonomy/tests/src/Functional/Hal/VocabularyHalJsonBasicAuthTest.php Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,35 @@ +grantPermissionsToTestedRole(['access content']); + break; + + case 'POST': + $this->grantPermissionsToTestedRole(['create terms in camelids']); + break; + + case 'PATCH': + // Grant the 'create url aliases' permission to test the case when + // the path field is accessible, see + // \Drupal\Tests\rest\Functional\EntityResource\Node\NodeResourceTestBase + // for a negative test. + $this->grantPermissionsToTestedRole(['edit terms in camelids', 'create url aliases']); + break; + + case 'DELETE': + $this->grantPermissionsToTestedRole(['delete terms in camelids']); + break; + + } + } + + /** + * {@inheritdoc} + */ + protected function createEntity() { + $vocabulary = Vocabulary::load('camelids'); + if (!$vocabulary) { + // Create a "Camelids" vocabulary. + $vocabulary = Vocabulary::create([ + 'name' => 'Camelids', + 'vid' => 'camelids', + ]); + $vocabulary->save(); + } + + // Create a "Llama" taxonomy term. + $term = Term::create(['vid' => $vocabulary->id()]) + ->setName('Llama') + ->setDescription("It is a little known fact that llamas cannot count higher than seven.") + ->setChangedTime(123456789) + ->set('path', '/llama'); + $term->save(); + + return $term; + } + + /** + * {@inheritdoc} + */ + protected function getExpectedNormalizedEntity() { + return [ + 'tid' => [ + ['value' => 1], + ], + 'uuid' => [ + ['value' => $this->entity->uuid()], + ], + 'vid' => [ + [ + 'target_id' => 'camelids', + 'target_type' => 'taxonomy_vocabulary', + 'target_uuid' => Vocabulary::load('camelids')->uuid(), + ], + ], + 'name' => [ + ['value' => 'Llama'], + ], + 'description' => [ + [ + 'value' => 'It is a little known fact that llamas cannot count higher than seven.', + 'format' => NULL, + 'processed' => "

      It is a little known fact that llamas cannot count higher than seven.

      \n", + ], + ], + 'parent' => [], + 'weight' => [ + ['value' => 0], + ], + 'langcode' => [ + [ + 'value' => 'en', + ], + ], + 'changed' => [ + $this->formatExpectedTimestampItemValues($this->entity->getChangedTime()), + ], + 'default_langcode' => [ + [ + 'value' => TRUE, + ], + ], + 'path' => [ + [ + 'alias' => '/llama', + 'pid' => 1, + 'langcode' => 'en', + ], + ], + ]; + } + + /** + * {@inheritdoc} + */ + protected function getNormalizedPostEntity() { + return [ + 'vid' => [ + [ + 'target_id' => 'camelids', + ], + ], + 'name' => [ + [ + 'value' => 'Dramallama', + ], + ], + 'description' => [ + [ + 'value' => 'Dramallamas are the coolest camelids.', + 'format' => NULL, + ], + ], + ]; + } + + /** + * {@inheritdoc} + */ + protected function getExpectedUnauthorizedAccessMessage($method) { + if ($this->config('rest.settings')->get('bc_entity_resource_permissions')) { + return parent::getExpectedUnauthorizedAccessMessage($method); + } + + switch ($method) { + case 'GET': + return "The 'access content' permission is required."; + case 'POST': + return "The following permissions are required: 'create terms in camelids' OR 'administer taxonomy'."; + case 'PATCH': + return "The following permissions are required: 'edit terms in camelids' OR 'administer taxonomy'."; + case 'DELETE': + return "The following permissions are required: 'delete terms in camelids' OR 'administer taxonomy'."; + default: + return parent::getExpectedUnauthorizedAccessMessage($method); + } + } + + /** + * Tests PATCHing a term's path. + * + * For a negative test, see the similar test coverage for Node. + * + * @see \Drupal\Tests\rest\Functional\EntityResource\Node\NodeResourceTestBase::testPatchPath() + */ + public function testPatchPath() { + $this->initAuthentication(); + $this->provisionEntityResource(); + $this->setUpAuthorization('GET'); + $this->setUpAuthorization('PATCH'); + + $url = $this->getEntityResourceUrl()->setOption('query', ['_format' => static::$format]); + + // GET term's current normalization. + $response = $this->request('GET', $url, $this->getAuthenticationRequestOptions('GET')); + $normalization = $this->serializer->decode((string) $response->getBody(), static::$format); + + // Change term's path alias. + $normalization['path'][0]['alias'] .= 's-rule-the-world'; + + // Create term PATCH request. + $request_options = []; + $request_options[RequestOptions::HEADERS]['Content-Type'] = static::$mimeType; + $request_options = array_merge_recursive($request_options, $this->getAuthenticationRequestOptions('PATCH')); + $request_options[RequestOptions::BODY] = $this->serializer->encode($normalization, static::$format); + + // PATCH request: 200. + $response = $this->request('PATCH', $url, $request_options); + $this->assertResourceResponse(200, FALSE, $response); + $updated_normalization = $this->serializer->decode((string) $response->getBody(), static::$format); + $this->assertSame($normalization['path'], $updated_normalization['path']); + } + + /** + * {@inheritdoc} + */ + protected function getExpectedCacheTags() { + return Cache::mergeTags(parent::getExpectedCacheTags(), ['config:filter.format.plain_text', 'config:filter.settings']); + } + + /** + * {@inheritdoc} + */ + protected function getExpectedCacheContexts() { + return Cache::mergeContexts(['url.site'], $this->container->getParameter('renderer.config')['required_cache_contexts']); + } + +} diff -r e200cb7efeb3 -r c2387f117808 core/modules/taxonomy/tests/src/Functional/Rest/TermXmlAnonTest.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/core/modules/taxonomy/tests/src/Functional/Rest/TermXmlAnonTest.php Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,34 @@ +markTestSkipped(); + } + +} diff -r e200cb7efeb3 -r c2387f117808 core/modules/taxonomy/tests/src/Functional/Rest/TermXmlBasicAuthTest.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/core/modules/taxonomy/tests/src/Functional/Rest/TermXmlBasicAuthTest.php Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,44 @@ +markTestSkipped(); + } + +} diff -r e200cb7efeb3 -r c2387f117808 core/modules/taxonomy/tests/src/Functional/Rest/TermXmlCookieTest.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/core/modules/taxonomy/tests/src/Functional/Rest/TermXmlCookieTest.php Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,39 @@ +markTestSkipped(); + } + +} diff -r e200cb7efeb3 -r c2387f117808 core/modules/taxonomy/tests/src/Functional/Rest/VocabularyJsonAnonTest.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/core/modules/taxonomy/tests/src/Functional/Rest/VocabularyJsonAnonTest.php Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,32 @@ +markTestSkipped(); + } + +} diff -r e200cb7efeb3 -r c2387f117808 core/modules/taxonomy/tests/src/Functional/Rest/VocabularyJsonBasicAuthTest.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/core/modules/taxonomy/tests/src/Functional/Rest/VocabularyJsonBasicAuthTest.php Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,34 @@ +grantPermissionsToTestedRole(['administer taxonomy']); + } + + /** + * {@inheritdoc} + */ + protected function createEntity() { + $vocabulary = Vocabulary::create([ + 'name' => 'Llama', + 'vid' => 'llama', + ]); + $vocabulary->save(); + + return $vocabulary; + } + + /** + * {@inheritdoc} + */ + protected function getExpectedNormalizedEntity() { + return [ + 'uuid' => $this->entity->uuid(), + 'vid' => 'llama', + 'langcode' => 'en', + 'status' => TRUE, + 'dependencies' => [], + 'name' => 'Llama', + 'description' => NULL, + 'hierarchy' => 0, + 'weight' => 0, + ]; + } + + /** + * {@inheritdoc} + */ + protected function getNormalizedPostEntity() { + // @todo Update in https://www.drupal.org/node/2300677. + } + + /** + * {@inheritdoc} + */ + protected function getExpectedUnauthorizedAccessMessage($method) { + if ($this->config('rest.settings')->get('bc_entity_resource_permissions')) { + return parent::getExpectedUnauthorizedAccessMessage($method); + } + + if ($method === 'GET') { + return "The following permissions are required: 'access taxonomy overview' OR 'administer taxonomy'."; + } + return parent::getExpectedUnauthorizedAccessMessage($method); + } + +} diff -r e200cb7efeb3 -r c2387f117808 core/modules/taxonomy/tests/src/Functional/Rest/VocabularyXmlAnonTest.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/core/modules/taxonomy/tests/src/Functional/Rest/VocabularyXmlAnonTest.php Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,26 @@ +nodes[0]->url()); - $request->server->set('SCRIPT_NAME', $GLOBALS['base_path'] . 'index.php'); - $request->server->set('SCRIPT_FILENAME', 'index.php'); - - $response = $this->container->get('http_kernel') - ->handle($request, HttpKernelInterface::SUB_REQUEST); - $view->setRequest($request); - $view->setResponse($response); - - $view->initHandlers(); - $expected = implode(',', [$this->term1->id(), $this->term2->id()]); - $this->assertEqual($expected, $view->argument['tid']->getDefaultArgument()); - $view->destroy(); - } - - public function testNodePathWithViewSelection() { - // Change the term entity reference field to use a view as selection plugin. - \Drupal::service('module_installer')->install(['entity_reference_test']); - - $field_name = 'field_' . $this->vocabulary->id(); - $field = FieldConfig::loadByName('node', 'article', $field_name); - $field->setSetting('handler', 'views'); - $field->setSetting('handler_settings', [ - 'view' => [ - 'view_name' => 'test_entity_reference', - 'display_name' => 'entity_reference_1', - ], - ]); - $field->save(); - - $view = Views::getView('taxonomy_default_argument_test'); - - $request = Request::create($this->nodes[0]->url()); - $request->server->set('SCRIPT_NAME', $GLOBALS['base_path'] . 'index.php'); - $request->server->set('SCRIPT_FILENAME', 'index.php'); - - $response = $this->container->get('http_kernel')->handle($request, HttpKernelInterface::SUB_REQUEST); - $view->setRequest($request); - $view->setResponse($response); - - $view->initHandlers(); - $expected = implode(',', [$this->term1->id(), $this->term2->id()]); - $this->assertEqual($expected, $view->argument['tid']->getDefaultArgument()); - } - - public function testTermPath() { - $view = Views::getView('taxonomy_default_argument_test'); - - $request = Request::create($this->term1->url()); - $request->server->set('SCRIPT_NAME', $GLOBALS['base_path'] . 'index.php'); - $request->server->set('SCRIPT_FILENAME', 'index.php'); - - $response = $this->container->get('http_kernel')->handle($request, HttpKernelInterface::SUB_REQUEST); - $view->setRequest($request); - $view->setResponse($response); - $view->initHandlers(); - - $expected = $this->term1->id(); - $this->assertEqual($expected, $view->argument['tid']->getDefaultArgument()); - } - - /** * Tests escaping of page title when the taxonomy plugin provides it. */ public function testTermTitleEscaping() { diff -r e200cb7efeb3 -r c2387f117808 core/modules/taxonomy/tests/src/Functional/VocabularyPermissionsTest.php --- a/core/modules/taxonomy/tests/src/Functional/VocabularyPermissionsTest.php Thu Apr 26 11:26:54 2018 +0100 +++ b/core/modules/taxonomy/tests/src/Functional/VocabularyPermissionsTest.php Tue Jul 10 15:07:59 2018 +0100 @@ -83,6 +83,7 @@ $assert_session->linkExists('Add term'); $assert_session->buttonExists('Save'); $assert_session->pageTextContains('Weight'); + $assert_session->fieldExists('Weight'); $assert_session->pageTextContains($edit_help_text); // Visit vocabulary overview without terms. 'Add term' should be shown. @@ -108,7 +109,8 @@ $assert_session->linkNotExists('Edit'); $assert_session->linkNotExists('Delete'); $assert_session->buttonNotExists('Save'); - $assert_session->pageTextNotContains('Weight'); + $assert_session->pageTextContains('Weight'); + $assert_session->fieldNotExists('Weight'); $assert_session->linkNotExists('Add term'); $assert_session->pageTextContains($no_edit_help_text); @@ -132,6 +134,7 @@ $assert_session->linkNotExists('Delete'); $assert_session->buttonExists('Save'); $assert_session->pageTextContains('Weight'); + $assert_session->fieldExists('Weight'); $assert_session->linkNotExists('Add term'); $assert_session->pageTextContains($edit_help_text); @@ -154,7 +157,8 @@ $assert_session->linkExists('Delete'); $assert_session->linkNotExists('Add term'); $assert_session->buttonNotExists('Save'); - $assert_session->pageTextNotContains('Weight'); + $assert_session->pageTextContains('Weight'); + $assert_session->fieldNotExists('Weight'); $assert_session->pageTextContains($no_edit_help_text); // Visit vocabulary overview without terms. 'Add term' should not be shown. @@ -179,6 +183,7 @@ $assert_session->linkNotExists('Add term'); $assert_session->buttonExists('Save'); $assert_session->pageTextContains('Weight'); + $assert_session->fieldExists('Weight'); $assert_session->pageTextContains($edit_help_text); // Visit vocabulary overview without terms. 'Add term' should not be shown. @@ -201,7 +206,8 @@ $assert_session->linkNotExists('Delete'); $assert_session->linkExists('Add term'); $assert_session->buttonNotExists('Save'); - $assert_session->pageTextNotContains('Weight'); + $assert_session->pageTextContains('Weight'); + $assert_session->fieldNotExists('Weight'); $assert_session->pageTextContains($no_edit_help_text); // Visit vocabulary overview without terms. 'Add term' should not be shown. diff -r e200cb7efeb3 -r c2387f117808 core/modules/taxonomy/tests/src/Kernel/Migrate/d6/MigrateTaxonomyVocabularyTest.php --- a/core/modules/taxonomy/tests/src/Kernel/Migrate/d6/MigrateTaxonomyVocabularyTest.php Thu Apr 26 11:26:54 2018 +0100 +++ b/core/modules/taxonomy/tests/src/Kernel/Migrate/d6/MigrateTaxonomyVocabularyTest.php Tue Jul 10 15:07:59 2018 +0100 @@ -32,7 +32,7 @@ for ($i = 0; $i < 3; $i++) { $j = $i + 1; $vocabulary = Vocabulary::load("vocabulary_{$j}_i_{$i}_"); - $this->assertSame($this->getMigration('d6_taxonomy_vocabulary')->getIdMap()->lookupDestinationID([$j]), [$vocabulary->id()]); + $this->assertSame($this->getMigration('d6_taxonomy_vocabulary')->getIdMap()->lookupDestinationId([$j]), [$vocabulary->id()]); $this->assertSame("vocabulary $j (i=$i)", $vocabulary->label()); $this->assertSame("description of vocabulary $j (i=$i)", $vocabulary->getDescription()); $this->assertSame($i, $vocabulary->getHierarchy()); diff -r e200cb7efeb3 -r c2387f117808 core/modules/taxonomy/tests/src/Kernel/Migrate/d6/MigrateVocabularyEntityDisplayTest.php --- a/core/modules/taxonomy/tests/src/Kernel/Migrate/d6/MigrateVocabularyEntityDisplayTest.php Thu Apr 26 11:26:54 2018 +0100 +++ b/core/modules/taxonomy/tests/src/Kernel/Migrate/d6/MigrateVocabularyEntityDisplayTest.php Tue Jul 10 15:07:59 2018 +0100 @@ -45,7 +45,7 @@ $this->assertSame('entity_reference_label', $component['type']); $this->assertSame(20, $component['weight']); // Test the Id map. - $this->assertSame(['node', 'article', 'default', 'field_tags'], $this->getMigration('d6_vocabulary_entity_display')->getIdMap()->lookupDestinationID([4, 'article'])); + $this->assertSame(['node', 'article', 'default', 'field_tags'], $this->getMigration('d6_vocabulary_entity_display')->getIdMap()->lookupDestinationId([4, 'article'])); // Tests that a vocabulary named like a D8 base field will be migrated and // prefixed with 'field_' to avoid conflicts. diff -r e200cb7efeb3 -r c2387f117808 core/modules/taxonomy/tests/src/Kernel/Migrate/d6/MigrateVocabularyEntityFormDisplayTest.php --- a/core/modules/taxonomy/tests/src/Kernel/Migrate/d6/MigrateVocabularyEntityFormDisplayTest.php Thu Apr 26 11:26:54 2018 +0100 +++ b/core/modules/taxonomy/tests/src/Kernel/Migrate/d6/MigrateVocabularyEntityFormDisplayTest.php Tue Jul 10 15:07:59 2018 +0100 @@ -45,7 +45,7 @@ $this->assertSame('options_select', $component['type']); $this->assertSame(20, $component['weight']); // Test the Id map. - $this->assertSame(['node', 'article', 'default', 'field_tags'], $this->getMigration('d6_vocabulary_entity_form_display')->getIdMap()->lookupDestinationID([4, 'article'])); + $this->assertSame(['node', 'article', 'default', 'field_tags'], $this->getMigration('d6_vocabulary_entity_form_display')->getIdMap()->lookupDestinationId([4, 'article'])); // Test the term widget tags setting. $entity_form_display = EntityFormDisplay::load('node.story.default'); diff -r e200cb7efeb3 -r c2387f117808 core/modules/taxonomy/tests/src/Kernel/Migrate/d6/MigrateVocabularyFieldInstanceTest.php --- a/core/modules/taxonomy/tests/src/Kernel/Migrate/d6/MigrateVocabularyFieldInstanceTest.php Thu Apr 26 11:26:54 2018 +0100 +++ b/core/modules/taxonomy/tests/src/Kernel/Migrate/d6/MigrateVocabularyFieldInstanceTest.php Tue Jul 10 15:07:59 2018 +0100 @@ -58,7 +58,7 @@ $this->assertSame(['field_tags'], $settings['handler_settings']['target_bundles'], 'The target_bundles handler setting is correct.'); $this->assertSame(TRUE, $settings['handler_settings']['auto_create'], 'The "auto_create" setting is correct.'); - $this->assertSame(['node', 'article', 'field_tags'], $this->getMigration('d6_vocabulary_field_instance')->getIdMap()->lookupDestinationID([4, 'article'])); + $this->assertSame(['node', 'article', 'field_tags'], $this->getMigration('d6_vocabulary_field_instance')->getIdMap()->lookupDestinationId([4, 'article'])); // Test the the field vocabulary_1_i_0_. $field_id = 'node.story.field_vocabulary_1_i_0_'; diff -r e200cb7efeb3 -r c2387f117808 core/modules/taxonomy/tests/src/Kernel/Migrate/d6/MigrateVocabularyFieldTest.php --- a/core/modules/taxonomy/tests/src/Kernel/Migrate/d6/MigrateVocabularyFieldTest.php Thu Apr 26 11:26:54 2018 +0100 +++ b/core/modules/taxonomy/tests/src/Kernel/Migrate/d6/MigrateVocabularyFieldTest.php Tue Jul 10 15:07:59 2018 +0100 @@ -39,7 +39,7 @@ $this->assertSame('taxonomy_term', $settings['target_type'], "Target type is correct."); $this->assertSame(1, $field_storage->getCardinality(), "Field cardinality in 1."); - $this->assertSame(['node', 'field_tags'], $this->getMigration('d6_vocabulary_field')->getIdMap()->lookupDestinationID([4]), "Test IdMap"); + $this->assertSame(['node', 'field_tags'], $this->getMigration('d6_vocabulary_field')->getIdMap()->lookupDestinationId([4]), "Test IdMap"); // Tests that a vocabulary named like a D8 base field will be migrated and // prefixed with 'field_' to avoid conflicts. diff -r e200cb7efeb3 -r c2387f117808 core/modules/taxonomy/tests/src/Kernel/Views/TaxonomyDefaultArgumentTest.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/core/modules/taxonomy/tests/src/Kernel/Views/TaxonomyDefaultArgumentTest.php Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,93 @@ +server->set('SCRIPT_NAME', $GLOBALS['base_path'] . 'index.php'); + $request->server->set('SCRIPT_FILENAME', 'index.php'); + + $response = $this->container->get('http_kernel') + ->handle($request, HttpKernelInterface::SUB_REQUEST); + + $view->setRequest($request); + $view->setResponse($response); + $view->initHandlers(); + + return $view; + } + + /** + * Tests the relationship. + */ + public function testNodePath() { + $view = $this->initViewWithRequest($this->nodes[0]->url()); + + $expected = implode(',', [$this->term1->id(), $this->term2->id()]); + $this->assertEqual($expected, $view->argument['tid']->getDefaultArgument()); + $view->destroy(); + } + + public function testNodePathWithViewSelection() { + // Change the term entity reference field to use a view as selection plugin. + \Drupal::service('module_installer')->install(['entity_reference_test']); + + $field_name = 'field_' . $this->vocabulary->id(); + $field = FieldConfig::loadByName('node', 'article', $field_name); + $field->setSetting('handler', 'views'); + $field->setSetting('handler_settings', [ + 'view' => [ + 'view_name' => 'test_entity_reference', + 'display_name' => 'entity_reference_1', + ], + ]); + $field->save(); + + $view = $this->initViewWithRequest($this->nodes[0]->url()); + + $expected = implode(',', [$this->term1->id(), $this->term2->id()]); + $this->assertEqual($expected, $view->argument['tid']->getDefaultArgument()); + } + + public function testTermPath() { + $view = $this->initViewWithRequest($this->term1->url()); + + $expected = $this->term1->id(); + $this->assertEqual($expected, $view->argument['tid']->getDefaultArgument()); + } + +} diff -r e200cb7efeb3 -r c2387f117808 core/modules/taxonomy/tests/src/Kernel/Views/TaxonomyTestBase.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/core/modules/taxonomy/tests/src/Kernel/Views/TaxonomyTestBase.php Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,184 @@ +installConfig(['node', 'filter']); + $this->installEntitySchema('user'); + $this->installEntitySchema('taxonomy_term'); + $this->mockStandardInstall(); + + if ($import_test_views) { + ViewTestData::createTestViews(get_class($this), ['taxonomy_test_views']); + } + + $this->term1 = $this->createTerm(); + $this->term2 = $this->createTerm(); + + $node = []; + $node['type'] = 'article'; + $node['field_views_testing_tags'][]['target_id'] = $this->term1->id(); + $node['field_views_testing_tags'][]['target_id'] = $this->term2->id(); + $this->nodes[] = $this->drupalCreateNode($node); + $this->nodes[] = $this->drupalCreateNode($node); + } + + /** + * Provides a workaround for the inability to use the standard profile. + * + * @see https://www.drupal.org/node/1708692 + */ + protected function mockStandardInstall() { + $this->drupalCreateContentType([ + 'type' => 'article', + ]); + + // Create the vocabulary for the tag field. + $this->vocabulary = Vocabulary::create([ + 'name' => 'Views testing tags', + 'vid' => 'views_testing_tags', + ]); + $this->vocabulary->save(); + $field_name = 'field_' . $this->vocabulary->id(); + + $handler_settings = [ + 'target_bundles' => [ + $this->vocabulary->id() => $this->vocabulary->id(), + ], + 'auto_create' => TRUE, + ]; + + $this->installEntitySchema('node'); + $this->createEntityReferenceField('node', 'article', $field_name, 'Tags', 'taxonomy_term', 'default', $handler_settings, FieldStorageDefinitionInterface::CARDINALITY_UNLIMITED); + $entity_type_manager = $this->container->get('entity_type.manager'); + $entity_type_manager + ->getStorage('entity_form_display') + ->load('node.article.default') + ->setComponent($field_name, [ + 'type' => 'entity_reference_autocomplete_tags', + 'weight' => -4, + ]) + ->save(); + + $view_modes = [ + 'default', + 'teaser', + ]; + foreach ($view_modes as $view_mode) { + $entity_type_manager + ->getStorage('entity_view_display') + ->load("node.article.{$view_mode}") + ->setComponent($field_name, [ + 'type' => 'entity_reference_label', + 'weight' => 10, + ]) + ->save(); + } + } + + /** + * Creates and returns a taxonomy term. + * + * @param array $settings + * (optional) An array of values to override the following default + * properties of the term: + * - name: A random string. + * - description: A random string. + * - format: First available text format. + * - vid: Vocabulary ID of self::$vocabulary object. + * - langcode: LANGCODE_NOT_SPECIFIED. + * Defaults to an empty array. + * + * @return \Drupal\taxonomy\Entity\Term + * The created taxonomy term. + */ + protected function createTerm(array $settings = []) { + $filter_formats = filter_formats(); + $format = array_pop($filter_formats); + $settings += [ + 'name' => $this->randomMachineName(), + 'description' => $this->randomMachineName(), + // Use the first available text format. + 'format' => $format->id(), + 'vid' => $this->vocabulary->id(), + 'langcode' => LanguageInterface::LANGCODE_NOT_SPECIFIED, + ]; + $term = Term::create($settings); + $term->save(); + return $term; + } + +} diff -r e200cb7efeb3 -r c2387f117808 core/modules/text/tests/src/FunctionalJavascript/TextareaWithSummaryTest.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/core/modules/text/tests/src/FunctionalJavascript/TextareaWithSummaryTest.php Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,85 @@ +drupalCreateContentType(['type' => 'page']); + + $account = $this->drupalCreateUser(['create page content', 'edit own page content']); + $this->drupalLogin($account); + } + + /** + * Helper to test toggling the summary area. + */ + protected function assertSummaryToggle() { + $this->drupalGet('node/add/page'); + $widget = $this->getSession()->getPage()->findById('edit-body-wrapper'); + $summary_field = $widget->findField('edit-body-0-summary'); + + $this->assertEquals(FALSE, $summary_field->isVisible(), 'Summary field is hidden by default.'); + $this->assertEquals(FALSE, $widget->hasButton('Hide summary'), 'No Hide summary link by default.'); + + $widget->pressButton('Edit summary'); + $this->assertEquals(FALSE, $widget->hasButton('Edit summary'), 'Edit summary link is removed after clicking.'); + $this->assertEquals(TRUE, $summary_field->isVisible(), 'Summary field is shown.'); + + $widget->pressButton('Hide summary'); + $this->assertEquals(FALSE, $widget->hasButton('Hide summary'), 'Hide summary link is removed after clicking.'); + $this->assertEquals(FALSE, $summary_field->isVisible(), 'Summary field is hidden again.'); + $this->assertEquals(TRUE, $widget->hasButton('Edit summary'), 'Edit summary link is visible again.'); + } + + /** + * Tests the textSummary javascript behavior. + */ + public function testTextSummaryBehavior() { + // Test with field defaults. + $this->assertSummaryToggle(); + + // Repeat test with non-empty field description. + $body_field = FieldConfig::loadByName('node', 'page', 'body'); + $body_field->set('description', 'Text with Summary field description.'); + $body_field->save(); + + $this->assertSummaryToggle(); + + // Test summary is shown when non-empty. + $node = $this->createNode([ + 'body' => [ + [ + 'value' => $this->randomMachineName(32), + 'summary' => $this->randomMachineName(32), + 'format' => filter_default_format(), + ], + ], + ]); + + $this->drupalGet('node/' . $node->id() . '/edit'); + $page = $this->getSession()->getPage(); + $summary_field = $page->findField('edit-body-0-summary'); + + $this->assertEquals(TRUE, $summary_field->isVisible(), 'Non-empty summary field is shown by default.'); + } + +} diff -r e200cb7efeb3 -r c2387f117808 core/modules/text/text.es6.js --- a/core/modules/text/text.es6.js Thu Apr 26 11:26:54 2018 +0100 +++ b/core/modules/text/text.es6.js Tue Jul 10 15:07:59 2018 +0100 @@ -19,7 +19,7 @@ const $summary = $widget.find('.js-text-summary-wrapper'); const $summaryLabel = $summary.find('label').eq(0); - const $full = $widget.find('.js-text-full').closest('.js-form-item'); + const $full = $widget.children('.js-form-type-textarea'); let $fullLabel = $full.find('label').eq(0); // Create a placeholder label when the field cardinality is greater diff -r e200cb7efeb3 -r c2387f117808 core/modules/text/text.js --- a/core/modules/text/text.js Thu Apr 26 11:26:54 2018 +0100 +++ b/core/modules/text/text.js Tue Jul 10 15:07:59 2018 +0100 @@ -13,7 +13,7 @@ var $summary = $widget.find('.js-text-summary-wrapper'); var $summaryLabel = $summary.find('label').eq(0); - var $full = $widget.find('.js-text-full').closest('.js-form-item'); + var $full = $widget.children('.js-form-type-textarea'); var $fullLabel = $full.find('label').eq(0); if ($fullLabel.length === 0) { diff -r e200cb7efeb3 -r c2387f117808 core/modules/toolbar/toolbar.module --- a/core/modules/toolbar/toolbar.module Thu Apr 26 11:26:54 2018 +0100 +++ b/core/modules/toolbar/toolbar.module Tue Jul 10 15:07:59 2018 +0100 @@ -217,7 +217,7 @@ * @return array * The updated renderable array. * - * @see drupal_render() + * @see \Drupal\Core\Render\RendererInterface::render() */ function toolbar_prerender_toolbar_administration_tray(array $element) { $menu_tree = \Drupal::service('toolbar.menu_tree'); diff -r e200cb7efeb3 -r c2387f117808 core/modules/tour/src/Plugin/tour/tip/TipPluginText.php --- a/core/modules/tour/src/Plugin/tour/tip/TipPluginText.php Thu Apr 26 11:26:54 2018 +0100 +++ b/core/modules/tour/src/Plugin/tour/tip/TipPluginText.php Tue Jul 10 15:07:59 2018 +0100 @@ -40,6 +40,13 @@ protected $location; /** + * Unique aria-id. + * + * @var string + */ + protected $ariaId; + + /** * Constructs a \Drupal\tour\Plugin\tour\tip\TipPluginText object. * * @param array $configuration @@ -70,11 +77,10 @@ * A unique id to be used to generate aria attributes. */ public function getAriaId() { - static $id; - if (!isset($id)) { - $id = Html::getUniqueId($this->get('id')); + if (!$this->ariaId) { + $this->ariaId = Html::getUniqueId($this->get('id')); } - return $id; + return $this->ariaId; } /** diff -r e200cb7efeb3 -r c2387f117808 core/modules/tour/tests/src/Functional/Hal/TourHalJsonAnonTest.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/core/modules/tour/tests/src/Functional/Hal/TourHalJsonAnonTest.php Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,30 @@ +grantPermissionsToTestedRole(['access tour']); + } + + /** + * {@inheritdoc} + */ + protected function createEntity() { + $tour = Tour::create([ + 'id' => 'tour-llama', + 'label' => 'Llama tour', + 'langcode' => 'en', + 'module' => 'tour', + 'routes' => [ + [ + 'route_name' => '', + ], + ], + 'tips' => [ + 'tour-llama-1' => [ + 'id' => 'tour-llama-1', + 'plugin' => 'text', + 'label' => 'Llama', + 'body' => 'Who handle the awesomeness of llamas?', + 'weight' => 100, + 'attributes' => [ + 'data-id' => 'tour-llama-1', + ], + ], + ], + ]); + $tour->save(); + + return $tour; + } + + /** + * {@inheritdoc} + */ + protected function getExpectedNormalizedEntity() { + return [ + 'dependencies' => [], + 'id' => 'tour-llama', + 'label' => 'Llama tour', + 'langcode' => 'en', + 'module' => 'tour', + 'routes' => [ + [ + 'route_name' => '', + ], + ], + 'status' => TRUE, + 'tips' => [ + 'tour-llama-1' => [ + 'id' => 'tour-llama-1', + 'plugin' => 'text', + 'label' => 'Llama', + 'body' => 'Who handle the awesomeness of llamas?', + 'weight' => 100, + 'attributes' => [ + 'data-id' => 'tour-llama-1', + ], + ], + ], + 'uuid' => $this->entity->uuid(), + ]; + } + + /** + * {@inheritdoc} + */ + protected function getNormalizedPostEntity() { + // @todo Update in https://www.drupal.org/node/2300677. + } + + /** + * {@inheritdoc} + */ + protected function getExpectedCacheContexts() { + return [ + 'user.permissions', + ]; + } + + /** + * {@inheritdoc} + */ + protected function getExpectedUnauthorizedAccessMessage($method) { + if ($this->config('rest.settings')->get('bc_entity_resource_permissions')) { + return parent::getExpectedUnauthorizedAccessMessage($method); + } + + return "The following permissions are required: 'access tour' OR 'administer site configuration'."; + } + +} diff -r e200cb7efeb3 -r c2387f117808 core/modules/tour/tests/src/Functional/Rest/TourXmlAnonTest.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/core/modules/tour/tests/src/Functional/Rest/TourXmlAnonTest.php Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,26 @@ + $id_instance_one, + ]; + $config_instance_two = [ + 'id' => $id_instance_two, + ]; + $definition = []; + $plugin_id = 'text'; + $token = $this->createMock('\Drupal\Core\Utility\Token'); + $instance_one = new TipPluginText($config_instance_one, $plugin_id, $definition, $token); + $instance_two = new TipPluginText($config_instance_two, $plugin_id, $definition, $token); + $instance_three = new TipPluginText($config_instance_one, $plugin_id, $definition, $token); + + $this->assertEquals($id_instance_one, $instance_one->getAriaId()); + $this->assertEquals($id_instance_two, $instance_two->getAriaId()); + $this->assertNotEquals($instance_one->getAriaId(), $instance_two->getAriaId()); + $this->assertNotEquals($instance_one->getAriaId(), $instance_three->getAriaId()); + } + +} diff -r e200cb7efeb3 -r c2387f117808 core/modules/tracker/tests/src/Functional/TrackerTest.php --- a/core/modules/tracker/tests/src/Functional/TrackerTest.php Thu Apr 26 11:26:54 2018 +0100 +++ b/core/modules/tracker/tests/src/Functional/TrackerTest.php Tue Jul 10 15:07:59 2018 +0100 @@ -361,8 +361,14 @@ ]; $this->drupalPostForm('comment/reply/node/' . $nodes[3]->id() . '/comment', $comment, t('Save')); - // Start indexing backwards from node 3. - \Drupal::state()->set('tracker.index_nid', 3); + // Create an unpublished node. + $unpublished = $this->drupalCreateNode([ + 'title' => $this->randomMachineName(8), + 'status' => 0, + ]); + + // Start indexing backwards from node 4. + \Drupal::state()->set('tracker.index_nid', 4); // Clear the current tracker tables and rebuild them. db_delete('tracker_node') diff -r e200cb7efeb3 -r c2387f117808 core/modules/tracker/tracker.module --- a/core/modules/tracker/tracker.module Thu Apr 26 11:26:54 2018 +0100 +++ b/core/modules/tracker/tracker.module Tue Jul 10 15:07:59 2018 +0100 @@ -72,7 +72,7 @@ db_insert('tracker_node') ->fields([ 'nid' => $nid, - 'published' => $node->isPublished(), + 'published' => (int) $node->isPublished(), 'changed' => $changed, ]) ->execute(); @@ -81,7 +81,7 @@ db_insert('tracker_user') ->fields([ 'nid' => $nid, - 'published' => $node->isPublished(), + 'published' => (int) $node->isPublished(), 'changed' => $changed, 'uid' => $node->getOwnerId(), ]) diff -r e200cb7efeb3 -r c2387f117808 core/modules/user/migrations/user_profile_entity_display.yml --- a/core/modules/user/migrations/user_profile_entity_display.yml Thu Apr 26 11:26:54 2018 +0100 +++ b/core/modules/user/migrations/user_profile_entity_display.yml Tue Jul 10 15:07:59 2018 +0100 @@ -17,7 +17,18 @@ entity_type: 'constants/entity_type' bundle: 'constants/bundle' view_mode: 'constants/view_mode' - field_name: name + field_name: + - + plugin: migration_lookup + migration: user_profile_field + source: fid + - + plugin: skip_on_empty + method: row + - + plugin: extract + index: + - 1 type: plugin: static_map source: type diff -r e200cb7efeb3 -r c2387f117808 core/modules/user/migrations/user_profile_entity_form_display.yml --- a/core/modules/user/migrations/user_profile_entity_form_display.yml Thu Apr 26 11:26:54 2018 +0100 +++ b/core/modules/user/migrations/user_profile_entity_form_display.yml Tue Jul 10 15:07:59 2018 +0100 @@ -14,7 +14,18 @@ process: entity_type: 'constants/entity_type' bundle: 'constants/bundle' - field_name: name + field_name: + - + plugin: migration_lookup + migration: user_profile_field + source: fid + - + plugin: skip_on_empty + method: row + - + plugin: extract + index: + - 1 form_mode: 'constants/form_mode' type: plugin: static_map diff -r e200cb7efeb3 -r c2387f117808 core/modules/user/migrations/user_profile_field.yml --- a/core/modules/user/migrations/user_profile_field.yml Thu Apr 26 11:26:54 2018 +0100 +++ b/core/modules/user/migrations/user_profile_field.yml Tue Jul 10 15:07:59 2018 +0100 @@ -10,7 +10,15 @@ entity_type: user process: entity_type: 'constants/entity_type' - field_name: name + field_name: + - + plugin: machine_name + source: name + - + plugin: make_unique_entity_field + length: 30 + entity_type: field_storage_config + field: field_name type: plugin: static_map source: type diff -r e200cb7efeb3 -r c2387f117808 core/modules/user/migrations/user_profile_field_instance.yml --- a/core/modules/user/migrations/user_profile_field_instance.yml Thu Apr 26 11:26:54 2018 +0100 +++ b/core/modules/user/migrations/user_profile_field_instance.yml Tue Jul 10 15:07:59 2018 +0100 @@ -14,7 +14,18 @@ bundle: 'constants/bundle' label: title description: explanation - field_name: name + field_name: + - + plugin: migration_lookup + migration: user_profile_field + source: fid + - + plugin: skip_on_empty + method: row + - + plugin: extract + index: + - 1 required: required destination: plugin: entity:field_config diff -r e200cb7efeb3 -r c2387f117808 core/modules/user/src/Controller/UserController.php --- a/core/modules/user/src/Controller/UserController.php Thu Apr 26 11:26:54 2018 +0100 +++ b/core/modules/user/src/Controller/UserController.php Tue Jul 10 15:07:59 2018 +0100 @@ -312,7 +312,7 @@ // Since user_cancel() is not invoked via Form API, batch processing // needs to be invoked manually and should redirect to the front page // after completion. - return batch_process(''); + return batch_process(''); } else { drupal_set_message(t('You have tried to use an account cancellation link that has expired. Please request a new one using the form below.'), 'error'); diff -r e200cb7efeb3 -r c2387f117808 core/modules/user/src/Plugin/migrate/ProfileValues.php --- a/core/modules/user/src/Plugin/migrate/ProfileValues.php Thu Apr 26 11:26:54 2018 +0100 +++ b/core/modules/user/src/Plugin/migrate/ProfileValues.php Tue Jul 10 15:07:59 2018 +0100 @@ -3,6 +3,8 @@ namespace Drupal\user\Plugin\migrate; use Drupal\migrate\Exception\RequirementsException; +use Drupal\migrate\MigrateExecutable; +use Drupal\migrate\MigrateSkipRowException; use Drupal\migrate\Plugin\Migration; /** @@ -31,11 +33,28 @@ $definition['idMap']['plugin'] = 'null'; try { $profile_field_migration = $this->migrationPluginManager->createStubMigration($definition); + $migrate_executable = new MigrateExecutable($profile_field_migration); $source_plugin = $profile_field_migration->getSourcePlugin(); $source_plugin->checkRequirements(); foreach ($source_plugin as $row) { $name = $row->getSourceProperty('name'); - $this->process[$name] = $name; + $fid = $row->getSourceProperty('fid'); + // The user profile field name can be greater than 32 characters. Use + // the migrated profile field name in the process pipeline. + $configuration = + [ + 'migration' => 'user_profile_field', + 'source_ids' => $fid, + ]; + $plugin = $this->processPluginManager->createInstance('migration_lookup', $configuration, $profile_field_migration); + $new_value = $plugin->transform($fid, $migrate_executable, $row, 'tmp'); + if (isset($new_value[1])) { + // Set the destination to the migrated profile field name. + $this->process[$new_value[1]] = $name; + } + else { + throw new MigrateSkipRowException("Can't migrate source field $name."); + } } } catch (RequirementsException $e) { diff -r e200cb7efeb3 -r c2387f117808 core/modules/user/src/Plugin/migrate/destination/EntityUser.php --- a/core/modules/user/src/Plugin/migrate/destination/EntityUser.php Thu Apr 26 11:26:54 2018 +0100 +++ b/core/modules/user/src/Plugin/migrate/destination/EntityUser.php Tue Jul 10 15:07:59 2018 +0100 @@ -15,6 +15,52 @@ use Symfony\Component\DependencyInjection\ContainerInterface; /** + * Provides a destination plugin for migrating user entities. + * + * Example: + * + * The example below migrates users and preserves original passwords from a + * source that has passwords as MD5 hashes without salt. The passwords will be + * salted and re-hashed before they are saved to the destination Drupal + * database. The MD5 hash used in the example is a hash of 'password'. + * + * The example uses the EmbeddedDataSource source plugin for the sake of + * simplicity. The mapping between old user_ids and new Drupal uids is saved in + * the migration map table. + * @code + * id: custom_user_migration + * label: Custom user migration + * source: + * plugin: embedded_data + * data_rows: + * - + * user_id: 1 + * name: johnsmith + * mail: johnsmith@example.com + * hash: '5f4dcc3b5aa765d61d8327deb882cf99' + * ids: + * user_id: + * type: integer + * process: + * name: name + * mail: mail + * pass: hash + * status: + * plugin: default_value + * default_value: 1 + * destination: + * plugin: entity:user + * md5_passwords: true + * @endcode + * + * For configuration options inherited from the parent class, refer to + * \Drupal\migrate\Plugin\migrate\destination\EntityContentBase. + * + * The example above is about migrating an MD5 password hash. For more examples + * on different password hash types and a list of other user properties, refer + * to the handbook documentation: + * @see https://www.drupal.org/docs/8/api/migrate-api/migrate-destination-plugins-examples/migrating-users + * * @MigrateDestination( * id = "entity:user" * ) diff -r e200cb7efeb3 -r c2387f117808 core/modules/user/src/Plugin/migrate/source/d6/User.php --- a/core/modules/user/src/Plugin/migrate/source/d6/User.php Thu Apr 26 11:26:54 2018 +0100 +++ b/core/modules/user/src/Plugin/migrate/source/d6/User.php Tue Jul 10 15:07:59 2018 +0100 @@ -33,14 +33,6 @@ // Add roles field. $fields['roles'] = $this->t('Roles'); - // Profile fields. - if ($this->moduleExists('profile')) { - $fields += $this->select('profile_fields', 'pf') - ->fields('pf', ['name', 'title']) - ->execute() - ->fetchAllKeyed(); - } - return $fields; } diff -r e200cb7efeb3 -r c2387f117808 core/modules/user/src/Tests/UserAdminSettingsFormTest.php --- a/core/modules/user/src/Tests/UserAdminSettingsFormTest.php Thu Apr 26 11:26:54 2018 +0100 +++ b/core/modules/user/src/Tests/UserAdminSettingsFormTest.php Tue Jul 10 15:07:59 2018 +0100 @@ -2,7 +2,7 @@ namespace Drupal\user\Tests; -use Drupal\system\Tests\System\SystemConfigFormTestBase; +use Drupal\KernelTests\ConfigFormTestBase; use Drupal\user\AccountSettingsForm; /** @@ -10,8 +10,16 @@ * * @group user */ -class UserAdminSettingsFormTest extends SystemConfigFormTestBase { +class UserAdminSettingsFormTest extends ConfigFormTestBase { + /** + * {@inheritdoc} + */ + public static $modules = ['user', 'system']; + + /** + * {@inheritdoc} + */ protected function setUp() { parent::setUp(); diff -r e200cb7efeb3 -r c2387f117808 core/modules/user/tests/src/Functional/Hal/RoleHalJsonAnonTest.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/core/modules/user/tests/src/Functional/Hal/RoleHalJsonAnonTest.php Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,30 @@ +applyHalFieldNormalization($default_normalization); + + return $normalization + [ + '_links' => [ + 'self' => [ + 'href' => $this->baseUrl . '/user/3?_format=hal_json', + ], + 'type' => [ + 'href' => $this->baseUrl . '/rest/type/user/user', + ], + ], + ]; + } + + /** + * {@inheritdoc} + */ + protected function getNormalizedPostEntity() { + return parent::getNormalizedPostEntity() + [ + '_links' => [ + 'type' => [ + 'href' => $this->baseUrl . '/rest/type/user/user', + ], + ], + ]; + } + +} diff -r e200cb7efeb3 -r c2387f117808 core/modules/user/tests/src/Functional/Hal/UserHalJsonBasicAuthTest.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/core/modules/user/tests/src/Functional/Hal/UserHalJsonBasicAuthTest.php Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,24 @@ +grantPermissionsToTestedRole(['administer permissions']); + } + + /** + * {@inheritdoc} + */ + protected function createEntity() { + $role = Role::create([ + 'id' => 'llama', + 'name' => $this->randomString(), + ]); + $role->save(); + + return $role; + } + + /** + * {@inheritdoc} + */ + protected function getExpectedNormalizedEntity() { + return [ + 'uuid' => $this->entity->uuid(), + 'weight' => 2, + 'langcode' => 'en', + 'status' => TRUE, + 'dependencies' => [], + 'id' => 'llama', + 'label' => NULL, + 'is_admin' => NULL, + 'permissions' => [], + ]; + } + + /** + * {@inheritdoc} + */ + protected function getNormalizedPostEntity() { + // @todo Update in https://www.drupal.org/node/2300677. + } + +} diff -r e200cb7efeb3 -r c2387f117808 core/modules/user/tests/src/Functional/Rest/RoleXmlAnonTest.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/core/modules/user/tests/src/Functional/Rest/RoleXmlAnonTest.php Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,26 @@ +grantPermissionsToTestedRole(['access user profiles']); + break; + case 'POST': + case 'PATCH': + case 'DELETE': + $this->grantPermissionsToTestedRole(['administer users']); + break; + } + } + + /** + * {@inheritdoc} + */ + protected function createEntity() { + // Create a "Llama" user. + $user = User::create(['created' => 123456789]); + $user->setUsername('Llama') + ->setChangedTime(123456789) + ->activate() + ->save(); + + return $user; + } + + /** + * {@inheritdoc} + */ + protected function createAnotherEntity() { + /** @var \Drupal\user\UserInterface $user */ + $user = $this->entity->createDuplicate(); + $user->setUsername($user->label() . '_dupe'); + $user->save(); + return $user; + } + + /** + * {@inheritdoc} + */ + protected function getExpectedNormalizedEntity() { + return [ + 'uid' => [ + ['value' => 3], + ], + 'uuid' => [ + ['value' => $this->entity->uuid()], + ], + 'langcode' => [ + [ + 'value' => 'en', + ], + ], + 'name' => [ + [ + 'value' => 'Llama', + ], + ], + 'created' => [ + $this->formatExpectedTimestampItemValues(123456789), + ], + 'changed' => [ + $this->formatExpectedTimestampItemValues($this->entity->getChangedTime()), + ], + 'default_langcode' => [ + [ + 'value' => TRUE, + ], + ], + ]; + } + + /** + * {@inheritdoc} + */ + protected function getNormalizedPostEntity() { + return [ + 'name' => [ + [ + 'value' => 'Dramallama', + ], + ], + ]; + } + + /** + * Tests PATCHing security-sensitive base fields of the logged in account. + */ + public function testPatchDxForSecuritySensitiveBaseFields() { + // The anonymous user is never allowed to modify itself. + if (!static::$auth) { + $this->markTestSkipped(); + } + + $this->initAuthentication(); + $this->provisionEntityResource(); + + /** @var \Drupal\user\UserInterface $user */ + $user = static::$auth ? $this->account : User::load(0); + // @todo Remove the array_diff_key() call in https://www.drupal.org/node/2821077. + $original_normalization = array_diff_key($this->serializer->normalize($user, static::$format), ['created' => TRUE, 'changed' => TRUE, 'name' => TRUE]); + + // Since this test must be performed by the user that is being modified, + // we cannot use $this->getUrl(). + $url = $user->toUrl()->setOption('query', ['_format' => static::$format]); + $request_options = [ + RequestOptions::HEADERS => ['Content-Type' => static::$mimeType], + ]; + $request_options = array_merge_recursive($request_options, $this->getAuthenticationRequestOptions('PATCH')); + + // Test case 1: changing email. + $normalization = $original_normalization; + $normalization['mail'] = [['value' => 'new-email@example.com']]; + $request_options[RequestOptions::BODY] = $this->serializer->encode($normalization, static::$format); + + // DX: 422 when changing email without providing the password. + $response = $this->request('PATCH', $url, $request_options); + $this->assertResourceErrorResponse(422, "Unprocessable Entity: validation failed.\nmail: Your current password is missing or incorrect; it's required to change the Email.\n", $response, FALSE, FALSE, FALSE, FALSE); + + $normalization['pass'] = [['existing' => 'wrong']]; + $request_options[RequestOptions::BODY] = $this->serializer->encode($normalization, static::$format); + + // DX: 422 when changing email while providing a wrong password. + $response = $this->request('PATCH', $url, $request_options); + $this->assertResourceErrorResponse(422, "Unprocessable Entity: validation failed.\nmail: Your current password is missing or incorrect; it's required to change the Email.\n", $response, FALSE, FALSE, FALSE, FALSE); + + $normalization['pass'] = [['existing' => $this->account->passRaw]]; + $request_options[RequestOptions::BODY] = $this->serializer->encode($normalization, static::$format); + + // 200 for well-formed request. + $response = $this->request('PATCH', $url, $request_options); + $this->assertResourceResponse(200, FALSE, $response); + + // Test case 2: changing password. + $normalization = $original_normalization; + $new_password = $this->randomString(); + $normalization['pass'] = [['value' => $new_password]]; + $request_options[RequestOptions::BODY] = $this->serializer->encode($normalization, static::$format); + + // DX: 422 when changing password without providing the current password. + $response = $this->request('PATCH', $url, $request_options); + $this->assertResourceErrorResponse(422, "Unprocessable Entity: validation failed.\npass: Your current password is missing or incorrect; it's required to change the Password.\n", $response, FALSE, FALSE, FALSE, FALSE); + + $normalization['pass'][0]['existing'] = $this->account->pass_raw; + $request_options[RequestOptions::BODY] = $this->serializer->encode($normalization, static::$format); + + // 200 for well-formed request. + $response = $this->request('PATCH', $url, $request_options); + $this->assertResourceResponse(200, FALSE, $response); + + // Verify that we can log in with the new password. + $this->assertRpcLogin($user->getAccountName(), $new_password); + + // Update password in $this->account, prepare for future requests. + $this->account->passRaw = $new_password; + $this->initAuthentication(); + $request_options = [ + RequestOptions::HEADERS => ['Content-Type' => static::$mimeType], + ]; + $request_options = array_merge_recursive($request_options, $this->getAuthenticationRequestOptions('PATCH')); + + // Test case 3: changing name. + $normalization = $original_normalization; + $normalization['name'] = [['value' => 'Cooler Llama']]; + $request_options[RequestOptions::BODY] = $this->serializer->encode($normalization, static::$format); + + // DX: 403 when modifying username without required permission. + $response = $this->request('PATCH', $url, $request_options); + $this->assertResourceErrorResponse(403, "Access denied on updating field 'name'.", $response); + + $this->grantPermissionsToTestedRole(['change own username']); + + // 200 for well-formed request. + $response = $this->request('PATCH', $url, $request_options); + $this->assertResourceResponse(200, FALSE, $response); + + // Verify that we can log in with the new username. + $this->assertRpcLogin('Cooler Llama', $new_password); + } + + /** + * Verifies that logging in with the given username and password works. + * + * @param string $username + * The username to log in with. + * @param string $password + * The password to log in with. + */ + protected function assertRpcLogin($username, $password) { + $request_body = [ + 'name' => $username, + 'pass' => $password, + ]; + $request_options = [ + RequestOptions::HEADERS => [], + RequestOptions::BODY => $this->serializer->encode($request_body, 'json'), + ]; + $response = $this->request('POST', Url::fromRoute('user.login.http')->setRouteParameter('_format', 'json'), $request_options); + $this->assertSame(200, $response->getStatusCode()); + } + + /** + * Tests PATCHing security-sensitive base fields to change other users. + */ + public function testPatchSecurityOtherUser() { + // The anonymous user is never allowed to modify other users. + if (!static::$auth) { + $this->markTestSkipped(); + } + + $this->initAuthentication(); + $this->provisionEntityResource(); + + /** @var \Drupal\user\UserInterface $user */ + $user = $this->account; + $original_normalization = array_diff_key($this->serializer->normalize($user, static::$format), ['changed' => TRUE]); + + // Since this test must be performed by the user that is being modified, + // we cannot use $this->getUrl(). + $url = $user->toUrl()->setOption('query', ['_format' => static::$format]); + $request_options = [ + RequestOptions::HEADERS => ['Content-Type' => static::$mimeType], + ]; + $request_options = array_merge_recursive($request_options, $this->getAuthenticationRequestOptions('PATCH')); + + $normalization = $original_normalization; + $normalization['mail'] = [['value' => 'new-email@example.com']]; + $request_options[RequestOptions::BODY] = $this->serializer->encode($normalization, static::$format); + + // Try changing user 1's email. + $user1 = [ + 'mail' => [['value' => 'another_email_address@example.com']], + 'uid' => [['value' => 1]], + 'name' => [['value' => 'another_user_name']], + 'pass' => [['existing' => $this->account->passRaw]], + 'uuid' => [['value' => '2e9403a4-d8af-4096-a116-624710140be0']], + ] + $original_normalization; + $request_options[RequestOptions::BODY] = $this->serializer->encode($user1, static::$format); + $response = $this->request('PATCH', $url, $request_options); + // Ensure the email address has not changed. + $this->assertEquals('admin@example.com', $this->entityStorage->loadUnchanged(1)->getEmail()); + $this->assertResourceErrorResponse(403, "Access denied on updating field 'uid'.", $response); + } + + /** + * {@inheritdoc} + */ + protected function getExpectedUnauthorizedAccessMessage($method) { + if ($this->config('rest.settings')->get('bc_entity_resource_permissions')) { + return parent::getExpectedUnauthorizedAccessMessage($method); + } + + switch ($method) { + case 'GET': + return "The 'access user profiles' permission is required and the user must be active."; + case 'PATCH': + return "You are not authorized to update this user entity."; + case 'DELETE': + return 'You are not authorized to delete this user entity.'; + default: + return parent::getExpectedUnauthorizedAccessMessage($method); + } + } + + /** + * {@inheritdoc} + */ + protected function getExpectedUnauthorizedAccessCacheability() { + // @see \Drupal\user\UserAccessControlHandler::checkAccess() + return parent::getExpectedUnauthorizedAccessCacheability() + ->addCacheTags(['user:3']); + } + +} diff -r e200cb7efeb3 -r c2387f117808 core/modules/user/tests/src/Functional/Rest/UserXmlAnonTest.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/core/modules/user/tests/src/Functional/Rest/UserXmlAnonTest.php Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,34 @@ +markTestSkipped(); + } + +} diff -r e200cb7efeb3 -r c2387f117808 core/modules/user/tests/src/Functional/Rest/UserXmlBasicAuthTest.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/core/modules/user/tests/src/Functional/Rest/UserXmlBasicAuthTest.php Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,52 @@ +markTestSkipped(); + } + + /** + * {@inheritdoc} + */ + public function testPatchSecurityOtherUser() { + // Deserialization of the XML format is not supported. + $this->markTestSkipped(); + } + +} diff -r e200cb7efeb3 -r c2387f117808 core/modules/user/tests/src/Functional/Rest/UserXmlCookieTest.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/core/modules/user/tests/src/Functional/Rest/UserXmlCookieTest.php Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,47 @@ +markTestSkipped(); + } + + /** + * {@inheritdoc} + */ + public function testPatchSecurityOtherUser() { + // Deserialization of the XML format is not supported. + $this->markTestSkipped(); + } + +} diff -r e200cb7efeb3 -r c2387f117808 core/modules/user/tests/src/Functional/UserCancelTest.php --- a/core/modules/user/tests/src/Functional/UserCancelTest.php Thu Apr 26 11:26:54 2018 +0100 +++ b/core/modules/user/tests/src/Functional/UserCancelTest.php Tue Jul 10 15:07:59 2018 +0100 @@ -99,23 +99,6 @@ \Drupal::service('module_installer')->install(['views']); \Drupal::service('router.builder')->rebuild(); - // Update uid 1's name and password to we know it. - $password = user_password(); - $account = [ - 'name' => 'user1', - 'pass' => $this->container->get('password')->hash(trim($password)), - ]; - // We cannot use $account->save() here, because this would result in the - // password being hashed again. - db_update('users_field_data') - ->fields($account) - ->condition('uid', 1) - ->execute(); - - // Reload and log in uid 1. - $user_storage->resetCache([1]); - $user1 = $user_storage->load(1); - $user1->pass_raw = $password; // Try to cancel uid 1's account with a different user. $admin_user = $this->drupalCreateUser(['administer users']); @@ -268,6 +251,12 @@ // Confirm account cancellation request. $this->drupalGet("user/" . $account->id() . "/cancel/confirm/$timestamp/" . user_pass_rehash($account, $timestamp)); + // Confirm that the user was redirected to the front page. + $this->assertSession()->addressEquals(''); + $this->assertSession()->statusCodeEquals(200); + // Confirm that the confirmation message made it through to the end user. + $this->assertRaw(t('%name has been disabled.', ['%name' => $account->getUsername()]), "Confirmation message displayed to user."); + $user_storage->resetCache([$account->id()]); $account = $user_storage->load($account->id()); $this->assertTrue($account->isBlocked(), 'User has been blocked.'); @@ -283,9 +272,6 @@ $storage->resetCache([$comment->id()]); $comment = $storage->load($comment->id()); $this->assertFalse($comment->isPublished(), 'Comment of the user has been unpublished.'); - - // Confirm that the confirmation message made it through to the end user. - $this->assertRaw(t('%name has been disabled.', ['%name' => $account->getUsername()]), "Confirmation message displayed to user."); } /** diff -r e200cb7efeb3 -r c2387f117808 core/modules/user/tests/src/Functional/UserTranslationUITest.php --- a/core/modules/user/tests/src/Functional/UserTranslationUITest.php Thu Apr 26 11:26:54 2018 +0100 +++ b/core/modules/user/tests/src/Functional/UserTranslationUITest.php Tue Jul 10 15:07:59 2018 +0100 @@ -75,4 +75,25 @@ } } + /** + * Test translated user deletion. + */ + public function testTranslatedUserDeletion() { + $this->drupalLogin($this->administrator); + $entity_id = $this->createEntity($this->getNewEntityValues('en'), 'en'); + + $entity = $this->container->get('entity_type.manager') + ->getStorage($this->entityTypeId) + ->load($entity_id); + $translated_entity = $entity->addTranslation('fr'); + $translated_entity->save(); + + $url = $entity->toUrl( + 'edit-form', + ['language' => $this->container->get('language_manager')->getLanguage('en')] + ); + $this->drupalPostForm($url, [], t('Cancel account')); + $this->assertSession()->statusCodeEquals(200); + } + } diff -r e200cb7efeb3 -r c2387f117808 core/modules/user/tests/src/Kernel/Migrate/MigrateUserProfileEntityDisplayTest.php --- a/core/modules/user/tests/src/Kernel/Migrate/MigrateUserProfileEntityDisplayTest.php Thu Apr 26 11:26:54 2018 +0100 +++ b/core/modules/user/tests/src/Kernel/Migrate/MigrateUserProfileEntityDisplayTest.php Tue Jul 10 15:07:59 2018 +0100 @@ -47,6 +47,10 @@ // Test PROFILE_HIDDEN field is hidden. $this->assertNull($display->getComponent('profile_sold_to')); + + // Test a checkbox field. + $component = $display->getComponent('profile_really_really_love_mig'); + $this->assertIdentical('list_default', $component['type']); } } diff -r e200cb7efeb3 -r c2387f117808 core/modules/user/tests/src/Kernel/Migrate/MigrateUserProfileEntityFormDisplayTest.php --- a/core/modules/user/tests/src/Kernel/Migrate/MigrateUserProfileEntityFormDisplayTest.php Thu Apr 26 11:26:54 2018 +0100 +++ b/core/modules/user/tests/src/Kernel/Migrate/MigrateUserProfileEntityFormDisplayTest.php Tue Jul 10 15:07:59 2018 +0100 @@ -49,7 +49,7 @@ $this->assertNull($display->getComponent('profile_sold_to')); // Test that a checkbox field has the proper display label setting. - $component = $display->getComponent('profile_love_migrations'); + $component = $display->getComponent('profile_really_really_love_mig'); $this->assertIdentical('boolean_checkbox', $component['type']); $this->assertIdentical(TRUE, $component['settings']['display_label']); } diff -r e200cb7efeb3 -r c2387f117808 core/modules/user/tests/src/Kernel/Migrate/MigrateUserProfileFieldInstanceTest.php --- a/core/modules/user/tests/src/Kernel/Migrate/MigrateUserProfileFieldInstanceTest.php Thu Apr 26 11:26:54 2018 +0100 +++ b/core/modules/user/tests/src/Kernel/Migrate/MigrateUserProfileFieldInstanceTest.php Tue Jul 10 15:07:59 2018 +0100 @@ -68,8 +68,8 @@ $this->assertIdentical("Enter your birth date and we'll send you a coupon.", $field->getDescription()); // Another migrated checkbox field, with a different source visibility setting. - $field = FieldConfig::load('user.user.profile_love_migrations'); - $this->assertIdentical('I love migrations', $field->label()); + $field = FieldConfig::load('user.user.profile_really_really_love_mig'); + $this->assertIdentical('I really, really, really love migrations', $field->label()); $this->assertIdentical("If you check this box, you love migrations.", $field->getDescription()); } diff -r e200cb7efeb3 -r c2387f117808 core/modules/user/tests/src/Kernel/Migrate/d6/MigrateUserProfileValuesTest.php --- a/core/modules/user/tests/src/Kernel/Migrate/d6/MigrateUserProfileValuesTest.php Thu Apr 26 11:26:54 2018 +0100 +++ b/core/modules/user/tests/src/Kernel/Migrate/d6/MigrateUserProfileValuesTest.php Tue Jul 10 15:07:59 2018 +0100 @@ -59,7 +59,13 @@ $this->assertNull($user->profile_blog->title); $this->assertIdentical([], $user->profile_blog->options); $this->assertIdentical('http://example.com/blog', $user->profile_blog->uri); - $this->assertNull($user->profile_love_migrations->value); + + // Check that the source profile field names that are longer than 32 + // characters have been migrated. + $this->assertNotNull($user->getFieldDefinition('profile_really_really_love_mig')); + $this->assertNotNull($user->getFieldDefinition('profile_really_really_love_mig1')); + $this->assertSame('1', $user->profile_really_really_love_mig->value); + $this->assertNull($user->profile_really_really_love_mig1->value); $user = User::load(8); $this->assertIdentical('Forward/slash', $user->profile_sold_to->value); diff -r e200cb7efeb3 -r c2387f117808 core/modules/user/user.module --- a/core/modules/user/user.module Thu Apr 26 11:26:54 2018 +0100 +++ b/core/modules/user/user.module Tue Jul 10 15:07:59 2018 +0100 @@ -900,7 +900,7 @@ * content language of the current request. * * @return array - * An array as expected by drupal_render(). + * An array as expected by \Drupal\Core\Render\RendererInterface::render(). */ function user_view($account, $view_mode = 'full', $langcode = NULL) { return entity_view($account, $view_mode, $langcode); @@ -918,7 +918,8 @@ * content language of the current request. * * @return array - * An array in the format expected by drupal_render(). + * An array in the format expected by + * \Drupal\Core\Render\RendererInterface::render(). */ function user_view_multiple($accounts, $view_mode = 'full', $langcode = NULL) { return entity_view_multiple($accounts, $view_mode, $langcode); diff -r e200cb7efeb3 -r c2387f117808 core/modules/views/src/Controller/ViewAjaxController.php --- a/core/modules/views/src/Controller/ViewAjaxController.php Thu Apr 26 11:26:54 2018 +0100 +++ b/core/modules/views/src/Controller/ViewAjaxController.php Tue Jul 10 15:07:59 2018 +0100 @@ -132,7 +132,20 @@ // Remove all of this stuff from the query of the request so it doesn't // end up in pagers and tablesort URLs. - foreach (['view_name', 'view_display_id', 'view_args', 'view_path', 'view_dom_id', 'pager_element', 'view_base_path', AjaxResponseSubscriber::AJAX_REQUEST_PARAMETER] as $key) { + // @todo Remove this parsing once these are removed from the request in + // https://www.drupal.org/node/2504709. + foreach ([ + 'view_name', + 'view_display_id', + 'view_args', + 'view_path', + 'view_dom_id', + 'pager_element', + 'view_base_path', + AjaxResponseSubscriber::AJAX_REQUEST_PARAMETER, + FormBuilderInterface::AJAX_FORM_REQUEST, + MainContentViewSubscriber::WRAPPER_FORMAT, + ] as $key) { $request->query->remove($key); $request->request->remove($key); } @@ -152,6 +165,7 @@ // Add all POST data, because AJAX is always a post and many things, // such as tablesorts, exposed filters and paging assume GET. $request_all = $request->request->all(); + unset($request_all['ajax_page_state']); $query_all = $request->query->all(); $request->query->replace($request_all + $query_all); @@ -159,13 +173,7 @@ // @see the redirect.destination service. $origin_destination = $path; - // Remove some special parameters you never want to have part of the - // destination query. $used_query_parameters = $request->query->all(); - // @todo Remove this parsing once these are removed from the request in - // https://www.drupal.org/node/2504709. - unset($used_query_parameters[FormBuilderInterface::AJAX_FORM_REQUEST], $used_query_parameters[MainContentViewSubscriber::WRAPPER_FORMAT], $used_query_parameters['ajax_page_state']); - $query = UrlHelper::buildQuery($used_query_parameters); if ($query != '') { $origin_destination .= '?' . $query; diff -r e200cb7efeb3 -r c2387f117808 core/modules/views/src/Entity/View.php --- a/core/modules/views/src/Entity/View.php Thu Apr 26 11:26:54 2018 +0100 +++ b/core/modules/views/src/Entity/View.php Tue Jul 10 15:07:59 2018 +0100 @@ -317,6 +317,8 @@ * An array containing display handlers of a view. * * @deprecated in Drupal 8.3.0, will be removed in Drupal 9.0.0. + * + * @see https://www.drupal.org/node/2831499 */ private function fixTableNames(array &$displays) { // Fix wrong table names for entity revision metadata fields. diff -r e200cb7efeb3 -r c2387f117808 core/modules/views/src/EntityViewsData.php --- a/core/modules/views/src/EntityViewsData.php Thu Apr 26 11:26:54 2018 +0100 +++ b/core/modules/views/src/EntityViewsData.php Tue Jul 10 15:07:59 2018 +0100 @@ -253,6 +253,9 @@ } $this->addEntityLinks($data[$base_table]); + if ($views_revision_base_table) { + $this->addEntityLinks($data[$views_revision_base_table]); + } // Load all typed data definitions of all fields. This should cover each of // the entity base, revision, data tables. diff -r e200cb7efeb3 -r c2387f117808 core/modules/views/src/Form/ViewsExposedForm.php --- a/core/modules/views/src/Form/ViewsExposedForm.php Thu Apr 26 11:26:54 2018 +0100 +++ b/core/modules/views/src/Form/ViewsExposedForm.php Tue Jul 10 15:07:59 2018 +0100 @@ -183,7 +183,7 @@ // https://www.drupal.org/node/342316 is resolved. $checked = Checkboxes::getCheckedCheckboxes($value); foreach ($checked as $option_id) { - $view->exposed_raw_input[$option_id] = $value[$option_id]; + $view->exposed_raw_input[$key][] = $value[$option_id]; } } else { diff -r e200cb7efeb3 -r c2387f117808 core/modules/views/src/Plugin/views/area/Result.php --- a/core/modules/views/src/Plugin/views/area/Result.php Thu Apr 26 11:26:54 2018 +0100 +++ b/core/modules/views/src/Plugin/views/area/Result.php Tue Jul 10 15:07:59 2018 +0100 @@ -115,11 +115,13 @@ // Send the output. if (!empty($total) || !empty($this->options['empty'])) { $output .= Xss::filterAdmin(str_replace(array_keys($replacements), array_values($replacements), $format)); + // Return as render array. + return [ + '#markup' => $output, + ]; } - // Return as render array. - return [ - '#markup' => $output, - ]; + + return []; } } diff -r e200cb7efeb3 -r c2387f117808 core/modules/views/src/Plugin/views/cache/CachePluginBase.php --- a/core/modules/views/src/Plugin/views/cache/CachePluginBase.php Thu Apr 26 11:26:54 2018 +0100 +++ b/core/modules/views/src/Plugin/views/cache/CachePluginBase.php Tue Jul 10 15:07:59 2018 +0100 @@ -97,6 +97,9 @@ * Save data to the cache. * * A plugin should override this to provide specialized caching behavior. + * + * @param $type + * The cache type, either 'query', 'result'. */ public function cacheSet($type) { switch ($type) { @@ -119,6 +122,12 @@ * Retrieve data from the cache. * * A plugin should override this to provide specialized caching behavior. + * + * @param $type + * The cache type, either 'query', 'result'. + * + * @return bool + * TRUE if data has been taken from the cache, otherwise FALSE. */ public function cacheGet($type) { $cutoff = $this->cacheExpire($type); diff -r e200cb7efeb3 -r c2387f117808 core/modules/views/src/Plugin/views/display/EntityReference.php --- a/core/modules/views/src/Plugin/views/display/EntityReference.php Thu Apr 26 11:26:54 2018 +0100 +++ b/core/modules/views/src/Plugin/views/display/EntityReference.php Tue Jul 10 15:07:59 2018 +0100 @@ -54,9 +54,6 @@ $options['row']['contains']['type'] = ['default' => 'entity_reference']; $options['defaults']['default']['row'] = FALSE; - // Make sure the query is not cached. - $options['defaults']['default']['cache'] = FALSE; - // Set the display title to an empty string (not used in this display type). $options['title']['default'] = ''; $options['defaults']['default']['title'] = FALSE; @@ -65,13 +62,12 @@ } /** - * Overrides \Drupal\views\Plugin\views\display\DisplayPluginBase::optionsSummary(). - * - * Disable 'cache' and 'title' so it won't be changed. + * {@inheritdoc} */ public function optionsSummary(&$categories, &$options) { parent::optionsSummary($categories, $options); - unset($options['query']); + // Disable 'title' so it won't be changed from the default set in + // \Drupal\views\Plugin\views\display\EntityReference::defineOptions. unset($options['title']); } diff -r e200cb7efeb3 -r c2387f117808 core/modules/views/src/ViewExecutable.php --- a/core/modules/views/src/ViewExecutable.php Thu Apr 26 11:26:54 2018 +0100 +++ b/core/modules/views/src/ViewExecutable.php Tue Jul 10 15:07:59 2018 +0100 @@ -1096,7 +1096,8 @@ $argument->is_default = TRUE; } - // Set the argument, which will also validate that the argument can be set. + // Set the argument, which ensures that the argument is valid and + // possibly transforms the value. if (!$argument->setArgument($arg)) { $status = $argument->validateFail($arg); break; @@ -1110,9 +1111,11 @@ $argument->query($this->display_handler->useGroupBy()); } - // Add this argument's substitution + // Add this argument's substitution. $substitutions["{{ arguments.$id }}"] = $arg_title; - $substitutions["{{ raw_arguments.$id }}"] = strip_tags(Html::decodeEntities($arg)); + // Since argument validator plugins can potentially transform the value, + // use whatever value the argument handler now has, not the raw value. + $substitutions["{{ raw_arguments.$id }}"] = strip_tags(Html::decodeEntities($argument->getValue())); // Test to see if we should use this argument's title if (!empty($argument->options['title_enable']) && !empty($argument->options['title'])) { diff -r e200cb7efeb3 -r c2387f117808 core/modules/views/templates/views-view-grid.html.twig --- a/core/modules/views/templates/views-view-grid.html.twig Thu Apr 26 11:26:54 2018 +0100 +++ b/core/modules/views/templates/views-view-grid.html.twig Tue Jul 10 15:07:59 2018 +0100 @@ -59,7 +59,7 @@ {% for column in row.content %} - {{ column.content }} + {{- column.content -}}
    {% endfor %}
    @@ -69,7 +69,7 @@ {% for row in column.content %} - {{ row.content }} + {{- row.content -}} {% endfor %} diff -r e200cb7efeb3 -r c2387f117808 core/modules/views/templates/views-view-list.html.twig --- a/core/modules/views/templates/views-view-list.html.twig Thu Apr 26 11:26:54 2018 +0100 +++ b/core/modules/views/templates/views-view-list.html.twig Tue Jul 10 15:07:59 2018 +0100 @@ -28,7 +28,9 @@ <{{ list.type }}{{ list.attributes }}> {% for row in rows %} - {{ row.content }} + + {{- row.content -}} + {% endfor %} diff -r e200cb7efeb3 -r c2387f117808 core/modules/views/templates/views-view-unformatted.html.twig --- a/core/modules/views/templates/views-view-unformatted.html.twig Thu Apr 26 11:26:54 2018 +0100 +++ b/core/modules/views/templates/views-view-unformatted.html.twig Tue Jul 10 15:07:59 2018 +0100 @@ -27,6 +27,6 @@ ] %} - {{ row.content }} + {{- row.content -}} {% endfor %} diff -r e200cb7efeb3 -r c2387f117808 core/modules/views/tests/modules/views_test_data/src/Plugin/views/argument_validator/ArgumentValidatorTest.php --- a/core/modules/views/tests/modules/views_test_data/src/Plugin/views/argument_validator/ArgumentValidatorTest.php Thu Apr 26 11:26:54 2018 +0100 +++ b/core/modules/views/tests/modules/views_test_data/src/Plugin/views/argument_validator/ArgumentValidatorTest.php Tue Jul 10 15:07:59 2018 +0100 @@ -37,6 +37,12 @@ * {@inheritdoc} */ public function validateArgument($arg) { + if ($arg === 'this value should be replaced') { + // Set the argument to a numeric value so this is valid on PostgeSQL for + // numeric fields. + $this->argument->argument = '1'; + return TRUE; + } return $arg == $this->options['test_value']; } diff -r e200cb7efeb3 -r c2387f117808 core/modules/views/tests/modules/views_test_data/views_test_data.views_execution.inc --- a/core/modules/views/tests/modules/views_test_data/views_test_data.views_execution.inc Thu Apr 26 11:26:54 2018 +0100 +++ b/core/modules/views/tests/modules/views_test_data/views_test_data.views_execution.inc Tue Jul 10 15:07:59 2018 +0100 @@ -74,6 +74,11 @@ */ function views_test_data_views_post_render(ViewExecutable $view, &$output, CachePluginBase $cache) { \Drupal::state()->set('views_hook_test_views_post_render', TRUE); + if ($view->storage->id() === 'test_page_display' && $view->current_display === 'empty_row') { + for ($i = 0; $i < 5; $i++) { + $output['#rows'][0]['#rows'][] = []; + } + } } /** diff -r e200cb7efeb3 -r c2387f117808 core/modules/views/tests/src/Functional/Hal/ViewHalJsonAnonTest.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/core/modules/views/tests/src/Functional/Hal/ViewHalJsonAnonTest.php Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,30 @@ +drupalGet('admin/structure/views/view/test_display_entity_reference/edit/entity_reference_1'); + $this->assertSession()->linkByHrefNotExists('admin/structure/views/nojs/display/test_display_entity_reference/entity_reference_1/title'); + // Add the new field to the fields. $this->drupalPostForm('admin/structure/views/nojs/add-handler/test_display_entity_reference/default/field', ['name[entity_test__' . $this->fieldName . '.' . $this->fieldName . ']' => TRUE], t('Add and configure fields')); $this->drupalPostForm(NULL, [], t('Apply')); diff -r e200cb7efeb3 -r c2387f117808 core/modules/views/tests/src/Functional/Rest/ViewJsonAnonTest.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/core/modules/views/tests/src/Functional/Rest/ViewJsonAnonTest.php Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,24 @@ +grantPermissionsToTestedRole(['administer views']); + } + + /** + * {@inheritdoc} + */ + protected function createEntity() { + $view = View::create([ + 'id' => 'test_rest', + 'label' => 'Test REST', + ]); + $view->save(); + return $view; + } + + /** + * {@inheritdoc} + */ + protected function getExpectedNormalizedEntity() { + return [ + 'base_field' => 'nid', + 'base_table' => 'node', + 'core' => '8.x', + 'dependencies' => [], + 'description' => '', + 'display' => [ + 'default' => [ + 'display_plugin' => 'default', + 'id' => 'default', + 'display_title' => 'Master', + 'position' => 0, + 'display_options' => [ + 'display_extenders' => [], + ], + 'cache_metadata' => [ + 'max-age' => -1, + 'contexts' => [ + 'languages:language_interface', + 'url.query_args', + ], + 'tags' => [], + ], + ], + ], + 'id' => 'test_rest', + 'label' => 'Test REST', + 'langcode' => 'en', + 'module' => 'views', + 'status' => TRUE, + 'tag' => '', + 'uuid' => $this->entity->uuid(), + ]; + } + + /** + * {@inheritdoc} + */ + protected function getNormalizedPostEntity() { + // @todo Update in https://www.drupal.org/node/2300677. + } + + /** + * {@inheritdoc} + */ + protected function getExpectedCacheContexts() { + return [ + 'user.permissions', + ]; + } + +} diff -r e200cb7efeb3 -r c2387f117808 core/modules/views/tests/src/Functional/Rest/ViewXmlAnonTest.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/core/modules/views/tests/src/Functional/Rest/ViewXmlAnonTest.php Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,26 @@ +drupalLogin($user); @@ -71,6 +72,16 @@ $this->assertContains('Page Two', $html); $this->assertNotContains('Page One', $html); + // Submit bulk actions form to ensure that the previous AJAX submit does not + // break it. + $this->submitForm([ + 'action' => 'node_make_sticky_action', + 'node_bulk_form[0]' => TRUE, + ], t('Apply to selected items')); + + // Verify that the action was performed. + $this->assertSession()->pageTextContains('Make content sticky was applied to 1 item.'); + // Reset the form. $this->submitForm([], t('Reset')); $this->assertSession()->assertWaitOnAjaxRequest(); diff -r e200cb7efeb3 -r c2387f117808 core/modules/views/tests/src/FunctionalJavascript/PaginationAJAXTest.php --- a/core/modules/views/tests/src/FunctionalJavascript/PaginationAJAXTest.php Thu Apr 26 11:26:54 2018 +0100 +++ b/core/modules/views/tests/src/FunctionalJavascript/PaginationAJAXTest.php Tue Jul 10 15:07:59 2018 +0100 @@ -86,6 +86,10 @@ $rows = $page->findAll('css', 'tbody tr'); $this->assertCount(5, $rows); $this->assertContains('Node 6 content', $rows[0]->getHtml()); + $link = $page->findLink('Go to page 3'); + // Test that no unwanted parameters are added to the URL. + $this->assertEquals('?status=All&type=All&langcode=All&items_per_page=5&order=changed&sort=asc&title=&page=2', $link->getAttribute('href')); + $this->assertNoDuplicateAssetsOnPage(); $this->clickLink('Go to page 3'); $session_assert->assertWaitOnAjaxRequest(); @@ -115,4 +119,17 @@ $this->assertContains('Node 11 content', $rows[0]->getHtml()); } + /** + * Assert that assets are not loaded twice on a page. + */ + protected function assertNoDuplicateAssetsOnPage() { + /** @var \Behat\Mink\Element\NodeElement[] $scripts */ + $scripts = $this->getSession()->getPage()->findAll('xpath', '//script'); + $script_src = []; + foreach ($scripts as $script) { + $this->assertFalse(in_array($script->getAttribute('src'), $script_src)); + $script_src[] = $script->getAttribute('src'); + } + } + } diff -r e200cb7efeb3 -r c2387f117808 core/modules/views/tests/src/Kernel/Handler/AreaResultTest.php --- a/core/modules/views/tests/src/Kernel/Handler/AreaResultTest.php Thu Apr 26 11:26:54 2018 +0100 +++ b/core/modules/views/tests/src/Kernel/Handler/AreaResultTest.php Tue Jul 10 15:07:59 2018 +0100 @@ -57,6 +57,7 @@ $output = \Drupal::service('renderer')->renderRoot($output); $this->setRawContent($output); $this->assertText('start: 0 | end: 0 | total: 0 | label: test_area_result | per page: 0 | current page: 1 | current record count: 0 | page count: 1'); + $this->assertRaw('
    '); // Test that the area is not displayed if we have not checked the empty // checkbox. @@ -67,6 +68,8 @@ $output = \Drupal::service('renderer')->renderRoot($output); $this->setRawContent($output); $this->assertNoText('start: 0 | end: 0 | total: 0 | label: test_area_result | per page: 0 | current page: 1 | current record count: 0 | page count: 1'); + // Make sure the empty header region isn't rendered. + $this->assertNoRaw('
    '); } } diff -r e200cb7efeb3 -r c2387f117808 core/modules/views/tests/src/Kernel/Plugin/DisplayPageTest.php --- a/core/modules/views/tests/src/Kernel/Plugin/DisplayPageTest.php Thu Apr 26 11:26:54 2018 +0100 +++ b/core/modules/views/tests/src/Kernel/Plugin/DisplayPageTest.php Tue Jul 10 15:07:59 2018 +0100 @@ -30,7 +30,7 @@ * * @var array */ - public static $modules = ['system', 'user', 'field']; + public static $modules = ['system', 'user', 'field', 'views_test_data']; /** * The router dumper to get all routes. @@ -220,4 +220,40 @@ $this->assertTrue($view->getDisplay()->getOption('use_more_always'), 'Always display the more link by default.'); } + /** + * Tests the templates with empty rows. + */ + public function testEmptyRow() { + $view = Views::getView('test_page_display'); + $view->initDisplay(); + $view->newDisplay('page', 'Page', 'empty_row'); + $view->save(); + + $styles = [ + 'default' => '//div[@class="views-row"]', + 'grid' => '//div[contains(@class, "views-col")]', + 'html_list' => '//div[@class="item-list"]//li', + ]; + + $themes = ['bartik', 'classy', 'seven', 'stable', 'stark']; + + foreach ($themes as $theme) { + \Drupal::service('theme_handler')->install([$theme]); + \Drupal::theme()->setActiveTheme(\Drupal::service('theme.initialization')->initTheme($theme)); + foreach ($styles as $type => $xpath) { + $view = Views::getView('test_page_display'); + $view->storage->invalidateCaches(); + $view->initDisplay(); + $view->setDisplay('empty_row'); + $view->displayHandlers->get('empty_row')->default_display->options['style']['type'] = $type; + $view->initStyle(); + $this->executeView($view); + $output = $view->preview(); + $output = \Drupal::service('renderer')->renderRoot($output); + $this->setRawContent($output); + $this->assertCount(5, $this->xpath("{$xpath}[not(text()) and not(node())]"), "Empty rows in theme '$theme', type '$type'."); + } + } + } + } diff -r e200cb7efeb3 -r c2387f117808 core/modules/views/tests/src/Kernel/Plugin/ExposedFormRenderTest.php --- a/core/modules/views/tests/src/Kernel/Plugin/ExposedFormRenderTest.php Thu Apr 26 11:26:54 2018 +0100 +++ b/core/modules/views/tests/src/Kernel/Plugin/ExposedFormRenderTest.php Tue Jul 10 15:07:59 2018 +0100 @@ -3,11 +3,12 @@ namespace Drupal\Tests\views\Kernel\Plugin; use Drupal\Component\Utility\Html; +use Drupal\node\Entity\NodeType; use Drupal\Tests\views\Kernel\ViewsKernelTestBase; use Drupal\views\Views; /** - * Tests the exposed form markup. + * Tests the exposed form. * * @group views * @see \Drupal\views_test_data\Plugin\views\display_extender\DisplayExtenderTest @@ -52,4 +53,92 @@ $this->assertEqual(count($result), 1, 'Filter description was found.'); } + /** + * Tests the exposed form raw input. + */ + public function testExposedFormRawInput() { + $node_type = NodeType::create(['type' => 'article']); + $node_type->save(); + + $view = Views::getView('test_exposed_form_buttons'); + $view->setDisplay(); + $view->displayHandlers->get('default')->overrideOption('filters', [ + 'type' => [ + 'exposed' => TRUE, + 'field' => 'type', + 'id' => 'type', + 'table' => 'node_field_data', + 'plugin_id' => 'in_operator', + 'entity_type' => 'node', + 'entity_field' => 'type', + 'expose' => [ + 'identifier' => 'type', + 'label' => 'Content: Type', + 'operator_id' => 'type_op', + 'reduce' => FALSE, + 'multiple' => FALSE, + ], + ], + 'type_with_default_value' => [ + 'exposed' => TRUE, + 'field' => 'type', + 'id' => 'type_with_default_value', + 'table' => 'node_field_data', + 'plugin_id' => 'in_operator', + 'entity_type' => 'node', + 'entity_field' => 'type', + 'value' => ['article', 'article'], + 'expose' => [ + 'identifier' => 'type_with_default_value', + 'label' => 'Content: Type with value', + 'operator_id' => 'type_op', + 'reduce' => FALSE, + 'multiple' => FALSE, + ], + ], + 'multiple_types' => [ + 'exposed' => TRUE, + 'field' => 'type', + 'id' => 'multiple_types', + 'table' => 'node_field_data', + 'plugin_id' => 'in_operator', + 'entity_type' => 'node', + 'entity_field' => 'type', + 'expose' => [ + 'identifier' => 'multiple_types', + 'label' => 'Content: Type (multiple)', + 'operator_id' => 'type_op', + 'reduce' => FALSE, + 'multiple' => TRUE, + ], + ], + 'multiple_types_with_default_value' => [ + 'exposed' => TRUE, + 'field' => 'type', + 'id' => 'multiple_types_with_default_value', + 'table' => 'node_field_data', + 'plugin_id' => 'in_operator', + 'entity_type' => 'node', + 'entity_field' => 'type', + 'value' => ['article', 'article'], + 'expose' => [ + 'identifier' => 'multiple_types_with_default_value', + 'label' => 'Content: Type with default value (multiple)', + 'operator_id' => 'type_op', + 'reduce' => FALSE, + 'multiple' => TRUE, + ], + ], + ]); + $view->save(); + $this->executeView($view); + + $expected = [ + 'type' => 'All', + 'type_with_default_value' => 'article', + 'multiple_types_with_default_value' => ['article'], + ]; + $this->assertSame($view->exposed_raw_input, $expected); + } + } diff -r e200cb7efeb3 -r c2387f117808 core/modules/views/tests/src/Kernel/ViewExecutableTest.php --- a/core/modules/views/tests/src/Kernel/ViewExecutableTest.php Thu Apr 26 11:26:54 2018 +0100 +++ b/core/modules/views/tests/src/Kernel/ViewExecutableTest.php Tue Jul 10 15:07:59 2018 +0100 @@ -38,7 +38,7 @@ * * @var array */ - public static $testViews = ['test_destroy', 'test_executable_displays']; + public static $testViews = ['test_destroy', 'test_executable_displays', 'test_argument_dependency']; /** * Properties that should be stored in the configuration. @@ -525,4 +525,19 @@ $this->assertEquals($nid_definition_before->getPropertyDefinitions(), $nid_definition_after->getPropertyDefinitions()); } + /** + * Tests if argument overrides by validators are propagated to tokens. + */ + public function testArgumentValidatorValueOverride() { + $view = Views::getView('test_argument_dependency'); + $view->setDisplay('page_1'); + $view->setArguments(['1', 'this value should be replaced']); + $view->execute(); + $expected = [ + '{{ arguments.uid }}' => '1', + '{{ raw_arguments.uid }}' => '1', + ]; + $this->assertEquals($expected, $view->build_info['substitutions']); + } + } diff -r e200cb7efeb3 -r c2387f117808 core/modules/views/tests/src/Unit/EntityViewsDataTest.php --- a/core/modules/views/tests/src/Unit/EntityViewsDataTest.php Thu Apr 26 11:26:54 2018 +0100 +++ b/core/modules/views/tests/src/Unit/EntityViewsDataTest.php Tue Jul 10 15:07:59 2018 +0100 @@ -933,9 +933,11 @@ $this->baseEntityType->setLinkTemplate('delete-form', '/entity_test/{entity_test}/delete'); $data = $this->viewsData->getViewsData(); - $this->assertEquals('entity_link', $data['entity_test']['view_entity_test']['field']['id']); - $this->assertEquals('entity_link_edit', $data['entity_test']['edit_entity_test']['field']['id']); - $this->assertEquals('entity_link_delete', $data['entity_test']['delete_entity_test']['field']['id']); + foreach (['entity_test', 'entity_test_revision'] as $table_name) { + $this->assertEquals('entity_link', $data[$table_name]['view_entity_test']['field']['id']); + $this->assertEquals('entity_link_edit', $data[$table_name]['edit_entity_test']['field']['id']); + $this->assertEquals('entity_link_delete', $data[$table_name]['delete_entity_test']['field']['id']); + } } /** @@ -945,10 +947,13 @@ $this->baseEntityType->setLinkTemplate('edit-form', '/entity_test/{entity_test}/edit'); $data = $this->viewsData->getViewsData(); - $this->assertFalse(isset($data['entity_test']['view_entity_test'])); - $this->assertFalse(isset($data['entity_test']['delete_entity_test'])); - $this->assertEquals('entity_link_edit', $data['entity_test']['edit_entity_test']['field']['id']); + foreach (['entity_test', 'entity_test_revision'] as $table_name) { + $this->assertFalse(isset($data[$table_name]['view_entity_test'])); + $this->assertFalse(isset($data[$table_name]['delete_entity_test'])); + + $this->assertEquals('entity_link_edit', $data[$table_name]['edit_entity_test']['field']['id']); + } } /** diff -r e200cb7efeb3 -r c2387f117808 core/modules/views/views.module --- a/core/modules/views/views.module Thu Apr 26 11:26:54 2018 +0100 +++ b/core/modules/views/views.module Tue Jul 10 15:07:59 2018 +0100 @@ -326,9 +326,10 @@ * * @param $render_element * The renderable array to which contextual links will be added. This array - * should be suitable for passing in to drupal_render() and will normally - * contain a representation of the view display whose contextual links are - * being requested. + * should be suitable for passing in to + * \Drupal\Core\Render\RendererInterface::render() and will normally contain a + * representation of the view display whose contextual links are being + * requested. * @param $location * The location in which the calling function intends to render the view and * its contextual links. The core system supports three options for this @@ -358,7 +359,6 @@ * - #view_display_plugin_id: The plugin ID of the display. * * @see \Drupal\views\Plugin\Block\ViewsBlock::addContextualLinks() - * @see views_preprocess_page() * @see template_preprocess_views_view() */ function views_add_contextual_links(&$render_element, $location, $display_id, array $view_element = NULL) { diff -r e200cb7efeb3 -r c2387f117808 core/modules/views/views.post_update.php --- a/core/modules/views/views.post_update.php Thu Apr 26 11:26:54 2018 +0100 +++ b/core/modules/views/views.post_update.php Tue Jul 10 15:07:59 2018 +0100 @@ -206,6 +206,8 @@ /** * Fix table names for revision metadata fields. + * + * @see https://www.drupal.org/node/2831499 */ function views_post_update_revision_metadata_fields() { // The table names are fixed automatically in diff -r e200cb7efeb3 -r c2387f117808 core/modules/views_ui/tests/src/Functional/UITestBase.php --- a/core/modules/views_ui/tests/src/Functional/UITestBase.php Thu Apr 26 11:26:54 2018 +0100 +++ b/core/modules/views_ui/tests/src/Functional/UITestBase.php Tue Jul 10 15:07:59 2018 +0100 @@ -76,8 +76,8 @@ $url = $this->buildUrl($path, $options); // Ensure that each nojs page is accessible via ajax as well. - if (strpos($url, 'nojs') !== FALSE) { - $url = str_replace('nojs', 'ajax', $url); + if (strpos($url, '/nojs/') !== FALSE) { + $url = preg_replace('|/nojs/|', '/ajax/', $url, 1); $result = $this->drupalGet($url, $options); $this->assertSession()->statusCodeEquals(200); $this->assertEquals('application/json', $this->getSession()->getResponseHeader('Content-Type')); diff -r e200cb7efeb3 -r c2387f117808 core/modules/workflows/src/Form/WorkflowEditForm.php --- a/core/modules/workflows/src/Form/WorkflowEditForm.php Thu Apr 26 11:26:54 2018 +0100 +++ b/core/modules/workflows/src/Form/WorkflowEditForm.php Tue Jul 10 15:07:59 2018 +0100 @@ -112,6 +112,7 @@ ); } + $state_weight_delta = round(count($states) / 2); foreach ($states as $state) { $links = [ 'edit' => [ @@ -138,6 +139,7 @@ '#title_display' => 'invisible', '#default_value' => $state->weight(), '#attributes' => ['class' => ['state-weight']], + '#delta' => $state_weight_delta, ], 'operations' => [ '#type' => 'operations', @@ -174,7 +176,10 @@ ], ], ]; - foreach ($workflow->getTypePlugin()->getTransitions() as $transition) { + + $transitions = $workflow->getTypePlugin()->getTransitions(); + $transition_weight_delta = round(count($transitions) / 2); + foreach ($transitions as $transition) { $links['edit'] = [ 'title' => $this->t('Edit'), 'url' => Url::fromRoute('entity.workflow.edit_transition_form', ['workflow' => $workflow->id(), 'workflow_transition' => $transition->id()]), @@ -193,6 +198,7 @@ '#title_display' => 'invisible', '#default_value' => $transition->weight(), '#attributes' => ['class' => ['transition-weight']], + '#delta' => $transition_weight_delta, ], 'from' => [ '#theme' => 'item_list', diff -r e200cb7efeb3 -r c2387f117808 core/modules/workflows/tests/src/Functional/WorkflowUiTest.php --- a/core/modules/workflows/tests/src/Functional/WorkflowUiTest.php Thu Apr 26 11:26:54 2018 +0100 +++ b/core/modules/workflows/tests/src/Functional/WorkflowUiTest.php Tue Jul 10 15:07:59 2018 +0100 @@ -389,6 +389,21 @@ foreach ($elements as $key => $element) { $this->assertEquals($expected_transitions[$key], $element->find('xpath', 'td')->getText()); } + + // Ensure that there are enough weights to satisfy the potential number of + // states and transitions. + $this->assertSession() + ->selectExists('states[three][weight]') + ->selectOption('2'); + $this->assertSession() + ->selectExists('states[three][weight]') + ->selectOption('-2'); + $this->assertSession() + ->selectExists('transitions[three][weight]') + ->selectOption('2'); + $this->assertSession() + ->selectExists('transitions[three][weight]') + ->selectOption('-2'); } } diff -r e200cb7efeb3 -r c2387f117808 core/package.json --- a/core/package.json Thu Apr 26 11:26:54 2018 +0100 +++ b/core/package.json Tue Jul 10 15:07:59 2018 +0100 @@ -41,7 +41,7 @@ "modules": false, "targets": { "browsers": [ - "ie >= 9", + "ie >= 11", "edge >= 13", "firefox >= 5", "opera >= 12", diff -r e200cb7efeb3 -r c2387f117808 core/phpunit.xml.dist --- a/core/phpunit.xml.dist Thu Apr 26 11:26:54 2018 +0100 +++ b/core/phpunit.xml.dist Tue Jul 10 15:07:59 2018 +0100 @@ -28,7 +28,7 @@ - + diff -r e200cb7efeb3 -r c2387f117808 core/profiles/demo_umami/config/install/core.entity_form_display.node.recipe.default.yml --- a/core/profiles/demo_umami/config/install/core.entity_form_display.node.recipe.default.yml Thu Apr 26 11:26:54 2018 +0100 +++ b/core/profiles/demo_umami/config/install/core.entity_form_display.node.recipe.default.yml Tue Jul 10 15:07:59 2018 +0100 @@ -89,7 +89,7 @@ size: 60 placeholder: '' third_party_settings: { } - type: entity_reference_autocomplete + type: entity_reference_autocomplete_tags region: content field_recipe_instruction: weight: 11 @@ -114,7 +114,7 @@ size: 60 placeholder: '' third_party_settings: { } - type: entity_reference_autocomplete + type: entity_reference_autocomplete_tags region: content path: type: path diff -r e200cb7efeb3 -r c2387f117808 core/profiles/demo_umami/config/install/image.style.large_3_2_768x512.yml --- a/core/profiles/demo_umami/config/install/image.style.large_3_2_768x512.yml Thu Apr 26 11:26:54 2018 +0100 +++ b/core/profiles/demo_umami/config/install/image.style.large_3_2_768x512.yml Tue Jul 10 15:07:59 2018 +0100 @@ -5,7 +5,7 @@ label: 'Large 3:2 (768x512)' effects: 36c9f14a-8f5e-4794-92ea-bffab074f52e: - uuid: c7627da6-934e-47e2-a795-f10a424bda34 + uuid: 36c9f14a-8f5e-4794-92ea-bffab074f52e id: image_scale_and_crop weight: 1 data: diff -r e200cb7efeb3 -r c2387f117808 core/profiles/demo_umami/modules/demo_umami_content/default_content/LICENCE.txt --- a/core/profiles/demo_umami/modules/demo_umami_content/default_content/LICENCE.txt Thu Apr 26 11:26:54 2018 +0100 +++ b/core/profiles/demo_umami/modules/demo_umami_content/default_content/LICENCE.txt Tue Jul 10 15:07:59 2018 +0100 @@ -3,6 +3,7 @@ The following image files: +chili-sauce-umami.jpg by Elliot Ward chocolate-brownie-umami.jpg by Keith Jay heritage-carrots.jpg by Keith Jay home-grown-herbs.jpg by Keith Jay @@ -16,6 +17,7 @@ veggie-pasta-bake-umami.jpg by Keith Jay victoria-sponge-umami.jpg by Keith Jay watercress-soup-umami.jpg by Keith Jay +crema-catalana-umami.jpg by Cristina Chumillas are all licensed under a http://creativecommons.org/licenses/by-sa/4.0/ Creative Commons Attribution-ShareAlike 4.0 International License. diff -r e200cb7efeb3 -r c2387f117808 core/profiles/demo_umami/modules/demo_umami_content/default_content/article_body/baking-mishaps-our-troubleshooting-tips.html --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/core/profiles/demo_umami/modules/demo_umami_content/default_content/article_body/baking-mishaps-our-troubleshooting-tips.html Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,13 @@ +

    You follow the recipe, you weigh all your ingredients, you use the right oven temperature and you take your time and yet still, your baking comes out with a soggy bottom, fails to rise or just tastes plain horrible. We have come up with a list of the most frustrating baking problems and the techniques you can use to try and avoid them.

    +

    Your cake failed to rise

    +

    Don't under any circumstances open the oven door in the middle of the cooking time. The heat will come whooshing out, destroying the chemical reaction taking place inside your cake. Your raising agent needs the heat to become activated and you might kill it off.

    +

    Your cake is chewy and tough

    +

    If your light sponge is the consistency of a spare tyre, you might have over-mixed your batter. Keep the lightness inside your cake mixture by carefully and gently folding in the ingredients and only to the point they are just mixed. If you over-fold, the gluten in the flour will start to come out and you'll be making bread instead of cake.

    +

    Your cookies burned

    +

    A great trick is to use light colored bakeware, rather than black. It is less likely to absorb the heat and transfer it to the bottom of your biscuits. Using baking paper will also help with this. Also, using too much sugar can result in your cookies browning too much and giving them a caramelized look.

    +

    Split top to your cake or bread

    +

    Your oven is very likely too hot. If you suspect your oven doesn't keep to the right temperature, invest in a thermometer and check it regularly throughout the cooking. With bread, over-mixing the dough can result in a cracked or split top.

    +

    The dreaded soggy bottom

    +

    As mentioned above, the color of your pan is important. In this case, a dark pan will increase the heat at the bottom and give you that crisp underneath that you want. If you are using a flaky pastry, you really need to blind bake it. Putting your pie towards the bottom of the oven will increase the heat reaching that part.

    +

    Your pastry has shrunk

    +

    You simply tried to make it stretch too far. When rolling, don't try to make it too thin or too big and when draping over your pan, allow it to settle on its own without stretching it to fit. Or just add more pastry - everyone loves pastry anyway!

    diff -r e200cb7efeb3 -r c2387f117808 core/profiles/demo_umami/modules/demo_umami_content/default_content/articles.csv --- a/core/profiles/demo_umami/modules/demo_umami_content/default_content/articles.csv Thu Apr 26 11:26:54 2018 +0100 +++ b/core/profiles/demo_umami/modules/demo_umami_content/default_content/articles.csv Tue Jul 10 15:07:59 2018 +0100 @@ -3,3 +3,4 @@ The real deal for supermarket savvy shopping,the-real-deal-for-supermarket-savvy-shopping.html,Megan Collins Quinlan,articles/the-real-deal-for-supermarket-savvy-shopping,supermarket-savvy-umami.jpg,Products presented on supermarket shelving.,"Supermarkets,Shopping" The umami guide to our favorite mushrooms,the-umami-guide-to-our-favourite-mushrooms.html,Umami,articles/the-umami-guide-to-our-favourite-mushrooms,mushrooms-umami.jpg,A delightful selection of mushroom varieties laid out on a simple wooden plate.,"Mushrooms,Vegetarian" Let's hear it for carrots,lets-hear-it-for-carrots.html,Umami,articles/lets-hear-it-for-carrots,heritage-carrots.jpg,"Purple, orange, yellow and white heritage carrots.","Carrots,Vegetarian,Healthy" +Baking mishaps - our troubleshooting tips,baking-mishaps-our-troubleshooting-tips.html,"Umami",articles/baking-mishaps-our-troubleshooting-tips,chocolate-brownie-umami.jpg,"Alt text to be supplied","Baking,Learn to cook" diff -r e200cb7efeb3 -r c2387f117808 core/profiles/demo_umami/modules/demo_umami_content/default_content/images/chili-sauce-umami.jpg Binary file core/profiles/demo_umami/modules/demo_umami_content/default_content/images/chili-sauce-umami.jpg has changed diff -r e200cb7efeb3 -r c2387f117808 core/profiles/demo_umami/modules/demo_umami_content/default_content/images/crema-catalana-umami.jpg Binary file core/profiles/demo_umami/modules/demo_umami_content/default_content/images/crema-catalana-umami.jpg has changed diff -r e200cb7efeb3 -r c2387f117808 core/profiles/demo_umami/modules/demo_umami_content/default_content/recipe_instructions/chili-sauce-umami.html --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/core/profiles/demo_umami/modules/demo_umami_content/default_content/recipe_instructions/chili-sauce-umami.html Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,14 @@ +
      +
    1. Preheat the oven to 400°F/200°C.
    2. +
    3. Finely chop the red onions and sweat gently on a low heat in olive oil for 5 minutes.
    4. +
    5. Peel the garlic and add it to the onions.
    6. +
    7. Meanwhile, chop the bell peppers to 1 inch pieces. Add the bell peppers and tomatoes to a roasting dish, and rub with lemon juice, olive oil and black pepper. Transfer to the oven and roast for 30 minutes.
    8. +
    9. Once the onions and garlic have softened, chop and add the chilies, seeds and all. Mix well and continue to gently fry.
    10. +
    11. Thoroughly wash your hands following handling raw chilies.
    12. +
    13. Once the tomatoes and bell peppers have finished roasting, add them to the pan. Cook for at least 10 minutes, breaking them up with a masher or a hand blender as they simmer. Once broken up, mix in the sugar.
    14. +
    15. Transfer the sauce to a blender and blend until smooth.
    16. +
    17. Return to the pan and add the vinegar and juice of the limes.
    18. +
    19. Cook through for a further 10 minutes, then leave to cool.
    20. +
    21. Transfer to sterilized jars and keep refrigerated.
    22. +
    23. Leave for at least two weeks before tasting.
    24. +
    diff -r e200cb7efeb3 -r c2387f117808 core/profiles/demo_umami/modules/demo_umami_content/default_content/recipe_instructions/crema-catalana-umami.html --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/core/profiles/demo_umami/modules/demo_umami_content/default_content/recipe_instructions/crema-catalana-umami.html Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,9 @@ +
      +
    1. Mix the egg yolks, sugar, and cornstarch with 1/3 of the milk.
    2. +
    3. In a saucepan, boil 2/3 of the milk with the lemon peel and cinnamon.
    4. +
    5. After 3 minutes, remove from the heat and take out the lemon and cinnamon.
    6. +
    7. Slowly add the egg mixture to the hot milk through a strainer to ensure there are no lumps.
    8. +
    9. Return it to the heat until it boils, stirring constantly.
    10. +
    11. Once the mixture has begun to thicken, remove from the heat and put it into individual bowls to cool.
    12. +
    13. For an authentic finish, sprinkle with sugar and brown with a blowtorch or under a preheated broiler to caramelize.
    14. +
    diff -r e200cb7efeb3 -r c2387f117808 core/profiles/demo_umami/modules/demo_umami_content/default_content/recipes.csv --- a/core/profiles/demo_umami/modules/demo_umami_content/default_content/recipes.csv Thu Apr 26 11:26:54 2018 +0100 +++ b/core/profiles/demo_umami/modules/demo_umami_content/default_content/recipes.csv Tue Jul 10 15:07:59 2018 +0100 @@ -6,3 +6,5 @@ Victoria sponge cake,victoria-sponge-umami.jpg,"A classic, uncut Victoria sponge with a deep filling of butter cream and jam","A traditional Victoria sponge cake, perfect for any afternoon with a cup of tea.",Umami,Desert,20,20,40,easy,"225g butter or margarine,225g caster sugar,225g self-raising flour,4 eggs,1 tsp baking powder,3 tbsp of jam for the filling,Icing sugar to dust the top,Cream to serve",victoria-sponge-umami.html,10,Cake,recipes/victoria-sponge-cake Gluten free pizza,pizza-umami.jpg,"Olives, basil, and mozzarella top a gluten free pizza crust with marinara sauce.","A gorgeous and simple gluten free pizza, with deliciously indulgent mozzeralla and Parma ham. Can easily be vegetarian by leaving out the ham.",Umami,Main course,15,15,30,,"400g gluten free flour, 125ml warm water, 125ml milk, 1 sachet dried yeast, 2 tsp sugar, 1 tsp salt, 2 tbsp olive oil, 4 tbsp tomato puree, 1 garlic clove, Fresh basil, 200g mozzarella, 100g rocket, 5 slices Parma ham",pizza-umami.html,4,,recipes/gluten-free-pizza Thai green curry,thai-green-curry-umami.jpg,"A traditional bowl of creamy, aromatic Thai green curry with chunks of chicken in a small bowl with jasmine rice.",A quick and easy version of the classic Thai green curry. Perfect for a midweek meal!,Umami,Main course,10,15,25,,"400g coconut milk, 400g chicken or tofu, 1 tbsp Thai green curry paste, 1 garlic clove, 2 tsp fish sauce, 400g mushrooms, 200g green beans, Fresh coriander leaves, Jasmine rice",thai-green-curry-umami.html,4,,recipes/thai-green-curry +Crema catalana,crema-catalana-umami.jpg,"Typical Catalan dessert made from cream and egg yolks, covered with a traditional layer of caramelized sugar to provide a crispy contrast.",Enjoy this sweet recipe for one of the oldest desserts in Europe. It requires very few ingredients!,Umami,Dessert,10,20,30,,"1l milk, 200g sugar, 6 egg yolks, 30g cornstarch, 1 cinnamon stick, 1 piece lemon peel",crema-catalana-umami.html,8,"Egg, Vegetarian",recipes/crema-catalana +Fiery chili sauce,chili-sauce-umami.jpg,"An iridescent array of chilies, onions, and garlic, slowly sweating over a low heat","A rich and fiery chili sauce. Take care when handling chili peppers. And serve sparingly!",Umami,Accompaniment,10,50,60,easy,"2 red onions, 1 lemon, 2 limes, 250ml malt vinegar, 7 garlic cloves, 1 green bell pepper, 1 red bell pepper, 800g cherry tomatoes, 30 mixed chilies, Olive oil, 1 tbsp ground black pepper, 1 tbsp brown sugar",chili-sauce-umami.html,60,Vegetarian,recipes/fiery-chili-sauce diff -r e200cb7efeb3 -r c2387f117808 core/profiles/demo_umami/themes/umami/css/base.css --- a/core/profiles/demo_umami/themes/umami/css/base.css Thu Apr 26 11:26:54 2018 +0100 +++ b/core/profiles/demo_umami/themes/umami/css/base.css Tue Jul 10 15:07:59 2018 +0100 @@ -22,6 +22,7 @@ background-color: #e6eee0; color: #444; text-decoration: none; + outline-offset: 1px; } body { @@ -71,7 +72,6 @@ font-family: 'Scope One', Georgia, serif; font-size: 1.2rem; font-weight: 400; - font-weight: normal; transition: background-color 0.5s ease; } button:hover, @@ -218,7 +218,7 @@ color: #464646; display: block; font-size: 1rem; - font-weight: bold; + font-weight: 700; margin: 0.25rem 0; } diff -r e200cb7efeb3 -r c2387f117808 core/profiles/demo_umami/themes/umami/css/components/blocks/banner/banner.css --- a/core/profiles/demo_umami/themes/umami/css/components/blocks/banner/banner.css Thu Apr 26 11:26:54 2018 +0100 +++ b/core/profiles/demo_umami/themes/umami/css/components/blocks/banner/banner.css Tue Jul 10 15:07:59 2018 +0100 @@ -35,7 +35,6 @@ font-family: 'Scope One', Georgia, serif; font-size: 1.2rem; font-weight: 400; - font-weight: normal; transition: background-color 0.5s ease; } @@ -43,8 +42,8 @@ .block-type-banner-block .field--name-field-content-link a:hover { background-color: #00836d; color: #fff; - outline: 2px solid currentColor; - outline-offset: -2px; + box-shadow: 0 0 0 2px currentColor inset; + outline: none; } /* 768px */ @@ -62,6 +61,7 @@ margin: 0 auto; display: flex; padding: 0 1em; + height: 0; /* Required for flexbox vertical centering in IE11. Min-height will take precedence. */ min-height: 43vw; align-items: center; } diff -r e200cb7efeb3 -r c2387f117808 core/profiles/demo_umami/themes/umami/css/components/blocks/footer-promo/footer-promo.css --- a/core/profiles/demo_umami/themes/umami/css/components/blocks/footer-promo/footer-promo.css Thu Apr 26 11:26:54 2018 +0100 +++ b/core/profiles/demo_umami/themes/umami/css/components/blocks/footer-promo/footer-promo.css Tue Jul 10 15:07:59 2018 +0100 @@ -9,7 +9,7 @@ .block-type-footer-promo-block .block__title { font-size: 1.5rem; - font-weight: normal; + font-weight: 400; } .block-type-footer-promo-block .footer-promo-content { @@ -18,17 +18,14 @@ .block-type-footer-promo-block .footer-promo-content a { background-color: inherit; - display: block; color: #fff; - font-weight: bold; - text-decoration: none; + font-weight: 700; } .block-type-footer-promo-block .footer-promo-content a:active, .block-type-footer-promo-block .footer-promo-content a:focus, .block-type-footer-promo-block .footer-promo-content a:hover { background-color: transparent; - text-decoration: underline; } .block-type-footer-promo-block .footer-promo-content a:after { diff -r e200cb7efeb3 -r c2387f117808 core/profiles/demo_umami/themes/umami/css/components/blocks/search/search.css --- a/core/profiles/demo_umami/themes/umami/css/components/blocks/search/search.css Thu Apr 26 11:26:54 2018 +0100 +++ b/core/profiles/demo_umami/themes/umami/css/components/blocks/search/search.css Tue Jul 10 15:07:59 2018 +0100 @@ -67,6 +67,7 @@ margin-top: 0; margin-bottom: 0; } + .form-search { width: 20em; max-width: calc(100vw - 6.25em); @@ -79,9 +80,9 @@ font-size: 0.875rem; line-height: normal; background: url(../../../../images/svg/search.svg) no-repeat 0.5em center #fff; - background-size: 1.5em; color: #464646; } + .form-search:focus { outline: none; margin: 0 0 -2px -2px; diff -r e200cb7efeb3 -r c2387f117808 core/profiles/demo_umami/themes/umami/css/components/content-types/recipe/recipe.css --- a/core/profiles/demo_umami/themes/umami/css/components/content-types/recipe/recipe.css Thu Apr 26 11:26:54 2018 +0100 +++ b/core/profiles/demo_umami/themes/umami/css/components/content-types/recipe/recipe.css Tue Jul 10 15:07:59 2018 +0100 @@ -36,7 +36,8 @@ .node--type-recipe.node--view-mode-full .layout__region--top-first, .node--type-recipe.node--view-mode-full .layout__region--top-second { - flex: 0 0 calc(50% - 1rem); + flex: 0 0; + flex-basis: calc(50% - 1rem); /* fixed IE11 bug calc in shorthand */ } /* Recipe meta */ @@ -98,13 +99,13 @@ } } -.node--type-recipe.node--view-mode-full .layout__region--top-second .field { +.node--type-recipe.node--view-mode-full .layout__region--top-second .recipe-meta .field { flex: 1 0 auto; } /* Large */ @media screen and (min-width: 60rem) { /* 960px */ - .node--type-recipe.node--view-mode-full .layout__region--top-second .field { - flex: 0 0 100%; + .node--type-recipe.node--view-mode-full .layout__region--top-second .recipe-meta .field { + width: 100%; } } .node--type-recipe.node--view-mode-full .layout__region--top-second .field .field__label, @@ -143,7 +144,7 @@ } } .node--type-recipe.node--view-mode-full .layout__region--bottom > h2 { - flex: 0 0 100%; + flex: 0 1 100%; font-family: 'Scope One', Georgia, serif; font-size: 1.424em; font-weight: 400; @@ -169,6 +170,7 @@ .node--type-recipe.node--view-mode-full .layout__region--bottom-first { flex: 0 0 33%; padding: 0 2.369em 2.369em 2.369em; + max-width: 33%; /* fixed IE11 bug */ } } @@ -180,6 +182,7 @@ .node--type-recipe.node--view-mode-full .layout__region--bottom-second { flex: 0 0 67%; padding: 0 2.369em 2.369em 2.369em; + max-width: 67%; /* fixed IE11 bug */ } } diff -r e200cb7efeb3 -r c2387f117808 core/profiles/demo_umami/themes/umami/css/components/content/highlighted-bottom/highlighted-bottom.css --- a/core/profiles/demo_umami/themes/umami/css/components/content/highlighted-bottom/highlighted-bottom.css Thu Apr 26 11:26:54 2018 +0100 +++ b/core/profiles/demo_umami/themes/umami/css/components/content/highlighted-bottom/highlighted-bottom.css Tue Jul 10 15:07:59 2018 +0100 @@ -13,7 +13,7 @@ } .node--view-mode-highlighted-bottom .node__title { - font-weight: normal; + font-weight: 400; margin-bottom: 1rem; } diff -r e200cb7efeb3 -r c2387f117808 core/profiles/demo_umami/themes/umami/css/components/content/highlighted-medium/highlighted-medium.css --- a/core/profiles/demo_umami/themes/umami/css/components/content/highlighted-medium/highlighted-medium.css Thu Apr 26 11:26:54 2018 +0100 +++ b/core/profiles/demo_umami/themes/umami/css/components/content/highlighted-medium/highlighted-medium.css Tue Jul 10 15:07:59 2018 +0100 @@ -10,6 +10,10 @@ flex-direction: column; } +.node--view-mode-highlighted-medium .node__content { + flex: 0 0 auto; +} + .node--view-mode-highlighted-medium .node__meta { padding: 1rem 1.5rem 0 1.5rem; } @@ -20,7 +24,7 @@ } .node--view-mode-highlighted-medium .node__title { - font-weight: normal; + font-weight: 400; margin-bottom: 1rem; } diff -r e200cb7efeb3 -r c2387f117808 core/profiles/demo_umami/themes/umami/css/components/content/highlighted-small/highlighted-small.css --- a/core/profiles/demo_umami/themes/umami/css/components/content/highlighted-small/highlighted-small.css Thu Apr 26 11:26:54 2018 +0100 +++ b/core/profiles/demo_umami/themes/umami/css/components/content/highlighted-small/highlighted-small.css Tue Jul 10 15:07:59 2018 +0100 @@ -10,6 +10,10 @@ flex-direction: column; } +.node--view-mode-highlighted-small .node__content { + flex: 0 0 auto; +} + .node--view-mode-highlighted-small .node__meta { padding: 1rem 1.5rem 0 1.5rem; } @@ -20,7 +24,7 @@ } .node--view-mode-highlighted-small .node__title { - font-weight: normal; + font-weight: 400; margin-bottom: 1rem; } diff -r e200cb7efeb3 -r c2387f117808 core/profiles/demo_umami/themes/umami/css/components/content/highlighted-top/highlighted-top.css --- a/core/profiles/demo_umami/themes/umami/css/components/content/highlighted-top/highlighted-top.css Thu Apr 26 11:26:54 2018 +0100 +++ b/core/profiles/demo_umami/themes/umami/css/components/content/highlighted-top/highlighted-top.css Tue Jul 10 15:07:59 2018 +0100 @@ -31,6 +31,10 @@ /* Large */ @media screen and (min-width: 60rem) { /* 960px */ + .view-promoted-items--single .node--view-mode-highlighted-top .node__content { + flex: 0 0 auto; + } + .view-promoted-items--single .node--view-mode-highlighted-top .node__meta { order: -1; } @@ -41,7 +45,7 @@ } .node--view-mode-highlighted-top .node__title { - font-weight: normal; + font-weight: 400; margin-bottom: 1rem; } diff -r e200cb7efeb3 -r c2387f117808 core/profiles/demo_umami/themes/umami/css/components/fields/label-items.css --- a/core/profiles/demo_umami/themes/umami/css/components/fields/label-items.css Thu Apr 26 11:26:54 2018 +0100 +++ b/core/profiles/demo_umami/themes/umami/css/components/fields/label-items.css Tue Jul 10 15:07:59 2018 +0100 @@ -20,5 +20,5 @@ } .label-items .field__label { - font-weight: normal; + font-weight: 400; } diff -r e200cb7efeb3 -r c2387f117808 core/profiles/demo_umami/themes/umami/css/components/navigation/menu-account/menu-account.css --- a/core/profiles/demo_umami/themes/umami/css/components/navigation/menu-account/menu-account.css Thu Apr 26 11:26:54 2018 +0100 +++ b/core/profiles/demo_umami/themes/umami/css/components/navigation/menu-account/menu-account.css Tue Jul 10 15:07:59 2018 +0100 @@ -33,3 +33,6 @@ text-decoration: none; background-color: inherit; } +.menu-account__link:hover { + text-decoration: underline; +} diff -r e200cb7efeb3 -r c2387f117808 core/profiles/demo_umami/themes/umami/css/components/navigation/menu-footer/menu-footer.css --- a/core/profiles/demo_umami/themes/umami/css/components/navigation/menu-footer/menu-footer.css Thu Apr 26 11:26:54 2018 +0100 +++ b/core/profiles/demo_umami/themes/umami/css/components/navigation/menu-footer/menu-footer.css Tue Jul 10 15:07:59 2018 +0100 @@ -9,7 +9,7 @@ .menu-footer__title { font-size: 1.5rem; - font-weight: normal; + font-weight: 400; } .menu-footer__item { @@ -18,8 +18,7 @@ .menu-footer .menu-footer__link { background-color: transparent; - text-decoration: none; - font-weight: bold; + font-weight: 700; color: #fff; } @@ -27,7 +26,6 @@ .menu-footer .menu-footer__link:focus, .menu-footer .menu-footer__link:hover { background-color: transparent; - text-decoration: underline; } @media screen and (min-width: 60rem) { diff -r e200cb7efeb3 -r c2387f117808 core/profiles/demo_umami/themes/umami/css/components/navigation/menu-main/menu-main.css --- a/core/profiles/demo_umami/themes/umami/css/components/navigation/menu-main/menu-main.css Thu Apr 26 11:26:54 2018 +0100 +++ b/core/profiles/demo_umami/themes/umami/css/components/navigation/menu-main/menu-main.css Tue Jul 10 15:07:59 2018 +0100 @@ -75,7 +75,7 @@ display: flex; justify-content: flex-end; flex-wrap: wrap; - max-height: initial; + max-height: none; overflow: auto; } .menu-main-toggle { @@ -111,7 +111,9 @@ @media screen and (min-width: 48em) { .menu-main__wrapper { order: 4; - flex: 0 1 calc(100% - 220px); + flex-grow: 0; + flex-shrink: 1; + flex-basis: calc(100% - 220px); text-align: right; } } diff -r e200cb7efeb3 -r c2387f117808 core/profiles/demo_umami/themes/umami/css/layout/grid-2.css --- a/core/profiles/demo_umami/themes/umami/css/layout/grid-2.css Thu Apr 26 11:26:54 2018 +0100 +++ b/core/profiles/demo_umami/themes/umami/css/layout/grid-2.css Tue Jul 10 15:07:59 2018 +0100 @@ -19,7 +19,9 @@ } .grid--2 .views-row { display: flex; - flex: 0 0 calc(50% - 28px); + flex-grow: 0; + flex-shrink: 0; + flex-basis: calc(50% - 28px); margin: 0 14px 28px; padding: 0; } diff -r e200cb7efeb3 -r c2387f117808 core/profiles/demo_umami/themes/umami/css/layout/grid-3.css --- a/core/profiles/demo_umami/themes/umami/css/layout/grid-3.css Thu Apr 26 11:26:54 2018 +0100 +++ b/core/profiles/demo_umami/themes/umami/css/layout/grid-3.css Tue Jul 10 15:07:59 2018 +0100 @@ -19,7 +19,9 @@ } .grid--3 .views-row { display: flex; - flex: 0 0 calc(50% - 28px); + flex-grow: 0; + flex-shrink: 0; + flex-basis: calc(50% - 28px); margin: 0 14px 28px; padding: 0; } @@ -27,7 +29,9 @@ @media screen and (min-width: 60em) { .grid--3 .views-row { - flex: 0 0 calc(33% - 28px); + flex-grow: 0; + flex-shrink: 0; + flex-basis: calc(33% - 28px); } } diff -r e200cb7efeb3 -r c2387f117808 core/profiles/demo_umami/themes/umami/css/layout/grid-4.css --- a/core/profiles/demo_umami/themes/umami/css/layout/grid-4.css Thu Apr 26 11:26:54 2018 +0100 +++ b/core/profiles/demo_umami/themes/umami/css/layout/grid-4.css Tue Jul 10 15:07:59 2018 +0100 @@ -20,7 +20,9 @@ .grid--4 .views-row { display: flex; - flex: 0 0 calc(50% - 28px); + flex-grow: 0; + flex-shrink: 0; + flex-basis: calc(50% - 28px); margin: 0 14px 28px; padding: 0; } @@ -28,7 +30,9 @@ @media screen and (min-width: 60em) { .grid--4 .views-row { - flex: 0 0 calc(25% - 28px); + flex-grow: 0; + flex-shrink: 0; + flex-basis: calc(25% - 28px); } } diff -r e200cb7efeb3 -r c2387f117808 core/profiles/demo_umami/themes/umami/css/layout/layout-2-col.css --- a/core/profiles/demo_umami/themes/umami/css/layout/layout-2-col.css Thu Apr 26 11:26:54 2018 +0100 +++ b/core/profiles/demo_umami/themes/umami/css/layout/layout-2-col.css Tue Jul 10 15:07:59 2018 +0100 @@ -12,7 +12,12 @@ justify-content: space-between; } + .two-columns .main .layout-content { + flex: 0 0 75%; + } + .layout-sidebar { + flex: 0 0 25%; min-width: 300px; width: 25%; } diff -r e200cb7efeb3 -r c2387f117808 core/profiles/demo_umami/themes/umami/images/svg/search.svg --- a/core/profiles/demo_umami/themes/umami/images/svg/search.svg Thu Apr 26 11:26:54 2018 +0100 +++ b/core/profiles/demo_umami/themes/umami/images/svg/search.svg Tue Jul 10 15:07:59 2018 +0100 @@ -1,12 +1,14 @@ - - - - - - - - - - + + Search Icon + + + + + + + + + + + + \ No newline at end of file diff -r e200cb7efeb3 -r c2387f117808 core/profiles/demo_umami/themes/umami/logo.svg --- a/core/profiles/demo_umami/themes/umami/logo.svg Thu Apr 26 11:26:54 2018 +0100 +++ b/core/profiles/demo_umami/themes/umami/logo.svg Tue Jul 10 15:07:59 2018 +0100 @@ -1,5 +1,5 @@ - + umami logo diff -r e200cb7efeb3 -r c2387f117808 core/profiles/demo_umami/themes/umami/templates/components/messages/status-messages.html.twig --- a/core/profiles/demo_umami/themes/umami/templates/components/messages/status-messages.html.twig Thu Apr 26 11:26:54 2018 +0100 +++ b/core/profiles/demo_umami/themes/umami/templates/components/messages/status-messages.html.twig Tue Jul 10 15:07:59 2018 +0100 @@ -15,8 +15,6 @@ * Available variables: * - message_list: List of messages to be displayed, grouped by type. * - status_headings: List of all status types. - * - display: (optional) May have a value of 'status' or 'error' when only - * displaying messages of that specific type. * - attributes: HTML attributes for the element, including: * - class: HTML classes. */ diff -r e200cb7efeb3 -r c2387f117808 core/scripts/run-tests.sh --- a/core/scripts/run-tests.sh Thu Apr 26 11:26:54 2018 +0100 +++ b/core/scripts/run-tests.sh Tue Jul 10 15:07:59 2018 +0100 @@ -48,7 +48,7 @@ simpletest_script_init(); if (!class_exists(TestCase::class)) { - echo "\nrun-tests.sh requires the PHPUnit testing framework. Please use 'composer install --dev' to ensure that it is present.\n\n"; + echo "\nrun-tests.sh requires the PHPUnit testing framework. Please use 'composer install' to ensure that it is present.\n\n"; exit(SIMPLETEST_SCRIPT_EXIT_FAILURE); } diff -r e200cb7efeb3 -r c2387f117808 core/tests/Drupal/FunctionalJavascriptTests/JavascriptTestBase.php --- a/core/tests/Drupal/FunctionalJavascriptTests/JavascriptTestBase.php Thu Apr 26 11:26:54 2018 +0100 +++ b/core/tests/Drupal/FunctionalJavascriptTests/JavascriptTestBase.php Tue Jul 10 15:07:59 2018 +0100 @@ -92,11 +92,12 @@ * @param string $message * Optional message to show alongside the assertion. * - * @deprecated in Drupal 8.1.x, will be removed before Drupal 8.3.x. Use + * @deprecated in Drupal 8.1.0, will be removed before Drupal 9.0.0. Use * \Behat\Mink\Element\NodeElement::isVisible() instead. */ protected function assertElementVisible($css_selector, $message = '') { $this->assertTrue($this->getSession()->getDriver()->isVisible($this->cssSelectToXpath($css_selector)), $message); + @trigger_error('The ' . __METHOD__ . ' method is deprecated since version 8.1.0 and will be removed in 9.0.0. Use \Behat\Mink\Element\NodeElement::isVisible() instead.', E_USER_DEPRECATED); } /** @@ -107,11 +108,12 @@ * @param string $message * Optional message to show alongside the assertion. * - * @deprecated in Drupal 8.1.x, will be removed before Drupal 8.3.x. Use + * @deprecated in Drupal 8.1.0, will be removed before Drupal 9.0.0. Use * \Behat\Mink\Element\NodeElement::isVisible() instead. */ protected function assertElementNotVisible($css_selector, $message = '') { $this->assertFalse($this->getSession()->getDriver()->isVisible($this->cssSelectToXpath($css_selector)), $message); + @trigger_error('The ' . __METHOD__ . ' method is deprecated since version 8.1.0 and will be removed in 9.0.0. Use \Behat\Mink\Element\NodeElement::isVisible() instead.', E_USER_DEPRECATED); } /** diff -r e200cb7efeb3 -r c2387f117808 core/tests/Drupal/FunctionalTests/BrowserTestBaseTest.php --- a/core/tests/Drupal/FunctionalTests/BrowserTestBaseTest.php Thu Apr 26 11:26:54 2018 +0100 +++ b/core/tests/Drupal/FunctionalTests/BrowserTestBaseTest.php Tue Jul 10 15:07:59 2018 +0100 @@ -68,6 +68,21 @@ } /** + * Tests drupalGet(). + */ + public function testDrupalGet() { + $this->drupalGet('test-page'); + $this->assertSession()->statusCodeEquals(200); + $this->assertSession()->addressEquals('test-page'); + $this->drupalGet('/test-page'); + $this->assertSession()->statusCodeEquals(200); + $this->assertSession()->addressEquals('test-page'); + $this->drupalGet('/test-page/'); + $this->assertSession()->statusCodeEquals(200); + $this->assertSession()->addressEquals('/test-page/'); + } + + /** * Tests basic form functionality. */ public function testForm() { diff -r e200cb7efeb3 -r c2387f117808 core/tests/Drupal/FunctionalTests/Hal/BaseFieldOverrideHalJsonAnonTest.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/core/tests/Drupal/FunctionalTests/Hal/BaseFieldOverrideHalJsonAnonTest.php Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,30 @@ +addToAssertionCount(1); + /** @var \Drupal\Core\Config\StorageInterface $active_config_storage */ + $active_config_storage = $this->container->get('config.storage'); + /** @var \Drupal\Core\Config\ConfigManagerInterface $config_manager */ + $config_manager = $this->container->get('config.manager'); + + $default_install_path = 'core/profiles/' . $this->profile . '/' . InstallStorage::CONFIG_INSTALL_DIRECTORY; + $profile_config_storage = new FileStorage($default_install_path, StorageInterface::DEFAULT_COLLECTION); + + foreach ($profile_config_storage->listAll() as $config_name) { + $result = $config_manager->diff($profile_config_storage, $active_config_storage, $config_name); + try { + $this->assertConfigDiff($result, $config_name, $skipped_config); + } + catch (\Exception $e) { + $this->fail($e->getMessage()); + } + } + } + +} diff -r e200cb7efeb3 -r c2387f117808 core/tests/Drupal/FunctionalTests/Installer/DistributionProfileExistingSettingsTest.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/core/tests/Drupal/FunctionalTests/Installer/DistributionProfileExistingSettingsTest.php Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,130 @@ +info = [ + 'type' => 'profile', + 'core' => \Drupal::CORE_COMPATIBILITY, + 'name' => 'Distribution profile', + 'distribution' => [ + 'name' => 'My Distribution', + 'install' => [ + 'theme' => 'bartik', + ], + ], + ]; + // File API functions are not available yet. + $path = $this->siteDirectory . '/profiles/mydistro'; + mkdir($path, 0777, TRUE); + file_put_contents("$path/mydistro.info.yml", Yaml::encode($this->info)); + + // Pre-configure hash salt. + // Any string is valid, so simply use the class name of this test. + $this->settings['settings']['hash_salt'] = (object) [ + 'value' => __CLASS__, + 'required' => TRUE, + ]; + + // Pre-configure database credentials. + $connection_info = Database::getConnectionInfo(); + unset($connection_info['default']['pdo']); + unset($connection_info['default']['init_commands']); + + $this->settings['databases']['default'] = (object) [ + 'value' => $connection_info, + 'required' => TRUE, + ]; + + // Use the kernel to find the site path because the site.path service should + // not be available at this point in the install process. + $site_path = DrupalKernel::findSitePath(Request::createFromGlobals()); + // Pre-configure config directories. + $this->settings['config_directories'] = [ + CONFIG_SYNC_DIRECTORY => (object) [ + 'value' => $site_path . '/files/config_staging', + 'required' => TRUE, + ], + ]; + mkdir($this->settings['config_directories'][CONFIG_SYNC_DIRECTORY]->value, 0777, TRUE); + } + + /** + * {@inheritdoc} + */ + protected function setUpLanguage() { + // Make settings file not writable. + $filename = $this->siteDirectory . '/settings.php'; + // Make the settings file read-only. + // Not using File API; a potential error must trigger a PHP warning. + chmod($filename, 0444); + + // Verify that the distribution name appears. + $this->assertRaw($this->info['distribution']['name']); + // Verify that the requested theme is used. + $this->assertRaw($this->info['distribution']['install']['theme']); + // Verify that the "Choose profile" step does not appear. + $this->assertNoText('profile'); + + parent::setUpLanguage(); + } + + /** + * {@inheritdoc} + */ + protected function setUpProfile() { + // This step is skipped, because there is a distribution profile. + } + + /** + * {@inheritdoc} + */ + protected function setUpSettings() { + // This step should not appear, since settings.php is fully configured + // already. + } + + /** + * Confirms that the installation succeeded. + */ + public function testInstalled() { + $this->assertUrl('user/1'); + $this->assertResponse(200); + // Confirm that we are logged-in after installation. + $this->assertText($this->rootUser->getUsername()); + + // Confirm that Drupal recognizes this distribution as the current profile. + $this->assertEqual(\Drupal::installProfile(), 'mydistro'); + $this->assertNull(Settings::get('install_profile'), 'The install profile has not been written to settings.php.'); + $this->assertEqual($this->config('core.extension')->get('profile'), 'mydistro', 'The install profile has been written to core.extension configuration.'); + + $this->rebuildContainer(); + $this->pass('Container can be rebuilt even though distribution is not written to settings.php.'); + $this->assertEqual(\Drupal::installProfile(), 'mydistro'); + } + +} diff -r e200cb7efeb3 -r c2387f117808 core/tests/Drupal/FunctionalTests/Installer/DistributionProfileTest.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/core/tests/Drupal/FunctionalTests/Installer/DistributionProfileTest.php Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,79 @@ +info = [ + 'type' => 'profile', + 'core' => \Drupal::CORE_COMPATIBILITY, + 'name' => 'Distribution profile', + 'distribution' => [ + 'name' => 'My Distribution', + 'install' => [ + 'theme' => 'bartik', + ], + ], + ]; + // File API functions are not available yet. + $path = $this->siteDirectory . '/profiles/mydistro'; + mkdir($path, 0777, TRUE); + file_put_contents("$path/mydistro.info.yml", Yaml::encode($this->info)); + } + + /** + * {@inheritdoc} + */ + protected function setUpLanguage() { + // Verify that the distribution name appears. + $this->assertRaw($this->info['distribution']['name']); + // Verify that the distribution name is used in the site title. + $this->assertTitle('Choose language | ' . $this->info['distribution']['name']); + // Verify that the requested theme is used. + $this->assertRaw($this->info['distribution']['install']['theme']); + // Verify that the "Choose profile" step does not appear. + $this->assertNoText('profile'); + + parent::setUpLanguage(); + } + + /** + * {@inheritdoc} + */ + protected function setUpProfile() { + // This step is skipped, because there is a distribution profile. + } + + /** + * Confirms that the installation succeeded. + */ + public function testInstalled() { + $this->assertUrl('user/1'); + $this->assertResponse(200); + // Confirm that we are logged-in after installation. + $this->assertText($this->rootUser->getUsername()); + + // Confirm that Drupal recognizes this distribution as the current profile. + $this->assertEqual(\Drupal::installProfile(), 'mydistro'); + $this->assertEqual(Settings::get('install_profile'), 'mydistro', 'The install profile has been written to settings.php.'); + $this->assertEqual($this->config('core.extension')->get('profile'), 'mydistro', 'The install profile has been written to core.extension configuration.'); + } + +} diff -r e200cb7efeb3 -r c2387f117808 core/tests/Drupal/FunctionalTests/Installer/DistributionProfileTranslationQueryTest.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/core/tests/Drupal/FunctionalTests/Installer/DistributionProfileTranslationQueryTest.php Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,139 @@ +info = [ + 'type' => 'profile', + 'core' => \Drupal::CORE_COMPATIBILITY, + 'name' => 'Distribution profile', + 'distribution' => [ + 'name' => 'My Distribution', + 'langcode' => $this->langcode, + 'install' => [ + 'theme' => 'bartik', + ], + ], + ]; + // File API functions are not available yet. + $path = $this->root . DIRECTORY_SEPARATOR . $this->siteDirectory . '/profiles/mydistro'; + mkdir($path, 0777, TRUE); + file_put_contents("$path/mydistro.info.yml", Yaml::encode($this->info)); + // Place a custom local translation in the translations directory. + mkdir($this->root . '/' . $this->siteDirectory . '/files/translations', 0777, TRUE); + file_put_contents($this->root . '/' . $this->siteDirectory . '/files/translations/drupal-8.0.0.de.po', $this->getPo('de')); + file_put_contents($this->root . '/' . $this->siteDirectory . '/files/translations/drupal-8.0.0.fr.po', $this->getPo('fr')); + } + + /** + * {@inheritdoc} + */ + protected function visitInstaller() { + // Pass a different language code than the one set in the distribution + // profile. This distribution language should still be used. + // The unrouted URL assembler does not exist at this point, so we build the + // URL ourselves. + $this->drupalGet($GLOBALS['base_url'] . '/core/install.php' . '?langcode=fr'); + } + + /** + * {@inheritdoc} + */ + protected function setUpLanguage() { + // This step is skipped, because the distribution profile uses a fixed + // language. + } + + /** + * {@inheritdoc} + */ + protected function setUpProfile() { + // This step is skipped, because there is a distribution profile. + } + + /** + * {@inheritdoc} + */ + protected function setUpSettings() { + // The language should have been automatically detected, all following + // screens should be translated already. + $elements = $this->xpath('//input[@type="submit"]/@value'); + $this->assertEqual(current($elements)->getText(), 'Save and continue de'); + $this->translations['Save and continue'] = 'Save and continue de'; + + // Check the language direction. + $direction = $this->getSession()->getPage()->find('xpath', '/@dir')->getText(); + $this->assertEqual($direction, 'ltr'); + + // Verify that the distribution name appears. + $this->assertRaw($this->info['distribution']['name']); + // Verify that the requested theme is used. + $this->assertRaw($this->info['distribution']['install']['theme']); + // Verify that the "Choose profile" step does not appear. + $this->assertNoText('profile'); + + parent::setUpSettings(); + } + + /** + * Confirms that the installation succeeded. + */ + public function testInstalled() { + $this->assertUrl('user/1'); + $this->assertResponse(200); + + // Confirm that we are logged-in after installation. + $this->assertText($this->rootUser->getDisplayName()); + + // Verify German was configured but not English. + $this->drupalGet('admin/config/regional/language'); + $this->assertText('German'); + $this->assertNoText('English'); + } + + /** + * Returns the string for the test .po file. + * + * @param string $langcode + * The language code. + * @return string + * Contents for the test .po file. + */ + protected function getPo($langcode) { + return <<info = [ + 'type' => 'profile', + 'core' => \Drupal::CORE_COMPATIBILITY, + 'name' => 'Distribution profile', + 'distribution' => [ + 'name' => 'My Distribution', + 'langcode' => $this->langcode, + 'install' => [ + 'theme' => 'bartik', + ], + ], + ]; + // File API functions are not available yet. + $path = $this->root . DIRECTORY_SEPARATOR . $this->siteDirectory . '/profiles/mydistro'; + mkdir($path, 0777, TRUE); + file_put_contents("$path/mydistro.info.yml", Yaml::encode($this->info)); + + // Place a custom local translation in the translations directory. + mkdir($this->root . '/' . $this->siteDirectory . '/files/translations', 0777, TRUE); + file_put_contents($this->root . '/' . $this->siteDirectory . '/files/translations/drupal-8.0.0.de.po', $this->getPo('de')); + } + + /** + * {@inheritdoc} + */ + protected function setUpLanguage() { + // This step is skipped, because the distribution profile uses a fixed + // language. + } + + /** + * {@inheritdoc} + */ + protected function setUpProfile() { + // This step is skipped, because there is a distribution profile. + } + + /** + * {@inheritdoc} + */ + protected function setUpSettings() { + // The language should have been automatically detected, all following + // screens should be translated already. + $elements = $this->xpath('//input[@type="submit"]/@value'); + $this->assertEqual(current($elements)->getText(), 'Save and continue de'); + $this->translations['Save and continue'] = 'Save and continue de'; + + // Check the language direction. + $direction = current($this->xpath('/@dir'))->getText(); + $this->assertEqual($direction, 'ltr'); + + // Verify that the distribution name appears. + $this->assertRaw($this->info['distribution']['name']); + // Verify that the requested theme is used. + $this->assertRaw($this->info['distribution']['install']['theme']); + // Verify that the "Choose profile" step does not appear. + $this->assertNoText('profile'); + + parent::setUpSettings(); + } + + + /** + * Confirms that the installation succeeded. + */ + public function testInstalled() { + $this->assertUrl('user/1'); + $this->assertResponse(200); + + // Confirm that we are logged-in after installation. + $this->assertText($this->rootUser->getDisplayName()); + + // Verify German was configured but not English. + $this->drupalGet('admin/config/regional/language'); + $this->assertText('German'); + $this->assertNoText('English'); + } + + /** + * Returns the string for the test .po file. + * + * @param string $langcode + * The language code. + * @return string + * Contents for the test .po file. + */ + protected function getPo($langcode) { + return <<configDirectory = $this->publicFilesDirectory . '/config_' . Crypt::randomBytesBase64(); + $this->settings['config_directories'][CONFIG_SYNC_DIRECTORY] = (object) [ + 'value' => $this->configDirectory . '/sync', + 'required' => TRUE, + ]; + // Create the files directory early so we can test the error case. + mkdir($this->publicFilesDirectory); + // Create a file so the directory can not be created. + file_put_contents($this->configDirectory, 'Test'); + } + + /** + * Installer step: Configure settings. + */ + protected function setUpSettings() { + // This step should not appear as we had a failure prior to the settings + // screen. + } + + /** + * {@inheritdoc} + */ + protected function setUpSite() { + // This step should not appear as we had a failure prior to the settings + // screen. + } + + /** + * Verifies that installation failed. + */ + public function testError() { + $this->assertText("An automated attempt to create the directory {$this->configDirectory}/sync failed, possibly due to a permissions problem."); + $this->assertFalse(file_exists($this->configDirectory . '/sync') && is_dir($this->configDirectory . '/sync'), "The directory {$this->configDirectory}/sync does not exist."); + } + +} diff -r e200cb7efeb3 -r c2387f117808 core/tests/Drupal/FunctionalTests/Installer/InstallerConfigDirectorySetNoDirectoryTest.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/core/tests/Drupal/FunctionalTests/Installer/InstallerConfigDirectorySetNoDirectoryTest.php Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,48 @@ +syncDirectory = $this->publicFilesDirectory . '/config_' . Crypt::randomBytesBase64() . '/sync'; + $this->settings['config_directories'][CONFIG_SYNC_DIRECTORY] = (object) [ + 'value' => $this->syncDirectory, + 'required' => TRUE, + ]; + // Other directories will be created too. + $this->settings['config_directories']['custom'] = (object) [ + 'value' => $this->publicFilesDirectory . '/config_custom', + 'required' => TRUE, + ]; + } + + /** + * Verifies that installation succeeded. + */ + public function testInstaller() { + $this->assertUrl('user/1'); + $this->assertResponse(200); + $this->assertTrue(file_exists($this->syncDirectory) && is_dir($this->syncDirectory), "The directory {$this->syncDirectory} exists."); + $this->assertTrue(file_exists($this->publicFilesDirectory . '/config_custom') && is_dir($this->publicFilesDirectory . '/config_custom'), "The directory {$this->publicFilesDirectory}/custom_config exists."); + } + +} diff -r e200cb7efeb3 -r c2387f117808 core/tests/Drupal/FunctionalTests/Installer/InstallerDatabaseErrorMessagesTest.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/core/tests/Drupal/FunctionalTests/Installer/InstallerDatabaseErrorMessagesTest.php Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,40 @@ +query('CREATE TABLE {drupal_install_test} (id int NULL)'); + parent::setUpSettings(); + } + + /** + * {@inheritdoc} + */ + protected function setUpSite() { + // This step should not appear as we had a failure on the settings screen. + } + + /** + * Verifies that the error message in the settings step is correct. + */ + public function testSetUpSettingsErrorMessage() { + $this->assertRaw('
    • Failed to CREATE a test table'); + } + +} diff -r e200cb7efeb3 -r c2387f117808 core/tests/Drupal/FunctionalTests/Installer/InstallerEmptySettingsTest.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/core/tests/Drupal/FunctionalTests/Installer/InstallerEmptySettingsTest.php Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,30 @@ +root . DIRECTORY_SEPARATOR . $this->siteDirectory; + file_put_contents($path . '/settings.php', ''); + } + + /** + * Verifies that installation succeeded. + */ + public function testInstaller() { + $this->assertUrl('user/1'); + $this->assertResponse(200); + } + +} diff -r e200cb7efeb3 -r c2387f117808 core/tests/Drupal/FunctionalTests/Installer/InstallerExistingConfigDirectoryTest.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/core/tests/Drupal/FunctionalTests/Installer/InstallerExistingConfigDirectoryTest.php Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,42 @@ +root . DIRECTORY_SEPARATOR . $this->siteDirectory . '/config_read_only', 0444); + $this->expectedFilePerms = fileperms($this->siteDirectory . '/config_read_only'); + $this->settings['config_directories'][CONFIG_SYNC_DIRECTORY] = (object) [ + 'value' => $this->siteDirectory . '/config_read_only', + 'required' => TRUE, + ]; + } + + /** + * Verifies that installation succeeded. + */ + public function testInstaller() { + $this->assertUrl('user/1'); + $this->assertResponse(200); + $this->assertEqual($this->expectedFilePerms, fileperms($this->siteDirectory . '/config_read_only')); + $this->assertEqual([], glob($this->siteDirectory . '/config_read_only/*'), 'The sync directory is empty after install because it is read-only.'); + } + +} diff -r e200cb7efeb3 -r c2387f117808 core/tests/Drupal/FunctionalTests/Installer/InstallerExistingDatabaseSettingsTest.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/core/tests/Drupal/FunctionalTests/Installer/InstallerExistingDatabaseSettingsTest.php Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,61 @@ +settings['databases']['default'] = (object) [ + 'value' => $connection_info, + 'required' => TRUE, + ]; + } + + /** + * {@inheritdoc} + * + * @todo The database settings form is not supposed to appear if settings.php + * contains a valid database connection already (but e.g. no config + * directories yet). + */ + protected function setUpSettings() { + // All database settings should be pre-configured, except password. + $values = $this->parameters['forms']['install_settings_form']; + $driver = $values['driver']; + $edit = []; + if (isset($values[$driver]['password']) && $values[$driver]['password'] !== '') { + $edit = $this->translatePostValues([ + $driver => [ + 'password' => $values[$driver]['password'], + ], + ]); + } + $this->drupalPostForm(NULL, $edit, $this->translations['Save and continue']); + } + + /** + * Verifies that installation succeeded. + */ + public function testInstaller() { + $this->assertUrl('user/1'); + $this->assertResponse(200); + } + +} diff -r e200cb7efeb3 -r c2387f117808 core/tests/Drupal/FunctionalTests/Installer/InstallerExistingInstallationTest.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/core/tests/Drupal/FunctionalTests/Installer/InstallerExistingInstallationTest.php Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,31 @@ +visitInstaller(); + $this->assertRaw('Drupal already installed'); + + // Delete settings.php and attempt to reinstall again. + unlink($this->siteDirectory . '/settings.php'); + $this->visitInstaller(); + $this->setUpLanguage(); + $this->setUpProfile(); + $this->setUpRequirementsProblem(); + $this->setUpSettings(); + $this->assertRaw('Drupal already installed'); + } + +} diff -r e200cb7efeb3 -r c2387f117808 core/tests/Drupal/FunctionalTests/Installer/InstallerExistingSettingsMismatchProfileBrokenTest.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/core/tests/Drupal/FunctionalTests/Installer/InstallerExistingSettingsMismatchProfileBrokenTest.php Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,106 @@ +settings['settings']['hash_salt'] = (object) [ + 'value' => __CLASS__, + 'required' => TRUE, + ]; + + // Pre-configure database credentials. + $connection_info = Database::getConnectionInfo(); + unset($connection_info['default']['pdo']); + unset($connection_info['default']['init_commands']); + + $this->settings['databases']['default'] = (object) [ + 'value' => $connection_info, + 'required' => TRUE, + ]; + + // During interactive install we'll change this to a different profile and + // this test will ensure that the new value is written to settings.php. + $this->settings['settings']['install_profile'] = (object) [ + 'value' => 'minimal', + 'required' => TRUE, + ]; + + // Pre-configure config directories. + $site_path = DrupalKernel::findSitePath(Request::createFromGlobals()); + $this->settings['config_directories'] = [ + CONFIG_SYNC_DIRECTORY => (object) [ + 'value' => $site_path . '/files/config_staging', + 'required' => TRUE, + ], + ]; + mkdir($this->settings['config_directories'][CONFIG_SYNC_DIRECTORY]->value, 0777, TRUE); + } + + /** + * {@inheritdoc} + */ + protected function visitInstaller() { + // Make settings file not writable. This will break the installer. + $filename = $this->siteDirectory . '/settings.php'; + // Make the settings file read-only. + // Not using File API; a potential error must trigger a PHP warning. + chmod($filename, 0444); + + $this->drupalGet($GLOBALS['base_url'] . '/core/install.php?langcode=en&profile=testing'); + } + + /** + * {@inheritdoc} + */ + protected function setUpLanguage() { + // This step is skipped, because there is a lagcode as a query param. + } + + /** + * {@inheritdoc} + */ + protected function setUpProfile() { + // This step is skipped, because there is a profile as a query param. + } + + /** + * {@inheritdoc} + */ + protected function setUpSettings() { + // This step should not appear, since settings.php is fully configured + // already. + } + + protected function setUpSite() { + // This step should not appear, since settings.php could not be written. + } + + /** + * Verifies that installation did not succeed. + */ + public function testBrokenInstaller() { + $this->assertTitle('Install profile mismatch | Drupal'); + $this->assertText("The selected profile testing does not match the install_profile setting, which is minimal. Cannot write updated setting to {$this->siteDirectory}/settings.php."); + } + +} diff -r e200cb7efeb3 -r c2387f117808 core/tests/Drupal/FunctionalTests/Installer/InstallerExistingSettingsMismatchProfileTest.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/core/tests/Drupal/FunctionalTests/Installer/InstallerExistingSettingsMismatchProfileTest.php Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,99 @@ +settings['settings']['hash_salt'] = (object) [ + 'value' => __CLASS__, + 'required' => TRUE, + ]; + + // Pre-configure database credentials. + $connection_info = Database::getConnectionInfo(); + unset($connection_info['default']['pdo']); + unset($connection_info['default']['init_commands']); + + $this->settings['databases']['default'] = (object) [ + 'value' => $connection_info, + 'required' => TRUE, + ]; + + // During interactive install we'll change this to a different profile and + // this test will ensure that the new value is written to settings.php. + $this->settings['settings']['install_profile'] = (object) [ + 'value' => 'minimal', + 'required' => TRUE, + ]; + + // Pre-configure config directories. + $this->settings['config_directories'] = [ + CONFIG_SYNC_DIRECTORY => (object) [ + 'value' => DrupalKernel::findSitePath(Request::createFromGlobals()) . '/files/config_sync', + 'required' => TRUE, + ], + ]; + mkdir($this->settings['config_directories'][CONFIG_SYNC_DIRECTORY]->value, 0777, TRUE); + } + + /** + * {@inheritdoc} + */ + protected function visitInstaller() { + // Provide profile and language in query string to skip these pages. + $this->drupalGet($GLOBALS['base_url'] . '/core/install.php?langcode=en&profile=testing'); + } + + /** + * {@inheritdoc} + */ + protected function setUpLanguage() { + // This step is skipped, because there is a lagcode as a query param. + } + + /** + * {@inheritdoc} + */ + protected function setUpProfile() { + // This step is skipped, because there is a profile as a query param. + } + + /** + * {@inheritdoc} + */ + protected function setUpSettings() { + // This step should not appear, since settings.php is fully configured + // already. + } + + /** + * Verifies that installation succeeded. + */ + public function testInstaller() { + $this->assertUrl('user/1'); + $this->assertResponse(200); + $this->assertEqual('testing', \Drupal::installProfile()); + $this->assertEqual('testing', Settings::get('install_profile'), 'Profile was correctly changed to testing in Settings.php'); + } + +} diff -r e200cb7efeb3 -r c2387f117808 core/tests/Drupal/FunctionalTests/Installer/InstallerExistingSettingsNoProfileTest.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/core/tests/Drupal/FunctionalTests/Installer/InstallerExistingSettingsNoProfileTest.php Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,69 @@ +settings['settings']['hash_salt'] = (object) [ + 'value' => __CLASS__, + 'required' => TRUE, + ]; + + // Pre-configure database credentials. + $connection_info = Database::getConnectionInfo(); + unset($connection_info['default']['pdo']); + unset($connection_info['default']['init_commands']); + + $this->settings['databases']['default'] = (object) [ + 'value' => $connection_info, + 'required' => TRUE, + ]; + + // Pre-configure config directories. + $this->settings['config_directories'] = [ + CONFIG_SYNC_DIRECTORY => (object) [ + 'value' => DrupalKernel::findSitePath(Request::createFromGlobals()) . '/files/config_sync', + 'required' => TRUE, + ], + ]; + mkdir($this->settings['config_directories'][CONFIG_SYNC_DIRECTORY]->value, 0777, TRUE); + } + + /** + * {@inheritdoc} + */ + protected function setUpSettings() { + // This step should not appear, since settings.php is fully configured + // already. + } + + /** + * Verifies that installation succeeded. + */ + public function testInstaller() { + $this->assertUrl('user/1'); + $this->assertResponse(200); + $this->assertEqual('testing', \Drupal::installProfile()); + } + +} diff -r e200cb7efeb3 -r c2387f117808 core/tests/Drupal/FunctionalTests/Installer/InstallerExistingSettingsTest.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/core/tests/Drupal/FunctionalTests/Installer/InstallerExistingSettingsTest.php Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,80 @@ +settings['settings']['hash_salt'] = (object) [ + 'value' => __CLASS__, + 'required' => TRUE, + ]; + + // During interactive install we'll change this to a different profile and + // this test will ensure that the new value is written to settings.php. + $this->settings['settings']['install_profile'] = (object) [ + 'value' => 'minimal', + 'required' => TRUE, + ]; + + // Pre-configure database credentials. + $connection_info = Database::getConnectionInfo(); + unset($connection_info['default']['pdo']); + unset($connection_info['default']['init_commands']); + + $this->settings['databases']['default'] = (object) [ + 'value' => $connection_info, + 'required' => TRUE, + ]; + + // Use the kernel to find the site path because the site.path service should + // not be available at this point in the install process. + $site_path = DrupalKernel::findSitePath(Request::createFromGlobals()); + // Pre-configure config directories. + $this->settings['config_directories'] = [ + CONFIG_SYNC_DIRECTORY => (object) [ + 'value' => $site_path . '/files/config_sync', + 'required' => TRUE, + ], + ]; + mkdir($this->settings['config_directories'][CONFIG_SYNC_DIRECTORY]->value, 0777, TRUE); + } + + /** + * {@inheritdoc} + */ + protected function setUpSettings() { + // This step should not appear, since settings.php is fully configured + // already. + } + + /** + * Verifies that installation succeeded. + */ + public function testInstaller() { + $this->assertUrl('user/1'); + $this->assertResponse(200); + $this->assertEqual('testing', \Drupal::installProfile(), 'Profile was changed from minimal to testing during interactive install.'); + $this->assertEqual('testing', Settings::get('install_profile'), 'Profile was correctly changed to testing in Settings.php'); + } + +} diff -r e200cb7efeb3 -r c2387f117808 core/tests/Drupal/FunctionalTests/Installer/InstallerLanguageDirectionTest.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/core/tests/Drupal/FunctionalTests/Installer/InstallerLanguageDirectionTest.php Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,47 @@ +siteDirectory . '/files/translations', 0777, TRUE); + file_put_contents(\Drupal::root() . '/' . $this->siteDirectory . '/files/translations/drupal-8.0.0.ar.po', "msgid \"\"\nmsgstr \"\"\nmsgid \"Save and continue\"\nmsgstr \"Save and continue Arabic\""); + + parent::setUpLanguage(); + // After selecting a different language than English, all following screens + // should be translated already. + $elements = $this->xpath('//input[@type="submit"]/@value'); + $this->assertEqual(current($elements)->getText(), 'Save and continue Arabic'); + $this->translations['Save and continue'] = 'Save and continue Arabic'; + + // Verify that language direction is right-to-left. + $direction = current($this->xpath('/@dir'))->getText(); + $this->assertEqual($direction, 'rtl'); + } + + /** + * Confirms that the installation succeeded. + */ + public function testInstalled() { + $this->assertUrl('user/1'); + $this->assertResponse(200); + } + +} diff -r e200cb7efeb3 -r c2387f117808 core/tests/Drupal/FunctionalTests/Installer/InstallerLanguagePageTest.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/core/tests/Drupal/FunctionalTests/Installer/InstallerLanguagePageTest.php Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,44 @@ +siteDirectory . '/files/translations', 0777, TRUE); + touch(\Drupal::root() . '/' . $this->siteDirectory . '/files/translations/drupal-8.0.0.xoxo.po'); + + // Check that all predefined languages show up with their native names. + $this->visitInstaller(); + foreach (LanguageManager::getStandardLanguageList() as $langcode => $names) { + $this->assertOption('edit-langcode', $langcode); + $this->assertRaw('>' . $names[1] . '<'); + } + + // Check that our custom one shows up with the file name indicated language. + $this->assertOption('edit-langcode', 'xoxo'); + $this->assertRaw('>xoxo<'); + + parent::setUpLanguage(); + } + + /** + * Confirms that the installation succeeded. + */ + public function testInstalled() { + $this->assertUrl('user/1'); + $this->assertResponse(200); + } + +} diff -r e200cb7efeb3 -r c2387f117808 core/tests/Drupal/FunctionalTests/Installer/InstallerSkipPermissionHardeningTest.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/core/tests/Drupal/FunctionalTests/Installer/InstallerSkipPermissionHardeningTest.php Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,41 @@ +settings['settings']['skip_permissions_hardening'] = (object) ['value' => TRUE, 'required' => TRUE]; + } + + /** + * {@inheritdoc} + */ + protected function setUpSite() { + $site_directory = $this->container->get('app.root') . '/' . $this->siteDirectory; + $this->assertTrue(is_writable($site_directory)); + $this->assertTrue(is_writable($site_directory . '/settings.php')); + + $this->assertSession()->responseContains('All necessary changes to ' . $this->siteDirectory . ' and ' . $this->siteDirectory . '/settings.php have been made, so you should remove write permissions to them now in order to avoid security risks. If you are unsure how to do so, consult the online handbook.'); + + parent::setUpSite(); + } + + /** + * Verifies the expected behaviors of the installation result. + */ + public function testInstalled() { + $this->assertSession()->addressEquals('user/1'); + $this->assertSession()->statusCodeEquals(200); + } + +} diff -r e200cb7efeb3 -r c2387f117808 core/tests/Drupal/FunctionalTests/Installer/InstallerTest.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/core/tests/Drupal/FunctionalTests/Installer/InstallerTest.php Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,95 @@ +assertUrl('user/1'); + $this->assertResponse(200); + // Confirm that we are logged-in after installation. + $this->assertText($this->rootUser->getUsername()); + + // Verify that the confirmation message appears. + require_once \Drupal::root() . '/core/includes/install.inc'; + $this->assertRaw(t('Congratulations, you installed @drupal!', [ + '@drupal' => drupal_install_profile_distribution_name(), + ])); + + // Ensure that the timezone is correct for sites under test after installing + // interactively. + $this->assertEqual($this->config('system.date')->get('timezone.default'), 'Australia/Sydney'); + } + + /** + * Installer step: Select language. + */ + protected function setUpLanguage() { + // Test that \Drupal\Core\Render\BareHtmlPageRenderer adds assets and + // metatags as expected to the first page of the installer. + $this->assertRaw("core/themes/seven/css/components/buttons.css"); + $this->assertRaw(''); + + // Assert that the expected title is present. + $this->assertEqual('Choose language', $this->cssSelect('main h2')[0]->getText()); + + parent::setUpLanguage(); + } + + /** + * {@inheritdoc} + */ + protected function setUpProfile() { + // Assert that the expected title is present. + $this->assertEqual('Select an installation profile', $this->cssSelect('main h2')[0]->getText()); + $result = $this->xpath('//span[contains(@class, :class) and contains(text(), :text)]', [':class' => 'visually-hidden', ':text' => 'Select an installation profile']); + $this->assertEqual(count($result), 1, "Title/Label not displayed when '#title_display' => 'invisible' attribute is set"); + + parent::setUpProfile(); + } + + /** + * {@inheritdoc} + */ + protected function setUpSettings() { + // Assert that the expected title is present. + $this->assertEqual('Database configuration', $this->cssSelect('main h2')[0]->getText()); + + parent::setUpSettings(); + } + + /** + * {@inheritdoc} + */ + protected function setUpSite() { + // Assert that the expected title is present. + $this->assertEqual('Configure site', $this->cssSelect('main h2')[0]->getText()); + + // Test that SiteConfigureForm::buildForm() has made the site directory and + // the settings file non-writable. + $site_directory = $this->container->get('app.root') . '/' . $this->siteDirectory; + $this->assertFalse(is_writable($site_directory)); + $this->assertFalse(is_writable($site_directory . '/settings.php')); + + parent::setUpSite(); + } + + /** + * {@inheritdoc} + */ + protected function visitInstaller() { + parent::visitInstaller(); + + // Assert the title is correct and has the title suffix. + $this->assertTitle('Choose language | Drupal'); + } + +} diff -r e200cb7efeb3 -r c2387f117808 core/tests/Drupal/FunctionalTests/Installer/InstallerTestBase.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/core/tests/Drupal/FunctionalTests/Installer/InstallerTestBase.php Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,316 @@ + 'Save and continue', + ]; + + /** + * Whether the installer has completed. + * + * @var bool + */ + protected $isInstalled = FALSE; + + /** + * {@inheritdoc} + */ + protected function setUp() { + $this->isInstalled = FALSE; + + $this->setupBaseUrl(); + + $this->prepareDatabasePrefix(); + + // Install Drupal test site. + $this->prepareEnvironment(); + + // Define information about the user 1 account. + $this->rootUser = new UserSession([ + 'uid' => 1, + 'name' => 'admin', + 'mail' => 'admin@example.com', + 'pass_raw' => $this->randomMachineName(), + ]); + + // If any $settings are defined for this test, copy and prepare an actual + // settings.php, so as to resemble a regular installation. + if (!empty($this->settings)) { + // Not using File API; a potential error must trigger a PHP warning. + copy(DRUPAL_ROOT . '/sites/default/default.settings.php', DRUPAL_ROOT . '/' . $this->siteDirectory . '/settings.php'); + $this->writeSettings($this->settings); + } + + // Note that FunctionalTestSetupTrait::installParameters() returns form + // input values suitable for a programmed + // \Drupal::formBuilder()->submitForm(). + // @see InstallerTestBase::translatePostValues() + $this->parameters = $this->installParameters(); + + // Set up a minimal container (required by BrowserTestBase). Set cookie and + // server information so that XDebug works. + // @see install_begin_request() + $request = Request::create($GLOBALS['base_url'] . '/core/install.php', 'GET', [], $_COOKIE, [], $_SERVER); + $this->container = new ContainerBuilder(); + $request_stack = new RequestStack(); + $request_stack->push($request); + $this->container + ->set('request_stack', $request_stack); + $this->container + ->setParameter('language.default_values', Language::$defaultValues); + $this->container + ->register('language.default', 'Drupal\Core\Language\LanguageDefault') + ->addArgument('%language.default_values%'); + $this->container + ->register('string_translation', 'Drupal\Core\StringTranslation\TranslationManager') + ->addArgument(new Reference('language.default')); + $this->container + ->register('http_client', 'GuzzleHttp\Client') + ->setFactory('http_client_factory:fromOptions'); + $this->container + ->register('http_client_factory', 'Drupal\Core\Http\ClientFactory') + ->setArguments([new Reference('http_handler_stack')]); + $handler_stack = HandlerStack::create(); + $test_http_client_middleware = new TestHttpClientMiddleware(); + $handler_stack->push($test_http_client_middleware(), 'test.http_client.middleware'); + $this->container + ->set('http_handler_stack', $handler_stack); + + $this->container + ->set('app.root', DRUPAL_ROOT); + \Drupal::setContainer($this->container); + + // Setup Mink. + $this->initMink(); + + $this->visitInstaller(); + + // Select language. + $this->setUpLanguage(); + + // Select profile. + $this->setUpProfile(); + + // Address the requirements problem screen, if any. + $this->setUpRequirementsProblem(); + + // Configure settings. + $this->setUpSettings(); + + // @todo Allow test classes based on this class to act on further installer + // screens. + + // Configure site. + $this->setUpSite(); + + if ($this->isInstalled) { + // Import new settings.php written by the installer. + $request = Request::createFromGlobals(); + $class_loader = require $this->container->get('app.root') . '/autoload.php'; + Settings::initialize($this->container->get('app.root'), DrupalKernel::findSitePath($request), $class_loader); + foreach ($GLOBALS['config_directories'] as $type => $path) { + $this->configDirectories[$type] = $path; + } + + // After writing settings.php, the installer removes write permissions + // from the site directory. To allow drupal_generate_test_ua() to write + // a file containing the private key for drupal_valid_test_ua(), the site + // directory has to be writable. + // BrowserTestBase::tearDown() will delete the entire test site directory. + // Not using File API; a potential error must trigger a PHP warning. + chmod($this->container->get('app.root') . '/' . $this->siteDirectory, 0777); + $this->kernel = DrupalKernel::createFromRequest($request, $class_loader, 'prod', FALSE); + $this->kernel->prepareLegacyRequest($request); + $this->container = $this->kernel->getContainer(); + + // Manually configure the test mail collector implementation to prevent + // tests from sending out emails and collect them in state instead. + $this->container->get('config.factory') + ->getEditable('system.mail') + ->set('interface.default', 'test_mail_collector') + ->save(); + } + } + + /** + * {@inheritdoc} + */ + protected function initFrontPage() { + // We don't want to visit the front page with the installer when + // initializing Mink, so we do nothing here. + } + + /** + * Visits the interactive installer. + */ + protected function visitInstaller() { + $this->drupalGet($GLOBALS['base_url'] . '/core/install.php'); + } + + /** + * Installer step: Select language. + */ + protected function setUpLanguage() { + $edit = [ + 'langcode' => $this->langcode, + ]; + $this->drupalPostForm(NULL, $edit, $this->translations['Save and continue']); + } + + /** + * Installer step: Select installation profile. + */ + protected function setUpProfile() { + $edit = [ + 'profile' => $this->profile, + ]; + $this->drupalPostForm(NULL, $edit, $this->translations['Save and continue']); + } + + /** + * Installer step: Configure settings. + */ + protected function setUpSettings() { + $edit = $this->translatePostValues($this->parameters['forms']['install_settings_form']); + $this->drupalPostForm(NULL, $edit, $this->translations['Save and continue']); + } + + /** + * Installer step: Requirements problem. + * + * Override this method to test specific requirements warnings or errors + * during the installer. + * + * @see system_requirements() + */ + protected function setUpRequirementsProblem() { + // By default, skip the "recommended PHP version" warning on older test + // environments. This allows the installer to be tested consistently on + // both recommended PHP versions and older (but still supported) versions. + if (version_compare(phpversion(), '7.0') < 0) { + $this->continueOnExpectedWarnings(['PHP']); + } + } + + /** + * Final installer step: Configure site. + */ + protected function setUpSite() { + $edit = $this->translatePostValues($this->parameters['forms']['install_configure_form']); + $this->drupalPostForm(NULL, $edit, $this->translations['Save and continue']); + // If we've got to this point the site is installed using the regular + // installation workflow. + $this->isInstalled = TRUE; + } + + /** + * {@inheritdoc} + * + * FunctionalTestSetupTrait::refreshVariables() tries to operate on persistent + * storage, which is only available after the installer completed. + */ + protected function refreshVariables() { + if ($this->isInstalled) { + parent::refreshVariables(); + } + } + + /** + * Continues installation when an expected warning is found. + * + * @param string[] $expected_warnings + * A list of warning summaries to expect on the requirements screen (e.g. + * 'PHP', 'PHP OPcode caching', etc.). If only the expected warnings + * are found, the test will click the "continue anyway" link to go to the + * next screen of the installer. If an expected warning is not found, or if + * a warning not in the list is present, a fail is raised. + */ + protected function continueOnExpectedWarnings($expected_warnings = []) { + // Don't try to continue if there are errors. + if (strpos($this->getTextContent(), 'Errors found') !== FALSE) { + return; + } + // Allow only details elements that are directly after the warning header + // or each other. There is no guaranteed wrapper we can rely on across + // distributions. When there are multiple warnings, the selectors will be: + // - h3#warning+details summary + // - h3#warning+details+details summary + // - etc. + // We add one more selector than expected warnings to confirm that there + // isn't any other warning before clicking the link. + // @todo Make this more reliable in + // https://www.drupal.org/project/drupal/issues/2927345. + $selectors = []; + for ($i = 0; $i <= count($expected_warnings); $i++) { + $selectors[] = 'h3#warning' . implode('', array_fill(0, $i + 1, '+details')) . ' summary'; + } + $warning_elements = $this->cssSelect(implode(', ', $selectors)); + + // Confirm that there are only the expected warnings. + $warnings = []; + foreach ($warning_elements as $warning) { + $warnings[] = trim($warning->getText()); + } + $this->assertEquals($expected_warnings, $warnings); + $this->clickLink('continue anyway'); + $this->checkForMetaRefresh(); + } + +} diff -r e200cb7efeb3 -r c2387f117808 core/tests/Drupal/FunctionalTests/Installer/InstallerTranslationMultipleLanguageForeignTest.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/core/tests/Drupal/FunctionalTests/Installer/InstallerTranslationMultipleLanguageForeignTest.php Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,27 @@ +translations['Save and continue'] = 'Save and continue de'; + } + +} diff -r e200cb7efeb3 -r c2387f117808 core/tests/Drupal/FunctionalTests/Installer/InstallerTranslationMultipleLanguageKeepEnglishTest.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/core/tests/Drupal/FunctionalTests/Installer/InstallerTranslationMultipleLanguageKeepEnglishTest.php Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,19 @@ +siteDirectory . '/files/translations', 0777, TRUE); + file_put_contents(DRUPAL_ROOT . '/' . $this->siteDirectory . '/files/translations/drupal-8.0.0.de.po', $this->getPo('de')); + file_put_contents(DRUPAL_ROOT . '/' . $this->siteDirectory . '/files/translations/drupal-8.0.0.es.po', $this->getPo('es')); + + parent::setUpLanguage(); + } + + /** + * Returns the string for the test .po file. + * + * @param string $langcode + * The language code. + * @return string + * Contents for the test .po file. + */ + protected function getPo($langcode) { + return <<langcode; + return $params; + } + + /** + * Tests that translations ended up at the expected places. + */ + public function testTranslationsLoaded() { + // Ensure the title is correct. + $this->assertEqual('SITE_NAME_' . $this->langcode, \Drupal::config('system.site')->get('name')); + + // Verify German and Spanish were configured. + $this->drupalGet('admin/config/regional/language'); + $this->assertText('German'); + $this->assertText('Spanish'); + // If the installer was English or we used a profile that keeps English, we + // expect that configured also. Otherwise English should not be configured + // on the site. + if ($this->langcode == 'en' || $this->profile == 'testing_multilingual_with_english') { + $this->assertText('English'); + } + else { + $this->assertNoText('English'); + } + + // Verify the strings from the translation files were imported. + $this->verifyImportedStringsTranslated(); + + /** @var \Drupal\language\ConfigurableLanguageManager $language_manager */ + $language_manager = \Drupal::languageManager(); + + // If the site was installed in a foreign language (only tested with German + // in subclasses), then the active configuration should be updated and no + // override should exist in German. Otherwise the German translation should + // end up in overrides the same way as Spanish (which is not used as a site + // installation language). English should be available based on profile + // information and should be possible to add if not yet added, making + // English overrides available. + + $config = \Drupal::config('user.settings'); + $override_de = $language_manager->getLanguageConfigOverride('de', 'user.settings'); + $override_en = $language_manager->getLanguageConfigOverride('en', 'user.settings'); + $override_es = $language_manager->getLanguageConfigOverride('es', 'user.settings'); + + if ($this->langcode == 'de') { + // Active configuration should be in German and no German override should + // exist. + $this->assertEqual($config->get('anonymous'), 'Anonymous de'); + $this->assertEqual($config->get('langcode'), 'de'); + $this->assertTrue($override_de->isNew()); + + if ($this->profile == 'testing_multilingual_with_english') { + // English is already added in this profile. Should make the override + // available. + $this->assertEqual($override_en->get('anonymous'), 'Anonymous'); + } + else { + // English is not yet available. + $this->assertTrue($override_en->isNew()); + + // Adding English should make the English override available. + $edit = ['predefined_langcode' => 'en']; + $this->drupalPostForm('admin/config/regional/language/add', $edit, t('Add language')); + $override_en = $language_manager->getLanguageConfigOverride('en', 'user.settings'); + $this->assertEqual($override_en->get('anonymous'), 'Anonymous'); + } + + // Activate a module, to make sure that config is not overridden by module + // installation. + $edit = [ + 'modules[views][enable]' => TRUE, + 'modules[filter][enable]' => TRUE, + ]; + $this->drupalPostForm('admin/modules', $edit, t('Install')); + + // Verify the strings from the translation are still as expected. + $this->verifyImportedStringsTranslated(); + } + else { + // Active configuration should be English. + $this->assertEqual($config->get('anonymous'), 'Anonymous'); + $this->assertEqual($config->get('langcode'), 'en'); + // There should not be an English override. + $this->assertTrue($override_en->isNew()); + // German should be an override. + $this->assertEqual($override_de->get('anonymous'), 'Anonymous de'); + } + + // Spanish is always an override (never used as installation language). + $this->assertEqual($override_es->get('anonymous'), 'Anonymous es'); + + } + + /** + * Helper function to verify that the expected strings are translated. + */ + protected function verifyImportedStringsTranslated() { + $test_samples = ['Save and continue', 'Anonymous', 'Language']; + $langcodes = ['de', 'es']; + + foreach ($test_samples as $sample) { + foreach ($langcodes as $langcode) { + $edit = []; + $edit['langcode'] = $langcode; + $edit['translation'] = 'translated'; + $edit['string'] = $sample; + $this->drupalPostForm('admin/config/regional/translate', $edit, t('Filter')); + $this->assertText($sample . ' ' . $langcode); + } + } + } + +} diff -r e200cb7efeb3 -r c2387f117808 core/tests/Drupal/FunctionalTests/Installer/InstallerTranslationQueryTest.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/core/tests/Drupal/FunctionalTests/Installer/InstallerTranslationQueryTest.php Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,83 @@ +siteDirectory . '/files/translations', 0777, TRUE); + file_put_contents(\Drupal::root() . '/' . $this->siteDirectory . '/files/translations/drupal-8.0.0.de.po', $this->getPo('de')); + + // The unrouted URL assembler does not exist at this point, so we build the + // URL ourselves. + $this->drupalGet($GLOBALS['base_url'] . '/core/install.php' . '?langcode=' . $this->langcode); + + // The language should have been automatically detected, all following + // screens should be translated already. + $elements = $this->xpath('//input[@type="submit"]/@value'); + $this->assertEqual(current($elements)->getText(), 'Save and continue de'); + $this->translations['Save and continue'] = 'Save and continue de'; + + // Check the language direction. + $direction = current($this->xpath('/@dir'))->getText(); + $this->assertEqual($direction, 'ltr'); + } + + /** + * {@inheritdoc} + */ + protected function setUpLanguage() { + // The language was was preset by passing a query parameter in the URL, so + // no explicit language selection is necessary. + } + + /** + * Verifies the expected behaviors of the installation result. + */ + public function testInstaller() { + $this->assertUrl('user/1'); + $this->assertResponse(200); + + // Verify German was configured but not English. + $this->drupalGet('admin/config/regional/language'); + $this->assertText('German'); + $this->assertNoText('English'); + } + + /** + * Returns the string for the test .po file. + * + * @param string $langcode + * The language code. + * @return string + * Contents for the test .po file. + */ + protected function getPo($langcode) { + return <<siteDirectory . '/files/translations', 0777, TRUE); + file_put_contents(\Drupal::root() . '/' . $this->siteDirectory . '/files/translations/drupal-8.0.0.de.po', $this->getPo('de')); + + parent::setUpLanguage(); + + // After selecting a different language than English, all following screens + // should be translated already. + $elements = $this->xpath('//input[@type="submit"]/@value'); + $this->assertEqual(current($elements)->getText(), 'Save and continue de'); + $this->translations['Save and continue'] = 'Save and continue de'; + + // Check the language direction. + $direction = current($this->xpath('/@dir'))->getText(); + $this->assertEqual($direction, 'ltr'); + } + + /** + * {@inheritdoc} + */ + protected function setUpSettings() { + // We are creating a table here to force an error in the installer because + // it will try and create the drupal_install_test table as this is part of + // the standard database tests performed by the installer in + // Drupal\Core\Database\Install\Tasks. + Database::getConnection('default')->query('CREATE TABLE {drupal_install_test} (id int NULL)'); + parent::setUpSettings(); + + // Ensure that the error message translation is working. + $this->assertRaw('Beheben Sie alle Probleme unten, um die Installation fortzusetzen. Informationen zur Konfiguration der Datenbankserver finden Sie in der Installationshandbuch, oder kontaktieren Sie Ihren Hosting-Anbieter.'); + $this->assertRaw('CREATE ein Test-Tabelle auf Ihrem Datenbankserver mit dem Befehl CREATE TABLE {drupal_install_test} (id int NULL) fehlgeschlagen.'); + + // Now do it successfully. + Database::getConnection('default')->query('DROP TABLE {drupal_install_test}'); + parent::setUpSettings(); + } + + /** + * Verifies the expected behaviors of the installation result. + */ + public function testInstaller() { + $this->assertUrl('user/1'); + $this->assertResponse(200); + + // Verify German was configured but not English. + $this->drupalGet('admin/config/regional/language'); + $this->assertText('German'); + $this->assertNoText('English'); + + // The current container still has the english as current language, rebuild. + $this->rebuildContainer(); + /** @var \Drupal\user\Entity\User $account */ + $account = User::load(0); + $this->assertEqual($account->language()->getId(), 'en', 'Anonymous user is English.'); + $account = User::load(1); + $this->assertEqual($account->language()->getId(), 'en', 'Administrator user is English.'); + $account = $this->drupalCreateUser(); + $this->assertEqual($account->language()->getId(), 'de', 'New user is German.'); + + // Ensure that we can enable basic_auth on a non-english site. + $this->drupalPostForm('admin/modules', ['modules[basic_auth][enable]' => TRUE], t('Install')); + $this->assertResponse(200); + + // Assert that the theme CSS was added to the page. + $edit = ['preprocess_css' => FALSE]; + $this->drupalPostForm('admin/config/development/performance', $edit, t('Save configuration')); + $this->drupalGet(''); + $this->assertRaw('classy/css/components/action-links.css'); + + // Verify the strings from the translation files were imported. + $test_samples = ['Save and continue', 'Anonymous']; + foreach ($test_samples as $sample) { + $edit = []; + $edit['langcode'] = 'de'; + $edit['translation'] = 'translated'; + $edit['string'] = $sample; + $this->drupalPostForm('admin/config/regional/translate', $edit, t('Filter')); + $this->assertText($sample . ' de'); + } + + /** @var \Drupal\language\ConfigurableLanguageManager $language_manager */ + $language_manager = \Drupal::languageManager(); + + // Installed in German, configuration should be in German. No German or + // English overrides should be present. + $config = \Drupal::config('user.settings'); + $override_de = $language_manager->getLanguageConfigOverride('de', 'user.settings'); + $override_en = $language_manager->getLanguageConfigOverride('en', 'user.settings'); + $this->assertEqual($config->get('anonymous'), 'Anonymous de'); + $this->assertEqual($config->get('langcode'), 'de'); + $this->assertTrue($override_de->isNew()); + $this->assertTrue($override_en->isNew()); + + // Assert that adding English makes the English override available. + $edit = ['predefined_langcode' => 'en']; + $this->drupalPostForm('admin/config/regional/language/add', $edit, t('Add language')); + $override_en = $language_manager->getLanguageConfigOverride('en', 'user.settings'); + $this->assertFalse($override_en->isNew()); + $this->assertEqual($override_en->get('anonymous'), 'Anonymous'); + } + + /** + * Returns the string for the test .po file. + * + * @param string $langcode + * The language code. + * @return string + * Contents for the test .po file. + */ + protected function getPo($langcode) { + return <<installation handbook, or contact your hosting provider." +msgstr "Beheben Sie alle Probleme unten, um die Installation fortzusetzen. Informationen zur Konfiguration der Datenbankserver finden Sie in der Installationshandbuch, oder kontaktieren Sie Ihren Hosting-Anbieter." + +msgid "Failed to CREATE a test table on your database server with the command %query. The server reports the following message: %error.

      Are you sure the configured username has the necessary permissions to create tables in the database?

      " +msgstr "CREATE ein Test-Tabelle auf Ihrem Datenbankserver mit dem Befehl %query fehlgeschlagen." +ENDPO; + } + +} diff -r e200cb7efeb3 -r c2387f117808 core/tests/Drupal/FunctionalTests/Installer/MinimalInstallerTest.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/core/tests/Drupal/FunctionalTests/Installer/MinimalInstallerTest.php Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,28 @@ +assertInstalledConfig([]); + } + +} diff -r e200cb7efeb3 -r c2387f117808 core/tests/Drupal/FunctionalTests/Installer/MultipleDistributionsProfileTest.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/core/tests/Drupal/FunctionalTests/Installer/MultipleDistributionsProfileTest.php Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,89 @@ + 'profile', + 'core' => \Drupal::CORE_COMPATIBILITY, + 'name' => $name . ' profile', + 'distribution' => [ + 'name' => $name, + 'install' => [ + 'theme' => 'bartik', + ], + ], + ]; + // File API functions are not available yet. + $path = $this->root . DIRECTORY_SEPARATOR . $this->siteDirectory . '/profiles/' . $name; + mkdir($path, 0777, TRUE); + file_put_contents("$path/$name.info.yml", Yaml::encode($info)); + } + // Install the first distribution. + $this->profile = 'distribution_one'; + } + + /** + * {@inheritdoc} + */ + protected function setUpLanguage() { + // Verify that the distribution name appears. + $this->assertRaw('distribution_one'); + // Verify that the requested theme is used. + $this->assertRaw('bartik'); + // Verify that the "Choose profile" step does not appear. + $this->assertNoText('profile'); + + parent::setUpLanguage(); + } + + /** + * {@inheritdoc} + */ + protected function setUpProfile() { + // This step is skipped, because there is a distribution profile. + } + + /** + * Confirms that the installation succeeded. + */ + public function testInstalled() { + $this->assertUrl('user/1'); + $this->assertResponse(200); + // Confirm that we are logged-in after installation. + $this->assertText($this->rootUser->getUsername()); + + // Confirm that Drupal recognizes this distribution as the current profile. + $this->assertEqual(\Drupal::installProfile(), 'distribution_one'); + $this->assertEqual(Settings::get('install_profile'), 'distribution_one', 'The install profile has been written to settings.php.'); + $this->assertEqual($this->config('core.extension')->get('profile'), 'distribution_one', 'The install profile has been written to core.extension configuration.'); + + $this->rebuildContainer(); + $this->pass('Container can be rebuilt as distribution is written to configuration.'); + $this->assertEqual(\Drupal::installProfile(), 'distribution_one'); + } + +} diff -r e200cb7efeb3 -r c2387f117808 core/tests/Drupal/FunctionalTests/Installer/SingleVisibleProfileTest.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/core/tests/Drupal/FunctionalTests/Installer/SingleVisibleProfileTest.php Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,62 @@ + 'profile', + 'core' => \Drupal::CORE_COMPATIBILITY, + 'name' => 'Override ' . $profile, + 'hidden' => TRUE, + ]; + // File API functions are not available yet. + $path = $this->siteDirectory . '/profiles/' . $profile; + mkdir($path, 0777, TRUE); + file_put_contents("$path/$profile.info.yml", Yaml::encode($info)); + } + } + + /** + * {@inheritdoc} + */ + protected function setUpProfile() { + // This step is skipped, because there is only one visible profile. + } + + /** + * Confirms that the installation succeeded. + */ + public function testInstalled() { + $this->assertUrl('user/1'); + $this->assertResponse(200); + // Confirm that we are logged-in after installation. + $this->assertText($this->rootUser->getUsername()); + // Confirm that the minimal profile was installed. + $this->assertEqual(drupal_get_profile(), 'minimal'); + } + +} diff -r e200cb7efeb3 -r c2387f117808 core/tests/Drupal/FunctionalTests/Installer/SiteNameTest.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/core/tests/Drupal/FunctionalTests/Installer/SiteNameTest.php Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,39 @@ +siteName = $this->randomMachineName(); + $parameters = parent::installParameters(); + $parameters['forms']['install_configure_form']['site_name'] = $this->siteName; + return $parameters; + } + + /** + * Tests that the desired site name appears on the page after installation. + */ + public function testSiteName() { + $this->drupalGet(''); + $this->assertRaw($this->siteName, 'The site name that was set during the installation appears on the front page after installation.'); + } + +} diff -r e200cb7efeb3 -r c2387f117808 core/tests/Drupal/FunctionalTests/Installer/StandardInstallerTest.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/core/tests/Drupal/FunctionalTests/Installer/StandardInstallerTest.php Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,68 @@ +assertRaw('No front page content has been created yet.'); + } + + /** + * {@inheritdoc} + */ + protected function setUpSite() { + // Test that the correct theme is being used. + $this->assertNoRaw('bartik'); + $this->assertRaw('themes/seven/css/theme/install-page.css'); + parent::setUpSite(); + } + + /** + * {@inheritdoc} + */ + protected function curlExec($curl_options, $redirect = FALSE) { + // Ensure that we see the classy progress CSS on the batch page. + // Batch processing happens as part of HTTP redirects, so we can access the + // HTML of the batch page. + if (strpos($curl_options[CURLOPT_URL], '&id=1&op=do_nojs') !== FALSE) { + $this->assertRaw('themes/classy/css/components/progress.css'); + } + return parent::curlExec($curl_options, $redirect); + } + + /** + * Ensures that the exported standard configuration is up to date. + */ + public function testStandardConfig() { + $skipped_config = []; + // FunctionalTestSetupTrait::installParameters() uses + // simpletest@example.com as mail address. + $skipped_config['contact.form.feedback'][] = '- simpletest@example.com'; + // \Drupal\filter\Entity\FilterFormat::toArray() drops the roles of filter + // formats. + $skipped_config['filter.format.basic_html'][] = 'roles:'; + $skipped_config['filter.format.basic_html'][] = '- authenticated'; + $skipped_config['filter.format.full_html'][] = 'roles:'; + $skipped_config['filter.format.full_html'][] = '- administrator'; + $skipped_config['filter.format.restricted_html'][] = 'roles:'; + $skipped_config['filter.format.restricted_html'][] = '- anonymous'; + + $this->assertInstalledConfig($skipped_config); + } + +} diff -r e200cb7efeb3 -r c2387f117808 core/tests/Drupal/FunctionalTests/Rest/BaseFieldOverrideJsonAnonTest.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/core/tests/Drupal/FunctionalTests/Rest/BaseFieldOverrideJsonAnonTest.php Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,24 @@ +grantPermissionsToTestedRole(['administer node fields']); + } + + /** + * {@inheritdoc} + */ + protected function createEntity() { + $camelids = NodeType::create([ + 'name' => 'Camelids', + 'type' => 'camelids', + ]); + $camelids->save(); + + $entity = BaseFieldOverride::create([ + 'field_name' => 'promote', + 'entity_type' => 'node', + 'bundle' => 'camelids', + ]); + $entity->save(); + + return $entity; + } + + /** + * {@inheritdoc} + */ + protected function getExpectedNormalizedEntity() { + return [ + 'bundle' => 'camelids', + 'default_value' => [], + 'default_value_callback' => '', + 'dependencies' => [ + 'config' => [ + 'node.type.camelids', + ], + ], + 'description' => '', + 'entity_type' => 'node', + 'field_name' => 'promote', + 'field_type' => 'boolean', + 'id' => 'node.camelids.promote', + 'label' => NULL, + 'langcode' => 'en', + 'required' => FALSE, + 'settings' => [ + 'on_label' => 'On', + 'off_label' => 'Off', + ], + 'status' => TRUE, + 'translatable' => TRUE, + 'uuid' => $this->entity->uuid(), + ]; + } + + /** + * {@inheritdoc} + */ + protected function getNormalizedPostEntity() { + // @todo Update in https://www.drupal.org/node/2300677. + } + + /** + * {@inheritdoc} + */ + protected function getExpectedCacheContexts() { + return [ + 'user.permissions', + ]; + } + + /** + * {@inheritdoc} + */ + protected function getExpectedUnauthorizedAccessMessage($method) { + if ($this->config('rest.settings')->get('bc_entity_resource_permissions')) { + return parent::getExpectedUnauthorizedAccessMessage($method); + } + + return "The 'administer node fields' permission is required."; + } + +} diff -r e200cb7efeb3 -r c2387f117808 core/tests/Drupal/FunctionalTests/Rest/BaseFieldOverrideXmlAnonTest.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/core/tests/Drupal/FunctionalTests/Rest/BaseFieldOverrideXmlAnonTest.php Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,26 @@ +grantPermissionsToTestedRole(['administer site configuration']); + } + + /** + * {@inheritdoc} + */ + protected function createEntity() { + // Create a date format. + $date_format = DateFormat::create([ + 'id' => 'llama', + 'label' => 'Llama', + 'pattern' => 'F d, Y', + ]); + + $date_format->save(); + + return $date_format; + } + + /** + * {@inheritdoc} + */ + protected function getExpectedNormalizedEntity() { + return [ + 'dependencies' => [], + 'id' => 'llama', + 'label' => 'Llama', + 'langcode' => 'en', + 'locked' => FALSE, + 'pattern' => 'F d, Y', + 'status' => TRUE, + 'uuid' => $this->entity->uuid(), + ]; + } + + /** + * {@inheritdoc} + */ + protected function getNormalizedPostEntity() { + // @todo Update in https://www.drupal.org/node/2300677. + } + +} diff -r e200cb7efeb3 -r c2387f117808 core/tests/Drupal/FunctionalTests/Rest/DateFormatXmlAnonTest.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/core/tests/Drupal/FunctionalTests/Rest/DateFormatXmlAnonTest.php Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,26 @@ +grantPermissionsToTestedRole(['administer node form display']); + } + + /** + * {@inheritdoc} + */ + protected function createEntity() { + // Create a "Camelids" node type. + $camelids = NodeType::create([ + 'name' => 'Camelids', + 'type' => 'camelids', + ]); + + $camelids->save(); + + // Create a form display. + $form_display = EntityFormDisplay::create([ + 'targetEntityType' => 'node', + 'bundle' => 'camelids', + 'mode' => 'default', + ]); + $form_display->save(); + + return $form_display; + } + + /** + * {@inheritdoc} + */ + protected function getExpectedNormalizedEntity() { + return [ + 'bundle' => 'camelids', + 'content' => [ + 'created' => [ + 'type' => 'datetime_timestamp', + 'weight' => 10, + 'region' => 'content', + 'settings' => [], + 'third_party_settings' => [], + ], + 'promote' => [ + 'type' => 'boolean_checkbox', + 'settings' => [ + 'display_label' => TRUE, + ], + 'weight' => 15, + 'region' => 'content', + 'third_party_settings' => [], + ], + 'status' => [ + 'type' => 'boolean_checkbox', + 'weight' => 120, + 'region' => 'content', + 'settings' => [ + 'display_label' => TRUE, + ], + 'third_party_settings' => [], + ], + 'sticky' => [ + 'type' => 'boolean_checkbox', + 'settings' => [ + 'display_label' => TRUE, + ], + 'weight' => 16, + 'region' => 'content', + 'third_party_settings' => [], + ], + 'title' => [ + 'type' => 'string_textfield', + 'weight' => -5, + 'region' => 'content', + 'settings' => [ + 'size' => 60, + 'placeholder' => '', + ], + 'third_party_settings' => [], + ], + 'uid' => [ + 'type' => 'entity_reference_autocomplete', + 'weight' => 5, + 'settings' => [ + 'match_operator' => 'CONTAINS', + 'size' => 60, + 'placeholder' => '', + ], + 'region' => 'content', + 'third_party_settings' => [], + ], + ], + 'dependencies' => [ + 'config' => [ + 'node.type.camelids', + ], + ], + 'hidden' => [], + 'id' => 'node.camelids.default', + 'langcode' => 'en', + 'mode' => 'default', + 'status' => NULL, + 'targetEntityType' => 'node', + 'uuid' => $this->entity->uuid(), + ]; + } + + /** + * {@inheritdoc} + */ + protected function getNormalizedPostEntity() { + // @todo Update in https://www.drupal.org/node/2300677. + } + + /** + * {@inheritdoc} + */ + protected function getExpectedCacheContexts() { + return [ + 'user.permissions', + ]; + } + + /** + * {@inheritdoc} + */ + protected function getExpectedUnauthorizedAccessMessage($method) { + if ($this->config('rest.settings')->get('bc_entity_resource_permissions')) { + return parent::getExpectedUnauthorizedAccessMessage($method); + } + + return "The 'administer node form display' permission is required."; + } + +} diff -r e200cb7efeb3 -r c2387f117808 core/tests/Drupal/FunctionalTests/Rest/EntityFormDisplayXmlAnonTest.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/core/tests/Drupal/FunctionalTests/Rest/EntityFormDisplayXmlAnonTest.php Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,26 @@ +grantPermissionsToTestedRole(['administer display modes']); + } + + /** + * {@inheritdoc} + */ + protected function createEntity() { + $entity_form_mode = EntityFormMode::create([ + 'id' => 'user.test', + 'label' => 'Test', + 'targetEntityType' => 'user', + ]); + $entity_form_mode->save(); + return $entity_form_mode; + } + + /** + * {@inheritdoc} + */ + protected function getExpectedNormalizedEntity() { + return [ + 'cache' => TRUE, + 'dependencies' => [ + 'module' => [ + 'user', + ], + ], + 'id' => 'user.test', + 'label' => 'Test', + 'langcode' => 'en', + 'status' => TRUE, + 'targetEntityType' => 'user', + 'uuid' => $this->entity->uuid(), + ]; + } + + /** + * {@inheritdoc} + */ + protected function getNormalizedPostEntity() { + // @todo Update in https://www.drupal.org/node/2300677. + } + +} diff -r e200cb7efeb3 -r c2387f117808 core/tests/Drupal/FunctionalTests/Rest/EntityFormModeXmlAnonTest.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/core/tests/Drupal/FunctionalTests/Rest/EntityFormModeXmlAnonTest.php Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,26 @@ +grantPermissionsToTestedRole(['administer node display']); + } + + /** + * {@inheritdoc} + */ + protected function createEntity() { + // Create a "Camelids" node type. + $camelids = NodeType::create([ + 'name' => 'Camelids', + 'type' => 'camelids', + ]); + $camelids->save(); + + // Create a view display. + $view_display = EntityViewDisplay::create([ + 'targetEntityType' => 'node', + 'bundle' => 'camelids', + 'mode' => 'default', + 'status' => TRUE, + ]); + $view_display->save(); + + return $view_display; + } + + /** + * {@inheritdoc} + */ + protected function getExpectedNormalizedEntity() { + return [ + 'bundle' => 'camelids', + 'content' => [ + 'links' => [ + 'region' => 'content', + 'weight' => 100, + ], + ], + 'dependencies' => [ + 'config' => [ + 'node.type.camelids', + ], + 'module' => [ + 'user', + ], + ], + 'hidden' => [], + 'id' => 'node.camelids.default', + 'langcode' => 'en', + 'mode' => 'default', + 'status' => TRUE, + 'targetEntityType' => 'node', + 'uuid' => $this->entity->uuid(), + ]; + } + + /** + * {@inheritdoc} + */ + protected function getNormalizedPostEntity() { + // @todo Update in https://www.drupal.org/node/2300677. + } + + /** + * {@inheritdoc} + */ + protected function getExpectedCacheContexts() { + return [ + 'user.permissions', + ]; + } + + /** + * {@inheritdoc} + */ + protected function getExpectedUnauthorizedAccessMessage($method) { + if ($this->config('rest.settings')->get('bc_entity_resource_permissions')) { + return parent::getExpectedUnauthorizedAccessMessage($method); + } + + return "The 'administer node display' permission is required."; + } + +} diff -r e200cb7efeb3 -r c2387f117808 core/tests/Drupal/FunctionalTests/Rest/EntityViewDisplayXmlAnonTest.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/core/tests/Drupal/FunctionalTests/Rest/EntityViewDisplayXmlAnonTest.php Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,26 @@ +grantPermissionsToTestedRole(['administer display modes']); + } + + /** + * {@inheritdoc} + */ + protected function createEntity() { + $entity_view_mode = EntityViewMode::create([ + 'id' => 'user.test', + 'label' => 'Test', + 'targetEntityType' => 'user', + ]); + $entity_view_mode->save(); + return $entity_view_mode; + } + + /** + * {@inheritdoc} + */ + protected function getExpectedNormalizedEntity() { + return [ + 'cache' => TRUE, + 'dependencies' => [ + 'module' => [ + 'user', + ], + ], + 'id' => 'user.test', + 'label' => 'Test', + 'langcode' => 'en', + 'status' => TRUE, + 'targetEntityType' => 'user', + 'uuid' => $this->entity->uuid(), + ]; + } + + /** + * {@inheritdoc} + */ + protected function getNormalizedPostEntity() { + // @todo Update in https://www.drupal.org/node/2300677. + } + +} diff -r e200cb7efeb3 -r c2387f117808 core/tests/Drupal/FunctionalTests/Rest/EntityViewModeXmlAnonTest.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/core/tests/Drupal/FunctionalTests/Rest/EntityViewModeXmlAnonTest.php Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,26 @@ +drupalGet('/default_format_test/human'); + $this->assertSame('format:html', $this->getSession()->getPage()->getContent()); + $this->assertSame('MISS', $this->drupalGetHeader('X-Drupal-Cache')); + + $this->drupalGet('/default_format_test/machine'); + $this->assertSame('format:json', $this->getSession()->getPage()->getContent()); + $this->assertSame('MISS', $this->drupalGetHeader('X-Drupal-Cache')); + } + + public function testMultipleRoutesWithSameSingleFormat() { + $this->drupalGet('/default_format_test/machine'); + $this->assertSame('format:json', $this->getSession()->getPage()->getContent()); + } + +} diff -r e200cb7efeb3 -r c2387f117808 core/tests/Drupal/FunctionalTests/Update/UpdatePathTestBase.php --- a/core/tests/Drupal/FunctionalTests/Update/UpdatePathTestBase.php Thu Apr 26 11:26:54 2018 +0100 +++ b/core/tests/Drupal/FunctionalTests/Update/UpdatePathTestBase.php Tue Jul 10 15:07:59 2018 +0100 @@ -375,10 +375,10 @@ // Ensure that the update hooks updated all entity schema. $needs_updates = \Drupal::entityDefinitionUpdateManager()->needsUpdates(); if ($needs_updates) { - foreach (\Drupal::entityDefinitionUpdateManager() - ->getChangeSummary() as $entity_type_id => $summary) { + foreach (\Drupal::entityDefinitionUpdateManager()->getChangeSummary() as $entity_type_id => $summary) { + $entity_type_label = \Drupal::entityTypeManager()->getDefinition($entity_type_id)->getLabel(); foreach ($summary as $message) { - $this->fail($message); + $this->fail("$entity_type_label: $message"); } } // The above calls to `fail()` should prevent this from ever being diff -r e200cb7efeb3 -r c2387f117808 core/tests/Drupal/KernelTests/Config/TypedConfigTest.php --- a/core/tests/Drupal/KernelTests/Config/TypedConfigTest.php Thu Apr 26 11:26:54 2018 +0100 +++ b/core/tests/Drupal/KernelTests/Config/TypedConfigTest.php Tue Jul 10 15:07:59 2018 +0100 @@ -155,11 +155,12 @@ $value = $typed_config->getValue(); unset($value['giraffe']); $value['elephant'] = 'foo'; + $value['zebra'] = 'foo'; $typed_config->setValue($value); $result = $typed_config->validate(); $this->assertCount(1, $result); $this->assertEquals('', $result->get(0)->getPropertyPath()); - $this->assertEquals('Missing giraffe.', $result->get(0)->getMessage()); + $this->assertEquals('Unexpected keys: elephant, zebra', $result->get(0)->getMessage()); } } diff -r e200cb7efeb3 -r c2387f117808 core/tests/Drupal/KernelTests/ConfigFormTestBase.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/core/tests/Drupal/KernelTests/ConfigFormTestBase.php Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,66 @@ + array( + * '#value' => $this->randomString(), + * '#config_name' => 'user.mail', + * '#config_key' => 'cancel_confirm.body', + * ), + * ); + * @endcode + * + * @var array + */ + protected $values; + + /** + * Submit the system_config_form ensure the configuration has expected values. + */ + public function testConfigForm() { + // Programmatically submit the given values. + $values = []; + foreach ($this->values as $form_key => $data) { + $values[$form_key] = $data['#value']; + } + $form_state = (new FormState())->setValues($values); + \Drupal::formBuilder()->submitForm($this->form, $form_state); + + // Check that the form returns an error when expected, and vice versa. + $errors = $form_state->getErrors(); + $valid_form = empty($errors); + $args = [ + '%values' => print_r($values, TRUE), + '%errors' => $valid_form ? t('None') : implode(' ', $errors), + ]; + $this->assertTrue($valid_form, format_string('Input values: %values
      Validation handler errors: %errors', $args)); + + foreach ($this->values as $data) { + $this->assertEqual($data['#value'], $this->config($data['#config_name'])->get($data['#config_key'])); + } + } + +} diff -r e200cb7efeb3 -r c2387f117808 core/tests/Drupal/KernelTests/Core/Database/BasicSyntaxTest.php --- a/core/tests/Drupal/KernelTests/Core/Database/BasicSyntaxTest.php Thu Apr 26 11:26:54 2018 +0100 +++ b/core/tests/Drupal/KernelTests/Core/Database/BasicSyntaxTest.php Tue Jul 10 15:07:59 2018 +0100 @@ -28,15 +28,22 @@ /** * Tests string concatenation with field values. + * + * We use 'job' and 'age' fields from the {test} table. Using the 'name' field + * for concatenation causes issues with custom or contrib database drivers, + * since its type 'varchar_ascii' may lead to using field-level collations not + * compatible with the other fields. */ public function testConcatFields() { - $result = db_query('SELECT CONCAT(:a1, CONCAT(name, CONCAT(:a2, CONCAT(age, :a3)))) FROM {test} WHERE age = :age', [ - ':a1' => 'The age of ', - ':a2' => ' is ', - ':a3' => '.', - ':age' => 25, - ]); - $this->assertIdentical($result->fetchField(), 'The age of John is 25.', 'Field CONCAT works.'); + $result = $this->connection->query( + 'SELECT CONCAT(:a1, CONCAT(job, CONCAT(:a2, CONCAT(age, :a3)))) FROM {test} WHERE age = :age', [ + ':a1' => 'The age of ', + ':a2' => ' is ', + ':a3' => '.', + ':age' => 25, + ] + ); + $this->assertSame('The age of Singer is 25.', $result->fetchField(), 'Field CONCAT works.'); } /** diff -r e200cb7efeb3 -r c2387f117808 core/tests/Drupal/KernelTests/Core/Database/ConnectionUnitTest.php --- a/core/tests/Drupal/KernelTests/Core/Database/ConnectionUnitTest.php Thu Apr 26 11:26:54 2018 +0100 +++ b/core/tests/Drupal/KernelTests/Core/Database/ConnectionUnitTest.php Tue Jul 10 15:07:59 2018 +0100 @@ -63,7 +63,7 @@ * * @return int */ - protected function getConnectionID() { + protected function getConnectionId() { return (int) Database::getConnection($this->target, $this->key)->query('SELECT CONNECTION_ID()')->fetchField(); } @@ -92,7 +92,7 @@ /** * Tests Database::closeConnection() without query. * - * @todo getConnectionID() executes a query. + * @todo getConnectionId() executes a query. */ public function testOpenClose() { if ($this->skipTest) { @@ -100,7 +100,7 @@ } // Add and open a new connection. $this->addConnection(); - $id = $this->getConnectionID(); + $id = $this->getConnectionId(); Database::getConnection($this->target, $this->key); // Verify that there is a new connection. @@ -124,7 +124,7 @@ } // Add and open a new connection. $this->addConnection(); - $id = $this->getConnectionID(); + $id = $this->getConnectionId(); Database::getConnection($this->target, $this->key); // Verify that there is a new connection. @@ -151,7 +151,7 @@ } // Add and open a new connection. $this->addConnection(); - $id = $this->getConnectionID(); + $id = $this->getConnectionId(); Database::getConnection($this->target, $this->key); // Verify that there is a new connection. @@ -178,7 +178,7 @@ } // Add and open a new connection. $this->addConnection(); - $id = $this->getConnectionID(); + $id = $this->getConnectionId(); Database::getConnection($this->target, $this->key); // Verify that there is a new connection. diff -r e200cb7efeb3 -r c2387f117808 core/tests/Drupal/KernelTests/Core/Database/DatabaseTestBase.php --- a/core/tests/Drupal/KernelTests/Core/Database/DatabaseTestBase.php Thu Apr 26 11:26:54 2018 +0100 +++ b/core/tests/Drupal/KernelTests/Core/Database/DatabaseTestBase.php Tue Jul 10 15:07:59 2018 +0100 @@ -2,6 +2,7 @@ namespace Drupal\KernelTests\Core\Database; +use Drupal\Core\Database\Database; use Drupal\KernelTests\KernelTestBase; /** @@ -14,8 +15,16 @@ public static $modules = ['database_test']; + /** + * The database connection for testing. + * + * @var \Drupal\Core\Database\Connection + */ + protected $connection; + protected function setUp() { parent::setUp(); + $this->connection = Database::getConnection(); $this->installSchema('database_test', [ 'test', 'test_people', @@ -35,7 +44,7 @@ * Sets up tables for NULL handling. */ public function ensureSampleDataNull() { - db_insert('test_null') + $this->connection->insert('test_null') ->fields(['name', 'age']) ->values([ 'name' => 'Kermit', @@ -56,8 +65,10 @@ * Sets up our sample data. */ public static function addSampleData() { + $connection = Database::getConnection(); + // We need the IDs, so we can't use a multi-insert here. - $john = db_insert('test') + $john = $connection->insert('test') ->fields([ 'name' => 'John', 'age' => 25, @@ -65,7 +76,7 @@ ]) ->execute(); - $george = db_insert('test') + $george = $connection->insert('test') ->fields([ 'name' => 'George', 'age' => 27, @@ -73,7 +84,7 @@ ]) ->execute(); - db_insert('test') + $connection->insert('test') ->fields([ 'name' => 'Ringo', 'age' => 28, @@ -81,7 +92,7 @@ ]) ->execute(); - $paul = db_insert('test') + $paul = $connection->insert('test') ->fields([ 'name' => 'Paul', 'age' => 26, @@ -89,7 +100,7 @@ ]) ->execute(); - db_insert('test_people') + $connection->insert('test_people') ->fields([ 'name' => 'Meredith', 'age' => 30, @@ -97,7 +108,7 @@ ]) ->execute(); - db_insert('test_task') + $connection->insert('test_task') ->fields(['pid', 'task', 'priority']) ->values([ 'pid' => $john, @@ -136,7 +147,7 @@ ]) ->execute(); - db_insert('test_special_columns') + $connection->insert('test_special_columns') ->fields([ 'id' => 1, 'offset' => 'Offset value 1', diff -r e200cb7efeb3 -r c2387f117808 core/tests/Drupal/KernelTests/Core/Database/DeleteTruncateTest.php --- a/core/tests/Drupal/KernelTests/Core/Database/DeleteTruncateTest.php Thu Apr 26 11:26:54 2018 +0100 +++ b/core/tests/Drupal/KernelTests/Core/Database/DeleteTruncateTest.php Tue Jul 10 15:07:59 2018 +0100 @@ -67,6 +67,84 @@ } /** + * Confirms that we can truncate a whole table while in transaction. + */ + public function testTruncateInTransaction() { + // This test won't work right if transactions are not supported. + if (!$this->connection->supportsTransactions()) { + $this->markTestSkipped('The database driver does not support transactions.'); + } + + $num_records_before = $this->connection->select('test')->countQuery()->execute()->fetchField(); + $this->assertGreaterThan(0, $num_records_before, 'The table is not empty.'); + + $transaction = $this->connection->startTransaction('test_truncate_in_transaction'); + $this->connection->insert('test') + ->fields([ + 'name' => 'Freddie', + 'age' => 45, + 'job' => 'Great singer', + ]) + ->execute(); + $num_records_after_insert = $this->connection->select('test')->countQuery()->execute()->fetchField(); + $this->assertEquals($num_records_before + 1, $num_records_after_insert); + + $this->connection->truncate('test')->execute(); + + // Checks that there are no records left in the table, and transaction is + // still active. + $this->assertTrue($this->connection->inTransaction()); + $num_records_after = $this->connection->select('test')->countQuery()->execute()->fetchField(); + $this->assertEquals(0, $num_records_after); + + // Close the transaction, and check that there are still no records in the + // table. + $transaction = NULL; + $this->assertFalse($this->connection->inTransaction()); + $num_records_after = $this->connection->select('test')->countQuery()->execute()->fetchField(); + $this->assertEquals(0, $num_records_after); + } + + /** + * Confirms that transaction rollback voids a truncate operation. + */ + public function testTruncateTransactionRollback() { + // This test won't work right if transactions are not supported. + if (!$this->connection->supportsTransactions()) { + $this->markTestSkipped('The database driver does not support transactions.'); + } + + $num_records_before = $this->connection->select('test')->countQuery()->execute()->fetchField(); + $this->assertGreaterThan(0, $num_records_before, 'The table is not empty.'); + + $transaction = $this->connection->startTransaction('test_truncate_in_transaction'); + $this->connection->insert('test') + ->fields([ + 'name' => 'Freddie', + 'age' => 45, + 'job' => 'Great singer', + ]) + ->execute(); + $num_records_after_insert = $this->connection->select('test')->countQuery()->execute()->fetchField(); + $this->assertEquals($num_records_before + 1, $num_records_after_insert); + + $this->connection->truncate('test')->execute(); + + // Checks that there are no records left in the table, and transaction is + // still active. + $this->assertTrue($this->connection->inTransaction()); + $num_records_after = $this->connection->select('test')->countQuery()->execute()->fetchField(); + $this->assertEquals(0, $num_records_after); + + // Roll back the transaction, and check that we are back to status before + // insert and truncate. + $this->connection->rollBack(); + $this->assertFalse($this->connection->inTransaction()); + $num_records_after = $this->connection->select('test')->countQuery()->execute()->fetchField(); + $this->assertEquals($num_records_before, $num_records_after); + } + + /** * Confirms that we can delete a single special column name record successfully. */ public function testSpecialColumnDelete() { diff -r e200cb7efeb3 -r c2387f117808 core/tests/Drupal/KernelTests/Core/Database/SchemaTest.php --- a/core/tests/Drupal/KernelTests/Core/Database/SchemaTest.php Thu Apr 26 11:26:54 2018 +0100 +++ b/core/tests/Drupal/KernelTests/Core/Database/SchemaTest.php Tue Jul 10 15:07:59 2018 +0100 @@ -528,6 +528,11 @@ ['not null' => TRUE, 'initial' => 1], ['not null' => TRUE, 'initial' => 1, 'default' => 7], ['not null' => TRUE, 'initial_from_field' => 'serial_column'], + [ + 'not null' => TRUE, + 'initial_from_field' => 'test_nullable_field', + 'initial' => 100, + ], ]; foreach ($variations as $variation) { @@ -581,6 +586,7 @@ $table_spec = [ 'fields' => [ 'serial_column' => ['type' => 'serial', 'unsigned' => TRUE, 'not null' => TRUE], + 'test_nullable_field' => ['type' => 'int', 'not null' => FALSE], 'test_field' => $field_spec, ], 'primary key' => ['serial_column'], @@ -599,6 +605,7 @@ $table_spec = [ 'fields' => [ 'serial_column' => ['type' => 'serial', 'unsigned' => TRUE, 'not null' => TRUE], + 'test_nullable_field' => ['type' => 'int', 'not null' => FALSE], ], 'primary key' => ['serial_column'], ]; @@ -609,9 +616,15 @@ for ($i = 0; $i < 3; $i++) { db_insert($table_name) ->useDefaults(['serial_column']) + ->fields(['test_nullable_field' => 100]) ->execute(); } + // Add another row with no value for the 'test_nullable_field' column. + db_insert($table_name) + ->useDefaults(['serial_column']) + ->execute(); + db_add_field($table_name, 'test_field', $field_spec); $this->pass(format_string('Column %column created.', ['%column' => 'test_field'])); @@ -645,7 +658,7 @@ } // Check that the initial value from another field has been registered. - if (isset($field_spec['initial_from_field'])) { + if (isset($field_spec['initial_from_field']) && !isset($field_spec['initial'])) { // There should be no row with a value different than // $field_spec['initial_from_field']. $count = db_select($table_name) @@ -656,6 +669,16 @@ ->fetchField(); $this->assertEqual($count, 0, 'Initial values from another field filled out.'); } + elseif (isset($field_spec['initial_from_field']) && isset($field_spec['initial'])) { + // There should be no row with a value different than '100'. + $count = db_select($table_name) + ->fields($table_name, ['serial_column']) + ->condition($field_name, 100, '<>') + ->countQuery() + ->execute() + ->fetchField(); + $this->assertEqual($count, 0, 'Initial values from another field or a default value filled out.'); + } // Check that the default value has been registered. if (isset($field_spec['default'])) { diff -r e200cb7efeb3 -r c2387f117808 core/tests/Drupal/KernelTests/Core/Entity/ContentEntityCloneTest.php --- a/core/tests/Drupal/KernelTests/Core/Entity/ContentEntityCloneTest.php Thu Apr 26 11:26:54 2018 +0100 +++ b/core/tests/Drupal/KernelTests/Core/Entity/ContentEntityCloneTest.php Tue Jul 10 15:07:59 2018 +0100 @@ -297,7 +297,7 @@ // Retrieve the entity properties. $reflection = new \ReflectionClass($entity); $properties = $reflection->getProperties(~\ReflectionProperty::IS_STATIC); - $translation_unique_properties = ['activeLangcode', 'translationInitialize', 'fieldDefinitions', 'languages', 'langcodeKey', 'defaultLangcode', 'defaultLangcodeKey', 'revisionTranslationAffectedKey', 'validated', 'validationRequired', 'entityTypeId', 'typedData', 'cacheContexts', 'cacheTags', 'cacheMaxAge', '_serviceIds']; + $translation_unique_properties = ['activeLangcode', 'translationInitialize', 'fieldDefinitions', 'languages', 'langcodeKey', 'defaultLangcode', 'defaultLangcodeKey', 'revisionTranslationAffectedKey', 'validated', 'validationRequired', 'entityTypeId', 'typedData', 'cacheContexts', 'cacheTags', 'cacheMaxAge', '_serviceIds', '_entityStorages']; foreach ($properties as $property) { // Modify each entity property on the clone and assert that the change is diff -r e200cb7efeb3 -r c2387f117808 core/tests/Drupal/KernelTests/Core/Entity/DefaultTableMappingIntegrationTest.php --- a/core/tests/Drupal/KernelTests/Core/Entity/DefaultTableMappingIntegrationTest.php Thu Apr 26 11:26:54 2018 +0100 +++ b/core/tests/Drupal/KernelTests/Core/Entity/DefaultTableMappingIntegrationTest.php Tue Jul 10 15:07:59 2018 +0100 @@ -19,7 +19,7 @@ /** * The table mapping for the tested entity type. * - * @var \Drupal\Core\Entity\Sql\TableMappingInterface + * @var \Drupal\Core\Entity\Sql\DefaultTableMapping */ protected $tableMapping; @@ -39,11 +39,18 @@ ->setName('multivalued_base_field') ->setTargetEntityTypeId('entity_test_mulrev') ->setTargetBundle('entity_test_mulrev') - ->setCardinality(FieldStorageDefinitionInterface::CARDINALITY_UNLIMITED); + ->setCardinality(FieldStorageDefinitionInterface::CARDINALITY_UNLIMITED) + // Base fields are non-translatable and non-revisionable by default, but + // we explicitly set these values here for extra clarity. + ->setTranslatable(FALSE) + ->setRevisionable(FALSE); $this->state->set('entity_test_mulrev.additional_base_field_definitions', $definitions); $this->entityManager->clearCachedDefinitions(); $this->tableMapping = $this->entityManager->getStorage('entity_test_mulrev')->getTableMapping(); + + // Ensure that the tables for the new field are created. + \Drupal::entityDefinitionUpdateManager()->applyUpdates(); } /** @@ -68,4 +75,33 @@ $this->assertEquals($this->tableMapping->getFieldTableName('multivalued_base_field'), $expected); } + /** + * Tests DefaultTableMapping::getTableNames(). + * + * @covers ::getTableNames + */ + public function testGetTableNames() { + $storage_definitions = $this->entityManager->getFieldStorageDefinitions('entity_test_mulrev'); + $dedicated_data_table = $this->tableMapping->getDedicatedDataTableName($storage_definitions['multivalued_base_field']); + $dedicated_revision_table = $this->tableMapping->getDedicatedRevisionTableName($storage_definitions['multivalued_base_field']); + + // Check that both the data and the revision tables exist for a multi-valued + // base field. + $database_schema = \Drupal::database()->schema(); + $this->assertTrue($database_schema->tableExists($dedicated_data_table)); + $this->assertTrue($database_schema->tableExists($dedicated_revision_table)); + + // Check that the table mapping contains both the data and the revision + // tables exist for a multi-valued base field. + $expected = [ + 'entity_test_mulrev', + 'entity_test_mulrev_property_data', + 'entity_test_mulrev_revision', + 'entity_test_mulrev_property_revision', + $dedicated_data_table, + $dedicated_revision_table, + ]; + $this->assertEquals($expected, $this->tableMapping->getTableNames()); + } + } diff -r e200cb7efeb3 -r c2387f117808 core/tests/Drupal/KernelTests/Core/Entity/EntityDefinitionUpdateTest.php --- a/core/tests/Drupal/KernelTests/Core/Entity/EntityDefinitionUpdateTest.php Thu Apr 26 11:26:54 2018 +0100 +++ b/core/tests/Drupal/KernelTests/Core/Entity/EntityDefinitionUpdateTest.php Tue Jul 10 15:07:59 2018 +0100 @@ -1049,31 +1049,78 @@ /** * Tests adding a base field with initial values inherited from another field. + * + * @dataProvider initialValueFromFieldTestCases */ - public function testInitialValueFromField() { + public function testInitialValueFromField($default_initial_value, $expected_value) { $storage = \Drupal::entityTypeManager()->getStorage('entity_test_update'); $db_schema = $this->database->schema(); // Create two entities before adding the base field. - /** @var \Drupal\entity_test\Entity\EntityTestUpdate $entity */ - $storage->create(['name' => 'First entity'])->save(); - $storage->create(['name' => 'Second entity'])->save(); + /** @var \Drupal\entity_test_update\Entity\EntityTestUpdate $entity */ + $storage->create([ + 'name' => 'First entity', + 'test_single_property' => 'test existing value', + ])->save(); + + // The second entity does not have any value for the 'test_single_property' + // field, allowing us to test the 'default_value' parameter of + // \Drupal\Core\Field\BaseFieldDefinition::setInitialValueFromField(). + $storage->create([ + 'name' => 'Second entity' + ])->save(); // Add a base field with an initial value inherited from another field. - $this->addBaseField(); - $storage_definition = BaseFieldDefinition::create('string') - ->setLabel(t('A new base field')) + $definitions['new_base_field'] = BaseFieldDefinition::create('string') + ->setName('new_base_field') + ->setLabel('A new base field') ->setInitialValueFromField('name'); + $definitions['another_base_field'] = BaseFieldDefinition::create('string') + ->setName('another_base_field') + ->setLabel('Another base field') + ->setInitialValueFromField('test_single_property', $default_initial_value); + + $this->state->set('entity_test_update.additional_base_field_definitions', $definitions); $this->assertFalse($db_schema->fieldExists('entity_test_update', 'new_base_field'), "New field 'new_base_field' does not exist before applying the update."); - $this->entityDefinitionUpdateManager->installFieldStorageDefinition('new_base_field', 'entity_test_update', 'entity_test', $storage_definition); + $this->assertFalse($db_schema->fieldExists('entity_test_update', 'another_base_field'), "New field 'another_base_field' does not exist before applying the update."); + $this->entityDefinitionUpdateManager->installFieldStorageDefinition('new_base_field', 'entity_test_update', 'entity_test', $definitions['new_base_field']); + $this->entityDefinitionUpdateManager->installFieldStorageDefinition('another_base_field', 'entity_test_update', 'entity_test', $definitions['another_base_field']); $this->assertTrue($db_schema->fieldExists('entity_test_update', 'new_base_field'), "New field 'new_base_field' has been created on the 'entity_test_update' table."); + $this->assertTrue($db_schema->fieldExists('entity_test_update', 'another_base_field'), "New field 'another_base_field' has been created on the 'entity_test_update' table."); // Check that the initial values have been applied. $storage = \Drupal::entityTypeManager()->getStorage('entity_test_update'); $entities = $storage->loadMultiple(); $this->assertEquals('First entity', $entities[1]->get('new_base_field')->value); $this->assertEquals('Second entity', $entities[2]->get('new_base_field')->value); + + $this->assertEquals('test existing value', $entities[1]->get('another_base_field')->value); + $this->assertEquals($expected_value, $entities[2]->get('another_base_field')->value); + } + + /** + * Test cases for ::testInitialValueFromField. + */ + public function initialValueFromFieldTestCases() { + return [ + 'literal value' => [ + 'test initial value', + 'test initial value', + ], + 'indexed array' => [ + ['value' => 'test initial value'], + 'test initial value', + ], + 'empty array' => [ + [], + NULL, + ], + 'null' => [ + NULL, + NULL, + ], + ]; } /** diff -r e200cb7efeb3 -r c2387f117808 core/tests/Drupal/KernelTests/Core/Entity/EntityFieldTest.php --- a/core/tests/Drupal/KernelTests/Core/Entity/EntityFieldTest.php Thu Apr 26 11:26:54 2018 +0100 +++ b/core/tests/Drupal/KernelTests/Core/Entity/EntityFieldTest.php Tue Jul 10 15:07:59 2018 +0100 @@ -16,6 +16,7 @@ use Drupal\Core\TypedData\ListInterface; use Drupal\Core\TypedData\Type\StringInterface; use Drupal\Core\TypedData\TypedDataInterface; +use Drupal\entity_test\Entity\EntityTest; use Drupal\entity_test\Entity\EntityTestComputedField; use Drupal\node\Entity\Node; use Drupal\node\Entity\NodeType; @@ -871,6 +872,32 @@ } /** + * Tests an entity reference computed field. + */ + public function testEntityReferenceComputedField() { + $this->installEntitySchema('entity_test_computed_field'); + + // Create 2 entities to be referenced. + $ref1 = EntityTest::create(['name' => 'foo', 'type' => 'bar']); + $ref1->save(); + $ref2 = EntityTest::create(['name' => 'baz', 'type' => 'bar']); + $ref2->save(); + \Drupal::state()->set('entity_test_reference_computed_target_ids', [$ref1->id(), $ref2->id()]); + + $entity = EntityTestComputedField::create([]); + $entity->save(); + + /** @var \Drupal\entity_test\Plugin\Field\ComputedReferenceTestFieldItemList $field */ + $field = $entity->get('computed_reference_field'); + /** @var \Drupal\Core\Entity\EntityInterface[] $referenced_entities */ + $referenced_entities = $field->referencedEntities(); + + // Check that ::referencedEntities() is working with computed fields. + $this->assertEquals($ref1->id(), $referenced_entities[0]->id()); + $this->assertEquals($ref2->id(), $referenced_entities[1]->id()); + } + + /** * Executes the computed properties tests for the given entity type. * * @param string $entity_type diff -r e200cb7efeb3 -r c2387f117808 core/tests/Drupal/KernelTests/Core/Entity/EntityKeysTest.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/core/tests/Drupal/KernelTests/Core/Entity/EntityKeysTest.php Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,56 @@ +state->set('entity_test.additional_base_field_definitions', [ + 'test_field' => BaseFieldDefinition::create('string')->setTranslatable($translatable), + ]); + $this->state->set('entity_test.entity_keys', [ + 'key_1' => 'test_field', + 'key_2' => 'test_field', + ]); + drupal_flush_all_caches(); + $this->installEntitySchema('entity_test'); + + $entity = EntityTest::create([]); + + $entity->set('test_field', 'foo'); + $this->assertEquals('foo', $entity->getEntityKey('key_1')); + $this->assertEquals('foo', $entity->getEntityKey('key_2')); + + $entity->set('test_field', 'bar'); + $this->assertEquals('bar', $entity->getEntityKey('key_1')); + $this->assertEquals('bar', $entity->getEntityKey('key_2')); + } + + /** + * Data provider for ::testMultipleKeysCache. + */ + public function multipleKeysCacheTestCases() { + return [ + 'translatable Entity Key' => [ + TRUE, + ], + 'Non-translatable entity key' => [ + FALSE, + ], + ]; + } + +} diff -r e200cb7efeb3 -r c2387f117808 core/tests/Drupal/KernelTests/Core/Entity/EntityQueryTest.php --- a/core/tests/Drupal/KernelTests/Core/Entity/EntityQueryTest.php Thu Apr 26 11:26:54 2018 +0100 +++ b/core/tests/Drupal/KernelTests/Core/Entity/EntityQueryTest.php Tue Jul 10 15:07:59 2018 +0100 @@ -526,7 +526,7 @@ ->sort('id') ->execute(); - $this->assertResult(6, 14); + $this->assertResult(4, 6, 12, 14); } /** diff -r e200cb7efeb3 -r c2387f117808 core/tests/Drupal/KernelTests/Core/Entity/Sql/SqlContentEntityStorageSchemaTest.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/core/tests/Drupal/KernelTests/Core/Entity/Sql/SqlContentEntityStorageSchemaTest.php Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,130 @@ +container->get('keyvalue'); + $this->installedStorageSchema = $key_value_factory->get('entity.storage_schema.sql'); + $this->entityDefinitionUpdateManager = $this->container->get('entity.definition_update_manager'); + } + + /** + * Tests updating a shared table field definition. + */ + public function testOnFieldStorageDefinitionUpdateShared() { + // Install the test entity type with an additional field. Use a multi-column + // field so that field name and column name(s) do not match. + $field = BaseFieldDefinition::create('shape') + // Avoid creating a foreign key which is irrelevant for this test. + ->setSetting('foreign_key_name', NULL) + ->setName('shape') + ->setProvider('entity_test'); + $this->state->set('entity_test.additional_base_field_definitions', [ + 'shape' => $field, + ]); + $this->entityDefinitionUpdateManager->installFieldStorageDefinition( + 'shape', + 'entity_test', + 'entity_test', + $field + ); + + // Make sure the field is not marked as NOT NULL initially. + $expected = [ + 'entity_test' => [ + 'fields' => [ + 'shape__shape' => [ + 'type' => 'varchar', + 'length' => 32, + 'not null' => FALSE, + ], + 'shape__color' => [ + 'type' => 'varchar', + 'length' => 32, + 'not null' => FALSE, + ], + ], + ], + ]; + $actual = $this->installedStorageSchema->get('entity_test.field_schema_data.shape'); + $this->assertSame($expected, $actual); + + // Make the field an entity key, so that it will get marked as NOT NULL. + $entity_type = $this->entityDefinitionUpdateManager->getEntityType('entity_test'); + $original_keys = $entity_type->getKeys(); + $entity_type->set('entity_keys', $original_keys + ['shape' => 'shape']); + $this->entityDefinitionUpdateManager->updateEntityType($entity_type); + + // Update the field and make sure the schema got updated. + $this->entityDefinitionUpdateManager->updateFieldStorageDefinition($field); + $expected['entity_test']['fields']['shape__shape']['not null'] = TRUE; + $expected['entity_test']['fields']['shape__color']['not null'] = TRUE; + $actual = $this->installedStorageSchema->get('entity_test.field_schema_data.shape'); + $this->assertSame($expected, $actual); + + // Remove the entity key again and check that the schema got reverted. + $entity_type->set('entity_keys', $original_keys); + $this->entityDefinitionUpdateManager->updateEntityType($entity_type); + + $this->entityDefinitionUpdateManager->updateFieldStorageDefinition($field); + $expected['entity_test']['fields']['shape__shape']['not null'] = FALSE; + $expected['entity_test']['fields']['shape__color']['not null'] = FALSE; + $actual = $this->installedStorageSchema->get('entity_test.field_schema_data.shape'); + $this->assertSame($expected, $actual); + + // Now add an entity and repeat the process. + $entity_storage = $this->entityManager->getStorage('entity_test'); + $entity_storage->create([ + 'shape' => [ + 'shape' => 'rectangle', + 'color' => 'pink', + ], + ])->save(); + + $entity_type->set('entity_keys', $original_keys + ['shape' => 'shape']); + $this->entityDefinitionUpdateManager->updateEntityType($entity_type); + + $this->entityDefinitionUpdateManager->updateFieldStorageDefinition($field); + $expected['entity_test']['fields']['shape__shape']['not null'] = TRUE; + $expected['entity_test']['fields']['shape__color']['not null'] = TRUE; + $actual = $this->installedStorageSchema->get('entity_test.field_schema_data.shape'); + $this->assertSame($expected, $actual); + + $entity_type->set('entity_keys', $original_keys); + $this->entityDefinitionUpdateManager->updateEntityType($entity_type); + $this->entityDefinitionUpdateManager->updateFieldStorageDefinition($field); + $expected['entity_test']['fields']['shape__shape']['not null'] = FALSE; + $expected['entity_test']['fields']['shape__color']['not null'] = FALSE; + $actual = $this->installedStorageSchema->get('entity_test.field_schema_data.shape'); + $this->assertSame($expected, $actual); + } + +} diff -r e200cb7efeb3 -r c2387f117808 core/tests/Drupal/KernelTests/Core/File/UrlTransformRelativeTest.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/core/tests/Drupal/KernelTests/Core/File/UrlTransformRelativeTest.php Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,83 @@ +push($request); + + $this->assertSame($expected, file_url_transform_relative($url)); + } + + public function providerFileUrlTransformRelative() { + $data = []; + $data[] = [ + 'example.com', + 80, + '', + 'http://example.com/page', + '/page', + ]; + $data[] = [ + 'example.com', + 443, + 'on', + 'https://example.com/page', + '/page', + ]; + $data[] = [ + 'example.com', + 8080, + '', + 'https://example.com:8080/page', + '/page', + ]; + $data[] = [ + 'example.com', + 8443, + 'on', + 'https://example.com:8443/page', + '/page', + ]; + $data[] = [ + 'example.com', + 80, + '', + 'http://exampleXcom/page', + 'http://exampleXcom/page', + ]; + return $data; + } + +} diff -r e200cb7efeb3 -r c2387f117808 core/tests/Drupal/KernelTests/Core/Plugin/ContextDefinitionTest.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/core/tests/Drupal/KernelTests/Core/Plugin/ContextDefinitionTest.php Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,37 @@ +installEntitySchema('user'); + + $value = EntityTest::create([]); + // Assert that the entity has at least one violation. + $this->assertNotEmpty($value->validate()); + // Assert that these violations do not prevent it from satisfying the + // requirements of another object. + $requirement = new ContextDefinition('any'); + $context = new Context(new ContextDefinition('entity:entity_test'), $value); + $this->assertTrue($requirement->isSatisfiedBy($context)); + } + +} diff -r e200cb7efeb3 -r c2387f117808 core/tests/Drupal/KernelTests/Core/Render/Element/WeightTest.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/core/tests/Drupal/KernelTests/Core/Render/Element/WeightTest.php Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,52 @@ +installConfig(['system']); + } + + /** + * Test existing #default_value value in #options list. + * + * @covers ::processWeight + */ + public function testProcessWeight() { + $element = []; + $form_state = new FormState(); + $complete_form = []; + + $element_object = new Weight([], 'weight', []); + $info = $element_object->getInfo(); + $element += $info; + + $element['#default_value'] = $element['#delta'] + 5; + + Weight::processWeight($element, $form_state, $complete_form); + + $this->assertTrue( + isset($element['#options'][$element['#default_value']]), + 'Default value exists in the #options list' + ); + } + +} diff -r e200cb7efeb3 -r c2387f117808 core/tests/Drupal/KernelTests/Core/TempStore/AnonymousPrivateTempStoreTest.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/core/tests/Drupal/KernelTests/Core/TempStore/AnonymousPrivateTempStoreTest.php Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,60 @@ +installSchema('system', ['key_value_expire']); + + $session = $this->container->get('session'); + $request = Request::create('/'); + $request->setSession($session); + + $stack = $this->container->get('request_stack'); + $stack->pop(); + $stack->push($request); + + } + + /** + * Tests anonymous can use the PrivateTempStore. + */ + public function testAnonymousCanUsePrivateTempStore() { + $temp_store = $this->container->get('tempstore.private')->get('anonymous_private_temp_store'); + $temp_store->set('foo', 'bar'); + $metadata1 = $temp_store->getMetadata('foo'); + + $this->assertEquals('bar', $temp_store->get('foo')); + $this->assertNotEmpty($metadata1->owner); + + $temp_store->set('foo', 'bar2'); + $metadata2 = $temp_store->getMetadata('foo'); + $this->assertEquals('bar2', $temp_store->get('foo')); + $this->assertNotEmpty($metadata2->owner); + $this->assertEquals($metadata2->owner, $metadata1->owner); + } + +} diff -r e200cb7efeb3 -r c2387f117808 core/tests/Drupal/KernelTests/KernelTestBase.php --- a/core/tests/Drupal/KernelTests/KernelTestBase.php Thu Apr 26 11:26:54 2018 +0100 +++ b/core/tests/Drupal/KernelTests/KernelTestBase.php Tue Jul 10 15:07:59 2018 +0100 @@ -1027,7 +1027,7 @@ * Test authors should follow the provided instructions and adjust their tests * accordingly. * - * @deprecated in Drupal 8.0.x, will be removed before Drupal 8.2.0. + * @deprecated in Drupal 8.0.0, will be removed before Drupal 9.0.0. */ public function __get($name) { if (in_array($name, [ diff -r e200cb7efeb3 -r c2387f117808 core/tests/Drupal/Tests/BrowserTestBase.php --- a/core/tests/Drupal/Tests/BrowserTestBase.php Thu Apr 26 11:26:54 2018 +0100 +++ b/core/tests/Drupal/Tests/BrowserTestBase.php Tue Jul 10 15:07:59 2018 +0100 @@ -321,18 +321,27 @@ $this->mink->setDefaultSessionName('default'); $this->registerSessions(); - // According to the W3C WebDriver specification a cookie can only be set if - // the cookie domain is equal to the domain of the active document. When the - // browser starts up the active document is not our domain but 'about:blank' - // or similar. To be able to set our User-Agent and Xdebug cookies at the - // start of the test we now do a request to the front page so the active - // document matches the domain. - // @see https://w3c.github.io/webdriver/webdriver-spec.html#add-cookie - // @see https://www.w3.org/Bugs/Public/show_bug.cgi?id=20975 + $this->initFrontPage(); + + return $session; + } + + /** + * Visits the front page when initializing Mink. + * + * According to the W3C WebDriver specification a cookie can only be set if + * the cookie domain is equal to the domain of the active document. When the + * browser starts up the active document is not our domain but 'about:blank' + * or similar. To be able to set our User-Agent and Xdebug cookies at the + * start of the test we now do a request to the front page so the active + * document matches the domain. + * + * @see https://w3c.github.io/webdriver/webdriver-spec.html#add-cookie + * @see https://www.w3.org/Bugs/Public/show_bug.cgi?id=20975 + */ + protected function initFrontPage() { $session = $this->getSession(); $session->visit($this->baseUrl); - - return $session; } /** @@ -584,6 +593,33 @@ } /** + * Obtain the HTTP client for the system under test. + * + * Use this method for arbitrary HTTP requests to the site under test. For + * most tests, you should not get the HTTP client and instead use navigation + * methods such as drupalGet() and clickLink() in order to benefit from + * assertions. + * + * Subclasses which substitute a different Mink driver should override this + * method and provide a Guzzle client if the Mink driver provides one. + * + * @return \GuzzleHttp\ClientInterface + * The client with BrowserTestBase configuration. + * + * @throws \RuntimeException + * If the Mink driver does not support a Guzzle HTTP client, throw an + * exception. + */ + protected function getHttpClient() { + /* @var $mink_driver \Behat\Mink\Driver\DriverInterface */ + $mink_driver = $this->getSession()->getDriver(); + if ($mink_driver instanceof GoutteDriver) { + return $mink_driver->getClient()->getClient(); + } + throw new \RuntimeException('The Mink client type ' . get_class($mink_driver) . ' does not support getHttpClient().'); + } + + /** * Returns WebAssert object. * * @param string $name @@ -593,6 +629,7 @@ * A new web-assert option for asserting the presence of elements with. */ public function assertSession($name = NULL) { + $this->addToAssertionCount(1); return new WebAssert($this->getSession($name), $this->baseUrl); } @@ -662,11 +699,13 @@ * to set for example the "Accept-Language" header for requesting the page * in a different language. Note that not all headers are supported, for * example the "Accept" header is always overridden by the browser. For - * testing REST APIs it is recommended to directly use an HTTP client such - * as Guzzle instead. + * testing REST APIs it is recommended to obtain a separate HTTP client + * using getHttpClient() and performing requests that way. * * @return string * The retrieved HTML string, also available as $this->getRawContent() + * + * @see \Drupal\Tests\BrowserTestBase::getHttpClient() */ protected function drupalGet($path, array $options = [], array $headers = []) { $options['absolute'] = TRUE; @@ -1167,6 +1206,7 @@ protected function clickLink($label, $index = 0) { $label = (string) $label; $links = $this->getSession()->getPage()->findAll('named', ['link', $label]); + $this->assertArrayHasKey($index, $links, 'The link ' . $label . ' was not found on the page.'); $links[$index]->click(); } @@ -1308,6 +1348,28 @@ } /** + * Transforms a nested array into a flat array suitable for drupalPostForm(). + * + * @param array $values + * A multi-dimensional form values array to convert. + * + * @return array + * The flattened $edit array suitable for BrowserTestBase::drupalPostForm(). + */ + protected function translatePostValues(array $values) { + $edit = []; + // The easiest and most straightforward way to translate values suitable for + // BrowserTestBase::drupalPostForm() is to actually build the POST data + // string and convert the resulting key/value pairs back into a flat array. + $query = http_build_query($values); + foreach (explode('&', $query) as $item) { + list($key, $value) = explode('=', $item); + $edit[urldecode($key)] = urldecode($value); + } + return $edit; + } + + /** * Checks for meta refresh tag and if found call drupalGet() recursively. * * This function looks for the http-equiv attribute to be set to "Refresh" and diff -r e200cb7efeb3 -r c2387f117808 core/tests/Drupal/Tests/Core/Access/AccessResultTest.php --- a/core/tests/Drupal/Tests/Core/Access/AccessResultTest.php Thu Apr 26 11:26:54 2018 +0100 +++ b/core/tests/Drupal/Tests/Core/Access/AccessResultTest.php Tue Jul 10 15:07:59 2018 +0100 @@ -269,8 +269,12 @@ */ public function testOrIf() { $neutral = AccessResult::neutral('neutral message'); + $neutral_other = AccessResult::neutral('other neutral message'); + $neutral_reasonless = AccessResult::neutral(); $allowed = AccessResult::allowed(); $forbidden = AccessResult::forbidden('forbidden message'); + $forbidden_other = AccessResult::forbidden('other forbidden message'); + $forbidden_reasonless = AccessResult::forbidden(); $unused_access_result_due_to_lazy_evaluation = $this->getMock('\Drupal\Core\Access\AccessResultInterface'); $unused_access_result_due_to_lazy_evaluation->expects($this->never()) ->method($this->anything()); @@ -304,6 +308,18 @@ $this->assertTrue($access->isNeutral()); $this->assertEquals('neutral message', $access->getReason()); $this->assertDefaultCacheability($access); + // Reason inheritance edge case: first reason is kept. + $access = $neutral->orIf($neutral_other); + $this->assertEquals('neutral message', $access->getReason()); + $access = $neutral_other->orIf($neutral); + $this->assertEquals('other neutral message', $access->getReason()); + // Reason inheritance edge case: one of the operands is reasonless. + $access = $neutral->orIf($neutral_reasonless); + $this->assertEquals('neutral message', $access->getReason()); + $access = $neutral_reasonless->orIf($neutral); + $this->assertEquals('neutral message', $access->getReason()); + $access = $neutral_reasonless->orIf($neutral_reasonless); + $this->assertNull($access->getReason()); // NEUTRAL || ALLOWED === ALLOWED. $access = $neutral->orIf($allowed); @@ -329,7 +345,7 @@ $this->assertDefaultCacheability($access); // FORBIDDEN || NEUTRAL === FORBIDDEN. - $access = $forbidden->orIf($allowed); + $access = $forbidden->orIf($neutral); $this->assertFalse($access->isAllowed()); $this->assertTrue($access->isForbidden()); $this->assertFalse($access->isNeutral()); @@ -337,12 +353,24 @@ $this->assertDefaultCacheability($access); // FORBIDDEN || FORBIDDEN === FORBIDDEN. - $access = $forbidden->orIf($allowed); + $access = $forbidden->orIf($forbidden); $this->assertFalse($access->isAllowed()); $this->assertTrue($access->isForbidden()); $this->assertFalse($access->isNeutral()); $this->assertEquals('forbidden message', $access->getReason()); $this->assertDefaultCacheability($access); + // Reason inheritance edge case: first reason is kept. + $access = $forbidden->orIf($forbidden_other); + $this->assertEquals('forbidden message', $access->getReason()); + $access = $forbidden_other->orIf($forbidden); + $this->assertEquals('other forbidden message', $access->getReason()); + // Reason inheritance edge case: one of the operands is reasonless. + $access = $forbidden->orIf($forbidden_reasonless); + $this->assertEquals('forbidden message', $access->getReason()); + $access = $forbidden_reasonless->orIf($forbidden); + $this->assertEquals('forbidden message', $access->getReason()); + $access = $forbidden_reasonless->orIf($forbidden_reasonless); + $this->assertNull($access->getReason()); // FORBIDDEN || * === FORBIDDEN. $access = $forbidden->orIf($unused_access_result_due_to_lazy_evaluation); diff -r e200cb7efeb3 -r c2387f117808 core/tests/Drupal/Tests/Core/Entity/EntityUrlTest.php --- a/core/tests/Drupal/Tests/Core/Entity/EntityUrlTest.php Thu Apr 26 11:26:54 2018 +0100 +++ b/core/tests/Drupal/Tests/Core/Entity/EntityUrlTest.php Tue Jul 10 15:07:59 2018 +0100 @@ -2,14 +2,18 @@ namespace Drupal\Tests\Core\Entity; +use Drupal\Core\DependencyInjection\ContainerBuilder; use Drupal\Core\Entity\Entity; use Drupal\Core\Entity\EntityMalformedException; use Drupal\Core\Entity\EntityTypeBundleInfoInterface; use Drupal\Core\Entity\EntityTypeInterface; use Drupal\Core\Entity\Exception\UndefinedLinkTemplateException; use Drupal\Core\Entity\RevisionableInterface; +use Drupal\Core\GeneratedUrl; +use Drupal\Core\Routing\UrlGeneratorInterface; use Drupal\Core\Url; use Drupal\Tests\UnitTestCase; +use Symfony\Component\Routing\Exception\MissingMandatoryParametersException; /** * Tests URL handling of the \Drupal\Core\Entity\Entity class. @@ -497,6 +501,38 @@ } /** + * Tests the uriRelationships() method. + * + * @covers ::uriRelationships + */ + public function testUriRelationships() { + $entity = $this->getEntity(Entity::class, ['id' => $this->entityId]); + + $container_builder = new ContainerBuilder(); + $url_generator = $this->createMock(UrlGeneratorInterface::class); + $container_builder->set('url_generator', $url_generator); + \Drupal::setContainer($container_builder); + + // Test route with no mandatory parameters. + $this->registerLinkTemplate('canonical'); + $route_name_0 = 'entity.' . $this->entityTypeId . '.canonical'; + $url_generator->expects($this->at(0)) + ->method('generateFromRoute') + ->with($route_name_0) + ->willReturn((new GeneratedUrl())->setGeneratedUrl('/entity_test')); + $this->assertEquals(['canonical'], $entity->uriRelationships()); + + // Test route with non-default mandatory parameters. + $this->registerLinkTemplate('{non_default_parameter}'); + $route_name_1 = 'entity.' . $this->entityTypeId . '.{non_default_parameter}'; + $url_generator->expects($this->at(0)) + ->method('generateFromRoute') + ->with($route_name_1) + ->willThrowException(new MissingMandatoryParametersException()); + $this->assertEquals([], $entity->uriRelationships()); + } + + /** * Returns a mock entity for testing. * * @param string $class diff -r e200cb7efeb3 -r c2387f117808 core/tests/Drupal/Tests/Core/EventSubscriber/ActiveLinkResponseFilterTest.php --- a/core/tests/Drupal/Tests/Core/EventSubscriber/ActiveLinkResponseFilterTest.php Thu Apr 26 11:26:54 2018 +0100 +++ b/core/tests/Drupal/Tests/Core/EventSubscriber/ActiveLinkResponseFilterTest.php Tue Jul 10 15:07:59 2018 +0100 @@ -238,6 +238,19 @@ $situations[] = ['context' => $context, 'is active' => FALSE, 'attributes' => $attributes + ['hreflang' => 'en', 'data-drupal-link-query' => ""]]; $situations[] = ['context' => $context, 'is active' => FALSE, 'attributes' => $attributes + ['hreflang' => 'en', 'data-drupal-link-query' => TRUE]]; + // Query with unsorted keys must match when the attribute is in sorted form. + $context = [ + 'path' => 'myfrontpage', + 'front' => TRUE, + 'language' => 'en', + 'query' => ['foo' => 'bar', 'baz' => 'qux'], + ]; + $attributes = [ + 'data-drupal-link-system-path' => 'myfrontpage', + 'data-drupal-link-query' => Json::encode(['baz' => 'qux', 'foo' => 'bar']), + ]; + $situations[] = ['context' => $context, 'is active' => TRUE, 'attributes' => $attributes]; + // Loop over the surrounding HTML variations. $data = []; for ($h = 0; $h < count($html); $h++) { diff -r e200cb7efeb3 -r c2387f117808 core/tests/Drupal/Tests/Core/Plugin/Context/ContextDefinitionIsSatisfiedTest.php --- a/core/tests/Drupal/Tests/Core/Plugin/Context/ContextDefinitionIsSatisfiedTest.php Thu Apr 26 11:26:54 2018 +0100 +++ b/core/tests/Drupal/Tests/Core/Plugin/Context/ContextDefinitionIsSatisfiedTest.php Tue Jul 10 15:07:59 2018 +0100 @@ -17,6 +17,7 @@ use Drupal\Core\Plugin\Context\ContextDefinition; use Drupal\Core\TypedData\TypedDataManager; use Drupal\Core\Validation\ConstraintManager; +use Drupal\Tests\Core\Plugin\Fixtures\InheritedContextDefinition; use Drupal\Tests\UnitTestCase; use Prophecy\Argument; @@ -196,6 +197,13 @@ new ContextDefinition('entity:test_config'), ]; + // Inherited context definition class. + $data['both any, inherited context requirement definition'] = [ + TRUE, + new InheritedContextDefinition('any'), + new ContextDefinition('any'), + ]; + return $data; } diff -r e200cb7efeb3 -r c2387f117808 core/tests/Drupal/Tests/Core/Plugin/Fixtures/InheritedContextDefinition.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/core/tests/Drupal/Tests/Core/Plugin/Fixtures/InheritedContextDefinition.php Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,12 @@ + 'foo'], 'foo', ]; + // Basic #markup based renderable array with value '0'. + $data[] = [ + ['#markup' => '0'], + '0', + ]; + // Basic #markup based renderable array with value 0. + $data[] = [ + ['#markup' => 0], + '0', + ]; + // Basic #markup based renderable array with value ''. + $data[] = [ + ['#markup' => ''], + '', + ]; + // Basic #markup based renderable array with value NULL. + $data[] = [ + ['#markup' => NULL], + '', + ]; // Basic #plain_text based renderable array. $data[] = [ ['#plain_text' => 'foo'], @@ -104,6 +124,26 @@ ['#plain_text' => Markup::create('foo')], '<em>foo</em>', ]; + // #plain_text based renderable array with value '0'. + $data[] = [ + ['#plain_text' => '0'], + '0', + ]; + // #plain_text based renderable array with value 0. + $data[] = [ + ['#plain_text' => 0], + '0', + ]; + // #plain_text based renderable array with value ''. + $data[] = [ + ['#plain_text' => ''], + '', + ]; + // #plain_text based renderable array with value NULL. + $data[] = [ + ['#plain_text' => NULL], + '', + ]; // Renderable child element. $data[] = [ ['child' => ['#markup' => 'bar']], diff -r e200cb7efeb3 -r c2387f117808 core/tests/Drupal/Tests/Core/Routing/ContentTypeHeaderMatcherTest.php --- a/core/tests/Drupal/Tests/Core/Routing/ContentTypeHeaderMatcherTest.php Thu Apr 26 11:26:54 2018 +0100 +++ b/core/tests/Drupal/Tests/Core/Routing/ContentTypeHeaderMatcherTest.php Tue Jul 10 15:07:59 2018 +0100 @@ -61,6 +61,7 @@ ['HEAD'], ['OPTIONS'], ['TRACE'], + ['DELETE'], ]; } diff -r e200cb7efeb3 -r c2387f117808 core/tests/Drupal/Tests/Core/StackMiddleware/NegotiationMiddlewareTest.php --- a/core/tests/Drupal/Tests/Core/StackMiddleware/NegotiationMiddlewareTest.php Thu Apr 26 11:26:54 2018 +0100 +++ b/core/tests/Drupal/Tests/Core/StackMiddleware/NegotiationMiddlewareTest.php Tue Jul 10 15:07:59 2018 +0100 @@ -68,10 +68,10 @@ * * @covers ::getContentType */ - public function testUnknowContentTypeReturnsHtmlByDefault() { + public function testUnknowContentTypeReturnsNull() { $request = new Request(); - $this->assertSame('html', $this->contentNegotiation->getContentType($request)); + $this->assertNull($this->contentNegotiation->getContentType($request)); } /** @@ -83,7 +83,7 @@ $request = new Request(); $request->headers->set('X-Requested-With', 'XMLHttpRequest'); - $this->assertSame('html', $this->contentNegotiation->getContentType($request)); + $this->assertNull($this->contentNegotiation->getContentType($request)); } /** @@ -98,7 +98,7 @@ $request->setFormat()->shouldNotBeCalled(); // Request format will be set with default format. - $request->setRequestFormat('html')->shouldBeCalled(); + $request->setRequestFormat()->shouldNotBeCalled(); // Some getContentType calls we don't really care about but have to mock. $request_data = $this->prophesize(ParameterBag::class); @@ -127,7 +127,7 @@ $request->setFormat('david', 'geeky/david')->shouldBeCalled(); // Some calls we don't care about. - $request->setRequestFormat('html')->shouldBeCalled(); + $request->setRequestFormat()->shouldNotBeCalled(); $request_data = $this->prophesize(ParameterBag::class); $request_data->get('ajax_iframe_upload', FALSE)->shouldBeCalled(); $request_mock = $request->reveal(); diff -r e200cb7efeb3 -r c2387f117808 core/tests/Drupal/Tests/Core/Template/Loader/ThemeRegistryLoaderTest.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/core/tests/Drupal/Tests/Core/Template/Loader/ThemeRegistryLoaderTest.php Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,29 @@ +prophesize('Drupal\Core\Theme\Registry'); + $runtime = $this->prophesize('Drupal\Core\Utility\ThemeRegistry'); + $runtime->has('foo') + ->shouldBeCalled() + ->willReturn(FALSE); + $registry->getRuntime()->willReturn($runtime); + + $loader = new ThemeRegistryLoader($registry->reveal()); + $this->assertFalse($loader->exists('foo')); + } + +} diff -r e200cb7efeb3 -r c2387f117808 core/tests/Drupal/Tests/Core/Test/BrowserTestBaseTest.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/core/tests/Drupal/Tests/Core/Test/BrowserTestBaseTest.php Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,82 @@ +getMockBuilder(Session::class) + ->disableOriginalConstructor() + ->setMethods(['getDriver']) + ->getMock(); + $session->expects($this->once()) + ->method('getDriver') + ->willReturn($driver); + + $btb = $this->getMockBuilder(BrowserTestBase::class) + ->disableOriginalConstructor() + ->setMethods(['getSession']) + ->getMockForAbstractClass(); + $btb->expects($this->once()) + ->method('getSession') + ->willReturn($session); + + return $btb; + } + + /** + * @covers ::getHttpClient + */ + public function testGetHttpClient() { + // Our stand-in for the Guzzle client object. + $expected = new \stdClass(); + + $browserkit_client = $this->getMockBuilder(Client::class) + ->setMethods(['getClient']) + ->getMockForAbstractClass(); + $browserkit_client->expects($this->once()) + ->method('getClient') + ->willReturn($expected); + + // Because the driver is a GoutteDriver, we'll get back a client. + $driver = $this->getMockBuilder(GoutteDriver::class) + ->setMethods(['getClient']) + ->getMock(); + $driver->expects($this->once()) + ->method('getClient') + ->willReturn($browserkit_client); + + $btb = $this->mockBrowserTestBaseWithDriver($driver); + + $ref_gethttpclient = new \ReflectionMethod($btb, 'getHttpClient'); + $ref_gethttpclient->setAccessible(TRUE); + + $this->assertSame(get_class($expected), get_class($ref_gethttpclient->invoke($btb))); + } + + /** + * @covers ::getHttpClient + */ + public function testGetHttpClientException() { + // A driver type that isn't GoutteDriver. This should cause a + // RuntimeException. + $btb = $this->mockBrowserTestBaseWithDriver(new \stdClass()); + + $ref_gethttpclient = new \ReflectionMethod($btb, 'getHttpClient'); + $ref_gethttpclient->setAccessible(TRUE); + + $this->setExpectedException(\RuntimeException::class, 'The Mink client type stdClass does not support getHttpClient().'); + $ref_gethttpclient->invoke($btb); + } + +} diff -r e200cb7efeb3 -r c2387f117808 core/tests/Drupal/Tests/Core/Utility/UnroutedUrlAssemblerTest.php --- a/core/tests/Drupal/Tests/Core/Utility/UnroutedUrlAssemblerTest.php Thu Apr 26 11:26:54 2018 +0100 +++ b/core/tests/Drupal/Tests/Core/Utility/UnroutedUrlAssemblerTest.php Tue Jul 10 15:07:59 2018 +0100 @@ -96,6 +96,10 @@ ['http://example.com/test', ['https' => TRUE], 'https://example.com/test'], ['https://example.com/test', ['https' => FALSE], 'http://example.com/test'], ['https://example.com/test?foo=1#bar', [], 'https://example.com/test?foo=1#bar'], + 'override-query' => ['https://example.com/test?foo=1#bar', ['query' => ['foo' => 2]], 'https://example.com/test?foo=2#bar'], + 'override-query-merge' => ['https://example.com/test?foo=1#bar', ['query' => ['bar' => 2]], 'https://example.com/test?bar=2&foo=1#bar'], + 'override-deep-query-merge' => ['https://example.com/test?foo=1#bar', ['query' => ['bar' => ['baz' => 'foo']]], 'https://example.com/test?bar%5Bbaz%5D=foo&foo=1#bar'], + 'override-fragment' => ['https://example.com/test?foo=1#bar', ['fragment' => 'baz'], 'https://example.com/test?foo=1#baz'], ['//www.drupal.org', [], '//www.drupal.org'], ]; } diff -r e200cb7efeb3 -r c2387f117808 core/tests/Drupal/Tests/EntityViewTrait.php --- a/core/tests/Drupal/Tests/EntityViewTrait.php Thu Apr 26 11:26:54 2018 +0100 +++ b/core/tests/Drupal/Tests/EntityViewTrait.php Tue Jul 10 15:07:59 2018 +0100 @@ -32,7 +32,7 @@ * (optional) Whether to clear the cache for this entity. * @return array * - * @see drupal_render() + * @see \Drupal\Core\Render\RendererInterface::render() */ protected function buildEntityView(EntityInterface $entity, $view_mode = 'full', $langcode = NULL, $reset = FALSE) { $ensure_fully_built = function (&$elements) use (&$ensure_fully_built) { diff -r e200cb7efeb3 -r c2387f117808 core/tests/Drupal/Tests/Listeners/DeprecationListenerTrait.php --- a/core/tests/Drupal/Tests/Listeners/DeprecationListenerTrait.php Thu Apr 26 11:26:54 2018 +0100 +++ b/core/tests/Drupal/Tests/Listeners/DeprecationListenerTrait.php Tue Jul 10 15:07:59 2018 +0100 @@ -113,7 +113,6 @@ 'MigrateCckFieldPluginManager is deprecated in Drupal 8.3.x and will be removed before Drupal 9.0.x. Use \Drupal\migrate_drupal\Annotation\MigrateFieldPluginManager instead.', 'MigrateCckFieldPluginManagerInterface is deprecated in Drupal 8.3.x and will be removed before Drupal 9.0.x. Use \Drupal\migrate_drupal\Annotation\MigrateFieldPluginManagerInterface instead.', 'The "plugin.manager.migrate.cckfield" service is deprecated. You should use the \'plugin.manager.migrate.field\' service instead. See https://www.drupal.org/node/2751897', - 'The Drupal\migrate\Plugin\migrate\process\Iterator is deprecated in Drupal 8.4.x and will be removed before Drupal 9.0.0. Instead, use Drupal\migrate\Plugin\migrate\process\SubProcess', 'Drupal\system\Tests\Update\DbUpdatesTrait is deprecated in Drupal 8.4.0 and will be removed before Drupal 9.0.0. Use \Drupal\FunctionalTests\Update\DbUpdatesTrait instead. See https://www.drupal.org/node/2896640.', 'Using "null" for the value of node "count" of "Drupal\Core\Template\TwigNodeTrans" is deprecated since version 1.25 and will be removed in 2.0.', 'Using "null" for the value of node "options" of "Drupal\Core\Template\TwigNodeTrans" is deprecated since version 1.25 and will be removed in 2.0.', @@ -137,14 +136,10 @@ 'Using UTF-8 route patterns without setting the "utf8" option is deprecated since Symfony 3.2 and will throw a LogicException in 4.0. Turn on the "utf8" route option for pattern "/somewhere/{item}/over/the/קainbow".', 'Using UTF-8 route patterns without setting the "utf8" option is deprecated since Symfony 3.2 and will throw a LogicException in 4.0. Turn on the "utf8" route option for pattern "/place/meφω".', 'Using UTF-8 route patterns without setting the "utf8" option is deprecated since Symfony 3.2 and will throw a LogicException in 4.0. Turn on the "utf8" route option for pattern "/PLACE/meφω".', - 'Passing a Session object to the ExpectationException constructor is deprecated as of Mink 1.7. Pass the driver instead.', 'The Drupal\editor\Plugin\EditorBase::settingsFormValidate method is deprecated since version 8.3.x and will be removed in 9.0.0.', - 'CckFile is deprecated in Drupal 8.3.x and will be be removed before Drupal 9.0.x. Use \Drupal\file\Plugin\migrate\process\d6\FieldFile instead.', 'The Drupal\migrate\Plugin\migrate\process\Migration is deprecated in Drupal 8.4.0 and will be removed before Drupal 9.0.0. Instead, use Drupal\migrate\Plugin\migrate\process\MigrationLookup', - 'LinkField is deprecated in Drupal 8.3.x and will be be removed before Drupal 9.0.x. Use \Drupal\link\Plugin\migrate\field\d7\LinkField instead.', 'LinkField is deprecated in Drupal 8.3.x and will be be removed before Drupal 9.0.x. Use \Drupal\link\Plugin\migrate\field\d6\LinkField instead.', 'CckFieldPluginBase is deprecated in Drupal 8.3.x and will be be removed before Drupal 9.0.x. Use \Drupal\migrate_drupal\Plugin\migrate\field\FieldPluginBase instead.', - 'MigrateCckFieldInterface is deprecated in Drupal 8.3.x and will be removed before Drupal 9.0.x. Use \Drupal\migrate_drupal\Annotation\MigrateField instead.', 'Drupal\system\Plugin\views\field\BulkForm is deprecated in Drupal 8.5.x, will be removed before Drupal 9.0.0. Use \Drupal\views\Plugin\views\field\BulkForm instead. See https://www.drupal.org/node/2916716.', 'The numeric plugin for watchdog.wid field is deprecated in Drupal 8.4.0 and will be removed before Drupal 9.0.0. Must use standard plugin instead. See https://www.drupal.org/node/2876378.', 'The numeric plugin for watchdog.uid field is deprecated in Drupal 8.4.0 and will be removed before Drupal 9.0.0. Must use standard plugin instead. See https://www.drupal.org/node/2876378.', @@ -159,7 +154,6 @@ 'Referencing the "twig_extension_test.test_extension" extension by its name (defined by getName()) is deprecated since 1.26 and will be removed in Twig 2.0. Use the Fully Qualified Extension Class Name instead.', 'Passing in arguments the legacy way is deprecated in Drupal 8.4.0 and will be removed before Drupal 9.0.0. Provide the right parameter names in the method, similar to controllers. See https://www.drupal.org/node/2894819', 'DateField is deprecated in Drupal 8.4.x and will be removed before Drupal 9.0.x. Use \Drupal\datetime\Plugin\migrate\field\DateField instead.', - 'The Drupal\taxonomy\Entity\Term::getVocabularyId method is deprecated since version 8.4.0 and will be removed before 9.0.0. Use Drupal\taxonomy\Entity\Term::bundle() instead to get the vocabulary ID.', 'The Drupal\editor\Plugin\EditorBase::settingsFormSubmit method is deprecated since version 8.3.x and will be removed in 9.0.0.', 'CommentVariable is deprecated in Drupal 8.4.x and will be removed before Drupal 9.0.x. Use \Drupal\node\Plugin\migrate\source\d6\NodeType instead.', 'CommentType is deprecated in Drupal 8.4.x and will be removed before Drupal 9.0.x. Use \Drupal\node\Plugin\migrate\source\d7\NodeType instead.', diff -r e200cb7efeb3 -r c2387f117808 core/tests/Drupal/Tests/Traits/Core/Config/SchemaConfigListenerTestTrait.php --- a/core/tests/Drupal/Tests/Traits/Core/Config/SchemaConfigListenerTestTrait.php Thu Apr 26 11:26:54 2018 +0100 +++ b/core/tests/Drupal/Tests/Traits/Core/Config/SchemaConfigListenerTestTrait.php Tue Jul 10 15:07:59 2018 +0100 @@ -35,6 +35,19 @@ $this->fail($message); } + // Test a valid schema, where the value is accessed before saving. Ensures + // that overridden data is correctly reset after casting. + $message = 'Unexpected SchemaIncompleteException thrown'; + $config = $this->config('config_test.types')->set('int', '10'); + $config->get('int'); + try { + $config->save(); + $this->pass($message); + } + catch (SchemaIncompleteException $e) { + $this->fail($message); + } + // Test an invalid schema. $message = 'Expected SchemaIncompleteException thrown'; $config = $this->config('config_test.types') diff -r e200cb7efeb3 -r c2387f117808 core/tests/Drupal/Tests/WebAssert.php --- a/core/tests/Drupal/Tests/WebAssert.php Thu Apr 26 11:26:54 2018 +0100 +++ b/core/tests/Drupal/Tests/WebAssert.php Tue Jul 10 15:07:59 2018 +0100 @@ -202,7 +202,7 @@ public function titleEquals($expected_title) { $title_element = $this->session->getPage()->find('css', 'title'); if (!$title_element) { - throw new ExpectationException('No title element found on the page', $this->session); + throw new ExpectationException('No title element found on the page', $this->session->getDriver()); } $actual_title = $title_element->getText(); $this->assert($expected_title === $actual_title, 'Title found'); diff -r e200cb7efeb3 -r c2387f117808 core/tests/bootstrap.php --- a/core/tests/bootstrap.php Thu Apr 26 11:26:54 2018 +0100 +++ b/core/tests/bootstrap.php Tue Jul 10 15:07:59 2018 +0100 @@ -66,7 +66,7 @@ $paths[] = is_dir("$path/profiles") ? realpath("$path/profiles") : NULL; $paths[] = is_dir("$path/themes") ? realpath("$path/themes") : NULL; } - return array_filter($paths); + return array_filter($paths, 'file_exists'); } /** diff -r e200cb7efeb3 -r c2387f117808 core/themes/bartik/README.txt --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/core/themes/bartik/README.txt Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,19 @@ +ABOUT BARTIK +------------ + +Bartik is the default theme for Drupal 8. It is a flexible, recolorable theme +with a responsive and mobile-first layout, supporting 16 regions. + +The Bartik theme is named after Jean Bartik, one of the original programmers +for the ENIAC computer. + +This theme is not intended to be used as a base theme. + +To read more about the Bartik theme please see: +https://www.drupal.org/docs/8/core/themes/bartik-theme + +ABOUT DRUPAL THEMING +-------------------- + +See https://www.drupal.org/docs/8/theming for more information on Drupal +theming. diff -r e200cb7efeb3 -r c2387f117808 core/themes/bartik/css/colors.css --- a/core/themes/bartik/css/colors.css Thu Apr 26 11:26:54 2018 +0100 +++ b/core/themes/bartik/css/colors.css Tue Jul 10 15:07:59 2018 +0100 @@ -46,10 +46,10 @@ .region-header, .region-header a, .region-header li a.is-active, -.site-branding__text, -.site-branding, -.site-branding__text a, -.site-branding a, +.region-header .site-branding__text, +.region-header .site-branding, +.region-header .site-branding__text a, +.region-header .site-branding a, .region-secondary-menu .menu-item a, .region-secondary-menu .menu-item a.is-active { color: #fffeff; diff -r e200cb7efeb3 -r c2387f117808 core/themes/bartik/css/components/site-branding.css --- a/core/themes/bartik/css/components/site-branding.css Thu Apr 26 11:26:54 2018 +0100 +++ b/core/themes/bartik/css/components/site-branding.css Tue Jul 10 15:07:59 2018 +0100 @@ -7,6 +7,7 @@ display: inline-block; margin-right: 1em; /* LTR */ margin-bottom: 0.286em; + border-bottom: 0; } [dir="rtl"] .site-branding__logo { margin-right: 0; diff -r e200cb7efeb3 -r c2387f117808 core/themes/bartik/templates/status-messages.html.twig --- a/core/themes/bartik/templates/status-messages.html.twig Thu Apr 26 11:26:54 2018 +0100 +++ b/core/themes/bartik/templates/status-messages.html.twig Tue Jul 10 15:07:59 2018 +0100 @@ -16,8 +16,6 @@ * Available variables: * - message_list: List of messages to be displayed, grouped by type. * - status_headings: List of all status types. - * - display: (optional) May have a value of 'status' or 'error' when only - * displaying messages of that specific type. */ #} {% block messages %} diff -r e200cb7efeb3 -r c2387f117808 core/themes/classy/templates/content/media.html.twig --- a/core/themes/classy/templates/content/media.html.twig Thu Apr 26 11:26:54 2018 +0100 +++ b/core/themes/classy/templates/content/media.html.twig Tue Jul 10 15:07:59 2018 +0100 @@ -17,7 +17,7 @@ 'media', 'media--type-' ~ media.bundle()|clean_class, not media.isPublished() ? 'media--unpublished', - view_mode ? 'media--view-mode-' ~ view_mode.id()|clean_class, + view_mode ? 'media--view-mode-' ~ view_mode|clean_class, ] %} diff -r e200cb7efeb3 -r c2387f117808 core/themes/classy/templates/misc/status-messages.html.twig --- a/core/themes/classy/templates/misc/status-messages.html.twig Thu Apr 26 11:26:54 2018 +0100 +++ b/core/themes/classy/templates/misc/status-messages.html.twig Tue Jul 10 15:07:59 2018 +0100 @@ -15,8 +15,6 @@ * Available variables: * - message_list: List of messages to be displayed, grouped by type. * - status_headings: List of all status types. - * - display: (optional) May have a value of 'status' or 'error' when only - * displaying messages of that specific type. * - attributes: HTML attributes for the element, including: * - class: HTML classes. */ diff -r e200cb7efeb3 -r c2387f117808 core/themes/classy/templates/views/views-view-grid.html.twig --- a/core/themes/classy/templates/views/views-view-grid.html.twig Thu Apr 26 11:26:54 2018 +0100 +++ b/core/themes/classy/templates/views/views-view-grid.html.twig Tue Jul 10 15:07:59 2018 +0100 @@ -57,7 +57,7 @@ {% for column in row.content %} - {{ column.content }} + {{- column.content -}} {% endfor %} @@ -67,7 +67,7 @@ {% for row in column.content %} - {{ row.content }} + {{- row.content -}} {% endfor %} diff -r e200cb7efeb3 -r c2387f117808 core/themes/classy/templates/views/views-view-list.html.twig --- a/core/themes/classy/templates/views/views-view-list.html.twig Thu Apr 26 11:26:54 2018 +0100 +++ b/core/themes/classy/templates/views/views-view-list.html.twig Tue Jul 10 15:07:59 2018 +0100 @@ -26,7 +26,9 @@ <{{ list.type }}{{ list.attributes }}> {% for row in rows %} - {{ row.content }}
    • + + {{- row.content -}} + {% endfor %} diff -r e200cb7efeb3 -r c2387f117808 core/themes/classy/templates/views/views-view-unformatted.html.twig --- a/core/themes/classy/templates/views/views-view-unformatted.html.twig Thu Apr 26 11:26:54 2018 +0100 +++ b/core/themes/classy/templates/views/views-view-unformatted.html.twig Tue Jul 10 15:07:59 2018 +0100 @@ -25,6 +25,6 @@ ] %} - {{ row.content }} + {{- row.content -}} {% endfor %} diff -r e200cb7efeb3 -r c2387f117808 core/themes/stable/templates/content-edit/entity-moderation-form.html.twig --- a/core/themes/stable/templates/content-edit/entity-moderation-form.html.twig Thu Apr 26 11:26:54 2018 +0100 +++ b/core/themes/stable/templates/content-edit/entity-moderation-form.html.twig Tue Jul 10 15:07:59 2018 +0100 @@ -1,4 +1,3 @@ -{{ attach_library('content_moderation/content_moderation') }}
      • {{ form.current }}
      • {{ form.new_state }}
      • diff -r e200cb7efeb3 -r c2387f117808 core/themes/stable/templates/misc/status-messages.html.twig --- a/core/themes/stable/templates/misc/status-messages.html.twig Thu Apr 26 11:26:54 2018 +0100 +++ b/core/themes/stable/templates/misc/status-messages.html.twig Tue Jul 10 15:07:59 2018 +0100 @@ -15,8 +15,6 @@ * Available variables: * - message_list: List of messages to be displayed, grouped by type. * - status_headings: List of all status types. - * - display: (optional) May have a value of 'status' or 'error' when only - * displaying messages of that specific type. * - attributes: HTML attributes for the element, including: * - class: HTML classes. */ diff -r e200cb7efeb3 -r c2387f117808 core/themes/stable/templates/views/views-view-grid.html.twig --- a/core/themes/stable/templates/views/views-view-grid.html.twig Thu Apr 26 11:26:54 2018 +0100 +++ b/core/themes/stable/templates/views/views-view-grid.html.twig Tue Jul 10 15:07:59 2018 +0100 @@ -57,7 +57,7 @@ {% for column in row.content %} - {{ column.content }} + {{- column.content -}} {% endfor %} @@ -67,7 +67,7 @@ {% for row in column.content %} - {{ row.content }} + {{- row.content -}} {% endfor %} diff -r e200cb7efeb3 -r c2387f117808 core/themes/stable/templates/views/views-view-list.html.twig --- a/core/themes/stable/templates/views/views-view-list.html.twig Thu Apr 26 11:26:54 2018 +0100 +++ b/core/themes/stable/templates/views/views-view-list.html.twig Tue Jul 10 15:07:59 2018 +0100 @@ -26,7 +26,9 @@ <{{ list.type }}{{ list.attributes }}> {% for row in rows %} - {{ row.content }} + + {{- row.content -}} + {% endfor %} diff -r e200cb7efeb3 -r c2387f117808 core/themes/stable/templates/views/views-view-unformatted.html.twig --- a/core/themes/stable/templates/views/views-view-unformatted.html.twig Thu Apr 26 11:26:54 2018 +0100 +++ b/core/themes/stable/templates/views/views-view-unformatted.html.twig Tue Jul 10 15:07:59 2018 +0100 @@ -25,6 +25,6 @@ ] %} - {{ row.content }} + {{- row.content -}} {% endfor %} diff -r e200cb7efeb3 -r c2387f117808 sites/default/files/php/twig/.htaccess --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/default/files/php/twig/.htaccess Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,23 @@ +# Deny all requests from Apache 2.4+. + + Require all denied + + +# Deny all requests from Apache 2.0-2.2. + + Deny from all + +# Turn off all options we don't need. +Options -Indexes -ExecCGI -Includes -MultiViews + +# Set the catch-all handler to prevent scripts from being executed. +SetHandler Drupal_Security_Do_Not_Remove_See_SA_2006_006 + + # Override the handler again if we're run later in the evaluation list. + SetHandler Drupal_Security_Do_Not_Remove_See_SA_2013_003 + + +# If we know how to do it safely, disable the PHP engine entirely. + + php_flag engine off + \ No newline at end of file diff -r e200cb7efeb3 -r c2387f117808 sites/default/files/php/twig/5ae1a97e5eec7_block--local-tasks-block._XrY-Gbbe_3ZGK_eVUo36wAuEb/.htaccess --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/default/files/php/twig/5ae1a97e5eec7_block--local-tasks-block._XrY-Gbbe_3ZGK_eVUo36wAuEb/.htaccess Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,23 @@ +# Deny all requests from Apache 2.4+. + + Require all denied + + +# Deny all requests from Apache 2.0-2.2. + + Deny from all + +# Turn off all options we don't need. +Options -Indexes -ExecCGI -Includes -MultiViews + +# Set the catch-all handler to prevent scripts from being executed. +SetHandler Drupal_Security_Do_Not_Remove_See_SA_2006_006 + + # Override the handler again if we're run later in the evaluation list. + SetHandler Drupal_Security_Do_Not_Remove_See_SA_2013_003 + + +# If we know how to do it safely, disable the PHP engine entirely. + + php_flag engine off + \ No newline at end of file diff -r e200cb7efeb3 -r c2387f117808 sites/default/files/php/twig/5ae1a97e5eec7_block--local-tasks-block._XrY-Gbbe_3ZGK_eVUo36wAuEb/NTwcr1KdN89uRyP8o5nH9rOOAQR48l63ypRFA996FJA.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/default/files/php/twig/5ae1a97e5eec7_block--local-tasks-block._XrY-Gbbe_3ZGK_eVUo36wAuEb/NTwcr1KdN89uRyP8o5nH9rOOAQR48l63ypRFA996FJA.php Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,97 @@ +parent = $this->loadTemplate("block.html.twig", "core/themes/classy/templates/block/block--local-tasks-block.html.twig", 1); + $this->blocks = array( + 'content' => array($this, 'block_content'), + ); + } + + protected function doGetParent(array $context) + { + return "block.html.twig"; + } + + protected function doDisplay(array $context, array $blocks = array()) + { + $tags = array("if" => 9); + $filters = array("t" => 10); + $functions = array(); + + try { + $this->env->getExtension('Twig_Extension_Sandbox')->checkSecurity( + array('if'), + array('t'), + array() + ); + } catch (Twig_Sandbox_SecurityError $e) { + $e->setSourceContext($this->getSourceContext()); + + if ($e instanceof Twig_Sandbox_SecurityNotAllowedTagError && isset($tags[$e->getTagName()])) { + $e->setTemplateLine($tags[$e->getTagName()]); + } elseif ($e instanceof Twig_Sandbox_SecurityNotAllowedFilterError && isset($filters[$e->getFilterName()])) { + $e->setTemplateLine($filters[$e->getFilterName()]); + } elseif ($e instanceof Twig_Sandbox_SecurityNotAllowedFunctionError && isset($functions[$e->getFunctionName()])) { + $e->setTemplateLine($functions[$e->getFunctionName()]); + } + + throw $e; + } + + $this->parent->display($context, array_merge($this->blocks, $blocks)); + } + + // line 8 + public function block_content($context, array $blocks = array()) + { + // line 9 + echo " "; + if (($context["content"] ?? null)) { + // line 10 + echo " + "; + } + } + + public function getTemplateName() + { + return "core/themes/classy/templates/block/block--local-tasks-block.html.twig"; + } + + public function isTraitable() + { + return false; + } + + public function getDebugInfo() + { + return array ( 63 => 11, 58 => 10, 55 => 9, 52 => 8, 11 => 1,); + } + + /** @deprecated since 1.27 (to be removed in 2.0). Use getSourceContext() instead */ + public function getSource() + { + @trigger_error('The '.__METHOD__.' method is deprecated since version 1.27 and will be removed in 2.0. Use getSourceContext() instead.', E_USER_DEPRECATED); + + return $this->getSourceContext()->getCode(); + } + + public function getSourceContext() + { + return new Twig_Source("", "core/themes/classy/templates/block/block--local-tasks-block.html.twig", "/var/www/sites/isophonics.net/core/themes/classy/templates/block/block--local-tasks-block.html.twig"); + } +} diff -r e200cb7efeb3 -r c2387f117808 sites/default/files/php/twig/5ae1a97e5eec7_block--search-form-block._-9HtaDVE8pCe5SyzLjs47G6RZ/.htaccess --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/default/files/php/twig/5ae1a97e5eec7_block--search-form-block._-9HtaDVE8pCe5SyzLjs47G6RZ/.htaccess Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,23 @@ +# Deny all requests from Apache 2.4+. + + Require all denied + + +# Deny all requests from Apache 2.0-2.2. + + Deny from all + +# Turn off all options we don't need. +Options -Indexes -ExecCGI -Includes -MultiViews + +# Set the catch-all handler to prevent scripts from being executed. +SetHandler Drupal_Security_Do_Not_Remove_See_SA_2006_006 + + # Override the handler again if we're run later in the evaluation list. + SetHandler Drupal_Security_Do_Not_Remove_See_SA_2013_003 + + +# If we know how to do it safely, disable the PHP engine entirely. + + php_flag engine off + \ No newline at end of file diff -r e200cb7efeb3 -r c2387f117808 sites/default/files/php/twig/5ae1a97e5eec7_block--search-form-block._-9HtaDVE8pCe5SyzLjs47G6RZ/q6KEzyrtzxjJ1pSwR4b6_k742_V4PYNetrbciGrKR_M.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/default/files/php/twig/5ae1a97e5eec7_block--search-form-block._-9HtaDVE8pCe5SyzLjs47G6RZ/q6KEzyrtzxjJ1pSwR4b6_k742_V4PYNetrbciGrKR_M.php Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,113 @@ +parent = false; + + $this->blocks = array( + 'content' => array($this, 'block_content'), + ); + } + + protected function doDisplay(array $context, array $blocks = array()) + { + $tags = array("set" => 30, "if" => 38, "block" => 42); + $filters = array(); + $functions = array(); + + try { + $this->env->getExtension('Twig_Extension_Sandbox')->checkSecurity( + array('set', 'if', 'block'), + array(), + array() + ); + } catch (Twig_Sandbox_SecurityError $e) { + $e->setSourceContext($this->getSourceContext()); + + if ($e instanceof Twig_Sandbox_SecurityNotAllowedTagError && isset($tags[$e->getTagName()])) { + $e->setTemplateLine($tags[$e->getTagName()]); + } elseif ($e instanceof Twig_Sandbox_SecurityNotAllowedFilterError && isset($filters[$e->getFilterName()])) { + $e->setTemplateLine($filters[$e->getFilterName()]); + } elseif ($e instanceof Twig_Sandbox_SecurityNotAllowedFunctionError && isset($functions[$e->getFunctionName()])) { + $e->setTemplateLine($functions[$e->getFunctionName()]); + } + + throw $e; + } + + // line 30 + $context["classes"] = array(0 => "block", 1 => "block-search", 2 => "container-inline"); + // line 36 + echo "env->getExtension('Twig_Extension_Sandbox')->ensureToStringAllowed($this->env->getExtension('Drupal\Core\Template\TwigExtension')->escapeFilter($this->env, $this->getAttribute(($context["attributes"] ?? null), "addClass", array(0 => ($context["classes"] ?? null)), "method"), "html", null, true)); + echo "> + "; + // line 37 + echo $this->env->getExtension('Twig_Extension_Sandbox')->ensureToStringAllowed($this->env->getExtension('Drupal\Core\Template\TwigExtension')->escapeFilter($this->env, ($context["title_prefix"] ?? null), "html", null, true)); + echo " + "; + // line 38 + if (($context["label"] ?? null)) { + // line 39 + echo " env->getExtension('Twig_Extension_Sandbox')->ensureToStringAllowed($this->env->getExtension('Drupal\Core\Template\TwigExtension')->escapeFilter($this->env, ($context["title_attributes"] ?? null), "html", null, true)); + echo ">"; + echo $this->env->getExtension('Twig_Extension_Sandbox')->ensureToStringAllowed($this->env->getExtension('Drupal\Core\Template\TwigExtension')->escapeFilter($this->env, ($context["label"] ?? null), "html", null, true)); + echo " + "; + } + // line 41 + echo " "; + echo $this->env->getExtension('Twig_Extension_Sandbox')->ensureToStringAllowed($this->env->getExtension('Drupal\Core\Template\TwigExtension')->escapeFilter($this->env, ($context["title_suffix"] ?? null), "html", null, true)); + echo " + "; + // line 42 + $this->displayBlock('content', $context, $blocks); + // line 45 + echo " +"; + } + + // line 42 + public function block_content($context, array $blocks = array()) + { + // line 43 + echo " "; + echo $this->env->getExtension('Twig_Extension_Sandbox')->ensureToStringAllowed($this->env->getExtension('Drupal\Core\Template\TwigExtension')->escapeFilter($this->env, ($context["content"] ?? null), "html", null, true)); + echo " + "; + } + + public function getTemplateName() + { + return "@classy/block/block--search-form-block.html.twig"; + } + + public function isTraitable() + { + return false; + } + + public function getDebugInfo() + { + return array ( 80 => 43, 77 => 42, 72 => 45, 70 => 42, 65 => 41, 57 => 39, 55 => 38, 51 => 37, 46 => 36, 44 => 30,); + } + + /** @deprecated since 1.27 (to be removed in 2.0). Use getSourceContext() instead */ + public function getSource() + { + @trigger_error('The '.__METHOD__.' method is deprecated since version 1.27 and will be removed in 2.0. Use getSourceContext() instead.', E_USER_DEPRECATED); + + return $this->getSourceContext()->getCode(); + } + + public function getSourceContext() + { + return new Twig_Source("", "@classy/block/block--search-form-block.html.twig", "/var/www/sites/isophonics.net/core/themes/classy/templates/block/block--search-form-block.html.twig"); + } +} diff -r e200cb7efeb3 -r c2387f117808 sites/default/files/php/twig/5ae1a97e5eec7_block--search-form-block._Hw8-ysT8Nq_53Gz9gaqawBqFG/.htaccess --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/default/files/php/twig/5ae1a97e5eec7_block--search-form-block._Hw8-ysT8Nq_53Gz9gaqawBqFG/.htaccess Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,23 @@ +# Deny all requests from Apache 2.4+. + + Require all denied + + +# Deny all requests from Apache 2.0-2.2. + + Deny from all + +# Turn off all options we don't need. +Options -Indexes -ExecCGI -Includes -MultiViews + +# Set the catch-all handler to prevent scripts from being executed. +SetHandler Drupal_Security_Do_Not_Remove_See_SA_2006_006 + + # Override the handler again if we're run later in the evaluation list. + SetHandler Drupal_Security_Do_Not_Remove_See_SA_2013_003 + + +# If we know how to do it safely, disable the PHP engine entirely. + + php_flag engine off + \ No newline at end of file diff -r e200cb7efeb3 -r c2387f117808 sites/default/files/php/twig/5ae1a97e5eec7_block--search-form-block._Hw8-ysT8Nq_53Gz9gaqawBqFG/TpZ8DHcCbVl5jM85AXqjZbHud_TJjoUk7b6Ym9SR0ZY.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/default/files/php/twig/5ae1a97e5eec7_block--search-form-block._Hw8-ysT8Nq_53Gz9gaqawBqFG/TpZ8DHcCbVl5jM85AXqjZbHud_TJjoUk7b6Ym9SR0ZY.php Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,93 @@ +parent = $this->loadTemplate("@classy/block/block--search-form-block.html.twig", "themes/isobartik/templates/block--search-form-block.html.twig", 1); + $this->blocks = array( + 'content' => array($this, 'block_content'), + ); + } + + protected function doGetParent(array $context) + { + return "@classy/block/block--search-form-block.html.twig"; + } + + protected function doDisplay(array $context, array $blocks = array()) + { + $tags = array(); + $filters = array(); + $functions = array(); + + try { + $this->env->getExtension('Twig_Extension_Sandbox')->checkSecurity( + array(), + array(), + array() + ); + } catch (Twig_Sandbox_SecurityError $e) { + $e->setSourceContext($this->getSourceContext()); + + if ($e instanceof Twig_Sandbox_SecurityNotAllowedTagError && isset($tags[$e->getTagName()])) { + $e->setTemplateLine($tags[$e->getTagName()]); + } elseif ($e instanceof Twig_Sandbox_SecurityNotAllowedFilterError && isset($filters[$e->getFilterName()])) { + $e->setTemplateLine($filters[$e->getFilterName()]); + } elseif ($e instanceof Twig_Sandbox_SecurityNotAllowedFunctionError && isset($functions[$e->getFunctionName()])) { + $e->setTemplateLine($functions[$e->getFunctionName()]); + } + + throw $e; + } + + $this->parent->display($context, array_merge($this->blocks, $blocks)); + } + + // line 19 + public function block_content($context, array $blocks = array()) + { + // line 20 + echo " env->getExtension('Twig_Extension_Sandbox')->ensureToStringAllowed($this->env->getExtension('Drupal\Core\Template\TwigExtension')->escapeFilter($this->env, $this->getAttribute(($context["content_attributes"] ?? null), "addClass", array(0 => "content", 1 => "container-inline"), "method"), "html", null, true)); + echo "> + "; + // line 21 + $this->displayParentBlock("content", $context, $blocks); + echo " + +"; + } + + public function getTemplateName() + { + return "themes/isobartik/templates/block--search-form-block.html.twig"; + } + + public function isTraitable() + { + return false; + } + + public function getDebugInfo() + { + return array ( 60 => 21, 55 => 20, 52 => 19, 11 => 1,); + } + + /** @deprecated since 1.27 (to be removed in 2.0). Use getSourceContext() instead */ + public function getSource() + { + @trigger_error('The '.__METHOD__.' method is deprecated since version 1.27 and will be removed in 2.0. Use getSourceContext() instead.', E_USER_DEPRECATED); + + return $this->getSourceContext()->getCode(); + } + + public function getSourceContext() + { + return new Twig_Source("", "themes/isobartik/templates/block--search-form-block.html.twig", "/var/www/sites/isophonics.net/themes/isobartik/templates/block--search-form-block.html.twig"); + } +} diff -r e200cb7efeb3 -r c2387f117808 sites/default/files/php/twig/5ae1a97e5eec7_block--system-menu-block._1mrraq57epVEwI8rbKEg2iw1y/.htaccess --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/default/files/php/twig/5ae1a97e5eec7_block--system-menu-block._1mrraq57epVEwI8rbKEg2iw1y/.htaccess Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,23 @@ +# Deny all requests from Apache 2.4+. + + Require all denied + + +# Deny all requests from Apache 2.0-2.2. + + Deny from all + +# Turn off all options we don't need. +Options -Indexes -ExecCGI -Includes -MultiViews + +# Set the catch-all handler to prevent scripts from being executed. +SetHandler Drupal_Security_Do_Not_Remove_See_SA_2006_006 + + # Override the handler again if we're run later in the evaluation list. + SetHandler Drupal_Security_Do_Not_Remove_See_SA_2013_003 + + +# If we know how to do it safely, disable the PHP engine entirely. + + php_flag engine off + \ No newline at end of file diff -r e200cb7efeb3 -r c2387f117808 sites/default/files/php/twig/5ae1a97e5eec7_block--system-menu-block._1mrraq57epVEwI8rbKEg2iw1y/tBcf2roxCpa6Js_Prf0s7tQDnKnKEribno7TQqe-W1o.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/default/files/php/twig/5ae1a97e5eec7_block--system-menu-block._1mrraq57epVEwI8rbKEg2iw1y/tBcf2roxCpa6Js_Prf0s7tQDnKnKEribno7TQqe-W1o.php Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,119 @@ +parent = $this->loadTemplate("@classy/block/block--system-menu-block.html.twig", "themes/isobartik/templates/block--system-menu-block.html.twig", 1); + $this->blocks = array( + 'content' => array($this, 'block_content'), + ); + } + + protected function doGetParent(array $context) + { + return "@classy/block/block--system-menu-block.html.twig"; + } + + protected function doDisplay(array $context, array $blocks = array()) + { + $tags = array("set" => 10, "trans" => 17); + $filters = array("clean_id" => 10); + $functions = array(); + + try { + $this->env->getExtension('Twig_Extension_Sandbox')->checkSecurity( + array('set', 'trans'), + array('clean_id'), + array() + ); + } catch (Twig_Sandbox_SecurityError $e) { + $e->setSourceContext($this->getSourceContext()); + + if ($e instanceof Twig_Sandbox_SecurityNotAllowedTagError && isset($tags[$e->getTagName()])) { + $e->setTemplateLine($tags[$e->getTagName()]); + } elseif ($e instanceof Twig_Sandbox_SecurityNotAllowedFilterError && isset($filters[$e->getFilterName()])) { + $e->setTemplateLine($filters[$e->getFilterName()]); + } elseif ($e instanceof Twig_Sandbox_SecurityNotAllowedFunctionError && isset($functions[$e->getFunctionName()])) { + $e->setTemplateLine($functions[$e->getFunctionName()]); + } + + throw $e; + } + + // line 10 + $context["show_anchor"] = ("show-" . \Drupal\Component\Utility\Html::getId($this->getAttribute(($context["attributes"] ?? null), "id", array()))); + // line 11 + $context["hide_anchor"] = ("hide-" . \Drupal\Component\Utility\Html::getId($this->getAttribute(($context["attributes"] ?? null), "id", array()))); + // line 1 + $this->parent->display($context, array_merge($this->blocks, $blocks)); + } + + // line 12 + public function block_content($context, array $blocks = array()) + { + // line 13 + echo " env->getExtension('Twig_Extension_Sandbox')->ensureToStringAllowed($this->env->getExtension('Drupal\Core\Template\TwigExtension')->escapeFilter($this->env, $this->getAttribute(($context["content_attributes"] ?? null), "addClass", array(0 => "content"), "method"), "html", null, true)); + echo "> + "; + // line 15 + echo "
        env->getExtension('Twig_Extension_Sandbox')->ensureToStringAllowed($this->env->getExtension('Drupal\Core\Template\TwigExtension')->escapeFilter($this->env, ($context["show_anchor"] ?? null), "html", null, true)); + echo "\">
        +
        env->getExtension('Twig_Extension_Sandbox')->ensureToStringAllowed($this->env->getExtension('Drupal\Core\Template\TwigExtension')->escapeFilter($this->env, ($context["hide_anchor"] ?? null), "html", null, true)); + echo "\">
        + env->getExtension('Twig_Extension_Sandbox')->ensureToStringAllowed($this->env->getExtension('Drupal\Core\Template\TwigExtension')->escapeFilter($this->env, ($context["show_anchor"] ?? null), "html", null, true)); + echo "\">"; + echo t("Show — @configuration.label", array("@configuration.label" => $this->getAttribute(($context["configuration"] ?? null), "label", array()), )); + echo " + env->getExtension('Twig_Extension_Sandbox')->ensureToStringAllowed($this->env->getExtension('Drupal\Core\Template\TwigExtension')->escapeFilter($this->env, ($context["hide_anchor"] ?? null), "html", null, true)); + echo "\">"; + echo t("Hide — @configuration.label", array("@configuration.label" => $this->getAttribute(($context["configuration"] ?? null), "label", array()), )); + echo " + "; + // line 19 + echo $this->env->getExtension('Twig_Extension_Sandbox')->ensureToStringAllowed($this->env->getExtension('Drupal\Core\Template\TwigExtension')->escapeFilter($this->env, ($context["content"] ?? null), "html", null, true)); + echo " + +"; + } + + public function getTemplateName() + { + return "themes/isobartik/templates/block--system-menu-block.html.twig"; + } + + public function isTraitable() + { + return false; + } + + public function getDebugInfo() + { + return array ( 86 => 19, 80 => 18, 74 => 17, 70 => 16, 65 => 15, 60 => 13, 57 => 12, 53 => 1, 51 => 11, 49 => 10, 11 => 1,); + } + + /** @deprecated since 1.27 (to be removed in 2.0). Use getSourceContext() instead */ + public function getSource() + { + @trigger_error('The '.__METHOD__.' method is deprecated since version 1.27 and will be removed in 2.0. Use getSourceContext() instead.', E_USER_DEPRECATED); + + return $this->getSourceContext()->getCode(); + } + + public function getSourceContext() + { + return new Twig_Source("", "themes/isobartik/templates/block--system-menu-block.html.twig", "/var/www/sites/isophonics.net/themes/isobartik/templates/block--system-menu-block.html.twig"); + } +} diff -r e200cb7efeb3 -r c2387f117808 sites/default/files/php/twig/5ae1a97e5eec7_block--system-menu-block._2hNSCNK6Y2jmAWQaMH3vksp4p/.htaccess --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/default/files/php/twig/5ae1a97e5eec7_block--system-menu-block._2hNSCNK6Y2jmAWQaMH3vksp4p/.htaccess Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,23 @@ +# Deny all requests from Apache 2.4+. + + Require all denied + + +# Deny all requests from Apache 2.0-2.2. + + Deny from all + +# Turn off all options we don't need. +Options -Indexes -ExecCGI -Includes -MultiViews + +# Set the catch-all handler to prevent scripts from being executed. +SetHandler Drupal_Security_Do_Not_Remove_See_SA_2006_006 + + # Override the handler again if we're run later in the evaluation list. + SetHandler Drupal_Security_Do_Not_Remove_See_SA_2013_003 + + +# If we know how to do it safely, disable the PHP engine entirely. + + php_flag engine off + \ No newline at end of file diff -r e200cb7efeb3 -r c2387f117808 sites/default/files/php/twig/5ae1a97e5eec7_block--system-menu-block._2hNSCNK6Y2jmAWQaMH3vksp4p/Y3y0ffPuShkOfdL8i17DyLKR_Fz7QiTco6Dzw8HN_TY.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/default/files/php/twig/5ae1a97e5eec7_block--system-menu-block._2hNSCNK6Y2jmAWQaMH3vksp4p/Y3y0ffPuShkOfdL8i17DyLKR_Fz7QiTco6Dzw8HN_TY.php Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,125 @@ +parent = false; + + $this->blocks = array( + 'content' => array($this, 'block_content'), + ); + } + + protected function doDisplay(array $context, array $blocks = array()) + { + $tags = array("set" => 35, "if" => 45, "block" => 53); + $filters = array("clean_class" => 39, "clean_id" => 42, "without" => 43); + $functions = array(); + + try { + $this->env->getExtension('Twig_Extension_Sandbox')->checkSecurity( + array('set', 'if', 'block'), + array('clean_class', 'clean_id', 'without'), + array() + ); + } catch (Twig_Sandbox_SecurityError $e) { + $e->setSourceContext($this->getSourceContext()); + + if ($e instanceof Twig_Sandbox_SecurityNotAllowedTagError && isset($tags[$e->getTagName()])) { + $e->setTemplateLine($tags[$e->getTagName()]); + } elseif ($e instanceof Twig_Sandbox_SecurityNotAllowedFilterError && isset($filters[$e->getFilterName()])) { + $e->setTemplateLine($filters[$e->getFilterName()]); + } elseif ($e instanceof Twig_Sandbox_SecurityNotAllowedFunctionError && isset($functions[$e->getFunctionName()])) { + $e->setTemplateLine($functions[$e->getFunctionName()]); + } + + throw $e; + } + + // line 35 + $context["classes"] = array(0 => "block", 1 => "block-menu", 2 => "navigation", 3 => ("menu--" . \Drupal\Component\Utility\Html::getClass( // line 39 +($context["derivative_plugin_id"] ?? null)))); + // line 42 + $context["heading_id"] = ($this->getAttribute(($context["attributes"] ?? null), "id", array()) . \Drupal\Component\Utility\Html::getId("-menu")); + // line 43 + echo " +"; + } + + // line 53 + public function block_content($context, array $blocks = array()) + { + // line 54 + echo " "; + echo $this->env->getExtension('Twig_Extension_Sandbox')->ensureToStringAllowed($this->env->getExtension('Drupal\Core\Template\TwigExtension')->escapeFilter($this->env, ($context["content"] ?? null), "html", null, true)); + echo " + "; + } + + public function getTemplateName() + { + return "@classy/block/block--system-menu-block.html.twig"; + } + + public function isTraitable() + { + return false; + } + + public function getDebugInfo() + { + return array ( 92 => 54, 89 => 53, 84 => 56, 81 => 53, 76 => 50, 70 => 49, 65 => 48, 62 => 47, 59 => 46, 56 => 45, 49 => 43, 47 => 42, 45 => 39, 44 => 35,); + } + + /** @deprecated since 1.27 (to be removed in 2.0). Use getSourceContext() instead */ + public function getSource() + { + @trigger_error('The '.__METHOD__.' method is deprecated since version 1.27 and will be removed in 2.0. Use getSourceContext() instead.', E_USER_DEPRECATED); + + return $this->getSourceContext()->getCode(); + } + + public function getSourceContext() + { + return new Twig_Source("", "@classy/block/block--system-menu-block.html.twig", "/var/www/sites/isophonics.net/core/themes/classy/templates/block/block--system-menu-block.html.twig"); + } +} diff -r e200cb7efeb3 -r c2387f117808 sites/default/files/php/twig/5ae1a97e5eec7_block--system-messages-bl_ZI0iUqt_t91aPosCA454NgoNz/.htaccess --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/default/files/php/twig/5ae1a97e5eec7_block--system-messages-bl_ZI0iUqt_t91aPosCA454NgoNz/.htaccess Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,23 @@ +# Deny all requests from Apache 2.4+. + + Require all denied + + +# Deny all requests from Apache 2.0-2.2. + + Deny from all + +# Turn off all options we don't need. +Options -Indexes -ExecCGI -Includes -MultiViews + +# Set the catch-all handler to prevent scripts from being executed. +SetHandler Drupal_Security_Do_Not_Remove_See_SA_2006_006 + + # Override the handler again if we're run later in the evaluation list. + SetHandler Drupal_Security_Do_Not_Remove_See_SA_2013_003 + + +# If we know how to do it safely, disable the PHP engine entirely. + + php_flag engine off + \ No newline at end of file diff -r e200cb7efeb3 -r c2387f117808 sites/default/files/php/twig/5ae1a97e5eec7_block--system-messages-bl_ZI0iUqt_t91aPosCA454NgoNz/PWBxjQa4fh3sxMVVyMcQj-8Ckfs1xWg_8WSM70n6yGA.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/default/files/php/twig/5ae1a97e5eec7_block--system-messages-bl_ZI0iUqt_t91aPosCA454NgoNz/PWBxjQa4fh3sxMVVyMcQj-8Ckfs1xWg_8WSM70n6yGA.php Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,75 @@ +parent = false; + + $this->blocks = array( + ); + } + + protected function doDisplay(array $context, array $blocks = array()) + { + $tags = array(); + $filters = array(); + $functions = array(); + + try { + $this->env->getExtension('Twig_Extension_Sandbox')->checkSecurity( + array(), + array(), + array() + ); + } catch (Twig_Sandbox_SecurityError $e) { + $e->setSourceContext($this->getSourceContext()); + + if ($e instanceof Twig_Sandbox_SecurityNotAllowedTagError && isset($tags[$e->getTagName()])) { + $e->setTemplateLine($tags[$e->getTagName()]); + } elseif ($e instanceof Twig_Sandbox_SecurityNotAllowedFilterError && isset($filters[$e->getFilterName()])) { + $e->setTemplateLine($filters[$e->getFilterName()]); + } elseif ($e instanceof Twig_Sandbox_SecurityNotAllowedFunctionError && isset($functions[$e->getFunctionName()])) { + $e->setTemplateLine($functions[$e->getFunctionName()]); + } + + throw $e; + } + + // line 13 + echo $this->env->getExtension('Twig_Extension_Sandbox')->ensureToStringAllowed($this->env->getExtension('Drupal\Core\Template\TwigExtension')->escapeFilter($this->env, ($context["content"] ?? null), "html", null, true)); + echo " +"; + } + + public function getTemplateName() + { + return "core/themes/stable/templates/block/block--system-messages-block.html.twig"; + } + + public function isTraitable() + { + return false; + } + + public function getDebugInfo() + { + return array ( 43 => 13,); + } + + /** @deprecated since 1.27 (to be removed in 2.0). Use getSourceContext() instead */ + public function getSource() + { + @trigger_error('The '.__METHOD__.' method is deprecated since version 1.27 and will be removed in 2.0. Use getSourceContext() instead.', E_USER_DEPRECATED); + + return $this->getSourceContext()->getCode(); + } + + public function getSourceContext() + { + return new Twig_Source("", "core/themes/stable/templates/block/block--system-messages-block.html.twig", "/var/www/sites/isophonics.net/core/themes/stable/templates/block/block--system-messages-block.html.twig"); + } +} diff -r e200cb7efeb3 -r c2387f117808 sites/default/files/php/twig/5ae1a97e5eec7_block.html.twig_CIz2o0S3PkA8DW5E6V6XtYLjI/.htaccess --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/default/files/php/twig/5ae1a97e5eec7_block.html.twig_CIz2o0S3PkA8DW5E6V6XtYLjI/.htaccess Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,23 @@ +# Deny all requests from Apache 2.4+. + + Require all denied + + +# Deny all requests from Apache 2.0-2.2. + + Deny from all + +# Turn off all options we don't need. +Options -Indexes -ExecCGI -Includes -MultiViews + +# Set the catch-all handler to prevent scripts from being executed. +SetHandler Drupal_Security_Do_Not_Remove_See_SA_2006_006 + + # Override the handler again if we're run later in the evaluation list. + SetHandler Drupal_Security_Do_Not_Remove_See_SA_2013_003 + + +# If we know how to do it safely, disable the PHP engine entirely. + + php_flag engine off + \ No newline at end of file diff -r e200cb7efeb3 -r c2387f117808 sites/default/files/php/twig/5ae1a97e5eec7_block.html.twig_CIz2o0S3PkA8DW5E6V6XtYLjI/06RIHvFy9vSkRAvmFveGzMcK8uflPP6nsf_MpNT3l1M.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/default/files/php/twig/5ae1a97e5eec7_block.html.twig_CIz2o0S3PkA8DW5E6V6XtYLjI/06RIHvFy9vSkRAvmFveGzMcK8uflPP6nsf_MpNT3l1M.php Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,120 @@ +parent = false; + + $this->blocks = array( + 'content' => array($this, 'block_content'), + ); + } + + protected function doDisplay(array $context, array $blocks = array()) + { + $tags = array("set" => 33, "if" => 41, "block" => 45); + $filters = array("clean_class" => 35); + $functions = array(); + + try { + $this->env->getExtension('Twig_Extension_Sandbox')->checkSecurity( + array('set', 'if', 'block'), + array('clean_class'), + array() + ); + } catch (Twig_Sandbox_SecurityError $e) { + $e->setSourceContext($this->getSourceContext()); + + if ($e instanceof Twig_Sandbox_SecurityNotAllowedTagError && isset($tags[$e->getTagName()])) { + $e->setTemplateLine($tags[$e->getTagName()]); + } elseif ($e instanceof Twig_Sandbox_SecurityNotAllowedFilterError && isset($filters[$e->getFilterName()])) { + $e->setTemplateLine($filters[$e->getFilterName()]); + } elseif ($e instanceof Twig_Sandbox_SecurityNotAllowedFunctionError && isset($functions[$e->getFunctionName()])) { + $e->setTemplateLine($functions[$e->getFunctionName()]); + } + + throw $e; + } + + // line 33 + $context["classes"] = array(0 => "block", 1 => ("block-" . \Drupal\Component\Utility\Html::getClass($this->getAttribute( // line 35 +($context["configuration"] ?? null), "provider", array()))), 2 => ("block-" . \Drupal\Component\Utility\Html::getClass( // line 36 +($context["plugin_id"] ?? null)))); + // line 39 + echo "env->getExtension('Twig_Extension_Sandbox')->ensureToStringAllowed($this->env->getExtension('Drupal\Core\Template\TwigExtension')->escapeFilter($this->env, $this->getAttribute(($context["attributes"] ?? null), "addClass", array(0 => ($context["classes"] ?? null)), "method"), "html", null, true)); + echo "> + "; + // line 40 + echo $this->env->getExtension('Twig_Extension_Sandbox')->ensureToStringAllowed($this->env->getExtension('Drupal\Core\Template\TwigExtension')->escapeFilter($this->env, ($context["title_prefix"] ?? null), "html", null, true)); + echo " + "; + // line 41 + if (($context["label"] ?? null)) { + // line 42 + echo " env->getExtension('Twig_Extension_Sandbox')->ensureToStringAllowed($this->env->getExtension('Drupal\Core\Template\TwigExtension')->escapeFilter($this->env, ($context["title_attributes"] ?? null), "html", null, true)); + echo ">"; + echo $this->env->getExtension('Twig_Extension_Sandbox')->ensureToStringAllowed($this->env->getExtension('Drupal\Core\Template\TwigExtension')->escapeFilter($this->env, ($context["label"] ?? null), "html", null, true)); + echo " + "; + } + // line 44 + echo " "; + echo $this->env->getExtension('Twig_Extension_Sandbox')->ensureToStringAllowed($this->env->getExtension('Drupal\Core\Template\TwigExtension')->escapeFilter($this->env, ($context["title_suffix"] ?? null), "html", null, true)); + echo " + "; + // line 45 + $this->displayBlock('content', $context, $blocks); + // line 50 + echo " +"; + } + + // line 45 + public function block_content($context, array $blocks = array()) + { + // line 46 + echo " env->getExtension('Twig_Extension_Sandbox')->ensureToStringAllowed($this->env->getExtension('Drupal\Core\Template\TwigExtension')->escapeFilter($this->env, $this->getAttribute(($context["content_attributes"] ?? null), "addClass", array(0 => "content"), "method"), "html", null, true)); + echo "> + "; + // line 47 + echo $this->env->getExtension('Twig_Extension_Sandbox')->ensureToStringAllowed($this->env->getExtension('Drupal\Core\Template\TwigExtension')->escapeFilter($this->env, ($context["content"] ?? null), "html", null, true)); + echo " + + "; + } + + public function getTemplateName() + { + return "themes/isobartik/templates/block.html.twig"; + } + + public function isTraitable() + { + return false; + } + + public function getDebugInfo() + { + return array ( 87 => 47, 82 => 46, 79 => 45, 74 => 50, 72 => 45, 67 => 44, 59 => 42, 57 => 41, 53 => 40, 48 => 39, 46 => 36, 45 => 35, 44 => 33,); + } + + /** @deprecated since 1.27 (to be removed in 2.0). Use getSourceContext() instead */ + public function getSource() + { + @trigger_error('The '.__METHOD__.' method is deprecated since version 1.27 and will be removed in 2.0. Use getSourceContext() instead.', E_USER_DEPRECATED); + + return $this->getSourceContext()->getCode(); + } + + public function getSourceContext() + { + return new Twig_Source("", "themes/isobartik/templates/block.html.twig", "/var/www/sites/isophonics.net/themes/isobartik/templates/block.html.twig"); + } +} diff -r e200cb7efeb3 -r c2387f117808 sites/default/files/php/twig/5ae1a97e5eec7_container.html.twig_5ytYVUs_gdkx819cOy1xqJ2Z_/.htaccess --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/default/files/php/twig/5ae1a97e5eec7_container.html.twig_5ytYVUs_gdkx819cOy1xqJ2Z_/.htaccess Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,23 @@ +# Deny all requests from Apache 2.4+. + + Require all denied + + +# Deny all requests from Apache 2.0-2.2. + + Deny from all + +# Turn off all options we don't need. +Options -Indexes -ExecCGI -Includes -MultiViews + +# Set the catch-all handler to prevent scripts from being executed. +SetHandler Drupal_Security_Do_Not_Remove_See_SA_2006_006 + + # Override the handler again if we're run later in the evaluation list. + SetHandler Drupal_Security_Do_Not_Remove_See_SA_2013_003 + + +# If we know how to do it safely, disable the PHP engine entirely. + + php_flag engine off + \ No newline at end of file diff -r e200cb7efeb3 -r c2387f117808 sites/default/files/php/twig/5ae1a97e5eec7_container.html.twig_5ytYVUs_gdkx819cOy1xqJ2Z_/i4IHyG5RlNmoCwYuELCCBDPSg18__Tqs3kiAMHP6L14.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/default/files/php/twig/5ae1a97e5eec7_container.html.twig_5ytYVUs_gdkx819cOy1xqJ2Z_/i4IHyG5RlNmoCwYuELCCBDPSg18__Tqs3kiAMHP6L14.php Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,82 @@ +parent = false; + + $this->blocks = array( + ); + } + + protected function doDisplay(array $context, array $blocks = array()) + { + $tags = array("set" => 23); + $filters = array(); + $functions = array(); + + try { + $this->env->getExtension('Twig_Extension_Sandbox')->checkSecurity( + array('set'), + array(), + array() + ); + } catch (Twig_Sandbox_SecurityError $e) { + $e->setSourceContext($this->getSourceContext()); + + if ($e instanceof Twig_Sandbox_SecurityNotAllowedTagError && isset($tags[$e->getTagName()])) { + $e->setTemplateLine($tags[$e->getTagName()]); + } elseif ($e instanceof Twig_Sandbox_SecurityNotAllowedFilterError && isset($filters[$e->getFilterName()])) { + $e->setTemplateLine($filters[$e->getFilterName()]); + } elseif ($e instanceof Twig_Sandbox_SecurityNotAllowedFunctionError && isset($functions[$e->getFunctionName()])) { + $e->setTemplateLine($functions[$e->getFunctionName()]); + } + + throw $e; + } + + // line 23 + $context["classes"] = array(0 => (( // line 24 +($context["has_parent"] ?? null)) ? ("js-form-wrapper") : ("")), 1 => (( // line 25 +($context["has_parent"] ?? null)) ? ("form-wrapper") : (""))); + // line 28 + echo "env->getExtension('Twig_Extension_Sandbox')->ensureToStringAllowed($this->env->getExtension('Drupal\Core\Template\TwigExtension')->escapeFilter($this->env, $this->getAttribute(($context["attributes"] ?? null), "addClass", array(0 => ($context["classes"] ?? null)), "method"), "html", null, true)); + echo ">"; + echo $this->env->getExtension('Twig_Extension_Sandbox')->ensureToStringAllowed($this->env->getExtension('Drupal\Core\Template\TwigExtension')->escapeFilter($this->env, ($context["children"] ?? null), "html", null, true)); + echo " +"; + } + + public function getTemplateName() + { + return "core/themes/classy/templates/form/container.html.twig"; + } + + public function isTraitable() + { + return false; + } + + public function getDebugInfo() + { + return array ( 47 => 28, 45 => 25, 44 => 24, 43 => 23,); + } + + /** @deprecated since 1.27 (to be removed in 2.0). Use getSourceContext() instead */ + public function getSource() + { + @trigger_error('The '.__METHOD__.' method is deprecated since version 1.27 and will be removed in 2.0. Use getSourceContext() instead.', E_USER_DEPRECATED); + + return $this->getSourceContext()->getCode(); + } + + public function getSourceContext() + { + return new Twig_Source("", "core/themes/classy/templates/form/container.html.twig", "/var/www/sites/isophonics.net/core/themes/classy/templates/form/container.html.twig"); + } +} diff -r e200cb7efeb3 -r c2387f117808 sites/default/files/php/twig/5ae1a97e5eec7_form--search-block-form.h_YEtfwF0CQwlW4bNJjdBbzp2DC/.htaccess --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/default/files/php/twig/5ae1a97e5eec7_form--search-block-form.h_YEtfwF0CQwlW4bNJjdBbzp2DC/.htaccess Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,23 @@ +# Deny all requests from Apache 2.4+. + + Require all denied + + +# Deny all requests from Apache 2.0-2.2. + + Deny from all + +# Turn off all options we don't need. +Options -Indexes -ExecCGI -Includes -MultiViews + +# Set the catch-all handler to prevent scripts from being executed. +SetHandler Drupal_Security_Do_Not_Remove_See_SA_2006_006 + + # Override the handler again if we're run later in the evaluation list. + SetHandler Drupal_Security_Do_Not_Remove_See_SA_2013_003 + + +# If we know how to do it safely, disable the PHP engine entirely. + + php_flag engine off + \ No newline at end of file diff -r e200cb7efeb3 -r c2387f117808 sites/default/files/php/twig/5ae1a97e5eec7_form--search-block-form.h_YEtfwF0CQwlW4bNJjdBbzp2DC/up7vY4ZTZ7y4GFSVS0ZFP_UmocvkVoAV-oqLGm7zfeg.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/default/files/php/twig/5ae1a97e5eec7_form--search-block-form.h_YEtfwF0CQwlW4bNJjdBbzp2DC/up7vY4ZTZ7y4GFSVS0ZFP_UmocvkVoAV-oqLGm7zfeg.php Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,81 @@ +parent = false; + + $this->blocks = array( + ); + } + + protected function doDisplay(array $context, array $blocks = array()) + { + $tags = array(); + $filters = array(); + $functions = array(); + + try { + $this->env->getExtension('Twig_Extension_Sandbox')->checkSecurity( + array(), + array(), + array() + ); + } catch (Twig_Sandbox_SecurityError $e) { + $e->setSourceContext($this->getSourceContext()); + + if ($e instanceof Twig_Sandbox_SecurityNotAllowedTagError && isset($tags[$e->getTagName()])) { + $e->setTemplateLine($tags[$e->getTagName()]); + } elseif ($e instanceof Twig_Sandbox_SecurityNotAllowedFilterError && isset($filters[$e->getFilterName()])) { + $e->setTemplateLine($filters[$e->getFilterName()]); + } elseif ($e instanceof Twig_Sandbox_SecurityNotAllowedFunctionError && isset($functions[$e->getFunctionName()])) { + $e->setTemplateLine($functions[$e->getFunctionName()]); + } + + throw $e; + } + + // line 13 + echo "env->getExtension('Twig_Extension_Sandbox')->ensureToStringAllowed($this->env->getExtension('Drupal\Core\Template\TwigExtension')->escapeFilter($this->env, $this->getAttribute(($context["attributes"] ?? null), "addClass", array(0 => "search-form", 1 => "search-block-form"), "method"), "html", null, true)); + echo "> + "; + // line 14 + echo $this->env->getExtension('Twig_Extension_Sandbox')->ensureToStringAllowed($this->env->getExtension('Drupal\Core\Template\TwigExtension')->escapeFilter($this->env, ($context["children"] ?? null), "html", null, true)); + echo " + +"; + } + + public function getTemplateName() + { + return "themes/isobartik/templates/form--search-block-form.html.twig"; + } + + public function isTraitable() + { + return false; + } + + public function getDebugInfo() + { + return array ( 48 => 14, 43 => 13,); + } + + /** @deprecated since 1.27 (to be removed in 2.0). Use getSourceContext() instead */ + public function getSource() + { + @trigger_error('The '.__METHOD__.' method is deprecated since version 1.27 and will be removed in 2.0. Use getSourceContext() instead.', E_USER_DEPRECATED); + + return $this->getSourceContext()->getCode(); + } + + public function getSourceContext() + { + return new Twig_Source("", "themes/isobartik/templates/form--search-block-form.html.twig", "/var/www/sites/isophonics.net/themes/isobartik/templates/form--search-block-form.html.twig"); + } +} diff -r e200cb7efeb3 -r c2387f117808 sites/default/files/php/twig/5ae1a97e5eec7_form-element-label.html.t_LIUK9REF8eGBcgyB37knqChLi/.htaccess --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/default/files/php/twig/5ae1a97e5eec7_form-element-label.html.t_LIUK9REF8eGBcgyB37knqChLi/.htaccess Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,23 @@ +# Deny all requests from Apache 2.4+. + + Require all denied + + +# Deny all requests from Apache 2.0-2.2. + + Deny from all + +# Turn off all options we don't need. +Options -Indexes -ExecCGI -Includes -MultiViews + +# Set the catch-all handler to prevent scripts from being executed. +SetHandler Drupal_Security_Do_Not_Remove_See_SA_2006_006 + + # Override the handler again if we're run later in the evaluation list. + SetHandler Drupal_Security_Do_Not_Remove_See_SA_2013_003 + + +# If we know how to do it safely, disable the PHP engine entirely. + + php_flag engine off + \ No newline at end of file diff -r e200cb7efeb3 -r c2387f117808 sites/default/files/php/twig/5ae1a97e5eec7_form-element-label.html.t_LIUK9REF8eGBcgyB37knqChLi/uks9QsHDBYd-NzL6pRjx51nip0QAWd0VZT-DJpLDRh0.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/default/files/php/twig/5ae1a97e5eec7_form-element-label.html.t_LIUK9REF8eGBcgyB37knqChLi/uks9QsHDBYd-NzL6pRjx51nip0QAWd0VZT-DJpLDRh0.php Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,86 @@ +parent = false; + + $this->blocks = array( + ); + } + + protected function doDisplay(array $context, array $blocks = array()) + { + $tags = array("set" => 16, "if" => 23); + $filters = array(); + $functions = array(); + + try { + $this->env->getExtension('Twig_Extension_Sandbox')->checkSecurity( + array('set', 'if'), + array(), + array() + ); + } catch (Twig_Sandbox_SecurityError $e) { + $e->setSourceContext($this->getSourceContext()); + + if ($e instanceof Twig_Sandbox_SecurityNotAllowedTagError && isset($tags[$e->getTagName()])) { + $e->setTemplateLine($tags[$e->getTagName()]); + } elseif ($e instanceof Twig_Sandbox_SecurityNotAllowedFilterError && isset($filters[$e->getFilterName()])) { + $e->setTemplateLine($filters[$e->getFilterName()]); + } elseif ($e instanceof Twig_Sandbox_SecurityNotAllowedFunctionError && isset($functions[$e->getFunctionName()])) { + $e->setTemplateLine($functions[$e->getFunctionName()]); + } + + throw $e; + } + + // line 16 + $context["classes"] = array(0 => ((( // line 17 +($context["title_display"] ?? null) == "after")) ? ("option") : ("")), 1 => ((( // line 18 +($context["title_display"] ?? null) == "invisible")) ? ("visually-hidden") : ("")), 2 => (( // line 19 +($context["required"] ?? null)) ? ("js-form-required") : ("")), 3 => (( // line 20 +($context["required"] ?? null)) ? ("form-required") : (""))); + // line 23 + if (( !twig_test_empty(($context["title"] ?? null)) || ($context["required"] ?? null))) { + // line 24 + echo "env->getExtension('Twig_Extension_Sandbox')->ensureToStringAllowed($this->env->getExtension('Drupal\Core\Template\TwigExtension')->escapeFilter($this->env, $this->getAttribute(($context["attributes"] ?? null), "addClass", array(0 => ($context["classes"] ?? null)), "method"), "html", null, true)); + echo ">"; + echo $this->env->getExtension('Twig_Extension_Sandbox')->ensureToStringAllowed($this->env->getExtension('Drupal\Core\Template\TwigExtension')->escapeFilter($this->env, ($context["title"] ?? null), "html", null, true)); + echo ""; + } + } + + public function getTemplateName() + { + return "core/themes/classy/templates/form/form-element-label.html.twig"; + } + + public function isTraitable() + { + return false; + } + + public function getDebugInfo() + { + return array ( 51 => 24, 49 => 23, 47 => 20, 46 => 19, 45 => 18, 44 => 17, 43 => 16,); + } + + /** @deprecated since 1.27 (to be removed in 2.0). Use getSourceContext() instead */ + public function getSource() + { + @trigger_error('The '.__METHOD__.' method is deprecated since version 1.27 and will be removed in 2.0. Use getSourceContext() instead.', E_USER_DEPRECATED); + + return $this->getSourceContext()->getCode(); + } + + public function getSourceContext() + { + return new Twig_Source("", "core/themes/classy/templates/form/form-element-label.html.twig", "/var/www/sites/isophonics.net/core/themes/classy/templates/form/form-element-label.html.twig"); + } +} diff -r e200cb7efeb3 -r c2387f117808 sites/default/files/php/twig/5ae1a97e5eec7_form-element.html.twig_dJcTIbdx1y7B0dbOtEyyZSSZ1/.htaccess --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/default/files/php/twig/5ae1a97e5eec7_form-element.html.twig_dJcTIbdx1y7B0dbOtEyyZSSZ1/.htaccess Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,23 @@ +# Deny all requests from Apache 2.4+. + + Require all denied + + +# Deny all requests from Apache 2.0-2.2. + + Deny from all + +# Turn off all options we don't need. +Options -Indexes -ExecCGI -Includes -MultiViews + +# Set the catch-all handler to prevent scripts from being executed. +SetHandler Drupal_Security_Do_Not_Remove_See_SA_2006_006 + + # Override the handler again if we're run later in the evaluation list. + SetHandler Drupal_Security_Do_Not_Remove_See_SA_2013_003 + + +# If we know how to do it safely, disable the PHP engine entirely. + + php_flag engine off + \ No newline at end of file diff -r e200cb7efeb3 -r c2387f117808 sites/default/files/php/twig/5ae1a97e5eec7_form-element.html.twig_dJcTIbdx1y7B0dbOtEyyZSSZ1/SOBc-i-QBvfaX1TGlLcA_XLFeghitRDd0sm_5D_7Zug.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/default/files/php/twig/5ae1a97e5eec7_form-element.html.twig_dJcTIbdx1y7B0dbOtEyyZSSZ1/SOBc-i-QBvfaX1TGlLcA_XLFeghitRDd0sm_5D_7Zug.php Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,170 @@ +parent = false; + + $this->blocks = array( + ); + } + + protected function doDisplay(array $context, array $blocks = array()) + { + $tags = array("set" => 48, "if" => 67); + $filters = array("clean_class" => 51); + $functions = array(); + + try { + $this->env->getExtension('Twig_Extension_Sandbox')->checkSecurity( + array('set', 'if'), + array('clean_class'), + array() + ); + } catch (Twig_Sandbox_SecurityError $e) { + $e->setSourceContext($this->getSourceContext()); + + if ($e instanceof Twig_Sandbox_SecurityNotAllowedTagError && isset($tags[$e->getTagName()])) { + $e->setTemplateLine($tags[$e->getTagName()]); + } elseif ($e instanceof Twig_Sandbox_SecurityNotAllowedFilterError && isset($filters[$e->getFilterName()])) { + $e->setTemplateLine($filters[$e->getFilterName()]); + } elseif ($e instanceof Twig_Sandbox_SecurityNotAllowedFunctionError && isset($functions[$e->getFunctionName()])) { + $e->setTemplateLine($functions[$e->getFunctionName()]); + } + + throw $e; + } + + // line 48 + $context["classes"] = array(0 => "js-form-item", 1 => "form-item", 2 => ("js-form-type-" . \Drupal\Component\Utility\Html::getClass( // line 51 +($context["type"] ?? null))), 3 => ("form-type-" . \Drupal\Component\Utility\Html::getClass( // line 52 +($context["type"] ?? null))), 4 => ("js-form-item-" . \Drupal\Component\Utility\Html::getClass( // line 53 +($context["name"] ?? null))), 5 => ("form-item-" . \Drupal\Component\Utility\Html::getClass( // line 54 +($context["name"] ?? null))), 6 => ((!twig_in_filter( // line 55 +($context["title_display"] ?? null), array(0 => "after", 1 => "before"))) ? ("form-no-label") : ("")), 7 => ((( // line 56 +($context["disabled"] ?? null) == "disabled")) ? ("form-disabled") : ("")), 8 => (( // line 57 +($context["errors"] ?? null)) ? ("form-item--error") : (""))); + // line 61 + $context["description_classes"] = array(0 => "description", 1 => ((( // line 63 +($context["description_display"] ?? null) == "invisible")) ? ("visually-hidden") : (""))); + // line 66 + echo "env->getExtension('Twig_Extension_Sandbox')->ensureToStringAllowed($this->env->getExtension('Drupal\Core\Template\TwigExtension')->escapeFilter($this->env, $this->getAttribute(($context["attributes"] ?? null), "addClass", array(0 => ($context["classes"] ?? null)), "method"), "html", null, true)); + echo "> + "; + // line 67 + if (twig_in_filter(($context["label_display"] ?? null), array(0 => "before", 1 => "invisible"))) { + // line 68 + echo " "; + echo $this->env->getExtension('Twig_Extension_Sandbox')->ensureToStringAllowed($this->env->getExtension('Drupal\Core\Template\TwigExtension')->escapeFilter($this->env, ($context["label"] ?? null), "html", null, true)); + echo " + "; + } + // line 70 + echo " "; + if ( !twig_test_empty(($context["prefix"] ?? null))) { + // line 71 + echo " "; + echo $this->env->getExtension('Twig_Extension_Sandbox')->ensureToStringAllowed($this->env->getExtension('Drupal\Core\Template\TwigExtension')->escapeFilter($this->env, ($context["prefix"] ?? null), "html", null, true)); + echo " + "; + } + // line 73 + echo " "; + if (((($context["description_display"] ?? null) == "before") && $this->getAttribute(($context["description"] ?? null), "content", array()))) { + // line 74 + echo " env->getExtension('Twig_Extension_Sandbox')->ensureToStringAllowed($this->env->getExtension('Drupal\Core\Template\TwigExtension')->escapeFilter($this->env, $this->getAttribute(($context["description"] ?? null), "attributes", array()), "html", null, true)); + echo "> + "; + // line 75 + echo $this->env->getExtension('Twig_Extension_Sandbox')->ensureToStringAllowed($this->env->getExtension('Drupal\Core\Template\TwigExtension')->escapeFilter($this->env, $this->getAttribute(($context["description"] ?? null), "content", array()), "html", null, true)); + echo " + + "; + } + // line 78 + echo " "; + echo $this->env->getExtension('Twig_Extension_Sandbox')->ensureToStringAllowed($this->env->getExtension('Drupal\Core\Template\TwigExtension')->escapeFilter($this->env, ($context["children"] ?? null), "html", null, true)); + echo " + "; + // line 79 + if ( !twig_test_empty(($context["suffix"] ?? null))) { + // line 80 + echo " "; + echo $this->env->getExtension('Twig_Extension_Sandbox')->ensureToStringAllowed($this->env->getExtension('Drupal\Core\Template\TwigExtension')->escapeFilter($this->env, ($context["suffix"] ?? null), "html", null, true)); + echo " + "; + } + // line 82 + echo " "; + if ((($context["label_display"] ?? null) == "after")) { + // line 83 + echo " "; + echo $this->env->getExtension('Twig_Extension_Sandbox')->ensureToStringAllowed($this->env->getExtension('Drupal\Core\Template\TwigExtension')->escapeFilter($this->env, ($context["label"] ?? null), "html", null, true)); + echo " + "; + } + // line 85 + echo " "; + if (($context["errors"] ?? null)) { + // line 86 + echo "
        + "; + // line 87 + echo $this->env->getExtension('Twig_Extension_Sandbox')->ensureToStringAllowed($this->env->getExtension('Drupal\Core\Template\TwigExtension')->escapeFilter($this->env, ($context["errors"] ?? null), "html", null, true)); + echo " +
        + "; + } + // line 90 + echo " "; + if ((twig_in_filter(($context["description_display"] ?? null), array(0 => "after", 1 => "invisible")) && $this->getAttribute(($context["description"] ?? null), "content", array()))) { + // line 91 + echo " env->getExtension('Twig_Extension_Sandbox')->ensureToStringAllowed($this->env->getExtension('Drupal\Core\Template\TwigExtension')->escapeFilter($this->env, $this->getAttribute($this->getAttribute(($context["description"] ?? null), "attributes", array()), "addClass", array(0 => ($context["description_classes"] ?? null)), "method"), "html", null, true)); + echo "> + "; + // line 92 + echo $this->env->getExtension('Twig_Extension_Sandbox')->ensureToStringAllowed($this->env->getExtension('Drupal\Core\Template\TwigExtension')->escapeFilter($this->env, $this->getAttribute(($context["description"] ?? null), "content", array()), "html", null, true)); + echo " + + "; + } + // line 95 + echo " +"; + } + + public function getTemplateName() + { + return "core/themes/classy/templates/form/form-element.html.twig"; + } + + public function isTraitable() + { + return false; + } + + public function getDebugInfo() + { + return array ( 139 => 95, 133 => 92, 128 => 91, 125 => 90, 119 => 87, 116 => 86, 113 => 85, 107 => 83, 104 => 82, 98 => 80, 96 => 79, 91 => 78, 85 => 75, 80 => 74, 77 => 73, 71 => 71, 68 => 70, 62 => 68, 60 => 67, 55 => 66, 53 => 63, 52 => 61, 50 => 57, 49 => 56, 48 => 55, 47 => 54, 46 => 53, 45 => 52, 44 => 51, 43 => 48,); + } + + /** @deprecated since 1.27 (to be removed in 2.0). Use getSourceContext() instead */ + public function getSource() + { + @trigger_error('The '.__METHOD__.' method is deprecated since version 1.27 and will be removed in 2.0. Use getSourceContext() instead.', E_USER_DEPRECATED); + + return $this->getSourceContext()->getCode(); + } + + public function getSourceContext() + { + return new Twig_Source("", "core/themes/classy/templates/form/form-element.html.twig", "/var/www/sites/isophonics.net/core/themes/classy/templates/form/form-element.html.twig"); + } +} diff -r e200cb7efeb3 -r c2387f117808 sites/default/files/php/twig/5ae1a97e5eec7_form.html.twig_yB95M-mH2KEXj4tKtKISfLbel/.htaccess --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/default/files/php/twig/5ae1a97e5eec7_form.html.twig_yB95M-mH2KEXj4tKtKISfLbel/.htaccess Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,23 @@ +# Deny all requests from Apache 2.4+. + + Require all denied + + +# Deny all requests from Apache 2.0-2.2. + + Deny from all + +# Turn off all options we don't need. +Options -Indexes -ExecCGI -Includes -MultiViews + +# Set the catch-all handler to prevent scripts from being executed. +SetHandler Drupal_Security_Do_Not_Remove_See_SA_2006_006 + + # Override the handler again if we're run later in the evaluation list. + SetHandler Drupal_Security_Do_Not_Remove_See_SA_2013_003 + + +# If we know how to do it safely, disable the PHP engine entirely. + + php_flag engine off + \ No newline at end of file diff -r e200cb7efeb3 -r c2387f117808 sites/default/files/php/twig/5ae1a97e5eec7_form.html.twig_yB95M-mH2KEXj4tKtKISfLbel/a8CTtskS1LSFD3qpOIsRwIxbUhF8tg4RuntKIyFwf9Y.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/default/files/php/twig/5ae1a97e5eec7_form.html.twig_yB95M-mH2KEXj4tKtKISfLbel/a8CTtskS1LSFD3qpOIsRwIxbUhF8tg4RuntKIyFwf9Y.php Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,81 @@ +parent = false; + + $this->blocks = array( + ); + } + + protected function doDisplay(array $context, array $blocks = array()) + { + $tags = array(); + $filters = array(); + $functions = array(); + + try { + $this->env->getExtension('Twig_Extension_Sandbox')->checkSecurity( + array(), + array(), + array() + ); + } catch (Twig_Sandbox_SecurityError $e) { + $e->setSourceContext($this->getSourceContext()); + + if ($e instanceof Twig_Sandbox_SecurityNotAllowedTagError && isset($tags[$e->getTagName()])) { + $e->setTemplateLine($tags[$e->getTagName()]); + } elseif ($e instanceof Twig_Sandbox_SecurityNotAllowedFilterError && isset($filters[$e->getFilterName()])) { + $e->setTemplateLine($filters[$e->getFilterName()]); + } elseif ($e instanceof Twig_Sandbox_SecurityNotAllowedFunctionError && isset($functions[$e->getFunctionName()])) { + $e->setTemplateLine($functions[$e->getFunctionName()]); + } + + throw $e; + } + + // line 13 + echo "env->getExtension('Twig_Extension_Sandbox')->ensureToStringAllowed($this->env->getExtension('Drupal\Core\Template\TwigExtension')->escapeFilter($this->env, ($context["attributes"] ?? null), "html", null, true)); + echo "> + "; + // line 14 + echo $this->env->getExtension('Twig_Extension_Sandbox')->ensureToStringAllowed($this->env->getExtension('Drupal\Core\Template\TwigExtension')->escapeFilter($this->env, ($context["children"] ?? null), "html", null, true)); + echo " + +"; + } + + public function getTemplateName() + { + return "core/themes/classy/templates/form/form.html.twig"; + } + + public function isTraitable() + { + return false; + } + + public function getDebugInfo() + { + return array ( 48 => 14, 43 => 13,); + } + + /** @deprecated since 1.27 (to be removed in 2.0). Use getSourceContext() instead */ + public function getSource() + { + @trigger_error('The '.__METHOD__.' method is deprecated since version 1.27 and will be removed in 2.0. Use getSourceContext() instead.', E_USER_DEPRECATED); + + return $this->getSourceContext()->getCode(); + } + + public function getSourceContext() + { + return new Twig_Source("", "core/themes/classy/templates/form/form.html.twig", "/var/www/sites/isophonics.net/core/themes/classy/templates/form/form.html.twig"); + } +} diff -r e200cb7efeb3 -r c2387f117808 sites/default/files/php/twig/5ae1a97e5eec7_html.html.twig_gQv-GORxUVif_Pag4s-5z2NkO/.htaccess --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/default/files/php/twig/5ae1a97e5eec7_html.html.twig_gQv-GORxUVif_Pag4s-5z2NkO/.htaccess Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,23 @@ +# Deny all requests from Apache 2.4+. + + Require all denied + + +# Deny all requests from Apache 2.0-2.2. + + Deny from all + +# Turn off all options we don't need. +Options -Indexes -ExecCGI -Includes -MultiViews + +# Set the catch-all handler to prevent scripts from being executed. +SetHandler Drupal_Security_Do_Not_Remove_See_SA_2006_006 + + # Override the handler again if we're run later in the evaluation list. + SetHandler Drupal_Security_Do_Not_Remove_See_SA_2013_003 + + +# If we know how to do it safely, disable the PHP engine entirely. + + php_flag engine off + \ No newline at end of file diff -r e200cb7efeb3 -r c2387f117808 sites/default/files/php/twig/5ae1a97e5eec7_html.html.twig_gQv-GORxUVif_Pag4s-5z2NkO/eNdETkd2R_jnD9SrzAgGnxdALJLpgGTNZoZaD2VqNHA.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/default/files/php/twig/5ae1a97e5eec7_html.html.twig_gQv-GORxUVif_Pag4s-5z2NkO/eNdETkd2R_jnD9SrzAgGnxdALJLpgGTNZoZaD2VqNHA.php Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,132 @@ +parent = false; + + $this->blocks = array( + ); + } + + protected function doDisplay(array $context, array $blocks = array()) + { + $tags = array("set" => 27); + $filters = array("clean_class" => 29, "safe_join" => 38, "t" => 48); + $functions = array(); + + try { + $this->env->getExtension('Twig_Extension_Sandbox')->checkSecurity( + array('set'), + array('clean_class', 'safe_join', 't'), + array() + ); + } catch (Twig_Sandbox_SecurityError $e) { + $e->setSourceContext($this->getSourceContext()); + + if ($e instanceof Twig_Sandbox_SecurityNotAllowedTagError && isset($tags[$e->getTagName()])) { + $e->setTemplateLine($tags[$e->getTagName()]); + } elseif ($e instanceof Twig_Sandbox_SecurityNotAllowedFilterError && isset($filters[$e->getFilterName()])) { + $e->setTemplateLine($filters[$e->getFilterName()]); + } elseif ($e instanceof Twig_Sandbox_SecurityNotAllowedFunctionError && isset($functions[$e->getFunctionName()])) { + $e->setTemplateLine($functions[$e->getFunctionName()]); + } + + throw $e; + } + + // line 27 + $context["body_classes"] = array(0 => (( // line 28 +($context["logged_in"] ?? null)) ? ("user-logged-in") : ("")), 1 => (( ! // line 29 +($context["root_path"] ?? null)) ? ("path-frontpage") : (("path-" . \Drupal\Component\Utility\Html::getClass(($context["root_path"] ?? null))))), 2 => (( // line 30 +($context["node_type"] ?? null)) ? (("page-node-type-" . \Drupal\Component\Utility\Html::getClass(($context["node_type"] ?? null)))) : ("")), 3 => (( // line 31 +($context["db_offline"] ?? null)) ? ("db-offline") : (""))); + // line 34 + echo " +env->getExtension('Twig_Extension_Sandbox')->ensureToStringAllowed($this->env->getExtension('Drupal\Core\Template\TwigExtension')->escapeFilter($this->env, ($context["html_attributes"] ?? null), "html", null, true)); + echo "> + + env->getExtension('Twig_Extension_Sandbox')->ensureToStringAllowed($this->env->getExtension('Drupal\Core\Template\TwigExtension')->escapeFilter($this->env, ($context["placeholder_token"] ?? null), "html", null, true)); + echo "\"> + "; + // line 38 + echo $this->env->getExtension('Twig_Extension_Sandbox')->ensureToStringAllowed($this->env->getExtension('Drupal\Core\Template\TwigExtension')->renderVar($this->env->getExtension('Drupal\Core\Template\TwigExtension')->safeJoin($this->env, ($context["head_title"] ?? null), " | "))); + echo " + env->getExtension('Twig_Extension_Sandbox')->ensureToStringAllowed($this->env->getExtension('Drupal\Core\Template\TwigExtension')->escapeFilter($this->env, ($context["placeholder_token"] ?? null), "html", null, true)); + echo "\"> + env->getExtension('Twig_Extension_Sandbox')->ensureToStringAllowed($this->env->getExtension('Drupal\Core\Template\TwigExtension')->escapeFilter($this->env, ($context["placeholder_token"] ?? null), "html", null, true)); + echo "\"> + + env->getExtension('Twig_Extension_Sandbox')->ensureToStringAllowed($this->env->getExtension('Drupal\Core\Template\TwigExtension')->escapeFilter($this->env, $this->getAttribute(($context["attributes"] ?? null), "addClass", array(0 => ($context["body_classes"] ?? null)), "method"), "html", null, true)); + echo "> + "; + // line 47 + echo " + "; + // line 48 + echo $this->env->getExtension('Twig_Extension_Sandbox')->ensureToStringAllowed($this->env->getExtension('Drupal\Core\Template\TwigExtension')->renderVar(t("Skip to main content"))); + echo " + + "; + // line 50 + echo $this->env->getExtension('Twig_Extension_Sandbox')->ensureToStringAllowed($this->env->getExtension('Drupal\Core\Template\TwigExtension')->escapeFilter($this->env, ($context["page_top"] ?? null), "html", null, true)); + echo " + "; + // line 51 + echo $this->env->getExtension('Twig_Extension_Sandbox')->ensureToStringAllowed($this->env->getExtension('Drupal\Core\Template\TwigExtension')->escapeFilter($this->env, ($context["page"] ?? null), "html", null, true)); + echo " + "; + // line 52 + echo $this->env->getExtension('Twig_Extension_Sandbox')->ensureToStringAllowed($this->env->getExtension('Drupal\Core\Template\TwigExtension')->escapeFilter($this->env, ($context["page_bottom"] ?? null), "html", null, true)); + echo " + env->getExtension('Twig_Extension_Sandbox')->ensureToStringAllowed($this->env->getExtension('Drupal\Core\Template\TwigExtension')->escapeFilter($this->env, ($context["placeholder_token"] ?? null), "html", null, true)); + echo "\"> + + +"; + } + + public function getTemplateName() + { + return "core/themes/classy/templates/layout/html.html.twig"; + } + + public function isTraitable() + { + return false; + } + + public function getDebugInfo() + { + return array ( 98 => 53, 94 => 52, 90 => 51, 86 => 50, 81 => 48, 78 => 47, 74 => 42, 69 => 40, 65 => 39, 61 => 38, 57 => 37, 52 => 35, 49 => 34, 47 => 31, 46 => 30, 45 => 29, 44 => 28, 43 => 27,); + } + + /** @deprecated since 1.27 (to be removed in 2.0). Use getSourceContext() instead */ + public function getSource() + { + @trigger_error('The '.__METHOD__.' method is deprecated since version 1.27 and will be removed in 2.0. Use getSourceContext() instead.', E_USER_DEPRECATED); + + return $this->getSourceContext()->getCode(); + } + + public function getSourceContext() + { + return new Twig_Source("", "core/themes/classy/templates/layout/html.html.twig", "/var/www/sites/isophonics.net/core/themes/classy/templates/layout/html.html.twig"); + } +} diff -r e200cb7efeb3 -r c2387f117808 sites/default/files/php/twig/5ae1a97e5eec7_input.html.twig_jYi6QYvFpjKLYKZCId7BmHw8z/.htaccess --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/default/files/php/twig/5ae1a97e5eec7_input.html.twig_jYi6QYvFpjKLYKZCId7BmHw8z/.htaccess Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,23 @@ +# Deny all requests from Apache 2.4+. + + Require all denied + + +# Deny all requests from Apache 2.0-2.2. + + Deny from all + +# Turn off all options we don't need. +Options -Indexes -ExecCGI -Includes -MultiViews + +# Set the catch-all handler to prevent scripts from being executed. +SetHandler Drupal_Security_Do_Not_Remove_See_SA_2006_006 + + # Override the handler again if we're run later in the evaluation list. + SetHandler Drupal_Security_Do_Not_Remove_See_SA_2013_003 + + +# If we know how to do it safely, disable the PHP engine entirely. + + php_flag engine off + \ No newline at end of file diff -r e200cb7efeb3 -r c2387f117808 sites/default/files/php/twig/5ae1a97e5eec7_input.html.twig_jYi6QYvFpjKLYKZCId7BmHw8z/OzDG6lPg6C8EGFDnFWUB2igb68KN7-thoMg2YSzBAts.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/default/files/php/twig/5ae1a97e5eec7_input.html.twig_jYi6QYvFpjKLYKZCId7BmHw8z/OzDG6lPg6C8EGFDnFWUB2igb68KN7-thoMg2YSzBAts.php Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,78 @@ +parent = false; + + $this->blocks = array( + ); + } + + protected function doDisplay(array $context, array $blocks = array()) + { + $tags = array(); + $filters = array(); + $functions = array(); + + try { + $this->env->getExtension('Twig_Extension_Sandbox')->checkSecurity( + array(), + array(), + array() + ); + } catch (Twig_Sandbox_SecurityError $e) { + $e->setSourceContext($this->getSourceContext()); + + if ($e instanceof Twig_Sandbox_SecurityNotAllowedTagError && isset($tags[$e->getTagName()])) { + $e->setTemplateLine($tags[$e->getTagName()]); + } elseif ($e instanceof Twig_Sandbox_SecurityNotAllowedFilterError && isset($filters[$e->getFilterName()])) { + $e->setTemplateLine($filters[$e->getFilterName()]); + } elseif ($e instanceof Twig_Sandbox_SecurityNotAllowedFunctionError && isset($functions[$e->getFunctionName()])) { + $e->setTemplateLine($functions[$e->getFunctionName()]); + } + + throw $e; + } + + // line 13 + echo "env->getExtension('Twig_Extension_Sandbox')->ensureToStringAllowed($this->env->getExtension('Drupal\Core\Template\TwigExtension')->escapeFilter($this->env, ($context["attributes"] ?? null), "html", null, true)); + echo " />"; + echo $this->env->getExtension('Twig_Extension_Sandbox')->ensureToStringAllowed($this->env->getExtension('Drupal\Core\Template\TwigExtension')->escapeFilter($this->env, ($context["children"] ?? null), "html", null, true)); + echo " +"; + } + + public function getTemplateName() + { + return "core/themes/classy/templates/form/input.html.twig"; + } + + public function isTraitable() + { + return false; + } + + public function getDebugInfo() + { + return array ( 43 => 13,); + } + + /** @deprecated since 1.27 (to be removed in 2.0). Use getSourceContext() instead */ + public function getSource() + { + @trigger_error('The '.__METHOD__.' method is deprecated since version 1.27 and will be removed in 2.0. Use getSourceContext() instead.', E_USER_DEPRECATED); + + return $this->getSourceContext()->getCode(); + } + + public function getSourceContext() + { + return new Twig_Source("", "core/themes/classy/templates/form/input.html.twig", "/var/www/sites/isophonics.net/core/themes/classy/templates/form/input.html.twig"); + } +} diff -r e200cb7efeb3 -r c2387f117808 sites/default/files/php/twig/5ae1a97e5eec7_menu-local-task.html.twig_CyZBDRlpXnhaZDz3KzNHr4Ys1/.htaccess --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/default/files/php/twig/5ae1a97e5eec7_menu-local-task.html.twig_CyZBDRlpXnhaZDz3KzNHr4Ys1/.htaccess Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,23 @@ +# Deny all requests from Apache 2.4+. + + Require all denied + + +# Deny all requests from Apache 2.0-2.2. + + Deny from all + +# Turn off all options we don't need. +Options -Indexes -ExecCGI -Includes -MultiViews + +# Set the catch-all handler to prevent scripts from being executed. +SetHandler Drupal_Security_Do_Not_Remove_See_SA_2006_006 + + # Override the handler again if we're run later in the evaluation list. + SetHandler Drupal_Security_Do_Not_Remove_See_SA_2013_003 + + +# If we know how to do it safely, disable the PHP engine entirely. + + php_flag engine off + \ No newline at end of file diff -r e200cb7efeb3 -r c2387f117808 sites/default/files/php/twig/5ae1a97e5eec7_menu-local-task.html.twig_CyZBDRlpXnhaZDz3KzNHr4Ys1/ZwzBaM75XXHT6_IlUOuBG3KN6XBTm1gUeJtD3Lpryck.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/default/files/php/twig/5ae1a97e5eec7_menu-local-task.html.twig_CyZBDRlpXnhaZDz3KzNHr4Ys1/ZwzBaM75XXHT6_IlUOuBG3KN6XBTm1gUeJtD3Lpryck.php Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,78 @@ +parent = false; + + $this->blocks = array( + ); + } + + protected function doDisplay(array $context, array $blocks = array()) + { + $tags = array(); + $filters = array(); + $functions = array(); + + try { + $this->env->getExtension('Twig_Extension_Sandbox')->checkSecurity( + array(), + array(), + array() + ); + } catch (Twig_Sandbox_SecurityError $e) { + $e->setSourceContext($this->getSourceContext()); + + if ($e instanceof Twig_Sandbox_SecurityNotAllowedTagError && isset($tags[$e->getTagName()])) { + $e->setTemplateLine($tags[$e->getTagName()]); + } elseif ($e instanceof Twig_Sandbox_SecurityNotAllowedFilterError && isset($filters[$e->getFilterName()])) { + $e->setTemplateLine($filters[$e->getFilterName()]); + } elseif ($e instanceof Twig_Sandbox_SecurityNotAllowedFunctionError && isset($functions[$e->getFunctionName()])) { + $e->setTemplateLine($functions[$e->getFunctionName()]); + } + + throw $e; + } + + // line 17 + echo "env->getExtension('Twig_Extension_Sandbox')->ensureToStringAllowed($this->env->getExtension('Drupal\Core\Template\TwigExtension')->escapeFilter($this->env, $this->getAttribute(($context["attributes"] ?? null), "addClass", array(0 => ((($context["is_active"] ?? null)) ? ("is-active") : (""))), "method"), "html", null, true)); + echo ">"; + echo $this->env->getExtension('Twig_Extension_Sandbox')->ensureToStringAllowed($this->env->getExtension('Drupal\Core\Template\TwigExtension')->escapeFilter($this->env, ($context["link"] ?? null), "html", null, true)); + echo " +"; + } + + public function getTemplateName() + { + return "core/themes/classy/templates/navigation/menu-local-task.html.twig"; + } + + public function isTraitable() + { + return false; + } + + public function getDebugInfo() + { + return array ( 43 => 17,); + } + + /** @deprecated since 1.27 (to be removed in 2.0). Use getSourceContext() instead */ + public function getSource() + { + @trigger_error('The '.__METHOD__.' method is deprecated since version 1.27 and will be removed in 2.0. Use getSourceContext() instead.', E_USER_DEPRECATED); + + return $this->getSourceContext()->getCode(); + } + + public function getSourceContext() + { + return new Twig_Source("", "core/themes/classy/templates/navigation/menu-local-task.html.twig", "/var/www/sites/isophonics.net/core/themes/classy/templates/navigation/menu-local-task.html.twig"); + } +} diff -r e200cb7efeb3 -r c2387f117808 sites/default/files/php/twig/5ae1a97e5eec7_menu-local-tasks.html.twi_-U9q0KfMoCml9W-9XJZZCwICm/.htaccess --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/default/files/php/twig/5ae1a97e5eec7_menu-local-tasks.html.twi_-U9q0KfMoCml9W-9XJZZCwICm/.htaccess Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,23 @@ +# Deny all requests from Apache 2.4+. + + Require all denied + + +# Deny all requests from Apache 2.0-2.2. + + Deny from all + +# Turn off all options we don't need. +Options -Indexes -ExecCGI -Includes -MultiViews + +# Set the catch-all handler to prevent scripts from being executed. +SetHandler Drupal_Security_Do_Not_Remove_See_SA_2006_006 + + # Override the handler again if we're run later in the evaluation list. + SetHandler Drupal_Security_Do_Not_Remove_See_SA_2013_003 + + +# If we know how to do it safely, disable the PHP engine entirely. + + php_flag engine off + \ No newline at end of file diff -r e200cb7efeb3 -r c2387f117808 sites/default/files/php/twig/5ae1a97e5eec7_menu-local-tasks.html.twi_-U9q0KfMoCml9W-9XJZZCwICm/KEqm5dQCZ2W2krd2QoYb_e3yGNlV38q3Ci1C0XPRsS4.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/default/files/php/twig/5ae1a97e5eec7_menu-local-tasks.html.twi_-U9q0KfMoCml9W-9XJZZCwICm/KEqm5dQCZ2W2krd2QoYb_e3yGNlV38q3Ci1C0XPRsS4.php Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,95 @@ +parent = false; + + $this->blocks = array( + ); + } + + protected function doDisplay(array $context, array $blocks = array()) + { + $tags = array("if" => 14); + $filters = array("t" => 15); + $functions = array(); + + try { + $this->env->getExtension('Twig_Extension_Sandbox')->checkSecurity( + array('if'), + array('t'), + array() + ); + } catch (Twig_Sandbox_SecurityError $e) { + $e->setSourceContext($this->getSourceContext()); + + if ($e instanceof Twig_Sandbox_SecurityNotAllowedTagError && isset($tags[$e->getTagName()])) { + $e->setTemplateLine($tags[$e->getTagName()]); + } elseif ($e instanceof Twig_Sandbox_SecurityNotAllowedFilterError && isset($filters[$e->getFilterName()])) { + $e->setTemplateLine($filters[$e->getFilterName()]); + } elseif ($e instanceof Twig_Sandbox_SecurityNotAllowedFunctionError && isset($functions[$e->getFunctionName()])) { + $e->setTemplateLine($functions[$e->getFunctionName()]); + } + + throw $e; + } + + // line 14 + if (($context["primary"] ?? null)) { + // line 15 + echo "

        "; + echo $this->env->getExtension('Twig_Extension_Sandbox')->ensureToStringAllowed($this->env->getExtension('Drupal\Core\Template\TwigExtension')->renderVar(t("Primary tabs"))); + echo "

        +
          "; + // line 16 + echo $this->env->getExtension('Twig_Extension_Sandbox')->ensureToStringAllowed($this->env->getExtension('Drupal\Core\Template\TwigExtension')->escapeFilter($this->env, ($context["primary"] ?? null), "html", null, true)); + echo "
        +"; + } + // line 18 + if (($context["secondary"] ?? null)) { + // line 19 + echo "

        "; + echo $this->env->getExtension('Twig_Extension_Sandbox')->ensureToStringAllowed($this->env->getExtension('Drupal\Core\Template\TwigExtension')->renderVar(t("Secondary tabs"))); + echo "

        +
          "; + // line 20 + echo $this->env->getExtension('Twig_Extension_Sandbox')->ensureToStringAllowed($this->env->getExtension('Drupal\Core\Template\TwigExtension')->escapeFilter($this->env, ($context["secondary"] ?? null), "html", null, true)); + echo "
        +"; + } + } + + public function getTemplateName() + { + return "core/themes/classy/templates/navigation/menu-local-tasks.html.twig"; + } + + public function isTraitable() + { + return false; + } + + public function getDebugInfo() + { + return array ( 62 => 20, 57 => 19, 55 => 18, 50 => 16, 45 => 15, 43 => 14,); + } + + /** @deprecated since 1.27 (to be removed in 2.0). Use getSourceContext() instead */ + public function getSource() + { + @trigger_error('The '.__METHOD__.' method is deprecated since version 1.27 and will be removed in 2.0. Use getSourceContext() instead.', E_USER_DEPRECATED); + + return $this->getSourceContext()->getCode(); + } + + public function getSourceContext() + { + return new Twig_Source("", "core/themes/classy/templates/navigation/menu-local-tasks.html.twig", "/var/www/sites/isophonics.net/core/themes/classy/templates/navigation/menu-local-tasks.html.twig"); + } +} diff -r e200cb7efeb3 -r c2387f117808 sites/default/files/php/twig/5ae1a97e5eec7_menu.html.twig_6_49nUJrABYdgsuH1VhK8sIfM/.htaccess --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/default/files/php/twig/5ae1a97e5eec7_menu.html.twig_6_49nUJrABYdgsuH1VhK8sIfM/.htaccess Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,23 @@ +# Deny all requests from Apache 2.4+. + + Require all denied + + +# Deny all requests from Apache 2.0-2.2. + + Deny from all + +# Turn off all options we don't need. +Options -Indexes -ExecCGI -Includes -MultiViews + +# Set the catch-all handler to prevent scripts from being executed. +SetHandler Drupal_Security_Do_Not_Remove_See_SA_2006_006 + + # Override the handler again if we're run later in the evaluation list. + SetHandler Drupal_Security_Do_Not_Remove_See_SA_2013_003 + + +# If we know how to do it safely, disable the PHP engine entirely. + + php_flag engine off + \ No newline at end of file diff -r e200cb7efeb3 -r c2387f117808 sites/default/files/php/twig/5ae1a97e5eec7_menu.html.twig_6_49nUJrABYdgsuH1VhK8sIfM/9VYD6i2o2sKzUrOl8BE22vtNeeo4mVlqxq8EO1zoX1w.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/default/files/php/twig/5ae1a97e5eec7_menu.html.twig_6_49nUJrABYdgsuH1VhK8sIfM/9VYD6i2o2sKzUrOl8BE22vtNeeo4mVlqxq8EO1zoX1w.php Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,167 @@ +parent = false; + + $this->blocks = array( + ); + } + + protected function doDisplay(array $context, array $blocks = array()) + { + $tags = array("import" => 21, "macro" => 29, "if" => 31, "for" => 37, "set" => 39); + $filters = array(); + $functions = array("link" => 47); + + try { + $this->env->getExtension('Twig_Extension_Sandbox')->checkSecurity( + array('import', 'macro', 'if', 'for', 'set'), + array(), + array('link') + ); + } catch (Twig_Sandbox_SecurityError $e) { + $e->setSourceContext($this->getSourceContext()); + + if ($e instanceof Twig_Sandbox_SecurityNotAllowedTagError && isset($tags[$e->getTagName()])) { + $e->setTemplateLine($tags[$e->getTagName()]); + } elseif ($e instanceof Twig_Sandbox_SecurityNotAllowedFilterError && isset($filters[$e->getFilterName()])) { + $e->setTemplateLine($filters[$e->getFilterName()]); + } elseif ($e instanceof Twig_Sandbox_SecurityNotAllowedFunctionError && isset($functions[$e->getFunctionName()])) { + $e->setTemplateLine($functions[$e->getFunctionName()]); + } + + throw $e; + } + + // line 21 + $context["menus"] = $this; + // line 22 + echo " +"; + // line 27 + echo $this->env->getExtension('Twig_Extension_Sandbox')->ensureToStringAllowed($this->env->getExtension('Drupal\Core\Template\TwigExtension')->renderVar($context["menus"]->getmenu_links(($context["items"] ?? null), ($context["attributes"] ?? null), 0))); + echo " + +"; + } + + // line 29 + public function getmenu_links($__items__ = null, $__attributes__ = null, $__menu_level__ = null, ...$__varargs__) + { + $context = $this->env->mergeGlobals(array( + "items" => $__items__, + "attributes" => $__attributes__, + "menu_level" => $__menu_level__, + "varargs" => $__varargs__, + )); + + $blocks = array(); + + ob_start(); + try { + // line 30 + echo " "; + $context["menus"] = $this; + // line 31 + echo " "; + if (($context["items"] ?? null)) { + // line 32 + echo " "; + if ((($context["menu_level"] ?? null) == 0)) { + // line 33 + echo " env->getExtension('Twig_Extension_Sandbox')->ensureToStringAllowed($this->env->getExtension('Drupal\Core\Template\TwigExtension')->escapeFilter($this->env, $this->getAttribute(($context["attributes"] ?? null), "addClass", array(0 => "menu"), "method"), "html", null, true)); + echo "> + "; + } else { + // line 35 + echo "
          + "; + } + // line 37 + echo " "; + $context['_parent'] = $context; + $context['_seq'] = twig_ensure_traversable(($context["items"] ?? null)); + foreach ($context['_seq'] as $context["_key"] => $context["item"]) { + // line 38 + echo " "; + // line 39 + $context["classes"] = array(0 => "menu-item", 1 => (($this->getAttribute( // line 41 +$context["item"], "is_expanded", array())) ? ("menu-item--expanded") : ("")), 2 => (($this->getAttribute( // line 42 +$context["item"], "is_collapsed", array())) ? ("menu-item--collapsed") : ("")), 3 => (($this->getAttribute( // line 43 +$context["item"], "in_active_trail", array())) ? ("menu-item--active-trail") : (""))); + // line 46 + echo " env->getExtension('Twig_Extension_Sandbox')->ensureToStringAllowed($this->env->getExtension('Drupal\Core\Template\TwigExtension')->escapeFilter($this->env, $this->getAttribute($this->getAttribute($context["item"], "attributes", array()), "addClass", array(0 => ($context["classes"] ?? null)), "method"), "html", null, true)); + echo "> + "; + // line 47 + echo $this->env->getExtension('Twig_Extension_Sandbox')->ensureToStringAllowed($this->env->getExtension('Drupal\Core\Template\TwigExtension')->escapeFilter($this->env, $this->env->getExtension('Drupal\Core\Template\TwigExtension')->getLink($this->getAttribute($context["item"], "title", array()), $this->getAttribute($context["item"], "url", array())), "html", null, true)); + echo " + "; + // line 48 + if ($this->getAttribute($context["item"], "below", array())) { + // line 49 + echo " "; + echo $this->env->getExtension('Twig_Extension_Sandbox')->ensureToStringAllowed($this->env->getExtension('Drupal\Core\Template\TwigExtension')->renderVar($context["menus"]->getmenu_links($this->getAttribute($context["item"], "below", array()), ($context["attributes"] ?? null), (($context["menu_level"] ?? null) + 1)))); + echo " + "; + } + // line 51 + echo " + "; + } + $_parent = $context['_parent']; + unset($context['_seq'], $context['_iterated'], $context['_key'], $context['item'], $context['_parent'], $context['loop']); + $context = array_intersect_key($context, $_parent) + $_parent; + // line 53 + echo "
        + "; + } + } catch (Exception $e) { + ob_end_clean(); + + throw $e; + } catch (Throwable $e) { + ob_end_clean(); + + throw $e; + } + + return ('' === $tmp = ob_get_clean()) ? '' : new Twig_Markup($tmp, $this->env->getCharset()); + } + + public function getTemplateName() + { + return "core/themes/classy/templates/navigation/menu.html.twig"; + } + + public function isTraitable() + { + return false; + } + + public function getDebugInfo() + { + return array ( 124 => 53, 117 => 51, 111 => 49, 109 => 48, 105 => 47, 100 => 46, 98 => 43, 97 => 42, 96 => 41, 95 => 39, 93 => 38, 88 => 37, 84 => 35, 78 => 33, 75 => 32, 72 => 31, 69 => 30, 55 => 29, 48 => 27, 45 => 22, 43 => 21,); + } + + /** @deprecated since 1.27 (to be removed in 2.0). Use getSourceContext() instead */ + public function getSource() + { + @trigger_error('The '.__METHOD__.' method is deprecated since version 1.27 and will be removed in 2.0. Use getSourceContext() instead.', E_USER_DEPRECATED); + + return $this->getSourceContext()->getCode(); + } + + public function getSourceContext() + { + return new Twig_Source("", "core/themes/classy/templates/navigation/menu.html.twig", "/var/www/sites/isophonics.net/core/themes/classy/templates/navigation/menu.html.twig"); + } +} diff -r e200cb7efeb3 -r c2387f117808 sites/default/files/php/twig/5ae1a97e5eec7_off-canvas-page-wrapper.h_hlAfqNqVOta6cQY1nMpQqxAZ7/.htaccess --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/default/files/php/twig/5ae1a97e5eec7_off-canvas-page-wrapper.h_hlAfqNqVOta6cQY1nMpQqxAZ7/.htaccess Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,23 @@ +# Deny all requests from Apache 2.4+. + + Require all denied + + +# Deny all requests from Apache 2.0-2.2. + + Deny from all + +# Turn off all options we don't need. +Options -Indexes -ExecCGI -Includes -MultiViews + +# Set the catch-all handler to prevent scripts from being executed. +SetHandler Drupal_Security_Do_Not_Remove_See_SA_2006_006 + + # Override the handler again if we're run later in the evaluation list. + SetHandler Drupal_Security_Do_Not_Remove_See_SA_2013_003 + + +# If we know how to do it safely, disable the PHP engine entirely. + + php_flag engine off + \ No newline at end of file diff -r e200cb7efeb3 -r c2387f117808 sites/default/files/php/twig/5ae1a97e5eec7_off-canvas-page-wrapper.h_hlAfqNqVOta6cQY1nMpQqxAZ7/M8_wQQUqYpxlSF9oUmploIzz2nu09Laqa23c-iJivjQ.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/default/files/php/twig/5ae1a97e5eec7_off-canvas-page-wrapper.h_hlAfqNqVOta6cQY1nMpQqxAZ7/M8_wQQUqYpxlSF9oUmploIzz2nu09Laqa23c-iJivjQ.php Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,82 @@ +parent = false; + + $this->blocks = array( + ); + } + + protected function doDisplay(array $context, array $blocks = array()) + { + $tags = array("if" => 20); + $filters = array(); + $functions = array(); + + try { + $this->env->getExtension('Twig_Extension_Sandbox')->checkSecurity( + array('if'), + array(), + array() + ); + } catch (Twig_Sandbox_SecurityError $e) { + $e->setSourceContext($this->getSourceContext()); + + if ($e instanceof Twig_Sandbox_SecurityNotAllowedTagError && isset($tags[$e->getTagName()])) { + $e->setTemplateLine($tags[$e->getTagName()]); + } elseif ($e instanceof Twig_Sandbox_SecurityNotAllowedFilterError && isset($filters[$e->getFilterName()])) { + $e->setTemplateLine($filters[$e->getFilterName()]); + } elseif ($e instanceof Twig_Sandbox_SecurityNotAllowedFunctionError && isset($functions[$e->getFunctionName()])) { + $e->setTemplateLine($functions[$e->getFunctionName()]); + } + + throw $e; + } + + // line 20 + if (($context["children"] ?? null)) { + // line 21 + echo "
        + "; + // line 22 + echo $this->env->getExtension('Twig_Extension_Sandbox')->ensureToStringAllowed($this->env->getExtension('Drupal\Core\Template\TwigExtension')->escapeFilter($this->env, ($context["children"] ?? null), "html", null, true)); + echo " +
        +"; + } + } + + public function getTemplateName() + { + return "core/themes/stable/templates/content/off-canvas-page-wrapper.html.twig"; + } + + public function isTraitable() + { + return false; + } + + public function getDebugInfo() + { + return array ( 48 => 22, 45 => 21, 43 => 20,); + } + + /** @deprecated since 1.27 (to be removed in 2.0). Use getSourceContext() instead */ + public function getSource() + { + @trigger_error('The '.__METHOD__.' method is deprecated since version 1.27 and will be removed in 2.0. Use getSourceContext() instead.', E_USER_DEPRECATED); + + return $this->getSourceContext()->getCode(); + } + + public function getSourceContext() + { + return new Twig_Source("", "core/themes/stable/templates/content/off-canvas-page-wrapper.html.twig", "/var/www/sites/isophonics.net/core/themes/stable/templates/content/off-canvas-page-wrapper.html.twig"); + } +} diff -r e200cb7efeb3 -r c2387f117808 sites/default/files/php/twig/5ae1a97e5eec7_page-title.html.twig_5-d0Vm9L73Nnquj8G5WDwO2eX/.htaccess --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/default/files/php/twig/5ae1a97e5eec7_page-title.html.twig_5-d0Vm9L73Nnquj8G5WDwO2eX/.htaccess Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,23 @@ +# Deny all requests from Apache 2.4+. + + Require all denied + + +# Deny all requests from Apache 2.0-2.2. + + Deny from all + +# Turn off all options we don't need. +Options -Indexes -ExecCGI -Includes -MultiViews + +# Set the catch-all handler to prevent scripts from being executed. +SetHandler Drupal_Security_Do_Not_Remove_See_SA_2006_006 + + # Override the handler again if we're run later in the evaluation list. + SetHandler Drupal_Security_Do_Not_Remove_See_SA_2013_003 + + +# If we know how to do it safely, disable the PHP engine entirely. + + php_flag engine off + \ No newline at end of file diff -r e200cb7efeb3 -r c2387f117808 sites/default/files/php/twig/5ae1a97e5eec7_page-title.html.twig_5-d0Vm9L73Nnquj8G5WDwO2eX/zx-qW1pC1Nehz8rH9_1qvPbLjVa04qMbzOppllvG_TA.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/default/files/php/twig/5ae1a97e5eec7_page-title.html.twig_5-d0Vm9L73Nnquj8G5WDwO2eX/zx-qW1pC1Nehz8rH9_1qvPbLjVa04qMbzOppllvG_TA.php Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,80 @@ +parent = $this->loadTemplate("@classy/content/page-title.html.twig", "themes/isobartik/templates/page-title.html.twig", 1); + $this->blocks = array( + ); + } + + protected function doGetParent(array $context) + { + return "@classy/content/page-title.html.twig"; + } + + protected function doDisplay(array $context, array $blocks = array()) + { + $tags = array("set" => 16); + $filters = array(); + $functions = array(); + + try { + $this->env->getExtension('Twig_Extension_Sandbox')->checkSecurity( + array('set'), + array(), + array() + ); + } catch (Twig_Sandbox_SecurityError $e) { + $e->setSourceContext($this->getSourceContext()); + + if ($e instanceof Twig_Sandbox_SecurityNotAllowedTagError && isset($tags[$e->getTagName()])) { + $e->setTemplateLine($tags[$e->getTagName()]); + } elseif ($e instanceof Twig_Sandbox_SecurityNotAllowedFilterError && isset($filters[$e->getFilterName()])) { + $e->setTemplateLine($filters[$e->getFilterName()]); + } elseif ($e instanceof Twig_Sandbox_SecurityNotAllowedFunctionError && isset($functions[$e->getFunctionName()])) { + $e->setTemplateLine($functions[$e->getFunctionName()]); + } + + throw $e; + } + + // line 16 + $context["title_attributes"] = $this->getAttribute(($context["title_attributes"] ?? null), "addClass", array(0 => "title"), "method"); + // line 1 + $this->parent->display($context, array_merge($this->blocks, $blocks)); + } + + public function getTemplateName() + { + return "themes/isobartik/templates/page-title.html.twig"; + } + + public function isTraitable() + { + return false; + } + + public function getDebugInfo() + { + return array ( 50 => 1, 48 => 16, 11 => 1,); + } + + /** @deprecated since 1.27 (to be removed in 2.0). Use getSourceContext() instead */ + public function getSource() + { + @trigger_error('The '.__METHOD__.' method is deprecated since version 1.27 and will be removed in 2.0. Use getSourceContext() instead.', E_USER_DEPRECATED); + + return $this->getSourceContext()->getCode(); + } + + public function getSourceContext() + { + return new Twig_Source("", "themes/isobartik/templates/page-title.html.twig", "/var/www/sites/isophonics.net/themes/isobartik/templates/page-title.html.twig"); + } +} diff -r e200cb7efeb3 -r c2387f117808 sites/default/files/php/twig/5ae1a97e5eec7_page-title.html.twig_Kj22JzrbuWqFmqffbsmZOndRV/.htaccess --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/default/files/php/twig/5ae1a97e5eec7_page-title.html.twig_Kj22JzrbuWqFmqffbsmZOndRV/.htaccess Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,23 @@ +# Deny all requests from Apache 2.4+. + + Require all denied + + +# Deny all requests from Apache 2.0-2.2. + + Deny from all + +# Turn off all options we don't need. +Options -Indexes -ExecCGI -Includes -MultiViews + +# Set the catch-all handler to prevent scripts from being executed. +SetHandler Drupal_Security_Do_Not_Remove_See_SA_2006_006 + + # Override the handler again if we're run later in the evaluation list. + SetHandler Drupal_Security_Do_Not_Remove_See_SA_2013_003 + + +# If we know how to do it safely, disable the PHP engine entirely. + + php_flag engine off + \ No newline at end of file diff -r e200cb7efeb3 -r c2387f117808 sites/default/files/php/twig/5ae1a97e5eec7_page-title.html.twig_Kj22JzrbuWqFmqffbsmZOndRV/5st7ktq4Qr_Vi3Qzwz0rtVDZEuY1-nluYdtL5cWWWMc.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/default/files/php/twig/5ae1a97e5eec7_page-title.html.twig_Kj22JzrbuWqFmqffbsmZOndRV/5st7ktq4Qr_Vi3Qzwz0rtVDZEuY1-nluYdtL5cWWWMc.php Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,89 @@ +parent = false; + + $this->blocks = array( + ); + } + + protected function doDisplay(array $context, array $blocks = array()) + { + $tags = array("if" => 16); + $filters = array(); + $functions = array(); + + try { + $this->env->getExtension('Twig_Extension_Sandbox')->checkSecurity( + array('if'), + array(), + array() + ); + } catch (Twig_Sandbox_SecurityError $e) { + $e->setSourceContext($this->getSourceContext()); + + if ($e instanceof Twig_Sandbox_SecurityNotAllowedTagError && isset($tags[$e->getTagName()])) { + $e->setTemplateLine($tags[$e->getTagName()]); + } elseif ($e instanceof Twig_Sandbox_SecurityNotAllowedFilterError && isset($filters[$e->getFilterName()])) { + $e->setTemplateLine($filters[$e->getFilterName()]); + } elseif ($e instanceof Twig_Sandbox_SecurityNotAllowedFunctionError && isset($functions[$e->getFunctionName()])) { + $e->setTemplateLine($functions[$e->getFunctionName()]); + } + + throw $e; + } + + // line 15 + echo $this->env->getExtension('Twig_Extension_Sandbox')->ensureToStringAllowed($this->env->getExtension('Drupal\Core\Template\TwigExtension')->escapeFilter($this->env, ($context["title_prefix"] ?? null), "html", null, true)); + echo " +"; + // line 16 + if (($context["title"] ?? null)) { + // line 17 + echo " env->getExtension('Twig_Extension_Sandbox')->ensureToStringAllowed($this->env->getExtension('Drupal\Core\Template\TwigExtension')->escapeFilter($this->env, $this->getAttribute(($context["title_attributes"] ?? null), "addClass", array(0 => "page-title"), "method"), "html", null, true)); + echo ">"; + echo $this->env->getExtension('Twig_Extension_Sandbox')->ensureToStringAllowed($this->env->getExtension('Drupal\Core\Template\TwigExtension')->escapeFilter($this->env, ($context["title"] ?? null), "html", null, true)); + echo " +"; + } + // line 19 + echo $this->env->getExtension('Twig_Extension_Sandbox')->ensureToStringAllowed($this->env->getExtension('Drupal\Core\Template\TwigExtension')->escapeFilter($this->env, ($context["title_suffix"] ?? null), "html", null, true)); + echo " +"; + } + + public function getTemplateName() + { + return "@classy/content/page-title.html.twig"; + } + + public function isTraitable() + { + return false; + } + + public function getDebugInfo() + { + return array ( 57 => 19, 49 => 17, 47 => 16, 43 => 15,); + } + + /** @deprecated since 1.27 (to be removed in 2.0). Use getSourceContext() instead */ + public function getSource() + { + @trigger_error('The '.__METHOD__.' method is deprecated since version 1.27 and will be removed in 2.0. Use getSourceContext() instead.', E_USER_DEPRECATED); + + return $this->getSourceContext()->getCode(); + } + + public function getSourceContext() + { + return new Twig_Source("", "@classy/content/page-title.html.twig", "/var/www/sites/isophonics.net/core/themes/classy/templates/content/page-title.html.twig"); + } +} diff -r e200cb7efeb3 -r c2387f117808 sites/default/files/php/twig/5ae1a97e5eec7_page.html.twig_izP4tzIqfiN5N6VS1seT4HkZg/.htaccess --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/default/files/php/twig/5ae1a97e5eec7_page.html.twig_izP4tzIqfiN5N6VS1seT4HkZg/.htaccess Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,23 @@ +# Deny all requests from Apache 2.4+. + + Require all denied + + +# Deny all requests from Apache 2.0-2.2. + + Deny from all + +# Turn off all options we don't need. +Options -Indexes -ExecCGI -Includes -MultiViews + +# Set the catch-all handler to prevent scripts from being executed. +SetHandler Drupal_Security_Do_Not_Remove_See_SA_2006_006 + + # Override the handler again if we're run later in the evaluation list. + SetHandler Drupal_Security_Do_Not_Remove_See_SA_2013_003 + + +# If we know how to do it safely, disable the PHP engine entirely. + + php_flag engine off + \ No newline at end of file diff -r e200cb7efeb3 -r c2387f117808 sites/default/files/php/twig/5ae1a97e5eec7_page.html.twig_izP4tzIqfiN5N6VS1seT4HkZg/sb0KXBEnCUkwWJ5hcpXwI79gMYkoDNsthfJaXAY2qOQ.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/default/files/php/twig/5ae1a97e5eec7_page.html.twig_izP4tzIqfiN5N6VS1seT4HkZg/sb0KXBEnCUkwWJ5hcpXwI79gMYkoDNsthfJaXAY2qOQ.php Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,235 @@ +parent = false; + + $this->blocks = array( + ); + } + + protected function doDisplay(array $context, array $blocks = array()) + { + $tags = array("if" => 62); + $filters = array("t" => 55); + $functions = array(); + + try { + $this->env->getExtension('Twig_Extension_Sandbox')->checkSecurity( + array('if'), + array('t'), + array() + ); + } catch (Twig_Sandbox_SecurityError $e) { + $e->setSourceContext($this->getSourceContext()); + + if ($e instanceof Twig_Sandbox_SecurityNotAllowedTagError && isset($tags[$e->getTagName()])) { + $e->setTemplateLine($tags[$e->getTagName()]); + } elseif ($e instanceof Twig_Sandbox_SecurityNotAllowedFilterError && isset($filters[$e->getFilterName()])) { + $e->setTemplateLine($filters[$e->getFilterName()]); + } elseif ($e instanceof Twig_Sandbox_SecurityNotAllowedFunctionError && isset($functions[$e->getFunctionName()])) { + $e->setTemplateLine($functions[$e->getFunctionName()]); + } + + throw $e; + } + + // line 53 + echo "
        +
        +
        env->getExtension('Twig_Extension_Sandbox')->ensureToStringAllowed($this->env->getExtension('Drupal\Core\Template\TwigExtension')->renderVar(t("Site header"))); + echo "\"> +
        + "; + // line 57 + echo $this->env->getExtension('Twig_Extension_Sandbox')->ensureToStringAllowed($this->env->getExtension('Drupal\Core\Template\TwigExtension')->escapeFilter($this->env, $this->getAttribute(($context["page"] ?? null), "secondary_menu", array()), "html", null, true)); + echo " + "; + // line 58 + echo $this->env->getExtension('Twig_Extension_Sandbox')->ensureToStringAllowed($this->env->getExtension('Drupal\Core\Template\TwigExtension')->escapeFilter($this->env, $this->getAttribute(($context["page"] ?? null), "header", array()), "html", null, true)); + echo " + "; + // line 59 + echo $this->env->getExtension('Twig_Extension_Sandbox')->ensureToStringAllowed($this->env->getExtension('Drupal\Core\Template\TwigExtension')->escapeFilter($this->env, $this->getAttribute(($context["page"] ?? null), "primary_menu", array()), "html", null, true)); + echo " +
        +
        + "; + // line 62 + if ($this->getAttribute(($context["page"] ?? null), "highlighted", array())) { + // line 63 + echo "
        + +
        + "; + } + // line 69 + echo " "; + if ($this->getAttribute(($context["page"] ?? null), "featured_top", array())) { + // line 70 + echo "
        + +
        + "; + } + // line 76 + echo "
        +
        + "; + // line 78 + echo $this->env->getExtension('Twig_Extension_Sandbox')->ensureToStringAllowed($this->env->getExtension('Drupal\Core\Template\TwigExtension')->escapeFilter($this->env, $this->getAttribute(($context["page"] ?? null), "breadcrumb", array()), "html", null, true)); + echo " +
        +
        + + "; + // line 82 + echo $this->env->getExtension('Twig_Extension_Sandbox')->ensureToStringAllowed($this->env->getExtension('Drupal\Core\Template\TwigExtension')->escapeFilter($this->env, $this->getAttribute(($context["page"] ?? null), "content", array()), "html", null, true)); + echo " +
        +
        + "; + // line 85 + if ($this->getAttribute(($context["page"] ?? null), "sidebar_first", array())) { + // line 86 + echo "
        + +
        + "; + } + // line 92 + echo " "; + if ($this->getAttribute(($context["page"] ?? null), "sidebar_second", array())) { + // line 93 + echo "
        + +
        + "; + } + // line 99 + echo "
        +
        + "; + // line 101 + if ((($this->getAttribute(($context["page"] ?? null), "featured_bottom_first", array()) || $this->getAttribute(($context["page"] ?? null), "featured_bottom_second", array())) || $this->getAttribute(($context["page"] ?? null), "featured_bottom_third", array()))) { + // line 102 + echo "
        + +
        + "; + } + // line 110 + echo "
        +
        + "; + // line 112 + if (((($this->getAttribute(($context["page"] ?? null), "footer_first", array()) || $this->getAttribute(($context["page"] ?? null), "footer_second", array())) || $this->getAttribute(($context["page"] ?? null), "footer_third", array())) || $this->getAttribute(($context["page"] ?? null), "footer_fourth", array()))) { + // line 113 + echo " + "; + } + // line 120 + echo " "; + if ($this->getAttribute(($context["page"] ?? null), "footer_fifth", array())) { + // line 121 + echo " + "; + } + // line 125 + echo "
        +
        +
        +
        +"; + } + + public function getTemplateName() + { + return "themes/isobartik/templates/page.html.twig"; + } + + public function isTraitable() + { + return false; + } + + public function getDebugInfo() + { + return array ( 201 => 125, 195 => 122, 192 => 121, 189 => 120, 183 => 117, 179 => 116, 175 => 115, 171 => 114, 168 => 113, 166 => 112, 162 => 110, 155 => 106, 151 => 105, 147 => 104, 143 => 102, 141 => 101, 137 => 99, 130 => 95, 126 => 93, 123 => 92, 116 => 88, 112 => 86, 110 => 85, 104 => 82, 97 => 78, 93 => 76, 86 => 72, 82 => 70, 79 => 69, 72 => 65, 68 => 63, 66 => 62, 60 => 59, 56 => 58, 52 => 57, 47 => 55, 43 => 53,); + } + + /** @deprecated since 1.27 (to be removed in 2.0). Use getSourceContext() instead */ + public function getSource() + { + @trigger_error('The '.__METHOD__.' method is deprecated since version 1.27 and will be removed in 2.0. Use getSourceContext() instead.', E_USER_DEPRECATED); + + return $this->getSourceContext()->getCode(); + } + + public function getSourceContext() + { + return new Twig_Source("", "themes/isobartik/templates/page.html.twig", "/var/www/sites/isophonics.net/themes/isobartik/templates/page.html.twig"); + } +} diff -r e200cb7efeb3 -r c2387f117808 sites/default/files/php/twig/5ae1a97e5eec7_region.html.twig_MR3fMmw95qbpuDFvbyuI9QHlG/.htaccess --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/default/files/php/twig/5ae1a97e5eec7_region.html.twig_MR3fMmw95qbpuDFvbyuI9QHlG/.htaccess Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,23 @@ +# Deny all requests from Apache 2.4+. + + Require all denied + + +# Deny all requests from Apache 2.0-2.2. + + Deny from all + +# Turn off all options we don't need. +Options -Indexes -ExecCGI -Includes -MultiViews + +# Set the catch-all handler to prevent scripts from being executed. +SetHandler Drupal_Security_Do_Not_Remove_See_SA_2006_006 + + # Override the handler again if we're run later in the evaluation list. + SetHandler Drupal_Security_Do_Not_Remove_See_SA_2013_003 + + +# If we know how to do it safely, disable the PHP engine entirely. + + php_flag engine off + \ No newline at end of file diff -r e200cb7efeb3 -r c2387f117808 sites/default/files/php/twig/5ae1a97e5eec7_region.html.twig_MR3fMmw95qbpuDFvbyuI9QHlG/QOakA_jtMJUQJaPygOnIUWxX8g6e4Wie2dNXnfz8qGs.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/default/files/php/twig/5ae1a97e5eec7_region.html.twig_MR3fMmw95qbpuDFvbyuI9QHlG/QOakA_jtMJUQJaPygOnIUWxX8g6e4Wie2dNXnfz8qGs.php Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,87 @@ +parent = false; + + $this->blocks = array( + ); + } + + protected function doDisplay(array $context, array $blocks = array()) + { + $tags = array("set" => 16, "if" => 21); + $filters = array("clean_class" => 18); + $functions = array(); + + try { + $this->env->getExtension('Twig_Extension_Sandbox')->checkSecurity( + array('set', 'if'), + array('clean_class'), + array() + ); + } catch (Twig_Sandbox_SecurityError $e) { + $e->setSourceContext($this->getSourceContext()); + + if ($e instanceof Twig_Sandbox_SecurityNotAllowedTagError && isset($tags[$e->getTagName()])) { + $e->setTemplateLine($tags[$e->getTagName()]); + } elseif ($e instanceof Twig_Sandbox_SecurityNotAllowedFilterError && isset($filters[$e->getFilterName()])) { + $e->setTemplateLine($filters[$e->getFilterName()]); + } elseif ($e instanceof Twig_Sandbox_SecurityNotAllowedFunctionError && isset($functions[$e->getFunctionName()])) { + $e->setTemplateLine($functions[$e->getFunctionName()]); + } + + throw $e; + } + + // line 16 + $context["classes"] = array(0 => "region", 1 => ("region-" . \Drupal\Component\Utility\Html::getClass( // line 18 +($context["region"] ?? null)))); + // line 21 + if (($context["content"] ?? null)) { + // line 22 + echo " env->getExtension('Twig_Extension_Sandbox')->ensureToStringAllowed($this->env->getExtension('Drupal\Core\Template\TwigExtension')->escapeFilter($this->env, $this->getAttribute(($context["attributes"] ?? null), "addClass", array(0 => ($context["classes"] ?? null)), "method"), "html", null, true)); + echo "> + "; + // line 23 + echo $this->env->getExtension('Twig_Extension_Sandbox')->ensureToStringAllowed($this->env->getExtension('Drupal\Core\Template\TwigExtension')->escapeFilter($this->env, ($context["content"] ?? null), "html", null, true)); + echo " + +"; + } + } + + public function getTemplateName() + { + return "core/themes/classy/templates/layout/region.html.twig"; + } + + public function isTraitable() + { + return false; + } + + public function getDebugInfo() + { + return array ( 53 => 23, 48 => 22, 46 => 21, 44 => 18, 43 => 16,); + } + + /** @deprecated since 1.27 (to be removed in 2.0). Use getSourceContext() instead */ + public function getSource() + { + @trigger_error('The '.__METHOD__.' method is deprecated since version 1.27 and will be removed in 2.0. Use getSourceContext() instead.', E_USER_DEPRECATED); + + return $this->getSourceContext()->getCode(); + } + + public function getSourceContext() + { + return new Twig_Source("", "core/themes/classy/templates/layout/region.html.twig", "/var/www/sites/isophonics.net/core/themes/classy/templates/layout/region.html.twig"); + } +} diff -r e200cb7efeb3 -r c2387f117808 sites/default/files/php/twig/5ae1a97e5eec7_status-messages.html.twig_3IhisVoQLOYIb64NBegMDuHJs/.htaccess --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/default/files/php/twig/5ae1a97e5eec7_status-messages.html.twig_3IhisVoQLOYIb64NBegMDuHJs/.htaccess Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,23 @@ +# Deny all requests from Apache 2.4+. + + Require all denied + + +# Deny all requests from Apache 2.0-2.2. + + Deny from all + +# Turn off all options we don't need. +Options -Indexes -ExecCGI -Includes -MultiViews + +# Set the catch-all handler to prevent scripts from being executed. +SetHandler Drupal_Security_Do_Not_Remove_See_SA_2006_006 + + # Override the handler again if we're run later in the evaluation list. + SetHandler Drupal_Security_Do_Not_Remove_See_SA_2013_003 + + +# If we know how to do it safely, disable the PHP engine entirely. + + php_flag engine off + \ No newline at end of file diff -r e200cb7efeb3 -r c2387f117808 sites/default/files/php/twig/5ae1a97e5eec7_status-messages.html.twig_3IhisVoQLOYIb64NBegMDuHJs/lvyWodQowrG4hh-5oPuNcJZiFzJ8EWTh3ShV7eo6mSc.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/default/files/php/twig/5ae1a97e5eec7_status-messages.html.twig_3IhisVoQLOYIb64NBegMDuHJs/lvyWodQowrG4hh-5oPuNcJZiFzJ8EWTh3ShV7eo6mSc.php Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,150 @@ +parent = false; + + $this->blocks = array( + 'messages' => array($this, 'block_messages'), + ); + } + + protected function doDisplay(array $context, array $blocks = array()) + { + $tags = array("block" => 24, "for" => 25, "set" => 27, "if" => 33); + $filters = array("without" => 32, "length" => 39, "first" => 46); + $functions = array(); + + try { + $this->env->getExtension('Twig_Extension_Sandbox')->checkSecurity( + array('block', 'for', 'set', 'if'), + array('without', 'length', 'first'), + array() + ); + } catch (Twig_Sandbox_SecurityError $e) { + $e->setSourceContext($this->getSourceContext()); + + if ($e instanceof Twig_Sandbox_SecurityNotAllowedTagError && isset($tags[$e->getTagName()])) { + $e->setTemplateLine($tags[$e->getTagName()]); + } elseif ($e instanceof Twig_Sandbox_SecurityNotAllowedFilterError && isset($filters[$e->getFilterName()])) { + $e->setTemplateLine($filters[$e->getFilterName()]); + } elseif ($e instanceof Twig_Sandbox_SecurityNotAllowedFunctionError && isset($functions[$e->getFunctionName()])) { + $e->setTemplateLine($functions[$e->getFunctionName()]); + } + + throw $e; + } + + // line 24 + $this->displayBlock('messages', $context, $blocks); + } + + public function block_messages($context, array $blocks = array()) + { + // line 25 + $context['_parent'] = $context; + $context['_seq'] = twig_ensure_traversable(($context["message_list"] ?? null)); + foreach ($context['_seq'] as $context["type"] => $context["messages"]) { + // line 26 + echo " "; + // line 27 + $context["classes"] = array(0 => "messages", 1 => ("messages--" . // line 29 +$context["type"])); + // line 32 + echo "
        env->getExtension('Twig_Extension_Sandbox')->ensureToStringAllowed($this->env->getExtension('Drupal\Core\Template\TwigExtension')->escapeFilter($this->env, $this->getAttribute(($context["status_headings"] ?? null), $context["type"], array(), "array"), "html", null, true)); + echo "\""; + echo $this->env->getExtension('Twig_Extension_Sandbox')->ensureToStringAllowed($this->env->getExtension('Drupal\Core\Template\TwigExtension')->escapeFilter($this->env, twig_without($this->getAttribute(($context["attributes"] ?? null), "addClass", array(0 => ($context["classes"] ?? null)), "method"), "role", "aria-label"), "html", null, true)); + echo "> + "; + // line 33 + if (($context["type"] == "error")) { + // line 34 + echo "
        + "; + } + // line 36 + echo " "; + if ($this->getAttribute(($context["status_headings"] ?? null), $context["type"], array(), "array")) { + // line 37 + echo "

        "; + echo $this->env->getExtension('Twig_Extension_Sandbox')->ensureToStringAllowed($this->env->getExtension('Drupal\Core\Template\TwigExtension')->escapeFilter($this->env, $this->getAttribute(($context["status_headings"] ?? null), $context["type"], array(), "array"), "html", null, true)); + echo "

        + "; + } + // line 39 + echo " "; + if ((twig_length_filter($this->env, $context["messages"]) > 1)) { + // line 40 + echo "
          + "; + // line 41 + $context['_parent'] = $context; + $context['_seq'] = twig_ensure_traversable($context["messages"]); + foreach ($context['_seq'] as $context["_key"] => $context["message"]) { + // line 42 + echo "
        • "; + echo $this->env->getExtension('Twig_Extension_Sandbox')->ensureToStringAllowed($this->env->getExtension('Drupal\Core\Template\TwigExtension')->escapeFilter($this->env, $context["message"], "html", null, true)); + echo "
        • + "; + } + $_parent = $context['_parent']; + unset($context['_seq'], $context['_iterated'], $context['_key'], $context['message'], $context['_parent'], $context['loop']); + $context = array_intersect_key($context, $_parent) + $_parent; + // line 44 + echo "
        + "; + } else { + // line 46 + echo " "; + echo $this->env->getExtension('Twig_Extension_Sandbox')->ensureToStringAllowed($this->env->getExtension('Drupal\Core\Template\TwigExtension')->escapeFilter($this->env, twig_first($this->env, $context["messages"]), "html", null, true)); + echo " + "; + } + // line 48 + echo " "; + if (($context["type"] == "error")) { + // line 49 + echo "
        + "; + } + // line 51 + echo "
        + "; + // line 53 + echo " "; + $context["attributes"] = $this->getAttribute(($context["attributes"] ?? null), "removeClass", array(0 => ($context["classes"] ?? null)), "method"); + } + $_parent = $context['_parent']; + unset($context['_seq'], $context['_iterated'], $context['type'], $context['messages'], $context['_parent'], $context['loop']); + $context = array_intersect_key($context, $_parent) + $_parent; + } + + public function getTemplateName() + { + return "@classy/misc/status-messages.html.twig"; + } + + public function getDebugInfo() + { + return array ( 120 => 53, 117 => 51, 113 => 49, 110 => 48, 104 => 46, 100 => 44, 91 => 42, 87 => 41, 84 => 40, 81 => 39, 75 => 37, 72 => 36, 68 => 34, 66 => 33, 59 => 32, 57 => 29, 56 => 27, 54 => 26, 50 => 25, 44 => 24,); + } + + /** @deprecated since 1.27 (to be removed in 2.0). Use getSourceContext() instead */ + public function getSource() + { + @trigger_error('The '.__METHOD__.' method is deprecated since version 1.27 and will be removed in 2.0. Use getSourceContext() instead.', E_USER_DEPRECATED); + + return $this->getSourceContext()->getCode(); + } + + public function getSourceContext() + { + return new Twig_Source("", "@classy/misc/status-messages.html.twig", "/var/www/sites/isophonics.net/core/themes/classy/templates/misc/status-messages.html.twig"); + } +} diff -r e200cb7efeb3 -r c2387f117808 sites/default/files/php/twig/5ae1a97e5eec7_status-messages.html.twig_zEur8QZ9MtyIcD_RVkfsdP3I0/.htaccess --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/default/files/php/twig/5ae1a97e5eec7_status-messages.html.twig_zEur8QZ9MtyIcD_RVkfsdP3I0/.htaccess Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,23 @@ +# Deny all requests from Apache 2.4+. + + Require all denied + + +# Deny all requests from Apache 2.0-2.2. + + Deny from all + +# Turn off all options we don't need. +Options -Indexes -ExecCGI -Includes -MultiViews + +# Set the catch-all handler to prevent scripts from being executed. +SetHandler Drupal_Security_Do_Not_Remove_See_SA_2006_006 + + # Override the handler again if we're run later in the evaluation list. + SetHandler Drupal_Security_Do_Not_Remove_See_SA_2013_003 + + +# If we know how to do it safely, disable the PHP engine entirely. + + php_flag engine off + \ No newline at end of file diff -r e200cb7efeb3 -r c2387f117808 sites/default/files/php/twig/5ae1a97e5eec7_status-messages.html.twig_zEur8QZ9MtyIcD_RVkfsdP3I0/ElXAaxcRKibZXf0JAKpdfnnuZErCyU_PrS44Y2Bpa3k.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/default/files/php/twig/5ae1a97e5eec7_status-messages.html.twig_zEur8QZ9MtyIcD_RVkfsdP3I0/ElXAaxcRKibZXf0JAKpdfnnuZErCyU_PrS44Y2Bpa3k.php Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,98 @@ +parent = $this->loadTemplate("@classy/misc/status-messages.html.twig", "themes/isobartik/templates/status-messages.html.twig", 1); + $this->blocks = array( + 'messages' => array($this, 'block_messages'), + ); + } + + protected function doGetParent(array $context) + { + return "@classy/misc/status-messages.html.twig"; + } + + protected function doDisplay(array $context, array $blocks = array()) + { + $tags = array("if" => 24); + $filters = array(); + $functions = array("attach_library" => 25); + + try { + $this->env->getExtension('Twig_Extension_Sandbox')->checkSecurity( + array('if'), + array(), + array('attach_library') + ); + } catch (Twig_Sandbox_SecurityError $e) { + $e->setSourceContext($this->getSourceContext()); + + if ($e instanceof Twig_Sandbox_SecurityNotAllowedTagError && isset($tags[$e->getTagName()])) { + $e->setTemplateLine($tags[$e->getTagName()]); + } elseif ($e instanceof Twig_Sandbox_SecurityNotAllowedFilterError && isset($filters[$e->getFilterName()])) { + $e->setTemplateLine($filters[$e->getFilterName()]); + } elseif ($e instanceof Twig_Sandbox_SecurityNotAllowedFunctionError && isset($functions[$e->getFunctionName()])) { + $e->setTemplateLine($functions[$e->getFunctionName()]); + } + + throw $e; + } + + $this->parent->display($context, array_merge($this->blocks, $blocks)); + } + + // line 23 + public function block_messages($context, array $blocks = array()) + { + // line 24 + echo " "; + if ( !twig_test_empty(($context["message_list"] ?? null))) { + // line 25 + echo " "; + echo $this->env->getExtension('Twig_Extension_Sandbox')->ensureToStringAllowed($this->env->getExtension('Drupal\Core\Template\TwigExtension')->escapeFilter($this->env, $this->env->getExtension('Drupal\Core\Template\TwigExtension')->attachLibrary("isobartik/messages"), "html", null, true)); + echo " +
        + "; + // line 27 + $this->displayParentBlock("messages", $context, $blocks); + echo " +
        + "; + } + } + + public function getTemplateName() + { + return "themes/isobartik/templates/status-messages.html.twig"; + } + + public function isTraitable() + { + return false; + } + + public function getDebugInfo() + { + return array ( 64 => 27, 58 => 25, 55 => 24, 52 => 23, 11 => 1,); + } + + /** @deprecated since 1.27 (to be removed in 2.0). Use getSourceContext() instead */ + public function getSource() + { + @trigger_error('The '.__METHOD__.' method is deprecated since version 1.27 and will be removed in 2.0. Use getSourceContext() instead.', E_USER_DEPRECATED); + + return $this->getSourceContext()->getCode(); + } + + public function getSourceContext() + { + return new Twig_Source("", "themes/isobartik/templates/status-messages.html.twig", "/var/www/sites/isophonics.net/themes/isobartik/templates/status-messages.html.twig"); + } +} diff -r e200cb7efeb3 -r c2387f117808 sites/default/files/php/twig/5b44bda38f6c8_block.html.twig_CIz2o0S3PkA8DW5E6V6XtYLjI/.htaccess --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/default/files/php/twig/5b44bda38f6c8_block.html.twig_CIz2o0S3PkA8DW5E6V6XtYLjI/.htaccess Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,23 @@ +# Deny all requests from Apache 2.4+. + + Require all denied + + +# Deny all requests from Apache 2.0-2.2. + + Deny from all + +# Turn off all options we don't need. +Options -Indexes -ExecCGI -Includes -MultiViews + +# Set the catch-all handler to prevent scripts from being executed. +SetHandler Drupal_Security_Do_Not_Remove_See_SA_2006_006 + + # Override the handler again if we're run later in the evaluation list. + SetHandler Drupal_Security_Do_Not_Remove_See_SA_2013_003 + + +# If we know how to do it safely, disable the PHP engine entirely. + + php_flag engine off + \ No newline at end of file diff -r e200cb7efeb3 -r c2387f117808 sites/default/files/php/twig/5b44bda38f6c8_block.html.twig_CIz2o0S3PkA8DW5E6V6XtYLjI/HBJNMGOfoSfKlyav41gABYm4Nrgcx61H3uuRSWgtW_k.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/default/files/php/twig/5b44bda38f6c8_block.html.twig_CIz2o0S3PkA8DW5E6V6XtYLjI/HBJNMGOfoSfKlyav41gABYm4Nrgcx61H3uuRSWgtW_k.php Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,120 @@ +parent = false; + + $this->blocks = array( + 'content' => array($this, 'block_content'), + ); + } + + protected function doDisplay(array $context, array $blocks = array()) + { + $tags = array("set" => 33, "if" => 41, "block" => 45); + $filters = array("clean_class" => 35); + $functions = array(); + + try { + $this->env->getExtension('Twig_Extension_Sandbox')->checkSecurity( + array('set', 'if', 'block'), + array('clean_class'), + array() + ); + } catch (Twig_Sandbox_SecurityError $e) { + $e->setSourceContext($this->getSourceContext()); + + if ($e instanceof Twig_Sandbox_SecurityNotAllowedTagError && isset($tags[$e->getTagName()])) { + $e->setTemplateLine($tags[$e->getTagName()]); + } elseif ($e instanceof Twig_Sandbox_SecurityNotAllowedFilterError && isset($filters[$e->getFilterName()])) { + $e->setTemplateLine($filters[$e->getFilterName()]); + } elseif ($e instanceof Twig_Sandbox_SecurityNotAllowedFunctionError && isset($functions[$e->getFunctionName()])) { + $e->setTemplateLine($functions[$e->getFunctionName()]); + } + + throw $e; + } + + // line 33 + $context["classes"] = array(0 => "block", 1 => ("block-" . \Drupal\Component\Utility\Html::getClass($this->getAttribute( // line 35 +($context["configuration"] ?? null), "provider", array()))), 2 => ("block-" . \Drupal\Component\Utility\Html::getClass( // line 36 +($context["plugin_id"] ?? null)))); + // line 39 + echo "env->getExtension('Twig_Extension_Sandbox')->ensureToStringAllowed($this->env->getExtension('Drupal\Core\Template\TwigExtension')->escapeFilter($this->env, $this->getAttribute(($context["attributes"] ?? null), "addClass", array(0 => ($context["classes"] ?? null)), "method"), "html", null, true)); + echo "> + "; + // line 40 + echo $this->env->getExtension('Twig_Extension_Sandbox')->ensureToStringAllowed($this->env->getExtension('Drupal\Core\Template\TwigExtension')->escapeFilter($this->env, ($context["title_prefix"] ?? null), "html", null, true)); + echo " + "; + // line 41 + if (($context["label"] ?? null)) { + // line 42 + echo " env->getExtension('Twig_Extension_Sandbox')->ensureToStringAllowed($this->env->getExtension('Drupal\Core\Template\TwigExtension')->escapeFilter($this->env, ($context["title_attributes"] ?? null), "html", null, true)); + echo ">"; + echo $this->env->getExtension('Twig_Extension_Sandbox')->ensureToStringAllowed($this->env->getExtension('Drupal\Core\Template\TwigExtension')->escapeFilter($this->env, ($context["label"] ?? null), "html", null, true)); + echo " + "; + } + // line 44 + echo " "; + echo $this->env->getExtension('Twig_Extension_Sandbox')->ensureToStringAllowed($this->env->getExtension('Drupal\Core\Template\TwigExtension')->escapeFilter($this->env, ($context["title_suffix"] ?? null), "html", null, true)); + echo " + "; + // line 45 + $this->displayBlock('content', $context, $blocks); + // line 50 + echo " +"; + } + + // line 45 + public function block_content($context, array $blocks = array()) + { + // line 46 + echo " env->getExtension('Twig_Extension_Sandbox')->ensureToStringAllowed($this->env->getExtension('Drupal\Core\Template\TwigExtension')->escapeFilter($this->env, $this->getAttribute(($context["content_attributes"] ?? null), "addClass", array(0 => "content"), "method"), "html", null, true)); + echo "> + "; + // line 47 + echo $this->env->getExtension('Twig_Extension_Sandbox')->ensureToStringAllowed($this->env->getExtension('Drupal\Core\Template\TwigExtension')->escapeFilter($this->env, ($context["content"] ?? null), "html", null, true)); + echo " + + "; + } + + public function getTemplateName() + { + return "themes/isobartik/templates/block.html.twig"; + } + + public function isTraitable() + { + return false; + } + + public function getDebugInfo() + { + return array ( 87 => 47, 82 => 46, 79 => 45, 74 => 50, 72 => 45, 67 => 44, 59 => 42, 57 => 41, 53 => 40, 48 => 39, 46 => 36, 45 => 35, 44 => 33,); + } + + /** @deprecated since 1.27 (to be removed in 2.0). Use getSourceContext() instead */ + public function getSource() + { + @trigger_error('The '.__METHOD__.' method is deprecated since version 1.27 and will be removed in 2.0. Use getSourceContext() instead.', E_USER_DEPRECATED); + + return $this->getSourceContext()->getCode(); + } + + public function getSourceContext() + { + return new Twig_Source("", "themes/isobartik/templates/block.html.twig", "/var/www/sites/isophonics.net/themes/isobartik/templates/block.html.twig"); + } +} diff -r e200cb7efeb3 -r c2387f117808 sites/default/files/php/twig/5b44bda38f6c8_container.html.twig_5ytYVUs_gdkx819cOy1xqJ2Z_/.htaccess --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/default/files/php/twig/5b44bda38f6c8_container.html.twig_5ytYVUs_gdkx819cOy1xqJ2Z_/.htaccess Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,23 @@ +# Deny all requests from Apache 2.4+. + + Require all denied + + +# Deny all requests from Apache 2.0-2.2. + + Deny from all + +# Turn off all options we don't need. +Options -Indexes -ExecCGI -Includes -MultiViews + +# Set the catch-all handler to prevent scripts from being executed. +SetHandler Drupal_Security_Do_Not_Remove_See_SA_2006_006 + + # Override the handler again if we're run later in the evaluation list. + SetHandler Drupal_Security_Do_Not_Remove_See_SA_2013_003 + + +# If we know how to do it safely, disable the PHP engine entirely. + + php_flag engine off + \ No newline at end of file diff -r e200cb7efeb3 -r c2387f117808 sites/default/files/php/twig/5b44bda38f6c8_container.html.twig_5ytYVUs_gdkx819cOy1xqJ2Z_/L6TOgbaEF9pWX_DVhgHbAMGukuG4XUsi-mbdCJ4O4Xg.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/default/files/php/twig/5b44bda38f6c8_container.html.twig_5ytYVUs_gdkx819cOy1xqJ2Z_/L6TOgbaEF9pWX_DVhgHbAMGukuG4XUsi-mbdCJ4O4Xg.php Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,82 @@ +parent = false; + + $this->blocks = array( + ); + } + + protected function doDisplay(array $context, array $blocks = array()) + { + $tags = array("set" => 23); + $filters = array(); + $functions = array(); + + try { + $this->env->getExtension('Twig_Extension_Sandbox')->checkSecurity( + array('set'), + array(), + array() + ); + } catch (Twig_Sandbox_SecurityError $e) { + $e->setSourceContext($this->getSourceContext()); + + if ($e instanceof Twig_Sandbox_SecurityNotAllowedTagError && isset($tags[$e->getTagName()])) { + $e->setTemplateLine($tags[$e->getTagName()]); + } elseif ($e instanceof Twig_Sandbox_SecurityNotAllowedFilterError && isset($filters[$e->getFilterName()])) { + $e->setTemplateLine($filters[$e->getFilterName()]); + } elseif ($e instanceof Twig_Sandbox_SecurityNotAllowedFunctionError && isset($functions[$e->getFunctionName()])) { + $e->setTemplateLine($functions[$e->getFunctionName()]); + } + + throw $e; + } + + // line 23 + $context["classes"] = array(0 => (( // line 24 +($context["has_parent"] ?? null)) ? ("js-form-wrapper") : ("")), 1 => (( // line 25 +($context["has_parent"] ?? null)) ? ("form-wrapper") : (""))); + // line 28 + echo "env->getExtension('Twig_Extension_Sandbox')->ensureToStringAllowed($this->env->getExtension('Drupal\Core\Template\TwigExtension')->escapeFilter($this->env, $this->getAttribute(($context["attributes"] ?? null), "addClass", array(0 => ($context["classes"] ?? null)), "method"), "html", null, true)); + echo ">"; + echo $this->env->getExtension('Twig_Extension_Sandbox')->ensureToStringAllowed($this->env->getExtension('Drupal\Core\Template\TwigExtension')->escapeFilter($this->env, ($context["children"] ?? null), "html", null, true)); + echo " +"; + } + + public function getTemplateName() + { + return "core/themes/classy/templates/form/container.html.twig"; + } + + public function isTraitable() + { + return false; + } + + public function getDebugInfo() + { + return array ( 47 => 28, 45 => 25, 44 => 24, 43 => 23,); + } + + /** @deprecated since 1.27 (to be removed in 2.0). Use getSourceContext() instead */ + public function getSource() + { + @trigger_error('The '.__METHOD__.' method is deprecated since version 1.27 and will be removed in 2.0. Use getSourceContext() instead.', E_USER_DEPRECATED); + + return $this->getSourceContext()->getCode(); + } + + public function getSourceContext() + { + return new Twig_Source("", "core/themes/classy/templates/form/container.html.twig", "/var/www/sites/isophonics.net/core/themes/classy/templates/form/container.html.twig"); + } +} diff -r e200cb7efeb3 -r c2387f117808 sites/default/files/php/twig/5b44bda38f6c8_field--node--title.html.t_uHV16hM_5Ek2SKYrnVCT8a34x/.htaccess --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/default/files/php/twig/5b44bda38f6c8_field--node--title.html.t_uHV16hM_5Ek2SKYrnVCT8a34x/.htaccess Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,23 @@ +# Deny all requests from Apache 2.4+. + + Require all denied + + +# Deny all requests from Apache 2.0-2.2. + + Deny from all + +# Turn off all options we don't need. +Options -Indexes -ExecCGI -Includes -MultiViews + +# Set the catch-all handler to prevent scripts from being executed. +SetHandler Drupal_Security_Do_Not_Remove_See_SA_2006_006 + + # Override the handler again if we're run later in the evaluation list. + SetHandler Drupal_Security_Do_Not_Remove_See_SA_2013_003 + + +# If we know how to do it safely, disable the PHP engine entirely. + + php_flag engine off + \ No newline at end of file diff -r e200cb7efeb3 -r c2387f117808 sites/default/files/php/twig/5b44bda38f6c8_field--node--title.html.t_uHV16hM_5Ek2SKYrnVCT8a34x/PM0r1cF0BexU0pqdoIyexgMt-Ni0oyLaVVwzS8BSAy4.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/default/files/php/twig/5b44bda38f6c8_field--node--title.html.t_uHV16hM_5Ek2SKYrnVCT8a34x/PM0r1cF0BexU0pqdoIyexgMt-Ni0oyLaVVwzS8BSAy4.php Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,93 @@ +parent = false; + + $this->blocks = array( + ); + } + + protected function doDisplay(array $context, array $blocks = array()) + { + $tags = array("set" => 23, "for" => 31); + $filters = array("clean_class" => 25); + $functions = array(); + + try { + $this->env->getExtension('Twig_Extension_Sandbox')->checkSecurity( + array('set', 'for'), + array('clean_class'), + array() + ); + } catch (Twig_Sandbox_SecurityError $e) { + $e->setSourceContext($this->getSourceContext()); + + if ($e instanceof Twig_Sandbox_SecurityNotAllowedTagError && isset($tags[$e->getTagName()])) { + $e->setTemplateLine($tags[$e->getTagName()]); + } elseif ($e instanceof Twig_Sandbox_SecurityNotAllowedFilterError && isset($filters[$e->getFilterName()])) { + $e->setTemplateLine($filters[$e->getFilterName()]); + } elseif ($e instanceof Twig_Sandbox_SecurityNotAllowedFunctionError && isset($functions[$e->getFunctionName()])) { + $e->setTemplateLine($functions[$e->getFunctionName()]); + } + + throw $e; + } + + // line 23 + $context["classes"] = array(0 => "field", 1 => ("field--name-" . \Drupal\Component\Utility\Html::getClass( // line 25 +($context["field_name"] ?? null))), 2 => ("field--type-" . \Drupal\Component\Utility\Html::getClass( // line 26 +($context["field_type"] ?? null))), 3 => ("field--label-" . // line 27 +($context["label_display"] ?? null))); + // line 30 + echo "env->getExtension('Twig_Extension_Sandbox')->ensureToStringAllowed($this->env->getExtension('Drupal\Core\Template\TwigExtension')->escapeFilter($this->env, $this->getAttribute(($context["attributes"] ?? null), "addClass", array(0 => ($context["classes"] ?? null)), "method"), "html", null, true)); + echo ">"; + // line 31 + $context['_parent'] = $context; + $context['_seq'] = twig_ensure_traversable(($context["items"] ?? null)); + foreach ($context['_seq'] as $context["_key"] => $context["item"]) { + // line 32 + echo $this->env->getExtension('Twig_Extension_Sandbox')->ensureToStringAllowed($this->env->getExtension('Drupal\Core\Template\TwigExtension')->escapeFilter($this->env, $this->getAttribute($context["item"], "content", array()), "html", null, true)); + } + $_parent = $context['_parent']; + unset($context['_seq'], $context['_iterated'], $context['_key'], $context['item'], $context['_parent'], $context['loop']); + $context = array_intersect_key($context, $_parent) + $_parent; + // line 34 + echo " +"; + } + + public function getTemplateName() + { + return "core/themes/classy/templates/field/field--node--title.html.twig"; + } + + public function isTraitable() + { + return false; + } + + public function getDebugInfo() + { + return array ( 62 => 34, 56 => 32, 52 => 31, 48 => 30, 46 => 27, 45 => 26, 44 => 25, 43 => 23,); + } + + /** @deprecated since 1.27 (to be removed in 2.0). Use getSourceContext() instead */ + public function getSource() + { + @trigger_error('The '.__METHOD__.' method is deprecated since version 1.27 and will be removed in 2.0. Use getSourceContext() instead.', E_USER_DEPRECATED); + + return $this->getSourceContext()->getCode(); + } + + public function getSourceContext() + { + return new Twig_Source("", "core/themes/classy/templates/field/field--node--title.html.twig", "/var/www/sites/isophonics.net/core/themes/classy/templates/field/field--node--title.html.twig"); + } +} diff -r e200cb7efeb3 -r c2387f117808 sites/default/files/php/twig/5b44bda38f6c8_field--text-with-summary._gLNSZGKby7XjpK24cB7UxUBGx/.htaccess --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/default/files/php/twig/5b44bda38f6c8_field--text-with-summary._gLNSZGKby7XjpK24cB7UxUBGx/.htaccess Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,23 @@ +# Deny all requests from Apache 2.4+. + + Require all denied + + +# Deny all requests from Apache 2.0-2.2. + + Deny from all + +# Turn off all options we don't need. +Options -Indexes -ExecCGI -Includes -MultiViews + +# Set the catch-all handler to prevent scripts from being executed. +SetHandler Drupal_Security_Do_Not_Remove_See_SA_2006_006 + + # Override the handler again if we're run later in the evaluation list. + SetHandler Drupal_Security_Do_Not_Remove_See_SA_2013_003 + + +# If we know how to do it safely, disable the PHP engine entirely. + + php_flag engine off + \ No newline at end of file diff -r e200cb7efeb3 -r c2387f117808 sites/default/files/php/twig/5b44bda38f6c8_field--text-with-summary._gLNSZGKby7XjpK24cB7UxUBGx/PqoR9sjkOOVLRjXMouiZ3iUEbTN5SMc9LiccLzqp1Ok.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/default/files/php/twig/5b44bda38f6c8_field--text-with-summary._gLNSZGKby7XjpK24cB7UxUBGx/PqoR9sjkOOVLRjXMouiZ3iUEbTN5SMc9LiccLzqp1Ok.php Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,77 @@ +parent = $this->loadTemplate("field--text.html.twig", "core/themes/classy/templates/field/field--text-with-summary.html.twig", 1); + $this->blocks = array( + ); + } + + protected function doGetParent(array $context) + { + return "field--text.html.twig"; + } + + protected function doDisplay(array $context, array $blocks = array()) + { + $tags = array(); + $filters = array(); + $functions = array(); + + try { + $this->env->getExtension('Twig_Extension_Sandbox')->checkSecurity( + array(), + array(), + array() + ); + } catch (Twig_Sandbox_SecurityError $e) { + $e->setSourceContext($this->getSourceContext()); + + if ($e instanceof Twig_Sandbox_SecurityNotAllowedTagError && isset($tags[$e->getTagName()])) { + $e->setTemplateLine($tags[$e->getTagName()]); + } elseif ($e instanceof Twig_Sandbox_SecurityNotAllowedFilterError && isset($filters[$e->getFilterName()])) { + $e->setTemplateLine($filters[$e->getFilterName()]); + } elseif ($e instanceof Twig_Sandbox_SecurityNotAllowedFunctionError && isset($functions[$e->getFunctionName()])) { + $e->setTemplateLine($functions[$e->getFunctionName()]); + } + + throw $e; + } + + $this->parent->display($context, array_merge($this->blocks, $blocks)); + } + + public function getTemplateName() + { + return "core/themes/classy/templates/field/field--text-with-summary.html.twig"; + } + + public function isTraitable() + { + return false; + } + + public function getDebugInfo() + { + return array ( 11 => 1,); + } + + /** @deprecated since 1.27 (to be removed in 2.0). Use getSourceContext() instead */ + public function getSource() + { + @trigger_error('The '.__METHOD__.' method is deprecated since version 1.27 and will be removed in 2.0. Use getSourceContext() instead.', E_USER_DEPRECATED); + + return $this->getSourceContext()->getCode(); + } + + public function getSourceContext() + { + return new Twig_Source("", "core/themes/classy/templates/field/field--text-with-summary.html.twig", "/var/www/sites/isophonics.net/core/themes/classy/templates/field/field--text-with-summary.html.twig"); + } +} diff -r e200cb7efeb3 -r c2387f117808 sites/default/files/php/twig/5b44bda38f6c8_field--text.html.twig_QRokRSh6FCHqQzooG_1XDDBRv/.htaccess --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/default/files/php/twig/5b44bda38f6c8_field--text.html.twig_QRokRSh6FCHqQzooG_1XDDBRv/.htaccess Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,23 @@ +# Deny all requests from Apache 2.4+. + + Require all denied + + +# Deny all requests from Apache 2.0-2.2. + + Deny from all + +# Turn off all options we don't need. +Options -Indexes -ExecCGI -Includes -MultiViews + +# Set the catch-all handler to prevent scripts from being executed. +SetHandler Drupal_Security_Do_Not_Remove_See_SA_2006_006 + + # Override the handler again if we're run later in the evaluation list. + SetHandler Drupal_Security_Do_Not_Remove_See_SA_2013_003 + + +# If we know how to do it safely, disable the PHP engine entirely. + + php_flag engine off + \ No newline at end of file diff -r e200cb7efeb3 -r c2387f117808 sites/default/files/php/twig/5b44bda38f6c8_field--text.html.twig_QRokRSh6FCHqQzooG_1XDDBRv/3m2yQCEMiAcwpiuKTA-hclOEY_pyyWf44HI50Jmed90.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/default/files/php/twig/5b44bda38f6c8_field--text.html.twig_QRokRSh6FCHqQzooG_1XDDBRv/3m2yQCEMiAcwpiuKTA-hclOEY_pyyWf44HI50Jmed90.php Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,80 @@ +parent = $this->loadTemplate("field.html.twig", "field--text.html.twig", 1); + $this->blocks = array( + ); + } + + protected function doGetParent(array $context) + { + return "field.html.twig"; + } + + protected function doDisplay(array $context, array $blocks = array()) + { + $tags = array("set" => 28); + $filters = array(); + $functions = array(); + + try { + $this->env->getExtension('Twig_Extension_Sandbox')->checkSecurity( + array('set'), + array(), + array() + ); + } catch (Twig_Sandbox_SecurityError $e) { + $e->setSourceContext($this->getSourceContext()); + + if ($e instanceof Twig_Sandbox_SecurityNotAllowedTagError && isset($tags[$e->getTagName()])) { + $e->setTemplateLine($tags[$e->getTagName()]); + } elseif ($e instanceof Twig_Sandbox_SecurityNotAllowedFilterError && isset($filters[$e->getFilterName()])) { + $e->setTemplateLine($filters[$e->getFilterName()]); + } elseif ($e instanceof Twig_Sandbox_SecurityNotAllowedFunctionError && isset($functions[$e->getFunctionName()])) { + $e->setTemplateLine($functions[$e->getFunctionName()]); + } + + throw $e; + } + + // line 28 + $context["attributes"] = $this->getAttribute(($context["attributes"] ?? null), "addClass", array(0 => "clearfix", 1 => "text-formatted"), "method"); + // line 1 + $this->parent->display($context, array_merge($this->blocks, $blocks)); + } + + public function getTemplateName() + { + return "field--text.html.twig"; + } + + public function isTraitable() + { + return false; + } + + public function getDebugInfo() + { + return array ( 50 => 1, 48 => 28, 11 => 1,); + } + + /** @deprecated since 1.27 (to be removed in 2.0). Use getSourceContext() instead */ + public function getSource() + { + @trigger_error('The '.__METHOD__.' method is deprecated since version 1.27 and will be removed in 2.0. Use getSourceContext() instead.', E_USER_DEPRECATED); + + return $this->getSourceContext()->getCode(); + } + + public function getSourceContext() + { + return new Twig_Source("", "field--text.html.twig", "core/themes/classy/templates/field/field--text.html.twig"); + } +} diff -r e200cb7efeb3 -r c2387f117808 sites/default/files/php/twig/5b44bda38f6c8_field.html.twig_sg0aNDZNrB2qJXZQKh1ByVo-x/.htaccess --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/default/files/php/twig/5b44bda38f6c8_field.html.twig_sg0aNDZNrB2qJXZQKh1ByVo-x/.htaccess Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,23 @@ +# Deny all requests from Apache 2.4+. + + Require all denied + + +# Deny all requests from Apache 2.0-2.2. + + Deny from all + +# Turn off all options we don't need. +Options -Indexes -ExecCGI -Includes -MultiViews + +# Set the catch-all handler to prevent scripts from being executed. +SetHandler Drupal_Security_Do_Not_Remove_See_SA_2006_006 + + # Override the handler again if we're run later in the evaluation list. + SetHandler Drupal_Security_Do_Not_Remove_See_SA_2013_003 + + +# If we know how to do it safely, disable the PHP engine entirely. + + php_flag engine off + \ No newline at end of file diff -r e200cb7efeb3 -r c2387f117808 sites/default/files/php/twig/5b44bda38f6c8_field.html.twig_sg0aNDZNrB2qJXZQKh1ByVo-x/ntyuPntKRNsqSbkWD8N9esd2YINvg1ItWTkIRtLDSUM.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/default/files/php/twig/5b44bda38f6c8_field.html.twig_sg0aNDZNrB2qJXZQKh1ByVo-x/ntyuPntKRNsqSbkWD8N9esd2YINvg1ItWTkIRtLDSUM.php Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,175 @@ +parent = false; + + $this->blocks = array( + ); + } + + protected function doDisplay(array $context, array $blocks = array()) + { + $tags = array("set" => 41, "if" => 55, "for" => 58); + $filters = array("clean_class" => 43); + $functions = array(); + + try { + $this->env->getExtension('Twig_Extension_Sandbox')->checkSecurity( + array('set', 'if', 'for'), + array('clean_class'), + array() + ); + } catch (Twig_Sandbox_SecurityError $e) { + $e->setSourceContext($this->getSourceContext()); + + if ($e instanceof Twig_Sandbox_SecurityNotAllowedTagError && isset($tags[$e->getTagName()])) { + $e->setTemplateLine($tags[$e->getTagName()]); + } elseif ($e instanceof Twig_Sandbox_SecurityNotAllowedFilterError && isset($filters[$e->getFilterName()])) { + $e->setTemplateLine($filters[$e->getFilterName()]); + } elseif ($e instanceof Twig_Sandbox_SecurityNotAllowedFunctionError && isset($functions[$e->getFunctionName()])) { + $e->setTemplateLine($functions[$e->getFunctionName()]); + } + + throw $e; + } + + // line 41 + $context["classes"] = array(0 => "field", 1 => ("field--name-" . \Drupal\Component\Utility\Html::getClass( // line 43 +($context["field_name"] ?? null))), 2 => ("field--type-" . \Drupal\Component\Utility\Html::getClass( // line 44 +($context["field_type"] ?? null))), 3 => ("field--label-" . // line 45 +($context["label_display"] ?? null))); + // line 49 + $context["title_classes"] = array(0 => "field__label", 1 => ((( // line 51 +($context["label_display"] ?? null) == "visually_hidden")) ? ("visually-hidden") : (""))); + // line 54 + echo " +"; + // line 55 + if (($context["label_hidden"] ?? null)) { + // line 56 + echo " "; + if (($context["multiple"] ?? null)) { + // line 57 + echo " env->getExtension('Twig_Extension_Sandbox')->ensureToStringAllowed($this->env->getExtension('Drupal\Core\Template\TwigExtension')->escapeFilter($this->env, $this->getAttribute(($context["attributes"] ?? null), "addClass", array(0 => ($context["classes"] ?? null), 1 => "field__items"), "method"), "html", null, true)); + echo "> + "; + // line 58 + $context['_parent'] = $context; + $context['_seq'] = twig_ensure_traversable(($context["items"] ?? null)); + foreach ($context['_seq'] as $context["_key"] => $context["item"]) { + // line 59 + echo " env->getExtension('Twig_Extension_Sandbox')->ensureToStringAllowed($this->env->getExtension('Drupal\Core\Template\TwigExtension')->escapeFilter($this->env, $this->getAttribute($this->getAttribute($context["item"], "attributes", array()), "addClass", array(0 => "field__item"), "method"), "html", null, true)); + echo ">"; + echo $this->env->getExtension('Twig_Extension_Sandbox')->ensureToStringAllowed($this->env->getExtension('Drupal\Core\Template\TwigExtension')->escapeFilter($this->env, $this->getAttribute($context["item"], "content", array()), "html", null, true)); + echo " + "; + } + $_parent = $context['_parent']; + unset($context['_seq'], $context['_iterated'], $context['_key'], $context['item'], $context['_parent'], $context['loop']); + $context = array_intersect_key($context, $_parent) + $_parent; + // line 61 + echo " + "; + } else { + // line 63 + echo " "; + $context['_parent'] = $context; + $context['_seq'] = twig_ensure_traversable(($context["items"] ?? null)); + foreach ($context['_seq'] as $context["_key"] => $context["item"]) { + // line 64 + echo " env->getExtension('Twig_Extension_Sandbox')->ensureToStringAllowed($this->env->getExtension('Drupal\Core\Template\TwigExtension')->escapeFilter($this->env, $this->getAttribute(($context["attributes"] ?? null), "addClass", array(0 => ($context["classes"] ?? null), 1 => "field__item"), "method"), "html", null, true)); + echo ">"; + echo $this->env->getExtension('Twig_Extension_Sandbox')->ensureToStringAllowed($this->env->getExtension('Drupal\Core\Template\TwigExtension')->escapeFilter($this->env, $this->getAttribute($context["item"], "content", array()), "html", null, true)); + echo " + "; + } + $_parent = $context['_parent']; + unset($context['_seq'], $context['_iterated'], $context['_key'], $context['item'], $context['_parent'], $context['loop']); + $context = array_intersect_key($context, $_parent) + $_parent; + // line 66 + echo " "; + } + } else { + // line 68 + echo " env->getExtension('Twig_Extension_Sandbox')->ensureToStringAllowed($this->env->getExtension('Drupal\Core\Template\TwigExtension')->escapeFilter($this->env, $this->getAttribute(($context["attributes"] ?? null), "addClass", array(0 => ($context["classes"] ?? null)), "method"), "html", null, true)); + echo "> + env->getExtension('Twig_Extension_Sandbox')->ensureToStringAllowed($this->env->getExtension('Drupal\Core\Template\TwigExtension')->escapeFilter($this->env, $this->getAttribute(($context["title_attributes"] ?? null), "addClass", array(0 => ($context["title_classes"] ?? null)), "method"), "html", null, true)); + echo ">"; + echo $this->env->getExtension('Twig_Extension_Sandbox')->ensureToStringAllowed($this->env->getExtension('Drupal\Core\Template\TwigExtension')->escapeFilter($this->env, ($context["label"] ?? null), "html", null, true)); + echo " + "; + // line 70 + if (($context["multiple"] ?? null)) { + // line 71 + echo "
        + "; + } + // line 73 + echo " "; + $context['_parent'] = $context; + $context['_seq'] = twig_ensure_traversable(($context["items"] ?? null)); + foreach ($context['_seq'] as $context["_key"] => $context["item"]) { + // line 74 + echo " env->getExtension('Twig_Extension_Sandbox')->ensureToStringAllowed($this->env->getExtension('Drupal\Core\Template\TwigExtension')->escapeFilter($this->env, $this->getAttribute($this->getAttribute($context["item"], "attributes", array()), "addClass", array(0 => "field__item"), "method"), "html", null, true)); + echo ">"; + echo $this->env->getExtension('Twig_Extension_Sandbox')->ensureToStringAllowed($this->env->getExtension('Drupal\Core\Template\TwigExtension')->escapeFilter($this->env, $this->getAttribute($context["item"], "content", array()), "html", null, true)); + echo "
        + "; + } + $_parent = $context['_parent']; + unset($context['_seq'], $context['_iterated'], $context['_key'], $context['item'], $context['_parent'], $context['loop']); + $context = array_intersect_key($context, $_parent) + $_parent; + // line 76 + echo " "; + if (($context["multiple"] ?? null)) { + // line 77 + echo " + "; + } + // line 79 + echo " +"; + } + } + + public function getTemplateName() + { + return "field.html.twig"; + } + + public function isTraitable() + { + return false; + } + + public function getDebugInfo() + { + return array ( 143 => 79, 139 => 77, 136 => 76, 125 => 74, 120 => 73, 116 => 71, 114 => 70, 108 => 69, 103 => 68, 99 => 66, 88 => 64, 83 => 63, 79 => 61, 68 => 59, 64 => 58, 59 => 57, 56 => 56, 54 => 55, 51 => 54, 49 => 51, 48 => 49, 46 => 45, 45 => 44, 44 => 43, 43 => 41,); + } + + /** @deprecated since 1.27 (to be removed in 2.0). Use getSourceContext() instead */ + public function getSource() + { + @trigger_error('The '.__METHOD__.' method is deprecated since version 1.27 and will be removed in 2.0. Use getSourceContext() instead.', E_USER_DEPRECATED); + + return $this->getSourceContext()->getCode(); + } + + public function getSourceContext() + { + return new Twig_Source("", "field.html.twig", "core/themes/classy/templates/field/field.html.twig"); + } +} diff -r e200cb7efeb3 -r c2387f117808 sites/default/files/php/twig/5b44bda38f6c8_form-element-label.html.t_LIUK9REF8eGBcgyB37knqChLi/.htaccess --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/default/files/php/twig/5b44bda38f6c8_form-element-label.html.t_LIUK9REF8eGBcgyB37knqChLi/.htaccess Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,23 @@ +# Deny all requests from Apache 2.4+. + + Require all denied + + +# Deny all requests from Apache 2.0-2.2. + + Deny from all + +# Turn off all options we don't need. +Options -Indexes -ExecCGI -Includes -MultiViews + +# Set the catch-all handler to prevent scripts from being executed. +SetHandler Drupal_Security_Do_Not_Remove_See_SA_2006_006 + + # Override the handler again if we're run later in the evaluation list. + SetHandler Drupal_Security_Do_Not_Remove_See_SA_2013_003 + + +# If we know how to do it safely, disable the PHP engine entirely. + + php_flag engine off + \ No newline at end of file diff -r e200cb7efeb3 -r c2387f117808 sites/default/files/php/twig/5b44bda38f6c8_form-element-label.html.t_LIUK9REF8eGBcgyB37knqChLi/KEBDKvPm_g6ptWXn_Jz65K-haGiKaWAIJeDSksyN5gU.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/default/files/php/twig/5b44bda38f6c8_form-element-label.html.t_LIUK9REF8eGBcgyB37knqChLi/KEBDKvPm_g6ptWXn_Jz65K-haGiKaWAIJeDSksyN5gU.php Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,86 @@ +parent = false; + + $this->blocks = array( + ); + } + + protected function doDisplay(array $context, array $blocks = array()) + { + $tags = array("set" => 16, "if" => 23); + $filters = array(); + $functions = array(); + + try { + $this->env->getExtension('Twig_Extension_Sandbox')->checkSecurity( + array('set', 'if'), + array(), + array() + ); + } catch (Twig_Sandbox_SecurityError $e) { + $e->setSourceContext($this->getSourceContext()); + + if ($e instanceof Twig_Sandbox_SecurityNotAllowedTagError && isset($tags[$e->getTagName()])) { + $e->setTemplateLine($tags[$e->getTagName()]); + } elseif ($e instanceof Twig_Sandbox_SecurityNotAllowedFilterError && isset($filters[$e->getFilterName()])) { + $e->setTemplateLine($filters[$e->getFilterName()]); + } elseif ($e instanceof Twig_Sandbox_SecurityNotAllowedFunctionError && isset($functions[$e->getFunctionName()])) { + $e->setTemplateLine($functions[$e->getFunctionName()]); + } + + throw $e; + } + + // line 16 + $context["classes"] = array(0 => ((( // line 17 +($context["title_display"] ?? null) == "after")) ? ("option") : ("")), 1 => ((( // line 18 +($context["title_display"] ?? null) == "invisible")) ? ("visually-hidden") : ("")), 2 => (( // line 19 +($context["required"] ?? null)) ? ("js-form-required") : ("")), 3 => (( // line 20 +($context["required"] ?? null)) ? ("form-required") : (""))); + // line 23 + if (( !twig_test_empty(($context["title"] ?? null)) || ($context["required"] ?? null))) { + // line 24 + echo "env->getExtension('Twig_Extension_Sandbox')->ensureToStringAllowed($this->env->getExtension('Drupal\Core\Template\TwigExtension')->escapeFilter($this->env, $this->getAttribute(($context["attributes"] ?? null), "addClass", array(0 => ($context["classes"] ?? null)), "method"), "html", null, true)); + echo ">"; + echo $this->env->getExtension('Twig_Extension_Sandbox')->ensureToStringAllowed($this->env->getExtension('Drupal\Core\Template\TwigExtension')->escapeFilter($this->env, ($context["title"] ?? null), "html", null, true)); + echo ""; + } + } + + public function getTemplateName() + { + return "core/themes/classy/templates/form/form-element-label.html.twig"; + } + + public function isTraitable() + { + return false; + } + + public function getDebugInfo() + { + return array ( 51 => 24, 49 => 23, 47 => 20, 46 => 19, 45 => 18, 44 => 17, 43 => 16,); + } + + /** @deprecated since 1.27 (to be removed in 2.0). Use getSourceContext() instead */ + public function getSource() + { + @trigger_error('The '.__METHOD__.' method is deprecated since version 1.27 and will be removed in 2.0. Use getSourceContext() instead.', E_USER_DEPRECATED); + + return $this->getSourceContext()->getCode(); + } + + public function getSourceContext() + { + return new Twig_Source("", "core/themes/classy/templates/form/form-element-label.html.twig", "/var/www/sites/isophonics.net/core/themes/classy/templates/form/form-element-label.html.twig"); + } +} diff -r e200cb7efeb3 -r c2387f117808 sites/default/files/php/twig/5b44bda38f6c8_form-element.html.twig_dJcTIbdx1y7B0dbOtEyyZSSZ1/.htaccess --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/default/files/php/twig/5b44bda38f6c8_form-element.html.twig_dJcTIbdx1y7B0dbOtEyyZSSZ1/.htaccess Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,23 @@ +# Deny all requests from Apache 2.4+. + + Require all denied + + +# Deny all requests from Apache 2.0-2.2. + + Deny from all + +# Turn off all options we don't need. +Options -Indexes -ExecCGI -Includes -MultiViews + +# Set the catch-all handler to prevent scripts from being executed. +SetHandler Drupal_Security_Do_Not_Remove_See_SA_2006_006 + + # Override the handler again if we're run later in the evaluation list. + SetHandler Drupal_Security_Do_Not_Remove_See_SA_2013_003 + + +# If we know how to do it safely, disable the PHP engine entirely. + + php_flag engine off + \ No newline at end of file diff -r e200cb7efeb3 -r c2387f117808 sites/default/files/php/twig/5b44bda38f6c8_form-element.html.twig_dJcTIbdx1y7B0dbOtEyyZSSZ1/tDr8iUbq4qtCgwJvlyvc83BmVu8lDnNUhoV3HpY62Ww.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/default/files/php/twig/5b44bda38f6c8_form-element.html.twig_dJcTIbdx1y7B0dbOtEyyZSSZ1/tDr8iUbq4qtCgwJvlyvc83BmVu8lDnNUhoV3HpY62Ww.php Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,170 @@ +parent = false; + + $this->blocks = array( + ); + } + + protected function doDisplay(array $context, array $blocks = array()) + { + $tags = array("set" => 48, "if" => 67); + $filters = array("clean_class" => 51); + $functions = array(); + + try { + $this->env->getExtension('Twig_Extension_Sandbox')->checkSecurity( + array('set', 'if'), + array('clean_class'), + array() + ); + } catch (Twig_Sandbox_SecurityError $e) { + $e->setSourceContext($this->getSourceContext()); + + if ($e instanceof Twig_Sandbox_SecurityNotAllowedTagError && isset($tags[$e->getTagName()])) { + $e->setTemplateLine($tags[$e->getTagName()]); + } elseif ($e instanceof Twig_Sandbox_SecurityNotAllowedFilterError && isset($filters[$e->getFilterName()])) { + $e->setTemplateLine($filters[$e->getFilterName()]); + } elseif ($e instanceof Twig_Sandbox_SecurityNotAllowedFunctionError && isset($functions[$e->getFunctionName()])) { + $e->setTemplateLine($functions[$e->getFunctionName()]); + } + + throw $e; + } + + // line 48 + $context["classes"] = array(0 => "js-form-item", 1 => "form-item", 2 => ("js-form-type-" . \Drupal\Component\Utility\Html::getClass( // line 51 +($context["type"] ?? null))), 3 => ("form-type-" . \Drupal\Component\Utility\Html::getClass( // line 52 +($context["type"] ?? null))), 4 => ("js-form-item-" . \Drupal\Component\Utility\Html::getClass( // line 53 +($context["name"] ?? null))), 5 => ("form-item-" . \Drupal\Component\Utility\Html::getClass( // line 54 +($context["name"] ?? null))), 6 => ((!twig_in_filter( // line 55 +($context["title_display"] ?? null), array(0 => "after", 1 => "before"))) ? ("form-no-label") : ("")), 7 => ((( // line 56 +($context["disabled"] ?? null) == "disabled")) ? ("form-disabled") : ("")), 8 => (( // line 57 +($context["errors"] ?? null)) ? ("form-item--error") : (""))); + // line 61 + $context["description_classes"] = array(0 => "description", 1 => ((( // line 63 +($context["description_display"] ?? null) == "invisible")) ? ("visually-hidden") : (""))); + // line 66 + echo "env->getExtension('Twig_Extension_Sandbox')->ensureToStringAllowed($this->env->getExtension('Drupal\Core\Template\TwigExtension')->escapeFilter($this->env, $this->getAttribute(($context["attributes"] ?? null), "addClass", array(0 => ($context["classes"] ?? null)), "method"), "html", null, true)); + echo "> + "; + // line 67 + if (twig_in_filter(($context["label_display"] ?? null), array(0 => "before", 1 => "invisible"))) { + // line 68 + echo " "; + echo $this->env->getExtension('Twig_Extension_Sandbox')->ensureToStringAllowed($this->env->getExtension('Drupal\Core\Template\TwigExtension')->escapeFilter($this->env, ($context["label"] ?? null), "html", null, true)); + echo " + "; + } + // line 70 + echo " "; + if ( !twig_test_empty(($context["prefix"] ?? null))) { + // line 71 + echo " "; + echo $this->env->getExtension('Twig_Extension_Sandbox')->ensureToStringAllowed($this->env->getExtension('Drupal\Core\Template\TwigExtension')->escapeFilter($this->env, ($context["prefix"] ?? null), "html", null, true)); + echo " + "; + } + // line 73 + echo " "; + if (((($context["description_display"] ?? null) == "before") && $this->getAttribute(($context["description"] ?? null), "content", array()))) { + // line 74 + echo " env->getExtension('Twig_Extension_Sandbox')->ensureToStringAllowed($this->env->getExtension('Drupal\Core\Template\TwigExtension')->escapeFilter($this->env, $this->getAttribute(($context["description"] ?? null), "attributes", array()), "html", null, true)); + echo "> + "; + // line 75 + echo $this->env->getExtension('Twig_Extension_Sandbox')->ensureToStringAllowed($this->env->getExtension('Drupal\Core\Template\TwigExtension')->escapeFilter($this->env, $this->getAttribute(($context["description"] ?? null), "content", array()), "html", null, true)); + echo " + + "; + } + // line 78 + echo " "; + echo $this->env->getExtension('Twig_Extension_Sandbox')->ensureToStringAllowed($this->env->getExtension('Drupal\Core\Template\TwigExtension')->escapeFilter($this->env, ($context["children"] ?? null), "html", null, true)); + echo " + "; + // line 79 + if ( !twig_test_empty(($context["suffix"] ?? null))) { + // line 80 + echo " "; + echo $this->env->getExtension('Twig_Extension_Sandbox')->ensureToStringAllowed($this->env->getExtension('Drupal\Core\Template\TwigExtension')->escapeFilter($this->env, ($context["suffix"] ?? null), "html", null, true)); + echo " + "; + } + // line 82 + echo " "; + if ((($context["label_display"] ?? null) == "after")) { + // line 83 + echo " "; + echo $this->env->getExtension('Twig_Extension_Sandbox')->ensureToStringAllowed($this->env->getExtension('Drupal\Core\Template\TwigExtension')->escapeFilter($this->env, ($context["label"] ?? null), "html", null, true)); + echo " + "; + } + // line 85 + echo " "; + if (($context["errors"] ?? null)) { + // line 86 + echo "
        + "; + // line 87 + echo $this->env->getExtension('Twig_Extension_Sandbox')->ensureToStringAllowed($this->env->getExtension('Drupal\Core\Template\TwigExtension')->escapeFilter($this->env, ($context["errors"] ?? null), "html", null, true)); + echo " +
        + "; + } + // line 90 + echo " "; + if ((twig_in_filter(($context["description_display"] ?? null), array(0 => "after", 1 => "invisible")) && $this->getAttribute(($context["description"] ?? null), "content", array()))) { + // line 91 + echo " env->getExtension('Twig_Extension_Sandbox')->ensureToStringAllowed($this->env->getExtension('Drupal\Core\Template\TwigExtension')->escapeFilter($this->env, $this->getAttribute($this->getAttribute(($context["description"] ?? null), "attributes", array()), "addClass", array(0 => ($context["description_classes"] ?? null)), "method"), "html", null, true)); + echo "> + "; + // line 92 + echo $this->env->getExtension('Twig_Extension_Sandbox')->ensureToStringAllowed($this->env->getExtension('Drupal\Core\Template\TwigExtension')->escapeFilter($this->env, $this->getAttribute(($context["description"] ?? null), "content", array()), "html", null, true)); + echo " + + "; + } + // line 95 + echo " +"; + } + + public function getTemplateName() + { + return "core/themes/classy/templates/form/form-element.html.twig"; + } + + public function isTraitable() + { + return false; + } + + public function getDebugInfo() + { + return array ( 139 => 95, 133 => 92, 128 => 91, 125 => 90, 119 => 87, 116 => 86, 113 => 85, 107 => 83, 104 => 82, 98 => 80, 96 => 79, 91 => 78, 85 => 75, 80 => 74, 77 => 73, 71 => 71, 68 => 70, 62 => 68, 60 => 67, 55 => 66, 53 => 63, 52 => 61, 50 => 57, 49 => 56, 48 => 55, 47 => 54, 46 => 53, 45 => 52, 44 => 51, 43 => 48,); + } + + /** @deprecated since 1.27 (to be removed in 2.0). Use getSourceContext() instead */ + public function getSource() + { + @trigger_error('The '.__METHOD__.' method is deprecated since version 1.27 and will be removed in 2.0. Use getSourceContext() instead.', E_USER_DEPRECATED); + + return $this->getSourceContext()->getCode(); + } + + public function getSourceContext() + { + return new Twig_Source("", "core/themes/classy/templates/form/form-element.html.twig", "/var/www/sites/isophonics.net/core/themes/classy/templates/form/form-element.html.twig"); + } +} diff -r e200cb7efeb3 -r c2387f117808 sites/default/files/php/twig/5b44bda38f6c8_form.html.twig_yB95M-mH2KEXj4tKtKISfLbel/.htaccess --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/default/files/php/twig/5b44bda38f6c8_form.html.twig_yB95M-mH2KEXj4tKtKISfLbel/.htaccess Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,23 @@ +# Deny all requests from Apache 2.4+. + + Require all denied + + +# Deny all requests from Apache 2.0-2.2. + + Deny from all + +# Turn off all options we don't need. +Options -Indexes -ExecCGI -Includes -MultiViews + +# Set the catch-all handler to prevent scripts from being executed. +SetHandler Drupal_Security_Do_Not_Remove_See_SA_2006_006 + + # Override the handler again if we're run later in the evaluation list. + SetHandler Drupal_Security_Do_Not_Remove_See_SA_2013_003 + + +# If we know how to do it safely, disable the PHP engine entirely. + + php_flag engine off + \ No newline at end of file diff -r e200cb7efeb3 -r c2387f117808 sites/default/files/php/twig/5b44bda38f6c8_form.html.twig_yB95M-mH2KEXj4tKtKISfLbel/6L4cQ0TREhafRdOeoR4i9uRmwyzjD16kKtLEsloa2qg.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/default/files/php/twig/5b44bda38f6c8_form.html.twig_yB95M-mH2KEXj4tKtKISfLbel/6L4cQ0TREhafRdOeoR4i9uRmwyzjD16kKtLEsloa2qg.php Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,81 @@ +parent = false; + + $this->blocks = array( + ); + } + + protected function doDisplay(array $context, array $blocks = array()) + { + $tags = array(); + $filters = array(); + $functions = array(); + + try { + $this->env->getExtension('Twig_Extension_Sandbox')->checkSecurity( + array(), + array(), + array() + ); + } catch (Twig_Sandbox_SecurityError $e) { + $e->setSourceContext($this->getSourceContext()); + + if ($e instanceof Twig_Sandbox_SecurityNotAllowedTagError && isset($tags[$e->getTagName()])) { + $e->setTemplateLine($tags[$e->getTagName()]); + } elseif ($e instanceof Twig_Sandbox_SecurityNotAllowedFilterError && isset($filters[$e->getFilterName()])) { + $e->setTemplateLine($filters[$e->getFilterName()]); + } elseif ($e instanceof Twig_Sandbox_SecurityNotAllowedFunctionError && isset($functions[$e->getFunctionName()])) { + $e->setTemplateLine($functions[$e->getFunctionName()]); + } + + throw $e; + } + + // line 13 + echo "env->getExtension('Twig_Extension_Sandbox')->ensureToStringAllowed($this->env->getExtension('Drupal\Core\Template\TwigExtension')->escapeFilter($this->env, ($context["attributes"] ?? null), "html", null, true)); + echo "> + "; + // line 14 + echo $this->env->getExtension('Twig_Extension_Sandbox')->ensureToStringAllowed($this->env->getExtension('Drupal\Core\Template\TwigExtension')->escapeFilter($this->env, ($context["children"] ?? null), "html", null, true)); + echo " + +"; + } + + public function getTemplateName() + { + return "core/themes/classy/templates/form/form.html.twig"; + } + + public function isTraitable() + { + return false; + } + + public function getDebugInfo() + { + return array ( 48 => 14, 43 => 13,); + } + + /** @deprecated since 1.27 (to be removed in 2.0). Use getSourceContext() instead */ + public function getSource() + { + @trigger_error('The '.__METHOD__.' method is deprecated since version 1.27 and will be removed in 2.0. Use getSourceContext() instead.', E_USER_DEPRECATED); + + return $this->getSourceContext()->getCode(); + } + + public function getSourceContext() + { + return new Twig_Source("", "core/themes/classy/templates/form/form.html.twig", "/var/www/sites/isophonics.net/core/themes/classy/templates/form/form.html.twig"); + } +} diff -r e200cb7efeb3 -r c2387f117808 sites/default/files/php/twig/5b44bda38f6c8_html.html.twig_gQv-GORxUVif_Pag4s-5z2NkO/.htaccess --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/default/files/php/twig/5b44bda38f6c8_html.html.twig_gQv-GORxUVif_Pag4s-5z2NkO/.htaccess Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,23 @@ +# Deny all requests from Apache 2.4+. + + Require all denied + + +# Deny all requests from Apache 2.0-2.2. + + Deny from all + +# Turn off all options we don't need. +Options -Indexes -ExecCGI -Includes -MultiViews + +# Set the catch-all handler to prevent scripts from being executed. +SetHandler Drupal_Security_Do_Not_Remove_See_SA_2006_006 + + # Override the handler again if we're run later in the evaluation list. + SetHandler Drupal_Security_Do_Not_Remove_See_SA_2013_003 + + +# If we know how to do it safely, disable the PHP engine entirely. + + php_flag engine off + \ No newline at end of file diff -r e200cb7efeb3 -r c2387f117808 sites/default/files/php/twig/5b44bda38f6c8_html.html.twig_gQv-GORxUVif_Pag4s-5z2NkO/DU1Fv1SVqI7HAkPdwBq4JLJ-vQq78C_nTwgrTM_LYlk.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/default/files/php/twig/5b44bda38f6c8_html.html.twig_gQv-GORxUVif_Pag4s-5z2NkO/DU1Fv1SVqI7HAkPdwBq4JLJ-vQq78C_nTwgrTM_LYlk.php Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,132 @@ +parent = false; + + $this->blocks = array( + ); + } + + protected function doDisplay(array $context, array $blocks = array()) + { + $tags = array("set" => 27); + $filters = array("clean_class" => 29, "safe_join" => 38, "t" => 48); + $functions = array(); + + try { + $this->env->getExtension('Twig_Extension_Sandbox')->checkSecurity( + array('set'), + array('clean_class', 'safe_join', 't'), + array() + ); + } catch (Twig_Sandbox_SecurityError $e) { + $e->setSourceContext($this->getSourceContext()); + + if ($e instanceof Twig_Sandbox_SecurityNotAllowedTagError && isset($tags[$e->getTagName()])) { + $e->setTemplateLine($tags[$e->getTagName()]); + } elseif ($e instanceof Twig_Sandbox_SecurityNotAllowedFilterError && isset($filters[$e->getFilterName()])) { + $e->setTemplateLine($filters[$e->getFilterName()]); + } elseif ($e instanceof Twig_Sandbox_SecurityNotAllowedFunctionError && isset($functions[$e->getFunctionName()])) { + $e->setTemplateLine($functions[$e->getFunctionName()]); + } + + throw $e; + } + + // line 27 + $context["body_classes"] = array(0 => (( // line 28 +($context["logged_in"] ?? null)) ? ("user-logged-in") : ("")), 1 => (( ! // line 29 +($context["root_path"] ?? null)) ? ("path-frontpage") : (("path-" . \Drupal\Component\Utility\Html::getClass(($context["root_path"] ?? null))))), 2 => (( // line 30 +($context["node_type"] ?? null)) ? (("page-node-type-" . \Drupal\Component\Utility\Html::getClass(($context["node_type"] ?? null)))) : ("")), 3 => (( // line 31 +($context["db_offline"] ?? null)) ? ("db-offline") : (""))); + // line 34 + echo " +env->getExtension('Twig_Extension_Sandbox')->ensureToStringAllowed($this->env->getExtension('Drupal\Core\Template\TwigExtension')->escapeFilter($this->env, ($context["html_attributes"] ?? null), "html", null, true)); + echo "> + + env->getExtension('Twig_Extension_Sandbox')->ensureToStringAllowed($this->env->getExtension('Drupal\Core\Template\TwigExtension')->escapeFilter($this->env, ($context["placeholder_token"] ?? null), "html", null, true)); + echo "\"> + "; + // line 38 + echo $this->env->getExtension('Twig_Extension_Sandbox')->ensureToStringAllowed($this->env->getExtension('Drupal\Core\Template\TwigExtension')->renderVar($this->env->getExtension('Drupal\Core\Template\TwigExtension')->safeJoin($this->env, ($context["head_title"] ?? null), " | "))); + echo " + env->getExtension('Twig_Extension_Sandbox')->ensureToStringAllowed($this->env->getExtension('Drupal\Core\Template\TwigExtension')->escapeFilter($this->env, ($context["placeholder_token"] ?? null), "html", null, true)); + echo "\"> + env->getExtension('Twig_Extension_Sandbox')->ensureToStringAllowed($this->env->getExtension('Drupal\Core\Template\TwigExtension')->escapeFilter($this->env, ($context["placeholder_token"] ?? null), "html", null, true)); + echo "\"> + + env->getExtension('Twig_Extension_Sandbox')->ensureToStringAllowed($this->env->getExtension('Drupal\Core\Template\TwigExtension')->escapeFilter($this->env, $this->getAttribute(($context["attributes"] ?? null), "addClass", array(0 => ($context["body_classes"] ?? null)), "method"), "html", null, true)); + echo "> + "; + // line 47 + echo " + "; + // line 48 + echo $this->env->getExtension('Twig_Extension_Sandbox')->ensureToStringAllowed($this->env->getExtension('Drupal\Core\Template\TwigExtension')->renderVar(t("Skip to main content"))); + echo " + + "; + // line 50 + echo $this->env->getExtension('Twig_Extension_Sandbox')->ensureToStringAllowed($this->env->getExtension('Drupal\Core\Template\TwigExtension')->escapeFilter($this->env, ($context["page_top"] ?? null), "html", null, true)); + echo " + "; + // line 51 + echo $this->env->getExtension('Twig_Extension_Sandbox')->ensureToStringAllowed($this->env->getExtension('Drupal\Core\Template\TwigExtension')->escapeFilter($this->env, ($context["page"] ?? null), "html", null, true)); + echo " + "; + // line 52 + echo $this->env->getExtension('Twig_Extension_Sandbox')->ensureToStringAllowed($this->env->getExtension('Drupal\Core\Template\TwigExtension')->escapeFilter($this->env, ($context["page_bottom"] ?? null), "html", null, true)); + echo " + env->getExtension('Twig_Extension_Sandbox')->ensureToStringAllowed($this->env->getExtension('Drupal\Core\Template\TwigExtension')->escapeFilter($this->env, ($context["placeholder_token"] ?? null), "html", null, true)); + echo "\"> + + +"; + } + + public function getTemplateName() + { + return "core/themes/classy/templates/layout/html.html.twig"; + } + + public function isTraitable() + { + return false; + } + + public function getDebugInfo() + { + return array ( 98 => 53, 94 => 52, 90 => 51, 86 => 50, 81 => 48, 78 => 47, 74 => 42, 69 => 40, 65 => 39, 61 => 38, 57 => 37, 52 => 35, 49 => 34, 47 => 31, 46 => 30, 45 => 29, 44 => 28, 43 => 27,); + } + + /** @deprecated since 1.27 (to be removed in 2.0). Use getSourceContext() instead */ + public function getSource() + { + @trigger_error('The '.__METHOD__.' method is deprecated since version 1.27 and will be removed in 2.0. Use getSourceContext() instead.', E_USER_DEPRECATED); + + return $this->getSourceContext()->getCode(); + } + + public function getSourceContext() + { + return new Twig_Source("", "core/themes/classy/templates/layout/html.html.twig", "/var/www/sites/isophonics.net/core/themes/classy/templates/layout/html.html.twig"); + } +} diff -r e200cb7efeb3 -r c2387f117808 sites/default/files/php/twig/5b44bda38f6c8_inline-template_T-xhV_TNNJ3iO7wKK2rml8iOw/.htaccess --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/default/files/php/twig/5b44bda38f6c8_inline-template_T-xhV_TNNJ3iO7wKK2rml8iOw/.htaccess Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,23 @@ +# Deny all requests from Apache 2.4+. + + Require all denied + + +# Deny all requests from Apache 2.0-2.2. + + Deny from all + +# Turn off all options we don't need. +Options -Indexes -ExecCGI -Includes -MultiViews + +# Set the catch-all handler to prevent scripts from being executed. +SetHandler Drupal_Security_Do_Not_Remove_See_SA_2006_006 + + # Override the handler again if we're run later in the evaluation list. + SetHandler Drupal_Security_Do_Not_Remove_See_SA_2013_003 + + +# If we know how to do it safely, disable the PHP engine entirely. + + php_flag engine off + \ No newline at end of file diff -r e200cb7efeb3 -r c2387f117808 sites/default/files/php/twig/5b44bda38f6c8_inline-template_T-xhV_TNNJ3iO7wKK2rml8iOw/E_tt_yWCFFo1U0Bsq9Ry2kABuv8vR_CvMQ2yD1-VdVo.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/default/files/php/twig/5b44bda38f6c8_inline-template_T-xhV_TNNJ3iO7wKK2rml8iOw/E_tt_yWCFFo1U0Bsq9Ry2kABuv8vR_CvMQ2yD1-VdVo.php Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,73 @@ +parent = false; + + $this->blocks = array( + ); + } + + protected function doDisplay(array $context, array $blocks = array()) + { + $tags = array(); + $filters = array("nl2br" => 1); + $functions = array(); + + try { + $this->env->getExtension('Twig_Extension_Sandbox')->checkSecurity( + array(), + array('nl2br'), + array() + ); + } catch (Twig_Sandbox_SecurityError $e) { + $e->setSourceContext($this->getSourceContext()); + + if ($e instanceof Twig_Sandbox_SecurityNotAllowedTagError && isset($tags[$e->getTagName()])) { + $e->setTemplateLine($tags[$e->getTagName()]); + } elseif ($e instanceof Twig_Sandbox_SecurityNotAllowedFilterError && isset($filters[$e->getFilterName()])) { + $e->setTemplateLine($filters[$e->getFilterName()]); + } elseif ($e instanceof Twig_Sandbox_SecurityNotAllowedFunctionError && isset($functions[$e->getFunctionName()])) { + $e->setTemplateLine($functions[$e->getFunctionName()]); + } + + throw $e; + } + + // line 1 + echo $this->env->getExtension('Twig_Extension_Sandbox')->ensureToStringAllowed(nl2br($this->env->getExtension('Drupal\Core\Template\TwigExtension')->escapeFilter($this->env, ($context["value"] ?? null), "html", null, true))); + } + + public function getTemplateName() + { + return "{# inline_template_start #}{{ value|nl2br }}"; + } + + public function isTraitable() + { + return false; + } + + public function getDebugInfo() + { + return array ( 43 => 1,); + } + + /** @deprecated since 1.27 (to be removed in 2.0). Use getSourceContext() instead */ + public function getSource() + { + @trigger_error('The '.__METHOD__.' method is deprecated since version 1.27 and will be removed in 2.0. Use getSourceContext() instead.', E_USER_DEPRECATED); + + return $this->getSourceContext()->getCode(); + } + + public function getSourceContext() + { + return new Twig_Source("", "{# inline_template_start #}{{ value|nl2br }}", ""); + } +} diff -r e200cb7efeb3 -r c2387f117808 sites/default/files/php/twig/5b44bda38f6c8_inline-template_e_dqXOJJDBmEMudVP28luiygF/.htaccess --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/default/files/php/twig/5b44bda38f6c8_inline-template_e_dqXOJJDBmEMudVP28luiygF/.htaccess Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,23 @@ +# Deny all requests from Apache 2.4+. + + Require all denied + + +# Deny all requests from Apache 2.0-2.2. + + Deny from all + +# Turn off all options we don't need. +Options -Indexes -ExecCGI -Includes -MultiViews + +# Set the catch-all handler to prevent scripts from being executed. +SetHandler Drupal_Security_Do_Not_Remove_See_SA_2006_006 + + # Override the handler again if we're run later in the evaluation list. + SetHandler Drupal_Security_Do_Not_Remove_See_SA_2013_003 + + +# If we know how to do it safely, disable the PHP engine entirely. + + php_flag engine off + \ No newline at end of file diff -r e200cb7efeb3 -r c2387f117808 sites/default/files/php/twig/5b44bda38f6c8_inline-template_e_dqXOJJDBmEMudVP28luiygF/gh6k_DmvEeE0Wl8T9MaCUCsAVIdOJ0jiq9nfkgDWOuw.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/default/files/php/twig/5b44bda38f6c8_inline-template_e_dqXOJJDBmEMudVP28luiygF/gh6k_DmvEeE0Wl8T9MaCUCsAVIdOJ0jiq9nfkgDWOuw.php Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,73 @@ +parent = false; + + $this->blocks = array( + ); + } + + protected function doDisplay(array $context, array $blocks = array()) + { + $tags = array(); + $filters = array("safe_join" => 1); + $functions = array(); + + try { + $this->env->getExtension('Twig_Extension_Sandbox')->checkSecurity( + array(), + array('safe_join'), + array() + ); + } catch (Twig_Sandbox_SecurityError $e) { + $e->setSourceContext($this->getSourceContext()); + + if ($e instanceof Twig_Sandbox_SecurityNotAllowedTagError && isset($tags[$e->getTagName()])) { + $e->setTemplateLine($tags[$e->getTagName()]); + } elseif ($e instanceof Twig_Sandbox_SecurityNotAllowedFilterError && isset($filters[$e->getFilterName()])) { + $e->setTemplateLine($filters[$e->getFilterName()]); + } elseif ($e instanceof Twig_Sandbox_SecurityNotAllowedFunctionError && isset($functions[$e->getFunctionName()])) { + $e->setTemplateLine($functions[$e->getFunctionName()]); + } + + throw $e; + } + + // line 1 + echo $this->env->getExtension('Twig_Extension_Sandbox')->ensureToStringAllowed($this->env->getExtension('Drupal\Core\Template\TwigExtension')->renderVar($this->env->getExtension('Drupal\Core\Template\TwigExtension')->safeJoin($this->env, ($context["info"] ?? null), " - "))); + } + + public function getTemplateName() + { + return "{# inline_template_start #}{{ info|safe_join(\" - \") }}"; + } + + public function isTraitable() + { + return false; + } + + public function getDebugInfo() + { + return array ( 43 => 1,); + } + + /** @deprecated since 1.27 (to be removed in 2.0). Use getSourceContext() instead */ + public function getSource() + { + @trigger_error('The '.__METHOD__.' method is deprecated since version 1.27 and will be removed in 2.0. Use getSourceContext() instead.', E_USER_DEPRECATED); + + return $this->getSourceContext()->getCode(); + } + + public function getSourceContext() + { + return new Twig_Source("", "{# inline_template_start #}{{ info|safe_join(\" - \") }}", ""); + } +} diff -r e200cb7efeb3 -r c2387f117808 sites/default/files/php/twig/5b44bda38f6c8_input.html.twig_jYi6QYvFpjKLYKZCId7BmHw8z/.htaccess --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/default/files/php/twig/5b44bda38f6c8_input.html.twig_jYi6QYvFpjKLYKZCId7BmHw8z/.htaccess Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,23 @@ +# Deny all requests from Apache 2.4+. + + Require all denied + + +# Deny all requests from Apache 2.0-2.2. + + Deny from all + +# Turn off all options we don't need. +Options -Indexes -ExecCGI -Includes -MultiViews + +# Set the catch-all handler to prevent scripts from being executed. +SetHandler Drupal_Security_Do_Not_Remove_See_SA_2006_006 + + # Override the handler again if we're run later in the evaluation list. + SetHandler Drupal_Security_Do_Not_Remove_See_SA_2013_003 + + +# If we know how to do it safely, disable the PHP engine entirely. + + php_flag engine off + \ No newline at end of file diff -r e200cb7efeb3 -r c2387f117808 sites/default/files/php/twig/5b44bda38f6c8_input.html.twig_jYi6QYvFpjKLYKZCId7BmHw8z/r2ecjTgY39CrAt2A3cPuk8DAJjququlhKjCNAdhZJHY.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/default/files/php/twig/5b44bda38f6c8_input.html.twig_jYi6QYvFpjKLYKZCId7BmHw8z/r2ecjTgY39CrAt2A3cPuk8DAJjququlhKjCNAdhZJHY.php Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,78 @@ +parent = false; + + $this->blocks = array( + ); + } + + protected function doDisplay(array $context, array $blocks = array()) + { + $tags = array(); + $filters = array(); + $functions = array(); + + try { + $this->env->getExtension('Twig_Extension_Sandbox')->checkSecurity( + array(), + array(), + array() + ); + } catch (Twig_Sandbox_SecurityError $e) { + $e->setSourceContext($this->getSourceContext()); + + if ($e instanceof Twig_Sandbox_SecurityNotAllowedTagError && isset($tags[$e->getTagName()])) { + $e->setTemplateLine($tags[$e->getTagName()]); + } elseif ($e instanceof Twig_Sandbox_SecurityNotAllowedFilterError && isset($filters[$e->getFilterName()])) { + $e->setTemplateLine($filters[$e->getFilterName()]); + } elseif ($e instanceof Twig_Sandbox_SecurityNotAllowedFunctionError && isset($functions[$e->getFunctionName()])) { + $e->setTemplateLine($functions[$e->getFunctionName()]); + } + + throw $e; + } + + // line 13 + echo "env->getExtension('Twig_Extension_Sandbox')->ensureToStringAllowed($this->env->getExtension('Drupal\Core\Template\TwigExtension')->escapeFilter($this->env, ($context["attributes"] ?? null), "html", null, true)); + echo " />"; + echo $this->env->getExtension('Twig_Extension_Sandbox')->ensureToStringAllowed($this->env->getExtension('Drupal\Core\Template\TwigExtension')->escapeFilter($this->env, ($context["children"] ?? null), "html", null, true)); + echo " +"; + } + + public function getTemplateName() + { + return "core/themes/classy/templates/form/input.html.twig"; + } + + public function isTraitable() + { + return false; + } + + public function getDebugInfo() + { + return array ( 43 => 13,); + } + + /** @deprecated since 1.27 (to be removed in 2.0). Use getSourceContext() instead */ + public function getSource() + { + @trigger_error('The '.__METHOD__.' method is deprecated since version 1.27 and will be removed in 2.0. Use getSourceContext() instead.', E_USER_DEPRECATED); + + return $this->getSourceContext()->getCode(); + } + + public function getSourceContext() + { + return new Twig_Source("", "core/themes/classy/templates/form/input.html.twig", "/var/www/sites/isophonics.net/core/themes/classy/templates/form/input.html.twig"); + } +} diff -r e200cb7efeb3 -r c2387f117808 sites/default/files/php/twig/5b44bda38f6c8_item-list--search-results_AOG7DZ9sgGhpd08tIyusrEEk1/.htaccess --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/default/files/php/twig/5b44bda38f6c8_item-list--search-results_AOG7DZ9sgGhpd08tIyusrEEk1/.htaccess Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,23 @@ +# Deny all requests from Apache 2.4+. + + Require all denied + + +# Deny all requests from Apache 2.0-2.2. + + Deny from all + +# Turn off all options we don't need. +Options -Indexes -ExecCGI -Includes -MultiViews + +# Set the catch-all handler to prevent scripts from being executed. +SetHandler Drupal_Security_Do_Not_Remove_See_SA_2006_006 + + # Override the handler again if we're run later in the evaluation list. + SetHandler Drupal_Security_Do_Not_Remove_See_SA_2013_003 + + +# If we know how to do it safely, disable the PHP engine entirely. + + php_flag engine off + \ No newline at end of file diff -r e200cb7efeb3 -r c2387f117808 sites/default/files/php/twig/5b44bda38f6c8_item-list--search-results_AOG7DZ9sgGhpd08tIyusrEEk1/OXWmOkpNo9e2gjaqld1hpIFIc4xo0IDB2mkGk1LHWCI.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/default/files/php/twig/5b44bda38f6c8_item-list--search-results_AOG7DZ9sgGhpd08tIyusrEEk1/OXWmOkpNo9e2gjaqld1hpIFIc4xo0IDB2mkGk1LHWCI.php Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,83 @@ +parent = $this->loadTemplate("item-list.html.twig", "core/themes/classy/templates/dataset/item-list--search-results.html.twig", 1); + $this->blocks = array( + ); + } + + protected function doGetParent(array $context) + { + return "item-list.html.twig"; + } + + protected function doDisplay(array $context, array $blocks = array()) + { + $tags = array("set" => 24); + $filters = array(); + $functions = array(); + + try { + $this->env->getExtension('Twig_Extension_Sandbox')->checkSecurity( + array('set'), + array(), + array() + ); + } catch (Twig_Sandbox_SecurityError $e) { + $e->setSourceContext($this->getSourceContext()); + + if ($e instanceof Twig_Sandbox_SecurityNotAllowedTagError && isset($tags[$e->getTagName()])) { + $e->setTemplateLine($tags[$e->getTagName()]); + } elseif ($e instanceof Twig_Sandbox_SecurityNotAllowedFilterError && isset($filters[$e->getFilterName()])) { + $e->setTemplateLine($filters[$e->getFilterName()]); + } elseif ($e instanceof Twig_Sandbox_SecurityNotAllowedFunctionError && isset($functions[$e->getFunctionName()])) { + $e->setTemplateLine($functions[$e->getFunctionName()]); + } + + throw $e; + } + + // line 24 + $context["classes"] = array(0 => "search-results", 1 => ($this->getAttribute( // line 26 +($context["context"] ?? null), "plugin", array()) . "-results")); + // line 29 + $context["attributes"] = $this->getAttribute(($context["attributes"] ?? null), "addClass", array(0 => ($context["classes"] ?? null)), "method"); + // line 1 + $this->parent->display($context, array_merge($this->blocks, $blocks)); + } + + public function getTemplateName() + { + return "core/themes/classy/templates/dataset/item-list--search-results.html.twig"; + } + + public function isTraitable() + { + return false; + } + + public function getDebugInfo() + { + return array ( 53 => 1, 51 => 29, 49 => 26, 48 => 24, 11 => 1,); + } + + /** @deprecated since 1.27 (to be removed in 2.0). Use getSourceContext() instead */ + public function getSource() + { + @trigger_error('The '.__METHOD__.' method is deprecated since version 1.27 and will be removed in 2.0. Use getSourceContext() instead.', E_USER_DEPRECATED); + + return $this->getSourceContext()->getCode(); + } + + public function getSourceContext() + { + return new Twig_Source("", "core/themes/classy/templates/dataset/item-list--search-results.html.twig", "/var/www/sites/isophonics.net/core/themes/classy/templates/dataset/item-list--search-results.html.twig"); + } +} diff -r e200cb7efeb3 -r c2387f117808 sites/default/files/php/twig/5b44bda38f6c8_item-list.html.twig_1SeskqGbWCrGtyFEp_cHSP1pB/.htaccess --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/default/files/php/twig/5b44bda38f6c8_item-list.html.twig_1SeskqGbWCrGtyFEp_cHSP1pB/.htaccess Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,23 @@ +# Deny all requests from Apache 2.4+. + + Require all denied + + +# Deny all requests from Apache 2.0-2.2. + + Deny from all + +# Turn off all options we don't need. +Options -Indexes -ExecCGI -Includes -MultiViews + +# Set the catch-all handler to prevent scripts from being executed. +SetHandler Drupal_Security_Do_Not_Remove_See_SA_2006_006 + + # Override the handler again if we're run later in the evaluation list. + SetHandler Drupal_Security_Do_Not_Remove_See_SA_2013_003 + + +# If we know how to do it safely, disable the PHP engine entirely. + + php_flag engine off + \ No newline at end of file diff -r e200cb7efeb3 -r c2387f117808 sites/default/files/php/twig/5b44bda38f6c8_item-list.html.twig_1SeskqGbWCrGtyFEp_cHSP1pB/DIXFPWZ2s4LzOz3RxMIjNJ0bXtOLa9v6crtsLYbZoxY.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/default/files/php/twig/5b44bda38f6c8_item-list.html.twig_1SeskqGbWCrGtyFEp_cHSP1pB/DIXFPWZ2s4LzOz3RxMIjNJ0bXtOLa9v6crtsLYbZoxY.php Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,123 @@ +parent = false; + + $this->blocks = array( + ); + } + + protected function doDisplay(array $context, array $blocks = array()) + { + $tags = array("if" => 22, "set" => 23, "for" => 33); + $filters = array(); + $functions = array(); + + try { + $this->env->getExtension('Twig_Extension_Sandbox')->checkSecurity( + array('if', 'set', 'for'), + array(), + array() + ); + } catch (Twig_Sandbox_SecurityError $e) { + $e->setSourceContext($this->getSourceContext()); + + if ($e instanceof Twig_Sandbox_SecurityNotAllowedTagError && isset($tags[$e->getTagName()])) { + $e->setTemplateLine($tags[$e->getTagName()]); + } elseif ($e instanceof Twig_Sandbox_SecurityNotAllowedFilterError && isset($filters[$e->getFilterName()])) { + $e->setTemplateLine($filters[$e->getFilterName()]); + } elseif ($e instanceof Twig_Sandbox_SecurityNotAllowedFunctionError && isset($functions[$e->getFunctionName()])) { + $e->setTemplateLine($functions[$e->getFunctionName()]); + } + + throw $e; + } + + // line 22 + if ($this->getAttribute(($context["context"] ?? null), "list_style", array())) { + // line 23 + $context["wrapper_attributes"] = $this->getAttribute(($context["wrapper_attributes"] ?? null), "addClass", array(0 => ("item-list--" . $this->getAttribute(($context["context"] ?? null), "list_style", array()))), "method"); + // line 24 + $context["attributes"] = $this->getAttribute(($context["attributes"] ?? null), "addClass", array(0 => ("item-list__" . $this->getAttribute(($context["context"] ?? null), "list_style", array()))), "method"); + } + // line 26 + if ((($context["items"] ?? null) || ($context["empty"] ?? null))) { + // line 27 + echo "env->getExtension('Twig_Extension_Sandbox')->ensureToStringAllowed($this->env->getExtension('Drupal\Core\Template\TwigExtension')->escapeFilter($this->env, $this->getAttribute(($context["wrapper_attributes"] ?? null), "addClass", array(0 => "item-list"), "method"), "html", null, true)); + echo ">"; + // line 28 + if ( !twig_test_empty(($context["title"] ?? null))) { + // line 29 + echo "

        "; + echo $this->env->getExtension('Twig_Extension_Sandbox')->ensureToStringAllowed($this->env->getExtension('Drupal\Core\Template\TwigExtension')->escapeFilter($this->env, ($context["title"] ?? null), "html", null, true)); + echo "

        "; + } + // line 31 + if (($context["items"] ?? null)) { + // line 32 + echo "<"; + echo $this->env->getExtension('Twig_Extension_Sandbox')->ensureToStringAllowed($this->env->getExtension('Drupal\Core\Template\TwigExtension')->escapeFilter($this->env, ($context["list_type"] ?? null), "html", null, true)); + echo $this->env->getExtension('Twig_Extension_Sandbox')->ensureToStringAllowed($this->env->getExtension('Drupal\Core\Template\TwigExtension')->escapeFilter($this->env, ($context["attributes"] ?? null), "html", null, true)); + echo ">"; + // line 33 + $context['_parent'] = $context; + $context['_seq'] = twig_ensure_traversable(($context["items"] ?? null)); + foreach ($context['_seq'] as $context["_key"] => $context["item"]) { + // line 34 + echo "env->getExtension('Twig_Extension_Sandbox')->ensureToStringAllowed($this->env->getExtension('Drupal\Core\Template\TwigExtension')->escapeFilter($this->env, $this->getAttribute($context["item"], "attributes", array()), "html", null, true)); + echo ">"; + echo $this->env->getExtension('Twig_Extension_Sandbox')->ensureToStringAllowed($this->env->getExtension('Drupal\Core\Template\TwigExtension')->escapeFilter($this->env, $this->getAttribute($context["item"], "value", array()), "html", null, true)); + echo ""; + } + $_parent = $context['_parent']; + unset($context['_seq'], $context['_iterated'], $context['_key'], $context['item'], $context['_parent'], $context['loop']); + $context = array_intersect_key($context, $_parent) + $_parent; + // line 36 + echo "env->getExtension('Twig_Extension_Sandbox')->ensureToStringAllowed($this->env->getExtension('Drupal\Core\Template\TwigExtension')->escapeFilter($this->env, ($context["list_type"] ?? null), "html", null, true)); + echo ">"; + } else { + // line 38 + echo $this->env->getExtension('Twig_Extension_Sandbox')->ensureToStringAllowed($this->env->getExtension('Drupal\Core\Template\TwigExtension')->escapeFilter($this->env, ($context["empty"] ?? null), "html", null, true)); + } + // line 40 + echo ""; + } + } + + public function getTemplateName() + { + return "item-list.html.twig"; + } + + public function isTraitable() + { + return false; + } + + public function getDebugInfo() + { + return array ( 92 => 40, 89 => 38, 84 => 36, 74 => 34, 70 => 33, 65 => 32, 63 => 31, 58 => 29, 56 => 28, 52 => 27, 50 => 26, 47 => 24, 45 => 23, 43 => 22,); + } + + /** @deprecated since 1.27 (to be removed in 2.0). Use getSourceContext() instead */ + public function getSource() + { + @trigger_error('The '.__METHOD__.' method is deprecated since version 1.27 and will be removed in 2.0. Use getSourceContext() instead.', E_USER_DEPRECATED); + + return $this->getSourceContext()->getCode(); + } + + public function getSourceContext() + { + return new Twig_Source("", "item-list.html.twig", "core/themes/classy/templates/dataset/item-list.html.twig"); + } +} diff -r e200cb7efeb3 -r c2387f117808 sites/default/files/php/twig/5b44bda38f6c8_links--node.html.twig_1wXe-HY27nDkstwTVbPk4uUqL/.htaccess --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/default/files/php/twig/5b44bda38f6c8_links--node.html.twig_1wXe-HY27nDkstwTVbPk4uUqL/.htaccess Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,23 @@ +# Deny all requests from Apache 2.4+. + + Require all denied + + +# Deny all requests from Apache 2.0-2.2. + + Deny from all + +# Turn off all options we don't need. +Options -Indexes -ExecCGI -Includes -MultiViews + +# Set the catch-all handler to prevent scripts from being executed. +SetHandler Drupal_Security_Do_Not_Remove_See_SA_2006_006 + + # Override the handler again if we're run later in the evaluation list. + SetHandler Drupal_Security_Do_Not_Remove_See_SA_2013_003 + + +# If we know how to do it safely, disable the PHP engine entirely. + + php_flag engine off + \ No newline at end of file diff -r e200cb7efeb3 -r c2387f117808 sites/default/files/php/twig/5b44bda38f6c8_links--node.html.twig_1wXe-HY27nDkstwTVbPk4uUqL/74qKZwgKO7c4zFwOTvwr4hjdznWtPMDwhzGTWtbKyLU.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/default/files/php/twig/5b44bda38f6c8_links--node.html.twig_1wXe-HY27nDkstwTVbPk4uUqL/74qKZwgKO7c4zFwOTvwr4hjdznWtPMDwhzGTWtbKyLU.php Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,82 @@ +parent = false; + + $this->blocks = array( + ); + } + + protected function doDisplay(array $context, array $blocks = array()) + { + $tags = array("if" => 36, "include" => 38); + $filters = array(); + $functions = array(); + + try { + $this->env->getExtension('Twig_Extension_Sandbox')->checkSecurity( + array('if', 'include'), + array(), + array() + ); + } catch (Twig_Sandbox_SecurityError $e) { + $e->setSourceContext($this->getSourceContext()); + + if ($e instanceof Twig_Sandbox_SecurityNotAllowedTagError && isset($tags[$e->getTagName()])) { + $e->setTemplateLine($tags[$e->getTagName()]); + } elseif ($e instanceof Twig_Sandbox_SecurityNotAllowedFilterError && isset($filters[$e->getFilterName()])) { + $e->setTemplateLine($filters[$e->getFilterName()]); + } elseif ($e instanceof Twig_Sandbox_SecurityNotAllowedFunctionError && isset($functions[$e->getFunctionName()])) { + $e->setTemplateLine($functions[$e->getFunctionName()]); + } + + throw $e; + } + + // line 36 + if (($context["links"] ?? null)) { + // line 37 + echo "
        + "; + // line 38 + $this->loadTemplate("links.html.twig", "core/themes/classy/templates/content/links--node.html.twig", 38)->display($context); + // line 39 + echo "
        +"; + } + } + + public function getTemplateName() + { + return "core/themes/classy/templates/content/links--node.html.twig"; + } + + public function isTraitable() + { + return false; + } + + public function getDebugInfo() + { + return array ( 50 => 39, 48 => 38, 45 => 37, 43 => 36,); + } + + /** @deprecated since 1.27 (to be removed in 2.0). Use getSourceContext() instead */ + public function getSource() + { + @trigger_error('The '.__METHOD__.' method is deprecated since version 1.27 and will be removed in 2.0. Use getSourceContext() instead.', E_USER_DEPRECATED); + + return $this->getSourceContext()->getCode(); + } + + public function getSourceContext() + { + return new Twig_Source("", "core/themes/classy/templates/content/links--node.html.twig", "/var/www/sites/isophonics.net/core/themes/classy/templates/content/links--node.html.twig"); + } +} diff -r e200cb7efeb3 -r c2387f117808 sites/default/files/php/twig/5b44bda38f6c8_off-canvas-page-wrapper.h_hlAfqNqVOta6cQY1nMpQqxAZ7/.htaccess --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/default/files/php/twig/5b44bda38f6c8_off-canvas-page-wrapper.h_hlAfqNqVOta6cQY1nMpQqxAZ7/.htaccess Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,23 @@ +# Deny all requests from Apache 2.4+. + + Require all denied + + +# Deny all requests from Apache 2.0-2.2. + + Deny from all + +# Turn off all options we don't need. +Options -Indexes -ExecCGI -Includes -MultiViews + +# Set the catch-all handler to prevent scripts from being executed. +SetHandler Drupal_Security_Do_Not_Remove_See_SA_2006_006 + + # Override the handler again if we're run later in the evaluation list. + SetHandler Drupal_Security_Do_Not_Remove_See_SA_2013_003 + + +# If we know how to do it safely, disable the PHP engine entirely. + + php_flag engine off + \ No newline at end of file diff -r e200cb7efeb3 -r c2387f117808 sites/default/files/php/twig/5b44bda38f6c8_off-canvas-page-wrapper.h_hlAfqNqVOta6cQY1nMpQqxAZ7/IqqUP26JdL-23XIHqf-QEOq_F7CxG3cFyOG5db-r574.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/default/files/php/twig/5b44bda38f6c8_off-canvas-page-wrapper.h_hlAfqNqVOta6cQY1nMpQqxAZ7/IqqUP26JdL-23XIHqf-QEOq_F7CxG3cFyOG5db-r574.php Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,82 @@ +parent = false; + + $this->blocks = array( + ); + } + + protected function doDisplay(array $context, array $blocks = array()) + { + $tags = array("if" => 20); + $filters = array(); + $functions = array(); + + try { + $this->env->getExtension('Twig_Extension_Sandbox')->checkSecurity( + array('if'), + array(), + array() + ); + } catch (Twig_Sandbox_SecurityError $e) { + $e->setSourceContext($this->getSourceContext()); + + if ($e instanceof Twig_Sandbox_SecurityNotAllowedTagError && isset($tags[$e->getTagName()])) { + $e->setTemplateLine($tags[$e->getTagName()]); + } elseif ($e instanceof Twig_Sandbox_SecurityNotAllowedFilterError && isset($filters[$e->getFilterName()])) { + $e->setTemplateLine($filters[$e->getFilterName()]); + } elseif ($e instanceof Twig_Sandbox_SecurityNotAllowedFunctionError && isset($functions[$e->getFunctionName()])) { + $e->setTemplateLine($functions[$e->getFunctionName()]); + } + + throw $e; + } + + // line 20 + if (($context["children"] ?? null)) { + // line 21 + echo "
        + "; + // line 22 + echo $this->env->getExtension('Twig_Extension_Sandbox')->ensureToStringAllowed($this->env->getExtension('Drupal\Core\Template\TwigExtension')->escapeFilter($this->env, ($context["children"] ?? null), "html", null, true)); + echo " +
        +"; + } + } + + public function getTemplateName() + { + return "core/themes/stable/templates/content/off-canvas-page-wrapper.html.twig"; + } + + public function isTraitable() + { + return false; + } + + public function getDebugInfo() + { + return array ( 48 => 22, 45 => 21, 43 => 20,); + } + + /** @deprecated since 1.27 (to be removed in 2.0). Use getSourceContext() instead */ + public function getSource() + { + @trigger_error('The '.__METHOD__.' method is deprecated since version 1.27 and will be removed in 2.0. Use getSourceContext() instead.', E_USER_DEPRECATED); + + return $this->getSourceContext()->getCode(); + } + + public function getSourceContext() + { + return new Twig_Source("", "core/themes/stable/templates/content/off-canvas-page-wrapper.html.twig", "/var/www/sites/isophonics.net/core/themes/stable/templates/content/off-canvas-page-wrapper.html.twig"); + } +} diff -r e200cb7efeb3 -r c2387f117808 sites/default/files/php/twig/5b44bda38f6c8_page-title.html.twig_5-d0Vm9L73Nnquj8G5WDwO2eX/.htaccess --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/default/files/php/twig/5b44bda38f6c8_page-title.html.twig_5-d0Vm9L73Nnquj8G5WDwO2eX/.htaccess Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,23 @@ +# Deny all requests from Apache 2.4+. + + Require all denied + + +# Deny all requests from Apache 2.0-2.2. + + Deny from all + +# Turn off all options we don't need. +Options -Indexes -ExecCGI -Includes -MultiViews + +# Set the catch-all handler to prevent scripts from being executed. +SetHandler Drupal_Security_Do_Not_Remove_See_SA_2006_006 + + # Override the handler again if we're run later in the evaluation list. + SetHandler Drupal_Security_Do_Not_Remove_See_SA_2013_003 + + +# If we know how to do it safely, disable the PHP engine entirely. + + php_flag engine off + \ No newline at end of file diff -r e200cb7efeb3 -r c2387f117808 sites/default/files/php/twig/5b44bda38f6c8_page-title.html.twig_5-d0Vm9L73Nnquj8G5WDwO2eX/hkQTkSizjnMTE104hZQHhoc76mRNQGunxyGxy8ijpgE.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/default/files/php/twig/5b44bda38f6c8_page-title.html.twig_5-d0Vm9L73Nnquj8G5WDwO2eX/hkQTkSizjnMTE104hZQHhoc76mRNQGunxyGxy8ijpgE.php Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,80 @@ +parent = $this->loadTemplate("@classy/content/page-title.html.twig", "themes/isobartik/templates/page-title.html.twig", 1); + $this->blocks = array( + ); + } + + protected function doGetParent(array $context) + { + return "@classy/content/page-title.html.twig"; + } + + protected function doDisplay(array $context, array $blocks = array()) + { + $tags = array("set" => 16); + $filters = array(); + $functions = array(); + + try { + $this->env->getExtension('Twig_Extension_Sandbox')->checkSecurity( + array('set'), + array(), + array() + ); + } catch (Twig_Sandbox_SecurityError $e) { + $e->setSourceContext($this->getSourceContext()); + + if ($e instanceof Twig_Sandbox_SecurityNotAllowedTagError && isset($tags[$e->getTagName()])) { + $e->setTemplateLine($tags[$e->getTagName()]); + } elseif ($e instanceof Twig_Sandbox_SecurityNotAllowedFilterError && isset($filters[$e->getFilterName()])) { + $e->setTemplateLine($filters[$e->getFilterName()]); + } elseif ($e instanceof Twig_Sandbox_SecurityNotAllowedFunctionError && isset($functions[$e->getFunctionName()])) { + $e->setTemplateLine($functions[$e->getFunctionName()]); + } + + throw $e; + } + + // line 16 + $context["title_attributes"] = $this->getAttribute(($context["title_attributes"] ?? null), "addClass", array(0 => "title"), "method"); + // line 1 + $this->parent->display($context, array_merge($this->blocks, $blocks)); + } + + public function getTemplateName() + { + return "themes/isobartik/templates/page-title.html.twig"; + } + + public function isTraitable() + { + return false; + } + + public function getDebugInfo() + { + return array ( 50 => 1, 48 => 16, 11 => 1,); + } + + /** @deprecated since 1.27 (to be removed in 2.0). Use getSourceContext() instead */ + public function getSource() + { + @trigger_error('The '.__METHOD__.' method is deprecated since version 1.27 and will be removed in 2.0. Use getSourceContext() instead.', E_USER_DEPRECATED); + + return $this->getSourceContext()->getCode(); + } + + public function getSourceContext() + { + return new Twig_Source("", "themes/isobartik/templates/page-title.html.twig", "/var/www/sites/isophonics.net/themes/isobartik/templates/page-title.html.twig"); + } +} diff -r e200cb7efeb3 -r c2387f117808 sites/default/files/php/twig/5b44bda38f6c8_page-title.html.twig_Kj22JzrbuWqFmqffbsmZOndRV/.htaccess --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/default/files/php/twig/5b44bda38f6c8_page-title.html.twig_Kj22JzrbuWqFmqffbsmZOndRV/.htaccess Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,23 @@ +# Deny all requests from Apache 2.4+. + + Require all denied + + +# Deny all requests from Apache 2.0-2.2. + + Deny from all + +# Turn off all options we don't need. +Options -Indexes -ExecCGI -Includes -MultiViews + +# Set the catch-all handler to prevent scripts from being executed. +SetHandler Drupal_Security_Do_Not_Remove_See_SA_2006_006 + + # Override the handler again if we're run later in the evaluation list. + SetHandler Drupal_Security_Do_Not_Remove_See_SA_2013_003 + + +# If we know how to do it safely, disable the PHP engine entirely. + + php_flag engine off + \ No newline at end of file diff -r e200cb7efeb3 -r c2387f117808 sites/default/files/php/twig/5b44bda38f6c8_page-title.html.twig_Kj22JzrbuWqFmqffbsmZOndRV/ojhPk442PlqcAWfWrk3Cceq--q_wEpe0AUw4foQ0fxQ.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/default/files/php/twig/5b44bda38f6c8_page-title.html.twig_Kj22JzrbuWqFmqffbsmZOndRV/ojhPk442PlqcAWfWrk3Cceq--q_wEpe0AUw4foQ0fxQ.php Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,89 @@ +parent = false; + + $this->blocks = array( + ); + } + + protected function doDisplay(array $context, array $blocks = array()) + { + $tags = array("if" => 16); + $filters = array(); + $functions = array(); + + try { + $this->env->getExtension('Twig_Extension_Sandbox')->checkSecurity( + array('if'), + array(), + array() + ); + } catch (Twig_Sandbox_SecurityError $e) { + $e->setSourceContext($this->getSourceContext()); + + if ($e instanceof Twig_Sandbox_SecurityNotAllowedTagError && isset($tags[$e->getTagName()])) { + $e->setTemplateLine($tags[$e->getTagName()]); + } elseif ($e instanceof Twig_Sandbox_SecurityNotAllowedFilterError && isset($filters[$e->getFilterName()])) { + $e->setTemplateLine($filters[$e->getFilterName()]); + } elseif ($e instanceof Twig_Sandbox_SecurityNotAllowedFunctionError && isset($functions[$e->getFunctionName()])) { + $e->setTemplateLine($functions[$e->getFunctionName()]); + } + + throw $e; + } + + // line 15 + echo $this->env->getExtension('Twig_Extension_Sandbox')->ensureToStringAllowed($this->env->getExtension('Drupal\Core\Template\TwigExtension')->escapeFilter($this->env, ($context["title_prefix"] ?? null), "html", null, true)); + echo " +"; + // line 16 + if (($context["title"] ?? null)) { + // line 17 + echo " env->getExtension('Twig_Extension_Sandbox')->ensureToStringAllowed($this->env->getExtension('Drupal\Core\Template\TwigExtension')->escapeFilter($this->env, $this->getAttribute(($context["title_attributes"] ?? null), "addClass", array(0 => "page-title"), "method"), "html", null, true)); + echo ">"; + echo $this->env->getExtension('Twig_Extension_Sandbox')->ensureToStringAllowed($this->env->getExtension('Drupal\Core\Template\TwigExtension')->escapeFilter($this->env, ($context["title"] ?? null), "html", null, true)); + echo " +"; + } + // line 19 + echo $this->env->getExtension('Twig_Extension_Sandbox')->ensureToStringAllowed($this->env->getExtension('Drupal\Core\Template\TwigExtension')->escapeFilter($this->env, ($context["title_suffix"] ?? null), "html", null, true)); + echo " +"; + } + + public function getTemplateName() + { + return "@classy/content/page-title.html.twig"; + } + + public function isTraitable() + { + return false; + } + + public function getDebugInfo() + { + return array ( 57 => 19, 49 => 17, 47 => 16, 43 => 15,); + } + + /** @deprecated since 1.27 (to be removed in 2.0). Use getSourceContext() instead */ + public function getSource() + { + @trigger_error('The '.__METHOD__.' method is deprecated since version 1.27 and will be removed in 2.0. Use getSourceContext() instead.', E_USER_DEPRECATED); + + return $this->getSourceContext()->getCode(); + } + + public function getSourceContext() + { + return new Twig_Source("", "@classy/content/page-title.html.twig", "/var/www/sites/isophonics.net/core/themes/classy/templates/content/page-title.html.twig"); + } +} diff -r e200cb7efeb3 -r c2387f117808 sites/default/files/php/twig/5b44bda38f6c8_page.html.twig_izP4tzIqfiN5N6VS1seT4HkZg/.htaccess --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/default/files/php/twig/5b44bda38f6c8_page.html.twig_izP4tzIqfiN5N6VS1seT4HkZg/.htaccess Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,23 @@ +# Deny all requests from Apache 2.4+. + + Require all denied + + +# Deny all requests from Apache 2.0-2.2. + + Deny from all + +# Turn off all options we don't need. +Options -Indexes -ExecCGI -Includes -MultiViews + +# Set the catch-all handler to prevent scripts from being executed. +SetHandler Drupal_Security_Do_Not_Remove_See_SA_2006_006 + + # Override the handler again if we're run later in the evaluation list. + SetHandler Drupal_Security_Do_Not_Remove_See_SA_2013_003 + + +# If we know how to do it safely, disable the PHP engine entirely. + + php_flag engine off + \ No newline at end of file diff -r e200cb7efeb3 -r c2387f117808 sites/default/files/php/twig/5b44bda38f6c8_page.html.twig_izP4tzIqfiN5N6VS1seT4HkZg/d0-XJwTLx7VK59KnnGnUoMRC41TyhOIQwMDhTaRU0wU.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/default/files/php/twig/5b44bda38f6c8_page.html.twig_izP4tzIqfiN5N6VS1seT4HkZg/d0-XJwTLx7VK59KnnGnUoMRC41TyhOIQwMDhTaRU0wU.php Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,235 @@ +parent = false; + + $this->blocks = array( + ); + } + + protected function doDisplay(array $context, array $blocks = array()) + { + $tags = array("if" => 62); + $filters = array("t" => 55); + $functions = array(); + + try { + $this->env->getExtension('Twig_Extension_Sandbox')->checkSecurity( + array('if'), + array('t'), + array() + ); + } catch (Twig_Sandbox_SecurityError $e) { + $e->setSourceContext($this->getSourceContext()); + + if ($e instanceof Twig_Sandbox_SecurityNotAllowedTagError && isset($tags[$e->getTagName()])) { + $e->setTemplateLine($tags[$e->getTagName()]); + } elseif ($e instanceof Twig_Sandbox_SecurityNotAllowedFilterError && isset($filters[$e->getFilterName()])) { + $e->setTemplateLine($filters[$e->getFilterName()]); + } elseif ($e instanceof Twig_Sandbox_SecurityNotAllowedFunctionError && isset($functions[$e->getFunctionName()])) { + $e->setTemplateLine($functions[$e->getFunctionName()]); + } + + throw $e; + } + + // line 53 + echo "
        +
        +
        env->getExtension('Twig_Extension_Sandbox')->ensureToStringAllowed($this->env->getExtension('Drupal\Core\Template\TwigExtension')->renderVar(t("Site header"))); + echo "\"> +
        + "; + // line 57 + echo $this->env->getExtension('Twig_Extension_Sandbox')->ensureToStringAllowed($this->env->getExtension('Drupal\Core\Template\TwigExtension')->escapeFilter($this->env, $this->getAttribute(($context["page"] ?? null), "secondary_menu", array()), "html", null, true)); + echo " + "; + // line 58 + echo $this->env->getExtension('Twig_Extension_Sandbox')->ensureToStringAllowed($this->env->getExtension('Drupal\Core\Template\TwigExtension')->escapeFilter($this->env, $this->getAttribute(($context["page"] ?? null), "header", array()), "html", null, true)); + echo " + "; + // line 59 + echo $this->env->getExtension('Twig_Extension_Sandbox')->ensureToStringAllowed($this->env->getExtension('Drupal\Core\Template\TwigExtension')->escapeFilter($this->env, $this->getAttribute(($context["page"] ?? null), "primary_menu", array()), "html", null, true)); + echo " +
        +
        + "; + // line 62 + if ($this->getAttribute(($context["page"] ?? null), "highlighted", array())) { + // line 63 + echo "
        + +
        + "; + } + // line 69 + echo " "; + if ($this->getAttribute(($context["page"] ?? null), "featured_top", array())) { + // line 70 + echo "
        + +
        + "; + } + // line 76 + echo "
        +
        + "; + // line 78 + echo $this->env->getExtension('Twig_Extension_Sandbox')->ensureToStringAllowed($this->env->getExtension('Drupal\Core\Template\TwigExtension')->escapeFilter($this->env, $this->getAttribute(($context["page"] ?? null), "breadcrumb", array()), "html", null, true)); + echo " +
        +
        + + "; + // line 82 + echo $this->env->getExtension('Twig_Extension_Sandbox')->ensureToStringAllowed($this->env->getExtension('Drupal\Core\Template\TwigExtension')->escapeFilter($this->env, $this->getAttribute(($context["page"] ?? null), "content", array()), "html", null, true)); + echo " +
        +
        + "; + // line 85 + if ($this->getAttribute(($context["page"] ?? null), "sidebar_first", array())) { + // line 86 + echo "
        + +
        + "; + } + // line 92 + echo " "; + if ($this->getAttribute(($context["page"] ?? null), "sidebar_second", array())) { + // line 93 + echo "
        + +
        + "; + } + // line 99 + echo "
        +
        + "; + // line 101 + if ((($this->getAttribute(($context["page"] ?? null), "featured_bottom_first", array()) || $this->getAttribute(($context["page"] ?? null), "featured_bottom_second", array())) || $this->getAttribute(($context["page"] ?? null), "featured_bottom_third", array()))) { + // line 102 + echo "
        + +
        + "; + } + // line 110 + echo "
        +
        + "; + // line 112 + if (((($this->getAttribute(($context["page"] ?? null), "footer_first", array()) || $this->getAttribute(($context["page"] ?? null), "footer_second", array())) || $this->getAttribute(($context["page"] ?? null), "footer_third", array())) || $this->getAttribute(($context["page"] ?? null), "footer_fourth", array()))) { + // line 113 + echo " + "; + } + // line 120 + echo " "; + if ($this->getAttribute(($context["page"] ?? null), "footer_fifth", array())) { + // line 121 + echo " + "; + } + // line 125 + echo "
        +
        +
        +
        +"; + } + + public function getTemplateName() + { + return "themes/isobartik/templates/page.html.twig"; + } + + public function isTraitable() + { + return false; + } + + public function getDebugInfo() + { + return array ( 201 => 125, 195 => 122, 192 => 121, 189 => 120, 183 => 117, 179 => 116, 175 => 115, 171 => 114, 168 => 113, 166 => 112, 162 => 110, 155 => 106, 151 => 105, 147 => 104, 143 => 102, 141 => 101, 137 => 99, 130 => 95, 126 => 93, 123 => 92, 116 => 88, 112 => 86, 110 => 85, 104 => 82, 97 => 78, 93 => 76, 86 => 72, 82 => 70, 79 => 69, 72 => 65, 68 => 63, 66 => 62, 60 => 59, 56 => 58, 52 => 57, 47 => 55, 43 => 53,); + } + + /** @deprecated since 1.27 (to be removed in 2.0). Use getSourceContext() instead */ + public function getSource() + { + @trigger_error('The '.__METHOD__.' method is deprecated since version 1.27 and will be removed in 2.0. Use getSourceContext() instead.', E_USER_DEPRECATED); + + return $this->getSourceContext()->getCode(); + } + + public function getSourceContext() + { + return new Twig_Source("", "themes/isobartik/templates/page.html.twig", "/var/www/sites/isophonics.net/themes/isobartik/templates/page.html.twig"); + } +} diff -r e200cb7efeb3 -r c2387f117808 sites/default/files/php/twig/5b44bda38f6c8_pager.html.twig_sbCI69R_UAdtPaGn0ZzTyeyem/.htaccess --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/default/files/php/twig/5b44bda38f6c8_pager.html.twig_sbCI69R_UAdtPaGn0ZzTyeyem/.htaccess Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,23 @@ +# Deny all requests from Apache 2.4+. + + Require all denied + + +# Deny all requests from Apache 2.0-2.2. + + Deny from all + +# Turn off all options we don't need. +Options -Indexes -ExecCGI -Includes -MultiViews + +# Set the catch-all handler to prevent scripts from being executed. +SetHandler Drupal_Security_Do_Not_Remove_See_SA_2006_006 + + # Override the handler again if we're run later in the evaluation list. + SetHandler Drupal_Security_Do_Not_Remove_See_SA_2013_003 + + +# If we know how to do it safely, disable the PHP engine entirely. + + php_flag engine off + \ No newline at end of file diff -r e200cb7efeb3 -r c2387f117808 sites/default/files/php/twig/5b44bda38f6c8_pager.html.twig_sbCI69R_UAdtPaGn0ZzTyeyem/dhSIO2cZpmUPnuomWC78RBKoaIUMg6kUHftHSgDEhlQ.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/default/files/php/twig/5b44bda38f6c8_pager.html.twig_sbCI69R_UAdtPaGn0ZzTyeyem/dhSIO2cZpmUPnuomWC78RBKoaIUMg6kUHftHSgDEhlQ.php Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,260 @@ +parent = false; + + $this->blocks = array( + ); + } + + protected function doDisplay(array $context, array $blocks = array()) + { + $tags = array("if" => 32, "for" => 59, "set" => 62); + $filters = array("t" => 34, "without" => 39, "default" => 41); + $functions = array(); + + try { + $this->env->getExtension('Twig_Extension_Sandbox')->checkSecurity( + array('if', 'for', 'set'), + array('t', 'without', 'default'), + array() + ); + } catch (Twig_Sandbox_SecurityError $e) { + $e->setSourceContext($this->getSourceContext()); + + if ($e instanceof Twig_Sandbox_SecurityNotAllowedTagError && isset($tags[$e->getTagName()])) { + $e->setTemplateLine($tags[$e->getTagName()]); + } elseif ($e instanceof Twig_Sandbox_SecurityNotAllowedFilterError && isset($filters[$e->getFilterName()])) { + $e->setTemplateLine($filters[$e->getFilterName()]); + } elseif ($e instanceof Twig_Sandbox_SecurityNotAllowedFunctionError && isset($functions[$e->getFunctionName()])) { + $e->setTemplateLine($functions[$e->getFunctionName()]); + } + + throw $e; + } + + // line 32 + if (($context["items"] ?? null)) { + // line 33 + echo " +"; + } + } + + public function getTemplateName() + { + return "core/themes/classy/templates/navigation/pager.html.twig"; + } + + public function isTraitable() + { + return false; + } + + public function getDebugInfo() + { + return array ( 227 => 96, 220 => 92, 216 => 91, 208 => 90, 205 => 89, 202 => 88, 200 => 87, 193 => 83, 189 => 82, 181 => 81, 178 => 80, 175 => 79, 173 => 78, 169 => 76, 166 => 75, 164 => 74, 156 => 71, 154 => 70, 150 => 68, 140 => 66, 137 => 65, 134 => 64, 131 => 63, 128 => 62, 126 => 61, 121 => 60, 116 => 59, 114 => 58, 110 => 56, 107 => 55, 105 => 54, 98 => 50, 94 => 49, 86 => 48, 83 => 47, 80 => 46, 78 => 45, 71 => 41, 67 => 40, 59 => 39, 56 => 38, 53 => 37, 48 => 34, 45 => 33, 43 => 32,); + } + + /** @deprecated since 1.27 (to be removed in 2.0). Use getSourceContext() instead */ + public function getSource() + { + @trigger_error('The '.__METHOD__.' method is deprecated since version 1.27 and will be removed in 2.0. Use getSourceContext() instead.', E_USER_DEPRECATED); + + return $this->getSourceContext()->getCode(); + } + + public function getSourceContext() + { + return new Twig_Source("", "core/themes/classy/templates/navigation/pager.html.twig", "/var/www/sites/isophonics.net/core/themes/classy/templates/navigation/pager.html.twig"); + } +} diff -r e200cb7efeb3 -r c2387f117808 sites/default/files/php/twig/5b44bda38f6c8_region.html.twig_MR3fMmw95qbpuDFvbyuI9QHlG/.htaccess --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/default/files/php/twig/5b44bda38f6c8_region.html.twig_MR3fMmw95qbpuDFvbyuI9QHlG/.htaccess Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,23 @@ +# Deny all requests from Apache 2.4+. + + Require all denied + + +# Deny all requests from Apache 2.0-2.2. + + Deny from all + +# Turn off all options we don't need. +Options -Indexes -ExecCGI -Includes -MultiViews + +# Set the catch-all handler to prevent scripts from being executed. +SetHandler Drupal_Security_Do_Not_Remove_See_SA_2006_006 + + # Override the handler again if we're run later in the evaluation list. + SetHandler Drupal_Security_Do_Not_Remove_See_SA_2013_003 + + +# If we know how to do it safely, disable the PHP engine entirely. + + php_flag engine off + \ No newline at end of file diff -r e200cb7efeb3 -r c2387f117808 sites/default/files/php/twig/5b44bda38f6c8_region.html.twig_MR3fMmw95qbpuDFvbyuI9QHlG/OPpJWtngDr-xBzr2XCf9iGefuc42mCN6vd9ZVKbAoXg.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/default/files/php/twig/5b44bda38f6c8_region.html.twig_MR3fMmw95qbpuDFvbyuI9QHlG/OPpJWtngDr-xBzr2XCf9iGefuc42mCN6vd9ZVKbAoXg.php Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,87 @@ +parent = false; + + $this->blocks = array( + ); + } + + protected function doDisplay(array $context, array $blocks = array()) + { + $tags = array("set" => 16, "if" => 21); + $filters = array("clean_class" => 18); + $functions = array(); + + try { + $this->env->getExtension('Twig_Extension_Sandbox')->checkSecurity( + array('set', 'if'), + array('clean_class'), + array() + ); + } catch (Twig_Sandbox_SecurityError $e) { + $e->setSourceContext($this->getSourceContext()); + + if ($e instanceof Twig_Sandbox_SecurityNotAllowedTagError && isset($tags[$e->getTagName()])) { + $e->setTemplateLine($tags[$e->getTagName()]); + } elseif ($e instanceof Twig_Sandbox_SecurityNotAllowedFilterError && isset($filters[$e->getFilterName()])) { + $e->setTemplateLine($filters[$e->getFilterName()]); + } elseif ($e instanceof Twig_Sandbox_SecurityNotAllowedFunctionError && isset($functions[$e->getFunctionName()])) { + $e->setTemplateLine($functions[$e->getFunctionName()]); + } + + throw $e; + } + + // line 16 + $context["classes"] = array(0 => "region", 1 => ("region-" . \Drupal\Component\Utility\Html::getClass( // line 18 +($context["region"] ?? null)))); + // line 21 + if (($context["content"] ?? null)) { + // line 22 + echo " env->getExtension('Twig_Extension_Sandbox')->ensureToStringAllowed($this->env->getExtension('Drupal\Core\Template\TwigExtension')->escapeFilter($this->env, $this->getAttribute(($context["attributes"] ?? null), "addClass", array(0 => ($context["classes"] ?? null)), "method"), "html", null, true)); + echo "> + "; + // line 23 + echo $this->env->getExtension('Twig_Extension_Sandbox')->ensureToStringAllowed($this->env->getExtension('Drupal\Core\Template\TwigExtension')->escapeFilter($this->env, ($context["content"] ?? null), "html", null, true)); + echo " + +"; + } + } + + public function getTemplateName() + { + return "core/themes/classy/templates/layout/region.html.twig"; + } + + public function isTraitable() + { + return false; + } + + public function getDebugInfo() + { + return array ( 53 => 23, 48 => 22, 46 => 21, 44 => 18, 43 => 16,); + } + + /** @deprecated since 1.27 (to be removed in 2.0). Use getSourceContext() instead */ + public function getSource() + { + @trigger_error('The '.__METHOD__.' method is deprecated since version 1.27 and will be removed in 2.0. Use getSourceContext() instead.', E_USER_DEPRECATED); + + return $this->getSourceContext()->getCode(); + } + + public function getSourceContext() + { + return new Twig_Source("", "core/themes/classy/templates/layout/region.html.twig", "/var/www/sites/isophonics.net/core/themes/classy/templates/layout/region.html.twig"); + } +} diff -r e200cb7efeb3 -r c2387f117808 sites/default/files/php/twig/5b44bda38f6c8_search-result.html.twig_9RRL7IDU5vq0GQTMD1MTgd-jl/.htaccess --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/default/files/php/twig/5b44bda38f6c8_search-result.html.twig_9RRL7IDU5vq0GQTMD1MTgd-jl/.htaccess Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,23 @@ +# Deny all requests from Apache 2.4+. + + Require all denied + + +# Deny all requests from Apache 2.0-2.2. + + Deny from all + +# Turn off all options we don't need. +Options -Indexes -ExecCGI -Includes -MultiViews + +# Set the catch-all handler to prevent scripts from being executed. +SetHandler Drupal_Security_Do_Not_Remove_See_SA_2006_006 + + # Override the handler again if we're run later in the evaluation list. + SetHandler Drupal_Security_Do_Not_Remove_See_SA_2013_003 + + +# If we know how to do it safely, disable the PHP engine entirely. + + php_flag engine off + \ No newline at end of file diff -r e200cb7efeb3 -r c2387f117808 sites/default/files/php/twig/5b44bda38f6c8_search-result.html.twig_9RRL7IDU5vq0GQTMD1MTgd-jl/1HqXXhq4rSyzYX1xHD_z4uUV7XGIwUJqwBtNN6q9Sl4.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/default/files/php/twig/5b44bda38f6c8_search-result.html.twig_9RRL7IDU5vq0GQTMD1MTgd-jl/1HqXXhq4rSyzYX1xHD_z4uUV7XGIwUJqwBtNN6q9Sl4.php Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,117 @@ +parent = false; + + $this->blocks = array( + ); + } + + protected function doDisplay(array $context, array $blocks = array()) + { + $tags = array("if" => 66); + $filters = array(); + $functions = array("attach_library" => 59); + + try { + $this->env->getExtension('Twig_Extension_Sandbox')->checkSecurity( + array('if'), + array(), + array('attach_library') + ); + } catch (Twig_Sandbox_SecurityError $e) { + $e->setSourceContext($this->getSourceContext()); + + if ($e instanceof Twig_Sandbox_SecurityNotAllowedTagError && isset($tags[$e->getTagName()])) { + $e->setTemplateLine($tags[$e->getTagName()]); + } elseif ($e instanceof Twig_Sandbox_SecurityNotAllowedFilterError && isset($filters[$e->getFilterName()])) { + $e->setTemplateLine($filters[$e->getFilterName()]); + } elseif ($e instanceof Twig_Sandbox_SecurityNotAllowedFunctionError && isset($functions[$e->getFunctionName()])) { + $e->setTemplateLine($functions[$e->getFunctionName()]); + } + + throw $e; + } + + // line 59 + echo $this->env->getExtension('Twig_Extension_Sandbox')->ensureToStringAllowed($this->env->getExtension('Drupal\Core\Template\TwigExtension')->escapeFilter($this->env, $this->env->getExtension('Drupal\Core\Template\TwigExtension')->attachLibrary("classy/search-results"), "html", null, true)); + echo " +"; + // line 60 + echo $this->env->getExtension('Twig_Extension_Sandbox')->ensureToStringAllowed($this->env->getExtension('Drupal\Core\Template\TwigExtension')->escapeFilter($this->env, ($context["title_prefix"] ?? null), "html", null, true)); + echo " +env->getExtension('Twig_Extension_Sandbox')->ensureToStringAllowed($this->env->getExtension('Drupal\Core\Template\TwigExtension')->escapeFilter($this->env, $this->getAttribute(($context["title_attributes"] ?? null), "addClass", array(0 => "search-result__title"), "method"), "html", null, true)); + echo "> + env->getExtension('Twig_Extension_Sandbox')->ensureToStringAllowed($this->env->getExtension('Drupal\Core\Template\TwigExtension')->escapeFilter($this->env, ($context["url"] ?? null), "html", null, true)); + echo "\">"; + echo $this->env->getExtension('Twig_Extension_Sandbox')->ensureToStringAllowed($this->env->getExtension('Drupal\Core\Template\TwigExtension')->escapeFilter($this->env, ($context["title"] ?? null), "html", null, true)); + echo " + +"; + // line 64 + echo $this->env->getExtension('Twig_Extension_Sandbox')->ensureToStringAllowed($this->env->getExtension('Drupal\Core\Template\TwigExtension')->escapeFilter($this->env, ($context["title_suffix"] ?? null), "html", null, true)); + echo " +
        + "; + // line 66 + if (($context["snippet"] ?? null)) { + // line 67 + echo " env->getExtension('Twig_Extension_Sandbox')->ensureToStringAllowed($this->env->getExtension('Drupal\Core\Template\TwigExtension')->escapeFilter($this->env, $this->getAttribute(($context["content_attributes"] ?? null), "addClass", array(0 => "search-result__snippet"), "method"), "html", null, true)); + echo ">"; + echo $this->env->getExtension('Twig_Extension_Sandbox')->ensureToStringAllowed($this->env->getExtension('Drupal\Core\Template\TwigExtension')->escapeFilter($this->env, ($context["snippet"] ?? null), "html", null, true)); + echo "

        + "; + } + // line 69 + echo " "; + if (($context["info"] ?? null)) { + // line 70 + echo "

        "; + echo $this->env->getExtension('Twig_Extension_Sandbox')->ensureToStringAllowed($this->env->getExtension('Drupal\Core\Template\TwigExtension')->escapeFilter($this->env, ($context["info"] ?? null), "html", null, true)); + echo "

        + "; + } + // line 72 + echo "
        +"; + } + + public function getTemplateName() + { + return "core/themes/classy/templates/content/search-result.html.twig"; + } + + public function isTraitable() + { + return false; + } + + public function getDebugInfo() + { + return array ( 86 => 72, 80 => 70, 77 => 69, 69 => 67, 67 => 66, 62 => 64, 55 => 62, 51 => 61, 47 => 60, 43 => 59,); + } + + /** @deprecated since 1.27 (to be removed in 2.0). Use getSourceContext() instead */ + public function getSource() + { + @trigger_error('The '.__METHOD__.' method is deprecated since version 1.27 and will be removed in 2.0. Use getSourceContext() instead.', E_USER_DEPRECATED); + + return $this->getSourceContext()->getCode(); + } + + public function getSourceContext() + { + return new Twig_Source("", "core/themes/classy/templates/content/search-result.html.twig", "/var/www/sites/isophonics.net/core/themes/classy/templates/content/search-result.html.twig"); + } +} diff -r e200cb7efeb3 -r c2387f117808 sites/default/files/php/twig/5b44bda38f6c8_username.html.twig_tlStYGbLybmZLcjk08jW1Et4T/.htaccess --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/default/files/php/twig/5b44bda38f6c8_username.html.twig_tlStYGbLybmZLcjk08jW1Et4T/.htaccess Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,23 @@ +# Deny all requests from Apache 2.4+. + + Require all denied + + +# Deny all requests from Apache 2.0-2.2. + + Deny from all + +# Turn off all options we don't need. +Options -Indexes -ExecCGI -Includes -MultiViews + +# Set the catch-all handler to prevent scripts from being executed. +SetHandler Drupal_Security_Do_Not_Remove_See_SA_2006_006 + + # Override the handler again if we're run later in the evaluation list. + SetHandler Drupal_Security_Do_Not_Remove_See_SA_2013_003 + + +# If we know how to do it safely, disable the PHP engine entirely. + + php_flag engine off + \ No newline at end of file diff -r e200cb7efeb3 -r c2387f117808 sites/default/files/php/twig/5b44bda38f6c8_username.html.twig_tlStYGbLybmZLcjk08jW1Et4T/zirdAv11L70sDezz5-sRU51ooKc94svKmBORTx1Ujmg.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/default/files/php/twig/5b44bda38f6c8_username.html.twig_tlStYGbLybmZLcjk08jW1Et4T/zirdAv11L70sDezz5-sRU51ooKc94svKmBORTx1Ujmg.php Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,89 @@ +parent = false; + + $this->blocks = array( + ); + } + + protected function doDisplay(array $context, array $blocks = array()) + { + $tags = array("if" => 25); + $filters = array(); + $functions = array(); + + try { + $this->env->getExtension('Twig_Extension_Sandbox')->checkSecurity( + array('if'), + array(), + array() + ); + } catch (Twig_Sandbox_SecurityError $e) { + $e->setSourceContext($this->getSourceContext()); + + if ($e instanceof Twig_Sandbox_SecurityNotAllowedTagError && isset($tags[$e->getTagName()])) { + $e->setTemplateLine($tags[$e->getTagName()]); + } elseif ($e instanceof Twig_Sandbox_SecurityNotAllowedFilterError && isset($filters[$e->getFilterName()])) { + $e->setTemplateLine($filters[$e->getFilterName()]); + } elseif ($e instanceof Twig_Sandbox_SecurityNotAllowedFunctionError && isset($functions[$e->getFunctionName()])) { + $e->setTemplateLine($functions[$e->getFunctionName()]); + } + + throw $e; + } + + // line 25 + if (($context["link_path"] ?? null)) { + // line 26 + echo "env->getExtension('Twig_Extension_Sandbox')->ensureToStringAllowed($this->env->getExtension('Drupal\Core\Template\TwigExtension')->escapeFilter($this->env, $this->getAttribute(($context["attributes"] ?? null), "addClass", array(0 => "username"), "method"), "html", null, true)); + echo ">"; + echo $this->env->getExtension('Twig_Extension_Sandbox')->ensureToStringAllowed($this->env->getExtension('Drupal\Core\Template\TwigExtension')->escapeFilter($this->env, ($context["name"] ?? null), "html", null, true)); + echo $this->env->getExtension('Twig_Extension_Sandbox')->ensureToStringAllowed($this->env->getExtension('Drupal\Core\Template\TwigExtension')->escapeFilter($this->env, ($context["extra"] ?? null), "html", null, true)); + echo ""; + } else { + // line 28 + echo "env->getExtension('Twig_Extension_Sandbox')->ensureToStringAllowed($this->env->getExtension('Drupal\Core\Template\TwigExtension')->escapeFilter($this->env, ($context["attributes"] ?? null), "html", null, true)); + echo ">"; + echo $this->env->getExtension('Twig_Extension_Sandbox')->ensureToStringAllowed($this->env->getExtension('Drupal\Core\Template\TwigExtension')->escapeFilter($this->env, ($context["name"] ?? null), "html", null, true)); + echo $this->env->getExtension('Twig_Extension_Sandbox')->ensureToStringAllowed($this->env->getExtension('Drupal\Core\Template\TwigExtension')->escapeFilter($this->env, ($context["extra"] ?? null), "html", null, true)); + echo ""; + } + } + + public function getTemplateName() + { + return "core/themes/classy/templates/user/username.html.twig"; + } + + public function isTraitable() + { + return false; + } + + public function getDebugInfo() + { + return array ( 53 => 28, 45 => 26, 43 => 25,); + } + + /** @deprecated since 1.27 (to be removed in 2.0). Use getSourceContext() instead */ + public function getSource() + { + @trigger_error('The '.__METHOD__.' method is deprecated since version 1.27 and will be removed in 2.0. Use getSourceContext() instead.', E_USER_DEPRECATED); + + return $this->getSourceContext()->getCode(); + } + + public function getSourceContext() + { + return new Twig_Source("", "core/themes/classy/templates/user/username.html.twig", "/var/www/sites/isophonics.net/core/themes/classy/templates/user/username.html.twig"); + } +} diff -r e200cb7efeb3 -r c2387f117808 vendor/behat/mink-browserkit-driver/.travis.yml --- a/vendor/behat/mink-browserkit-driver/.travis.yml Thu Apr 26 11:26:54 2018 +0100 +++ b/vendor/behat/mink-browserkit-driver/.travis.yml Tue Jul 10 15:07:59 2018 +0100 @@ -2,33 +2,36 @@ sudo: false -php: [5.3, 5.4, 5.5, 5.6, 7.0, hhvm] +php: [5.4, 5.5, 5.6, 7.0, 7.1, hhvm] matrix: include: + - php: 5.3 + dist: precise # Test against LTS versions - - php: 5.5 - env: SYMFONY_VERSION='2.3.*' - - php: 5.5 - env: SYMFONY_VERSION='2.7.*' - - php: 5.6 - env: SYMFONY_VERSION='2.8.*' + - php: 7.1 + env: SYMFONY_VERSION='^2' + - php: 7.1 + env: SYMFONY_VERSION='^3' # Test against dev versions of dependencies - - php: 5.6 + - php: 7.1 env: DEPENDENCIES='dev' cache: directories: - $HOME/.composer/cache/files + - $HOME/symfony-bridge/.phpunit before_install: - - if [ "$DEPENDENCIES" = "dev" ]; then perl -pi -e 's/^}$/,"minimum-stability":"dev"}/' composer.json; fi; - - sh -c 'if [ "$SYMFONY_VERSION" != "" ]; then composer require -n --no-update symfony/symfony=$SYMFONY_VERSION; fi;' + - if [ "$DEPENDENCIES" = "dev" ]; then composer config minimum-stability dev; fi; + - sh -c 'if [ "$SYMFONY_VERSION" != "" ]; then composer require -n --no-update symfony/lts=$SYMFONY_VERSION; fi;' install: - composer install -n + - vendor/bin/simple-phpunit install -script: phpunit -v --coverage-clover=coverage.clover +script: vendor/bin/simple-phpunit -v --coverage-clover=coverage.clover after_script: - - wget https://scrutinizer-ci.com/ocular.phar && php ocular.phar code-coverage:upload --format=php-clover coverage.clover + - wget https://scrutinizer-ci.com/ocular.phar + - php ocular.phar code-coverage:upload --format=php-clover coverage.clover diff -r e200cb7efeb3 -r c2387f117808 vendor/behat/mink-browserkit-driver/CHANGELOG.md --- a/vendor/behat/mink-browserkit-driver/CHANGELOG.md Thu Apr 26 11:26:54 2018 +0100 +++ b/vendor/behat/mink-browserkit-driver/CHANGELOG.md Tue Jul 10 15:07:59 2018 +0100 @@ -1,3 +1,8 @@ +1.3.3 / 2018-05-02 +================== + +* Added Symfony 4.0 compatibility. + 1.3.2 / 2016-03-05 ================== diff -r e200cb7efeb3 -r c2387f117808 vendor/behat/mink-browserkit-driver/README.md --- a/vendor/behat/mink-browserkit-driver/README.md Thu Apr 26 11:26:54 2018 +0100 +++ b/vendor/behat/mink-browserkit-driver/README.md Tue Jul 10 15:07:59 2018 +0100 @@ -33,18 +33,10 @@ Installation ------------ -``` json -{ - "require": { - "behat/mink": "~1.5", - "behat/mink-browserkit-driver": "~1.1" - } -} -``` +To install use the `composer require` command: -``` bash -$> curl -sS https://getcomposer.org/installer | php -$> php composer.phar install +```bash +composer require --dev behat/mink behat/mink-browserkit-driver ``` Maintainers diff -r e200cb7efeb3 -r c2387f117808 vendor/behat/mink-browserkit-driver/composer.json --- a/vendor/behat/mink-browserkit-driver/composer.json Thu Apr 26 11:26:54 2018 +0100 +++ b/vendor/behat/mink-browserkit-driver/composer.json Tue Jul 10 15:07:59 2018 +0100 @@ -17,13 +17,13 @@ "require": { "php": ">=5.3.6", "behat/mink": "^1.7.1@dev", - "symfony/browser-kit": "~2.3|~3.0", - "symfony/dom-crawler": "~2.3|~3.0" + "symfony/browser-kit": "~2.3|~3.0|~4.0", + "symfony/dom-crawler": "~2.3|~3.0|~4.0" }, "require-dev": { - "symfony/phpunit-bridge": "~2.7|~3.0", - "silex/silex": "~1.2" + "mink/driver-testsuite": "dev-master", + "symfony/http-kernel": "~2.3|~3.0|~4.0" }, "autoload": { diff -r e200cb7efeb3 -r c2387f117808 vendor/behat/mink-browserkit-driver/phpunit.xml.dist --- a/vendor/behat/mink-browserkit-driver/phpunit.xml.dist Thu Apr 26 11:26:54 2018 +0100 +++ b/vendor/behat/mink-browserkit-driver/phpunit.xml.dist Tue Jul 10 15:07:59 2018 +0100 @@ -1,6 +1,6 @@ - + @@ -8,8 +8,8 @@ tests - vendor/behat/mink/driver-testsuite/tests/Basic - vendor/behat/mink/driver-testsuite/tests/Form + vendor/mink/driver-testsuite/tests/Basic + vendor/mink/driver-testsuite/tests/Form diff -r e200cb7efeb3 -r c2387f117808 vendor/behat/mink-browserkit-driver/src/BrowserKitDriver.php --- a/vendor/behat/mink-browserkit-driver/src/BrowserKitDriver.php Thu Apr 26 11:26:54 2018 +0100 +++ b/vendor/behat/mink-browserkit-driver/src/BrowserKitDriver.php Tue Jul 10 15:07:59 2018 +0100 @@ -77,7 +77,7 @@ */ public function setRemoveHostFromUrl($remove = true) { - trigger_error( + @trigger_error( 'setRemoveHostFromUrl() is deprecated as of 1.2 and will be removed in 2.0. Pass the base url in the constructor instead.', E_USER_DEPRECATED ); @@ -93,7 +93,7 @@ */ public function setRemoveScriptFromUrl($remove = true) { - trigger_error( + @trigger_error( 'setRemoveScriptFromUrl() is deprecated as of 1.2 and will be removed in 2.0. Pass the base url in the constructor instead.', E_USER_DEPRECATED ); diff -r e200cb7efeb3 -r c2387f117808 vendor/behat/mink-selenium2-driver/src/Selenium2Driver.php --- a/vendor/behat/mink-selenium2-driver/src/Selenium2Driver.php Thu Apr 26 11:26:54 2018 +0100 +++ b/vendor/behat/mink-selenium2-driver/src/Selenium2Driver.php Tue Jul 10 15:07:59 2018 +0100 @@ -683,7 +683,20 @@ } $element->postValue(array('value' => array($value))); - $this->trigger($xpath, 'change'); + // Remove the focus from the element if the field still has focus in + // order to trigger the change event. By doing this instead of simply + // triggering the change event for the given xpath we ensure that the + // change event will not be triggered twice for the same element if it + // has lost focus in the meanwhile. If the element has lost focus + // already then there is nothing to do as this will already have caused + // the triggering of the change event for that element. + $script = <<executeJsOnElement($element, $script); } /** diff -r e200cb7efeb3 -r c2387f117808 vendor/behat/mink/composer.json --- a/vendor/behat/mink/composer.json Thu Apr 26 11:26:54 2018 +0100 +++ b/vendor/behat/mink/composer.json Tue Jul 10 15:07:59 2018 +0100 @@ -27,6 +27,7 @@ "behat/mink-browserkit-driver": "extremely fast headless driver for Symfony\\Kernel-based apps (Sf2, Silex)", "behat/mink-goutte-driver": "fast headless driver for any app without JS emulation", "behat/mink-selenium2-driver": "slow, but JS-enabled driver for any app (requires Selenium2)", + "dmore/chrome-mink-driver": "fast and JS-enabled driver for any app (requires chromium or google chrome)", "behat/mink-zombie-driver": "fast and JS-enabled headless driver for any app (requires node.js)" }, diff -r e200cb7efeb3 -r c2387f117808 vendor/composer/ClassLoader.php --- a/vendor/composer/ClassLoader.php Thu Apr 26 11:26:54 2018 +0100 +++ b/vendor/composer/ClassLoader.php Tue Jul 10 15:07:59 2018 +0100 @@ -379,9 +379,9 @@ $subPath = substr($subPath, 0, $lastPos); $search = $subPath.'\\'; if (isset($this->prefixDirsPsr4[$search])) { + $pathEnd = DIRECTORY_SEPARATOR . substr($logicalPathPsr4, $lastPos + 1); foreach ($this->prefixDirsPsr4[$search] as $dir) { - $length = $this->prefixLengthsPsr4[$first][$search]; - if (file_exists($file = $dir . DIRECTORY_SEPARATOR . substr($logicalPathPsr4, $length))) { + if (file_exists($file = $dir . $pathEnd)) { return $file; } } diff -r e200cb7efeb3 -r c2387f117808 vendor/composer/autoload_files.php --- a/vendor/composer/autoload_files.php Thu Apr 26 11:26:54 2018 +0100 +++ b/vendor/composer/autoload_files.php Tue Jul 10 15:07:59 2018 +0100 @@ -7,14 +7,23 @@ return array( '0e6d7bf4a5811bfa5cf40c5ccd6fae6a' => $vendorDir . '/symfony/polyfill-mbstring/bootstrap.php', + '6124b4c8570aa390c21fafd04a26c69f' => $vendorDir . '/myclabs/deep-copy/src/DeepCopy/deep_copy.php', + '320cde22f66dd4f5d3fd621d3e88b98f' => $vendorDir . '/symfony/polyfill-ctype/bootstrap.php', '5255c38a0faeba867671b61dfda6d864' => $vendorDir . '/paragonie/random_compat/lib/random.php', '023d27dca8066ef29e6739335ea73bad' => $vendorDir . '/symfony/polyfill-php70/bootstrap.php', '92c8763cd6170fce6fcfe7e26b4e8c10' => $vendorDir . '/symfony/phpunit-bridge/bootstrap.php', '667aeda72477189d0494fecd327c3641' => $vendorDir . '/symfony/var-dumper/Resources/functions/dump.php', + 'c964ee0ededf28c96ebd9db5099ef910' => $vendorDir . '/guzzlehttp/promises/src/functions_include.php', 'a0edc8309cc5e1d60e3047b5df6b7052' => $vendorDir . '/guzzlehttp/psr7/src/functions_include.php', - 'c964ee0ededf28c96ebd9db5099ef910' => $vendorDir . '/guzzlehttp/promises/src/functions_include.php', '37a3dc5111fe8f707ab4c132ef1dbc62' => $vendorDir . '/guzzlehttp/guzzle/src/functions_include.php', '801c31d8ed748cfa537fa45402288c95' => $vendorDir . '/psy/psysh/src/functions.php', 'def43f6c87e4f8dfd0c9e1b1bab14fe8' => $vendorDir . '/symfony/polyfill-iconv/bootstrap.php', - '6124b4c8570aa390c21fafd04a26c69f' => $vendorDir . '/myclabs/deep-copy/src/DeepCopy/deep_copy.php', + 'cf97c57bfe0f23854afd2f3818abb7a0' => $vendorDir . '/zendframework/zend-diactoros/src/functions/create_uploaded_file.php', + '9bf37a3d0dad93e29cb4e1b1bfab04e9' => $vendorDir . '/zendframework/zend-diactoros/src/functions/marshal_headers_from_sapi.php', + 'ce70dccb4bcc2efc6e94d2ee526e6972' => $vendorDir . '/zendframework/zend-diactoros/src/functions/marshal_method_from_sapi.php', + 'f86420df471f14d568bfcb71e271b523' => $vendorDir . '/zendframework/zend-diactoros/src/functions/marshal_protocol_version_from_sapi.php', + 'b87481e008a3700344428ae089e7f9e5' => $vendorDir . '/zendframework/zend-diactoros/src/functions/marshal_uri_from_sapi.php', + '0b0974a5566a1077e4f2e111341112c1' => $vendorDir . '/zendframework/zend-diactoros/src/functions/normalize_server.php', + '1ca3bc274755662169f9629d5412a1da' => $vendorDir . '/zendframework/zend-diactoros/src/functions/normalize_uploaded_files.php', + '40360c0b9b437e69bcbb7f1349ce029e' => $vendorDir . '/zendframework/zend-diactoros/src/functions/parse_cookie_header.php', ); diff -r e200cb7efeb3 -r c2387f117808 vendor/composer/autoload_psr4.php --- a/vendor/composer/autoload_psr4.php Thu Apr 26 11:26:54 2018 +0100 +++ b/vendor/composer/autoload_psr4.php Tue Jul 10 15:07:59 2018 +0100 @@ -6,7 +6,7 @@ $baseDir = dirname($vendorDir); return array( - 'phpDocumentor\\Reflection\\' => array($vendorDir . '/phpdocumentor/reflection-common/src', $vendorDir . '/phpdocumentor/type-resolver/src', $vendorDir . '/phpdocumentor/reflection-docblock/src'), + 'phpDocumentor\\Reflection\\' => array($vendorDir . '/phpdocumentor/reflection-common/src', $vendorDir . '/phpdocumentor/reflection-docblock/src', $vendorDir . '/phpdocumentor/type-resolver/src'), 'Zumba\\Mink\\Driver\\' => array($vendorDir . '/jcalderonzumba/mink-phantomjs-driver/src'), 'Zumba\\GastonJS\\' => array($vendorDir . '/jcalderonzumba/gastonjs/src'), 'Zend\\Stdlib\\' => array($vendorDir . '/zendframework/zend-stdlib/src'), @@ -21,6 +21,7 @@ 'Symfony\\Polyfill\\Php70\\' => array($vendorDir . '/symfony/polyfill-php70'), 'Symfony\\Polyfill\\Mbstring\\' => array($vendorDir . '/symfony/polyfill-mbstring'), 'Symfony\\Polyfill\\Iconv\\' => array($vendorDir . '/symfony/polyfill-iconv'), + 'Symfony\\Polyfill\\Ctype\\' => array($vendorDir . '/symfony/polyfill-ctype'), 'Symfony\\Component\\Yaml\\' => array($vendorDir . '/symfony/yaml'), 'Symfony\\Component\\VarDumper\\' => array($vendorDir . '/symfony/var-dumper'), 'Symfony\\Component\\Validator\\' => array($vendorDir . '/symfony/validator'), @@ -66,7 +67,7 @@ 'Consolidation\\AnnotatedCommand\\' => array($vendorDir . '/consolidation/annotated-command/src'), 'Composer\\Semver\\' => array($vendorDir . '/composer/semver/src'), 'Composer\\Installers\\' => array($vendorDir . '/composer/installers/src/Composer/Installers'), - 'Behat\\Mink\\Driver\\' => array($vendorDir . '/behat/mink-selenium2-driver/src', $vendorDir . '/behat/mink-browserkit-driver/src', $vendorDir . '/behat/mink-goutte-driver/src'), + 'Behat\\Mink\\Driver\\' => array($vendorDir . '/behat/mink-browserkit-driver/src', $vendorDir . '/behat/mink-goutte-driver/src', $vendorDir . '/behat/mink-selenium2-driver/src'), 'Behat\\Mink\\' => array($vendorDir . '/behat/mink/src'), 'Asm89\\Stack\\' => array($vendorDir . '/asm89/stack-cors/src/Asm89/Stack'), ); diff -r e200cb7efeb3 -r c2387f117808 vendor/composer/autoload_static.php --- a/vendor/composer/autoload_static.php Thu Apr 26 11:26:54 2018 +0100 +++ b/vendor/composer/autoload_static.php Tue Jul 10 15:07:59 2018 +0100 @@ -8,16 +8,25 @@ { public static $files = array ( '0e6d7bf4a5811bfa5cf40c5ccd6fae6a' => __DIR__ . '/..' . '/symfony/polyfill-mbstring/bootstrap.php', + '6124b4c8570aa390c21fafd04a26c69f' => __DIR__ . '/..' . '/myclabs/deep-copy/src/DeepCopy/deep_copy.php', + '320cde22f66dd4f5d3fd621d3e88b98f' => __DIR__ . '/..' . '/symfony/polyfill-ctype/bootstrap.php', '5255c38a0faeba867671b61dfda6d864' => __DIR__ . '/..' . '/paragonie/random_compat/lib/random.php', '023d27dca8066ef29e6739335ea73bad' => __DIR__ . '/..' . '/symfony/polyfill-php70/bootstrap.php', '92c8763cd6170fce6fcfe7e26b4e8c10' => __DIR__ . '/..' . '/symfony/phpunit-bridge/bootstrap.php', '667aeda72477189d0494fecd327c3641' => __DIR__ . '/..' . '/symfony/var-dumper/Resources/functions/dump.php', + 'c964ee0ededf28c96ebd9db5099ef910' => __DIR__ . '/..' . '/guzzlehttp/promises/src/functions_include.php', 'a0edc8309cc5e1d60e3047b5df6b7052' => __DIR__ . '/..' . '/guzzlehttp/psr7/src/functions_include.php', - 'c964ee0ededf28c96ebd9db5099ef910' => __DIR__ . '/..' . '/guzzlehttp/promises/src/functions_include.php', '37a3dc5111fe8f707ab4c132ef1dbc62' => __DIR__ . '/..' . '/guzzlehttp/guzzle/src/functions_include.php', '801c31d8ed748cfa537fa45402288c95' => __DIR__ . '/..' . '/psy/psysh/src/functions.php', 'def43f6c87e4f8dfd0c9e1b1bab14fe8' => __DIR__ . '/..' . '/symfony/polyfill-iconv/bootstrap.php', - '6124b4c8570aa390c21fafd04a26c69f' => __DIR__ . '/..' . '/myclabs/deep-copy/src/DeepCopy/deep_copy.php', + 'cf97c57bfe0f23854afd2f3818abb7a0' => __DIR__ . '/..' . '/zendframework/zend-diactoros/src/functions/create_uploaded_file.php', + '9bf37a3d0dad93e29cb4e1b1bfab04e9' => __DIR__ . '/..' . '/zendframework/zend-diactoros/src/functions/marshal_headers_from_sapi.php', + 'ce70dccb4bcc2efc6e94d2ee526e6972' => __DIR__ . '/..' . '/zendframework/zend-diactoros/src/functions/marshal_method_from_sapi.php', + 'f86420df471f14d568bfcb71e271b523' => __DIR__ . '/..' . '/zendframework/zend-diactoros/src/functions/marshal_protocol_version_from_sapi.php', + 'b87481e008a3700344428ae089e7f9e5' => __DIR__ . '/..' . '/zendframework/zend-diactoros/src/functions/marshal_uri_from_sapi.php', + '0b0974a5566a1077e4f2e111341112c1' => __DIR__ . '/..' . '/zendframework/zend-diactoros/src/functions/normalize_server.php', + '1ca3bc274755662169f9629d5412a1da' => __DIR__ . '/..' . '/zendframework/zend-diactoros/src/functions/normalize_uploaded_files.php', + '40360c0b9b437e69bcbb7f1349ce029e' => __DIR__ . '/..' . '/zendframework/zend-diactoros/src/functions/parse_cookie_header.php', ); public static $prefixLengthsPsr4 = array ( @@ -53,6 +62,7 @@ 'Symfony\\Polyfill\\Php70\\' => 23, 'Symfony\\Polyfill\\Mbstring\\' => 26, 'Symfony\\Polyfill\\Iconv\\' => 23, + 'Symfony\\Polyfill\\Ctype\\' => 23, 'Symfony\\Component\\Yaml\\' => 23, 'Symfony\\Component\\VarDumper\\' => 28, 'Symfony\\Component\\Validator\\' => 28, @@ -129,8 +139,8 @@ 'phpDocumentor\\Reflection\\' => array ( 0 => __DIR__ . '/..' . '/phpdocumentor/reflection-common/src', - 1 => __DIR__ . '/..' . '/phpdocumentor/type-resolver/src', - 2 => __DIR__ . '/..' . '/phpdocumentor/reflection-docblock/src', + 1 => __DIR__ . '/..' . '/phpdocumentor/reflection-docblock/src', + 2 => __DIR__ . '/..' . '/phpdocumentor/type-resolver/src', ), 'Zumba\\Mink\\Driver\\' => array ( @@ -188,6 +198,10 @@ array ( 0 => __DIR__ . '/..' . '/symfony/polyfill-iconv', ), + 'Symfony\\Polyfill\\Ctype\\' => + array ( + 0 => __DIR__ . '/..' . '/symfony/polyfill-ctype', + ), 'Symfony\\Component\\Yaml\\' => array ( 0 => __DIR__ . '/..' . '/symfony/yaml', @@ -373,9 +387,9 @@ ), 'Behat\\Mink\\Driver\\' => array ( - 0 => __DIR__ . '/..' . '/behat/mink-selenium2-driver/src', - 1 => __DIR__ . '/..' . '/behat/mink-browserkit-driver/src', - 2 => __DIR__ . '/..' . '/behat/mink-goutte-driver/src', + 0 => __DIR__ . '/..' . '/behat/mink-browserkit-driver/src', + 1 => __DIR__ . '/..' . '/behat/mink-goutte-driver/src', + 2 => __DIR__ . '/..' . '/behat/mink-selenium2-driver/src', ), 'Behat\\Mink\\' => array ( diff -r e200cb7efeb3 -r c2387f117808 vendor/composer/installed.json --- a/vendor/composer/installed.json Thu Apr 26 11:26:54 2018 +0100 +++ b/vendor/composer/installed.json Tue Jul 10 15:07:59 2018 +0100 @@ -1,5 +1,298 @@ [ { + "name": "asm89/stack-cors", + "version": "1.2.0", + "version_normalized": "1.2.0.0", + "source": { + "type": "git", + "url": "https://github.com/asm89/stack-cors.git", + "reference": "c163e2b614550aedcf71165db2473d936abbced6" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/asm89/stack-cors/zipball/c163e2b614550aedcf71165db2473d936abbced6", + "reference": "c163e2b614550aedcf71165db2473d936abbced6", + "shasum": "" + }, + "require": { + "php": ">=5.5.9", + "symfony/http-foundation": "~2.7|~3.0|~4.0", + "symfony/http-kernel": "~2.7|~3.0|~4.0" + }, + "require-dev": { + "phpunit/phpunit": "^5.0 || ^4.8.10", + "squizlabs/php_codesniffer": "^2.3" + }, + "time": "2017-12-20T14:37:45+00:00", + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.2-dev" + } + }, + "installation-source": "dist", + "autoload": { + "psr-4": { + "Asm89\\Stack\\": "src/Asm89/Stack/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Alexander", + "email": "iam.asm89@gmail.com" + } + ], + "description": "Cross-origin resource sharing library and stack middleware", + "homepage": "https://github.com/asm89/stack-cors", + "keywords": [ + "cors", + "stack" + ] + }, + { + "name": "behat/mink", + "version": "dev-master", + "version_normalized": "9999999-dev", + "source": { + "type": "git", + "url": "https://github.com/minkphp/Mink.git", + "reference": "d5ee350c40baff5f331a05ebdbe1927345c9ac8b" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/minkphp/Mink/zipball/d5ee350c40baff5f331a05ebdbe1927345c9ac8b", + "reference": "d5ee350c40baff5f331a05ebdbe1927345c9ac8b", + "shasum": "" + }, + "require": { + "php": ">=5.3.1", + "symfony/css-selector": "^2.7|^3.0|^4.0" + }, + "require-dev": { + "symfony/phpunit-bridge": "^3.3|^4.0" + }, + "suggest": { + "behat/mink-browserkit-driver": "extremely fast headless driver for Symfony\\Kernel-based apps (Sf2, Silex)", + "behat/mink-goutte-driver": "fast headless driver for any app without JS emulation", + "behat/mink-selenium2-driver": "slow, but JS-enabled driver for any app (requires Selenium2)", + "behat/mink-zombie-driver": "fast and JS-enabled headless driver for any app (requires node.js)", + "dmore/chrome-mink-driver": "fast and JS-enabled driver for any app (requires chromium or google chrome)" + }, + "time": "2018-06-24T20:08:51+00:00", + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.7.x-dev" + } + }, + "installation-source": "dist", + "autoload": { + "psr-4": { + "Behat\\Mink\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Konstantin Kudryashov", + "email": "ever.zet@gmail.com", + "homepage": "http://everzet.com" + } + ], + "description": "Browser controller/emulator abstraction for PHP", + "homepage": "http://mink.behat.org/", + "keywords": [ + "browser", + "testing", + "web" + ] + }, + { + "name": "behat/mink-browserkit-driver", + "version": "1.3.3", + "version_normalized": "1.3.3.0", + "source": { + "type": "git", + "url": "https://github.com/minkphp/MinkBrowserKitDriver.git", + "reference": "1b9a7ce903cfdaaec5fb32bfdbb26118343662eb" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/minkphp/MinkBrowserKitDriver/zipball/1b9a7ce903cfdaaec5fb32bfdbb26118343662eb", + "reference": "1b9a7ce903cfdaaec5fb32bfdbb26118343662eb", + "shasum": "" + }, + "require": { + "behat/mink": "^1.7.1@dev", + "php": ">=5.3.6", + "symfony/browser-kit": "~2.3|~3.0|~4.0", + "symfony/dom-crawler": "~2.3|~3.0|~4.0" + }, + "require-dev": { + "mink/driver-testsuite": "dev-master", + "symfony/http-kernel": "~2.3|~3.0|~4.0" + }, + "time": "2018-05-02T09:25:31+00:00", + "type": "mink-driver", + "extra": { + "branch-alias": { + "dev-master": "1.3.x-dev" + } + }, + "installation-source": "dist", + "autoload": { + "psr-4": { + "Behat\\Mink\\Driver\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Konstantin Kudryashov", + "email": "ever.zet@gmail.com", + "homepage": "http://everzet.com" + } + ], + "description": "Symfony2 BrowserKit driver for Mink framework", + "homepage": "http://mink.behat.org/", + "keywords": [ + "Mink", + "Symfony2", + "browser", + "testing" + ] + }, + { + "name": "behat/mink-goutte-driver", + "version": "v1.2.1", + "version_normalized": "1.2.1.0", + "source": { + "type": "git", + "url": "https://github.com/minkphp/MinkGoutteDriver.git", + "reference": "8b9ad6d2d95bc70b840d15323365f52fcdaea6ca" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/minkphp/MinkGoutteDriver/zipball/8b9ad6d2d95bc70b840d15323365f52fcdaea6ca", + "reference": "8b9ad6d2d95bc70b840d15323365f52fcdaea6ca", + "shasum": "" + }, + "require": { + "behat/mink": "~1.6@dev", + "behat/mink-browserkit-driver": "~1.2@dev", + "fabpot/goutte": "~1.0.4|~2.0|~3.1", + "php": ">=5.3.1" + }, + "require-dev": { + "symfony/phpunit-bridge": "~2.7|~3.0" + }, + "time": "2016-03-05T09:04:22+00:00", + "type": "mink-driver", + "extra": { + "branch-alias": { + "dev-master": "1.2.x-dev" + } + }, + "installation-source": "dist", + "autoload": { + "psr-4": { + "Behat\\Mink\\Driver\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Konstantin Kudryashov", + "email": "ever.zet@gmail.com", + "homepage": "http://everzet.com" + } + ], + "description": "Goutte driver for Mink framework", + "homepage": "http://mink.behat.org/", + "keywords": [ + "browser", + "goutte", + "headless", + "testing" + ] + }, + { + "name": "behat/mink-selenium2-driver", + "version": "dev-master", + "version_normalized": "9999999-dev", + "source": { + "type": "git", + "url": "https://github.com/minkphp/MinkSelenium2Driver.git", + "reference": "d8adafd0ba04fcd5a3865400e2bd0500c683f981" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/minkphp/MinkSelenium2Driver/zipball/d8adafd0ba04fcd5a3865400e2bd0500c683f981", + "reference": "d8adafd0ba04fcd5a3865400e2bd0500c683f981", + "shasum": "" + }, + "require": { + "behat/mink": "~1.7@dev", + "instaclick/php-webdriver": "~1.1", + "php": ">=5.3.1" + }, + "require-dev": { + "mink/driver-testsuite": "dev-master" + }, + "time": "2018-06-25T17:38:20+00:00", + "type": "mink-driver", + "extra": { + "branch-alias": { + "dev-master": "1.3.x-dev" + } + }, + "installation-source": "dist", + "autoload": { + "psr-4": { + "Behat\\Mink\\Driver\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Konstantin Kudryashov", + "email": "ever.zet@gmail.com", + "homepage": "http://everzet.com" + }, + { + "name": "Pete Otaqui", + "email": "pete@otaqui.com", + "homepage": "https://github.com/pete-otaqui" + } + ], + "description": "Selenium2 (WebDriver) driver for Mink framework", + "homepage": "http://mink.behat.org/", + "keywords": [ + "ajax", + "browser", + "javascript", + "selenium", + "testing", + "webdriver" + ] + }, + { "name": "composer/installers", "version": "v1.5.0", "version_normalized": "1.5.0.0", @@ -122,42 +415,38 @@ ] }, { - "name": "wikimedia/composer-merge-plugin", - "version": "v1.4.1", - "version_normalized": "1.4.1.0", + "name": "composer/semver", + "version": "1.4.2", + "version_normalized": "1.4.2.0", "source": { "type": "git", - "url": "https://github.com/wikimedia/composer-merge-plugin.git", - "reference": "81c6ac72a24a67383419c7eb9aa2b3437f2ab100" + "url": "https://github.com/composer/semver.git", + "reference": "c7cb9a2095a074d131b65a8a0cd294479d785573" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/wikimedia/composer-merge-plugin/zipball/81c6ac72a24a67383419c7eb9aa2b3437f2ab100", - "reference": "81c6ac72a24a67383419c7eb9aa2b3437f2ab100", + "url": "https://api.github.com/repos/composer/semver/zipball/c7cb9a2095a074d131b65a8a0cd294479d785573", + "reference": "c7cb9a2095a074d131b65a8a0cd294479d785573", "shasum": "" }, "require": { - "composer-plugin-api": "^1.0", - "php": ">=5.3.2" + "php": "^5.3.2 || ^7.0" }, "require-dev": { - "composer/composer": "~1.0.0", - "jakub-onderka/php-parallel-lint": "~0.8", - "phpunit/phpunit": "~4.8|~5.0", - "squizlabs/php_codesniffer": "~2.1.0" - }, - "time": "2017-04-25T02:31:25+00:00", - "type": "composer-plugin", + "phpunit/phpunit": "^4.5 || ^5.0.5", + "phpunit/phpunit-mock-objects": "2.3.0 || ^3.0" + }, + "time": "2016-08-30T16:08:34+00:00", + "type": "library", "extra": { "branch-alias": { - "dev-master": "1.3.x-dev" - }, - "class": "Wikimedia\\Composer\\MergePlugin" + "dev-master": "1.x-dev" + } }, "installation-source": "dist", "autoload": { "psr-4": { - "Wikimedia\\Composer\\": "src/" + "Composer\\Semver\\": "src" } }, "notification-url": "https://packagist.org/downloads/", @@ -166,45 +455,69 @@ ], "authors": [ { - "name": "Bryan Davis", - "email": "bd808@wikimedia.org" - } - ], - "description": "Composer plugin to merge multiple composer.json files" + "name": "Nils Adermann", + "email": "naderman@naderman.de", + "homepage": "http://www.naderman.de" + }, + { + "name": "Jordi Boggiano", + "email": "j.boggiano@seld.be", + "homepage": "http://seld.be" + }, + { + "name": "Rob Bast", + "email": "rob.bast@gmail.com", + "homepage": "http://robbast.nl" + } + ], + "description": "Semver library that offers utilities, version constraint parsing and validation.", + "keywords": [ + "semantic", + "semver", + "validation", + "versioning" + ] }, { - "name": "webmozart/assert", - "version": "1.3.0", - "version_normalized": "1.3.0.0", + "name": "consolidation/annotated-command", + "version": "2.8.4", + "version_normalized": "2.8.4.0", "source": { "type": "git", - "url": "https://github.com/webmozart/assert.git", - "reference": "0df1908962e7a3071564e857d86874dad1ef204a" + "url": "https://github.com/consolidation/annotated-command.git", + "reference": "651541a0b68318a2a202bda558a676e5ad92223c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/webmozart/assert/zipball/0df1908962e7a3071564e857d86874dad1ef204a", - "reference": "0df1908962e7a3071564e857d86874dad1ef204a", + "url": "https://api.github.com/repos/consolidation/annotated-command/zipball/651541a0b68318a2a202bda558a676e5ad92223c", + "reference": "651541a0b68318a2a202bda558a676e5ad92223c", "shasum": "" }, "require": { - "php": "^5.3.3 || ^7.0" + "consolidation/output-formatters": "^3.1.12", + "php": ">=5.4.0", + "psr/log": "^1", + "symfony/console": "^2.8|^3|^4", + "symfony/event-dispatcher": "^2.5|^3|^4", + "symfony/finder": "^2.5|^3|^4" }, "require-dev": { - "phpunit/phpunit": "^4.6", - "sebastian/version": "^1.0.1" - }, - "time": "2018-01-29T19:49:41+00:00", + "g1a/composer-test-scenarios": "^2", + "phpunit/phpunit": "^6", + "satooshi/php-coveralls": "^2", + "squizlabs/php_codesniffer": "^2.7" + }, + "time": "2018-05-25T18:04:25+00:00", "type": "library", "extra": { "branch-alias": { - "dev-master": "1.3-dev" + "dev-master": "2.x-dev" } }, "installation-source": "dist", "autoload": { "psr-4": { - "Webmozart\\Assert\\": "src/" + "Consolidation\\AnnotatedCommand\\": "src" } }, "notification-url": "https://packagist.org/downloads/", @@ -213,51 +526,55 @@ ], "authors": [ { - "name": "Bernhard Schussek", - "email": "bschussek@gmail.com" - } - ], - "description": "Assertions to validate method input/output with nice error messages.", - "keywords": [ - "assert", - "check", - "validate" - ] + "name": "Greg Anderson", + "email": "greg.1.anderson@greenknowe.org" + } + ], + "description": "Initialize Symfony Console commands from annotated command class methods." }, { - "name": "webmozart/path-util", - "version": "2.3.0", - "version_normalized": "2.3.0.0", + "name": "consolidation/output-formatters", + "version": "3.2.1", + "version_normalized": "3.2.1.0", "source": { "type": "git", - "url": "https://github.com/webmozart/path-util.git", - "reference": "d939f7edc24c9a1bb9c0dee5cb05d8e859490725" + "url": "https://github.com/consolidation/output-formatters.git", + "reference": "d78ef59aea19d3e2e5a23f90a055155ee78a0ad5" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/webmozart/path-util/zipball/d939f7edc24c9a1bb9c0dee5cb05d8e859490725", - "reference": "d939f7edc24c9a1bb9c0dee5cb05d8e859490725", + "url": "https://api.github.com/repos/consolidation/output-formatters/zipball/d78ef59aea19d3e2e5a23f90a055155ee78a0ad5", + "reference": "d78ef59aea19d3e2e5a23f90a055155ee78a0ad5", "shasum": "" }, "require": { - "php": ">=5.3.3", - "webmozart/assert": "~1.0" + "php": ">=5.4.0", + "symfony/console": "^2.8|^3|^4", + "symfony/finder": "^2.5|^3|^4" }, "require-dev": { - "phpunit/phpunit": "^4.6", - "sebastian/version": "^1.0.1" - }, - "time": "2015-12-17T08:42:14+00:00", + "g1a/composer-test-scenarios": "^2", + "phpunit/phpunit": "^5.7.27", + "satooshi/php-coveralls": "^2", + "squizlabs/php_codesniffer": "^2.7", + "symfony/console": "3.2.3", + "symfony/var-dumper": "^2.8|^3|^4", + "victorjonsson/markdowndocs": "^1.3" + }, + "suggest": { + "symfony/var-dumper": "For using the var_dump formatter" + }, + "time": "2018-05-25T18:02:34+00:00", "type": "library", "extra": { "branch-alias": { - "dev-master": "2.3-dev" + "dev-master": "3.x-dev" } }, "installation-source": "dist", "autoload": { "psr-4": { - "Webmozart\\PathUtil\\": "src/" + "Consolidation\\OutputFormatters\\": "src" } }, "notification-url": "https://packagist.org/downloads/", @@ -266,588 +583,11 @@ ], "authors": [ { - "name": "Bernhard Schussek", - "email": "bschussek@gmail.com" - } - ], - "description": "A robust cross-platform utility for normalizing, comparing and modifying file paths." - }, - { - "name": "symfony/yaml", - "version": "v3.4.8", - "version_normalized": "3.4.8.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/yaml.git", - "reference": "a42f9da85c7c38d59f5e53f076fe81a091f894d0" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/yaml/zipball/a42f9da85c7c38d59f5e53f076fe81a091f894d0", - "reference": "a42f9da85c7c38d59f5e53f076fe81a091f894d0", - "shasum": "" - }, - "require": { - "php": "^5.5.9|>=7.0.8" - }, - "conflict": { - "symfony/console": "<3.4" - }, - "require-dev": { - "symfony/console": "~3.4|~4.0" - }, - "suggest": { - "symfony/console": "For validating YAML files using the lint command" - }, - "time": "2018-04-03T05:14:20+00:00", - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "3.4-dev" - } - }, - "installation-source": "dist", - "autoload": { - "psr-4": { - "Symfony\\Component\\Yaml\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Symfony Yaml Component", - "homepage": "https://symfony.com" - }, - { - "name": "symfony/polyfill-mbstring", - "version": "v1.7.0", - "version_normalized": "1.7.0.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/polyfill-mbstring.git", - "reference": "78be803ce01e55d3491c1397cf1c64beb9c1b63b" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/78be803ce01e55d3491c1397cf1c64beb9c1b63b", - "reference": "78be803ce01e55d3491c1397cf1c64beb9c1b63b", - "shasum": "" - }, - "require": { - "php": ">=5.3.3" - }, - "suggest": { - "ext-mbstring": "For best performance" - }, - "time": "2018-01-30T19:27:44+00:00", - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.7-dev" - } - }, - "installation-source": "dist", - "autoload": { - "psr-4": { - "Symfony\\Polyfill\\Mbstring\\": "" - }, - "files": [ - "bootstrap.php" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Symfony polyfill for the Mbstring extension", - "homepage": "https://symfony.com", - "keywords": [ - "compatibility", - "mbstring", - "polyfill", - "portable", - "shim" - ] - }, - { - "name": "symfony/var-dumper", - "version": "v3.4.8", - "version_normalized": "3.4.8.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/var-dumper.git", - "reference": "951643091b39a6fd40fce56cd16e21e12bef3feb" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/var-dumper/zipball/951643091b39a6fd40fce56cd16e21e12bef3feb", - "reference": "951643091b39a6fd40fce56cd16e21e12bef3feb", - "shasum": "" - }, - "require": { - "php": "^5.5.9|>=7.0.8", - "symfony/polyfill-mbstring": "~1.0" - }, - "conflict": { - "phpunit/phpunit": "<4.8.35|<5.4.3,>=5.0" - }, - "require-dev": { - "ext-iconv": "*", - "twig/twig": "~1.34|~2.4" - }, - "suggest": { - "ext-iconv": "To convert non-UTF-8 strings to UTF-8 (or symfony/polyfill-iconv in case ext-iconv cannot be used).", - "ext-intl": "To show region name in time zone dump", - "ext-symfony_debug": "" - }, - "time": "2018-04-03T20:34:11+00:00", - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "3.4-dev" - } - }, - "installation-source": "dist", - "autoload": { - "files": [ - "Resources/functions/dump.php" - ], - "psr-4": { - "Symfony\\Component\\VarDumper\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Symfony mechanism for exploring and dumping PHP variables", - "homepage": "https://symfony.com", - "keywords": [ - "debug", - "dump" - ] - }, - { - "name": "symfony/finder", - "version": "v3.4.8", - "version_normalized": "3.4.8.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/finder.git", - "reference": "bd14efe8b1fabc4de82bf50dce62f05f9a102433" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/finder/zipball/bd14efe8b1fabc4de82bf50dce62f05f9a102433", - "reference": "bd14efe8b1fabc4de82bf50dce62f05f9a102433", - "shasum": "" - }, - "require": { - "php": "^5.5.9|>=7.0.8" - }, - "time": "2018-04-04T05:07:11+00:00", - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "3.4-dev" - } - }, - "installation-source": "dist", - "autoload": { - "psr-4": { - "Symfony\\Component\\Finder\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Symfony Finder Component", - "homepage": "https://symfony.com" - }, - { - "name": "symfony/event-dispatcher", - "version": "v3.4.8", - "version_normalized": "3.4.8.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/event-dispatcher.git", - "reference": "fdd5abcebd1061ec647089c6c41a07ed60af09f8" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/fdd5abcebd1061ec647089c6c41a07ed60af09f8", - "reference": "fdd5abcebd1061ec647089c6c41a07ed60af09f8", - "shasum": "" - }, - "require": { - "php": "^5.5.9|>=7.0.8" - }, - "conflict": { - "symfony/dependency-injection": "<3.3" - }, - "require-dev": { - "psr/log": "~1.0", - "symfony/config": "~2.8|~3.0|~4.0", - "symfony/dependency-injection": "~3.3|~4.0", - "symfony/expression-language": "~2.8|~3.0|~4.0", - "symfony/stopwatch": "~2.8|~3.0|~4.0" - }, - "suggest": { - "symfony/dependency-injection": "", - "symfony/http-kernel": "" - }, - "time": "2018-04-06T07:35:25+00:00", - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "3.4-dev" - } - }, - "installation-source": "dist", - "autoload": { - "psr-4": { - "Symfony\\Component\\EventDispatcher\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Symfony EventDispatcher Component", - "homepage": "https://symfony.com" - }, - { - "name": "psr/log", - "version": "1.0.2", - "version_normalized": "1.0.2.0", - "source": { - "type": "git", - "url": "https://github.com/php-fig/log.git", - "reference": "4ebe3a8bf773a19edfe0a84b6585ba3d401b724d" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/php-fig/log/zipball/4ebe3a8bf773a19edfe0a84b6585ba3d401b724d", - "reference": "4ebe3a8bf773a19edfe0a84b6585ba3d401b724d", - "shasum": "" - }, - "require": { - "php": ">=5.3.0" - }, - "time": "2016-10-10T12:19:37+00:00", - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.0.x-dev" - } - }, - "installation-source": "dist", - "autoload": { - "psr-4": { - "Psr\\Log\\": "Psr/Log/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "PHP-FIG", - "homepage": "http://www.php-fig.org/" - } - ], - "description": "Common interface for logging libraries", - "homepage": "https://github.com/php-fig/log", - "keywords": [ - "log", - "psr", - "psr-3" - ] - }, - { - "name": "symfony/debug", - "version": "v3.4.8", - "version_normalized": "3.4.8.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/debug.git", - "reference": "9cf7c2271cfb89ef9727db1b740ca77be57bf9d7" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/debug/zipball/9cf7c2271cfb89ef9727db1b740ca77be57bf9d7", - "reference": "9cf7c2271cfb89ef9727db1b740ca77be57bf9d7", - "shasum": "" - }, - "require": { - "php": "^5.5.9|>=7.0.8", - "psr/log": "~1.0" - }, - "conflict": { - "symfony/http-kernel": ">=2.3,<2.3.24|~2.4.0|>=2.5,<2.5.9|>=2.6,<2.6.2" - }, - "require-dev": { - "symfony/http-kernel": "~2.8|~3.0|~4.0" - }, - "time": "2018-04-03T05:22:50+00:00", - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "3.4-dev" - } - }, - "installation-source": "dist", - "autoload": { - "psr-4": { - "Symfony\\Component\\Debug\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Symfony Debug Component", - "homepage": "https://symfony.com" - }, - { - "name": "symfony/console", - "version": "v3.4.8", - "version_normalized": "3.4.8.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/console.git", - "reference": "d4bb70fa24d540c309d88a9d6e43fb2d339b1fbf" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/console/zipball/d4bb70fa24d540c309d88a9d6e43fb2d339b1fbf", - "reference": "d4bb70fa24d540c309d88a9d6e43fb2d339b1fbf", - "shasum": "" - }, - "require": { - "php": "^5.5.9|>=7.0.8", - "symfony/debug": "~2.8|~3.0|~4.0", - "symfony/polyfill-mbstring": "~1.0" - }, - "conflict": { - "symfony/dependency-injection": "<3.4", - "symfony/process": "<3.3" - }, - "require-dev": { - "psr/log": "~1.0", - "symfony/config": "~3.3|~4.0", - "symfony/dependency-injection": "~3.4|~4.0", - "symfony/event-dispatcher": "~2.8|~3.0|~4.0", - "symfony/lock": "~3.4|~4.0", - "symfony/process": "~3.3|~4.0" - }, - "suggest": { - "psr/log": "For using the console logger", - "symfony/event-dispatcher": "", - "symfony/lock": "", - "symfony/process": "" - }, - "time": "2018-04-03T05:22:50+00:00", - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "3.4-dev" - } - }, - "installation-source": "dist", - "autoload": { - "psr-4": { - "Symfony\\Component\\Console\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Symfony Console Component", - "homepage": "https://symfony.com" - }, - { - "name": "jakub-onderka/php-console-color", - "version": "0.1", - "version_normalized": "0.1.0.0", - "source": { - "type": "git", - "url": "https://github.com/JakubOnderka/PHP-Console-Color.git", - "reference": "e0b393dacf7703fc36a4efc3df1435485197e6c1" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/JakubOnderka/PHP-Console-Color/zipball/e0b393dacf7703fc36a4efc3df1435485197e6c1", - "reference": "e0b393dacf7703fc36a4efc3df1435485197e6c1", - "shasum": "" - }, - "require": { - "php": ">=5.3.2" - }, - "require-dev": { - "jakub-onderka/php-code-style": "1.0", - "jakub-onderka/php-parallel-lint": "0.*", - "jakub-onderka/php-var-dump-check": "0.*", - "phpunit/phpunit": "3.7.*", - "squizlabs/php_codesniffer": "1.*" - }, - "time": "2014-04-08T15:00:19+00:00", - "type": "library", - "installation-source": "dist", - "autoload": { - "psr-0": { - "JakubOnderka\\PhpConsoleColor": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-2-Clause" - ], - "authors": [ - { - "name": "Jakub Onderka", - "email": "jakub.onderka@gmail.com", - "homepage": "http://www.acci.cz" - } - ] - }, - { - "name": "jakub-onderka/php-console-highlighter", - "version": "v0.3.2", - "version_normalized": "0.3.2.0", - "source": { - "type": "git", - "url": "https://github.com/JakubOnderka/PHP-Console-Highlighter.git", - "reference": "7daa75df45242c8d5b75a22c00a201e7954e4fb5" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/JakubOnderka/PHP-Console-Highlighter/zipball/7daa75df45242c8d5b75a22c00a201e7954e4fb5", - "reference": "7daa75df45242c8d5b75a22c00a201e7954e4fb5", - "shasum": "" - }, - "require": { - "jakub-onderka/php-console-color": "~0.1", - "php": ">=5.3.0" - }, - "require-dev": { - "jakub-onderka/php-code-style": "~1.0", - "jakub-onderka/php-parallel-lint": "~0.5", - "jakub-onderka/php-var-dump-check": "~0.1", - "phpunit/phpunit": "~4.0", - "squizlabs/php_codesniffer": "~1.5" - }, - "time": "2015-04-20T18:58:01+00:00", - "type": "library", - "installation-source": "dist", - "autoload": { - "psr-0": { - "JakubOnderka\\PhpConsoleHighlighter": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Jakub Onderka", - "email": "acci@acci.cz", - "homepage": "http://www.acci.cz/" - } - ] + "name": "Greg Anderson", + "email": "greg.1.anderson@greenknowe.org" + } + ], + "description": "Format text by applying transformations provided by plug-in formatters." }, { "name": "dnoegel/php-xdg-base-dir", @@ -885,110 +625,39 @@ "description": "implementation of xdg base directory specification for php" }, { - "name": "nikic/php-parser", - "version": "v4.0.1", - "version_normalized": "4.0.1.0", + "name": "doctrine/annotations", + "version": "v1.4.0", + "version_normalized": "1.4.0.0", "source": { "type": "git", - "url": "https://github.com/nikic/PHP-Parser.git", - "reference": "e4a54fa90a5cd8e8dd3fb4099942681731c5cdd3" + "url": "https://github.com/doctrine/annotations.git", + "reference": "54cacc9b81758b14e3ce750f205a393d52339e97" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/e4a54fa90a5cd8e8dd3fb4099942681731c5cdd3", - "reference": "e4a54fa90a5cd8e8dd3fb4099942681731c5cdd3", + "url": "https://api.github.com/repos/doctrine/annotations/zipball/54cacc9b81758b14e3ce750f205a393d52339e97", + "reference": "54cacc9b81758b14e3ce750f205a393d52339e97", "shasum": "" }, "require": { - "ext-tokenizer": "*", - "php": ">=7.0" + "doctrine/lexer": "1.*", + "php": "^5.6 || ^7.0" }, "require-dev": { - "phpunit/phpunit": "^6.5 || ^7.0" - }, - "time": "2018-03-25T17:35:16+00:00", - "bin": [ - "bin/php-parse" - ], + "doctrine/cache": "1.*", + "phpunit/phpunit": "^5.7" + }, + "time": "2017-02-24T16:22:25+00:00", "type": "library", "extra": { "branch-alias": { - "dev-master": "4.0-dev" + "dev-master": "1.4.x-dev" } }, "installation-source": "dist", "autoload": { "psr-4": { - "PhpParser\\": "lib/PhpParser" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Nikita Popov" - } - ], - "description": "A PHP parser written in PHP", - "keywords": [ - "parser", - "php" - ] - }, - { - "name": "psy/psysh", - "version": "v0.9.3", - "version_normalized": "0.9.3.0", - "source": { - "type": "git", - "url": "https://github.com/bobthecow/psysh.git", - "reference": "79c280013cf0b30fa23f3ba8bd3649218075adf4" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/bobthecow/psysh/zipball/79c280013cf0b30fa23f3ba8bd3649218075adf4", - "reference": "79c280013cf0b30fa23f3ba8bd3649218075adf4", - "shasum": "" - }, - "require": { - "dnoegel/php-xdg-base-dir": "0.1", - "jakub-onderka/php-console-highlighter": "0.3.*", - "nikic/php-parser": "~1.3|~2.0|~3.0|~4.0", - "php": ">=5.4.0", - "symfony/console": "~2.3.10|^2.4.2|~3.0|~4.0", - "symfony/var-dumper": "~2.7|~3.0|~4.0" - }, - "require-dev": { - "hoa/console": "~2.15|~3.16", - "phpunit/phpunit": "~4.8.35|~5.0|~6.0|~7.0", - "symfony/finder": "~2.1|~3.0|~4.0" - }, - "suggest": { - "ext-pcntl": "Enabling the PCNTL extension makes PsySH a lot happier :)", - "ext-pdo-sqlite": "The doc command requires SQLite to work.", - "ext-posix": "If you have PCNTL, you'll want the POSIX extension as well.", - "ext-readline": "Enables support for arrow-key history navigation, and showing and manipulating command history.", - "hoa/console": "A pure PHP readline implementation. You'll want this if your PHP install doesn't already support readline or libedit." - }, - "time": "2018-04-18T12:32:50+00:00", - "bin": [ - "bin/psysh" - ], - "type": "library", - "extra": { - "branch-alias": { - "dev-develop": "0.9.x-dev" - } - }, - "installation-source": "dist", - "autoload": { - "files": [ - "src/functions.php" - ], - "psr-4": { - "Psy\\": "src/" + "Doctrine\\Common\\Annotations\\": "lib/Doctrine/Common/Annotations" } }, "notification-url": "https://packagist.org/downloads/", @@ -997,1966 +666,71 @@ ], "authors": [ { - "name": "Justin Hileman", - "email": "justin@justinhileman.info", - "homepage": "http://justinhileman.com" - } - ], - "description": "An interactive shell for modern PHP.", - "homepage": "http://psysh.org", - "keywords": [ - "REPL", - "console", - "interactive", - "shell" - ] - }, - { - "name": "pear/console_table", - "version": "v1.3.1", - "version_normalized": "1.3.1.0", - "source": { - "type": "git", - "url": "https://github.com/pear/Console_Table.git", - "reference": "1930c11897ca61fd24b95f2f785e99e0f36dcdea" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/pear/Console_Table/zipball/1930c11897ca61fd24b95f2f785e99e0f36dcdea", - "reference": "1930c11897ca61fd24b95f2f785e99e0f36dcdea", - "shasum": "" - }, - "require": { - "php": ">=5.2.0" - }, - "suggest": { - "pear/Console_Color2": ">=0.1.2" - }, - "time": "2018-01-25T20:47:17+00:00", - "type": "library", - "installation-source": "dist", - "autoload": { - "classmap": [ - "Table.php" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-2-Clause" - ], - "authors": [ - { - "name": "Jan Schneider", - "homepage": "http://pear.php.net/user/yunosh" - }, - { - "name": "Tal Peer", - "homepage": "http://pear.php.net/user/tal" - }, - { - "name": "Xavier Noguer", - "homepage": "http://pear.php.net/user/xnoguer" - }, - { - "name": "Richard Heyes", - "homepage": "http://pear.php.net/user/richard" - } - ], - "description": "Library that makes it easy to build console style tables.", - "homepage": "http://pear.php.net/package/Console_Table/", - "keywords": [ - "console" - ] - }, - { - "name": "consolidation/output-formatters", - "version": "3.2.0", - "version_normalized": "3.2.0.0", - "source": { - "type": "git", - "url": "https://github.com/consolidation/output-formatters.git", - "reference": "da889e4bce19f145ca4ec5b1725a946f4eb625a9" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/consolidation/output-formatters/zipball/da889e4bce19f145ca4ec5b1725a946f4eb625a9", - "reference": "da889e4bce19f145ca4ec5b1725a946f4eb625a9", - "shasum": "" - }, - "require": { - "php": ">=5.4.0", - "symfony/console": "^2.8|^3|^4", - "symfony/finder": "^2.5|^3|^4" - }, - "require-dev": { - "g-1-a/composer-test-scenarios": "^2", - "phpunit/phpunit": "^5.7.27", - "satooshi/php-coveralls": "^2", - "squizlabs/php_codesniffer": "^2.7", - "symfony/console": "3.2.3", - "symfony/var-dumper": "^2.8|^3|^4", - "victorjonsson/markdowndocs": "^1.3" - }, - "suggest": { - "symfony/var-dumper": "For using the var_dump formatter" - }, - "time": "2018-03-20T15:18:32+00:00", - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "3.x-dev" - } - }, - "installation-source": "dist", - "autoload": { - "psr-4": { - "Consolidation\\OutputFormatters\\": "src" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Greg Anderson", - "email": "greg.1.anderson@greenknowe.org" - } - ], - "description": "Format text by applying transformations provided by plug-in formatters." - }, - { - "name": "consolidation/annotated-command", - "version": "2.8.3", - "version_normalized": "2.8.3.0", - "source": { - "type": "git", - "url": "https://github.com/consolidation/annotated-command.git", - "reference": "8f8f5da2ca06fbd3a85f7d551c49f844b7c59437" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/consolidation/annotated-command/zipball/8f8f5da2ca06fbd3a85f7d551c49f844b7c59437", - "reference": "8f8f5da2ca06fbd3a85f7d551c49f844b7c59437", - "shasum": "" - }, - "require": { - "consolidation/output-formatters": "^3.1.12", - "php": ">=5.4.0", - "psr/log": "^1", - "symfony/console": "^2.8|^3|^4", - "symfony/event-dispatcher": "^2.5|^3|^4", - "symfony/finder": "^2.5|^3|^4" - }, - "require-dev": { - "greg-1-anderson/composer-test-scenarios": "^1", - "phpunit/phpunit": "^4.8", - "satooshi/php-coveralls": "^1.0.2 | dev-master", - "squizlabs/php_codesniffer": "^2.7" - }, - "time": "2018-02-23T16:32:04+00:00", - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.x-dev" - } - }, - "installation-source": "dist", - "autoload": { - "psr-4": { - "Consolidation\\AnnotatedCommand\\": "src" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Greg Anderson", - "email": "greg.1.anderson@greenknowe.org" - } - ], - "description": "Initialize Symfony Console commands from annotated command class methods." - }, - { - "name": "drush/drush", - "version": "8.1.16", - "version_normalized": "8.1.16.0", - "source": { - "type": "git", - "url": "https://github.com/drush-ops/drush.git", - "reference": "bbaff2dc725a5f3eb22006c5de3dc92a2de54b08" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/drush-ops/drush/zipball/bbaff2dc725a5f3eb22006c5de3dc92a2de54b08", - "reference": "bbaff2dc725a5f3eb22006c5de3dc92a2de54b08", - "shasum": "" - }, - "require": { - "consolidation/annotated-command": "^2.8.1", - "consolidation/output-formatters": "~3", - "pear/console_table": "~1.3.1", - "php": ">=5.4.5", - "psr/log": "~1.0", - "psy/psysh": "~0.6", - "symfony/console": "~2.7|^3", - "symfony/event-dispatcher": "~2.7|^3", - "symfony/finder": "~2.7|^3", - "symfony/var-dumper": "~2.7|^3", - "symfony/yaml": "~2.3|^3", - "webmozart/path-util": "~2" - }, - "require-dev": { - "phpunit/phpunit": "4.*", - "symfony/console": "~2.7", - "symfony/event-dispatcher": "~2.7", - "symfony/finder": "~2.7", - "symfony/process": "2.7.*", - "symfony/var-dumper": "~2.7", - "symfony/yaml": "~2.3" - }, - "suggest": { - "drush/config-extra": "Provides configuration workflow commands, such as config-merge.", - "ext-pcntl": "*" - }, - "time": "2018-02-06T21:18:48+00:00", - "bin": [ - "drush", - "drush.launcher", - "drush.php", - "drush.complete.sh" - ], - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "8.0.x-dev" - } - }, - "installation-source": "dist", - "autoload": { - "psr-0": { - "Drush": "lib/", - "Consolidation": "lib/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "GPL-2.0-or-later" - ], - "authors": [ - { - "name": "Moshe Weitzman", - "email": "weitzman@tejasa.com" - }, - { - "name": "Owen Barton", - "email": "drupal@owenbarton.com" - }, - { - "name": "Mark Sonnabaum", - "email": "marksonnabaum@gmail.com" - }, - { - "name": "Antoine Beaupré", - "email": "anarcat@koumbit.org" - }, - { - "name": "Greg Anderson", - "email": "greg.1.anderson@greenknowe.org" - }, - { - "name": "Jonathan Araña Cruz", - "email": "jonhattan@faita.net" - }, - { - "name": "Jonathan Hedstrom", - "email": "jhedstrom@gmail.com" - }, - { - "name": "Christopher Gervais", - "email": "chris@ergonlogic.com" - }, - { - "name": "Dave Reid", - "email": "dave@davereid.net" - }, - { - "name": "Damian Lee", - "email": "damiankloip@googlemail.com" - } - ], - "description": "Drush is a command line shell and scripting interface for Drupal, a veritable Swiss Army knife designed to make life easier for those of us who spend some of our working hours hacking away at the command prompt.", - "homepage": "http://www.drush.org" - }, - { - "name": "zendframework/zend-stdlib", - "version": "3.1.1", - "version_normalized": "3.1.1.0", - "source": { - "type": "git", - "url": "https://github.com/zendframework/zend-stdlib.git", - "reference": "10ef03144902d1955f935fff5346ed52f7d99bcc" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/zendframework/zend-stdlib/zipball/10ef03144902d1955f935fff5346ed52f7d99bcc", - "reference": "10ef03144902d1955f935fff5346ed52f7d99bcc", - "shasum": "" - }, - "require": { - "php": "^5.6 || ^7.0" - }, - "require-dev": { - "athletic/athletic": "~0.1", - "phpunit/phpunit": "~4.0", - "zendframework/zend-coding-standard": "~1.0.0" - }, - "time": "2018-04-12T16:05:42+00:00", - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "3.1-dev", - "dev-develop": "3.2-dev" - } - }, - "installation-source": "dist", - "autoload": { - "psr-4": { - "Zend\\Stdlib\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "homepage": "https://github.com/zendframework/zend-stdlib", - "keywords": [ - "stdlib", - "zf2" - ] - }, - { - "name": "zendframework/zend-feed", - "version": "2.9.0", - "version_normalized": "2.9.0.0", - "source": { - "type": "git", - "url": "https://github.com/zendframework/zend-feed.git", - "reference": "abe88686124d492e0a2a84656f15e5482bfbe030" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/zendframework/zend-feed/zipball/abe88686124d492e0a2a84656f15e5482bfbe030", - "reference": "abe88686124d492e0a2a84656f15e5482bfbe030", - "shasum": "" - }, - "require": { - "php": "^5.6 || ^7.0", - "zendframework/zend-escaper": "^2.5.2", - "zendframework/zend-stdlib": "^2.7.7 || ^3.1" - }, - "require-dev": { - "phpunit/phpunit": "^5.7.23 || ^6.4.3", - "psr/http-message": "^1.0.1", - "zendframework/zend-cache": "^2.7.2", - "zendframework/zend-coding-standard": "~1.0.0", - "zendframework/zend-db": "^2.8.2", - "zendframework/zend-http": "^2.7", - "zendframework/zend-servicemanager": "^2.7.8 || ^3.3", - "zendframework/zend-validator": "^2.10.1" - }, - "suggest": { - "psr/http-message": "PSR-7 ^1.0.1, if you wish to use Zend\\Feed\\Reader\\Http\\Psr7ResponseDecorator", - "zendframework/zend-cache": "Zend\\Cache component, for optionally caching feeds between requests", - "zendframework/zend-db": "Zend\\Db component, for use with PubSubHubbub", - "zendframework/zend-http": "Zend\\Http for PubSubHubbub, and optionally for use with Zend\\Feed\\Reader", - "zendframework/zend-servicemanager": "Zend\\ServiceManager component, for easily extending ExtensionManager implementations", - "zendframework/zend-validator": "Zend\\Validator component, for validating email addresses used in Atom feeds and entries when using the Writer subcomponent" - }, - "time": "2017-12-04T17:59:38+00:00", - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.9-dev", - "dev-develop": "2.10-dev" - } - }, - "installation-source": "dist", - "autoload": { - "psr-4": { - "Zend\\Feed\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "description": "provides functionality for consuming RSS and Atom feeds", - "keywords": [ - "ZendFramework", - "feed", - "zf" - ] - }, - { - "name": "psr/http-message", - "version": "1.0.1", - "version_normalized": "1.0.1.0", - "source": { - "type": "git", - "url": "https://github.com/php-fig/http-message.git", - "reference": "f6561bf28d520154e4b0ec72be95418abe6d9363" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/php-fig/http-message/zipball/f6561bf28d520154e4b0ec72be95418abe6d9363", - "reference": "f6561bf28d520154e4b0ec72be95418abe6d9363", - "shasum": "" - }, - "require": { - "php": ">=5.3.0" - }, - "time": "2016-08-06T14:39:51+00:00", - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.0.x-dev" - } - }, - "installation-source": "dist", - "autoload": { - "psr-4": { - "Psr\\Http\\Message\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "PHP-FIG", - "homepage": "http://www.php-fig.org/" - } - ], - "description": "Common interface for HTTP messages", - "homepage": "https://github.com/php-fig/http-message", - "keywords": [ - "http", - "http-message", - "psr", - "psr-7", - "request", - "response" - ] - }, - { - "name": "zendframework/zend-diactoros", - "version": "1.7.1", - "version_normalized": "1.7.1.0", - "source": { - "type": "git", - "url": "https://github.com/zendframework/zend-diactoros.git", - "reference": "bf26aff803a11c5cc8eb7c4878a702c403ec67f1" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/zendframework/zend-diactoros/zipball/bf26aff803a11c5cc8eb7c4878a702c403ec67f1", - "reference": "bf26aff803a11c5cc8eb7c4878a702c403ec67f1", - "shasum": "" - }, - "require": { - "php": "^5.6 || ^7.0", - "psr/http-message": "^1.0" - }, - "provide": { - "psr/http-message-implementation": "1.0" - }, - "require-dev": { - "ext-dom": "*", - "ext-libxml": "*", - "phpunit/phpunit": "^5.7.16 || ^6.0.8", - "zendframework/zend-coding-standard": "~1.0" - }, - "time": "2018-02-26T15:44:50+00:00", - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.7.x-dev", - "dev-develop": "1.8.x-dev" - } - }, - "installation-source": "dist", - "autoload": { - "psr-4": { - "Zend\\Diactoros\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-2-Clause" - ], - "description": "PSR HTTP Message implementations", - "homepage": "https://github.com/zendframework/zend-diactoros", - "keywords": [ - "http", - "psr", - "psr-7" - ] - }, - { - "name": "twig/twig", - "version": "v1.35.3", - "version_normalized": "1.35.3.0", - "source": { - "type": "git", - "url": "https://github.com/twigphp/Twig.git", - "reference": "b48680b6eb7d16b5025b9bfc4108d86f6b8af86f" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/twigphp/Twig/zipball/b48680b6eb7d16b5025b9bfc4108d86f6b8af86f", - "reference": "b48680b6eb7d16b5025b9bfc4108d86f6b8af86f", - "shasum": "" - }, - "require": { - "php": ">=5.3.3" - }, - "require-dev": { - "psr/container": "^1.0", - "symfony/debug": "^2.7", - "symfony/phpunit-bridge": "^3.3" - }, - "time": "2018-03-20T04:25:58+00:00", - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.35-dev" - } - }, - "installation-source": "dist", - "autoload": { - "psr-0": { - "Twig_": "lib/" - }, - "psr-4": { - "Twig\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com", - "homepage": "http://fabien.potencier.org", - "role": "Lead Developer" - }, - { - "name": "Armin Ronacher", - "email": "armin.ronacher@active-4.com", - "role": "Project Founder" - }, - { - "name": "Twig Team", - "homepage": "http://twig.sensiolabs.org/contributors", - "role": "Contributors" - } - ], - "description": "Twig, the flexible, fast, and secure template language for PHP", - "homepage": "http://twig.sensiolabs.org", - "keywords": [ - "templating" - ] - }, - { - "name": "symfony/translation", - "version": "v3.4.8", - "version_normalized": "3.4.8.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/translation.git", - "reference": "80e19eaf12cbb546ac40384e5c55c36306823e57" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/translation/zipball/80e19eaf12cbb546ac40384e5c55c36306823e57", - "reference": "80e19eaf12cbb546ac40384e5c55c36306823e57", - "shasum": "" - }, - "require": { - "php": "^5.5.9|>=7.0.8", - "symfony/polyfill-mbstring": "~1.0" - }, - "conflict": { - "symfony/config": "<2.8", - "symfony/dependency-injection": "<3.4", - "symfony/yaml": "<3.4" - }, - "require-dev": { - "psr/log": "~1.0", - "symfony/config": "~2.8|~3.0|~4.0", - "symfony/dependency-injection": "~3.4|~4.0", - "symfony/finder": "~2.8|~3.0|~4.0", - "symfony/intl": "^2.8.18|^3.2.5|~4.0", - "symfony/yaml": "~3.4|~4.0" - }, - "suggest": { - "psr/log": "To use logging capability in translator", - "symfony/config": "", - "symfony/yaml": "" - }, - "time": "2018-02-22T06:28:18+00:00", - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "3.4-dev" - } - }, - "installation-source": "dist", - "autoload": { - "psr-4": { - "Symfony\\Component\\Translation\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Symfony Translation Component", - "homepage": "https://symfony.com" - }, - { - "name": "symfony/validator", - "version": "v3.4.8", - "version_normalized": "3.4.8.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/validator.git", - "reference": "6fa41262dcbd50eedb1e841cfd97f5a1956cf2e7" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/validator/zipball/6fa41262dcbd50eedb1e841cfd97f5a1956cf2e7", - "reference": "6fa41262dcbd50eedb1e841cfd97f5a1956cf2e7", - "shasum": "" - }, - "require": { - "php": "^5.5.9|>=7.0.8", - "symfony/polyfill-mbstring": "~1.0", - "symfony/translation": "~2.8|~3.0|~4.0" - }, - "conflict": { - "phpunit/phpunit": "<4.8.35|<5.4.3,>=5.0", - "symfony/dependency-injection": "<3.3", - "symfony/http-kernel": "<3.3.5", - "symfony/yaml": "<3.4" - }, - "require-dev": { - "doctrine/annotations": "~1.0", - "doctrine/cache": "~1.0", - "egulias/email-validator": "^1.2.8|~2.0", - "symfony/cache": "~3.1|~4.0", - "symfony/config": "~2.8|~3.0|~4.0", - "symfony/dependency-injection": "~3.3|~4.0", - "symfony/expression-language": "~2.8|~3.0|~4.0", - "symfony/http-foundation": "~2.8|~3.0|~4.0", - "symfony/http-kernel": "^3.3.5|~4.0", - "symfony/intl": "^2.8.18|^3.2.5|~4.0", - "symfony/property-access": "~2.8|~3.0|~4.0", - "symfony/var-dumper": "~3.3|~4.0", - "symfony/yaml": "~3.4|~4.0" - }, - "suggest": { - "doctrine/annotations": "For using the annotation mapping. You will also need doctrine/cache.", - "doctrine/cache": "For using the default cached annotation reader and metadata cache.", - "egulias/email-validator": "Strict (RFC compliant) email validation", - "psr/cache-implementation": "For using the metadata cache.", - "symfony/config": "", - "symfony/expression-language": "For using the Expression validator", - "symfony/http-foundation": "", - "symfony/intl": "", - "symfony/property-access": "For accessing properties within comparison constraints", - "symfony/yaml": "" - }, - "time": "2018-04-06T07:35:25+00:00", - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "3.4-dev" - } - }, - "installation-source": "dist", - "autoload": { - "psr-4": { - "Symfony\\Component\\Validator\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Symfony Validator Component", - "homepage": "https://symfony.com" - }, - { - "name": "symfony/serializer", - "version": "v3.4.8", - "version_normalized": "3.4.8.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/serializer.git", - "reference": "d4dc1551da627273230fe16511f4bb4844c02399" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/serializer/zipball/d4dc1551da627273230fe16511f4bb4844c02399", - "reference": "d4dc1551da627273230fe16511f4bb4844c02399", - "shasum": "" - }, - "require": { - "php": "^5.5.9|>=7.0.8" - }, - "conflict": { - "phpdocumentor/type-resolver": "<0.2.1", - "symfony/dependency-injection": "<3.2", - "symfony/property-access": ">=3.0,<3.0.4|>=2.8,<2.8.4", - "symfony/property-info": "<3.1", - "symfony/yaml": "<3.4" - }, - "require-dev": { - "doctrine/annotations": "~1.0", - "doctrine/cache": "~1.0", - "phpdocumentor/reflection-docblock": "^3.0|^4.0", - "symfony/cache": "~3.1|~4.0", - "symfony/config": "~2.8|~3.0|~4.0", - "symfony/dependency-injection": "~3.2|~4.0", - "symfony/http-foundation": "~2.8|~3.0|~4.0", - "symfony/property-access": "~2.8|~3.0|~4.0", - "symfony/property-info": "~3.1|~4.0", - "symfony/yaml": "~3.4|~4.0" - }, - "suggest": { - "doctrine/annotations": "For using the annotation mapping. You will also need doctrine/cache.", - "doctrine/cache": "For using the default cached annotation reader and metadata cache.", - "psr/cache-implementation": "For using the metadata cache.", - "symfony/config": "For using the XML mapping loader.", - "symfony/http-foundation": "To use the DataUriNormalizer.", - "symfony/property-access": "For using the ObjectNormalizer.", - "symfony/property-info": "To deserialize relations.", - "symfony/yaml": "For using the default YAML mapping loader." - }, - "time": "2018-03-15T19:08:29+00:00", - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "3.4-dev" - } - }, - "installation-source": "dist", - "autoload": { - "psr-4": { - "Symfony\\Component\\Serializer\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Symfony Serializer Component", - "homepage": "https://symfony.com" - }, - { - "name": "symfony/routing", - "version": "v3.4.8", - "version_normalized": "3.4.8.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/routing.git", - "reference": "50f333b707bef9f6972ad04e6df3ec8875c9a67c" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/routing/zipball/50f333b707bef9f6972ad04e6df3ec8875c9a67c", - "reference": "50f333b707bef9f6972ad04e6df3ec8875c9a67c", - "shasum": "" - }, - "require": { - "php": "^5.5.9|>=7.0.8" - }, - "conflict": { - "symfony/config": "<3.3.1", - "symfony/dependency-injection": "<3.3", - "symfony/yaml": "<3.4" - }, - "require-dev": { - "doctrine/annotations": "~1.0", - "doctrine/common": "~2.2", - "psr/log": "~1.0", - "symfony/config": "^3.3.1|~4.0", - "symfony/dependency-injection": "~3.3|~4.0", - "symfony/expression-language": "~2.8|~3.0|~4.0", - "symfony/http-foundation": "~2.8|~3.0|~4.0", - "symfony/yaml": "~3.4|~4.0" - }, - "suggest": { - "doctrine/annotations": "For using the annotation loader", - "symfony/config": "For using the all-in-one router or any loader", - "symfony/dependency-injection": "For loading routes from a service", - "symfony/expression-language": "For using expression matching", - "symfony/http-foundation": "For using a Symfony Request object", - "symfony/yaml": "For using the YAML loader" - }, - "time": "2018-04-04T13:22:16+00:00", - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "3.4-dev" - } - }, - "installation-source": "dist", - "autoload": { - "psr-4": { - "Symfony\\Component\\Routing\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Symfony Routing Component", - "homepage": "https://symfony.com", - "keywords": [ - "router", - "routing", - "uri", - "url" - ] - }, - { - "name": "paragonie/random_compat", - "version": "v2.0.12", - "version_normalized": "2.0.12.0", - "source": { - "type": "git", - "url": "https://github.com/paragonie/random_compat.git", - "reference": "258c89a6b97de7dfaf5b8c7607d0478e236b04fb" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/paragonie/random_compat/zipball/258c89a6b97de7dfaf5b8c7607d0478e236b04fb", - "reference": "258c89a6b97de7dfaf5b8c7607d0478e236b04fb", - "shasum": "" - }, - "require": { - "php": ">=5.2.0" - }, - "require-dev": { - "phpunit/phpunit": "4.*|5.*" - }, - "suggest": { - "ext-libsodium": "Provides a modern crypto API that can be used to generate random bytes." - }, - "time": "2018-04-04T21:24:14+00:00", - "type": "library", - "installation-source": "dist", - "autoload": { - "files": [ - "lib/random.php" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Paragon Initiative Enterprises", - "email": "security@paragonie.com", - "homepage": "https://paragonie.com" - } - ], - "description": "PHP 5.x polyfill for random_bytes() and random_int() from PHP 7", - "keywords": [ - "csprng", - "pseudorandom", - "random" - ] - }, - { - "name": "symfony/polyfill-php70", - "version": "v1.7.0", - "version_normalized": "1.7.0.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/polyfill-php70.git", - "reference": "3532bfcd8f933a7816f3a0a59682fc404776600f" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php70/zipball/3532bfcd8f933a7816f3a0a59682fc404776600f", - "reference": "3532bfcd8f933a7816f3a0a59682fc404776600f", - "shasum": "" - }, - "require": { - "paragonie/random_compat": "~1.0|~2.0", - "php": ">=5.3.3" - }, - "time": "2018-01-30T19:27:44+00:00", - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.7-dev" - } - }, - "installation-source": "dist", - "autoload": { - "psr-4": { - "Symfony\\Polyfill\\Php70\\": "" - }, - "files": [ - "bootstrap.php" - ], - "classmap": [ - "Resources/stubs" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Symfony polyfill backporting some PHP 7.0+ features to lower PHP versions", - "homepage": "https://symfony.com", - "keywords": [ - "compatibility", - "polyfill", - "portable", - "shim" - ] - }, - { - "name": "symfony/http-foundation", - "version": "v3.4.8", - "version_normalized": "3.4.8.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/http-foundation.git", - "reference": "b11e6d165ff4cbf5685d185ab19a90f2f3bb7d1e" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/http-foundation/zipball/b11e6d165ff4cbf5685d185ab19a90f2f3bb7d1e", - "reference": "b11e6d165ff4cbf5685d185ab19a90f2f3bb7d1e", - "shasum": "" - }, - "require": { - "php": "^5.5.9|>=7.0.8", - "symfony/polyfill-mbstring": "~1.1", - "symfony/polyfill-php70": "~1.6" - }, - "require-dev": { - "symfony/expression-language": "~2.8|~3.0|~4.0" - }, - "time": "2018-04-03T05:22:50+00:00", - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "3.4-dev" - } - }, - "installation-source": "dist", - "autoload": { - "psr-4": { - "Symfony\\Component\\HttpFoundation\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Symfony HttpFoundation Component", - "homepage": "https://symfony.com" - }, - { - "name": "symfony/psr-http-message-bridge", - "version": "v1.0.2", - "version_normalized": "1.0.2.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/psr-http-message-bridge.git", - "reference": "c2b757934f2d9681a287e662efbc27c41fe8ef86" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/psr-http-message-bridge/zipball/c2b757934f2d9681a287e662efbc27c41fe8ef86", - "reference": "c2b757934f2d9681a287e662efbc27c41fe8ef86", - "shasum": "" - }, - "require": { - "php": ">=5.3.3", - "psr/http-message": "~1.0", - "symfony/http-foundation": "~2.3|~3.0|~4.0" - }, - "require-dev": { - "symfony/phpunit-bridge": "~3.2|4.0" - }, - "suggest": { - "psr/http-message-implementation": "To use the HttpFoundation factory", - "zendframework/zend-diactoros": "To use the Zend Diactoros factory" - }, - "time": "2017-12-19T00:31:44+00:00", - "type": "symfony-bridge", - "extra": { - "branch-alias": { - "dev-master": "1.0-dev" - } - }, - "installation-source": "dist", - "autoload": { - "psr-4": { - "Symfony\\Bridge\\PsrHttpMessage\\": "" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Symfony Community", - "homepage": "http://symfony.com/contributors" - }, - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - } - ], - "description": "PSR HTTP message bridge", - "homepage": "http://symfony.com", - "keywords": [ - "http", - "http-message", - "psr-7" - ] - }, - { - "name": "symfony/process", - "version": "v3.4.8", - "version_normalized": "3.4.8.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/process.git", - "reference": "4b7d64e852886319e93ddfdecff0d744ab87658b" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/process/zipball/4b7d64e852886319e93ddfdecff0d744ab87658b", - "reference": "4b7d64e852886319e93ddfdecff0d744ab87658b", - "shasum": "" - }, - "require": { - "php": "^5.5.9|>=7.0.8" - }, - "time": "2018-04-03T05:22:50+00:00", - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "3.4-dev" - } - }, - "installation-source": "dist", - "autoload": { - "psr-4": { - "Symfony\\Component\\Process\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Symfony Process Component", - "homepage": "https://symfony.com" - }, - { - "name": "symfony/polyfill-iconv", - "version": "v1.7.0", - "version_normalized": "1.7.0.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/polyfill-iconv.git", - "reference": "bd515d8f392730c833bc1ba993a4f598da64fa5b" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-iconv/zipball/bd515d8f392730c833bc1ba993a4f598da64fa5b", - "reference": "bd515d8f392730c833bc1ba993a4f598da64fa5b", - "shasum": "" - }, - "require": { - "php": ">=5.3.3" - }, - "suggest": { - "ext-iconv": "For best performance" - }, - "time": "2018-01-30T19:27:44+00:00", - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.7-dev" - } - }, - "installation-source": "dist", - "autoload": { - "psr-4": { - "Symfony\\Polyfill\\Iconv\\": "" - }, - "files": [ - "bootstrap.php" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Symfony polyfill for the Iconv extension", - "homepage": "https://symfony.com", - "keywords": [ - "compatibility", - "iconv", - "polyfill", - "portable", - "shim" - ] - }, - { - "name": "symfony/http-kernel", - "version": "v3.4.8", - "version_normalized": "3.4.8.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/http-kernel.git", - "reference": "3cc2d4374aa9590c09277ad68657671cf49dbbf4" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/http-kernel/zipball/3cc2d4374aa9590c09277ad68657671cf49dbbf4", - "reference": "3cc2d4374aa9590c09277ad68657671cf49dbbf4", - "shasum": "" - }, - "require": { - "php": "^5.5.9|>=7.0.8", - "psr/log": "~1.0", - "symfony/debug": "~2.8|~3.0|~4.0", - "symfony/event-dispatcher": "~2.8|~3.0|~4.0", - "symfony/http-foundation": "^3.4.4|^4.0.4" - }, - "conflict": { - "symfony/config": "<2.8", - "symfony/dependency-injection": "<3.4.5|<4.0.5,>=4", - "symfony/var-dumper": "<3.3", - "twig/twig": "<1.34|<2.4,>=2" - }, - "provide": { - "psr/log-implementation": "1.0" - }, - "require-dev": { - "psr/cache": "~1.0", - "symfony/browser-kit": "~2.8|~3.0|~4.0", - "symfony/class-loader": "~2.8|~3.0", - "symfony/config": "~2.8|~3.0|~4.0", - "symfony/console": "~2.8|~3.0|~4.0", - "symfony/css-selector": "~2.8|~3.0|~4.0", - "symfony/dependency-injection": "^3.4.5|^4.0.5", - "symfony/dom-crawler": "~2.8|~3.0|~4.0", - "symfony/expression-language": "~2.8|~3.0|~4.0", - "symfony/finder": "~2.8|~3.0|~4.0", - "symfony/process": "~2.8|~3.0|~4.0", - "symfony/routing": "~3.4|~4.0", - "symfony/stopwatch": "~2.8|~3.0|~4.0", - "symfony/templating": "~2.8|~3.0|~4.0", - "symfony/translation": "~2.8|~3.0|~4.0", - "symfony/var-dumper": "~3.3|~4.0" - }, - "suggest": { - "symfony/browser-kit": "", - "symfony/config": "", - "symfony/console": "", - "symfony/dependency-injection": "", - "symfony/finder": "", - "symfony/var-dumper": "" - }, - "time": "2018-04-06T15:19:48+00:00", - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "3.4-dev" - } - }, - "installation-source": "dist", - "autoload": { - "psr-4": { - "Symfony\\Component\\HttpKernel\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Symfony HttpKernel Component", - "homepage": "https://symfony.com" - }, - { - "name": "psr/container", - "version": "1.0.0", - "version_normalized": "1.0.0.0", - "source": { - "type": "git", - "url": "https://github.com/php-fig/container.git", - "reference": "b7ce3b176482dbbc1245ebf52b181af44c2cf55f" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/php-fig/container/zipball/b7ce3b176482dbbc1245ebf52b181af44c2cf55f", - "reference": "b7ce3b176482dbbc1245ebf52b181af44c2cf55f", - "shasum": "" - }, - "require": { - "php": ">=5.3.0" - }, - "time": "2017-02-14T16:28:37+00:00", - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.0.x-dev" - } - }, - "installation-source": "dist", - "autoload": { - "psr-4": { - "Psr\\Container\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "PHP-FIG", - "homepage": "http://www.php-fig.org/" - } - ], - "description": "Common Container Interface (PHP FIG PSR-11)", - "homepage": "https://github.com/php-fig/container", - "keywords": [ - "PSR-11", - "container", - "container-interface", - "container-interop", - "psr" - ] - }, - { - "name": "symfony/dependency-injection", - "version": "v3.4.8", - "version_normalized": "3.4.8.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/dependency-injection.git", - "reference": "24a68710c6ddc1e3d159a110cef94cedfcf3c611" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/dependency-injection/zipball/24a68710c6ddc1e3d159a110cef94cedfcf3c611", - "reference": "24a68710c6ddc1e3d159a110cef94cedfcf3c611", - "shasum": "" - }, - "require": { - "php": "^5.5.9|>=7.0.8", - "psr/container": "^1.0" - }, - "conflict": { - "symfony/config": "<3.3.7", - "symfony/finder": "<3.3", - "symfony/proxy-manager-bridge": "<3.4", - "symfony/yaml": "<3.4" - }, - "provide": { - "psr/container-implementation": "1.0" - }, - "require-dev": { - "symfony/config": "~3.3|~4.0", - "symfony/expression-language": "~2.8|~3.0|~4.0", - "symfony/yaml": "~3.4|~4.0" - }, - "suggest": { - "symfony/config": "", - "symfony/expression-language": "For using expressions in service container configuration", - "symfony/finder": "For using double-star glob patterns or when GLOB_BRACE portability is required", - "symfony/proxy-manager-bridge": "Generate service proxies to lazy load them", - "symfony/yaml": "" - }, - "time": "2018-03-29T11:25:31+00:00", - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "3.4-dev" - } - }, - "installation-source": "dist", - "autoload": { - "psr-4": { - "Symfony\\Component\\DependencyInjection\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Symfony DependencyInjection Component", - "homepage": "https://symfony.com" - }, - { - "name": "symfony/class-loader", - "version": "v3.4.8", - "version_normalized": "3.4.8.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/class-loader.git", - "reference": "e63c12699822bb3b667e7216ba07fbcc3a3e203e" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/class-loader/zipball/e63c12699822bb3b667e7216ba07fbcc3a3e203e", - "reference": "e63c12699822bb3b667e7216ba07fbcc3a3e203e", - "shasum": "" - }, - "require": { - "php": "^5.5.9|>=7.0.8" - }, - "require-dev": { - "symfony/finder": "~2.8|~3.0|~4.0", - "symfony/polyfill-apcu": "~1.1" - }, - "suggest": { - "symfony/polyfill-apcu": "For using ApcClassLoader on HHVM" - }, - "time": "2018-01-03T07:37:34+00:00", - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "3.4-dev" - } - }, - "installation-source": "dist", - "autoload": { - "psr-4": { - "Symfony\\Component\\ClassLoader\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Symfony ClassLoader Component", - "homepage": "https://symfony.com" - }, - { - "name": "symfony-cmf/routing", - "version": "1.4.1", - "version_normalized": "1.4.1.0", - "source": { - "type": "git", - "url": "https://github.com/symfony-cmf/routing.git", - "reference": "fb1e7f85ff8c6866238b7e73a490a0a0243ae8ac" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony-cmf/routing/zipball/fb1e7f85ff8c6866238b7e73a490a0a0243ae8ac", - "reference": "fb1e7f85ff8c6866238b7e73a490a0a0243ae8ac", - "shasum": "" - }, - "require": { - "php": "^5.3.9|^7.0", - "psr/log": "1.*", - "symfony/http-kernel": "^2.2|3.*", - "symfony/routing": "^2.2|3.*" - }, - "require-dev": { - "friendsofsymfony/jsrouting-bundle": "^1.1", - "symfony-cmf/testing": "^1.3", - "symfony/config": "^2.2|3.*", - "symfony/dependency-injection": "^2.0.5|3.*", - "symfony/event-dispatcher": "^2.1|3.*" - }, - "suggest": { - "symfony/event-dispatcher": "DynamicRouter can optionally trigger an event at the start of matching. Minimal version (~2.1)" - }, - "time": "2017-05-09T08:10:41+00:00", - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.4-dev" - } - }, - "installation-source": "dist", - "autoload": { - "psr-4": { - "Symfony\\Cmf\\Component\\Routing\\": "" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Symfony CMF Community", - "homepage": "https://github.com/symfony-cmf/Routing/contributors" - } - ], - "description": "Extends the Symfony2 routing component for dynamic routes and chaining several routers", - "homepage": "http://cmf.symfony.com", - "keywords": [ - "database", - "routing" - ] - }, - { - "name": "stack/builder", - "version": "v1.0.5", - "version_normalized": "1.0.5.0", - "source": { - "type": "git", - "url": "https://github.com/stackphp/builder.git", - "reference": "fb3d136d04c6be41120ebf8c0cc71fe9507d750a" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/stackphp/builder/zipball/fb3d136d04c6be41120ebf8c0cc71fe9507d750a", - "reference": "fb3d136d04c6be41120ebf8c0cc71fe9507d750a", - "shasum": "" - }, - "require": { - "php": ">=5.3.0", - "symfony/http-foundation": "~2.1|~3.0|~4.0", - "symfony/http-kernel": "~2.1|~3.0|~4.0" - }, - "require-dev": { - "silex/silex": "~1.0" - }, - "time": "2017-11-18T14:57:29+00:00", - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.0-dev" - } - }, - "installation-source": "dist", - "autoload": { - "psr-0": { - "Stack": "src" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Igor Wiedler", - "email": "igor@wiedler.ch" - } - ], - "description": "Builder for stack middlewares based on HttpKernelInterface.", - "keywords": [ - "stack" - ] - }, - { - "name": "masterminds/html5", - "version": "2.3.0", - "version_normalized": "2.3.0.0", - "source": { - "type": "git", - "url": "https://github.com/Masterminds/html5-php.git", - "reference": "2c37c6c520b995b761674de3be8455a381679067" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/Masterminds/html5-php/zipball/2c37c6c520b995b761674de3be8455a381679067", - "reference": "2c37c6c520b995b761674de3be8455a381679067", - "shasum": "" - }, - "require": { - "ext-libxml": "*", - "php": ">=5.3.0" - }, - "require-dev": { - "phpunit/phpunit": "4.*", - "sami/sami": "~2.0", - "satooshi/php-coveralls": "1.0.*" - }, - "time": "2017-09-04T12:26:28+00:00", - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.2-dev" - } - }, - "installation-source": "dist", - "autoload": { - "psr-4": { - "Masterminds\\": "src" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Matt Butcher", - "email": "technosophos@gmail.com" - }, - { - "name": "Asmir Mustafic", - "email": "goetas@gmail.com" - }, - { - "name": "Matt Farina", - "email": "matt@mattfarina.com" - } - ], - "description": "An HTML5 parser and serializer.", - "homepage": "http://masterminds.github.io/html5-php", - "keywords": [ - "HTML5", - "dom", - "html", - "parser", - "querypath", - "serializer", - "xml" - ] - }, - { - "name": "guzzlehttp/psr7", - "version": "1.4.2", - "version_normalized": "1.4.2.0", - "source": { - "type": "git", - "url": "https://github.com/guzzle/psr7.git", - "reference": "f5b8a8512e2b58b0071a7280e39f14f72e05d87c" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/guzzle/psr7/zipball/f5b8a8512e2b58b0071a7280e39f14f72e05d87c", - "reference": "f5b8a8512e2b58b0071a7280e39f14f72e05d87c", - "shasum": "" - }, - "require": { - "php": ">=5.4.0", - "psr/http-message": "~1.0" - }, - "provide": { - "psr/http-message-implementation": "1.0" - }, - "require-dev": { - "phpunit/phpunit": "~4.0" - }, - "time": "2017-03-20T17:10:46+00:00", - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.4-dev" - } - }, - "installation-source": "dist", - "autoload": { - "psr-4": { - "GuzzleHttp\\Psr7\\": "src/" - }, - "files": [ - "src/functions_include.php" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Michael Dowling", - "email": "mtdowling@gmail.com", - "homepage": "https://github.com/mtdowling" - }, - { - "name": "Tobias Schultze", - "homepage": "https://github.com/Tobion" - } - ], - "description": "PSR-7 message implementation that also provides common utility methods", - "keywords": [ - "http", - "message", - "request", - "response", - "stream", - "uri", - "url" - ] - }, - { - "name": "guzzlehttp/promises", - "version": "v1.3.1", - "version_normalized": "1.3.1.0", - "source": { - "type": "git", - "url": "https://github.com/guzzle/promises.git", - "reference": "a59da6cf61d80060647ff4d3eb2c03a2bc694646" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/guzzle/promises/zipball/a59da6cf61d80060647ff4d3eb2c03a2bc694646", - "reference": "a59da6cf61d80060647ff4d3eb2c03a2bc694646", - "shasum": "" - }, - "require": { - "php": ">=5.5.0" - }, - "require-dev": { - "phpunit/phpunit": "^4.0" - }, - "time": "2016-12-20T10:07:11+00:00", - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.4-dev" - } - }, - "installation-source": "dist", - "autoload": { - "psr-4": { - "GuzzleHttp\\Promise\\": "src/" - }, - "files": [ - "src/functions_include.php" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Michael Dowling", - "email": "mtdowling@gmail.com", - "homepage": "https://github.com/mtdowling" - } - ], - "description": "Guzzle promises library", - "keywords": [ - "promise" - ] - }, - { - "name": "guzzlehttp/guzzle", - "version": "6.3.3", - "version_normalized": "6.3.3.0", - "source": { - "type": "git", - "url": "https://github.com/guzzle/guzzle.git", - "reference": "407b0cb880ace85c9b63c5f9551db498cb2d50ba" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/guzzle/guzzle/zipball/407b0cb880ace85c9b63c5f9551db498cb2d50ba", - "reference": "407b0cb880ace85c9b63c5f9551db498cb2d50ba", - "shasum": "" - }, - "require": { - "guzzlehttp/promises": "^1.0", - "guzzlehttp/psr7": "^1.4", - "php": ">=5.5" - }, - "require-dev": { - "ext-curl": "*", - "phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.4 || ^7.0", - "psr/log": "^1.0" - }, - "suggest": { - "psr/log": "Required for using the Log middleware" - }, - "time": "2018-04-22T15:46:56+00:00", - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "6.3-dev" - } - }, - "installation-source": "dist", - "autoload": { - "files": [ - "src/functions_include.php" - ], - "psr-4": { - "GuzzleHttp\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Michael Dowling", - "email": "mtdowling@gmail.com", - "homepage": "https://github.com/mtdowling" - } - ], - "description": "Guzzle is a PHP HTTP client library", - "homepage": "http://guzzlephp.org/", - "keywords": [ - "client", - "curl", - "framework", - "http", - "http client", - "rest", - "web service" - ] - }, - { - "name": "doctrine/lexer", - "version": "v1.0.1", - "version_normalized": "1.0.1.0", - "source": { - "type": "git", - "url": "https://github.com/doctrine/lexer.git", - "reference": "83893c552fd2045dd78aef794c31e694c37c0b8c" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/doctrine/lexer/zipball/83893c552fd2045dd78aef794c31e694c37c0b8c", - "reference": "83893c552fd2045dd78aef794c31e694c37c0b8c", - "shasum": "" - }, - "require": { - "php": ">=5.3.2" - }, - "time": "2014-09-09T13:34:57+00:00", - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.0.x-dev" - } - }, - "installation-source": "dist", - "autoload": { - "psr-0": { - "Doctrine\\Common\\Lexer\\": "lib/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { "name": "Roman Borschel", "email": "roman@code-factory.org" }, { + "name": "Benjamin Eberlei", + "email": "kontakt@beberlei.de" + }, + { "name": "Guilherme Blanco", "email": "guilhermeblanco@gmail.com" }, { + "name": "Jonathan Wage", + "email": "jonwage@gmail.com" + }, + { "name": "Johannes Schmitt", "email": "schmittjoh@gmail.com" } ], - "description": "Base library for a lexer that can be used in Top-Down, Recursive Descent Parsers.", + "description": "Docblock Annotations Parser", "homepage": "http://www.doctrine-project.org", "keywords": [ - "lexer", + "annotations", + "docblock", "parser" ] }, { - "name": "egulias/email-validator", - "version": "1.2.14", - "version_normalized": "1.2.14.0", + "name": "doctrine/cache", + "version": "v1.6.2", + "version_normalized": "1.6.2.0", "source": { "type": "git", - "url": "https://github.com/egulias/EmailValidator.git", - "reference": "5642614492f0ca2064c01d60cc33284cc2f731a9" + "url": "https://github.com/doctrine/cache.git", + "reference": "eb152c5100571c7a45470ff2a35095ab3f3b900b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/egulias/EmailValidator/zipball/5642614492f0ca2064c01d60cc33284cc2f731a9", - "reference": "5642614492f0ca2064c01d60cc33284cc2f731a9", + "url": "https://api.github.com/repos/doctrine/cache/zipball/eb152c5100571c7a45470ff2a35095ab3f3b900b", + "reference": "eb152c5100571c7a45470ff2a35095ab3f3b900b", "shasum": "" }, "require": { - "doctrine/lexer": "^1.0.1", - "php": ">= 5.3.3" + "php": "~5.5|~7.0" + }, + "conflict": { + "doctrine/common": ">2.2,<2.4" }, "require-dev": { - "phpunit/phpunit": "^4.8.24" - }, - "time": "2017-02-03T22:48:59+00:00", + "phpunit/phpunit": "~4.8|~5.0", + "predis/predis": "~1.0", + "satooshi/php-coveralls": "~0.6" + }, + "time": "2017-07-22T12:49:21+00:00", "type": "library", "extra": { "branch-alias": { - "dev-master": "2.0.x-dev" + "dev-master": "1.6.x-dev" } }, "installation-source": "dist", "autoload": { - "psr-0": { - "Egulias\\": "src/" + "psr-4": { + "Doctrine\\Common\\Cache\\": "lib/Doctrine/Common/Cache" } }, "notification-url": "https://packagist.org/downloads/", @@ -2965,123 +739,6 @@ ], "authors": [ { - "name": "Eduardo Gulias Davis" - } - ], - "description": "A library for validating emails", - "homepage": "https://github.com/egulias/EmailValidator", - "keywords": [ - "email", - "emailvalidation", - "emailvalidator", - "validation", - "validator" - ] - }, - { - "name": "easyrdf/easyrdf", - "version": "0.9.1", - "version_normalized": "0.9.1.0", - "source": { - "type": "git", - "url": "https://github.com/njh/easyrdf.git", - "reference": "acd09dfe0555fbcfa254291e433c45fdd4652566" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/njh/easyrdf/zipball/acd09dfe0555fbcfa254291e433c45fdd4652566", - "reference": "acd09dfe0555fbcfa254291e433c45fdd4652566", - "shasum": "" - }, - "require": { - "ext-mbstring": "*", - "ext-pcre": "*", - "php": ">=5.2.8" - }, - "require-dev": { - "phpunit/phpunit": "~3.5", - "sami/sami": "~1.4", - "squizlabs/php_codesniffer": "~1.4.3" - }, - "suggest": { - "ml/json-ld": "~1.0" - }, - "time": "2015-02-27T09:45:49+00:00", - "type": "library", - "installation-source": "dist", - "autoload": { - "psr-0": { - "EasyRdf_": "lib/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Nicholas Humfrey", - "email": "njh@aelius.com", - "homepage": "http://www.aelius.com/njh/", - "role": "Developer" - }, - { - "name": "Alexey Zakhlestin", - "email": "indeyets@gmail.com", - "role": "Developer" - } - ], - "description": "EasyRdf is a PHP library designed to make it easy to consume and produce RDF.", - "homepage": "http://www.easyrdf.org/", - "keywords": [ - "Linked Data", - "RDF", - "Semantic Web", - "Turtle", - "rdfa", - "sparql" - ] - }, - { - "name": "doctrine/inflector", - "version": "v1.2.0", - "version_normalized": "1.2.0.0", - "source": { - "type": "git", - "url": "https://github.com/doctrine/inflector.git", - "reference": "e11d84c6e018beedd929cff5220969a3c6d1d462" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/doctrine/inflector/zipball/e11d84c6e018beedd929cff5220969a3c6d1d462", - "reference": "e11d84c6e018beedd929cff5220969a3c6d1d462", - "shasum": "" - }, - "require": { - "php": "^7.0" - }, - "require-dev": { - "phpunit/phpunit": "^6.2" - }, - "time": "2017-07-22T12:18:28+00:00", - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.2.x-dev" - } - }, - "installation-source": "dist", - "autoload": { - "psr-4": { - "Doctrine\\Common\\Inflector\\": "lib/Doctrine/Common/Inflector" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { "name": "Roman Borschel", "email": "roman@code-factory.org" }, @@ -3102,13 +759,11 @@ "email": "schmittjoh@gmail.com" } ], - "description": "Common String Manipulations with regard to casing and singular/plural rules.", + "description": "Caching library offering an object-oriented API for many cache backends", "homepage": "http://www.doctrine-project.org", "keywords": [ - "inflection", - "pluralize", - "singularize", - "string" + "cache", + "caching" ] }, { @@ -3181,148 +836,6 @@ ] }, { - "name": "doctrine/cache", - "version": "v1.6.2", - "version_normalized": "1.6.2.0", - "source": { - "type": "git", - "url": "https://github.com/doctrine/cache.git", - "reference": "eb152c5100571c7a45470ff2a35095ab3f3b900b" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/doctrine/cache/zipball/eb152c5100571c7a45470ff2a35095ab3f3b900b", - "reference": "eb152c5100571c7a45470ff2a35095ab3f3b900b", - "shasum": "" - }, - "require": { - "php": "~5.5|~7.0" - }, - "conflict": { - "doctrine/common": ">2.2,<2.4" - }, - "require-dev": { - "phpunit/phpunit": "~4.8|~5.0", - "predis/predis": "~1.0", - "satooshi/php-coveralls": "~0.6" - }, - "time": "2017-07-22T12:49:21+00:00", - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.6.x-dev" - } - }, - "installation-source": "dist", - "autoload": { - "psr-4": { - "Doctrine\\Common\\Cache\\": "lib/Doctrine/Common/Cache" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Roman Borschel", - "email": "roman@code-factory.org" - }, - { - "name": "Benjamin Eberlei", - "email": "kontakt@beberlei.de" - }, - { - "name": "Guilherme Blanco", - "email": "guilhermeblanco@gmail.com" - }, - { - "name": "Jonathan Wage", - "email": "jonwage@gmail.com" - }, - { - "name": "Johannes Schmitt", - "email": "schmittjoh@gmail.com" - } - ], - "description": "Caching library offering an object-oriented API for many cache backends", - "homepage": "http://www.doctrine-project.org", - "keywords": [ - "cache", - "caching" - ] - }, - { - "name": "doctrine/annotations", - "version": "v1.4.0", - "version_normalized": "1.4.0.0", - "source": { - "type": "git", - "url": "https://github.com/doctrine/annotations.git", - "reference": "54cacc9b81758b14e3ce750f205a393d52339e97" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/doctrine/annotations/zipball/54cacc9b81758b14e3ce750f205a393d52339e97", - "reference": "54cacc9b81758b14e3ce750f205a393d52339e97", - "shasum": "" - }, - "require": { - "doctrine/lexer": "1.*", - "php": "^5.6 || ^7.0" - }, - "require-dev": { - "doctrine/cache": "1.*", - "phpunit/phpunit": "^5.7" - }, - "time": "2017-02-24T16:22:25+00:00", - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.4.x-dev" - } - }, - "installation-source": "dist", - "autoload": { - "psr-4": { - "Doctrine\\Common\\Annotations\\": "lib/Doctrine/Common/Annotations" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Roman Borschel", - "email": "roman@code-factory.org" - }, - { - "name": "Benjamin Eberlei", - "email": "kontakt@beberlei.de" - }, - { - "name": "Guilherme Blanco", - "email": "guilhermeblanco@gmail.com" - }, - { - "name": "Jonathan Wage", - "email": "jonwage@gmail.com" - }, - { - "name": "Johannes Schmitt", - "email": "schmittjoh@gmail.com" - } - ], - "description": "Docblock Annotations Parser", - "homepage": "http://www.doctrine-project.org", - "keywords": [ - "annotations", - "docblock", - "parser" - ] - }, - { "name": "doctrine/common", "version": "v2.7.3", "version_normalized": "2.7.3.0", @@ -3398,38 +911,37 @@ ] }, { - "name": "composer/semver", - "version": "1.4.2", - "version_normalized": "1.4.2.0", + "name": "doctrine/inflector", + "version": "v1.2.0", + "version_normalized": "1.2.0.0", "source": { "type": "git", - "url": "https://github.com/composer/semver.git", - "reference": "c7cb9a2095a074d131b65a8a0cd294479d785573" + "url": "https://github.com/doctrine/inflector.git", + "reference": "e11d84c6e018beedd929cff5220969a3c6d1d462" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/composer/semver/zipball/c7cb9a2095a074d131b65a8a0cd294479d785573", - "reference": "c7cb9a2095a074d131b65a8a0cd294479d785573", + "url": "https://api.github.com/repos/doctrine/inflector/zipball/e11d84c6e018beedd929cff5220969a3c6d1d462", + "reference": "e11d84c6e018beedd929cff5220969a3c6d1d462", "shasum": "" }, "require": { - "php": "^5.3.2 || ^7.0" + "php": "^7.0" }, "require-dev": { - "phpunit/phpunit": "^4.5 || ^5.0.5", - "phpunit/phpunit-mock-objects": "2.3.0 || ^3.0" - }, - "time": "2016-08-30T16:08:34+00:00", + "phpunit/phpunit": "^6.2" + }, + "time": "2017-07-22T12:18:28+00:00", "type": "library", "extra": { "branch-alias": { - "dev-master": "1.x-dev" + "dev-master": "1.2.x-dev" } }, "installation-source": "dist", "autoload": { "psr-4": { - "Composer\\Semver\\": "src" + "Doctrine\\Common\\Inflector\\": "lib/Doctrine/Common/Inflector" } }, "notification-url": "https://packagist.org/downloads/", @@ -3438,64 +950,71 @@ ], "authors": [ { - "name": "Nils Adermann", - "email": "naderman@naderman.de", - "homepage": "http://www.naderman.de" + "name": "Roman Borschel", + "email": "roman@code-factory.org" }, { - "name": "Jordi Boggiano", - "email": "j.boggiano@seld.be", - "homepage": "http://seld.be" + "name": "Benjamin Eberlei", + "email": "kontakt@beberlei.de" }, { - "name": "Rob Bast", - "email": "rob.bast@gmail.com", - "homepage": "http://robbast.nl" - } - ], - "description": "Semver library that offers utilities, version constraint parsing and validation.", + "name": "Guilherme Blanco", + "email": "guilhermeblanco@gmail.com" + }, + { + "name": "Jonathan Wage", + "email": "jonwage@gmail.com" + }, + { + "name": "Johannes Schmitt", + "email": "schmittjoh@gmail.com" + } + ], + "description": "Common String Manipulations with regard to casing and singular/plural rules.", + "homepage": "http://www.doctrine-project.org", "keywords": [ - "semantic", - "semver", - "validation", - "versioning" + "inflection", + "pluralize", + "singularize", + "string" ] }, { - "name": "asm89/stack-cors", - "version": "1.2.0", - "version_normalized": "1.2.0.0", + "name": "doctrine/instantiator", + "version": "1.0.5", + "version_normalized": "1.0.5.0", "source": { "type": "git", - "url": "https://github.com/asm89/stack-cors.git", - "reference": "c163e2b614550aedcf71165db2473d936abbced6" + "url": "https://github.com/doctrine/instantiator.git", + "reference": "8e884e78f9f0eb1329e445619e04456e64d8051d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/asm89/stack-cors/zipball/c163e2b614550aedcf71165db2473d936abbced6", - "reference": "c163e2b614550aedcf71165db2473d936abbced6", + "url": "https://api.github.com/repos/doctrine/instantiator/zipball/8e884e78f9f0eb1329e445619e04456e64d8051d", + "reference": "8e884e78f9f0eb1329e445619e04456e64d8051d", "shasum": "" }, "require": { - "php": ">=5.5.9", - "symfony/http-foundation": "~2.7|~3.0|~4.0", - "symfony/http-kernel": "~2.7|~3.0|~4.0" + "php": ">=5.3,<8.0-DEV" }, "require-dev": { - "phpunit/phpunit": "^5.0 || ^4.8.10", - "squizlabs/php_codesniffer": "^2.3" - }, - "time": "2017-12-20T14:37:45+00:00", + "athletic/athletic": "~0.1.8", + "ext-pdo": "*", + "ext-phar": "*", + "phpunit/phpunit": "~4.0", + "squizlabs/php_codesniffer": "~2.0" + }, + "time": "2015-06-14T21:17:01+00:00", "type": "library", "extra": { "branch-alias": { - "dev-master": "1.2-dev" + "dev-master": "1.0.x-dev" } }, "installation-source": "dist", "autoload": { "psr-4": { - "Asm89\\Stack\\": "src/Asm89/Stack/" + "Doctrine\\Instantiator\\": "src/Doctrine/Instantiator/" } }, "notification-url": "https://packagist.org/downloads/", @@ -3504,50 +1023,48 @@ ], "authors": [ { - "name": "Alexander", - "email": "iam.asm89@gmail.com" - } - ], - "description": "Cross-origin resource sharing library and stack middleware", - "homepage": "https://github.com/asm89/stack-cors", + "name": "Marco Pivetta", + "email": "ocramius@gmail.com", + "homepage": "http://ocramius.github.com/" + } + ], + "description": "A small, lightweight utility to instantiate objects in PHP without invoking their constructors", + "homepage": "https://github.com/doctrine/instantiator", "keywords": [ - "cors", - "stack" + "constructor", + "instantiate" ] }, { - "name": "symfony/css-selector", - "version": "v3.4.8", - "version_normalized": "3.4.8.0", + "name": "doctrine/lexer", + "version": "v1.0.1", + "version_normalized": "1.0.1.0", "source": { "type": "git", - "url": "https://github.com/symfony/css-selector.git", - "reference": "519a80d7c1d95c6cc0b67f686d15fe27c6910de0" + "url": "https://github.com/doctrine/lexer.git", + "reference": "83893c552fd2045dd78aef794c31e694c37c0b8c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/css-selector/zipball/519a80d7c1d95c6cc0b67f686d15fe27c6910de0", - "reference": "519a80d7c1d95c6cc0b67f686d15fe27c6910de0", + "url": "https://api.github.com/repos/doctrine/lexer/zipball/83893c552fd2045dd78aef794c31e694c37c0b8c", + "reference": "83893c552fd2045dd78aef794c31e694c37c0b8c", "shasum": "" }, "require": { - "php": "^5.5.9|>=7.0.8" - }, - "time": "2018-03-19T22:32:39+00:00", + "php": ">=5.3.2" + }, + "time": "2014-09-09T13:34:57+00:00", "type": "library", "extra": { "branch-alias": { - "dev-master": "3.4-dev" + "dev-master": "1.0.x-dev" } }, "installation-source": "dist", "autoload": { - "psr-4": { - "Symfony\\Component\\CssSelector\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] + "psr-0": { + "Doctrine\\Common\\Lexer\\": "lib/" + } }, "notification-url": "https://packagist.org/downloads/", "license": [ @@ -3555,283 +1072,23 @@ ], "authors": [ { - "name": "Jean-François Simon", - "email": "jeanfrancois.simon@sensiolabs.com" + "name": "Roman Borschel", + "email": "roman@code-factory.org" }, { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" + "name": "Guilherme Blanco", + "email": "guilhermeblanco@gmail.com" }, { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Symfony CssSelector Component", - "homepage": "https://symfony.com" - }, - { - "name": "behat/mink", - "version": "dev-master", - "version_normalized": "9999999-dev", - "source": { - "type": "git", - "url": "https://github.com/minkphp/Mink.git", - "reference": "04ab7af68536ac2c80fd6c08a6fd3620d3409891" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/minkphp/Mink/zipball/04ab7af68536ac2c80fd6c08a6fd3620d3409891", - "reference": "04ab7af68536ac2c80fd6c08a6fd3620d3409891", - "shasum": "" - }, - "require": { - "php": ">=5.3.1", - "symfony/css-selector": "^2.7|^3.0|^4.0" - }, - "require-dev": { - "symfony/phpunit-bridge": "^3.3|^4.0" - }, - "suggest": { - "behat/mink-browserkit-driver": "extremely fast headless driver for Symfony\\Kernel-based apps (Sf2, Silex)", - "behat/mink-goutte-driver": "fast headless driver for any app without JS emulation", - "behat/mink-selenium2-driver": "slow, but JS-enabled driver for any app (requires Selenium2)", - "behat/mink-zombie-driver": "fast and JS-enabled headless driver for any app (requires node.js)" - }, - "time": "2018-01-07T17:25:05+00:00", - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.7.x-dev" - } - }, - "installation-source": "dist", - "autoload": { - "psr-4": { - "Behat\\Mink\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Konstantin Kudryashov", - "email": "ever.zet@gmail.com", - "homepage": "http://everzet.com" - } - ], - "description": "Browser controller/emulator abstraction for PHP", - "homepage": "http://mink.behat.org/", + "name": "Johannes Schmitt", + "email": "schmittjoh@gmail.com" + } + ], + "description": "Base library for a lexer that can be used in Top-Down, Recursive Descent Parsers.", + "homepage": "http://www.doctrine-project.org", "keywords": [ - "browser", - "testing", - "web" - ] - }, - { - "name": "instaclick/php-webdriver", - "version": "1.4.5", - "version_normalized": "1.4.5.0", - "source": { - "type": "git", - "url": "https://github.com/instaclick/php-webdriver.git", - "reference": "6fa959452e774dcaed543faad3a9d1a37d803327" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/instaclick/php-webdriver/zipball/6fa959452e774dcaed543faad3a9d1a37d803327", - "reference": "6fa959452e774dcaed543faad3a9d1a37d803327", - "shasum": "" - }, - "require": { - "ext-curl": "*", - "php": ">=5.3.2" - }, - "require-dev": { - "phpunit/phpunit": "^4.8", - "satooshi/php-coveralls": "^1.0||^2.0" - }, - "time": "2017-06-30T04:02:48+00:00", - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.4.x-dev" - } - }, - "installation-source": "dist", - "autoload": { - "psr-0": { - "WebDriver": "lib/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "Apache-2.0" - ], - "authors": [ - { - "name": "Justin Bishop", - "email": "jubishop@gmail.com", - "role": "Developer" - }, - { - "name": "Anthon Pang", - "email": "apang@softwaredevelopment.ca", - "role": "Fork Maintainer" - } - ], - "description": "PHP WebDriver for Selenium 2", - "homepage": "http://instaclick.com/", - "keywords": [ - "browser", - "selenium", - "webdriver", - "webtest" - ] - }, - { - "name": "behat/mink-selenium2-driver", - "version": "dev-master", - "version_normalized": "9999999-dev", - "source": { - "type": "git", - "url": "https://github.com/minkphp/MinkSelenium2Driver.git", - "reference": "93474c65a2a7bf959200ab5f7a14cc450645c185" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/minkphp/MinkSelenium2Driver/zipball/93474c65a2a7bf959200ab5f7a14cc450645c185", - "reference": "93474c65a2a7bf959200ab5f7a14cc450645c185", - "shasum": "" - }, - "require": { - "behat/mink": "~1.7@dev", - "instaclick/php-webdriver": "~1.1", - "php": ">=5.3.1" - }, - "require-dev": { - "mink/driver-testsuite": "dev-master" - }, - "time": "2018-01-07T19:17:08+00:00", - "type": "mink-driver", - "extra": { - "branch-alias": { - "dev-master": "1.3.x-dev" - } - }, - "installation-source": "dist", - "autoload": { - "psr-4": { - "Behat\\Mink\\Driver\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Konstantin Kudryashov", - "email": "ever.zet@gmail.com", - "homepage": "http://everzet.com" - }, - { - "name": "Pete Otaqui", - "email": "pete@otaqui.com", - "homepage": "https://github.com/pete-otaqui" - } - ], - "description": "Selenium2 (WebDriver) driver for Mink framework", - "homepage": "http://mink.behat.org/", - "keywords": [ - "ajax", - "browser", - "javascript", - "selenium", - "testing", - "webdriver" - ] - }, - { - "name": "squizlabs/php_codesniffer", - "version": "2.9.1", - "version_normalized": "2.9.1.0", - "source": { - "type": "git", - "url": "https://github.com/squizlabs/PHP_CodeSniffer.git", - "reference": "dcbed1074f8244661eecddfc2a675430d8d33f62" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/squizlabs/PHP_CodeSniffer/zipball/dcbed1074f8244661eecddfc2a675430d8d33f62", - "reference": "dcbed1074f8244661eecddfc2a675430d8d33f62", - "shasum": "" - }, - "require": { - "ext-simplexml": "*", - "ext-tokenizer": "*", - "ext-xmlwriter": "*", - "php": ">=5.1.2" - }, - "require-dev": { - "phpunit/phpunit": "~4.0" - }, - "time": "2017-05-22T02:43:20+00:00", - "bin": [ - "scripts/phpcs", - "scripts/phpcbf" - ], - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.x-dev" - } - }, - "installation-source": "dist", - "autoload": { - "classmap": [ - "CodeSniffer.php", - "CodeSniffer/CLI.php", - "CodeSniffer/Exception.php", - "CodeSniffer/File.php", - "CodeSniffer/Fixer.php", - "CodeSniffer/Report.php", - "CodeSniffer/Reporting.php", - "CodeSniffer/Sniff.php", - "CodeSniffer/Tokens.php", - "CodeSniffer/Reports/", - "CodeSniffer/Tokenizers/", - "CodeSniffer/DocGenerators/", - "CodeSniffer/Standards/AbstractPatternSniff.php", - "CodeSniffer/Standards/AbstractScopeSniff.php", - "CodeSniffer/Standards/AbstractVariableSniff.php", - "CodeSniffer/Standards/IncorrectPatternException.php", - "CodeSniffer/Standards/Generic/Sniffs/", - "CodeSniffer/Standards/MySource/Sniffs/", - "CodeSniffer/Standards/PEAR/Sniffs/", - "CodeSniffer/Standards/PSR1/Sniffs/", - "CodeSniffer/Standards/PSR2/Sniffs/", - "CodeSniffer/Standards/Squiz/Sniffs/", - "CodeSniffer/Standards/Zend/Sniffs/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Greg Sherwood", - "role": "lead" - } - ], - "description": "PHP_CodeSniffer tokenizes PHP, JavaScript and CSS files and detects violations of a defined set of coding standards.", - "homepage": "http://www.squizlabs.com/php-codesniffer", - "keywords": [ - "phpcs", - "standards" + "lexer", + "parser" ] }, { @@ -3868,2050 +1125,18 @@ ] }, { - "name": "symfony/dom-crawler", - "version": "v3.4.8", - "version_normalized": "3.4.8.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/dom-crawler.git", - "reference": "1a4cffeb059226ff6bee9f48acb388faf674afff" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/dom-crawler/zipball/1a4cffeb059226ff6bee9f48acb388faf674afff", - "reference": "1a4cffeb059226ff6bee9f48acb388faf674afff", - "shasum": "" - }, - "require": { - "php": "^5.5.9|>=7.0.8", - "symfony/polyfill-mbstring": "~1.0" - }, - "require-dev": { - "symfony/css-selector": "~2.8|~3.0|~4.0" - }, - "suggest": { - "symfony/css-selector": "" - }, - "time": "2018-03-19T22:32:39+00:00", - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "3.4-dev" - } - }, - "installation-source": "dist", - "autoload": { - "psr-4": { - "Symfony\\Component\\DomCrawler\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Symfony DomCrawler Component", - "homepage": "https://symfony.com" - }, - { - "name": "symfony/browser-kit", - "version": "v3.4.8", - "version_normalized": "3.4.8.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/browser-kit.git", - "reference": "840bb6f0d5b3701fd768b68adf7193c2d0f98f79" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/browser-kit/zipball/840bb6f0d5b3701fd768b68adf7193c2d0f98f79", - "reference": "840bb6f0d5b3701fd768b68adf7193c2d0f98f79", - "shasum": "" - }, - "require": { - "php": "^5.5.9|>=7.0.8", - "symfony/dom-crawler": "~2.8|~3.0|~4.0" - }, - "require-dev": { - "symfony/css-selector": "~2.8|~3.0|~4.0", - "symfony/process": "~2.8|~3.0|~4.0" - }, - "suggest": { - "symfony/process": "" - }, - "time": "2018-03-19T22:32:39+00:00", - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "3.4-dev" - } - }, - "installation-source": "dist", - "autoload": { - "psr-4": { - "Symfony\\Component\\BrowserKit\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Symfony BrowserKit Component", - "homepage": "https://symfony.com" - }, - { - "name": "fabpot/goutte", - "version": "v3.2.2", - "version_normalized": "3.2.2.0", - "source": { - "type": "git", - "url": "https://github.com/FriendsOfPHP/Goutte.git", - "reference": "395f61d7c2e15a813839769553a4de16fa3b3c96" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/FriendsOfPHP/Goutte/zipball/395f61d7c2e15a813839769553a4de16fa3b3c96", - "reference": "395f61d7c2e15a813839769553a4de16fa3b3c96", - "shasum": "" - }, - "require": { - "guzzlehttp/guzzle": "^6.0", - "php": ">=5.5.0", - "symfony/browser-kit": "~2.1|~3.0|~4.0", - "symfony/css-selector": "~2.1|~3.0|~4.0", - "symfony/dom-crawler": "~2.1|~3.0|~4.0" - }, - "require-dev": { - "symfony/phpunit-bridge": "^3.3 || ^4" - }, - "time": "2017-11-19T08:45:40+00:00", - "type": "application", - "extra": { - "branch-alias": { - "dev-master": "3.2-dev" - } - }, - "installation-source": "dist", - "autoload": { - "psr-4": { - "Goutte\\": "Goutte" - }, - "exclude-from-classmap": [ - "Goutte/Tests" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - } - ], - "description": "A simple PHP Web Scraper", - "homepage": "https://github.com/FriendsOfPHP/Goutte", - "keywords": [ - "scraper" - ] - }, - { - "name": "behat/mink-browserkit-driver", - "version": "v1.3.2", - "version_normalized": "1.3.2.0", - "source": { - "type": "git", - "url": "https://github.com/minkphp/MinkBrowserKitDriver.git", - "reference": "10e67fb4a295efcd62ea0bf16025a85ea19534fb" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/minkphp/MinkBrowserKitDriver/zipball/10e67fb4a295efcd62ea0bf16025a85ea19534fb", - "reference": "10e67fb4a295efcd62ea0bf16025a85ea19534fb", - "shasum": "" - }, - "require": { - "behat/mink": "^1.7.1@dev", - "php": ">=5.3.6", - "symfony/browser-kit": "~2.3|~3.0", - "symfony/dom-crawler": "~2.3|~3.0" - }, - "require-dev": { - "silex/silex": "~1.2", - "symfony/phpunit-bridge": "~2.7|~3.0" - }, - "time": "2016-03-05T08:59:47+00:00", - "type": "mink-driver", - "extra": { - "branch-alias": { - "dev-master": "1.3.x-dev" - } - }, - "installation-source": "dist", - "autoload": { - "psr-4": { - "Behat\\Mink\\Driver\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Konstantin Kudryashov", - "email": "ever.zet@gmail.com", - "homepage": "http://everzet.com" - } - ], - "description": "Symfony2 BrowserKit driver for Mink framework", - "homepage": "http://mink.behat.org/", - "keywords": [ - "Mink", - "Symfony2", - "browser", - "testing" - ] - }, - { - "name": "behat/mink-goutte-driver", - "version": "v1.2.1", - "version_normalized": "1.2.1.0", - "source": { - "type": "git", - "url": "https://github.com/minkphp/MinkGoutteDriver.git", - "reference": "8b9ad6d2d95bc70b840d15323365f52fcdaea6ca" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/minkphp/MinkGoutteDriver/zipball/8b9ad6d2d95bc70b840d15323365f52fcdaea6ca", - "reference": "8b9ad6d2d95bc70b840d15323365f52fcdaea6ca", - "shasum": "" - }, - "require": { - "behat/mink": "~1.6@dev", - "behat/mink-browserkit-driver": "~1.2@dev", - "fabpot/goutte": "~1.0.4|~2.0|~3.1", - "php": ">=5.3.1" - }, - "require-dev": { - "symfony/phpunit-bridge": "~2.7|~3.0" - }, - "time": "2016-03-05T09:04:22+00:00", - "type": "mink-driver", - "extra": { - "branch-alias": { - "dev-master": "1.2.x-dev" - } - }, - "installation-source": "dist", - "autoload": { - "psr-4": { - "Behat\\Mink\\Driver\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Konstantin Kudryashov", - "email": "ever.zet@gmail.com", - "homepage": "http://everzet.com" - } - ], - "description": "Goutte driver for Mink framework", - "homepage": "http://mink.behat.org/", - "keywords": [ - "browser", - "goutte", - "headless", - "testing" - ] - }, - { - "name": "jcalderonzumba/gastonjs", - "version": "v1.2.0", - "version_normalized": "1.2.0.0", - "source": { - "type": "git", - "url": "https://github.com/jcalderonzumba/gastonjs.git", - "reference": "575a9c18d8b87990c37252e8d9707b29f0a313f3" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/jcalderonzumba/gastonjs/zipball/575a9c18d8b87990c37252e8d9707b29f0a313f3", - "reference": "575a9c18d8b87990c37252e8d9707b29f0a313f3", - "shasum": "" - }, - "require": { - "guzzlehttp/guzzle": "~5.0|~6.0", - "php": ">=5.4" - }, - "require-dev": { - "phpunit/phpunit": "~4.6", - "silex/silex": "~1.2", - "symfony/phpunit-bridge": "~2.7", - "symfony/process": "~2.1" - }, - "time": "2017-03-31T07:31:47+00:00", - "type": "phantomjs-api", - "extra": { - "branch-alias": { - "dev-master": "1.1.x-dev" - } - }, - "installation-source": "dist", - "autoload": { - "psr-4": { - "Zumba\\GastonJS\\": "src" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Juan Francisco Calderón Zumba", - "email": "juanfcz@gmail.com", - "homepage": "http://github.com/jcalderonzumba" - } - ], - "description": "PhantomJS API based server for webpage automation", - "homepage": "https://github.com/jcalderonzumba/gastonjs", - "keywords": [ - "api", - "automation", - "browser", - "headless", - "phantomjs" - ] - }, - { - "name": "jcalderonzumba/mink-phantomjs-driver", - "version": "v0.3.3", - "version_normalized": "0.3.3.0", - "source": { - "type": "git", - "url": "https://github.com/jcalderonzumba/MinkPhantomJSDriver.git", - "reference": "008f43670e94acd39273d15add1e7348eb23848d" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/jcalderonzumba/MinkPhantomJSDriver/zipball/008f43670e94acd39273d15add1e7348eb23848d", - "reference": "008f43670e94acd39273d15add1e7348eb23848d", - "shasum": "" - }, - "require": { - "behat/mink": "~1.7", - "jcalderonzumba/gastonjs": "~1.0", - "php": ">=5.4", - "twig/twig": "~1.20|~2.0" - }, - "require-dev": { - "mink/driver-testsuite": "dev-master", - "phpunit/phpunit": "~4.6" - }, - "time": "2016-12-01T10:57:30+00:00", - "type": "mink-driver", - "extra": { - "branch-alias": { - "dev-master": "0.4.x-dev" - } - }, - "installation-source": "dist", - "autoload": { - "psr-4": { - "Zumba\\Mink\\Driver\\": "src" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Juan Francisco Calderón Zumba", - "email": "juanfcz@gmail.com", - "homepage": "http://github.com/jcalderonzumba" - } - ], - "description": "PhantomJS driver for Mink framework", - "homepage": "http://mink.behat.org/", - "keywords": [ - "ajax", - "browser", - "headless", - "javascript", - "phantomjs", - "testing" - ] - }, - { - "name": "mikey179/vfsStream", - "version": "v1.6.5", - "version_normalized": "1.6.5.0", - "source": { - "type": "git", - "url": "https://github.com/mikey179/vfsStream.git", - "reference": "d5fec95f541d4d71c4823bb5e30cf9b9e5b96145" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/mikey179/vfsStream/zipball/d5fec95f541d4d71c4823bb5e30cf9b9e5b96145", - "reference": "d5fec95f541d4d71c4823bb5e30cf9b9e5b96145", - "shasum": "" - }, - "require": { - "php": ">=5.3.0" - }, - "require-dev": { - "phpunit/phpunit": "~4.5" - }, - "time": "2017-08-01T08:02:14+00:00", - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.6.x-dev" - } - }, - "installation-source": "dist", - "autoload": { - "psr-0": { - "org\\bovigo\\vfs\\": "src/main/php" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Frank Kleine", - "homepage": "http://frankkleine.de/", - "role": "Developer" - } - ], - "description": "Virtual file system to mock the real file system in unit tests.", - "homepage": "http://vfs.bovigo.org/" - }, - { - "name": "sebastian/version", - "version": "2.0.1", - "version_normalized": "2.0.1.0", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/version.git", - "reference": "99732be0ddb3361e16ad77b68ba41efc8e979019" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/version/zipball/99732be0ddb3361e16ad77b68ba41efc8e979019", - "reference": "99732be0ddb3361e16ad77b68ba41efc8e979019", - "shasum": "" - }, - "require": { - "php": ">=5.6" - }, - "time": "2016-10-03T07:35:21+00:00", - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.0.x-dev" - } - }, - "installation-source": "dist", - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" - } - ], - "description": "Library that helps with managing the version number of Git-hosted PHP projects", - "homepage": "https://github.com/sebastianbergmann/version" - }, - { - "name": "sebastian/resource-operations", - "version": "1.0.0", - "version_normalized": "1.0.0.0", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/resource-operations.git", - "reference": "ce990bb21759f94aeafd30209e8cfcdfa8bc3f52" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/resource-operations/zipball/ce990bb21759f94aeafd30209e8cfcdfa8bc3f52", - "reference": "ce990bb21759f94aeafd30209e8cfcdfa8bc3f52", - "shasum": "" - }, - "require": { - "php": ">=5.6.0" - }, - "time": "2015-07-28T20:34:47+00:00", - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.0.x-dev" - } - }, - "installation-source": "dist", - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - } - ], - "description": "Provides a list of PHP built-in functions that operate on resources", - "homepage": "https://www.github.com/sebastianbergmann/resource-operations" - }, - { - "name": "sebastian/object-reflector", - "version": "1.1.1", - "version_normalized": "1.1.1.0", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/object-reflector.git", - "reference": "773f97c67f28de00d397be301821b06708fca0be" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/object-reflector/zipball/773f97c67f28de00d397be301821b06708fca0be", - "reference": "773f97c67f28de00d397be301821b06708fca0be", - "shasum": "" - }, - "require": { - "php": "^7.0" - }, - "require-dev": { - "phpunit/phpunit": "^6.0" - }, - "time": "2017-03-29T09:07:27+00:00", - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.1-dev" - } - }, - "installation-source": "dist", - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - } - ], - "description": "Allows reflection of object attributes, including inherited and non-public ones", - "homepage": "https://github.com/sebastianbergmann/object-reflector/" - }, - { - "name": "sebastian/recursion-context", - "version": "3.0.0", - "version_normalized": "3.0.0.0", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/recursion-context.git", - "reference": "5b0cd723502bac3b006cbf3dbf7a1e3fcefe4fa8" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/5b0cd723502bac3b006cbf3dbf7a1e3fcefe4fa8", - "reference": "5b0cd723502bac3b006cbf3dbf7a1e3fcefe4fa8", - "shasum": "" - }, - "require": { - "php": "^7.0" - }, - "require-dev": { - "phpunit/phpunit": "^6.0" - }, - "time": "2017-03-03T06:23:57+00:00", - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "3.0.x-dev" - } - }, - "installation-source": "dist", - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Jeff Welch", - "email": "whatthejeff@gmail.com" - }, - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - }, - { - "name": "Adam Harvey", - "email": "aharvey@php.net" - } - ], - "description": "Provides functionality to recursively process PHP variables", - "homepage": "http://www.github.com/sebastianbergmann/recursion-context" - }, - { - "name": "sebastian/object-enumerator", - "version": "3.0.3", - "version_normalized": "3.0.3.0", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/object-enumerator.git", - "reference": "7cfd9e65d11ffb5af41198476395774d4c8a84c5" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/object-enumerator/zipball/7cfd9e65d11ffb5af41198476395774d4c8a84c5", - "reference": "7cfd9e65d11ffb5af41198476395774d4c8a84c5", - "shasum": "" - }, - "require": { - "php": "^7.0", - "sebastian/object-reflector": "^1.1.1", - "sebastian/recursion-context": "^3.0" - }, - "require-dev": { - "phpunit/phpunit": "^6.0" - }, - "time": "2017-08-03T12:35:26+00:00", - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "3.0.x-dev" - } - }, - "installation-source": "dist", - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - } - ], - "description": "Traverses array structures and object graphs to enumerate all referenced objects", - "homepage": "https://github.com/sebastianbergmann/object-enumerator/" - }, - { - "name": "sebastian/global-state", - "version": "2.0.0", - "version_normalized": "2.0.0.0", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/global-state.git", - "reference": "e8ba02eed7bbbb9e59e43dedd3dddeff4a56b0c4" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/e8ba02eed7bbbb9e59e43dedd3dddeff4a56b0c4", - "reference": "e8ba02eed7bbbb9e59e43dedd3dddeff4a56b0c4", - "shasum": "" - }, - "require": { - "php": "^7.0" - }, - "require-dev": { - "phpunit/phpunit": "^6.0" - }, - "suggest": { - "ext-uopz": "*" - }, - "time": "2017-04-27T15:39:26+00:00", - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.0-dev" - } - }, - "installation-source": "dist", - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - } - ], - "description": "Snapshotting of global state", - "homepage": "http://www.github.com/sebastianbergmann/global-state", - "keywords": [ - "global state" - ] - }, - { - "name": "sebastian/exporter", - "version": "3.1.0", - "version_normalized": "3.1.0.0", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/exporter.git", - "reference": "234199f4528de6d12aaa58b612e98f7d36adb937" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/234199f4528de6d12aaa58b612e98f7d36adb937", - "reference": "234199f4528de6d12aaa58b612e98f7d36adb937", - "shasum": "" - }, - "require": { - "php": "^7.0", - "sebastian/recursion-context": "^3.0" - }, - "require-dev": { - "ext-mbstring": "*", - "phpunit/phpunit": "^6.0" - }, - "time": "2017-04-03T13:19:02+00:00", - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "3.1.x-dev" - } - }, - "installation-source": "dist", - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Jeff Welch", - "email": "whatthejeff@gmail.com" - }, - { - "name": "Volker Dusch", - "email": "github@wallbash.com" - }, - { - "name": "Bernhard Schussek", - "email": "bschussek@2bepublished.at" - }, - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - }, - { - "name": "Adam Harvey", - "email": "aharvey@php.net" - } - ], - "description": "Provides the functionality to export PHP variables for visualization", - "homepage": "http://www.github.com/sebastianbergmann/exporter", - "keywords": [ - "export", - "exporter" - ] - }, - { - "name": "sebastian/environment", - "version": "3.1.0", - "version_normalized": "3.1.0.0", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/environment.git", - "reference": "cd0871b3975fb7fc44d11314fd1ee20925fce4f5" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/cd0871b3975fb7fc44d11314fd1ee20925fce4f5", - "reference": "cd0871b3975fb7fc44d11314fd1ee20925fce4f5", - "shasum": "" - }, - "require": { - "php": "^7.0" - }, - "require-dev": { - "phpunit/phpunit": "^6.1" - }, - "time": "2017-07-01T08:51:00+00:00", - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "3.1.x-dev" - } - }, - "installation-source": "dist", - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - } - ], - "description": "Provides functionality to handle HHVM/PHP environments", - "homepage": "http://www.github.com/sebastianbergmann/environment", - "keywords": [ - "Xdebug", - "environment", - "hhvm" - ] - }, - { - "name": "sebastian/diff", - "version": "2.0.1", - "version_normalized": "2.0.1.0", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/diff.git", - "reference": "347c1d8b49c5c3ee30c7040ea6fc446790e6bddd" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/347c1d8b49c5c3ee30c7040ea6fc446790e6bddd", - "reference": "347c1d8b49c5c3ee30c7040ea6fc446790e6bddd", - "shasum": "" - }, - "require": { - "php": "^7.0" - }, - "require-dev": { - "phpunit/phpunit": "^6.2" - }, - "time": "2017-08-03T08:09:46+00:00", - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.0-dev" - } - }, - "installation-source": "dist", - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Kore Nordmann", - "email": "mail@kore-nordmann.de" - }, - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - } - ], - "description": "Diff implementation", - "homepage": "https://github.com/sebastianbergmann/diff", - "keywords": [ - "diff" - ] - }, - { - "name": "sebastian/comparator", - "version": "2.1.3", - "version_normalized": "2.1.3.0", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/comparator.git", - "reference": "34369daee48eafb2651bea869b4b15d75ccc35f9" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/34369daee48eafb2651bea869b4b15d75ccc35f9", - "reference": "34369daee48eafb2651bea869b4b15d75ccc35f9", - "shasum": "" - }, - "require": { - "php": "^7.0", - "sebastian/diff": "^2.0 || ^3.0", - "sebastian/exporter": "^3.1" - }, - "require-dev": { - "phpunit/phpunit": "^6.4" - }, - "time": "2018-02-01T13:46:46+00:00", - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.1.x-dev" - } - }, - "installation-source": "dist", - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Jeff Welch", - "email": "whatthejeff@gmail.com" - }, - { - "name": "Volker Dusch", - "email": "github@wallbash.com" - }, - { - "name": "Bernhard Schussek", - "email": "bschussek@2bepublished.at" - }, - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - } - ], - "description": "Provides the functionality to compare PHP values for equality", - "homepage": "https://github.com/sebastianbergmann/comparator", - "keywords": [ - "comparator", - "compare", - "equality" - ] - }, - { - "name": "doctrine/instantiator", - "version": "1.0.5", - "version_normalized": "1.0.5.0", - "source": { - "type": "git", - "url": "https://github.com/doctrine/instantiator.git", - "reference": "8e884e78f9f0eb1329e445619e04456e64d8051d" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/doctrine/instantiator/zipball/8e884e78f9f0eb1329e445619e04456e64d8051d", - "reference": "8e884e78f9f0eb1329e445619e04456e64d8051d", - "shasum": "" - }, - "require": { - "php": ">=5.3,<8.0-DEV" - }, - "require-dev": { - "athletic/athletic": "~0.1.8", - "ext-pdo": "*", - "ext-phar": "*", - "phpunit/phpunit": "~4.0", - "squizlabs/php_codesniffer": "~2.0" - }, - "time": "2015-06-14T21:17:01+00:00", - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.0.x-dev" - } - }, - "installation-source": "dist", - "autoload": { - "psr-4": { - "Doctrine\\Instantiator\\": "src/Doctrine/Instantiator/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Marco Pivetta", - "email": "ocramius@gmail.com", - "homepage": "http://ocramius.github.com/" - } - ], - "description": "A small, lightweight utility to instantiate objects in PHP without invoking their constructors", - "homepage": "https://github.com/doctrine/instantiator", - "keywords": [ - "constructor", - "instantiate" - ] - }, - { - "name": "phpunit/php-text-template", - "version": "1.2.1", - "version_normalized": "1.2.1.0", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/php-text-template.git", - "reference": "31f8b717e51d9a2afca6c9f046f5d69fc27c8686" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/31f8b717e51d9a2afca6c9f046f5d69fc27c8686", - "reference": "31f8b717e51d9a2afca6c9f046f5d69fc27c8686", - "shasum": "" - }, - "require": { - "php": ">=5.3.3" - }, - "time": "2015-06-21T13:50:34+00:00", - "type": "library", - "installation-source": "dist", - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" - } - ], - "description": "Simple template engine.", - "homepage": "https://github.com/sebastianbergmann/php-text-template/", - "keywords": [ - "template" - ] - }, - { - "name": "phpunit/phpunit-mock-objects", - "version": "5.0.6", - "version_normalized": "5.0.6.0", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/phpunit-mock-objects.git", - "reference": "33fd41a76e746b8fa96d00b49a23dadfa8334cdf" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit-mock-objects/zipball/33fd41a76e746b8fa96d00b49a23dadfa8334cdf", - "reference": "33fd41a76e746b8fa96d00b49a23dadfa8334cdf", - "shasum": "" - }, - "require": { - "doctrine/instantiator": "^1.0.5", - "php": "^7.0", - "phpunit/php-text-template": "^1.2.1", - "sebastian/exporter": "^3.1" - }, - "conflict": { - "phpunit/phpunit": "<6.0" - }, - "require-dev": { - "phpunit/phpunit": "^6.5" - }, - "suggest": { - "ext-soap": "*" - }, - "time": "2018-01-06T05:45:45+00:00", - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "5.0.x-dev" - } - }, - "installation-source": "dist", - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" - } - ], - "description": "Mock Object library for PHPUnit", - "homepage": "https://github.com/sebastianbergmann/phpunit-mock-objects/", - "keywords": [ - "mock", - "xunit" - ] - }, - { - "name": "phpunit/php-timer", - "version": "1.0.9", - "version_normalized": "1.0.9.0", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/php-timer.git", - "reference": "3dcf38ca72b158baf0bc245e9184d3fdffa9c46f" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/3dcf38ca72b158baf0bc245e9184d3fdffa9c46f", - "reference": "3dcf38ca72b158baf0bc245e9184d3fdffa9c46f", - "shasum": "" - }, - "require": { - "php": "^5.3.3 || ^7.0" - }, - "require-dev": { - "phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.0" - }, - "time": "2017-02-26T11:10:40+00:00", - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.0-dev" - } - }, - "installation-source": "dist", - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sb@sebastian-bergmann.de", - "role": "lead" - } - ], - "description": "Utility class for timing", - "homepage": "https://github.com/sebastianbergmann/php-timer/", - "keywords": [ - "timer" - ] - }, - { - "name": "phpunit/php-file-iterator", - "version": "1.4.5", - "version_normalized": "1.4.5.0", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/php-file-iterator.git", - "reference": "730b01bc3e867237eaac355e06a36b85dd93a8b4" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/730b01bc3e867237eaac355e06a36b85dd93a8b4", - "reference": "730b01bc3e867237eaac355e06a36b85dd93a8b4", - "shasum": "" - }, - "require": { - "php": ">=5.3.3" - }, - "time": "2017-11-27T13:52:08+00:00", - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.4.x-dev" - } - }, - "installation-source": "dist", - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sb@sebastian-bergmann.de", - "role": "lead" - } - ], - "description": "FilterIterator implementation that filters files based on a list of suffixes.", - "homepage": "https://github.com/sebastianbergmann/php-file-iterator/", - "keywords": [ - "filesystem", - "iterator" - ] - }, - { - "name": "theseer/tokenizer", - "version": "1.1.0", - "version_normalized": "1.1.0.0", - "source": { - "type": "git", - "url": "https://github.com/theseer/tokenizer.git", - "reference": "cb2f008f3f05af2893a87208fe6a6c4985483f8b" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/theseer/tokenizer/zipball/cb2f008f3f05af2893a87208fe6a6c4985483f8b", - "reference": "cb2f008f3f05af2893a87208fe6a6c4985483f8b", - "shasum": "" - }, - "require": { - "ext-dom": "*", - "ext-tokenizer": "*", - "ext-xmlwriter": "*", - "php": "^7.0" - }, - "time": "2017-04-07T12:08:54+00:00", - "type": "library", - "installation-source": "dist", - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Arne Blankerts", - "email": "arne@blankerts.de", - "role": "Developer" - } - ], - "description": "A small library for converting tokenized PHP source code into XML and potentially other formats" - }, - { - "name": "sebastian/code-unit-reverse-lookup", - "version": "1.0.1", - "version_normalized": "1.0.1.0", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/code-unit-reverse-lookup.git", - "reference": "4419fcdb5eabb9caa61a27c7a1db532a6b55dd18" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/code-unit-reverse-lookup/zipball/4419fcdb5eabb9caa61a27c7a1db532a6b55dd18", - "reference": "4419fcdb5eabb9caa61a27c7a1db532a6b55dd18", - "shasum": "" - }, - "require": { - "php": "^5.6 || ^7.0" - }, - "require-dev": { - "phpunit/phpunit": "^5.7 || ^6.0" - }, - "time": "2017-03-04T06:30:41+00:00", - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.0.x-dev" - } - }, - "installation-source": "dist", - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - } - ], - "description": "Looks up which function or method a line of code belongs to", - "homepage": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/" - }, - { - "name": "phpunit/php-token-stream", - "version": "2.0.2", - "version_normalized": "2.0.2.0", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/php-token-stream.git", - "reference": "791198a2c6254db10131eecfe8c06670700904db" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-token-stream/zipball/791198a2c6254db10131eecfe8c06670700904db", - "reference": "791198a2c6254db10131eecfe8c06670700904db", - "shasum": "" - }, - "require": { - "ext-tokenizer": "*", - "php": "^7.0" - }, - "require-dev": { - "phpunit/phpunit": "^6.2.4" - }, - "time": "2017-11-27T05:48:46+00:00", - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.0-dev" - } - }, - "installation-source": "dist", - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - } - ], - "description": "Wrapper around PHP's tokenizer extension.", - "homepage": "https://github.com/sebastianbergmann/php-token-stream/", - "keywords": [ - "tokenizer" - ] - }, - { - "name": "phpunit/php-code-coverage", - "version": "5.3.2", - "version_normalized": "5.3.2.0", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/php-code-coverage.git", - "reference": "c89677919c5dd6d3b3852f230a663118762218ac" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/c89677919c5dd6d3b3852f230a663118762218ac", - "reference": "c89677919c5dd6d3b3852f230a663118762218ac", - "shasum": "" - }, - "require": { - "ext-dom": "*", - "ext-xmlwriter": "*", - "php": "^7.0", - "phpunit/php-file-iterator": "^1.4.2", - "phpunit/php-text-template": "^1.2.1", - "phpunit/php-token-stream": "^2.0.1", - "sebastian/code-unit-reverse-lookup": "^1.0.1", - "sebastian/environment": "^3.0", - "sebastian/version": "^2.0.1", - "theseer/tokenizer": "^1.1" - }, - "require-dev": { - "phpunit/phpunit": "^6.0" - }, - "suggest": { - "ext-xdebug": "^2.5.5" - }, - "time": "2018-04-06T15:36:58+00:00", - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "5.3.x-dev" - } - }, - "installation-source": "dist", - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" - } - ], - "description": "Library that provides collection, processing, and rendering functionality for PHP code coverage information.", - "homepage": "https://github.com/sebastianbergmann/php-code-coverage", - "keywords": [ - "coverage", - "testing", - "xunit" - ] - }, - { - "name": "phpdocumentor/reflection-common", - "version": "1.0.1", - "version_normalized": "1.0.1.0", - "source": { - "type": "git", - "url": "https://github.com/phpDocumentor/ReflectionCommon.git", - "reference": "21bdeb5f65d7ebf9f43b1b25d404f87deab5bfb6" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/phpDocumentor/ReflectionCommon/zipball/21bdeb5f65d7ebf9f43b1b25d404f87deab5bfb6", - "reference": "21bdeb5f65d7ebf9f43b1b25d404f87deab5bfb6", - "shasum": "" - }, - "require": { - "php": ">=5.5" - }, - "require-dev": { - "phpunit/phpunit": "^4.6" - }, - "time": "2017-09-11T18:02:19+00:00", - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.0.x-dev" - } - }, - "installation-source": "dist", - "autoload": { - "psr-4": { - "phpDocumentor\\Reflection\\": [ - "src" - ] - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Jaap van Otterdijk", - "email": "opensource@ijaap.nl" - } - ], - "description": "Common reflection classes used by phpdocumentor to reflect the code structure", - "homepage": "http://www.phpdoc.org", - "keywords": [ - "FQSEN", - "phpDocumentor", - "phpdoc", - "reflection", - "static analysis" - ] - }, - { - "name": "phpdocumentor/type-resolver", - "version": "0.4.0", - "version_normalized": "0.4.0.0", - "source": { - "type": "git", - "url": "https://github.com/phpDocumentor/TypeResolver.git", - "reference": "9c977708995954784726e25d0cd1dddf4e65b0f7" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/phpDocumentor/TypeResolver/zipball/9c977708995954784726e25d0cd1dddf4e65b0f7", - "reference": "9c977708995954784726e25d0cd1dddf4e65b0f7", - "shasum": "" - }, - "require": { - "php": "^5.5 || ^7.0", - "phpdocumentor/reflection-common": "^1.0" - }, - "require-dev": { - "mockery/mockery": "^0.9.4", - "phpunit/phpunit": "^5.2||^4.8.24" - }, - "time": "2017-07-14T14:27:02+00:00", - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.0.x-dev" - } - }, - "installation-source": "dist", - "autoload": { - "psr-4": { - "phpDocumentor\\Reflection\\": [ - "src/" - ] - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Mike van Riel", - "email": "me@mikevanriel.com" - } - ] - }, - { - "name": "phpdocumentor/reflection-docblock", - "version": "4.3.0", - "version_normalized": "4.3.0.0", - "source": { - "type": "git", - "url": "https://github.com/phpDocumentor/ReflectionDocBlock.git", - "reference": "94fd0001232e47129dd3504189fa1c7225010d08" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/94fd0001232e47129dd3504189fa1c7225010d08", - "reference": "94fd0001232e47129dd3504189fa1c7225010d08", - "shasum": "" - }, - "require": { - "php": "^7.0", - "phpdocumentor/reflection-common": "^1.0.0", - "phpdocumentor/type-resolver": "^0.4.0", - "webmozart/assert": "^1.0" - }, - "require-dev": { - "doctrine/instantiator": "~1.0.5", - "mockery/mockery": "^1.0", - "phpunit/phpunit": "^6.4" - }, - "time": "2017-11-30T07:14:17+00:00", - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "4.x-dev" - } - }, - "installation-source": "dist", - "autoload": { - "psr-4": { - "phpDocumentor\\Reflection\\": [ - "src/" - ] - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Mike van Riel", - "email": "me@mikevanriel.com" - } - ], - "description": "With this component, a library can provide support for annotations via DocBlocks or otherwise retrieve information that is embedded in a DocBlock." - }, - { - "name": "phpspec/prophecy", - "version": "1.7.6", - "version_normalized": "1.7.6.0", - "source": { - "type": "git", - "url": "https://github.com/phpspec/prophecy.git", - "reference": "33a7e3c4fda54e912ff6338c48823bd5c0f0b712" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/phpspec/prophecy/zipball/33a7e3c4fda54e912ff6338c48823bd5c0f0b712", - "reference": "33a7e3c4fda54e912ff6338c48823bd5c0f0b712", - "shasum": "" - }, - "require": { - "doctrine/instantiator": "^1.0.2", - "php": "^5.3|^7.0", - "phpdocumentor/reflection-docblock": "^2.0|^3.0.2|^4.0", - "sebastian/comparator": "^1.1|^2.0|^3.0", - "sebastian/recursion-context": "^1.0|^2.0|^3.0" - }, - "require-dev": { - "phpspec/phpspec": "^2.5|^3.2", - "phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.5" - }, - "time": "2018-04-18T13:57:24+00:00", - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.7.x-dev" - } - }, - "installation-source": "dist", - "autoload": { - "psr-0": { - "Prophecy\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Konstantin Kudryashov", - "email": "ever.zet@gmail.com", - "homepage": "http://everzet.com" - }, - { - "name": "Marcello Duarte", - "email": "marcello.duarte@gmail.com" - } - ], - "description": "Highly opinionated mocking framework for PHP 5.3+", - "homepage": "https://github.com/phpspec/prophecy", - "keywords": [ - "Double", - "Dummy", - "fake", - "mock", - "spy", - "stub" - ] - }, - { - "name": "phar-io/version", - "version": "1.0.1", - "version_normalized": "1.0.1.0", - "source": { - "type": "git", - "url": "https://github.com/phar-io/version.git", - "reference": "a70c0ced4be299a63d32fa96d9281d03e94041df" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/phar-io/version/zipball/a70c0ced4be299a63d32fa96d9281d03e94041df", - "reference": "a70c0ced4be299a63d32fa96d9281d03e94041df", - "shasum": "" - }, - "require": { - "php": "^5.6 || ^7.0" - }, - "time": "2017-03-05T17:38:23+00:00", - "type": "library", - "installation-source": "dist", - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Arne Blankerts", - "email": "arne@blankerts.de", - "role": "Developer" - }, - { - "name": "Sebastian Heuer", - "email": "sebastian@phpeople.de", - "role": "Developer" - }, - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "Developer" - } - ], - "description": "Library for handling version information and constraints" - }, - { - "name": "phar-io/manifest", - "version": "1.0.1", - "version_normalized": "1.0.1.0", - "source": { - "type": "git", - "url": "https://github.com/phar-io/manifest.git", - "reference": "2df402786ab5368a0169091f61a7c1e0eb6852d0" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/phar-io/manifest/zipball/2df402786ab5368a0169091f61a7c1e0eb6852d0", - "reference": "2df402786ab5368a0169091f61a7c1e0eb6852d0", - "shasum": "" - }, - "require": { - "ext-dom": "*", - "ext-phar": "*", - "phar-io/version": "^1.0.1", - "php": "^5.6 || ^7.0" - }, - "time": "2017-03-05T18:14:27+00:00", - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.0.x-dev" - } - }, - "installation-source": "dist", - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Arne Blankerts", - "email": "arne@blankerts.de", - "role": "Developer" - }, - { - "name": "Sebastian Heuer", - "email": "sebastian@phpeople.de", - "role": "Developer" - }, - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "Developer" - } - ], - "description": "Component for reading phar.io manifest information from a PHP Archive (PHAR)" - }, - { - "name": "myclabs/deep-copy", - "version": "1.7.0", - "version_normalized": "1.7.0.0", - "source": { - "type": "git", - "url": "https://github.com/myclabs/DeepCopy.git", - "reference": "3b8a3a99ba1f6a3952ac2747d989303cbd6b7a3e" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/3b8a3a99ba1f6a3952ac2747d989303cbd6b7a3e", - "reference": "3b8a3a99ba1f6a3952ac2747d989303cbd6b7a3e", - "shasum": "" - }, - "require": { - "php": "^5.6 || ^7.0" - }, - "require-dev": { - "doctrine/collections": "^1.0", - "doctrine/common": "^2.6", - "phpunit/phpunit": "^4.1" - }, - "time": "2017-10-19T19:58:43+00:00", - "type": "library", - "installation-source": "dist", - "autoload": { - "psr-4": { - "DeepCopy\\": "src/DeepCopy/" - }, - "files": [ - "src/DeepCopy/deep_copy.php" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "description": "Create deep copies (clones) of your objects", - "keywords": [ - "clone", - "copy", - "duplicate", - "object", - "object graph" - ] - }, - { - "name": "phpunit/phpunit", - "version": "6.5.8", - "version_normalized": "6.5.8.0", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/phpunit.git", - "reference": "4f21a3c6b97c42952fd5c2837bb354ec0199b97b" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/4f21a3c6b97c42952fd5c2837bb354ec0199b97b", - "reference": "4f21a3c6b97c42952fd5c2837bb354ec0199b97b", - "shasum": "" - }, - "require": { - "ext-dom": "*", - "ext-json": "*", - "ext-libxml": "*", - "ext-mbstring": "*", - "ext-xml": "*", - "myclabs/deep-copy": "^1.6.1", - "phar-io/manifest": "^1.0.1", - "phar-io/version": "^1.0", - "php": "^7.0", - "phpspec/prophecy": "^1.7", - "phpunit/php-code-coverage": "^5.3", - "phpunit/php-file-iterator": "^1.4.3", - "phpunit/php-text-template": "^1.2.1", - "phpunit/php-timer": "^1.0.9", - "phpunit/phpunit-mock-objects": "^5.0.5", - "sebastian/comparator": "^2.1", - "sebastian/diff": "^2.0", - "sebastian/environment": "^3.1", - "sebastian/exporter": "^3.1", - "sebastian/global-state": "^2.0", - "sebastian/object-enumerator": "^3.0.3", - "sebastian/resource-operations": "^1.0", - "sebastian/version": "^2.0.1" - }, - "conflict": { - "phpdocumentor/reflection-docblock": "3.0.2", - "phpunit/dbunit": "<3.0" - }, - "require-dev": { - "ext-pdo": "*" - }, - "suggest": { - "ext-xdebug": "*", - "phpunit/php-invoker": "^1.1" - }, - "time": "2018-04-10T11:38:34+00:00", - "bin": [ - "phpunit" - ], - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "6.5.x-dev" - } - }, - "installation-source": "dist", - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" - } - ], - "description": "The PHP Unit Testing framework.", - "homepage": "https://phpunit.de/", - "keywords": [ - "phpunit", - "testing", - "xunit" - ] - }, - { - "name": "symfony/phpunit-bridge", - "version": "v3.4.8", - "version_normalized": "3.4.8.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/phpunit-bridge.git", - "reference": "48c669ec1a2b0425d4a82c7ad4bce2f5b947b95e" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/phpunit-bridge/zipball/48c669ec1a2b0425d4a82c7ad4bce2f5b947b95e", - "reference": "48c669ec1a2b0425d4a82c7ad4bce2f5b947b95e", - "shasum": "" - }, - "require": { - "php": ">=5.3.3" - }, - "conflict": { - "phpunit/phpunit": "<4.8.35|<5.4.3,>=5.0" - }, - "suggest": { - "ext-zip": "Zip support is required when using bin/simple-phpunit", - "symfony/debug": "For tracking deprecated interfaces usages at runtime with DebugClassLoader" - }, - "time": "2018-04-04T15:02:59+00:00", - "bin": [ - "bin/simple-phpunit" - ], - "type": "symfony-bridge", - "extra": { - "branch-alias": { - "dev-master": "3.4-dev" - }, - "thanks": { - "name": "phpunit/phpunit", - "url": "https://github.com/sebastianbergmann/phpunit" - } - }, - "installation-source": "dist", - "autoload": { - "files": [ - "bootstrap.php" - ], - "psr-4": { - "Symfony\\Bridge\\PhpUnit\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Symfony PHPUnit Bridge", - "homepage": "https://symfony.com" - }, - { - "name": "zendframework/zend-escaper", - "version": "2.6.0", - "version_normalized": "2.6.0.0", - "source": { - "type": "git", - "url": "https://github.com/zendframework/zend-escaper.git", - "reference": "31d8aafae982f9568287cb4dce987e6aff8fd074" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/zendframework/zend-escaper/zipball/31d8aafae982f9568287cb4dce987e6aff8fd074", - "reference": "31d8aafae982f9568287cb4dce987e6aff8fd074", - "shasum": "" - }, - "require": { - "php": "^5.6 || ^7.0" - }, - "require-dev": { - "phpunit/phpunit": "^5.7.27 || ^6.5.8 || ^7.1.2", - "zendframework/zend-coding-standard": "~1.0.0" - }, - "time": "2018-04-25T15:48:53+00:00", - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.6.x-dev", - "dev-develop": "2.7.x-dev" - } - }, - "installation-source": "dist", - "autoload": { - "psr-4": { - "Zend\\Escaper\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "description": "Securely and safely escape HTML, HTML attributes, JavaScript, CSS, and URLs", - "keywords": [ - "ZendFramework", - "escaper", - "zf" - ] - }, - { "name": "drupal/core", - "version": "8.5.3", - "version_normalized": "8.5.3.0", + "version": "8.5.5", + "version_normalized": "8.5.5.0", "source": { "type": "git", "url": "https://github.com/drupal/core.git", - "reference": "b012f0ae51504880e920f2c6efdbdf03b6fe2129" + "reference": "900c28f19d4b5643f43c1cf046684046402eaac4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/drupal/core/zipball/b012f0ae51504880e920f2c6efdbdf03b6fe2129", - "reference": "b012f0ae51504880e920f2c6efdbdf03b6fe2129", + "url": "https://api.github.com/repos/drupal/core/zipball/900c28f19d4b5643f43c1cf046684046402eaac4", + "reference": "900c28f19d4b5643f43c1cf046684046402eaac4", "shasum": "" }, "require": { @@ -6080,7 +1305,7 @@ "symfony/debug": "^3.4.0", "symfony/phpunit-bridge": "^3.4.3" }, - "time": "2018-04-25T15:39:01+00:00", + "time": "2018-07-04T21:08:11+00:00", "type": "drupal-core", "extra": { "merge-plugin": { @@ -6135,5 +1360,4855 @@ "GPL-2.0-or-later" ], "description": "Drupal is an open source content management platform powering millions of websites and applications." + }, + { + "name": "drush/drush", + "version": "8.1.17", + "version_normalized": "8.1.17.0", + "source": { + "type": "git", + "url": "https://github.com/drush-ops/drush.git", + "reference": "7ea681dc7e639f6ddab906e78611d3558f88d9b0" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/drush-ops/drush/zipball/7ea681dc7e639f6ddab906e78611d3558f88d9b0", + "reference": "7ea681dc7e639f6ddab906e78611d3558f88d9b0", + "shasum": "" + }, + "require": { + "consolidation/annotated-command": "^2.8.1", + "consolidation/output-formatters": "~3", + "pear/console_table": "~1.3.1", + "php": ">=5.4.5", + "psr/log": "~1.0", + "psy/psysh": "~0.6", + "symfony/console": "~2.7|^3", + "symfony/event-dispatcher": "~2.7|^3", + "symfony/finder": "~2.7|^3", + "symfony/var-dumper": "~2.7|^3", + "symfony/yaml": "~2.3|^3", + "webmozart/path-util": "~2" + }, + "require-dev": { + "phpunit/phpunit": "4.*", + "symfony/console": "~2.7", + "symfony/event-dispatcher": "~2.7", + "symfony/finder": "~2.7", + "symfony/process": "2.7.*", + "symfony/var-dumper": "~2.7", + "symfony/yaml": "~2.3" + }, + "suggest": { + "drush/config-extra": "Provides configuration workflow commands, such as config-merge.", + "ext-pcntl": "*" + }, + "time": "2018-05-23T16:58:54+00:00", + "bin": [ + "drush", + "drush.launcher", + "drush.php", + "drush.complete.sh" + ], + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "8.0.x-dev" + } + }, + "installation-source": "dist", + "autoload": { + "psr-0": { + "Drush": "lib/", + "Consolidation": "lib/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "GPL-2.0-or-later" + ], + "authors": [ + { + "name": "Moshe Weitzman", + "email": "weitzman@tejasa.com" + }, + { + "name": "Owen Barton", + "email": "drupal@owenbarton.com" + }, + { + "name": "Mark Sonnabaum", + "email": "marksonnabaum@gmail.com" + }, + { + "name": "Antoine Beaupré", + "email": "anarcat@koumbit.org" + }, + { + "name": "Greg Anderson", + "email": "greg.1.anderson@greenknowe.org" + }, + { + "name": "Jonathan Araña Cruz", + "email": "jonhattan@faita.net" + }, + { + "name": "Jonathan Hedstrom", + "email": "jhedstrom@gmail.com" + }, + { + "name": "Christopher Gervais", + "email": "chris@ergonlogic.com" + }, + { + "name": "Dave Reid", + "email": "dave@davereid.net" + }, + { + "name": "Damian Lee", + "email": "damiankloip@googlemail.com" + } + ], + "description": "Drush is a command line shell and scripting interface for Drupal, a veritable Swiss Army knife designed to make life easier for those of us who spend some of our working hours hacking away at the command prompt.", + "homepage": "http://www.drush.org" + }, + { + "name": "easyrdf/easyrdf", + "version": "0.9.1", + "version_normalized": "0.9.1.0", + "source": { + "type": "git", + "url": "https://github.com/njh/easyrdf.git", + "reference": "acd09dfe0555fbcfa254291e433c45fdd4652566" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/njh/easyrdf/zipball/acd09dfe0555fbcfa254291e433c45fdd4652566", + "reference": "acd09dfe0555fbcfa254291e433c45fdd4652566", + "shasum": "" + }, + "require": { + "ext-mbstring": "*", + "ext-pcre": "*", + "php": ">=5.2.8" + }, + "require-dev": { + "phpunit/phpunit": "~3.5", + "sami/sami": "~1.4", + "squizlabs/php_codesniffer": "~1.4.3" + }, + "suggest": { + "ml/json-ld": "~1.0" + }, + "time": "2015-02-27T09:45:49+00:00", + "type": "library", + "installation-source": "dist", + "autoload": { + "psr-0": { + "EasyRdf_": "lib/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Nicholas Humfrey", + "email": "njh@aelius.com", + "homepage": "http://www.aelius.com/njh/", + "role": "Developer" + }, + { + "name": "Alexey Zakhlestin", + "email": "indeyets@gmail.com", + "role": "Developer" + } + ], + "description": "EasyRdf is a PHP library designed to make it easy to consume and produce RDF.", + "homepage": "http://www.easyrdf.org/", + "keywords": [ + "Linked Data", + "RDF", + "Semantic Web", + "Turtle", + "rdfa", + "sparql" + ] + }, + { + "name": "egulias/email-validator", + "version": "1.2.14", + "version_normalized": "1.2.14.0", + "source": { + "type": "git", + "url": "https://github.com/egulias/EmailValidator.git", + "reference": "5642614492f0ca2064c01d60cc33284cc2f731a9" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/egulias/EmailValidator/zipball/5642614492f0ca2064c01d60cc33284cc2f731a9", + "reference": "5642614492f0ca2064c01d60cc33284cc2f731a9", + "shasum": "" + }, + "require": { + "doctrine/lexer": "^1.0.1", + "php": ">= 5.3.3" + }, + "require-dev": { + "phpunit/phpunit": "^4.8.24" + }, + "time": "2017-02-03T22:48:59+00:00", + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0.x-dev" + } + }, + "installation-source": "dist", + "autoload": { + "psr-0": { + "Egulias\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Eduardo Gulias Davis" + } + ], + "description": "A library for validating emails", + "homepage": "https://github.com/egulias/EmailValidator", + "keywords": [ + "email", + "emailvalidation", + "emailvalidator", + "validation", + "validator" + ] + }, + { + "name": "fabpot/goutte", + "version": "v3.2.3", + "version_normalized": "3.2.3.0", + "source": { + "type": "git", + "url": "https://github.com/FriendsOfPHP/Goutte.git", + "reference": "3f0eaf0a40181359470651f1565b3e07e3dd31b8" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/FriendsOfPHP/Goutte/zipball/3f0eaf0a40181359470651f1565b3e07e3dd31b8", + "reference": "3f0eaf0a40181359470651f1565b3e07e3dd31b8", + "shasum": "" + }, + "require": { + "guzzlehttp/guzzle": "^6.0", + "php": ">=5.5.0", + "symfony/browser-kit": "~2.1|~3.0|~4.0", + "symfony/css-selector": "~2.1|~3.0|~4.0", + "symfony/dom-crawler": "~2.1|~3.0|~4.0" + }, + "require-dev": { + "symfony/phpunit-bridge": "^3.3 || ^4" + }, + "time": "2018-06-29T15:13:57+00:00", + "type": "application", + "extra": { + "branch-alias": { + "dev-master": "3.2-dev" + } + }, + "installation-source": "dist", + "autoload": { + "psr-4": { + "Goutte\\": "Goutte" + }, + "exclude-from-classmap": [ + "Goutte/Tests" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + } + ], + "description": "A simple PHP Web Scraper", + "homepage": "https://github.com/FriendsOfPHP/Goutte", + "keywords": [ + "scraper" + ] + }, + { + "name": "guzzlehttp/guzzle", + "version": "6.3.3", + "version_normalized": "6.3.3.0", + "source": { + "type": "git", + "url": "https://github.com/guzzle/guzzle.git", + "reference": "407b0cb880ace85c9b63c5f9551db498cb2d50ba" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/guzzle/guzzle/zipball/407b0cb880ace85c9b63c5f9551db498cb2d50ba", + "reference": "407b0cb880ace85c9b63c5f9551db498cb2d50ba", + "shasum": "" + }, + "require": { + "guzzlehttp/promises": "^1.0", + "guzzlehttp/psr7": "^1.4", + "php": ">=5.5" + }, + "require-dev": { + "ext-curl": "*", + "phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.4 || ^7.0", + "psr/log": "^1.0" + }, + "suggest": { + "psr/log": "Required for using the Log middleware" + }, + "time": "2018-04-22T15:46:56+00:00", + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "6.3-dev" + } + }, + "installation-source": "dist", + "autoload": { + "files": [ + "src/functions_include.php" + ], + "psr-4": { + "GuzzleHttp\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Michael Dowling", + "email": "mtdowling@gmail.com", + "homepage": "https://github.com/mtdowling" + } + ], + "description": "Guzzle is a PHP HTTP client library", + "homepage": "http://guzzlephp.org/", + "keywords": [ + "client", + "curl", + "framework", + "http", + "http client", + "rest", + "web service" + ] + }, + { + "name": "guzzlehttp/promises", + "version": "v1.3.1", + "version_normalized": "1.3.1.0", + "source": { + "type": "git", + "url": "https://github.com/guzzle/promises.git", + "reference": "a59da6cf61d80060647ff4d3eb2c03a2bc694646" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/guzzle/promises/zipball/a59da6cf61d80060647ff4d3eb2c03a2bc694646", + "reference": "a59da6cf61d80060647ff4d3eb2c03a2bc694646", + "shasum": "" + }, + "require": { + "php": ">=5.5.0" + }, + "require-dev": { + "phpunit/phpunit": "^4.0" + }, + "time": "2016-12-20T10:07:11+00:00", + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.4-dev" + } + }, + "installation-source": "dist", + "autoload": { + "psr-4": { + "GuzzleHttp\\Promise\\": "src/" + }, + "files": [ + "src/functions_include.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Michael Dowling", + "email": "mtdowling@gmail.com", + "homepage": "https://github.com/mtdowling" + } + ], + "description": "Guzzle promises library", + "keywords": [ + "promise" + ] + }, + { + "name": "guzzlehttp/psr7", + "version": "1.4.2", + "version_normalized": "1.4.2.0", + "source": { + "type": "git", + "url": "https://github.com/guzzle/psr7.git", + "reference": "f5b8a8512e2b58b0071a7280e39f14f72e05d87c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/guzzle/psr7/zipball/f5b8a8512e2b58b0071a7280e39f14f72e05d87c", + "reference": "f5b8a8512e2b58b0071a7280e39f14f72e05d87c", + "shasum": "" + }, + "require": { + "php": ">=5.4.0", + "psr/http-message": "~1.0" + }, + "provide": { + "psr/http-message-implementation": "1.0" + }, + "require-dev": { + "phpunit/phpunit": "~4.0" + }, + "time": "2017-03-20T17:10:46+00:00", + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.4-dev" + } + }, + "installation-source": "dist", + "autoload": { + "psr-4": { + "GuzzleHttp\\Psr7\\": "src/" + }, + "files": [ + "src/functions_include.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Michael Dowling", + "email": "mtdowling@gmail.com", + "homepage": "https://github.com/mtdowling" + }, + { + "name": "Tobias Schultze", + "homepage": "https://github.com/Tobion" + } + ], + "description": "PSR-7 message implementation that also provides common utility methods", + "keywords": [ + "http", + "message", + "request", + "response", + "stream", + "uri", + "url" + ] + }, + { + "name": "instaclick/php-webdriver", + "version": "1.4.5", + "version_normalized": "1.4.5.0", + "source": { + "type": "git", + "url": "https://github.com/instaclick/php-webdriver.git", + "reference": "6fa959452e774dcaed543faad3a9d1a37d803327" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/instaclick/php-webdriver/zipball/6fa959452e774dcaed543faad3a9d1a37d803327", + "reference": "6fa959452e774dcaed543faad3a9d1a37d803327", + "shasum": "" + }, + "require": { + "ext-curl": "*", + "php": ">=5.3.2" + }, + "require-dev": { + "phpunit/phpunit": "^4.8", + "satooshi/php-coveralls": "^1.0||^2.0" + }, + "time": "2017-06-30T04:02:48+00:00", + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.4.x-dev" + } + }, + "installation-source": "dist", + "autoload": { + "psr-0": { + "WebDriver": "lib/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "Apache-2.0" + ], + "authors": [ + { + "name": "Justin Bishop", + "email": "jubishop@gmail.com", + "role": "Developer" + }, + { + "name": "Anthon Pang", + "email": "apang@softwaredevelopment.ca", + "role": "Fork Maintainer" + } + ], + "description": "PHP WebDriver for Selenium 2", + "homepage": "http://instaclick.com/", + "keywords": [ + "browser", + "selenium", + "webdriver", + "webtest" + ] + }, + { + "name": "jakub-onderka/php-console-color", + "version": "0.1", + "version_normalized": "0.1.0.0", + "source": { + "type": "git", + "url": "https://github.com/JakubOnderka/PHP-Console-Color.git", + "reference": "e0b393dacf7703fc36a4efc3df1435485197e6c1" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/JakubOnderka/PHP-Console-Color/zipball/e0b393dacf7703fc36a4efc3df1435485197e6c1", + "reference": "e0b393dacf7703fc36a4efc3df1435485197e6c1", + "shasum": "" + }, + "require": { + "php": ">=5.3.2" + }, + "require-dev": { + "jakub-onderka/php-code-style": "1.0", + "jakub-onderka/php-parallel-lint": "0.*", + "jakub-onderka/php-var-dump-check": "0.*", + "phpunit/phpunit": "3.7.*", + "squizlabs/php_codesniffer": "1.*" + }, + "time": "2014-04-08T15:00:19+00:00", + "type": "library", + "installation-source": "dist", + "autoload": { + "psr-0": { + "JakubOnderka\\PhpConsoleColor": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-2-Clause" + ], + "authors": [ + { + "name": "Jakub Onderka", + "email": "jakub.onderka@gmail.com", + "homepage": "http://www.acci.cz" + } + ] + }, + { + "name": "jakub-onderka/php-console-highlighter", + "version": "v0.3.2", + "version_normalized": "0.3.2.0", + "source": { + "type": "git", + "url": "https://github.com/JakubOnderka/PHP-Console-Highlighter.git", + "reference": "7daa75df45242c8d5b75a22c00a201e7954e4fb5" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/JakubOnderka/PHP-Console-Highlighter/zipball/7daa75df45242c8d5b75a22c00a201e7954e4fb5", + "reference": "7daa75df45242c8d5b75a22c00a201e7954e4fb5", + "shasum": "" + }, + "require": { + "jakub-onderka/php-console-color": "~0.1", + "php": ">=5.3.0" + }, + "require-dev": { + "jakub-onderka/php-code-style": "~1.0", + "jakub-onderka/php-parallel-lint": "~0.5", + "jakub-onderka/php-var-dump-check": "~0.1", + "phpunit/phpunit": "~4.0", + "squizlabs/php_codesniffer": "~1.5" + }, + "time": "2015-04-20T18:58:01+00:00", + "type": "library", + "installation-source": "dist", + "autoload": { + "psr-0": { + "JakubOnderka\\PhpConsoleHighlighter": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Jakub Onderka", + "email": "acci@acci.cz", + "homepage": "http://www.acci.cz/" + } + ] + }, + { + "name": "jcalderonzumba/gastonjs", + "version": "v1.2.0", + "version_normalized": "1.2.0.0", + "source": { + "type": "git", + "url": "https://github.com/jcalderonzumba/gastonjs.git", + "reference": "575a9c18d8b87990c37252e8d9707b29f0a313f3" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/jcalderonzumba/gastonjs/zipball/575a9c18d8b87990c37252e8d9707b29f0a313f3", + "reference": "575a9c18d8b87990c37252e8d9707b29f0a313f3", + "shasum": "" + }, + "require": { + "guzzlehttp/guzzle": "~5.0|~6.0", + "php": ">=5.4" + }, + "require-dev": { + "phpunit/phpunit": "~4.6", + "silex/silex": "~1.2", + "symfony/phpunit-bridge": "~2.7", + "symfony/process": "~2.1" + }, + "time": "2017-03-31T07:31:47+00:00", + "type": "phantomjs-api", + "extra": { + "branch-alias": { + "dev-master": "1.1.x-dev" + } + }, + "installation-source": "dist", + "autoload": { + "psr-4": { + "Zumba\\GastonJS\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Juan Francisco Calderón Zumba", + "email": "juanfcz@gmail.com", + "homepage": "http://github.com/jcalderonzumba" + } + ], + "description": "PhantomJS API based server for webpage automation", + "homepage": "https://github.com/jcalderonzumba/gastonjs", + "keywords": [ + "api", + "automation", + "browser", + "headless", + "phantomjs" + ] + }, + { + "name": "jcalderonzumba/mink-phantomjs-driver", + "version": "v0.3.3", + "version_normalized": "0.3.3.0", + "source": { + "type": "git", + "url": "https://github.com/jcalderonzumba/MinkPhantomJSDriver.git", + "reference": "008f43670e94acd39273d15add1e7348eb23848d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/jcalderonzumba/MinkPhantomJSDriver/zipball/008f43670e94acd39273d15add1e7348eb23848d", + "reference": "008f43670e94acd39273d15add1e7348eb23848d", + "shasum": "" + }, + "require": { + "behat/mink": "~1.7", + "jcalderonzumba/gastonjs": "~1.0", + "php": ">=5.4", + "twig/twig": "~1.20|~2.0" + }, + "require-dev": { + "mink/driver-testsuite": "dev-master", + "phpunit/phpunit": "~4.6" + }, + "time": "2016-12-01T10:57:30+00:00", + "type": "mink-driver", + "extra": { + "branch-alias": { + "dev-master": "0.4.x-dev" + } + }, + "installation-source": "dist", + "autoload": { + "psr-4": { + "Zumba\\Mink\\Driver\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Juan Francisco Calderón Zumba", + "email": "juanfcz@gmail.com", + "homepage": "http://github.com/jcalderonzumba" + } + ], + "description": "PhantomJS driver for Mink framework", + "homepage": "http://mink.behat.org/", + "keywords": [ + "ajax", + "browser", + "headless", + "javascript", + "phantomjs", + "testing" + ] + }, + { + "name": "masterminds/html5", + "version": "2.3.0", + "version_normalized": "2.3.0.0", + "source": { + "type": "git", + "url": "https://github.com/Masterminds/html5-php.git", + "reference": "2c37c6c520b995b761674de3be8455a381679067" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/Masterminds/html5-php/zipball/2c37c6c520b995b761674de3be8455a381679067", + "reference": "2c37c6c520b995b761674de3be8455a381679067", + "shasum": "" + }, + "require": { + "ext-libxml": "*", + "php": ">=5.3.0" + }, + "require-dev": { + "phpunit/phpunit": "4.*", + "sami/sami": "~2.0", + "satooshi/php-coveralls": "1.0.*" + }, + "time": "2017-09-04T12:26:28+00:00", + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.2-dev" + } + }, + "installation-source": "dist", + "autoload": { + "psr-4": { + "Masterminds\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Matt Butcher", + "email": "technosophos@gmail.com" + }, + { + "name": "Asmir Mustafic", + "email": "goetas@gmail.com" + }, + { + "name": "Matt Farina", + "email": "matt@mattfarina.com" + } + ], + "description": "An HTML5 parser and serializer.", + "homepage": "http://masterminds.github.io/html5-php", + "keywords": [ + "HTML5", + "dom", + "html", + "parser", + "querypath", + "serializer", + "xml" + ] + }, + { + "name": "mikey179/vfsStream", + "version": "v1.6.5", + "version_normalized": "1.6.5.0", + "source": { + "type": "git", + "url": "https://github.com/mikey179/vfsStream.git", + "reference": "d5fec95f541d4d71c4823bb5e30cf9b9e5b96145" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/mikey179/vfsStream/zipball/d5fec95f541d4d71c4823bb5e30cf9b9e5b96145", + "reference": "d5fec95f541d4d71c4823bb5e30cf9b9e5b96145", + "shasum": "" + }, + "require": { + "php": ">=5.3.0" + }, + "require-dev": { + "phpunit/phpunit": "~4.5" + }, + "time": "2017-08-01T08:02:14+00:00", + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.6.x-dev" + } + }, + "installation-source": "dist", + "autoload": { + "psr-0": { + "org\\bovigo\\vfs\\": "src/main/php" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Frank Kleine", + "homepage": "http://frankkleine.de/", + "role": "Developer" + } + ], + "description": "Virtual file system to mock the real file system in unit tests.", + "homepage": "http://vfs.bovigo.org/" + }, + { + "name": "myclabs/deep-copy", + "version": "1.7.0", + "version_normalized": "1.7.0.0", + "source": { + "type": "git", + "url": "https://github.com/myclabs/DeepCopy.git", + "reference": "3b8a3a99ba1f6a3952ac2747d989303cbd6b7a3e" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/3b8a3a99ba1f6a3952ac2747d989303cbd6b7a3e", + "reference": "3b8a3a99ba1f6a3952ac2747d989303cbd6b7a3e", + "shasum": "" + }, + "require": { + "php": "^5.6 || ^7.0" + }, + "require-dev": { + "doctrine/collections": "^1.0", + "doctrine/common": "^2.6", + "phpunit/phpunit": "^4.1" + }, + "time": "2017-10-19T19:58:43+00:00", + "type": "library", + "installation-source": "dist", + "autoload": { + "psr-4": { + "DeepCopy\\": "src/DeepCopy/" + }, + "files": [ + "src/DeepCopy/deep_copy.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "Create deep copies (clones) of your objects", + "keywords": [ + "clone", + "copy", + "duplicate", + "object", + "object graph" + ] + }, + { + "name": "nikic/php-parser", + "version": "v4.0.2", + "version_normalized": "4.0.2.0", + "source": { + "type": "git", + "url": "https://github.com/nikic/PHP-Parser.git", + "reference": "35b8caf75e791ba1b2d24fec1552168d72692b12" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/35b8caf75e791ba1b2d24fec1552168d72692b12", + "reference": "35b8caf75e791ba1b2d24fec1552168d72692b12", + "shasum": "" + }, + "require": { + "ext-tokenizer": "*", + "php": ">=7.0" + }, + "require-dev": { + "phpunit/phpunit": "^6.5 || ^7.0" + }, + "time": "2018-06-03T11:33:10+00:00", + "bin": [ + "bin/php-parse" + ], + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "4.0-dev" + } + }, + "installation-source": "dist", + "autoload": { + "psr-4": { + "PhpParser\\": "lib/PhpParser" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Nikita Popov" + } + ], + "description": "A PHP parser written in PHP", + "keywords": [ + "parser", + "php" + ] + }, + { + "name": "paragonie/random_compat", + "version": "v2.0.17", + "version_normalized": "2.0.17.0", + "source": { + "type": "git", + "url": "https://github.com/paragonie/random_compat.git", + "reference": "29af24f25bab834fcbb38ad2a69fa93b867e070d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/paragonie/random_compat/zipball/29af24f25bab834fcbb38ad2a69fa93b867e070d", + "reference": "29af24f25bab834fcbb38ad2a69fa93b867e070d", + "shasum": "" + }, + "require": { + "php": ">=5.2.0" + }, + "require-dev": { + "phpunit/phpunit": "4.*|5.*" + }, + "suggest": { + "ext-libsodium": "Provides a modern crypto API that can be used to generate random bytes." + }, + "time": "2018-07-04T16:31:37+00:00", + "type": "library", + "installation-source": "dist", + "autoload": { + "files": [ + "lib/random.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Paragon Initiative Enterprises", + "email": "security@paragonie.com", + "homepage": "https://paragonie.com" + } + ], + "description": "PHP 5.x polyfill for random_bytes() and random_int() from PHP 7", + "keywords": [ + "csprng", + "polyfill", + "pseudorandom", + "random" + ] + }, + { + "name": "pear/console_table", + "version": "v1.3.1", + "version_normalized": "1.3.1.0", + "source": { + "type": "git", + "url": "https://github.com/pear/Console_Table.git", + "reference": "1930c11897ca61fd24b95f2f785e99e0f36dcdea" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/pear/Console_Table/zipball/1930c11897ca61fd24b95f2f785e99e0f36dcdea", + "reference": "1930c11897ca61fd24b95f2f785e99e0f36dcdea", + "shasum": "" + }, + "require": { + "php": ">=5.2.0" + }, + "suggest": { + "pear/Console_Color2": ">=0.1.2" + }, + "time": "2018-01-25T20:47:17+00:00", + "type": "library", + "installation-source": "dist", + "autoload": { + "classmap": [ + "Table.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-2-Clause" + ], + "authors": [ + { + "name": "Jan Schneider", + "homepage": "http://pear.php.net/user/yunosh" + }, + { + "name": "Tal Peer", + "homepage": "http://pear.php.net/user/tal" + }, + { + "name": "Xavier Noguer", + "homepage": "http://pear.php.net/user/xnoguer" + }, + { + "name": "Richard Heyes", + "homepage": "http://pear.php.net/user/richard" + } + ], + "description": "Library that makes it easy to build console style tables.", + "homepage": "http://pear.php.net/package/Console_Table/", + "keywords": [ + "console" + ] + }, + { + "name": "phar-io/manifest", + "version": "1.0.1", + "version_normalized": "1.0.1.0", + "source": { + "type": "git", + "url": "https://github.com/phar-io/manifest.git", + "reference": "2df402786ab5368a0169091f61a7c1e0eb6852d0" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phar-io/manifest/zipball/2df402786ab5368a0169091f61a7c1e0eb6852d0", + "reference": "2df402786ab5368a0169091f61a7c1e0eb6852d0", + "shasum": "" + }, + "require": { + "ext-dom": "*", + "ext-phar": "*", + "phar-io/version": "^1.0.1", + "php": "^5.6 || ^7.0" + }, + "time": "2017-03-05T18:14:27+00:00", + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "installation-source": "dist", + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Arne Blankerts", + "email": "arne@blankerts.de", + "role": "Developer" + }, + { + "name": "Sebastian Heuer", + "email": "sebastian@phpeople.de", + "role": "Developer" + }, + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "Developer" + } + ], + "description": "Component for reading phar.io manifest information from a PHP Archive (PHAR)" + }, + { + "name": "phar-io/version", + "version": "1.0.1", + "version_normalized": "1.0.1.0", + "source": { + "type": "git", + "url": "https://github.com/phar-io/version.git", + "reference": "a70c0ced4be299a63d32fa96d9281d03e94041df" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phar-io/version/zipball/a70c0ced4be299a63d32fa96d9281d03e94041df", + "reference": "a70c0ced4be299a63d32fa96d9281d03e94041df", + "shasum": "" + }, + "require": { + "php": "^5.6 || ^7.0" + }, + "time": "2017-03-05T17:38:23+00:00", + "type": "library", + "installation-source": "dist", + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Arne Blankerts", + "email": "arne@blankerts.de", + "role": "Developer" + }, + { + "name": "Sebastian Heuer", + "email": "sebastian@phpeople.de", + "role": "Developer" + }, + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "Developer" + } + ], + "description": "Library for handling version information and constraints" + }, + { + "name": "phpdocumentor/reflection-common", + "version": "1.0.1", + "version_normalized": "1.0.1.0", + "source": { + "type": "git", + "url": "https://github.com/phpDocumentor/ReflectionCommon.git", + "reference": "21bdeb5f65d7ebf9f43b1b25d404f87deab5bfb6" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpDocumentor/ReflectionCommon/zipball/21bdeb5f65d7ebf9f43b1b25d404f87deab5bfb6", + "reference": "21bdeb5f65d7ebf9f43b1b25d404f87deab5bfb6", + "shasum": "" + }, + "require": { + "php": ">=5.5" + }, + "require-dev": { + "phpunit/phpunit": "^4.6" + }, + "time": "2017-09-11T18:02:19+00:00", + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "installation-source": "dist", + "autoload": { + "psr-4": { + "phpDocumentor\\Reflection\\": [ + "src" + ] + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Jaap van Otterdijk", + "email": "opensource@ijaap.nl" + } + ], + "description": "Common reflection classes used by phpdocumentor to reflect the code structure", + "homepage": "http://www.phpdoc.org", + "keywords": [ + "FQSEN", + "phpDocumentor", + "phpdoc", + "reflection", + "static analysis" + ] + }, + { + "name": "phpdocumentor/reflection-docblock", + "version": "4.3.0", + "version_normalized": "4.3.0.0", + "source": { + "type": "git", + "url": "https://github.com/phpDocumentor/ReflectionDocBlock.git", + "reference": "94fd0001232e47129dd3504189fa1c7225010d08" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/94fd0001232e47129dd3504189fa1c7225010d08", + "reference": "94fd0001232e47129dd3504189fa1c7225010d08", + "shasum": "" + }, + "require": { + "php": "^7.0", + "phpdocumentor/reflection-common": "^1.0.0", + "phpdocumentor/type-resolver": "^0.4.0", + "webmozart/assert": "^1.0" + }, + "require-dev": { + "doctrine/instantiator": "~1.0.5", + "mockery/mockery": "^1.0", + "phpunit/phpunit": "^6.4" + }, + "time": "2017-11-30T07:14:17+00:00", + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "4.x-dev" + } + }, + "installation-source": "dist", + "autoload": { + "psr-4": { + "phpDocumentor\\Reflection\\": [ + "src/" + ] + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Mike van Riel", + "email": "me@mikevanriel.com" + } + ], + "description": "With this component, a library can provide support for annotations via DocBlocks or otherwise retrieve information that is embedded in a DocBlock." + }, + { + "name": "phpdocumentor/type-resolver", + "version": "0.4.0", + "version_normalized": "0.4.0.0", + "source": { + "type": "git", + "url": "https://github.com/phpDocumentor/TypeResolver.git", + "reference": "9c977708995954784726e25d0cd1dddf4e65b0f7" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpDocumentor/TypeResolver/zipball/9c977708995954784726e25d0cd1dddf4e65b0f7", + "reference": "9c977708995954784726e25d0cd1dddf4e65b0f7", + "shasum": "" + }, + "require": { + "php": "^5.5 || ^7.0", + "phpdocumentor/reflection-common": "^1.0" + }, + "require-dev": { + "mockery/mockery": "^0.9.4", + "phpunit/phpunit": "^5.2||^4.8.24" + }, + "time": "2017-07-14T14:27:02+00:00", + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "installation-source": "dist", + "autoload": { + "psr-4": { + "phpDocumentor\\Reflection\\": [ + "src/" + ] + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Mike van Riel", + "email": "me@mikevanriel.com" + } + ] + }, + { + "name": "phpspec/prophecy", + "version": "1.7.6", + "version_normalized": "1.7.6.0", + "source": { + "type": "git", + "url": "https://github.com/phpspec/prophecy.git", + "reference": "33a7e3c4fda54e912ff6338c48823bd5c0f0b712" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpspec/prophecy/zipball/33a7e3c4fda54e912ff6338c48823bd5c0f0b712", + "reference": "33a7e3c4fda54e912ff6338c48823bd5c0f0b712", + "shasum": "" + }, + "require": { + "doctrine/instantiator": "^1.0.2", + "php": "^5.3|^7.0", + "phpdocumentor/reflection-docblock": "^2.0|^3.0.2|^4.0", + "sebastian/comparator": "^1.1|^2.0|^3.0", + "sebastian/recursion-context": "^1.0|^2.0|^3.0" + }, + "require-dev": { + "phpspec/phpspec": "^2.5|^3.2", + "phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.5" + }, + "time": "2018-04-18T13:57:24+00:00", + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.7.x-dev" + } + }, + "installation-source": "dist", + "autoload": { + "psr-0": { + "Prophecy\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Konstantin Kudryashov", + "email": "ever.zet@gmail.com", + "homepage": "http://everzet.com" + }, + { + "name": "Marcello Duarte", + "email": "marcello.duarte@gmail.com" + } + ], + "description": "Highly opinionated mocking framework for PHP 5.3+", + "homepage": "https://github.com/phpspec/prophecy", + "keywords": [ + "Double", + "Dummy", + "fake", + "mock", + "spy", + "stub" + ] + }, + { + "name": "phpunit/php-code-coverage", + "version": "5.3.2", + "version_normalized": "5.3.2.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-code-coverage.git", + "reference": "c89677919c5dd6d3b3852f230a663118762218ac" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/c89677919c5dd6d3b3852f230a663118762218ac", + "reference": "c89677919c5dd6d3b3852f230a663118762218ac", + "shasum": "" + }, + "require": { + "ext-dom": "*", + "ext-xmlwriter": "*", + "php": "^7.0", + "phpunit/php-file-iterator": "^1.4.2", + "phpunit/php-text-template": "^1.2.1", + "phpunit/php-token-stream": "^2.0.1", + "sebastian/code-unit-reverse-lookup": "^1.0.1", + "sebastian/environment": "^3.0", + "sebastian/version": "^2.0.1", + "theseer/tokenizer": "^1.1" + }, + "require-dev": { + "phpunit/phpunit": "^6.0" + }, + "suggest": { + "ext-xdebug": "^2.5.5" + }, + "time": "2018-04-06T15:36:58+00:00", + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "5.3.x-dev" + } + }, + "installation-source": "dist", + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Library that provides collection, processing, and rendering functionality for PHP code coverage information.", + "homepage": "https://github.com/sebastianbergmann/php-code-coverage", + "keywords": [ + "coverage", + "testing", + "xunit" + ] + }, + { + "name": "phpunit/php-file-iterator", + "version": "1.4.5", + "version_normalized": "1.4.5.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-file-iterator.git", + "reference": "730b01bc3e867237eaac355e06a36b85dd93a8b4" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/730b01bc3e867237eaac355e06a36b85dd93a8b4", + "reference": "730b01bc3e867237eaac355e06a36b85dd93a8b4", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "time": "2017-11-27T13:52:08+00:00", + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.4.x-dev" + } + }, + "installation-source": "dist", + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sb@sebastian-bergmann.de", + "role": "lead" + } + ], + "description": "FilterIterator implementation that filters files based on a list of suffixes.", + "homepage": "https://github.com/sebastianbergmann/php-file-iterator/", + "keywords": [ + "filesystem", + "iterator" + ] + }, + { + "name": "phpunit/php-text-template", + "version": "1.2.1", + "version_normalized": "1.2.1.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-text-template.git", + "reference": "31f8b717e51d9a2afca6c9f046f5d69fc27c8686" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/31f8b717e51d9a2afca6c9f046f5d69fc27c8686", + "reference": "31f8b717e51d9a2afca6c9f046f5d69fc27c8686", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "time": "2015-06-21T13:50:34+00:00", + "type": "library", + "installation-source": "dist", + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Simple template engine.", + "homepage": "https://github.com/sebastianbergmann/php-text-template/", + "keywords": [ + "template" + ] + }, + { + "name": "phpunit/php-timer", + "version": "1.0.9", + "version_normalized": "1.0.9.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-timer.git", + "reference": "3dcf38ca72b158baf0bc245e9184d3fdffa9c46f" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/3dcf38ca72b158baf0bc245e9184d3fdffa9c46f", + "reference": "3dcf38ca72b158baf0bc245e9184d3fdffa9c46f", + "shasum": "" + }, + "require": { + "php": "^5.3.3 || ^7.0" + }, + "require-dev": { + "phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.0" + }, + "time": "2017-02-26T11:10:40+00:00", + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0-dev" + } + }, + "installation-source": "dist", + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sb@sebastian-bergmann.de", + "role": "lead" + } + ], + "description": "Utility class for timing", + "homepage": "https://github.com/sebastianbergmann/php-timer/", + "keywords": [ + "timer" + ] + }, + { + "name": "phpunit/php-token-stream", + "version": "2.0.2", + "version_normalized": "2.0.2.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-token-stream.git", + "reference": "791198a2c6254db10131eecfe8c06670700904db" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-token-stream/zipball/791198a2c6254db10131eecfe8c06670700904db", + "reference": "791198a2c6254db10131eecfe8c06670700904db", + "shasum": "" + }, + "require": { + "ext-tokenizer": "*", + "php": "^7.0" + }, + "require-dev": { + "phpunit/phpunit": "^6.2.4" + }, + "time": "2017-11-27T05:48:46+00:00", + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0-dev" + } + }, + "installation-source": "dist", + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Wrapper around PHP's tokenizer extension.", + "homepage": "https://github.com/sebastianbergmann/php-token-stream/", + "keywords": [ + "tokenizer" + ] + }, + { + "name": "phpunit/phpunit", + "version": "6.5.9", + "version_normalized": "6.5.9.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/phpunit.git", + "reference": "093ca5508174cd8ab8efe44fd1dde447adfdec8f" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/093ca5508174cd8ab8efe44fd1dde447adfdec8f", + "reference": "093ca5508174cd8ab8efe44fd1dde447adfdec8f", + "shasum": "" + }, + "require": { + "ext-dom": "*", + "ext-json": "*", + "ext-libxml": "*", + "ext-mbstring": "*", + "ext-xml": "*", + "myclabs/deep-copy": "^1.6.1", + "phar-io/manifest": "^1.0.1", + "phar-io/version": "^1.0", + "php": "^7.0", + "phpspec/prophecy": "^1.7", + "phpunit/php-code-coverage": "^5.3", + "phpunit/php-file-iterator": "^1.4.3", + "phpunit/php-text-template": "^1.2.1", + "phpunit/php-timer": "^1.0.9", + "phpunit/phpunit-mock-objects": "^5.0.5", + "sebastian/comparator": "^2.1", + "sebastian/diff": "^2.0", + "sebastian/environment": "^3.1", + "sebastian/exporter": "^3.1", + "sebastian/global-state": "^2.0", + "sebastian/object-enumerator": "^3.0.3", + "sebastian/resource-operations": "^1.0", + "sebastian/version": "^2.0.1" + }, + "conflict": { + "phpdocumentor/reflection-docblock": "3.0.2", + "phpunit/dbunit": "<3.0" + }, + "require-dev": { + "ext-pdo": "*" + }, + "suggest": { + "ext-xdebug": "*", + "phpunit/php-invoker": "^1.1" + }, + "time": "2018-07-03T06:40:40+00:00", + "bin": [ + "phpunit" + ], + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "6.5.x-dev" + } + }, + "installation-source": "dist", + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "The PHP Unit Testing framework.", + "homepage": "https://phpunit.de/", + "keywords": [ + "phpunit", + "testing", + "xunit" + ] + }, + { + "name": "phpunit/phpunit-mock-objects", + "version": "5.0.7", + "version_normalized": "5.0.7.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/phpunit-mock-objects.git", + "reference": "3eaf040f20154d27d6da59ca2c6e28ac8fd56dce" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit-mock-objects/zipball/3eaf040f20154d27d6da59ca2c6e28ac8fd56dce", + "reference": "3eaf040f20154d27d6da59ca2c6e28ac8fd56dce", + "shasum": "" + }, + "require": { + "doctrine/instantiator": "^1.0.5", + "php": "^7.0", + "phpunit/php-text-template": "^1.2.1", + "sebastian/exporter": "^3.1" + }, + "conflict": { + "phpunit/phpunit": "<6.0" + }, + "require-dev": { + "phpunit/phpunit": "^6.5" + }, + "suggest": { + "ext-soap": "*" + }, + "time": "2018-05-29T13:50:43+00:00", + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "5.0.x-dev" + } + }, + "installation-source": "dist", + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Mock Object library for PHPUnit", + "homepage": "https://github.com/sebastianbergmann/phpunit-mock-objects/", + "keywords": [ + "mock", + "xunit" + ] + }, + { + "name": "psr/container", + "version": "1.0.0", + "version_normalized": "1.0.0.0", + "source": { + "type": "git", + "url": "https://github.com/php-fig/container.git", + "reference": "b7ce3b176482dbbc1245ebf52b181af44c2cf55f" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/container/zipball/b7ce3b176482dbbc1245ebf52b181af44c2cf55f", + "reference": "b7ce3b176482dbbc1245ebf52b181af44c2cf55f", + "shasum": "" + }, + "require": { + "php": ">=5.3.0" + }, + "time": "2017-02-14T16:28:37+00:00", + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "installation-source": "dist", + "autoload": { + "psr-4": { + "Psr\\Container\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "http://www.php-fig.org/" + } + ], + "description": "Common Container Interface (PHP FIG PSR-11)", + "homepage": "https://github.com/php-fig/container", + "keywords": [ + "PSR-11", + "container", + "container-interface", + "container-interop", + "psr" + ] + }, + { + "name": "psr/http-message", + "version": "1.0.1", + "version_normalized": "1.0.1.0", + "source": { + "type": "git", + "url": "https://github.com/php-fig/http-message.git", + "reference": "f6561bf28d520154e4b0ec72be95418abe6d9363" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/http-message/zipball/f6561bf28d520154e4b0ec72be95418abe6d9363", + "reference": "f6561bf28d520154e4b0ec72be95418abe6d9363", + "shasum": "" + }, + "require": { + "php": ">=5.3.0" + }, + "time": "2016-08-06T14:39:51+00:00", + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "installation-source": "dist", + "autoload": { + "psr-4": { + "Psr\\Http\\Message\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "http://www.php-fig.org/" + } + ], + "description": "Common interface for HTTP messages", + "homepage": "https://github.com/php-fig/http-message", + "keywords": [ + "http", + "http-message", + "psr", + "psr-7", + "request", + "response" + ] + }, + { + "name": "psr/log", + "version": "1.0.2", + "version_normalized": "1.0.2.0", + "source": { + "type": "git", + "url": "https://github.com/php-fig/log.git", + "reference": "4ebe3a8bf773a19edfe0a84b6585ba3d401b724d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/log/zipball/4ebe3a8bf773a19edfe0a84b6585ba3d401b724d", + "reference": "4ebe3a8bf773a19edfe0a84b6585ba3d401b724d", + "shasum": "" + }, + "require": { + "php": ">=5.3.0" + }, + "time": "2016-10-10T12:19:37+00:00", + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "installation-source": "dist", + "autoload": { + "psr-4": { + "Psr\\Log\\": "Psr/Log/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "http://www.php-fig.org/" + } + ], + "description": "Common interface for logging libraries", + "homepage": "https://github.com/php-fig/log", + "keywords": [ + "log", + "psr", + "psr-3" + ] + }, + { + "name": "psy/psysh", + "version": "v0.9.6", + "version_normalized": "0.9.6.0", + "source": { + "type": "git", + "url": "https://github.com/bobthecow/psysh.git", + "reference": "4a2ce86f199d51b6e2524214dc06835e872f4fce" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/bobthecow/psysh/zipball/4a2ce86f199d51b6e2524214dc06835e872f4fce", + "reference": "4a2ce86f199d51b6e2524214dc06835e872f4fce", + "shasum": "" + }, + "require": { + "dnoegel/php-xdg-base-dir": "0.1", + "jakub-onderka/php-console-highlighter": "0.3.*", + "nikic/php-parser": "~1.3|~2.0|~3.0|~4.0", + "php": ">=5.4.0", + "symfony/console": "~2.3.10|^2.4.2|~3.0|~4.0", + "symfony/var-dumper": "~2.7|~3.0|~4.0" + }, + "require-dev": { + "bamarni/composer-bin-plugin": "^1.2", + "hoa/console": "~2.15|~3.16", + "phpunit/phpunit": "~4.8.35|~5.0|~6.0|~7.0" + }, + "suggest": { + "ext-pcntl": "Enabling the PCNTL extension makes PsySH a lot happier :)", + "ext-pdo-sqlite": "The doc command requires SQLite to work.", + "ext-posix": "If you have PCNTL, you'll want the POSIX extension as well.", + "ext-readline": "Enables support for arrow-key history navigation, and showing and manipulating command history.", + "hoa/console": "A pure PHP readline implementation. You'll want this if your PHP install doesn't already support readline or libedit." + }, + "time": "2018-06-10T17:57:20+00:00", + "bin": [ + "bin/psysh" + ], + "type": "library", + "extra": { + "branch-alias": { + "dev-develop": "0.9.x-dev" + } + }, + "installation-source": "dist", + "autoload": { + "files": [ + "src/functions.php" + ], + "psr-4": { + "Psy\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Justin Hileman", + "email": "justin@justinhileman.info", + "homepage": "http://justinhileman.com" + } + ], + "description": "An interactive shell for modern PHP.", + "homepage": "http://psysh.org", + "keywords": [ + "REPL", + "console", + "interactive", + "shell" + ] + }, + { + "name": "sebastian/code-unit-reverse-lookup", + "version": "1.0.1", + "version_normalized": "1.0.1.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/code-unit-reverse-lookup.git", + "reference": "4419fcdb5eabb9caa61a27c7a1db532a6b55dd18" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/code-unit-reverse-lookup/zipball/4419fcdb5eabb9caa61a27c7a1db532a6b55dd18", + "reference": "4419fcdb5eabb9caa61a27c7a1db532a6b55dd18", + "shasum": "" + }, + "require": { + "php": "^5.6 || ^7.0" + }, + "require-dev": { + "phpunit/phpunit": "^5.7 || ^6.0" + }, + "time": "2017-03-04T06:30:41+00:00", + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "installation-source": "dist", + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Looks up which function or method a line of code belongs to", + "homepage": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/" + }, + { + "name": "sebastian/comparator", + "version": "2.1.3", + "version_normalized": "2.1.3.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/comparator.git", + "reference": "34369daee48eafb2651bea869b4b15d75ccc35f9" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/34369daee48eafb2651bea869b4b15d75ccc35f9", + "reference": "34369daee48eafb2651bea869b4b15d75ccc35f9", + "shasum": "" + }, + "require": { + "php": "^7.0", + "sebastian/diff": "^2.0 || ^3.0", + "sebastian/exporter": "^3.1" + }, + "require-dev": { + "phpunit/phpunit": "^6.4" + }, + "time": "2018-02-01T13:46:46+00:00", + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.1.x-dev" + } + }, + "installation-source": "dist", + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Jeff Welch", + "email": "whatthejeff@gmail.com" + }, + { + "name": "Volker Dusch", + "email": "github@wallbash.com" + }, + { + "name": "Bernhard Schussek", + "email": "bschussek@2bepublished.at" + }, + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Provides the functionality to compare PHP values for equality", + "homepage": "https://github.com/sebastianbergmann/comparator", + "keywords": [ + "comparator", + "compare", + "equality" + ] + }, + { + "name": "sebastian/diff", + "version": "2.0.1", + "version_normalized": "2.0.1.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/diff.git", + "reference": "347c1d8b49c5c3ee30c7040ea6fc446790e6bddd" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/347c1d8b49c5c3ee30c7040ea6fc446790e6bddd", + "reference": "347c1d8b49c5c3ee30c7040ea6fc446790e6bddd", + "shasum": "" + }, + "require": { + "php": "^7.0" + }, + "require-dev": { + "phpunit/phpunit": "^6.2" + }, + "time": "2017-08-03T08:09:46+00:00", + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0-dev" + } + }, + "installation-source": "dist", + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Kore Nordmann", + "email": "mail@kore-nordmann.de" + }, + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Diff implementation", + "homepage": "https://github.com/sebastianbergmann/diff", + "keywords": [ + "diff" + ] + }, + { + "name": "sebastian/environment", + "version": "3.1.0", + "version_normalized": "3.1.0.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/environment.git", + "reference": "cd0871b3975fb7fc44d11314fd1ee20925fce4f5" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/cd0871b3975fb7fc44d11314fd1ee20925fce4f5", + "reference": "cd0871b3975fb7fc44d11314fd1ee20925fce4f5", + "shasum": "" + }, + "require": { + "php": "^7.0" + }, + "require-dev": { + "phpunit/phpunit": "^6.1" + }, + "time": "2017-07-01T08:51:00+00:00", + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.1.x-dev" + } + }, + "installation-source": "dist", + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Provides functionality to handle HHVM/PHP environments", + "homepage": "http://www.github.com/sebastianbergmann/environment", + "keywords": [ + "Xdebug", + "environment", + "hhvm" + ] + }, + { + "name": "sebastian/exporter", + "version": "3.1.0", + "version_normalized": "3.1.0.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/exporter.git", + "reference": "234199f4528de6d12aaa58b612e98f7d36adb937" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/234199f4528de6d12aaa58b612e98f7d36adb937", + "reference": "234199f4528de6d12aaa58b612e98f7d36adb937", + "shasum": "" + }, + "require": { + "php": "^7.0", + "sebastian/recursion-context": "^3.0" + }, + "require-dev": { + "ext-mbstring": "*", + "phpunit/phpunit": "^6.0" + }, + "time": "2017-04-03T13:19:02+00:00", + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.1.x-dev" + } + }, + "installation-source": "dist", + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Jeff Welch", + "email": "whatthejeff@gmail.com" + }, + { + "name": "Volker Dusch", + "email": "github@wallbash.com" + }, + { + "name": "Bernhard Schussek", + "email": "bschussek@2bepublished.at" + }, + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + }, + { + "name": "Adam Harvey", + "email": "aharvey@php.net" + } + ], + "description": "Provides the functionality to export PHP variables for visualization", + "homepage": "http://www.github.com/sebastianbergmann/exporter", + "keywords": [ + "export", + "exporter" + ] + }, + { + "name": "sebastian/global-state", + "version": "2.0.0", + "version_normalized": "2.0.0.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/global-state.git", + "reference": "e8ba02eed7bbbb9e59e43dedd3dddeff4a56b0c4" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/e8ba02eed7bbbb9e59e43dedd3dddeff4a56b0c4", + "reference": "e8ba02eed7bbbb9e59e43dedd3dddeff4a56b0c4", + "shasum": "" + }, + "require": { + "php": "^7.0" + }, + "require-dev": { + "phpunit/phpunit": "^6.0" + }, + "suggest": { + "ext-uopz": "*" + }, + "time": "2017-04-27T15:39:26+00:00", + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0-dev" + } + }, + "installation-source": "dist", + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Snapshotting of global state", + "homepage": "http://www.github.com/sebastianbergmann/global-state", + "keywords": [ + "global state" + ] + }, + { + "name": "sebastian/object-enumerator", + "version": "3.0.3", + "version_normalized": "3.0.3.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/object-enumerator.git", + "reference": "7cfd9e65d11ffb5af41198476395774d4c8a84c5" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/object-enumerator/zipball/7cfd9e65d11ffb5af41198476395774d4c8a84c5", + "reference": "7cfd9e65d11ffb5af41198476395774d4c8a84c5", + "shasum": "" + }, + "require": { + "php": "^7.0", + "sebastian/object-reflector": "^1.1.1", + "sebastian/recursion-context": "^3.0" + }, + "require-dev": { + "phpunit/phpunit": "^6.0" + }, + "time": "2017-08-03T12:35:26+00:00", + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.0.x-dev" + } + }, + "installation-source": "dist", + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Traverses array structures and object graphs to enumerate all referenced objects", + "homepage": "https://github.com/sebastianbergmann/object-enumerator/" + }, + { + "name": "sebastian/object-reflector", + "version": "1.1.1", + "version_normalized": "1.1.1.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/object-reflector.git", + "reference": "773f97c67f28de00d397be301821b06708fca0be" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/object-reflector/zipball/773f97c67f28de00d397be301821b06708fca0be", + "reference": "773f97c67f28de00d397be301821b06708fca0be", + "shasum": "" + }, + "require": { + "php": "^7.0" + }, + "require-dev": { + "phpunit/phpunit": "^6.0" + }, + "time": "2017-03-29T09:07:27+00:00", + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.1-dev" + } + }, + "installation-source": "dist", + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Allows reflection of object attributes, including inherited and non-public ones", + "homepage": "https://github.com/sebastianbergmann/object-reflector/" + }, + { + "name": "sebastian/recursion-context", + "version": "3.0.0", + "version_normalized": "3.0.0.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/recursion-context.git", + "reference": "5b0cd723502bac3b006cbf3dbf7a1e3fcefe4fa8" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/5b0cd723502bac3b006cbf3dbf7a1e3fcefe4fa8", + "reference": "5b0cd723502bac3b006cbf3dbf7a1e3fcefe4fa8", + "shasum": "" + }, + "require": { + "php": "^7.0" + }, + "require-dev": { + "phpunit/phpunit": "^6.0" + }, + "time": "2017-03-03T06:23:57+00:00", + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.0.x-dev" + } + }, + "installation-source": "dist", + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Jeff Welch", + "email": "whatthejeff@gmail.com" + }, + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + }, + { + "name": "Adam Harvey", + "email": "aharvey@php.net" + } + ], + "description": "Provides functionality to recursively process PHP variables", + "homepage": "http://www.github.com/sebastianbergmann/recursion-context" + }, + { + "name": "sebastian/resource-operations", + "version": "1.0.0", + "version_normalized": "1.0.0.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/resource-operations.git", + "reference": "ce990bb21759f94aeafd30209e8cfcdfa8bc3f52" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/resource-operations/zipball/ce990bb21759f94aeafd30209e8cfcdfa8bc3f52", + "reference": "ce990bb21759f94aeafd30209e8cfcdfa8bc3f52", + "shasum": "" + }, + "require": { + "php": ">=5.6.0" + }, + "time": "2015-07-28T20:34:47+00:00", + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "installation-source": "dist", + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Provides a list of PHP built-in functions that operate on resources", + "homepage": "https://www.github.com/sebastianbergmann/resource-operations" + }, + { + "name": "sebastian/version", + "version": "2.0.1", + "version_normalized": "2.0.1.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/version.git", + "reference": "99732be0ddb3361e16ad77b68ba41efc8e979019" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/version/zipball/99732be0ddb3361e16ad77b68ba41efc8e979019", + "reference": "99732be0ddb3361e16ad77b68ba41efc8e979019", + "shasum": "" + }, + "require": { + "php": ">=5.6" + }, + "time": "2016-10-03T07:35:21+00:00", + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0.x-dev" + } + }, + "installation-source": "dist", + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Library that helps with managing the version number of Git-hosted PHP projects", + "homepage": "https://github.com/sebastianbergmann/version" + }, + { + "name": "squizlabs/php_codesniffer", + "version": "2.9.1", + "version_normalized": "2.9.1.0", + "source": { + "type": "git", + "url": "https://github.com/squizlabs/PHP_CodeSniffer.git", + "reference": "dcbed1074f8244661eecddfc2a675430d8d33f62" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/squizlabs/PHP_CodeSniffer/zipball/dcbed1074f8244661eecddfc2a675430d8d33f62", + "reference": "dcbed1074f8244661eecddfc2a675430d8d33f62", + "shasum": "" + }, + "require": { + "ext-simplexml": "*", + "ext-tokenizer": "*", + "ext-xmlwriter": "*", + "php": ">=5.1.2" + }, + "require-dev": { + "phpunit/phpunit": "~4.0" + }, + "time": "2017-05-22T02:43:20+00:00", + "bin": [ + "scripts/phpcs", + "scripts/phpcbf" + ], + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.x-dev" + } + }, + "installation-source": "dist", + "autoload": { + "classmap": [ + "CodeSniffer.php", + "CodeSniffer/CLI.php", + "CodeSniffer/Exception.php", + "CodeSniffer/File.php", + "CodeSniffer/Fixer.php", + "CodeSniffer/Report.php", + "CodeSniffer/Reporting.php", + "CodeSniffer/Sniff.php", + "CodeSniffer/Tokens.php", + "CodeSniffer/Reports/", + "CodeSniffer/Tokenizers/", + "CodeSniffer/DocGenerators/", + "CodeSniffer/Standards/AbstractPatternSniff.php", + "CodeSniffer/Standards/AbstractScopeSniff.php", + "CodeSniffer/Standards/AbstractVariableSniff.php", + "CodeSniffer/Standards/IncorrectPatternException.php", + "CodeSniffer/Standards/Generic/Sniffs/", + "CodeSniffer/Standards/MySource/Sniffs/", + "CodeSniffer/Standards/PEAR/Sniffs/", + "CodeSniffer/Standards/PSR1/Sniffs/", + "CodeSniffer/Standards/PSR2/Sniffs/", + "CodeSniffer/Standards/Squiz/Sniffs/", + "CodeSniffer/Standards/Zend/Sniffs/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Greg Sherwood", + "role": "lead" + } + ], + "description": "PHP_CodeSniffer tokenizes PHP, JavaScript and CSS files and detects violations of a defined set of coding standards.", + "homepage": "http://www.squizlabs.com/php-codesniffer", + "keywords": [ + "phpcs", + "standards" + ] + }, + { + "name": "stack/builder", + "version": "v1.0.5", + "version_normalized": "1.0.5.0", + "source": { + "type": "git", + "url": "https://github.com/stackphp/builder.git", + "reference": "fb3d136d04c6be41120ebf8c0cc71fe9507d750a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/stackphp/builder/zipball/fb3d136d04c6be41120ebf8c0cc71fe9507d750a", + "reference": "fb3d136d04c6be41120ebf8c0cc71fe9507d750a", + "shasum": "" + }, + "require": { + "php": ">=5.3.0", + "symfony/http-foundation": "~2.1|~3.0|~4.0", + "symfony/http-kernel": "~2.1|~3.0|~4.0" + }, + "require-dev": { + "silex/silex": "~1.0" + }, + "time": "2017-11-18T14:57:29+00:00", + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0-dev" + } + }, + "installation-source": "dist", + "autoload": { + "psr-0": { + "Stack": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Igor Wiedler", + "email": "igor@wiedler.ch" + } + ], + "description": "Builder for stack middlewares based on HttpKernelInterface.", + "keywords": [ + "stack" + ] + }, + { + "name": "symfony-cmf/routing", + "version": "1.4.1", + "version_normalized": "1.4.1.0", + "source": { + "type": "git", + "url": "https://github.com/symfony-cmf/routing.git", + "reference": "fb1e7f85ff8c6866238b7e73a490a0a0243ae8ac" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony-cmf/routing/zipball/fb1e7f85ff8c6866238b7e73a490a0a0243ae8ac", + "reference": "fb1e7f85ff8c6866238b7e73a490a0a0243ae8ac", + "shasum": "" + }, + "require": { + "php": "^5.3.9|^7.0", + "psr/log": "1.*", + "symfony/http-kernel": "^2.2|3.*", + "symfony/routing": "^2.2|3.*" + }, + "require-dev": { + "friendsofsymfony/jsrouting-bundle": "^1.1", + "symfony-cmf/testing": "^1.3", + "symfony/config": "^2.2|3.*", + "symfony/dependency-injection": "^2.0.5|3.*", + "symfony/event-dispatcher": "^2.1|3.*" + }, + "suggest": { + "symfony/event-dispatcher": "DynamicRouter can optionally trigger an event at the start of matching. Minimal version (~2.1)" + }, + "time": "2017-05-09T08:10:41+00:00", + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.4-dev" + } + }, + "installation-source": "dist", + "autoload": { + "psr-4": { + "Symfony\\Cmf\\Component\\Routing\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Symfony CMF Community", + "homepage": "https://github.com/symfony-cmf/Routing/contributors" + } + ], + "description": "Extends the Symfony2 routing component for dynamic routes and chaining several routers", + "homepage": "http://cmf.symfony.com", + "keywords": [ + "database", + "routing" + ] + }, + { + "name": "symfony/browser-kit", + "version": "v3.4.12", + "version_normalized": "3.4.12.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/browser-kit.git", + "reference": "840bb6f0d5b3701fd768b68adf7193c2d0f98f79" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/browser-kit/zipball/840bb6f0d5b3701fd768b68adf7193c2d0f98f79", + "reference": "840bb6f0d5b3701fd768b68adf7193c2d0f98f79", + "shasum": "" + }, + "require": { + "php": "^5.5.9|>=7.0.8", + "symfony/dom-crawler": "~2.8|~3.0|~4.0" + }, + "require-dev": { + "symfony/css-selector": "~2.8|~3.0|~4.0", + "symfony/process": "~2.8|~3.0|~4.0" + }, + "suggest": { + "symfony/process": "" + }, + "time": "2018-03-19T22:32:39+00:00", + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.4-dev" + } + }, + "installation-source": "dist", + "autoload": { + "psr-4": { + "Symfony\\Component\\BrowserKit\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony BrowserKit Component", + "homepage": "https://symfony.com" + }, + { + "name": "symfony/class-loader", + "version": "v3.4.12", + "version_normalized": "3.4.12.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/class-loader.git", + "reference": "e63c12699822bb3b667e7216ba07fbcc3a3e203e" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/class-loader/zipball/e63c12699822bb3b667e7216ba07fbcc3a3e203e", + "reference": "e63c12699822bb3b667e7216ba07fbcc3a3e203e", + "shasum": "" + }, + "require": { + "php": "^5.5.9|>=7.0.8" + }, + "require-dev": { + "symfony/finder": "~2.8|~3.0|~4.0", + "symfony/polyfill-apcu": "~1.1" + }, + "suggest": { + "symfony/polyfill-apcu": "For using ApcClassLoader on HHVM" + }, + "time": "2018-01-03T07:37:34+00:00", + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.4-dev" + } + }, + "installation-source": "dist", + "autoload": { + "psr-4": { + "Symfony\\Component\\ClassLoader\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony ClassLoader Component", + "homepage": "https://symfony.com" + }, + { + "name": "symfony/console", + "version": "v3.4.12", + "version_normalized": "3.4.12.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/console.git", + "reference": "1b97071a26d028c9bd4588264e101e14f6e7cd00" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/console/zipball/1b97071a26d028c9bd4588264e101e14f6e7cd00", + "reference": "1b97071a26d028c9bd4588264e101e14f6e7cd00", + "shasum": "" + }, + "require": { + "php": "^5.5.9|>=7.0.8", + "symfony/debug": "~2.8|~3.0|~4.0", + "symfony/polyfill-mbstring": "~1.0" + }, + "conflict": { + "symfony/dependency-injection": "<3.4", + "symfony/process": "<3.3" + }, + "require-dev": { + "psr/log": "~1.0", + "symfony/config": "~3.3|~4.0", + "symfony/dependency-injection": "~3.4|~4.0", + "symfony/event-dispatcher": "~2.8|~3.0|~4.0", + "symfony/lock": "~3.4|~4.0", + "symfony/process": "~3.3|~4.0" + }, + "suggest": { + "psr/log-implementation": "For using the console logger", + "symfony/event-dispatcher": "", + "symfony/lock": "", + "symfony/process": "" + }, + "time": "2018-05-23T05:02:55+00:00", + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.4-dev" + } + }, + "installation-source": "dist", + "autoload": { + "psr-4": { + "Symfony\\Component\\Console\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony Console Component", + "homepage": "https://symfony.com" + }, + { + "name": "symfony/css-selector", + "version": "v3.4.12", + "version_normalized": "3.4.12.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/css-selector.git", + "reference": "d2ce52290b648ae33b5301d09bc14ee378612914" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/css-selector/zipball/d2ce52290b648ae33b5301d09bc14ee378612914", + "reference": "d2ce52290b648ae33b5301d09bc14ee378612914", + "shasum": "" + }, + "require": { + "php": "^5.5.9|>=7.0.8" + }, + "time": "2018-05-16T12:49:49+00:00", + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.4-dev" + } + }, + "installation-source": "dist", + "autoload": { + "psr-4": { + "Symfony\\Component\\CssSelector\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Jean-François Simon", + "email": "jeanfrancois.simon@sensiolabs.com" + }, + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony CssSelector Component", + "homepage": "https://symfony.com" + }, + { + "name": "symfony/debug", + "version": "v3.4.12", + "version_normalized": "3.4.12.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/debug.git", + "reference": "47e6788c5b151cf0cfdf3329116bf33800632d75" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/debug/zipball/47e6788c5b151cf0cfdf3329116bf33800632d75", + "reference": "47e6788c5b151cf0cfdf3329116bf33800632d75", + "shasum": "" + }, + "require": { + "php": "^5.5.9|>=7.0.8", + "psr/log": "~1.0" + }, + "conflict": { + "symfony/http-kernel": ">=2.3,<2.3.24|~2.4.0|>=2.5,<2.5.9|>=2.6,<2.6.2" + }, + "require-dev": { + "symfony/http-kernel": "~2.8|~3.0|~4.0" + }, + "time": "2018-06-25T11:10:40+00:00", + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.4-dev" + } + }, + "installation-source": "dist", + "autoload": { + "psr-4": { + "Symfony\\Component\\Debug\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony Debug Component", + "homepage": "https://symfony.com" + }, + { + "name": "symfony/dependency-injection", + "version": "v3.4.12", + "version_normalized": "3.4.12.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/dependency-injection.git", + "reference": "a0be80e3f8c11aca506e250c00bb100c04c35d10" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/dependency-injection/zipball/a0be80e3f8c11aca506e250c00bb100c04c35d10", + "reference": "a0be80e3f8c11aca506e250c00bb100c04c35d10", + "shasum": "" + }, + "require": { + "php": "^5.5.9|>=7.0.8", + "psr/container": "^1.0" + }, + "conflict": { + "symfony/config": "<3.3.7", + "symfony/finder": "<3.3", + "symfony/proxy-manager-bridge": "<3.4", + "symfony/yaml": "<3.4" + }, + "provide": { + "psr/container-implementation": "1.0" + }, + "require-dev": { + "symfony/config": "~3.3|~4.0", + "symfony/expression-language": "~2.8|~3.0|~4.0", + "symfony/yaml": "~3.4|~4.0" + }, + "suggest": { + "symfony/config": "", + "symfony/expression-language": "For using expressions in service container configuration", + "symfony/finder": "For using double-star glob patterns or when GLOB_BRACE portability is required", + "symfony/proxy-manager-bridge": "Generate service proxies to lazy load them", + "symfony/yaml": "" + }, + "time": "2018-06-25T08:36:56+00:00", + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.4-dev" + } + }, + "installation-source": "dist", + "autoload": { + "psr-4": { + "Symfony\\Component\\DependencyInjection\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony DependencyInjection Component", + "homepage": "https://symfony.com" + }, + { + "name": "symfony/dom-crawler", + "version": "v3.4.12", + "version_normalized": "3.4.12.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/dom-crawler.git", + "reference": "201b210fafcdd193c1e45b2994bf7133fb6263e8" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/dom-crawler/zipball/201b210fafcdd193c1e45b2994bf7133fb6263e8", + "reference": "201b210fafcdd193c1e45b2994bf7133fb6263e8", + "shasum": "" + }, + "require": { + "php": "^5.5.9|>=7.0.8", + "symfony/polyfill-ctype": "~1.8", + "symfony/polyfill-mbstring": "~1.0" + }, + "require-dev": { + "symfony/css-selector": "~2.8|~3.0|~4.0" + }, + "suggest": { + "symfony/css-selector": "" + }, + "time": "2018-05-01T22:53:27+00:00", + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.4-dev" + } + }, + "installation-source": "dist", + "autoload": { + "psr-4": { + "Symfony\\Component\\DomCrawler\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony DomCrawler Component", + "homepage": "https://symfony.com" + }, + { + "name": "symfony/event-dispatcher", + "version": "v3.4.12", + "version_normalized": "3.4.12.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/event-dispatcher.git", + "reference": "fdd5abcebd1061ec647089c6c41a07ed60af09f8" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/fdd5abcebd1061ec647089c6c41a07ed60af09f8", + "reference": "fdd5abcebd1061ec647089c6c41a07ed60af09f8", + "shasum": "" + }, + "require": { + "php": "^5.5.9|>=7.0.8" + }, + "conflict": { + "symfony/dependency-injection": "<3.3" + }, + "require-dev": { + "psr/log": "~1.0", + "symfony/config": "~2.8|~3.0|~4.0", + "symfony/dependency-injection": "~3.3|~4.0", + "symfony/expression-language": "~2.8|~3.0|~4.0", + "symfony/stopwatch": "~2.8|~3.0|~4.0" + }, + "suggest": { + "symfony/dependency-injection": "", + "symfony/http-kernel": "" + }, + "time": "2018-04-06T07:35:25+00:00", + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.4-dev" + } + }, + "installation-source": "dist", + "autoload": { + "psr-4": { + "Symfony\\Component\\EventDispatcher\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony EventDispatcher Component", + "homepage": "https://symfony.com" + }, + { + "name": "symfony/finder", + "version": "v3.4.12", + "version_normalized": "3.4.12.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/finder.git", + "reference": "3a8c3de91d2b2c68cd2d665cf9d00f7ef9eaa394" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/finder/zipball/3a8c3de91d2b2c68cd2d665cf9d00f7ef9eaa394", + "reference": "3a8c3de91d2b2c68cd2d665cf9d00f7ef9eaa394", + "shasum": "" + }, + "require": { + "php": "^5.5.9|>=7.0.8" + }, + "time": "2018-06-19T20:52:10+00:00", + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.4-dev" + } + }, + "installation-source": "dist", + "autoload": { + "psr-4": { + "Symfony\\Component\\Finder\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony Finder Component", + "homepage": "https://symfony.com" + }, + { + "name": "symfony/http-foundation", + "version": "v3.4.12", + "version_normalized": "3.4.12.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/http-foundation.git", + "reference": "1c28679fcbb0d9b35e4fd49fbb74d2ca4ea17bce" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/http-foundation/zipball/1c28679fcbb0d9b35e4fd49fbb74d2ca4ea17bce", + "reference": "1c28679fcbb0d9b35e4fd49fbb74d2ca4ea17bce", + "shasum": "" + }, + "require": { + "php": "^5.5.9|>=7.0.8", + "symfony/polyfill-mbstring": "~1.1", + "symfony/polyfill-php70": "~1.6" + }, + "require-dev": { + "symfony/expression-language": "~2.8|~3.0|~4.0" + }, + "time": "2018-06-21T11:10:19+00:00", + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.4-dev" + } + }, + "installation-source": "dist", + "autoload": { + "psr-4": { + "Symfony\\Component\\HttpFoundation\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony HttpFoundation Component", + "homepage": "https://symfony.com" + }, + { + "name": "symfony/http-kernel", + "version": "v3.4.12", + "version_normalized": "3.4.12.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/http-kernel.git", + "reference": "cb7edcdc47cab3c61c891e6e55337f8dd470d820" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/http-kernel/zipball/cb7edcdc47cab3c61c891e6e55337f8dd470d820", + "reference": "cb7edcdc47cab3c61c891e6e55337f8dd470d820", + "shasum": "" + }, + "require": { + "php": "^5.5.9|>=7.0.8", + "psr/log": "~1.0", + "symfony/debug": "~2.8|~3.0|~4.0", + "symfony/event-dispatcher": "~2.8|~3.0|~4.0", + "symfony/http-foundation": "~3.4.12|~4.0.12|^4.1.1", + "symfony/polyfill-ctype": "~1.8" + }, + "conflict": { + "symfony/config": "<2.8", + "symfony/dependency-injection": "<3.4.5|<4.0.5,>=4", + "symfony/var-dumper": "<3.3", + "twig/twig": "<1.34|<2.4,>=2" + }, + "provide": { + "psr/log-implementation": "1.0" + }, + "require-dev": { + "psr/cache": "~1.0", + "symfony/browser-kit": "~2.8|~3.0|~4.0", + "symfony/class-loader": "~2.8|~3.0", + "symfony/config": "~2.8|~3.0|~4.0", + "symfony/console": "~2.8|~3.0|~4.0", + "symfony/css-selector": "~2.8|~3.0|~4.0", + "symfony/dependency-injection": "^3.4.5|^4.0.5", + "symfony/dom-crawler": "~2.8|~3.0|~4.0", + "symfony/expression-language": "~2.8|~3.0|~4.0", + "symfony/finder": "~2.8|~3.0|~4.0", + "symfony/process": "~2.8|~3.0|~4.0", + "symfony/routing": "~3.4|~4.0", + "symfony/stopwatch": "~2.8|~3.0|~4.0", + "symfony/templating": "~2.8|~3.0|~4.0", + "symfony/translation": "~2.8|~3.0|~4.0", + "symfony/var-dumper": "~3.3|~4.0" + }, + "suggest": { + "symfony/browser-kit": "", + "symfony/config": "", + "symfony/console": "", + "symfony/dependency-injection": "", + "symfony/finder": "", + "symfony/var-dumper": "" + }, + "time": "2018-06-25T12:29:19+00:00", + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.4-dev" + } + }, + "installation-source": "dist", + "autoload": { + "psr-4": { + "Symfony\\Component\\HttpKernel\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony HttpKernel Component", + "homepage": "https://symfony.com" + }, + { + "name": "symfony/phpunit-bridge", + "version": "v3.4.12", + "version_normalized": "3.4.12.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/phpunit-bridge.git", + "reference": "8a21eb6bedad38bf1f15d529c65eb9e17d0242fd" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/phpunit-bridge/zipball/8a21eb6bedad38bf1f15d529c65eb9e17d0242fd", + "reference": "8a21eb6bedad38bf1f15d529c65eb9e17d0242fd", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "conflict": { + "phpunit/phpunit": "<4.8.35|<5.4.3,>=5.0" + }, + "suggest": { + "ext-zip": "Zip support is required when using bin/simple-phpunit", + "symfony/debug": "For tracking deprecated interfaces usages at runtime with DebugClassLoader" + }, + "time": "2018-06-10T07:25:02+00:00", + "bin": [ + "bin/simple-phpunit" + ], + "type": "symfony-bridge", + "extra": { + "branch-alias": { + "dev-master": "3.4-dev" + }, + "thanks": { + "name": "phpunit/phpunit", + "url": "https://github.com/sebastianbergmann/phpunit" + } + }, + "installation-source": "dist", + "autoload": { + "files": [ + "bootstrap.php" + ], + "psr-4": { + "Symfony\\Bridge\\PhpUnit\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony PHPUnit Bridge", + "homepage": "https://symfony.com" + }, + { + "name": "symfony/polyfill-ctype", + "version": "v1.8.0", + "version_normalized": "1.8.0.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-ctype.git", + "reference": "7cc359f1b7b80fc25ed7796be7d96adc9b354bae" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/7cc359f1b7b80fc25ed7796be7d96adc9b354bae", + "reference": "7cc359f1b7b80fc25ed7796be7d96adc9b354bae", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "time": "2018-04-30T19:57:29+00:00", + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.8-dev" + } + }, + "installation-source": "dist", + "autoload": { + "psr-4": { + "Symfony\\Polyfill\\Ctype\\": "" + }, + "files": [ + "bootstrap.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + }, + { + "name": "Gert de Pagter", + "email": "BackEndTea@gmail.com" + } + ], + "description": "Symfony polyfill for ctype functions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "ctype", + "polyfill", + "portable" + ] + }, + { + "name": "symfony/polyfill-iconv", + "version": "v1.8.0", + "version_normalized": "1.8.0.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-iconv.git", + "reference": "7cb8436a814d5b0fcf292810ee26f8b0cb47584d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-iconv/zipball/7cb8436a814d5b0fcf292810ee26f8b0cb47584d", + "reference": "7cb8436a814d5b0fcf292810ee26f8b0cb47584d", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "suggest": { + "ext-iconv": "For best performance" + }, + "time": "2018-04-26T10:06:28+00:00", + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.8-dev" + } + }, + "installation-source": "dist", + "autoload": { + "psr-4": { + "Symfony\\Polyfill\\Iconv\\": "" + }, + "files": [ + "bootstrap.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill for the Iconv extension", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "iconv", + "polyfill", + "portable", + "shim" + ] + }, + { + "name": "symfony/polyfill-mbstring", + "version": "v1.8.0", + "version_normalized": "1.8.0.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-mbstring.git", + "reference": "3296adf6a6454a050679cde90f95350ad604b171" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/3296adf6a6454a050679cde90f95350ad604b171", + "reference": "3296adf6a6454a050679cde90f95350ad604b171", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "suggest": { + "ext-mbstring": "For best performance" + }, + "time": "2018-04-26T10:06:28+00:00", + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.8-dev" + } + }, + "installation-source": "dist", + "autoload": { + "psr-4": { + "Symfony\\Polyfill\\Mbstring\\": "" + }, + "files": [ + "bootstrap.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill for the Mbstring extension", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "mbstring", + "polyfill", + "portable", + "shim" + ] + }, + { + "name": "symfony/polyfill-php70", + "version": "v1.8.0", + "version_normalized": "1.8.0.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-php70.git", + "reference": "77454693d8f10dd23bb24955cffd2d82db1007a6" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-php70/zipball/77454693d8f10dd23bb24955cffd2d82db1007a6", + "reference": "77454693d8f10dd23bb24955cffd2d82db1007a6", + "shasum": "" + }, + "require": { + "paragonie/random_compat": "~1.0|~2.0", + "php": ">=5.3.3" + }, + "time": "2018-04-26T10:06:28+00:00", + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.8-dev" + } + }, + "installation-source": "dist", + "autoload": { + "psr-4": { + "Symfony\\Polyfill\\Php70\\": "" + }, + "files": [ + "bootstrap.php" + ], + "classmap": [ + "Resources/stubs" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill backporting some PHP 7.0+ features to lower PHP versions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "polyfill", + "portable", + "shim" + ] + }, + { + "name": "symfony/process", + "version": "v3.4.12", + "version_normalized": "3.4.12.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/process.git", + "reference": "acc5a37c706ace827962851b69705b24e71ca17c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/process/zipball/acc5a37c706ace827962851b69705b24e71ca17c", + "reference": "acc5a37c706ace827962851b69705b24e71ca17c", + "shasum": "" + }, + "require": { + "php": "^5.5.9|>=7.0.8" + }, + "time": "2018-05-30T04:24:30+00:00", + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.4-dev" + } + }, + "installation-source": "dist", + "autoload": { + "psr-4": { + "Symfony\\Component\\Process\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony Process Component", + "homepage": "https://symfony.com" + }, + { + "name": "symfony/psr-http-message-bridge", + "version": "v1.0.2", + "version_normalized": "1.0.2.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/psr-http-message-bridge.git", + "reference": "c2b757934f2d9681a287e662efbc27c41fe8ef86" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/psr-http-message-bridge/zipball/c2b757934f2d9681a287e662efbc27c41fe8ef86", + "reference": "c2b757934f2d9681a287e662efbc27c41fe8ef86", + "shasum": "" + }, + "require": { + "php": ">=5.3.3", + "psr/http-message": "~1.0", + "symfony/http-foundation": "~2.3|~3.0|~4.0" + }, + "require-dev": { + "symfony/phpunit-bridge": "~3.2|4.0" + }, + "suggest": { + "psr/http-message-implementation": "To use the HttpFoundation factory", + "zendframework/zend-diactoros": "To use the Zend Diactoros factory" + }, + "time": "2017-12-19T00:31:44+00:00", + "type": "symfony-bridge", + "extra": { + "branch-alias": { + "dev-master": "1.0-dev" + } + }, + "installation-source": "dist", + "autoload": { + "psr-4": { + "Symfony\\Bridge\\PsrHttpMessage\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Symfony Community", + "homepage": "http://symfony.com/contributors" + }, + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + } + ], + "description": "PSR HTTP message bridge", + "homepage": "http://symfony.com", + "keywords": [ + "http", + "http-message", + "psr-7" + ] + }, + { + "name": "symfony/routing", + "version": "v3.4.12", + "version_normalized": "3.4.12.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/routing.git", + "reference": "6b9fef5343828e542db17e2519722ef08992f2c1" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/routing/zipball/6b9fef5343828e542db17e2519722ef08992f2c1", + "reference": "6b9fef5343828e542db17e2519722ef08992f2c1", + "shasum": "" + }, + "require": { + "php": "^5.5.9|>=7.0.8" + }, + "conflict": { + "symfony/config": "<3.3.1", + "symfony/dependency-injection": "<3.3", + "symfony/yaml": "<3.4" + }, + "require-dev": { + "doctrine/annotations": "~1.0", + "psr/log": "~1.0", + "symfony/config": "^3.3.1|~4.0", + "symfony/dependency-injection": "~3.3|~4.0", + "symfony/expression-language": "~2.8|~3.0|~4.0", + "symfony/http-foundation": "~2.8|~3.0|~4.0", + "symfony/yaml": "~3.4|~4.0" + }, + "suggest": { + "doctrine/annotations": "For using the annotation loader", + "symfony/config": "For using the all-in-one router or any loader", + "symfony/dependency-injection": "For loading routes from a service", + "symfony/expression-language": "For using expression matching", + "symfony/http-foundation": "For using a Symfony Request object", + "symfony/yaml": "For using the YAML loader" + }, + "time": "2018-06-19T20:52:10+00:00", + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.4-dev" + } + }, + "installation-source": "dist", + "autoload": { + "psr-4": { + "Symfony\\Component\\Routing\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony Routing Component", + "homepage": "https://symfony.com", + "keywords": [ + "router", + "routing", + "uri", + "url" + ] + }, + { + "name": "symfony/serializer", + "version": "v3.4.12", + "version_normalized": "3.4.12.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/serializer.git", + "reference": "2e6d57dbbb37691f1480393440aff3a4b69dd9f7" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/serializer/zipball/2e6d57dbbb37691f1480393440aff3a4b69dd9f7", + "reference": "2e6d57dbbb37691f1480393440aff3a4b69dd9f7", + "shasum": "" + }, + "require": { + "php": "^5.5.9|>=7.0.8", + "symfony/polyfill-ctype": "~1.8" + }, + "conflict": { + "phpdocumentor/type-resolver": "<0.2.1", + "symfony/dependency-injection": "<3.2", + "symfony/property-access": ">=3.0,<3.0.4|>=2.8,<2.8.4", + "symfony/property-info": "<3.1", + "symfony/yaml": "<3.4" + }, + "require-dev": { + "doctrine/annotations": "~1.0", + "doctrine/cache": "~1.0", + "phpdocumentor/reflection-docblock": "^3.0|^4.0", + "symfony/cache": "~3.1|~4.0", + "symfony/config": "~2.8|~3.0|~4.0", + "symfony/dependency-injection": "~3.2|~4.0", + "symfony/http-foundation": "~2.8|~3.0|~4.0", + "symfony/property-access": "~2.8|~3.0|~4.0", + "symfony/property-info": "~3.1|~4.0", + "symfony/yaml": "~3.4|~4.0" + }, + "suggest": { + "doctrine/annotations": "For using the annotation mapping. You will also need doctrine/cache.", + "doctrine/cache": "For using the default cached annotation reader and metadata cache.", + "psr/cache-implementation": "For using the metadata cache.", + "symfony/config": "For using the XML mapping loader.", + "symfony/http-foundation": "To use the DataUriNormalizer.", + "symfony/property-access": "For using the ObjectNormalizer.", + "symfony/property-info": "To deserialize relations.", + "symfony/yaml": "For using the default YAML mapping loader." + }, + "time": "2018-06-22T08:58:39+00:00", + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.4-dev" + } + }, + "installation-source": "dist", + "autoload": { + "psr-4": { + "Symfony\\Component\\Serializer\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony Serializer Component", + "homepage": "https://symfony.com" + }, + { + "name": "symfony/translation", + "version": "v3.4.12", + "version_normalized": "3.4.12.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/translation.git", + "reference": "7047f725e35eab768137c677f8c38e4a2a8e38fb" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/translation/zipball/7047f725e35eab768137c677f8c38e4a2a8e38fb", + "reference": "7047f725e35eab768137c677f8c38e4a2a8e38fb", + "shasum": "" + }, + "require": { + "php": "^5.5.9|>=7.0.8", + "symfony/polyfill-mbstring": "~1.0" + }, + "conflict": { + "symfony/config": "<2.8", + "symfony/dependency-injection": "<3.4", + "symfony/yaml": "<3.4" + }, + "require-dev": { + "psr/log": "~1.0", + "symfony/config": "~2.8|~3.0|~4.0", + "symfony/dependency-injection": "~3.4|~4.0", + "symfony/finder": "~2.8|~3.0|~4.0", + "symfony/intl": "^2.8.18|^3.2.5|~4.0", + "symfony/yaml": "~3.4|~4.0" + }, + "suggest": { + "psr/log-implementation": "To use logging capability in translator", + "symfony/config": "", + "symfony/yaml": "" + }, + "time": "2018-05-21T10:06:52+00:00", + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.4-dev" + } + }, + "installation-source": "dist", + "autoload": { + "psr-4": { + "Symfony\\Component\\Translation\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony Translation Component", + "homepage": "https://symfony.com" + }, + { + "name": "symfony/validator", + "version": "v3.4.12", + "version_normalized": "3.4.12.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/validator.git", + "reference": "fca490df65008eb680c5ee9c2d521191c9e54ed5" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/validator/zipball/fca490df65008eb680c5ee9c2d521191c9e54ed5", + "reference": "fca490df65008eb680c5ee9c2d521191c9e54ed5", + "shasum": "" + }, + "require": { + "php": "^5.5.9|>=7.0.8", + "symfony/polyfill-ctype": "~1.8", + "symfony/polyfill-mbstring": "~1.0", + "symfony/translation": "~2.8|~3.0|~4.0" + }, + "conflict": { + "phpunit/phpunit": "<4.8.35|<5.4.3,>=5.0", + "symfony/dependency-injection": "<3.3", + "symfony/http-kernel": "<3.3.5", + "symfony/yaml": "<3.4" + }, + "require-dev": { + "doctrine/annotations": "~1.0", + "doctrine/cache": "~1.0", + "egulias/email-validator": "^1.2.8|~2.0", + "symfony/cache": "~3.1|~4.0", + "symfony/config": "~2.8|~3.0|~4.0", + "symfony/dependency-injection": "~3.3|~4.0", + "symfony/expression-language": "~2.8|~3.0|~4.0", + "symfony/http-foundation": "~2.8|~3.0|~4.0", + "symfony/http-kernel": "^3.3.5|~4.0", + "symfony/intl": "^2.8.18|^3.2.5|~4.0", + "symfony/property-access": "~2.8|~3.0|~4.0", + "symfony/var-dumper": "~3.3|~4.0", + "symfony/yaml": "~3.4|~4.0" + }, + "suggest": { + "doctrine/annotations": "For using the annotation mapping. You will also need doctrine/cache.", + "doctrine/cache": "For using the default cached annotation reader and metadata cache.", + "egulias/email-validator": "Strict (RFC compliant) email validation", + "psr/cache-implementation": "For using the metadata cache.", + "symfony/config": "", + "symfony/expression-language": "For using the Expression validator", + "symfony/http-foundation": "", + "symfony/intl": "", + "symfony/property-access": "For accessing properties within comparison constraints", + "symfony/yaml": "" + }, + "time": "2018-06-19T20:52:10+00:00", + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.4-dev" + } + }, + "installation-source": "dist", + "autoload": { + "psr-4": { + "Symfony\\Component\\Validator\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony Validator Component", + "homepage": "https://symfony.com" + }, + { + "name": "symfony/var-dumper", + "version": "v3.4.12", + "version_normalized": "3.4.12.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/var-dumper.git", + "reference": "e173954a28a44a32c690815fbe4d0f2eac43accb" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/var-dumper/zipball/e173954a28a44a32c690815fbe4d0f2eac43accb", + "reference": "e173954a28a44a32c690815fbe4d0f2eac43accb", + "shasum": "" + }, + "require": { + "php": "^5.5.9|>=7.0.8", + "symfony/polyfill-mbstring": "~1.0" + }, + "conflict": { + "phpunit/phpunit": "<4.8.35|<5.4.3,>=5.0" + }, + "require-dev": { + "ext-iconv": "*", + "twig/twig": "~1.34|~2.4" + }, + "suggest": { + "ext-iconv": "To convert non-UTF-8 strings to UTF-8 (or symfony/polyfill-iconv in case ext-iconv cannot be used).", + "ext-intl": "To show region name in time zone dump", + "ext-symfony_debug": "" + }, + "time": "2018-06-15T07:47:49+00:00", + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.4-dev" + } + }, + "installation-source": "dist", + "autoload": { + "files": [ + "Resources/functions/dump.php" + ], + "psr-4": { + "Symfony\\Component\\VarDumper\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony mechanism for exploring and dumping PHP variables", + "homepage": "https://symfony.com", + "keywords": [ + "debug", + "dump" + ] + }, + { + "name": "symfony/yaml", + "version": "v3.4.12", + "version_normalized": "3.4.12.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/yaml.git", + "reference": "c5010cc1692ce1fa328b1fb666961eb3d4a85bb0" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/yaml/zipball/c5010cc1692ce1fa328b1fb666961eb3d4a85bb0", + "reference": "c5010cc1692ce1fa328b1fb666961eb3d4a85bb0", + "shasum": "" + }, + "require": { + "php": "^5.5.9|>=7.0.8", + "symfony/polyfill-ctype": "~1.8" + }, + "conflict": { + "symfony/console": "<3.4" + }, + "require-dev": { + "symfony/console": "~3.4|~4.0" + }, + "suggest": { + "symfony/console": "For validating YAML files using the lint command" + }, + "time": "2018-05-03T23:18:14+00:00", + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.4-dev" + } + }, + "installation-source": "dist", + "autoload": { + "psr-4": { + "Symfony\\Component\\Yaml\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony Yaml Component", + "homepage": "https://symfony.com" + }, + { + "name": "theseer/tokenizer", + "version": "1.1.0", + "version_normalized": "1.1.0.0", + "source": { + "type": "git", + "url": "https://github.com/theseer/tokenizer.git", + "reference": "cb2f008f3f05af2893a87208fe6a6c4985483f8b" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/theseer/tokenizer/zipball/cb2f008f3f05af2893a87208fe6a6c4985483f8b", + "reference": "cb2f008f3f05af2893a87208fe6a6c4985483f8b", + "shasum": "" + }, + "require": { + "ext-dom": "*", + "ext-tokenizer": "*", + "ext-xmlwriter": "*", + "php": "^7.0" + }, + "time": "2017-04-07T12:08:54+00:00", + "type": "library", + "installation-source": "dist", + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Arne Blankerts", + "email": "arne@blankerts.de", + "role": "Developer" + } + ], + "description": "A small library for converting tokenized PHP source code into XML and potentially other formats" + }, + { + "name": "twig/twig", + "version": "v1.35.3", + "version_normalized": "1.35.3.0", + "source": { + "type": "git", + "url": "https://github.com/twigphp/Twig.git", + "reference": "b48680b6eb7d16b5025b9bfc4108d86f6b8af86f" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/twigphp/Twig/zipball/b48680b6eb7d16b5025b9bfc4108d86f6b8af86f", + "reference": "b48680b6eb7d16b5025b9bfc4108d86f6b8af86f", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "require-dev": { + "psr/container": "^1.0", + "symfony/debug": "^2.7", + "symfony/phpunit-bridge": "^3.3" + }, + "time": "2018-03-20T04:25:58+00:00", + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.35-dev" + } + }, + "installation-source": "dist", + "autoload": { + "psr-0": { + "Twig_": "lib/" + }, + "psr-4": { + "Twig\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com", + "homepage": "http://fabien.potencier.org", + "role": "Lead Developer" + }, + { + "name": "Armin Ronacher", + "email": "armin.ronacher@active-4.com", + "role": "Project Founder" + }, + { + "name": "Twig Team", + "homepage": "http://twig.sensiolabs.org/contributors", + "role": "Contributors" + } + ], + "description": "Twig, the flexible, fast, and secure template language for PHP", + "homepage": "http://twig.sensiolabs.org", + "keywords": [ + "templating" + ] + }, + { + "name": "webmozart/assert", + "version": "1.3.0", + "version_normalized": "1.3.0.0", + "source": { + "type": "git", + "url": "https://github.com/webmozart/assert.git", + "reference": "0df1908962e7a3071564e857d86874dad1ef204a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/webmozart/assert/zipball/0df1908962e7a3071564e857d86874dad1ef204a", + "reference": "0df1908962e7a3071564e857d86874dad1ef204a", + "shasum": "" + }, + "require": { + "php": "^5.3.3 || ^7.0" + }, + "require-dev": { + "phpunit/phpunit": "^4.6", + "sebastian/version": "^1.0.1" + }, + "time": "2018-01-29T19:49:41+00:00", + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.3-dev" + } + }, + "installation-source": "dist", + "autoload": { + "psr-4": { + "Webmozart\\Assert\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Bernhard Schussek", + "email": "bschussek@gmail.com" + } + ], + "description": "Assertions to validate method input/output with nice error messages.", + "keywords": [ + "assert", + "check", + "validate" + ] + }, + { + "name": "webmozart/path-util", + "version": "2.3.0", + "version_normalized": "2.3.0.0", + "source": { + "type": "git", + "url": "https://github.com/webmozart/path-util.git", + "reference": "d939f7edc24c9a1bb9c0dee5cb05d8e859490725" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/webmozart/path-util/zipball/d939f7edc24c9a1bb9c0dee5cb05d8e859490725", + "reference": "d939f7edc24c9a1bb9c0dee5cb05d8e859490725", + "shasum": "" + }, + "require": { + "php": ">=5.3.3", + "webmozart/assert": "~1.0" + }, + "require-dev": { + "phpunit/phpunit": "^4.6", + "sebastian/version": "^1.0.1" + }, + "time": "2015-12-17T08:42:14+00:00", + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.3-dev" + } + }, + "installation-source": "dist", + "autoload": { + "psr-4": { + "Webmozart\\PathUtil\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Bernhard Schussek", + "email": "bschussek@gmail.com" + } + ], + "description": "A robust cross-platform utility for normalizing, comparing and modifying file paths." + }, + { + "name": "wikimedia/composer-merge-plugin", + "version": "v1.4.1", + "version_normalized": "1.4.1.0", + "source": { + "type": "git", + "url": "https://github.com/wikimedia/composer-merge-plugin.git", + "reference": "81c6ac72a24a67383419c7eb9aa2b3437f2ab100" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/wikimedia/composer-merge-plugin/zipball/81c6ac72a24a67383419c7eb9aa2b3437f2ab100", + "reference": "81c6ac72a24a67383419c7eb9aa2b3437f2ab100", + "shasum": "" + }, + "require": { + "composer-plugin-api": "^1.0", + "php": ">=5.3.2" + }, + "require-dev": { + "composer/composer": "~1.0.0", + "jakub-onderka/php-parallel-lint": "~0.8", + "phpunit/phpunit": "~4.8|~5.0", + "squizlabs/php_codesniffer": "~2.1.0" + }, + "time": "2017-04-25T02:31:25+00:00", + "type": "composer-plugin", + "extra": { + "branch-alias": { + "dev-master": "1.3.x-dev" + }, + "class": "Wikimedia\\Composer\\MergePlugin" + }, + "installation-source": "dist", + "autoload": { + "psr-4": { + "Wikimedia\\Composer\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Bryan Davis", + "email": "bd808@wikimedia.org" + } + ], + "description": "Composer plugin to merge multiple composer.json files" + }, + { + "name": "zendframework/zend-diactoros", + "version": "1.8.1", + "version_normalized": "1.8.1.0", + "source": { + "type": "git", + "url": "https://github.com/zendframework/zend-diactoros.git", + "reference": "63d920d1c9ebc009d860c3666593a66298727dd6" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/zendframework/zend-diactoros/zipball/63d920d1c9ebc009d860c3666593a66298727dd6", + "reference": "63d920d1c9ebc009d860c3666593a66298727dd6", + "shasum": "" + }, + "require": { + "php": "^5.6 || ^7.0", + "psr/http-message": "^1.0" + }, + "provide": { + "psr/http-message-implementation": "1.0" + }, + "require-dev": { + "ext-dom": "*", + "ext-libxml": "*", + "phpunit/phpunit": "^5.7.16 || ^6.0.8", + "zendframework/zend-coding-standard": "~1.0" + }, + "time": "2018-07-09T21:17:27+00:00", + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.8.x-dev", + "dev-develop": "1.9.x-dev", + "dev-release-2.0": "2.0.x-dev" + } + }, + "installation-source": "dist", + "autoload": { + "files": [ + "src/functions/create_uploaded_file.php", + "src/functions/marshal_headers_from_sapi.php", + "src/functions/marshal_method_from_sapi.php", + "src/functions/marshal_protocol_version_from_sapi.php", + "src/functions/marshal_uri_from_sapi.php", + "src/functions/normalize_server.php", + "src/functions/normalize_uploaded_files.php", + "src/functions/parse_cookie_header.php" + ], + "psr-4": { + "Zend\\Diactoros\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-2-Clause" + ], + "description": "PSR HTTP Message implementations", + "homepage": "https://github.com/zendframework/zend-diactoros", + "keywords": [ + "http", + "psr", + "psr-7" + ] + }, + { + "name": "zendframework/zend-escaper", + "version": "2.6.0", + "version_normalized": "2.6.0.0", + "source": { + "type": "git", + "url": "https://github.com/zendframework/zend-escaper.git", + "reference": "31d8aafae982f9568287cb4dce987e6aff8fd074" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/zendframework/zend-escaper/zipball/31d8aafae982f9568287cb4dce987e6aff8fd074", + "reference": "31d8aafae982f9568287cb4dce987e6aff8fd074", + "shasum": "" + }, + "require": { + "php": "^5.6 || ^7.0" + }, + "require-dev": { + "phpunit/phpunit": "^5.7.27 || ^6.5.8 || ^7.1.2", + "zendframework/zend-coding-standard": "~1.0.0" + }, + "time": "2018-04-25T15:48:53+00:00", + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.6.x-dev", + "dev-develop": "2.7.x-dev" + } + }, + "installation-source": "dist", + "autoload": { + "psr-4": { + "Zend\\Escaper\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "description": "Securely and safely escape HTML, HTML attributes, JavaScript, CSS, and URLs", + "keywords": [ + "ZendFramework", + "escaper", + "zf" + ] + }, + { + "name": "zendframework/zend-feed", + "version": "2.10.2", + "version_normalized": "2.10.2.0", + "source": { + "type": "git", + "url": "https://github.com/zendframework/zend-feed.git", + "reference": "5253f949f4ad999086ab9b408908b6c6776f24db" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/zendframework/zend-feed/zipball/5253f949f4ad999086ab9b408908b6c6776f24db", + "reference": "5253f949f4ad999086ab9b408908b6c6776f24db", + "shasum": "" + }, + "require": { + "php": "^5.6 || ^7.0", + "zendframework/zend-escaper": "^2.5.2", + "zendframework/zend-stdlib": "^2.7.7 || ^3.1" + }, + "require-dev": { + "phpunit/phpunit": "^5.7.23 || ^6.4.3", + "psr/http-message": "^1.0.1", + "zendframework/zend-cache": "^2.7.2", + "zendframework/zend-coding-standard": "~1.0.0", + "zendframework/zend-db": "^2.8.2", + "zendframework/zend-http": "^2.7", + "zendframework/zend-servicemanager": "^2.7.8 || ^3.3", + "zendframework/zend-validator": "^2.10.1" + }, + "suggest": { + "psr/http-message": "PSR-7 ^1.0.1, if you wish to use Zend\\Feed\\Reader\\Http\\Psr7ResponseDecorator", + "zendframework/zend-cache": "Zend\\Cache component, for optionally caching feeds between requests", + "zendframework/zend-db": "Zend\\Db component, for use with PubSubHubbub", + "zendframework/zend-http": "Zend\\Http for PubSubHubbub, and optionally for use with Zend\\Feed\\Reader", + "zendframework/zend-servicemanager": "Zend\\ServiceManager component, for easily extending ExtensionManager implementations", + "zendframework/zend-validator": "Zend\\Validator component, for validating email addresses used in Atom feeds and entries when using the Writer subcomponent" + }, + "time": "2018-06-18T20:14:01+00:00", + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.10.x-dev", + "dev-develop": "2.11.x-dev" + } + }, + "installation-source": "dist", + "autoload": { + "psr-4": { + "Zend\\Feed\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "description": "provides functionality for consuming RSS and Atom feeds", + "keywords": [ + "ZendFramework", + "feed", + "zf" + ] + }, + { + "name": "zendframework/zend-stdlib", + "version": "3.2.0", + "version_normalized": "3.2.0.0", + "source": { + "type": "git", + "url": "https://github.com/zendframework/zend-stdlib.git", + "reference": "cd164b4a18b5d1aeb69be2c26db035b5ed6925ae" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/zendframework/zend-stdlib/zipball/cd164b4a18b5d1aeb69be2c26db035b5ed6925ae", + "reference": "cd164b4a18b5d1aeb69be2c26db035b5ed6925ae", + "shasum": "" + }, + "require": { + "php": "^5.6 || ^7.0" + }, + "require-dev": { + "phpbench/phpbench": "^0.13", + "phpunit/phpunit": "^5.7.27 || ^6.5.8 || ^7.1.2", + "zendframework/zend-coding-standard": "~1.0.0" + }, + "time": "2018-04-30T13:50:40+00:00", + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.2.x-dev", + "dev-develop": "3.3.x-dev" + } + }, + "installation-source": "dist", + "autoload": { + "psr-4": { + "Zend\\Stdlib\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "description": "SPL extensions, array utilities, error handlers, and more", + "keywords": [ + "ZendFramework", + "stdlib", + "zf" + ] } ] diff -r e200cb7efeb3 -r c2387f117808 vendor/consolidation/annotated-command/.github/issue_template.md --- a/vendor/consolidation/annotated-command/.github/issue_template.md Thu Apr 26 11:26:54 2018 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,11 +0,0 @@ -### Steps to reproduce -What did you do? - -### Expected behavior -Tell us what should happen - -### Actual behavior -Tell us what happens instead - -### System Configuration -Which O.S. and PHP version are you using? diff -r e200cb7efeb3 -r c2387f117808 vendor/consolidation/annotated-command/.github/pull_request_template.md --- a/vendor/consolidation/annotated-command/.github/pull_request_template.md Thu Apr 26 11:26:54 2018 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,13 +0,0 @@ -### Disposition -This pull request: - -- [ ] Fixes a bug -- [ ] Adds a feature -- [ ] Breaks backwards compatibility -- [ ] Has tests that cover changes - -### Summary -Short overview of what changed. - -### Description -Any additional information. diff -r e200cb7efeb3 -r c2387f117808 vendor/consolidation/annotated-command/.gitignore --- a/vendor/consolidation/annotated-command/.gitignore Thu Apr 26 11:26:54 2018 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,5 +0,0 @@ -.DS_Store -phpunit.xml -vendor -build -.idea diff -r e200cb7efeb3 -r c2387f117808 vendor/consolidation/annotated-command/.travis.yml --- a/vendor/consolidation/annotated-command/.travis.yml Thu Apr 26 11:26:54 2018 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,87 +0,0 @@ -language: php - -branches: - # Only test the master branch and SemVer tags. - only: - - master - - '/^[[:digit:]]+\.[[:digit:]]+\.[[:digit:]]+.*$/' - -matrix: - include: - - php: 7.2 - env: 'SCENARIO=symfony4 HIGHEST_LOWEST="update"' - - php: 7.1 - env: 'SCENARIO=symfony4' - - php: 7.0.11 - env: 'HIGHEST_LOWEST="update"' - - php: 7.0.11 - - php: 5.6 - - php: 5.5 - - php: 5.4 - env: 'SCENARIO=symfony2 HIGHEST_LOWEST="update --prefer-lowest' - -sudo: false - -cache: - directories: - - vendor - - $HOME/.composer/cache - -install: - - 'scenarios/install "${SCENARIO}" "${HIGHEST_LOWEST-install}"' - -script: - - composer test - -after_success: - - 'travis_retry php vendor/bin/coveralls -v' - - | - # Only do post-build actions in one environment, and only if there is a GITHUB token. - if [ -z "$DO_POST_BUILD_ACTIONS" ] ; then - return - fi - if [ -z "$GITHUB_TOKEN" ]; then - echo "No GITHUB_TOKEN defined; exiting." - return - fi - ### - # Run composer lock update on cron jobs. - # See: https://github.com/danielbachhuber/composer-lock-updater - ### - if [ "$TRAVIS_EVENT_TYPE" != "cron" ] ; then - echo "Not a cron job; exiting." - return - fi - ### - # Only run on one job of a master branch build - ### - if [ "master" != "$TRAVIS_BRANCH" ] ; then - echo "composer.lock update only runs on the master branch." - return - fi - ### - # Install composer-lock-updater - ### - export PATH="$HOME/.composer/vendor/bin:$PATH" - composer global require danielbachhuber/composer-lock-updater - ### - # Optional: install Sensio Labs security checker to include security advisories in PR comments - ### - mkdir -p $HOME/bin - wget -O $HOME/bin/security-checker.phar http://get.sensiolabs.org/security-checker.phar - chmod +x $HOME/bin/security-checker.phar - export PATH="$HOME/bin:$PATH" - ### - # Install hub for creating GitHub pull requests - ### - wget -O hub.tgz https://github.com/github/hub/releases/download/v2.2.9/hub-linux-amd64-2.2.9.tgz - tar -zxvf hub.tgz - export PATH=$PATH:$PWD/hub-linux-amd64-2.2.9/bin/ - ### - # Run composer-lock-updater - ### - clu - - - - diff -r e200cb7efeb3 -r c2387f117808 vendor/consolidation/annotated-command/LICENSE --- a/vendor/consolidation/annotated-command/LICENSE Thu Apr 26 11:26:54 2018 +0100 +++ b/vendor/consolidation/annotated-command/LICENSE Tue Jul 10 15:07:59 2018 +0100 @@ -1,4 +1,6 @@ -Copyright (c) 2016 Consolidation Org Developers +The MIT License (MIT) + +Copyright (c) 2016-2018 Consolidation Org Developers Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: @@ -6,3 +8,14 @@ The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +DEPENDENCY LICENSES: + +Name Version License +consolidation/output-formatters 3.2.0 MIT +psr/log 1.0.2 MIT +symfony/console v3.4.11 MIT +symfony/debug v3.4.11 MIT +symfony/event-dispatcher v3.4.11 MIT +symfony/finder v3.4.11 MIT +symfony/polyfill-mbstring v1.8.0 MIT diff -r e200cb7efeb3 -r c2387f117808 vendor/consolidation/annotated-command/appveyor.yml --- a/vendor/consolidation/annotated-command/appveyor.yml Thu Apr 26 11:26:54 2018 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,66 +0,0 @@ -build: false -shallow_clone: true -platform: 'x86' -clone_folder: C:\projects\annotated-commands -branches: - only: - - master - -## Cache composer bits -cache: - - '%LOCALAPPDATA%\Composer\files -> composer.lock' - -init: - #https://github.com/composer/composer/blob/master/appveyor.yml - #- SET ANSICON=121x90 (121x90) - -# Inspired by https://github.com/Codeception/base/blob/master/appveyor.yml and https://github.com/phpmd/phpmd/blob/master/appveyor.yml -install: - - cinst -y curl - - SET PATH=C:\Program Files\curl;%PATH% - #which is only needed by the test suite. - - cinst -y which - - SET PATH=C:\Program Files\which;%PATH% - - git clone -q https://github.com/acquia/DevDesktopCommon.git #For tar, cksum, ... - - SET PATH=%APPVEYOR_BUILD_FOLDER%/DevDesktopCommon/bintools-win/msys/bin;%PATH% - - SET PATH=C:\Program Files\MySql\MySQL Server 5.7\bin\;%PATH% - #Install PHP per https://blog.wyrihaximus.net/2016/11/running-php-unit-tests-on-windows-using-appveyor-and-chocolatey/ - - ps: appveyor-retry cinst --ignore-checksums -y php --version ((choco search php --exact --all-versions -r | select-string -pattern $Env:php_ver_target | Select-Object -first 1) -replace '[php|]','') - - cd c:\tools\php70 - - copy php.ini-production php.ini - - - echo extension_dir=ext >> php.ini - - echo extension=php_openssl.dll >> php.ini - - echo date.timezone="UTC" >> php.ini - - echo variables_order="EGPCS" >> php.ini #May be unneeded. - - echo mbstring.http_input=pass >> php.ini - - echo mbstring.http_output=pass >> php.ini - - echo sendmail_path=nul >> php.ini - - echo extension=php_mbstring.dll >> php.ini - - echo extension=php_curl.dll >> php.ini - - echo extension=php_pdo_mysql.dll >> php.ini - - echo extension=php_pdo_pgsql.dll >> php.ini - - echo extension=php_pdo_sqlite.dll >> php.ini - - echo extension=php_pgsql.dll >> php.ini - - echo extension=php_gd2.dll >> php.ini - - SET PATH=C:\tools\php70;%PATH% - #Install Composer - - cd %APPVEYOR_BUILD_FOLDER% - #- appveyor DownloadFile https://getcomposer.org/composer.phar - - php -r "readfile('http://getcomposer.org/installer');" | php - #Install dependencies via Composer - - php composer.phar -q install --prefer-dist -n - - SET PATH=%APPVEYOR_BUILD_FOLDER%;%APPVEYOR_BUILD_FOLDER%/vendor/bin;%PATH% - #Create a sandbox for testing. Don't think we need this. - - mkdir c:\test_temp - -test_script: - - phpunit - - php composer.phar cs - -# environment variables -environment: - global: - SHELL_INTERACTIVE: true - php_ver_target: 7.0 - diff -r e200cb7efeb3 -r c2387f117808 vendor/consolidation/annotated-command/composer.json --- a/vendor/consolidation/annotated-command/composer.json Thu Apr 26 11:26:54 2018 +0100 +++ b/vendor/consolidation/annotated-command/composer.json Tue Jul 10 15:07:59 2018 +0100 @@ -27,16 +27,16 @@ "symfony/finder": "^2.5|^3|^4" }, "require-dev": { - "phpunit/phpunit": "^4.8", - "satooshi/php-coveralls": "^1.0.2 | dev-master", - "greg-1-anderson/composer-test-scenarios": "^1", + "phpunit/phpunit": "^6", + "satooshi/php-coveralls": "^2", + "g1a/composer-test-scenarios": "^2", "squizlabs/php_codesniffer": "^2.7" }, "config": { "optimize-autoloader": true, "sort-packages": true, "platform": { - "php": "5.6" + "php": "7.0.8" } }, "scripts": { @@ -54,8 +54,10 @@ ], "scenario": "scenarios/install", "post-update-cmd": [ - "create-scenario symfony4 'symfony/console:^4.0'", - "create-scenario symfony2 'symfony/console:^2.8' --platform-php '5.4' --no-lockfile" + "create-scenario symfony4 'symfony/console:^4.0' --platform-php '7.1.3'", + "create-scenario symfony2 'symfony/console:^2.8' 'phpunit/phpunit:^4.8.36' --remove 'satooshi/php-coveralls' --platform-php '5.4' --no-lockfile", + "create-scenario phpunit4 'phpunit/phpunit:^4.8.36' --remove 'satooshi/php-coveralls' --platform-php '5.4'", + "dependency-licenses" ] }, "extra": { diff -r e200cb7efeb3 -r c2387f117808 vendor/consolidation/annotated-command/composer.lock --- a/vendor/consolidation/annotated-command/composer.lock Thu Apr 26 11:26:54 2018 +0100 +++ b/vendor/consolidation/annotated-command/composer.lock Tue Jul 10 15:07:59 2018 +0100 @@ -1,23 +1,23 @@ { "_readme": [ "This file locks the dependencies of your project to a known state", - "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", + "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "7310da82087734800a6fbd1b48f6eb5c", + "content-hash": "180dd9d3779b6c35cdb29faac7f66db3", "packages": [ { "name": "consolidation/output-formatters", - "version": "3.1.13", + "version": "3.2.0", "source": { "type": "git", "url": "https://github.com/consolidation/output-formatters.git", - "reference": "3188461e965b32148c8fb85261833b2b72d34b8c" + "reference": "da889e4bce19f145ca4ec5b1725a946f4eb625a9" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/consolidation/output-formatters/zipball/3188461e965b32148c8fb85261833b2b72d34b8c", - "reference": "3188461e965b32148c8fb85261833b2b72d34b8c", + "url": "https://api.github.com/repos/consolidation/output-formatters/zipball/da889e4bce19f145ca4ec5b1725a946f4eb625a9", + "reference": "da889e4bce19f145ca4ec5b1725a946f4eb625a9", "shasum": "" }, "require": { @@ -26,11 +26,17 @@ "symfony/finder": "^2.5|^3|^4" }, "require-dev": { - "phpunit/phpunit": "^4.8", - "satooshi/php-coveralls": "^1.0.2 | dev-master", + "g-1-a/composer-test-scenarios": "^2", + "phpunit/phpunit": "^5.7.27", + "satooshi/php-coveralls": "^2", "squizlabs/php_codesniffer": "^2.7", + "symfony/console": "3.2.3", + "symfony/var-dumper": "^2.8|^3|^4", "victorjonsson/markdowndocs": "^1.3" }, + "suggest": { + "symfony/var-dumper": "For using the var_dump formatter" + }, "type": "library", "extra": { "branch-alias": { @@ -53,7 +59,7 @@ } ], "description": "Format text by applying transformations provided by plug-in formatters.", - "time": "2017-11-29T15:25:38+00:00" + "time": "2018-03-20T15:18:32+00:00" }, { "name": "psr/log", @@ -104,16 +110,16 @@ }, { "name": "symfony/console", - "version": "v3.4.4", + "version": "v3.4.11", "source": { "type": "git", "url": "https://github.com/symfony/console.git", - "reference": "26b6f419edda16c19775211987651cb27baea7f1" + "reference": "36f83f642443c46f3cf751d4d2ee5d047d757a27" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/console/zipball/26b6f419edda16c19775211987651cb27baea7f1", - "reference": "26b6f419edda16c19775211987651cb27baea7f1", + "url": "https://api.github.com/repos/symfony/console/zipball/36f83f642443c46f3cf751d4d2ee5d047d757a27", + "reference": "36f83f642443c46f3cf751d4d2ee5d047d757a27", "shasum": "" }, "require": { @@ -134,7 +140,7 @@ "symfony/process": "~3.3|~4.0" }, "suggest": { - "psr/log": "For using the console logger", + "psr/log-implementation": "For using the console logger", "symfony/event-dispatcher": "", "symfony/lock": "", "symfony/process": "" @@ -169,20 +175,20 @@ ], "description": "Symfony Console Component", "homepage": "https://symfony.com", - "time": "2018-01-29T09:03:43+00:00" + "time": "2018-05-16T08:49:21+00:00" }, { "name": "symfony/debug", - "version": "v3.4.4", + "version": "v3.4.11", "source": { "type": "git", "url": "https://github.com/symfony/debug.git", - "reference": "53f6af2805daf52a43b393b93d2f24925d35c937" + "reference": "b28fd73fefbac341f673f5efd707d539d6a19f68" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/debug/zipball/53f6af2805daf52a43b393b93d2f24925d35c937", - "reference": "53f6af2805daf52a43b393b93d2f24925d35c937", + "url": "https://api.github.com/repos/symfony/debug/zipball/b28fd73fefbac341f673f5efd707d539d6a19f68", + "reference": "b28fd73fefbac341f673f5efd707d539d6a19f68", "shasum": "" }, "require": { @@ -225,20 +231,20 @@ ], "description": "Symfony Debug Component", "homepage": "https://symfony.com", - "time": "2018-01-18T22:16:57+00:00" + "time": "2018-05-16T14:03:39+00:00" }, { "name": "symfony/event-dispatcher", - "version": "v3.4.4", + "version": "v3.4.11", "source": { "type": "git", "url": "https://github.com/symfony/event-dispatcher.git", - "reference": "26b87b6bca8f8f797331a30b76fdae5342dc26ca" + "reference": "fdd5abcebd1061ec647089c6c41a07ed60af09f8" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/26b87b6bca8f8f797331a30b76fdae5342dc26ca", - "reference": "26b87b6bca8f8f797331a30b76fdae5342dc26ca", + "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/fdd5abcebd1061ec647089c6c41a07ed60af09f8", + "reference": "fdd5abcebd1061ec647089c6c41a07ed60af09f8", "shasum": "" }, "require": { @@ -288,20 +294,20 @@ ], "description": "Symfony EventDispatcher Component", "homepage": "https://symfony.com", - "time": "2018-01-03T07:37:34+00:00" + "time": "2018-04-06T07:35:25+00:00" }, { "name": "symfony/finder", - "version": "v3.4.4", + "version": "v3.4.11", "source": { "type": "git", "url": "https://github.com/symfony/finder.git", - "reference": "613e26310776f49a1773b6737c6bd554b8bc8c6f" + "reference": "472a92f3df8b247b49ae364275fb32943b9656c6" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/finder/zipball/613e26310776f49a1773b6737c6bd554b8bc8c6f", - "reference": "613e26310776f49a1773b6737c6bd554b8bc8c6f", + "url": "https://api.github.com/repos/symfony/finder/zipball/472a92f3df8b247b49ae364275fb32943b9656c6", + "reference": "472a92f3df8b247b49ae364275fb32943b9656c6", "shasum": "" }, "require": { @@ -337,20 +343,20 @@ ], "description": "Symfony Finder Component", "homepage": "https://symfony.com", - "time": "2018-01-03T07:37:34+00:00" + "time": "2018-05-16T08:49:21+00:00" }, { "name": "symfony/polyfill-mbstring", - "version": "v1.7.0", + "version": "v1.8.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-mbstring.git", - "reference": "78be803ce01e55d3491c1397cf1c64beb9c1b63b" + "reference": "3296adf6a6454a050679cde90f95350ad604b171" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/78be803ce01e55d3491c1397cf1c64beb9c1b63b", - "reference": "78be803ce01e55d3491c1397cf1c64beb9c1b63b", + "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/3296adf6a6454a050679cde90f95350ad604b171", + "reference": "3296adf6a6454a050679cde90f95350ad604b171", "shasum": "" }, "require": { @@ -362,7 +368,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "1.7-dev" + "dev-master": "1.8-dev" } }, "autoload": { @@ -396,7 +402,7 @@ "portable", "shim" ], - "time": "2018-01-30T19:27:44+00:00" + "time": "2018-04-26T10:06:28+00:00" } ], "packages-dev": [ @@ -455,21 +461,22 @@ "time": "2015-06-14T21:17:01+00:00" }, { - "name": "greg-1-anderson/composer-test-scenarios", - "version": "1.0.2", + "name": "g1a/composer-test-scenarios", + "version": "2.0.1", "source": { "type": "git", - "url": "https://github.com/greg-1-anderson/composer-test-scenarios.git", - "reference": "78733a4a8dea12d51aafada30932e666f68c13e7" + "url": "https://github.com/g1a/composer-test-scenarios.git", + "reference": "d9a7619f6e1c01498fad19c34539bd5b0d2506ef" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/greg-1-anderson/composer-test-scenarios/zipball/78733a4a8dea12d51aafada30932e666f68c13e7", - "reference": "78733a4a8dea12d51aafada30932e666f68c13e7", + "url": "https://api.github.com/repos/g1a/composer-test-scenarios/zipball/d9a7619f6e1c01498fad19c34539bd5b0d2506ef", + "reference": "d9a7619f6e1c01498fad19c34539bd5b0d2506ef", "shasum": "" }, "bin": [ "scripts/create-scenario", + "scripts/dependency-licenses", "scripts/install-scenario" ], "type": "library", @@ -484,20 +491,20 @@ } ], "description": "Useful scripts for testing multiple sets of Composer dependencies.", - "time": "2018-01-17T20:25:16+00:00" + "time": "2018-05-25T16:45:48+00:00" }, { "name": "guzzlehttp/guzzle", - "version": "6.3.0", + "version": "6.3.3", "source": { "type": "git", "url": "https://github.com/guzzle/guzzle.git", - "reference": "f4db5a78a5ea468d4831de7f0bf9d9415e348699" + "reference": "407b0cb880ace85c9b63c5f9551db498cb2d50ba" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/guzzle/guzzle/zipball/f4db5a78a5ea468d4831de7f0bf9d9415e348699", - "reference": "f4db5a78a5ea468d4831de7f0bf9d9415e348699", + "url": "https://api.github.com/repos/guzzle/guzzle/zipball/407b0cb880ace85c9b63c5f9551db498cb2d50ba", + "reference": "407b0cb880ace85c9b63c5f9551db498cb2d50ba", "shasum": "" }, "require": { @@ -507,7 +514,7 @@ }, "require-dev": { "ext-curl": "*", - "phpunit/phpunit": "^4.0 || ^5.0", + "phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.4 || ^7.0", "psr/log": "^1.0" }, "suggest": { @@ -516,7 +523,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "6.2-dev" + "dev-master": "6.3-dev" } }, "autoload": { @@ -549,7 +556,7 @@ "rest", "web service" ], - "time": "2017-06-22T18:50:49+00:00" + "time": "2018-04-22T15:46:56+00:00" }, { "name": "guzzlehttp/promises", @@ -668,6 +675,153 @@ "time": "2017-03-20T17:10:46+00:00" }, { + "name": "myclabs/deep-copy", + "version": "1.7.0", + "source": { + "type": "git", + "url": "https://github.com/myclabs/DeepCopy.git", + "reference": "3b8a3a99ba1f6a3952ac2747d989303cbd6b7a3e" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/3b8a3a99ba1f6a3952ac2747d989303cbd6b7a3e", + "reference": "3b8a3a99ba1f6a3952ac2747d989303cbd6b7a3e", + "shasum": "" + }, + "require": { + "php": "^5.6 || ^7.0" + }, + "require-dev": { + "doctrine/collections": "^1.0", + "doctrine/common": "^2.6", + "phpunit/phpunit": "^4.1" + }, + "type": "library", + "autoload": { + "psr-4": { + "DeepCopy\\": "src/DeepCopy/" + }, + "files": [ + "src/DeepCopy/deep_copy.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "Create deep copies (clones) of your objects", + "keywords": [ + "clone", + "copy", + "duplicate", + "object", + "object graph" + ], + "time": "2017-10-19T19:58:43+00:00" + }, + { + "name": "phar-io/manifest", + "version": "1.0.1", + "source": { + "type": "git", + "url": "https://github.com/phar-io/manifest.git", + "reference": "2df402786ab5368a0169091f61a7c1e0eb6852d0" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phar-io/manifest/zipball/2df402786ab5368a0169091f61a7c1e0eb6852d0", + "reference": "2df402786ab5368a0169091f61a7c1e0eb6852d0", + "shasum": "" + }, + "require": { + "ext-dom": "*", + "ext-phar": "*", + "phar-io/version": "^1.0.1", + "php": "^5.6 || ^7.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Arne Blankerts", + "email": "arne@blankerts.de", + "role": "Developer" + }, + { + "name": "Sebastian Heuer", + "email": "sebastian@phpeople.de", + "role": "Developer" + }, + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "Developer" + } + ], + "description": "Component for reading phar.io manifest information from a PHP Archive (PHAR)", + "time": "2017-03-05T18:14:27+00:00" + }, + { + "name": "phar-io/version", + "version": "1.0.1", + "source": { + "type": "git", + "url": "https://github.com/phar-io/version.git", + "reference": "a70c0ced4be299a63d32fa96d9281d03e94041df" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phar-io/version/zipball/a70c0ced4be299a63d32fa96d9281d03e94041df", + "reference": "a70c0ced4be299a63d32fa96d9281d03e94041df", + "shasum": "" + }, + "require": { + "php": "^5.6 || ^7.0" + }, + "type": "library", + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Arne Blankerts", + "email": "arne@blankerts.de", + "role": "Developer" + }, + { + "name": "Sebastian Heuer", + "email": "sebastian@phpeople.de", + "role": "Developer" + }, + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "Developer" + } + ], + "description": "Library for handling version information and constraints", + "time": "2017-03-05T17:38:23+00:00" + }, + { "name": "phpdocumentor/reflection-common", "version": "1.0.1", "source": { @@ -723,29 +877,35 @@ }, { "name": "phpdocumentor/reflection-docblock", - "version": "3.3.2", + "version": "4.3.0", "source": { "type": "git", "url": "https://github.com/phpDocumentor/ReflectionDocBlock.git", - "reference": "bf329f6c1aadea3299f08ee804682b7c45b326a2" + "reference": "94fd0001232e47129dd3504189fa1c7225010d08" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/bf329f6c1aadea3299f08ee804682b7c45b326a2", - "reference": "bf329f6c1aadea3299f08ee804682b7c45b326a2", + "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/94fd0001232e47129dd3504189fa1c7225010d08", + "reference": "94fd0001232e47129dd3504189fa1c7225010d08", "shasum": "" }, "require": { - "php": "^5.6 || ^7.0", + "php": "^7.0", "phpdocumentor/reflection-common": "^1.0.0", "phpdocumentor/type-resolver": "^0.4.0", "webmozart/assert": "^1.0" }, "require-dev": { - "mockery/mockery": "^0.9.4", - "phpunit/phpunit": "^4.4" + "doctrine/instantiator": "~1.0.5", + "mockery/mockery": "^1.0", + "phpunit/phpunit": "^6.4" }, "type": "library", + "extra": { + "branch-alias": { + "dev-master": "4.x-dev" + } + }, "autoload": { "psr-4": { "phpDocumentor\\Reflection\\": [ @@ -764,7 +924,7 @@ } ], "description": "With this component, a library can provide support for annotations via DocBlocks or otherwise retrieve information that is embedded in a DocBlock.", - "time": "2017-11-10T14:09:06+00:00" + "time": "2017-11-30T07:14:17+00:00" }, { "name": "phpdocumentor/type-resolver", @@ -815,23 +975,23 @@ }, { "name": "phpspec/prophecy", - "version": "1.7.5", + "version": "1.7.6", "source": { "type": "git", "url": "https://github.com/phpspec/prophecy.git", - "reference": "dfd6be44111a7c41c2e884a336cc4f461b3b2401" + "reference": "33a7e3c4fda54e912ff6338c48823bd5c0f0b712" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpspec/prophecy/zipball/dfd6be44111a7c41c2e884a336cc4f461b3b2401", - "reference": "dfd6be44111a7c41c2e884a336cc4f461b3b2401", + "url": "https://api.github.com/repos/phpspec/prophecy/zipball/33a7e3c4fda54e912ff6338c48823bd5c0f0b712", + "reference": "33a7e3c4fda54e912ff6338c48823bd5c0f0b712", "shasum": "" }, "require": { "doctrine/instantiator": "^1.0.2", "php": "^5.3|^7.0", "phpdocumentor/reflection-docblock": "^2.0|^3.0.2|^4.0", - "sebastian/comparator": "^1.1|^2.0", + "sebastian/comparator": "^1.1|^2.0|^3.0", "sebastian/recursion-context": "^1.0|^2.0|^3.0" }, "require-dev": { @@ -874,43 +1034,44 @@ "spy", "stub" ], - "time": "2018-02-19T10:16:54+00:00" + "time": "2018-04-18T13:57:24+00:00" }, { "name": "phpunit/php-code-coverage", - "version": "2.2.4", + "version": "5.3.2", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-code-coverage.git", - "reference": "eabf68b476ac7d0f73793aada060f1c1a9bf8979" + "reference": "c89677919c5dd6d3b3852f230a663118762218ac" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/eabf68b476ac7d0f73793aada060f1c1a9bf8979", - "reference": "eabf68b476ac7d0f73793aada060f1c1a9bf8979", + "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/c89677919c5dd6d3b3852f230a663118762218ac", + "reference": "c89677919c5dd6d3b3852f230a663118762218ac", "shasum": "" }, "require": { - "php": ">=5.3.3", - "phpunit/php-file-iterator": "~1.3", - "phpunit/php-text-template": "~1.2", - "phpunit/php-token-stream": "~1.3", - "sebastian/environment": "^1.3.2", - "sebastian/version": "~1.0" + "ext-dom": "*", + "ext-xmlwriter": "*", + "php": "^7.0", + "phpunit/php-file-iterator": "^1.4.2", + "phpunit/php-text-template": "^1.2.1", + "phpunit/php-token-stream": "^2.0.1", + "sebastian/code-unit-reverse-lookup": "^1.0.1", + "sebastian/environment": "^3.0", + "sebastian/version": "^2.0.1", + "theseer/tokenizer": "^1.1" }, "require-dev": { - "ext-xdebug": ">=2.1.4", - "phpunit/phpunit": "~4" + "phpunit/phpunit": "^6.0" }, "suggest": { - "ext-dom": "*", - "ext-xdebug": ">=2.2.1", - "ext-xmlwriter": "*" + "ext-xdebug": "^2.5.5" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "2.2.x-dev" + "dev-master": "5.3.x-dev" } }, "autoload": { @@ -925,7 +1086,7 @@ "authors": [ { "name": "Sebastian Bergmann", - "email": "sb@sebastian-bergmann.de", + "email": "sebastian@phpunit.de", "role": "lead" } ], @@ -936,7 +1097,7 @@ "testing", "xunit" ], - "time": "2015-10-06T15:47:00+00:00" + "time": "2018-04-06T15:36:58+00:00" }, { "name": "phpunit/php-file-iterator", @@ -1077,29 +1238,29 @@ }, { "name": "phpunit/php-token-stream", - "version": "1.4.12", + "version": "2.0.2", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-token-stream.git", - "reference": "1ce90ba27c42e4e44e6d8458241466380b51fa16" + "reference": "791198a2c6254db10131eecfe8c06670700904db" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-token-stream/zipball/1ce90ba27c42e4e44e6d8458241466380b51fa16", - "reference": "1ce90ba27c42e4e44e6d8458241466380b51fa16", + "url": "https://api.github.com/repos/sebastianbergmann/php-token-stream/zipball/791198a2c6254db10131eecfe8c06670700904db", + "reference": "791198a2c6254db10131eecfe8c06670700904db", "shasum": "" }, "require": { "ext-tokenizer": "*", - "php": ">=5.3.3" + "php": "^7.0" }, "require-dev": { - "phpunit/phpunit": "~4.2" + "phpunit/phpunit": "^6.2.4" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.4-dev" + "dev-master": "2.0-dev" } }, "autoload": { @@ -1122,45 +1283,57 @@ "keywords": [ "tokenizer" ], - "time": "2017-12-04T08:55:13+00:00" + "time": "2017-11-27T05:48:46+00:00" }, { "name": "phpunit/phpunit", - "version": "4.8.36", + "version": "6.5.8", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/phpunit.git", - "reference": "46023de9a91eec7dfb06cc56cb4e260017298517" + "reference": "4f21a3c6b97c42952fd5c2837bb354ec0199b97b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/46023de9a91eec7dfb06cc56cb4e260017298517", - "reference": "46023de9a91eec7dfb06cc56cb4e260017298517", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/4f21a3c6b97c42952fd5c2837bb354ec0199b97b", + "reference": "4f21a3c6b97c42952fd5c2837bb354ec0199b97b", "shasum": "" }, "require": { "ext-dom": "*", "ext-json": "*", - "ext-pcre": "*", - "ext-reflection": "*", - "ext-spl": "*", - "php": ">=5.3.3", - "phpspec/prophecy": "^1.3.1", - "phpunit/php-code-coverage": "~2.1", - "phpunit/php-file-iterator": "~1.4", - "phpunit/php-text-template": "~1.2", - "phpunit/php-timer": "^1.0.6", - "phpunit/phpunit-mock-objects": "~2.3", - "sebastian/comparator": "~1.2.2", - "sebastian/diff": "~1.2", - "sebastian/environment": "~1.3", - "sebastian/exporter": "~1.2", - "sebastian/global-state": "~1.0", - "sebastian/version": "~1.0", - "symfony/yaml": "~2.1|~3.0" + "ext-libxml": "*", + "ext-mbstring": "*", + "ext-xml": "*", + "myclabs/deep-copy": "^1.6.1", + "phar-io/manifest": "^1.0.1", + "phar-io/version": "^1.0", + "php": "^7.0", + "phpspec/prophecy": "^1.7", + "phpunit/php-code-coverage": "^5.3", + "phpunit/php-file-iterator": "^1.4.3", + "phpunit/php-text-template": "^1.2.1", + "phpunit/php-timer": "^1.0.9", + "phpunit/phpunit-mock-objects": "^5.0.5", + "sebastian/comparator": "^2.1", + "sebastian/diff": "^2.0", + "sebastian/environment": "^3.1", + "sebastian/exporter": "^3.1", + "sebastian/global-state": "^2.0", + "sebastian/object-enumerator": "^3.0.3", + "sebastian/resource-operations": "^1.0", + "sebastian/version": "^2.0.1" + }, + "conflict": { + "phpdocumentor/reflection-docblock": "3.0.2", + "phpunit/dbunit": "<3.0" + }, + "require-dev": { + "ext-pdo": "*" }, "suggest": { - "phpunit/php-invoker": "~1.1" + "ext-xdebug": "*", + "phpunit/php-invoker": "^1.1" }, "bin": [ "phpunit" @@ -1168,7 +1341,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "4.8.x-dev" + "dev-master": "6.5.x-dev" } }, "autoload": { @@ -1194,30 +1367,33 @@ "testing", "xunit" ], - "time": "2017-06-21T08:07:12+00:00" + "time": "2018-04-10T11:38:34+00:00" }, { "name": "phpunit/phpunit-mock-objects", - "version": "2.3.8", + "version": "5.0.6", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/phpunit-mock-objects.git", - "reference": "ac8e7a3db35738d56ee9a76e78a4e03d97628983" + "reference": "33fd41a76e746b8fa96d00b49a23dadfa8334cdf" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit-mock-objects/zipball/ac8e7a3db35738d56ee9a76e78a4e03d97628983", - "reference": "ac8e7a3db35738d56ee9a76e78a4e03d97628983", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit-mock-objects/zipball/33fd41a76e746b8fa96d00b49a23dadfa8334cdf", + "reference": "33fd41a76e746b8fa96d00b49a23dadfa8334cdf", "shasum": "" }, "require": { - "doctrine/instantiator": "^1.0.2", - "php": ">=5.3.3", - "phpunit/php-text-template": "~1.2", - "sebastian/exporter": "~1.2" + "doctrine/instantiator": "^1.0.5", + "php": "^7.0", + "phpunit/php-text-template": "^1.2.1", + "sebastian/exporter": "^3.1" + }, + "conflict": { + "phpunit/phpunit": "<6.0" }, "require-dev": { - "phpunit/phpunit": "~4.4" + "phpunit/phpunit": "^6.5" }, "suggest": { "ext-soap": "*" @@ -1225,7 +1401,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "2.3.x-dev" + "dev-master": "5.0.x-dev" } }, "autoload": { @@ -1240,7 +1416,7 @@ "authors": [ { "name": "Sebastian Bergmann", - "email": "sb@sebastian-bergmann.de", + "email": "sebastian@phpunit.de", "role": "lead" } ], @@ -1250,7 +1426,7 @@ "mock", "xunit" ], - "time": "2015-10-02T06:51:40+00:00" + "time": "2018-01-06T05:45:45+00:00" }, { "name": "psr/http-message", @@ -1304,16 +1480,16 @@ }, { "name": "satooshi/php-coveralls", - "version": "dev-master", + "version": "v2.0.0", "source": { "type": "git", "url": "https://github.com/php-coveralls/php-coveralls.git", - "reference": "c9d3fe2327c8539f1105dc19954673ba993e4ad9" + "reference": "3eaf7eb689cdf6b86801a3843940d974dc657068" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/php-coveralls/php-coveralls/zipball/c9d3fe2327c8539f1105dc19954673ba993e4ad9", - "reference": "c9d3fe2327c8539f1105dc19954673ba993e4ad9", + "url": "https://api.github.com/repos/php-coveralls/php-coveralls/zipball/3eaf7eb689cdf6b86801a3843940d974dc657068", + "reference": "3eaf7eb689cdf6b86801a3843940d974dc657068", "shasum": "" }, "require": { @@ -1334,7 +1510,7 @@ "symfony/http-kernel": "Allows Symfony integration" }, "bin": [ - "bin/coveralls" + "bin/php-coveralls" ], "type": "library", "extra": { @@ -1383,34 +1559,79 @@ "github", "test" ], - "time": "2017-10-14T23:16:28+00:00" + "time": "2017-12-08T14:28:16+00:00" }, { - "name": "sebastian/comparator", - "version": "1.2.4", + "name": "sebastian/code-unit-reverse-lookup", + "version": "1.0.1", "source": { "type": "git", - "url": "https://github.com/sebastianbergmann/comparator.git", - "reference": "2b7424b55f5047b47ac6e5ccb20b2aea4011d9be" + "url": "https://github.com/sebastianbergmann/code-unit-reverse-lookup.git", + "reference": "4419fcdb5eabb9caa61a27c7a1db532a6b55dd18" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/2b7424b55f5047b47ac6e5ccb20b2aea4011d9be", - "reference": "2b7424b55f5047b47ac6e5ccb20b2aea4011d9be", + "url": "https://api.github.com/repos/sebastianbergmann/code-unit-reverse-lookup/zipball/4419fcdb5eabb9caa61a27c7a1db532a6b55dd18", + "reference": "4419fcdb5eabb9caa61a27c7a1db532a6b55dd18", "shasum": "" }, "require": { - "php": ">=5.3.3", - "sebastian/diff": "~1.2", - "sebastian/exporter": "~1.2 || ~2.0" + "php": "^5.6 || ^7.0" }, "require-dev": { - "phpunit/phpunit": "~4.4" + "phpunit/phpunit": "^5.7 || ^6.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.2.x-dev" + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Looks up which function or method a line of code belongs to", + "homepage": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/", + "time": "2017-03-04T06:30:41+00:00" + }, + { + "name": "sebastian/comparator", + "version": "2.1.3", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/comparator.git", + "reference": "34369daee48eafb2651bea869b4b15d75ccc35f9" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/34369daee48eafb2651bea869b4b15d75ccc35f9", + "reference": "34369daee48eafb2651bea869b4b15d75ccc35f9", + "shasum": "" + }, + "require": { + "php": "^7.0", + "sebastian/diff": "^2.0 || ^3.0", + "sebastian/exporter": "^3.1" + }, + "require-dev": { + "phpunit/phpunit": "^6.4" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.1.x-dev" } }, "autoload": { @@ -1441,38 +1662,38 @@ } ], "description": "Provides the functionality to compare PHP values for equality", - "homepage": "http://www.github.com/sebastianbergmann/comparator", + "homepage": "https://github.com/sebastianbergmann/comparator", "keywords": [ "comparator", "compare", "equality" ], - "time": "2017-01-29T09:50:25+00:00" + "time": "2018-02-01T13:46:46+00:00" }, { "name": "sebastian/diff", - "version": "1.4.3", + "version": "2.0.1", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/diff.git", - "reference": "7f066a26a962dbe58ddea9f72a4e82874a3975a4" + "reference": "347c1d8b49c5c3ee30c7040ea6fc446790e6bddd" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/7f066a26a962dbe58ddea9f72a4e82874a3975a4", - "reference": "7f066a26a962dbe58ddea9f72a4e82874a3975a4", + "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/347c1d8b49c5c3ee30c7040ea6fc446790e6bddd", + "reference": "347c1d8b49c5c3ee30c7040ea6fc446790e6bddd", "shasum": "" }, "require": { - "php": "^5.3.3 || ^7.0" + "php": "^7.0" }, "require-dev": { - "phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.0" + "phpunit/phpunit": "^6.2" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.4-dev" + "dev-master": "2.0-dev" } }, "autoload": { @@ -1499,32 +1720,32 @@ "keywords": [ "diff" ], - "time": "2017-05-22T07:24:03+00:00" + "time": "2017-08-03T08:09:46+00:00" }, { "name": "sebastian/environment", - "version": "1.3.8", + "version": "3.1.0", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/environment.git", - "reference": "be2c607e43ce4c89ecd60e75c6a85c126e754aea" + "reference": "cd0871b3975fb7fc44d11314fd1ee20925fce4f5" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/be2c607e43ce4c89ecd60e75c6a85c126e754aea", - "reference": "be2c607e43ce4c89ecd60e75c6a85c126e754aea", + "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/cd0871b3975fb7fc44d11314fd1ee20925fce4f5", + "reference": "cd0871b3975fb7fc44d11314fd1ee20925fce4f5", "shasum": "" }, "require": { - "php": "^5.3.3 || ^7.0" + "php": "^7.0" }, "require-dev": { - "phpunit/phpunit": "^4.8 || ^5.0" + "phpunit/phpunit": "^6.1" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.3.x-dev" + "dev-master": "3.1.x-dev" } }, "autoload": { @@ -1549,34 +1770,34 @@ "environment", "hhvm" ], - "time": "2016-08-18T05:49:44+00:00" + "time": "2017-07-01T08:51:00+00:00" }, { "name": "sebastian/exporter", - "version": "1.2.2", + "version": "3.1.0", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/exporter.git", - "reference": "42c4c2eec485ee3e159ec9884f95b431287edde4" + "reference": "234199f4528de6d12aaa58b612e98f7d36adb937" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/42c4c2eec485ee3e159ec9884f95b431287edde4", - "reference": "42c4c2eec485ee3e159ec9884f95b431287edde4", + "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/234199f4528de6d12aaa58b612e98f7d36adb937", + "reference": "234199f4528de6d12aaa58b612e98f7d36adb937", "shasum": "" }, "require": { - "php": ">=5.3.3", - "sebastian/recursion-context": "~1.0" + "php": "^7.0", + "sebastian/recursion-context": "^3.0" }, "require-dev": { "ext-mbstring": "*", - "phpunit/phpunit": "~4.4" + "phpunit/phpunit": "^6.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.3.x-dev" + "dev-master": "3.1.x-dev" } }, "autoload": { @@ -1616,27 +1837,27 @@ "export", "exporter" ], - "time": "2016-06-17T09:04:28+00:00" + "time": "2017-04-03T13:19:02+00:00" }, { "name": "sebastian/global-state", - "version": "1.1.1", + "version": "2.0.0", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/global-state.git", - "reference": "bc37d50fea7d017d3d340f230811c9f1d7280af4" + "reference": "e8ba02eed7bbbb9e59e43dedd3dddeff4a56b0c4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/bc37d50fea7d017d3d340f230811c9f1d7280af4", - "reference": "bc37d50fea7d017d3d340f230811c9f1d7280af4", + "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/e8ba02eed7bbbb9e59e43dedd3dddeff4a56b0c4", + "reference": "e8ba02eed7bbbb9e59e43dedd3dddeff4a56b0c4", "shasum": "" }, "require": { - "php": ">=5.3.3" + "php": "^7.0" }, "require-dev": { - "phpunit/phpunit": "~4.2" + "phpunit/phpunit": "^6.0" }, "suggest": { "ext-uopz": "*" @@ -1644,7 +1865,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "1.0-dev" + "dev-master": "2.0-dev" } }, "autoload": { @@ -1667,32 +1888,124 @@ "keywords": [ "global state" ], - "time": "2015-10-12T03:26:01+00:00" + "time": "2017-04-27T15:39:26+00:00" }, { - "name": "sebastian/recursion-context", - "version": "1.0.5", + "name": "sebastian/object-enumerator", + "version": "3.0.3", "source": { "type": "git", - "url": "https://github.com/sebastianbergmann/recursion-context.git", - "reference": "b19cc3298482a335a95f3016d2f8a6950f0fbcd7" + "url": "https://github.com/sebastianbergmann/object-enumerator.git", + "reference": "7cfd9e65d11ffb5af41198476395774d4c8a84c5" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/b19cc3298482a335a95f3016d2f8a6950f0fbcd7", - "reference": "b19cc3298482a335a95f3016d2f8a6950f0fbcd7", + "url": "https://api.github.com/repos/sebastianbergmann/object-enumerator/zipball/7cfd9e65d11ffb5af41198476395774d4c8a84c5", + "reference": "7cfd9e65d11ffb5af41198476395774d4c8a84c5", "shasum": "" }, "require": { - "php": ">=5.3.3" + "php": "^7.0", + "sebastian/object-reflector": "^1.1.1", + "sebastian/recursion-context": "^3.0" }, "require-dev": { - "phpunit/phpunit": "~4.4" + "phpunit/phpunit": "^6.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.0.x-dev" + "dev-master": "3.0.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Traverses array structures and object graphs to enumerate all referenced objects", + "homepage": "https://github.com/sebastianbergmann/object-enumerator/", + "time": "2017-08-03T12:35:26+00:00" + }, + { + "name": "sebastian/object-reflector", + "version": "1.1.1", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/object-reflector.git", + "reference": "773f97c67f28de00d397be301821b06708fca0be" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/object-reflector/zipball/773f97c67f28de00d397be301821b06708fca0be", + "reference": "773f97c67f28de00d397be301821b06708fca0be", + "shasum": "" + }, + "require": { + "php": "^7.0" + }, + "require-dev": { + "phpunit/phpunit": "^6.0" + }, + "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" + } + ], + "description": "Allows reflection of object attributes, including inherited and non-public ones", + "homepage": "https://github.com/sebastianbergmann/object-reflector/", + "time": "2017-03-29T09:07:27+00:00" + }, + { + "name": "sebastian/recursion-context", + "version": "3.0.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/recursion-context.git", + "reference": "5b0cd723502bac3b006cbf3dbf7a1e3fcefe4fa8" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/5b0cd723502bac3b006cbf3dbf7a1e3fcefe4fa8", + "reference": "5b0cd723502bac3b006cbf3dbf7a1e3fcefe4fa8", + "shasum": "" + }, + "require": { + "php": "^7.0" + }, + "require-dev": { + "phpunit/phpunit": "^6.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.0.x-dev" } }, "autoload": { @@ -1720,23 +2033,73 @@ ], "description": "Provides functionality to recursively process PHP variables", "homepage": "http://www.github.com/sebastianbergmann/recursion-context", - "time": "2016-10-03T07:41:43+00:00" + "time": "2017-03-03T06:23:57+00:00" + }, + { + "name": "sebastian/resource-operations", + "version": "1.0.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/resource-operations.git", + "reference": "ce990bb21759f94aeafd30209e8cfcdfa8bc3f52" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/resource-operations/zipball/ce990bb21759f94aeafd30209e8cfcdfa8bc3f52", + "reference": "ce990bb21759f94aeafd30209e8cfcdfa8bc3f52", + "shasum": "" + }, + "require": { + "php": ">=5.6.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Provides a list of PHP built-in functions that operate on resources", + "homepage": "https://www.github.com/sebastianbergmann/resource-operations", + "time": "2015-07-28T20:34:47+00:00" }, { "name": "sebastian/version", - "version": "1.0.6", + "version": "2.0.1", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/version.git", - "reference": "58b3a85e7999757d6ad81c787a1fbf5ff6c628c6" + "reference": "99732be0ddb3361e16ad77b68ba41efc8e979019" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/version/zipball/58b3a85e7999757d6ad81c787a1fbf5ff6c628c6", - "reference": "58b3a85e7999757d6ad81c787a1fbf5ff6c628c6", + "url": "https://api.github.com/repos/sebastianbergmann/version/zipball/99732be0ddb3361e16ad77b68ba41efc8e979019", + "reference": "99732be0ddb3361e16ad77b68ba41efc8e979019", "shasum": "" }, + "require": { + "php": ">=5.6" + }, "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0.x-dev" + } + }, "autoload": { "classmap": [ "src/" @@ -1755,7 +2118,7 @@ ], "description": "Library that helps with managing the version number of Git-hosted PHP projects", "homepage": "https://github.com/sebastianbergmann/version", - "time": "2015-06-21T13:59:46+00:00" + "time": "2016-10-03T07:35:21+00:00" }, { "name": "squizlabs/php_codesniffer", @@ -1837,21 +2200,22 @@ }, { "name": "symfony/config", - "version": "v3.4.4", + "version": "v3.4.11", "source": { "type": "git", "url": "https://github.com/symfony/config.git", - "reference": "72689b934d6c6ecf73eca874e98933bf055313c9" + "reference": "73e055cf2e6467715f187724a0347ea32079967c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/config/zipball/72689b934d6c6ecf73eca874e98933bf055313c9", - "reference": "72689b934d6c6ecf73eca874e98933bf055313c9", + "url": "https://api.github.com/repos/symfony/config/zipball/73e055cf2e6467715f187724a0347ea32079967c", + "reference": "73e055cf2e6467715f187724a0347ea32079967c", "shasum": "" }, "require": { "php": "^5.5.9|>=7.0.8", - "symfony/filesystem": "~2.8|~3.0|~4.0" + "symfony/filesystem": "~2.8|~3.0|~4.0", + "symfony/polyfill-ctype": "~1.8" }, "conflict": { "symfony/dependency-injection": "<3.3", @@ -1859,6 +2223,7 @@ }, "require-dev": { "symfony/dependency-injection": "~3.3|~4.0", + "symfony/event-dispatcher": "~3.3|~4.0", "symfony/finder": "~3.3|~4.0", "symfony/yaml": "~3.0|~4.0" }, @@ -1895,24 +2260,25 @@ ], "description": "Symfony Config Component", "homepage": "https://symfony.com", - "time": "2018-01-21T19:05:02+00:00" + "time": "2018-05-14T16:49:53+00:00" }, { "name": "symfony/filesystem", - "version": "v3.4.4", + "version": "v3.4.11", "source": { "type": "git", "url": "https://github.com/symfony/filesystem.git", - "reference": "e078773ad6354af38169faf31c21df0f18ace03d" + "reference": "8e03ca3fa52a0f56b87506f38cf7bd3f9442b3a0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/filesystem/zipball/e078773ad6354af38169faf31c21df0f18ace03d", - "reference": "e078773ad6354af38169faf31c21df0f18ace03d", + "url": "https://api.github.com/repos/symfony/filesystem/zipball/8e03ca3fa52a0f56b87506f38cf7bd3f9442b3a0", + "reference": "8e03ca3fa52a0f56b87506f38cf7bd3f9442b3a0", "shasum": "" }, "require": { - "php": "^5.5.9|>=7.0.8" + "php": "^5.5.9|>=7.0.8", + "symfony/polyfill-ctype": "~1.8" }, "type": "library", "extra": { @@ -1944,20 +2310,75 @@ ], "description": "Symfony Filesystem Component", "homepage": "https://symfony.com", - "time": "2018-01-03T07:37:34+00:00" + "time": "2018-05-16T08:49:21+00:00" + }, + { + "name": "symfony/polyfill-ctype", + "version": "v1.8.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-ctype.git", + "reference": "7cc359f1b7b80fc25ed7796be7d96adc9b354bae" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/7cc359f1b7b80fc25ed7796be7d96adc9b354bae", + "reference": "7cc359f1b7b80fc25ed7796be7d96adc9b354bae", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.8-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Polyfill\\Ctype\\": "" + }, + "files": [ + "bootstrap.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + }, + { + "name": "Gert de Pagter", + "email": "BackEndTea@gmail.com" + } + ], + "description": "Symfony polyfill for ctype functions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "ctype", + "polyfill", + "portable" + ], + "time": "2018-04-30T19:57:29+00:00" }, { "name": "symfony/stopwatch", - "version": "v3.4.4", + "version": "v3.4.11", "source": { "type": "git", "url": "https://github.com/symfony/stopwatch.git", - "reference": "c865551df7c17e63fc1f09f763db04387f91ae4d" + "reference": "eb17cfa072cab26537ac37e9c4ece6c0361369af" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/stopwatch/zipball/c865551df7c17e63fc1f09f763db04387f91ae4d", - "reference": "c865551df7c17e63fc1f09f763db04387f91ae4d", + "url": "https://api.github.com/repos/symfony/stopwatch/zipball/eb17cfa072cab26537ac37e9c4ece6c0361369af", + "reference": "eb17cfa072cab26537ac37e9c4ece6c0361369af", "shasum": "" }, "require": { @@ -1993,24 +2414,25 @@ ], "description": "Symfony Stopwatch Component", "homepage": "https://symfony.com", - "time": "2018-01-03T07:37:34+00:00" + "time": "2018-02-17T14:55:25+00:00" }, { "name": "symfony/yaml", - "version": "v3.4.4", + "version": "v3.4.11", "source": { "type": "git", "url": "https://github.com/symfony/yaml.git", - "reference": "eab73b6c21d27ae4cd037c417618dfd4befb0bfe" + "reference": "c5010cc1692ce1fa328b1fb666961eb3d4a85bb0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/yaml/zipball/eab73b6c21d27ae4cd037c417618dfd4befb0bfe", - "reference": "eab73b6c21d27ae4cd037c417618dfd4befb0bfe", + "url": "https://api.github.com/repos/symfony/yaml/zipball/c5010cc1692ce1fa328b1fb666961eb3d4a85bb0", + "reference": "c5010cc1692ce1fa328b1fb666961eb3d4a85bb0", "shasum": "" }, "require": { - "php": "^5.5.9|>=7.0.8" + "php": "^5.5.9|>=7.0.8", + "symfony/polyfill-ctype": "~1.8" }, "conflict": { "symfony/console": "<3.4" @@ -2051,7 +2473,47 @@ ], "description": "Symfony Yaml Component", "homepage": "https://symfony.com", - "time": "2018-01-21T19:05:02+00:00" + "time": "2018-05-03T23:18:14+00:00" + }, + { + "name": "theseer/tokenizer", + "version": "1.1.0", + "source": { + "type": "git", + "url": "https://github.com/theseer/tokenizer.git", + "reference": "cb2f008f3f05af2893a87208fe6a6c4985483f8b" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/theseer/tokenizer/zipball/cb2f008f3f05af2893a87208fe6a6c4985483f8b", + "reference": "cb2f008f3f05af2893a87208fe6a6c4985483f8b", + "shasum": "" + }, + "require": { + "ext-dom": "*", + "ext-tokenizer": "*", + "ext-xmlwriter": "*", + "php": "^7.0" + }, + "type": "library", + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Arne Blankerts", + "email": "arne@blankerts.de", + "role": "Developer" + } + ], + "description": "A small library for converting tokenized PHP source code into XML and potentially other formats", + "time": "2017-04-07T12:08:54+00:00" }, { "name": "webmozart/assert", @@ -2106,9 +2568,7 @@ ], "aliases": [], "minimum-stability": "stable", - "stability-flags": { - "satooshi/php-coveralls": 20 - }, + "stability-flags": [], "prefer-stable": false, "prefer-lowest": false, "platform": { @@ -2116,6 +2576,6 @@ }, "platform-dev": [], "platform-overrides": { - "php": "5.6" + "php": "7.0.8" } } diff -r e200cb7efeb3 -r c2387f117808 vendor/consolidation/annotated-command/scenarios/install --- a/vendor/consolidation/annotated-command/scenarios/install Thu Apr 26 11:26:54 2018 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,28 +0,0 @@ -#!/bin/bash - -SCENARIO=$1 -ACTION=${2-install} - -dir=scenarios/${SCENARIO} -if [ -z "$SCENARIO" ] ; then - SCENARIO=default - dir=. -fi - - -if [ ! -d "$dir" ] ; then - echo "Requested scenario '${SCENARIO}' does not exist." - exit 1 -fi - -echo -echo "::" -echo ":: Switch to ${SCENARIO} scenario" -echo "::" -echo - -set -ex - -composer -n validate --working-dir=$dir --no-check-all --ansi -composer -n --working-dir=$dir ${ACTION} --prefer-dist --no-scripts -composer -n --working-dir=$dir info diff -r e200cb7efeb3 -r c2387f117808 vendor/consolidation/annotated-command/scenarios/symfony2/.gitignore --- a/vendor/consolidation/annotated-command/scenarios/symfony2/.gitignore Thu Apr 26 11:26:54 2018 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,2 +0,0 @@ -vendor -composer.lock diff -r e200cb7efeb3 -r c2387f117808 vendor/consolidation/annotated-command/scenarios/symfony2/composer.json --- a/vendor/consolidation/annotated-command/scenarios/symfony2/composer.json Thu Apr 26 11:26:54 2018 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,68 +0,0 @@ -{ - "name": "consolidation/annotated-command", - "description": "Initialize Symfony Console commands from annotated command class methods.", - "license": "MIT", - "authors": [ - { - "name": "Greg Anderson", - "email": "greg.1.anderson@greenknowe.org" - } - ], - "autoload":{ - "psr-4":{ - "Consolidation\\AnnotatedCommand\\": "src" - } - }, - "autoload-dev": { - "psr-4": { - "Consolidation\\TestUtils\\": "tests/src" - } - }, - "require": { - "php": ">=5.4.0", - "consolidation/output-formatters": "^3.1.12", - "psr/log": "^1", - "symfony/event-dispatcher": "^2.5|^3|^4", - "symfony/finder": "^2.5|^3|^4" - }, - "require-dev": { - "greg-1-anderson/composer-test-scenarios": "^1", - "phpunit/phpunit": "^4.8", - "satooshi/php-coveralls": "^1.0.2 | dev-master", - "squizlabs/php_codesniffer": "^2.7", - "symfony/console": "^2.8" - }, - "config": { - "optimize-autoloader": true, - "sort-packages": true, - "platform": { - "php": "5.4" - }, - "vendor-dir": "../../vendor" - }, - "scripts": { - "cs": "phpcs --standard=PSR2 -n src", - "cbf": "phpcbf --standard=PSR2 -n src", - "unit": "SHELL_INTERACTIVE=true phpunit --colors=always", - "lint": [ - "find src -name '*.php' -print0 | xargs -0 -n1 php -l", - "find tests/src -name '*.php' -print0 | xargs -0 -n1 php -l" - ], - "test": [ - "@lint", - "@unit", - "@cs" - ], - "scenario": "scenarios/install", - "post-update-cmd": [ - "create-scenario symfony4 'symfony/console:^4.0'", - "create-scenario symfony2 'symfony/console:^2.8' --platform-php '5.4' --no-lockfile" - ] - }, - "extra": { - "branch-alias": { - "dev-master": "2.x-dev" - } - }, - "minimum-stability": "stable" -} diff -r e200cb7efeb3 -r c2387f117808 vendor/consolidation/annotated-command/scenarios/symfony2/src --- a/vendor/consolidation/annotated-command/scenarios/symfony2/src Thu Apr 26 11:26:54 2018 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1 +0,0 @@ -../../src \ No newline at end of file diff -r e200cb7efeb3 -r c2387f117808 vendor/consolidation/annotated-command/scenarios/symfony2/tests --- a/vendor/consolidation/annotated-command/scenarios/symfony2/tests Thu Apr 26 11:26:54 2018 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1 +0,0 @@ -../../tests \ No newline at end of file diff -r e200cb7efeb3 -r c2387f117808 vendor/consolidation/annotated-command/scenarios/symfony4/.gitignore --- a/vendor/consolidation/annotated-command/scenarios/symfony4/.gitignore Thu Apr 26 11:26:54 2018 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1 +0,0 @@ -vendor diff -r e200cb7efeb3 -r c2387f117808 vendor/consolidation/annotated-command/scenarios/symfony4/composer.json --- a/vendor/consolidation/annotated-command/scenarios/symfony4/composer.json Thu Apr 26 11:26:54 2018 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,68 +0,0 @@ -{ - "name": "consolidation/annotated-command", - "description": "Initialize Symfony Console commands from annotated command class methods.", - "license": "MIT", - "authors": [ - { - "name": "Greg Anderson", - "email": "greg.1.anderson@greenknowe.org" - } - ], - "autoload":{ - "psr-4":{ - "Consolidation\\AnnotatedCommand\\": "src" - } - }, - "autoload-dev": { - "psr-4": { - "Consolidation\\TestUtils\\": "tests/src" - } - }, - "require": { - "php": ">=5.4.0", - "consolidation/output-formatters": "^3.1.12", - "psr/log": "^1", - "symfony/event-dispatcher": "^2.5|^3|^4", - "symfony/finder": "^2.5|^3|^4" - }, - "require-dev": { - "greg-1-anderson/composer-test-scenarios": "^1", - "phpunit/phpunit": "^4.8", - "satooshi/php-coveralls": "^1.0.2 | dev-master", - "squizlabs/php_codesniffer": "^2.7", - "symfony/console": "^4.0" - }, - "config": { - "optimize-autoloader": true, - "sort-packages": true, - "platform": { - - }, - "vendor-dir": "../../vendor" - }, - "scripts": { - "cs": "phpcs --standard=PSR2 -n src", - "cbf": "phpcbf --standard=PSR2 -n src", - "unit": "SHELL_INTERACTIVE=true phpunit --colors=always", - "lint": [ - "find src -name '*.php' -print0 | xargs -0 -n1 php -l", - "find tests/src -name '*.php' -print0 | xargs -0 -n1 php -l" - ], - "test": [ - "@lint", - "@unit", - "@cs" - ], - "scenario": "scenarios/install", - "post-update-cmd": [ - "create-scenario symfony4 'symfony/console:^4.0'", - "create-scenario symfony2 'symfony/console:^2.8' --platform-php '5.4' --no-lockfile" - ] - }, - "extra": { - "branch-alias": { - "dev-master": "2.x-dev" - } - }, - "minimum-stability": "stable" -} diff -r e200cb7efeb3 -r c2387f117808 vendor/consolidation/annotated-command/scenarios/symfony4/composer.lock --- a/vendor/consolidation/annotated-command/scenarios/symfony4/composer.lock Thu Apr 26 11:26:54 2018 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,2065 +0,0 @@ -{ - "_readme": [ - "This file locks the dependencies of your project to a known state", - "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", - "This file is @generated automatically" - ], - "content-hash": "e0f5a2f56fb0d331d002571fdcb82d20", - "packages": [ - { - "name": "consolidation/output-formatters", - "version": "3.1.13", - "source": { - "type": "git", - "url": "https://github.com/consolidation/output-formatters.git", - "reference": "3188461e965b32148c8fb85261833b2b72d34b8c" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/consolidation/output-formatters/zipball/3188461e965b32148c8fb85261833b2b72d34b8c", - "reference": "3188461e965b32148c8fb85261833b2b72d34b8c", - "shasum": "" - }, - "require": { - "php": ">=5.4.0", - "symfony/console": "^2.8|^3|^4", - "symfony/finder": "^2.5|^3|^4" - }, - "require-dev": { - "phpunit/phpunit": "^4.8", - "satooshi/php-coveralls": "^1.0.2 | dev-master", - "squizlabs/php_codesniffer": "^2.7", - "victorjonsson/markdowndocs": "^1.3" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "3.x-dev" - } - }, - "autoload": { - "psr-4": { - "Consolidation\\OutputFormatters\\": "src" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Greg Anderson", - "email": "greg.1.anderson@greenknowe.org" - } - ], - "description": "Format text by applying transformations provided by plug-in formatters.", - "time": "2017-11-29T15:25:38+00:00" - }, - { - "name": "psr/log", - "version": "1.0.2", - "source": { - "type": "git", - "url": "https://github.com/php-fig/log.git", - "reference": "4ebe3a8bf773a19edfe0a84b6585ba3d401b724d" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/php-fig/log/zipball/4ebe3a8bf773a19edfe0a84b6585ba3d401b724d", - "reference": "4ebe3a8bf773a19edfe0a84b6585ba3d401b724d", - "shasum": "" - }, - "require": { - "php": ">=5.3.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.0.x-dev" - } - }, - "autoload": { - "psr-4": { - "Psr\\Log\\": "Psr/Log/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "PHP-FIG", - "homepage": "http://www.php-fig.org/" - } - ], - "description": "Common interface for logging libraries", - "homepage": "https://github.com/php-fig/log", - "keywords": [ - "log", - "psr", - "psr-3" - ], - "time": "2016-10-10T12:19:37+00:00" - }, - { - "name": "symfony/console", - "version": "v4.0.4", - "source": { - "type": "git", - "url": "https://github.com/symfony/console.git", - "reference": "36d5b41e7d4e1ccf0370f6babe966c08ef0a1488" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/console/zipball/36d5b41e7d4e1ccf0370f6babe966c08ef0a1488", - "reference": "36d5b41e7d4e1ccf0370f6babe966c08ef0a1488", - "shasum": "" - }, - "require": { - "php": "^7.1.3", - "symfony/polyfill-mbstring": "~1.0" - }, - "conflict": { - "symfony/dependency-injection": "<3.4", - "symfony/process": "<3.3" - }, - "require-dev": { - "psr/log": "~1.0", - "symfony/config": "~3.4|~4.0", - "symfony/dependency-injection": "~3.4|~4.0", - "symfony/event-dispatcher": "~3.4|~4.0", - "symfony/lock": "~3.4|~4.0", - "symfony/process": "~3.4|~4.0" - }, - "suggest": { - "psr/log": "For using the console logger", - "symfony/event-dispatcher": "", - "symfony/lock": "", - "symfony/process": "" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "4.0-dev" - } - }, - "autoload": { - "psr-4": { - "Symfony\\Component\\Console\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Symfony Console Component", - "homepage": "https://symfony.com", - "time": "2018-01-29T09:06:29+00:00" - }, - { - "name": "symfony/event-dispatcher", - "version": "v4.0.4", - "source": { - "type": "git", - "url": "https://github.com/symfony/event-dispatcher.git", - "reference": "74d33aac36208c4d6757807d9f598f0133a3a4eb" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/74d33aac36208c4d6757807d9f598f0133a3a4eb", - "reference": "74d33aac36208c4d6757807d9f598f0133a3a4eb", - "shasum": "" - }, - "require": { - "php": "^7.1.3" - }, - "conflict": { - "symfony/dependency-injection": "<3.4" - }, - "require-dev": { - "psr/log": "~1.0", - "symfony/config": "~3.4|~4.0", - "symfony/dependency-injection": "~3.4|~4.0", - "symfony/expression-language": "~3.4|~4.0", - "symfony/stopwatch": "~3.4|~4.0" - }, - "suggest": { - "symfony/dependency-injection": "", - "symfony/http-kernel": "" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "4.0-dev" - } - }, - "autoload": { - "psr-4": { - "Symfony\\Component\\EventDispatcher\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Symfony EventDispatcher Component", - "homepage": "https://symfony.com", - "time": "2018-01-03T07:38:00+00:00" - }, - { - "name": "symfony/finder", - "version": "v4.0.4", - "source": { - "type": "git", - "url": "https://github.com/symfony/finder.git", - "reference": "8b08180f2b7ccb41062366b9ad91fbc4f1af8601" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/finder/zipball/8b08180f2b7ccb41062366b9ad91fbc4f1af8601", - "reference": "8b08180f2b7ccb41062366b9ad91fbc4f1af8601", - "shasum": "" - }, - "require": { - "php": "^7.1.3" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "4.0-dev" - } - }, - "autoload": { - "psr-4": { - "Symfony\\Component\\Finder\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Symfony Finder Component", - "homepage": "https://symfony.com", - "time": "2018-01-03T07:38:00+00:00" - }, - { - "name": "symfony/polyfill-mbstring", - "version": "v1.7.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/polyfill-mbstring.git", - "reference": "78be803ce01e55d3491c1397cf1c64beb9c1b63b" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/78be803ce01e55d3491c1397cf1c64beb9c1b63b", - "reference": "78be803ce01e55d3491c1397cf1c64beb9c1b63b", - "shasum": "" - }, - "require": { - "php": ">=5.3.3" - }, - "suggest": { - "ext-mbstring": "For best performance" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.7-dev" - } - }, - "autoload": { - "psr-4": { - "Symfony\\Polyfill\\Mbstring\\": "" - }, - "files": [ - "bootstrap.php" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Symfony polyfill for the Mbstring extension", - "homepage": "https://symfony.com", - "keywords": [ - "compatibility", - "mbstring", - "polyfill", - "portable", - "shim" - ], - "time": "2018-01-30T19:27:44+00:00" - } - ], - "packages-dev": [ - { - "name": "doctrine/instantiator", - "version": "1.1.0", - "source": { - "type": "git", - "url": "https://github.com/doctrine/instantiator.git", - "reference": "185b8868aa9bf7159f5f953ed5afb2d7fcdc3bda" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/doctrine/instantiator/zipball/185b8868aa9bf7159f5f953ed5afb2d7fcdc3bda", - "reference": "185b8868aa9bf7159f5f953ed5afb2d7fcdc3bda", - "shasum": "" - }, - "require": { - "php": "^7.1" - }, - "require-dev": { - "athletic/athletic": "~0.1.8", - "ext-pdo": "*", - "ext-phar": "*", - "phpunit/phpunit": "^6.2.3", - "squizlabs/php_codesniffer": "^3.0.2" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.2.x-dev" - } - }, - "autoload": { - "psr-4": { - "Doctrine\\Instantiator\\": "src/Doctrine/Instantiator/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Marco Pivetta", - "email": "ocramius@gmail.com", - "homepage": "http://ocramius.github.com/" - } - ], - "description": "A small, lightweight utility to instantiate objects in PHP without invoking their constructors", - "homepage": "https://github.com/doctrine/instantiator", - "keywords": [ - "constructor", - "instantiate" - ], - "time": "2017-07-22T11:58:36+00:00" - }, - { - "name": "greg-1-anderson/composer-test-scenarios", - "version": "1.0.2", - "source": { - "type": "git", - "url": "https://github.com/greg-1-anderson/composer-test-scenarios.git", - "reference": "78733a4a8dea12d51aafada30932e666f68c13e7" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/greg-1-anderson/composer-test-scenarios/zipball/78733a4a8dea12d51aafada30932e666f68c13e7", - "reference": "78733a4a8dea12d51aafada30932e666f68c13e7", - "shasum": "" - }, - "bin": [ - "scripts/create-scenario", - "scripts/install-scenario" - ], - "type": "library", - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Greg Anderson", - "email": "greg.1.anderson@greenknowe.org" - } - ], - "description": "Useful scripts for testing multiple sets of Composer dependencies.", - "time": "2018-01-17T20:25:16+00:00" - }, - { - "name": "guzzlehttp/guzzle", - "version": "6.3.0", - "source": { - "type": "git", - "url": "https://github.com/guzzle/guzzle.git", - "reference": "f4db5a78a5ea468d4831de7f0bf9d9415e348699" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/guzzle/guzzle/zipball/f4db5a78a5ea468d4831de7f0bf9d9415e348699", - "reference": "f4db5a78a5ea468d4831de7f0bf9d9415e348699", - "shasum": "" - }, - "require": { - "guzzlehttp/promises": "^1.0", - "guzzlehttp/psr7": "^1.4", - "php": ">=5.5" - }, - "require-dev": { - "ext-curl": "*", - "phpunit/phpunit": "^4.0 || ^5.0", - "psr/log": "^1.0" - }, - "suggest": { - "psr/log": "Required for using the Log middleware" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "6.2-dev" - } - }, - "autoload": { - "files": [ - "src/functions_include.php" - ], - "psr-4": { - "GuzzleHttp\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Michael Dowling", - "email": "mtdowling@gmail.com", - "homepage": "https://github.com/mtdowling" - } - ], - "description": "Guzzle is a PHP HTTP client library", - "homepage": "http://guzzlephp.org/", - "keywords": [ - "client", - "curl", - "framework", - "http", - "http client", - "rest", - "web service" - ], - "time": "2017-06-22T18:50:49+00:00" - }, - { - "name": "guzzlehttp/promises", - "version": "v1.3.1", - "source": { - "type": "git", - "url": "https://github.com/guzzle/promises.git", - "reference": "a59da6cf61d80060647ff4d3eb2c03a2bc694646" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/guzzle/promises/zipball/a59da6cf61d80060647ff4d3eb2c03a2bc694646", - "reference": "a59da6cf61d80060647ff4d3eb2c03a2bc694646", - "shasum": "" - }, - "require": { - "php": ">=5.5.0" - }, - "require-dev": { - "phpunit/phpunit": "^4.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.4-dev" - } - }, - "autoload": { - "psr-4": { - "GuzzleHttp\\Promise\\": "src/" - }, - "files": [ - "src/functions_include.php" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Michael Dowling", - "email": "mtdowling@gmail.com", - "homepage": "https://github.com/mtdowling" - } - ], - "description": "Guzzle promises library", - "keywords": [ - "promise" - ], - "time": "2016-12-20T10:07:11+00:00" - }, - { - "name": "guzzlehttp/psr7", - "version": "1.4.2", - "source": { - "type": "git", - "url": "https://github.com/guzzle/psr7.git", - "reference": "f5b8a8512e2b58b0071a7280e39f14f72e05d87c" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/guzzle/psr7/zipball/f5b8a8512e2b58b0071a7280e39f14f72e05d87c", - "reference": "f5b8a8512e2b58b0071a7280e39f14f72e05d87c", - "shasum": "" - }, - "require": { - "php": ">=5.4.0", - "psr/http-message": "~1.0" - }, - "provide": { - "psr/http-message-implementation": "1.0" - }, - "require-dev": { - "phpunit/phpunit": "~4.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.4-dev" - } - }, - "autoload": { - "psr-4": { - "GuzzleHttp\\Psr7\\": "src/" - }, - "files": [ - "src/functions_include.php" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Michael Dowling", - "email": "mtdowling@gmail.com", - "homepage": "https://github.com/mtdowling" - }, - { - "name": "Tobias Schultze", - "homepage": "https://github.com/Tobion" - } - ], - "description": "PSR-7 message implementation that also provides common utility methods", - "keywords": [ - "http", - "message", - "request", - "response", - "stream", - "uri", - "url" - ], - "time": "2017-03-20T17:10:46+00:00" - }, - { - "name": "phpdocumentor/reflection-common", - "version": "1.0.1", - "source": { - "type": "git", - "url": "https://github.com/phpDocumentor/ReflectionCommon.git", - "reference": "21bdeb5f65d7ebf9f43b1b25d404f87deab5bfb6" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/phpDocumentor/ReflectionCommon/zipball/21bdeb5f65d7ebf9f43b1b25d404f87deab5bfb6", - "reference": "21bdeb5f65d7ebf9f43b1b25d404f87deab5bfb6", - "shasum": "" - }, - "require": { - "php": ">=5.5" - }, - "require-dev": { - "phpunit/phpunit": "^4.6" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.0.x-dev" - } - }, - "autoload": { - "psr-4": { - "phpDocumentor\\Reflection\\": [ - "src" - ] - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Jaap van Otterdijk", - "email": "opensource@ijaap.nl" - } - ], - "description": "Common reflection classes used by phpdocumentor to reflect the code structure", - "homepage": "http://www.phpdoc.org", - "keywords": [ - "FQSEN", - "phpDocumentor", - "phpdoc", - "reflection", - "static analysis" - ], - "time": "2017-09-11T18:02:19+00:00" - }, - { - "name": "phpdocumentor/reflection-docblock", - "version": "4.3.0", - "source": { - "type": "git", - "url": "https://github.com/phpDocumentor/ReflectionDocBlock.git", - "reference": "94fd0001232e47129dd3504189fa1c7225010d08" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/94fd0001232e47129dd3504189fa1c7225010d08", - "reference": "94fd0001232e47129dd3504189fa1c7225010d08", - "shasum": "" - }, - "require": { - "php": "^7.0", - "phpdocumentor/reflection-common": "^1.0.0", - "phpdocumentor/type-resolver": "^0.4.0", - "webmozart/assert": "^1.0" - }, - "require-dev": { - "doctrine/instantiator": "~1.0.5", - "mockery/mockery": "^1.0", - "phpunit/phpunit": "^6.4" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "4.x-dev" - } - }, - "autoload": { - "psr-4": { - "phpDocumentor\\Reflection\\": [ - "src/" - ] - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Mike van Riel", - "email": "me@mikevanriel.com" - } - ], - "description": "With this component, a library can provide support for annotations via DocBlocks or otherwise retrieve information that is embedded in a DocBlock.", - "time": "2017-11-30T07:14:17+00:00" - }, - { - "name": "phpdocumentor/type-resolver", - "version": "0.4.0", - "source": { - "type": "git", - "url": "https://github.com/phpDocumentor/TypeResolver.git", - "reference": "9c977708995954784726e25d0cd1dddf4e65b0f7" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/phpDocumentor/TypeResolver/zipball/9c977708995954784726e25d0cd1dddf4e65b0f7", - "reference": "9c977708995954784726e25d0cd1dddf4e65b0f7", - "shasum": "" - }, - "require": { - "php": "^5.5 || ^7.0", - "phpdocumentor/reflection-common": "^1.0" - }, - "require-dev": { - "mockery/mockery": "^0.9.4", - "phpunit/phpunit": "^5.2||^4.8.24" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.0.x-dev" - } - }, - "autoload": { - "psr-4": { - "phpDocumentor\\Reflection\\": [ - "src/" - ] - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Mike van Riel", - "email": "me@mikevanriel.com" - } - ], - "time": "2017-07-14T14:27:02+00:00" - }, - { - "name": "phpspec/prophecy", - "version": "1.7.5", - "source": { - "type": "git", - "url": "https://github.com/phpspec/prophecy.git", - "reference": "dfd6be44111a7c41c2e884a336cc4f461b3b2401" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/phpspec/prophecy/zipball/dfd6be44111a7c41c2e884a336cc4f461b3b2401", - "reference": "dfd6be44111a7c41c2e884a336cc4f461b3b2401", - "shasum": "" - }, - "require": { - "doctrine/instantiator": "^1.0.2", - "php": "^5.3|^7.0", - "phpdocumentor/reflection-docblock": "^2.0|^3.0.2|^4.0", - "sebastian/comparator": "^1.1|^2.0", - "sebastian/recursion-context": "^1.0|^2.0|^3.0" - }, - "require-dev": { - "phpspec/phpspec": "^2.5|^3.2", - "phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.5" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.7.x-dev" - } - }, - "autoload": { - "psr-0": { - "Prophecy\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Konstantin Kudryashov", - "email": "ever.zet@gmail.com", - "homepage": "http://everzet.com" - }, - { - "name": "Marcello Duarte", - "email": "marcello.duarte@gmail.com" - } - ], - "description": "Highly opinionated mocking framework for PHP 5.3+", - "homepage": "https://github.com/phpspec/prophecy", - "keywords": [ - "Double", - "Dummy", - "fake", - "mock", - "spy", - "stub" - ], - "time": "2018-02-19T10:16:54+00:00" - }, - { - "name": "phpunit/php-code-coverage", - "version": "2.2.4", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/php-code-coverage.git", - "reference": "eabf68b476ac7d0f73793aada060f1c1a9bf8979" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/eabf68b476ac7d0f73793aada060f1c1a9bf8979", - "reference": "eabf68b476ac7d0f73793aada060f1c1a9bf8979", - "shasum": "" - }, - "require": { - "php": ">=5.3.3", - "phpunit/php-file-iterator": "~1.3", - "phpunit/php-text-template": "~1.2", - "phpunit/php-token-stream": "~1.3", - "sebastian/environment": "^1.3.2", - "sebastian/version": "~1.0" - }, - "require-dev": { - "ext-xdebug": ">=2.1.4", - "phpunit/phpunit": "~4" - }, - "suggest": { - "ext-dom": "*", - "ext-xdebug": ">=2.2.1", - "ext-xmlwriter": "*" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.2.x-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sb@sebastian-bergmann.de", - "role": "lead" - } - ], - "description": "Library that provides collection, processing, and rendering functionality for PHP code coverage information.", - "homepage": "https://github.com/sebastianbergmann/php-code-coverage", - "keywords": [ - "coverage", - "testing", - "xunit" - ], - "time": "2015-10-06T15:47:00+00:00" - }, - { - "name": "phpunit/php-file-iterator", - "version": "1.4.5", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/php-file-iterator.git", - "reference": "730b01bc3e867237eaac355e06a36b85dd93a8b4" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/730b01bc3e867237eaac355e06a36b85dd93a8b4", - "reference": "730b01bc3e867237eaac355e06a36b85dd93a8b4", - "shasum": "" - }, - "require": { - "php": ">=5.3.3" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.4.x-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sb@sebastian-bergmann.de", - "role": "lead" - } - ], - "description": "FilterIterator implementation that filters files based on a list of suffixes.", - "homepage": "https://github.com/sebastianbergmann/php-file-iterator/", - "keywords": [ - "filesystem", - "iterator" - ], - "time": "2017-11-27T13:52:08+00:00" - }, - { - "name": "phpunit/php-text-template", - "version": "1.2.1", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/php-text-template.git", - "reference": "31f8b717e51d9a2afca6c9f046f5d69fc27c8686" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/31f8b717e51d9a2afca6c9f046f5d69fc27c8686", - "reference": "31f8b717e51d9a2afca6c9f046f5d69fc27c8686", - "shasum": "" - }, - "require": { - "php": ">=5.3.3" - }, - "type": "library", - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" - } - ], - "description": "Simple template engine.", - "homepage": "https://github.com/sebastianbergmann/php-text-template/", - "keywords": [ - "template" - ], - "time": "2015-06-21T13:50:34+00:00" - }, - { - "name": "phpunit/php-timer", - "version": "1.0.9", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/php-timer.git", - "reference": "3dcf38ca72b158baf0bc245e9184d3fdffa9c46f" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/3dcf38ca72b158baf0bc245e9184d3fdffa9c46f", - "reference": "3dcf38ca72b158baf0bc245e9184d3fdffa9c46f", - "shasum": "" - }, - "require": { - "php": "^5.3.3 || ^7.0" - }, - "require-dev": { - "phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sb@sebastian-bergmann.de", - "role": "lead" - } - ], - "description": "Utility class for timing", - "homepage": "https://github.com/sebastianbergmann/php-timer/", - "keywords": [ - "timer" - ], - "time": "2017-02-26T11:10:40+00:00" - }, - { - "name": "phpunit/php-token-stream", - "version": "1.4.12", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/php-token-stream.git", - "reference": "1ce90ba27c42e4e44e6d8458241466380b51fa16" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-token-stream/zipball/1ce90ba27c42e4e44e6d8458241466380b51fa16", - "reference": "1ce90ba27c42e4e44e6d8458241466380b51fa16", - "shasum": "" - }, - "require": { - "ext-tokenizer": "*", - "php": ">=5.3.3" - }, - "require-dev": { - "phpunit/phpunit": "~4.2" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.4-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - } - ], - "description": "Wrapper around PHP's tokenizer extension.", - "homepage": "https://github.com/sebastianbergmann/php-token-stream/", - "keywords": [ - "tokenizer" - ], - "time": "2017-12-04T08:55:13+00:00" - }, - { - "name": "phpunit/phpunit", - "version": "4.8.36", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/phpunit.git", - "reference": "46023de9a91eec7dfb06cc56cb4e260017298517" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/46023de9a91eec7dfb06cc56cb4e260017298517", - "reference": "46023de9a91eec7dfb06cc56cb4e260017298517", - "shasum": "" - }, - "require": { - "ext-dom": "*", - "ext-json": "*", - "ext-pcre": "*", - "ext-reflection": "*", - "ext-spl": "*", - "php": ">=5.3.3", - "phpspec/prophecy": "^1.3.1", - "phpunit/php-code-coverage": "~2.1", - "phpunit/php-file-iterator": "~1.4", - "phpunit/php-text-template": "~1.2", - "phpunit/php-timer": "^1.0.6", - "phpunit/phpunit-mock-objects": "~2.3", - "sebastian/comparator": "~1.2.2", - "sebastian/diff": "~1.2", - "sebastian/environment": "~1.3", - "sebastian/exporter": "~1.2", - "sebastian/global-state": "~1.0", - "sebastian/version": "~1.0", - "symfony/yaml": "~2.1|~3.0" - }, - "suggest": { - "phpunit/php-invoker": "~1.1" - }, - "bin": [ - "phpunit" - ], - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "4.8.x-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": "The PHP Unit Testing framework.", - "homepage": "https://phpunit.de/", - "keywords": [ - "phpunit", - "testing", - "xunit" - ], - "time": "2017-06-21T08:07:12+00:00" - }, - { - "name": "phpunit/phpunit-mock-objects", - "version": "2.3.8", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/phpunit-mock-objects.git", - "reference": "ac8e7a3db35738d56ee9a76e78a4e03d97628983" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit-mock-objects/zipball/ac8e7a3db35738d56ee9a76e78a4e03d97628983", - "reference": "ac8e7a3db35738d56ee9a76e78a4e03d97628983", - "shasum": "" - }, - "require": { - "doctrine/instantiator": "^1.0.2", - "php": ">=5.3.3", - "phpunit/php-text-template": "~1.2", - "sebastian/exporter": "~1.2" - }, - "require-dev": { - "phpunit/phpunit": "~4.4" - }, - "suggest": { - "ext-soap": "*" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.3.x-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sb@sebastian-bergmann.de", - "role": "lead" - } - ], - "description": "Mock Object library for PHPUnit", - "homepage": "https://github.com/sebastianbergmann/phpunit-mock-objects/", - "keywords": [ - "mock", - "xunit" - ], - "time": "2015-10-02T06:51:40+00:00" - }, - { - "name": "psr/http-message", - "version": "1.0.1", - "source": { - "type": "git", - "url": "https://github.com/php-fig/http-message.git", - "reference": "f6561bf28d520154e4b0ec72be95418abe6d9363" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/php-fig/http-message/zipball/f6561bf28d520154e4b0ec72be95418abe6d9363", - "reference": "f6561bf28d520154e4b0ec72be95418abe6d9363", - "shasum": "" - }, - "require": { - "php": ">=5.3.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.0.x-dev" - } - }, - "autoload": { - "psr-4": { - "Psr\\Http\\Message\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "PHP-FIG", - "homepage": "http://www.php-fig.org/" - } - ], - "description": "Common interface for HTTP messages", - "homepage": "https://github.com/php-fig/http-message", - "keywords": [ - "http", - "http-message", - "psr", - "psr-7", - "request", - "response" - ], - "time": "2016-08-06T14:39:51+00:00" - }, - { - "name": "satooshi/php-coveralls", - "version": "dev-master", - "source": { - "type": "git", - "url": "https://github.com/php-coveralls/php-coveralls.git", - "reference": "c9d3fe2327c8539f1105dc19954673ba993e4ad9" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/php-coveralls/php-coveralls/zipball/c9d3fe2327c8539f1105dc19954673ba993e4ad9", - "reference": "c9d3fe2327c8539f1105dc19954673ba993e4ad9", - "shasum": "" - }, - "require": { - "ext-json": "*", - "ext-simplexml": "*", - "guzzlehttp/guzzle": "^6.0", - "php": "^5.5 || ^7.0", - "psr/log": "^1.0", - "symfony/config": "^2.1 || ^3.0 || ^4.0", - "symfony/console": "^2.1 || ^3.0 || ^4.0", - "symfony/stopwatch": "^2.0 || ^3.0 || ^4.0", - "symfony/yaml": "^2.0 || ^3.0 || ^4.0" - }, - "require-dev": { - "phpunit/phpunit": "^4.8.35 || ^5.4.3 || ^6.0" - }, - "suggest": { - "symfony/http-kernel": "Allows Symfony integration" - }, - "bin": [ - "bin/coveralls" - ], - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.0-dev" - } - }, - "autoload": { - "psr-4": { - "PhpCoveralls\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Kitamura Satoshi", - "email": "with.no.parachute@gmail.com", - "homepage": "https://www.facebook.com/satooshi.jp", - "role": "Original creator" - }, - { - "name": "Takashi Matsuo", - "email": "tmatsuo@google.com" - }, - { - "name": "Google Inc" - }, - { - "name": "Dariusz Ruminski", - "email": "dariusz.ruminski@gmail.com", - "homepage": "https://github.com/keradus" - }, - { - "name": "Contributors", - "homepage": "https://github.com/php-coveralls/php-coveralls/graphs/contributors" - } - ], - "description": "PHP client library for Coveralls API", - "homepage": "https://github.com/php-coveralls/php-coveralls", - "keywords": [ - "ci", - "coverage", - "github", - "test" - ], - "time": "2017-10-14T23:16:28+00:00" - }, - { - "name": "sebastian/comparator", - "version": "1.2.4", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/comparator.git", - "reference": "2b7424b55f5047b47ac6e5ccb20b2aea4011d9be" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/2b7424b55f5047b47ac6e5ccb20b2aea4011d9be", - "reference": "2b7424b55f5047b47ac6e5ccb20b2aea4011d9be", - "shasum": "" - }, - "require": { - "php": ">=5.3.3", - "sebastian/diff": "~1.2", - "sebastian/exporter": "~1.2 || ~2.0" - }, - "require-dev": { - "phpunit/phpunit": "~4.4" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.2.x-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Jeff Welch", - "email": "whatthejeff@gmail.com" - }, - { - "name": "Volker Dusch", - "email": "github@wallbash.com" - }, - { - "name": "Bernhard Schussek", - "email": "bschussek@2bepublished.at" - }, - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - } - ], - "description": "Provides the functionality to compare PHP values for equality", - "homepage": "http://www.github.com/sebastianbergmann/comparator", - "keywords": [ - "comparator", - "compare", - "equality" - ], - "time": "2017-01-29T09:50:25+00:00" - }, - { - "name": "sebastian/diff", - "version": "1.4.3", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/diff.git", - "reference": "7f066a26a962dbe58ddea9f72a4e82874a3975a4" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/7f066a26a962dbe58ddea9f72a4e82874a3975a4", - "reference": "7f066a26a962dbe58ddea9f72a4e82874a3975a4", - "shasum": "" - }, - "require": { - "php": "^5.3.3 || ^7.0" - }, - "require-dev": { - "phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.4-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Kore Nordmann", - "email": "mail@kore-nordmann.de" - }, - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - } - ], - "description": "Diff implementation", - "homepage": "https://github.com/sebastianbergmann/diff", - "keywords": [ - "diff" - ], - "time": "2017-05-22T07:24:03+00:00" - }, - { - "name": "sebastian/environment", - "version": "1.3.8", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/environment.git", - "reference": "be2c607e43ce4c89ecd60e75c6a85c126e754aea" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/be2c607e43ce4c89ecd60e75c6a85c126e754aea", - "reference": "be2c607e43ce4c89ecd60e75c6a85c126e754aea", - "shasum": "" - }, - "require": { - "php": "^5.3.3 || ^7.0" - }, - "require-dev": { - "phpunit/phpunit": "^4.8 || ^5.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.3.x-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - } - ], - "description": "Provides functionality to handle HHVM/PHP environments", - "homepage": "http://www.github.com/sebastianbergmann/environment", - "keywords": [ - "Xdebug", - "environment", - "hhvm" - ], - "time": "2016-08-18T05:49:44+00:00" - }, - { - "name": "sebastian/exporter", - "version": "1.2.2", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/exporter.git", - "reference": "42c4c2eec485ee3e159ec9884f95b431287edde4" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/42c4c2eec485ee3e159ec9884f95b431287edde4", - "reference": "42c4c2eec485ee3e159ec9884f95b431287edde4", - "shasum": "" - }, - "require": { - "php": ">=5.3.3", - "sebastian/recursion-context": "~1.0" - }, - "require-dev": { - "ext-mbstring": "*", - "phpunit/phpunit": "~4.4" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.3.x-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Jeff Welch", - "email": "whatthejeff@gmail.com" - }, - { - "name": "Volker Dusch", - "email": "github@wallbash.com" - }, - { - "name": "Bernhard Schussek", - "email": "bschussek@2bepublished.at" - }, - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - }, - { - "name": "Adam Harvey", - "email": "aharvey@php.net" - } - ], - "description": "Provides the functionality to export PHP variables for visualization", - "homepage": "http://www.github.com/sebastianbergmann/exporter", - "keywords": [ - "export", - "exporter" - ], - "time": "2016-06-17T09:04:28+00:00" - }, - { - "name": "sebastian/global-state", - "version": "1.1.1", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/global-state.git", - "reference": "bc37d50fea7d017d3d340f230811c9f1d7280af4" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/bc37d50fea7d017d3d340f230811c9f1d7280af4", - "reference": "bc37d50fea7d017d3d340f230811c9f1d7280af4", - "shasum": "" - }, - "require": { - "php": ">=5.3.3" - }, - "require-dev": { - "phpunit/phpunit": "~4.2" - }, - "suggest": { - "ext-uopz": "*" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - } - ], - "description": "Snapshotting of global state", - "homepage": "http://www.github.com/sebastianbergmann/global-state", - "keywords": [ - "global state" - ], - "time": "2015-10-12T03:26:01+00:00" - }, - { - "name": "sebastian/recursion-context", - "version": "1.0.5", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/recursion-context.git", - "reference": "b19cc3298482a335a95f3016d2f8a6950f0fbcd7" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/b19cc3298482a335a95f3016d2f8a6950f0fbcd7", - "reference": "b19cc3298482a335a95f3016d2f8a6950f0fbcd7", - "shasum": "" - }, - "require": { - "php": ">=5.3.3" - }, - "require-dev": { - "phpunit/phpunit": "~4.4" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.0.x-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Jeff Welch", - "email": "whatthejeff@gmail.com" - }, - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - }, - { - "name": "Adam Harvey", - "email": "aharvey@php.net" - } - ], - "description": "Provides functionality to recursively process PHP variables", - "homepage": "http://www.github.com/sebastianbergmann/recursion-context", - "time": "2016-10-03T07:41:43+00:00" - }, - { - "name": "sebastian/version", - "version": "1.0.6", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/version.git", - "reference": "58b3a85e7999757d6ad81c787a1fbf5ff6c628c6" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/version/zipball/58b3a85e7999757d6ad81c787a1fbf5ff6c628c6", - "reference": "58b3a85e7999757d6ad81c787a1fbf5ff6c628c6", - "shasum": "" - }, - "type": "library", - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" - } - ], - "description": "Library that helps with managing the version number of Git-hosted PHP projects", - "homepage": "https://github.com/sebastianbergmann/version", - "time": "2015-06-21T13:59:46+00:00" - }, - { - "name": "squizlabs/php_codesniffer", - "version": "2.9.1", - "source": { - "type": "git", - "url": "https://github.com/squizlabs/PHP_CodeSniffer.git", - "reference": "dcbed1074f8244661eecddfc2a675430d8d33f62" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/squizlabs/PHP_CodeSniffer/zipball/dcbed1074f8244661eecddfc2a675430d8d33f62", - "reference": "dcbed1074f8244661eecddfc2a675430d8d33f62", - "shasum": "" - }, - "require": { - "ext-simplexml": "*", - "ext-tokenizer": "*", - "ext-xmlwriter": "*", - "php": ">=5.1.2" - }, - "require-dev": { - "phpunit/phpunit": "~4.0" - }, - "bin": [ - "scripts/phpcs", - "scripts/phpcbf" - ], - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.x-dev" - } - }, - "autoload": { - "classmap": [ - "CodeSniffer.php", - "CodeSniffer/CLI.php", - "CodeSniffer/Exception.php", - "CodeSniffer/File.php", - "CodeSniffer/Fixer.php", - "CodeSniffer/Report.php", - "CodeSniffer/Reporting.php", - "CodeSniffer/Sniff.php", - "CodeSniffer/Tokens.php", - "CodeSniffer/Reports/", - "CodeSniffer/Tokenizers/", - "CodeSniffer/DocGenerators/", - "CodeSniffer/Standards/AbstractPatternSniff.php", - "CodeSniffer/Standards/AbstractScopeSniff.php", - "CodeSniffer/Standards/AbstractVariableSniff.php", - "CodeSniffer/Standards/IncorrectPatternException.php", - "CodeSniffer/Standards/Generic/Sniffs/", - "CodeSniffer/Standards/MySource/Sniffs/", - "CodeSniffer/Standards/PEAR/Sniffs/", - "CodeSniffer/Standards/PSR1/Sniffs/", - "CodeSniffer/Standards/PSR2/Sniffs/", - "CodeSniffer/Standards/Squiz/Sniffs/", - "CodeSniffer/Standards/Zend/Sniffs/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Greg Sherwood", - "role": "lead" - } - ], - "description": "PHP_CodeSniffer tokenizes PHP, JavaScript and CSS files and detects violations of a defined set of coding standards.", - "homepage": "http://www.squizlabs.com/php-codesniffer", - "keywords": [ - "phpcs", - "standards" - ], - "time": "2017-05-22T02:43:20+00:00" - }, - { - "name": "symfony/config", - "version": "v4.0.4", - "source": { - "type": "git", - "url": "https://github.com/symfony/config.git", - "reference": "ecd917899167922086ddb3247aa43eb1c418fcb2" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/config/zipball/ecd917899167922086ddb3247aa43eb1c418fcb2", - "reference": "ecd917899167922086ddb3247aa43eb1c418fcb2", - "shasum": "" - }, - "require": { - "php": "^7.1.3", - "symfony/filesystem": "~3.4|~4.0" - }, - "conflict": { - "symfony/finder": "<3.4" - }, - "require-dev": { - "symfony/finder": "~3.4|~4.0", - "symfony/yaml": "~3.4|~4.0" - }, - "suggest": { - "symfony/yaml": "To use the yaml reference dumper" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "4.0-dev" - } - }, - "autoload": { - "psr-4": { - "Symfony\\Component\\Config\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Symfony Config Component", - "homepage": "https://symfony.com", - "time": "2018-01-21T19:06:11+00:00" - }, - { - "name": "symfony/filesystem", - "version": "v4.0.4", - "source": { - "type": "git", - "url": "https://github.com/symfony/filesystem.git", - "reference": "760e47a4ee64b4c48f4b30017011e09d4c0f05ed" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/filesystem/zipball/760e47a4ee64b4c48f4b30017011e09d4c0f05ed", - "reference": "760e47a4ee64b4c48f4b30017011e09d4c0f05ed", - "shasum": "" - }, - "require": { - "php": "^7.1.3" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "4.0-dev" - } - }, - "autoload": { - "psr-4": { - "Symfony\\Component\\Filesystem\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Symfony Filesystem Component", - "homepage": "https://symfony.com", - "time": "2018-01-03T07:38:00+00:00" - }, - { - "name": "symfony/stopwatch", - "version": "v4.0.4", - "source": { - "type": "git", - "url": "https://github.com/symfony/stopwatch.git", - "reference": "d52321f0e2b596bd03b5d1dd6eebe71caa925704" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/stopwatch/zipball/d52321f0e2b596bd03b5d1dd6eebe71caa925704", - "reference": "d52321f0e2b596bd03b5d1dd6eebe71caa925704", - "shasum": "" - }, - "require": { - "php": "^7.1.3" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "4.0-dev" - } - }, - "autoload": { - "psr-4": { - "Symfony\\Component\\Stopwatch\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Symfony Stopwatch Component", - "homepage": "https://symfony.com", - "time": "2018-01-03T07:38:00+00:00" - }, - { - "name": "symfony/yaml", - "version": "v3.4.4", - "source": { - "type": "git", - "url": "https://github.com/symfony/yaml.git", - "reference": "eab73b6c21d27ae4cd037c417618dfd4befb0bfe" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/yaml/zipball/eab73b6c21d27ae4cd037c417618dfd4befb0bfe", - "reference": "eab73b6c21d27ae4cd037c417618dfd4befb0bfe", - "shasum": "" - }, - "require": { - "php": "^5.5.9|>=7.0.8" - }, - "conflict": { - "symfony/console": "<3.4" - }, - "require-dev": { - "symfony/console": "~3.4|~4.0" - }, - "suggest": { - "symfony/console": "For validating YAML files using the lint command" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "3.4-dev" - } - }, - "autoload": { - "psr-4": { - "Symfony\\Component\\Yaml\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Symfony Yaml Component", - "homepage": "https://symfony.com", - "time": "2018-01-21T19:05:02+00:00" - }, - { - "name": "webmozart/assert", - "version": "1.3.0", - "source": { - "type": "git", - "url": "https://github.com/webmozart/assert.git", - "reference": "0df1908962e7a3071564e857d86874dad1ef204a" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/webmozart/assert/zipball/0df1908962e7a3071564e857d86874dad1ef204a", - "reference": "0df1908962e7a3071564e857d86874dad1ef204a", - "shasum": "" - }, - "require": { - "php": "^5.3.3 || ^7.0" - }, - "require-dev": { - "phpunit/phpunit": "^4.6", - "sebastian/version": "^1.0.1" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.3-dev" - } - }, - "autoload": { - "psr-4": { - "Webmozart\\Assert\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Bernhard Schussek", - "email": "bschussek@gmail.com" - } - ], - "description": "Assertions to validate method input/output with nice error messages.", - "keywords": [ - "assert", - "check", - "validate" - ], - "time": "2018-01-29T19:49:41+00:00" - } - ], - "aliases": [], - "minimum-stability": "stable", - "stability-flags": { - "satooshi/php-coveralls": 20 - }, - "prefer-stable": false, - "prefer-lowest": false, - "platform": { - "php": ">=5.4.0" - }, - "platform-dev": [] -} diff -r e200cb7efeb3 -r c2387f117808 vendor/consolidation/annotated-command/scenarios/symfony4/src --- a/vendor/consolidation/annotated-command/scenarios/symfony4/src Thu Apr 26 11:26:54 2018 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1 +0,0 @@ -../../src \ No newline at end of file diff -r e200cb7efeb3 -r c2387f117808 vendor/consolidation/annotated-command/scenarios/symfony4/tests --- a/vendor/consolidation/annotated-command/scenarios/symfony4/tests Thu Apr 26 11:26:54 2018 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1 +0,0 @@ -../../tests \ No newline at end of file diff -r e200cb7efeb3 -r c2387f117808 vendor/consolidation/annotated-command/tests/FullyQualifiedClassCacheTests.php --- a/vendor/consolidation/annotated-command/tests/FullyQualifiedClassCacheTests.php Thu Apr 26 11:26:54 2018 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,59 +0,0 @@ -getFileName(); - - $fqcnCache = new FullyQualifiedClassCache(); - - $handle = fopen($filename, "r"); - $this->assertTrue($handle !== false); - - $namespaceName = $this->callProtected($fqcnCache, 'readNamespace', [$handle]); - - $this->assertEquals('Consolidation\TestUtils\alpha', $namespaceName); - - $usedClasses = $this->callProtected($fqcnCache, 'readUseStatements', [$handle]); - - $this->assertTrue(isset($usedClasses['RowsOfFields'])); - $this->assertEquals('Consolidation\OutputFormatters\StructuredData\RowsOfFields', $usedClasses['RowsOfFields']); - - fclose($handle); - - $fqcn = $fqcnCache->qualify($filename, 'RowsOfFields'); - $this->assertEquals('Consolidation\OutputFormatters\StructuredData\RowsOfFields', $fqcn); - - $fqcn = $fqcnCache->qualify($filename, 'ClassWithoutUse'); - $this->assertEquals('Consolidation\TestUtils\alpha\ClassWithoutUse', $fqcn); - - $fqcn = $fqcnCache->qualify($filename, 'ExampleAliasedClass'); - $this->assertEquals('Consolidation\TestUtils\ExampleCommandFile', $fqcn); - } - - function callProtected($object, $method, $args = []) - { - $r = new \ReflectionMethod($object, $method); - $r->setAccessible(true); - return $r->invokeArgs($object, $args); - } -} diff -r e200cb7efeb3 -r c2387f117808 vendor/consolidation/annotated-command/tests/src/ApplicationWithTerminalWidth.php --- a/vendor/consolidation/annotated-command/tests/src/ApplicationWithTerminalWidth.php Thu Apr 26 11:26:54 2018 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,26 +0,0 @@ -width = $width; - $this->height = $height; - } - - public function getTerminalDimensions() - { - return [ $this->width, $this->height ]; - } -} diff -r e200cb7efeb3 -r c2387f117808 vendor/consolidation/annotated-command/tests/src/ExampleAnnotatedCommand.php --- a/vendor/consolidation/annotated-command/tests/src/ExampleAnnotatedCommand.php Thu Apr 26 11:26:54 2018 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,63 +0,0 @@ -getArgument('one'); - $two = $input->getArgument('two'); - $multiple = $input->getOption('multiple'); - $flip = $input->getOption('flip'); - - $result = $this->myCat($one, $two, $multiple, $flip); - - // We could also just use $output->writeln($result) here, - // but calling processResults enables the use of output - // formatters. Note also that if you use processResults, you - // should correctly inject the command processor into your - // annotated command via AnnotatedCommand::setCommandProcessor(). - return $this->processResults($input, $output, $result); - } -} diff -r e200cb7efeb3 -r c2387f117808 vendor/consolidation/annotated-command/tests/src/ExampleCommandFile.php --- a/vendor/consolidation/annotated-command/tests/src/ExampleCommandFile.php Thu Apr 26 11:26:54 2018 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,521 +0,0 @@ -state = $state; - } - - public function setOutput($output) - { - $this->output = $output; - } - - /** - * Import config from a config directory. - * - * @command config:import - * @param $label A config directory label (i.e. a key in \$config_directories array in settings.php). - * @interact-config-label - * @option preview Format for displaying proposed changes. Recognized values: list, diff. - * @option source An arbitrary directory that holds the configuration files. An alternative to label argument - * @option partial Allows for partial config imports from the source directory. Only updates and new configs will be processed with this flag (missing configs will not be deleted). - * @aliases cim,config-import - */ - public function import($label = null, $options = ['preview' => 'list', 'source' => InputOption::VALUE_REQUIRED, 'partial' => false]) - { - } - - /** - * Calculate the fibonacci sequence between two numbers. - * - * Graphic output will look like - * +----+---+-------------+ - * | | | | - * | |-+-| | - * |----+-+-+ | - * | | | - * | | | - * | | | - * +--------+-------------+ - * - * @param int $start Number to start from - * @param int $steps Number of steps to perform - * @param array $opts - * @option $graphic Display the sequence graphically using cube - * representation - */ - public function fibonacci($start, $steps, $opts = ['graphic' => false]) - { - } - - /** - * Code sniffer. - * - * Run the PHP Codesniffer on a file or directory. - * - * @param string $file - * A file or directory to analyze. - * @option $autofix Whether to run the automatic fixer or not. - * @option $strict Show warnings as well as errors. - * Default is to show only errors. - */ - public function sniff( - $file = 'src', - array $options = [ - 'autofix' => false, - 'strict' => false, - ] - ) { - return var_export($options, true); - } - - /** - * This is the my:cat command - * - * This command will concatenate two parameters. If the --flip flag - * is provided, then the result is the concatenation of two and one. - * - * @param string $one The first parameter. - * @param string $two The other parameter. - * @option boolean $flip Whether or not the second parameter should come first in the result. - * @aliases c - * @usage bet alpha --flip - * Concatenate "alpha" and "bet". - * @arbitrary This annotation is here merely as a marker used in testing. - */ - public function myCat($one, $two = '', array $options = ['flip' => false]) - { - if ($options['flip']) { - return "{$two}{$one}"; - } - return "{$one}{$two}"; - } - - /** - * @command my:repeat - */ - public function myRepeat($one, $two = '', array $options = ['repeat' => 1]) - { - return str_repeat("{$one}{$two}", $options['repeat']); - } - - /** - * This is the my:join command - * - * This command will join its parameters together. It can also reverse and repeat its arguments. - * - * @command my:join - * @usage a b - * Join a and b to produce "a,b" - * @usage - * Example with no parameters or options - */ - public function myJoin(array $args, array $options = ['flip' => false, 'repeat' => 1]) - { - if ($options['flip']) { - $args = array_reverse($args); - } - $result = implode('', $args); - return str_repeat($result, $options['repeat']); - } - - /** - * This is a command with no options - * - * This command will concatenate two parameters. - * - * @param $one The first parameter. - * @param $two The other parameter. - * @aliases nope - * @usage alpha bet - * Concatenate "alpha" and "bet". - */ - public function commandWithNoOptions($one, $two = 'default') - { - return "{$one}{$two}"; - } - - /** - * This command work with app's input and output - * - * @command command:with-io-parameters - */ - public function commandWithIOParameters(InputInterface $input, OutputInterface $output) - { - return $input->getFirstArgument(); - } - - /** - * This command has no arguments--only options - * - * Return a result only if not silent. - * - * @option silent Supress output. - */ - public function commandWithNoArguments(array $opts = ['silent|s' => false]) - { - if (!$opts['silent']) { - return "Hello, world"; - } - } - - /** - * Shortcut on annotation - * - * This command defines the option shortcut on the annotation instead of in the options array. - * - * @param $opts The options - * @option silent|s Supress output. - */ - public function shortcutOnAnnotation(array $opts = ['silent' => false]) - { - if (!$opts['silent']) { - return "Hello, world"; - } - } - - /** - * This is the test:arithmatic command - * - * This command will add one and two. If the --negate flag - * is provided, then the result is negated. - * - * @command test:arithmatic - * @param integer $one The first number to add. - * @param integer $two The other number to add. - * @option negate Whether or not the result should be negated. - * @aliases arithmatic - * @usage 2 2 --negate - * Add two plus two and then negate. - * @custom - * @dup one - * @dup two - */ - public function testArithmatic($one, $two = 2, array $options = ['negate' => false, 'unused' => 'bob']) - { - $result = $one + $two; - if ($options['negate']) { - $result = -$result; - } - - // Integer return codes are exit codes (errors), so - // return a the result as a string so that it will be printed. - return "$result"; - } - - /** - * This is the test:state command - * - * This command tests to see if the state of the Commandfile instance - */ - public function testState() - { - return $this->state; - } - - /** - * This is the test:passthrough command - * - * This command takes a variable number of parameters as - * an array and returns them as a csv. - */ - public function testPassthrough(array $params) - { - return implode(',', $params); - } - - /** - * This command wraps its parameter in []; its alter hook - * then wraps the result in <>. - */ - public function testHook($parameter) - { - return "[$parameter]"; - } - - /** - * Wrap the results of test:hook in <>. - * - * @hook alter test:hook - */ - public function hookTestHook($result) - { - return "<$result>"; - } - - /** - * This test is very similar to the preceding test, except - * it uses an annotation hook instead of a named-function hook. - * - * @hookme - * @before > - * @after < - */ - public function testAnnotationHook($parameter) - { - return "($parameter)"; - } - - /** - * Wrap the results of test:hook in whatever the @before and @after - * annotations contain. - * - * @hook alter @hookme - */ - public function hookTestAnnotatedHook($result, CommandData $commandData) - { - $before = $commandData->annotationData()->get('before', '-'); - $after = $commandData->annotationData()->get('after', '-'); - return "$before$result$after"; - } - - /** - * Alter the results of the hook with its command name. - * - * @hook alter @addmycommandname - */ - public function hookAddCommandName($result, CommandData $commandData) - { - $annotationData = $commandData->annotationData(); - return "$result from " . $annotationData['command']; - } - - /** - * Here is a hook with an explicit command annotation that we will alter - * with the preceeding hook - * - * @command alter-me - * @addmycommandname - */ - public function alterMe() - { - return "splendiferous"; - } - - /** - * Here is another hook that has no command annotation that should be - * altered with the default value for the command name - * - * @addmycommandname - */ - public function alterMeToo() - { - return "fantabulous"; - } - - /** - * @command test:replace-command - */ - public function testReplaceCommand($value) - { - $this->output->writeln($value); - } - - /** - * @hook replace-command test:replace-command - */ - public function hookTestReplaceCommandHook($value) - { - $this->output->writeln("bar"); - } - - /** - * @hook pre-command test:post-command - */ - public function hookTestPreCommandHook(CommandData $commandData) - { - // Use 'writeln' to detect order that hooks are called - $this->output->writeln("foo"); - } - - /** - * @command test:post-command - */ - public function testPostCommand($value) - { - $this->output->writeln($value); - } - - /** - * @hook post-command test:post-command - */ - public function hookTestPostCommandHook($result, CommandData $commandData) - { - // Use 'writeln' to detect order that hooks are called - $this->output->writeln("baz"); - } - - public function testHello($who) - { - return "Hello, $who."; - } - - public function testException($what) - { - throw new \Exception($what); - } - - /** - * @hook init test:hello - */ - public function initializeTestHello($input, AnnotationData $annotationData) - { - $who = $input->getArgument('who'); - if (!$who) { - $input->setArgument('who', 'Huey'); - } - } - - /** - * @hook command-event test:hello - */ - public function commandEventTestHello(ConsoleCommandEvent $event) - { - // Note that Symfony Console will not allow us to alter the - // input from this hook, so we'll just print something to - // show that this hook was executed. - $input = $event->getInput(); - $who = $input->getArgument('who'); - $this->output->writeln("Here comes $who!"); - } - - /** - * @hook interact test:hello - */ - public function interactTestHello($input, $output) - { - $who = $input->getArgument('who'); - if (!$who) { - $input->setArgument('who', 'Goofey'); - } - } - - /** - * @hook validate test:hello - */ - public function validateTestHello($commandData) - { - $args = $commandData->arguments(); - if ($args['who'] == 'Donald Duck') { - return new CommandError("I won't say hello to Donald Duck."); - } - if ($args['who'] == 'Drumph') { - throw new \Exception('Irrational value error.'); - } - } - - /** - * Test default values in arguments - * - * @param string|null $one - * @param string|null $two - * @return string - */ - public function defaults($one = null, $two = null) - { - if ($one && $two) { - return "$one and $two"; - } - if ($one) { - return "only $one"; - } - return "nothing provided"; - } - - /** - * @return string - */ - public function defaultOptionOne(array $options = ['foo' => '1']) - { - return "Foo is " . $options['foo']; - } - - /** - * @return string - */ - public function defaultOptionTwo(array $options = ['foo' => '2']) - { - return "Foo is " . $options['foo']; - } - - /** - * @return string - */ - public function defaultOptionNone(array $options = ['foo' => InputOption::VALUE_REQUIRED]) - { - return "Foo is " . $options['foo']; - } - - /** - * @return string - */ - public function defaultOptionalValue(array $options = ['foo' => InputOption::VALUE_OPTIONAL]) - { - return "Foo is " . var_export($options['foo'], true); - } - - /** - * @return string - */ - public function defaultOptionDefaultsToTrue(array $options = ['foo' => true]) - { - return "Foo is " . var_export($options['foo'], true); - } - - /** - * This is the test:required-array-option command - * - * This command will print all the valused of passed option - * - * @param array $opts - * @return string - */ - public function testRequiredArrayOption(array $opts = ['arr|a' => []]) - { - return implode(' ', $opts['arr']); - } - - /** - * This is the test:array-option command - * - * This command will print all the valused of passed option - * - * @param array $opts - * @return string - */ - public function testArrayOption(array $opts = ['arr|a' => ['1', '2', '3']]) - { - return implode(' ', $opts['arr']); - } - - /** - * @command global-options-only - */ - public function globalOptionsOnly($arg, array $options = []) - { - return "Arg is $arg, options[help] is " . var_export($options['help'], true) . "\n"; - } -} diff -r e200cb7efeb3 -r c2387f117808 vendor/consolidation/annotated-command/tests/src/ExampleCommandInfoAlterer.php --- a/vendor/consolidation/annotated-command/tests/src/ExampleCommandInfoAlterer.php Thu Apr 26 11:26:54 2018 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,15 +0,0 @@ -hasAnnotation('arbitrary')) { - $commandInfo->addAnnotation('dynamic', "This annotation was dynamically added by ExampleCommandInfoAlterer"); - } - } -} diff -r e200cb7efeb3 -r c2387f117808 vendor/consolidation/annotated-command/tests/src/ExampleHookAllCommandFile.php --- a/vendor/consolidation/annotated-command/tests/src/ExampleHookAllCommandFile.php Thu Apr 26 11:26:54 2018 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,41 +0,0 @@ - false]) - { - if ($options['flip']) { - return "{$two}{$one}"; - } - return "{$one}{$two}"; - } - - public function doRepeat($one, $two = '', $options = ['repeat' => 1]) - { - return str_repeat("{$one}{$two}", $options['repeat']); - } - - /** - * This hook function does not specify which command or annotation - * it is hooking; that makes it apply to every command in the same class. - * - * @hook alter - */ - public function alterAllCommands($result) - { - if (is_string($result)) { - $result = "*** $result ***"; - } - return $result; - } -} diff -r e200cb7efeb3 -r c2387f117808 vendor/consolidation/annotated-command/tests/src/InMemoryCacheStore.php --- a/vendor/consolidation/annotated-command/tests/src/InMemoryCacheStore.php Thu Apr 26 11:26:54 2018 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,50 +0,0 @@ -cache = []; - } - - /** - * Test for an entry from the cache - * @param string $key - * @return boolean - */ - public function has($key) - { - return array_key_exists($key, $this->cache); - } - - /** - * Get an entry from the cache - * @param string $key - * @return array - */ - public function get($key) - { - if (!$this->has($key)) { - return []; - } - return $this->cache[$key]; - } - - /** - * Store an entry in the cache - * @param string $key - * @param array $data - */ - public function set($key, $data) - { - $this->cache[$key] = $data; - } -} diff -r e200cb7efeb3 -r c2387f117808 vendor/consolidation/annotated-command/tests/src/TestTerminal.php --- a/vendor/consolidation/annotated-command/tests/src/TestTerminal.php Thu Apr 26 11:26:54 2018 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,22 +0,0 @@ -width = $width; - } - - public function getWidth() - { - return $this->width; - } - - public function setWidth($width) - { - $this->width = $width; - } -} diff -r e200cb7efeb3 -r c2387f117808 vendor/consolidation/annotated-command/tests/src/alpha/AlphaCommandFile.php --- a/vendor/consolidation/annotated-command/tests/src/alpha/AlphaCommandFile.php Thu Apr 26 11:26:54 2018 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,325 +0,0 @@ - 42]; - } - - /** - * @command example:output - */ - public function exampleOutput() - { - return 'Hello, World.'; - } - - /** - * @command example:cat - */ - public function exampleCat($one, $two = '', $options = ['flip' => false]) - { - if ($options['flip']) { - return "{$two}{$one}"; - } - return "{$one}{$two}"; - } - - /** - * @command example:echo - */ - public function exampleEcho(array $args) - { - return ['item-list' => $args]; - } - - /** - * @command example:message - */ - public function exampleMessage() - { - return ['message' => 'Shipwrecked; send bananas.']; - } - - /** - * Test command with formatters - * - * @command example:table - * @param $unused An unused argument - * @field-labels - * first: I - * second: II - * third: III - * @usage example:table --format=yml - * Show the example table in yml format. - * @usage example:table --fields=first,third - * Show only the first and third fields in the table. - * @usage example:table --fields=II,III - * Note that either the field ID or the visible field label may be used. - * @aliases extab - * @topics docs-tables - * @return \Consolidation\OutputFormatters\StructuredData\RowsOfFields Fully-qualified class name - */ - public function exampleTable($unused = '', $options = ['format' => 'table', 'fields' => '']) - { - $outputData = [ - [ 'first' => 'One', 'second' => 'Two', 'third' => 'Three' ], - [ 'first' => 'Eins', 'second' => 'Zwei', 'third' => 'Drei' ], - [ 'first' => 'Ichi', 'second' => 'Ni', 'third' => 'San' ], - [ 'first' => 'Uno', 'second' => 'Dos', 'third' => 'Tres' ], - ]; - return new RowsOfFields($outputData); - } - - /** - * Test command with formatters using a short classname in @return - * - * @command example:table2 - * @param $unused An unused argument - * @field-labels - * first: I - * second: II - * third: III - * @usage example:table --format=yml - * Show the example table in yml format. - * @usage example:table --fields=first,third - * Show only the first and third fields in the table. - * @usage example:table --fields=II,III - * Note that either the field ID or the visible field label may be used. - * @aliases extab - * @topics docs-tables - * @return RowsOfFields Short class names are converted to fqcns - */ - public function exampleTableTwo($unused = '', $options = ['format' => 'table', 'fields' => '']) - { - $outputData = [ - [ 'first' => 'One', 'second' => 'Two', 'third' => 'Three' ], - [ 'first' => 'Eins', 'second' => 'Zwei', 'third' => 'Drei' ], - [ 'first' => 'Ichi', 'second' => 'Ni', 'third' => 'San' ], - [ 'first' => 'Uno', 'second' => 'Dos', 'third' => 'Tres' ], - ]; - return new RowsOfFields($outputData); - } - - /** - * Test word wrapping - * - * @command example:wrap - * @field-labels - * first: First - * second: Second - * - * @return \Consolidation\OutputFormatters\StructuredData\RowsOfFields - */ - public function exampleWrap() - { - $data = [ - [ - 'first' => 'This is a really long cell that contains a lot of data. When it is rendered, it should be wrapped across multiple lines.', - 'second' => 'This is the second column of the same table. It is also very long, and should be wrapped across multiple lines, just like the first column.', - ] - ]; - return new RowsOfFields($data); - } - - /** - * @hook option example:table - */ - public function additionalOptionForExampleTable(Command $command, AnnotationData $annotationData) - { - $command->addOption( - 'dynamic', - '', - InputOption::VALUE_NONE, - 'Option added by @hook option example:table' - ); - } - - /** - * Demonstrate an alter hook with an option - * - * @hook alter example:table - * @option french Add a row with French numbers. - * @usage example:table --french - */ - public function alterFormatters($result, CommandData $commandData) - { - if ($commandData->input()->getOption('french')) { - $result[] = [ 'first' => 'Un', 'second' => 'Deux', 'third' => 'Trois' ]; - } - - return $result; - } - - /** - * Test command with formatters using an associative list - * - * @command example:list - * @field-labels - * sftp_command: SFTP Command - * sftp_username: SFTP Username - * sftp_host: SFTP Host - * sftp_password: SFTP Password - * sftp_url: SFTP URL - * git_command: Git Command - * git_username: Git Username - * git_host: Git Host - * git_port: Git Port - * git_url: Git URL - * mysql_command: MySQL Command - * mysql_username: MySQL Username - * mysql_host: MySQL Host - * mysql_password: MySQL Password - * mysql_url: MySQL URL - * mysql_port: MySQL Port - * mysql_database: MySQL Database - * redis_command: Redis Command - * redis_port: Redis Port - * redis_url: Redis URL - * redis_password: Redis Password - * @default-fields *_command - * @return \Consolidation\OutputFormatters\StructuredData\AssociativeList - */ - public function exampleAssociativeList() - { - $outputData = [ - 'sftp_command' => 'sftp -o Port=2222 dev@appserver.dev.drush.in', - 'sftp_username' => 'dev', - 'sftp_host' => 'appserver.dev.drush.in', - 'sftp_password' => 'Use your account password', - 'sftp_url' => 'sftp://dev@appserver.dev.drush.in:2222', - 'git_command' => 'git clone ssh://codeserver.dev@codeserver.dev.drush.in:2222/~/repository.git wp-update', - 'git_username' => 'codeserver.dev', - 'git_host' => 'codeserver.dev.drush.in', - 'git_port' => 2222, - 'git_url' => 'ssh://codeserver.dev@codeserver.dev.drush.in:2222/~/repository.git', - 'mysql_command' => 'mysql -u pantheon -p4b33cb -h dbserver.dev.drush.in -P 16191 pantheon', - 'mysql_username' => 'pantheon', - 'mysql_host' => 'dbserver.dev.drush.in', - 'mysql_password' => '4b33cb', - 'mysql_url' => 'mysql://pantheon:4b33cb@dbserver.dev.drush.in:16191/pantheon', - 'mysql_port' => 16191, - 'mysql_database' => 'pantheon', - ]; - return new AssociativeList($outputData); - } - - /** - * This command has no annotations; this means that it will not be - * found when createCommandsFromClass() is called with - * '$includeAllPublicMethods' set to false. - */ - public function withoutAnnotations() - { - return 'ok'; - } - - /** - * @command command:with-one-optional-argument - * - * This command has just one optional argument. - * - * Return a result only if not silent. - * - * @option silent Supress output. - */ - public function commandWithOneOptionalArgument($who = 'world', $opts = ['silent|s' => false]) - { - if (!$opts['silent']) { - return "Hello, $who"; - } - } - - /** - * This should be a command, because it is annotated like one. - * - * @command get:serious - */ - public function getSerious() - { - return 'very serious'; - } - - /** - * This should not be a command, because it looks like an accessor and - * has no @command annotation. - */ - public function getLost() - { - return 'very lost'; - } - - /** - * This command uses a custom event 'my-event' to collect data. Note that - * the event handlers will not be found unless the hook manager is - * injected into this command handler object via `setHookManager()` - * (defined in CustomEventAwareTrait). - * - * @command use:event - */ - public function useEvent() - { - $myEventHandlers = $this->getCustomEventHandlers('my-event'); - $result = []; - foreach ($myEventHandlers as $handler) { - $result[] = $handler(); - } - sort($result); - return implode(',', $result); - } - - /** - * @hook on-event my-event - */ - public function hookOne() - { - return 'one'; - } - - /** - * @hook on-event my-event - */ - public function hookTwo() - { - return 'two'; - } -} diff -r e200cb7efeb3 -r c2387f117808 vendor/consolidation/annotated-command/tests/src/alpha/Exclude/ExcludedCommandFile.php --- a/vendor/consolidation/annotated-command/tests/src/alpha/Exclude/ExcludedCommandFile.php Thu Apr 26 11:26:54 2018 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,14 +0,0 @@ -input()->getOption('chinese')) { - $result[] = [ 'first' => '壹', 'second' => '貳', 'third' => '叁' ]; - } - - return $result; - } - - /** - * Demonstrate an alter hook with an option - * - * @hook alter * - * @option kanji Add a row with Kanji numbers. - * @usage example:table --kanji - */ - public function alterFormattersKanji($result, CommandData $commandData) - { - if ($commandData->input()->getOption('kanji')) { - $result[] = [ 'first' => '一', 'second' => '二', 'third' => '三' ]; - } - - return $result; - } -} diff -r e200cb7efeb3 -r c2387f117808 vendor/consolidation/annotated-command/tests/testAnnotatedCommand.php --- a/vendor/consolidation/annotated-command/tests/testAnnotatedCommand.php Thu Apr 26 11:26:54 2018 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,45 +0,0 @@ -assertInstanceOf('\Symfony\Component\Console\Command\Command', $command); - $this->assertEquals('my:cat', $command->getName()); - $this->assertEquals('This is the my:cat command implemented as an AnnotatedCommand subclass.', $command->getDescription()); - $this->assertEquals("This command will concatenate two parameters. If the --flip flag\nis provided, then the result is the concatenation of two and one.", $command->getHelp()); - $this->assertEquals('c', implode(',', $command->getAliases())); - // Symfony Console composes the synopsis; perhaps we should not test it. Remove if this gives false failures. - $this->assertEquals('my:cat [--multiple MULTIPLE] [--flip] [--] []', $command->getSynopsis()); - $this->assertEquals('my:cat bet alpha --flip', implode(',', $command->getUsages())); - - $input = new StringInput('my:cat b alpha --multiple=t --multiple=e --flip'); - $this->assertRunCommandViaApplicationEquals($command, $input, 'alphabet'); - } - - // TODO: Make a base test class to hold this. - function assertRunCommandViaApplicationEquals($command, $input, $expectedOutput, $expectedStatusCode = 0) - { - $output = new BufferedOutput(); - - $application = new Application('TestApplication', '0.0.0'); - $application->setAutoExit(false); - $application->add($command); - - $statusCode = $application->run($input, $output); - $commandOutput = trim($output->fetch()); - - $this->assertEquals($expectedOutput, $commandOutput); - $this->assertEquals($expectedStatusCode, $statusCode); - } -} diff -r e200cb7efeb3 -r c2387f117808 vendor/consolidation/annotated-command/tests/testAnnotatedCommandFactory.php --- a/vendor/consolidation/annotated-command/tests/testAnnotatedCommandFactory.php Thu Apr 26 11:26:54 2018 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,999 +0,0 @@ -commandFileInstance = new \Consolidation\TestUtils\ExampleCommandFile; - $this->commandFactory = new AnnotatedCommandFactory(); - $commandInfo = $this->commandFactory->createCommandInfo($this->commandFileInstance, 'fibonacci'); - - $command = $this->commandFactory->createCommand($commandInfo, $this->commandFileInstance); - $this->assertEquals('fibonacci', $command->getName()); - $this->assertEquals('fibonacci [--graphic] [--] ', $command->getSynopsis()); - $this->assertEquals('Calculate the fibonacci sequence between two numbers.', $command->getDescription()); - $this->assertEquals("Graphic output will look like -+----+---+-------------+ -| | | | -| |-+-| | -|----+-+-+ | -| | | -| | | -| | | -+--------+-------------+", $command->getHelp()); - - $this->assertInstanceOf('\Symfony\Component\Console\Command\Command', $command); - - $input = new StringInput('help fibonacci'); - $this->assertRunCommandViaApplicationContains($command, $input, ['Display the sequence graphically using cube representation']); - } - - function testSniff() - { - $this->commandFileInstance = new \Consolidation\TestUtils\ExampleCommandFile; - $this->commandFactory = new AnnotatedCommandFactory(); - $commandInfo = $this->commandFactory->createCommandInfo($this->commandFileInstance, 'sniff'); - - $command = $this->commandFactory->createCommand($commandInfo, $this->commandFileInstance); - $this->assertEquals('sniff', $command->getName()); - $this->assertEquals('sniff [--autofix] [--strict] [--] []', $command->getSynopsis()); - - $this->assertInstanceOf('\Symfony\Component\Console\Command\Command', $command); - - $input = new StringInput('help sniff'); - $this->assertRunCommandViaApplicationContains($command, $input, ['A file or directory to analyze.']); - - $input = new StringInput('sniff --autofix --strict -- foo'); - $this->assertRunCommandViaApplicationContains($command, $input, ["'autofix' => true", - "'strict' => true"]); - } - - function testOptionDefaultValue() - { - $this->commandFileInstance = new \Consolidation\TestUtils\ExampleCommandFile; - $this->commandFactory = new AnnotatedCommandFactory(); - $commandInfo = $this->commandFactory->createCommandInfo($this->commandFileInstance, 'defaultOptionOne'); - - $command = $this->commandFactory->createCommand($commandInfo, $this->commandFileInstance); - $this->assertEquals('default:option-one', $command->getName()); - $this->assertEquals('default:option-one [--foo [FOO]]', $command->getSynopsis()); - - $this->assertInstanceOf('\Symfony\Component\Console\Command\Command', $command); - - $input = new StringInput('default:option-one'); - $this->assertRunCommandViaApplicationEquals($command, $input, 'Foo is 1'); - - $commandInfo = $this->commandFactory->createCommandInfo($this->commandFileInstance, 'defaultOptionTwo'); - - $command = $this->commandFactory->createCommand($commandInfo, $this->commandFileInstance); - - $command = $this->commandFactory->createCommand($commandInfo, $this->commandFileInstance); - $this->assertEquals('default:option-two', $command->getName()); - $this->assertEquals('default:option-two [--foo [FOO]]', $command->getSynopsis()); - - $input = new StringInput('default:option-two'); - $this->assertRunCommandViaApplicationEquals($command, $input, 'Foo is 2'); - - $commandInfo = $this->commandFactory->createCommandInfo($this->commandFileInstance, 'defaultOptionNone'); - - $command = $this->commandFactory->createCommand($commandInfo, $this->commandFileInstance); - - $command = $this->commandFactory->createCommand($commandInfo, $this->commandFileInstance); - $this->assertEquals('default:option-none', $command->getName()); - $this->assertEquals('default:option-none [--foo FOO]', $command->getSynopsis()); - - // Skip failing test until Symfony is fixed. - $this->markTestSkipped('Symfony Console 3.2.5 and 3.2.6 do not handle default options with required values correctly.'); - - $input = new StringInput('default:option-none --foo'); - $this->assertRunCommandViaApplicationContains($command, $input, ['The "--foo" option requires a value.'], 1); - } - - function testGlobalOptionsOnly() - { - $this->commandFileInstance = new \Consolidation\TestUtils\ExampleCommandFile; - $this->commandFactory = new AnnotatedCommandFactory(); - $commandInfo = $this->commandFactory->createCommandInfo($this->commandFileInstance, 'globalOptionsOnly'); - - $command = $this->commandFactory->createCommand($commandInfo, $this->commandFileInstance); - - $input = new StringInput('global-options-only test'); - $this->assertRunCommandViaApplicationEquals($command, $input, "Arg is test, options[help] is false"); - } - - function testOptionWithOptionalValue() - { - $this->commandFileInstance = new \Consolidation\TestUtils\ExampleCommandFile; - $this->commandFactory = new AnnotatedCommandFactory(); - - $commandInfo = $this->commandFactory->createCommandInfo($this->commandFileInstance, 'defaultOptionalValue'); - - $command = $this->commandFactory->createCommand($commandInfo, $this->commandFileInstance); - - // Test to see if we can differentiate between a missing option, and - // an option that has no value at all. - $input = new StringInput('default:optional-value --foo=bar'); - $this->assertRunCommandViaApplicationEquals($command, $input, "Foo is 'bar'"); - - $input = new StringInput('default:optional-value --foo'); - $this->assertRunCommandViaApplicationEquals($command, $input, 'Foo is true'); - - $input = new StringInput('default:optional-value'); - $this->assertRunCommandViaApplicationEquals($command, $input, 'Foo is NULL'); - } - - function testOptionThatDefaultsToTrue() - { - $this->commandFileInstance = new \Consolidation\TestUtils\ExampleCommandFile; - $this->commandFactory = new AnnotatedCommandFactory(); - - $commandInfo = $this->commandFactory->createCommandInfo($this->commandFileInstance, 'defaultOptionDefaultsToTrue'); - - $command = $this->commandFactory->createCommand($commandInfo, $this->commandFileInstance); - - // Test to see if we can differentiate between a missing option, and - // an option that has no value at all. - $input = new StringInput('default:option-defaults-to-true --foo=bar'); - $this->assertRunCommandViaApplicationEquals($command, $input, "Foo is 'bar'"); - - $input = new StringInput('default:option-defaults-to-true --foo'); - $this->assertRunCommandViaApplicationEquals($command, $input, 'Foo is true'); - - $input = new StringInput('default:option-defaults-to-true'); - $this->assertRunCommandViaApplicationEquals($command, $input, 'Foo is true'); - - $input = new StringInput('help default:option-defaults-to-true'); - $this->assertRunCommandViaApplicationContains( - $command, - $input, - [ - '--no-foo', - 'Negate --foo option', - ] - ); - $input = new ArgvInput(['cli.php', 'default:option-defaults-to-true', '--no-foo']); - $this->assertRunCommandViaApplicationEquals($command, $input, 'Foo is false'); - - // Do all of those things again, but with ArgvInput - $input = new ArgvInput(['cli.php', 'default:option-defaults-to-true', '--foo=bar']); - $this->assertRunCommandViaApplicationEquals($command, $input, "Foo is 'bar'"); - - $input = new ArgvInput(['cli.php', 'default:option-defaults-to-true', '--foo']); - $this->assertRunCommandViaApplicationEquals($command, $input, 'Foo is true'); - - $input = new ArgvInput(['cli.php', 'default:option-defaults-to-true']); - $this->assertRunCommandViaApplicationEquals($command, $input, 'Foo is true'); - - $input = new ArgvInput(['cli.php', 'default:option-defaults-to-true', '--no-foo']); - $this->assertRunCommandViaApplicationEquals($command, $input, 'Foo is false'); - } - /** - * Test CommandInfo command caching. - * - * Sequence: - * - Create all of the command info objects from one class, caching them. - * - Change the method name of one of the items in the cache to a non-existent method - * - Restore all of the cached commandinfo objects - * - Ensure that the non-existent method cached commandinfo was not created - * - Ensure that the now-missing cached commandinfo was still created - * - * This tests both save/restore, plus adding a new command method to - * a class, and removing a command method from a class. - */ - function testAnnotatedCommandCache() - { - $testCacheStore = new \Consolidation\TestUtils\InMemoryCacheStore(); - - $this->commandFileInstance = new \Consolidation\TestUtils\ExampleCommandFile; - $this->commandFactory = new AnnotatedCommandFactory(); - $this->commandFactory->setDataStore($testCacheStore); - - // Make commandInfo objects for every command in the test commandfile. - // These will also be stored in our cache. - $commandInfoList = $this->commandFactory->getCommandInfoListFromClass($this->commandFileInstance); - - $cachedClassName = get_class($this->commandFileInstance); - - $this->assertTrue($testCacheStore->has($cachedClassName)); - - $cachedData = $testCacheStore->get($cachedClassName); - $this->assertFalse(empty($cachedData)); - $this->assertTrue(array_key_exists('testArithmatic', $cachedData)); - - $alterCommandInfoCache = $cachedData['testArithmatic']; - unset($cachedData['testArithmatic']); - $alterCommandInfoCache['method_name'] = 'nonExistentMethod'; - $cachedData[$alterCommandInfoCache['method_name']] = $alterCommandInfoCache; - - $testCacheStore->set($cachedClassName, $cachedData); - - $restoredCommandInfoList = $this->commandFactory->getCommandInfoListFromClass($this->commandFileInstance); - - $rebuiltCachedData = $testCacheStore->get($cachedClassName); - - $this->assertFalse(empty($rebuiltCachedData)); - $this->assertTrue(array_key_exists('testArithmatic', $rebuiltCachedData)); - $this->assertFalse(array_key_exists('nonExistentMethod', $rebuiltCachedData)); - } - - /** - * Test CommandInfo command annotation parsing. - */ - function testAnnotatedCommandCreation() - { - $this->commandFileInstance = new \Consolidation\TestUtils\ExampleCommandFile; - $this->commandFactory = new AnnotatedCommandFactory(); - $commandInfo = $this->commandFactory->createCommandInfo($this->commandFileInstance, 'testArithmatic'); - - $command = $this->commandFactory->createCommand($commandInfo, $this->commandFileInstance); - - $this->assertInstanceOf('\Symfony\Component\Console\Command\Command', $command); - $this->assertEquals('test:arithmatic', $command->getName()); - $this->assertEquals('This is the test:arithmatic command', $command->getDescription()); - $this->assertEquals("This command will add one and two. If the --negate flag\nis provided, then the result is negated.", $command->getHelp()); - $this->assertEquals('arithmatic', implode(',', $command->getAliases())); - $this->assertEquals('test:arithmatic [--negate] [--unused [UNUSED]] [--] []', $command->getSynopsis()); - $this->assertEquals('test:arithmatic 2 2 --negate', implode(',', $command->getUsages())); - - $input = new StringInput('arithmatic 2 3 --negate'); - $this->assertRunCommandViaApplicationEquals($command, $input, '-5'); - } - - /** - * Test CommandInfo command annotation altering. - */ - function testAnnotatedCommandInfoAlteration() - { - $this->commandFileInstance = new \Consolidation\TestUtils\ExampleCommandFile; - $this->commandFactory = new AnnotatedCommandFactory(); - $commandInfo = $this->commandFactory->createCommandInfo($this->commandFileInstance, 'myCat'); - - $command = $this->commandFactory->createCommand($commandInfo, $this->commandFileInstance); - - $annotationData = $command->getAnnotationData(); - $this->assertTrue($annotationData->has('arbitrary')); - $this->assertFalse($annotationData->has('dynamic')); - - $this->commandFactory->addCommandInfoAlterer(new ExampleCommandInfoAlterer()); - - $command = $this->commandFactory->createCommand($commandInfo, $this->commandFileInstance); - - $annotationData = $command->getAnnotationData(); - $this->assertTrue($annotationData->has('arbitrary')); - $this->assertTrue($annotationData->has('dynamic')); - } - - function testMyCatCommand() - { - $this->commandFileInstance = new \Consolidation\TestUtils\ExampleCommandFile; - $this->commandFactory = new AnnotatedCommandFactory(); - $commandInfo = $this->commandFactory->createCommandInfo($this->commandFileInstance, 'myCat'); - - $command = $this->commandFactory->createCommand($commandInfo, $this->commandFileInstance); - - $this->assertInstanceOf('\Symfony\Component\Console\Command\Command', $command); - $this->assertEquals('my:cat', $command->getName()); - $this->assertEquals('This is the my:cat command', $command->getDescription()); - $this->assertEquals("This command will concatenate two parameters. If the --flip flag\nis provided, then the result is the concatenation of two and one.", $command->getHelp()); - $this->assertEquals('c', implode(',', $command->getAliases())); - $this->assertEquals('my:cat [--flip] [--] []', $command->getSynopsis()); - $this->assertEquals('my:cat bet alpha --flip', implode(',', $command->getUsages())); - - $input = new StringInput('my:cat bet alpha --flip'); - $this->assertRunCommandViaApplicationEquals($command, $input, 'alphabet'); - } - - function testJoinCommandHelp() - { - $this->commandFileInstance = new \Consolidation\TestUtils\ExampleCommandFile; - $this->commandFactory = new AnnotatedCommandFactory(); - $commandInfo = $this->commandFactory->createCommandInfo($this->commandFileInstance, 'myJoin'); - - $command = $this->commandFactory->createCommand($commandInfo, $this->commandFileInstance); - - $this->assertInstanceOf('\Symfony\Component\Console\Command\Command', $command); - $this->assertEquals('my:join', $command->getName()); - $this->assertEquals('This is the my:join command', $command->getDescription()); - $this->assertEquals("This command will join its parameters together. It can also reverse and repeat its arguments.", $command->getHelp()); - $this->assertEquals('my:join [--flip] [--repeat [REPEAT]] [--] []...', $command->getSynopsis()); - - // TODO: Extra whitespace character if there are no options et. al. in the - // usage. This is uncommon, and the defect is invisible. Maybe find it someday. - $actualUsages = implode(',', $command->getUsages()); - $this->assertEquals('my:join a b,my:join ', $actualUsages); - - $input = new StringInput('my:join bet alpha --flip --repeat=2'); - $this->assertRunCommandViaApplicationEquals($command, $input, 'alphabetalphabet'); - } - - function testDefaultsCommand() - { - $this->commandFileInstance = new \Consolidation\TestUtils\ExampleCommandFile; - $this->commandFactory = new AnnotatedCommandFactory(); - $commandInfo = $this->commandFactory->createCommandInfo($this->commandFileInstance, 'defaults'); - - $command = $this->commandFactory->createCommand($commandInfo, $this->commandFileInstance); - - $this->assertInstanceOf('\Symfony\Component\Console\Command\Command', $command); - $this->assertEquals('defaults', $command->getName()); - $this->assertEquals('Test default values in arguments', $command->getDescription()); - - $input = new StringInput('defaults'); - $this->assertRunCommandViaApplicationEquals($command, $input, 'nothing provided'); - - $input = new StringInput('defaults ichi'); - $this->assertRunCommandViaApplicationEquals($command, $input, 'only ichi'); - - $input = new StringInput('defaults I II'); - $this->assertRunCommandViaApplicationEquals($command, $input, 'I and II'); - } - - function testCommandWithNoOptions() - { - $this->commandFileInstance = new \Consolidation\TestUtils\ExampleCommandFile; - $this->commandFactory = new AnnotatedCommandFactory(); - $commandInfo = $this->commandFactory->createCommandInfo($this->commandFileInstance, 'commandWithNoOptions'); - - $command = $this->commandFactory->createCommand($commandInfo, $this->commandFileInstance); - - $this->assertInstanceOf('\Symfony\Component\Console\Command\Command', $command); - $this->assertEquals('command:with-no-options', $command->getName()); - $this->assertEquals('This is a command with no options', $command->getDescription()); - $this->assertEquals("This command will concatenate two parameters.", $command->getHelp()); - $this->assertEquals('nope', implode(',', $command->getAliases())); - $this->assertEquals('command:with-no-options []', $command->getSynopsis()); - $this->assertEquals('command:with-no-options alpha bet', implode(',', $command->getUsages())); - - $input = new StringInput('command:with-no-options something'); - $this->assertRunCommandViaApplicationEquals($command, $input, 'somethingdefault'); - - $input = new StringInput('help command:with-no-options something'); - $this->assertRunCommandViaApplicationContains( - $command, - $input, - [ - 'The first parameter.', - 'The other parameter.', - ] - ); - } - - function testCommandWithIOParameters() - { - $this->commandFileInstance = new \Consolidation\TestUtils\ExampleCommandFile; - $this->commandFactory = new AnnotatedCommandFactory(); - $commandInfo = $this->commandFactory->createCommandInfo($this->commandFileInstance, 'commandWithIOParameters'); - - $command = $this->commandFactory->createCommand($commandInfo, $this->commandFileInstance); - - $this->assertInstanceOf('\Symfony\Component\Console\Command\Command', $command); - $this->assertEquals('command:with-io-parameters', $command->getName()); - $this->assertEquals("This command work with app's input and output", $command->getDescription()); - $this->assertEquals('', $command->getHelp()); - $this->assertEquals('command:with-io-parameters', $command->getSynopsis()); - - $input = new StringInput('command:with-io-parameters'); - $this->assertRunCommandViaApplicationEquals($command, $input, 'command:with-io-parameters'); - } - - function testCommandWithNoArguments() - { - $this->commandFileInstance = new \Consolidation\TestUtils\ExampleCommandFile; - $this->commandFactory = new AnnotatedCommandFactory(); - $commandInfo = $this->commandFactory->createCommandInfo($this->commandFileInstance, 'commandWithNoArguments'); - - $command = $this->commandFactory->createCommand($commandInfo, $this->commandFileInstance); - - $this->assertInstanceOf('\Symfony\Component\Console\Command\Command', $command); - $this->assertEquals('command:with-no-arguments', $command->getName()); - $this->assertEquals('This command has no arguments--only options', $command->getDescription()); - $this->assertEquals("Return a result only if not silent.", $command->getHelp()); - $this->assertEquals('command:with-no-arguments [-s|--silent]', $command->getSynopsis()); - - $input = new StringInput('command:with-no-arguments'); - $this->assertRunCommandViaApplicationEquals($command, $input, 'Hello, world'); - $input = new StringInput('command:with-no-arguments -s'); - $this->assertRunCommandViaApplicationEquals($command, $input, ''); - $input = new StringInput('command:with-no-arguments --silent'); - $this->assertRunCommandViaApplicationEquals($command, $input, ''); - } - - function testCommandWithShortcutOnAnnotation() - { - $this->commandFileInstance = new \Consolidation\TestUtils\ExampleCommandFile; - $this->commandFactory = new AnnotatedCommandFactory(); - $commandInfo = $this->commandFactory->createCommandInfo($this->commandFileInstance, 'shortcutOnAnnotation'); - - $command = $this->commandFactory->createCommand($commandInfo, $this->commandFileInstance); - - $this->assertInstanceOf('\Symfony\Component\Console\Command\Command', $command); - $this->assertEquals('shortcut:on-annotation', $command->getName()); - $this->assertEquals('Shortcut on annotation', $command->getDescription()); - $this->assertEquals("This command defines the option shortcut on the annotation instead of in the options array.", $command->getHelp()); - $this->assertEquals('shortcut:on-annotation [-s|--silent]', $command->getSynopsis()); - - $input = new StringInput('shortcut:on-annotation'); - $this->assertRunCommandViaApplicationEquals($command, $input, 'Hello, world'); - $input = new StringInput('shortcut:on-annotation -s'); - $this->assertRunCommandViaApplicationEquals($command, $input, ''); - $input = new StringInput('shortcut:on-annotation --silent'); - $this->assertRunCommandViaApplicationEquals($command, $input, ''); - } - - function testState() - { - $this->commandFileInstance = new \Consolidation\TestUtils\ExampleCommandFile('secret secret'); - $this->commandFactory = new AnnotatedCommandFactory(); - $commandInfo = $this->commandFactory->createCommandInfo($this->commandFileInstance, 'testState'); - - $command = $this->commandFactory->createCommand($commandInfo, $this->commandFileInstance); - - $this->assertInstanceOf('\Symfony\Component\Console\Command\Command', $command); - $this->assertEquals('test:state', $command->getName()); - - $input = new StringInput('test:state'); - $this->assertRunCommandViaApplicationEquals($command, $input, 'secret secret'); - } - - function testPassthroughArray() - { - $this->commandFileInstance = new \Consolidation\TestUtils\ExampleCommandFile; - $this->commandFactory = new AnnotatedCommandFactory(); - $commandInfo = $this->commandFactory->createCommandInfo($this->commandFileInstance, 'testPassthrough'); - - $command = $this->commandFactory->createCommand($commandInfo, $this->commandFileInstance); - - $this->assertInstanceOf('\Symfony\Component\Console\Command\Command', $command); - $this->assertEquals('test:passthrough', $command->getName()); - - $input = new StringInput('test:passthrough a b c -- x y z'); - $this->assertRunCommandViaApplicationEquals($command, $input, 'a,b,c,x,y,z'); - } - - function testPassThroughNonArray() - { - $this->commandFileInstance = new \Consolidation\TestUtils\ExampleCommandFile; - $this->commandFactory = new AnnotatedCommandFactory(); - $commandInfo = $this->commandFactory->createCommandInfo($this->commandFileInstance, 'myJoin'); - - $command = $this->commandFactory->createCommand($commandInfo, $this->commandFileInstance); - - $input = new StringInput('my:join bet --flip -- x y z'); - $this->assertRunCommandViaApplicationEquals($command, $input, 'zyxbet'); - // Can't look at 'hasOption' until after the command initializes the - // option, because Symfony. - $this->assertTrue($input->hasOption('flip')); - } - - function testPassThroughWithInputManipulation() - { - $this->commandFileInstance = new \Consolidation\TestUtils\ExampleCommandFile; - $this->commandFactory = new AnnotatedCommandFactory(); - $commandInfo = $this->commandFactory->createCommandInfo($this->commandFileInstance, 'myJoin'); - - $command = $this->commandFactory->createCommand($commandInfo, $this->commandFileInstance); - - $input = new StringInput('my:join bet --repeat=2 -- x y z'); - $this->assertRunCommandViaApplicationEquals($command, $input, 'betxyzbetxyz'); - // Symfony does not allow us to manipulate the options via setOption until - // the definition from the command object has been set up. - $input->setOption('repeat', 3); - $this->assertEquals(3, $input->getOption('repeat')); - $input->setArgument(0, 'q'); - // Manipulating $input does not work -- the changes are not effective. - // The end result here should be 'qx y yqx y yqx y y' - $this->assertRunCommandViaApplicationEquals($command, $input, 'betxyzbetxyz'); - } - - function testRequiredArrayOption() - { - $this->commandFileInstance = new \Consolidation\TestUtils\ExampleCommandFile; - $this->commandFactory = new AnnotatedCommandFactory(); - $commandInfo = $this->commandFactory->createCommandInfo($this->commandFileInstance, 'testRequiredArrayOption'); - - $command = $this->commandFactory->createCommand($commandInfo, $this->commandFileInstance); - $this->assertEquals('test:required-array-option [-a|--arr ARR]', $command->getSynopsis()); - - $input = new StringInput('test:required-array-option --arr=1 --arr=2 --arr=3'); - $this->assertRunCommandViaApplicationEquals($command, $input, '1 2 3'); - - $input = new StringInput('test:required-array-option -a 1 -a 2 -a 3'); - $this->assertRunCommandViaApplicationEquals($command, $input, '1 2 3'); - } - - function testArrayOption() - { - $this->commandFileInstance = new \Consolidation\TestUtils\ExampleCommandFile; - $this->commandFactory = new AnnotatedCommandFactory(); - $commandInfo = $this->commandFactory->createCommandInfo($this->commandFileInstance, 'testArrayOption'); - - $command = $this->commandFactory->createCommand($commandInfo, $this->commandFileInstance); - $this->assertEquals('test:array-option [-a|--arr [ARR]]', $command->getSynopsis()); - - $input = new StringInput('test:array-option'); - $this->assertRunCommandViaApplicationEquals($command, $input, '1 2 3'); - - $input = new StringInput('test:array-option --arr=a --arr=b --arr=c'); - $this->assertRunCommandViaApplicationEquals($command, $input, 'a b c'); - - $input = new StringInput('test:array-option -a a'); - $this->assertRunCommandViaApplicationEquals($command, $input, 'a'); - } - - function testHookedCommand() - { - $this->commandFileInstance = new \Consolidation\TestUtils\ExampleCommandFile(); - $this->commandFactory = new AnnotatedCommandFactory(); - - $hookInfo = $this->commandFactory->createCommandInfo($this->commandFileInstance, 'hookTestHook'); - - $this->assertTrue($hookInfo->hasAnnotation('hook')); - $this->assertEquals('alter test:hook', $hookInfo->getAnnotation('hook')); - - $this->commandFactory->registerCommandHook($hookInfo, $this->commandFileInstance); - - $hookCallback = $this->commandFactory->hookManager()->get('test:hook', [HookManager::ALTER_RESULT]); - $this->assertTrue($hookCallback != null); - $this->assertEquals(1, count($hookCallback)); - $this->assertEquals(2, count($hookCallback[0])); - $this->assertTrue(is_callable($hookCallback[0])); - $this->assertEquals('hookTestHook', $hookCallback[0][1]); - - $commandInfo = $this->commandFactory->createCommandInfo($this->commandFileInstance, 'testHook'); - $command = $this->commandFactory->createCommand($commandInfo, $this->commandFileInstance); - - $this->assertInstanceOf('\Symfony\Component\Console\Command\Command', $command); - $this->assertEquals('test:hook', $command->getName()); - - $input = new StringInput('test:hook bar'); - $this->assertRunCommandViaApplicationEquals($command, $input, '<[bar]>'); - - $input = new StringInput('list --raw'); - $this->assertRunCommandViaApplicationContains($command, $input, ['This command wraps its parameter in []; its alter hook then wraps the result in .']); - } - - function testReplaceCommandHook(){ - $this->commandFileInstance = new \Consolidation\TestUtils\ExampleCommandFile(); - $this->commandFactory = new AnnotatedCommandFactory(); - - $hookInfo = $this->commandFactory->createCommandInfo($this->commandFileInstance, 'hookTestReplaceCommandHook'); - - $this->assertTrue($hookInfo->hasAnnotation('hook')); - $this->assertEquals('replace-command test:replace-command', $hookInfo->getAnnotation('hook')); - - $this->commandFactory->registerCommandHook($hookInfo, $this->commandFileInstance); - - $hookCallback = $this->commandFactory->hookManager()->get('test:replace-command', [HookManager::REPLACE_COMMAND_HOOK]); - $this->assertTrue($hookCallback != null); - $this->assertEquals(1, count($hookCallback)); - $this->assertEquals(2, count($hookCallback[0])); - $this->assertTrue(is_callable($hookCallback[0])); - $this->assertEquals('hookTestReplaceCommandHook', $hookCallback[0][1]); - - $input = new StringInput('test:replace-command foo'); - $commandInfo = $this->commandFactory->createCommandInfo($this->commandFileInstance, 'testReplaceCommand'); - $command = $this->commandFactory->createCommand($commandInfo, $this->commandFileInstance); - $this->assertRunCommandViaApplicationEquals($command, $input, "bar", 0); - } - - function testPostCommandCalledAfterCommand() - { - $this->commandFileInstance = new \Consolidation\TestUtils\ExampleCommandFile(); - $this->commandFactory = new AnnotatedCommandFactory(); - - $hookInfo = $this->commandFactory->createCommandInfo($this->commandFileInstance, 'hookTestPostCommandHook'); - - $this->assertTrue($hookInfo->hasAnnotation('hook')); - $this->assertEquals('post-command test:post-command', $hookInfo->getAnnotation('hook')); - - $this->commandFactory->registerCommandHook($hookInfo, $this->commandFileInstance); - - $hookCallback = $this->commandFactory->hookManager()->get('test:post-command', [HookManager::POST_COMMAND_HOOK]); - $this->assertTrue($hookCallback != null); - $this->assertEquals(1, count($hookCallback)); - $this->assertEquals(2, count($hookCallback[0])); - $this->assertTrue(is_callable($hookCallback[0])); - $this->assertEquals('hookTestPostCommandHook', $hookCallback[0][1]); - - $hookInfo = $this->commandFactory->createCommandInfo($this->commandFileInstance, 'hookTestPreCommandHook'); - - $this->assertTrue($hookInfo->hasAnnotation('hook')); - $this->assertEquals('pre-command test:post-command', $hookInfo->getAnnotation('hook')); - - $this->commandFactory->registerCommandHook($hookInfo, $this->commandFileInstance); - - $hookCallback = $this->commandFactory->hookManager()->get('test:post-command', [HookManager::PRE_COMMAND_HOOK]); - $this->assertTrue($hookCallback != null); - $this->assertEquals(1, count($hookCallback)); - $this->assertEquals(2, count($hookCallback[0])); - $this->assertTrue(is_callable($hookCallback[0])); - $this->assertEquals('hookTestPreCommandHook', $hookCallback[0][1]); - - $commandInfo = $this->commandFactory->createCommandInfo($this->commandFileInstance, 'testPostCommand'); - $command = $this->commandFactory->createCommand($commandInfo, $this->commandFileInstance); - - $this->assertInstanceOf('\Symfony\Component\Console\Command\Command', $command); - $this->assertEquals('test:post-command', $command->getName()); - - $input = new StringInput('test:post-command bar'); - $this->assertRunCommandViaApplicationEquals($command, $input, "foo\nbar\nbaz", 0, $this->commandFileInstance); - } - - function testHookAllCommands() - { - $this->commandFileInstance = new \Consolidation\TestUtils\ExampleHookAllCommandFile(); - $this->commandFactory = new AnnotatedCommandFactory(); - - $hookInfo = $this->commandFactory->createCommandInfo($this->commandFileInstance, 'alterAllCommands'); - - $this->assertTrue($hookInfo->hasAnnotation('hook')); - $this->assertEquals('alter', $hookInfo->getAnnotation('hook')); - - $this->commandFactory->registerCommandHook($hookInfo, $this->commandFileInstance); - - $hookCallback = $this->commandFactory->hookManager()->get('Consolidation\TestUtils\ExampleHookAllCommandFile', [HookManager::ALTER_RESULT]); - $this->assertTrue($hookCallback != null); - $this->assertEquals(1, count($hookCallback)); - $this->assertEquals(2, count($hookCallback[0])); - $this->assertTrue(is_callable($hookCallback[0])); - $this->assertEquals('alterAllCommands', $hookCallback[0][1]); - - $commandInfo = $this->commandFactory->createCommandInfo($this->commandFileInstance, 'doCat'); - $command = $this->commandFactory->createCommand($commandInfo, $this->commandFileInstance); - - $this->assertInstanceOf('\Symfony\Component\Console\Command\Command', $command); - $this->assertEquals('do:cat', $command->getName()); - - $input = new StringInput('do:cat bar'); - $this->assertRunCommandViaApplicationEquals($command, $input, '*** bar ***'); - } - - function testDoubleDashWithVersion() - { - $this->commandFileInstance = new \Consolidation\TestUtils\ExampleHookAllCommandFile(); - $this->commandFactory = new AnnotatedCommandFactory(); - $commandInfo = $this->commandFactory->createCommandInfo($this->commandFileInstance, 'doCat'); - $command = $this->commandFactory->createCommand($commandInfo, $this->commandFileInstance); - - $input = new ArgvInput(['placeholder', 'do:cat', 'one', '--', '--version']); - list($statusCode, $commandOutput) = $this->runCommandViaApplication($command, $input); - - if ($commandOutput == 'TestApplication version 0.0.0') { - $this->markTestSkipped('Symfony/Console 2.x does not respect -- with --version'); - } - $this->assertEquals('one--version', $commandOutput); - } - - function testAnnotatedHookedCommand() - { - $this->commandFileInstance = new \Consolidation\TestUtils\ExampleCommandFile(); - $this->commandFactory = new AnnotatedCommandFactory(); - - $hookInfo = $this->commandFactory->createCommandInfo($this->commandFileInstance, 'hookTestAnnotatedHook'); - - $this->assertTrue($hookInfo->hasAnnotation('hook')); - $this->assertEquals('alter @hookme', $hookInfo->getAnnotation('hook')); - - $this->commandFactory->registerCommandHook($hookInfo, $this->commandFileInstance); - $hookCallback = $this->commandFactory->hookManager()->get('@hookme', [HookManager::ALTER_RESULT]); - $this->assertTrue($hookCallback != null); - $this->assertEquals(1, count($hookCallback)); - $this->assertEquals(2, count($hookCallback[0])); - $this->assertTrue(is_callable($hookCallback[0])); - $this->assertEquals('hookTestAnnotatedHook', $hookCallback[0][1]); - - $commandInfo = $this->commandFactory->createCommandInfo($this->commandFileInstance, 'testAnnotationHook'); - $annotationData = $commandInfo->getRawAnnotations(); - $this->assertEquals('hookme,before,after', implode(',', $annotationData->keys())); - $this->assertEquals('@hookme,@before,@after', implode(',', array_map(function ($item) { return "@$item"; }, $annotationData->keys()))); - - $command = $this->commandFactory->createCommand($commandInfo, $this->commandFileInstance); - - $this->assertInstanceOf('\Symfony\Component\Console\Command\Command', $command); - $this->assertEquals('test:annotation-hook', $command->getName()); - - $input = new StringInput('test:annotation-hook baz'); - $this->assertRunCommandViaApplicationEquals($command, $input, '>(baz)<'); - } - - function testHookHasCommandAnnotation() - { - $this->commandFileInstance = new \Consolidation\TestUtils\ExampleCommandFile(); - $this->commandFactory = new AnnotatedCommandFactory(); - - $hookInfo = $this->commandFactory->createCommandInfo($this->commandFileInstance, 'hookAddCommandName'); - - $this->assertTrue($hookInfo->hasAnnotation('hook')); - $this->assertEquals('alter @addmycommandname', $hookInfo->getAnnotation('hook')); - - $this->commandFactory->registerCommandHook($hookInfo, $this->commandFileInstance); - $hookCallback = $this->commandFactory->hookManager()->get('@addmycommandname', [HookManager::ALTER_RESULT]); - $this->assertTrue($hookCallback != null); - $this->assertEquals(1, count($hookCallback)); - $this->assertEquals(2, count($hookCallback[0])); - $this->assertTrue(is_callable($hookCallback[0])); - $this->assertEquals('hookAddCommandName', $hookCallback[0][1]); - - $commandInfo = $this->commandFactory->createCommandInfo($this->commandFileInstance, 'alterMe'); - $annotationData = $commandInfo->getRawAnnotations(); - $this->assertEquals('command,addmycommandname', implode(',', $annotationData->keys())); - - $command = $this->commandFactory->createCommand($commandInfo, $this->commandFileInstance); - - $this->assertInstanceOf('\Symfony\Component\Console\Command\Command', $command); - $this->assertEquals('alter-me', $command->getName()); - - $input = new StringInput('alter-me'); - $this->assertRunCommandViaApplicationEquals($command, $input, 'splendiferous from alter-me'); - - $commandInfo = $this->commandFactory->createCommandInfo($this->commandFileInstance, 'alterMeToo'); - $annotationData = $commandInfo->getRawAnnotations(); - $this->assertEquals('addmycommandname', implode(',', $annotationData->keys())); - $annotationData = $commandInfo->getAnnotations(); - $this->assertEquals('addmycommandname,command,_path,_classname', implode(',', $annotationData->keys())); - - $command = $this->commandFactory->createCommand($commandInfo, $this->commandFileInstance); - - $this->assertInstanceOf('\Symfony\Component\Console\Command\Command', $command); - $this->assertEquals('alter:me-too', $command->getName()); - - $input = new StringInput('alter:me-too'); - $this->assertRunCommandViaApplicationEquals($command, $input, 'fantabulous from alter:me-too'); - } - - function testHookedCommandWithHookAddedLater() - { - $this->commandFileInstance = new \Consolidation\TestUtils\ExampleCommandFile(); - $this->commandFactory = new AnnotatedCommandFactory(); - $commandInfo = $this->commandFactory->createCommandInfo($this->commandFileInstance, 'testHook'); - - $command = $this->commandFactory->createCommand($commandInfo, $this->commandFileInstance); - - $this->assertInstanceOf('\Symfony\Component\Console\Command\Command', $command); - $this->assertEquals('test:hook', $command->getName()); - - // Run the command once without the hook - $input = new StringInput('test:hook foo'); - $this->assertRunCommandViaApplicationEquals($command, $input, '[foo]'); - - // Register the hook and run the command again - $hookInfo = $this->commandFactory->createCommandInfo($this->commandFileInstance, 'hookTestHook'); - - $this->assertTrue($hookInfo->hasAnnotation('hook')); - $this->assertEquals('alter test:hook', $hookInfo->getAnnotation('hook')); - - $this->commandFactory->registerCommandHook($hookInfo, $this->commandFileInstance); - $hookCallback = $this->commandFactory->hookManager()->get('test:hook', [HookManager::ALTER_RESULT]);; - $this->assertTrue($hookCallback != null); - $this->assertEquals(1, count($hookCallback)); - $this->assertEquals(2, count($hookCallback[0])); - $this->assertTrue(is_callable($hookCallback[0])); - $this->assertEquals('hookTestHook', $hookCallback[0][1]); - - $input = new StringInput('test:hook bar'); - $this->assertRunCommandViaApplicationEquals($command, $input, '<[bar]>'); - } - - function testInitializeHook() - { - $this->commandFileInstance = new \Consolidation\TestUtils\ExampleCommandFile(); - $this->commandFactory = new AnnotatedCommandFactory(); - - $hookInfo = $this->commandFactory->createCommandInfo($this->commandFileInstance, 'initializeTestHello'); - - $this->assertTrue($hookInfo->hasAnnotation('hook')); - $this->assertEquals($hookInfo->getAnnotation('hook'), 'init test:hello'); - - $this->commandFactory->registerCommandHook($hookInfo, $this->commandFileInstance); - - $hookCallback = $this->commandFactory->hookManager()->get('test:hello', [HookManager::INITIALIZE]); - $this->assertTrue($hookCallback != null); - $this->assertEquals(1, count($hookCallback)); - $this->assertEquals(2, count($hookCallback[0])); - $this->assertTrue(is_callable($hookCallback[0])); - $this->assertEquals('initializeTestHello', $hookCallback[0][1]); - - $commandInfo = $this->commandFactory->createCommandInfo($this->commandFileInstance, 'testHello'); - $command = $this->commandFactory->createCommand($commandInfo, $this->commandFileInstance); - - $this->assertInstanceOf('\Symfony\Component\Console\Command\Command', $command); - $this->assertEquals('test:hello', $command->getName()); - $commandGetNames = $this->callProtected($command, 'getNames'); - $this->assertEquals('test:hello,Consolidation\TestUtils\ExampleCommandFile', implode(',', $commandGetNames)); - - $hookCallback = $command->commandProcessor()->hookManager()->get('test:hello', 'init'); - $this->assertTrue($hookCallback != null); - $this->assertEquals('initializeTestHello', $hookCallback[0][1]); - - $input = new StringInput('test:hello'); - $this->assertRunCommandViaApplicationEquals($command, $input, "Hello, Huey."); - } - - function testCommandEventHook() - { - $this->commandFileInstance = new \Consolidation\TestUtils\ExampleCommandFile(); - $this->commandFactory = new AnnotatedCommandFactory(); - - $hookInfo = $this->commandFactory->createCommandInfo($this->commandFileInstance, 'commandEventTestHello'); - - $this->assertTrue($hookInfo->hasAnnotation('hook')); - $this->assertEquals($hookInfo->getAnnotation('hook'), 'command-event test:hello'); - - $this->commandFactory->registerCommandHook($hookInfo, $this->commandFileInstance); - - $hookCallback = $this->commandFactory->hookManager()->get('test:hello', [HookManager::COMMAND_EVENT]); - $this->assertTrue($hookCallback != null); - $this->assertEquals(1, count($hookCallback)); - $this->assertEquals(2, count($hookCallback[0])); - $this->assertTrue(is_callable($hookCallback[0])); - $this->assertEquals('commandEventTestHello', $hookCallback[0][1]); - - $commandInfo = $this->commandFactory->createCommandInfo($this->commandFileInstance, 'testHello'); - $command = $this->commandFactory->createCommand($commandInfo, $this->commandFileInstance); - - $this->assertInstanceOf('\Symfony\Component\Console\Command\Command', $command); - $this->assertEquals('test:hello', $command->getName()); - $commandGetNames = $this->callProtected($command, 'getNames'); - $this->assertEquals('test:hello,Consolidation\TestUtils\ExampleCommandFile', implode(',', $commandGetNames)); - - $hookCallback = $command->commandProcessor()->hookManager()->get('test:hello', 'command-event'); - $this->assertTrue($hookCallback != null); - $this->assertEquals('commandEventTestHello', $hookCallback[0][1]); - - $input = new StringInput('test:hello Pluto'); - $this->assertRunCommandViaApplicationEquals($command, $input, "Here comes Pluto!\nHello, Pluto."); - } - - - function testInteractAndValidate() - { - $this->commandFileInstance = new \Consolidation\TestUtils\ExampleCommandFile(); - $this->commandFactory = new AnnotatedCommandFactory(); - - $hookInfo = $this->commandFactory->createCommandInfo($this->commandFileInstance, 'interactTestHello'); - - $this->assertTrue($hookInfo->hasAnnotation('hook')); - $this->assertEquals($hookInfo->getAnnotation('hook'), 'interact test:hello'); - - $this->commandFactory->registerCommandHook($hookInfo, $this->commandFileInstance); - - $hookInfo = $this->commandFactory->createCommandInfo($this->commandFileInstance, 'validateTestHello'); - - $this->assertTrue($hookInfo->hasAnnotation('hook')); - $this->assertEquals($hookInfo->getAnnotation('hook'), 'validate test:hello'); - - $this->commandFactory->registerCommandHook($hookInfo, $this->commandFileInstance); - - $hookCallback = $this->commandFactory->hookManager()->get('test:hello', [HookManager::ARGUMENT_VALIDATOR]); - $this->assertTrue($hookCallback != null); - $this->assertEquals(1, count($hookCallback)); - $this->assertEquals(2, count($hookCallback[0])); - $this->assertTrue(is_callable($hookCallback[0])); - $this->assertEquals('validateTestHello', $hookCallback[0][1]); - - $hookCallback = $this->commandFactory->hookManager()->get('test:hello', [HookManager::INTERACT]); - $this->assertTrue($hookCallback != null); - $this->assertEquals(1, count($hookCallback)); - $this->assertEquals(2, count($hookCallback[0])); - $this->assertTrue(is_callable($hookCallback[0])); - $this->assertEquals('interactTestHello', $hookCallback[0][1]); - - $commandInfo = $this->commandFactory->createCommandInfo($this->commandFileInstance, 'testHello'); - $command = $this->commandFactory->createCommand($commandInfo, $this->commandFileInstance); - - $this->assertInstanceOf('\Symfony\Component\Console\Command\Command', $command); - $this->assertEquals('test:hello', $command->getName()); - $commandGetNames = $this->callProtected($command, 'getNames'); - $this->assertEquals('test:hello,Consolidation\TestUtils\ExampleCommandFile', implode(',', $commandGetNames)); - - $testInteractInput = new StringInput('test:hello'); - $definition = new \Symfony\Component\Console\Input\InputDefinition( - [ - new \Symfony\Component\Console\Input\InputArgument('application', \Symfony\Component\Console\Input\InputArgument::REQUIRED), - new \Symfony\Component\Console\Input\InputArgument('who', \Symfony\Component\Console\Input\InputArgument::REQUIRED), - ] - ); - $testInteractInput->bind($definition); - $testInteractOutput = new BufferedOutput(); - $command->commandProcessor()->interact( - $testInteractInput, - $testInteractOutput, - $commandGetNames, - $command->getAnnotationData() - ); - $this->assertEquals('Goofey', $testInteractInput->getArgument('who')); - - $hookCallback = $command->commandProcessor()->hookManager()->get('test:hello', 'interact'); - $this->assertTrue($hookCallback != null); - $this->assertEquals('interactTestHello', $hookCallback[0][1]); - - $input = new StringInput('test:hello "Mickey Mouse"'); - $this->assertRunCommandViaApplicationEquals($command, $input, 'Hello, Mickey Mouse.'); - - $input = new StringInput('test:hello'); - $this->assertRunCommandViaApplicationEquals($command, $input, 'Hello, Goofey.'); - - $input = new StringInput('test:hello "Donald Duck"'); - $this->assertRunCommandViaApplicationEquals($command, $input, "I won't say hello to Donald Duck.", 1); - - $input = new StringInput('test:hello "Drumph"'); - $this->assertRunCommandViaApplicationEquals($command, $input, "Irrational value error.", 1); - - // Try the last test again with a display error function installed. - $this->commandFactory->commandProcessor()->setDisplayErrorFunction( - function ($output, $message) { - $output->writeln("*** $message ****"); - } - ); - - $input = new StringInput('test:hello "Drumph"'); - $this->assertRunCommandViaApplicationEquals($command, $input, "*** Irrational value error. ****", 1); - } - - function callProtected($object, $method, $args = []) - { - $r = new \ReflectionMethod($object, $method); - $r->setAccessible(true); - return $r->invokeArgs($object, $args); - } - - function assertRunCommandViaApplicationContains($command, $input, $containsList, $expectedStatusCode = 0) - { - list($statusCode, $commandOutput) = $this->runCommandViaApplication($command, $input); - - foreach ($containsList as $contains) { - $this->assertContains($contains, $commandOutput); - } - $this->assertEquals($expectedStatusCode, $statusCode); - } - - function assertRunCommandViaApplicationEquals($command, $input, $expectedOutput, $expectedStatusCode = 0) - { - list($statusCode, $commandOutput) = $this->runCommandViaApplication($command, $input); - - $this->assertEquals($expectedOutput, $commandOutput); - $this->assertEquals($expectedStatusCode, $statusCode); - } - - function runCommandViaApplication($command, $input) - { - $output = new BufferedOutput(); - if ($this->commandFileInstance && method_exists($this->commandFileInstance, 'setOutput')) { - $this->commandFileInstance->setOutput($output); - } - - $application = new Application('TestApplication', '0.0.0'); - $alterOptionsEventManager = new AlterOptionsCommandEvent($application); - - $eventDispatcher = new \Symfony\Component\EventDispatcher\EventDispatcher(); - $eventDispatcher->addSubscriber($this->commandFactory->commandProcessor()->hookManager()); - $this->commandFactory->commandProcessor()->hookManager()->addCommandEvent($alterOptionsEventManager); - $application->setDispatcher($eventDispatcher); - - $application->setAutoExit(false); - $application->add($command); - - $statusCode = $application->run($input, $output); - $commandOutput = trim(str_replace("\r", '', $output->fetch())); - - return [$statusCode, $commandOutput]; - } -} diff -r e200cb7efeb3 -r c2387f117808 vendor/consolidation/annotated-command/tests/testCommandFileDiscovery.php --- a/vendor/consolidation/annotated-command/tests/testCommandFileDiscovery.php Thu Apr 26 11:26:54 2018 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,82 +0,0 @@ -setSearchPattern('*CommandFile.php') - ->setSearchLocations(['alpha']); - - chdir(__DIR__); - $commandFiles = $discovery->discover('.', '\Consolidation\TestUtils'); - - $commandFilePaths = array_keys($commandFiles); - $commandFileNamespaces = array_values($commandFiles); - - // Ensure that the command files that we expected to - // find were all found. We don't find anything in - // 'beta' because only 'alpha' is in the search path. - $this->assertContains('./src/ExampleCommandFile.php', $commandFilePaths); - $this->assertContains('./src/ExampleHookAllCommandFile.php', $commandFilePaths); - $this->assertContains('./src/alpha/AlphaCommandFile.php', $commandFilePaths); - $this->assertContains('./src/alpha/Inclusive/IncludedCommandFile.php', $commandFilePaths); - - // Make sure that there are no additional items found. - $this->assertEquals(4, count($commandFilePaths)); - - // Ensure that the command file namespaces that we expected - // to be generated all match. - $this->assertContains('\Consolidation\TestUtils\ExampleCommandFile', $commandFileNamespaces); - $this->assertContains('\Consolidation\TestUtils\ExampleHookAllCommandFile', $commandFileNamespaces); - $this->assertContains('\Consolidation\TestUtils\alpha\AlphaCommandFile', $commandFileNamespaces); - $this->assertContains('\Consolidation\TestUtils\alpha\Inclusive\IncludedCommandFile', $commandFileNamespaces); - - // We do not need to test for additional namespace items, because we - // know that the length of the array_keys must be the same as the - // length of the array_values. - } - - function testDeepCommandDiscovery() - { - $discovery = new CommandFileDiscovery(); - $discovery - ->setSearchPattern('*CommandFile.php') - ->setSearchDepth(1) - ->setSearchLocations([]); - - chdir(__DIR__); - $commandFiles = $discovery->discover('.', '\Consolidation\TestUtils'); - - $commandFilePaths = array_keys($commandFiles); - $commandFileNamespaces = array_values($commandFiles); - - // Ensure that the command files that we expected to - // find were all found. We find both 'alpha' and 'beta' - // items because the search locations is empty, which - // causes the search at the base directory to be deep. - // We do not find alpha/Inclusive, though, as the search - // depth is only 2, which excludes directories that are - // three levels deep. - $this->assertContains('./src/ExampleCommandFile.php', $commandFilePaths); - $this->assertContains('./src/ExampleHookAllCommandFile.php', $commandFilePaths); - $this->assertContains('./src/alpha/AlphaCommandFile.php', $commandFilePaths); - $this->assertContains('./src/beta/BetaCommandFile.php', $commandFilePaths); - - // Make sure that there are no additional items found. - $this->assertEquals(4, count($commandFilePaths)); - - // Ensure that the command file namespaces that we expected - // to be generated all match. - $this->assertContains('\Consolidation\TestUtils\ExampleCommandFile', $commandFileNamespaces); - $this->assertContains('\Consolidation\TestUtils\ExampleHookAllCommandFile', $commandFileNamespaces); - $this->assertContains('\Consolidation\TestUtils\alpha\AlphaCommandFile', $commandFileNamespaces); - $this->assertContains('\Consolidation\TestUtils\beta\BetaCommandFile', $commandFileNamespaces); - - // We do not need to test for additional namespace items, because we - // know that the length of the array_keys must be the same as the - // length of the array_values. - } -} diff -r e200cb7efeb3 -r c2387f117808 vendor/consolidation/annotated-command/tests/testCommandInfo.php --- a/vendor/consolidation/annotated-command/tests/testCommandInfo.php Thu Apr 26 11:26:54 2018 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,102 +0,0 @@ - $value) { - if (!is_string($value)) { - $value = var_export($value, true); - } - $result[] = "{$key}=>{$value}"; - } - return implode("\n", $result); - } - - /** - * Test CommandInfo command annotation parsing. - */ - function testParsing() - { - $commandInfo = CommandInfo::create('\Consolidation\TestUtils\ExampleCommandFile', 'testArithmatic'); - $this->assertCommandInfoIsAsExpected($commandInfo); - - $serializer = new CommandInfoSerializer(); - $serialized = $serializer->serialize($commandInfo); - - $deserializer = new CommandInfoDeserializer(); - - $deserializedCommandInfo = $deserializer->deserialize($serialized); - $this->assertCommandInfoIsAsExpected($deserializedCommandInfo); - } - - function testWithConfigImport() - { - $commandInfo = CommandInfo::create('\Consolidation\TestUtils\ExampleCommandFile', 'import'); - $this->assertEquals('config:import', $commandInfo->getName()); - - $this->assertEquals( - 'A config directory label (i.e. a key in \$config_directories array in settings.php).', - $commandInfo->arguments()->getDescription('label') - ); - } - - function assertCommandInfoIsAsExpected($commandInfo) - { - $this->assertEquals('test:arithmatic', $commandInfo->getName()); - $this->assertEquals( - 'This is the test:arithmatic command', - $commandInfo->getDescription() - ); - $this->assertEquals( - "This command will add one and two. If the --negate flag\nis provided, then the result is negated.", - $commandInfo->getHelp() - ); - $this->assertEquals('arithmatic', implode(',', $commandInfo->getAliases())); - $this->assertEquals( - '2 2 --negate=>Add two plus two and then negate.', - $this->flattenArray($commandInfo->getExampleUsages()) - ); - $this->assertEquals( - 'The first number to add.', - $commandInfo->arguments()->getDescription('one') - ); - $this->assertEquals( - 'The other number to add.', - $commandInfo->arguments()->getDescription('two') - ); - $this->assertEquals( - '2', - $commandInfo->arguments()->get('two') - ); - $this->assertEquals( - 'Whether or not the result should be negated.', - $commandInfo->options()->getDescription('negate') - ); - $this->assertEquals( - 'bob', - $commandInfo->options()->get('unused') - ); - $this->assertEquals( - 'one,two', - $commandInfo->getAnnotation('dup') - ); - $this->assertEquals( - ['one','two'], - $commandInfo->getAnnotationList('dup') - ); - } - - function testReturnValue() - { - $commandInfo = CommandInfo::create('\Consolidation\TestUtils\alpha\AlphaCommandFile', 'exampleTable'); - $this->assertEquals('example:table', $commandInfo->getName()); - $this->assertEquals('\Consolidation\OutputFormatters\StructuredData\RowsOfFields', $commandInfo->getReturnType()); - } -} diff -r e200cb7efeb3 -r c2387f117808 vendor/consolidation/annotated-command/tests/testFullStack.php --- a/vendor/consolidation/annotated-command/tests/testFullStack.php Thu Apr 26 11:26:54 2018 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,530 +0,0 @@ -application = new ApplicationWithTerminalWidth('TestApplication', '0.0.0'); - $this->commandFactory = new AnnotatedCommandFactory(); - $alterOptionsEventManager = new AlterOptionsCommandEvent($this->application); - $eventDispatcher = new \Symfony\Component\EventDispatcher\EventDispatcher(); - $eventDispatcher->addSubscriber($this->commandFactory->commandProcessor()->hookManager()); - $this->commandFactory->commandProcessor()->hookManager()->addCommandEvent($alterOptionsEventManager); - $this->application->setDispatcher($eventDispatcher); - $this->application->setAutoExit(false); - } - - function testValidFormats() - { - $formatter = new FormatterManager(); - $formatter->addDefaultFormatters(); - $formatter->addDefaultSimplifiers(); - $commandInfo = CommandInfo::create('\Consolidation\TestUtils\alpha\AlphaCommandFile', 'exampleTable'); - $this->assertEquals('example:table', $commandInfo->getName()); - $this->assertEquals('\Consolidation\OutputFormatters\StructuredData\RowsOfFields', $commandInfo->getReturnType()); - } - - function testAutomaticOptions() - { - $commandFileInstance = new \Consolidation\TestUtils\alpha\AlphaCommandFile; - $formatter = new FormatterManager(); - $formatter->addDefaultFormatters(); - $formatter->addDefaultSimplifiers(); - - $this->commandFactory->commandProcessor()->setFormatterManager($formatter); - $this->assertAutomaticOptionsForCommand($commandFileInstance, 'exampleTable', 'example:table'); - $this->assertAutomaticOptionsForCommand($commandFileInstance, 'exampleTableTwo', 'example:table2'); - } - - function assertAutomaticOptionsForCommand($commandFileInstance, $functionName, $commandName) - { - $commandInfo = $this->commandFactory->createCommandInfo($commandFileInstance, $functionName); - - $command = $this->commandFactory->createCommand($commandInfo, $commandFileInstance); - $this->application->add($command); - - $containsList = - [ - '--format[=FORMAT] Format the result data. Available formats: csv,json,list,php,print-r,sections,string,table,tsv,var_export,xml,yaml [default: "table"]', - '--fields[=FIELDS] Available fields: I (first), II (second), III (third) [default: ""]', - ]; - $this->assertRunCommandViaApplicationContains('help ' . $commandName, $containsList); - } - - function testCommandsAndHooks() - { - // First, search for commandfiles in the 'alpha' - // directory. Note that this same functionality - // is tested more thoroughly in isolation in - // testCommandFileDiscovery.php - $discovery = new CommandFileDiscovery(); - $discovery - ->setSearchPattern('*CommandFile.php') - ->setIncludeFilesAtBase(false) - ->setSearchLocations(['alpha']); - - chdir(__DIR__); - $commandFiles = $discovery->discover('.', '\Consolidation\TestUtils'); - - $formatter = new FormatterManager(); - $formatter->addDefaultFormatters(); - $formatter->addDefaultSimplifiers(); - $hookManager = new HookManager(); - $terminalWidthOption = new PrepareTerminalWidthOption(); - $terminalWidthOption->enableWrap(true); - $terminalWidthOption->setApplication($this->application); - $testTerminal = new TestTerminal(0); - $terminalWidthOption->setTerminal($testTerminal); - $commandProcessor = new CommandProcessor($hookManager); - $commandProcessor->setFormatterManager($formatter); - $commandProcessor->addPrepareFormatter($terminalWidthOption); - - // Create a new factory, and load all of the files - // discovered above. - $factory = new AnnotatedCommandFactory(); - $factory->setCommandProcessor($commandProcessor); - // Add a listener to configure our command handler object - $factory->addListernerCallback(function($command) use($hookManager) { - if ($command instanceof CustomEventAwareInterface) { - $command->setHookManager($hookManager); - } - } ); - $factory->setIncludeAllPublicMethods(false); - $this->addDiscoveredCommands($factory, $commandFiles); - - $this->assertRunCommandViaApplicationContains('list', ['example:table'], ['additional:option', 'without:annotations']); - - $this->assertTrue($this->application->has('example:table')); - $this->assertFalse($this->application->has('without:annotations')); - - // Run the use:event command that defines a custom event, my-event. - $this->assertRunCommandViaApplicationEquals('use:event', 'one,two'); - // Watch as we dynamically add a custom event to the hook manager to change the command results: - $hookManager->add(function () { return 'three'; }, HookManager::ON_EVENT, 'my-event'); - $this->assertRunCommandViaApplicationEquals('use:event', 'one,three,two'); - - // Fetch a reference to the 'example:table' command and test its valid format types - $exampleTableCommand = $this->application->find('example:table'); - $returnType = $exampleTableCommand->getReturnType(); - $this->assertEquals('\Consolidation\OutputFormatters\StructuredData\RowsOfFields', $returnType); - $validFormats = $formatter->validFormats($returnType); - $this->assertEquals('csv,json,list,php,print-r,sections,string,table,tsv,var_export,xml,yaml', implode(',', $validFormats)); - - // Control: run commands without hooks. - $this->assertRunCommandViaApplicationEquals('always:fail', 'This command always fails.', 13); - $this->assertRunCommandViaApplicationEquals('simulated:status', '42'); - $this->assertRunCommandViaApplicationEquals('example:output', 'Hello, World.'); - $this->assertRunCommandViaApplicationEquals('example:cat bet alpha --flip', 'alphabet'); - $this->assertRunCommandViaApplicationEquals('example:echo a b c', "a\tb\tc"); - $this->assertRunCommandViaApplicationEquals('example:message', 'Shipwrecked; send bananas.'); - $this->assertRunCommandViaApplicationEquals('command:with-one-optional-argument', 'Hello, world'); - $this->assertRunCommandViaApplicationEquals('command:with-one-optional-argument Joe', 'Hello, Joe'); - - // Add some hooks. - $factory->hookManager()->addValidator(new ExampleValidator()); - $factory->hookManager()->addResultProcessor(new ExampleResultProcessor()); - $factory->hookManager()->addAlterResult(new ExampleResultAlterer()); - $factory->hookManager()->addStatusDeterminer(new ExampleStatusDeterminer()); - $factory->hookManager()->addOutputExtractor(new ExampleOutputExtractor()); - - // Run the same commands as before, and confirm that results - // are different now that the hooks are in place. - $this->assertRunCommandViaApplicationEquals('simulated:status', '', 42); - $this->assertRunCommandViaApplicationEquals('example:output', 'Hello, World!'); - $this->assertRunCommandViaApplicationEquals('example:cat bet alpha --flip', 'alphareplaced'); - $this->assertRunCommandViaApplicationEquals('example:echo a b c', 'a,b,c'); - $this->assertRunCommandViaApplicationEquals('example:message', 'Shipwrecked; send bananas.'); - - $expected = <<assertRunCommandViaApplicationEquals('example:table', $expected); - - $expected = <<assertRunCommandViaApplicationEquals('example:table --fields=III,II', $expected); - - $expectedSingleField = <<assertRunCommandViaApplicationEquals('example:table --field=II', $expectedSingleField); - - // Check the help for the example table command and see if the options - // from the alter hook were added. We expect that we should not see - // any of the information from the alter hook in the 'beta' folder yet. - $this->assertRunCommandViaApplicationContains('help example:table', - [ - 'Option added by @hook option example:table', - 'example:table --french', - 'Add a row with French numbers.' - ], - [ - 'chinese', - 'kanji', - ] - ); - - $expectedOutputWithFrench = <<assertRunCommandViaApplicationEquals('example:table --french', $expectedOutputWithFrench); - - $expectedAssociativeListTable = <<assertRunCommandViaApplicationEquals('example:list', $expectedAssociativeListTable); - $this->assertRunCommandViaApplicationEquals('example:list --field=sftp_command', 'sftp -o Port=2222 dev@appserver.dev.drush.in'); - - $this->assertRunCommandViaApplicationEquals('get:serious', 'very serious'); - $this->assertRunCommandViaApplicationContains('get:lost', 'Command "get:lost" is not defined.', [], 1); - - $this->assertRunCommandViaApplicationContains('help example:wrap', - [ - 'Test word wrapping', - '[default: "table"]', - ] - ); - - $expectedUnwrappedOutput = <<application->setWidthAndHeight(0, 0); - $this->assertRunCommandViaApplicationEquals('example:wrap', $expectedUnwrappedOutput); - - $expectedWrappedOutput = <<application->setWidthAndHeight(42, 24); - $testTerminal->setWidth(42); - $this->assertRunCommandViaApplicationEquals('example:wrap', $expectedWrappedOutput); - } - - function testCommandsAndHooksIncludeAllPublicMethods() - { - // First, search for commandfiles in the 'alpha' - // directory. Note that this same functionality - // is tested more thoroughly in isolation in - // testCommandFileDiscovery.php - $discovery = new CommandFileDiscovery(); - $discovery - ->setSearchPattern('*CommandFile.php') - ->setIncludeFilesAtBase(false) - ->setSearchLocations(['alpha']); - - chdir(__DIR__); - $commandFiles = $discovery->discover('.', '\Consolidation\TestUtils'); - - $formatter = new FormatterManager(); - $formatter->addDefaultFormatters(); - $formatter->addDefaultSimplifiers(); - $hookManager = new HookManager(); - $commandProcessor = new CommandProcessor($hookManager); - $commandProcessor->setFormatterManager($formatter); - - // Create a new factory, and load all of the files - // discovered above. The command factory class is - // tested in isolation in testAnnotatedCommandFactory.php, - // but this is the only place where - $factory = new AnnotatedCommandFactory(); - $factory->setCommandProcessor($commandProcessor); - // $factory->addListener(...); - - // Now we will once again add all commands, this time including all - // public methods. The command 'withoutAnnotations' should now be found. - $factory->setIncludeAllPublicMethods(true); - $this->addDiscoveredCommands($factory, $commandFiles); - $this->assertTrue($this->application->has('without:annotations')); - - $this->assertRunCommandViaApplicationContains('list', ['example:table', 'without:annotations'], ['alter:formatters']); - - $this->assertRunCommandViaApplicationEquals('get:serious', 'very serious'); - $this->assertRunCommandViaApplicationContains('get:lost', 'Command "get:lost" is not defined.', [], 1); - } - - function testCommandsAndHooksWithBetaFolder() - { - // First, search for commandfiles in the 'alpha' - // directory. Note that this same functionality - // is tested more thoroughly in isolation in - // testCommandFileDiscovery.php - $discovery = new CommandFileDiscovery(); - $discovery - ->setSearchPattern('*CommandFile.php') - ->setIncludeFilesAtBase(false) - ->setSearchLocations(['alpha', 'beta']); - - chdir(__DIR__); - $commandFiles = $discovery->discover('.', '\Consolidation\TestUtils'); - - $formatter = new FormatterManager(); - $formatter->addDefaultFormatters(); - $formatter->addDefaultSimplifiers(); - $hookManager = new HookManager(); - $commandProcessor = new CommandProcessor($hookManager); - $commandProcessor->setFormatterManager($formatter); - - // Create a new factory, and load all of the files - // discovered above. The command factory class is - // tested in isolation in testAnnotatedCommandFactory.php, - // but this is the only place where - $factory = new AnnotatedCommandFactory(); - $factory->setCommandProcessor($commandProcessor); - // $factory->addListener(...); - $factory->setIncludeAllPublicMethods(true); - $this->addDiscoveredCommands($factory, $commandFiles); - - // A few asserts, to make sure that our hooks all get registered. - $allRegisteredHooks = $hookManager->getAllHooks(); - $registeredHookNames = array_keys($allRegisteredHooks); - sort($registeredHookNames); - $this->assertEquals('*,example:table,my-event', implode(',', $registeredHookNames)); - $allHooksForExampleTable = $allRegisteredHooks['example:table']; - $allHookPhasesForExampleTable = array_keys($allHooksForExampleTable); - sort($allHookPhasesForExampleTable); - $this->assertEquals('alter,option', implode(',', $allHookPhasesForExampleTable)); - - $this->assertContains('alterFormattersChinese', var_export($allHooksForExampleTable, true)); - - $alterHooksForExampleTable = $this->callProtected($hookManager, 'getHooks', [['example:table'], 'alter']); - $this->assertContains('alterFormattersKanji', var_export($alterHooksForExampleTable, true)); - - $allHooksForAnyCommand = $allRegisteredHooks['*']; - $allHookPhasesForAnyCommand = array_keys($allHooksForAnyCommand); - sort($allHookPhasesForAnyCommand); - $this->assertEquals('alter', implode(',', $allHookPhasesForAnyCommand)); - - $this->assertContains('alterFormattersKanji', var_export($allHooksForAnyCommand, true)); - - // Help should have the information from the hooks in the 'beta' folder - $this->assertRunCommandViaApplicationContains('help example:table', - [ - 'Option added by @hook option example:table', - 'example:table --french', - 'Add a row with French numbers.', - 'chinese', - 'kanji', - ] - ); - - // Confirm that the "unavailable" command is now available - $this->assertTrue($this->application->has('unavailable:command')); - - $expectedOutputWithChinese = <<assertRunCommandViaApplicationEquals('example:table --chinese', $expectedOutputWithChinese); - - $expectedOutputWithKanji = <<assertRunCommandViaApplicationEquals('example:table --kanji', $expectedOutputWithKanji); - } - - public function addDiscoveredCommands($factory, $commandFiles) { - foreach ($commandFiles as $path => $commandClass) { - $this->assertFileExists($path); - if (!class_exists($commandClass)) { - include $path; - } - $commandInstance = new $commandClass(); - $commandList = $factory->createCommandsFromClass($commandInstance); - foreach ($commandList as $command) { - $this->application->add($command); - } - } - } - - function assertRunCommandViaApplicationEquals($cmd, $expectedOutput, $expectedStatusCode = 0) - { - $input = new StringInput($cmd); - $output = new BufferedOutput(); - - $statusCode = $this->application->run($input, $output); - $commandOutput = trim($output->fetch()); - - $expectedOutput = $this->simplifyWhitespace($expectedOutput); - $commandOutput = $this->simplifyWhitespace($commandOutput); - - $this->assertEquals($expectedOutput, $commandOutput); - $this->assertEquals($expectedStatusCode, $statusCode); - } - - function assertRunCommandViaApplicationContains($cmd, $containsList, $doesNotContainList = [], $expectedStatusCode = 0) - { - $input = new StringInput($cmd); - $output = new BufferedOutput(); - $containsList = (array) $containsList; - - $statusCode = $this->application->run($input, $output); - $commandOutput = trim($output->fetch()); - - $commandOutput = $this->simplifyWhitespace($commandOutput); - - foreach ($containsList as $expectedToContain) { - $this->assertContains($this->simplifyWhitespace($expectedToContain), $commandOutput); - } - foreach ($doesNotContainList as $expectedToNotContain) { - $this->assertNotContains($this->simplifyWhitespace($expectedToNotContain), $commandOutput); - } - $this->assertEquals($expectedStatusCode, $statusCode); - } - - function simplifyWhitespace($data) - { - return trim(preg_replace('#\s+$#m', '', $data)); - } - - function callProtected($object, $method, $args = []) - { - $r = new \ReflectionMethod($object, $method); - $r->setAccessible(true); - return $r->invokeArgs($object, $args); - } - -} - -class ExampleValidator implements ValidatorInterface -{ - public function validate(CommandData $commandData) - { - $args = $commandData->arguments(); - if (isset($args['one']) && ($args['one'] == 'bet')) { - $commandData->input()->setArgument('one', 'replaced'); - return $args; - } - } -} - -class ExampleResultProcessor implements ProcessResultInterface -{ - public function process($result, CommandData $commandData) - { - if (is_array($result) && array_key_exists('item-list', $result)) { - return implode(',', $result['item-list']); - } - } -} - -class ExampleResultAlterer implements AlterResultInterface -{ - public function process($result, CommandData $commandData) - { - if (is_string($result) && ($result == 'Hello, World.')) { - return 'Hello, World!'; - } - } -} - -class ExampleStatusDeterminer implements StatusDeterminerInterface -{ - public function determineStatusCode($result) - { - if (is_array($result) && array_key_exists('status-code', $result)) { - return $result['status-code']; - } - } -} - -class ExampleOutputExtractor implements ExtractOutputInterface -{ - public function extractOutput($result) - { - if (is_array($result) && array_key_exists('message', $result)) { - return $result['message']; - } - } -} diff -r e200cb7efeb3 -r c2387f117808 vendor/consolidation/annotated-command/tests/testHelp.php --- a/vendor/consolidation/annotated-command/tests/testHelp.php Thu Apr 26 11:26:54 2018 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,313 +0,0 @@ -application = new ApplicationWithTerminalWidth('TestApplication', '0.0.0'); - $this->commandFactory = new AnnotatedCommandFactory(); - // $factory->addListener(...); - $alterOptionsEventManager = new AlterOptionsCommandEvent($this->application); - $eventDispatcher = new \Symfony\Component\EventDispatcher\EventDispatcher(); - $eventDispatcher->addSubscriber($this->commandFactory->commandProcessor()->hookManager()); - $this->commandFactory->commandProcessor()->hookManager()->addCommandEvent($alterOptionsEventManager); - $this->application->setDispatcher($eventDispatcher); - $this->application->setAutoExit(false); - - $discovery = new CommandFileDiscovery(); - $discovery - ->setSearchPattern('*CommandFile.php') - ->setIncludeFilesAtBase(false) - ->setSearchLocations(['alpha']); - - chdir(__DIR__); - $commandFiles = $discovery->discover('.', '\Consolidation\TestUtils'); - - $formatter = new FormatterManager(); - $formatter->addDefaultFormatters(); - $formatter->addDefaultSimplifiers(); - $terminalWidthOption = new PrepareTerminalWidthOption(); - $terminalWidthOption->setApplication($this->application); - $this->commandFactory->commandProcessor()->setFormatterManager($formatter); - $this->commandFactory->commandProcessor()->addPrepareFormatter($terminalWidthOption); - - $this->commandFactory->setIncludeAllPublicMethods(false); - $this->addDiscoveredCommands($this->commandFactory, $commandFiles); - - $helpCommandfile = new HelpCommand($this->application); - $commandList = $this->commandFactory->createCommandsFromClass($helpCommandfile); - foreach ($commandList as $command) { - $this->application->add($command); - } - } - - public function addDiscoveredCommands($factory, $commandFiles) { - foreach ($commandFiles as $path => $commandClass) { - $this->assertFileExists($path); - if (!class_exists($commandClass)) { - include $path; - } - $commandInstance = new $commandClass(); - $commandList = $factory->createCommandsFromClass($commandInstance); - foreach ($commandList as $command) { - $this->application->add($command); - } - } - } - - function assertRunCommandViaApplicationEquals($cmd, $expectedOutput, $expectedStatusCode = 0) - { - $input = new StringInput($cmd); - $output = new BufferedOutput(); - - $statusCode = $this->application->run($input, $output); - $commandOutput = trim($output->fetch()); - - $expectedOutput = $this->simplifyWhitespace($expectedOutput); - $commandOutput = $this->simplifyWhitespace($commandOutput); - - $this->assertEquals($expectedOutput, $commandOutput); - $this->assertEquals($expectedStatusCode, $statusCode); - } - - function simplifyWhitespace($data) - { - return trim(preg_replace('#\s+$#m', '', $data)); - } - - function testHelp() - { - $expectedXML = << - - - example:table [--format [FORMAT]] [--fields [FIELDS]] [--field FIELD] [--] [<unused>] - - - - example:table --format=yml - Show the example table in yml format. - - - example:table --fields=first,third - Show only the first and third fields in the table. - - - example:table --fields=II,III - Note that either the field ID or the visible field label may be used. - - - Test command with formatters - - - An unused argument - - - - - - - - - - - - - - - - Test command with formatters - - extab - - - docs-tables - - -EOT; - - $this->assertRunCommandViaApplicationEquals('my-help --format=xml example:table', $expectedXML); - - $expectedJSON = <<]" - ], - "examples": [ - { - "usage": "example:table --format=yml", - "description": "Show the example table in yml format." - }, - { - "usage": "example:table --fields=first,third", - "description": "Show only the first and third fields in the table." - }, - { - "usage": "example:table --fields=II,III", - "description": "Note that either the field ID or the visible field label may be used." - } - ], - "description": "Test command with formatters", - "arguments": { - "unused": { - "name": "unused", - "is_required": "0", - "is_array": "0", - "description": "An unused argument" - } - }, - "options": { - "format": { - "name": "--format", - "shortcut": "", - "accept_value": "1", - "is_value_required": "0", - "is_multiple": "0", - "description": "Format the result data. Available formats: csv,json,list,php,print-r,sections,string,table,tsv,var_export,xml,yaml", - "defaults": [ - "table" - ] - }, - "fields": { - "name": "--fields", - "shortcut": "", - "accept_value": "1", - "is_value_required": "0", - "is_multiple": "0", - "description": "Available fields: I (first), II (second), III (third)" - }, - "field": { - "name": "--field", - "shortcut": "", - "accept_value": "1", - "is_value_required": "1", - "is_multiple": "0", - "description": "Select just one field, and force format to 'string'." - }, - "help": { - "name": "--help", - "shortcut": "-h", - "accept_value": "0", - "is_value_required": "0", - "is_multiple": "0", - "description": "Display this help message" - }, - "quiet": { - "name": "--quiet", - "shortcut": "-q", - "accept_value": "0", - "is_value_required": "0", - "is_multiple": "0", - "description": "Do not output any message" - }, - "verbose": { - "name": "--verbose", - "shortcut": "-v", - "shortcuts": "-v|-vv|-vvv", - "accept_value": "0", - "is_value_required": "0", - "is_multiple": "0", - "description": "Increase the verbosity of messages: 1 for normal output, 2 for more verbose output and 3 for debug" - }, - "version": { - "name": "--version", - "shortcut": "-V", - "accept_value": "0", - "is_value_required": "0", - "is_multiple": "0", - "description": "Display this application version" - }, - "ansi": { - "name": "--ansi", - "shortcut": "", - "accept_value": "0", - "is_value_required": "0", - "is_multiple": "0", - "description": "Force ANSI output" - }, - "no-ansi": { - "name": "--no-ansi", - "shortcut": "", - "accept_value": "0", - "is_value_required": "0", - "is_multiple": "0", - "description": "Disable ANSI output" - }, - "no-interaction": { - "name": "--no-interaction", - "shortcut": "-n", - "accept_value": "0", - "is_value_required": "0", - "is_multiple": "0", - "description": "Do not ask any interactive question" - } - }, - "help": "Test command with formatters", - "aliases": [ - "extab" - ], - "topics": [ - "docs-tables" - ] -} -EOT; - $this->assertRunCommandViaApplicationEquals('my-help --format=json example:table', $expectedJSON); - } -} diff -r e200cb7efeb3 -r c2387f117808 vendor/consolidation/output-formatters/LICENSE --- a/vendor/consolidation/output-formatters/LICENSE Thu Apr 26 11:26:54 2018 +0100 +++ b/vendor/consolidation/output-formatters/LICENSE Tue Jul 10 15:07:59 2018 +0100 @@ -12,6 +12,6 @@ Name Version License psr/log 1.0.2 MIT symfony/console v3.2.3 MIT -symfony/debug v3.4.6 MIT -symfony/finder v3.4.6 MIT -symfony/polyfill-mbstring v1.7.0 MIT +symfony/debug v3.4.11 MIT +symfony/finder v3.4.11 MIT +symfony/polyfill-mbstring v1.8.0 MIT diff -r e200cb7efeb3 -r c2387f117808 vendor/consolidation/output-formatters/composer.json --- a/vendor/consolidation/output-formatters/composer.json Thu Apr 26 11:26:54 2018 +0100 +++ b/vendor/consolidation/output-formatters/composer.json Tue Jul 10 15:07:59 2018 +0100 @@ -24,7 +24,7 @@ "symfony/finder": "^2.5|^3|^4" }, "require-dev": { - "g-1-a/composer-test-scenarios": "^2", + "g1a/composer-test-scenarios": "^2", "satooshi/php-coveralls": "^2", "phpunit/phpunit": "^5.7.27", "squizlabs/php_codesniffer": "^2.7", diff -r e200cb7efeb3 -r c2387f117808 vendor/consolidation/output-formatters/composer.lock --- a/vendor/consolidation/output-formatters/composer.lock Thu Apr 26 11:26:54 2018 +0100 +++ b/vendor/consolidation/output-formatters/composer.lock Tue Jul 10 15:07:59 2018 +0100 @@ -1,10 +1,10 @@ { "_readme": [ "This file locks the dependencies of your project to a known state", - "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", + "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "e2bbb58b3928f0bfa988f94bdd209c84", + "content-hash": "e726e2302b89b56b1cf5c8148a65a648", "packages": [ { "name": "psr/log", @@ -118,16 +118,16 @@ }, { "name": "symfony/debug", - "version": "v3.4.6", + "version": "v3.4.11", "source": { "type": "git", "url": "https://github.com/symfony/debug.git", - "reference": "9b1071f86e79e1999b3d3675d2e0e7684268b9bc" + "reference": "b28fd73fefbac341f673f5efd707d539d6a19f68" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/debug/zipball/9b1071f86e79e1999b3d3675d2e0e7684268b9bc", - "reference": "9b1071f86e79e1999b3d3675d2e0e7684268b9bc", + "url": "https://api.github.com/repos/symfony/debug/zipball/b28fd73fefbac341f673f5efd707d539d6a19f68", + "reference": "b28fd73fefbac341f673f5efd707d539d6a19f68", "shasum": "" }, "require": { @@ -170,20 +170,20 @@ ], "description": "Symfony Debug Component", "homepage": "https://symfony.com", - "time": "2018-02-28T21:49:22+00:00" + "time": "2018-05-16T14:03:39+00:00" }, { "name": "symfony/finder", - "version": "v3.4.6", + "version": "v3.4.11", "source": { "type": "git", "url": "https://github.com/symfony/finder.git", - "reference": "a479817ce0a9e4adfd7d39c6407c95d97c254625" + "reference": "472a92f3df8b247b49ae364275fb32943b9656c6" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/finder/zipball/a479817ce0a9e4adfd7d39c6407c95d97c254625", - "reference": "a479817ce0a9e4adfd7d39c6407c95d97c254625", + "url": "https://api.github.com/repos/symfony/finder/zipball/472a92f3df8b247b49ae364275fb32943b9656c6", + "reference": "472a92f3df8b247b49ae364275fb32943b9656c6", "shasum": "" }, "require": { @@ -219,20 +219,20 @@ ], "description": "Symfony Finder Component", "homepage": "https://symfony.com", - "time": "2018-03-05T18:28:11+00:00" + "time": "2018-05-16T08:49:21+00:00" }, { "name": "symfony/polyfill-mbstring", - "version": "v1.7.0", + "version": "v1.8.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-mbstring.git", - "reference": "78be803ce01e55d3491c1397cf1c64beb9c1b63b" + "reference": "3296adf6a6454a050679cde90f95350ad604b171" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/78be803ce01e55d3491c1397cf1c64beb9c1b63b", - "reference": "78be803ce01e55d3491c1397cf1c64beb9c1b63b", + "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/3296adf6a6454a050679cde90f95350ad604b171", + "reference": "3296adf6a6454a050679cde90f95350ad604b171", "shasum": "" }, "require": { @@ -244,7 +244,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "1.7-dev" + "dev-master": "1.8-dev" } }, "autoload": { @@ -278,7 +278,7 @@ "portable", "shim" ], - "time": "2018-01-30T19:27:44+00:00" + "time": "2018-04-26T10:06:28+00:00" } ], "packages-dev": [ @@ -337,17 +337,17 @@ "time": "2015-06-14T21:17:01+00:00" }, { - "name": "g-1-a/composer-test-scenarios", - "version": "dev-better-highest-lowest", + "name": "g1a/composer-test-scenarios", + "version": "2.0.1", "source": { "type": "git", - "url": "https://github.com/g-1-a/composer-test-scenarios.git", - "reference": "d206cd08a9dcecf38419093fedd286f452ba4685" + "url": "https://github.com/g1a/composer-test-scenarios.git", + "reference": "d9a7619f6e1c01498fad19c34539bd5b0d2506ef" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/g-1-a/composer-test-scenarios/zipball/d206cd08a9dcecf38419093fedd286f452ba4685", - "reference": "d206cd08a9dcecf38419093fedd286f452ba4685", + "url": "https://api.github.com/repos/g1a/composer-test-scenarios/zipball/d9a7619f6e1c01498fad19c34539bd5b0d2506ef", + "reference": "d9a7619f6e1c01498fad19c34539bd5b0d2506ef", "shasum": "" }, "bin": [ @@ -367,20 +367,20 @@ } ], "description": "Useful scripts for testing multiple sets of Composer dependencies.", - "time": "2018-03-19T05:06:40+00:00" + "time": "2018-05-25T16:45:48+00:00" }, { "name": "guzzlehttp/guzzle", - "version": "6.3.0", + "version": "6.3.3", "source": { "type": "git", "url": "https://github.com/guzzle/guzzle.git", - "reference": "f4db5a78a5ea468d4831de7f0bf9d9415e348699" + "reference": "407b0cb880ace85c9b63c5f9551db498cb2d50ba" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/guzzle/guzzle/zipball/f4db5a78a5ea468d4831de7f0bf9d9415e348699", - "reference": "f4db5a78a5ea468d4831de7f0bf9d9415e348699", + "url": "https://api.github.com/repos/guzzle/guzzle/zipball/407b0cb880ace85c9b63c5f9551db498cb2d50ba", + "reference": "407b0cb880ace85c9b63c5f9551db498cb2d50ba", "shasum": "" }, "require": { @@ -390,7 +390,7 @@ }, "require-dev": { "ext-curl": "*", - "phpunit/phpunit": "^4.0 || ^5.0", + "phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.4 || ^7.0", "psr/log": "^1.0" }, "suggest": { @@ -399,7 +399,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "6.2-dev" + "dev-master": "6.3-dev" } }, "autoload": { @@ -432,7 +432,7 @@ "rest", "web service" ], - "time": "2017-06-22T18:50:49+00:00" + "time": "2018-04-22T15:46:56+00:00" }, { "name": "guzzlehttp/promises", @@ -743,23 +743,23 @@ }, { "name": "phpspec/prophecy", - "version": "1.7.5", + "version": "1.7.6", "source": { "type": "git", "url": "https://github.com/phpspec/prophecy.git", - "reference": "dfd6be44111a7c41c2e884a336cc4f461b3b2401" + "reference": "33a7e3c4fda54e912ff6338c48823bd5c0f0b712" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpspec/prophecy/zipball/dfd6be44111a7c41c2e884a336cc4f461b3b2401", - "reference": "dfd6be44111a7c41c2e884a336cc4f461b3b2401", + "url": "https://api.github.com/repos/phpspec/prophecy/zipball/33a7e3c4fda54e912ff6338c48823bd5c0f0b712", + "reference": "33a7e3c4fda54e912ff6338c48823bd5c0f0b712", "shasum": "" }, "require": { "doctrine/instantiator": "^1.0.2", "php": "^5.3|^7.0", "phpdocumentor/reflection-docblock": "^2.0|^3.0.2|^4.0", - "sebastian/comparator": "^1.1|^2.0", + "sebastian/comparator": "^1.1|^2.0|^3.0", "sebastian/recursion-context": "^1.0|^2.0|^3.0" }, "require-dev": { @@ -802,7 +802,7 @@ "spy", "stub" ], - "time": "2018-02-19T10:16:54+00:00" + "time": "2018-04-18T13:57:24+00:00" }, { "name": "phpunit/php-code-coverage", @@ -1325,6 +1325,7 @@ "github", "test" ], + "abandoned": "php-coveralls/php-coveralls", "time": "2017-12-08T14:28:16+00:00" }, { @@ -1920,21 +1921,22 @@ }, { "name": "symfony/config", - "version": "v3.4.6", + "version": "v3.4.11", "source": { "type": "git", "url": "https://github.com/symfony/config.git", - "reference": "05e10567b529476a006b00746c5f538f1636810e" + "reference": "73e055cf2e6467715f187724a0347ea32079967c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/config/zipball/05e10567b529476a006b00746c5f538f1636810e", - "reference": "05e10567b529476a006b00746c5f538f1636810e", + "url": "https://api.github.com/repos/symfony/config/zipball/73e055cf2e6467715f187724a0347ea32079967c", + "reference": "73e055cf2e6467715f187724a0347ea32079967c", "shasum": "" }, "require": { "php": "^5.5.9|>=7.0.8", - "symfony/filesystem": "~2.8|~3.0|~4.0" + "symfony/filesystem": "~2.8|~3.0|~4.0", + "symfony/polyfill-ctype": "~1.8" }, "conflict": { "symfony/dependency-injection": "<3.3", @@ -1979,24 +1981,25 @@ ], "description": "Symfony Config Component", "homepage": "https://symfony.com", - "time": "2018-02-14T10:03:57+00:00" + "time": "2018-05-14T16:49:53+00:00" }, { "name": "symfony/filesystem", - "version": "v3.4.6", + "version": "v3.4.11", "source": { "type": "git", "url": "https://github.com/symfony/filesystem.git", - "reference": "253a4490b528597aa14d2bf5aeded6f5e5e4a541" + "reference": "8e03ca3fa52a0f56b87506f38cf7bd3f9442b3a0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/filesystem/zipball/253a4490b528597aa14d2bf5aeded6f5e5e4a541", - "reference": "253a4490b528597aa14d2bf5aeded6f5e5e4a541", + "url": "https://api.github.com/repos/symfony/filesystem/zipball/8e03ca3fa52a0f56b87506f38cf7bd3f9442b3a0", + "reference": "8e03ca3fa52a0f56b87506f38cf7bd3f9442b3a0", "shasum": "" }, "require": { - "php": "^5.5.9|>=7.0.8" + "php": "^5.5.9|>=7.0.8", + "symfony/polyfill-ctype": "~1.8" }, "type": "library", "extra": { @@ -2028,11 +2031,66 @@ ], "description": "Symfony Filesystem Component", "homepage": "https://symfony.com", - "time": "2018-02-22T10:48:49+00:00" + "time": "2018-05-16T08:49:21+00:00" + }, + { + "name": "symfony/polyfill-ctype", + "version": "v1.8.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-ctype.git", + "reference": "7cc359f1b7b80fc25ed7796be7d96adc9b354bae" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/7cc359f1b7b80fc25ed7796be7d96adc9b354bae", + "reference": "7cc359f1b7b80fc25ed7796be7d96adc9b354bae", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.8-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Polyfill\\Ctype\\": "" + }, + "files": [ + "bootstrap.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + }, + { + "name": "Gert de Pagter", + "email": "BackEndTea@gmail.com" + } + ], + "description": "Symfony polyfill for ctype functions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "ctype", + "polyfill", + "portable" + ], + "time": "2018-04-30T19:57:29+00:00" }, { "name": "symfony/stopwatch", - "version": "v3.4.6", + "version": "v3.4.11", "source": { "type": "git", "url": "https://github.com/symfony/stopwatch.git", @@ -2081,16 +2139,16 @@ }, { "name": "symfony/var-dumper", - "version": "v3.4.6", + "version": "v3.4.11", "source": { "type": "git", "url": "https://github.com/symfony/var-dumper.git", - "reference": "80964679d81da3d5618519e0e4be488c3d7ecd7d" + "reference": "0e6545672d8c9ce70dd472adc2f8b03155a46f73" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/var-dumper/zipball/80964679d81da3d5618519e0e4be488c3d7ecd7d", - "reference": "80964679d81da3d5618519e0e4be488c3d7ecd7d", + "url": "https://api.github.com/repos/symfony/var-dumper/zipball/0e6545672d8c9ce70dd472adc2f8b03155a46f73", + "reference": "0e6545672d8c9ce70dd472adc2f8b03155a46f73", "shasum": "" }, "require": { @@ -2146,11 +2204,11 @@ "debug", "dump" ], - "time": "2018-02-22T17:29:24+00:00" + "time": "2018-04-26T12:42:15+00:00" }, { "name": "symfony/yaml", - "version": "v3.3.16", + "version": "v3.3.17", "source": { "type": "git", "url": "https://github.com/symfony/yaml.git", @@ -2300,9 +2358,7 @@ ], "aliases": [], "minimum-stability": "stable", - "stability-flags": { - "g-1-a/composer-test-scenarios": 20 - }, + "stability-flags": [], "prefer-stable": false, "prefer-lowest": false, "platform": { diff -r e200cb7efeb3 -r c2387f117808 vendor/drush/drush/.travis.yml --- a/vendor/drush/drush/.travis.yml Thu Apr 26 11:26:54 2018 +0100 +++ b/vendor/drush/drush/.travis.yml Tue Jul 10 15:07:59 2018 +0100 @@ -8,10 +8,6 @@ - 5.x - /^[[:digit:]]+\.[[:digit:]]+\.[[:digit:]]+.*$/ language: php -php: -# See master-fulltest branch for broader PHP version testing. - - 5.4 - - 7.0 # Cache Composer & Unish directories. cache: @@ -23,46 +19,6 @@ sudo: false env: - matrix: -#D6 - - UNISH_DRUPAL_MAJOR_VERSION=6 PHPUNIT_ARGS=--group=base - - UNISH_DRUPAL_MAJOR_VERSION=6 PHPUNIT_ARGS=--group=commands - - UNISH_DRUPAL_MAJOR_VERSION=6 PHPUNIT_ARGS=--group=pm - - UNISH_DRUPAL_MAJOR_VERSION=6 PHPUNIT_ARGS=--exclude-group=base,make,commands,pm,quick-drupal -#D7 - - UNISH_DRUPAL_MAJOR_VERSION=7 PHPUNIT_ARGS=--group=make - - UNISH_DRUPAL_MAJOR_VERSION=7 PHPUNIT_ARGS=--group=base - - UNISH_DRUPAL_MAJOR_VERSION=7 PHPUNIT_ARGS=--group=commands - - UNISH_DRUPAL_MAJOR_VERSION=7 PHPUNIT_ARGS=--group=pm - - UNISH_DRUPAL_MAJOR_VERSION=7 PHPUNIT_ARGS=--group=quick-drupal - - UNISH_DRUPAL_MAJOR_VERSION=7 PHPUNIT_ARGS=--exclude-group=base,make,commands,pm,quick-drupal -#D8.3.x - - UNISH_DRUPAL_MAJOR_VERSION=8 UNISH_DRUPAL_MINOR_VERSION=3.7 PHPUNIT_ARGS=--group=make - - UNISH_DRUPAL_MAJOR_VERSION=8 UNISH_DRUPAL_MINOR_VERSION=3.7 PHPUNIT_ARGS=--group=base - - UNISH_DRUPAL_MAJOR_VERSION=8 UNISH_DRUPAL_MINOR_VERSION=3.7 PHPUNIT_ARGS=--group=commands - - UNISH_DRUPAL_MAJOR_VERSION=8 UNISH_DRUPAL_MINOR_VERSION=3.7 PHPUNIT_ARGS=--group=pm - - UNISH_DRUPAL_MAJOR_VERSION=8 UNISH_DRUPAL_MINOR_VERSION=3.7 PHPUNIT_ARGS=--group=quick-drupal - - UNISH_DRUPAL_MAJOR_VERSION=8 UNISH_DRUPAL_MINOR_VERSION=3.7 PHPUNIT_ARGS=--exclude-group=base,make,commands,pm,quick-drupal TEST_CHILDREN="drush-ops/config-extra" -#D8.4.x - - UNISH_DRUPAL_MAJOR_VERSION=8 PHPUNIT_ARGS=--group=make - - UNISH_DRUPAL_MAJOR_VERSION=8 PHPUNIT_ARGS=--group=base - - UNISH_DRUPAL_MAJOR_VERSION=8 PHPUNIT_ARGS=--group=commands - - UNISH_DRUPAL_MAJOR_VERSION=8 PHPUNIT_ARGS=--group=pm - - UNISH_DRUPAL_MAJOR_VERSION=8 PHPUNIT_ARGS=--group=quick-drupal - - UNISH_DRUPAL_MAJOR_VERSION=8 PHPUNIT_ARGS=--exclude-group=base,make,commands,pm,quick-drupal - - # - UNISH_DB_URL=sqlite://none/of/this/matters PHPUNIT_ARGS=--group=make - # - UNISH_DB_URL=sqlite://none/of/this/matters PHPUNIT_ARGS=--group=base - # - UNISH_DB_URL=sqlite://none/of/this/matters PHPUNIT_ARGS=--group=commands - # - UNISH_DB_URL=sqlite://none/of/this/matters PHPUNIT_ARGS=--group=pm - # - UNISH_DB_URL=sqlite://none/of/this/matters PHPUNIT_ARGS=--group=quick-drupal - # - UNISH_DB_URL=sqlite://none/of/this/matters PHPUNIT_ARGS=--exclude-group=base,make,commands,pm,quick-drupal - # - UNISH_DB_URL=pgsql://postgres:@localhost PHPUNIT_ARGS=--group=make - # - UNISH_DB_URL=pgsql://postgres:@localhost PHPUNIT_ARGS=--group=base - # - UNISH_DB_URL=pgsql://postgres:@localhost PHPUNIT_ARGS=--group=commands - # - UNISH_DB_URL=pgsql://postgres:@localhost PHPUNIT_ARGS=--group=pm - # - UNISH_DB_URL=pgsql://postgres:@localhost PHPUNIT_ARGS=--group=quick-drupal - # - UNISH_DB_URL=pgsql://postgres:@localhost PHPUNIT_ARGS=--exclude-group=base,make,commands,pm,quick-drupal global: # Github deploy - secure: VfYokT2CchfuBRJp9/gSwfVGPfsVfkZdDVEuNWEqxww3z4vq+5aLKqoCtPL54E5EIMjhyCE3GVo+biG35Gab1KOVgUs8zD1hAUWA1FPKfMFhoPDfI3ZJC2rX2T1iWK4ZR90pBtcPzS+2OObzTYz8go0PfeSTT6eq69Na1KcNLaE= @@ -70,41 +26,81 @@ - UNISH_DB_URL=mysql://root:@127.0.0.1 matrix: - exclude: - # Drupal 6 does not work with php 7, so skip all of the Drupal 6 tests with this php. + include: + # D8.5.x - php: 7.0 - env: UNISH_DRUPAL_MAJOR_VERSION=6 PHPUNIT_ARGS=--group=base + env: 'UNISH_DRUPAL_MAJOR_VERSION=8 UNISH_DRUPAL_MINOR_VERSION=5.0-rc1 PHPUNIT_ARGS=--group=base' - php: 7.0 - env: UNISH_DRUPAL_MAJOR_VERSION=6 PHPUNIT_ARGS=--group=commands + env: 'UNISH_DRUPAL_MAJOR_VERSION=8 UNISH_DRUPAL_MINOR_VERSION=5.0-rc1 PHPUNIT_ARGS=--group=commands' - php: 7.0 - env: UNISH_DRUPAL_MAJOR_VERSION=6 PHPUNIT_ARGS=--group=pm + env: 'UNISH_DRUPAL_MAJOR_VERSION=8 UNISH_DRUPAL_MINOR_VERSION=5.0-rc1 PHPUNIT_ARGS=--group=pm' - php: 7.0 - env: UNISH_DRUPAL_MAJOR_VERSION=6 PHPUNIT_ARGS=--exclude-group=base,make,commands,pm,quick-drupal - # Drupal 8 requires a minimum php of 5.5, so skip all of the Drupal 8 tests with this php. + env: 'UNISH_DRUPAL_MAJOR_VERSION=8 UNISH_DRUPAL_MINOR_VERSION=5.0-rc1 PHPUNIT_ARGS=--group=quick-drupal' + - php: 7.0 + env: 'UNISH_DRUPAL_MAJOR_VERSION=8 UNISH_DRUPAL_MINOR_VERSION=5.0-rc1 PHPUNIT_ARGS=--group=make' + - php: 7.0 + env: 'UNISH_DRUPAL_MAJOR_VERSION=8 UNISH_DRUPAL_MINOR_VERSION=5.0-rc1 PHPUNIT_ARGS=--exclude-group=base,make,commands,pm,quick-drupal TEST_CHILDREN="drush-ops/config-extra"' + + # D8.4.x + - php: 7.0 + env: 'UNISH_DRUPAL_MAJOR_VERSION=8 UNISH_DRUPAL_MINOR_VERSION=4.5 PHPUNIT_ARGS=--group=base' + - php: 7.0 + env: 'UNISH_DRUPAL_MAJOR_VERSION=8 UNISH_DRUPAL_MINOR_VERSION=4.5 PHPUNIT_ARGS=--group=commands' + - php: 7.0 + env: 'UNISH_DRUPAL_MAJOR_VERSION=8 UNISH_DRUPAL_MINOR_VERSION=4.5 PHPUNIT_ARGS=--group=pm' + - php: 7.0 + env: 'UNISH_DRUPAL_MAJOR_VERSION=8 UNISH_DRUPAL_MINOR_VERSION=4.5 PHPUNIT_ARGS=--group=quick-drupal' + - php: 7.0 + env: 'UNISH_DRUPAL_MAJOR_VERSION=8 UNISH_DRUPAL_MINOR_VERSION=4.5 PHPUNIT_ARGS=--group=make' + - php: 7.0 + env: 'UNISH_DRUPAL_MAJOR_VERSION=8 UNISH_DRUPAL_MINOR_VERSION=4.5 PHPUNIT_ARGS=--exclude-group=base,make,commands,pm,quick-drupal TEST_CHILDREN="drush-ops/config-extra"' + + # D8.3.x + - php: 7.0 + env: 'UNISH_DRUPAL_MAJOR_VERSION=8 UNISH_DRUPAL_MINOR_VERSION=3.7 PHPUNIT_ARGS=--group=commands' + + # D8.2.x + - php: 7.0 + env: 'UNISH_DRUPAL_MAJOR_VERSION=8 UNISH_DRUPAL_MINOR_VERSION=2.8 PHPUNIT_ARGS=--group=commands' + + # D7 + - php: 7.0 + env: 'UNISH_DRUPAL_MAJOR_VERSION=7 PHPUNIT_ARGS=--group=base' + - php: 7.0 + env: 'UNISH_DRUPAL_MAJOR_VERSION=7 PHPUNIT_ARGS=--group=commands' + - php: 7.0 + env: 'UNISH_DRUPAL_MAJOR_VERSION=7 PHPUNIT_ARGS=--group=pm' + - php: 7.0 + env: 'UNISH_DRUPAL_MAJOR_VERSION=7 PHPUNIT_ARGS=--group=quick-drupal' + - php: 7.0 + env: 'UNISH_DRUPAL_MAJOR_VERSION=7 PHPUNIT_ARGS=--group=make' + - php: 7.0 + env: 'UNISH_DRUPAL_MAJOR_VERSION=7 PHPUNIT_ARGS=--exclude-group=base,make,commands,pm,quick-drupal TEST_CHILDREN="drush-ops/config-extra"' + + # D7 + - php: 5.6 + env: 'UNISH_DRUPAL_MAJOR_VERSION=7 PHPUNIT_ARGS=--group=base' + - php: 5.6 + env: 'UNISH_DRUPAL_MAJOR_VERSION=7 PHPUNIT_ARGS=--group=commands' + - php: 5.6 + env: 'UNISH_DRUPAL_MAJOR_VERSION=7 PHPUNIT_ARGS=--group=pm' + - php: 5.6 + env: 'UNISH_DRUPAL_MAJOR_VERSION=7 PHPUNIT_ARGS=--group=quick-drupal' + - php: 5.6 + env: 'UNISH_DRUPAL_MAJOR_VERSION=7 PHPUNIT_ARGS=--group=make' + - php: 5.6 + env: 'UNISH_DRUPAL_MAJOR_VERSION=7 PHPUNIT_ARGS=--exclude-group=base,make,commands,pm,quick-drupal TEST_CHILDREN="drush-ops/config-extra"' + + # D6 + # Note that Drupal 6 does not work with PHP 7 - php: 5.4 - env: UNISH_DRUPAL_MAJOR_VERSION=8 UNISH_DRUPAL_MINOR_VERSION=3.7 PHPUNIT_ARGS=--group=make + env: 'UNISH_DRUPAL_MAJOR_VERSION=7 PHPUNIT_ARGS=--group=base' - php: 5.4 - env: UNISH_DRUPAL_MAJOR_VERSION=8 UNISH_DRUPAL_MINOR_VERSION=3.7 PHPUNIT_ARGS=--group=base + env: 'UNISH_DRUPAL_MAJOR_VERSION=7 PHPUNIT_ARGS=--group=commands' - php: 5.4 - env: UNISH_DRUPAL_MAJOR_VERSION=8 UNISH_DRUPAL_MINOR_VERSION=3.7 PHPUNIT_ARGS=--group=commands + env: 'UNISH_DRUPAL_MAJOR_VERSION=7 PHPUNIT_ARGS=--group=pm' - php: 5.4 - env: UNISH_DRUPAL_MAJOR_VERSION=8 UNISH_DRUPAL_MINOR_VERSION=3.7 PHPUNIT_ARGS=--group=pm - - php: 5.4 - env: UNISH_DRUPAL_MAJOR_VERSION=8 UNISH_DRUPAL_MINOR_VERSION=3.7 PHPUNIT_ARGS=--group=quick-drupal - - php: 5.4 - env: UNISH_DRUPAL_MAJOR_VERSION=8 UNISH_DRUPAL_MINOR_VERSION=3.7 PHPUNIT_ARGS=--exclude-group=base,make,commands,pm,quick-drupal TEST_CHILDREN="drush-ops/config-extra" - - php: 5.4 - env: UNISH_DRUPAL_MAJOR_VERSION=8 PHPUNIT_ARGS=--group=make - - php: 5.4 - env: UNISH_DRUPAL_MAJOR_VERSION=8 PHPUNIT_ARGS=--group=base - - php: 5.4 - env: UNISH_DRUPAL_MAJOR_VERSION=8 PHPUNIT_ARGS=--group=commands - - php: 5.4 - env: UNISH_DRUPAL_MAJOR_VERSION=8 PHPUNIT_ARGS=--group=pm - - php: 5.4 - env: UNISH_DRUPAL_MAJOR_VERSION=8 PHPUNIT_ARGS=--group=quick-drupal - - php: 5.4 - env: UNISH_DRUPAL_MAJOR_VERSION=8 PHPUNIT_ARGS=--exclude-group=base,make,commands,pm,quick-drupal + env: 'UNISH_DRUPAL_MAJOR_VERSION=7 PHPUNIT_ARGS=--exclude-group=base,make,commands,pm,quick-drupal TEST_CHILDREN="drush-ops/config-extra"' before_install: - echo 'mbstring.http_input = pass' >> ~/.phpenv/versions/$(phpenv version-name)/etc/conf.d/travis.ini diff -r e200cb7efeb3 -r c2387f117808 vendor/drush/drush/commands/core/drupal/batch.inc --- a/vendor/drush/drush/commands/core/drupal/batch.inc Thu Apr 26 11:26:54 2018 +0100 +++ b/vendor/drush/drush/commands/core/drupal/batch.inc Tue Jul 10 15:07:59 2018 +0100 @@ -243,7 +243,7 @@ $operations = $queue->getAllItems(); $elapsed = $batch_set['elapsed'] / 1000; $elapsed = drush_drupal_major_version() >=8 ? \Drupal::service('date.formatter')->formatInterval($elapsed) : format_interval($elapsed); - $batch_set['finished']($batch_set['success'], $batch_set['results'], $operations, $elapsed); + call_user_func_array($batch_set['finished'], [$batch_set['success'], $batch_set['results'], $operations, $elapsed]); } } } diff -r e200cb7efeb3 -r c2387f117808 vendor/drush/drush/commands/make/make.drush.inc --- a/vendor/drush/drush/commands/make/make.drush.inc Thu Apr 26 11:26:54 2018 +0100 +++ b/vendor/drush/drush/commands/make/make.drush.inc Tue Jul 10 15:07:59 2018 +0100 @@ -567,21 +567,89 @@ $core_major_version = substr($info['core'], 0, 1); $core_project_name = $core_major_version == 7 ? 'drupal/drupal' : 'drupal/core'; - // Add default projects. - $projects = array( - 'composer/installers' => '^1.0.20', - 'cweagans/composer-patches' => '~1.0', - $core_project_name => str_replace('x', '*', $info['core']), - ); + if ($core_major_version == 7) { + // Add PHP version and extension requirements. + $php_reqs = array( + 'php' => '>= 5.2.5', + 'ext-curl' => '*', + 'ext-gd' => '*', + 'ext-json' => '*', + 'ext-openssl' => '*', + 'ext-pdo' => '*', + 'ext-pdo_mysql' => '*', + 'ext-xml' => '*', + ); - $patches = array(); + // Add default projects. + $projects = array( + 'composer/installers' => '^1.2', + 'cweagans/composer-patches' => '^1.6', + 'drupal-composer/preserve-paths' => '^0.1', + 'drush/drush' => '~8.0', + $core_project_name => str_replace('x', '*', $info['core']), + ); + + $conflict = array( + 'drupal/core' => '8.*', + ); + + $extra = array( + 'installer-paths' => array( + 'web' => array('type:drupal-core'), + 'web/profiles/{$name}' => array('type:drupal-profile'), + 'web/sites/all/drush/{$name}' => array('type:drupal-drush'), + 'web/sites/all/libraries/{$name}' => array('type:drupal-library'), + 'web/sites/all/modules/contrib/{$name}' => array('type:drupal-module'), + 'web/sites/all/themes/contrib/{$name}' => array('type:drupal-theme'), + ), + 'patches' => array(), + 'preserve-paths' => array( + 'web/sites/all/drush', + 'web/sites/all/libraries', + 'web/sites/all/modules/contrib', + 'web/sites/all/modules/custom', + 'web/sites/all/modules/features', + 'web/sites/all/themes/contrib', + 'web/sites/all/themes/custom', + 'web/sites/all/translations', + 'web/sites/default' + ), + ); + } + else { + $php_reqs = array(); + + // Add default projects. + $projects = array( + 'composer/installers' => '^1.2', + 'cweagans/composer-patches' => '^1.6', + 'drush/drush' => '^9.0.0', + $core_project_name => str_replace('x', '*', $info['core']), + ); + + $conflict = array( + 'drupal/drupal' => '*', + ); + + $extra = array( + 'installer-paths' => array( + 'web/core' => array('type:drupal-core'), + 'web/libraries/{$name}' => array('type:drupal-library'), + 'web/modules/contrib/{$name}' => array('type:drupal-module'), + 'web/profiles/contrib/{$name}' => array('type:drupal-profile'), + 'web/themes/contrib/{$name}' => array('type:drupal-theme'), + 'drush/contrib/{$name}' => array('type:drupal-drush'), + ), + 'patches' => array(), + ); + } // Iterate over projects, populating composer-friendly array. foreach ($info['projects'] as $project_name => $project) { switch ($project['type']) { case 'core': - $project['name'] = 'drupal/core'; - $projects[$project['name']] = str_replace('x', '*', $project['version']); + $project['name'] = $core_project_name; + $projects[$project['name']] = '^' . str_replace('x', '*', $project['version']); break; default: @@ -594,7 +662,7 @@ if (!empty($project['patch'])) { foreach($project['patch'] as $key => $patch) { $patch_description = "Enter {$project['name']} patch #$key description here"; - $patches[$project['name']][$patch_description] = $patch; + $extra['patches'][$project['name']][$patch_description] = $patch; } } } @@ -607,26 +675,25 @@ } } + // Sort the projects to simplify pull requests on composer.json due to the + // sort-packages configuration. + ksort($projects); + $output = array( 'name' => 'Enter project name here', 'description' => 'Enter project description here', 'type' => 'project', 'repositories' => array( - array('type' => 'composer', 'url' => 'https://packagist.drupal-composer.org'), + array('type' => 'composer', 'url' => 'https://packages.drupal.org/' . $core_major_version), ), - 'require' => $projects, + 'require' => array_merge($php_reqs, $projects), + 'conflict'=> $conflict, 'minimum-stability' => 'dev', 'prefer-stable' => TRUE, - 'extra' => array( - 'installer-paths' => array( - 'core' => array('type:drupal-core'), - 'docroot/modules/contrib/{$name}' => array('type:drupal-module'), - 'docroot/profiles/contrib/{$name}' => array('type:drupal-profile'), - 'docroot/themes/contrib/{$name}' => array('type:drupal-theme'), - 'drush/contrib/{$name}' => array('type:drupal-drush'), - ), - 'patches' => $patches, + 'config' => array( + 'sort-packages' => TRUE, ), + 'extra' => $extra, ); $output = json_encode($output, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES); @@ -650,19 +717,17 @@ function drush_make_convert_project_to_composer($original_project, $core_major_version) { // Typical specified version with major version "x" removed. if (!empty($original_project['version'])) { - $version = str_replace('x', '0', $original_project['version']); + $version = drush_make_convert_version_to_composer($original_project['version']); } // Git branch or revision. elseif (!empty($original_project['download'])) { switch ($original_project['download']['type']) { case 'git': if (!empty($original_project['download']['branch'])) { - // @todo Determine if '0' will always be correct. - $version = str_replace('x', '0', $original_project['download']['branch']); + $version = drush_make_convert_version_to_composer($original_project['download']['branch']); } if (!empty($original_project['download']['tag'])) { - // @todo Determine if '0' will always be correct. - $version = str_replace('x', '0', $original_project['download']['tag']); + $version = drush_make_convert_version_to_composer($original_project['download']['tag']); } if (!empty($project['download']['revision'])) { $version .= '#' . $original_project['download']['revision']; @@ -675,9 +740,32 @@ } } - $version = "$core_major_version." . $version; + return $version; +} - return $version; +/** + * Converts a drush version into a composer version. + * + * @param string $version + * Original drush version. + * + * @return string + * The converted composer version. + */ +function drush_make_convert_version_to_composer($version) { + $cver = '*'; + if (!empty($version)) { + if (substr($version, -3) === 'dev') { + // Dev versions maintain the 7.x-dev syntax. + $cver = $version; + } + else { + // Replace '1.x' with '^1.*'. + $cver = '^' . str_replace('x', '*', $version); + } + } + + return $cver; } /** @@ -934,7 +1022,7 @@ $backend_options['integrate'] = TRUE; } $results = drush_backend_invoke_concurrent($invocations, $common_options, $backend_options, 'make-process', '@none'); - if (count($results['error_log'])) { + if (!empty($results['error_log'])) { return FALSE; } } diff -r e200cb7efeb3 -r c2387f117808 vendor/drush/drush/docs/install-alternative.md --- a/vendor/drush/drush/docs/install-alternative.md Thu Apr 26 11:26:54 2018 +0100 +++ b/vendor/drush/drush/docs/install-alternative.md Tue Jul 10 15:07:59 2018 +0100 @@ -1,28 +1,32 @@ Install a global Drush via Composer ------------------ -Follow the instructions below, or [watch a video by Drupalize.me](https://youtu.be/eAtDaD8xz0Q). +Follow the instructions below: 1. [Install Composer globally](https://getcomposer.org/doc/00-intro.md#globally). +1. Install the [cgr tool](https://github.com/consolidation/cgr) following the [instructions in that project](https://github.com/consolidation/cgr#installation-and-usage). 1. Add composer's `bin` directory to the system path by placing `export PATH="$HOME/.composer/vendor/bin:$PATH"` into your ~/.bash_profile (Mac OS users) or into your ~/.bashrc (Linux users). -1. Install latest stable Drush: `composer global require drush/drush`. +1. Install latest stable Drush: `cgr drush/drush`. 1. Verify that Drush works: `drush status` +Please do not install Drush using `composer global require`. See [Fixing the Composer Global command](https://pantheon.io/blog/fixing-composer-global-command) for more information. + #### Notes -* Update to latest release (per your specification in ~/.composer/composer.json): `composer global update` +* Update to latest release (per your specification in ~/.composer/composer.json): `cgr update drush/drush` * Install a specific version of Drush: # Install a specific version of Drush, e.g. Drush 7.1.0 - composer global require drush/drush:7.1.0 + cgr update drush/drush:7.1.0 # Install 8.x branch as a git clone. Great for contributing back to Drush project. - composer global require drush/drush:8.x-dev --prefer-source + cgr drush/drush:8.x-dev --prefer-source + * Alternate way to install for all users via Composer: - COMPOSER_HOME=/opt/drush COMPOSER_BIN_DIR=/usr/local/bin COMPOSER_VENDOR_DIR=/opt/drush/7 composer require drush/drush:7 + COMPOSER_HOME=/opt/drush COMPOSER_BIN_DIR=/usr/local/bin COMPOSER_VENDOR_DIR=/opt/drush/8 composer require drush/drush:^8 * [Documentation for composer's require command.](http://getcomposer.org/doc/03-cli.md#require) -* Uninstall with : `composer global remove drush/drush` +* Uninstall with : `cgr remove drush/drush` Windows ------------ diff -r e200cb7efeb3 -r c2387f117808 vendor/drush/drush/docs/install.md --- a/vendor/drush/drush/docs/install.md Thu Apr 26 11:26:54 2018 +0100 +++ b/vendor/drush/drush/docs/install.md Tue Jul 10 15:07:59 2018 +0100 @@ -31,26 +31,6 @@ Drupal Compatibility ----------------- -!!! note - - Drush 9 only supports one install method. It requires that your Drupal 8 site be built with Composer and Drush be listed as a dependency. - - See the [Drush 8 docs](http://docs.drush.org/en/8.x) for installing prior versions of Drush. - -Install a site-local Drush and Drush Launcher. ------------------ -1. It is recommended that Drupal 8 sites be [built using Composer, with Drush listed as a dependency](https://github.com/drupal-composer/drupal-project). That project already includes Drush in its composer.json. If your Composer project doesn't yet depend on Drush, run `composer require drush/drush` to add it. -1. To be able to call `drush` from anywhere, install the [Drush Launcher](https://github.com/drush-ops/drush-launcher). That is a small program which listens on your $PATH and hands control to a site-local Drush that is in the /vendor directory of your Composer project. If you skip this step, run Drush from Drupal root via `../vendor/bin/drush`. In that case Drush's bash integration and custom prompt won't work. -1. Run `drush init`. This edits ~/.bashrc so that Drush's custom prompt and bash integration are active. -1. See [Usage](http://docs.drush.org/en/master/usage/) for details on using Drush. -1. To use a non-default PHP, [edit ~/.bashrc so that the desired PHP is in front of your $PATH](http://stackoverflow.com/questions/4145667/how-to-override-the-path-of-php-to-use-the-mamp-path/10653443#10653443). If that is not desirable, you can change your PATH for just one request: `PATH=/path/to/php:$PATH` drush status ...` - -!!! note - - Drush 9 cannot run commandfiles from Drush 8 and below (e.g. example.drush.inc). See our [guide on porting commandfiles](https://weitzman.github.io/blog/port-to-drush9). Also note that alias and config files use a new .yml format in Drush 9. - -Drupal Compatibility ------------------ diff -r e200cb7efeb3 -r c2387f117808 vendor/drush/drush/drush.info --- a/vendor/drush/drush/drush.info Thu Apr 26 11:26:54 2018 +0100 +++ b/vendor/drush/drush/drush.info Tue Jul 10 15:07:59 2018 +0100 @@ -1,1 +1,1 @@ -drush_version=8.1.16 +drush_version=8.1.17 diff -r e200cb7efeb3 -r c2387f117808 vendor/drush/drush/includes/drush.inc --- a/vendor/drush/drush/includes/drush.inc Thu Apr 26 11:26:54 2018 +0100 +++ b/vendor/drush/drush/includes/drush.inc Tue Jul 10 15:07:59 2018 +0100 @@ -1665,16 +1665,17 @@ function drush_memory_limit() { $value = trim(ini_get('memory_limit')); $last = strtolower($value[strlen($value)-1]); + $size = (int) substr($value, 0, -1); switch ($last) { case 'g': - $value *= DRUSH_KILOBYTE; + $size *= DRUSH_KILOBYTE; case 'm': - $value *= DRUSH_KILOBYTE; + $size *= DRUSH_KILOBYTE; case 'k': - $value *= DRUSH_KILOBYTE; + $size *= DRUSH_KILOBYTE; } - return $value; + return $size; } /** diff -r e200cb7efeb3 -r c2387f117808 vendor/drush/drush/includes/preflight.inc --- a/vendor/drush/drush/includes/preflight.inc Thu Apr 26 11:26:54 2018 +0100 +++ b/vendor/drush/drush/includes/preflight.inc Tue Jul 10 15:07:59 2018 +0100 @@ -438,7 +438,7 @@ * On Windows in CMD and PowerShell is this exported using mode con. */ function _drush_preflight_columns() { - if (!($columns = getenv('COLUMNS'))) { + if (!($columns = getenv('COLUMNS') ?: 0)) { // Trying to export the columns using stty. exec('stty size 2>&1', $columns_output, $columns_status); if (!$columns_status) $columns = preg_replace('/\d+\s(\d+)/', '$1', $columns_output[0], -1, $columns_count); @@ -611,8 +611,15 @@ $local_drush = find_wrapper_or_launcher($root); } $is_local = drush_get_option('local'); + $must_use_site_local = !empty($root) && !empty($local_drush) && empty($is_local); + // If the command sets the 'handle-remote-commands' flag, then we will short-circuit + // remote command dispatching and site-list command dispatching, and always let + // the command handler run on the local machine. + if (is_array($command) && !empty($command['handle-remote-commands']) && !$must_use_site_local) { + return FALSE; + } $values = NULL; - if (!empty($root) && !empty($local_drush) && empty($is_local)) { + if (!isset($remote_host) && !isset($site_list) && $must_use_site_local) { if (!drush_is_absolute_path($local_drush)) { $local_drush = $root . DIRECTORY_SEPARATOR . $local_drush; } @@ -639,12 +646,6 @@ $values = drush_do_command_redispatch(is_array($command) ? $command : $command_name, $args, NULL, NULL, $local_drush, TRUE, $aditional_options); } } - // If the command sets the 'handle-remote-commands' flag, then we will short-circuit - // remote command dispatching and site-list command dispatching, and always let - // the command handler run on the local machine. - if (is_array($command) && !empty($command['handle-remote-commands'])) { - return FALSE; - } if (isset($remote_host)) { $remote_user = drush_get_option('remote-user'); diff -r e200cb7efeb3 -r c2387f117808 vendor/drush/drush/includes/startup.inc --- a/vendor/drush/drush/includes/startup.inc Thu Apr 26 11:26:54 2018 +0100 +++ b/vendor/drush/drush/includes/startup.inc Tue Jul 10 15:07:59 2018 +0100 @@ -414,6 +414,9 @@ // Get the current environment for pnctl_exec. $env = drush_env(); + // Make sure Drush can locates original working directory. https://github.com/drush-ops/drush/issues/2285 + chdir($cwd); + // Launch the new script in the same process. // If the launch succeeds, then it will not return. $error = pcntl_exec($found_script, $arguments, $env); diff -r e200cb7efeb3 -r c2387f117808 vendor/drush/drush/lib/Drush/Queue/Queue8.php --- a/vendor/drush/drush/lib/Drush/Queue/Queue8.php Thu Apr 26 11:26:54 2018 +0100 +++ b/vendor/drush/drush/lib/Drush/Queue/Queue8.php Tue Jul 10 15:07:59 2018 +0100 @@ -65,9 +65,10 @@ } catch (SuspendQueueException $e) { // If the worker indicates there is a problem with the whole queue, - // release the item and skip to the next queue. + // release the item and stop further processing. $queue->releaseItem($item); drush_set_error('DRUSH_SUSPEND_QUEUE_EXCEPTION', $e->getMessage()); + break; } catch (\Exception $e) { // In case of any other kind of exception, log it and leave the item diff -r e200cb7efeb3 -r c2387f117808 vendor/drush/drush/tests/makeConvertTest.php --- a/vendor/drush/drush/tests/makeConvertTest.php Thu Apr 26 11:26:54 2018 +0100 +++ b/vendor/drush/drush/tests/makeConvertTest.php Tue Jul 10 15:07:59 2018 +0100 @@ -60,7 +60,7 @@ array('format' => 'composer'), array( '"drupal/drupal": "7.*",', - '"drupal/features": "7.1.0-beta4",', + '"drupal/features": "^1.0-beta4",', '"patches": {', '"drupal/features": {', '"Enter drupal/features patch #0 description here": "http://drupal.org/files/issues/features-drush-backend-invoke-25.patch"', @@ -71,7 +71,7 @@ array('format' => 'composer'), array( '"drupal/drupal": "7.*",', - '"drupal/features": "7.1.0-beta4",', + '"drupal/features": "^1.0-beta4",', '"patches": {', '"drupal/features": {', '"Enter drupal/features patch #0 description here": "http://drupal.org/files/issues/features-drush-backend-invoke-25.patch"', diff -r e200cb7efeb3 -r c2387f117808 vendor/drush/drush/tests/pmReleaseNotesTest.php --- a/vendor/drush/drush/tests/pmReleaseNotesTest.php Thu Apr 26 11:26:54 2018 +0100 +++ b/vendor/drush/drush/tests/pmReleaseNotesTest.php Tue Jul 10 15:07:59 2018 +0100 @@ -14,7 +14,6 @@ $this->drush('pm-releasenotes', array('drupal-7.1')); $output = $this->getOutput(); $this->assertContains("RELEASE NOTES FOR 'DRUPAL' PROJECT, VERSION 7.1", $output); - $this->assertContains('Last updated: 25 May 2011 at 20:59 UTC.', $output); $this->assertContains('SA-CORE-2011-001 - Drupal core - Multiple vulnerabilities', $output); } } diff -r e200cb7efeb3 -r c2387f117808 vendor/drush/drush/tests/resources/queue_script-D7.php --- a/vendor/drush/drush/tests/resources/queue_script-D7.php Thu Apr 26 11:26:54 2018 +0100 +++ b/vendor/drush/drush/tests/resources/queue_script-D7.php Tue Jul 10 15:07:59 2018 +0100 @@ -3,7 +3,7 @@ // Create a new feed. aggregator_save_feed(array( 'title' => 'test', - 'url' => 'http://drupal.org/project/issues/rss/drupal?categories=All', + 'url' => 'https://www.drupal.org/project/issues/rss/goofy?categories=All', 'refresh' => 3600, 'block' => 5, )); diff -r e200cb7efeb3 -r c2387f117808 vendor/fabpot/goutte/Goutte/Client.php --- a/vendor/fabpot/goutte/Goutte/Client.php Thu Apr 26 11:26:54 2018 +0100 +++ b/vendor/fabpot/goutte/Goutte/Client.php Tue Jul 10 15:07:59 2018 +0100 @@ -16,6 +16,7 @@ use GuzzleHttp\Cookie\CookieJar; use GuzzleHttp\Exception\RequestException; use Psr\Http\Message\ResponseInterface; +use Psr\Http\Message\UriInterface; use Symfony\Component\BrowserKit\Client as BaseClient; use Symfony\Component\BrowserKit\Request; use Symfony\Component\BrowserKit\Response; @@ -26,18 +27,42 @@ * @author Fabien Potencier * @author Michael Dowling * @author Charles Sarrazin + * @author Kévin Dunglas */ class Client extends BaseClient { protected $client; private $headers = array(); - private $auth = null; + private $auth; public function setClient(GuzzleClientInterface $client) { $this->client = $client; + /** + * @var $baseUri UriInterface + */ + if (null !== $this->getServerParameter('HTTP_HOST', null) || null === $baseUri = $client->getConfig('base_uri')) { + return $this; + } + + $path = $baseUri->getPath(); + if ('' !== $path && '/' !== $path) { + throw new \InvalidArgumentException('Setting a path in the Guzzle "base_uri" config option is not supported by Goutte yet.'); + } + + if (null === $this->getServerParameter('HTTPS', null) && 'https' === $baseUri->getScheme()) { + $this->setServerParameter('HTTPS', 'on'); + } + + $host = $baseUri->getHost(); + if (null !== $port = $baseUri->getPort()) { + $host .= ":$port"; + } + + $this->setServerParameter('HTTP_HOST', $host); + return $this; } diff -r e200cb7efeb3 -r c2387f117808 vendor/nikic/php-parser/CHANGELOG.md --- a/vendor/nikic/php-parser/CHANGELOG.md Thu Apr 26 11:26:54 2018 +0100 +++ b/vendor/nikic/php-parser/CHANGELOG.md Tue Jul 10 15:07:59 2018 +0100 @@ -1,8 +1,18 @@ -Version 4.0.2-dev +Version 4.0.3-dev ----------------- Nothing yet. +Version 4.0.2 (2018-06-03) +-------------------------- + +### Added + +* Improved error recovery inside classes. +* Support error recovery for `foreach` without `as`. +* Support error recovery for parameters without variable (`function (Type ) {}`). +* Support error recovery for functions without body (`function ($foo)`). + Version 4.0.1 (2018-03-25) -------------------------- diff -r e200cb7efeb3 -r c2387f117808 vendor/nikic/php-parser/README.md --- a/vendor/nikic/php-parser/README.md Thu Apr 26 11:26:54 2018 +0100 +++ b/vendor/nikic/php-parser/README.md Tue Jul 10 15:07:59 2018 +0100 @@ -200,7 +200,7 @@ * Converting AST back to PHP code * Customizing formatting * Formatting-preserving code transformations - * [AST builders](component/AST_builders.markdown) + * [AST builders](doc/component/AST_builders.markdown) * Fluent builders for AST nodes * [Lexer](doc/component/Lexer.markdown) * Lexer options @@ -209,16 +209,16 @@ * [Error handling](doc/component/Error_handling.markdown) * Column information for errors * Error recovery (parsing of syntactically incorrect code) - * [Constant expression evaluation](component/Constant_expression_evaluation.markdown) + * [Constant expression evaluation](doc/component/Constant_expression_evaluation.markdown) * Evaluating constant/property/etc initializers * Handling errors and unsupported expressions - * [JSON representation](component/JSON_representation.markdown) + * [JSON representation](doc/component/JSON_representation.markdown) * JSON encoding and decoding of ASTs * [Performance](doc/component/Performance.markdown) * Disabling XDebug * Reusing objects * Garbage collection impact - * [Frequently asked questions](component/FAQ.markdown) + * [Frequently asked questions](doc/component/FAQ.markdown) * Parent and sibling references [doc_3_x]: https://github.com/nikic/PHP-Parser/tree/3.x/doc diff -r e200cb7efeb3 -r c2387f117808 vendor/nikic/php-parser/UPGRADE-4.0.md --- a/vendor/nikic/php-parser/UPGRADE-4.0.md Thu Apr 26 11:26:54 2018 +0100 +++ b/vendor/nikic/php-parser/UPGRADE-4.0.md Tue Jul 10 15:07:59 2018 +0100 @@ -17,7 +17,7 @@ comparisons or strict-mode may require adjustment. The following is an exhaustive list of all affected subnodes: - * `Const::$name` + * `Const_::$name` * `NullableType::$type` (for simple types) * `Param::$type` (for simple types) * `Expr\ClassConstFetch::$name` @@ -29,8 +29,8 @@ * `Stmt\Class_::$name` * `Stmt\ClassMethod::$name` * `Stmt\ClassMethod::$returnType` (for simple types) - * `Stmt\Function::$name` - * `Stmt\Function::$returnType` (for simple types) + * `Stmt\Function_::$name` + * `Stmt\Function_::$returnType` (for simple types) * `Stmt\Goto_::$name` * `Stmt\Interface_::$name` * `Stmt\Label::$name` @@ -48,7 +48,7 @@ * The `name` subnode of `StaticVar` has been renamed to `var` and now contains a `Variable` rather than a plain string. * The `var` subnode of `ClosureUse` now contains a `Variable` rather than a plain string. -* The `var` subnode of `Catch` now contains a `Variable` rather than a plain string. +* The `var` subnode of `Catch_` now contains a `Variable` rather than a plain string. * The `alias` subnode of `UseUse` is now `null` if no explicit alias is given. As such, `use Foo\Bar` and `use Foo\Bar as Bar` are now represented differently. The `getAlias()` method can be used to get the effective alias, even if it is not explicitly given. @@ -62,7 +62,7 @@ ### Removed functionality -* Removed `type` subnode on `Class`, `ClassMethod` and `Property` nodes. Use `flags` instead. +* Removed `type` subnode on `Class_`, `ClassMethod` and `Property` nodes. Use `flags` instead. * The `ClassConst::isStatic()` method has been removed. Constants cannot have a static modifier. * The `NodeTraverser` no longer accepts `false` as a return value from a `leaveNode()` method. `NodeTraverser::REMOVE_NODE` should be returned instead. @@ -74,4 +74,4 @@ `Unserializer\XML`, as well as the interfaces `Serializer` and `Unserializer` no longer exist. * The `BuilderAbstract` class has been removed. It's functionality is moved into `BuilderHelpers`. However, this is an internal class and should not be used directly. -* The `Autoloader` class has been removed in favor of relying on the Composer autoloader. \ No newline at end of file +* The `Autoloader` class has been removed in favor of relying on the Composer autoloader. diff -r e200cb7efeb3 -r c2387f117808 vendor/nikic/php-parser/doc/2_Usage_of_basic_components.markdown --- a/vendor/nikic/php-parser/doc/2_Usage_of_basic_components.markdown Thu Apr 26 11:26:54 2018 +0100 +++ b/vendor/nikic/php-parser/doc/2_Usage_of_basic_components.markdown Tue Jul 10 15:07:59 2018 +0100 @@ -409,7 +409,7 @@ foreach ($files as $file) { try { // read the file that should be converted - $code = file_get_contents($file); + $code = file_get_contents($file->getPathName()); // parse $stmts = $parser->parse($code); diff -r e200cb7efeb3 -r c2387f117808 vendor/nikic/php-parser/grammar/php7.y --- a/vendor/nikic/php-parser/grammar/php7.y Thu Apr 26 11:26:54 2018 +0100 +++ b/vendor/nikic/php-parser/grammar/php7.y Tue Jul 10 15:07:59 2018 +0100 @@ -240,6 +240,8 @@ { $$ = Stmt\Foreach_[$3, $5[0], ['keyVar' => null, 'byRef' => $5[1], 'stmts' => $7]]; } | T_FOREACH '(' expr T_AS variable T_DOUBLE_ARROW foreach_variable ')' foreach_statement { $$ = Stmt\Foreach_[$3, $7[0], ['keyVar' => $5, 'byRef' => $7[1], 'stmts' => $9]]; } + | T_FOREACH '(' expr error ')' foreach_statement + { $$ = Stmt\Foreach_[$3, new Expr\Error(stackAttributes(#4)), ['stmts' => $6]]; } | T_DECLARE '(' declare_list ')' declare_statement { $$ = Stmt\Declare_[$3, $5]; } | T_TRY '{' inner_statement_list '}' catches optional_finally { $$ = Stmt\TryCatch[$3, $5, $6]; $this->checkTryCatch($$); } @@ -295,9 +297,14 @@ | T_ELLIPSIS { $$ = true; } ; +block_or_error: + '{' inner_statement_list '}' { $$ = $2; } + | error { $$ = []; } +; + function_declaration_statement: - T_FUNCTION optional_ref identifier '(' parameter_list ')' optional_return_type '{' inner_statement_list '}' - { $$ = Stmt\Function_[$3, ['byRef' => $2, 'params' => $5, 'returnType' => $7, 'stmts' => $9]]; } + T_FUNCTION optional_ref identifier '(' parameter_list ')' optional_return_type block_or_error + { $$ = Stmt\Function_[$3, ['byRef' => $2, 'params' => $5, 'returnType' => $7, 'stmts' => $8]]; } ; class_declaration_statement: @@ -447,6 +454,8 @@ { $$ = Node\Param[$4, null, $1, $2, $3]; $this->checkParam($$); } | optional_param_type optional_ref optional_ellipsis plain_variable '=' expr { $$ = Node\Param[$4, $6, $1, $2, $3]; $this->checkParam($$); } + | optional_param_type optional_ref optional_ellipsis error + { $$ = Node\Param[Expr\Error[], null, $1, $2, $3]; } ; type_expr: @@ -514,7 +523,7 @@ ; class_statement_list: - class_statement_list class_statement { push($1, $2); } + class_statement_list class_statement { if ($2 !== null) { push($1, $2); } } | /* empty */ { init(); } ; @@ -527,6 +536,7 @@ { $$ = Stmt\ClassMethod[$4, ['type' => $1, 'byRef' => $3, 'params' => $6, 'returnType' => $8, 'stmts' => $9]]; $this->checkClassMethod($$, #1); } | T_USE class_name_list trait_adaptations { $$ = Stmt\TraitUse[$2, $3]; } + | error { $$ = null; /* will be skipped */ } ; trait_adaptations: @@ -562,7 +572,7 @@ method_body: ';' /* abstract method */ { $$ = null; } - | '{' inner_statement_list '}' { $$ = $2; } + | block_or_error { $$ = $1; } ; variable_modifiers: @@ -708,11 +718,11 @@ | T_YIELD expr T_DOUBLE_ARROW expr { $$ = Expr\Yield_[$4, $2]; } | T_YIELD_FROM expr { $$ = Expr\YieldFrom[$2]; } | T_FUNCTION optional_ref '(' parameter_list ')' lexical_vars optional_return_type - '{' inner_statement_list '}' - { $$ = Expr\Closure[['static' => false, 'byRef' => $2, 'params' => $4, 'uses' => $6, 'returnType' => $7, 'stmts' => $9]]; } + block_or_error + { $$ = Expr\Closure[['static' => false, 'byRef' => $2, 'params' => $4, 'uses' => $6, 'returnType' => $7, 'stmts' => $8]]; } | T_STATIC T_FUNCTION optional_ref '(' parameter_list ')' lexical_vars optional_return_type - '{' inner_statement_list '}' - { $$ = Expr\Closure[['static' => true, 'byRef' => $3, 'params' => $5, 'uses' => $7, 'returnType' => $8, 'stmts' => $10]]; } + block_or_error + { $$ = Expr\Closure[['static' => true, 'byRef' => $3, 'params' => $5, 'uses' => $7, 'returnType' => $8, 'stmts' => $9]]; } ; anonymous_class: diff -r e200cb7efeb3 -r c2387f117808 vendor/nikic/php-parser/lib/PhpParser/BuilderFactory.php --- a/vendor/nikic/php-parser/lib/PhpParser/BuilderFactory.php Thu Apr 26 11:26:54 2018 +0100 +++ b/vendor/nikic/php-parser/lib/PhpParser/BuilderFactory.php Tue Jul 10 15:07:59 2018 +0100 @@ -104,7 +104,7 @@ /** * Creates a namespace/class use builder. * - * @param string|Node\Name Name to alias + * @param string|Node\Name $name Name to alias * * @return Builder\Use_ The create use builder */ diff -r e200cb7efeb3 -r c2387f117808 vendor/nikic/php-parser/lib/PhpParser/Error.php --- a/vendor/nikic/php-parser/lib/PhpParser/Error.php Thu Apr 26 11:26:54 2018 +0100 +++ b/vendor/nikic/php-parser/lib/PhpParser/Error.php Tue Jul 10 15:07:59 2018 +0100 @@ -15,7 +15,7 @@ * (or start line of error -- deprecated) */ public function __construct(string $message, $attributes = []) { - $this->rawMessage = (string) $message; + $this->rawMessage = $message; if (is_array($attributes)) { $this->attributes = $attributes; } else { @@ -76,7 +76,7 @@ * @param string $message Error message */ public function setRawMessage(string $message) { - $this->rawMessage = (string) $message; + $this->rawMessage = $message; $this->updateMessage(); } @@ -86,7 +86,7 @@ * @param int $line Error start line */ public function setStartLine(int $line) { - $this->attributes['startLine'] = (int) $line; + $this->attributes['startLine'] = $line; $this->updateMessage(); } diff -r e200cb7efeb3 -r c2387f117808 vendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp.php --- a/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp.php Thu Apr 26 11:26:54 2018 +0100 +++ b/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp.php Tue Jul 10 15:07:59 2018 +0100 @@ -12,7 +12,7 @@ public $right; /** - * Constructs a bitwise and node. + * Constructs a binary operator node. * * @param Expr $left The left hand side expression * @param Expr $right The right hand side expression diff -r e200cb7efeb3 -r c2387f117808 vendor/nikic/php-parser/lib/PhpParser/Node/Param.php --- a/vendor/nikic/php-parser/lib/PhpParser/Node/Param.php Thu Apr 26 11:26:54 2018 +0100 +++ b/vendor/nikic/php-parser/lib/PhpParser/Node/Param.php Tue Jul 10 15:07:59 2018 +0100 @@ -12,7 +12,7 @@ public $byRef; /** @var bool Whether this is a variadic argument */ public $variadic; - /** @var Expr\Variable Parameter variable */ + /** @var Expr\Variable|Expr\Error Parameter variable */ public $var; /** @var null|Expr Default value */ public $default; @@ -20,7 +20,7 @@ /** * Constructs a parameter node. * - * @param Expr\Variable $var Parameter variable + * @param Expr\Variable|Expr\Error $var Parameter variable * @param null|Expr $default Default value * @param null|string|Name|NullableType $type Typehint * @param bool $byRef Whether is passed by reference @@ -28,7 +28,7 @@ * @param array $attributes Additional attributes */ public function __construct( - Expr\Variable $var, Expr $default = null, $type = null, + $var, Expr $default = null, $type = null, bool $byRef = false, bool $variadic = false, array $attributes = [] ) { parent::__construct($attributes); diff -r e200cb7efeb3 -r c2387f117808 vendor/nikic/php-parser/lib/PhpParser/Parser/Php7.php --- a/vendor/nikic/php-parser/lib/PhpParser/Parser/Php7.php Thu Apr 26 11:26:54 2018 +0100 +++ b/vendor/nikic/php-parser/lib/PhpParser/Parser/Php7.php Tue Jul 10 15:07:59 2018 +0100 @@ -18,16 +18,16 @@ class Php7 extends \PhpParser\ParserAbstract { protected $tokenToSymbolMapSize = 392; - protected $actionTableSize = 946; - protected $gotoTableSize = 483; + protected $actionTableSize = 950; + protected $gotoTableSize = 488; protected $invalidSymbol = 157; protected $errorSymbol = 1; protected $defaultAction = -32766; protected $unexpectedTokenRule = 32767; - protected $YY2TBLSTATE = 333; - protected $numNonLeafStates = 584; + protected $YY2TBLSTATE = 338; + protected $numNonLeafStates = 580; protected $symbolToName = array( "EOF", @@ -233,262 +233,262 @@ ); protected $action = array( - 589, 590, 591, 592, 593, 217, 594, 595, 596, 632, - 633, 1047, 31, 101, 102, 103, 104, 105, 106, 107, - 108, 109, 110, 111, 112,-32766,-32766,-32766, 97, 98, - 99, 0, 243, 28, -285,-32766,-32766,-32766,-32766,-32766, - -32766, 666, 229, 116, 100,-32766, 118,-32766,-32766,-32766, - -32766,-32766, 597, 911, 913,-32766,-32766,-32766,-32766,-32766, - -32766,-32766,-32766, 267,-32766, 276, 598, 599, 600, 601, - 602, 603, 604,-32766, 252, 664, 878, 879, 880, 877, - 876, 875, 605, 606, 607, 608, 609, 610, 611, 612, - 613, 614, 615, 635, 636, 637, 638, 639, 627, 628, - 629, 630, 631, 616, 617, 618, 619, 620, 621, 622, - 658, 659, 660, 661, 662, 663, 623, 624, 625, 626, - 656, 647, 645, 646, 642, 643, 673, 634, 640, 641, - 648, 649, 651, 650, 652, 653, 44, 45, 403, 46, - 47, 644, 655, 654, -230, 48, 49, 1044, 50,-32767, - -32767,-32767,-32767, 92, 93, 94, 95, 96, 262, 73, - 121, 878, 879, 880, 877, 876, 875, 870, 668, 450, - -445, 353, 994, 23, -447, 994, 827, 828, 538, 800, - 223, 51, 52,-32766,-32766,-32766, 9, 53, 292, 54, - 221, 222, 55, 56, 57, 58, 59, 60, 61, 62, - -446, 24, 236, 63, 354,-32766,-32766,-32766, 668, 1011, - 1012, 405, 1062, 1044, -482, 689, 690, 1010,-32766,-32766, - -32766, 748, 668, 226, 269,-32766, 1024,-32766,-32766,-32766, - -32766, -445, 29, 130, 427, -447, 362, 359,-32766, 126, - -32766,-32766,-32766, 426, 539, -445, 291, 359, 244, -447, - 1044, 856, -445, 1044, 415, 416, -447, 426, -450, 343, - 252, -446, -176, 417, 418, 668, 1016, 1017, 1018, 1019, - 1013, 1014, 247, 672, -445, -446, -254, 427, 1020, 1015, - 359, 352, -446, 987, -449, 65, 987, 259, 666, 264, - 269, 404, -136, -136, -136, -4, 748, 348, 801, 252, - 426, 738, 24, 668, 36, 19, 406, -136, 407, -136, - 408, -136, 409, -136, 1044, 410, 227, 351, 1010, 37, - 38, 355, 356, 120, 39, 411, 385, 269, 64, 350, - 269, 290, 487, 412, 413, -445, -486, -495, 426, 414, - -32766,-32766, 724, 769, 357, 358, 347, 987, 370, -445, - 43, 557,-32766,-32766,-32766, 268, -445, 1006, 668, -482, - 124, 1094, 827, 828, 1095, 418, 404, 748, 750, 555, - -136, 227,-32766, 32,-32766,-32766, 738, 1063, 230, 36, - 19, 406, -494, 407, -235, 408, 67, 409, 524, 525, - 410, 269, 231, 426, 37, 38, 355, 356, 339, 39, - 411, 827, 828, 64, 258, -485, 290, -176, 412, 413, - 24, 251, 299, 668, 414, 41, 376, 681, 769, 357, - 358, -254, 1044, -91, 24, 294, 1010, -483, 122, -175, - 295, 671, 117, 833, 1085, 1044, 1044, 404, 278, 748, - 1010, 511, 20, 750, 555, -4, 386, 738, 426, 218, - 36, 19, 406, 128, 407, 987, 408, 119, 409, 129, - 316, 410, -215, -215, -215, 37, 38, 355, 356, 987, - 39, 411, 417, 418, 64, 132, 250, 290, 133, 412, - 413, -486, -495, 122, -495, 414, 417, 418, 724, 769, - 357, 358, 27, 224, 67, 689, 690, 115, 113, 269, - -32766,-32766,-32766, 225, 114, 123, 668, 473, 67, 404, - 396, 8, 269, 269, 750, 555, -215, 504, 505, 738, - -32766, 280, 36, 19, 406, 246, 407, -494, 408, -494, - 409, 827, 828, 410, -214, -214, -214, 37, 38, 355, - 356, 426, 39, 411, 566, 668, 64, -82, 748, 290, - -485, 412, 413, 94, 95, 96, 570, 414, 855, 581, - 724, 769, 357, 358, 867, 571, 747, 762, 243, 74, - 75, 76, -483, 100, -175, 127, 560, 228, 42, 533, - 426, 666, 671, 454,-32766, 459, 750, 555, -214, 30, - 668, 77, 78, 79, 80, 81, 82, 83, 84, 85, - 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, - 96, 97, 98, 99, 884, 243, 669, 748, 404, 668, - 1096, 512, 548, 516, 517, 216, 367, 100, 738, 534, - 374, 36, 19, 406, 503, 407, 263, 408, 10, 409, - -80, 528, 410, 770, 771, 567, 37, 38, 355, 748, - 261, 39, 411, 987, 426, 64, 1026, 764, 290, 767, - 35, 1023, 456, 0, 0, 327, 414, 0, 0, 266, - 0, -404, 0, 0, 260, 0, 0, 561, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 404, 0, 0, - 0, 12, 5, 293, 0, 750, 555, 738, 321, 332, - 36, 19, 406, 344, 407, 370, 408, 572, 409, 328, - 345, 410, 766, 579, 580, 37, 38, 355, 748, 404, - 39, 411, 729, 861, 64, 851, 803, 290, 787, 738, - 794, 852, 36, 19, 406, 414, 407, 727, 408, 795, - 409, 860, 863, 410, 862, 859, 562, 37, 38, 355, - 748, 784, 39, 411, 782, 34, 64, 338, 569, 290, - 568, 565, 564, 563, 750, 555, 558, 414, 274, 275, - 337, 574, 577, 576, 556, 0, 975, 792, 559, 793, - 768, 573, 868, 755, 974, 765, 973, 757, 404, 748, - 725, 1091, 1093, 684, 683, 693, 786, 555, 738, 694, - 691, 36, 19, 406, 1092, 407, 692, 408, 1060, 409, - 1090, 1045, 410, 1038, 1052, 1057, 37, 38, 355, 22, - 404, 39, 411, -474, -472, 64, -450, -449, 290, -448, - 738, 25, 26, 36, 19, 406, 414, 407, 33, 408, - 40, 409, 66, 68, 410, 342, 340, 277, 37, 38, - 355, 242, 241, 39, 411, 240, 239, 64, 220, 404, - 290, 219, 134, 131, 125, 750, 555, 72, 414, 738, - 71, 70, 36, 19, 406, 69, 407, -233, 408, 13, - 409, 17, 21, 410, 254, 951, 313, 37, 38, 355, - 483, 499, 39, 411, 547, 954, 64, 750, 555, 290, - -32766,-32766,-32766, 979, 834, 1008, 950, 414, -91, 998, - 544, 401, 394, 392, 387, 314, 18, 16, 15, 14, - -32766, -230,-32766,-32766,-32766,-32766,-32766,-32766,-32767,-32767, - -32767,-32767,-32767, -231, 510, 967, 750, 555, -416, 1025, - 1051, 1088, 0, 1036, 1037, 1007 + 585, 586, 587, 588, 589, 218, 590, 591, 592, 628, + 629, 492, 32, 102, 103, 104, 105, 106, 107, 108, + 109, 110, 111, 112, 113,-32766,-32766,-32766, 98, 99, + 100, 375, 244, 489, 556,-32766,-32766,-32766, 664, 855, + 1095, 662, 0, 1096, 101,-32766, 823,-32766,-32766,-32766, + -32766,-32766, 593, 912, 914,-32766, 29,-32766,-32766,-32766, + -32766,-32766,-32766, -491, 253, 669, 594, 595, 596, 597, + 598, 599, 600, 430, 253, 660, 879, 880, 881, 878, + 877, 876, 601, 602, 603, 604, 605, 606, 607, 608, + 609, 610, 611, 631, 632, 633, 634, 635, 623, 624, + 625, 626, 627, 612, 613, 614, 615, 616, 617, 618, + 654, 655, 656, 657, 658, 659, 619, 620, 621, 622, + 652, 643, 641, 642, 638, 639, 217, 630, 636, 637, + 644, 645, 647, 646, 648, 649, 45, 46, 407, 47, + 48, 640, 651, 650, -233, 49, 50, 263, 51, 253, + 879, 880, 881, 878, 877, 876, 871,-32767,-32767,-32767, + -32767, 93, 94, 95, 96, 97, 827, 828, 390, 1063, + 667, 685, 686, 1086, -452, 995, 827, 828,-32766,-32766, + -32766, 52, 53, 117, 763, -292, -292, 54, -91, 55, + 226, 227, 56, 57, 58, 59, 60, 61, 62, 63, + -451, 25, 237, 64, 359,-32766,-32766,-32766, -491, 1012, + 1013, 409, 668, 1045, -487, 348, 119, 1011,-32766,-32766, + -32766, 745, 799, 228, 234,-32766, 454,-32766,-32766,-32766, + -32766, 28, 229, 976, 245, -452, 367, 9,-32766, 268, + -32766,-32766,-32766, 24, -176, 662, 293,-32766,-32766, -452, + 294, 827, 828, 1045, 419, 420, -452, 664, -455, 297, + 995, -451, 301, 421, 422, 664, 1017, 1018, 1019, 1020, + 1014, 1015, 248, -238, -450, -451, 352, 431, 1021, 1016, + 364, 1048, -451, 1025, -454, 66, 988, 260, 391, 265, + 270, 408, -136, -136, -136, -4, 745, 353, 358,-32766, + 430, 734, 25, -490, 37, 20, 410, -136, 411, -136, + 412, -136, 413, -136, 1045, 414, 232, 125, 1011, 38, + 39, 360, 361, 431, 40, 415, 364, 1007, 65, 277, + 270, 292, 563, 416, 417, -450, -292, -292, 1045, 418, + 122, 800, 720, 768, 362, 363, 355, 988, -500, -450, + -450, 33,-32766,-32766,-32766, -499, -450, 356, 664, -487, + 44, 539,-32766,-32766,-32766, 422, 408, 745, 747, 554, + -136, 988,-32766,-32766,-32766,-32766, 734, -290, 236, 37, + 20, 410,-32766, 411, 765, 412, 68, 413, 664, -176, + 414, 270, 235, 430, 38, 39, 360, 361, 344, 40, + 415, 516, 21, 65, 259, 1045, 292,-32766, 416, 417, + 25, -450, -292, -292, 418, 270,-32766, 677, 768, 362, + 363, 252, 1045, 430, 25, -450, 1011, 540, 123, 74, + 364, 269, -450, 833, 857, 296, 1045, 408, 279, 745, + 1011, 232, 118, 747, 554, -4, 219, 734, -490, 42, + 37, 20, 410, 357, 411, 988, 412, 133, 413, 134, + 766, 414, -217, -217, -217, 38, 39, 360, 361, 988, + 40, 415, 421, 422, 65, 124, -177, 292, 230, 416, + 417, 30, 270, 664, -258, 418, 421, 422, 720, 768, + 362, 363, 381, -500, 68, -500, -292, -292, -488, 270, + -499, 1045, -499, 231, 121, 233, 664, 477, 68, 408, + 251, 528, 529, 270, 747, 554, -217, 120, 430, 734, + 664, 114, 37, 20, 410, 115, 411, 127, 412, 131, + 413, 116, -82, 414, -218, -218, -218, 38, 39, 360, + 361, 430, 40, 415, 767, 664, 65, 664, 745, 292, + 129, 416, 417, 123, 759, 430, 247, 418, 130, 319, + 720, 768, 362, 363,-32766,-32766,-32766, 400, 8, 75, + 76, 77, 95, 96, 97, 564, 565, 567, 270, 744, + 430, 101, 430, 685, 686, 281, 747, 554, -218, 31, + 244, 78, 79, 80, 81, 82, 83, 84, 85, 86, + 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, + 97, 98, 99, 100, 536, 244, 43, 745, 408, 509, + 510, -177, 827, 828, 856, 577, 1064, 101, 734, -258, + 128, 37, 20, 410, 664, 411, 665, 412, 1097, 413, + 463, 662, 414, -488, 667, 558, 38, 39, 360, 745, + 885, 40, 415, 517,-32766, 65, 458, 548, 292, 261, + 531, -80, 372, 522, 508, 988, 418, 10, 770, 379, + 267, 1027, 532, 523, 769, 375, 1024, 559, 761, 555, + 12, -409, 863, 5, 295, 1092, 0, 408, 264, 262, + 0, 861, 0, 0, 0, 747, 554, 734, 0, 0, + 37, 20, 410, 0, 411, 0, 412, 0, 413, 0, + 0, 414, 0, 0, 0, 38, 39, 360, 745, 408, + 40, 415, 0, 0, 65, 350, 337, 292, 333, 734, + 332, 326, 37, 20, 410, 418, 411, 460, 412, 349, + 413, 557, 864, 414, 862, 575, 561, 38, 39, 360, + 745, 860, 40, 415, 781, 576, 65, 851, 723, 292, + 36, 725, 868, 794, 747, 554, 783, 418, 852, 793, + 786, 802, 35, 515, 562, 275, 276, 342, 560, 566, + 343, 573, 568, 570, 572, 0, 721, 1094, 408, 745, + 569, 792, 791, 762, 754, 688, 747, 554, 734, 1093, + 687, 37, 20, 410, 1091, 411, 1046, 412, 1039, 413, + 1053, 1058, 414, 1061, 680, 690, 38, 39, 360, 752, + 408, 40, 415, 689, 679, 65, 26, 23, 292, -453, + 734, -454, -455, 37, 20, 410, 418, 411, -477, 412, + -479, 413, 27, 34, 414, 41, 67, 69, 38, 39, + 360, 70, 71, 40, 415, 72, 73, 65, 126, 408, + 292, 132, 135, 224, 225, 747, 554, 240, 418, 734, + 347, 345, 37, 20, 410, 278, 411, 243, 412, 242, + 413, 241, 968, 414, 952, 955, 547, 38, 39, 360, + 504, 487, 40, 415, 315, 255, 65, 785, 554, 292, + -32766,-32766,-32766, 22, 18, 13, -236, 418, -91, -234, + 980, 834, 1009, 951, 999, 545, 405, 398, 396, 392, + -32766, 316,-32766,-32766,-32766,-32766,-32766,-32766,-32767,-32767, + -32767,-32767,-32767, 19, 17, 16, 747, 554, 15, 14, + 1026, -233, 0, -421, 0, 1052, 1089, 1037, 1038, 1008 ); protected $actionCheck = array( 2, 3, 4, 5, 6, 13, 8, 9, 10, 11, - 12, 1, 15, 16, 17, 18, 19, 20, 21, 22, + 12, 48, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 8, 9, 10, 50, 51, - 52, 0, 54, 7, 79, 8, 9, 10, 8, 9, - 10, 77, 7, 13, 66, 28, 7, 30, 31, 32, - 33, 34, 54, 56, 57, 28, 8, 30, 31, 32, - 33, 34, 35, 7, 109, 7, 68, 69, 70, 71, - 72, 73, 74, 118, 28, 77, 112, 113, 114, 115, + 52, 146, 54, 1, 149, 8, 9, 10, 77, 1, + 77, 77, 0, 80, 66, 28, 1, 30, 31, 32, + 33, 34, 54, 56, 57, 28, 7, 30, 31, 32, + 33, 34, 35, 7, 28, 1, 68, 69, 70, 71, + 72, 73, 74, 112, 28, 77, 112, 113, 114, 115, 116, 117, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, - 122, 123, 124, 125, 126, 127, 1, 129, 130, 131, + 122, 123, 124, 125, 126, 127, 94, 129, 130, 131, 132, 133, 134, 135, 136, 137, 2, 3, 4, 5, - 6, 143, 144, 145, 152, 11, 12, 79, 14, 41, - 42, 43, 44, 45, 46, 47, 48, 49, 109, 149, - 29, 112, 113, 114, 115, 116, 117, 118, 77, 82, - 67, 7, 1, 7, 67, 1, 130, 131, 77, 29, - 35, 47, 48, 8, 9, 10, 7, 53, 7, 55, + 6, 143, 144, 145, 152, 11, 12, 109, 14, 28, + 112, 113, 114, 115, 116, 117, 118, 41, 42, 43, + 44, 45, 46, 47, 48, 49, 130, 131, 29, 1, + 79, 102, 103, 82, 67, 1, 130, 131, 8, 9, + 10, 47, 48, 13, 1, 102, 103, 53, 152, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, - 67, 67, 68, 69, 70, 8, 9, 10, 77, 75, - 76, 77, 1, 79, 7, 102, 103, 83, 8, 9, - 10, 1, 77, 35, 156, 28, 139, 30, 31, 32, - 33, 128, 7, 15, 143, 128, 102, 146, 28, 15, - 30, 31, 32, 112, 143, 142, 112, 146, 7, 142, - 79, 150, 149, 79, 120, 121, 149, 112, 151, 146, - 28, 128, 7, 129, 130, 77, 132, 133, 134, 135, - 136, 137, 138, 148, 67, 142, 7, 143, 144, 145, - 146, 7, 149, 112, 151, 151, 112, 153, 77, 155, - 156, 71, 72, 73, 74, 0, 1, 123, 148, 28, - 112, 81, 67, 77, 84, 85, 86, 87, 88, 89, - 90, 91, 92, 93, 79, 95, 35, 7, 83, 99, - 100, 101, 102, 15, 104, 105, 29, 156, 108, 7, - 156, 111, 48, 113, 114, 128, 7, 7, 112, 119, - 8, 9, 122, 123, 124, 125, 7, 112, 146, 142, - 67, 149, 8, 9, 10, 67, 149, 1, 77, 152, - 149, 77, 130, 131, 80, 130, 71, 1, 148, 149, - 150, 35, 28, 13, 30, 31, 81, 152, 35, 84, - 85, 86, 7, 88, 152, 90, 151, 92, 72, 73, + 67, 67, 68, 69, 70, 8, 9, 10, 152, 75, + 76, 77, 148, 79, 7, 146, 7, 83, 8, 9, + 10, 1, 29, 35, 7, 28, 82, 30, 31, 32, + 33, 140, 141, 150, 7, 128, 102, 7, 28, 7, + 30, 31, 32, 7, 7, 77, 112, 8, 9, 142, + 7, 130, 131, 79, 120, 121, 149, 77, 151, 7, + 1, 128, 7, 129, 130, 77, 132, 133, 134, 135, + 136, 137, 138, 152, 67, 142, 7, 143, 144, 145, + 146, 1, 149, 139, 151, 151, 112, 153, 149, 155, + 156, 71, 72, 73, 74, 0, 1, 123, 7, 1, + 112, 81, 67, 7, 84, 85, 86, 87, 88, 89, + 90, 91, 92, 93, 79, 95, 35, 149, 83, 99, + 100, 101, 102, 143, 104, 105, 146, 1, 108, 7, + 156, 111, 149, 113, 114, 128, 102, 103, 79, 119, + 29, 148, 122, 123, 124, 125, 7, 112, 7, 142, + 67, 13, 8, 9, 10, 7, 149, 7, 77, 152, + 67, 77, 8, 9, 10, 130, 71, 1, 148, 149, + 150, 112, 28, 8, 30, 31, 81, 79, 35, 84, + 85, 86, 28, 88, 150, 90, 151, 92, 77, 152, 95, 156, 35, 112, 99, 100, 101, 102, 103, 104, - 105, 130, 131, 108, 109, 7, 111, 152, 113, 114, - 67, 128, 7, 77, 119, 67, 128, 122, 123, 124, - 125, 152, 79, 152, 67, 142, 83, 7, 147, 7, - 7, 79, 149, 152, 82, 79, 79, 71, 143, 1, - 83, 72, 73, 148, 149, 150, 149, 81, 112, 13, - 84, 85, 86, 29, 88, 112, 90, 15, 92, 97, - 98, 95, 96, 97, 98, 99, 100, 101, 102, 112, - 104, 105, 129, 130, 108, 15, 128, 111, 15, 113, - 114, 152, 152, 147, 154, 119, 129, 130, 122, 123, - 124, 125, 140, 141, 151, 102, 103, 149, 15, 156, - 8, 9, 10, 35, 15, 149, 77, 78, 151, 71, - 102, 103, 156, 156, 148, 149, 150, 106, 107, 81, - 28, 33, 84, 85, 86, 29, 88, 152, 90, 154, - 92, 130, 131, 95, 96, 97, 98, 99, 100, 101, - 102, 112, 104, 105, 29, 77, 108, 29, 1, 111, - 152, 113, 114, 47, 48, 49, 29, 119, 148, 149, - 122, 123, 124, 125, 148, 149, 29, 35, 54, 8, - 9, 10, 152, 66, 152, 67, 29, 35, 67, 74, - 112, 77, 79, 82, 82, 86, 148, 149, 150, 28, - 77, 30, 31, 32, 33, 34, 35, 36, 37, 38, + 105, 72, 73, 108, 109, 79, 111, 109, 113, 114, + 67, 128, 102, 103, 119, 156, 118, 122, 123, 124, + 125, 128, 79, 112, 67, 142, 83, 143, 147, 149, + 146, 67, 149, 152, 150, 142, 79, 71, 143, 1, + 83, 35, 149, 148, 149, 150, 13, 81, 152, 67, + 84, 85, 86, 7, 88, 112, 90, 15, 92, 15, + 150, 95, 96, 97, 98, 99, 100, 101, 102, 112, + 104, 105, 129, 130, 108, 149, 7, 111, 35, 113, + 114, 7, 156, 77, 7, 119, 129, 130, 122, 123, + 124, 125, 128, 152, 151, 154, 102, 103, 7, 156, + 152, 79, 154, 35, 15, 35, 77, 78, 151, 71, + 128, 72, 73, 156, 148, 149, 150, 15, 112, 81, + 77, 15, 84, 85, 86, 15, 88, 15, 90, 15, + 92, 149, 29, 95, 96, 97, 98, 99, 100, 101, + 102, 112, 104, 105, 150, 77, 108, 77, 1, 111, + 29, 113, 114, 147, 35, 112, 29, 119, 97, 98, + 122, 123, 124, 125, 8, 9, 10, 102, 103, 8, + 9, 10, 47, 48, 49, 29, 29, 29, 156, 29, + 112, 66, 112, 102, 103, 33, 148, 149, 150, 28, + 54, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, - 49, 50, 51, 52, 79, 54, 77, 1, 71, 77, - 80, 87, 89, 93, 96, 94, 102, 66, 81, 91, - 94, 84, 85, 86, 109, 88, 110, 90, 94, 92, - 94, 96, 95, 123, 123, 29, 99, 100, 101, 1, - 127, 104, 105, 112, 112, 108, 139, 147, 111, 150, - 148, 139, 146, -1, -1, 146, 119, -1, -1, 126, - -1, 142, -1, -1, 126, -1, -1, 29, -1, -1, - -1, -1, -1, -1, -1, -1, -1, 71, -1, -1, - -1, 142, 142, 142, -1, 148, 149, 81, 146, 146, - 84, 85, 86, 146, 88, 146, 90, 149, 92, 146, - 146, 95, 150, 148, 148, 99, 100, 101, 1, 71, - 104, 105, 148, 148, 108, 148, 148, 111, 148, 81, - 148, 148, 84, 85, 86, 119, 88, 148, 90, 148, - 92, 148, 148, 95, 148, 148, 29, 99, 100, 101, - 1, 148, 104, 105, 148, 148, 108, 149, 149, 111, - 149, 149, 149, 149, 148, 149, 149, 119, 149, 149, - 149, 149, 149, 149, 149, -1, 150, 150, 29, 150, - 150, 150, 150, 150, 150, 150, 150, 150, 71, 1, + 49, 50, 51, 52, 74, 54, 67, 1, 71, 106, + 107, 152, 130, 131, 148, 149, 152, 66, 81, 152, + 67, 84, 85, 86, 77, 88, 77, 90, 80, 92, + 86, 77, 95, 152, 79, 29, 99, 100, 101, 1, + 79, 104, 105, 87, 82, 108, 82, 89, 111, 126, + 91, 94, 102, 93, 109, 112, 119, 94, 123, 94, + 126, 139, 96, 96, 123, 146, 139, 29, 147, 149, + 142, 142, 148, 142, 142, 150, -1, 71, 110, 127, + -1, 148, -1, -1, -1, 148, 149, 81, -1, -1, + 84, 85, 86, -1, 88, -1, 90, -1, 92, -1, + -1, 95, -1, -1, -1, 99, 100, 101, 1, 71, + 104, 105, -1, -1, 108, 146, 146, 111, 146, 81, + 146, 146, 84, 85, 86, 119, 88, 146, 90, 146, + 92, 149, 148, 95, 148, 148, 29, 99, 100, 101, + 1, 148, 104, 105, 148, 148, 108, 148, 148, 111, + 148, 148, 148, 148, 148, 149, 148, 119, 148, 148, + 148, 148, 148, 154, 149, 149, 149, 149, 29, 149, + 149, 149, 149, 149, 149, -1, 150, 150, 71, 1, 150, 150, 150, 150, 150, 150, 148, 149, 81, 150, 150, 84, 85, 86, 150, 88, 150, 90, 150, 92, - 150, 150, 95, 150, 150, 150, 99, 100, 101, 151, - 71, 104, 105, 151, 151, 108, 151, 151, 111, 151, + 150, 150, 95, 150, 150, 150, 99, 100, 101, 150, + 71, 104, 105, 150, 150, 108, 151, 151, 111, 151, 81, 151, 151, 84, 85, 86, 119, 88, 151, 90, 151, 92, 151, 151, 95, 151, 151, 151, 99, 100, 101, 151, 151, 104, 105, 151, 151, 108, 151, 71, 111, 151, 151, 151, 151, 148, 149, 151, 119, 81, - 151, 151, 84, 85, 86, 151, 88, 152, 90, 152, - 92, 152, 152, 95, 152, 152, 152, 99, 100, 101, + 151, 151, 84, 85, 86, 151, 88, 151, 90, 151, + 92, 151, 153, 95, 152, 152, 152, 99, 100, 101, 152, 152, 104, 105, 152, 152, 108, 148, 149, 111, 8, 9, 10, 152, 152, 152, 152, 119, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 28, 152, 30, 31, 32, 33, 34, 35, 36, 37, - 38, 39, 40, 152, 154, 153, 148, 149, 153, 155, - 154, 154, -1, 154, 154, 154 + 38, 39, 40, 152, 152, 152, 148, 149, 152, 152, + 155, 152, -1, 153, -1, 154, 154, 154, 154, 154 ); protected $actionBase = array( - 0, 220, 295, 366, 438, 356, 101, 575, -2, -2, - -36, -2, -2, 547, 717, 616, 717, 749, 648, 788, - 788, 788, 281, 336, 145, 145, 468, 429, 145, 468, - 131, 188, 542, 226, 226, 226, 226, 226, 226, 226, - 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, - 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, - 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, - 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, - 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, - 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, - 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, - 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, - 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, - 226, 226, 226, 226, 226, 125, 125, 150, 360, 732, - 743, 738, 729, 727, 531, 734, 733, 436, 660, 661, - 424, 663, 664, 665, 658, 739, 780, 730, 742, 561, + 0, 220, 295, 438, 366, 326, 284, 596, -2, -2, + -36, -2, -2, 648, 717, 717, 547, 717, 616, 749, + 788, 788, 788, 281, 406, 188, 188, 443, 429, 188, + 443, 311, 468, 470, -39, -39, -39, -39, -39, -39, + -39, -39, -39, -39, -39, -39, -39, -39, -39, -39, + -39, -39, -39, -39, -39, -39, -39, -39, -39, -39, + -39, -39, -39, -39, -39, -39, -39, -39, -39, -39, + -39, -39, -39, -39, -39, -39, -39, -39, -39, -39, + -39, -39, -39, -39, -39, -39, -39, -39, -39, -39, + -39, -39, -39, -39, -39, -39, -39, -39, -39, -39, + -39, -39, -39, -39, -39, -39, -39, -39, -39, -39, + -39, -39, -39, -39, -39, -39, -39, -39, -39, -39, + -39, -39, -39, -39, -39, -39, -39, -39, -39, -39, + -39, -39, -39, -39, -39, -39, 64, 64, 193, 32, + 338, 743, 733, 739, 752, 753, 742, 732, 433, 654, + 656, 521, 658, 660, 661, 663, 738, 619, 751, 734, 561, 561, 561, 561, 561, 561, 561, 561, 561, 561, - 561, 561, 561, 561, 561, 48, 30, 332, 175, 175, - 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, - 175, 175, 175, 175, 175, 175, 175, 492, 492, 492, - 344, 210, 207, 197, 17, 103, 27, 892, 892, 892, - 892, 892, 108, 108, 108, 108, 343, 343, 357, 235, - 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, - 235, 235, 630, 509, 562, 626, 174, 506, 506, 232, - 232, 232, 232, 171, 271, -45, 46, 87, 517, 784, - 211, 211, 401, 107, 133, -22, -22, -22, 113, 501, - 541, 541, 541, 541, 352, 352, 541, 541, 284, 10, - 103, 103, 283, 103, 393, 393, 393, 91, 202, 502, - 91, 617, 528, 627, 545, 629, 348, 330, 375, 557, - 68, 524, 564, 68, 68, 68, 411, 369, 316, 756, - 125, 529, 125, 125, 125, 125, 705, 125, 125, 125, - 125, 125, 125, 297, 125, 410, 150, 488, 416, 514, - 288, 619, 422, 225, 514, 514, 514, 620, 621, 420, - 269, -8, 608, 255, 408, 398, 329, 513, 513, 504, - 504, 535, 532, 513, 513, 513, 513, 513, 668, 668, - 504, 503, 504, 535, 689, 504, 532, 504, 504, 513, - 504, 668, 532, 39, 322, 181, 423, 532, 310, 548, - 513, 543, 543, 274, 504, 35, 504, 166, 523, 668, - 668, 523, 241, 532, 56, 565, 566, 525, 510, 58, - 496, 503, 496, 339, 525, 164, 532, 496, 179, 503, - 405, 496, 31, 691, 692, 518, 724, 687, 720, 695, - 719, 625, 520, 521, 710, 707, 716, 681, 680, 537, - 516, 483, 489, 550, 511, 678, 524, 559, 507, 507, - 507, 511, 675, 507, 507, 507, 507, 507, 507, 507, - 507, 791, 26, 551, 499, 442, 552, 536, 308, 558, - 522, 516, 516, 640, 785, 782, 539, 705, 757, 713, - 607, 224, 764, 704, 631, 519, 563, 701, 763, 754, - 622, 483, 753, 641, 508, 642, 516, 643, 507, 673, - 672, 789, 790, 676, 786, 762, 553, 540, 787, 644, - 752, 624, 623, 512, 767, 725, 761, 645, 760, 574, - 534, 781, 530, 694, 696, 614, 649, 650, 577, 218, - 654, 712, 578, 766, 765, 769, 580, 582, 613, 460, - 612, 656, 463, 583, 711, 515, 505, 538, 591, 751, - 637, 611, 700, 589, 603, 636, 635, 758, 546, 559, - 549, 526, 544, 533, 609, 634, 759, 527, 606, 597, - 596, 594, 633, 593, 632, 0, 0, 0, 0, 0, + 561, 561, 561, 561, 561, 561, 365, 170, 239, 556, + 556, 556, 556, 556, 556, 556, 556, 556, 556, 556, + 556, 556, 556, 556, 556, 556, 556, 556, 354, 354, + 354, 344, 210, 207, 197, 17, 283, 27, 892, 892, + 892, 892, 892, 116, 116, 116, 116, 357, 357, 343, + 394, 310, 234, 83, 235, 235, 235, 235, 235, 235, + 235, 235, 235, 235, 235, 235, 235, 174, 525, 525, + 121, 121, 121, 121, 259, 36, 298, 46, 144, 532, + 785, 168, 168, 492, 107, 133, -22, -22, -22, 69, + 574, 553, 553, 553, 553, 91, 91, 553, 553, -37, + 280, 283, 283, 293, 283, 481, 481, 481, 180, -115, + 572, 180, 614, 592, 577, 642, 576, 641, 382, 341, + 348, 593, 422, 560, 579, 422, 422, 422, 513, 329, + 439, 756, 64, 539, 64, 64, 64, 64, 716, 64, + 64, 64, 64, 64, 64, 139, 64, 45, 476, 193, + 183, 183, 552, 183, 536, 364, 626, 237, 474, 536, + 536, 536, 627, 628, 491, 477, -8, 631, 469, 465, + 296, 56, 557, 557, 564, 564, 571, 519, 557, 557, + 557, 557, 557, 676, 676, 564, 565, 564, 571, 694, + 564, 519, 564, 564, 557, 564, 676, 519, 209, 339, + 243, 252, 519, 350, 533, 557, 544, 544, 446, 564, + 217, 564, 236, 562, 676, 676, 562, 227, 519, 232, + 597, 607, 555, 531, 322, 527, 527, 269, 555, 291, + 519, 527, 230, 565, 255, 527, 42, 695, 696, 503, + 700, 692, 701, 720, 704, 530, 551, 545, 712, 713, + 705, 691, 675, 550, 591, 506, 510, 541, 549, 678, + 560, 529, 515, 515, 515, 549, 681, 515, 515, 515, + 515, 515, 515, 515, 515, 795, 49, 542, 554, 502, + 585, 575, 489, 633, 537, 591, 591, 636, 790, 729, + 559, 716, 762, 707, 624, 512, 781, 730, 640, 584, + 582, 728, 769, 761, 634, 506, 760, 535, 563, 637, + 591, 664, 515, 687, 689, 793, 794, 680, 791, 787, + 767, 580, 558, 792, 674, 759, 635, 632, 612, 786, + 754, 766, 673, 765, 613, 566, 757, 570, 719, 724, + 625, 665, 650, 609, 514, 649, 710, 623, 783, 569, + 782, 789, 622, 621, 442, 645, 444, 620, 711, 546, + 540, 618, 615, 758, 644, 726, 610, 643, 763, 567, + 529, 538, 578, 573, 568, 630, 764, 548, 606, 603, + 534, 594, 669, 543, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 134, 134, 134, 134, -2, - -2, -2, 0, 0, -2, 0, 0, 134, 134, 134, + 0, 134, 134, 134, 134, -2, -2, -2, 0, 0, + -2, 0, 0, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, @@ -500,141 +500,140 @@ 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, - 134, 134, 134, 134, 134, 134, 134, 134, 134, 561, + 134, 134, 134, 134, 134, 134, 561, 561, 561, 561, 561, 561, 561, 561, 561, 561, 561, 561, 561, 561, 561, 561, 561, 561, 561, 561, 561, 561, 561, 561, - 561, 561, 561, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 561, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 561, 561, 561, 561, 561, 561, 561, 561, 561, 561, 561, 561, 561, 561, 561, 561, 561, 561, 561, 561, 561, 561, 561, 561, - 561, 561, 561, 561, 561, 561, -3, 561, 561, -3, - 561, 561, 561, 561, 561, 561, -22, -22, -22, -22, - 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, - 91, 91, 91, 91, 91, 91, 49, 49, 49, 49, - 91, -22, -22, 91, 91, 91, 91, 91, 91, 49, - 91, 352, 352, 352, 68, 68, 91, 0, 0, 0, - 0, 0, 513, 352, 91, 91, 91, 91, 0, 0, - 91, 91, 503, 68, 0, 0, 0, 0, 513, 513, - 513, 0, 513, 352, 0, 125, 362, 362, 362, 362, - 0, 0, 0, 513, 0, 503, 513, 0, 0, 0, - 0, 0, 0, 532, 0, 668, 0, 0, 0, 0, - 504, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 503, 0, 507, 0, 539, 0, 0, 507, 507, - 507, 539, 539, 0, 0, 0, 539 + 561, 561, 561, -3, 561, 561, -3, 561, 561, 561, + 561, 561, 561, -22, -22, -22, -22, 180, 180, 180, + 38, 38, 38, 38, 180, 180, 180, 180, 180, 180, + 180, 180, 180, 180, 180, 180, 180, 180, -22, -22, + 180, 180, 180, 180, 180, 180, 38, 180, 91, 91, + 91, 422, 422, 180, 0, 0, 0, 0, 0, 557, + 91, 180, 180, 180, 180, 0, 0, 180, 180, 565, + 422, 0, 0, 0, 0, 557, 557, 557, 0, 557, + 91, 0, 183, 64, 461, 461, 461, 461, 0, 0, + 0, 557, 0, 565, 557, 0, 0, 0, 0, 0, + 0, 519, 0, 676, 0, 0, 0, 0, 564, 0, + 0, 0, 0, 0, 0, 0, 0, 565, 0, 0, + 0, 0, 565, 0, 515, 0, 559, 0, 0, 515, + 515, 515, 559, 559, 0, 0, 0, 559 ); protected $actionDefault = array( 3,32767,32767,32767,32767,32767,32767,32767,32767, 91, 32767,32767,32767,32767,32767,32767,32767,32767,32767,32767, - 32767,32767,32767, 93, 496, 496, 488,32767, 496, 488, - 32767,32767,32767, 306, 306, 306,32767, 443, 443, 443, - 443, 443, 443, 443,32767,32767,32767,32767,32767, 385, + 32767,32767,32767,32767, 93, 501, 501, 493,32767, 501, + 493,32767,32767,32767, 311, 311, 311,32767, 448, 448, + 448, 448, 448, 448, 448,32767,32767,32767,32767,32767, + 390,32767,32767,32767,32767,32767,32767,32767,32767,32767, 32767,32767,32767,32767,32767,32767,32767,32767,32767,32767, 32767,32767,32767,32767,32767,32767,32767,32767,32767,32767, 32767,32767,32767,32767,32767,32767,32767,32767,32767,32767, 32767,32767,32767,32767,32767,32767,32767,32767,32767,32767, 32767,32767,32767,32767,32767,32767,32767,32767,32767,32767, + 32767,32767,32767,32767,32767,32767,32767,32767,32767, 91, 32767,32767,32767,32767,32767,32767,32767,32767,32767,32767, - 32767,32767,32767,32767,32767,32767,32767,32767, 91,32767, 32767,32767,32767,32767,32767,32767,32767,32767,32767,32767, - 32767,32767,32767,32767,32767,32767,32767,32767, 493,32767, + 498,32767,32767,32767,32767,32767,32767,32767,32767,32767, 32767,32767,32767,32767,32767,32767,32767,32767,32767,32767, - 32767,32767,32767,32767,32767,32767,32767,32767,32767, 368, - 369, 371, 372, 305, 444, 253, 492, 304, 129, 264, - 255, 207, 302, 239, 133, 333, 386, 335, 384, 388, - 334, 311, 315, 316, 317, 318, 319, 320, 321, 322, - 323, 324, 325, 326, 309, 310, 387, 365, 364, 363, - 331, 332, 308, 336, 338, 308, 337, 354, 355, 352, - 353, 356, 357, 358, 359, 360,32767,32767,32767,32767, - 32767,32767,32767,32767,32767,32767,32767,32767,32767, 93, - 32767,32767, 287, 287, 287, 287,32767, 345, 346, 245, - 245, 245, 245,32767, 245, 288,32767,32767,32767,32767, - 32767,32767,32767, 437, 362, 340, 341, 339,32767, 415, - 32767,32767,32767,32767,32767, 417,32767, 91,32767,32767, - 328, 330, 409, 312,32767,32767, 93,32767,32767,32767, - 32767,32767,32767,32767,32767,32767, 412, 445, 445,32767, - 32767, 403, 91,32767,32767, 91, 172, 226, 228, 177, - 32767, 420,32767,32767,32767,32767,32767,32767,32767,32767, - 32767,32767,32767,32767,32767,32767,32767,32767,32767, 350, - 503,32767, 445,32767, 342, 343, 344,32767,32767, 445, - 445, 445,32767, 445,32767, 445, 445,32767,32767,32767, - 32767,32767, 177,32767,32767,32767,32767, 93, 418, 418, - 91, 91, 91, 91, 413,32767, 177,32767,32767,32767, - 32767,32767, 177, 90, 90, 90, 90, 177, 90, 190, - 32767, 188, 188, 90,32767, 92,32767, 92, 192,32767, - 459, 192, 90, 177, 90, 212, 212, 394, 179, 92, - 247,32767, 247, 92, 394, 90, 177, 247, 90,32767, - 90, 247,32767,32767,32767, 84,32767,32767,32767,32767, + 373, 374, 376, 377, 310, 449, 257, 497, 309, 129, + 268, 259, 210, 307, 242, 133, 338, 391, 340, 389, + 393, 339, 316, 320, 321, 322, 323, 324, 325, 326, + 327, 328, 329, 330, 331, 314, 315, 392, 370, 369, + 368, 336, 337, 313, 341, 343, 313, 342, 359, 360, + 357, 358, 361, 362, 363, 364, 365,32767,32767,32767, 32767,32767,32767,32767,32767,32767,32767,32767,32767,32767, - 405,32767, 425,32767, 438, 457, 403,32767, 348, 349, - 351,32767, 447, 373, 374, 375, 376, 377, 378, 379, - 381,32767, 489, 408,32767,32767, 86, 120, 263,32767, - 501, 86, 406,32767, 501,32767,32767,32767,32767,32767, - 32767,32767,32767,32767,32767, 86, 86,32767,32767,32767, - 32767, 484,32767, 502,32767, 445, 407,32767, 347, 421, - 464,32767,32767, 446,32767,32767, 86,32767,32767,32767, - 32767,32767,32767,32767,32767, 425,32767,32767,32767,32767, - 32767, 445,32767,32767,32767,32767,32767,32767,32767, 301, - 32767,32767,32767,32767,32767, 445,32767,32767,32767, 238, + 32767,32767,32767,32767, 93,32767,32767,32767, 350, 351, + 249, 249, 249, 249,32767, 249, 293,32767,32767,32767, + 32767,32767,32767,32767, 442, 367, 345, 346, 344,32767, + 420,32767,32767,32767,32767,32767, 422,32767, 91,32767, + 32767, 333, 335, 414, 317,32767,32767, 93,32767,32767, + 32767,32767,32767,32767,32767,32767,32767,32767, 417, 450, + 450,32767,32767, 408, 91,32767,32767, 91, 173, 229, + 231, 178,32767, 425,32767,32767,32767,32767,32767,32767, 32767,32767,32767,32767,32767,32767,32767,32767,32767,32767, - 32767,32767,32767,32767,32767,32767,32767,32767, 84, 60, - 32767, 281,32767,32767,32767,32767,32767,32767,32767,32767, - 32767,32767,32767,32767,32767, 135, 135, 3, 3, 135, - 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, - 135, 135, 266, 167, 266, 220, 266, 266, 223, 212, - 212, 273, 135, 135 + 32767,32767,32767,32767, 355, 508,32767, 450,32767, 347, + 348, 349,32767,32767, 450, 450, 450,32767, 450,32767, + 450, 450,32767,32767,32767,32767,32767, 178,32767,32767, + 32767,32767, 93, 423, 423, 91, 91, 91, 91, 418, + 32767, 178,32767,32767,32767,32767,32767, 178, 90, 90, + 90, 90, 178, 90, 193,32767, 191, 191, 90,32767, + 92,32767, 92, 195,32767, 464, 195, 90, 178, 90, + 215, 215, 399, 180, 92, 251, 251, 92, 399, 90, + 178, 251, 90,32767, 90, 251,32767,32767,32767, 84, + 32767,32767,32767,32767,32767,32767,32767,32767,32767,32767, + 32767,32767,32767,32767, 410,32767, 430,32767, 443, 462, + 408,32767, 353, 354, 356,32767, 452, 378, 379, 380, + 381, 382, 383, 384, 386,32767, 494, 413,32767,32767, + 86, 120, 267,32767, 506, 86, 411,32767, 506,32767, + 32767,32767,32767,32767,32767,32767,32767,32767,32767, 86, + 86,32767,32767,32767,32767, 489,32767, 507,32767, 450, + 412,32767, 352, 426, 469,32767,32767, 451,32767,32767, + 32767, 86,32767,32767,32767,32767,32767,32767,32767,32767, + 430,32767,32767,32767,32767,32767, 450,32767,32767,32767, + 32767,32767,32767,32767, 306,32767,32767,32767,32767,32767, + 32767, 450,32767,32767, 241,32767,32767,32767,32767,32767, + 32767,32767,32767,32767,32767,32767,32767,32767,32767, 84, + 60,32767, 286,32767,32767,32767,32767,32767,32767,32767, + 32767,32767,32767,32767, 135, 135, 3, 3, 135, 135, + 135, 135, 135, 135, 135, 135, 135, 135, 270, 168, + 270, 223, 270, 270, 226, 215, 215, 278, 135, 135 ); protected $goto = array( - 165, 165, 138, 138, 147, 148, 138, 147, 150, 181, - 166, 163, 163, 163, 163, 164, 164, 164, 164, 164, - 164, 164, 159, 160, 161, 162, 178, 176, 179, 428, - 429, 319, 430, 433, 434, 435, 436, 437, 438, 439, - 440, 898, 136, 139, 140, 141, 142, 143, 144, 145, - 146, 149, 175, 177, 180, 197, 200, 201, 203, 204, - 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, - 237, 238, 255, 256, 257, 324, 325, 326, 478, 182, - 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, - 193, 194, 195, 151, 196, 152, 167, 168, 169, 198, - 170, 153, 154, 155, 171, 156, 199, 137, 172, 157, - 173, 174, 158, 540, 202, 446, 550, 202, 745, 304, - 308, 458, 481, 482, 484, 678, 233, 283, 234, 235, - 715, 451, 451, 451, 480, 451, 802, 783, 781, 783, - 575, 7, 444, 811, 806, 471, 466, 680, 471, 451, - 431, 431, 431, 431, 431, 431, 431, 431, 431, 431, - 431, 431, 431, 431, 431, 431, 432, 432, 432, 432, - 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, - 432, 432, 496, 498, 546, 265, 706, 710, 698, 840, - 249, 844, 493, 513, 451, 451, 788, 777, 315, 549, - 465, 486, 451, 451, 451, 818, 679, 778, 479, 866, - 553, 667, 1054, 1055, 532, 864, 452, 706, 881, 984, - 706, 714, 742, 980, 477, 489, 785, 476, 495, 495, - 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009, - 1009, 1009, 1009, 1009, 464, 1081, 1081, 578, 500, 502, - 527, 530, 535, 536, 813, 543, 545, 552, 809, 554, - 3, 4, 1081, 682, 836, 697, 697, 472, 1074, 302, - 514, 707, 707, 707, 709, 696, 1084, 1097, 1064, 985, - 469, 945, 687, 490, 737, 732, 733, 746, 821, 688, - 734, 685, 735, 736, 686, 701, 740, 986, 1040, 695, - 448, 832, 1053, 289, 331, 515, 335, 322, 322, 270, - 271, 287, 475, 329, 273, 330, 288, 333, 501, 336, - 284, 285, 1082, 1082, 520, 825, 537, 506, 281, 531, - 702, 312, 699, 318, 841, 816, 816, 1071, 582, 1082, - 521, 981, 976, 988, 711, 883, 826, 826, 826, 826, - 988, 826, 845, 826, 492, 790, 1059, 1059, 381, 826, - 448, 397, 0, 0, 443, 1050, 0, 988, 988, 988, - 988, 443, 1050, 988, 988, 306, 874, 0, 0, 1061, - 1061, 457, 0, 0, 753, 0, 467, 754, 779, 779, - 779, 779, 0, 0, 773, 780, 0, 0, 1046, 0, - 519, 0, 388, 0, 0, 0, 0, 0, 983, 0, - 0, 0, 463, 0, 0, 11, 0, 0, 0, 843, - 0, 0, 1048, 1048, 843, 0, 0, 0, 0, 0, + 166, 166, 140, 140, 148, 149, 140, 148, 151, 182, + 167, 164, 164, 164, 164, 165, 165, 165, 165, 165, + 165, 165, 160, 161, 162, 163, 179, 177, 180, 432, + 433, 324, 434, 437, 438, 439, 440, 441, 442, 443, + 444, 899, 137, 141, 142, 143, 144, 145, 139, 146, + 147, 150, 176, 178, 181, 198, 201, 202, 204, 205, + 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, + 238, 239, 256, 257, 258, 329, 330, 331, 482, 183, + 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, + 194, 195, 196, 152, 197, 153, 168, 169, 170, 199, + 171, 154, 155, 156, 172, 157, 200, 138, 173, 158, + 174, 175, 159, 541, 203, 450, 550, 203, 742, 306, + 310, 462, 485, 486, 488, 974, 764, 221, 975, 222, + 223, 455, 455, 455, 484, 455, 483, 867, 553, 501, + 503, 546, 535, 865, 435, 435, 435, 470, 985, 285, + 455, 435, 435, 435, 435, 435, 435, 435, 435, 435, + 435, 435, 435, 435, 436, 436, 436, 7, 702, 498, + 518, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 468, 1082, 1082, 574, 505, 507, + 519, 534, 537, 812, 544, 552, 808, 495, 455, 455, + 702, 675, 1082, 702, 469, 491, 455, 455, 455, 697, + 475, 986, 691, 475, 321, 676, 1085, 266, 711, 323, + 456, 663, 250, 282, 784, 500, 500, 1010, 836, 987, + 1041, 480, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, + 1010, 1010, 1010, 1010, 1010, 706, 694, 840, 1098, 844, + 476, 693, 693, 737, 787, 738, 1075, 703, 703, 703, + 705, 692, 1065, 817, 678, 777, 304, 1083, 1083, 1055, + 1056, 308, 452, 481, 494, 882, 520, 461, 710, 473, + 981, 946, 471, 683, 1083, 733, 728, 729, 743, 820, + 684, 730, 681, 731, 732, 682, 524, 736, 393, 832, + 447, 538, 3, 4, 336, 521, 340, 447, 1054, 291, + 11, 327, 327, 271, 272, 289, 479, 334, 274, 335, + 290, 338, 506, 341, 778, 778, 778, 778, 825, 511, + 772, 779, 698, 286, 287, 452, 776, 318, 549, 283, + 314, 695, 841, 578, 989, 525, 982, 826, 826, 826, + 826, 989, 826, 707, 826, 977, 497, 1060, 1060, 845, + 826, 789, 386, 884, 401, 0, 1051, 0, 989, 989, + 989, 989, 0, 1051, 989, 989, 0, 0, 674, 0, + 1062, 1062, 984, 0, 0, 750, 0, 0, 751, 801, + 782, 782, 780, 782, 571, 0, 448, 810, 805, 1047, + 815, 815, 1072, 875, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 467, 0, 0, 0, 0, 0, + 0, 843, 0, 0, 1049, 1049, 843, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 445, 461, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 445, 0, 461, 0, - 0, 305, 0, 449, 369, 0, 371, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 705, 0, 1089 + 449, 465, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 449, 0, 465, 0, 0, 307, 0, 453, 374, + 0, 376, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 701, 0, 1090 ); protected $gotoCheck = array( @@ -650,79 +649,79 @@ 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 63, 56, 10, 8, 56, 13, 49, - 49, 49, 49, 49, 49, 16, 72, 79, 72, 72, - 36, 10, 10, 10, 96, 10, 16, 16, 16, 16, - 16, 109, 16, 16, 16, 84, 10, 18, 84, 10, - 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, - 133, 133, 133, 133, 133, 133, 135, 135, 135, 135, - 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, - 135, 135, 67, 67, 67, 132, 26, 14, 14, 14, - 132, 14, 46, 46, 10, 10, 14, 75, 75, 75, - 10, 10, 10, 10, 10, 14, 17, 14, 7, 7, - 7, 5, 139, 139, 7, 7, 10, 26, 14, 91, - 26, 14, 55, 14, 2, 2, 40, 10, 85, 85, - 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, - 85, 85, 85, 85, 39, 144, 144, 39, 39, 39, - 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, - 37, 37, 144, 13, 93, 26, 26, 134, 143, 52, - 54, 26, 26, 26, 26, 26, 144, 12, 141, 91, - 53, 116, 13, 15, 13, 13, 13, 13, 87, 13, - 13, 13, 13, 13, 13, 15, 13, 91, 91, 15, - 12, 89, 137, 20, 56, 56, 56, 56, 56, 56, - 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, - 79, 79, 145, 145, 68, 90, 12, 24, 11, 68, - 30, 19, 28, 68, 95, 84, 84, 84, 81, 145, - 23, 125, 122, 63, 32, 112, 63, 63, 63, 63, - 63, 63, 98, 63, 71, 78, 8, 8, 70, 63, - 12, 120, -1, -1, 74, 96, -1, 63, 63, 63, - 63, 74, 96, 63, 63, 65, 109, -1, -1, 96, - 96, 65, -1, -1, 63, -1, 65, 63, 74, 74, - 74, 74, -1, -1, 74, 74, -1, -1, 96, -1, - 12, -1, 65, -1, -1, -1, -1, -1, 12, -1, - -1, -1, 8, -1, -1, 65, -1, -1, -1, 96, - -1, -1, 96, 96, 96, -1, -1, -1, -1, -1, + 49, 49, 49, 49, 49, 67, 67, 73, 67, 73, + 73, 10, 10, 10, 97, 10, 7, 7, 7, 68, + 68, 68, 7, 7, 134, 134, 134, 10, 92, 80, + 10, 134, 134, 134, 134, 134, 134, 134, 134, 134, + 134, 134, 134, 134, 136, 136, 136, 110, 26, 46, + 46, 136, 136, 136, 136, 136, 136, 136, 136, 136, + 136, 136, 136, 136, 39, 145, 145, 39, 39, 39, + 39, 39, 39, 39, 39, 39, 39, 15, 10, 10, + 26, 17, 145, 26, 10, 10, 10, 10, 10, 15, + 85, 92, 15, 85, 69, 18, 145, 133, 36, 69, + 10, 5, 133, 69, 40, 86, 86, 86, 94, 92, + 92, 10, 86, 86, 86, 86, 86, 86, 86, 86, + 86, 86, 86, 86, 86, 14, 14, 14, 12, 14, + 135, 26, 26, 55, 14, 55, 144, 26, 26, 26, + 26, 26, 142, 14, 13, 14, 52, 146, 146, 140, + 140, 65, 12, 2, 2, 14, 54, 65, 14, 53, + 14, 117, 65, 13, 146, 13, 13, 13, 13, 88, + 13, 13, 13, 13, 13, 13, 12, 13, 65, 90, + 75, 12, 37, 37, 56, 56, 56, 75, 138, 20, + 65, 56, 56, 56, 56, 56, 56, 56, 56, 56, + 56, 56, 56, 56, 75, 75, 75, 75, 91, 24, + 75, 75, 30, 80, 80, 12, 76, 76, 76, 11, + 19, 28, 96, 82, 63, 23, 126, 63, 63, 63, + 63, 63, 63, 32, 63, 123, 72, 8, 8, 99, + 63, 79, 71, 113, 121, -1, 97, -1, 63, 63, + 63, 63, -1, 97, 63, 63, -1, -1, 16, -1, + 97, 97, 12, -1, -1, 63, -1, -1, 63, 16, + 16, 16, 16, 16, 16, -1, 16, 16, 16, 97, + 85, 85, 85, 110, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, 8, -1, -1, -1, -1, -1, + -1, 97, -1, -1, 97, 97, 97, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, 8, 8, -1, -1, -1, - -1, -1, -1, -1, -1, -1, 8, -1, 8, -1, - -1, 8, -1, 8, 8, -1, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - 8, -1, 8 + 8, 8, -1, -1, -1, -1, -1, -1, -1, -1, + -1, 8, -1, 8, -1, -1, 8, -1, 8, 8, + -1, 8, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, 8, -1, 8 ); protected $gotoBase = array( - 0, 0, -333, 0, 0, 201, 0, 203, 106, 0, - -143, 50, 9, -18, -177, -94, 123, 204, 145, 42, - 45, 0, 0, 2, 52, 0, -72, 0, 40, 0, - 54, 0, -6, -22, 0, 0, 121, -322, 0, -312, - 208, 0, 0, 0, 0, 0, 158, 0, 0, 81, - 0, 0, 233, 60, 53, 206, 88, 0, 0, 0, - 0, 0, 0, 107, 0, 19, 0, -58, -68, 0, - -14, -27, -448, 0, 128, -64, 0, 0, 3, -259, - 0, 22, 0, 0, 119, 12, 0, 44, 0, 55, - 73, -82, 0, 241, 0, 39, 129, 0, 1, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 131, - 0, 0, -8, 0, 0, 0, 38, 0, 0, 0, - -33, 0, -7, 0, 0, -1, 0, 0, 0, 0, - 0, 0, -74, -66, 242, -50, 0, 51, 0, -81, - 0, 249, 0, 240, -3, 74, 0, 0 + 0, 0, -283, 0, 0, 211, 0, 131, 106, 0, + -144, 60, -21, -19, -124, -185, 376, 199, 213, 49, + 50, 0, 0, 2, 53, 0, -91, 0, 47, 0, + 55, 0, -2, -23, 0, 0, 209, -276, 0, -371, + 205, 0, 0, 0, 0, 0, 134, 0, 0, 80, + 0, 0, 229, 54, 58, 238, 87, 0, 0, 0, + 0, 0, 0, 107, 0, -90, 0, -195, -102, -182, + 0, -15, -30, -443, 0, 63, 74, 0, 0, 4, + -242, 0, 24, 0, 0, 183, 8, 0, 44, 0, + 52, 75, -155, 0, 204, 0, 45, 129, 0, 3, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 157, 0, 0, 5, 0, 0, 0, 37, 0, 0, + 0, -34, 0, 1, 0, 0, -1, 0, 0, 0, + 0, 0, 0, -43, -73, 224, -53, 0, 56, 0, + -26, 0, 232, 0, 227, -64, 18, 0, 0 ); protected $gotoDefault = array( - -32768, 402, 585, 2, 586, 657, 665, 522, 419, 551, - 420, 447, 320, 739, 887, 758, 721, 722, 723, 309, - 346, 300, 307, 507, 497, 393, 708, 365, 700, 389, - 703, 364, 712, 135, 523, 398, 716, 1, 718, 453, - 749, 297, 726, 298, 526, 728, 460, 730, 731, 303, - 310, 311, 891, 468, 494, 741, 205, 462, 743, 296, - 744, 752, 317, 301, 375, 399, 391, 485, 518, 360, - 378, 491, 232, 470, 995, 775, 384, 373, 789, 282, - 797, 583, 805, 808, 421, 422, 382, 820, 383, 830, - 824, 1003, 377, 835, 366, 842, 1035, 368, 846, 849, - 341, 508, 334, 853, 854, 6, 858, 541, 542, 873, - 245, 395, 882, 509, 363, 897, 349, 964, 966, 455, - 390, 977, 372, 529, 400, 982, 1039, 361, 423, 379, - 272, 286, 248, 424, 441, 253, 425, 380, 1042, 1049, - 323, 1065, 442, 1075, 1083, 279, 474, 488 + -32768, 406, 581, 2, 582, 653, 661, 526, 423, 551, + 424, 451, 325, 735, 888, 755, 717, 718, 719, 311, + 351, 302, 309, 512, 502, 397, 704, 370, 696, 394, + 699, 369, 708, 136, 527, 402, 712, 1, 714, 457, + 746, 299, 722, 300, 530, 724, 464, 726, 727, 305, + 312, 313, 892, 472, 499, 739, 206, 466, 740, 298, + 741, 749, 322, 303, 380, 403, 317, 869, 490, 320, + 365, 383, 496, 220, 474, 996, 774, 389, 378, 788, + 284, 796, 579, 804, 807, 425, 426, 387, 819, 388, + 830, 824, 1004, 382, 835, 371, 842, 1036, 373, 846, + 849, 346, 513, 339, 853, 854, 6, 859, 542, 543, + 874, 246, 399, 883, 514, 368, 898, 354, 965, 967, + 459, 395, 978, 377, 533, 404, 983, 1040, 366, 427, + 384, 273, 288, 249, 428, 445, 254, 429, 385, 1043, + 1050, 328, 1066, 446, 1076, 1084, 280, 478, 493 ); protected $ruleToNonTerminal = array( @@ -742,21 +741,22 @@ 34, 35, 35, 36, 37, 37, 39, 38, 38, 38, 38, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, - 40, 40, 40, 40, 40, 16, 16, 59, 59, 62, - 62, 61, 60, 60, 53, 64, 64, 65, 65, 66, - 66, 17, 18, 18, 18, 69, 69, 69, 70, 70, - 73, 73, 71, 71, 75, 76, 76, 47, 47, 55, - 55, 58, 58, 58, 57, 77, 77, 78, 48, 48, - 48, 48, 79, 79, 80, 80, 81, 81, 45, 45, - 41, 41, 82, 43, 43, 83, 42, 42, 44, 44, - 54, 54, 54, 54, 67, 67, 86, 86, 87, 87, - 89, 89, 90, 90, 90, 88, 88, 68, 68, 91, - 91, 92, 92, 93, 93, 93, 50, 94, 94, 95, - 51, 97, 97, 98, 98, 72, 72, 99, 99, 99, - 99, 104, 104, 105, 105, 106, 106, 106, 106, 106, - 107, 108, 108, 103, 103, 100, 100, 102, 102, 110, - 110, 109, 109, 109, 109, 109, 109, 101, 111, 111, - 113, 112, 112, 52, 114, 114, 46, 46, 33, 33, + 40, 40, 40, 40, 40, 40, 16, 16, 59, 59, + 62, 62, 61, 60, 60, 53, 64, 64, 65, 65, + 66, 66, 67, 67, 17, 18, 18, 18, 70, 70, + 70, 71, 71, 74, 74, 72, 72, 76, 77, 77, + 47, 47, 55, 55, 58, 58, 58, 57, 78, 78, + 79, 48, 48, 48, 48, 80, 80, 81, 81, 82, + 82, 45, 45, 41, 41, 83, 43, 43, 84, 42, + 42, 44, 44, 54, 54, 54, 54, 68, 68, 87, + 87, 88, 88, 88, 90, 90, 91, 91, 91, 89, + 89, 69, 69, 92, 92, 93, 93, 94, 94, 94, + 50, 95, 95, 96, 51, 98, 98, 99, 99, 73, + 73, 100, 100, 100, 100, 100, 105, 105, 106, 106, + 107, 107, 107, 107, 107, 108, 109, 109, 104, 104, + 101, 101, 103, 103, 111, 111, 110, 110, 110, 110, + 110, 110, 102, 112, 112, 114, 113, 113, 52, 115, + 115, 46, 46, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, @@ -764,20 +764,19 @@ 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, - 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, - 33, 121, 115, 115, 120, 120, 123, 124, 124, 125, - 126, 126, 126, 74, 74, 63, 63, 63, 116, 116, - 116, 128, 128, 117, 117, 119, 119, 119, 122, 122, - 133, 133, 133, 85, 135, 135, 135, 118, 118, 118, - 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, - 118, 118, 118, 49, 49, 131, 131, 131, 127, 127, - 127, 136, 136, 136, 136, 136, 136, 56, 56, 56, - 96, 96, 96, 96, 139, 138, 130, 130, 130, 130, - 130, 130, 129, 129, 129, 137, 137, 137, 137, 84, - 140, 140, 141, 141, 141, 141, 141, 141, 141, 134, - 142, 142, 143, 143, 143, 143, 143, 132, 132, 132, - 132, 145, 146, 144, 144, 144, 144, 144, 144, 144, - 147, 147, 147, 147 + 33, 33, 33, 33, 33, 33, 122, 116, 116, 121, + 121, 124, 125, 125, 126, 127, 127, 127, 75, 75, + 63, 63, 63, 117, 117, 117, 129, 129, 118, 118, + 120, 120, 120, 123, 123, 134, 134, 134, 86, 136, + 136, 136, 119, 119, 119, 119, 119, 119, 119, 119, + 119, 119, 119, 119, 119, 119, 119, 119, 49, 49, + 132, 132, 132, 128, 128, 128, 137, 137, 137, 137, + 137, 137, 56, 56, 56, 97, 97, 97, 97, 140, + 139, 131, 131, 131, 131, 131, 131, 130, 130, 130, + 138, 138, 138, 138, 85, 141, 141, 142, 142, 142, + 142, 142, 142, 142, 135, 143, 143, 144, 144, 144, + 144, 144, 133, 133, 133, 133, 146, 147, 145, 145, + 145, 145, 145, 145, 145, 148, 148, 148, 148 ); protected $ruleToLength = array( @@ -796,43 +795,43 @@ 1, 3, 1, 2, 1, 2, 2, 3, 1, 3, 2, 3, 1, 3, 2, 0, 1, 1, 1, 1, 1, 3, 7, 10, 5, 7, 9, 5, 3, 3, - 3, 3, 3, 3, 1, 2, 5, 7, 9, 5, - 6, 3, 3, 2, 1, 1, 1, 0, 2, 1, - 3, 8, 0, 4, 2, 1, 3, 0, 1, 0, - 1, 10, 7, 6, 5, 1, 2, 2, 0, 2, - 0, 2, 0, 2, 2, 1, 3, 1, 4, 1, - 4, 1, 1, 4, 2, 1, 3, 3, 3, 4, - 4, 5, 0, 2, 4, 3, 1, 1, 1, 4, - 0, 2, 5, 0, 2, 6, 0, 2, 0, 3, - 1, 2, 1, 1, 2, 0, 1, 3, 4, 6, - 1, 2, 1, 1, 1, 0, 1, 0, 2, 2, - 4, 1, 3, 1, 2, 2, 2, 3, 1, 1, - 2, 3, 1, 1, 3, 2, 0, 3, 4, 9, - 3, 1, 3, 0, 2, 4, 5, 4, 4, 4, - 3, 1, 1, 1, 3, 1, 1, 0, 1, 1, - 2, 1, 1, 1, 1, 1, 1, 2, 1, 3, - 1, 1, 3, 2, 3, 1, 0, 1, 1, 3, - 3, 3, 4, 1, 2, 3, 3, 3, 3, 3, - 3, 3, 3, 3, 3, 3, 3, 2, 2, 2, - 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, - 3, 3, 3, 3, 3, 3, 3, 3, 2, 2, - 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, - 3, 3, 3, 5, 4, 3, 4, 4, 2, 2, - 4, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 1, 3, 2, 1, 2, 4, 2, 10, - 11, 7, 3, 2, 0, 4, 2, 1, 3, 2, - 2, 2, 4, 1, 1, 1, 2, 3, 1, 1, - 1, 1, 1, 0, 3, 0, 1, 1, 0, 1, - 1, 3, 3, 3, 4, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, - 2, 3, 3, 0, 1, 1, 3, 1, 1, 3, - 1, 1, 4, 4, 4, 1, 4, 1, 1, 3, - 1, 4, 2, 2, 1, 3, 1, 4, 4, 3, - 3, 3, 1, 3, 1, 1, 3, 1, 1, 4, - 3, 1, 1, 2, 1, 3, 4, 3, 0, 1, - 3, 1, 3, 1, 4, 2, 0, 2, 2, 1, - 2, 1, 1, 1, 4, 3, 3, 3, 6, 3, - 1, 1, 2, 1 + 3, 3, 3, 3, 1, 2, 5, 7, 9, 6, + 5, 6, 3, 3, 2, 1, 1, 1, 0, 2, + 1, 3, 8, 0, 4, 2, 1, 3, 0, 1, + 0, 1, 3, 1, 8, 7, 6, 5, 1, 2, + 2, 0, 2, 0, 2, 0, 2, 2, 1, 3, + 1, 4, 1, 4, 1, 1, 4, 2, 1, 3, + 3, 3, 4, 4, 5, 0, 2, 4, 3, 1, + 1, 1, 4, 0, 2, 5, 0, 2, 6, 0, + 2, 0, 3, 1, 2, 1, 1, 2, 0, 1, + 3, 4, 6, 4, 1, 2, 1, 1, 1, 0, + 1, 0, 2, 2, 4, 1, 3, 1, 2, 2, + 2, 3, 1, 1, 2, 3, 1, 1, 3, 2, + 0, 3, 4, 9, 3, 1, 1, 3, 0, 2, + 4, 5, 4, 4, 4, 3, 1, 1, 1, 1, + 1, 1, 0, 1, 1, 2, 1, 1, 1, 1, + 1, 1, 2, 1, 3, 1, 1, 3, 2, 3, + 1, 0, 1, 1, 3, 3, 3, 4, 1, 2, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 2, 2, 2, 2, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 2, 2, 2, 2, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 5, 4, + 3, 4, 4, 2, 2, 4, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 1, 3, 2, + 1, 2, 4, 2, 8, 9, 7, 3, 2, 0, + 4, 2, 1, 3, 2, 2, 2, 4, 1, 1, + 1, 2, 3, 1, 1, 1, 1, 1, 0, 3, + 0, 1, 1, 0, 1, 1, 3, 3, 3, 4, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 3, 2, 3, 3, 0, 1, + 1, 3, 1, 1, 3, 1, 1, 4, 4, 4, + 1, 4, 1, 1, 3, 1, 4, 2, 2, 1, + 3, 1, 4, 4, 3, 3, 3, 1, 3, 1, + 1, 3, 1, 1, 4, 3, 1, 1, 2, 1, + 3, 4, 3, 0, 1, 3, 1, 3, 1, 4, + 2, 0, 2, 2, 1, 2, 1, 1, 1, 4, + 3, 3, 3, 6, 3, 1, 1, 2, 1 ); protected function initReduceCallbacks() { @@ -1330,200 +1329,200 @@ $this->semValue = new Stmt\Foreach_($this->semStack[$stackPos-(9-3)], $this->semStack[$stackPos-(9-7)][0], ['keyVar' => $this->semStack[$stackPos-(9-5)], 'byRef' => $this->semStack[$stackPos-(9-7)][1], 'stmts' => $this->semStack[$stackPos-(9-9)]], $this->startAttributeStack[$stackPos-(9-1)] + $this->endAttributes); }, 159 => function ($stackPos) { + $this->semValue = new Stmt\Foreach_($this->semStack[$stackPos-(6-3)], new Expr\Error($this->startAttributeStack[$stackPos-(6-4)] + $this->endAttributeStack[$stackPos-(6-4)]), ['stmts' => $this->semStack[$stackPos-(6-6)]], $this->startAttributeStack[$stackPos-(6-1)] + $this->endAttributes); + }, + 160 => function ($stackPos) { $this->semValue = new Stmt\Declare_($this->semStack[$stackPos-(5-3)], $this->semStack[$stackPos-(5-5)], $this->startAttributeStack[$stackPos-(5-1)] + $this->endAttributes); }, - 160 => function ($stackPos) { + 161 => function ($stackPos) { $this->semValue = new Stmt\TryCatch($this->semStack[$stackPos-(6-3)], $this->semStack[$stackPos-(6-5)], $this->semStack[$stackPos-(6-6)], $this->startAttributeStack[$stackPos-(6-1)] + $this->endAttributes); $this->checkTryCatch($this->semValue); }, - 161 => function ($stackPos) { + 162 => function ($stackPos) { $this->semValue = new Stmt\Throw_($this->semStack[$stackPos-(3-2)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); }, - 162 => function ($stackPos) { + 163 => function ($stackPos) { $this->semValue = new Stmt\Goto_($this->semStack[$stackPos-(3-2)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); }, - 163 => function ($stackPos) { + 164 => function ($stackPos) { $this->semValue = new Stmt\Label($this->semStack[$stackPos-(2-1)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); }, - 164 => function ($stackPos) { + 165 => function ($stackPos) { $this->semValue = array(); /* means: no statement */ }, - 165 => function ($stackPos) { + 166 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos-(1-1)]; }, - 166 => function ($stackPos) { + 167 => function ($stackPos) { $startAttributes = $this->startAttributeStack[$stackPos-(1-1)]; if (isset($startAttributes['comments'])) { $this->semValue = new Stmt\Nop($startAttributes + $this->endAttributes); } else { $this->semValue = null; }; if ($this->semValue === null) $this->semValue = array(); /* means: no statement */ }, - 167 => function ($stackPos) { + 168 => function ($stackPos) { $this->semValue = array(); }, - 168 => function ($stackPos) { + 169 => function ($stackPos) { $this->semStack[$stackPos-(2-1)][] = $this->semStack[$stackPos-(2-2)]; $this->semValue = $this->semStack[$stackPos-(2-1)]; }, - 169 => function ($stackPos) { + 170 => function ($stackPos) { $this->semValue = array($this->semStack[$stackPos-(1-1)]); }, - 170 => function ($stackPos) { + 171 => function ($stackPos) { $this->semStack[$stackPos-(3-1)][] = $this->semStack[$stackPos-(3-3)]; $this->semValue = $this->semStack[$stackPos-(3-1)]; }, - 171 => function ($stackPos) { + 172 => function ($stackPos) { $this->semValue = new Stmt\Catch_($this->semStack[$stackPos-(8-3)], $this->semStack[$stackPos-(8-4)], $this->semStack[$stackPos-(8-7)], $this->startAttributeStack[$stackPos-(8-1)] + $this->endAttributes); }, - 172 => function ($stackPos) { + 173 => function ($stackPos) { $this->semValue = null; }, - 173 => function ($stackPos) { + 174 => function ($stackPos) { $this->semValue = new Stmt\Finally_($this->semStack[$stackPos-(4-3)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes); }, - 174 => function ($stackPos) { + 175 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos-(2-1)]; }, - 175 => function ($stackPos) { + 176 => function ($stackPos) { $this->semValue = array($this->semStack[$stackPos-(1-1)]); }, - 176 => function ($stackPos) { + 177 => function ($stackPos) { $this->semStack[$stackPos-(3-1)][] = $this->semStack[$stackPos-(3-3)]; $this->semValue = $this->semStack[$stackPos-(3-1)]; }, - 177 => function ($stackPos) { + 178 => function ($stackPos) { $this->semValue = false; }, - 178 => function ($stackPos) { + 179 => function ($stackPos) { $this->semValue = true; }, - 179 => function ($stackPos) { + 180 => function ($stackPos) { $this->semValue = false; }, - 180 => function ($stackPos) { + 181 => function ($stackPos) { $this->semValue = true; }, - 181 => function ($stackPos) { - $this->semValue = new Stmt\Function_($this->semStack[$stackPos-(10-3)], ['byRef' => $this->semStack[$stackPos-(10-2)], 'params' => $this->semStack[$stackPos-(10-5)], 'returnType' => $this->semStack[$stackPos-(10-7)], 'stmts' => $this->semStack[$stackPos-(10-9)]], $this->startAttributeStack[$stackPos-(10-1)] + $this->endAttributes); - }, 182 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(3-2)]; + }, + 183 => function ($stackPos) { + $this->semValue = []; + }, + 184 => function ($stackPos) { + $this->semValue = new Stmt\Function_($this->semStack[$stackPos-(8-3)], ['byRef' => $this->semStack[$stackPos-(8-2)], 'params' => $this->semStack[$stackPos-(8-5)], 'returnType' => $this->semStack[$stackPos-(8-7)], 'stmts' => $this->semStack[$stackPos-(8-8)]], $this->startAttributeStack[$stackPos-(8-1)] + $this->endAttributes); + }, + 185 => function ($stackPos) { $this->semValue = new Stmt\Class_($this->semStack[$stackPos-(7-2)], ['type' => $this->semStack[$stackPos-(7-1)], 'extends' => $this->semStack[$stackPos-(7-3)], 'implements' => $this->semStack[$stackPos-(7-4)], 'stmts' => $this->semStack[$stackPos-(7-6)]], $this->startAttributeStack[$stackPos-(7-1)] + $this->endAttributes); $this->checkClass($this->semValue, $stackPos-(7-2)); }, - 183 => function ($stackPos) { + 186 => function ($stackPos) { $this->semValue = new Stmt\Interface_($this->semStack[$stackPos-(6-2)], ['extends' => $this->semStack[$stackPos-(6-3)], 'stmts' => $this->semStack[$stackPos-(6-5)]], $this->startAttributeStack[$stackPos-(6-1)] + $this->endAttributes); $this->checkInterface($this->semValue, $stackPos-(6-2)); }, - 184 => function ($stackPos) { + 187 => function ($stackPos) { $this->semValue = new Stmt\Trait_($this->semStack[$stackPos-(5-2)], ['stmts' => $this->semStack[$stackPos-(5-4)]], $this->startAttributeStack[$stackPos-(5-1)] + $this->endAttributes); }, - 185 => function ($stackPos) { + 188 => function ($stackPos) { $this->semValue = 0; }, - 186 => function ($stackPos) { + 189 => function ($stackPos) { $this->semValue = Stmt\Class_::MODIFIER_ABSTRACT; }, - 187 => function ($stackPos) { + 190 => function ($stackPos) { $this->semValue = Stmt\Class_::MODIFIER_FINAL; }, - 188 => function ($stackPos) { + 191 => function ($stackPos) { $this->semValue = null; }, - 189 => function ($stackPos) { + 192 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos-(2-2)]; }, - 190 => function ($stackPos) { + 193 => function ($stackPos) { $this->semValue = array(); }, - 191 => function ($stackPos) { + 194 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos-(2-2)]; }, - 192 => function ($stackPos) { + 195 => function ($stackPos) { $this->semValue = array(); }, - 193 => function ($stackPos) { + 196 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos-(2-2)]; }, - 194 => function ($stackPos) { + 197 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos-(2-1)]; }, - 195 => function ($stackPos) { + 198 => function ($stackPos) { $this->semValue = array($this->semStack[$stackPos-(1-1)]); }, - 196 => function ($stackPos) { + 199 => function ($stackPos) { $this->semStack[$stackPos-(3-1)][] = $this->semStack[$stackPos-(3-3)]; $this->semValue = $this->semStack[$stackPos-(3-1)]; }, - 197 => function ($stackPos) { + 200 => function ($stackPos) { $this->semValue = is_array($this->semStack[$stackPos-(1-1)]) ? $this->semStack[$stackPos-(1-1)] : array($this->semStack[$stackPos-(1-1)]); }, - 198 => function ($stackPos) { + 201 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos-(4-2)]; }, - 199 => function ($stackPos) { + 202 => function ($stackPos) { $this->semValue = is_array($this->semStack[$stackPos-(1-1)]) ? $this->semStack[$stackPos-(1-1)] : array($this->semStack[$stackPos-(1-1)]); }, - 200 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos-(4-2)]; - }, - 201 => function ($stackPos) { - $this->semValue = is_array($this->semStack[$stackPos-(1-1)]) ? $this->semStack[$stackPos-(1-1)] : array($this->semStack[$stackPos-(1-1)]); - }, - 202 => function ($stackPos) { - $this->semValue = null; - }, 203 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos-(4-2)]; }, 204 => function ($stackPos) { + $this->semValue = is_array($this->semStack[$stackPos-(1-1)]) ? $this->semStack[$stackPos-(1-1)] : array($this->semStack[$stackPos-(1-1)]); + }, + 205 => function ($stackPos) { + $this->semValue = null; + }, + 206 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(4-2)]; + }, + 207 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos-(2-1)]; }, - 205 => function ($stackPos) { + 208 => function ($stackPos) { $this->semValue = array($this->semStack[$stackPos-(1-1)]); }, - 206 => function ($stackPos) { + 209 => function ($stackPos) { $this->semStack[$stackPos-(3-1)][] = $this->semStack[$stackPos-(3-3)]; $this->semValue = $this->semStack[$stackPos-(3-1)]; }, - 207 => function ($stackPos) { + 210 => function ($stackPos) { $this->semValue = new Stmt\DeclareDeclare($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); }, - 208 => function ($stackPos) { + 211 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos-(3-2)]; }, - 209 => function ($stackPos) { + 212 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos-(4-3)]; }, - 210 => function ($stackPos) { + 213 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos-(4-2)]; }, - 211 => function ($stackPos) { + 214 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos-(5-3)]; }, - 212 => function ($stackPos) { + 215 => function ($stackPos) { $this->semValue = array(); }, - 213 => function ($stackPos) { + 216 => function ($stackPos) { $this->semStack[$stackPos-(2-1)][] = $this->semStack[$stackPos-(2-2)]; $this->semValue = $this->semStack[$stackPos-(2-1)]; }, - 214 => function ($stackPos) { + 217 => function ($stackPos) { $this->semValue = new Stmt\Case_($this->semStack[$stackPos-(4-2)], $this->semStack[$stackPos-(4-4)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes); }, - 215 => function ($stackPos) { + 218 => function ($stackPos) { $this->semValue = new Stmt\Case_(null, $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); }, - 216 => function ($stackPos) { + 219 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos]; }, - 217 => function ($stackPos) { + 220 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos]; }, - 218 => function ($stackPos) { + 221 => function ($stackPos) { $this->semValue = is_array($this->semStack[$stackPos-(1-1)]) ? $this->semStack[$stackPos-(1-1)] : array($this->semStack[$stackPos-(1-1)]); }, - 219 => function ($stackPos) { + 222 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos-(4-2)]; }, - 220 => function ($stackPos) { - $this->semValue = array(); - }, - 221 => function ($stackPos) { - $this->semStack[$stackPos-(2-1)][] = $this->semStack[$stackPos-(2-2)]; $this->semValue = $this->semStack[$stackPos-(2-1)]; - }, - 222 => function ($stackPos) { - $this->semValue = new Stmt\ElseIf_($this->semStack[$stackPos-(5-3)], is_array($this->semStack[$stackPos-(5-5)]) ? $this->semStack[$stackPos-(5-5)] : array($this->semStack[$stackPos-(5-5)]), $this->startAttributeStack[$stackPos-(5-1)] + $this->endAttributes); - }, 223 => function ($stackPos) { $this->semValue = array(); }, @@ -1531,110 +1530,110 @@ $this->semStack[$stackPos-(2-1)][] = $this->semStack[$stackPos-(2-2)]; $this->semValue = $this->semStack[$stackPos-(2-1)]; }, 225 => function ($stackPos) { + $this->semValue = new Stmt\ElseIf_($this->semStack[$stackPos-(5-3)], is_array($this->semStack[$stackPos-(5-5)]) ? $this->semStack[$stackPos-(5-5)] : array($this->semStack[$stackPos-(5-5)]), $this->startAttributeStack[$stackPos-(5-1)] + $this->endAttributes); + }, + 226 => function ($stackPos) { + $this->semValue = array(); + }, + 227 => function ($stackPos) { + $this->semStack[$stackPos-(2-1)][] = $this->semStack[$stackPos-(2-2)]; $this->semValue = $this->semStack[$stackPos-(2-1)]; + }, + 228 => function ($stackPos) { $this->semValue = new Stmt\ElseIf_($this->semStack[$stackPos-(6-3)], $this->semStack[$stackPos-(6-6)], $this->startAttributeStack[$stackPos-(6-1)] + $this->endAttributes); }, - 226 => function ($stackPos) { + 229 => function ($stackPos) { $this->semValue = null; }, - 227 => function ($stackPos) { + 230 => function ($stackPos) { $this->semValue = new Stmt\Else_(is_array($this->semStack[$stackPos-(2-2)]) ? $this->semStack[$stackPos-(2-2)] : array($this->semStack[$stackPos-(2-2)]), $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); }, - 228 => function ($stackPos) { + 231 => function ($stackPos) { $this->semValue = null; }, - 229 => function ($stackPos) { + 232 => function ($stackPos) { $this->semValue = new Stmt\Else_($this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); }, - 230 => function ($stackPos) { - $this->semValue = array($this->semStack[$stackPos-(1-1)], false); - }, - 231 => function ($stackPos) { - $this->semValue = array($this->semStack[$stackPos-(2-2)], true); - }, - 232 => function ($stackPos) { - $this->semValue = array($this->semStack[$stackPos-(1-1)], false); - }, 233 => function ($stackPos) { $this->semValue = array($this->semStack[$stackPos-(1-1)], false); }, 234 => function ($stackPos) { + $this->semValue = array($this->semStack[$stackPos-(2-2)], true); + }, + 235 => function ($stackPos) { + $this->semValue = array($this->semStack[$stackPos-(1-1)], false); + }, + 236 => function ($stackPos) { + $this->semValue = array($this->semStack[$stackPos-(1-1)], false); + }, + 237 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos-(2-1)]; }, - 235 => function ($stackPos) { + 238 => function ($stackPos) { $this->semValue = array(); }, - 236 => function ($stackPos) { + 239 => function ($stackPos) { $this->semValue = array($this->semStack[$stackPos-(1-1)]); }, - 237 => function ($stackPos) { + 240 => function ($stackPos) { $this->semStack[$stackPos-(3-1)][] = $this->semStack[$stackPos-(3-3)]; $this->semValue = $this->semStack[$stackPos-(3-1)]; }, - 238 => function ($stackPos) { + 241 => function ($stackPos) { $this->semValue = new Node\Param($this->semStack[$stackPos-(4-4)], null, $this->semStack[$stackPos-(4-1)], $this->semStack[$stackPos-(4-2)], $this->semStack[$stackPos-(4-3)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes); $this->checkParam($this->semValue); }, - 239 => function ($stackPos) { + 242 => function ($stackPos) { $this->semValue = new Node\Param($this->semStack[$stackPos-(6-4)], $this->semStack[$stackPos-(6-6)], $this->semStack[$stackPos-(6-1)], $this->semStack[$stackPos-(6-2)], $this->semStack[$stackPos-(6-3)], $this->startAttributeStack[$stackPos-(6-1)] + $this->endAttributes); $this->checkParam($this->semValue); }, - 240 => function ($stackPos) { + 243 => function ($stackPos) { + $this->semValue = new Node\Param(new Expr\Error($this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes), null, $this->semStack[$stackPos-(4-1)], $this->semStack[$stackPos-(4-2)], $this->semStack[$stackPos-(4-3)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes); + }, + 244 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos-(1-1)]; }, - 241 => function ($stackPos) { + 245 => function ($stackPos) { $this->semValue = new Node\NullableType($this->semStack[$stackPos-(2-2)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); }, - 242 => function ($stackPos) { + 246 => function ($stackPos) { $this->semValue = $this->handleBuiltinTypes($this->semStack[$stackPos-(1-1)]); }, - 243 => function ($stackPos) { + 247 => function ($stackPos) { $this->semValue = new Node\Identifier('array', $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); }, - 244 => function ($stackPos) { + 248 => function ($stackPos) { $this->semValue = new Node\Identifier('callable', $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); }, - 245 => function ($stackPos) { + 249 => function ($stackPos) { $this->semValue = null; }, - 246 => function ($stackPos) { + 250 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos-(1-1)]; }, - 247 => function ($stackPos) { + 251 => function ($stackPos) { $this->semValue = null; }, - 248 => function ($stackPos) { + 252 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos-(2-2)]; }, - 249 => function ($stackPos) { + 253 => function ($stackPos) { $this->semValue = array(); }, - 250 => function ($stackPos) { + 254 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos-(4-2)]; }, - 251 => function ($stackPos) { + 255 => function ($stackPos) { $this->semValue = array($this->semStack[$stackPos-(1-1)]); }, - 252 => function ($stackPos) { + 256 => function ($stackPos) { $this->semStack[$stackPos-(3-1)][] = $this->semStack[$stackPos-(3-3)]; $this->semValue = $this->semStack[$stackPos-(3-1)]; }, - 253 => function ($stackPos) { + 257 => function ($stackPos) { $this->semValue = new Node\Arg($this->semStack[$stackPos-(1-1)], false, false, $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); }, - 254 => function ($stackPos) { + 258 => function ($stackPos) { $this->semValue = new Node\Arg($this->semStack[$stackPos-(2-2)], true, false, $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); }, - 255 => function ($stackPos) { + 259 => function ($stackPos) { $this->semValue = new Node\Arg($this->semStack[$stackPos-(2-2)], false, true, $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); }, - 256 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos-(2-1)]; - }, - 257 => function ($stackPos) { - $this->semStack[$stackPos-(3-1)][] = $this->semStack[$stackPos-(3-3)]; $this->semValue = $this->semStack[$stackPos-(3-1)]; - }, - 258 => function ($stackPos) { - $this->semValue = array($this->semStack[$stackPos-(1-1)]); - }, - 259 => function ($stackPos) { - $this->semValue = new Expr\Variable($this->semStack[$stackPos-(1-1)], $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); - }, 260 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos-(2-1)]; }, @@ -1645,767 +1644,782 @@ $this->semValue = array($this->semStack[$stackPos-(1-1)]); }, 263 => function ($stackPos) { + $this->semValue = new Expr\Variable($this->semStack[$stackPos-(1-1)], $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); + }, + 264 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(2-1)]; + }, + 265 => function ($stackPos) { + $this->semStack[$stackPos-(3-1)][] = $this->semStack[$stackPos-(3-3)]; $this->semValue = $this->semStack[$stackPos-(3-1)]; + }, + 266 => function ($stackPos) { + $this->semValue = array($this->semStack[$stackPos-(1-1)]); + }, + 267 => function ($stackPos) { $this->semValue = new Stmt\StaticVar($this->semStack[$stackPos-(1-1)], null, $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); }, - 264 => function ($stackPos) { + 268 => function ($stackPos) { $this->semValue = new Stmt\StaticVar($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); }, - 265 => function ($stackPos) { - $this->semStack[$stackPos-(2-1)][] = $this->semStack[$stackPos-(2-2)]; $this->semValue = $this->semStack[$stackPos-(2-1)]; - }, - 266 => function ($stackPos) { + 269 => function ($stackPos) { + if ($this->semStack[$stackPos-(2-2)] !== null) { $this->semStack[$stackPos-(2-1)][] = $this->semStack[$stackPos-(2-2)]; $this->semValue = $this->semStack[$stackPos-(2-1)]; } + }, + 270 => function ($stackPos) { $this->semValue = array(); }, - 267 => function ($stackPos) { + 271 => function ($stackPos) { $this->semValue = new Stmt\Property($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-2)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); $this->checkProperty($this->semValue, $stackPos-(3-1)); }, - 268 => function ($stackPos) { + 272 => function ($stackPos) { $this->semValue = new Stmt\ClassConst($this->semStack[$stackPos-(4-3)], $this->semStack[$stackPos-(4-1)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes); $this->checkClassConst($this->semValue, $stackPos-(4-1)); }, - 269 => function ($stackPos) { + 273 => function ($stackPos) { $this->semValue = new Stmt\ClassMethod($this->semStack[$stackPos-(9-4)], ['type' => $this->semStack[$stackPos-(9-1)], 'byRef' => $this->semStack[$stackPos-(9-3)], 'params' => $this->semStack[$stackPos-(9-6)], 'returnType' => $this->semStack[$stackPos-(9-8)], 'stmts' => $this->semStack[$stackPos-(9-9)]], $this->startAttributeStack[$stackPos-(9-1)] + $this->endAttributes); $this->checkClassMethod($this->semValue, $stackPos-(9-1)); }, - 270 => function ($stackPos) { + 274 => function ($stackPos) { $this->semValue = new Stmt\TraitUse($this->semStack[$stackPos-(3-2)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); }, - 271 => function ($stackPos) { + 275 => function ($stackPos) { + $this->semValue = null; /* will be skipped */ + }, + 276 => function ($stackPos) { $this->semValue = array(); }, - 272 => function ($stackPos) { + 277 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos-(3-2)]; }, - 273 => function ($stackPos) { + 278 => function ($stackPos) { $this->semValue = array(); }, - 274 => function ($stackPos) { + 279 => function ($stackPos) { $this->semStack[$stackPos-(2-1)][] = $this->semStack[$stackPos-(2-2)]; $this->semValue = $this->semStack[$stackPos-(2-1)]; }, - 275 => function ($stackPos) { + 280 => function ($stackPos) { $this->semValue = new Stmt\TraitUseAdaptation\Precedence($this->semStack[$stackPos-(4-1)][0], $this->semStack[$stackPos-(4-1)][1], $this->semStack[$stackPos-(4-3)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes); }, - 276 => function ($stackPos) { + 281 => function ($stackPos) { $this->semValue = new Stmt\TraitUseAdaptation\Alias($this->semStack[$stackPos-(5-1)][0], $this->semStack[$stackPos-(5-1)][1], $this->semStack[$stackPos-(5-3)], $this->semStack[$stackPos-(5-4)], $this->startAttributeStack[$stackPos-(5-1)] + $this->endAttributes); }, - 277 => function ($stackPos) { + 282 => function ($stackPos) { $this->semValue = new Stmt\TraitUseAdaptation\Alias($this->semStack[$stackPos-(4-1)][0], $this->semStack[$stackPos-(4-1)][1], $this->semStack[$stackPos-(4-3)], null, $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes); }, - 278 => function ($stackPos) { + 283 => function ($stackPos) { $this->semValue = new Stmt\TraitUseAdaptation\Alias($this->semStack[$stackPos-(4-1)][0], $this->semStack[$stackPos-(4-1)][1], null, $this->semStack[$stackPos-(4-3)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes); }, - 279 => function ($stackPos) { + 284 => function ($stackPos) { $this->semValue = new Stmt\TraitUseAdaptation\Alias($this->semStack[$stackPos-(4-1)][0], $this->semStack[$stackPos-(4-1)][1], null, $this->semStack[$stackPos-(4-3)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes); }, - 280 => function ($stackPos) { + 285 => function ($stackPos) { $this->semValue = array($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)]); }, - 281 => function ($stackPos) { + 286 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos-(1-1)]; }, - 282 => function ($stackPos) { + 287 => function ($stackPos) { $this->semValue = array(null, $this->semStack[$stackPos-(1-1)]); }, - 283 => function ($stackPos) { + 288 => function ($stackPos) { $this->semValue = null; }, - 284 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos-(3-2)]; - }, - 285 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos-(1-1)]; - }, - 286 => function ($stackPos) { - $this->semValue = 0; - }, - 287 => function ($stackPos) { - $this->semValue = 0; - }, - 288 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos-(1-1)]; - }, 289 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos-(1-1)]; }, 290 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(1-1)]; + }, + 291 => function ($stackPos) { + $this->semValue = 0; + }, + 292 => function ($stackPos) { + $this->semValue = 0; + }, + 293 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(1-1)]; + }, + 294 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(1-1)]; + }, + 295 => function ($stackPos) { $this->checkModifier($this->semStack[$stackPos-(2-1)], $this->semStack[$stackPos-(2-2)], $stackPos-(2-2)); $this->semValue = $this->semStack[$stackPos-(2-1)] | $this->semStack[$stackPos-(2-2)]; }, - 291 => function ($stackPos) { + 296 => function ($stackPos) { $this->semValue = Stmt\Class_::MODIFIER_PUBLIC; }, - 292 => function ($stackPos) { + 297 => function ($stackPos) { $this->semValue = Stmt\Class_::MODIFIER_PROTECTED; }, - 293 => function ($stackPos) { + 298 => function ($stackPos) { $this->semValue = Stmt\Class_::MODIFIER_PRIVATE; }, - 294 => function ($stackPos) { + 299 => function ($stackPos) { $this->semValue = Stmt\Class_::MODIFIER_STATIC; }, - 295 => function ($stackPos) { + 300 => function ($stackPos) { $this->semValue = Stmt\Class_::MODIFIER_ABSTRACT; }, - 296 => function ($stackPos) { + 301 => function ($stackPos) { $this->semValue = Stmt\Class_::MODIFIER_FINAL; }, - 297 => function ($stackPos) { + 302 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos-(2-1)]; }, - 298 => function ($stackPos) { + 303 => function ($stackPos) { $this->semValue = array($this->semStack[$stackPos-(1-1)]); }, - 299 => function ($stackPos) { - $this->semStack[$stackPos-(3-1)][] = $this->semStack[$stackPos-(3-3)]; $this->semValue = $this->semStack[$stackPos-(3-1)]; - }, - 300 => function ($stackPos) { - $this->semValue = new Node\VarLikeIdentifier(substr($this->semStack[$stackPos-(1-1)], 1), $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); - }, - 301 => function ($stackPos) { - $this->semValue = new Stmt\PropertyProperty($this->semStack[$stackPos-(1-1)], null, $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); - }, - 302 => function ($stackPos) { - $this->semValue = new Stmt\PropertyProperty($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); - }, - 303 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos-(2-1)]; - }, 304 => function ($stackPos) { $this->semStack[$stackPos-(3-1)][] = $this->semStack[$stackPos-(3-3)]; $this->semValue = $this->semStack[$stackPos-(3-1)]; }, 305 => function ($stackPos) { + $this->semValue = new Node\VarLikeIdentifier(substr($this->semStack[$stackPos-(1-1)], 1), $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); + }, + 306 => function ($stackPos) { + $this->semValue = new Stmt\PropertyProperty($this->semStack[$stackPos-(1-1)], null, $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); + }, + 307 => function ($stackPos) { + $this->semValue = new Stmt\PropertyProperty($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 308 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(2-1)]; + }, + 309 => function ($stackPos) { + $this->semStack[$stackPos-(3-1)][] = $this->semStack[$stackPos-(3-3)]; $this->semValue = $this->semStack[$stackPos-(3-1)]; + }, + 310 => function ($stackPos) { $this->semValue = array($this->semStack[$stackPos-(1-1)]); }, - 306 => function ($stackPos) { + 311 => function ($stackPos) { $this->semValue = array(); }, - 307 => function ($stackPos) { + 312 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos-(1-1)]; }, - 308 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos-(1-1)]; - }, - 309 => function ($stackPos) { - $this->semValue = new Expr\Assign($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); - }, - 310 => function ($stackPos) { - $this->semValue = new Expr\Assign($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); - }, - 311 => function ($stackPos) { - $this->semValue = new Expr\Assign($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); - }, - 312 => function ($stackPos) { - $this->semValue = new Expr\AssignRef($this->semStack[$stackPos-(4-1)], $this->semStack[$stackPos-(4-4)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes); - }, 313 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos-(1-1)]; }, 314 => function ($stackPos) { + $this->semValue = new Expr\Assign($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 315 => function ($stackPos) { + $this->semValue = new Expr\Assign($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 316 => function ($stackPos) { + $this->semValue = new Expr\Assign($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 317 => function ($stackPos) { + $this->semValue = new Expr\AssignRef($this->semStack[$stackPos-(4-1)], $this->semStack[$stackPos-(4-4)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes); + }, + 318 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(1-1)]; + }, + 319 => function ($stackPos) { $this->semValue = new Expr\Clone_($this->semStack[$stackPos-(2-2)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); }, - 315 => function ($stackPos) { + 320 => function ($stackPos) { $this->semValue = new Expr\AssignOp\Plus($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); }, - 316 => function ($stackPos) { + 321 => function ($stackPos) { $this->semValue = new Expr\AssignOp\Minus($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); }, - 317 => function ($stackPos) { + 322 => function ($stackPos) { $this->semValue = new Expr\AssignOp\Mul($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); }, - 318 => function ($stackPos) { + 323 => function ($stackPos) { $this->semValue = new Expr\AssignOp\Div($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); }, - 319 => function ($stackPos) { + 324 => function ($stackPos) { $this->semValue = new Expr\AssignOp\Concat($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); }, - 320 => function ($stackPos) { + 325 => function ($stackPos) { $this->semValue = new Expr\AssignOp\Mod($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); }, - 321 => function ($stackPos) { + 326 => function ($stackPos) { $this->semValue = new Expr\AssignOp\BitwiseAnd($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); }, - 322 => function ($stackPos) { + 327 => function ($stackPos) { $this->semValue = new Expr\AssignOp\BitwiseOr($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); }, - 323 => function ($stackPos) { + 328 => function ($stackPos) { $this->semValue = new Expr\AssignOp\BitwiseXor($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); }, - 324 => function ($stackPos) { + 329 => function ($stackPos) { $this->semValue = new Expr\AssignOp\ShiftLeft($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); }, - 325 => function ($stackPos) { + 330 => function ($stackPos) { $this->semValue = new Expr\AssignOp\ShiftRight($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); }, - 326 => function ($stackPos) { + 331 => function ($stackPos) { $this->semValue = new Expr\AssignOp\Pow($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); }, - 327 => function ($stackPos) { + 332 => function ($stackPos) { $this->semValue = new Expr\PostInc($this->semStack[$stackPos-(2-1)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); }, - 328 => function ($stackPos) { + 333 => function ($stackPos) { $this->semValue = new Expr\PreInc($this->semStack[$stackPos-(2-2)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); }, - 329 => function ($stackPos) { + 334 => function ($stackPos) { $this->semValue = new Expr\PostDec($this->semStack[$stackPos-(2-1)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); }, - 330 => function ($stackPos) { + 335 => function ($stackPos) { $this->semValue = new Expr\PreDec($this->semStack[$stackPos-(2-2)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); }, - 331 => function ($stackPos) { + 336 => function ($stackPos) { $this->semValue = new Expr\BinaryOp\BooleanOr($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); }, - 332 => function ($stackPos) { + 337 => function ($stackPos) { $this->semValue = new Expr\BinaryOp\BooleanAnd($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); }, - 333 => function ($stackPos) { + 338 => function ($stackPos) { $this->semValue = new Expr\BinaryOp\LogicalOr($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); }, - 334 => function ($stackPos) { + 339 => function ($stackPos) { $this->semValue = new Expr\BinaryOp\LogicalAnd($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); }, - 335 => function ($stackPos) { + 340 => function ($stackPos) { $this->semValue = new Expr\BinaryOp\LogicalXor($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); }, - 336 => function ($stackPos) { + 341 => function ($stackPos) { $this->semValue = new Expr\BinaryOp\BitwiseOr($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); }, - 337 => function ($stackPos) { + 342 => function ($stackPos) { $this->semValue = new Expr\BinaryOp\BitwiseAnd($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); }, - 338 => function ($stackPos) { + 343 => function ($stackPos) { $this->semValue = new Expr\BinaryOp\BitwiseXor($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); }, - 339 => function ($stackPos) { + 344 => function ($stackPos) { $this->semValue = new Expr\BinaryOp\Concat($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); }, - 340 => function ($stackPos) { + 345 => function ($stackPos) { $this->semValue = new Expr\BinaryOp\Plus($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); }, - 341 => function ($stackPos) { + 346 => function ($stackPos) { $this->semValue = new Expr\BinaryOp\Minus($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); }, - 342 => function ($stackPos) { + 347 => function ($stackPos) { $this->semValue = new Expr\BinaryOp\Mul($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); }, - 343 => function ($stackPos) { + 348 => function ($stackPos) { $this->semValue = new Expr\BinaryOp\Div($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); }, - 344 => function ($stackPos) { + 349 => function ($stackPos) { $this->semValue = new Expr\BinaryOp\Mod($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); }, - 345 => function ($stackPos) { + 350 => function ($stackPos) { $this->semValue = new Expr\BinaryOp\ShiftLeft($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); }, - 346 => function ($stackPos) { + 351 => function ($stackPos) { $this->semValue = new Expr\BinaryOp\ShiftRight($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); }, - 347 => function ($stackPos) { + 352 => function ($stackPos) { $this->semValue = new Expr\BinaryOp\Pow($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); }, - 348 => function ($stackPos) { + 353 => function ($stackPos) { $this->semValue = new Expr\UnaryPlus($this->semStack[$stackPos-(2-2)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); }, - 349 => function ($stackPos) { + 354 => function ($stackPos) { $this->semValue = new Expr\UnaryMinus($this->semStack[$stackPos-(2-2)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); }, - 350 => function ($stackPos) { + 355 => function ($stackPos) { $this->semValue = new Expr\BooleanNot($this->semStack[$stackPos-(2-2)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); }, - 351 => function ($stackPos) { + 356 => function ($stackPos) { $this->semValue = new Expr\BitwiseNot($this->semStack[$stackPos-(2-2)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); }, - 352 => function ($stackPos) { + 357 => function ($stackPos) { $this->semValue = new Expr\BinaryOp\Identical($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); }, - 353 => function ($stackPos) { + 358 => function ($stackPos) { $this->semValue = new Expr\BinaryOp\NotIdentical($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); }, - 354 => function ($stackPos) { + 359 => function ($stackPos) { $this->semValue = new Expr\BinaryOp\Equal($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); }, - 355 => function ($stackPos) { + 360 => function ($stackPos) { $this->semValue = new Expr\BinaryOp\NotEqual($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); }, - 356 => function ($stackPos) { + 361 => function ($stackPos) { $this->semValue = new Expr\BinaryOp\Spaceship($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); }, - 357 => function ($stackPos) { + 362 => function ($stackPos) { $this->semValue = new Expr\BinaryOp\Smaller($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); }, - 358 => function ($stackPos) { + 363 => function ($stackPos) { $this->semValue = new Expr\BinaryOp\SmallerOrEqual($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); }, - 359 => function ($stackPos) { + 364 => function ($stackPos) { $this->semValue = new Expr\BinaryOp\Greater($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); }, - 360 => function ($stackPos) { + 365 => function ($stackPos) { $this->semValue = new Expr\BinaryOp\GreaterOrEqual($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); }, - 361 => function ($stackPos) { + 366 => function ($stackPos) { $this->semValue = new Expr\Instanceof_($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); }, - 362 => function ($stackPos) { + 367 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos-(3-2)]; }, - 363 => function ($stackPos) { + 368 => function ($stackPos) { $this->semValue = new Expr\Ternary($this->semStack[$stackPos-(5-1)], $this->semStack[$stackPos-(5-3)], $this->semStack[$stackPos-(5-5)], $this->startAttributeStack[$stackPos-(5-1)] + $this->endAttributes); }, - 364 => function ($stackPos) { + 369 => function ($stackPos) { $this->semValue = new Expr\Ternary($this->semStack[$stackPos-(4-1)], null, $this->semStack[$stackPos-(4-4)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes); }, - 365 => function ($stackPos) { + 370 => function ($stackPos) { $this->semValue = new Expr\BinaryOp\Coalesce($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); }, - 366 => function ($stackPos) { + 371 => function ($stackPos) { $this->semValue = new Expr\Isset_($this->semStack[$stackPos-(4-3)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes); }, - 367 => function ($stackPos) { + 372 => function ($stackPos) { $this->semValue = new Expr\Empty_($this->semStack[$stackPos-(4-3)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes); }, - 368 => function ($stackPos) { + 373 => function ($stackPos) { $this->semValue = new Expr\Include_($this->semStack[$stackPos-(2-2)], Expr\Include_::TYPE_INCLUDE, $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); }, - 369 => function ($stackPos) { + 374 => function ($stackPos) { $this->semValue = new Expr\Include_($this->semStack[$stackPos-(2-2)], Expr\Include_::TYPE_INCLUDE_ONCE, $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); }, - 370 => function ($stackPos) { + 375 => function ($stackPos) { $this->semValue = new Expr\Eval_($this->semStack[$stackPos-(4-3)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes); }, - 371 => function ($stackPos) { + 376 => function ($stackPos) { $this->semValue = new Expr\Include_($this->semStack[$stackPos-(2-2)], Expr\Include_::TYPE_REQUIRE, $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); }, - 372 => function ($stackPos) { + 377 => function ($stackPos) { $this->semValue = new Expr\Include_($this->semStack[$stackPos-(2-2)], Expr\Include_::TYPE_REQUIRE_ONCE, $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); }, - 373 => function ($stackPos) { + 378 => function ($stackPos) { $this->semValue = new Expr\Cast\Int_($this->semStack[$stackPos-(2-2)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); }, - 374 => function ($stackPos) { + 379 => function ($stackPos) { $this->semValue = new Expr\Cast\Double($this->semStack[$stackPos-(2-2)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); }, - 375 => function ($stackPos) { + 380 => function ($stackPos) { $this->semValue = new Expr\Cast\String_($this->semStack[$stackPos-(2-2)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); }, - 376 => function ($stackPos) { + 381 => function ($stackPos) { $this->semValue = new Expr\Cast\Array_($this->semStack[$stackPos-(2-2)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); }, - 377 => function ($stackPos) { + 382 => function ($stackPos) { $this->semValue = new Expr\Cast\Object_($this->semStack[$stackPos-(2-2)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); }, - 378 => function ($stackPos) { + 383 => function ($stackPos) { $this->semValue = new Expr\Cast\Bool_($this->semStack[$stackPos-(2-2)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); }, - 379 => function ($stackPos) { + 384 => function ($stackPos) { $this->semValue = new Expr\Cast\Unset_($this->semStack[$stackPos-(2-2)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); }, - 380 => function ($stackPos) { + 385 => function ($stackPos) { $attrs = $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes; $attrs['kind'] = strtolower($this->semStack[$stackPos-(2-1)]) === 'exit' ? Expr\Exit_::KIND_EXIT : Expr\Exit_::KIND_DIE; $this->semValue = new Expr\Exit_($this->semStack[$stackPos-(2-2)], $attrs); }, - 381 => function ($stackPos) { + 386 => function ($stackPos) { $this->semValue = new Expr\ErrorSuppress($this->semStack[$stackPos-(2-2)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); }, - 382 => function ($stackPos) { + 387 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos-(1-1)]; }, - 383 => function ($stackPos) { + 388 => function ($stackPos) { $this->semValue = new Expr\ShellExec($this->semStack[$stackPos-(3-2)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); }, - 384 => function ($stackPos) { + 389 => function ($stackPos) { $this->semValue = new Expr\Print_($this->semStack[$stackPos-(2-2)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); }, - 385 => function ($stackPos) { + 390 => function ($stackPos) { $this->semValue = new Expr\Yield_(null, null, $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); }, - 386 => function ($stackPos) { + 391 => function ($stackPos) { $this->semValue = new Expr\Yield_($this->semStack[$stackPos-(2-2)], null, $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); }, - 387 => function ($stackPos) { + 392 => function ($stackPos) { $this->semValue = new Expr\Yield_($this->semStack[$stackPos-(4-4)], $this->semStack[$stackPos-(4-2)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes); }, - 388 => function ($stackPos) { + 393 => function ($stackPos) { $this->semValue = new Expr\YieldFrom($this->semStack[$stackPos-(2-2)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); }, - 389 => function ($stackPos) { - $this->semValue = new Expr\Closure(['static' => false, 'byRef' => $this->semStack[$stackPos-(10-2)], 'params' => $this->semStack[$stackPos-(10-4)], 'uses' => $this->semStack[$stackPos-(10-6)], 'returnType' => $this->semStack[$stackPos-(10-7)], 'stmts' => $this->semStack[$stackPos-(10-9)]], $this->startAttributeStack[$stackPos-(10-1)] + $this->endAttributes); - }, - 390 => function ($stackPos) { - $this->semValue = new Expr\Closure(['static' => true, 'byRef' => $this->semStack[$stackPos-(11-3)], 'params' => $this->semStack[$stackPos-(11-5)], 'uses' => $this->semStack[$stackPos-(11-7)], 'returnType' => $this->semStack[$stackPos-(11-8)], 'stmts' => $this->semStack[$stackPos-(11-10)]], $this->startAttributeStack[$stackPos-(11-1)] + $this->endAttributes); - }, - 391 => function ($stackPos) { + 394 => function ($stackPos) { + $this->semValue = new Expr\Closure(['static' => false, 'byRef' => $this->semStack[$stackPos-(8-2)], 'params' => $this->semStack[$stackPos-(8-4)], 'uses' => $this->semStack[$stackPos-(8-6)], 'returnType' => $this->semStack[$stackPos-(8-7)], 'stmts' => $this->semStack[$stackPos-(8-8)]], $this->startAttributeStack[$stackPos-(8-1)] + $this->endAttributes); + }, + 395 => function ($stackPos) { + $this->semValue = new Expr\Closure(['static' => true, 'byRef' => $this->semStack[$stackPos-(9-3)], 'params' => $this->semStack[$stackPos-(9-5)], 'uses' => $this->semStack[$stackPos-(9-7)], 'returnType' => $this->semStack[$stackPos-(9-8)], 'stmts' => $this->semStack[$stackPos-(9-9)]], $this->startAttributeStack[$stackPos-(9-1)] + $this->endAttributes); + }, + 396 => function ($stackPos) { $this->semValue = array(new Stmt\Class_(null, ['type' => 0, 'extends' => $this->semStack[$stackPos-(7-3)], 'implements' => $this->semStack[$stackPos-(7-4)], 'stmts' => $this->semStack[$stackPos-(7-6)]], $this->startAttributeStack[$stackPos-(7-1)] + $this->endAttributes), $this->semStack[$stackPos-(7-2)]); $this->checkClass($this->semValue[0], -1); }, - 392 => function ($stackPos) { + 397 => function ($stackPos) { $this->semValue = new Expr\New_($this->semStack[$stackPos-(3-2)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); }, - 393 => function ($stackPos) { + 398 => function ($stackPos) { list($class, $ctorArgs) = $this->semStack[$stackPos-(2-2)]; $this->semValue = new Expr\New_($class, $ctorArgs, $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); }, - 394 => function ($stackPos) { + 399 => function ($stackPos) { $this->semValue = array(); }, - 395 => function ($stackPos) { + 400 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos-(4-3)]; }, - 396 => function ($stackPos) { + 401 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos-(2-1)]; }, - 397 => function ($stackPos) { + 402 => function ($stackPos) { $this->semValue = array($this->semStack[$stackPos-(1-1)]); }, - 398 => function ($stackPos) { + 403 => function ($stackPos) { $this->semStack[$stackPos-(3-1)][] = $this->semStack[$stackPos-(3-3)]; $this->semValue = $this->semStack[$stackPos-(3-1)]; }, - 399 => function ($stackPos) { + 404 => function ($stackPos) { $this->semValue = new Expr\ClosureUse($this->semStack[$stackPos-(2-2)], $this->semStack[$stackPos-(2-1)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); }, - 400 => function ($stackPos) { + 405 => function ($stackPos) { $this->semValue = new Expr\FuncCall($this->semStack[$stackPos-(2-1)], $this->semStack[$stackPos-(2-2)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); }, - 401 => function ($stackPos) { + 406 => function ($stackPos) { $this->semValue = new Expr\FuncCall($this->semStack[$stackPos-(2-1)], $this->semStack[$stackPos-(2-2)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); }, - 402 => function ($stackPos) { + 407 => function ($stackPos) { $this->semValue = new Expr\StaticCall($this->semStack[$stackPos-(4-1)], $this->semStack[$stackPos-(4-3)], $this->semStack[$stackPos-(4-4)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes); }, - 403 => function ($stackPos) { + 408 => function ($stackPos) { $this->semValue = new Name($this->semStack[$stackPos-(1-1)], $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); }, - 404 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos-(1-1)]; - }, - 405 => function ($stackPos) { - $this->semValue = new Name($this->semStack[$stackPos-(1-1)], $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); - }, - 406 => function ($stackPos) { - $this->semValue = new Name\FullyQualified($this->semStack[$stackPos-(2-2)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); - }, - 407 => function ($stackPos) { - $this->semValue = new Name\Relative($this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); - }, - 408 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos-(1-1)]; - }, 409 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos-(1-1)]; }, 410 => function ($stackPos) { + $this->semValue = new Name($this->semStack[$stackPos-(1-1)], $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); + }, + 411 => function ($stackPos) { + $this->semValue = new Name\FullyQualified($this->semStack[$stackPos-(2-2)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); + }, + 412 => function ($stackPos) { + $this->semValue = new Name\Relative($this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 413 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(1-1)]; + }, + 414 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(1-1)]; + }, + 415 => function ($stackPos) { $this->semValue = new Expr\Error($this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); $this->errorState = 2; }, - 411 => function ($stackPos) { + 416 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos-(1-1)]; }, - 412 => function ($stackPos) { + 417 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos-(1-1)]; }, - 413 => function ($stackPos) { + 418 => function ($stackPos) { $this->semValue = null; }, - 414 => function ($stackPos) { + 419 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos-(3-2)]; }, - 415 => function ($stackPos) { + 420 => function ($stackPos) { $this->semValue = array(); }, - 416 => function ($stackPos) { + 421 => function ($stackPos) { $this->semValue = array(new Scalar\EncapsedStringPart(Scalar\String_::parseEscapeSequences($this->semStack[$stackPos-(1-1)], '`'), $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes)); }, - 417 => function ($stackPos) { + 422 => function ($stackPos) { foreach ($this->semStack[$stackPos-(1-1)] as $s) { if ($s instanceof Node\Scalar\EncapsedStringPart) { $s->value = Node\Scalar\String_::parseEscapeSequences($s->value, '`', true); } }; $this->semValue = $this->semStack[$stackPos-(1-1)]; }, - 418 => function ($stackPos) { + 423 => function ($stackPos) { $this->semValue = array(); }, - 419 => function ($stackPos) { + 424 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos-(1-1)]; }, - 420 => function ($stackPos) { + 425 => function ($stackPos) { $this->semValue = new Expr\ConstFetch($this->semStack[$stackPos-(1-1)], $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); }, - 421 => function ($stackPos) { + 426 => function ($stackPos) { $this->semValue = new Expr\ClassConstFetch($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); }, - 422 => function ($stackPos) { + 427 => function ($stackPos) { $this->semValue = new Expr\ClassConstFetch($this->semStack[$stackPos-(3-1)], new Expr\Error($this->startAttributeStack[$stackPos-(3-3)] + $this->endAttributeStack[$stackPos-(3-3)]), $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); $this->errorState = 2; }, - 423 => function ($stackPos) { + 428 => function ($stackPos) { $attrs = $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes; $attrs['kind'] = Expr\Array_::KIND_SHORT; $this->semValue = new Expr\Array_($this->semStack[$stackPos-(3-2)], $attrs); }, - 424 => function ($stackPos) { + 429 => function ($stackPos) { $attrs = $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes; $attrs['kind'] = Expr\Array_::KIND_LONG; $this->semValue = new Expr\Array_($this->semStack[$stackPos-(4-3)], $attrs); }, - 425 => function ($stackPos) { + 430 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos-(1-1)]; }, - 426 => function ($stackPos) { + 431 => function ($stackPos) { $attrs = $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes; $attrs['kind'] = ($this->semStack[$stackPos-(1-1)][0] === "'" || ($this->semStack[$stackPos-(1-1)][1] === "'" && ($this->semStack[$stackPos-(1-1)][0] === 'b' || $this->semStack[$stackPos-(1-1)][0] === 'B')) ? Scalar\String_::KIND_SINGLE_QUOTED : Scalar\String_::KIND_DOUBLE_QUOTED); $this->semValue = new Scalar\String_(Scalar\String_::parse($this->semStack[$stackPos-(1-1)]), $attrs); }, - 427 => function ($stackPos) { + 432 => function ($stackPos) { $this->semValue = $this->parseLNumber($this->semStack[$stackPos-(1-1)], $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); }, - 428 => function ($stackPos) { + 433 => function ($stackPos) { $this->semValue = new Scalar\DNumber(Scalar\DNumber::parse($this->semStack[$stackPos-(1-1)]), $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); }, - 429 => function ($stackPos) { + 434 => function ($stackPos) { $this->semValue = new Scalar\MagicConst\Line($this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); }, - 430 => function ($stackPos) { + 435 => function ($stackPos) { $this->semValue = new Scalar\MagicConst\File($this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); }, - 431 => function ($stackPos) { + 436 => function ($stackPos) { $this->semValue = new Scalar\MagicConst\Dir($this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); }, - 432 => function ($stackPos) { + 437 => function ($stackPos) { $this->semValue = new Scalar\MagicConst\Class_($this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); }, - 433 => function ($stackPos) { + 438 => function ($stackPos) { $this->semValue = new Scalar\MagicConst\Trait_($this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); }, - 434 => function ($stackPos) { + 439 => function ($stackPos) { $this->semValue = new Scalar\MagicConst\Method($this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); }, - 435 => function ($stackPos) { + 440 => function ($stackPos) { $this->semValue = new Scalar\MagicConst\Function_($this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); }, - 436 => function ($stackPos) { + 441 => function ($stackPos) { $this->semValue = new Scalar\MagicConst\Namespace_($this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); }, - 437 => function ($stackPos) { + 442 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos-(1-1)]; }, - 438 => function ($stackPos) { + 443 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos-(1-1)]; }, - 439 => function ($stackPos) { + 444 => function ($stackPos) { $attrs = $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes; $attrs['kind'] = strpos($this->semStack[$stackPos-(3-1)], "'") === false ? Scalar\String_::KIND_HEREDOC : Scalar\String_::KIND_NOWDOC; preg_match('/\A[bB]?<<<[ \t]*[\'"]?([a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*)[\'"]?(?:\r\n|\n|\r)\z/', $this->semStack[$stackPos-(3-1)], $matches); $attrs['docLabel'] = $matches[1];; $this->semValue = new Scalar\String_(Scalar\String_::parseDocString($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-2)]), $attrs); }, - 440 => function ($stackPos) { + 445 => function ($stackPos) { $attrs = $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes; $attrs['kind'] = strpos($this->semStack[$stackPos-(2-1)], "'") === false ? Scalar\String_::KIND_HEREDOC : Scalar\String_::KIND_NOWDOC; preg_match('/\A[bB]?<<<[ \t]*[\'"]?([a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*)[\'"]?(?:\r\n|\n|\r)\z/', $this->semStack[$stackPos-(2-1)], $matches); $attrs['docLabel'] = $matches[1];; $this->semValue = new Scalar\String_('', $attrs); }, - 441 => function ($stackPos) { + 446 => function ($stackPos) { $attrs = $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes; $attrs['kind'] = Scalar\String_::KIND_DOUBLE_QUOTED; foreach ($this->semStack[$stackPos-(3-2)] as $s) { if ($s instanceof Node\Scalar\EncapsedStringPart) { $s->value = Node\Scalar\String_::parseEscapeSequences($s->value, '"', true); } }; $this->semValue = new Scalar\Encapsed($this->semStack[$stackPos-(3-2)], $attrs); }, - 442 => function ($stackPos) { + 447 => function ($stackPos) { $attrs = $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes; $attrs['kind'] = strpos($this->semStack[$stackPos-(3-1)], "'") === false ? Scalar\String_::KIND_HEREDOC : Scalar\String_::KIND_NOWDOC; preg_match('/\A[bB]?<<<[ \t]*[\'"]?([a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*)[\'"]?(?:\r\n|\n|\r)\z/', $this->semStack[$stackPos-(3-1)], $matches); $attrs['docLabel'] = $matches[1];; foreach ($this->semStack[$stackPos-(3-2)] as $s) { if ($s instanceof Node\Scalar\EncapsedStringPart) { $s->value = Node\Scalar\String_::parseEscapeSequences($s->value, null, true); } } $s->value = preg_replace('~(\r\n|\n|\r)\z~', '', $s->value); if ('' === $s->value) array_pop($this->semStack[$stackPos-(3-2)]);; $this->semValue = new Scalar\Encapsed($this->semStack[$stackPos-(3-2)], $attrs); }, - 443 => function ($stackPos) { + 448 => function ($stackPos) { $this->semValue = null; }, - 444 => function ($stackPos) { + 449 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos-(1-1)]; }, - 445 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos-(1-1)]; - }, - 446 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos-(3-2)]; - }, - 447 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos-(1-1)]; - }, - 448 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos-(1-1)]; - }, - 449 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos-(3-2)]; - }, 450 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos-(1-1)]; }, 451 => function ($stackPos) { - $this->semValue = new Expr\Variable($this->semStack[$stackPos-(1-1)], $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); + $this->semValue = $this->semStack[$stackPos-(3-2)]; }, 452 => function ($stackPos) { - $this->semValue = new Expr\ArrayDimFetch($this->semStack[$stackPos-(4-1)], $this->semStack[$stackPos-(4-3)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes); + $this->semValue = $this->semStack[$stackPos-(1-1)]; }, 453 => function ($stackPos) { - $this->semValue = new Expr\ArrayDimFetch($this->semStack[$stackPos-(4-1)], $this->semStack[$stackPos-(4-3)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes); + $this->semValue = $this->semStack[$stackPos-(1-1)]; }, 454 => function ($stackPos) { - $this->semValue = new Expr\ArrayDimFetch($this->semStack[$stackPos-(4-1)], $this->semStack[$stackPos-(4-3)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes); + $this->semValue = $this->semStack[$stackPos-(3-2)]; }, 455 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos-(1-1)]; }, 456 => function ($stackPos) { + $this->semValue = new Expr\Variable($this->semStack[$stackPos-(1-1)], $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); + }, + 457 => function ($stackPos) { + $this->semValue = new Expr\ArrayDimFetch($this->semStack[$stackPos-(4-1)], $this->semStack[$stackPos-(4-3)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes); + }, + 458 => function ($stackPos) { + $this->semValue = new Expr\ArrayDimFetch($this->semStack[$stackPos-(4-1)], $this->semStack[$stackPos-(4-3)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes); + }, + 459 => function ($stackPos) { + $this->semValue = new Expr\ArrayDimFetch($this->semStack[$stackPos-(4-1)], $this->semStack[$stackPos-(4-3)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes); + }, + 460 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(1-1)]; + }, + 461 => function ($stackPos) { $this->semValue = new Expr\MethodCall($this->semStack[$stackPos-(4-1)], $this->semStack[$stackPos-(4-3)], $this->semStack[$stackPos-(4-4)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes); }, - 457 => function ($stackPos) { + 462 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos-(1-1)]; }, - 458 => function ($stackPos) { + 463 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos-(1-1)]; }, - 459 => function ($stackPos) { + 464 => function ($stackPos) { $this->semValue = new Expr\PropertyFetch($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); }, - 460 => function ($stackPos) { + 465 => function ($stackPos) { $this->semValue = substr($this->semStack[$stackPos-(1-1)], 1); }, - 461 => function ($stackPos) { + 466 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos-(4-3)]; }, - 462 => function ($stackPos) { + 467 => function ($stackPos) { $this->semValue = new Expr\Variable($this->semStack[$stackPos-(2-2)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); }, - 463 => function ($stackPos) { + 468 => function ($stackPos) { $this->semValue = new Expr\Error($this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); $this->errorState = 2; }, - 464 => function ($stackPos) { + 469 => function ($stackPos) { $var = $this->semStack[$stackPos-(1-1)]; $this->semValue = \is_string($var) ? new Node\VarLikeIdentifier($var, $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes) : $var; }, - 465 => function ($stackPos) { - $this->semValue = new Expr\StaticPropertyFetch($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); - }, - 466 => function ($stackPos) { - $this->semValue = new Expr\Variable($this->semStack[$stackPos-(1-1)], $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); - }, - 467 => function ($stackPos) { - $this->semValue = new Expr\ArrayDimFetch($this->semStack[$stackPos-(4-1)], $this->semStack[$stackPos-(4-3)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes); - }, - 468 => function ($stackPos) { - $this->semValue = new Expr\ArrayDimFetch($this->semStack[$stackPos-(4-1)], $this->semStack[$stackPos-(4-3)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes); - }, - 469 => function ($stackPos) { - $this->semValue = new Expr\PropertyFetch($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); - }, 470 => function ($stackPos) { $this->semValue = new Expr\StaticPropertyFetch($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); }, 471 => function ($stackPos) { + $this->semValue = new Expr\Variable($this->semStack[$stackPos-(1-1)], $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); + }, + 472 => function ($stackPos) { + $this->semValue = new Expr\ArrayDimFetch($this->semStack[$stackPos-(4-1)], $this->semStack[$stackPos-(4-3)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes); + }, + 473 => function ($stackPos) { + $this->semValue = new Expr\ArrayDimFetch($this->semStack[$stackPos-(4-1)], $this->semStack[$stackPos-(4-3)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes); + }, + 474 => function ($stackPos) { + $this->semValue = new Expr\PropertyFetch($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 475 => function ($stackPos) { $this->semValue = new Expr\StaticPropertyFetch($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); }, - 472 => function ($stackPos) { + 476 => function ($stackPos) { + $this->semValue = new Expr\StaticPropertyFetch($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 477 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos-(1-1)]; }, - 473 => function ($stackPos) { + 478 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos-(3-2)]; }, - 474 => function ($stackPos) { + 479 => function ($stackPos) { $this->semValue = new Expr\Variable($this->semStack[$stackPos-(1-1)], $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); }, - 475 => function ($stackPos) { + 480 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos-(1-1)]; }, - 476 => function ($stackPos) { + 481 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos-(3-2)]; }, - 477 => function ($stackPos) { + 482 => function ($stackPos) { $this->semValue = new Expr\Variable($this->semStack[$stackPos-(1-1)], $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); }, - 478 => function ($stackPos) { + 483 => function ($stackPos) { $this->semValue = new Expr\Error($this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); $this->errorState = 2; }, - 479 => function ($stackPos) { + 484 => function ($stackPos) { $this->semValue = new Expr\List_($this->semStack[$stackPos-(4-3)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes); }, - 480 => function ($stackPos) { + 485 => function ($stackPos) { $this->semStack[$stackPos-(3-1)][] = $this->semStack[$stackPos-(3-3)]; $this->semValue = $this->semStack[$stackPos-(3-1)]; }, - 481 => function ($stackPos) { + 486 => function ($stackPos) { $this->semValue = array($this->semStack[$stackPos-(1-1)]); }, - 482 => function ($stackPos) { + 487 => function ($stackPos) { $this->semValue = new Expr\ArrayItem($this->semStack[$stackPos-(1-1)], null, false, $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); }, - 483 => function ($stackPos) { + 488 => function ($stackPos) { $this->semValue = new Expr\ArrayItem($this->semStack[$stackPos-(2-2)], null, true, $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); }, - 484 => function ($stackPos) { + 489 => function ($stackPos) { $this->semValue = new Expr\ArrayItem($this->semStack[$stackPos-(1-1)], null, false, $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); }, - 485 => function ($stackPos) { + 490 => function ($stackPos) { $this->semValue = new Expr\ArrayItem($this->semStack[$stackPos-(3-3)], $this->semStack[$stackPos-(3-1)], false, $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); }, - 486 => function ($stackPos) { + 491 => function ($stackPos) { $this->semValue = new Expr\ArrayItem($this->semStack[$stackPos-(4-4)], $this->semStack[$stackPos-(4-1)], true, $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes); }, - 487 => function ($stackPos) { - $this->semValue = new Expr\ArrayItem($this->semStack[$stackPos-(3-3)], $this->semStack[$stackPos-(3-1)], false, $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); - }, - 488 => function ($stackPos) { - $this->semValue = null; - }, - 489 => function ($stackPos) { - $this->semValue = $this->semStack[$stackPos-(1-1)]; $end = count($this->semValue)-1; if ($this->semValue[$end] === null) array_pop($this->semValue); - }, - 490 => function ($stackPos) { - $this->semStack[$stackPos-(3-1)][] = $this->semStack[$stackPos-(3-3)]; $this->semValue = $this->semStack[$stackPos-(3-1)]; - }, - 491 => function ($stackPos) { - $this->semValue = array($this->semStack[$stackPos-(1-1)]); - }, 492 => function ($stackPos) { $this->semValue = new Expr\ArrayItem($this->semStack[$stackPos-(3-3)], $this->semStack[$stackPos-(3-1)], false, $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); }, 493 => function ($stackPos) { + $this->semValue = null; + }, + 494 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(1-1)]; $end = count($this->semValue)-1; if ($this->semValue[$end] === null) array_pop($this->semValue); + }, + 495 => function ($stackPos) { + $this->semStack[$stackPos-(3-1)][] = $this->semStack[$stackPos-(3-3)]; $this->semValue = $this->semStack[$stackPos-(3-1)]; + }, + 496 => function ($stackPos) { + $this->semValue = array($this->semStack[$stackPos-(1-1)]); + }, + 497 => function ($stackPos) { + $this->semValue = new Expr\ArrayItem($this->semStack[$stackPos-(3-3)], $this->semStack[$stackPos-(3-1)], false, $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 498 => function ($stackPos) { $this->semValue = new Expr\ArrayItem($this->semStack[$stackPos-(1-1)], null, false, $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); }, - 494 => function ($stackPos) { + 499 => function ($stackPos) { $this->semValue = new Expr\ArrayItem($this->semStack[$stackPos-(4-4)], $this->semStack[$stackPos-(4-1)], true, $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes); }, - 495 => function ($stackPos) { + 500 => function ($stackPos) { $this->semValue = new Expr\ArrayItem($this->semStack[$stackPos-(2-2)], null, true, $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); }, - 496 => function ($stackPos) { + 501 => function ($stackPos) { $this->semValue = null; }, - 497 => function ($stackPos) { + 502 => function ($stackPos) { $this->semStack[$stackPos-(2-1)][] = $this->semStack[$stackPos-(2-2)]; $this->semValue = $this->semStack[$stackPos-(2-1)]; }, - 498 => function ($stackPos) { + 503 => function ($stackPos) { $this->semStack[$stackPos-(2-1)][] = $this->semStack[$stackPos-(2-2)]; $this->semValue = $this->semStack[$stackPos-(2-1)]; }, - 499 => function ($stackPos) { + 504 => function ($stackPos) { $this->semValue = array($this->semStack[$stackPos-(1-1)]); }, - 500 => function ($stackPos) { + 505 => function ($stackPos) { $this->semValue = array($this->semStack[$stackPos-(2-1)], $this->semStack[$stackPos-(2-2)]); }, - 501 => function ($stackPos) { + 506 => function ($stackPos) { $this->semValue = new Scalar\EncapsedStringPart($this->semStack[$stackPos-(1-1)], $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); }, - 502 => function ($stackPos) { + 507 => function ($stackPos) { $this->semValue = new Expr\Variable($this->semStack[$stackPos-(1-1)], $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); }, - 503 => function ($stackPos) { + 508 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos-(1-1)]; }, - 504 => function ($stackPos) { + 509 => function ($stackPos) { $this->semValue = new Expr\ArrayDimFetch($this->semStack[$stackPos-(4-1)], $this->semStack[$stackPos-(4-3)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes); }, - 505 => function ($stackPos) { + 510 => function ($stackPos) { $this->semValue = new Expr\PropertyFetch($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); }, - 506 => function ($stackPos) { + 511 => function ($stackPos) { $this->semValue = new Expr\Variable($this->semStack[$stackPos-(3-2)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); }, - 507 => function ($stackPos) { + 512 => function ($stackPos) { $this->semValue = new Expr\Variable($this->semStack[$stackPos-(3-2)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); }, - 508 => function ($stackPos) { + 513 => function ($stackPos) { $this->semValue = new Expr\ArrayDimFetch($this->semStack[$stackPos-(6-2)], $this->semStack[$stackPos-(6-4)], $this->startAttributeStack[$stackPos-(6-1)] + $this->endAttributes); }, - 509 => function ($stackPos) { + 514 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos-(3-2)]; }, - 510 => function ($stackPos) { + 515 => function ($stackPos) { $this->semValue = new Scalar\String_($this->semStack[$stackPos-(1-1)], $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); }, - 511 => function ($stackPos) { + 516 => function ($stackPos) { $this->semValue = $this->parseNumString($this->semStack[$stackPos-(1-1)], $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); }, - 512 => function ($stackPos) { + 517 => function ($stackPos) { $this->semValue = $this->parseNumString('-' . $this->semStack[$stackPos-(2-2)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); }, - 513 => function ($stackPos) { + 518 => function ($stackPos) { $this->semValue = $this->semStack[$stackPos-(1-1)]; }, ]; diff -r e200cb7efeb3 -r c2387f117808 vendor/nikic/php-parser/lib/PhpParser/ParserAbstract.php --- a/vendor/nikic/php-parser/lib/PhpParser/ParserAbstract.php Thu Apr 26 11:26:54 2018 +0100 +++ b/vendor/nikic/php-parser/lib/PhpParser/ParserAbstract.php Tue Jul 10 15:07:59 2018 +0100 @@ -109,8 +109,6 @@ /** @var ErrorHandler Error handler */ protected $errorHandler; - /** @var Error[] Errors collected during last parse */ - protected $errors; /** @var int Error state, used to avoid error floods */ protected $errorState; @@ -129,7 +127,6 @@ */ public function __construct(Lexer $lexer, array $options = []) { $this->lexer = $lexer; - $this->errors = []; if (isset($options['throwOnError'])) { throw new \LogicException( diff -r e200cb7efeb3 -r c2387f117808 vendor/nikic/php-parser/lib/PhpParser/PrettyPrinter/Standard.php --- a/vendor/nikic/php-parser/lib/PhpParser/PrettyPrinter/Standard.php Thu Apr 26 11:26:54 2018 +0100 +++ b/vendor/nikic/php-parser/lib/PhpParser/PrettyPrinter/Standard.php Tue Jul 10 15:07:59 2018 +0100 @@ -198,6 +198,10 @@ return preg_match('/^-?[0-9]+$/', $stringValue) ? $stringValue . '.0' : $stringValue; } + protected function pScalar_EncapsedStringPart(Scalar\EncapsedStringPart $node) { + throw new \LogicException('Cannot directly print EncapsedStringPart'); + } + // Assignments protected function pExpr_Assign(Expr\Assign $node) { diff -r e200cb7efeb3 -r c2387f117808 vendor/nikic/php-parser/test/PhpParser/NodeVisitor/FirstFindingVisitorTest.php --- a/vendor/nikic/php-parser/test/PhpParser/NodeVisitor/FirstFindingVisitorTest.php Thu Apr 26 11:26:54 2018 +0100 +++ b/vendor/nikic/php-parser/test/PhpParser/NodeVisitor/FirstFindingVisitorTest.php Tue Jul 10 15:07:59 2018 +0100 @@ -34,6 +34,6 @@ $stmts = [new Node\Stmt\Expression($assign)]; $traverser->traverse($stmts); - $this->assertSame(null, $visitor->getFoundNode()); + $this->assertNull($visitor->getFoundNode()); } } diff -r e200cb7efeb3 -r c2387f117808 vendor/nikic/php-parser/test/PhpParser/PrettyPrinterTest.php --- a/vendor/nikic/php-parser/test/PhpParser/PrettyPrinterTest.php Thu Apr 26 11:26:54 2018 +0100 +++ b/vendor/nikic/php-parser/test/PhpParser/PrettyPrinterTest.php Tue Jul 10 15:07:59 2018 +0100 @@ -209,6 +209,16 @@ } /** + * @expectedException \LogicException + * @expectedExceptionMessage Cannot directly print EncapsedStringPart + */ + public function testPrettyPrintEncapsedStringPart() { + $expr = new Node\Scalar\EncapsedStringPart('foo'); + $prettyPrinter = new PrettyPrinter\Standard; + $prettyPrinter->prettyPrintExpr($expr); + } + + /** * @dataProvider provideTestFormatPreservingPrint * @covers \PhpParser\PrettyPrinter\Standard */ diff -r e200cb7efeb3 -r c2387f117808 vendor/nikic/php-parser/test/code/parser/errorHandling/recovery.test --- a/vendor/nikic/php-parser/test/code/parser/errorHandling/recovery.test Thu Apr 26 11:26:54 2018 +0100 +++ b/vendor/nikic/php-parser/test/code/parser/errorHandling/recovery.test Tue Jul 10 15:07:59 2018 +0100 @@ -952,4 +952,318 @@ ) ) ) +) +----- + ~PHP_INT_MAX - && + && $number < PHP_INT_MAX ) { $number = (int) $number; diff -r e200cb7efeb3 -r c2387f117808 vendor/paragonie/random_compat/lib/error_polyfill.php --- a/vendor/paragonie/random_compat/lib/error_polyfill.php Thu Apr 26 11:26:54 2018 +0100 +++ b/vendor/paragonie/random_compat/lib/error_polyfill.php Tue Jul 10 15:07:59 2018 +0100 @@ -5,7 +5,7 @@ * * The MIT License (MIT) * - * Copyright (c) 2015 - 2017 Paragon Initiative Enterprises + * Copyright (c) 2015 - 2018 Paragon Initiative Enterprises * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal diff -r e200cb7efeb3 -r c2387f117808 vendor/paragonie/random_compat/lib/random.php --- a/vendor/paragonie/random_compat/lib/random.php Thu Apr 26 11:26:54 2018 +0100 +++ b/vendor/paragonie/random_compat/lib/random.php Tue Jul 10 15:07:59 2018 +0100 @@ -3,12 +3,12 @@ * Random_* Compatibility Library * for using the new PHP 7 random_* API in PHP 5 projects * - * @version 2.0.10 - * @released 2017-03-13 + * @version 2.0.17 + * @released 2018-07-04 * * The MIT License (MIT) * - * Copyright (c) 2015 - 2017 Paragon Initiative Enterprises + * Copyright (c) 2015 - 2018 Paragon Initiative Enterprises * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -54,9 +54,9 @@ $RandomCompatDIR = dirname(__FILE__); -require_once $RandomCompatDIR . '/byte_safe_strings.php'; -require_once $RandomCompatDIR . '/cast_to_int.php'; -require_once $RandomCompatDIR . '/error_polyfill.php'; +require_once $RandomCompatDIR . DIRECTORY_SEPARATOR . 'byte_safe_strings.php'; +require_once $RandomCompatDIR . DIRECTORY_SEPARATOR . 'cast_to_int.php'; +require_once $RandomCompatDIR . DIRECTORY_SEPARATOR . 'error_polyfill.php'; if (!is_callable('random_bytes')) { /** @@ -76,9 +76,9 @@ if (extension_loaded('libsodium')) { // See random_bytes_libsodium.php if (PHP_VERSION_ID >= 50300 && is_callable('\\Sodium\\randombytes_buf')) { - require_once $RandomCompatDIR . '/random_bytes_libsodium.php'; + require_once $RandomCompatDIR . DIRECTORY_SEPARATOR . 'random_bytes_libsodium.php'; } elseif (method_exists('Sodium', 'randombytes_buf')) { - require_once $RandomCompatDIR . '/random_bytes_libsodium_legacy.php'; + require_once $RandomCompatDIR . DIRECTORY_SEPARATOR . 'random_bytes_libsodium_legacy.php'; } } @@ -117,7 +117,7 @@ // place, that is not helpful to us here. // See random_bytes_dev_urandom.php - require_once $RandomCompatDIR . '/random_bytes_dev_urandom.php'; + require_once $RandomCompatDIR . DIRECTORY_SEPARATOR . 'random_bytes_dev_urandom.php'; } // Unset variables after use $RandomCompat_basedir = null; @@ -159,7 +159,7 @@ extension_loaded('mcrypt') ) { // See random_bytes_mcrypt.php - require_once $RandomCompatDIR . '/random_bytes_mcrypt.php'; + require_once $RandomCompatDIR . DIRECTORY_SEPARATOR . 'random_bytes_mcrypt.php'; } $RandomCompatUrandom = null; @@ -184,7 +184,7 @@ $RandomCompatCOMtest = new COM('CAPICOM.Utilities.1'); if (method_exists($RandomCompatCOMtest, 'GetRandom')) { // See random_bytes_com_dotnet.php - require_once $RandomCompatDIR . '/random_bytes_com_dotnet.php'; + require_once $RandomCompatDIR . DIRECTORY_SEPARATOR . 'random_bytes_com_dotnet.php'; } } catch (com_exception $e) { // Don't try to use it. @@ -203,7 +203,7 @@ * and hope the developer won't let it fail silently. * * @param mixed $length - * @psalm-suppress MissingReturnType + * @psalm-suppress InvalidReturnType * @throws Exception * @return string */ @@ -219,7 +219,7 @@ } if (!is_callable('random_int')) { - require_once $RandomCompatDIR . '/random_int.php'; + require_once $RandomCompatDIR . DIRECTORY_SEPARATOR . 'random_int.php'; } $RandomCompatDIR = null; diff -r e200cb7efeb3 -r c2387f117808 vendor/paragonie/random_compat/lib/random_bytes_com_dotnet.php --- a/vendor/paragonie/random_compat/lib/random_bytes_com_dotnet.php Thu Apr 26 11:26:54 2018 +0100 +++ b/vendor/paragonie/random_compat/lib/random_bytes_com_dotnet.php Tue Jul 10 15:07:59 2018 +0100 @@ -5,7 +5,7 @@ * * The MIT License (MIT) * - * Copyright (c) 2015 - 2017 Paragon Initiative Enterprises + * Copyright (c) 2015 - 2018 Paragon Initiative Enterprises * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -41,6 +41,7 @@ function random_bytes($bytes) { try { + /** @var int $bytes */ $bytes = RandomCompat_intval($bytes); } catch (TypeError $ex) { throw new TypeError( @@ -54,12 +55,14 @@ ); } + /** @var string $buf */ $buf = ''; if (!class_exists('COM')) { throw new Error( 'COM does not exist' ); } + /** @var COM $util */ $util = new COM('CAPICOM.Utilities.1'); $execCount = 0; @@ -68,12 +71,12 @@ * get N bytes of random data, then CAPICOM has failed us. */ do { - $buf .= base64_decode($util->GetRandom($bytes, 0)); + $buf .= base64_decode((string) $util->GetRandom($bytes, 0)); if (RandomCompat_strlen($buf) >= $bytes) { /** * Return our random entropy buffer here: */ - return RandomCompat_substr($buf, 0, $bytes); + return (string) RandomCompat_substr($buf, 0, $bytes); } ++$execCount; } while ($execCount < $bytes); diff -r e200cb7efeb3 -r c2387f117808 vendor/paragonie/random_compat/lib/random_bytes_dev_urandom.php --- a/vendor/paragonie/random_compat/lib/random_bytes_dev_urandom.php Thu Apr 26 11:26:54 2018 +0100 +++ b/vendor/paragonie/random_compat/lib/random_bytes_dev_urandom.php Tue Jul 10 15:07:59 2018 +0100 @@ -5,7 +5,7 @@ * * The MIT License (MIT) * - * Copyright (c) 2015 - 2017 Paragon Initiative Enterprises + * Copyright (c) 2015 - 2018 Paragon Initiative Enterprises * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -46,7 +46,9 @@ */ function random_bytes($bytes) { + /** @var resource $fp */ static $fp = null; + /** * This block should only be run once */ @@ -55,8 +57,10 @@ * We use /dev/urandom if it is a char device. * We never fall back to /dev/random */ + /** @var resource|bool $fp */ $fp = fopen('/dev/urandom', 'rb'); - if (!empty($fp)) { + if (is_resource($fp)) { + /** @var array $st */ $st = fstat($fp); if (($st['mode'] & 0170000) !== 020000) { fclose($fp); @@ -64,7 +68,7 @@ } } - if (!empty($fp)) { + if (is_resource($fp)) { /** * stream_set_read_buffer() does not exist in HHVM * @@ -83,6 +87,7 @@ } try { + /** @var int $bytes */ $bytes = RandomCompat_intval($bytes); } catch (TypeError $ex) { throw new TypeError( @@ -103,7 +108,7 @@ * if (empty($fp)) line is logic that should only be run once per * page load. */ - if (!empty($fp)) { + if (is_resource($fp)) { /** * @var int */ diff -r e200cb7efeb3 -r c2387f117808 vendor/paragonie/random_compat/lib/random_bytes_libsodium.php --- a/vendor/paragonie/random_compat/lib/random_bytes_libsodium.php Thu Apr 26 11:26:54 2018 +0100 +++ b/vendor/paragonie/random_compat/lib/random_bytes_libsodium.php Tue Jul 10 15:07:59 2018 +0100 @@ -5,7 +5,7 @@ * * The MIT License (MIT) * - * Copyright (c) 2015 - 2017 Paragon Initiative Enterprises + * Copyright (c) 2015 - 2018 Paragon Initiative Enterprises * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -43,6 +43,7 @@ function random_bytes($bytes) { try { + /** @var int $bytes */ $bytes = RandomCompat_intval($bytes); } catch (TypeError $ex) { throw new TypeError( @@ -60,6 +61,7 @@ * \Sodium\randombytes_buf() doesn't allow more than 2147483647 bytes to be * generated in one invocation. */ + /** @var string|bool $buf */ if ($bytes > 2147483647) { $buf = ''; for ($i = 0; $i < $bytes; $i += 1073741824) { @@ -69,10 +71,11 @@ $buf .= \Sodium\randombytes_buf($n); } } else { + /** @var string|bool $buf */ $buf = \Sodium\randombytes_buf($bytes); } - if ($buf !== false) { + if (is_string($buf)) { if (RandomCompat_strlen($buf) === $bytes) { return $buf; } diff -r e200cb7efeb3 -r c2387f117808 vendor/paragonie/random_compat/lib/random_bytes_libsodium_legacy.php --- a/vendor/paragonie/random_compat/lib/random_bytes_libsodium_legacy.php Thu Apr 26 11:26:54 2018 +0100 +++ b/vendor/paragonie/random_compat/lib/random_bytes_libsodium_legacy.php Tue Jul 10 15:07:59 2018 +0100 @@ -5,7 +5,7 @@ * * The MIT License (MIT) * - * Copyright (c) 2015 - 2017 Paragon Initiative Enterprises + * Copyright (c) 2015 - 2018 Paragon Initiative Enterprises * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -43,6 +43,7 @@ function random_bytes($bytes) { try { + /** @var int $bytes */ $bytes = RandomCompat_intval($bytes); } catch (TypeError $ex) { throw new TypeError( diff -r e200cb7efeb3 -r c2387f117808 vendor/paragonie/random_compat/lib/random_bytes_mcrypt.php --- a/vendor/paragonie/random_compat/lib/random_bytes_mcrypt.php Thu Apr 26 11:26:54 2018 +0100 +++ b/vendor/paragonie/random_compat/lib/random_bytes_mcrypt.php Tue Jul 10 15:07:59 2018 +0100 @@ -5,7 +5,7 @@ * * The MIT License (MIT) * - * Copyright (c) 2015 - 2017 Paragon Initiative Enterprises + * Copyright (c) 2015 - 2018 Paragon Initiative Enterprises * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -42,6 +42,7 @@ function random_bytes($bytes) { try { + /** @var int $bytes */ $bytes = RandomCompat_intval($bytes); } catch (TypeError $ex) { throw new TypeError( @@ -55,10 +56,11 @@ ); } - $buf = @mcrypt_create_iv($bytes, MCRYPT_DEV_URANDOM); + /** @var string|bool $buf */ + $buf = @mcrypt_create_iv((int) $bytes, (int) MCRYPT_DEV_URANDOM); if ( - $buf !== false - && + is_string($buf) + && RandomCompat_strlen($buf) === $bytes ) { /** diff -r e200cb7efeb3 -r c2387f117808 vendor/paragonie/random_compat/lib/random_int.php --- a/vendor/paragonie/random_compat/lib/random_int.php Thu Apr 26 11:26:54 2018 +0100 +++ b/vendor/paragonie/random_compat/lib/random_int.php Tue Jul 10 15:07:59 2018 +0100 @@ -7,7 +7,7 @@ * * The MIT License (MIT) * - * Copyright (c) 2015 - 2017 Paragon Initiative Enterprises + * Copyright (c) 2015 - 2018 Paragon Initiative Enterprises * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -51,6 +51,7 @@ */ try { + /** @var int $min */ $min = RandomCompat_intval($min); } catch (TypeError $ex) { throw new TypeError( @@ -59,6 +60,7 @@ } try { + /** @var int $max */ $max = RandomCompat_intval($max); } catch (TypeError $ex) { throw new TypeError( @@ -90,11 +92,18 @@ * so we can minimize the number of discards */ $attempts = $bits = $bytes = $mask = $valueShift = 0; + /** @var int $attempts */ + /** @var int $bits */ + /** @var int $bytes */ + /** @var int $mask */ + /** @var int $valueShift */ /** * At this point, $range is a positive number greater than 0. It might * overflow, however, if $max - $min > PHP_INT_MAX. PHP will cast it to * a float and we will lose some precision. + * + * @var int|float $range */ $range = $max - $min; @@ -115,6 +124,7 @@ * @ref http://3v4l.org/XX9r5 (64-bit) */ $bytes = PHP_INT_SIZE; + /** @var int $mask */ $mask = ~0; } else { @@ -129,16 +139,19 @@ } ++$bits; $range >>= 1; + /** @var int $mask */ $mask = $mask << 1 | 1; } $valueShift = $min; } + /** @var int $val */ $val = 0; /** * Now that we have our parameters set up, let's begin generating * random integers until one falls between $min and $max */ + /** @psalm-suppress RedundantCondition */ do { /** * The rejection probability is at most 0.5, so this corresponds @@ -169,6 +182,7 @@ for ($i = 0; $i < $bytes; ++$i) { $val |= ord($randomByteString[$i]) << ($i * 8); } + /** @var int $val */ /** * Apply mask diff -r e200cb7efeb3 -r c2387f117808 vendor/paragonie/random_compat/psalm.xml --- a/vendor/paragonie/random_compat/psalm.xml Thu Apr 26 11:26:54 2018 +0100 +++ b/vendor/paragonie/random_compat/psalm.xml Tue Jul 10 15:07:59 2018 +0100 @@ -1,18 +1,28 @@ + + - + + + + + + + diff -r e200cb7efeb3 -r c2387f117808 vendor/phpunit/phpunit-mock-objects/src/Generator.php --- a/vendor/phpunit/phpunit-mock-objects/src/Generator.php Thu Apr 26 11:26:54 2018 +0100 +++ b/vendor/phpunit/phpunit-mock-objects/src/Generator.php Tue Jul 10 15:07:59 2018 +0100 @@ -1115,8 +1115,13 @@ if (!$parameter->isVariadic()) { if ($parameter->isDefaultValueAvailable()) { - $value = $parameter->getDefaultValue(); - $default = ' = ' . \var_export($value, true); + $value = $parameter->getDefaultValueConstantName(); + + if ($value === null) { + $value = \var_export($parameter->getDefaultValue(), true); + } + + $default = ' = ' . $value; } elseif ($parameter->isOptional()) { $default = ' = null'; } diff -r e200cb7efeb3 -r c2387f117808 vendor/phpunit/phpunit-mock-objects/tests/Generator/397.phpt --- a/vendor/phpunit/phpunit-mock-objects/tests/Generator/397.phpt Thu Apr 26 11:26:54 2018 +0100 +++ b/vendor/phpunit/phpunit-mock-objects/tests/Generator/397.phpt Tue Jul 10 15:07:59 2018 +0100 @@ -1,5 +1,8 @@ --TEST-- https://github.com/sebastianbergmann/phpunit-mock-objects/issues/397 +--SKIPIF-- +=')) print 'skip: PHP >= 7.1 required'; --FILE-- generate( + 'Foo', + [], + 'MockFoo', + true, + true +); + +print $mock['code']; +?> +--EXPECT-- +class MockFoo extends Foo implements PHPUnit\Framework\MockObject\MockObject +{ + private $__phpunit_invocationMocker; + private $__phpunit_originalObject; + private $__phpunit_configurable = ['bar']; + + public function __clone() + { + $this->__phpunit_invocationMocker = clone $this->__phpunit_getInvocationMocker(); + } + + public function bar(int $baz = PHP_INT_MIN) + { + $arguments = array($baz); + $count = func_num_args(); + + if ($count > 1) { + $_arguments = func_get_args(); + + for ($i = 1; $i < $count; $i++) { + $arguments[] = $_arguments[$i]; + } + } + + $result = $this->__phpunit_getInvocationMocker()->invoke( + new \PHPUnit\Framework\MockObject\Invocation\ObjectInvocation( + 'Foo', 'bar', $arguments, '', $this, true + ) + ); + + return $result; + } + + public function expects(\PHPUnit\Framework\MockObject\Matcher\Invocation $matcher) + { + return $this->__phpunit_getInvocationMocker()->expects($matcher); + } + + public function method() + { + $any = new \PHPUnit\Framework\MockObject\Matcher\AnyInvokedCount; + $expects = $this->expects($any); + return call_user_func_array(array($expects, 'method'), func_get_args()); + } + + public function __phpunit_setOriginalObject($originalObject) + { + $this->__phpunit_originalObject = $originalObject; + } + + public function __phpunit_getInvocationMocker() + { + if ($this->__phpunit_invocationMocker === null) { + $this->__phpunit_invocationMocker = new \PHPUnit\Framework\MockObject\InvocationMocker($this->__phpunit_configurable); + } + + return $this->__phpunit_invocationMocker; + } + + public function __phpunit_hasMatchers() + { + return $this->__phpunit_getInvocationMocker()->hasMatchers(); + } + + public function __phpunit_verify($unsetInvocationMocker = true) + { + $this->__phpunit_getInvocationMocker()->verify(); + + if ($unsetInvocationMocker) { + $this->__phpunit_invocationMocker = null; + } + } +} diff -r e200cb7efeb3 -r c2387f117808 vendor/phpunit/phpunit/.gitignore --- a/vendor/phpunit/phpunit/.gitignore Thu Apr 26 11:26:54 2018 +0100 +++ b/vendor/phpunit/phpunit/.gitignore Tue Jul 10 15:07:59 2018 +0100 @@ -2,6 +2,7 @@ /.idea /.php_cs /.php_cs.cache +/.phpunit.result.cache /build/documentation /build/logfiles /build/phar diff -r e200cb7efeb3 -r c2387f117808 vendor/phpunit/phpunit/ChangeLog-6.5.md --- a/vendor/phpunit/phpunit/ChangeLog-6.5.md Thu Apr 26 11:26:54 2018 +0100 +++ b/vendor/phpunit/phpunit/ChangeLog-6.5.md Tue Jul 10 15:07:59 2018 +0100 @@ -2,6 +2,12 @@ All notable changes of the PHPUnit 6.5 release series are documented in this file using the [Keep a CHANGELOG](http://keepachangelog.com/) principles. +## [6.5.9] - 2018-07-03 + +### Fixed + +* Fixed [#3142](https://github.com/sebastianbergmann/phpunit/issues/3142): Method-level annotations (`@backupGlobals`, `@backupStaticAttributes`, `@errorHandler`, `@preserveGlobalState`) do not override class-level annotations + ## [6.5.8] - 2018-04-10 ### Fixed @@ -62,6 +68,7 @@ * Fixed [#2654](https://github.com/sebastianbergmann/phpunit/issues/2654): Problems with `assertJsonStringEqualsJsonString()` * Fixed [#2810](https://github.com/sebastianbergmann/phpunit/pull/2810): Code Coverage for PHPT tests does not work +[6.5.9]: https://github.com/sebastianbergmann/phpunit/compare/6.5.8...6.5.9 [6.5.8]: https://github.com/sebastianbergmann/phpunit/compare/6.5.7...6.5.8 [6.5.7]: https://github.com/sebastianbergmann/phpunit/compare/6.5.6...6.5.7 [6.5.6]: https://github.com/sebastianbergmann/phpunit/compare/6.5.5...6.5.6 diff -r e200cb7efeb3 -r c2387f117808 vendor/phpunit/phpunit/README.md --- a/vendor/phpunit/phpunit/README.md Thu Apr 26 11:26:54 2018 +0100 +++ b/vendor/phpunit/phpunit/README.md Tue Jul 10 15:07:59 2018 +0100 @@ -8,25 +8,15 @@ ## Installation -We distribute a [PHP Archive (PHAR)](https://php.net/phar) that has all required (as well as some optional) dependencies of PHPUnit bundled in a single file: +We distribute a [PHP Archive (PHAR)](https://php.net/phar) that has all required (as well as some optional) dependencies of PHPUnit 6.5 bundled in a single file: ```bash -$ wget https://phar.phpunit.de/phpunit.phar +$ wget https://phar.phpunit.de/phpunit-6.5.phar -$ chmod +x phpunit.phar - -$ mv phpunit.phar /usr/local/bin/phpunit +$ php phpunit-6.5.phar --version ``` -You can also immediately use the PHAR after you have downloaded it, of course: - -```bash -$ wget https://phar.phpunit.de/phpunit.phar - -$ php phpunit.phar -``` - -Alternatively, you may use [Composer](https://getcomposer.org/) to download and install PHPUnit as well as its dependencies. Please refer to the [documentation](https://phpunit.de/documentation.html) for details on how to do this. +Alternatively, you may use [Composer](https://getcomposer.org/) to download and install PHPUnit as well as its dependencies. Please refer to the "[Getting Started](https://phpunit.de/getting-started-with-phpunit.html)" guide for details on how to install PHPUnit. ## Contribute @@ -37,10 +27,15 @@ Thanks to everyone who has contributed to PHPUnit! You can find a detailed list of contributors on every PHPUnit related package on GitHub. This list shows only the major components: * [PHPUnit](https://github.com/sebastianbergmann/phpunit/graphs/contributors) -* [PHP_CodeCoverage](https://github.com/sebastianbergmann/php-code-coverage/graphs/contributors) -* [PHPUnit_MockObject](https://github.com/sebastianbergmann/phpunit-mock-objects/graphs/contributors) +* [php-code-coverage](https://github.com/sebastianbergmann/php-code-coverage/graphs/contributors) +* [phpunit-mock-objects](https://github.com/sebastianbergmann/phpunit-mock-objects/graphs/contributors) A very special thanks to everyone who has contributed to the documentation and helps maintain the translations: -* [PHPUnit Documentation](https://github.com/sebastianbergmann/phpunit-documentation/graphs/contributors) +* [English](https://github.com/sebastianbergmann/phpunit-documentation-english/graphs/contributors) +* [Spanish](https://github.com/sebastianbergmann/phpunit-documentation-spanish/graphs/contributors) +* [French](https://github.com/sebastianbergmann/phpunit-documentation-french/graphs/contributors) +* [Japanese](https://github.com/sebastianbergmann/phpunit-documentation-japanese/graphs/contributors) +* [Brazilian Portuguese](https://github.com/sebastianbergmann/phpunit-documentation-brazilian-portuguese/graphs/contributors) +* [Simplified Chinese](https://github.com/sebastianbergmann/phpunit-documentation-chinese/graphs/contributors) diff -r e200cb7efeb3 -r c2387f117808 vendor/phpunit/phpunit/appveyor.yml --- a/vendor/phpunit/phpunit/appveyor.yml Thu Apr 26 11:26:54 2018 +0100 +++ b/vendor/phpunit/phpunit/appveyor.yml Tue Jul 10 15:07:59 2018 +0100 @@ -37,7 +37,7 @@ - IF NOT EXIST c:\php mkdir c:\php - IF NOT EXIST c:\php\%PHP_VERSION% mkdir c:\php\%PHP_VERSION% - cd c:\php\%PHP_VERSION% - - IF NOT EXIST php-installed.txt appveyor DownloadFile http://windows.php.net/downloads/releases/archives/php-%PHP_VERSION%-Win32-VC14-x86.zip + - IF NOT EXIST php-installed.txt curl -fsS -o php-%PHP_VERSION%-Win32-VC14-x86.zip https://windows.php.net/downloads/releases/archives/php-%PHP_VERSION%-Win32-VC14-x86.zip - IF NOT EXIST php-installed.txt 7z x php-%PHP_VERSION%-Win32-VC14-x86.zip -y >nul - IF NOT EXIST php-installed.txt del /Q *.zip - IF NOT EXIST php-installed.txt copy /Y php.ini-development php.ini @@ -52,9 +52,9 @@ - IF NOT EXIST php-installed.txt echo extension=php_pdo_sqlite.dll >> php.ini - IF NOT EXIST php-installed.txt echo zend.assertions=1 >> php.ini - IF NOT EXIST php-installed.txt echo assert.exception=On >> php.ini - - IF NOT EXIST php-installed.txt appveyor DownloadFile https://getcomposer.org/composer.phar + - IF NOT EXIST php-installed.txt curl -fsS -o composer.phar https://getcomposer.org/composer.phar - IF NOT EXIST php-installed.txt echo @php %%~dp0composer.phar %%* > composer.bat - - IF NOT EXIST php-installed.txt appveyor DownloadFile https://xdebug.org/files/php_xdebug-%XDEBUG_VERSION%-vc14.dll -FileName c:\php\%PHP_VERSION%\ext\php_xdebug-%XDEBUG_VERSION%-vc14.dll + - IF NOT EXIST php-installed.txt curl -fsS -o c:\php\%PHP_VERSION%\ext\php_xdebug-%XDEBUG_VERSION%-vc14.dll https://xdebug.org/files/php_xdebug-%XDEBUG_VERSION%-vc14.dll - IF NOT EXIST php-installed.txt echo zend_extension=php_xdebug-%XDEBUG_VERSION%-vc14.dll >> php.ini - IF NOT EXIST php-installed.txt type nul >> php-installed.txt - cd c:\phpunit diff -r e200cb7efeb3 -r c2387f117808 vendor/phpunit/phpunit/build.xml --- a/vendor/phpunit/phpunit/build.xml Thu Apr 26 11:26:54 2018 +0100 +++ b/vendor/phpunit/phpunit/build.xml Tue Jul 10 15:07:59 2018 +0100 @@ -124,7 +124,6 @@ - @@ -376,10 +375,21 @@ - + + + + + + + + + + + + @@ -399,16 +409,6 @@ - - - - - - - - - - diff -r e200cb7efeb3 -r c2387f117808 vendor/phpunit/phpunit/phive.xml --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vendor/phpunit/phpunit/phive.xml Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,7 @@ + + + + + + + diff -r e200cb7efeb3 -r c2387f117808 vendor/phpunit/phpunit/src/Framework/Constraint/IsEqual.php --- a/vendor/phpunit/phpunit/src/Framework/Constraint/IsEqual.php Thu Apr 26 11:26:54 2018 +0100 +++ b/vendor/phpunit/phpunit/src/Framework/Constraint/IsEqual.php Tue Jul 10 15:07:59 2018 +0100 @@ -11,7 +11,8 @@ use PHPUnit\Framework\ExpectationFailedException; use PHPUnit\Util\InvalidArgumentHelper; -use SebastianBergmann; +use SebastianBergmann\Comparator\ComparisonFailure; +use SebastianBergmann\Comparator\Factory as ComparatorFactory; /** * Constraint that checks if one value is equal to another. @@ -50,11 +51,6 @@ protected $ignoreCase = false; /** - * @var SebastianBergmann\Comparator\ComparisonFailure - */ - protected $lastFailure; - - /** * @param mixed $value * @param float $delta * @param int $maxDepth @@ -117,7 +113,7 @@ return true; } - $comparatorFactory = SebastianBergmann\Comparator\Factory::getInstance(); + $comparatorFactory = ComparatorFactory::getInstance(); try { $comparator = $comparatorFactory->getComparatorFor( @@ -132,7 +128,7 @@ $this->canonicalize, $this->ignoreCase ); - } catch (SebastianBergmann\Comparator\ComparisonFailure $f) { + } catch (ComparisonFailure $f) { if ($returnResult) { return false; } diff -r e200cb7efeb3 -r c2387f117808 vendor/phpunit/phpunit/src/Framework/Constraint/IsIdentical.php --- a/vendor/phpunit/phpunit/src/Framework/Constraint/IsIdentical.php Thu Apr 26 11:26:54 2018 +0100 +++ b/vendor/phpunit/phpunit/src/Framework/Constraint/IsIdentical.php Tue Jul 10 15:07:59 2018 +0100 @@ -10,7 +10,7 @@ namespace PHPUnit\Framework\Constraint; use PHPUnit\Framework\ExpectationFailedException; -use SebastianBergmann; +use SebastianBergmann\Comparator\ComparisonFailure; /** * Constraint that asserts that one value is identical to another. @@ -81,7 +81,7 @@ // if both values are strings, make sure a diff is generated if (\is_string($this->value) && \is_string($other)) { - $f = new SebastianBergmann\Comparator\ComparisonFailure( + $f = new ComparisonFailure( $this->value, $other, \sprintf("'%s'", $this->value), diff -r e200cb7efeb3 -r c2387f117808 vendor/phpunit/phpunit/src/Framework/TestCase.php --- a/vendor/phpunit/phpunit/src/Framework/TestCase.php Thu Apr 26 11:26:54 2018 +0100 +++ b/vendor/phpunit/phpunit/src/Framework/TestCase.php Tue Jul 10 15:07:59 2018 +0100 @@ -42,7 +42,6 @@ use ReflectionClass; use ReflectionException; use ReflectionObject; -use SebastianBergmann; use SebastianBergmann\Comparator\Comparator; use SebastianBergmann\Comparator\Factory as ComparatorFactory; use SebastianBergmann\Diff\Differ; @@ -293,7 +292,7 @@ private $outputBufferingLevel; /** - * @var SebastianBergmann\GlobalState\Snapshot + * @var Snapshot */ private $snapshot; diff -r e200cb7efeb3 -r c2387f117808 vendor/phpunit/phpunit/src/Runner/Version.php --- a/vendor/phpunit/phpunit/src/Runner/Version.php Thu Apr 26 11:26:54 2018 +0100 +++ b/vendor/phpunit/phpunit/src/Runner/Version.php Tue Jul 10 15:07:59 2018 +0100 @@ -32,7 +32,7 @@ } if (self::$version === null) { - $version = new VersionId('6.5.8', \dirname(\dirname(__DIR__))); + $version = new VersionId('6.5.9', \dirname(\dirname(__DIR__))); self::$version = $version->getVersion(); } diff -r e200cb7efeb3 -r c2387f117808 vendor/phpunit/phpunit/src/TextUI/TestRunner.php --- a/vendor/phpunit/phpunit/src/TextUI/TestRunner.php Thu Apr 26 11:26:54 2018 +0100 +++ b/vendor/phpunit/phpunit/src/TextUI/TestRunner.php Tue Jul 10 15:07:59 2018 +0100 @@ -34,7 +34,6 @@ use PHPUnit\Util\TestDox\TextResultPrinter; use PHPUnit\Util\TestDox\XmlResultPrinter; use ReflectionClass; -use SebastianBergmann; use SebastianBergmann\CodeCoverage\CodeCoverage; use SebastianBergmann\CodeCoverage\Exception as CodeCoverageException; use SebastianBergmann\CodeCoverage\Filter as CodeCoverageFilter; @@ -44,6 +43,7 @@ use SebastianBergmann\CodeCoverage\Report\PHP as PhpReport; use SebastianBergmann\CodeCoverage\Report\Text as TextReport; use SebastianBergmann\CodeCoverage\Report\Xml\Facade as XmlReport; +use SebastianBergmann\Comparator\Comparator; use SebastianBergmann\Environment\Runtime; /** @@ -429,7 +429,7 @@ ); $codeCoverage->setUnintentionallyCoveredSubclassesWhitelist( - [SebastianBergmann\Comparator\Comparator::class] + [Comparator::class] ); $codeCoverage->setCheckForUnintentionallyCoveredCode( diff -r e200cb7efeb3 -r c2387f117808 vendor/phpunit/phpunit/src/Util/Configuration.php --- a/vendor/phpunit/phpunit/src/Util/Configuration.php Thu Apr 26 11:26:54 2018 +0100 +++ b/vendor/phpunit/phpunit/src/Util/Configuration.php Tue Jul 10 15:07:59 2018 +0100 @@ -568,6 +568,8 @@ \putenv("{$name}={$value}"); } + $value = \getenv($name); + if (!isset($_ENV[$name])) { $_ENV[$name] = $value; } diff -r e200cb7efeb3 -r c2387f117808 vendor/phpunit/phpunit/src/Util/Test.php --- a/vendor/phpunit/phpunit/src/Util/Test.php Thu Apr 26 11:26:54 2018 +0100 +++ b/vendor/phpunit/phpunit/src/Util/Test.php Tue Jul 10 15:07:59 2018 +0100 @@ -967,22 +967,22 @@ $methodName ); - if (isset($annotations['class'][$settingName])) { - if ($annotations['class'][$settingName][0] == 'enabled') { + if (isset($annotations['method'][$settingName])) { + if ($annotations['method'][$settingName][0] === 'enabled') { return true; } - if ($annotations['class'][$settingName][0] == 'disabled') { + if ($annotations['method'][$settingName][0] === 'disabled') { return false; } } - if (isset($annotations['method'][$settingName])) { - if ($annotations['method'][$settingName][0] == 'enabled') { + if (isset($annotations['class'][$settingName])) { + if ($annotations['class'][$settingName][0] === 'enabled') { return true; } - if ($annotations['method'][$settingName][0] == 'disabled') { + if ($annotations['class'][$settingName][0] === 'disabled') { return false; } } diff -r e200cb7efeb3 -r c2387f117808 vendor/psy/psysh/.editorconfig --- a/vendor/psy/psysh/.editorconfig Thu Apr 26 11:26:54 2018 +0100 +++ b/vendor/psy/psysh/.editorconfig Tue Jul 10 15:07:59 2018 +0100 @@ -10,3 +10,6 @@ [*.md] trim_trailing_whitespace = false + +[Makefile] +indent_style = tab diff -r e200cb7efeb3 -r c2387f117808 vendor/psy/psysh/.github/CONTRIBUTING.md --- a/vendor/psy/psysh/.github/CONTRIBUTING.md Thu Apr 26 11:26:54 2018 +0100 +++ b/vendor/psy/psysh/.github/CONTRIBUTING.md Tue Jul 10 15:07:59 2018 +0100 @@ -7,14 +7,3 @@ ## Branching model Please branch off and send pull requests to the `develop` branch. - -## Building the manual - -```sh -svn co https://svn.php.net/repository/phpdoc/en/trunk/reference/ php_manual -bin/build_manual phpdoc_manual ~/.local/share/psysh/php_manual.sqlite -``` - -To build the manual for another language, switch out `en` above for `de`, `es`, or any of the other languages listed in the docs. - -[Partial or outdated documentation is available for other languages](http://www.php.net/manual/help-translate.php) but these translations are outdated, so their content may be completely wrong or insecure! diff -r e200cb7efeb3 -r c2387f117808 vendor/psy/psysh/.gitignore --- a/vendor/psy/psysh/.gitignore Thu Apr 26 11:26:54 2018 +0100 +++ b/vendor/psy/psysh/.gitignore Tue Jul 10 15:07:59 2018 +0100 @@ -1,11 +1,9 @@ -build-vendor/ -vendor/ -composer.lock -composer-compat.json -composer-compat.lock -manual/ -dist/ -__pycache__ -.php_cs.cache -psysh.phar -psysh-compat.phar +/build/ +/dist/ +/composer.lock +/manual/ +/psysh +/__pycache__ +/.php_cs.cache +/vendor/ +/vendor-bin/*/vendor/ diff -r e200cb7efeb3 -r c2387f117808 vendor/psy/psysh/.travis.yml --- a/vendor/psy/psysh/.travis.yml Thu Apr 26 11:26:54 2018 +0100 +++ b/vendor/psy/psysh/.travis.yml Tue Jul 10 15:07:59 2018 +0100 @@ -18,12 +18,18 @@ - php: 5.4 env: 'COMPOSER_FLAGS="--prefer-lowest --prefer-stable"' - php: hhvm + fast_finish: true install: travis_retry composer update --no-interaction $COMPOSER_FLAGS -script: vendor/bin/phpunit --verbose +script: + - vendor/bin/phpunit --verbose --coverage-clover=coverage.xml + - '[[ $TRAVIS_PHP_VERSION = 7.2* ]] && make build -j 4 || true' -before_deploy: bin/package -v $TRAVIS_TAG +after_success: + - bash <(curl -s https://codecov.io/bash) + +before_deploy: make dist -j 4 deploy: provider: releases @@ -35,4 +41,4 @@ on: tags: true repo: bobthecow/psysh - condition: (($TRAVIS_PHP_VERSION = 5.4* && -z "$COMPOSER_FLAGS") || $TRAVIS_PHP_VERSION = 7.0*) + condition: $TRAVIS_PHP_VERSION = 7.2* diff -r e200cb7efeb3 -r c2387f117808 vendor/psy/psysh/LICENSE --- a/vendor/psy/psysh/LICENSE Thu Apr 26 11:26:54 2018 +0100 +++ b/vendor/psy/psysh/LICENSE Tue Jul 10 15:07:59 2018 +0100 @@ -1,6 +1,6 @@ The MIT License (MIT) -Copyright (c) 2012-2017 Justin Hileman +Copyright (c) 2012-2018 Justin Hileman Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff -r e200cb7efeb3 -r c2387f117808 vendor/psy/psysh/Makefile --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vendor/psy/psysh/Makefile Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,95 @@ +PSYSH_SRC = bin src box.json.dist composer.json build/stub +PSYSH_SRC_FILES = $(shell find src -type f -name "*.php") +VERSION = $(shell git describe --tag --always --dirty=-dev) + +COMPOSER_OPTS = --no-interaction --no-progress --verbose +COMPOSER_REQUIRE_OPTS = $(COMPOSER_OPTS) --no-update +COMPOSER_UPDATE_OPTS = $(COMPOSER_OPTS) --prefer-stable --no-dev --classmap-authoritative --prefer-dist + + +# Commands + +.PHONY: help clean build dist +.DEFAULT_GOAL := help + +help: + @echo "\033[33mUsage:\033[0m\n make TARGET\n\n\033[33mTargets:\033[0m" + @grep -E '^[a-zA-Z0-9_-]+:.*?## .*$$' $(MAKEFILE_LIST) | sort | awk 'BEGIN {FS = ":.*?## "}; {printf " \033[32m%-7s\033[0m %s\n", $$1, $$2}' + +clean: ## Clean all created artifacts + rm -rf build/* + rm -rf dist/* + rm -rf vendor-bin/*/vendor/ + +build: ## Compile PHARs +build: build/psysh/psysh build/psysh-compat/psysh build/psysh-php54/psysh build/psysh-php54-compat/psysh + +dist: ## Build tarballs for distribution +dist: dist/psysh-$(VERSION).tar.gz dist/psysh-$(VERSION)-compat.tar.gz dist/psysh-$(VERSION)-php54.tar.gz dist/psysh-$(VERSION)-php54-compat.tar.gz + + +# All the composer stuffs + +composer.lock: composer.json + composer install + touch $@ + +vendor/autoload.php: composer.lock + composer install + touch $@ + +vendor/bin/box: vendor/autoload.php + composer bin box install + touch $@ + + +# Lots of PHARs + +build/stub: bin/build-stub bin/psysh LICENSE + bin/build-stub + +build/psysh: $(PSYSH_SRC) $(PSYSH_SRC_FILES) + rm -rf $@ || true + mkdir $@ + cp -R $(PSYSH_SRC) $@/ + composer config --working-dir $@ platform.php 7.0 + composer require --working-dir $@ $(COMPOSER_REQUIRE_OPTS) php:'>=7.0.0' + composer update --working-dir $@ $(COMPOSER_UPDATE_OPTS) + +build/psysh-compat: $(PSYSH_SRC) $(PSYSH_SRC_FILES) + rm -rf $@ || true + mkdir $@ + cp -R $(PSYSH_SRC) $@/ + composer config --working-dir $@ platform.php 7.0 + composer require --working-dir $@ $(COMPOSER_REQUIRE_OPTS) php:'>=7.0.0' + composer require --working-dir $@ $(COMPOSER_REQUIRE_OPTS) symfony/polyfill-iconv symfony/polyfill-mbstring hoa/console + composer update --working-dir $@ $(COMPOSER_UPDATE_OPTS) + +build/psysh-php54: $(PSYSH_SRC) $(PSYSH_SRC_FILES) + rm -rf $@ || true + mkdir $@ + cp -R $(PSYSH_SRC) $@/ + composer config --working-dir $@ platform.php 5.4 + composer update --working-dir $@ $(COMPOSER_UPDATE_OPTS) + +build/psysh-php54-compat: $(PSYSH_SRC) $(PSYSH_SRC_FILES) + rm -rf $@ || true + mkdir $@ + cp -R $(PSYSH_SRC) $@/ + composer config --working-dir $@ platform.php 5.4 + composer require --working-dir $@ $(COMPOSER_REQUIRE_OPTS) symfony/polyfill-iconv symfony/polyfill-mbstring hoa/console:^2.15 + composer update --working-dir $@ $(COMPOSER_UPDATE_OPTS) + +build/%/psysh: vendor/bin/box build/% + vendor/bin/box compile --working-dir $(dir $@) + + +# Dist packages + +dist/psysh-$(VERSION).tar.gz: build/psysh/psysh + @mkdir -p $(@D) + tar -C $(dir $<) -czf $@ $(notdir $<) + +dist/psysh-$(VERSION)-%.tar.gz: build/psysh-%/psysh + @mkdir -p $(@D) + tar -C $(dir $<) -czf $@ $(notdir $<) diff -r e200cb7efeb3 -r c2387f117808 vendor/psy/psysh/README.md --- a/vendor/psy/psysh/README.md Thu Apr 26 11:26:54 2018 +0100 +++ b/vendor/psy/psysh/README.md Tue Jul 10 15:07:59 2018 +0100 @@ -17,6 +17,7 @@ ### [💾 Installation](https://github.com/bobthecow/psysh/wiki/Installation) * [📕 PHP manual installation](https://github.com/bobthecow/psysh/wiki/PHP-manual) + * Windows ### [🖥 Usage](https://github.com/bobthecow/psysh/wiki/Usage) * [✨ Magic variables](https://github.com/bobthecow/psysh/wiki/Magic-variables) diff -r e200cb7efeb3 -r c2387f117808 vendor/psy/psysh/bin/build --- a/vendor/psy/psysh/bin/build Thu Apr 26 11:26:54 2018 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,13 +0,0 @@ -#!/usr/bin/env bash - -set -e - -cd "${BASH_SOURCE%/*}/.." - -echo "Building phar" -./bin/build-vendor -php -d 'phar.readonly=0' ./bin/build-phar - -echo "Building compat phar" -./bin/build-vendor-compat -php -d 'phar.readonly=0' ./bin/build-phar --compat diff -r e200cb7efeb3 -r c2387f117808 vendor/psy/psysh/bin/build-manual --- a/vendor/psy/psysh/bin/build-manual Thu Apr 26 11:26:54 2018 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,312 +0,0 @@ -#!/usr/bin/env php -': - $inTag = false; - break; - } - - if ($inTag) { - $tagWidth++; - } - - $i++; - - if (!$inTag && ($i - $tagWidth > $width)) { - $lastSpace = $lastSpace ?: $width; - - $return[] = trim(substr($text, 0, $lastSpace)); - $text = substr($text, $lastSpace); - $len = strlen($text); - - $i = $tagWidth = 0; - } - } while ($i < $len); - - $return[] = trim($text); - - return implode("\n", $return); -} - -function extract_paragraphs($element) -{ - $paragraphs = []; - foreach ($element->getElementsByTagName('para') as $p) { - $text = ''; - foreach ($p->childNodes as $child) { - // @todo figure out if there's something we can do with tables. - if ($child instanceof DOMElement && $child->tagName === 'table') { - continue; - } - - // skip references, because ugh. - if (preg_match('{^\s*&[a-z][a-z\.]+;\s*$}', $child->textContent)) { - continue; - } - - $text .= $child->ownerDocument->saveXML($child); - } - - if ($text = trim(preg_replace('{\n[ \t]+}', ' ', $text))) { - $paragraphs[] = $text; - } - } - - return implode("\n\n", $paragraphs); -} - -function format_doc($doc) -{ - $chunks = []; - - if (!empty($doc['description'])) { - $chunks[] = 'Description:'; - $chunks[] = indent_text(htmlwrap(thunk_tags($doc['description']), WRAP_WIDTH - 2)); - $chunks[] = ''; - } - - if (!empty($doc['params'])) { - $chunks[] = 'Param:'; - - $typeMax = max(array_map(function ($param) { - return strlen($param['type']); - }, $doc['params'])); - - $max = max(array_map(function ($param) { - return strlen($param['name']); - }, $doc['params'])); - - $template = ' %-' . $typeMax . 's %-' . $max . 's %s'; - $indent = str_repeat(' ', $typeMax + $max + 6); - $wrapWidth = WRAP_WIDTH - strlen($indent); - - foreach ($doc['params'] as $param) { - $desc = indent_text(htmlwrap(thunk_tags($param['description']), $wrapWidth), $indent, false); - $chunks[] = sprintf($template, $param['type'], $param['name'], $desc); - } - $chunks[] = ''; - } - - if (isset($doc['return']) || isset($doc['return_type'])) { - $chunks[] = 'Return:'; - - $type = isset($doc['return_type']) ? $doc['return_type'] : 'unknown'; - $desc = isset($doc['return']) ? $doc['return'] : ''; - - $indent = str_repeat(' ', strlen($type) + 4); - $wrapWidth = WRAP_WIDTH - strlen($indent); - - if (!empty($desc)) { - $desc = indent_text(htmlwrap(thunk_tags($doc['return']), $wrapWidth), $indent, false); - } - - $chunks[] = sprintf(' %s %s', $type, $desc); - $chunks[] = ''; - } - - array_pop($chunks); // get rid of the trailing newline - - return implode("\n", $chunks); -} - -function thunk_tags($text) -{ - $tagMap = [ - 'parameter>' => 'strong>', - 'function>' => 'strong>', - 'literal>' => 'return>', - 'type>' => 'info>', - 'constant>' => 'info>', - ]; - - $andBack = [ - '&' => '&', - '&true;' => 'true', - '&false;' => 'false', - '&null;' => 'null', - ]; - - return strtr(strip_tags(strtr($text, $tagMap), ''), $andBack); -} - -function indent_text($text, $indent = ' ', $leading = true) -{ - return ($leading ? $indent : '') . str_replace("\n", "\n" . $indent, $text); -} - -function find_type($xml, $paramName) -{ - foreach ($xml->getElementsByTagName('methodparam') as $param) { - if ($type = $param->getElementsByTagName('type')->item(0)) { - if ($parameter = $param->getElementsByTagName('parameter')->item(0)) { - if ($paramName === $parameter->textContent) { - return $type->textContent; - } - } - } - } -} - -function format_function_doc($xml) -{ - $doc = []; - $refsect1s = $xml->getElementsByTagName('refsect1'); - foreach ($refsect1s as $refsect1) { - $role = $refsect1->getAttribute('role'); - switch ($role) { - case 'description': - $doc['description'] = extract_paragraphs($refsect1); - - if ($synopsis = $refsect1->getElementsByTagName('methodsynopsis')->item(0)) { - foreach ($synopsis->childNodes as $node) { - if ($node instanceof DOMElement && $node->tagName === 'type') { - $doc['return_type'] = $node->textContent; - break; - } - } - } - break; - - case 'returnvalues': - // do nothing. - $doc['return'] = extract_paragraphs($refsect1); - break; - - case 'parameters': - $params = []; - $vars = $refsect1->getElementsByTagName('varlistentry'); - foreach ($vars as $var) { - if ($name = $var->getElementsByTagName('parameter')->item(0)) { - $params[] = [ - 'name' => '$' . $name->textContent, - 'type' => find_type($xml, $name->textContent), - 'description' => extract_paragraphs($var), - ]; - } - } - - $doc['params'] = $params; - break; - } - } - - // and the purpose - if ($purpose = $xml->getElementsByTagName('refpurpose')->item(0)) { - $desc = htmlwrap($purpose->textContent); - if (isset($doc['description'])) { - $desc .= "\n\n" . $doc['description']; - } - - $doc['description'] = trim($desc); - } - - $ids = []; - foreach ($xml->getElementsByTagName('refname') as $ref) { - $ids[] = $ref->textContent; - } - - return [$ids, format_doc($doc)]; -} - -function format_class_doc($xml) -{ - // @todo implement this - return [[], null]; -} - -$dir = new RecursiveDirectoryIterator($argv[1]); -$filter = new RecursiveCallbackFilterIterator($dir, function ($current, $key, $iterator) { - return $current->getFilename()[0] !== '.' && - ($current->isDir() || $current->getExtension() === 'xml') && - strpos($current->getFilename(), 'entities.') !== 0 && - $current->getFilename() !== 'pdo_4d'; // Temporarily blacklist this one, the docs are weird. -}); -$iterator = new RecursiveIteratorIterator($filter); - -$docs = []; -foreach ($iterator as $file) { - $xmlstr = str_replace('&', '&', file_get_contents($file)); - - $xml = new DOMDocument(); - $xml->preserveWhiteSpace = false; - - if (!@$xml->loadXml($xmlstr)) { - echo "XML Parse Error: $file\n"; - continue; - } - - if ($xml->getElementsByTagName('refentry')->length !== 0) { - list($ids, $doc) = format_function_doc($xml); - } elseif ($xml->getElementsByTagName('classref')->length !== 0) { - list($ids, $doc) = format_class_doc($xml); - } else { - $ids = []; - $doc = null; - } - - foreach ($ids as $id) { - $docs[$id] = $doc; - } -} - -if (is_file($argv[2])) { - unlink($argv[2]); -} - -$db = new PDO('sqlite:' . $argv[2]); - -$db->query('CREATE TABLE php_manual (id char(256) PRIMARY KEY, doc TEXT)'); -$cmd = $db->prepare('INSERT INTO php_manual (id, doc) VALUES (?, ?)'); -foreach ($docs as $id => $doc) { - $cmd->execute([$id, $doc]); -} diff -r e200cb7efeb3 -r c2387f117808 vendor/psy/psysh/bin/build-phar --- a/vendor/psy/psysh/bin/build-phar Thu Apr 26 11:26:54 2018 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,38 +0,0 @@ -#!/usr/bin/env php -compile('psysh-compat.phar'); -} else { - $compiler->compile(); -} diff -r e200cb7efeb3 -r c2387f117808 vendor/psy/psysh/bin/build-stub --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vendor/psy/psysh/bin/build-stub Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,22 @@ +#!/usr/bin/env php +>> \*/}sm', $autoload, $content); +$content = preg_replace('/\\(c\\) .*?with this source code./sm', $license, $content); + +$content .= '__HALT_COMPILER();'; + +@mkdir(dirname(__DIR__) . '/build'); + +file_put_contents(dirname(__DIR__) . '/build/stub', $content); diff -r e200cb7efeb3 -r c2387f117808 vendor/psy/psysh/bin/build-vendor --- a/vendor/psy/psysh/bin/build-vendor Thu Apr 26 11:26:54 2018 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,10 +0,0 @@ -#!/usr/bin/env bash - -set -e - -cd "${BASH_SOURCE%/*}/.." - -rm -rf build-vendor - -COMPOSER_VENDOR_DIR=build-vendor composer update \ - --prefer-stable --no-dev --no-progress --classmap-authoritative --no-interaction --verbose diff -r e200cb7efeb3 -r c2387f117808 vendor/psy/psysh/bin/build-vendor-compat --- a/vendor/psy/psysh/bin/build-vendor-compat Thu Apr 26 11:26:54 2018 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,21 +0,0 @@ -#!/usr/bin/env bash - -set -e - -cd "${BASH_SOURCE%/*}/.." - -rm -rf build-vendor -rm -f composer-*.lock - -cp composer.json composer-compat.json - -if [[ $(php --version) = PHP\ 5.4* ]]; then - HOA_VERSION=^2.15 -fi - -COMPOSER=composer-compat.json COMPOSER_VENDOR_DIR=build-vendor \ - composer require symfony/intl hoa/console $HOA_VERSION --no-progress --no-update --no-interaction --verbose - -COMPOSER=composer-compat.json COMPOSER_VENDOR_DIR=build-vendor \ - composer update --prefer-stable --no-dev --no-progress --classmap-authoritative --no-interaction --verbose - diff -r e200cb7efeb3 -r c2387f117808 vendor/psy/psysh/bin/package --- a/vendor/psy/psysh/bin/package Thu Apr 26 11:26:54 2018 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,55 +0,0 @@ -#!/usr/bin/env bash - -set -e - -cd "${BASH_SOURCE%/*}/.." - -USAGE="usage: bin/package [-v PACKAGE_VERSION]" - -while getopts ":v:h" opt; do - case $opt in - v) - PKG_VERSION="v${OPTARG#v}" - ;; - h) - echo $USAGE >&2 - exit - ;; - \?) - echo "Invalid option: -$OPTARG" >&2 - echo $USAGE >&2 - exit 1 - ;; - :) - echo "Option -$OPTARG requires an argument" >&2 - echo $USAGE >&2 - exit 1 - ;; - esac -done - -if [ -z "$PKG_VERSION" ]; then - PKG_VERSION=$(git describe --tag --exact-match) -fi - -if [[ $(php --version) = PHP\ 5.4* ]]; then - PKG_VERSION=${PKG_VERSION}-php54 -fi - -echo "Packaging $PKG_VERSION" - -mkdir -p dist || exit 1 - -./bin/build || exit 1 -chmod +x *.phar - -echo "Creating tarballs" - -# Support BSD tar because OS X :( -if [[ $(tar --version) = bsdtar* ]]; then - tar -s "/.*/psysh/" -czf dist/psysh-${PKG_VERSION}.tar.gz psysh.phar - tar -s "/.*/psysh/" -czf dist/psysh-${PKG_VERSION}-compat.tar.gz psysh-compat.phar -else - tar --transform "s/.*/psysh/" -czf dist/psysh-${PKG_VERSION}.tar.gz psysh.phar - tar --transform "s/.*/psysh/" -czf dist/psysh-${PKG_VERSION}-compat.tar.gz psysh-compat.phar -fi diff -r e200cb7efeb3 -r c2387f117808 vendor/psy/psysh/box.json.dist --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vendor/psy/psysh/box.json.dist Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,13 @@ +{ + "stub": "stub", + "output": "psysh", + "compactors": [ + "KevinGH\\Box\\Compactor\\Php" + ], + "chmod": "0755", + "blacklist": [ + "grammar", + "test_old", + "Documentation" + ] +} diff -r e200cb7efeb3 -r c2387f117808 vendor/psy/psysh/composer.json --- a/vendor/psy/psysh/composer.json Thu Apr 26 11:26:54 2018 +0100 +++ b/vendor/psy/psysh/composer.json Tue Jul 10 15:07:59 2018 +0100 @@ -22,8 +22,8 @@ }, "require-dev": { "phpunit/phpunit": "~4.8.35|~5.0|~6.0|~7.0", - "symfony/finder": "~2.1|~3.0|~4.0", - "hoa/console": "~2.15|~3.16" + "hoa/console": "~2.15|~3.16", + "bamarni/composer-bin-plugin": "^1.2" }, "suggest": { "ext-pcntl": "Enabling the PCNTL extension makes PsySH a lot happier :)", diff -r e200cb7efeb3 -r c2387f117808 vendor/psy/psysh/src/CodeCleaner.php --- a/vendor/psy/psysh/src/CodeCleaner.php Thu Apr 26 11:26:54 2018 +0100 +++ b/vendor/psy/psysh/src/CodeCleaner.php Tue Jul 10 15:07:59 2018 +0100 @@ -26,6 +26,7 @@ use Psy\CodeCleaner\InstanceOfPass; use Psy\CodeCleaner\LeavePsyshAlonePass; use Psy\CodeCleaner\LegacyEmptyPass; +use Psy\CodeCleaner\ListPass; use Psy\CodeCleaner\LoopContextPass; use Psy\CodeCleaner\MagicConstantsPass; use Psy\CodeCleaner\NamespacePass; @@ -99,6 +100,7 @@ new InstanceOfPass(), new LeavePsyshAlonePass(), new LegacyEmptyPass(), + new ListPass(), new LoopContextPass(), new PassableByReferencePass(), new ValidConstructorPass(), diff -r e200cb7efeb3 -r c2387f117808 vendor/psy/psysh/src/CodeCleaner/CallTimePassByReferencePass.php --- a/vendor/psy/psysh/src/CodeCleaner/CallTimePassByReferencePass.php Thu Apr 26 11:26:54 2018 +0100 +++ b/vendor/psy/psysh/src/CodeCleaner/CallTimePassByReferencePass.php Tue Jul 10 15:07:59 2018 +0100 @@ -31,7 +31,7 @@ /** * Validate of use call-time pass-by-reference. * - * @throws RuntimeException if the user used call-time pass-by-reference in PHP >= 5.4.0 + * @throws RuntimeException if the user used call-time pass-by-reference * * @param Node $node */ diff -r e200cb7efeb3 -r c2387f117808 vendor/psy/psysh/src/CodeCleaner/FunctionReturnInWriteContextPass.php --- a/vendor/psy/psysh/src/CodeCleaner/FunctionReturnInWriteContextPass.php Thu Apr 26 11:26:54 2018 +0100 +++ b/vendor/psy/psysh/src/CodeCleaner/FunctionReturnInWriteContextPass.php Tue Jul 10 15:07:59 2018 +0100 @@ -68,7 +68,7 @@ throw new FatalErrorException($msg, 0, E_ERROR, null, $node->getLine()); } } elseif ($node instanceof Empty_ && !$this->atLeastPhp55 && $this->isCallNode($node->expr)) { - throw new FatalErrorException(self::EXCEPTION_MESSAGE, 0, E_ERROR, null, $node->getLine()); + throw new FatalErrorException(self::EXCEPTION_MESSAGE, 0, E_ERROR, null, $node->getLine()); // @codeCoverageIgnore } elseif ($node instanceof Assign && $this->isCallNode($node->var)) { throw new FatalErrorException(self::EXCEPTION_MESSAGE, 0, E_ERROR, null, $node->getLine()); } diff -r e200cb7efeb3 -r c2387f117808 vendor/psy/psysh/src/CodeCleaner/ImplicitReturnPass.php --- a/vendor/psy/psysh/src/CodeCleaner/ImplicitReturnPass.php Thu Apr 26 11:26:54 2018 +0100 +++ b/vendor/psy/psysh/src/CodeCleaner/ImplicitReturnPass.php Tue Jul 10 15:07:59 2018 +0100 @@ -14,8 +14,6 @@ use PhpParser\Node; use PhpParser\Node\Expr; use PhpParser\Node\Expr\Exit_; -use PhpParser\Node\Expr\New_; -use PhpParser\Node\Name\FullyQualified as FullyQualifiedName; use PhpParser\Node\Stmt; use PhpParser\Node\Stmt\Break_; use PhpParser\Node\Stmt\Expression; @@ -48,7 +46,7 @@ { // If nodes is empty, it can't have a return value. if (empty($nodes)) { - return [new Return_(new New_(new FullyQualifiedName('Psy\CodeCleaner\NoReturnValue')))]; + return [new Return_(NoReturnValue::create())]; } $last = end($nodes); @@ -77,10 +75,12 @@ } } } elseif ($last instanceof Expr && !($last instanceof Exit_)) { + // @codeCoverageIgnoreStart $nodes[count($nodes) - 1] = new Return_($last, [ 'startLine' => $last->getLine(), 'endLine' => $last->getLine(), ]); + // @codeCoverageIgnoreEnd } elseif ($last instanceof Expression && !($last->expr instanceof Exit_)) { // For PHP Parser 4.x $nodes[count($nodes) - 1] = new Return_($last->expr, [ @@ -102,7 +102,7 @@ // because code outside namespace statements doesn't really work, and // there's already an implicit return in the namespace statement anyway. if (self::isNonExpressionStmt($last)) { - $nodes[] = new Return_(new New_(new FullyQualifiedName('Psy\CodeCleaner\NoReturnValue'))); + $nodes[] = new Return_(NoReturnValue::create()); } return $nodes; diff -r e200cb7efeb3 -r c2387f117808 vendor/psy/psysh/src/CodeCleaner/LegacyEmptyPass.php --- a/vendor/psy/psysh/src/CodeCleaner/LegacyEmptyPass.php Thu Apr 26 11:26:54 2018 +0100 +++ b/vendor/psy/psysh/src/CodeCleaner/LegacyEmptyPass.php Tue Jul 10 15:07:59 2018 +0100 @@ -19,6 +19,8 @@ /** * Validate that the user did not call the language construct `empty()` on a * statement in PHP < 5.5. + * + * @codeCoverageIgnore */ class LegacyEmptyPass extends CodeCleanerPass { diff -r e200cb7efeb3 -r c2387f117808 vendor/psy/psysh/src/CodeCleaner/ListPass.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vendor/psy/psysh/src/CodeCleaner/ListPass.php Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,89 @@ +atLeastPhp71 = version_compare(PHP_VERSION, '7.1', '>='); + } + + /** + * Validate use of list assignment. + * + * @throws ParseErrorException if the user used empty with anything but a variable + * + * @param Node $node + */ + public function enterNode(Node $node) + { + if (!$node instanceof Assign) { + return; + } + + if (!$node->var instanceof Array_ && !$node->var instanceof List_) { + return; + } + + if (!$this->atLeastPhp71 && $node->var instanceof Array_) { + $msg = "syntax error, unexpected '='"; + throw new ParseErrorException($msg, $node->expr->getLine()); + } + + // Polyfill for PHP-Parser 2.x + $items = isset($node->var->items) ? $node->var->items : $node->var->vars; + + if ($items === [] || $items === [null]) { + throw new ParseErrorException('Cannot use empty list', $node->var->getLine()); + } + + $itemFound = false; + foreach ($items as $item) { + if ($item === null) { + continue; + } + + $itemFound = true; + + // List_->$vars in PHP-Parser 2.x is Variable instead of ArrayItem. + if (!$this->atLeastPhp71 && $item instanceof ArrayItem && $item->key !== null) { + $msg = 'Syntax error, unexpected T_CONSTANT_ENCAPSED_STRING, expecting \',\' or \')\''; + throw new ParseErrorException($msg, $item->key->getLine()); + } + + $value = ($item instanceof ArrayItem) ? $item->value : $item; + + if (!$value instanceof Variable) { + $msg = 'Assignments can only happen to writable values'; + throw new ParseErrorException($msg, $item->getLine()); + } + } + + if (!$itemFound) { + throw new ParseErrorException('Cannot use empty list'); + } + } +} diff -r e200cb7efeb3 -r c2387f117808 vendor/psy/psysh/src/CodeCleaner/NoReturnValue.php --- a/vendor/psy/psysh/src/CodeCleaner/NoReturnValue.php Thu Apr 26 11:26:54 2018 +0100 +++ b/vendor/psy/psysh/src/CodeCleaner/NoReturnValue.php Tue Jul 10 15:07:59 2018 +0100 @@ -11,6 +11,9 @@ namespace Psy\CodeCleaner; +use PhpParser\Node\Expr\New_; +use PhpParser\Node\Name\FullyQualified as FullyQualifiedName; + /** * A class used internally by CodeCleaner to represent input, such as * non-expression statements, with no return value. @@ -20,5 +23,13 @@ */ class NoReturnValue { - // this space intentionally left blank + /** + * Get PhpParser AST expression for creating a new NoReturnValue. + * + * @return PhpParser\Node\Expr\New_ + */ + public static function create() + { + return new New_(new FullyQualifiedName('Psy\CodeCleaner\NoReturnValue')); + } } diff -r e200cb7efeb3 -r c2387f117808 vendor/psy/psysh/src/CodeCleaner/StrictTypesPass.php --- a/vendor/psy/psysh/src/CodeCleaner/StrictTypesPass.php Thu Apr 26 11:26:54 2018 +0100 +++ b/vendor/psy/psysh/src/CodeCleaner/StrictTypesPass.php Tue Jul 10 15:07:59 2018 +0100 @@ -52,7 +52,7 @@ public function beforeTraverse(array $nodes) { if (!$this->atLeastPhp7) { - return; + return; // @codeCoverageIgnore } $prependStrictTypes = $this->strictTypes; diff -r e200cb7efeb3 -r c2387f117808 vendor/psy/psysh/src/CodeCleaner/ValidClassNamePass.php --- a/vendor/psy/psysh/src/CodeCleaner/ValidClassNamePass.php Thu Apr 26 11:26:54 2018 +0100 +++ b/vendor/psy/psysh/src/CodeCleaner/ValidClassNamePass.php Tue Jul 10 15:07:59 2018 +0100 @@ -38,13 +38,11 @@ const INTERFACE_TYPE = 'interface'; const TRAIT_TYPE = 'trait'; - protected $checkTraits; private $conditionalScopes = 0; private $atLeastPhp55; public function __construct() { - $this->checkTraits = function_exists('trait_exists'); $this->atLeastPhp55 = version_compare(PHP_VERSION, '5.5', '>='); } @@ -117,7 +115,7 @@ */ protected function validateClassStatement(Class_ $stmt) { - $this->ensureCanDefine($stmt); + $this->ensureCanDefine($stmt, self::CLASS_TYPE); if (isset($stmt->extends)) { $this->ensureClassExists($this->getFullyQualifiedName($stmt->extends), $stmt); } @@ -131,7 +129,7 @@ */ protected function validateInterfaceStatement(Interface_ $stmt) { - $this->ensureCanDefine($stmt); + $this->ensureCanDefine($stmt, self::INTERFACE_TYPE); $this->ensureInterfacesExist($stmt->extends, $stmt); } @@ -142,7 +140,7 @@ */ protected function validateTraitStatement(Trait_ $stmt) { - $this->ensureCanDefine($stmt); + $this->ensureCanDefine($stmt, self::TRAIT_TYPE); } /** @@ -194,9 +192,10 @@ * * @throws FatalErrorException * - * @param Stmt $stmt + * @param Stmt $stmt + * @param string $scopeType */ - protected function ensureCanDefine(Stmt $stmt) + protected function ensureCanDefine(Stmt $stmt, $scopeType = self::CLASS_TYPE) { $name = $this->getFullyQualifiedName($stmt->name); @@ -216,7 +215,7 @@ // Store creation for the rest of this code snippet so we can find local // issue too - $this->currentScope[strtolower($name)] = $this->getScopeType($stmt); + $this->currentScope[strtolower($name)] = $scopeType; } /** @@ -304,6 +303,9 @@ /** * Get a symbol type key for storing in the scope name cache. * + * @deprecated No longer used. Scope type should be passed into ensureCanDefine directly. + * @codeCoverageIgnore + * * @param Stmt $stmt * * @return string @@ -361,7 +363,7 @@ */ protected function traitExists($name) { - return $this->checkTraits && (trait_exists($name) || $this->findInScope($name) === self::TRAIT_TYPE); + return trait_exists($name) || $this->findInScope($name) === self::TRAIT_TYPE; } /** diff -r e200cb7efeb3 -r c2387f117808 vendor/psy/psysh/src/Command/DocCommand.php --- a/vendor/psy/psysh/src/Command/DocCommand.php Thu Apr 26 11:26:54 2018 +0100 +++ b/vendor/psy/psysh/src/Command/DocCommand.php Tue Jul 10 15:07:59 2018 +0100 @@ -14,6 +14,7 @@ use Psy\Formatter\DocblockFormatter; use Psy\Formatter\SignatureFormatter; use Psy\Input\CodeArgument; +use Psy\Reflection\ReflectionClassConstant; use Psy\Reflection\ReflectionLanguageConstruct; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; @@ -101,6 +102,18 @@ $id = $reflector->class . '::$' . $reflector->name; break; + case 'ReflectionClassConstant': + case 'Psy\Reflection\ReflectionClassConstant': + // @todo this is going to collide with ReflectionMethod ids + // someday... start running the query by id + type if the DB + // supports it. + $id = $reflector->class . '::' . $reflector->name; + break; + + case 'Psy\Reflection\ReflectionConstant_': + $id = $reflector->name; + break; + default: return false; } diff -r e200cb7efeb3 -r c2387f117808 vendor/psy/psysh/src/Command/ListCommand/ClassConstantEnumerator.php --- a/vendor/psy/psysh/src/Command/ListCommand/ClassConstantEnumerator.php Thu Apr 26 11:26:54 2018 +0100 +++ b/vendor/psy/psysh/src/Command/ListCommand/ClassConstantEnumerator.php Tue Jul 10 15:07:59 2018 +0100 @@ -11,7 +11,7 @@ namespace Psy\Command\ListCommand; -use Psy\Reflection\ReflectionConstant; +use Psy\Reflection\ReflectionClassConstant; use Symfony\Component\Console\Input\InputInterface; /** @@ -68,7 +68,7 @@ $constants = []; foreach ($reflector->getConstants() as $name => $constant) { - $constReflector = new ReflectionConstant($reflector, $name); + $constReflector = ReflectionClassConstant::create($reflector, $name); if ($noInherit && $constReflector->getDeclaringClass()->getName() !== $className) { continue; diff -r e200cb7efeb3 -r c2387f117808 vendor/psy/psysh/src/Command/ListCommand/ClassEnumerator.php --- a/vendor/psy/psysh/src/Command/ListCommand/ClassEnumerator.php Thu Apr 26 11:26:54 2018 +0100 +++ b/vendor/psy/psysh/src/Command/ListCommand/ClassEnumerator.php Tue Jul 10 15:07:59 2018 +0100 @@ -50,7 +50,7 @@ $ret = array_merge($ret, $this->filterClasses('Interfaces', get_declared_interfaces(), $internal, $user)); } - if (function_exists('get_declared_traits') && $input->getOption('traits')) { + if ($input->getOption('traits')) { $ret = array_merge($ret, $this->filterClasses('Traits', get_declared_traits(), $internal, $user)); } diff -r e200cb7efeb3 -r c2387f117808 vendor/psy/psysh/src/Command/ListCommand/TraitEnumerator.php --- a/vendor/psy/psysh/src/Command/ListCommand/TraitEnumerator.php Thu Apr 26 11:26:54 2018 +0100 +++ b/vendor/psy/psysh/src/Command/ListCommand/TraitEnumerator.php Tue Jul 10 15:07:59 2018 +0100 @@ -32,11 +32,6 @@ */ protected function listItems(InputInterface $input, \Reflector $reflector = null, $target = null) { - // bail early if current PHP doesn't know about traits. - if (!function_exists('trait_exists')) { - return; - } - // only list traits when no Reflector is present. // // @todo make a NamespaceReflector and pass that in for commands like: diff -r e200cb7efeb3 -r c2387f117808 vendor/psy/psysh/src/Command/ReflectingCommand.php --- a/vendor/psy/psysh/src/Command/ReflectingCommand.php Thu Apr 26 11:26:54 2018 +0100 +++ b/vendor/psy/psysh/src/Command/ReflectingCommand.php Tue Jul 10 15:07:59 2018 +0100 @@ -14,6 +14,7 @@ use Psy\CodeCleaner\NoReturnValue; use Psy\Context; use Psy\ContextAware; +use Psy\Exception\ErrorException; use Psy\Exception\RuntimeException; use Psy\Util\Mirror; @@ -84,6 +85,8 @@ /** * Resolve a class or function name (with the current shell namespace). * + * @throws ErrorException when `self` or `static` is used in a non-class scope + * * @param string $name * @param bool $includeFunctions (default: false) * @@ -91,11 +94,27 @@ */ protected function resolveName($name, $includeFunctions = false) { + $shell = $this->getApplication(); + + // While not *technically* 100% accurate, let's treat `self` and `static` as equivalent. + if (in_array(strtolower($name), ['self', 'static'])) { + if ($boundClass = $shell->getBoundClass()) { + return $boundClass; + } + + if ($boundObject = $shell->getBoundObject()) { + return get_class($boundObject); + } + + $msg = sprintf('Cannot use "%s" when no class scope is active', strtolower($name)); + throw new ErrorException($msg, 0, E_USER_ERROR, "eval()'d code", 1); + } + if (substr($name, 0, 1) === '\\') { return $name; } - if ($namespace = $this->getApplication()->getNamespace()) { + if ($namespace = $shell->getNamespace()) { $fullName = $namespace . '\\' . $name; if (class_exists($fullName) || interface_exists($fullName) || ($includeFunctions && function_exists($fullName))) { @@ -250,7 +269,8 @@ break; case 'ReflectionProperty': - case 'Psy\Reflection\ReflectionConstant': + case 'ReflectionClassConstant': + case 'Psy\Reflection\ReflectionClassConstant': $classReflector = $reflector->getDeclaringClass(); $vars['__class'] = $classReflector->name; if ($classReflector->inNamespace()) { @@ -262,6 +282,12 @@ $vars['__dir'] = dirname($fileName); } break; + + case 'Psy\Reflection\ReflectionConstant_': + if ($reflector->inNamespace()) { + $vars['__namespace'] = $reflector->getNamespaceName(); + } + break; } if ($reflector instanceof \ReflectionClass || $reflector instanceof \ReflectionFunctionAbstract) { diff -r e200cb7efeb3 -r c2387f117808 vendor/psy/psysh/src/Command/ThrowUpCommand.php --- a/vendor/psy/psysh/src/Command/ThrowUpCommand.php Thu Apr 26 11:26:54 2018 +0100 +++ b/vendor/psy/psysh/src/Command/ThrowUpCommand.php Tue Jul 10 15:07:59 2018 +0100 @@ -12,9 +12,11 @@ namespace Psy\Command; use PhpParser\Node\Arg; +use PhpParser\Node\Expr\New_; use PhpParser\Node\Expr\StaticCall; use PhpParser\Node\Expr\Variable; use PhpParser\Node\Name\FullyQualified as FullyQualifiedName; +use PhpParser\Node\Scalar\String_; use PhpParser\Node\Stmt\Throw_; use PhpParser\PrettyPrinter\Standard as Printer; use Psy\Context; @@ -85,6 +87,7 @@ >>> throw-up >>> throw-up $e >>> throw-up new Exception('WHEEEEEE!') +>>> throw-up "bye!" HELP ); } @@ -126,13 +129,24 @@ $code = 'parse($code); - - if (count($expr) !== 1) { + $nodes = $this->parse($code); + if (count($nodes) !== 1) { throw new \InvalidArgumentException('No idea how to throw this'); } - return [new Arg($expr[0])]; + $node = $nodes[0]; + + // Make this work for PHP Parser v3.x + $expr = isset($node->expr) ? $node->expr : $node; + + $args = [new Arg($expr, false, false, $node->getAttributes())]; + + // Allow throwing via a string, e.g. `throw-up "SUP"` + if ($expr instanceof String_) { + return [new New_(new FullyQualifiedName('Exception'), $args)]; + } + + return $args; } /** diff -r e200cb7efeb3 -r c2387f117808 vendor/psy/psysh/src/Command/TimeitCommand.php --- a/vendor/psy/psysh/src/Command/TimeitCommand.php Thu Apr 26 11:26:54 2018 +0100 +++ b/vendor/psy/psysh/src/Command/TimeitCommand.php Tue Jul 10 15:07:59 2018 +0100 @@ -11,7 +11,11 @@ namespace Psy\Command; +use PhpParser\NodeTraverser; +use PhpParser\PrettyPrinter\Standard as Printer; +use Psy\Command\TimeitCommand\TimeitVisitor; use Psy\Input\CodeArgument; +use Psy\ParserFactory; use Psy\Shell; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Input\InputOption; @@ -25,6 +29,29 @@ const RESULT_MSG = 'Command took %.6f seconds to complete.'; const AVG_RESULT_MSG = 'Command took %.6f seconds on average (%.6f median; %.6f total) to complete.'; + private static $start = null; + private static $times = []; + + private $parser; + private $traverser; + private $printer; + + /** + * {@inheritdoc} + */ + public function __construct($name = null) + { + $parserFactory = new ParserFactory(); + $this->parser = $parserFactory->createParser(); + + $this->traverser = new NodeTraverser(); + $this->traverser->addVisitor(new TimeitVisitor()); + + $this->printer = new Printer(); + + parent::__construct($name); + } + /** * {@inheritdoc} */ @@ -57,15 +84,20 @@ $num = $input->getOption('num') ?: 1; $shell = $this->getApplication(); - $times = []; + $instrumentedCode = $this->instrumentCode($code); + + self::$times = []; + for ($i = 0; $i < $num; $i++) { - $start = microtime(true); - $_ = $shell->execute($code); - $times[] = microtime(true) - $start; + $_ = $shell->execute($instrumentedCode); + $this->ensureEndMarked(); } $shell->writeReturnValue($_); + $times = self::$times; + self::$times = []; + if ($num === 1) { $output->writeln(sprintf(self::RESULT_MSG, $times[0])); } else { @@ -76,4 +108,89 @@ $output->writeln(sprintf(self::AVG_RESULT_MSG, $total / $num, $median, $total)); } } + + /** + * Internal method for marking the start of timeit execution. + * + * A static call to this method will be injected at the start of the timeit + * input code to instrument the call. We will use the saved start time to + * more accurately calculate time elapsed during execution. + */ + public static function markStart() + { + self::$start = microtime(true); + } + + /** + * Internal method for marking the end of timeit execution. + * + * A static call to this method is injected by TimeitVisitor at the end + * of the timeit input code to instrument the call. + * + * Note that this accepts an optional $ret parameter, which is used to pass + * the return value of the last statement back out of timeit. This saves us + * a bunch of code rewriting shenanigans. + * + * @param mixed $ret + * + * @return mixed it just passes $ret right back + */ + public static function markEnd($ret = null) + { + self::$times[] = microtime(true) - self::$start; + self::$start = null; + + return $ret; + } + + /** + * Ensure that the end of code execution was marked. + * + * The end *should* be marked in the instrumented code, but just in case + * we'll add a fallback here. + */ + private function ensureEndMarked() + { + if (self::$start !== null) { + self::markEnd(); + } + } + + /** + * Instrument code for timeit execution. + * + * This inserts `markStart` and `markEnd` calls to ensure that (reasonably) + * accurate times are recorded for just the code being executed. + * + * @param string $code + * + * @return string + */ + private function instrumentCode($code) + { + return $this->printer->prettyPrint($this->traverser->traverse($this->parse($code))); + } + + /** + * Lex and parse a string of code into statements. + * + * @param string $code + * + * @return array Statements + */ + private function parse($code) + { + $code = 'parser->parse($code); + } catch (\PhpParser\Error $e) { + if (strpos($e->getMessage(), 'unexpected EOF') === false) { + throw $e; + } + + // If we got an unexpected EOF, let's try it again with a semicolon. + return $this->parser->parse($code . ';'); + } + } } diff -r e200cb7efeb3 -r c2387f117808 vendor/psy/psysh/src/Command/TimeitCommand/TimeitVisitor.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vendor/psy/psysh/src/Command/TimeitCommand/TimeitVisitor.php Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,139 @@ +functionDepth = 0; + } + + /** + * {@inheritdoc} + */ + public function enterNode(Node $node) + { + // keep track of nested function-like nodes, because they can have + // returns statements... and we don't want to call markEnd for those. + if ($node instanceof FunctionLike) { + $this->functionDepth++; + + return; + } + + // replace any top-level `return` statements with a `markEnd` call + if ($this->functionDepth === 0 && $node instanceof Return_) { + return new Return_($this->getEndCall($node->expr), $node->getAttributes()); + } + } + + /** + * {@inheritdoc} + */ + public function leaveNode(Node $node) + { + if ($node instanceof FunctionLike) { + $this->functionDepth--; + } + } + + /** + * {@inheritdoc} + */ + public function afterTraverse(array $nodes) + { + // prepend a `markStart` call + array_unshift($nodes, $this->maybeExpression($this->getStartCall())); + + // append a `markEnd` call (wrapping the final node, if it's an expression) + $last = $nodes[count($nodes) - 1]; + if ($last instanceof Expr) { + array_pop($nodes); + $nodes[] = $this->getEndCall($last); + } elseif ($last instanceof Expression) { + array_pop($nodes); + $nodes[] = new Expression($this->getEndCall($last->expr), $last->getAttributes()); + } elseif ($last instanceof Return_) { + // nothing to do here, we're already ending with a return call + } else { + $nodes[] = $this->maybeExpression($this->getEndCall()); + } + + return $nodes; + } + + /** + * Get PhpParser AST nodes for a `markStart` call. + * + * @return PhpParser\Node\Expr\StaticCall + */ + private function getStartCall() + { + return new StaticCall(new FullyQualifiedName('Psy\Command\TimeitCommand'), 'markStart'); + } + + /** + * Get PhpParser AST nodes for a `markEnd` call. + * + * Optionally pass in a return value. + * + * @param Expr|null $arg + * + * @return PhpParser\Node\Expr\StaticCall + */ + private function getEndCall(Expr $arg = null) + { + if ($arg === null) { + $arg = NoReturnValue::create(); + } + + return new StaticCall(new FullyQualifiedName('Psy\Command\TimeitCommand'), 'markEnd', [new Arg($arg)]); + } + + /** + * Compatibility shim for PHP Parser 3.x. + * + * Wrap $expr in a PhpParser\Node\Stmt\Expression if the class exists. + * + * @param PhpParser\Node $expr + * @param array $attrs + * + * @return PhpParser\Node\Expr|PhpParser\Node\Stmt\Expression + */ + private function maybeExpression($expr, $attrs = []) + { + return class_exists('PhpParser\Node\Stmt\Expression') ? new Expression($expr, $attrs) : $expr; + } +} diff -r e200cb7efeb3 -r c2387f117808 vendor/psy/psysh/src/Command/TraceCommand.php --- a/vendor/psy/psysh/src/Command/TraceCommand.php Thu Apr 26 11:26:54 2018 +0100 +++ b/vendor/psy/psysh/src/Command/TraceCommand.php Tue Jul 10 15:07:59 2018 +0100 @@ -126,7 +126,7 @@ $line = isset($trace[$i]['line']) ? $trace[$i]['line'] : 'n/a'; // Leave execution loop out of the `eval()'d code` lines - if (preg_match("#/src/ExecutionClosure.php\(\d+\) : eval\(\)'d code$#", str_replace('\\', '/', $file))) { + if (preg_match("#/src/Execution(?:Loop)?Closure.php\(\d+\) : eval\(\)'d code$#", str_replace('\\', '/', $file))) { $file = "eval()'d code"; } diff -r e200cb7efeb3 -r c2387f117808 vendor/psy/psysh/src/Compiler.php --- a/vendor/psy/psysh/src/Compiler.php Thu Apr 26 11:26:54 2018 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,161 +0,0 @@ -version = Shell::VERSION; - - $phar = new \Phar($pharFile, 0, 'psysh.phar'); - $phar->setSignatureAlgorithm(\Phar::SHA1); - - $phar->startBuffering(); - - $finder = Finder::create() - ->files() - ->ignoreVCS(true) - ->name('*.php') - ->notName('Compiler.php') - ->in(__DIR__); - - foreach ($finder as $file) { - $this->addFile($phar, $file); - } - - $finder = Finder::create() - ->files() - ->ignoreVCS(true) - ->name('*.php') - ->exclude('Tests') - ->exclude('tests') - ->exclude('Test') - ->exclude('test') - ->in(dirname(__DIR__) . '/build-vendor'); - - foreach ($finder as $file) { - $this->addFile($phar, $file); - } - - // Stubs - $phar->setStub($this->getStub()); - - $phar->stopBuffering(); - - unset($phar); - } - - /** - * Add a file to the psysh Phar. - * - * @param \Phar $phar - * @param \SplFileInfo $file - * @param bool $strip (default: true) - */ - private function addFile($phar, $file, $strip = true) - { - $path = str_replace(dirname(__DIR__) . DIRECTORY_SEPARATOR, '', $file->getRealPath()); - - $content = file_get_contents($file); - if ($strip) { - $content = $this->stripWhitespace($content); - } elseif ('LICENSE' === basename($file)) { - $content = "\n" . $content . "\n"; - } - - $phar->addFromString($path, $content); - } - - /** - * Removes whitespace from a PHP source string while preserving line numbers. - * - * @param string $source A PHP string - * - * @return string The PHP string with the whitespace removed - */ - private function stripWhitespace($source) - { - if (!function_exists('token_get_all')) { - return $source; - } - - $output = ''; - foreach (token_get_all($source) as $token) { - if (is_string($token)) { - $output .= $token; - } elseif (in_array($token[0], [T_COMMENT, T_DOC_COMMENT])) { - $output .= str_repeat("\n", substr_count($token[1], "\n")); - } elseif (T_WHITESPACE === $token[0]) { - // reduce wide spaces - $whitespace = preg_replace('{[ \t]+}', ' ', $token[1]); - // normalize newlines to \n - $whitespace = preg_replace('{(?:\r\n|\r|\n)}', "\n", $whitespace); - // trim leading spaces - $whitespace = preg_replace('{\n +}', "\n", $whitespace); - $output .= $whitespace; - } else { - $output .= $token[1]; - } - } - - return $output; - } - - private static function getStubLicense() - { - $license = file_get_contents(dirname(__DIR__) . '/LICENSE'); - $license = str_replace('The MIT License (MIT)', '', $license); - $license = str_replace("\n", "\n * ", trim($license)); - - return $license; - } - - const STUB_AUTOLOAD = <<<'EOS' - Phar::mapPhar('psysh.phar'); - require 'phar://psysh.phar/build-vendor/autoload.php'; -EOS; - - /** - * Get a Phar stub for psysh. - * - * This is basically the psysh bin, with the autoload require statements swapped out. - * - * @return string - */ - private function getStub() - { - $content = file_get_contents(dirname(__DIR__) . '/bin/psysh'); - $content = preg_replace('{/\* <<<.*?>>> \*/}sm', self::STUB_AUTOLOAD, $content); - $content = preg_replace('/\\(c\\) .*?with this source code./sm', self::getStubLicense(), $content); - - $content .= '__HALT_COMPILER();'; - - return $content; - } -} diff -r e200cb7efeb3 -r c2387f117808 vendor/psy/psysh/src/Configuration.php --- a/vendor/psy/psysh/src/Configuration.php Thu Apr 26 11:26:54 2018 +0100 +++ b/vendor/psy/psysh/src/Configuration.php Tue Jul 10 15:07:59 2018 +0100 @@ -880,7 +880,7 @@ { if (!isset($this->pager) && $this->usePcntl()) { if ($pager = ini_get('cli.pager')) { - // use the default pager (5.4+) + // use the default pager $this->pager = $pager; } elseif ($less = exec('which less 2>/dev/null')) { // check for the presence of less... diff -r e200cb7efeb3 -r c2387f117808 vendor/psy/psysh/src/Context.php --- a/vendor/psy/psysh/src/Context.php Thu Apr 26 11:26:54 2018 +0100 +++ b/vendor/psy/psysh/src/Context.php Tue Jul 10 15:07:59 2018 +0100 @@ -33,6 +33,7 @@ private $lastException; private $lastStdout; private $boundObject; + private $boundClass; /** * Get a context variable. @@ -221,11 +222,14 @@ /** * Set the bound object ($this variable) for the interactive shell. * + * Note that this unsets the bound class, if any exists. + * * @param object|null $boundObject */ public function setBoundObject($boundObject) { $this->boundObject = is_object($boundObject) ? $boundObject : null; + $this->boundClass = null; } /** @@ -239,6 +243,29 @@ } /** + * Set the bound class (self) for the interactive shell. + * + * Note that this unsets the bound object, if any exists. + * + * @param string|null $boundClass + */ + public function setBoundClass($boundClass) + { + $this->boundClass = (is_string($boundClass) && $boundClass !== '') ? $boundClass : null; + $this->boundObject = null; + } + + /** + * Get the bound class (self) for the interactive shell. + * + * @return string|null + */ + public function getBoundClass() + { + return $this->boundClass; + } + + /** * Set command-scope magic variables: $__class, $__file, etc. * * @param array $commandScopeVariables diff -r e200cb7efeb3 -r c2387f117808 vendor/psy/psysh/src/Exception/TypeErrorException.php --- a/vendor/psy/psysh/src/Exception/TypeErrorException.php Thu Apr 26 11:26:54 2018 +0100 +++ b/vendor/psy/psysh/src/Exception/TypeErrorException.php Tue Jul 10 15:07:59 2018 +0100 @@ -50,6 +50,6 @@ */ public static function fromTypeError(\TypeError $e) { - return new self($e->getMessage(), $e->getLine()); + return new self($e->getMessage(), $e->getCode()); } } diff -r e200cb7efeb3 -r c2387f117808 vendor/psy/psysh/src/ExecutionClosure.php --- a/vendor/psy/psysh/src/ExecutionClosure.php Thu Apr 26 11:26:54 2018 +0100 +++ b/vendor/psy/psysh/src/ExecutionClosure.php Tue Jul 10 15:07:59 2018 +0100 @@ -25,7 +25,7 @@ */ public function __construct(Shell $__psysh__) { - $exec = function () use ($__psysh__) { + $this->setClosure($__psysh__, function () use ($__psysh__) { try { // Restore execution scope variables extract($__psysh__->getScopeVariables(false)); @@ -66,20 +66,27 @@ $__psysh__->setScopeVariables(get_defined_vars()); return $_; - }; + }); + } + /** + * Set the closure instance. + * + * @param Shell $psysh + * @param \Closure $closure + */ + protected function setClosure(Shell $shell, \Closure $closure) + { if (self::shouldBindClosure()) { - $that = $__psysh__->getBoundObject(); + $that = $shell->getBoundObject(); if (is_object($that)) { - $this->closure = $exec->bindTo($that, get_class($that)); + $closure = $closure->bindTo($that, get_class($that)); } else { - $this->closure = $exec->bindTo(null, null); + $closure = $closure->bindTo(null, $shell->getBoundClass()); } - - return; } - $this->closure = $exec; + $this->closure = $closure; } /** diff -r e200cb7efeb3 -r c2387f117808 vendor/psy/psysh/src/ExecutionLoop.php --- a/vendor/psy/psysh/src/ExecutionLoop.php Thu Apr 26 11:26:54 2018 +0100 +++ b/vendor/psy/psysh/src/ExecutionLoop.php Tue Jul 10 15:07:59 2018 +0100 @@ -11,10 +11,7 @@ namespace Psy; -use Psy\Exception\BreakException; use Psy\Exception\ErrorException; -use Psy\Exception\ThrowUpException; -use Psy\Exception\TypeErrorException; /** * The Psy Shell execution loop. @@ -32,33 +29,8 @@ { $this->loadIncludes($shell); - $closure = new ExecutionClosure($shell); - - do { - $shell->beforeLoop(); - - try { - $shell->getInput(); - $_ = $closure->execute(); - $shell->writeReturnValue($_); - } catch (BreakException $_e) { - $shell->writeException($_e); - - return; - } catch (ThrowUpException $_e) { - $shell->writeException($_e); - - throw $_e; - } catch (\TypeError $_e) { - $shell->writeException(TypeErrorException::fromTypeError($_e)); - } catch (\Error $_e) { - $shell->writeException(ErrorException::fromError($_e)); - } catch (\Exception $_e) { - $shell->writeException($_e); - } - - $shell->afterLoop(); - } while (true); + $closure = new ExecutionLoopClosure($shell); + $closure->execute(); } /** diff -r e200cb7efeb3 -r c2387f117808 vendor/psy/psysh/src/ExecutionLoop/ProcessForker.php --- a/vendor/psy/psysh/src/ExecutionLoop/ProcessForker.php Thu Apr 26 11:26:54 2018 +0100 +++ b/vendor/psy/psysh/src/ExecutionLoop/ProcessForker.php Tue Jul 10 15:07:59 2018 +0100 @@ -65,9 +65,24 @@ $read = [$down]; $write = null; $except = null; - if (stream_select($read, $write, $except, null) === false) { - throw new \RuntimeException('Error waiting for execution loop'); - } + + do { + $n = @stream_select($read, $write, $except, null); + + if ($n === 0) { + throw new \RuntimeException('Process timed out waiting for execution loop'); + } + + if ($n === false) { + $err = error_get_last(); + if (!isset($err['message']) || stripos($err['message'], 'interrupted system call') === false) { + $msg = $err['message'] ? + sprintf('Error waiting for execution loop: %s', $err['message']) : + 'Error waiting for execution loop'; + throw new \RuntimeException($msg); + } + } + } while ($n < 1); $content = stream_get_contents($down); fclose($down); diff -r e200cb7efeb3 -r c2387f117808 vendor/psy/psysh/src/ExecutionLoopClosure.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vendor/psy/psysh/src/ExecutionLoopClosure.php Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,99 @@ +setClosure($__psysh__, function () use ($__psysh__) { + // Restore execution scope variables + extract($__psysh__->getScopeVariables(false)); + + do { + $__psysh__->beforeLoop(); + + try { + $__psysh__->getInput(); + + try { + // Buffer stdout; we'll need it later + ob_start([$__psysh__, 'writeStdout'], 1); + + // Convert all errors to exceptions + set_error_handler([$__psysh__, 'handleError']); + + // Evaluate the current code buffer + $_ = eval($__psysh__->onExecute($__psysh__->flushCode() ?: ExecutionClosure::NOOP_INPUT)); + } catch (\Throwable $_e) { + // Clean up on our way out. + restore_error_handler(); + if (ob_get_level() > 0) { + ob_end_clean(); + } + + throw $_e; + } catch (\Exception $_e) { + // Clean up on our way out. + restore_error_handler(); + if (ob_get_level() > 0) { + ob_end_clean(); + } + + throw $_e; + } + + // Won't be needing this anymore + restore_error_handler(); + + // Flush stdout (write to shell output, plus save to magic variable) + ob_end_flush(); + + // Save execution scope variables for next time + $__psysh__->setScopeVariables(get_defined_vars()); + + $__psysh__->writeReturnValue($_); + } catch (BreakException $_e) { + $__psysh__->writeException($_e); + + return; + } catch (ThrowUpException $_e) { + $__psysh__->writeException($_e); + + throw $_e; + } catch (\TypeError $_e) { + $__psysh__->writeException(TypeErrorException::fromTypeError($_e)); + } catch (\Error $_e) { + $__psysh__->writeException(ErrorException::fromError($_e)); + } catch (\Exception $_e) { + $__psysh__->writeException($_e); + } + + $__psysh__->afterLoop(); + } while (true); + }); + } +} diff -r e200cb7efeb3 -r c2387f117808 vendor/psy/psysh/src/Formatter/CodeFormatter.php --- a/vendor/psy/psysh/src/Formatter/CodeFormatter.php Thu Apr 26 11:26:54 2018 +0100 +++ b/vendor/psy/psysh/src/Formatter/CodeFormatter.php Tue Jul 10 15:07:59 2018 +0100 @@ -37,10 +37,6 @@ $colorMode = $colorMode ?: Configuration::COLOR_MODE_AUTO; - if ($reflector instanceof \ReflectionGenerator) { - $reflector = $reflector->getFunction(); - } - if ($fileName = $reflector->getFileName()) { if (!is_file($fileName)) { throw new RuntimeException('Source code unavailable'); @@ -70,7 +66,6 @@ private static function isReflectable(\Reflector $reflector) { return $reflector instanceof \ReflectionClass || - $reflector instanceof \ReflectionFunctionAbstract || - $reflector instanceof \ReflectionGenerator; + $reflector instanceof \ReflectionFunctionAbstract; } } diff -r e200cb7efeb3 -r c2387f117808 vendor/psy/psysh/src/Formatter/SignatureFormatter.php --- a/vendor/psy/psysh/src/Formatter/SignatureFormatter.php Thu Apr 26 11:26:54 2018 +0100 +++ b/vendor/psy/psysh/src/Formatter/SignatureFormatter.php Tue Jul 10 15:07:59 2018 +0100 @@ -11,7 +11,8 @@ namespace Psy\Formatter; -use Psy\Reflection\ReflectionConstant; +use Psy\Reflection\ReflectionClassConstant; +use Psy\Reflection\ReflectionConstant_; use Psy\Reflection\ReflectionLanguageConstruct; use Psy\Util\Json; use Symfony\Component\Console\Formatter\OutputFormatter; @@ -41,8 +42,9 @@ case $reflector instanceof \ReflectionClass: return self::formatClass($reflector); - case $reflector instanceof ReflectionConstant: - return self::formatConstant($reflector); + case $reflector instanceof ReflectionClassConstant: + case $reflector instanceof \ReflectionClassConstant: + return self::formatClassConstant($reflector); case $reflector instanceof \ReflectionMethod: return self::formatMethod($reflector); @@ -50,6 +52,9 @@ case $reflector instanceof \ReflectionProperty: return self::formatProperty($reflector); + case $reflector instanceof ReflectionConstant_: + return self::formatConstant($reflector); + default: throw new \InvalidArgumentException('Unexpected Reflector class: ' . get_class($reflector)); } @@ -70,14 +75,20 @@ /** * Print the method, property or class modifiers. * - * Technically this should be a trait. Can't wait for 5.4 :) - * * @param \Reflector $reflector * * @return string Formatted modifiers */ private static function formatModifiers(\Reflector $reflector) { + if ($reflector instanceof \ReflectionClass && $reflector->isTrait()) { + // For some reason, PHP 5.x returns `abstract public` modifiers for + // traits. Let's just ignore that business entirely. + if (version_compare(PHP_VERSION, '7.0.0', '<')) { + return []; + } + } + return implode(' ', array_map(function ($modifier) { return sprintf('%s', $modifier); }, \Reflection::getModifierNames($reflector->getModifiers()))); @@ -127,11 +138,11 @@ /** * Format a constant signature. * - * @param ReflectionConstant $reflector + * @param ReflectionClassConstant|\ReflectionClassConstant $reflector * * @return string Formatted signature */ - private static function formatConstant(ReflectionConstant $reflector) + private static function formatClassConstant($reflector) { $value = $reflector->getValue(); $style = self::getTypeStyle($value); @@ -146,6 +157,27 @@ } /** + * Format a constant signature. + * + * @param ReflectionConstant_ $reflector + * + * @return string Formatted signature + */ + private static function formatConstant($reflector) + { + $value = $reflector->getValue(); + $style = self::getTypeStyle($value); + + return sprintf( + 'define(%s, <%s>%s)', + OutputFormatter::escape(Json::encode($reflector->getName())), + $style, + OutputFormatter::escape(Json::encode($value)), + $style + ); + } + + /** * Helper for getting output style for a given value's type. * * @param mixed $value @@ -161,7 +193,7 @@ } elseif (is_bool($value) || is_null($value)) { return 'bool'; } else { - return 'strong'; + return 'strong'; // @codeCoverageIgnore } } @@ -238,11 +270,14 @@ // come to think of it, the only time I've seen this is with the intl extension. // Hax: we'll try to extract it :P + + // @codeCoverageIgnoreStart $chunks = explode('$' . $param->getName(), (string) $param); $chunks = explode(' ', trim($chunks[0])); $guess = end($chunks); $hint = sprintf('%s ', $guess); + // @codeCoverageIgnoreEnd } if ($param->isOptional()) { diff -r e200cb7efeb3 -r c2387f117808 vendor/psy/psysh/src/Input/FilterOptions.php --- a/vendor/psy/psysh/src/Input/FilterOptions.php Thu Apr 26 11:26:54 2018 +0100 +++ b/vendor/psy/psysh/src/Input/FilterOptions.php Tue Jul 10 15:07:59 2018 +0100 @@ -137,6 +137,7 @@ try { preg_match($pattern, ''); } catch (ErrorException $e) { + restore_error_handler(); throw new RuntimeException(str_replace('preg_match(): ', 'Invalid regular expression: ', $e->getRawMessage())); } restore_error_handler(); diff -r e200cb7efeb3 -r c2387f117808 vendor/psy/psysh/src/Input/ShellInput.php --- a/vendor/psy/psysh/src/Input/ShellInput.php Thu Apr 26 11:26:54 2018 +0100 +++ b/vendor/psy/psysh/src/Input/ShellInput.php Tue Jul 10 15:07:59 2018 +0100 @@ -105,7 +105,9 @@ ]; } else { // should never happen + // @codeCoverageIgnoreStart throw new \InvalidArgumentException(sprintf('Unable to parse input near "... %s ..."', substr($input, $cursor, 10))); + // @codeCoverageIgnoreEnd } $cursor += strlen($match[0]); @@ -168,6 +170,10 @@ return; } + // (copypasta) + // + // @codeCoverageIgnoreStart + // if last argument isArray(), append token to last argument if ($this->definition->hasArgument($c - 1) && $this->definition->getArgument($c - 1)->isArray()) { $arg = $this->definition->getArgument($c - 1); @@ -183,9 +189,11 @@ } throw new \RuntimeException(sprintf('No arguments expected, got "%s".', $token)); + // @codeCoverageIgnoreEnd } // Everything below this is copypasta from ArgvInput private methods + // @codeCoverageIgnoreStart /** * Parses a short option. @@ -323,4 +331,6 @@ $this->options[$name] = $value; } } + + // @codeCoverageIgnoreEnd } diff -r e200cb7efeb3 -r c2387f117808 vendor/psy/psysh/src/Reflection/ReflectionClassConstant.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vendor/psy/psysh/src/Reflection/ReflectionClassConstant.php Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,228 @@ +class = $class; + $this->name = $name; + + $constants = $class->getConstants(); + if (!array_key_exists($name, $constants)) { + throw new \InvalidArgumentException('Unknown constant: ' . $name); + } + + $this->value = $constants[$name]; + } + + /** + * Exports a reflection. + * + * @param string|object $class + * @param string $name + * @param bool $return pass true to return the export, as opposed to emitting it + * + * @return null|string + */ + public static function export($class, $name, $return = false) + { + $refl = new self($class, $name); + $value = $refl->getValue(); + + $str = sprintf('Constant [ public %s %s ] { %s }', gettype($value), $refl->getName(), $value); + + if ($return) { + return $str; + } + + echo $str . "\n"; + } + + /** + * Gets the declaring class. + * + * @return \ReflectionClass + */ + public function getDeclaringClass() + { + $parent = $this->class; + + // Since we don't have real reflection constants, we can't see where + // it's actually defined. Let's check for a constant that is also + // available on the parent class which has exactly the same value. + // + // While this isn't _technically_ correct, it's prolly close enough. + do { + $class = $parent; + $parent = $class->getParentClass(); + } while ($parent && $parent->hasConstant($this->name) && $parent->getConstant($this->name) === $this->value); + + return $class; + } + + /** + * Get the constant's docblock. + * + * @return false + */ + public function getDocComment() + { + return false; + } + + /** + * Gets the class constant modifiers. + * + * Since this is only used for PHP < 7.1, we can just return "public". All + * the fancier modifiers are only available on PHP versions which have their + * own ReflectionClassConstant class :) + * + * @return int + */ + public function getModifiers() + { + return \ReflectionMethod::IS_PUBLIC; + } + + /** + * Gets the constant name. + * + * @return string + */ + public function getName() + { + return $this->name; + } + + /** + * Gets the value of the constant. + * + * @return mixed + */ + public function getValue() + { + return $this->value; + } + + /** + * Checks if class constant is private. + * + * @return bool false + */ + public function isPrivate() + { + return false; + } + + /** + * Checks if class constant is protected. + * + * @return bool false + */ + public function isProtected() + { + return false; + } + + /** + * Checks if class constant is public. + * + * @return bool true + */ + public function isPublic() + { + return true; + } + + /** + * To string. + * + * @return string + */ + public function __toString() + { + return $this->getName(); + } + + /** + * Gets the constant's file name. + * + * Currently returns null, because if it returns a file name the signature + * formatter will barf. + */ + public function getFileName() + { + return; + // return $this->class->getFileName(); + } + + /** + * Get the code start line. + * + * @throws \RuntimeException + */ + public function getStartLine() + { + throw new \RuntimeException('Not yet implemented because it\'s unclear what I should do here :)'); + } + + /** + * Get the code end line. + * + * @throws \RuntimeException + */ + public function getEndLine() + { + return $this->getStartLine(); + } + + /** + * Get a ReflectionClassConstant instance. + * + * In PHP >= 7.1, this will return a \ReflectionClassConstant from the + * standard reflection library. For older PHP, it will return this polyfill. + * + * @param string|object $class + * @param string $name + * + * @return ReflectionClassConstant|\ReflectionClassConstant + */ + public static function create($class, $name) + { + if (class_exists('\\ReflectionClassConstant')) { + return new \ReflectionClassConstant($class, $name); + } + + return new self($class, $name); + } +} diff -r e200cb7efeb3 -r c2387f117808 vendor/psy/psysh/src/Reflection/ReflectionConstant.php --- a/vendor/psy/psysh/src/Reflection/ReflectionConstant.php Thu Apr 26 11:26:54 2018 +0100 +++ b/vendor/psy/psysh/src/Reflection/ReflectionConstant.php Tue Jul 10 15:07:59 2018 +0100 @@ -12,140 +12,19 @@ namespace Psy\Reflection; /** - * Somehow the standard reflection library doesn't include constants. - * - * ReflectionConstant corrects that omission. + * @deprecated ReflectionConstant is now ReflectionClassConstant. This class + * name will be reclaimed in the next stable release, to be used for + * ReflectionConstant_ :) */ -class ReflectionConstant implements \Reflector +class ReflectionConstant extends ReflectionClassConstant { - private $class; - private $name; - private $value; - /** - * Construct a ReflectionConstant object. - * - * @param mixed $class - * @param string $name + * {inheritDoc}. */ public function __construct($class, $name) { - if (!$class instanceof \ReflectionClass) { - $class = new \ReflectionClass($class); - } + @trigger_error('ReflectionConstant is now ReflectionClassConstant', E_USER_DEPRECATED); - $this->class = $class; - $this->name = $name; - - $constants = $class->getConstants(); - if (!array_key_exists($name, $constants)) { - throw new \InvalidArgumentException('Unknown constant: ' . $name); - } - - $this->value = $constants[$name]; - } - - /** - * Gets the declaring class. - * - * @return string - */ - public function getDeclaringClass() - { - $parent = $this->class; - - // Since we don't have real reflection constants, we can't see where - // it's actually defined. Let's check for a constant that is also - // available on the parent class which has exactly the same value. - // - // While this isn't _technically_ correct, it's prolly close enough. - do { - $class = $parent; - $parent = $class->getParentClass(); - } while ($parent && $parent->hasConstant($this->name) && $parent->getConstant($this->name) === $this->value); - - return $class; - } - - /** - * Gets the constant name. - * - * @return string - */ - public function getName() - { - return $this->name; - } - - /** - * Gets the value of the constant. - * - * @return mixed - */ - public function getValue() - { - return $this->value; - } - - /** - * Gets the constant's file name. - * - * Currently returns null, because if it returns a file name the signature - * formatter will barf. - */ - public function getFileName() - { - return; - // return $this->class->getFileName(); - } - - /** - * Get the code start line. - * - * @throws \RuntimeException - */ - public function getStartLine() - { - throw new \RuntimeException('Not yet implemented because it\'s unclear what I should do here :)'); - } - - /** - * Get the code end line. - * - * @throws \RuntimeException - */ - public function getEndLine() - { - return $this->getStartLine(); - } - - /** - * Get the constant's docblock. - * - * @return false - */ - public function getDocComment() - { - return false; - } - - /** - * Export the constant? I don't think this is possible. - * - * @throws \RuntimeException - */ - public static function export() - { - throw new \RuntimeException('Not yet implemented because it\'s unclear what I should do here :)'); - } - - /** - * To string. - * - * @return string - */ - public function __toString() - { - return $this->getName(); + parent::__construct($class, $name); } } diff -r e200cb7efeb3 -r c2387f117808 vendor/psy/psysh/src/Reflection/ReflectionConstant_.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vendor/psy/psysh/src/Reflection/ReflectionConstant_.php Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,182 @@ +name = $name; + + if (!defined($name) && !self::isMagicConstant($name)) { + throw new \InvalidArgumentException('Unknown constant: ' . $name); + } + + if (!self::isMagicConstant($name)) { + $this->value = @constant($name); + } + } + + /** + * Exports a reflection. + * + * @param string $name + * @param bool $return pass true to return the export, as opposed to emitting it + * + * @return null|string + */ + public static function export($name, $return = false) + { + $refl = new self($name); + $value = $refl->getValue(); + + $str = sprintf('Constant [ %s %s ] { %s }', gettype($value), $refl->getName(), $value); + + if ($return) { + return $str; + } + + echo $str . "\n"; + } + + public static function isMagicConstant($name) + { + return in_array($name, self::$magicConstants); + } + + /** + * Get the constant's docblock. + * + * @return false + */ + public function getDocComment() + { + return false; + } + + /** + * Gets the constant name. + * + * @return string + */ + public function getName() + { + return $this->name; + } + + /** + * Gets the namespace name. + * + * Returns '' when the constant is not namespaced. + * + * @return string + */ + public function getNamespaceName() + { + if (!$this->inNamespace()) { + return ''; + } + + return preg_replace('/\\\\[^\\\\]+$/', '', $this->name); + } + + /** + * Gets the value of the constant. + * + * @return mixed + */ + public function getValue() + { + return $this->value; + } + + /** + * Checks if this constant is defined in a namespace. + * + * @return bool + */ + public function inNamespace() + { + return strpos($this->name, '\\') !== false; + } + + /** + * To string. + * + * @return string + */ + public function __toString() + { + return $this->getName(); + } + + /** + * Gets the constant's file name. + * + * Currently returns null, because if it returns a file name the signature + * formatter will barf. + */ + public function getFileName() + { + return; + // return $this->class->getFileName(); + } + + /** + * Get the code start line. + * + * @throws \RuntimeException + */ + public function getStartLine() + { + throw new \RuntimeException('Not yet implemented because it\'s unclear what I should do here :)'); + } + + /** + * Get the code end line. + * + * @throws \RuntimeException + */ + public function getEndLine() + { + return $this->getStartLine(); + } +} diff -r e200cb7efeb3 -r c2387f117808 vendor/psy/psysh/src/Reflection/ReflectionLanguageConstruct.php --- a/vendor/psy/psysh/src/Reflection/ReflectionLanguageConstruct.php Thu Apr 26 11:26:54 2018 +0100 +++ b/vendor/psy/psysh/src/Reflection/ReflectionLanguageConstruct.php Tue Jul 10 15:07:59 2018 +0100 @@ -76,7 +76,7 @@ */ public function __construct($keyword) { - if (self::isLanguageConstruct($keyword)) { + if (!self::isLanguageConstruct($keyword)) { throw new \InvalidArgumentException('Unknown language construct: ' . $keyword); } @@ -129,6 +129,18 @@ } /** + * Gets the file name from a language construct. + * + * (Hint: it always returns false) + * + * @return bool false + */ + public function getFileName() + { + return false; + } + + /** * To string. * * @return string diff -r e200cb7efeb3 -r c2387f117808 vendor/psy/psysh/src/Shell.php --- a/vendor/psy/psysh/src/Shell.php Thu Apr 26 11:26:54 2018 +0100 +++ b/vendor/psy/psysh/src/Shell.php Tue Jul 10 15:07:59 2018 +0100 @@ -47,7 +47,7 @@ */ class Shell extends Application { - const VERSION = 'v0.9.3'; + const VERSION = 'v0.9.6'; const PROMPT = '>>> '; const BUFF_PROMPT = '... '; @@ -118,14 +118,14 @@ * @see Psy\debug * @deprecated will be removed in 1.0. Use \Psy\debug instead * - * @param array $vars Scope variables from the calling context (default: array()) - * @param object $boundObject Bound object ($this) value for the shell + * @param array $vars Scope variables from the calling context (default: array()) + * @param object|string $bindTo Bound object ($this) or class (self) value for the shell * * @return array Scope variables from the debugger session */ - public static function debug(array $vars = [], $boundObject = null) + public static function debug(array $vars = [], $bindTo = null) { - return \Psy\debug($vars, $boundObject); + return \Psy\debug($vars, $bindTo); } /** @@ -392,13 +392,14 @@ } // handle empty input - if (trim($input) === '') { + if (trim($input) === '' && !$this->codeBufferOpen) { continue; } $input = $this->onInput($input); - if ($this->hasCommand($input)) { + // If the input isn't in an open string or comment, check for commands to run. + if ($this->hasCommand($input) && !$this->inputInOpenStringOrComment($input)) { $this->addHistory($input); $this->runCommand($input); @@ -410,6 +411,28 @@ } /** + * Check whether the code buffer (plus current input) is in an open string or comment. + * + * @param string $input current line of input + * + * @return bool true if the input is in an open string or comment + */ + private function inputInOpenStringOrComment($input) + { + if (!$this->hasCode()) { + return; + } + + $code = $this->codeBuffer; + array_push($code, $input); + $tokens = @token_get_all('context->setBoundClass($boundClass); + } + + /** + * Get the bound class (self) for the interactive shell. + * + * @return string|null + */ + public function getBoundClass() + { + return $this->context->getBoundClass(); + } + + /** * Add includes, to be parsed and executed before running the interactive shell. * * @param array $includes @@ -945,7 +988,7 @@ } $message = preg_replace( - "#(\\w:)?(/\\w+)*/src/ExecutionClosure.php\(\d+\) : eval\(\)'d code#", + "#(\\w:)?(/\\w+)*/src/Execution(?:Loop)?Closure.php\(\d+\) : eval\(\)'d code#", "eval()'d code", str_replace('\\', '/', $message) ); @@ -1089,9 +1132,8 @@ */ protected function hasCommand($input) { - $input = new StringInput($input); - if ($name = $input->getFirstArgument()) { - return $this->has($name); + if (preg_match('/([^\s]+?)(?:\s|$)/A', ltrim($input), $match)) { + return $this->has($match[1]); } return false; diff -r e200cb7efeb3 -r c2387f117808 vendor/psy/psysh/src/TabCompletion/AutoCompleter.php --- a/vendor/psy/psysh/src/TabCompletion/AutoCompleter.php Thu Apr 26 11:26:54 2018 +0100 +++ b/vendor/psy/psysh/src/TabCompletion/AutoCompleter.php Tue Jul 10 15:07:59 2018 +0100 @@ -103,8 +103,6 @@ { // PHP didn't implement the whole readline API when they first switched // to libedit. And they still haven't. - // - // So this is a thing to make PsySH work on 5.3.x: if (function_exists('readline_callback_handler_remove')) { readline_callback_handler_remove(); } diff -r e200cb7efeb3 -r c2387f117808 vendor/psy/psysh/src/TabCompletion/Matcher/AbstractMatcher.php --- a/vendor/psy/psysh/src/TabCompletion/Matcher/AbstractMatcher.php Thu Apr 26 11:26:54 2018 +0100 +++ b/vendor/psy/psysh/src/TabCompletion/Matcher/AbstractMatcher.php Tue Jul 10 15:07:59 2018 +0100 @@ -86,6 +86,10 @@ [self::T_NS_SEPARATOR, self::T_STRING], $token = array_pop($tokens) )) { + if (self::needCompleteClass($token)) { + continue; + } + $class = $token[1] . $class; } @@ -167,6 +171,11 @@ return strpos(self::MISC_OPERATORS, $token) !== false; } + public static function needCompleteClass($token) + { + return in_array($token[1], ['doc', 'ls', 'show']); + } + /** * Check whether $token type is present in $coll. * diff -r e200cb7efeb3 -r c2387f117808 vendor/psy/psysh/src/TabCompletion/Matcher/ClassAttributesMatcher.php --- a/vendor/psy/psysh/src/TabCompletion/Matcher/ClassAttributesMatcher.php Thu Apr 26 11:26:54 2018 +0100 +++ b/vendor/psy/psysh/src/TabCompletion/Matcher/ClassAttributesMatcher.php Tue Jul 10 15:07:59 2018 +0100 @@ -54,7 +54,10 @@ return array_map( function ($name) use ($class) { - return $class . '::' . $name; + $chunks = explode('\\', $class); + $className = array_pop($chunks); + + return $className . '::' . $name; }, array_filter( $vars, diff -r e200cb7efeb3 -r c2387f117808 vendor/psy/psysh/src/TabCompletion/Matcher/ClassMethodsMatcher.php --- a/vendor/psy/psysh/src/TabCompletion/Matcher/ClassMethodsMatcher.php Thu Apr 26 11:26:54 2018 +0100 +++ b/vendor/psy/psysh/src/TabCompletion/Matcher/ClassMethodsMatcher.php Tue Jul 10 15:07:59 2018 +0100 @@ -42,14 +42,22 @@ return []; } - $methods = $reflection->getMethods(\ReflectionMethod::IS_STATIC); + if (self::needCompleteClass($tokens[1])) { + $methods = $reflection->getMethods(); + } else { + $methods = $reflection->getMethods(\ReflectionMethod::IS_STATIC); + } + $methods = array_map(function (\ReflectionMethod $method) { return $method->getName(); }, $methods); return array_map( function ($name) use ($class) { - return $class . '::' . $name; + $chunks = explode('\\', $class); + $className = array_pop($chunks); + + return $className . '::' . $name; }, array_filter($methods, function ($method) use ($input) { return AbstractMatcher::startsWith($input, $method); diff -r e200cb7efeb3 -r c2387f117808 vendor/psy/psysh/src/TabCompletion/Matcher/ClassNamesMatcher.php --- a/vendor/psy/psysh/src/TabCompletion/Matcher/ClassNamesMatcher.php Thu Apr 26 11:26:54 2018 +0100 +++ b/vendor/psy/psysh/src/TabCompletion/Matcher/ClassNamesMatcher.php Tue Jul 10 15:07:59 2018 +0100 @@ -65,7 +65,7 @@ case self::hasToken([$blacklistedTokens], $prevToken): case is_string($token) && $token === '$': return false; - case self::hasToken([self::T_NEW, self::T_OPEN_TAG, self::T_NS_SEPARATOR], $prevToken): + case self::hasToken([self::T_NEW, self::T_OPEN_TAG, self::T_NS_SEPARATOR, self::T_STRING], $prevToken): case self::hasToken([self::T_NEW, self::T_OPEN_TAG, self::T_NS_SEPARATOR], $token): case self::hasToken([self::T_OPEN_TAG, self::T_VARIABLE], $token): case self::isOperator($token): diff -r e200cb7efeb3 -r c2387f117808 vendor/psy/psysh/src/Util/Mirror.php --- a/vendor/psy/psysh/src/Util/Mirror.php Thu Apr 26 11:26:54 2018 +0100 +++ b/vendor/psy/psysh/src/Util/Mirror.php Tue Jul 10 15:07:59 2018 +0100 @@ -12,7 +12,8 @@ namespace Psy\Util; use Psy\Exception\RuntimeException; -use Psy\Reflection\ReflectionConstant; +use Psy\Reflection\ReflectionClassConstant; +use Psy\Reflection\ReflectionConstant_; /** * A utility class for getting Reflectors. @@ -43,8 +44,12 @@ */ public static function get($value, $member = null, $filter = 15) { - if ($member === null && is_string($value) && function_exists($value)) { - return new \ReflectionFunction($value); + if ($member === null && is_string($value)) { + if (function_exists($value)) { + return new \ReflectionFunction($value); + } elseif (defined($value) || ReflectionConstant_::isMagicConstant($value)) { + return new ReflectionConstant_($value); + } } $class = self::getClass($value); @@ -52,7 +57,7 @@ if ($member === null) { return $class; } elseif ($filter & self::CONSTANT && $class->hasConstant($member)) { - return new ReflectionConstant($class, $member); + return ReflectionClassConstant::create($value, $member); } elseif ($filter & self::METHOD && $class->hasMethod($member)) { return $class->getMethod($member); } elseif ($filter & self::PROPERTY && $class->hasProperty($member)) { @@ -85,7 +90,7 @@ if (!is_string($value)) { throw new \InvalidArgumentException('Mirror expects an object or class'); - } elseif (!class_exists($value) && !interface_exists($value) && !(function_exists('trait_exists') && trait_exists($value))) { + } elseif (!class_exists($value) && !interface_exists($value) && !trait_exists($value)) { throw new \InvalidArgumentException('Unknown class or function: ' . $value); } diff -r e200cb7efeb3 -r c2387f117808 vendor/psy/psysh/src/functions.php --- a/vendor/psy/psysh/src/functions.php Thu Apr 26 11:26:54 2018 +0100 +++ b/vendor/psy/psysh/src/functions.php Tue Jul 10 15:07:59 2018 +0100 @@ -28,7 +28,7 @@ */ function sh() { - return 'extract(\Psy\debug(get_defined_vars(), isset($this) ? $this : null));'; + return 'extract(\Psy\debug(get_defined_vars(), isset($this) ? $this : @get_called_class()));'; } } @@ -50,9 +50,9 @@ * var_dump($item); // will be whatever you set $item to in Psy Shell * } * - * Optionally, supply an object as the `$boundObject` parameter. This - * determines the value `$this` will have in the shell, and sets up class - * scope so that private and protected members are accessible: + * Optionally, supply an object as the `$bindTo` parameter. This determines + * the value `$this` will have in the shell, and sets up class scope so that + * private and protected members are accessible: * * class Foo { * function bar() { @@ -60,12 +60,22 @@ * } * } * - * @param array $vars Scope variables from the calling context (default: array()) - * @param object $boundObject Bound object ($this) value for the shell + * For the static equivalent, pass a class name as the `$bindTo` parameter. + * This makes `self` work in the shell, and sets up static scope so that + * private and protected static members are accessible: + * + * class Foo { + * static function bar() { + * \Psy\debug(get_defined_vars(), get_called_class()); + * } + * } + * + * @param array $vars Scope variables from the calling context (default: array()) + * @param object|string $bindTo Bound object ($this) or class (self) value for the shell * * @return array Scope variables from the debugger session */ - function debug(array $vars = [], $boundObject = null) + function debug(array $vars = [], $bindTo = null) { echo PHP_EOL; @@ -79,8 +89,10 @@ $sh->addInput('whereami -n2', true); } - if ($boundObject !== null) { - $sh->setBoundObject($boundObject); + if (is_string($bindTo)) { + $sh->setBoundClass($bindTo); + } elseif ($bindTo !== null) { + $sh->setBoundObject($bindTo); } $sh->run(); diff -r e200cb7efeb3 -r c2387f117808 vendor/psy/psysh/test/CodeCleaner/CodeCleanerTestCase.php --- a/vendor/psy/psysh/test/CodeCleaner/CodeCleanerTestCase.php Thu Apr 26 11:26:54 2018 +0100 +++ b/vendor/psy/psysh/test/CodeCleaner/CodeCleanerTestCase.php Tue Jul 10 15:07:59 2018 +0100 @@ -19,6 +19,12 @@ { protected $pass; + public function tearDown() + { + $this->pass = null; + parent::tearDown(); + } + protected function setPass(CodeCleanerPass $pass) { $this->pass = $pass; diff -r e200cb7efeb3 -r c2387f117808 vendor/psy/psysh/test/CodeCleaner/FunctionReturnInWriteContextPassTest.php --- a/vendor/psy/psysh/test/CodeCleaner/FunctionReturnInWriteContextPassTest.php Thu Apr 26 11:26:54 2018 +0100 +++ b/vendor/psy/psysh/test/CodeCleaner/FunctionReturnInWriteContextPassTest.php Tue Jul 10 15:07:59 2018 +0100 @@ -72,4 +72,20 @@ $this->traverser->traverse($this->parse('empty(strtolower("A"))')); } + + /** + * @dataProvider validStatements + */ + public function testValidStatements($code) + { + $this->parseAndTraverse($code); + $this->assertTrue(true); + } + + public function validStatements() + { + return [ + ['isset($foo)'], + ]; + } } diff -r e200cb7efeb3 -r c2387f117808 vendor/psy/psysh/test/CodeCleaner/ImplicitReturnPassTest.php --- a/vendor/psy/psysh/test/CodeCleaner/ImplicitReturnPassTest.php Thu Apr 26 11:26:54 2018 +0100 +++ b/vendor/psy/psysh/test/CodeCleaner/ImplicitReturnPassTest.php Tue Jul 10 15:07:59 2018 +0100 @@ -34,8 +34,16 @@ ['4', 'return 4;'], ['foo()', 'return foo();'], ['return 1', 'return 1;'], + ['', 'return new \Psy\CodeCleaner\NoReturnValue();'], ]; + $from = 'echo "foo";'; + $to = <<<'EOS' +echo "foo"; +return new \Psy\CodeCleaner\NoReturnValue(); +EOS; + $data[] = [$from, $to]; + $from = 'if (true) { 1; } elseif (true) { 2; } else { 3; }'; $to = <<<'EOS' if (true) { @@ -85,6 +93,18 @@ EOS; $data[] = [$from, $to]; + $from = <<<'EOS' +namespace Foo { + 1 + 1; +} +EOS; + $to = <<<'EOS' +namespace Foo; + +return 1 + 1; +EOS; + $data[] = [$from, $to]; + $data[] = ['exit()', 'exit;']; return $data; diff -r e200cb7efeb3 -r c2387f117808 vendor/psy/psysh/test/CodeCleaner/ListPassTest.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vendor/psy/psysh/test/CodeCleaner/ListPassTest.php Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,104 @@ +setPass(new ListPass()); + } + + /** + * @dataProvider invalidStatements + * @expectedException \Psy\Exception\ParseErrorException + */ + public function testProcessInvalidStatement($code, $expectedMessage) + { + if (method_exists($this, 'setExpectedException')) { + $this->setExpectedException('Psy\Exception\ParseErrorException', $expectedMessage); + } else { + $this->expectExceptionMessage($expectedMessage); + } + + $stmts = $this->parse($code); + $this->traverser->traverse($stmts); + } + + public function invalidStatements() + { + // Not typo. It is ambiguous whether "Syntax" or "syntax". + $errorShortListAssign = "yntax error, unexpected '='"; + $errorEmptyList = 'Cannot use empty list'; + $errorAssocListAssign = 'Syntax error, unexpected T_CONSTANT_ENCAPSED_STRING, expecting \',\' or \')\''; + $errorNonVariableAssign = 'Assignments can only happen to writable values'; + $errorPhpParserSyntax = 'PHP Parse error: Syntax error, unexpected'; + + $invalidExpr = [ + ['list() = array()', $errorEmptyList], + ['list("a") = array(1)', $errorPhpParserSyntax], + ]; + + if (version_compare(PHP_VERSION, '7.1', '<')) { + return array_merge($invalidExpr, [ + ['list("a" => _) = array("a" => 1)', $errorPhpParserSyntax], + ['[] = []', $errorShortListAssign], + ['[$a] = [1]', $errorShortListAssign], + ['list("a" => $a) = array("a" => 1)', $errorAssocListAssign], + ]); + } + + return array_merge($invalidExpr, [ + ['list("a" => _) = array("a" => 1)', $errorPhpParserSyntax], + ['["a"] = [1]', $errorNonVariableAssign], + ['[] = []', $errorEmptyList], + ['[,] = [1,2]', $errorEmptyList], + ]); + } + + /** + * @dataProvider validStatements + */ + public function testProcessValidStatement($code) + { + $stmts = $this->parse($code); + $this->traverser->traverse($stmts); + $this->assertTrue(true); + } + + public function validStatements() + { + $validExpr = [ + ['list($a) = array(1)'], + ['list($x, $y) = array(1, 2)'], + ]; + + if (version_compare(PHP_VERSION, '7.1', '>=')) { + return array_merge($validExpr, [ + ['[$a] = array(1)'], + ['list($b) = [2]'], + ['[$x, $y] = array(1, 2)'], + ['[$a] = [1]'], + ['[$x, $y] = [1, 2]'], + ['["_" => $v] = ["_" => 1]'], + ['[$a,] = [1,2,3]'], + ['[,$b] = [1,2,3]'], + ['[$a,,$c] = [1,2,3]'], + ['[$a,,,] = [1,2,3]'], + ]); + } + + return $validExpr; + } +} diff -r e200cb7efeb3 -r c2387f117808 vendor/psy/psysh/test/CodeCleaner/LoopContextPassTest.php --- a/vendor/psy/psysh/test/CodeCleaner/LoopContextPassTest.php Thu Apr 26 11:26:54 2018 +0100 +++ b/vendor/psy/psysh/test/CodeCleaner/LoopContextPassTest.php Tue Jul 10 15:07:59 2018 +0100 @@ -53,29 +53,6 @@ ['while (true) { break 2; }'], ['while (true) { continue 2; }'], - // invalid in 5.4+ because they're floats - // ... in 5.3 because the number is too big - ['while (true) { break 2.0; }'], - ['while (true) { continue 2.0; }'], - - // and once with nested loops, just for good measure - ['while (true) { while (true) { break 3; } }'], - ['while (true) { while (true) { continue 3; } }'], - ]; - } - - /** - * @dataProvider invalidPHP54Statements - * @expectedException \Psy\Exception\FatalErrorException - */ - public function testPHP54ProcessStatementFails($code) - { - $this->parseAndTraverse($code); - } - - public function invalidPHP54Statements() - { - return [ // In PHP 5.4+, only positive literal integers are allowed ['while (true) { break $n; }'], ['while (true) { continue $n; }'], @@ -87,6 +64,12 @@ ['while (true) { continue -1; }'], ['while (true) { break 1.0; }'], ['while (true) { continue 1.0; }'], + ['while (true) { break 2.0; }'], + ['while (true) { continue 2.0; }'], + + // and once with nested loops, just for good measure + ['while (true) { while (true) { break 3; } }'], + ['while (true) { while (true) { continue 3; } }'], ]; } diff -r e200cb7efeb3 -r c2387f117808 vendor/psy/psysh/test/CodeCleaner/NamespacePassTest.php --- a/vendor/psy/psysh/test/CodeCleaner/NamespacePassTest.php Thu Apr 26 11:26:54 2018 +0100 +++ b/vendor/psy/psysh/test/CodeCleaner/NamespacePassTest.php Tue Jul 10 15:07:59 2018 +0100 @@ -26,6 +26,9 @@ public function testProcess() { + $this->parseAndTraverse(''); + $this->assertNull($this->cleaner->getNamespace()); + $this->parseAndTraverse('array_merge()'); $this->assertNull($this->cleaner->getNamespace()); diff -r e200cb7efeb3 -r c2387f117808 vendor/psy/psysh/test/CodeCleaner/NoReturnValueTest.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vendor/psy/psysh/test/CodeCleaner/NoReturnValueTest.php Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,32 @@ +assertSame( + $this->prettyPrint($this->parse('new \\Psy\CodeCleaner\\NoReturnValue()')), + $this->prettyPrint([$stmt]) + ); + } +} diff -r e200cb7efeb3 -r c2387f117808 vendor/psy/psysh/test/CodeCleaner/RequirePassTest.php --- a/vendor/psy/psysh/test/CodeCleaner/RequirePassTest.php Thu Apr 26 11:26:54 2018 +0100 +++ b/vendor/psy/psysh/test/CodeCleaner/RequirePassTest.php Tue Jul 10 15:07:59 2018 +0100 @@ -85,4 +85,9 @@ [''], ]; } + + public function testResolveWorks() + { + $this->assertEquals(__FILE__, RequirePass::resolve(__FILE__, 3)); + } } diff -r e200cb7efeb3 -r c2387f117808 vendor/psy/psysh/test/CodeCleaner/UseStatementPassTest.php --- a/vendor/psy/psysh/test/CodeCleaner/UseStatementPassTest.php Thu Apr 26 11:26:54 2018 +0100 +++ b/vendor/psy/psysh/test/CodeCleaner/UseStatementPassTest.php Tue Jul 10 15:07:59 2018 +0100 @@ -55,6 +55,48 @@ "namespace Foo;\nuse Bar;\n\$baz = new Bar\\Baz();", "namespace Foo;\n\n\$baz = new \\Bar\\Baz();", ], + [ + "namespace Foo;\n\nuse \\StdClass as S;\n\$std = new S();\nnamespace Foo;\n\n\$std = new S();", + "namespace Foo;\n\n\$std = new \\StdClass();\nnamespace Foo;\n\n\$std = new \\StdClass();", + ], + [ + "namespace Foo;\n\nuse \\StdClass as S;\n\$std = new S();\nnamespace Bar;\n\n\$std = new S();", + "namespace Foo;\n\n\$std = new \\StdClass();\nnamespace Bar;\n\n\$std = new S();", + ], + [ + "use Foo\\Bar as fb, Qux as Q;\n\$baz = new fb\\Baz();\n\$qux = new Q();", + "\$baz = new \\Foo\\Bar\\Baz();\n\$qux = new \\Qux();", + ], + ]; + } + + /** + * @dataProvider groupUseStatements + */ + public function testGroupUseProcess($from, $to) + { + $this->assertProcessesAs($from, $to); + } + + public function groupUseStatements() + { + if (version_compare(PHP_VERSION, '7.0', '<')) { + $this->markTestSkipped(); + } + + return [ + [ + "use Foo\\{Bar, Baz, Qux as Q};\n\$bar = new Bar();\n\$baz = new Baz();\n\$qux = new Q();", + "\$bar = new \\Foo\\Bar();\n\$baz = new \\Foo\\Baz();\n\$qux = new \\Foo\\Qux();", + ], + [ + "use X\\{Foo, Bar as B};\n\$foo = new Foo();\n\$baz = new B\\Baz();", + "\$foo = new \\X\\Foo();\n\$baz = new \\X\\Bar\\Baz();", + ], + [ + "use X\\{Foo, Bar as B};\n\$foo = new Foo();\n\$bar = new Bar();\n\$baz = new B\\Baz();", + "\$foo = new \\X\\Foo();\n\$bar = new Bar();\n\$baz = new \\X\\Bar\\Baz();", + ], ]; } } diff -r e200cb7efeb3 -r c2387f117808 vendor/psy/psysh/test/CodeCleaner/ValidClassNamePassTest.php --- a/vendor/psy/psysh/test/CodeCleaner/ValidClassNamePassTest.php Thu Apr 26 11:26:54 2018 +0100 +++ b/vendor/psy/psysh/test/CodeCleaner/ValidClassNamePassTest.php Tue Jul 10 15:07:59 2018 +0100 @@ -109,6 +109,7 @@ // static call ['Psy\\Test\\CodeCleaner\\ValidClassNamePass\\NotAClass::foo()'], ['Psy\\Test\\CodeCleaner\\ValidClassNamePass\\NotAClass::$foo()'], + ['Psy\\Test\\CodeCleaner\\ValidClassNamePassTest::notAMethod()'], ]; } diff -r e200cb7efeb3 -r c2387f117808 vendor/psy/psysh/test/CodeCleanerTest.php --- a/vendor/psy/psysh/test/CodeCleanerTest.php Thu Apr 26 11:26:54 2018 +0100 +++ b/vendor/psy/psysh/test/CodeCleanerTest.php Tue Jul 10 15:07:59 2018 +0100 @@ -60,6 +60,8 @@ [['echo \''], true], [['if (1) {'], true], + [['echo "foo",'], true], + [['echo ""'], false], [["echo ''"], false], [['if (1) {}'], false], diff -r e200cb7efeb3 -r c2387f117808 vendor/psy/psysh/test/Command/ExitCommandTest.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vendor/psy/psysh/test/Command/ExitCommandTest.php Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,29 @@ +execute([]); + } +} diff -r e200cb7efeb3 -r c2387f117808 vendor/psy/psysh/test/Command/ThrowUpCommandTest.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vendor/psy/psysh/test/Command/ThrowUpCommandTest.php Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,89 @@ +getMockBuilder('Psy\\Shell') + ->setMethods(['hasCode', 'addCode']) + ->getMock(); + + $shell->expects($this->once())->method('hasCode')->willReturn($hasCode); + $shell->expects($this->once()) + ->method('addCode') + ->with($this->equalTo($expect), $this->equalTo($addSilent)); + + $command = new ThrowUpCommand(); + $command->setApplication($shell); + $tester = new CommandTester($command); + $tester->execute($args); + $this->assertEquals('', $tester->getDisplay()); + } + + public function executeThis() + { + $throw = 'throw \Psy\Exception\ThrowUpException::fromThrowable'; + + return [ + [[], false, $throw . '($_e);'], + + [['exception' => '$ex'], false, $throw . '($ex);'], + [['exception' => 'getException()'], false, $throw . '(getException());'], + [['exception' => 'new \\Exception("WAT")'], false, $throw . '(new \\Exception("WAT"));'], + + [['exception' => '\'some string\''], false, $throw . '(new \\Exception(\'some string\'));'], + [['exception' => '"WHEEEEEEE!"'], false, $throw . '(new \\Exception("WHEEEEEEE!"));'], + + // Everything should work with or without semicolons. + [['exception' => '$ex;'], false, $throw . '($ex);'], + [['exception' => '"WHEEEEEEE!";'], false, $throw . '(new \\Exception("WHEEEEEEE!"));'], + + // Don't add as silent code if we've already got code. + [[], true, $throw . '($_e);', false], + [['exception' => 'getException()'], true, $throw . '(getException());', false], + [['exception' => '\'some string\''], true, $throw . '(new \\Exception(\'some string\'));', false], + ]; + } + + /** + * @expectedException \InvalidArgumentException + * @expectedExceptionMessage No idea how to throw this + */ + public function testMultipleArgsThrowsException() + { + $command = new ThrowUpCommand(); + $command->setApplication(new Shell()); + $tester = new CommandTester($command); + $tester->execute(['exception' => 'foo(); bar()']); + } + + /** + * @expectedException \PhpParser\Error + * @expectedExceptionMessage Syntax error, unexpected ')' on line 1 + */ + public function testParseErrorThrowsException() + { + $command = new ThrowUpCommand(); + $command->setApplication(new Shell()); + $tester = new CommandTester($command); + $tester->execute(['exception' => 'foo)']); + } +} diff -r e200cb7efeb3 -r c2387f117808 vendor/psy/psysh/test/Command/TimeitCommand/TimeitVisitorTest.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vendor/psy/psysh/test/Command/TimeitCommand/TimeitVisitorTest.php Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,52 @@ +traverser = new NodeTraverser(); + $this->traverser->addVisitor(new TimeitVisitor()); + } + + /** + * @dataProvider codez + */ + public function testProcess($from, $to) + { + $this->assertProcessesAs($from, $to); + } + + public function codez() + { + $start = '\Psy\Command\TimeitCommand::markStart'; + $end = '\Psy\Command\TimeitCommand::markEnd'; + $noReturn = 'new \Psy\CodeCleaner\NoReturnValue()'; + + return [ + ['', "$end($start());"], // heh + ['a()', "$start(); $end(a());"], + ['$b()', "$start(); $end(\$b());"], + ['$c->d()', "$start(); $end(\$c->d());"], + ['e(); f()', "$start(); e(); $end(f());"], + ['function g() { return 1; }', "$start(); function g() {return 1;} $end($noReturn);"], + ['return 1', "$start(); return $end(1);"], + ['return 1; 2', "$start(); return $end(1); $end(2);"], + ['return 1; function h() {}', "$start(); return $end(1); function h() {} $end($noReturn);"], + ]; + } +} diff -r e200cb7efeb3 -r c2387f117808 vendor/psy/psysh/test/ContextTest.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vendor/psy/psysh/test/ContextTest.php Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,325 @@ +assertTrue(true); + } + + public function testGetAll() + { + $this->assertTrue(true); + } + + public function testGetSpecialVariables() + { + $context = new Context(); + + $this->assertNull($context->get('_')); + $this->assertNull($context->getReturnValue()); + + $this->assertEquals(['_' => null], $context->getAll()); + + $e = new \Exception('eeeeeee'); + $obj = new \StdClass(); + $context->setLastException($e); + $context->setLastStdout('out'); + $context->setBoundObject($obj); + + $context->setCommandScopeVariables([ + '__function' => 'function', + '__method' => 'method', + '__class' => 'class', + '__namespace' => 'namespace', + '__file' => 'file', + '__line' => 'line', + '__dir' => 'dir', + ]); + + $expected = [ + '_' => null, + '_e' => $e, + '__out' => 'out', + 'this' => $obj, + '__function' => 'function', + '__method' => 'method', + '__class' => 'class', + '__namespace' => 'namespace', + '__file' => 'file', + '__line' => 'line', + '__dir' => 'dir', + ]; + + $this->assertEquals($expected, $context->getAll()); + } + + public function testSetAll() + { + $context = new Context(); + + $baz = new \StdClass(); + $vars = [ + 'foo' => 'Foo', + 'bar' => 123, + 'baz' => $baz, + + '_' => 'fail', + '_e' => 'fail', + '__out' => 'fail', + 'this' => 'fail', + '__psysh__' => 'fail', + + '__function' => 'fail', + '__method' => 'fail', + '__class' => 'fail', + '__namespace' => 'fail', + '__file' => 'fail', + '__line' => 'fail', + '__dir' => 'fail', + ]; + + $context->setAll($vars); + + $this->assertEquals('Foo', $context->get('foo')); + $this->assertEquals(123, $context->get('bar')); + $this->assertSame($baz, $context->get('baz')); + + $this->assertEquals(['foo' => 'Foo', 'bar' => 123, 'baz' => $baz, '_' => null], $context->getAll()); + } + + /** + * @dataProvider specialNames + * @expectedException \InvalidArgumentException + * @expectedExceptionMessageRegEx /Unknown variable: \$\w+/ + */ + public function testSetAllDoesNotSetSpecial($name) + { + $context = new Context(); + $context->setAll([$name => 'fail']); + $context->get($name); + } + + public function specialNames() + { + return [ + ['_e'], + ['__out'], + ['this'], + ['__psysh__'], + ['__function'], + ['__method'], + ['__class'], + ['__namespace'], + ['__file'], + ['__line'], + ['__dir'], + ]; + } + + public function testReturnValue() + { + $context = new Context(); + $this->assertNull($context->getReturnValue()); + + $val = 'some string'; + $context->setReturnValue($val); + $this->assertEquals($val, $context->getReturnValue()); + $this->assertEquals($val, $context->get('_')); + + $obj = new \StdClass(); + $context->setReturnValue($obj); + $this->assertSame($obj, $context->getReturnValue()); + $this->assertSame($obj, $context->get('_')); + + $context->setReturnValue(null); + $this->assertNull($context->getReturnValue()); + } + + public function testLastException() + { + $context = new Context(); + $e = new \Exception('wat'); + $context->setLastException($e); + $this->assertSame($e, $context->getLastException()); + $this->assertSame($e, $context->get('_e')); + } + + /** + * @expectedException \InvalidArgumentException + * @expectedExceptionMessage No most-recent exception + */ + public function testLastExceptionThrowsSometimes() + { + $context = new Context(); + $context->getLastException(); + } + + public function testLastStdout() + { + $context = new Context(); + $context->setLastStdout('ouuuuut'); + $this->assertEquals('ouuuuut', $context->getLastStdout()); + $this->assertEquals('ouuuuut', $context->get('__out')); + } + + /** + * @expectedException \InvalidArgumentException + * @expectedExceptionMessage No most-recent output + */ + public function testLastStdoutThrowsSometimes() + { + $context = new Context(); + $context->getLastStdout(); + } + + public function testBoundObject() + { + $context = new Context(); + $this->assertNull($context->getBoundObject()); + + $obj = new \StdClass(); + $context->setBoundObject($obj); + $this->assertSame($obj, $context->getBoundObject()); + $this->assertSame($obj, $context->get('this')); + + $context->setBoundObject(null); + $this->assertNull($context->getBoundObject()); + } + + /** + * @expectedException \InvalidArgumentException + * @expectedExceptionMessage Unknown variable: $this + */ + public function testBoundObjectThrowsSometimes() + { + $context = new Context(); + $context->get('this'); + } + + public function testBoundClass() + { + $context = new Context(); + $this->assertNull($context->getBoundClass()); + + $context->setBoundClass(''); + $this->assertNull($context->getBoundClass()); + + $context->setBoundClass('Psy\Shell'); + $this->assertEquals('Psy\Shell', $context->getBoundClass()); + + $context->setBoundObject(new \StdClass()); + $this->assertNotNull($context->getBoundObject()); + $this->assertNull($context->getBoundClass()); + + $context->setBoundClass('Psy\Shell'); + $this->assertEquals('Psy\Shell', $context->getBoundClass()); + $this->assertNull($context->getBoundObject()); + + $context->setBoundClass(null); + $this->assertNull($context->getBoundClass()); + $this->assertNull($context->getBoundObject()); + } + + public function testCommandScopeVariables() + { + $__function = 'donkey'; + $__method = 'diddy'; + $__class = 'cranky'; + $__namespace = 'funky'; + $__file = 'candy'; + $__line = 'dixie'; + $__dir = 'wrinkly'; + + $vars = compact('__function', '__method', '__class', '__namespace', '__file', '__line', '__dir'); + + $context = new Context(); + $context->setCommandScopeVariables($vars); + + $this->assertEquals($vars, $context->getCommandScopeVariables()); + + $this->assertEquals($__function, $context->get('__function')); + $this->assertEquals($__method, $context->get('__method')); + $this->assertEquals($__class, $context->get('__class')); + $this->assertEquals($__namespace, $context->get('__namespace')); + $this->assertEquals($__file, $context->get('__file')); + $this->assertEquals($__line, $context->get('__line')); + $this->assertEquals($__dir, $context->get('__dir')); + + $someVars = compact('__function', '__namespace', '__file', '__line', '__dir'); + $context->setCommandScopeVariables($someVars); + } + + public function testGetUnusedCommandScopeVariableNames() + { + $context = new Context(); + + $this->assertEquals( + ['__function', '__method', '__class', '__namespace', '__file', '__line', '__dir'], + $context->getUnusedCommandScopeVariableNames() + ); + + $context->setCommandScopeVariables([ + '__function' => 'foo', + '__namespace' => 'bar', + '__file' => 'baz', + '__line' => 123, + '__dir' => 'qux', + ]); + + $this->assertEquals( + ['__method', '__class'], + array_values($context->getUnusedCommandScopeVariableNames()) + ); + } + + /** + * @dataProvider specialAndNotSpecialVariableNames + */ + public function testIsSpecialVariableName($name, $isSpecial) + { + $context = new Context(); + + if ($isSpecial) { + $this->assertTrue($context->isSpecialVariableName($name)); + } else { + $this->assertFalse($context->isSpecialVariableName($name)); + } + } + + public function specialAndNotSpecialVariableNames() + { + return [ + ['foo', false], + ['psysh', false], + ['__psysh', false], + + ['_', true], + ['_e', true], + ['__out', true], + ['this', true], + ['__psysh__', true], + + ['__function', true], + ['__method', true], + ['__class', true], + ['__namespace', true], + ['__file', true], + ['__line', true], + ['__dir', true], + ]; + } +} diff -r e200cb7efeb3 -r c2387f117808 vendor/psy/psysh/test/Exception/BreakExceptionTest.php --- a/vendor/psy/psysh/test/Exception/BreakExceptionTest.php Thu Apr 26 11:26:54 2018 +0100 +++ b/vendor/psy/psysh/test/Exception/BreakExceptionTest.php Tue Jul 10 15:07:59 2018 +0100 @@ -30,4 +30,13 @@ $this->assertContains('foo', $e->getMessage()); $this->assertSame('foo', $e->getRawMessage()); } + + /** + * @expectedException \Psy\Exception\BreakException + * @expectedExceptionMessage Goodbye + */ + public function testExitShell() + { + BreakException::exitShell(); + } } diff -r e200cb7efeb3 -r c2387f117808 vendor/psy/psysh/test/Exception/ErrorExceptionTest.php --- a/vendor/psy/psysh/test/Exception/ErrorExceptionTest.php Thu Apr 26 11:26:54 2018 +0100 +++ b/vendor/psy/psysh/test/Exception/ErrorExceptionTest.php Tue Jul 10 15:07:59 2018 +0100 @@ -59,12 +59,15 @@ public function getLevels() { return [ - [E_WARNING, 'Warning'], - [E_CORE_WARNING, 'Warning'], - [E_COMPILE_WARNING, 'Warning'], - [E_USER_WARNING, 'Warning'], - [E_STRICT, 'Strict error'], - [0, 'Error'], + [E_WARNING, 'Warning'], + [E_CORE_WARNING, 'Warning'], + [E_COMPILE_WARNING, 'Warning'], + [E_USER_WARNING, 'Warning'], + [E_STRICT, 'Strict error'], + [E_DEPRECATED, 'Deprecated'], + [E_USER_DEPRECATED, 'Deprecated'], + [E_RECOVERABLE_ERROR, 'Recoverable fatal error'], + [0, 'Error'], ]; } @@ -104,4 +107,19 @@ $e = new ErrorException('{{message}}', 0, 1, '/fake/path/to/Psy/File.php'); $this->assertNotEmpty($e->getFile()); } + + public function testFromError() + { + if (version_compare(PHP_VERSION, '7.0.0', '<')) { + $this->markTestSkipped(); + } + + $error = new \Error('{{message}}', 0); + $exception = ErrorException::fromError($error); + + $this->assertContains('PHP Error: {{message}}', $exception->getMessage()); + $this->assertEquals(0, $exception->getCode()); + $this->assertEquals($error->getFile(), $exception->getFile()); + $this->assertSame($exception->getPrevious(), $error); + } } diff -r e200cb7efeb3 -r c2387f117808 vendor/psy/psysh/test/Exception/FatalErrorExceptionTest.php --- a/vendor/psy/psysh/test/Exception/FatalErrorExceptionTest.php Thu Apr 26 11:26:54 2018 +0100 +++ b/vendor/psy/psysh/test/Exception/FatalErrorExceptionTest.php Tue Jul 10 15:07:59 2018 +0100 @@ -42,4 +42,10 @@ $this->assertContains('{msg}', $e->getMessage()); $this->assertContains('eval()\'d code', $e->getMessage()); } + + public function testNegativeOneLineNumberIgnored() + { + $e = new FatalErrorException('{msg}', 0, 1, null, -1); + $this->assertEquals(0, $e->getLine()); + } } diff -r e200cb7efeb3 -r c2387f117808 vendor/psy/psysh/test/Exception/ThrowUpExceptionTest.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vendor/psy/psysh/test/Exception/ThrowUpExceptionTest.php Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,66 @@ +assertInstanceOf('Psy\Exception\Exception', $e); + $this->assertInstanceOf('Psy\Exception\ThrowUpException', $e); + + $this->assertEquals("Throwing Exception with message '{{message}}'", $e->getMessage()); + $this->assertEquals('{{message}}', $e->getRawMessage()); + $this->assertEquals(123, $e->getCode()); + $this->assertSame($previous, $e->getPrevious()); + } + + public function testFromThrowable() + { + $previous = new \Exception('{{message}}'); + $e = ThrowUpException::fromThrowable($previous); + + $this->assertInstanceOf('Psy\Exception\ThrowUpException', $e); + $this->assertSame($previous, $e->getPrevious()); + } + + public function testFromThrowableWithError() + { + if (version_compare(PHP_VERSION, '7.0.0', '<')) { + $this->markTestSkipped(); + } + + $previous = new \Error('{{message}}'); + $e = ThrowUpException::fromThrowable($previous); + + $this->assertInstanceOf('Psy\Exception\ThrowUpException', $e); + $this->assertInstanceOf('Psy\Exception\ErrorException', $e->getPrevious()); + + $this->assertNotSame($previous, $e->getPrevious()); + $this->assertSame($previous, $e->getPrevious()->getPrevious()); + } + + /** + * @expectedException \InvalidArgumentException + * @expectedExceptionMessage throw-up can only throw Exceptions and Errors + */ + public function testFromThrowableThrowsError() + { + $notThrowable = new \StdClass(); + ThrowUpException::fromThrowable($notThrowable); + } +} diff -r e200cb7efeb3 -r c2387f117808 vendor/psy/psysh/test/Exception/TypeErrorExceptionTest.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vendor/psy/psysh/test/Exception/TypeErrorExceptionTest.php Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,52 @@ +assertInstanceOf('Psy\Exception\Exception', $e); + $this->assertInstanceOf('Psy\Exception\TypeErrorException', $e); + + $this->assertEquals('TypeError: {{message}}', $e->getMessage()); + $this->assertEquals('{{message}}', $e->getRawMessage()); + $this->assertEquals(13, $e->getCode()); + } + + public function testStripsEvalFromMessage() + { + $message = 'Something or other, called in line 10: eval()\'d code'; + $e = new TypeErrorException($message); + $this->assertEquals($message, $e->getRawMessage()); + $this->assertEquals('TypeError: Something or other', $e->getMessage()); + } + + public function testFromTypeError() + { + if (version_compare(PHP_VERSION, '7.0.0', '<')) { + $this->markTestSkipped(); + } + + $previous = new \TypeError('{{message}}', 13); + $e = TypeErrorException::fromTypeError($previous); + + $this->assertInstanceOf('Psy\Exception\TypeErrorException', $e); + $this->assertEquals('TypeError: {{message}}', $e->getMessage()); + $this->assertEquals('{{message}}', $e->getRawMessage()); + $this->assertEquals(13, $e->getCode()); + } +} diff -r e200cb7efeb3 -r c2387f117808 vendor/psy/psysh/test/Formatter/CodeFormatterTest.php --- a/vendor/psy/psysh/test/Formatter/CodeFormatterTest.php Thu Apr 26 11:26:54 2018 +0100 +++ b/vendor/psy/psysh/test/Formatter/CodeFormatterTest.php Tue Jul 10 15:07:59 2018 +0100 @@ -12,35 +12,94 @@ namespace Psy\Test\Formatter; use Psy\Formatter\CodeFormatter; +use Psy\Test\Formatter\Fixtures\SomeClass; class CodeFormatterTest extends \PHPUnit\Framework\TestCase { - private function ignoreThisMethod($arg) + /** + * @dataProvider reflectors + */ + public function testFormat($reflector, $expected) { - echo 'whot!'; + $formatted = CodeFormatter::format($reflector); + $formattedWithoutColors = preg_replace('#' . chr(27) . '\[\d\d?m#', '', $formatted); + + $this->assertEquals($expected, self::trimLines($formattedWithoutColors)); + $this->assertNotEquals($expected, self::trimLines($formatted)); } - public function testFormat() + public function reflectors() { - $expected = <<<'EOS' - > 18| private function ignoreThisMethod($arg) - 19| { - 20| echo 'whot!'; - 21| } + $expectClass = <<<'EOS' + > 14| class SomeClass + 15| { + 16| const SOME_CONST = 'some const'; + 17| private $someProp = 'some prop'; + 18| + 19| public function someMethod($someParam) + 20| { + 21| return 'some method'; + 22| } + 23| + 24| public static function someClosure() + 25| { + 26| return function () { + 27| return 'some closure'; + 28| }; + 29| } + 30| } EOS; - $formatted = CodeFormatter::format(new \ReflectionMethod($this, 'ignoreThisMethod')); - $formattedWithoutColors = preg_replace('#' . chr(27) . '\[\d\d?m#', '', $formatted); + $expectMethod = <<<'EOS' + > 19| public function someMethod($someParam) + 20| { + 21| return 'some method'; + 22| } +EOS; - $this->assertEquals($expected, rtrim($formattedWithoutColors)); - $this->assertNotEquals($expected, rtrim($formatted)); + $expectClosure = <<<'EOS' + > 26| return function () { + 27| return 'some closure'; + 28| }; +EOS; + + return [ + [new \ReflectionClass('Psy\Test\Formatter\Fixtures\SomeClass'), $expectClass], + [new \ReflectionObject(new SomeClass()), $expectClass], + [new \ReflectionMethod('Psy\Test\Formatter\Fixtures\SomeClass', 'someMethod'), $expectMethod], + [new \ReflectionFunction(SomeClass::someClosure()), $expectClosure], + ]; + } + + /** + * @dataProvider invalidReflectors + * @expectedException \Psy\Exception\RuntimeException + */ + public function testCodeFormatterThrowsExceptionForReflectorsItDoesntUnderstand($reflector) + { + CodeFormatter::format($reflector); + } + + public function invalidReflectors() + { + $reflectors = [ + [new \ReflectionExtension('json')], + [new \ReflectionParameter(['Psy\Test\Formatter\Fixtures\SomeClass', 'someMethod'], 'someParam')], + [new \ReflectionProperty('Psy\Test\Formatter\Fixtures\SomeClass', 'someProp')], + ]; + + if (version_compare(PHP_VERSION, '7.1.0', '>=')) { + $reflectors[] = [new \ReflectionClassConstant('Psy\Test\Formatter\Fixtures\SomeClass', 'SOME_CONST')]; + } + + return $reflectors; } /** * @dataProvider filenames * @expectedException \Psy\Exception\RuntimeException */ - public function testCodeFormatterThrowsException($filename) + public function testCodeFormatterThrowsExceptionForMissingFile($filename) { $reflector = $this->getMockBuilder('ReflectionClass') ->disableOriginalConstructor() @@ -62,4 +121,9 @@ return [[null], ['not a file']]; } + + private static function trimLines($code) + { + return rtrim(implode("\n", array_map('rtrim', explode("\n", $code)))); + } } diff -r e200cb7efeb3 -r c2387f117808 vendor/psy/psysh/test/Formatter/Fixtures/BoringTrait.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vendor/psy/psysh/test/Formatter/Fixtures/BoringTrait.php Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,20 @@ +assertCount(3, $opts); + } + + /** + * @dataProvider validInputs + */ + public function testBindValidInput($input, $hasFilter = true) + { + $input = $this->getInput($input); + $filterOptions = new FilterOptions(); + $filterOptions->bind($input); + + $this->assertEquals($hasFilter, $filterOptions->hasFilter()); + } + + public function validInputs() + { + return [ + ['--grep="bar"'], + ['--grep="bar" --invert'], + ['--grep="bar" --insensitive'], + ['--grep="bar" --invert --insensitive'], + ['', false], + ]; + } + + /** + * @dataProvider invalidInputs + * @expectedException \Psy\Exception\RuntimeException + */ + public function testBindInvalidInput($input) + { + $input = $this->getInput($input); + $filterOptions = new FilterOptions(); + $filterOptions->bind($input); + } + + public function invalidInputs() + { + return [ + ['--invert'], + ['--insensitive'], + ['--invert --insensitive'], + + // invalid because regex + ['--grep /*/'], + ]; + } + + /** + * @dataProvider matchData + */ + public function testMatch($input, $str, $matches) + { + $input = $this->getInput($input); + $filterOptions = new FilterOptions(); + $filterOptions->bind($input); + + $this->assertEquals($matches, $filterOptions->match($str)); + } + + public function matchData() + { + return [ + ['', 'whatever', true], + ['--grep FOO', 'foo', false], + ['--grep foo', 'foo', true], + ['--grep foo', 'food', true], + ['--grep oo', 'Food', true], + ['--grep oo -i', 'FOOD', true], + ['--grep foo -v', 'food', false], + ['--grep foo -v', 'whatever', true], + ]; + } + + private function getInput($input) + { + $input = new StringInput($input); + $input->bind(new InputDefinition(FilterOptions::getOptions())); + + return $input; + } +} diff -r e200cb7efeb3 -r c2387f117808 vendor/psy/psysh/test/Input/ShellInputTest.php --- a/vendor/psy/psysh/test/Input/ShellInputTest.php Thu Apr 26 11:26:54 2018 +0100 +++ b/vendor/psy/psysh/test/Input/ShellInputTest.php Tue Jul 10 15:07:59 2018 +0100 @@ -20,15 +20,18 @@ class ShellInputTest extends \PHPUnit\Framework\TestCase { /** - * @dataProvider getTokenizeData + * @expectedException \InvalidArgumentException + * @expectedExceptionMessage Unexpected CodeArgument before the final position: a */ - public function testTokenize($input, $tokens, $message) + public function testThrowsWhenCodeArgumentNotInFinalPosition() { - $input = new ShellInput($input); - $r = new \ReflectionClass('Psy\Input\ShellInput'); - $p = $r->getProperty('tokenPairs'); - $p->setAccessible(true); - $this->assertSame($tokens, $p->getValue($input), $message); + $definition = new InputDefinition([ + new CodeArgument('a', null, CodeArgument::REQUIRED), + new InputArgument('b', null, InputArgument::REQUIRED), + ]); + + $input = new ShellInput('foo bar'); + $input->bind($definition); } public function testInputOptionWithGivenString() @@ -48,17 +51,56 @@ { $definition = new InputDefinition([ new InputOption('foo', null, InputOption::VALUE_REQUIRED), + new InputOption('qux', 'q', InputOption::VALUE_REQUIRED), new InputArgument('bar', null, InputArgument::REQUIRED), new InputArgument('baz', null, InputArgument::REQUIRED), ]); - $input = new ShellInput('--foo=foo bar "baz\\\\n"'); + $input = new ShellInput('--foo=foo -q qux bar "baz\\\\n"'); $input->bind($definition); $this->assertSame('foo', $input->getOption('foo')); + $this->assertSame('qux', $input->getOption('qux')); $this->assertSame('bar', $input->getArgument('bar')); $this->assertSame('baz\\n', $input->getArgument('baz')); } + public function testInputWithDashDash() + { + $definition = new InputDefinition([ + new InputOption('foo', null, InputOption::VALUE_REQUIRED), + new CodeArgument('code', null, CodeArgument::REQUIRED), + ]); + + $input = new ShellInput('-- echo --foo::$bar'); + $input->bind($definition); + $this->assertNull($input->getOption('foo')); + $this->assertSame('echo --foo::$bar', $input->getArgument('code')); + } + + public function testInputWithEmptyString() + { + $definition = new InputDefinition([ + new InputOption('foo', null, InputOption::VALUE_REQUIRED), + new CodeArgument('code', null, CodeArgument::REQUIRED), + ]); + + $input = new ShellInput('"" --foo bar'); + $input->bind($definition); + $this->assertSame('"" --foo bar', $input->getArgument('code')); + } + + /** + * @dataProvider getTokenizeData + */ + public function testTokenize($input, $tokens, $message) + { + $input = new ShellInput($input); + $r = new \ReflectionClass('Psy\Input\ShellInput'); + $p = $r->getProperty('tokenPairs'); + $p->setAccessible(true); + $this->assertSame($tokens, $p->getValue($input), $message); + } + public function getTokenizeData() { // Test all the cases from StringInput test, ensuring they have an appropriate $rest token. diff -r e200cb7efeb3 -r c2387f117808 vendor/psy/psysh/test/ParserTestCase.php --- a/vendor/psy/psysh/test/ParserTestCase.php Thu Apr 26 11:26:54 2018 +0100 +++ b/vendor/psy/psysh/test/ParserTestCase.php Tue Jul 10 15:07:59 2018 +0100 @@ -21,6 +21,13 @@ private $parser; private $printer; + public function tearDown() + { + $this->traverser = null; + $this->parser = null; + $this->printer = null; + } + protected function parse($code, $prefix = 'parse($from); $stmts = $this->traverse($stmts); - $this->assertSame($to, $this->prettyPrint($stmts)); + $toStmts = $this->parse($to); + $this->assertSame($this->prettyPrint($toStmts), $this->prettyPrint($stmts)); } private function getParser() diff -r e200cb7efeb3 -r c2387f117808 vendor/psy/psysh/test/Reflection/ReflectionClassConstantTest.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vendor/psy/psysh/test/Reflection/ReflectionClassConstantTest.php Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,81 @@ +getDeclaringClass(); + + $this->assertInstanceOf('ReflectionClass', $class); + $this->assertSame('Psy\Test\Reflection\ReflectionClassConstantTest', $class->getName()); + $this->assertSame('CONSTANT_ONE', $refl->getName()); + $this->assertSame('CONSTANT_ONE', (string) $refl); + $this->assertSame('one', $refl->getValue()); + $this->assertNull($refl->getFileName()); + $this->assertFalse($refl->getDocComment()); + } + + /** + * @expectedException \InvalidArgumentException + */ + public function testUnknownConstantThrowsException() + { + new ReflectionClassConstant($this, 'UNKNOWN_CONSTANT'); + } + + public function testExport() + { + $ret = ReflectionClassConstant::export($this, 'CONSTANT_ONE', true); + $this->assertEquals($ret, 'Constant [ public string CONSTANT_ONE ] { one }'); + } + + public function testExportOutput() + { + $this->expectOutputString("Constant [ public string CONSTANT_ONE ] { one }\n"); + ReflectionClassConstant::export($this, 'CONSTANT_ONE', false); + } + + public function testModifiers() + { + $refl = new ReflectionClassConstant($this, 'CONSTANT_ONE'); + + $this->assertEquals(\ReflectionMethod::IS_PUBLIC, $refl->getModifiers()); + $this->assertFalse($refl->isPrivate()); + $this->assertFalse($refl->isProtected()); + $this->assertTrue($refl->isPublic()); + } + + /** + * @expectedException \RuntimeException + * @dataProvider notYetImplemented + */ + public function testNotYetImplemented($method) + { + $refl = new ReflectionClassConstant($this, 'CONSTANT_ONE'); + $refl->$method(); + } + + public function notYetImplemented() + { + return [ + ['getStartLine'], + ['getEndLine'], + ]; + } +} diff -r e200cb7efeb3 -r c2387f117808 vendor/psy/psysh/test/Reflection/ReflectionConstantBCTest.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vendor/psy/psysh/test/Reflection/ReflectionConstantBCTest.php Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,26 @@ +assertInstanceOf('Psy\Reflection\ReflectionConstant', $refl); + $this->assertInstanceOf('Psy\Reflection\ReflectionClassConstant', $refl); + } +} diff -r e200cb7efeb3 -r c2387f117808 vendor/psy/psysh/test/Reflection/ReflectionConstantTest.php --- a/vendor/psy/psysh/test/Reflection/ReflectionConstantTest.php Thu Apr 26 11:26:54 2018 +0100 +++ b/vendor/psy/psysh/test/Reflection/ReflectionConstantTest.php Tue Jul 10 15:07:59 2018 +0100 @@ -11,24 +11,61 @@ namespace Psy\Test\Reflection; -use Psy\Reflection\ReflectionConstant; +use Psy\Reflection\ReflectionConstant_; + +define('Psy\\Test\\Reflection\\SOME_CONSTANT', 'yep'); class ReflectionConstantTest extends \PHPUnit\Framework\TestCase { - const CONSTANT_ONE = 'one'; - public function testConstruction() { - $refl = new ReflectionConstant($this, 'CONSTANT_ONE'); - $class = $refl->getDeclaringClass(); + $refl = new ReflectionConstant_('Psy\\Test\\Reflection\\SOME_CONSTANT'); - $this->assertInstanceOf('ReflectionClass', $class); - $this->assertSame('Psy\Test\Reflection\ReflectionConstantTest', $class->getName()); - $this->assertSame('CONSTANT_ONE', $refl->getName()); - $this->assertSame('CONSTANT_ONE', (string) $refl); - $this->assertSame('one', $refl->getValue()); + $this->assertFalse($refl->getDocComment()); + $this->assertEquals('Psy\\Test\\Reflection\\SOME_CONSTANT', $refl->getName()); + $this->assertEquals('Psy\\Test\\Reflection', $refl->getNamespaceName()); + $this->assertEquals('yep', $refl->getValue()); + $this->assertTrue($refl->inNamespace()); + $this->assertEquals('Psy\\Test\\Reflection\\SOME_CONSTANT', (string) $refl); $this->assertNull($refl->getFileName()); - $this->assertFalse($refl->getDocComment()); + } + + public function testBuiltInConstant() + { + $refl = new ReflectionConstant_('PHP_VERSION'); + + $this->assertEquals('PHP_VERSION', $refl->getName()); + $this->assertEquals('PHP_VERSION', (string) $refl); + $this->assertEquals(PHP_VERSION, $refl->getValue()); + $this->assertFalse($refl->inNamespace()); + $this->assertSame('', $refl->getNamespaceName()); + } + + /** + * @dataProvider magicConstants + */ + public function testIsMagicConstant($name, $is) + { + $this->assertEquals($is, ReflectionConstant_::isMagicConstant($name)); + } + + public function magicConstants() + { + return [ + ['__LINE__', true], + ['__FILE__', true], + ['__DIR__', true], + ['__FUNCTION__', true], + ['__CLASS__', true], + ['__TRAIT__', true], + ['__METHOD__', true], + ['__NAMESPACE__', true], + ['__COMPILER_HALT_OFFSET__', true], + ['PHP_VERSION', false], + ['PHP_EOL', false], + ['Psy\\Test\\Reflection\\SOME_CONSTANT', false], + ['What if it isn\'t even a valid constant name?', false], + ]; } /** @@ -36,7 +73,25 @@ */ public function testUnknownConstantThrowsException() { - new ReflectionConstant($this, 'UNKNOWN_CONSTANT'); + new ReflectionConstant_('UNKNOWN_CONSTANT'); + } + + public function testExport() + { + $ret = ReflectionConstant_::export('Psy\\Test\\Reflection\\SOME_CONSTANT', true); + $this->assertEquals($ret, 'Constant [ string Psy\\Test\\Reflection\\SOME_CONSTANT ] { yep }'); + } + + public function testExportOutput() + { + $this->expectOutputString("Constant [ string Psy\\Test\\Reflection\\SOME_CONSTANT ] { yep }\n"); + ReflectionConstant_::export('Psy\\Test\\Reflection\\SOME_CONSTANT', false); + } + + public function testGetFileName() + { + $refl = new ReflectionConstant_('Psy\\Test\\Reflection\\SOME_CONSTANT'); + $this->assertNull($refl->getFileName()); } /** @@ -45,7 +100,7 @@ */ public function testNotYetImplemented($method) { - $refl = new ReflectionConstant($this, 'CONSTANT_ONE'); + $refl = new ReflectionConstant_('Psy\\Test\\Reflection\\SOME_CONSTANT'); $refl->$method(); } @@ -54,7 +109,6 @@ return [ ['getStartLine'], ['getEndLine'], - ['export'], ]; } } diff -r e200cb7efeb3 -r c2387f117808 vendor/psy/psysh/test/Reflection/ReflectionLanguageConstructParameterTest.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vendor/psy/psysh/test/Reflection/ReflectionLanguageConstructParameterTest.php Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,64 @@ + false, + 'defaultValue' => null, + 'isOptional' => false, + 'isPassedByReference' => false, + ]); + + $this->assertNull($refl->getClass()); + $this->assertEquals('one', $refl->getName()); + $this->assertFalse($refl->isArray()); + $this->assertTrue($refl->isDefaultValueAvailable()); + $this->assertNull($refl->getDefaultValue()); + $this->assertFalse($refl->isOptional()); + $this->assertFalse($refl->isPassedByReference()); + + $reflTwo = new ReflectionLanguageConstructParameter($keyword, 'two', [ + 'isArray' => true, + 'isOptional' => true, + 'isPassedByReference' => true, + ]); + + $this->assertNull($refl->getClass()); + $this->assertEquals('two', $reflTwo->getName()); + $this->assertTrue($reflTwo->isArray()); + $this->assertFalse($reflTwo->isDefaultValueAvailable()); + $this->assertNull($reflTwo->getDefaultValue()); + $this->assertTrue($reflTwo->isOptional()); + $this->assertTrue($reflTwo->isPassedByReference()); + + $refl = new ReflectionLanguageConstructParameter($keyword, 'three', [ + 'defaultValue' => 3, + ]); + + $this->assertNull($refl->getClass()); + $this->assertEquals('three', $refl->getName()); + $this->assertFalse($refl->isArray()); + $this->assertTrue($refl->isDefaultValueAvailable()); + $this->assertEquals(3, $refl->getDefaultValue()); + $this->assertFalse($refl->isOptional()); + $this->assertFalse($refl->isPassedByReference()); + } +} diff -r e200cb7efeb3 -r c2387f117808 vendor/psy/psysh/test/Reflection/ReflectionLanguageConstructTest.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vendor/psy/psysh/test/Reflection/ReflectionLanguageConstructTest.php Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,102 @@ +assertEquals($keyword, $refl->getName()); + $this->assertEquals($keyword, (string) $refl); + } + + /** + * @dataProvider languageConstructs + */ + public function testKnownLanguageConstructs($keyword) + { + $this->assertTrue(ReflectionLanguageConstruct::isLanguageConstruct($keyword)); + } + + /** + * @dataProvider languageConstructs + */ + public function testFileName($keyword) + { + $refl = new ReflectionLanguageConstruct($keyword); + $this->assertFalse($refl->getFileName()); + } + + /** + * @dataProvider languageConstructs + */ + public function testReturnsReference($keyword) + { + $refl = new ReflectionLanguageConstruct($keyword); + $this->assertFalse($refl->returnsReference()); + } + + /** + * @dataProvider languageConstructs + */ + public function testGetParameters($keyword) + { + $refl = new ReflectionLanguageConstruct($keyword); + $this->assertNotEmpty($refl->getParameters()); + } + + /** + * @dataProvider languageConstructs + * @expectedException \RuntimeException + */ + public function testExportThrows($keyword) + { + ReflectionLanguageConstruct::export($keyword); + } + + public function languageConstructs() + { + return [ + ['isset'], + ['unset'], + ['empty'], + ['echo'], + ['print'], + ['die'], + ['exit'], + ]; + } + + /** + * @dataProvider unknownLanguageConstructs + * @expectedException \InvalidArgumentException + */ + public function testUnknownLanguageConstructsThrowExceptions($keyword) + { + new ReflectionLanguageConstruct($keyword); + } + + public function unknownLanguageConstructs() + { + return [ + ['async'], + ['await'], + ['comefrom'], + ]; + } +} diff -r e200cb7efeb3 -r c2387f117808 vendor/psy/psysh/test/ShellTest.php --- a/vendor/psy/psysh/test/ShellTest.php Thu Apr 26 11:26:54 2018 +0100 +++ b/vendor/psy/psysh/test/ShellTest.php Tue Jul 10 15:07:59 2018 +0100 @@ -380,6 +380,38 @@ ]; } + /** + * @dataProvider commandsToHas + */ + public function testHasCommand($command, $has) + { + $shell = new Shell($this->getConfig()); + + // :-/ + $refl = new \ReflectionClass('Psy\\Shell'); + $method = $refl->getMethod('hasCommand'); + $method->setAccessible(true); + + $this->assertEquals($method->invokeArgs($shell, [$command]), $has); + } + + public function commandsToHas() + { + return [ + ['help', true], + ['help help', true], + ['"help"', false], + ['"help help"', false], + ['ls -al ', true], + ['ls "-al" ', true], + ['ls"-al"', false], + [' q', true], + [' q --help', true], + ['"q"', false], + ['"q",', false], + ]; + } + private function getOutput() { $stream = fopen('php://memory', 'w+'); diff -r e200cb7efeb3 -r c2387f117808 vendor/psy/psysh/test/TabCompletion/AutoCompleterTest.php --- a/vendor/psy/psysh/test/TabCompletion/AutoCompleterTest.php Thu Apr 26 11:26:54 2018 +0100 +++ b/vendor/psy/psysh/test/TabCompletion/AutoCompleterTest.php Tue Jul 10 15:07:59 2018 +0100 @@ -127,17 +127,17 @@ ], [ 'Psy\Test\TabCompletion\StaticSample::CO', - ['Psy\Test\TabCompletion\StaticSample::CONSTANT_VALUE'], + ['StaticSample::CONSTANT_VALUE'], [], ], [ 'Psy\Test\TabCompletion\StaticSample::', - ['Psy\Test\TabCompletion\StaticSample::$staticVariable'], + ['StaticSample::$staticVariable'], [], ], [ 'Psy\Test\TabCompletion\StaticSample::', - ['Psy\Test\TabCompletion\StaticSample::staticFunction'], + ['StaticSample::staticFunction'], [], ], ]; diff -r e200cb7efeb3 -r c2387f117808 vendor/psy/psysh/test/Util/MirrorTest.php --- a/vendor/psy/psysh/test/Util/MirrorTest.php Thu Apr 26 11:26:54 2018 +0100 +++ b/vendor/psy/psysh/test/Util/MirrorTest.php Tue Jul 10 15:07:59 2018 +0100 @@ -36,7 +36,14 @@ $this->assertInstanceOf('ReflectionObject', $refl); $refl = Mirror::get($this, 'FOO'); - $this->assertInstanceOf('Psy\Reflection\ReflectionConstant', $refl); + if (version_compare(PHP_VERSION, '7.1.0', '>=')) { + $this->assertInstanceOf('ReflectionClassConstant', $refl); + } else { + $this->assertInstanceOf('Psy\Reflection\ReflectionClassConstant', $refl); + } + + $refl = Mirror::get('PHP_VERSION'); + $this->assertInstanceOf('Psy\Reflection\ReflectionConstant_', $refl); $refl = Mirror::get($this, 'bar'); $this->assertInstanceOf('ReflectionProperty', $refl); diff -r e200cb7efeb3 -r c2387f117808 vendor/psy/psysh/test/VersionUpdater/NoopCheckerTest.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vendor/psy/psysh/test/VersionUpdater/NoopCheckerTest.php Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,25 @@ +assertTrue($checker->isLatest()); + $this->assertEquals(Shell::VERSION, $checker->getLatest()); + } +} diff -r e200cb7efeb3 -r c2387f117808 vendor/psy/psysh/vendor-bin/box/composer.json --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vendor/psy/psysh/vendor-bin/box/composer.json Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,7 @@ +{ + "minimum-stability": "dev", + "prefer-stable": true, + "require": { + "humbug/box": "^3.0@alpha" + } +} diff -r e200cb7efeb3 -r c2387f117808 vendor/psy/psysh/vendor-bin/box/composer.lock --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vendor/psy/psysh/vendor-bin/box/composer.lock Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,2524 @@ +{ + "_readme": [ + "This file locks the dependencies of your project to a known state", + "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", + "This file is @generated automatically" + ], + "content-hash": "d98ffe050f0ba4e81c2d1a98ca945200", + "packages": [ + { + "name": "amphp/amp", + "version": "v2.0.7", + "source": { + "type": "git", + "url": "https://github.com/amphp/amp.git", + "reference": "d561cc9736bc18dd94a2fc9cdae98b616bd92c43" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/amphp/amp/zipball/d561cc9736bc18dd94a2fc9cdae98b616bd92c43", + "reference": "d561cc9736bc18dd94a2fc9cdae98b616bd92c43", + "shasum": "" + }, + "require": { + "php": ">=7" + }, + "require-dev": { + "amphp/phpunit-util": "^1", + "friendsofphp/php-cs-fixer": "^2.3", + "phpstan/phpstan": "^0.8.5", + "phpunit/phpunit": "^6.0.9", + "react/promise": "^2" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Amp\\": "lib" + }, + "files": [ + "lib/functions.php", + "lib/Internal/functions.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Bob Weinand", + "email": "bobwei9@hotmail.com" + }, + { + "name": "Niklas Keller", + "email": "me@kelunik.com" + }, + { + "name": "Daniel Lowrey", + "email": "rdlowrey@php.net" + }, + { + "name": "Aaron Piotrowski", + "email": "aaron@trowski.com" + } + ], + "description": "A non-blocking concurrency framework for PHP applications.", + "homepage": "http://amphp.org/amp", + "keywords": [ + "async", + "asynchronous", + "awaitable", + "concurrency", + "event", + "event-loop", + "future", + "non-blocking", + "promise" + ], + "time": "2018-04-30T20:49:57+00:00" + }, + { + "name": "amphp/byte-stream", + "version": "v1.3.1", + "source": { + "type": "git", + "url": "https://github.com/amphp/byte-stream.git", + "reference": "1b75b122e6f069e7d102eef065dc192119d99ca7" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/amphp/byte-stream/zipball/1b75b122e6f069e7d102eef065dc192119d99ca7", + "reference": "1b75b122e6f069e7d102eef065dc192119d99ca7", + "shasum": "" + }, + "require": { + "amphp/amp": "^2" + }, + "require-dev": { + "amphp/phpunit-util": "^1", + "friendsofphp/php-cs-fixer": "^2.3", + "phpunit/phpunit": "^6" + }, + "type": "library", + "autoload": { + "psr-4": { + "Amp\\ByteStream\\": "lib" + }, + "files": [ + "lib/functions.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Niklas Keller", + "email": "me@kelunik.com" + }, + { + "name": "Aaron Piotrowski", + "email": "aaron@trowski.com" + } + ], + "description": "A stream abstraction to make working with non-blocking I/O simple.", + "homepage": "http://amphp.org/byte-stream", + "keywords": [ + "amp", + "amphp", + "async", + "io", + "non-blocking", + "stream" + ], + "time": "2018-04-04T05:33:09+00:00" + }, + { + "name": "amphp/parallel", + "version": "v0.2.5", + "source": { + "type": "git", + "url": "https://github.com/amphp/parallel.git", + "reference": "732694688461936bec02c0ccf020dfee10c4f7ee" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/amphp/parallel/zipball/732694688461936bec02c0ccf020dfee10c4f7ee", + "reference": "732694688461936bec02c0ccf020dfee10c4f7ee", + "shasum": "" + }, + "require": { + "amphp/amp": "^2", + "amphp/byte-stream": "^1.2", + "amphp/parser": "^1", + "amphp/process": "^0.2 || ^0.3", + "amphp/sync": "^1.0.1" + }, + "require-dev": { + "amphp/phpunit-util": "^1", + "friendsofphp/php-cs-fixer": "^2.3", + "phpunit/phpunit": "^6" + }, + "suggest": { + "ext-pthreads": "Required for thread contexts" + }, + "type": "library", + "autoload": { + "psr-4": { + "Amp\\Parallel\\": "lib" + }, + "files": [ + "lib/Worker/functions.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Stephen Coakley", + "email": "me@stephencoakley.com" + }, + { + "name": "Aaron Piotrowski", + "email": "aaron@trowski.com" + } + ], + "description": "Parallel processing component for Amp.", + "homepage": "https://github.com/amphp/parallel", + "keywords": [ + "async", + "asynchronous", + "concurrent", + "multi-processing", + "multi-threading" + ], + "time": "2018-03-21T14:37:51+00:00" + }, + { + "name": "amphp/parallel-functions", + "version": "v0.1.2", + "source": { + "type": "git", + "url": "https://github.com/amphp/parallel-functions.git", + "reference": "999ba8a00adaf4d1fd3a7cb40bf7e565e507ff48" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/amphp/parallel-functions/zipball/999ba8a00adaf4d1fd3a7cb40bf7e565e507ff48", + "reference": "999ba8a00adaf4d1fd3a7cb40bf7e565e507ff48", + "shasum": "" + }, + "require": { + "amphp/amp": "^2.0.3", + "amphp/parallel": "^0.1.8 || ^0.2", + "opis/closure": "^3.0.7", + "php": ">=7" + }, + "require-dev": { + "amphp/phpunit-util": "^1.0", + "friendsofphp/php-cs-fixer": "^2.9", + "phpunit/phpunit": "^6.5" + }, + "type": "library", + "autoload": { + "psr-4": { + "Amp\\ParallelFunctions\\": "src" + }, + "files": [ + "src/functions.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Niklas Keller", + "email": "me@kelunik.com" + } + ], + "description": "Parallel processing made simple.", + "time": "2017-12-17T18:33:29+00:00" + }, + { + "name": "amphp/parser", + "version": "v1.0.0", + "source": { + "type": "git", + "url": "https://github.com/amphp/parser.git", + "reference": "f83e68f03d5b8e8e0365b8792985a7f341c57ae1" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/amphp/parser/zipball/f83e68f03d5b8e8e0365b8792985a7f341c57ae1", + "reference": "f83e68f03d5b8e8e0365b8792985a7f341c57ae1", + "shasum": "" + }, + "require": { + "php": ">=7" + }, + "require-dev": { + "friendsofphp/php-cs-fixer": "^2.3", + "phpunit/phpunit": "^6" + }, + "type": "library", + "autoload": { + "psr-4": { + "Amp\\Parser\\": "lib" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Niklas Keller", + "email": "me@kelunik.com" + }, + { + "name": "Aaron Piotrowski", + "email": "aaron@trowski.com" + } + ], + "description": "A generator parser to make streaming parsers simple.", + "homepage": "https://github.com/amphp/parser", + "keywords": [ + "async", + "non-blocking", + "parser", + "stream" + ], + "time": "2017-06-06T05:29:10+00:00" + }, + { + "name": "amphp/process", + "version": "v0.3.3", + "source": { + "type": "git", + "url": "https://github.com/amphp/process.git", + "reference": "b795d20a7f6d5a0637128a02be613f520f1705fc" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/amphp/process/zipball/b795d20a7f6d5a0637128a02be613f520f1705fc", + "reference": "b795d20a7f6d5a0637128a02be613f520f1705fc", + "shasum": "" + }, + "require": { + "amphp/amp": "^2", + "amphp/byte-stream": "^1", + "php": ">=7" + }, + "require-dev": { + "amphp/phpunit-util": "^1", + "friendsofphp/php-cs-fixer": "^2.3", + "phpunit/phpunit": "^6" + }, + "type": "library", + "autoload": { + "psr-4": { + "Amp\\Process\\": "lib" + }, + "files": [ + "lib/constants.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Bob Weinand", + "email": "bobwei9@hotmail.com" + }, + { + "name": "Niklas Keller", + "email": "me@kelunik.com" + }, + { + "name": "Aaron Piotrowski", + "email": "aaron@trowski.com" + } + ], + "description": "Asynchronous process manager.", + "homepage": "https://github.com/amphp/process", + "time": "2018-04-08T18:55:42+00:00" + }, + { + "name": "amphp/sync", + "version": "v1.0.1", + "source": { + "type": "git", + "url": "https://github.com/amphp/sync.git", + "reference": "a1d8f244eb19e3e2a96abc4686cebc80995bbc90" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/amphp/sync/zipball/a1d8f244eb19e3e2a96abc4686cebc80995bbc90", + "reference": "a1d8f244eb19e3e2a96abc4686cebc80995bbc90", + "shasum": "" + }, + "require": { + "amphp/amp": "^2" + }, + "require-dev": { + "amphp/phpunit-util": "^1", + "friendsofphp/php-cs-fixer": "^2.3", + "phpunit/phpunit": "^6" + }, + "type": "library", + "autoload": { + "psr-4": { + "Amp\\Sync\\": "lib" + }, + "files": [ + "lib/functions.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Stephen Coakley", + "email": "me@stephencoakley.com" + }, + { + "name": "Aaron Piotrowski", + "email": "aaron@trowski.com" + } + ], + "description": "Mutex, Semaphore, and other synchronization tools for Amp.", + "homepage": "https://github.com/amphp/sync", + "keywords": [ + "async", + "asynchronous", + "mutex", + "semaphore", + "synchronization" + ], + "time": "2017-11-29T21:48:53+00:00" + }, + { + "name": "beberlei/assert", + "version": "v2.9.5", + "source": { + "type": "git", + "url": "https://github.com/beberlei/assert.git", + "reference": "c07fe163d6a3b3e4b1275981ec004397954afa89" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/beberlei/assert/zipball/c07fe163d6a3b3e4b1275981ec004397954afa89", + "reference": "c07fe163d6a3b3e4b1275981ec004397954afa89", + "shasum": "" + }, + "require": { + "ext-mbstring": "*", + "php": ">=5.3" + }, + "require-dev": { + "friendsofphp/php-cs-fixer": "^2.1.1", + "phpunit/phpunit": "^4.8.35|^5.7" + }, + "type": "library", + "autoload": { + "psr-4": { + "Assert\\": "lib/Assert" + }, + "files": [ + "lib/Assert/functions.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-2-Clause" + ], + "authors": [ + { + "name": "Benjamin Eberlei", + "email": "kontakt@beberlei.de", + "role": "Lead Developer" + }, + { + "name": "Richard Quadling", + "email": "rquadling@gmail.com", + "role": "Collaborator" + } + ], + "description": "Thin assertion library for input validation in business models.", + "keywords": [ + "assert", + "assertion", + "validation" + ], + "time": "2018-04-16T11:18:27+00:00" + }, + { + "name": "composer/ca-bundle", + "version": "1.1.1", + "source": { + "type": "git", + "url": "https://github.com/composer/ca-bundle.git", + "reference": "d2c0a83b7533d6912e8d516756ebd34f893e9169" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/composer/ca-bundle/zipball/d2c0a83b7533d6912e8d516756ebd34f893e9169", + "reference": "d2c0a83b7533d6912e8d516756ebd34f893e9169", + "shasum": "" + }, + "require": { + "ext-openssl": "*", + "ext-pcre": "*", + "php": "^5.3.2 || ^7.0" + }, + "require-dev": { + "phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.5", + "psr/log": "^1.0", + "symfony/process": "^2.5 || ^3.0 || ^4.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.x-dev" + } + }, + "autoload": { + "psr-4": { + "Composer\\CaBundle\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Jordi Boggiano", + "email": "j.boggiano@seld.be", + "homepage": "http://seld.be" + } + ], + "description": "Lets you find a path to the system CA bundle, and includes a fallback to the Mozilla CA bundle.", + "keywords": [ + "cabundle", + "cacert", + "certificate", + "ssl", + "tls" + ], + "time": "2018-03-29T19:57:20+00:00" + }, + { + "name": "composer/composer", + "version": "1.6.5", + "source": { + "type": "git", + "url": "https://github.com/composer/composer.git", + "reference": "b184a92419cc9a9c4c6a09db555a94d441cb11c9" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/composer/composer/zipball/b184a92419cc9a9c4c6a09db555a94d441cb11c9", + "reference": "b184a92419cc9a9c4c6a09db555a94d441cb11c9", + "shasum": "" + }, + "require": { + "composer/ca-bundle": "^1.0", + "composer/semver": "^1.0", + "composer/spdx-licenses": "^1.2", + "justinrainbow/json-schema": "^3.0 || ^4.0 || ^5.0", + "php": "^5.3.2 || ^7.0", + "psr/log": "^1.0", + "seld/cli-prompt": "^1.0", + "seld/jsonlint": "^1.4", + "seld/phar-utils": "^1.0", + "symfony/console": "^2.7 || ^3.0 || ^4.0", + "symfony/filesystem": "^2.7 || ^3.0 || ^4.0", + "symfony/finder": "^2.7 || ^3.0 || ^4.0", + "symfony/process": "^2.7 || ^3.0 || ^4.0" + }, + "conflict": { + "symfony/console": "2.8.38" + }, + "require-dev": { + "phpunit/phpunit": "^4.8.35 || ^5.7", + "phpunit/phpunit-mock-objects": "^2.3 || ^3.0" + }, + "suggest": { + "ext-openssl": "Enabling the openssl extension allows you to access https URLs for repositories and packages", + "ext-zip": "Enabling the zip extension allows you to unzip archives", + "ext-zlib": "Allow gzip compression of HTTP requests" + }, + "bin": [ + "bin/composer" + ], + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.6-dev" + } + }, + "autoload": { + "psr-4": { + "Composer\\": "src/Composer" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nils Adermann", + "email": "naderman@naderman.de", + "homepage": "http://www.naderman.de" + }, + { + "name": "Jordi Boggiano", + "email": "j.boggiano@seld.be", + "homepage": "http://seld.be" + } + ], + "description": "Composer helps you declare, manage and install dependencies of PHP projects, ensuring you have the right stack everywhere.", + "homepage": "https://getcomposer.org/", + "keywords": [ + "autoload", + "dependency", + "package" + ], + "time": "2018-05-04T09:44:59+00:00" + }, + { + "name": "composer/semver", + "version": "1.4.2", + "source": { + "type": "git", + "url": "https://github.com/composer/semver.git", + "reference": "c7cb9a2095a074d131b65a8a0cd294479d785573" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/composer/semver/zipball/c7cb9a2095a074d131b65a8a0cd294479d785573", + "reference": "c7cb9a2095a074d131b65a8a0cd294479d785573", + "shasum": "" + }, + "require": { + "php": "^5.3.2 || ^7.0" + }, + "require-dev": { + "phpunit/phpunit": "^4.5 || ^5.0.5", + "phpunit/phpunit-mock-objects": "2.3.0 || ^3.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.x-dev" + } + }, + "autoload": { + "psr-4": { + "Composer\\Semver\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nils Adermann", + "email": "naderman@naderman.de", + "homepage": "http://www.naderman.de" + }, + { + "name": "Jordi Boggiano", + "email": "j.boggiano@seld.be", + "homepage": "http://seld.be" + }, + { + "name": "Rob Bast", + "email": "rob.bast@gmail.com", + "homepage": "http://robbast.nl" + } + ], + "description": "Semver library that offers utilities, version constraint parsing and validation.", + "keywords": [ + "semantic", + "semver", + "validation", + "versioning" + ], + "time": "2016-08-30T16:08:34+00:00" + }, + { + "name": "composer/spdx-licenses", + "version": "1.4.0", + "source": { + "type": "git", + "url": "https://github.com/composer/spdx-licenses.git", + "reference": "cb17687e9f936acd7e7245ad3890f953770dec1b" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/composer/spdx-licenses/zipball/cb17687e9f936acd7e7245ad3890f953770dec1b", + "reference": "cb17687e9f936acd7e7245ad3890f953770dec1b", + "shasum": "" + }, + "require": { + "php": "^5.3.2 || ^7.0" + }, + "require-dev": { + "phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.5", + "phpunit/phpunit-mock-objects": "2.3.0 || ^3.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.x-dev" + } + }, + "autoload": { + "psr-4": { + "Composer\\Spdx\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nils Adermann", + "email": "naderman@naderman.de", + "homepage": "http://www.naderman.de" + }, + { + "name": "Jordi Boggiano", + "email": "j.boggiano@seld.be", + "homepage": "http://seld.be" + }, + { + "name": "Rob Bast", + "email": "rob.bast@gmail.com", + "homepage": "http://robbast.nl" + } + ], + "description": "SPDX licenses list and validation library.", + "keywords": [ + "license", + "spdx", + "validator" + ], + "time": "2018-04-30T10:33:04+00:00" + }, + { + "name": "composer/xdebug-handler", + "version": "1.1.0", + "source": { + "type": "git", + "url": "https://github.com/composer/xdebug-handler.git", + "reference": "c919dc6c62e221fc6406f861ea13433c0aa24f08" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/composer/xdebug-handler/zipball/c919dc6c62e221fc6406f861ea13433c0aa24f08", + "reference": "c919dc6c62e221fc6406f861ea13433c0aa24f08", + "shasum": "" + }, + "require": { + "php": "^5.3.2 || ^7.0", + "psr/log": "^1.0" + }, + "require-dev": { + "phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.5" + }, + "type": "library", + "autoload": { + "psr-4": { + "Composer\\XdebugHandler\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "John Stevenson", + "email": "john-stevenson@blueyonder.co.uk" + } + ], + "description": "Restarts a process without xdebug.", + "keywords": [ + "Xdebug", + "performance" + ], + "time": "2018-04-11T15:42:36+00:00" + }, + { + "name": "doctrine/annotations", + "version": "v1.6.0", + "source": { + "type": "git", + "url": "https://github.com/doctrine/annotations.git", + "reference": "c7f2050c68a9ab0bdb0f98567ec08d80ea7d24d5" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/doctrine/annotations/zipball/c7f2050c68a9ab0bdb0f98567ec08d80ea7d24d5", + "reference": "c7f2050c68a9ab0bdb0f98567ec08d80ea7d24d5", + "shasum": "" + }, + "require": { + "doctrine/lexer": "1.*", + "php": "^7.1" + }, + "require-dev": { + "doctrine/cache": "1.*", + "phpunit/phpunit": "^6.4" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.6.x-dev" + } + }, + "autoload": { + "psr-4": { + "Doctrine\\Common\\Annotations\\": "lib/Doctrine/Common/Annotations" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Roman Borschel", + "email": "roman@code-factory.org" + }, + { + "name": "Benjamin Eberlei", + "email": "kontakt@beberlei.de" + }, + { + "name": "Guilherme Blanco", + "email": "guilhermeblanco@gmail.com" + }, + { + "name": "Jonathan Wage", + "email": "jonwage@gmail.com" + }, + { + "name": "Johannes Schmitt", + "email": "schmittjoh@gmail.com" + } + ], + "description": "Docblock Annotations Parser", + "homepage": "http://www.doctrine-project.org", + "keywords": [ + "annotations", + "docblock", + "parser" + ], + "time": "2017-12-06T07:11:42+00:00" + }, + { + "name": "doctrine/lexer", + "version": "v1.0.1", + "source": { + "type": "git", + "url": "https://github.com/doctrine/lexer.git", + "reference": "83893c552fd2045dd78aef794c31e694c37c0b8c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/doctrine/lexer/zipball/83893c552fd2045dd78aef794c31e694c37c0b8c", + "reference": "83893c552fd2045dd78aef794c31e694c37c0b8c", + "shasum": "" + }, + "require": { + "php": ">=5.3.2" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-0": { + "Doctrine\\Common\\Lexer\\": "lib/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Roman Borschel", + "email": "roman@code-factory.org" + }, + { + "name": "Guilherme Blanco", + "email": "guilhermeblanco@gmail.com" + }, + { + "name": "Johannes Schmitt", + "email": "schmittjoh@gmail.com" + } + ], + "description": "Base library for a lexer that can be used in Top-Down, Recursive Descent Parsers.", + "homepage": "http://www.doctrine-project.org", + "keywords": [ + "lexer", + "parser" + ], + "time": "2014-09-09T13:34:57+00:00" + }, + { + "name": "herrera-io/annotations", + "version": "1.0.1", + "source": { + "type": "git", + "url": "https://github.com/kherge-abandoned/php-annotations.git", + "reference": "7d8b9a536da7f12aad8de7f28b2cb5266bde8da1" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/kherge-abandoned/php-annotations/zipball/7d8b9a536da7f12aad8de7f28b2cb5266bde8da1", + "reference": "7d8b9a536da7f12aad8de7f28b2cb5266bde8da1", + "shasum": "" + }, + "require": { + "doctrine/annotations": "~1.0", + "php": ">=5.3.3" + }, + "require-dev": { + "herrera-io/phpunit-test-case": "1.*", + "phpunit/phpunit": "3.7.*" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0-dev" + } + }, + "autoload": { + "psr-0": { + "Herrera\\Annotations": "src/lib" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Kevin Herrera", + "email": "kevin@herrera.io", + "homepage": "http://kevin.herrera.io" + } + ], + "description": "A tokenizer for Doctrine annotations.", + "homepage": "https://github.com/herrera-io/php-annotations", + "keywords": [ + "annotations", + "doctrine", + "tokenizer" + ], + "abandoned": true, + "time": "2014-02-03T17:34:08+00:00" + }, + { + "name": "humbug/box", + "version": "3.0.0-alpha.5", + "source": { + "type": "git", + "url": "https://github.com/humbug/box.git", + "reference": "26b3f481e3b375f55c0644f501b831f7c05d8058" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/humbug/box/zipball/26b3f481e3b375f55c0644f501b831f7c05d8058", + "reference": "26b3f481e3b375f55c0644f501b831f7c05d8058", + "shasum": "" + }, + "require": { + "amphp/parallel-functions": "^0.1.2", + "beberlei/assert": "^2.8", + "composer/composer": "^1.6", + "composer/xdebug-handler": "^1.1.0", + "ext-phar": "*", + "herrera-io/annotations": "~1.0", + "humbug/php-scoper": "^1.0@dev", + "justinrainbow/json-schema": "^5.2", + "nikic/iter": "^1.6", + "php": "^7.1", + "phpseclib/phpseclib": "~2.0", + "seld/jsonlint": "^1.6", + "symfony/console": "^3.4 || ^4.0", + "symfony/filesystem": "^3.4 || ^4.0", + "symfony/finder": "^3.4 || ^4.0", + "symfony/var-dumper": "^3.4 || ^4.0", + "webmozart/path-util": "^2.3" + }, + "require-dev": { + "bamarni/composer-bin-plugin": "^1.2", + "infection/infection": "^0.8", + "mikey179/vfsstream": "^1.1", + "phpunit/phpunit": "^7.0" + }, + "suggest": { + "ext-openssl": "To accelerate private key generation." + }, + "bin": [ + "bin/box" + ], + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.x-dev" + }, + "bamarni-bin": { + "bin-links": false + } + }, + "autoload": { + "psr-4": { + "KevinGH\\Box\\": "src" + }, + "files": [ + "src/FileSystem/file_system.php", + "src/functions.php" + ], + "exclude-from-classmap": [ + "/Test/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Kevin Herrera", + "email": "kevin@herrera.io", + "homepage": "http://kevin.herrera.io" + }, + { + "name": "Théo Fidry", + "email": "theo.fidry@gmail.com" + } + ], + "description": "Fast, zero config application bundler with PHARs.", + "keywords": [ + "phar" + ], + "time": "2018-05-04T22:04:10+00:00" + }, + { + "name": "humbug/php-scoper", + "version": "dev-master", + "source": { + "type": "git", + "url": "https://github.com/humbug/php-scoper.git", + "reference": "450fe36a7457847d0cb431e7379b5df9d05992a4" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/humbug/php-scoper/zipball/450fe36a7457847d0cb431e7379b5df9d05992a4", + "reference": "450fe36a7457847d0cb431e7379b5df9d05992a4", + "shasum": "" + }, + "require": { + "nikic/php-parser": "^3.0", + "ocramius/package-versions": "^1.1", + "padraic/phar-updater": "^1.0", + "php": "^7.1", + "roave/better-reflection": "^2.0", + "symfony/console": "^3.2 || ^4.0", + "symfony/filesystem": "^3.2 || ^4.0", + "symfony/finder": "^3.2 || ^4.0" + }, + "require-dev": { + "bamarni/composer-bin-plugin": "^1.1", + "phpunit/phpunit": "^6.1" + }, + "bin": [ + "bin/php-scoper" + ], + "type": "library", + "extra": { + "bamarni-bin": { + "bin-links": false + }, + "branch-alias": { + "dev-master": "1.0-dev" + } + }, + "autoload": { + "files": [ + "src/functions.php" + ], + "psr-4": { + "Humbug\\PhpScoper\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Bernhard Schussek", + "email": "bschussek@gmail.com" + }, + { + "name": "Théo Fidry", + "email": "theo.fidry@gmail.com" + }, + { + "name": "Pádraic Brady", + "email": "padraic.brady@gmail.com" + } + ], + "description": "Prefixes all PHP namespaces in a file or directory.", + "time": "2018-04-25T21:59:07+00:00" + }, + { + "name": "justinrainbow/json-schema", + "version": "5.2.7", + "source": { + "type": "git", + "url": "https://github.com/justinrainbow/json-schema.git", + "reference": "8560d4314577199ba51bf2032f02cd1315587c23" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/justinrainbow/json-schema/zipball/8560d4314577199ba51bf2032f02cd1315587c23", + "reference": "8560d4314577199ba51bf2032f02cd1315587c23", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "require-dev": { + "friendsofphp/php-cs-fixer": "^2.1", + "json-schema/json-schema-test-suite": "1.2.0", + "phpunit/phpunit": "^4.8.35" + }, + "bin": [ + "bin/validate-json" + ], + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "5.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "JsonSchema\\": "src/JsonSchema/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Bruno Prieto Reis", + "email": "bruno.p.reis@gmail.com" + }, + { + "name": "Justin Rainbow", + "email": "justin.rainbow@gmail.com" + }, + { + "name": "Igor Wiedler", + "email": "igor@wiedler.ch" + }, + { + "name": "Robert Schönthal", + "email": "seroscho@googlemail.com" + } + ], + "description": "A library to validate a json schema.", + "homepage": "https://github.com/justinrainbow/json-schema", + "keywords": [ + "json", + "schema" + ], + "time": "2018-02-14T22:26:30+00:00" + }, + { + "name": "nikic/iter", + "version": "v1.6.0", + "source": { + "type": "git", + "url": "https://github.com/nikic/iter.git", + "reference": "fed36b417ea93fe9b4b7cb2e2abf98d91092564c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/nikic/iter/zipball/fed36b417ea93fe9b4b7cb2e2abf98d91092564c", + "reference": "fed36b417ea93fe9b4b7cb2e2abf98d91092564c", + "shasum": "" + }, + "require": { + "php": ">=5.5.0" + }, + "require-dev": { + "phpunit/phpunit": "~4.0|~5.0" + }, + "type": "library", + "autoload": { + "files": [ + "src/bootstrap.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Nikita Popov", + "email": "nikic@php.net" + } + ], + "description": "Iteration primitives using generators", + "keywords": [ + "functional", + "generator", + "iterator" + ], + "time": "2017-11-10T22:56:03+00:00" + }, + { + "name": "nikic/php-parser", + "version": "v3.1.5", + "source": { + "type": "git", + "url": "https://github.com/nikic/PHP-Parser.git", + "reference": "bb87e28e7d7b8d9a7fda231d37457c9210faf6ce" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/bb87e28e7d7b8d9a7fda231d37457c9210faf6ce", + "reference": "bb87e28e7d7b8d9a7fda231d37457c9210faf6ce", + "shasum": "" + }, + "require": { + "ext-tokenizer": "*", + "php": ">=5.5" + }, + "require-dev": { + "phpunit/phpunit": "~4.0|~5.0" + }, + "bin": [ + "bin/php-parse" + ], + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.0-dev" + } + }, + "autoload": { + "psr-4": { + "PhpParser\\": "lib/PhpParser" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Nikita Popov" + } + ], + "description": "A PHP parser written in PHP", + "keywords": [ + "parser", + "php" + ], + "time": "2018-02-28T20:30:58+00:00" + }, + { + "name": "ocramius/package-versions", + "version": "1.3.0", + "source": { + "type": "git", + "url": "https://github.com/Ocramius/PackageVersions.git", + "reference": "4489d5002c49d55576fa0ba786f42dbb009be46f" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/Ocramius/PackageVersions/zipball/4489d5002c49d55576fa0ba786f42dbb009be46f", + "reference": "4489d5002c49d55576fa0ba786f42dbb009be46f", + "shasum": "" + }, + "require": { + "composer-plugin-api": "^1.0.0", + "php": "^7.1.0" + }, + "require-dev": { + "composer/composer": "^1.6.3", + "ext-zip": "*", + "infection/infection": "^0.7.1", + "phpunit/phpunit": "^7.0.0" + }, + "type": "composer-plugin", + "extra": { + "class": "PackageVersions\\Installer", + "branch-alias": { + "dev-master": "2.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "PackageVersions\\": "src/PackageVersions" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Marco Pivetta", + "email": "ocramius@gmail.com" + } + ], + "description": "Composer plugin that provides efficient querying for installed package versions (no runtime IO)", + "time": "2018-02-05T13:05:30+00:00" + }, + { + "name": "opis/closure", + "version": "3.0.12", + "source": { + "type": "git", + "url": "https://github.com/opis/closure.git", + "reference": "507a28d15e79258d404ba76e73976ba895d0eb11" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/opis/closure/zipball/507a28d15e79258d404ba76e73976ba895d0eb11", + "reference": "507a28d15e79258d404ba76e73976ba895d0eb11", + "shasum": "" + }, + "require": { + "php": ">=5.4.0" + }, + "require-dev": { + "jeremeamia/superclosure": "^2.0", + "phpunit/phpunit": "^4.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Opis\\Closure\\": "src/" + }, + "files": [ + "functions.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Marius Sarca", + "email": "marius.sarca@gmail.com" + } + ], + "description": "A library that can be used to serialize closures (anonymous functions) and arbitrary objects.", + "homepage": "http://www.opis.io/closure", + "keywords": [ + "anonymous functions", + "closure", + "function", + "serializable", + "serialization", + "serialize" + ], + "time": "2018-02-23T08:08:14+00:00" + }, + { + "name": "padraic/humbug_get_contents", + "version": "1.1.2", + "source": { + "type": "git", + "url": "https://github.com/humbug/file_get_contents.git", + "reference": "dcb086060c9dd6b2f51d8f7a895500307110b7a7" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/humbug/file_get_contents/zipball/dcb086060c9dd6b2f51d8f7a895500307110b7a7", + "reference": "dcb086060c9dd6b2f51d8f7a895500307110b7a7", + "shasum": "" + }, + "require": { + "composer/ca-bundle": "^1.0", + "ext-openssl": "*", + "php": "^5.3 || ^7.0 || ^7.1 || ^7.2" + }, + "require-dev": { + "bamarni/composer-bin-plugin": "^1.1", + "mikey179/vfsstream": "^1.6", + "phpunit/phpunit": "^4.8 || ^5.7 || ^6.5" + }, + "type": "library", + "extra": { + "bamarni-bin": { + "bin-links": false + }, + "branch-alias": { + "dev-master": "2.0-dev" + } + }, + "autoload": { + "psr-4": { + "Humbug\\": "src/" + }, + "files": [ + "src/function.php", + "src/functions.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Padraic Brady", + "email": "padraic.brady@gmail.com", + "homepage": "http://blog.astrumfutura.com" + }, + { + "name": "Théo Fidry", + "email": "theo.fidry@gmail.com" + } + ], + "description": "Secure wrapper for accessing HTTPS resources with file_get_contents for PHP 5.3+", + "homepage": "https://github.com/padraic/file_get_contents", + "keywords": [ + "download", + "file_get_contents", + "http", + "https", + "ssl", + "tls" + ], + "time": "2018-02-12T18:47:17+00:00" + }, + { + "name": "padraic/phar-updater", + "version": "v1.0.6", + "source": { + "type": "git", + "url": "https://github.com/humbug/phar-updater.git", + "reference": "d01d3b8f26e541ac9b9eeba1e18d005d852f7ff1" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/humbug/phar-updater/zipball/d01d3b8f26e541ac9b9eeba1e18d005d852f7ff1", + "reference": "d01d3b8f26e541ac9b9eeba1e18d005d852f7ff1", + "shasum": "" + }, + "require": { + "padraic/humbug_get_contents": "^1.0", + "php": ">=5.3.3" + }, + "require-dev": { + "phpunit/phpunit": "~4.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0-dev" + } + }, + "autoload": { + "psr-4": { + "Humbug\\SelfUpdate\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Pádraic Brady", + "email": "padraic.brady@gmail.com", + "homepage": "http://blog.astrumfutura.com" + } + ], + "description": "A thing to make PHAR self-updating easy and secure.", + "keywords": [ + "humbug", + "phar", + "self-update", + "update" + ], + "time": "2018-03-30T12:52:15+00:00" + }, + { + "name": "phpdocumentor/reflection-common", + "version": "1.0.1", + "source": { + "type": "git", + "url": "https://github.com/phpDocumentor/ReflectionCommon.git", + "reference": "21bdeb5f65d7ebf9f43b1b25d404f87deab5bfb6" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpDocumentor/ReflectionCommon/zipball/21bdeb5f65d7ebf9f43b1b25d404f87deab5bfb6", + "reference": "21bdeb5f65d7ebf9f43b1b25d404f87deab5bfb6", + "shasum": "" + }, + "require": { + "php": ">=5.5" + }, + "require-dev": { + "phpunit/phpunit": "^4.6" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "phpDocumentor\\Reflection\\": [ + "src" + ] + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Jaap van Otterdijk", + "email": "opensource@ijaap.nl" + } + ], + "description": "Common reflection classes used by phpdocumentor to reflect the code structure", + "homepage": "http://www.phpdoc.org", + "keywords": [ + "FQSEN", + "phpDocumentor", + "phpdoc", + "reflection", + "static analysis" + ], + "time": "2017-09-11T18:02:19+00:00" + }, + { + "name": "phpdocumentor/reflection-docblock", + "version": "4.3.0", + "source": { + "type": "git", + "url": "https://github.com/phpDocumentor/ReflectionDocBlock.git", + "reference": "94fd0001232e47129dd3504189fa1c7225010d08" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/94fd0001232e47129dd3504189fa1c7225010d08", + "reference": "94fd0001232e47129dd3504189fa1c7225010d08", + "shasum": "" + }, + "require": { + "php": "^7.0", + "phpdocumentor/reflection-common": "^1.0.0", + "phpdocumentor/type-resolver": "^0.4.0", + "webmozart/assert": "^1.0" + }, + "require-dev": { + "doctrine/instantiator": "~1.0.5", + "mockery/mockery": "^1.0", + "phpunit/phpunit": "^6.4" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "4.x-dev" + } + }, + "autoload": { + "psr-4": { + "phpDocumentor\\Reflection\\": [ + "src/" + ] + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Mike van Riel", + "email": "me@mikevanriel.com" + } + ], + "description": "With this component, a library can provide support for annotations via DocBlocks or otherwise retrieve information that is embedded in a DocBlock.", + "time": "2017-11-30T07:14:17+00:00" + }, + { + "name": "phpdocumentor/type-resolver", + "version": "0.4.0", + "source": { + "type": "git", + "url": "https://github.com/phpDocumentor/TypeResolver.git", + "reference": "9c977708995954784726e25d0cd1dddf4e65b0f7" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpDocumentor/TypeResolver/zipball/9c977708995954784726e25d0cd1dddf4e65b0f7", + "reference": "9c977708995954784726e25d0cd1dddf4e65b0f7", + "shasum": "" + }, + "require": { + "php": "^5.5 || ^7.0", + "phpdocumentor/reflection-common": "^1.0" + }, + "require-dev": { + "mockery/mockery": "^0.9.4", + "phpunit/phpunit": "^5.2||^4.8.24" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "phpDocumentor\\Reflection\\": [ + "src/" + ] + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Mike van Riel", + "email": "me@mikevanriel.com" + } + ], + "time": "2017-07-14T14:27:02+00:00" + }, + { + "name": "phpseclib/phpseclib", + "version": "2.0.11", + "source": { + "type": "git", + "url": "https://github.com/phpseclib/phpseclib.git", + "reference": "7053f06f91b3de78e143d430e55a8f7889efc08b" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpseclib/phpseclib/zipball/7053f06f91b3de78e143d430e55a8f7889efc08b", + "reference": "7053f06f91b3de78e143d430e55a8f7889efc08b", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "require-dev": { + "phing/phing": "~2.7", + "phpunit/phpunit": "^4.8.35|^5.7|^6.0", + "sami/sami": "~2.0", + "squizlabs/php_codesniffer": "~2.0" + }, + "suggest": { + "ext-gmp": "Install the GMP (GNU Multiple Precision) extension in order to speed up arbitrary precision integer arithmetic operations.", + "ext-libsodium": "SSH2/SFTP can make use of some algorithms provided by the libsodium-php extension.", + "ext-mcrypt": "Install the Mcrypt extension in order to speed up a few other cryptographic operations.", + "ext-openssl": "Install the OpenSSL extension in order to speed up a wide variety of cryptographic operations." + }, + "type": "library", + "autoload": { + "files": [ + "phpseclib/bootstrap.php" + ], + "psr-4": { + "phpseclib\\": "phpseclib/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Jim Wigginton", + "email": "terrafrost@php.net", + "role": "Lead Developer" + }, + { + "name": "Patrick Monnerat", + "email": "pm@datasphere.ch", + "role": "Developer" + }, + { + "name": "Andreas Fischer", + "email": "bantu@phpbb.com", + "role": "Developer" + }, + { + "name": "Hans-Jürgen Petrich", + "email": "petrich@tronic-media.com", + "role": "Developer" + }, + { + "name": "Graham Campbell", + "email": "graham@alt-three.com", + "role": "Developer" + } + ], + "description": "PHP Secure Communications Library - Pure-PHP implementations of RSA, AES, SSH2, SFTP, X.509 etc.", + "homepage": "http://phpseclib.sourceforge.net", + "keywords": [ + "BigInteger", + "aes", + "asn.1", + "asn1", + "blowfish", + "crypto", + "cryptography", + "encryption", + "rsa", + "security", + "sftp", + "signature", + "signing", + "ssh", + "twofish", + "x.509", + "x509" + ], + "time": "2018-04-15T16:55:05+00:00" + }, + { + "name": "psr/log", + "version": "1.0.2", + "source": { + "type": "git", + "url": "https://github.com/php-fig/log.git", + "reference": "4ebe3a8bf773a19edfe0a84b6585ba3d401b724d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/log/zipball/4ebe3a8bf773a19edfe0a84b6585ba3d401b724d", + "reference": "4ebe3a8bf773a19edfe0a84b6585ba3d401b724d", + "shasum": "" + }, + "require": { + "php": ">=5.3.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Log\\": "Psr/Log/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "http://www.php-fig.org/" + } + ], + "description": "Common interface for logging libraries", + "homepage": "https://github.com/php-fig/log", + "keywords": [ + "log", + "psr", + "psr-3" + ], + "time": "2016-10-10T12:19:37+00:00" + }, + { + "name": "roave/better-reflection", + "version": "2.0.2", + "source": { + "type": "git", + "url": "https://github.com/Roave/BetterReflection.git", + "reference": "efc45b50cb52d5eeaacab15741376e981e28738b" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/Roave/BetterReflection/zipball/efc45b50cb52d5eeaacab15741376e981e28738b", + "reference": "efc45b50cb52d5eeaacab15741376e981e28738b", + "shasum": "" + }, + "require": { + "nikic/php-parser": "^3.1.1", + "php": ">=7.1.0,<7.3.0", + "phpdocumentor/reflection-docblock": "^4.1.1", + "phpdocumentor/type-resolver": "^0.4.0", + "roave/signature": "^1.0" + }, + "require-dev": { + "phpunit/phpunit": "^6.3.0" + }, + "suggest": { + "composer/composer": "Required to use the ComposerSourceLocator" + }, + "type": "library", + "autoload": { + "psr-4": { + "Roave\\BetterReflection\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Marco Pivetta", + "email": "ocramius@gmail.com", + "homepage": "http://ocramius.github.io/" + }, + { + "name": "James Titcumb", + "email": "james@asgrim.com", + "homepage": "https://github.com/asgrim" + }, + { + "name": "Gary Hockin", + "email": "gary@roave.com", + "homepage": "https://github.com/geeh" + }, + { + "name": "Jaroslav Hanslík", + "email": "kukulich@kukulich.cz", + "homepage": "https://github.com/kukulich" + } + ], + "description": "Better Reflection - an improved code reflection API", + "time": "2018-02-05T08:08:57+00:00" + }, + { + "name": "roave/signature", + "version": "1.0.0", + "source": { + "type": "git", + "url": "https://github.com/Roave/Signature.git", + "reference": "bed4ecbdd7f312ab6bb39561ac191f520bcee386" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/Roave/Signature/zipball/bed4ecbdd7f312ab6bb39561ac191f520bcee386", + "reference": "bed4ecbdd7f312ab6bb39561ac191f520bcee386", + "shasum": "" + }, + "require": { + "php": "^7.0|^7.1" + }, + "require-dev": { + "phpunit/phpunit": "^5.6" + }, + "type": "library", + "autoload": { + "psr-4": { + "Roave\\Signature\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "Sign and verify stuff", + "time": "2017-02-17T13:53:21+00:00" + }, + { + "name": "seld/cli-prompt", + "version": "1.0.3", + "source": { + "type": "git", + "url": "https://github.com/Seldaek/cli-prompt.git", + "reference": "a19a7376a4689d4d94cab66ab4f3c816019ba8dd" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/Seldaek/cli-prompt/zipball/a19a7376a4689d4d94cab66ab4f3c816019ba8dd", + "reference": "a19a7376a4689d4d94cab66ab4f3c816019ba8dd", + "shasum": "" + }, + "require": { + "php": ">=5.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.x-dev" + } + }, + "autoload": { + "psr-4": { + "Seld\\CliPrompt\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Jordi Boggiano", + "email": "j.boggiano@seld.be" + } + ], + "description": "Allows you to prompt for user input on the command line, and optionally hide the characters they type", + "keywords": [ + "cli", + "console", + "hidden", + "input", + "prompt" + ], + "time": "2017-03-18T11:32:45+00:00" + }, + { + "name": "seld/jsonlint", + "version": "1.7.1", + "source": { + "type": "git", + "url": "https://github.com/Seldaek/jsonlint.git", + "reference": "d15f59a67ff805a44c50ea0516d2341740f81a38" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/Seldaek/jsonlint/zipball/d15f59a67ff805a44c50ea0516d2341740f81a38", + "reference": "d15f59a67ff805a44c50ea0516d2341740f81a38", + "shasum": "" + }, + "require": { + "php": "^5.3 || ^7.0" + }, + "require-dev": { + "phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.0" + }, + "bin": [ + "bin/jsonlint" + ], + "type": "library", + "autoload": { + "psr-4": { + "Seld\\JsonLint\\": "src/Seld/JsonLint/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Jordi Boggiano", + "email": "j.boggiano@seld.be", + "homepage": "http://seld.be" + } + ], + "description": "JSON Linter", + "keywords": [ + "json", + "linter", + "parser", + "validator" + ], + "time": "2018-01-24T12:46:19+00:00" + }, + { + "name": "seld/phar-utils", + "version": "1.0.1", + "source": { + "type": "git", + "url": "https://github.com/Seldaek/phar-utils.git", + "reference": "7009b5139491975ef6486545a39f3e6dad5ac30a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/Seldaek/phar-utils/zipball/7009b5139491975ef6486545a39f3e6dad5ac30a", + "reference": "7009b5139491975ef6486545a39f3e6dad5ac30a", + "shasum": "" + }, + "require": { + "php": ">=5.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.x-dev" + } + }, + "autoload": { + "psr-4": { + "Seld\\PharUtils\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Jordi Boggiano", + "email": "j.boggiano@seld.be" + } + ], + "description": "PHAR file format utilities, for when PHP phars you up", + "keywords": [ + "phra" + ], + "time": "2015-10-13T18:44:15+00:00" + }, + { + "name": "symfony/console", + "version": "v4.0.9", + "source": { + "type": "git", + "url": "https://github.com/symfony/console.git", + "reference": "3e820bc2c520a87ca209ad8fa961c97f42e0b4ae" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/console/zipball/3e820bc2c520a87ca209ad8fa961c97f42e0b4ae", + "reference": "3e820bc2c520a87ca209ad8fa961c97f42e0b4ae", + "shasum": "" + }, + "require": { + "php": "^7.1.3", + "symfony/polyfill-mbstring": "~1.0" + }, + "conflict": { + "symfony/dependency-injection": "<3.4", + "symfony/process": "<3.3" + }, + "require-dev": { + "psr/log": "~1.0", + "symfony/config": "~3.4|~4.0", + "symfony/dependency-injection": "~3.4|~4.0", + "symfony/event-dispatcher": "~3.4|~4.0", + "symfony/lock": "~3.4|~4.0", + "symfony/process": "~3.4|~4.0" + }, + "suggest": { + "psr/log-implementation": "For using the console logger", + "symfony/event-dispatcher": "", + "symfony/lock": "", + "symfony/process": "" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "4.0-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\Console\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony Console Component", + "homepage": "https://symfony.com", + "time": "2018-04-30T01:23:47+00:00" + }, + { + "name": "symfony/filesystem", + "version": "v4.0.9", + "source": { + "type": "git", + "url": "https://github.com/symfony/filesystem.git", + "reference": "5d2d655b2c72fc4d9bf7e9bf14f72a447b940f21" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/filesystem/zipball/5d2d655b2c72fc4d9bf7e9bf14f72a447b940f21", + "reference": "5d2d655b2c72fc4d9bf7e9bf14f72a447b940f21", + "shasum": "" + }, + "require": { + "php": "^7.1.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "4.0-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\Filesystem\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony Filesystem Component", + "homepage": "https://symfony.com", + "time": "2018-02-22T10:50:29+00:00" + }, + { + "name": "symfony/finder", + "version": "v4.0.9", + "source": { + "type": "git", + "url": "https://github.com/symfony/finder.git", + "reference": "ca27c02b7a3fef4828c998c2ff9ba7aae1641c49" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/finder/zipball/ca27c02b7a3fef4828c998c2ff9ba7aae1641c49", + "reference": "ca27c02b7a3fef4828c998c2ff9ba7aae1641c49", + "shasum": "" + }, + "require": { + "php": "^7.1.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "4.0-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\Finder\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony Finder Component", + "homepage": "https://symfony.com", + "time": "2018-04-04T05:10:37+00:00" + }, + { + "name": "symfony/polyfill-mbstring", + "version": "v1.8.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-mbstring.git", + "reference": "3296adf6a6454a050679cde90f95350ad604b171" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/3296adf6a6454a050679cde90f95350ad604b171", + "reference": "3296adf6a6454a050679cde90f95350ad604b171", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "suggest": { + "ext-mbstring": "For best performance" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.8-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Polyfill\\Mbstring\\": "" + }, + "files": [ + "bootstrap.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill for the Mbstring extension", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "mbstring", + "polyfill", + "portable", + "shim" + ], + "time": "2018-04-26T10:06:28+00:00" + }, + { + "name": "symfony/polyfill-php72", + "version": "v1.8.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-php72.git", + "reference": "a4576e282d782ad82397f3e4ec1df8e0f0cafb46" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-php72/zipball/a4576e282d782ad82397f3e4ec1df8e0f0cafb46", + "reference": "a4576e282d782ad82397f3e4ec1df8e0f0cafb46", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.8-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Polyfill\\Php72\\": "" + }, + "files": [ + "bootstrap.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill backporting some PHP 7.2+ features to lower PHP versions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "polyfill", + "portable", + "shim" + ], + "time": "2018-04-26T10:06:28+00:00" + }, + { + "name": "symfony/process", + "version": "v4.0.9", + "source": { + "type": "git", + "url": "https://github.com/symfony/process.git", + "reference": "d7dc1ee5dfe9f732cb1bba7310f5b99f2b7a6d25" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/process/zipball/d7dc1ee5dfe9f732cb1bba7310f5b99f2b7a6d25", + "reference": "d7dc1ee5dfe9f732cb1bba7310f5b99f2b7a6d25", + "shasum": "" + }, + "require": { + "php": "^7.1.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "4.0-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\Process\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony Process Component", + "homepage": "https://symfony.com", + "time": "2018-04-03T05:24:00+00:00" + }, + { + "name": "symfony/var-dumper", + "version": "v4.0.9", + "source": { + "type": "git", + "url": "https://github.com/symfony/var-dumper.git", + "reference": "3c34cf3f4bbac9e003d9325225e9ef1a49180a18" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/var-dumper/zipball/3c34cf3f4bbac9e003d9325225e9ef1a49180a18", + "reference": "3c34cf3f4bbac9e003d9325225e9ef1a49180a18", + "shasum": "" + }, + "require": { + "php": "^7.1.3", + "symfony/polyfill-mbstring": "~1.0", + "symfony/polyfill-php72": "~1.5" + }, + "conflict": { + "phpunit/phpunit": "<4.8.35|<5.4.3,>=5.0" + }, + "require-dev": { + "ext-iconv": "*", + "twig/twig": "~1.34|~2.4" + }, + "suggest": { + "ext-iconv": "To convert non-UTF-8 strings to UTF-8 (or symfony/polyfill-iconv in case ext-iconv cannot be used).", + "ext-intl": "To show region name in time zone dump" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "4.0-dev" + } + }, + "autoload": { + "files": [ + "Resources/functions/dump.php" + ], + "psr-4": { + "Symfony\\Component\\VarDumper\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony mechanism for exploring and dumping PHP variables", + "homepage": "https://symfony.com", + "keywords": [ + "debug", + "dump" + ], + "time": "2018-04-26T16:12:06+00:00" + }, + { + "name": "webmozart/assert", + "version": "1.3.0", + "source": { + "type": "git", + "url": "https://github.com/webmozart/assert.git", + "reference": "0df1908962e7a3071564e857d86874dad1ef204a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/webmozart/assert/zipball/0df1908962e7a3071564e857d86874dad1ef204a", + "reference": "0df1908962e7a3071564e857d86874dad1ef204a", + "shasum": "" + }, + "require": { + "php": "^5.3.3 || ^7.0" + }, + "require-dev": { + "phpunit/phpunit": "^4.6", + "sebastian/version": "^1.0.1" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.3-dev" + } + }, + "autoload": { + "psr-4": { + "Webmozart\\Assert\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Bernhard Schussek", + "email": "bschussek@gmail.com" + } + ], + "description": "Assertions to validate method input/output with nice error messages.", + "keywords": [ + "assert", + "check", + "validate" + ], + "time": "2018-01-29T19:49:41+00:00" + }, + { + "name": "webmozart/path-util", + "version": "2.3.0", + "source": { + "type": "git", + "url": "https://github.com/webmozart/path-util.git", + "reference": "d939f7edc24c9a1bb9c0dee5cb05d8e859490725" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/webmozart/path-util/zipball/d939f7edc24c9a1bb9c0dee5cb05d8e859490725", + "reference": "d939f7edc24c9a1bb9c0dee5cb05d8e859490725", + "shasum": "" + }, + "require": { + "php": ">=5.3.3", + "webmozart/assert": "~1.0" + }, + "require-dev": { + "phpunit/phpunit": "^4.6", + "sebastian/version": "^1.0.1" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.3-dev" + } + }, + "autoload": { + "psr-4": { + "Webmozart\\PathUtil\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Bernhard Schussek", + "email": "bschussek@gmail.com" + } + ], + "description": "A robust cross-platform utility for normalizing, comparing and modifying file paths.", + "time": "2015-12-17T08:42:14+00:00" + } + ], + "packages-dev": [], + "aliases": [], + "minimum-stability": "dev", + "stability-flags": { + "humbug/box": 15 + }, + "prefer-stable": true, + "prefer-lowest": false, + "platform": [], + "platform-dev": [] +} diff -r e200cb7efeb3 -r c2387f117808 vendor/symfony/console/Command/Command.php --- a/vendor/symfony/console/Command/Command.php Thu Apr 26 11:26:54 2018 +0100 +++ b/vendor/symfony/console/Command/Command.php Tue Jul 10 15:07:59 2018 +0100 @@ -218,12 +218,11 @@ if (null !== $this->processTitle) { if (function_exists('cli_set_process_title')) { - if (false === @cli_set_process_title($this->processTitle)) { + if (!@cli_set_process_title($this->processTitle)) { if ('Darwin' === PHP_OS) { $output->writeln('Running "cli_get_process_title" as an unprivileged user is not supported on MacOS.'); } else { - $error = error_get_last(); - trigger_error($error['message'], E_USER_WARNING); + cli_set_process_title($this->processTitle); } } } elseif (function_exists('setproctitle')) { diff -r e200cb7efeb3 -r c2387f117808 vendor/symfony/console/Descriptor/JsonDescriptor.php --- a/vendor/symfony/console/Descriptor/JsonDescriptor.php Thu Apr 26 11:26:54 2018 +0100 +++ b/vendor/symfony/console/Descriptor/JsonDescriptor.php Tue Jul 10 15:07:59 2018 +0100 @@ -121,7 +121,7 @@ { return array( 'name' => '--'.$option->getName(), - 'shortcut' => $option->getShortcut() ? '-'.implode('|-', explode('|', $option->getShortcut())) : '', + 'shortcut' => $option->getShortcut() ? '-'.str_replace('|', '|-', $option->getShortcut()) : '', 'accept_value' => $option->acceptValue(), 'is_value_required' => $option->isValueRequired(), 'is_multiple' => $option->isArray(), diff -r e200cb7efeb3 -r c2387f117808 vendor/symfony/console/Descriptor/MarkdownDescriptor.php --- a/vendor/symfony/console/Descriptor/MarkdownDescriptor.php Thu Apr 26 11:26:54 2018 +0100 +++ b/vendor/symfony/console/Descriptor/MarkdownDescriptor.php Tue Jul 10 15:07:59 2018 +0100 @@ -70,7 +70,7 @@ { $name = '--'.$option->getName(); if ($option->getShortcut()) { - $name .= '|-'.implode('|-', explode('|', $option->getShortcut())).''; + $name .= '|-'.str_replace('|', '|-', $option->getShortcut()).''; } $this->write( diff -r e200cb7efeb3 -r c2387f117808 vendor/symfony/console/Descriptor/XmlDescriptor.php --- a/vendor/symfony/console/Descriptor/XmlDescriptor.php Thu Apr 26 11:26:54 2018 +0100 +++ b/vendor/symfony/console/Descriptor/XmlDescriptor.php Tue Jul 10 15:07:59 2018 +0100 @@ -224,7 +224,7 @@ $pos = strpos($option->getShortcut(), '|'); if (false !== $pos) { $objectXML->setAttribute('shortcut', '-'.substr($option->getShortcut(), 0, $pos)); - $objectXML->setAttribute('shortcuts', '-'.implode('|-', explode('|', $option->getShortcut()))); + $objectXML->setAttribute('shortcuts', '-'.str_replace('|', '|-', $option->getShortcut())); } else { $objectXML->setAttribute('shortcut', $option->getShortcut() ? '-'.$option->getShortcut() : ''); } diff -r e200cb7efeb3 -r c2387f117808 vendor/symfony/console/EventListener/ErrorListener.php --- a/vendor/symfony/console/EventListener/ErrorListener.php Thu Apr 26 11:26:54 2018 +0100 +++ b/vendor/symfony/console/EventListener/ErrorListener.php Tue Jul 10 15:07:59 2018 +0100 @@ -40,10 +40,10 @@ $error = $event->getError(); if (!$inputString = $this->getInputString($event)) { - return $this->logger->error('An error occurred while using the console. Message: "{message}"', array('error' => $error, 'message' => $error->getMessage())); + return $this->logger->error('An error occurred while using the console. Message: "{message}"', array('exception' => $error, 'message' => $error->getMessage())); } - $this->logger->error('Error thrown while running command "{command}". Message: "{message}"', array('error' => $error, 'command' => $inputString, 'message' => $error->getMessage())); + $this->logger->error('Error thrown while running command "{command}". Message: "{message}"', array('exception' => $error, 'command' => $inputString, 'message' => $error->getMessage())); } public function onConsoleTerminate(ConsoleTerminateEvent $event) diff -r e200cb7efeb3 -r c2387f117808 vendor/symfony/console/Helper/QuestionHelper.php --- a/vendor/symfony/console/Helper/QuestionHelper.php Thu Apr 26 11:26:54 2018 +0100 +++ b/vendor/symfony/console/Helper/QuestionHelper.php Tue Jul 10 15:07:59 2018 +0100 @@ -305,7 +305,7 @@ foreach ($autocomplete as $value) { // If typed characters match the beginning chunk of value (e.g. [AcmeDe]moBundle) - if (0 === strpos($value, $ret) && $i !== strlen($value)) { + if (0 === strpos($value, $ret)) { $matches[$numMatches++] = $value; } } diff -r e200cb7efeb3 -r c2387f117808 vendor/symfony/console/Input/InputOption.php --- a/vendor/symfony/console/Input/InputOption.php Thu Apr 26 11:26:54 2018 +0100 +++ b/vendor/symfony/console/Input/InputOption.php Tue Jul 10 15:07:59 2018 +0100 @@ -195,7 +195,7 @@ * * @return bool */ - public function equals(InputOption $option) + public function equals(self $option) { return $option->getName() === $this->getName() && $option->getShortcut() === $this->getShortcut() diff -r e200cb7efeb3 -r c2387f117808 vendor/symfony/console/Output/StreamOutput.php --- a/vendor/symfony/console/Output/StreamOutput.php Thu Apr 26 11:26:54 2018 +0100 +++ b/vendor/symfony/console/Output/StreamOutput.php Tue Jul 10 15:07:59 2018 +0100 @@ -83,31 +83,34 @@ * * Colorization is disabled if not supported by the stream: * - * - the stream is redirected (eg php file.php >log) - * - Windows without VT100 support, Ansicon, ConEmu, Mintty - * - non tty consoles + * This is tricky on Windows, because Cygwin, Msys2 etc emulate pseudo + * terminals via named pipes, so we can only check the environment. + * + * Reference: Composer\XdebugHandler\Process::supportsColor + * https://github.com/composer/xdebug-handler * * @return bool true if the stream supports colorization, false otherwise */ protected function hasColorSupport() { - if (function_exists('stream_isatty') && !@stream_isatty($this->stream)) { - return false; - } if (DIRECTORY_SEPARATOR === '\\') { - if (function_exists('sapi_windows_vt100_support')) { - $vt100Enabled = @sapi_windows_vt100_support($this->stream); - } else { - $vt100Enabled = '10.0.10586' === PHP_WINDOWS_VERSION_MAJOR.'.'.PHP_WINDOWS_VERSION_MINOR.'.'.PHP_WINDOWS_VERSION_BUILD; - } - - return - $vt100Enabled + return (function_exists('sapi_windows_vt100_support') + && @sapi_windows_vt100_support($this->stream)) || false !== getenv('ANSICON') || 'ON' === getenv('ConEmuANSI') || 'xterm' === getenv('TERM'); } - return function_exists('posix_isatty') && @posix_isatty($this->stream); + if (function_exists('stream_isatty')) { + return @stream_isatty($this->stream); + } + + if (function_exists('posix_isatty')) { + return @posix_isatty($this->stream); + } + + $stat = @fstat($this->stream); + // Check if formatted mode is S_IFCHR + return $stat ? 0020000 === ($stat['mode'] & 0170000) : false; } } diff -r e200cb7efeb3 -r c2387f117808 vendor/symfony/console/composer.json --- a/vendor/symfony/console/composer.json Thu Apr 26 11:26:54 2018 +0100 +++ b/vendor/symfony/console/composer.json Tue Jul 10 15:07:59 2018 +0100 @@ -32,7 +32,7 @@ "symfony/event-dispatcher": "", "symfony/lock": "", "symfony/process": "", - "psr/log": "For using the console logger" + "psr/log-implementation": "For using the console logger" }, "conflict": { "symfony/dependency-injection": "<3.4", diff -r e200cb7efeb3 -r c2387f117808 vendor/symfony/css-selector/Node/Specificity.php --- a/vendor/symfony/css-selector/Node/Specificity.php Thu Apr 26 11:26:54 2018 +0100 +++ b/vendor/symfony/css-selector/Node/Specificity.php Tue Jul 10 15:07:59 2018 +0100 @@ -48,7 +48,7 @@ /** * @return self */ - public function plus(Specificity $specificity) + public function plus(self $specificity) { return new self($this->a + $specificity->a, $this->b + $specificity->b, $this->c + $specificity->c); } @@ -69,7 +69,7 @@ * * @return int */ - public function compareTo(Specificity $specificity) + public function compareTo(self $specificity) { if ($this->a !== $specificity->a) { return $this->a > $specificity->a ? 1 : -1; diff -r e200cb7efeb3 -r c2387f117808 vendor/symfony/css-selector/XPath/XPathExpr.php --- a/vendor/symfony/css-selector/XPath/XPathExpr.php Thu Apr 26 11:26:54 2018 +0100 +++ b/vendor/symfony/css-selector/XPath/XPathExpr.php Tue Jul 10 15:07:59 2018 +0100 @@ -53,8 +53,6 @@ } /** - * @param $condition - * * @return $this */ public function addCondition($condition) diff -r e200cb7efeb3 -r c2387f117808 vendor/symfony/debug/Debug.php --- a/vendor/symfony/debug/Debug.php Thu Apr 26 11:26:54 2018 +0100 +++ b/vendor/symfony/debug/Debug.php Tue Jul 10 15:07:59 2018 +0100 @@ -23,10 +23,7 @@ /** * Enables the debug tools. * - * This method registers an error handler and an exception handler. - * - * If the Symfony ClassLoader component is available, a special - * class loader is also registered. + * This method registers an error handler, an exception handler and a special class loader. * * @param int $errorReportingLevel The level of error reporting you want * @param bool $displayErrors Whether to display errors (for development) or just log them (for production) diff -r e200cb7efeb3 -r c2387f117808 vendor/symfony/debug/ErrorHandler.php --- a/vendor/symfony/debug/ErrorHandler.php Thu Apr 26 11:26:54 2018 +0100 +++ b/vendor/symfony/debug/ErrorHandler.php Tue Jul 10 15:07:59 2018 +0100 @@ -383,14 +383,16 @@ public function handleError($type, $message, $file, $line) { // Level is the current error reporting level to manage silent error. + $level = error_reporting(); + $silenced = 0 === ($level & $type); // Strong errors are not authorized to be silenced. - $level = error_reporting() | E_RECOVERABLE_ERROR | E_USER_ERROR | E_DEPRECATED | E_USER_DEPRECATED; + $level |= E_RECOVERABLE_ERROR | E_USER_ERROR | E_DEPRECATED | E_USER_DEPRECATED; $log = $this->loggedErrors & $type; $throw = $this->thrownErrors & $type & $level; $type &= $level | $this->screamedErrors; if (!$type || (!$log && !$throw)) { - return $type && $log; + return !$silenced && $type && $log; } $scope = $this->scopedErrors & $type; @@ -524,7 +526,7 @@ } } - return $type && $log; + return !$silenced && $type && $log; } /** diff -r e200cb7efeb3 -r c2387f117808 vendor/symfony/debug/Exception/ClassNotFoundException.php --- a/vendor/symfony/debug/Exception/ClassNotFoundException.php Thu Apr 26 11:26:54 2018 +0100 +++ b/vendor/symfony/debug/Exception/ClassNotFoundException.php Tue Jul 10 15:07:59 2018 +0100 @@ -26,6 +26,9 @@ $previous->getSeverity(), $previous->getFile(), $previous->getLine(), + null, + true, + null, $previous->getPrevious() ); $this->setTrace($previous->getTrace()); diff -r e200cb7efeb3 -r c2387f117808 vendor/symfony/debug/Exception/FatalErrorException.php --- a/vendor/symfony/debug/Exception/FatalErrorException.php Thu Apr 26 11:26:54 2018 +0100 +++ b/vendor/symfony/debug/Exception/FatalErrorException.php Tue Jul 10 15:07:59 2018 +0100 @@ -18,9 +18,9 @@ */ class FatalErrorException extends \ErrorException { - public function __construct($message, $code, $severity, $filename, $lineno, $traceOffset = null, $traceArgs = true, array $trace = null) + public function __construct($message, $code, $severity, $filename, $lineno, $traceOffset = null, $traceArgs = true, array $trace = null, $previous = null) { - parent::__construct($message, $code, $severity, $filename, $lineno); + parent::__construct($message, $code, $severity, $filename, $lineno, $previous); if (null !== $trace) { if (!$traceArgs) { diff -r e200cb7efeb3 -r c2387f117808 vendor/symfony/debug/Exception/FlattenException.php --- a/vendor/symfony/debug/Exception/FlattenException.php Thu Apr 26 11:26:54 2018 +0100 +++ b/vendor/symfony/debug/Exception/FlattenException.php Tue Jul 10 15:07:59 2018 +0100 @@ -157,7 +157,7 @@ return $this->previous; } - public function setPrevious(FlattenException $previous) + public function setPrevious(self $previous) { $this->previous = $previous; } diff -r e200cb7efeb3 -r c2387f117808 vendor/symfony/debug/Exception/UndefinedFunctionException.php --- a/vendor/symfony/debug/Exception/UndefinedFunctionException.php Thu Apr 26 11:26:54 2018 +0100 +++ b/vendor/symfony/debug/Exception/UndefinedFunctionException.php Tue Jul 10 15:07:59 2018 +0100 @@ -26,6 +26,9 @@ $previous->getSeverity(), $previous->getFile(), $previous->getLine(), + null, + true, + null, $previous->getPrevious() ); $this->setTrace($previous->getTrace()); diff -r e200cb7efeb3 -r c2387f117808 vendor/symfony/debug/Exception/UndefinedMethodException.php --- a/vendor/symfony/debug/Exception/UndefinedMethodException.php Thu Apr 26 11:26:54 2018 +0100 +++ b/vendor/symfony/debug/Exception/UndefinedMethodException.php Tue Jul 10 15:07:59 2018 +0100 @@ -26,6 +26,9 @@ $previous->getSeverity(), $previous->getFile(), $previous->getLine(), + null, + true, + null, $previous->getPrevious() ); $this->setTrace($previous->getTrace()); diff -r e200cb7efeb3 -r c2387f117808 vendor/symfony/debug/ExceptionHandler.php --- a/vendor/symfony/debug/ExceptionHandler.php Thu Apr 26 11:26:54 2018 +0100 +++ b/vendor/symfony/debug/ExceptionHandler.php Tue Jul 10 15:07:59 2018 +0100 @@ -40,7 +40,7 @@ { $this->debug = $debug; $this->charset = $charset ?: ini_get('default_charset') ?: 'UTF-8'; - $this->fileLinkFormat = $fileLinkFormat ?: ini_get('xdebug.file_link_format') ?: get_cfg_var('xdebug.file_link_format'); + $this->fileLinkFormat = $fileLinkFormat; } /** @@ -355,13 +355,29 @@ private function formatPath($path, $line) { $file = $this->escapeHtml(preg_match('#[^/\\\\]*+$#', $path, $file) ? $file[0] : $path); - $fmt = $this->fileLinkFormat; + $fmt = $this->fileLinkFormat ?: ini_get('xdebug.file_link_format') ?: get_cfg_var('xdebug.file_link_format'); - if ($fmt && $link = is_string($fmt) ? strtr($fmt, array('%f' => $path, '%l' => $line)) : $fmt->format($path, $line)) { - return sprintf('in %s (line %d)', $this->escapeHtml($link), $file, $line); + if (!$fmt) { + return sprintf('in %s%s', $this->escapeHtml($path), $file, 0 < $line ? ' line '.$line : ''); } - return sprintf('in %s (line %d)', $this->escapeHtml($path), $file, $line); + if (\is_string($fmt)) { + $i = strpos($f = $fmt, '&', max(strrpos($f, '%f'), strrpos($f, '%l'))) ?: strlen($f); + $fmt = array(substr($f, 0, $i)) + preg_split('/&([^>]++)>/', substr($f, $i), -1, PREG_SPLIT_DELIM_CAPTURE); + + for ($i = 1; isset($fmt[$i]); ++$i) { + if (0 === strpos($path, $k = $fmt[$i++])) { + $path = substr_replace($path, $fmt[$i], 0, strlen($k)); + break; + } + } + + $link = strtr($fmt[0], array('%f' => $path, '%l' => $line)); + } else { + $link = $fmt->format($path, $line); + } + + return sprintf('in %s%s', $this->escapeHtml($link), $file, 0 < $line ? ' line '.$line : ''); } /** diff -r e200cb7efeb3 -r c2387f117808 vendor/symfony/dependency-injection/ChildDefinition.php --- a/vendor/symfony/dependency-injection/ChildDefinition.php Thu Apr 26 11:26:54 2018 +0100 +++ b/vendor/symfony/dependency-injection/ChildDefinition.php Tue Jul 10 15:07:59 2018 +0100 @@ -121,14 +121,6 @@ { throw new BadMethodCallException('A ChildDefinition cannot have instanceof conditionals set on it.'); } - - /** - * @internal - */ - public function setBindings(array $bindings) - { - throw new BadMethodCallException('A ChildDefinition cannot have bindings set on it.'); - } } class_alias(ChildDefinition::class, DefinitionDecorator::class); diff -r e200cb7efeb3 -r c2387f117808 vendor/symfony/dependency-injection/Compiler/AbstractRecursivePass.php --- a/vendor/symfony/dependency-injection/Compiler/AbstractRecursivePass.php Thu Apr 26 11:26:54 2018 +0100 +++ b/vendor/symfony/dependency-injection/Compiler/AbstractRecursivePass.php Tue Jul 10 15:07:59 2018 +0100 @@ -118,8 +118,12 @@ $class = $definition->getClass(); - if (!$r = $this->container->getReflectionClass($class)) { - throw new RuntimeException(sprintf('Invalid service "%s": class "%s" does not exist.', $this->currentId, $class)); + try { + if (!$r = $this->container->getReflectionClass($class)) { + throw new RuntimeException(sprintf('Invalid service "%s": class "%s" does not exist.', $this->currentId, $class)); + } + } catch (\ReflectionException $e) { + throw new RuntimeException(sprintf('Invalid service "%s": %s.', $this->currentId, lcfirst(rtrim($e->getMessage(), '.')))); } if (!$r = $r->getConstructor()) { if ($required) { diff -r e200cb7efeb3 -r c2387f117808 vendor/symfony/dependency-injection/Compiler/AutowirePass.php --- a/vendor/symfony/dependency-injection/Compiler/AutowirePass.php Thu Apr 26 11:26:54 2018 +0100 +++ b/vendor/symfony/dependency-injection/Compiler/AutowirePass.php Tue Jul 10 15:07:59 2018 +0100 @@ -233,7 +233,10 @@ if ($parameter->isOptional()) { continue; } - throw new AutowiringFailedException($this->currentId, sprintf('Cannot autowire service "%s": argument "$%s" of method "%s()" must have a type-hint or be given a value explicitly.', $this->currentId, $parameter->name, $class !== $this->currentId ? $class.'::'.$method : $method)); + $type = ProxyHelper::getTypeHint($reflectionMethod, $parameter, false); + $type = $type ? sprintf('is type-hinted "%s"', $type) : 'has no type-hint'; + + throw new AutowiringFailedException($this->currentId, sprintf('Cannot autowire service "%s": argument "$%s" of method "%s()" %s, you should configure its value explicitly.', $this->currentId, $parameter->name, $class !== $this->currentId ? $class.'::'.$method : $method, $type)); } // specifically pass the default value diff -r e200cb7efeb3 -r c2387f117808 vendor/symfony/dependency-injection/Compiler/CheckExceptionOnInvalidReferenceBehaviorPass.php --- a/vendor/symfony/dependency-injection/Compiler/CheckExceptionOnInvalidReferenceBehaviorPass.php Thu Apr 26 11:26:54 2018 +0100 +++ b/vendor/symfony/dependency-injection/Compiler/CheckExceptionOnInvalidReferenceBehaviorPass.php Tue Jul 10 15:07:59 2018 +0100 @@ -11,7 +11,6 @@ namespace Symfony\Component\DependencyInjection\Compiler; -use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException; use Symfony\Component\DependencyInjection\Exception\ServiceNotFoundException; use Symfony\Component\DependencyInjection\ContainerInterface; use Symfony\Component\DependencyInjection\Reference; @@ -31,9 +30,6 @@ if (ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE === $value->getInvalidBehavior() && !$this->container->has($id = (string) $value)) { throw new ServiceNotFoundException($id, $this->currentId); } - if (ContainerInterface::IGNORE_ON_UNINITIALIZED_REFERENCE === $value->getInvalidBehavior() && $this->container->has($id = (string) $value) && !$this->container->findDefinition($id)->isShared()) { - throw new InvalidArgumentException(sprintf('Invalid ignore-on-uninitialized reference found in service "%s": target service "%s" is not shared.', $this->currentId, $id)); - } return $value; } diff -r e200cb7efeb3 -r c2387f117808 vendor/symfony/dependency-injection/Compiler/InlineServiceDefinitionsPass.php --- a/vendor/symfony/dependency-injection/Compiler/InlineServiceDefinitionsPass.php Thu Apr 26 11:26:54 2018 +0100 +++ b/vendor/symfony/dependency-injection/Compiler/InlineServiceDefinitionsPass.php Tue Jul 10 15:07:59 2018 +0100 @@ -106,11 +106,15 @@ */ private function isInlineableDefinition($id, Definition $definition, ServiceReferenceGraph $graph) { + if ($definition->getErrors() || $definition->isDeprecated() || $definition->isLazy() || $definition->isSynthetic()) { + return false; + } + if (!$definition->isShared()) { return true; } - if ($definition->isDeprecated() || $definition->isPublic() || $definition->isPrivate() || $definition->isLazy()) { + if ($definition->isPublic() || $definition->isPrivate()) { return false; } @@ -138,6 +142,6 @@ return false; } - return true; + return !$ids || $this->container->getDefinition($ids[0])->isShared(); } } diff -r e200cb7efeb3 -r c2387f117808 vendor/symfony/dependency-injection/Compiler/ResolveBindingsPass.php --- a/vendor/symfony/dependency-injection/Compiler/ResolveBindingsPass.php Thu Apr 26 11:26:54 2018 +0100 +++ b/vendor/symfony/dependency-injection/Compiler/ResolveBindingsPass.php Tue Jul 10 15:07:59 2018 +0100 @@ -15,6 +15,7 @@ use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\DependencyInjection\Definition; use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException; +use Symfony\Component\DependencyInjection\Exception\RuntimeException; use Symfony\Component\DependencyInjection\LazyProxy\ProxyHelper; use Symfony\Component\DependencyInjection\TypedReference; use Symfony\Component\DependencyInjection\Reference; @@ -26,6 +27,7 @@ { private $usedBindings = array(); private $unusedBindings = array(); + private $errorMessages = array(); /** * {@inheritdoc} @@ -36,11 +38,19 @@ parent::process($container); foreach ($this->unusedBindings as list($key, $serviceId)) { - throw new InvalidArgumentException(sprintf('Unused binding "%s" in service "%s".', $key, $serviceId)); + $message = sprintf('Unused binding "%s" in service "%s".', $key, $serviceId); + if ($this->errorMessages) { + $message .= sprintf("\nCould be related to%s:", 1 < \count($this->errorMessages) ? ' one of' : ''); + } + foreach ($this->errorMessages as $m) { + $message .= "\n - ".$m; + } + throw new InvalidArgumentException($message); } } finally { $this->usedBindings = array(); $this->unusedBindings = array(); + $this->errorMessages = array(); } } @@ -88,8 +98,15 @@ $calls = $value->getMethodCalls(); - if ($constructor = $this->getConstructor($value, false)) { - $calls[] = array($constructor, $value->getArguments()); + try { + if ($constructor = $this->getConstructor($value, false)) { + $calls[] = array($constructor, $value->getArguments()); + } + } catch (RuntimeException $e) { + $this->errorMessages[] = $e->getMessage(); + $this->container->getDefinition($this->currentId)->addError($e->getMessage()); + + return parent::processValue($value, $isRoot); } foreach ($calls as $i => $call) { diff -r e200cb7efeb3 -r c2387f117808 vendor/symfony/dependency-injection/Compiler/ResolveChildDefinitionsPass.php --- a/vendor/symfony/dependency-injection/Compiler/ResolveChildDefinitionsPass.php Thu Apr 26 11:26:54 2018 +0100 +++ b/vendor/symfony/dependency-injection/Compiler/ResolveChildDefinitionsPass.php Tue Jul 10 15:07:59 2018 +0100 @@ -103,7 +103,7 @@ $def->setAutowired($parentDef->isAutowired()); $def->setChanges($parentDef->getChanges()); - $def->setBindings($parentDef->getBindings()); + $def->setBindings($definition->getBindings() + $parentDef->getBindings()); // overwrite with values specified in the decorator $changes = $definition->getChanges(); diff -r e200cb7efeb3 -r c2387f117808 vendor/symfony/dependency-injection/Compiler/ResolveServiceSubscribersPass.php --- a/vendor/symfony/dependency-injection/Compiler/ResolveServiceSubscribersPass.php Thu Apr 26 11:26:54 2018 +0100 +++ b/vendor/symfony/dependency-injection/Compiler/ResolveServiceSubscribersPass.php Tue Jul 10 15:07:59 2018 +0100 @@ -35,7 +35,12 @@ } $serviceLocator = $this->serviceLocator; - $this->serviceLocator = $value->hasTag('container.service_subscriber.locator') ? $value->getTag('container.service_subscriber.locator')[0]['id'] : null; + $this->serviceLocator = null; + + if ($value->hasTag('container.service_subscriber.locator')) { + $this->serviceLocator = $value->getTag('container.service_subscriber.locator')[0]['id']; + $value->clearTag('container.service_subscriber.locator'); + } try { return parent::processValue($value); diff -r e200cb7efeb3 -r c2387f117808 vendor/symfony/dependency-injection/ContainerBuilder.php --- a/vendor/symfony/dependency-injection/ContainerBuilder.php Thu Apr 26 11:26:54 2018 +0100 +++ b/vendor/symfony/dependency-injection/ContainerBuilder.php Tue Jul 10 15:07:59 2018 +0100 @@ -124,6 +124,20 @@ private $removedIds = array(); private $alreadyLoading = array(); + private static $internalTypes = array( + 'int' => true, + 'float' => true, + 'string' => true, + 'bool' => true, + 'resource' => true, + 'object' => true, + 'array' => true, + 'null' => true, + 'callable' => true, + 'iterable' => true, + 'mixed' => true, + ); + public function __construct(ParameterBagInterface $parameterBag = null) { parent::__construct($parameterBag); @@ -341,6 +355,11 @@ if (!$class = $this->getParameterBag()->resolveValue($class)) { return; } + + if (isset(self::$internalTypes[$class])) { + return null; + } + $resource = null; try { @@ -1389,6 +1408,7 @@ } $envPlaceholders = $bag instanceof EnvPlaceholderParameterBag ? $bag->getEnvPlaceholders() : $this->envPlaceholders; + $completed = false; foreach ($envPlaceholders as $env => $placeholders) { foreach ($placeholders as $placeholder) { if (false !== stripos($value, $placeholder)) { @@ -1399,14 +1419,19 @@ } if ($placeholder === $value) { $value = $resolved; + $completed = true; } else { if (!is_string($resolved) && !is_numeric($resolved)) { - throw new RuntimeException(sprintf('A string value must be composed of strings and/or numbers, but found parameter "env(%s)" of type %s inside string value "%s".', $env, gettype($resolved), $value)); + throw new RuntimeException(sprintf('A string value must be composed of strings and/or numbers, but found parameter "env(%s)" of type %s inside string value "%s".', $env, gettype($resolved), $this->resolveEnvPlaceholders($value))); } $value = str_ireplace($placeholder, $resolved, $value); } $usedEnvs[$env] = $env; $this->envCounters[$env] = isset($this->envCounters[$env]) ? 1 + $this->envCounters[$env] : 1; + + if ($completed) { + break 2; + } } } } @@ -1454,7 +1479,7 @@ */ public function log(CompilerPassInterface $pass, $message) { - $this->getCompiler()->log($pass, $message); + $this->getCompiler()->log($pass, $this->resolveEnvPlaceholders($message)); } /** diff -r e200cb7efeb3 -r c2387f117808 vendor/symfony/dependency-injection/Dumper/PhpDumper.php --- a/vendor/symfony/dependency-injection/Dumper/PhpDumper.php Thu Apr 26 11:26:54 2018 +0100 +++ b/vendor/symfony/dependency-injection/Dumper/PhpDumper.php Tue Jul 10 15:07:59 2018 +0100 @@ -396,6 +396,7 @@ private function generateProxyClasses() { + $alreadyGenerated = array(); $definitions = $this->container->getDefinitions(); $strip = '' === $this->docStar && method_exists('Symfony\Component\HttpKernel\Kernel', 'stripComments'); $proxyDumper = $this->getProxyDumper(); @@ -404,8 +405,12 @@ if (!$proxyDumper->isProxyCandidate($definition)) { continue; } + if (isset($alreadyGenerated[$class = $definition->getClass()])) { + continue; + } + $alreadyGenerated[$class] = true; // register class' reflector for resource tracking - $this->container->getReflectionClass($definition->getClass()); + $this->container->getReflectionClass($class); $proxyCode = "\n".$proxyDumper->getProxyCode($definition); if ($strip) { $proxyCode = "setServiceA(ServiceA $a); - if (isset($inlinedDefinition[$definition]) && $this->hasReference($id, array($def->getArguments(), $def->getFactory()))) { + if (isset($inlinedDefinitions[$definition]) && $this->hasReference($id, array($def->getArguments(), $def->getFactory()))) { throw new ServiceCircularReferenceException($id, array($id)); } @@ -1896,6 +1901,9 @@ if ($this->container->hasDefinition($id) && ($definition = $this->container->getDefinition($id)) && !$definition->isSynthetic()) { if (null !== $reference && ContainerInterface::IGNORE_ON_UNINITIALIZED_REFERENCE === $reference->getInvalidBehavior()) { $code = 'null'; + if (!$definition->isShared()) { + return $code; + } } elseif ($this->isTrivialInstance($definition)) { $code = substr($this->addNewInstance($definition, '', '', $id), 8, -2); if ($definition->isShared()) { diff -r e200cb7efeb3 -r c2387f117808 vendor/symfony/dependency-injection/LazyProxy/ProxyHelper.php --- a/vendor/symfony/dependency-injection/LazyProxy/ProxyHelper.php Thu Apr 26 11:26:54 2018 +0100 +++ b/vendor/symfony/dependency-injection/LazyProxy/ProxyHelper.php Tue Jul 10 15:07:59 2018 +0100 @@ -62,17 +62,4 @@ return $prefix.$parent->name; } } - - private static function export($value) - { - if (!is_array($value)) { - return var_export($value, true); - } - $code = array(); - foreach ($value as $k => $v) { - $code[] = sprintf('%s => %s', var_export($k, true), self::export($v)); - } - - return sprintf('array(%s)', implode(', ', $code)); - } } diff -r e200cb7efeb3 -r c2387f117808 vendor/symfony/dependency-injection/Loader/Configurator/InstanceofConfigurator.php --- a/vendor/symfony/dependency-injection/Loader/Configurator/InstanceofConfigurator.php Thu Apr 26 11:26:54 2018 +0100 +++ b/vendor/symfony/dependency-injection/Loader/Configurator/InstanceofConfigurator.php Tue Jul 10 15:07:59 2018 +0100 @@ -34,7 +34,7 @@ * * @param string $fqcn * - * @return InstanceofConfigurator + * @return self */ final protected function setInstanceof($fqcn) { diff -r e200cb7efeb3 -r c2387f117808 vendor/symfony/dom-crawler/composer.json --- a/vendor/symfony/dom-crawler/composer.json Thu Apr 26 11:26:54 2018 +0100 +++ b/vendor/symfony/dom-crawler/composer.json Tue Jul 10 15:07:59 2018 +0100 @@ -17,6 +17,7 @@ ], "require": { "php": "^5.5.9|>=7.0.8", + "symfony/polyfill-ctype": "~1.8", "symfony/polyfill-mbstring": "~1.0" }, "require-dev": { diff -r e200cb7efeb3 -r c2387f117808 vendor/symfony/finder/SplFileInfo.php --- a/vendor/symfony/finder/SplFileInfo.php Thu Apr 26 11:26:54 2018 +0100 +++ b/vendor/symfony/finder/SplFileInfo.php Tue Jul 10 15:07:59 2018 +0100 @@ -66,12 +66,11 @@ */ public function getContents() { - $level = error_reporting(0); + set_error_handler(function ($type, $msg) use (&$error) { $error = $msg; }); $content = file_get_contents($this->getPathname()); - error_reporting($level); + restore_error_handler(); if (false === $content) { - $error = error_get_last(); - throw new \RuntimeException($error['message']); + throw new \RuntimeException($error); } return $content; diff -r e200cb7efeb3 -r c2387f117808 vendor/symfony/finder/Tests/Iterator/RealIteratorTestCase.php --- a/vendor/symfony/finder/Tests/Iterator/RealIteratorTestCase.php Thu Apr 26 11:26:54 2018 +0100 +++ b/vendor/symfony/finder/Tests/Iterator/RealIteratorTestCase.php Tue Jul 10 15:07:59 2018 +0100 @@ -60,11 +60,20 @@ public static function tearDownAfterClass() { - foreach (array_reverse(self::$files) as $file) { - if (DIRECTORY_SEPARATOR === $file[strlen($file) - 1]) { - @rmdir($file); + $paths = new \RecursiveIteratorIterator( + new \RecursiveDirectoryIterator(self::$tmpDir, \RecursiveDirectoryIterator::SKIP_DOTS), + \RecursiveIteratorIterator::CHILD_FIRST + ); + + foreach ($paths as $path) { + if ($path->isDir()) { + if ($path->isLink()) { + @unlink($path); + } else { + @rmdir($path); + } } else { - @unlink($file); + @unlink($path); } } } diff -r e200cb7efeb3 -r c2387f117808 vendor/symfony/http-foundation/Cookie.php --- a/vendor/symfony/http-foundation/Cookie.php Thu Apr 26 11:26:54 2018 +0100 +++ b/vendor/symfony/http-foundation/Cookie.php Tue Jul 10 15:07:59 2018 +0100 @@ -145,12 +145,12 @@ $str = ($this->isRaw() ? $this->getName() : urlencode($this->getName())).'='; if ('' === (string) $this->getValue()) { - $str .= 'deleted; expires='.gmdate('D, d-M-Y H:i:s T', time() - 31536001).'; max-age=-31536001'; + $str .= 'deleted; expires='.gmdate('D, d-M-Y H:i:s T', time() - 31536001).'; Max-Age=0'; } else { $str .= $this->isRaw() ? $this->getValue() : rawurlencode($this->getValue()); if (0 !== $this->getExpiresTime()) { - $str .= '; expires='.gmdate('D, d-M-Y H:i:s T', $this->getExpiresTime()).'; max-age='.$this->getMaxAge(); + $str .= '; expires='.gmdate('D, d-M-Y H:i:s T', $this->getExpiresTime()).'; Max-Age='.$this->getMaxAge(); } } @@ -224,7 +224,9 @@ */ public function getMaxAge() { - return 0 !== $this->expire ? $this->expire - time() : 0; + $maxAge = $this->expire - time(); + + return 0 >= $maxAge ? 0 : $maxAge; } /** diff -r e200cb7efeb3 -r c2387f117808 vendor/symfony/http-foundation/File/File.php --- a/vendor/symfony/http-foundation/File/File.php Thu Apr 26 11:26:54 2018 +0100 +++ b/vendor/symfony/http-foundation/File/File.php Tue Jul 10 15:07:59 2018 +0100 @@ -93,9 +93,11 @@ { $target = $this->getTargetFile($directory, $name); - if (!@rename($this->getPathname(), $target)) { - $error = error_get_last(); - throw new FileException(sprintf('Could not move the file "%s" to "%s" (%s)', $this->getPathname(), $target, strip_tags($error['message']))); + set_error_handler(function ($type, $msg) use (&$error) { $error = $msg; }); + $renamed = rename($this->getPathname(), $target); + restore_error_handler(); + if (!$renamed) { + throw new FileException(sprintf('Could not move the file "%s" to "%s" (%s)', $this->getPathname(), $target, strip_tags($error))); } @chmod($target, 0666 & ~umask()); diff -r e200cb7efeb3 -r c2387f117808 vendor/symfony/http-foundation/File/MimeType/FileBinaryMimeTypeGuesser.php --- a/vendor/symfony/http-foundation/File/MimeType/FileBinaryMimeTypeGuesser.php Thu Apr 26 11:26:54 2018 +0100 +++ b/vendor/symfony/http-foundation/File/MimeType/FileBinaryMimeTypeGuesser.php Tue Jul 10 15:07:59 2018 +0100 @@ -43,7 +43,21 @@ */ public static function isSupported() { - return '\\' !== DIRECTORY_SEPARATOR && function_exists('passthru') && function_exists('escapeshellarg'); + static $supported = null; + + if (null !== $supported) { + return $supported; + } + + if ('\\' === DIRECTORY_SEPARATOR || !function_exists('passthru') || !function_exists('escapeshellarg')) { + return $supported = false; + } + + ob_start(); + passthru('command -v file', $exitStatus); + $binPath = trim(ob_get_clean()); + + return $supported = 0 === $exitStatus && '' !== $binPath; } /** diff -r e200cb7efeb3 -r c2387f117808 vendor/symfony/http-foundation/File/MimeType/MimeTypeGuesser.php --- a/vendor/symfony/http-foundation/File/MimeType/MimeTypeGuesser.php Thu Apr 26 11:26:54 2018 +0100 +++ b/vendor/symfony/http-foundation/File/MimeType/MimeTypeGuesser.php Tue Jul 10 15:07:59 2018 +0100 @@ -80,13 +80,8 @@ */ private function __construct() { - if (FileBinaryMimeTypeGuesser::isSupported()) { - $this->register(new FileBinaryMimeTypeGuesser()); - } - - if (FileinfoMimeTypeGuesser::isSupported()) { - $this->register(new FileinfoMimeTypeGuesser()); - } + $this->register(new FileBinaryMimeTypeGuesser()); + $this->register(new FileinfoMimeTypeGuesser()); } /** @@ -125,18 +120,14 @@ throw new AccessDeniedException($path); } - if (!$this->guessers) { - $msg = 'Unable to guess the mime type as no guessers are available'; - if (!FileinfoMimeTypeGuesser::isSupported()) { - $msg .= ' (Did you enable the php_fileinfo extension?)'; - } - throw new \LogicException($msg); - } - foreach ($this->guessers as $guesser) { if (null !== $mimeType = $guesser->guess($path)) { return $mimeType; } } + + if (2 === \count($this->guessers) && !FileBinaryMimeTypeGuesser::isSupported() && !FileinfoMimeTypeGuesser::isSupported()) { + throw new \LogicException('Unable to guess the mime type as no guessers are available (Did you enable the php_fileinfo extension?)'); + } } } diff -r e200cb7efeb3 -r c2387f117808 vendor/symfony/http-foundation/File/UploadedFile.php --- a/vendor/symfony/http-foundation/File/UploadedFile.php Thu Apr 26 11:26:54 2018 +0100 +++ b/vendor/symfony/http-foundation/File/UploadedFile.php Tue Jul 10 15:07:59 2018 +0100 @@ -192,9 +192,11 @@ $target = $this->getTargetFile($directory, $name); - if (!@move_uploaded_file($this->getPathname(), $target)) { - $error = error_get_last(); - throw new FileException(sprintf('Could not move the file "%s" to "%s" (%s)', $this->getPathname(), $target, strip_tags($error['message']))); + set_error_handler(function ($type, $msg) use (&$error) { $error = $msg; }); + $moved = move_uploaded_file($this->getPathname(), $target); + restore_error_handler(); + if (!$moved) { + throw new FileException(sprintf('Could not move the file "%s" to "%s" (%s)', $this->getPathname(), $target, strip_tags($error))); } @chmod($target, 0666 & ~umask()); diff -r e200cb7efeb3 -r c2387f117808 vendor/symfony/http-foundation/Request.php --- a/vendor/symfony/http-foundation/Request.php Thu Apr 26 11:26:54 2018 +0100 +++ b/vendor/symfony/http-foundation/Request.php Tue Jul 10 15:07:59 2018 +0100 @@ -641,7 +641,7 @@ public static function setTrustedHosts(array $hostPatterns) { self::$trustedHostPatterns = array_map(function ($hostPattern) { - return sprintf('#%s#i', $hostPattern); + return sprintf('{%s}i', $hostPattern); }, $hostPatterns); // we need to reset trusted hosts on trusted host patterns change self::$trustedHosts = array(); @@ -1378,7 +1378,7 @@ * * @param string $format The format * - * @return string The associated mime type (null if not found) + * @return string|null The associated mime type (null if not found) */ public function getMimeType($format) { diff -r e200cb7efeb3 -r c2387f117808 vendor/symfony/http-foundation/Response.php --- a/vendor/symfony/http-foundation/Response.php Thu Apr 26 11:26:54 2018 +0100 +++ b/vendor/symfony/http-foundation/Response.php Tue Jul 10 15:07:59 2018 +0100 @@ -21,6 +21,7 @@ const HTTP_CONTINUE = 100; const HTTP_SWITCHING_PROTOCOLS = 101; const HTTP_PROCESSING = 102; // RFC2518 + const HTTP_EARLY_HINTS = 103; // RFC8297 const HTTP_OK = 200; const HTTP_CREATED = 201; const HTTP_ACCEPTED = 202; @@ -327,7 +328,7 @@ } // headers - foreach ($this->headers->allPreserveCaseWithoutCookies() as $name => $values) { + foreach ($this->headers->allPreserveCase() as $name => $values) { foreach ($values as $value) { header($name.': '.$value, false, $this->statusCode); } @@ -336,15 +337,6 @@ // status header(sprintf('HTTP/%s %s %s', $this->version, $this->statusCode, $this->statusText), true, $this->statusCode); - // cookies - foreach ($this->headers->getCookies() as $cookie) { - if ($cookie->isRaw()) { - setrawcookie($cookie->getName(), $cookie->getValue(), $cookie->getExpiresTime(), $cookie->getPath(), $cookie->getDomain(), $cookie->isSecure(), $cookie->isHttpOnly()); - } else { - setcookie($cookie->getName(), $cookie->getValue(), $cookie->getExpiresTime(), $cookie->getPath(), $cookie->getDomain(), $cookie->isSecure(), $cookie->isHttpOnly()); - } - } - return $this; } @@ -519,13 +511,19 @@ } /** - * Returns true if the response is worth caching under any circumstance. + * Returns true if the response may safely be kept in a shared (surrogate) cache. * * Responses marked "private" with an explicit Cache-Control directive are * considered uncacheable. * * Responses with neither a freshness lifetime (Expires, max-age) nor cache - * validator (Last-Modified, ETag) are considered uncacheable. + * validator (Last-Modified, ETag) are considered uncacheable because there is + * no way to tell when or how to remove them from the cache. + * + * Note that RFC 7231 and RFC 7234 possibly allow for a more permissive implementation, + * for example "status codes that are defined as cacheable by default [...] + * can be reused by a cache with heuristic expiration unless otherwise indicated" + * (https://tools.ietf.org/html/rfc7231#section-6.1) * * @return bool true if the response is worth caching, false otherwise * diff -r e200cb7efeb3 -r c2387f117808 vendor/symfony/http-foundation/ResponseHeaderBag.php --- a/vendor/symfony/http-foundation/ResponseHeaderBag.php Thu Apr 26 11:26:54 2018 +0100 +++ b/vendor/symfony/http-foundation/ResponseHeaderBag.php Tue Jul 10 15:07:59 2018 +0100 @@ -210,7 +210,7 @@ * * @param string $format * - * @return array + * @return Cookie[] * * @throws \InvalidArgumentException When the $format is invalid */ diff -r e200cb7efeb3 -r c2387f117808 vendor/symfony/http-foundation/Session/Session.php --- a/vendor/symfony/http-foundation/Session/Session.php Thu Apr 26 11:26:54 2018 +0100 +++ b/vendor/symfony/http-foundation/Session/Session.php Tue Jul 10 15:07:59 2018 +0100 @@ -29,7 +29,7 @@ private $flashName; private $attributeName; private $data = array(); - private $hasBeenStarted; + private $usageIndex = 0; /** * @param SessionStorageInterface $storage A SessionStorageInterface instance @@ -54,6 +54,8 @@ */ public function start() { + ++$this->usageIndex; + return $this->storage->start(); } @@ -142,13 +144,13 @@ } /** - * @return bool + * @return int * * @internal */ - public function hasBeenStarted() + public function getUsageIndex() { - return $this->hasBeenStarted; + return $this->usageIndex; } /** @@ -158,6 +160,7 @@ */ public function isEmpty() { + ++$this->usageIndex; foreach ($this->data as &$data) { if (!empty($data)) { return false; @@ -182,6 +185,8 @@ */ public function migrate($destroy = false, $lifetime = null) { + ++$this->usageIndex; + return $this->storage->regenerate($destroy, $lifetime); } @@ -190,6 +195,8 @@ */ public function save() { + ++$this->usageIndex; + $this->storage->save(); } @@ -230,6 +237,8 @@ */ public function getMetadataBag() { + ++$this->usageIndex; + return $this->storage->getMetadataBag(); } @@ -238,7 +247,7 @@ */ public function registerBag(SessionBagInterface $bag) { - $this->storage->registerBag(new SessionBagProxy($bag, $this->data, $this->hasBeenStarted)); + $this->storage->registerBag(new SessionBagProxy($bag, $this->data, $this->usageIndex)); } /** diff -r e200cb7efeb3 -r c2387f117808 vendor/symfony/http-foundation/Session/SessionBagProxy.php --- a/vendor/symfony/http-foundation/Session/SessionBagProxy.php Thu Apr 26 11:26:54 2018 +0100 +++ b/vendor/symfony/http-foundation/Session/SessionBagProxy.php Tue Jul 10 15:07:59 2018 +0100 @@ -20,13 +20,13 @@ { private $bag; private $data; - private $hasBeenStarted; + private $usageIndex; - public function __construct(SessionBagInterface $bag, array &$data, &$hasBeenStarted) + public function __construct(SessionBagInterface $bag, array &$data, &$usageIndex) { $this->bag = $bag; $this->data = &$data; - $this->hasBeenStarted = &$hasBeenStarted; + $this->usageIndex = &$usageIndex; } /** @@ -34,6 +34,8 @@ */ public function getBag() { + ++$this->usageIndex; + return $this->bag; } @@ -42,6 +44,8 @@ */ public function isEmpty() { + ++$this->usageIndex; + return empty($this->data[$this->bag->getStorageKey()]); } @@ -58,7 +62,7 @@ */ public function initialize(array &$array) { - $this->hasBeenStarted = true; + ++$this->usageIndex; $this->data[$this->bag->getStorageKey()] = &$array; $this->bag->initialize($array); @@ -77,6 +81,8 @@ */ public function clear() { + ++$this->usageIndex; + return $this->bag->clear(); } } diff -r e200cb7efeb3 -r c2387f117808 vendor/symfony/http-foundation/Session/Storage/Handler/PdoSessionHandler.php --- a/vendor/symfony/http-foundation/Session/Storage/Handler/PdoSessionHandler.php Thu Apr 26 11:26:54 2018 +0100 +++ b/vendor/symfony/http-foundation/Session/Storage/Handler/PdoSessionHandler.php Tue Jul 10 15:07:59 2018 +0100 @@ -616,6 +616,7 @@ $selectSql = $this->getSelectSql(); $selectStmt = $this->pdo->prepare($selectSql); $selectStmt->bindParam(':id', $sessionId, \PDO::PARAM_STR); + $insertStmt = null; do { $selectStmt->execute(); @@ -631,6 +632,11 @@ return is_resource($sessionRows[0][0]) ? stream_get_contents($sessionRows[0][0]) : $sessionRows[0][0]; } + if (null !== $insertStmt) { + $this->rollback(); + throw new \RuntimeException('Failed to read session: INSERT reported a duplicate id but next SELECT did not return any data.'); + } + if (!ini_get('session.use_strict_mode') && self::LOCK_TRANSACTIONAL === $this->lockMode && 'sqlite' !== $this->driver) { // In strict mode, session fixation is not possible: new sessions always start with a unique // random id, so that concurrency is not possible and this code path can be skipped. @@ -676,14 +682,16 @@ { switch ($this->driver) { case 'mysql': + // MySQL 5.7.5 and later enforces a maximum length on lock names of 64 characters. Previously, no limit was enforced. + $lockId = \substr($sessionId, 0, 64); // should we handle the return value? 0 on timeout, null on error // we use a timeout of 50 seconds which is also the default for innodb_lock_wait_timeout $stmt = $this->pdo->prepare('SELECT GET_LOCK(:key, 50)'); - $stmt->bindValue(':key', $sessionId, \PDO::PARAM_STR); + $stmt->bindValue(':key', $lockId, \PDO::PARAM_STR); $stmt->execute(); $releaseStmt = $this->pdo->prepare('DO RELEASE_LOCK(:key)'); - $releaseStmt->bindValue(':key', $sessionId, \PDO::PARAM_STR); + $releaseStmt->bindValue(':key', $lockId, \PDO::PARAM_STR); return $releaseStmt; case 'pgsql': diff -r e200cb7efeb3 -r c2387f117808 vendor/symfony/http-foundation/Session/Storage/NativeSessionStorage.php --- a/vendor/symfony/http-foundation/Session/Storage/NativeSessionStorage.php Thu Apr 26 11:26:54 2018 +0100 +++ b/vendor/symfony/http-foundation/Session/Storage/NativeSessionStorage.php Tue Jul 10 15:07:59 2018 +0100 @@ -349,7 +349,7 @@ } $validOptions = array_flip(array( - 'cache_limiter', 'cache_expire', 'cookie_domain', 'cookie_httponly', + 'cache_expire', 'cache_limiter', 'cookie_domain', 'cookie_httponly', 'cookie_lifetime', 'cookie_path', 'cookie_secure', 'entropy_file', 'entropy_length', 'gc_divisor', 'gc_maxlifetime', 'gc_probability', 'hash_bits_per_character', @@ -357,13 +357,13 @@ 'serialize_handler', 'use_strict_mode', 'use_cookies', 'use_only_cookies', 'use_trans_sid', 'upload_progress.enabled', 'upload_progress.cleanup', 'upload_progress.prefix', 'upload_progress.name', - 'upload_progress.freq', 'upload_progress.min-freq', 'url_rewriter.tags', + 'upload_progress.freq', 'upload_progress.min_freq', 'url_rewriter.tags', 'sid_length', 'sid_bits_per_character', 'trans_sid_hosts', 'trans_sid_tags', )); foreach ($options as $key => $value) { if (isset($validOptions[$key])) { - ini_set('session.'.$key, $value); + ini_set('url_rewriter.tags' !== $key ? 'session.'.$key : $key, $value); } } } diff -r e200cb7efeb3 -r c2387f117808 vendor/symfony/http-kernel/Controller/ArgumentResolver/ServiceValueResolver.php --- a/vendor/symfony/http-kernel/Controller/ArgumentResolver/ServiceValueResolver.php Thu Apr 26 11:26:54 2018 +0100 +++ b/vendor/symfony/http-kernel/Controller/ArgumentResolver/ServiceValueResolver.php Tue Jul 10 15:07:59 2018 +0100 @@ -39,9 +39,15 @@ if (\is_array($controller) && \is_callable($controller, true) && \is_string($controller[0])) { $controller = $controller[0].'::'.$controller[1]; + } elseif (!\is_string($controller) || '' === $controller) { + return false; } - return \is_string($controller) && $this->container->has($controller) && $this->container->get($controller)->has($argument->getName()); + if ('\\' === $controller[0]) { + $controller = ltrim($controller, '\\'); + } + + return $this->container->has($controller) && $this->container->get($controller)->has($argument->getName()); } /** @@ -53,6 +59,10 @@ $controller = $controller[0].'::'.$controller[1]; } + if ('\\' === $controller[0]) { + $controller = ltrim($controller, '\\'); + } + yield $this->container->get($controller)->get($argument->getName()); } } diff -r e200cb7efeb3 -r c2387f117808 vendor/symfony/http-kernel/ControllerMetadata/ArgumentMetadataFactory.php --- a/vendor/symfony/http-kernel/ControllerMetadata/ArgumentMetadataFactory.php Thu Apr 26 11:26:54 2018 +0100 +++ b/vendor/symfony/http-kernel/ControllerMetadata/ArgumentMetadataFactory.php Tue Jul 10 15:07:59 2018 +0100 @@ -58,7 +58,7 @@ } foreach ($reflection->getParameters() as $param) { - $arguments[] = new ArgumentMetadata($param->getName(), $this->getType($param), $this->isVariadic($param), $this->hasDefaultValue($param), $this->getDefaultValue($param), $param->allowsNull()); + $arguments[] = new ArgumentMetadata($param->getName(), $this->getType($param, $reflection), $this->isVariadic($param), $this->hasDefaultValue($param), $this->getDefaultValue($param), $param->allowsNull()); } return $arguments; @@ -107,23 +107,35 @@ * * @return null|string */ - private function getType(\ReflectionParameter $parameter) + private function getType(\ReflectionParameter $parameter, \ReflectionFunctionAbstract $function) { if ($this->supportsParameterType) { if (!$type = $parameter->getType()) { return; } - $typeName = $type instanceof \ReflectionNamedType ? $type->getName() : $type->__toString(); - if ('array' === $typeName && !$type->isBuiltin()) { + $name = $type instanceof \ReflectionNamedType ? $type->getName() : $type->__toString(); + if ('array' === $name && !$type->isBuiltin()) { // Special case for HHVM with variadics return; } + } elseif (preg_match('/^(?:[^ ]++ ){4}([a-zA-Z_\x7F-\xFF][^ ]++)/', $parameter, $name)) { + $name = $name[1]; + } else { + return; + } + $lcName = strtolower($name); - return $typeName; + if ('self' !== $lcName && 'parent' !== $lcName) { + return $name; } - - if (preg_match('/^(?:[^ ]++ ){4}([a-zA-Z_\x7F-\xFF][^ ]++)/', $parameter, $info)) { - return $info[1]; + if (!$function instanceof \ReflectionMethod) { + return; + } + if ('self' === $lcName) { + return $function->getDeclaringClass()->name; + } + if ($parent = $function->getDeclaringClass()->getParentClass()) { + return $parent->name; } } } diff -r e200cb7efeb3 -r c2387f117808 vendor/symfony/http-kernel/DataCollector/DumpDataCollector.php --- a/vendor/symfony/http-kernel/DataCollector/DumpDataCollector.php Thu Apr 26 11:26:54 2018 +0100 +++ b/vendor/symfony/http-kernel/DataCollector/DumpDataCollector.php Tue Jul 10 15:07:59 2018 +0100 @@ -171,7 +171,7 @@ } $this->data = array(); $this->dataCount = 0; - $this->isCollected = false; + $this->isCollected = true; $this->clonesCount = 0; $this->clonesIndex = 0; } diff -r e200cb7efeb3 -r c2387f117808 vendor/symfony/http-kernel/EventListener/AbstractSessionListener.php --- a/vendor/symfony/http-kernel/EventListener/AbstractSessionListener.php Thu Apr 26 11:26:54 2018 +0100 +++ b/vendor/symfony/http-kernel/EventListener/AbstractSessionListener.php Tue Jul 10 15:07:59 2018 +0100 @@ -14,6 +14,7 @@ use Symfony\Component\HttpFoundation\Session\Session; use Symfony\Component\HttpFoundation\Session\SessionInterface; use Symfony\Component\HttpKernel\Event\FilterResponseEvent; +use Symfony\Component\HttpKernel\Event\FinishRequestEvent; use Symfony\Component\HttpKernel\Event\GetResponseEvent; use Symfony\Component\HttpKernel\KernelEvents; use Symfony\Component\EventDispatcher\EventSubscriberInterface; @@ -25,6 +26,8 @@ */ abstract class AbstractSessionListener implements EventSubscriberInterface { + private $sessionUsageStack = array(); + public function onKernelRequest(GetResponseEvent $event) { if (!$event->isMasterRequest()) { @@ -33,6 +36,7 @@ $request = $event->getRequest(); $session = $this->getSession(); + $this->sessionUsageStack[] = $session instanceof Session ? $session->getUsageIndex() : null; if (null === $session || $request->hasSession()) { return; } @@ -50,7 +54,7 @@ return; } - if ($session->isStarted() || ($session instanceof Session && $session->hasBeenStarted())) { + if ($session instanceof Session ? $session->getUsageIndex() !== end($this->sessionUsageStack) : $session->isStarted()) { $event->getResponse() ->setPrivate() ->setMaxAge(0) @@ -58,12 +62,23 @@ } } + /** + * @internal + */ + public function onFinishRequest(FinishRequestEvent $event) + { + if ($event->isMasterRequest()) { + array_pop($this->sessionUsageStack); + } + } + public static function getSubscribedEvents() { return array( KernelEvents::REQUEST => array('onKernelRequest', 128), // low priority to come after regular response listeners, same as SaveSessionListener KernelEvents::RESPONSE => array('onKernelResponse', -1000), + KernelEvents::FINISH_REQUEST => array('onFinishRequest'), ); } diff -r e200cb7efeb3 -r c2387f117808 vendor/symfony/http-kernel/EventListener/AbstractTestSessionListener.php --- a/vendor/symfony/http-kernel/EventListener/AbstractTestSessionListener.php Thu Apr 26 11:26:54 2018 +0100 +++ b/vendor/symfony/http-kernel/EventListener/AbstractTestSessionListener.php Tue Jul 10 15:07:59 2018 +0100 @@ -69,7 +69,7 @@ $session->save(); } - if ($session instanceof Session ? !$session->isEmpty() || $session->getId() !== $this->sessionId : $wasStarted) { + if ($session instanceof Session ? !$session->isEmpty() || (null !== $this->sessionId && $session->getId() !== $this->sessionId) : $wasStarted) { $params = session_get_cookie_params(); $event->getResponse()->headers->setCookie(new Cookie($session->getName(), $session->getId(), 0 === $params['lifetime'] ? 0 : time() + $params['lifetime'], $params['path'], $params['domain'], $params['secure'], $params['httponly'])); $this->sessionId = $session->getId(); diff -r e200cb7efeb3 -r c2387f117808 vendor/symfony/http-kernel/EventListener/ExceptionListener.php --- a/vendor/symfony/http-kernel/EventListener/ExceptionListener.php Thu Apr 26 11:26:54 2018 +0100 +++ b/vendor/symfony/http-kernel/EventListener/ExceptionListener.php Tue Jul 10 15:07:59 2018 +0100 @@ -64,7 +64,7 @@ } } - $prev = new \ReflectionProperty('Exception', 'previous'); + $prev = new \ReflectionProperty($wrapper instanceof \Exception ? \Exception::class : \Error::class, 'previous'); $prev->setAccessible(true); $prev->setValue($wrapper, $exception); diff -r e200cb7efeb3 -r c2387f117808 vendor/symfony/http-kernel/EventListener/RouterListener.php --- a/vendor/symfony/http-kernel/EventListener/RouterListener.php Thu Apr 26 11:26:54 2018 +0100 +++ b/vendor/symfony/http-kernel/EventListener/RouterListener.php Tue Jul 10 15:07:59 2018 +0100 @@ -14,6 +14,7 @@ use Psr\Log\LoggerInterface; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpKernel\Event\GetResponseEvent; +use Symfony\Component\HttpKernel\Event\GetResponseForExceptionEvent; use Symfony\Component\HttpKernel\Event\FinishRequestEvent; use Symfony\Component\HttpKernel\Kernel; use Symfony\Component\HttpKernel\KernelEvents; @@ -129,12 +130,6 @@ unset($parameters['_route'], $parameters['_controller']); $request->attributes->set('_route_params', $parameters); } catch (ResourceNotFoundException $e) { - if ($this->debug && $e instanceof NoConfigurationException) { - $event->setResponse($this->createWelcomeResponse()); - - return; - } - $message = sprintf('No route found for "%s %s"', $request->getMethod(), $request->getPathInfo()); if ($referer = $request->headers->get('referer')) { @@ -149,11 +144,23 @@ } } + public function onKernelException(GetResponseForExceptionEvent $event) + { + if (!$this->debug || !($e = $event->getException()) instanceof NotFoundHttpException) { + return; + } + + if ($e->getPrevious() instanceof NoConfigurationException) { + $event->setResponse($this->createWelcomeResponse()); + } + } + public static function getSubscribedEvents() { return array( KernelEvents::REQUEST => array(array('onKernelRequest', 32)), KernelEvents::FINISH_REQUEST => array(array('onKernelFinishRequest', 0)), + KernelEvents::EXCEPTION => array('onKernelException', -64), ); } diff -r e200cb7efeb3 -r c2387f117808 vendor/symfony/http-kernel/Fragment/InlineFragmentRenderer.php --- a/vendor/symfony/http-kernel/Fragment/InlineFragmentRenderer.php Thu Apr 26 11:26:54 2018 +0100 +++ b/vendor/symfony/http-kernel/Fragment/InlineFragmentRenderer.php Tue Jul 10 15:07:59 2018 +0100 @@ -126,7 +126,9 @@ // Do nothing } - $server['REMOTE_ADDR'] = '127.0.0.1'; + $trustedProxies = Request::getTrustedProxies(); + $server['REMOTE_ADDR'] = $trustedProxies ? reset($trustedProxies) : '127.0.0.1'; + unset($server['HTTP_IF_MODIFIED_SINCE']); unset($server['HTTP_IF_NONE_MATCH']); diff -r e200cb7efeb3 -r c2387f117808 vendor/symfony/http-kernel/HttpCache/HttpCache.php --- a/vendor/symfony/http-kernel/HttpCache/HttpCache.php Thu Apr 26 11:26:54 2018 +0100 +++ b/vendor/symfony/http-kernel/HttpCache/HttpCache.php Tue Jul 10 15:07:59 2018 +0100 @@ -165,7 +165,11 @@ // FIXME: catch exceptions and implement a 500 error page here? -> in Varnish, there is a built-in error page mechanism if (HttpKernelInterface::MASTER_REQUEST === $type) { $this->traces = array(); - $this->request = $request; + // Keep a clone of the original request for surrogates so they can access it. + // We must clone here to get a separate instance because the application will modify the request during + // the application flow (we know it always does because we do ourselves by setting REMOTE_ADDR to 127.0.0.1 + // and adding the X-Forwarded-For header, see HttpCache::forward()). + $this->request = clone $request; if (null !== $this->surrogate) { $this->surrogateCacheStrategy = $this->surrogate->createCacheStrategy(); } diff -r e200cb7efeb3 -r c2387f117808 vendor/symfony/http-kernel/HttpCache/ResponseCacheStrategy.php --- a/vendor/symfony/http-kernel/HttpCache/ResponseCacheStrategy.php Thu Apr 26 11:26:54 2018 +0100 +++ b/vendor/symfony/http-kernel/HttpCache/ResponseCacheStrategy.php Tue Jul 10 15:07:59 2018 +0100 @@ -72,7 +72,7 @@ $response->setLastModified(null); } - if (!$response->isFresh()) { + if (!$response->isFresh() || !$response->isCacheable()) { $this->cacheable = false; } diff -r e200cb7efeb3 -r c2387f117808 vendor/symfony/http-kernel/Kernel.php --- a/vendor/symfony/http-kernel/Kernel.php Thu Apr 26 11:26:54 2018 +0100 +++ b/vendor/symfony/http-kernel/Kernel.php Tue Jul 10 15:07:59 2018 +0100 @@ -67,11 +67,11 @@ private $requestStackSize = 0; private $resetServices = false; - const VERSION = '3.4.8'; - const VERSION_ID = 30408; + const VERSION = '3.4.12'; + const VERSION_ID = 30412; const MAJOR_VERSION = 3; const MINOR_VERSION = 4; - const RELEASE_VERSION = 8; + const RELEASE_VERSION = 12; const EXTRA_VERSION = ''; const END_OF_MAINTENANCE = '11/2020'; @@ -87,18 +87,10 @@ $this->debug = (bool) $debug; $this->rootDir = $this->getRootDir(); $this->name = $this->getName(); - - if ($this->debug) { - $this->startTime = microtime(true); - } } public function __clone() { - if ($this->debug) { - $this->startTime = microtime(true); - } - $this->booted = false; $this->container = null; $this->requestStackSize = 0; @@ -116,10 +108,16 @@ $this->container->get('services_resetter')->reset(); } $this->resetServices = false; + if ($this->debug) { + $this->startTime = microtime(true); + } } return; } + if ($this->debug) { + $this->startTime = microtime(true); + } if ($this->debug && !isset($_ENV['SHELL_VERBOSITY']) && !isset($_SERVER['SHELL_VERBOSITY'])) { putenv('SHELL_VERBOSITY=3'); $_ENV['SHELL_VERBOSITY'] = 3; @@ -587,7 +585,7 @@ $errorLevel = error_reporting(\E_ALL ^ \E_WARNING); $fresh = $oldContainer = false; try { - if (\is_object($this->container = include $cache->getPath())) { + if (file_exists($cache->getPath()) && \is_object($this->container = include $cache->getPath())) { $this->container->set('kernel', $this); $oldContainer = $this->container; $fresh = true; @@ -650,7 +648,7 @@ } } - if (null === $oldContainer) { + if (null === $oldContainer && file_exists($cache->getPath())) { $errorLevel = error_reporting(\E_ALL ^ \E_WARNING); try { $oldContainer = include $cache->getPath(); @@ -670,9 +668,11 @@ // Because concurrent requests might still be using them, // old container files are not removed immediately, // but on a next dump of the container. + static $legacyContainers = array(); $oldContainerDir = dirname($oldContainer->getFileName()); - foreach (glob(dirname($oldContainerDir).'/*.legacy') as $legacyContainer) { - if ($oldContainerDir.'.legacy' !== $legacyContainer && @unlink($legacyContainer)) { + $legacyContainers[$oldContainerDir.'.legacy'] = true; + foreach (glob(dirname($oldContainerDir).DIRECTORY_SEPARATOR.'*.legacy') as $legacyContainer) { + if (!isset($legacyContainers[$legacyContainer]) && @unlink($legacyContainer)) { (new Filesystem())->remove(substr($legacyContainer, 0, -7)); } } diff -r e200cb7efeb3 -r c2387f117808 vendor/symfony/http-kernel/Profiler/Profiler.php --- a/vendor/symfony/http-kernel/Profiler/Profiler.php Thu Apr 26 11:26:54 2018 +0100 +++ b/vendor/symfony/http-kernel/Profiler/Profiler.php Tue Jul 10 15:07:59 2018 +0100 @@ -37,7 +37,7 @@ private $enabled = true; /** - * @param bool $enable The initial enabled state + * @param bool $enable The initial enabled state */ public function __construct(ProfilerStorageInterface $storage, LoggerInterface $logger = null, $enable = true) { diff -r e200cb7efeb3 -r c2387f117808 vendor/symfony/http-kernel/composer.json --- a/vendor/symfony/http-kernel/composer.json Thu Apr 26 11:26:54 2018 +0100 +++ b/vendor/symfony/http-kernel/composer.json Tue Jul 10 15:07:59 2018 +0100 @@ -18,8 +18,9 @@ "require": { "php": "^5.5.9|>=7.0.8", "symfony/event-dispatcher": "~2.8|~3.0|~4.0", - "symfony/http-foundation": "^3.4.4|^4.0.4", + "symfony/http-foundation": "~3.4.12|~4.0.12|^4.1.1", "symfony/debug": "~2.8|~3.0|~4.0", + "symfony/polyfill-ctype": "~1.8", "psr/log": "~1.0" }, "require-dev": { diff -r e200cb7efeb3 -r c2387f117808 vendor/symfony/phpunit-bridge/DeprecationErrorHandler.php --- a/vendor/symfony/phpunit-bridge/DeprecationErrorHandler.php Thu Apr 26 11:26:54 2018 +0100 +++ b/vendor/symfony/phpunit-bridge/DeprecationErrorHandler.php Tue Jul 10 15:07:59 2018 +0100 @@ -297,17 +297,38 @@ }); } + /** + * Returns true if STDOUT is defined and supports colorization. + * + * Reference: Composer\XdebugHandler\Process::supportsColor + * https://github.com/composer/xdebug-handler + * + * @return bool + */ private static function hasColorSupport() { - if ('\\' === DIRECTORY_SEPARATOR) { - return - defined('STDOUT') && function_exists('sapi_windows_vt100_support') && sapi_windows_vt100_support(STDOUT) - || '10.0.10586' === PHP_WINDOWS_VERSION_MAJOR.'.'.PHP_WINDOWS_VERSION_MINOR.'.'.PHP_WINDOWS_VERSION_BUILD + if (!defined('STDOUT')) { + return false; + } + + if (DIRECTORY_SEPARATOR === '\\') { + return (function_exists('sapi_windows_vt100_support') + && sapi_windows_vt100_support(STDOUT)) || false !== getenv('ANSICON') || 'ON' === getenv('ConEmuANSI') || 'xterm' === getenv('TERM'); } - return defined('STDOUT') && function_exists('posix_isatty') && @posix_isatty(STDOUT); + if (function_exists('stream_isatty')) { + return stream_isatty(STDOUT); + } + + if (function_exists('posix_isatty')) { + return posix_isatty(STDOUT); + } + + $stat = fstat(STDOUT); + // Check if formatted mode is S_IFCHR + return $stat ? 0020000 === ($stat['mode'] & 0170000) : false; } } diff -r e200cb7efeb3 -r c2387f117808 vendor/symfony/phpunit-bridge/Legacy/Command.php --- a/vendor/symfony/phpunit-bridge/Legacy/Command.php Thu Apr 26 11:26:54 2018 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,28 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Bridge\PhpUnit\Legacy; - -/** - * {@inheritdoc} - * - * @internal - */ -class Command extends \PHPUnit_TextUI_Command -{ - /** - * {@inheritdoc} - */ - protected function createRunner() - { - return new TestRunner($this->arguments['loader']); - } -} diff -r e200cb7efeb3 -r c2387f117808 vendor/symfony/phpunit-bridge/Legacy/CommandForV5.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vendor/symfony/phpunit-bridge/Legacy/CommandForV5.php Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,28 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bridge\PhpUnit\Legacy; + +/** + * {@inheritdoc} + * + * @internal + */ +class CommandForV5 extends \PHPUnit_TextUI_Command +{ + /** + * {@inheritdoc} + */ + protected function createRunner() + { + return new TestRunnerForV5($this->arguments['loader']); + } +} diff -r e200cb7efeb3 -r c2387f117808 vendor/symfony/phpunit-bridge/Legacy/CommandForV6.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vendor/symfony/phpunit-bridge/Legacy/CommandForV6.php Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,32 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bridge\PhpUnit\Legacy; + +use PHPUnit\TextUI\Command as BaseCommand; +use PHPUnit\TextUI\TestRunner as BaseRunner; +use Symfony\Bridge\PhpUnit\TextUI\TestRunner; + +/** + * {@inheritdoc} + * + * @internal + */ +class CommandForV6 extends BaseCommand +{ + /** + * {@inheritdoc} + */ + protected function createRunner(): BaseRunner + { + return new TestRunner($this->arguments['loader']); + } +} diff -r e200cb7efeb3 -r c2387f117808 vendor/symfony/phpunit-bridge/Legacy/CoverageListenerTrait.php --- a/vendor/symfony/phpunit-bridge/Legacy/CoverageListenerTrait.php Thu Apr 26 11:26:54 2018 +0100 +++ b/vendor/symfony/phpunit-bridge/Legacy/CoverageListenerTrait.php Tue Jul 10 15:07:59 2018 +0100 @@ -11,7 +11,6 @@ namespace Symfony\Bridge\PhpUnit\Legacy; -use PHPUnit\Framework\Test; use PHPUnit\Framework\TestCase; use PHPUnit\Framework\Warning; diff -r e200cb7efeb3 -r c2387f117808 vendor/symfony/phpunit-bridge/Legacy/TestRunner.php --- a/vendor/symfony/phpunit-bridge/Legacy/TestRunner.php Thu Apr 26 11:26:54 2018 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,48 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Bridge\PhpUnit\Legacy; - -/** - * {@inheritdoc} - * - * @internal - */ -class TestRunner extends \PHPUnit_TextUI_TestRunner -{ - /** - * {@inheritdoc} - */ - protected function handleConfiguration(array &$arguments) - { - $listener = new SymfonyTestsListenerForV5(); - - $result = parent::handleConfiguration($arguments); - - $arguments['listeners'] = isset($arguments['listeners']) ? $arguments['listeners'] : array(); - - $registeredLocally = false; - - foreach ($arguments['listeners'] as $registeredListener) { - if ($registeredListener instanceof SymfonyTestsListenerForV5) { - $registeredListener->globalListenerDisabled(); - $registeredLocally = true; - break; - } - } - - if (!$registeredLocally) { - $arguments['listeners'][] = $listener; - } - - return $result; - } -} diff -r e200cb7efeb3 -r c2387f117808 vendor/symfony/phpunit-bridge/Legacy/TestRunnerForV5.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vendor/symfony/phpunit-bridge/Legacy/TestRunnerForV5.php Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,48 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bridge\PhpUnit\Legacy; + +/** + * {@inheritdoc} + * + * @internal + */ +class TestRunnerForV5 extends \PHPUnit_TextUI_TestRunner +{ + /** + * {@inheritdoc} + */ + protected function handleConfiguration(array &$arguments) + { + $listener = new SymfonyTestsListenerForV5(); + + $result = parent::handleConfiguration($arguments); + + $arguments['listeners'] = isset($arguments['listeners']) ? $arguments['listeners'] : array(); + + $registeredLocally = false; + + foreach ($arguments['listeners'] as $registeredListener) { + if ($registeredListener instanceof SymfonyTestsListenerForV5) { + $registeredListener->globalListenerDisabled(); + $registeredLocally = true; + break; + } + } + + if (!$registeredLocally) { + $arguments['listeners'][] = $listener; + } + + return $result; + } +} diff -r e200cb7efeb3 -r c2387f117808 vendor/symfony/phpunit-bridge/Legacy/TestRunnerForV6.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vendor/symfony/phpunit-bridge/Legacy/TestRunnerForV6.php Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,49 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bridge\PhpUnit\Legacy; + +use PHPUnit\TextUI\TestRunner as BaseRunner; +use Symfony\Bridge\PhpUnit\SymfonyTestsListener; + +/** + * {@inheritdoc} + * + * @internal + */ +class TestRunnerForV6 extends BaseRunner +{ + /** + * {@inheritdoc} + */ + protected function handleConfiguration(array &$arguments) + { + $listener = new SymfonyTestsListener(); + + parent::handleConfiguration($arguments); + + $arguments['listeners'] = isset($arguments['listeners']) ? $arguments['listeners'] : array(); + + $registeredLocally = false; + + foreach ($arguments['listeners'] as $registeredListener) { + if ($registeredListener instanceof SymfonyTestsListener) { + $registeredListener->globalListenerDisabled(); + $registeredLocally = true; + break; + } + } + + if (!$registeredLocally) { + $arguments['listeners'][] = $listener; + } + } +} diff -r e200cb7efeb3 -r c2387f117808 vendor/symfony/phpunit-bridge/Legacy/TestRunnerForV7.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vendor/symfony/phpunit-bridge/Legacy/TestRunnerForV7.php Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,49 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bridge\PhpUnit\Legacy; + +use PHPUnit\TextUI\TestRunner as BaseRunner; +use Symfony\Bridge\PhpUnit\SymfonyTestsListener; + +/** + * {@inheritdoc} + * + * @internal + */ +class TestRunnerForV7 extends BaseRunner +{ + /** + * {@inheritdoc} + */ + protected function handleConfiguration(array &$arguments): void + { + $listener = new SymfonyTestsListener(); + + parent::handleConfiguration($arguments); + + $arguments['listeners'] = isset($arguments['listeners']) ? $arguments['listeners'] : array(); + + $registeredLocally = false; + + foreach ($arguments['listeners'] as $registeredListener) { + if ($registeredListener instanceof SymfonyTestsListener) { + $registeredListener->globalListenerDisabled(); + $registeredLocally = true; + break; + } + } + + if (!$registeredLocally) { + $arguments['listeners'][] = $listener; + } + } +} diff -r e200cb7efeb3 -r c2387f117808 vendor/symfony/phpunit-bridge/Tests/CoverageListenerTest.php --- a/vendor/symfony/phpunit-bridge/Tests/CoverageListenerTest.php Thu Apr 26 11:26:54 2018 +0100 +++ b/vendor/symfony/phpunit-bridge/Tests/CoverageListenerTest.php Tue Jul 10 15:07:59 2018 +0100 @@ -31,11 +31,11 @@ $dir = __DIR__.'/../Tests/Fixtures/coverage'; $phpunit = $_SERVER['argv'][0]; - exec("$php $phpunit -c $dir/phpunit-without-listener.xml.dist $dir/tests/ --coverage-text", $output); + exec("$php $phpunit -c $dir/phpunit-without-listener.xml.dist $dir/tests/ --coverage-text 2> /dev/null", $output); $output = implode("\n", $output); $this->assertContains('FooCov', $output); - exec("$php $phpunit -c $dir/phpunit-with-listener.xml.dist $dir/tests/ --coverage-text", $output); + exec("$php $phpunit -c $dir/phpunit-with-listener.xml.dist $dir/tests/ --coverage-text 2> /dev/null", $output); $output = implode("\n", $output); $this->assertNotContains('FooCov', $output); $this->assertContains("SutNotFoundTest::test\nCould not find the tested class.", $output); diff -r e200cb7efeb3 -r c2387f117808 vendor/symfony/phpunit-bridge/Tests/DeprecationErrorHandler/weak_vendors_on_eval_d_deprecation.phpt --- a/vendor/symfony/phpunit-bridge/Tests/DeprecationErrorHandler/weak_vendors_on_eval_d_deprecation.phpt Thu Apr 26 11:26:54 2018 +0100 +++ b/vendor/symfony/phpunit-bridge/Tests/DeprecationErrorHandler/weak_vendors_on_eval_d_deprecation.phpt Tue Jul 10 15:07:59 2018 +0100 @@ -15,7 +15,7 @@ define('PHPUNIT_COMPOSER_INSTALL', $vendor.'/vendor/autoload.php'); require PHPUNIT_COMPOSER_INSTALL; require_once __DIR__.'/../../bootstrap.php'; -eval("@trigger_error('who knows where I come from?', E_USER_DEPRECATED);") +eval("@trigger_error('who knows where I come from?', E_USER_DEPRECATED);"); ?> --EXPECTF-- diff -r e200cb7efeb3 -r c2387f117808 vendor/symfony/phpunit-bridge/TextUI/Command.php --- a/vendor/symfony/phpunit-bridge/TextUI/Command.php Thu Apr 26 11:26:54 2018 +0100 +++ b/vendor/symfony/phpunit-bridge/TextUI/Command.php Tue Jul 10 15:07:59 2018 +0100 @@ -11,24 +11,14 @@ namespace Symfony\Bridge\PhpUnit\TextUI; -use PHPUnit\TextUI\Command as BaseCommand; +if (class_exists('PHPUnit_Runner_Version') && version_compare(\PHPUnit_Runner_Version::id(), '6.0.0', '<')) { + class_alias('Symfony\Bridge\PhpUnit\Legacy\CommandForV5', 'Symfony\Bridge\PhpUnit\TextUI\Command'); +} else { + class_alias('Symfony\Bridge\PhpUnit\Legacy\CommandForV6', 'Symfony\Bridge\PhpUnit\TextUI\Command'); +} -if (class_exists('PHPUnit_Runner_Version') && version_compare(\PHPUnit_Runner_Version::id(), '6.0.0', '<')) { - class_alias('Symfony\Bridge\PhpUnit\Legacy\Command', 'Symfony\Bridge\PhpUnit\TextUI\Command'); -} else { - /** - * {@inheritdoc} - * - * @internal - */ - class Command extends BaseCommand +if (false) { + class Command { - /** - * {@inheritdoc} - */ - protected function createRunner() - { - return new TestRunner($this->arguments['loader']); - } } } diff -r e200cb7efeb3 -r c2387f117808 vendor/symfony/phpunit-bridge/TextUI/TestRunner.php --- a/vendor/symfony/phpunit-bridge/TextUI/TestRunner.php Thu Apr 26 11:26:54 2018 +0100 +++ b/vendor/symfony/phpunit-bridge/TextUI/TestRunner.php Tue Jul 10 15:07:59 2018 +0100 @@ -11,45 +11,16 @@ namespace Symfony\Bridge\PhpUnit\TextUI; -use PHPUnit\TextUI\TestRunner as BaseRunner; -use Symfony\Bridge\PhpUnit\SymfonyTestsListener; +if (class_exists('PHPUnit_Runner_Version') && version_compare(\PHPUnit_Runner_Version::id(), '6.0.0', '<')) { + class_alias('Symfony\Bridge\PhpUnit\Legacy\TestRunnerForV5', 'Symfony\Bridge\PhpUnit\TextUI\TestRunner'); +} elseif (version_compare(\PHPUnit\Runner\Version::id(), '7.0.0', '<')) { + class_alias('Symfony\Bridge\PhpUnit\Legacy\TestRunnerForV6', 'Symfony\Bridge\PhpUnit\TextUI\TestRunner'); +} else { + class_alias('Symfony\Bridge\PhpUnit\Legacy\TestRunnerForV7', 'Symfony\Bridge\PhpUnit\TextUI\TestRunner'); +} -if (class_exists('PHPUnit_Runner_Version') && version_compare(\PHPUnit_Runner_Version::id(), '6.0.0', '<')) { - class_alias('Symfony\Bridge\PhpUnit\Legacy\TestRunner', 'Symfony\Bridge\PhpUnit\TextUI\TestRunner'); -} else { - /** - * {@inheritdoc} - * - * @internal - */ - class TestRunner extends BaseRunner +if (false) { + class TestRunner { - /** - * {@inheritdoc} - */ - protected function handleConfiguration(array &$arguments) - { - $listener = new SymfonyTestsListener(); - - $result = parent::handleConfiguration($arguments); - - $arguments['listeners'] = isset($arguments['listeners']) ? $arguments['listeners'] : array(); - - $registeredLocally = false; - - foreach ($arguments['listeners'] as $registeredListener) { - if ($registeredListener instanceof SymfonyTestsListener) { - $registeredListener->globalListenerDisabled(); - $registeredLocally = true; - break; - } - } - - if (!$registeredLocally) { - $arguments['listeners'][] = $listener; - } - - return $result; - } } } diff -r e200cb7efeb3 -r c2387f117808 vendor/symfony/phpunit-bridge/bin/simple-phpunit --- a/vendor/symfony/phpunit-bridge/bin/simple-phpunit Thu Apr 26 11:26:54 2018 +0100 +++ b/vendor/symfony/phpunit-bridge/bin/simple-phpunit Tue Jul 10 15:07:59 2018 +0100 @@ -47,7 +47,7 @@ $PHP .= ' -qrr'; } -$COMPOSER = file_exists($COMPOSER = $oldPwd.'/composer.phar') || ($COMPOSER = rtrim('\\' === DIRECTORY_SEPARATOR ? preg_replace('/[\r\n].*/', '', `where.exe composer.phar`) : `which composer.phar`)) +$COMPOSER = file_exists($COMPOSER = $oldPwd.'/composer.phar') || ($COMPOSER = rtrim('\\' === DIRECTORY_SEPARATOR ? preg_replace('/[\r\n].*/', '', `where.exe composer.phar`) : `which composer.phar 2> /dev/null`)) ? $PHP.' '.escapeshellarg($COMPOSER) : 'composer'; @@ -70,9 +70,11 @@ throw new \RuntimeException("Could not find $remoteZip"); } stream_copy_to_stream($remoteZipStream, fopen("$PHPUNIT_VERSION.zip", 'wb')); + } elseif ('\\' === DIRECTORY_SEPARATOR) { + passthru("certutil -urlcache -split -f \"https://github.com/sebastianbergmann/phpunit/archive/$PHPUNIT_VERSION.zip\" $PHPUNIT_VERSION.zip"); } else { @unlink("$PHPUNIT_VERSION.zip"); - passthru("wget https://github.com/sebastianbergmann/phpunit/archive/$PHPUNIT_VERSION.zip"); + passthru("wget -q https://github.com/sebastianbergmann/phpunit/archive/$PHPUNIT_VERSION.zip"); } if (!class_exists('ZipArchive')) { throw new \Exception('simple-phpunit requires the "zip" PHP extension to be installed and enabled in order to uncompress the downloaded PHPUnit packages.'); @@ -188,15 +190,6 @@ } } - // Fixes for colors support on appveyor - // See https://github.com/appveyor/ci/issues/373 - $colorFixes = array( - array("S\033[0m\033[0m\033[36m\033[1mS", "E\033[0m\033[0m\033[31m\033[1mE", "I\033[0m\033[0m\033[33m\033[1mI", "F\033[0m\033[0m\033[41m\033[37mF"), - array("SS", "EE", "II", "FF"), - ); - $colorFixes[0] = array_merge($colorFixes[0], $colorFixes[0]); - $colorFixes[1] = array_merge($colorFixes[1], $colorFixes[1]); - while ($runningProcs) { usleep(300000); $terminatedProcs = array(); @@ -212,20 +205,7 @@ foreach ($terminatedProcs as $component => $procStatus) { foreach (array('out', 'err') as $file) { $file = "$component/phpunit.std$file"; - - if ('\\' === DIRECTORY_SEPARATOR) { - $h = fopen($file, 'rb'); - while (false !== $line = fgets($h)) { - echo str_replace($colorFixes[0], $colorFixes[1], preg_replace( - '/(\033\[[0-9]++);([0-9]++m)(?:(.)(\033\[0m))?/', - "$1m\033[$2$3$4$4", - $line - )); - } - fclose($h); - } else { - readfile($file); - } + readfile($file); unlink($file); } diff -r e200cb7efeb3 -r c2387f117808 vendor/symfony/polyfill-ctype/Ctype.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vendor/symfony/polyfill-ctype/Ctype.php Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,227 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Polyfill\Ctype; + +/** + * Ctype implementation through regex. + * + * @internal + * + * @author Gert de Pagter + */ +final class Ctype +{ + /** + * Returns TRUE if every character in text is either a letter or a digit, FALSE otherwise. + * + * @see https://php.net/ctype-alnum + * + * @param string|int $text + * + * @return bool + */ + public static function ctype_alnum($text) + { + $text = self::convert_int_to_char_for_ctype($text); + + return \is_string($text) && '' !== $text && !preg_match('/[^A-Za-z0-9]/', $text); + } + + /** + * Returns TRUE if every character in text is a letter, FALSE otherwise. + * + * @see https://php.net/ctype-alpha + * + * @param string|int $text + * + * @return bool + */ + public static function ctype_alpha($text) + { + $text = self::convert_int_to_char_for_ctype($text); + + return \is_string($text) && '' !== $text && !preg_match('/[^A-Za-z]/', $text); + } + + /** + * Returns TRUE if every character in text is a control character from the current locale, FALSE otherwise. + * + * @see https://php.net/ctype-cntrl + * + * @param string|int $text + * + * @return bool + */ + public static function ctype_cntrl($text) + { + $text = self::convert_int_to_char_for_ctype($text); + + return \is_string($text) && '' !== $text && !preg_match('/[^\x00-\x1f\x7f]/', $text); + } + + /** + * Returns TRUE if every character in the string text is a decimal digit, FALSE otherwise. + * + * @see https://php.net/ctype-digit + * + * @param string|int $text + * + * @return bool + */ + public static function ctype_digit($text) + { + $text = self::convert_int_to_char_for_ctype($text); + + return \is_string($text) && '' !== $text && !preg_match('/[^0-9]/', $text); + } + + /** + * Returns TRUE if every character in text is printable and actually creates visible output (no white space), FALSE otherwise. + * + * @see https://php.net/ctype-graph + * + * @param string|int $text + * + * @return bool + */ + public static function ctype_graph($text) + { + $text = self::convert_int_to_char_for_ctype($text); + + return \is_string($text) && '' !== $text && !preg_match('/[^!-~]/', $text); + } + + /** + * Returns TRUE if every character in text is a lowercase letter. + * + * @see https://php.net/ctype-lower + * + * @param string|int $text + * + * @return bool + */ + public static function ctype_lower($text) + { + $text = self::convert_int_to_char_for_ctype($text); + + return \is_string($text) && '' !== $text && !preg_match('/[^a-z]/', $text); + } + + /** + * Returns TRUE if every character in text will actually create output (including blanks). Returns FALSE if text contains control characters or characters that do not have any output or control function at all. + * + * @see https://php.net/ctype-print + * + * @param string|int $text + * + * @return bool + */ + public static function ctype_print($text) + { + $text = self::convert_int_to_char_for_ctype($text); + + return \is_string($text) && '' !== $text && !preg_match('/[^ -~]/', $text); + } + + /** + * Returns TRUE if every character in text is printable, but neither letter, digit or blank, FALSE otherwise. + * + * @see https://php.net/ctype-punct + * + * @param string|int $text + * + * @return bool + */ + public static function ctype_punct($text) + { + $text = self::convert_int_to_char_for_ctype($text); + + return \is_string($text) && '' !== $text && !preg_match('/[^!-\/\:-@\[-`\{-~]/', $text); + } + + /** + * Returns TRUE if every character in text creates some sort of white space, FALSE otherwise. Besides the blank character this also includes tab, vertical tab, line feed, carriage return and form feed characters. + * + * @see https://php.net/ctype-space + * + * @param string|int $text + * + * @return bool + */ + public static function ctype_space($text) + { + $text = self::convert_int_to_char_for_ctype($text); + + return \is_string($text) && '' !== $text && !preg_match('/[^\s]/', $text); + } + + /** + * Returns TRUE if every character in text is an uppercase letter. + * + * @see https://php.net/ctype-upper + * + * @param string|int $text + * + * @return bool + */ + public static function ctype_upper($text) + { + $text = self::convert_int_to_char_for_ctype($text); + + return \is_string($text) && '' !== $text && !preg_match('/[^A-Z]/', $text); + } + + /** + * Returns TRUE if every character in text is a hexadecimal 'digit', that is a decimal digit or a character from [A-Fa-f] , FALSE otherwise. + * + * @see https://php.net/ctype-xdigit + * + * @param string|int $text + * + * @return bool + */ + public static function ctype_xdigit($text) + { + $text = self::convert_int_to_char_for_ctype($text); + + return \is_string($text) && '' !== $text && !preg_match('/[^A-Fa-f0-9]/', $text); + } + + /** + * Converts integers to their char versions according to normal ctype behaviour, if needed. + * + * If an integer between -128 and 255 inclusive is provided, + * it is interpreted as the ASCII value of a single character + * (negative values have 256 added in order to allow characters in the Extended ASCII range). + * Any other integer is interpreted as a string containing the decimal digits of the integer. + * + * @param string|int $int + * + * @return mixed + */ + private static function convert_int_to_char_for_ctype($int) + { + if (!\is_int($int)) { + return $int; + } + + if ($int < -128 || $int > 255) { + return (string) $int; + } + + if ($int < 0) { + $int += 256; + } + + return \chr($int); + } +} diff -r e200cb7efeb3 -r c2387f117808 vendor/symfony/polyfill-ctype/LICENSE --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vendor/symfony/polyfill-ctype/LICENSE Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,19 @@ +Copyright (c) 2018 Fabien Potencier + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is furnished +to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff -r e200cb7efeb3 -r c2387f117808 vendor/symfony/polyfill-ctype/README.md --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vendor/symfony/polyfill-ctype/README.md Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,12 @@ +Symfony Polyfill / Ctype +======================== + +This component provides `ctype_*` functions to users who run php versions without the ctype extension. + +More information can be found in the +[main Polyfill README](https://github.com/symfony/polyfill/blob/master/README.md). + +License +======= + +This library is released under the [MIT license](LICENSE). diff -r e200cb7efeb3 -r c2387f117808 vendor/symfony/polyfill-ctype/bootstrap.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vendor/symfony/polyfill-ctype/bootstrap.php Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,26 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +use Symfony\Polyfill\Ctype as p; + +if (!function_exists('ctype_alnum')) { + function ctype_alnum($text) { return p\Ctype::ctype_alnum($text); } + function ctype_alpha($text) { return p\Ctype::ctype_alpha($text); } + function ctype_cntrl($text) { return p\Ctype::ctype_cntrl($text); } + function ctype_digit($text) { return p\Ctype::ctype_digit($text); } + function ctype_graph($text) { return p\Ctype::ctype_graph($text); } + function ctype_lower($text) { return p\Ctype::ctype_lower($text); } + function ctype_print($text) { return p\Ctype::ctype_print($text); } + function ctype_punct($text) { return p\Ctype::ctype_punct($text); } + function ctype_space($text) { return p\Ctype::ctype_space($text); } + function ctype_upper($text) { return p\Ctype::ctype_upper($text); } + function ctype_xdigit($text) { return p\Ctype::ctype_xdigit($text); } +} diff -r e200cb7efeb3 -r c2387f117808 vendor/symfony/polyfill-ctype/composer.json --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vendor/symfony/polyfill-ctype/composer.json Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,31 @@ +{ + "name": "symfony/polyfill-ctype", + "type": "library", + "description": "Symfony polyfill for ctype functions", + "keywords": ["polyfill", "compatibility", "portable", "ctype"], + "homepage": "https://symfony.com", + "license": "MIT", + "authors": [ + { + "name": "Gert de Pagter", + "email": "BackEndTea@gmail.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "require": { + "php": ">=5.3.3" + }, + "autoload": { + "psr-4": { "Symfony\\Polyfill\\Ctype\\": "" }, + "files": [ "bootstrap.php" ] + }, + "minimum-stability": "dev", + "extra": { + "branch-alias": { + "dev-master": "1.8-dev" + } + } +} diff -r e200cb7efeb3 -r c2387f117808 vendor/symfony/polyfill-iconv/Iconv.php --- a/vendor/symfony/polyfill-iconv/Iconv.php Thu Apr 26 11:26:54 2018 +0100 +++ b/vendor/symfony/polyfill-iconv/Iconv.php Tue Jul 10 15:07:59 2018 +0100 @@ -248,9 +248,9 @@ } $str = explode(':', $str, 2); - if (2 === count($str)) { + if (2 === \count($str)) { if (isset($headers[$str[0]])) { - if (!is_array($headers[$str[0]])) { + if (!\is_array($headers[$str[0]])) { $headers[$str[0]] = array($headers[$str[0]]); } $headers[$str[0]][] = ltrim($str[1]); @@ -285,7 +285,7 @@ } $i = 1; - $len = count($str); + $len = \count($str); while ($i < $len) { $c = strtolower($str[$i]); @@ -355,7 +355,7 @@ public static function iconv_mime_encode($fieldName, $fieldValue, $pref = null) { - if (!is_array($pref)) { + if (!\is_array($pref)) { $pref = array(); } @@ -385,8 +385,8 @@ $lineBreak = (int) $pref['line-length']; $lineStart = "=?{$pref['output-charset']}?{$scheme}?"; - $lineLength = strlen($fieldName) + 2 + strlen($lineStart) + 2; - $lineOffset = strlen($lineStart) + 3; + $lineLength = \strlen($fieldName) + 2 + \strlen($lineStart) + 2; + $lineOffset = \strlen($lineStart) + 3; $lineData = ''; $fieldValue = array(); @@ -416,7 +416,7 @@ } $lineData .= $c; - $Q && $lineLength += strlen($c); + $Q && $lineLength += \strlen($c); } if ('' !== $lineData) { @@ -452,7 +452,7 @@ return false; } - return strlen(utf8_decode($s)); + return \strlen(utf8_decode($s)); } public static function strlen2($s, $encoding = null) @@ -468,7 +468,7 @@ $i = 0; $j = 0; - $len = strlen($s); + $len = \strlen($s); while ($i < $len) { $u = $s[$i] & "\xF0"; @@ -600,7 +600,7 @@ $u = $str; $i = $j = 0; - $len = strlen($str); + $len = \strlen($str); while ($i < $len) { if ($str[$i] < "\x80") { @@ -636,7 +636,7 @@ private static function mapToUtf8(&$result, array $map, $str, $ignore) { - $len = strlen($str); + $len = \strlen($str); for ($i = 0; $i < $len; ++$i) { if (isset($str[$i + 1], $map[$str[$i].$str[$i + 1]])) { $result .= $map[$str[$i].$str[++$i]]; @@ -662,7 +662,7 @@ } $i = 0; - $len = strlen($str); + $len = \strlen($str); while ($i < $len) { if ($str[$i] < "\x80") { @@ -698,7 +698,7 @@ } $str = $uchr.substr($str, $i); - $len = strlen($str); + $len = \strlen($str); $i = 0; } elseif (!$ignore) { return false; @@ -710,7 +710,7 @@ private static function qpByteCallback(array $m) { - return '='.strtoupper(dechex(ord($m[0]))); + return '='.strtoupper(dechex(\ord($m[0]))); } private static function pregOffset($offset) diff -r e200cb7efeb3 -r c2387f117808 vendor/symfony/polyfill-iconv/composer.json --- a/vendor/symfony/polyfill-iconv/composer.json Thu Apr 26 11:26:54 2018 +0100 +++ b/vendor/symfony/polyfill-iconv/composer.json Tue Jul 10 15:07:59 2018 +0100 @@ -28,7 +28,7 @@ "minimum-stability": "dev", "extra": { "branch-alias": { - "dev-master": "1.7-dev" + "dev-master": "1.8-dev" } } } diff -r e200cb7efeb3 -r c2387f117808 vendor/symfony/polyfill-mbstring/Mbstring.php --- a/vendor/symfony/polyfill-mbstring/Mbstring.php Thu Apr 26 11:26:54 2018 +0100 +++ b/vendor/symfony/polyfill-mbstring/Mbstring.php Tue Jul 10 15:07:59 2018 +0100 @@ -78,7 +78,7 @@ public static function mb_convert_encoding($s, $toEncoding, $fromEncoding = null) { - if (is_array($fromEncoding) || false !== strpos($fromEncoding, ',')) { + if (\is_array($fromEncoding) || false !== strpos($fromEncoding, ',')) { $fromEncoding = self::mb_detect_encoding($s, $fromEncoding); } else { $fromEncoding = self::getEncoding($fromEncoding); @@ -140,16 +140,16 @@ public static function mb_decode_numericentity($s, $convmap, $encoding = null) { - if (null !== $s && !is_scalar($s) && !(is_object($s) && method_exists($s, '__toString'))) { + if (null !== $s && !\is_scalar($s) && !(\is_object($s) && \method_exists($s, '__toString'))) { trigger_error('mb_decode_numericentity() expects parameter 1 to be string, '.gettype($s).' given', E_USER_WARNING); return null; } - if (!is_array($convmap) || !$convmap) { + if (!\is_array($convmap) || !$convmap) { return false; } - if (null !== $encoding && !is_scalar($encoding)) { + if (null !== $encoding && !\is_scalar($encoding)) { trigger_error('mb_decode_numericentity() expects parameter 3 to be string, '.gettype($s).' given', E_USER_WARNING); return ''; // Instead of null (cf. mb_encode_numericentity). } @@ -170,7 +170,7 @@ $s = iconv($encoding, 'UTF-8//IGNORE', $s); } - $cnt = floor(count($convmap) / 4) * 4; + $cnt = floor(\count($convmap) / 4) * 4; for ($i = 0; $i < $cnt; $i += 4) { // collector_decode_htmlnumericentity ignores $convmap[$i + 3] @@ -197,21 +197,21 @@ public static function mb_encode_numericentity($s, $convmap, $encoding = null, $is_hex = false) { - if (null !== $s && !is_scalar($s) && !(is_object($s) && method_exists($s, '__toString'))) { + if (null !== $s && !\is_scalar($s) && !(\is_object($s) && \method_exists($s, '__toString'))) { trigger_error('mb_encode_numericentity() expects parameter 1 to be string, '.gettype($s).' given', E_USER_WARNING); return null; } - if (!is_array($convmap) || !$convmap) { + if (!\is_array($convmap) || !$convmap) { return false; } - if (null !== $encoding && !is_scalar($encoding)) { + if (null !== $encoding && !\is_scalar($encoding)) { trigger_error('mb_encode_numericentity() expects parameter 3 to be string, '.gettype($s).' given', E_USER_WARNING); return null; // Instead of '' (cf. mb_decode_numericentity). } - if (null !== $is_hex && !is_scalar($is_hex)) { + if (null !== $is_hex && !\is_scalar($is_hex)) { trigger_error('mb_encode_numericentity() expects parameter 4 to be boolean, '.gettype($s).' given', E_USER_WARNING); return null; } @@ -234,9 +234,9 @@ static $ulenMask = array("\xC0" => 2, "\xD0" => 2, "\xE0" => 3, "\xF0" => 4); - $cnt = floor(count($convmap) / 4) * 4; + $cnt = floor(\count($convmap) / 4) * 4; $i = 0; - $len = strlen($s); + $len = \strlen($s); $result = ''; while ($i < $len) { @@ -305,7 +305,7 @@ static $ulenMask = array("\xC0" => 2, "\xD0" => 2, "\xE0" => 3, "\xF0" => 4); $i = 0; - $len = strlen($s); + $len = \strlen($s); while ($i < $len) { $ulen = $s[$i] < "\x80" ? 1 : $ulenMask[$s[$i] & "\xF0"]; @@ -314,7 +314,7 @@ if (isset($map[$uchr])) { $uchr = $map[$uchr]; - $nlen = strlen($uchr); + $nlen = \strlen($uchr); if ($nlen == $ulen) { $nlen = $i; @@ -404,7 +404,7 @@ if (null === $encodingList) { $encodingList = self::$encodingList; } else { - if (!is_array($encodingList)) { + if (!\is_array($encodingList)) { $encodingList = array_map('trim', explode(',', $encodingList)); } $encodingList = array_map('strtoupper', $encodingList); @@ -441,7 +441,7 @@ return self::$encodingList; } - if (!is_array($encodingList)) { + if (!\is_array($encodingList)) { $encodingList = array_map('trim', explode(',', $encodingList)); } $encodingList = array_map('strtoupper', $encodingList); @@ -467,7 +467,7 @@ { $encoding = self::getEncoding($encoding); if ('CP850' === $encoding || 'ASCII' === $encoding) { - return strlen($s); + return \strlen($s); } return @iconv_strlen($s, $encoding); @@ -679,13 +679,13 @@ public static function mb_chr($code, $encoding = null) { if (0x80 > $code %= 0x200000) { - $s = chr($code); + $s = \chr($code); } elseif (0x800 > $code) { - $s = chr(0xC0 | $code >> 6).chr(0x80 | $code & 0x3F); + $s = \chr(0xC0 | $code >> 6).\chr(0x80 | $code & 0x3F); } elseif (0x10000 > $code) { - $s = chr(0xE0 | $code >> 12).chr(0x80 | $code >> 6 & 0x3F).chr(0x80 | $code & 0x3F); + $s = \chr(0xE0 | $code >> 12).\chr(0x80 | $code >> 6 & 0x3F).\chr(0x80 | $code & 0x3F); } else { - $s = chr(0xF0 | $code >> 18).chr(0x80 | $code >> 12 & 0x3F).chr(0x80 | $code >> 6 & 0x3F).chr(0x80 | $code & 0x3F); + $s = \chr(0xF0 | $code >> 18).\chr(0x80 | $code >> 12 & 0x3F).\chr(0x80 | $code >> 6 & 0x3F).\chr(0x80 | $code & 0x3F); } if ('UTF-8' !== $encoding = self::getEncoding($encoding)) { @@ -735,7 +735,7 @@ while (isset($m[$i])) { if (0x80 > $m[$i]) { - $entities .= chr($m[$i++]); + $entities .= \chr($m[$i++]); continue; } if (0xF0 <= $m[$i]) { diff -r e200cb7efeb3 -r c2387f117808 vendor/symfony/polyfill-mbstring/composer.json --- a/vendor/symfony/polyfill-mbstring/composer.json Thu Apr 26 11:26:54 2018 +0100 +++ b/vendor/symfony/polyfill-mbstring/composer.json Tue Jul 10 15:07:59 2018 +0100 @@ -28,7 +28,7 @@ "minimum-stability": "dev", "extra": { "branch-alias": { - "dev-master": "1.7-dev" + "dev-master": "1.8-dev" } } } diff -r e200cb7efeb3 -r c2387f117808 vendor/symfony/polyfill-php70/Php70.php --- a/vendor/symfony/polyfill-php70/Php70.php Thu Apr 26 11:26:54 2018 +0100 +++ b/vendor/symfony/polyfill-php70/Php70.php Tue Jul 10 15:07:59 2018 +0100 @@ -60,12 +60,12 @@ restore_error_handler(); } - public static function intArg($value, $caller, $pos) + private static function intArg($value, $caller, $pos) { - if (is_int($value)) { + if (\is_int($value)) { return $value; } - if (!is_numeric($value) || PHP_INT_MAX <= ($value += 0) || ~PHP_INT_MAX >= $value) { + if (!\is_numeric($value) || PHP_INT_MAX <= ($value += 0) || ~PHP_INT_MAX >= $value) { throw new \TypeError(sprintf('%s() expects parameter %d to be integer, %s given', $caller, $pos, gettype($value))); } diff -r e200cb7efeb3 -r c2387f117808 vendor/symfony/polyfill-php70/composer.json --- a/vendor/symfony/polyfill-php70/composer.json Thu Apr 26 11:26:54 2018 +0100 +++ b/vendor/symfony/polyfill-php70/composer.json Tue Jul 10 15:07:59 2018 +0100 @@ -27,7 +27,7 @@ "minimum-stability": "dev", "extra": { "branch-alias": { - "dev-master": "1.7-dev" + "dev-master": "1.8-dev" } } } diff -r e200cb7efeb3 -r c2387f117808 vendor/symfony/process/ExecutableFinder.php --- a/vendor/symfony/process/ExecutableFinder.php Thu Apr 26 11:26:54 2018 +0100 +++ b/vendor/symfony/process/ExecutableFinder.php Tue Jul 10 15:07:59 2018 +0100 @@ -73,11 +73,11 @@ $suffixes = array(''); if ('\\' === DIRECTORY_SEPARATOR) { $pathExt = getenv('PATHEXT'); - $suffixes = array_merge($suffixes, $pathExt ? explode(PATH_SEPARATOR, $pathExt) : $this->suffixes); + $suffixes = array_merge($pathExt ? explode(PATH_SEPARATOR, $pathExt) : $this->suffixes, $suffixes); } foreach ($suffixes as $suffix) { foreach ($dirs as $dir) { - if (@is_file($file = $dir.DIRECTORY_SEPARATOR.$name.$suffix) && ('\\' === DIRECTORY_SEPARATOR || is_executable($file))) { + if (@is_file($file = $dir.DIRECTORY_SEPARATOR.$name.$suffix) && ('\\' === DIRECTORY_SEPARATOR || @is_executable($file))) { return $file; } } diff -r e200cb7efeb3 -r c2387f117808 vendor/symfony/process/PhpExecutableFinder.php --- a/vendor/symfony/process/PhpExecutableFinder.php Thu Apr 26 11:26:54 2018 +0100 +++ b/vendor/symfony/process/PhpExecutableFinder.php Tue Jul 10 15:07:59 2018 +0100 @@ -49,7 +49,7 @@ } if ($php = getenv('PHP_PATH')) { - if (!is_executable($php)) { + if (!@is_executable($php)) { return false; } @@ -57,12 +57,12 @@ } if ($php = getenv('PHP_PEAR_PHP_BIN')) { - if (is_executable($php)) { + if (@is_executable($php)) { return $php; } } - if (is_executable($php = PHP_BINDIR.('\\' === DIRECTORY_SEPARATOR ? '\\php.exe' : '/php'))) { + if (@is_executable($php = PHP_BINDIR.('\\' === DIRECTORY_SEPARATOR ? '\\php.exe' : '/php'))) { return $php; } diff -r e200cb7efeb3 -r c2387f117808 vendor/symfony/process/Pipes/AbstractPipes.php --- a/vendor/symfony/process/Pipes/AbstractPipes.php Thu Apr 26 11:26:54 2018 +0100 +++ b/vendor/symfony/process/Pipes/AbstractPipes.php Tue Jul 10 15:07:59 2018 +0100 @@ -25,6 +25,7 @@ private $inputBuffer = ''; private $input; private $blocked = true; + private $lastError; /** * @param resource|string|int|float|bool|\Iterator|null $input @@ -58,10 +59,11 @@ */ protected function hasSystemCallBeenInterrupted() { - $lastError = error_get_last(); + $lastError = $this->lastError; + $this->lastError = null; // stream_select returns false when the `select` system call is interrupted by an incoming signal - return isset($lastError['message']) && false !== stripos($lastError['message'], 'interrupted system call'); + return null !== $lastError && false !== stripos($lastError, 'interrupted system call'); } /** @@ -165,4 +167,12 @@ return array($this->pipes[0]); } } + + /** + * @internal + */ + public function handleError($type, $msg) + { + $this->lastError = $msg; + } } diff -r e200cb7efeb3 -r c2387f117808 vendor/symfony/process/Pipes/UnixPipes.php --- a/vendor/symfony/process/Pipes/UnixPipes.php Thu Apr 26 11:26:54 2018 +0100 +++ b/vendor/symfony/process/Pipes/UnixPipes.php Tue Jul 10 15:07:59 2018 +0100 @@ -99,7 +99,9 @@ unset($r[0]); // let's have a look if something changed in streams - if (($r || $w) && false === @stream_select($r, $w, $e, 0, $blocking ? Process::TIMEOUT_PRECISION * 1E6 : 0)) { + set_error_handler(array($this, 'handleError')); + if (($r || $w) && false === stream_select($r, $w, $e, 0, $blocking ? Process::TIMEOUT_PRECISION * 1E6 : 0)) { + restore_error_handler(); // if a system call has been interrupted, forget about it, let's try again // otherwise, an error occurred, let's reset pipes if (!$this->hasSystemCallBeenInterrupted()) { @@ -108,6 +110,7 @@ return $read; } + restore_error_handler(); foreach ($r as $pipe) { // prior PHP 5.4 the array passed to stream_select is modified and diff -r e200cb7efeb3 -r c2387f117808 vendor/symfony/routing/Loader/AnnotationClassLoader.php --- a/vendor/symfony/routing/Loader/AnnotationClassLoader.php Thu Apr 26 11:26:54 2018 +0100 +++ b/vendor/symfony/routing/Loader/AnnotationClassLoader.php Tue Jul 10 15:07:59 2018 +0100 @@ -119,10 +119,15 @@ } } - if (0 === $collection->count() && $class->hasMethod('__invoke') && $annot = $this->reader->getClassAnnotation($class, $this->routeAnnotationClass)) { - $globals['path'] = ''; - $globals['name'] = ''; - $this->addRoute($collection, $annot, $globals, $class, $class->getMethod('__invoke')); + if (0 === $collection->count() && $class->hasMethod('__invoke')) { + foreach ($this->reader->getClassAnnotations($class) as $annot) { + if ($annot instanceof $this->routeAnnotationClass) { + $globals['path'] = ''; + $globals['name'] = ''; + + $this->addRoute($collection, $annot, $globals, $class, $class->getMethod('__invoke')); + } + } } return $collection; diff -r e200cb7efeb3 -r c2387f117808 vendor/symfony/routing/Matcher/Dumper/DumperCollection.php --- a/vendor/symfony/routing/Matcher/Dumper/DumperCollection.php Thu Apr 26 11:26:54 2018 +0100 +++ b/vendor/symfony/routing/Matcher/Dumper/DumperCollection.php Tue Jul 10 15:07:59 2018 +0100 @@ -106,7 +106,7 @@ /** * Sets the parent collection. */ - protected function setParent(DumperCollection $parent) + protected function setParent(self $parent) { $this->parent = $parent; } diff -r e200cb7efeb3 -r c2387f117808 vendor/symfony/routing/RouteCollectionBuilder.php --- a/vendor/symfony/routing/RouteCollectionBuilder.php Thu Apr 26 11:26:54 2018 +0100 +++ b/vendor/symfony/routing/RouteCollectionBuilder.php Tue Jul 10 15:07:59 2018 +0100 @@ -118,7 +118,7 @@ * @param string $prefix * @param RouteCollectionBuilder $builder */ - public function mount($prefix, RouteCollectionBuilder $builder) + public function mount($prefix, self $builder) { $builder->prefix = trim(trim($prefix), '/'); $this->routes[] = $builder; @@ -251,8 +251,6 @@ /** * Adds a resource for this collection. * - * @param ResourceInterface $resource - * * @return $this */ private function addResource(ResourceInterface $resource) diff -r e200cb7efeb3 -r c2387f117808 vendor/symfony/routing/composer.json --- a/vendor/symfony/routing/composer.json Thu Apr 26 11:26:54 2018 +0100 +++ b/vendor/symfony/routing/composer.json Tue Jul 10 15:07:59 2018 +0100 @@ -25,7 +25,6 @@ "symfony/expression-language": "~2.8|~3.0|~4.0", "symfony/dependency-injection": "~3.3|~4.0", "doctrine/annotations": "~1.0", - "doctrine/common": "~2.2", "psr/log": "~1.0" }, "conflict": { diff -r e200cb7efeb3 -r c2387f117808 vendor/symfony/serializer/Mapping/ClassMetadataInterface.php --- a/vendor/symfony/serializer/Mapping/ClassMetadataInterface.php Thu Apr 26 11:26:54 2018 +0100 +++ b/vendor/symfony/serializer/Mapping/ClassMetadataInterface.php Tue Jul 10 15:07:59 2018 +0100 @@ -46,7 +46,7 @@ /** * Merges a {@link ClassMetadataInterface} in the current one. */ - public function merge(ClassMetadataInterface $classMetadata); + public function merge(self $classMetadata); /** * Returns a {@link \ReflectionClass} instance for this class. diff -r e200cb7efeb3 -r c2387f117808 vendor/symfony/serializer/Normalizer/AbstractNormalizer.php --- a/vendor/symfony/serializer/Normalizer/AbstractNormalizer.php Thu Apr 26 11:26:54 2018 +0100 +++ b/vendor/symfony/serializer/Normalizer/AbstractNormalizer.php Tue Jul 10 15:07:59 2018 +0100 @@ -200,11 +200,17 @@ * @param array $context * @param bool $attributesAsString If false, return an array of {@link AttributeMetadataInterface} * + * @throws LogicException if the 'allow_extra_attributes' context variable is false and no class metadata factory is provided + * * @return string[]|AttributeMetadataInterface[]|bool */ protected function getAllowedAttributes($classOrObject, array $context, $attributesAsString = false) { if (!$this->classMetadataFactory) { + if (isset($context[static::ALLOW_EXTRA_ATTRIBUTES]) && !$context[static::ALLOW_EXTRA_ATTRIBUTES]) { + throw new LogicException(sprintf('A class metadata factory must be provided in the constructor when setting "%s" to false.', static::ALLOW_EXTRA_ATTRIBUTES)); + } + return false; } @@ -349,6 +355,12 @@ } } elseif ($allowed && !$ignored && (isset($data[$key]) || array_key_exists($key, $data))) { $parameterData = $data[$key]; + if (null === $parameterData && $constructorParameter->allowsNull()) { + $params[] = null; + // Don't run set for a parameter passed to the constructor + unset($data[$key]); + continue; + } try { if (null !== $constructorParameter->getClass()) { if (!$this->serializer instanceof DenormalizerInterface) { diff -r e200cb7efeb3 -r c2387f117808 vendor/symfony/serializer/Normalizer/AbstractObjectNormalizer.php --- a/vendor/symfony/serializer/Normalizer/AbstractObjectNormalizer.php Thu Apr 26 11:26:54 2018 +0100 +++ b/vendor/symfony/serializer/Normalizer/AbstractObjectNormalizer.php Tue Jul 10 15:07:59 2018 +0100 @@ -255,6 +255,12 @@ $builtinType = Type::BUILTIN_TYPE_OBJECT; $class = $collectionValueType->getClassName().'[]'; + // Fix a collection that contains the only one element + // This is special to xml format only + if ('xml' === $format && !is_int(key($data))) { + $data = array($data); + } + if (null !== $collectionKeyType = $type->getCollectionKeyType()) { $context['key_type'] = $collectionKeyType; } @@ -301,7 +307,6 @@ /** * Sets an attribute and apply the name converter if necessary. * - * @param array $data * @param string $attribute * @param mixed $attributeValue * @@ -332,6 +337,7 @@ { if ( !isset($context[static::ENABLE_MAX_DEPTH]) || + !$context[static::ENABLE_MAX_DEPTH] || !isset($attributesMetadata[$attribute]) || null === $maxDepth = $attributesMetadata[$attribute]->getMaxDepth() ) { diff -r e200cb7efeb3 -r c2387f117808 vendor/symfony/serializer/Normalizer/NormalizerInterface.php --- a/vendor/symfony/serializer/Normalizer/NormalizerInterface.php Thu Apr 26 11:26:54 2018 +0100 +++ b/vendor/symfony/serializer/Normalizer/NormalizerInterface.php Tue Jul 10 15:07:59 2018 +0100 @@ -25,7 +25,7 @@ /** * Normalizes an object into a set of arrays/scalars. * - * @param object $object Object to normalize + * @param mixed $object Object to normalize * @param string $format Format the normalization result will be encoded as * @param array $context Context options for the normalizer * diff -r e200cb7efeb3 -r c2387f117808 vendor/symfony/serializer/composer.json --- a/vendor/symfony/serializer/composer.json Thu Apr 26 11:26:54 2018 +0100 +++ b/vendor/symfony/serializer/composer.json Tue Jul 10 15:07:59 2018 +0100 @@ -16,7 +16,8 @@ } ], "require": { - "php": "^5.5.9|>=7.0.8" + "php": "^5.5.9|>=7.0.8", + "symfony/polyfill-ctype": "~1.8" }, "require-dev": { "symfony/yaml": "~3.4|~4.0", diff -r e200cb7efeb3 -r c2387f117808 vendor/symfony/translation/Command/XliffLintCommand.php --- a/vendor/symfony/translation/Command/XliffLintCommand.php Thu Apr 26 11:26:54 2018 +0100 +++ b/vendor/symfony/translation/Command/XliffLintCommand.php Tue Jul 10 15:07:59 2018 +0100 @@ -12,6 +12,7 @@ namespace Symfony\Component\Translation\Command; use Symfony\Component\Console\Command\Command; +use Symfony\Component\Console\Exception\RuntimeException; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Output\OutputInterface; @@ -81,14 +82,14 @@ if (!$filename) { if (!$stdin = $this->getStdin()) { - throw new \RuntimeException('Please provide a filename or pipe file content to STDIN.'); + throw new RuntimeException('Please provide a filename or pipe file content to STDIN.'); } return $this->display($io, array($this->validate($stdin))); } if (!$this->isReadable($filename)) { - throw new \RuntimeException(sprintf('File or directory "%s" is not readable.', $filename)); + throw new RuntimeException(sprintf('File or directory "%s" is not readable.', $filename)); } $filesInfo = array(); @@ -136,7 +137,7 @@ case 'json': return $this->displayJson($io, $files); default: - throw new \InvalidArgumentException(sprintf('The format "%s" is not supported.', $this->format)); + throw new InvalidArgumentException(sprintf('The format "%s" is not supported.', $this->format)); } } diff -r e200cb7efeb3 -r c2387f117808 vendor/symfony/translation/MessageCatalogueInterface.php --- a/vendor/symfony/translation/MessageCatalogueInterface.php Thu Apr 26 11:26:54 2018 +0100 +++ b/vendor/symfony/translation/MessageCatalogueInterface.php Tue Jul 10 15:07:59 2018 +0100 @@ -105,7 +105,7 @@ * * The two catalogues must have the same locale. */ - public function addCatalogue(MessageCatalogueInterface $catalogue); + public function addCatalogue(self $catalogue); /** * Merges translations from the given Catalogue into the current one @@ -113,7 +113,7 @@ * * This is used to provide default translations when they do not exist for the current locale. */ - public function addFallbackCatalogue(MessageCatalogueInterface $catalogue); + public function addFallbackCatalogue(self $catalogue); /** * Gets the fallback catalogue. diff -r e200cb7efeb3 -r c2387f117808 vendor/symfony/translation/PluralizationRules.php --- a/vendor/symfony/translation/PluralizationRules.php Thu Apr 26 11:26:54 2018 +0100 +++ b/vendor/symfony/translation/PluralizationRules.php Tue Jul 10 15:07:59 2018 +0100 @@ -107,6 +107,7 @@ case 'nl': case 'nn': case 'no': + case 'oc': case 'om': case 'or': case 'pa': diff -r e200cb7efeb3 -r c2387f117808 vendor/symfony/translation/Resources/schemas/xliff-core-1.2-strict.xsd --- a/vendor/symfony/translation/Resources/schemas/xliff-core-1.2-strict.xsd Thu Apr 26 11:26:54 2018 +0100 +++ b/vendor/symfony/translation/Resources/schemas/xliff-core-1.2-strict.xsd Tue Jul 10 15:07:59 2018 +0100 @@ -1,2223 +1,2223 @@ - - - - - - - - - - - - - - - Values for the attribute 'context-type'. - - - - - Indicates a database content. - - - - - Indicates the content of an element within an XML document. - - - - - Indicates the name of an element within an XML document. - - - - - Indicates the line number from the sourcefile (see context-type="sourcefile") where the <source> is found. - - - - - Indicates a the number of parameters contained within the <source>. - - - - - Indicates notes pertaining to the parameters in the <source>. - - - - - Indicates the content of a record within a database. - - - - - Indicates the name of a record within a database. - - - - - Indicates the original source file in the case that multiple files are merged to form the original file from which the XLIFF file is created. This differs from the original <file> attribute in that this sourcefile is one of many that make up that file. - - - - - - - Values for the attribute 'count-type'. - - - - - Indicates the count units are items that are used X times in a certain context; example: this is a reusable text unit which is used 42 times in other texts. - - - - - Indicates the count units are translation units existing already in the same document. - - - - - Indicates a total count. - - - - - - - Values for the attribute 'ctype' when used other elements than <ph> or <x>. - - - - - Indicates a run of bolded text. - - - - - Indicates a run of text in italics. - - - - - Indicates a run of underlined text. - - - - - Indicates a run of hyper-text. - - - - - - - Values for the attribute 'ctype' when used with <ph> or <x>. - - - - - Indicates a inline image. - - - - - Indicates a page break. - - - - - Indicates a line break. - - - - - - - - - - - - Values for the attribute 'datatype'. - - - - - Indicates Active Server Page data. - - - - - Indicates C source file data. - - - - - Indicates Channel Definition Format (CDF) data. - - - - - Indicates ColdFusion data. - - - - - Indicates C++ source file data. - - - - - Indicates C-Sharp data. - - - - - Indicates strings from C, ASM, and driver files data. - - - - - Indicates comma-separated values data. - - - - - Indicates database data. - - - - - Indicates portions of document that follows data and contains metadata. - - - - - Indicates portions of document that precedes data and contains metadata. - - - - - Indicates data from standard UI file operations dialogs (e.g., Open, Save, Save As, Export, Import). - - - - - Indicates standard user input screen data. - - - - - Indicates HyperText Markup Language (HTML) data - document instance. - - - - - Indicates content within an HTML document’s <body> element. - - - - - Indicates Windows INI file data. - - - - - Indicates Interleaf data. - - - - - Indicates Java source file data (extension '.java'). - - - - - Indicates Java property resource bundle data. - - - - - Indicates Java list resource bundle data. - - - - - Indicates JavaScript source file data. - - - - - Indicates JScript source file data. - - - - - Indicates information relating to formatting. - - - - - Indicates LISP source file data. - - - - - Indicates information relating to margin formats. - - - - - Indicates a file containing menu. - - - - - Indicates numerically identified string table. - - - - - Indicates Maker Interchange Format (MIF) data. - - - - - Indicates that the datatype attribute value is a MIME Type value and is defined in the mime-type attribute. - - - - - Indicates GNU Machine Object data. - - - - - Indicates Message Librarian strings created by Novell's Message Librarian Tool. - - - - - Indicates information to be displayed at the bottom of each page of a document. - - - - - Indicates information to be displayed at the top of each page of a document. - - - - - Indicates a list of property values (e.g., settings within INI files or preferences dialog). - - - - - Indicates Pascal source file data. - - - - - Indicates Hypertext Preprocessor data. - - - - - Indicates plain text file (no formatting other than, possibly, wrapping). - - - - - Indicates GNU Portable Object file. - - - - - Indicates dynamically generated user defined document. e.g. Oracle Report, Crystal Report, etc. - - - - - Indicates Windows .NET binary resources. - - - - - Indicates Windows .NET Resources. - - - - - Indicates Rich Text Format (RTF) data. - - - - - Indicates Standard Generalized Markup Language (SGML) data - document instance. - - - - - Indicates Standard Generalized Markup Language (SGML) data - Document Type Definition (DTD). - - - - - Indicates Scalable Vector Graphic (SVG) data. - - - - - Indicates VisualBasic Script source file. - - - - - Indicates warning message. - - - - - Indicates Windows (Win32) resources (i.e. resources extracted from an RC script, a message file, or a compiled file). - - - - - Indicates Extensible HyperText Markup Language (XHTML) data - document instance. - - - - - Indicates Extensible Markup Language (XML) data - document instance. - - - - - Indicates Extensible Markup Language (XML) data - Document Type Definition (DTD). - - - - - Indicates Extensible Stylesheet Language (XSL) data. - - - - - Indicates XUL elements. - - - - - - - Values for the attribute 'mtype'. - - - - - Indicates the marked text is an abbreviation. - - - - - ISO-12620 2.1.8: A term resulting from the omission of any part of the full term while designating the same concept. - - - - - ISO-12620 2.1.8.1: An abbreviated form of a simple term resulting from the omission of some of its letters (e.g. 'adj.' for 'adjective'). - - - - - ISO-12620 2.1.8.4: An abbreviated form of a term made up of letters from the full form of a multiword term strung together into a sequence pronounced only syllabically (e.g. 'radar' for 'radio detecting and ranging'). - - - - - ISO-12620: A proper-name term, such as the name of an agency or other proper entity. - - - - - ISO-12620 2.1.18.1: A recurrent word combination characterized by cohesion in that the components of the collocation must co-occur within an utterance or series of utterances, even though they do not necessarily have to maintain immediate proximity to one another. - - - - - ISO-12620 2.1.5: A synonym for an international scientific term that is used in general discourse in a given language. - - - - - Indicates the marked text is a date and/or time. - - - - - ISO-12620 2.1.15: An expression used to represent a concept based on a statement that two mathematical expressions are, for instance, equal as identified by the equal sign (=), or assigned to one another by a similar sign. - - - - - ISO-12620 2.1.7: The complete representation of a term for which there is an abbreviated form. - - - - - ISO-12620 2.1.14: Figures, symbols or the like used to express a concept briefly, such as a mathematical or chemical formula. - - - - - ISO-12620 2.1.1: The concept designation that has been chosen to head a terminological record. - - - - - ISO-12620 2.1.8.3: An abbreviated form of a term consisting of some of the initial letters of the words making up a multiword term or the term elements making up a compound term when these letters are pronounced individually (e.g. 'BSE' for 'bovine spongiform encephalopathy'). - - - - - ISO-12620 2.1.4: A term that is part of an international scientific nomenclature as adopted by an appropriate scientific body. - - - - - ISO-12620 2.1.6: A term that has the same or nearly identical orthographic or phonemic form in many languages. - - - - - ISO-12620 2.1.16: An expression used to represent a concept based on mathematical or logical relations, such as statements of inequality, set relationships, Boolean operations, and the like. - - - - - ISO-12620 2.1.17: A unit to track object. - - - - - Indicates the marked text is a name. - - - - - ISO-12620 2.1.3: A term that represents the same or a very similar concept as another term in the same language, but for which interchangeability is limited to some contexts and inapplicable in others. - - - - - ISO-12620 2.1.17.2: A unique alphanumeric designation assigned to an object in a manufacturing system. - - - - - Indicates the marked text is a phrase. - - - - - ISO-12620 2.1.18: Any group of two or more words that form a unit, the meaning of which frequently cannot be deduced based on the combined sense of the words making up the phrase. - - - - - Indicates the marked text should not be translated. - - - - - ISO-12620 2.1.12: A form of a term resulting from an operation whereby non-Latin writing systems are converted to the Latin alphabet. - - - - - Indicates that the marked text represents a segment. - - - - - ISO-12620 2.1.18.2: A fixed, lexicalized phrase. - - - - - ISO-12620 2.1.8.2: A variant of a multiword term that includes fewer words than the full form of the term (e.g. 'Group of Twenty-four' for 'Intergovernmental Group of Twenty-four on International Monetary Affairs'). - - - - - ISO-12620 2.1.17.1: Stock keeping unit, an inventory item identified by a unique alphanumeric designation assigned to an object in an inventory control system. - - - - - ISO-12620 2.1.19: A fixed chunk of recurring text. - - - - - ISO-12620 2.1.13: A designation of a concept by letters, numerals, pictograms or any combination thereof. - - - - - ISO-12620 2.1.2: Any term that represents the same or a very similar concept as the main entry term in a term entry. - - - - - ISO-12620 2.1.18.3: Phraseological unit in a language that expresses the same semantic content as another phrase in that same language. - - - - - Indicates the marked text is a term. - - - - - ISO-12620 2.1.11: A form of a term resulting from an operation whereby the characters of one writing system are represented by characters from another writing system, taking into account the pronunciation of the characters converted. - - - - - ISO-12620 2.1.10: A form of a term resulting from an operation whereby the characters of an alphabetic writing system are represented by characters from another alphabetic writing system. - - - - - ISO-12620 2.1.8.5: An abbreviated form of a term resulting from the omission of one or more term elements or syllables (e.g. 'flu' for 'influenza'). - - - - - ISO-12620 2.1.9: One of the alternate forms of a term. - - - - - - - Values for the attribute 'restype'. - - - - - Indicates a Windows RC AUTO3STATE control. - - - - - Indicates a Windows RC AUTOCHECKBOX control. - - - - - Indicates a Windows RC AUTORADIOBUTTON control. - - - - - Indicates a Windows RC BEDIT control. - - - - - Indicates a bitmap, for example a BITMAP resource in Windows. - - - - - Indicates a button object, for example a BUTTON control Windows. - - - - - Indicates a caption, such as the caption of a dialog box. - - - - - Indicates the cell in a table, for example the content of the <td> element in HTML. - - - - - Indicates check box object, for example a CHECKBOX control in Windows. - - - - - Indicates a menu item with an associated checkbox. - - - - - Indicates a list box, but with a check-box for each item. - - - - - Indicates a color selection dialog. - - - - - Indicates a combination of edit box and listbox object, for example a COMBOBOX control in Windows. - - - - - Indicates an initialization entry of an extended combobox DLGINIT resource block. (code 0x1234). - - - - - Indicates an initialization entry of a combobox DLGINIT resource block (code 0x0403). - - - - - Indicates a UI base class element that cannot be represented by any other element. - - - - - Indicates a context menu. - - - - - Indicates a Windows RC CTEXT control. - - - - - Indicates a cursor, for example a CURSOR resource in Windows. - - - - - Indicates a date/time picker. - - - - - Indicates a Windows RC DEFPUSHBUTTON control. - - - - - Indicates a dialog box. - - - - - Indicates a Windows RC DLGINIT resource block. - - - - - Indicates an edit box object, for example an EDIT control in Windows. - - - - - Indicates a filename. - - - - - Indicates a file dialog. - - - - - Indicates a footnote. - - - - - Indicates a font name. - - - - - Indicates a footer. - - - - - Indicates a frame object. - - - - - Indicates a XUL grid element. - - - - - Indicates a groupbox object, for example a GROUPBOX control in Windows. - - - - - Indicates a header item. - - - - - Indicates a heading, such has the content of <h1>, <h2>, etc. in HTML. - - - - - Indicates a Windows RC HEDIT control. - - - - - Indicates a horizontal scrollbar. - - - - - Indicates an icon, for example an ICON resource in Windows. - - - - - Indicates a Windows RC IEDIT control. - - - - - Indicates keyword list, such as the content of the Keywords meta-data in HTML, or a K footnote in WinHelp RTF. - - - - - Indicates a label object. - - - - - Indicates a label that is also a HTML link (not necessarily a URL). - - - - - Indicates a list (a group of list-items, for example an <ol> or <ul> element in HTML). - - - - - Indicates a listbox object, for example an LISTBOX control in Windows. - - - - - Indicates an list item (an entry in a list). - - - - - Indicates a Windows RC LTEXT control. - - - - - Indicates a menu (a group of menu-items). - - - - - Indicates a toolbar containing one or more tope level menus. - - - - - Indicates a menu item (an entry in a menu). - - - - - Indicates a XUL menuseparator element. - - - - - Indicates a message, for example an entry in a MESSAGETABLE resource in Windows. - - - - - Indicates a calendar control. - - - - - Indicates an edit box beside a spin control. - - - - - Indicates a catch all for rectangular areas. - - - - - Indicates a standalone menu not necessarily associated with a menubar. - - - - - Indicates a pushbox object, for example a PUSHBOX control in Windows. - - - - - Indicates a Windows RC PUSHBUTTON control. - - - - - Indicates a radio button object. - - - - - Indicates a menuitem with associated radio button. - - - - - Indicates raw data resources for an application. - - - - - Indicates a row in a table. - - - - - Indicates a Windows RC RTEXT control. - - - - - Indicates a user navigable container used to show a portion of a document. - - - - - Indicates a generic divider object (e.g. menu group separator). - - - - - Windows accelerators, shortcuts in resource or property files. - - - - - Indicates a UI control to indicate process activity but not progress. - - - - - Indicates a splitter bar. - - - - - Indicates a Windows RC STATE3 control. - - - - - Indicates a window for providing feedback to the users, like 'read-only', etc. - - - - - Indicates a string, for example an entry in a STRINGTABLE resource in Windows. - - - - - Indicates a layers of controls with a tab to select layers. - - - - - Indicates a display and edits regular two-dimensional tables of cells. - - - - - Indicates a XUL textbox element. - - - - - Indicates a UI button that can be toggled to on or off state. - - - - - Indicates an array of controls, usually buttons. - - - - - Indicates a pop up tool tip text. - - - - - Indicates a bar with a pointer indicating a position within a certain range. - - - - - Indicates a control that displays a set of hierarchical data. - - - - - Indicates a URI (URN or URL). - - - - - Indicates a Windows RC USERBUTTON control. - - - - - Indicates a user-defined control like CONTROL control in Windows. - - - - - Indicates the text of a variable. - - - - - Indicates version information about a resource like VERSIONINFO in Windows. - - - - - Indicates a vertical scrollbar. - - - - - Indicates a graphical window. - - - - - - - Values for the attribute 'size-unit'. - - - - - Indicates a size in 8-bit bytes. - - - - - Indicates a size in Unicode characters. - - - - - Indicates a size in columns. Used for HTML text area. - - - - - Indicates a size in centimeters. - - - - - Indicates a size in dialog units, as defined in Windows resources. - - - - - Indicates a size in 'font-size' units (as defined in CSS). - - - - - Indicates a size in 'x-height' units (as defined in CSS). - - - - - Indicates a size in glyphs. A glyph is considered to be one or more combined Unicode characters that represent a single displayable text character. Sometimes referred to as a 'grapheme cluster' - - - - - Indicates a size in inches. - - - - - Indicates a size in millimeters. - - - - - Indicates a size in percentage. - - - - - Indicates a size in pixels. - - - - - Indicates a size in point. - - - - - Indicates a size in rows. Used for HTML text area. - - - - - - - Values for the attribute 'state'. - - - - - Indicates the terminating state. - - - - - Indicates only non-textual information needs adaptation. - - - - - Indicates both text and non-textual information needs adaptation. - - - - - Indicates only non-textual information needs review. - - - - - Indicates both text and non-textual information needs review. - - - - - Indicates that only the text of the item needs to be reviewed. - - - - - Indicates that the item needs to be translated. - - - - - Indicates that the item is new. For example, translation units that were not in a previous version of the document. - - - - - Indicates that changes are reviewed and approved. - - - - - Indicates that the item has been translated. - - - - - - - Values for the attribute 'state-qualifier'. - - - - - Indicates an exact match. An exact match occurs when a source text of a segment is exactly the same as the source text of a segment that was translated previously. - - - - - Indicates a fuzzy match. A fuzzy match occurs when a source text of a segment is very similar to the source text of a segment that was translated previously (e.g. when the difference is casing, a few changed words, white-space discripancy, etc.). - - - - - Indicates a match based on matching IDs (in addition to matching text). - - - - - Indicates a translation derived from a glossary. - - - - - Indicates a translation derived from existing translation. - - - - - Indicates a translation derived from machine translation. - - - - - Indicates a translation derived from a translation repository. - - - - - Indicates a translation derived from a translation memory. - - - - - Indicates the translation is suggested by machine translation. - - - - - Indicates that the item has been rejected because of incorrect grammar. - - - - - Indicates that the item has been rejected because it is incorrect. - - - - - Indicates that the item has been rejected because it is too long or too short. - - - - - Indicates that the item has been rejected because of incorrect spelling. - - - - - Indicates the translation is suggested by translation memory. - - - - - - - Values for the attribute 'unit'. - - - - - Refers to words. - - - - - Refers to pages. - - - - - Refers to <trans-unit> elements. - - - - - Refers to <bin-unit> elements. - - - - - Refers to glyphs. - - - - - Refers to <trans-unit> and/or <bin-unit> elements. - - - - - Refers to the occurrences of instances defined by the count-type value. - - - - - Refers to characters. - - - - - Refers to lines. - - - - - Refers to sentences. - - - - - Refers to paragraphs. - - - - - Refers to segments. - - - - - Refers to placeables (inline elements). - - - - - - - Values for the attribute 'priority'. - - - - - Highest priority. - - - - - High priority. - - - - - High priority, but not as important as 2. - - - - - High priority, but not as important as 3. - - - - - Medium priority, but more important than 6. - - - - - Medium priority, but less important than 5. - - - - - Low priority, but more important than 8. - - - - - Low priority, but more important than 9. - - - - - Low priority. - - - - - Lowest priority. - - - - - - - - - This value indicates that all properties can be reformatted. This value must be used alone. - - - - - This value indicates that no properties should be reformatted. This value must be used alone. - - - - - - - - - - - - - This value indicates that all information in the coord attribute can be modified. - - - - - This value indicates that the x information in the coord attribute can be modified. - - - - - This value indicates that the y information in the coord attribute can be modified. - - - - - This value indicates that the cx information in the coord attribute can be modified. - - - - - This value indicates that the cy information in the coord attribute can be modified. - - - - - This value indicates that all the information in the font attribute can be modified. - - - - - This value indicates that the name information in the font attribute can be modified. - - - - - This value indicates that the size information in the font attribute can be modified. - - - - - This value indicates that the weight information in the font attribute can be modified. - - - - - This value indicates that the information in the css-style attribute can be modified. - - - - - This value indicates that the information in the style attribute can be modified. - - - - - This value indicates that the information in the exstyle attribute can be modified. - - - - - - - - - - - - - Indicates that the context is informational in nature, specifying for example, how a term should be translated. Thus, should be displayed to anyone editing the XLIFF document. - - - - - Indicates that the context-group is used to specify where the term was found in the translatable source. Thus, it is not displayed. - - - - - Indicates that the context information should be used during translation memory lookups. Thus, it is not displayed. - - - - - - - - - Represents a translation proposal from a translation memory or other resource. - - - - - Represents a previous version of the target element. - - - - - Represents a rejected version of the target element. - - - - - Represents a translation to be used for reference purposes only, for example from a related product or a different language. - - - - - Represents a proposed translation that was used for the translation of the trans-unit, possibly modified. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Values for the attribute 'coord'. - - - - - - - - Version values: 1.0 and 1.1 are allowed for backward compatibility. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file + + + + + + + + + + + + + + + Values for the attribute 'context-type'. + + + + + Indicates a database content. + + + + + Indicates the content of an element within an XML document. + + + + + Indicates the name of an element within an XML document. + + + + + Indicates the line number from the sourcefile (see context-type="sourcefile") where the <source> is found. + + + + + Indicates a the number of parameters contained within the <source>. + + + + + Indicates notes pertaining to the parameters in the <source>. + + + + + Indicates the content of a record within a database. + + + + + Indicates the name of a record within a database. + + + + + Indicates the original source file in the case that multiple files are merged to form the original file from which the XLIFF file is created. This differs from the original <file> attribute in that this sourcefile is one of many that make up that file. + + + + + + + Values for the attribute 'count-type'. + + + + + Indicates the count units are items that are used X times in a certain context; example: this is a reusable text unit which is used 42 times in other texts. + + + + + Indicates the count units are translation units existing already in the same document. + + + + + Indicates a total count. + + + + + + + Values for the attribute 'ctype' when used other elements than <ph> or <x>. + + + + + Indicates a run of bolded text. + + + + + Indicates a run of text in italics. + + + + + Indicates a run of underlined text. + + + + + Indicates a run of hyper-text. + + + + + + + Values for the attribute 'ctype' when used with <ph> or <x>. + + + + + Indicates a inline image. + + + + + Indicates a page break. + + + + + Indicates a line break. + + + + + + + + + + + + Values for the attribute 'datatype'. + + + + + Indicates Active Server Page data. + + + + + Indicates C source file data. + + + + + Indicates Channel Definition Format (CDF) data. + + + + + Indicates ColdFusion data. + + + + + Indicates C++ source file data. + + + + + Indicates C-Sharp data. + + + + + Indicates strings from C, ASM, and driver files data. + + + + + Indicates comma-separated values data. + + + + + Indicates database data. + + + + + Indicates portions of document that follows data and contains metadata. + + + + + Indicates portions of document that precedes data and contains metadata. + + + + + Indicates data from standard UI file operations dialogs (e.g., Open, Save, Save As, Export, Import). + + + + + Indicates standard user input screen data. + + + + + Indicates HyperText Markup Language (HTML) data - document instance. + + + + + Indicates content within an HTML document’s <body> element. + + + + + Indicates Windows INI file data. + + + + + Indicates Interleaf data. + + + + + Indicates Java source file data (extension '.java'). + + + + + Indicates Java property resource bundle data. + + + + + Indicates Java list resource bundle data. + + + + + Indicates JavaScript source file data. + + + + + Indicates JScript source file data. + + + + + Indicates information relating to formatting. + + + + + Indicates LISP source file data. + + + + + Indicates information relating to margin formats. + + + + + Indicates a file containing menu. + + + + + Indicates numerically identified string table. + + + + + Indicates Maker Interchange Format (MIF) data. + + + + + Indicates that the datatype attribute value is a MIME Type value and is defined in the mime-type attribute. + + + + + Indicates GNU Machine Object data. + + + + + Indicates Message Librarian strings created by Novell's Message Librarian Tool. + + + + + Indicates information to be displayed at the bottom of each page of a document. + + + + + Indicates information to be displayed at the top of each page of a document. + + + + + Indicates a list of property values (e.g., settings within INI files or preferences dialog). + + + + + Indicates Pascal source file data. + + + + + Indicates Hypertext Preprocessor data. + + + + + Indicates plain text file (no formatting other than, possibly, wrapping). + + + + + Indicates GNU Portable Object file. + + + + + Indicates dynamically generated user defined document. e.g. Oracle Report, Crystal Report, etc. + + + + + Indicates Windows .NET binary resources. + + + + + Indicates Windows .NET Resources. + + + + + Indicates Rich Text Format (RTF) data. + + + + + Indicates Standard Generalized Markup Language (SGML) data - document instance. + + + + + Indicates Standard Generalized Markup Language (SGML) data - Document Type Definition (DTD). + + + + + Indicates Scalable Vector Graphic (SVG) data. + + + + + Indicates VisualBasic Script source file. + + + + + Indicates warning message. + + + + + Indicates Windows (Win32) resources (i.e. resources extracted from an RC script, a message file, or a compiled file). + + + + + Indicates Extensible HyperText Markup Language (XHTML) data - document instance. + + + + + Indicates Extensible Markup Language (XML) data - document instance. + + + + + Indicates Extensible Markup Language (XML) data - Document Type Definition (DTD). + + + + + Indicates Extensible Stylesheet Language (XSL) data. + + + + + Indicates XUL elements. + + + + + + + Values for the attribute 'mtype'. + + + + + Indicates the marked text is an abbreviation. + + + + + ISO-12620 2.1.8: A term resulting from the omission of any part of the full term while designating the same concept. + + + + + ISO-12620 2.1.8.1: An abbreviated form of a simple term resulting from the omission of some of its letters (e.g. 'adj.' for 'adjective'). + + + + + ISO-12620 2.1.8.4: An abbreviated form of a term made up of letters from the full form of a multiword term strung together into a sequence pronounced only syllabically (e.g. 'radar' for 'radio detecting and ranging'). + + + + + ISO-12620: A proper-name term, such as the name of an agency or other proper entity. + + + + + ISO-12620 2.1.18.1: A recurrent word combination characterized by cohesion in that the components of the collocation must co-occur within an utterance or series of utterances, even though they do not necessarily have to maintain immediate proximity to one another. + + + + + ISO-12620 2.1.5: A synonym for an international scientific term that is used in general discourse in a given language. + + + + + Indicates the marked text is a date and/or time. + + + + + ISO-12620 2.1.15: An expression used to represent a concept based on a statement that two mathematical expressions are, for instance, equal as identified by the equal sign (=), or assigned to one another by a similar sign. + + + + + ISO-12620 2.1.7: The complete representation of a term for which there is an abbreviated form. + + + + + ISO-12620 2.1.14: Figures, symbols or the like used to express a concept briefly, such as a mathematical or chemical formula. + + + + + ISO-12620 2.1.1: The concept designation that has been chosen to head a terminological record. + + + + + ISO-12620 2.1.8.3: An abbreviated form of a term consisting of some of the initial letters of the words making up a multiword term or the term elements making up a compound term when these letters are pronounced individually (e.g. 'BSE' for 'bovine spongiform encephalopathy'). + + + + + ISO-12620 2.1.4: A term that is part of an international scientific nomenclature as adopted by an appropriate scientific body. + + + + + ISO-12620 2.1.6: A term that has the same or nearly identical orthographic or phonemic form in many languages. + + + + + ISO-12620 2.1.16: An expression used to represent a concept based on mathematical or logical relations, such as statements of inequality, set relationships, Boolean operations, and the like. + + + + + ISO-12620 2.1.17: A unit to track object. + + + + + Indicates the marked text is a name. + + + + + ISO-12620 2.1.3: A term that represents the same or a very similar concept as another term in the same language, but for which interchangeability is limited to some contexts and inapplicable in others. + + + + + ISO-12620 2.1.17.2: A unique alphanumeric designation assigned to an object in a manufacturing system. + + + + + Indicates the marked text is a phrase. + + + + + ISO-12620 2.1.18: Any group of two or more words that form a unit, the meaning of which frequently cannot be deduced based on the combined sense of the words making up the phrase. + + + + + Indicates the marked text should not be translated. + + + + + ISO-12620 2.1.12: A form of a term resulting from an operation whereby non-Latin writing systems are converted to the Latin alphabet. + + + + + Indicates that the marked text represents a segment. + + + + + ISO-12620 2.1.18.2: A fixed, lexicalized phrase. + + + + + ISO-12620 2.1.8.2: A variant of a multiword term that includes fewer words than the full form of the term (e.g. 'Group of Twenty-four' for 'Intergovernmental Group of Twenty-four on International Monetary Affairs'). + + + + + ISO-12620 2.1.17.1: Stock keeping unit, an inventory item identified by a unique alphanumeric designation assigned to an object in an inventory control system. + + + + + ISO-12620 2.1.19: A fixed chunk of recurring text. + + + + + ISO-12620 2.1.13: A designation of a concept by letters, numerals, pictograms or any combination thereof. + + + + + ISO-12620 2.1.2: Any term that represents the same or a very similar concept as the main entry term in a term entry. + + + + + ISO-12620 2.1.18.3: Phraseological unit in a language that expresses the same semantic content as another phrase in that same language. + + + + + Indicates the marked text is a term. + + + + + ISO-12620 2.1.11: A form of a term resulting from an operation whereby the characters of one writing system are represented by characters from another writing system, taking into account the pronunciation of the characters converted. + + + + + ISO-12620 2.1.10: A form of a term resulting from an operation whereby the characters of an alphabetic writing system are represented by characters from another alphabetic writing system. + + + + + ISO-12620 2.1.8.5: An abbreviated form of a term resulting from the omission of one or more term elements or syllables (e.g. 'flu' for 'influenza'). + + + + + ISO-12620 2.1.9: One of the alternate forms of a term. + + + + + + + Values for the attribute 'restype'. + + + + + Indicates a Windows RC AUTO3STATE control. + + + + + Indicates a Windows RC AUTOCHECKBOX control. + + + + + Indicates a Windows RC AUTORADIOBUTTON control. + + + + + Indicates a Windows RC BEDIT control. + + + + + Indicates a bitmap, for example a BITMAP resource in Windows. + + + + + Indicates a button object, for example a BUTTON control Windows. + + + + + Indicates a caption, such as the caption of a dialog box. + + + + + Indicates the cell in a table, for example the content of the <td> element in HTML. + + + + + Indicates check box object, for example a CHECKBOX control in Windows. + + + + + Indicates a menu item with an associated checkbox. + + + + + Indicates a list box, but with a check-box for each item. + + + + + Indicates a color selection dialog. + + + + + Indicates a combination of edit box and listbox object, for example a COMBOBOX control in Windows. + + + + + Indicates an initialization entry of an extended combobox DLGINIT resource block. (code 0x1234). + + + + + Indicates an initialization entry of a combobox DLGINIT resource block (code 0x0403). + + + + + Indicates a UI base class element that cannot be represented by any other element. + + + + + Indicates a context menu. + + + + + Indicates a Windows RC CTEXT control. + + + + + Indicates a cursor, for example a CURSOR resource in Windows. + + + + + Indicates a date/time picker. + + + + + Indicates a Windows RC DEFPUSHBUTTON control. + + + + + Indicates a dialog box. + + + + + Indicates a Windows RC DLGINIT resource block. + + + + + Indicates an edit box object, for example an EDIT control in Windows. + + + + + Indicates a filename. + + + + + Indicates a file dialog. + + + + + Indicates a footnote. + + + + + Indicates a font name. + + + + + Indicates a footer. + + + + + Indicates a frame object. + + + + + Indicates a XUL grid element. + + + + + Indicates a groupbox object, for example a GROUPBOX control in Windows. + + + + + Indicates a header item. + + + + + Indicates a heading, such has the content of <h1>, <h2>, etc. in HTML. + + + + + Indicates a Windows RC HEDIT control. + + + + + Indicates a horizontal scrollbar. + + + + + Indicates an icon, for example an ICON resource in Windows. + + + + + Indicates a Windows RC IEDIT control. + + + + + Indicates keyword list, such as the content of the Keywords meta-data in HTML, or a K footnote in WinHelp RTF. + + + + + Indicates a label object. + + + + + Indicates a label that is also a HTML link (not necessarily a URL). + + + + + Indicates a list (a group of list-items, for example an <ol> or <ul> element in HTML). + + + + + Indicates a listbox object, for example an LISTBOX control in Windows. + + + + + Indicates an list item (an entry in a list). + + + + + Indicates a Windows RC LTEXT control. + + + + + Indicates a menu (a group of menu-items). + + + + + Indicates a toolbar containing one or more tope level menus. + + + + + Indicates a menu item (an entry in a menu). + + + + + Indicates a XUL menuseparator element. + + + + + Indicates a message, for example an entry in a MESSAGETABLE resource in Windows. + + + + + Indicates a calendar control. + + + + + Indicates an edit box beside a spin control. + + + + + Indicates a catch all for rectangular areas. + + + + + Indicates a standalone menu not necessarily associated with a menubar. + + + + + Indicates a pushbox object, for example a PUSHBOX control in Windows. + + + + + Indicates a Windows RC PUSHBUTTON control. + + + + + Indicates a radio button object. + + + + + Indicates a menuitem with associated radio button. + + + + + Indicates raw data resources for an application. + + + + + Indicates a row in a table. + + + + + Indicates a Windows RC RTEXT control. + + + + + Indicates a user navigable container used to show a portion of a document. + + + + + Indicates a generic divider object (e.g. menu group separator). + + + + + Windows accelerators, shortcuts in resource or property files. + + + + + Indicates a UI control to indicate process activity but not progress. + + + + + Indicates a splitter bar. + + + + + Indicates a Windows RC STATE3 control. + + + + + Indicates a window for providing feedback to the users, like 'read-only', etc. + + + + + Indicates a string, for example an entry in a STRINGTABLE resource in Windows. + + + + + Indicates a layers of controls with a tab to select layers. + + + + + Indicates a display and edits regular two-dimensional tables of cells. + + + + + Indicates a XUL textbox element. + + + + + Indicates a UI button that can be toggled to on or off state. + + + + + Indicates an array of controls, usually buttons. + + + + + Indicates a pop up tool tip text. + + + + + Indicates a bar with a pointer indicating a position within a certain range. + + + + + Indicates a control that displays a set of hierarchical data. + + + + + Indicates a URI (URN or URL). + + + + + Indicates a Windows RC USERBUTTON control. + + + + + Indicates a user-defined control like CONTROL control in Windows. + + + + + Indicates the text of a variable. + + + + + Indicates version information about a resource like VERSIONINFO in Windows. + + + + + Indicates a vertical scrollbar. + + + + + Indicates a graphical window. + + + + + + + Values for the attribute 'size-unit'. + + + + + Indicates a size in 8-bit bytes. + + + + + Indicates a size in Unicode characters. + + + + + Indicates a size in columns. Used for HTML text area. + + + + + Indicates a size in centimeters. + + + + + Indicates a size in dialog units, as defined in Windows resources. + + + + + Indicates a size in 'font-size' units (as defined in CSS). + + + + + Indicates a size in 'x-height' units (as defined in CSS). + + + + + Indicates a size in glyphs. A glyph is considered to be one or more combined Unicode characters that represent a single displayable text character. Sometimes referred to as a 'grapheme cluster' + + + + + Indicates a size in inches. + + + + + Indicates a size in millimeters. + + + + + Indicates a size in percentage. + + + + + Indicates a size in pixels. + + + + + Indicates a size in point. + + + + + Indicates a size in rows. Used for HTML text area. + + + + + + + Values for the attribute 'state'. + + + + + Indicates the terminating state. + + + + + Indicates only non-textual information needs adaptation. + + + + + Indicates both text and non-textual information needs adaptation. + + + + + Indicates only non-textual information needs review. + + + + + Indicates both text and non-textual information needs review. + + + + + Indicates that only the text of the item needs to be reviewed. + + + + + Indicates that the item needs to be translated. + + + + + Indicates that the item is new. For example, translation units that were not in a previous version of the document. + + + + + Indicates that changes are reviewed and approved. + + + + + Indicates that the item has been translated. + + + + + + + Values for the attribute 'state-qualifier'. + + + + + Indicates an exact match. An exact match occurs when a source text of a segment is exactly the same as the source text of a segment that was translated previously. + + + + + Indicates a fuzzy match. A fuzzy match occurs when a source text of a segment is very similar to the source text of a segment that was translated previously (e.g. when the difference is casing, a few changed words, white-space discripancy, etc.). + + + + + Indicates a match based on matching IDs (in addition to matching text). + + + + + Indicates a translation derived from a glossary. + + + + + Indicates a translation derived from existing translation. + + + + + Indicates a translation derived from machine translation. + + + + + Indicates a translation derived from a translation repository. + + + + + Indicates a translation derived from a translation memory. + + + + + Indicates the translation is suggested by machine translation. + + + + + Indicates that the item has been rejected because of incorrect grammar. + + + + + Indicates that the item has been rejected because it is incorrect. + + + + + Indicates that the item has been rejected because it is too long or too short. + + + + + Indicates that the item has been rejected because of incorrect spelling. + + + + + Indicates the translation is suggested by translation memory. + + + + + + + Values for the attribute 'unit'. + + + + + Refers to words. + + + + + Refers to pages. + + + + + Refers to <trans-unit> elements. + + + + + Refers to <bin-unit> elements. + + + + + Refers to glyphs. + + + + + Refers to <trans-unit> and/or <bin-unit> elements. + + + + + Refers to the occurrences of instances defined by the count-type value. + + + + + Refers to characters. + + + + + Refers to lines. + + + + + Refers to sentences. + + + + + Refers to paragraphs. + + + + + Refers to segments. + + + + + Refers to placeables (inline elements). + + + + + + + Values for the attribute 'priority'. + + + + + Highest priority. + + + + + High priority. + + + + + High priority, but not as important as 2. + + + + + High priority, but not as important as 3. + + + + + Medium priority, but more important than 6. + + + + + Medium priority, but less important than 5. + + + + + Low priority, but more important than 8. + + + + + Low priority, but more important than 9. + + + + + Low priority. + + + + + Lowest priority. + + + + + + + + + This value indicates that all properties can be reformatted. This value must be used alone. + + + + + This value indicates that no properties should be reformatted. This value must be used alone. + + + + + + + + + + + + + This value indicates that all information in the coord attribute can be modified. + + + + + This value indicates that the x information in the coord attribute can be modified. + + + + + This value indicates that the y information in the coord attribute can be modified. + + + + + This value indicates that the cx information in the coord attribute can be modified. + + + + + This value indicates that the cy information in the coord attribute can be modified. + + + + + This value indicates that all the information in the font attribute can be modified. + + + + + This value indicates that the name information in the font attribute can be modified. + + + + + This value indicates that the size information in the font attribute can be modified. + + + + + This value indicates that the weight information in the font attribute can be modified. + + + + + This value indicates that the information in the css-style attribute can be modified. + + + + + This value indicates that the information in the style attribute can be modified. + + + + + This value indicates that the information in the exstyle attribute can be modified. + + + + + + + + + + + + + Indicates that the context is informational in nature, specifying for example, how a term should be translated. Thus, should be displayed to anyone editing the XLIFF document. + + + + + Indicates that the context-group is used to specify where the term was found in the translatable source. Thus, it is not displayed. + + + + + Indicates that the context information should be used during translation memory lookups. Thus, it is not displayed. + + + + + + + + + Represents a translation proposal from a translation memory or other resource. + + + + + Represents a previous version of the target element. + + + + + Represents a rejected version of the target element. + + + + + Represents a translation to be used for reference purposes only, for example from a related product or a different language. + + + + + Represents a proposed translation that was used for the translation of the trans-unit, possibly modified. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Values for the attribute 'coord'. + + + + + + + + Version values: 1.0 and 1.1 are allowed for backward compatibility. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff -r e200cb7efeb3 -r c2387f117808 vendor/symfony/translation/composer.json --- a/vendor/symfony/translation/composer.json Thu Apr 26 11:26:54 2018 +0100 +++ b/vendor/symfony/translation/composer.json Tue Jul 10 15:07:59 2018 +0100 @@ -35,7 +35,7 @@ "suggest": { "symfony/config": "", "symfony/yaml": "", - "psr/log": "To use logging capability in translator" + "psr/log-implementation": "To use logging capability in translator" }, "autoload": { "psr-4": { "Symfony\\Component\\Translation\\": "" }, diff -r e200cb7efeb3 -r c2387f117808 vendor/symfony/validator/Constraints/UrlValidator.php --- a/vendor/symfony/validator/Constraints/UrlValidator.php Thu Apr 26 11:26:54 2018 +0100 +++ b/vendor/symfony/validator/Constraints/UrlValidator.php Tue Jul 10 15:07:59 2018 +0100 @@ -92,7 +92,7 @@ Url::CHECK_DNS_TYPE_SOA, Url::CHECK_DNS_TYPE_SRV, Url::CHECK_DNS_TYPE_TXT, - ))) { + ), true)) { throw new InvalidOptionsException(sprintf('Invalid value for option "checkDNS" in constraint %s', get_class($constraint)), array('checkDNS')); } diff -r e200cb7efeb3 -r c2387f117808 vendor/symfony/validator/Mapping/ClassMetadata.php --- a/vendor/symfony/validator/Mapping/ClassMetadata.php Thu Apr 26 11:26:54 2018 +0100 +++ b/vendor/symfony/validator/Mapping/ClassMetadata.php Tue Jul 10 15:07:59 2018 +0100 @@ -335,7 +335,7 @@ /** * Merges the constraints of the given metadata into this object. */ - public function mergeConstraints(ClassMetadata $source) + public function mergeConstraints(self $source) { if ($source->isGroupSequenceProvider()) { $this->setGroupSequenceProvider(true); diff -r e200cb7efeb3 -r c2387f117808 vendor/symfony/validator/Mapping/Factory/LazyLoadingMetadataFactory.php --- a/vendor/symfony/validator/Mapping/Factory/LazyLoadingMetadataFactory.php Thu Apr 26 11:26:54 2018 +0100 +++ b/vendor/symfony/validator/Mapping/Factory/LazyLoadingMetadataFactory.php Tue Jul 10 15:07:59 2018 +0100 @@ -88,6 +88,10 @@ return $this->loadedClasses[$class]; } + if (!class_exists($class) && !interface_exists($class, false)) { + throw new NoSuchMetadataException(sprintf('The class or interface "%s" does not exist.', $class)); + } + if (null !== $this->cache && false !== ($metadata = $this->cache->read($class))) { // Include constraints from the parent class $this->mergeConstraints($metadata); @@ -95,10 +99,6 @@ return $this->loadedClasses[$class] = $metadata; } - if (!class_exists($class) && !interface_exists($class)) { - throw new NoSuchMetadataException(sprintf('The class or interface "%s" does not exist.', $class)); - } - $metadata = new ClassMetadata($class); if (null !== $this->loader) { @@ -160,10 +160,6 @@ $class = ltrim(is_object($value) ? get_class($value) : $value, '\\'); - if (class_exists($class) || interface_exists($class)) { - return true; - } - - return false; + return class_exists($class) || interface_exists($class, false); } } diff -r e200cb7efeb3 -r c2387f117808 vendor/symfony/validator/ObjectInitializerInterface.php --- a/vendor/symfony/validator/ObjectInitializerInterface.php Thu Apr 26 11:26:54 2018 +0100 +++ b/vendor/symfony/validator/ObjectInitializerInterface.php Tue Jul 10 15:07:59 2018 +0100 @@ -14,7 +14,7 @@ /** * Prepares an object for validation. * - * Concrete implementations of this interface are used by {@link ValidationVisitorInterface} + * Concrete implementations of this interface are used by {@link Validator\ContextualValidatorInterface} * to initialize objects just before validating them. * * @author Fabien Potencier diff -r e200cb7efeb3 -r c2387f117808 vendor/symfony/validator/composer.json --- a/vendor/symfony/validator/composer.json Thu Apr 26 11:26:54 2018 +0100 +++ b/vendor/symfony/validator/composer.json Tue Jul 10 15:07:59 2018 +0100 @@ -17,6 +17,7 @@ ], "require": { "php": "^5.5.9|>=7.0.8", + "symfony/polyfill-ctype": "~1.8", "symfony/polyfill-mbstring": "~1.0", "symfony/translation": "~2.8|~3.0|~4.0" }, diff -r e200cb7efeb3 -r c2387f117808 vendor/symfony/var-dumper/Caster/SplCaster.php --- a/vendor/symfony/var-dumper/Caster/SplCaster.php Thu Apr 26 11:26:54 2018 +0100 +++ b/vendor/symfony/var-dumper/Caster/SplCaster.php Tue Jul 10 15:07:59 2018 +0100 @@ -29,30 +29,12 @@ public static function castArrayObject(\ArrayObject $c, array $a, Stub $stub, $isNested) { - $prefix = Caster::PREFIX_VIRTUAL; - $class = $stub->class; - $flags = $c->getFlags(); + return self::castSplArray($c, $a, $stub, $isNested); + } - $b = array( - $prefix.'flag::STD_PROP_LIST' => (bool) ($flags & \ArrayObject::STD_PROP_LIST), - $prefix.'flag::ARRAY_AS_PROPS' => (bool) ($flags & \ArrayObject::ARRAY_AS_PROPS), - $prefix.'iteratorClass' => new ClassStub($c->getIteratorClass()), - $prefix.'storage' => $c->getArrayCopy(), - ); - - if ('ArrayObject' === $class) { - $a = $b; - } else { - if (!($flags & \ArrayObject::STD_PROP_LIST)) { - $c->setFlags(\ArrayObject::STD_PROP_LIST); - $a = Caster::castObject($c, $class); - $c->setFlags($flags); - } - - $a += $b; - } - - return $a; + public static function castArrayIterator(\ArrayIterator $c, array $a, Stub $stub, $isNested) + { + return self::castSplArray($c, $a, $stub, $isNested); } public static function castHeap(\Iterator $c, array $a, Stub $stub, $isNested) @@ -184,10 +166,11 @@ $storage = array(); unset($a[Caster::PREFIX_DYNAMIC."\0gcdata"]); // Don't hit https://bugs.php.net/65967 - foreach (clone $c as $obj) { - $storage[spl_object_hash($obj)] = array( + $clone = clone $c; + foreach ($clone as $obj) { + $storage[] = array( 'object' => $obj, - 'info' => $c->getInfo(), + 'info' => $clone->getInfo(), ); } @@ -204,4 +187,27 @@ return $a; } + + private static function castSplArray($c, array $a, Stub $stub, $isNested) + { + $prefix = Caster::PREFIX_VIRTUAL; + $class = $stub->class; + $flags = $c->getFlags(); + + if (!($flags & \ArrayObject::STD_PROP_LIST)) { + $c->setFlags(\ArrayObject::STD_PROP_LIST); + $a = Caster::castObject($c, $class); + $c->setFlags($flags); + } + $a += array( + $prefix.'flag::STD_PROP_LIST' => (bool) ($flags & \ArrayObject::STD_PROP_LIST), + $prefix.'flag::ARRAY_AS_PROPS' => (bool) ($flags & \ArrayObject::ARRAY_AS_PROPS), + ); + if ($c instanceof \ArrayObject) { + $a[$prefix.'iteratorClass'] = new ClassStub($c->getIteratorClass()); + } + $a[$prefix.'storage'] = $c->getArrayCopy(); + + return $a; + } } diff -r e200cb7efeb3 -r c2387f117808 vendor/symfony/var-dumper/Cloner/AbstractCloner.php --- a/vendor/symfony/var-dumper/Cloner/AbstractCloner.php Thu Apr 26 11:26:54 2018 +0100 +++ b/vendor/symfony/var-dumper/Cloner/AbstractCloner.php Tue Jul 10 15:07:59 2018 +0100 @@ -95,6 +95,7 @@ 'AMQPEnvelope' => array('Symfony\Component\VarDumper\Caster\AmqpCaster', 'castEnvelope'), 'ArrayObject' => array('Symfony\Component\VarDumper\Caster\SplCaster', 'castArrayObject'), + 'ArrayIterator' => array('Symfony\Component\VarDumper\Caster\SplCaster', 'castArrayIterator'), 'SplDoublyLinkedList' => array('Symfony\Component\VarDumper\Caster\SplCaster', 'castDoublyLinkedList'), 'SplFileInfo' => array('Symfony\Component\VarDumper\Caster\SplCaster', 'castFileInfo'), 'SplFileObject' => array('Symfony\Component\VarDumper\Caster\SplCaster', 'castFileObject'), diff -r e200cb7efeb3 -r c2387f117808 vendor/symfony/var-dumper/Dumper/CliDumper.php --- a/vendor/symfony/var-dumper/Dumper/CliDumper.php Thu Apr 26 11:26:54 2018 +0100 +++ b/vendor/symfony/var-dumper/Dumper/CliDumper.php Tue Jul 10 15:07:59 2018 +0100 @@ -62,7 +62,7 @@ { parent::__construct($output, $charset, $flags); - if ('\\' === DIRECTORY_SEPARATOR && 'ON' !== @getenv('ConEmuANSI') && 'xterm' !== @getenv('TERM')) { + if ('\\' === DIRECTORY_SEPARATOR && !$this->isWindowsTrueColor()) { // Use only the base 16 xterm colors when using ANSICON or standard Windows 10 CLI $this->setStyles(array( 'default' => '31', @@ -467,7 +467,7 @@ protected function supportsColors() { if ($this->outputStream !== static::$defaultOutput) { - return @(is_resource($this->outputStream) && function_exists('posix_isatty') && posix_isatty($this->outputStream)); + return $this->hasColorSupport($this->outputStream); } if (null !== static::$defaultColors) { return static::$defaultColors; @@ -495,23 +495,10 @@ } } - if ('\\' === DIRECTORY_SEPARATOR) { - static::$defaultColors = @( - function_exists('sapi_windows_vt100_support') && sapi_windows_vt100_support($this->outputStream) - || '10.0.10586' === PHP_WINDOWS_VERSION_MAJOR.'.'.PHP_WINDOWS_VERSION_MINOR.'.'.PHP_WINDOWS_VERSION_BUILD - || false !== getenv('ANSICON') - || 'ON' === getenv('ConEmuANSI') - || 'xterm' === getenv('TERM') - ); - } elseif (function_exists('posix_isatty')) { - $h = stream_get_meta_data($this->outputStream) + array('wrapper_type' => null); - $h = 'Output' === $h['stream_type'] && 'PHP' === $h['wrapper_type'] ? fopen('php://stdout', 'wb') : $this->outputStream; - static::$defaultColors = @posix_isatty($h); - } else { - static::$defaultColors = false; - } + $h = stream_get_meta_data($this->outputStream) + array('wrapper_type' => null); + $h = 'Output' === $h['stream_type'] && 'PHP' === $h['wrapper_type'] ? fopen('php://stdout', 'wb') : $this->outputStream; - return static::$defaultColors; + return static::$defaultColors = $this->hasColorSupport($h); } /** @@ -537,4 +524,69 @@ $this->dumpLine($cursor->depth, true); } + + /** + * Returns true if the stream supports colorization. + * + * Reference: Composer\XdebugHandler\Process::supportsColor + * https://github.com/composer/xdebug-handler + * + * @param mixed $stream A CLI output stream + * + * @return bool + */ + private function hasColorSupport($stream) + { + if (!is_resource($stream) || 'stream' !== get_resource_type($stream)) { + return false; + } + + if (DIRECTORY_SEPARATOR === '\\') { + return (function_exists('sapi_windows_vt100_support') + && @sapi_windows_vt100_support($stream)) + || false !== getenv('ANSICON') + || 'ON' === getenv('ConEmuANSI') + || 'xterm' === getenv('TERM'); + } + + if (function_exists('stream_isatty')) { + return @stream_isatty($stream); + } + + if (function_exists('posix_isatty')) { + return @posix_isatty($stream); + } + + $stat = @fstat($stream); + // Check if formatted mode is S_IFCHR + return $stat ? 0020000 === ($stat['mode'] & 0170000) : false; + } + + /** + * Returns true if the Windows terminal supports true color. + * + * Note that this does not check an output stream, but relies on environment + * variables from known implementations, or a PHP and Windows version that + * supports true color. + * + * @return bool + */ + private function isWindowsTrueColor() + { + $result = 183 <= getenv('ANSICON_VER') + || 'ON' === getenv('ConEmuANSI') + || 'xterm' === getenv('TERM'); + + if (!$result && PHP_VERSION_ID >= 70200) { + $version = sprintf( + '%s.%s.%s', + PHP_WINDOWS_VERSION_MAJOR, + PHP_WINDOWS_VERSION_MINOR, + PHP_WINDOWS_VERSION_BUILD + ); + $result = $version >= '10.0.15063'; + } + + return $result; + } } diff -r e200cb7efeb3 -r c2387f117808 vendor/symfony/var-dumper/Dumper/HtmlDumper.php --- a/vendor/symfony/var-dumper/Dumper/HtmlDumper.php Thu Apr 26 11:26:54 2018 +0100 +++ b/vendor/symfony/var-dumper/Dumper/HtmlDumper.php Tue Jul 10 15:07:59 2018 +0100 @@ -310,6 +310,9 @@ return "concat(" + parts.join(",") + ", '')"; } + function xpathHasClass(className) { + return "contains(concat(' ', normalize-space(@class), ' '), ' " + className +" ')"; + } addEventListener(root, 'mouseover', function (e) { if ('' != refStyle.innerHTML) { refStyle.innerHTML = ''; @@ -516,7 +519,15 @@ return; } - var xpathResult = doc.evaluate('//pre[@id="' + root.id + '"]//span[@class="sf-dump-str" or @class="sf-dump-key" or @class="sf-dump-public" or @class="sf-dump-protected" or @class="sf-dump-private"][contains(translate(child::text(), ' + xpathString(searchQuery.toUpperCase()) + ', ' + xpathString(searchQuery.toLowerCase()) + '), ' + xpathString(searchQuery.toLowerCase()) + ')]', document, null, XPathResult.ORDERED_NODE_ITERATOR_TYPE, null); + var classMatches = [ + "sf-dump-str", + "sf-dump-key", + "sf-dump-public", + "sf-dump-protected", + "sf-dump-private", + ].map(xpathHasClass).join(' or '); + + var xpathResult = doc.evaluate('.//span[' + classMatches + '][contains(translate(child::text(), ' + xpathString(searchQuery.toUpperCase()) + ', ' + xpathString(searchQuery.toLowerCase()) + '), ' + xpathString(searchQuery.toLowerCase()) + ')]', root, null, XPathResult.ORDERED_NODE_ITERATOR_TYPE, null); while (node = xpathResult.iterateNext()) state.nodes.push(node); diff -r e200cb7efeb3 -r c2387f117808 vendor/symfony/var-dumper/Tests/Caster/SplCasterTest.php --- a/vendor/symfony/var-dumper/Tests/Caster/SplCasterTest.php Thu Apr 26 11:26:54 2018 +0100 +++ b/vendor/symfony/var-dumper/Tests/Caster/SplCasterTest.php Tue Jul 10 15:07:59 2018 +0100 @@ -144,4 +144,70 @@ array(\SplDoublyLinkedList::IT_MODE_LIFO | \SplDoublyLinkedList::IT_MODE_DELETE, 'IT_MODE_LIFO | IT_MODE_DELETE'), ); } + + public function testCastObjectStorageIsntModified() + { + $var = new \SplObjectStorage(); + $var->attach(new \stdClass()); + $var->rewind(); + $current = $var->current(); + + $this->assertDumpMatchesFormat('%A', $var); + $this->assertSame($current, $var->current()); + } + + public function testCastObjectStorageDumpsInfo() + { + $var = new \SplObjectStorage(); + $var->attach(new \stdClass(), new \DateTime()); + + $this->assertDumpMatchesFormat('%ADateTime%A', $var); + } + + public function testCastArrayObject() + { + if (\defined('HHVM_VERSION')) { + $this->markTestSkipped('HHVM as different internal details.'); + } + $var = new \ArrayObject(array(123)); + $var->foo = 234; + + $expected = << 123 + ] } +EOTXT; + $this->assertDumpEquals($expected, $var); + } + + public function testArrayIterator() + { + if (\defined('HHVM_VERSION')) { + $this->markTestSkipped('HHVM as different internal details.'); + } + $var = new MyArrayIterator(array(234)); + + $expected = << 234 + ] +} +EOTXT; + $this->assertDumpEquals($expected, $var); + } +} + +class MyArrayIterator extends \ArrayIterator +{ + private $foo = 123; +} diff -r e200cb7efeb3 -r c2387f117808 vendor/symfony/yaml/Command/LintCommand.php --- a/vendor/symfony/yaml/Command/LintCommand.php Thu Apr 26 11:26:54 2018 +0100 +++ b/vendor/symfony/yaml/Command/LintCommand.php Tue Jul 10 15:07:59 2018 +0100 @@ -12,6 +12,8 @@ namespace Symfony\Component\Yaml\Command; use Symfony\Component\Console\Command\Command; +use Symfony\Component\Console\Exception\InvalidArgumentException; +use Symfony\Component\Console\Exception\RuntimeException; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Output\OutputInterface; @@ -86,14 +88,14 @@ if (!$filename) { if (!$stdin = $this->getStdin()) { - throw new \RuntimeException('Please provide a filename or pipe file content to STDIN.'); + throw new RuntimeException('Please provide a filename or pipe file content to STDIN.'); } return $this->display($io, array($this->validate($stdin, $flags))); } if (!$this->isReadable($filename)) { - throw new \RuntimeException(sprintf('File or directory "%s" is not readable.', $filename)); + throw new RuntimeException(sprintf('File or directory "%s" is not readable.', $filename)); } $filesInfo = array(); @@ -133,7 +135,7 @@ case 'json': return $this->displayJson($io, $files); default: - throw new \InvalidArgumentException(sprintf('The format "%s" is not supported.', $this->format)); + throw new InvalidArgumentException(sprintf('The format "%s" is not supported.', $this->format)); } } diff -r e200cb7efeb3 -r c2387f117808 vendor/symfony/yaml/Inline.php --- a/vendor/symfony/yaml/Inline.php Thu Apr 26 11:26:54 2018 +0100 +++ b/vendor/symfony/yaml/Inline.php Tue Jul 10 15:07:59 2018 +0100 @@ -324,6 +324,9 @@ if (null !== $delimiters) { $tmp = ltrim(substr($scalar, $i), ' '); + if ('' === $tmp) { + throw new ParseException(sprintf('Unexpected end of line, expected one of "%s".', implode($delimiters)), self::$parsedLineNumber + 1, $scalar, self::$parsedFilename); + } if (!in_array($tmp[0], $delimiters)) { throw new ParseException(sprintf('Unexpected characters (%s).', substr($scalar, $i)), self::$parsedLineNumber + 1, $scalar, self::$parsedFilename); } diff -r e200cb7efeb3 -r c2387f117808 vendor/symfony/yaml/composer.json --- a/vendor/symfony/yaml/composer.json Thu Apr 26 11:26:54 2018 +0100 +++ b/vendor/symfony/yaml/composer.json Tue Jul 10 15:07:59 2018 +0100 @@ -16,7 +16,8 @@ } ], "require": { - "php": "^5.5.9|>=7.0.8" + "php": "^5.5.9|>=7.0.8", + "symfony/polyfill-ctype": "~1.8" }, "require-dev": { "symfony/console": "~3.4|~4.0" diff -r e200cb7efeb3 -r c2387f117808 vendor/zendframework/zend-diactoros/CHANGELOG.md --- a/vendor/zendframework/zend-diactoros/CHANGELOG.md Thu Apr 26 11:26:54 2018 +0100 +++ b/vendor/zendframework/zend-diactoros/CHANGELOG.md Tue Jul 10 15:07:59 2018 +0100 @@ -2,6 +2,130 @@ All notable changes to this project will be documented in this file, in reverse chronological order by release. +## 1.8.1 - 2018-07-09 + +### Added + +- Nothing. + +### Changed + +- [#313](https://github.com/zendframework/zend-diactoros/pull/313) changes the reason phrase associated with the status code 425 + to "Too Early", corresponding to a new definition of the code as specified by the IANA. + +### Deprecated + +- Nothing. + +### Removed + +- Nothing. + +### Fixed + +- [#312](https://github.com/zendframework/zend-diactoros/pull/312) fixes how the `normalizeUploadedFiles()` utility function handles nested trees of + uploaded files, ensuring it detects them properly. + +## 1.8.0 - 2018-06-27 + +### Added + +- [#307](https://github.com/zendframework/zend-diactoros/pull/307) adds the following functions under the `Zend\Diactoros` namespace, each of + which may be used to derive artifacts from SAPI supergloabls for the purposes + of generating a `ServerRequest` instance: + - `normalizeServer(array $server, callable $apacheRequestHeaderCallback = null) : array` + (main purpose is to aggregate the `Authorization` header in the SAPI params + when under Apache) + - `marshalProtocolVersionFromSapi(array $server) : string` + - `marshalMethodFromSapi(array $server) : string` + - `marshalUriFromSapi(array $server, array $headers) : Uri` + - `marshalHeadersFromSapi(array $server) : array` + - `parseCookieHeader(string $header) : array` + - `createUploadedFile(array $spec) : UploadedFile` (creates the instance from + a normal `$_FILES` entry) + - `normalizeUploadedFiles(array $files) : UploadedFileInterface[]` (traverses + a potentially nested array of uploaded file instances and/or `$_FILES` + entries, including those aggregated under mod_php, php-fpm, and php-cgi in + order to create a flat array of `UploadedFileInterface` instances to use in a + request) + +### Changed + +- Nothing. + +### Deprecated + +- [#307](https://github.com/zendframework/zend-diactoros/pull/307) deprecates `ServerRequestFactory::normalizeServer()`; the method is + no longer used internally, and users should instead use `Zend\Diactoros\normalizeServer()`, + to which it proxies. + +- [#307](https://github.com/zendframework/zend-diactoros/pull/307) deprecates `ServerRequestFactory::marshalHeaders()`; the method is + no longer used internally, and users should instead use `Zend\Diactoros\marshalHeadersFromSapi()`, + to which it proxies. + +- [#307](https://github.com/zendframework/zend-diactoros/pull/307) deprecates `ServerRequestFactory::marshalUriFromServer()`; the method + is no longer used internally. Users should use `marshalUriFromSapi()` instead. + +- [#307](https://github.com/zendframework/zend-diactoros/pull/307) deprecates `ServerRequestFactory::marshalRequestUri()`. the method is no longer + used internally, and currently proxies to `marshalUriFromSapi()`, pulling the + discovered path from the `Uri` instance returned by that function. Users + should use `marshalUriFromSapi()` instead. + +- [#307](https://github.com/zendframework/zend-diactoros/pull/307) deprecates `ServerRequestFactory::marshalHostAndPortFromHeaders()`; the method + is no longer used internally, and currently proxies to `marshalUriFromSapi()`, + pulling the discovered host and port from the `Uri` instance returned by that + function. Users should use `marshalUriFromSapi()` instead. + +- [#307](https://github.com/zendframework/zend-diactoros/pull/307) deprecates `ServerRequestFactory::getHeader()`; the method is no longer + used internally. Users should copy and paste the functionality into their own + applications if needed, or rely on headers from a fully-populated `Uri` + instance instead. + +- [#307](https://github.com/zendframework/zend-diactoros/pull/307) deprecates `ServerRequestFactory::stripQueryString()`; the method is no longer + used internally, and users can mimic the functionality via the expression + `$path = explode('?', $path, 2)[0];`. + +- [#307](https://github.com/zendframework/zend-diactoros/pull/307) deprecates `ServerRequestFactory::normalizeFiles()`; the functionality + is no longer used internally, and users can use `normalizeUploadedFiles()` as + a replacement. + +- [#303](https://github.com/zendframework/zend-diactoros/pull/303) deprecates `Zend\Diactoros\Response\EmitterInterface` and its various implementations. These are now provided via the + [zendframework/zend-httphandlerrunner](https://docs.zendframework.com/zend-httphandlerrunner) package as 1:1 substitutions. + +- [#303](https://github.com/zendframework/zend-diactoros/pull/303) deprecates the `Zend\Diactoros\Server` class. Users are directed to the `RequestHandlerRunner` class from the + [zendframework/zend-httphandlerrunner](https://docs.zendframework.com/zend-httphandlerrunner) package as an alternative. + +### Removed + +- Nothing. + +### Fixed + +- Nothing. + +## 1.7.2 - 2018-05-29 + +### Added + +- Nothing. + +### Changed + +- Nothing. + +### Deprecated + +- Nothing. + +### Removed + +- Nothing. + +### Fixed + +- [#301](https://github.com/zendframework/zend-diactoros/pull/301) adds stricter comparisons within the `uri` class to ensure non-empty + values are not treated as empty. + ## 1.7.1 - 2018-02-26 ### Added diff -r e200cb7efeb3 -r c2387f117808 vendor/zendframework/zend-diactoros/composer.json --- a/vendor/zendframework/zend-diactoros/composer.json Thu Apr 26 11:26:54 2018 +0100 +++ b/vendor/zendframework/zend-diactoros/composer.json Tue Jul 10 15:07:59 2018 +0100 @@ -18,8 +18,9 @@ }, "extra": { "branch-alias": { - "dev-master": "1.7.x-dev", - "dev-develop": "1.8.x-dev" + "dev-master": "1.8.x-dev", + "dev-develop": "1.9.x-dev", + "dev-release-2.0": "2.0.x-dev" } }, "require": { @@ -36,6 +37,16 @@ "psr/http-message-implementation": "1.0" }, "autoload": { + "files": [ + "src/functions/create_uploaded_file.php", + "src/functions/marshal_headers_from_sapi.php", + "src/functions/marshal_method_from_sapi.php", + "src/functions/marshal_protocol_version_from_sapi.php", + "src/functions/marshal_uri_from_sapi.php", + "src/functions/normalize_server.php", + "src/functions/normalize_uploaded_files.php", + "src/functions/parse_cookie_header.php" + ], "psr-4": { "Zend\\Diactoros\\": "src/" } diff -r e200cb7efeb3 -r c2387f117808 vendor/zendframework/zend-diactoros/composer.lock --- a/vendor/zendframework/zend-diactoros/composer.lock Thu Apr 26 11:26:54 2018 +0100 +++ b/vendor/zendframework/zend-diactoros/composer.lock Tue Jul 10 15:07:59 2018 +0100 @@ -1,10 +1,10 @@ { "_readme": [ "This file locks the dependencies of your project to a known state", - "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", + "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "de254758c5d28198ad8441fb154fc7f3", + "content-hash": "6a979d48e42840de5442a250eb48ea3c", "packages": [ { "name": "psr/http-message", diff -r e200cb7efeb3 -r c2387f117808 vendor/zendframework/zend-diactoros/src/AbstractSerializer.php --- a/vendor/zendframework/zend-diactoros/src/AbstractSerializer.php Thu Apr 26 11:26:54 2018 +0100 +++ b/vendor/zendframework/zend-diactoros/src/AbstractSerializer.php Tue Jul 10 15:07:59 2018 +0100 @@ -12,6 +12,14 @@ use Psr\Http\Message\StreamInterface; use UnexpectedValueException; +use function array_pop; +use function implode; +use function ltrim; +use function preg_match; +use function sprintf; +use function str_replace; +use function ucwords; + /** * Provides base functionality for request and response de/serialization * strategies, including functionality for retrieving a line at a time from diff -r e200cb7efeb3 -r c2387f117808 vendor/zendframework/zend-diactoros/src/CallbackStream.php --- a/vendor/zendframework/zend-diactoros/src/CallbackStream.php Thu Apr 26 11:26:54 2018 +0100 +++ b/vendor/zendframework/zend-diactoros/src/CallbackStream.php Tue Jul 10 15:07:59 2018 +0100 @@ -10,8 +10,12 @@ namespace Zend\Diactoros; use InvalidArgumentException; +use Psr\Http\Message\StreamInterface; use RuntimeException; -use Psr\Http\Message\StreamInterface; + +use function array_key_exists; + +use const SEEK_SET; /** * Implementation of PSR HTTP streams diff -r e200cb7efeb3 -r c2387f117808 vendor/zendframework/zend-diactoros/src/HeaderSecurity.php --- a/vendor/zendframework/zend-diactoros/src/HeaderSecurity.php Thu Apr 26 11:26:54 2018 +0100 +++ b/vendor/zendframework/zend-diactoros/src/HeaderSecurity.php Tue Jul 10 15:07:59 2018 +0100 @@ -9,6 +9,17 @@ use InvalidArgumentException; +use function get_class; +use function gettype; +use function in_array; +use function is_numeric; +use function is_object; +use function is_string; +use function ord; +use function preg_match; +use function sprintf; +use function strlen; + /** * Provide security tools around HTTP headers to prevent common injection vectors. * diff -r e200cb7efeb3 -r c2387f117808 vendor/zendframework/zend-diactoros/src/MessageTrait.php --- a/vendor/zendframework/zend-diactoros/src/MessageTrait.php Thu Apr 26 11:26:54 2018 +0100 +++ b/vendor/zendframework/zend-diactoros/src/MessageTrait.php Tue Jul 10 15:07:59 2018 +0100 @@ -10,6 +10,19 @@ use InvalidArgumentException; use Psr\Http\Message\StreamInterface; +use function array_map; +use function array_merge; +use function get_class; +use function gettype; +use function implode; +use function is_array; +use function is_object; +use function is_resource; +use function is_string; +use function preg_match; +use function sprintf; +use function strtolower; + /** * Trait implementing the various methods defined in MessageInterface. * diff -r e200cb7efeb3 -r c2387f117808 vendor/zendframework/zend-diactoros/src/PhpInputStream.php --- a/vendor/zendframework/zend-diactoros/src/PhpInputStream.php Thu Apr 26 11:26:54 2018 +0100 +++ b/vendor/zendframework/zend-diactoros/src/PhpInputStream.php Tue Jul 10 15:07:59 2018 +0100 @@ -7,6 +7,8 @@ namespace Zend\Diactoros; +use function stream_get_contents; + /** * Caching version of php://input */ diff -r e200cb7efeb3 -r c2387f117808 vendor/zendframework/zend-diactoros/src/RelativeStream.php --- a/vendor/zendframework/zend-diactoros/src/RelativeStream.php Thu Apr 26 11:26:54 2018 +0100 +++ b/vendor/zendframework/zend-diactoros/src/RelativeStream.php Tue Jul 10 15:07:59 2018 +0100 @@ -10,6 +10,8 @@ use Psr\Http\Message\StreamInterface; use RuntimeException; +use const SEEK_SET; + /** * Class RelativeStream * diff -r e200cb7efeb3 -r c2387f117808 vendor/zendframework/zend-diactoros/src/Request.php --- a/vendor/zendframework/zend-diactoros/src/Request.php Thu Apr 26 11:26:54 2018 +0100 +++ b/vendor/zendframework/zend-diactoros/src/Request.php Tue Jul 10 15:07:59 2018 +0100 @@ -11,6 +11,8 @@ use Psr\Http\Message\StreamInterface; use Psr\Http\Message\UriInterface; +use function strtolower; + /** * HTTP Request encapsulation * diff -r e200cb7efeb3 -r c2387f117808 vendor/zendframework/zend-diactoros/src/Request/ArraySerializer.php --- a/vendor/zendframework/zend-diactoros/src/Request/ArraySerializer.php Thu Apr 26 11:26:54 2018 +0100 +++ b/vendor/zendframework/zend-diactoros/src/Request/ArraySerializer.php Tue Jul 10 15:07:59 2018 +0100 @@ -12,6 +12,8 @@ use Zend\Diactoros\Request; use Zend\Diactoros\Stream; +use function sprintf; + /** * Serialize or deserialize request messages to/from arrays. * diff -r e200cb7efeb3 -r c2387f117808 vendor/zendframework/zend-diactoros/src/Request/Serializer.php --- a/vendor/zendframework/zend-diactoros/src/Request/Serializer.php Thu Apr 26 11:26:54 2018 +0100 +++ b/vendor/zendframework/zend-diactoros/src/Request/Serializer.php Tue Jul 10 15:07:59 2018 +0100 @@ -18,6 +18,9 @@ use Zend\Diactoros\Stream; use Zend\Diactoros\Uri; +use function preg_match; +use function sprintf; + /** * Serialize (cast to string) or deserialize (cast string to Request) messages. * diff -r e200cb7efeb3 -r c2387f117808 vendor/zendframework/zend-diactoros/src/RequestTrait.php --- a/vendor/zendframework/zend-diactoros/src/RequestTrait.php Thu Apr 26 11:26:54 2018 +0100 +++ b/vendor/zendframework/zend-diactoros/src/RequestTrait.php Tue Jul 10 15:07:59 2018 +0100 @@ -11,6 +11,15 @@ use Psr\Http\Message\StreamInterface; use Psr\Http\Message\UriInterface; +use function array_keys; +use function get_class; +use function gettype; +use function is_object; +use function is_string; +use function preg_match; +use function sprintf; +use function strtolower; + /** * Trait with common request behaviors. * diff -r e200cb7efeb3 -r c2387f117808 vendor/zendframework/zend-diactoros/src/Response.php --- a/vendor/zendframework/zend-diactoros/src/Response.php Thu Apr 26 11:26:54 2018 +0100 +++ b/vendor/zendframework/zend-diactoros/src/Response.php Tue Jul 10 15:07:59 2018 +0100 @@ -11,6 +11,12 @@ use Psr\Http\Message\ResponseInterface; use Psr\Http\Message\StreamInterface; +use function gettype; +use function is_float; +use function is_numeric; +use function is_scalar; +use function sprintf; + /** * HTTP response encapsulation. * @@ -81,7 +87,7 @@ 422 => 'Unprocessable Entity', 423 => 'Locked', 424 => 'Failed Dependency', - 425 => 'Unordered Collection', + 425 => 'Too Early', 426 => 'Upgrade Required', 428 => 'Precondition Required', 429 => 'Too Many Requests', diff -r e200cb7efeb3 -r c2387f117808 vendor/zendframework/zend-diactoros/src/Response/ArraySerializer.php --- a/vendor/zendframework/zend-diactoros/src/Response/ArraySerializer.php Thu Apr 26 11:26:54 2018 +0100 +++ b/vendor/zendframework/zend-diactoros/src/Response/ArraySerializer.php Tue Jul 10 15:07:59 2018 +0100 @@ -12,6 +12,8 @@ use Zend\Diactoros\Response; use Zend\Diactoros\Stream; +use function sprintf; + /** * Serialize or deserialize response messages to/from arrays. * diff -r e200cb7efeb3 -r c2387f117808 vendor/zendframework/zend-diactoros/src/Response/EmitterInterface.php --- a/vendor/zendframework/zend-diactoros/src/Response/EmitterInterface.php Thu Apr 26 11:26:54 2018 +0100 +++ b/vendor/zendframework/zend-diactoros/src/Response/EmitterInterface.php Tue Jul 10 15:07:59 2018 +0100 @@ -1,9 +1,7 @@ $value) { - if ($value instanceof UploadedFileInterface) { - $normalized[$key] = $value; - continue; - } - - if (is_array($value) && isset($value['tmp_name'])) { - $normalized[$key] = self::createUploadedFileFromSpec($value); - continue; - } - - if (is_array($value)) { - $normalized[$key] = self::normalizeFiles($value); - continue; - } - - throw new InvalidArgumentException('Invalid value in files specification'); - } - return $normalized; + return normalizeUploadedFiles($files); } /** * Marshal headers from $_SERVER * + * @deprecated since 1.8.0; use Zend\Diactoros\marshalHeadersFromSapi(). * @param array $server * @return array */ public static function marshalHeaders(array $server) { - $headers = []; - foreach ($server as $key => $value) { - // Apache prefixes environment variables with REDIRECT_ - // if they are added by rewrite rules - if (strpos($key, 'REDIRECT_') === 0) { - $key = substr($key, 9); - - // We will not overwrite existing variables with the - // prefixed versions, though - if (array_key_exists($key, $server)) { - continue; - } - } - - if ($value && strpos($key, 'HTTP_') === 0) { - $name = strtr(strtolower(substr($key, 5)), '_', '-'); - $headers[$name] = $value; - continue; - } - - if ($value && strpos($key, 'CONTENT_') === 0) { - $name = 'content-' . strtolower(substr($key, 8)); - $headers[$name] = $value; - continue; - } - } - - return $headers; + return marshalHeadersFromSapi($server); } /** * Marshal the URI from the $_SERVER array and headers * + * @deprecated since 1.8.0; use Zend\Diactoros\marshalUriFromSapi() instead. * @param array $server * @param array $headers * @return Uri */ public static function marshalUriFromServer(array $server, array $headers) { - $uri = new Uri(''); - - // URI scheme - $scheme = 'http'; - $https = self::get('HTTPS', $server); - if (($https && 'off' !== $https) - || self::getHeader('x-forwarded-proto', $headers, false) === 'https' - ) { - $scheme = 'https'; - } - $uri = $uri->withScheme($scheme); - - // Set the host - $accumulator = (object) ['host' => '', 'port' => null]; - self::marshalHostAndPortFromHeaders($accumulator, $server, $headers); - $host = $accumulator->host; - $port = $accumulator->port; - if (! empty($host)) { - $uri = $uri->withHost($host); - if (! empty($port)) { - $uri = $uri->withPort($port); - } - } - - // URI path - $path = self::marshalRequestUri($server); - $path = self::stripQueryString($path); - - // URI query - $query = ''; - if (isset($server['QUERY_STRING'])) { - $query = ltrim($server['QUERY_STRING'], '?'); - } - - // URI fragment - $fragment = ''; - if (strpos($path, '#') !== false) { - list($path, $fragment) = explode('#', $path, 2); - } - - return $uri - ->withPath($path) - ->withFragment($fragment) - ->withQuery($query); + return marshalUriFromSapi($server, $headers); } /** * Marshal the host and port from HTTP headers and/or the PHP environment * + * @deprecated since 1.8.0; use Zend\Diactoros\marshalUriFromSapi() instead, + * and pull the host and port from the Uri instance that function + * returns. * @param stdClass $accumulator * @param array $server * @param array $headers */ public static function marshalHostAndPortFromHeaders(stdClass $accumulator, array $server, array $headers) { - if (self::getHeader('host', $headers, false)) { - self::marshalHostAndPortFromHeader($accumulator, self::getHeader('host', $headers)); - return; - } - - if (! isset($server['SERVER_NAME'])) { - return; - } - - $accumulator->host = $server['SERVER_NAME']; - if (isset($server['SERVER_PORT'])) { - $accumulator->port = (int) $server['SERVER_PORT']; - } - - if (! isset($server['SERVER_ADDR']) || ! preg_match('/^\[[0-9a-fA-F\:]+\]$/', $accumulator->host)) { - return; - } - - // Misinterpreted IPv6-Address - // Reported for Safari on Windows - self::marshalIpv6HostAndPort($accumulator, $server); + $uri = marshalUriFromSapi($server, $headers); + $accumulator->host = $uri->getHost(); + $accumulator->port = $uri->getPort(); } /** @@ -318,201 +215,26 @@ * Looks at a variety of criteria in order to attempt to autodetect a base * URI, including rewrite URIs, proxy URIs, etc. * - * From ZF2's Zend\Http\PhpEnvironment\Request class - * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) - * @license http://framework.zend.com/license/new-bsd New BSD License - * + * @deprecated since 1.8.0; use Zend\Diactoros\marshalUriFromSapi() instead, + * and pull the path from the Uri instance that function returns. * @param array $server * @return string */ public static function marshalRequestUri(array $server) { - // IIS7 with URL Rewrite: make sure we get the unencoded url - // (double slash problem). - $iisUrlRewritten = self::get('IIS_WasUrlRewritten', $server); - $unencodedUrl = self::get('UNENCODED_URL', $server, ''); - if ('1' == $iisUrlRewritten && ! empty($unencodedUrl)) { - return $unencodedUrl; - } - - $requestUri = self::get('REQUEST_URI', $server); - - // Check this first so IIS will catch. - $httpXRewriteUrl = self::get('HTTP_X_REWRITE_URL', $server); - if ($httpXRewriteUrl !== null) { - $requestUri = $httpXRewriteUrl; - } - - // Check for IIS 7.0 or later with ISAPI_Rewrite - $httpXOriginalUrl = self::get('HTTP_X_ORIGINAL_URL', $server); - if ($httpXOriginalUrl !== null) { - $requestUri = $httpXOriginalUrl; - } - - if ($requestUri !== null) { - return preg_replace('#^[^/:]+://[^/]+#', '', $requestUri); - } - - $origPathInfo = self::get('ORIG_PATH_INFO', $server); - if (empty($origPathInfo)) { - return '/'; - } - - return $origPathInfo; + $uri = marshalUriFromSapi($server, []); + return $uri->getPath(); } /** * Strip the query string from a path * + * @deprecated since 1.8.0; no longer used internally. * @param mixed $path * @return string */ public static function stripQueryString($path) { - if (($qpos = strpos($path, '?')) !== false) { - return substr($path, 0, $qpos); - } - return $path; - } - - /** - * Marshal the host and port from the request header - * - * @param stdClass $accumulator - * @param string|array $host - * @return void - */ - private static function marshalHostAndPortFromHeader(stdClass $accumulator, $host) - { - if (is_array($host)) { - $host = implode(', ', $host); - } - - $accumulator->host = $host; - $accumulator->port = null; - - // works for regname, IPv4 & IPv6 - if (preg_match('|\:(\d+)$|', $accumulator->host, $matches)) { - $accumulator->host = substr($accumulator->host, 0, -1 * (strlen($matches[1]) + 1)); - $accumulator->port = (int) $matches[1]; - } - } - - /** - * Marshal host/port from misinterpreted IPv6 address - * - * @param stdClass $accumulator - * @param array $server - */ - private static function marshalIpv6HostAndPort(stdClass $accumulator, array $server) - { - $accumulator->host = '[' . $server['SERVER_ADDR'] . ']'; - $accumulator->port = $accumulator->port ?: 80; - if ($accumulator->port . ']' === substr($accumulator->host, strrpos($accumulator->host, ':') + 1)) { - // The last digit of the IPv6-Address has been taken as port - // Unset the port so the default port can be used - $accumulator->port = null; - } - } - - /** - * Create and return an UploadedFile instance from a $_FILES specification. - * - * If the specification represents an array of values, this method will - * delegate to normalizeNestedFileSpec() and return that return value. - * - * @param array $value $_FILES struct - * @return array|UploadedFileInterface - */ - private static function createUploadedFileFromSpec(array $value) - { - if (is_array($value['tmp_name'])) { - return self::normalizeNestedFileSpec($value); - } - - return new UploadedFile( - $value['tmp_name'], - $value['size'], - $value['error'], - $value['name'], - $value['type'] - ); - } - - /** - * Normalize an array of file specifications. - * - * Loops through all nested files and returns a normalized array of - * UploadedFileInterface instances. - * - * @param array $files - * @return UploadedFileInterface[] - */ - private static function normalizeNestedFileSpec(array $files = []) - { - $normalizedFiles = []; - foreach (array_keys($files['tmp_name']) as $key) { - $spec = [ - 'tmp_name' => $files['tmp_name'][$key], - 'size' => $files['size'][$key], - 'error' => $files['error'][$key], - 'name' => $files['name'][$key], - 'type' => $files['type'][$key], - ]; - $normalizedFiles[$key] = self::createUploadedFileFromSpec($spec); - } - return $normalizedFiles; - } - - /** - * Return HTTP protocol version (X.Y) - * - * @param array $server - * @return string - */ - private static function marshalProtocolVersion(array $server) - { - if (! isset($server['SERVER_PROTOCOL'])) { - return '1.1'; - } - - if (! preg_match('#^(HTTP/)?(?P[1-9]\d*(?:\.\d)?)$#', $server['SERVER_PROTOCOL'], $matches)) { - throw new UnexpectedValueException(sprintf( - 'Unrecognized protocol version (%s)', - $server['SERVER_PROTOCOL'] - )); - } - - return $matches['version']; - } - - /** - * Parse a cookie header according to RFC 6265. - * - * PHP will replace special characters in cookie names, which results in other cookies not being available due to - * overwriting. Thus, the server request should take the cookies from the request header instead. - * - * @param $cookieHeader - * @return array - */ - private static function parseCookieHeader($cookieHeader) - { - preg_match_all('( - (?:^\\n?[ \t]*|;[ ]) - (?P[!#$%&\'*+-.0-9A-Z^_`a-z|~]+) - = - (?P"?) - (?P[\x21\x23-\x2b\x2d-\x3a\x3c-\x5b\x5d-\x7e]*) - (?P=DQUOTE) - (?=\\n?[ \t]*$|;[ ]) - )x', $cookieHeader, $matches, PREG_SET_ORDER); - - $cookies = []; - - foreach ($matches as $match) { - $cookies[$match['name']] = urldecode($match['value']); - } - - return $cookies; + return explode('?', $path, 2)[0]; } } diff -r e200cb7efeb3 -r c2387f117808 vendor/zendframework/zend-diactoros/src/Stream.php --- a/vendor/zendframework/zend-diactoros/src/Stream.php Thu Apr 26 11:26:54 2018 +0100 +++ b/vendor/zendframework/zend-diactoros/src/Stream.php Tue Jul 10 15:07:59 2018 +0100 @@ -8,8 +8,30 @@ namespace Zend\Diactoros; use InvalidArgumentException; +use Psr\Http\Message\StreamInterface; use RuntimeException; -use Psr\Http\Message\StreamInterface; + +use function array_key_exists; +use function fclose; +use function feof; +use function fopen; +use function fread; +use function fseek; +use function fstat; +use function ftell; +use function fwrite; +use function get_resource_type; +use function is_int; +use function is_resource; +use function is_string; +use function restore_error_handler; +use function set_error_handler; +use function stream_get_contents; +use function stream_get_meta_data; +use function strstr; + +use const E_WARNING; +use const SEEK_SET; /** * Implementation of PSR HTTP streams diff -r e200cb7efeb3 -r c2387f117808 vendor/zendframework/zend-diactoros/src/UploadedFile.php --- a/vendor/zendframework/zend-diactoros/src/UploadedFile.php Thu Apr 26 11:26:54 2018 +0100 +++ b/vendor/zendframework/zend-diactoros/src/UploadedFile.php Tue Jul 10 15:07:59 2018 +0100 @@ -12,6 +12,29 @@ use Psr\Http\Message\UploadedFileInterface; use RuntimeException; +use function dirname; +use function fclose; +use function fopen; +use function fwrite; +use function is_dir; +use function is_int; +use function is_resource; +use function is_string; +use function is_writable; +use function move_uploaded_file; +use function sprintf; +use function strpos; + +use const PHP_SAPI; +use const UPLOAD_ERR_CANT_WRITE; +use const UPLOAD_ERR_EXTENSION; +use const UPLOAD_ERR_FORM_SIZE; +use const UPLOAD_ERR_INI_SIZE; +use const UPLOAD_ERR_NO_FILE; +use const UPLOAD_ERR_NO_TMP_DIR; +use const UPLOAD_ERR_OK; +use const UPLOAD_ERR_PARTIAL; + class UploadedFile implements UploadedFileInterface { const ERROR_MESSAGES = [ diff -r e200cb7efeb3 -r c2387f117808 vendor/zendframework/zend-diactoros/src/Uri.php --- a/vendor/zendframework/zend-diactoros/src/Uri.php Thu Apr 26 11:26:54 2018 +0100 +++ b/vendor/zendframework/zend-diactoros/src/Uri.php Tue Jul 10 15:07:59 2018 +0100 @@ -10,6 +10,26 @@ use InvalidArgumentException; use Psr\Http\Message\UriInterface; +use function array_key_exists; +use function array_keys; +use function count; +use function explode; +use function get_class; +use function gettype; +use function implode; +use function is_numeric; +use function is_object; +use function is_string; +use function ltrim; +use function parse_url; +use function preg_replace; +use function preg_replace_callback; +use function rawurlencode; +use function sprintf; +use function strpos; +use function strtolower; +use function substr; + /** * Implementation of Psr\Http\UriInterface. * @@ -98,7 +118,7 @@ )); } - if (! empty($uri)) { + if ('' !== $uri) { $this->parseUri($uri); } } @@ -147,12 +167,12 @@ */ public function getAuthority() { - if (empty($this->host)) { + if ('' === $this->host) { return ''; } $authority = $this->host; - if (! empty($this->userInfo)) { + if ('' !== $this->userInfo) { $authority = $this->userInfo . '@' . $authority; } @@ -476,27 +496,26 @@ { $uri = ''; - if (! empty($scheme)) { + if ('' !== $scheme) { $uri .= sprintf('%s:', $scheme); } - if (! empty($authority)) { + if ('' !== $authority) { $uri .= '//' . $authority; } - if ($path) { - if (empty($path) || '/' !== substr($path, 0, 1)) { - $path = '/' . $path; - } - - $uri .= $path; + if ('' !== $path && '/' !== substr($path, 0, 1)) { + $path = '/' . $path; } - if ($query) { + $uri .= $path; + + + if ('' !== $query) { $uri .= sprintf('?%s', $query); } - if ($fragment) { + if ('' !== $fragment) { $uri .= sprintf('#%s', $fragment); } @@ -513,14 +532,11 @@ */ private function isNonStandardPort($scheme, $host, $port) { - if (! $scheme) { - if ($host && ! $port) { - return false; - } - return true; + if ('' === $scheme) { + return '' === $host || null !== $port; } - if (! $host || ! $port) { + if ('' === $host || null === $port) { return false; } @@ -539,7 +555,7 @@ $scheme = strtolower($scheme); $scheme = preg_replace('#:(//)?$#', '', $scheme); - if (empty($scheme)) { + if ('' === $scheme) { return ''; } @@ -585,7 +601,7 @@ $path ); - if (empty($path)) { + if ('' === $path) { // No path return $path; } @@ -609,7 +625,7 @@ */ private function filterQuery($query) { - if (! empty($query) && strpos($query, '?') === 0) { + if ('' !== $query && strpos($query, '?') === 0) { $query = substr($query, 1); } @@ -653,7 +669,7 @@ */ private function filterFragment($fragment) { - if (! empty($fragment) && strpos($fragment, '#') === 0) { + if ('' !== $fragment && strpos($fragment, '#') === 0) { $fragment = '%23' . substr($fragment, 1); } diff -r e200cb7efeb3 -r c2387f117808 vendor/zendframework/zend-diactoros/src/functions/create_uploaded_file.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vendor/zendframework/zend-diactoros/src/functions/create_uploaded_file.php Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,40 @@ + $value) { + // Apache prefixes environment variables with REDIRECT_ + // if they are added by rewrite rules + if (strpos($key, 'REDIRECT_') === 0) { + $key = substr($key, 9); + + // We will not overwrite existing variables with the + // prefixed versions, though + if (array_key_exists($key, $server)) { + continue; + } + } + + if ($value && strpos($key, 'HTTP_') === 0) { + $name = strtr(strtolower(substr($key, 5)), '_', '-'); + $headers[$name] = $value; + continue; + } + + if ($value && strpos($key, 'CONTENT_') === 0) { + $name = 'content-' . strtolower(substr($key, 8)); + $headers[$name] = $value; + continue; + } + } + + return $headers; +} diff -r e200cb7efeb3 -r c2387f117808 vendor/zendframework/zend-diactoros/src/functions/marshal_method_from_sapi.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vendor/zendframework/zend-diactoros/src/functions/marshal_method_from_sapi.php Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,19 @@ +[1-9]\d*(?:\.\d)?)$#', $server['SERVER_PROTOCOL'], $matches)) { + throw new UnexpectedValueException(sprintf( + 'Unrecognized protocol version (%s)', + $server['SERVER_PROTOCOL'] + )); + } + + return $matches['version']; +} diff -r e200cb7efeb3 -r c2387f117808 vendor/zendframework/zend-diactoros/src/functions/marshal_uri_from_sapi.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vendor/zendframework/zend-diactoros/src/functions/marshal_uri_from_sapi.php Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,214 @@ +withScheme($scheme); + + // Set the host + list($host, $port) = $marshalHostAndPort($headers, $server); + if (! empty($host)) { + $uri = $uri->withHost($host); + if (! empty($port)) { + $uri = $uri->withPort($port); + } + } + + // URI path + $path = $marshalRequestPath($server); + + // Strip query string + $path = explode('?', $path, 2)[0]; + + // URI query + $query = ''; + if (isset($server['QUERY_STRING'])) { + $query = ltrim($server['QUERY_STRING'], '?'); + } + + // URI fragment + $fragment = ''; + if (strpos($path, '#') !== false) { + list($path, $fragment) = explode('#', $path, 2); + } + + return $uri + ->withPath($path) + ->withFragment($fragment) + ->withQuery($query); +} diff -r e200cb7efeb3 -r c2387f117808 vendor/zendframework/zend-diactoros/src/functions/normalize_server.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vendor/zendframework/zend-diactoros/src/functions/normalize_server.php Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,51 @@ + $value) { + if (is_array($value)) { + // Traverse + $normalized[$key] = $recursiveNormalize( + $tmpNameTree[$key], + $sizeTree[$key], + $errorTree[$key], + isset($nameTree[$key]) ? $nameTree[$key] : null, + isset($typeTree[$key]) ? $typeTree[$key] : null + ); + continue; + } + $normalized[$key] = createUploadedFile([ + 'tmp_name' => $tmpNameTree[$key], + 'size' => $sizeTree[$key], + 'error' => $errorTree[$key], + 'name' => isset($nameTree[$key]) ? $nameTree[$key] : null, + 'type' => isset($typeTree[$key]) ? $typeTree[$key] : null + ]); + } + return $normalized; + }; + + /** + * Normalize an array of file specifications. + * + * Loops through all nested files (as determined by receiving an array to the + * `tmp_name` key of a `$_FILES` specification) and returns a normalized array + * of UploadedFile instances. + * + * This function normalizes a `$_FILES` array representing a nested set of + * uploaded files as produced by the php-fpm SAPI, CGI SAPI, or mod_php + * SAPI. + * + * @param array $files + * @return UploadedFile[] + */ + $normalizeUploadedFileSpecification = function (array $files = []) use (&$recursiveNormalize) { + if (! isset($files['tmp_name']) || ! is_array($files['tmp_name']) + || ! isset($files['size']) || ! is_array($files['size']) + || ! isset($files['error']) || ! is_array($files['error']) + ) { + throw new InvalidArgumentException(sprintf( + '$files provided to %s MUST contain each of the keys "tmp_name",' + . ' "size", and "error", with each represented as an array;' + . ' one or more were missing or non-array values', + __FUNCTION__ + )); + } + + return $recursiveNormalize( + $files['tmp_name'], + $files['size'], + $files['error'], + isset($files['name']) ? $files['name'] : null, + isset($files['type']) ? $files['type'] : null + ); + }; + + $normalized = []; + foreach ($files as $key => $value) { + if ($value instanceof UploadedFileInterface) { + $normalized[$key] = $value; + continue; + } + + if (is_array($value) && isset($value['tmp_name']) && is_array($value['tmp_name'])) { + $normalized[$key] = $normalizeUploadedFileSpecification($value); + continue; + } + + if (is_array($value) && isset($value['tmp_name'])) { + $normalized[$key] = createUploadedFile($value); + continue; + } + + if (is_array($value)) { + $normalized[$key] = normalizeUploadedFiles($value); + continue; + } + + throw new InvalidArgumentException('Invalid value in files specification'); + } + return $normalized; +} diff -r e200cb7efeb3 -r c2387f117808 vendor/zendframework/zend-diactoros/src/functions/parse_cookie_header.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vendor/zendframework/zend-diactoros/src/functions/parse_cookie_header.php Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,41 @@ +[!#$%&\'*+-.0-9A-Z^_`a-z|~]+) + = + (?P"?) + (?P[\x21\x23-\x2b\x2d-\x3a\x3c-\x5b\x5d-\x7e]*) + (?P=DQUOTE) + (?=\\n?[ \t]*$|;[ ]) + )x', $cookieHeader, $matches, PREG_SET_ORDER); + + $cookies = []; + + foreach ($matches as $match) { + $cookies[$match['name']] = urldecode($match['value']); + } + + return $cookies; +} diff -r e200cb7efeb3 -r c2387f117808 vendor/zendframework/zend-feed/CHANGELOG.md --- a/vendor/zendframework/zend-feed/CHANGELOG.md Thu Apr 26 11:26:54 2018 +0100 +++ b/vendor/zendframework/zend-feed/CHANGELOG.md Tue Jul 10 15:07:59 2018 +0100 @@ -2,6 +2,181 @@ All notable changes to this project will be documented in this file, in reverse chronological order by release. +## 2.10.2 - 2018-06-18 + +### Added + +- Nothing. + +### Changed + +- Nothing. + +### Deprecated + +- Nothing. + +### Removed + +- Nothing. + +### Fixed + +- [#81](https://github.com/zendframework/zend-feed/pull/81) updates the `Zend\Feed\Reader\Reader` and `Zend\Feed\Writer\Writer` classes to + conditionally register their respective "GooglePlayPodcast" extensions only if + their extension managers are aware of it. This is done due to the fact that + existing `ExtensionManagerInterface` implementations may not register it by + default as the extension did not exist in releases prior to 2.10.0. By having + the registration conditional, we prevent an exception from being raised; users + are not impacted by its absence, as the extension features were not exposed + previously. + + Both `Reader` and `Writer` emit an `E_USER_NOTICE` when the extension is not + found in the extension manager, indicating that the + `ExtensionManagerInterface` implementation should be updated to add entries + for the "GooglePlayPodcast" entry, feed, and/or renderer classes. + +## 2.10.1 - 2018-06-05 + +### Added + +- Nothing. + +### Changed + +- Nothing. + +### Deprecated + +- Nothing. + +### Removed + +- Nothing. + +### Fixed + +- [#79](https://github.com/zendframework/zend-feed/pull/79) fixes an issue in the `setType()` method of the iTunes feed renderer whereby it was setting + the DOM content with an uninitialized variable. + +## 2.10.0 - 2018-05-24 + +### Added + +- [#78](https://github.com/zendframework/zend-feed/pull/78) adds support for the Google Play Podcasts 1.0 DTD in both the Reader and + Writer subcomponents. The following new classes provide the support: + + - `Zend\Feed\Reader\Extension\GooglePlayPodcast\Entry` + - `Zend\Feed\Reader\Extension\GooglePlayPodcast\Feed` + - `Zend\Feed\Writer\Extension\GooglePlayPodcast\Entry` + - `Zend\Feed\Writer\Extension\GooglePlayPodcast\Feed` + - `Zend\Feed\Writer\Extension\GooglePlayPodcast\Renderer\Entry` + - `Zend\Feed\Writer\Extension\GooglePlayPodcast\Renderer\Feed` + + The extensions are registered by default with both `Zend\Feed\Reader\Reader` + and `Zend\Feed\Writer\Writer`. + +- [#77](https://github.com/zendframework/zend-feed/pull/77) adds support for `itunes:image` for each of: + - `Zend\Feed\Reader\Extension\Podcast\Entry`, via `getItunesImage()`; previously only the `Feed` supported it. + - `Zend\Feed\Writer\Extension\ITunes\Entry`, via `setItunesImage()`; previously only the `Feed` supported it. + - `Zend\Feed\Writer\Extension\ITunes\Renderer\Entry`; previously on the `Feed` supported it. + +- [#75](https://github.com/zendframework/zend-feed/pull/75) adds `Zend\Feed\Writer\Extension\ITunes\Entry::setItunesSeason()`, corresponding to the + `itunes:season` tag, and allowing setting the season number of the episode the + entry represents. + +- [#75](https://github.com/zendframework/zend-feed/pull/75) adds `Zend\Feed\Writer\Extension\ITunes\Entry::setItunesIsClosedCaptioned()`, corresponding to the + `itunes:isClosedCaptioned` tag, and allowing setting the status of closed + captioning support in the episode the entry represents. + +- [#75](https://github.com/zendframework/zend-feed/pull/75) adds `Zend\Feed\Writer\Extension\ITunes\Entry::setItunesEpisodeType()`, corresponding to the + `itunes:episodeType` tag, and allowing setting the type of episode the entry represents + (one of "full", "trailer", or "bonus", and defaulting to "full"). + +- [#75](https://github.com/zendframework/zend-feed/pull/75) adds `Zend\Feed\Writer\Extension\ITunes\Entry::setEpisode()`, corresponding to the + `itunes:episode` tag, and allowing setting the number of the episode the entry represents. + +- [#75](https://github.com/zendframework/zend-feed/pull/75) adds `Zend\Feed\Writer\Extension\ITunes\Feed::setItunesComplete()`, corresponding to the + `itunes:complete` tag. It allows setting a boolean flag, indicating whether or not the + podcast is complete (will not air new episodes). + +- [#75](https://github.com/zendframework/zend-feed/pull/75) adds `Zend\Feed\Writer\Extension\ITunes\Feed::setItunesType()`, corresponding to the + `itunes:type` tag, and allowing setting the podcast type (one of "serial" or "episodic"). + +- [#75](https://github.com/zendframework/zend-feed/pull/75) adds `Zend\Feed\Reader\Extension\Podcast\Entry::getEpisodeType()`, corresponding to the + `itunes:episodeType` tag, and returning the type of episode the entry represents + (one of "full", "trailer", or "bonus", and defaulting to "full"). + +- [#75](https://github.com/zendframework/zend-feed/pull/75) adds `Zend\Feed\Reader\Extension\Podcast\Entry::getSeason()`, corresponding to the + `itunes:season` tag, and returning the season number of the episode the entry represents. + +- [#75](https://github.com/zendframework/zend-feed/pull/75) adds `Zend\Feed\Reader\Extension\Podcast\Entry::isClsoedCaptioned()`, corresponding to the + `itunes:isClosedCaptioned` tag, and returning the status of closed captioning + in the episode the entry represents. + +- [#75](https://github.com/zendframework/zend-feed/pull/75) adds `Zend\Feed\Reader\Extension\Podcast\Entry::getEpisode()`, corresponding to the + `itunes:episode` tag, and returning the number of the episode the entry represents. + +- [#75](https://github.com/zendframework/zend-feed/pull/75) adds `Zend\Feed\Reader\Extension\Podcast\Feed::isComplete()`, corresponding to the + `itunes:complete` tag. It returns a boolean, indicating whether or not the podcast is + complete (will not air new episodes). + +- [#75](https://github.com/zendframework/zend-feed/pull/75) adds `Zend\Feed\Reader\Extension\Podcast\Feed::getPodcastType()`, corresponding to the + `itunes:type` tag, and providing the podcast type (one of "serial" or "episodic", defaulting + to the latter). + +### Changed + +- [#77](https://github.com/zendframework/zend-feed/pull/77) updates URI validation for `Zend\Feed\Writer\Extension\ITunes\Feed::setItunesImage()` to + first check that we have received a string value before proceeding. + +### Deprecated + +- [#75](https://github.com/zendframework/zend-feed/pull/75) deprecates each of: + - `Zend\Feed\Reader\Extension\Podcast\Entry::getKeywords()` + - `Zend\Feed\Reader\Extension\Podcast\Feed::getKeywords()` + - `Zend\Feed\Writer\Extension\ITunes\Entry::setKeywords()` + - `Zend\Feed\Writer\Extension\ITunes\Feed::setKeywords()` + as the iTunes Podcast RSS specification no longer supports keywords. + +### Removed + +- Nothing. + +### Fixed + +- Nothing. + +## 2.9.1 - 2018-05-14 + +### Added + +- Nothing. + +### Changed + +- [#16](https://github.com/zendframework/zend-feed/pull/16) updates the `Zend\Feed\Pubsubhubbub\AbstractCallback` to no longer use the + `$GLOBALS['HTTP_RAW_POST_DATA']` value as a fallback when `php://input` is + empty. The fallback existed because, prior to PHP 5.6, `php://input` could + only be read once. As we now require PHP 5.6, the fallback is unnecessary, + and best removed as the globals value is deprecated. + +### Deprecated + +- Nothing. + +### Removed + +- Nothing. + +### Fixed + +- [#68](https://github.com/zendframework/zend-feed/pull/68) fixes the behavior of `Zend\Feed\Writer\AbstractFeed::setTitle()` and + `Zend\Feed\Writer\Entry::setTitle()` to accept the string `"0"`. + +- [#68](https://github.com/zendframework/zend-feed/pull/68) updates both `Zend\Feed\Writer\AbstractFeed` and `Zend\Feed\Writer\Entry` + to no longer throw an exception for entry titles which have a string value of `0`. + ## 2.9.0 - 2017-12-04 ### Added diff -r e200cb7efeb3 -r c2387f117808 vendor/zendframework/zend-feed/composer.json --- a/vendor/zendframework/zend-feed/composer.json Thu Apr 26 11:26:54 2018 +0100 +++ b/vendor/zendframework/zend-feed/composer.json Tue Jul 10 15:07:59 2018 +0100 @@ -53,8 +53,8 @@ }, "extra": { "branch-alias": { - "dev-master": "2.9-dev", - "dev-develop": "2.10-dev" + "dev-master": "2.10.x-dev", + "dev-develop": "2.11.x-dev" } }, "scripts": { @@ -65,7 +65,6 @@ "cs-check": "phpcs", "cs-fix": "phpcbf", "test": "phpunit --colors=always", - "test-coverage": "phpunit --colors=always --coverage-clover clover.xml", - "upload-coverage": "coveralls -v" + "test-coverage": "phpunit --colors=always --coverage-clover clover.xml" } } diff -r e200cb7efeb3 -r c2387f117808 vendor/zendframework/zend-feed/src/PubSubHubbub/AbstractCallback.php --- a/vendor/zendframework/zend-feed/src/PubSubHubbub/AbstractCallback.php Thu Apr 26 11:26:54 2018 +0100 +++ b/vendor/zendframework/zend-feed/src/PubSubHubbub/AbstractCallback.php Tue Jul 10 15:07:59 2018 +0100 @@ -34,6 +34,17 @@ protected $httpResponse = null; /** + * The input stream to use when retrieving the request body. Defaults to + * php://input, but can be set to another value in order to force usage + * of another input method. This should primarily be used for testing + * purposes. + * + * @var string|resource String indicates a filename or stream to open; + * resource indicates an already created stream to use. + */ + protected $inputStream = 'php://input'; + + /** * The number of Subscribers for which any updates are on behalf of. * * @var int @@ -287,13 +298,10 @@ protected function _getRawBody() { // @codingStandardsIgnoreEnd - $body = file_get_contents('php://input'); - if (strlen(trim($body)) == 0 && isset($GLOBALS['HTTP_RAW_POST_DATA'])) { - $body = $GLOBALS['HTTP_RAW_POST_DATA']; - } - if (strlen(trim($body)) > 0) { - return $body; - } - return false; + $body = is_resource($this->inputStream) + ? stream_get_contents($this->inputStream) + : file_get_contents($this->inputStream); + + return strlen(trim($body)) > 0 ? $body : false; } } diff -r e200cb7efeb3 -r c2387f117808 vendor/zendframework/zend-feed/src/Reader/Extension/GooglePlayPodcast/Entry.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vendor/zendframework/zend-feed/src/Reader/Extension/GooglePlayPodcast/Entry.php Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,90 @@ +data['block'])) { + return $this->data['block']; + } + + $block = $this->xpath->evaluate('string(' . $this->getXpathPrefix() . '/googleplay:block)'); + + if (! $block) { + $block = null; + } + + $this->data['block'] = $block; + + return $this->data['block']; + } + + /** + * Get the entry explicit + * + * @return string + */ + public function getPlayPodcastExplicit() + { + if (isset($this->data['explicit'])) { + return $this->data['explicit']; + } + + $explicit = $this->xpath->evaluate('string(' . $this->getXpathPrefix() . '/googleplay:explicit)'); + + if (! $explicit) { + $explicit = null; + } + + $this->data['explicit'] = $explicit; + + return $this->data['explicit']; + } + + /** + * Get the episode summary/description + * + * Uses verbiage so it does not conflict with base entry. + * + * @return string + */ + public function getPlayPodcastDescription() + { + if (isset($this->data['description'])) { + return $this->data['description']; + } + + $description = $this->xpath->evaluate('string(' . $this->getXpathPrefix() . '/googleplay:description)'); + + if (! $description) { + $description = null; + } + + $this->data['description'] = $description; + + return $this->data['description']; + } + + /** + * Register googleplay namespace + * + */ + protected function registerNamespaces() + { + $this->xpath->registerNamespace('googleplay', 'http://www.google.com/schemas/play-podcasts/1.0'); + } +} diff -r e200cb7efeb3 -r c2387f117808 vendor/zendframework/zend-feed/src/Reader/Extension/GooglePlayPodcast/Feed.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vendor/zendframework/zend-feed/src/Reader/Extension/GooglePlayPodcast/Feed.php Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,175 @@ +data['author'])) { + return $this->data['author']; + } + + $author = $this->xpath->evaluate('string(' . $this->getXpathPrefix() . '/googleplay:author)'); + + if (! $author) { + $author = null; + } + + $this->data['author'] = $author; + + return $this->data['author']; + } + + /** + * Get the entry block + * + * @return string + */ + public function getPlayPodcastBlock() + { + if (isset($this->data['block'])) { + return $this->data['block']; + } + + $block = $this->xpath->evaluate('string(' . $this->getXpathPrefix() . '/googleplay:block)'); + + if (! $block) { + $block = null; + } + + $this->data['block'] = $block; + + return $this->data['block']; + } + + /** + * Get the entry category + * + * @return array|null + */ + public function getPlayPodcastCategories() + { + if (isset($this->data['categories'])) { + return $this->data['categories']; + } + + $categoryList = $this->xpath->query($this->getXpathPrefix() . '/googleplay:category'); + + $categories = []; + + if ($categoryList->length > 0) { + foreach ($categoryList as $node) { + $children = null; + + if ($node->childNodes->length > 0) { + $children = []; + + foreach ($node->childNodes as $childNode) { + if (! ($childNode instanceof DOMText)) { + $children[$childNode->getAttribute('text')] = null; + } + } + } + + $categories[$node->getAttribute('text')] = $children; + } + } + + if (! $categories) { + $categories = null; + } + + $this->data['categories'] = $categories; + + return $this->data['categories']; + } + + /** + * Get the entry explicit + * + * @return string + */ + public function getPlayPodcastExplicit() + { + if (isset($this->data['explicit'])) { + return $this->data['explicit']; + } + + $explicit = $this->xpath->evaluate('string(' . $this->getXpathPrefix() . '/googleplay:explicit)'); + + if (! $explicit) { + $explicit = null; + } + + $this->data['explicit'] = $explicit; + + return $this->data['explicit']; + } + + /** + * Get the feed/podcast image + * + * @return string + */ + public function getPlayPodcastImage() + { + if (isset($this->data['image'])) { + return $this->data['image']; + } + + $image = $this->xpath->evaluate('string(' . $this->getXpathPrefix() . '/googleplay:image/@href)'); + + if (! $image) { + $image = null; + } + + $this->data['image'] = $image; + + return $this->data['image']; + } + + /** + * Get the entry description + * + * @return string + */ + public function getPlayPodcastDescription() + { + if (isset($this->data['description'])) { + return $this->data['description']; + } + + $description = $this->xpath->evaluate('string(' . $this->getXpathPrefix() . '/googleplay:description)'); + + if (! $description) { + $description = null; + } + + $this->data['description'] = $description; + + return $this->data['description']; + } + + /** + * Register googleplay namespace + * + */ + protected function registerNamespaces() + { + $this->xpath->registerNamespace('googleplay', 'http://www.google.com/schemas/play-podcasts/1.0'); + } +} diff -r e200cb7efeb3 -r c2387f117808 vendor/zendframework/zend-feed/src/Reader/Extension/Podcast/Entry.php --- a/vendor/zendframework/zend-feed/src/Reader/Extension/Podcast/Entry.php Thu Apr 26 11:26:54 2018 +0100 +++ b/vendor/zendframework/zend-feed/src/Reader/Extension/Podcast/Entry.php Tue Jul 10 15:07:59 2018 +0100 @@ -1,18 +1,14 @@ data['keywords'])) { return $this->data['keywords']; } @@ -170,6 +174,114 @@ } /** + * Get the entry image + * + * @return string + */ + public function getItunesImage() + { + if (isset($this->data['image'])) { + return $this->data['image']; + } + + $image = $this->xpath->evaluate('string(' . $this->getXpathPrefix() . '/itunes:image/@href)'); + + if (! $image) { + $image = null; + } + + $this->data['image'] = $image; + + return $this->data['image']; + } + + /** + * Get the episode number + * + * @return null|int + */ + public function getEpisode() + { + if (isset($this->data['episode'])) { + return $this->data['episode']; + } + + $episode = $this->xpath->evaluate('string(' . $this->getXpathPrefix() . '/itunes:episode)'); + + if (! $episode) { + $episode = null; + } + + $this->data['episode'] = null === $episode ? $episode : (int) $episode; + + return $this->data['episode']; + } + + /** + * Get the episode number + * + * @return string One of "full", "trailer", or "bonus"; defaults to "full". + */ + public function getEpisodeType() + { + if (isset($this->data['episodeType'])) { + return $this->data['episodeType']; + } + + $type = $this->xpath->evaluate('string(' . $this->getXpathPrefix() . '/itunes:episodeType)'); + + if (! $type) { + $type = 'full'; + } + + $this->data['episodeType'] = (string) $type; + + return $this->data['episodeType']; + } + + /** + * Is the episode closed captioned? + * + * Returns true only if itunes:isClosedCaptioned has the value 'Yes'. + * + * @return bool + */ + public function isClosedCaptioned() + { + if (isset($this->data['isClosedCaptioned'])) { + return $this->data['isClosedCaptioned']; + } + + $status = $this->xpath->evaluate('string(' . $this->getXpathPrefix() . '/itunes:isClosedCaptioned)'); + + $this->data['isClosedCaptioned'] = $status === 'Yes'; + + return $this->data['isClosedCaptioned']; + } + + /** + * Get the season number + * + * @return null|int + */ + public function getSeason() + { + if (isset($this->data['season'])) { + return $this->data['season']; + } + + $season = $this->xpath->evaluate('string(' . $this->getXpathPrefix() . '/itunes:season)'); + + if (! $season) { + $season = null; + } + + $this->data['season'] = null === $season ? $season : (int) $season; + + return $this->data['season']; + } + + /** * Register iTunes namespace * */ diff -r e200cb7efeb3 -r c2387f117808 vendor/zendframework/zend-feed/src/Reader/Extension/Podcast/Feed.php --- a/vendor/zendframework/zend-feed/src/Reader/Extension/Podcast/Feed.php Thu Apr 26 11:26:54 2018 +0100 +++ b/vendor/zendframework/zend-feed/src/Reader/Extension/Podcast/Feed.php Tue Jul 10 15:07:59 2018 +0100 @@ -1,10 +1,8 @@ data['keywords'])) { return $this->data['keywords']; } @@ -266,6 +270,51 @@ } /** + * Get the type of podcast + * + * @return string One of "episodic" or "serial". Defaults to "episodic" + * if no itunes:type tag is encountered. + */ + public function getPodcastType() + { + if (isset($this->data['podcastType'])) { + return $this->data['podcastType']; + } + + $type = $this->xpath->evaluate('string(' . $this->getXpathPrefix() . '/itunes:type)'); + + if (! $type) { + $type = 'episodic'; + } + + $this->data['podcastType'] = (string) $type; + + return $this->data['podcastType']; + } + + /** + * Is the podcast complete (no more episodes will post)? + * + * @return bool + */ + public function isComplete() + { + if (isset($this->data['complete'])) { + return $this->data['complete']; + } + + $complete = $this->xpath->evaluate('string(' . $this->getXpathPrefix() . '/itunes:complete)'); + + if (! $complete) { + $complete = false; + } + + $this->data['complete'] = $complete === 'Yes'; + + return $this->data['complete']; + } + + /** * Register iTunes namespace * */ diff -r e200cb7efeb3 -r c2387f117808 vendor/zendframework/zend-feed/src/Reader/ExtensionPluginManager.php --- a/vendor/zendframework/zend-feed/src/Reader/ExtensionPluginManager.php Thu Apr 26 11:26:54 2018 +0100 +++ b/vendor/zendframework/zend-feed/src/Reader/ExtensionPluginManager.php Tue Jul 10 15:07:59 2018 +0100 @@ -56,6 +56,14 @@ 'dublinCoreFeed' => Extension\DublinCore\Feed::class, 'DublinCoreFeed' => Extension\DublinCore\Feed::class, 'DublinCore\Feed' => Extension\DublinCore\Feed::class, + 'googleplaypodcastentry' => Extension\GooglePlayPodcast\Entry::class, + 'googlePlayPodcastEntry' => Extension\GooglePlayPodcast\Entry::class, + 'GooglePlayPodcastEntry' => Extension\GooglePlayPodcast\Entry::class, + 'GooglePlayPodcast\Entry' => Extension\GooglePlayPodcast\Entry::class, + 'googleplaypodcastfeed' => Extension\GooglePlayPodcast\Feed::class, + 'googlePlayPodcastFeed' => Extension\GooglePlayPodcast\Feed::class, + 'GooglePlayPodcastFeed' => Extension\GooglePlayPodcast\Feed::class, + 'GooglePlayPodcast\Feed' => Extension\GooglePlayPodcast\Feed::class, 'podcastentry' => Extension\Podcast\Entry::class, 'podcastEntry' => Extension\Podcast\Entry::class, 'PodcastEntry' => Extension\Podcast\Entry::class, @@ -95,6 +103,8 @@ Extension\CreativeCommons\Feed::class => InvokableFactory::class, Extension\DublinCore\Entry::class => InvokableFactory::class, Extension\DublinCore\Feed::class => InvokableFactory::class, + Extension\GooglePlayPodcast\Entry::class => InvokableFactory::class, + Extension\GooglePlayPodcast\Feed::class => InvokableFactory::class, Extension\Podcast\Entry::class => InvokableFactory::class, Extension\Podcast\Feed::class => InvokableFactory::class, Extension\Slash\Entry::class => InvokableFactory::class, @@ -111,6 +121,8 @@ 'zendfeedreaderextensioncreativecommonsfeed' => InvokableFactory::class, 'zendfeedreaderextensiondublincoreentry' => InvokableFactory::class, 'zendfeedreaderextensiondublincorefeed' => InvokableFactory::class, + 'zendfeedreaderextensiongoogleplaypodcastentry' => InvokableFactory::class, + 'zendfeedreaderextensiongoogleplaypodcastfeed' => InvokableFactory::class, 'zendfeedreaderextensionpodcastentry' => InvokableFactory::class, 'zendfeedreaderextensionpodcastfeed' => InvokableFactory::class, 'zendfeedreaderextensionslashentry' => InvokableFactory::class, diff -r e200cb7efeb3 -r c2387f117808 vendor/zendframework/zend-feed/src/Reader/Reader.php --- a/vendor/zendframework/zend-feed/src/Reader/Reader.php Thu Apr 26 11:26:54 2018 +0100 +++ b/vendor/zendframework/zend-feed/src/Reader/Reader.php Tue Jul 10 15:07:59 2018 +0100 @@ -577,22 +577,27 @@ */ public static function registerExtension($name) { - $feedName = $name . '\Feed'; - $entryName = $name . '\Entry'; - $manager = static::getExtensionManager(); - if (static::isRegistered($name)) { - if ($manager->has($feedName) || $manager->has($entryName)) { - return; - } + if (! static::hasExtension($name)) { + throw new Exception\RuntimeException(sprintf( + 'Could not load extension "%s" using Plugin Loader.' + . ' Check prefix paths are configured and extension exists.', + $name + )); } - if (! $manager->has($feedName) && ! $manager->has($entryName)) { - throw new Exception\RuntimeException('Could not load extension: ' . $name - . ' using Plugin Loader. Check prefix paths are configured and extension exists.'); + // Return early if already registered. + if (static::isRegistered($name)) { + return; } + + $manager = static::getExtensionManager(); + + $feedName = $name . '\Feed'; if ($manager->has($feedName)) { static::$extensions['feed'][] = $feedName; } + + $entryName = $name . '\Entry'; if ($manager->has($entryName)) { static::$extensions['entry'][] = $entryName; } @@ -672,6 +677,18 @@ static::registerExtension('WellFormedWeb'); static::registerExtension('Thread'); static::registerExtension('Podcast'); + + // Added in 2.10.0; check for it conditionally + static::hasExtension('GooglePlayPodcast') + ? static::registerExtension('GooglePlayPodcast') + : trigger_error( + sprintf( + 'Please update your %1$s\ExtensionManagerInterface implementation to add entries for' + . ' %1$s\Extension\GooglePlayPodcast\Entry and %1$s\Extension\GooglePlayPodcast\Feed.', + __NAMESPACE__ + ), + \E_USER_NOTICE + ); } /** @@ -692,4 +709,28 @@ } return $array; } + + /** + * Does the extension manager have the named extension? + * + * This method exists to allow us to test if an extension is present in the + * extension manager. It may be used by registerExtension() to determine if + * the extension has items present in the manager, or by + * registerCoreExtension() to determine if the core extension has entries + * in the extension manager. In the latter case, this can be useful when + * adding new extensions in a minor release, as custom extension manager + * implementations may not yet have an entry for the extension, which would + * then otherwise cause registerExtension() to fail. + * + * @param string $name + * @return bool + */ + protected static function hasExtension($name) + { + $feedName = $name . '\Feed'; + $entryName = $name . '\Entry'; + $manager = static::getExtensionManager(); + + return $manager->has($feedName) || $manager->has($entryName); + } } diff -r e200cb7efeb3 -r c2387f117808 vendor/zendframework/zend-feed/src/Reader/StandaloneExtensionManager.php --- a/vendor/zendframework/zend-feed/src/Reader/StandaloneExtensionManager.php Thu Apr 26 11:26:54 2018 +0100 +++ b/vendor/zendframework/zend-feed/src/Reader/StandaloneExtensionManager.php Tue Jul 10 15:07:59 2018 +0100 @@ -21,6 +21,8 @@ 'CreativeCommons\Feed' => Extension\CreativeCommons\Feed::class, 'DublinCore\Entry' => Extension\DublinCore\Entry::class, 'DublinCore\Feed' => Extension\DublinCore\Feed::class, + 'GooglePlayPodcast\Entry' => Extension\GooglePlayPodcast\Entry::class, + 'GooglePlayPodcast\Feed' => Extension\GooglePlayPodcast\Feed::class, 'Podcast\Entry' => Extension\Podcast\Entry::class, 'Podcast\Feed' => Extension\Podcast\Feed::class, 'Slash\Entry' => Extension\Slash\Entry::class, diff -r e200cb7efeb3 -r c2387f117808 vendor/zendframework/zend-feed/src/Writer/AbstractFeed.php --- a/vendor/zendframework/zend-feed/src/Writer/AbstractFeed.php Thu Apr 26 11:26:54 2018 +0100 +++ b/vendor/zendframework/zend-feed/src/Writer/AbstractFeed.php Tue Jul 10 15:07:59 2018 +0100 @@ -421,7 +421,7 @@ */ public function setTitle($title) { - if (empty($title) || ! is_string($title)) { + if ((empty($title) && ! is_numeric($title)) || ! is_string($title)) { throw new Exception\InvalidArgumentException('Invalid parameter: parameter must be a non-empty string'); } $this->data['title'] = $title; diff -r e200cb7efeb3 -r c2387f117808 vendor/zendframework/zend-feed/src/Writer/Entry.php --- a/vendor/zendframework/zend-feed/src/Writer/Entry.php Thu Apr 26 11:26:54 2018 +0100 +++ b/vendor/zendframework/zend-feed/src/Writer/Entry.php Tue Jul 10 15:07:59 2018 +0100 @@ -364,7 +364,7 @@ */ public function setTitle($title) { - if (empty($title) || ! is_string($title)) { + if ((empty($title) && ! is_numeric($title)) || ! is_string($title)) { throw new Exception\InvalidArgumentException('Invalid parameter: parameter must be a non-empty string'); } $this->data['title'] = $title; diff -r e200cb7efeb3 -r c2387f117808 vendor/zendframework/zend-feed/src/Writer/Extension/GooglePlayPodcast/Entry.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vendor/zendframework/zend-feed/src/Writer/Extension/GooglePlayPodcast/Entry.php Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,150 @@ +stringWrapper = StringUtils::getWrapper($this->encoding); + } + + /** + * Set feed encoding + * + * @param string $enc + * @return Entry + */ + public function setEncoding($enc) + { + $this->stringWrapper = StringUtils::getWrapper($enc); + $this->encoding = $enc; + return $this; + } + + /** + * Get feed encoding + * + * @return string + */ + public function getEncoding() + { + return $this->encoding; + } + + /** + * Set a block value of "yes" or "no". You may also set an empty string. + * + * @param string + * @return Entry + * @throws Writer\Exception\InvalidArgumentException + */ + public function setPlayPodcastBlock($value) + { + if (! ctype_alpha($value) && strlen($value) > 0) { + throw new Writer\Exception\InvalidArgumentException( + 'invalid parameter: "block" may only contain alphabetic characters' + ); + } + + if ($this->stringWrapper->strlen($value) > 255) { + throw new Writer\Exception\InvalidArgumentException( + 'invalid parameter: "block" may only contain a maximum of 255 characters' + ); + } + $this->data['block'] = $value; + } + + /** + * Set "explicit" flag + * + * @param bool $value + * @return Entry + * @throws Writer\Exception\InvalidArgumentException + */ + public function setPlayPodcastExplicit($value) + { + if (! in_array($value, ['yes', 'no', 'clean'], true)) { + throw new Writer\Exception\InvalidArgumentException( + 'invalid parameter: "explicit" may only be one of "yes", "no" or "clean"' + ); + } + $this->data['explicit'] = $value; + return $this; + } + + /** + * Set episode description + * + * @param string $value + * @return Entry + * @throws Writer\Exception\InvalidArgumentException + */ + public function setPlayPodcastDescription($value) + { + if ($this->stringWrapper->strlen($value) > 4000) { + throw new Writer\Exception\InvalidArgumentException( + 'invalid parameter: "description" may only contain a maximum of 4000 characters' + ); + } + $this->data['description'] = $value; + return $this; + } + + /** + * Overloading to itunes specific setters + * + * @param string $method + * @param array $params + * @throws Writer\Exception\BadMethodCallException + * @return mixed + */ + public function __call($method, array $params) + { + $point = lcfirst(substr($method, 14)); + if (! method_exists($this, 'setPlayPodcast' . ucfirst($point)) + && ! method_exists($this, 'addPlayPodcast' . ucfirst($point)) + ) { + throw new Writer\Exception\BadMethodCallException( + 'invalid method: ' . $method + ); + } + if (! array_key_exists($point, $this->data) + || empty($this->data[$point]) + ) { + return; + } + return $this->data[$point]; + } +} diff -r e200cb7efeb3 -r c2387f117808 vendor/zendframework/zend-feed/src/Writer/Extension/GooglePlayPodcast/Feed.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vendor/zendframework/zend-feed/src/Writer/Extension/GooglePlayPodcast/Feed.php Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,245 @@ +stringWrapper = StringUtils::getWrapper($this->encoding); + } + + /** + * Set feed encoding + * + * @param string $enc + * @return Feed + */ + public function setEncoding($enc) + { + $this->stringWrapper = StringUtils::getWrapper($enc); + $this->encoding = $enc; + return $this; + } + + /** + * Get feed encoding + * + * @return string + */ + public function getEncoding() + { + return $this->encoding; + } + + /** + * Set a block value of "yes" or "no". You may also set an empty string. + * + * @param string + * @return Feed + * @throws Writer\Exception\InvalidArgumentException + */ + public function setPlayPodcastBlock($value) + { + if (! ctype_alpha($value) && strlen($value) > 0) { + throw new Writer\Exception\InvalidArgumentException( + 'invalid parameter: "block" may only contain alphabetic characters' + ); + } + if ($this->stringWrapper->strlen($value) > 255) { + throw new Writer\Exception\InvalidArgumentException( + 'invalid parameter: "block" may only contain a maximum of 255 characters' + ); + } + $this->data['block'] = $value; + return $this; + } + + /** + * Add feed authors + * + * @param array $values + * @return Feed + */ + public function addPlayPodcastAuthors(array $values) + { + foreach ($values as $value) { + $this->addPlayPodcastAuthor($value); + } + return $this; + } + + /** + * Add feed author + * + * @param string $value + * @return Feed + * @throws Writer\Exception\InvalidArgumentException + */ + public function addPlayPodcastAuthor($value) + { + if ($this->stringWrapper->strlen($value) > 255) { + throw new Writer\Exception\InvalidArgumentException( + 'invalid parameter: any "author" may only contain a maximum of 255 characters each' + ); + } + if (! isset($this->data['authors'])) { + $this->data['authors'] = []; + } + $this->data['authors'][] = $value; + return $this; + } + + /** + * Set feed categories + * + * @param array $values + * @return Feed + * @throws Writer\Exception\InvalidArgumentException + */ + public function setPlayPodcastCategories(array $values) + { + if (! isset($this->data['categories'])) { + $this->data['categories'] = []; + } + foreach ($values as $key => $value) { + if (! is_array($value)) { + if ($this->stringWrapper->strlen($value) > 255) { + throw new Writer\Exception\InvalidArgumentException( + 'invalid parameter: any "category" may only contain a maximum of 255 characters each' + ); + } + $this->data['categories'][] = $value; + } else { + if ($this->stringWrapper->strlen($key) > 255) { + throw new Writer\Exception\InvalidArgumentException( + 'invalid parameter: any "category" may only contain a maximum of 255 characters each' + ); + } + $this->data['categories'][$key] = []; + foreach ($value as $val) { + if ($this->stringWrapper->strlen($val) > 255) { + throw new Writer\Exception\InvalidArgumentException( + 'invalid parameter: any "category" may only contain a maximum of 255 characters each' + ); + } + $this->data['categories'][$key][] = $val; + } + } + } + return $this; + } + + /** + * Set feed image (icon) + * + * @param string $value + * @return Feed + * @throws Writer\Exception\InvalidArgumentException + */ + public function setPlayPodcastImage($value) + { + if (! is_string($value) || ! Uri::factory($value)->isValid()) { + throw new Writer\Exception\InvalidArgumentException( + 'invalid parameter: "image" may only be a valid URI/IRI' + ); + } + $this->data['image'] = $value; + return $this; + } + + /** + * Set "explicit" flag + * + * @param bool $value + * @return Feed + * @throws Writer\Exception\InvalidArgumentException + */ + public function setPlayPodcastExplicit($value) + { + if (! in_array($value, ['yes', 'no', 'clean'], true)) { + throw new Writer\Exception\InvalidArgumentException( + 'invalid parameter: "explicit" may only be one of "yes", "no" or "clean"' + ); + } + $this->data['explicit'] = $value; + return $this; + } + + /** + * Set podcast description + * + * @param string $value + * @return Feed + * @throws Writer\Exception\InvalidArgumentException + */ + public function setPlayPodcastDescription($value) + { + if ($this->stringWrapper->strlen($value) > 4000) { + throw new Writer\Exception\InvalidArgumentException( + 'invalid parameter: "description" may only contain a maximum of 4000 characters' + ); + } + $this->data['description'] = $value; + return $this; + } + + /** + * Overloading: proxy to internal setters + * + * @param string $method + * @param array $params + * @return mixed + * @throws Writer\Exception\BadMethodCallException + */ + public function __call($method, array $params) + { + $point = lcfirst(substr($method, 14)); + if (! method_exists($this, 'setPlayPodcast' . ucfirst($point)) + && ! method_exists($this, 'addPlayPodcast' . ucfirst($point)) + ) { + throw new Writer\Exception\BadMethodCallException( + 'invalid method: ' . $method + ); + } + + if (! array_key_exists($point, $this->data) || empty($this->data[$point])) { + return; + } + return $this->data[$point]; + } +} diff -r e200cb7efeb3 -r c2387f117808 vendor/zendframework/zend-feed/src/Writer/Extension/GooglePlayPodcast/Renderer/Entry.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vendor/zendframework/zend-feed/src/Writer/Extension/GooglePlayPodcast/Renderer/Entry.php Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,120 @@ +_setBlock($this->dom, $this->base); + $this->_setExplicit($this->dom, $this->base); + $this->_setDescription($this->dom, $this->base); + if ($this->called) { + $this->_appendNamespaces(); + } + } + + /** + * Append namespaces to entry root + * + * @return void + */ + // @codingStandardsIgnoreStart + protected function _appendNamespaces() + { + // @codingStandardsIgnoreEnd + $this->getRootElement()->setAttribute( + 'xmlns:googleplay', + 'http://www.google.com/schemas/play-podcasts/1.0' + ); + } + + /** + * Set itunes block + * + * @param DOMDocument $dom + * @param DOMElement $root + * @return void + */ + // @codingStandardsIgnoreStart + protected function _setBlock(DOMDocument $dom, DOMElement $root) + { + // @codingStandardsIgnoreEnd + $block = $this->getDataContainer()->getPlayPodcastBlock(); + if ($block === null) { + return; + } + $el = $dom->createElement('googleplay:block'); + $text = $dom->createTextNode($block); + $el->appendChild($text); + $root->appendChild($el); + $this->called = true; + } + + /** + * Set explicit flag + * + * @param DOMDocument $dom + * @param DOMElement $root + * @return void + */ + // @codingStandardsIgnoreStart + protected function _setExplicit(DOMDocument $dom, DOMElement $root) + { + // @codingStandardsIgnoreEnd + $explicit = $this->getDataContainer()->getPlayPodcastExplicit(); + if ($explicit === null) { + return; + } + $el = $dom->createElement('googleplay:explicit'); + $text = $dom->createTextNode($explicit); + $el->appendChild($text); + $root->appendChild($el); + $this->called = true; + } + + /** + * Set episode description + * + * @param DOMDocument $dom + * @param DOMElement $root + * @return void + */ + // @codingStandardsIgnoreStart + protected function _setDescription(DOMDocument $dom, DOMElement $root) + { + // @codingStandardsIgnoreEnd + $description = $this->getDataContainer()->getPlayPodcastDescription(); + if (! $description) { + return; + } + $el = $dom->createElement('googleplay:description'); + $text = $dom->createTextNode($description); + $el->appendChild($text); + $root->appendChild($el); + $this->called = true; + } +} diff -r e200cb7efeb3 -r c2387f117808 vendor/zendframework/zend-feed/src/Writer/Extension/GooglePlayPodcast/Renderer/Feed.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vendor/zendframework/zend-feed/src/Writer/Extension/GooglePlayPodcast/Renderer/Feed.php Tue Jul 10 15:07:59 2018 +0100 @@ -0,0 +1,202 @@ +_setAuthors($this->dom, $this->base); + $this->_setBlock($this->dom, $this->base); + $this->_setCategories($this->dom, $this->base); + $this->_setImage($this->dom, $this->base); + $this->_setExplicit($this->dom, $this->base); + $this->_setDescription($this->dom, $this->base); + if ($this->called) { + $this->_appendNamespaces(); + } + } + + /** + * Append feed namespaces + * + * @return void + */ + // @codingStandardsIgnoreStart + protected function _appendNamespaces() + { + // @codingStandardsIgnoreEnd + $this->getRootElement()->setAttribute( + 'xmlns:googleplay', + 'http://www.google.com/schemas/play-podcasts/1.0' + ); + } + + /** + * Set feed authors + * + * @param DOMDocument $dom + * @param DOMElement $root + * @return void + */ + // @codingStandardsIgnoreStart + protected function _setAuthors(DOMDocument $dom, DOMElement $root) + { + // @codingStandardsIgnoreEnd + $authors = $this->getDataContainer()->getPlayPodcastAuthors(); + if (! $authors || empty($authors)) { + return; + } + foreach ($authors as $author) { + $el = $dom->createElement('googleplay:author'); + $text = $dom->createTextNode($author); + $el->appendChild($text); + $root->appendChild($el); + } + $this->called = true; + } + + /** + * Set feed itunes block + * + * @param DOMDocument $dom + * @param DOMElement $root + * @return void + */ + // @codingStandardsIgnoreStart + protected function _setBlock(DOMDocument $dom, DOMElement $root) + { + // @codingStandardsIgnoreEnd + $block = $this->getDataContainer()->getPlayPodcastBlock(); + if ($block === null) { + return; + } + $el = $dom->createElement('googleplay:block'); + $text = $dom->createTextNode($block); + $el->appendChild($text); + $root->appendChild($el); + $this->called = true; + } + + /** + * Set feed categories + * + * @param DOMDocument $dom + * @param DOMElement $root + * @return void + */ + // @codingStandardsIgnoreStart + protected function _setCategories(DOMDocument $dom, DOMElement $root) + { + // @codingStandardsIgnoreEnd + $cats = $this->getDataContainer()->getPlayPodcastCategories(); + if (! $cats || empty($cats)) { + return; + } + foreach ($cats as $key => $cat) { + if (! is_array($cat)) { + $el = $dom->createElement('googleplay:category'); + $el->setAttribute('text', $cat); + $root->appendChild($el); + } else { + $el = $dom->createElement('googleplay:category'); + $el->setAttribute('text', $key); + $root->appendChild($el); + foreach ($cat as $subcat) { + $el2 = $dom->createElement('googleplay:category'); + $el2->setAttribute('text', $subcat); + $el->appendChild($el2); + } + } + } + $this->called = true; + } + + /** + * Set feed image (icon) + * + * @param DOMDocument $dom + * @param DOMElement $root + * @return void + */ + // @codingStandardsIgnoreStart + protected function _setImage(DOMDocument $dom, DOMElement $root) + { + // @codingStandardsIgnoreEnd + $image = $this->getDataContainer()->getPlayPodcastImage(); + if (! $image) { + return; + } + $el = $dom->createElement('googleplay:image'); + $el->setAttribute('href', $image); + $root->appendChild($el); + $this->called = true; + } + + /** + * Set explicit flag + * + * @param DOMDocument $dom + * @param DOMElement $root + * @return void + */ + // @codingStandardsIgnoreStart + protected function _setExplicit(DOMDocument $dom, DOMElement $root) + { + // @codingStandardsIgnoreEnd + $explicit = $this->getDataContainer()->getPlayPodcastExplicit(); + if ($explicit === null) { + return; + } + $el = $dom->createElement('googleplay:explicit'); + $text = $dom->createTextNode($explicit); + $el->appendChild($text); + $root->appendChild($el); + $this->called = true; + } + + /** + * Set podcast description + * + * @param DOMDocument $dom + * @param DOMElement $root + * @return void + */ + // @codingStandardsIgnoreStart + protected function _setDescription(DOMDocument $dom, DOMElement $root) + { + // @codingStandardsIgnoreEnd + $description = $this->getDataContainer()->getPlayPodcastDescription(); + if (! $description) { + return; + } + $el = $dom->createElement('googleplay:description'); + $text = $dom->createTextNode($description); + $el->appendChild($text); + $root->appendChild($el); + $this->called = true; + } +} diff -r e200cb7efeb3 -r c2387f117808 vendor/zendframework/zend-feed/src/Writer/Extension/ITunes/Entry.php --- a/vendor/zendframework/zend-feed/src/Writer/Extension/ITunes/Entry.php Thu Apr 26 11:26:54 2018 +0100 +++ b/vendor/zendframework/zend-feed/src/Writer/Extension/ITunes/Entry.php Tue Jul 10 15:07:59 2018 +0100 @@ -9,6 +9,7 @@ namespace Zend\Feed\Writer\Extension\ITunes; +use Zend\Feed\Uri; use Zend\Feed\Writer; use Zend\Stdlib\StringUtils; use Zend\Stdlib\StringWrapper\StringWrapperInterface; @@ -162,12 +163,20 @@ /** * Set keywords * + * @deprecated since 2.10.0; itunes:keywords is no longer part of the + * iTunes podcast RSS specification. * @param array $value * @return Entry * @throws Writer\Exception\InvalidArgumentException */ public function setItunesKeywords(array $value) { + trigger_error( + 'itunes:keywords has been deprecated in the iTunes podcast RSS specification,' + . ' and should not be relied on.', + \E_USER_DEPRECATED + ); + if (count($value) > 12) { throw new Writer\Exception\InvalidArgumentException('invalid parameter: "keywords" may only' . ' contain a maximum of 12 terms'); @@ -218,6 +227,123 @@ } /** + * Set entry image (icon) + * + * @param string $value + * @return Feed + * @throws Writer\Exception\InvalidArgumentException + */ + public function setItunesImage($value) + { + if (! is_string($value) || ! Uri::factory($value)->isValid()) { + throw new Writer\Exception\InvalidArgumentException( + 'invalid parameter: "image" may only be a valid URI/IRI' + ); + } + + if (! in_array(substr($value, -3), ['jpg', 'png'])) { + throw new Writer\Exception\InvalidArgumentException( + 'invalid parameter: "image" may only use file extension "jpg"' + . ' or "png" which must be the last three characters of the URI' + . ' (i.e. no query string or fragment)' + ); + } + + $this->data['image'] = $value; + return $this; + } + + /** + * Set the episode number + * + * @param int $number + * @return self + * @throws Writer\Exception\InvalidArgumentException + */ + public function setItunesEpisode($number) + { + if (! is_numeric($number) || is_float($number)) { + throw new Writer\Exception\InvalidArgumentException(sprintf( + 'invalid parameter: "number" may only be an integer; received %s', + is_object($number) ? get_class($number) : gettype($number) + )); + } + + $this->data['episode'] = (int) $number; + + return $this; + } + + /** + * Set the episode type + * + * @param string $type One of "full", "trailer", or "bonus". + * @return self + * @throws Writer\Exception\InvalidArgumentException + */ + public function setItunesEpisodeType($type) + { + $validTypes = ['full', 'trailer', 'bonus']; + if (! in_array($type, $validTypes, true)) { + throw new Writer\Exception\InvalidArgumentException(sprintf( + 'invalid parameter: "episodeType" MUST be one of the strings [%s]; received %s', + implode(', ', $validTypes), + is_object($type) ? get_class($type) : var_export($type, true) + )); + } + + $this->data['episodeType'] = $type; + + return $this; + } + + /** + * Set the status of closed captioning + * + * @param bool $status + * @return self + * @throws Writer\Exception\InvalidArgumentException + */ + public function setItunesIsClosedCaptioned($status) + { + if (! is_bool($status)) { + throw new Writer\Exception\InvalidArgumentException(sprintf( + 'invalid parameter: "isClosedCaptioned" MUST be a boolean; received %s', + is_object($status) ? get_class($status) : var_export($status, true) + )); + } + + if (! $status) { + return $this; + } + + $this->data['isClosedCaptioned'] = true; + + return $this; + } + + /** + * Set the season number to which the episode belongs + * + * @param int $number + * @return self + * @throws Writer\Exception\InvalidArgumentException + */ + public function setItunesSeason($number) + { + if (! is_numeric($number) || is_float($number)) { + throw new Writer\Exception\InvalidArgumentException(sprintf( + 'invalid parameter: "season" may only be an integer; received %s', + is_object($number) ? get_class($number) : gettype($number) + )); + } + + $this->data['season'] = (int) $number; + + return $this; + } + + /** * Overloading to itunes specific setters * * @param string $method diff -r e200cb7efeb3 -r c2387f117808 vendor/zendframework/zend-feed/src/Writer/Extension/ITunes/Feed.php --- a/vendor/zendframework/zend-feed/src/Writer/Extension/ITunes/Feed.php Thu Apr 26 11:26:54 2018 +0100 +++ b/vendor/zendframework/zend-feed/src/Writer/Extension/ITunes/Feed.php Tue Jul 10 15:07:59 2018 +0100 @@ -169,7 +169,7 @@ */ public function setItunesImage($value) { - if (! Uri::factory($value)->isValid()) { + if (! is_string($value) || ! Uri::factory($value)->isValid()) { throw new Writer\Exception\InvalidArgumentException('invalid parameter: "image" may only' . ' be a valid URI/IRI'); } @@ -223,12 +223,20 @@ /** * Set feed keywords * + * @deprecated since 2.10.0; itunes:keywords is no longer part of the + * iTunes podcast RSS specification. * @param array $value * @return Feed * @throws Writer\Exception\InvalidArgumentException */ public function setItunesKeywords(array $value) { + trigger_error( + 'itunes:keywords has been deprecated in the iTunes podcast RSS specification,' + . ' and should not be relied on.', + \E_USER_DEPRECATED + ); + if (count($value) > 12) { throw new Writer\Exception\InvalidArgumentException('invalid parameter: "keywords" may only' . ' contain a maximum of 12 terms'); @@ -335,6 +343,51 @@ } /** + * Set podcast type + * + * @param string $type + * @return Feed + * @throws Writer\Exception\InvalidArgumentException + */ + public function setItunesType($type) + { + $validTypes = ['episodic', 'serial']; + if (! in_array($type, $validTypes, true)) { + throw new Writer\Exception\InvalidArgumentException(sprintf( + 'invalid parameter: "type" MUST be one of [%s]; received %s', + implode(', ', $validTypes), + is_object($type) ? get_class($type) : var_export($type, true) + )); + } + $this->data['type'] = $type; + return $this; + } + + /** + * Set "completion" status (whether more episodes will be released) + * + * @param bool $status + * @return Feed + * @throws Writer\Exception\InvalidArgumentException + */ + public function setItunesComplete($status) + { + if (! is_bool($status)) { + throw new Writer\Exception\InvalidArgumentException(sprintf( + 'invalid parameter: "complete" MUST be boolean; received %s', + is_object($status) ? get_class($status) : var_export($status, true) + )); + } + + if (! $status) { + return $this; + } + + $this->data['complete'] = 'Yes'; + return $this; + } + + /** * Overloading: proxy to internal setters * * @param string $method @@ -352,6 +405,7 @@ 'invalid method: ' . $method ); } + if (! array_key_exists($point, $this->data) || empty($this->data[$point])) { return; } diff -r e200cb7efeb3 -r c2387f117808 vendor/zendframework/zend-feed/src/Writer/Extension/ITunes/Renderer/Entry.php --- a/vendor/zendframework/zend-feed/src/Writer/Extension/ITunes/Renderer/Entry.php Thu Apr 26 11:26:54 2018 +0100 +++ b/vendor/zendframework/zend-feed/src/Writer/Extension/ITunes/Renderer/Entry.php Tue Jul 10 15:07:59 2018 +0100 @@ -36,10 +36,15 @@ $this->_setAuthors($this->dom, $this->base); $this->_setBlock($this->dom, $this->base); $this->_setDuration($this->dom, $this->base); + $this->_setImage($this->dom, $this->base); $this->_setExplicit($this->dom, $this->base); $this->_setKeywords($this->dom, $this->base); $this->_setSubtitle($this->dom, $this->base); $this->_setSummary($this->dom, $this->base); + $this->_setEpisode($this->dom, $this->base); + $this->_setEpisodeType($this->dom, $this->base); + $this->_setClosedCaptioned($this->dom, $this->base); + $this->_setSeason($this->dom, $this->base); if ($this->called) { $this->_appendNamespaces(); } @@ -129,6 +134,27 @@ } /** + * Set feed image (icon) + * + * @param DOMDocument $dom + * @param DOMElement $root + * @return void + */ + // @codingStandardsIgnoreStart + protected function _setImage(DOMDocument $dom, DOMElement $root) + { + // @codingStandardsIgnoreEnd + $image = $this->getDataContainer()->getItunesImage(); + if (! $image) { + return; + } + $el = $dom->createElement('itunes:image'); + $el->setAttribute('href', $image); + $root->appendChild($el); + $this->called = true; + } + + /** * Set explicit flag * * @param DOMDocument $dom @@ -215,4 +241,92 @@ $root->appendChild($el); $this->called = true; } + + /** + * Set entry episode number + * + * @param DOMDocument $dom + * @param DOMElement $root + * @return void + */ + // @codingStandardsIgnoreStart + protected function _setEpisode(DOMDocument $dom, DOMElement $root) + { + // @codingStandardsIgnoreEnd + $episode = $this->getDataContainer()->getItunesEpisode(); + if (! $episode) { + return; + } + $el = $dom->createElement('itunes:episode'); + $text = $dom->createTextNode($episode); + $el->appendChild($text); + $root->appendChild($el); + $this->called = true; + } + + /** + * Set entry episode type + * + * @param DOMDocument $dom + * @param DOMElement $root + * @return void + */ + // @codingStandardsIgnoreStart + protected function _setEpisodeType(DOMDocument $dom, DOMElement $root) + { + // @codingStandardsIgnoreEnd + $type = $this->getDataContainer()->getItunesEpisodeType(); + if (! $type) { + return; + } + $el = $dom->createElement('itunes:episodeType'); + $text = $dom->createTextNode($type); + $el->appendChild($text); + $root->appendChild($el); + $this->called = true; + } + + /** + * Set closed captioning status for episode + * + * @param DOMDocument $dom + * @param DOMElement $root + * @return void + */ + // @codingStandardsIgnoreStart + protected function _setClosedCaptioned(DOMDocument $dom, DOMElement $root) + { + // @codingStandardsIgnoreEnd + $status = $this->getDataContainer()->getItunesIsClosedCaptioned(); + if (! $status) { + return; + } + $el = $dom->createElement('itunes:isClosedCaptioned'); + $text = $dom->createTextNode('Yes'); + $el->appendChild($text); + $root->appendChild($el); + $this->called = true; + } + + /** + * Set entry season number + * + * @param DOMDocument $dom + * @param DOMElement $root + * @return void + */ + // @codingStandardsIgnoreStart + protected function _setSeason(DOMDocument $dom, DOMElement $root) + { + // @codingStandardsIgnoreEnd + $season = $this->getDataContainer()->getItunesSeason(); + if (! $season) { + return; + } + $el = $dom->createElement('itunes:season'); + $text = $dom->createTextNode($season); + $el->appendChild($text); + $root->appendChild($el); + $this->called = true; + } } diff -r e200cb7efeb3 -r c2387f117808 vendor/zendframework/zend-feed/src/Writer/Extension/ITunes/Renderer/Feed.php --- a/vendor/zendframework/zend-feed/src/Writer/Extension/ITunes/Renderer/Feed.php Thu Apr 26 11:26:54 2018 +0100 +++ b/vendor/zendframework/zend-feed/src/Writer/Extension/ITunes/Renderer/Feed.php Tue Jul 10 15:07:59 2018 +0100 @@ -44,6 +44,8 @@ $this->_setOwners($this->dom, $this->base); $this->_setSubtitle($this->dom, $this->base); $this->_setSummary($this->dom, $this->base); + $this->_setType($this->dom, $this->base); + $this->_setComplete($this->dom, $this->base); if ($this->called) { $this->_appendNamespaces(); } @@ -326,4 +328,48 @@ $root->appendChild($el); $this->called = true; } + + /** + * Set podcast type + * + * @param DOMDocument $dom + * @param DOMElement $root + * @return void + */ + // @codingStandardsIgnoreStart + protected function _setType(DOMDocument $dom, DOMElement $root) + { + // @codingStandardsIgnoreEnd + $type = $this->getDataContainer()->getItunesType(); + if (! $type) { + return; + } + $el = $dom->createElement('itunes:type'); + $text = $dom->createTextNode($type); + $el->appendChild($text); + $root->appendChild($el); + $this->called = true; + } + + /** + * Set complete status + * + * @param DOMDocument $dom + * @param DOMElement $root + * @return void + */ + // @codingStandardsIgnoreStart + protected function _setComplete(DOMDocument $dom, DOMElement $root) + { + // @codingStandardsIgnoreEnd + $status = $this->getDataContainer()->getItunesComplete(); + if (! $status) { + return; + } + $el = $dom->createElement('itunes:complete'); + $text = $dom->createTextNode('Yes'); + $el->appendChild($text); + $root->appendChild($el); + $this->called = true; + } } diff -r e200cb7efeb3 -r c2387f117808 vendor/zendframework/zend-feed/src/Writer/ExtensionPluginManager.php --- a/vendor/zendframework/zend-feed/src/Writer/ExtensionPluginManager.php Thu Apr 26 11:26:54 2018 +0100 +++ b/vendor/zendframework/zend-feed/src/Writer/ExtensionPluginManager.php Tue Jul 10 15:07:59 2018 +0100 @@ -46,6 +46,30 @@ 'DublinCoreRendererFeed' => Extension\DublinCore\Renderer\Feed::class, 'DublinCoreRenderer\Feed' => Extension\DublinCore\Renderer\Feed::class, 'DublinCore\Renderer\Feed' => Extension\DublinCore\Renderer\Feed::class, + 'googleplaypodcastentry' => Extension\GooglePlayPodcast\Entry::class, + 'googleplaypodcastEntry' => Extension\GooglePlayPodcast\Entry::class, + 'googlePlayPodcastEntry' => Extension\GooglePlayPodcast\Entry::class, + 'GooglePlayPodcastEntry' => Extension\GooglePlayPodcast\Entry::class, + 'Googleplaypodcast\Entry' => Extension\GooglePlayPodcast\Entry::class, + 'GooglePlayPodcast\Entry' => Extension\GooglePlayPodcast\Entry::class, + 'googleplaypodcastfeed' => Extension\GooglePlayPodcast\Feed::class, + 'googleplaypodcastFeed' => Extension\GooglePlayPodcast\Feed::class, + 'googlePlayPodcastFeed' => Extension\GooglePlayPodcast\Feed::class, + 'GooglePlayPodcastFeed' => Extension\GooglePlayPodcast\Feed::class, + 'Googleplaypodcast\Feed' => Extension\GooglePlayPodcast\Feed::class, + 'GooglePlayPodcast\Feed' => Extension\GooglePlayPodcast\Feed::class, + 'googleplaypodcastrendererentry' => Extension\GooglePlayPodcast\Renderer\Entry::class, + 'googleplaypodcastRendererEntry' => Extension\GooglePlayPodcast\Renderer\Entry::class, + 'googlePlayPodcastRendererEntry' => Extension\GooglePlayPodcast\Renderer\Entry::class, + 'GooglePlayPodcastRendererEntry' => Extension\GooglePlayPodcast\Renderer\Entry::class, + 'GoogleplaypodcastRenderer\Entry' => Extension\GooglePlayPodcast\Renderer\Entry::class, + 'GooglePlayPodcast\Renderer\Entry' => Extension\GooglePlayPodcast\Renderer\Entry::class, + 'googleplaypodcastrendererfeed' => Extension\GooglePlayPodcast\Renderer\Feed::class, + 'googleplaypodcastRendererFeed' => Extension\GooglePlayPodcast\Renderer\Feed::class, + 'googlePlayPodcastRendererFeed' => Extension\GooglePlayPodcast\Renderer\Feed::class, + 'GooglePlayPodcastRendererFeed' => Extension\GooglePlayPodcast\Renderer\Feed::class, + 'GoogleplaypodcastRenderer\Feed' => Extension\GooglePlayPodcast\Renderer\Feed::class, + 'GooglePlayPodcast\Renderer\Feed' => Extension\GooglePlayPodcast\Renderer\Feed::class, 'itunesentry' => Extension\ITunes\Entry::class, 'itunesEntry' => Extension\ITunes\Entry::class, 'iTunesEntry' => Extension\ITunes\Entry::class, @@ -97,6 +121,10 @@ Extension\Content\Renderer\Entry::class => InvokableFactory::class, Extension\DublinCore\Renderer\Entry::class => InvokableFactory::class, Extension\DublinCore\Renderer\Feed::class => InvokableFactory::class, + Extension\GooglePlayPodcast\Entry::class => InvokableFactory::class, + Extension\GooglePlayPodcast\Feed::class => InvokableFactory::class, + Extension\GooglePlayPodcast\Renderer\Entry::class => InvokableFactory::class, + Extension\GooglePlayPodcast\Renderer\Feed::class => InvokableFactory::class, Extension\ITunes\Entry::class => InvokableFactory::class, Extension\ITunes\Feed::class => InvokableFactory::class, Extension\ITunes\Renderer\Entry::class => InvokableFactory::class, @@ -111,6 +139,11 @@ 'zendfeedwriterextensioncontentrendererentry' => InvokableFactory::class, 'zendfeedwriterextensiondublincorerendererentry' => InvokableFactory::class, 'zendfeedwriterextensiondublincorerendererfeed' => InvokableFactory::class, + 'zendfeedwriterextensiongoogleplaypodcastentry' => InvokableFactory::class, + 'zendfeedwriterextensiongoogleplaypodcastfeed' => InvokableFactory::class, + 'zendfeedwriterextensiongoogleplaypodcastrendererentry' => InvokableFactory::class, + 'zendfeedwriterextensiongoogleplaypodcastrendererfeed' => InvokableFactory::class, + 'zendfeedwriterextensionitunesentry' => InvokableFactory::class, 'zendfeedwriterextensionitunesfeed' => InvokableFactory::class, 'zendfeedwriterextensionitunesrendererentry' => InvokableFactory::class, diff -r e200cb7efeb3 -r c2387f117808 vendor/zendframework/zend-feed/src/Writer/Renderer/AbstractRenderer.php --- a/vendor/zendframework/zend-feed/src/Writer/Renderer/AbstractRenderer.php Thu Apr 26 11:26:54 2018 +0100 +++ b/vendor/zendframework/zend-feed/src/Writer/Renderer/AbstractRenderer.php Tue Jul 10 15:07:59 2018 +0100 @@ -222,11 +222,9 @@ Writer\Writer::registerCoreExtensions(); $manager = Writer\Writer::getExtensionManager(); $all = Writer\Writer::getExtensions(); - if (stripos(get_class($this), 'entry')) { - $exts = $all['entryRenderer']; - } else { - $exts = $all['feedRenderer']; - } + $exts = stripos(get_class($this), 'entry') + ? $all['entryRenderer'] + : $all['feedRenderer']; foreach ($exts as $extension) { $plugin = $manager->get($extension); $plugin->setDataContainer($this->getDataContainer()); diff -r e200cb7efeb3 -r c2387f117808 vendor/zendframework/zend-feed/src/Writer/StandaloneExtensionManager.php --- a/vendor/zendframework/zend-feed/src/Writer/StandaloneExtensionManager.php Thu Apr 26 11:26:54 2018 +0100 +++ b/vendor/zendframework/zend-feed/src/Writer/StandaloneExtensionManager.php Tue Jul 10 15:07:59 2018 +0100 @@ -18,6 +18,10 @@ 'Content\Renderer\Entry' => Extension\Content\Renderer\Entry::class, 'DublinCore\Renderer\Entry' => Extension\DublinCore\Renderer\Entry::class, 'DublinCore\Renderer\Feed' => Extension\DublinCore\Renderer\Feed::class, + 'GooglePlayPodcast\Entry' => Extension\GooglePlayPodcast\Entry::class, + 'GooglePlayPodcast\Feed' => Extension\GooglePlayPodcast\Feed::class, + 'GooglePlayPodcast\Renderer\Entry' => Extension\GooglePlayPodcast\Renderer\Entry::class, + 'GooglePlayPodcast\Renderer\Feed' => Extension\GooglePlayPodcast\Renderer\Feed::class, 'ITunes\Entry' => Extension\ITunes\Entry::class, 'ITunes\Feed' => Extension\ITunes\Feed::class, 'ITunes\Renderer\Entry' => Extension\ITunes\Renderer\Entry::class, diff -r e200cb7efeb3 -r c2387f117808 vendor/zendframework/zend-feed/src/Writer/Writer.php --- a/vendor/zendframework/zend-feed/src/Writer/Writer.php Thu Apr 26 11:26:54 2018 +0100 +++ b/vendor/zendframework/zend-feed/src/Writer/Writer.php Tue Jul 10 15:07:59 2018 +0100 @@ -91,40 +91,36 @@ */ public static function registerExtension($name) { - $feedName = $name . '\Feed'; - $entryName = $name . '\Entry'; - $feedRendererName = $name . '\Renderer\Feed'; - $entryRendererName = $name . '\Renderer\Entry'; - $manager = static::getExtensionManager(); - if (static::isRegistered($name)) { - if ($manager->has($feedName) - || $manager->has($entryName) - || $manager->has($feedRendererName) - || $manager->has($entryRendererName) - ) { - return; - } - } - if (! $manager->has($feedName) - && ! $manager->has($entryName) - && ! $manager->has($feedRendererName) - && ! $manager->has($entryRendererName) - ) { + if (! static::hasExtension($name)) { throw new Exception\RuntimeException(sprintf( - 'Could not load extension "%s" using Plugin Loader. ' - . 'Check prefix paths are configured and extension exists.', + 'Could not load extension "%s" using Plugin Loader.' + . ' Check prefix paths are configured and extension exists.', $name )); } + + if (static::isRegistered($name)) { + return; + } + + $manager = static::getExtensionManager(); + + $feedName = $name . '\Feed'; if ($manager->has($feedName)) { static::$extensions['feed'][] = $feedName; } + + $entryName = $name . '\Entry'; if ($manager->has($entryName)) { static::$extensions['entry'][] = $entryName; } + + $feedRendererName = $name . '\Renderer\Feed'; if ($manager->has($feedRendererName)) { static::$extensions['feedRenderer'][] = $feedRendererName; } + + $entryRendererName = $name . '\Renderer\Entry'; if ($manager->has($entryRendererName)) { static::$extensions['entryRenderer'][] = $entryRendererName; } @@ -192,6 +188,21 @@ static::registerExtension('WellFormedWeb'); static::registerExtension('Threading'); static::registerExtension('ITunes'); + + // Added in 2.10.0; check for it conditionally + static::hasExtension('GooglePlayPodcast') + ? static::registerExtension('GooglePlayPodcast') + : trigger_error( + sprintf( + 'Please update your %1$s\ExtensionManagerInterface implementation to add entries for' + . ' %1$s\Extension\GooglePlayPodcast\Entry,' + . ' %1$s\Extension\GooglePlayPodcast\Feed,' + . ' %1$s\Extension\GooglePlayPodcast\Renderer\Entry,' + . ' and %1$s\Extension\GooglePlayPodcast\Renderer\Feed.', + __NAMESPACE__ + ), + \E_USER_NOTICE + ); } public static function lcfirst($str) @@ -199,4 +210,34 @@ $str[0] = strtolower($str[0]); return $str; } + + /** + * Does the extension manager have the named extension? + * + * This method exists to allow us to test if an extension is present in the + * extension manager. It may be used by registerExtension() to determine if + * the extension has items present in the manager, or by + * registerCoreExtension() to determine if the core extension has entries + * in the extension manager. In the latter case, this can be useful when + * adding new extensions in a minor release, as custom extension manager + * implementations may not yet have an entry for the extension, which would + * then otherwise cause registerExtension() to fail. + * + * @param string $name + * @return bool + */ + protected static function hasExtension($name) + { + $manager = static::getExtensionManager(); + + $feedName = $name . '\Feed'; + $entryName = $name . '\Entry'; + $feedRendererName = $name . '\Renderer\Feed'; + $entryRendererName = $name . '\Renderer\Entry'; + + return $manager->has($feedName) + || $manager->has($entryName) + || $manager->has($feedRendererName) + || $manager->has($entryRendererName); + } } diff -r e200cb7efeb3 -r c2387f117808 vendor/zendframework/zend-stdlib/CHANGELOG.md --- a/vendor/zendframework/zend-stdlib/CHANGELOG.md Thu Apr 26 11:26:54 2018 +0100 +++ b/vendor/zendframework/zend-stdlib/CHANGELOG.md Tue Jul 10 15:07:59 2018 +0100 @@ -2,6 +2,28 @@ All notable changes to this project will be documented in this file, in reverse chronological order by release. +## 3.2.0 - 2018-04-30 + +### Added + +- [#87](https://github.com/zendframework/zend-stdlib/pull/87) adds support for PHP 7.2. + +### Changed + +- Nothing. + +### Deprecated + +- Nothing. + +### Removed + +- [#87](https://github.com/zendframework/zend-stdlib/pull/87) removes support for HHVM. + +### Fixed + +- Nothing. + ## 3.1.1 - 2018-04-12 ### Added diff -r e200cb7efeb3 -r c2387f117808 vendor/zendframework/zend-stdlib/CONDUCT.md --- a/vendor/zendframework/zend-stdlib/CONDUCT.md Thu Apr 26 11:26:54 2018 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,43 +0,0 @@ -# Contributor Code of Conduct - -The Zend Framework project adheres to [The Code Manifesto](http://codemanifesto.com) -as its guidelines for contributor interactions. - -## The Code Manifesto - -We want to work in an ecosystem that empowers developers to reach their -potential — one that encourages growth and effective collaboration. A space that -is safe for all. - -A space such as this benefits everyone that participates in it. It encourages -new developers to enter our field. It is through discussion and collaboration -that we grow, and through growth that we improve. - -In the effort to create such a place, we hold to these values: - -1. **Discrimination limits us.** This includes discrimination on the basis of - race, gender, sexual orientation, gender identity, age, nationality, technology - and any other arbitrary exclusion of a group of people. -2. **Boundaries honor us.** Your comfort levels are not everyone’s comfort - levels. Remember that, and if brought to your attention, heed it. -3. **We are our biggest assets.** None of us were born masters of our trade. - Each of us has been helped along the way. Return that favor, when and where - you can. -4. **We are resources for the future.** As an extension of #3, share what you - know. Make yourself a resource to help those that come after you. -5. **Respect defines us.** Treat others as you wish to be treated. Make your - discussions, criticisms and debates from a position of respectfulness. Ask - yourself, is it true? Is it necessary? Is it constructive? Anything less is - unacceptable. -6. **Reactions require grace.** Angry responses are valid, but abusive language - and vindictive actions are toxic. When something happens that offends you, - handle it assertively, but be respectful. Escalate reasonably, and try to - allow the offender an opportunity to explain themselves, and possibly correct - the issue. -7. **Opinions are just that: opinions.** Each and every one of us, due to our - background and upbringing, have varying opinions. The fact of the matter, is - that is perfectly acceptable. Remember this: if you respect your own - opinions, you should respect the opinions of others. -8. **To err is human.** You might not intend it, but mistakes do happen and - contribute to build experience. Tolerate honest mistakes, and don't hesitate - to apologize if you make one yourself. diff -r e200cb7efeb3 -r c2387f117808 vendor/zendframework/zend-stdlib/CONTRIBUTING.md --- a/vendor/zendframework/zend-stdlib/CONTRIBUTING.md Thu Apr 26 11:26:54 2018 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,244 +0,0 @@ -# CONTRIBUTING - -## RESOURCES - -If you wish to contribute to Zend Framework, please be sure to -read/subscribe to the following resources: - - - [Coding Standards](https://github.com/zendframework/zf2/wiki/Coding-Standards) - - [Contributor's Guide](http://framework.zend.com/participate/contributor-guide) - - ZF Contributor's mailing list: - Archives: http://zend-framework-community.634137.n4.nabble.com/ZF-Contributor-f680267.html - Subscribe: zf-contributors-subscribe@lists.zend.com - - ZF Contributor's IRC channel: - #zftalk.dev on Freenode.net - -If you are working on new features or refactoring [create a proposal](https://github.com/zendframework/zend-stdlib/issues/new). - -## Reporting Potential Security Issues - -If you have encountered a potential security vulnerability, please **DO NOT** report it on the public -issue tracker: send it to us at [zf-security@zend.com](mailto:zf-security@zend.com) instead. -We will work with you to verify the vulnerability and patch it as soon as possible. - -When reporting issues, please provide the following information: - -- Component(s) affected -- A description indicating how to reproduce the issue -- A summary of the security vulnerability and impact - -We request that you contact us via the email address above and give the project -contributors a chance to resolve the vulnerability and issue a new release prior -to any public exposure; this helps protect users and provides them with a chance -to upgrade and/or update in order to protect their applications. - -For sensitive email communications, please use [our PGP key](http://framework.zend.com/zf-security-pgp-key.asc). - -## RUNNING TESTS - -> ### Note: testing versions prior to 2.4 -> -> This component originates with Zend Framework 2. During the lifetime of ZF2, -> testing infrastructure migrated from PHPUnit 3 to PHPUnit 4. In most cases, no -> changes were necessary. However, due to the migration, tests may not run on -> versions < 2.4. As such, you may need to change the PHPUnit dependency if -> attempting a fix on such a version. - -To run tests: - -- Clone the repository: - - ```console - $ git clone git@github.com:zendframework/zend-stdlib.git - $ cd - ``` - -- Install dependencies via composer: - - ```console - $ curl -sS https://getcomposer.org/installer | php -- - $ ./composer.phar install - ``` - - If you don't have `curl` installed, you can also download `composer.phar` from https://getcomposer.org/ - -- Run the tests via `phpunit` and the provided PHPUnit config, like in this example: - - ```console - $ ./vendor/bin/phpunit - ``` - -You can turn on conditional tests with the phpunit.xml file. -To do so: - - - Copy `phpunit.xml.dist` file to `phpunit.xml` - - Edit `phpunit.xml` to enable any specific functionality you - want to test, as well as to provide test values to utilize. - -## Running Coding Standards Checks - -This component uses [php-cs-fixer](http://cs.sensiolabs.org/) for coding -standards checks, and provides configuration for our selected checks. -`php-cs-fixer` is installed by default via Composer. - -To run checks only: - -```console -$ ./vendor/bin/php-cs-fixer fix . -v --diff --dry-run --config-file=.php_cs -``` - -To have `php-cs-fixer` attempt to fix problems for you, omit the `--dry-run` -flag: - -```console -$ ./vendor/bin/php-cs-fixer fix . -v --diff --config-file=.php_cs -``` - -If you allow php-cs-fixer to fix CS issues, please re-run the tests to ensure -they pass, and make sure you add and commit the changes after verification. - -## Benchmarks - -We provide benchmark tests for zend-stdlib under the directory [benchmark/](benchmark/), -using. [athletic](https://github.com/polyfractal/athletic). You can execute -the benchmarks running the following command: - -```bash -$ ./vendor/bin/athletic -p benchmark -``` - -## Recommended Workflow for Contributions - -Your first step is to establish a public repository from which we can -pull your work into the master repository. We recommend using -[GitHub](https://github.com), as that is where the component is already hosted. - -1. Setup a [GitHub account](http://github.com/), if you haven't yet -2. Fork the repository (http://github.com/zendframework/zend-stdlib) -3. Clone the canonical repository locally and enter it. - - ```console - $ git clone git://github.com:zendframework/zend-stdlib.git - $ cd zend-stdlib - ``` - -4. Add a remote to your fork; substitute your GitHub username in the command - below. - - ```console - $ git remote add {username} git@github.com:{username}/zend-stdlib.git - $ git fetch {username} - ``` - -### Keeping Up-to-Date - -Periodically, you should update your fork or personal repository to -match the canonical ZF repository. Assuming you have setup your local repository -per the instructions above, you can do the following: - - -```console -$ git checkout master -$ git fetch origin -$ git rebase origin/master -# OPTIONALLY, to keep your remote up-to-date - -$ git push {username} master:master -``` - -If you're tracking other branches -- for example, the "develop" branch, where -new feature development occurs -- you'll want to do the same operations for that -branch; simply substitute "develop" for "master". - -### Working on a patch - -We recommend you do each new feature or bugfix in a new branch. This simplifies -the task of code review as well as the task of merging your changes into the -canonical repository. - -A typical workflow will then consist of the following: - -1. Create a new local branch based off either your master or develop branch. -2. Switch to your new local branch. (This step can be combined with the - previous step with the use of `git checkout -b`.) -3. Do some work, commit, repeat as necessary. -4. Push the local branch to your remote repository. -5. Send a pull request. - -The mechanics of this process are actually quite trivial. Below, we will -create a branch for fixing an issue in the tracker. - -```console -$ git checkout -b hotfix/9295 -Switched to a new branch 'hotfix/9295' -``` - -... do some work ... - - -```console -$ git commit -``` - -... write your log message ... - - -```console -$ git push {username} hotfix/9295:hotfix/9295 -Counting objects: 38, done. -Delta compression using up to 2 threads. -Compression objects: 100% (18/18), done. -Writing objects: 100% (20/20), 8.19KiB, done. -Total 20 (delta 12), reused 0 (delta 0) -To ssh://git@github.com/{username}/zend-stdlib.git - b5583aa..4f51698 HEAD -> master -``` - -To send a pull request, you have two options. - -If using GitHub, you can do the pull request from there. Navigate to -your repository, select the branch you just created, and then select the -"Pull Request" button in the upper right. Select the user/organization -"zendframework" as the recipient. - -If using your own repository - or even if using GitHub - you can use `git -format-patch` to create a patchset for us to apply; in fact, this is -**recommended** for security-related patches. If you use `format-patch`, please -send the patches as attachments to: - -- zf-devteam@zend.com for patches without security implications -- zf-security@zend.com for security patches - -#### What branch to issue the pull request against? - -Which branch should you issue a pull request against? - -- For fixes against the stable release, issue the pull request against the - "master" branch. -- For new features, or fixes that introduce new elements to the public API (such - as new public methods or properties), issue the pull request against the - "develop" branch. - -### Branch Cleanup - -As you might imagine, if you are a frequent contributor, you'll start to -get a ton of branches both locally and on your remote. - -Once you know that your changes have been accepted to the master -repository, we suggest doing some cleanup of these branches. - -- Local branch cleanup - - ```console - $ git branch -d - ``` - -- Remote branch removal - - ```console - $ git push {username} : - ``` - - -## Conduct - -Please see our [CONDUCT.md](CONDUCT.md) to understand expected behavior when interacting with others in the project. diff -r e200cb7efeb3 -r c2387f117808 vendor/zendframework/zend-stdlib/LICENSE.md --- a/vendor/zendframework/zend-stdlib/LICENSE.md Thu Apr 26 11:26:54 2018 +0100 +++ b/vendor/zendframework/zend-stdlib/LICENSE.md Tue Jul 10 15:07:59 2018 +0100 @@ -1,16 +1,15 @@ -Copyright (c) 2005-2015, Zend Technologies USA, Inc. - +Copyright (c) 2005-2018, Zend Technologies USA, Inc. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: -- Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. +- Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. -- Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. +- Redistributions in binary form must reproduce the above copyright notice, this + list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. - Neither the name of Zend Technologies USA, Inc. nor the names of its contributors may be used to endorse or promote products derived from this diff -r e200cb7efeb3 -r c2387f117808 vendor/zendframework/zend-stdlib/README.md --- a/vendor/zendframework/zend-stdlib/README.md Thu Apr 26 11:26:54 2018 +0100 +++ b/vendor/zendframework/zend-stdlib/README.md Tue Jul 10 15:07:59 2018 +0100 @@ -1,7 +1,7 @@ # zend-stdlib [![Build Status](https://secure.travis-ci.org/zendframework/zend-stdlib.svg?branch=master)](https://secure.travis-ci.org/zendframework/zend-stdlib) -[![Coverage Status](https://coveralls.io/repos/zendframework/zend-stdlib/badge.svg?branch=master)](https://coveralls.io/r/zendframework/zend-stdlib?branch=master) +[![Coverage Status](https://coveralls.io/repos/github/zendframework/zend-stdlib/badge.svg?branch=master)](https://coveralls.io/github/zendframework/zend-stdlib?branch=master) `Zend\Stdlib` is a set of components that implements general purpose utility class for different scopes like: @@ -15,3 +15,15 @@ - File issues at https://github.com/zendframework/zend-stdlib/issues - Documentation is at https://docs.zendframework.com/zend-stdlib/ + +## Benchmarks + +We provide scripts for benchmarking zend-stdlib using the +[PHPBench](https://github.com/phpbench/phpbench) framework; these can be +found in the `benchmark/` directory. + +To execute the benchmarks you can run the following command: + +```bash +$ vendor/bin/phpbench run --report=aggregate +``` diff -r e200cb7efeb3 -r c2387f117808 vendor/zendframework/zend-stdlib/benchmark/ExtractPriorityQueue.php --- a/vendor/zendframework/zend-stdlib/benchmark/ExtractPriorityQueue.php Thu Apr 26 11:26:54 2018 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,56 +0,0 @@ -splPriorityQueue = new SplPriorityQueue(); - $this->fastPriorityQueue = new FastPriorityQueue(); - $this->priorityQueue = new PriorityQueue(); - - for ($i = 0; $i < 5000; $i += 1) { - $priority = rand(1, 100); - $this->splPriorityQueue->insert('foo', $priority); - $this->fastPriorityQueue->insert('foo', $priority); - $this->priorityQueue->insert('foo', $priority); - } - } - - /** - * @iterations 5000 - */ - public function extractSplPriorityQueue() - { - $this->splPriorityQueue->extract(); - } - - /** - * @iterations 5000 - */ - public function extractPriorityQueue() - { - $this->priorityQueue->extract(); - } - - /** - * @iterations 5000 - */ - public function extractFastPriorityQueue() - { - $this->fastPriorityQueue->extract(); - } -} diff -r e200cb7efeb3 -r c2387f117808 vendor/zendframework/zend-stdlib/benchmark/InsertPriorityQueue.php --- a/vendor/zendframework/zend-stdlib/benchmark/InsertPriorityQueue.php Thu Apr 26 11:26:54 2018 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,49 +0,0 @@ -splPriorityQueue = new SplPriorityQueue(); - $this->fastPriorityQueue = new FastPriorityQueue(); - $this->priorityQueue = new PriorityQueue(); - } - - /** - * @iterations 5000 - */ - public function insertSplPriorityQueue() - { - $this->splPriorityQueue->insert('foo', rand(1, 100)); - } - - /** - * @iterations 5000 - */ - public function insertPriorityQueue() - { - $this->priorityQueue->insert('foo', rand(1, 100)); - } - - /** - * @iterations 5000 - */ - public function insertFastPriorityQueue() - { - $this->fastPriorityQueue->insert('foo', rand(1, 100)); - } -} diff -r e200cb7efeb3 -r c2387f117808 vendor/zendframework/zend-stdlib/benchmark/RemovePriorityQueue.php --- a/vendor/zendframework/zend-stdlib/benchmark/RemovePriorityQueue.php Thu Apr 26 11:26:54 2018 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,45 +0,0 @@ -fastPriorityQueue = new FastPriorityQueue(); - $this->priorityQueue = new PriorityQueue(); - - for ($i = 0; $i < 1000; $i += 1) { - $priority = rand(1, 100); - $this->fastPriorityQueue->insert('foo', $priority); - $this->priorityQueue->insert('foo', $priority); - } - } - - /** - * @iterations 1000 - */ - public function removePriorityQueue() - { - $this->priorityQueue->remove('foo'); - } - - /** - * @iterations 1000 - */ - public function removeFastPriorityQueue() - { - $this->fastPriorityQueue->remove('foo'); - } -} diff -r e200cb7efeb3 -r c2387f117808 vendor/zendframework/zend-stdlib/composer.json --- a/vendor/zendframework/zend-stdlib/composer.json Thu Apr 26 11:26:54 2018 +0100 +++ b/vendor/zendframework/zend-stdlib/composer.json Tue Jul 10 15:07:59 2018 +0100 @@ -1,29 +1,31 @@ { "name": "zendframework/zend-stdlib", - "description": " ", + "description": "SPL extensions, array utilities, error handlers, and more", "license": "BSD-3-Clause", "keywords": [ - "zf2", + "zf", + "zendframework", "stdlib" ], - "homepage": "https://github.com/zendframework/zend-stdlib", - "autoload": { - "psr-4": { - "Zend\\Stdlib\\": "src/" - } + "support": { + "docs": "https://docs.zendframework.com/zend-stdlib/", + "issues": "https://github.com/zendframework/zend-stdlib/issues", + "source": "https://github.com/zendframework/zend-stdlib", + "rss": "https://github.com/zendframework/zend-stdlib/releases.atom", + "slack": "https://zendframework-slack.herokuapp.com", + "forum": "https://discourse.zendframework.com/c/questions/components" }, "require": { "php": "^5.6 || ^7.0" }, "require-dev": { - "athletic/athletic": "~0.1", - "phpunit/PHPUnit": "~4.0", + "phpbench/phpbench": "^0.13", + "phpunit/phpunit": "^5.7.27 || ^6.5.8 || ^7.1.2", "zendframework/zend-coding-standard": "~1.0.0" }, - "extra": { - "branch-alias": { - "dev-master": "3.1-dev", - "dev-develop": "3.2-dev" + "autoload": { + "psr-4": { + "Zend\\Stdlib\\": "src/" } }, "autoload-dev": { @@ -32,6 +34,15 @@ "ZendBench\\Stdlib\\": "benchmark/" } }, + "config": { + "sort-packages": true + }, + "extra": { + "branch-alias": { + "dev-master": "3.2.x-dev", + "dev-develop": "3.3.x-dev" + } + }, "scripts": { "check": [ "@cs-check", @@ -40,7 +51,6 @@ "cs-check": "phpcs", "cs-fix": "phpcbf", "test": "phpunit --colors=always", - "test-coverage": "phpunit --colors=always --coverage-clover clover.xml", - "upload-coverage": "coveralls -v" + "test-coverage": "phpunit --colors=always --coverage-clover clover.xml" } } diff -r e200cb7efeb3 -r c2387f117808 vendor/zendframework/zend-stdlib/doc/book/console-helper.md --- a/vendor/zendframework/zend-stdlib/doc/book/console-helper.md Thu Apr 26 11:26:54 2018 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,126 +0,0 @@ -# Console Helper - -Writing one-off scripts or vendor binaries for a package is often problematic: - -- You need to parse arguments manually. -- You need to send output to the console in a meaningful fashion: - - Using `STDOUT` for meaningful, expected output - - Using `STDERR` for error messages - - Ensuring any line breaks are converted to `PHP_EOL` - - Optionally, using console colors to provide context, which means: - - Detecting whether or not the console supports colors in the first place - - Providing appropriate escape sequences to produce color - -`Zend\Stdlib\ConsoleHelper` helps to address the second major bullet point and -all beneath it in a minimal fashion. - -## Usage - -Typical usage is to instantiate a `ConsoleHelper`, and call one of its methods: - -```php -use Zend\Stdlib\ConsoleHelper; - -$helper = new ConsoleHelper(); -$helper->writeLine('This is output'); -``` - -You can optionally pass a PHP stream resource to the constructor, which will be -used to determine whether or not color support is available: - -```php -$helper = new ConsoleHelper($stream); -``` - -By default, it assumes `STDOUT`, and tests against that. - -## Available methods - -`ConsoleHelper` provides the following methods. - -### colorize - -- `colorize(string $string) : string` - -`colorize()` accepts a formatted string, and will then apply ANSI color -sequences to them, if color support is detected. - -The following sequences are currently supported: - -- `...` will apply a green color sequence around the provided text. -- `...` will apply a red color sequence around the provided text. - -You may mix multiple sequences within the same stream. - -### write - -- `write(string $string, bool $colorize = true, resource $stream = STDOUT) : void` - -Emits the provided `$string` to the provided `$stream` (which defaults to -`STDOUT` if not provided). Any EOL sequences are convered to `PHP_EOL`. If -`$colorize` is `true`, the string is first passed to `colorize()` as well. - -### writeline - -- `writeLine(string $string, bool $colorize = true, resource $stream = STDOUT) : void` - -Same as `write()`, except it also appends a `PHP_EOL` sequence to the `$string`. - -### writeErrorMessage - -- `writeErrorMessage(string $message)` - -Wraps `$message` in an `` sequence, and passes it to -`writeLine()`, using `STDERR` as the `$stream`. - -## Example - -Below is an example class that accepts an argument list, and determines how and -what to emit. - -```php -namespace Foo; - -use Zend\Stdlib\ConsoleHelper; - -class HelloWorld -{ - private $helper; - - public function __construct(ConsoleHelper $helper = null) - { - $this->helper = $helper ?: new ConsoleHelper(); - } - - public function __invoke(array $args) - { - if (! count($args)) { - $this->helper->writeErrorMessage('Missing arguments!'); - return; - } - - if (count($args) > 1) { - $this->helper->writeErrorMessage('Too many arguments!'); - return; - } - - $target = array_shift($args); - - $this->helper->writeLine(sprintf( - 'Hello %s', - $target - )); - } -} -``` - -## When to upgrade - -`ConsoleHelper` is deliberately simple, and assumes that your primary need for -console tooling is for output considerations. - -If you need to parse complex argument strings, we recommend using -[zend-console](https://docs.zendframework.com/zend-console/)/[zf-console](https://github.com/zfcampus/zf-console) -or [symfony/console](http://symfony.com/doc/current/components/console.html), -as these packages provide those capabilities, as well as far more colorization -and console feature detection facilities. diff -r e200cb7efeb3 -r c2387f117808 vendor/zendframework/zend-stdlib/doc/book/index.html --- a/vendor/zendframework/zend-stdlib/doc/book/index.html Thu Apr 26 11:26:54 2018 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,10 +0,0 @@ -
        -
        -

        zend-stdlib

        - -

        SPL extensions, array utilities, error handlers, and more.

        - -
        $ composer require zendframework/zend-stdlib
        -
        -
        - diff -r e200cb7efeb3 -r c2387f117808 vendor/zendframework/zend-stdlib/doc/book/index.md --- a/vendor/zendframework/zend-stdlib/doc/book/index.md Thu Apr 26 11:26:54 2018 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1 +0,0 @@ -../../README.md \ No newline at end of file diff -r e200cb7efeb3 -r c2387f117808 vendor/zendframework/zend-stdlib/doc/book/migration.md --- a/vendor/zendframework/zend-stdlib/doc/book/migration.md Thu Apr 26 11:26:54 2018 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,60 +0,0 @@ -# Migration Guide - -## From v2 to v3 - -The changes made going from v2 to v3 were: - -- Removal of the Hydrator subcomponent. -- Removal of the `CallbackHandler` class. -- Removal of `Zend\Stdlib\Guard\GuardUtils`. - -### Hydrators - -The biggest single change from version 2 to version 3 is that the hydrator -subcomponent, which was deprecated in v2.7.0, is now removed. This means that if -you were using zend-stdlib principally for the hydrators, you need to convert -your code to use [zend-hydrator](https://github.com/zendframework/zend-hydrator). - -This will also mean a multi-step migration. zend-stdlib v3 pre-dates -zend-hydrator v2.1, which will be the first version that supports zend-stdlib v3 -and zend-servicemanager v3. If you are using Composer, the migration should be -seamless: - -- Remove your zend-stdlib dependency: - - ```bash - $ composer remove zendframework/zend-stdlib - ``` - -- Update to use zend-hydrator: - - ```bash - $ composer require zendframework/zend-hydrator - ``` - -When zend-hydrator updates to newer versions of zend-stdlib and -zend-servicemanager, you will either automatically get those versions, or you -can tell composer to use those specific versions: - -```bash -$ composer require "zendframework/zend-stdlib:^3.0" -``` - -### CallbackHandler - -`Zend\Stdlib\CallbackHandler` primarily existed for legacy purposes; it was -created before the `callable` typehint existed, so that we could typehint PHP -callables. It also provided some minimal features around lazy-loading callables -from instantiable classes, but these features were rarely used, and better -approaches already exist for handling such functinality in zend-servicemanager -and zend-expressive. - -As such, the class was marked deprecated in v2.7.0, and removed for v3.0.0. - -### GuardUtils - -Version 3 removes `Zend\Stdlib\Guard\GuardUtils`. This abstract class existed to -provide the functionality of the various traits also present in that -subcomponent, for consumers on versions of PHP earlier than 5.4. Since the -minimum required version is now PHP 5.5, the class is unnecessary. If you were -using it previously, compose the related traits instead. diff -r e200cb7efeb3 -r c2387f117808 vendor/zendframework/zend-stdlib/doc/bookdown.json --- a/vendor/zendframework/zend-stdlib/doc/bookdown.json Thu Apr 26 11:26:54 2018 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,14 +0,0 @@ -{ - "title": "Zend\\Stdlib", - "target": "html/", - "content": [ - "book/zend.stdlib.hydrator.md", - "book/zend.stdlib.hydrator.filter.md", - "book/zend.stdlib.hydrator.strategy.md", - "book/zend.stdlib.hydrator.aggregate.md", - "book/zend.stdlib.hydrator.namingstrategy.compositenamingstrategy.md", - "book/zend.stdlib.hydrator.namingstrategy.identitynamingstrategy.md", - "book/zend.stdlib.hydrator.namingstrategy.mapnamingstrategy.md", - "book/zend.stdlib.hydrator.namingstrategy.underscorenamingstrategy.md" - ] -} \ No newline at end of file diff -r e200cb7efeb3 -r c2387f117808 vendor/zendframework/zend-stdlib/mkdocs.yml --- a/vendor/zendframework/zend-stdlib/mkdocs.yml Thu Apr 26 11:26:54 2018 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,11 +0,0 @@ -docs_dir: doc/book -site_dir: doc/html -pages: - - index.md - - Reference: - - "Console Helper": console-helper.md - - Migration: migration.md -site_name: zend-stdlib -site_description: Zend\Stdlib -repo_url: 'https://github.com/zendframework/zend-stdlib' -copyright: 'Copyright (c) 2016 Zend Technologies USA Inc.' diff -r e200cb7efeb3 -r c2387f117808 vendor/zendframework/zend-stdlib/phpcs.xml --- a/vendor/zendframework/zend-stdlib/phpcs.xml Thu Apr 26 11:26:54 2018 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,8 +0,0 @@ - - - - - - src - test - diff -r e200cb7efeb3 -r c2387f117808 vendor/zendframework/zend-stdlib/src/ArrayUtils.php --- a/vendor/zendframework/zend-stdlib/src/ArrayUtils.php Thu Apr 26 11:26:54 2018 +0100 +++ b/vendor/zendframework/zend-stdlib/src/ArrayUtils.php Tue Jul 10 15:07:59 2018 +0100 @@ -292,12 +292,13 @@ } /** - * Compatibility Method for array_filter on <5.6 systems + * @deprecated Since 3.2.0; use the native array_filter methods * * @param array $data * @param callable $callback * @param null|int $flag * @return array + * @throws Exception\InvalidArgumentException */ public static function filter(array $data, $callback, $flag = null) { @@ -308,28 +309,6 @@ )); } - if (version_compare(PHP_VERSION, '5.6.0') >= 0) { - return array_filter($data, $callback, $flag); - } - - $output = []; - foreach ($data as $key => $value) { - $params = [$value]; - - if ($flag === static::ARRAY_FILTER_USE_BOTH) { - $params[] = $key; - } - - if ($flag === static::ARRAY_FILTER_USE_KEY) { - $params = [$key]; - } - - $response = call_user_func_array($callback, $params); - if ($response) { - $output[$key] = $value; - } - } - - return $output; + return array_filter($data, $callback, $flag); } }
        Drush Version