diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index c28d1c0..7817247 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -6,59 +6,58 @@ on: jobs: unit-test: - runs-on: ubuntu-latest strategy: fail-fast: false matrix: - php: ['8.2'] + php: ["8.3"] steps: - - uses: actions/checkout@v3 - - - name: Setup PHP with PCOV - uses: shivammathur/setup-php@v2 - with: - php-version: ${{matrix.php}} - coverage: pcov - - - name: Validate composer.json and composer.lock - run: composer validate --strict - - - name: Cache Composer packages - id: composer-cache - uses: actions/cache@v3 - with: - path: vendor - key: ${{ runner.os }}-php-${{ hashFiles('**/composer.lock') }} - restore-keys: | - ${{ runner.os }}-php- - - - name: Install dependencies - run: composer install --prefer-dist --no-progress - - - name: CodeStyle - run: vendor/bin/php-cs-fixer fix --dry-run --using-cache=no --diff --verbose - - - name: Static analysis - run: vendor/bin/phpstan analyse - - - name: Setup Apache for http app-test - uses: ./.github/actions/apache-setup - with: - php-version: ${{ matrix.php }} - site-directory: /home/runner/work/fohn-ui/fohn-ui - http-port: 7000 - - - name: Run test suite - run: composer run-script unit-test - - - name: merge coverage - run: vendor/bin/phpcov merge build/logs/ --clover build/coverage/merged.xml - - - name: Upload Coverage - uses: codecov/codecov-action@v4 - with: - token: ${{ secrets.CODECOV_TOKEN }} - files: build/coverage/merged.xml - verbose: true + - uses: actions/checkout@v3 + + - name: Setup PHP with PCOV + uses: shivammathur/setup-php@v2 + with: + php-version: ${{matrix.php}} + coverage: pcov + + - name: Validate composer.json and composer.lock + run: composer validate --strict + + - name: Cache Composer packages + id: composer-cache + uses: actions/cache@v3 + with: + path: vendor + key: ${{ runner.os }}-php-${{ hashFiles('**/composer.lock') }} + restore-keys: | + ${{ runner.os }}-php- + + - name: Install dependencies + run: composer install --prefer-dist --no-progress + + - name: CodeStyle + run: vendor/bin/php-cs-fixer fix --dry-run --using-cache=no --diff --verbose + + - name: Static analysis + run: vendor/bin/phpstan analyse + + - name: Setup Apache for http app-test + uses: ./.github/actions/apache-setup + with: + php-version: ${{ matrix.php }} + site-directory: /home/runner/work/fohn-ui/fohn-ui + http-port: 7000 + + - name: Run test suite + run: composer run-script unit-test + + - name: merge coverage + run: vendor/bin/phpcov merge build/logs/ --clover build/coverage/merged.xml + + - name: Upload Coverage + uses: codecov/codecov-action@v4 + with: + token: ${{ secrets.CODECOV_TOKEN }} + files: build/coverage/merged.xml + verbose: true diff --git a/.php-cs-fixer.dist.php b/.php-cs-fixer.dist.php index a6a294a..87ca5ea 100644 --- a/.php-cs-fixer.dist.php +++ b/.php-cs-fixer.dist.php @@ -14,9 +14,6 @@ ->setRiskyAllowed(true) ->setRules([ '@PhpCsFixer' => true, - '@PhpCsFixer:risky' => true, - '@PHP74Migration:risky' => true, - '@PHP74Migration' => true, // required by PSR-12 'concat_space' => [ @@ -62,9 +59,6 @@ 'general_phpdoc_annotation_remove' => [ 'annotations' => ['author', 'copyright', 'throws'], ], - 'nullable_type_declaration_for_default_null_value' => [ - 'use_nullable_type_declaration' => false, - ], // fn => without curly brackets is less readable, // also prevent bounding of unwanted variables for GC diff --git a/app-test/_includes/Model/Country.php b/app-test/_includes/Model/Country.php index 5a8e2fb..fc01079 100644 --- a/app-test/_includes/Model/Country.php +++ b/app-test/_includes/Model/Country.php @@ -31,7 +31,7 @@ protected function init(): void }); } - public function validate(string $intent = null): array + public function validate(?string $intent = null): array { $errors = parent::validate($intent); diff --git a/app-test/_includes/Model/FieldTest.php b/app-test/_includes/Model/FieldTest.php index b7112ce..a5da7cd 100644 --- a/app-test/_includes/Model/FieldTest.php +++ b/app-test/_includes/Model/FieldTest.php @@ -46,7 +46,7 @@ protected function init(): void ]); } - public function validate(string $intent = null): array + public function validate(?string $intent = null): array { $errors = parent::validate($intent); if (mb_strlen($this->get('first_name') ?? '') < 2) { diff --git a/app-test/_includes/Model/File.php b/app-test/_includes/Model/File.php index 001cc9a..276949a 100644 --- a/app-test/_includes/Model/File.php +++ b/app-test/_includes/Model/File.php @@ -39,7 +39,7 @@ public function getFilesHierarchy(bool $isFolderSelectable = true): array /** * Return Files Hierarchy as a TreeNode property. */ - private function getHierarchicalTreeNodes(array $files, int $useId = null, bool $isFolderSelectable): array + private function getHierarchicalTreeNodes(array $files, ?int $useId = null, bool $isFolderSelectable = true): array { $parent = []; // Get top level files or folders. diff --git a/app-test/basic/grid-layout.php b/app-test/basic/grid-layout.php index 806e2a0..217fc99 100644 --- a/app-test/basic/grid-layout.php +++ b/app-test/basic/grid-layout.php @@ -12,8 +12,8 @@ require_once __DIR__ . '/../init-ui.php'; -$viewStyle = - [ +$viewStyle + = [ 'text-white', 'flex', 'items-center', diff --git a/app-test/collection/table-as-crud.php b/app-test/collection/table-as-crud.php index 3c319e7..76c52a4 100644 --- a/app-test/collection/table-as-crud.php +++ b/app-test/collection/table-as-crud.php @@ -1,4 +1,5 @@ log('info', 'Console Implements Logger Interface'); diff --git a/index.php b/index.php new file mode 100644 index 0000000..4742ab7 --- /dev/null +++ b/index.php @@ -0,0 +1,7 @@ +setUrlTrigger($this->urlTrigger); } - public function setUrlTrigger(string $trigger = null): void + public function setUrlTrigger(?string $trigger = null): void { if (!$trigger && strlen($this->getViewId()) > 10) { $this->urlTrigger = Ui::service()->factoryId($this->getViewId()); diff --git a/src/Callback/ServerEvent.php b/src/Callback/ServerEvent.php index bc4d1fd..6876788 100644 --- a/src/Callback/ServerEvent.php +++ b/src/Callback/ServerEvent.php @@ -66,7 +66,7 @@ protected function initStreamingApp(): void $this->app = new App(['registerShutdown' => false]); } - public function onRequest(\Closure $fx, array $params = [], \Closure $onAbortedFx = null): void + public function onRequest(\Closure $fx, array $params = [], ?\Closure $onAbortedFx = null): void { if ($onAbortedFx) { $this->onAborted($onAbortedFx); @@ -139,7 +139,7 @@ protected function sendBlock(string $id, string $event, string $name): void $this->app->streamEvent($streamEvent, $this->minBufferSize); } - public function start(JsStatements $statements = null): JsRenderInterface + public function start(?JsStatements $statements = null): JsRenderInterface { if (!$statements) { $statements = JsStatements::with([]); @@ -152,7 +152,7 @@ public function start(JsStatements $statements = null): JsRenderInterface return $statements; } - public function stop(JsStatements $statements = null): JsRenderInterface + public function stop(?JsStatements $statements = null): JsRenderInterface { if (!$statements) { $statements = JsStatements::with([]); diff --git a/src/Component/Form.php b/src/Component/Form.php index bb2b626..7faccdc 100644 --- a/src/Component/Form.php +++ b/src/Component/Form.php @@ -65,7 +65,7 @@ protected function initRenderTree(): void $this->initDefaultLayout(self::MAIN_LAYOUT, $this->defaultLayout); } - protected function initDefaultLayout(string $layoutName, FormLayoutInterface $layout = null): self + protected function initDefaultLayout(string $layoutName, ?FormLayoutInterface $layout = null): self { $this->defaultLayout = $layout ?: Ui::service()->getFormLayout(); @@ -180,7 +180,7 @@ public function addControls(array $controls, string $layoutName = self::MAIN_LAY return $this; } - public function addControl(Control $control, string $layoutName = self::MAIN_LAYOUT, string $regionName = null): Control + public function addControl(Control $control, string $layoutName = self::MAIN_LAYOUT, ?string $regionName = null): Control { $this->registerControl($control); diff --git a/src/Component/Form/Layout/FormLayoutInterface.php b/src/Component/Form/Layout/FormLayoutInterface.php index 0c0daa5..814ab13 100644 --- a/src/Component/Form/Layout/FormLayoutInterface.php +++ b/src/Component/Form/Layout/FormLayoutInterface.php @@ -10,7 +10,7 @@ interface FormLayoutInterface { - public function setSubmitButton(Button $button = null): self; + public function setSubmitButton(?Button $button = null): self; public function addButton(Button $button): Button; diff --git a/src/Component/Form/Layout/Standard.php b/src/Component/Form/Layout/Standard.php index 05d58b6..03145ea 100644 --- a/src/Component/Form/Layout/Standard.php +++ b/src/Component/Form/Layout/Standard.php @@ -35,7 +35,7 @@ public function addSubmitButton(bool $add): void $this->addSubmitBtnInLayout = false; } - public function setSubmitButton(Button $button = null): self + public function setSubmitButton(?Button $button = null): self { if (!$button) { $button = Button::factoryFromSeed($this->defaultSubmitBtnSeed); @@ -46,7 +46,7 @@ public function setSubmitButton(Button $button = null): self return $this; } - public function addControl(Control $control, string $regionName = null): Control + public function addControl(Control $control, ?string $regionName = null): Control { if (!$regionName) { $regionName = $this->template->hasTag(self::CTRL_REGION_PREFIX . $control->getControlName()) ? self::CTRL_REGION_PREFIX . $control->getControlName() : View::MAIN_TEMPLATE_REGION; diff --git a/src/Component/Modal/AsDialog.php b/src/Component/Modal/AsDialog.php index a87d62b..cc39d8a 100644 --- a/src/Component/Modal/AsDialog.php +++ b/src/Component/Modal/AsDialog.php @@ -31,7 +31,7 @@ class AsDialog extends Modal * When calling this method with no Closure function, the modal will * close without triggering a callback event. */ - public function addCancelEvent(\Closure $fx = null, View $trigger = null): View + public function addCancelEvent(?\Closure $fx = null, ?View $trigger = null): View { $cancelTrigger = $trigger ?: View::factoryFromSeed($this->cancelButtonSeed); if ($fx) { @@ -45,7 +45,7 @@ public function addCancelEvent(\Closure $fx = null, View $trigger = null): View return $cancelTrigger; } - public function addConfirmEvent(\Closure $fx = null, View $trigger = null): View + public function addConfirmEvent(?\Closure $fx = null, ?View $trigger = null): View { $confirmTrigger = $trigger ?: View::factoryFromSeed($this->confirmButtonSeed); if ($fx) { diff --git a/src/Component/Table.php b/src/Component/Table.php index 1bf7149..923383c 100644 --- a/src/Component/Table.php +++ b/src/Component/Table.php @@ -206,7 +206,7 @@ public function jsGetCellValue(string $colName): JsRenderInterface return $this->jsGetStore(self::PINIA_PREFIX)->getCellValue(Js::var($idVar), Js::string($colName)); } - public function addActionColumn(string $columnName, string $actionName, View\Button $button, Header $header = null, string $eventName = 'click.stop'): JsFunction + public function addActionColumn(string $columnName, string $actionName, View\Button $button, ?Header $header = null, string $eventName = 'click.stop'): JsFunction { if (!$this->hasColumn($columnName)) { if (!$header) { @@ -242,7 +242,7 @@ public function addFilter(Filter $filter, string $regionName = self::FILTER_REGI return $this->filter; } - public function filterColumns(array $columnFilters, Filter $filter = null): self + public function filterColumns(array $columnFilters, ?Filter $filter = null): self { if (!$this->filter) { $this->addFilter($filter ?? new Filter()); diff --git a/src/Component/Table/Action.php b/src/Component/Table/Action.php index aa86afa..6f1d254 100644 --- a/src/Component/Table/Action.php +++ b/src/Component/Table/Action.php @@ -46,7 +46,7 @@ public function getConfirmationModal(): ?AsDialog return $this->confirmationModal; } - public function addConfirmationDialog(string $title, Messages $messages, View\Button $ok = null, View\Button $cancel = null, bool $isClosable = true): self + public function addConfirmationDialog(string $title, Messages $messages, ?View\Button $ok = null, ?View\Button $cancel = null, bool $isClosable = true): self { $this->addProperty('messages', $messages->getJsMessages()); $this->confirmationModal = AsDialog::addTo($this, ['title' => $title, 'isClosable' => $isClosable]); diff --git a/src/Component/Table/Filter/Date.php b/src/Component/Table/Filter/Date.php index 4f91a2f..cf24b71 100644 --- a/src/Component/Table/Filter/Date.php +++ b/src/Component/Table/Filter/Date.php @@ -14,7 +14,7 @@ class Date extends Generic implements FilterColumnInterface protected string $type = 'date'; protected string $format; - public function __construct(string $id, string $format = 'Y-m-d', string $label = null, array $props = []) + public function __construct(string $id, string $format = 'Y-m-d', ?string $label = null, array $props = []) { $props['config'] = Utils::getFlatPickrConfig($this->type, $format); $props['config']['allowInput'] = true; diff --git a/src/Component/Table/Filter/Generic.php b/src/Component/Table/Filter/Generic.php index 0d8feb1..9a3a37a 100644 --- a/src/Component/Table/Filter/Generic.php +++ b/src/Component/Table/Filter/Generic.php @@ -16,7 +16,7 @@ abstract class Generic 'type' => 'text', ]; - public function __construct(string $id, string $label = null, array $props = []) + public function __construct(string $id, ?string $label = null, array $props = []) { $this->id = $id; $this->label = $label ?? ucfirst($id); diff --git a/src/Component/Tree.php b/src/Component/Tree.php index ae82f4d..b616e1a 100644 --- a/src/Component/Tree.php +++ b/src/Component/Tree.php @@ -108,7 +108,7 @@ public function setValue(array $value): void * Function $fx to be executed when using Save Btn. * The callback function ($fx) must return a jsRenderInterface. */ - public function onTreePost(\Closure $fx, Button $btn = null): void + public function onTreePost(\Closure $fx, ?Button $btn = null): void { $this->initTreePostRequest($fx); @@ -168,7 +168,7 @@ public function onTreeNodeChanged(\Closure $fx): void }); } - public function setFilter(array $fields, string $mode = 'lenient', string $placeholder = null, ?string $locale = 'en'): self + public function setFilter(array $fields, string $mode = 'lenient', ?string $placeholder = null, ?string $locale = 'en'): self { $this->ptProps['filter'] = true; $this->ptProps['filterBy'] = implode(',', $fields); diff --git a/src/Core/ContainerTrait.php b/src/Core/ContainerTrait.php index 82239b1..fdfcf50 100644 --- a/src/Core/ContainerTrait.php +++ b/src/Core/ContainerTrait.php @@ -72,7 +72,7 @@ public function getOwner(): AbstractView * Starting with the immediate owner of the view and each owner of view-owner * until no more owner is set. */ - public function getOwners(AbstractView $view = null, array $owners = []): array + public function getOwners(?AbstractView $view = null, array $owners = []): array { if (!$view) { $view = $this; diff --git a/src/Core/Exception.php b/src/Core/Exception.php index 877ebb7..5ea3660 100644 --- a/src/Core/Exception.php +++ b/src/Core/Exception.php @@ -21,7 +21,7 @@ class Exception extends \Exception /** @var string[] */ private array $solutions = []; // store solutions - public function __construct(string $message = '', int $code = 0, \Throwable $previous = null) + public function __construct(string $message = '', int $code = 0, ?\Throwable $previous = null) { parent::__construct($message, $code, $previous); diff --git a/src/Core/ExceptionRenderer/RendererAbstract.php b/src/Core/ExceptionRenderer/RendererAbstract.php index f847c42..fd33c91 100644 --- a/src/Core/ExceptionRenderer/RendererAbstract.php +++ b/src/Core/ExceptionRenderer/RendererAbstract.php @@ -17,7 +17,7 @@ abstract class RendererAbstract public string $output = ''; - final public function __construct(\Throwable $exception, \Throwable $parent_exception = null) + final public function __construct(\Throwable $exception, ?\Throwable $parent_exception = null) { $this->exception = $exception; $this->parent_exception = $parent_exception; diff --git a/src/HtmlTemplate.php b/src/HtmlTemplate.php index 389b009..979954e 100644 --- a/src/HtmlTemplate.php +++ b/src/HtmlTemplate.php @@ -320,7 +320,7 @@ protected function parseTemplate(string $str): void } } - protected function parseTemplateTree(array &$inputReversed, string $openedTag = null): TagTree + protected function parseTemplateTree(array &$inputReversed, ?string $openedTag = null): TagTree { $tagTree = new TagTree($this, $openedTag ?? self::TOP_TAG); @@ -398,7 +398,7 @@ public function toLoadableString(string $region = self::TOP_TAG): string return implode('', $res); } - public function renderToHtml(string $region = null): string + public function renderToHtml(?string $region = null): string { return $this->renderTagTreeToHtml($this->getTagTree($region ?? self::TOP_TAG)); } diff --git a/src/Js/Chain/Method.php b/src/Js/Chain/Method.php index c22d27c..bea2cbc 100644 --- a/src/Js/Chain/Method.php +++ b/src/Js/Chain/Method.php @@ -39,10 +39,10 @@ public static function renderMethodArguments(array $args): string public function renderArguments(array $args): string { - return '(' . - implode(',', array_map(static function ($arg) { + return '(' + . implode(',', array_map(static function ($arg) { return $arg->jsRender(); - }, $args)) . - ')'; + }, $args)) + . ')'; } } diff --git a/src/Js/Jquery.php b/src/Js/Jquery.php index 836a64b..1d9e783 100644 --- a/src/Js/Jquery.php +++ b/src/Js/Jquery.php @@ -96,7 +96,7 @@ public static function withSelf(): self /** * Start chain with a string selector $("selector"). */ - public static function withSelector(string $selector = null): self + public static function withSelector(?string $selector = null): self { return new static(self::$jquery, Js::string($selector)); } @@ -122,7 +122,7 @@ public static function withThis(): self * Add a javascript event to a View. * render as $('#view_id')->on(event, selector, function() {}). */ - public static function addEventTo(View $view, string $event, string $selector = null, bool $prevent = false, bool $stop = false): JsFunction + public static function addEventTo(View $view, string $event, ?string $selector = null, bool $prevent = false, bool $stop = false): JsFunction { $fn = JqFunction::anonymous(); @@ -146,7 +146,7 @@ public static function addEventTo(View $view, string $event, string $selector = /** * Add a Jquery ajax callback event to a View. */ - public static function jqCallback(View $view, string $event, \Closure $fn, array $requestPayload = [], string $selector = null): JsFunction + public static function jqCallback(View $view, string $event, \Closure $fn, array $requestPayload = [], ?string $selector = null): JsFunction { $callback = \Fohn\Ui\Callback\Jquery::addAbstractTo($view); $callback->onJqueryRequest(static function (array $payload) use ($fn, $view): JsRenderInterface { diff --git a/src/Js/JsChain.php b/src/Js/JsChain.php index d29dc56..68c6ff7 100644 --- a/src/Js/JsChain.php +++ b/src/Js/JsChain.php @@ -28,7 +28,7 @@ class JsChain implements JsRenderInterface /** @var Chainable[] The remaining chaining methods or property. */ protected array $chains = []; - final protected function __construct(string $library, JsRenderInterface $variable = null) + final protected function __construct(string $library, ?JsRenderInterface $variable = null) { if ($variable) { $this->arguments[] = $variable; @@ -41,12 +41,12 @@ final protected function __construct(string $library, JsRenderInterface $variabl * Start of the chain. * ex: Js::with('flatpickr', Js::var('')) translate into flatpickr(). */ - public static function with(string $library, JsRenderInterface $variable = null): self + public static function with(string $library, ?JsRenderInterface $variable = null): self { return new static($library, $variable); } - public static function withUiLibrary(JsRenderInterface $variable = null): self + public static function withUiLibrary(?JsRenderInterface $variable = null): self { return self::with(Ui::service()->jsLibrary, $variable); } diff --git a/src/Js/JsToast.php b/src/Js/JsToast.php index 940b71b..adb323a 100644 --- a/src/Js/JsToast.php +++ b/src/Js/JsToast.php @@ -84,7 +84,7 @@ public static function info(string $title, string $message = '', array $options * fohn.toastService.notify($(this).text(),{}); * });. */ - public static function notifyWithJs(JsRenderInterface $title, JsRenderInterface $message = null, JsRenderInterface $options = null, bool $sanitize = true): JsRenderInterface + public static function notifyWithJs(JsRenderInterface $title, ?JsRenderInterface $message = null, ?JsRenderInterface $options = null, bool $sanitize = true): JsRenderInterface { // / @phpstan-ignore-next-line return (new static())->toastService->notify($title, $message ?? StringLiteral::set(''), $options ?? ObjectLiteral::set([]), Boolean::set($sanitize)); diff --git a/src/Page.php b/src/Page.php index 47d8139..72beaa7 100644 --- a/src/Page.php +++ b/src/Page.php @@ -78,7 +78,7 @@ protected function initRenderTree(): void /** * Protect all callback request, coming from this page, from CSFR attack. */ - public function csfrProtect(string $secret, string $redirectTo = null, int $strength = 16): void + public function csfrProtect(string $secret, ?string $redirectTo = null, int $strength = 16): void { Request::protect($redirectTo); @@ -128,7 +128,7 @@ public function appendMetaTag(string $htmlTag): void * Render the entire Html page. * Update template with page specific content. */ - public function outputHtml(string $content = null): string + public function outputHtml(?string $content = null): string { $renderView = Ui::viewRenderer($this); $template = $renderView->getRenderTemplate(); diff --git a/src/Service/Atk/ModelController.php b/src/Service/Atk/ModelController.php index f938292..c3780ce 100644 --- a/src/Service/Atk/ModelController.php +++ b/src/Service/Atk/ModelController.php @@ -70,7 +70,7 @@ public function delete($id): bool } } - public function getRows(array $fieldNames = [], int $limit = null): array + public function getRows(array $fieldNames = [], ?int $limit = null): array { if ($limit) { $this->model->setLimit($limit); @@ -79,7 +79,7 @@ public function getRows(array $fieldNames = [], int $limit = null): array return $this->model->export($fieldNames); } - public function searchModel(string $query, array $searchFieldNames, int $limit = null): array + public function searchModel(string $query, array $searchFieldNames, ?int $limit = null): array { $scope = Model\Scope::createOr(); foreach ($searchFieldNames as $fieldName) { diff --git a/src/Service/ModelControllerInterface.php b/src/Service/ModelControllerInterface.php index db7b499..ab9650d 100644 --- a/src/Service/ModelControllerInterface.php +++ b/src/Service/ModelControllerInterface.php @@ -27,7 +27,7 @@ public function getEntityValues($id): array; */ public function delete($id): bool; - public function getRows(array $fieldNames = [], int $limit = null): array; + public function getRows(array $fieldNames = [], ?int $limit = null): array; - public function searchModel(string $query, array $searchFieldNames, int $limit = null): array; + public function searchModel(string $query, array $searchFieldNames, ?int $limit = null): array; } diff --git a/src/Service/Session.php b/src/Service/Session.php index 89cfb73..e3e4012 100644 --- a/src/Service/Session.php +++ b/src/Service/Session.php @@ -56,7 +56,7 @@ public function setMultiple(array $values, bool $keepOpen = false): void * Retrieve a Session key and remove it after. * Will return $default if key is not set. */ - public function retrieve(string $key, string $default = null): ?string + public function retrieve(string $key, ?string $default = null): ?string { $value = $this->get($key, $default); $this->forget($key); @@ -64,7 +64,7 @@ public function retrieve(string $key, string $default = null): ?string return $value; } - public function forget(string $key = null): void + public function forget(?string $key = null): void { $this->startSession(); if (!$key && isset($_SESSION[$this->namespace])) { @@ -75,7 +75,7 @@ public function forget(string $key = null): void } } - public function get(string $key, string $default = null): ?string + public function get(string $key, ?string $default = null): ?string { $this->startSession(array_merge($this->sessionOptions, [self::READ_ONLY_OPTION => true])); diff --git a/src/Service/SessionInterface.php b/src/Service/SessionInterface.php index 1c2c9be..b492dce 100644 --- a/src/Service/SessionInterface.php +++ b/src/Service/SessionInterface.php @@ -14,7 +14,7 @@ interface SessionInterface */ public function setOptions(array $options): void; - public function get(string $key, string $default = null): ?string; + public function get(string $key, ?string $default = null): ?string; public function set(string $key, string $value, bool $keepOpen = false): void; @@ -23,12 +23,12 @@ public function setMultiple(array $values, bool $keepOpen = false): void; /** * Retrieve a key and remove it from body. */ - public function retrieve(string $key, string $default = null): ?string; + public function retrieve(string $key, ?string $default = null): ?string; /** * Remove a key from body. */ - public function forget(string $key = null): void; + public function forget(?string $key = null): void; /** * Retrieve all key from Session. diff --git a/src/Service/Ui.php b/src/Service/Ui.php index f608a5d..6a08126 100644 --- a/src/Service/Ui.php +++ b/src/Service/Ui.php @@ -192,7 +192,7 @@ public static function buildUrl(string $url, array $params = []): string return (string) (new Uri($url))->withQuery(Query::build($params)); } - public static function locale(string $locale = null, int $option = \LC_ALL): string + public static function locale(?string $locale = null, int $option = \LC_ALL): string { if ($locale) { setlocale($option, $locale); @@ -202,7 +202,7 @@ public static function locale(string $locale = null, int $option = \LC_ALL): str return static::service()->locale; } - public static function timezone(string $timezone = null): string + public static function timezone(?string $timezone = null): string { if ($timezone) { static::service()->timezone = $timezone; diff --git a/src/Service/UiInterface.php b/src/Service/UiInterface.php index a1bfdd5..f9ac107 100644 --- a/src/Service/UiInterface.php +++ b/src/Service/UiInterface.php @@ -42,7 +42,7 @@ public static function serverRequest(): ServerRequestInterface; public function getQueryParamValue(string $param): ?string; - public static function timezone(string $timezone = null): string; + public static function timezone(?string $timezone = null): string; /** Get current Url as request by the client, without query. */ public static function parseRequestUrl(): string; diff --git a/src/Tailwind/Tw.php b/src/Tailwind/Tw.php index bc125ef..6016a6e 100644 --- a/src/Tailwind/Tw.php +++ b/src/Tailwind/Tw.php @@ -1,4 +1,5 @@ tw)->reduce($fn, $seed)->get()); } - public function toString(\Closure $fn = null, string $seed = ''): string + public function toString(?\Closure $fn = null, string $seed = ''): string { if (!$fn) { $fn = static function (string $output, string $utility): string { diff --git a/src/Tailwind/Utilities/BackgroundTrait.php b/src/Tailwind/Utilities/BackgroundTrait.php index eb60feb..eb20d7a 100644 --- a/src/Tailwind/Utilities/BackgroundTrait.php +++ b/src/Tailwind/Utilities/BackgroundTrait.php @@ -1,4 +1,5 @@ htmlStyles[$property] = $style; @@ -293,7 +293,7 @@ public function removeHtmlStyle(string $property): self return $this; } - public function appendHtmlAttribute(string $attribute, string $value = null): self + public function appendHtmlAttribute(string $attribute, ?string $value = null): self { if ($value || $value === null) { $this->htmlAttributes[$attribute] = $value; @@ -384,7 +384,7 @@ protected function renderStyles(): void /** * Render View using json format. */ - public function renderToJsonArr(string $region = null): array + public function renderToJsonArr(?string $region = null): array { $renderer = Ui::viewRenderer($this); @@ -473,7 +473,7 @@ private function getStickyArgs(): array * If GET argument is not presently set you can specify a 2nd argument * to forge-set the GET argument for current view, and it's sub-views. */ - public function stickyGet(string $name, string $newValue = null): ?string + public function stickyGet(string $name, ?string $newValue = null): ?string { $this->stickyArgs[$name] = Ui::service()->getQueryParamValue($name) ?? $newValue; diff --git a/src/View/Button.php b/src/View/Button.php index 8900ae8..7d2e5c6 100644 --- a/src/View/Button.php +++ b/src/View/Button.php @@ -1,4 +1,5 @@ text('')]); diff --git a/src/View/Lister.php b/src/View/Lister.php index 5ccd570..138c4f3 100644 --- a/src/View/Lister.php +++ b/src/View/Lister.php @@ -24,7 +24,7 @@ class Lister extends View { protected const HOOK_REGION_RENDER = self::class . '@region_render'; - /** @var array Repeatable region name of this template. */ + /** @var array Repeatable region name of this template. */ public array $repeatableRegions = []; public function setRegionItems(string $regionName, array $items, HtmlTemplate $template): self diff --git a/src/ViewRenderer.php b/src/ViewRenderer.php index ed1ef4a..ac2dda0 100644 --- a/src/ViewRenderer.php +++ b/src/ViewRenderer.php @@ -39,7 +39,7 @@ public function getRenderTemplate(): HtmlTemplate return $this->renderTemplate; } - public function getHtml(string $region = null): string + public function getHtml(?string $region = null): string { return $this->getRenderTemplate()->renderToHtml($region); } diff --git a/tests/DemoApp/AppTest.php b/tests/DemoApp/AppTest.php index 9106d77..b5c5d34 100644 --- a/tests/DemoApp/AppTest.php +++ b/tests/DemoApp/AppTest.php @@ -30,6 +30,17 @@ protected function setUp(): void ); } + /** + * @dataProvider provideAppTestHtmlResponseCases + */ + public function testAppTestHtmlResponse(string $uri): void + { + $request = new Request('GET', '/app-test/' . $uri); + $response = $this->client->send($request); + + $this->assertSame(200, $response->getStatusCode(), ' Status error on ' . $uri); + } + public static function provideAppTestHtmlResponseCases(): iterable { $excludeDirs = ['_app-data', '_includes', 'local']; @@ -58,15 +69,4 @@ public static function provideAppTestHtmlResponseCases(): iterable return $items; }, []); } - - /** - * @dataProvider provideAppTestHtmlResponseCases - */ - public function testAppTestHtmlResponse(string $uri): void - { - $request = new Request('GET', '/app-test/' . $uri); - $response = $this->client->send($request); - - $this->assertSame(200, $response->getStatusCode(), ' Status error on ' . $uri); - } } diff --git a/tests/FohnTestCase.php b/tests/FohnTestCase.php index 610fb4b..e0730b7 100644 --- a/tests/FohnTestCase.php +++ b/tests/FohnTestCase.php @@ -10,7 +10,7 @@ class FohnTestCase extends TestCase { - public function __construct(string $name = null, array $data = [], $dataName = '') + public function __construct(?string $name = null, array $data = [], $dataName = '') { MockUi::service(); MockUi::service()->setApp(new MockApp(['registerShutdown' => false])); diff --git a/tests/Service/UiServiceTest.php b/tests/Service/UiServiceTest.php index e49be5b..2d3d9c5 100644 --- a/tests/Service/UiServiceTest.php +++ b/tests/Service/UiServiceTest.php @@ -55,7 +55,7 @@ public static function provideGetFromClassNameCases(): iterable 'test view name' => ['view', View::class], 'test table name' => ['table', Table::class], 'test button name' => ['button', View\Button::class], - 'test anonymous' => ['anonymous', get_class(new class() {})], + 'test anonymous' => ['anonymous', get_class(new class {})], ]; }