Skip to content

[4.6] refactor: Validation rules and tests #8975

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
Jun 24, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 0 additions & 30 deletions phpstan-baseline.php
Original file line number Diff line number Diff line change
Expand Up @@ -9973,12 +9973,6 @@
'count' => 1,
'path' => __DIR__ . '/system/Validation/DotArrayFilter.php',
];
$ignoreErrors[] = [
// identifier: booleanNot.exprNotBoolean
'message' => '#^Only booleans are allowed in a negated boolean, array\\|null given\\.$#',
'count' => 6,
'path' => __DIR__ . '/system/Validation/FileRules.php',
];
$ignoreErrors[] = [
// identifier: missingType.iterableValue
'message' => '#^Method CodeIgniter\\\\Validation\\\\Rules\\:\\:differs\\(\\) has parameter \\$data with no value type specified in iterable type array\\.$#',
Expand Down Expand Up @@ -17953,24 +17947,6 @@
'count' => 1,
'path' => __DIR__ . '/tests/system/Throttle/ThrottleTest.php',
];
$ignoreErrors[] = [
// identifier: missingType.iterableValue
'message' => '#^Method CodeIgniter\\\\Validation\\\\CreditCardRulesTest\\:\\:calculateLuhnChecksum\\(\\) has parameter \\$digits with no value type specified in iterable type array\\.$#',
'count' => 1,
'path' => __DIR__ . '/tests/system/Validation/CreditCardRulesTest.php',
];
$ignoreErrors[] = [
// identifier: missingType.iterableValue
'message' => '#^Method CodeIgniter\\\\Validation\\\\CreditCardRulesTest\\:\\:provideValidCCNumber\\(\\) return type has no value type specified in iterable type iterable\\.$#',
'count' => 1,
'path' => __DIR__ . '/tests/system/Validation/CreditCardRulesTest.php',
];
$ignoreErrors[] = [
// identifier: argument.type
'message' => '#^Parameter \\#1 \\$config of class CodeIgniter\\\\Validation\\\\Validation constructor expects Config\\\\Validation, stdClass given\\.$#',
'count' => 1,
'path' => __DIR__ . '/tests/system/Validation/CreditCardRulesTest.php',
];
$ignoreErrors[] = [
// identifier: missingType.iterableValue
'message' => '#^Property CodeIgniter\\\\Validation\\\\CreditCardRulesTest\\:\\:\\$config type has no value type specified in iterable type array\\.$#',
Expand All @@ -17989,12 +17965,6 @@
'count' => 1,
'path' => __DIR__ . '/tests/system/Validation/DatabaseRelatedRulesTest.php',
];
$ignoreErrors[] = [
// identifier: argument.type
'message' => '#^Parameter \\#1 \\$config of class CodeIgniter\\\\Validation\\\\Validation constructor expects Config\\\\Validation, stdClass given\\.$#',
'count' => 1,
'path' => __DIR__ . '/tests/system/Validation/FileRulesTest.php',
];
$ignoreErrors[] = [
// identifier: missingType.iterableValue
'message' => '#^Property CodeIgniter\\\\Validation\\\\FileRulesTest\\:\\:\\$config type has no value type specified in iterable type array\\.$#',
Expand Down
290 changes: 2 additions & 288 deletions system/Validation/FileRules.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,299 +13,13 @@

namespace CodeIgniter\Validation;

use CodeIgniter\Exceptions\InvalidArgumentException;
use CodeIgniter\HTTP\CLIRequest;
use CodeIgniter\HTTP\IncomingRequest;
use CodeIgniter\HTTP\RequestInterface;
use Config\Mimes;
use CodeIgniter\Validation\StrictRules\FileRules as StrictFileRules;

/**
* File validation rules
*
* @see \CodeIgniter\Validation\FileRulesTest
*/
class FileRules
class FileRules extends StrictFileRules
{
/**
* Request instance. So we can get access to the files.
*
* @var IncomingRequest
*/
protected $request;

/**
* Constructor.
*/
public function __construct(?RequestInterface $request = null)
{
if ($request === null) {
$request = service('request');
}

assert($request instanceof IncomingRequest || $request instanceof CLIRequest);

$this->request = $request;
}

/**
* Verifies that $name is the name of a valid uploaded file.
*/
public function uploaded(?string $blank, string $name): bool
{
if (! ($files = $this->request->getFileMultiple($name))) {
$files = [$this->request->getFile($name)];
}

foreach ($files as $file) {
if ($file === null) {
return false;
}

if (ENVIRONMENT === 'testing') {
if ($file->getError() !== 0) {
return false;
}
} else {
// Note: cannot unit test this; no way to over-ride ENVIRONMENT?
// @codeCoverageIgnoreStart
if (! $file->isValid()) {
return false;
}
// @codeCoverageIgnoreEnd
}
}

return true;
}

/**
* Verifies if the file's size in Kilobytes is no larger than the parameter.
*/
public function max_size(?string $blank, string $params): bool
{
// Grab the file name off the top of the $params
// after we split it.
$paramArray = explode(',', $params);
if (count($paramArray) !== 2) {
throw new InvalidArgumentException('Invalid max_size parameter: "' . $params . '"');
}
$name = array_shift($paramArray);

if (! ($files = $this->request->getFileMultiple($name))) {
$files = [$this->request->getFile($name)];
}

foreach ($files as $file) {
if ($file === null) {
return false;
}

if ($file->getError() === UPLOAD_ERR_NO_FILE) {
return true;
}

if ($file->getError() === UPLOAD_ERR_INI_SIZE) {
return false;
}

if ($file->getSize() / 1024 > $paramArray[0]) {
return false;
}
}

return true;
}

/**
* Uses the mime config file to determine if a file is considered an "image",
* which for our purposes basically means that it's a raster image or svg.
*/
public function is_image(?string $blank, string $params): bool
{
// Grab the file name off the top of the $params
// after we split it.
$params = explode(',', $params);
$name = array_shift($params);

if (! ($files = $this->request->getFileMultiple($name))) {
$files = [$this->request->getFile($name)];
}

foreach ($files as $file) {
if ($file === null) {
return false;
}

if ($file->getError() === UPLOAD_ERR_NO_FILE) {
return true;
}

// We know that our mimes list always has the first mime
// start with `image` even when then are multiple accepted types.
$type = Mimes::guessTypeFromExtension($file->getExtension()) ?? '';

if (mb_strpos($type, 'image') !== 0) {
return false;
}
}

return true;
}

/**
* Checks to see if an uploaded file's mime type matches one in the parameter.
*/
public function mime_in(?string $blank, string $params): bool
{
// Grab the file name off the top of the $params
// after we split it.
$params = explode(',', $params);
$name = array_shift($params);

if (! ($files = $this->request->getFileMultiple($name))) {
$files = [$this->request->getFile($name)];
}

foreach ($files as $file) {
if ($file === null) {
return false;
}

if ($file->getError() === UPLOAD_ERR_NO_FILE) {
return true;
}

if (! in_array($file->getMimeType(), $params, true)) {
return false;
}
}

return true;
}

/**
* Checks to see if an uploaded file's extension matches one in the parameter.
*/
public function ext_in(?string $blank, string $params): bool
{
// Grab the file name off the top of the $params
// after we split it.
$params = explode(',', $params);
$name = array_shift($params);

if (! ($files = $this->request->getFileMultiple($name))) {
$files = [$this->request->getFile($name)];
}

foreach ($files as $file) {
if ($file === null) {
return false;
}

if ($file->getError() === UPLOAD_ERR_NO_FILE) {
return true;
}

if (! in_array($file->guessExtension(), $params, true)) {
return false;
}
}

return true;
}

/**
* Checks an uploaded file to verify that the dimensions are within
* a specified allowable dimension.
*/
public function max_dims(?string $blank, string $params): bool
{
// Grab the file name off the top of the $params
// after we split it.
$params = explode(',', $params);
$name = array_shift($params);

if (! ($files = $this->request->getFileMultiple($name))) {
$files = [$this->request->getFile($name)];
}

foreach ($files as $file) {
if ($file === null) {
return false;
}

if ($file->getError() === UPLOAD_ERR_NO_FILE) {
return true;
}

// Get Parameter sizes
$allowedWidth = $params[0] ?? 0;
$allowedHeight = $params[1] ?? 0;

// Get uploaded image size
$info = getimagesize($file->getTempName());

if ($info === false) {
// Cannot get the image size.
return false;
}

$fileWidth = $info[0];
$fileHeight = $info[1];

if ($fileWidth > $allowedWidth || $fileHeight > $allowedHeight) {
return false;
}
}

return true;
}

/**
* Checks an uploaded file to verify that the dimensions are greater than
* a specified dimension.
*/
public function min_dims(?string $blank, string $params): bool
{
// Grab the file name off the top of the $params
// after we split it.
$params = explode(',', $params);
$name = array_shift($params);

$files = $this->request->getFileMultiple($name);
if ($files === null) {
$files = [$this->request->getFile($name)];
}

foreach ($files as $file) {
if ($file === null) {
return false;
}

if ($file->getError() === UPLOAD_ERR_NO_FILE) {
return true;
}

// Get Parameter sizes
$minimumWidth = $params[0] ?? 0;
$minimumHeight = $params[1] ?? 0;

// Get uploaded image size
$info = getimagesize($file->getTempName());

if ($info === false) {
// Cannot get the image size.
return false;
}

$fileWidth = $info[0];
$fileHeight = $info[1];

if ($fileWidth < $minimumWidth || $fileHeight < $minimumHeight) {
return false;
}
}

return true;
}
}
Loading
Loading