Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
| Total | |
0.00% |
0 / 15 |
|
0.00% |
0 / 4 |
CRAP | |
0.00% |
0 / 1 |
| JsonCodecableWithCodecTrait | |
0.00% |
0 / 15 |
|
0.00% |
0 / 4 |
56 | |
0.00% |
0 / 1 |
| jsonClassCodec | |
0.00% |
0 / 6 |
|
0.00% |
0 / 1 |
2 | |||
| toJsonArray | n/a |
0 / 0 |
n/a |
0 / 0 |
0 | |||||
| newFromJsonArray | n/a |
0 / 0 |
n/a |
0 / 0 |
0 | |||||
| jsonClassHintFor | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
| decodeDocumentFragment | |
0.00% |
0 / 4 |
|
0.00% |
0 / 1 |
12 | |||
| encodeDocumentFragment | |
0.00% |
0 / 4 |
|
0.00% |
0 / 1 |
6 | |||
| 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 | namespace Wikimedia\Parsoid\Utils; |
| 23 | |
| 24 | use Psr\Container\ContainerInterface; |
| 25 | use stdClass; |
| 26 | use Wikimedia\JsonCodec\Hint; |
| 27 | use Wikimedia\JsonCodec\JsonClassCodec; |
| 28 | use Wikimedia\JsonCodec\JsonCodecInterface; |
| 29 | use Wikimedia\Parsoid\DOM\DocumentFragment; |
| 30 | |
| 31 | /** |
| 32 | * This is an implementation of JsonCodecableTrait which passes the |
| 33 | * JsonCodec along to the class. This allows us to implement |
| 34 | * custom encodings for properties with DocumentFragment types |
| 35 | * by manually encoding the property. |
| 36 | */ |
| 37 | trait JsonCodecableWithCodecTrait { |
| 38 | /** |
| 39 | * Implements JsonCodecable by providing an implementation of |
| 40 | * ::jsonClassCodec() which does not use the provided $serviceContainer |
| 41 | * nor does it maintain any state; it just calls the ::toJsonArray() |
| 42 | * and ::newFromJsonArray() methods of this instance, passing along |
| 43 | * the JsonCodecInterface to allow custom encodings. |
| 44 | * @param JsonCodecInterface $codec |
| 45 | * @param ContainerInterface $serviceContainer |
| 46 | * @return JsonClassCodec |
| 47 | */ |
| 48 | public static function jsonClassCodec( |
| 49 | JsonCodecInterface $codec, ContainerInterface $serviceContainer |
| 50 | ): JsonClassCodec { |
| 51 | /** @implements JsonClassCodec<JsonCodecableWithCodecTrait> */ |
| 52 | return new class( $codec ) implements JsonClassCodec { |
| 53 | |
| 54 | public function __construct( private JsonCodecInterface $codec ) { |
| 55 | } |
| 56 | |
| 57 | /** @inheritDoc */ |
| 58 | public function toJsonArray( $obj ): array { |
| 59 | return $obj->toJsonArray( $this->codec ); |
| 60 | } |
| 61 | |
| 62 | /** @inheritDoc */ |
| 63 | public function newFromJsonArray( string $className, array $json ) { |
| 64 | return $className::newFromJsonArray( $this->codec, $json ); |
| 65 | } |
| 66 | |
| 67 | /** @inheritDoc */ |
| 68 | public function jsonClassHintFor( string $className, string $keyName ) { |
| 69 | return $className::jsonClassHintFor( $keyName ); |
| 70 | } |
| 71 | }; |
| 72 | } |
| 73 | |
| 74 | /** |
| 75 | * Return an associative array representing the contents of this object, |
| 76 | * which can be passed to ::newFromJsonArray() to deserialize it. |
| 77 | * @param JsonCodecInterface $codec For custom encodings |
| 78 | * @return array |
| 79 | */ |
| 80 | abstract public function toJsonArray( JsonCodecInterface $codec ): array; |
| 81 | |
| 82 | /** |
| 83 | * Return an instance of this object representing the deserialization |
| 84 | * from the array passed in $json. |
| 85 | * @param JsonCodecInterface $codec For custom encodings |
| 86 | * @param array $json |
| 87 | * @return stdClass |
| 88 | */ |
| 89 | abstract public static function newFromJsonArray( JsonCodecInterface $codec, array $json ); |
| 90 | |
| 91 | /** |
| 92 | * Return an optional type hint for the given array key in the result of |
| 93 | * ::toJsonArray() / input to ::newFromJsonArray. If a class name is |
| 94 | * returned here and it matches the runtime type of the value of that |
| 95 | * array key, then type information will be omitted from the generated |
| 96 | * JSON which can save space. The class name can be suffixed with `[]` |
| 97 | * to indicate an array or list containing objects of the given class |
| 98 | * name. |
| 99 | * |
| 100 | * Default implementation of ::jsonClassHintFor() provides no hints. |
| 101 | * Implementer can override. |
| 102 | * |
| 103 | * @param string $keyName |
| 104 | * @return class-string|string|Hint|null A class string, Hint, or null. |
| 105 | * For backward compatibility, a class string suffixed with `[]` can |
| 106 | * also be returned, but that is deprecated. |
| 107 | */ |
| 108 | public static function jsonClassHintFor( string $keyName ) { |
| 109 | return null; |
| 110 | } |
| 111 | |
| 112 | // Helper methods specific to Parsoid. |
| 113 | |
| 114 | /** |
| 115 | * Helper function for deserializing DocumentFragments which |
| 116 | * could be encoded as strings. |
| 117 | * @param JsonCodecInterface $codec |
| 118 | * @param string|array|DocumentFragment $v |
| 119 | * @return DocumentFragment |
| 120 | */ |
| 121 | private static function decodeDocumentFragment( JsonCodecInterface $codec, $v ): DocumentFragment { |
| 122 | // Usually '_h' or '_t' is used as a marker for caption/html, but |
| 123 | // allow a bare string as well. |
| 124 | // If v is a string, rewrite it to match the 'expected' |
| 125 | // [ _h => '...' ] serialization of a DocumentFragment. |
| 126 | $v = is_string( $v ) ? [ '_h' => $v ] : $v; |
| 127 | if ( is_array( $v ) ) { |
| 128 | $v = $codec->newFromJsonArray( $v, DocumentFragment::class ); |
| 129 | } |
| 130 | return $v; |
| 131 | } |
| 132 | |
| 133 | /** |
| 134 | * Helper function for serializing DocumentFragments as strings, |
| 135 | * for compatibility w/ existing MediaWiki DOM Spec 2.8.0. |
| 136 | * @param JsonCodecInterface $codec |
| 137 | * @param DocumentFragment $df |
| 138 | * @return string|array |
| 139 | */ |
| 140 | private static function encodeDocumentFragment( JsonCodecInterface $codec, DocumentFragment $df ) { |
| 141 | // compatibility with MediaWiki DOM Spec 2.8.0 |
| 142 | // See [[mw:Parsoid/MediaWiki DOM spec/Rich Attributes]] Phase 3 |
| 143 | // for discussion about alternate _h/_t marking for DocumentFragments |
| 144 | $c = $codec->toJsonArray( $df, DocumentFragment::class ); |
| 145 | if ( is_string( $c['_h'] ?? null ) ) { |
| 146 | return $c['_h']; |
| 147 | } |
| 148 | return $c; |
| 149 | } |
| 150 | } |