From b6b4cf0d753788ab1d051a3fba2d7e42a0b9983c Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Ji=C5=99=C3=AD=20Pudil?= <me@jiripudil.cz>
Date: Fri, 24 Jan 2025 14:05:54 +0100
Subject: [PATCH] chore: freshen this package up

- bump PHP requirement to 8.2
- ensure compatibility with PHP 8.4
- update to PHPStan 2
---
 .gitlab-ci.yml                               | 26 ++++++++++----------
 composer.json                                | 22 ++++++++---------
 phpstan.neon                                 |  9 -------
 src/Conditions/Composite.php                 |  2 +-
 src/Conditions/IsIn.php                      |  2 +-
 src/Conditions/IsNotIn.php                   |  2 +-
 src/Conditions/IsNotNull.php                 |  2 +-
 src/Conditions/IsNull.php                    |  2 +-
 src/Conditions/functions.php                 |  6 ++---
 src/Database/Identifier.php                  |  2 +-
 src/Scaffolding/PostgresReflector.php        |  4 +--
 src/Scaffolding/PrimaryKeyImplementation.php |  2 +-
 src/Scaffolding/TableImplementation.php      |  2 +-
 src/Scaffolding/TablesDefinitions.php        | 14 +++++------
 src/TableManager.php                         | 18 +++++++-------
 src/Types/ArrayType.php                      |  2 +-
 src/Types/CompositeType.php                  | 11 +++++----
 src/functions.php                            |  2 +-
 18 files changed, 60 insertions(+), 70 deletions(-)

diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index 6e6519b..32afcc2 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -12,10 +12,6 @@ stages:
       - vendor/
     expire_in: 1 day
 
-install.php81:
-  extends: .install
-  image: grifart/php8.1-with-all-modules-and-various-tools
-
 install.php82:
   extends: .install
   image: grifart/php8.2-with-all-modules-and-various-tools
@@ -24,11 +20,15 @@ install.php83:
   extends: .install
   image: grifart/php8.3-with-all-modules-and-various-tools
 
+install.php84:
+  extends: .install
+  image: grifart/php8.4-with-all-modules-and-various-tools
+
 .tests:
   stage: test
   interruptible: true
   services:
-    - postgres:14-alpine
+    - postgres:16-alpine
   variables:
     POSTGRES_DB: tables
     POSTGRES_USER: postgres
@@ -39,12 +39,6 @@ install.php83:
   script:
     - composer run test
 
-tests.php81:
-  extends: .tests
-  image: grifart/php8.1-with-all-modules-and-various-tools
-  dependencies:
-    - install.php81
-
 tests.php82:
   extends: .tests
   image: grifart/php8.2-with-all-modules-and-various-tools
@@ -57,11 +51,17 @@ tests.php83:
   dependencies:
     - install.php83
 
+tests.php84:
+  extends: .tests
+  image: grifart/php8.4-with-all-modules-and-various-tools
+  dependencies:
+    - install.php84
+
 phpstan:
   stage: test
-  image: grifart/php8.3-with-all-modules-and-various-tools
+  image: grifart/php8.4-with-all-modules-and-various-tools
   interruptible: true
   dependencies:
-    - install.php83
+    - install.php84
   script:
     - composer run phpstan
