Version 5.1 - All the GraphQL #32

Closed
timw4mail wants to merge 1160 commits from develop into master
9 changed files with 314 additions and 310 deletions
Showing only changes of commit b13c35eaec - Show all commits

View File

@ -5,22 +5,12 @@ use PhpCsFixer\{Config, Finder};
$finder = Finder::create() $finder = Finder::create()
->in([ ->in([
__DIR__, __DIR__ . '/src',
__DIR__ . '/app', __DIR__ . '/tests',
__DIR__ . '/tools', __DIR__ . '/tools',
]) ])
->exclude([ ->exclude([
'apidocs',
'build',
'coverage',
'frontEndSrc',
'phinx',
'public',
'tools',
'tmp',
'vendor', 'vendor',
'views',
'templates',
]); ]);
return (new Config()) return (new Config())
@ -45,7 +35,7 @@ return (new Config())
'blank_line_after_opening_tag' => false, 'blank_line_after_opening_tag' => false,
'blank_line_before_statement' => [ 'blank_line_before_statement' => [
'statements' => [ 'statements' => [
'case', // 'case',
'continue', 'continue',
'declare', 'declare',
'default', 'default',
@ -128,12 +118,12 @@ return (new Config())
'noise_remaining_usages_exclude' => [], 'noise_remaining_usages_exclude' => [],
], ],
'escape_implicit_backslashes' => [ 'escape_implicit_backslashes' => [
'double_quoted' => true, 'double_quoted' => false,
'heredoc_syntax' => true, 'heredoc_syntax' => false,
'single_quoted' => false, 'single_quoted' => false,
], ],
'explicit_indirect_variable' => true, 'explicit_indirect_variable' => false,
'explicit_string_variable' => true, 'explicit_string_variable' => false,
'final_class' => false, 'final_class' => false,
'final_internal_class' => [ 'final_internal_class' => [
'annotation_exclude' => ['@no-final'], 'annotation_exclude' => ['@no-final'],
@ -167,7 +157,7 @@ return (new Config())
], ],
'group_import' => true, 'group_import' => true,
'header_comment' => false, // false by default 'header_comment' => false, // false by default
'heredoc_indentation' => ['indentation' => 'start_plus_one'], // 'heredoc_indentation' => ['indentation' => 'start_plus_one'],
'heredoc_to_nowdoc' => true, 'heredoc_to_nowdoc' => true,
'implode_call' => true, 'implode_call' => true,
'include' => true, 'include' => true,
@ -232,8 +222,7 @@ return (new Config())
'allow_unused_params' => true, 'allow_unused_params' => true,
'remove_inheritdoc' => false, 'remove_inheritdoc' => false,
], ],
'no_trailing_comma_in_list_call' => true, 'no_trailing_comma_in_singleline' => true,
'no_trailing_comma_in_singleline_array' => true,
'no_trailing_whitespace' => true, 'no_trailing_whitespace' => true,
'no_trailing_whitespace_in_comment' => true, 'no_trailing_whitespace_in_comment' => true,
'no_trailing_whitespace_in_string' => true, 'no_trailing_whitespace_in_string' => true,
@ -270,9 +259,16 @@ return (new Config())
'ordered_class_elements' => [ 'ordered_class_elements' => [
'order' => [ 'order' => [
'use_trait', 'use_trait',
'constant', 'case',
'property', 'constant_public',
'method', 'constant_protected',
'constant_private',
'property_public',
'property_protected',
'property_private',
'construct',
'destruct',
'magic',
], ],
'sort_algorithm' => 'none', 'sort_algorithm' => 'none',
], ],

View File

