Skip to content

Commit

Permalink
added attribute #Request
Browse files Browse the repository at this point in the history
  • Loading branch information
dg committed Sep 23, 2023
1 parent 87df261 commit 770a325
Show file tree
Hide file tree
Showing 5 changed files with 181 additions and 26 deletions.
18 changes: 18 additions & 0 deletions src/Application/Attributes/Request.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<?php

/**
* This file is part of the Nette Framework (https://nette.org)
* Copyright (c) 2004 David Grudl (https://davidgrudl.com)
*/

declare(strict_types=1);

namespace Nette\Application\Attributes;

use Attribute;


#[Attribute(Attribute::TARGET_PROPERTY)]
class Request
{
}
2 changes: 1 addition & 1 deletion src/Application/UI/Component.php
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,7 @@ public static function getReflection(): ComponentReflection
public function loadState(array $params): void
{
$reflection = $this->getReflection();
foreach ($reflection->getPersistentParams() as $name => $meta) {
foreach ($reflection->getRequestParams() as $name => $meta) {
if (isset($params[$name])) { // nulls are ignored
if (!$reflection->convertType($params[$name], $meta['type'])) {
throw new Nette\Application\BadRequestException(sprintf(
Expand Down
33 changes: 23 additions & 10 deletions src/Application/UI/ComponentReflection.php
Original file line number Diff line number Diff line change
Expand Up @@ -33,9 +33,9 @@ final class ComponentReflection extends \ReflectionClass


/**
* Returns array of persistent properties. They are public and have attribute #[Persistent] or annotation @persistent.
* Returns array of request properties. They are public and have attribute #[Persistent] or #[Request] or annotation @persistent.
*/
public function getPersistentParams(): array
public function getRequestParams(): array
{
$params = &self::$ppCache[$this->getName()];
if ($params !== null) {
Expand All @@ -45,26 +45,28 @@ public function getPersistentParams(): array
$params = [];
$isPresenter = $this->isSubclassOf(Presenter::class);
foreach ($this->getProperties(\ReflectionProperty::IS_PUBLIC) as $prop) {
if (!$prop->isStatic()
&& ((PHP_VERSION_ID >= 80000 && $prop->getAttributes(Nette\Application\Attributes\Persistent::class))
|| self::parseAnnotation($prop, 'persistent'))
) {
$persistent = (PHP_VERSION_ID >= 80000 && $prop->getAttributes(Nette\Application\Attributes\Persistent::class))
|| self::parseAnnotation($prop, 'persistent');
if (!$prop->isStatic() && ($persistent || $prop->getAttributes(Nette\Application\Attributes\Request::class))) {
$default = $prop->getDefaultValue();
$params[$prop->getName()] = [
'def' => $default,
'type' => self::getPropertyType($prop, $default),
'since' => $isPresenter ? Nette\Utils\Reflection::getPropertyDeclaringClass($prop)->getName() : null,
'persist' => $persistent,
];
}
}

if ($this->getParentClass()->isSubclassOf(Component::class)) {
$parent = new self($this->getParentClass()->getName());
foreach ($parent->getPersistentParams() as $name => $meta) {
if (isset($params[$name])) {
$params[$name]['since'] = $meta['since'];
foreach ($parent->getRequestParams() as $name => $meta) {
$param = &$params[$name];
if ($param) {
$param['since'] = $meta['since'];
$param['persist'] = $param['persist'] || $meta['persist'];
} else {
$params[$name] = $meta;
$param = $meta;
}
}
}
Expand All @@ -73,6 +75,17 @@ public function getPersistentParams(): array
}


/**
* Returns array of persistent properties. They are public and have attribute #[Persistent] or annotation @persistent.
*/
public function getPersistentParams(): array
{
return array_filter($this->getRequestParams(), function ($param) {
return $param['persist'];
});
}


public function getPersistentComponents(): array
{
$class = $this->getName();
Expand Down
124 changes: 124 additions & 0 deletions tests/UI/Presenter.getRequestParams.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
<?php

/**
* Test: Nette\Application\UI\Presenter::getRequestParams
*/

declare(strict_types=1);

use Nette\Application\Attributes\Persistent;
use Nette\Application\Attributes\Request;
use Nette\Application\UI\ComponentReflection;
use Nette\Application\UI\Presenter;
use Tester\Assert;

require __DIR__ . '/../bootstrap.php';


class OnePresenter extends Presenter
{
public static $no1;
public $no2;

/** @persistent */
public $yes1;

#[Persistent]
public $yes2;

#[Request]
public $yes3;
}


class TwoPresenter extends OnePresenter
{
#[Request]
public $yes2;
public $yes3;

#[Request]
public $yes4;
}


if (PHP_VERSION_ID < 80000) {
Assert::same(
[
'yes1' => [
'def' => null,
'type' => 'scalar',
'since' => 'OnePresenter',
'persist' => true,
],
],
(new ComponentReflection(OnePresenter::class))->getRequestParams()
);

Assert::same(
[
'yes1' => [
'def' => null,
'type' => 'scalar',
'since' => 'OnePresenter',
'persist' => true,
],
],
(new ComponentReflection(TwoPresenter::class))->getRequestParams()
);

} else {
Assert::same(
[
'yes1' => [
'def' => null,
'type' => 'scalar',
'since' => 'OnePresenter',
'persist' => true,
],
'yes2' => [
'def' => null,
'type' => 'scalar',
'since' => 'OnePresenter',
'persist' => true,
],
'yes3' => [
'def' => null,
'type' => 'scalar',
'since' => 'OnePresenter',
'persist' => false,
],
],
(new ComponentReflection(OnePresenter::class))->getRequestParams()
);

Assert::same(
[
'yes2' => [
'def' => null,
'type' => 'scalar',
'since' => 'OnePresenter',
'persist' => true,
],
'yes4' => [
'def' => null,
'type' => 'scalar',
'since' => 'TwoPresenter',
'persist' => false,
],
'yes1' => [
'def' => null,
'type' => 'scalar',
'since' => 'OnePresenter',
'persist' => true,
],
'yes3' => [
'def' => null,
'type' => 'scalar',
'since' => 'OnePresenter',
'persist' => false,
],
],
(new ComponentReflection(TwoPresenter::class))->getRequestParams()
);
}
30 changes: 15 additions & 15 deletions tests/UI/Presenter.link().persistent.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -103,34 +103,34 @@ class FourthPresenter extends BasePresenter


Assert::same([
'p1' => ['def' => null, 'type' => 'scalar', 'since' => 'BasePresenter'],
't1' => ['def' => null, 'type' => 'scalar', 'since' => 'PersistentParam1'],
'p1' => ['def' => null, 'type' => 'scalar', 'since' => 'BasePresenter', 'persist' => true],
't1' => ['def' => null, 'type' => 'scalar', 'since' => 'PersistentParam1', 'persist' => true],
], BasePresenter::getReflection()->getPersistentParams());

Assert::same([
'p2' => ['def' => null, 'type' => 'scalar', 'since' => 'TestPresenter'],
'p1' => ['def' => null, 'type' => 'scalar', 'since' => 'BasePresenter'],
't1' => ['def' => null, 'type' => 'scalar', 'since' => 'PersistentParam1'],
't2' => ['def' => null, 'type' => 'scalar', 'since' => 'PersistentParam2A'],
'p2' => ['def' => null, 'type' => 'scalar', 'since' => 'TestPresenter', 'persist' => true],
'p1' => ['def' => null, 'type' => 'scalar', 'since' => 'BasePresenter', 'persist' => true],
't1' => ['def' => null, 'type' => 'scalar', 'since' => 'PersistentParam1', 'persist' => true],
't2' => ['def' => null, 'type' => 'scalar', 'since' => 'PersistentParam2A', 'persist' => true],
], TestPresenter::getReflection()->getPersistentParams());

Assert::same([
'p1' => ['def' => 20, 'type' => 'integer', 'since' => 'BasePresenter'],
'p3' => ['def' => null, 'type' => 'scalar', 'since' => 'SecondPresenter'],
't1' => ['def' => null, 'type' => 'scalar', 'since' => 'PersistentParam1'],
't3' => ['def' => null, 'type' => 'scalar', 'since' => 'PersistentParam3'],
'p1' => ['def' => 20, 'type' => 'integer', 'since' => 'BasePresenter', 'persist' => true],
'p3' => ['def' => null, 'type' => 'scalar', 'since' => 'SecondPresenter', 'persist' => true],
't1' => ['def' => null, 'type' => 'scalar', 'since' => 'PersistentParam1', 'persist' => true],
't3' => ['def' => null, 'type' => 'scalar', 'since' => 'PersistentParam3', 'persist' => true],
], SecondPresenter::getReflection()->getPersistentParams());

Assert::same([
'p1' => ['def' => null, 'type' => 'scalar', 'since' => 'BasePresenter'],
't1' => ['def' => null, 'type' => 'scalar', 'since' => 'PersistentParam1'],
't2' => ['def' => null, 'type' => 'scalar', 'since' => 'PersistentParam2A'],
'p1' => ['def' => null, 'type' => 'scalar', 'since' => 'BasePresenter', 'persist' => true],
't1' => ['def' => null, 'type' => 'scalar', 'since' => 'PersistentParam1', 'persist' => true],
't2' => ['def' => null, 'type' => 'scalar', 'since' => 'PersistentParam2A', 'persist' => true],
], ThirdPresenter::getReflection()->getPersistentParams());

if (PHP_VERSION_ID >= 80000) {
Assert::same([
'p1' => ['def' => null, 'type' => 'scalar', 'since' => 'BasePresenter'],
't1' => ['def' => null, 'type' => 'scalar', 'since' => 'PersistentParam1'],
'p1' => ['def' => null, 'type' => 'scalar', 'since' => 'BasePresenter', 'persist' => true],
't1' => ['def' => null, 'type' => 'scalar', 'since' => 'PersistentParam1', 'persist' => true],
], FourthPresenter::getReflection()->getPersistentParams());
}

Expand Down

0 comments on commit 770a325

Please sign in to comment.