Skip to content

Commit

Permalink
SmartObject: added support for annotations in traits (thx @matej21) [C…
Browse files Browse the repository at this point in the history
…loses #121]
  • Loading branch information
dg committed Sep 28, 2016
1 parent 47dc563 commit a2c86f4
Show file tree
Hide file tree
Showing 3 changed files with 180 additions and 0 deletions.
9 changes: 9 additions & 0 deletions src/Utils/ObjectMixin.php
Original file line number Diff line number Diff line change
Expand Up @@ -299,6 +299,10 @@ public static function getMagicProperties($class)
}
}

foreach ($rc->getTraits() as $trait) {
$props += self::getMagicProperties($trait->getName());
}

if ($parent = get_parent_class($class)) {
$props += self::getMagicProperties($parent);
}
Expand Down Expand Up @@ -512,6 +516,11 @@ private static function parseFullDoc(\ReflectionClass $rc, $pattern)
{
do {
$doc[] = $rc->getDocComment();
$traits = $rc->getTraits();
while ($trait = array_pop($traits)) {
$doc[] = $trait->getDocComment();
$traits += $trait->getTraits();
}
} while ($rc = $rc->getParentClass());
return preg_match_all($pattern, implode($doc), $m) ? $m[1] : [];
}
Expand Down
101 changes: 101 additions & 0 deletions tests/Utils/SmartObject.property.inheritance.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
<?php

/**
* Test: Nette\SmartObject properties and inheritance.
*/

use Tester\Assert;

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


/**
* @property int $traitA
*/
trait TraitA
{
public function getTraitA()
{
return __FUNCTION__;
}
}

/**
* @property int $traitB
*/
trait TraitB
{
public function getTraitB()
{
return __FUNCTION__;
}
}

/**
* @property int $traitC
*/
trait TraitC
{
use TraitB;

public function getTraitC()
{
return __FUNCTION__;
}
}

/**
* @property int $classA
*/
class ParentClass
{
use Nette\SmartObject;
use TraitA;

public function getClassA()
{
return __FUNCTION__;
}
}

/**
* @property int $classB
*/
class ChildClass extends ParentClass
{
use TraitC;

public function getClassB()
{
return __FUNCTION__;
}
}


$obj = new ChildClass;

Assert::same('getTraitA', $obj->traitA);
Assert::same('getTraitB', $obj->traitB);
Assert::same('getTraitC', $obj->traitC);
Assert::same('getClassA', $obj->classA);
Assert::same('getClassB', $obj->classB);

Assert::exception(function () use ($obj) {
$obj->classBX;
}, Nette\MemberAccessException::class, 'Cannot read an undeclared property ChildClass::$classBX, did you mean $classB?');

Assert::exception(function () use ($obj) {
$obj->classAX;
}, Nette\MemberAccessException::class, 'Cannot read an undeclared property ChildClass::$classAX, did you mean $classA?');

Assert::exception(function () use ($obj) {
$obj->traitCX;
}, Nette\MemberAccessException::class, 'Cannot read an undeclared property ChildClass::$traitCX, did you mean $traitC?');

Assert::exception(function () use ($obj) {
$obj->traitBX;
}, Nette\MemberAccessException::class, 'Cannot read an undeclared property ChildClass::$traitBX, did you mean $traitB?');

Assert::exception(function () use ($obj) {
$obj->traitAX;
}, Nette\MemberAccessException::class, 'Cannot read an undeclared property ChildClass::$traitAX, did you mean $traitA?');
70 changes: 70 additions & 0 deletions tests/Utils/SmartObject.undeclaredMethod.annotation.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
<?php

/**
* Test: Nette\SmartObject undeclared method and annotation @method.
*/

use Tester\Assert;

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


/**
* @method traitA()
*/
trait TraitA
{}

/**
* @method traitB()
*/
trait TraitB
{}

/**
* @method traitC()
*/
trait TraitC
{
use TraitB;
}

/**
* @method classA()
*/
class ParentClass
{
use Nette\SmartObject;
use TraitA;
}

/**
* @method classB()
*/
class ChildClass extends ParentClass
{
use TraitC;
}


$obj = new ChildClass;

Assert::exception(function () use ($obj) {
$obj->classBX();
}, Nette\MemberAccessException::class, 'Call to undefined method ChildClass::classBX(), did you mean classB()?');

Assert::exception(function () use ($obj) {
$obj->classAX();
}, Nette\MemberAccessException::class, 'Call to undefined method ChildClass::classAX(), did you mean classA()?');

Assert::exception(function () use ($obj) {
$obj->traitCX();
}, Nette\MemberAccessException::class, 'Call to undefined method ChildClass::traitCX(), did you mean traitC()?');

Assert::exception(function () use ($obj) {
$obj->traitBX();
}, Nette\MemberAccessException::class, 'Call to undefined method ChildClass::traitBX(), did you mean traitB()?');

Assert::exception(function () use ($obj) {
$obj->traitAX();
}, Nette\MemberAccessException::class, 'Call to undefined method ChildClass::traitAX(), did you mean traitA()?');

0 comments on commit a2c86f4

Please sign in to comment.