1: | <?php |
2: | |
3: | namespace Teto\Object; |
4: | |
5: | use function is_numeric; |
6: | use function preg_match; |
7: | use function property_exists; |
8: | |
9: | /** |
10: | * Type Definition syntax |
11: | * |
12: | * @author USAMI Kenta <tadsan@zonu.me> |
13: | * @copyright 2016 Baguette HQ |
14: | * @license http://www.apache.org/licenses/LICENSE-2.0 |
15: | * |
16: | * @property-read string $expected |
17: | * @property-read bool $is_nullable |
18: | * @property-read bool $is_array |
19: | * @property-read int|null $len |
20: | */ |
21: | final class TypeDefinition |
22: | { |
23: | /** |
24: | * @var string |
25: | */ |
26: | private $expected; |
27: | |
28: | /** |
29: | * @var bool |
30: | */ |
31: | private $is_nullable; |
32: | |
33: | /** |
34: | * @var bool |
35: | */ |
36: | private $is_array; |
37: | |
38: | /** |
39: | * @var int|null |
40: | */ |
41: | private $len; |
42: | |
43: | public function __construct() |
44: | { |
45: | } |
46: | |
47: | /** |
48: | * @param string $def Type definition |
49: | * @return TypeDefinition |
50: | */ |
51: | public static function parse($def) |
52: | { |
53: | $type = new TypeDefinition(); |
54: | |
55: | preg_match(self::RE_PROPERTY, $def, $matches); |
56: | |
57: | if (empty($matches[2])) { |
58: | throw new \LogicException(); |
59: | } |
60: | $type->is_nullable = !empty($matches[1]); |
61: | $type->expected = $matches[2]; |
62: | $type->is_array = !empty($matches[3]); |
63: | if (isset($matches[4]) && is_numeric($matches[4])) { |
64: | $type->len = (int) $matches[4]; |
65: | } |
66: | |
67: | return $type; |
68: | } |
69: | |
70: | public const RE_PROPERTY = '/^(\??)([^\s\[\]?]+)((?:\[(\d*)\])?)$/'; |
71: | |
72: | /** |
73: | * @throws \OutOfRangeException |
74: | */ |
75: | public function __get($name) |
76: | { |
77: | if (property_exists($this, $name)) { |
78: | return $this->$name; |
79: | } |
80: | |
81: | throw new \OutOfRangeException(); |
82: | } |
83: | } |
84: |