Skip to content

Commit

Permalink
refactor: code for is_unique and is_not_unique methods; extracted com…
Browse files Browse the repository at this point in the history
…mon code into prepareUniqueQuery method
  • Loading branch information
maniaba committed Nov 14, 2024
1 parent 180eebf commit 440545e
Show file tree
Hide file tree
Showing 2 changed files with 40 additions and 103 deletions.
80 changes: 38 additions & 42 deletions system/Validation/Rules.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@

namespace CodeIgniter\Validation;

use CodeIgniter\Database\BaseBuilder;
use CodeIgniter\Exceptions\InvalidArgumentException;
use CodeIgniter\Helpers\Array\ArrayHelper;
use Config\Database;
Expand Down Expand Up @@ -118,40 +119,17 @@ public function greater_than_equal_to($str, string $min): bool
*/
public function is_not_unique($str, string $field, array $data): bool
{
if (! is_string($str) && $str !== null) {
$str = (string) $str;
}

// Grab any data for exclusion of a single row.
[$field, $whereField, $whereValue] = array_pad(explode(',', $field), 3, null);

// Break the dbGroup, table and field apart from the field string
$parts = explode('.', $field, 3);
$numParts = count($parts);

if ($numParts === 3) {
[$dbGroup, $table, $field] = $parts;
} elseif ($numParts === 2) {
[$table, $field] = $parts;
} else {
throw new InvalidArgumentException('The field must be in the format "table.field" or "dbGroup.table.field".');
}

$row = Database::connect($dbGroup ?? $data['DBGroup'] ?? null)
->table($table)
->select('1')
->where($field, $str)
->limit(1);
[$builder, $whereField, $whereValue] = $this->prepareUniqueQuery($str, $field, $data);

if (
$whereField !== null && $whereField !== ''
&& $whereValue !== null && $whereValue !== ''
&& ! preg_match('/^\{(\w+)\}$/', $whereValue)
) {
$row = $row->where($whereField, $whereValue);
$builder = $builder->where($whereField, $whereValue);
}

return $row->get()->getRow() !== null;
return $builder->get()->getRow() !== null;
}

/**
Expand Down Expand Up @@ -184,14 +162,38 @@ public function in_list($value, string $list): bool
*/
public function is_unique($str, string $field, array $data): bool
{
if (! is_string($str) && $str !== null) {
$str = (string) $str;
[$builder, $ignoreField, $ignoreValue] = $this->prepareUniqueQuery($str, $field, $data);

if (
$ignoreField !== null && $ignoreField !== ''
&& $ignoreValue !== null && $ignoreValue !== ''
&& ! preg_match('/^\{(\w+)\}$/', $ignoreValue)
) {
$builder = $builder->where("{$ignoreField} !=", $ignoreValue);
}

return $builder->get()->getRow() === null;
}

/**
* Prepares the database query for uniqueness checks.
*
* @param mixed $value The value to check.
* @param string $field The field parameters.
* @param array $data Additional data.
*
* @return array{0: BaseBuilder, 1: string|null, 2: string|null}
*/
private function prepareUniqueQuery($value, string $field, array $data): array

Check failure on line 187 in system/Validation/Rules.php

View workflow job for this annotation

GitHub Actions / PHP Static Analysis

Method CodeIgniter\Validation\Rules::prepareUniqueQuery() has parameter $data with no value type specified in iterable type array.
{
if (! is_string($value) && $value !== null) {
$value = (string) $value;
}

// Grab any data for exclusion of a single row.
[$field, $ignoreField, $ignoreValue] = array_pad(explode(',', $field), 3, null);
// Split the field parameters and pad the array to ensure three elements.
[$field, $extraField, $extraValue] = array_pad(explode(',', $field), 3, null);

// Break the dbGroup, table and field apart from the field string
// Parse the field string to extract dbGroup, table, and field.
$parts = explode('.', $field, 3);
$numParts = count($parts);

Expand All @@ -203,21 +205,15 @@ public function is_unique($str, string $field, array $data): bool
throw new InvalidArgumentException('The field must be in the format "table.field" or "dbGroup.table.field".');
}

$row = Database::connect($dbGroup ?? $data['DBGroup'] ?? null)
// Connect to the database.
$dbGroup ??= $data['DBGroup'] ?? null;
$builder = Database::connect($dbGroup)
->table($table)
->select('1')
->where($field, $str)
->where($field, $value)
->limit(1);

if (
$ignoreField !== null && $ignoreField !== ''
&& $ignoreValue !== null && $ignoreValue !== ''
&& ! preg_match('/^\{(\w+)\}$/', $ignoreValue)
) {
$row = $row->where("{$ignoreField} !=", $ignoreValue);
}

return $row->get()->getRow() === null;
return [$builder, $extraField, $extraValue];
}

/**
Expand Down
63 changes: 2 additions & 61 deletions system/Validation/StrictRules/Rules.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@
use CodeIgniter\Helpers\Array\ArrayHelper;
use CodeIgniter\Validation\Rules as NonStrictRules;
use Config\Database;
use InvalidArgumentException;

/**
* Validation Rules.
Expand Down Expand Up @@ -147,36 +146,7 @@ public function is_not_unique($str, string $field, array $data): bool
return false;
}

// Grab any data for exclusion of a single row.
[$field, $whereField, $whereValue] = array_pad(explode(',', $field), 3, null);

// Break the dbGroup, table and field apart from the field string
$parts = explode('.', $field, 3);
$numParts = count($parts);

if ($numParts === 3) {
[$dbGroup, $table, $field] = $parts;
} elseif ($numParts === 2) {
[$table, $field] = $parts;
} else {
throw new InvalidArgumentException('The field must be in the format "table.field" or "dbGroup.table.field".');
}

$row = Database::connect($dbGroup ?? $data['DBGroup'] ?? null)
->table($table)
->select('1')
->where($field, $str)
->limit(1);

if (
$whereField !== null && $whereField !== ''
&& $whereValue !== null && $whereValue !== ''
&& ! preg_match('/^\{(\w+)\}$/', $whereValue)
) {
$row = $row->where($whereField, $whereValue);
}

return $row->get()->getRow() !== null;
return $this->nonStrictRules->is_not_unique($str, $field, $data);
}

/**
Expand Down Expand Up @@ -215,36 +185,7 @@ public function is_unique($str, string $field, array $data): bool
return false;
}

// Grab any data for exclusion of a single row.
[$field, $ignoreField, $ignoreValue] = array_pad(explode(',', $field), 3, null);

// Break the dbGroup, table and field apart from the field string
$parts = explode('.', $field, 3);
$numParts = count($parts);

if ($numParts === 3) {
[$dbGroup, $table, $field] = $parts;
} elseif ($numParts === 2) {
[$table, $field] = $parts;
} else {
throw new InvalidArgumentException('The field must be in the format "table.field" or "dbGroup.table.field".');
}

$row = Database::connect($dbGroup ?? $data['DBGroup'] ?? null)
->table($table)
->select('1')
->where($field, $str)
->limit(1);

if (
$ignoreField !== null && $ignoreField !== ''
&& $ignoreValue !== null && $ignoreValue !== ''
&& ! preg_match('/^\{(\w+)\}$/', $ignoreValue)
) {
$row = $row->where("{$ignoreField} !=", $ignoreValue);
}

return $row->get()->getRow() === null;
return $this->nonStrictRules->is_unique($str, $field, $data);
}

/**
Expand Down

0 comments on commit 440545e

Please sign in to comment.