Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
0.00% covered (danger)
0.00%
0 / 42
0.00% covered (danger)
0.00%
0 / 6
CRAP
0.00% covered (danger)
0.00%
0 / 1
FlowAction
0.00% covered (danger)
0.00%
0 / 42
0.00% covered (danger)
0.00%
0 / 6
210
0.00% covered (danger)
0.00%
0 / 1
 __construct
0.00% covered (danger)
0.00%
0 / 2
0.00% covered (danger)
0.00%
0 / 1
2
 doesWrites
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 getName
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 show
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 showForAction
0.00% covered (danger)
0.00%
0 / 23
0.00% covered (danger)
0.00%
0 / 1
30
 getRedirectUrl
0.00% covered (danger)
0.00%
0 / 14
0.00% covered (danger)
0.00%
0 / 1
30
1<?php
2
3namespace Flow\Actions;
4
5use Action;
6use Article;
7use ErrorPageError;
8use Flow\Container;
9use Flow\Data\ManagerGroup;
10use Flow\Exception\FlowException;
11use Flow\Model\UUID;
12use Flow\Model\Workflow;
13use Flow\View;
14use Flow\WorkflowLoaderFactory;
15use MediaWiki\Context\IContextSource;
16use MediaWiki\Output\OutputPage;
17use MediaWiki\Request\WebRequest;
18use MediaWiki\Title\Title;
19
20class FlowAction extends Action {
21    /**
22     * @var string
23     */
24    protected $actionName;
25
26    /**
27     * @param Article $article
28     * @param IContextSource $source
29     * @param string $actionName
30     */
31    public function __construct( Article $article, IContextSource $source, $actionName ) {
32        parent::__construct( $article, $source );
33        $this->actionName = $actionName;
34    }
35
36    public function doesWrites() {
37        return true;
38    }
39
40    /**
41     * @return string
42     */
43    public function getName() {
44        return $this->actionName;
45    }
46
47    public function show() {
48        $this->showForAction( $this->getName() );
49    }
50
51    /**
52     * @param string $action
53     * @param OutputPage|null $output
54     * @throws ErrorPageError
55     * @throws FlowException
56     */
57    public function showForAction( $action, ?OutputPage $output = null ) {
58        $container = Container::getContainer();
59        $output ??= $this->context->getOutput();
60        $title = $this->getTitle();
61
62        $titleContentModel = $title->getContentModel();
63        if ( $titleContentModel !== CONTENT_MODEL_FLOW_BOARD ) {
64            // If we make it to this method, something thinks it's Flow.
65            // However, if we get here the Title class thinks otherwise.
66
67            // This may mean it is a non-Flow page in a Flow namespace, if
68            // page_content_model is populated but rev_content_model is not.
69
70            throw new ErrorPageError( 'nosuchaction', 'flow-action-wrong-title-content-model', [ $titleContentModel ] );
71        }
72
73        // @todo much of this seems to duplicate BoardContent::getParserOutput
74        $view = new View(
75            $container['url_generator'],
76            $container['lightncandy'],
77            $output,
78            $container['flow_actions']
79        );
80
81        $request = $this->context->getRequest();
82
83        // BC for urls pre july 2014 with workflow query parameter
84        $redirect = $this->getRedirectUrl( $request, $title );
85        if ( $redirect ) {
86            $output->redirect( $redirect );
87            return;
88        }
89
90        $action = $request->getVal( 'action', 'view' );
91        /** @var WorkflowLoaderFactory $factory */
92        $factory = $container['factory.loader.workflow'];
93        $loader = $factory->createWorkflowLoader( $title );
94
95        if ( $title->getNamespace() === NS_TOPIC && $loader->getWorkflow()->getType() !== 'topic' ) {
96            // @todo better error handling
97            throw new FlowException( 'Invalid title: uuid is not a topic' );
98        }
99
100        $view->show( $loader, $action );
101    }
102
103    /**
104     * Flow used to output some permalink urls with workflow ids in them. Each
105     * workflow now has its own page, so those have been deprecated. This checks
106     * a web request for the old workflow parameter and returns a url to redirect
107     * to if necessary.
108     *
109     * @param WebRequest $request
110     * @param Title $title
111     * @return string URL to redirect to or blank string for no redirect
112     */
113    protected function getRedirectUrl( WebRequest $request, Title $title ) {
114        $workflow = $request->getVal( 'workflow', null );
115        $workflowId = $workflow !== null ? UUID::create( strtolower( $workflow ) ) : null;
116        if ( !$workflowId ) {
117            return '';
118        }
119
120        /** @var ManagerGroup $storage */
121        $storage = Container::get( 'storage' );
122        /** @var Workflow $workflow */
123        $workflow = $storage->get( 'Workflow', $workflowId );
124
125        // The uuid points to a non-existant workflow
126        if ( !$workflow ) {
127            return '';
128        }
129
130        // The uuid points to the current page
131        $redirTitle = $workflow->getArticleTitle();
132        if ( $redirTitle->equals( $title ) ) {
133            return '';
134        }
135
136        // We need to redirect
137        return $redirTitle->getLinkURL(
138            array_diff_key( $request->getValues(), [ 'title' => '', 'workflow' => '' ] )
139        );
140    }
141}