Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
0.00% covered (danger)
0.00%
0 / 75
0.00% covered (danger)
0.00%
0 / 17
CRAP
0.00% covered (danger)
0.00%
0 / 1
TraditionalMode
0.00% covered (danger)
0.00%
0 / 75
0.00% covered (danger)
0.00%
0 / 17
756
0.00% covered (danger)
0.00%
0 / 1
 __construct
0.00% covered (danger)
0.00%
0 / 3
0.00% covered (danger)
0.00%
0 / 1
2
 appendAttr
0.00% covered (danger)
0.00%
0 / 3
0.00% covered (danger)
0.00%
0 / 1
12
 ul
0.00% covered (danger)
0.00%
0 / 9
0.00% covered (danger)
0.00%
0 / 1
6
 perRow
0.00% covered (danger)
0.00%
0 / 5
0.00% covered (danger)
0.00%
0 / 1
6
 setAdditionalOptions
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 caption
0.00% covered (danger)
0.00%
0 / 6
0.00% covered (danger)
0.00%
0 / 1
2
 dimensions
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 scaleMedia
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 thumbWidth
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 thumbHeight
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 thumbStyle
0.00% covered (danger)
0.00%
0 / 6
0.00% covered (danger)
0.00%
0 / 1
20
 boxWidth
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 boxStyle
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 galleryText
0.00% covered (danger)
0.00%
0 / 7
0.00% covered (danger)
0.00%
0 / 1
6
 line
0.00% covered (danger)
0.00%
0 / 20
0.00% covered (danger)
0.00%
0 / 1
2
 render
