Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
0.00% covered (danger)
0.00%
0 / 88
0.00% covered (danger)
0.00%
0 / 3
CRAP
0.00% covered (danger)
0.00%
0 / 1
CargoSlideshowFormat
0.00% covered (danger)
0.00%
0 / 88
0.00% covered (danger)
0.00%
0 / 3
1122
0.00% covered (danger)
0.00%
0 / 1
 allowedParameters
0.00% covered (danger)
0.00%
0 / 5
0.00% covered (danger)
0.00%
0 / 1
2
 getFileTitles
0.00% covered (danger)
0.00%
0 / 35
0.00% covered (danger)
0.00%
0 / 1
210
 display
0.00% covered (danger)
0.00%
0 / 48
0.00% covered (danger)
0.00%
0 / 1
342
1<?php
2
3use MediaWiki\Html\Html;
4use MediaWiki\MediaWikiServices;
5use MediaWiki\Title\Title;
6
7/**
8 * @author Yaron Koren
9 * @ingroup Cargo
10 *
11 * Defines the 'slideshow' format, which displays a slideshow of images,
12 * using the Slick JS library.
13 */
14
15class CargoSlideshowFormat extends CargoDisplayFormat {
16
17    public static function allowedParameters() {
18        return [
19            'caption field' => [ 'type' => 'string' ],
20            'link field' => [ 'type' => 'string' ],
21            'slides per screen' => [ 'type' => 'int' ]
22        ];
23    }
24
25    protected function getFileTitles( $valuesTable, $fieldDescriptions, $captionField, $linkField ) {
26        $fileField = null;
27        foreach ( $fieldDescriptions as $field => $fieldDesc ) {
28            if ( $fieldDesc->mType == 'File' ) {
29                $fileField = $field;
30                break;
31            }
32        }
33
34        // If there's no 'File' field in the schema, just use the
35        // page name.
36        if ( $fileField == null ) {
37            $usingPageName = true;
38            $fileField = '_pageName';
39        } else {
40            $usingPageName = false;
41        }
42
43        $fileNames = [];
44        foreach ( $valuesTable as $row ) {
45            if ( array_key_exists( $fileField, $row ) ) {
46                $caption = ( $captionField == null ) ? null : $row[$captionField];
47                $link = ( $linkField == null ) ? null : Title::newFromText( $row[$linkField] );
48                $fileNames[] = [
49                    'title' => $row[$fileField],
50                    'caption' => $caption,
51                    'link' => $link
52                ];
53            }
54        }
55
56        $files = [];
57        foreach ( $fileNames as $f ) {
58            $pageOrFileName = htmlspecialchars_decode( $f['title'], ENT_QUOTES );
59            if ( $usingPageName ) {
60                $title = Title::newFromText( $pageOrFileName );
61                if ( $title == null || $title->getNamespace() != NS_FILE ) {
62                    continue;
63                }
64            } else {
65                $title = Title::makeTitleSafe( NS_FILE, $pageOrFileName );
66                if ( $title == null ) {
67                    continue;
68                }
69            }
70
71            $files[] = [
72                'title' => $title,
73                'caption' => CargoUtils::smartParse( $f['caption'], null ),
74                'link' => ( $f['link'] !== null ) ? $f['link']->getLinkURL() : null
75            ];
76
77        }
78
79        return $files;
80    }
81
82    /**
83     * @param array $valuesTable Unused
84     * @param array $formattedValuesTable
85     * @param array $fieldDescriptions
86     * @param array $displayParams Unused
87     * @return string HTML
88     */
89    public function display( $valuesTable, $formattedValuesTable, $fieldDescriptions, $displayParams ) {
90        $this->mOutput->addModules( [ 'ext.cargo.slick' ] );
91
92        if ( array_key_exists( 'caption field', $displayParams ) ) {
93            $captionField = str_replace( '_', ' ', $displayParams['caption field'] );
94            if ( $captionField[0] == ' ' ) {
95                $captionField[0] = '_';
96            }
97            if ( count( $valuesTable ) > 0 && !array_key_exists( $captionField, $valuesTable[0] ) ) {
98                throw new MWException( wfMessage( "cargo-query-specifiedfieldmissing", $captionField, "caption field" )->parse() );
99            }
100        } else {
101            $captionField = null;
102        }
103        if ( array_key_exists( 'link field', $displayParams ) ) {
104            $linkField = str_replace( '_', ' ', $displayParams['link field'] );
105            if ( $linkField[0] == ' ' ) {
106                $linkField[0] = '_';
107            }
108            if ( count( $valuesTable ) > 0 && !array_key_exists( $linkField, $valuesTable[0] ) ) {
109                throw new MWException( wfMessage( "cargo-query-specifiedfieldmissing", $linkField, "link field" )->parse() );
110            }
111        } else {
112            $linkField = null;
113        }
114
115        $localRepo = MediaWikiServices::getInstance()->getRepoGroup()->getLocalRepo();
116        $bodyText = '';
117        $files = self::getFileTitles( $valuesTable, $fieldDescriptions, $captionField, $linkField );
118        foreach ( $files as $file ) {
119            $fileTitle = $file['title'];
120            $actualFile = $localRepo->newFile( $fileTitle->getText() );
121            $imageHTML = '<img src="' . $actualFile->getURL() . '" />';
122            if ( $file['link'] != '' ) {
123                $imageHTML = Html::rawElement( 'a', [ 'href' => $file['link'] ], $imageHTML );
124            }
125            $slideText = '<div class="image">' . $imageHTML .
126                "</div>\n";
127            if ( $file['caption'] != '' ) {
128                $slideText .= '<span class="cargoSliderCaption">' . $file['caption'] . '</span>';
129            }
130            $bodyText .= "<div>$slideText</div>\n";
131        }
132
133        $slickData = [];
134        if ( array_key_exists( 'slides per screen', $displayParams ) ) {
135            $slickData['slidesToShow'] = $displayParams['slides per screen'];
136            // @TODO - add this? Add a separate param for it?
137            // $slickData['slidesToScroll'] = $displayParams['slides per screen'];
138        }
139        if ( array_key_exists( 'autoplay speed', $displayParams ) && $displayParams['autoplay speed'] != '' ) {
140            $slickData['autoplay'] = 'true';
141            // Cargo's value is in seconds, not milliseconds.
142            $slickData['autoplaySpeed'] = 1000 * $displayParams['autoplay speed'];
143        }
144
145        $text = '<div class="cargoSlider"';
146        if ( count( $slickData ) > 0 ) {
147            // Slick requires the inline data to be encoded in a
148            // JSON-like way, but it's not quite JSON, and it has
149            // to be done in the exact right format, so we just
150            // create it manually.
151            $slickDataStr = '{';
152            $firstVal = true;
153            foreach ( $slickData as $key => $val ) {
154                if ( !$firstVal ) {
155                    $slickDataStr .= ', ';
156                } else {
157                    $firstVal = false;
158                }
159                $slickDataStr .= "\"$key\": $val";
160            }
161            $slickDataStr .= '}';
162            $text .= " data-slick='$slickDataStr'";
163        }
164        $text .= ">$bodyText</div>";
165
166        return $text;
167    }
168
169}