Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
0.00% covered (danger)
0.00%
0 / 167
0.00% covered (danger)
0.00%
0 / 8
CRAP
0.00% covered (danger)
0.00%
0 / 1
PFTemplateDisplay
0.00% covered (danger)
0.00%
0 / 167
0.00% covered (danger)
0.00%
0 / 8
3306
0.00% covered (danger)
0.00%
0 / 1
 run
0.00% covered (danger)
0.00%
0 / 95
0.00% covered (danger)
0.00%
0 / 1
1482
 mapText
0.00% covered (danger)
0.00%
0 / 21
0.00% covered (danger)
0.00%
0 / 1
30
 pageListText
0.00% covered (danger)
0.00%
0 / 10
0.00% covered (danger)
0.00%
0 / 1
20
 pageText
0.00% covered (danger)
0.00%
0 / 16
0.00% covered (danger)
0.00%
0 / 1
20
 stringListText
0.00% covered (danger)
0.00%
0 / 3
0.00% covered (danger)
0.00%
0 / 1
2
 ratingText
0.00% covered (danger)
0.00%
0 / 5
0.00% covered (danger)
0.00%
0 / 1
2
 fileText
0.00% covered (danger)
0.00%
0 / 9
0.00% covered (danger)
0.00%
0 / 1
2
 fileListText