0.00% covered (danger)
0.00%
0 / 8
0.00% covered (danger)
0.00%
0 / 1
12
 getModuleStyles
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
1<?php
2declare( strict_types = 1 );
3
4namespace Wikimedia\Parsoid\Ext\Gallery;
5
6use Wikimedia\Parsoid\DOM\Document;
7use Wikimedia\Parsoid\DOM\DocumentFragment;
8use Wikimedia\Parsoid\DOM\Element;
9use Wikimedia\Parsoid\Ext\DOMDataUtils;
10use Wikimedia\Parsoid\Ext\DOMUtils;
11use Wikimedia\Parsoid\Ext\ParsoidExtensionAPI;
12use Wikimedia\Parsoid\Utils\DOMCompat;
13
14class TraditionalMode extends Mode {
15    /**
16     * Create a TraditionalMode singleton.
17     * @param ?string $mode Only used by subclasses.
18     */
19    protected function __construct( ?string $mode = null ) {
20        parent::__construct( $mode ?? 'traditional' );
21        $this->scale = 1;
22        $this->padding = (object)[ 'thumb' => 30, 'box' => 5, 'border' => 8 ];
23    }
24
25    /** @var float */
26    protected $scale;
27    /** @var \stdClass */
28    protected $padding;
29
30    private function appendAttr( Element $ul, string $k, string $v ): void {
31        $val = DOMCompat::getAttribute( $ul, $k );
32        $val = ( $val === null || trim( $val ) === '' ) ? $v : "$val $v";
33        $ul->setAttribute( $k, $val );
34    }
35
36    /**
37     * Attributes in this method are applied to the list element in the order
38     * that matches the legacy parser.
39     *
40     * 1. Default
41     * 2. Inline
42     * 3. Additional
43     *
44     * The order is particularly important for appending to the style attribute
45     * since editors do not always terminate with a semi-colon.
46     */
47    private function ul(
48        Opts $opts, DocumentFragment $domFragment
49    ): Element {
50        $ul = $domFragment->ownerDocument->createElement( 'ul' );
51        $cl = 'gallery mw-gallery-' . $this->mode;
52        $ul->setAttribute( 'class', $cl );
53        $this->perRow( $opts, $ul );
54        foreach ( $opts->attrs as $k => $v ) {
55            $this->appendAttr( $ul, $k, $v );
56        }
57        $this->setAdditionalOptions( $opts, $ul );
58        $domFragment->appendChild( $ul );
59        return $ul;
60    }
61
62    protected function perRow( Opts $opts, Element $ul ): void {
63        if ( $opts->imagesPerRow > 0 ) {
64            $padding = $this->padding;
65            $total = $opts->imageWidth + $padding->thumb + $padding->box + $padding->border;
66            $total *= $opts->imagesPerRow;
67            $this->appendAttr( $ul, 'style', 'max-width: ' . $total . 'px;' );
68        }
69    }
70
71    protected function setAdditionalOptions( Opts $opts, Element $ul ): void {
72    }
73
74    private function caption(
75        Opts $opts, Element $ul, DocumentFragment $caption
76    ): void {
77        $doc = $ul->ownerDocument;
78        $li = $doc->createElement( 'li' );
79        $li->setAttribute( 'class', 'gallerycaption' );
80        DOMUtils::migrateChildren( $caption, $li );
81        $ul->appendChild( $doc->createTextNode( "\n" ) );
82        $ul->appendChild( $li );
83    }
84
85    /** @inheritDoc */
86    public function dimensions( Opts $opts ): string {
87        return "{$opts->imageWidth}x{$opts->imageHeight}px";
88    }
89
90    /**
91     * @param Opts $opts
92     * @param Element $wrapper
93     * @return int|float
94     */
95    protected function scaleMedia( Opts $opts, Element $wrapper ) {
96        return $opts->imageWidth;
97    }
98
99    /**
100     * @param float|int $width
101     * @return float|int
102     */
103    protected function thumbWidth( $width ) {
104        return $width + $this->padding->thumb;
105    }
106
107    /**
108     * @param float|int $height
109     * @return float|int
110     */
111    protected function thumbHeight( $height ) {
112        return $height + $this->padding->thumb;
113    }
114
115    /**
116     * @param float|int $width
117     * @param float|int $height
118     * @param bool $hasError
119     * @return string
120     */
121    protected function thumbStyle( $width, $height, bool $hasError ): string {
122        $style = [];
123        if ( !$hasError ) {
124            $style[] = 'width: ' . $this->thumbWidth( $width ) . 'px;';
125        }
126        if ( $hasError || $this->mode === 'traditional' ) {
127            $style[] = 'height: ' . $this->thumbHeight( $height ) . 'px;';
128        }
129        return implode( ' ', $style );
130    }
131
132    /**
133     * @param float|int $width
134     * @return float|int
135     */
136    protected function boxWidth( $width ) {
137        return $this->thumbWidth( $width ) + $this->padding->box;
138    }
139
140    /**
141     * @param float|int $width
142     * @param float|int $height
143     * @return string
144     */
145    protected function boxStyle( $width, $height ): string {
146        return 'width: ' . $this->boxWidth( $width ) . 'px;';
147    }
148
149    protected function galleryText(
150        Document $doc, Element $box, ?Element $gallerytext,
151        float $width
152    ): void {
153        $div = $doc->createElement( 'div' );
154        $div->setAttribute( 'class', 'gallerytext' );
155        if ( $gallerytext ) {
156            ParsoidExtensionAPI::migrateChildrenAndTransferWrapperDataAttribs(
157                $gallerytext, $div
158            );
159        }
160        $box->appendChild( $div );
161    }
162
163    private function line( Opts $opts, Element $ul, ParsedLine $o ): void {
164        $doc = $ul->ownerDocument;
165
166        $width = $this->scaleMedia( $opts, $o->thumb );
167        $height = $opts->imageHeight;
168
169        $box = $doc->createElement( 'li' );
170        $box->setAttribute( 'class', 'gallerybox' );
171        $box->setAttribute( 'style', $this->boxStyle( $width, $height ) );
172        DOMDataUtils::getDataParsoid( $box )->dsr = $o->dsr;
173
174        $thumb = $doc->createElement( 'div' );
175        $thumb->setAttribute( 'class', 'thumb' );
176        $thumb->setAttribute( 'style', $this->thumbStyle( $width, $height, $o->hasError ) );
177
178        $wrapper = $doc->createElement( 'span' );
179        $wrapper->setAttribute( 'typeof', $o->rdfaType );
180        ParsoidExtensionAPI::migrateChildrenAndTransferWrapperDataAttribs(
181            $o->thumb, $wrapper
182        );
183        $thumb->appendChild( $wrapper );
184
185        $box->appendChild( $thumb );
186        $this->galleryText( $doc, $box, $o->gallerytext, $width );
187        $ul->appendChild( $doc->createTextNode( "\n" ) );
188        $ul->appendChild( $box );
189    }
190
191    /** @inheritDoc */
192    public function render(
193        ParsoidExtensionAPI $extApi, Opts $opts, ?DocumentFragment $caption,
194        array $lines
195    ): DocumentFragment {
196        $domFragment = $extApi->htmlToDom( '' );
197        $ul = $this->ul( $opts, $domFragment );
198        if ( $caption ) {
199            $this->caption( $opts, $ul, $caption );
200        }
201        foreach ( $lines as $l ) {
202            $this->line( $opts, $ul, $l );
203        }
204        $ul->appendChild( $domFragment->ownerDocument->createTextNode( "\n" ) );
205        return $domFragment;
206    }
207
208    public function getModuleStyles(): array {
209        return [ 'mediawiki.page.gallery.styles' ];
210    }
211
212}