Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
0.00% covered (danger)
0.00%
0 / 111
0.00% covered (danger)
0.00%
0 / 2
CRAP
0.00% covered (danger)
0.00%
0 / 1
CargoPageData
0.00% covered (danger)
0.00%
0 / 111
0.00% covered (danger)
0.00%
0 / 2
2162
0.00% covered (danger)
0.00%
0 / 1
 getTableSchema
0.00% covered (danger)
0.00%
0 / 33
0.00% covered (danger)
0.00%
0 / 1
210
 storeValuesForPage
0.00% covered (danger)
0.00%
0 / 78
0.00% covered (danger)
0.00%
0 / 1
1056
1<?php
2
3use MediaWiki\MediaWikiServices;
4use MediaWiki\Parser\ParserOutputLinkTypes;
5use MediaWiki\Title\Title;
6
7/**
8 * Static functions for dealing with the "_pageData" table.
9 *
10 * @author Yaron Koren
11 */
12class 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}