Skip to content
This repository was archived by the owner on Jan 29, 2020. It is now read-only.

Commit 47892b3

Browse files
committed
Merge branch 'feature/169' into develop
Close #169
2 parents 14fee05 + 3743c26 commit 47892b3

File tree

4 files changed

+308
-0
lines changed

4 files changed

+308
-0
lines changed

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@ All notable changes to this project will be documented in this file, in reverse
88

99
- [#170](https://github.com/zendframework/zend-code/pull/170) adds class constant visibility modifiers support.
1010

11+
- [#169](https://github.com/zendframework/zend-code/pull/169) adds the ability to define declare statements.
12+
1113
- [#167](https://github.com/zendframework/zend-code/pull/167) adds the ability to remove doc block of a member.
1214

1315
### Changed

src/DeclareStatement.php

Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,116 @@
1+
<?php
2+
3+
namespace Zend\Code;
4+
5+
use Zend\Code\Exception\InvalidArgumentException;
6+
7+
class DeclareStatement
8+
{
9+
public const TICKS = 'ticks';
10+
public const STRICT_TYPES = 'strict_types';
11+
public const ENCODING = 'encoding';
12+
13+
private const ALLOWED = [
14+
self::TICKS => 'integer',
15+
self::STRICT_TYPES => 'integer',
16+
self::ENCODING => 'string',
17+
];
18+
19+
/**
20+
* @var string
21+
*/
22+
protected $directive;
23+
24+
/**
25+
* @var int|string
26+
*/
27+
protected $value;
28+
29+
private function __construct(string $directive, $value)
30+
{
31+
$this->directive = $directive;
32+
$this->value = $value;
33+
}
34+
35+
/**
36+
* @return string
37+
*/
38+
public function getDirective(): string
39+
{
40+
return $this->directive;
41+
}
42+
43+
/**
44+
* @return int|string
45+
*/
46+
public function getValue()
47+
{
48+
return $this->value;
49+
}
50+
51+
/**
52+
* @param int $value
53+
* @return self
54+
*/
55+
public static function ticks(int $value): self
56+
{
57+
return new self(self::TICKS, $value);
58+
}
59+
60+
/**
61+
* @param int $value
62+
* @return self
63+
*/
64+
public static function strictTypes(int $value): self
65+
{
66+
return new self(self::STRICT_TYPES, $value);
67+
}
68+
69+
/**
70+
* @param string $value
71+
* @return self
72+
*/
73+
public static function encoding(string $value): self
74+
{
75+
return new self(self::ENCODING, $value);
76+
}
77+
78+
public static function fromArray(array $config): self
79+
{
80+
$directive = key($config);
81+
$value = $config[$directive];
82+
83+
if (! isset(self::ALLOWED[$directive])) {
84+
throw new InvalidArgumentException(
85+
sprintf(
86+
'Declare directive must be one of: %s.',
87+
implode(', ', array_keys(self::ALLOWED))
88+
)
89+
);
90+
}
91+
92+
if (gettype($value) !== self::ALLOWED[$directive]) {
93+
throw new InvalidArgumentException(
94+
sprintf(
95+
'Declare value invalid. Expected %s, got %s.',
96+
self::ALLOWED[$directive],
97+
gettype($value)
98+
)
99+
);
100+
}
101+
102+
$method = str_replace('_', '', lcfirst(ucwords($directive, '_')));
103+
104+
return self::{$method}($value);
105+
}
106+
107+
/**
108+
* @return string
109+
*/
110+
public function getStatement(): string
111+
{
112+
$value = is_string($this->value) ? '\'' . $this->value . '\'' : $this->value;
113+
114+
return sprintf('declare(%s=%s);', $this->directive, $value);
115+
}
116+
}

src/Generator/FileGenerator.php

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@
99

1010
namespace Zend\Code\Generator;
1111

12+
use Zend\Code\DeclareStatement;
13+
use Zend\Code\Exception\InvalidArgumentException;
1214
use Zend\Code\Reflection\Exception as ReflectionException;
1315
use Zend\Code\Reflection\FileReflection;
1416

@@ -72,6 +74,11 @@ class FileGenerator extends AbstractGenerator
7274
*/
7375
protected $body;
7476

77+
/**
78+
* @var DeclareStatement[]
79+
*/
80+
protected $declares = [];
81+
7582
/**
7683
* Passes $options to {@link setOptions()}.
7784
*
@@ -166,6 +173,11 @@ public static function fromArray(array $values)
166173
case 'requiredfiles':
167174
$fileGenerator->setRequiredFiles($value);
168175
break;
176+
case 'declares':
177+
$fileGenerator->setDeclares(array_map(static function ($directive, $value) {
178+
return DeclareStatement::fromArray([$directive => $value]);
179+
}, array_keys($value), $value));
180+
break;
169181
default:
170182
if (property_exists($fileGenerator, $name)) {
171183
$fileGenerator->{$name} = $value;
@@ -408,6 +420,25 @@ public function getBody()
408420
return $this->body;
409421
}
410422

423+
public function setDeclares(array $declares)
424+
{
425+
foreach ($declares as $declare) {
426+
if (! $declare instanceof DeclareStatement) {
427+
throw new InvalidArgumentException(sprintf(
428+
'%s is expecting an array of %s objects',
429+
__METHOD__,
430+
DeclareStatement::class
431+
));
432+
}
433+
434+
if (! array_key_exists($declare->getDirective(), $this->declares)) {
435+
$this->declares[$declare->getDirective()] = $declare;
436+
}
437+
}
438+
439+
return $this;
440+
}
441+
411442
/**
412443
* @return bool
413444
*/
@@ -491,6 +522,28 @@ public function generate()
491522
}
492523
}
493524

525+
// declares, if any
526+
if ($this->declares) {
527+
$declareStatements = '';
528+
529+
foreach ($this->declares as $declare) {
530+
$declareStatements .= $declare->getStatement() . self::LINE_FEED;
531+
}
532+
533+
if (preg_match('#/\* Zend_Code_Generator_FileGenerator-DeclaresMarker \*/#m', $output)) {
534+
$output = preg_replace(
535+
'#/\* Zend_Code_Generator_FileGenerator-DeclaresMarker \*/#m',
536+
$declareStatements,
537+
$output,
538+
1
539+
);
540+
} else {
541+
$output .= $declareStatements;
542+
}
543+
544+
$output .= self::LINE_FEED;
545+
}
546+
494547
// process required files
495548
// @todo marker replacement for required files
496549
$requiredFiles = $this->getRequiredFiles();

test/Generator/FileGeneratorTest.php

Lines changed: 137 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@
1010
namespace ZendTest\Code\Generator;
1111

1212
use PHPUnit\Framework\TestCase;
13+
use Zend\Code\DeclareStatement;
14+
use Zend\Code\Exception\InvalidArgumentException;
1315
use Zend\Code\Generator\ClassGenerator;
1416
use Zend\Code\Generator\FileGenerator;
1517
use Zend\Code\Reflection\FileReflection;
@@ -413,4 +415,139 @@ public function added()
413415
$actual = file_get_contents(sys_get_temp_dir() . '/result_class.php');
414416
self::assertEquals($expected, $actual);
415417
}
418+
419+
public function testSingleDeclareStatement(): void
420+
{
421+
$generator = FileGenerator::fromArray([
422+
'declares' => [
423+
'strict_types' => 1,
424+
],
425+
'class' => [
426+
'name' => 'SampleClass',
427+
],
428+
]);
429+
$generator->setFilename(sys_get_temp_dir() . '/result_file.php');
430+
$generator->write();
431+
432+
$expected = <<<EOS
433+
<?php
434+
435+
declare(strict_types=1);
436+
437+
class SampleClass
438+
{
439+
440+
441+
}
442+
443+
444+
EOS;
445+
446+
$actual = file_get_contents(sys_get_temp_dir() . '/result_file.php');
447+
$this->assertEquals($expected, $actual);
448+
}
449+
450+
public function testMultiDeclareStatements(): void
451+
{
452+
$generator = FileGenerator::fromArray([
453+
'declares' => [
454+
'strict_types' => 1,
455+
'ticks' => 2,
456+
],
457+
'class' => [
458+
'name' => 'SampleClass',
459+
],
460+
]);
461+
$generator->setFilename(sys_get_temp_dir() . '/result_file.php');
462+
$generator->write();
463+
464+
$expected = <<<EOS
465+
<?php
466+
467+
declare(strict_types=1);
468+
declare(ticks=2);
469+
470+
class SampleClass
471+
{
472+
473+
474+
}
475+
476+
477+
EOS;
478+
479+
$actual = file_get_contents(sys_get_temp_dir() . '/result_file.php');
480+
$this->assertEquals($expected, $actual);
481+
}
482+
483+
public function testDeclareUnknownDirectiveShouldRaiseException(): void
484+
{
485+
$this->expectException(InvalidArgumentException::class);
486+
$this->expectExceptionMessage('Declare directive must be one of: ticks, strict_types, encoding.');
487+
488+
FileGenerator::fromArray([
489+
'declares' => [
490+
'fubar' => 1,
491+
],
492+
'class' => [
493+
'name' => 'SampleClass',
494+
],
495+
]);
496+
}
497+
498+
public function testDeclareWrongTypeShouldRaiseException(): void
499+
{
500+
$this->expectException(InvalidArgumentException::class);
501+
$this->expectExceptionMessage('Declare value invalid. Expected integer, got string.');
502+
503+
FileGenerator::fromArray([
504+
'declares' => [
505+
'strict_types' => 'wrong type',
506+
],
507+
'class' => [
508+
'name' => 'SampleClass',
509+
],
510+
]);
511+
}
512+
513+
public function testDeclareDuplicatesShouldOnlyGenerateOne(): void
514+
{
515+
$generator = FileGenerator::fromArray([
516+
'class' => [
517+
'name' => 'SampleClass',
518+
],
519+
]);
520+
$generator->setFilename(sys_get_temp_dir() . '/result_file.php');
521+
$generator->setDeclares([
522+
DeclareStatement::strictTypes(1),
523+
DeclareStatement::strictTypes(2)
524+
]);
525+
$generator->write();
526+
527+
$expected = <<<EOS
528+
<?php
529+
530+
declare(strict_types=1);
531+
532+
class SampleClass
533+
{
534+
535+
536+
}
537+
538+
539+
EOS;
540+
541+
$actual = file_get_contents(sys_get_temp_dir() . '/result_file.php');
542+
$this->assertEquals($expected, $actual);
543+
}
544+
545+
public function testWrongDeclareTypeShouldRaiseException(): void
546+
{
547+
$generator = new FileGenerator();
548+
549+
$this->expectException(InvalidArgumentException::class);
550+
$this->expectExceptionMessage('setDeclares is expecting an array of Zend\\Code\\DeclareStatement objects');
551+
$generator->setDeclares([new \stdClass()]);
552+
}
416553
}

0 commit comments

Comments
 (0)