Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
0.00% covered (danger)
0.00%
0 / 59
0.00% covered (danger)
0.00%
0 / 9
CRAP
0.00% covered (danger)
0.00%
0 / 1
StoryContentHandler
0.00% covered (danger)
0.00%
0 / 59
0.00% covered (danger)
0.00%
0 / 9
240
0.00% covered (danger)
0.00%
0 / 1
 __construct
0.00% covered (danger)
0.00%
0 / 7
0.00% covered (danger)
0.00%
0 / 1
2
 getContentClass
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 getActionOverrides
0.00% covered (danger)
0.00%
0 / 11
0.00% covered (danger)
0.00%
0 / 1
2
 fillParserOutput
0.00% covered (danger)
0.00%
0 / 22
0.00% covered (danger)
0.00%
0 / 1
42
 isParserCacheSupported
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 getSlotDiffRendererWithOptions
0.00% covered (danger)
0.00%
0 / 5
0.00% covered (danger)
0.00%
0 / 1
2
 preloadTransform
0.00% covered (danger)
0.00%
0 / 3
0.00% covered (danger)
0.00%
0 / 1
2
 preSaveTransform
0.00% covered (danger)
0.00%
0 / 3
0.00% covered (danger)
0.00%
0 / 1
2
 validateSave
0.00% covered (danger)
0.00%
0 / 6
0.00% covered (danger)
0.00%
0 / 1
6
1<?php
2
3namespace MediaWiki\Extension\Wikistories;
4
5use Content;
6use IContextSource;
7use JobQueueGroup;
8use JsonContentHandler;
9use MediaWiki\Category\TrackingCategories;
10use MediaWiki\Content\Renderer\ContentParseParams;
11use MediaWiki\Content\Transform\PreloadTransformParams;
12use MediaWiki\Content\Transform\PreSaveTransformParams;
13use MediaWiki\Content\ValidationParams;
14use MediaWiki\Parser\ParserOutput;
15use MediaWiki\Title\Title;
16use MediaWiki\Title\TitleValue;
17use RefreshLinksJob;
18
19class StoryContentHandler extends JsonContentHandler {
20
21    /** @var StoryConverter */
22    private $storyConverter;
23
24    /** @var StoryValidator */
25    private $storyValidator;
26
27    /** @var StoryRenderer */
28    private $storyRenderer;
29
30    /** @var StoryTrackingCategories */
31    private $storyTrackingCategories;
32
33    /** @var TrackingCategories */
34    private $trackingCategories;
35
36    /** @var JobQueueGroup */
37    private $jobQueueGroup;
38
39    /**
40     * @param string $modelId
41     * @param StoryConverter $storyConverter
42     * @param StoryValidator $storyValidator
43     * @param StoryRenderer $storyRenderer
44     * @param StoryTrackingCategories $storyTrackingCategories
45     * @param TrackingCategories $trackingCategories
46     * @param JobQueueGroup $jobQueueGroup
47     */
48    public function __construct(
49        $modelId,
50        StoryConverter $storyConverter,
51        StoryValidator $storyValidator,
52        StoryRenderer $storyRenderer,
53        StoryTrackingCategories $storyTrackingCategories,
54        TrackingCategories $trackingCategories,
55        JobQueueGroup $jobQueueGroup
56    ) {
57        parent::__construct( $modelId );
58        $this->storyConverter = $storyConverter;
59        $this->storyValidator = $storyValidator;
60        $this->storyRenderer = $storyRenderer;
61        $this->storyTrackingCategories = $storyTrackingCategories;
62        $this->trackingCategories = $trackingCategories;
63        $this->jobQueueGroup = $jobQueueGroup;
64    }
65
66    /**
67     * @return string
68     */
69    protected function getContentClass() {
70        return StoryContent::class;
71    }
72
73    /**
74     * @return array
75     */
76    public function getActionOverrides() {
77        return [
78            'edit' => StoryEditAction::class,
79            'submit' => StorySubmitAction::class,
80            'storyview' => [
81                'class' => StoryViewAction::class,
82                'services' => [
83                    'Wikistories.Cache',
84                    'UrlUtils',
85                ]
86            ],
87        ];
88    }
89
90    /**
91     * Outputs the plain html version of a story.
92     *
93     * @param Content $content
94     * @param ContentParseParams $cpoParams
95     * @param ParserOutput &$parserOutput
96     */
97    public function fillParserOutput(
98        Content $content,
99        ContentParseParams $cpoParams,
100        ParserOutput &$parserOutput
101    ) {
102        '@phan-var StoryContent $content';
103        /** @var StoryContent $story */
104        $story = $this->storyConverter->toLatest( $content );
105        $storyPage = $cpoParams->getPage();
106        $storyTitle = Title::newFromPageReference( $storyPage );
107        $storyData = $this->storyRenderer->getStoryData( $story, $storyTitle );
108
109        // Links
110        $parserOutput->addLink( new TitleValue( NS_MAIN, $storyData[ 'articleTitle' ] ) );
111        foreach ( $storyData[ 'frames' ] as $frame ) {
112            $parserOutput->addImage( strtr( $frame[ 'filename' ], ' ', '_' ) );
113        }
114
115        // Categories
116        foreach ( $story->getCategories() as $category ) {
117            $parserOutput->addCategory( $category, $storyPage->getDBkey() );
118        }
119
120        // Tracking categories
121        foreach ( $storyData[ 'trackingCategories' ] as $trackingCategory ) {
122            $this->trackingCategories->addTrackingCategory(
123                $parserOutput, $trackingCategory, $storyPage
124            );
125        }
126
127        // refresh links job when there are changes of tracking categories
128        if ( $this->storyTrackingCategories->hasDiff( $storyData[ 'trackingCategories' ], $storyTitle ) ) {
129            $this->jobQueueGroup->push(
130                RefreshLinksJob::newPrioritized( $storyTitle, [] )
131            );
132        }
133
134        // HTML version
135        if ( $cpoParams->getGenerateHtml() ) {
136            $parts = $this->storyRenderer->renderNoJS( $storyData );
137            $parserOutput->addModuleStyles( [ $parts['style'] ] );
138            $parserOutput->setText( $parts['html'] );
139        }
140    }
141
142    /**
143     * @inheritDoc
144     */
145    public function isParserCacheSupported() {
146        return true;
147    }
148
149    /**
150     * @param IContextSource $context
151     * @param array $options
152     * @return StorySlotDiffRenderer
153     */
154    public function getSlotDiffRendererWithOptions( IContextSource $context, $options = [] ) {
155        return new StorySlotDiffRenderer(
156            $this->storyConverter,
157            $this->createTextSlotDiffRenderer( $options )
158        );
159    }
160
161    /**
162     * @inheritDoc
163     */
164    public function preloadTransform( Content $content, PreloadTransformParams $pltParams ): Content {
165        '@phan-var StoryContent $content';
166        /** @var StoryContent $story */
167        $story = $content;
168        return $this->storyConverter->toLatest( $story );
169    }
170
171    /**
172     * @inheritDoc
173     */
174    public function preSaveTransform( Content $content, PreSaveTransformParams $pstParams ): Content {
175        '@phan-var StoryContent $content';
176        /** @var StoryContent $story */
177        $story = $content;
178        return $this->storyConverter->withSchemaVersion( $story );
179    }
180
181    /**
182     * @inheritDoc
183     */
184    public function validateSave( Content $content, ValidationParams $validationParams ) {
185        '@phan-var StoryContent $content';
186        $status = parent::validateSave( $content, $validationParams );
187        if ( !$status->isGood() ) {
188            return $status;
189        }
190        /** @var StoryContent $story */
191        $story = $content;
192        return $this->storyValidator->isValid( $story );
193    }
194
195}