Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
| Total | |
0.00% |
0 / 167 |
|
0.00% |
0 / 8 |
CRAP | |
0.00% |
0 / 1 |
| PFTemplateDisplay | |
0.00% |
0 / 167 |
|
0.00% |
0 / 8 |
3306 | |
0.00% |
0 / 1 |
| run | |
0.00% |
0 / 95 |
|
0.00% |
0 / 1 |
1482 | |||
| mapText | |
0.00% |
0 / 21 |
|
0.00% |
0 / 1 |
30 | |||
| pageListText | |
0.00% |
0 / 10 |
|
0.00% |
0 / 1 |
20 | |||
| pageText | |
0.00% |
0 / 16 |
|
0.00% |
0 / 1 |
20 | |||
| stringListText | |
0.00% |
0 / 3 |
|
0.00% |
0 / 1 |
2 | |||
| ratingText | |
0.00% |
0 / 5 |
|
0.00% |
0 / 1 |
2 | |||
| fileText | |
0.00% |
0 / 9 |
|
0.00% |
0 / 1 |
2 | |||
| fileListText | |
0.00% |
0 / 8 |
|
0.00% |
0 / 1 |
12 | |||
| 1 | <?php |
| 2 | |
| 3 | use MediaWiki\Html\Html; |
| 4 | use MediaWiki\Linker\Linker; |
| 5 | use MediaWiki\MediaWikiServices; |
| 6 | use MediaWiki\Title\Title; |
| 7 | |
| 8 | /** |
| 9 | * Defines the #template_display parser function. |
| 10 | * |
| 11 | * @author Yaron Koren |
| 12 | */ |
| 13 | |
| 14 | class 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">•</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">•</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 | } |