Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit d049640

Browse files
committed
added ClassManipulator
1 parent 6c438e0 commit d049640

File tree

5 files changed

+150
-53
lines changed

5 files changed

+150
-53
lines changed
Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
<?php
2+
3+
/**
4+
* This file is part of the Nette Framework (https://nette.org)
5+
* Copyright (c) 2004 David Grudl (https://davidgrudl.com)
6+
*/
7+
8+
declare(strict_types=1);
9+
10+
namespace Nette\PhpGenerator;
11+
12+
use Nette;
13+
14+
15+
final class ClassManipulator
16+
{
17+
public function __construct(
18+
private ClassType $class,
19+
) {
20+
}
21+
22+
23+
/**
24+
* Inherits property from parent class.
25+
*/
26+
public function inheritProperty(string $name, bool $returnIfExists = false): Property
27+
{
28+
$extends = $this->class->getExtends();
29+
if ($this->class->hasProperty($name)) {
30+
return $returnIfExists
31+
? $this->class->getProperty($name)
32+
: throw new Nette\InvalidStateException("Cannot inherit property '$name', because it already exists.");
33+
34+
} elseif (!$extends) {
35+
throw new Nette\InvalidStateException("Class '{$this->class->getName()}' has not setExtends() set.");
36+
}
37+
38+
try {
39+
$rp = new \ReflectionProperty($extends, $name);
40+
} catch (\ReflectionException) {
41+
throw new Nette\InvalidStateException("Property '$name' has not been found in ancestor {$extends}");
42+
}
43+
44+
$property = (new Factory)->fromPropertyReflection($rp);
45+
$this->class->addMember($property);
46+
return $property;
47+
}
48+
49+
50+
/**
51+
* Inherits method from parent class or interface.
52+
*/
53+
public function inheritMethod(string $name, bool $returnIfExists = false): Method
54+
{
55+
$parents = [...(array) $this->class->getExtends(), ...$this->class->getImplements()];
56+
if ($this->class->hasMethod($name)) {
57+
return $returnIfExists
58+
? $this->class->getMethod($name)
59+
: throw new Nette\InvalidStateException("Cannot inherit method '$name', because it already exists.");
60+
61+
} elseif (!$parents) {
62+
throw new Nette\InvalidStateException("Class '{$this->class->getName()}' has neither setExtends() nor setImplements() set.");
63+
}
64+
65+
foreach ($parents as $parent) {
66+
try {
67+
$rm = new \ReflectionMethod($parent, $name);
68+
} catch (\ReflectionException) {
69+
continue;
70+
}
71+
$method = (new Factory)->fromMethodReflection($rm);
72+
$this->class->addMember($method);
73+
return $method;
74+
}
75+
76+
throw new Nette\InvalidStateException("Method '$name' has not been found in any ancestor: " . implode(', ', $parents));
77+
}
78+
79+
80+
/**
81+
* Implements all methods from the given interface.
82+
*/
83+
public function implementInterface(string $interfaceName): void
84+
{
85+
$interface = new \ReflectionClass($interfaceName);
86+
if (!$interface->isInterface()) {
87+
throw new Nette\InvalidArgumentException("Class '$interfaceName' is not an interface.");
88+
}
89+
90+
$this->class->addImplement($interfaceName);
91+
foreach ($interface->getMethods() as $method) {
92+
$this->inheritMethod($method->getName(), returnIfExists: true);
93+
}
94+
}
95+
}

‎src/PhpGenerator/ClassType.php‎

