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 | } |