1<?php 2 3namespace Mpdf; 4 5use Mpdf\Strict; 6use Mpdf\Color\ColorConverter; 7use \dokuwiki\plugin\dw2pdf\DokuImageProcessorDecorator as ImageProcessor; 8use Mpdf\Language\LanguageToFontInterface; 9 10class Tag 11{ 12 13 use Strict; 14 15 /** 16 * @var \Mpdf\Mpdf 17 */ 18 private $mpdf; 19 20 /** 21 * @var \Mpdf\Cache 22 */ 23 private $cache; 24 25 /** 26 * @var \Mpdf\CssManager 27 */ 28 private $cssManager; 29 30 /** 31 * @var \Mpdf\Form 32 */ 33 private $form; 34 35 /** 36 * @var \Mpdf\Otl 37 */ 38 private $otl; 39 40 /** 41 * @var \Mpdf\TableOfContents 42 */ 43 private $tableOfContents; 44 45 /** 46 * @var \Mpdf\SizeConverter 47 */ 48 private $sizeConverter; 49 50 /** 51 * @var \Mpdf\Color\ColorConverter 52 */ 53 private $colorConverter; 54 55 /** 56 * @var ImageProcessor 57 */ 58 private $imageProcessor; 59 60 /** 61 * @var \Mpdf\Language\LanguageToFontInterface 62 */ 63 private $languageToFont; 64 65 /** 66 * @param \Mpdf\Mpdf $mpdf 67 * @param \Mpdf\Cache $cache 68 * @param \Mpdf\CssManager $cssManager 69 * @param \Mpdf\Form $form 70 * @param \Mpdf\Otl $otl 71 * @param \Mpdf\TableOfContents $tableOfContents 72 * @param \Mpdf\SizeConverter $sizeConverter 73 * @param \Mpdf\Color\ColorConverter $colorConverter 74 * @param \Mpdf\Image\ImageProcessor $imageProcessor 75 * @param \Mpdf\Language\LanguageToFontInterface $languageToFont 76 */ 77 public function __construct( 78 Mpdf $mpdf, 79 Cache $cache, 80 CssManager $cssManager, 81 Form $form, 82 Otl $otl, 83 TableOfContents $tableOfContents, 84 SizeConverter $sizeConverter, 85 ColorConverter $colorConverter, 86 ImageProcessor $imageProcessor, 87 LanguageToFontInterface $languageToFont 88 ) { 89 90 $this->mpdf = $mpdf; 91 $this->cache = $cache; 92 $this->cssManager = $cssManager; 93 $this->form = $form; 94 $this->otl = $otl; 95 $this->tableOfContents = $tableOfContents; 96 $this->sizeConverter = $sizeConverter; 97 $this->colorConverter = $colorConverter; 98 $this->imageProcessor = $imageProcessor; 99 $this->languageToFont = $languageToFont; 100 } 101 102 /** 103 * @param string $tag The tag name 104 * @return \Mpdf\Tag\Tag 105 */ 106 private function getTagInstance($tag) 107 { 108 $className = self::getTagClassName($tag); 109 if (class_exists($className)) { 110 return new $className( 111 $this->mpdf, 112 $this->cache, 113 $this->cssManager, 114 $this->form, 115 $this->otl, 116 $this->tableOfContents, 117 $this->sizeConverter, 118 $this->colorConverter, 119 $this->imageProcessor, 120 $this->languageToFont 121 ); 122 } 123 } 124 125 /** 126 * Returns the fully qualified name of the class handling the rendering of the given tag 127 * 128 * @param string $tag The tag name 129 * @return string The fully qualified name 130 */ 131 public static function getTagClassName($tag) 132 { 133 static $map = [ 134 'BARCODE' => 'BarCode', 135 'BLOCKQUOTE' => 'BlockQuote', 136 'COLUMN_BREAK' => 'ColumnBreak', 137 'COLUMNBREAK' => 'ColumnBreak', 138 'DOTTAB' => 'DotTab', 139 'FIELDSET' => 'FieldSet', 140 'FIGCAPTION' => 'FigCaption', 141 'FORMFEED' => 'FormFeed', 142 'HGROUP' => 'HGroup', 143 'INDEXENTRY' => 'IndexEntry', 144 'INDEXINSERT' => 'IndexInsert', 145 'NEWCOLUMN' => 'NewColumn', 146 'NEWPAGE' => 'NewPage', 147 'PAGEFOOTER' => 'PageFooter', 148 'PAGEHEADER' => 'PageHeader', 149 'PAGE_BREAK' => 'PageBreak', 150 'PAGEBREAK' => 'PageBreak', 151 'SETHTMLPAGEFOOTER' => 'SetHtmlPageFooter', 152 'SETHTMLPAGEHEADER' => 'SetHtmlPageHeader', 153 'SETPAGEFOOTER' => 'SetPageFooter', 154 'SETPAGEHEADER' => 'SetPageHeader', 155 'TBODY' => 'TBody', 156 'TFOOT' => 'TFoot', 157 'THEAD' => 'THead', 158 'TEXTAREA' => 'TextArea', 159 'TEXTCIRCLE' => 'TextCircle', 160 'TOCENTRY' => 'TocEntry', 161 'TOCPAGEBREAK' => 'TocPageBreak', 162 'VAR' => 'VarTag', 163 'WATERMARKIMAGE' => 'WatermarkImage', 164 'WATERMARKTEXT' => 'WatermarkText', 165 ]; 166 167 $className = 'Mpdf\Tag\\'; 168 $className .= isset($map[$tag]) ? $map[$tag] : ucfirst(strtolower($tag)); 169 170 return $className; 171 } 172 173 public function OpenTag($tag, $attr, &$ahtml, &$ihtml) 174 { 175 // Correct for tags where HTML5 specifies optional end tags excluding table elements (cf WriteHTML() ) 176 if ($this->mpdf->allow_html_optional_endtags) { 177 if (isset($this->mpdf->blk[$this->mpdf->blklvl]['tag'])) { 178 $closed = false; 179 // li end tag may be omitted if immediately followed by another li element 180 if (!$closed && $this->mpdf->blk[$this->mpdf->blklvl]['tag'] == 'LI' && $tag == 'LI') { 181 $this->CloseTag('LI', $ahtml, $ihtml); 182 $closed = true; 183 } 184 // dt end tag may be omitted if immediately followed by another dt element or a dd element 185 if (!$closed && $this->mpdf->blk[$this->mpdf->blklvl]['tag'] == 'DT' && ($tag == 'DT' || $tag == 'DD')) { 186 $this->CloseTag('DT', $ahtml, $ihtml); 187 $closed = true; 188 } 189 // dd end tag may be omitted if immediately followed by another dd element or a dt element 190 if (!$closed && $this->mpdf->blk[$this->mpdf->blklvl]['tag'] == 'DD' && ($tag == 'DT' || $tag == 'DD')) { 191 $this->CloseTag('DD', $ahtml, $ihtml); 192 $closed = true; 193 } 194 // p end tag may be omitted if immediately followed by an address, article, aside, blockquote, div, dl, 195 // fieldset, form, h1, h2, h3, h4, h5, h6, hgroup, hr, main, nav, ol, p, pre, section, table, ul 196 if (!$closed && $this->mpdf->blk[$this->mpdf->blklvl]['tag'] == 'P' 197 && ($tag == 'P' || $tag == 'DIV' || $tag == 'H1' || $tag == 'H2' || $tag == 'H3' 198 || $tag == 'H4' || $tag == 'H5' || $tag == 'H6' || $tag == 'UL' || $tag == 'OL' 199 || $tag == 'TABLE' || $tag == 'PRE' || $tag == 'FORM' || $tag == 'ADDRESS' || $tag == 'BLOCKQUOTE' 200 || $tag == 'CENTER' || $tag == 'DL' || $tag == 'HR' || $tag == 'ARTICLE' || $tag == 'ASIDE' 201 || $tag == 'FIELDSET' || $tag == 'HGROUP' || $tag == 'MAIN' || $tag == 'NAV' || $tag == 'SECTION')) { 202 $this->CloseTag('P', $ahtml, $ihtml); 203 $closed = true; 204 } 205 // option end tag may be omitted if immediately followed by another option element 206 // (or if it is immediately followed by an optgroup element) 207 if (!$closed && $this->mpdf->blk[$this->mpdf->blklvl]['tag'] == 'OPTION' && $tag == 'OPTION') { 208 $this->CloseTag('OPTION', $ahtml, $ihtml); 209 $closed = true; 210 } 211 // Table elements - see also WriteHTML() 212 if (!$closed && ($tag == 'TD' || $tag == 'TH') && $this->mpdf->lastoptionaltag == 'TD') { 213 $this->CloseTag($this->mpdf->lastoptionaltag, $ahtml, $ihtml); 214 $closed = true; 215 } // *TABLES* 216 if (!$closed && ($tag == 'TD' || $tag == 'TH') && $this->mpdf->lastoptionaltag == 'TH') { 217 $this->CloseTag($this->mpdf->lastoptionaltag, $ahtml, $ihtml); 218 $closed = true; 219 } // *TABLES* 220 if (!$closed && $tag == 'TR' && $this->mpdf->lastoptionaltag == 'TR') { 221 $this->CloseTag($this->mpdf->lastoptionaltag, $ahtml, $ihtml); 222 $closed = true; 223 } // *TABLES* 224 if (!$closed && $tag == 'TR' && $this->mpdf->lastoptionaltag == 'TD') { 225 $this->CloseTag($this->mpdf->lastoptionaltag, $ahtml, $ihtml); 226 $this->CloseTag('TR', $ahtml, $ihtml); 227 $this->CloseTag('THEAD', $ahtml, $ihtml); 228 $closed = true; 229 } // *TABLES* 230 if (!$closed && $tag == 'TR' && $this->mpdf->lastoptionaltag == 'TH') { 231 $this->CloseTag($this->mpdf->lastoptionaltag, $ahtml, $ihtml); 232 $this->CloseTag('TR', $ahtml, $ihtml); 233 $this->CloseTag('THEAD', $ahtml, $ihtml); 234 $closed = true; 235 } // *TABLES* 236 } 237 } 238 239 if ($object = $this->getTagInstance($tag)) { 240 return $object->open($attr, $ahtml, $ihtml); 241 } 242 } 243 244 public function CloseTag($tag, &$ahtml, &$ihtml) 245 { 246 if ($object = $this->getTagInstance($tag)) { 247 return $object->close($ahtml, $ihtml); 248 } 249 } 250} 251