From a8c2e6564fc5c686cc8dc8c2b589861ddde3ffae Mon Sep 17 00:00:00 2001 From: David Grudl Date: Sat, 21 Jan 2017 18:16:07 +0100 Subject: [PATCH] Container, BaseControl: extension methods are implemented independently on ObjectMixin --- src/Forms/Container.php | 12 +++++-- src/Forms/Controls/BaseControl.php | 18 ++++++++-- tests/Forms/BaseControl.extensionMethod.phpt | 38 ++++++++++++++++++++ tests/Forms/Container.extensionMethod.phpt | 20 +++++++++++ 4 files changed, 82 insertions(+), 6 deletions(-) create mode 100644 tests/Forms/BaseControl.extensionMethod.phpt create mode 100644 tests/Forms/Container.extensionMethod.phpt diff --git a/src/Forms/Container.php b/src/Forms/Container.php index fde6dec5e..07ff5cc82 100644 --- a/src/Forms/Container.php +++ b/src/Forms/Container.php @@ -21,6 +21,9 @@ */ class Container extends Nette\ComponentModel\Container implements \ArrayAccess { + /** @var callable[] extension methods */ + private static $extMethods = []; + /** @var callable[] function (Container $sender); Occurs when the form is validated */ public $onValidate; @@ -410,19 +413,22 @@ public function addContainer($name): self public function __call(string $name, array $args) { - if ($callback = Nette\Utils\ObjectMixin::getExtensionMethod(__CLASS__, $name)) { + if (isset(self::$extMethods[$name])) { + return (self::$extMethods[$name])($this, ...$args); + } elseif ($callback = Nette\Utils\ObjectMixin::getExtensionMethod($class = __CLASS__, $name)) { + trigger_error("Define extension method '$name' via $class::extensionMethod('$name', ...), don't use Nette\\Object or Nette\\Utils\\ObjectMixin.", E_USER_DEPRECATED); return Nette\Utils\Callback::invoke($callback, $this, ...$args); } return parent::__call($name, $args); } - public static function extensionMethod($name, /*callable*/ $callback = NULL): void + public static function extensionMethod($name, /*callable*/ $callback): void { if (strpos($name, '::') !== FALSE) { // back compatibility [, $name] = explode('::', $name); } - Nette\Utils\ObjectMixin::setExtensionMethod(__CLASS__, $name, $callback); + self::$extMethods[$name] = $callback; } diff --git a/src/Forms/Controls/BaseControl.php b/src/Forms/Controls/BaseControl.php index 734057939..1a65402e1 100644 --- a/src/Forms/Controls/BaseControl.php +++ b/src/Forms/Controls/BaseControl.php @@ -40,6 +40,9 @@ abstract class BaseControl extends Nette\ComponentModel\Component implements ICo /** @var string */ public static $idMask = 'frm-%s'; + /** @var callable[][] extension methods */ + private static $extMethods = []; + /** @var string|object textual caption or label */ public $caption; @@ -556,19 +559,28 @@ public function getOptions(): array public function __call(string $name, array $args) { - if ($callback = Nette\Utils\ObjectMixin::getExtensionMethod(get_class($this), $name)) { + $class = static::class; + do { + if (isset(self::$extMethods[$name][$class])) { + return (self::$extMethods[$name][$class])($this, ...$args); + } + $class = get_parent_class($class); + } while ($class); + + if ($callback = Nette\Utils\ObjectMixin::getExtensionMethod($class = static::class, $name)) { + trigger_error("Define extension method '$name' via $class::extensionMethod('$name', ...), don't use Nette\\Object or Nette\\Utils\\ObjectMixin.", E_USER_DEPRECATED); return Nette\Utils\Callback::invoke($callback, $this, ...$args); } return parent::__call($name, $args); } - public static function extensionMethod(string $name, /*callable*/ $callback = NULL): void + public static function extensionMethod($name, /*callable*/ $callback): void { if (strpos($name, '::') !== FALSE) { // back compatibility [, $name] = explode('::', $name); } - Nette\Utils\ObjectMixin::setExtensionMethod(get_called_class(), $name, $callback); + self::$extMethods[$name][static::class] = $callback; } } diff --git a/tests/Forms/BaseControl.extensionMethod.phpt b/tests/Forms/BaseControl.extensionMethod.phpt new file mode 100644 index 000000000..6231fc330 --- /dev/null +++ b/tests/Forms/BaseControl.extensionMethod.phpt @@ -0,0 +1,38 @@ +test(1, 2)); + +$control2 = new Checkbox; +Assert::same('Checkbox', $control2->test(1, 2)); + +Assert::exception(function () { + $control3 = new Button; + $control3->test(1, 2); +}, Nette\MemberAccessException::class); diff --git a/tests/Forms/Container.extensionMethod.phpt b/tests/Forms/Container.extensionMethod.phpt new file mode 100644 index 000000000..6dbf79132 --- /dev/null +++ b/tests/Forms/Container.extensionMethod.phpt @@ -0,0 +1,20 @@ +test(1, 2));