From 98f5df6920e55c4e60b4e43f6c897fcda2440e3d Mon Sep 17 00:00:00 2001 From: Alessandro Lai Date: Fri, 12 Mar 2021 11:28:07 +0100 Subject: [PATCH 01/15] Require Psalm --- composer.json | 3 ++- psalm.xml | 15 +++++++++++++++ 2 files changed, 17 insertions(+), 1 deletion(-) create mode 100644 psalm.xml diff --git a/composer.json b/composer.json index 100c28c..9fe1d8d 100644 --- a/composer.json +++ b/composer.json @@ -28,6 +28,7 @@ "symfony/var-dumper": "^3.3", "symfony/debug": "^3.3", "mark-gerarts/phpstan-automapper-plus": "^0.1.0", - "phpunit/phpunit": "^7.0" + "phpunit/phpunit": "^7.0", + "vimeo/psalm": "^4.6" } } diff --git a/psalm.xml b/psalm.xml new file mode 100644 index 0000000..3e4e3d0 --- /dev/null +++ b/psalm.xml @@ -0,0 +1,15 @@ + + + + + + + + + From ad5e2e8e5dc916be444e416cf47b2f3baaa53389 Mon Sep 17 00:00:00 2001 From: Alessandro Lai Date: Fri, 12 Mar 2021 11:29:42 +0100 Subject: [PATCH 02/15] Add Psalm to CI --- .travis.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.travis.yml b/.travis.yml index 6920f64..6472116 100644 --- a/.travis.yml +++ b/.travis.yml @@ -6,3 +6,7 @@ php: - '7.4' install: - composer install +jobs: + include: + - name: Psalm + script: vendor/bin/psalm From f760225b476950d4a160bdc0e93ec71a02bacd88 Mon Sep 17 00:00:00 2001 From: Alessandro Lai Date: Fri, 12 Mar 2021 11:33:14 +0100 Subject: [PATCH 03/15] Add template annotation to MapperInterface --- src/MapperInterface.php | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/MapperInterface.php b/src/MapperInterface.php index 23a6df4..804911a 100644 --- a/src/MapperInterface.php +++ b/src/MapperInterface.php @@ -15,9 +15,11 @@ interface MapperInterface * Maps an object to an instance of class $to, provided a mapping is * configured. * + * @template T of object * @param array|object $source * The source object. * @param string $targetClass + * @psalm-param class-string $targetClass * The target classname. * @param array $context * An arbitrary array of values that will be passed to supporting @@ -26,6 +28,7 @@ interface MapperInterface * This is not explicitly required on the interface yet to preserve * backwards compatibility, but will be added in version 2.0. * @return mixed + * @psalm-return T * An instance of class $to. * @throws UnregisteredMappingException */ @@ -34,13 +37,16 @@ public function map($source, string $targetClass/**, array $context = [] */); /** * Maps properties of object $from to an existing object $to. * + * @template T of object * @param array|object $source * The source object. * @param object $destination + * @psalm-param T $destination * The target object. * @param array $context * See MapperInterface::map() * @return mixed + * @psalm-return T * $to, with properties copied from $from. * @throws UnregisteredMappingException */ From a96da698c92530ad852153aac59915232f66fd30 Mon Sep 17 00:00:00 2001 From: Alessandro Lai Date: Fri, 12 Mar 2021 11:44:20 +0100 Subject: [PATCH 04/15] Resolve some Psalm issues --- src/AutoMapper.php | 20 +++++++++---------- src/Configuration/Options.php | 5 +++-- .../DefaultMappingOperation.php | 1 + .../PropertyReaderInterface.php | 6 +++--- 4 files changed, 17 insertions(+), 15 deletions(-) diff --git a/src/AutoMapper.php b/src/AutoMapper.php index cbbfdfe..9462e47 100644 --- a/src/AutoMapper.php +++ b/src/AutoMapper.php @@ -51,7 +51,7 @@ public static function initialize(callable $configurator): AutoMapperInterface return $mapper; } - private function push($key, $value, &$context) + private function push($key, $value, &$context): void { if (!array_key_exists($key, $context)) { $stack = []; @@ -62,7 +62,7 @@ private function push($key, $value, &$context) $context[$key] = $stack; } - private function pop($key, &$context) + private function pop($key, &$context): void { array_pop($context[$key]); } @@ -70,7 +70,7 @@ private function pop($key, &$context) /** * @inheritdoc */ - public function map($source, string $destinationClass, array $context = []) + public function map($source, string $targetClass, array $context = []) { if ($source === null) { return null; @@ -85,11 +85,11 @@ public function map($source, string $destinationClass, array $context = []) } } - $context[self::DESTINATION_CLASS_CONTEXT] = $destinationClass; + $context[self::DESTINATION_CLASS_CONTEXT] = $targetClass; - $mapping = $this->getMapping($sourceClass, $destinationClass); + $mapping = $this->getMapping($sourceClass, $targetClass); if ($mapping->providesCustomMapper()) { - return $this->getCustomMapper($mapping)->map($source, $destinationClass); + return $this->getCustomMapper($mapping)->map($source, $targetClass); } if ($mapping->hasCustomConstructor()) { @@ -98,14 +98,14 @@ public function map($source, string $destinationClass, array $context = []) $this, $context ); - } elseif (interface_exists($destinationClass)) { + } elseif (interface_exists($targetClass)) { // If we're mapping to an interface a valid custom constructor has // to be provided. Otherwise we can't know what to do. $message = 'Mapping to an interface is not possible. Please ' . 'provide a concrete class or use mapToObject instead.'; throw new AutoMapperPlusException($message); } else { - $destinationObject = new $destinationClass; + $destinationObject = new $targetClass; } $context[self::DESTINATION_CONTEXT] = $destinationObject; @@ -126,7 +126,7 @@ public function map($source, string $destinationClass, array $context = []) */ public function mapMultiple( $sourceCollection, - string $destinationClass, + string $targetClass, array $context = [] ): array { @@ -138,7 +138,7 @@ public function mapMultiple( $mappedResults = []; foreach ($sourceCollection as $source) { - $mappedResults[] = $this->map($source, $destinationClass, $context); + $mappedResults[] = $this->map($source, $targetClass, $context); } return $mappedResults; diff --git a/src/Configuration/Options.php b/src/Configuration/Options.php index 5707201..ee40436 100644 --- a/src/Configuration/Options.php +++ b/src/Configuration/Options.php @@ -71,7 +71,8 @@ class Options private $useSubstitution = true; /** - * @var string[] + * @var bool[] + * @psalm-var array */ private $objectCrates = []; @@ -280,7 +281,7 @@ public function providesCustomMapper(): bool } /** - * @param string $className + * @param class-string $className */ public function registerObjectCrate(string $className): void { diff --git a/src/MappingOperation/DefaultMappingOperation.php b/src/MappingOperation/DefaultMappingOperation.php index 65eb568..eeed295 100644 --- a/src/MappingOperation/DefaultMappingOperation.php +++ b/src/MappingOperation/DefaultMappingOperation.php @@ -4,6 +4,7 @@ use AutoMapperPlus\Configuration\Options; use AutoMapperPlus\NameResolver\NameResolverInterface; +use AutoMapperPlus\PropertyAccessor\PropertyAccessorInterface; use AutoMapperPlus\PropertyAccessor\PropertyReaderInterface; use AutoMapperPlus\PropertyAccessor\PropertyWriterInterface; diff --git a/src/PropertyAccessor/PropertyReaderInterface.php b/src/PropertyAccessor/PropertyReaderInterface.php index b938404..3ea494e 100644 --- a/src/PropertyAccessor/PropertyReaderInterface.php +++ b/src/PropertyAccessor/PropertyReaderInterface.php @@ -10,14 +10,14 @@ interface PropertyReaderInterface { /** - * @param $object + * @param object|array $object * @param string $propertyName * @return bool */ public function hasProperty($object, string $propertyName): bool; /** - * @param $object + * @param object|array $object * @param string $propertyName * @return mixed */ @@ -26,7 +26,7 @@ public function getProperty($object, string $propertyName); /** * Returns a list of property names available on the object. * - * @param object $object + * @param object|array $object * @return string[] */ public function getPropertyNames($object): array; From 6d05f1f4f5def6d56eb30de748ad6bcecfc122f8 Mon Sep 17 00:00:00 2001 From: Alessandro Lai Date: Fri, 12 Mar 2021 11:45:08 +0100 Subject: [PATCH 05/15] Set Psalm baseline --- psalm.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/psalm.xml b/psalm.xml index 3e4e3d0..72b4005 100644 --- a/psalm.xml +++ b/psalm.xml @@ -5,6 +5,7 @@ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="https://getpsalm.org/schema/config" xsi:schemaLocation="https://getpsalm.org/schema/config vendor/vimeo/psalm/config.xsd" + errorBaseline="psalm-baseline.xml" > From 591e4888b5614c892470472b7d16cd1dcdc775ee Mon Sep 17 00:00:00 2001 From: Alessandro Lai Date: Fri, 12 Mar 2021 11:46:06 +0100 Subject: [PATCH 06/15] Add Psalm baseline --- psalm-baseline.xml | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) create mode 100644 psalm-baseline.xml diff --git a/psalm-baseline.xml b/psalm-baseline.xml new file mode 100644 index 0000000..d2bdf8e --- /dev/null +++ b/psalm-baseline.xml @@ -0,0 +1,26 @@ + + + + + mapToObject + + + + + map + mapMultiple + + + + + array + + + $array + + + $array + $array + + + From d125d1dba82e19a363ead7128e02b31555274cf6 Mon Sep 17 00:00:00 2001 From: Alessandro Lai Date: Fri, 12 Mar 2021 15:12:38 +0100 Subject: [PATCH 07/15] Move the param description for better IDE parsing --- src/MapperInterface.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/MapperInterface.php b/src/MapperInterface.php index 804911a..6c50ec8 100644 --- a/src/MapperInterface.php +++ b/src/MapperInterface.php @@ -19,8 +19,8 @@ interface MapperInterface * @param array|object $source * The source object. * @param string $targetClass - * @psalm-param class-string $targetClass * The target classname. + * @psalm-param class-string $targetClass * @param array $context * An arbitrary array of values that will be passed to supporting * mapping operations (e.g. MapFrom) to alter their behaviour based on @@ -41,8 +41,8 @@ public function map($source, string $targetClass/**, array $context = [] */); * @param array|object $source * The source object. * @param object $destination - * @psalm-param T $destination * The target object. + * @psalm-param T $destination * @param array $context * See MapperInterface::map() * @return mixed From 618dd6be32699a5be28b6fcbd4aefa22ae63fa81 Mon Sep 17 00:00:00 2001 From: Alessandro Lai Date: Thu, 13 Feb 2025 17:49:53 +0100 Subject: [PATCH 08/15] Move Psalm CI run into GHA --- .github/workflows/continuous-integration.yaml | 9 +++++++++ .travis.yml | 12 ------------ 2 files changed, 9 insertions(+), 12 deletions(-) delete mode 100644 .travis.yml diff --git a/.github/workflows/continuous-integration.yaml b/.github/workflows/continuous-integration.yaml index 08d55aa..3a3fa55 100644 --- a/.github/workflows/continuous-integration.yaml +++ b/.github/workflows/continuous-integration.yaml @@ -14,6 +14,8 @@ jobs: phpunit: '8.5' - php: '8.0' phpunit: '8.5' + - php: '8.1' + psalm: true - php: '8.1' phpunit: '8.5' steps: @@ -38,6 +40,13 @@ jobs: - name: Run test suite uses: php-actions/phpunit@v3 + if: ${{ matrix.phpunit != '' }} with: php_version: ${{ matrix.php }} version: ${{ matrix.phpunit }} + + - name: Run Psalm analysis + run: vendor/bin/psalm + if: ${{ matrix.psalm == true }} + with: + php_version: ${{ matrix.php }} diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index 6472116..0000000 --- a/.travis.yml +++ /dev/null @@ -1,12 +0,0 @@ -language: php -php: - - '7.1' - - '7.2' - - '7.3' - - '7.4' -install: - - composer install -jobs: - include: - - name: Psalm - script: vendor/bin/psalm From 2fe1c185710f698117db11dbe3afb026179189a9 Mon Sep 17 00:00:00 2001 From: Alessandro Lai Date: Thu, 13 Feb 2025 17:51:27 +0100 Subject: [PATCH 09/15] Ignore PHPUnit cache file --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 58fb006..d338484 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ +*.cache # Composer vendor/ composer.lock From fc0658d11895724c52932176e96d10df2745908d Mon Sep 17 00:00:00 2001 From: Alessandro Lai Date: Thu, 13 Feb 2025 17:52:12 +0100 Subject: [PATCH 10/15] Fix merge error --- src/AutoMapper.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/AutoMapper.php b/src/AutoMapper.php index e34339c..15824b6 100644 --- a/src/AutoMapper.php +++ b/src/AutoMapper.php @@ -91,7 +91,7 @@ public function map($source, string $targetClass, array $context = []) if ($mapping->providesCustomMapper()) { $customMapper = $this->getCustomMapper($mapping); - return $customMapper->map($source, $destinationClass, $context); + return $customMapper->map($source, $targetClass, $context); } if ($mapping->hasCustomConstructor()) { From d1fbc490101a77c5b754588640a4a4adcb3f09e3 Mon Sep 17 00:00:00 2001 From: Mark Gerarts Date: Wed, 24 Dec 2025 12:32:11 +0100 Subject: [PATCH 11/15] Resolve merge conflict --- .github/workflows/continuous-integration.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/continuous-integration.yaml b/.github/workflows/continuous-integration.yaml index 3a3fa55..5031d96 100644 --- a/.github/workflows/continuous-integration.yaml +++ b/.github/workflows/continuous-integration.yaml @@ -39,7 +39,7 @@ jobs: run: composer update --no-interaction --no-progress - name: Run test suite - uses: php-actions/phpunit@v3 + uses: php-actions/phpunit@v4 if: ${{ matrix.phpunit != '' }} with: php_version: ${{ matrix.php }} From 688e3e47edd8774cb7cbfdfc455d23811c6aefbb Mon Sep 17 00:00:00 2001 From: Mark Gerarts Date: Wed, 24 Dec 2025 12:36:49 +0100 Subject: [PATCH 12/15] Remove 'with' for run-action --- .github/workflows/continuous-integration.yaml | 2 -- 1 file changed, 2 deletions(-) diff --git a/.github/workflows/continuous-integration.yaml b/.github/workflows/continuous-integration.yaml index 5031d96..1bad45e 100644 --- a/.github/workflows/continuous-integration.yaml +++ b/.github/workflows/continuous-integration.yaml @@ -48,5 +48,3 @@ jobs: - name: Run Psalm analysis run: vendor/bin/psalm if: ${{ matrix.psalm == true }} - with: - php_version: ${{ matrix.php }} From 6dd0b7230efdaa9c95d26deb7b5cc8e2c778654f Mon Sep 17 00:00:00 2001 From: Mark Gerarts Date: Wed, 24 Dec 2025 12:47:31 +0100 Subject: [PATCH 13/15] Apply action updates --- .github/workflows/continuous-integration.yaml | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/.github/workflows/continuous-integration.yaml b/.github/workflows/continuous-integration.yaml index 1bad45e..84c56ed 100644 --- a/.github/workflows/continuous-integration.yaml +++ b/.github/workflows/continuous-integration.yaml @@ -6,20 +6,20 @@ on: jobs: phpunit: - runs-on: ubuntu-20.04 + runs-on: ubuntu-24.04 strategy: matrix: include: - - php: '7.4' - phpunit: '8.5' - - php: '8.0' - phpunit: '8.5' - php: '8.1' psalm: true - php: '8.1' phpunit: '8.5' + - php: '8.5' + psalm: true + - php: '8.5' + phpunit: '8.5' steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v6 - name: Install PHP uses: shivammathur/setup-php@v2 @@ -28,7 +28,7 @@ jobs: tools: 'composer:v2' - name: Cache Composer dependencies - uses: actions/cache@v2 + uses: actions/cache@v5 with: path: '~/.composer/cache' key: ${{ runner.os }}-php${{ matrix.php }}-phpunit${{ matrix.phpunit }}-symfony${{ matrix.symfony }}-${{ hashFiles('**/composer.json') }} From a39e44d442b307f82ebf4c4e2b3095a7cdd45aa4 Mon Sep 17 00:00:00 2001 From: Mark Gerarts Date: Wed, 24 Dec 2025 13:01:08 +0100 Subject: [PATCH 14/15] Suppress palm errors for now --- src/AutoMapper.php | 4 ++++ src/CustomMapper/CustomMapper.php | 4 ++++ src/MappingOperation/Implementations/MapToAnyOf.php | 5 +++++ src/PropertyAccessor/ArrayPropertyReader.php | 2 ++ 4 files changed, 15 insertions(+) diff --git a/src/AutoMapper.php b/src/AutoMapper.php index 15824b6..93a2d9c 100644 --- a/src/AutoMapper.php +++ b/src/AutoMapper.php @@ -69,6 +69,10 @@ private function pop($key, &$context): void /** * @inheritdoc + * + * @psalm-suppress TooManyArguments + * Psalm borks on the missing $context on the interface, which is there + * because of backwards compatibility. */ public function map($source, string $targetClass, array $context = []) { diff --git a/src/CustomMapper/CustomMapper.php b/src/CustomMapper/CustomMapper.php index e254b97..c8876d6 100644 --- a/src/CustomMapper/CustomMapper.php +++ b/src/CustomMapper/CustomMapper.php @@ -13,6 +13,10 @@ abstract class CustomMapper implements MapperInterface { /** * @inheritdoc + * + * @psalm-suppress TooManyArguments + * Psalm borks on the missing $context on the interface, which is there + * because of backwards compatibility. */ public function map($source, string $targetClass) { diff --git a/src/MappingOperation/Implementations/MapToAnyOf.php b/src/MappingOperation/Implementations/MapToAnyOf.php index 51ab1a7..b4c4b65 100644 --- a/src/MappingOperation/Implementations/MapToAnyOf.php +++ b/src/MappingOperation/Implementations/MapToAnyOf.php @@ -70,6 +70,11 @@ function ($value) use ($context) { ); } + /** + * @psalm-suppress TooManyArguments + * Psalm borks on the missing $context on the interface, which is there + * because of backwards compatibility. + */ private function mapSingle($item, $context) { $destinationClass = $this->getDestinationClass($item); diff --git a/src/PropertyAccessor/ArrayPropertyReader.php b/src/PropertyAccessor/ArrayPropertyReader.php index 71bdfa9..6622564 100644 --- a/src/PropertyAccessor/ArrayPropertyReader.php +++ b/src/PropertyAccessor/ArrayPropertyReader.php @@ -29,6 +29,8 @@ public function getProperty($array, string $propertyName) * @inheritdoc * * @param array $array + * + * @psalm-suppress ParamNameMismatch */ public function getPropertyNames($array): array { From 1f8ce69d54e9a9d99d595745df7f96be7100dd01 Mon Sep 17 00:00:00 2001 From: Mark Gerarts Date: Wed, 24 Dec 2025 14:14:49 +0100 Subject: [PATCH 15/15] Update dependencies --- .github/workflows/continuous-integration.yaml | 1 + composer.json | 14 +++++++++----- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/.github/workflows/continuous-integration.yaml b/.github/workflows/continuous-integration.yaml index 84c56ed..faeca00 100644 --- a/.github/workflows/continuous-integration.yaml +++ b/.github/workflows/continuous-integration.yaml @@ -48,3 +48,4 @@ jobs: - name: Run Psalm analysis run: vendor/bin/psalm if: ${{ matrix.psalm == true }} + continue-on-error: true diff --git a/composer.json b/composer.json index 3f53b1a..deb6741 100644 --- a/composer.json +++ b/composer.json @@ -3,7 +3,11 @@ "description": "An AutoMapper for PHP", "license": "MIT", "type": "library", - "keywords": ["automapper", "converter", "object-to-object"], + "keywords": [ + "automapper", + "converter", + "object-to-object" + ], "authors": [ { "name": "Mark Gerarts", @@ -12,7 +16,7 @@ ], "autoload": { "psr-4": { - "AutoMapperPlus\\": "src/" + "AutoMapperPlus\\": "src/" } }, "autoload-dev": { @@ -22,13 +26,13 @@ } }, "require": { - "php": ">=7.4.0" + "php": ">=8.1.0" }, "require-dev": { "symfony/var-dumper": "^3.3", "symfony/debug": "^3.3", "mark-gerarts/phpstan-automapper-plus": "^0.1.0", - "phpunit/phpunit": "^7.0|^8.0", - "vimeo/psalm": "^4.6" + "phpunit/phpunit": "^10.0|^11.0|12.0", + "vimeo/psalm": "^6.0" } }