• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

nextras / orm / 13354993605

16 Feb 2025 12:29PM UTC coverage: 91.73% (-0.3%) from 92.021%
13354993605

push

github

web-flow
Merge pull request #732 from nextras/datetime-property-wrapper

Datetime property wrapper

94 of 112 new or added lines in 15 files covered. (83.93%)

1 existing line in 1 file now uncovered.

4115 of 4486 relevant lines covered (91.73%)

4.57 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

96.61
/src/Collection/Helpers/ArrayCollectionHelper.php
1
<?php declare(strict_types = 1);
2

3
namespace Nextras\Orm\Collection\Helpers;
4

5

6
use Closure;
7
use Nette\Utils\Arrays;
8
use Nextras\Orm\Collection\Aggregations\Aggregator;
9
use Nextras\Orm\Collection\Functions\CollectionFunction;
10
use Nextras\Orm\Collection\Functions\FetchPropertyFunction;
11
use Nextras\Orm\Collection\Functions\Result\ArrayExpressionResult;
12
use Nextras\Orm\Collection\ICollection;
13
use Nextras\Orm\Entity\IEntity;
14
use Nextras\Orm\Entity\Reflection\PropertyMetadata;
15
use Nextras\Orm\Exception\InvalidArgumentException;
16
use Nextras\Orm\Repository\IRepository;
17
use function array_map;
18
use function array_shift;
19
use function is_array;
20

21

22
class ArrayCollectionHelper
23
{
24
        /**
25
         * @param IRepository<IEntity> $repository
26
         */
27
        public function __construct(
5✔
28
                private readonly IRepository $repository,
29
        )
30
        {
31
        }
5✔
32

33

34
        /**
35
         * @param array<mixed> $expr
36
         * @param Aggregator<mixed>|null $aggregator
37
         * @return Closure(IEntity): ArrayExpressionResult
38
         */
39
        public function createFilter(array $expr, ?Aggregator $aggregator): Closure
40
        {
41
                $function = isset($expr[0]) ? array_shift($expr) : ICollection::AND;
5✔
42
                $customFunction = $this->repository->getCollectionFunction($function);
5✔
43
                return function (IEntity $entity) use ($customFunction, $expr, $aggregator) {
5✔
44
                        return $customFunction->processArrayExpression($this, $entity, $expr, $aggregator);
5✔
45
                };
5✔
46
        }
47

48

49
        /**
50
         * @param array<array<string, mixed>|list<mixed>> $expressions
51
         * @return Closure(IEntity, IEntity): int
52
         */
53
        public function createSorter(array $expressions): Closure
54
        {
55
                /** @var list<array{CollectionFunction, string, array<mixed>}> $parsedExpressions */
56
                $parsedExpressions = [];
5✔
57
                $fetchPropertyFunction = $this->repository->getCollectionFunction(FetchPropertyFunction::class);
5✔
58
                foreach ($expressions as $expression) {
5✔
59
                        if (is_array($expression[0])) {
5✔
60
                                if (!isset($expression[0][0])) {
5✔
61
                                        throw new InvalidArgumentException();
×
62
                                }
63
                                $function = array_shift($expression[0]);
5✔
64
                                $collectionFunction = $this->repository->getCollectionFunction($function);
5✔
65
                                $parsedExpressions[] = [$collectionFunction, $expression[1], $expression[0]];
5✔
66
                        } else {
67
                                $parsedExpressions[] = [$fetchPropertyFunction, $expression[1], [$expression[0]]];
5✔
68
                        }
69
                }
70

71
                return function ($a, $b) use ($parsedExpressions): int {
5✔
72
                        foreach ($parsedExpressions as [$function, $ordering, $functionArgs]) {
5✔
73
                                /** @var CollectionFunction $function */
74
                                $_aResult = $function->processArrayExpression($this, $a, $functionArgs);
5✔
75
                                $_bResult = $function->processArrayExpression($this, $b, $functionArgs);
5✔
76

77
                                $_a = $_aResult->value;
5✔
78
                                $_b = $_bResult->value;
5✔
79

80
                                $descReverse = ($ordering === ICollection::ASC || $ordering === ICollection::ASC_NULLS_FIRST || $ordering === ICollection::ASC_NULLS_LAST) ? 1 : -1;
5✔
81
                                $comparator = $_aResult->propertyMetadata?->getPropertyComparator();
5✔
82
                                if ($_a === null || $_b === null) {
5✔
83
                                        $nullsFirst = $ordering === ICollection::ASC_NULLS_FIRST || $ordering === ICollection::DESC_NULLS_FIRST ? 1 : -1;
5✔
84
                                        $result = $_b === null ? $nullsFirst : -$nullsFirst;
5✔
85
                                } elseif ($comparator !== null) {
5✔
86
                                        $result = $comparator->compare($_a, $_b) * $descReverse;
5✔
87
                                } elseif (is_int($_a) || is_float($_a) || is_int($_b) || is_float($_b)) {
5✔
88
                                        $result = ($_a <=> $_b) * $descReverse;
5✔
89
                                } else {
90
                                        $result = ((string) $_a <=> (string) $_b) * $descReverse;
5✔
91
                                }
92

93
                                if ($result !== 0) {
5✔
94
                                        return $result;
5✔
95
                                }
96
                        }
97

UNCOV
98
                        return 0;
×
99
                };
5✔
100
        }
101

102

103
        /**
104
         * @param string|array<string, mixed>|list<mixed> $expression
105
         * @param Aggregator<mixed>|null $aggregator
106
         */
107
        public function getValue(
108
                IEntity $entity,
109
                array|string $expression,
110
                ?Aggregator $aggregator,
111
        ): ArrayExpressionResult
112
        {
113
                if (is_string($expression)) {
5✔
114
                        $function = FetchPropertyFunction::class;
5✔
115
                        $collectionFunction = $this->repository->getCollectionFunction($function);
5✔
116
                        $expression = [$expression];
5✔
117
                } else {
118
                        $function = isset($expression[0]) ? array_shift($expression) : ICollection::AND;
5✔
119
                        $collectionFunction = $this->repository->getCollectionFunction($function);
5✔
120
                }
121

122
                return $collectionFunction->processArrayExpression($this, $entity, $expression, $aggregator);
5✔
123
        }
124

125

126
        public function normalizeValue(
127
                mixed $value,
128
                PropertyMetadata $propertyMetadata,
129
                bool $checkMultiDimension = true,
130
        ): mixed
131
        {
132
                if ($checkMultiDimension && isset($propertyMetadata->types['array'])) {
5✔
133
                        if (is_array($value) && !is_array(reset($value))) {
5✔
134
                                $value = [$value];
5✔
135
                        }
136
                        if ($propertyMetadata->isPrimary) {
5✔
137
                                foreach ($value as $subValue) {
5✔
138
                                        if (!Arrays::isList($subValue)) {
5✔
139
                                                throw new InvalidArgumentException('Composite primary value has to be passed as a list, without array keys.');
5✔
140
                                        }
141
                                }
142
                        }
143
                }
144

145
                if ($propertyMetadata->wrapper !== null) {
5✔
146
                        $property = $propertyMetadata->getWrapperPrototype();
5✔
147
                        if (is_array($value)) {
5✔
148
                                $value = array_map(function ($subValue) use ($property) {
5✔
149
                                        return $property->convertToRawValue($subValue);
5✔
150
                                }, $value);
5✔
151
                        } else {
152
                                $value = $property->convertToRawValue($value);
5✔
153
                        }
154
                }
155

156
                return $value;
5✔
157
        }
158
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc