Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
0.00% covered (danger)
0.00%
0 / 95
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 / 95
0.00% covered (danger)
0.00%
0 / 2
1806
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 / 64
0.00% covered (danger)
0.00%
0 / 1
870
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            list( $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        if ( $title == null ) {
93            return;
94        }
95
96        $pageDataTable = $createReplacement ? '_pageData__NEXT' : '_pageData';
97
98        // If this table does not exist, getTableSchemas() will
99        // throw an error.
100        try {
101            $tableSchemas = CargoUtils::getTableSchemas( [ $pageDataTable ] );
102        } catch ( MWException $e ) {
103            return;
104        }
105
106        $wikiPage = CargoUtils::makeWikiPage( $title );
107        $pageDataValues = [];
108
109        if ( in_array( 'creationDate', $wgCargoPageDataColumns ) ) {
110            if ( method_exists( 'MediaWiki\Revision\RevisionLookup', 'getFirstRevision' ) ) {
111                // MW >= 1.35
112                $firstRevision = MediaWikiServices::getInstance()->getRevisionLookup()->getFirstRevision( $title );
113            } else {
114                $firstRevision = $title->getFirstRevision();
115            }
116            if ( $firstRevision == null ) {
117                // This can sometimes happen.
118                $pageDataValues['_creationDate'] = null;
119            } else {
120                $pageDataValues['_creationDate'] = $firstRevision->getTimestamp();
121            }
122        }
123        if ( in_array( 'modificationDate', $wgCargoPageDataColumns ) ) {
124            $pageDataValues['_modificationDate'] = $wikiPage->getTimestamp();
125        }
126        if ( in_array( 'creator', $wgCargoPageDataColumns ) ) {
127            $pageDataValues['_creator'] = $wikiPage->getCreator();
128        }
129        if ( in_array( 'fullText', $wgCargoPageDataColumns ) ) {
130            if ( $setToBlank ) {
131                $pageDataValues['_fullText'] = '';
132            } else {
133                $page = CargoUtils::makeWikiPage( $title );
134                $pageDataValues['_fullText'] = ContentHandler::getContentText( $page->getContent() );
135            }
136        }
137        if ( $storeCategories && in_array( 'categories', $wgCargoPageDataColumns ) ) {
138            $pageCategories = [];
139            if ( !$setToBlank ) {
140                $lb = MediaWikiServices::getInstance()->getDBLoadBalancer();
141                $dbr = $lb->getConnectionRef( DB_REPLICA );
142                $res = $dbr->select(
143                    'categorylinks',
144                    'cl_to',
145                    [ 'cl_from' => $title->getArticleID() ],
146                    __METHOD__
147                );
148                foreach ( $res as $row ) {
149                    $pageCategories[] = str_replace( '_', ' ', $row->cl_to );
150                }
151            }
152
153            $pageCategoriesString = implode( '|', $pageCategories );
154            $pageDataValues['_categories'] = $pageCategoriesString;
155        }
156        if ( in_array( 'numRevisions', $wgCargoPageDataColumns ) ) {
157            $lb = MediaWikiServices::getInstance()->getDBLoadBalancer();
158            $dbr = $lb->getConnectionRef( DB_REPLICA );
159            $pageDataValues['_numRevisions'] = $dbr->selectRowCount(
160                'revision',
161                '*',
162                [ 'rev_page' => $title->getArticleID() ],
163                __METHOD__
164            );
165        }
166        if ( in_array( 'isRedirect', $wgCargoPageDataColumns ) ) {
167            $pageDataValues['_isRedirect'] = ( $title->isRedirect() ? 1 : 0 );
168        }
169        // Check whether the page is a redirect only once,
170        // and evaluate pageNameOrRedirect and pageIDOrRedirect at the same time
171        if ( in_array( 'pageNameOrRedirect', $wgCargoPageDataColumns ) || in_array( 'pageIDOrRedirect', $wgCargoPageDataColumns ) ) {
172            // case when redirect
173            if ( $title->isRedirect() ) {
174                $page = CargoUtils::makeWikiPage( $title );
175                $redirTitle = $page->getRedirectTarget();
176                if ( $redirTitle !== null ) {
177                    if ( in_array( 'pageNameOrRedirect', $wgCargoPageDataColumns ) ) {
178                        $pageDataValues['_pageNameOrRedirect'] = $redirTitle->getPrefixedText();
179                    }
180                    if ( in_array( 'pageIDOrRedirect', $wgCargoPageDataColumns ) ) {
181                        $pageDataValues['_pageIDOrRedirect'] = $redirTitle->getArticleID();
182                    }
183                }
184            // case when not a redirect
185            } else {
186                if ( in_array( 'pageNameOrRedirect', $wgCargoPageDataColumns ) ) {
187                    $pageDataValues['_pageNameOrRedirect'] = $title->getPrefixedText();
188                }
189                if ( in_array( 'pageIDOrRedirect', $wgCargoPageDataColumns ) ) {
190                    $pageDataValues['_pageIDOrRedirect'] = $title->getArticleID();
191                }
192            }
193        }
194        if ( in_array( 'lastEditor', $wgCargoPageDataColumns ) ) {
195            $latestRevision = MediaWikiServices::getInstance()->getRevisionLookup()->getRevisionByTitle( $title );
196            if ( $latestRevision == null ) {
197                $pageDataValues['_lastEditor'] = null;
198            } else {
199                $pageDataValues['_lastEditor'] = $latestRevision->getUser()->getName();
200            }
201        }
202
203        $pageDataSchema = $tableSchemas[$pageDataTable];
204        // If this is being called as a result of a page save, we
205        // don't handle the '_categories' field, because categories
206        // often don't get set until after the page has been saved,
207        // due to jobs. Instead there are separate hooks to handle it.
208        if ( !$storeCategories ) {
209            $pageDataSchema->removeField( '_categories' );
210        }
211
212        CargoStore::storeAllData( $title, $pageDataTable, $pageDataValues, $pageDataSchema );
213    }
214
215}