Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
Total | |
0.00% |
0 / 75 |
|
0.00% |
0 / 17 |
CRAP | |
0.00% |
0 / 1 |
TraditionalMode | |
0.00% |
0 / 75 |
|
0.00% |
0 / 17 |
756 | |
0.00% |
0 / 1 |
__construct | |
0.00% |
0 / 3 |
|
0.00% |
0 / 1 |
2 | |||
appendAttr | |
0.00% |
0 / 3 |
|
0.00% |
0 / 1 |
12 | |||
ul | |
0.00% |
0 / 9 |
|
0.00% |
0 / 1 |
6 | |||
perRow | |
0.00% |
0 / 5 |
|
0.00% |
0 / 1 |
6 | |||
setAdditionalOptions | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
caption | |
0.00% |
0 / 6 |
|
0.00% |
0 / 1 |
2 | |||
dimensions | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
scaleMedia | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
thumbWidth | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
thumbHeight | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
thumbStyle | |
0.00% |
0 / 6 |
|
0.00% |
0 / 1 |
20 | |||
boxWidth | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
boxStyle | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
galleryText | |
0.00% |
0 / 7 |
|
0.00% |
0 / 1 |
6 | |||
line | |
0.00% |
0 / 20 |
|
0.00% |
0 / 1 |
2 | |||
render | |
0.00% |
0 / 8 |
|
0.00% |
0 / 1 |
12 | |||
getModuleStyles | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 |
1 | <?php |
2 | declare( strict_types = 1 ); |
3 | |
4 | namespace Wikimedia\Parsoid\Ext\Gallery; |
5 | |
6 | use Wikimedia\Parsoid\DOM\Document; |
7 | use Wikimedia\Parsoid\DOM\DocumentFragment; |
8 | use Wikimedia\Parsoid\DOM\Element; |
9 | use Wikimedia\Parsoid\Ext\DOMDataUtils; |
10 | use Wikimedia\Parsoid\Ext\DOMUtils; |
11 | use Wikimedia\Parsoid\Ext\ParsoidExtensionAPI; |
12 | use Wikimedia\Parsoid\Utils\DOMCompat; |
13 | |
14 | class 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 | } |