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: