Skip to content

Commit f4d03c3

Browse files
committed
types available as singletons
1 parent dbb792d commit f4d03c3

10 files changed

Lines changed: 209 additions & 26 deletions

File tree

src/Parser.php

Lines changed: 30 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -19,39 +19,60 @@ class Parser extends DynamicParser
1919
* @var array
2020
*/
2121
protected $types = [
22-
'\Minime\Annotations\Types\IntegerType' => 'integer',
23-
'\Minime\Annotations\Types\StringType' => 'string',
24-
'\Minime\Annotations\Types\FloatType' => 'float',
25-
'\Minime\Annotations\Types\JsonType' => 'json',
26-
'\Minime\Annotations\Types\ConcreteType' => '->'
22+
'integerType' => 'integer',
23+
'stringType' => 'string',
24+
'floatType' => 'float',
25+
'jsonType' => 'json',
26+
'concreteType' => '->'
2727
];
2828

29+
/**
30+
* A fallback type if no strong type declaration found.
31+
*
32+
* @var string
33+
*/
34+
protected $typeFallback = 'dynamicType';
35+
2936
/**
3037
* The regex equivalent of $types
3138
*
3239
* @var string
3340
*/
3441
protected $typesPattern;
3542

43+
/**
44+
* @var TypeContainer
45+
*/
46+
private $typeContainer;
47+
3648
/**
3749
* Parser constructor
3850
*
3951
*/
4052
public function __construct()
4153
{
54+
$this->typeContainer = new TypeContainer();
55+
$this->typeContainer->add($this->typeFallback);
56+
57+
foreach ($this->types as $key => $value) {
58+
$this->typeContainer->add($key);
59+
}
60+
4261
$this->buildTypesPattern();
4362
parent::__construct();
4463
}
4564

4665
public function registerType($class, $token)
4766
{
4867
$this->types[$class] = $token;
68+
$this->typeContainer->add($class);
4969
$this->buildTypesPattern();
5070
}
5171

5272
public function unregisterType($class)
5373
{
5474
unset($this->types[$class]);
75+
$this->typeContainer->remove($class);
5576
$this->buildTypesPattern();
5677
}
5778

@@ -65,16 +86,18 @@ public function unregisterType($class)
6586
protected function parseValue($value, $key = null)
6687
{
6788
$value = trim($value);
68-
$type = '\Minime\\Annotations\\Types\\DynamicType';
89+
$type = $this->typeFallback;
90+
6991
if (preg_match($this->typesPattern, $value, $found)) { // strong typed
7092
$type = $found[1];
7193
$value = trim(substr($value, strlen($type)));
94+
7295
if (in_array($type, $this->types)) {
7396
$type = array_search($type, $this->types);
7497
}
7598
}
7699

77-
return (new $type)->parse($value, $key);
100+
return $this->typeContainer->{$type}->parse($value, $key);
78101
}
79102

80103
/**

src/TypeContainer.php

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
<?php
2+
3+
namespace Minime\Annotations;
4+
5+
/**
6+
* @property Types\IntegerType $integerType
7+
* @property Types\StringType $stringType
8+
* @property Types\FloatType $floatType
9+
* @property Types\JsonType $jsonType
10+
* @property Types\ConcreteType $concreteType
11+
*/
12+
class TypeContainer
13+
{
14+
/**
15+
* Stores the lambda functions for each type.
16+
*
17+
* @var array
18+
*/
19+
private $builders;
20+
21+
/**
22+
* Stores built types.
23+
*
24+
* @var array
25+
*/
26+
private $types;
27+
28+
/**
29+
* Add a lambda function.
30+
*
31+
* @param string $name
32+
*/
33+
public function add($name)
34+
{
35+
$this->builders[$name] = function() use($name) {
36+
$type = 'Minime\\Annotations\\Types\\' . ucfirst($name);
37+
38+
// do we have in default configuration setup?
39+
if (!class_exists($type)) {
40+
$type = $name;
41+
}
42+
43+
if (is_callable($type . '::getType')) {
44+
$typeClass = call_user_func($type . '::getType');
45+
} else {
46+
$typeClass = new $type;
47+
}
48+
49+
return new $typeClass;
50+
};
51+
}
52+
53+
/**
54+
* Remove a lambda function.
55+
*
56+
* @param string $name
57+
*/
58+
public function remove($name)
59+
{
60+
unset($this->builders[$name]);
61+
unset($this->types[$name]);
62+
}
63+
64+
/**
65+
* @param string $name
66+
*
67+
* @return TypeInterface
68+
*/
69+
public function __get($name)
70+
{
71+
if (!isset($this->types[$name]) && isset($this->builders[$name])) {
72+
$this->types[$name] = $this->builders[$name]();
73+
}
74+
75+
return $this->types[$name];
76+
}
77+
}

src/Types/AbstractType.php

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
<?php
2+
3+
namespace Minime\Annotations\Types;
4+
5+
use Minime\Annotations\Interfaces\TypeInterface;
6+
7+
abstract class AbstractType implements TypeInterface
8+
{
9+
/**
10+
* @return TypeInterface
11+
*/
12+
abstract public static function getType();
13+
}

