Skip to content

Commit

Permalink
Improve
Browse files Browse the repository at this point in the history
  • Loading branch information
Tigrov committed Oct 8, 2024
1 parent 3c5039b commit c0e41b7
Show file tree
Hide file tree
Showing 3 changed files with 50 additions and 27 deletions.
59 changes: 41 additions & 18 deletions src/Expression/StructuredExpression.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@

use function array_key_exists;
use function array_keys;
use function is_iterable;
use function get_object_vars;
use function is_object;
use function iterator_to_array;

/**
Expand All @@ -28,11 +29,22 @@
final class StructuredExpression implements ExpressionInterface
{
/**
* @param ColumnSchemaInterface[] $columns
* @param array|object $value The content of the structured type. It can be represented as
* - an associative `array` of column names and values;
* - an indexed `array` of column values in the order of structured type columns;
* - an `iterable` object that can be converted to an `array` using `iterator_to_array()`;
* - an `object` that can be converted to an `array` using `get_object_vars()`;
* - an `ExpressionInterface` object that represents a SQL expression.
* @param string|null $type The structured database type name. Defaults to `null` which means the type is not
* explicitly specified. Note that in the case where a type is not specified explicitly and DBMS cannot guess it
* from the context, SQL error will be raised.
* @param ColumnSchemaInterface[] $columns The structured type columns that are used for value normalization and type
* casting.
*
* @psalm-param array<string, ColumnSchemaInterface> $columns
*/
public function __construct(
private mixed $value,
private array|object $value,
private string|null $type = null,
private array $columns = [],
) {
Expand Down Expand Up @@ -62,34 +74,45 @@ public function getColumns(): array
}

/**
* The content of the structured type. It can be represented as an associative array of structured type column names
* and values.
* The content of the structured type. It can be represented as
* - an associative `array` of column names and values;
* - an indexed `array` of column values in the order of structured type columns;
* - an `iterable` object that can be converted to an `array` using `iterator_to_array()`;
* - an `object` that can be converted to an `array` using `get_object_vars()`;
* - an `ExpressionInterface` object that represents a SQL expression.
*/
public function getValue(): mixed
public function getValue(): array|object
{
return $this->value;
}

/**
* Sorted values according to the order of structured type columns,
* indexed keys are replaced with column names,
* missing elements are filled in with default values,
* excessive elements are removed.
* Returns the normalized value of the structured type, where:
* - values sorted according to the order of structured type columns;
* - indexed keys are replaced with column names;
* - missing elements are filled in with default values;
* - excessive elements are removed.
*
* If the structured type columns are not specified or the value is an `ExpressionInterface` object,
* it will be returned as is.
*/
public function getNormalizedValue(): mixed
public function getNormalizedValue(): array|object
{
if (empty($this->columns) || !is_iterable($this->value)) {
return $this->value;
$value = $this->value;

if (empty($this->columns) || $value instanceof ExpressionInterface) {
return $value;
}

if (is_object($value)) {
$value = $value instanceof Traversable
? iterator_to_array($value)
: get_object_vars($value);
}

$normalized = [];
$value = $this->value;
$columnsNames = array_keys($this->columns);

if ($value instanceof Traversable) {
$value = iterator_to_array($value);
}

foreach ($columnsNames as $i => $columnsName) {
$normalized[$columnsName] = match (true) {
array_key_exists($columnsName, $value) => $value[$columnsName],
Expand Down
4 changes: 2 additions & 2 deletions tests/Db/Expression/StructuredExpressionTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,9 @@ public function testConstruct(): void
'currency' => ColumnBuilder::char(3),
];

$expression = new StructuredExpression(123.45, 'currency_money_structured', $columns);
$expression = new StructuredExpression([5, 'USD'], 'currency_money_structured', $columns);

$this->assertSame(123.45, $expression->getValue());
$this->assertSame([5, 'USD'], $expression->getValue());
$this->assertSame('currency_money_structured', $expression->getType());
$this->assertSame($columns, $expression->getColumns());
}
Expand Down
14 changes: 7 additions & 7 deletions tests/Provider/StructuredTypeProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

namespace Yiisoft\Db\Tests\Provider;

use ArrayIterator;
use Yiisoft\Db\Expression\Expression;
use Yiisoft\Db\Schema\Column\ColumnBuilder;
use Yiisoft\Db\Tests\Support\TraversableObject;

Expand Down Expand Up @@ -38,13 +38,13 @@ public static function normolizedValues()
['value' => 10.0, 'currency_code' => 'USD'],
$price5UsdColumns,
],
'Fill default values and column names for iterable object' => [
'Fill default values and column names for an iterable object' => [
new TraversableObject([10.0]),
['value' => 10.0, 'currency_code' => 'USD'],
$price5UsdColumns,
],
'Fill default values for iterable object' => [
new ArrayIterator(['currency_code' => 'CNY']),
'Fill default values for an object' => [
(object) ['currency_code' => 'CNY'],
['value' => 5.0, 'currency_code' => 'CNY'],
$price5UsdColumns,
],
Expand All @@ -53,9 +53,9 @@ public static function normolizedValues()
['value' => 5.0, 'currency_code' => 'USD'],
$price5UsdColumns,
],
'Do not normalize scalar values' => [
1,
1,
'Do not normalize expressions' => [
$expression = new Expression('(5,USD)'),
$expression,
$price5UsdColumns,
],
'Do not normalize with empty columns' => [
Expand Down

0 comments on commit c0e41b7

Please sign in to comment.