Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
Total | |
91.43% |
32 / 35 |
|
66.67% |
4 / 6 |
CRAP | |
0.00% |
0 / 1 |
SimpleParsoidOutputStash | |
91.43% |
32 / 35 |
|
66.67% |
4 / 6 |
12.09 | |
0.00% |
0 / 1 |
__construct | |
100.00% |
3 / 3 |
|
100.00% |
1 / 1 |
1 | |||
makeCacheKey | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
set | |
100.00% |
3 / 3 |
|
100.00% |
1 / 1 |
1 | |||
get | |
83.33% |
5 / 6 |
|
0.00% |
0 / 1 |
3.04 | |||
newSelserContextFromJson | |
81.82% |
9 / 11 |
|
0.00% |
0 / 1 |
4.10 | |||
selserContextToJsonArray | |
100.00% |
11 / 11 |
|
100.00% |
1 / 1 |
2 |
1 | <?php |
2 | |
3 | namespace MediaWiki\Edit; |
4 | |
5 | use BagOStuff; |
6 | use MediaWiki\Content\IContentHandlerFactory; |
7 | use MediaWiki\Parser\Parsoid\PageBundleJsonTrait; |
8 | |
9 | /** |
10 | * @internal |
11 | * @since 1.39 |
12 | */ |
13 | class SimpleParsoidOutputStash implements ParsoidOutputStash { |
14 | use PageBundleJsonTrait; |
15 | |
16 | /** @var BagOStuff */ |
17 | private $bagOfStuff; |
18 | |
19 | /** @var int */ |
20 | private $duration; |
21 | |
22 | /** @var IContentHandlerFactory */ |
23 | private $contentHandlerFactory; |
24 | |
25 | /** |
26 | * @param IContentHandlerFactory $contentHandlerFactory |
27 | * @param BagOStuff $bagOfStuff storage backend |
28 | * @param int $duration cache duration in seconds |
29 | */ |
30 | public function __construct( IContentHandlerFactory $contentHandlerFactory, BagOStuff $bagOfStuff, int $duration ) { |
31 | $this->bagOfStuff = $bagOfStuff; |
32 | $this->duration = $duration; |
33 | $this->contentHandlerFactory = $contentHandlerFactory; |
34 | } |
35 | |
36 | private function makeCacheKey( ParsoidRenderID $renderId ): string { |
37 | return $this->bagOfStuff->makeKey( 'ParsoidOutputStash', $renderId->getKey() ); |
38 | } |
39 | |
40 | /** |
41 | * Before we stash, we serialize & encode into JSON the relevant |
42 | * parts of the data we need to construct a page bundle in the future. |
43 | * |
44 | * @param ParsoidRenderID $renderId Combination of revision ID and revision's time ID |
45 | * @param SelserContext $selserContext |
46 | * |
47 | * @return bool |
48 | */ |
49 | public function set( ParsoidRenderID $renderId, SelserContext $selserContext ): bool { |
50 | $jsonic = $this->selserContextToJsonArray( $selserContext ); |
51 | |
52 | $key = $this->makeCacheKey( $renderId ); |
53 | return $this->bagOfStuff->set( $key, $jsonic, $this->duration ); |
54 | } |
55 | |
56 | /** |
57 | * This will decode the JSON data and create a page bundle from it |
58 | * if we have something in the stash that matches a given rendering or |
59 | * will just return an empty array if no entry in the stash. |
60 | * |
61 | * @param ParsoidRenderID $renderId |
62 | * |
63 | * @return SelserContext|null |
64 | */ |
65 | public function get( ParsoidRenderID $renderId ): ?SelserContext { |
66 | $key = $this->makeCacheKey( $renderId ); |
67 | $jsonic = $this->bagOfStuff->get( $key ) ?? []; |
68 | |
69 | if ( !is_array( $jsonic ) ) { |
70 | // Defend against old stashed data. |
71 | // Only needed for a couple of days after this code has been deployed. |
72 | return null; |
73 | } |
74 | |
75 | $selserContext = $this->newSelserContextFromJson( $jsonic ); |
76 | return $selserContext ?: null; |
77 | } |
78 | |
79 | private function newSelserContextFromJson( array $json ): ?SelserContext { |
80 | if ( !isset( $json['pb'] ) ) { |
81 | return null; |
82 | } |
83 | |
84 | $pb = $this->newPageBundleFromJson( $json['pb'] ); |
85 | |
86 | if ( !$pb ) { |
87 | return null; |
88 | } |
89 | |
90 | $revId = (int)$json['revId']; |
91 | |
92 | if ( isset( $json['content'] ) ) { |
93 | $contentHandler = $this->contentHandlerFactory->getContentHandler( $json['content']['model'] ); |
94 | $content = $contentHandler->unserializeContent( $json['content']['data'] ); |
95 | } else { |
96 | $content = null; |
97 | } |
98 | |
99 | return new SelserContext( $pb, $revId, $content ); |
100 | } |
101 | |
102 | private function selserContextToJsonArray( SelserContext $selserContext ): array { |
103 | $json = [ |
104 | 'revId' => $selserContext->getRevisionID(), |
105 | ]; |
106 | |
107 | $json['pb'] = $this->jsonSerializePageBundle( $selserContext->getPageBundle() ); |
108 | |
109 | $content = $selserContext->getContent(); |
110 | if ( $content ) { |
111 | $json['content'] = [ |
112 | 'model' => $content->getModel(), |
113 | 'data' => $content->serialize() |
114 | ]; |
115 | } |
116 | |
117 | return $json; |
118 | } |
119 | |
120 | } |