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

Commit

Permalink
Merge branch 'feature/169' into develop
Browse files Browse the repository at this point in the history
Close #169
  • Loading branch information
michalbundyra committed Oct 5, 2019
2 parents 14fee05 + 3743c26 commit 47892b3
Show file tree
Hide file tree
Showing 4 changed files with 308 additions and 0 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ All notable changes to this project will be documented in this file, in reverse

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

- [#169](https://github.com/zendframework/zend-code/pull/169) adds the ability to define declare statements.

- [#167](https://github.com/zendframework/zend-code/pull/167) adds the ability to remove doc block of a member.

### Changed
Expand Down
116 changes: 116 additions & 0 deletions src/DeclareStatement.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
<?php

namespace Zend\Code;

use Zend\Code\Exception\InvalidArgumentException;

class DeclareStatement
{
public const TICKS = 'ticks';
public const STRICT_TYPES = 'strict_types';
public const ENCODING = 'encoding';

private const ALLOWED = [
self::TICKS => 'integer',
self::STRICT_TYPES => 'integer',
self::ENCODING => 'string',
];

/**
* @var string
*/
protected $directive;

/**
* @var int|string
*/
protected $value;

private function __construct(string $directive, $value)
{
$this->directive = $directive;
$this->value = $value;
}

/**
* @return string
*/
public function getDirective(): string
{
return $this->directive;
}

/**
* @return int|string
*/
public function getValue()
{
return $this->value;
}

/**
* @param int $value
* @return self
*/
public static function ticks(int $value): self
{
return new self(self::TICKS, $value);
}

/**
* @param int $value
* @return self
*/
public static function strictTypes(int $value): self
{
return new self(self::STRICT_TYPES, $value);
}

/**
* @param string $value
* @return self
*/
public static function encoding(string $value): self
{
return new self(self::ENCODING, $value);
}

public static function fromArray(array $config): self
{
$directive = key($config);
$value = $config[$directive];

if (! isset(self::ALLOWED[$directive])) {
throw new InvalidArgumentException(
sprintf(
'Declare directive must be one of: %s.',
implode(', ', array_keys(self::ALLOWED))
)
);
}

if (gettype($value) !== self::ALLOWED[$directive]) {
throw new InvalidArgumentException(
sprintf(
'Declare value invalid. Expected %s, got %s.',
self::ALLOWED[$directive],
gettype($value)
)
);
}

$method = str_replace('_', '', lcfirst(ucwords($directive, '_')));

return self::{$method}($value);
}

/**
* @return string
*/
public function getStatement(): string
{
$value = is_string($this->value) ? '\'' . $this->value . '\'' : $this->value;

return sprintf('declare(%s=%s);', $this->directive, $value);
}
}
53 changes: 53 additions & 0 deletions src/Generator/FileGenerator.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@

namespace Zend\Code\Generator;

use Zend\Code\DeclareStatement;
use Zend\Code\Exception\InvalidArgumentException;
use Zend\Code\Reflection\Exception as ReflectionException;
use Zend\Code\Reflection\FileReflection;

Expand Down Expand Up @@ -72,6 +74,11 @@ class FileGenerator extends AbstractGenerator
*/
protected $body;

/**
* @var DeclareStatement[]
*/
protected $declares = [];

/**
* Passes $options to {@link setOptions()}.
*
Expand Down Expand Up @@ -166,6 +173,11 @@ public static function fromArray(array $values)
case 'requiredfiles':
$fileGenerator->setRequiredFiles($value);
break;
case 'declares':
$fileGenerator->setDeclares(array_map(static function ($directive, $value) {
return DeclareStatement::fromArray([$directive => $value]);
}, array_keys($value), $value));
break;
default:
if (property_exists($fileGenerator, $name)) {
$fileGenerator->{$name} = $value;
Expand Down Expand Up @@ -408,6 +420,25 @@ public function getBody()
return $this->body;
}

public function setDeclares(array $declares)
{
foreach ($declares as $declare) {
if (! $declare instanceof DeclareStatement) {
throw new InvalidArgumentException(sprintf(
'%s is expecting an array of %s objects',
__METHOD__,
DeclareStatement::class
));
}

if (! array_key_exists($declare->getDirective(), $this->declares)) {
$this->declares[$declare->getDirective()] = $declare;
}
}

return $this;
}

/**
* @return bool
*/
Expand Down Expand Up @@ -491,6 +522,28 @@ public function generate()
}
}

