mirror of
https://github.com/getgrav/grav.git
synced 2026-01-30 11:20:07 +01:00
Merge branch 'develop' into 1.8
Signed-off-by: Andy Miller <rhuk@mac.com>
This commit is contained in:
22
.github/workflows/tests.yaml
vendored
22
.github/workflows/tests.yaml
vendored
@@ -10,20 +10,18 @@ permissions:
|
||||
contents: read # to fetch code (actions/checkout)
|
||||
|
||||
jobs:
|
||||
|
||||
unit-tests:
|
||||
|
||||
runs-on: ${{ matrix.os }}
|
||||
|
||||
strategy:
|
||||
matrix:
|
||||
php: [8.4, 8.3, 8.2]
|
||||
os: [ubuntu-latest]
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
runs-on: ${{ matrix.os }}
|
||||
|
||||
- name: Setup PHP
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Setup PHP ${{ matrix.php }}
|
||||
uses: shivammathur/setup-php@v2
|
||||
with:
|
||||
php-version: ${{ matrix.php }}
|
||||
@@ -31,17 +29,11 @@ jobs:
|
||||
tools: composer:v2
|
||||
coverage: none
|
||||
env:
|
||||
COMPOSER_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
# - name: Update composer
|
||||
# run: composer update
|
||||
#
|
||||
# - name: Validate composer.json and composer.lock
|
||||
# run: composer validate
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Get composer cache directory
|
||||
id: composer-cache
|
||||
run: echo "::set-output name=dir::$(composer config cache-files-dir)"
|
||||
run: echo "dir=$(composer config cache-files-dir)" >> $GITHUB_OUTPUT
|
||||
|
||||
- name: Cache dependencies
|
||||
uses: actions/cache@v4
|
||||
|
||||
@@ -196,6 +196,38 @@ class BlueprintSchema extends BlueprintSchemaBase implements ExportInterface
|
||||
|
||||
$messages += Validation::validate($child, $rule);
|
||||
|
||||
if (isset($rule['validate']['match']) || isset($rule['validate']['match_exact']) || isset($rule['validate']['match_any'])) {
|
||||
$ruleKey = current(array_intersect(['match', 'match_exact', 'match_any'], array_keys($rule['validate'])));
|
||||
$otherKey = $rule['validate'][$ruleKey] ?? null;
|
||||
$otherVal = $data[$otherKey] ?? null;
|
||||
$otherLabel = $this->items[$otherKey]['label'] ?? $otherKey;
|
||||
$currentVal = $data[$key] ?? null;
|
||||
$currentLabel = $this->items[$key]['label'] ?? $key;
|
||||
|
||||
// Determine comparison type (loose, strict, substring)
|
||||
// Perform comparison:
|
||||
$isValid = false;
|
||||
if ($ruleKey === 'match') {
|
||||
$isValid = ($currentVal == $otherVal);
|
||||
} elseif ($ruleKey === 'match_exact') {
|
||||
$isValid = ($currentVal === $otherVal);
|
||||
} elseif ($ruleKey === 'match_any') {
|
||||
// If strings:
|
||||
if (is_string($currentVal) && is_string($otherVal)) {
|
||||
$isValid = (strlen($currentVal) && strlen($otherVal) && (str_contains($currentVal,
|
||||
$otherVal) || strpos($otherVal, $currentVal) !== false));
|
||||
}
|
||||
// If arrays:
|
||||
if (is_array($currentVal) && is_array($otherVal)) {
|
||||
$common = array_intersect($currentVal, $otherVal);
|
||||
$isValid = !empty($common);
|
||||
}
|
||||
}
|
||||
if (!$isValid) {
|
||||
$messages[$rule['name']][] = sprintf(Grav::instance()['language']->translate('PLUGIN_FORM.VALIDATION_MATCH'), $currentLabel, $otherLabel);
|
||||
}
|
||||
}
|
||||
|
||||
} elseif (is_array($child) && is_array($val)) {
|
||||
// Array has been defined in blueprints.
|
||||
$messages += $this->validateArray($child, $val, $strict);
|
||||
|
||||
@@ -47,12 +47,14 @@ class Validation
|
||||
}
|
||||
|
||||
$validate = (array)($field['validate'] ?? null);
|
||||
$type = $validate['type'] ?? $field['type'];
|
||||
$validate_type = $validate['type'] ?? null;
|
||||
$required = $validate['required'] ?? false;
|
||||
$type = $validate_type ?? $field['type'];
|
||||
|
||||
$required = $required && ($validate_type !== 'ignore');
|
||||
|
||||
// If value isn't required, we will stop validation if empty value is given.
|
||||
if ($required !== true && ($value === null || $value === '' || (($field['type'] === 'checkbox' || $field['type'] === 'switch') && $value == false))
|
||||
) {
|
||||
if ($required !== true && ($value === null || $value === '' || empty($value) || (($field['type'] === 'checkbox' || $field['type'] === 'switch') && $value == false))) {
|
||||
return [];
|
||||
}
|
||||
|
||||
|
||||
@@ -26,7 +26,7 @@ abstract class AbstractLazyCollection extends BaseAbstractLazyCollection impleme
|
||||
* @par ArrayCollection
|
||||
* @phpstan-var ArrayCollection<TKey,T>
|
||||
*/
|
||||
protected ?\Doctrine\Common\Collections\Collection $collection = null;
|
||||
protected $collection;
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
|
||||
@@ -16,11 +16,14 @@ use InvalidArgumentException;
|
||||
use JsonSerializable;
|
||||
use Psr\Http\Message\StreamInterface;
|
||||
use Psr\Http\Message\UploadedFileInterface;
|
||||
use ReturnTypeWillChange;
|
||||
use RuntimeException;
|
||||
use function copy;
|
||||
use function fopen;
|
||||
use function is_string;
|
||||
use function sprintf;
|
||||
use const UPLOAD_ERR_NO_FILE;
|
||||
use const UPLOAD_ERR_OK;
|
||||
|
||||
/**
|
||||
* Class FormFlashFile
|
||||
@@ -29,11 +32,15 @@ use function sprintf;
|
||||
class FormFlashFile implements UploadedFileInterface, JsonSerializable
|
||||
{
|
||||
/** @var string */
|
||||
private $id;
|
||||
private string $id;
|
||||
/** @var string */
|
||||
private string $field;
|
||||
/** @var bool */
|
||||
private $moved = false;
|
||||
private bool $moved = false;
|
||||
/** @var array */
|
||||
private array $upload;
|
||||
/** @var FormFlash */
|
||||
private $flash;
|
||||
private FormFlash $flash;
|
||||
|
||||
/**
|
||||
* FormFlashFile constructor.
|
||||
@@ -41,14 +48,16 @@ class FormFlashFile implements UploadedFileInterface, JsonSerializable
|
||||
* @param array $upload
|
||||
* @param FormFlash $flash
|
||||
*/
|
||||
public function __construct(private readonly string $field, private array $upload, FormFlash $flash)
|
||||
public function __construct(string $field, array $upload, FormFlash $flash)
|
||||
{
|
||||
$this->id = $flash->getId() ?: $flash->getUniqueId();
|
||||
$this->field = $field;
|
||||
$this->upload = $upload;
|
||||
$this->flash = $flash;
|
||||
|
||||
$tmpFile = $this->getTmpFile();
|
||||
if (!$tmpFile && $this->isOk()) {
|
||||
$this->upload['error'] = \UPLOAD_ERR_NO_FILE;
|
||||
$this->upload['error'] = UPLOAD_ERR_NO_FILE;
|
||||
}
|
||||
|
||||
if (!isset($this->upload['size'])) {
|
||||
@@ -59,7 +68,7 @@ class FormFlashFile implements UploadedFileInterface, JsonSerializable
|
||||
/**
|
||||
* @return StreamInterface
|
||||
*/
|
||||
public function getStream()
|
||||
public function getStream(): StreamInterface
|
||||
{
|
||||
$this->validateActive();
|
||||
|
||||
@@ -80,7 +89,7 @@ class FormFlashFile implements UploadedFileInterface, JsonSerializable
|
||||
* @param string $targetPath
|
||||
* @return void
|
||||
*/
|
||||
public function moveTo($targetPath)
|
||||
public function moveTo($targetPath): void
|
||||
{
|
||||
$this->validateActive();
|
||||
|
||||
@@ -120,7 +129,7 @@ class FormFlashFile implements UploadedFileInterface, JsonSerializable
|
||||
/**
|
||||
* @return int
|
||||
*/
|
||||
public function getSize()
|
||||
public function getSize(): int
|
||||
{
|
||||
return $this->upload['size'];
|
||||
}
|
||||
@@ -128,15 +137,15 @@ class FormFlashFile implements UploadedFileInterface, JsonSerializable
|
||||
/**
|
||||
* @return int
|
||||
*/
|
||||
public function getError()
|
||||
public function getError(): int
|
||||
{
|
||||
return $this->upload['error'] ?? \UPLOAD_ERR_OK;
|
||||
return $this->upload['error'] ?? UPLOAD_ERR_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getClientFilename()
|
||||
public function getClientFilename(): string
|
||||
{
|
||||
return $this->upload['name'] ?? 'unknown';
|
||||
}
|
||||
@@ -144,7 +153,7 @@ class FormFlashFile implements UploadedFileInterface, JsonSerializable
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getClientMediaType()
|
||||
public function getClientMediaType(): string
|
||||
{
|
||||
return $this->upload['type'] ?? 'application/octet-stream';
|
||||
}
|
||||
@@ -172,7 +181,7 @@ class FormFlashFile implements UploadedFileInterface, JsonSerializable
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getDestination()
|
||||
public function getDestination(): string
|
||||
{
|
||||
return $this->upload['path'] ?? '';
|
||||
}
|
||||
@@ -180,8 +189,8 @@ class FormFlashFile implements UploadedFileInterface, JsonSerializable
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
#[\ReturnTypeWillChange]
|
||||
public function jsonSerialize()
|
||||
#[ReturnTypeWillChange]
|
||||
public function jsonSerialize(): array
|
||||
{
|
||||
return $this->upload;
|
||||
}
|
||||
@@ -220,7 +229,7 @@ class FormFlashFile implements UploadedFileInterface, JsonSerializable
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
#[\ReturnTypeWillChange]
|
||||
#[ReturnTypeWillChange]
|
||||
public function __debugInfo()
|
||||
{
|
||||
return [
|
||||
@@ -255,6 +264,6 @@ class FormFlashFile implements UploadedFileInterface, JsonSerializable
|
||||
*/
|
||||
private function isOk(): bool
|
||||
{
|
||||
return \UPLOAD_ERR_OK === $this->getError();
|
||||
return UPLOAD_ERR_OK === $this->getError();
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user