Skip to content

Commit 6255ec1

Browse files
authored
Merge pull request #48 from stellarwp/fix/ensuring-array-values-can-be-used
Fix/ensuring array values can be used
2 parents eb3ce5d + b3c191e commit 6255ec1

File tree

4 files changed

+339
-20
lines changed

4 files changed

+339
-20
lines changed

CHANGELOG.md

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,19 @@
22

33
All notable changes to this project will be documented in this file. This project adhere to the [Semantic Versioning](http://semver.org/) standard.
44

5+
## [3.1.4] 2025-10-16
6+
7+
* Fix - Handle array values correctly in the `get_*` query methods.
8+
59
## [3.1.3] 2025-10-08
610

7-
* Fix - Fix the `get_current_schema` method to cache the schema of each implementation.
11+
* Fix - `get_current_schema` method will npw cache the schema of each implementation correctly.
812

913
[3.1.3]: https://github.com/stellarwp/schema/releases/tag/3.1.3
1014

1115
## [3.1.2] 2025-10-02
1216

13-
* Fix - Fix the `update_many` method to properly check if the transaction was successful.
17+
* Fix - `update_many` method will now properly check if the transaction was successful.
1418

1519
[3.1.2]: https://github.com/stellarwp/schema/releases/tag/3.1.2
1620

phpstan.neon.dist

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ parameters:
2020
level: 5
2121
inferPrivatePropertyTypeFromConstructor: true
2222
reportUnmatchedIgnoredErrors: false
23+
treatPhpDocTypesAsCertain: false
2324

2425
# Paths to be analyzed.
2526
paths:

src/Schema/Traits/Custom_Table_Query_Methods.php

Lines changed: 59 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -336,8 +336,9 @@ public static function get_total_items( array $args = [] ): int {
336336
* Updates multiple rows into the table.
337337
*
338338
* @since 3.0.0
339+
* @since 3.1.4 Enabled unfolding the value if is an array.
339340
*
340-
* @param array<mixed> $entries The entries to update.
341+
* @param array<array<string, null|int|string|float|bool|DateTimeInterface|string[]|int[]|float[]|DateTimeInterface[]>> $entries The entries to update.
341342
*
342343
* @return bool Whether the update was successful.
343344
*/
@@ -372,7 +373,7 @@ public static function update_many( array $entries ): bool {
372373

373374
[ $value, $placeholder ] = self::prepare_value_for_query( $column, $value );
374375

375-
$set_statement[] = $database::prepare( "%i = {$placeholder}", ...array_filter( [ $column, $value ], static fn( $v ) => null !== $v ) );
376+
$set_statement[] = $database::prepare( "%i = {$placeholder}", ...array_filter( [ $column, ...self::ensure_array( $value ) ], static fn( $v ) => null !== $v ) );
376377
}
377378

378379
$set_statement = implode( ', ', $set_statement );
@@ -672,12 +673,13 @@ protected static function get_join_parts( string $join_table, string $join_condi
672673
*
673674
* @since 3.0.0
674675
* @since 3.1.1 Added the $order_by parameter.
676+
* @since 3.1.4 Enabled unfolding the value if is an array.
675677
*
676-
* @param string $column The column to get the models by.
677-
* @param mixed $value The value to get the models by.
678-
* @param string $operator The operator to use.
679-
* @param int $limit The limit of models to return.
680-
* @param string $order_by The order by clause to use.
678+
* @param string $column The column to get the models by.
679+
* @param null|int|string|float|bool|DateTimeInterface|string[]|int[]|float[]|DateTimeInterface[] $value The value to get the models by.
680+
* @param string $operator The operator to use.
681+
* @param int $limit The limit of models to return.
682+
* @param string $order_by The order by clause to use.
681683
*
682684
* @return mixed[] The models, or an empty array if no models are found.
683685
*
@@ -690,12 +692,12 @@ public static function get_all_by( string $column, $value, string $operator = '=
690692

691693
$database = Config::get_db();
692694
$results = [];
693-
foreach ( static::fetch_all_where( $database::prepare( "WHERE %i {$operator} {$placeholder}", ...array_filter( [ $column, $value ], static fn( $v ) => null !== $v ) ), $limit, ARRAY_A, $order_by ) as $task_array ) {
694-
if ( empty( $task_array[ static::uid_column() ] ) ) {
695+
foreach ( static::fetch_all_where( $database::prepare( "WHERE %i {$operator} {$placeholder}", ...array_filter( [ $column, ...self::ensure_array( $value ) ], static fn( $v ) => null !== $v ) ), $limit, ARRAY_A, $order_by ) as $data_array ) {
696+
if ( empty( $data_array[ static::uid_column() ] ) ) {
695697
continue;
696698
}
697699

698-
$results[] = static::transform_from_array( self::amend_value_types( $task_array ) );
700+
$results[] = static::transform_from_array( self::amend_value_types( $data_array ) );
699701
}
700702

701703
return $results;
@@ -705,34 +707,44 @@ public static function get_all_by( string $column, $value, string $operator = '=
705707
* Gets the first model by a column.
706708
*
707709
* @since 3.0.0
710+
* @since 3.1.4 Enabled unfolding the value if is an array.
711+
* @since 3.1.4 Added the $operator parameter.
708712
*
709-
* @param string $column The column to get the model by.
710-
* @param mixed $value The value to get the model by.
713+
* @param string $column The column to get the model by.
714+
* @param null|int|string|float|bool|DateTimeInterface|string[]|int[]|float[]|DateTimeInterface[] $value The value to get the model by.
715+
* @param string $operator The operator to use.
711716
*
712717
* @return ?mixed The model, or `null` if no model is found.
713718
*
714719
* @throws InvalidArgumentException If the column does not exist.
720+
* @throws InvalidArgumentException If the operator is invalid.
715721
*/
716-
public static function get_first_by( string $column, $value ) {
722+
public static function get_first_by( string $column, $value, string $operator = '=' ) {
717723
[ $value, $placeholder ] = self::prepare_value_for_query( $column, $value );
718724

725+
$operator = strtoupper( $operator );
726+
727+
if ( ! in_array( $operator, self::operators(), true ) ) {
728+
throw new InvalidArgumentException( "Invalid operator: {$operator}." );
729+
}
730+
719731
$database = Config::get_db();
720-
$task_array = static::fetch_first_where( $database::prepare( "WHERE %i = {$placeholder}", ...array_filter( [ $column, $value ], static fn( $v ) => null !== $v ) ), ARRAY_A );
732+
$data_array = static::fetch_first_where( $database::prepare( "WHERE %i {$operator} {$placeholder}", ...array_filter( [ $column, ...self::ensure_array( $value ) ], static fn( $v ) => null !== $v ) ), ARRAY_A );
721733

722-
if ( empty( $task_array[ static::uid_column() ] ) ) {
734+
if ( empty( $data_array[ static::uid_column() ] ) ) {
723735
return null;
724736
}
725737

726-
return static::transform_from_array( self::amend_value_types( $task_array ) );
738+
return static::transform_from_array( self::amend_value_types( $data_array ) );
727739
}
728740

729741
/**
730742
* Prepares a value for a query.
731743
*
732744
* @since 3.0.0
733745
*
734-
* @param string $column The column to prepare the value for.
735-
* @param mixed $value The value to prepare.
746+
* @param string $column The column to prepare the value for.
747+
* @param null|string|int|float|bool|DateTimeInterface|array<null|string|int|float|bool|DateTimeInterface> $value The value to prepare.
736748
*
737749
* @return array{0: mixed, 1: string} The prepared value and placeholder.
738750
*
@@ -791,6 +803,10 @@ private static function prepare_value_for_query( string $column, $value ): array
791803
throw new InvalidArgumentException( "Unsupported column type: $column_type." );
792804
}
793805

806+
if ( is_array( $value ) && ! $value ) {
807+
return [ null, '(NULL)' ];
808+
}
809+
794810
// @phpstan-ignore-next-line
795811
return [ $value, is_array( $value ) ? '(' . implode( ',', array_fill( 0, count( $value ), $placeholder ) ) . ')' : $placeholder ];
796812
}
@@ -918,4 +934,29 @@ public static function cast_value_based_on_type( string $type, $value ) {
918934
throw new InvalidArgumentException( "Unsupported column type: {$type}." );
919935
}
920936
}
937+
938+
/**
939+
* Ensures the value is an array.
940+
*
941+
* @since 3.1.4
942+
*
943+
* @param null|string|int|float|bool|DateTimeInterface|string[]|int[]|float[]|DateTimeInterface[] $value The value to ensure is an array.
944+
*
945+
* @return array<null|string|int|float|bool|DateTimeInterface> The value as an array.
946+
*/
947+
private static function ensure_array( $value ): array {
948+
if ( null !== $value && ! is_int( $value ) && ! is_string( $value ) && ! is_float( $value ) && ! is_bool( $value ) && ! $value instanceof DateTimeInterface && ! is_array( $value ) ) {
949+
throw new InvalidArgumentException( 'Value should be an integer, string, float, boolean, DateTimeInterface, or array.' );
950+
}
951+
952+
if ( is_array( $value ) && $value ) {
953+
foreach ( $value as $k => $v ) {
954+
if ( null !== $v && ! is_int( $v ) && ! is_string( $v ) && ! is_float( $v ) && ! is_bool( $v ) && ! $v instanceof DateTimeInterface ) {
955+
throw new InvalidArgumentException( 'Value with offset ' . $k . ' should be an integer, string, float, boolean or DateTimeInterface.' );
956+
}
957+
}
958+
}
959+
960+
return is_array( $value ) ? $value : [ $value ];
961+
}
921962
}

0 commit comments

Comments
 (0)