Skip to content

Commit bcd9d51

Browse files
committed
Container, BaseControl: extension methods are implemented independently on ObjectMixin
1 parent 35c19af commit bcd9d51

4 files changed

Lines changed: 80 additions & 4 deletions

File tree

src/Forms/Container.php

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,9 @@
2121
*/
2222
class Container extends Nette\ComponentModel\Container implements \ArrayAccess
2323
{
24+
/** @var callable[] extension methods */
25+
private static $extMethods = [];
26+
2427
/** @var callable[] function (Container $sender); Occurs when the form is validated */
2528
public $onValidate;
2629

@@ -411,7 +414,10 @@ public function addContainer($name): self
411414

412415
public function __call($name, $args)
413416
{
414-
if ($callback = Nette\Utils\ObjectMixin::getExtensionMethod(__CLASS__, $name)) {
417+
if (isset(self::$extMethods[$name])) {
418+
return (self::$extMethods[$name])($this, ...$args);
419+
} elseif ($callback = Nette\Utils\ObjectMixin::getExtensionMethod($class = __CLASS__, $name)) {
420+
trigger_error("Define extension method '$name' via $class::extensionMethod('$name', ...), don't use Nette\\Object or Nette\\Utils\\ObjectMixin.", E_USER_DEPRECATED);
415421
return Nette\Utils\Callback::invoke($callback, $this, ...$args);
416422
}
417423
return parent::__call($name, $args);
@@ -423,7 +429,7 @@ public static function extensionMethod($name, $callback = NULL)
423429
if (strpos($name, '::') !== FALSE) { // back compatibility
424430
[, $name] = explode('::', $name);
425431
}
426-
Nette\Utils\ObjectMixin::setExtensionMethod(__CLASS__, $name, $callback);
432+
self::$extMethods[$name] = $callback;
427433
}
428434

429435

src/Forms/Controls/BaseControl.php

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,9 @@ abstract class BaseControl extends Nette\ComponentModel\Component implements ICo
4040
/** @var string */
4141
public static $idMask = 'frm-%s';
4242

43+
/** @var callable[][] extension methods */
44+
private static $extMethods = [];
45+
4346
/** @var string|object textual caption or label */
4447
public $caption;
4548

@@ -558,7 +561,16 @@ public function getOptions(): array
558561

559562
public function __call($name, $args)
560563
{
561-
if ($callback = Nette\Utils\ObjectMixin::getExtensionMethod(get_class($this), $name)) {
564+
$class = static::class;
565+
do {
566+
if (isset(self::$extMethods[$name][$class])) {
567+
return (self::$extMethods[$name][$class])($this, ...$args);
568+
}
569+
$class = get_parent_class($class);
570+
} while ($class);
571+
572+
if ($callback = Nette\Utils\ObjectMixin::getExtensionMethod($class = static::class, $name)) {
573+
trigger_error("Define extension method '$name' via $class::extensionMethod('$name', ...), don't use Nette\\Object or Nette\\Utils\\ObjectMixin.", E_USER_DEPRECATED);
562574
return Nette\Utils\Callback::invoke($callback, $this, ...$args);
563575
}
564576
return parent::__call($name, $args);
@@ -570,7 +582,7 @@ public static function extensionMethod($name, $callback = NULL)
570582
if (strpos($name, '::') !== FALSE) { // back compatibility
571583
[, $name] = explode('::', $name);
572584
}
573-
Nette\Utils\ObjectMixin::setExtensionMethod(get_called_class(), $name, $callback);
585+
self::$extMethods[$name][static::class] = $callback;
574586
}
575587

576588
}
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
use Nette\Forms\Controls\TextBase;
6+
use Nette\Forms\Controls\TextInput;
7+
use Nette\Forms\Controls\Checkbox;
8+
use Nette\Forms\Controls\Button;
9+
use Tester\Assert;
10+
11+
12+
require __DIR__ . '/../bootstrap.php';
13+
14+
15+
TextBase::extensionMethod('test', function ($control, $a, $b) {
16+
Assert::type(TextInput::class, $control);
17+
Assert::same(1, $a);
18+
Assert::same(2, $b);
19+
return 'TextInput';
20+
});
21+
22+
Checkbox::extensionMethod('test', function ($control, $a, $b) {
23+
Assert::type(Checkbox::class, $control);
24+
Assert::same(1, $a);
25+
Assert::same(2, $b);
26+
return 'Checkbox';
27+
});
28+
29+
$control1 = new TextInput;
30+
Assert::same('TextInput', $control1->test(1, 2));
31+
32+
$control2 = new Checkbox;
33+
Assert::same('Checkbox', $control2->test(1, 2));
34+
35+
Assert::exception(function () {
36+
$control3 = new Button;
37+
$control3->test(1, 2);
38+
}, Nette\MemberAccessException::class);
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
use Nette\Forms\Form;
6+
use Tester\Assert;
7+
8+
9+
require __DIR__ . '/../bootstrap.php';
10+
11+
12+
Nette\Forms\Container::extensionMethod('test', function ($form, $a, $b) {
13+
Assert::type(Nette\Forms\Form::class, $form);
14+
Assert::same(1, $a);
15+
Assert::same(2, $b);
16+
return 3;
17+
});
18+
19+
$form = new Form;
20+
Assert::same(3, $form->test(1, 2));

0 commit comments

Comments
 (0)