Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
0.00% covered (danger)
0.00%
0 / 83
0.00% covered (danger)
0.00%
0 / 5
CRAP
0.00% covered (danger)
0.00%
0 / 1
SpecialStoryBuilder
0.00% covered (danger)
0.00%
0 / 83
0.00% covered (danger)
0.00%
0 / 5
110
0.00% covered (danger)
0.00%
0 / 1
 __construct
0.00% covered (danger)
0.00%
0 / 9
0.00% covered (danger)
0.00%
0 / 1
2
 execute
0.00% covered (danger)
0.00%
0 / 25
0.00% covered (danger)
0.00%
0 / 1
2
 getSubPage
0.00% covered (danger)
0.00%
0 / 12
0.00% covered (danger)
0.00%
0 / 1
12
 getUserBlockStatus
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 getConfigForStoryBuilder
0.00% covered (danger)
0.00%
0 / 36
0.00% covered (danger)
0.00%
0 / 1
20
1<?php
2/**
3 * @license MIT
4 */
5
6namespace MediaWiki\Extension\Wikistories;
7
8use ErrorPageError;
9use MediaWiki\Config\Config;
10use MediaWiki\Html\Html;
11use MediaWiki\MainConfigNames;
12use MediaWiki\Page\ExistingPageRecord;
13use MediaWiki\Page\PageLookup;
14use MediaWiki\Page\WikiPageFactory;
15use MediaWiki\Permissions\PermissionManager;
16use MediaWiki\SpecialPage\SpecialPage;
17use MediaWiki\User\Options\UserOptionsLookup;
18use MediaWiki\Watchlist\WatchedItemStore;
19use MediaWiki\Watchlist\WatchlistManager;
20use WatchAction;
21
22class SpecialStoryBuilder extends SpecialPage {
23
24    private const MODE_NEW = 'new';
25    private const MODE_EDIT = 'edit';
26
27    /** @var WikiPageFactory */
28    private $wikiPageFactory;
29
30    /** @var PageLookup */
31    private $pageLookup;
32
33    /** @var UserOptionsLookup */
34    private $userOptionsLookup;
35
36    /** @var WatchlistManager */
37    private $watchlistManager;
38
39    /** @var Config */
40    private $config;
41
42    /** @var WatchedItemStore */
43    private $watchedItemStore;
44
45    /** @var StoriesCache */
46    private $storiesCache;
47
48    /** @var PermissionManager */
49    private $permissionManager;
50
51    /**
52     * @param WikiPageFactory $wikiPageFactory
53     * @param PageLookup $pageLookup
54     * @param UserOptionsLookup $userOptionsLookup
55     * @param WatchlistManager $watchlistManager
56     * @param WatchedItemStore $watchedItemStore
57     * @param Config $config
58     * @param StoriesCache $storiesCache
59     * @param PermissionManager $permissionManager
60     */
61    public function __construct(
62        WikiPageFactory $wikiPageFactory,
63        PageLookup $pageLookup,
64        UserOptionsLookup $userOptionsLookup,
65        WatchlistManager $watchlistManager,
66        WatchedItemStore $watchedItemStore,
67        Config $config,
68        StoriesCache $storiesCache,
69        PermissionManager $permissionManager
70    ) {
71        parent::__construct( 'StoryBuilder' );
72        $this->wikiPageFactory = $wikiPageFactory;
73        $this->pageLookup = $pageLookup;
74        $this->userOptionsLookup = $userOptionsLookup;
75        $this->watchlistManager = $watchlistManager;
76        $this->config = $config;
77        $this->watchedItemStore = $watchedItemStore;
78        $this->storiesCache = $storiesCache;
79        $this->permissionManager = $permissionManager;
80    }
81
82    /**
83     * @inheritDoc
84     */
85    public function execute( $subPage ) {
86        $this->requireNamedUser( 'wikistories-specialstorybuilder-mustbeloggedin' );
87        parent::execute( $subPage );
88        $out = $this->getOutput();
89        $out->setPageTitleMsg( $this->msg( 'wikistories-specialstorybuilder-title' ) );
90        $out->addJsConfigVars( $this->getConfigForStoryBuilder( $this->getSubPage( $subPage ) ) );
91        $out->addModuleStyles( [ 'ext.wikistories.builder.styles' ] );
92        $out->addModules( [ 'ext.wikistories.builder' ] );
93        $out->addHTML(
94            Html::rawElement(
95                'div',
96                [ 'class' => 'ext-wikistories-container' ],
97                Html::element(
98                    'span',
99                    [ 'class' => 'ext-wikistories-loading' ],
100                    $this->msg( 'wikistories-specialstorybuilder-loading' )->text()
101                )
102            )
103        );
104        $out->addHTML(
105            Html::element(
106                'div',
107                [ 'class' => 'ext-wikistories-nojswarning' ],
108                $this->msg( 'wikistories-specialstorybuilder-nojswarning' )->text()
109            )
110        );
111    }
112
113    /**
114     * @param string|null $subPage
115     * @return ExistingPageRecord
116     * @throws ErrorPageError when the subpage is empty or invalid
117     */
118    private function getSubPage( $subPage ): ExistingPageRecord {
119        if ( !$subPage ) {
120            throw new ErrorPageError(
121                'wikistories-specialstorybuilder-title',
122                'wikistories-specialstorybuilder-invalidsubpage'
123            );
124        }
125        $page = $this->pageLookup->getExistingPageByText( $subPage );
126        if ( !$page ) {
127            throw new ErrorPageError(
128                'wikistories-specialstorybuilder-title',
129                'wikistories-specialstorybuilder-invalidsubpage'
130            );
131        }
132        return $page;
133    }
134
135    /**
136     * @param ExistingPageRecord $page
137     * @return bool
138     */
139    private function getUserBlockStatus( $page ): bool {
140        return $this->permissionManager->isBlockedFrom( $this->getUser(), $page );
141    }
142
143    /**
144     * @param ExistingPageRecord $page
145     * @return array Configuration needed by the story builder
146     */
147    private function getConfigForStoryBuilder( ExistingPageRecord $page ): array {
148        $watchExpiryEnabled = $this->config->get( MainConfigNames::WatchlistExpiry );
149        if ( $page->getNamespace() === NS_STORY ) {
150            $wikiPage = $this->wikiPageFactory->newFromTitle( $page );
151            $storyContent = $this->storiesCache->getStory( $page->getId() );
152            $mode = self::MODE_EDIT;
153            $articlePage = $this->pageLookup->getExistingPageByText( $storyContent[ 'articleTitle' ] );
154            $userBlock = $articlePage ? $this->getUserBlockStatus( $articlePage ) : false;
155            $watchDefault = $this->userOptionsLookup->getOption( $this->getUser(), 'watchdefault' ) ||
156                $this->watchlistManager->isWatched( $this->getUser(), $page );
157            $watchExpiryOptions = WatchAction::getExpiryOptions(
158                $this->getContext(),
159                $this->watchedItemStore->getWatchedItem( $this->getUser(), $wikiPage )
160            );
161        } else {
162            $mode = self::MODE_NEW;
163            $storyContent = [
164                'articleId' => $page->getId(),
165                'articleTitle' => $page->getDBkey(),
166                'frames' => [],
167            ];
168            $userBlock = $this->getUserBlockStatus( $page );
169            $watchDefault = $this->userOptionsLookup->getOption( $this->getUser(), 'watchcreations' );
170            $watchExpiryOptions = WatchAction::getExpiryOptions( $this->getContext(), false );
171        }
172        return [
173            'wgWikistoriesMode' => $mode,
174            'wgWikistoriesStoryContent' => $storyContent,
175            'wgWikistoriesMinFrames' => $this->getConfig()->get( 'WikistoriesMinFrames' ),
176            'wgWikistoriesMaxFrames' => $this->getConfig()->get( 'WikistoriesMaxFrames' ),
177            'wgWikistoriesMaxTextLength' => $this->getConfig()->get( 'WikistoriesMaxTextLength' ),
178            'wgWikistoriesCommonsDomain' => $this->getConfig()->get( 'WikistoriesCommonsDomain' ),
179            'wgWikistoriesRestDomain' => $this->getConfig()->get( 'WikistoriesRestDomain' ),
180            'wgWikistoriesUnmodifiedTextThreshold' => $this->getConfig()->get( 'WikistoriesUnmodifiedTextThreshold' ),
181            'wgWikistoriesWatchDefault' => $watchDefault,
182            'wgWikistoriesWatchlistExpiryEnabled' => $watchExpiryEnabled,
183            'wgWikistoriesWatchlistExpiryOptions' => $watchExpiryOptions,
184            'wgWikistoriesUserBlockStatus' => $userBlock,
185        ];
186    }
187
188}