@ -42,6 +42,11 @@ class Controller
{ {
use ContainerAware; use ContainerAware;
/**
* The global configuration object
*/
public ConfigInterface $config;
/** /**
* The authentication object * The authentication object
*/ */
@ -52,11 +57,6 @@ class Controller
*/ */
protected CacheInterface $cache; protected CacheInterface $cache;
/**
* The global configuration object
*/
public ConfigInterface $config;
/** /**
* Request object * Request object
*/ */
@ -120,7 +120,7 @@ class Controller
Event::on(EventType::RESET_CACHE_KEY, fn (string $key) => $this->cache->delete($key)); Event::on(EventType::RESET_CACHE_KEY, fn (string $key) => $this->cache->delete($key));
} }
/** /**
* Set the current url in the session as the target of a future redirect * Set the current url in the session as the target of a future redirect
* *
* @throws ContainerException * @throws ContainerException
@ -128,37 +128,37 @@ class Controller
*/ */
#[\PHPUnit\Framework\Attributes\CodeCoverageIgnore] #[\PHPUnit\Framework\Attributes\CodeCoverageIgnore]
public function setSessionRedirect(?string $url = NULL): void public function setSessionRedirect(?string $url = NULL): void
{ {
$serverParams = $this->request->getServerParams(); $serverParams = $this->request->getServerParams();
if ( ! array_key_exists('HTTP_REFERER', $serverParams)) if ( ! array_key_exists('HTTP_REFERER', $serverParams))
{ {
return; return;
} }
$util = $this->container->get('util'); $util = $this->container->get('util');
$doubleFormPage = $serverParams['HTTP_REFERER'] === $this->request->getUri(); $doubleFormPage = $serverParams['HTTP_REFERER'] === $this->request->getUri();
$isLoginPage = str_contains($serverParams['HTTP_REFERER'], 'login'); $isLoginPage = str_contains($serverParams['HTTP_REFERER'], 'login');
// Don't attempt to set the redirect url if // Don't attempt to set the redirect url if
// the page is one of the form type pages, // the page is one of the form type pages,
// and the previous page is also a form type // and the previous page is also a form type
if ($doubleFormPage || $isLoginPage) if ($doubleFormPage || $isLoginPage)
{ {
return; return;
} }
if (NULL === $url) if (NULL === $url)
{ {
$url = $util->isViewPage() $url = $util->isViewPage()
? (string) $this->request->getUri() ? (string) $this->request->getUri()
: $serverParams['HTTP_REFERER']; : $serverParams['HTTP_REFERER'];
} }
$this->session->set('redirect_url', $url); $this->session->set('redirect_url', $url);
} }
/** /**
* Redirect to the url previously set in the session * Redirect to the url previously set in the session
* *
* If one is not set, redirect to default url * If one is not set, redirect to default url
@ -167,147 +167,147 @@ class Controller
*/ */
#[\PHPUnit\Framework\Attributes\CodeCoverageIgnore] #[\PHPUnit\Framework\Attributes\CodeCoverageIgnore]
public function sessionRedirect(): void public function sessionRedirect(): void
{ {
$target = $this->session->get('redirect_url') ?? '/'; $target = $this->session->get('redirect_url') ?? '/';
$this->redirect($target, 303); $this->redirect($target, 303);
$this->session->set('redirect_url', NULL); $this->session->set('redirect_url', NULL);
} }
/** /**
* Check if the current user is authenticated, else error and exit * Check if the current user is authenticated, else error and exit
*/ */
#[\PHPUnit\Framework\Attributes\CodeCoverageIgnore] #[\PHPUnit\Framework\Attributes\CodeCoverageIgnore]
protected function checkAuth(): void protected function checkAuth(): void
{ {
if ( ! $this->auth->isAuthenticated()) if ( ! $this->auth->isAuthenticated())
{ {
$this->errorPage( $this->errorPage(
403, 403,
'Forbidden', 'Forbidden',
'You must <a href="/login">log in</a> to perform this action.' 'You must <a href="/login">log in</a> to perform this action.'
); );
} }
} }
/** /**
* Get the string output of a partial template * Get the string output of a partial template
*/ */
#[\PHPUnit\Framework\Attributes\CodeCoverageIgnore] #[\PHPUnit\Framework\Attributes\CodeCoverageIgnore]
protected function loadPartial(HtmlView $view, string $template, array $data = []): string protected function loadPartial(HtmlView $view, string $template, array $data = []): string
{ {
$router = $this->container->get('dispatcher'); $router = $this->container->get('dispatcher');
if (isset($this->baseData)) if (isset($this->baseData))
{ {
$data = array_merge($this->baseData, $data); $data = array_merge($this->baseData, $data);
} }
$route = $router->getRoute(); $route = $router->getRoute();
$data['route_path'] = $route !== FALSE ? $route->path : ''; $data['route_path'] = $route !== FALSE ? $route->path : '';
$templatePath = _dir($this->config->get('view_path'), "{$template}.php"); $templatePath = _dir($this->config->get('view_path'), "{$template}.php");
if ( ! is_file($templatePath)) if ( ! is_file($templatePath))
{ {
throw new InvalidArgumentException("Invalid template : {$template}"); throw new InvalidArgumentException("Invalid template : {$template}");
} }
return $view->renderTemplate($templatePath, $data); return $view->renderTemplate($templatePath, $data);
} }
/** /**
* Render a template with header and footer * Render a template with header and footer
*/ */
#[\PHPUnit\Framework\Attributes\CodeCoverageIgnore] #[\PHPUnit\Framework\Attributes\CodeCoverageIgnore]
protected function renderFullPage(HtmlView $view, string $template, array $data): HtmlView protected function renderFullPage(HtmlView $view, string $template, array $data): HtmlView
{ {
$csp = [ $csp = [
"default-src 'self' media.kitsu.io kitsu-production-media.s3.us-west-002.backblazeb2.com", "default-src 'self' media.kitsu.io kitsu-production-media.s3.us-west-002.backblazeb2.com",
"object-src 'none'", "object-src 'none'",
"child-src 'self' *.youtube.com polyfill.io", "child-src 'self' *.youtube.com polyfill.io",
]; ];
$view->addHeader('Content-Security-Policy', implode('; ', $csp)); $view->addHeader('Content-Security-Policy', implode('; ', $csp));
$view->appendOutput($this->loadPartial($view, 'header', $data)); $view->appendOutput($this->loadPartial($view, 'header', $data));
if (array_key_exists('message', $data) && is_array($data['message'])) if (array_key_exists('message', $data) && is_array($data['message']))
{ {
$view->appendOutput($this->loadPartial($view, 'message', $data['message'])); $view->appendOutput($this->loadPartial($view, 'message', $data['message']));
} }
$view->appendOutput($this->loadPartial($view, $template, $data)); $view->appendOutput($this->loadPartial($view, $template, $data));
$view->appendOutput($this->loadPartial($view, 'footer', $data)); $view->appendOutput($this->loadPartial($view, 'footer', $data));
return $view; return $view;
} }
/** /**
* 404 action * 404 action
* *
* @throws InvalidArgumentException * @throws InvalidArgumentException
*/ */
#[\PHPUnit\Framework\Attributes\CodeCoverageIgnore] #[\PHPUnit\Framework\Attributes\CodeCoverageIgnore]
public function notFound( public function notFound(
string $title = 'Sorry, page not found', string $title = 'Sorry, page not found',
string $message = 'Page Not Found' string $message = 'Page Not Found'
): void { ): void {
$this->outputHTML('404', [ $this->outputHTML('404', [
'title' => $title, 'title' => $title,
'message' => $message, 'message' => $message,
], NULL, 404); ], NULL, 404);
exit(); exit();
} }
/** /**
* Display a generic error page * Display a generic error page
* *
* @throws InvalidArgumentException * @throws InvalidArgumentException
*/ */
#[\PHPUnit\Framework\Attributes\CodeCoverageIgnore] #[\PHPUnit\Framework\Attributes\CodeCoverageIgnore]
public function errorPage(int $httpCode, string $title, string $message, string $longMessage = ''): void public function errorPage(int $httpCode, string $title, string $message, string $longMessage = ''): void
{ {
$this->outputHTML('error', [ $this->outputHTML('error', [
'title' => $title, 'title' => $title,
'message' => $message, 'message' => $message,
'long_message' => $longMessage, 'long_message' => $longMessage,
], NULL, $httpCode); ], NULL, $httpCode);
} }
/** /**
* Redirect to the default controller/url from an empty path * Redirect to the default controller/url from an empty path
* *
* @throws InvalidArgumentException * @throws InvalidArgumentException
*/ */
#[\PHPUnit\Framework\Attributes\CodeCoverageIgnore] #[\PHPUnit\Framework\Attributes\CodeCoverageIgnore]
public function redirectToDefaultRoute(): void public function redirectToDefaultRoute(): void
{ {
$defaultType = $this->config->get('default_list'); $defaultType = $this->config->get('default_list');
$this->redirect($this->urlGenerator->defaultUrl($defaultType), 303); $this->redirect($this->urlGenerator->defaultUrl($defaultType), 303);
} }
/** /**
* Set a session flash variable to display a message on * Set a session flash variable to display a message on
* next page load * next page load
*/ */
#[\PHPUnit\Framework\Attributes\CodeCoverageIgnore] #[\PHPUnit\Framework\Attributes\CodeCoverageIgnore]
public function setFlashMessage(string $message, string $type = 'info'): void public function setFlashMessage(string $message, string $type = 'info'): void
{ {
static $messages; static $messages;
if ( ! $messages) if ( ! $messages)
{ {
$messages = []; $messages = [];
} }
$messages[] = [ $messages[] = [
'message_type' => $type, 'message_type' => $type,
'message' => $message, 'message' => $message,
]; ];
$this->session->setFlash('message', $messages); $this->session->setFlash('message', $messages);
} }
/** /**
* Helper for consistent page titles * Helper for consistent page titles
@ -319,38 +319,38 @@ class Controller
return implode(' &middot; ', $parts); return implode(' &middot; ', $parts);
} }
/** /**
* Add a message box to the page * Add a message box to the page
* *
* @throws InvalidArgumentException * @throws InvalidArgumentException
*/ */
#[\PHPUnit\Framework\Attributes\CodeCoverageIgnore] #[\PHPUnit\Framework\Attributes\CodeCoverageIgnore]
protected function showMessage(HtmlView $view, string $type, string $message): string protected function showMessage(HtmlView $view, string $type, string $message): string
{ {
return $this->loadPartial($view, 'message', [ return $this->loadPartial($view, 'message', [
'message_type' => $type, 'message_type' => $type,
'message' => $message, 'message' => $message,
]); ]);
} }
/** /**
* Output a template to HTML, using the provided data * Output a template to HTML, using the provided data
* *
* @throws InvalidArgumentException * @throws InvalidArgumentException
*/ */
#[\PHPUnit\Framework\Attributes\CodeCoverageIgnore] #[\PHPUnit\Framework\Attributes\CodeCoverageIgnore]
protected function outputHTML(string $template, array $data = [], ?HtmlView $view = NULL, int $code = 200): void protected function outputHTML(string $template, array $data = [], ?HtmlView $view = NULL, int $code = 200): void
{ {
if (NULL === $view) if (NULL === $view)
{ {
$view = new HtmlView($this->container); $view = new HtmlView($this->container);
} }
$view->setStatusCode($code); $view->setStatusCode($code);
$this->renderFullPage($view, $template, $data)->send(); $this->renderFullPage($view, $template, $data)->send();
} }
/** /**
* Output a JSON Response * Output a JSON Response
* *
* @param int $code - the http status code * @param int $code - the http status code
@ -358,23 +358,23 @@ class Controller
*/ */
#[\PHPUnit\Framework\Attributes\CodeCoverageIgnore] #[\PHPUnit\Framework\Attributes\CodeCoverageIgnore]
protected function outputJSON(mixed $data, int $code): void protected function outputJSON(mixed $data, int $code): void
{ {
JsonView::new() JsonView::new()
->setOutput($data) ->setOutput($data)
->setStatusCode($code) ->setStatusCode($code)
->send(); ->send();
} }
/** /**
* Redirect to the selected page * Redirect to the selected page
*/ */
#[\PHPUnit\Framework\Attributes\CodeCoverageIgnore] #[\PHPUnit\Framework\Attributes\CodeCoverageIgnore]
protected function redirect(string $url, int $code): void protected function redirect(string $url, int $code): void
{ {
HttpView::new() HttpView::new()
->redirect($url, $code) ->redirect($url, $code)
->send(); ->send();
} }
} }
// End of BaseController.php // End of BaseController.php