0.00% covered (danger)
0.00%
0 / 8
0.00% covered (danger)
0.00%
0 / 1
12
1<?php
2
3use MediaWiki\Html\Html;
4use MediaWiki\Linker\Linker;
5use MediaWiki\MediaWikiServices;
6use MediaWiki\Title\Title;
7
8/**
9 * Defines the #template_display parser function.
10 *
11 * @author Yaron Koren
12 */
13
14class PFTemplateDisplay {
15
16    public static function run( &$parser, $frame, $args ) {
17        $title = $parser->getTitle();
18        $params = [];
19        foreach ( $args as $arg ) {
20            $params[] = trim( $frame->expand( $arg ) );
21        }
22
23        $templateFields = [];
24        $format = 'infobox';
25        $infoboxTitle = null;
26        $tableFieldValues = [];
27
28        $templateTitle = $frame->title;
29        $template = PFTemplate::newFromName( $templateTitle->getText() );
30        $templateParams = $template->getTemplateParams();
31        if ( $templateParams == null ) {
32            return '<div class="error">' . 'Error: #template_params must be called in the template "' . $templateTitle->getText() . '".</div>';
33        }
34
35        $parser->getOutput()->addModules( [ 'ext.pageforms.templatedisplay' ] );
36
37        foreach ( $params as $param ) {
38            $parts = explode( '=', $param, 2 );
39            if ( count( $parts ) == 1 ) {
40                // No such handled params at the moment.
41            } else {
42                $key = trim( $parts[0] );
43                $value = trim( $parts[1] );
44                if ( $key == '_format' ) {
45                    $format = $value;
46                } elseif ( $key == '_title' ) {
47                    $infoboxTitle = $value;
48                } else {
49                    $tableFieldValues[$key] = $value;
50                }
51            }
52        }
53
54        // Get all the values in this template call.
55        $templateFields = $template->getTemplateFields();
56        foreach ( $templateFields as $fieldName => $templateField ) {
57            $curFieldValue = $frame->getArgument( $fieldName );
58            if ( $curFieldValue == null ) {
59                $unescapedFieldName = str_replace( '_', ' ', $fieldName );
60                $curFieldValue = $frame->getArgument( $unescapedFieldName );
61            }
62            $tableFieldValues[$fieldName] = $parser->internalParse( $curFieldValue );
63        }
64
65        if ( $format == 'table' ) {
66            $text = '<table class="wikitable">' . "\n";
67        } elseif ( $format == 'infobox' ) {
68            $text = '<table class="infoboxTable">' . "\n";
69            // If it's blank (as opposed to null), it means the
70            // infobox title was deliberately set to empty, to avoid
71            // displaying a title row.
72            if ( $infoboxTitle !== '' ) {
73                if ( $infoboxTitle === null ) {
74                    $pageProps = MediaWikiServices::getInstance()->getPageProps()
75                        ->getProperties( $title, 'displaytitle' );
76                    $infoboxTitle = array_shift( $pageProps ) ??
77                        htmlspecialchars( $title->getFullText(), ENT_NOQUOTES );
78                }
79                $text .= '<tr><th colspan="2" class="infoboxTitle">' . $infoboxTitle . '</th></tr>' . "\n";
80            }
81        } else {
82            $text = '';
83        }
84        foreach ( $tableFieldValues as $fieldName => $fieldValue ) {
85            if ( !array_key_exists( $fieldName, $templateFields ) ) {
86                continue;
87            }
88            $templateField = $templateFields[$fieldName];
89            $fieldDisplay = $templateField->getDisplay();
90            if ( $fieldDisplay == 'hidden' ) {
91                continue;
92            }
93            if ( $fieldDisplay == 'nonempty' && $fieldValue == '' ) {
94                continue;
95            }
96
97            $fieldType = $templateField->getFieldType();
98            // Ignore stuff like 'Enumeration' - we don't need it.
99            $realFieldType = $templateField->getRealFieldType();
100            if ( $realFieldType !== null ) {
101                $fieldType = $realFieldType;
102            }
103
104            $fieldLabel = $templateField->getLabel();
105            if ( $fieldLabel == null ) {
106                $fieldLabel = $fieldName;
107            }
108
109            // If this field holds a template, and it has a value,
110            // create a separate fieldset, outside of the table
111            // (if this is a table) to display that other set of
112            // data.
113            // Possibly it would be better to do this not based on
114            // whether this field holds a template, but rather on
115            // whether the field value contains a <table> tag.
116            // However, with the current parser, it may not be
117            // possible for this parser function to know that
118            // information.
119            $holdsTemplate = $templateField->getHoldsTemplate();
120            if ( $format !== 'infobox' && $holdsTemplate !== null ) {
121                if ( trim( $fieldValue ) !== '' ) {
122                    if ( $format == 'table' ) {
123                        $text .= "</table>\n";
124                    }
125                    $text .= "<fieldset><legend>$fieldLabel</legend>";
126                    $text .= $fieldValue;
127                    $text .= '</fieldset>' . "\n";
128                    if ( $format == 'table' ) {
129                        $text .= '<table class="wikitable">' . "\n";
130                    }
131                }
132                continue;
133            }
134            if ( trim( $fieldValue ) == '' ) {
135                $formattedFieldValue = '';
136            } elseif ( $fieldType == 'Page' ) {
137                if ( $templateField->isList() ) {
138                    $formattedFieldValue = self::pageListText( $fieldValue, $templateField );
139                } else {
140                    $formattedFieldValue = self::pageText( $fieldValue, $templateField );
141                }
142            } elseif ( $fieldType == 'Coordinates' ) {
143                $formattedFieldValue = self::mapText( $fieldValue, $format, $parser );
144            } elseif ( $fieldType == 'Rating' ) {
145                $formattedFieldValue = self::ratingText( $fieldValue );
146            } elseif ( $fieldType == 'File' ) {
147                if ( $templateField->isList() ) {
148                    $formattedFieldValue = self::fileListText( $fieldValue, $templateField );
149                } else {
150                    $formattedFieldValue = self::fileText( $fieldValue );
151                }
152            } elseif ( $templateField->isList() ) {
153                $formattedFieldValue = self::stringListText( $fieldValue, $templateField );
154            } else {
155                $formattedFieldValue = $fieldValue;
156            }
157            if ( $format == 'table' || $format == 'infobox' ) {
158                $text .= "<tr><th>$fieldLabel</th><td>$formattedFieldValue</td></tr>\n";
159            } elseif ( $format == 'sections' ) {
160                $text .= "<h2>$fieldLabel</h2>\n$formattedFieldValue\n\n";
161            } else {
162                $text .= "<strong>$fieldLabel:</strong> $formattedFieldValue\n\n";
163            }
164        }
165
166        if ( $format == 'table' || $format == 'infobox' ) {
167            $text .= "</table>\n";
168        }
169
170        return [ $text, 'noparse' => true, 'isHTML' => true ];
171    }
172
173    private static function mapText( $coordinatesStr, $format, $parser ) {
174        if ( $coordinatesStr == '' ) {
175            return '';
176        }
177
178        $mappingFormat = new CargoMapsFormat( $parser->getOutput() );
179
180        try {
181            [ $lat, $lon ] = CargoUtils::parseCoordinatesString( $coordinatesStr );
182        // @phan-suppress-next-line PhanUnusedVariableCaughtException
183        } catch ( MWException $e ) {
184            return '';
185        }
186        $valuesTable = [ [ 'Coords  lat' => $lat, 'Coords  lon' => $lon ] ];
187        $formattedValuesTable = $valuesTable;
188        $coordsDesc = new CargoFieldDescription();
189        $coordsDesc->mType = 'Coordinates';
190        $fieldDescriptions = [ 'Coords' => $coordsDesc ];
191        $displayParams = [];
192        if ( $format == 'infobox' ) {
193            $displayParams['width'] = '300';
194            $displayParams['height'] = '300';
195        }
196
197        try {
198            $text = $mappingFormat->display( $valuesTable,
199                $formattedValuesTable, $fieldDescriptions,
200                $displayParams );
201        // @phan-suppress-next-line PhanUnusedVariableCaughtException
202        } catch ( MWException $e ) {
203            return '';
204        }
205        return $text;
206    }
207
208    private static function pageListText( $value, $templateField ) {
209        $text = '';
210        $delimiter = $templateField->getDelimiter();
211        $fieldValues = explode( $delimiter, $value );
212        foreach ( $fieldValues as $i => $fieldValue ) {
213            if ( trim( $fieldValue ) == '' ) {
214                continue;
215            }
216            if ( $i > 0 ) {
217                $text .= ' <span class="CargoDelimiter">&bull;</span> ';
218            }
219            $text .= self::pageText( $fieldValue, $templateField );
220        }
221        return $text;
222    }
223
224    private static function pageText( $value, $templateField ) {
225        $linkRenderer = MediaWikiServices::getInstance()->getLinkRenderer();
226        $namespace = $templateField->getNamespace();
227        $title = Title::makeTitleSafe( $namespace, $value );
228        if ( $title == null ) {
229            return $value;
230        }
231        if ( $title->exists() ) {
232            return PFUtils::makeLink( $linkRenderer, $title );
233        }
234        $form = $templateField->getForm();
235        if ( $form == null ) {
236            return PFUtils::makeLink( $linkRenderer, $title );
237        }
238
239        // The page doesn't exist, and a form has been found for this
240        // template field - link to this form for this page.
241        $formSpecialPage = PFUtils::getSpecialPage( 'FormEdit' );
242        $formSpecialPageTitle = $formSpecialPage->getPageTitle();
243        $target = $title->getFullText();
244        $formURL = $formSpecialPageTitle->getLocalURL() .
245            str_replace( ' ', '_', "/$form/$target" );
246        return Html::rawElement( 'a', [ 'href' => $formURL, 'class' => 'new' ], $value );
247    }
248
249    private static function stringListText( $value, $templateField ) {
250        $delimiter = $templateField->getDelimiter();
251        $fieldValues = explode( $delimiter, $value );
252        return implode( ' <span class="CargoDelimiter">&bull;</span> ', $fieldValues );
253    }
254
255    private static function ratingText( $value ) {
256        global $wgServer, $wgScriptPath;
257
258        $rate = (int)$value * 20;
259        $url = $wgServer . $wgScriptPath . '/' . 'extensions/Cargo/resources/images/star-rating-sprite-1.png';
260        $text = '<span style="display: block; width: 65px; height: 13px; background: url(\'' . $url . '\') 0 0;">
261            <span style="display: block; width: ' . (string)$rate . '%; height: 13px; background: url(\'' . $url . '\') 0 -13px;"></span>';
262        return $text;
263    }
264
265    private static function fileText( $value ) {
266        $title = Title::newFromText( $value, NS_FILE );
267        $file = MediaWikiServices::getInstance()->getRepoGroup()->findFile( $title );
268        return Linker::makeThumbLinkObj(
269            $title,
270            $file,
271            $value,
272            '',
273            'left'
274        );
275    }
276
277    private static function fileListText( $value, $templateField ) {
278        $text = '';
279        $delimiter = $templateField->getDelimiter();
280        $fieldValues = explode( $delimiter, $value );
281        foreach ( $fieldValues as $i => $fieldValue ) {
282            if ( trim( $fieldValue ) == '' ) {
283                continue;
284            }
285            $text .= self::fileText( $fieldValue );
286        }
287        return $text;
288    }
289}