Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
0.00% covered (danger)
0.00%
0 / 118
0.00% covered (danger)
0.00%
0 / 3
CRAP
0.00% covered (danger)
0.00%
0 / 1
SpecialCargoRecreateData
0.00% covered (danger)
0.00%
0 / 118
0.00% covered (danger)
0.00%
0 / 3
462
0.00% covered (danger)
0.00%
0 / 1
 __construct
0.00% covered (danger)
0.00%
0 / 4
0.00% covered (danger)
0.00%
0 / 1
2
 execute
0.00% covered (danger)
0.00%
0 / 102
0.00% covered (danger)
0.00%
0 / 1
380
 getNumPagesThatCallTemplate
0.00% covered (danger)
0.00%
0 / 12
0.00% covered (danger)
0.00%
0 / 1
2
1<?php
2
3use MediaWiki\Html\Html;
4use MediaWiki\Linker\LinkTarget;
5use MediaWiki\MediaWikiServices;
6use MediaWiki\Title\Title;
7
8/**
9 * Displays an interface to let users recreate data via the Cargo
10 * extension.
11 *
12 * @author Yaron Koren
13 * @ingroup Cargo
14 */
15
16class SpecialCargoRecreateData extends UnlistedSpecialPage {
17    public $mTemplateTitle;
18    public $mTableName;
19    public $mIsDeclared;
20
21    public function __construct( $templateTitle = null, $tableName = null, $isDeclared = false ) {
22        parent::__construct( 'RecreateCargoData' );
23        $this->mTemplateTitle = $templateTitle;
24        $this->mTableName = $tableName;
25        $this->mIsDeclared = $isDeclared;
26    }
27
28    public function execute( $query = null ) {
29        global $cgScriptPath;
30
31        // Check permissions.
32        if ( !$this->getUser()->isAllowed( 'recreatecargodata' ) ) {
33            $this->displayRestrictionError();
34        }
35
36        $out = $this->getOutput();
37        $out->enableOOUI();
38        $this->setHeaders();
39
40        if ( $this->mTableName == null ) {
41            $this->mTableName = $query;
42        }
43        $tableExists = CargoUtils::tableFullyExists( $this->mTableName );
44        if ( !$tableExists ) {
45            $out->setPageTitle( $this->msg( 'cargo-createdatatable' )->parse() );
46        }
47
48        // Disable page if "replacement table" exists.
49        $possibleReplacementTable = $this->mTableName . '__NEXT';
50        if ( CargoUtils::tableFullyExists( $this->mTableName ) && CargoUtils::tableFullyExists( $possibleReplacementTable ) ) {
51            $text = $this->msg( 'cargo-recreatedata-replacementexists', $this->mTableName, $possibleReplacementTable )->parse();
52            $ctURL = SpecialPage::getTitleFor( 'CargoTables' )->getFullURL();
53            $viewURL = $ctURL . '/' . $this->mTableName;
54            $viewURL .= strpos( $viewURL, '?' ) ? '&' : '?';
55            $viewURL .= "_replacement";
56            $viewReplacementText = $this->msg( 'cargo-cargotables-viewreplacementlink' )->parse();
57
58            $text .= ' (' . Html::element( 'a', [ 'href' => $viewURL ], $viewReplacementText ) . ')';
59            $out->addHTML( $text );
60            return true;
61        }
62
63        $specialTableNames = CargoUtils::specialTableNames();
64        if ( !$this->mTemplateTitle && !in_array( $this->mTableName, $specialTableNames ) ) {
65            // TODO - show an error message.
66            return true;
67        }
68
69        $out->addModules( 'ext.cargo.recreatedata' );
70
71        $templateData = [];
72        $dbr = CargoUtils::getMainDBForRead();
73        if ( $this->mTemplateTitle === null ) {
74            if ( $this->mTableName == '_pageData' ) {
75                $conds = '';
76            } elseif ( $this->mTableName == '_fileData' ) {
77                $conds = 'page_namespace = ' . NS_FILE;
78            } elseif ( $this->mTableName == '_bpmnData' ) {
79                $conds = 'page_namespace = ' . FD_NS_BPMN;
80            } else { // if ( $this->mTableName == '_ganttData' ) {
81                $conds = 'page_namespace = ' . FD_NS_GANTT;
82            }
83            $numTotalPages = $dbr->selectField( 'page', 'COUNT(*)', $conds, __METHOD__ );
84        } else {
85            $numTotalPages = null;
86            $templateData[] = [
87                'name' => $this->mTemplateTitle->getText(),
88                'numPages' => $this->getNumPagesThatCallTemplate( $dbr, $this->mTemplateTitle )
89            ];
90        }
91
92        if ( $this->mIsDeclared ) {
93            // Get all attached templates.
94            $res = $dbr->select( 'page_props',
95                [
96                    'pp_page'
97                ],
98                [
99                    'pp_value' => $this->mTableName,
100                    'pp_propname' => 'CargoAttachedTable'
101                ],
102                __METHOD__
103            );
104            foreach ( $res as $row ) {
105                $templateID = $row->pp_page;
106                $attachedTemplateTitle = Title::newFromID( $templateID );
107                $numPages = $this->getNumPagesThatCallTemplate( $dbr, $attachedTemplateTitle );
108                $attachedTemplateName = $attachedTemplateTitle->getText();
109                $templateData[] = [
110                    'name' => $attachedTemplateName,
111                    'numPages' => $numPages
112                ];
113            }
114        }
115
116        $ct = SpecialPage::getTitleFor( 'CargoTables' );
117        $viewTableURL = $ct->getLocalURL() . '/' . $this->mTableName;
118
119        // Store all the necesssary data on the page.
120        $text = Html::element( 'div', [
121                'hidden' => 'true',
122                'id' => 'recreateDataData',
123                // 'cargoscriptpath' is not data-
124                // specific, but this seemed like the
125                // easiest way to pass it over without
126                // interfering with any other pages.
127                'cargoscriptpath' => $cgScriptPath,
128                'tablename' => $this->mTableName,
129                'isspecialtable' => ( $this->mTemplateTitle == null ),
130                'isdeclared' => $this->mIsDeclared,
131                'totalpages' => $numTotalPages,
132                'viewtableurl' => $viewTableURL
133            ], json_encode( $templateData ) );
134
135        // Simple form.
136        $text .= '<div id="recreateDataCanvas">' . "\n";
137        if ( $tableExists ) {
138            $checkBox = new OOUI\FieldLayout(
139                new OOUI\CheckboxInputWidget( [
140                    'name' => 'createReplacement',
141                    'selected' => true,
142                    'value' => 1,
143                ] ),
144                [
145                    'label' => $this->msg( 'cargo-recreatedata-createreplacement' )->parse(),
146                    'align' => 'inline',
147                    'infusable' => true,
148                ]
149            );
150            $text .= Html::rawElement( 'p', [], $checkBox->toString() );
151        }
152
153        if ( $this->mTemplateTitle == null ) {
154            $msg = $tableExists ? 'cargo-recreatedata-recreatetable' : 'cargo-recreatedata-createtable';
155            $text .= Html::element( 'p', [], $this->msg( $msg, $this->mTableName )->parse() );
156        } else {
157            $msg = $tableExists ? 'cargo-recreatedata-desc' : 'cargo-recreatedata-createdata';
158            $text .= Html::element( 'p', [], $this->msg( $msg )->parse() );
159        }
160
161        $text .= new OOUI\ButtonInputWidget( [
162            'id' => 'cargoSubmit',
163            'label' => $this->msg( 'ok' )->parse(),
164            'flags' => [ 'primary', 'progressive' ]
165         ] );
166        $text .= "\n</div>";
167
168        $out->addHTML( $text );
169
170        return true;
171    }
172
173    public function getNumPagesThatCallTemplate( $dbr, LinkTarget $templateTitle ) {
174        $conds = [ "tl_from=page_id" ];
175        $linkTargetLookup = MediaWikiServices::getInstance()->getLinkTargetLookup();
176        $conds['tl_target_id'] = $linkTargetLookup->getLinkTargetId( $templateTitle );
177
178        $res = $dbr->select(
179            [ 'page', 'templatelinks' ],
180            'COUNT(*) AS total',
181            $conds,
182            __METHOD__,
183            []
184        );
185        $row = $res->fetchRow();
186        return intval( $row['total'] );
187    }
188
189}