3 namespace MediaWiki\Edit
;
5 use MediaWiki\Content\IContentHandlerFactory
;
6 use Wikimedia\ObjectCache\BagOStuff
;
7 use Wikimedia\Parsoid\Core\PageBundle
;
13 class SimpleParsoidOutputStash
implements ParsoidOutputStash
{
21 /** @var IContentHandlerFactory */
22 private $contentHandlerFactory;
25 * @param IContentHandlerFactory $contentHandlerFactory
26 * @param BagOStuff $bagOfStuff storage backend
27 * @param int $duration cache duration in seconds
29 public function __construct( IContentHandlerFactory
$contentHandlerFactory, BagOStuff
$bagOfStuff, int $duration ) {
30 $this->bagOfStuff
= $bagOfStuff;
31 $this->duration
= $duration;
32 $this->contentHandlerFactory
= $contentHandlerFactory;
35 private function makeCacheKey( ParsoidRenderID
$renderId ): string {
36 return $this->bagOfStuff
->makeKey( 'ParsoidOutputStash', $renderId->getKey() );
40 * Before we stash, we serialize & encode into JSON the relevant
41 * parts of the data we need to construct a page bundle in the future.
43 * @param ParsoidRenderID $renderId Combination of revision ID and revision's time ID
44 * @param SelserContext $selserContext
48 public function set( ParsoidRenderID
$renderId, SelserContext
$selserContext ): bool {
49 $jsonic = $this->selserContextToJsonArray( $selserContext );
51 $key = $this->makeCacheKey( $renderId );
52 return $this->bagOfStuff
->set( $key, $jsonic, $this->duration
);
56 * This will decode the JSON data and create a page bundle from it
57 * if we have something in the stash that matches a given rendering or
58 * will just return an empty array if no entry in the stash.
60 * @param ParsoidRenderID $renderId
62 * @return SelserContext|null
64 public function get( ParsoidRenderID
$renderId ): ?SelserContext
{
65 $key = $this->makeCacheKey( $renderId );
66 $jsonic = $this->bagOfStuff
->get( $key ) ??
[];
68 if ( !is_array( $jsonic ) ) {
69 // Defend against old stashed data.
70 // Only needed for a couple of days after this code has been deployed.
74 $selserContext = $this->newSelserContextFromJson( $jsonic );
75 return $selserContext ?
: null;
78 private function newSelserContextFromJson( array $json ): ?SelserContext
{
79 if ( !isset( $json['pb'] ) ) {
83 // TODO: should use proper JsonCodec for this
84 $pb = PageBundle
::newFromJsonArray( $json['pb'] );
86 $revId = (int)$json['revId'];
88 if ( isset( $json['content'] ) ) {
89 $contentHandler = $this->contentHandlerFactory
->getContentHandler( $json['content']['model'] );
90 $content = $contentHandler->unserializeContent( $json['content']['data'] );
95 return new SelserContext( $pb, $revId, $content );
98 private function selserContextToJsonArray( SelserContext
$selserContext ): array {
100 'revId' => $selserContext->getRevisionID(),
103 // TODO: should use proper JsonCodec for this
104 $json['pb'] = $selserContext->getPageBundle()->toJsonArray();
106 $content = $selserContext->getContent();
109 'model' => $content->getModel(),
110 'data' => $content->serialize()