From af40eee3ad965aa9c52ee90770a5e76fa298358d Mon Sep 17 00:00:00 2001 From: Sam Minnee Date: Sat, 29 Aug 2020 17:06:55 +1200 Subject: [PATCH 01/15] TEST Add nightly (aka PHP 8) to build matrix --- .travis.yml | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 1c5926702..1801ac1aa 100644 --- a/.travis.yml +++ b/.travis.yml @@ -49,6 +49,16 @@ matrix: packages: - libonig-dev + - php: nightly + env: + - DB=MYSQL + - PHPUNIT_TEST=framework + - COMPOSER_INSTALL_ARG="--ignore-platform-reqs" + addons: + apt: + packages: + - libonig-dev + - php: 7.3 if: type IN (cron) env: @@ -78,7 +88,7 @@ before_script: - composer require silverstripe/recipe-testing:^1 silverstripe/recipe-core:4.x-dev silverstripe/admin:1.x-dev silverstripe/versioned:1.x-dev --no-update - if [[ $PHPUNIT_TEST == cms ]]; then composer require silverstripe/recipe-cms:4.x-dev --no-update; fi - if [[ $PHPCS_TEST ]]; then composer global require squizlabs/php_codesniffer:^3 --prefer-dist --no-interaction --no-progress --no-suggest -o; fi - - composer install --prefer-source --no-interaction --no-progress --no-suggest --optimize-autoloader --verbose --profile + - composer install --prefer-source --no-interaction --no-progress --no-suggest --optimize-autoloader --verbose --profile $COMPOSER_INSTALL_ARG # Log constants to CI for debugging purposes - php ./tests/dump_constants.php From 08010d5933a2ecce32890e92ce8b2bf8764934ac Mon Sep 17 00:00:00 2001 From: Garion Herman Date: Sat, 29 Aug 2020 12:08:24 +1200 Subject: [PATCH 02/15] NEW Support namespace tokens in ClassInfo::parse_class_spec() The T_NAME_QUALIFIED and T_NAME_FULLY_QUALIFIED tokens are introduced in PHP 8, and encapsulate theentire FQCN, replacing the previous structure of a group of T_STRINGs and T_NS_SEPARATORs. --- src/Core/ClassInfo.php | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/Core/ClassInfo.php b/src/Core/ClassInfo.php index e67df316b..dc64b9324 100644 --- a/src/Core/ClassInfo.php +++ b/src/Core/ClassInfo.php @@ -439,7 +439,13 @@ class ClassInfo $tokenName = is_array($token) ? $token[0] : $token; // Get the class name - if ($class === null && is_array($token) && $token[0] === T_STRING) { + if (\defined('T_NAME_QUALIFIED') && is_array($token) && + ($token[0] === T_NAME_QUALIFIED || $token[0] === T_NAME_FULLY_QUALIFIED) + ) { + // PHP 8 exposes the FQCN as a single T_NAME_QUALIFIED or T_NAME_FULLY_QUALIFIED token + $class .= $token[1]; + $hadNamespace = true; + } elseif ($class === null && is_array($token) && $token[0] === T_STRING) { $class = $token[1]; } elseif (is_array($token) && $token[0] === T_NS_SEPARATOR) { $class .= $token[1]; From e0f3797489584a08e6c290e61462a16359958f2b Mon Sep 17 00:00:00 2001 From: Sam Minnee Date: Sun, 30 Aug 2020 11:51:27 +1200 Subject: [PATCH 03/15] FIX: Remove deprecated & non-functional default argument config This throws deprecation errors on PHP 8. Fixes #9666 --- src/ORM/DataQueryManipulator.php | 4 ++-- src/ORM/ManyManyThroughQueryManipulator.php | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/ORM/DataQueryManipulator.php b/src/ORM/DataQueryManipulator.php index dd06cb780..12cf66c5b 100644 --- a/src/ORM/DataQueryManipulator.php +++ b/src/ORM/DataQueryManipulator.php @@ -16,7 +16,7 @@ interface DataQueryManipulator * @param array $queriedColumns * @param SQLSelect $sqlSelect */ - public function beforeGetFinalisedQuery(DataQuery $dataQuery, $queriedColumns = [], SQLSelect $sqlSelect); + public function beforeGetFinalisedQuery(DataQuery $dataQuery, $queriedColumns, SQLSelect $sqlSelect); /** * Invoked after getFinalisedQuery() @@ -25,5 +25,5 @@ interface DataQueryManipulator * @param array $queriedColumns * @param SQLSelect $sqlQuery */ - public function afterGetFinalisedQuery(DataQuery $dataQuery, $queriedColumns = [], SQLSelect $sqlQuery); + public function afterGetFinalisedQuery(DataQuery $dataQuery, $queriedColumns, SQLSelect $sqlQuery); } diff --git a/src/ORM/ManyManyThroughQueryManipulator.php b/src/ORM/ManyManyThroughQueryManipulator.php index 6fffbbe60..93ff393f4 100644 --- a/src/ORM/ManyManyThroughQueryManipulator.php +++ b/src/ORM/ManyManyThroughQueryManipulator.php @@ -231,7 +231,7 @@ class ManyManyThroughQueryManipulator implements DataQueryManipulator * @param array $queriedColumns * @param SQLSelect $sqlSelect */ - public function beforeGetFinalisedQuery(DataQuery $dataQuery, $queriedColumns = [], SQLSelect $sqlSelect) + public function beforeGetFinalisedQuery(DataQuery $dataQuery, $queriedColumns, SQLSelect $sqlSelect) { // Get metadata and SQL from join table $hasManyRelation = $this->getParentRelationship($dataQuery); @@ -281,7 +281,7 @@ class ManyManyThroughQueryManipulator implements DataQueryManipulator * @param array $queriedColumns * @param SQLSelect $sqlQuery */ - public function afterGetFinalisedQuery(DataQuery $dataQuery, $queriedColumns = [], SQLSelect $sqlQuery) + public function afterGetFinalisedQuery(DataQuery $dataQuery, $queriedColumns, SQLSelect $sqlQuery) { // Inject final replacement after manipulation has been performed on the base dataquery $joinTableSQL = $dataQuery->getQueryParam('Foreign.JoinTableSQL'); From 622cf8b914b1ca35ba379ecd55179632bd824b6c Mon Sep 17 00:00:00 2001 From: Sam Minnee Date: Sun, 30 Aug 2020 11:54:39 +1200 Subject: [PATCH 04/15] FIX: Drop parameter names in Injector instantiation to preserve behaviour in PHP 8 Fixes #9667 --- src/Core/Injector/InjectionCreator.php | 2 ++ src/Security/PasswordEncryptor.php | 3 ++- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/src/Core/Injector/InjectionCreator.php b/src/Core/Injector/InjectionCreator.php index 3dc7448ab..44fe99a21 100644 --- a/src/Core/Injector/InjectionCreator.php +++ b/src/Core/Injector/InjectionCreator.php @@ -20,6 +20,8 @@ class InjectionCreator implements Factory } if (count($params)) { + // Remove named keys to ensure that PHP7 and PHP8 interpret these the same way + $params = array_values($params); return $reflector->newInstanceArgs($params); } diff --git a/src/Security/PasswordEncryptor.php b/src/Security/PasswordEncryptor.php index 6b2b0e695..8a94ddebd 100644 --- a/src/Security/PasswordEncryptor.php +++ b/src/Security/PasswordEncryptor.php @@ -56,7 +56,8 @@ abstract class PasswordEncryptor return new $class; } - $arguments = $encryptors[$algorithm]; + // Don't treat array keys as argument names - keeps PHP 7 and PHP 8 operating similarly + $arguments = array_values($encryptors[$algorithm]); return($refClass->newInstanceArgs($arguments)); } From 5cb3d07f44d35a904db511c01dcd8fc64dfd64ec Mon Sep 17 00:00:00 2001 From: Sam Minnee Date: Sun, 30 Aug 2020 12:05:44 +1200 Subject: [PATCH 05/15] FIX: Avoid pass-literal-by-reference warning in PHP 8 --- .../Middleware/ConfirmationMiddleware/HttpMethodBypass.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Control/Middleware/ConfirmationMiddleware/HttpMethodBypass.php b/src/Control/Middleware/ConfirmationMiddleware/HttpMethodBypass.php index 277f3c13b..bc41ea1e4 100644 --- a/src/Control/Middleware/ConfirmationMiddleware/HttpMethodBypass.php +++ b/src/Control/Middleware/ConfirmationMiddleware/HttpMethodBypass.php @@ -48,7 +48,7 @@ class HttpMethodBypass implements Bypass // uppercase and exclude empties $methods = array_reduce( $methods, - static function &(&$result, $method) { + function ($result, $method) { $method = strtoupper(trim($method)); if (strlen($method)) { $result[] = $method; From 09fb33e657607844cbb9a42c306bc4ce5bd383b7 Mon Sep 17 00:00:00 2001 From: Sam Minnee Date: Sun, 30 Aug 2020 12:14:49 +1200 Subject: [PATCH 06/15] FIX: Avoid passing non-class to get_parent_class() Throws errors in PHP 8 --- src/Core/Config/Middleware/InheritanceMiddleware.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Core/Config/Middleware/InheritanceMiddleware.php b/src/Core/Config/Middleware/InheritanceMiddleware.php index ea394795c..5b0bf1fd6 100644 --- a/src/Core/Config/Middleware/InheritanceMiddleware.php +++ b/src/Core/Config/Middleware/InheritanceMiddleware.php @@ -32,8 +32,8 @@ class InheritanceMiddleware implements Middleware return $config; } - // Skip if no parent class - $parent = get_parent_class($class); + // Skip if not a class or not parent class + $parent = class_exists($class) ? get_parent_class($class) : null; if (!$parent) { return $config; } From b3dd27953b7e863b3e2ee032966f22e2961b5abb Mon Sep 17 00:00:00 2001 From: Sam Minnee Date: Sun, 30 Aug 2020 16:01:27 +1200 Subject: [PATCH 07/15] NEW: Allow league/csv ^9 Hopefully this has better PHP 8 support. --- composer.json | 4 +-- src/Dev/CsvBulkLoader.php | 30 +++++++++++++++---- src/Forms/GridField/GridFieldExportButton.php | 4 +++ .../GridField/GridFieldExportButtonTest.php | 28 ++++++++++++----- 4 files changed, 50 insertions(+), 16 deletions(-) diff --git a/composer.json b/composer.json index c7513cc79..45e1390df 100644 --- a/composer.json +++ b/composer.json @@ -25,7 +25,7 @@ "bramus/monolog-colored-line-formatter": "~2.0", "composer/installers": "~1.0", "embed/embed": "^3.0", - "league/csv": "^8", + "league/csv": "^8 || ^9", "league/flysystem": "~1.0.12", "m1/env": "^2.1", "monolog/monolog": "~1.11", @@ -54,7 +54,7 @@ }, "require-dev": { "phpunit/phpunit": "^5.7", - "sminnee/phpunit-mock-objects": "^3.4.5", + "sminnee/phpunit-mock-objects": "^3.4.9", "silverstripe/versioned": "^1", "squizlabs/php_codesniffer": "^3.5" }, diff --git a/src/Dev/CsvBulkLoader.php b/src/Dev/CsvBulkLoader.php index 5a3a0a56c..f90f76eca 100644 --- a/src/Dev/CsvBulkLoader.php +++ b/src/Dev/CsvBulkLoader.php @@ -2,6 +2,7 @@ namespace SilverStripe\Dev; +use League\Csv\MapIterator; use League\Csv\Reader; use SilverStripe\Control\Director; use SilverStripe\ORM\DataObject; @@ -76,9 +77,16 @@ class CsvBulkLoader extends BulkLoader $filepath = Director::getAbsFile($filepath); $csvReader = Reader::createFromPath($filepath, 'r'); $csvReader->setDelimiter($this->delimiter); - $csvReader->stripBom(true); - $tabExtractor = function ($row, $rowOffset, $iterator) { + // league/csv 9 + if (method_exists($csvReader, 'skipInputBOM')) { + $csvReader->skipInputBOM(); + // league/csv 8 + } else { + $csvReader->stripBom(true); + } + + $tabExtractor = function ($row, $rowOffset) { foreach ($row as &$item) { // [SS-2017-007] Ensure all cells with leading tab and then [@=+] have the tab removed on import if (preg_match("/^\t[\-@=\+]+.*/", $item)) { @@ -90,8 +98,9 @@ class CsvBulkLoader extends BulkLoader if ($this->columnMap) { $headerMap = $this->getNormalisedColumnMap(); - $remapper = function ($row, $rowOffset, $iterator) use ($headerMap, $tabExtractor) { - $row = $tabExtractor($row, $rowOffset, $iterator); + + $remapper = function ($row, $rowOffset) use ($headerMap, $tabExtractor) { + $row = $tabExtractor($row, $rowOffset); foreach ($headerMap as $column => $renamedColumn) { if ($column == $renamedColumn) { continue; @@ -110,9 +119,18 @@ class CsvBulkLoader extends BulkLoader } if ($this->hasHeaderRow) { - $rows = $csvReader->fetchAssoc(0, $remapper); + if (method_exists($csvReader, 'fetchAssoc')) { + $rows = $csvReader->fetchAssoc(0, $remapper); + } else { + $csvReader->setHeaderOffset(0); + $rows = new MapIterator($csvReader->getRecords(), $remapper); + } } elseif ($this->columnMap) { - $rows = $csvReader->fetchAssoc($headerMap, $remapper); + if (method_exists($csvReader, 'fetchAssoc')) { + $rows = $csvReader->fetchAssoc($headerMap, $remapper); + } else { + $rows = new MapIterator($csvReader->getRecords($headerMap), $remapper); + } } foreach ($rows as $row) { diff --git a/src/Forms/GridField/GridFieldExportButton.php b/src/Forms/GridField/GridFieldExportButton.php index 02b6a6c87..8d5b3b427 100644 --- a/src/Forms/GridField/GridFieldExportButton.php +++ b/src/Forms/GridField/GridFieldExportButton.php @@ -257,6 +257,10 @@ class GridFieldExportButton implements GridField_HTMLProvider, GridField_ActionP } } + if (method_exists($csvWriter, 'getContent')) { + return $csvWriter->getContent(); + } + return (string)$csvWriter; } diff --git a/tests/php/Forms/GridField/GridFieldExportButtonTest.php b/tests/php/Forms/GridField/GridFieldExportButtonTest.php index 5738beb98..222d5f657 100644 --- a/tests/php/Forms/GridField/GridFieldExportButtonTest.php +++ b/tests/php/Forms/GridField/GridFieldExportButtonTest.php @@ -55,7 +55,7 @@ class GridFieldExportButtonTest extends SapphireTest $config = GridFieldConfig::create()->addComponent(new GridFieldExportButton()); $gridField = new GridField('testfield', 'testfield', $list, $config); - $csvReader = Reader::createFromString($button->generateExportFileData($gridField)); + $csvReader = $this->createReader($button->generateExportFileData($gridField)); $bom = $csvReader->getInputBOM(); $this->assertEquals( @@ -69,7 +69,7 @@ class GridFieldExportButtonTest extends SapphireTest $button = new GridFieldExportButton(); $button->setExportColumns(['Name' => 'My Name']); - $csvReader = Reader::createFromString($button->generateExportFileData($this->gridField)); + $csvReader = $this->createReader($button->generateExportFileData($this->gridField)); $bom = $csvReader->getInputBOM(); $this->assertEquals( @@ -89,7 +89,7 @@ class GridFieldExportButtonTest extends SapphireTest $button = new GridFieldExportButton(); $button->setExportColumns(['Name' => 'My Name']); - $csvReader = Reader::createFromString($button->generateExportFileData($this->gridField)); + $csvReader = $this->createReader($button->generateExportFileData($this->gridField)); $bom = $csvReader->getInputBOM(); $this->assertEquals( @@ -108,7 +108,7 @@ class GridFieldExportButtonTest extends SapphireTest } ]); - $csvReader = Reader::createFromString($button->generateExportFileData($this->gridField)); + $csvReader = $this->createReader($button->generateExportFileData($this->gridField)); $bom = $csvReader->getInputBOM(); $this->assertEquals( @@ -125,7 +125,7 @@ class GridFieldExportButtonTest extends SapphireTest 'City' => 'strtolower', ]); - $csvReader = Reader::createFromString($button->generateExportFileData($this->gridField)); + $csvReader = $this->createReader($button->generateExportFileData($this->gridField)); $bom = $csvReader->getInputBOM(); $this->assertEquals( @@ -143,7 +143,7 @@ class GridFieldExportButtonTest extends SapphireTest ]); $button->setCsvHasHeader(false); - $csvReader = Reader::createFromString($button->generateExportFileData($this->gridField)); + $csvReader = $this->createReader($button->generateExportFileData($this->gridField)); $bom = $csvReader->getInputBOM(); $this->assertEquals( @@ -167,7 +167,7 @@ class GridFieldExportButtonTest extends SapphireTest $exportData = $button->generateExportFileData($this->gridField); - $csvReader = Reader::createFromString($exportData); + $csvReader = $this->createReader($exportData); $bom = $csvReader->getInputBOM(); $this->assertEquals( @@ -183,7 +183,7 @@ class GridFieldExportButtonTest extends SapphireTest 'RugbyTeamNumber' => 'Rugby Team Number' ]); - $csvReader = Reader::createFromString($button->generateExportFileData($this->gridField)); + $csvReader = $this->createReader($button->generateExportFileData($this->gridField)); $bom = $csvReader->getInputBOM(); $this->assertEquals( @@ -191,4 +191,16 @@ class GridFieldExportButtonTest extends SapphireTest (string) $csvReader ); } + + protected function createReader($string) + { + $reader = Reader::createFromString($string); + + // Explicitly set the output BOM in league/csv 9 + if (method_exists($reader, 'getContent')) { + $reader->setOutputBOM(Reader::BOM_UTF8); + } + + return $reader; + } } From 57bdef3b2e7cba284bfe0ff2cb798b70c995ca41 Mon Sep 17 00:00:00 2001 From: Sam Minnee Date: Sun, 30 Aug 2020 16:39:12 +1200 Subject: [PATCH 08/15] FIX: Fix test mistakenly labelling content as name arguments in data provider --- .../php/Dev/SapphireTestTest/DataProvider.php | 40 +++++++++---------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/tests/php/Dev/SapphireTestTest/DataProvider.php b/tests/php/Dev/SapphireTestTest/DataProvider.php index c54ea33ea..922a46c48 100644 --- a/tests/php/Dev/SapphireTestTest/DataProvider.php +++ b/tests/php/Dev/SapphireTestTest/DataProvider.php @@ -42,34 +42,34 @@ class DataProvider implements TestOnly public static function provideEqualLists() { return [ - [ - 'oneParameterOneItem' => [ + 'oneParameterOneItem' => [ + [ ['FirstName' => 'Ingo'], ], self::$oneItemList, ], - [ - 'twoParametersOneItem' => [ + 'twoParametersOneItem' => [ + [ ['FirstName' => 'Ingo', 'Surname' => 'Schommer'], ], self::$oneItemList, ], - [ - 'oneParameterTwoItems' => [ + 'oneParameterTwoItems' => [ + [ ['FirstName' => 'Ingo'], ['FirstName' => 'Sam'], ], self::$twoItemList, ], - [ - 'twoParametersTwoItems' => [ + 'twoParametersTwoItems' => [ + [ ['FirstName' => 'Ingo', 'Surname' => 'Schommer'], ['FirstName' => 'Sam', 'Surname' => 'Minnee'], ], self::$twoItemList, ], - [ - 'mixedParametersTwoItems' => [ + 'mixedParametersTwoItems' => [ + [ ['FirstName' => 'Ingo', 'Surname' => 'Schommer'], ['FirstName' => 'Sam'], ], @@ -85,34 +85,34 @@ class DataProvider implements TestOnly { return [ - [ - 'checkAgainstEmptyList' => [ + 'checkAgainstEmptyList' => [ + [ ['FirstName' => 'Ingo'], ], [], ], - [ - 'oneItemExpectedListContainsMore' => [ + 'oneItemExpectedListContainsMore' => [ + [ ['FirstName' => 'Ingo'], ], self::$twoItemList, ], - [ - 'oneExpectationHasWrontParamter' => [ + 'oneExpectationHasWrontParamter' => [ + [ ['FirstName' => 'IngoXX'], ['FirstName' => 'Sam'], ], self::$twoItemList, ], - [ - 'differentParametersInDifferentItemsAreWrong' => [ + 'differentParametersInDifferentItemsAreWrong' => [ + [ ['FirstName' => 'IngoXXX', 'Surname' => 'Schommer'], ['FirstName' => 'Sam', 'Surname' => 'MinneeXXX'], ], self::$twoItemList, ], - [ - 'differentParametersNotMatching' => [ + 'differentParametersNotMatching' => [ + [ ['FirstName' => 'Daniel', 'Surname' => 'Foo'], ['FirstName' => 'Dan'], ], From fb9e6e51a69274a3885a6c65574ea467e44082ed Mon Sep 17 00:00:00 2001 From: Sam Minnee Date: Sun, 30 Aug 2020 20:21:58 +1200 Subject: [PATCH 09/15] FIX: Switch to sminnee fork of phpunit 5.7 This provides 5.7.28 with fixes for PHP 8 support. --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index 45e1390df..56c3d5dd0 100644 --- a/composer.json +++ b/composer.json @@ -53,7 +53,7 @@ "ext-xml": "*" }, "require-dev": { - "phpunit/phpunit": "^5.7", + "sminnee/phpunit": "^5.7.29", "sminnee/phpunit-mock-objects": "^3.4.9", "silverstripe/versioned": "^1", "squizlabs/php_codesniffer": "^3.5" From bad066229192d1c9618ce18c4bf81e5cb972040e Mon Sep 17 00:00:00 2001 From: Garion Herman Date: Fri, 4 Sep 2020 18:47:46 +1200 Subject: [PATCH 10/15] FIX Disable libxml_disable_entity_loader() calls in PHP 8 --- src/Core/Convert.php | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/Core/Convert.php b/src/Core/Convert.php index 206de49ef..5cd41dba7 100644 --- a/src/Core/Convert.php +++ b/src/Core/Convert.php @@ -296,12 +296,17 @@ class Convert * @param string $val * @param boolean $disableDoctypes Disables the use of DOCTYPE, and will trigger an error if encountered. * false by default. - * @param boolean $disableExternals Disables the loading of external entities. false by default. + * @param boolean $disableExternals Disables the loading of external entities. false by default. No-op in PHP 8. * @return array * @throws Exception */ public static function xml2array($val, $disableDoctypes = false, $disableExternals = false) { + // PHP 8 deprecates libxml_disable_entity_loader() as it is no longer needed + if (\PHP_VERSION_ID >= 80000) { + $disableExternals = false; + } + // Check doctype if ($disableDoctypes && preg_match('/\<\!DOCTYPE.+]\>/', $val)) { throw new InvalidArgumentException('XML Doctype parsing disabled'); From 44685eceba6667a45799ab1f3805bd53f3372e8a Mon Sep 17 00:00:00 2001 From: Garion Herman Date: Sat, 5 Sep 2020 11:13:09 +1200 Subject: [PATCH 11/15] FIX Support PHP 8 namespace tokens in i18nTextCollector --- src/i18n/TextCollection/i18nTextCollector.php | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/i18n/TextCollection/i18nTextCollector.php b/src/i18n/TextCollection/i18nTextCollector.php index 843412dd5..5d3445f7a 100644 --- a/src/i18n/TextCollection/i18nTextCollector.php +++ b/src/i18n/TextCollection/i18nTextCollector.php @@ -570,6 +570,13 @@ class i18nTextCollector if (is_array($token)) { list($id, $text) = $token; + // PHP 8 namespace tokens + if (\defined('T_NAME_QUALIFIED') && in_array($id, [T_NAME_FULLY_QUALIFIED, T_NAME_QUALIFIED])) { + $inNamespace = true; + $currentClass[] = $text; + continue; + } + // Check class if ($id === T_NAMESPACE) { $inNamespace = true; From f1c94e6d54d1c660abe04951cc5e162e3dd664f7 Mon Sep 17 00:00:00 2001 From: Garion Herman Date: Sat, 5 Sep 2020 11:24:37 +1200 Subject: [PATCH 12/15] FIX Allow quotes in expected ReflectionExceptions within tests --- src/Core/Injector/InjectorNotFoundException.php | 1 + tests/php/Core/ClassInfoTest.php | 2 +- tests/php/ORM/DataListTest.php | 14 +++++++------- 3 files changed, 9 insertions(+), 8 deletions(-) diff --git a/src/Core/Injector/InjectorNotFoundException.php b/src/Core/Injector/InjectorNotFoundException.php index ff30fb441..05a9bd139 100644 --- a/src/Core/Injector/InjectorNotFoundException.php +++ b/src/Core/Injector/InjectorNotFoundException.php @@ -3,6 +3,7 @@ namespace SilverStripe\Core\Injector; use Psr\Container\NotFoundExceptionInterface; +use Throwable; class InjectorNotFoundException extends \Exception implements NotFoundExceptionInterface { diff --git a/tests/php/Core/ClassInfoTest.php b/tests/php/Core/ClassInfoTest.php index 939aa9cbe..e730ff0a0 100644 --- a/tests/php/Core/ClassInfoTest.php +++ b/tests/php/Core/ClassInfoTest.php @@ -105,7 +105,7 @@ class ClassInfoTest extends SapphireTest public function testNonClassName() { $this->expectException(ReflectionException::class); - $this->expectExceptionMessage('Class IAmAClassThatDoesNotExist does not exist'); + $this->expectExceptionMessageRegExp('/Class "?IAmAClassThatDoesNotExist"? does not exist/'); $this->assertEquals('IAmAClassThatDoesNotExist', ClassInfo::class_name('IAmAClassThatDoesNotExist')); } diff --git a/tests/php/ORM/DataListTest.php b/tests/php/ORM/DataListTest.php index 35e77c726..9658f52d1 100755 --- a/tests/php/ORM/DataListTest.php +++ b/tests/php/ORM/DataListTest.php @@ -4,6 +4,7 @@ namespace SilverStripe\ORM\Tests; use InvalidArgumentException; use SilverStripe\Core\Convert; +use SilverStripe\Core\Injector\InjectorNotFoundException; use SilverStripe\Dev\SapphireTest; use SilverStripe\ORM\DataList; use SilverStripe\ORM\DataQuery; @@ -751,24 +752,23 @@ class DataListTest extends SapphireTest $this->assertEquals('Bob', $list->first()->Name, 'First comment should be from Bob'); } - /** - * @expectedException \SilverStripe\Core\Injector\InjectorNotFoundException - * @expectedExceptionMessage Class DataListFilter.Bogus does not exist - */ public function testSimpleFilterWithNonExistingComparisator() { + $this->expectException(InjectorNotFoundException::class); + $this->expectExceptionMessageRegExp('/Class "?DataListFilter.Bogus"? does not exist/'); + $list = TeamComment::get(); $list->filter('Comment:Bogus', 'team comment'); } /** * Invalid modifiers are treated as failed filter construction - * - * @expectedException \SilverStripe\Core\Injector\InjectorNotFoundException - * @expectedExceptionMessage Class DataListFilter.invalidmodifier does not exist */ public function testInvalidModifier() { + $this->expectException(InjectorNotFoundException::class); + $this->expectExceptionMessageRegExp('/Class "?DataListFilter.invalidmodifier"? does not exist/'); + $list = TeamComment::get(); $list->filter('Comment:invalidmodifier', 'team comment'); } From 099ee2deb7c58415732b0959473ab6b61128ecc3 Mon Sep 17 00:00:00 2001 From: Garion Herman Date: Mon, 7 Sep 2020 14:56:36 +1200 Subject: [PATCH 13/15] FIX Remove extraneous @depends annotations --- tests/php/ORM/MySQLPDOConnectorTest.php | 1 - tests/php/ORM/MySQLiConnectorTest.php | 1 - 2 files changed, 2 deletions(-) diff --git a/tests/php/ORM/MySQLPDOConnectorTest.php b/tests/php/ORM/MySQLPDOConnectorTest.php index bbf648d55..9ce68399d 100644 --- a/tests/php/ORM/MySQLPDOConnectorTest.php +++ b/tests/php/ORM/MySQLPDOConnectorTest.php @@ -45,7 +45,6 @@ class MySQLPDOConnectorTest extends SapphireTest implements TestOnly } /** - * @depends testConnectionCharsetControl * @dataProvider charsetProvider */ public function testConnectionCollationControl($charset, $defaultCollation, $customCollation) diff --git a/tests/php/ORM/MySQLiConnectorTest.php b/tests/php/ORM/MySQLiConnectorTest.php index fd65e502f..001c18cdb 100644 --- a/tests/php/ORM/MySQLiConnectorTest.php +++ b/tests/php/ORM/MySQLiConnectorTest.php @@ -38,7 +38,6 @@ class MySQLiConnectorTest extends SapphireTest implements TestOnly } /** - * @depends testConnectionCharsetControl * @dataProvider charsetProvider */ public function testConnectionCollationControl($charset, $defaultCollation, $customCollation) From 24dfe0b026e04905cdae1f6eab9322a98e05abe7 Mon Sep 17 00:00:00 2001 From: Sam Minnee Date: Tue, 8 Sep 2020 11:19:03 +1200 Subject: [PATCH 14/15] NEW: Add --prefer-lowest to PHP 7.1 build MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This build will ensure that older versions of packages that we claim work with silverstripe/framework do, in fact, work. ‘Composer install’ changed to ‘composer update’ as that’s what’s being executed in the absence of a composer.lock, and better clarifies intent. Note that: * Support for nikic/php-parser ^2 was lost in 25759ffc5fe532a239b1487ca6b025140d2e144f. * Support for monolog/logger < 1.16 was lost in 7ab55a4948617d61abfe4d47264de2803ec0583e --- .travis.yml | 3 ++- composer.json | 4 ++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/.travis.yml b/.travis.yml index 1801ac1aa..3ade7065a 100644 --- a/.travis.yml +++ b/.travis.yml @@ -27,6 +27,7 @@ matrix: - DB=PGSQL - PHPCS_TEST=1 - PHPUNIT_TEST=framework + - COMPOSER_INSTALL_ARG="--prefer-lowest" - php: 7.2 env: @@ -88,7 +89,7 @@ before_script: - composer require silverstripe/recipe-testing:^1 silverstripe/recipe-core:4.x-dev silverstripe/admin:1.x-dev silverstripe/versioned:1.x-dev --no-update - if [[ $PHPUNIT_TEST == cms ]]; then composer require silverstripe/recipe-cms:4.x-dev --no-update; fi - if [[ $PHPCS_TEST ]]; then composer global require squizlabs/php_codesniffer:^3 --prefer-dist --no-interaction --no-progress --no-suggest -o; fi - - composer install --prefer-source --no-interaction --no-progress --no-suggest --optimize-autoloader --verbose --profile $COMPOSER_INSTALL_ARG + - composer update --prefer-source --no-interaction --no-progress --no-suggest --optimize-autoloader --verbose --profile $COMPOSER_INSTALL_ARG # Log constants to CI for debugging purposes - php ./tests/dump_constants.php diff --git a/composer.json b/composer.json index 56c3d5dd0..30c133cd7 100644 --- a/composer.json +++ b/composer.json @@ -28,8 +28,8 @@ "league/csv": "^8 || ^9", "league/flysystem": "~1.0.12", "m1/env": "^2.1", - "monolog/monolog": "~1.11", - "nikic/php-parser": "^2 || ^3 || ^4", + "monolog/monolog": "~1.16", + "nikic/php-parser": "^3 || ^4", "psr/container": "1.0.0", "psr/container-implementation": "1.0.0", "silverstripe/config": "^1@dev", From 85252ca05e5e4c98f4d8670e385a2c2c3875e21f Mon Sep 17 00:00:00 2001 From: Sam Minnee Date: Tue, 8 Sep 2020 13:20:08 +1200 Subject: [PATCH 15/15] FIX: Ensure Embed options are always array This maintains support for embed 3.0.0. --- src/View/Embed/EmbedResource.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/View/Embed/EmbedResource.php b/src/View/Embed/EmbedResource.php index 3f867465f..8a1c2127c 100644 --- a/src/View/Embed/EmbedResource.php +++ b/src/View/Embed/EmbedResource.php @@ -29,7 +29,7 @@ class EmbedResource implements Embeddable /** * @var array */ - protected $options; + protected $options = []; /** * @var DispatcherInterface