Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
Total | |
0.00% |
0 / 86 |
|
0.00% |
0 / 6 |
CRAP | |
0.00% |
0 / 1 |
SpecialCode | |
0.00% |
0 / 86 |
|
0.00% |
0 / 6 |
930 | |
0.00% |
0 / 1 |
__construct | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
getSubpagesForPrefixSearch | |
0.00% |
0 / 8 |
|
0.00% |
0 / 1 |
12 | |||
execute | |
0.00% |
0 / 23 |
|
0.00% |
0 / 1 |
30 | |||
getViewFrom | |
0.00% |
0 / 52 |
|
0.00% |
0 / 1 |
380 | |||
getGroupName | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
isListed | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 |
1 | <?php |
2 | |
3 | namespace MediaWiki\Extension\CodeReview\UI; |
4 | |
5 | use MediaWiki\Extension\CodeReview\Backend\CodeRepository; |
6 | use SpecialPage; |
7 | |
8 | /** |
9 | * Main UI entry point. This calls the appropriate CodeView subclass and runs it |
10 | */ |
11 | class SpecialCode extends SpecialPage { |
12 | public function __construct() { |
13 | parent::__construct( 'Code', 'codereview-use' ); |
14 | } |
15 | |
16 | /** |
17 | * Return an array of subpages that this special page will accept. |
18 | * |
19 | * @return string[] subpages |
20 | */ |
21 | public function getSubpagesForPrefixSearch() { |
22 | $repos = CodeRepository::getRepoList(); |
23 | if ( count( $repos ) ) { |
24 | $retVal = []; |
25 | foreach ( $repos as $repo ) { |
26 | $retVal[] = $repo->getName(); |
27 | } |
28 | sort( $retVal ); |
29 | return $retVal; |
30 | } |
31 | return []; |
32 | } |
33 | |
34 | /** |
35 | * @param string $subpage |
36 | */ |
37 | public function execute( $subpage ) { |
38 | $this->checkPermissions(); |
39 | |
40 | $this->setHeaders(); |
41 | // Base styles used for all code review UI actions. |
42 | $out = $this->getOutput(); |
43 | $out->addModules( 'ext.codereview' ); |
44 | $out->addModules( 'ext.codereview.tooltips' ); |
45 | $out->addModuleStyles( 'ext.codereview.styles' ); |
46 | |
47 | // Load [[MediaWiki:CodeReview.css]] (bug #16049) if site CSS is enabled |
48 | if ( $this->getConfig()->get( 'UseSiteCss' ) ) { |
49 | $out->addModuleStyles( 'ext.codereview.local' ); |
50 | } |
51 | |
52 | $view = $this->getViewFrom( $subpage ); |
53 | if ( $view ) { |
54 | $view->execute(); |
55 | } else { |
56 | $out->addWikiMsg( 'nosuchactiontext' ); |
57 | $out->returnToMain( null, $this->getPageTitle() ); |
58 | return; |
59 | } |
60 | |
61 | // Add subtitle for easy navigation |
62 | if ( $view instanceof CodeView ) { |
63 | $repo = $view->getRepo(); |
64 | |
65 | if ( $repo ) { |
66 | $out->setSubtitle( |
67 | $this->msg( |
68 | 'codereview-subtitle', |
69 | CodeRepoListView::getNavItem( $repo, $this->getUser() ) |
70 | )->parseAsBlock() |
71 | ); |
72 | } |
73 | } |
74 | } |
75 | |
76 | /** |
77 | * Get a view object from a sub page path. |
78 | * @param string|null $subpage |
79 | * @return CodeView|CodeRepoListView|null - Null if no valid action could be found |
80 | */ |
81 | private function getViewFrom( $subpage ) { |
82 | // Defines the classes to use for each view type. |
83 | // The first class name is used if no additional parameters are provided. |
84 | // The second, if defined, is used if there is an additional parameter. If |
85 | // there is no second class defined, then the first class is used in both |
86 | // cases. |
87 | static $paramClasses = [ |
88 | 'tag' => [ CodeTagListView::class, CodeRevisionTagView::class, ], |
89 | 'author' => [ CodeAuthorListView::class, CodeRevisionAuthorView::class ], |
90 | 'status' => [ CodeStatusListView::class, CodeRevisionStatusView::class ], |
91 | 'comments' => [ CodeCommentsListView::class ], |
92 | 'statuschanges' => [ CodeStatusChangeListView::class ], |
93 | 'releasenotes' => [ CodeReleaseNotes::class ], |
94 | 'stats' => [ CodeRepoStatsView::class ], |
95 | ]; |
96 | |
97 | $request = $this->getRequest(); |
98 | # Remove stray slashes |
99 | $subpage = preg_replace( '/\/$/', '', $subpage ?? '' ); |
100 | if ( $subpage == '' ) { |
101 | $view = new CodeRepoListView(); |
102 | } else { |
103 | $params = explode( '/', $subpage ); |
104 | |
105 | $repo = CodeRepository::newFromName( $params[0] ); |
106 | // If a repository was specified, but it does not exist, redirect to the |
107 | // repository list with an appropriate message. |
108 | if ( !$repo ) { |
109 | $view = new CodeRepoListView(); |
110 | $this->getOutput()->addWikiMsg( 'code-repo-not-found', wfEscapeWikiText( $params[0] ) ); |
111 | return $view; |
112 | } |
113 | |
114 | $user = $this->getUser(); |
115 | |
116 | switch ( count( $params ) ) { |
117 | case 1: |
118 | $view = new CodeRevisionListView( $repo ); |
119 | break; |
120 | case 2: |
121 | // drop through... |
122 | case 3: |
123 | if ( isset( $paramClasses[$params[1]] ) ) { |
124 | $row = $paramClasses[$params[1]]; |
125 | if ( isset( $params[2] ) && isset( $row[1] ) ) { |
126 | $view = new $row[1]( $repo, $params[2] ); |
127 | } else { |
128 | $view = new $row[0]( $repo ); |
129 | } |
130 | } elseif ( $request->wasPosted() && !$request->getCheck( 'wpPreview' ) ) { |
131 | # This is not really a view, but we return it nonetheless. |
132 | # Add any tags, Set status, Adds comments |
133 | // @phan-suppress-next-line PhanTypeMismatchArgumentReal |
134 | $view = new CodeRevisionCommitter( $repo, $user, $params[1] ); |
135 | } elseif ( empty( $params[1] ) ) { |
136 | $view = new CodeRevisionListView( $repo ); |
137 | } else { |
138 | $view = new CodeRevisionView( $repo, $params[1], $user ); |
139 | } |
140 | break; |
141 | case 4: |
142 | if ( $params[1] === 'author' && $params[3] === 'link' ) { |
143 | $view = new CodeRevisionAuthorLink( $repo, $params[2], $this->getUser() ); |
144 | break; |
145 | } elseif ( $params[1] === 'comments' ) { |
146 | $view = new CodeCommentsAuthorListView( $repo, $params[3] ); |
147 | break; |
148 | } elseif ( $params[1] === 'statuschanges' ) { |
149 | $view = new CodeStatusChangeAuthorListView( $repo, $params[3] ); |
150 | break; |
151 | } |
152 | // @todo FIXME: Fall through or not? |
153 | default: |
154 | if ( $params[2] == 'reply' ) { |
155 | $view = new CodeRevisionView( $repo, $params[1], $user, $params[3] ); |
156 | break; |
157 | } |
158 | return null; |
159 | } |
160 | } |
161 | return $view; |
162 | } |
163 | |
164 | protected function getGroupName() { |
165 | return 'developer'; |
166 | } |
167 | |
168 | /** |
169 | * Only list me on Special:SpecialPages when configured. |
170 | * @return bool |
171 | */ |
172 | public function isListed() { |
173 | return $this->getConfig()->get( 'CodeReviewListSpecialPage' ); |
174 | } |
175 | } |