Lines changed: 4 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -195,55 +195,20 @@ public function addMember(Method|Property|Constant|TraitUse $member, bool $overw
195195

196196

197197
/**
198-
* Inherits property from parent class.
198+
* @deprecated use ClassManipulator::inheritProperty()
199199
*/
200200
public function inheritProperty(string $name, bool $returnIfExists = false): Property
201201
{
202-
if (isset($this->properties[$name])) {
203-
return $returnIfExists
204-
? $this->properties[$name]
205-
: throw new Nette\InvalidStateException("Cannot inherit property '$name', because it already exists.");
206-
207-
} elseif (!$this->extends) {
208-
throw new Nette\InvalidStateException("Class '{$this->getName()}' has not setExtends() set.");
209-
}
210-
211-
try {
212-
$rp = new \ReflectionProperty($this->extends, $name);
213-
} catch (\ReflectionException) {
214-
throw new Nette\InvalidStateException("Property '$name' has not been found in ancestor {$this->extends}");
215-
}
216-
217-
return $this->properties[$name] = (new Factory)->fromPropertyReflection($rp);
202+
return (new ClassManipulator($this))->inheritProperty($name, $returnIfExists);
218203
}
219204

220205

221206
/**
222-
* Inherits method from parent class or interface.
207+
* @deprecated use ClassManipulator::inheritMethod()
223208
*/
224209
public function inheritMethod(string $name, bool $returnIfExists = false): Method
225210
{
226-
$lower = strtolower($name);
227-
$parents = [...(array) $this->extends, ...$this->implements];
228-
if (isset($this->methods[$lower])) {
229-
return $returnIfExists
230-
? $this->methods[$lower]
231-
: throw new Nette\InvalidStateException("Cannot inherit method '$name', because it already exists.");
232-
233-
} elseif (!$parents) {
234-
throw new Nette\InvalidStateException("Class '{$this->getName()}' has neither setExtends() nor setImplements() set.");
235-
}
236-
237-
foreach ($parents as $parent) {
238-
try {
239-
$rm = new \ReflectionMethod($parent, $name);
240-
} catch (\ReflectionException) {
241-
continue;
242-
}
243-
return $this->methods[$lower] = (new Factory)->fromMethodReflection($rm);
244-
}
245-
246-
throw new Nette\InvalidStateException("Method '$name' has not been found in any ancestor: " . implode(', ', $parents));
211+
return (new ClassManipulator($this))->inheritMethod($name, $returnIfExists);
247212
}
248213

249214

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
use Nette\PhpGenerator\ClassManipulator;
6+
use Nette\PhpGenerator\ClassType;
7+
use Tester\Assert;
8+
9+
require __DIR__ . '/../bootstrap.php';
10+
11+
12+
interface TestInterface
13+
{
14+
public function testMethod();
15+
}
16+
17+
$class = new ClassType('TestClass');
18+
$manipulator = new ClassManipulator($class);
19+
20+
// Test valid interface implementation
21+
$manipulator->implementInterface(TestInterface::class);
22+
Assert::true(in_array(TestInterface::class, $class->getImplements(), true));
23+
Assert::true($class->hasMethod('testMethod'));
24+
25+
// Test exception for non-interface
26+
Assert::exception(
27+
fn() => $manipulator->implementInterface(stdClass::class),
28+
InvalidArgumentException::class,
29+
);

‎tests/PhpGenerator/Method.inherit.phpt‎ renamed to ‎tests/PhpGenerator/ClassManipulator.inheritMethod.phpt‎

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22

33
declare(strict_types=1);
44

5+
use Nette\PhpGenerator\ClassManipulator;
6+
use Nette\PhpGenerator\ClassType;
57
use Tester\Assert;
68

79
require __DIR__ . '/../bootstrap.php';
@@ -16,36 +18,38 @@ class Foo
1618

1719

1820
// missing parent
19-
$class = new Nette\PhpGenerator\ClassType('Test');
21+
$class = new ClassType('Test');
22+
$manipulator = new ClassManipulator($class);
2023
Assert::exception(
21-
fn() => $class->inheritMethod('bar'),
24+
fn() => $manipulator->inheritMethod('bar'),
2225
Nette\InvalidStateException::class,
2326
"Class 'Test' has neither setExtends() nor setImplements() set.",
2427
);
2528

2629
$class->setExtends('Unknown1');
2730
$class->addImplement('Unknown2');
2831
Assert::exception(
29-
fn() => $class->inheritMethod('bar'),
32+
fn() => $manipulator->inheritMethod('bar'),
3033
Nette\InvalidStateException::class,
3134
"Method 'bar' has not been found in any ancestor: Unknown1, Unknown2",
3235
);
3336

3437

3538
// implement method
36-
$class = new Nette\PhpGenerator\ClassType('Test');
39+
$class = new ClassType('Test');
3740
$class->setExtends(Foo::class);
38-
$method = $class->inheritMethod('bar');
41+
$manipulator = new ClassManipulator($class);
42+
$method = $manipulator->inheritMethod('bar');
3943
Assert::match(<<<'XX'
4044
public function bar(int $a, ...$b): void
4145
{
4246
}
4347

4448
XX, (string) $method);
4549

46-
Assert::same($method, $class->inheritMethod('bar', returnIfExists: true));
50+
Assert::same($method, $manipulator->inheritMethod('bar', returnIfExists: true));
4751
Assert::exception(
48-
fn() => $class->inheritMethod('bar', returnIfExists: false),
52+
fn() => $manipulator->inheritMethod('bar', returnIfExists: false),
4953
Nette\InvalidStateException::class,
5054
"Cannot inherit method 'bar', because it already exists.",
5155
);

‎tests/PhpGenerator/Property.inherit.phpt‎ renamed to ‎tests/PhpGenerator/ClassManipulator.inheritProperty.phpt‎

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22

33
declare(strict_types=1);
44

5+
use Nette\PhpGenerator\ClassManipulator;
6+
use Nette\PhpGenerator\ClassType;
57
use Tester\Assert;
68

79
require __DIR__ . '/../bootstrap.php';
@@ -14,25 +16,27 @@ class Foo
1416

1517

1618
// missing parent
17-
$class = new Nette\PhpGenerator\ClassType('Test');
19+
$class = new ClassType('Test');
20+
$manipulator = new ClassManipulator($class);
1821
Assert::exception(
19-
fn() => $class->inheritProperty('bar'),
22+
fn() => $manipulator->inheritProperty('bar'),
2023
Nette\InvalidStateException::class,
2124
"Class 'Test' has not setExtends() set.",
2225
);
2326

2427
$class->setExtends('Unknown');
2528
Assert::exception(
26-
fn() => $class->inheritProperty('bar'),
29+
fn() => $manipulator->inheritProperty('bar'),
2730
Nette\InvalidStateException::class,
2831
"Property 'bar' has not been found in ancestor Unknown",
2932
);
3033

3134

3235
// implement property
33-
$class = new Nette\PhpGenerator\ClassType('Test');
36+
$class = new ClassType('Test');
3437
$class->setExtends(Foo::class);
35-
$prop = $class->inheritProperty('bar');
38+
$manipulator = new ClassManipulator($class);
39+
$prop = $manipulator->inheritProperty('bar');
3640
Assert::match(<<<'XX'
3741
class Test extends Foo
3842
{
@@ -41,9 +45,9 @@ Assert::match(<<<'XX'
4145

4246
XX, (string) $class);
4347

44-
Assert::same($prop, $class->inheritProperty('bar', returnIfExists: true));
48+
Assert::same($prop, $manipulator->inheritProperty('bar', returnIfExists: true));
4549
Assert::exception(
46-
fn() => $class->inheritProperty('bar', returnIfExists: false),
50+
fn() => $manipulator->inheritProperty('bar', returnIfExists: false),
4751
Nette\InvalidStateException::class,
4852
"Cannot inherit property 'bar', because it already exists.",
4953
);

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /