Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
Total | |
0.00% |
0 / 15 |
|
0.00% |
0 / 3 |
CRAP | |
0.00% |
0 / 1 |
Hint | |
0.00% |
0 / 15 |
|
0.00% |
0 / 3 |
132 | |
0.00% |
0 / 1 |
__construct | |
0.00% |
0 / 2 |
|
0.00% |
0 / 1 |
2 | |||
build | |
0.00% |
0 / 4 |
|
0.00% |
0 / 1 |
6 | |||
__toString | |
0.00% |
0 / 9 |
|
0.00% |
0 / 1 |
72 |
1 | <?php |
2 | declare( strict_types=1 ); |
3 | |
4 | /** |
5 | * This program is free software; you can redistribute it and/or modify |
6 | * it under the terms of the GNU General Public License as published by |
7 | * the Free Software Foundation; either version 2 of the License, or |
8 | * (at your option) any later version. |
9 | * |
10 | * This program is distributed in the hope that it will be useful, |
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
13 | * GNU General Public License for more details. |
14 | * |
15 | * You should have received a copy of the GNU General Public License along |
16 | * with this program; if not, write to the Free Software Foundation, Inc., |
17 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
18 | * http://www.gnu.org/copyleft/gpl.html |
19 | * |
20 | * @file |
21 | */ |
22 | |
23 | namespace Wikimedia\JsonCodec; |
24 | |
25 | use Stringable; |
26 | |
27 | /** |
28 | * Class hints with modifiers. |
29 | * @template T |
30 | */ |
31 | class Hint implements Stringable { |
32 | /** |
33 | * The default class hint behavior: an exact match for class name, |
34 | * and the serialization for an object will always use curly |
35 | * braces `{}` but the return value from `::toJsonArray()` will |
36 | * always be an array. This requires adding an explicit |
37 | * `JsonCodec::TYPE_ANNOTATION` element to lists even if proper |
38 | * type hints are supplied. |
39 | */ |
40 | public const DEFAULT = 0; |
41 | /** |
42 | * A list of the hinted type. |
43 | */ |
44 | public const LIST = 1; |
45 | /** |
46 | * A map of the hinted type. The value is a stdClass object with |
47 | * string keys and property values of the specified type. |
48 | */ |
49 | public const STDCLASS = 2; |
50 | /** |
51 | * Prefer to use square brackets to serialize this object, when |
52 | * possible. Not compatible with `ALLOW_OBJECT`. |
53 | */ |
54 | public const USE_SQUARE = 3; |
55 | /** |
56 | * Tweak the return type of `JsonCodec::toJsonArray()` to return |
57 | * a `stdClass` object instead of array where that makes it possible |
58 | * to generate curly braces instead of adding an extra |
59 | * `JsonCodec::TYPE_ANNOTATION` value. Not compatible with `USE_SQUARE`. |
60 | */ |
61 | public const ALLOW_OBJECT = 4; |
62 | /** |
63 | * The value is an `instanceof` the hinted type, and the |
64 | * `JsonClassCodec` for the hinted type will be able to |
65 | * deserialize the object. This is useful for tagged objects of |
66 | * various kinds, where a superclass can look at the json data to |
67 | * determine which of its subclasses to instantiate. Note that in |
68 | * this case hints will be taken from the superclass's codec. |
69 | */ |
70 | public const INHERITED = 5; |
71 | |
72 | /** @var class-string<T>|Hint<T> */ |
73 | public $parent; |
74 | public int $modifier; |
75 | |
76 | /** |
77 | * Create a new serialization class type hint. |
78 | * @param class-string<T>|Hint<T> $parent |
79 | * @param int $modifier A hint modifier |
80 | */ |
81 | public function __construct( $parent, int $modifier = 0 ) { |
82 | $this->parent = $parent; |
83 | $this->modifier = $modifier; |
84 | } |
85 | |
86 | /** |
87 | * Helper function to create nested hints. For example, the |
88 | * `Foo[][]` type can be created as |
89 | * `Hint::build(Foo::class, Hint:LIST, Hint::LIST)`. |
90 | * |
91 | * Note that, in the grand (?) tradition of C-like types, |
92 | * modifiers are read right-to-left. That is, a "stdClass containing |
93 | * values which are lists of Foo" is written 'backwards' as: |
94 | * `Hint::build(Foo::class, Hint::LIST, Hint::STDCLASS)`. |
95 | * |
96 | * @phan-template T |
97 | * @param class-string<T> $className |
98 | * @param int ...$modifiers |
99 | * @return class-string<T>|Hint<T> |
100 | */ |
101 | public static function build( string $className, int ...$modifiers ) { |
102 | if ( count( $modifiers ) === 0 ) { |
103 | return $className; |
104 | } |
105 | $last = array_pop( $modifiers ); |
106 | return new Hint( self::build( $className, ...$modifiers ), $last ); |
107 | } |
108 | |
109 | public function __toString(): string { |
110 | $parent = strval( $this->parent ); |
111 | switch ( $this->modifier ) { |
112 | case self::DEFAULT: |
113 | return "DEFAULT($parent)"; |
114 | case self::LIST: |
115 | return "LIST($parent)"; |
116 | case self::STDCLASS: |
117 | return "STDCLASS($parent)"; |
118 | case self::USE_SQUARE: |
119 | return "USE_SQUARE($parent)"; |
120 | case self::ALLOW_OBJECT: |
121 | return "ALLOW_OBJECT($parent)"; |
122 | case self::INHERITED: |
123 | return "INHERITED($parent)"; |
124 | default: |
125 | return "UNKNOWN($parent)"; |
126 | } |
127 | } |
128 | } |