src/Types/ConcreteType.php

Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,23 @@
44

55
use stdClass;
66
use ReflectionClass;
7-
use Minime\Annotations\Interfaces\TypeInterface;
87
use Minime\Annotations\ParserException;
98

10-
class ConcreteType implements TypeInterface
9+
class ConcreteType extends AbstractType
1110
{
11+
/**
12+
* @var TypeInterface
13+
*/
14+
private static $instance;
15+
16+
public static function getType()
17+
{
18+
if (!isset(self::$instance)) {
19+
self::$instance = new ConcreteType();
20+
}
21+
22+
return self::$instance;
23+
}
1224

1325
/**
1426
* Process a value to be a concrete annotation
@@ -20,8 +32,8 @@ class ConcreteType implements TypeInterface
2032
*/
2133
public function parse($value, $class = null)
2234
{
23-
if (! class_exists($class)) {
24-
throw new ParserException("Concrete annotation expects {$class} to exist.");
35+
if (!class_exists($class)) {
36+
throw new ParserException("Concrete annotation expects '{$class}' to exist.");
2537
}
2638

2739
$prototype = (new JsonType)->parse($value);
@@ -79,7 +91,7 @@ protected function doMethodConfiguration($instance, stdClass $prototype)
7991
{
8092
foreach ($prototype as $method => $args) {
8193
call_user_func_array([$instance, $method], $args);
82-
}
94+
}
8395

8496
return $instance;
8597
}
@@ -92,7 +104,7 @@ protected function doMethodConfiguration($instance, stdClass $prototype)
92104
*/
93105
protected function isPrototypeSchemaValid(stdclass $prototype)
94106
{
95-
foreach ($prototype as $method => $args) {
107+
foreach ($prototype as $args) {
96108
if (! is_array($args)) {
97109
return false;
98110
}

src/Types/DynamicType.php

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,21 @@
22

33
namespace Minime\Annotations\Types;
44

5-
use Minime\Annotations\Interfaces\TypeInterface;
6-
7-
class DynamicType implements TypeInterface
5+
class DynamicType extends AbstractType
86
{
7+
/**
8+
* @var TypeInterface
9+
*/
10+
private static $instance;
11+
12+
public static function getType()
13+
{
14+
if (!isset(self::$instance)) {
15+
self::$instance = new DynamicType();
16+
}
17+
18+
return self::$instance;
19+
}
920

1021
/**
1122
* Parse a given undefined type value

src/Types/FloatType.php

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,23 @@
22

33
namespace Minime\Annotations\Types;
44

5-
use Minime\Annotations\Interfaces\TypeInterface;
65
use Minime\Annotations\ParserException;
76

8-
class FloatType implements TypeInterface
7+
class FloatType extends AbstractType
98
{
9+
/**
10+
* @var TypeInterface
11+
*/
12+
private static $instance;
13+
14+
public static function getType()
15+
{
16+
if (!isset(self::$instance)) {
17+
self::$instance = new FloatType();
18+
}
19+
20+
return self::$instance;
21+
}
1022

1123
/**
1224
* Filter a value to be a Float

src/Types/IntegerType.php

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,23 @@
22

33
namespace Minime\Annotations\Types;
44

5-
use Minime\Annotations\Interfaces\TypeInterface;
65
use Minime\Annotations\ParserException;
76

8-
class IntegerType implements TypeInterface
7+
class IntegerType extends AbstractType
98
{
9+
/**
10+
* @var TypeInterface
11+
*/
12+
private static $instance;
13+
14+
public static function getType()
15+
{
16+
if (!isset(self::$instance)) {
17+
self::$instance = new IntegerType();
18+
}
19+
20+
return self::$instance;
21+
}
1022

1123
/**
1224
* Filter a value to be an Integer

src/Types/JsonType.php

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,23 @@
22

33
namespace Minime\Annotations\Types;
44

5-
use Minime\Annotations\Interfaces\TypeInterface;
65
use Minime\Annotations\ParserException;
76

8-
class JsonType implements TypeInterface
7+
class JsonType extends AbstractType
98
{
9+
/**
10+
* @var TypeInterface
11+
*/
12+
private static $instance;
13+
14+
public static function getType()
15+
{
16+
if (!isset(self::$instance)) {
17+
self::$instance = new JsonType();
18+
}
19+
20+
return self::$instance;
21+
}
1022

1123
/**
1224
* Filter a value to be a Json

src/Types/StringType.php

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,21 @@
22

33
namespace Minime\Annotations\Types;
44

5-
use Minime\Annotations\Interfaces\TypeInterface;
6-
7-
class StringType implements TypeInterface
5+
class StringType extends AbstractType
86
{
7+
/**
8+
* @var TypeInterface
9+
*/
10+
private static $instance;
11+
12+
public static function getType()
13+
{
14+
if (!isset(self::$instance)) {
15+
self::$instance = new StringType();
16+
}
17+
18+
return self::$instance;
19+
}
920

1021
/**
1122
* Parse a given value as string

test/suite/ParserTest.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77

88
/**
99
* ParserTest
10-
*
10+
*
1111
* @group parser
1212
*/
1313
class ParserTest extends DynamicParserTest

0 commit comments

Comments
 (0)