From 72d28ebb7a0ce0f57389025ead44886aae7a4ec5 Mon Sep 17 00:00:00 2001 From: Christopher Georg Date: Fri, 23 Dec 2022 10:25:46 +0100 Subject: [PATCH 01/10] feat: drop support oh php 7, use language level features of php 8m add strong types --- CraueGeoBundle.php | 8 +- DependencyInjection/CraueGeoExtension.php | 6 +- Doctrine/Fixtures/GeonamesPostalCodeData.php | 114 +++++++++--------- Doctrine/Query/Mysql/GeoDistance.php | 20 +-- .../Query/Mysql/GeoDistanceByPostalCode.php | 15 ++- Doctrine/Query/Postgresql/GeoDistance.php | 2 +- Entity/GeoPostalCode.php | 70 +++++------ Tests/AppKernel.php | 10 +- .../PuertoRicoGeonamesPostalCodeData.php | 7 +- Tests/Doctrine/Fixtures/FixtureTest.php | 21 ++-- .../Query/Mysql/CustomFunctionNameTest.php | 12 +- .../Mysql/DisablePostalCodeEntityTest.php | 6 +- Tests/Doctrine/Query/Mysql/FlavorTest.php | 9 +- .../Mysql/GeoDistanceByPostalCodeTest.php | 12 +- .../Doctrine/Query/Mysql/GeoDistanceTest.php | 11 +- Tests/Doctrine/Query/Mysql/TimingTest.php | 33 +++-- Tests/IntegrationTestCase.php | 95 +++++++-------- composer.json | 38 +++--- 18 files changed, 262 insertions(+), 227 deletions(-) diff --git a/CraueGeoBundle.php b/CraueGeoBundle.php index 1f7c363..342b253 100644 --- a/CraueGeoBundle.php +++ b/CraueGeoBundle.php @@ -16,15 +16,13 @@ class CraueGeoBundle extends Bundle { /** * {@inheritDoc} */ - public function build(ContainerBuilder $container) { + public function build(ContainerBuilder $container): void { parent::build($container); $this->addRegisterMappingsPass($container); } - /** - * @param ContainerBuilder $container - */ - private function addRegisterMappingsPass(ContainerBuilder $container) { + private function addRegisterMappingsPass(ContainerBuilder $container): void + { $mappings = [ realpath(__DIR__ . '/Resources/config/doctrine-mapping') => 'Craue\GeoBundle\Entity', ]; diff --git a/DependencyInjection/CraueGeoExtension.php b/DependencyInjection/CraueGeoExtension.php index 9388c59..6a9c9a5 100644 --- a/DependencyInjection/CraueGeoExtension.php +++ b/DependencyInjection/CraueGeoExtension.php @@ -18,13 +18,13 @@ class CraueGeoExtension extends Extension implements PrependExtensionInterface { /** * {@inheritDoc} */ - public function load(array $config, ContainerBuilder $container) { + public function load(array $configs, ContainerBuilder $container): void { } /** * {@inheritDoc} - */ - public function prepend(ContainerBuilder $container) { + */ + public function prepend(ContainerBuilder $container): void { $config = $this->processConfiguration(new Configuration(), $container->getExtensionConfig($this->getAlias())); if ($config['enable_postal_code_entity'] === true) { diff --git a/Doctrine/Fixtures/GeonamesPostalCodeData.php b/Doctrine/Fixtures/GeonamesPostalCodeData.php index 6dbe092..e77a39e 100644 --- a/Doctrine/Fixtures/GeonamesPostalCodeData.php +++ b/Doctrine/Fixtures/GeonamesPostalCodeData.php @@ -14,15 +14,16 @@ */ abstract class BaseGeonamesPostalCodeData implements FixtureInterface { - protected $batchSize = 1000; + protected int $batchSize = 1000; // TODO remove as soon as doctrine/persistence >= 2.0 is required - protected final function _getRepository($manager) { + final protected function _getRepository($manager) { return $manager->getRepository(GeoPostalCode::class); } // TODO remove as soon as doctrine/persistence >= 2.0 is required - protected final function _clearPostalCodesTable($manager) { + final protected function _clearPostalCodesTable($manager): void + { foreach ($this->_getRepository($manager)->findAll() as $entity) { $manager->remove($entity); } @@ -30,54 +31,55 @@ protected final function _clearPostalCodesTable($manager) { } // TODO remove as soon as doctrine/persistence >= 2.0 is required - protected final function _addEntries($manager, $filename) { + final protected function _addEntries($manager, $filename): int + { $repo = $this->_getRepository($manager); $entriesAdded = 0; $currentBatchEntries = []; $fcontents = file($filename); - for ($i = 0, $numLines = count($fcontents); $i < $numLines; ++$i) { - $line = trim($fcontents[$i]); - $arr = explode("\t", $line); - - // skip if no lat/lng values - if (!array_key_exists(9, $arr) || !array_key_exists(10, $arr)) { - continue; - } - - $country = $arr[0]; - $postalCode = $arr[1]; - - // skip duplicate entries in current batch - if (in_array($country.'-'.$postalCode, $currentBatchEntries, true)) { - continue; - } - - // skip duplicate entries already persisted - if ($repo->findOneBy(['country' => $country, 'postalCode' => $postalCode]) !== null) { - continue; - } - - $entity = new GeoPostalCode(); - $entity->setCountry($country); - $entity->setPostalCode($postalCode); - $entity->setLat((float) $arr[9]); - $entity->setLng((float) $arr[10]); - $manager->persist($entity); - - ++$entriesAdded; - $currentBatchEntries[] = $country.'-'.$postalCode; - - if ((($i + 1) % $this->batchSize) === 0) { - $manager->flush(); - $manager->clear(); - $currentBatchEntries = []; - echo '.'; // progress indicator - } - } - - $manager->flush(); // Flush for the last batch, which doesn't reach the batch size in most cases. (fixes #2) + foreach ($fcontents as $i => $iValue) { + $line = trim($iValue); + $arr = explode("\t", $line); + + // skip if no lat/lng values + if (!array_key_exists(9, $arr) || !array_key_exists(10, $arr)) { + continue; + } + + $country = $arr[0]; + $postalCode = $arr[1]; + + // skip duplicate entries in current batch + if (in_array($country.'-'.$postalCode, $currentBatchEntries, true)) { + continue; + } + + // skip duplicate entries already persisted + if ($repo->findOneBy(['country' => $country, 'postalCode' => $postalCode]) !== null) { + continue; + } + + $entity = new GeoPostalCode(); + $entity->setCountry($country); + $entity->setPostalCode($postalCode); + $entity->setLat((float) $arr[9]); + $entity->setLng((float) $arr[10]); + $manager->persist($entity); + + ++$entriesAdded; + $currentBatchEntries[] = $country.'-'.$postalCode; + + if ((($i + 1) % $this->batchSize) === 0) { + $manager->flush(); + $manager->clear(); + $currentBatchEntries = []; + echo '.'; // progress indicator + } + } + + $manager->flush(); // Flush for the last batch, which doesn't reach the batch size in most cases. (fixes #2) echo ' ', $entriesAdded, "\n"; @@ -98,23 +100,24 @@ abstract class GeonamesPostalCodeData extends BaseGeonamesPostalCodeData { * @param ObjectManager $manager * @return ObjectRepository */ - protected function getRepository(ObjectManager $manager) { + protected function getRepository(ObjectManager $manager): ObjectRepository + { return $this->_getRepository($manager); } /** * @param ObjectManager $manager */ - protected function clearPostalCodesTable(ObjectManager $manager) { + protected function clearPostalCodesTable(ObjectManager $manager): void + { $this->_clearPostalCodesTable($manager); } /** - * @param ObjectManager $manager - * @param string $filename * @return int Number of entries actually added. */ - protected function addEntries(ObjectManager $manager, $filename) { + protected function addEntries(ObjectManager $manager, string $filename): int + { return $this->_addEntries($manager, $filename); } } @@ -129,23 +132,24 @@ abstract class GeonamesPostalCodeData extends BaseGeonamesPostalCodeData { * @param LegacyObjectManager $manager * @return LegacyObjectRepository */ - protected function getRepository(LegacyObjectManager $manager) { + protected function getRepository(LegacyObjectManager $manager): LegacyObjectRepository + { return $this->_getRepository($manager); } /** * @param LegacyObjectManager $manager */ - protected function clearPostalCodesTable(LegacyObjectManager $manager) { + protected function clearPostalCodesTable(LegacyObjectManager $manager): void + { $this->_clearPostalCodesTable($manager); } /** - * @param LegacyObjectManager $manager - * @param string $filename * @return int Number of entries actually added. */ - protected function addEntries(LegacyObjectManager $manager, $filename) { + protected function addEntries(LegacyObjectManager $manager, string $filename): int + { return $this->_addEntries($manager, $filename); } } diff --git a/Doctrine/Query/Mysql/GeoDistance.php b/Doctrine/Query/Mysql/GeoDistance.php index 275e5d0..de4698b 100644 --- a/Doctrine/Query/Mysql/GeoDistance.php +++ b/Doctrine/Query/Mysql/GeoDistance.php @@ -2,9 +2,11 @@ namespace Craue\GeoBundle\Doctrine\Query\Mysql; +use Doctrine\ORM\Query\AST\ArithmeticExpression; use Doctrine\ORM\Query\AST\Functions\FunctionNode; use Doctrine\ORM\Query\Lexer; use Doctrine\ORM\Query\Parser; +use Doctrine\ORM\Query\QueryException; use Doctrine\ORM\Query\SqlWalker; /** @@ -17,14 +19,17 @@ */ class GeoDistance extends FunctionNode { - const EARTH_DIAMETER = 12742; // 2 * Earth's radius (6371 km) + public const EARTH_DIAMETER = 12742; // 2 * Earth's radius (6371 km) - protected $latOrigin; - protected $lngOrigin; - protected $latDestination; - protected $lngDestination; + protected ArithmeticExpression $latOrigin; + protected ArithmeticExpression $lngOrigin; + protected ArithmeticExpression $latDestination; + protected ArithmeticExpression $lngDestination; - public function parse(Parser $parser) : void { + /** + * @throws QueryException + */ + public function parse(Parser $parser) : void { $parser->match(Lexer::T_IDENTIFIER); $parser->match(Lexer::T_OPEN_PARENTHESIS); $this->latOrigin = $parser->ArithmeticExpression(); @@ -56,7 +61,8 @@ public function getSql(SqlWalker $sqlWalker) : string { ); } - protected function getSqlWithPlaceholders() { + protected function getSqlWithPlaceholders(): string + { return '%s * ASIN(SQRT(POWER(SIN((%s - %s) * PI()/360), 2) + COS(%s * PI()/180) * COS(%s * PI()/180) * POWER(SIN((%s - %s) * PI()/360), 2)))'; } diff --git a/Doctrine/Query/Mysql/GeoDistanceByPostalCode.php b/Doctrine/Query/Mysql/GeoDistanceByPostalCode.php index 15b17c7..c83a0b2 100644 --- a/Doctrine/Query/Mysql/GeoDistanceByPostalCode.php +++ b/Doctrine/Query/Mysql/GeoDistanceByPostalCode.php @@ -3,8 +3,10 @@ namespace Craue\GeoBundle\Doctrine\Query\Mysql; use Doctrine\ORM\Query\AST\Functions\FunctionNode; +use Doctrine\ORM\Query\AST\Node; use Doctrine\ORM\Query\Lexer; use Doctrine\ORM\Query\Parser; +use Doctrine\ORM\Query\QueryException; use Doctrine\ORM\Query\SqlWalker; /** @@ -17,12 +19,15 @@ */ class GeoDistanceByPostalCode extends FunctionNode { - protected $countryOrigin; - protected $postalCodeOrigin; - protected $countryDestination; - protected $postalCodeDestination; + protected Node $countryOrigin; + protected Node $postalCodeOrigin; + protected Node $countryDestination; + protected Node $postalCodeDestination; - public function parse(Parser $parser) : void { + /** + * @throws QueryException + */ + public function parse(Parser $parser) : void { $parser->match(Lexer::T_IDENTIFIER); $parser->match(Lexer::T_OPEN_PARENTHESIS); $this->countryOrigin = $parser->StringPrimary(); diff --git a/Doctrine/Query/Postgresql/GeoDistance.php b/Doctrine/Query/Postgresql/GeoDistance.php index abf77c1..f114604 100644 --- a/Doctrine/Query/Postgresql/GeoDistance.php +++ b/Doctrine/Query/Postgresql/GeoDistance.php @@ -9,7 +9,7 @@ */ class GeoDistance extends BaseGeoDistance { - protected function getSqlWithPlaceholders() { + protected function getSqlWithPlaceholders(): string { return '%s * ASIN(SQRT(POWER(SIN((CAST(%s AS numeric) - CAST(%s AS numeric)) * PI()/360), 2) + COS(%s * PI()/180) * COS(%s * PI()/180) * POWER(SIN((CAST(%s AS numeric) - CAST(%s AS numeric)) * PI()/360), 2)))'; } diff --git a/Entity/GeoPostalCode.php b/Entity/GeoPostalCode.php index d33b5c1..e6c5a0b 100644 --- a/Entity/GeoPostalCode.php +++ b/Entity/GeoPostalCode.php @@ -11,68 +11,62 @@ */ class GeoPostalCode { - /** - * @var int - */ - protected $id; - - /** - * @var string - * @Assert\NotBlank - */ - protected $country; - - /** - * @var string - * @Assert\NotBlank - */ - protected $postalCode; - - /** - * @var double - * @Assert\NotBlank - */ - protected $lat; - - /** - * @var double - * @Assert\NotBlank - */ - protected $lng; - - public function getId() { + protected int $id; + + #[Assert\NotBlank] + protected string $country; + + #[Assert\NotBlank] + protected string $postalCode; + + #[Assert\NotBlank] + protected float $lat; + + #[Assert\NotBlank] + protected float $lng; + + public function getId(): int + { return $this->id; } - public function setCountry($country) { + public function setCountry(string $country): void + { $this->country = $country; } - public function getCountry() { + public function getCountry(): string + { return $this->country; } - public function setPostalCode($postalCode) { + public function setPostalCode(string $postalCode): void + { $this->postalCode = $postalCode; } - public function getPostalCode() { + public function getPostalCode(): string + { return $this->postalCode; } - public function setLat($lat) { + public function setLat(float $lat): void + { $this->lat = $lat; } - public function getLat() { + public function getLat(): float + { return $this->lat; } - public function setLng($lng) { + public function setLng(float $lng): void + { $this->lng = $lng; } - public function getLng() { + public function getLng(): float + { return $this->lng; } diff --git a/Tests/AppKernel.php b/Tests/AppKernel.php index b37af87..50172c1 100644 --- a/Tests/AppKernel.php +++ b/Tests/AppKernel.php @@ -8,7 +8,7 @@ class AppKernel extends Kernel { - private $configFiles; + private array $configFiles; public function __construct($environment, $configFiles) { parent::__construct($environment, true); @@ -42,7 +42,7 @@ public function registerBundles() : iterable { ]; } - public function registerContainerConfiguration(LoaderInterface $loader) { + public function registerContainerConfiguration(LoaderInterface $loader): void { if (!is_array($this->configFiles)) { $this->configFiles = (array) $this->configFiles; } @@ -68,11 +68,13 @@ public function getLogDir() : string { return parent::getLogDir(); } - public function serialize() { + public function serialize(): string + { return serialize([$this->environment, $this->configFiles]); } - public function unserialize($data) { + public function unserialize($data): void + { list($environment, $configFiles) = unserialize($data); $this->__construct($environment, $configFiles); } diff --git a/Tests/Doctrine/Fixtures/CraueGeo/PuertoRicoGeonamesPostalCodeData.php b/Tests/Doctrine/Fixtures/CraueGeo/PuertoRicoGeonamesPostalCodeData.php index 922e599..c2a9699 100644 --- a/Tests/Doctrine/Fixtures/CraueGeo/PuertoRicoGeonamesPostalCodeData.php +++ b/Tests/Doctrine/Fixtures/CraueGeo/PuertoRicoGeonamesPostalCodeData.php @@ -12,7 +12,8 @@ abstract class BasePuertoRicoGeonamesPostalCodeData extends GeonamesPostalCodeData { // TODO update README with Doctrine\Persistence\ObjectManager type-hint as soon as doctrine/persistence >= 2.0 is required - protected final function _load($manager) { + final protected function _load($manager): void + { $this->clearPostalCodesTable($manager); $zip = new \ZipArchive(); @@ -39,7 +40,7 @@ class PuertoRicoGeonamesPostalCodeData extends BasePuertoRicoGeonamesPostalCodeD /** * {@inheritDoc} */ - public function load(ObjectManager $manager) { + public function load(ObjectManager $manager): void { $this->_load($manager); } } @@ -53,7 +54,7 @@ class PuertoRicoGeonamesPostalCodeData extends BasePuertoRicoGeonamesPostalCodeD /** * {@inheritDoc} */ - public function load(LegacyObjectManager $manager) { + public function load(LegacyObjectManager $manager): void { $this->_load($manager); } } diff --git a/Tests/Doctrine/Fixtures/FixtureTest.php b/Tests/Doctrine/Fixtures/FixtureTest.php index 8db5d2b..91c2bfa 100644 --- a/Tests/Doctrine/Fixtures/FixtureTest.php +++ b/Tests/Doctrine/Fixtures/FixtureTest.php @@ -21,7 +21,8 @@ class FixtureTest extends IntegrationTestCase { /** * @dataProvider getPlatformConfigs */ - public function testImportByUsingFixtureDirectly($platform, $config, $requiredExtension) { + public function testImportByUsingFixtureDirectly($platform, $config, $requiredExtension): void + { $this->initClient($requiredExtension, ['environment' => $platform, 'config' => $config]); // [A] add some data which is meant to be removed by importing new data @@ -44,7 +45,8 @@ public function testImportByUsingFixtureDirectly($platform, $config, $requiredEx /** * @dataProvider getPlatformConfigs */ - public function testImportByDoctrineFixturesBundle2Command($platform, $config, $requiredExtension) { + public function testImportByDoctrineFixturesBundle2Command($platform, $config, $requiredExtension): void + { if (class_exists(SymfonyFixturesLoader::class)) { $this->markTestSkipped('DoctrineFixturesBundle >= 3.0 does not allow loading fixtures from a directory anymore.'); } @@ -70,7 +72,8 @@ public function testImportByDoctrineFixturesBundle2Command($platform, $config, $ /** * @dataProvider dataImportByDoctrineFixturesBundle3Command */ - public function testImportByDoctrineFixturesBundle3Command($platform, $config, $requiredExtension) { + public function testImportByDoctrineFixturesBundle3Command($platform, $config, $requiredExtension): void + { if (!interface_exists(FixtureGroupInterface::class)) { $this->markTestSkipped('DoctrineFixturesBundle < 3.1 does not support fixture groups.'); } @@ -93,7 +96,8 @@ public function testImportByDoctrineFixturesBundle3Command($platform, $config, $ $this->assertCount(177, $this->getRepo()->findAll()); } - public function dataImportByDoctrineFixturesBundle3Command() { + public function dataImportByDoctrineFixturesBundle3Command(): array + { return self::duplicateTestDataForEachPlatform([ [], ], 'config_fixtureAsAService.yml'); @@ -102,7 +106,8 @@ public function dataImportByDoctrineFixturesBundle3Command() { /** * @dataProvider dataImportByDoctrineFixturesBundle3CommandWithAutoRegistration */ - public function testImportByDoctrineFixturesBundle3CommandWithAutoRegistration($platform, $config, $requiredExtension) { + public function testImportByDoctrineFixturesBundle3CommandWithAutoRegistration($platform, $config, $requiredExtension): void + { if (!interface_exists(FixtureGroupInterface::class)) { $this->markTestSkipped('DoctrineFixturesBundle < 3.1 does not support fixture groups.'); } @@ -125,13 +130,15 @@ public function testImportByDoctrineFixturesBundle3CommandWithAutoRegistration($ $this->assertCount(177, $this->getRepo()->findAll()); } - public function dataImportByDoctrineFixturesBundle3CommandWithAutoRegistration() { + public function dataImportByDoctrineFixturesBundle3CommandWithAutoRegistration(): array + { return self::duplicateTestDataForEachPlatform([ [], ], 'config_fixtureAsAService_autoRegistration.yml'); } - private static function executeCommand(Application $application, $command, array $options = []) { + private static function executeCommand(Application $application, string $command, array $options = []): string + { $options = array_merge($options, [ '--env' => $application->getKernel()->getEnvironment(), '--no-debug' => null, diff --git a/Tests/Doctrine/Query/Mysql/CustomFunctionNameTest.php b/Tests/Doctrine/Query/Mysql/CustomFunctionNameTest.php index baff190..f5af54c 100644 --- a/Tests/Doctrine/Query/Mysql/CustomFunctionNameTest.php +++ b/Tests/Doctrine/Query/Mysql/CustomFunctionNameTest.php @@ -19,7 +19,8 @@ class CustomFunctionNameTest extends IntegrationTestCase { * * @dataProvider dataCustomFunctionName */ - public function testCustomFunctionName($platform, $config, $requiredExtension) { + public function testCustomFunctionName($platform, $config, $requiredExtension): void + { $this->initClient($requiredExtension, ['environment' => 'customFunctionName_' . $platform, 'config' => $config]); $this->assertSame(sprintf('Craue\GeoBundle\Doctrine\Query\%s\GeoDistance', ucfirst($platform)), @@ -28,7 +29,8 @@ public function testCustomFunctionName($platform, $config, $requiredExtension) { $this->getEntityManager()->getConfiguration()->getCustomNumericFunction('CRAUE_GEO_DISTANCE_BY_POSTAL_CODE')); } - public function dataCustomFunctionName() { + public function dataCustomFunctionName(): array + { return self::duplicateTestDataForEachPlatform([ [], ], 'config_customFunctionName.yml'); @@ -39,13 +41,15 @@ public function dataCustomFunctionName() { * * @dataProvider dataOverrideFunction */ - public function testOverrideFunction($platform, $config, $requiredExtension) { + public function testOverrideFunction($platform, $config, $requiredExtension): void + { $this->initClient($requiredExtension, ['environment' => 'overrideFunction_' . $platform, 'config' => $config]); $this->assertSame(GeoDistance::class, $this->getEntityManager()->getConfiguration()->getCustomNumericFunction('MY_GEO_DISTANCE')); } - public function dataOverrideFunction() { + public function dataOverrideFunction(): array + { return self::duplicateTestDataForEachPlatform([ [], ], 'config_overrideFunction.yml'); diff --git a/Tests/Doctrine/Query/Mysql/DisablePostalCodeEntityTest.php b/Tests/Doctrine/Query/Mysql/DisablePostalCodeEntityTest.php index dec0ed1..3fffcad 100644 --- a/Tests/Doctrine/Query/Mysql/DisablePostalCodeEntityTest.php +++ b/Tests/Doctrine/Query/Mysql/DisablePostalCodeEntityTest.php @@ -19,7 +19,8 @@ class DisablePostalCodeEntityTest extends IntegrationTestCase { * * @dataProvider dataDisablePostalCodeEntity */ - public function testDisablePostalCodeEntity($platform, $config, $requiredExtension) { + public function testDisablePostalCodeEntity($platform, $config, $requiredExtension): void + { $this->initClient($requiredExtension, ['environment' => 'disablePostalCodeEntity_' . $platform, 'config' => $config]); $this->expectException(MappingException::class); @@ -33,7 +34,8 @@ public function testDisablePostalCodeEntity($platform, $config, $requiredExtensi $this->getRepo(); } - public function dataDisablePostalCodeEntity() { + public function dataDisablePostalCodeEntity(): array + { return self::duplicateTestDataForEachPlatform([ [], ], 'config_disablePostalCodeEntity.yml'); diff --git a/Tests/Doctrine/Query/Mysql/FlavorTest.php b/Tests/Doctrine/Query/Mysql/FlavorTest.php index 51ef2b2..5bacfb3 100644 --- a/Tests/Doctrine/Query/Mysql/FlavorTest.php +++ b/Tests/Doctrine/Query/Mysql/FlavorTest.php @@ -18,7 +18,8 @@ class FlavorTest extends IntegrationTestCase { /** * Ensure that only valid values can be used for the flavor. */ - public function testFlavorInvalid() { + public function testFlavorInvalid(): void + { $this->expectException(InvalidConfigurationException::class); $this->expectExceptionMessage('The value "invalid" is not allowed for path "craue_geo.flavor". Permissible values: "none", "mysql", "postgresql"'); @@ -28,7 +29,8 @@ public function testFlavorInvalid() { /** * Ensure that function GEO_DISTANCE is not registered when using flavor 'none'. */ - public function testFlavorNone_geoDistance() { + public function testFlavorNone_geoDistance(): void + { $this->initClient(null, ['environment' => 'flavorNone', 'config' => ['config.yml', 'config_flavor_none.yml']]); $this->expectException(QueryException::class); @@ -40,7 +42,8 @@ public function testFlavorNone_geoDistance() { /** * Ensure that function GEO_DISTANCE_BY_POSTAL_CODE is not registered when using flavor 'none'. */ - public function testFlavorNone_geoDistanceByPostalCode() { + public function testFlavorNone_geoDistanceByPostalCode(): void + { $this->initClient(null, ['environment' => 'flavorNone', 'config' => ['config.yml', 'config_flavor_none.yml']]); $this->expectException(QueryException::class); diff --git a/Tests/Doctrine/Query/Mysql/GeoDistanceByPostalCodeTest.php b/Tests/Doctrine/Query/Mysql/GeoDistanceByPostalCodeTest.php index d2cc185..a31f7b7 100644 --- a/Tests/Doctrine/Query/Mysql/GeoDistanceByPostalCodeTest.php +++ b/Tests/Doctrine/Query/Mysql/GeoDistanceByPostalCodeTest.php @@ -16,7 +16,8 @@ class GeoDistanceByPostalCodeTest extends IntegrationTestCase { /** * @dataProvider getPlatformConfigs */ - public function testNoResults($platform, $config, $requiredExtension) { + public function testNoResults($platform, $config, $requiredExtension): void + { $this->initClient($requiredExtension, ['environment' => $platform, 'config' => $config]); $result = $this->getPoisPerGeoDistanceByPostalCode('DE', '10551'); @@ -27,7 +28,8 @@ public function testNoResults($platform, $config, $requiredExtension) { /** * @dataProvider getPlatformConfigs */ - public function testDistance($platform, $config, $requiredExtension) { + public function testDistance($platform, $config, $requiredExtension): void + { $this->initClient($requiredExtension, ['environment' => $platform, 'config' => $config]); $this->persistGeoPostalCode('DE', '14473', 52.392759, 13.065135); @@ -43,7 +45,8 @@ public function testDistance($platform, $config, $requiredExtension) { /** * @dataProvider getPlatformConfigs */ - public function testUnknownPostalCode_withRadius($platform, $config, $requiredExtension) { + public function testUnknownPostalCode_withRadius($platform, $config, $requiredExtension): void + { $this->initClient($requiredExtension, ['environment' => $platform, 'config' => $config]); $this->persistGeoPostalCode('DE', '14473', 52.392759, 13.065135); @@ -57,7 +60,8 @@ public function testUnknownPostalCode_withRadius($platform, $config, $requiredEx /** * @dataProvider getPlatformConfigs */ - public function testUnknownPostalCode_withoutRadius($platform, $config, $requiredExtension) { + public function testUnknownPostalCode_withoutRadius($platform, $config, $requiredExtension): void + { $this->initClient($requiredExtension, ['environment' => $platform, 'config' => $config]); $this->persistGeoPostalCode('DE', '14473', 52.392759, 13.065135); diff --git a/Tests/Doctrine/Query/Mysql/GeoDistanceTest.php b/Tests/Doctrine/Query/Mysql/GeoDistanceTest.php index 5525f3f..bd7dc4d 100644 --- a/Tests/Doctrine/Query/Mysql/GeoDistanceTest.php +++ b/Tests/Doctrine/Query/Mysql/GeoDistanceTest.php @@ -16,9 +16,10 @@ class GeoDistanceTest extends IntegrationTestCase { /** * @var bool[] */ - private static $dummyDataAdded = []; + private static array $dummyDataAdded = []; - protected function prepareDatabase($platform, $config, $requiredExtension) { + protected function prepareDatabase($platform, $config, $requiredExtension): void + { if (!array_key_exists($platform, self::$dummyDataAdded)) { self::$dummyDataAdded[$platform] = false; } @@ -36,7 +37,8 @@ protected function prepareDatabase($platform, $config, $requiredExtension) { * @dataProvider dataGeoDistance */ public function testGeoDistance($platform, $config, $requiredExtension, - $latOrigin, $lngOrigin, $latDestination, $lngDestination, $expectedDistance) { + $latOrigin, $lngOrigin, $latDestination, $lngDestination, $expectedDistance): void + { $this->prepareDatabase($platform, $config, $requiredExtension); $qb = $this->getRepo()->createQueryBuilder('poi') @@ -51,7 +53,8 @@ public function testGeoDistance($platform, $config, $requiredExtension, $this->assertEquals($expectedDistance, $qb->getQuery()->getSingleScalarResult()); } - public function dataGeoDistance() { + public function dataGeoDistance(): array + { return self::duplicateTestDataForEachPlatform([ [52.392759, 13.065135, 52.392759, 13.065135, 0], [52.392759, 13.065135, 52.525011, 13.369438, 25.32498093345365], diff --git a/Tests/Doctrine/Query/Mysql/TimingTest.php b/Tests/Doctrine/Query/Mysql/TimingTest.php index 80b29be..5e41141 100644 --- a/Tests/Doctrine/Query/Mysql/TimingTest.php +++ b/Tests/Doctrine/Query/Mysql/TimingTest.php @@ -13,14 +13,15 @@ */ class TimingTest extends IntegrationTestCase { - const NUMBER_OF_POIS = 50000; + public const NUMBER_OF_POIS = 50000; /** * @var bool[] */ - private static $dummyDataAdded = []; + private static array $dummyDataAdded = []; - protected function prepareDatabase($platform, $config, $requiredExtension) { + protected function prepareDatabase($platform, $config, $requiredExtension): void + { if (!array_key_exists($platform, self::$dummyDataAdded)) { self::$dummyDataAdded[$platform] = false; } @@ -37,7 +38,8 @@ protected function prepareDatabase($platform, $config, $requiredExtension) { /** * @dataProvider getPlatformConfigs */ - public function testTimingGeoDistance_withRadius($platform, $config, $requiredExtension) { + public function testTimingGeoDistance_withRadius($platform, $config, $requiredExtension): void + { $this->prepareDatabase($platform, $config, $requiredExtension); $startTime = microtime(true); @@ -45,13 +47,14 @@ public function testTimingGeoDistance_withRadius($platform, $config, $requiredEx $duration = microtime(true) - $startTime; $this->assertLessThan($platform === self::PLATFORM_POSTGRESQL ? 0.6 : 0.4, $duration); - $this->assertEquals(854, count($result)); + $this->assertCount(854, $result); } /** * @dataProvider getPlatformConfigs */ - public function testTimingGeoDistance_withRadius_optimized($platform, $config, $requiredExtension) { + public function testTimingGeoDistance_withRadius_optimized($platform, $config, $requiredExtension): void + { $this->prepareDatabase($platform, $config, $requiredExtension); $startTime = microtime(true); @@ -59,13 +62,14 @@ public function testTimingGeoDistance_withRadius_optimized($platform, $config, $ $duration = microtime(true) - $startTime; $this->assertLessThan(0.4, $duration); - $this->assertEquals(854, count($result)); + $this->assertCount(854, $result); } /** * @dataProvider getPlatformConfigs */ - public function testTimingGeoDistance_withoutRadius($platform, $config, $requiredExtension) { + public function testTimingGeoDistance_withoutRadius($platform, $config, $requiredExtension): void + { $this->prepareDatabase($platform, $config, $requiredExtension); $startTime = microtime(true); @@ -79,7 +83,8 @@ public function testTimingGeoDistance_withoutRadius($platform, $config, $require /** * @dataProvider getPlatformConfigs */ - public function testTimingGeoDistanceByPostalCode_withRadius($platform, $config, $requiredExtension) { + public function testTimingGeoDistanceByPostalCode_withRadius($platform, $config, $requiredExtension): void + { $this->prepareDatabase($platform, $config, $requiredExtension); $startTime = microtime(true); @@ -87,13 +92,14 @@ public function testTimingGeoDistanceByPostalCode_withRadius($platform, $config, $duration = microtime(true) - $startTime; $this->assertLessThan($platform === self::PLATFORM_POSTGRESQL ? 7 : 2.8, $duration); - $this->assertEquals(1703, count($result)); + $this->assertCount(1703, $result); } /** * @dataProvider getPlatformConfigs */ - public function testTimingGeoDistanceByPostalCode_withRadius_optimized($platform, $config, $requiredExtension) { + public function testTimingGeoDistanceByPostalCode_withRadius_optimized($platform, $config, $requiredExtension): void + { $this->prepareDatabase($platform, $config, $requiredExtension); $startTime = microtime(true); @@ -101,13 +107,14 @@ public function testTimingGeoDistanceByPostalCode_withRadius_optimized($platform $duration = microtime(true) - $startTime; $this->assertLessThan($platform === self::PLATFORM_POSTGRESQL ? 0.8 : 0.65, $duration); - $this->assertEquals(1703, count($result)); + $this->assertCount(1703, $result); } /** * @dataProvider getPlatformConfigs */ - public function testTimingGeoDistanceByPostalCode_withoutRadius($platform, $config, $requiredExtension) { + public function testTimingGeoDistanceByPostalCode_withoutRadius($platform, $config, $requiredExtension): void + { $this->prepareDatabase($platform, $config, $requiredExtension); $startTime = microtime(true); diff --git a/Tests/IntegrationTestCase.php b/Tests/IntegrationTestCase.php index 5498892..88b0151 100644 --- a/Tests/IntegrationTestCase.php +++ b/Tests/IntegrationTestCase.php @@ -18,10 +18,11 @@ */ abstract class IntegrationTestCase extends WebTestCase { - const PLATFORM_MYSQL = 'mysql'; - const PLATFORM_POSTGRESQL = 'postgresql'; + public const PLATFORM_MYSQL = 'mysql'; + public const PLATFORM_POSTGRESQL = 'postgresql'; - public static function getValidPlatformsWithRequiredExtensions() { + public static function getValidPlatformsWithRequiredExtensions(): array + { return [ self::PLATFORM_MYSQL => 'pdo_mysql', self::PLATFORM_POSTGRESQL => 'pdo_pgsql', @@ -31,14 +32,15 @@ public static function getValidPlatformsWithRequiredExtensions() { /** * @var bool[] */ - private static $databaseInitialized = []; + private static array $databaseInitialized = []; /** * @param string $testName The name of the test, set by PHPUnit when called directly as a {@code dataProvider}. * @param string $baseConfig The base config filename. - * @return string[] + * @return array> */ - public static function getPlatformConfigs($testName, $baseConfig = 'config.yml') { + public static function getPlatformConfigs(string $testName, string $baseConfig = 'config.yml'): array + { $testData = []; foreach (self::getValidPlatformsWithRequiredExtensions() as $platform => $extension) { @@ -48,11 +50,8 @@ public static function getPlatformConfigs($testName, $baseConfig = 'config.yml') return $testData; } - /** - * @param array $allTestData - * @return array - */ - public static function duplicateTestDataForEachPlatform(array $allTestData, $baseConfig = 'config.yml') { + public static function duplicateTestDataForEachPlatform(array $allTestData, string $baseConfig = 'config.yml'): array + { $testData = []; foreach ($allTestData as $oneTestData) { @@ -65,13 +64,13 @@ public static function duplicateTestDataForEachPlatform(array $allTestData, $bas } /** - * @param double $lat - * @param double $lng - * @param double $maxRadiusInKm - * @param bool $addRadiusOptimization * @return GeoPostalCode[] */ - protected function getPoisPerGeoDistance($lat, $lng, $maxRadiusInKm = null, $addRadiusOptimization = false) { + protected function getPoisPerGeoDistance(float $lat, + float $lng, + ?float $maxRadiusInKm = null, + bool $addRadiusOptimization = false): array + { $distanceFunction = 'GEO_DISTANCE(:lat, :lng, poi.lat, poi.lng)'; $qb = $this->getRepo()->createQueryBuilder('poi') @@ -97,13 +96,13 @@ protected function getPoisPerGeoDistance($lat, $lng, $maxRadiusInKm = null, $add } /** - * @param string $country - * @param string $postalCode - * @param double $maxRadiusInKm - * @param bool $addRadiusOptimization * @return GeoPostalCode[] */ - protected function getPoisPerGeoDistanceByPostalCode($country, $postalCode, $maxRadiusInKm = null, $addRadiusOptimization = false) { + protected function getPoisPerGeoDistanceByPostalCode(string $country, + string $postalCode, + ?float $maxRadiusInKm = null, + bool $addRadiusOptimization = false): array + { $distanceFunction = 'GEO_DISTANCE_BY_POSTAL_CODE(:country, :postalCode, poi.country, poi.postalCode)'; $qb = $this->getRepo()->createQueryBuilder('poi') @@ -140,12 +139,9 @@ protected function getPoisPerGeoDistanceByPostalCode($country, $postalCode, $max /** * Adds the radius optimization mentioned in {@see http://www.scribd.com/doc/2569355/Geo-Distance-Search-with-MySQL} (pages 11-13) to * the given {@code QueryBuilder} instance. - * @param QueryBuilder $qb - * @param double $latOrigin - * @param double $lngOrigin - * @param double $maxRadiusInKm */ - private function addRadiusOptimization(QueryBuilder $qb, $latOrigin, $lngOrigin, $maxRadiusInKm) { + private function addRadiusOptimization(QueryBuilder $qb, float $latOrigin, float $lngOrigin, float $maxRadiusInKm): void + { $latDistance = 111.2; // distance between two latitudes is about 111.2 km $latDiff = $maxRadiusInKm / $latDistance; $lngDiff = $maxRadiusInKm / abs(cos(deg2rad($latOrigin)) * $latDistance); @@ -163,7 +159,8 @@ private function addRadiusOptimization(QueryBuilder $qb, $latOrigin, $lngOrigin, /** * @return boolean Whether the database platform supports using aliases in the HAVING clause. */ - private function platformSupportsAliasInHavingClause() { + private function platformSupportsAliasInHavingClause(): bool + { return $this->getEntityManager()->getConnection()->getDatabasePlatform()->getName() !== self::PLATFORM_POSTGRESQL; } @@ -184,7 +181,8 @@ protected static function createKernel(array $options = []) : KernelInterface { * @param bool $cleanDatabase If the database should be cleaned in case it already exists. * @return AbstractBrowser */ - protected function initClient($requiredExtension, array $options = [], $cleanDatabase = true) { + protected function initClient(?string $requiredExtension, array $options = [], bool $cleanDatabase = true): AbstractBrowser + { if ($requiredExtension !== null && !extension_loaded($requiredExtension)) { $this->markTestSkipped(sprintf('Extension "%s" is not loaded.', $requiredExtension)); } @@ -203,7 +201,8 @@ protected function initClient($requiredExtension, array $options = [], $cleanDat return $client; } - protected function rebuildDatabase() { + protected function rebuildDatabase(): void + { $em = $this->getEntityManager(); $metadata = $em->getMetadataFactory()->getAllMetadata(); $schemaTool = new SchemaTool($em); @@ -214,13 +213,9 @@ protected function rebuildDatabase() { /** * Persists a {@code GeoPostalCode}. - * @param string $country - * @param string $postalCode - * @param double $lat - * @param double $lng - * @return GeoPostalCode */ - protected function persistGeoPostalCode($country, $postalCode, $lat, $lng) { + protected function persistGeoPostalCode(string $country, string $postalCode, float $lat, float $lng): GeoPostalCode + { $entity = new GeoPostalCode(); $entity->setCountry($country); $entity->setPostalCode($postalCode); @@ -236,17 +231,17 @@ protected function persistGeoPostalCode($country, $postalCode, $lat, $lng) { /** * Persists a number of {@code GeoPostalCode}s using non-random dummy data. - * @param int $number */ - protected function persistDummyGeoPostalCodes($number) { + protected function persistDummyGeoPostalCodes(int $number): void + { $em = $this->getEntityManager(); for ($i = 0; $i < $number; ++$i) { $entity = new GeoPostalCode(); $entity->setCountry('DE'); - $entity->setPostalCode($i); - $entity->setLat('52.'.$i); - $entity->setLng('13.'.$i); + $entity->setPostalCode((string) $i); + $entity->setLat((float) ('52.' . $i)); + $entity->setLng((float) ('13.'.$i)); $em->persist($entity); if ((($i + 1) % 10000) === 0) { @@ -261,7 +256,8 @@ protected function persistDummyGeoPostalCodes($number) { /** * Removes all {@code GeoPostalCode}s. */ - protected function removeAllGeoPostalCodes() { + protected function removeAllGeoPostalCodes(): void + { $em = $this->getEntityManager(); foreach ($this->getRepo()->findAll() as $entity) { @@ -271,17 +267,13 @@ protected function removeAllGeoPostalCodes() { $em->flush(); } - /** - * @return EntityManager - */ - protected function getEntityManager() { + protected function getEntityManager(): EntityManager + { return $this->getService('doctrine')->getManager(); } - /** - * @return EntityRepository - */ - protected function getRepo() { + protected function getRepo(): EntityRepository + { return $this->getEntityManager()->getRepository(GeoPostalCode::class); } @@ -289,8 +281,9 @@ protected function getRepo() { * @param string $id The service identifier. * @return object The associated service. */ - protected function getService($id) { + protected function getService(string $id): object + { return static::$kernel->getContainer()->get($id); } -} +} diff --git a/composer.json b/composer.json index 151eeba..c098858 100644 --- a/composer.json +++ b/composer.json @@ -16,27 +16,29 @@ } ], "require": { - "php": "^7.3|^8", - "doctrine/doctrine-bundle": "^1.6.12|^2", - "doctrine/orm": "^2.5.2", - "symfony/config": "~4.4|~5.3|^6", - "symfony/dependency-injection": "~4.4|~5.3|^6", - "symfony/framework-bundle": "~4.4|~5.3|^6" + "php": "^8", + "doctrine/doctrine-bundle": "^2.7", + "doctrine/orm": "^2.14", + "symfony/config": "~4.4|~5.4|^6", + "symfony/dependency-injection": "~4.4|~5.4|^6", + "symfony/framework-bundle": "~4.4|~5.4|^6", + "symfony/validator": "~4.4|~5.4|^6" }, "require-dev": { - "doctrine/annotations": "^1.6", - "doctrine/data-fixtures": "^1.0.1", - "doctrine/dbal": "^2.7|^3", - "doctrine/doctrine-fixtures-bundle": "^2.4.1|^3.1", - "phpstan/extension-installer": "^1.1", - "phpstan/phpstan": "^1.4", - "phpstan/phpstan-deprecation-rules": "^1.0", - "phpstan/phpstan-strict-rules": "^1.1", - "phpstan/phpstan-symfony": "^1.1", + "doctrine/annotations": "^1.14", + "doctrine/data-fixtures": "^1.6", + "doctrine/dbal": "^2.13|^3.5", + "doctrine/doctrine-fixtures-bundle": "^3.4", + "phpstan/extension-installer": "^1.2", + "phpstan/phpstan": "^1.9", + "phpstan/phpstan-deprecation-rules": "^1.1", + "phpstan/phpstan-strict-rules": "^1.4", + "phpstan/phpstan-symfony": "^1.2", "phpunit/phpunit": "^9.5", - "symfony/browser-kit": "~4.4|~5.3|^6", + "symfony/browser-kit": "~4.4|~5.4|^6", "symfony/phpunit-bridge": "^6", - "symfony/yaml": "~4.4|~5.3|^6" + "symfony/yaml": "~4.4|~5.4|^6", + "ext-zip": "*" }, "suggest": { "doctrine/data-fixtures": "*" @@ -55,7 +57,7 @@ "dev-master": "1.9.x-dev" }, "symfony": { - "require": "~4.4|~5.3|^6" + "require": "~4.4|~5.4|^6" } }, "config": { From 326a32f46ddcc9b15b374cde68007f1d30793300 Mon Sep 17 00:00:00 2001 From: Christopher Georg Date: Fri, 23 Dec 2022 11:05:01 +0100 Subject: [PATCH 02/10] feat: drop support oh php 7, use language level features of php 8m add strong types, drop support of doctrine/persistence v2 --- .travis.yml | 17 +- CHANGELOG.md | 9 + Doctrine/Fixtures/GeonamesPostalCodeData.php | 185 ++++++------------ README.md | 38 +--- .../PuertoRicoGeonamesPostalCodeData.php | 66 ++----- 5 files changed, 98 insertions(+), 217 deletions(-) diff --git a/.travis.yml b/.travis.yml index 5572729..45d4e2c 100644 --- a/.travis.yml +++ b/.travis.yml @@ -8,19 +8,13 @@ stages: jobs: include: - stage: smoke test 🕵️ - php: 7.3 + php: 8.0 env: DEPS='lowest' SYMFONY_DEPRECATIONS_HELPER='max[self]=2&max[direct]=2&max[indirect]=382' - - php: 8.1 + php: 8.2 env: DEPS='unmodified' WITH_STATIC_ANALYSIS='yes' SYMFONY_DEPRECATIONS_HELPER='max[indirect]=1' - stage: test - php: 7.3 - env: SYMFONY_VERSION='4.4.*' SYMFONY_DEPRECATIONS_HELPER='max[indirect]=1' - - - php: 7.4 - env: SYMFONY_VERSION='5.3.*' SYMFONY_DEPRECATIONS_HELPER='max[indirect]=1' - - php: 8.0 env: SYMFONY_VERSION='5.4.*' SYMFONY_DEPRECATIONS_HELPER='max[indirect]=1' - @@ -28,9 +22,12 @@ jobs: env: SYMFONY_VERSION='6.0.*' SYMFONY_DEPRECATIONS_HELPER='max[indirect]=1' - php: 8.1 - env: SYMFONY_VERSION='6.1.*' MIN_STABILITY='dev' SYMFONY_DEPRECATIONS_HELPER='max[indirect]=1' + env: SYMFONY_VERSION='6.1.*' SYMFONY_DEPRECATIONS_HELPER='max[indirect]=1' + - + php: 8.2 + env: SYMFONY_VERSION='6.2.*' SYMFONY_DEPRECATIONS_HELPER='max[indirect]=1' allow_failures: - - env: SYMFONY_VERSION='6.1.*' MIN_STABILITY='dev' SYMFONY_DEPRECATIONS_HELPER='max[indirect]=1' + - env: SYMFONY_VERSION='6.3.*' MIN_STABILITY='dev' SYMFONY_DEPRECATIONS_HELPER='max[indirect]=1' fast_finish: true services: diff --git a/CHANGELOG.md b/CHANGELOG.md index 6129952..27e2bb9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,14 @@ # Changelog +## [2.0.0] – 2022-xx + +- added strong php types +- dropped support for Php 7 +- dropped support for Symfony 5.3 +- drop support of doctrine/persistence v2 + +[2.0.0]: https://github.com/craue/CraueGeoBundle/compare/1.9.0...2.0.0 + ## [1.9.0] – 2022-01-24 - added support for PHP 8.0 diff --git a/Doctrine/Fixtures/GeonamesPostalCodeData.php b/Doctrine/Fixtures/GeonamesPostalCodeData.php index e77a39e..adf54f5 100644 --- a/Doctrine/Fixtures/GeonamesPostalCodeData.php +++ b/Doctrine/Fixtures/GeonamesPostalCodeData.php @@ -4,113 +4,29 @@ use Craue\GeoBundle\Entity\GeoPostalCode; use Doctrine\Common\DataFixtures\FixtureInterface; -use Doctrine\Common\Persistence\ObjectManager as LegacyObjectManager; -use Doctrine\Common\Persistence\ObjectRepository as LegacyObjectRepository; use Doctrine\Persistence\ObjectManager; use Doctrine\Persistence\ObjectRepository; -/** - * @internal - */ -abstract class BaseGeonamesPostalCodeData implements FixtureInterface { - - protected int $batchSize = 1000; - - // TODO remove as soon as doctrine/persistence >= 2.0 is required - final protected function _getRepository($manager) { - return $manager->getRepository(GeoPostalCode::class); - } - - // TODO remove as soon as doctrine/persistence >= 2.0 is required - final protected function _clearPostalCodesTable($manager): void - { - foreach ($this->_getRepository($manager)->findAll() as $entity) { - $manager->remove($entity); - } - $manager->flush(); - } - - // TODO remove as soon as doctrine/persistence >= 2.0 is required - final protected function _addEntries($manager, $filename): int - { - $repo = $this->_getRepository($manager); - - $entriesAdded = 0; - $currentBatchEntries = []; - - $fcontents = file($filename); - foreach ($fcontents as $i => $iValue) { - $line = trim($iValue); - $arr = explode("\t", $line); - - // skip if no lat/lng values - if (!array_key_exists(9, $arr) || !array_key_exists(10, $arr)) { - continue; - } - - $country = $arr[0]; - $postalCode = $arr[1]; - - // skip duplicate entries in current batch - if (in_array($country.'-'.$postalCode, $currentBatchEntries, true)) { - continue; - } - - // skip duplicate entries already persisted - if ($repo->findOneBy(['country' => $country, 'postalCode' => $postalCode]) !== null) { - continue; - } - - $entity = new GeoPostalCode(); - $entity->setCountry($country); - $entity->setPostalCode($postalCode); - $entity->setLat((float) $arr[9]); - $entity->setLng((float) $arr[10]); - $manager->persist($entity); - - ++$entriesAdded; - $currentBatchEntries[] = $country.'-'.$postalCode; - - if ((($i + 1) % $this->batchSize) === 0) { - $manager->flush(); - $manager->clear(); - $currentBatchEntries = []; - echo '.'; // progress indicator - } - } - - $manager->flush(); // Flush for the last batch, which doesn't reach the batch size in most cases. (fixes #2) - - echo ' ', $entriesAdded, "\n"; - - return $entriesAdded; - } - -} - -// TODO revert to one clean class definition as soon as doctrine/persistence >= 2.0 is required -if (interface_exists(ObjectManager::class)) { /** * @author Christian Raue * @copyright 2011-2022 Christian Raue * @license http://opensource.org/licenses/mit-license.php MIT License */ - abstract class GeonamesPostalCodeData extends BaseGeonamesPostalCodeData { - /** - * @param ObjectManager $manager - * @return ObjectRepository - */ + abstract class GeonamesPostalCodeData implements FixtureInterface { + + protected int $batchSize = 1000; + protected function getRepository(ObjectManager $manager): ObjectRepository { - return $this->_getRepository($manager); + return $manager->getRepository(GeoPostalCode::class); } - /** - * @param ObjectManager $manager - */ protected function clearPostalCodesTable(ObjectManager $manager): void { - $this->_clearPostalCodesTable($manager); + foreach ($this->getRepository($manager)->findAll() as $entity) { + $manager->remove($entity); + } + $manager->flush(); } /** @@ -118,39 +34,58 @@ protected function clearPostalCodesTable(ObjectManager $manager): void */ protected function addEntries(ObjectManager $manager, string $filename): int { - return $this->_addEntries($manager, $filename); - } - } -} else { - /** - * @author Christian Raue - * @copyright 2011-2022 Christian Raue - * @license http://opensource.org/licenses/mit-license.php MIT License - */ - abstract class GeonamesPostalCodeData extends BaseGeonamesPostalCodeData { - /** - * @param LegacyObjectManager $manager - * @return LegacyObjectRepository - */ - protected function getRepository(LegacyObjectManager $manager): LegacyObjectRepository - { - return $this->_getRepository($manager); - } + $repo = $this->getRepository($manager); + + $entriesAdded = 0; + $currentBatchEntries = []; + + $fcontents = file($filename); + foreach ($fcontents as $i => $iValue) { + $line = trim($iValue); + $arr = explode("\t", $line); + + // skip if no lat/lng values + if (!array_key_exists(9, $arr) || !array_key_exists(10, $arr)) { + continue; + } + + $country = $arr[0]; + $postalCode = $arr[1]; + + // skip duplicate entries in current batch + if (in_array($country.'-'.$postalCode, $currentBatchEntries, true)) { + continue; + } + + // skip duplicate entries already persisted + if ($repo->findOneBy(['country' => $country, 'postalCode' => $postalCode]) !== null) { + continue; + } + + $entity = new GeoPostalCode(); + $entity->setCountry($country); + $entity->setPostalCode($postalCode); + $entity->setLat((float) $arr[9]); + $entity->setLng((float) $arr[10]); + $manager->persist($entity); + + ++$entriesAdded; + $currentBatchEntries[] = $country.'-'.$postalCode; + + if ((($i + 1) % $this->batchSize) === 0) { + $manager->flush(); + $manager->clear(); + $currentBatchEntries = []; + echo '.'; // progress indicator + } + } - /** - * @param LegacyObjectManager $manager - */ - protected function clearPostalCodesTable(LegacyObjectManager $manager): void - { - $this->_clearPostalCodesTable($manager); - } + $manager->flush(); // Flush for the last batch, which doesn't reach the batch size in most cases. (fixes #2) - /** - * @return int Number of entries actually added. - */ - protected function addEntries(LegacyObjectManager $manager, string $filename): int - { - return $this->_addEntries($manager, $filename); + echo ' ', $entriesAdded, "\n"; + + return $entriesAdded; } - } + + public function load(ObjectManager $manager): void {} } diff --git a/README.md b/README.md index 59cbd70..d4d7c82 100644 --- a/README.md +++ b/README.md @@ -33,19 +33,6 @@ return [ ]; ``` -Or, for Symfony 3.4: - -```php -// in app/AppKernel.php -public function registerBundles() { - $bundles = [ - // ... - new Craue\GeoBundle\CraueGeoBundle(), - ]; - // ... -} -``` - ## Prepare the table with geographical data needed for calculations The `GEO_DISTANCE_BY_POSTAL_CODE` function, if you'd like to use it, relies on some data which has to be added to your @@ -85,7 +72,7 @@ Create a fixture class (in a separate folder to be able to load only this one) w namespace MyCompany\MyBundle\Doctrine\Fixtures\CraueGeo; use Craue\GeoBundle\Doctrine\Fixtures\GeonamesPostalCodeData; -use Doctrine\Common\Persistence\ObjectManager; +use Doctrine\Persistence\ObjectManager; class MyGeonamesPostalCodeData extends GeonamesPostalCodeData { @@ -100,26 +87,13 @@ class MyGeonamesPostalCodeData extends GeonamesPostalCodeData { Now, backup your database! Don't blame anyone else for data loss if something goes wrong. Then import the fixture and remember to use the `--append` parameter. -Choose the following steps depending on the version of DoctrineFixturesBundle you're using. -
- DoctrineFixturesBundle < 3.0 - - Load the fixture(s) in the given folder. - - ```sh - # in a shell - php bin/console doctrine:fixtures:load --append --fixtures="src/MyCompany/MyBundle/Doctrine/Fixtures/CraueGeo" - ``` -
- -
- DoctrineFixturesBundle >= 3.1 + DoctrineFixturesBundle >= 3.3.2 1. a) You first need to register the fixture as a service with a group of your choice. ```yaml - # in app/config/config.yml + # in config/config.yml services: my_geonames_postal_code_data: class: MyCompany\MyBundle\Doctrine\Fixtures\CraueGeo\MyGeonamesPostalCodeData @@ -131,7 +105,7 @@ Choose the following steps depending on the version of DoctrineFixturesBundle yo 1. b) It's also possible to register all classes in a specific folder as services. ```yaml - # in app/config/config.yml + # in config/config.yml services: MyCompany\MyBundle\Doctrine\Fixtures\CraueGeo\: resource: '../../src/MyCompany/MyBundle/Doctrine/Fixtures/CraueGeo/*' @@ -221,7 +195,7 @@ $queryBuilder If you want to avoid registering the `GeoPostalCode` entity (and as a result, avoid creating the `craue_geo_postalcode` table) at all, add ```yaml -# in app/config/config.yml +# in config/config.yml craue_geo: enable_postal_code_entity: false ``` @@ -233,7 +207,7 @@ to your configuration. If you don't like the default names or need to avoid conflicts with other functions, you can set custom names: ```yaml -# in app/config/config.yml +# in config/config.yml craue_geo: functions: geo_distance: MY_VERY_OWN_GEO_DISTANCE_FUNCTION diff --git a/Tests/Doctrine/Fixtures/CraueGeo/PuertoRicoGeonamesPostalCodeData.php b/Tests/Doctrine/Fixtures/CraueGeo/PuertoRicoGeonamesPostalCodeData.php index c2a9699..87db52a 100644 --- a/Tests/Doctrine/Fixtures/CraueGeo/PuertoRicoGeonamesPostalCodeData.php +++ b/Tests/Doctrine/Fixtures/CraueGeo/PuertoRicoGeonamesPostalCodeData.php @@ -3,59 +3,25 @@ namespace Craue\GeoBundle\Tests\Doctrine\Fixtures\CraueGeo; use Craue\GeoBundle\Doctrine\Fixtures\GeonamesPostalCodeData; -use Doctrine\Common\Persistence\ObjectManager as LegacyObjectManager; use Doctrine\Persistence\ObjectManager; -/** - * @internal - */ -abstract class BasePuertoRicoGeonamesPostalCodeData extends GeonamesPostalCodeData { +class PuertoRicoGeonamesPostalCodeData extends GeonamesPostalCodeData { - // TODO update README with Doctrine\Persistence\ObjectManager type-hint as soon as doctrine/persistence >= 2.0 is required - final protected function _load($manager): void + /** + * {@inheritDoc} + */ + final public function load(ObjectManager $manager): void { - $this->clearPostalCodesTable($manager); + $this->clearPostalCodesTable($manager); - $zip = new \ZipArchive(); - $res = $zip->open(__DIR__.'/PR.zip'); - if ($res === true) { - $zip->extractTo(__DIR__); - $zip->close(); - $this->addEntries($manager, __DIR__.'/PR.txt'); - unlink(__DIR__.'/PR.txt'); - unlink(__DIR__.'/readme.txt'); - } - } - -} - -// TODO revert to one clean class definition as soon as doctrine/persistence >= 2.0 is required -if (interface_exists(ObjectManager::class)) { - /** - * @author Christian Raue - * @copyright 2011-2022 Christian Raue - * @license http://opensource.org/licenses/mit-license.php MIT License - */ - class PuertoRicoGeonamesPostalCodeData extends BasePuertoRicoGeonamesPostalCodeData { - /** - * {@inheritDoc} - */ - public function load(ObjectManager $manager): void { - $this->_load($manager); - } - } -} else { - /** - * @author Christian Raue - * @copyright 2011-2022 Christian Raue - * @license http://opensource.org/licenses/mit-license.php MIT License - */ - class PuertoRicoGeonamesPostalCodeData extends BasePuertoRicoGeonamesPostalCodeData { - /** - * {@inheritDoc} - */ - public function load(LegacyObjectManager $manager): void { - $this->_load($manager); - } - } + $zip = new \ZipArchive(); + $res = $zip->open(__DIR__.'/PR.zip'); + if ($res === true) { + $zip->extractTo(__DIR__); + $zip->close(); + $this->addEntries($manager, __DIR__.'/PR.txt'); + unlink(__DIR__.'/PR.txt'); + unlink(__DIR__.'/readme.txt'); + } + } } From 8b8d1db739867014ebe033d164d7ddc8a1ae5c97 Mon Sep 17 00:00:00 2001 From: Christopher Georg Date: Fri, 23 Dec 2022 11:18:29 +0100 Subject: [PATCH 03/10] feat: drop support oh php 7, use language level features of php 8m add strong types, drop support of doctrine/persistence v2 --- .travis.yml | 2 +- composer.json | 12 ++++++------ 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/.travis.yml b/.travis.yml index 45d4e2c..963f891 100644 --- a/.travis.yml +++ b/.travis.yml @@ -11,7 +11,7 @@ jobs: php: 8.0 env: DEPS='lowest' SYMFONY_DEPRECATIONS_HELPER='max[self]=2&max[direct]=2&max[indirect]=382' - - php: 8.2 + php: 8.1 env: DEPS='unmodified' WITH_STATIC_ANALYSIS='yes' SYMFONY_DEPRECATIONS_HELPER='max[indirect]=1' - stage: test diff --git a/composer.json b/composer.json index c098858..380faa4 100644 --- a/composer.json +++ b/composer.json @@ -19,10 +19,10 @@ "php": "^8", "doctrine/doctrine-bundle": "^2.7", "doctrine/orm": "^2.14", - "symfony/config": "~4.4|~5.4|^6", - "symfony/dependency-injection": "~4.4|~5.4|^6", - "symfony/framework-bundle": "~4.4|~5.4|^6", - "symfony/validator": "~4.4|~5.4|^6" + "symfony/config": "~4.4.20|~5.4|^6", + "symfony/dependency-injection": "~4.4.20|~5.4|^6", + "symfony/framework-bundle": "~4.4.20|~5.4|^6", + "symfony/validator": "~4.4.20|~5.4|^6" }, "require-dev": { "doctrine/annotations": "^1.14", @@ -35,9 +35,9 @@ "phpstan/phpstan-strict-rules": "^1.4", "phpstan/phpstan-symfony": "^1.2", "phpunit/phpunit": "^9.5", - "symfony/browser-kit": "~4.4|~5.4|^6", + "symfony/browser-kit": "~4.4.20|~5.4|^6", "symfony/phpunit-bridge": "^6", - "symfony/yaml": "~4.4|~5.4|^6", + "symfony/yaml": "~4.4.20|~5.4|^6", "ext-zip": "*" }, "suggest": { From e798c9f17713ff84c17481874c6a88c7e03b5413 Mon Sep 17 00:00:00 2001 From: Christopher Georg Date: Fri, 23 Dec 2022 11:52:48 +0100 Subject: [PATCH 04/10] feat: drop support oh php 7, use language level features of php 8m add strong types, drop support of doctrine/persistence v2 --- Tests/Doctrine/Fixtures/FixtureTest.php | 35 ------------------- .../Mysql/GeoDistanceByPostalCodeTest.php | 2 +- .../Doctrine/Query/Mysql/GeoDistanceTest.php | 6 ++-- Tests/config/config.yml | 1 + 4 files changed, 5 insertions(+), 39 deletions(-) diff --git a/Tests/Doctrine/Fixtures/FixtureTest.php b/Tests/Doctrine/Fixtures/FixtureTest.php index 91c2bfa..3167f38 100644 --- a/Tests/Doctrine/Fixtures/FixtureTest.php +++ b/Tests/Doctrine/Fixtures/FixtureTest.php @@ -42,42 +42,11 @@ public function testImportByUsingFixtureDirectly($platform, $config, $requiredEx $this->assertCount(177, $this->getRepo()->findAll()); } - /** - * @dataProvider getPlatformConfigs - */ - public function testImportByDoctrineFixturesBundle2Command($platform, $config, $requiredExtension): void - { - if (class_exists(SymfonyFixturesLoader::class)) { - $this->markTestSkipped('DoctrineFixturesBundle >= 3.0 does not allow loading fixtures from a directory anymore.'); - } - - $this->initClient($requiredExtension, ['environment' => $platform, 'config' => $config]); - - // [A] add some data which is meant to be removed by importing new data - $this->persistGeoPostalCode('DE', '14473', 52.392759, 13.065135); - - // [B] import new data by using a command to load the fixture - $application = new Application(static::$kernel); - $application->setAutoExit(false); - $output = self::executeCommand($application, 'doctrine:fixtures:load', ['--append' => null, '--fixtures' => 'Tests/Doctrine/Fixtures/CraueGeo']); - $this->assertEquals(sprintf(" > loading %s\n 177\n", PuertoRicoGeonamesPostalCodeData::class), $output); - - // [A] verify that old data has been removed - $this->assertCount(0, $this->getRepo()->findBy(['country' => 'DE'])); - - // [B] verify that new data was imported as expected - $this->assertCount(177, $this->getRepo()->findAll()); - } - /** * @dataProvider dataImportByDoctrineFixturesBundle3Command */ public function testImportByDoctrineFixturesBundle3Command($platform, $config, $requiredExtension): void { - if (!interface_exists(FixtureGroupInterface::class)) { - $this->markTestSkipped('DoctrineFixturesBundle < 3.1 does not support fixture groups.'); - } - $this->initClient($requiredExtension, ['environment' => 'fixtureAsAService_' . $platform, 'config' => $config]); // [A] add some data which is meant to be removed by importing new data @@ -108,10 +77,6 @@ public function dataImportByDoctrineFixturesBundle3Command(): array */ public function testImportByDoctrineFixturesBundle3CommandWithAutoRegistration($platform, $config, $requiredExtension): void { - if (!interface_exists(FixtureGroupInterface::class)) { - $this->markTestSkipped('DoctrineFixturesBundle < 3.1 does not support fixture groups.'); - } - $this->initClient($requiredExtension, ['environment' => 'fixtureAsAService_autoRegistration_' . $platform, 'config' => $config]); // [A] add some data which is meant to be removed by importing new data diff --git a/Tests/Doctrine/Query/Mysql/GeoDistanceByPostalCodeTest.php b/Tests/Doctrine/Query/Mysql/GeoDistanceByPostalCodeTest.php index a31f7b7..52e41e8 100644 --- a/Tests/Doctrine/Query/Mysql/GeoDistanceByPostalCodeTest.php +++ b/Tests/Doctrine/Query/Mysql/GeoDistanceByPostalCodeTest.php @@ -39,7 +39,7 @@ public function testDistance($platform, $config, $requiredExtension): void $this->assertCount(2, $result); $this->assertEquals(0, $result[0]['distance']); - $this->assertEquals(25.324980933453528, $result[1]['distance']); + $this->assertEquals(25.3249809334535, $result[1]['distance']); } /** diff --git a/Tests/Doctrine/Query/Mysql/GeoDistanceTest.php b/Tests/Doctrine/Query/Mysql/GeoDistanceTest.php index bd7dc4d..5614bee 100644 --- a/Tests/Doctrine/Query/Mysql/GeoDistanceTest.php +++ b/Tests/Doctrine/Query/Mysql/GeoDistanceTest.php @@ -57,9 +57,9 @@ public function dataGeoDistance(): array { return self::duplicateTestDataForEachPlatform([ [52.392759, 13.065135, 52.392759, 13.065135, 0], - [52.392759, 13.065135, 52.525011, 13.369438, 25.32498093345365], - [-43.5131367, 172.5990772, -43.8951617, 171.7203311, 82.42610380554926], - [-0.1865943, -78.4305382, 0.3516889, -78.1234253, 68.91091929958483], + [52.392759, 13.065135, 52.525011, 13.369438, 25.3249809334535], + [-43.5131367, 172.5990772, -43.8951617, 171.7203311, 82.4261038055489], + [-0.1865943, -78.4305382, 0.3516889, -78.1234253, 68.9109192995844], ]); } diff --git a/Tests/config/config.yml b/Tests/config/config.yml index 8ea6de0..53fd9b4 100644 --- a/Tests/config/config.yml +++ b/Tests/config/config.yml @@ -14,6 +14,7 @@ doctrine: framework: secret: whatever test: ~ + http_method_override: false # workaround for symfony/framework-bundle not loading its annotations config when doctrine/annotations is installed only as a dev dependency resulting in non-existent service "annotation_reader" imports: From ba7ba0402734a585ec6074ed9cc8386c2fe78cd2 Mon Sep 17 00:00:00 2001 From: Christopher Georg Date: Mon, 26 Jun 2023 21:18:46 +0200 Subject: [PATCH 05/10] feat: drop support of php 7, use language level features of php 8.1, add strong types, drop support of doctrine/persistence v2 --- .gitignore | 1 + Tests/Doctrine/Fixtures/FixtureTest.php | 2 +- .../Query/Mysql/CustomFunctionNameTest.php | 4 +-- .../Mysql/DisablePostalCodeEntityTest.php | 2 +- composer.json | 35 +++++++++---------- phpunit.xml.dist | 6 ++-- 6 files changed, 26 insertions(+), 24 deletions(-) diff --git a/.gitignore b/.gitignore index 8751a3b..9180854 100644 --- a/.gitignore +++ b/.gitignore @@ -2,3 +2,4 @@ /phpstan.neon /phpunit.xml /vendor +/var/cache diff --git a/Tests/Doctrine/Fixtures/FixtureTest.php b/Tests/Doctrine/Fixtures/FixtureTest.php index 3167f38..bbdf2b9 100644 --- a/Tests/Doctrine/Fixtures/FixtureTest.php +++ b/Tests/Doctrine/Fixtures/FixtureTest.php @@ -65,7 +65,7 @@ public function testImportByDoctrineFixturesBundle3Command($platform, $config, $ $this->assertCount(177, $this->getRepo()->findAll()); } - public function dataImportByDoctrineFixturesBundle3Command(): array + public static function dataImportByDoctrineFixturesBundle3Command(): array { return self::duplicateTestDataForEachPlatform([ [], diff --git a/Tests/Doctrine/Query/Mysql/CustomFunctionNameTest.php b/Tests/Doctrine/Query/Mysql/CustomFunctionNameTest.php index f5af54c..948b281 100644 --- a/Tests/Doctrine/Query/Mysql/CustomFunctionNameTest.php +++ b/Tests/Doctrine/Query/Mysql/CustomFunctionNameTest.php @@ -29,7 +29,7 @@ public function testCustomFunctionName($platform, $config, $requiredExtension): $this->getEntityManager()->getConfiguration()->getCustomNumericFunction('CRAUE_GEO_DISTANCE_BY_POSTAL_CODE')); } - public function dataCustomFunctionName(): array + public static function dataCustomFunctionName(): array { return self::duplicateTestDataForEachPlatform([ [], @@ -48,7 +48,7 @@ public function testOverrideFunction($platform, $config, $requiredExtension): vo $this->assertSame(GeoDistance::class, $this->getEntityManager()->getConfiguration()->getCustomNumericFunction('MY_GEO_DISTANCE')); } - public function dataOverrideFunction(): array + public static function dataOverrideFunction(): array { return self::duplicateTestDataForEachPlatform([ [], diff --git a/Tests/Doctrine/Query/Mysql/DisablePostalCodeEntityTest.php b/Tests/Doctrine/Query/Mysql/DisablePostalCodeEntityTest.php index 3fffcad..9a94f11 100644 --- a/Tests/Doctrine/Query/Mysql/DisablePostalCodeEntityTest.php +++ b/Tests/Doctrine/Query/Mysql/DisablePostalCodeEntityTest.php @@ -34,7 +34,7 @@ public function testDisablePostalCodeEntity($platform, $config, $requiredExtensi $this->getRepo(); } - public function dataDisablePostalCodeEntity(): array + public static function dataDisablePostalCodeEntity(): array { return self::duplicateTestDataForEachPlatform([ [], diff --git a/composer.json b/composer.json index 380faa4..9dc28a9 100644 --- a/composer.json +++ b/composer.json @@ -16,28 +16,27 @@ } ], "require": { - "php": "^8", - "doctrine/doctrine-bundle": "^2.7", - "doctrine/orm": "^2.14", - "symfony/config": "~4.4.20|~5.4|^6", - "symfony/dependency-injection": "~4.4.20|~5.4|^6", - "symfony/framework-bundle": "~4.4.20|~5.4|^6", - "symfony/validator": "~4.4.20|~5.4|^6" + "php": "^8.1", + "doctrine/doctrine-bundle": "^2.9", + "doctrine/orm": "^2.15", + "symfony/config": "^5.4 | ^6.2", + "symfony/dependency-injection": "^5.4 | ^6.2", + "symfony/framework-bundle": "^5.4 | ^6.2", + "symfony/validator": "^5.4 | ^6.2" }, "require-dev": { - "doctrine/annotations": "^1.14", "doctrine/data-fixtures": "^1.6", - "doctrine/dbal": "^2.13|^3.5", + "doctrine/dbal": "^2.13.9|^3.6", "doctrine/doctrine-fixtures-bundle": "^3.4", - "phpstan/extension-installer": "^1.2", - "phpstan/phpstan": "^1.9", + "phpstan/extension-installer": "^1.3", + "phpstan/phpstan": "^1.10", "phpstan/phpstan-deprecation-rules": "^1.1", - "phpstan/phpstan-strict-rules": "^1.4", - "phpstan/phpstan-symfony": "^1.2", - "phpunit/phpunit": "^9.5", - "symfony/browser-kit": "~4.4.20|~5.4|^6", - "symfony/phpunit-bridge": "^6", - "symfony/yaml": "~4.4.20|~5.4|^6", + "phpstan/phpstan-strict-rules": "^1.5", + "phpstan/phpstan-symfony": "^1.3", + "phpunit/phpunit": "^10.2", + "symfony/browser-kit": "^5.4 | ^6.2", + "symfony/phpunit-bridge": "^6.2", + "symfony/yaml": "^5.4 | ^6.2", "ext-zip": "*" }, "suggest": { @@ -57,7 +56,7 @@ "dev-master": "1.9.x-dev" }, "symfony": { - "require": "~4.4|~5.4|^6" + "require": "^5.4 | ^6.2" } }, "config": { diff --git a/phpunit.xml.dist b/phpunit.xml.dist index c3ba169..dddfd0b 100644 --- a/phpunit.xml.dist +++ b/phpunit.xml.dist @@ -2,16 +2,17 @@ + - Tests + Tests + + From 4fcc467120cef84a6a845b2808263aa75ab630a1 Mon Sep 17 00:00:00 2001 From: Christopher Georg Date: Mon, 26 Jun 2023 21:41:30 +0200 Subject: [PATCH 06/10] feat: drop support of php 7, use language level features of php 8.1, add strong types, drop support of doctrine/persistence v2 --- .github/workflows/ci.yaml | 66 +++++++++++++++++++++++++++++ .travis.yml | 74 --------------------------------- .travis_install_dependencies.sh | 31 -------------- composer.json | 1 - 4 files changed, 66 insertions(+), 106 deletions(-) create mode 100644 .github/workflows/ci.yaml delete mode 100644 .travis.yml delete mode 100644 .travis_install_dependencies.sh diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml new file mode 100644 index 0000000..6c76baa --- /dev/null +++ b/.github/workflows/ci.yaml @@ -0,0 +1,66 @@ +# .github/workflows/ci.yaml +name: CI + +on: ["push", "pull_request"] + +jobs: + tests: + runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + php: ['8.2'] + stability: [ prefer-stable ] + symfony-version: ['6.3.*'] + include: + - php: '8.1' + symfony-version: 5.4.* + stability: prefer-lowest + - php: '8.1' + symfony-version: 5.4.* + stability: prefer-stable + - php: '8.1' + symfony-version: 6.3.* + stability: prefer-stable + - php: '8.2' + symfony-version: 6.3.* + stability: prefer-stable + + env: + DB_DATABASE: test + DB_USER: root + DB_PASSWORD: root + + name: PHP ${{ matrix.php }} - ${{ matrix.symfony-version }} - ${{ matrix.stability }} + steps: + - name: Set up MySQL + run: | + sudo systemctl start mysql + mysql -e 'CREATE DATABASE ${{ env.DB_DATABASE }};' -u${{ env.DB_USER }} -p${{ env.DB_PASSWORD }} + + # basically git clone + - uses: actions/checkout@v3 + + - name: Cache dependencies + uses: actions/cache@v3 + with: + path: ~/.composer/cache/files + key: dependencies-php-${{ matrix.php }}-composer-${{ hashFiles('composer.json') }} + + # use PHP of specific version + - uses: shivammathur/setup-php@v2 + with: + php-version: ${{ matrix.php }} + extensions: pcov, pdo, pdo_pgsql + coverage: pcov + + - name: Install dependencies + env: + SYMFONY_REQUIRE: ${{ matrix.symfony-version }} + run: | + composer update --no-interaction --prefer-dist + + - name: Execute tests + env: + SYMFONY_DEPRECATIONS_HELPER: 'weak' + run: vendor/bin/phpunit diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index 963f891..0000000 --- a/.travis.yml +++ /dev/null @@ -1,74 +0,0 @@ -language: php -dist: bionic # https://docs.travis-ci.com/user/reference/overview/#which-one-do-i-use - -stages: - - smoke test 🕵️ - - test - -jobs: - include: - - stage: smoke test 🕵️ - php: 8.0 - env: DEPS='lowest' SYMFONY_DEPRECATIONS_HELPER='max[self]=2&max[direct]=2&max[indirect]=382' - - - php: 8.1 - env: DEPS='unmodified' WITH_STATIC_ANALYSIS='yes' SYMFONY_DEPRECATIONS_HELPER='max[indirect]=1' - - - stage: test - php: 8.0 - env: SYMFONY_VERSION='5.4.*' SYMFONY_DEPRECATIONS_HELPER='max[indirect]=1' - - - php: 8.0 - env: SYMFONY_VERSION='6.0.*' SYMFONY_DEPRECATIONS_HELPER='max[indirect]=1' - - - php: 8.1 - env: SYMFONY_VERSION='6.1.*' SYMFONY_DEPRECATIONS_HELPER='max[indirect]=1' - - - php: 8.2 - env: SYMFONY_VERSION='6.2.*' SYMFONY_DEPRECATIONS_HELPER='max[indirect]=1' - allow_failures: - - env: SYMFONY_VERSION='6.3.*' MIN_STABILITY='dev' SYMFONY_DEPRECATIONS_HELPER='max[indirect]=1' - fast_finish: true - -services: - - mysql - - postgresql - -install: - # set unlimited memory_limit - - INI_FILE=~/.phpenv/versions/$(phpenv version-name)/etc/conf.d/travis.ini - - echo "memory_limit = -1" >> "${INI_FILE}" - # disable Xdebug for better Composer performance - - if php -v | grep -q 'Xdebug'; then phpenv config-rm xdebug.ini; fi; - # install dependencies using Composer - - travis_wait bash .travis_install_dependencies.sh - # show installed dependencies - - composer show - -before_script: - # set up MySQL - - mysql -u root -e 'CREATE DATABASE IF NOT EXISTS test;' - - mysql -u root -e 'DROP USER "travis"@"localhost";' - - mysql -u root -e 'CREATE USER "travis"@"localhost" IDENTIFIED BY "";' - - mysql -u root -e 'GRANT ALL ON test.* TO "travis"@"localhost";' - - mysql -u root -e 'FLUSH PRIVILEGES;' - # set up PostgreSQL - - psql -c 'create database test;' -U postgres - -script: - # validate composer.json - - if [ -n "${WITH_STATIC_ANALYSIS:-}" ]; then composer validate --strict --no-check-lock; fi; - # run PHPStan - - if [ -n "${WITH_STATIC_ANALYSIS:-}" ]; then vendor/bin/phpstan analyse; fi; - # run PHPUnit - - vendor/bin/phpunit -v - -notifications: - email: - on_success: always - on_failure: always - -# cache Composer's package cache -cache: - directories: - - $HOME/.composer/cache/files diff --git a/.travis_install_dependencies.sh b/.travis_install_dependencies.sh deleted file mode 100644 index bd5ce37..0000000 --- a/.travis_install_dependencies.sh +++ /dev/null @@ -1,31 +0,0 @@ -#!/bin/bash - -set -euv - -export COMPOSER_NO_INTERACTION=1 -composer self-update - -# install Symfony Flex -composer require --no-progress --no-scripts --no-plugins symfony/flex - -case "${DEPS:-}" in - 'lowest') - COMPOSER_UPDATE_ARGS='--prefer-lowest' - ;; - 'unmodified') - # don't modify dependencies, install them as defined - ;; - *) - if [ -n "${MIN_STABILITY:-}" ]; then - composer config minimum-stability "${MIN_STABILITY}" - fi - - if [ -n "${SYMFONY_VERSION:-}" ]; then - composer config extra.symfony.require "${SYMFONY_VERSION}" - fi -esac - -composer update ${COMPOSER_UPDATE_ARGS:-} --with-all-dependencies - -# revert changes applied by Flex recipes -git reset --hard && git clean -df diff --git a/composer.json b/composer.json index 9dc28a9..9f13a87 100644 --- a/composer.json +++ b/composer.json @@ -35,7 +35,6 @@ "phpstan/phpstan-symfony": "^1.3", "phpunit/phpunit": "^10.2", "symfony/browser-kit": "^5.4 | ^6.2", - "symfony/phpunit-bridge": "^6.2", "symfony/yaml": "^5.4 | ^6.2", "ext-zip": "*" }, From 429c57164c11434085bab9787fc7b9fad5ef8bc9 Mon Sep 17 00:00:00 2001 From: Christopher Georg Date: Mon, 26 Jun 2023 21:43:51 +0200 Subject: [PATCH 07/10] feat: drop support of php 7, use language level features of php 8.1, add strong types, drop support of doctrine/persistence v2 --- .gitattributes | 2 -- Tests/config/config.yml | 2 +- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/.gitattributes b/.gitattributes index 0e1189d..b8c8656 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1,8 +1,6 @@ /Tests export-ignore /.gitattributes export-ignore /.gitignore export-ignore -/.travis_install_dependencies.sh export-ignore -/.travis.yml export-ignore /phpstan-config.neon export-ignore /phpstan.neon.dist export-ignore /phpunit.xml.dist export-ignore diff --git a/Tests/config/config.yml b/Tests/config/config.yml index 53fd9b4..d71aae3 100644 --- a/Tests/config/config.yml +++ b/Tests/config/config.yml @@ -5,7 +5,7 @@ doctrine: host: 127.0.0.1 port: ~ dbname: test - user: travis + user: root password: ~ orm: auto_generate_proxy_classes: '%kernel.debug%' From 3d91b44c284ed74598f2566cf3e2353f6cd6cdc2 Mon Sep 17 00:00:00 2001 From: Christopher Georg Date: Mon, 26 Jun 2023 21:59:37 +0200 Subject: [PATCH 08/10] feat: drop support of php 7, use language level features of php 8.1, add strong types, drop support of doctrine/persistence v2 --- .github/workflows/ci.yaml | 27 ++++++++++++++++++++++++++- Tests/IntegrationTestCase.php | 1 - 2 files changed, 26 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 6c76baa..d6c9b5c 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -26,6 +26,31 @@ jobs: symfony-version: 6.3.* stability: prefer-stable + # Docker Hub image that `postgres-job` executes in + container: node:latest + + # service containers to run with `postgres-job` + services: + # label used to access the service container + postgres: + # Docker Hub image + image: postgres:latest + # service environment variables + # `POSTGRES_HOST` is `postgres` + env: + POSTGRES_DB: test + POSTGRES_PASSWORD: root + POSTGRES_PORT: 5432 + POSTGRES_USER: root + ports: + - 5432:5432 + # set health checks to wait until postgres has started + options: >- + --health-cmd pg_isready + --health-interval 10s + --health-timeout 5s + --health-retries 5 + env: DB_DATABASE: test DB_USER: root @@ -51,7 +76,7 @@ jobs: - uses: shivammathur/setup-php@v2 with: php-version: ${{ matrix.php }} - extensions: pcov, pdo, pdo_pgsql + extensions: pcov, pdo, pdo_mysql, pdo_pgsql coverage: pcov - name: Install dependencies diff --git a/Tests/IntegrationTestCase.php b/Tests/IntegrationTestCase.php index 88b0151..04f229f 100644 --- a/Tests/IntegrationTestCase.php +++ b/Tests/IntegrationTestCase.php @@ -179,7 +179,6 @@ protected static function createKernel(array $options = []) : KernelInterface { * @param string|null $requiredExtension Required PHP extension. * @param array $options Options for creating the client. * @param bool $cleanDatabase If the database should be cleaned in case it already exists. - * @return AbstractBrowser */ protected function initClient(?string $requiredExtension, array $options = [], bool $cleanDatabase = true): AbstractBrowser { From 49fa83af021042fc5c64415ebdc2730e2ad84454 Mon Sep 17 00:00:00 2001 From: Christopher Georg Date: Mon, 26 Jun 2023 22:09:31 +0200 Subject: [PATCH 09/10] feat: drop support of php 7, use language level features of php 8.1, add strong types, drop support of doctrine/persistence v2 --- .github/workflows/ci.yaml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index d6c9b5c..a7b4992 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -36,8 +36,8 @@ jobs: # Docker Hub image image: postgres:latest # service environment variables - # `POSTGRES_HOST` is `postgres` env: + POSTGRES_HOST: 'localhost' POSTGRES_DB: test POSTGRES_PASSWORD: root POSTGRES_PORT: 5432 @@ -60,7 +60,8 @@ jobs: steps: - name: Set up MySQL run: | - sudo systemctl start mysql + #sudo systemctl start mysql + sudo /etc/init.d/mysql start mysql -e 'CREATE DATABASE ${{ env.DB_DATABASE }};' -u${{ env.DB_USER }} -p${{ env.DB_PASSWORD }} # basically git clone From 89fdeebec967e97de1fad3d70dfabccfc9addfe0 Mon Sep 17 00:00:00 2001 From: Christopher Georg Date: Mon, 26 Jun 2023 22:19:14 +0200 Subject: [PATCH 10/10] feat: drop support of php 7, use language level features of php 8.1, add strong types, drop support of doctrine/persistence v2 --- .github/workflows/ci.yaml | 27 +++++++++++++++++---------- 1 file changed, 17 insertions(+), 10 deletions(-) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index a7b4992..d9b37b9 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -31,7 +31,8 @@ jobs: # service containers to run with `postgres-job` services: - # label used to access the service container + + # https://docs.github.com/en/actions/using-containerized-services/creating-postgresql-service-containers postgres: # Docker Hub image image: postgres:latest @@ -51,18 +52,24 @@ jobs: --health-timeout 5s --health-retries 5 - env: - DB_DATABASE: test - DB_USER: root - DB_PASSWORD: root + # https://atlasgo.io/guides/testing/github-actions + mysql: + image: mysql:8.0.29 + env: + MYSQL_ROOT_PASSWORD: root + MYSQL_DATABASE: test + ports: + - "3306:3306" + options: >- + --health-cmd "mysqladmin ping -proot" + --health-interval 10s + --health-start-period 10s + --health-timeout 5s + --health-retries 10 + name: PHP ${{ matrix.php }} - ${{ matrix.symfony-version }} - ${{ matrix.stability }} steps: - - name: Set up MySQL - run: | - #sudo systemctl start mysql - sudo /etc/init.d/mysql start - mysql -e 'CREATE DATABASE ${{ env.DB_DATABASE }};' -u${{ env.DB_USER }} -p${{ env.DB_PASSWORD }} # basically git clone - uses: actions/checkout@v3