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