Add types to class constants

This commit is contained in:
Giuseppe Criscione 2024-11-18 22:58:26 +01:00
parent 1a9678436d
commit 9e247ad9ae
67 changed files with 446 additions and 182 deletions

View File

@ -47,7 +47,7 @@ final class App
/**
* Current Formwork version
*/
public const VERSION = '2.0.0-beta.2';
public const string VERSION = '2.0.0-beta.2';
protected Container $container;

View File

@ -14,7 +14,7 @@ class Backupper
/**
* Date format used in backup archive name
*/
protected const DATE_FORMAT = 'YmdHis';
protected const string DATE_FORMAT = 'YmdHis';
/**
* Backupper options

View File

@ -11,7 +11,7 @@ use Formwork\Utils\FileSystem;
class Config implements ArraySerializable
{
protected const INTERPOLATION_REGEX = '/\$(?!\$)\{([%a-z._]+)\}/i';
protected const string INTERPOLATION_REGEX = '/\$(?!\$)\{([%a-z._]+)\}/i';
protected bool $resolved = false;

View File

@ -30,7 +30,12 @@ class Field implements Arrayable, Stringable
}
use Methods;
protected const UNTRANSLATABLE_KEYS = ['name', 'type', 'value', 'default', 'translate'];
/**
* Keys that should not be translated
*
* @var list<string>
*/
protected const array UNTRANSLATABLE_KEYS = ['name', 'type', 'value', 'default', 'translate'];
/**
* Field validation status

View File

@ -16,9 +16,9 @@ use Stringable;
class File extends Model implements Arrayable, Stringable
{
protected const MODEL_IDENTIFIER = 'file';
protected const string MODEL_IDENTIFIER = 'file';
protected const SCHEME_IDENTIFIER = 'files.file';
protected const string SCHEME_IDENTIFIER = 'files.file';
/**
* File name

View File

@ -14,12 +14,12 @@ class Client
/**
* Default Formwork user agent
*/
protected const DEFAULT_USER_AGENT = 'PHP Formwork/' . App::VERSION;
protected const string DEFAULT_USER_AGENT = 'PHP Formwork/' . App::VERSION;
/**
* Regex matching HTTP status line
*/
protected const STATUS_LINE_REGEX = '~^(HTTP/\d+\.\d+)\s+(\d+)\s+(.+)~i';
protected const string STATUS_LINE_REGEX = '~^(HTTP/\d+\.\d+)\s+(\d+)\s+(.+)~i';
/**
* Client options

View File

@ -8,7 +8,7 @@ use RuntimeException;
class FileResponse extends Response
{
protected const CHUNK_SIZE = 512 * 1024;
protected const int CHUNK_SIZE = 512 * 1024;
protected int $fileSize;

View File

@ -9,8 +9,10 @@ class UploadedFile
{
/**
* Human-readable Uploader error messages
*
* @var array<int, string>
*/
protected const ERROR_MESSAGES = [
protected const array ERROR_MESSAGES = [
UPLOAD_ERR_OK => 'The file uploaded with success',
UPLOAD_ERR_INI_SIZE => 'The uploaded file exceeds the upload_max_filesize directive in php.ini',
UPLOAD_ERR_FORM_SIZE => 'The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the HTML form',
@ -23,8 +25,10 @@ class UploadedFile
/**
* Uploader errors language strings
*
* @var array<int, string>
*/
protected const ERROR_TRANSLATION_STRINGS = [
protected const array ERROR_TRANSLATION_STRINGS = [
UPLOAD_ERR_INI_SIZE => 'upload.error.size',
UPLOAD_ERR_FORM_SIZE => 'upload.error.size',
UPLOAD_ERR_PARTIAL => 'upload.error.partial',

View File

@ -11,11 +11,26 @@ use InvalidArgumentException;
class Request
{
public const DEFAULT_PORTS = ['http' => 80, 'https' => 430];
/**
* Default ports for HTTP and HTTPS protocols
*
* @var array<string, int>
*/
public const array DEFAULT_PORTS = ['http' => 80, 'https' => 430];
protected const LOCALHOST_IP_ADDRESSES = ['127.0.0.1', '::1'];
/**
* List of IP addresses considered as localhost
*
* @var list<string>
*/
protected const array LOCALHOST_IP_ADDRESSES = ['127.0.0.1', '::1'];
protected const FORWARDED_DIRECTIVES = ['for', 'host', 'proto', 'port'];
/**
* List of forwarded directives
*
* @var list<string>
*/
protected const array FORWARDED_DIRECTIVES = ['for', 'host', 'proto', 'port'];
protected RequestData $input;

View File

@ -24,11 +24,11 @@ class Session implements Arrayable
remove as protected baseRemove;
}
protected const SESSION_NAME = 'formwork_session';
protected const string SESSION_NAME = 'formwork_session';
protected const SESSION_MESSAGES_KEY = '_formwork_messages';
protected const string SESSION_MESSAGES_KEY = '_formwork_messages';
protected const SESSION_ID_REGEX = '/^[a-z0-9,-]{22,256}$/i';
protected const string SESSION_ID_REGEX = '/^[a-z0-9,-]{22,256}$/i';
protected Messages $messages;

View File

@ -13,16 +13,16 @@ class Cookie
/**
* 'Strict' value for SameSite attribute
*/
public const SAMESITE_STRICT = 'Strict';
public const string SAMESITE_STRICT = 'Strict';
/**
* 'Lax' value for SameSite attribute
*/
public const SAMESITE_LAX = 'Lax';
public const string SAMESITE_LAX = 'Lax';
public const SAMESITE_NONE = 'None';
public const string SAMESITE_NONE = 'None';
protected const INVALID_NAME_CHARACTERS = '/[\x00-\x20.()<>@,;:\"\/[\]?={}]|[^\x21-\x7e]/';
protected const string INVALID_NAME_CHARACTERS = '/[\x00-\x20.()<>@,;:\"\/[\]?={}]|[^\x21-\x7e]/';
/**
* Send a cookie

View File

@ -12,12 +12,12 @@ class IpAnonymizer
/**
* IPv4 addresses mask
*/
protected const IPV4_MASK = '255.255.255.0';
protected const string IPV4_MASK = '255.255.255.0';
/**
* IPv6 addresses mask
*/
protected const IPV6_MASK = 'ffff:ffff:ffff:ffff::';
protected const string IPV6_MASK = 'ffff:ffff:ffff:ffff::';
/**
* Anonymize an IP address

View File

@ -8,9 +8,9 @@ use UnexpectedValueException;
class ColorProfile
{
protected const ICC_PROFILE_SIGNATURE = 'acsp';
protected const string ICC_PROFILE_SIGNATURE = 'acsp';
protected const ICC_PROFILE_SIGNATURE_OFFSET = 36;
protected const int ICC_PROFILE_SIGNATURE_OFFSET = 36;
/**
* @var array<string, mixed>

View File

@ -8,7 +8,12 @@ use UnexpectedValueException;
class GifDecoder implements DecoderInterface
{
protected const GIF_HEADERS = ['GIF87a', 'GIF89a'];
/**
* GIF headers
*
* @var array<string>
*/
protected const array GIF_HEADERS = ['GIF87a', 'GIF89a'];
public function decode(string &$data): Generator
{

View File

@ -8,7 +8,7 @@ use UnexpectedValueException;
class PngDecoder implements DecoderInterface
{
protected const PNG_HEADER = "\x89PNG\x0d\x0a\x1a\x0a";
protected const string PNG_HEADER = "\x89PNG\x0d\x0a\x1a\x0a";
public function decode(string &$data): Generator
{

View File

@ -8,9 +8,9 @@ use UnexpectedValueException;
class WebpDecoder implements DecoderInterface
{
protected const RIFF_HEADER = 'RIFF';
protected const string RIFF_HEADER = 'RIFF';
protected const WEBP_HEADER = 'WEBP';
protected const string WEBP_HEADER = 'WEBP';
public function decode(string &$data): Generator
{

View File

@ -7,9 +7,9 @@ use Stringable;
class ExifDateTime extends DateTimeImmutable implements Stringable
{
public const EXIF = 'Y:m:d H:i:s';
public const string EXIF = 'Y:m:d H:i:s';
public const EXIF_EXTENDED = self::EXIF . '.uP';
public const string EXIF_EXTENDED = self::EXIF . '.uP';
public function __toString(): string
{

View File

@ -8,19 +8,22 @@ use UnexpectedValueException;
class ExifReader
{
protected const EXIF_LITTLE_ENDIAN = 'II';
protected const string EXIF_LITTLE_ENDIAN = 'II';
protected const EXIF_BIG_ENDIAN = 'MM';
protected const string EXIF_BIG_ENDIAN = 'MM';
protected const EXIF_ENCODING_ASCII = "ASCII\x00\x00\x00";
protected const string EXIF_ENCODING_ASCII = "ASCII\x00\x00\x00";
protected const EXIF_ENCODING_JIS = "JIS\x00\x00\x00\x00\x00";
protected const string EXIF_ENCODING_JIS = "JIS\x00\x00\x00\x00\x00";
protected const EXIF_ENCODING_UNICODE = "UNICODE\x00";
protected const string EXIF_ENCODING_UNICODE = "UNICODE\x00";
protected const EXIF_ENCODING_UNDEFINED = "\x00\x00\x00\x00\x00\x00\x00\x00";
protected const string EXIF_ENCODING_UNDEFINED = "\x00\x00\x00\x00\x00\x00\x00\x00";
protected const IGNORED_SECTIONS = [
/**
* @var list<string>
*/
protected const array IGNORED_SECTIONS = [
'FileName',
'FileDateTime',
'FileSize',
@ -34,7 +37,10 @@ class ExifReader
'InteroperabilityOffset',
];
protected const UNDEFINED_TAGS_TO_EXIF_TAGS = [
/**
* @var array<string, string>
*/
protected const array UNDEFINED_TAGS_TO_EXIF_TAGS = [
'UndefinedTag:0x001F' => 'GPSHPositioningError',
'UndefinedTag:0x9010' => 'OffsetTime',
'UndefinedTag:0x9011' => 'OffsetTimeOriginal',
@ -60,7 +66,10 @@ class ExifReader
'UndefinedTag:0xA435' => 'LensSerialNumber',
];
protected const TAG_ALIASES = [
/**
* @var array<string, string>
*/
protected const array TAG_ALIASES = [
'SpectralSensity' => 'SpectralSensitivity',
'ISOSpeedRatings' => 'PhotographicSensitivity',
'SubjectLocation' => 'SubjectArea',

View File

@ -14,7 +14,7 @@ use UnexpectedValueException;
class GifHandler extends AbstractHandler
{
protected const NETSCAPE_EXT_HEADER = "!\xff\x0bNETSCAPE2.0";
protected const string NETSCAPE_EXT_HEADER = "!\xff\x0bNETSCAPE2.0";
public function getInfo(): ImageInfo
{

View File

@ -13,11 +13,11 @@ use UnexpectedValueException;
class JpegHandler extends AbstractHandler
{
protected const MAX_BYTES_IN_SEGMENT = 65533;
protected const int MAX_BYTES_IN_SEGMENT = 65533;
protected const EXIF_HEADER = "Exif\x00\x00";
protected const string EXIF_HEADER = "Exif\x00\x00";
protected const ICC_PROFILE_HEADER = "ICC_PROFILE\x00";
protected const string ICC_PROFILE_HEADER = "ICC_PROFILE\x00";
public function getInfo(): ImageInfo
{

View File

@ -14,15 +14,15 @@ use UnexpectedValueException;
class WebpHandler extends AbstractHandler
{
protected const RIFF_HEADER = 'RIFF';
protected const string RIFF_HEADER = 'RIFF';
protected const NO_FLAG = 0b00000000;
protected const int NO_FLAG = 0b00000000;
protected const ALPHA_FLAG = 0b00010000;
protected const int ALPHA_FLAG = 0b00010000;
protected const ICC_FLAG = 0b00100000;
protected const int ICC_FLAG = 0b00100000;
protected const EXIF_FLAG = 0b00001000;
protected const int EXIF_FLAG = 0b00001000;
public function getInfo(): ImageInfo
{

View File

@ -39,9 +39,9 @@ use RuntimeException;
class Image extends File
{
protected const MODEL_IDENTIFIER = 'image';
protected const string MODEL_IDENTIFIER = 'image';
protected const SCHEME_IDENTIFIER = 'files.image';
protected const string SCHEME_IDENTIFIER = 'files.image';
#[ReadonlyModelProperty]
protected AbstractHandler $handler;

View File

@ -11,8 +11,10 @@ class Blur extends AbstractTransform
{
/**
* Convolution kernels used for image effects
*
* @var array<string, array<list<float>>>
*/
protected const CONVOLUTION_KERNELS = [
protected const array CONVOLUTION_KERNELS = [
BlurMode::Smooth->value => [
[0.075, 0.125, 0.075],
[0.125, 0.200, 0.125],

View File

@ -7,7 +7,12 @@ use GdImage;
class Flip extends AbstractTransform
{
protected const DIRECTIONS = [
/**
* Flip directions
*
* @var array<string, int>
*/
protected const array DIRECTIONS = [
'Horizontal' => IMG_FLIP_HORIZONTAL,
'Vertical' => IMG_FLIP_VERTICAL,
'Both' => IMG_FLIP_BOTH,

View File

@ -9,7 +9,7 @@ abstract class AbstractNode implements Stringable
/**
* Node type
*/
public const TYPE = 'node';
public const string TYPE = 'node';
/**
* Node value

View File

@ -7,7 +7,7 @@ class ArgumentsNode extends AbstractNode
/**
* @inheritdoc
*/
public const TYPE = 'arguments';
public const string TYPE = 'arguments';
/**
* @param list<AbstractNode> $value

View File

@ -7,7 +7,7 @@ class ArrayKeysNode extends AbstractNode
/**
* @inheritdoc
*/
public const TYPE = 'array keys';
public const string TYPE = 'array keys';
/**
* @param list<array-key> $value

View File

@ -7,7 +7,7 @@ class ArrayNode extends AbstractNode
/**
* @inheritdoc
*/
public const TYPE = 'array';
public const string TYPE = 'array';
/**
* @param list<mixed> $value

View File

@ -7,7 +7,7 @@ class IdentifierNode extends AbstractNode
/**
* @inheritdoc
*/
public const TYPE = 'identifier';
public const string TYPE = 'identifier';
public function __construct(string $value, protected ?ArgumentsNode $argumentsNode, protected ?AbstractNode $node)
{

View File

@ -7,5 +7,5 @@ class ImplicitArrayKeyNode extends AbstractNode
/**
* @inheritdoc
*/
public const TYPE = 'implicit array key';
public const string TYPE = 'implicit array key';
}

View File

@ -7,7 +7,7 @@ class NumberNode extends AbstractNode
/**
* @inheritdoc
*/
public const TYPE = 'number';
public const string TYPE = 'number';
public function __construct(float|int $value)
{

View File

@ -7,7 +7,7 @@ class StringNode extends AbstractNode
/**
* @inheritdoc
*/
public const TYPE = 'string';
public const string TYPE = 'string';
public function __construct(string $value)
{

View File

@ -9,32 +9,32 @@ class Token implements Stringable
/**
* Identifier token type
*/
public const TYPE_IDENTIFIER = 'identifier';
public const string TYPE_IDENTIFIER = 'identifier';
/**
* Number token type
*/
public const TYPE_NUMBER = 'number';
public const string TYPE_NUMBER = 'number';
/**
* String token type
*/
public const TYPE_STRING = 'string';
public const string TYPE_STRING = 'string';
/**
* Punctuation token type
*/
public const TYPE_PUNCTUATION = 'punctuation';
public const string TYPE_PUNCTUATION = 'punctuation';
/**
* Arrow token type
*/
public const TYPE_ARROW = 'arrow';
public const string TYPE_ARROW = 'arrow';
/**
* End token type
*/
public const TYPE_END = 'end';
public const string TYPE_END = 'end';
public function __construct(protected string $type, protected ?string $value, protected int $position)
{

View File

@ -9,32 +9,32 @@ class Tokenizer implements TokenizerInterface
/**
* Regex matching identifier tokens
*/
protected const IDENTIFIER_REGEX = '/[A-Za-z_][A-Za-z0-9_]*/A';
protected const string IDENTIFIER_REGEX = '/[A-Za-z_][A-Za-z0-9_]*/A';
/**
* Regex matching number tokens
*/
protected const NUMBER_REGEX = '/[+-]?[0-9]+(.[0-9]+)?([Ee][+-]?[0-9]+)?/A';
protected const string NUMBER_REGEX = '/[+-]?[0-9]+(.[0-9]+)?([Ee][+-]?[0-9]+)?/A';
/**
* Regex matching single quote string tokens
*/
protected const SINGLE_QUOTE_STRING_REGEX = '/\'(?:[^\'\\\]|\\\.)*\'/A';
protected const string SINGLE_QUOTE_STRING_REGEX = '/\'(?:[^\'\\\]|\\\.)*\'/A';
/**
* Regex matching double quote string tokens
*/
protected const DOUBLE_QUOTE_STRING_REGEX = '/"(?:[^"\\\]|\\\.)*"/A';
protected const string DOUBLE_QUOTE_STRING_REGEX = '/"(?:[^"\\\]|\\\.)*"/A';
/**
* Punctuation characters
*/
protected const PUNCTUATION_CHARACTERS = '.,()[]';
protected const string PUNCTUATION_CHARACTERS = '.,()[]';
/**
* Arrow sequence
*/
protected const ARROW_SEQUENCE = '=>';
protected const string ARROW_SEQUENCE = '=>';
/**
* Tokenizer input length

View File

@ -11,8 +11,10 @@ class LanguageCodes
/**
* All available language codes
*
* @var array<string, array{name: string, native: string, rtl?: bool, continents: list<'AF'|'AS'|'EU'|'NA'|'OC'|'SA'>}>
*/
protected const LANGUAGE_CODES = [
protected const array LANGUAGE_CODES = [
'af' => ['name' => 'Afrikaans', 'native' => 'Afrikaans', 'continents' => ['AF']],
'am' => ['name' => 'Amharic', 'native' => 'አማርኛ', 'continents' => ['AF']],
'ar' => ['name' => 'Arabic', 'native' => 'العربية', 'rtl' => true, 'continents' => ['AF', 'AS']],

View File

@ -7,7 +7,12 @@ use Stringable;
class Metadata implements Stringable
{
protected const HTTP_EQUIV_NAMES = ['content-type', 'default-style', 'refresh'];
/**
* List of metadata names that are http-equiv directives
*
* @var list<string>
*/
protected const array HTTP_EQUIV_NAMES = ['content-type', 'default-style', 'refresh'];
/**
* Metadata name

View File

@ -18,10 +18,7 @@ class Model implements Arrayable
use DataMultipleGetter;
use DataMultipleSetter;
/**
* @var string
*/
protected const MODEL_IDENTIFIER = 'model';
protected const string MODEL_IDENTIFIER = 'model';
protected Scheme $scheme;

View File

@ -41,39 +41,43 @@ class Page extends Model implements Stringable
/**
* Page num regex
*/
public const NUM_REGEX = '/^(\d+)-/';
public const string NUM_REGEX = '/^(\d+)-/';
/**
* Page `published` status
*/
public const PAGE_STATUS_PUBLISHED = 'published';
public const string PAGE_STATUS_PUBLISHED = 'published';
/**
* Page `not published` status
*/
public const PAGE_STATUS_NOT_PUBLISHED = 'notPublished';
public const string PAGE_STATUS_NOT_PUBLISHED = 'notPublished';
protected const MODEL_IDENTIFIER = 'page';
protected const string MODEL_IDENTIFIER = 'page';
/**
* Ignored field names on frontmatter generation
*
* @var list<string>
*/
protected const IGNORED_FIELD_NAMES = ['content', 'slug', 'template', 'parent'];
protected const array IGNORED_FIELD_NAMES = ['content', 'slug', 'template', 'parent'];
/**
* Ignored field types on frontmatter generation
*
* @var list<string>
*/
protected const IGNORED_FIELD_TYPES = ['upload'];
protected const array IGNORED_FIELD_TYPES = ['upload'];
/**
* Slug regex
*/
protected const SLUG_REGEX = '/^[a-z0-9]+(?:-[a-z0-9]+)*$/i';
protected const string SLUG_REGEX = '/^[a-z0-9]+(?:-[a-z0-9]+)*$/i';
/**
* Datetime format used for page numbering with `date` mode
*/
protected const DATE_NUM_FORMAT = 'Ymd';
protected const string DATE_NUM_FORMAT = 'Ymd';
/**
* Page path

View File

@ -8,9 +8,9 @@ use Formwork\Utils\FileSystem;
class ContentHistory
{
public const HISTORY_FILENAME = '.history';
public const string HISTORY_FILENAME = '.history';
public const HISTORY_DEFAULT_LIMIT = 1;
public const int HISTORY_DEFAULT_LIMIT = 1;
protected ContentHistoryItemCollection $items;

View File

@ -15,7 +15,7 @@ use Formwork\Utils\FileSystem;
class AuthenticationController extends AbstractController
{
public const SESSION_REDIRECT_KEY = '_formwork_redirect_to';
public const string SESSION_REDIRECT_KEY = '_formwork_redirect_to';
/**
* Authentication@login action

View File

@ -17,7 +17,7 @@ use Formwork\Utils\Uri;
final class Panel
{
protected const CSRF_TOKEN_NAME = 'panel';
protected const string CSRF_TOKEN_NAME = 'panel';
/**
* Assets instance

View File

@ -7,17 +7,19 @@ class Json extends AbstractEncoder
/**
* Default flags used to parse JSON
*/
protected const DEFAULT_PARSE_FLAGS = JSON_THROW_ON_ERROR;
protected const int DEFAULT_PARSE_FLAGS = JSON_THROW_ON_ERROR;
/**
* Default flags used to encode JSON
*/
protected const DEFAULT_ENCODE_FLAGS = JSON_UNESCAPED_SLASHES | JSON_PRESERVE_ZERO_FRACTION | JSON_THROW_ON_ERROR;
protected const int DEFAULT_ENCODE_FLAGS = JSON_UNESCAPED_SLASHES | JSON_PRESERVE_ZERO_FRACTION | JSON_THROW_ON_ERROR;
/**
* Default options used to encode JSON
*
* @var array{forceObject: bool, prettyPrint: bool, escapeUnicode: bool}
*/
protected const DEFAULT_ENCODE_OPTIONS = [
protected const array DEFAULT_ENCODE_OPTIONS = [
'forceObject' => false,
'prettyPrint' => false,
'escapeUnicode' => false,
@ -39,7 +41,7 @@ class Json extends AbstractEncoder
* Encode data to JSON format
*
* @param array<mixed> $data
* @param array<string, mixed> $options
* @param array{forceObject?: bool, prettyPrint?: bool, escapeUnicode?: bool} $options
*/
public static function encode($data, array $options = []): string
{

View File

@ -15,12 +15,14 @@ class Php extends AbstractEncoder
/**
* Number of spaces used to indent arrays
*/
protected const INDENT_SPACES = 4;
protected const int INDENT_SPACES = 4;
/**
* Class names of objects which cannot be encoded
*
* @var array<class-string>
*/
protected const UNENCODABLE_CLASSES = [\Closure::class, \Reflector::class, \ReflectionGenerator::class, \ReflectionType::class, \IteratorIterator::class, \RecursiveIteratorIterator::class];
protected const array UNENCODABLE_CLASSES = [\Closure::class, \Reflector::class, \ReflectionGenerator::class, \ReflectionType::class, \IteratorIterator::class, \RecursiveIteratorIterator::class];
/**
* @inheritdoc

View File

@ -6,16 +6,6 @@ use Symfony\Component\Yaml\Yaml as SymfonyYaml;
class Yaml extends AbstractEncoder
{
/**
* Document start delimiter required by yaml_parse()
*/
protected const DOCUMENT_START = "---\n";
/**
* Regex matching document delimiters to be removed from yaml_emit() output
*/
protected const DOCUMENT_DELIMITERS_REGEX = '/^-{3}[\n ]|\n\.{3}$/';
/**
* Parse a YAML string
*

View File

@ -8,13 +8,17 @@ class Route
{
/**
* Default route methods
*
* @var list<value-of<Router::REQUEST_METHODS>>
*/
protected const DEFAULT_METHODS = ['GET'];
protected const array DEFAULT_METHODS = ['GET'];
/**
* Default route types
*
* @var list<value-of<Router::REQUEST_TYPES>>
*/
protected const DEFAULT_TYPES = ['HTTP'];
protected const array DEFAULT_TYPES = ['HTTP'];
/**
* Route action

View File

@ -8,13 +8,17 @@ class RouteFilter
{
/**
* Default filter methods
*
* @var list<value-of<Router::REQUEST_METHODS>>
*/
protected const DEFAULT_METHODS = ['GET'];
protected const array DEFAULT_METHODS = ['GET'];
/**
* Default filter types
*
* @var list<value-of<Router::REQUEST_TYPES>>
*/
protected const DEFAULT_TYPES = ['HTTP'];
protected const array DEFAULT_TYPES = ['HTTP'];
/**
* Filter action

View File

@ -21,28 +21,34 @@ class Router
{
/**
* Valid request types
*
* @var list<string>
*/
protected const REQUEST_TYPES = ['HTTP', 'XHR'];
protected const array REQUEST_TYPES = ['HTTP', 'XHR'];
/**
* Valid request methods
*
* @var list<string>
*/
protected const REQUEST_METHODS = ['HEAD', 'GET', 'POST', 'PUT', 'PATCH', 'DELETE'];
protected const array REQUEST_METHODS = ['HEAD', 'GET', 'POST', 'PUT', 'PATCH', 'DELETE'];
/**
* Valid param separators
*/
protected const PARAMS_SEPARATORS = '/,;.:-_';
protected const string PARAMS_SEPARATORS = '/,;.:-_';
/**
* Route params regex
*/
protected const PARAMS_REGEX = '~([' . self::PARAMS_SEPARATORS . '])?{([A-Za-z0-9_]+)(?::([^{]+))?}(\?)?~';
protected const string PARAMS_REGEX = '~([' . self::PARAMS_SEPARATORS . '])?{([A-Za-z0-9_]+)(?::([^{]+))?}(\?)?~';
/**
* Array containing route patterns shortcuts
*
* @var array<string, string>
*/
protected const PATTERN_SHORTCUTS = [
protected const array PATTERN_SHORTCUTS = [
'all' => '[^?#]+',
'any' => '[^/?#]+',
'slug' => '[A-Za-z0-9]+(?:-[A-Za-z0-9]+)*',

View File

@ -4,7 +4,10 @@ namespace Formwork\Sanitizer\Reference;
class HtmlReference
{
public const ALLOWED_ELEMENTS = [
/**
* @var list<string>
*/
public const array ALLOWED_ELEMENTS = [
'a',
'abbr',
'acronym',
@ -135,7 +138,10 @@ class HtmlReference
'xmp',
];
public const ALLOWED_ATTRIBUTES = [
/**
* @var list<string>
*/
public const array ALLOWED_ATTRIBUTES = [
'abbr',
'accept-charset',
'accept',
@ -352,7 +358,10 @@ class HtmlReference
'wrap',
];
public const URI_ATTRIBUTES = [
/**
* @var list<string>
*/
public const array URI_ATTRIBUTES = [
'action',
'src',
'href',

View File

@ -4,9 +4,12 @@ namespace Formwork\Sanitizer\Reference;
class SvgReference
{
public const NAMESPACE_URI = 'http://www.w3.org/2000/svg';
public const string NAMESPACE_URI = 'http://www.w3.org/2000/svg';
public const ALLOWED_ELEMENTS = [
/**
* @var list<string>
*/
public const array ALLOWED_ELEMENTS = [
'a',
'animate',
'animateMotion',
@ -77,7 +80,10 @@ class SvgReference
'vkern',
];
public const ALLOWED_ATTRIBUTES = [
/**
* @var list<string>
*/
public const array ALLOWED_ATTRIBUTES = [
'accent-height',
'accumulate',
'additive',
@ -298,7 +304,10 @@ class SvgReference
'zoomAndPan',
];
public const URI_ATTRIBUTES = [
/**
* @var list<string>
*/
public const array URI_ATTRIBUTES = [
'src',
'href',
'xlink:href',

View File

@ -9,7 +9,7 @@ class CsrfToken
/**
* Session key to store the CSRF token
*/
protected const SESSION_KEY_PREFIX = '_formwork_csrf_tokens';
protected const string SESSION_KEY_PREFIX = '_formwork_csrf_tokens';
public function __construct(protected Request $request)
{

View File

@ -26,7 +26,7 @@ class Site extends Model implements Stringable
use PageUid;
use PageUri;
protected const MODEL_IDENTIFIER = 'site';
protected const string MODEL_IDENTIFIER = 'site';
/**
* Site path

View File

@ -17,32 +17,32 @@ class Statistics
/**
* Date format
*/
protected const DATE_FORMAT = 'Ymd';
protected const string DATE_FORMAT = 'Ymd';
/**
* Number of days displayed in the statistics chart
*/
protected const CHART_LIMIT = 7;
protected const int CHART_LIMIT = 7;
/**
* Visits registry filename
*/
protected const VISITS_FILENAME = 'visits.json';
protected const string VISITS_FILENAME = 'visits.json';
/**
* Unique visits registry filename
*/
protected const UNIQUE_VISITS_FILENAME = 'uniqueVisits.json';
protected const string UNIQUE_VISITS_FILENAME = 'uniqueVisits.json';
/**
* Visitors registry filename
*/
protected const VISITORS_FILENAME = 'visitors.json';
protected const string VISITORS_FILENAME = 'visitors.json';
/**
* Page views registry filename
*/
protected const PAGE_VIEWS_FILENAME = 'pageViews.json';
protected const string PAGE_VIEWS_FILENAME = 'pageViews.json';
/**
* Visits registry

View File

@ -19,12 +19,12 @@ class Updater
/**
* GitHub repository from which updates are retrieved
*/
protected const REPOSITORY = 'getformwork/formwork';
protected const string REPOSITORY = 'getformwork/formwork';
/**
* GitHub API latest release URI
*/
protected const API_RELEASE_URI = 'https://api.github.com/repos/' . self::REPOSITORY . '/releases/latest';
protected const string API_RELEASE_URI = 'https://api.github.com/repos/' . self::REPOSITORY . '/releases/latest';
/**
* Updater options

View File

@ -18,9 +18,9 @@ use SensitiveParameter;
class User extends Model
{
public const SESSION_LOGGED_USER_KEY = '_formwork_logged_user';
public const string SESSION_LOGGED_USER_KEY = '_formwork_logged_user';
protected const MODEL_IDENTIFIER = 'user';
protected const string MODEL_IDENTIFIER = 'user';
/**
* Default data of the user

View File

@ -10,18 +10,24 @@ class Constraint
/**
* Values considered true when parsed as boolean
*
* @var list<mixed>
*/
public const TRUTHY_VALUES = [true, 1, 'true', '1', 'on', 'yes'];
public const array TRUTHY_VALUES = [true, 1, 'true', '1', 'on', 'yes'];
/**
* Values considered false when parsed as boolean
*
* @var list<mixed>
*/
public const FALSY_VALUES = [false, 0, 'false', '0', 'off', 'no'];
public const array FALSY_VALUES = [false, 0, 'false', '0', 'off', 'no'];
/**
* Values considered null when parsed as such
*
* @var list<mixed>
*/
public const EMPTY_VALUES = [null, '', []];
public const array EMPTY_VALUES = [null, '', []];
/**
* Return whether a value is considered true when parsed as boolean

View File

@ -16,33 +16,59 @@ class Date
/**
* Characters used in formats accepted by date()
*/
protected const DATE_FORMAT_CHARACTERS = 'AaBcDdeFgGHhIijlLMmnNoOpPrsSTtUuvWwyYzZ';
protected const string DATE_FORMAT_CHARACTERS = 'AaBcDdeFgGHhIijlLMmnNoOpPrsSTtUuvWwyYzZ';
/**
* Regex used to parse formats accepted by date()
*/
protected const DATE_FORMAT_REGEX = '/(?P<escaped>(?:\\\[A-Za-z])+)|[' . self::DATE_FORMAT_CHARACTERS . ']|(?P<invalid>[A-Za-z])/';
protected const string DATE_FORMAT_REGEX = '/(?P<escaped>(?:\\\[A-Za-z])+)|[' . self::DATE_FORMAT_CHARACTERS . ']|(?P<invalid>[A-Za-z])/';
/**
* Regex used to parse date patterns like 'DD/MM/YYYY hh:mm:ss'
*/
protected const PATTERN_REGEX = '/(?:\[(?P<escaped>[^\]]+)\])|[YR]{4}|uuu|[YR]{2}|[MD]{1,4}|[WHhms]{1,2}|[AaZz]|(?P<invalid>[A-Za-z]+)/';
protected const string PATTERN_REGEX = '/(?:\[(?P<escaped>[^\]]+)\])|[YR]{4}|uuu|[YR]{2}|[MD]{1,4}|[WHhms]{1,2}|[AaZz]|(?P<invalid>[A-Za-z]+)/';
/**
* Array used to translate pattern tokens to their date() format counterparts
*
* @var array<string, string>
*/
protected const PATTERN_TO_DATE_FORMAT = [
'YY' => 'y', 'YYYY' => 'Y', 'M' => 'n', 'MM' => 'm', 'MMM' => 'M', 'MMMM' => 'F',
'D' => 'j', 'DD' => 'd', 'DDD' => 'D', 'DDDD' => 'l', 'W' => 'W', 'WW' => 'W',
'RR' => 'o', 'RRRR' => 'o', 'H' => 'g', 'HH' => 'h', 'h' => 'G', 'hh' => 'H',
'm' => 'i', 'mm' => 'i', 's' => 's', 'ss' => 's', 'uuu' => 'v', 'A' => 'A',
'a' => 'a', 'Z' => 'P', 'z' => 'O',
protected const array PATTERN_TO_DATE_FORMAT = [
'YY' => 'y',
'YYYY' => 'Y',
'M' => 'n',
'MM' => 'm',
'MMM' => 'M',
'MMMM' => 'F',
'D' => 'j',
'DD' => 'd',
'DDD' => 'D',
'DDDD' => 'l',
'W' => 'W',
'WW' => 'W',
'RR' => 'o',
'RRRR' => 'o',
'H' => 'g',
'HH' => 'h',
'h' => 'G',
'hh' => 'H',
'm' => 'i',
'mm' => 'i',
's' => 's',
'ss' => 's',
'uuu' => 'v',
'A' => 'A',
'a' => 'a',
'Z' => 'P',
'z' => 'O',
];
/**
* Time intervals in seconds
*
* @var array<string, int>
*/
protected const TIME_INTERVALS = [
protected const array TIME_INTERVALS = [
'years' => 60 * 60 * 24 * 365,
'months' => 60 * 60 * 24 * 30,
'weeks' => 60 * 60 * 24 * 7,

View File

@ -8,7 +8,7 @@ use UnitEnum;
class Debug
{
protected const INDENT_SPACES = 2;
protected const int INDENT_SPACES = 2;
protected static string $css = <<<'CSS'
.__formwork-dump {

View File

@ -15,57 +15,61 @@ class FileSystem
/**
* List only files flag
*/
public const LIST_FILES = 1;
public const int LIST_FILES = 1;
/**
* List only directories flag
*/
public const LIST_DIRECTORIES = 2;
public const int LIST_DIRECTORIES = 2;
/**
* List hidden files flag
*/
public const LIST_HIDDEN = 4;
public const int LIST_HIDDEN = 4;
/**
* List visible files and directories flag
*/
public const LIST_VISIBLE = self::LIST_FILES | self::LIST_DIRECTORIES;
public const int LIST_VISIBLE = self::LIST_FILES | self::LIST_DIRECTORIES;
/**
* List visible and hidden files and directories flag
*/
public const LIST_ALL = self::LIST_FILES | self::LIST_DIRECTORIES | self::LIST_HIDDEN;
public const int LIST_ALL = self::LIST_FILES | self::LIST_DIRECTORIES | self::LIST_HIDDEN;
/**
* Maximum path length provided by the system
*/
public const MAX_PATH_LENGTH = PHP_MAXPATHLEN - 2;
public const int MAX_PATH_LENGTH = PHP_MAXPATHLEN - 2;
/**
* Maximum directory or filename length
*/
public const MAX_NAME_LENGTH = 255;
public const int MAX_NAME_LENGTH = 255;
/**
* Default mode for created files
*/
protected const DEFAULT_FILE_MODE = 0o666;
protected const int DEFAULT_FILE_MODE = 0o666;
/**
* Default mode for created directories
*/
protected const DEFAULT_DIRECTORY_MODE = 0o777;
protected const int DEFAULT_DIRECTORY_MODE = 0o777;
/**
* Array containing files to ignore
*
* @var list<string>
*/
protected const IGNORED_FILES = ['.', '..'];
protected const array IGNORED_FILES = ['.', '..'];
/**
* Array containing units of measurement for human-readable file sizes
*
* @var list<string>
*/
protected const FILE_SIZE_UNITS = ['B', 'KB', 'MB', 'GB', 'TB'];
protected const array FILE_SIZE_UNITS = ['B', 'KB', 'MB', 'GB', 'TB'];
/**
* Normalize path slashes

View File

@ -13,9 +13,24 @@ class Html
* Void HTML elements without content and end tag
*
* @see https://html.spec.whatwg.org/multipage/syntax.html#void-elements
*
* @var list<string>
*/
protected const VOID_ELEMENTS = [
'area', 'base', 'br', 'col', 'embed', 'hr', 'img', 'input', 'link', 'meta', 'param', 'source', 'track', 'wbr',
protected const array VOID_ELEMENTS = [
'area',
'base',
'br',
'col',
'embed',
'hr',
'img',
'input',
'link',
'meta',
'param',
'source',
'track',
'wbr',
];
/**

View File

@ -14,9 +14,12 @@ class MimeType
/**
* Default MIME type for unknown files
*/
protected const DEFAULT_MIME_TYPE = 'application/octet-stream';
protected const string DEFAULT_MIME_TYPE = 'application/octet-stream';
protected const SAFE_PLAINTEXT_EXTENSIONS = ['css', 'js', 'html', 'htm', 'md', 'markdown', 'yaml', 'yml', 'json'];
/**
* @var list<key-of<MimeType::MIME_TYPES>>
*/
protected const array SAFE_PLAINTEXT_EXTENSIONS = ['css', 'js', 'html', 'htm', 'md', 'markdown', 'yaml', 'yml', 'json'];
/**
* Extension to MIME type mapping
@ -24,8 +27,10 @@ class MimeType
* Last updated: 2024-11-09
*
* @see scripts/update-mime-types.php To update this list
*
* @var array<string, string>
*/
protected const MIME_TYPES = [
protected const array MIME_TYPES = [
'ez' => 'application/andrew-inset',
'appinstaller' => 'application/appinstaller',
'aw' => 'application/applixware',

View File

@ -12,12 +12,12 @@ class Path
/**
* Default path separator (forward slash)
*/
protected const DEFAULT_SEPARATOR = '/';
protected const string DEFAULT_SEPARATOR = '/';
/**
* Regex matching multiple separators (forward and backward slash) to split paths into segments
*/
protected const SEPARATORS_REGEX = '~[/\\\]+~';
protected const string SEPARATORS_REGEX = '~[/\\\]+~';
/**
* Return whether a path is absolute

View File

@ -12,17 +12,21 @@ final class SemVer implements Stringable
*
* @see https://semver.org/
*/
protected const SEMVER_REGEX = '/^(?P<major>0|[1-9]\d*)\.(?P<minor>0|[1-9]\d*)\.(?P<patch>0|[1-9]\d*)(?:-(?P<prerelease>(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\+(?P<buildmetadata>[0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?$/';
protected const string SEMVER_REGEX = '/^(?P<major>0|[1-9]\d*)\.(?P<minor>0|[1-9]\d*)\.(?P<patch>0|[1-9]\d*)(?:-(?P<prerelease>(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\+(?P<buildmetadata>[0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?$/';
/**
* Valid operators to compare versions
*
* @var list<string>
*/
protected const COMPARISON_OPERATORS = ['<', '<=', '==', '>=', '>', '!=', '~', '^'];
protected const array COMPARISON_OPERATORS = ['<', '<=', '==', '>=', '>', '!=', '~', '^'];
/**
* Valid prerelease tags, compatible with version_compare()
*
* @var list<string>
*/
protected const PRERELEASE_TAGS = ['dev', 'alpha', 'beta', 'RC', 'pl'];
protected const array PRERELEASE_TAGS = ['dev', 'alpha', 'beta', 'RC', 'pl'];
public function __construct(protected int $major = 0, protected int $minor = 0, protected int $patch = 0, protected ?string $prerelease = null, protected ?string $buildMetadata = null)
{

View File

@ -13,15 +13,134 @@ class Str
/**
* Translate map to make slugs
*
* @var array<string, string>
*/
protected const SLUG_TRANSLATE_MAP = [
'\t' => '', '\r' => '', '!' => '', '"' => '', '#' => '', '$' => '', '%' => '', '\'' => '-', '(' => '', ')' => '', '*' => '', '+' => '', ',' => '', '.' => '', ':' => '', ';' => '', '<' => '', '=' => '', '>' => '', '?' => '', '@' => '', '[' => '', ']' => '', '^' => '', '`' => '', '{' => '', '|' => '', '}' => '', '¡' => '', '£' => '', '¤' => '', '¥' => '', '¦' => '', '§' => '', '«' => '', '°' => '', '»' => '', '' => '', '' => '', '“' => '', '”' => '', '\n' => '-', ' ' => '-', '-' => '-', '' => '-', '—' => '-', '/' => '-', '\\' => '-', '_' => '-', '~' => '-', 'À' => 'A', 'Á' => 'A', 'Â' => 'A', 'Ã' => 'A', 'Ä' => 'A', 'Å' => 'A', 'Æ' => 'Ae', 'Ç' => 'C', 'Ð' => 'D', 'È' => 'E', 'É' => 'E', 'Ê' => 'E', 'Ë' => 'E', 'Ì' => 'I', 'Í' => 'I', 'Î' => 'I', 'Ï' => 'I', 'Ñ' => 'N', 'Ò' => 'O', 'Ó' => 'O', 'Ô' => 'O', 'Õ' => 'O', 'Ö' => 'O', 'Ø' => 'O', 'Œ' => 'Oe', 'Š' => 'S', 'Þ' => 'Th', 'Ù' => 'U', 'Ú' => 'U', 'Û' => 'U', 'Ü' => 'U', 'Ý' => 'Y', 'à' => 'a', 'á' => 'a', 'â' => 'a', 'ã' => 'a', 'ä' => 'ae', 'å' => 'a', 'æ' => 'ae', '¢' => 'c', 'ç' => 'c', 'ð' => 'd', 'è' => 'e', 'é' => 'e', 'ê' => 'e', 'ë' => 'e', 'ì' => 'i', 'í' => 'i', 'î' => 'i', 'ï' => 'i', 'ñ' => 'n', 'ò' => 'o', 'ó' => 'o', 'ô' => 'o', 'õ' => 'o', 'ö' => 'oe', 'ø' => 'o', 'œ' => 'oe', 'š' => 's', 'ß' => 'ss', 'þ' => 'th', 'ù' => 'u', 'ú' => 'u', 'û' => 'u', 'ü' => 'ue', 'ý' => 'y', 'ÿ' => 'y', 'Ÿ' => 'y',
protected const array SLUG_TRANSLATE_MAP = [
'\t' => '',
'\r' => '',
'!' => '',
'"' => '',
'#' => '',
'$' => '',
'%' => '',
'\'' => '-',
'(' => '',
')' => '',
'*' => '',
'+' => '',
',' => '',
'.' => '',
':' => '',
';' => '',
'<' => '',
'=' => '',
'>' => '',
'?' => '',
'@' => '',
'[' => '',
']' => '',
'^' => '',
'`' => '',
'{' => '',
'|' => '',
'}' => '',
'¡' => '',
'£' => '',
'¤' => '',
'¥' => '',
'¦' => '',
'§' => '',
'«' => '',
'°' => '',
'»' => '',
'' => '',
'' => '',
'“' => '',
'”' => '',
'\n' => '-',
' ' => '-',
'-' => '-',
'' => '-',
'—' => '-',
'/' => '-',
'\\' => '-',
'_' => '-',
'~' => '-',
'À' => 'A',
'Á' => 'A',
'Â' => 'A',
'Ã' => 'A',
'Ä' => 'A',
'Å' => 'A',
'Æ' => 'Ae',
'Ç' => 'C',
'Ð' => 'D',
'È' => 'E',
'É' => 'E',
'Ê' => 'E',
'Ë' => 'E',
'Ì' => 'I',
'Í' => 'I',
'Î' => 'I',
'Ï' => 'I',
'Ñ' => 'N',
'Ò' => 'O',
'Ó' => 'O',
'Ô' => 'O',
'Õ' => 'O',
'Ö' => 'O',
'Ø' => 'O',
'Œ' => 'Oe',
'Š' => 'S',
'Þ' => 'Th',
'Ù' => 'U',
'Ú' => 'U',
'Û' => 'U',
'Ü' => 'U',
'Ý' => 'Y',
'à' => 'a',
'á' => 'a',
'â' => 'a',
'ã' => 'a',
'ä' => 'ae',
'å' => 'a',
'æ' => 'ae',
'¢' => 'c',
'ç' => 'c',
'ð' => 'd',
'è' => 'e',
'é' => 'e',
'ê' => 'e',
'ë' => 'e',
'ì' => 'i',
'í' => 'i',
'î' => 'i',
'ï' => 'i',
'ñ' => 'n',
'ò' => 'o',
'ó' => 'o',
'ô' => 'o',
'õ' => 'o',
'ö' => 'oe',
'ø' => 'o',
'œ' => 'oe',
'š' => 's',
'ß' => 'ss',
'þ' => 'th',
'ù' => 'u',
'ú' => 'u',
'û' => 'u',
'ü' => 'ue',
'ý' => 'y',
'ÿ' => 'y',
'Ÿ' => 'y',
];
/**
* Regex to match interpolated sequences in strings
*/
protected const INTERPOLATION_REGEX = '/(\\\)?{{([\-._a-z]+)\\\?}}/i';
protected const string INTERPOLATION_REGEX = '/(\\\)?{{([\-._a-z]+)\\\?}}/i';
/**
* Return whether $haystack string starts with $needle

View File

@ -12,22 +12,22 @@ class Text
/**
* Regex matching whitespace characters
*/
protected const WHITESPACE_REGEX = '/[\s\xb\p{Z}]+/u';
protected const string WHITESPACE_REGEX = '/[\s\xb\p{Z}]+/u';
/**
* Normalized whitespace sequence
*/
protected const WHITESPACE_SEQUENCE = ' ';
protected const string WHITESPACE_SEQUENCE = ' ';
/**
* Default sequence appended when text is truncated
*/
protected const DEFAULT_ELLIPSIS_SEQUENCE = '…';
protected const string DEFAULT_ELLIPSIS_SEQUENCE = '…';
/**
* Default words per minute used to determine reading time
*/
protected const DEFAULT_WORDS_PER_MINUTE = 180;
protected const int DEFAULT_WORDS_PER_MINUTE = 180;
/**
* Normalize whitespace of a given text

View File

@ -12,8 +12,10 @@ class Uri
/**
* Default ports which will not be present in generated URI
*
* @var array<string, int>
*/
protected const DEFAULT_PORTS = ['http' => 80, 'https' => 443];
protected const array DEFAULT_PORTS = ['http' => 80, 'https' => 443];
/**
* Current URI

View File

@ -11,8 +11,10 @@ class ZipErrors
/**
* Human-readable ZipArchive error messages
*
* @var array<int, string>
*/
public const ERROR_MESSAGES = [
public const array ERROR_MESSAGES = [
ZipArchive::ER_MULTIDISK => 'Multi-disk zip archives not supported',
ZipArchive::ER_RENAME => 'Renaming temporary file failed',
ZipArchive::ER_CLOSE => 'Closing zip archive failed',
@ -40,8 +42,10 @@ class ZipErrors
/**
* ZipArchive errors language strings
*
* @var array<int, string>
*/
public const ERROR_LANGUAGE_STRINGS = [
public const array ERROR_LANGUAGE_STRINGS = [
ZipArchive::ER_MULTIDISK => 'zip.error.unspecified',
ZipArchive::ER_RENAME => 'zip.error.unspecified',
ZipArchive::ER_CLOSE => 'zip.error.unspecified',

View File

@ -17,7 +17,7 @@ class View
/**
* View type
*/
protected const TYPE = 'view';
protected const string TYPE = 'view';
/**
* View file