Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
Total | |
0.00% |
0 / 97 |
|
0.00% |
0 / 13 |
CRAP | |
0.00% |
0 / 1 |
Session | |
0.00% |
0 / 97 |
|
0.00% |
0 / 13 |
1640 | |
0.00% |
0 / 1 |
hasSession | |
0.00% |
0 / 2 |
|
0.00% |
0 / 1 |
2 | |||
startSession | |
0.00% |
0 / 3 |
|
0.00% |
0 / 1 |
2 | |||
touchSession | |
0.00% |
0 / 4 |
|
0.00% |
0 / 1 |
2 | |||
clearCollection | |
0.00% |
0 / 10 |
|
0.00% |
0 / 1 |
2 | |||
enable | |
0.00% |
0 / 4 |
|
0.00% |
0 / 1 |
2 | |||
disable | |
0.00% |
0 / 6 |
|
0.00% |
0 / 1 |
6 | |||
isEnabled | |
0.00% |
0 / 4 |
|
0.00% |
0 / 1 |
12 | |||
hasItems | |
0.00% |
0 / 3 |
|
0.00% |
0 / 1 |
6 | |||
countArticles | |
0.00% |
0 / 8 |
|
0.00% |
0 / 1 |
30 | |||
findArticle | |
0.00% |
0 / 17 |
|
0.00% |
0 / 1 |
132 | |||
purge | |
0.00% |
0 / 25 |
|
0.00% |
0 / 1 |
90 | |||
getCollection | |
0.00% |
0 / 8 |
|
0.00% |
0 / 1 |
6 | |||
setCollection | |
0.00% |
0 / 3 |
|
0.00% |
0 / 1 |
2 |
1 | <?php |
2 | |
3 | namespace MediaWiki\Extension\Collection; |
4 | |
5 | use MediaWiki\MediaWikiServices; |
6 | use MediaWiki\Session\SessionManager; |
7 | use MediaWiki\Title\Title; |
8 | |
9 | /** |
10 | * Collection Extension for MediaWiki |
11 | * |
12 | * Copyright (C) PediaPress GmbH |
13 | * |
14 | * This program is free software; you can redistribute it and/or modify |
15 | * it under the terms of the GNU General Public License as published by |
16 | * the Free Software Foundation; either version 2 of the License, or |
17 | * (at your option) any later version. |
18 | * |
19 | * This program is distributed in the hope that it will be useful, |
20 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
21 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
22 | * GNU General Public License for more details. |
23 | * |
24 | * You should have received a copy of the GNU General Public License along |
25 | * with this program; if not, write to the Free Software Foundation, Inc., |
26 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
27 | * http://www.gnu.org/copyleft/gpl.html |
28 | */ |
29 | |
30 | class Session { |
31 | /** |
32 | * @return bool |
33 | */ |
34 | public static function hasSession() { |
35 | $session = SessionManager::getGlobalSession(); |
36 | return isset( $session['wsCollection'] ); |
37 | } |
38 | |
39 | public static function startSession() { |
40 | $session = SessionManager::getGlobalSession(); |
41 | $session->persist(); |
42 | |
43 | self::clearCollection(); |
44 | } |
45 | |
46 | public static function touchSession() { |
47 | $session = SessionManager::getGlobalSession(); |
48 | $collection = $session['wsCollection']; |
49 | $collection['timestamp'] = wfTimestampNow(); |
50 | $session['wsCollection'] = $collection; |
51 | } |
52 | |
53 | public static function clearCollection() { |
54 | $session = SessionManager::getGlobalSession(); |
55 | $session['wsCollection'] = [ |
56 | 'enabled' => true, |
57 | 'title' => '', |
58 | 'subtitle' => '', |
59 | 'settings' => [], |
60 | 'items' => [], |
61 | ]; |
62 | Suggest::clear(); |
63 | self::touchSession(); |
64 | } |
65 | |
66 | public static function enable() { |
67 | $session = SessionManager::getGlobalSession(); |
68 | $session->persist(); |
69 | |
70 | $session['wsCollection']['enabled'] = true; |
71 | self::touchSession(); |
72 | } |
73 | |
74 | public static function disable() { |
75 | $session = SessionManager::getGlobalSession(); |
76 | |
77 | if ( !isset( $session['wsCollection'] ) ) { |
78 | return; |
79 | } |
80 | self::clearCollection(); |
81 | $session['wsCollection']['enabled'] = false; |
82 | self::touchSession(); |
83 | } |
84 | |
85 | /** |
86 | * @return bool |
87 | */ |
88 | public static function isEnabled() { |
89 | $session = SessionManager::getGlobalSession(); |
90 | |
91 | return isset( $session['wsCollection'] ) && |
92 | isset( $session['wsCollection']['enabled'] ) && |
93 | $session['wsCollection']['enabled']; |
94 | } |
95 | |
96 | /** |
97 | * @return bool |
98 | */ |
99 | public static function hasItems() { |
100 | $session = SessionManager::getGlobalSession(); |
101 | |
102 | return isset( $session['wsCollection'] ) && |
103 | isset( $session['wsCollection']['items'] ); |
104 | } |
105 | |
106 | /** |
107 | * @return int |
108 | */ |
109 | public static function countArticles() { |
110 | if ( !self::hasItems() ) { |
111 | return 0; |
112 | } |
113 | $session = SessionManager::getGlobalSession(); |
114 | $count = 0; |
115 | foreach ( $session['wsCollection']['items'] as $item ) { |
116 | if ( $item && $item['type'] == 'article' ) { |
117 | $count++; |
118 | } |
119 | } |
120 | return $count; |
121 | } |
122 | |
123 | /** |
124 | * @param string $title |
125 | * @param int $oldid |
126 | * @return int |
127 | */ |
128 | public static function findArticle( $title, $oldid = 0 ) { |
129 | if ( !self::hasItems() ) { |
130 | return -1; |
131 | } |
132 | |
133 | // FIXME: Some places use DB keys, other use prefixedtext, and this can lead to mismatches. |
134 | // This class should just take Title (or a narrower interface) and be responsible for the stringification! |
135 | $titleObj = Title::newFromText( $title ); |
136 | $titleStr = $titleObj ? $titleObj->getPrefixedDBkey() : $title; |
137 | $session = SessionManager::getGlobalSession(); |
138 | |
139 | foreach ( $session['wsCollection']['items'] as $index => $item ) { |
140 | if ( !$item || $item['type'] !== 'article' ) { |
141 | continue; |
142 | } |
143 | $curTitleObj = Title::newFromText( $item['title'] ); |
144 | $curTitleStr = $curTitleObj ? $curTitleObj->getPrefixedDBkey() : $item['title']; |
145 | if ( $curTitleStr === $titleStr ) { |
146 | if ( $oldid ) { |
147 | if ( $item['revision'] == strval( $oldid ) ) { |
148 | return $index; |
149 | } |
150 | } else { |
151 | if ( $item['revision'] == $item['latest'] ) { |
152 | return $index; |
153 | } |
154 | } |
155 | } |
156 | } |
157 | return -1; |
158 | } |
159 | |
160 | /** |
161 | * @return bool |
162 | */ |
163 | public static function purge() { |
164 | $session = SessionManager::getGlobalSession(); |
165 | |
166 | if ( !isset( $session['wsCollection'] ) ) { |
167 | return false; |
168 | } |
169 | |
170 | $coll = $session['wsCollection']; |
171 | $coll['items'] ??= []; |
172 | // Remove broken entries caused by old, bogus code paths |
173 | $coll['items'] = array_filter( $coll['items'] ); |
174 | |
175 | // Checking if articles exist is expensive, use a single batch to speed it up |
176 | $services = MediaWikiServices::getInstance(); |
177 | $linkBatch = $services->getLinkBatchFactory()->newLinkBatch(); |
178 | $linkCache = $services->getLinkCache(); |
179 | foreach ( $coll['items'] as $item ) { |
180 | if ( $item['type'] === 'article' ) { |
181 | $title = Title::newFromText( $item['title'] ); |
182 | if ( $title ) { |
183 | $linkBatch->addObj( $title ); |
184 | } |
185 | } |
186 | } |
187 | $linkBatch->execute(); |
188 | |
189 | $newitems = []; |
190 | foreach ( $coll['items'] as $item ) { |
191 | if ( $item['type'] === 'article' ) { |
192 | $title = Title::newFromText( $item['title'] ); |
193 | // Remove articles that don't exist any more |
194 | if ( !$title || $linkCache->isBadLink( $title->getPrefixedDBkey() ) ) { |
195 | continue; |
196 | } |
197 | } |
198 | $newitems[] = $item; |
199 | } |
200 | $coll['items'] = $newitems; |
201 | $session['wsCollection'] = $coll; |
202 | return true; |
203 | } |
204 | |
205 | /** |
206 | * @return array |
207 | */ |
208 | public static function getCollection() { |
209 | $session = SessionManager::getGlobalSession(); |
210 | $collection = self::purge() ? $session['wsCollection'] : []; |
211 | return array_merge( [ |
212 | /* Make sure required properties are present. */ |
213 | 'title' => '', |
214 | 'subtitle' => '', |
215 | 'settings' => [], |
216 | 'items' => [], |
217 | ], $collection ); |
218 | } |
219 | |
220 | /** |
221 | * @param array $collection |
222 | */ |
223 | public static function setCollection( array $collection ) { |
224 | $session = SessionManager::getGlobalSession(); |
225 | $session['wsCollection'] = $collection; |
226 | self::touchSession(); |
227 | } |
228 | } |