Skip to content

Commit

Permalink
added attribute #Parameter
Browse files Browse the repository at this point in the history
  • Loading branch information
dg committed Oct 2, 2023
1 parent 91fd723 commit 7916644
Show file tree
Hide file tree
Showing 4 changed files with 151 additions and 10 deletions.
18 changes: 18 additions & 0 deletions src/Application/Attributes/Parameter.php
@@ -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 Parameter
{
}
2 changes: 1 addition & 1 deletion src/Application/UI/Component.php
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->getParameters() 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
34 changes: 25 additions & 9 deletions src/Application/UI/ComponentReflection.php
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 class properties that are public and have attribute #[Persistent] or #[Parameter] or annotation @persistent.
*/
public function getPersistentParams(): array
public function getParameters(): array
{
$params = &self::$ppCache[$this->getName()];
if ($params !== null) {
Expand All @@ -45,26 +45,31 @@ public function getPersistentParams(): array
$params = [];
$isPresenter = $this->isSubclassOf(Presenter::class);
foreach ($this->getProperties(\ReflectionProperty::IS_PUBLIC) as $prop) {
if (!$prop->isStatic()
&& (self::parseAnnotation($prop, 'persistent')
|| (PHP_VERSION_ID >= 80000 && $prop->getAttributes(Nette\Application\Attributes\Persistent::class)))
if ($prop->isStatic()) {
continue;
} elseif (self::parseAnnotation($prop, 'persistent')

Check failure on line 50 in src/Application/UI/ComponentReflection.php

View workflow job for this annotation

GitHub Actions / PHPStan

Parameter #1 $ref of static method Nette\Application\UI\ComponentReflection::parseAnnotation() expects ReflectionClass|ReflectionMethod, ReflectionProperty given.
|| (PHP_VERSION_ID >= 80000 && $prop->getAttributes(Nette\Application\Attributes\Persistent::class))

Check failure on line 51 in src/Application/UI/ComponentReflection.php

View workflow job for this annotation

GitHub Actions / PHPStan

Call to an undefined method ReflectionProperty::getAttributes().
) {
$default = $prop->getDefaultValue();

Check failure on line 53 in src/Application/UI/ComponentReflection.php

View workflow job for this annotation

GitHub Actions / PHPStan

Call to an undefined method ReflectionProperty::getDefaultValue().
$params[$prop->getName()] = [
'def' => $default,
'type' => self::getPropertyType($prop, $default),
'since' => $isPresenter ? Nette\Utils\Reflection::getPropertyDeclaringClass($prop)->getName() : null,
];
} elseif (PHP_VERSION_ID >= 80000 && $prop->getAttributes(Nette\Application\Attributes\Parameter::class)) {
$params[$prop->getName()] = [
'type' => $prop->getType() ? (string) $prop->getType() : 'mixed',
];
}
}

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'];
} else {
foreach ($parent->getParameters() as $name => $meta) {
if (!isset($params[$name])) {
$params[$name] = $meta;
} elseif (array_key_exists('since', $params[$name])) {
$params[$name]['since'] = $meta['since'];
}
}
}
Expand All @@ -73,6 +78,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->getParameters(), function ($param) {
return array_key_exists('since', $param);
});
}


public function getPersistentComponents(): array
{
$class = $this->getName();
Expand Down
107 changes: 107 additions & 0 deletions tests/UI/Presenter.getParameters.phpt
@@ -0,0 +1,107 @@
<?php

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

declare(strict_types=1);

use Nette\Application\Attributes\Parameter;
use Nette\Application\Attributes\Persistent;
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, Parameter]
public $yes2; // Parameter is ignored

#[Parameter]
public $yes3;
}


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

#[Parameter]
public $yes4;
}


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

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

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

Assert::same(
[
'yes2' => [
'type' => 'mixed',
],
'yes4' => [
'type' => 'mixed',
],
'yes1' => [
'def' => null,
'type' => 'scalar',
'since' => 'OnePresenter',
],
'yes3' => [
'type' => 'mixed',
],
],
(new ComponentReflection(TwoPresenter::class))->getParameters()
);
}

0 comments on commit 7916644

Please sign in to comment.