From 9919ea7a76a4bf1eaffe5e288ab82dcafeb775ce Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Sat, 13 Apr 2024 13:30:22 +0200 Subject: Merging upstream version 0.13.2. Signed-off-by: Daniel Baumann --- vendor/ipl/orm/src/Behavior/Binary.php | 5 ++- vendor/ipl/orm/src/Compat/FilterProcessor.php | 13 ++++++ vendor/ipl/orm/src/Hydrator.php | 64 ++++++++++++++++++++++----- 3 files changed, 71 insertions(+), 11 deletions(-) (limited to 'vendor/ipl/orm/src') diff --git a/vendor/ipl/orm/src/Behavior/Binary.php b/vendor/ipl/orm/src/Behavior/Binary.php index c43082a..602c9c7 100644 --- a/vendor/ipl/orm/src/Behavior/Binary.php +++ b/vendor/ipl/orm/src/Behavior/Binary.php @@ -29,7 +29,10 @@ class Binary extends PropertyBehavior implements QueryAwareBehavior, RewriteFilt if ($value !== null) { if (is_resource($value)) { - return stream_get_contents($value); + $content = stream_get_contents($value); + rewind($value); + + return $content; } return $value; diff --git a/vendor/ipl/orm/src/Compat/FilterProcessor.php b/vendor/ipl/orm/src/Compat/FilterProcessor.php index 7956898..361aabb 100644 --- a/vendor/ipl/orm/src/Compat/FilterProcessor.php +++ b/vendor/ipl/orm/src/Compat/FilterProcessor.php @@ -139,6 +139,13 @@ class FilterProcessor extends \ipl\Sql\Compat\FilterProcessor if (! $behaviorsApplied) { $rewrittenFilter = $subjectBehaviors->rewriteCondition($filter, $path . '.'); if ($rewrittenFilter !== null) { + if ( + $rewrittenFilter instanceof MetaDataProvider + && $rewrittenFilter->metaData()->get('forceResolved', false) + ) { + return $rewrittenFilter; + } + return $this->requireAndResolveFilterColumns($rewrittenFilter, $query, $forceOptimization) ?: $rewrittenFilter; } @@ -328,6 +335,12 @@ class FilterProcessor extends \ipl\Sql\Compat\FilterProcessor $subQuerySelect->having(["COUNT(DISTINCT $targetKeys) >= ?" => $count]); $subQuerySelect->groupBy(array_values($subQuerySelect->getColumns())); + + if ($negate) { + $subQuerySelect->where(array_map(function ($k) { + return $k . ' IS NOT NULL'; + }, array_values($subQuerySelect->getColumns()))); + } } // TODO: Qualification is only necessary since the `In` and `NotIn` conditions are ignored by diff --git a/vendor/ipl/orm/src/Hydrator.php b/vendor/ipl/orm/src/Hydrator.php index e3cd23d..63b3ff2 100644 --- a/vendor/ipl/orm/src/Hydrator.php +++ b/vendor/ipl/orm/src/Hydrator.php @@ -13,6 +13,9 @@ class Hydrator /** @var array Additional hydration rules for the model's relations */ protected $hydrators = []; + /** @var array> Map of columns to referencing paths */ + protected $columnToTargetMap = []; + /** @var Query The query the hydration rules are for */ protected $query; @@ -70,11 +73,31 @@ class Hydrator } } + $this->updateColumnToTargetMap($path, $columnToPropertyMap); $this->hydrators[$path] = [$target, $relation, $columnToPropertyMap, $defaults]; return $this; } + /** + * Update which columns the given path is referencing + * + * @param string $path + * @param array $columnToPropertyMap + * + * @return void + */ + protected function updateColumnToTargetMap(string $path, array $columnToPropertyMap): void + { + foreach ($columnToPropertyMap as $qualifiedColumnPath => $_) { + if (isset($this->columnToTargetMap[$qualifiedColumnPath])) { + $this->columnToTargetMap[$qualifiedColumnPath][$path] = true; + } else { + $this->columnToTargetMap[$qualifiedColumnPath] = [$path => true]; + } + } + } + /** * Hydrate the given raw database rows into the specified model * @@ -86,6 +109,7 @@ class Hydrator public function hydrate(array $data, Model $model) { $defaultsToApply = []; + $columnToTargetMap = $this->columnToTargetMap; foreach ($this->hydrators as $path => $vars) { list($target, $relation, $columnToPropertyMap, $defaults) = $vars; @@ -120,33 +144,44 @@ class Hydrator } } - $subject->setProperties($this->extractAndMap($data, $columnToPropertyMap)); + $subject->setProperties($this->extractAndMap($data, $columnToPropertyMap, $path, $columnToTargetMap)); $this->query->getResolver()->getBehaviors($target)->retrieve($subject); $defaultsToApply[] = [$subject, $defaults]; } // If there are any columns left, propagate them to the targeted relation if possible, to the base otherwise foreach ($data as $column => $value) { + if (($aliasPrefix = $this->query->getResolver()->getAliasPrefix())) { + $column = substr($column, strlen($aliasPrefix)); + } + $columnName = $column; $steps = explode('_', $column); $baseTable = array_shift($steps); + while (! empty($steps) && $baseTable !== $model->getTableAlias()) { + $baseTable .= '_' . array_shift($steps); + } $subject = $model; $target = $this->query->getModel(); $stepsTaken = []; - foreach ($steps as $step) { + for ($i = 0; $i < count($steps); $i++) { + $step = $steps[$i]; $stepsTaken[] = $step; $relationPath = "$baseTable." . implode('.', $stepsTaken); try { $relation = $this->query->getResolver()->resolveRelation($relationPath); - } catch (InvalidArgumentException $_) { - // The base table is missing, which means the alias hasn't been qualified and is custom defined - break; } catch (InvalidRelationException $_) { - array_pop($stepsTaken); - $columnName = implode('_', array_slice($steps, count($stepsTaken))); - break; + if (isset($steps[$i + 1])) { + $steps[$i + 1] = $step . '_' . $steps[$i + 1]; + array_pop($stepsTaken); + continue; + } else { + array_pop($stepsTaken); + $columnName = implode('_', array_slice($steps, $i)); + break; + } } if (! $subject->hasProperty($step)) { @@ -181,15 +216,24 @@ class Hydrator * * @param array $data * @param array $columnToPropertyMap + * @param string $path + * @param array> $columnToTargetMap * * @return array */ - protected function extractAndMap(array &$data, array $columnToPropertyMap) + protected function extractAndMap(array &$data, array $columnToPropertyMap, string $path, array &$columnToTargetMap) { $extracted = []; foreach (array_intersect_key($columnToPropertyMap, $data) as $column => $property) { $extracted[$property] = $data[$column]; - unset($data[$column]); + + if (isset($columnToTargetMap[$column][$path])) { + unset($columnToTargetMap[$column][$path]); + if (empty($columnToTargetMap[$column])) { + // Only unset a column once it's really not required anymore + unset($data[$column], $columnToTargetMap[$column]); + } + } } return $extracted; -- cgit v1.2.3