Skip to content

Commit

Permalink
SmartObject: supports property deprecation
Browse files Browse the repository at this point in the history
  • Loading branch information
dg committed Jan 1, 2022
1 parent 77fc958 commit 7e22bc1
Show file tree
Hide file tree
Showing 3 changed files with 44 additions and 4 deletions.
21 changes: 19 additions & 2 deletions src/SmartObject.php
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,15 @@ public function &__get(string $name): mixed
throw new MemberAccessException("Cannot read a write-only property $class::\$$name.");
}

$m = ($prop & 0b0010 ? 'get' : 'is') . $name;
$m = ($prop & 0b0010 ? 'get' : 'is') . ucfirst($name);
if ($prop & 0b10000) {
$trace = debug_backtrace(0, 1)[0]; // suppose this method is called from __call()
$loc = isset($trace['file'], $trace['line'])
? " in $trace[file] on line $trace[line]"
: '';
trigger_error("Property $class::\$$name is deprecated, use $class::$m() method$loc.", E_USER_DEPRECATED);
}

if ($prop & 0b0100) { // return by reference
return $this->$m();
} else {
Expand Down Expand Up @@ -94,7 +102,16 @@ public function __set(string $name, mixed $value): void
throw new MemberAccessException("Cannot write to a read-only property $class::\$$name.");
}

$this->{'set' . $name}($value);
$m = 'set' . ucfirst($name);
if ($prop & 0b10000) {
$trace = debug_backtrace(0, 1)[0]; // suppose this method is called from __call()
$loc = isset($trace['file'], $trace['line'])
? " in $trace[file] on line $trace[line]"
: '';
trigger_error("Property $class::\$$name is deprecated, use $class::$m() method$loc.", E_USER_DEPRECATED);
}

$this->$m($value);

} else {
ObjectHelpers::strictSet($class, $name);
Expand Down
4 changes: 2 additions & 2 deletions src/Utils/ObjectHelpers.php
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,7 @@ public static function getMagicProperties(string $class): array

$rc = new \ReflectionClass($class);
preg_match_all(
'~^ [ \t*]* @property(|-read|-write) [ \t]+ [^\s$]+ [ \t]+ \$ (\w+) ()~mx',
'~^ [ \t*]* @property(|-read|-write|-deprecated) [ \t]+ [^\s$]+ [ \t]+ \$ (\w+) ()~mx',
(string) $rc->getDocComment(),
$matches,
PREG_SET_ORDER,
Expand All @@ -147,7 +147,7 @@ public static function getMagicProperties(string $class): array
&& ($rm = $rc->getMethod($nm))->name === $nm && !$rm->isPrivate() && !$rm->isStatic();

if ($read || $write) {
$props[$name] = $read << 0 | ($nm[0] === 'g') << 1 | $rm->returnsReference() << 2 | $write << 3;
$props[$name] = $read << 0 | ($nm[0] === 'g') << 1 | $rm->returnsReference() << 2 | $write << 3 | ($type === '-deprecated') << 4;
}
}

Expand Down
23 changes: 23 additions & 0 deletions tests/Utils/SmartObject.property.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ require __DIR__ . '/../bootstrap.php';
* @property int $bar
* @property int $bazz
* @property int $s
* @property-deprecated int $depr
*/
class TestClass
{
Expand Down Expand Up @@ -69,6 +70,16 @@ class TestClass
echo __METHOD__;
return 'ERROR';
}


public function setDepr($value)
{
}


public function getDepr()
{
}
}


Expand Down Expand Up @@ -115,3 +126,15 @@ Assert::same('World', $obj->bar);
Assert::exception(function () use ($obj) {
$val = $obj->bazz;
}, Nette\MemberAccessException::class, 'Cannot read a write-only property TestClass::$bazz.');


// deprecated property
Assert::error(function () {
$obj = new TestClass;
$obj->depr = 10;
}, E_USER_DEPRECATED, 'Property TestClass::$depr is deprecated, use TestClass::setDepr() method in %a%SmartObject.property.phpt on line %d%.');

Assert::error(function () {
$obj = new TestClass;
$val = $obj->depr;
}, E_USER_DEPRECATED, 'Property TestClass::$depr is deprecated, use TestClass::getDepr() method in %a%SmartObject.property.phpt on line %d%.');

0 comments on commit 7e22bc1

Please sign in to comment.