// declares, if any
if ($this->declares) {
$declareStatements = '';

foreach ($this->declares as $declare) {
$declareStatements .= $declare->getStatement() . self::LINE_FEED;
}

if (preg_match('#/\* Zend_Code_Generator_FileGenerator-DeclaresMarker \*/#m', $output)) {
$output = preg_replace(
'#/\* Zend_Code_Generator_FileGenerator-DeclaresMarker \*/#m',
$declareStatements,
$output,
1
);
} else {
$output .= $declareStatements;
}

$output .= self::LINE_FEED;
}

// process required files
// @todo marker replacement for required files
$requiredFiles = $this->getRequiredFiles();
Expand Down
137 changes: 137 additions & 0 deletions test/Generator/FileGeneratorTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@
namespace ZendTest\Code\Generator;

use PHPUnit\Framework\TestCase;
use Zend\Code\DeclareStatement;
use Zend\Code\Exception\InvalidArgumentException;
use Zend\Code\Generator\ClassGenerator;
use Zend\Code\Generator\FileGenerator;
use Zend\Code\Reflection\FileReflection;
Expand Down Expand Up @@ -413,4 +415,139 @@ public function added()
$actual = file_get_contents(sys_get_temp_dir() . '/result_class.php');
self::assertEquals($expected, $actual);
}

public function testSingleDeclareStatement(): void
{
$generator = FileGenerator::fromArray([
'declares' => [
'strict_types' => 1,
],
'class' => [
'name' => 'SampleClass',
],
]);
$generator->setFilename(sys_get_temp_dir() . '/result_file.php');
$generator->write();

$expected = <<<EOS
<?php
declare(strict_types=1);
class SampleClass
{
}
EOS;

$actual = file_get_contents(sys_get_temp_dir() . '/result_file.php');
$this->assertEquals($expected, $actual);
}

public function testMultiDeclareStatements(): void
{
$generator = FileGenerator::fromArray([
'declares' => [
'strict_types' => 1,
'ticks' => 2,
],
'class' => [
'name' => 'SampleClass',
],
]);
$generator->setFilename(sys_get_temp_dir() . '/result_file.php');
$generator->write();

$expected = <<<EOS
<?php
declare(strict_types=1);
declare(ticks=2);
class SampleClass
{
}
EOS;

$actual = file_get_contents(sys_get_temp_dir() . '/result_file.php');
$this->assertEquals($expected, $actual);
}

public function testDeclareUnknownDirectiveShouldRaiseException(): void
{
$this->expectException(InvalidArgumentException::class);
$this->expectExceptionMessage('Declare directive must be one of: ticks, strict_types, encoding.');

FileGenerator::fromArray([
'declares' => [
'fubar' => 1,
],
'class' => [
'name' => 'SampleClass',
],
]);
}

public function testDeclareWrongTypeShouldRaiseException(): void
{
$this->expectException(InvalidArgumentException::class);
$this->expectExceptionMessage('Declare value invalid. Expected integer, got string.');

FileGenerator::fromArray([
'declares' => [
'strict_types' => 'wrong type',
],
'class' => [
'name' => 'SampleClass',
],
]);
}

public function testDeclareDuplicatesShouldOnlyGenerateOne(): void
{
$generator = FileGenerator::fromArray([
'class' => [
'name' => 'SampleClass',
],
]);
$generator->setFilename(sys_get_temp_dir() . '/result_file.php');
$generator->setDeclares([
DeclareStatement::strictTypes(1),
DeclareStatement::strictTypes(2)
]);
$generator->write();

$expected = <<<EOS
<?php
declare(strict_types=1);
class SampleClass
{
}
EOS;

$actual = file_get_contents(sys_get_temp_dir() . '/result_file.php');
$this->assertEquals($expected, $actual);
}

public function testWrongDeclareTypeShouldRaiseException(): void
{
$generator = new FileGenerator();

$this->expectException(InvalidArgumentException::class);
$this->expectExceptionMessage('setDeclares is expecting an array of Zend\\Code\\DeclareStatement objects');
$generator->setDeclares([new \stdClass()]);
}
}

0 comments on commit 47892b3

Please sign in to comment.