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