Skip to content

Commit 1acc593

Browse files
committed
PhpGenerator: added methods from()
1 parent 883cd64 commit 1acc593

File tree

8 files changed

+345
-3
lines changed

8 files changed

+345
-3
lines changed

src/PhpGenerator/ClassType.php

Lines changed: 40 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,8 @@
1111

1212
namespace Nette\Utils\PhpGenerator;
1313

14-
use Nette;
14+
use Nette,
15+
Nette\Utils\Strings;
1516

1617

1718

@@ -65,6 +66,42 @@ class ClassType extends Nette\Object
6566
public $methods = array();
6667

6768

69+
/** @return Class */
70+
public static function from($from)
71+
{
72+
$from = $from instanceof \ReflectionClass ? $from : new \ReflectionClass($from);
73+
$class = new static(/*5.2*PHP_VERSION_ID < 50300 ? $from->getName() : */$from->getShortName());
74+
$class->type = $from->isInterface() ? 'interface' : (PHP_VERSION_ID >= 50400 && $from->isTrait() ? 'trait' : 'class');
75+
$class->final = $from->isFinal();
76+
$class->abstract = $from->isAbstract() && $class->type === 'class';
77+
$class->implements = $from->getInterfaceNames();
78+
$class->documents = preg_replace('#^\s*\* ?#m', '', trim($from->getDocComment(), "/* \r\n"));
79+
$namespace = /*5.2*PHP_VERSION_ID < 50300 ? NULL : */$from->getNamespaceName();
80+
if ($from->getParentClass()) {
81+
$class->extends = $from->getParentClass()->getName();
82+
if ($namespace) {
83+
$class->extends = Strings::startsWith($class->extends, "$namespace\\") ? substr($class->extends, strlen($namespace) + 1) : '\\' . $class->extends;
84+
}
85+
$class->implements = array_diff($class->implements, $from->getParentClass()->getInterfaceNames());
86+
}
87+
if ($namespace) {
88+
foreach ($class->implements as & $interface) {
89+
$interface = Strings::startsWith($interface, "$namespace\\") ? substr($interface, strlen($namespace) + 1) : '\\' . $interface;
90+
}
91+
}
92+
foreach ($from->getProperties() as $prop) {
93+
$class->properties[] = Property::from($prop);
94+
}
95+
foreach ($from->getMethods() as $method) {
96+
if ($method->getDeclaringClass() == $from) { // intentionally ==
97+
$class->methods[] = Method::from($method);
98+
}
99+
}
100+
return $class;
101+
}
102+
103+
104+
68105
public function __construct($name)
69106
{
70107
$this->name = $name;
@@ -125,7 +162,7 @@ public function __toString()
125162
. ($property->value === NULL ? '' : ' = ' . Helpers::dump($property->value))
126163
. ";\n";
127164
}
128-
return Nette\Utils\Strings::normalize(
165+
return Strings::normalize(
129166
($this->documents ? str_replace("\n", "\n * ", "/**\n" . implode("\n", (array) $this->documents)) . "\n */\n" : '')
130167
. ($this->abstract ? 'abstract ' : '')
131168
. ($this->final ? 'final ' : '')
@@ -134,7 +171,7 @@ public function __toString()
134171
. ($this->extends ? 'extends ' . implode(', ', (array) $this->extends) . ' ' : '')
135172
. ($this->implements ? 'implements ' . implode(', ', (array) $this->implements) . ' ' : '')
136173
. "\n{\n\n"
137-
. Nette\Utils\Strings::indent(
174+
. Strings::indent(
138175
($this->traits ? "use " . implode(', ', (array) $this->traits) . ";\n\n" : '')
139176
. ($this->consts ? implode('', $consts) . "\n\n" : '')
140177
. ($this->properties ? implode("\n", $properties) . "\n\n" : '')

src/PhpGenerator/Method.php

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,27 @@ class Method extends Nette\Object
6262
public $documents = array();
6363

6464

65+
/** @return Method */
66+
public static function from($from)
67+
{
68+
$from = $from instanceof \ReflectionMethod ? $from : new \ReflectionMethod($from);
69+
$method = new static;
70+
$method->name = $from->getName();
71+
foreach ($from->getParameters() as $param) {
72+
$method->parameters[] = Parameter::from($param);
73+
}
74+
$method->static = $from->isStatic();
75+
$method->visibility = $from->isPrivate() ? 'private' : ($from->isProtected() ? 'protected' : '');
76+
$method->final = $from->isFinal();
77+
$method->abstract = $from->isAbstract() && !$from->getDeclaringClass()->isInterface();
78+
$method->body = $from->isAbstract() ? FALSE : '';
79+
$method->returnReference = $from->returnsReference();
80+
$method->documents = preg_replace('#^\s*\* ?#m', '', trim($from->getDocComment(), "/* \r\n"));
81+
return $method;
82+
}
83+
84+
85+
6586
/** @return Parameter */
6687
public function addParameter($name, $defaultValue = NULL)
6788
{

src/PhpGenerator/Parameter.php

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,33 @@ class Parameter extends Nette\Object
4444
public $defaultValue;
4545

4646

47+
/** @return Parameter */
48+
public static function from(\ReflectionParameter $from)
49+
{
50+
$param = new static;
51+
$param->name = $from->getName();
52+
$param->reference = $from->isPassedByReference();
53+
$param->optional = $from->isOptional() || $from->allowsNull();
54+
$param->defaultValue = $from->isOptional() ? $from->getDefaultValue() : NULL; // PHP bug #62988
55+
try {
56+
$param->typeHint = $from->isArray() ? 'array' : ($from->getClass() ? '\\' . $from->getClass()->getName() : '');
57+
} catch (\ReflectionException $e) {
58+
if (preg_match('#Class (.+) does not exist#', $e->getMessage(), $m)) {
59+
$param->typeHint = '\\' . $m[1];
60+
} else {
61+
throw $e;
62+
}
63+
}
64+
$namespace = /*5.2*PHP_VERSION_ID < 50300 ? '' : */$from->getDeclaringClass()->getNamespaceName();
65+
$namespace = $namespace ? "\\$namespace\\" : "\\";
66+
if (Nette\Utils\Strings::startsWith($param->typeHint, $namespace)) {
67+
$param->typeHint = substr($param->typeHint, strlen($namespace));
68+
}
69+
return $param;
70+
}
71+
72+
73+
4774
public function __call($name, $args)
4875
{
4976
return Nette\ObjectMixin::callProperty($this, $name, $args);

src/PhpGenerator/Property.php

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,21 @@ class Property extends Nette\Object
4444
public $documents = array();
4545

4646

47+
/** @return Property */
48+
public static function from(\ReflectionProperty $from)
49+
{
50+
$prop = new static;
51+
$prop->name = $from->getName();
52+
$defaults = $from->getDeclaringClass()->getDefaultProperties();
53+
$prop->value = isset($defaults[$from->name]) ? $defaults[$from->name] : NULL;
54+
$prop->static = $from->isStatic();
55+
$prop->visibility = $from->isPrivate() ? 'private' : ($from->isProtected() ? 'protected' : 'public');
56+
$prop->documents = preg_replace('#^\s*\* ?#m', '', trim($from->getDocComment(), "/* \r\n"));
57+
return $prop;
58+
}
59+
60+
61+
4762
public function __call($name, $args)
4863
{
4964
return Nette\ObjectMixin::callProperty($this, $name, $args);
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
/**
2+
* Interface
3+
* @author John Doe
4+
*/
5+
interface Interface1
6+
{
7+
8+
function func1();
9+
10+
}
11+
12+
interface Interface2
13+
{
14+
15+
16+
17+
}
18+
19+
abstract class Class1 implements Interface1
20+
{
21+
22+
/**
23+
* @return Class1
24+
*/
25+
function func1()
26+
{
27+
28+
}
29+
30+
31+
abstract protected function func2();
32+
33+
}
34+
35+
class Class2 extends Class1 implements Interface2
36+
{
37+
38+
/**
39+
* Public
40+
* @var int
41+
*
42+
*/
43+
public $public;
44+
45+
/**
46+
* @var int
47+
*/
48+
protected $protected = 10;
49+
50+
private $private = array();
51+
52+
public static $static;
53+
54+
55+
/**
56+
* Func3
57+
* @return Class1
58+
*
59+
*/
60+
private function & func3(array $a, Class2 $b = NULL, Unknown $c, \Xyz\Unknown $d)
61+
{
62+
63+
}
64+
65+
66+
final function func2()
67+
{
68+
69+
}
70+
71+
}
Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
<?php
2+
3+
/**
4+
* Test: Nette\Utils\PhpGenerator generator.
5+
*
6+
* @author David Grudl
7+
* @package Nette\Utils
8+
* @subpackage UnitTests
9+
* @phpversion 5.3
10+
*/
11+
12+
namespace Abc;
13+
14+
use Nette\Utils\PhpGenerator\ClassType,
15+
Assert,
16+
ReflectionClass;
17+
18+
19+
20+
require __DIR__ . '/../bootstrap.php';
21+
22+
23+
/**
24+
* Interface
25+
* @author John Doe
26+
*/
27+
interface Interface1
28+
{
29+
function func1();
30+
}
31+
32+
interface Interface2
33+
{
34+
}
35+
36+
abstract class Class1 implements Interface1
37+
{
38+
/** @return Class1 */
39+
function func1()
40+
{}
41+
42+
abstract protected function func2();
43+
}
44+
45+
class Class2 extends Class1 implements Interface2
46+
{
47+
/**
48+
* Public
49+
* @var int
50+
*/
51+
public $public;
52+
53+
/** @var int */
54+
protected $protected = 10;
55+
56+
private $private = array();
57+
58+
static public $static;
59+
60+
/**
61+
* Func3
62+
* @return Class1
63+
*/
64+
private function & func3(array $a = array(), Class2 $b = NULL, \Abc\Unknown $c, \Xyz\Unknown $d)
65+
{}
66+
67+
final function func2()
68+
{}
69+
}
70+
71+
72+
$res[] = ClassType::from('Abc\Interface1');
73+
$res[] = ClassType::from('Abc\Interface2');
74+
$res[] = ClassType::from('Abc\Class1');
75+
$res[] = ClassType::from(new ReflectionClass('Abc\Class2'));
76+
77+
Assert::match(file_get_contents(__DIR__ . '/PhpGenerator.reflection.expect'), implode("\n", $res));
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
/**
2+
* Trait1
3+
*/
4+
trait Trait1
5+
{
6+
7+
function func1()
8+
{
9+
10+
}
11+
12+
}
13+
14+
trait Trait2
15+
{
16+
17+
protected function func2()
18+
{
19+
20+
}
21+
22+
}
23+
24+
abstract class Class1
25+
{
26+
27+
function func1()
28+
{
29+
30+
}
31+
32+
33+
protected function func2()
34+
{
35+
36+
}
37+
38+
}
39+
40+
class Class2 extends Class1
41+
{
42+
43+
44+
45+
}

0 commit comments

Comments
 (0)