View File

@ -69,37 +69,6 @@ final class Dispatcher extends RoutingBase
$this->outputRoutes = $this->setupRoutes(); $this->outputRoutes = $this->setupRoutes();
} }
/**
* Get the current route object, if one matches
*/
public function getRoute(): Route|false
{
$logger = $this->container->getLogger();
$rawRoute = $this->request->getUri()->getPath();
$routePath = '/' . trim($rawRoute, '/');
if ($logger !== NULL)
{
$logger->info('Dispatcher - Routing data from get_route method');
$logger->info(print_r([
'route_path' => $routePath,
], TRUE));
}
return $this->matcher->match($this->request);
}
/**
* Get list of routes applied
*
* @return mixed[]
*/
public function getOutputRoutes(): array
{
return $this->outputRoutes;
}
/** /**
* Handle the current route * Handle the current route
* *
@ -141,6 +110,37 @@ final class Dispatcher extends RoutingBase
$this->call($controllerName, $actionMethod, $params); $this->call($controllerName, $actionMethod, $params);
} }
/**
* Get the current route object, if one matches
*/
public function getRoute(): Route|false
{
$logger = $this->container->getLogger();
$rawRoute = $this->request->getUri()->getPath();
$routePath = '/' . trim($rawRoute, '/');
if ($logger !== NULL)
{
$logger->info('Dispatcher - Routing data from get_route method');
$logger->info(print_r([
'route_path' => $routePath,
], TRUE));
}
return $this->matcher->match($this->request);
}
/**
* Get list of routes applied
*
* @return mixed[]
*/
public function getOutputRoutes(): array
{
return $this->outputRoutes;
}
/** /**
* Parse out the arguments for the appropriate controller for * Parse out the arguments for the appropriate controller for
* the current route * the current route

View File

@ -83,16 +83,16 @@ final class FormGenerator
]; ];
$params['strict'] = TRUE; $params['strict'] = TRUE;
unset($params['attribs']['id']); unset($params['attribs']['id']);
break; break;
case 'string': case 'string':
$params['type'] = 'text'; $params['type'] = 'text';
break; break;
case 'select': case 'select':
$params['type'] = 'select'; $params['type'] = 'select';
$params['options'] = array_flip($form['options']); $params['options'] = array_flip($form['options']);
break; break;
default: default:
break; break;

View File

@ -36,6 +36,19 @@ final class MenuGenerator extends UrlGenerator
*/ */
protected ServerRequestInterface $request; protected ServerRequestInterface $request;
/**
* MenuGenerator constructor.
*
* @throws ContainerException
* @throws NotFoundException
*/
private function __construct(ContainerInterface $container)
{
parent::__construct($container);
$this->helper = $container->get('html-helper');
$this->request = $container->get('request');
}
public static function new(ContainerInterface $container): self public static function new(ContainerInterface $container): self
{ {
return new self($container); return new self($container);
@ -80,19 +93,6 @@ final class MenuGenerator extends UrlGenerator
return (string) $this->helper->ul(); return (string) $this->helper->ul();
} }
/**
* MenuGenerator constructor.
*
* @throws ContainerException
* @throws NotFoundException
*/
private function __construct(ContainerInterface $container)
{
parent::__construct($container);
$this->helper = $container->get('html-helper');
$this->request = $container->get('request');
}
/** /**
* Generate the full menu structure from the config files * Generate the full menu structure from the config files
* *

View File

@ -20,37 +20,6 @@ use Stringable;
abstract class AbstractType implements ArrayAccess, Countable, Stringable abstract class AbstractType implements ArrayAccess, Countable, Stringable
{ {
/**
* Populate values for un-serializing data
*/
public static function __set_state(mixed $properties): self
{
return new static($properties);
}
/**
* Check the shape of the object, and return the array equivalent
*/
final public static function check(array $data = []): ?array
{
$currentClass = static::class;
if (get_parent_class($currentClass) !== FALSE)
{
return static::class::from($data)->toArray();
}
return NULL;
}
/**
* Static constructor
*/
final public static function from(mixed $data): static
{
return new static($data);
}
/** /**
* Sets the properties by using the constructor * Sets the properties by using the constructor
*/ */
@ -73,6 +42,14 @@ abstract class AbstractType implements ArrayAccess, Countable, Stringable
} }
} }
/**
* Populate values for un-serializing data
*/
public static function __set_state(mixed $properties): self
{
return new static($properties);
}
/** /**
* See if a property is set * See if a property is set
*/ */
@ -123,6 +100,29 @@ abstract class AbstractType implements ArrayAccess, Countable, Stringable
return print_r($this, TRUE); return print_r($this, TRUE);
} }
/**
* Check the shape of the object, and return the array equivalent
*/
final public static function check(array $data = []): ?array
{
$currentClass = static::class;
if (get_parent_class($currentClass) !== FALSE)
{
return static::class::from($data)->toArray();
}
return NULL;
}
/**
* Static constructor
*/
final public static function from(mixed $data): static
{
return new static($data);
}
/** /**
* Implementing ArrayAccess * Implementing ArrayAccess
*/ */
@ -203,23 +203,23 @@ abstract class AbstractType implements ArrayAccess, Countable, Stringable
#[\PHPUnit\Framework\Attributes\CodeCoverageIgnore] #[\PHPUnit\Framework\Attributes\CodeCoverageIgnore]
final protected function fromObject(mixed $parent = NULL): float|null|bool|int|array|string final protected function fromObject(mixed $parent = NULL): float|null|bool|int|array|string
{ {
$object = $parent ?? $this; $object = $parent ?? $this;
if (is_scalar($object) || $object === NULL) if (is_scalar($object) || $object === NULL)
{ {
return $object; return $object;
} }
$output = []; $output = [];
foreach ($object as $key => $value) foreach ($object as $key => $value)
{ {
$output[$key] = (is_scalar($value) || empty($value)) $output[$key] = (is_scalar($value) || empty($value))
? $value ? $value
: $this->fromObject((array) $value); : $this->fromObject((array) $value);
} }
return $output; return $output;
} }
} }

View File

@ -65,14 +65,6 @@ class ArrayType
'pop' => 'array_pop', 'pop' => 'array_pop',
]; ];
/**
* Create an ArrayType wrapper class from an array
*/
public static function from(array $arr): ArrayType
{
return new ArrayType($arr);
}
/** /**
* Create an ArrayType wrapper class * Create an ArrayType wrapper class
*/ */
@ -108,6 +100,14 @@ class ArrayType
throw new InvalidArgumentException("Method '{$method}' does not exist"); throw new InvalidArgumentException("Method '{$method}' does not exist");
} }
/**
* Create an ArrayType wrapper class from an array
*/
public static function from(array $arr): ArrayType
{
return new ArrayType($arr);
}
/** /**
* Does the passed key exist in the current array? * Does the passed key exist in the current array?
*/ */

View File

@ -41,7 +41,8 @@ use const MB_CASE_TITLE;
/** /**
* Vendored, slightly modernized version of Stringy * Vendored, slightly modernized version of Stringy
*/ */
abstract class Stringy implements Countable, IteratorAggregate, ArrayAccess { abstract class Stringy implements Countable, IteratorAggregate, ArrayAccess
{
/** /**
* An instance's string. * An instance's string.
*/ */
@ -80,10 +81,20 @@ abstract class Stringy implements Countable, IteratorAggregate, ArrayAccess {
); );
} }
$this->str = (string)$str; $this->str = (string) $str;
$this->encoding = $encoding ?: mb_internal_encoding(); $this->encoding = $encoding ?: mb_internal_encoding();
} }
/**
* Returns the value in $str.
*
* @return string The current value of the $str property
*/
public function __toString(): string
{
return $this->str;
}
/** /**
* Creates a Stringy object and assigns both str and encoding properties * Creates a Stringy object and assigns both str and encoding properties
* the supplied values. $str is cast to a string prior to assignment, and if * the supplied values. $str is cast to a string prior to assignment, and if
@ -93,25 +104,15 @@ abstract class Stringy implements Countable, IteratorAggregate, ArrayAccess {
* *
* @param mixed $str Value to modify, after being cast to string * @param mixed $str Value to modify, after being cast to string
* @param string|null $encoding The character encoding * @param string|null $encoding The character encoding
* @return static A Stringy object
* @throws InvalidArgumentException if an array or object without a * @throws InvalidArgumentException if an array or object without a
* __toString method is passed as the first argument * __toString method is passed as the first argument
* @return static A Stringy object
*/ */
public static function create(mixed $str = '', ?string $encoding = NULL): self public static function create(mixed $str = '', ?string $encoding = NULL): self
{ {
return new static($str, $encoding); return new static($str, $encoding);
} }
/**
* Returns the value in $str.
*
* @return string The current value of the $str property
*/
public function __toString(): string
{
return $this->str;
}
/** /**
* Returns a new string with $string appended. * Returns a new string with $string appended.
* *
@ -190,7 +191,7 @@ abstract class Stringy implements Countable, IteratorAggregate, ArrayAccess {
$stringy->str = preg_replace_callback( $stringy->str = preg_replace_callback(
'/[\d]+(.)?/u', '/[\d]+(.)?/u',
static fn($match) => mb_strtoupper($match[0], $encoding), static fn ($match) => mb_strtoupper($match[0], $encoding),
$stringy->str $stringy->str
); );
@ -395,7 +396,7 @@ abstract class Stringy implements Countable, IteratorAggregate, ArrayAccess {
$endOfStr = mb_strtolower($endOfStr, $this->encoding); $endOfStr = mb_strtolower($endOfStr, $this->encoding);
} }
return (string)$substring === $endOfStr; return (string) $substring === $endOfStr;
} }
/** /**
@ -585,8 +586,8 @@ abstract class Stringy implements Countable, IteratorAggregate, ArrayAccess {
{ {
return \mb_strpos( return \mb_strpos(
$this->str, $this->str,
(string)$needle, (string) $needle,
(int)$offset, (int) $offset,
$this->encoding $this->encoding
); );
} }
@ -605,8 +606,8 @@ abstract class Stringy implements Countable, IteratorAggregate, ArrayAccess {
{ {
return mb_strrpos( return mb_strrpos(
$this->str, $this->str,
(string)$needle, (string) $needle,
(int)$offset, (int) $offset,
$this->encoding $this->encoding
); );
} }
@ -813,7 +814,8 @@ abstract class Stringy implements Countable, IteratorAggregate, ArrayAccess {
if ($char === mb_substr($otherStr, $i, 1, $encoding)) if ($char === mb_substr($otherStr, $i, 1, $encoding))
{ {
$longestCommonPrefix .= $char; $longestCommonPrefix .= $char;
} else }
else
{ {
break; break;
} }
@ -842,7 +844,8 @@ abstract class Stringy implements Countable, IteratorAggregate, ArrayAccess {
if ($char === mb_substr($otherStr, -$i, 1, $encoding)) if ($char === mb_substr($otherStr, -$i, 1, $encoding))
{ {
$longestCommonSuffix = $char . $longestCommonSuffix; $longestCommonSuffix = $char . $longestCommonSuffix;
} else }
else
{ {
break; break;
} }
@ -898,7 +901,8 @@ abstract class Stringy implements Countable, IteratorAggregate, ArrayAccess {
$len = $table[$i][$j]; $len = $table[$i][$j];
$end = $i; $end = $i;
} }
} else }
else
{ {
$table[$i][$j] = 0; $table[$i][$j] = 0;
} }
@ -941,7 +945,7 @@ abstract class Stringy implements Countable, IteratorAggregate, ArrayAccess {
public function offsetExists(mixed $offset): bool public function offsetExists(mixed $offset): bool
{ {
$length = $this->length(); $length = $this->length();
$offset = (int)$offset; $offset = (int) $offset;
if ($offset >= 0) if ($offset >= 0)
{ {
@ -958,13 +962,13 @@ abstract class Stringy implements Countable, IteratorAggregate, ArrayAccess {
* does not exist. * does not exist.
* *
* @param mixed $offset The index from which to retrieve the char * @param mixed $offset The index from which to retrieve the char
* @return string The character at the specified index
* @throws OutOfBoundsException If the positive or negative offset does * @throws OutOfBoundsException If the positive or negative offset does
* not exist * not exist
* @return string The character at the specified index
*/ */
public function offsetGet(mixed $offset): string public function offsetGet(mixed $offset): string
{ {
$offset = (int)$offset; $offset = (int) $offset;
$length = $this->length(); $length = $this->length();
if (($offset >= 0 && $length <= $offset) || $length < abs($offset)) if (($offset >= 0 && $length <= $offset) || $length < abs($offset))
@ -1012,9 +1016,9 @@ abstract class Stringy implements Countable, IteratorAggregate, ArrayAccess {
* @param int $length Desired string length after padding * @param int $length Desired string length after padding
* @param string $padStr String used to pad, defaults to space * @param string $padStr String used to pad, defaults to space
* @param string $padType One of 'left', 'right', 'both' * @param string $padType One of 'left', 'right', 'both'
* @return static Object with a padded $str
* @throws /InvalidArgumentException If $padType isn't one of 'right', * @throws /InvalidArgumentException If $padType isn't one of 'right',
* 'left' or 'both' * 'left' or 'both'
* @return static Object with a padded $str
*/ */
public function pad(int $length, string $padStr = ' ', string $padType = 'right'): self public function pad(int $length, string $padStr = ' ', string $padType = 'right'): self
{ {
@ -1313,7 +1317,7 @@ abstract class Stringy implements Countable, IteratorAggregate, ArrayAccess {
$startOfStr = mb_strtolower($startOfStr, $this->encoding); $startOfStr = mb_strtolower($startOfStr, $this->encoding);
} }
return (string)$substring === $startOfStr; return (string) $substring === $startOfStr;
} }
/** /**
@ -1359,13 +1363,16 @@ abstract class Stringy implements Countable, IteratorAggregate, ArrayAccess {
if ($end === NULL) if ($end === NULL)
{ {
$length = $this->length(); $length = $this->length();
} elseif ($end >= 0 && $end <= $start) }
elseif ($end >= 0 && $end <= $start)
{ {
return static::create('', $this->encoding); return static::create('', $this->encoding);
} elseif ($end < 0) }
elseif ($end < 0)
{ {
$length = $this->length() + $end - $start; $length = $this->length() + $end - $start;
} else }
else
{ {
$length = $end - $start; $length = $end - $start;
} }
@ -1412,7 +1419,8 @@ abstract class Stringy implements Countable, IteratorAggregate, ArrayAccess {
if ($functionExists) if ($functionExists)
{ {
$array = mb_split($pattern, $this->str, $limit); $array = mb_split($pattern, $this->str, $limit);
} elseif ($this->supportsEncoding()) }
elseif ($this->supportsEncoding())
{ {
$array = \preg_split("/{$pattern}/", $this->str, $limit); $array = \preg_split("/{$pattern}/", $this->str, $limit);
} }
@ -1549,7 +1557,7 @@ abstract class Stringy implements Countable, IteratorAggregate, ArrayAccess {
$stringy = static::create($match[0], $encoding); $stringy = static::create($match[0], $encoding);
return (string)$stringy->toLowerCase()->upperCaseFirst(); return (string) $stringy->toLowerCase()->upperCaseFirst();
}, },
$stringy->str $stringy->str
); );
@ -1624,10 +1632,10 @@ abstract class Stringy implements Countable, IteratorAggregate, ArrayAccess {
} }
if (is_numeric($this->str)) if (is_numeric($this->str))
{ {
return (int)($this->str) > 0; return (int) ($this->str) > 0;
} }
return (bool)$this->regexReplace('[[:space:]]', '')->str; return (bool) $this->regexReplace('[[:space:]]', '')->str;
} }
/** /**
@ -2024,7 +2032,7 @@ abstract class Stringy implements Countable, IteratorAggregate, ArrayAccess {
], ],
]; ];
$charsArray[$language] = isset($languageSpecific[$language]) ? $languageSpecific[$language] : []; $charsArray[$language] = $languageSpecific[$language] ?? [];
return $charsArray[$language]; return $charsArray[$language];
} }
@ -2104,7 +2112,7 @@ abstract class Stringy implements Countable, IteratorAggregate, ArrayAccess {
} }
if ($this->supportsEncoding()) if ($this->supportsEncoding())
{ {
$option = str_replace('r', '', (string)$option); $option = str_replace('r', '', (string) $option);
return \preg_replace("/{$pattern}/u{$option}", $replacement, $string); return \preg_replace("/{$pattern}/u{$option}", $replacement, $string);
} }

View File

@ -3,10 +3,6 @@
use Rector\CodeQuality\Rector\Class_\CompleteDynamicPropertiesRector; use Rector\CodeQuality\Rector\Class_\CompleteDynamicPropertiesRector;
use Rector\CodeQuality\Rector\For_\{ForRepeatedCountToOwnVariableRector, ForToForeachRector}; use Rector\CodeQuality\Rector\For_\{ForRepeatedCountToOwnVariableRector, ForToForeachRector};
use Rector\CodeQuality\Rector\If_\{ConsecutiveNullCompareReturnsToNullCoalesceQueueRector, SimplifyIfElseToTernaryRector, SimplifyIfReturnBoolRector}; use Rector\CodeQuality\Rector\If_\{ConsecutiveNullCompareReturnsToNullCoalesceQueueRector, SimplifyIfElseToTernaryRector, SimplifyIfReturnBoolRector};
use Rector\CodingStyle\Rector\String_\SymplifyQuoteEscapeRector;
use Rector\Php74\Rector\Property\RestoreDefaultNullToNullableTypePropertyRector;
use Rector\Php81\Rector\Property\ReadOnlyPropertyRector;
use Rector\Set\ValueObject\LevelSetList;
use Rector\CodeQuality\Rector\Ternary\{SimplifyTautologyTernaryRector, SwitchNegatedTernaryRector}; use Rector\CodeQuality\Rector\Ternary\{SimplifyTautologyTernaryRector, SwitchNegatedTernaryRector};
use Rector\CodingStyle\Rector\ArrowFunction\StaticArrowFunctionRector; use Rector\CodingStyle\Rector\ArrowFunction\StaticArrowFunctionRector;
use Rector\CodingStyle\Rector\Class_\AddArrayDefaultToArrayPropertyRector; use Rector\CodingStyle\Rector\Class_\AddArrayDefaultToArrayPropertyRector;
@ -19,6 +15,7 @@ use Rector\CodingStyle\Rector\FuncCall\
CountArrayToEmptyArrayComparisonRector, CountArrayToEmptyArrayComparisonRector,
VersionCompareFuncCallToConstantRector}; VersionCompareFuncCallToConstantRector};
use Rector\CodingStyle\Rector\Stmt\NewlineAfterStatementRector; use Rector\CodingStyle\Rector\Stmt\NewlineAfterStatementRector;
use Rector\CodingStyle\Rector\String_\SymplifyQuoteEscapeRector;
use Rector\Config\RectorConfig; use Rector\Config\RectorConfig;
use Rector\DeadCode\Rector\ClassMethod\{RemoveUselessParamTagRector, RemoveUselessReturnTagRector}; use Rector\DeadCode\Rector\ClassMethod\{RemoveUselessParamTagRector, RemoveUselessReturnTagRector};
use Rector\DeadCode\Rector\Foreach_\RemoveUnusedForeachKeyRector; use Rector\DeadCode\Rector\Foreach_\RemoveUnusedForeachKeyRector;
@ -26,7 +23,10 @@ use Rector\DeadCode\Rector\Property\RemoveUselessVarTagRector;
use Rector\DeadCode\Rector\Switch_\RemoveDuplicatedCaseInSwitchRector; use Rector\DeadCode\Rector\Switch_\RemoveDuplicatedCaseInSwitchRector;
use Rector\EarlyReturn\Rector\Foreach_\ChangeNestedForeachIfsToEarlyContinueRector; use Rector\EarlyReturn\Rector\Foreach_\ChangeNestedForeachIfsToEarlyContinueRector;
use Rector\EarlyReturn\Rector\If_\{ChangeIfElseValueAssignToEarlyReturnRector, RemoveAlwaysElseRector}; use Rector\EarlyReturn\Rector\If_\{ChangeIfElseValueAssignToEarlyReturnRector, RemoveAlwaysElseRector};
use Rector\Php74\Rector\Property\RestoreDefaultNullToNullableTypePropertyRector;
use Rector\Php81\Rector\Property\ReadOnlyPropertyRector;
use Rector\PHPUnit\Set\PHPUnitSetList; use Rector\PHPUnit\Set\PHPUnitSetList;
use Rector\Set\ValueObject\LevelSetList;
use Rector\TypeDeclaration\Rector\ClassMethod\{AddMethodCallBasedStrictParamTypeRector, ParamTypeByMethodCallTypeRector, ParamTypeByParentCallTypeRector}; use Rector\TypeDeclaration\Rector\ClassMethod\{AddMethodCallBasedStrictParamTypeRector, ParamTypeByMethodCallTypeRector, ParamTypeByParentCallTypeRector};
use Rector\TypeDeclaration\Rector\Closure\AddClosureReturnTypeRector; use Rector\TypeDeclaration\Rector\Closure\AddClosureReturnTypeRector;
use Rector\TypeDeclaration\Rector\Property\TypedPropertyFromAssignsRector; use Rector\TypeDeclaration\Rector\Property\TypedPropertyFromAssignsRector;
@ -34,7 +34,7 @@ use Rector\TypeDeclaration\Rector\Property\TypedPropertyFromAssignsRector;
return static function (RectorConfig $config): void { return static function (RectorConfig $config): void {
// Import names with use statements // Import names with use statements
$config->importNames(); $config->importNames();
$config->importShortClasses(false); $config->importShortClasses(FALSE);
$config->sets([ $config->sets([
LevelSetList::UP_TO_PHP_81, LevelSetList::UP_TO_PHP_81,