diff --git a/composer.json b/composer.json
index 6f14188..43beb4f 100644
--- a/composer.json
+++ b/composer.json
@@ -22,22 +22,22 @@
 		"test": "tester -C tests"
 	},
 	"require": {
-		"php": "^8.1",
+		"php": "^8.2",
 		"dibi/dibi": "^4.0.2||^5.0",
 		"grifart/scaffolder": "^0.6.3",
-		"lstrojny/functional-php": "^1.17",
+		"jiripudil/phun": "^0.1.0",
 		"nette/utils": "^3.0.1||^4.0"
 	},
 	"require-dev": {
-		"brick/date-time": "^0.4.1",
-		"brick/math": "^0.11.0",
-		"grifart/phpstan-oneline": "^0.4.0",
-		"nette/bootstrap": "^3.1",
-		"nette/di": "^3.0",
-		"nette/tester": "^2.3",
-		"nikic/php-parser": "^4.13",
-		"phpstan/phpstan": "^1.0",
-		"ramsey/uuid": "^4.2"
+		"brick/date-time": "^0.7.0",
+		"brick/math": "^0.12.0",
+		"grifart/phpstan-oneline": "^0.5.0",
+		"nette/bootstrap": "^3.2",
+		"nette/di": "^3.2",
+		"nette/tester": "^2.5",
+		"nikic/php-parser": "^5.4",
+		"phpstan/phpstan": "^2.0",
+		"ramsey/uuid": "^4.7"
 	},
 	"suggest": {
 		"brick/date-time": "if you want to use date-time types",
diff --git a/phpstan.neon b/phpstan.neon
index 885431b..d974faf 100644
--- a/phpstan.neon
+++ b/phpstan.neon
@@ -11,12 +11,3 @@ parameters:
 
 	excludePaths:
 		- tests/DI/temp/*
-
-	ignoreErrors:
-		# null() / notNull() currently require type parameter so that it can be used in the return annotation.
-		# A better solution would be to use a type projection in the return type, but that's not currently supported in PHPStan.
-		# more info: https://gitlab.grifart.cz/grifart/tables/-/merge_requests/38#note_90571, https://github.com/phpstan/phpstan/issues/3290
-		-
-			message: "#^Template type ValueType of function Grifart\\\\Tables\\\\Conditions\\\\(null|notNull)\\(\\) is not referenced in a parameter\\.$#"
-			count: 2
-			path: src/Conditions/functions.php
diff --git a/src/Conditions/Composite.php b/src/Conditions/Composite.php
index 146bb63..1d6eeb0 100644
--- a/src/Conditions/Composite.php
+++ b/src/Conditions/Composite.php
@@ -5,7 +5,7 @@ declare(strict_types=1);
 namespace Grifart\Tables\Conditions;
 
 use Dibi\Expression as DibiExpression;
-use function Functional\map;
+use function Phun\map;
 
 final class Composite implements Condition
 {
diff --git a/src/Conditions/IsIn.php b/src/Conditions/IsIn.php
index 50c2db4..b9bb5ca 100644
--- a/src/Conditions/IsIn.php
+++ b/src/Conditions/IsIn.php
@@ -6,8 +6,8 @@ namespace Grifart\Tables\Conditions;
 
 use Dibi\Expression as DibiExpression;
 use Grifart\Tables\Expression;
-use function Functional\map;
 use function Grifart\Tables\Types\mapToDatabase;
+use function Phun\map;
 
 /**
  * @template ValueType
diff --git a/src/Conditions/IsNotIn.php b/src/Conditions/IsNotIn.php
index c9bb3f6..f2bdd34 100644
--- a/src/Conditions/IsNotIn.php
+++ b/src/Conditions/IsNotIn.php
@@ -6,8 +6,8 @@ namespace Grifart\Tables\Conditions;
 
 use Dibi\Expression as DibiExpression;
 use Grifart\Tables\Expression;
-use function Functional\map;
 use function Grifart\Tables\Types\mapToDatabase;
+use function Phun\map;
 
 /**
  * @template ValueType
diff --git a/src/Conditions/IsNotNull.php b/src/Conditions/IsNotNull.php
index 9496096..c1aac9d 100644
--- a/src/Conditions/IsNotNull.php
+++ b/src/Conditions/IsNotNull.php
@@ -10,7 +10,7 @@ use Grifart\Tables\Expression;
 final class IsNotNull implements Condition
 {
 	/**
-	 * @param Expression<mixed> $expression
+	 * @param Expression<*> $expression
 	 */
 	public function __construct(
 		private Expression $expression,
diff --git a/src/Conditions/IsNull.php b/src/Conditions/IsNull.php
index ed08268..e75992f 100644
--- a/src/Conditions/IsNull.php
+++ b/src/Conditions/IsNull.php
@@ -10,7 +10,7 @@ use Grifart\Tables\Expression;
 final class IsNull implements Condition
 {
 	/**
-	 * @param Expression<mixed> $expression
+	 * @param Expression<*> $expression
 	 */
 	public function __construct(
 		private Expression $expression,
diff --git a/src/Conditions/functions.php b/src/Conditions/functions.php
index 57f445b..8cfa714 100644
--- a/src/Conditions/functions.php
+++ b/src/Conditions/functions.php
@@ -94,8 +94,7 @@ function notIn(array $values): \Closure {
 }
 
 /**
- * @template ValueType
- * @return \Closure(Expression<ValueType>): IsNull
+ * @return \Closure(Expression<*>): IsNull
  */
 function null(): \Closure
 {
@@ -103,8 +102,7 @@ function null(): \Closure
 }
 
 /**
- * @template ValueType
- * @return \Closure(Expression<ValueType>): IsNotNull
+ * @return \Closure(Expression<*>): IsNotNull
  */
 function notNull(): \Closure
 {
diff --git a/src/Database/Identifier.php b/src/Database/Identifier.php
index 5cef9a3..b7b1aea 100644
--- a/src/Database/Identifier.php
+++ b/src/Database/Identifier.php
@@ -5,7 +5,7 @@ namespace Grifart\Tables\Database;
 
 use Dibi\Expression;
 use Dibi\Literal;
-use function Functional\map;
+use function Phun\map;
 
 final class Identifier
 {
diff --git a/src/Scaffolding/PostgresReflector.php b/src/Scaffolding/PostgresReflector.php
index 3c4ce66..5565d53 100644
--- a/src/Scaffolding/PostgresReflector.php
+++ b/src/Scaffolding/PostgresReflector.php
@@ -7,8 +7,8 @@ namespace Grifart\Tables\Scaffolding;
 use Dibi\Connection;
 use Grifart\Tables\ColumnMetadata;
 use Grifart\Tables\MissingPrimaryIndex;
-use function Functional\map;
-use function Functional\reindex;
+use function Phun\map;
+use function Phun\reindex;
 
 final class PostgresReflector
 {
diff --git a/src/Scaffolding/PrimaryKeyImplementation.php b/src/Scaffolding/PrimaryKeyImplementation.php
index 7f2a8b3..56c68de 100644
--- a/src/Scaffolding/PrimaryKeyImplementation.php
+++ b/src/Scaffolding/PrimaryKeyImplementation.php
@@ -13,7 +13,7 @@ use Grifart\Tables\Conditions\Condition;
 use Grifart\Tables\PrimaryKey;
 use Grifart\Tables\Table;
 use Nette\PhpGenerator\Literal;
-use function Functional\map;
+use function Phun\map;
 
 final class PrimaryKeyImplementation implements Capability
 {
diff --git a/src/Scaffolding/TableImplementation.php b/src/Scaffolding/TableImplementation.php
index bc5bd15..89192cd 100644
--- a/src/Scaffolding/TableImplementation.php
+++ b/src/Scaffolding/TableImplementation.php
@@ -27,8 +27,8 @@ use Grifart\Tables\Type;
 use Grifart\Tables\TypeResolver;
 use Nette\PhpGenerator as Code;
 use Nette\Utils\Paginator;
-use function Functional\map;
 use function Grifart\ClassScaffolder\Definition\Types\resolve;
+use function Phun\map;
 use function usort;
 
 final class TableImplementation implements Capability
diff --git a/src/Scaffolding/TablesDefinitions.php b/src/Scaffolding/TablesDefinitions.php
index ebd350c..0a5b629 100644
--- a/src/Scaffolding/TablesDefinitions.php
+++ b/src/Scaffolding/TablesDefinitions.php
@@ -11,14 +11,14 @@ use Grifart\Tables\Database\Identifier;
 use Grifart\Tables\Row;
 use Grifart\Tables\Type;
 use Grifart\Tables\TypeResolver;
-use function array_keys;
-use function Functional\map;
 use function Grifart\ClassScaffolder\Capabilities\constructorWithPromotedProperties;
 use function Grifart\ClassScaffolder\Capabilities\getters;
 use function Grifart\ClassScaffolder\Capabilities\implementedInterface;
 use function Grifart\ClassScaffolder\Capabilities\namedConstructor;
 use function Grifart\ClassScaffolder\Capabilities\privatizedConstructor;
 use function Grifart\ClassScaffolder\Definition\Types\nullable;
+use function Phun\map;
+use function Phun\mapWithKeys;
 
 final class TablesDefinitions
 {
@@ -41,17 +41,17 @@ final class TablesDefinitions
 			throw new \LogicException('No columns found for given configuration. Does referenced table exist?');
 		}
 
-		$columnResolvedTypes = map(
+		$columnResolvedTypes = mapWithKeys(
 			$columnMetadata,
-			function (ColumnMetadata $column) use ($schema, $table): Type {
+			function ($_, ColumnMetadata $column) use ($schema, $table): Type {
 				$location = new Identifier($schema, $table, $column->getName());
 				return $this->typeResolver->resolveType($column->getType(), $location);
 			},
 		);
 
-		$columnPhpTypes = map(
+		$columnPhpTypes = mapWithKeys(
 			$columnMetadata,
-			static function (ColumnMetadata $column) use ($columnResolvedTypes): PhpType {
+			static function ($_, ColumnMetadata $column) use ($columnResolvedTypes): PhpType {
 				$type = $columnResolvedTypes[$column->getName()];
 				$phpType = $type->getPhpType();
 				return $column->isNullable() ? nullable($phpType) : $phpType;
@@ -78,7 +78,7 @@ final class TablesDefinitions
 			->with(new ModificationsImplementation($tableClassName, $primaryKeyClassName, $columnMetadata));
 
 		$primaryKeyColumnNames = $this->pgReflector->retrievePrimaryKeyColumns($schema, $table);
-		$primaryKeyFields = map($primaryKeyColumnNames, static fn(string $name) => $columnPhpTypes[$name]);
+		$primaryKeyFields = mapWithKeys($primaryKeyColumnNames, static fn($_, string $name) => $columnPhpTypes[$name]);
 		$primaryKeyClass = (new ClassDefinition($primaryKeyClassName))
 			->withFields($primaryKeyFields)
 			->with(
diff --git a/src/TableManager.php b/src/TableManager.php
index 48ee27d..acbf929 100644
--- a/src/TableManager.php
+++ b/src/TableManager.php
@@ -11,7 +11,8 @@ use Grifart\Tables\Conditions\Condition;
 use Grifart\Tables\OrderBy\OrderBy;
 use Grifart\Tables\OrderBy\OrderByDirection;
 use Nette\Utils\Paginator;
-use function Functional\map;
+use function Phun\map;
+use function Phun\mapWithKeys;
 
 // todo: error handling
 // todo: mapping of exceptions
@@ -37,9 +38,9 @@ final class TableManager
 			$this->connection->query(
 				'INSERT',
 				'INTO %n.%n', $table::getSchema(), $table::getTableName(),
-				map(
+				mapWithKeys(
 					$changes->getModifications(),
-					static fn(mixed $value, string $columnName) => $value !== null ? $table->getTypeOf($columnName)->toDatabase($value) : null,
+					static fn(string $columnName, mixed $value) => $value !== null ? $table->getTypeOf($columnName)->toDatabase($value) : null,
 				),
 			);
 		} catch (UniqueConstraintViolationException $e) {
@@ -60,7 +61,6 @@ final class TableManager
 		$rows = $this->findBy($table, $primaryKey->getCondition($table));
 		if (\count($rows) === 1) {
 			$row = \reset($rows);
-			\assert($row instanceof Row, 'It cannot return false as there must be one element in array');
 			return $row;
 		}
 		\assert(\count($rows) === 0);
@@ -110,15 +110,15 @@ final class TableManager
 
 		$dibiRows = $result->fetchAll();
 
-		/** @var Row $rowClass */
+		/** @var class-string<Row> $rowClass */
 		$rowClass = $table::getRowClass();
 		$modelRows = [];
 		foreach ($dibiRows as $dibiRow) {
 			\assert($dibiRow instanceof \Dibi\Row);
 			$modelRows[] = $rowClass::reconstitute(
-				map(
+				mapWithKeys(
 					$dibiRow->toArray(),
-					static fn(mixed $value, string $columnName) => $value !== null ? $table->getTypeOf($columnName)->fromDatabase($value) : null,
+					static fn(string $columnName, mixed $value) => $value !== null ? $table->getTypeOf($columnName)->fromDatabase($value) : null,
 				),
 			);
 		}
@@ -150,9 +150,9 @@ final class TableManager
 		$this->connection->query(
 			'UPDATE %n.%n', $table::getSchema(), $table::getTableName(),
 			'SET %a',
-			map(
+			mapWithKeys(
 				$changes->getModifications(),
-				static fn(mixed $value, string $columnName) => $value !== null ? $table->getTypeOf($columnName)->toDatabase($value) : null,
+				static fn(string $columnName, mixed $value) => $value !== null ? $table->getTypeOf($columnName)->toDatabase($value) : null,
 			),
 			'WHERE %ex', $primaryKey->getCondition($table)->toSql()->getValues(),
 		);
diff --git a/src/Types/ArrayType.php b/src/Types/ArrayType.php
index a5cc3db..5248634 100644
--- a/src/Types/ArrayType.php
+++ b/src/Types/ArrayType.php
@@ -9,8 +9,8 @@ use Dibi\Literal;
 use Grifart\ClassScaffolder\Definition\Types\Type as PhpType;
 use Grifart\Tables\Database\ArrayType as DatabaseArrayType;
 use Grifart\Tables\Type;
-use function Functional\map;
 use function Grifart\ClassScaffolder\Definition\Types\listOf;
+use function Phun\map;
 
 /**
  * @template ItemType
diff --git a/src/Types/CompositeType.php b/src/Types/CompositeType.php
index eaf60c0..64c42f6 100644
--- a/src/Types/CompositeType.php
+++ b/src/Types/CompositeType.php
@@ -8,7 +8,8 @@ use Dibi\Expression;
 use Dibi\Literal;
 use Grifart\Tables\Database\DatabaseType;
 use Grifart\Tables\Type;
-use function Functional\map;
+use function Phun\map;
+use function Phun\mapWithKeys;
 
 /**
  * @template T
@@ -44,9 +45,9 @@ abstract class CompositeType implements Type
 	{
 		$args = [
 			new Literal('ROW('),
-			...map(
+			...mapWithKeys(
 				$value,
-				fn(mixed $item, int $index) => $item !== null ? $this->types[$index]->toDatabase($item) : new Literal('NULL'),
+				fn(int $index, mixed $item) => $item !== null ? $this->types[$index]->toDatabase($item) : new Literal('NULL'),
 			),
 			new Literal(')::'),
 			$this->getDatabaseType()->toSql(),
@@ -66,9 +67,9 @@ abstract class CompositeType implements Type
 		$result = $this->parseComposite($value);
 
 		\assert(\count($result) === \count($this->types));
-		return map(
+		return mapWithKeys(
 			$result,
-			fn($item, $index) => $item !== null ? $this->types[$index]->fromDatabase($item) : null,
+			fn($index, $item) => $item !== null ? $this->types[$index]->fromDatabase($item) : null,
 		);
 	}
 
diff --git a/src/functions.php b/src/functions.php
index 891dea6..5500ccf 100644
--- a/src/functions.php
+++ b/src/functions.php
@@ -5,7 +5,7 @@ declare(strict_types=1);
 namespace Grifart\Tables;
 
 use Dibi\Expression as DibiExpression;
-use function Functional\map;
+use function Phun\map;
 
 /**
  * @template ValueType
-- 
GitLab