Skip to content

Commit 5de8bde

Browse files
committed
Container, BaseControl: extension methods are implemented independently on ObjectMixin
1 parent d69a327 commit 5de8bde

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

@@ -557,7 +560,16 @@ public function getOptions(): array
557560

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

575587
}
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)