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