Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
Total | |
0.00% |
0 / 111 |
|
0.00% |
0 / 2 |
CRAP | |
0.00% |
0 / 1 |
CargoPageData | |
0.00% |
0 / 111 |
|
0.00% |
0 / 2 |
2162 | |
0.00% |
0 / 1 |
getTableSchema | |
0.00% |
0 / 33 |
|
0.00% |
0 / 1 |
210 | |||
storeValuesForPage | |
0.00% |
0 / 78 |
|
0.00% |
0 / 1 |
1056 |
1 | <?php |
2 | |
3 | use MediaWiki\MediaWikiServices; |
4 | use MediaWiki\Parser\ParserOutputLinkTypes; |
5 | use MediaWiki\Title\Title; |
6 | |
7 | /** |
8 | * Static functions for dealing with the "_pageData" table. |
9 | * |
10 | * @author Yaron Koren |
11 | */ |
12 | class CargoPageData { |
13 | |
14 | /** |
15 | * Set the schema based on what has been entered in LocalSettings.php. |
16 | * Strings are used to set the field names; it would have been |
17 | * better to use constants (like CARGO_CREATION_DATE or |
18 | * CargoPageData::CREATION_DATE instead of 'creationDate') but |
19 | * unfortunately the extension.json system doesn't support any kind |
20 | * of constants. |
21 | * |
22 | * @return CargoTableSchema |
23 | */ |
24 | public static function getTableSchema() { |
25 | global $wgCargoPageDataColumns; |
26 | |
27 | $fieldTypes = []; |
28 | |
29 | // @TODO - change this code to match the approach taken in |
30 | // CargoFileData.php. This will be more important if/when |
31 | // some additional parameter is added, like 'hidden'. |
32 | if ( in_array( 'creationDate', $wgCargoPageDataColumns ) ) { |
33 | $fieldTypes['_creationDate'] = [ 'Datetime', false ]; |
34 | } |
35 | if ( in_array( 'modificationDate', $wgCargoPageDataColumns ) ) { |
36 | $fieldTypes['_modificationDate'] = [ 'Datetime', false ]; |
37 | } |
38 | if ( in_array( 'creator', $wgCargoPageDataColumns ) ) { |
39 | $fieldTypes['_creator'] = [ 'String', false ]; |
40 | } |
41 | if ( in_array( 'fullText', $wgCargoPageDataColumns ) ) { |
42 | $fieldTypes['_fullText'] = [ 'Searchtext', false ]; |
43 | } |
44 | if ( in_array( 'categories', $wgCargoPageDataColumns ) ) { |
45 | $fieldTypes['_categories'] = [ 'String', true ]; |
46 | } |
47 | if ( in_array( 'numRevisions', $wgCargoPageDataColumns ) ) { |
48 | $fieldTypes['_numRevisions'] = [ 'Integer', false ]; |
49 | } |
50 | if ( in_array( 'isRedirect', $wgCargoPageDataColumns ) ) { |
51 | $fieldTypes['_isRedirect'] = [ 'Boolean', false ]; |
52 | } |
53 | if ( in_array( 'pageNameOrRedirect', $wgCargoPageDataColumns ) ) { |
54 | $fieldTypes['_pageNameOrRedirect'] = [ 'String', false ]; |
55 | } |
56 | if ( in_array( 'pageIDOrRedirect', $wgCargoPageDataColumns ) ) { |
57 | $fieldTypes['_pageIDOrRedirect'] = [ 'Integer', false ]; |
58 | } |
59 | if ( in_array( 'lastEditor', $wgCargoPageDataColumns ) ) { |
60 | $fieldTypes['_lastEditor'] = [ 'String', false ]; |
61 | } |
62 | if ( in_array( 'outgoingLinks', $wgCargoPageDataColumns ) ) { |
63 | $fieldTypes['_outgoingLinks'] = [ 'String', true ]; |
64 | } |
65 | |
66 | $tableSchema = new CargoTableSchema(); |
67 | foreach ( $fieldTypes as $field => $fieldVals ) { |
68 | [ $type, $isList ] = $fieldVals; |
69 | $fieldDesc = new CargoFieldDescription(); |
70 | $fieldDesc->mType = $type; |
71 | if ( $isList ) { |
72 | $fieldDesc->mIsList = true; |
73 | $fieldDesc->setDelimiter( '|' ); |
74 | } |
75 | $tableSchema->mFieldDescriptions[$field] = $fieldDesc; |
76 | } |
77 | |
78 | return $tableSchema; |
79 | } |
80 | |
81 | /** |
82 | * The $setToBlank argument is a bit of a hack - used right now only |
83 | * for "blank if unapproved" with the Approved Revs extension, because |
84 | * that setting doesn't seem to take effect soon enough to get parsed |
85 | * as a blank page. |
86 | * |
87 | * @param Title $title |
88 | * @param bool $createReplacement |
89 | * @param bool $storeCategories |
90 | * @param bool $setToBlank |
91 | */ |
92 | public static function storeValuesForPage( |
93 | Title $title, $createReplacement, $storeCategories = true, $setToBlank = false |
94 | ) { |
95 | global $wgCargoPageDataColumns; |
96 | |
97 | $pageDataTable = $createReplacement ? '_pageData__NEXT' : '_pageData'; |
98 | |
99 | // If this table does not exist, getTableSchemas() will |
100 | // throw an error. |
101 | try { |
102 | $tableSchemas = CargoUtils::getTableSchemas( [ $pageDataTable ] ); |
103 | } catch ( MWException $e ) { |
104 | return; |
105 | } |
106 | |
107 | $wikiPage = CargoUtils::makeWikiPage( $title ); |
108 | $pageDataValues = []; |
109 | |
110 | if ( in_array( 'creationDate', $wgCargoPageDataColumns ) ) { |
111 | $firstRevision = MediaWikiServices::getInstance()->getRevisionLookup()->getFirstRevision( $title ); |
112 | if ( $firstRevision == null ) { |
113 | // This can sometimes happen. |
114 | $pageDataValues['_creationDate'] = null; |
115 | } else { |
116 | $pageDataValues['_creationDate'] = $firstRevision->getTimestamp(); |
117 | } |
118 | } |
119 | if ( in_array( 'modificationDate', $wgCargoPageDataColumns ) ) { |
120 | $pageDataValues['_modificationDate'] = $wikiPage->getTimestamp(); |
121 | } |
122 | if ( in_array( 'creator', $wgCargoPageDataColumns ) ) { |
123 | $pageDataValues['_creator'] = $wikiPage->getCreator(); |
124 | } |
125 | if ( in_array( 'fullText', $wgCargoPageDataColumns ) ) { |
126 | if ( $setToBlank ) { |
127 | $pageDataValues['_fullText'] = ''; |
128 | } else { |
129 | $pageDataValues['_fullText'] = CargoUtils::getContentText( $wikiPage->getContent() ); |
130 | } |
131 | } |
132 | if ( $storeCategories && in_array( 'categories', $wgCargoPageDataColumns ) ) { |
133 | $pageCategories = []; |
134 | if ( !$setToBlank ) { |
135 | $dbr = CargoUtils::getMainDBForRead(); |
136 | $res = $dbr->select( |
137 | 'categorylinks', |
138 | 'cl_to', |
139 | [ 'cl_from' => $title->getArticleID() ], |
140 | __METHOD__ |
141 | ); |
142 | foreach ( $res as $row ) { |
143 | $pageCategories[] = str_replace( '_', ' ', $row->cl_to ); |
144 | } |
145 | } |
146 | |
147 | $pageCategoriesString = implode( '|', $pageCategories ); |
148 | $pageDataValues['_categories'] = $pageCategoriesString; |
149 | } |
150 | if ( in_array( 'numRevisions', $wgCargoPageDataColumns ) ) { |
151 | $dbr = CargoUtils::getMainDBForRead(); |
152 | $pageDataValues['_numRevisions'] = $dbr->selectRowCount( |
153 | 'revision', |
154 | '*', |
155 | [ 'rev_page' => $title->getArticleID() ], |
156 | __METHOD__ |
157 | ); |
158 | } |
159 | if ( in_array( 'isRedirect', $wgCargoPageDataColumns ) ) { |
160 | $pageDataValues['_isRedirect'] = ( $title->isRedirect() ? 1 : 0 ); |
161 | } |
162 | // Check whether the page is a redirect only once, |
163 | // and evaluate pageNameOrRedirect and pageIDOrRedirect at the same time |
164 | if ( in_array( 'pageNameOrRedirect', $wgCargoPageDataColumns ) || in_array( 'pageIDOrRedirect', $wgCargoPageDataColumns ) ) { |
165 | // case when redirect |
166 | if ( $title->isRedirect() ) { |
167 | $redirTitle = $wikiPage->getRedirectTarget(); |
168 | if ( $redirTitle !== null ) { |
169 | if ( in_array( 'pageNameOrRedirect', $wgCargoPageDataColumns ) ) { |
170 | $pageDataValues['_pageNameOrRedirect'] = $redirTitle->getPrefixedText(); |
171 | } |
172 | if ( in_array( 'pageIDOrRedirect', $wgCargoPageDataColumns ) ) { |
173 | $pageDataValues['_pageIDOrRedirect'] = $redirTitle->getArticleID(); |
174 | } |
175 | } |
176 | // case when not a redirect |
177 | } else { |
178 | if ( in_array( 'pageNameOrRedirect', $wgCargoPageDataColumns ) ) { |
179 | $pageDataValues['_pageNameOrRedirect'] = $title->getPrefixedText(); |
180 | } |
181 | if ( in_array( 'pageIDOrRedirect', $wgCargoPageDataColumns ) ) { |
182 | $pageDataValues['_pageIDOrRedirect'] = $title->getArticleID(); |
183 | } |
184 | } |
185 | } |
186 | if ( in_array( 'lastEditor', $wgCargoPageDataColumns ) ) { |
187 | $latestRevision = MediaWikiServices::getInstance()->getRevisionLookup()->getRevisionByTitle( $title ); |
188 | if ( $latestRevision == null ) { |
189 | $pageDataValues['_lastEditor'] = null; |
190 | } else { |
191 | $pageDataValues['_lastEditor'] = $latestRevision->getUser()->getName(); |
192 | } |
193 | } |
194 | if ( in_array( 'outgoingLinks', $wgCargoPageDataColumns ) ) { |
195 | $outLinkPageIDs = []; |
196 | // ParserOutputLinkTypes exists only for MW versions >= 1.43 |
197 | if ( class_exists( 'MediaWiki\\Parser\\ParserOutputLinkTypes' ) ) { |
198 | $parserOutput = $wikiPage->getParserOutput(); |
199 | $outLinks = $parserOutput->getLinkList( ParserOutputLinkTypes::LOCAL ); |
200 | foreach ( $outLinks as $outLink ) { |
201 | $outLinkPageIDs[] = $outLink['pageid']; |
202 | } |
203 | } else { |
204 | $outTitles = $wikiPage->getTitle()->getLinksFrom(); |
205 | foreach ( $outTitles as $outTitle ) { |
206 | $outLinkPageIDs[] = $outTitle->getArticleID(); |
207 | } |
208 | } |
209 | if ( count( $outLinkPageIDs ) > 0 ) { |
210 | $outLinkString = implode( '|', $outLinkPageIDs ); |
211 | $pageDataValues['_outgoingLinks'] = $outLinkString; |
212 | } else { |
213 | $pageDataValues['_outgoingLinks'] = null; |
214 | } |
215 | } |
216 | |
217 | $pageDataSchema = $tableSchemas[$pageDataTable]; |
218 | // If this is being called as a result of a page save, we |
219 | // don't handle the '_categories' field, because categories |
220 | // often don't get set until after the page has been saved, |
221 | // due to jobs. Instead there are separate hooks to handle it. |
222 | if ( !$storeCategories ) { |
223 | $pageDataSchema->removeField( '_categories' ); |
224 | } |
225 | |
226 | CargoStore::storeAllData( $title, $pageDataTable, $pageDataValues, $pageDataSchema ); |
227 | } |
228 | |
229 | } |