• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

nette / php-generator / 21808450793

09 Feb 2026 12:39AM UTC coverage: 93.947% (+0.1%) from 93.811%
21808450793

push

github

dg
added CLAUDE.md

1816 of 1933 relevant lines covered (93.95%)

0.94 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

94.34
/src/PhpGenerator/ClassManipulator.php
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
use const PHP_VERSION_ID;
14

15

16
final class ClassManipulator
17
{
18
        public function __construct(
1✔
19
                private readonly ClassType $class,
20
        ) {
21
        }
1✔
22

23

24
        /**
25
         * Inherits property from parent class.
26
         */
27
        public function inheritProperty(string $name, bool $returnIfExists = false): Property
1✔
28
        {
29
                if ($this->class->hasProperty($name)) {
1✔
30
                        return $returnIfExists
1✔
31
                                ? $this->class->getProperty($name)
1✔
32
                                : throw new Nette\InvalidStateException("Cannot inherit property '$name', because it already exists.");
1✔
33
                }
34

35
                $parents = [...(array) $this->class->getExtends(), ...$this->class->getImplements()]
1✔
36
                        ?: throw new Nette\InvalidStateException("Class '{$this->class->getName()}' has neither setExtends() nor setImplements() set.");
1✔
37

38
                foreach ($parents as $parent) {
1✔
39
                        try {
40
                                $rp = new \ReflectionProperty($parent, $name);
1✔
41
                        } catch (\ReflectionException) {
1✔
42
                                continue;
1✔
43
                        }
44
                        return $this->implementProperty($rp);
1✔
45
                }
46

47
                throw new Nette\InvalidStateException("Property '$name' has not been found in any ancestor: " . implode(', ', $parents));
1✔
48
        }
49

50

51
        /**
52
         * Inherits method from parent class or interface.
53
         */
54
        public function inheritMethod(string $name, bool $returnIfExists = false): Method
1✔
55
        {
56
                if ($this->class->hasMethod($name)) {
1✔
57
                        return $returnIfExists
1✔
58
                                ? $this->class->getMethod($name)
1✔
59
                                : throw new Nette\InvalidStateException("Cannot inherit method '$name', because it already exists.");
1✔
60
                }
61

62
                $parents = [...(array) $this->class->getExtends(), ...$this->class->getImplements()]
1✔
63
                        ?: throw new Nette\InvalidStateException("Class '{$this->class->getName()}' has neither setExtends() nor setImplements() set.");
1✔
64

65
                foreach ($parents as $parent) {
1✔
66
                        try {
67
                                $rm = new \ReflectionMethod($parent, $name);
1✔
68
                        } catch (\ReflectionException) {
1✔
69
                                continue;
1✔
70
                        }
71
                        return $this->implementMethod($rm);
1✔
72
                }
73

74
                throw new Nette\InvalidStateException("Method '$name' has not been found in any ancestor: " . implode(', ', $parents));
1✔
75
        }
76

77

78
        /**
79
         * Implements all methods from the given interface or abstract class.
80
         * @param class-string  $name
81
         */
82
        public function implement(string $name): void
1✔
83
        {
84
                $definition = new \ReflectionClass($name);
1✔
85
                if ($definition->isInterface()) {
1✔
86
                        $this->class->addImplement($name);
1✔
87
                } elseif ($definition->isAbstract()) {
1✔
88
                        $this->class->setExtends($name);
1✔
89
                } else {
90
                        throw new Nette\InvalidArgumentException("'$name' is not an interface or abstract class.");
1✔
91
                }
92

93
                foreach ($definition->getMethods() as $method) {
1✔
94
                        if (!$this->class->hasMethod($method->getName()) && $method->isAbstract()) {
1✔
95
                                $this->implementMethod($method);
1✔
96
                        }
97
                }
98

99
                if (PHP_VERSION_ID >= 80400) {
1✔
100
                        foreach ($definition->getProperties() as $property) {
×
101
                                if (!$this->class->hasProperty($property->getName()) && $property->isAbstract()) {
×
102
                                        $this->implementProperty($property);
×
103
                                }
104
                        }
105
                }
106
        }
1✔
107

108

109
        private function implementMethod(\ReflectionMethod $rm): Method
1✔
110
        {
111
                $method = (new Factory)->fromMethodReflection($rm);
1✔
112
                $method->setAbstract(false);
1✔
113
                $this->class->addMember($method);
1✔
114
                return $method;
1✔
115
        }
116

117

118
        private function implementProperty(\ReflectionProperty $rp): Property
1✔
119
        {
120
                $property = (new Factory)->fromPropertyReflection($rp);
1✔
121
                $property->setHooks([])->setAbstract(false);
1✔
122
                $this->class->addMember($property);
1✔
123
                return $property;
1✔
124
        }
125
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc